blob: f8ad5bbd2102b6c11c95ca36f078fc98d6d86c0b [file] [log] [blame]
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001/* //device/include/server/AudioFlinger/AudioFlinger.cpp
2**
3** Copyright 2007, The Android Open Source Project
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9** http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
18
19#define LOG_TAG "AudioFlinger"
Eric Laurent7d850f22010-07-09 13:34:17 -070020//#define LOG_NDEBUG 0
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070021
22#include <math.h>
23#include <signal.h>
24#include <sys/time.h>
25#include <sys/resource.h>
26
Gloria Wang9b3f1522011-02-24 14:51:45 -080027#include <binder/IPCThreadState.h>
Mathias Agopian07952722009-05-19 19:08:10 -070028#include <binder/IServiceManager.h>
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070029#include <utils/Log.h>
Mathias Agopian07952722009-05-19 19:08:10 -070030#include <binder/Parcel.h>
31#include <binder/IPCThreadState.h>
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070032#include <utils/String16.h>
33#include <utils/threads.h>
Eric Laurentae29b762011-03-28 18:37:07 -070034#include <utils/Atomic.h>
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070035
Dima Zavin24fc2fb2011-04-19 22:30:36 -070036#include <cutils/bitops.h>
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -080037#include <cutils/properties.h>
38
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070039#include <media/AudioTrack.h>
40#include <media/AudioRecord.h>
Gloria Wang9b3f1522011-02-24 14:51:45 -080041#include <media/IMediaPlayerService.h>
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070042
43#include <private/media/AudioTrackShared.h>
Eric Laurent65b65452010-06-01 23:49:17 -070044#include <private/media/AudioEffectShared.h>
Dima Zavin24fc2fb2011-04-19 22:30:36 -070045
46#include <hardware/audio.h>
47#include <hardware/audio_hal.h>
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070048
49#include "AudioMixer.h"
50#include "AudioFlinger.h"
51
Eric Laurent53334cd2010-06-23 17:38:20 -070052#include <media/EffectsFactoryApi.h>
Eric Laurentdf9b81c2010-07-02 08:12:41 -070053#include <media/EffectVisualizerApi.h>
Eric Laurent65b65452010-06-01 23:49:17 -070054
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080055// ----------------------------------------------------------------------------
56// the sim build doesn't have gettid
57
58#ifndef HAVE_GETTID
59# define gettid getpid
60#endif
61
62// ----------------------------------------------------------------------------
63
Eric Laurent8ed6ed02010-07-13 04:45:46 -070064extern const char * const gEffectLibPath;
65
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070066namespace android {
67
The Android Open Source Project10592532009-03-18 17:39:46 -070068static const char* kDeadlockedString = "AudioFlinger may be deadlocked\n";
69static const char* kHardwareLockedString = "Hardware lock is taken\n";
70
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -080071//static const nsecs_t kStandbyTimeInNsecs = seconds(3);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070072static const float MAX_GAIN = 4096.0f;
Eric Laurent65b65452010-06-01 23:49:17 -070073static const float MAX_GAIN_INT = 0x1000;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070074
75// retry counts for buffer fill timeout
76// 50 * ~20msecs = 1 second
77static const int8_t kMaxTrackRetries = 50;
78static const int8_t kMaxTrackStartupRetries = 50;
Eric Laurentef9500f2010-03-11 14:47:00 -080079// allow less retry attempts on direct output thread.
80// direct outputs can be a scarce resource in audio hardware and should
81// be released as quickly as possible.
82static const int8_t kMaxTrackRetriesDirect = 2;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070083
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -070084static const int kDumpLockRetries = 50;
85static const int kDumpLockSleep = 20000;
86
Dave Sparksd0ac8c02009-09-30 03:09:03 -070087static const nsecs_t kWarningThrottle = seconds(5);
88
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080089
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070090#define AUDIOFLINGER_SECURITY_ENABLED 1
91
92// ----------------------------------------------------------------------------
93
94static bool recordingAllowed() {
95#ifndef HAVE_ANDROID_OS
96 return true;
97#endif
98#if AUDIOFLINGER_SECURITY_ENABLED
99 if (getpid() == IPCThreadState::self()->getCallingPid()) return true;
100 bool ok = checkCallingPermission(String16("android.permission.RECORD_AUDIO"));
101 if (!ok) LOGE("Request requires android.permission.RECORD_AUDIO");
102 return ok;
103#else
104 if (!checkCallingPermission(String16("android.permission.RECORD_AUDIO")))
105 LOGW("WARNING: Need to add android.permission.RECORD_AUDIO to manifest");
106 return true;
107#endif
108}
109
110static bool settingsAllowed() {
111#ifndef HAVE_ANDROID_OS
112 return true;
113#endif
114#if AUDIOFLINGER_SECURITY_ENABLED
115 if (getpid() == IPCThreadState::self()->getCallingPid()) return true;
116 bool ok = checkCallingPermission(String16("android.permission.MODIFY_AUDIO_SETTINGS"));
117 if (!ok) LOGE("Request requires android.permission.MODIFY_AUDIO_SETTINGS");
118 return ok;
119#else
120 if (!checkCallingPermission(String16("android.permission.MODIFY_AUDIO_SETTINGS")))
121 LOGW("WARNING: Need to add android.permission.MODIFY_AUDIO_SETTINGS to manifest");
122 return true;
123#endif
124}
125
Gloria Wang9b3f1522011-02-24 14:51:45 -0800126// To collect the amplifier usage
127static void addBatteryData(uint32_t params) {
128 sp<IBinder> binder =
129 defaultServiceManager()->getService(String16("media.player"));
130 sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder);
131 if (service.get() == NULL) {
132 LOGW("Cannot connect to the MediaPlayerService for battery tracking");
133 return;
134 }
135
136 service->addBatteryData(params);
137}
138
Dima Zavin31f188892011-04-18 16:57:27 -0700139static int load_audio_interface(const char *if_name, const hw_module_t **mod,
140 audio_hw_device_t **dev)
141{
142 int rc;
143
144 rc = hw_get_module_by_class(AUDIO_HARDWARE_MODULE_ID, if_name, mod);
145 if (rc)
146 goto out;
147
148 rc = audio_hw_device_open(*mod, dev);
149 LOGE_IF(rc, "couldn't open audio hw device in %s.%s (%s)",
150 AUDIO_HARDWARE_MODULE_ID, if_name, strerror(-rc));
151 if (rc)
152 goto out;
153
154 return 0;
155
156out:
157 *mod = NULL;
158 *dev = NULL;
159 return rc;
160}
161
162static const char *audio_interfaces[] = {
163 "primary",
164 "a2dp",
165 "usb",
166};
167#define ARRAY_SIZE(x) (sizeof((x))/sizeof(((x)[0])))
168
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700169// ----------------------------------------------------------------------------
170
171AudioFlinger::AudioFlinger()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800172 : BnAudioFlinger(),
Dima Zavin31f188892011-04-18 16:57:27 -0700173 mPrimaryHardwareDev(0), mMasterVolume(1.0f), mMasterMute(false), mNextUniqueId(1)
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700174{
Dima Zavin2986f5b2011-04-19 19:04:32 -0700175}
176
177void AudioFlinger::onFirstRef()
178{
Dima Zavin31f188892011-04-18 16:57:27 -0700179 int rc = 0;
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700180
Eric Laurent01635942011-01-18 18:39:02 -0800181 Mutex::Autolock _l(mLock);
182
Dima Zavin31f188892011-04-18 16:57:27 -0700183 /* TODO: move all this work into an Init() function */
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700184 mHardwareStatus = AUDIO_HW_IDLE;
Eric Laurenta553c252009-07-17 12:17:14 -0700185
Dima Zavin31f188892011-04-18 16:57:27 -0700186 for (size_t i = 0; i < ARRAY_SIZE(audio_interfaces); i++) {
187 const hw_module_t *mod;
188 audio_hw_device_t *dev;
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700189
Dima Zavin31f188892011-04-18 16:57:27 -0700190 rc = load_audio_interface(audio_interfaces[i], &mod, &dev);
191 if (rc)
192 continue;
193
194 LOGI("Loaded %s audio interface from %s (%s)", audio_interfaces[i],
195 mod->name, mod->id);
196 mAudioHwDevs.push(dev);
197
198 if (!mPrimaryHardwareDev) {
199 mPrimaryHardwareDev = dev;
200 LOGI("Using '%s' (%s.%s) as the primary audio interface",
Dima Zavin2986f5b2011-04-19 19:04:32 -0700201 mod->name, mod->id, audio_interfaces[i]);
Dima Zavin31f188892011-04-18 16:57:27 -0700202 }
203 }
Eric Laurenta553c252009-07-17 12:17:14 -0700204
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700205 mHardwareStatus = AUDIO_HW_INIT;
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700206
Dima Zavin31f188892011-04-18 16:57:27 -0700207 if (!mPrimaryHardwareDev || mAudioHwDevs.size() == 0) {
208 LOGE("Primary audio interface not found");
209 return;
210 }
211
212 for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
213 audio_hw_device_t *dev = mAudioHwDevs[i];
214
215 mHardwareStatus = AUDIO_HW_INIT;
216 rc = dev->init_check(dev);
217 if (rc == 0) {
218 AutoMutex lock(mHardwareLock);
219
220 mMode = AUDIO_MODE_NORMAL;
221 mHardwareStatus = AUDIO_HW_SET_MODE;
222 dev->set_mode(dev, mMode);
223 mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
224 dev->set_master_volume(dev, 1.0f);
225 mHardwareStatus = AUDIO_HW_IDLE;
226 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700227 }
228}
229
Dima Zavin2986f5b2011-04-19 19:04:32 -0700230status_t AudioFlinger::initCheck() const
231{
232 Mutex::Autolock _l(mLock);
233 if (mPrimaryHardwareDev == NULL || mAudioHwDevs.size() == 0)
234 return NO_INIT;
235 return NO_ERROR;
236}
237
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700238AudioFlinger::~AudioFlinger()
239{
Dima Zavin31f188892011-04-18 16:57:27 -0700240 int num_devs = mAudioHwDevs.size();
241
Eric Laurent7954c462009-08-28 10:39:03 -0700242 while (!mRecordThreads.isEmpty()) {
243 // closeInput() will remove first entry from mRecordThreads
244 closeInput(mRecordThreads.keyAt(0));
245 }
246 while (!mPlaybackThreads.isEmpty()) {
247 // closeOutput() will remove first entry from mPlaybackThreads
248 closeOutput(mPlaybackThreads.keyAt(0));
249 }
Dima Zavin31f188892011-04-18 16:57:27 -0700250
251 for (int i = 0; i < num_devs; i++) {
252 audio_hw_device_t *dev = mAudioHwDevs[i];
253 audio_hw_device_close(dev);
Eric Laurent7954c462009-08-28 10:39:03 -0700254 }
Dima Zavin31f188892011-04-18 16:57:27 -0700255 mAudioHwDevs.clear();
The Android Open Source Projectb7986892009-01-09 17:51:23 -0800256}
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800257
Dima Zavin31f188892011-04-18 16:57:27 -0700258audio_hw_device_t* AudioFlinger::findSuitableHwDev_l(uint32_t devices)
259{
260 /* first matching HW device is returned */
261 for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
262 audio_hw_device_t *dev = mAudioHwDevs[i];
263 if ((dev->get_supported_devices(dev) & devices) == devices)
264 return dev;
265 }
266 return NULL;
267}
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -0700268
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700269status_t AudioFlinger::dumpClients(int fd, const Vector<String16>& args)
270{
271 const size_t SIZE = 256;
272 char buffer[SIZE];
273 String8 result;
274
275 result.append("Clients:\n");
276 for (size_t i = 0; i < mClients.size(); ++i) {
277 wp<Client> wClient = mClients.valueAt(i);
278 if (wClient != 0) {
279 sp<Client> client = wClient.promote();
280 if (client != 0) {
281 snprintf(buffer, SIZE, " pid: %d\n", client->pid());
282 result.append(buffer);
283 }
284 }
285 }
286 write(fd, result.string(), result.size());
287 return NO_ERROR;
288}
289
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700290
291status_t AudioFlinger::dumpInternals(int fd, const Vector<String16>& args)
292{
293 const size_t SIZE = 256;
294 char buffer[SIZE];
295 String8 result;
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -0700296 int hardwareStatus = mHardwareStatus;
Eric Laurenta553c252009-07-17 12:17:14 -0700297
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -0700298 snprintf(buffer, SIZE, "Hardware status: %d\n", hardwareStatus);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700299 result.append(buffer);
300 write(fd, result.string(), result.size());
301 return NO_ERROR;
302}
303
304status_t AudioFlinger::dumpPermissionDenial(int fd, const Vector<String16>& args)
305{
306 const size_t SIZE = 256;
307 char buffer[SIZE];
308 String8 result;
309 snprintf(buffer, SIZE, "Permission Denial: "
310 "can't dump AudioFlinger from pid=%d, uid=%d\n",
311 IPCThreadState::self()->getCallingPid(),
312 IPCThreadState::self()->getCallingUid());
313 result.append(buffer);
314 write(fd, result.string(), result.size());
315 return NO_ERROR;
316}
317
The Android Open Source Project10592532009-03-18 17:39:46 -0700318static bool tryLock(Mutex& mutex)
319{
320 bool locked = false;
321 for (int i = 0; i < kDumpLockRetries; ++i) {
322 if (mutex.tryLock() == NO_ERROR) {
323 locked = true;
324 break;
325 }
326 usleep(kDumpLockSleep);
327 }
328 return locked;
329}
330
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700331status_t AudioFlinger::dump(int fd, const Vector<String16>& args)
332{
333 if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
334 dumpPermissionDenial(fd, args);
335 } else {
The Android Open Source Project10592532009-03-18 17:39:46 -0700336 // get state of hardware lock
337 bool hardwareLocked = tryLock(mHardwareLock);
338 if (!hardwareLocked) {
339 String8 result(kHardwareLockedString);
340 write(fd, result.string(), result.size());
341 } else {
342 mHardwareLock.unlock();
343 }
344
345 bool locked = tryLock(mLock);
346
347 // failed to lock - AudioFlinger is probably deadlocked
348 if (!locked) {
349 String8 result(kDeadlockedString);
350 write(fd, result.string(), result.size());
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -0700351 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700352
353 dumpClients(fd, args);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700354 dumpInternals(fd, args);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800355
Eric Laurenta553c252009-07-17 12:17:14 -0700356 // dump playback threads
357 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
Eric Laurentddb78e72009-07-28 08:44:33 -0700358 mPlaybackThreads.valueAt(i)->dump(fd, args);
Eric Laurenta553c252009-07-17 12:17:14 -0700359 }
360
361 // dump record threads
Eric Laurent102313a2009-07-23 13:35:01 -0700362 for (size_t i = 0; i < mRecordThreads.size(); i++) {
Eric Laurentddb78e72009-07-28 08:44:33 -0700363 mRecordThreads.valueAt(i)->dump(fd, args);
Eric Laurenta553c252009-07-17 12:17:14 -0700364 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800365
Dima Zavin31f188892011-04-18 16:57:27 -0700366 // dump all hardware devs
367 for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
368 audio_hw_device_t *dev = mAudioHwDevs[i];
369 dev->dump(dev, fd);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700370 }
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -0700371 if (locked) mLock.unlock();
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700372 }
373 return NO_ERROR;
374}
375
Eric Laurenta553c252009-07-17 12:17:14 -0700376
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700377// IAudioFlinger interface
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800378
379
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700380sp<IAudioTrack> AudioFlinger::createTrack(
381 pid_t pid,
382 int streamType,
383 uint32_t sampleRate,
384 int format,
385 int channelCount,
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800386 int frameCount,
387 uint32_t flags,
388 const sp<IMemory>& sharedBuffer,
Eric Laurentddb78e72009-07-28 08:44:33 -0700389 int output,
Eric Laurent65b65452010-06-01 23:49:17 -0700390 int *sessionId,
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800391 status_t *status)
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700392{
Eric Laurenta553c252009-07-17 12:17:14 -0700393 sp<PlaybackThread::Track> track;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700394 sp<TrackHandle> trackHandle;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700395 sp<Client> client;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800396 wp<Client> wclient;
397 status_t lStatus;
Eric Laurent65b65452010-06-01 23:49:17 -0700398 int lSessionId;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700399
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700400 if (streamType >= AUDIO_STREAM_CNT) {
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800401 LOGE("invalid stream type");
402 lStatus = BAD_VALUE;
403 goto Exit;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700404 }
405
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800406 {
407 Mutex::Autolock _l(mLock);
Eric Laurenta553c252009-07-17 12:17:14 -0700408 PlaybackThread *thread = checkPlaybackThread_l(output);
Eric Laurent493941b2010-07-28 01:32:47 -0700409 PlaybackThread *effectThread = NULL;
Eric Laurenta553c252009-07-17 12:17:14 -0700410 if (thread == NULL) {
411 LOGE("unknown output thread");
412 lStatus = BAD_VALUE;
413 goto Exit;
414 }
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800415
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800416 wclient = mClients.valueFor(pid);
417
418 if (wclient != NULL) {
419 client = wclient.promote();
420 } else {
421 client = new Client(this, pid);
422 mClients.add(pid, client);
423 }
Eric Laurent65b65452010-06-01 23:49:17 -0700424
Eric Laurent65b65452010-06-01 23:49:17 -0700425 LOGV("createTrack() sessionId: %d", (sessionId == NULL) ? -2 : *sessionId);
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700426 if (sessionId != NULL && *sessionId != AUDIO_SESSION_OUTPUT_MIX) {
Eric Laurent8ed6ed02010-07-13 04:45:46 -0700427 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
Eric Laurent493941b2010-07-28 01:32:47 -0700428 sp<PlaybackThread> t = mPlaybackThreads.valueAt(i);
429 if (mPlaybackThreads.keyAt(i) != output) {
430 // prevent same audio session on different output threads
431 uint32_t sessions = t->hasAudioSession(*sessionId);
432 if (sessions & PlaybackThread::TRACK_SESSION) {
433 lStatus = BAD_VALUE;
434 goto Exit;
435 }
436 // check if an effect with same session ID is waiting for a track to be created
437 if (sessions & PlaybackThread::EFFECT_SESSION) {
438 effectThread = t.get();
439 }
Eric Laurent8ed6ed02010-07-13 04:45:46 -0700440 }
441 }
Eric Laurent65b65452010-06-01 23:49:17 -0700442 lSessionId = *sessionId;
443 } else {
Eric Laurent8ed6ed02010-07-13 04:45:46 -0700444 // if no audio session id is provided, create one here
Eric Laurentf3d6dd02010-11-18 08:40:16 -0800445 lSessionId = nextUniqueId_l();
Eric Laurent65b65452010-06-01 23:49:17 -0700446 if (sessionId != NULL) {
447 *sessionId = lSessionId;
448 }
449 }
450 LOGV("createTrack() lSessionId: %d", lSessionId);
451
Eric Laurenta553c252009-07-17 12:17:14 -0700452 track = thread->createTrack_l(client, streamType, sampleRate, format,
Eric Laurent65b65452010-06-01 23:49:17 -0700453 channelCount, frameCount, sharedBuffer, lSessionId, &lStatus);
Eric Laurent493941b2010-07-28 01:32:47 -0700454
455 // move effect chain to this output thread if an effect on same session was waiting
456 // for a track to be created
457 if (lStatus == NO_ERROR && effectThread != NULL) {
458 Mutex::Autolock _dl(thread->mLock);
459 Mutex::Autolock _sl(effectThread->mLock);
460 moveEffectChain_l(lSessionId, effectThread, thread, true);
461 }
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -0700462 }
463 if (lStatus == NO_ERROR) {
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800464 trackHandle = new TrackHandle(track);
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -0700465 } else {
Eric Laurentb9481d82009-09-17 05:12:56 -0700466 // remove local strong reference to Client before deleting the Track so that the Client
467 // destructor is called by the TrackBase destructor with mLock held
468 client.clear();
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -0700469 track.clear();
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800470 }
471
472Exit:
473 if(status) {
474 *status = lStatus;
475 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700476 return trackHandle;
477}
478
Eric Laurentddb78e72009-07-28 08:44:33 -0700479uint32_t AudioFlinger::sampleRate(int output) const
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700480{
Eric Laurenta553c252009-07-17 12:17:14 -0700481 Mutex::Autolock _l(mLock);
482 PlaybackThread *thread = checkPlaybackThread_l(output);
483 if (thread == NULL) {
Eric Laurentddb78e72009-07-28 08:44:33 -0700484 LOGW("sampleRate() unknown thread %d", output);
Eric Laurenta553c252009-07-17 12:17:14 -0700485 return 0;
486 }
487 return thread->sampleRate();
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700488}
489
Eric Laurentddb78e72009-07-28 08:44:33 -0700490int AudioFlinger::channelCount(int output) const
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700491{
Eric Laurenta553c252009-07-17 12:17:14 -0700492 Mutex::Autolock _l(mLock);
493 PlaybackThread *thread = checkPlaybackThread_l(output);
494 if (thread == NULL) {
Eric Laurentddb78e72009-07-28 08:44:33 -0700495 LOGW("channelCount() unknown thread %d", output);
Eric Laurenta553c252009-07-17 12:17:14 -0700496 return 0;
497 }
498 return thread->channelCount();
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700499}
500
Eric Laurentddb78e72009-07-28 08:44:33 -0700501int AudioFlinger::format(int output) const
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700502{
Eric Laurenta553c252009-07-17 12:17:14 -0700503 Mutex::Autolock _l(mLock);
504 PlaybackThread *thread = checkPlaybackThread_l(output);
505 if (thread == NULL) {
Eric Laurentddb78e72009-07-28 08:44:33 -0700506 LOGW("format() unknown thread %d", output);
Eric Laurenta553c252009-07-17 12:17:14 -0700507 return 0;
508 }
509 return thread->format();
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700510}
511
Eric Laurentddb78e72009-07-28 08:44:33 -0700512size_t AudioFlinger::frameCount(int output) const
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700513{
Eric Laurenta553c252009-07-17 12:17:14 -0700514 Mutex::Autolock _l(mLock);
515 PlaybackThread *thread = checkPlaybackThread_l(output);
516 if (thread == NULL) {
Eric Laurentddb78e72009-07-28 08:44:33 -0700517 LOGW("frameCount() unknown thread %d", output);
Eric Laurenta553c252009-07-17 12:17:14 -0700518 return 0;
519 }
520 return thread->frameCount();
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700521}
522
Eric Laurentddb78e72009-07-28 08:44:33 -0700523uint32_t AudioFlinger::latency(int output) const
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800524{
Eric Laurenta553c252009-07-17 12:17:14 -0700525 Mutex::Autolock _l(mLock);
526 PlaybackThread *thread = checkPlaybackThread_l(output);
527 if (thread == NULL) {
Eric Laurentddb78e72009-07-28 08:44:33 -0700528 LOGW("latency() unknown thread %d", output);
Eric Laurenta553c252009-07-17 12:17:14 -0700529 return 0;
530 }
531 return thread->latency();
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800532}
533
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700534status_t AudioFlinger::setMasterVolume(float value)
535{
536 // check calling permissions
537 if (!settingsAllowed()) {
538 return PERMISSION_DENIED;
539 }
540
541 // when hw supports master volume, don't scale in sw mixer
Eric Laurent01635942011-01-18 18:39:02 -0800542 { // scope for the lock
543 AutoMutex lock(mHardwareLock);
544 mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
Dima Zavin31f188892011-04-18 16:57:27 -0700545 if (mPrimaryHardwareDev->set_master_volume(mPrimaryHardwareDev, value) == NO_ERROR) {
Eric Laurent01635942011-01-18 18:39:02 -0800546 value = 1.0f;
547 }
548 mHardwareStatus = AUDIO_HW_IDLE;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700549 }
Eric Laurenta553c252009-07-17 12:17:14 -0700550
Eric Laurent01635942011-01-18 18:39:02 -0800551 Mutex::Autolock _l(mLock);
Eric Laurenta553c252009-07-17 12:17:14 -0700552 mMasterVolume = value;
553 for (uint32_t i = 0; i < mPlaybackThreads.size(); i++)
Eric Laurentddb78e72009-07-28 08:44:33 -0700554 mPlaybackThreads.valueAt(i)->setMasterVolume(value);
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -0700555
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700556 return NO_ERROR;
557}
558
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700559status_t AudioFlinger::setMode(int mode)
560{
Eric Laurent53334cd2010-06-23 17:38:20 -0700561 status_t ret;
562
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700563 // check calling permissions
564 if (!settingsAllowed()) {
565 return PERMISSION_DENIED;
566 }
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700567 if ((mode < 0) || (mode >= AUDIO_MODE_CNT)) {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700568 LOGW("Illegal value: setMode(%d)", mode);
569 return BAD_VALUE;
570 }
571
Eric Laurent53334cd2010-06-23 17:38:20 -0700572 { // scope for the lock
573 AutoMutex lock(mHardwareLock);
574 mHardwareStatus = AUDIO_HW_SET_MODE;
Dima Zavin31f188892011-04-18 16:57:27 -0700575 ret = mPrimaryHardwareDev->set_mode(mPrimaryHardwareDev, mode);
Eric Laurent53334cd2010-06-23 17:38:20 -0700576 mHardwareStatus = AUDIO_HW_IDLE;
Glenn Kasten871c16c2010-03-05 12:18:01 -0800577 }
Eric Laurent53334cd2010-06-23 17:38:20 -0700578
579 if (NO_ERROR == ret) {
580 Mutex::Autolock _l(mLock);
581 mMode = mode;
582 for (uint32_t i = 0; i < mPlaybackThreads.size(); i++)
583 mPlaybackThreads.valueAt(i)->setMode(mode);
Eric Laurent53334cd2010-06-23 17:38:20 -0700584 }
585
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700586 return ret;
587}
588
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700589status_t AudioFlinger::setMicMute(bool state)
590{
591 // check calling permissions
592 if (!settingsAllowed()) {
593 return PERMISSION_DENIED;
594 }
595
596 AutoMutex lock(mHardwareLock);
597 mHardwareStatus = AUDIO_HW_SET_MIC_MUTE;
Dima Zavin31f188892011-04-18 16:57:27 -0700598 status_t ret = mPrimaryHardwareDev->set_mic_mute(mPrimaryHardwareDev, state);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700599 mHardwareStatus = AUDIO_HW_IDLE;
600 return ret;
601}
602
603bool AudioFlinger::getMicMute() const
604{
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700605 bool state = AUDIO_MODE_INVALID;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700606 mHardwareStatus = AUDIO_HW_GET_MIC_MUTE;
Dima Zavin31f188892011-04-18 16:57:27 -0700607 mPrimaryHardwareDev->get_mic_mute(mPrimaryHardwareDev, &state);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700608 mHardwareStatus = AUDIO_HW_IDLE;
609 return state;
610}
611
612status_t AudioFlinger::setMasterMute(bool muted)
613{
614 // check calling permissions
615 if (!settingsAllowed()) {
616 return PERMISSION_DENIED;
617 }
Eric Laurenta553c252009-07-17 12:17:14 -0700618
Eric Laurent01635942011-01-18 18:39:02 -0800619 Mutex::Autolock _l(mLock);
Eric Laurenta553c252009-07-17 12:17:14 -0700620 mMasterMute = muted;
621 for (uint32_t i = 0; i < mPlaybackThreads.size(); i++)
Eric Laurentddb78e72009-07-28 08:44:33 -0700622 mPlaybackThreads.valueAt(i)->setMasterMute(muted);
Eric Laurenta553c252009-07-17 12:17:14 -0700623
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700624 return NO_ERROR;
625}
626
627float AudioFlinger::masterVolume() const
628{
Eric Laurenta553c252009-07-17 12:17:14 -0700629 return mMasterVolume;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700630}
631
632bool AudioFlinger::masterMute() const
633{
Eric Laurenta553c252009-07-17 12:17:14 -0700634 return mMasterMute;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700635}
636
Eric Laurentddb78e72009-07-28 08:44:33 -0700637status_t AudioFlinger::setStreamVolume(int stream, float value, int output)
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700638{
639 // check calling permissions
640 if (!settingsAllowed()) {
641 return PERMISSION_DENIED;
642 }
643
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700644 if (stream < 0 || uint32_t(stream) >= AUDIO_STREAM_CNT) {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700645 return BAD_VALUE;
646 }
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800647
Eric Laurenta553c252009-07-17 12:17:14 -0700648 AutoMutex lock(mLock);
649 PlaybackThread *thread = NULL;
650 if (output) {
651 thread = checkPlaybackThread_l(output);
652 if (thread == NULL) {
653 return BAD_VALUE;
654 }
655 }
656
Eric Laurenta553c252009-07-17 12:17:14 -0700657 mStreamTypes[stream].volume = value;
658
659 if (thread == NULL) {
Eric Laurent415f3e22009-10-21 08:14:22 -0700660 for (uint32_t i = 0; i < mPlaybackThreads.size(); i++) {
Eric Laurentddb78e72009-07-28 08:44:33 -0700661 mPlaybackThreads.valueAt(i)->setStreamVolume(stream, value);
Eric Laurent415f3e22009-10-21 08:14:22 -0700662 }
Eric Laurenta553c252009-07-17 12:17:14 -0700663 } else {
664 thread->setStreamVolume(stream, value);
665 }
Eric Laurentef028272009-04-21 07:56:33 -0700666
Eric Laurent415f3e22009-10-21 08:14:22 -0700667 return NO_ERROR;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700668}
669
670status_t AudioFlinger::setStreamMute(int stream, bool muted)
671{
672 // check calling permissions
673 if (!settingsAllowed()) {
674 return PERMISSION_DENIED;
675 }
676
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700677 if (stream < 0 || uint32_t(stream) >= AUDIO_STREAM_CNT ||
678 uint32_t(stream) == AUDIO_STREAM_ENFORCED_AUDIBLE) {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700679 return BAD_VALUE;
680 }
The Android Open Source Project10592532009-03-18 17:39:46 -0700681
Eric Laurent01635942011-01-18 18:39:02 -0800682 AutoMutex lock(mLock);
Eric Laurenta553c252009-07-17 12:17:14 -0700683 mStreamTypes[stream].mute = muted;
684 for (uint32_t i = 0; i < mPlaybackThreads.size(); i++)
Eric Laurentddb78e72009-07-28 08:44:33 -0700685 mPlaybackThreads.valueAt(i)->setStreamMute(stream, muted);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800686
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700687 return NO_ERROR;
688}
689
Eric Laurentddb78e72009-07-28 08:44:33 -0700690float AudioFlinger::streamVolume(int stream, int output) const
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700691{
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700692 if (stream < 0 || uint32_t(stream) >= AUDIO_STREAM_CNT) {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700693 return 0.0f;
694 }
Eric Laurenta553c252009-07-17 12:17:14 -0700695
696 AutoMutex lock(mLock);
697 float volume;
698 if (output) {
699 PlaybackThread *thread = checkPlaybackThread_l(output);
700 if (thread == NULL) {
701 return 0.0f;
702 }
703 volume = thread->streamVolume(stream);
704 } else {
705 volume = mStreamTypes[stream].volume;
706 }
707
Eric Laurentef028272009-04-21 07:56:33 -0700708 return volume;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700709}
710
711bool AudioFlinger::streamMute(int stream) const
712{
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700713 if (stream < 0 || stream >= (int)AUDIO_STREAM_CNT) {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700714 return true;
715 }
Eric Laurenta553c252009-07-17 12:17:14 -0700716
717 return mStreamTypes[stream].mute;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700718}
719
Eric Laurentddb78e72009-07-28 08:44:33 -0700720status_t AudioFlinger::setParameters(int ioHandle, const String8& keyValuePairs)
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700721{
Eric Laurenta553c252009-07-17 12:17:14 -0700722 status_t result;
723
Eric Laurentddb78e72009-07-28 08:44:33 -0700724 LOGV("setParameters(): io %d, keyvalue %s, tid %d, calling tid %d",
Eric Laurenta553c252009-07-17 12:17:14 -0700725 ioHandle, keyValuePairs.string(), gettid(), IPCThreadState::self()->getCallingPid());
726 // check calling permissions
727 if (!settingsAllowed()) {
728 return PERMISSION_DENIED;
The Android Open Source Project9266c552009-01-15 16:12:10 -0800729 }
Eric Laurenta553c252009-07-17 12:17:14 -0700730
731 // ioHandle == 0 means the parameters are global to the audio hardware interface
732 if (ioHandle == 0) {
733 AutoMutex lock(mHardwareLock);
734 mHardwareStatus = AUDIO_SET_PARAMETER;
Dima Zavin31f188892011-04-18 16:57:27 -0700735 status_t final_result = NO_ERROR;
736 for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
737 audio_hw_device_t *dev = mAudioHwDevs[i];
738 result = dev->set_parameters(dev, keyValuePairs.string());
739 final_result = result ?: final_result;
740 }
Eric Laurenta553c252009-07-17 12:17:14 -0700741 mHardwareStatus = AUDIO_HW_IDLE;
Dima Zavin31f188892011-04-18 16:57:27 -0700742 return final_result;
Eric Laurenta553c252009-07-17 12:17:14 -0700743 }
744
Eric Laurentb7d94602009-09-29 11:12:57 -0700745 // hold a strong ref on thread in case closeOutput() or closeInput() is called
746 // and the thread is exited once the lock is released
747 sp<ThreadBase> thread;
748 {
749 Mutex::Autolock _l(mLock);
750 thread = checkPlaybackThread_l(ioHandle);
751 if (thread == NULL) {
752 thread = checkRecordThread_l(ioHandle);
753 }
Eric Laurenta553c252009-07-17 12:17:14 -0700754 }
Eric Laurentb7d94602009-09-29 11:12:57 -0700755 if (thread != NULL) {
Glenn Kasten871c16c2010-03-05 12:18:01 -0800756 result = thread->setParameters(keyValuePairs);
Glenn Kasten871c16c2010-03-05 12:18:01 -0800757 return result;
Eric Laurenta553c252009-07-17 12:17:14 -0700758 }
Eric Laurenta553c252009-07-17 12:17:14 -0700759 return BAD_VALUE;
760}
761
Eric Laurentddb78e72009-07-28 08:44:33 -0700762String8 AudioFlinger::getParameters(int ioHandle, const String8& keys)
Eric Laurenta553c252009-07-17 12:17:14 -0700763{
Eric Laurentddb78e72009-07-28 08:44:33 -0700764// LOGV("getParameters() io %d, keys %s, tid %d, calling tid %d",
Eric Laurenta553c252009-07-17 12:17:14 -0700765// ioHandle, keys.string(), gettid(), IPCThreadState::self()->getCallingPid());
766
767 if (ioHandle == 0) {
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700768 String8 out_s8;
769
Dima Zavin31f188892011-04-18 16:57:27 -0700770 for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
771 audio_hw_device_t *dev = mAudioHwDevs[i];
772 char *s = dev->get_parameters(dev, keys.string());
773 out_s8 += String8(s);
774 free(s);
775 }
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700776 return out_s8;
Eric Laurenta553c252009-07-17 12:17:14 -0700777 }
Eric Laurentb7d94602009-09-29 11:12:57 -0700778
779 Mutex::Autolock _l(mLock);
780
Eric Laurenta553c252009-07-17 12:17:14 -0700781 PlaybackThread *playbackThread = checkPlaybackThread_l(ioHandle);
782 if (playbackThread != NULL) {
783 return playbackThread->getParameters(keys);
784 }
785 RecordThread *recordThread = checkRecordThread_l(ioHandle);
786 if (recordThread != NULL) {
787 return recordThread->getParameters(keys);
788 }
789 return String8("");
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700790}
791
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800792size_t AudioFlinger::getInputBufferSize(uint32_t sampleRate, int format, int channelCount)
793{
Dima Zavin31f188892011-04-18 16:57:27 -0700794 return mPrimaryHardwareDev->get_input_buffer_size(mPrimaryHardwareDev, sampleRate, format, channelCount);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800795}
796
Eric Laurent47d0a922010-02-26 02:47:27 -0800797unsigned int AudioFlinger::getInputFramesLost(int ioHandle)
798{
799 if (ioHandle == 0) {
800 return 0;
801 }
802
803 Mutex::Autolock _l(mLock);
804
805 RecordThread *recordThread = checkRecordThread_l(ioHandle);
806 if (recordThread != NULL) {
807 return recordThread->getInputFramesLost();
808 }
809 return 0;
810}
811
Eric Laurent415f3e22009-10-21 08:14:22 -0700812status_t AudioFlinger::setVoiceVolume(float value)
813{
814 // check calling permissions
815 if (!settingsAllowed()) {
816 return PERMISSION_DENIED;
817 }
818
819 AutoMutex lock(mHardwareLock);
820 mHardwareStatus = AUDIO_SET_VOICE_VOLUME;
Dima Zavin31f188892011-04-18 16:57:27 -0700821 status_t ret = mPrimaryHardwareDev->set_voice_volume(mPrimaryHardwareDev, value);
Eric Laurent415f3e22009-10-21 08:14:22 -0700822 mHardwareStatus = AUDIO_HW_IDLE;
823
824 return ret;
825}
826
Eric Laurent0986e792010-01-19 17:37:09 -0800827status_t AudioFlinger::getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames, int output)
828{
829 status_t status;
830
831 Mutex::Autolock _l(mLock);
832
833 PlaybackThread *playbackThread = checkPlaybackThread_l(output);
834 if (playbackThread != NULL) {
835 return playbackThread->getRenderPosition(halFrames, dspFrames);
836 }
837
838 return BAD_VALUE;
839}
840
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800841void AudioFlinger::registerClient(const sp<IAudioFlingerClient>& client)
842{
Eric Laurenta553c252009-07-17 12:17:14 -0700843
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800844 Mutex::Autolock _l(mLock);
845
Eric Laurent4f0f17d2010-05-12 02:05:53 -0700846 int pid = IPCThreadState::self()->getCallingPid();
847 if (mNotificationClients.indexOfKey(pid) < 0) {
848 sp<NotificationClient> notificationClient = new NotificationClient(this,
849 client,
850 pid);
851 LOGV("registerClient() client %p, pid %d", notificationClient.get(), pid);
Eric Laurenta553c252009-07-17 12:17:14 -0700852
Eric Laurent4f0f17d2010-05-12 02:05:53 -0700853 mNotificationClients.add(pid, notificationClient);
Eric Laurenta553c252009-07-17 12:17:14 -0700854
Eric Laurent4f0f17d2010-05-12 02:05:53 -0700855 sp<IBinder> binder = client->asBinder();
856 binder->linkToDeath(notificationClient);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800857
Eric Laurent4f0f17d2010-05-12 02:05:53 -0700858 // the config change is always sent from playback or record threads to avoid deadlock
859 // with AudioSystem::gLock
860 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
861 mPlaybackThreads.valueAt(i)->sendConfigEvent(AudioSystem::OUTPUT_OPENED);
862 }
Eric Laurenta553c252009-07-17 12:17:14 -0700863
Eric Laurent4f0f17d2010-05-12 02:05:53 -0700864 for (size_t i = 0; i < mRecordThreads.size(); i++) {
865 mRecordThreads.valueAt(i)->sendConfigEvent(AudioSystem::INPUT_OPENED);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800866 }
867 }
868}
869
Eric Laurent4f0f17d2010-05-12 02:05:53 -0700870void AudioFlinger::removeNotificationClient(pid_t pid)
871{
872 Mutex::Autolock _l(mLock);
873
874 int index = mNotificationClients.indexOfKey(pid);
875 if (index >= 0) {
876 sp <NotificationClient> client = mNotificationClients.valueFor(pid);
877 LOGV("removeNotificationClient() %p, pid %d", client.get(), pid);
Eric Laurent4f0f17d2010-05-12 02:05:53 -0700878 mNotificationClients.removeItem(pid);
879 }
880}
881
Eric Laurent296a0ec2009-09-15 07:10:12 -0700882// audioConfigChanged_l() must be called with AudioFlinger::mLock held
Eric Laurent4f0f17d2010-05-12 02:05:53 -0700883void AudioFlinger::audioConfigChanged_l(int event, int ioHandle, void *param2)
884{
Eric Laurent49f02be2009-11-19 09:00:56 -0800885 size_t size = mNotificationClients.size();
886 for (size_t i = 0; i < size; i++) {
Eric Laurent4f0f17d2010-05-12 02:05:53 -0700887 mNotificationClients.valueAt(i)->client()->ioConfigChanged(event, ioHandle, param2);
Eric Laurenta553c252009-07-17 12:17:14 -0700888 }
889}
890
Eric Laurentb9481d82009-09-17 05:12:56 -0700891// removeClient_l() must be called with AudioFlinger::mLock held
892void AudioFlinger::removeClient_l(pid_t pid)
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700893{
Eric Laurentb9481d82009-09-17 05:12:56 -0700894 LOGV("removeClient_l() pid %d, tid %d, calling tid %d", pid, gettid(), IPCThreadState::self()->getCallingPid());
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700895 mClients.removeItem(pid);
896}
897
Eric Laurent4f0f17d2010-05-12 02:05:53 -0700898
Eric Laurenta553c252009-07-17 12:17:14 -0700899// ----------------------------------------------------------------------------
900
Eric Laurent49f02be2009-11-19 09:00:56 -0800901AudioFlinger::ThreadBase::ThreadBase(const sp<AudioFlinger>& audioFlinger, int id)
Eric Laurenta553c252009-07-17 12:17:14 -0700902 : Thread(false),
903 mAudioFlinger(audioFlinger), mSampleRate(0), mFrameCount(0), mChannelCount(0),
Eric Laurentb0a01472010-05-14 05:45:46 -0700904 mFrameSize(1), mFormat(0), mStandby(false), mId(id), mExiting(false)
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700905{
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800906}
907
Eric Laurenta553c252009-07-17 12:17:14 -0700908AudioFlinger::ThreadBase::~ThreadBase()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800909{
Eric Laurent8fce46a2009-08-04 09:45:33 -0700910 mParamCond.broadcast();
911 mNewParameters.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800912}
913
Eric Laurenta553c252009-07-17 12:17:14 -0700914void AudioFlinger::ThreadBase::exit()
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -0700915{
Eric Laurentb7d94602009-09-29 11:12:57 -0700916 // keep a strong ref on ourself so that we wont get
Eric Laurenta553c252009-07-17 12:17:14 -0700917 // destroyed in the middle of requestExitAndWait()
918 sp <ThreadBase> strongMe = this;
919
920 LOGV("ThreadBase::exit");
921 {
922 AutoMutex lock(&mLock);
Eric Laurent49f02be2009-11-19 09:00:56 -0800923 mExiting = true;
Eric Laurenta553c252009-07-17 12:17:14 -0700924 requestExit();
925 mWaitWorkCV.signal();
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -0700926 }
Eric Laurenta553c252009-07-17 12:17:14 -0700927 requestExitAndWait();
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -0700928}
Eric Laurenta553c252009-07-17 12:17:14 -0700929
930uint32_t AudioFlinger::ThreadBase::sampleRate() const
931{
932 return mSampleRate;
933}
934
935int AudioFlinger::ThreadBase::channelCount() const
936{
Eric Laurentb0a01472010-05-14 05:45:46 -0700937 return (int)mChannelCount;
Eric Laurenta553c252009-07-17 12:17:14 -0700938}
939
940int AudioFlinger::ThreadBase::format() const
941{
942 return mFormat;
943}
944
945size_t AudioFlinger::ThreadBase::frameCount() const
946{
947 return mFrameCount;
948}
949
950status_t AudioFlinger::ThreadBase::setParameters(const String8& keyValuePairs)
951{
Eric Laurent8fce46a2009-08-04 09:45:33 -0700952 status_t status;
Eric Laurenta553c252009-07-17 12:17:14 -0700953
Eric Laurent8fce46a2009-08-04 09:45:33 -0700954 LOGV("ThreadBase::setParameters() %s", keyValuePairs.string());
Eric Laurenta553c252009-07-17 12:17:14 -0700955 Mutex::Autolock _l(mLock);
Eric Laurenta553c252009-07-17 12:17:14 -0700956
Eric Laurent8fce46a2009-08-04 09:45:33 -0700957 mNewParameters.add(keyValuePairs);
Eric Laurenta553c252009-07-17 12:17:14 -0700958 mWaitWorkCV.signal();
Eric Laurentb7d94602009-09-29 11:12:57 -0700959 // wait condition with timeout in case the thread loop has exited
960 // before the request could be processed
961 if (mParamCond.waitRelative(mLock, seconds(2)) == NO_ERROR) {
962 status = mParamStatus;
963 mWaitWorkCV.signal();
964 } else {
965 status = TIMED_OUT;
966 }
Eric Laurent8fce46a2009-08-04 09:45:33 -0700967 return status;
Eric Laurenta553c252009-07-17 12:17:14 -0700968}
969
970void AudioFlinger::ThreadBase::sendConfigEvent(int event, int param)
971{
972 Mutex::Autolock _l(mLock);
Eric Laurent8fce46a2009-08-04 09:45:33 -0700973 sendConfigEvent_l(event, param);
974}
975
976// sendConfigEvent_l() must be called with ThreadBase::mLock held
977void AudioFlinger::ThreadBase::sendConfigEvent_l(int event, int param)
978{
Eric Laurenta553c252009-07-17 12:17:14 -0700979 ConfigEvent *configEvent = new ConfigEvent();
980 configEvent->mEvent = event;
981 configEvent->mParam = param;
982 mConfigEvents.add(configEvent);
983 LOGV("sendConfigEvent() num events %d event %d, param %d", mConfigEvents.size(), event, param);
984 mWaitWorkCV.signal();
985}
986
987void AudioFlinger::ThreadBase::processConfigEvents()
988{
989 mLock.lock();
990 while(!mConfigEvents.isEmpty()) {
991 LOGV("processConfigEvents() remaining events %d", mConfigEvents.size());
992 ConfigEvent *configEvent = mConfigEvents[0];
993 mConfigEvents.removeAt(0);
Eric Laurenteb8f850d2010-05-14 03:26:45 -0700994 // release mLock before locking AudioFlinger mLock: lock order is always
995 // AudioFlinger then ThreadBase to avoid cross deadlock
Eric Laurenta553c252009-07-17 12:17:14 -0700996 mLock.unlock();
Eric Laurenteb8f850d2010-05-14 03:26:45 -0700997 mAudioFlinger->mLock.lock();
998 audioConfigChanged_l(configEvent->mEvent, configEvent->mParam);
999 mAudioFlinger->mLock.unlock();
Eric Laurenta553c252009-07-17 12:17:14 -07001000 delete configEvent;
1001 mLock.lock();
1002 }
1003 mLock.unlock();
1004}
1005
Eric Laurent3fdb1262009-11-07 00:01:32 -08001006status_t AudioFlinger::ThreadBase::dumpBase(int fd, const Vector<String16>& args)
1007{
1008 const size_t SIZE = 256;
1009 char buffer[SIZE];
1010 String8 result;
1011
1012 bool locked = tryLock(mLock);
1013 if (!locked) {
1014 snprintf(buffer, SIZE, "thread %p maybe dead locked\n", this);
1015 write(fd, buffer, strlen(buffer));
1016 }
1017
1018 snprintf(buffer, SIZE, "standby: %d\n", mStandby);
1019 result.append(buffer);
1020 snprintf(buffer, SIZE, "Sample rate: %d\n", mSampleRate);
1021 result.append(buffer);
1022 snprintf(buffer, SIZE, "Frame count: %d\n", mFrameCount);
1023 result.append(buffer);
1024 snprintf(buffer, SIZE, "Channel Count: %d\n", mChannelCount);
1025 result.append(buffer);
1026 snprintf(buffer, SIZE, "Format: %d\n", mFormat);
1027 result.append(buffer);
1028 snprintf(buffer, SIZE, "Frame size: %d\n", mFrameSize);
1029 result.append(buffer);
1030
1031 snprintf(buffer, SIZE, "\nPending setParameters commands: \n");
1032 result.append(buffer);
1033 result.append(" Index Command");
1034 for (size_t i = 0; i < mNewParameters.size(); ++i) {
1035 snprintf(buffer, SIZE, "\n %02d ", i);
1036 result.append(buffer);
1037 result.append(mNewParameters[i]);
1038 }
1039
1040 snprintf(buffer, SIZE, "\n\nPending config events: \n");
1041 result.append(buffer);
1042 snprintf(buffer, SIZE, " Index event param\n");
1043 result.append(buffer);
1044 for (size_t i = 0; i < mConfigEvents.size(); i++) {
1045 snprintf(buffer, SIZE, " %02d %02d %d\n", i, mConfigEvents[i]->mEvent, mConfigEvents[i]->mParam);
1046 result.append(buffer);
1047 }
1048 result.append("\n");
1049
1050 write(fd, result.string(), result.size());
1051
1052 if (locked) {
1053 mLock.unlock();
1054 }
1055 return NO_ERROR;
1056}
1057
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001058
1059// ----------------------------------------------------------------------------
1060
Dima Zavin31f188892011-04-18 16:57:27 -07001061AudioFlinger::PlaybackThread::PlaybackThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id, uint32_t device)
Eric Laurent49f02be2009-11-19 09:00:56 -08001062 : ThreadBase(audioFlinger, id),
Eric Laurentd5603c12009-08-06 08:49:39 -07001063 mMixBuffer(0), mSuspended(0), mBytesWritten(0), mOutput(output),
Eric Laurent65b65452010-06-01 23:49:17 -07001064 mLastWriteTime(0), mNumWrites(0), mNumDelayedWrites(0), mInWrite(false),
1065 mDevice(device)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001066{
Eric Laurenta553c252009-07-17 12:17:14 -07001067 readOutputParameters();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001068
Eric Laurenta553c252009-07-17 12:17:14 -07001069 mMasterVolume = mAudioFlinger->masterVolume();
1070 mMasterMute = mAudioFlinger->masterMute();
1071
Dima Zavin24fc2fb2011-04-19 22:30:36 -07001072 for (int stream = 0; stream < AUDIO_STREAM_CNT; stream++) {
Eric Laurenta553c252009-07-17 12:17:14 -07001073 mStreamTypes[stream].volume = mAudioFlinger->streamVolumeInternal(stream);
1074 mStreamTypes[stream].mute = mAudioFlinger->streamMute(stream);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001075 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001076}
1077
Eric Laurenta553c252009-07-17 12:17:14 -07001078AudioFlinger::PlaybackThread::~PlaybackThread()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001079{
1080 delete [] mMixBuffer;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001081}
1082
Eric Laurenta553c252009-07-17 12:17:14 -07001083status_t AudioFlinger::PlaybackThread::dump(int fd, const Vector<String16>& args)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001084{
1085 dumpInternals(fd, args);
1086 dumpTracks(fd, args);
Eric Laurent65b65452010-06-01 23:49:17 -07001087 dumpEffectChains(fd, args);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001088 return NO_ERROR;
1089}
1090
Eric Laurenta553c252009-07-17 12:17:14 -07001091status_t AudioFlinger::PlaybackThread::dumpTracks(int fd, const Vector<String16>& args)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001092{
1093 const size_t SIZE = 256;
1094 char buffer[SIZE];
1095 String8 result;
1096
Eric Laurenta553c252009-07-17 12:17:14 -07001097 snprintf(buffer, SIZE, "Output thread %p tracks\n", this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001098 result.append(buffer);
Eric Laurent65b65452010-06-01 23:49:17 -07001099 result.append(" Name Clien Typ Fmt Chn Session Buf S M F SRate LeftV RighV Serv User Main buf Aux Buf\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001100 for (size_t i = 0; i < mTracks.size(); ++i) {
Eric Laurentd3b4d0c2009-03-31 14:34:35 -07001101 sp<Track> track = mTracks[i];
1102 if (track != 0) {
1103 track->dump(buffer, SIZE);
1104 result.append(buffer);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001105 }
1106 }
1107
Eric Laurenta553c252009-07-17 12:17:14 -07001108 snprintf(buffer, SIZE, "Output thread %p active tracks\n", this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001109 result.append(buffer);
Eric Laurent65b65452010-06-01 23:49:17 -07001110 result.append(" Name Clien Typ Fmt Chn Session Buf S M F SRate LeftV RighV Serv User Main buf Aux Buf\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001111 for (size_t i = 0; i < mActiveTracks.size(); ++i) {
Eric Laurentd3b4d0c2009-03-31 14:34:35 -07001112 wp<Track> wTrack = mActiveTracks[i];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001113 if (wTrack != 0) {
1114 sp<Track> track = wTrack.promote();
1115 if (track != 0) {
1116 track->dump(buffer, SIZE);
1117 result.append(buffer);
1118 }
1119 }
1120 }
1121 write(fd, result.string(), result.size());
1122 return NO_ERROR;
1123}
1124
Eric Laurent65b65452010-06-01 23:49:17 -07001125status_t AudioFlinger::PlaybackThread::dumpEffectChains(int fd, const Vector<String16>& args)
1126{
1127 const size_t SIZE = 256;
1128 char buffer[SIZE];
1129 String8 result;
1130
1131 snprintf(buffer, SIZE, "\n- %d Effect Chains:\n", mEffectChains.size());
1132 write(fd, buffer, strlen(buffer));
1133
1134 for (size_t i = 0; i < mEffectChains.size(); ++i) {
1135 sp<EffectChain> chain = mEffectChains[i];
1136 if (chain != 0) {
1137 chain->dump(fd, args);
1138 }
1139 }
1140 return NO_ERROR;
1141}
1142
Eric Laurenta553c252009-07-17 12:17:14 -07001143status_t AudioFlinger::PlaybackThread::dumpInternals(int fd, const Vector<String16>& args)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001144{
1145 const size_t SIZE = 256;
1146 char buffer[SIZE];
1147 String8 result;
1148
Eric Laurent3fdb1262009-11-07 00:01:32 -08001149 snprintf(buffer, SIZE, "\nOutput thread %p internals\n", this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001150 result.append(buffer);
1151 snprintf(buffer, SIZE, "last write occurred (msecs): %llu\n", ns2ms(systemTime() - mLastWriteTime));
1152 result.append(buffer);
1153 snprintf(buffer, SIZE, "total writes: %d\n", mNumWrites);
1154 result.append(buffer);
1155 snprintf(buffer, SIZE, "delayed writes: %d\n", mNumDelayedWrites);
1156 result.append(buffer);
1157 snprintf(buffer, SIZE, "blocked in write: %d\n", mInWrite);
1158 result.append(buffer);
Eric Laurent8ac9f8d2009-12-18 05:47:48 -08001159 snprintf(buffer, SIZE, "suspend count: %d\n", mSuspended);
1160 result.append(buffer);
Eric Laurent65b65452010-06-01 23:49:17 -07001161 snprintf(buffer, SIZE, "mix buffer : %p\n", mMixBuffer);
1162 result.append(buffer);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001163 write(fd, result.string(), result.size());
Eric Laurent3fdb1262009-11-07 00:01:32 -08001164
1165 dumpBase(fd, args);
1166
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001167 return NO_ERROR;
1168}
1169
1170// Thread virtuals
Eric Laurenta553c252009-07-17 12:17:14 -07001171status_t AudioFlinger::PlaybackThread::readyToRun()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001172{
1173 if (mSampleRate == 0) {
1174 LOGE("No working audio driver found.");
1175 return NO_INIT;
1176 }
Eric Laurenta553c252009-07-17 12:17:14 -07001177 LOGI("AudioFlinger's thread %p ready to run", this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001178 return NO_ERROR;
1179}
1180
Eric Laurenta553c252009-07-17 12:17:14 -07001181void AudioFlinger::PlaybackThread::onFirstRef()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001182{
1183 const size_t SIZE = 256;
1184 char buffer[SIZE];
1185
Eric Laurenta553c252009-07-17 12:17:14 -07001186 snprintf(buffer, SIZE, "Playback Thread %p", this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001187
1188 run(buffer, ANDROID_PRIORITY_URGENT_AUDIO);
1189}
1190
Eric Laurenta553c252009-07-17 12:17:14 -07001191// PlaybackThread::createTrack_l() must be called with AudioFlinger::mLock held
1192sp<AudioFlinger::PlaybackThread::Track> AudioFlinger::PlaybackThread::createTrack_l(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001193 const sp<AudioFlinger::Client>& client,
1194 int streamType,
1195 uint32_t sampleRate,
1196 int format,
1197 int channelCount,
1198 int frameCount,
1199 const sp<IMemory>& sharedBuffer,
Eric Laurent65b65452010-06-01 23:49:17 -07001200 int sessionId,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001201 status_t *status)
1202{
1203 sp<Track> track;
1204 status_t lStatus;
Eric Laurenta553c252009-07-17 12:17:14 -07001205
1206 if (mType == DIRECT) {
Eric Laurentb0a01472010-05-14 05:45:46 -07001207 if (sampleRate != mSampleRate || format != mFormat || channelCount != (int)mChannelCount) {
Eric Laurenta553c252009-07-17 12:17:14 -07001208 LOGE("createTrack_l() Bad parameter: sampleRate %d format %d, channelCount %d for output %p",
1209 sampleRate, format, channelCount, mOutput);
1210 lStatus = BAD_VALUE;
1211 goto Exit;
1212 }
1213 } else {
1214 // Resampler implementation limits input sampling rate to 2 x output sampling rate.
1215 if (sampleRate > mSampleRate*2) {
1216 LOGE("Sample rate out of range: %d mSampleRate %d", sampleRate, mSampleRate);
1217 lStatus = BAD_VALUE;
1218 goto Exit;
1219 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001220 }
1221
Eric Laurenta553c252009-07-17 12:17:14 -07001222 if (mOutput == 0) {
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07001223 LOGE("Audio driver not initialized.");
1224 lStatus = NO_INIT;
1225 goto Exit;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001226 }
1227
Eric Laurenta553c252009-07-17 12:17:14 -07001228 { // scope for mLock
1229 Mutex::Autolock _l(mLock);
Eric Laurent8ed6ed02010-07-13 04:45:46 -07001230
1231 // all tracks in same audio session must share the same routing strategy otherwise
1232 // conflicts will happen when tracks are moved from one output to another by audio policy
1233 // manager
1234 uint32_t strategy =
Dima Zavin24fc2fb2011-04-19 22:30:36 -07001235 AudioSystem::getStrategyForStream((audio_stream_type_t)streamType);
Eric Laurent8ed6ed02010-07-13 04:45:46 -07001236 for (size_t i = 0; i < mTracks.size(); ++i) {
1237 sp<Track> t = mTracks[i];
1238 if (t != 0) {
1239 if (sessionId == t->sessionId() &&
Dima Zavin24fc2fb2011-04-19 22:30:36 -07001240 strategy != AudioSystem::getStrategyForStream((audio_stream_type_t)t->type())) {
Eric Laurent8ed6ed02010-07-13 04:45:46 -07001241 lStatus = BAD_VALUE;
1242 goto Exit;
1243 }
1244 }
1245 }
1246
Eric Laurenta553c252009-07-17 12:17:14 -07001247 track = new Track(this, client, streamType, sampleRate, format,
Eric Laurent65b65452010-06-01 23:49:17 -07001248 channelCount, frameCount, sharedBuffer, sessionId);
Eric Laurent73b60352009-11-09 04:45:39 -08001249 if (track->getCblk() == NULL || track->name() < 0) {
Eric Laurenta553c252009-07-17 12:17:14 -07001250 lStatus = NO_MEMORY;
1251 goto Exit;
1252 }
1253 mTracks.add(track);
Eric Laurent65b65452010-06-01 23:49:17 -07001254
1255 sp<EffectChain> chain = getEffectChain_l(sessionId);
1256 if (chain != 0) {
1257 LOGV("createTrack_l() setting main buffer %p", chain->inBuffer());
1258 track->setMainBuffer(chain->inBuffer());
Dima Zavin24fc2fb2011-04-19 22:30:36 -07001259 chain->setStrategy(AudioSystem::getStrategyForStream((audio_stream_type_t)track->type()));
Eric Laurent65b65452010-06-01 23:49:17 -07001260 }
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07001261 }
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07001262 lStatus = NO_ERROR;
1263
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001264Exit:
1265 if(status) {
1266 *status = lStatus;
1267 }
1268 return track;
1269}
1270
Eric Laurenta553c252009-07-17 12:17:14 -07001271uint32_t AudioFlinger::PlaybackThread::latency() const
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001272{
1273 if (mOutput) {
Dima Zavin31f188892011-04-18 16:57:27 -07001274 return mOutput->stream->get_latency(mOutput->stream);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001275 }
1276 else {
1277 return 0;
1278 }
1279}
1280
Eric Laurenta553c252009-07-17 12:17:14 -07001281status_t AudioFlinger::PlaybackThread::setMasterVolume(float value)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001282{
1283 mMasterVolume = value;
1284 return NO_ERROR;
1285}
1286
Eric Laurenta553c252009-07-17 12:17:14 -07001287status_t AudioFlinger::PlaybackThread::setMasterMute(bool muted)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001288{
1289 mMasterMute = muted;
1290 return NO_ERROR;
1291}
1292
Eric Laurenta553c252009-07-17 12:17:14 -07001293float AudioFlinger::PlaybackThread::masterVolume() const
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001294{
1295 return mMasterVolume;
1296}
1297
Eric Laurenta553c252009-07-17 12:17:14 -07001298bool AudioFlinger::PlaybackThread::masterMute() const
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001299{
1300 return mMasterMute;
1301}
1302
Eric Laurenta553c252009-07-17 12:17:14 -07001303status_t AudioFlinger::PlaybackThread::setStreamVolume(int stream, float value)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001304{
1305 mStreamTypes[stream].volume = value;
1306 return NO_ERROR;
1307}
1308
Eric Laurenta553c252009-07-17 12:17:14 -07001309status_t AudioFlinger::PlaybackThread::setStreamMute(int stream, bool muted)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001310{
1311 mStreamTypes[stream].mute = muted;
1312 return NO_ERROR;
1313}
1314
Eric Laurenta553c252009-07-17 12:17:14 -07001315float AudioFlinger::PlaybackThread::streamVolume(int stream) const
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001316{
1317 return mStreamTypes[stream].volume;
1318}
1319
Eric Laurenta553c252009-07-17 12:17:14 -07001320bool AudioFlinger::PlaybackThread::streamMute(int stream) const
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001321{
1322 return mStreamTypes[stream].mute;
1323}
1324
Eric Laurenta553c252009-07-17 12:17:14 -07001325// addTrack_l() must be called with ThreadBase::mLock held
1326status_t AudioFlinger::PlaybackThread::addTrack_l(const sp<Track>& track)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001327{
1328 status_t status = ALREADY_EXISTS;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001329
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001330 // set retry count for buffer fill
1331 track->mRetryCount = kMaxTrackStartupRetries;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001332 if (mActiveTracks.indexOf(track) < 0) {
1333 // the track is newly added, make sure it fills up all its
1334 // buffers before playing. This is to ensure the client will
1335 // effectively get the latency it requested.
1336 track->mFillingUpStatus = Track::FS_FILLING;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001337 track->mResetDone = false;
Eric Laurenta553c252009-07-17 12:17:14 -07001338 mActiveTracks.add(track);
Eric Laurent65b65452010-06-01 23:49:17 -07001339 if (track->mainBuffer() != mMixBuffer) {
1340 sp<EffectChain> chain = getEffectChain_l(track->sessionId());
1341 if (chain != 0) {
1342 LOGV("addTrack_l() starting track on chain %p for session %d", chain.get(), track->sessionId());
1343 chain->startTrack();
1344 }
1345 }
1346
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001347 status = NO_ERROR;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001348 }
Eric Laurenta553c252009-07-17 12:17:14 -07001349
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001350 LOGV("mWaitWorkCV.broadcast");
Eric Laurenta553c252009-07-17 12:17:14 -07001351 mWaitWorkCV.broadcast();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001352
1353 return status;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001354}
1355
Eric Laurenta553c252009-07-17 12:17:14 -07001356// destroyTrack_l() must be called with ThreadBase::mLock held
1357void AudioFlinger::PlaybackThread::destroyTrack_l(const sp<Track>& track)
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001358{
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001359 track->mState = TrackBase::TERMINATED;
1360 if (mActiveTracks.indexOf(track) < 0) {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001361 mTracks.remove(track);
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07001362 deleteTrackName_l(track->name());
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001363 }
1364}
1365
Eric Laurenta553c252009-07-17 12:17:14 -07001366String8 AudioFlinger::PlaybackThread::getParameters(const String8& keys)
The Android Open Source Projectf1e484a2009-01-22 00:13:42 -08001367{
Dima Zavin24fc2fb2011-04-19 22:30:36 -07001368 String8 out_s8;
1369 char *s;
1370
Dima Zavin31f188892011-04-18 16:57:27 -07001371 s = mOutput->stream->common.get_parameters(&mOutput->stream->common, keys.string());
Dima Zavin24fc2fb2011-04-19 22:30:36 -07001372 out_s8 = String8(s);
1373 free(s);
1374 return out_s8;
Eric Laurenta553c252009-07-17 12:17:14 -07001375}
The Android Open Source Projectf1e484a2009-01-22 00:13:42 -08001376
Eric Laurenteb8f850d2010-05-14 03:26:45 -07001377// destroyTrack_l() must be called with AudioFlinger::mLock held
1378void AudioFlinger::PlaybackThread::audioConfigChanged_l(int event, int param) {
Eric Laurenta553c252009-07-17 12:17:14 -07001379 AudioSystem::OutputDescriptor desc;
1380 void *param2 = 0;
1381
Eric Laurenteb8f850d2010-05-14 03:26:45 -07001382 LOGV("PlaybackThread::audioConfigChanged_l, thread %p, event %d, param %d", this, event, param);
Eric Laurenta553c252009-07-17 12:17:14 -07001383
1384 switch (event) {
1385 case AudioSystem::OUTPUT_OPENED:
1386 case AudioSystem::OUTPUT_CONFIG_CHANGED:
Eric Laurentb0a01472010-05-14 05:45:46 -07001387 desc.channels = mChannels;
Eric Laurenta553c252009-07-17 12:17:14 -07001388 desc.samplingRate = mSampleRate;
1389 desc.format = mFormat;
1390 desc.frameCount = mFrameCount;
1391 desc.latency = latency();
1392 param2 = &desc;
1393 break;
1394
1395 case AudioSystem::STREAM_CONFIG_CHANGED:
1396 param2 = &param;
1397 case AudioSystem::OUTPUT_CLOSED:
1398 default:
1399 break;
1400 }
Eric Laurent49f02be2009-11-19 09:00:56 -08001401 mAudioFlinger->audioConfigChanged_l(event, mId, param2);
Eric Laurenta553c252009-07-17 12:17:14 -07001402}
1403
1404void AudioFlinger::PlaybackThread::readOutputParameters()
1405{
Dima Zavin31f188892011-04-18 16:57:27 -07001406 mSampleRate = mOutput->stream->common.get_sample_rate(&mOutput->stream->common);
1407 mChannels = mOutput->stream->common.get_channels(&mOutput->stream->common);
Dima Zavin24fc2fb2011-04-19 22:30:36 -07001408 mChannelCount = (uint16_t)popcount(mChannels);
Dima Zavin31f188892011-04-18 16:57:27 -07001409 mFormat = mOutput->stream->common.get_format(&mOutput->stream->common);
1410 mFrameSize = (uint16_t)audio_stream_frame_size(&mOutput->stream->common);
1411 mFrameCount = mOutput->stream->common.get_buffer_size(&mOutput->stream->common) / mFrameSize;
Eric Laurenta553c252009-07-17 12:17:14 -07001412
Eric Laurenta553c252009-07-17 12:17:14 -07001413 // FIXME - Current mixer implementation only supports stereo output: Always
1414 // Allocate a stereo buffer even if HW output is mono.
Eric Laurent65b65452010-06-01 23:49:17 -07001415 if (mMixBuffer != NULL) delete[] mMixBuffer;
Eric Laurenta553c252009-07-17 12:17:14 -07001416 mMixBuffer = new int16_t[mFrameCount * 2];
1417 memset(mMixBuffer, 0, mFrameCount * 2 * sizeof(int16_t));
Eric Laurent65b65452010-06-01 23:49:17 -07001418
Eric Laurent8ed6ed02010-07-13 04:45:46 -07001419 // force reconfiguration of effect chains and engines to take new buffer size and audio
1420 // parameters into account
1421 // Note that mLock is not held when readOutputParameters() is called from the constructor
1422 // but in this case nothing is done below as no audio sessions have effect yet so it doesn't
1423 // matter.
1424 // create a copy of mEffectChains as calling moveEffectChain_l() can reorder some effect chains
1425 Vector< sp<EffectChain> > effectChains = mEffectChains;
1426 for (size_t i = 0; i < effectChains.size(); i ++) {
Eric Laurent493941b2010-07-28 01:32:47 -07001427 mAudioFlinger->moveEffectChain_l(effectChains[i]->sessionId(), this, this, false);
Eric Laurent8ed6ed02010-07-13 04:45:46 -07001428 }
Eric Laurenta553c252009-07-17 12:17:14 -07001429}
1430
Eric Laurent0986e792010-01-19 17:37:09 -08001431status_t AudioFlinger::PlaybackThread::getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames)
1432{
1433 if (halFrames == 0 || dspFrames == 0) {
1434 return BAD_VALUE;
1435 }
1436 if (mOutput == 0) {
1437 return INVALID_OPERATION;
1438 }
Dima Zavin31f188892011-04-18 16:57:27 -07001439 *halFrames = mBytesWritten / audio_stream_frame_size(&mOutput->stream->common);
Eric Laurent0986e792010-01-19 17:37:09 -08001440
Dima Zavin31f188892011-04-18 16:57:27 -07001441 return mOutput->stream->get_render_position(mOutput->stream, dspFrames);
Eric Laurent0986e792010-01-19 17:37:09 -08001442}
1443
Eric Laurent493941b2010-07-28 01:32:47 -07001444uint32_t AudioFlinger::PlaybackThread::hasAudioSession(int sessionId)
Eric Laurent65b65452010-06-01 23:49:17 -07001445{
1446 Mutex::Autolock _l(mLock);
Eric Laurent493941b2010-07-28 01:32:47 -07001447 uint32_t result = 0;
Eric Laurent65b65452010-06-01 23:49:17 -07001448 if (getEffectChain_l(sessionId) != 0) {
Eric Laurent493941b2010-07-28 01:32:47 -07001449 result = EFFECT_SESSION;
Eric Laurent65b65452010-06-01 23:49:17 -07001450 }
1451
1452 for (size_t i = 0; i < mTracks.size(); ++i) {
1453 sp<Track> track = mTracks[i];
Eric Laurent8ed6ed02010-07-13 04:45:46 -07001454 if (sessionId == track->sessionId() &&
1455 !(track->mCblk->flags & CBLK_INVALID_MSK)) {
Eric Laurent493941b2010-07-28 01:32:47 -07001456 result |= TRACK_SESSION;
1457 break;
Eric Laurent65b65452010-06-01 23:49:17 -07001458 }
1459 }
1460
Eric Laurent493941b2010-07-28 01:32:47 -07001461 return result;
Eric Laurent65b65452010-06-01 23:49:17 -07001462}
1463
Eric Laurent8ed6ed02010-07-13 04:45:46 -07001464uint32_t AudioFlinger::PlaybackThread::getStrategyForSession_l(int sessionId)
1465{
Dima Zavin24fc2fb2011-04-19 22:30:36 -07001466 // session AUDIO_SESSION_OUTPUT_MIX is placed in same strategy as MUSIC stream so that
Eric Laurent8ed6ed02010-07-13 04:45:46 -07001467 // it is moved to correct output by audio policy manager when A2DP is connected or disconnected
Dima Zavin24fc2fb2011-04-19 22:30:36 -07001468 if (sessionId == AUDIO_SESSION_OUTPUT_MIX) {
1469 return AudioSystem::getStrategyForStream(AUDIO_STREAM_MUSIC);
Eric Laurent8ed6ed02010-07-13 04:45:46 -07001470 }
1471 for (size_t i = 0; i < mTracks.size(); i++) {
1472 sp<Track> track = mTracks[i];
1473 if (sessionId == track->sessionId() &&
1474 !(track->mCblk->flags & CBLK_INVALID_MSK)) {
Dima Zavin24fc2fb2011-04-19 22:30:36 -07001475 return AudioSystem::getStrategyForStream((audio_stream_type_t) track->type());
Eric Laurent8ed6ed02010-07-13 04:45:46 -07001476 }
1477 }
Dima Zavin24fc2fb2011-04-19 22:30:36 -07001478 return AudioSystem::getStrategyForStream(AUDIO_STREAM_MUSIC);
Eric Laurent8ed6ed02010-07-13 04:45:46 -07001479}
1480
Eric Laurent65b65452010-06-01 23:49:17 -07001481sp<AudioFlinger::EffectChain> AudioFlinger::PlaybackThread::getEffectChain(int sessionId)
1482{
1483 Mutex::Autolock _l(mLock);
1484 return getEffectChain_l(sessionId);
1485}
1486
1487sp<AudioFlinger::EffectChain> AudioFlinger::PlaybackThread::getEffectChain_l(int sessionId)
1488{
1489 sp<EffectChain> chain;
1490
1491 size_t size = mEffectChains.size();
1492 for (size_t i = 0; i < size; i++) {
1493 if (mEffectChains[i]->sessionId() == sessionId) {
1494 chain = mEffectChains[i];
1495 break;
1496 }
1497 }
1498 return chain;
1499}
1500
Eric Laurent53334cd2010-06-23 17:38:20 -07001501void AudioFlinger::PlaybackThread::setMode(uint32_t mode)
1502{
1503 Mutex::Autolock _l(mLock);
1504 size_t size = mEffectChains.size();
1505 for (size_t i = 0; i < size; i++) {
Eric Laurent76c40f72010-07-15 12:50:15 -07001506 mEffectChains[i]->setMode_l(mode);
Eric Laurent53334cd2010-06-23 17:38:20 -07001507 }
1508}
1509
Eric Laurenta553c252009-07-17 12:17:14 -07001510// ----------------------------------------------------------------------------
1511
Dima Zavin31f188892011-04-18 16:57:27 -07001512AudioFlinger::MixerThread::MixerThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id, uint32_t device)
Eric Laurent65b65452010-06-01 23:49:17 -07001513 : PlaybackThread(audioFlinger, output, id, device),
Eric Laurenta553c252009-07-17 12:17:14 -07001514 mAudioMixer(0)
1515{
1516 mType = PlaybackThread::MIXER;
1517 mAudioMixer = new AudioMixer(mFrameCount, mSampleRate);
1518
1519 // FIXME - Current mixer implementation only supports stereo output
1520 if (mChannelCount == 1) {
1521 LOGE("Invalid audio hardware channel count");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001522 }
The Android Open Source Projectf1e484a2009-01-22 00:13:42 -08001523}
1524
Eric Laurenta553c252009-07-17 12:17:14 -07001525AudioFlinger::MixerThread::~MixerThread()
The Android Open Source Projectf1e484a2009-01-22 00:13:42 -08001526{
Eric Laurenta553c252009-07-17 12:17:14 -07001527 delete mAudioMixer;
1528}
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001529
Eric Laurenta553c252009-07-17 12:17:14 -07001530bool AudioFlinger::MixerThread::threadLoop()
1531{
Eric Laurenta553c252009-07-17 12:17:14 -07001532 Vector< sp<Track> > tracksToRemove;
Eric Laurent059b4be2009-11-09 23:32:22 -08001533 uint32_t mixerStatus = MIXER_IDLE;
Eric Laurenta553c252009-07-17 12:17:14 -07001534 nsecs_t standbyTime = systemTime();
1535 size_t mixBufferSize = mFrameCount * mFrameSize;
Dave Sparksd0ac8c02009-09-30 03:09:03 -07001536 // FIXME: Relaxed timing because of a certain device that can't meet latency
1537 // Should be reduced to 2x after the vendor fixes the driver issue
1538 nsecs_t maxPeriod = seconds(mFrameCount) / mSampleRate * 3;
1539 nsecs_t lastWarning = 0;
Eric Laurent059b4be2009-11-09 23:32:22 -08001540 bool longStandbyExit = false;
1541 uint32_t activeSleepTime = activeSleepTimeUs();
1542 uint32_t idleSleepTime = idleSleepTimeUs();
1543 uint32_t sleepTime = idleSleepTime;
Eric Laurent65b65452010-06-01 23:49:17 -07001544 Vector< sp<EffectChain> > effectChains;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001545
Eric Laurenta553c252009-07-17 12:17:14 -07001546 while (!exitPending())
1547 {
1548 processConfigEvents();
1549
Eric Laurent059b4be2009-11-09 23:32:22 -08001550 mixerStatus = MIXER_IDLE;
Eric Laurenta553c252009-07-17 12:17:14 -07001551 { // scope for mLock
1552
1553 Mutex::Autolock _l(mLock);
1554
1555 if (checkForNewParameters_l()) {
1556 mixBufferSize = mFrameCount * mFrameSize;
Dave Sparksd0ac8c02009-09-30 03:09:03 -07001557 // FIXME: Relaxed timing because of a certain device that can't meet latency
1558 // Should be reduced to 2x after the vendor fixes the driver issue
1559 maxPeriod = seconds(mFrameCount) / mSampleRate * 3;
Eric Laurent059b4be2009-11-09 23:32:22 -08001560 activeSleepTime = activeSleepTimeUs();
1561 idleSleepTime = idleSleepTimeUs();
Eric Laurenta553c252009-07-17 12:17:14 -07001562 }
1563
1564 const SortedVector< wp<Track> >& activeTracks = mActiveTracks;
1565
1566 // put audio hardware into standby after short delay
1567 if UNLIKELY((!activeTracks.size() && systemTime() > standbyTime) ||
1568 mSuspended) {
1569 if (!mStandby) {
1570 LOGV("Audio hardware entering standby, mixer %p, mSuspended %d\n", this, mSuspended);
Dima Zavin31f188892011-04-18 16:57:27 -07001571 mOutput->stream->common.standby(&mOutput->stream->common);
Eric Laurenta553c252009-07-17 12:17:14 -07001572 mStandby = true;
1573 mBytesWritten = 0;
1574 }
1575
1576 if (!activeTracks.size() && mConfigEvents.isEmpty()) {
1577 // we're about to wait, flush the binder command buffer
1578 IPCThreadState::self()->flushCommands();
1579
1580 if (exitPending()) break;
1581
1582 // wait until we have something to do...
1583 LOGV("MixerThread %p TID %d going to sleep\n", this, gettid());
1584 mWaitWorkCV.wait(mLock);
1585 LOGV("MixerThread %p TID %d waking up\n", this, gettid());
1586
1587 if (mMasterMute == false) {
1588 char value[PROPERTY_VALUE_MAX];
1589 property_get("ro.audio.silent", value, "0");
1590 if (atoi(value)) {
1591 LOGD("Silence is golden");
1592 setMasterMute(true);
1593 }
1594 }
1595
1596 standbyTime = systemTime() + kStandbyTimeInNsecs;
Eric Laurent059b4be2009-11-09 23:32:22 -08001597 sleepTime = idleSleepTime;
Eric Laurenta553c252009-07-17 12:17:14 -07001598 continue;
1599 }
1600 }
1601
Eric Laurent059b4be2009-11-09 23:32:22 -08001602 mixerStatus = prepareTracks_l(activeTracks, &tracksToRemove);
Eric Laurent65b65452010-06-01 23:49:17 -07001603
1604 // prevent any changes in effect chain list and in each effect chain
1605 // during mixing and effect process as the audio buffers could be deleted
1606 // or modified if an effect is created or deleted
Eric Laurent8ed6ed02010-07-13 04:45:46 -07001607 lockEffectChains_l(effectChains);
Eric Laurenta553c252009-07-17 12:17:14 -07001608 }
1609
Eric Laurent059b4be2009-11-09 23:32:22 -08001610 if (LIKELY(mixerStatus == MIXER_TRACKS_READY)) {
Eric Laurentf69a3f82009-09-22 00:35:48 -07001611 // mix buffers...
Eric Laurent65b65452010-06-01 23:49:17 -07001612 mAudioMixer->process();
Eric Laurentf69a3f82009-09-22 00:35:48 -07001613 sleepTime = 0;
1614 standbyTime = systemTime() + kStandbyTimeInNsecs;
Eric Laurent65b65452010-06-01 23:49:17 -07001615 //TODO: delay standby when effects have a tail
Eric Laurent96c08a62009-09-07 08:38:38 -07001616 } else {
Eric Laurent62443f52009-10-05 20:29:18 -07001617 // If no tracks are ready, sleep once for the duration of an output
1618 // buffer size, then write 0s to the output
1619 if (sleepTime == 0) {
Eric Laurent059b4be2009-11-09 23:32:22 -08001620 if (mixerStatus == MIXER_TRACKS_ENABLED) {
1621 sleepTime = activeSleepTime;
1622 } else {
1623 sleepTime = idleSleepTime;
1624 }
1625 } else if (mBytesWritten != 0 ||
1626 (mixerStatus == MIXER_TRACKS_ENABLED && longStandbyExit)) {
Eric Laurent65b65452010-06-01 23:49:17 -07001627 memset (mMixBuffer, 0, mixBufferSize);
Eric Laurent96c08a62009-09-07 08:38:38 -07001628 sleepTime = 0;
Eric Laurent059b4be2009-11-09 23:32:22 -08001629 LOGV_IF((mBytesWritten == 0 && (mixerStatus == MIXER_TRACKS_ENABLED && longStandbyExit)), "anticipated start");
Eric Laurent96c08a62009-09-07 08:38:38 -07001630 }
Eric Laurent65b65452010-06-01 23:49:17 -07001631 // TODO add standby time extension fct of effect tail
Eric Laurentf69a3f82009-09-22 00:35:48 -07001632 }
1633
1634 if (mSuspended) {
Eric Laurent8448a792010-08-18 18:13:17 -07001635 sleepTime = suspendSleepTimeUs();
Eric Laurentf69a3f82009-09-22 00:35:48 -07001636 }
1637 // sleepTime == 0 means we must write to audio hardware
1638 if (sleepTime == 0) {
Eric Laurent65b65452010-06-01 23:49:17 -07001639 for (size_t i = 0; i < effectChains.size(); i ++) {
1640 effectChains[i]->process_l();
1641 }
1642 // enable changes in effect chain
Eric Laurent8ed6ed02010-07-13 04:45:46 -07001643 unlockEffectChains(effectChains);
Eric Laurent65b65452010-06-01 23:49:17 -07001644 mLastWriteTime = systemTime();
1645 mInWrite = true;
1646 mBytesWritten += mixBufferSize;
1647
Dima Zavin31f188892011-04-18 16:57:27 -07001648 int bytesWritten = (int)mOutput->stream->write(mOutput->stream, mMixBuffer, mixBufferSize);
Eric Laurent0986e792010-01-19 17:37:09 -08001649 if (bytesWritten < 0) mBytesWritten -= mixBufferSize;
Eric Laurentf69a3f82009-09-22 00:35:48 -07001650 mNumWrites++;
1651 mInWrite = false;
Dave Sparksd0ac8c02009-09-30 03:09:03 -07001652 nsecs_t now = systemTime();
1653 nsecs_t delta = now - mLastWriteTime;
Eric Laurentf69a3f82009-09-22 00:35:48 -07001654 if (delta > maxPeriod) {
Eric Laurentf69a3f82009-09-22 00:35:48 -07001655 mNumDelayedWrites++;
Dave Sparksd0ac8c02009-09-30 03:09:03 -07001656 if ((now - lastWarning) > kWarningThrottle) {
1657 LOGW("write blocked for %llu msecs, %d delayed writes, thread %p",
1658 ns2ms(delta), mNumDelayedWrites, this);
1659 lastWarning = now;
1660 }
Eric Laurent059b4be2009-11-09 23:32:22 -08001661 if (mStandby) {
1662 longStandbyExit = true;
1663 }
Eric Laurenta553c252009-07-17 12:17:14 -07001664 }
Eric Laurent059b4be2009-11-09 23:32:22 -08001665 mStandby = false;
Eric Laurentf69a3f82009-09-22 00:35:48 -07001666 } else {
Eric Laurent65b65452010-06-01 23:49:17 -07001667 // enable changes in effect chain
Eric Laurent8ed6ed02010-07-13 04:45:46 -07001668 unlockEffectChains(effectChains);
Eric Laurentf69a3f82009-09-22 00:35:48 -07001669 usleep(sleepTime);
Eric Laurenta553c252009-07-17 12:17:14 -07001670 }
1671
1672 // finally let go of all our tracks, without the lock held
1673 // since we can't guarantee the destructors won't acquire that
1674 // same lock.
1675 tracksToRemove.clear();
Eric Laurent65b65452010-06-01 23:49:17 -07001676
1677 // Effect chains will be actually deleted here if they were removed from
1678 // mEffectChains list during mixing or effects processing
1679 effectChains.clear();
Eric Laurenta553c252009-07-17 12:17:14 -07001680 }
1681
1682 if (!mStandby) {
Dima Zavin31f188892011-04-18 16:57:27 -07001683 mOutput->stream->common.standby(&mOutput->stream->common);
Eric Laurenta553c252009-07-17 12:17:14 -07001684 }
Eric Laurenta553c252009-07-17 12:17:14 -07001685
1686 LOGV("MixerThread %p exiting", this);
1687 return false;
1688}
1689
1690// prepareTracks_l() must be called with ThreadBase::mLock held
Eric Laurent059b4be2009-11-09 23:32:22 -08001691uint32_t AudioFlinger::MixerThread::prepareTracks_l(const SortedVector< wp<Track> >& activeTracks, Vector< sp<Track> > *tracksToRemove)
Eric Laurenta553c252009-07-17 12:17:14 -07001692{
1693
Eric Laurent059b4be2009-11-09 23:32:22 -08001694 uint32_t mixerStatus = MIXER_IDLE;
Eric Laurenta553c252009-07-17 12:17:14 -07001695 // find out which tracks need to be processed
1696 size_t count = activeTracks.size();
Eric Laurent65b65452010-06-01 23:49:17 -07001697 size_t mixedTracks = 0;
1698 size_t tracksWithEffect = 0;
Glenn Kasten871c16c2010-03-05 12:18:01 -08001699
1700 float masterVolume = mMasterVolume;
1701 bool masterMute = mMasterMute;
1702
Eric Laurent8cc93b92010-08-11 05:20:11 -07001703 if (masterMute) {
1704 masterVolume = 0;
1705 }
Eric Laurent65b65452010-06-01 23:49:17 -07001706 // Delegate master volume control to effect in output mix effect chain if needed
Dima Zavin24fc2fb2011-04-19 22:30:36 -07001707 sp<EffectChain> chain = getEffectChain_l(AUDIO_SESSION_OUTPUT_MIX);
Eric Laurent65b65452010-06-01 23:49:17 -07001708 if (chain != 0) {
Eric Laurent8cc93b92010-08-11 05:20:11 -07001709 uint32_t v = (uint32_t)(masterVolume * (1 << 24));
Eric Laurent76c40f72010-07-15 12:50:15 -07001710 chain->setVolume_l(&v, &v);
Eric Laurent65b65452010-06-01 23:49:17 -07001711 masterVolume = (float)((v + (1 << 23)) >> 24);
1712 chain.clear();
1713 }
Glenn Kasten871c16c2010-03-05 12:18:01 -08001714
Eric Laurenta553c252009-07-17 12:17:14 -07001715 for (size_t i=0 ; i<count ; i++) {
1716 sp<Track> t = activeTracks[i].promote();
1717 if (t == 0) continue;
1718
1719 Track* const track = t.get();
1720 audio_track_cblk_t* cblk = track->cblk();
1721
1722 // The first time a track is added we wait
1723 // for all its buffers to be filled before processing it
1724 mAudioMixer->setActiveTrack(track->name());
Eric Laurent9a30fc12010-10-05 14:41:42 -07001725 if (cblk->framesReady() && track->isReady() &&
Eric Laurent71f37cd2010-03-31 12:21:17 -07001726 !track->isPaused() && !track->isTerminated())
Eric Laurenta553c252009-07-17 12:17:14 -07001727 {
Eric Laurent8ac9f8d2009-12-18 05:47:48 -08001728 //LOGV("track %d u=%08x, s=%08x [OK] on thread %p", track->name(), cblk->user, cblk->server, this);
Eric Laurenta553c252009-07-17 12:17:14 -07001729
Eric Laurent65b65452010-06-01 23:49:17 -07001730 mixedTracks++;
1731
1732 // track->mainBuffer() != mMixBuffer means there is an effect chain
1733 // connected to the track
1734 chain.clear();
1735 if (track->mainBuffer() != mMixBuffer) {
1736 chain = getEffectChain_l(track->sessionId());
1737 // Delegate volume control to effect in track effect chain if needed
1738 if (chain != 0) {
1739 tracksWithEffect++;
1740 } else {
1741 LOGW("prepareTracks_l(): track %08x attached to effect but no chain found on session %d",
1742 track->name(), track->sessionId());
1743 }
1744 }
1745
1746
1747 int param = AudioMixer::VOLUME;
1748 if (track->mFillingUpStatus == Track::FS_FILLED) {
1749 // no ramp for the first volume setting
1750 track->mFillingUpStatus = Track::FS_ACTIVE;
1751 if (track->mState == TrackBase::RESUMING) {
1752 track->mState = TrackBase::ACTIVE;
1753 param = AudioMixer::RAMP_VOLUME;
1754 }
Eric Laurent4bb21c42011-02-28 16:52:51 -08001755 mAudioMixer->setParameter(AudioMixer::RESAMPLE, AudioMixer::RESET, NULL);
Eric Laurent65b65452010-06-01 23:49:17 -07001756 } else if (cblk->server != 0) {
1757 // If the track is stopped before the first frame was mixed,
1758 // do not apply ramp
1759 param = AudioMixer::RAMP_VOLUME;
1760 }
1761
Eric Laurenta553c252009-07-17 12:17:14 -07001762 // compute volume for this track
Eric Laurent27a2fdf2010-09-10 17:44:44 -07001763 uint32_t vl, vr, va;
Eric Laurent2a6b80b2010-07-29 23:43:43 -07001764 if (track->isMuted() || track->isPausing() ||
Eric Laurenta553c252009-07-17 12:17:14 -07001765 mStreamTypes[track->type()].mute) {
Eric Laurent27a2fdf2010-09-10 17:44:44 -07001766 vl = vr = va = 0;
Eric Laurenta553c252009-07-17 12:17:14 -07001767 if (track->isPausing()) {
1768 track->setPaused();
1769 }
1770 } else {
Eric Laurent27a2fdf2010-09-10 17:44:44 -07001771
Glenn Kasten871c16c2010-03-05 12:18:01 -08001772 // read original volumes with volume control
Eric Laurenta553c252009-07-17 12:17:14 -07001773 float typeVolume = mStreamTypes[track->type()].volume;
Glenn Kasten871c16c2010-03-05 12:18:01 -08001774 float v = masterVolume * typeVolume;
Eric Laurent27a2fdf2010-09-10 17:44:44 -07001775 vl = (uint32_t)(v * cblk->volume[0]) << 12;
1776 vr = (uint32_t)(v * cblk->volume[1]) << 12;
Eric Laurenta553c252009-07-17 12:17:14 -07001777
Eric Laurent27a2fdf2010-09-10 17:44:44 -07001778 va = (uint32_t)(v * cblk->sendLevel);
Eric Laurenta553c252009-07-17 12:17:14 -07001779 }
Eric Laurent27a2fdf2010-09-10 17:44:44 -07001780 // Delegate volume control to effect in track effect chain if needed
1781 if (chain != 0 && chain->setVolume_l(&vl, &vr)) {
1782 // Do not ramp volume if volume is controlled by effect
1783 param = AudioMixer::VOLUME;
1784 track->mHasVolumeController = true;
1785 } else {
1786 // force no volume ramp when volume controller was just disabled or removed
1787 // from effect chain to avoid volume spike
1788 if (track->mHasVolumeController) {
1789 param = AudioMixer::VOLUME;
1790 }
1791 track->mHasVolumeController = false;
1792 }
1793
1794 // Convert volumes from 8.24 to 4.12 format
1795 int16_t left, right, aux;
1796 uint32_t v_clamped = (vl + (1 << 11)) >> 12;
1797 if (v_clamped > MAX_GAIN_INT) v_clamped = MAX_GAIN_INT;
1798 left = int16_t(v_clamped);
1799 v_clamped = (vr + (1 << 11)) >> 12;
1800 if (v_clamped > MAX_GAIN_INT) v_clamped = MAX_GAIN_INT;
1801 right = int16_t(v_clamped);
1802
1803 if (va > MAX_GAIN_INT) va = MAX_GAIN_INT;
1804 aux = int16_t(va);
Eric Laurent65b65452010-06-01 23:49:17 -07001805
Eric Laurent65b65452010-06-01 23:49:17 -07001806 // XXX: these things DON'T need to be done each time
1807 mAudioMixer->setBufferProvider(track);
1808 mAudioMixer->enable(AudioMixer::MIXING);
1809
1810 mAudioMixer->setParameter(param, AudioMixer::VOLUME0, (void *)left);
1811 mAudioMixer->setParameter(param, AudioMixer::VOLUME1, (void *)right);
1812 mAudioMixer->setParameter(param, AudioMixer::AUXLEVEL, (void *)aux);
Eric Laurenta553c252009-07-17 12:17:14 -07001813 mAudioMixer->setParameter(
1814 AudioMixer::TRACK,
Eric Laurent65b65452010-06-01 23:49:17 -07001815 AudioMixer::FORMAT, (void *)track->format());
Eric Laurenta553c252009-07-17 12:17:14 -07001816 mAudioMixer->setParameter(
1817 AudioMixer::TRACK,
Eric Laurent65b65452010-06-01 23:49:17 -07001818 AudioMixer::CHANNEL_COUNT, (void *)track->channelCount());
Eric Laurenta553c252009-07-17 12:17:14 -07001819 mAudioMixer->setParameter(
1820 AudioMixer::RESAMPLE,
1821 AudioMixer::SAMPLE_RATE,
Eric Laurent65b65452010-06-01 23:49:17 -07001822 (void *)(cblk->sampleRate));
1823 mAudioMixer->setParameter(
1824 AudioMixer::TRACK,
1825 AudioMixer::MAIN_BUFFER, (void *)track->mainBuffer());
1826 mAudioMixer->setParameter(
1827 AudioMixer::TRACK,
1828 AudioMixer::AUX_BUFFER, (void *)track->auxBuffer());
Eric Laurenta553c252009-07-17 12:17:14 -07001829
1830 // reset retry count
1831 track->mRetryCount = kMaxTrackRetries;
Eric Laurent059b4be2009-11-09 23:32:22 -08001832 mixerStatus = MIXER_TRACKS_READY;
Eric Laurenta553c252009-07-17 12:17:14 -07001833 } else {
Eric Laurent8ac9f8d2009-12-18 05:47:48 -08001834 //LOGV("track %d u=%08x, s=%08x [NOT READY] on thread %p", track->name(), cblk->user, cblk->server, this);
Eric Laurenta553c252009-07-17 12:17:14 -07001835 if (track->isStopped()) {
1836 track->reset();
1837 }
1838 if (track->isTerminated() || track->isStopped() || track->isPaused()) {
1839 // We have consumed all the buffers of this track.
1840 // Remove it from the list of active tracks.
1841 tracksToRemove->add(track);
Eric Laurenta553c252009-07-17 12:17:14 -07001842 } else {
1843 // No buffers for this track. Give it a few chances to
1844 // fill a buffer, then remove it from active list.
1845 if (--(track->mRetryCount) <= 0) {
Eric Laurent62443f52009-10-05 20:29:18 -07001846 LOGV("BUFFER TIMEOUT: remove(%d) from active list on thread %p", track->name(), this);
Eric Laurenta553c252009-07-17 12:17:14 -07001847 tracksToRemove->add(track);
Eric Laurent4712baa2010-09-30 16:12:31 -07001848 // indicate to client process that the track was disabled because of underrun
Eric Laurentae29b762011-03-28 18:37:07 -07001849 android_atomic_or(CBLK_DISABLED_ON, &cblk->flags);
Eric Laurent059b4be2009-11-09 23:32:22 -08001850 } else if (mixerStatus != MIXER_TRACKS_READY) {
1851 mixerStatus = MIXER_TRACKS_ENABLED;
Eric Laurenta553c252009-07-17 12:17:14 -07001852 }
Eric Laurenta553c252009-07-17 12:17:14 -07001853 }
Eric Laurent65b65452010-06-01 23:49:17 -07001854 mAudioMixer->disable(AudioMixer::MIXING);
Eric Laurenta553c252009-07-17 12:17:14 -07001855 }
1856 }
1857
1858 // remove all the tracks that need to be...
1859 count = tracksToRemove->size();
1860 if (UNLIKELY(count)) {
1861 for (size_t i=0 ; i<count ; i++) {
1862 const sp<Track>& track = tracksToRemove->itemAt(i);
1863 mActiveTracks.remove(track);
Eric Laurent65b65452010-06-01 23:49:17 -07001864 if (track->mainBuffer() != mMixBuffer) {
1865 chain = getEffectChain_l(track->sessionId());
1866 if (chain != 0) {
1867 LOGV("stopping track on chain %p for session Id: %d", chain.get(), track->sessionId());
1868 chain->stopTrack();
1869 }
1870 }
Eric Laurenta553c252009-07-17 12:17:14 -07001871 if (track->isTerminated()) {
1872 mTracks.remove(track);
1873 deleteTrackName_l(track->mName);
1874 }
1875 }
1876 }
1877
Eric Laurent65b65452010-06-01 23:49:17 -07001878 // mix buffer must be cleared if all tracks are connected to an
1879 // effect chain as in this case the mixer will not write to
1880 // mix buffer and track effects will accumulate into it
1881 if (mixedTracks != 0 && mixedTracks == tracksWithEffect) {
1882 memset(mMixBuffer, 0, mFrameCount * mChannelCount * sizeof(int16_t));
1883 }
1884
Eric Laurent059b4be2009-11-09 23:32:22 -08001885 return mixerStatus;
Eric Laurenta553c252009-07-17 12:17:14 -07001886}
1887
Eric Laurenteb8f850d2010-05-14 03:26:45 -07001888void AudioFlinger::MixerThread::invalidateTracks(int streamType)
Eric Laurenta553c252009-07-17 12:17:14 -07001889{
Eric Laurent8ed6ed02010-07-13 04:45:46 -07001890 LOGV ("MixerThread::invalidateTracks() mixer %p, streamType %d, mTracks.size %d",
1891 this, streamType, mTracks.size());
Eric Laurenta553c252009-07-17 12:17:14 -07001892 Mutex::Autolock _l(mLock);
Eric Laurent8ed6ed02010-07-13 04:45:46 -07001893
Eric Laurenta553c252009-07-17 12:17:14 -07001894 size_t size = mTracks.size();
1895 for (size_t i = 0; i < size; i++) {
1896 sp<Track> t = mTracks[i];
1897 if (t->type() == streamType) {
Eric Laurentae29b762011-03-28 18:37:07 -07001898 android_atomic_or(CBLK_INVALID_ON, &t->mCblk->flags);
Eric Laurenteb8f850d2010-05-14 03:26:45 -07001899 t->mCblk->cv.signal();
Eric Laurenta553c252009-07-17 12:17:14 -07001900 }
Eric Laurent53334cd2010-06-23 17:38:20 -07001901 }
1902}
Eric Laurenta553c252009-07-17 12:17:14 -07001903
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001904
Eric Laurenta553c252009-07-17 12:17:14 -07001905// getTrackName_l() must be called with ThreadBase::mLock held
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07001906int AudioFlinger::MixerThread::getTrackName_l()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001907{
1908 return mAudioMixer->getTrackName();
1909}
1910
Eric Laurenta553c252009-07-17 12:17:14 -07001911// deleteTrackName_l() must be called with ThreadBase::mLock held
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07001912void AudioFlinger::MixerThread::deleteTrackName_l(int name)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001913{
Eric Laurent0a080292009-12-07 10:53:10 -08001914 LOGV("remove track (%d) and delete from mixer", name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001915 mAudioMixer->deleteTrackName(name);
1916}
1917
Eric Laurenta553c252009-07-17 12:17:14 -07001918// checkForNewParameters_l() must be called with ThreadBase::mLock held
1919bool AudioFlinger::MixerThread::checkForNewParameters_l()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001920{
Eric Laurenta553c252009-07-17 12:17:14 -07001921 bool reconfig = false;
1922
Eric Laurent8fce46a2009-08-04 09:45:33 -07001923 while (!mNewParameters.isEmpty()) {
Eric Laurenta553c252009-07-17 12:17:14 -07001924 status_t status = NO_ERROR;
Eric Laurent8fce46a2009-08-04 09:45:33 -07001925 String8 keyValuePair = mNewParameters[0];
1926 AudioParameter param = AudioParameter(keyValuePair);
Eric Laurenta553c252009-07-17 12:17:14 -07001927 int value;
Eric Laurent8fce46a2009-08-04 09:45:33 -07001928
Eric Laurenta553c252009-07-17 12:17:14 -07001929 if (param.getInt(String8(AudioParameter::keySamplingRate), value) == NO_ERROR) {
1930 reconfig = true;
1931 }
1932 if (param.getInt(String8(AudioParameter::keyFormat), value) == NO_ERROR) {
Dima Zavin24fc2fb2011-04-19 22:30:36 -07001933 if (value != AUDIO_FORMAT_PCM_16_BIT) {
Eric Laurenta553c252009-07-17 12:17:14 -07001934 status = BAD_VALUE;
1935 } else {
1936 reconfig = true;
1937 }
1938 }
1939 if (param.getInt(String8(AudioParameter::keyChannels), value) == NO_ERROR) {
Dima Zavin24fc2fb2011-04-19 22:30:36 -07001940 if (value != AUDIO_CHANNEL_OUT_STEREO) {
Eric Laurenta553c252009-07-17 12:17:14 -07001941 status = BAD_VALUE;
1942 } else {
1943 reconfig = true;
1944 }
1945 }
1946 if (param.getInt(String8(AudioParameter::keyFrameCount), value) == NO_ERROR) {
1947 // do not accept frame count changes if tracks are open as the track buffer
1948 // size depends on frame count and correct behavior would not be garantied
1949 // if frame count is changed after track creation
1950 if (!mTracks.isEmpty()) {
1951 status = INVALID_OPERATION;
1952 } else {
1953 reconfig = true;
1954 }
1955 }
Eric Laurent65b65452010-06-01 23:49:17 -07001956 if (param.getInt(String8(AudioParameter::keyRouting), value) == NO_ERROR) {
Gloria Wang9b3f1522011-02-24 14:51:45 -08001957 // when changing the audio output device, call addBatteryData to notify
1958 // the change
1959 if (mDevice != value) {
1960 uint32_t params = 0;
1961 // check whether speaker is on
Dima Zavin24fc2fb2011-04-19 22:30:36 -07001962 if (value & AUDIO_DEVICE_OUT_SPEAKER) {
Gloria Wang9b3f1522011-02-24 14:51:45 -08001963 params |= IMediaPlayerService::kBatteryDataSpeakerOn;
1964 }
1965
1966 int deviceWithoutSpeaker
Dima Zavin24fc2fb2011-04-19 22:30:36 -07001967 = AUDIO_DEVICE_OUT_ALL & ~AUDIO_DEVICE_OUT_SPEAKER;
Gloria Wang9b3f1522011-02-24 14:51:45 -08001968 // check if any other device (except speaker) is on
1969 if (value & deviceWithoutSpeaker ) {
1970 params |= IMediaPlayerService::kBatteryDataOtherAudioDeviceOn;
1971 }
1972
1973 if (params != 0) {
1974 addBatteryData(params);
1975 }
1976 }
1977
Eric Laurent65b65452010-06-01 23:49:17 -07001978 // forward device change to effects that have requested to be
1979 // aware of attached audio device.
1980 mDevice = (uint32_t)value;
1981 for (size_t i = 0; i < mEffectChains.size(); i++) {
Eric Laurent76c40f72010-07-15 12:50:15 -07001982 mEffectChains[i]->setDevice_l(mDevice);
Eric Laurent65b65452010-06-01 23:49:17 -07001983 }
1984 }
1985
Eric Laurenta553c252009-07-17 12:17:14 -07001986 if (status == NO_ERROR) {
Dima Zavin31f188892011-04-18 16:57:27 -07001987 status = mOutput->stream->common.set_parameters(&mOutput->stream->common,
Dima Zavin24fc2fb2011-04-19 22:30:36 -07001988 keyValuePair.string());
Eric Laurenta553c252009-07-17 12:17:14 -07001989 if (!mStandby && status == INVALID_OPERATION) {
Dima Zavin31f188892011-04-18 16:57:27 -07001990 mOutput->stream->common.standby(&mOutput->stream->common);
Eric Laurenta553c252009-07-17 12:17:14 -07001991 mStandby = true;
1992 mBytesWritten = 0;
Dima Zavin31f188892011-04-18 16:57:27 -07001993 status = mOutput->stream->common.set_parameters(&mOutput->stream->common,
Dima Zavin24fc2fb2011-04-19 22:30:36 -07001994 keyValuePair.string());
Eric Laurenta553c252009-07-17 12:17:14 -07001995 }
1996 if (status == NO_ERROR && reconfig) {
1997 delete mAudioMixer;
1998 readOutputParameters();
1999 mAudioMixer = new AudioMixer(mFrameCount, mSampleRate);
2000 for (size_t i = 0; i < mTracks.size() ; i++) {
2001 int name = getTrackName_l();
2002 if (name < 0) break;
2003 mTracks[i]->mName = name;
Eric Laurent6f7e0972009-08-10 08:15:12 -07002004 // limit track sample rate to 2 x new output sample rate
2005 if (mTracks[i]->mCblk->sampleRate > 2 * sampleRate()) {
2006 mTracks[i]->mCblk->sampleRate = 2 * sampleRate();
2007 }
Eric Laurenta553c252009-07-17 12:17:14 -07002008 }
Eric Laurent8fce46a2009-08-04 09:45:33 -07002009 sendConfigEvent_l(AudioSystem::OUTPUT_CONFIG_CHANGED);
Eric Laurenta553c252009-07-17 12:17:14 -07002010 }
2011 }
Eric Laurent3fdb1262009-11-07 00:01:32 -08002012
2013 mNewParameters.removeAt(0);
2014
Eric Laurenta553c252009-07-17 12:17:14 -07002015 mParamStatus = status;
Eric Laurenta553c252009-07-17 12:17:14 -07002016 mParamCond.signal();
Eric Laurent8fce46a2009-08-04 09:45:33 -07002017 mWaitWorkCV.wait(mLock);
Eric Laurenta553c252009-07-17 12:17:14 -07002018 }
2019 return reconfig;
2020}
2021
2022status_t AudioFlinger::MixerThread::dumpInternals(int fd, const Vector<String16>& args)
2023{
2024 const size_t SIZE = 256;
2025 char buffer[SIZE];
2026 String8 result;
2027
2028 PlaybackThread::dumpInternals(fd, args);
2029
2030 snprintf(buffer, SIZE, "AudioMixer tracks: %08x\n", mAudioMixer->trackNames());
2031 result.append(buffer);
2032 write(fd, result.string(), result.size());
2033 return NO_ERROR;
2034}
2035
Eric Laurent059b4be2009-11-09 23:32:22 -08002036uint32_t AudioFlinger::MixerThread::activeSleepTimeUs()
Eric Laurent62443f52009-10-05 20:29:18 -07002037{
Dima Zavin31f188892011-04-18 16:57:27 -07002038 return (uint32_t)(mOutput->stream->get_latency(mOutput->stream) * 1000) / 2;
Eric Laurent059b4be2009-11-09 23:32:22 -08002039}
2040
2041uint32_t AudioFlinger::MixerThread::idleSleepTimeUs()
2042{
Eric Laurenta54d7d32010-07-29 06:50:24 -07002043 return (uint32_t)(((mFrameCount * 1000) / mSampleRate) * 1000) / 2;
Eric Laurent62443f52009-10-05 20:29:18 -07002044}
2045
Eric Laurent8448a792010-08-18 18:13:17 -07002046uint32_t AudioFlinger::MixerThread::suspendSleepTimeUs()
2047{
2048 return (uint32_t)(((mFrameCount * 1000) / mSampleRate) * 1000);
2049}
2050
Eric Laurenta553c252009-07-17 12:17:14 -07002051// ----------------------------------------------------------------------------
Dima Zavin31f188892011-04-18 16:57:27 -07002052AudioFlinger::DirectOutputThread::DirectOutputThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id, uint32_t device)
Eric Laurent65b65452010-06-01 23:49:17 -07002053 : PlaybackThread(audioFlinger, output, id, device)
Eric Laurenta553c252009-07-17 12:17:14 -07002054{
2055 mType = PlaybackThread::DIRECT;
2056}
2057
2058AudioFlinger::DirectOutputThread::~DirectOutputThread()
2059{
2060}
2061
2062
Eric Laurent65b65452010-06-01 23:49:17 -07002063static inline int16_t clamp16(int32_t sample)
2064{
2065 if ((sample>>15) ^ (sample>>31))
2066 sample = 0x7FFF ^ (sample>>31);
2067 return sample;
2068}
2069
2070static inline
2071int32_t mul(int16_t in, int16_t v)
2072{
2073#if defined(__arm__) && !defined(__thumb__)
2074 int32_t out;
2075 asm( "smulbb %[out], %[in], %[v] \n"
2076 : [out]"=r"(out)
2077 : [in]"%r"(in), [v]"r"(v)
2078 : );
2079 return out;
2080#else
2081 return in * int32_t(v);
2082#endif
2083}
2084
2085void AudioFlinger::DirectOutputThread::applyVolume(uint16_t leftVol, uint16_t rightVol, bool ramp)
2086{
2087 // Do not apply volume on compressed audio
Dima Zavin24fc2fb2011-04-19 22:30:36 -07002088 if (!audio_is_linear_pcm(mFormat)) {
Eric Laurent65b65452010-06-01 23:49:17 -07002089 return;
2090 }
2091
2092 // convert to signed 16 bit before volume calculation
Dima Zavin24fc2fb2011-04-19 22:30:36 -07002093 if (mFormat == AUDIO_FORMAT_PCM_8_BIT) {
Eric Laurent65b65452010-06-01 23:49:17 -07002094 size_t count = mFrameCount * mChannelCount;
2095 uint8_t *src = (uint8_t *)mMixBuffer + count-1;
2096 int16_t *dst = mMixBuffer + count-1;
2097 while(count--) {
2098 *dst-- = (int16_t)(*src--^0x80) << 8;
2099 }
2100 }
2101
2102 size_t frameCount = mFrameCount;
2103 int16_t *out = mMixBuffer;
2104 if (ramp) {
2105 if (mChannelCount == 1) {
2106 int32_t d = ((int32_t)leftVol - (int32_t)mLeftVolShort) << 16;
2107 int32_t vlInc = d / (int32_t)frameCount;
2108 int32_t vl = ((int32_t)mLeftVolShort << 16);
2109 do {
2110 out[0] = clamp16(mul(out[0], vl >> 16) >> 12);
2111 out++;
2112 vl += vlInc;
2113 } while (--frameCount);
2114
2115 } else {
2116 int32_t d = ((int32_t)leftVol - (int32_t)mLeftVolShort) << 16;
2117 int32_t vlInc = d / (int32_t)frameCount;
2118 d = ((int32_t)rightVol - (int32_t)mRightVolShort) << 16;
2119 int32_t vrInc = d / (int32_t)frameCount;
2120 int32_t vl = ((int32_t)mLeftVolShort << 16);
2121 int32_t vr = ((int32_t)mRightVolShort << 16);
2122 do {
2123 out[0] = clamp16(mul(out[0], vl >> 16) >> 12);
2124 out[1] = clamp16(mul(out[1], vr >> 16) >> 12);
2125 out += 2;
2126 vl += vlInc;
2127 vr += vrInc;
2128 } while (--frameCount);
2129 }
2130 } else {
2131 if (mChannelCount == 1) {
2132 do {
2133 out[0] = clamp16(mul(out[0], leftVol) >> 12);
2134 out++;
2135 } while (--frameCount);
2136 } else {
2137 do {
2138 out[0] = clamp16(mul(out[0], leftVol) >> 12);
2139 out[1] = clamp16(mul(out[1], rightVol) >> 12);
2140 out += 2;
2141 } while (--frameCount);
2142 }
2143 }
2144
2145 // convert back to unsigned 8 bit after volume calculation
Dima Zavin24fc2fb2011-04-19 22:30:36 -07002146 if (mFormat == AUDIO_FORMAT_PCM_8_BIT) {
Eric Laurent65b65452010-06-01 23:49:17 -07002147 size_t count = mFrameCount * mChannelCount;
2148 int16_t *src = mMixBuffer;
2149 uint8_t *dst = (uint8_t *)mMixBuffer;
2150 while(count--) {
2151 *dst++ = (uint8_t)(((int32_t)*src++ + (1<<7)) >> 8)^0x80;
2152 }
2153 }
2154
2155 mLeftVolShort = leftVol;
2156 mRightVolShort = rightVol;
2157}
2158
Eric Laurenta553c252009-07-17 12:17:14 -07002159bool AudioFlinger::DirectOutputThread::threadLoop()
2160{
Eric Laurent059b4be2009-11-09 23:32:22 -08002161 uint32_t mixerStatus = MIXER_IDLE;
Eric Laurenta553c252009-07-17 12:17:14 -07002162 sp<Track> trackToRemove;
2163 sp<Track> activeTrack;
2164 nsecs_t standbyTime = systemTime();
2165 int8_t *curBuf;
2166 size_t mixBufferSize = mFrameCount*mFrameSize;
Eric Laurent059b4be2009-11-09 23:32:22 -08002167 uint32_t activeSleepTime = activeSleepTimeUs();
2168 uint32_t idleSleepTime = idleSleepTimeUs();
2169 uint32_t sleepTime = idleSleepTime;
Eric Laurentef9500f2010-03-11 14:47:00 -08002170 // use shorter standby delay as on normal output to release
2171 // hardware resources as soon as possible
2172 nsecs_t standbyDelay = microseconds(activeSleepTime*2);
Eric Laurent059b4be2009-11-09 23:32:22 -08002173
Eric Laurenta553c252009-07-17 12:17:14 -07002174 while (!exitPending())
2175 {
Eric Laurent65b65452010-06-01 23:49:17 -07002176 bool rampVolume;
2177 uint16_t leftVol;
2178 uint16_t rightVol;
2179 Vector< sp<EffectChain> > effectChains;
2180
Eric Laurenta553c252009-07-17 12:17:14 -07002181 processConfigEvents();
2182
Eric Laurent059b4be2009-11-09 23:32:22 -08002183 mixerStatus = MIXER_IDLE;
2184
Eric Laurenta553c252009-07-17 12:17:14 -07002185 { // scope for the mLock
2186
2187 Mutex::Autolock _l(mLock);
2188
2189 if (checkForNewParameters_l()) {
2190 mixBufferSize = mFrameCount*mFrameSize;
Eric Laurent059b4be2009-11-09 23:32:22 -08002191 activeSleepTime = activeSleepTimeUs();
2192 idleSleepTime = idleSleepTimeUs();
Eric Laurentef9500f2010-03-11 14:47:00 -08002193 standbyDelay = microseconds(activeSleepTime*2);
Eric Laurenta553c252009-07-17 12:17:14 -07002194 }
2195
2196 // put audio hardware into standby after short delay
2197 if UNLIKELY((!mActiveTracks.size() && systemTime() > standbyTime) ||
2198 mSuspended) {
2199 // wait until we have something to do...
2200 if (!mStandby) {
2201 LOGV("Audio hardware entering standby, mixer %p\n", this);
Dima Zavin31f188892011-04-18 16:57:27 -07002202 mOutput->stream->common.standby(&mOutput->stream->common);
Eric Laurenta553c252009-07-17 12:17:14 -07002203 mStandby = true;
2204 mBytesWritten = 0;
2205 }
2206
2207 if (!mActiveTracks.size() && mConfigEvents.isEmpty()) {
2208 // we're about to wait, flush the binder command buffer
2209 IPCThreadState::self()->flushCommands();
2210
2211 if (exitPending()) break;
2212
2213 LOGV("DirectOutputThread %p TID %d going to sleep\n", this, gettid());
2214 mWaitWorkCV.wait(mLock);
2215 LOGV("DirectOutputThread %p TID %d waking up in active mode\n", this, gettid());
2216
2217 if (mMasterMute == false) {
2218 char value[PROPERTY_VALUE_MAX];
2219 property_get("ro.audio.silent", value, "0");
2220 if (atoi(value)) {
2221 LOGD("Silence is golden");
2222 setMasterMute(true);
2223 }
2224 }
2225
Eric Laurentef9500f2010-03-11 14:47:00 -08002226 standbyTime = systemTime() + standbyDelay;
Eric Laurent059b4be2009-11-09 23:32:22 -08002227 sleepTime = idleSleepTime;
Eric Laurenta553c252009-07-17 12:17:14 -07002228 continue;
2229 }
2230 }
2231
Eric Laurent65b65452010-06-01 23:49:17 -07002232 effectChains = mEffectChains;
2233
Eric Laurenta553c252009-07-17 12:17:14 -07002234 // find out which tracks need to be processed
2235 if (mActiveTracks.size() != 0) {
2236 sp<Track> t = mActiveTracks[0].promote();
2237 if (t == 0) continue;
2238
2239 Track* const track = t.get();
2240 audio_track_cblk_t* cblk = track->cblk();
2241
2242 // The first time a track is added we wait
2243 // for all its buffers to be filled before processing it
Eric Laurent9a30fc12010-10-05 14:41:42 -07002244 if (cblk->framesReady() && track->isReady() &&
Eric Laurent380558b2010-04-09 06:11:48 -07002245 !track->isPaused() && !track->isTerminated())
Eric Laurenta553c252009-07-17 12:17:14 -07002246 {
2247 //LOGV("track %d u=%08x, s=%08x [OK]", track->name(), cblk->user, cblk->server);
2248
Eric Laurent65b65452010-06-01 23:49:17 -07002249 if (track->mFillingUpStatus == Track::FS_FILLED) {
2250 track->mFillingUpStatus = Track::FS_ACTIVE;
2251 mLeftVolFloat = mRightVolFloat = 0;
2252 mLeftVolShort = mRightVolShort = 0;
2253 if (track->mState == TrackBase::RESUMING) {
2254 track->mState = TrackBase::ACTIVE;
2255 rampVolume = true;
2256 }
2257 } else if (cblk->server != 0) {
2258 // If the track is stopped before the first frame was mixed,
2259 // do not apply ramp
2260 rampVolume = true;
2261 }
Eric Laurenta553c252009-07-17 12:17:14 -07002262 // compute volume for this track
2263 float left, right;
2264 if (track->isMuted() || mMasterMute || track->isPausing() ||
2265 mStreamTypes[track->type()].mute) {
2266 left = right = 0;
2267 if (track->isPausing()) {
2268 track->setPaused();
2269 }
2270 } else {
2271 float typeVolume = mStreamTypes[track->type()].volume;
2272 float v = mMasterVolume * typeVolume;
2273 float v_clamped = v * cblk->volume[0];
2274 if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN;
2275 left = v_clamped/MAX_GAIN;
2276 v_clamped = v * cblk->volume[1];
2277 if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN;
2278 right = v_clamped/MAX_GAIN;
2279 }
2280
Eric Laurent65b65452010-06-01 23:49:17 -07002281 if (left != mLeftVolFloat || right != mRightVolFloat) {
2282 mLeftVolFloat = left;
2283 mRightVolFloat = right;
Eric Laurenta553c252009-07-17 12:17:14 -07002284
Eric Laurent65b65452010-06-01 23:49:17 -07002285 // If audio HAL implements volume control,
2286 // force software volume to nominal value
Dima Zavin31f188892011-04-18 16:57:27 -07002287 if (mOutput->stream->set_volume(mOutput->stream, left, right) == NO_ERROR) {
Eric Laurent65b65452010-06-01 23:49:17 -07002288 left = 1.0f;
2289 right = 1.0f;
Eric Laurenta553c252009-07-17 12:17:14 -07002290 }
Eric Laurent65b65452010-06-01 23:49:17 -07002291
2292 // Convert volumes from float to 8.24
2293 uint32_t vl = (uint32_t)(left * (1 << 24));
2294 uint32_t vr = (uint32_t)(right * (1 << 24));
2295
2296 // Delegate volume control to effect in track effect chain if needed
2297 // only one effect chain can be present on DirectOutputThread, so if
2298 // there is one, the track is connected to it
2299 if (!effectChains.isEmpty()) {
Eric Laurent27a2fdf2010-09-10 17:44:44 -07002300 // Do not ramp volume if volume is controlled by effect
Eric Laurent76c40f72010-07-15 12:50:15 -07002301 if(effectChains[0]->setVolume_l(&vl, &vr)) {
Eric Laurent65b65452010-06-01 23:49:17 -07002302 rampVolume = false;
2303 }
2304 }
2305
2306 // Convert volumes from 8.24 to 4.12 format
2307 uint32_t v_clamped = (vl + (1 << 11)) >> 12;
2308 if (v_clamped > MAX_GAIN_INT) v_clamped = MAX_GAIN_INT;
2309 leftVol = (uint16_t)v_clamped;
2310 v_clamped = (vr + (1 << 11)) >> 12;
2311 if (v_clamped > MAX_GAIN_INT) v_clamped = MAX_GAIN_INT;
2312 rightVol = (uint16_t)v_clamped;
2313 } else {
2314 leftVol = mLeftVolShort;
2315 rightVol = mRightVolShort;
2316 rampVolume = false;
Eric Laurenta553c252009-07-17 12:17:14 -07002317 }
2318
2319 // reset retry count
Eric Laurentef9500f2010-03-11 14:47:00 -08002320 track->mRetryCount = kMaxTrackRetriesDirect;
Eric Laurenta553c252009-07-17 12:17:14 -07002321 activeTrack = t;
Eric Laurent059b4be2009-11-09 23:32:22 -08002322 mixerStatus = MIXER_TRACKS_READY;
Eric Laurenta553c252009-07-17 12:17:14 -07002323 } else {
2324 //LOGV("track %d u=%08x, s=%08x [NOT READY]", track->name(), cblk->user, cblk->server);
2325 if (track->isStopped()) {
2326 track->reset();
2327 }
2328 if (track->isTerminated() || track->isStopped() || track->isPaused()) {
2329 // We have consumed all the buffers of this track.
2330 // Remove it from the list of active tracks.
2331 trackToRemove = track;
2332 } else {
2333 // No buffers for this track. Give it a few chances to
2334 // fill a buffer, then remove it from active list.
2335 if (--(track->mRetryCount) <= 0) {
2336 LOGV("BUFFER TIMEOUT: remove(%d) from active list", track->name());
2337 trackToRemove = track;
Eric Laurent059b4be2009-11-09 23:32:22 -08002338 } else {
2339 mixerStatus = MIXER_TRACKS_ENABLED;
Eric Laurenta553c252009-07-17 12:17:14 -07002340 }
Eric Laurent059b4be2009-11-09 23:32:22 -08002341 }
Eric Laurenta553c252009-07-17 12:17:14 -07002342 }
2343 }
2344
2345 // remove all the tracks that need to be...
2346 if (UNLIKELY(trackToRemove != 0)) {
2347 mActiveTracks.remove(trackToRemove);
Eric Laurent65b65452010-06-01 23:49:17 -07002348 if (!effectChains.isEmpty()) {
Eric Laurent8ed6ed02010-07-13 04:45:46 -07002349 LOGV("stopping track on chain %p for session Id: %d", effectChains[0].get(),
2350 trackToRemove->sessionId());
Eric Laurent65b65452010-06-01 23:49:17 -07002351 effectChains[0]->stopTrack();
2352 }
Eric Laurenta553c252009-07-17 12:17:14 -07002353 if (trackToRemove->isTerminated()) {
2354 mTracks.remove(trackToRemove);
2355 deleteTrackName_l(trackToRemove->mName);
2356 }
2357 }
Eric Laurent65b65452010-06-01 23:49:17 -07002358
Eric Laurent8ed6ed02010-07-13 04:45:46 -07002359 lockEffectChains_l(effectChains);
Eric Laurenta553c252009-07-17 12:17:14 -07002360 }
2361
Eric Laurent059b4be2009-11-09 23:32:22 -08002362 if (LIKELY(mixerStatus == MIXER_TRACKS_READY)) {
Eric Laurentf69a3f82009-09-22 00:35:48 -07002363 AudioBufferProvider::Buffer buffer;
2364 size_t frameCount = mFrameCount;
2365 curBuf = (int8_t *)mMixBuffer;
2366 // output audio to hardware
Eric Laurent65b65452010-06-01 23:49:17 -07002367 while (frameCount) {
Eric Laurentf69a3f82009-09-22 00:35:48 -07002368 buffer.frameCount = frameCount;
2369 activeTrack->getNextBuffer(&buffer);
2370 if (UNLIKELY(buffer.raw == 0)) {
2371 memset(curBuf, 0, frameCount * mFrameSize);
2372 break;
2373 }
2374 memcpy(curBuf, buffer.raw, buffer.frameCount * mFrameSize);
2375 frameCount -= buffer.frameCount;
2376 curBuf += buffer.frameCount * mFrameSize;
2377 activeTrack->releaseBuffer(&buffer);
2378 }
2379 sleepTime = 0;
Eric Laurentef9500f2010-03-11 14:47:00 -08002380 standbyTime = systemTime() + standbyDelay;
Eric Laurent96c08a62009-09-07 08:38:38 -07002381 } else {
Eric Laurent62443f52009-10-05 20:29:18 -07002382 if (sleepTime == 0) {
Eric Laurent059b4be2009-11-09 23:32:22 -08002383 if (mixerStatus == MIXER_TRACKS_ENABLED) {
2384 sleepTime = activeSleepTime;
2385 } else {
2386 sleepTime = idleSleepTime;
2387 }
Dima Zavin24fc2fb2011-04-19 22:30:36 -07002388 } else if (mBytesWritten != 0 && audio_is_linear_pcm(mFormat)) {
Eric Laurentf69a3f82009-09-22 00:35:48 -07002389 memset (mMixBuffer, 0, mFrameCount * mFrameSize);
Eric Laurent96c08a62009-09-07 08:38:38 -07002390 sleepTime = 0;
Eric Laurent96c08a62009-09-07 08:38:38 -07002391 }
Eric Laurentf69a3f82009-09-22 00:35:48 -07002392 }
Eric Laurent96c08a62009-09-07 08:38:38 -07002393
Eric Laurentf69a3f82009-09-22 00:35:48 -07002394 if (mSuspended) {
Eric Laurent8448a792010-08-18 18:13:17 -07002395 sleepTime = suspendSleepTimeUs();
Eric Laurentf69a3f82009-09-22 00:35:48 -07002396 }
2397 // sleepTime == 0 means we must write to audio hardware
2398 if (sleepTime == 0) {
Eric Laurent65b65452010-06-01 23:49:17 -07002399 if (mixerStatus == MIXER_TRACKS_READY) {
2400 applyVolume(leftVol, rightVol, rampVolume);
2401 }
2402 for (size_t i = 0; i < effectChains.size(); i ++) {
2403 effectChains[i]->process_l();
2404 }
Eric Laurent8ed6ed02010-07-13 04:45:46 -07002405 unlockEffectChains(effectChains);
Eric Laurent65b65452010-06-01 23:49:17 -07002406
Eric Laurentf69a3f82009-09-22 00:35:48 -07002407 mLastWriteTime = systemTime();
2408 mInWrite = true;
Eric Laurent0986e792010-01-19 17:37:09 -08002409 mBytesWritten += mixBufferSize;
Dima Zavin31f188892011-04-18 16:57:27 -07002410 int bytesWritten = (int)mOutput->stream->write(mOutput->stream, mMixBuffer, mixBufferSize);
Eric Laurent0986e792010-01-19 17:37:09 -08002411 if (bytesWritten < 0) mBytesWritten -= mixBufferSize;
Eric Laurentf69a3f82009-09-22 00:35:48 -07002412 mNumWrites++;
2413 mInWrite = false;
2414 mStandby = false;
2415 } else {
Eric Laurent8ed6ed02010-07-13 04:45:46 -07002416 unlockEffectChains(effectChains);
Eric Laurentf69a3f82009-09-22 00:35:48 -07002417 usleep(sleepTime);
Eric Laurenta553c252009-07-17 12:17:14 -07002418 }
2419
2420 // finally let go of removed track, without the lock held
2421 // since we can't guarantee the destructors won't acquire that
2422 // same lock.
2423 trackToRemove.clear();
2424 activeTrack.clear();
Eric Laurent65b65452010-06-01 23:49:17 -07002425
2426 // Effect chains will be actually deleted here if they were removed from
2427 // mEffectChains list during mixing or effects processing
2428 effectChains.clear();
Eric Laurenta553c252009-07-17 12:17:14 -07002429 }
2430
2431 if (!mStandby) {
Dima Zavin31f188892011-04-18 16:57:27 -07002432 mOutput->stream->common.standby(&mOutput->stream->common);
Eric Laurenta553c252009-07-17 12:17:14 -07002433 }
Eric Laurenta553c252009-07-17 12:17:14 -07002434
2435 LOGV("DirectOutputThread %p exiting", this);
2436 return false;
2437}
2438
2439// getTrackName_l() must be called with ThreadBase::mLock held
2440int AudioFlinger::DirectOutputThread::getTrackName_l()
2441{
2442 return 0;
2443}
2444
2445// deleteTrackName_l() must be called with ThreadBase::mLock held
2446void AudioFlinger::DirectOutputThread::deleteTrackName_l(int name)
2447{
2448}
2449
2450// checkForNewParameters_l() must be called with ThreadBase::mLock held
2451bool AudioFlinger::DirectOutputThread::checkForNewParameters_l()
2452{
2453 bool reconfig = false;
2454
Eric Laurent8fce46a2009-08-04 09:45:33 -07002455 while (!mNewParameters.isEmpty()) {
Eric Laurenta553c252009-07-17 12:17:14 -07002456 status_t status = NO_ERROR;
Eric Laurent8fce46a2009-08-04 09:45:33 -07002457 String8 keyValuePair = mNewParameters[0];
2458 AudioParameter param = AudioParameter(keyValuePair);
Eric Laurenta553c252009-07-17 12:17:14 -07002459 int value;
Eric Laurent8fce46a2009-08-04 09:45:33 -07002460
Eric Laurenta553c252009-07-17 12:17:14 -07002461 if (param.getInt(String8(AudioParameter::keyFrameCount), value) == NO_ERROR) {
2462 // do not accept frame count changes if tracks are open as the track buffer
2463 // size depends on frame count and correct behavior would not be garantied
2464 // if frame count is changed after track creation
2465 if (!mTracks.isEmpty()) {
2466 status = INVALID_OPERATION;
2467 } else {
2468 reconfig = true;
2469 }
2470 }
2471 if (status == NO_ERROR) {
Dima Zavin31f188892011-04-18 16:57:27 -07002472 status = mOutput->stream->common.set_parameters(&mOutput->stream->common,
Dima Zavin24fc2fb2011-04-19 22:30:36 -07002473 keyValuePair.string());
Eric Laurenta553c252009-07-17 12:17:14 -07002474 if (!mStandby && status == INVALID_OPERATION) {
Dima Zavin31f188892011-04-18 16:57:27 -07002475 mOutput->stream->common.standby(&mOutput->stream->common);
Eric Laurenta553c252009-07-17 12:17:14 -07002476 mStandby = true;
2477 mBytesWritten = 0;
Dima Zavin31f188892011-04-18 16:57:27 -07002478 status = mOutput->stream->common.set_parameters(&mOutput->stream->common,
Dima Zavin24fc2fb2011-04-19 22:30:36 -07002479 keyValuePair.string());
Eric Laurenta553c252009-07-17 12:17:14 -07002480 }
2481 if (status == NO_ERROR && reconfig) {
2482 readOutputParameters();
Eric Laurent8fce46a2009-08-04 09:45:33 -07002483 sendConfigEvent_l(AudioSystem::OUTPUT_CONFIG_CHANGED);
Eric Laurenta553c252009-07-17 12:17:14 -07002484 }
2485 }
Eric Laurent3fdb1262009-11-07 00:01:32 -08002486
2487 mNewParameters.removeAt(0);
2488
Eric Laurenta553c252009-07-17 12:17:14 -07002489 mParamStatus = status;
Eric Laurenta553c252009-07-17 12:17:14 -07002490 mParamCond.signal();
Eric Laurent8fce46a2009-08-04 09:45:33 -07002491 mWaitWorkCV.wait(mLock);
Eric Laurenta553c252009-07-17 12:17:14 -07002492 }
2493 return reconfig;
The Android Open Source Projectf1e484a2009-01-22 00:13:42 -08002494}
2495
Eric Laurent059b4be2009-11-09 23:32:22 -08002496uint32_t AudioFlinger::DirectOutputThread::activeSleepTimeUs()
Eric Laurent62443f52009-10-05 20:29:18 -07002497{
2498 uint32_t time;
Dima Zavin24fc2fb2011-04-19 22:30:36 -07002499 if (audio_is_linear_pcm(mFormat)) {
Dima Zavin31f188892011-04-18 16:57:27 -07002500 time = (uint32_t)(mOutput->stream->get_latency(mOutput->stream) * 1000) / 2;
Eric Laurent059b4be2009-11-09 23:32:22 -08002501 } else {
2502 time = 10000;
2503 }
2504 return time;
2505}
2506
2507uint32_t AudioFlinger::DirectOutputThread::idleSleepTimeUs()
2508{
2509 uint32_t time;
Dima Zavin24fc2fb2011-04-19 22:30:36 -07002510 if (audio_is_linear_pcm(mFormat)) {
Eric Laurenta54d7d32010-07-29 06:50:24 -07002511 time = (uint32_t)(((mFrameCount * 1000) / mSampleRate) * 1000) / 2;
Eric Laurent62443f52009-10-05 20:29:18 -07002512 } else {
2513 time = 10000;
2514 }
2515 return time;
2516}
2517
Eric Laurent8448a792010-08-18 18:13:17 -07002518uint32_t AudioFlinger::DirectOutputThread::suspendSleepTimeUs()
2519{
2520 uint32_t time;
Dima Zavin24fc2fb2011-04-19 22:30:36 -07002521 if (audio_is_linear_pcm(mFormat)) {
Eric Laurent8448a792010-08-18 18:13:17 -07002522 time = (uint32_t)(((mFrameCount * 1000) / mSampleRate) * 1000);
2523 } else {
2524 time = 10000;
2525 }
2526 return time;
2527}
2528
2529
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002530// ----------------------------------------------------------------------------
2531
Eric Laurent49f02be2009-11-19 09:00:56 -08002532AudioFlinger::DuplicatingThread::DuplicatingThread(const sp<AudioFlinger>& audioFlinger, AudioFlinger::MixerThread* mainThread, int id)
Eric Laurent65b65452010-06-01 23:49:17 -07002533 : MixerThread(audioFlinger, mainThread->getOutput(), id, mainThread->device()), mWaitTimeMs(UINT_MAX)
Eric Laurenta553c252009-07-17 12:17:14 -07002534{
2535 mType = PlaybackThread::DUPLICATING;
2536 addOutputTrack(mainThread);
2537}
2538
2539AudioFlinger::DuplicatingThread::~DuplicatingThread()
2540{
Eric Laurent0a080292009-12-07 10:53:10 -08002541 for (size_t i = 0; i < mOutputTracks.size(); i++) {
2542 mOutputTracks[i]->destroy();
2543 }
Eric Laurenta553c252009-07-17 12:17:14 -07002544 mOutputTracks.clear();
2545}
2546
2547bool AudioFlinger::DuplicatingThread::threadLoop()
2548{
Eric Laurenta553c252009-07-17 12:17:14 -07002549 Vector< sp<Track> > tracksToRemove;
Eric Laurent059b4be2009-11-09 23:32:22 -08002550 uint32_t mixerStatus = MIXER_IDLE;
Eric Laurenta553c252009-07-17 12:17:14 -07002551 nsecs_t standbyTime = systemTime();
2552 size_t mixBufferSize = mFrameCount*mFrameSize;
2553 SortedVector< sp<OutputTrack> > outputTracks;
Eric Laurent62443f52009-10-05 20:29:18 -07002554 uint32_t writeFrames = 0;
Eric Laurent059b4be2009-11-09 23:32:22 -08002555 uint32_t activeSleepTime = activeSleepTimeUs();
2556 uint32_t idleSleepTime = idleSleepTimeUs();
2557 uint32_t sleepTime = idleSleepTime;
Eric Laurent65b65452010-06-01 23:49:17 -07002558 Vector< sp<EffectChain> > effectChains;
Eric Laurenta553c252009-07-17 12:17:14 -07002559
2560 while (!exitPending())
2561 {
2562 processConfigEvents();
2563
Eric Laurent059b4be2009-11-09 23:32:22 -08002564 mixerStatus = MIXER_IDLE;
Eric Laurenta553c252009-07-17 12:17:14 -07002565 { // scope for the mLock
2566
2567 Mutex::Autolock _l(mLock);
2568
2569 if (checkForNewParameters_l()) {
2570 mixBufferSize = mFrameCount*mFrameSize;
Eric Laurent8ac9f8d2009-12-18 05:47:48 -08002571 updateWaitTime();
Eric Laurent059b4be2009-11-09 23:32:22 -08002572 activeSleepTime = activeSleepTimeUs();
2573 idleSleepTime = idleSleepTimeUs();
Eric Laurenta553c252009-07-17 12:17:14 -07002574 }
2575
2576 const SortedVector< wp<Track> >& activeTracks = mActiveTracks;
2577
2578 for (size_t i = 0; i < mOutputTracks.size(); i++) {
2579 outputTracks.add(mOutputTracks[i]);
2580 }
2581
2582 // put audio hardware into standby after short delay
2583 if UNLIKELY((!activeTracks.size() && systemTime() > standbyTime) ||
2584 mSuspended) {
2585 if (!mStandby) {
2586 for (size_t i = 0; i < outputTracks.size(); i++) {
Eric Laurenta553c252009-07-17 12:17:14 -07002587 outputTracks[i]->stop();
Eric Laurenta553c252009-07-17 12:17:14 -07002588 }
2589 mStandby = true;
2590 mBytesWritten = 0;
2591 }
2592
2593 if (!activeTracks.size() && mConfigEvents.isEmpty()) {
2594 // we're about to wait, flush the binder command buffer
2595 IPCThreadState::self()->flushCommands();
2596 outputTracks.clear();
2597
2598 if (exitPending()) break;
2599
2600 LOGV("DuplicatingThread %p TID %d going to sleep\n", this, gettid());
2601 mWaitWorkCV.wait(mLock);
2602 LOGV("DuplicatingThread %p TID %d waking up\n", this, gettid());
2603 if (mMasterMute == false) {
2604 char value[PROPERTY_VALUE_MAX];
2605 property_get("ro.audio.silent", value, "0");
2606 if (atoi(value)) {
2607 LOGD("Silence is golden");
2608 setMasterMute(true);
2609 }
2610 }
2611
2612 standbyTime = systemTime() + kStandbyTimeInNsecs;
Eric Laurent059b4be2009-11-09 23:32:22 -08002613 sleepTime = idleSleepTime;
Eric Laurenta553c252009-07-17 12:17:14 -07002614 continue;
2615 }
2616 }
2617
Eric Laurent059b4be2009-11-09 23:32:22 -08002618 mixerStatus = prepareTracks_l(activeTracks, &tracksToRemove);
Eric Laurent65b65452010-06-01 23:49:17 -07002619
2620 // prevent any changes in effect chain list and in each effect chain
2621 // during mixing and effect process as the audio buffers could be deleted
2622 // or modified if an effect is created or deleted
Eric Laurent8ed6ed02010-07-13 04:45:46 -07002623 lockEffectChains_l(effectChains);
Eric Laurentf69a3f82009-09-22 00:35:48 -07002624 }
Eric Laurenta553c252009-07-17 12:17:14 -07002625
Eric Laurent059b4be2009-11-09 23:32:22 -08002626 if (LIKELY(mixerStatus == MIXER_TRACKS_READY)) {
Eric Laurenta553c252009-07-17 12:17:14 -07002627 // mix buffers...
Eric Laurent8ac9f8d2009-12-18 05:47:48 -08002628 if (outputsReady(outputTracks)) {
Eric Laurent65b65452010-06-01 23:49:17 -07002629 mAudioMixer->process();
Eric Laurent8ac9f8d2009-12-18 05:47:48 -08002630 } else {
Eric Laurent65b65452010-06-01 23:49:17 -07002631 memset(mMixBuffer, 0, mixBufferSize);
Eric Laurent8ac9f8d2009-12-18 05:47:48 -08002632 }
Eric Laurentf69a3f82009-09-22 00:35:48 -07002633 sleepTime = 0;
Eric Laurent62443f52009-10-05 20:29:18 -07002634 writeFrames = mFrameCount;
Eric Laurenta553c252009-07-17 12:17:14 -07002635 } else {
Eric Laurent62443f52009-10-05 20:29:18 -07002636 if (sleepTime == 0) {
Eric Laurent059b4be2009-11-09 23:32:22 -08002637 if (mixerStatus == MIXER_TRACKS_ENABLED) {
2638 sleepTime = activeSleepTime;
2639 } else {
2640 sleepTime = idleSleepTime;
2641 }
Eric Laurent62443f52009-10-05 20:29:18 -07002642 } else if (mBytesWritten != 0) {
2643 // flush remaining overflow buffers in output tracks
2644 for (size_t i = 0; i < outputTracks.size(); i++) {
2645 if (outputTracks[i]->isActive()) {
2646 sleepTime = 0;
2647 writeFrames = 0;
Eric Laurent65b65452010-06-01 23:49:17 -07002648 memset(mMixBuffer, 0, mixBufferSize);
Eric Laurent62443f52009-10-05 20:29:18 -07002649 break;
2650 }
2651 }
Eric Laurenta553c252009-07-17 12:17:14 -07002652 }
2653 }
Eric Laurentf69a3f82009-09-22 00:35:48 -07002654
2655 if (mSuspended) {
Eric Laurent8448a792010-08-18 18:13:17 -07002656 sleepTime = suspendSleepTimeUs();
Eric Laurentf69a3f82009-09-22 00:35:48 -07002657 }
2658 // sleepTime == 0 means we must write to audio hardware
2659 if (sleepTime == 0) {
Eric Laurent65b65452010-06-01 23:49:17 -07002660 for (size_t i = 0; i < effectChains.size(); i ++) {
2661 effectChains[i]->process_l();
2662 }
2663 // enable changes in effect chain
Eric Laurent8ed6ed02010-07-13 04:45:46 -07002664 unlockEffectChains(effectChains);
Eric Laurent65b65452010-06-01 23:49:17 -07002665
Eric Laurent62443f52009-10-05 20:29:18 -07002666 standbyTime = systemTime() + kStandbyTimeInNsecs;
Eric Laurentf69a3f82009-09-22 00:35:48 -07002667 for (size_t i = 0; i < outputTracks.size(); i++) {
Eric Laurent65b65452010-06-01 23:49:17 -07002668 outputTracks[i]->write(mMixBuffer, writeFrames);
Eric Laurenta553c252009-07-17 12:17:14 -07002669 }
Eric Laurentf69a3f82009-09-22 00:35:48 -07002670 mStandby = false;
2671 mBytesWritten += mixBufferSize;
Eric Laurenta553c252009-07-17 12:17:14 -07002672 } else {
Eric Laurent65b65452010-06-01 23:49:17 -07002673 // enable changes in effect chain
Eric Laurent8ed6ed02010-07-13 04:45:46 -07002674 unlockEffectChains(effectChains);
Eric Laurentf69a3f82009-09-22 00:35:48 -07002675 usleep(sleepTime);
Eric Laurenta553c252009-07-17 12:17:14 -07002676 }
2677
2678 // finally let go of all our tracks, without the lock held
2679 // since we can't guarantee the destructors won't acquire that
2680 // same lock.
2681 tracksToRemove.clear();
2682 outputTracks.clear();
Eric Laurent65b65452010-06-01 23:49:17 -07002683
2684 // Effect chains will be actually deleted here if they were removed from
2685 // mEffectChains list during mixing or effects processing
2686 effectChains.clear();
Eric Laurenta553c252009-07-17 12:17:14 -07002687 }
2688
Eric Laurenta553c252009-07-17 12:17:14 -07002689 return false;
2690}
2691
2692void AudioFlinger::DuplicatingThread::addOutputTrack(MixerThread *thread)
2693{
2694 int frameCount = (3 * mFrameCount * mSampleRate) / thread->sampleRate();
2695 OutputTrack *outputTrack = new OutputTrack((ThreadBase *)thread,
Eric Laurent8ac9f8d2009-12-18 05:47:48 -08002696 this,
Eric Laurenta553c252009-07-17 12:17:14 -07002697 mSampleRate,
2698 mFormat,
2699 mChannelCount,
2700 frameCount);
Eric Laurent6c30a712009-08-10 23:22:32 -07002701 if (outputTrack->cblk() != NULL) {
Dima Zavin24fc2fb2011-04-19 22:30:36 -07002702 thread->setStreamVolume(AUDIO_STREAM_CNT, 1.0f);
Eric Laurent6c30a712009-08-10 23:22:32 -07002703 mOutputTracks.add(outputTrack);
2704 LOGV("addOutputTrack() track %p, on thread %p", outputTrack, thread);
Eric Laurent8ac9f8d2009-12-18 05:47:48 -08002705 updateWaitTime();
Eric Laurent6c30a712009-08-10 23:22:32 -07002706 }
Eric Laurenta553c252009-07-17 12:17:14 -07002707}
2708
2709void AudioFlinger::DuplicatingThread::removeOutputTrack(MixerThread *thread)
2710{
2711 Mutex::Autolock _l(mLock);
2712 for (size_t i = 0; i < mOutputTracks.size(); i++) {
2713 if (mOutputTracks[i]->thread() == (ThreadBase *)thread) {
Eric Laurent6c30a712009-08-10 23:22:32 -07002714 mOutputTracks[i]->destroy();
Eric Laurenta553c252009-07-17 12:17:14 -07002715 mOutputTracks.removeAt(i);
Eric Laurent8ac9f8d2009-12-18 05:47:48 -08002716 updateWaitTime();
Eric Laurenta553c252009-07-17 12:17:14 -07002717 return;
2718 }
2719 }
2720 LOGV("removeOutputTrack(): unkonwn thread: %p", thread);
2721}
2722
Eric Laurent8ac9f8d2009-12-18 05:47:48 -08002723void AudioFlinger::DuplicatingThread::updateWaitTime()
2724{
2725 mWaitTimeMs = UINT_MAX;
2726 for (size_t i = 0; i < mOutputTracks.size(); i++) {
2727 sp<ThreadBase> strong = mOutputTracks[i]->thread().promote();
2728 if (strong != NULL) {
2729 uint32_t waitTimeMs = (strong->frameCount() * 2 * 1000) / strong->sampleRate();
2730 if (waitTimeMs < mWaitTimeMs) {
2731 mWaitTimeMs = waitTimeMs;
2732 }
2733 }
2734 }
2735}
2736
2737
2738bool AudioFlinger::DuplicatingThread::outputsReady(SortedVector< sp<OutputTrack> > &outputTracks)
2739{
2740 for (size_t i = 0; i < outputTracks.size(); i++) {
2741 sp <ThreadBase> thread = outputTracks[i]->thread().promote();
2742 if (thread == 0) {
2743 LOGW("DuplicatingThread::outputsReady() could not promote thread on output track %p", outputTracks[i].get());
2744 return false;
2745 }
2746 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
2747 if (playbackThread->standby() && !playbackThread->isSuspended()) {
2748 LOGV("DuplicatingThread output track %p on thread %p Not Ready", outputTracks[i].get(), thread.get());
2749 return false;
2750 }
2751 }
2752 return true;
2753}
2754
2755uint32_t AudioFlinger::DuplicatingThread::activeSleepTimeUs()
2756{
2757 return (mWaitTimeMs * 1000) / 2;
2758}
2759
Eric Laurenta553c252009-07-17 12:17:14 -07002760// ----------------------------------------------------------------------------
2761
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07002762// TrackBase constructor must be called with AudioFlinger::mLock held
Eric Laurenta553c252009-07-17 12:17:14 -07002763AudioFlinger::ThreadBase::TrackBase::TrackBase(
2764 const wp<ThreadBase>& thread,
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002765 const sp<Client>& client,
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002766 uint32_t sampleRate,
2767 int format,
2768 int channelCount,
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002769 int frameCount,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002770 uint32_t flags,
Eric Laurent65b65452010-06-01 23:49:17 -07002771 const sp<IMemory>& sharedBuffer,
2772 int sessionId)
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002773 : RefBase(),
Eric Laurenta553c252009-07-17 12:17:14 -07002774 mThread(thread),
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002775 mClient(client),
Eric Laurent8a77a992009-09-09 05:16:08 -07002776 mCblk(0),
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002777 mFrameCount(0),
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002778 mState(IDLE),
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002779 mClientTid(-1),
2780 mFormat(format),
Eric Laurent65b65452010-06-01 23:49:17 -07002781 mFlags(flags & ~SYSTEM_FLAGS_MASK),
2782 mSessionId(sessionId)
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002783{
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002784 LOGV_IF(sharedBuffer != 0, "sharedBuffer: %p, size: %d", sharedBuffer->pointer(), sharedBuffer->size());
2785
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002786 // LOGD("Creating track with %d buffers @ %d bytes", bufferCount, bufferSize);
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002787 size_t size = sizeof(audio_track_cblk_t);
2788 size_t bufferSize = frameCount*channelCount*sizeof(int16_t);
2789 if (sharedBuffer == 0) {
2790 size += bufferSize;
2791 }
2792
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002793 if (client != NULL) {
2794 mCblkMemory = client->heap()->allocate(size);
2795 if (mCblkMemory != 0) {
2796 mCblk = static_cast<audio_track_cblk_t *>(mCblkMemory->pointer());
2797 if (mCblk) { // construct the shared structure in-place.
2798 new(mCblk) audio_track_cblk_t();
2799 // clear all buffers
2800 mCblk->frameCount = frameCount;
Eric Laurent88e209d2009-07-07 07:10:45 -07002801 mCblk->sampleRate = sampleRate;
Eric Laurentb0a01472010-05-14 05:45:46 -07002802 mCblk->channelCount = (uint8_t)channelCount;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002803 if (sharedBuffer == 0) {
2804 mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t);
2805 memset(mBuffer, 0, frameCount*channelCount*sizeof(int16_t));
2806 // Force underrun condition to avoid false underrun callback until first data is
Eric Laurent4712baa2010-09-30 16:12:31 -07002807 // written to buffer (other flags are cleared)
Eric Laurenteb8f850d2010-05-14 03:26:45 -07002808 mCblk->flags = CBLK_UNDERRUN_ON;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002809 } else {
2810 mBuffer = sharedBuffer->pointer();
2811 }
2812 mBufferEnd = (uint8_t *)mBuffer + bufferSize;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002813 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002814 } else {
2815 LOGE("not enough memory for AudioTrack size=%u", size);
2816 client->heap()->dump("AudioTrack");
2817 return;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002818 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002819 } else {
2820 mCblk = (audio_track_cblk_t *)(new uint8_t[size]);
2821 if (mCblk) { // construct the shared structure in-place.
2822 new(mCblk) audio_track_cblk_t();
2823 // clear all buffers
2824 mCblk->frameCount = frameCount;
Eric Laurent88e209d2009-07-07 07:10:45 -07002825 mCblk->sampleRate = sampleRate;
Eric Laurentb0a01472010-05-14 05:45:46 -07002826 mCblk->channelCount = (uint8_t)channelCount;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002827 mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t);
2828 memset(mBuffer, 0, frameCount*channelCount*sizeof(int16_t));
2829 // Force underrun condition to avoid false underrun callback until first data is
Eric Laurent4712baa2010-09-30 16:12:31 -07002830 // written to buffer (other flags are cleared)
Eric Laurenteb8f850d2010-05-14 03:26:45 -07002831 mCblk->flags = CBLK_UNDERRUN_ON;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002832 mBufferEnd = (uint8_t *)mBuffer + bufferSize;
2833 }
2834 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002835}
2836
Eric Laurent2bb6b2a2009-09-16 06:02:45 -07002837AudioFlinger::ThreadBase::TrackBase::~TrackBase()
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002838{
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002839 if (mCblk) {
Eric Laurenta553c252009-07-17 12:17:14 -07002840 mCblk->~audio_track_cblk_t(); // destroy our shared-structure.
2841 if (mClient == NULL) {
2842 delete mCblk;
2843 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002844 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002845 mCblkMemory.clear(); // and free the shared memory
Eric Laurentb9481d82009-09-17 05:12:56 -07002846 if (mClient != NULL) {
2847 Mutex::Autolock _l(mClient->audioFlinger()->mLock);
2848 mClient.clear();
2849 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002850}
2851
Eric Laurent2bb6b2a2009-09-16 06:02:45 -07002852void AudioFlinger::ThreadBase::TrackBase::releaseBuffer(AudioBufferProvider::Buffer* buffer)
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002853{
2854 buffer->raw = 0;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002855 mFrameCount = buffer->frameCount;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002856 step();
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002857 buffer->frameCount = 0;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002858}
2859
Eric Laurent2bb6b2a2009-09-16 06:02:45 -07002860bool AudioFlinger::ThreadBase::TrackBase::step() {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002861 bool result;
2862 audio_track_cblk_t* cblk = this->cblk();
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002863
2864 result = cblk->stepServer(mFrameCount);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002865 if (!result) {
2866 LOGV("stepServer failed acquiring cblk mutex");
2867 mFlags |= STEPSERVER_FAILED;
2868 }
2869 return result;
2870}
2871
Eric Laurent2bb6b2a2009-09-16 06:02:45 -07002872void AudioFlinger::ThreadBase::TrackBase::reset() {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002873 audio_track_cblk_t* cblk = this->cblk();
2874
2875 cblk->user = 0;
2876 cblk->server = 0;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002877 cblk->userBase = 0;
2878 cblk->serverBase = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002879 mFlags &= (uint32_t)(~SYSTEM_FLAGS_MASK);
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002880 LOGV("TrackBase::reset");
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002881}
2882
Eric Laurent2bb6b2a2009-09-16 06:02:45 -07002883sp<IMemory> AudioFlinger::ThreadBase::TrackBase::getCblk() const
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002884{
2885 return mCblkMemory;
2886}
2887
Eric Laurent2bb6b2a2009-09-16 06:02:45 -07002888int AudioFlinger::ThreadBase::TrackBase::sampleRate() const {
The Android Open Source Project10592532009-03-18 17:39:46 -07002889 return (int)mCblk->sampleRate;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002890}
2891
Eric Laurent2bb6b2a2009-09-16 06:02:45 -07002892int AudioFlinger::ThreadBase::TrackBase::channelCount() const {
Eric Laurentb0a01472010-05-14 05:45:46 -07002893 return (int)mCblk->channelCount;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002894}
2895
Eric Laurent2bb6b2a2009-09-16 06:02:45 -07002896void* AudioFlinger::ThreadBase::TrackBase::getBuffer(uint32_t offset, uint32_t frames) const {
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002897 audio_track_cblk_t* cblk = this->cblk();
Eric Laurenta553c252009-07-17 12:17:14 -07002898 int8_t *bufferStart = (int8_t *)mBuffer + (offset-cblk->serverBase)*cblk->frameSize;
2899 int8_t *bufferEnd = bufferStart + frames * cblk->frameSize;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002900
2901 // Check validity of returned pointer in case the track control block would have been corrupted.
Eric Laurenta553c252009-07-17 12:17:14 -07002902 if (bufferStart < mBuffer || bufferStart > bufferEnd || bufferEnd > mBufferEnd ||
2903 ((unsigned long)bufferStart & (unsigned long)(cblk->frameSize - 1))) {
The Android Open Source Project10592532009-03-18 17:39:46 -07002904 LOGE("TrackBase::getBuffer buffer out of range:\n start: %p, end %p , mBuffer %p mBufferEnd %p\n \
Eric Laurentb0a01472010-05-14 05:45:46 -07002905 server %d, serverBase %d, user %d, userBase %d, channelCount %d",
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002906 bufferStart, bufferEnd, mBuffer, mBufferEnd,
Eric Laurentb0a01472010-05-14 05:45:46 -07002907 cblk->server, cblk->serverBase, cblk->user, cblk->userBase, cblk->channelCount);
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002908 return 0;
2909 }
2910
2911 return bufferStart;
2912}
2913
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002914// ----------------------------------------------------------------------------
2915
Eric Laurenta553c252009-07-17 12:17:14 -07002916// Track constructor must be called with AudioFlinger::mLock and ThreadBase::mLock held
2917AudioFlinger::PlaybackThread::Track::Track(
2918 const wp<ThreadBase>& thread,
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002919 const sp<Client>& client,
2920 int streamType,
2921 uint32_t sampleRate,
2922 int format,
2923 int channelCount,
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002924 int frameCount,
Eric Laurent65b65452010-06-01 23:49:17 -07002925 const sp<IMemory>& sharedBuffer,
2926 int sessionId)
2927 : TrackBase(thread, client, sampleRate, format, channelCount, frameCount, 0, sharedBuffer, sessionId),
Eric Laurenta92ebfa2010-08-31 13:50:07 -07002928 mMute(false), mSharedBuffer(sharedBuffer), mName(-1), mMainBuffer(NULL), mAuxBuffer(NULL),
2929 mAuxEffectId(0), mHasVolumeController(false)
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002930{
Eric Laurent8a77a992009-09-09 05:16:08 -07002931 if (mCblk != NULL) {
2932 sp<ThreadBase> baseThread = thread.promote();
2933 if (baseThread != 0) {
2934 PlaybackThread *playbackThread = (PlaybackThread *)baseThread.get();
2935 mName = playbackThread->getTrackName_l();
Eric Laurent65b65452010-06-01 23:49:17 -07002936 mMainBuffer = playbackThread->mixBuffer();
Eric Laurent8a77a992009-09-09 05:16:08 -07002937 }
2938 LOGV("Track constructor name %d, calling thread %d", mName, IPCThreadState::self()->getCallingPid());
2939 if (mName < 0) {
2940 LOGE("no more track names available");
2941 }
2942 mVolume[0] = 1.0f;
2943 mVolume[1] = 1.0f;
2944 mStreamType = streamType;
2945 // NOTE: audio_track_cblk_t::frameSize for 8 bit PCM data is based on a sample size of
2946 // 16 bit because data is converted to 16 bit before being stored in buffer by AudioTrack
Dima Zavin24fc2fb2011-04-19 22:30:36 -07002947 mCblk->frameSize = audio_is_linear_pcm(format) ? channelCount * sizeof(int16_t) : sizeof(int8_t);
Eric Laurenta553c252009-07-17 12:17:14 -07002948 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002949}
2950
Eric Laurenta553c252009-07-17 12:17:14 -07002951AudioFlinger::PlaybackThread::Track::~Track()
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002952{
Eric Laurenta553c252009-07-17 12:17:14 -07002953 LOGV("PlaybackThread::Track destructor");
2954 sp<ThreadBase> thread = mThread.promote();
2955 if (thread != 0) {
Eric Laurentac196e12009-12-01 02:17:41 -08002956 Mutex::Autolock _l(thread->mLock);
Eric Laurenta553c252009-07-17 12:17:14 -07002957 mState = TERMINATED;
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07002958 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002959}
2960
Eric Laurenta553c252009-07-17 12:17:14 -07002961void AudioFlinger::PlaybackThread::Track::destroy()
2962{
2963 // NOTE: destroyTrack_l() can remove a strong reference to this Track
2964 // by removing it from mTracks vector, so there is a risk that this Tracks's
2965 // desctructor is called. As the destructor needs to lock mLock,
2966 // we must acquire a strong reference on this Track before locking mLock
2967 // here so that the destructor is called only when exiting this function.
2968 // On the other hand, as long as Track::destroy() is only called by
2969 // TrackHandle destructor, the TrackHandle still holds a strong ref on
2970 // this Track with its member mTrack.
2971 sp<Track> keep(this);
2972 { // scope for mLock
2973 sp<ThreadBase> thread = mThread.promote();
2974 if (thread != 0) {
Eric Laurentac196e12009-12-01 02:17:41 -08002975 if (!isOutputTrack()) {
2976 if (mState == ACTIVE || mState == RESUMING) {
Eric Laurent8ed6ed02010-07-13 04:45:46 -07002977 AudioSystem::stopOutput(thread->id(),
Dima Zavin24fc2fb2011-04-19 22:30:36 -07002978 (audio_stream_type_t)mStreamType,
Eric Laurent8ed6ed02010-07-13 04:45:46 -07002979 mSessionId);
Gloria Wang9b3f1522011-02-24 14:51:45 -08002980
2981 // to track the speaker usage
2982 addBatteryData(IMediaPlayerService::kBatteryDataAudioFlingerStop);
Eric Laurentac196e12009-12-01 02:17:41 -08002983 }
2984 AudioSystem::releaseOutput(thread->id());
Eric Laurent49f02be2009-11-19 09:00:56 -08002985 }
Eric Laurenta553c252009-07-17 12:17:14 -07002986 Mutex::Autolock _l(thread->mLock);
2987 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
2988 playbackThread->destroyTrack_l(this);
2989 }
2990 }
2991}
2992
2993void AudioFlinger::PlaybackThread::Track::dump(char* buffer, size_t size)
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002994{
Eric Laurent65b65452010-06-01 23:49:17 -07002995 snprintf(buffer, size, " %05d %05d %03u %03u %03u %05u %04u %1d %1d %1d %05u %05u %05u 0x%08x 0x%08x 0x%08x 0x%08x\n",
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002996 mName - AudioMixer::TRACK0,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002997 (mClient == NULL) ? getpid() : mClient->pid(),
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002998 mStreamType,
2999 mFormat,
Eric Laurentb0a01472010-05-14 05:45:46 -07003000 mCblk->channelCount,
Eric Laurent65b65452010-06-01 23:49:17 -07003001 mSessionId,
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08003002 mFrameCount,
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003003 mState,
3004 mMute,
3005 mFillingUpStatus,
3006 mCblk->sampleRate,
3007 mCblk->volume[0],
3008 mCblk->volume[1],
3009 mCblk->server,
Eric Laurent65b65452010-06-01 23:49:17 -07003010 mCblk->user,
3011 (int)mMainBuffer,
3012 (int)mAuxBuffer);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003013}
3014
Eric Laurenta553c252009-07-17 12:17:14 -07003015status_t AudioFlinger::PlaybackThread::Track::getNextBuffer(AudioBufferProvider::Buffer* buffer)
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003016{
3017 audio_track_cblk_t* cblk = this->cblk();
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08003018 uint32_t framesReady;
3019 uint32_t framesReq = buffer->frameCount;
3020
3021 // Check if last stepServer failed, try to step now
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003022 if (mFlags & TrackBase::STEPSERVER_FAILED) {
3023 if (!step()) goto getNextBuffer_exit;
3024 LOGV("stepServer recovered");
3025 mFlags &= ~TrackBase::STEPSERVER_FAILED;
3026 }
3027
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08003028 framesReady = cblk->framesReady();
3029
3030 if (LIKELY(framesReady)) {
3031 uint32_t s = cblk->server;
3032 uint32_t bufferEnd = cblk->serverBase + cblk->frameCount;
3033
3034 bufferEnd = (cblk->loopEnd < bufferEnd) ? cblk->loopEnd : bufferEnd;
3035 if (framesReq > framesReady) {
3036 framesReq = framesReady;
3037 }
3038 if (s + framesReq > bufferEnd) {
3039 framesReq = bufferEnd - s;
3040 }
3041
3042 buffer->raw = getBuffer(s, framesReq);
3043 if (buffer->raw == 0) goto getNextBuffer_exit;
3044
3045 buffer->frameCount = framesReq;
3046 return NO_ERROR;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003047 }
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08003048
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003049getNextBuffer_exit:
3050 buffer->raw = 0;
3051 buffer->frameCount = 0;
Eric Laurent62443f52009-10-05 20:29:18 -07003052 LOGV("getNextBuffer() no more data for track %d on thread %p", mName, mThread.unsafe_get());
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003053 return NOT_ENOUGH_DATA;
3054}
3055
Eric Laurenta553c252009-07-17 12:17:14 -07003056bool AudioFlinger::PlaybackThread::Track::isReady() const {
Eric Laurent9a30fc12010-10-05 14:41:42 -07003057 if (mFillingUpStatus != FS_FILLING || isStopped() || isPausing()) return true;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08003058
3059 if (mCblk->framesReady() >= mCblk->frameCount ||
Eric Laurenteb8f850d2010-05-14 03:26:45 -07003060 (mCblk->flags & CBLK_FORCEREADY_MSK)) {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003061 mFillingUpStatus = FS_FILLED;
Eric Laurentae29b762011-03-28 18:37:07 -07003062 android_atomic_and(~CBLK_FORCEREADY_MSK, &mCblk->flags);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003063 return true;
3064 }
3065 return false;
3066}
3067
Eric Laurenta553c252009-07-17 12:17:14 -07003068status_t AudioFlinger::PlaybackThread::Track::start()
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003069{
Eric Laurent49f02be2009-11-19 09:00:56 -08003070 status_t status = NO_ERROR;
Eric Laurent0d7e0482010-07-19 06:24:46 -07003071 LOGV("start(%d), calling thread %d session %d",
3072 mName, IPCThreadState::self()->getCallingPid(), mSessionId);
Eric Laurenta553c252009-07-17 12:17:14 -07003073 sp<ThreadBase> thread = mThread.promote();
3074 if (thread != 0) {
3075 Mutex::Autolock _l(thread->mLock);
Eric Laurent49f02be2009-11-19 09:00:56 -08003076 int state = mState;
3077 // here the track could be either new, or restarted
3078 // in both cases "unstop" the track
3079 if (mState == PAUSED) {
3080 mState = TrackBase::RESUMING;
3081 LOGV("PAUSED => RESUMING (%d) on thread %p", mName, this);
3082 } else {
3083 mState = TrackBase::ACTIVE;
3084 LOGV("? => ACTIVE (%d) on thread %p", mName, this);
3085 }
3086
3087 if (!isOutputTrack() && state != ACTIVE && state != RESUMING) {
3088 thread->mLock.unlock();
Eric Laurent8ed6ed02010-07-13 04:45:46 -07003089 status = AudioSystem::startOutput(thread->id(),
Dima Zavin24fc2fb2011-04-19 22:30:36 -07003090 (audio_stream_type_t)mStreamType,
Eric Laurent8ed6ed02010-07-13 04:45:46 -07003091 mSessionId);
Eric Laurent49f02be2009-11-19 09:00:56 -08003092 thread->mLock.lock();
Gloria Wang9b3f1522011-02-24 14:51:45 -08003093
3094 // to track the speaker usage
3095 if (status == NO_ERROR) {
3096 addBatteryData(IMediaPlayerService::kBatteryDataAudioFlingerStart);
3097 }
Eric Laurent49f02be2009-11-19 09:00:56 -08003098 }
3099 if (status == NO_ERROR) {
3100 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
3101 playbackThread->addTrack_l(this);
3102 } else {
3103 mState = state;
3104 }
3105 } else {
3106 status = BAD_VALUE;
Eric Laurenta553c252009-07-17 12:17:14 -07003107 }
Eric Laurent49f02be2009-11-19 09:00:56 -08003108 return status;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003109}
3110
Eric Laurenta553c252009-07-17 12:17:14 -07003111void AudioFlinger::PlaybackThread::Track::stop()
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003112{
Eric Laurenta553c252009-07-17 12:17:14 -07003113 LOGV("stop(%d), calling thread %d", mName, IPCThreadState::self()->getCallingPid());
3114 sp<ThreadBase> thread = mThread.promote();
3115 if (thread != 0) {
3116 Mutex::Autolock _l(thread->mLock);
Eric Laurent49f02be2009-11-19 09:00:56 -08003117 int state = mState;
Eric Laurenta553c252009-07-17 12:17:14 -07003118 if (mState > STOPPED) {
3119 mState = STOPPED;
3120 // If the track is not active (PAUSED and buffers full), flush buffers
3121 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
3122 if (playbackThread->mActiveTracks.indexOf(this) < 0) {
3123 reset();
3124 }
Eric Laurent62443f52009-10-05 20:29:18 -07003125 LOGV("(> STOPPED) => STOPPED (%d) on thread %p", mName, playbackThread);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003126 }
Eric Laurent49f02be2009-11-19 09:00:56 -08003127 if (!isOutputTrack() && (state == ACTIVE || state == RESUMING)) {
3128 thread->mLock.unlock();
Eric Laurent8ed6ed02010-07-13 04:45:46 -07003129 AudioSystem::stopOutput(thread->id(),
Dima Zavin24fc2fb2011-04-19 22:30:36 -07003130 (audio_stream_type_t)mStreamType,
Eric Laurent8ed6ed02010-07-13 04:45:46 -07003131 mSessionId);
Eric Laurent49f02be2009-11-19 09:00:56 -08003132 thread->mLock.lock();
Gloria Wang9b3f1522011-02-24 14:51:45 -08003133
3134 // to track the speaker usage
3135 addBatteryData(IMediaPlayerService::kBatteryDataAudioFlingerStop);
Eric Laurent49f02be2009-11-19 09:00:56 -08003136 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003137 }
3138}
3139
Eric Laurenta553c252009-07-17 12:17:14 -07003140void AudioFlinger::PlaybackThread::Track::pause()
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003141{
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003142 LOGV("pause(%d), calling thread %d", mName, IPCThreadState::self()->getCallingPid());
Eric Laurenta553c252009-07-17 12:17:14 -07003143 sp<ThreadBase> thread = mThread.promote();
3144 if (thread != 0) {
3145 Mutex::Autolock _l(thread->mLock);
3146 if (mState == ACTIVE || mState == RESUMING) {
3147 mState = PAUSING;
Eric Laurent62443f52009-10-05 20:29:18 -07003148 LOGV("ACTIVE/RESUMING => PAUSING (%d) on thread %p", mName, thread.get());
Eric Laurent49f02be2009-11-19 09:00:56 -08003149 if (!isOutputTrack()) {
3150 thread->mLock.unlock();
Eric Laurent8ed6ed02010-07-13 04:45:46 -07003151 AudioSystem::stopOutput(thread->id(),
Dima Zavin24fc2fb2011-04-19 22:30:36 -07003152 (audio_stream_type_t)mStreamType,
Eric Laurent8ed6ed02010-07-13 04:45:46 -07003153 mSessionId);
Eric Laurent49f02be2009-11-19 09:00:56 -08003154 thread->mLock.lock();
Gloria Wang9b3f1522011-02-24 14:51:45 -08003155
3156 // to track the speaker usage
3157 addBatteryData(IMediaPlayerService::kBatteryDataAudioFlingerStop);
Eric Laurent49f02be2009-11-19 09:00:56 -08003158 }
Eric Laurenta553c252009-07-17 12:17:14 -07003159 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003160 }
3161}
3162
Eric Laurenta553c252009-07-17 12:17:14 -07003163void AudioFlinger::PlaybackThread::Track::flush()
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003164{
3165 LOGV("flush(%d)", mName);
Eric Laurenta553c252009-07-17 12:17:14 -07003166 sp<ThreadBase> thread = mThread.promote();
3167 if (thread != 0) {
3168 Mutex::Autolock _l(thread->mLock);
3169 if (mState != STOPPED && mState != PAUSED && mState != PAUSING) {
3170 return;
3171 }
3172 // No point remaining in PAUSED state after a flush => go to
3173 // STOPPED state
3174 mState = STOPPED;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003175
Eric Laurentae29b762011-03-28 18:37:07 -07003176 // do not reset the track if it is still in the process of being stopped or paused.
3177 // this will be done by prepareTracks_l() when the track is stopped.
3178 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
3179 if (playbackThread->mActiveTracks.indexOf(this) < 0) {
3180 reset();
3181 }
Eric Laurenta553c252009-07-17 12:17:14 -07003182 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003183}
3184
Eric Laurenta553c252009-07-17 12:17:14 -07003185void AudioFlinger::PlaybackThread::Track::reset()
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003186{
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08003187 // Do not reset twice to avoid discarding data written just after a flush and before
3188 // the audioflinger thread detects the track is stopped.
3189 if (!mResetDone) {
3190 TrackBase::reset();
3191 // Force underrun condition to avoid false underrun callback until first data is
3192 // written to buffer
Eric Laurentae29b762011-03-28 18:37:07 -07003193 android_atomic_and(~CBLK_FORCEREADY_MSK, &mCblk->flags);
3194 android_atomic_or(CBLK_UNDERRUN_ON, &mCblk->flags);
Eric Laurenta553c252009-07-17 12:17:14 -07003195 mFillingUpStatus = FS_FILLING;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08003196 mResetDone = true;
3197 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003198}
3199
Eric Laurenta553c252009-07-17 12:17:14 -07003200void AudioFlinger::PlaybackThread::Track::mute(bool muted)
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003201{
3202 mMute = muted;
3203}
3204
Eric Laurenta553c252009-07-17 12:17:14 -07003205void AudioFlinger::PlaybackThread::Track::setVolume(float left, float right)
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003206{
3207 mVolume[0] = left;
3208 mVolume[1] = right;
3209}
3210
Eric Laurent65b65452010-06-01 23:49:17 -07003211status_t AudioFlinger::PlaybackThread::Track::attachAuxEffect(int EffectId)
3212{
3213 status_t status = DEAD_OBJECT;
3214 sp<ThreadBase> thread = mThread.promote();
3215 if (thread != 0) {
3216 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
3217 status = playbackThread->attachAuxEffect(this, EffectId);
3218 }
3219 return status;
3220}
3221
3222void AudioFlinger::PlaybackThread::Track::setAuxBuffer(int EffectId, int32_t *buffer)
3223{
3224 mAuxEffectId = EffectId;
3225 mAuxBuffer = buffer;
3226}
3227
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003228// ----------------------------------------------------------------------------
3229
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07003230// RecordTrack constructor must be called with AudioFlinger::mLock held
Eric Laurenta553c252009-07-17 12:17:14 -07003231AudioFlinger::RecordThread::RecordTrack::RecordTrack(
3232 const wp<ThreadBase>& thread,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003233 const sp<Client>& client,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003234 uint32_t sampleRate,
3235 int format,
3236 int channelCount,
3237 int frameCount,
Eric Laurent65b65452010-06-01 23:49:17 -07003238 uint32_t flags,
3239 int sessionId)
Eric Laurenta553c252009-07-17 12:17:14 -07003240 : TrackBase(thread, client, sampleRate, format,
Eric Laurent65b65452010-06-01 23:49:17 -07003241 channelCount, frameCount, flags, 0, sessionId),
Eric Laurenta553c252009-07-17 12:17:14 -07003242 mOverflow(false)
3243{
Eric Laurent8a77a992009-09-09 05:16:08 -07003244 if (mCblk != NULL) {
3245 LOGV("RecordTrack constructor, size %d", (int)mBufferEnd - (int)mBuffer);
Dima Zavin24fc2fb2011-04-19 22:30:36 -07003246 if (format == AUDIO_FORMAT_PCM_16_BIT) {
Eric Laurent8a77a992009-09-09 05:16:08 -07003247 mCblk->frameSize = channelCount * sizeof(int16_t);
Dima Zavin24fc2fb2011-04-19 22:30:36 -07003248 } else if (format == AUDIO_FORMAT_PCM_8_BIT) {
Eric Laurent8a77a992009-09-09 05:16:08 -07003249 mCblk->frameSize = channelCount * sizeof(int8_t);
3250 } else {
3251 mCblk->frameSize = sizeof(int8_t);
3252 }
3253 }
Eric Laurenta553c252009-07-17 12:17:14 -07003254}
3255
3256AudioFlinger::RecordThread::RecordTrack::~RecordTrack()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003257{
Eric Laurent49f02be2009-11-19 09:00:56 -08003258 sp<ThreadBase> thread = mThread.promote();
3259 if (thread != 0) {
3260 AudioSystem::releaseInput(thread->id());
3261 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003262}
3263
Eric Laurenta553c252009-07-17 12:17:14 -07003264status_t AudioFlinger::RecordThread::RecordTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003265{
3266 audio_track_cblk_t* cblk = this->cblk();
3267 uint32_t framesAvail;
3268 uint32_t framesReq = buffer->frameCount;
3269
3270 // Check if last stepServer failed, try to step now
3271 if (mFlags & TrackBase::STEPSERVER_FAILED) {
3272 if (!step()) goto getNextBuffer_exit;
3273 LOGV("stepServer recovered");
3274 mFlags &= ~TrackBase::STEPSERVER_FAILED;
3275 }
3276
3277 framesAvail = cblk->framesAvailable_l();
3278
3279 if (LIKELY(framesAvail)) {
3280 uint32_t s = cblk->server;
3281 uint32_t bufferEnd = cblk->serverBase + cblk->frameCount;
3282
3283 if (framesReq > framesAvail) {
3284 framesReq = framesAvail;
3285 }
3286 if (s + framesReq > bufferEnd) {
3287 framesReq = bufferEnd - s;
3288 }
3289
3290 buffer->raw = getBuffer(s, framesReq);
3291 if (buffer->raw == 0) goto getNextBuffer_exit;
3292
3293 buffer->frameCount = framesReq;
3294 return NO_ERROR;
3295 }
3296
3297getNextBuffer_exit:
3298 buffer->raw = 0;
3299 buffer->frameCount = 0;
3300 return NOT_ENOUGH_DATA;
3301}
3302
Eric Laurenta553c252009-07-17 12:17:14 -07003303status_t AudioFlinger::RecordThread::RecordTrack::start()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003304{
Eric Laurenta553c252009-07-17 12:17:14 -07003305 sp<ThreadBase> thread = mThread.promote();
3306 if (thread != 0) {
3307 RecordThread *recordThread = (RecordThread *)thread.get();
3308 return recordThread->start(this);
Eric Laurent49f02be2009-11-19 09:00:56 -08003309 } else {
3310 return BAD_VALUE;
Eric Laurenta553c252009-07-17 12:17:14 -07003311 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003312}
3313
Eric Laurenta553c252009-07-17 12:17:14 -07003314void AudioFlinger::RecordThread::RecordTrack::stop()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003315{
Eric Laurenta553c252009-07-17 12:17:14 -07003316 sp<ThreadBase> thread = mThread.promote();
3317 if (thread != 0) {
3318 RecordThread *recordThread = (RecordThread *)thread.get();
3319 recordThread->stop(this);
Eric Laurentae29b762011-03-28 18:37:07 -07003320 TrackBase::reset();
3321 // Force overerrun condition to avoid false overrun callback until first data is
3322 // read from buffer
3323 android_atomic_or(CBLK_UNDERRUN_ON, &mCblk->flags);
Eric Laurenta553c252009-07-17 12:17:14 -07003324 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003325}
3326
Eric Laurent3fdb1262009-11-07 00:01:32 -08003327void AudioFlinger::RecordThread::RecordTrack::dump(char* buffer, size_t size)
3328{
Eric Laurent65b65452010-06-01 23:49:17 -07003329 snprintf(buffer, size, " %05d %03u %03u %05d %04u %01d %05u %08x %08x\n",
Eric Laurent3fdb1262009-11-07 00:01:32 -08003330 (mClient == NULL) ? getpid() : mClient->pid(),
3331 mFormat,
Eric Laurentb0a01472010-05-14 05:45:46 -07003332 mCblk->channelCount,
Eric Laurent65b65452010-06-01 23:49:17 -07003333 mSessionId,
Eric Laurent3fdb1262009-11-07 00:01:32 -08003334 mFrameCount,
3335 mState,
3336 mCblk->sampleRate,
3337 mCblk->server,
3338 mCblk->user);
3339}
3340
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003341
3342// ----------------------------------------------------------------------------
3343
Eric Laurenta553c252009-07-17 12:17:14 -07003344AudioFlinger::PlaybackThread::OutputTrack::OutputTrack(
3345 const wp<ThreadBase>& thread,
Eric Laurent8ac9f8d2009-12-18 05:47:48 -08003346 DuplicatingThread *sourceThread,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003347 uint32_t sampleRate,
3348 int format,
3349 int channelCount,
3350 int frameCount)
Dima Zavin24fc2fb2011-04-19 22:30:36 -07003351 : Track(thread, NULL, AUDIO_STREAM_CNT, sampleRate, format, channelCount, frameCount, NULL, 0),
Eric Laurent8ac9f8d2009-12-18 05:47:48 -08003352 mActive(false), mSourceThread(sourceThread)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003353{
Eric Laurenta553c252009-07-17 12:17:14 -07003354
3355 PlaybackThread *playbackThread = (PlaybackThread *)thread.unsafe_get();
Eric Laurent6c30a712009-08-10 23:22:32 -07003356 if (mCblk != NULL) {
Eric Laurenteb8f850d2010-05-14 03:26:45 -07003357 mCblk->flags |= CBLK_DIRECTION_OUT;
Eric Laurent6c30a712009-08-10 23:22:32 -07003358 mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t);
3359 mCblk->volume[0] = mCblk->volume[1] = 0x1000;
3360 mOutBuffer.frameCount = 0;
Eric Laurent6c30a712009-08-10 23:22:32 -07003361 playbackThread->mTracks.add(this);
Eric Laurentb0a01472010-05-14 05:45:46 -07003362 LOGV("OutputTrack constructor mCblk %p, mBuffer %p, mCblk->buffers %p, mCblk->frameCount %d, mCblk->sampleRate %d, mCblk->channelCount %d mBufferEnd %p",
3363 mCblk, mBuffer, mCblk->buffers, mCblk->frameCount, mCblk->sampleRate, mCblk->channelCount, mBufferEnd);
Eric Laurent6c30a712009-08-10 23:22:32 -07003364 } else {
3365 LOGW("Error creating output track on thread %p", playbackThread);
3366 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003367}
3368
Eric Laurenta553c252009-07-17 12:17:14 -07003369AudioFlinger::PlaybackThread::OutputTrack::~OutputTrack()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003370{
Eric Laurent6c30a712009-08-10 23:22:32 -07003371 clearBufferQueue();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003372}
3373
Eric Laurenta553c252009-07-17 12:17:14 -07003374status_t AudioFlinger::PlaybackThread::OutputTrack::start()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003375{
3376 status_t status = Track::start();
Eric Laurenta553c252009-07-17 12:17:14 -07003377 if (status != NO_ERROR) {
3378 return status;
3379 }
3380
3381 mActive = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003382 mRetryCount = 127;
3383 return status;
3384}
3385
Eric Laurenta553c252009-07-17 12:17:14 -07003386void AudioFlinger::PlaybackThread::OutputTrack::stop()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003387{
3388 Track::stop();
3389 clearBufferQueue();
3390 mOutBuffer.frameCount = 0;
Eric Laurenta553c252009-07-17 12:17:14 -07003391 mActive = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003392}
3393
Eric Laurenta553c252009-07-17 12:17:14 -07003394bool AudioFlinger::PlaybackThread::OutputTrack::write(int16_t* data, uint32_t frames)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003395{
3396 Buffer *pInBuffer;
3397 Buffer inBuffer;
Eric Laurentb0a01472010-05-14 05:45:46 -07003398 uint32_t channelCount = mCblk->channelCount;
Eric Laurenta553c252009-07-17 12:17:14 -07003399 bool outputBufferFull = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003400 inBuffer.frameCount = frames;
3401 inBuffer.i16 = data;
Eric Laurenta553c252009-07-17 12:17:14 -07003402
Eric Laurent8ac9f8d2009-12-18 05:47:48 -08003403 uint32_t waitTimeLeftMs = mSourceThread->waitTimeMs();
Eric Laurenta553c252009-07-17 12:17:14 -07003404
Eric Laurent62443f52009-10-05 20:29:18 -07003405 if (!mActive && frames != 0) {
Eric Laurenta553c252009-07-17 12:17:14 -07003406 start();
3407 sp<ThreadBase> thread = mThread.promote();
3408 if (thread != 0) {
3409 MixerThread *mixerThread = (MixerThread *)thread.get();
3410 if (mCblk->frameCount > frames){
3411 if (mBufferQueue.size() < kMaxOverFlowBuffers) {
3412 uint32_t startFrames = (mCblk->frameCount - frames);
3413 pInBuffer = new Buffer;
Eric Laurentb0a01472010-05-14 05:45:46 -07003414 pInBuffer->mBuffer = new int16_t[startFrames * channelCount];
Eric Laurenta553c252009-07-17 12:17:14 -07003415 pInBuffer->frameCount = startFrames;
3416 pInBuffer->i16 = pInBuffer->mBuffer;
Eric Laurentb0a01472010-05-14 05:45:46 -07003417 memset(pInBuffer->raw, 0, startFrames * channelCount * sizeof(int16_t));
Eric Laurenta553c252009-07-17 12:17:14 -07003418 mBufferQueue.add(pInBuffer);
3419 } else {
3420 LOGW ("OutputTrack::write() %p no more buffers in queue", this);
3421 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003422 }
Eric Laurenta553c252009-07-17 12:17:14 -07003423 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003424 }
3425
Eric Laurenta553c252009-07-17 12:17:14 -07003426 while (waitTimeLeftMs) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003427 // First write pending buffers, then new data
3428 if (mBufferQueue.size()) {
3429 pInBuffer = mBufferQueue.itemAt(0);
3430 } else {
3431 pInBuffer = &inBuffer;
3432 }
Eric Laurenta553c252009-07-17 12:17:14 -07003433
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003434 if (pInBuffer->frameCount == 0) {
3435 break;
3436 }
Eric Laurenta553c252009-07-17 12:17:14 -07003437
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003438 if (mOutBuffer.frameCount == 0) {
3439 mOutBuffer.frameCount = pInBuffer->frameCount;
Eric Laurenta553c252009-07-17 12:17:14 -07003440 nsecs_t startTime = systemTime();
3441 if (obtainBuffer(&mOutBuffer, waitTimeLeftMs) == (status_t)AudioTrack::NO_MORE_BUFFERS) {
Eric Laurent8ac9f8d2009-12-18 05:47:48 -08003442 LOGV ("OutputTrack::write() %p thread %p no more output buffers", this, mThread.unsafe_get());
Eric Laurenta553c252009-07-17 12:17:14 -07003443 outputBufferFull = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003444 break;
3445 }
Eric Laurenta553c252009-07-17 12:17:14 -07003446 uint32_t waitTimeMs = (uint32_t)ns2ms(systemTime() - startTime);
Eric Laurenta553c252009-07-17 12:17:14 -07003447 if (waitTimeLeftMs >= waitTimeMs) {
3448 waitTimeLeftMs -= waitTimeMs;
3449 } else {
3450 waitTimeLeftMs = 0;
3451 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003452 }
Eric Laurenta553c252009-07-17 12:17:14 -07003453
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003454 uint32_t outFrames = pInBuffer->frameCount > mOutBuffer.frameCount ? mOutBuffer.frameCount : pInBuffer->frameCount;
Eric Laurentb0a01472010-05-14 05:45:46 -07003455 memcpy(mOutBuffer.raw, pInBuffer->raw, outFrames * channelCount * sizeof(int16_t));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003456 mCblk->stepUser(outFrames);
3457 pInBuffer->frameCount -= outFrames;
Eric Laurentb0a01472010-05-14 05:45:46 -07003458 pInBuffer->i16 += outFrames * channelCount;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003459 mOutBuffer.frameCount -= outFrames;
Eric Laurentb0a01472010-05-14 05:45:46 -07003460 mOutBuffer.i16 += outFrames * channelCount;
Eric Laurenta553c252009-07-17 12:17:14 -07003461
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003462 if (pInBuffer->frameCount == 0) {
3463 if (mBufferQueue.size()) {
3464 mBufferQueue.removeAt(0);
3465 delete [] pInBuffer->mBuffer;
3466 delete pInBuffer;
Eric Laurent8ac9f8d2009-12-18 05:47:48 -08003467 LOGV("OutputTrack::write() %p thread %p released overflow buffer %d", this, mThread.unsafe_get(), mBufferQueue.size());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003468 } else {
3469 break;
3470 }
3471 }
3472 }
Eric Laurenta553c252009-07-17 12:17:14 -07003473
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003474 // If we could not write all frames, allocate a buffer and queue it for next time.
3475 if (inBuffer.frameCount) {
Eric Laurent8ac9f8d2009-12-18 05:47:48 -08003476 sp<ThreadBase> thread = mThread.promote();
3477 if (thread != 0 && !thread->standby()) {
3478 if (mBufferQueue.size() < kMaxOverFlowBuffers) {
3479 pInBuffer = new Buffer;
Eric Laurentb0a01472010-05-14 05:45:46 -07003480 pInBuffer->mBuffer = new int16_t[inBuffer.frameCount * channelCount];
Eric Laurent8ac9f8d2009-12-18 05:47:48 -08003481 pInBuffer->frameCount = inBuffer.frameCount;
3482 pInBuffer->i16 = pInBuffer->mBuffer;
Eric Laurentb0a01472010-05-14 05:45:46 -07003483 memcpy(pInBuffer->raw, inBuffer.raw, inBuffer.frameCount * channelCount * sizeof(int16_t));
Eric Laurent8ac9f8d2009-12-18 05:47:48 -08003484 mBufferQueue.add(pInBuffer);
3485 LOGV("OutputTrack::write() %p thread %p adding overflow buffer %d", this, mThread.unsafe_get(), mBufferQueue.size());
3486 } else {
3487 LOGW("OutputTrack::write() %p thread %p no more overflow buffers", mThread.unsafe_get(), this);
3488 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003489 }
3490 }
Eric Laurenta553c252009-07-17 12:17:14 -07003491
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003492 // Calling write() with a 0 length buffer, means that no more data will be written:
Eric Laurenta553c252009-07-17 12:17:14 -07003493 // If no more buffers are pending, fill output track buffer to make sure it is started
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003494 // by output mixer.
Eric Laurenta553c252009-07-17 12:17:14 -07003495 if (frames == 0 && mBufferQueue.size() == 0) {
3496 if (mCblk->user < mCblk->frameCount) {
3497 frames = mCblk->frameCount - mCblk->user;
3498 pInBuffer = new Buffer;
Eric Laurentb0a01472010-05-14 05:45:46 -07003499 pInBuffer->mBuffer = new int16_t[frames * channelCount];
Eric Laurenta553c252009-07-17 12:17:14 -07003500 pInBuffer->frameCount = frames;
3501 pInBuffer->i16 = pInBuffer->mBuffer;
Eric Laurentb0a01472010-05-14 05:45:46 -07003502 memset(pInBuffer->raw, 0, frames * channelCount * sizeof(int16_t));
Eric Laurenta553c252009-07-17 12:17:14 -07003503 mBufferQueue.add(pInBuffer);
Eric Laurent62443f52009-10-05 20:29:18 -07003504 } else if (mActive) {
Eric Laurenta553c252009-07-17 12:17:14 -07003505 stop();
3506 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003507 }
3508
Eric Laurenta553c252009-07-17 12:17:14 -07003509 return outputBufferFull;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003510}
3511
Eric Laurenta553c252009-07-17 12:17:14 -07003512status_t AudioFlinger::PlaybackThread::OutputTrack::obtainBuffer(AudioBufferProvider::Buffer* buffer, uint32_t waitTimeMs)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003513{
3514 int active;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003515 status_t result;
3516 audio_track_cblk_t* cblk = mCblk;
3517 uint32_t framesReq = buffer->frameCount;
3518
Eric Laurenta553c252009-07-17 12:17:14 -07003519// LOGV("OutputTrack::obtainBuffer user %d, server %d", cblk->user, cblk->server);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003520 buffer->frameCount = 0;
Eric Laurenta553c252009-07-17 12:17:14 -07003521
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003522 uint32_t framesAvail = cblk->framesAvailable();
3523
Eric Laurenta553c252009-07-17 12:17:14 -07003524
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003525 if (framesAvail == 0) {
Eric Laurenta553c252009-07-17 12:17:14 -07003526 Mutex::Autolock _l(cblk->lock);
3527 goto start_loop_here;
3528 while (framesAvail == 0) {
3529 active = mActive;
3530 if (UNLIKELY(!active)) {
3531 LOGV("Not active and NO_MORE_BUFFERS");
3532 return AudioTrack::NO_MORE_BUFFERS;
3533 }
3534 result = cblk->cv.waitRelative(cblk->lock, milliseconds(waitTimeMs));
3535 if (result != NO_ERROR) {
3536 return AudioTrack::NO_MORE_BUFFERS;
3537 }
3538 // read the server count again
3539 start_loop_here:
3540 framesAvail = cblk->framesAvailable_l();
3541 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003542 }
3543
Eric Laurenta553c252009-07-17 12:17:14 -07003544// if (framesAvail < framesReq) {
3545// return AudioTrack::NO_MORE_BUFFERS;
3546// }
3547
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003548 if (framesReq > framesAvail) {
3549 framesReq = framesAvail;
3550 }
3551
3552 uint32_t u = cblk->user;
3553 uint32_t bufferEnd = cblk->userBase + cblk->frameCount;
3554
3555 if (u + framesReq > bufferEnd) {
3556 framesReq = bufferEnd - u;
3557 }
3558
3559 buffer->frameCount = framesReq;
3560 buffer->raw = (void *)cblk->buffer(u);
3561 return NO_ERROR;
3562}
3563
3564
Eric Laurenta553c252009-07-17 12:17:14 -07003565void AudioFlinger::PlaybackThread::OutputTrack::clearBufferQueue()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003566{
3567 size_t size = mBufferQueue.size();
3568 Buffer *pBuffer;
Eric Laurenta553c252009-07-17 12:17:14 -07003569
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003570 for (size_t i = 0; i < size; i++) {
3571 pBuffer = mBufferQueue.itemAt(i);
3572 delete [] pBuffer->mBuffer;
3573 delete pBuffer;
3574 }
3575 mBufferQueue.clear();
3576}
3577
3578// ----------------------------------------------------------------------------
3579
3580AudioFlinger::Client::Client(const sp<AudioFlinger>& audioFlinger, pid_t pid)
3581 : RefBase(),
3582 mAudioFlinger(audioFlinger),
Mathias Agopian6faf7892010-01-25 19:00:00 -08003583 mMemoryDealer(new MemoryDealer(1024*1024, "AudioFlinger::Client")),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003584 mPid(pid)
3585{
3586 // 1 MB of address space is good for 32 tracks, 8 buffers each, 4 KB/buffer
3587}
3588
Eric Laurentb9481d82009-09-17 05:12:56 -07003589// Client destructor must be called with AudioFlinger::mLock held
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003590AudioFlinger::Client::~Client()
3591{
Eric Laurentb9481d82009-09-17 05:12:56 -07003592 mAudioFlinger->removeClient_l(mPid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003593}
3594
3595const sp<MemoryDealer>& AudioFlinger::Client::heap() const
3596{
3597 return mMemoryDealer;
3598}
3599
3600// ----------------------------------------------------------------------------
3601
Eric Laurent4f0f17d2010-05-12 02:05:53 -07003602AudioFlinger::NotificationClient::NotificationClient(const sp<AudioFlinger>& audioFlinger,
3603 const sp<IAudioFlingerClient>& client,
3604 pid_t pid)
3605 : mAudioFlinger(audioFlinger), mPid(pid), mClient(client)
3606{
3607}
3608
3609AudioFlinger::NotificationClient::~NotificationClient()
3610{
3611 mClient.clear();
3612}
3613
3614void AudioFlinger::NotificationClient::binderDied(const wp<IBinder>& who)
3615{
3616 sp<NotificationClient> keep(this);
3617 {
3618 mAudioFlinger->removeNotificationClient(mPid);
3619 }
3620}
3621
3622// ----------------------------------------------------------------------------
3623
Eric Laurenta553c252009-07-17 12:17:14 -07003624AudioFlinger::TrackHandle::TrackHandle(const sp<AudioFlinger::PlaybackThread::Track>& track)
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003625 : BnAudioTrack(),
3626 mTrack(track)
3627{
3628}
3629
3630AudioFlinger::TrackHandle::~TrackHandle() {
3631 // just stop the track on deletion, associated resources
3632 // will be freed from the main thread once all pending buffers have
3633 // been played. Unless it's not in the active track list, in which
3634 // case we free everything now...
3635 mTrack->destroy();
3636}
3637
3638status_t AudioFlinger::TrackHandle::start() {
3639 return mTrack->start();
3640}
3641
3642void AudioFlinger::TrackHandle::stop() {
3643 mTrack->stop();
3644}
3645
3646void AudioFlinger::TrackHandle::flush() {
3647 mTrack->flush();
3648}
3649
3650void AudioFlinger::TrackHandle::mute(bool e) {
3651 mTrack->mute(e);
3652}
3653
3654void AudioFlinger::TrackHandle::pause() {
3655 mTrack->pause();
3656}
3657
3658void AudioFlinger::TrackHandle::setVolume(float left, float right) {
3659 mTrack->setVolume(left, right);
3660}
3661
3662sp<IMemory> AudioFlinger::TrackHandle::getCblk() const {
3663 return mTrack->getCblk();
3664}
3665
Eric Laurent65b65452010-06-01 23:49:17 -07003666status_t AudioFlinger::TrackHandle::attachAuxEffect(int EffectId)
3667{
3668 return mTrack->attachAuxEffect(EffectId);
3669}
3670
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003671status_t AudioFlinger::TrackHandle::onTransact(
3672 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
3673{
3674 return BnAudioTrack::onTransact(code, data, reply, flags);
3675}
3676
3677// ----------------------------------------------------------------------------
3678
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003679sp<IAudioRecord> AudioFlinger::openRecord(
3680 pid_t pid,
Eric Laurentddb78e72009-07-28 08:44:33 -07003681 int input,
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003682 uint32_t sampleRate,
3683 int format,
3684 int channelCount,
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08003685 int frameCount,
3686 uint32_t flags,
Eric Laurent65b65452010-06-01 23:49:17 -07003687 int *sessionId,
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08003688 status_t *status)
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003689{
Eric Laurenta553c252009-07-17 12:17:14 -07003690 sp<RecordThread::RecordTrack> recordTrack;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003691 sp<RecordHandle> recordHandle;
3692 sp<Client> client;
3693 wp<Client> wclient;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08003694 status_t lStatus;
Eric Laurenta553c252009-07-17 12:17:14 -07003695 RecordThread *thread;
3696 size_t inFrameCount;
Eric Laurent65b65452010-06-01 23:49:17 -07003697 int lSessionId;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003698
3699 // check calling permissions
3700 if (!recordingAllowed()) {
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08003701 lStatus = PERMISSION_DENIED;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003702 goto Exit;
3703 }
3704
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003705 // add client to list
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07003706 { // scope for mLock
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003707 Mutex::Autolock _l(mLock);
Eric Laurenta553c252009-07-17 12:17:14 -07003708 thread = checkRecordThread_l(input);
3709 if (thread == NULL) {
3710 lStatus = BAD_VALUE;
3711 goto Exit;
3712 }
3713
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003714 wclient = mClients.valueFor(pid);
3715 if (wclient != NULL) {
3716 client = wclient.promote();
3717 } else {
3718 client = new Client(this, pid);
3719 mClients.add(pid, client);
3720 }
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07003721
Eric Laurent65b65452010-06-01 23:49:17 -07003722 // If no audio session id is provided, create one here
Dima Zavin24fc2fb2011-04-19 22:30:36 -07003723 if (sessionId != NULL && *sessionId != AUDIO_SESSION_OUTPUT_MIX) {
Eric Laurent65b65452010-06-01 23:49:17 -07003724 lSessionId = *sessionId;
3725 } else {
Eric Laurentf3d6dd02010-11-18 08:40:16 -08003726 lSessionId = nextUniqueId_l();
Eric Laurent65b65452010-06-01 23:49:17 -07003727 if (sessionId != NULL) {
3728 *sessionId = lSessionId;
3729 }
3730 }
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07003731 // create new record track. The record track uses one track in mHardwareMixerThread by convention.
Eric Laurenta553c252009-07-17 12:17:14 -07003732 recordTrack = new RecordThread::RecordTrack(thread, client, sampleRate,
Eric Laurent65b65452010-06-01 23:49:17 -07003733 format, channelCount, frameCount, flags, lSessionId);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003734 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003735 if (recordTrack->getCblk() == NULL) {
Eric Laurentb9481d82009-09-17 05:12:56 -07003736 // remove local strong reference to Client before deleting the RecordTrack so that the Client
3737 // destructor is called by the TrackBase destructor with mLock held
3738 client.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003739 recordTrack.clear();
3740 lStatus = NO_MEMORY;
3741 goto Exit;
3742 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003743
3744 // return to handle to client
3745 recordHandle = new RecordHandle(recordTrack);
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08003746 lStatus = NO_ERROR;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003747
3748Exit:
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08003749 if (status) {
3750 *status = lStatus;
3751 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003752 return recordHandle;
3753}
3754
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003755// ----------------------------------------------------------------------------
3756
Eric Laurenta553c252009-07-17 12:17:14 -07003757AudioFlinger::RecordHandle::RecordHandle(const sp<AudioFlinger::RecordThread::RecordTrack>& recordTrack)
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003758 : BnAudioRecord(),
3759 mRecordTrack(recordTrack)
3760{
3761}
3762
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08003763AudioFlinger::RecordHandle::~RecordHandle() {
3764 stop();
3765}
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003766
3767status_t AudioFlinger::RecordHandle::start() {
3768 LOGV("RecordHandle::start()");
3769 return mRecordTrack->start();
3770}
3771
3772void AudioFlinger::RecordHandle::stop() {
3773 LOGV("RecordHandle::stop()");
3774 mRecordTrack->stop();
3775}
3776
3777sp<IMemory> AudioFlinger::RecordHandle::getCblk() const {
3778 return mRecordTrack->getCblk();
3779}
3780
3781status_t AudioFlinger::RecordHandle::onTransact(
3782 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
3783{
3784 return BnAudioRecord::onTransact(code, data, reply, flags);
3785}
3786
3787// ----------------------------------------------------------------------------
3788
Dima Zavin31f188892011-04-18 16:57:27 -07003789AudioFlinger::RecordThread::RecordThread(const sp<AudioFlinger>& audioFlinger, AudioStreamIn *input, uint32_t sampleRate, uint32_t channels, int id) :
Eric Laurent49f02be2009-11-19 09:00:56 -08003790 ThreadBase(audioFlinger, id),
Eric Laurenta553c252009-07-17 12:17:14 -07003791 mInput(input), mResampler(0), mRsmpOutBuffer(0), mRsmpInBuffer(0)
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003792{
Dima Zavin24fc2fb2011-04-19 22:30:36 -07003793 mReqChannelCount = popcount(channels);
Eric Laurenta553c252009-07-17 12:17:14 -07003794 mReqSampleRate = sampleRate;
3795 readInputParameters();
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003796}
3797
Eric Laurenta553c252009-07-17 12:17:14 -07003798
3799AudioFlinger::RecordThread::~RecordThread()
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003800{
Eric Laurenta553c252009-07-17 12:17:14 -07003801 delete[] mRsmpInBuffer;
3802 if (mResampler != 0) {
3803 delete mResampler;
3804 delete[] mRsmpOutBuffer;
3805 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003806}
3807
Eric Laurenta553c252009-07-17 12:17:14 -07003808void AudioFlinger::RecordThread::onFirstRef()
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003809{
Eric Laurenta553c252009-07-17 12:17:14 -07003810 const size_t SIZE = 256;
3811 char buffer[SIZE];
3812
3813 snprintf(buffer, SIZE, "Record Thread %p", this);
3814
3815 run(buffer, PRIORITY_URGENT_AUDIO);
3816}
Eric Laurent49f02be2009-11-19 09:00:56 -08003817
Eric Laurenta553c252009-07-17 12:17:14 -07003818bool AudioFlinger::RecordThread::threadLoop()
3819{
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08003820 AudioBufferProvider::Buffer buffer;
Eric Laurenta553c252009-07-17 12:17:14 -07003821 sp<RecordTrack> activeTrack;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003822
Eric Laurent4712baa2010-09-30 16:12:31 -07003823 nsecs_t lastWarning = 0;
3824
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003825 // start recording
3826 while (!exitPending()) {
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08003827
Eric Laurenta553c252009-07-17 12:17:14 -07003828 processConfigEvents();
3829
3830 { // scope for mLock
3831 Mutex::Autolock _l(mLock);
3832 checkForNewParameters_l();
3833 if (mActiveTrack == 0 && mConfigEvents.isEmpty()) {
3834 if (!mStandby) {
Dima Zavin31f188892011-04-18 16:57:27 -07003835 mInput->stream->common.standby(&mInput->stream->common);
Eric Laurenta553c252009-07-17 12:17:14 -07003836 mStandby = true;
3837 }
3838
3839 if (exitPending()) break;
3840
3841 LOGV("RecordThread: loop stopping");
3842 // go to sleep
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003843 mWaitWorkCV.wait(mLock);
Eric Laurenta553c252009-07-17 12:17:14 -07003844 LOGV("RecordThread: loop starting");
3845 continue;
3846 }
3847 if (mActiveTrack != 0) {
3848 if (mActiveTrack->mState == TrackBase::PAUSING) {
Eric Laurent9cc489a2009-12-05 05:20:01 -08003849 if (!mStandby) {
Dima Zavin31f188892011-04-18 16:57:27 -07003850 mInput->stream->common.standby(&mInput->stream->common);
Eric Laurent9cc489a2009-12-05 05:20:01 -08003851 mStandby = true;
3852 }
Eric Laurenta553c252009-07-17 12:17:14 -07003853 mActiveTrack.clear();
3854 mStartStopCond.broadcast();
3855 } else if (mActiveTrack->mState == TrackBase::RESUMING) {
Eric Laurenta553c252009-07-17 12:17:14 -07003856 if (mReqChannelCount != mActiveTrack->channelCount()) {
3857 mActiveTrack.clear();
Eric Laurent9cc489a2009-12-05 05:20:01 -08003858 mStartStopCond.broadcast();
3859 } else if (mBytesRead != 0) {
3860 // record start succeeds only if first read from audio input
3861 // succeeds
3862 if (mBytesRead > 0) {
3863 mActiveTrack->mState = TrackBase::ACTIVE;
3864 } else {
3865 mActiveTrack.clear();
3866 }
3867 mStartStopCond.broadcast();
Eric Laurenta553c252009-07-17 12:17:14 -07003868 }
Eric Laurent9cc489a2009-12-05 05:20:01 -08003869 mStandby = false;
Eric Laurenta553c252009-07-17 12:17:14 -07003870 }
Eric Laurenta553c252009-07-17 12:17:14 -07003871 }
3872 }
3873
3874 if (mActiveTrack != 0) {
Eric Laurent9cc489a2009-12-05 05:20:01 -08003875 if (mActiveTrack->mState != TrackBase::ACTIVE &&
3876 mActiveTrack->mState != TrackBase::RESUMING) {
Eric Laurent49f02be2009-11-19 09:00:56 -08003877 usleep(5000);
3878 continue;
3879 }
Eric Laurenta553c252009-07-17 12:17:14 -07003880 buffer.frameCount = mFrameCount;
3881 if (LIKELY(mActiveTrack->getNextBuffer(&buffer) == NO_ERROR)) {
3882 size_t framesOut = buffer.frameCount;
3883 if (mResampler == 0) {
3884 // no resampling
3885 while (framesOut) {
3886 size_t framesIn = mFrameCount - mRsmpInIndex;
3887 if (framesIn) {
3888 int8_t *src = (int8_t *)mRsmpInBuffer + mRsmpInIndex * mFrameSize;
3889 int8_t *dst = buffer.i8 + (buffer.frameCount - framesOut) * mActiveTrack->mCblk->frameSize;
3890 if (framesIn > framesOut)
3891 framesIn = framesOut;
3892 mRsmpInIndex += framesIn;
3893 framesOut -= framesIn;
Eric Laurentb0a01472010-05-14 05:45:46 -07003894 if ((int)mChannelCount == mReqChannelCount ||
Dima Zavin24fc2fb2011-04-19 22:30:36 -07003895 mFormat != AUDIO_FORMAT_PCM_16_BIT) {
Eric Laurenta553c252009-07-17 12:17:14 -07003896 memcpy(dst, src, framesIn * mFrameSize);
3897 } else {
3898 int16_t *src16 = (int16_t *)src;
3899 int16_t *dst16 = (int16_t *)dst;
3900 if (mChannelCount == 1) {
3901 while (framesIn--) {
3902 *dst16++ = *src16;
3903 *dst16++ = *src16++;
3904 }
3905 } else {
3906 while (framesIn--) {
3907 *dst16++ = (int16_t)(((int32_t)*src16 + (int32_t)*(src16 + 1)) >> 1);
3908 src16 += 2;
3909 }
3910 }
3911 }
3912 }
3913 if (framesOut && mFrameCount == mRsmpInIndex) {
Eric Laurenta553c252009-07-17 12:17:14 -07003914 if (framesOut == mFrameCount &&
Dima Zavin24fc2fb2011-04-19 22:30:36 -07003915 ((int)mChannelCount == mReqChannelCount || mFormat != AUDIO_FORMAT_PCM_16_BIT)) {
Dima Zavin31f188892011-04-18 16:57:27 -07003916 mBytesRead = mInput->stream->read(mInput->stream, buffer.raw, mInputBytes);
Eric Laurenta553c252009-07-17 12:17:14 -07003917 framesOut = 0;
3918 } else {
Dima Zavin31f188892011-04-18 16:57:27 -07003919 mBytesRead = mInput->stream->read(mInput->stream, mRsmpInBuffer, mInputBytes);
Eric Laurenta553c252009-07-17 12:17:14 -07003920 mRsmpInIndex = 0;
3921 }
Eric Laurent9cc489a2009-12-05 05:20:01 -08003922 if (mBytesRead < 0) {
Eric Laurenta553c252009-07-17 12:17:14 -07003923 LOGE("Error reading audio input");
Eric Laurent9cc489a2009-12-05 05:20:01 -08003924 if (mActiveTrack->mState == TrackBase::ACTIVE) {
Eric Laurentba8811f2010-03-02 18:38:06 -08003925 // Force input into standby so that it tries to
3926 // recover at next read attempt
Dima Zavin31f188892011-04-18 16:57:27 -07003927 mInput->stream->common.standby(&mInput->stream->common);
Eric Laurentba8811f2010-03-02 18:38:06 -08003928 usleep(5000);
Eric Laurent9cc489a2009-12-05 05:20:01 -08003929 }
Eric Laurenta553c252009-07-17 12:17:14 -07003930 mRsmpInIndex = mFrameCount;
3931 framesOut = 0;
3932 buffer.frameCount = 0;
3933 }
3934 }
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08003935 }
3936 } else {
Eric Laurenta553c252009-07-17 12:17:14 -07003937 // resampling
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003938
Eric Laurenta553c252009-07-17 12:17:14 -07003939 memset(mRsmpOutBuffer, 0, framesOut * 2 * sizeof(int32_t));
3940 // alter output frame count as if we were expecting stereo samples
3941 if (mChannelCount == 1 && mReqChannelCount == 1) {
3942 framesOut >>= 1;
3943 }
3944 mResampler->resample(mRsmpOutBuffer, framesOut, this);
3945 // ditherAndClamp() works as long as all buffers returned by mActiveTrack->getNextBuffer()
3946 // are 32 bit aligned which should be always true.
3947 if (mChannelCount == 2 && mReqChannelCount == 1) {
3948 AudioMixer::ditherAndClamp(mRsmpOutBuffer, mRsmpOutBuffer, framesOut);
3949 // the resampler always outputs stereo samples: do post stereo to mono conversion
3950 int16_t *src = (int16_t *)mRsmpOutBuffer;
3951 int16_t *dst = buffer.i16;
3952 while (framesOut--) {
3953 *dst++ = (int16_t)(((int32_t)*src + (int32_t)*(src + 1)) >> 1);
3954 src += 2;
3955 }
3956 } else {
3957 AudioMixer::ditherAndClamp((int32_t *)buffer.raw, mRsmpOutBuffer, framesOut);
3958 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003959
Eric Laurenta553c252009-07-17 12:17:14 -07003960 }
3961 mActiveTrack->releaseBuffer(&buffer);
3962 mActiveTrack->overflow();
3963 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003964 // client isn't retrieving buffers fast enough
3965 else {
Eric Laurent4712baa2010-09-30 16:12:31 -07003966 if (!mActiveTrack->setOverflow()) {
3967 nsecs_t now = systemTime();
3968 if ((now - lastWarning) > kWarningThrottle) {
3969 LOGW("RecordThread: buffer overflow");
3970 lastWarning = now;
3971 }
3972 }
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08003973 // Release the processor for a while before asking for a new buffer.
3974 // This will give the application more chance to read from the buffer and
3975 // clear the overflow.
3976 usleep(5000);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003977 }
3978 }
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08003979 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003980
Eric Laurenta553c252009-07-17 12:17:14 -07003981 if (!mStandby) {
Dima Zavin31f188892011-04-18 16:57:27 -07003982 mInput->stream->common.standby(&mInput->stream->common);
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08003983 }
Eric Laurenta553c252009-07-17 12:17:14 -07003984 mActiveTrack.clear();
3985
Eric Laurent49f02be2009-11-19 09:00:56 -08003986 mStartStopCond.broadcast();
3987
Eric Laurenta553c252009-07-17 12:17:14 -07003988 LOGV("RecordThread %p exiting", this);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003989 return false;
3990}
3991
Eric Laurenta553c252009-07-17 12:17:14 -07003992status_t AudioFlinger::RecordThread::start(RecordThread::RecordTrack* recordTrack)
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003993{
Eric Laurenta553c252009-07-17 12:17:14 -07003994 LOGV("RecordThread::start");
Eric Laurent49f02be2009-11-19 09:00:56 -08003995 sp <ThreadBase> strongMe = this;
3996 status_t status = NO_ERROR;
3997 {
3998 AutoMutex lock(&mLock);
3999 if (mActiveTrack != 0) {
4000 if (recordTrack != mActiveTrack.get()) {
4001 status = -EBUSY;
4002 } else if (mActiveTrack->mState == TrackBase::PAUSING) {
Eric Laurent9cc489a2009-12-05 05:20:01 -08004003 mActiveTrack->mState = TrackBase::ACTIVE;
Eric Laurent49f02be2009-11-19 09:00:56 -08004004 }
4005 return status;
4006 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07004007
Eric Laurent49f02be2009-11-19 09:00:56 -08004008 recordTrack->mState = TrackBase::IDLE;
4009 mActiveTrack = recordTrack;
4010 mLock.unlock();
4011 status_t status = AudioSystem::startInput(mId);
4012 mLock.lock();
4013 if (status != NO_ERROR) {
4014 mActiveTrack.clear();
4015 return status;
4016 }
Eric Laurent9cc489a2009-12-05 05:20:01 -08004017 mRsmpInIndex = mFrameCount;
4018 mBytesRead = 0;
Eric Laurent4bb21c42011-02-28 16:52:51 -08004019 if (mResampler != NULL) {
4020 mResampler->reset();
4021 }
4022 mActiveTrack->mState = TrackBase::RESUMING;
Eric Laurent49f02be2009-11-19 09:00:56 -08004023 // signal thread to start
4024 LOGV("Signal record thread");
4025 mWaitWorkCV.signal();
4026 // do not wait for mStartStopCond if exiting
4027 if (mExiting) {
4028 mActiveTrack.clear();
4029 status = INVALID_OPERATION;
4030 goto startError;
4031 }
4032 mStartStopCond.wait(mLock);
4033 if (mActiveTrack == 0) {
4034 LOGV("Record failed to start");
4035 status = BAD_VALUE;
4036 goto startError;
4037 }
Eric Laurenta553c252009-07-17 12:17:14 -07004038 LOGV("Record started OK");
Eric Laurent49f02be2009-11-19 09:00:56 -08004039 return status;
Eric Laurenta553c252009-07-17 12:17:14 -07004040 }
Eric Laurent49f02be2009-11-19 09:00:56 -08004041startError:
4042 AudioSystem::stopInput(mId);
4043 return status;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07004044}
4045
Eric Laurenta553c252009-07-17 12:17:14 -07004046void AudioFlinger::RecordThread::stop(RecordThread::RecordTrack* recordTrack) {
4047 LOGV("RecordThread::stop");
Eric Laurent49f02be2009-11-19 09:00:56 -08004048 sp <ThreadBase> strongMe = this;
4049 {
4050 AutoMutex lock(&mLock);
4051 if (mActiveTrack != 0 && recordTrack == mActiveTrack.get()) {
4052 mActiveTrack->mState = TrackBase::PAUSING;
4053 // do not wait for mStartStopCond if exiting
4054 if (mExiting) {
4055 return;
4056 }
4057 mStartStopCond.wait(mLock);
4058 // if we have been restarted, recordTrack == mActiveTrack.get() here
4059 if (mActiveTrack == 0 || recordTrack != mActiveTrack.get()) {
4060 mLock.unlock();
4061 AudioSystem::stopInput(mId);
4062 mLock.lock();
Eric Laurent9cc489a2009-12-05 05:20:01 -08004063 LOGV("Record stopped OK");
Eric Laurent49f02be2009-11-19 09:00:56 -08004064 }
4065 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07004066 }
4067}
4068
Eric Laurenta553c252009-07-17 12:17:14 -07004069status_t AudioFlinger::RecordThread::dump(int fd, const Vector<String16>& args)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004070{
4071 const size_t SIZE = 256;
4072 char buffer[SIZE];
4073 String8 result;
4074 pid_t pid = 0;
4075
Eric Laurent3fdb1262009-11-07 00:01:32 -08004076 snprintf(buffer, SIZE, "\nInput thread %p internals\n", this);
4077 result.append(buffer);
4078
4079 if (mActiveTrack != 0) {
4080 result.append("Active Track:\n");
Eric Laurent65b65452010-06-01 23:49:17 -07004081 result.append(" Clien Fmt Chn Session Buf S SRate Serv User\n");
Eric Laurent3fdb1262009-11-07 00:01:32 -08004082 mActiveTrack->dump(buffer, SIZE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004083 result.append(buffer);
Eric Laurent3fdb1262009-11-07 00:01:32 -08004084
4085 snprintf(buffer, SIZE, "In index: %d\n", mRsmpInIndex);
4086 result.append(buffer);
4087 snprintf(buffer, SIZE, "In size: %d\n", mInputBytes);
4088 result.append(buffer);
4089 snprintf(buffer, SIZE, "Resampling: %d\n", (mResampler != 0));
4090 result.append(buffer);
4091 snprintf(buffer, SIZE, "Out channel count: %d\n", mReqChannelCount);
4092 result.append(buffer);
4093 snprintf(buffer, SIZE, "Out sample rate: %d\n", mReqSampleRate);
4094 result.append(buffer);
4095
4096
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004097 } else {
4098 result.append("No record client\n");
4099 }
4100 write(fd, result.string(), result.size());
Eric Laurent3fdb1262009-11-07 00:01:32 -08004101
4102 dumpBase(fd, args);
4103
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004104 return NO_ERROR;
4105}
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07004106
Eric Laurenta553c252009-07-17 12:17:14 -07004107status_t AudioFlinger::RecordThread::getNextBuffer(AudioBufferProvider::Buffer* buffer)
4108{
4109 size_t framesReq = buffer->frameCount;
4110 size_t framesReady = mFrameCount - mRsmpInIndex;
4111 int channelCount;
4112
4113 if (framesReady == 0) {
Dima Zavin31f188892011-04-18 16:57:27 -07004114 mBytesRead = mInput->stream->read(mInput->stream, mRsmpInBuffer, mInputBytes);
Eric Laurent9cc489a2009-12-05 05:20:01 -08004115 if (mBytesRead < 0) {
Eric Laurenta553c252009-07-17 12:17:14 -07004116 LOGE("RecordThread::getNextBuffer() Error reading audio input");
Eric Laurent9cc489a2009-12-05 05:20:01 -08004117 if (mActiveTrack->mState == TrackBase::ACTIVE) {
Eric Laurentba8811f2010-03-02 18:38:06 -08004118 // Force input into standby so that it tries to
4119 // recover at next read attempt
Dima Zavin31f188892011-04-18 16:57:27 -07004120 mInput->stream->common.standby(&mInput->stream->common);
Eric Laurentba8811f2010-03-02 18:38:06 -08004121 usleep(5000);
Eric Laurent9cc489a2009-12-05 05:20:01 -08004122 }
Eric Laurenta553c252009-07-17 12:17:14 -07004123 buffer->raw = 0;
4124 buffer->frameCount = 0;
4125 return NOT_ENOUGH_DATA;
4126 }
4127 mRsmpInIndex = 0;
4128 framesReady = mFrameCount;
4129 }
4130
4131 if (framesReq > framesReady) {
4132 framesReq = framesReady;
4133 }
4134
4135 if (mChannelCount == 1 && mReqChannelCount == 2) {
4136 channelCount = 1;
4137 } else {
4138 channelCount = 2;
4139 }
4140 buffer->raw = mRsmpInBuffer + mRsmpInIndex * channelCount;
4141 buffer->frameCount = framesReq;
4142 return NO_ERROR;
4143}
4144
4145void AudioFlinger::RecordThread::releaseBuffer(AudioBufferProvider::Buffer* buffer)
4146{
4147 mRsmpInIndex += buffer->frameCount;
4148 buffer->frameCount = 0;
4149}
4150
4151bool AudioFlinger::RecordThread::checkForNewParameters_l()
4152{
4153 bool reconfig = false;
4154
Eric Laurent8fce46a2009-08-04 09:45:33 -07004155 while (!mNewParameters.isEmpty()) {
Eric Laurenta553c252009-07-17 12:17:14 -07004156 status_t status = NO_ERROR;
Eric Laurent8fce46a2009-08-04 09:45:33 -07004157 String8 keyValuePair = mNewParameters[0];
4158 AudioParameter param = AudioParameter(keyValuePair);
Eric Laurenta553c252009-07-17 12:17:14 -07004159 int value;
4160 int reqFormat = mFormat;
4161 int reqSamplingRate = mReqSampleRate;
4162 int reqChannelCount = mReqChannelCount;
Eric Laurent8fce46a2009-08-04 09:45:33 -07004163
Eric Laurenta553c252009-07-17 12:17:14 -07004164 if (param.getInt(String8(AudioParameter::keySamplingRate), value) == NO_ERROR) {
4165 reqSamplingRate = value;
4166 reconfig = true;
4167 }
4168 if (param.getInt(String8(AudioParameter::keyFormat), value) == NO_ERROR) {
4169 reqFormat = value;
4170 reconfig = true;
4171 }
4172 if (param.getInt(String8(AudioParameter::keyChannels), value) == NO_ERROR) {
Dima Zavin24fc2fb2011-04-19 22:30:36 -07004173 reqChannelCount = popcount(value);
Eric Laurenta553c252009-07-17 12:17:14 -07004174 reconfig = true;
4175 }
4176 if (param.getInt(String8(AudioParameter::keyFrameCount), value) == NO_ERROR) {
4177 // do not accept frame count changes if tracks are open as the track buffer
4178 // size depends on frame count and correct behavior would not be garantied
4179 // if frame count is changed after track creation
4180 if (mActiveTrack != 0) {
4181 status = INVALID_OPERATION;
4182 } else {
4183 reconfig = true;
4184 }
4185 }
4186 if (status == NO_ERROR) {
Dima Zavin31f188892011-04-18 16:57:27 -07004187 status = mInput->stream->common.set_parameters(&mInput->stream->common, keyValuePair.string());
Eric Laurenta553c252009-07-17 12:17:14 -07004188 if (status == INVALID_OPERATION) {
Dima Zavin31f188892011-04-18 16:57:27 -07004189 mInput->stream->common.standby(&mInput->stream->common);
4190 status = mInput->stream->common.set_parameters(&mInput->stream->common, keyValuePair.string());
Eric Laurenta553c252009-07-17 12:17:14 -07004191 }
4192 if (reconfig) {
4193 if (status == BAD_VALUE &&
Dima Zavin31f188892011-04-18 16:57:27 -07004194 reqFormat == mInput->stream->common.get_format(&mInput->stream->common) &&
Dima Zavin24fc2fb2011-04-19 22:30:36 -07004195 reqFormat == AUDIO_FORMAT_PCM_16_BIT &&
Dima Zavin31f188892011-04-18 16:57:27 -07004196 ((int)mInput->stream->common.get_sample_rate(&mInput->stream->common) <= (2 * reqSamplingRate)) &&
4197 (popcount(mInput->stream->common.get_channels(&mInput->stream->common)) < 3) &&
Dima Zavin24fc2fb2011-04-19 22:30:36 -07004198 (reqChannelCount < 3)) {
Eric Laurenta553c252009-07-17 12:17:14 -07004199 status = NO_ERROR;
4200 }
4201 if (status == NO_ERROR) {
4202 readInputParameters();
Eric Laurent8fce46a2009-08-04 09:45:33 -07004203 sendConfigEvent_l(AudioSystem::INPUT_CONFIG_CHANGED);
Eric Laurenta553c252009-07-17 12:17:14 -07004204 }
4205 }
4206 }
Eric Laurent3fdb1262009-11-07 00:01:32 -08004207
4208 mNewParameters.removeAt(0);
4209
Eric Laurenta553c252009-07-17 12:17:14 -07004210 mParamStatus = status;
4211 mParamCond.signal();
Eric Laurent8fce46a2009-08-04 09:45:33 -07004212 mWaitWorkCV.wait(mLock);
Eric Laurenta553c252009-07-17 12:17:14 -07004213 }
4214 return reconfig;
4215}
4216
4217String8 AudioFlinger::RecordThread::getParameters(const String8& keys)
4218{
Dima Zavin24fc2fb2011-04-19 22:30:36 -07004219 char *s;
4220 String8 out_s8;
4221
Dima Zavin31f188892011-04-18 16:57:27 -07004222 s = mInput->stream->common.get_parameters(&mInput->stream->common, keys.string());
Dima Zavin24fc2fb2011-04-19 22:30:36 -07004223 out_s8 = String8(s);
4224 free(s);
4225 return out_s8;
Eric Laurenta553c252009-07-17 12:17:14 -07004226}
4227
Eric Laurenteb8f850d2010-05-14 03:26:45 -07004228void AudioFlinger::RecordThread::audioConfigChanged_l(int event, int param) {
Eric Laurenta553c252009-07-17 12:17:14 -07004229 AudioSystem::OutputDescriptor desc;
4230 void *param2 = 0;
4231
4232 switch (event) {
4233 case AudioSystem::INPUT_OPENED:
4234 case AudioSystem::INPUT_CONFIG_CHANGED:
Eric Laurentb0a01472010-05-14 05:45:46 -07004235 desc.channels = mChannels;
Eric Laurenta553c252009-07-17 12:17:14 -07004236 desc.samplingRate = mSampleRate;
4237 desc.format = mFormat;
4238 desc.frameCount = mFrameCount;
4239 desc.latency = 0;
4240 param2 = &desc;
4241 break;
4242
4243 case AudioSystem::INPUT_CLOSED:
4244 default:
4245 break;
4246 }
Eric Laurent49f02be2009-11-19 09:00:56 -08004247 mAudioFlinger->audioConfigChanged_l(event, mId, param2);
Eric Laurenta553c252009-07-17 12:17:14 -07004248}
4249
4250void AudioFlinger::RecordThread::readInputParameters()
4251{
4252 if (mRsmpInBuffer) delete mRsmpInBuffer;
4253 if (mRsmpOutBuffer) delete mRsmpOutBuffer;
4254 if (mResampler) delete mResampler;
4255 mResampler = 0;
4256
Dima Zavin31f188892011-04-18 16:57:27 -07004257 mSampleRate = mInput->stream->common.get_sample_rate(&mInput->stream->common);
4258 mChannels = mInput->stream->common.get_channels(&mInput->stream->common);
Dima Zavin24fc2fb2011-04-19 22:30:36 -07004259 mChannelCount = (uint16_t)popcount(mChannels);
Dima Zavin31f188892011-04-18 16:57:27 -07004260 mFormat = mInput->stream->common.get_format(&mInput->stream->common);
4261 mFrameSize = (uint16_t)audio_stream_frame_size(&mInput->stream->common);
4262 mInputBytes = mInput->stream->common.get_buffer_size(&mInput->stream->common);
Eric Laurenta553c252009-07-17 12:17:14 -07004263 mFrameCount = mInputBytes / mFrameSize;
4264 mRsmpInBuffer = new int16_t[mFrameCount * mChannelCount];
4265
4266 if (mSampleRate != mReqSampleRate && mChannelCount < 3 && mReqChannelCount < 3)
4267 {
4268 int channelCount;
4269 // optmization: if mono to mono, use the resampler in stereo to stereo mode to avoid
4270 // stereo to mono post process as the resampler always outputs stereo.
4271 if (mChannelCount == 1 && mReqChannelCount == 2) {
4272 channelCount = 1;
4273 } else {
4274 channelCount = 2;
4275 }
4276 mResampler = AudioResampler::create(16, channelCount, mReqSampleRate);
4277 mResampler->setSampleRate(mSampleRate);
4278 mResampler->setVolume(AudioMixer::UNITY_GAIN, AudioMixer::UNITY_GAIN);
4279 mRsmpOutBuffer = new int32_t[mFrameCount * 2];
4280
4281 // optmization: if mono to mono, alter input frame count as if we were inputing stereo samples
4282 if (mChannelCount == 1 && mReqChannelCount == 1) {
4283 mFrameCount >>= 1;
4284 }
4285
4286 }
4287 mRsmpInIndex = mFrameCount;
4288}
4289
Eric Laurent47d0a922010-02-26 02:47:27 -08004290unsigned int AudioFlinger::RecordThread::getInputFramesLost()
4291{
Dima Zavin31f188892011-04-18 16:57:27 -07004292 return mInput->stream->get_input_frames_lost(mInput->stream);
Eric Laurent47d0a922010-02-26 02:47:27 -08004293}
4294
Eric Laurenta553c252009-07-17 12:17:14 -07004295// ----------------------------------------------------------------------------
4296
Eric Laurentddb78e72009-07-28 08:44:33 -07004297int AudioFlinger::openOutput(uint32_t *pDevices,
Eric Laurenta553c252009-07-17 12:17:14 -07004298 uint32_t *pSamplingRate,
4299 uint32_t *pFormat,
4300 uint32_t *pChannels,
4301 uint32_t *pLatencyMs,
4302 uint32_t flags)
4303{
4304 status_t status;
4305 PlaybackThread *thread = NULL;
4306 mHardwareStatus = AUDIO_HW_OUTPUT_OPEN;
4307 uint32_t samplingRate = pSamplingRate ? *pSamplingRate : 0;
4308 uint32_t format = pFormat ? *pFormat : 0;
4309 uint32_t channels = pChannels ? *pChannels : 0;
4310 uint32_t latency = pLatencyMs ? *pLatencyMs : 0;
Dima Zavin31f188892011-04-18 16:57:27 -07004311 audio_stream_out_t *outStream;
4312 audio_hw_device_t *outHwDev;
Eric Laurenta553c252009-07-17 12:17:14 -07004313
4314 LOGV("openOutput(), Device %x, SamplingRate %d, Format %d, Channels %x, flags %x",
4315 pDevices ? *pDevices : 0,
4316 samplingRate,
4317 format,
4318 channels,
4319 flags);
4320
4321 if (pDevices == NULL || *pDevices == 0) {
Eric Laurentddb78e72009-07-28 08:44:33 -07004322 return 0;
Eric Laurenta553c252009-07-17 12:17:14 -07004323 }
Dima Zavin31f188892011-04-18 16:57:27 -07004324
Eric Laurenta553c252009-07-17 12:17:14 -07004325 Mutex::Autolock _l(mLock);
4326
Dima Zavin31f188892011-04-18 16:57:27 -07004327 outHwDev = findSuitableHwDev_l(*pDevices);
4328 if (outHwDev == NULL)
4329 return 0;
4330
4331 status = outHwDev->open_output_stream(outHwDev, *pDevices, (int *)&format,
4332 &channels, &samplingRate, &outStream);
Eric Laurenta553c252009-07-17 12:17:14 -07004333 LOGV("openOutput() openOutputStream returned output %p, SamplingRate %d, Format %d, Channels %x, status %d",
Dima Zavin31f188892011-04-18 16:57:27 -07004334 outStream,
Eric Laurenta553c252009-07-17 12:17:14 -07004335 samplingRate,
4336 format,
4337 channels,
4338 status);
4339
4340 mHardwareStatus = AUDIO_HW_IDLE;
Dima Zavin31f188892011-04-18 16:57:27 -07004341 if (outStream != NULL) {
4342 AudioStreamOut *output = new AudioStreamOut(outHwDev, outStream);
Eric Laurentf3d6dd02010-11-18 08:40:16 -08004343 int id = nextUniqueId_l();
Dima Zavin31f188892011-04-18 16:57:27 -07004344
Dima Zavin24fc2fb2011-04-19 22:30:36 -07004345 if ((flags & AUDIO_POLICY_OUTPUT_FLAG_DIRECT) ||
4346 (format != AUDIO_FORMAT_PCM_16_BIT) ||
4347 (channels != AUDIO_CHANNEL_OUT_STEREO)) {
Eric Laurent65b65452010-06-01 23:49:17 -07004348 thread = new DirectOutputThread(this, output, id, *pDevices);
4349 LOGV("openOutput() created direct output: ID %d thread %p", id, thread);
Eric Laurenta553c252009-07-17 12:17:14 -07004350 } else {
Eric Laurent65b65452010-06-01 23:49:17 -07004351 thread = new MixerThread(this, output, id, *pDevices);
4352 LOGV("openOutput() created mixer output: ID %d thread %p", id, thread);
Eric Laurenta553c252009-07-17 12:17:14 -07004353 }
Eric Laurent65b65452010-06-01 23:49:17 -07004354 mPlaybackThreads.add(id, thread);
Eric Laurenta553c252009-07-17 12:17:14 -07004355
4356 if (pSamplingRate) *pSamplingRate = samplingRate;
4357 if (pFormat) *pFormat = format;
4358 if (pChannels) *pChannels = channels;
4359 if (pLatencyMs) *pLatencyMs = thread->latency();
Eric Laurent9cc489a2009-12-05 05:20:01 -08004360
Eric Laurenteb8f850d2010-05-14 03:26:45 -07004361 // notify client processes of the new output creation
4362 thread->audioConfigChanged_l(AudioSystem::OUTPUT_OPENED);
Eric Laurent65b65452010-06-01 23:49:17 -07004363 return id;
Eric Laurenta553c252009-07-17 12:17:14 -07004364 }
4365
Eric Laurent9cc489a2009-12-05 05:20:01 -08004366 return 0;
Eric Laurenta553c252009-07-17 12:17:14 -07004367}
4368
Eric Laurentddb78e72009-07-28 08:44:33 -07004369int AudioFlinger::openDuplicateOutput(int output1, int output2)
Eric Laurenta553c252009-07-17 12:17:14 -07004370{
4371 Mutex::Autolock _l(mLock);
Eric Laurentddb78e72009-07-28 08:44:33 -07004372 MixerThread *thread1 = checkMixerThread_l(output1);
4373 MixerThread *thread2 = checkMixerThread_l(output2);
Eric Laurenta553c252009-07-17 12:17:14 -07004374
Eric Laurentddb78e72009-07-28 08:44:33 -07004375 if (thread1 == NULL || thread2 == NULL) {
4376 LOGW("openDuplicateOutput() wrong output mixer type for output %d or %d", output1, output2);
4377 return 0;
Eric Laurenta553c252009-07-17 12:17:14 -07004378 }
4379
Eric Laurentf3d6dd02010-11-18 08:40:16 -08004380 int id = nextUniqueId_l();
Eric Laurent65b65452010-06-01 23:49:17 -07004381 DuplicatingThread *thread = new DuplicatingThread(this, thread1, id);
Eric Laurentddb78e72009-07-28 08:44:33 -07004382 thread->addOutputTrack(thread2);
Eric Laurent65b65452010-06-01 23:49:17 -07004383 mPlaybackThreads.add(id, thread);
Eric Laurenteb8f850d2010-05-14 03:26:45 -07004384 // notify client processes of the new output creation
4385 thread->audioConfigChanged_l(AudioSystem::OUTPUT_OPENED);
Eric Laurent65b65452010-06-01 23:49:17 -07004386 return id;
Eric Laurenta553c252009-07-17 12:17:14 -07004387}
4388
Eric Laurentddb78e72009-07-28 08:44:33 -07004389status_t AudioFlinger::closeOutput(int output)
Eric Laurenta553c252009-07-17 12:17:14 -07004390{
Eric Laurent49018a52009-08-04 08:37:05 -07004391 // keep strong reference on the playback thread so that
4392 // it is not destroyed while exit() is executed
4393 sp <PlaybackThread> thread;
Eric Laurenta553c252009-07-17 12:17:14 -07004394 {
4395 Mutex::Autolock _l(mLock);
4396 thread = checkPlaybackThread_l(output);
4397 if (thread == NULL) {
4398 return BAD_VALUE;
4399 }
4400
Eric Laurentddb78e72009-07-28 08:44:33 -07004401 LOGV("closeOutput() %d", output);
Eric Laurenta553c252009-07-17 12:17:14 -07004402
4403 if (thread->type() == PlaybackThread::MIXER) {
4404 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
Eric Laurentddb78e72009-07-28 08:44:33 -07004405 if (mPlaybackThreads.valueAt(i)->type() == PlaybackThread::DUPLICATING) {
4406 DuplicatingThread *dupThread = (DuplicatingThread *)mPlaybackThreads.valueAt(i).get();
Eric Laurent49018a52009-08-04 08:37:05 -07004407 dupThread->removeOutputTrack((MixerThread *)thread.get());
Eric Laurenta553c252009-07-17 12:17:14 -07004408 }
4409 }
4410 }
Eric Laurent296a0ec2009-09-15 07:10:12 -07004411 void *param2 = 0;
Eric Laurent49f02be2009-11-19 09:00:56 -08004412 audioConfigChanged_l(AudioSystem::OUTPUT_CLOSED, output, param2);
Eric Laurentddb78e72009-07-28 08:44:33 -07004413 mPlaybackThreads.removeItem(output);
Eric Laurenta553c252009-07-17 12:17:14 -07004414 }
4415 thread->exit();
4416
Eric Laurent49018a52009-08-04 08:37:05 -07004417 if (thread->type() != PlaybackThread::DUPLICATING) {
Dima Zavin31f188892011-04-18 16:57:27 -07004418 AudioStreamOut *out = thread->getOutput();
4419 out->hwDev->close_output_stream(out->hwDev, out->stream);
4420 delete out;
Eric Laurent49018a52009-08-04 08:37:05 -07004421 }
Eric Laurenta553c252009-07-17 12:17:14 -07004422 return NO_ERROR;
4423}
4424
Eric Laurentddb78e72009-07-28 08:44:33 -07004425status_t AudioFlinger::suspendOutput(int output)
Eric Laurenta553c252009-07-17 12:17:14 -07004426{
4427 Mutex::Autolock _l(mLock);
4428 PlaybackThread *thread = checkPlaybackThread_l(output);
4429
4430 if (thread == NULL) {
4431 return BAD_VALUE;
4432 }
4433
Eric Laurentddb78e72009-07-28 08:44:33 -07004434 LOGV("suspendOutput() %d", output);
Eric Laurenta553c252009-07-17 12:17:14 -07004435 thread->suspend();
4436
4437 return NO_ERROR;
4438}
4439
Eric Laurentddb78e72009-07-28 08:44:33 -07004440status_t AudioFlinger::restoreOutput(int output)
Eric Laurenta553c252009-07-17 12:17:14 -07004441{
4442 Mutex::Autolock _l(mLock);
4443 PlaybackThread *thread = checkPlaybackThread_l(output);
4444
4445 if (thread == NULL) {
4446 return BAD_VALUE;
4447 }
4448
Eric Laurentddb78e72009-07-28 08:44:33 -07004449 LOGV("restoreOutput() %d", output);
Eric Laurenta553c252009-07-17 12:17:14 -07004450
4451 thread->restore();
4452
4453 return NO_ERROR;
4454}
4455
Eric Laurentddb78e72009-07-28 08:44:33 -07004456int AudioFlinger::openInput(uint32_t *pDevices,
Eric Laurenta553c252009-07-17 12:17:14 -07004457 uint32_t *pSamplingRate,
4458 uint32_t *pFormat,
4459 uint32_t *pChannels,
4460 uint32_t acoustics)
4461{
4462 status_t status;
4463 RecordThread *thread = NULL;
4464 uint32_t samplingRate = pSamplingRate ? *pSamplingRate : 0;
4465 uint32_t format = pFormat ? *pFormat : 0;
4466 uint32_t channels = pChannels ? *pChannels : 0;
4467 uint32_t reqSamplingRate = samplingRate;
4468 uint32_t reqFormat = format;
4469 uint32_t reqChannels = channels;
Dima Zavin31f188892011-04-18 16:57:27 -07004470 audio_stream_in_t *inStream;
4471 audio_hw_device_t *inHwDev;
Eric Laurenta553c252009-07-17 12:17:14 -07004472
4473 if (pDevices == NULL || *pDevices == 0) {
Eric Laurentddb78e72009-07-28 08:44:33 -07004474 return 0;
Eric Laurenta553c252009-07-17 12:17:14 -07004475 }
Dima Zavin31f188892011-04-18 16:57:27 -07004476
Eric Laurenta553c252009-07-17 12:17:14 -07004477 Mutex::Autolock _l(mLock);
4478
Dima Zavin31f188892011-04-18 16:57:27 -07004479 inHwDev = findSuitableHwDev_l(*pDevices);
4480 if (inHwDev == NULL)
4481 return 0;
4482
4483 status = inHwDev->open_input_stream(inHwDev, *pDevices, (int *)&format,
4484 &channels, &samplingRate,
Dima Zavin24fc2fb2011-04-19 22:30:36 -07004485 (audio_in_acoustics_t)acoustics,
Dima Zavin31f188892011-04-18 16:57:27 -07004486 &inStream);
Eric Laurenta553c252009-07-17 12:17:14 -07004487 LOGV("openInput() openInputStream returned input %p, SamplingRate %d, Format %d, Channels %x, acoustics %x, status %d",
Dima Zavin31f188892011-04-18 16:57:27 -07004488 inStream,
Eric Laurenta553c252009-07-17 12:17:14 -07004489 samplingRate,
4490 format,
4491 channels,
4492 acoustics,
4493 status);
4494
4495 // If the input could not be opened with the requested parameters and we can handle the conversion internally,
4496 // try to open again with the proposed parameters. The AudioFlinger can resample the input and do mono to stereo
4497 // or stereo to mono conversions on 16 bit PCM inputs.
Dima Zavin31f188892011-04-18 16:57:27 -07004498 if (inStream == NULL && status == BAD_VALUE &&
Dima Zavin24fc2fb2011-04-19 22:30:36 -07004499 reqFormat == format && format == AUDIO_FORMAT_PCM_16_BIT &&
Eric Laurenta553c252009-07-17 12:17:14 -07004500 (samplingRate <= 2 * reqSamplingRate) &&
Dima Zavin24fc2fb2011-04-19 22:30:36 -07004501 (popcount(channels) < 3) && (popcount(reqChannels) < 3)) {
Eric Laurenta553c252009-07-17 12:17:14 -07004502 LOGV("openInput() reopening with proposed sampling rate and channels");
Dima Zavin31f188892011-04-18 16:57:27 -07004503 status = inHwDev->open_input_stream(inHwDev, *pDevices, (int *)&format,
4504 &channels, &samplingRate,
Dima Zavin24fc2fb2011-04-19 22:30:36 -07004505 (audio_in_acoustics_t)acoustics,
Dima Zavin31f188892011-04-18 16:57:27 -07004506 &inStream);
Eric Laurenta553c252009-07-17 12:17:14 -07004507 }
4508
Dima Zavin31f188892011-04-18 16:57:27 -07004509 if (inStream != NULL) {
4510 AudioStreamIn *input = new AudioStreamIn(inHwDev, inStream);
4511
Eric Laurentf3d6dd02010-11-18 08:40:16 -08004512 int id = nextUniqueId_l();
Eric Laurenta553c252009-07-17 12:17:14 -07004513 // Start record thread
Eric Laurent65b65452010-06-01 23:49:17 -07004514 thread = new RecordThread(this, input, reqSamplingRate, reqChannels, id);
4515 mRecordThreads.add(id, thread);
4516 LOGV("openInput() created record thread: ID %d thread %p", id, thread);
Eric Laurenta553c252009-07-17 12:17:14 -07004517 if (pSamplingRate) *pSamplingRate = reqSamplingRate;
4518 if (pFormat) *pFormat = format;
4519 if (pChannels) *pChannels = reqChannels;
4520
Dima Zavin31f188892011-04-18 16:57:27 -07004521 input->stream->common.standby(&input->stream->common);
Eric Laurent9cc489a2009-12-05 05:20:01 -08004522
Eric Laurenteb8f850d2010-05-14 03:26:45 -07004523 // notify client processes of the new input creation
4524 thread->audioConfigChanged_l(AudioSystem::INPUT_OPENED);
Eric Laurent65b65452010-06-01 23:49:17 -07004525 return id;
Eric Laurenta553c252009-07-17 12:17:14 -07004526 }
4527
Eric Laurent9cc489a2009-12-05 05:20:01 -08004528 return 0;
Eric Laurenta553c252009-07-17 12:17:14 -07004529}
4530
Eric Laurentddb78e72009-07-28 08:44:33 -07004531status_t AudioFlinger::closeInput(int input)
Eric Laurenta553c252009-07-17 12:17:14 -07004532{
Eric Laurent49018a52009-08-04 08:37:05 -07004533 // keep strong reference on the record thread so that
4534 // it is not destroyed while exit() is executed
4535 sp <RecordThread> thread;
Eric Laurenta553c252009-07-17 12:17:14 -07004536 {
4537 Mutex::Autolock _l(mLock);
4538 thread = checkRecordThread_l(input);
4539 if (thread == NULL) {
4540 return BAD_VALUE;
4541 }
4542
Eric Laurentddb78e72009-07-28 08:44:33 -07004543 LOGV("closeInput() %d", input);
Eric Laurent296a0ec2009-09-15 07:10:12 -07004544 void *param2 = 0;
Eric Laurent49f02be2009-11-19 09:00:56 -08004545 audioConfigChanged_l(AudioSystem::INPUT_CLOSED, input, param2);
Eric Laurentddb78e72009-07-28 08:44:33 -07004546 mRecordThreads.removeItem(input);
Eric Laurenta553c252009-07-17 12:17:14 -07004547 }
4548 thread->exit();
4549
Dima Zavin31f188892011-04-18 16:57:27 -07004550 AudioStreamIn *in = thread->getInput();
4551 in->hwDev->close_input_stream(in->hwDev, in->stream);
4552 delete in;
Eric Laurent49018a52009-08-04 08:37:05 -07004553
Eric Laurenta553c252009-07-17 12:17:14 -07004554 return NO_ERROR;
4555}
4556
Eric Laurentddb78e72009-07-28 08:44:33 -07004557status_t AudioFlinger::setStreamOutput(uint32_t stream, int output)
Eric Laurenta553c252009-07-17 12:17:14 -07004558{
4559 Mutex::Autolock _l(mLock);
4560 MixerThread *dstThread = checkMixerThread_l(output);
4561 if (dstThread == NULL) {
Eric Laurentddb78e72009-07-28 08:44:33 -07004562 LOGW("setStreamOutput() bad output id %d", output);
Eric Laurenta553c252009-07-17 12:17:14 -07004563 return BAD_VALUE;
4564 }
4565
Eric Laurentddb78e72009-07-28 08:44:33 -07004566 LOGV("setStreamOutput() stream %d to output %d", stream, output);
Eric Laurenteb8f850d2010-05-14 03:26:45 -07004567 audioConfigChanged_l(AudioSystem::STREAM_CONFIG_CHANGED, output, &stream);
Eric Laurenta553c252009-07-17 12:17:14 -07004568
4569 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
Eric Laurentddb78e72009-07-28 08:44:33 -07004570 PlaybackThread *thread = mPlaybackThreads.valueAt(i).get();
Eric Laurenta553c252009-07-17 12:17:14 -07004571 if (thread != dstThread &&
4572 thread->type() != PlaybackThread::DIRECT) {
4573 MixerThread *srcThread = (MixerThread *)thread;
Eric Laurenteb8f850d2010-05-14 03:26:45 -07004574 srcThread->invalidateTracks(stream);
Eric Laurenta553c252009-07-17 12:17:14 -07004575 }
Eric Laurent8ed6ed02010-07-13 04:45:46 -07004576 }
Eric Laurentd069f322009-09-01 05:56:26 -07004577
Eric Laurenta553c252009-07-17 12:17:14 -07004578 return NO_ERROR;
4579}
4580
Eric Laurent65b65452010-06-01 23:49:17 -07004581
4582int AudioFlinger::newAudioSessionId()
4583{
Eric Laurentf3d6dd02010-11-18 08:40:16 -08004584 AutoMutex _l(mLock);
4585 return nextUniqueId_l();
Eric Laurent65b65452010-06-01 23:49:17 -07004586}
4587
Eric Laurenta553c252009-07-17 12:17:14 -07004588// checkPlaybackThread_l() must be called with AudioFlinger::mLock held
Eric Laurentddb78e72009-07-28 08:44:33 -07004589AudioFlinger::PlaybackThread *AudioFlinger::checkPlaybackThread_l(int output) const
Eric Laurenta553c252009-07-17 12:17:14 -07004590{
4591 PlaybackThread *thread = NULL;
Eric Laurentddb78e72009-07-28 08:44:33 -07004592 if (mPlaybackThreads.indexOfKey(output) >= 0) {
4593 thread = (PlaybackThread *)mPlaybackThreads.valueFor(output).get();
Eric Laurenta553c252009-07-17 12:17:14 -07004594 }
Eric Laurenta553c252009-07-17 12:17:14 -07004595 return thread;
4596}
4597
4598// checkMixerThread_l() must be called with AudioFlinger::mLock held
Eric Laurentddb78e72009-07-28 08:44:33 -07004599AudioFlinger::MixerThread *AudioFlinger::checkMixerThread_l(int output) const
Eric Laurenta553c252009-07-17 12:17:14 -07004600{
4601 PlaybackThread *thread = checkPlaybackThread_l(output);
4602 if (thread != NULL) {
4603 if (thread->type() == PlaybackThread::DIRECT) {
4604 thread = NULL;
4605 }
4606 }
4607 return (MixerThread *)thread;
4608}
4609
4610// checkRecordThread_l() must be called with AudioFlinger::mLock held
Eric Laurentddb78e72009-07-28 08:44:33 -07004611AudioFlinger::RecordThread *AudioFlinger::checkRecordThread_l(int input) const
Eric Laurenta553c252009-07-17 12:17:14 -07004612{
4613 RecordThread *thread = NULL;
Eric Laurentddb78e72009-07-28 08:44:33 -07004614 if (mRecordThreads.indexOfKey(input) >= 0) {
4615 thread = (RecordThread *)mRecordThreads.valueFor(input).get();
Eric Laurenta553c252009-07-17 12:17:14 -07004616 }
Eric Laurenta553c252009-07-17 12:17:14 -07004617 return thread;
4618}
4619
Eric Laurentf3d6dd02010-11-18 08:40:16 -08004620// nextUniqueId_l() must be called with AudioFlinger::mLock held
4621int AudioFlinger::nextUniqueId_l()
Eric Laurent65b65452010-06-01 23:49:17 -07004622{
Eric Laurentf3d6dd02010-11-18 08:40:16 -08004623 return mNextUniqueId++;
Eric Laurent65b65452010-06-01 23:49:17 -07004624}
4625
4626// ----------------------------------------------------------------------------
4627// Effect management
4628// ----------------------------------------------------------------------------
4629
4630
4631status_t AudioFlinger::loadEffectLibrary(const char *libPath, int *handle)
4632{
Eric Laurent8ed6ed02010-07-13 04:45:46 -07004633 // check calling permissions
4634 if (!settingsAllowed()) {
4635 return PERMISSION_DENIED;
4636 }
4637 // only allow libraries loaded from /system/lib/soundfx for now
4638 if (strncmp(gEffectLibPath, libPath, strlen(gEffectLibPath)) != 0) {
4639 return PERMISSION_DENIED;
4640 }
4641
Eric Laurent65b65452010-06-01 23:49:17 -07004642 Mutex::Autolock _l(mLock);
4643 return EffectLoadLibrary(libPath, handle);
4644}
4645
4646status_t AudioFlinger::unloadEffectLibrary(int handle)
4647{
Eric Laurent8ed6ed02010-07-13 04:45:46 -07004648 // check calling permissions
4649 if (!settingsAllowed()) {
4650 return PERMISSION_DENIED;
4651 }
4652
Eric Laurent65b65452010-06-01 23:49:17 -07004653 Mutex::Autolock _l(mLock);
4654 return EffectUnloadLibrary(handle);
4655}
4656
4657status_t AudioFlinger::queryNumberEffects(uint32_t *numEffects)
4658{
4659 Mutex::Autolock _l(mLock);
4660 return EffectQueryNumberEffects(numEffects);
4661}
4662
Eric Laurent53334cd2010-06-23 17:38:20 -07004663status_t AudioFlinger::queryEffect(uint32_t index, effect_descriptor_t *descriptor)
Eric Laurent65b65452010-06-01 23:49:17 -07004664{
4665 Mutex::Autolock _l(mLock);
Eric Laurent53334cd2010-06-23 17:38:20 -07004666 return EffectQueryEffect(index, descriptor);
Eric Laurent65b65452010-06-01 23:49:17 -07004667}
4668
4669status_t AudioFlinger::getEffectDescriptor(effect_uuid_t *pUuid, effect_descriptor_t *descriptor)
4670{
4671 Mutex::Autolock _l(mLock);
4672 return EffectGetDescriptor(pUuid, descriptor);
4673}
4674
Eric Laurentdf9b81c2010-07-02 08:12:41 -07004675
4676// this UUID must match the one defined in media/libeffects/EffectVisualizer.cpp
4677static const effect_uuid_t VISUALIZATION_UUID_ =
4678 {0xd069d9e0, 0x8329, 0x11df, 0x9168, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}};
4679
Eric Laurent65b65452010-06-01 23:49:17 -07004680sp<IEffect> AudioFlinger::createEffect(pid_t pid,
4681 effect_descriptor_t *pDesc,
4682 const sp<IEffectClient>& effectClient,
4683 int32_t priority,
4684 int output,
4685 int sessionId,
4686 status_t *status,
4687 int *id,
4688 int *enabled)
4689{
4690 status_t lStatus = NO_ERROR;
4691 sp<EffectHandle> handle;
4692 effect_interface_t itfe;
4693 effect_descriptor_t desc;
4694 sp<Client> client;
4695 wp<Client> wclient;
4696
Eric Laurent8ed6ed02010-07-13 04:45:46 -07004697 LOGV("createEffect pid %d, client %p, priority %d, sessionId %d, output %d",
4698 pid, effectClient.get(), priority, sessionId, output);
Eric Laurent65b65452010-06-01 23:49:17 -07004699
4700 if (pDesc == NULL) {
4701 lStatus = BAD_VALUE;
4702 goto Exit;
4703 }
4704
Eric Laurent98c92592010-09-23 16:10:16 -07004705 // check audio settings permission for global effects
Dima Zavin24fc2fb2011-04-19 22:30:36 -07004706 if (sessionId == AUDIO_SESSION_OUTPUT_MIX && !settingsAllowed()) {
Eric Laurent98c92592010-09-23 16:10:16 -07004707 lStatus = PERMISSION_DENIED;
4708 goto Exit;
4709 }
4710
Dima Zavin24fc2fb2011-04-19 22:30:36 -07004711 // Session AUDIO_SESSION_OUTPUT_STAGE is reserved for output stage effects
Eric Laurent98c92592010-09-23 16:10:16 -07004712 // that can only be created by audio policy manager (running in same process)
Dima Zavin24fc2fb2011-04-19 22:30:36 -07004713 if (sessionId == AUDIO_SESSION_OUTPUT_STAGE && getpid() != pid) {
Eric Laurent98c92592010-09-23 16:10:16 -07004714 lStatus = PERMISSION_DENIED;
4715 goto Exit;
4716 }
4717
4718 // check recording permission for visualizer
4719 if ((memcmp(&pDesc->type, SL_IID_VISUALIZATION, sizeof(effect_uuid_t)) == 0 ||
4720 memcmp(&pDesc->uuid, &VISUALIZATION_UUID_, sizeof(effect_uuid_t)) == 0) &&
4721 !recordingAllowed()) {
4722 lStatus = PERMISSION_DENIED;
4723 goto Exit;
4724 }
4725
4726 if (output == 0) {
Dima Zavin24fc2fb2011-04-19 22:30:36 -07004727 if (sessionId == AUDIO_SESSION_OUTPUT_STAGE) {
Eric Laurent98c92592010-09-23 16:10:16 -07004728 // output must be specified by AudioPolicyManager when using session
Dima Zavin24fc2fb2011-04-19 22:30:36 -07004729 // AUDIO_SESSION_OUTPUT_STAGE
Eric Laurent98c92592010-09-23 16:10:16 -07004730 lStatus = BAD_VALUE;
4731 goto Exit;
Dima Zavin24fc2fb2011-04-19 22:30:36 -07004732 } else if (sessionId == AUDIO_SESSION_OUTPUT_MIX) {
Eric Laurent98c92592010-09-23 16:10:16 -07004733 // if the output returned by getOutputForEffect() is removed before we lock the
4734 // mutex below, the call to checkPlaybackThread_l(output) below will detect it
4735 // and we will exit safely
4736 output = AudioSystem::getOutputForEffect(&desc);
4737 }
4738 }
4739
Eric Laurent65b65452010-06-01 23:49:17 -07004740 {
4741 Mutex::Autolock _l(mLock);
4742
Eric Laurentdf9b81c2010-07-02 08:12:41 -07004743
Eric Laurent65b65452010-06-01 23:49:17 -07004744 if (!EffectIsNullUuid(&pDesc->uuid)) {
4745 // if uuid is specified, request effect descriptor
4746 lStatus = EffectGetDescriptor(&pDesc->uuid, &desc);
4747 if (lStatus < 0) {
4748 LOGW("createEffect() error %d from EffectGetDescriptor", lStatus);
4749 goto Exit;
4750 }
4751 } else {
4752 // if uuid is not specified, look for an available implementation
4753 // of the required type in effect factory
4754 if (EffectIsNullUuid(&pDesc->type)) {
4755 LOGW("createEffect() no effect type");
4756 lStatus = BAD_VALUE;
4757 goto Exit;
4758 }
4759 uint32_t numEffects = 0;
4760 effect_descriptor_t d;
4761 bool found = false;
4762
4763 lStatus = EffectQueryNumberEffects(&numEffects);
4764 if (lStatus < 0) {
4765 LOGW("createEffect() error %d from EffectQueryNumberEffects", lStatus);
4766 goto Exit;
4767 }
Eric Laurent53334cd2010-06-23 17:38:20 -07004768 for (uint32_t i = 0; i < numEffects; i++) {
4769 lStatus = EffectQueryEffect(i, &desc);
Eric Laurent65b65452010-06-01 23:49:17 -07004770 if (lStatus < 0) {
Eric Laurent53334cd2010-06-23 17:38:20 -07004771 LOGW("createEffect() error %d from EffectQueryEffect", lStatus);
Eric Laurent65b65452010-06-01 23:49:17 -07004772 continue;
4773 }
4774 if (memcmp(&desc.type, &pDesc->type, sizeof(effect_uuid_t)) == 0) {
4775 // If matching type found save effect descriptor. If the session is
4776 // 0 and the effect is not auxiliary, continue enumeration in case
4777 // an auxiliary version of this effect type is available
4778 found = true;
4779 memcpy(&d, &desc, sizeof(effect_descriptor_t));
Dima Zavin24fc2fb2011-04-19 22:30:36 -07004780 if (sessionId != AUDIO_SESSION_OUTPUT_MIX ||
Eric Laurent65b65452010-06-01 23:49:17 -07004781 (desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
4782 break;
4783 }
4784 }
4785 }
4786 if (!found) {
4787 lStatus = BAD_VALUE;
4788 LOGW("createEffect() effect not found");
4789 goto Exit;
4790 }
4791 // For same effect type, chose auxiliary version over insert version if
4792 // connect to output mix (Compliance to OpenSL ES)
Dima Zavin24fc2fb2011-04-19 22:30:36 -07004793 if (sessionId == AUDIO_SESSION_OUTPUT_MIX &&
Eric Laurent65b65452010-06-01 23:49:17 -07004794 (d.flags & EFFECT_FLAG_TYPE_MASK) != EFFECT_FLAG_TYPE_AUXILIARY) {
4795 memcpy(&desc, &d, sizeof(effect_descriptor_t));
4796 }
4797 }
4798
4799 // Do not allow auxiliary effects on a session different from 0 (output mix)
Dima Zavin24fc2fb2011-04-19 22:30:36 -07004800 if (sessionId != AUDIO_SESSION_OUTPUT_MIX &&
Eric Laurent65b65452010-06-01 23:49:17 -07004801 (desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
4802 lStatus = INVALID_OPERATION;
4803 goto Exit;
4804 }
4805
4806 // return effect descriptor
4807 memcpy(pDesc, &desc, sizeof(effect_descriptor_t));
4808
4809 // If output is not specified try to find a matching audio session ID in one of the
4810 // output threads.
Eric Laurent98c92592010-09-23 16:10:16 -07004811 // If output is 0 here, sessionId is neither SESSION_OUTPUT_STAGE nor SESSION_OUTPUT_MIX
4812 // because of code checking output when entering the function.
Eric Laurent65b65452010-06-01 23:49:17 -07004813 if (output == 0) {
Eric Laurent98c92592010-09-23 16:10:16 -07004814 // look for the thread where the specified audio session is present
4815 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
4816 if (mPlaybackThreads.valueAt(i)->hasAudioSession(sessionId) != 0) {
4817 output = mPlaybackThreads.keyAt(i);
4818 break;
Eric Laurent493941b2010-07-28 01:32:47 -07004819 }
Eric Laurent65b65452010-06-01 23:49:17 -07004820 }
Eric Laurent98c92592010-09-23 16:10:16 -07004821 // If no output thread contains the requested session ID, default to
4822 // first output. The effect chain will be moved to the correct output
4823 // thread when a track with the same session ID is created
4824 if (output == 0 && mPlaybackThreads.size()) {
4825 output = mPlaybackThreads.keyAt(0);
4826 }
Eric Laurent65b65452010-06-01 23:49:17 -07004827 }
Eric Laurent98c92592010-09-23 16:10:16 -07004828 LOGV("createEffect() got output %d for effect %s", output, desc.name);
Eric Laurent65b65452010-06-01 23:49:17 -07004829 PlaybackThread *thread = checkPlaybackThread_l(output);
4830 if (thread == NULL) {
Eric Laurent8ed6ed02010-07-13 04:45:46 -07004831 LOGE("createEffect() unknown output thread");
Eric Laurent65b65452010-06-01 23:49:17 -07004832 lStatus = BAD_VALUE;
4833 goto Exit;
4834 }
4835
Eric Laurent98c92592010-09-23 16:10:16 -07004836 // TODO: allow attachment of effect to inputs
4837
Eric Laurent65b65452010-06-01 23:49:17 -07004838 wclient = mClients.valueFor(pid);
4839
4840 if (wclient != NULL) {
4841 client = wclient.promote();
4842 } else {
4843 client = new Client(this, pid);
4844 mClients.add(pid, client);
4845 }
4846
4847 // create effect on selected output trhead
Eric Laurent8ed6ed02010-07-13 04:45:46 -07004848 handle = thread->createEffect_l(client, effectClient, priority, sessionId,
4849 &desc, enabled, &lStatus);
Eric Laurent65b65452010-06-01 23:49:17 -07004850 if (handle != 0 && id != NULL) {
4851 *id = handle->id();
4852 }
4853 }
4854
4855Exit:
4856 if(status) {
4857 *status = lStatus;
4858 }
4859 return handle;
4860}
4861
Eric Laurent8ed6ed02010-07-13 04:45:46 -07004862status_t AudioFlinger::moveEffects(int session, int srcOutput, int dstOutput)
4863{
4864 LOGV("moveEffects() session %d, srcOutput %d, dstOutput %d",
4865 session, srcOutput, dstOutput);
4866 Mutex::Autolock _l(mLock);
4867 if (srcOutput == dstOutput) {
4868 LOGW("moveEffects() same dst and src outputs %d", dstOutput);
4869 return NO_ERROR;
Eric Laurent53334cd2010-06-23 17:38:20 -07004870 }
Eric Laurent8ed6ed02010-07-13 04:45:46 -07004871 PlaybackThread *srcThread = checkPlaybackThread_l(srcOutput);
4872 if (srcThread == NULL) {
4873 LOGW("moveEffects() bad srcOutput %d", srcOutput);
4874 return BAD_VALUE;
Eric Laurent53334cd2010-06-23 17:38:20 -07004875 }
Eric Laurent8ed6ed02010-07-13 04:45:46 -07004876 PlaybackThread *dstThread = checkPlaybackThread_l(dstOutput);
4877 if (dstThread == NULL) {
4878 LOGW("moveEffects() bad dstOutput %d", dstOutput);
4879 return BAD_VALUE;
4880 }
4881
4882 Mutex::Autolock _dl(dstThread->mLock);
4883 Mutex::Autolock _sl(srcThread->mLock);
Eric Laurent493941b2010-07-28 01:32:47 -07004884 moveEffectChain_l(session, srcThread, dstThread, false);
Eric Laurent8ed6ed02010-07-13 04:45:46 -07004885
Eric Laurent53334cd2010-06-23 17:38:20 -07004886 return NO_ERROR;
4887}
4888
Eric Laurent8ed6ed02010-07-13 04:45:46 -07004889// moveEffectChain_l mustbe called with both srcThread and dstThread mLocks held
4890status_t AudioFlinger::moveEffectChain_l(int session,
4891 AudioFlinger::PlaybackThread *srcThread,
Eric Laurent493941b2010-07-28 01:32:47 -07004892 AudioFlinger::PlaybackThread *dstThread,
4893 bool reRegister)
Eric Laurent8ed6ed02010-07-13 04:45:46 -07004894{
4895 LOGV("moveEffectChain_l() session %d from thread %p to thread %p",
4896 session, srcThread, dstThread);
4897
4898 sp<EffectChain> chain = srcThread->getEffectChain_l(session);
4899 if (chain == 0) {
4900 LOGW("moveEffectChain_l() effect chain for session %d not on source thread %p",
4901 session, srcThread);
4902 return INVALID_OPERATION;
4903 }
4904
Eric Laurent493941b2010-07-28 01:32:47 -07004905 // remove chain first. This is useful only if reconfiguring effect chain on same output thread,
Eric Laurent8ed6ed02010-07-13 04:45:46 -07004906 // so that a new chain is created with correct parameters when first effect is added. This is
4907 // otherwise unecessary as removeEffect_l() will remove the chain when last effect is
4908 // removed.
4909 srcThread->removeEffectChain_l(chain);
4910
4911 // transfer all effects one by one so that new effect chain is created on new thread with
4912 // correct buffer sizes and audio parameters and effect engines reconfigured accordingly
Eric Laurent493941b2010-07-28 01:32:47 -07004913 int dstOutput = dstThread->id();
4914 sp<EffectChain> dstChain;
4915 uint32_t strategy;
Eric Laurent8ed6ed02010-07-13 04:45:46 -07004916 sp<EffectModule> effect = chain->getEffectFromId_l(0);
4917 while (effect != 0) {
4918 srcThread->removeEffect_l(effect);
4919 dstThread->addEffect_l(effect);
Eric Laurent493941b2010-07-28 01:32:47 -07004920 // if the move request is not received from audio policy manager, the effect must be
4921 // re-registered with the new strategy and output
4922 if (dstChain == 0) {
4923 dstChain = effect->chain().promote();
4924 if (dstChain == 0) {
4925 LOGW("moveEffectChain_l() cannot get chain from effect %p", effect.get());
4926 srcThread->addEffect_l(effect);
4927 return NO_INIT;
4928 }
4929 strategy = dstChain->strategy();
4930 }
4931 if (reRegister) {
4932 AudioSystem::unregisterEffect(effect->id());
4933 AudioSystem::registerEffect(&effect->desc(),
4934 dstOutput,
4935 strategy,
4936 session,
4937 effect->id());
4938 }
Eric Laurent8ed6ed02010-07-13 04:45:46 -07004939 effect = chain->getEffectFromId_l(0);
4940 }
4941
4942 return NO_ERROR;
Eric Laurent53334cd2010-06-23 17:38:20 -07004943}
4944
Eric Laurent65b65452010-06-01 23:49:17 -07004945// PlaybackThread::createEffect_l() must be called with AudioFlinger::mLock held
4946sp<AudioFlinger::EffectHandle> AudioFlinger::PlaybackThread::createEffect_l(
4947 const sp<AudioFlinger::Client>& client,
4948 const sp<IEffectClient>& effectClient,
4949 int32_t priority,
4950 int sessionId,
4951 effect_descriptor_t *desc,
4952 int *enabled,
4953 status_t *status
4954 )
4955{
4956 sp<EffectModule> effect;
4957 sp<EffectHandle> handle;
4958 status_t lStatus;
4959 sp<Track> track;
4960 sp<EffectChain> chain;
Eric Laurent8ed6ed02010-07-13 04:45:46 -07004961 bool chainCreated = false;
Eric Laurent65b65452010-06-01 23:49:17 -07004962 bool effectCreated = false;
Eric Laurent53334cd2010-06-23 17:38:20 -07004963 bool effectRegistered = false;
Eric Laurent65b65452010-06-01 23:49:17 -07004964
4965 if (mOutput == 0) {
4966 LOGW("createEffect_l() Audio driver not initialized.");
4967 lStatus = NO_INIT;
4968 goto Exit;
4969 }
4970
4971 // Do not allow auxiliary effect on session other than 0
4972 if ((desc->flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY &&
Dima Zavin24fc2fb2011-04-19 22:30:36 -07004973 sessionId != AUDIO_SESSION_OUTPUT_MIX) {
Eric Laurent8ed6ed02010-07-13 04:45:46 -07004974 LOGW("createEffect_l() Cannot add auxiliary effect %s to session %d",
4975 desc->name, sessionId);
Eric Laurent65b65452010-06-01 23:49:17 -07004976 lStatus = BAD_VALUE;
4977 goto Exit;
4978 }
4979
4980 // Do not allow effects with session ID 0 on direct output or duplicating threads
4981 // TODO: add rule for hw accelerated effects on direct outputs with non PCM format
Dima Zavin24fc2fb2011-04-19 22:30:36 -07004982 if (sessionId == AUDIO_SESSION_OUTPUT_MIX && mType != MIXER) {
Eric Laurent8ed6ed02010-07-13 04:45:46 -07004983 LOGW("createEffect_l() Cannot add auxiliary effect %s to session %d",
4984 desc->name, sessionId);
Eric Laurent65b65452010-06-01 23:49:17 -07004985 lStatus = BAD_VALUE;
4986 goto Exit;
4987 }
4988
4989 LOGV("createEffect_l() thread %p effect %s on session %d", this, desc->name, sessionId);
4990
4991 { // scope for mLock
4992 Mutex::Autolock _l(mLock);
4993
4994 // check for existing effect chain with the requested audio session
4995 chain = getEffectChain_l(sessionId);
4996 if (chain == 0) {
4997 // create a new chain for this session
4998 LOGV("createEffect_l() new effect chain for session %d", sessionId);
4999 chain = new EffectChain(this, sessionId);
5000 addEffectChain_l(chain);
Eric Laurent8ed6ed02010-07-13 04:45:46 -07005001 chain->setStrategy(getStrategyForSession_l(sessionId));
5002 chainCreated = true;
Eric Laurent65b65452010-06-01 23:49:17 -07005003 } else {
Eric Laurent76c40f72010-07-15 12:50:15 -07005004 effect = chain->getEffectFromDesc_l(desc);
Eric Laurent65b65452010-06-01 23:49:17 -07005005 }
5006
5007 LOGV("createEffect_l() got effect %p on chain %p", effect == 0 ? 0 : effect.get(), chain.get());
5008
5009 if (effect == 0) {
Eric Laurentf3d6dd02010-11-18 08:40:16 -08005010 int id = mAudioFlinger->nextUniqueId_l();
Eric Laurent53334cd2010-06-23 17:38:20 -07005011 // Check CPU and memory usage
Eric Laurent8ed6ed02010-07-13 04:45:46 -07005012 lStatus = AudioSystem::registerEffect(desc, mId, chain->strategy(), sessionId, id);
Eric Laurent53334cd2010-06-23 17:38:20 -07005013 if (lStatus != NO_ERROR) {
5014 goto Exit;
5015 }
5016 effectRegistered = true;
Eric Laurent65b65452010-06-01 23:49:17 -07005017 // create a new effect module if none present in the chain
Eric Laurent8ed6ed02010-07-13 04:45:46 -07005018 effect = new EffectModule(this, chain, desc, id, sessionId);
Eric Laurent65b65452010-06-01 23:49:17 -07005019 lStatus = effect->status();
5020 if (lStatus != NO_ERROR) {
5021 goto Exit;
5022 }
Eric Laurent76c40f72010-07-15 12:50:15 -07005023 lStatus = chain->addEffect_l(effect);
Eric Laurent65b65452010-06-01 23:49:17 -07005024 if (lStatus != NO_ERROR) {
5025 goto Exit;
5026 }
Eric Laurent53334cd2010-06-23 17:38:20 -07005027 effectCreated = true;
Eric Laurent65b65452010-06-01 23:49:17 -07005028
5029 effect->setDevice(mDevice);
Eric Laurent53334cd2010-06-23 17:38:20 -07005030 effect->setMode(mAudioFlinger->getMode());
Eric Laurent65b65452010-06-01 23:49:17 -07005031 }
5032 // create effect handle and connect it to effect module
5033 handle = new EffectHandle(effect, client, effectClient, priority);
5034 lStatus = effect->addHandle(handle);
5035 if (enabled) {
5036 *enabled = (int)effect->isEnabled();
5037 }
5038 }
5039
5040Exit:
5041 if (lStatus != NO_ERROR && lStatus != ALREADY_EXISTS) {
Eric Laurent8ed6ed02010-07-13 04:45:46 -07005042 Mutex::Autolock _l(mLock);
Eric Laurent53334cd2010-06-23 17:38:20 -07005043 if (effectCreated) {
Eric Laurent8ed6ed02010-07-13 04:45:46 -07005044 chain->removeEffect_l(effect);
Eric Laurent65b65452010-06-01 23:49:17 -07005045 }
Eric Laurent53334cd2010-06-23 17:38:20 -07005046 if (effectRegistered) {
Eric Laurent8ed6ed02010-07-13 04:45:46 -07005047 AudioSystem::unregisterEffect(effect->id());
5048 }
5049 if (chainCreated) {
5050 removeEffectChain_l(chain);
Eric Laurent53334cd2010-06-23 17:38:20 -07005051 }
Eric Laurent65b65452010-06-01 23:49:17 -07005052 handle.clear();
5053 }
5054
5055 if(status) {
5056 *status = lStatus;
5057 }
5058 return handle;
5059}
5060
Eric Laurent8ed6ed02010-07-13 04:45:46 -07005061// PlaybackThread::addEffect_l() must be called with AudioFlinger::mLock and
5062// PlaybackThread::mLock held
5063status_t AudioFlinger::PlaybackThread::addEffect_l(const sp<EffectModule>& effect)
5064{
5065 // check for existing effect chain with the requested audio session
5066 int sessionId = effect->sessionId();
5067 sp<EffectChain> chain = getEffectChain_l(sessionId);
5068 bool chainCreated = false;
5069
5070 if (chain == 0) {
5071 // create a new chain for this session
5072 LOGV("addEffect_l() new effect chain for session %d", sessionId);
5073 chain = new EffectChain(this, sessionId);
5074 addEffectChain_l(chain);
5075 chain->setStrategy(getStrategyForSession_l(sessionId));
5076 chainCreated = true;
5077 }
5078 LOGV("addEffect_l() %p chain %p effect %p", this, chain.get(), effect.get());
5079
5080 if (chain->getEffectFromId_l(effect->id()) != 0) {
5081 LOGW("addEffect_l() %p effect %s already present in chain %p",
5082 this, effect->desc().name, chain.get());
5083 return BAD_VALUE;
5084 }
5085
5086 status_t status = chain->addEffect_l(effect);
5087 if (status != NO_ERROR) {
5088 if (chainCreated) {
5089 removeEffectChain_l(chain);
5090 }
5091 return status;
5092 }
5093
5094 effect->setDevice(mDevice);
5095 effect->setMode(mAudioFlinger->getMode());
5096 return NO_ERROR;
5097}
5098
5099void AudioFlinger::PlaybackThread::removeEffect_l(const sp<EffectModule>& effect) {
5100
5101 LOGV("removeEffect_l() %p effect %p", this, effect.get());
Eric Laurent53334cd2010-06-23 17:38:20 -07005102 effect_descriptor_t desc = effect->desc();
Eric Laurent8ed6ed02010-07-13 04:45:46 -07005103 if ((desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
5104 detachAuxEffect_l(effect->id());
5105 }
5106
5107 sp<EffectChain> chain = effect->chain().promote();
5108 if (chain != 0) {
5109 // remove effect chain if removing last effect
5110 if (chain->removeEffect_l(effect) == 0) {
5111 removeEffectChain_l(chain);
5112 }
5113 } else {
5114 LOGW("removeEffect_l() %p cannot promote chain for effect %p", this, effect.get());
5115 }
5116}
5117
5118void AudioFlinger::PlaybackThread::disconnectEffect(const sp<EffectModule>& effect,
5119 const wp<EffectHandle>& handle) {
Eric Laurent53334cd2010-06-23 17:38:20 -07005120 Mutex::Autolock _l(mLock);
Eric Laurent8ed6ed02010-07-13 04:45:46 -07005121 LOGV("disconnectEffect() %p effect %p", this, effect.get());
Eric Laurent53334cd2010-06-23 17:38:20 -07005122 // delete the effect module if removing last handle on it
5123 if (effect->removeHandle(handle) == 0) {
Eric Laurent8ed6ed02010-07-13 04:45:46 -07005124 removeEffect_l(effect);
5125 AudioSystem::unregisterEffect(effect->id());
Eric Laurent53334cd2010-06-23 17:38:20 -07005126 }
5127}
5128
Eric Laurent65b65452010-06-01 23:49:17 -07005129status_t AudioFlinger::PlaybackThread::addEffectChain_l(const sp<EffectChain>& chain)
5130{
5131 int session = chain->sessionId();
5132 int16_t *buffer = mMixBuffer;
Eric Laurent53334cd2010-06-23 17:38:20 -07005133 bool ownsBuffer = false;
Eric Laurent65b65452010-06-01 23:49:17 -07005134
5135 LOGV("addEffectChain_l() %p on thread %p for session %d", chain.get(), this, session);
Eric Laurent53334cd2010-06-23 17:38:20 -07005136 if (session > 0) {
Eric Laurent65b65452010-06-01 23:49:17 -07005137 // Only one effect chain can be present in direct output thread and it uses
5138 // the mix buffer as input
5139 if (mType != DIRECT) {
5140 size_t numSamples = mFrameCount * mChannelCount;
5141 buffer = new int16_t[numSamples];
5142 memset(buffer, 0, numSamples * sizeof(int16_t));
5143 LOGV("addEffectChain_l() creating new input buffer %p session %d", buffer, session);
5144 ownsBuffer = true;
5145 }
Eric Laurent65b65452010-06-01 23:49:17 -07005146
Eric Laurent53334cd2010-06-23 17:38:20 -07005147 // Attach all tracks with same session ID to this chain.
5148 for (size_t i = 0; i < mTracks.size(); ++i) {
5149 sp<Track> track = mTracks[i];
5150 if (session == track->sessionId()) {
5151 LOGV("addEffectChain_l() track->setMainBuffer track %p buffer %p", track.get(), buffer);
5152 track->setMainBuffer(buffer);
5153 }
5154 }
5155
5156 // indicate all active tracks in the chain
5157 for (size_t i = 0 ; i < mActiveTracks.size() ; ++i) {
5158 sp<Track> track = mActiveTracks[i].promote();
5159 if (track == 0) continue;
5160 if (session == track->sessionId()) {
5161 LOGV("addEffectChain_l() activating track %p on session %d", track.get(), session);
5162 chain->startTrack();
5163 }
Eric Laurent65b65452010-06-01 23:49:17 -07005164 }
5165 }
5166
Eric Laurent53334cd2010-06-23 17:38:20 -07005167 chain->setInBuffer(buffer, ownsBuffer);
5168 chain->setOutBuffer(mMixBuffer);
Dima Zavin24fc2fb2011-04-19 22:30:36 -07005169 // Effect chain for session AUDIO_SESSION_OUTPUT_STAGE is inserted at end of effect
Eric Laurent8ed6ed02010-07-13 04:45:46 -07005170 // chains list in order to be processed last as it contains output stage effects
Dima Zavin24fc2fb2011-04-19 22:30:36 -07005171 // Effect chain for session AUDIO_SESSION_OUTPUT_MIX is inserted before
5172 // session AUDIO_SESSION_OUTPUT_STAGE to be processed
Eric Laurent53334cd2010-06-23 17:38:20 -07005173 // after track specific effects and before output stage
Dima Zavin24fc2fb2011-04-19 22:30:36 -07005174 // It is therefore mandatory that AUDIO_SESSION_OUTPUT_MIX == 0 and
5175 // that AUDIO_SESSION_OUTPUT_STAGE < AUDIO_SESSION_OUTPUT_MIX
Eric Laurent8ed6ed02010-07-13 04:45:46 -07005176 // Effect chain for other sessions are inserted at beginning of effect
5177 // chains list to be processed before output mix effects. Relative order between other
5178 // sessions is not important
Eric Laurent53334cd2010-06-23 17:38:20 -07005179 size_t size = mEffectChains.size();
5180 size_t i = 0;
5181 for (i = 0; i < size; i++) {
5182 if (mEffectChains[i]->sessionId() < session) break;
Eric Laurent65b65452010-06-01 23:49:17 -07005183 }
Eric Laurent53334cd2010-06-23 17:38:20 -07005184 mEffectChains.insertAt(chain, i);
Eric Laurent65b65452010-06-01 23:49:17 -07005185
5186 return NO_ERROR;
5187}
5188
5189size_t AudioFlinger::PlaybackThread::removeEffectChain_l(const sp<EffectChain>& chain)
5190{
5191 int session = chain->sessionId();
5192
5193 LOGV("removeEffectChain_l() %p from thread %p for session %d", chain.get(), this, session);
5194
5195 for (size_t i = 0; i < mEffectChains.size(); i++) {
5196 if (chain == mEffectChains[i]) {
5197 mEffectChains.removeAt(i);
5198 // detach all tracks with same session ID from this chain
5199 for (size_t i = 0; i < mTracks.size(); ++i) {
5200 sp<Track> track = mTracks[i];
5201 if (session == track->sessionId()) {
5202 track->setMainBuffer(mMixBuffer);
5203 }
5204 }
Eric Laurent8ed6ed02010-07-13 04:45:46 -07005205 break;
Eric Laurent65b65452010-06-01 23:49:17 -07005206 }
5207 }
5208 return mEffectChains.size();
5209}
5210
Eric Laurent8ed6ed02010-07-13 04:45:46 -07005211void AudioFlinger::PlaybackThread::lockEffectChains_l(
5212 Vector<sp <AudioFlinger::EffectChain> >& effectChains)
Eric Laurent65b65452010-06-01 23:49:17 -07005213{
Eric Laurent8ed6ed02010-07-13 04:45:46 -07005214 effectChains = mEffectChains;
Eric Laurent65b65452010-06-01 23:49:17 -07005215 for (size_t i = 0; i < mEffectChains.size(); i++) {
5216 mEffectChains[i]->lock();
5217 }
5218}
5219
Eric Laurent8ed6ed02010-07-13 04:45:46 -07005220void AudioFlinger::PlaybackThread::unlockEffectChains(
5221 Vector<sp <AudioFlinger::EffectChain> >& effectChains)
Eric Laurent65b65452010-06-01 23:49:17 -07005222{
Eric Laurent8ed6ed02010-07-13 04:45:46 -07005223 for (size_t i = 0; i < effectChains.size(); i++) {
5224 effectChains[i]->unlock();
Eric Laurent65b65452010-06-01 23:49:17 -07005225 }
5226}
5227
Eric Laurent8ed6ed02010-07-13 04:45:46 -07005228
Eric Laurent65b65452010-06-01 23:49:17 -07005229sp<AudioFlinger::EffectModule> AudioFlinger::PlaybackThread::getEffect_l(int sessionId, int effectId)
5230{
5231 sp<EffectModule> effect;
5232
5233 sp<EffectChain> chain = getEffectChain_l(sessionId);
5234 if (chain != 0) {
Eric Laurent76c40f72010-07-15 12:50:15 -07005235 effect = chain->getEffectFromId_l(effectId);
Eric Laurent65b65452010-06-01 23:49:17 -07005236 }
5237 return effect;
5238}
5239
Eric Laurent8ed6ed02010-07-13 04:45:46 -07005240status_t AudioFlinger::PlaybackThread::attachAuxEffect(
5241 const sp<AudioFlinger::PlaybackThread::Track> track, int EffectId)
Eric Laurent65b65452010-06-01 23:49:17 -07005242{
5243 Mutex::Autolock _l(mLock);
5244 return attachAuxEffect_l(track, EffectId);
5245}
5246
Eric Laurent8ed6ed02010-07-13 04:45:46 -07005247status_t AudioFlinger::PlaybackThread::attachAuxEffect_l(
5248 const sp<AudioFlinger::PlaybackThread::Track> track, int EffectId)
Eric Laurent65b65452010-06-01 23:49:17 -07005249{
5250 status_t status = NO_ERROR;
5251
5252 if (EffectId == 0) {
5253 track->setAuxBuffer(0, NULL);
5254 } else {
Dima Zavin24fc2fb2011-04-19 22:30:36 -07005255 // Auxiliary effects are always in audio session AUDIO_SESSION_OUTPUT_MIX
5256 sp<EffectModule> effect = getEffect_l(AUDIO_SESSION_OUTPUT_MIX, EffectId);
Eric Laurent65b65452010-06-01 23:49:17 -07005257 if (effect != 0) {
5258 if ((effect->desc().flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
5259 track->setAuxBuffer(EffectId, (int32_t *)effect->inBuffer());
5260 } else {
5261 status = INVALID_OPERATION;
5262 }
5263 } else {
5264 status = BAD_VALUE;
5265 }
5266 }
5267 return status;
5268}
5269
5270void AudioFlinger::PlaybackThread::detachAuxEffect_l(int effectId)
5271{
5272 for (size_t i = 0; i < mTracks.size(); ++i) {
5273 sp<Track> track = mTracks[i];
5274 if (track->auxEffectId() == effectId) {
5275 attachAuxEffect_l(track, 0);
5276 }
5277 }
5278}
5279
5280// ----------------------------------------------------------------------------
5281// EffectModule implementation
5282// ----------------------------------------------------------------------------
5283
5284#undef LOG_TAG
5285#define LOG_TAG "AudioFlinger::EffectModule"
5286
5287AudioFlinger::EffectModule::EffectModule(const wp<ThreadBase>& wThread,
5288 const wp<AudioFlinger::EffectChain>& chain,
5289 effect_descriptor_t *desc,
5290 int id,
5291 int sessionId)
5292 : mThread(wThread), mChain(chain), mId(id), mSessionId(sessionId), mEffectInterface(NULL),
5293 mStatus(NO_INIT), mState(IDLE)
5294{
5295 LOGV("Constructor %p", this);
5296 int lStatus;
5297 sp<ThreadBase> thread = mThread.promote();
5298 if (thread == 0) {
5299 return;
5300 }
5301 PlaybackThread *p = (PlaybackThread *)thread.get();
5302
5303 memcpy(&mDescriptor, desc, sizeof(effect_descriptor_t));
5304
5305 // create effect engine from effect factory
Eric Laurent53334cd2010-06-23 17:38:20 -07005306 mStatus = EffectCreate(&desc->uuid, sessionId, p->id(), &mEffectInterface);
5307
Eric Laurent65b65452010-06-01 23:49:17 -07005308 if (mStatus != NO_ERROR) {
5309 return;
5310 }
5311 lStatus = init();
5312 if (lStatus < 0) {
5313 mStatus = lStatus;
5314 goto Error;
5315 }
5316
5317 LOGV("Constructor success name %s, Interface %p", mDescriptor.name, mEffectInterface);
5318 return;
5319Error:
5320 EffectRelease(mEffectInterface);
5321 mEffectInterface = NULL;
5322 LOGV("Constructor Error %d", mStatus);
5323}
5324
5325AudioFlinger::EffectModule::~EffectModule()
5326{
5327 LOGV("Destructor %p", this);
5328 if (mEffectInterface != NULL) {
5329 // release effect engine
5330 EffectRelease(mEffectInterface);
5331 }
5332}
5333
5334status_t AudioFlinger::EffectModule::addHandle(sp<EffectHandle>& handle)
5335{
5336 status_t status;
5337
5338 Mutex::Autolock _l(mLock);
5339 // First handle in mHandles has highest priority and controls the effect module
5340 int priority = handle->priority();
5341 size_t size = mHandles.size();
5342 sp<EffectHandle> h;
5343 size_t i;
5344 for (i = 0; i < size; i++) {
5345 h = mHandles[i].promote();
5346 if (h == 0) continue;
5347 if (h->priority() <= priority) break;
5348 }
5349 // if inserted in first place, move effect control from previous owner to this handle
5350 if (i == 0) {
5351 if (h != 0) {
5352 h->setControl(false, true);
5353 }
5354 handle->setControl(true, false);
5355 status = NO_ERROR;
5356 } else {
5357 status = ALREADY_EXISTS;
5358 }
5359 mHandles.insertAt(handle, i);
5360 return status;
5361}
5362
5363size_t AudioFlinger::EffectModule::removeHandle(const wp<EffectHandle>& handle)
5364{
5365 Mutex::Autolock _l(mLock);
5366 size_t size = mHandles.size();
5367 size_t i;
5368 for (i = 0; i < size; i++) {
5369 if (mHandles[i] == handle) break;
5370 }
5371 if (i == size) {
5372 return size;
5373 }
5374 mHandles.removeAt(i);
5375 size = mHandles.size();
5376 // if removed from first place, move effect control from this handle to next in line
5377 if (i == 0 && size != 0) {
5378 sp<EffectHandle> h = mHandles[0].promote();
5379 if (h != 0) {
5380 h->setControl(true, true);
5381 }
5382 }
5383
Eric Laurent4fd3ecc2010-09-28 14:09:57 -07005384 // Release effect engine here so that it is done immediately. Otherwise it will be released
5385 // by the destructor when the last strong reference on the this object is released which can
5386 // happen after next process is called on this effect.
5387 if (size == 0 && mEffectInterface != NULL) {
5388 // release effect engine
5389 EffectRelease(mEffectInterface);
5390 mEffectInterface = NULL;
5391 }
5392
Eric Laurent65b65452010-06-01 23:49:17 -07005393 return size;
5394}
5395
5396void AudioFlinger::EffectModule::disconnect(const wp<EffectHandle>& handle)
5397{
5398 // keep a strong reference on this EffectModule to avoid calling the
5399 // destructor before we exit
5400 sp<EffectModule> keep(this);
Eric Laurent53334cd2010-06-23 17:38:20 -07005401 {
5402 sp<ThreadBase> thread = mThread.promote();
5403 if (thread != 0) {
Eric Laurent65b65452010-06-01 23:49:17 -07005404 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
Eric Laurent53334cd2010-06-23 17:38:20 -07005405 playbackThread->disconnectEffect(keep, handle);
Eric Laurent65b65452010-06-01 23:49:17 -07005406 }
5407 }
5408}
5409
Eric Laurent7d850f22010-07-09 13:34:17 -07005410void AudioFlinger::EffectModule::updateState() {
5411 Mutex::Autolock _l(mLock);
5412
5413 switch (mState) {
5414 case RESTART:
5415 reset_l();
5416 // FALL THROUGH
5417
5418 case STARTING:
5419 // clear auxiliary effect input buffer for next accumulation
5420 if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
5421 memset(mConfig.inputCfg.buffer.raw,
5422 0,
5423 mConfig.inputCfg.buffer.frameCount*sizeof(int32_t));
5424 }
5425 start_l();
5426 mState = ACTIVE;
5427 break;
5428 case STOPPING:
5429 stop_l();
5430 mDisableWaitCnt = mMaxDisableWaitCnt;
5431 mState = STOPPED;
5432 break;
5433 case STOPPED:
5434 // mDisableWaitCnt is forced to 1 by process() when the engine indicates the end of the
5435 // turn off sequence.
5436 if (--mDisableWaitCnt == 0) {
5437 reset_l();
5438 mState = IDLE;
5439 }
5440 break;
5441 default: //IDLE , ACTIVE
5442 break;
5443 }
5444}
5445
Eric Laurent65b65452010-06-01 23:49:17 -07005446void AudioFlinger::EffectModule::process()
5447{
5448 Mutex::Autolock _l(mLock);
5449
Eric Laurent7d850f22010-07-09 13:34:17 -07005450 if (mEffectInterface == NULL ||
5451 mConfig.inputCfg.buffer.raw == NULL ||
5452 mConfig.outputCfg.buffer.raw == NULL) {
Eric Laurent65b65452010-06-01 23:49:17 -07005453 return;
5454 }
5455
Eric Laurenta92ebfa2010-08-31 13:50:07 -07005456 if (isProcessEnabled()) {
Eric Laurent65b65452010-06-01 23:49:17 -07005457 // do 32 bit to 16 bit conversion for auxiliary effect input buffer
5458 if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
5459 AudioMixer::ditherAndClamp(mConfig.inputCfg.buffer.s32,
5460 mConfig.inputCfg.buffer.s32,
Eric Laurent8ed6ed02010-07-13 04:45:46 -07005461 mConfig.inputCfg.buffer.frameCount/2);
Eric Laurent65b65452010-06-01 23:49:17 -07005462 }
5463
Eric Laurent65b65452010-06-01 23:49:17 -07005464 // do the actual processing in the effect engine
Eric Laurent7d850f22010-07-09 13:34:17 -07005465 int ret = (*mEffectInterface)->process(mEffectInterface,
5466 &mConfig.inputCfg.buffer,
5467 &mConfig.outputCfg.buffer);
5468
5469 // force transition to IDLE state when engine is ready
5470 if (mState == STOPPED && ret == -ENODATA) {
5471 mDisableWaitCnt = 1;
5472 }
Eric Laurent65b65452010-06-01 23:49:17 -07005473
5474 // clear auxiliary effect input buffer for next accumulation
5475 if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
Eric Laurent67b5ed32011-01-19 18:36:13 -08005476 memset(mConfig.inputCfg.buffer.raw, 0,
5477 mConfig.inputCfg.buffer.frameCount*sizeof(int32_t));
Eric Laurent65b65452010-06-01 23:49:17 -07005478 }
5479 } else if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_INSERT &&
Eric Laurent67b5ed32011-01-19 18:36:13 -08005480 mConfig.inputCfg.buffer.raw != mConfig.outputCfg.buffer.raw) {
5481 // If an insert effect is idle and input buffer is different from output buffer,
5482 // accumulate input onto output
Eric Laurent65b65452010-06-01 23:49:17 -07005483 sp<EffectChain> chain = mChain.promote();
5484 if (chain != 0 && chain->activeTracks() != 0) {
Eric Laurent67b5ed32011-01-19 18:36:13 -08005485 size_t frameCnt = mConfig.inputCfg.buffer.frameCount * 2; //always stereo here
5486 int16_t *in = mConfig.inputCfg.buffer.s16;
5487 int16_t *out = mConfig.outputCfg.buffer.s16;
5488 for (size_t i = 0; i < frameCnt; i++) {
5489 out[i] = clamp16((int32_t)out[i] + (int32_t)in[i]);
Eric Laurent65b65452010-06-01 23:49:17 -07005490 }
Eric Laurent65b65452010-06-01 23:49:17 -07005491 }
5492 }
5493}
5494
Eric Laurentdf9b81c2010-07-02 08:12:41 -07005495void AudioFlinger::EffectModule::reset_l()
Eric Laurent65b65452010-06-01 23:49:17 -07005496{
5497 if (mEffectInterface == NULL) {
5498 return;
5499 }
5500 (*mEffectInterface)->command(mEffectInterface, EFFECT_CMD_RESET, 0, NULL, 0, NULL);
5501}
5502
5503status_t AudioFlinger::EffectModule::configure()
5504{
5505 uint32_t channels;
5506 if (mEffectInterface == NULL) {
5507 return NO_INIT;
5508 }
5509
5510 sp<ThreadBase> thread = mThread.promote();
5511 if (thread == 0) {
5512 return DEAD_OBJECT;
5513 }
5514
5515 // TODO: handle configuration of effects replacing track process
5516 if (thread->channelCount() == 1) {
5517 channels = CHANNEL_MONO;
5518 } else {
5519 channels = CHANNEL_STEREO;
5520 }
5521
5522 if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
5523 mConfig.inputCfg.channels = CHANNEL_MONO;
5524 } else {
5525 mConfig.inputCfg.channels = channels;
5526 }
5527 mConfig.outputCfg.channels = channels;
Eric Laurent53334cd2010-06-23 17:38:20 -07005528 mConfig.inputCfg.format = SAMPLE_FORMAT_PCM_S15;
5529 mConfig.outputCfg.format = SAMPLE_FORMAT_PCM_S15;
Eric Laurent65b65452010-06-01 23:49:17 -07005530 mConfig.inputCfg.samplingRate = thread->sampleRate();
5531 mConfig.outputCfg.samplingRate = mConfig.inputCfg.samplingRate;
5532 mConfig.inputCfg.bufferProvider.cookie = NULL;
5533 mConfig.inputCfg.bufferProvider.getBuffer = NULL;
5534 mConfig.inputCfg.bufferProvider.releaseBuffer = NULL;
5535 mConfig.outputCfg.bufferProvider.cookie = NULL;
5536 mConfig.outputCfg.bufferProvider.getBuffer = NULL;
5537 mConfig.outputCfg.bufferProvider.releaseBuffer = NULL;
5538 mConfig.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ;
5539 // Insert effect:
Dima Zavin24fc2fb2011-04-19 22:30:36 -07005540 // - in session AUDIO_SESSION_OUTPUT_MIX or AUDIO_SESSION_OUTPUT_STAGE,
Eric Laurent8ed6ed02010-07-13 04:45:46 -07005541 // always overwrites output buffer: input buffer == output buffer
Eric Laurent65b65452010-06-01 23:49:17 -07005542 // - in other sessions:
5543 // last effect in the chain accumulates in output buffer: input buffer != output buffer
5544 // other effect: overwrites output buffer: input buffer == output buffer
5545 // Auxiliary effect:
5546 // accumulates in output buffer: input buffer != output buffer
5547 // Therefore: accumulate <=> input buffer != output buffer
5548 if (mConfig.inputCfg.buffer.raw != mConfig.outputCfg.buffer.raw) {
5549 mConfig.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_ACCUMULATE;
5550 } else {
5551 mConfig.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_WRITE;
5552 }
5553 mConfig.inputCfg.mask = EFFECT_CONFIG_ALL;
5554 mConfig.outputCfg.mask = EFFECT_CONFIG_ALL;
5555 mConfig.inputCfg.buffer.frameCount = thread->frameCount();
5556 mConfig.outputCfg.buffer.frameCount = mConfig.inputCfg.buffer.frameCount;
5557
Eric Laurent8ed6ed02010-07-13 04:45:46 -07005558 LOGV("configure() %p thread %p buffer %p framecount %d",
5559 this, thread.get(), mConfig.inputCfg.buffer.raw, mConfig.inputCfg.buffer.frameCount);
5560
Eric Laurent65b65452010-06-01 23:49:17 -07005561 status_t cmdStatus;
Eric Laurenta4c72ac2010-07-28 05:40:18 -07005562 uint32_t size = sizeof(int);
5563 status_t status = (*mEffectInterface)->command(mEffectInterface,
5564 EFFECT_CMD_CONFIGURE,
5565 sizeof(effect_config_t),
5566 &mConfig,
5567 &size,
5568 &cmdStatus);
Eric Laurent65b65452010-06-01 23:49:17 -07005569 if (status == 0) {
5570 status = cmdStatus;
5571 }
Eric Laurent7d850f22010-07-09 13:34:17 -07005572
5573 mMaxDisableWaitCnt = (MAX_DISABLE_TIME_MS * mConfig.outputCfg.samplingRate) /
5574 (1000 * mConfig.outputCfg.buffer.frameCount);
5575
Eric Laurent65b65452010-06-01 23:49:17 -07005576 return status;
5577}
5578
5579status_t AudioFlinger::EffectModule::init()
5580{
Eric Laurentdf9b81c2010-07-02 08:12:41 -07005581 Mutex::Autolock _l(mLock);
Eric Laurent65b65452010-06-01 23:49:17 -07005582 if (mEffectInterface == NULL) {
5583 return NO_INIT;
5584 }
5585 status_t cmdStatus;
Eric Laurenta4c72ac2010-07-28 05:40:18 -07005586 uint32_t size = sizeof(status_t);
5587 status_t status = (*mEffectInterface)->command(mEffectInterface,
5588 EFFECT_CMD_INIT,
5589 0,
5590 NULL,
5591 &size,
5592 &cmdStatus);
Eric Laurent65b65452010-06-01 23:49:17 -07005593 if (status == 0) {
5594 status = cmdStatus;
5595 }
5596 return status;
5597}
5598
Eric Laurentdf9b81c2010-07-02 08:12:41 -07005599status_t AudioFlinger::EffectModule::start_l()
Eric Laurent65b65452010-06-01 23:49:17 -07005600{
5601 if (mEffectInterface == NULL) {
5602 return NO_INIT;
5603 }
5604 status_t cmdStatus;
Eric Laurenta4c72ac2010-07-28 05:40:18 -07005605 uint32_t size = sizeof(status_t);
5606 status_t status = (*mEffectInterface)->command(mEffectInterface,
5607 EFFECT_CMD_ENABLE,
5608 0,
5609 NULL,
5610 &size,
5611 &cmdStatus);
Eric Laurent65b65452010-06-01 23:49:17 -07005612 if (status == 0) {
5613 status = cmdStatus;
5614 }
5615 return status;
5616}
5617
Eric Laurentdf9b81c2010-07-02 08:12:41 -07005618status_t AudioFlinger::EffectModule::stop_l()
Eric Laurent65b65452010-06-01 23:49:17 -07005619{
5620 if (mEffectInterface == NULL) {
5621 return NO_INIT;
5622 }
5623 status_t cmdStatus;
Eric Laurenta4c72ac2010-07-28 05:40:18 -07005624 uint32_t size = sizeof(status_t);
5625 status_t status = (*mEffectInterface)->command(mEffectInterface,
5626 EFFECT_CMD_DISABLE,
5627 0,
5628 NULL,
5629 &size,
5630 &cmdStatus);
Eric Laurent65b65452010-06-01 23:49:17 -07005631 if (status == 0) {
5632 status = cmdStatus;
5633 }
5634 return status;
5635}
5636
Eric Laurenta4c72ac2010-07-28 05:40:18 -07005637status_t AudioFlinger::EffectModule::command(uint32_t cmdCode,
5638 uint32_t cmdSize,
5639 void *pCmdData,
5640 uint32_t *replySize,
5641 void *pReplyData)
Eric Laurent65b65452010-06-01 23:49:17 -07005642{
Eric Laurentdf9b81c2010-07-02 08:12:41 -07005643 Mutex::Autolock _l(mLock);
5644// LOGV("command(), cmdCode: %d, mEffectInterface: %p", cmdCode, mEffectInterface);
Eric Laurent65b65452010-06-01 23:49:17 -07005645
5646 if (mEffectInterface == NULL) {
5647 return NO_INIT;
5648 }
Eric Laurenta4c72ac2010-07-28 05:40:18 -07005649 status_t status = (*mEffectInterface)->command(mEffectInterface,
5650 cmdCode,
5651 cmdSize,
5652 pCmdData,
5653 replySize,
5654 pReplyData);
Eric Laurent65b65452010-06-01 23:49:17 -07005655 if (cmdCode != EFFECT_CMD_GET_PARAM && status == NO_ERROR) {
Eric Laurenta4c72ac2010-07-28 05:40:18 -07005656 uint32_t size = (replySize == NULL) ? 0 : *replySize;
Eric Laurent65b65452010-06-01 23:49:17 -07005657 for (size_t i = 1; i < mHandles.size(); i++) {
5658 sp<EffectHandle> h = mHandles[i].promote();
5659 if (h != 0) {
5660 h->commandExecuted(cmdCode, cmdSize, pCmdData, size, pReplyData);
5661 }
5662 }
5663 }
5664 return status;
5665}
5666
5667status_t AudioFlinger::EffectModule::setEnabled(bool enabled)
5668{
5669 Mutex::Autolock _l(mLock);
5670 LOGV("setEnabled %p enabled %d", this, enabled);
5671
5672 if (enabled != isEnabled()) {
5673 switch (mState) {
5674 // going from disabled to enabled
5675 case IDLE:
Eric Laurent7d850f22010-07-09 13:34:17 -07005676 mState = STARTING;
5677 break;
5678 case STOPPED:
5679 mState = RESTART;
Eric Laurent65b65452010-06-01 23:49:17 -07005680 break;
5681 case STOPPING:
5682 mState = ACTIVE;
5683 break;
Eric Laurent65b65452010-06-01 23:49:17 -07005684
5685 // going from enabled to disabled
Eric Laurent7d850f22010-07-09 13:34:17 -07005686 case RESTART:
Eric Laurenta92ebfa2010-08-31 13:50:07 -07005687 mState = STOPPED;
5688 break;
Eric Laurent65b65452010-06-01 23:49:17 -07005689 case STARTING:
Eric Laurent7d850f22010-07-09 13:34:17 -07005690 mState = IDLE;
Eric Laurent65b65452010-06-01 23:49:17 -07005691 break;
5692 case ACTIVE:
5693 mState = STOPPING;
5694 break;
5695 }
5696 for (size_t i = 1; i < mHandles.size(); i++) {
5697 sp<EffectHandle> h = mHandles[i].promote();
5698 if (h != 0) {
5699 h->setEnabled(enabled);
5700 }
5701 }
5702 }
5703 return NO_ERROR;
5704}
5705
5706bool AudioFlinger::EffectModule::isEnabled()
5707{
5708 switch (mState) {
Eric Laurent7d850f22010-07-09 13:34:17 -07005709 case RESTART:
Eric Laurent65b65452010-06-01 23:49:17 -07005710 case STARTING:
5711 case ACTIVE:
5712 return true;
5713 case IDLE:
5714 case STOPPING:
5715 case STOPPED:
5716 default:
5717 return false;
5718 }
5719}
5720
Eric Laurenta92ebfa2010-08-31 13:50:07 -07005721bool AudioFlinger::EffectModule::isProcessEnabled()
5722{
5723 switch (mState) {
5724 case RESTART:
5725 case ACTIVE:
5726 case STOPPING:
5727 case STOPPED:
5728 return true;
5729 case IDLE:
5730 case STARTING:
5731 default:
5732 return false;
5733 }
5734}
5735
Eric Laurent65b65452010-06-01 23:49:17 -07005736status_t AudioFlinger::EffectModule::setVolume(uint32_t *left, uint32_t *right, bool controller)
5737{
Eric Laurentdf9b81c2010-07-02 08:12:41 -07005738 Mutex::Autolock _l(mLock);
Eric Laurent65b65452010-06-01 23:49:17 -07005739 status_t status = NO_ERROR;
5740
5741 // Send volume indication if EFFECT_FLAG_VOLUME_IND is set and read back altered volume
5742 // if controller flag is set (Note that controller == TRUE => EFFECT_FLAG_VOLUME_CTRL set)
Eric Laurenta92ebfa2010-08-31 13:50:07 -07005743 if (isProcessEnabled() &&
Eric Laurent0d7e0482010-07-19 06:24:46 -07005744 ((mDescriptor.flags & EFFECT_FLAG_VOLUME_MASK) == EFFECT_FLAG_VOLUME_CTRL ||
5745 (mDescriptor.flags & EFFECT_FLAG_VOLUME_MASK) == EFFECT_FLAG_VOLUME_IND)) {
Eric Laurent65b65452010-06-01 23:49:17 -07005746 status_t cmdStatus;
5747 uint32_t volume[2];
5748 uint32_t *pVolume = NULL;
Eric Laurenta4c72ac2010-07-28 05:40:18 -07005749 uint32_t size = sizeof(volume);
Eric Laurent65b65452010-06-01 23:49:17 -07005750 volume[0] = *left;
5751 volume[1] = *right;
5752 if (controller) {
5753 pVolume = volume;
5754 }
Eric Laurenta4c72ac2010-07-28 05:40:18 -07005755 status = (*mEffectInterface)->command(mEffectInterface,
5756 EFFECT_CMD_SET_VOLUME,
5757 size,
5758 volume,
5759 &size,
5760 pVolume);
Eric Laurent65b65452010-06-01 23:49:17 -07005761 if (controller && status == NO_ERROR && size == sizeof(volume)) {
5762 *left = volume[0];
5763 *right = volume[1];
5764 }
5765 }
5766 return status;
5767}
5768
5769status_t AudioFlinger::EffectModule::setDevice(uint32_t device)
5770{
Eric Laurentdf9b81c2010-07-02 08:12:41 -07005771 Mutex::Autolock _l(mLock);
Eric Laurent65b65452010-06-01 23:49:17 -07005772 status_t status = NO_ERROR;
Eric Laurent53334cd2010-06-23 17:38:20 -07005773 if ((mDescriptor.flags & EFFECT_FLAG_DEVICE_MASK) == EFFECT_FLAG_DEVICE_IND) {
5774 // convert device bit field from AudioSystem to EffectApi format.
5775 device = deviceAudioSystemToEffectApi(device);
5776 if (device == 0) {
5777 return BAD_VALUE;
5778 }
Eric Laurent65b65452010-06-01 23:49:17 -07005779 status_t cmdStatus;
Eric Laurenta4c72ac2010-07-28 05:40:18 -07005780 uint32_t size = sizeof(status_t);
5781 status = (*mEffectInterface)->command(mEffectInterface,
5782 EFFECT_CMD_SET_DEVICE,
5783 sizeof(uint32_t),
5784 &device,
5785 &size,
5786 &cmdStatus);
Eric Laurent65b65452010-06-01 23:49:17 -07005787 if (status == NO_ERROR) {
5788 status = cmdStatus;
5789 }
5790 }
5791 return status;
5792}
5793
Eric Laurent53334cd2010-06-23 17:38:20 -07005794status_t AudioFlinger::EffectModule::setMode(uint32_t mode)
5795{
Eric Laurentdf9b81c2010-07-02 08:12:41 -07005796 Mutex::Autolock _l(mLock);
Eric Laurent53334cd2010-06-23 17:38:20 -07005797 status_t status = NO_ERROR;
5798 if ((mDescriptor.flags & EFFECT_FLAG_AUDIO_MODE_MASK) == EFFECT_FLAG_AUDIO_MODE_IND) {
5799 // convert audio mode from AudioSystem to EffectApi format.
5800 int effectMode = modeAudioSystemToEffectApi(mode);
5801 if (effectMode < 0) {
5802 return BAD_VALUE;
5803 }
5804 status_t cmdStatus;
Eric Laurenta4c72ac2010-07-28 05:40:18 -07005805 uint32_t size = sizeof(status_t);
5806 status = (*mEffectInterface)->command(mEffectInterface,
5807 EFFECT_CMD_SET_AUDIO_MODE,
5808 sizeof(int),
5809 &effectMode,
5810 &size,
5811 &cmdStatus);
Eric Laurent53334cd2010-06-23 17:38:20 -07005812 if (status == NO_ERROR) {
5813 status = cmdStatus;
5814 }
5815 }
5816 return status;
5817}
5818
5819// update this table when AudioSystem::audio_devices or audio_device_e (in EffectApi.h) are modified
5820const uint32_t AudioFlinger::EffectModule::sDeviceConvTable[] = {
Dima Zavin24fc2fb2011-04-19 22:30:36 -07005821 DEVICE_EARPIECE, // AUDIO_DEVICE_OUT_EARPIECE
5822 DEVICE_SPEAKER, // AUDIO_DEVICE_OUT_SPEAKER
5823 DEVICE_WIRED_HEADSET, // case AUDIO_DEVICE_OUT_WIRED_HEADSET
5824 DEVICE_WIRED_HEADPHONE, // AUDIO_DEVICE_OUT_WIRED_HEADPHONE
5825 DEVICE_BLUETOOTH_SCO, // AUDIO_DEVICE_OUT_BLUETOOTH_SCO
5826 DEVICE_BLUETOOTH_SCO_HEADSET, // AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET
5827 DEVICE_BLUETOOTH_SCO_CARKIT, // AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT
5828 DEVICE_BLUETOOTH_A2DP, // AUDIO_DEVICE_OUT_BLUETOOTH_A2DP
5829 DEVICE_BLUETOOTH_A2DP_HEADPHONES, // AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES
5830 DEVICE_BLUETOOTH_A2DP_SPEAKER, // AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER
5831 DEVICE_AUX_DIGITAL // AUDIO_DEVICE_OUT_AUX_DIGITAL
Eric Laurent53334cd2010-06-23 17:38:20 -07005832};
5833
5834uint32_t AudioFlinger::EffectModule::deviceAudioSystemToEffectApi(uint32_t device)
5835{
5836 uint32_t deviceOut = 0;
5837 while (device) {
5838 const uint32_t i = 31 - __builtin_clz(device);
5839 device &= ~(1 << i);
5840 if (i >= sizeof(sDeviceConvTable)/sizeof(uint32_t)) {
Glenn Kastened0079d2011-04-04 10:50:50 -07005841 LOGE("device conversion error for AudioSystem device 0x%08x", device);
Eric Laurent53334cd2010-06-23 17:38:20 -07005842 return 0;
5843 }
5844 deviceOut |= (uint32_t)sDeviceConvTable[i];
5845 }
5846 return deviceOut;
5847}
5848
5849// update this table when AudioSystem::audio_mode or audio_mode_e (in EffectApi.h) are modified
5850const uint32_t AudioFlinger::EffectModule::sModeConvTable[] = {
Dima Zavin24fc2fb2011-04-19 22:30:36 -07005851 AUDIO_EFFECT_MODE_NORMAL, // AUDIO_MODE_NORMAL
5852 AUDIO_EFFECT_MODE_RINGTONE, // AUDIO_MODE_RINGTONE
5853 AUDIO_EFFECT_MODE_IN_CALL, // AUDIO_MODE_IN_CALL
5854 AUDIO_EFFECT_MODE_IN_CALL // AUDIO_MODE_IN_COMMUNICATION, same conversion as for AUDIO_MODE_IN_CALL
Eric Laurent53334cd2010-06-23 17:38:20 -07005855};
5856
5857int AudioFlinger::EffectModule::modeAudioSystemToEffectApi(uint32_t mode)
5858{
5859 int modeOut = -1;
5860 if (mode < sizeof(sModeConvTable) / sizeof(uint32_t)) {
5861 modeOut = (int)sModeConvTable[mode];
5862 }
5863 return modeOut;
5864}
Eric Laurent65b65452010-06-01 23:49:17 -07005865
5866status_t AudioFlinger::EffectModule::dump(int fd, const Vector<String16>& args)
5867{
5868 const size_t SIZE = 256;
5869 char buffer[SIZE];
5870 String8 result;
5871
5872 snprintf(buffer, SIZE, "\tEffect ID %d:\n", mId);
5873 result.append(buffer);
5874
5875 bool locked = tryLock(mLock);
5876 // failed to lock - AudioFlinger is probably deadlocked
5877 if (!locked) {
5878 result.append("\t\tCould not lock Fx mutex:\n");
5879 }
5880
5881 result.append("\t\tSession Status State Engine:\n");
5882 snprintf(buffer, SIZE, "\t\t%05d %03d %03d 0x%08x\n",
5883 mSessionId, mStatus, mState, (uint32_t)mEffectInterface);
5884 result.append(buffer);
5885
5886 result.append("\t\tDescriptor:\n");
5887 snprintf(buffer, SIZE, "\t\t- UUID: %08X-%04X-%04X-%04X-%02X%02X%02X%02X%02X%02X\n",
5888 mDescriptor.uuid.timeLow, mDescriptor.uuid.timeMid, mDescriptor.uuid.timeHiAndVersion,
5889 mDescriptor.uuid.clockSeq, mDescriptor.uuid.node[0], mDescriptor.uuid.node[1],mDescriptor.uuid.node[2],
5890 mDescriptor.uuid.node[3],mDescriptor.uuid.node[4],mDescriptor.uuid.node[5]);
5891 result.append(buffer);
5892 snprintf(buffer, SIZE, "\t\t- TYPE: %08X-%04X-%04X-%04X-%02X%02X%02X%02X%02X%02X\n",
5893 mDescriptor.type.timeLow, mDescriptor.type.timeMid, mDescriptor.type.timeHiAndVersion,
5894 mDescriptor.type.clockSeq, mDescriptor.type.node[0], mDescriptor.type.node[1],mDescriptor.type.node[2],
5895 mDescriptor.type.node[3],mDescriptor.type.node[4],mDescriptor.type.node[5]);
5896 result.append(buffer);
5897 snprintf(buffer, SIZE, "\t\t- apiVersion: %04X\n\t\t- flags: %08X\n",
5898 mDescriptor.apiVersion,
5899 mDescriptor.flags);
5900 result.append(buffer);
5901 snprintf(buffer, SIZE, "\t\t- name: %s\n",
5902 mDescriptor.name);
5903 result.append(buffer);
5904 snprintf(buffer, SIZE, "\t\t- implementor: %s\n",
5905 mDescriptor.implementor);
5906 result.append(buffer);
5907
5908 result.append("\t\t- Input configuration:\n");
5909 result.append("\t\t\tBuffer Frames Smp rate Channels Format\n");
5910 snprintf(buffer, SIZE, "\t\t\t0x%08x %05d %05d %08x %d\n",
5911 (uint32_t)mConfig.inputCfg.buffer.raw,
5912 mConfig.inputCfg.buffer.frameCount,
5913 mConfig.inputCfg.samplingRate,
5914 mConfig.inputCfg.channels,
5915 mConfig.inputCfg.format);
5916 result.append(buffer);
5917
5918 result.append("\t\t- Output configuration:\n");
5919 result.append("\t\t\tBuffer Frames Smp rate Channels Format\n");
5920 snprintf(buffer, SIZE, "\t\t\t0x%08x %05d %05d %08x %d\n",
5921 (uint32_t)mConfig.outputCfg.buffer.raw,
5922 mConfig.outputCfg.buffer.frameCount,
5923 mConfig.outputCfg.samplingRate,
5924 mConfig.outputCfg.channels,
5925 mConfig.outputCfg.format);
5926 result.append(buffer);
5927
5928 snprintf(buffer, SIZE, "\t\t%d Clients:\n", mHandles.size());
5929 result.append(buffer);
5930 result.append("\t\t\tPid Priority Ctrl Locked client server\n");
5931 for (size_t i = 0; i < mHandles.size(); ++i) {
5932 sp<EffectHandle> handle = mHandles[i].promote();
5933 if (handle != 0) {
5934 handle->dump(buffer, SIZE);
5935 result.append(buffer);
5936 }
5937 }
5938
5939 result.append("\n");
5940
5941 write(fd, result.string(), result.length());
5942
5943 if (locked) {
5944 mLock.unlock();
5945 }
5946
5947 return NO_ERROR;
5948}
5949
5950// ----------------------------------------------------------------------------
5951// EffectHandle implementation
5952// ----------------------------------------------------------------------------
5953
5954#undef LOG_TAG
5955#define LOG_TAG "AudioFlinger::EffectHandle"
5956
5957AudioFlinger::EffectHandle::EffectHandle(const sp<EffectModule>& effect,
5958 const sp<AudioFlinger::Client>& client,
5959 const sp<IEffectClient>& effectClient,
5960 int32_t priority)
5961 : BnEffect(),
5962 mEffect(effect), mEffectClient(effectClient), mClient(client), mPriority(priority), mHasControl(false)
5963{
5964 LOGV("constructor %p", this);
5965
5966 int bufOffset = ((sizeof(effect_param_cblk_t) - 1) / sizeof(int) + 1) * sizeof(int);
5967 mCblkMemory = client->heap()->allocate(EFFECT_PARAM_BUFFER_SIZE + bufOffset);
5968 if (mCblkMemory != 0) {
5969 mCblk = static_cast<effect_param_cblk_t *>(mCblkMemory->pointer());
5970
5971 if (mCblk) {
5972 new(mCblk) effect_param_cblk_t();
5973 mBuffer = (uint8_t *)mCblk + bufOffset;
5974 }
5975 } else {
5976 LOGE("not enough memory for Effect size=%u", EFFECT_PARAM_BUFFER_SIZE + sizeof(effect_param_cblk_t));
5977 return;
5978 }
5979}
5980
5981AudioFlinger::EffectHandle::~EffectHandle()
5982{
5983 LOGV("Destructor %p", this);
5984 disconnect();
5985}
5986
5987status_t AudioFlinger::EffectHandle::enable()
5988{
5989 if (!mHasControl) return INVALID_OPERATION;
5990 if (mEffect == 0) return DEAD_OBJECT;
5991
5992 return mEffect->setEnabled(true);
5993}
5994
5995status_t AudioFlinger::EffectHandle::disable()
5996{
5997 if (!mHasControl) return INVALID_OPERATION;
5998 if (mEffect == NULL) return DEAD_OBJECT;
5999
6000 return mEffect->setEnabled(false);
6001}
6002
6003void AudioFlinger::EffectHandle::disconnect()
6004{
6005 if (mEffect == 0) {
6006 return;
6007 }
6008 mEffect->disconnect(this);
6009 // release sp on module => module destructor can be called now
6010 mEffect.clear();
6011 if (mCblk) {
6012 mCblk->~effect_param_cblk_t(); // destroy our shared-structure.
6013 }
6014 mCblkMemory.clear(); // and free the shared memory
6015 if (mClient != 0) {
6016 Mutex::Autolock _l(mClient->audioFlinger()->mLock);
6017 mClient.clear();
6018 }
6019}
6020
Eric Laurenta4c72ac2010-07-28 05:40:18 -07006021status_t AudioFlinger::EffectHandle::command(uint32_t cmdCode,
6022 uint32_t cmdSize,
6023 void *pCmdData,
6024 uint32_t *replySize,
6025 void *pReplyData)
Eric Laurent65b65452010-06-01 23:49:17 -07006026{
Eric Laurenta4c72ac2010-07-28 05:40:18 -07006027// LOGV("command(), cmdCode: %d, mHasControl: %d, mEffect: %p",
6028// cmdCode, mHasControl, (mEffect == 0) ? 0 : mEffect.get());
Eric Laurent65b65452010-06-01 23:49:17 -07006029
6030 // only get parameter command is permitted for applications not controlling the effect
6031 if (!mHasControl && cmdCode != EFFECT_CMD_GET_PARAM) {
6032 return INVALID_OPERATION;
6033 }
6034 if (mEffect == 0) return DEAD_OBJECT;
6035
6036 // handle commands that are not forwarded transparently to effect engine
6037 if (cmdCode == EFFECT_CMD_SET_PARAM_COMMIT) {
6038 // No need to trylock() here as this function is executed in the binder thread serving a particular client process:
6039 // no risk to block the whole media server process or mixer threads is we are stuck here
6040 Mutex::Autolock _l(mCblk->lock);
6041 if (mCblk->clientIndex > EFFECT_PARAM_BUFFER_SIZE ||
6042 mCblk->serverIndex > EFFECT_PARAM_BUFFER_SIZE) {
6043 mCblk->serverIndex = 0;
6044 mCblk->clientIndex = 0;
6045 return BAD_VALUE;
6046 }
6047 status_t status = NO_ERROR;
6048 while (mCblk->serverIndex < mCblk->clientIndex) {
6049 int reply;
Eric Laurenta4c72ac2010-07-28 05:40:18 -07006050 uint32_t rsize = sizeof(int);
Eric Laurent65b65452010-06-01 23:49:17 -07006051 int *p = (int *)(mBuffer + mCblk->serverIndex);
6052 int size = *p++;
Eric Laurent53334cd2010-06-23 17:38:20 -07006053 if (((uint8_t *)p + size) > mBuffer + mCblk->clientIndex) {
6054 LOGW("command(): invalid parameter block size");
6055 break;
6056 }
Eric Laurent65b65452010-06-01 23:49:17 -07006057 effect_param_t *param = (effect_param_t *)p;
Eric Laurent53334cd2010-06-23 17:38:20 -07006058 if (param->psize == 0 || param->vsize == 0) {
6059 LOGW("command(): null parameter or value size");
6060 mCblk->serverIndex += size;
6061 continue;
6062 }
Eric Laurenta4c72ac2010-07-28 05:40:18 -07006063 uint32_t psize = sizeof(effect_param_t) +
6064 ((param->psize - 1) / sizeof(int) + 1) * sizeof(int) +
6065 param->vsize;
6066 status_t ret = mEffect->command(EFFECT_CMD_SET_PARAM,
6067 psize,
6068 p,
6069 &rsize,
6070 &reply);
Eric Laurente65280c2010-09-02 11:56:55 -07006071 // stop at first error encountered
6072 if (ret != NO_ERROR) {
Eric Laurent65b65452010-06-01 23:49:17 -07006073 status = ret;
Eric Laurente65280c2010-09-02 11:56:55 -07006074 *(int *)pReplyData = reply;
6075 break;
6076 } else if (reply != NO_ERROR) {
6077 *(int *)pReplyData = reply;
6078 break;
Eric Laurent65b65452010-06-01 23:49:17 -07006079 }
6080 mCblk->serverIndex += size;
6081 }
6082 mCblk->serverIndex = 0;
6083 mCblk->clientIndex = 0;
6084 return status;
6085 } else if (cmdCode == EFFECT_CMD_ENABLE) {
Eric Laurente65280c2010-09-02 11:56:55 -07006086 *(int *)pReplyData = NO_ERROR;
Eric Laurent65b65452010-06-01 23:49:17 -07006087 return enable();
6088 } else if (cmdCode == EFFECT_CMD_DISABLE) {
Eric Laurente65280c2010-09-02 11:56:55 -07006089 *(int *)pReplyData = NO_ERROR;
Eric Laurent65b65452010-06-01 23:49:17 -07006090 return disable();
6091 }
6092
6093 return mEffect->command(cmdCode, cmdSize, pCmdData, replySize, pReplyData);
6094}
6095
6096sp<IMemory> AudioFlinger::EffectHandle::getCblk() const {
6097 return mCblkMemory;
6098}
6099
6100void AudioFlinger::EffectHandle::setControl(bool hasControl, bool signal)
6101{
6102 LOGV("setControl %p control %d", this, hasControl);
6103
6104 mHasControl = hasControl;
6105 if (signal && mEffectClient != 0) {
6106 mEffectClient->controlStatusChanged(hasControl);
6107 }
6108}
6109
Eric Laurenta4c72ac2010-07-28 05:40:18 -07006110void AudioFlinger::EffectHandle::commandExecuted(uint32_t cmdCode,
6111 uint32_t cmdSize,
6112 void *pCmdData,
6113 uint32_t replySize,
6114 void *pReplyData)
Eric Laurent65b65452010-06-01 23:49:17 -07006115{
6116 if (mEffectClient != 0) {
6117 mEffectClient->commandExecuted(cmdCode, cmdSize, pCmdData, replySize, pReplyData);
6118 }
6119}
6120
6121
6122
6123void AudioFlinger::EffectHandle::setEnabled(bool enabled)
6124{
6125 if (mEffectClient != 0) {
6126 mEffectClient->enableStatusChanged(enabled);
6127 }
6128}
6129
6130status_t AudioFlinger::EffectHandle::onTransact(
6131 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
6132{
6133 return BnEffect::onTransact(code, data, reply, flags);
6134}
6135
6136
6137void AudioFlinger::EffectHandle::dump(char* buffer, size_t size)
6138{
6139 bool locked = tryLock(mCblk->lock);
6140
6141 snprintf(buffer, size, "\t\t\t%05d %05d %01u %01u %05u %05u\n",
6142 (mClient == NULL) ? getpid() : mClient->pid(),
6143 mPriority,
6144 mHasControl,
6145 !locked,
6146 mCblk->clientIndex,
6147 mCblk->serverIndex
6148 );
6149
6150 if (locked) {
6151 mCblk->lock.unlock();
6152 }
6153}
6154
6155#undef LOG_TAG
6156#define LOG_TAG "AudioFlinger::EffectChain"
6157
6158AudioFlinger::EffectChain::EffectChain(const wp<ThreadBase>& wThread,
6159 int sessionId)
Eric Laurent76c40f72010-07-15 12:50:15 -07006160 : mThread(wThread), mSessionId(sessionId), mActiveTrackCnt(0), mOwnInBuffer(false),
Eric Laurent2a6b80b2010-07-29 23:43:43 -07006161 mVolumeCtrlIdx(-1), mLeftVolume(UINT_MAX), mRightVolume(UINT_MAX),
6162 mNewLeftVolume(UINT_MAX), mNewRightVolume(UINT_MAX)
Eric Laurent65b65452010-06-01 23:49:17 -07006163{
Dima Zavin24fc2fb2011-04-19 22:30:36 -07006164 mStrategy = AudioSystem::getStrategyForStream(AUDIO_STREAM_MUSIC);
Eric Laurent65b65452010-06-01 23:49:17 -07006165}
6166
6167AudioFlinger::EffectChain::~EffectChain()
6168{
6169 if (mOwnInBuffer) {
6170 delete mInBuffer;
6171 }
6172
6173}
6174
Eric Laurent76c40f72010-07-15 12:50:15 -07006175// getEffectFromDesc_l() must be called with PlaybackThread::mLock held
6176sp<AudioFlinger::EffectModule> AudioFlinger::EffectChain::getEffectFromDesc_l(effect_descriptor_t *descriptor)
Eric Laurent65b65452010-06-01 23:49:17 -07006177{
6178 sp<EffectModule> effect;
6179 size_t size = mEffects.size();
6180
6181 for (size_t i = 0; i < size; i++) {
6182 if (memcmp(&mEffects[i]->desc().uuid, &descriptor->uuid, sizeof(effect_uuid_t)) == 0) {
6183 effect = mEffects[i];
6184 break;
6185 }
6186 }
6187 return effect;
6188}
6189
Eric Laurent76c40f72010-07-15 12:50:15 -07006190// getEffectFromId_l() must be called with PlaybackThread::mLock held
6191sp<AudioFlinger::EffectModule> AudioFlinger::EffectChain::getEffectFromId_l(int id)
Eric Laurent65b65452010-06-01 23:49:17 -07006192{
6193 sp<EffectModule> effect;
6194 size_t size = mEffects.size();
6195
6196 for (size_t i = 0; i < size; i++) {
Eric Laurent8ed6ed02010-07-13 04:45:46 -07006197 // by convention, return first effect if id provided is 0 (0 is never a valid id)
6198 if (id == 0 || mEffects[i]->id() == id) {
Eric Laurent65b65452010-06-01 23:49:17 -07006199 effect = mEffects[i];
6200 break;
6201 }
6202 }
6203 return effect;
6204}
6205
6206// Must be called with EffectChain::mLock locked
6207void AudioFlinger::EffectChain::process_l()
6208{
Eric Laurent4fd3ecc2010-09-28 14:09:57 -07006209 sp<ThreadBase> thread = mThread.promote();
6210 if (thread == 0) {
6211 LOGW("process_l(): cannot promote mixer thread");
6212 return;
6213 }
6214 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
Dima Zavin24fc2fb2011-04-19 22:30:36 -07006215 bool isGlobalSession = (mSessionId == AUDIO_SESSION_OUTPUT_MIX) ||
6216 (mSessionId == AUDIO_SESSION_OUTPUT_STAGE);
Eric Laurent4fd3ecc2010-09-28 14:09:57 -07006217 bool tracksOnSession = false;
6218 if (!isGlobalSession) {
6219 tracksOnSession =
6220 playbackThread->hasAudioSession(mSessionId) & PlaybackThread::TRACK_SESSION;
6221 }
6222
Eric Laurent65b65452010-06-01 23:49:17 -07006223 size_t size = mEffects.size();
Eric Laurent4fd3ecc2010-09-28 14:09:57 -07006224 // do not process effect if no track is present in same audio session
6225 if (isGlobalSession || tracksOnSession) {
6226 for (size_t i = 0; i < size; i++) {
6227 mEffects[i]->process();
6228 }
Eric Laurent65b65452010-06-01 23:49:17 -07006229 }
Eric Laurent7d850f22010-07-09 13:34:17 -07006230 for (size_t i = 0; i < size; i++) {
6231 mEffects[i]->updateState();
6232 }
Eric Laurent65b65452010-06-01 23:49:17 -07006233 // if no track is active, input buffer must be cleared here as the mixer process
6234 // will not do it
Eric Laurent4fd3ecc2010-09-28 14:09:57 -07006235 if (tracksOnSession &&
6236 activeTracks() == 0) {
6237 size_t numSamples = playbackThread->frameCount() * playbackThread->channelCount();
6238 memset(mInBuffer, 0, numSamples * sizeof(int16_t));
Eric Laurent65b65452010-06-01 23:49:17 -07006239 }
6240}
6241
Eric Laurent76c40f72010-07-15 12:50:15 -07006242// addEffect_l() must be called with PlaybackThread::mLock held
Eric Laurent8ed6ed02010-07-13 04:45:46 -07006243status_t AudioFlinger::EffectChain::addEffect_l(const sp<EffectModule>& effect)
Eric Laurent65b65452010-06-01 23:49:17 -07006244{
6245 effect_descriptor_t desc = effect->desc();
6246 uint32_t insertPref = desc.flags & EFFECT_FLAG_INSERT_MASK;
6247
6248 Mutex::Autolock _l(mLock);
Eric Laurent8ed6ed02010-07-13 04:45:46 -07006249 effect->setChain(this);
6250 sp<ThreadBase> thread = mThread.promote();
6251 if (thread == 0) {
6252 return NO_INIT;
6253 }
6254 effect->setThread(thread);
Eric Laurent65b65452010-06-01 23:49:17 -07006255
6256 if ((desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
6257 // Auxiliary effects are inserted at the beginning of mEffects vector as
6258 // they are processed first and accumulated in chain input buffer
6259 mEffects.insertAt(effect, 0);
Eric Laurent8ed6ed02010-07-13 04:45:46 -07006260
Eric Laurent65b65452010-06-01 23:49:17 -07006261 // the input buffer for auxiliary effect contains mono samples in
6262 // 32 bit format. This is to avoid saturation in AudoMixer
6263 // accumulation stage. Saturation is done in EffectModule::process() before
6264 // calling the process in effect engine
6265 size_t numSamples = thread->frameCount();
6266 int32_t *buffer = new int32_t[numSamples];
6267 memset(buffer, 0, numSamples * sizeof(int32_t));
6268 effect->setInBuffer((int16_t *)buffer);
6269 // auxiliary effects output samples to chain input buffer for further processing
6270 // by insert effects
6271 effect->setOutBuffer(mInBuffer);
6272 } else {
6273 // Insert effects are inserted at the end of mEffects vector as they are processed
6274 // after track and auxiliary effects.
Eric Laurent53334cd2010-06-23 17:38:20 -07006275 // Insert effect order as a function of indicated preference:
6276 // if EFFECT_FLAG_INSERT_EXCLUSIVE, insert in first position or reject if
6277 // another effect is present
6278 // else if EFFECT_FLAG_INSERT_FIRST, insert in first position or after the
6279 // last effect claiming first position
6280 // else if EFFECT_FLAG_INSERT_LAST, insert in last position or before the
6281 // first effect claiming last position
Eric Laurent65b65452010-06-01 23:49:17 -07006282 // else if EFFECT_FLAG_INSERT_ANY insert after first or before last
Eric Laurent53334cd2010-06-23 17:38:20 -07006283 // Reject insertion if an effect with EFFECT_FLAG_INSERT_EXCLUSIVE is
6284 // already present
Eric Laurent65b65452010-06-01 23:49:17 -07006285
6286 int size = (int)mEffects.size();
6287 int idx_insert = size;
6288 int idx_insert_first = -1;
6289 int idx_insert_last = -1;
6290
6291 for (int i = 0; i < size; i++) {
6292 effect_descriptor_t d = mEffects[i]->desc();
6293 uint32_t iMode = d.flags & EFFECT_FLAG_TYPE_MASK;
6294 uint32_t iPref = d.flags & EFFECT_FLAG_INSERT_MASK;
6295 if (iMode == EFFECT_FLAG_TYPE_INSERT) {
6296 // check invalid effect chaining combinations
6297 if (insertPref == EFFECT_FLAG_INSERT_EXCLUSIVE ||
Eric Laurent53334cd2010-06-23 17:38:20 -07006298 iPref == EFFECT_FLAG_INSERT_EXCLUSIVE) {
Eric Laurent76c40f72010-07-15 12:50:15 -07006299 LOGW("addEffect_l() could not insert effect %s: exclusive conflict with %s", desc.name, d.name);
Eric Laurent65b65452010-06-01 23:49:17 -07006300 return INVALID_OPERATION;
6301 }
Eric Laurent53334cd2010-06-23 17:38:20 -07006302 // remember position of first insert effect and by default
6303 // select this as insert position for new effect
Eric Laurent65b65452010-06-01 23:49:17 -07006304 if (idx_insert == size) {
6305 idx_insert = i;
6306 }
Eric Laurent53334cd2010-06-23 17:38:20 -07006307 // remember position of last insert effect claiming
6308 // first position
Eric Laurent65b65452010-06-01 23:49:17 -07006309 if (iPref == EFFECT_FLAG_INSERT_FIRST) {
6310 idx_insert_first = i;
6311 }
Eric Laurent53334cd2010-06-23 17:38:20 -07006312 // remember position of first insert effect claiming
6313 // last position
6314 if (iPref == EFFECT_FLAG_INSERT_LAST &&
6315 idx_insert_last == -1) {
Eric Laurent65b65452010-06-01 23:49:17 -07006316 idx_insert_last = i;
6317 }
6318 }
6319 }
6320
Eric Laurent53334cd2010-06-23 17:38:20 -07006321 // modify idx_insert from first position if needed
6322 if (insertPref == EFFECT_FLAG_INSERT_LAST) {
6323 if (idx_insert_last != -1) {
6324 idx_insert = idx_insert_last;
6325 } else {
6326 idx_insert = size;
6327 }
6328 } else {
6329 if (idx_insert_first != -1) {
6330 idx_insert = idx_insert_first + 1;
6331 }
Eric Laurent65b65452010-06-01 23:49:17 -07006332 }
6333
6334 // always read samples from chain input buffer
6335 effect->setInBuffer(mInBuffer);
6336
6337 // if last effect in the chain, output samples to chain
6338 // output buffer, otherwise to chain input buffer
6339 if (idx_insert == size) {
6340 if (idx_insert != 0) {
6341 mEffects[idx_insert-1]->setOutBuffer(mInBuffer);
6342 mEffects[idx_insert-1]->configure();
6343 }
6344 effect->setOutBuffer(mOutBuffer);
6345 } else {
6346 effect->setOutBuffer(mInBuffer);
6347 }
Eric Laurent53334cd2010-06-23 17:38:20 -07006348 mEffects.insertAt(effect, idx_insert);
Eric Laurent65b65452010-06-01 23:49:17 -07006349
Eric Laurent76c40f72010-07-15 12:50:15 -07006350 LOGV("addEffect_l() effect %p, added in chain %p at rank %d", effect.get(), this, idx_insert);
Eric Laurent65b65452010-06-01 23:49:17 -07006351 }
6352 effect->configure();
6353 return NO_ERROR;
6354}
6355
Eric Laurent76c40f72010-07-15 12:50:15 -07006356// removeEffect_l() must be called with PlaybackThread::mLock held
6357size_t AudioFlinger::EffectChain::removeEffect_l(const sp<EffectModule>& effect)
Eric Laurent65b65452010-06-01 23:49:17 -07006358{
6359 Mutex::Autolock _l(mLock);
Eric Laurent65b65452010-06-01 23:49:17 -07006360 int size = (int)mEffects.size();
6361 int i;
6362 uint32_t type = effect->desc().flags & EFFECT_FLAG_TYPE_MASK;
6363
6364 for (i = 0; i < size; i++) {
6365 if (effect == mEffects[i]) {
6366 if (type == EFFECT_FLAG_TYPE_AUXILIARY) {
6367 delete[] effect->inBuffer();
6368 } else {
6369 if (i == size - 1 && i != 0) {
6370 mEffects[i - 1]->setOutBuffer(mOutBuffer);
6371 mEffects[i - 1]->configure();
6372 }
6373 }
6374 mEffects.removeAt(i);
Eric Laurent76c40f72010-07-15 12:50:15 -07006375 LOGV("removeEffect_l() effect %p, removed from chain %p at rank %d", effect.get(), this, i);
Eric Laurent65b65452010-06-01 23:49:17 -07006376 break;
6377 }
6378 }
Eric Laurent65b65452010-06-01 23:49:17 -07006379
6380 return mEffects.size();
6381}
6382
Eric Laurent76c40f72010-07-15 12:50:15 -07006383// setDevice_l() must be called with PlaybackThread::mLock held
6384void AudioFlinger::EffectChain::setDevice_l(uint32_t device)
Eric Laurent65b65452010-06-01 23:49:17 -07006385{
6386 size_t size = mEffects.size();
6387 for (size_t i = 0; i < size; i++) {
6388 mEffects[i]->setDevice(device);
6389 }
6390}
6391
Eric Laurent76c40f72010-07-15 12:50:15 -07006392// setMode_l() must be called with PlaybackThread::mLock held
6393void AudioFlinger::EffectChain::setMode_l(uint32_t mode)
Eric Laurent53334cd2010-06-23 17:38:20 -07006394{
6395 size_t size = mEffects.size();
6396 for (size_t i = 0; i < size; i++) {
6397 mEffects[i]->setMode(mode);
6398 }
6399}
6400
Eric Laurent76c40f72010-07-15 12:50:15 -07006401// setVolume_l() must be called with PlaybackThread::mLock held
6402bool AudioFlinger::EffectChain::setVolume_l(uint32_t *left, uint32_t *right)
Eric Laurent65b65452010-06-01 23:49:17 -07006403{
6404 uint32_t newLeft = *left;
6405 uint32_t newRight = *right;
6406 bool hasControl = false;
Eric Laurent76c40f72010-07-15 12:50:15 -07006407 int ctrlIdx = -1;
6408 size_t size = mEffects.size();
Eric Laurent65b65452010-06-01 23:49:17 -07006409
Eric Laurent76c40f72010-07-15 12:50:15 -07006410 // first update volume controller
6411 for (size_t i = size; i > 0; i--) {
Eric Laurenta92ebfa2010-08-31 13:50:07 -07006412 if (mEffects[i - 1]->isProcessEnabled() &&
Eric Laurent76c40f72010-07-15 12:50:15 -07006413 (mEffects[i - 1]->desc().flags & EFFECT_FLAG_VOLUME_MASK) == EFFECT_FLAG_VOLUME_CTRL) {
6414 ctrlIdx = i - 1;
Eric Laurent0d7e0482010-07-19 06:24:46 -07006415 hasControl = true;
Eric Laurent76c40f72010-07-15 12:50:15 -07006416 break;
6417 }
6418 }
6419
6420 if (ctrlIdx == mVolumeCtrlIdx && *left == mLeftVolume && *right == mRightVolume) {
Eric Laurent0d7e0482010-07-19 06:24:46 -07006421 if (hasControl) {
6422 *left = mNewLeftVolume;
6423 *right = mNewRightVolume;
6424 }
6425 return hasControl;
Eric Laurent76c40f72010-07-15 12:50:15 -07006426 }
6427
6428 mVolumeCtrlIdx = ctrlIdx;
Eric Laurent0d7e0482010-07-19 06:24:46 -07006429 mLeftVolume = newLeft;
6430 mRightVolume = newRight;
Eric Laurent76c40f72010-07-15 12:50:15 -07006431
6432 // second get volume update from volume controller
6433 if (ctrlIdx >= 0) {
6434 mEffects[ctrlIdx]->setVolume(&newLeft, &newRight, true);
Eric Laurent0d7e0482010-07-19 06:24:46 -07006435 mNewLeftVolume = newLeft;
6436 mNewRightVolume = newRight;
Eric Laurent65b65452010-06-01 23:49:17 -07006437 }
6438 // then indicate volume to all other effects in chain.
6439 // Pass altered volume to effects before volume controller
6440 // and requested volume to effects after controller
6441 uint32_t lVol = newLeft;
6442 uint32_t rVol = newRight;
Eric Laurent76c40f72010-07-15 12:50:15 -07006443
Eric Laurent65b65452010-06-01 23:49:17 -07006444 for (size_t i = 0; i < size; i++) {
Eric Laurent76c40f72010-07-15 12:50:15 -07006445 if ((int)i == ctrlIdx) continue;
6446 // this also works for ctrlIdx == -1 when there is no volume controller
6447 if ((int)i > ctrlIdx) {
Eric Laurent65b65452010-06-01 23:49:17 -07006448 lVol = *left;
6449 rVol = *right;
6450 }
6451 mEffects[i]->setVolume(&lVol, &rVol, false);
6452 }
6453 *left = newLeft;
6454 *right = newRight;
6455
6456 return hasControl;
6457}
6458
Eric Laurent65b65452010-06-01 23:49:17 -07006459status_t AudioFlinger::EffectChain::dump(int fd, const Vector<String16>& args)
6460{
6461 const size_t SIZE = 256;
6462 char buffer[SIZE];
6463 String8 result;
6464
6465 snprintf(buffer, SIZE, "Effects for session %d:\n", mSessionId);
6466 result.append(buffer);
6467
6468 bool locked = tryLock(mLock);
6469 // failed to lock - AudioFlinger is probably deadlocked
6470 if (!locked) {
6471 result.append("\tCould not lock mutex:\n");
6472 }
6473
Eric Laurent76c40f72010-07-15 12:50:15 -07006474 result.append("\tNum fx In buffer Out buffer Active tracks:\n");
6475 snprintf(buffer, SIZE, "\t%02d 0x%08x 0x%08x %d\n",
Eric Laurent65b65452010-06-01 23:49:17 -07006476 mEffects.size(),
6477 (uint32_t)mInBuffer,
6478 (uint32_t)mOutBuffer,
Eric Laurent65b65452010-06-01 23:49:17 -07006479 mActiveTrackCnt);
6480 result.append(buffer);
6481 write(fd, result.string(), result.size());
6482
6483 for (size_t i = 0; i < mEffects.size(); ++i) {
6484 sp<EffectModule> effect = mEffects[i];
6485 if (effect != 0) {
6486 effect->dump(fd, args);
6487 }
6488 }
6489
6490 if (locked) {
6491 mLock.unlock();
6492 }
6493
6494 return NO_ERROR;
6495}
6496
6497#undef LOG_TAG
6498#define LOG_TAG "AudioFlinger"
6499
Eric Laurenta553c252009-07-17 12:17:14 -07006500// ----------------------------------------------------------------------------
6501
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07006502status_t AudioFlinger::onTransact(
6503 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
6504{
6505 return BnAudioFlinger::onTransact(code, data, reply, flags);
6506}
6507
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07006508}; // namespace android