blob: 44df5b552df00208a3605b4136ad9fb707442847 [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
Dima Zavin34bb4192011-05-11 14:15:23 -070046#include <system/audio.h>
Dima Zavin290029d2011-06-13 18:16:26 -070047#include <hardware/audio.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// ----------------------------------------------------------------------------
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080056
Eric Laurent8ed6ed02010-07-13 04:45:46 -070057
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070058namespace android {
59
The Android Open Source Project10592532009-03-18 17:39:46 -070060static const char* kDeadlockedString = "AudioFlinger may be deadlocked\n";
61static const char* kHardwareLockedString = "Hardware lock is taken\n";
62
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -080063//static const nsecs_t kStandbyTimeInNsecs = seconds(3);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070064static const float MAX_GAIN = 4096.0f;
Eric Laurent65b65452010-06-01 23:49:17 -070065static const float MAX_GAIN_INT = 0x1000;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070066
67// retry counts for buffer fill timeout
68// 50 * ~20msecs = 1 second
69static const int8_t kMaxTrackRetries = 50;
70static const int8_t kMaxTrackStartupRetries = 50;
Eric Laurentef9500f2010-03-11 14:47:00 -080071// allow less retry attempts on direct output thread.
72// direct outputs can be a scarce resource in audio hardware and should
73// be released as quickly as possible.
74static const int8_t kMaxTrackRetriesDirect = 2;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070075
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -070076static const int kDumpLockRetries = 50;
77static const int kDumpLockSleep = 20000;
78
Dave Sparksd0ac8c02009-09-30 03:09:03 -070079static const nsecs_t kWarningThrottle = seconds(5);
80
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080081
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070082// ----------------------------------------------------------------------------
83
84static bool recordingAllowed() {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070085 if (getpid() == IPCThreadState::self()->getCallingPid()) return true;
86 bool ok = checkCallingPermission(String16("android.permission.RECORD_AUDIO"));
87 if (!ok) LOGE("Request requires android.permission.RECORD_AUDIO");
88 return ok;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070089}
90
91static bool settingsAllowed() {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070092 if (getpid() == IPCThreadState::self()->getCallingPid()) return true;
93 bool ok = checkCallingPermission(String16("android.permission.MODIFY_AUDIO_SETTINGS"));
94 if (!ok) LOGE("Request requires android.permission.MODIFY_AUDIO_SETTINGS");
95 return ok;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070096}
97
Gloria Wang9b3f1522011-02-24 14:51:45 -080098// To collect the amplifier usage
99static void addBatteryData(uint32_t params) {
100 sp<IBinder> binder =
101 defaultServiceManager()->getService(String16("media.player"));
102 sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder);
103 if (service.get() == NULL) {
104 LOGW("Cannot connect to the MediaPlayerService for battery tracking");
105 return;
106 }
107
108 service->addBatteryData(params);
109}
110
Dima Zavin31f188892011-04-18 16:57:27 -0700111static int load_audio_interface(const char *if_name, const hw_module_t **mod,
112 audio_hw_device_t **dev)
113{
114 int rc;
115
116 rc = hw_get_module_by_class(AUDIO_HARDWARE_MODULE_ID, if_name, mod);
117 if (rc)
118 goto out;
119
120 rc = audio_hw_device_open(*mod, dev);
121 LOGE_IF(rc, "couldn't open audio hw device in %s.%s (%s)",
122 AUDIO_HARDWARE_MODULE_ID, if_name, strerror(-rc));
123 if (rc)
124 goto out;
125
126 return 0;
127
128out:
129 *mod = NULL;
130 *dev = NULL;
131 return rc;
132}
133
134static const char *audio_interfaces[] = {
135 "primary",
136 "a2dp",
137 "usb",
138};
139#define ARRAY_SIZE(x) (sizeof((x))/sizeof(((x)[0])))
140
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700141// ----------------------------------------------------------------------------
142
143AudioFlinger::AudioFlinger()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800144 : BnAudioFlinger(),
Dima Zavin31f188892011-04-18 16:57:27 -0700145 mPrimaryHardwareDev(0), mMasterVolume(1.0f), mMasterMute(false), mNextUniqueId(1)
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700146{
Dima Zavin2986f5b2011-04-19 19:04:32 -0700147}
148
149void AudioFlinger::onFirstRef()
150{
Dima Zavin31f188892011-04-18 16:57:27 -0700151 int rc = 0;
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700152
Eric Laurent01635942011-01-18 18:39:02 -0800153 Mutex::Autolock _l(mLock);
154
Dima Zavin31f188892011-04-18 16:57:27 -0700155 /* TODO: move all this work into an Init() function */
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700156 mHardwareStatus = AUDIO_HW_IDLE;
Eric Laurenta553c252009-07-17 12:17:14 -0700157
Dima Zavin31f188892011-04-18 16:57:27 -0700158 for (size_t i = 0; i < ARRAY_SIZE(audio_interfaces); i++) {
159 const hw_module_t *mod;
160 audio_hw_device_t *dev;
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700161
Dima Zavin31f188892011-04-18 16:57:27 -0700162 rc = load_audio_interface(audio_interfaces[i], &mod, &dev);
163 if (rc)
164 continue;
165
166 LOGI("Loaded %s audio interface from %s (%s)", audio_interfaces[i],
167 mod->name, mod->id);
168 mAudioHwDevs.push(dev);
169
170 if (!mPrimaryHardwareDev) {
171 mPrimaryHardwareDev = dev;
172 LOGI("Using '%s' (%s.%s) as the primary audio interface",
Dima Zavin2986f5b2011-04-19 19:04:32 -0700173 mod->name, mod->id, audio_interfaces[i]);
Dima Zavin31f188892011-04-18 16:57:27 -0700174 }
175 }
Eric Laurenta553c252009-07-17 12:17:14 -0700176
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700177 mHardwareStatus = AUDIO_HW_INIT;
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700178
Dima Zavin31f188892011-04-18 16:57:27 -0700179 if (!mPrimaryHardwareDev || mAudioHwDevs.size() == 0) {
180 LOGE("Primary audio interface not found");
181 return;
182 }
183
184 for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
185 audio_hw_device_t *dev = mAudioHwDevs[i];
186
187 mHardwareStatus = AUDIO_HW_INIT;
188 rc = dev->init_check(dev);
189 if (rc == 0) {
190 AutoMutex lock(mHardwareLock);
191
192 mMode = AUDIO_MODE_NORMAL;
193 mHardwareStatus = AUDIO_HW_SET_MODE;
194 dev->set_mode(dev, mMode);
195 mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
196 dev->set_master_volume(dev, 1.0f);
197 mHardwareStatus = AUDIO_HW_IDLE;
198 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700199 }
200}
201
Dima Zavin2986f5b2011-04-19 19:04:32 -0700202status_t AudioFlinger::initCheck() const
203{
204 Mutex::Autolock _l(mLock);
205 if (mPrimaryHardwareDev == NULL || mAudioHwDevs.size() == 0)
206 return NO_INIT;
207 return NO_ERROR;
208}
209
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700210AudioFlinger::~AudioFlinger()
211{
Dima Zavin31f188892011-04-18 16:57:27 -0700212 int num_devs = mAudioHwDevs.size();
213
Eric Laurent7954c462009-08-28 10:39:03 -0700214 while (!mRecordThreads.isEmpty()) {
215 // closeInput() will remove first entry from mRecordThreads
216 closeInput(mRecordThreads.keyAt(0));
217 }
218 while (!mPlaybackThreads.isEmpty()) {
219 // closeOutput() will remove first entry from mPlaybackThreads
220 closeOutput(mPlaybackThreads.keyAt(0));
221 }
Dima Zavin31f188892011-04-18 16:57:27 -0700222
223 for (int i = 0; i < num_devs; i++) {
224 audio_hw_device_t *dev = mAudioHwDevs[i];
225 audio_hw_device_close(dev);
Eric Laurent7954c462009-08-28 10:39:03 -0700226 }
Dima Zavin31f188892011-04-18 16:57:27 -0700227 mAudioHwDevs.clear();
The Android Open Source Projectb7986892009-01-09 17:51:23 -0800228}
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800229
Dima Zavin31f188892011-04-18 16:57:27 -0700230audio_hw_device_t* AudioFlinger::findSuitableHwDev_l(uint32_t devices)
231{
232 /* first matching HW device is returned */
233 for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
234 audio_hw_device_t *dev = mAudioHwDevs[i];
235 if ((dev->get_supported_devices(dev) & devices) == devices)
236 return dev;
237 }
238 return NULL;
239}
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -0700240
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700241status_t AudioFlinger::dumpClients(int fd, const Vector<String16>& args)
242{
243 const size_t SIZE = 256;
244 char buffer[SIZE];
245 String8 result;
246
247 result.append("Clients:\n");
248 for (size_t i = 0; i < mClients.size(); ++i) {
249 wp<Client> wClient = mClients.valueAt(i);
250 if (wClient != 0) {
251 sp<Client> client = wClient.promote();
252 if (client != 0) {
253 snprintf(buffer, SIZE, " pid: %d\n", client->pid());
254 result.append(buffer);
255 }
256 }
257 }
258 write(fd, result.string(), result.size());
259 return NO_ERROR;
260}
261
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700262
263status_t AudioFlinger::dumpInternals(int fd, const Vector<String16>& args)
264{
265 const size_t SIZE = 256;
266 char buffer[SIZE];
267 String8 result;
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -0700268 int hardwareStatus = mHardwareStatus;
Eric Laurenta553c252009-07-17 12:17:14 -0700269
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -0700270 snprintf(buffer, SIZE, "Hardware status: %d\n", hardwareStatus);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700271 result.append(buffer);
272 write(fd, result.string(), result.size());
273 return NO_ERROR;
274}
275
276status_t AudioFlinger::dumpPermissionDenial(int fd, const Vector<String16>& args)
277{
278 const size_t SIZE = 256;
279 char buffer[SIZE];
280 String8 result;
281 snprintf(buffer, SIZE, "Permission Denial: "
282 "can't dump AudioFlinger from pid=%d, uid=%d\n",
283 IPCThreadState::self()->getCallingPid(),
284 IPCThreadState::self()->getCallingUid());
285 result.append(buffer);
286 write(fd, result.string(), result.size());
287 return NO_ERROR;
288}
289
The Android Open Source Project10592532009-03-18 17:39:46 -0700290static bool tryLock(Mutex& mutex)
291{
292 bool locked = false;
293 for (int i = 0; i < kDumpLockRetries; ++i) {
294 if (mutex.tryLock() == NO_ERROR) {
295 locked = true;
296 break;
297 }
298 usleep(kDumpLockSleep);
299 }
300 return locked;
301}
302
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700303status_t AudioFlinger::dump(int fd, const Vector<String16>& args)
304{
305 if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
306 dumpPermissionDenial(fd, args);
307 } else {
The Android Open Source Project10592532009-03-18 17:39:46 -0700308 // get state of hardware lock
309 bool hardwareLocked = tryLock(mHardwareLock);
310 if (!hardwareLocked) {
311 String8 result(kHardwareLockedString);
312 write(fd, result.string(), result.size());
313 } else {
314 mHardwareLock.unlock();
315 }
316
317 bool locked = tryLock(mLock);
318
319 // failed to lock - AudioFlinger is probably deadlocked
320 if (!locked) {
321 String8 result(kDeadlockedString);
322 write(fd, result.string(), result.size());
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -0700323 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700324
325 dumpClients(fd, args);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700326 dumpInternals(fd, args);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800327
Eric Laurenta553c252009-07-17 12:17:14 -0700328 // dump playback threads
329 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
Eric Laurentddb78e72009-07-28 08:44:33 -0700330 mPlaybackThreads.valueAt(i)->dump(fd, args);
Eric Laurenta553c252009-07-17 12:17:14 -0700331 }
332
333 // dump record threads
Eric Laurent102313a2009-07-23 13:35:01 -0700334 for (size_t i = 0; i < mRecordThreads.size(); i++) {
Eric Laurentddb78e72009-07-28 08:44:33 -0700335 mRecordThreads.valueAt(i)->dump(fd, args);
Eric Laurenta553c252009-07-17 12:17:14 -0700336 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800337
Dima Zavin31f188892011-04-18 16:57:27 -0700338 // dump all hardware devs
339 for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
340 audio_hw_device_t *dev = mAudioHwDevs[i];
341 dev->dump(dev, fd);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700342 }
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -0700343 if (locked) mLock.unlock();
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700344 }
345 return NO_ERROR;
346}
347
Eric Laurenta553c252009-07-17 12:17:14 -0700348
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700349// IAudioFlinger interface
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800350
351
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700352sp<IAudioTrack> AudioFlinger::createTrack(
353 pid_t pid,
354 int streamType,
355 uint32_t sampleRate,
Jean-Michel Trivi54392232011-05-24 15:53:33 -0700356 uint32_t format,
357 uint32_t channelMask,
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800358 int frameCount,
359 uint32_t flags,
360 const sp<IMemory>& sharedBuffer,
Eric Laurentddb78e72009-07-28 08:44:33 -0700361 int output,
Eric Laurent65b65452010-06-01 23:49:17 -0700362 int *sessionId,
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800363 status_t *status)
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700364{
Eric Laurenta553c252009-07-17 12:17:14 -0700365 sp<PlaybackThread::Track> track;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700366 sp<TrackHandle> trackHandle;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700367 sp<Client> client;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800368 wp<Client> wclient;
369 status_t lStatus;
Eric Laurent65b65452010-06-01 23:49:17 -0700370 int lSessionId;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700371
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700372 if (streamType >= AUDIO_STREAM_CNT) {
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800373 LOGE("invalid stream type");
374 lStatus = BAD_VALUE;
375 goto Exit;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700376 }
377
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800378 {
379 Mutex::Autolock _l(mLock);
Eric Laurenta553c252009-07-17 12:17:14 -0700380 PlaybackThread *thread = checkPlaybackThread_l(output);
Eric Laurent493941b2010-07-28 01:32:47 -0700381 PlaybackThread *effectThread = NULL;
Eric Laurenta553c252009-07-17 12:17:14 -0700382 if (thread == NULL) {
383 LOGE("unknown output thread");
384 lStatus = BAD_VALUE;
385 goto Exit;
386 }
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800387
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800388 wclient = mClients.valueFor(pid);
389
390 if (wclient != NULL) {
391 client = wclient.promote();
392 } else {
393 client = new Client(this, pid);
394 mClients.add(pid, client);
395 }
Eric Laurent65b65452010-06-01 23:49:17 -0700396
Eric Laurent65b65452010-06-01 23:49:17 -0700397 LOGV("createTrack() sessionId: %d", (sessionId == NULL) ? -2 : *sessionId);
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700398 if (sessionId != NULL && *sessionId != AUDIO_SESSION_OUTPUT_MIX) {
Eric Laurent8ed6ed02010-07-13 04:45:46 -0700399 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
Eric Laurent493941b2010-07-28 01:32:47 -0700400 sp<PlaybackThread> t = mPlaybackThreads.valueAt(i);
401 if (mPlaybackThreads.keyAt(i) != output) {
402 // prevent same audio session on different output threads
403 uint32_t sessions = t->hasAudioSession(*sessionId);
404 if (sessions & PlaybackThread::TRACK_SESSION) {
405 lStatus = BAD_VALUE;
406 goto Exit;
407 }
408 // check if an effect with same session ID is waiting for a track to be created
409 if (sessions & PlaybackThread::EFFECT_SESSION) {
410 effectThread = t.get();
411 }
Eric Laurent8ed6ed02010-07-13 04:45:46 -0700412 }
413 }
Eric Laurent65b65452010-06-01 23:49:17 -0700414 lSessionId = *sessionId;
415 } else {
Eric Laurent8ed6ed02010-07-13 04:45:46 -0700416 // if no audio session id is provided, create one here
Eric Laurentf3d6dd02010-11-18 08:40:16 -0800417 lSessionId = nextUniqueId_l();
Eric Laurent65b65452010-06-01 23:49:17 -0700418 if (sessionId != NULL) {
419 *sessionId = lSessionId;
420 }
421 }
422 LOGV("createTrack() lSessionId: %d", lSessionId);
423
Eric Laurenta553c252009-07-17 12:17:14 -0700424 track = thread->createTrack_l(client, streamType, sampleRate, format,
Jean-Michel Trivi54392232011-05-24 15:53:33 -0700425 channelMask, frameCount, sharedBuffer, lSessionId, &lStatus);
Eric Laurent493941b2010-07-28 01:32:47 -0700426
427 // move effect chain to this output thread if an effect on same session was waiting
428 // for a track to be created
429 if (lStatus == NO_ERROR && effectThread != NULL) {
430 Mutex::Autolock _dl(thread->mLock);
431 Mutex::Autolock _sl(effectThread->mLock);
432 moveEffectChain_l(lSessionId, effectThread, thread, true);
433 }
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -0700434 }
435 if (lStatus == NO_ERROR) {
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800436 trackHandle = new TrackHandle(track);
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -0700437 } else {
Eric Laurentb9481d82009-09-17 05:12:56 -0700438 // remove local strong reference to Client before deleting the Track so that the Client
439 // destructor is called by the TrackBase destructor with mLock held
440 client.clear();
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -0700441 track.clear();
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800442 }
443
444Exit:
445 if(status) {
446 *status = lStatus;
447 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700448 return trackHandle;
449}
450
Eric Laurentddb78e72009-07-28 08:44:33 -0700451uint32_t AudioFlinger::sampleRate(int output) const
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700452{
Eric Laurenta553c252009-07-17 12:17:14 -0700453 Mutex::Autolock _l(mLock);
454 PlaybackThread *thread = checkPlaybackThread_l(output);
455 if (thread == NULL) {
Eric Laurentddb78e72009-07-28 08:44:33 -0700456 LOGW("sampleRate() unknown thread %d", output);
Eric Laurenta553c252009-07-17 12:17:14 -0700457 return 0;
458 }
459 return thread->sampleRate();
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700460}
461
Eric Laurentddb78e72009-07-28 08:44:33 -0700462int AudioFlinger::channelCount(int output) const
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700463{
Eric Laurenta553c252009-07-17 12:17:14 -0700464 Mutex::Autolock _l(mLock);
465 PlaybackThread *thread = checkPlaybackThread_l(output);
466 if (thread == NULL) {
Eric Laurentddb78e72009-07-28 08:44:33 -0700467 LOGW("channelCount() unknown thread %d", output);
Eric Laurenta553c252009-07-17 12:17:14 -0700468 return 0;
469 }
470 return thread->channelCount();
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700471}
472
Jean-Michel Trivi54392232011-05-24 15:53:33 -0700473uint32_t AudioFlinger::format(int output) const
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700474{
Eric Laurenta553c252009-07-17 12:17:14 -0700475 Mutex::Autolock _l(mLock);
476 PlaybackThread *thread = checkPlaybackThread_l(output);
477 if (thread == NULL) {
Eric Laurentddb78e72009-07-28 08:44:33 -0700478 LOGW("format() unknown thread %d", output);
Eric Laurenta553c252009-07-17 12:17:14 -0700479 return 0;
480 }
481 return thread->format();
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700482}
483
Eric Laurentddb78e72009-07-28 08:44:33 -0700484size_t AudioFlinger::frameCount(int output) const
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700485{
Eric Laurenta553c252009-07-17 12:17:14 -0700486 Mutex::Autolock _l(mLock);
487 PlaybackThread *thread = checkPlaybackThread_l(output);
488 if (thread == NULL) {
Eric Laurentddb78e72009-07-28 08:44:33 -0700489 LOGW("frameCount() unknown thread %d", output);
Eric Laurenta553c252009-07-17 12:17:14 -0700490 return 0;
491 }
492 return thread->frameCount();
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700493}
494
Eric Laurentddb78e72009-07-28 08:44:33 -0700495uint32_t AudioFlinger::latency(int output) const
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800496{
Eric Laurenta553c252009-07-17 12:17:14 -0700497 Mutex::Autolock _l(mLock);
498 PlaybackThread *thread = checkPlaybackThread_l(output);
499 if (thread == NULL) {
Eric Laurentddb78e72009-07-28 08:44:33 -0700500 LOGW("latency() unknown thread %d", output);
Eric Laurenta553c252009-07-17 12:17:14 -0700501 return 0;
502 }
503 return thread->latency();
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800504}
505
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700506status_t AudioFlinger::setMasterVolume(float value)
507{
508 // check calling permissions
509 if (!settingsAllowed()) {
510 return PERMISSION_DENIED;
511 }
512
513 // when hw supports master volume, don't scale in sw mixer
Eric Laurent01635942011-01-18 18:39:02 -0800514 { // scope for the lock
515 AutoMutex lock(mHardwareLock);
516 mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
Dima Zavin31f188892011-04-18 16:57:27 -0700517 if (mPrimaryHardwareDev->set_master_volume(mPrimaryHardwareDev, value) == NO_ERROR) {
Eric Laurent01635942011-01-18 18:39:02 -0800518 value = 1.0f;
519 }
520 mHardwareStatus = AUDIO_HW_IDLE;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700521 }
Eric Laurenta553c252009-07-17 12:17:14 -0700522
Eric Laurent01635942011-01-18 18:39:02 -0800523 Mutex::Autolock _l(mLock);
Eric Laurenta553c252009-07-17 12:17:14 -0700524 mMasterVolume = value;
525 for (uint32_t i = 0; i < mPlaybackThreads.size(); i++)
Eric Laurentddb78e72009-07-28 08:44:33 -0700526 mPlaybackThreads.valueAt(i)->setMasterVolume(value);
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -0700527
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700528 return NO_ERROR;
529}
530
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700531status_t AudioFlinger::setMode(int mode)
532{
Eric Laurent53334cd2010-06-23 17:38:20 -0700533 status_t ret;
534
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700535 // check calling permissions
536 if (!settingsAllowed()) {
537 return PERMISSION_DENIED;
538 }
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700539 if ((mode < 0) || (mode >= AUDIO_MODE_CNT)) {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700540 LOGW("Illegal value: setMode(%d)", mode);
541 return BAD_VALUE;
542 }
543
Eric Laurent53334cd2010-06-23 17:38:20 -0700544 { // scope for the lock
545 AutoMutex lock(mHardwareLock);
546 mHardwareStatus = AUDIO_HW_SET_MODE;
Dima Zavin31f188892011-04-18 16:57:27 -0700547 ret = mPrimaryHardwareDev->set_mode(mPrimaryHardwareDev, mode);
Eric Laurent53334cd2010-06-23 17:38:20 -0700548 mHardwareStatus = AUDIO_HW_IDLE;
Glenn Kasten871c16c2010-03-05 12:18:01 -0800549 }
Eric Laurent53334cd2010-06-23 17:38:20 -0700550
551 if (NO_ERROR == ret) {
552 Mutex::Autolock _l(mLock);
553 mMode = mode;
554 for (uint32_t i = 0; i < mPlaybackThreads.size(); i++)
555 mPlaybackThreads.valueAt(i)->setMode(mode);
Eric Laurent53334cd2010-06-23 17:38:20 -0700556 }
557
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700558 return ret;
559}
560
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700561status_t AudioFlinger::setMicMute(bool state)
562{
563 // check calling permissions
564 if (!settingsAllowed()) {
565 return PERMISSION_DENIED;
566 }
567
568 AutoMutex lock(mHardwareLock);
569 mHardwareStatus = AUDIO_HW_SET_MIC_MUTE;
Dima Zavin31f188892011-04-18 16:57:27 -0700570 status_t ret = mPrimaryHardwareDev->set_mic_mute(mPrimaryHardwareDev, state);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700571 mHardwareStatus = AUDIO_HW_IDLE;
572 return ret;
573}
574
575bool AudioFlinger::getMicMute() const
576{
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700577 bool state = AUDIO_MODE_INVALID;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700578 mHardwareStatus = AUDIO_HW_GET_MIC_MUTE;
Dima Zavin31f188892011-04-18 16:57:27 -0700579 mPrimaryHardwareDev->get_mic_mute(mPrimaryHardwareDev, &state);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700580 mHardwareStatus = AUDIO_HW_IDLE;
581 return state;
582}
583
584status_t AudioFlinger::setMasterMute(bool muted)
585{
586 // check calling permissions
587 if (!settingsAllowed()) {
588 return PERMISSION_DENIED;
589 }
Eric Laurenta553c252009-07-17 12:17:14 -0700590
Eric Laurent01635942011-01-18 18:39:02 -0800591 Mutex::Autolock _l(mLock);
Eric Laurenta553c252009-07-17 12:17:14 -0700592 mMasterMute = muted;
593 for (uint32_t i = 0; i < mPlaybackThreads.size(); i++)
Eric Laurentddb78e72009-07-28 08:44:33 -0700594 mPlaybackThreads.valueAt(i)->setMasterMute(muted);
Eric Laurenta553c252009-07-17 12:17:14 -0700595
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700596 return NO_ERROR;
597}
598
599float AudioFlinger::masterVolume() const
600{
Eric Laurenta553c252009-07-17 12:17:14 -0700601 return mMasterVolume;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700602}
603
604bool AudioFlinger::masterMute() const
605{
Eric Laurenta553c252009-07-17 12:17:14 -0700606 return mMasterMute;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700607}
608
Eric Laurentddb78e72009-07-28 08:44:33 -0700609status_t AudioFlinger::setStreamVolume(int stream, float value, int output)
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700610{
611 // check calling permissions
612 if (!settingsAllowed()) {
613 return PERMISSION_DENIED;
614 }
615
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700616 if (stream < 0 || uint32_t(stream) >= AUDIO_STREAM_CNT) {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700617 return BAD_VALUE;
618 }
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800619
Eric Laurenta553c252009-07-17 12:17:14 -0700620 AutoMutex lock(mLock);
621 PlaybackThread *thread = NULL;
622 if (output) {
623 thread = checkPlaybackThread_l(output);
624 if (thread == NULL) {
625 return BAD_VALUE;
626 }
627 }
628
Eric Laurenta553c252009-07-17 12:17:14 -0700629 mStreamTypes[stream].volume = value;
630
631 if (thread == NULL) {
Eric Laurent415f3e22009-10-21 08:14:22 -0700632 for (uint32_t i = 0; i < mPlaybackThreads.size(); i++) {
Eric Laurentddb78e72009-07-28 08:44:33 -0700633 mPlaybackThreads.valueAt(i)->setStreamVolume(stream, value);
Eric Laurent415f3e22009-10-21 08:14:22 -0700634 }
Eric Laurenta553c252009-07-17 12:17:14 -0700635 } else {
636 thread->setStreamVolume(stream, value);
637 }
Eric Laurentef028272009-04-21 07:56:33 -0700638
Eric Laurent415f3e22009-10-21 08:14:22 -0700639 return NO_ERROR;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700640}
641
642status_t AudioFlinger::setStreamMute(int stream, bool muted)
643{
644 // check calling permissions
645 if (!settingsAllowed()) {
646 return PERMISSION_DENIED;
647 }
648
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700649 if (stream < 0 || uint32_t(stream) >= AUDIO_STREAM_CNT ||
650 uint32_t(stream) == AUDIO_STREAM_ENFORCED_AUDIBLE) {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700651 return BAD_VALUE;
652 }
The Android Open Source Project10592532009-03-18 17:39:46 -0700653
Eric Laurent01635942011-01-18 18:39:02 -0800654 AutoMutex lock(mLock);
Eric Laurenta553c252009-07-17 12:17:14 -0700655 mStreamTypes[stream].mute = muted;
656 for (uint32_t i = 0; i < mPlaybackThreads.size(); i++)
Eric Laurentddb78e72009-07-28 08:44:33 -0700657 mPlaybackThreads.valueAt(i)->setStreamMute(stream, muted);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800658
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700659 return NO_ERROR;
660}
661
Eric Laurentddb78e72009-07-28 08:44:33 -0700662float AudioFlinger::streamVolume(int stream, int output) const
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700663{
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700664 if (stream < 0 || uint32_t(stream) >= AUDIO_STREAM_CNT) {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700665 return 0.0f;
666 }
Eric Laurenta553c252009-07-17 12:17:14 -0700667
668 AutoMutex lock(mLock);
669 float volume;
670 if (output) {
671 PlaybackThread *thread = checkPlaybackThread_l(output);
672 if (thread == NULL) {
673 return 0.0f;
674 }
675 volume = thread->streamVolume(stream);
676 } else {
677 volume = mStreamTypes[stream].volume;
678 }
679
Eric Laurentef028272009-04-21 07:56:33 -0700680 return volume;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700681}
682
683bool AudioFlinger::streamMute(int stream) const
684{
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700685 if (stream < 0 || stream >= (int)AUDIO_STREAM_CNT) {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700686 return true;
687 }
Eric Laurenta553c252009-07-17 12:17:14 -0700688
689 return mStreamTypes[stream].mute;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700690}
691
Eric Laurentddb78e72009-07-28 08:44:33 -0700692status_t AudioFlinger::setParameters(int ioHandle, const String8& keyValuePairs)
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700693{
Eric Laurenta553c252009-07-17 12:17:14 -0700694 status_t result;
695
Eric Laurentddb78e72009-07-28 08:44:33 -0700696 LOGV("setParameters(): io %d, keyvalue %s, tid %d, calling tid %d",
Eric Laurenta553c252009-07-17 12:17:14 -0700697 ioHandle, keyValuePairs.string(), gettid(), IPCThreadState::self()->getCallingPid());
698 // check calling permissions
699 if (!settingsAllowed()) {
700 return PERMISSION_DENIED;
The Android Open Source Project9266c552009-01-15 16:12:10 -0800701 }
Eric Laurenta553c252009-07-17 12:17:14 -0700702
703 // ioHandle == 0 means the parameters are global to the audio hardware interface
704 if (ioHandle == 0) {
705 AutoMutex lock(mHardwareLock);
706 mHardwareStatus = AUDIO_SET_PARAMETER;
Dima Zavin31f188892011-04-18 16:57:27 -0700707 status_t final_result = NO_ERROR;
708 for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
709 audio_hw_device_t *dev = mAudioHwDevs[i];
710 result = dev->set_parameters(dev, keyValuePairs.string());
711 final_result = result ?: final_result;
712 }
Eric Laurenta553c252009-07-17 12:17:14 -0700713 mHardwareStatus = AUDIO_HW_IDLE;
Dima Zavin31f188892011-04-18 16:57:27 -0700714 return final_result;
Eric Laurenta553c252009-07-17 12:17:14 -0700715 }
716
Eric Laurentb7d94602009-09-29 11:12:57 -0700717 // hold a strong ref on thread in case closeOutput() or closeInput() is called
718 // and the thread is exited once the lock is released
719 sp<ThreadBase> thread;
720 {
721 Mutex::Autolock _l(mLock);
722 thread = checkPlaybackThread_l(ioHandle);
723 if (thread == NULL) {
724 thread = checkRecordThread_l(ioHandle);
725 }
Eric Laurenta553c252009-07-17 12:17:14 -0700726 }
Eric Laurentb7d94602009-09-29 11:12:57 -0700727 if (thread != NULL) {
Glenn Kasten871c16c2010-03-05 12:18:01 -0800728 result = thread->setParameters(keyValuePairs);
Glenn Kasten871c16c2010-03-05 12:18:01 -0800729 return result;
Eric Laurenta553c252009-07-17 12:17:14 -0700730 }
Eric Laurenta553c252009-07-17 12:17:14 -0700731 return BAD_VALUE;
732}
733
Eric Laurentddb78e72009-07-28 08:44:33 -0700734String8 AudioFlinger::getParameters(int ioHandle, const String8& keys)
Eric Laurenta553c252009-07-17 12:17:14 -0700735{
Eric Laurentddb78e72009-07-28 08:44:33 -0700736// LOGV("getParameters() io %d, keys %s, tid %d, calling tid %d",
Eric Laurenta553c252009-07-17 12:17:14 -0700737// ioHandle, keys.string(), gettid(), IPCThreadState::self()->getCallingPid());
738
739 if (ioHandle == 0) {
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700740 String8 out_s8;
741
Dima Zavin31f188892011-04-18 16:57:27 -0700742 for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
743 audio_hw_device_t *dev = mAudioHwDevs[i];
744 char *s = dev->get_parameters(dev, keys.string());
745 out_s8 += String8(s);
746 free(s);
747 }
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700748 return out_s8;
Eric Laurenta553c252009-07-17 12:17:14 -0700749 }
Eric Laurentb7d94602009-09-29 11:12:57 -0700750
751 Mutex::Autolock _l(mLock);
752
Eric Laurenta553c252009-07-17 12:17:14 -0700753 PlaybackThread *playbackThread = checkPlaybackThread_l(ioHandle);
754 if (playbackThread != NULL) {
755 return playbackThread->getParameters(keys);
756 }
757 RecordThread *recordThread = checkRecordThread_l(ioHandle);
758 if (recordThread != NULL) {
759 return recordThread->getParameters(keys);
760 }
761 return String8("");
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700762}
763
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800764size_t AudioFlinger::getInputBufferSize(uint32_t sampleRate, int format, int channelCount)
765{
Dima Zavin31f188892011-04-18 16:57:27 -0700766 return mPrimaryHardwareDev->get_input_buffer_size(mPrimaryHardwareDev, sampleRate, format, channelCount);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800767}
768
Eric Laurent47d0a922010-02-26 02:47:27 -0800769unsigned int AudioFlinger::getInputFramesLost(int ioHandle)
770{
771 if (ioHandle == 0) {
772 return 0;
773 }
774
775 Mutex::Autolock _l(mLock);
776
777 RecordThread *recordThread = checkRecordThread_l(ioHandle);
778 if (recordThread != NULL) {
779 return recordThread->getInputFramesLost();
780 }
781 return 0;
782}
783
Eric Laurent415f3e22009-10-21 08:14:22 -0700784status_t AudioFlinger::setVoiceVolume(float value)
785{
786 // check calling permissions
787 if (!settingsAllowed()) {
788 return PERMISSION_DENIED;
789 }
790
791 AutoMutex lock(mHardwareLock);
792 mHardwareStatus = AUDIO_SET_VOICE_VOLUME;
Dima Zavin31f188892011-04-18 16:57:27 -0700793 status_t ret = mPrimaryHardwareDev->set_voice_volume(mPrimaryHardwareDev, value);
Eric Laurent415f3e22009-10-21 08:14:22 -0700794 mHardwareStatus = AUDIO_HW_IDLE;
795
796 return ret;
797}
798
Eric Laurent0986e792010-01-19 17:37:09 -0800799status_t AudioFlinger::getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames, int output)
800{
801 status_t status;
802
803 Mutex::Autolock _l(mLock);
804
805 PlaybackThread *playbackThread = checkPlaybackThread_l(output);
806 if (playbackThread != NULL) {
807 return playbackThread->getRenderPosition(halFrames, dspFrames);
808 }
809
810 return BAD_VALUE;
811}
812
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800813void AudioFlinger::registerClient(const sp<IAudioFlingerClient>& client)
814{
Eric Laurenta553c252009-07-17 12:17:14 -0700815
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800816 Mutex::Autolock _l(mLock);
817
Eric Laurent4f0f17d2010-05-12 02:05:53 -0700818 int pid = IPCThreadState::self()->getCallingPid();
819 if (mNotificationClients.indexOfKey(pid) < 0) {
820 sp<NotificationClient> notificationClient = new NotificationClient(this,
821 client,
822 pid);
823 LOGV("registerClient() client %p, pid %d", notificationClient.get(), pid);
Eric Laurenta553c252009-07-17 12:17:14 -0700824
Eric Laurent4f0f17d2010-05-12 02:05:53 -0700825 mNotificationClients.add(pid, notificationClient);
Eric Laurenta553c252009-07-17 12:17:14 -0700826
Eric Laurent4f0f17d2010-05-12 02:05:53 -0700827 sp<IBinder> binder = client->asBinder();
828 binder->linkToDeath(notificationClient);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800829
Eric Laurent4f0f17d2010-05-12 02:05:53 -0700830 // the config change is always sent from playback or record threads to avoid deadlock
831 // with AudioSystem::gLock
832 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
833 mPlaybackThreads.valueAt(i)->sendConfigEvent(AudioSystem::OUTPUT_OPENED);
834 }
Eric Laurenta553c252009-07-17 12:17:14 -0700835
Eric Laurent4f0f17d2010-05-12 02:05:53 -0700836 for (size_t i = 0; i < mRecordThreads.size(); i++) {
837 mRecordThreads.valueAt(i)->sendConfigEvent(AudioSystem::INPUT_OPENED);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800838 }
839 }
840}
841
Eric Laurent4f0f17d2010-05-12 02:05:53 -0700842void AudioFlinger::removeNotificationClient(pid_t pid)
843{
844 Mutex::Autolock _l(mLock);
845
846 int index = mNotificationClients.indexOfKey(pid);
847 if (index >= 0) {
848 sp <NotificationClient> client = mNotificationClients.valueFor(pid);
849 LOGV("removeNotificationClient() %p, pid %d", client.get(), pid);
Eric Laurent4f0f17d2010-05-12 02:05:53 -0700850 mNotificationClients.removeItem(pid);
851 }
852}
853
Eric Laurent296a0ec2009-09-15 07:10:12 -0700854// audioConfigChanged_l() must be called with AudioFlinger::mLock held
Eric Laurent4f0f17d2010-05-12 02:05:53 -0700855void AudioFlinger::audioConfigChanged_l(int event, int ioHandle, void *param2)
856{
Eric Laurent49f02be2009-11-19 09:00:56 -0800857 size_t size = mNotificationClients.size();
858 for (size_t i = 0; i < size; i++) {
Eric Laurent4f0f17d2010-05-12 02:05:53 -0700859 mNotificationClients.valueAt(i)->client()->ioConfigChanged(event, ioHandle, param2);
Eric Laurenta553c252009-07-17 12:17:14 -0700860 }
861}
862
Eric Laurentb9481d82009-09-17 05:12:56 -0700863// removeClient_l() must be called with AudioFlinger::mLock held
864void AudioFlinger::removeClient_l(pid_t pid)
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700865{
Eric Laurentb9481d82009-09-17 05:12:56 -0700866 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 -0700867 mClients.removeItem(pid);
868}
869
Eric Laurent4f0f17d2010-05-12 02:05:53 -0700870
Eric Laurenta553c252009-07-17 12:17:14 -0700871// ----------------------------------------------------------------------------
872
Eric Laurent49f02be2009-11-19 09:00:56 -0800873AudioFlinger::ThreadBase::ThreadBase(const sp<AudioFlinger>& audioFlinger, int id)
Eric Laurenta553c252009-07-17 12:17:14 -0700874 : Thread(false),
875 mAudioFlinger(audioFlinger), mSampleRate(0), mFrameCount(0), mChannelCount(0),
Eric Laurentb0a01472010-05-14 05:45:46 -0700876 mFrameSize(1), mFormat(0), mStandby(false), mId(id), mExiting(false)
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700877{
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800878}
879
Eric Laurenta553c252009-07-17 12:17:14 -0700880AudioFlinger::ThreadBase::~ThreadBase()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800881{
Eric Laurent8fce46a2009-08-04 09:45:33 -0700882 mParamCond.broadcast();
883 mNewParameters.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800884}
885
Eric Laurenta553c252009-07-17 12:17:14 -0700886void AudioFlinger::ThreadBase::exit()
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -0700887{
Eric Laurentb7d94602009-09-29 11:12:57 -0700888 // keep a strong ref on ourself so that we wont get
Eric Laurenta553c252009-07-17 12:17:14 -0700889 // destroyed in the middle of requestExitAndWait()
890 sp <ThreadBase> strongMe = this;
891
892 LOGV("ThreadBase::exit");
893 {
894 AutoMutex lock(&mLock);
Eric Laurent49f02be2009-11-19 09:00:56 -0800895 mExiting = true;
Eric Laurenta553c252009-07-17 12:17:14 -0700896 requestExit();
897 mWaitWorkCV.signal();
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -0700898 }
Eric Laurenta553c252009-07-17 12:17:14 -0700899 requestExitAndWait();
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -0700900}
Eric Laurenta553c252009-07-17 12:17:14 -0700901
902uint32_t AudioFlinger::ThreadBase::sampleRate() const
903{
904 return mSampleRate;
905}
906
907int AudioFlinger::ThreadBase::channelCount() const
908{
Eric Laurentb0a01472010-05-14 05:45:46 -0700909 return (int)mChannelCount;
Eric Laurenta553c252009-07-17 12:17:14 -0700910}
911
Jean-Michel Trivi54392232011-05-24 15:53:33 -0700912uint32_t AudioFlinger::ThreadBase::format() const
Eric Laurenta553c252009-07-17 12:17:14 -0700913{
914 return mFormat;
915}
916
917size_t AudioFlinger::ThreadBase::frameCount() const
918{
919 return mFrameCount;
920}
921
922status_t AudioFlinger::ThreadBase::setParameters(const String8& keyValuePairs)
923{
Eric Laurent8fce46a2009-08-04 09:45:33 -0700924 status_t status;
Eric Laurenta553c252009-07-17 12:17:14 -0700925
Eric Laurent8fce46a2009-08-04 09:45:33 -0700926 LOGV("ThreadBase::setParameters() %s", keyValuePairs.string());
Eric Laurenta553c252009-07-17 12:17:14 -0700927 Mutex::Autolock _l(mLock);
Eric Laurenta553c252009-07-17 12:17:14 -0700928
Eric Laurent8fce46a2009-08-04 09:45:33 -0700929 mNewParameters.add(keyValuePairs);
Eric Laurenta553c252009-07-17 12:17:14 -0700930 mWaitWorkCV.signal();
Eric Laurentb7d94602009-09-29 11:12:57 -0700931 // wait condition with timeout in case the thread loop has exited
932 // before the request could be processed
933 if (mParamCond.waitRelative(mLock, seconds(2)) == NO_ERROR) {
934 status = mParamStatus;
935 mWaitWorkCV.signal();
936 } else {
937 status = TIMED_OUT;
938 }
Eric Laurent8fce46a2009-08-04 09:45:33 -0700939 return status;
Eric Laurenta553c252009-07-17 12:17:14 -0700940}
941
942void AudioFlinger::ThreadBase::sendConfigEvent(int event, int param)
943{
944 Mutex::Autolock _l(mLock);
Eric Laurent8fce46a2009-08-04 09:45:33 -0700945 sendConfigEvent_l(event, param);
946}
947
948// sendConfigEvent_l() must be called with ThreadBase::mLock held
949void AudioFlinger::ThreadBase::sendConfigEvent_l(int event, int param)
950{
Eric Laurenta553c252009-07-17 12:17:14 -0700951 ConfigEvent *configEvent = new ConfigEvent();
952 configEvent->mEvent = event;
953 configEvent->mParam = param;
954 mConfigEvents.add(configEvent);
955 LOGV("sendConfigEvent() num events %d event %d, param %d", mConfigEvents.size(), event, param);
956 mWaitWorkCV.signal();
957}
958
959void AudioFlinger::ThreadBase::processConfigEvents()
960{
961 mLock.lock();
962 while(!mConfigEvents.isEmpty()) {
963 LOGV("processConfigEvents() remaining events %d", mConfigEvents.size());
964 ConfigEvent *configEvent = mConfigEvents[0];
965 mConfigEvents.removeAt(0);
Eric Laurenteb8f850d2010-05-14 03:26:45 -0700966 // release mLock before locking AudioFlinger mLock: lock order is always
967 // AudioFlinger then ThreadBase to avoid cross deadlock
Eric Laurenta553c252009-07-17 12:17:14 -0700968 mLock.unlock();
Eric Laurenteb8f850d2010-05-14 03:26:45 -0700969 mAudioFlinger->mLock.lock();
970 audioConfigChanged_l(configEvent->mEvent, configEvent->mParam);
971 mAudioFlinger->mLock.unlock();
Eric Laurenta553c252009-07-17 12:17:14 -0700972 delete configEvent;
973 mLock.lock();
974 }
975 mLock.unlock();
976}
977
Eric Laurent3fdb1262009-11-07 00:01:32 -0800978status_t AudioFlinger::ThreadBase::dumpBase(int fd, const Vector<String16>& args)
979{
980 const size_t SIZE = 256;
981 char buffer[SIZE];
982 String8 result;
983
984 bool locked = tryLock(mLock);
985 if (!locked) {
986 snprintf(buffer, SIZE, "thread %p maybe dead locked\n", this);
987 write(fd, buffer, strlen(buffer));
988 }
989
990 snprintf(buffer, SIZE, "standby: %d\n", mStandby);
991 result.append(buffer);
992 snprintf(buffer, SIZE, "Sample rate: %d\n", mSampleRate);
993 result.append(buffer);
994 snprintf(buffer, SIZE, "Frame count: %d\n", mFrameCount);
995 result.append(buffer);
996 snprintf(buffer, SIZE, "Channel Count: %d\n", mChannelCount);
997 result.append(buffer);
Jean-Michel Trivi54392232011-05-24 15:53:33 -0700998 snprintf(buffer, SIZE, "Channel Mask: 0x%08x\n", mChannelMask);
999 result.append(buffer);
Eric Laurent3fdb1262009-11-07 00:01:32 -08001000 snprintf(buffer, SIZE, "Format: %d\n", mFormat);
1001 result.append(buffer);
1002 snprintf(buffer, SIZE, "Frame size: %d\n", mFrameSize);
1003 result.append(buffer);
1004
1005 snprintf(buffer, SIZE, "\nPending setParameters commands: \n");
1006 result.append(buffer);
1007 result.append(" Index Command");
1008 for (size_t i = 0; i < mNewParameters.size(); ++i) {
1009 snprintf(buffer, SIZE, "\n %02d ", i);
1010 result.append(buffer);
1011 result.append(mNewParameters[i]);
1012 }
1013
1014 snprintf(buffer, SIZE, "\n\nPending config events: \n");
1015 result.append(buffer);
1016 snprintf(buffer, SIZE, " Index event param\n");
1017 result.append(buffer);
1018 for (size_t i = 0; i < mConfigEvents.size(); i++) {
1019 snprintf(buffer, SIZE, " %02d %02d %d\n", i, mConfigEvents[i]->mEvent, mConfigEvents[i]->mParam);
1020 result.append(buffer);
1021 }
1022 result.append("\n");
1023
1024 write(fd, result.string(), result.size());
1025
1026 if (locked) {
1027 mLock.unlock();
1028 }
1029 return NO_ERROR;
1030}
1031
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001032
1033// ----------------------------------------------------------------------------
1034
Dima Zavin31f188892011-04-18 16:57:27 -07001035AudioFlinger::PlaybackThread::PlaybackThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id, uint32_t device)
Eric Laurent49f02be2009-11-19 09:00:56 -08001036 : ThreadBase(audioFlinger, id),
Eric Laurentd5603c12009-08-06 08:49:39 -07001037 mMixBuffer(0), mSuspended(0), mBytesWritten(0), mOutput(output),
Eric Laurent65b65452010-06-01 23:49:17 -07001038 mLastWriteTime(0), mNumWrites(0), mNumDelayedWrites(0), mInWrite(false),
1039 mDevice(device)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001040{
Eric Laurenta553c252009-07-17 12:17:14 -07001041 readOutputParameters();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001042
Eric Laurenta553c252009-07-17 12:17:14 -07001043 mMasterVolume = mAudioFlinger->masterVolume();
1044 mMasterMute = mAudioFlinger->masterMute();
1045
Dima Zavin24fc2fb2011-04-19 22:30:36 -07001046 for (int stream = 0; stream < AUDIO_STREAM_CNT; stream++) {
Eric Laurenta553c252009-07-17 12:17:14 -07001047 mStreamTypes[stream].volume = mAudioFlinger->streamVolumeInternal(stream);
1048 mStreamTypes[stream].mute = mAudioFlinger->streamMute(stream);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001049 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001050}
1051
Eric Laurenta553c252009-07-17 12:17:14 -07001052AudioFlinger::PlaybackThread::~PlaybackThread()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001053{
1054 delete [] mMixBuffer;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001055}
1056
Eric Laurenta553c252009-07-17 12:17:14 -07001057status_t AudioFlinger::PlaybackThread::dump(int fd, const Vector<String16>& args)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001058{
1059 dumpInternals(fd, args);
1060 dumpTracks(fd, args);
Eric Laurent65b65452010-06-01 23:49:17 -07001061 dumpEffectChains(fd, args);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001062 return NO_ERROR;
1063}
1064
Eric Laurenta553c252009-07-17 12:17:14 -07001065status_t AudioFlinger::PlaybackThread::dumpTracks(int fd, const Vector<String16>& args)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001066{
1067 const size_t SIZE = 256;
1068 char buffer[SIZE];
1069 String8 result;
1070
Eric Laurenta553c252009-07-17 12:17:14 -07001071 snprintf(buffer, SIZE, "Output thread %p tracks\n", this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001072 result.append(buffer);
Jean-Michel Trivi54392232011-05-24 15:53:33 -07001073 result.append(" Name Clien Typ Fmt Chn mask 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 -08001074 for (size_t i = 0; i < mTracks.size(); ++i) {
Eric Laurentd3b4d0c2009-03-31 14:34:35 -07001075 sp<Track> track = mTracks[i];
1076 if (track != 0) {
1077 track->dump(buffer, SIZE);
1078 result.append(buffer);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001079 }
1080 }
1081
Eric Laurenta553c252009-07-17 12:17:14 -07001082 snprintf(buffer, SIZE, "Output thread %p active tracks\n", this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001083 result.append(buffer);
Jean-Michel Trivi54392232011-05-24 15:53:33 -07001084 result.append(" Name Clien Typ Fmt Chn mask 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 -08001085 for (size_t i = 0; i < mActiveTracks.size(); ++i) {
Eric Laurentd3b4d0c2009-03-31 14:34:35 -07001086 wp<Track> wTrack = mActiveTracks[i];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001087 if (wTrack != 0) {
1088 sp<Track> track = wTrack.promote();
1089 if (track != 0) {
1090 track->dump(buffer, SIZE);
1091 result.append(buffer);
1092 }
1093 }
1094 }
1095 write(fd, result.string(), result.size());
1096 return NO_ERROR;
1097}
1098
Eric Laurent65b65452010-06-01 23:49:17 -07001099status_t AudioFlinger::PlaybackThread::dumpEffectChains(int fd, const Vector<String16>& args)
1100{
1101 const size_t SIZE = 256;
1102 char buffer[SIZE];
1103 String8 result;
1104
1105 snprintf(buffer, SIZE, "\n- %d Effect Chains:\n", mEffectChains.size());
1106 write(fd, buffer, strlen(buffer));
1107
1108 for (size_t i = 0; i < mEffectChains.size(); ++i) {
1109 sp<EffectChain> chain = mEffectChains[i];
1110 if (chain != 0) {
1111 chain->dump(fd, args);
1112 }
1113 }
1114 return NO_ERROR;
1115}
1116
Eric Laurenta553c252009-07-17 12:17:14 -07001117status_t AudioFlinger::PlaybackThread::dumpInternals(int fd, const Vector<String16>& args)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001118{
1119 const size_t SIZE = 256;
1120 char buffer[SIZE];
1121 String8 result;
1122
Eric Laurent3fdb1262009-11-07 00:01:32 -08001123 snprintf(buffer, SIZE, "\nOutput thread %p internals\n", this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001124 result.append(buffer);
1125 snprintf(buffer, SIZE, "last write occurred (msecs): %llu\n", ns2ms(systemTime() - mLastWriteTime));
1126 result.append(buffer);
1127 snprintf(buffer, SIZE, "total writes: %d\n", mNumWrites);
1128 result.append(buffer);
1129 snprintf(buffer, SIZE, "delayed writes: %d\n", mNumDelayedWrites);
1130 result.append(buffer);
1131 snprintf(buffer, SIZE, "blocked in write: %d\n", mInWrite);
1132 result.append(buffer);
Eric Laurent8ac9f8d2009-12-18 05:47:48 -08001133 snprintf(buffer, SIZE, "suspend count: %d\n", mSuspended);
1134 result.append(buffer);
Eric Laurent65b65452010-06-01 23:49:17 -07001135 snprintf(buffer, SIZE, "mix buffer : %p\n", mMixBuffer);
1136 result.append(buffer);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001137 write(fd, result.string(), result.size());
Eric Laurent3fdb1262009-11-07 00:01:32 -08001138
1139 dumpBase(fd, args);
1140
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001141 return NO_ERROR;
1142}
1143
1144// Thread virtuals
Eric Laurenta553c252009-07-17 12:17:14 -07001145status_t AudioFlinger::PlaybackThread::readyToRun()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001146{
1147 if (mSampleRate == 0) {
1148 LOGE("No working audio driver found.");
1149 return NO_INIT;
1150 }
Eric Laurenta553c252009-07-17 12:17:14 -07001151 LOGI("AudioFlinger's thread %p ready to run", this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001152 return NO_ERROR;
1153}
1154
Eric Laurenta553c252009-07-17 12:17:14 -07001155void AudioFlinger::PlaybackThread::onFirstRef()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001156{
1157 const size_t SIZE = 256;
1158 char buffer[SIZE];
1159
Eric Laurenta553c252009-07-17 12:17:14 -07001160 snprintf(buffer, SIZE, "Playback Thread %p", this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001161
1162 run(buffer, ANDROID_PRIORITY_URGENT_AUDIO);
1163}
1164
Eric Laurenta553c252009-07-17 12:17:14 -07001165// PlaybackThread::createTrack_l() must be called with AudioFlinger::mLock held
1166sp<AudioFlinger::PlaybackThread::Track> AudioFlinger::PlaybackThread::createTrack_l(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001167 const sp<AudioFlinger::Client>& client,
1168 int streamType,
1169 uint32_t sampleRate,
Jean-Michel Trivi54392232011-05-24 15:53:33 -07001170 uint32_t format,
1171 uint32_t channelMask,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001172 int frameCount,
1173 const sp<IMemory>& sharedBuffer,
Eric Laurent65b65452010-06-01 23:49:17 -07001174 int sessionId,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001175 status_t *status)
1176{
1177 sp<Track> track;
1178 status_t lStatus;
Eric Laurenta553c252009-07-17 12:17:14 -07001179
1180 if (mType == DIRECT) {
Jean-Michel Trivi54392232011-05-24 15:53:33 -07001181 if ((format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM) {
1182 if (sampleRate != mSampleRate || format != mFormat || channelMask != mChannelMask) {
1183 LOGE("createTrack_l() Bad parameter: sampleRate %d format %d, channelMask 0x%08x \""
1184 "for output %p with format %d",
1185 sampleRate, format, channelMask, mOutput, mFormat);
1186 lStatus = BAD_VALUE;
1187 goto Exit;
1188 }
Eric Laurenta553c252009-07-17 12:17:14 -07001189 }
1190 } else {
1191 // Resampler implementation limits input sampling rate to 2 x output sampling rate.
1192 if (sampleRate > mSampleRate*2) {
1193 LOGE("Sample rate out of range: %d mSampleRate %d", sampleRate, mSampleRate);
1194 lStatus = BAD_VALUE;
1195 goto Exit;
1196 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001197 }
1198
Eric Laurenta553c252009-07-17 12:17:14 -07001199 if (mOutput == 0) {
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07001200 LOGE("Audio driver not initialized.");
1201 lStatus = NO_INIT;
1202 goto Exit;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001203 }
1204
Eric Laurenta553c252009-07-17 12:17:14 -07001205 { // scope for mLock
1206 Mutex::Autolock _l(mLock);
Eric Laurent8ed6ed02010-07-13 04:45:46 -07001207
1208 // all tracks in same audio session must share the same routing strategy otherwise
1209 // conflicts will happen when tracks are moved from one output to another by audio policy
1210 // manager
1211 uint32_t strategy =
Dima Zavin24fc2fb2011-04-19 22:30:36 -07001212 AudioSystem::getStrategyForStream((audio_stream_type_t)streamType);
Eric Laurent8ed6ed02010-07-13 04:45:46 -07001213 for (size_t i = 0; i < mTracks.size(); ++i) {
1214 sp<Track> t = mTracks[i];
1215 if (t != 0) {
1216 if (sessionId == t->sessionId() &&
Dima Zavin24fc2fb2011-04-19 22:30:36 -07001217 strategy != AudioSystem::getStrategyForStream((audio_stream_type_t)t->type())) {
Eric Laurent8ed6ed02010-07-13 04:45:46 -07001218 lStatus = BAD_VALUE;
1219 goto Exit;
1220 }
1221 }
1222 }
1223
Eric Laurenta553c252009-07-17 12:17:14 -07001224 track = new Track(this, client, streamType, sampleRate, format,
Jean-Michel Trivi54392232011-05-24 15:53:33 -07001225 channelMask, frameCount, sharedBuffer, sessionId);
Eric Laurent73b60352009-11-09 04:45:39 -08001226 if (track->getCblk() == NULL || track->name() < 0) {
Eric Laurenta553c252009-07-17 12:17:14 -07001227 lStatus = NO_MEMORY;
1228 goto Exit;
1229 }
1230 mTracks.add(track);
Eric Laurent65b65452010-06-01 23:49:17 -07001231
1232 sp<EffectChain> chain = getEffectChain_l(sessionId);
1233 if (chain != 0) {
1234 LOGV("createTrack_l() setting main buffer %p", chain->inBuffer());
1235 track->setMainBuffer(chain->inBuffer());
Dima Zavin24fc2fb2011-04-19 22:30:36 -07001236 chain->setStrategy(AudioSystem::getStrategyForStream((audio_stream_type_t)track->type()));
Eric Laurent90681d62011-05-09 12:09:06 -07001237 chain->incTrackCnt();
Eric Laurent65b65452010-06-01 23:49:17 -07001238 }
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07001239 }
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07001240 lStatus = NO_ERROR;
1241
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001242Exit:
1243 if(status) {
1244 *status = lStatus;
1245 }
1246 return track;
1247}
1248
Eric Laurenta553c252009-07-17 12:17:14 -07001249uint32_t AudioFlinger::PlaybackThread::latency() const
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001250{
1251 if (mOutput) {
Dima Zavin31f188892011-04-18 16:57:27 -07001252 return mOutput->stream->get_latency(mOutput->stream);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001253 }
1254 else {
1255 return 0;
1256 }
1257}
1258
Eric Laurenta553c252009-07-17 12:17:14 -07001259status_t AudioFlinger::PlaybackThread::setMasterVolume(float value)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001260{
1261 mMasterVolume = value;
1262 return NO_ERROR;
1263}
1264
Eric Laurenta553c252009-07-17 12:17:14 -07001265status_t AudioFlinger::PlaybackThread::setMasterMute(bool muted)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001266{
1267 mMasterMute = muted;
1268 return NO_ERROR;
1269}
1270
Eric Laurenta553c252009-07-17 12:17:14 -07001271float AudioFlinger::PlaybackThread::masterVolume() const
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001272{
1273 return mMasterVolume;
1274}
1275
Eric Laurenta553c252009-07-17 12:17:14 -07001276bool AudioFlinger::PlaybackThread::masterMute() const
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001277{
1278 return mMasterMute;
1279}
1280
Eric Laurenta553c252009-07-17 12:17:14 -07001281status_t AudioFlinger::PlaybackThread::setStreamVolume(int stream, float value)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001282{
1283 mStreamTypes[stream].volume = value;
1284 return NO_ERROR;
1285}
1286
Eric Laurenta553c252009-07-17 12:17:14 -07001287status_t AudioFlinger::PlaybackThread::setStreamMute(int stream, bool muted)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001288{
1289 mStreamTypes[stream].mute = muted;
1290 return NO_ERROR;
1291}
1292
Eric Laurenta553c252009-07-17 12:17:14 -07001293float AudioFlinger::PlaybackThread::streamVolume(int stream) const
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001294{
1295 return mStreamTypes[stream].volume;
1296}
1297
Eric Laurenta553c252009-07-17 12:17:14 -07001298bool AudioFlinger::PlaybackThread::streamMute(int stream) const
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001299{
1300 return mStreamTypes[stream].mute;
1301}
1302
Eric Laurenta553c252009-07-17 12:17:14 -07001303// addTrack_l() must be called with ThreadBase::mLock held
1304status_t AudioFlinger::PlaybackThread::addTrack_l(const sp<Track>& track)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001305{
1306 status_t status = ALREADY_EXISTS;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001307
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001308 // set retry count for buffer fill
1309 track->mRetryCount = kMaxTrackStartupRetries;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001310 if (mActiveTracks.indexOf(track) < 0) {
1311 // the track is newly added, make sure it fills up all its
1312 // buffers before playing. This is to ensure the client will
1313 // effectively get the latency it requested.
1314 track->mFillingUpStatus = Track::FS_FILLING;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001315 track->mResetDone = false;
Eric Laurenta553c252009-07-17 12:17:14 -07001316 mActiveTracks.add(track);
Eric Laurent65b65452010-06-01 23:49:17 -07001317 if (track->mainBuffer() != mMixBuffer) {
1318 sp<EffectChain> chain = getEffectChain_l(track->sessionId());
1319 if (chain != 0) {
1320 LOGV("addTrack_l() starting track on chain %p for session %d", chain.get(), track->sessionId());
Eric Laurent90681d62011-05-09 12:09:06 -07001321 chain->incActiveTrackCnt();
Eric Laurent65b65452010-06-01 23:49:17 -07001322 }
1323 }
1324
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001325 status = NO_ERROR;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001326 }
Eric Laurenta553c252009-07-17 12:17:14 -07001327
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001328 LOGV("mWaitWorkCV.broadcast");
Eric Laurenta553c252009-07-17 12:17:14 -07001329 mWaitWorkCV.broadcast();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001330
1331 return status;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001332}
1333
Eric Laurenta553c252009-07-17 12:17:14 -07001334// destroyTrack_l() must be called with ThreadBase::mLock held
1335void AudioFlinger::PlaybackThread::destroyTrack_l(const sp<Track>& track)
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001336{
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001337 track->mState = TrackBase::TERMINATED;
1338 if (mActiveTracks.indexOf(track) < 0) {
Eric Laurent90681d62011-05-09 12:09:06 -07001339 removeTrack_l(track);
1340 }
1341}
1342
1343void AudioFlinger::PlaybackThread::removeTrack_l(const sp<Track>& track)
1344{
1345 mTracks.remove(track);
1346 deleteTrackName_l(track->name());
1347 sp<EffectChain> chain = getEffectChain_l(track->sessionId());
1348 if (chain != 0) {
1349 chain->decTrackCnt();
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001350 }
1351}
1352
Eric Laurenta553c252009-07-17 12:17:14 -07001353String8 AudioFlinger::PlaybackThread::getParameters(const String8& keys)
The Android Open Source Projectf1e484a2009-01-22 00:13:42 -08001354{
Dima Zavin24fc2fb2011-04-19 22:30:36 -07001355 String8 out_s8;
1356 char *s;
1357
Dima Zavin31f188892011-04-18 16:57:27 -07001358 s = mOutput->stream->common.get_parameters(&mOutput->stream->common, keys.string());
Dima Zavin24fc2fb2011-04-19 22:30:36 -07001359 out_s8 = String8(s);
1360 free(s);
1361 return out_s8;
Eric Laurenta553c252009-07-17 12:17:14 -07001362}
The Android Open Source Projectf1e484a2009-01-22 00:13:42 -08001363
Eric Laurenteb8f850d2010-05-14 03:26:45 -07001364// destroyTrack_l() must be called with AudioFlinger::mLock held
1365void AudioFlinger::PlaybackThread::audioConfigChanged_l(int event, int param) {
Eric Laurenta553c252009-07-17 12:17:14 -07001366 AudioSystem::OutputDescriptor desc;
1367 void *param2 = 0;
1368
Eric Laurenteb8f850d2010-05-14 03:26:45 -07001369 LOGV("PlaybackThread::audioConfigChanged_l, thread %p, event %d, param %d", this, event, param);
Eric Laurenta553c252009-07-17 12:17:14 -07001370
1371 switch (event) {
1372 case AudioSystem::OUTPUT_OPENED:
1373 case AudioSystem::OUTPUT_CONFIG_CHANGED:
Jean-Michel Trivi54392232011-05-24 15:53:33 -07001374 desc.channels = mChannelMask;
Eric Laurenta553c252009-07-17 12:17:14 -07001375 desc.samplingRate = mSampleRate;
1376 desc.format = mFormat;
1377 desc.frameCount = mFrameCount;
1378 desc.latency = latency();
1379 param2 = &desc;
1380 break;
1381
1382 case AudioSystem::STREAM_CONFIG_CHANGED:
1383 param2 = &param;
1384 case AudioSystem::OUTPUT_CLOSED:
1385 default:
1386 break;
1387 }
Eric Laurent49f02be2009-11-19 09:00:56 -08001388 mAudioFlinger->audioConfigChanged_l(event, mId, param2);
Eric Laurenta553c252009-07-17 12:17:14 -07001389}
1390
1391void AudioFlinger::PlaybackThread::readOutputParameters()
1392{
Dima Zavin31f188892011-04-18 16:57:27 -07001393 mSampleRate = mOutput->stream->common.get_sample_rate(&mOutput->stream->common);
Jean-Michel Trivi54392232011-05-24 15:53:33 -07001394 mChannelMask = mOutput->stream->common.get_channels(&mOutput->stream->common);
1395 mChannelCount = (uint16_t)popcount(mChannelMask);
Dima Zavin31f188892011-04-18 16:57:27 -07001396 mFormat = mOutput->stream->common.get_format(&mOutput->stream->common);
1397 mFrameSize = (uint16_t)audio_stream_frame_size(&mOutput->stream->common);
1398 mFrameCount = mOutput->stream->common.get_buffer_size(&mOutput->stream->common) / mFrameSize;
Eric Laurenta553c252009-07-17 12:17:14 -07001399
Eric Laurenta553c252009-07-17 12:17:14 -07001400 // FIXME - Current mixer implementation only supports stereo output: Always
1401 // Allocate a stereo buffer even if HW output is mono.
Eric Laurent65b65452010-06-01 23:49:17 -07001402 if (mMixBuffer != NULL) delete[] mMixBuffer;
Eric Laurenta553c252009-07-17 12:17:14 -07001403 mMixBuffer = new int16_t[mFrameCount * 2];
1404 memset(mMixBuffer, 0, mFrameCount * 2 * sizeof(int16_t));
Eric Laurent65b65452010-06-01 23:49:17 -07001405
Eric Laurent8ed6ed02010-07-13 04:45:46 -07001406 // force reconfiguration of effect chains and engines to take new buffer size and audio
1407 // parameters into account
1408 // Note that mLock is not held when readOutputParameters() is called from the constructor
1409 // but in this case nothing is done below as no audio sessions have effect yet so it doesn't
1410 // matter.
1411 // create a copy of mEffectChains as calling moveEffectChain_l() can reorder some effect chains
1412 Vector< sp<EffectChain> > effectChains = mEffectChains;
1413 for (size_t i = 0; i < effectChains.size(); i ++) {
Eric Laurent493941b2010-07-28 01:32:47 -07001414 mAudioFlinger->moveEffectChain_l(effectChains[i]->sessionId(), this, this, false);
Eric Laurent8ed6ed02010-07-13 04:45:46 -07001415 }
Eric Laurenta553c252009-07-17 12:17:14 -07001416}
1417
Eric Laurent0986e792010-01-19 17:37:09 -08001418status_t AudioFlinger::PlaybackThread::getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames)
1419{
1420 if (halFrames == 0 || dspFrames == 0) {
1421 return BAD_VALUE;
1422 }
1423 if (mOutput == 0) {
1424 return INVALID_OPERATION;
1425 }
Dima Zavin31f188892011-04-18 16:57:27 -07001426 *halFrames = mBytesWritten / audio_stream_frame_size(&mOutput->stream->common);
Eric Laurent0986e792010-01-19 17:37:09 -08001427
Dima Zavin31f188892011-04-18 16:57:27 -07001428 return mOutput->stream->get_render_position(mOutput->stream, dspFrames);
Eric Laurent0986e792010-01-19 17:37:09 -08001429}
1430
Eric Laurent493941b2010-07-28 01:32:47 -07001431uint32_t AudioFlinger::PlaybackThread::hasAudioSession(int sessionId)
Eric Laurent65b65452010-06-01 23:49:17 -07001432{
1433 Mutex::Autolock _l(mLock);
Eric Laurent493941b2010-07-28 01:32:47 -07001434 uint32_t result = 0;
Eric Laurent65b65452010-06-01 23:49:17 -07001435 if (getEffectChain_l(sessionId) != 0) {
Eric Laurent493941b2010-07-28 01:32:47 -07001436 result = EFFECT_SESSION;
Eric Laurent65b65452010-06-01 23:49:17 -07001437 }
1438
1439 for (size_t i = 0; i < mTracks.size(); ++i) {
1440 sp<Track> track = mTracks[i];
Eric Laurent8ed6ed02010-07-13 04:45:46 -07001441 if (sessionId == track->sessionId() &&
1442 !(track->mCblk->flags & CBLK_INVALID_MSK)) {
Eric Laurent493941b2010-07-28 01:32:47 -07001443 result |= TRACK_SESSION;
1444 break;
Eric Laurent65b65452010-06-01 23:49:17 -07001445 }
1446 }
1447
Eric Laurent493941b2010-07-28 01:32:47 -07001448 return result;
Eric Laurent65b65452010-06-01 23:49:17 -07001449}
1450
Eric Laurent8ed6ed02010-07-13 04:45:46 -07001451uint32_t AudioFlinger::PlaybackThread::getStrategyForSession_l(int sessionId)
1452{
Dima Zavin24fc2fb2011-04-19 22:30:36 -07001453 // session AUDIO_SESSION_OUTPUT_MIX is placed in same strategy as MUSIC stream so that
Eric Laurent8ed6ed02010-07-13 04:45:46 -07001454 // it is moved to correct output by audio policy manager when A2DP is connected or disconnected
Dima Zavin24fc2fb2011-04-19 22:30:36 -07001455 if (sessionId == AUDIO_SESSION_OUTPUT_MIX) {
1456 return AudioSystem::getStrategyForStream(AUDIO_STREAM_MUSIC);
Eric Laurent8ed6ed02010-07-13 04:45:46 -07001457 }
1458 for (size_t i = 0; i < mTracks.size(); i++) {
1459 sp<Track> track = mTracks[i];
1460 if (sessionId == track->sessionId() &&
1461 !(track->mCblk->flags & CBLK_INVALID_MSK)) {
Dima Zavin24fc2fb2011-04-19 22:30:36 -07001462 return AudioSystem::getStrategyForStream((audio_stream_type_t) track->type());
Eric Laurent8ed6ed02010-07-13 04:45:46 -07001463 }
1464 }
Dima Zavin24fc2fb2011-04-19 22:30:36 -07001465 return AudioSystem::getStrategyForStream(AUDIO_STREAM_MUSIC);
Eric Laurent8ed6ed02010-07-13 04:45:46 -07001466}
1467
Eric Laurent65b65452010-06-01 23:49:17 -07001468sp<AudioFlinger::EffectChain> AudioFlinger::PlaybackThread::getEffectChain(int sessionId)
1469{
1470 Mutex::Autolock _l(mLock);
1471 return getEffectChain_l(sessionId);
1472}
1473
1474sp<AudioFlinger::EffectChain> AudioFlinger::PlaybackThread::getEffectChain_l(int sessionId)
1475{
1476 sp<EffectChain> chain;
1477
1478 size_t size = mEffectChains.size();
1479 for (size_t i = 0; i < size; i++) {
1480 if (mEffectChains[i]->sessionId() == sessionId) {
1481 chain = mEffectChains[i];
1482 break;
1483 }
1484 }
1485 return chain;
1486}
1487
Eric Laurent53334cd2010-06-23 17:38:20 -07001488void AudioFlinger::PlaybackThread::setMode(uint32_t mode)
1489{
1490 Mutex::Autolock _l(mLock);
1491 size_t size = mEffectChains.size();
1492 for (size_t i = 0; i < size; i++) {
Eric Laurent76c40f72010-07-15 12:50:15 -07001493 mEffectChains[i]->setMode_l(mode);
Eric Laurent53334cd2010-06-23 17:38:20 -07001494 }
1495}
1496
Eric Laurenta553c252009-07-17 12:17:14 -07001497// ----------------------------------------------------------------------------
1498
Dima Zavin31f188892011-04-18 16:57:27 -07001499AudioFlinger::MixerThread::MixerThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id, uint32_t device)
Eric Laurent65b65452010-06-01 23:49:17 -07001500 : PlaybackThread(audioFlinger, output, id, device),
Eric Laurenta553c252009-07-17 12:17:14 -07001501 mAudioMixer(0)
1502{
1503 mType = PlaybackThread::MIXER;
1504 mAudioMixer = new AudioMixer(mFrameCount, mSampleRate);
1505
1506 // FIXME - Current mixer implementation only supports stereo output
1507 if (mChannelCount == 1) {
1508 LOGE("Invalid audio hardware channel count");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001509 }
The Android Open Source Projectf1e484a2009-01-22 00:13:42 -08001510}
1511
Eric Laurenta553c252009-07-17 12:17:14 -07001512AudioFlinger::MixerThread::~MixerThread()
The Android Open Source Projectf1e484a2009-01-22 00:13:42 -08001513{
Eric Laurenta553c252009-07-17 12:17:14 -07001514 delete mAudioMixer;
1515}
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001516
Eric Laurenta553c252009-07-17 12:17:14 -07001517bool AudioFlinger::MixerThread::threadLoop()
1518{
Eric Laurenta553c252009-07-17 12:17:14 -07001519 Vector< sp<Track> > tracksToRemove;
Eric Laurent059b4be2009-11-09 23:32:22 -08001520 uint32_t mixerStatus = MIXER_IDLE;
Eric Laurenta553c252009-07-17 12:17:14 -07001521 nsecs_t standbyTime = systemTime();
1522 size_t mixBufferSize = mFrameCount * mFrameSize;
Dave Sparksd0ac8c02009-09-30 03:09:03 -07001523 // FIXME: Relaxed timing because of a certain device that can't meet latency
1524 // Should be reduced to 2x after the vendor fixes the driver issue
1525 nsecs_t maxPeriod = seconds(mFrameCount) / mSampleRate * 3;
1526 nsecs_t lastWarning = 0;
Eric Laurent059b4be2009-11-09 23:32:22 -08001527 bool longStandbyExit = false;
1528 uint32_t activeSleepTime = activeSleepTimeUs();
1529 uint32_t idleSleepTime = idleSleepTimeUs();
1530 uint32_t sleepTime = idleSleepTime;
Eric Laurent65b65452010-06-01 23:49:17 -07001531 Vector< sp<EffectChain> > effectChains;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001532
Eric Laurenta553c252009-07-17 12:17:14 -07001533 while (!exitPending())
1534 {
1535 processConfigEvents();
1536
Eric Laurent059b4be2009-11-09 23:32:22 -08001537 mixerStatus = MIXER_IDLE;
Eric Laurenta553c252009-07-17 12:17:14 -07001538 { // scope for mLock
1539
1540 Mutex::Autolock _l(mLock);
1541
1542 if (checkForNewParameters_l()) {
1543 mixBufferSize = mFrameCount * mFrameSize;
Dave Sparksd0ac8c02009-09-30 03:09:03 -07001544 // FIXME: Relaxed timing because of a certain device that can't meet latency
1545 // Should be reduced to 2x after the vendor fixes the driver issue
1546 maxPeriod = seconds(mFrameCount) / mSampleRate * 3;
Eric Laurent059b4be2009-11-09 23:32:22 -08001547 activeSleepTime = activeSleepTimeUs();
1548 idleSleepTime = idleSleepTimeUs();
Eric Laurenta553c252009-07-17 12:17:14 -07001549 }
1550
1551 const SortedVector< wp<Track> >& activeTracks = mActiveTracks;
1552
1553 // put audio hardware into standby after short delay
1554 if UNLIKELY((!activeTracks.size() && systemTime() > standbyTime) ||
1555 mSuspended) {
1556 if (!mStandby) {
1557 LOGV("Audio hardware entering standby, mixer %p, mSuspended %d\n", this, mSuspended);
Dima Zavin31f188892011-04-18 16:57:27 -07001558 mOutput->stream->common.standby(&mOutput->stream->common);
Eric Laurenta553c252009-07-17 12:17:14 -07001559 mStandby = true;
1560 mBytesWritten = 0;
1561 }
1562
1563 if (!activeTracks.size() && mConfigEvents.isEmpty()) {
1564 // we're about to wait, flush the binder command buffer
1565 IPCThreadState::self()->flushCommands();
1566
1567 if (exitPending()) break;
1568
1569 // wait until we have something to do...
1570 LOGV("MixerThread %p TID %d going to sleep\n", this, gettid());
1571 mWaitWorkCV.wait(mLock);
1572 LOGV("MixerThread %p TID %d waking up\n", this, gettid());
1573
1574 if (mMasterMute == false) {
1575 char value[PROPERTY_VALUE_MAX];
1576 property_get("ro.audio.silent", value, "0");
1577 if (atoi(value)) {
1578 LOGD("Silence is golden");
1579 setMasterMute(true);
1580 }
1581 }
1582
1583 standbyTime = systemTime() + kStandbyTimeInNsecs;
Eric Laurent059b4be2009-11-09 23:32:22 -08001584 sleepTime = idleSleepTime;
Eric Laurenta553c252009-07-17 12:17:14 -07001585 continue;
1586 }
1587 }
1588
Eric Laurent059b4be2009-11-09 23:32:22 -08001589 mixerStatus = prepareTracks_l(activeTracks, &tracksToRemove);
Eric Laurent65b65452010-06-01 23:49:17 -07001590
1591 // prevent any changes in effect chain list and in each effect chain
1592 // during mixing and effect process as the audio buffers could be deleted
1593 // or modified if an effect is created or deleted
Eric Laurent8ed6ed02010-07-13 04:45:46 -07001594 lockEffectChains_l(effectChains);
Eric Laurenta553c252009-07-17 12:17:14 -07001595 }
1596
Eric Laurent059b4be2009-11-09 23:32:22 -08001597 if (LIKELY(mixerStatus == MIXER_TRACKS_READY)) {
Eric Laurentf69a3f82009-09-22 00:35:48 -07001598 // mix buffers...
Eric Laurent65b65452010-06-01 23:49:17 -07001599 mAudioMixer->process();
Eric Laurentf69a3f82009-09-22 00:35:48 -07001600 sleepTime = 0;
1601 standbyTime = systemTime() + kStandbyTimeInNsecs;
Eric Laurent65b65452010-06-01 23:49:17 -07001602 //TODO: delay standby when effects have a tail
Eric Laurent96c08a62009-09-07 08:38:38 -07001603 } else {
Eric Laurent62443f52009-10-05 20:29:18 -07001604 // If no tracks are ready, sleep once for the duration of an output
1605 // buffer size, then write 0s to the output
1606 if (sleepTime == 0) {
Eric Laurent059b4be2009-11-09 23:32:22 -08001607 if (mixerStatus == MIXER_TRACKS_ENABLED) {
1608 sleepTime = activeSleepTime;
1609 } else {
1610 sleepTime = idleSleepTime;
1611 }
1612 } else if (mBytesWritten != 0 ||
1613 (mixerStatus == MIXER_TRACKS_ENABLED && longStandbyExit)) {
Eric Laurent65b65452010-06-01 23:49:17 -07001614 memset (mMixBuffer, 0, mixBufferSize);
Eric Laurent96c08a62009-09-07 08:38:38 -07001615 sleepTime = 0;
Eric Laurent059b4be2009-11-09 23:32:22 -08001616 LOGV_IF((mBytesWritten == 0 && (mixerStatus == MIXER_TRACKS_ENABLED && longStandbyExit)), "anticipated start");
Eric Laurent96c08a62009-09-07 08:38:38 -07001617 }
Eric Laurent65b65452010-06-01 23:49:17 -07001618 // TODO add standby time extension fct of effect tail
Eric Laurentf69a3f82009-09-22 00:35:48 -07001619 }
1620
1621 if (mSuspended) {
Eric Laurent8448a792010-08-18 18:13:17 -07001622 sleepTime = suspendSleepTimeUs();
Eric Laurentf69a3f82009-09-22 00:35:48 -07001623 }
1624 // sleepTime == 0 means we must write to audio hardware
1625 if (sleepTime == 0) {
Eric Laurent65b65452010-06-01 23:49:17 -07001626 for (size_t i = 0; i < effectChains.size(); i ++) {
1627 effectChains[i]->process_l();
1628 }
1629 // enable changes in effect chain
Eric Laurent8ed6ed02010-07-13 04:45:46 -07001630 unlockEffectChains(effectChains);
Eric Laurent65b65452010-06-01 23:49:17 -07001631 mLastWriteTime = systemTime();
1632 mInWrite = true;
1633 mBytesWritten += mixBufferSize;
1634
Dima Zavin31f188892011-04-18 16:57:27 -07001635 int bytesWritten = (int)mOutput->stream->write(mOutput->stream, mMixBuffer, mixBufferSize);
Eric Laurent0986e792010-01-19 17:37:09 -08001636 if (bytesWritten < 0) mBytesWritten -= mixBufferSize;
Eric Laurentf69a3f82009-09-22 00:35:48 -07001637 mNumWrites++;
1638 mInWrite = false;
Dave Sparksd0ac8c02009-09-30 03:09:03 -07001639 nsecs_t now = systemTime();
1640 nsecs_t delta = now - mLastWriteTime;
Eric Laurentf69a3f82009-09-22 00:35:48 -07001641 if (delta > maxPeriod) {
Eric Laurentf69a3f82009-09-22 00:35:48 -07001642 mNumDelayedWrites++;
Dave Sparksd0ac8c02009-09-30 03:09:03 -07001643 if ((now - lastWarning) > kWarningThrottle) {
1644 LOGW("write blocked for %llu msecs, %d delayed writes, thread %p",
1645 ns2ms(delta), mNumDelayedWrites, this);
1646 lastWarning = now;
1647 }
Eric Laurent059b4be2009-11-09 23:32:22 -08001648 if (mStandby) {
1649 longStandbyExit = true;
1650 }
Eric Laurenta553c252009-07-17 12:17:14 -07001651 }
Eric Laurent059b4be2009-11-09 23:32:22 -08001652 mStandby = false;
Eric Laurentf69a3f82009-09-22 00:35:48 -07001653 } else {
Eric Laurent65b65452010-06-01 23:49:17 -07001654 // enable changes in effect chain
Eric Laurent8ed6ed02010-07-13 04:45:46 -07001655 unlockEffectChains(effectChains);
Eric Laurentf69a3f82009-09-22 00:35:48 -07001656 usleep(sleepTime);
Eric Laurenta553c252009-07-17 12:17:14 -07001657 }
1658
1659 // finally let go of all our tracks, without the lock held
1660 // since we can't guarantee the destructors won't acquire that
1661 // same lock.
1662 tracksToRemove.clear();
Eric Laurent65b65452010-06-01 23:49:17 -07001663
1664 // Effect chains will be actually deleted here if they were removed from
1665 // mEffectChains list during mixing or effects processing
1666 effectChains.clear();
Eric Laurenta553c252009-07-17 12:17:14 -07001667 }
1668
1669 if (!mStandby) {
Dima Zavin31f188892011-04-18 16:57:27 -07001670 mOutput->stream->common.standby(&mOutput->stream->common);
Eric Laurenta553c252009-07-17 12:17:14 -07001671 }
Eric Laurenta553c252009-07-17 12:17:14 -07001672
1673 LOGV("MixerThread %p exiting", this);
1674 return false;
1675}
1676
1677// prepareTracks_l() must be called with ThreadBase::mLock held
Eric Laurent059b4be2009-11-09 23:32:22 -08001678uint32_t AudioFlinger::MixerThread::prepareTracks_l(const SortedVector< wp<Track> >& activeTracks, Vector< sp<Track> > *tracksToRemove)
Eric Laurenta553c252009-07-17 12:17:14 -07001679{
1680
Eric Laurent059b4be2009-11-09 23:32:22 -08001681 uint32_t mixerStatus = MIXER_IDLE;
Eric Laurenta553c252009-07-17 12:17:14 -07001682 // find out which tracks need to be processed
1683 size_t count = activeTracks.size();
Eric Laurent65b65452010-06-01 23:49:17 -07001684 size_t mixedTracks = 0;
1685 size_t tracksWithEffect = 0;
Glenn Kasten871c16c2010-03-05 12:18:01 -08001686
1687 float masterVolume = mMasterVolume;
1688 bool masterMute = mMasterMute;
1689
Eric Laurent8cc93b92010-08-11 05:20:11 -07001690 if (masterMute) {
1691 masterVolume = 0;
1692 }
Eric Laurent65b65452010-06-01 23:49:17 -07001693 // Delegate master volume control to effect in output mix effect chain if needed
Dima Zavin24fc2fb2011-04-19 22:30:36 -07001694 sp<EffectChain> chain = getEffectChain_l(AUDIO_SESSION_OUTPUT_MIX);
Eric Laurent65b65452010-06-01 23:49:17 -07001695 if (chain != 0) {
Eric Laurent8cc93b92010-08-11 05:20:11 -07001696 uint32_t v = (uint32_t)(masterVolume * (1 << 24));
Eric Laurent76c40f72010-07-15 12:50:15 -07001697 chain->setVolume_l(&v, &v);
Eric Laurent65b65452010-06-01 23:49:17 -07001698 masterVolume = (float)((v + (1 << 23)) >> 24);
1699 chain.clear();
1700 }
Glenn Kasten871c16c2010-03-05 12:18:01 -08001701
Eric Laurenta553c252009-07-17 12:17:14 -07001702 for (size_t i=0 ; i<count ; i++) {
1703 sp<Track> t = activeTracks[i].promote();
1704 if (t == 0) continue;
1705
1706 Track* const track = t.get();
1707 audio_track_cblk_t* cblk = track->cblk();
1708
1709 // The first time a track is added we wait
1710 // for all its buffers to be filled before processing it
1711 mAudioMixer->setActiveTrack(track->name());
Eric Laurent9a30fc12010-10-05 14:41:42 -07001712 if (cblk->framesReady() && track->isReady() &&
Eric Laurent71f37cd2010-03-31 12:21:17 -07001713 !track->isPaused() && !track->isTerminated())
Eric Laurenta553c252009-07-17 12:17:14 -07001714 {
Eric Laurent8ac9f8d2009-12-18 05:47:48 -08001715 //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 -07001716
Eric Laurent65b65452010-06-01 23:49:17 -07001717 mixedTracks++;
1718
1719 // track->mainBuffer() != mMixBuffer means there is an effect chain
1720 // connected to the track
1721 chain.clear();
1722 if (track->mainBuffer() != mMixBuffer) {
1723 chain = getEffectChain_l(track->sessionId());
1724 // Delegate volume control to effect in track effect chain if needed
1725 if (chain != 0) {
1726 tracksWithEffect++;
1727 } else {
1728 LOGW("prepareTracks_l(): track %08x attached to effect but no chain found on session %d",
1729 track->name(), track->sessionId());
1730 }
1731 }
1732
1733
1734 int param = AudioMixer::VOLUME;
1735 if (track->mFillingUpStatus == Track::FS_FILLED) {
1736 // no ramp for the first volume setting
1737 track->mFillingUpStatus = Track::FS_ACTIVE;
1738 if (track->mState == TrackBase::RESUMING) {
1739 track->mState = TrackBase::ACTIVE;
1740 param = AudioMixer::RAMP_VOLUME;
1741 }
Eric Laurent4bb21c42011-02-28 16:52:51 -08001742 mAudioMixer->setParameter(AudioMixer::RESAMPLE, AudioMixer::RESET, NULL);
Eric Laurent65b65452010-06-01 23:49:17 -07001743 } else if (cblk->server != 0) {
1744 // If the track is stopped before the first frame was mixed,
1745 // do not apply ramp
1746 param = AudioMixer::RAMP_VOLUME;
1747 }
1748
Eric Laurenta553c252009-07-17 12:17:14 -07001749 // compute volume for this track
Eric Laurent27a2fdf2010-09-10 17:44:44 -07001750 uint32_t vl, vr, va;
Eric Laurent2a6b80b2010-07-29 23:43:43 -07001751 if (track->isMuted() || track->isPausing() ||
Eric Laurenta553c252009-07-17 12:17:14 -07001752 mStreamTypes[track->type()].mute) {
Eric Laurent27a2fdf2010-09-10 17:44:44 -07001753 vl = vr = va = 0;
Eric Laurenta553c252009-07-17 12:17:14 -07001754 if (track->isPausing()) {
1755 track->setPaused();
1756 }
1757 } else {
Eric Laurent27a2fdf2010-09-10 17:44:44 -07001758
Glenn Kasten871c16c2010-03-05 12:18:01 -08001759 // read original volumes with volume control
Eric Laurenta553c252009-07-17 12:17:14 -07001760 float typeVolume = mStreamTypes[track->type()].volume;
Glenn Kasten871c16c2010-03-05 12:18:01 -08001761 float v = masterVolume * typeVolume;
Eric Laurent27a2fdf2010-09-10 17:44:44 -07001762 vl = (uint32_t)(v * cblk->volume[0]) << 12;
1763 vr = (uint32_t)(v * cblk->volume[1]) << 12;
Eric Laurenta553c252009-07-17 12:17:14 -07001764
Eric Laurent27a2fdf2010-09-10 17:44:44 -07001765 va = (uint32_t)(v * cblk->sendLevel);
Eric Laurenta553c252009-07-17 12:17:14 -07001766 }
Eric Laurent27a2fdf2010-09-10 17:44:44 -07001767 // Delegate volume control to effect in track effect chain if needed
1768 if (chain != 0 && chain->setVolume_l(&vl, &vr)) {
1769 // Do not ramp volume if volume is controlled by effect
1770 param = AudioMixer::VOLUME;
1771 track->mHasVolumeController = true;
1772 } else {
1773 // force no volume ramp when volume controller was just disabled or removed
1774 // from effect chain to avoid volume spike
1775 if (track->mHasVolumeController) {
1776 param = AudioMixer::VOLUME;
1777 }
1778 track->mHasVolumeController = false;
1779 }
1780
1781 // Convert volumes from 8.24 to 4.12 format
1782 int16_t left, right, aux;
1783 uint32_t v_clamped = (vl + (1 << 11)) >> 12;
1784 if (v_clamped > MAX_GAIN_INT) v_clamped = MAX_GAIN_INT;
1785 left = int16_t(v_clamped);
1786 v_clamped = (vr + (1 << 11)) >> 12;
1787 if (v_clamped > MAX_GAIN_INT) v_clamped = MAX_GAIN_INT;
1788 right = int16_t(v_clamped);
1789
1790 if (va > MAX_GAIN_INT) va = MAX_GAIN_INT;
1791 aux = int16_t(va);
Eric Laurent65b65452010-06-01 23:49:17 -07001792
Eric Laurent65b65452010-06-01 23:49:17 -07001793 // XXX: these things DON'T need to be done each time
1794 mAudioMixer->setBufferProvider(track);
1795 mAudioMixer->enable(AudioMixer::MIXING);
1796
1797 mAudioMixer->setParameter(param, AudioMixer::VOLUME0, (void *)left);
1798 mAudioMixer->setParameter(param, AudioMixer::VOLUME1, (void *)right);
1799 mAudioMixer->setParameter(param, AudioMixer::AUXLEVEL, (void *)aux);
Eric Laurenta553c252009-07-17 12:17:14 -07001800 mAudioMixer->setParameter(
1801 AudioMixer::TRACK,
Eric Laurent65b65452010-06-01 23:49:17 -07001802 AudioMixer::FORMAT, (void *)track->format());
Eric Laurenta553c252009-07-17 12:17:14 -07001803 mAudioMixer->setParameter(
1804 AudioMixer::TRACK,
Jean-Michel Trivi54392232011-05-24 15:53:33 -07001805 AudioMixer::CHANNEL_MASK, (void *)track->channelMask());
Eric Laurenta553c252009-07-17 12:17:14 -07001806 mAudioMixer->setParameter(
1807 AudioMixer::RESAMPLE,
1808 AudioMixer::SAMPLE_RATE,
Eric Laurent65b65452010-06-01 23:49:17 -07001809 (void *)(cblk->sampleRate));
1810 mAudioMixer->setParameter(
1811 AudioMixer::TRACK,
1812 AudioMixer::MAIN_BUFFER, (void *)track->mainBuffer());
1813 mAudioMixer->setParameter(
1814 AudioMixer::TRACK,
1815 AudioMixer::AUX_BUFFER, (void *)track->auxBuffer());
Eric Laurenta553c252009-07-17 12:17:14 -07001816
1817 // reset retry count
1818 track->mRetryCount = kMaxTrackRetries;
Eric Laurent059b4be2009-11-09 23:32:22 -08001819 mixerStatus = MIXER_TRACKS_READY;
Eric Laurenta553c252009-07-17 12:17:14 -07001820 } else {
Eric Laurent8ac9f8d2009-12-18 05:47:48 -08001821 //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 -07001822 if (track->isStopped()) {
1823 track->reset();
1824 }
1825 if (track->isTerminated() || track->isStopped() || track->isPaused()) {
1826 // We have consumed all the buffers of this track.
1827 // Remove it from the list of active tracks.
1828 tracksToRemove->add(track);
Eric Laurenta553c252009-07-17 12:17:14 -07001829 } else {
1830 // No buffers for this track. Give it a few chances to
1831 // fill a buffer, then remove it from active list.
1832 if (--(track->mRetryCount) <= 0) {
Eric Laurent62443f52009-10-05 20:29:18 -07001833 LOGV("BUFFER TIMEOUT: remove(%d) from active list on thread %p", track->name(), this);
Eric Laurenta553c252009-07-17 12:17:14 -07001834 tracksToRemove->add(track);
Eric Laurent4712baa2010-09-30 16:12:31 -07001835 // indicate to client process that the track was disabled because of underrun
Eric Laurentae29b762011-03-28 18:37:07 -07001836 android_atomic_or(CBLK_DISABLED_ON, &cblk->flags);
Eric Laurent059b4be2009-11-09 23:32:22 -08001837 } else if (mixerStatus != MIXER_TRACKS_READY) {
1838 mixerStatus = MIXER_TRACKS_ENABLED;
Eric Laurenta553c252009-07-17 12:17:14 -07001839 }
Eric Laurenta553c252009-07-17 12:17:14 -07001840 }
Eric Laurent65b65452010-06-01 23:49:17 -07001841 mAudioMixer->disable(AudioMixer::MIXING);
Eric Laurenta553c252009-07-17 12:17:14 -07001842 }
1843 }
1844
1845 // remove all the tracks that need to be...
1846 count = tracksToRemove->size();
1847 if (UNLIKELY(count)) {
1848 for (size_t i=0 ; i<count ; i++) {
1849 const sp<Track>& track = tracksToRemove->itemAt(i);
1850 mActiveTracks.remove(track);
Eric Laurent65b65452010-06-01 23:49:17 -07001851 if (track->mainBuffer() != mMixBuffer) {
1852 chain = getEffectChain_l(track->sessionId());
1853 if (chain != 0) {
1854 LOGV("stopping track on chain %p for session Id: %d", chain.get(), track->sessionId());
Eric Laurent90681d62011-05-09 12:09:06 -07001855 chain->decActiveTrackCnt();
Eric Laurent65b65452010-06-01 23:49:17 -07001856 }
1857 }
Eric Laurenta553c252009-07-17 12:17:14 -07001858 if (track->isTerminated()) {
Eric Laurent90681d62011-05-09 12:09:06 -07001859 removeTrack_l(track);
Eric Laurenta553c252009-07-17 12:17:14 -07001860 }
1861 }
1862 }
1863
Eric Laurent65b65452010-06-01 23:49:17 -07001864 // mix buffer must be cleared if all tracks are connected to an
1865 // effect chain as in this case the mixer will not write to
1866 // mix buffer and track effects will accumulate into it
1867 if (mixedTracks != 0 && mixedTracks == tracksWithEffect) {
1868 memset(mMixBuffer, 0, mFrameCount * mChannelCount * sizeof(int16_t));
1869 }
1870
Eric Laurent059b4be2009-11-09 23:32:22 -08001871 return mixerStatus;
Eric Laurenta553c252009-07-17 12:17:14 -07001872}
1873
Eric Laurenteb8f850d2010-05-14 03:26:45 -07001874void AudioFlinger::MixerThread::invalidateTracks(int streamType)
Eric Laurenta553c252009-07-17 12:17:14 -07001875{
Eric Laurent8ed6ed02010-07-13 04:45:46 -07001876 LOGV ("MixerThread::invalidateTracks() mixer %p, streamType %d, mTracks.size %d",
1877 this, streamType, mTracks.size());
Eric Laurenta553c252009-07-17 12:17:14 -07001878 Mutex::Autolock _l(mLock);
Eric Laurent8ed6ed02010-07-13 04:45:46 -07001879
Eric Laurenta553c252009-07-17 12:17:14 -07001880 size_t size = mTracks.size();
1881 for (size_t i = 0; i < size; i++) {
1882 sp<Track> t = mTracks[i];
1883 if (t->type() == streamType) {
Eric Laurentae29b762011-03-28 18:37:07 -07001884 android_atomic_or(CBLK_INVALID_ON, &t->mCblk->flags);
Eric Laurenteb8f850d2010-05-14 03:26:45 -07001885 t->mCblk->cv.signal();
Eric Laurenta553c252009-07-17 12:17:14 -07001886 }
Eric Laurent53334cd2010-06-23 17:38:20 -07001887 }
1888}
Eric Laurenta553c252009-07-17 12:17:14 -07001889
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001890
Eric Laurenta553c252009-07-17 12:17:14 -07001891// getTrackName_l() must be called with ThreadBase::mLock held
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07001892int AudioFlinger::MixerThread::getTrackName_l()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001893{
1894 return mAudioMixer->getTrackName();
1895}
1896
Eric Laurenta553c252009-07-17 12:17:14 -07001897// deleteTrackName_l() must be called with ThreadBase::mLock held
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07001898void AudioFlinger::MixerThread::deleteTrackName_l(int name)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001899{
Eric Laurent0a080292009-12-07 10:53:10 -08001900 LOGV("remove track (%d) and delete from mixer", name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001901 mAudioMixer->deleteTrackName(name);
1902}
1903
Eric Laurenta553c252009-07-17 12:17:14 -07001904// checkForNewParameters_l() must be called with ThreadBase::mLock held
1905bool AudioFlinger::MixerThread::checkForNewParameters_l()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001906{
Eric Laurenta553c252009-07-17 12:17:14 -07001907 bool reconfig = false;
1908
Eric Laurent8fce46a2009-08-04 09:45:33 -07001909 while (!mNewParameters.isEmpty()) {
Eric Laurenta553c252009-07-17 12:17:14 -07001910 status_t status = NO_ERROR;
Eric Laurent8fce46a2009-08-04 09:45:33 -07001911 String8 keyValuePair = mNewParameters[0];
1912 AudioParameter param = AudioParameter(keyValuePair);
Eric Laurenta553c252009-07-17 12:17:14 -07001913 int value;
Eric Laurent8fce46a2009-08-04 09:45:33 -07001914
Eric Laurenta553c252009-07-17 12:17:14 -07001915 if (param.getInt(String8(AudioParameter::keySamplingRate), value) == NO_ERROR) {
1916 reconfig = true;
1917 }
1918 if (param.getInt(String8(AudioParameter::keyFormat), value) == NO_ERROR) {
Dima Zavin24fc2fb2011-04-19 22:30:36 -07001919 if (value != AUDIO_FORMAT_PCM_16_BIT) {
Eric Laurenta553c252009-07-17 12:17:14 -07001920 status = BAD_VALUE;
1921 } else {
1922 reconfig = true;
1923 }
1924 }
1925 if (param.getInt(String8(AudioParameter::keyChannels), value) == NO_ERROR) {
Dima Zavin24fc2fb2011-04-19 22:30:36 -07001926 if (value != AUDIO_CHANNEL_OUT_STEREO) {
Eric Laurenta553c252009-07-17 12:17:14 -07001927 status = BAD_VALUE;
1928 } else {
1929 reconfig = true;
1930 }
1931 }
1932 if (param.getInt(String8(AudioParameter::keyFrameCount), value) == NO_ERROR) {
1933 // do not accept frame count changes if tracks are open as the track buffer
1934 // size depends on frame count and correct behavior would not be garantied
1935 // if frame count is changed after track creation
1936 if (!mTracks.isEmpty()) {
1937 status = INVALID_OPERATION;
1938 } else {
1939 reconfig = true;
1940 }
1941 }
Eric Laurent65b65452010-06-01 23:49:17 -07001942 if (param.getInt(String8(AudioParameter::keyRouting), value) == NO_ERROR) {
Gloria Wang9b3f1522011-02-24 14:51:45 -08001943 // when changing the audio output device, call addBatteryData to notify
1944 // the change
Eric Laurent90681d62011-05-09 12:09:06 -07001945 if ((int)mDevice != value) {
Gloria Wang9b3f1522011-02-24 14:51:45 -08001946 uint32_t params = 0;
1947 // check whether speaker is on
Dima Zavin24fc2fb2011-04-19 22:30:36 -07001948 if (value & AUDIO_DEVICE_OUT_SPEAKER) {
Gloria Wang9b3f1522011-02-24 14:51:45 -08001949 params |= IMediaPlayerService::kBatteryDataSpeakerOn;
1950 }
1951
1952 int deviceWithoutSpeaker
Dima Zavin24fc2fb2011-04-19 22:30:36 -07001953 = AUDIO_DEVICE_OUT_ALL & ~AUDIO_DEVICE_OUT_SPEAKER;
Gloria Wang9b3f1522011-02-24 14:51:45 -08001954 // check if any other device (except speaker) is on
1955 if (value & deviceWithoutSpeaker ) {
1956 params |= IMediaPlayerService::kBatteryDataOtherAudioDeviceOn;
1957 }
1958
1959 if (params != 0) {
1960 addBatteryData(params);
1961 }
1962 }
1963
Eric Laurent65b65452010-06-01 23:49:17 -07001964 // forward device change to effects that have requested to be
1965 // aware of attached audio device.
1966 mDevice = (uint32_t)value;
1967 for (size_t i = 0; i < mEffectChains.size(); i++) {
Eric Laurent76c40f72010-07-15 12:50:15 -07001968 mEffectChains[i]->setDevice_l(mDevice);
Eric Laurent65b65452010-06-01 23:49:17 -07001969 }
1970 }
1971
Eric Laurenta553c252009-07-17 12:17:14 -07001972 if (status == NO_ERROR) {
Dima Zavin31f188892011-04-18 16:57:27 -07001973 status = mOutput->stream->common.set_parameters(&mOutput->stream->common,
Dima Zavin24fc2fb2011-04-19 22:30:36 -07001974 keyValuePair.string());
Eric Laurenta553c252009-07-17 12:17:14 -07001975 if (!mStandby && status == INVALID_OPERATION) {
Dima Zavin31f188892011-04-18 16:57:27 -07001976 mOutput->stream->common.standby(&mOutput->stream->common);
Eric Laurenta553c252009-07-17 12:17:14 -07001977 mStandby = true;
1978 mBytesWritten = 0;
Dima Zavin31f188892011-04-18 16:57:27 -07001979 status = mOutput->stream->common.set_parameters(&mOutput->stream->common,
Dima Zavin24fc2fb2011-04-19 22:30:36 -07001980 keyValuePair.string());
Eric Laurenta553c252009-07-17 12:17:14 -07001981 }
1982 if (status == NO_ERROR && reconfig) {
1983 delete mAudioMixer;
1984 readOutputParameters();
1985 mAudioMixer = new AudioMixer(mFrameCount, mSampleRate);
1986 for (size_t i = 0; i < mTracks.size() ; i++) {
1987 int name = getTrackName_l();
1988 if (name < 0) break;
1989 mTracks[i]->mName = name;
Eric Laurent6f7e0972009-08-10 08:15:12 -07001990 // limit track sample rate to 2 x new output sample rate
1991 if (mTracks[i]->mCblk->sampleRate > 2 * sampleRate()) {
1992 mTracks[i]->mCblk->sampleRate = 2 * sampleRate();
1993 }
Eric Laurenta553c252009-07-17 12:17:14 -07001994 }
Eric Laurent8fce46a2009-08-04 09:45:33 -07001995 sendConfigEvent_l(AudioSystem::OUTPUT_CONFIG_CHANGED);
Eric Laurenta553c252009-07-17 12:17:14 -07001996 }
1997 }
Eric Laurent3fdb1262009-11-07 00:01:32 -08001998
1999 mNewParameters.removeAt(0);
2000
Eric Laurenta553c252009-07-17 12:17:14 -07002001 mParamStatus = status;
Eric Laurenta553c252009-07-17 12:17:14 -07002002 mParamCond.signal();
Eric Laurent8fce46a2009-08-04 09:45:33 -07002003 mWaitWorkCV.wait(mLock);
Eric Laurenta553c252009-07-17 12:17:14 -07002004 }
2005 return reconfig;
2006}
2007
2008status_t AudioFlinger::MixerThread::dumpInternals(int fd, const Vector<String16>& args)
2009{
2010 const size_t SIZE = 256;
2011 char buffer[SIZE];
2012 String8 result;
2013
2014 PlaybackThread::dumpInternals(fd, args);
2015
2016 snprintf(buffer, SIZE, "AudioMixer tracks: %08x\n", mAudioMixer->trackNames());
2017 result.append(buffer);
2018 write(fd, result.string(), result.size());
2019 return NO_ERROR;
2020}
2021
Eric Laurent059b4be2009-11-09 23:32:22 -08002022uint32_t AudioFlinger::MixerThread::activeSleepTimeUs()
Eric Laurent62443f52009-10-05 20:29:18 -07002023{
Dima Zavin31f188892011-04-18 16:57:27 -07002024 return (uint32_t)(mOutput->stream->get_latency(mOutput->stream) * 1000) / 2;
Eric Laurent059b4be2009-11-09 23:32:22 -08002025}
2026
2027uint32_t AudioFlinger::MixerThread::idleSleepTimeUs()
2028{
Eric Laurenta54d7d32010-07-29 06:50:24 -07002029 return (uint32_t)(((mFrameCount * 1000) / mSampleRate) * 1000) / 2;
Eric Laurent62443f52009-10-05 20:29:18 -07002030}
2031
Eric Laurent8448a792010-08-18 18:13:17 -07002032uint32_t AudioFlinger::MixerThread::suspendSleepTimeUs()
2033{
2034 return (uint32_t)(((mFrameCount * 1000) / mSampleRate) * 1000);
2035}
2036
Eric Laurenta553c252009-07-17 12:17:14 -07002037// ----------------------------------------------------------------------------
Dima Zavin31f188892011-04-18 16:57:27 -07002038AudioFlinger::DirectOutputThread::DirectOutputThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id, uint32_t device)
Eric Laurent65b65452010-06-01 23:49:17 -07002039 : PlaybackThread(audioFlinger, output, id, device)
Eric Laurenta553c252009-07-17 12:17:14 -07002040{
2041 mType = PlaybackThread::DIRECT;
2042}
2043
2044AudioFlinger::DirectOutputThread::~DirectOutputThread()
2045{
2046}
2047
2048
Eric Laurent65b65452010-06-01 23:49:17 -07002049static inline int16_t clamp16(int32_t sample)
2050{
2051 if ((sample>>15) ^ (sample>>31))
2052 sample = 0x7FFF ^ (sample>>31);
2053 return sample;
2054}
2055
2056static inline
2057int32_t mul(int16_t in, int16_t v)
2058{
2059#if defined(__arm__) && !defined(__thumb__)
2060 int32_t out;
2061 asm( "smulbb %[out], %[in], %[v] \n"
2062 : [out]"=r"(out)
2063 : [in]"%r"(in), [v]"r"(v)
2064 : );
2065 return out;
2066#else
2067 return in * int32_t(v);
2068#endif
2069}
2070
2071void AudioFlinger::DirectOutputThread::applyVolume(uint16_t leftVol, uint16_t rightVol, bool ramp)
2072{
2073 // Do not apply volume on compressed audio
Dima Zavin24fc2fb2011-04-19 22:30:36 -07002074 if (!audio_is_linear_pcm(mFormat)) {
Eric Laurent65b65452010-06-01 23:49:17 -07002075 return;
2076 }
2077
2078 // convert to signed 16 bit before volume calculation
Dima Zavin24fc2fb2011-04-19 22:30:36 -07002079 if (mFormat == AUDIO_FORMAT_PCM_8_BIT) {
Eric Laurent65b65452010-06-01 23:49:17 -07002080 size_t count = mFrameCount * mChannelCount;
2081 uint8_t *src = (uint8_t *)mMixBuffer + count-1;
2082 int16_t *dst = mMixBuffer + count-1;
2083 while(count--) {
2084 *dst-- = (int16_t)(*src--^0x80) << 8;
2085 }
2086 }
2087
2088 size_t frameCount = mFrameCount;
2089 int16_t *out = mMixBuffer;
2090 if (ramp) {
2091 if (mChannelCount == 1) {
2092 int32_t d = ((int32_t)leftVol - (int32_t)mLeftVolShort) << 16;
2093 int32_t vlInc = d / (int32_t)frameCount;
2094 int32_t vl = ((int32_t)mLeftVolShort << 16);
2095 do {
2096 out[0] = clamp16(mul(out[0], vl >> 16) >> 12);
2097 out++;
2098 vl += vlInc;
2099 } while (--frameCount);
2100
2101 } else {
2102 int32_t d = ((int32_t)leftVol - (int32_t)mLeftVolShort) << 16;
2103 int32_t vlInc = d / (int32_t)frameCount;
2104 d = ((int32_t)rightVol - (int32_t)mRightVolShort) << 16;
2105 int32_t vrInc = d / (int32_t)frameCount;
2106 int32_t vl = ((int32_t)mLeftVolShort << 16);
2107 int32_t vr = ((int32_t)mRightVolShort << 16);
2108 do {
2109 out[0] = clamp16(mul(out[0], vl >> 16) >> 12);
2110 out[1] = clamp16(mul(out[1], vr >> 16) >> 12);
2111 out += 2;
2112 vl += vlInc;
2113 vr += vrInc;
2114 } while (--frameCount);
2115 }
2116 } else {
2117 if (mChannelCount == 1) {
2118 do {
2119 out[0] = clamp16(mul(out[0], leftVol) >> 12);
2120 out++;
2121 } while (--frameCount);
2122 } else {
2123 do {
2124 out[0] = clamp16(mul(out[0], leftVol) >> 12);
2125 out[1] = clamp16(mul(out[1], rightVol) >> 12);
2126 out += 2;
2127 } while (--frameCount);
2128 }
2129 }
2130
2131 // convert back to unsigned 8 bit after volume calculation
Dima Zavin24fc2fb2011-04-19 22:30:36 -07002132 if (mFormat == AUDIO_FORMAT_PCM_8_BIT) {
Eric Laurent65b65452010-06-01 23:49:17 -07002133 size_t count = mFrameCount * mChannelCount;
2134 int16_t *src = mMixBuffer;
2135 uint8_t *dst = (uint8_t *)mMixBuffer;
2136 while(count--) {
2137 *dst++ = (uint8_t)(((int32_t)*src++ + (1<<7)) >> 8)^0x80;
2138 }
2139 }
2140
2141 mLeftVolShort = leftVol;
2142 mRightVolShort = rightVol;
2143}
2144
Eric Laurenta553c252009-07-17 12:17:14 -07002145bool AudioFlinger::DirectOutputThread::threadLoop()
2146{
Eric Laurent059b4be2009-11-09 23:32:22 -08002147 uint32_t mixerStatus = MIXER_IDLE;
Eric Laurenta553c252009-07-17 12:17:14 -07002148 sp<Track> trackToRemove;
2149 sp<Track> activeTrack;
2150 nsecs_t standbyTime = systemTime();
2151 int8_t *curBuf;
2152 size_t mixBufferSize = mFrameCount*mFrameSize;
Eric Laurent059b4be2009-11-09 23:32:22 -08002153 uint32_t activeSleepTime = activeSleepTimeUs();
2154 uint32_t idleSleepTime = idleSleepTimeUs();
2155 uint32_t sleepTime = idleSleepTime;
Eric Laurentef9500f2010-03-11 14:47:00 -08002156 // use shorter standby delay as on normal output to release
2157 // hardware resources as soon as possible
2158 nsecs_t standbyDelay = microseconds(activeSleepTime*2);
Eric Laurent059b4be2009-11-09 23:32:22 -08002159
Eric Laurenta553c252009-07-17 12:17:14 -07002160 while (!exitPending())
2161 {
Eric Laurent65b65452010-06-01 23:49:17 -07002162 bool rampVolume;
2163 uint16_t leftVol;
2164 uint16_t rightVol;
2165 Vector< sp<EffectChain> > effectChains;
2166
Eric Laurenta553c252009-07-17 12:17:14 -07002167 processConfigEvents();
2168
Eric Laurent059b4be2009-11-09 23:32:22 -08002169 mixerStatus = MIXER_IDLE;
2170
Eric Laurenta553c252009-07-17 12:17:14 -07002171 { // scope for the mLock
2172
2173 Mutex::Autolock _l(mLock);
2174
2175 if (checkForNewParameters_l()) {
2176 mixBufferSize = mFrameCount*mFrameSize;
Eric Laurent059b4be2009-11-09 23:32:22 -08002177 activeSleepTime = activeSleepTimeUs();
2178 idleSleepTime = idleSleepTimeUs();
Eric Laurentef9500f2010-03-11 14:47:00 -08002179 standbyDelay = microseconds(activeSleepTime*2);
Eric Laurenta553c252009-07-17 12:17:14 -07002180 }
2181
2182 // put audio hardware into standby after short delay
2183 if UNLIKELY((!mActiveTracks.size() && systemTime() > standbyTime) ||
2184 mSuspended) {
2185 // wait until we have something to do...
2186 if (!mStandby) {
2187 LOGV("Audio hardware entering standby, mixer %p\n", this);
Dima Zavin31f188892011-04-18 16:57:27 -07002188 mOutput->stream->common.standby(&mOutput->stream->common);
Eric Laurenta553c252009-07-17 12:17:14 -07002189 mStandby = true;
2190 mBytesWritten = 0;
2191 }
2192
2193 if (!mActiveTracks.size() && mConfigEvents.isEmpty()) {
2194 // we're about to wait, flush the binder command buffer
2195 IPCThreadState::self()->flushCommands();
2196
2197 if (exitPending()) break;
2198
2199 LOGV("DirectOutputThread %p TID %d going to sleep\n", this, gettid());
2200 mWaitWorkCV.wait(mLock);
2201 LOGV("DirectOutputThread %p TID %d waking up in active mode\n", this, gettid());
2202
2203 if (mMasterMute == false) {
2204 char value[PROPERTY_VALUE_MAX];
2205 property_get("ro.audio.silent", value, "0");
2206 if (atoi(value)) {
2207 LOGD("Silence is golden");
2208 setMasterMute(true);
2209 }
2210 }
2211
Eric Laurentef9500f2010-03-11 14:47:00 -08002212 standbyTime = systemTime() + standbyDelay;
Eric Laurent059b4be2009-11-09 23:32:22 -08002213 sleepTime = idleSleepTime;
Eric Laurenta553c252009-07-17 12:17:14 -07002214 continue;
2215 }
2216 }
2217
Eric Laurent65b65452010-06-01 23:49:17 -07002218 effectChains = mEffectChains;
2219
Eric Laurenta553c252009-07-17 12:17:14 -07002220 // find out which tracks need to be processed
2221 if (mActiveTracks.size() != 0) {
2222 sp<Track> t = mActiveTracks[0].promote();
2223 if (t == 0) continue;
2224
2225 Track* const track = t.get();
2226 audio_track_cblk_t* cblk = track->cblk();
2227
2228 // The first time a track is added we wait
2229 // for all its buffers to be filled before processing it
Eric Laurent9a30fc12010-10-05 14:41:42 -07002230 if (cblk->framesReady() && track->isReady() &&
Eric Laurent380558b2010-04-09 06:11:48 -07002231 !track->isPaused() && !track->isTerminated())
Eric Laurenta553c252009-07-17 12:17:14 -07002232 {
2233 //LOGV("track %d u=%08x, s=%08x [OK]", track->name(), cblk->user, cblk->server);
2234
Eric Laurent65b65452010-06-01 23:49:17 -07002235 if (track->mFillingUpStatus == Track::FS_FILLED) {
2236 track->mFillingUpStatus = Track::FS_ACTIVE;
2237 mLeftVolFloat = mRightVolFloat = 0;
2238 mLeftVolShort = mRightVolShort = 0;
2239 if (track->mState == TrackBase::RESUMING) {
2240 track->mState = TrackBase::ACTIVE;
2241 rampVolume = true;
2242 }
2243 } else if (cblk->server != 0) {
2244 // If the track is stopped before the first frame was mixed,
2245 // do not apply ramp
2246 rampVolume = true;
2247 }
Eric Laurenta553c252009-07-17 12:17:14 -07002248 // compute volume for this track
2249 float left, right;
2250 if (track->isMuted() || mMasterMute || track->isPausing() ||
2251 mStreamTypes[track->type()].mute) {
2252 left = right = 0;
2253 if (track->isPausing()) {
2254 track->setPaused();
2255 }
2256 } else {
2257 float typeVolume = mStreamTypes[track->type()].volume;
2258 float v = mMasterVolume * typeVolume;
2259 float v_clamped = v * cblk->volume[0];
2260 if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN;
2261 left = v_clamped/MAX_GAIN;
2262 v_clamped = v * cblk->volume[1];
2263 if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN;
2264 right = v_clamped/MAX_GAIN;
2265 }
2266
Eric Laurent65b65452010-06-01 23:49:17 -07002267 if (left != mLeftVolFloat || right != mRightVolFloat) {
2268 mLeftVolFloat = left;
2269 mRightVolFloat = right;
Eric Laurenta553c252009-07-17 12:17:14 -07002270
Eric Laurent65b65452010-06-01 23:49:17 -07002271 // If audio HAL implements volume control,
2272 // force software volume to nominal value
Dima Zavin31f188892011-04-18 16:57:27 -07002273 if (mOutput->stream->set_volume(mOutput->stream, left, right) == NO_ERROR) {
Eric Laurent65b65452010-06-01 23:49:17 -07002274 left = 1.0f;
2275 right = 1.0f;
Eric Laurenta553c252009-07-17 12:17:14 -07002276 }
Eric Laurent65b65452010-06-01 23:49:17 -07002277
2278 // Convert volumes from float to 8.24
2279 uint32_t vl = (uint32_t)(left * (1 << 24));
2280 uint32_t vr = (uint32_t)(right * (1 << 24));
2281
2282 // Delegate volume control to effect in track effect chain if needed
2283 // only one effect chain can be present on DirectOutputThread, so if
2284 // there is one, the track is connected to it
2285 if (!effectChains.isEmpty()) {
Eric Laurent27a2fdf2010-09-10 17:44:44 -07002286 // Do not ramp volume if volume is controlled by effect
Eric Laurent76c40f72010-07-15 12:50:15 -07002287 if(effectChains[0]->setVolume_l(&vl, &vr)) {
Eric Laurent65b65452010-06-01 23:49:17 -07002288 rampVolume = false;
2289 }
2290 }
2291
2292 // Convert volumes from 8.24 to 4.12 format
2293 uint32_t v_clamped = (vl + (1 << 11)) >> 12;
2294 if (v_clamped > MAX_GAIN_INT) v_clamped = MAX_GAIN_INT;
2295 leftVol = (uint16_t)v_clamped;
2296 v_clamped = (vr + (1 << 11)) >> 12;
2297 if (v_clamped > MAX_GAIN_INT) v_clamped = MAX_GAIN_INT;
2298 rightVol = (uint16_t)v_clamped;
2299 } else {
2300 leftVol = mLeftVolShort;
2301 rightVol = mRightVolShort;
2302 rampVolume = false;
Eric Laurenta553c252009-07-17 12:17:14 -07002303 }
2304
2305 // reset retry count
Eric Laurentef9500f2010-03-11 14:47:00 -08002306 track->mRetryCount = kMaxTrackRetriesDirect;
Eric Laurenta553c252009-07-17 12:17:14 -07002307 activeTrack = t;
Eric Laurent059b4be2009-11-09 23:32:22 -08002308 mixerStatus = MIXER_TRACKS_READY;
Eric Laurenta553c252009-07-17 12:17:14 -07002309 } else {
2310 //LOGV("track %d u=%08x, s=%08x [NOT READY]", track->name(), cblk->user, cblk->server);
2311 if (track->isStopped()) {
2312 track->reset();
2313 }
2314 if (track->isTerminated() || track->isStopped() || track->isPaused()) {
2315 // We have consumed all the buffers of this track.
2316 // Remove it from the list of active tracks.
2317 trackToRemove = track;
2318 } else {
2319 // No buffers for this track. Give it a few chances to
2320 // fill a buffer, then remove it from active list.
2321 if (--(track->mRetryCount) <= 0) {
2322 LOGV("BUFFER TIMEOUT: remove(%d) from active list", track->name());
2323 trackToRemove = track;
Eric Laurent059b4be2009-11-09 23:32:22 -08002324 } else {
2325 mixerStatus = MIXER_TRACKS_ENABLED;
Eric Laurenta553c252009-07-17 12:17:14 -07002326 }
Eric Laurent059b4be2009-11-09 23:32:22 -08002327 }
Eric Laurenta553c252009-07-17 12:17:14 -07002328 }
2329 }
2330
2331 // remove all the tracks that need to be...
2332 if (UNLIKELY(trackToRemove != 0)) {
2333 mActiveTracks.remove(trackToRemove);
Eric Laurent65b65452010-06-01 23:49:17 -07002334 if (!effectChains.isEmpty()) {
Eric Laurent8ed6ed02010-07-13 04:45:46 -07002335 LOGV("stopping track on chain %p for session Id: %d", effectChains[0].get(),
2336 trackToRemove->sessionId());
Eric Laurent90681d62011-05-09 12:09:06 -07002337 effectChains[0]->decActiveTrackCnt();
Eric Laurent65b65452010-06-01 23:49:17 -07002338 }
Eric Laurenta553c252009-07-17 12:17:14 -07002339 if (trackToRemove->isTerminated()) {
Eric Laurent90681d62011-05-09 12:09:06 -07002340 removeTrack_l(trackToRemove);
Eric Laurenta553c252009-07-17 12:17:14 -07002341 }
2342 }
Eric Laurent65b65452010-06-01 23:49:17 -07002343
Eric Laurent8ed6ed02010-07-13 04:45:46 -07002344 lockEffectChains_l(effectChains);
Eric Laurenta553c252009-07-17 12:17:14 -07002345 }
2346
Eric Laurent059b4be2009-11-09 23:32:22 -08002347 if (LIKELY(mixerStatus == MIXER_TRACKS_READY)) {
Eric Laurentf69a3f82009-09-22 00:35:48 -07002348 AudioBufferProvider::Buffer buffer;
2349 size_t frameCount = mFrameCount;
2350 curBuf = (int8_t *)mMixBuffer;
2351 // output audio to hardware
Eric Laurent65b65452010-06-01 23:49:17 -07002352 while (frameCount) {
Eric Laurentf69a3f82009-09-22 00:35:48 -07002353 buffer.frameCount = frameCount;
2354 activeTrack->getNextBuffer(&buffer);
2355 if (UNLIKELY(buffer.raw == 0)) {
2356 memset(curBuf, 0, frameCount * mFrameSize);
2357 break;
2358 }
2359 memcpy(curBuf, buffer.raw, buffer.frameCount * mFrameSize);
2360 frameCount -= buffer.frameCount;
2361 curBuf += buffer.frameCount * mFrameSize;
2362 activeTrack->releaseBuffer(&buffer);
2363 }
2364 sleepTime = 0;
Eric Laurentef9500f2010-03-11 14:47:00 -08002365 standbyTime = systemTime() + standbyDelay;
Eric Laurent96c08a62009-09-07 08:38:38 -07002366 } else {
Eric Laurent62443f52009-10-05 20:29:18 -07002367 if (sleepTime == 0) {
Eric Laurent059b4be2009-11-09 23:32:22 -08002368 if (mixerStatus == MIXER_TRACKS_ENABLED) {
2369 sleepTime = activeSleepTime;
2370 } else {
2371 sleepTime = idleSleepTime;
2372 }
Dima Zavin24fc2fb2011-04-19 22:30:36 -07002373 } else if (mBytesWritten != 0 && audio_is_linear_pcm(mFormat)) {
Eric Laurentf69a3f82009-09-22 00:35:48 -07002374 memset (mMixBuffer, 0, mFrameCount * mFrameSize);
Eric Laurent96c08a62009-09-07 08:38:38 -07002375 sleepTime = 0;
Eric Laurent96c08a62009-09-07 08:38:38 -07002376 }
Eric Laurentf69a3f82009-09-22 00:35:48 -07002377 }
Eric Laurent96c08a62009-09-07 08:38:38 -07002378
Eric Laurentf69a3f82009-09-22 00:35:48 -07002379 if (mSuspended) {
Eric Laurent8448a792010-08-18 18:13:17 -07002380 sleepTime = suspendSleepTimeUs();
Eric Laurentf69a3f82009-09-22 00:35:48 -07002381 }
2382 // sleepTime == 0 means we must write to audio hardware
2383 if (sleepTime == 0) {
Eric Laurent65b65452010-06-01 23:49:17 -07002384 if (mixerStatus == MIXER_TRACKS_READY) {
2385 applyVolume(leftVol, rightVol, rampVolume);
2386 }
2387 for (size_t i = 0; i < effectChains.size(); i ++) {
2388 effectChains[i]->process_l();
2389 }
Eric Laurent8ed6ed02010-07-13 04:45:46 -07002390 unlockEffectChains(effectChains);
Eric Laurent65b65452010-06-01 23:49:17 -07002391
Eric Laurentf69a3f82009-09-22 00:35:48 -07002392 mLastWriteTime = systemTime();
2393 mInWrite = true;
Eric Laurent0986e792010-01-19 17:37:09 -08002394 mBytesWritten += mixBufferSize;
Dima Zavin31f188892011-04-18 16:57:27 -07002395 int bytesWritten = (int)mOutput->stream->write(mOutput->stream, mMixBuffer, mixBufferSize);
Eric Laurent0986e792010-01-19 17:37:09 -08002396 if (bytesWritten < 0) mBytesWritten -= mixBufferSize;
Eric Laurentf69a3f82009-09-22 00:35:48 -07002397 mNumWrites++;
2398 mInWrite = false;
2399 mStandby = false;
2400 } else {
Eric Laurent8ed6ed02010-07-13 04:45:46 -07002401 unlockEffectChains(effectChains);
Eric Laurentf69a3f82009-09-22 00:35:48 -07002402 usleep(sleepTime);
Eric Laurenta553c252009-07-17 12:17:14 -07002403 }
2404
2405 // finally let go of removed track, without the lock held
2406 // since we can't guarantee the destructors won't acquire that
2407 // same lock.
2408 trackToRemove.clear();
2409 activeTrack.clear();
Eric Laurent65b65452010-06-01 23:49:17 -07002410
2411 // Effect chains will be actually deleted here if they were removed from
2412 // mEffectChains list during mixing or effects processing
2413 effectChains.clear();
Eric Laurenta553c252009-07-17 12:17:14 -07002414 }
2415
2416 if (!mStandby) {
Dima Zavin31f188892011-04-18 16:57:27 -07002417 mOutput->stream->common.standby(&mOutput->stream->common);
Eric Laurenta553c252009-07-17 12:17:14 -07002418 }
Eric Laurenta553c252009-07-17 12:17:14 -07002419
2420 LOGV("DirectOutputThread %p exiting", this);
2421 return false;
2422}
2423
2424// getTrackName_l() must be called with ThreadBase::mLock held
2425int AudioFlinger::DirectOutputThread::getTrackName_l()
2426{
2427 return 0;
2428}
2429
2430// deleteTrackName_l() must be called with ThreadBase::mLock held
2431void AudioFlinger::DirectOutputThread::deleteTrackName_l(int name)
2432{
2433}
2434
2435// checkForNewParameters_l() must be called with ThreadBase::mLock held
2436bool AudioFlinger::DirectOutputThread::checkForNewParameters_l()
2437{
2438 bool reconfig = false;
2439
Eric Laurent8fce46a2009-08-04 09:45:33 -07002440 while (!mNewParameters.isEmpty()) {
Eric Laurenta553c252009-07-17 12:17:14 -07002441 status_t status = NO_ERROR;
Eric Laurent8fce46a2009-08-04 09:45:33 -07002442 String8 keyValuePair = mNewParameters[0];
2443 AudioParameter param = AudioParameter(keyValuePair);
Eric Laurenta553c252009-07-17 12:17:14 -07002444 int value;
Eric Laurent8fce46a2009-08-04 09:45:33 -07002445
Eric Laurenta553c252009-07-17 12:17:14 -07002446 if (param.getInt(String8(AudioParameter::keyFrameCount), value) == NO_ERROR) {
2447 // do not accept frame count changes if tracks are open as the track buffer
2448 // size depends on frame count and correct behavior would not be garantied
2449 // if frame count is changed after track creation
2450 if (!mTracks.isEmpty()) {
2451 status = INVALID_OPERATION;
2452 } else {
2453 reconfig = true;
2454 }
2455 }
2456 if (status == NO_ERROR) {
Dima Zavin31f188892011-04-18 16:57:27 -07002457 status = mOutput->stream->common.set_parameters(&mOutput->stream->common,
Dima Zavin24fc2fb2011-04-19 22:30:36 -07002458 keyValuePair.string());
Eric Laurenta553c252009-07-17 12:17:14 -07002459 if (!mStandby && status == INVALID_OPERATION) {
Dima Zavin31f188892011-04-18 16:57:27 -07002460 mOutput->stream->common.standby(&mOutput->stream->common);
Eric Laurenta553c252009-07-17 12:17:14 -07002461 mStandby = true;
2462 mBytesWritten = 0;
Dima Zavin31f188892011-04-18 16:57:27 -07002463 status = mOutput->stream->common.set_parameters(&mOutput->stream->common,
Dima Zavin24fc2fb2011-04-19 22:30:36 -07002464 keyValuePair.string());
Eric Laurenta553c252009-07-17 12:17:14 -07002465 }
2466 if (status == NO_ERROR && reconfig) {
2467 readOutputParameters();
Eric Laurent8fce46a2009-08-04 09:45:33 -07002468 sendConfigEvent_l(AudioSystem::OUTPUT_CONFIG_CHANGED);
Eric Laurenta553c252009-07-17 12:17:14 -07002469 }
2470 }
Eric Laurent3fdb1262009-11-07 00:01:32 -08002471
2472 mNewParameters.removeAt(0);
2473
Eric Laurenta553c252009-07-17 12:17:14 -07002474 mParamStatus = status;
Eric Laurenta553c252009-07-17 12:17:14 -07002475 mParamCond.signal();
Eric Laurent8fce46a2009-08-04 09:45:33 -07002476 mWaitWorkCV.wait(mLock);
Eric Laurenta553c252009-07-17 12:17:14 -07002477 }
2478 return reconfig;
The Android Open Source Projectf1e484a2009-01-22 00:13:42 -08002479}
2480
Eric Laurent059b4be2009-11-09 23:32:22 -08002481uint32_t AudioFlinger::DirectOutputThread::activeSleepTimeUs()
Eric Laurent62443f52009-10-05 20:29:18 -07002482{
2483 uint32_t time;
Dima Zavin24fc2fb2011-04-19 22:30:36 -07002484 if (audio_is_linear_pcm(mFormat)) {
Dima Zavin31f188892011-04-18 16:57:27 -07002485 time = (uint32_t)(mOutput->stream->get_latency(mOutput->stream) * 1000) / 2;
Eric Laurent059b4be2009-11-09 23:32:22 -08002486 } else {
2487 time = 10000;
2488 }
2489 return time;
2490}
2491
2492uint32_t AudioFlinger::DirectOutputThread::idleSleepTimeUs()
2493{
2494 uint32_t time;
Dima Zavin24fc2fb2011-04-19 22:30:36 -07002495 if (audio_is_linear_pcm(mFormat)) {
Eric Laurenta54d7d32010-07-29 06:50:24 -07002496 time = (uint32_t)(((mFrameCount * 1000) / mSampleRate) * 1000) / 2;
Eric Laurent62443f52009-10-05 20:29:18 -07002497 } else {
2498 time = 10000;
2499 }
2500 return time;
2501}
2502
Eric Laurent8448a792010-08-18 18:13:17 -07002503uint32_t AudioFlinger::DirectOutputThread::suspendSleepTimeUs()
2504{
2505 uint32_t time;
Dima Zavin24fc2fb2011-04-19 22:30:36 -07002506 if (audio_is_linear_pcm(mFormat)) {
Eric Laurent8448a792010-08-18 18:13:17 -07002507 time = (uint32_t)(((mFrameCount * 1000) / mSampleRate) * 1000);
2508 } else {
2509 time = 10000;
2510 }
2511 return time;
2512}
2513
2514
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002515// ----------------------------------------------------------------------------
2516
Eric Laurent49f02be2009-11-19 09:00:56 -08002517AudioFlinger::DuplicatingThread::DuplicatingThread(const sp<AudioFlinger>& audioFlinger, AudioFlinger::MixerThread* mainThread, int id)
Eric Laurent65b65452010-06-01 23:49:17 -07002518 : MixerThread(audioFlinger, mainThread->getOutput(), id, mainThread->device()), mWaitTimeMs(UINT_MAX)
Eric Laurenta553c252009-07-17 12:17:14 -07002519{
2520 mType = PlaybackThread::DUPLICATING;
2521 addOutputTrack(mainThread);
2522}
2523
2524AudioFlinger::DuplicatingThread::~DuplicatingThread()
2525{
Eric Laurent0a080292009-12-07 10:53:10 -08002526 for (size_t i = 0; i < mOutputTracks.size(); i++) {
2527 mOutputTracks[i]->destroy();
2528 }
Eric Laurenta553c252009-07-17 12:17:14 -07002529 mOutputTracks.clear();
2530}
2531
2532bool AudioFlinger::DuplicatingThread::threadLoop()
2533{
Eric Laurenta553c252009-07-17 12:17:14 -07002534 Vector< sp<Track> > tracksToRemove;
Eric Laurent059b4be2009-11-09 23:32:22 -08002535 uint32_t mixerStatus = MIXER_IDLE;
Eric Laurenta553c252009-07-17 12:17:14 -07002536 nsecs_t standbyTime = systemTime();
2537 size_t mixBufferSize = mFrameCount*mFrameSize;
2538 SortedVector< sp<OutputTrack> > outputTracks;
Eric Laurent62443f52009-10-05 20:29:18 -07002539 uint32_t writeFrames = 0;
Eric Laurent059b4be2009-11-09 23:32:22 -08002540 uint32_t activeSleepTime = activeSleepTimeUs();
2541 uint32_t idleSleepTime = idleSleepTimeUs();
2542 uint32_t sleepTime = idleSleepTime;
Eric Laurent65b65452010-06-01 23:49:17 -07002543 Vector< sp<EffectChain> > effectChains;
Eric Laurenta553c252009-07-17 12:17:14 -07002544
2545 while (!exitPending())
2546 {
2547 processConfigEvents();
2548
Eric Laurent059b4be2009-11-09 23:32:22 -08002549 mixerStatus = MIXER_IDLE;
Eric Laurenta553c252009-07-17 12:17:14 -07002550 { // scope for the mLock
2551
2552 Mutex::Autolock _l(mLock);
2553
2554 if (checkForNewParameters_l()) {
2555 mixBufferSize = mFrameCount*mFrameSize;
Eric Laurent8ac9f8d2009-12-18 05:47:48 -08002556 updateWaitTime();
Eric Laurent059b4be2009-11-09 23:32:22 -08002557 activeSleepTime = activeSleepTimeUs();
2558 idleSleepTime = idleSleepTimeUs();
Eric Laurenta553c252009-07-17 12:17:14 -07002559 }
2560
2561 const SortedVector< wp<Track> >& activeTracks = mActiveTracks;
2562
2563 for (size_t i = 0; i < mOutputTracks.size(); i++) {
2564 outputTracks.add(mOutputTracks[i]);
2565 }
2566
2567 // put audio hardware into standby after short delay
2568 if UNLIKELY((!activeTracks.size() && systemTime() > standbyTime) ||
2569 mSuspended) {
2570 if (!mStandby) {
2571 for (size_t i = 0; i < outputTracks.size(); i++) {
Eric Laurenta553c252009-07-17 12:17:14 -07002572 outputTracks[i]->stop();
Eric Laurenta553c252009-07-17 12:17:14 -07002573 }
2574 mStandby = true;
2575 mBytesWritten = 0;
2576 }
2577
2578 if (!activeTracks.size() && mConfigEvents.isEmpty()) {
2579 // we're about to wait, flush the binder command buffer
2580 IPCThreadState::self()->flushCommands();
2581 outputTracks.clear();
2582
2583 if (exitPending()) break;
2584
2585 LOGV("DuplicatingThread %p TID %d going to sleep\n", this, gettid());
2586 mWaitWorkCV.wait(mLock);
2587 LOGV("DuplicatingThread %p TID %d waking up\n", this, gettid());
2588 if (mMasterMute == false) {
2589 char value[PROPERTY_VALUE_MAX];
2590 property_get("ro.audio.silent", value, "0");
2591 if (atoi(value)) {
2592 LOGD("Silence is golden");
2593 setMasterMute(true);
2594 }
2595 }
2596
2597 standbyTime = systemTime() + kStandbyTimeInNsecs;
Eric Laurent059b4be2009-11-09 23:32:22 -08002598 sleepTime = idleSleepTime;
Eric Laurenta553c252009-07-17 12:17:14 -07002599 continue;
2600 }
2601 }
2602
Eric Laurent059b4be2009-11-09 23:32:22 -08002603 mixerStatus = prepareTracks_l(activeTracks, &tracksToRemove);
Eric Laurent65b65452010-06-01 23:49:17 -07002604
2605 // prevent any changes in effect chain list and in each effect chain
2606 // during mixing and effect process as the audio buffers could be deleted
2607 // or modified if an effect is created or deleted
Eric Laurent8ed6ed02010-07-13 04:45:46 -07002608 lockEffectChains_l(effectChains);
Eric Laurentf69a3f82009-09-22 00:35:48 -07002609 }
Eric Laurenta553c252009-07-17 12:17:14 -07002610
Eric Laurent059b4be2009-11-09 23:32:22 -08002611 if (LIKELY(mixerStatus == MIXER_TRACKS_READY)) {
Eric Laurenta553c252009-07-17 12:17:14 -07002612 // mix buffers...
Eric Laurent8ac9f8d2009-12-18 05:47:48 -08002613 if (outputsReady(outputTracks)) {
Eric Laurent65b65452010-06-01 23:49:17 -07002614 mAudioMixer->process();
Eric Laurent8ac9f8d2009-12-18 05:47:48 -08002615 } else {
Eric Laurent65b65452010-06-01 23:49:17 -07002616 memset(mMixBuffer, 0, mixBufferSize);
Eric Laurent8ac9f8d2009-12-18 05:47:48 -08002617 }
Eric Laurentf69a3f82009-09-22 00:35:48 -07002618 sleepTime = 0;
Eric Laurent62443f52009-10-05 20:29:18 -07002619 writeFrames = mFrameCount;
Eric Laurenta553c252009-07-17 12:17:14 -07002620 } else {
Eric Laurent62443f52009-10-05 20:29:18 -07002621 if (sleepTime == 0) {
Eric Laurent059b4be2009-11-09 23:32:22 -08002622 if (mixerStatus == MIXER_TRACKS_ENABLED) {
2623 sleepTime = activeSleepTime;
2624 } else {
2625 sleepTime = idleSleepTime;
2626 }
Eric Laurent62443f52009-10-05 20:29:18 -07002627 } else if (mBytesWritten != 0) {
2628 // flush remaining overflow buffers in output tracks
2629 for (size_t i = 0; i < outputTracks.size(); i++) {
2630 if (outputTracks[i]->isActive()) {
2631 sleepTime = 0;
2632 writeFrames = 0;
Eric Laurent65b65452010-06-01 23:49:17 -07002633 memset(mMixBuffer, 0, mixBufferSize);
Eric Laurent62443f52009-10-05 20:29:18 -07002634 break;
2635 }
2636 }
Eric Laurenta553c252009-07-17 12:17:14 -07002637 }
2638 }
Eric Laurentf69a3f82009-09-22 00:35:48 -07002639
2640 if (mSuspended) {
Eric Laurent8448a792010-08-18 18:13:17 -07002641 sleepTime = suspendSleepTimeUs();
Eric Laurentf69a3f82009-09-22 00:35:48 -07002642 }
2643 // sleepTime == 0 means we must write to audio hardware
2644 if (sleepTime == 0) {
Eric Laurent65b65452010-06-01 23:49:17 -07002645 for (size_t i = 0; i < effectChains.size(); i ++) {
2646 effectChains[i]->process_l();
2647 }
2648 // enable changes in effect chain
Eric Laurent8ed6ed02010-07-13 04:45:46 -07002649 unlockEffectChains(effectChains);
Eric Laurent65b65452010-06-01 23:49:17 -07002650
Eric Laurent62443f52009-10-05 20:29:18 -07002651 standbyTime = systemTime() + kStandbyTimeInNsecs;
Eric Laurentf69a3f82009-09-22 00:35:48 -07002652 for (size_t i = 0; i < outputTracks.size(); i++) {
Eric Laurent65b65452010-06-01 23:49:17 -07002653 outputTracks[i]->write(mMixBuffer, writeFrames);
Eric Laurenta553c252009-07-17 12:17:14 -07002654 }
Eric Laurentf69a3f82009-09-22 00:35:48 -07002655 mStandby = false;
2656 mBytesWritten += mixBufferSize;
Eric Laurenta553c252009-07-17 12:17:14 -07002657 } else {
Eric Laurent65b65452010-06-01 23:49:17 -07002658 // enable changes in effect chain
Eric Laurent8ed6ed02010-07-13 04:45:46 -07002659 unlockEffectChains(effectChains);
Eric Laurentf69a3f82009-09-22 00:35:48 -07002660 usleep(sleepTime);
Eric Laurenta553c252009-07-17 12:17:14 -07002661 }
2662
2663 // finally let go of all our tracks, without the lock held
2664 // since we can't guarantee the destructors won't acquire that
2665 // same lock.
2666 tracksToRemove.clear();
2667 outputTracks.clear();
Eric Laurent65b65452010-06-01 23:49:17 -07002668
2669 // Effect chains will be actually deleted here if they were removed from
2670 // mEffectChains list during mixing or effects processing
2671 effectChains.clear();
Eric Laurenta553c252009-07-17 12:17:14 -07002672 }
2673
Eric Laurenta553c252009-07-17 12:17:14 -07002674 return false;
2675}
2676
2677void AudioFlinger::DuplicatingThread::addOutputTrack(MixerThread *thread)
2678{
2679 int frameCount = (3 * mFrameCount * mSampleRate) / thread->sampleRate();
2680 OutputTrack *outputTrack = new OutputTrack((ThreadBase *)thread,
Eric Laurent8ac9f8d2009-12-18 05:47:48 -08002681 this,
Eric Laurenta553c252009-07-17 12:17:14 -07002682 mSampleRate,
2683 mFormat,
Jean-Michel Trivi54392232011-05-24 15:53:33 -07002684 mChannelMask,
Eric Laurenta553c252009-07-17 12:17:14 -07002685 frameCount);
Eric Laurent6c30a712009-08-10 23:22:32 -07002686 if (outputTrack->cblk() != NULL) {
Dima Zavin24fc2fb2011-04-19 22:30:36 -07002687 thread->setStreamVolume(AUDIO_STREAM_CNT, 1.0f);
Eric Laurent6c30a712009-08-10 23:22:32 -07002688 mOutputTracks.add(outputTrack);
2689 LOGV("addOutputTrack() track %p, on thread %p", outputTrack, thread);
Eric Laurent8ac9f8d2009-12-18 05:47:48 -08002690 updateWaitTime();
Eric Laurent6c30a712009-08-10 23:22:32 -07002691 }
Eric Laurenta553c252009-07-17 12:17:14 -07002692}
2693
2694void AudioFlinger::DuplicatingThread::removeOutputTrack(MixerThread *thread)
2695{
2696 Mutex::Autolock _l(mLock);
2697 for (size_t i = 0; i < mOutputTracks.size(); i++) {
2698 if (mOutputTracks[i]->thread() == (ThreadBase *)thread) {
Eric Laurent6c30a712009-08-10 23:22:32 -07002699 mOutputTracks[i]->destroy();
Eric Laurenta553c252009-07-17 12:17:14 -07002700 mOutputTracks.removeAt(i);
Eric Laurent8ac9f8d2009-12-18 05:47:48 -08002701 updateWaitTime();
Eric Laurenta553c252009-07-17 12:17:14 -07002702 return;
2703 }
2704 }
2705 LOGV("removeOutputTrack(): unkonwn thread: %p", thread);
2706}
2707
Eric Laurent8ac9f8d2009-12-18 05:47:48 -08002708void AudioFlinger::DuplicatingThread::updateWaitTime()
2709{
2710 mWaitTimeMs = UINT_MAX;
2711 for (size_t i = 0; i < mOutputTracks.size(); i++) {
2712 sp<ThreadBase> strong = mOutputTracks[i]->thread().promote();
2713 if (strong != NULL) {
2714 uint32_t waitTimeMs = (strong->frameCount() * 2 * 1000) / strong->sampleRate();
2715 if (waitTimeMs < mWaitTimeMs) {
2716 mWaitTimeMs = waitTimeMs;
2717 }
2718 }
2719 }
2720}
2721
2722
2723bool AudioFlinger::DuplicatingThread::outputsReady(SortedVector< sp<OutputTrack> > &outputTracks)
2724{
2725 for (size_t i = 0; i < outputTracks.size(); i++) {
2726 sp <ThreadBase> thread = outputTracks[i]->thread().promote();
2727 if (thread == 0) {
2728 LOGW("DuplicatingThread::outputsReady() could not promote thread on output track %p", outputTracks[i].get());
2729 return false;
2730 }
2731 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
2732 if (playbackThread->standby() && !playbackThread->isSuspended()) {
2733 LOGV("DuplicatingThread output track %p on thread %p Not Ready", outputTracks[i].get(), thread.get());
2734 return false;
2735 }
2736 }
2737 return true;
2738}
2739
2740uint32_t AudioFlinger::DuplicatingThread::activeSleepTimeUs()
2741{
2742 return (mWaitTimeMs * 1000) / 2;
2743}
2744
Eric Laurenta553c252009-07-17 12:17:14 -07002745// ----------------------------------------------------------------------------
2746
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07002747// TrackBase constructor must be called with AudioFlinger::mLock held
Eric Laurenta553c252009-07-17 12:17:14 -07002748AudioFlinger::ThreadBase::TrackBase::TrackBase(
2749 const wp<ThreadBase>& thread,
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002750 const sp<Client>& client,
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002751 uint32_t sampleRate,
Jean-Michel Trivi54392232011-05-24 15:53:33 -07002752 uint32_t format,
2753 uint32_t channelMask,
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002754 int frameCount,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002755 uint32_t flags,
Eric Laurent65b65452010-06-01 23:49:17 -07002756 const sp<IMemory>& sharedBuffer,
2757 int sessionId)
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002758 : RefBase(),
Eric Laurenta553c252009-07-17 12:17:14 -07002759 mThread(thread),
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002760 mClient(client),
Eric Laurent8a77a992009-09-09 05:16:08 -07002761 mCblk(0),
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002762 mFrameCount(0),
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002763 mState(IDLE),
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002764 mClientTid(-1),
2765 mFormat(format),
Eric Laurent65b65452010-06-01 23:49:17 -07002766 mFlags(flags & ~SYSTEM_FLAGS_MASK),
2767 mSessionId(sessionId)
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002768{
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002769 LOGV_IF(sharedBuffer != 0, "sharedBuffer: %p, size: %d", sharedBuffer->pointer(), sharedBuffer->size());
2770
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002771 // LOGD("Creating track with %d buffers @ %d bytes", bufferCount, bufferSize);
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002772 size_t size = sizeof(audio_track_cblk_t);
Jean-Michel Trivi54392232011-05-24 15:53:33 -07002773 uint8_t channelCount = popcount(channelMask);
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002774 size_t bufferSize = frameCount*channelCount*sizeof(int16_t);
2775 if (sharedBuffer == 0) {
2776 size += bufferSize;
2777 }
2778
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002779 if (client != NULL) {
2780 mCblkMemory = client->heap()->allocate(size);
2781 if (mCblkMemory != 0) {
2782 mCblk = static_cast<audio_track_cblk_t *>(mCblkMemory->pointer());
2783 if (mCblk) { // construct the shared structure in-place.
2784 new(mCblk) audio_track_cblk_t();
2785 // clear all buffers
2786 mCblk->frameCount = frameCount;
Eric Laurent88e209d2009-07-07 07:10:45 -07002787 mCblk->sampleRate = sampleRate;
Jean-Michel Trivi54392232011-05-24 15:53:33 -07002788 mChannelCount = channelCount;
2789 mChannelMask = channelMask;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002790 if (sharedBuffer == 0) {
2791 mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t);
2792 memset(mBuffer, 0, frameCount*channelCount*sizeof(int16_t));
2793 // Force underrun condition to avoid false underrun callback until first data is
Eric Laurent4712baa2010-09-30 16:12:31 -07002794 // written to buffer (other flags are cleared)
Eric Laurenteb8f850d2010-05-14 03:26:45 -07002795 mCblk->flags = CBLK_UNDERRUN_ON;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002796 } else {
2797 mBuffer = sharedBuffer->pointer();
2798 }
2799 mBufferEnd = (uint8_t *)mBuffer + bufferSize;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002800 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002801 } else {
2802 LOGE("not enough memory for AudioTrack size=%u", size);
2803 client->heap()->dump("AudioTrack");
2804 return;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002805 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002806 } else {
2807 mCblk = (audio_track_cblk_t *)(new uint8_t[size]);
2808 if (mCblk) { // construct the shared structure in-place.
2809 new(mCblk) audio_track_cblk_t();
2810 // clear all buffers
2811 mCblk->frameCount = frameCount;
Eric Laurent88e209d2009-07-07 07:10:45 -07002812 mCblk->sampleRate = sampleRate;
Jean-Michel Trivi54392232011-05-24 15:53:33 -07002813 mChannelCount = channelCount;
2814 mChannelMask = channelMask;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002815 mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t);
2816 memset(mBuffer, 0, frameCount*channelCount*sizeof(int16_t));
2817 // Force underrun condition to avoid false underrun callback until first data is
Eric Laurent4712baa2010-09-30 16:12:31 -07002818 // written to buffer (other flags are cleared)
Eric Laurenteb8f850d2010-05-14 03:26:45 -07002819 mCblk->flags = CBLK_UNDERRUN_ON;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002820 mBufferEnd = (uint8_t *)mBuffer + bufferSize;
2821 }
2822 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002823}
2824
Eric Laurent2bb6b2a2009-09-16 06:02:45 -07002825AudioFlinger::ThreadBase::TrackBase::~TrackBase()
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002826{
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002827 if (mCblk) {
Eric Laurenta553c252009-07-17 12:17:14 -07002828 mCblk->~audio_track_cblk_t(); // destroy our shared-structure.
2829 if (mClient == NULL) {
2830 delete mCblk;
2831 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002832 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002833 mCblkMemory.clear(); // and free the shared memory
Eric Laurentb9481d82009-09-17 05:12:56 -07002834 if (mClient != NULL) {
2835 Mutex::Autolock _l(mClient->audioFlinger()->mLock);
2836 mClient.clear();
2837 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002838}
2839
Eric Laurent2bb6b2a2009-09-16 06:02:45 -07002840void AudioFlinger::ThreadBase::TrackBase::releaseBuffer(AudioBufferProvider::Buffer* buffer)
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002841{
2842 buffer->raw = 0;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002843 mFrameCount = buffer->frameCount;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002844 step();
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002845 buffer->frameCount = 0;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002846}
2847
Eric Laurent2bb6b2a2009-09-16 06:02:45 -07002848bool AudioFlinger::ThreadBase::TrackBase::step() {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002849 bool result;
2850 audio_track_cblk_t* cblk = this->cblk();
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002851
2852 result = cblk->stepServer(mFrameCount);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002853 if (!result) {
2854 LOGV("stepServer failed acquiring cblk mutex");
2855 mFlags |= STEPSERVER_FAILED;
2856 }
2857 return result;
2858}
2859
Eric Laurent2bb6b2a2009-09-16 06:02:45 -07002860void AudioFlinger::ThreadBase::TrackBase::reset() {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002861 audio_track_cblk_t* cblk = this->cblk();
2862
2863 cblk->user = 0;
2864 cblk->server = 0;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002865 cblk->userBase = 0;
2866 cblk->serverBase = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002867 mFlags &= (uint32_t)(~SYSTEM_FLAGS_MASK);
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002868 LOGV("TrackBase::reset");
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002869}
2870
Eric Laurent2bb6b2a2009-09-16 06:02:45 -07002871sp<IMemory> AudioFlinger::ThreadBase::TrackBase::getCblk() const
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002872{
2873 return mCblkMemory;
2874}
2875
Eric Laurent2bb6b2a2009-09-16 06:02:45 -07002876int AudioFlinger::ThreadBase::TrackBase::sampleRate() const {
The Android Open Source Project10592532009-03-18 17:39:46 -07002877 return (int)mCblk->sampleRate;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002878}
2879
Eric Laurent2bb6b2a2009-09-16 06:02:45 -07002880int AudioFlinger::ThreadBase::TrackBase::channelCount() const {
Jean-Michel Trivi54392232011-05-24 15:53:33 -07002881 return (const int)mChannelCount;
2882}
2883
2884uint32_t AudioFlinger::ThreadBase::TrackBase::channelMask() const {
2885 return mChannelMask;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002886}
2887
Eric Laurent2bb6b2a2009-09-16 06:02:45 -07002888void* AudioFlinger::ThreadBase::TrackBase::getBuffer(uint32_t offset, uint32_t frames) const {
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002889 audio_track_cblk_t* cblk = this->cblk();
Eric Laurenta553c252009-07-17 12:17:14 -07002890 int8_t *bufferStart = (int8_t *)mBuffer + (offset-cblk->serverBase)*cblk->frameSize;
2891 int8_t *bufferEnd = bufferStart + frames * cblk->frameSize;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002892
2893 // Check validity of returned pointer in case the track control block would have been corrupted.
Eric Laurenta553c252009-07-17 12:17:14 -07002894 if (bufferStart < mBuffer || bufferStart > bufferEnd || bufferEnd > mBufferEnd ||
2895 ((unsigned long)bufferStart & (unsigned long)(cblk->frameSize - 1))) {
The Android Open Source Project10592532009-03-18 17:39:46 -07002896 LOGE("TrackBase::getBuffer buffer out of range:\n start: %p, end %p , mBuffer %p mBufferEnd %p\n \
Jean-Michel Trivi54392232011-05-24 15:53:33 -07002897 server %d, serverBase %d, user %d, userBase %d",
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002898 bufferStart, bufferEnd, mBuffer, mBufferEnd,
Jean-Michel Trivi54392232011-05-24 15:53:33 -07002899 cblk->server, cblk->serverBase, cblk->user, cblk->userBase);
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002900 return 0;
2901 }
2902
2903 return bufferStart;
2904}
2905
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002906// ----------------------------------------------------------------------------
2907
Eric Laurenta553c252009-07-17 12:17:14 -07002908// Track constructor must be called with AudioFlinger::mLock and ThreadBase::mLock held
2909AudioFlinger::PlaybackThread::Track::Track(
2910 const wp<ThreadBase>& thread,
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002911 const sp<Client>& client,
2912 int streamType,
2913 uint32_t sampleRate,
Jean-Michel Trivi54392232011-05-24 15:53:33 -07002914 uint32_t format,
2915 uint32_t channelMask,
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002916 int frameCount,
Eric Laurent65b65452010-06-01 23:49:17 -07002917 const sp<IMemory>& sharedBuffer,
2918 int sessionId)
Jean-Michel Trivi54392232011-05-24 15:53:33 -07002919 : TrackBase(thread, client, sampleRate, format, channelMask, frameCount, 0, sharedBuffer, sessionId),
Eric Laurenta92ebfa2010-08-31 13:50:07 -07002920 mMute(false), mSharedBuffer(sharedBuffer), mName(-1), mMainBuffer(NULL), mAuxBuffer(NULL),
2921 mAuxEffectId(0), mHasVolumeController(false)
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002922{
Eric Laurent8a77a992009-09-09 05:16:08 -07002923 if (mCblk != NULL) {
2924 sp<ThreadBase> baseThread = thread.promote();
2925 if (baseThread != 0) {
2926 PlaybackThread *playbackThread = (PlaybackThread *)baseThread.get();
2927 mName = playbackThread->getTrackName_l();
Eric Laurent65b65452010-06-01 23:49:17 -07002928 mMainBuffer = playbackThread->mixBuffer();
Eric Laurent8a77a992009-09-09 05:16:08 -07002929 }
2930 LOGV("Track constructor name %d, calling thread %d", mName, IPCThreadState::self()->getCallingPid());
2931 if (mName < 0) {
2932 LOGE("no more track names available");
2933 }
2934 mVolume[0] = 1.0f;
2935 mVolume[1] = 1.0f;
2936 mStreamType = streamType;
2937 // NOTE: audio_track_cblk_t::frameSize for 8 bit PCM data is based on a sample size of
2938 // 16 bit because data is converted to 16 bit before being stored in buffer by AudioTrack
Jean-Michel Trivi54392232011-05-24 15:53:33 -07002939 mCblk->frameSize = audio_is_linear_pcm(format) ? mChannelCount * sizeof(int16_t) : sizeof(int8_t);
Eric Laurenta553c252009-07-17 12:17:14 -07002940 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002941}
2942
Eric Laurenta553c252009-07-17 12:17:14 -07002943AudioFlinger::PlaybackThread::Track::~Track()
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002944{
Eric Laurenta553c252009-07-17 12:17:14 -07002945 LOGV("PlaybackThread::Track destructor");
2946 sp<ThreadBase> thread = mThread.promote();
2947 if (thread != 0) {
Eric Laurentac196e12009-12-01 02:17:41 -08002948 Mutex::Autolock _l(thread->mLock);
Eric Laurenta553c252009-07-17 12:17:14 -07002949 mState = TERMINATED;
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07002950 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002951}
2952
Eric Laurenta553c252009-07-17 12:17:14 -07002953void AudioFlinger::PlaybackThread::Track::destroy()
2954{
2955 // NOTE: destroyTrack_l() can remove a strong reference to this Track
2956 // by removing it from mTracks vector, so there is a risk that this Tracks's
2957 // desctructor is called. As the destructor needs to lock mLock,
2958 // we must acquire a strong reference on this Track before locking mLock
2959 // here so that the destructor is called only when exiting this function.
2960 // On the other hand, as long as Track::destroy() is only called by
2961 // TrackHandle destructor, the TrackHandle still holds a strong ref on
2962 // this Track with its member mTrack.
2963 sp<Track> keep(this);
2964 { // scope for mLock
2965 sp<ThreadBase> thread = mThread.promote();
2966 if (thread != 0) {
Eric Laurentac196e12009-12-01 02:17:41 -08002967 if (!isOutputTrack()) {
2968 if (mState == ACTIVE || mState == RESUMING) {
Eric Laurent8ed6ed02010-07-13 04:45:46 -07002969 AudioSystem::stopOutput(thread->id(),
Dima Zavin24fc2fb2011-04-19 22:30:36 -07002970 (audio_stream_type_t)mStreamType,
Eric Laurent8ed6ed02010-07-13 04:45:46 -07002971 mSessionId);
Gloria Wang9b3f1522011-02-24 14:51:45 -08002972
2973 // to track the speaker usage
2974 addBatteryData(IMediaPlayerService::kBatteryDataAudioFlingerStop);
Eric Laurentac196e12009-12-01 02:17:41 -08002975 }
2976 AudioSystem::releaseOutput(thread->id());
Eric Laurent49f02be2009-11-19 09:00:56 -08002977 }
Eric Laurenta553c252009-07-17 12:17:14 -07002978 Mutex::Autolock _l(thread->mLock);
2979 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
2980 playbackThread->destroyTrack_l(this);
2981 }
2982 }
2983}
2984
2985void AudioFlinger::PlaybackThread::Track::dump(char* buffer, size_t size)
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002986{
Jean-Michel Trivi54392232011-05-24 15:53:33 -07002987 snprintf(buffer, size, " %05d %05d %03u %03u 0x%08x %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 -07002988 mName - AudioMixer::TRACK0,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002989 (mClient == NULL) ? getpid() : mClient->pid(),
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002990 mStreamType,
2991 mFormat,
Jean-Michel Trivi54392232011-05-24 15:53:33 -07002992 mChannelMask,
Eric Laurent65b65452010-06-01 23:49:17 -07002993 mSessionId,
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002994 mFrameCount,
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002995 mState,
2996 mMute,
2997 mFillingUpStatus,
2998 mCblk->sampleRate,
2999 mCblk->volume[0],
3000 mCblk->volume[1],
3001 mCblk->server,
Eric Laurent65b65452010-06-01 23:49:17 -07003002 mCblk->user,
3003 (int)mMainBuffer,
3004 (int)mAuxBuffer);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003005}
3006
Eric Laurenta553c252009-07-17 12:17:14 -07003007status_t AudioFlinger::PlaybackThread::Track::getNextBuffer(AudioBufferProvider::Buffer* buffer)
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003008{
3009 audio_track_cblk_t* cblk = this->cblk();
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08003010 uint32_t framesReady;
3011 uint32_t framesReq = buffer->frameCount;
3012
3013 // Check if last stepServer failed, try to step now
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003014 if (mFlags & TrackBase::STEPSERVER_FAILED) {
3015 if (!step()) goto getNextBuffer_exit;
3016 LOGV("stepServer recovered");
3017 mFlags &= ~TrackBase::STEPSERVER_FAILED;
3018 }
3019
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08003020 framesReady = cblk->framesReady();
3021
3022 if (LIKELY(framesReady)) {
3023 uint32_t s = cblk->server;
3024 uint32_t bufferEnd = cblk->serverBase + cblk->frameCount;
3025
3026 bufferEnd = (cblk->loopEnd < bufferEnd) ? cblk->loopEnd : bufferEnd;
3027 if (framesReq > framesReady) {
3028 framesReq = framesReady;
3029 }
3030 if (s + framesReq > bufferEnd) {
3031 framesReq = bufferEnd - s;
3032 }
3033
3034 buffer->raw = getBuffer(s, framesReq);
3035 if (buffer->raw == 0) goto getNextBuffer_exit;
3036
3037 buffer->frameCount = framesReq;
3038 return NO_ERROR;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003039 }
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08003040
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003041getNextBuffer_exit:
3042 buffer->raw = 0;
3043 buffer->frameCount = 0;
Eric Laurent62443f52009-10-05 20:29:18 -07003044 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 -07003045 return NOT_ENOUGH_DATA;
3046}
3047
Eric Laurenta553c252009-07-17 12:17:14 -07003048bool AudioFlinger::PlaybackThread::Track::isReady() const {
Eric Laurent9a30fc12010-10-05 14:41:42 -07003049 if (mFillingUpStatus != FS_FILLING || isStopped() || isPausing()) return true;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08003050
3051 if (mCblk->framesReady() >= mCblk->frameCount ||
Eric Laurenteb8f850d2010-05-14 03:26:45 -07003052 (mCblk->flags & CBLK_FORCEREADY_MSK)) {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003053 mFillingUpStatus = FS_FILLED;
Eric Laurentae29b762011-03-28 18:37:07 -07003054 android_atomic_and(~CBLK_FORCEREADY_MSK, &mCblk->flags);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003055 return true;
3056 }
3057 return false;
3058}
3059
Eric Laurenta553c252009-07-17 12:17:14 -07003060status_t AudioFlinger::PlaybackThread::Track::start()
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003061{
Eric Laurent49f02be2009-11-19 09:00:56 -08003062 status_t status = NO_ERROR;
Eric Laurent0d7e0482010-07-19 06:24:46 -07003063 LOGV("start(%d), calling thread %d session %d",
3064 mName, IPCThreadState::self()->getCallingPid(), mSessionId);
Eric Laurenta553c252009-07-17 12:17:14 -07003065 sp<ThreadBase> thread = mThread.promote();
3066 if (thread != 0) {
3067 Mutex::Autolock _l(thread->mLock);
Eric Laurent49f02be2009-11-19 09:00:56 -08003068 int state = mState;
3069 // here the track could be either new, or restarted
3070 // in both cases "unstop" the track
3071 if (mState == PAUSED) {
3072 mState = TrackBase::RESUMING;
3073 LOGV("PAUSED => RESUMING (%d) on thread %p", mName, this);
3074 } else {
3075 mState = TrackBase::ACTIVE;
3076 LOGV("? => ACTIVE (%d) on thread %p", mName, this);
3077 }
3078
3079 if (!isOutputTrack() && state != ACTIVE && state != RESUMING) {
3080 thread->mLock.unlock();
Eric Laurent8ed6ed02010-07-13 04:45:46 -07003081 status = AudioSystem::startOutput(thread->id(),
Dima Zavin24fc2fb2011-04-19 22:30:36 -07003082 (audio_stream_type_t)mStreamType,
Eric Laurent8ed6ed02010-07-13 04:45:46 -07003083 mSessionId);
Eric Laurent49f02be2009-11-19 09:00:56 -08003084 thread->mLock.lock();
Gloria Wang9b3f1522011-02-24 14:51:45 -08003085
3086 // to track the speaker usage
3087 if (status == NO_ERROR) {
3088 addBatteryData(IMediaPlayerService::kBatteryDataAudioFlingerStart);
3089 }
Eric Laurent49f02be2009-11-19 09:00:56 -08003090 }
3091 if (status == NO_ERROR) {
3092 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
3093 playbackThread->addTrack_l(this);
3094 } else {
3095 mState = state;
3096 }
3097 } else {
3098 status = BAD_VALUE;
Eric Laurenta553c252009-07-17 12:17:14 -07003099 }
Eric Laurent49f02be2009-11-19 09:00:56 -08003100 return status;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003101}
3102
Eric Laurenta553c252009-07-17 12:17:14 -07003103void AudioFlinger::PlaybackThread::Track::stop()
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003104{
Eric Laurenta553c252009-07-17 12:17:14 -07003105 LOGV("stop(%d), calling thread %d", mName, IPCThreadState::self()->getCallingPid());
3106 sp<ThreadBase> thread = mThread.promote();
3107 if (thread != 0) {
3108 Mutex::Autolock _l(thread->mLock);
Eric Laurent49f02be2009-11-19 09:00:56 -08003109 int state = mState;
Eric Laurenta553c252009-07-17 12:17:14 -07003110 if (mState > STOPPED) {
3111 mState = STOPPED;
3112 // If the track is not active (PAUSED and buffers full), flush buffers
3113 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
3114 if (playbackThread->mActiveTracks.indexOf(this) < 0) {
3115 reset();
3116 }
Eric Laurent62443f52009-10-05 20:29:18 -07003117 LOGV("(> STOPPED) => STOPPED (%d) on thread %p", mName, playbackThread);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003118 }
Eric Laurent49f02be2009-11-19 09:00:56 -08003119 if (!isOutputTrack() && (state == ACTIVE || state == RESUMING)) {
3120 thread->mLock.unlock();
Eric Laurent8ed6ed02010-07-13 04:45:46 -07003121 AudioSystem::stopOutput(thread->id(),
Dima Zavin24fc2fb2011-04-19 22:30:36 -07003122 (audio_stream_type_t)mStreamType,
Eric Laurent8ed6ed02010-07-13 04:45:46 -07003123 mSessionId);
Eric Laurent49f02be2009-11-19 09:00:56 -08003124 thread->mLock.lock();
Gloria Wang9b3f1522011-02-24 14:51:45 -08003125
3126 // to track the speaker usage
3127 addBatteryData(IMediaPlayerService::kBatteryDataAudioFlingerStop);
Eric Laurent49f02be2009-11-19 09:00:56 -08003128 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003129 }
3130}
3131
Eric Laurenta553c252009-07-17 12:17:14 -07003132void AudioFlinger::PlaybackThread::Track::pause()
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003133{
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003134 LOGV("pause(%d), calling thread %d", mName, IPCThreadState::self()->getCallingPid());
Eric Laurenta553c252009-07-17 12:17:14 -07003135 sp<ThreadBase> thread = mThread.promote();
3136 if (thread != 0) {
3137 Mutex::Autolock _l(thread->mLock);
3138 if (mState == ACTIVE || mState == RESUMING) {
3139 mState = PAUSING;
Eric Laurent62443f52009-10-05 20:29:18 -07003140 LOGV("ACTIVE/RESUMING => PAUSING (%d) on thread %p", mName, thread.get());
Eric Laurent49f02be2009-11-19 09:00:56 -08003141 if (!isOutputTrack()) {
3142 thread->mLock.unlock();
Eric Laurent8ed6ed02010-07-13 04:45:46 -07003143 AudioSystem::stopOutput(thread->id(),
Dima Zavin24fc2fb2011-04-19 22:30:36 -07003144 (audio_stream_type_t)mStreamType,
Eric Laurent8ed6ed02010-07-13 04:45:46 -07003145 mSessionId);
Eric Laurent49f02be2009-11-19 09:00:56 -08003146 thread->mLock.lock();
Gloria Wang9b3f1522011-02-24 14:51:45 -08003147
3148 // to track the speaker usage
3149 addBatteryData(IMediaPlayerService::kBatteryDataAudioFlingerStop);
Eric Laurent49f02be2009-11-19 09:00:56 -08003150 }
Eric Laurenta553c252009-07-17 12:17:14 -07003151 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003152 }
3153}
3154
Eric Laurenta553c252009-07-17 12:17:14 -07003155void AudioFlinger::PlaybackThread::Track::flush()
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003156{
3157 LOGV("flush(%d)", mName);
Eric Laurenta553c252009-07-17 12:17:14 -07003158 sp<ThreadBase> thread = mThread.promote();
3159 if (thread != 0) {
3160 Mutex::Autolock _l(thread->mLock);
3161 if (mState != STOPPED && mState != PAUSED && mState != PAUSING) {
3162 return;
3163 }
3164 // No point remaining in PAUSED state after a flush => go to
3165 // STOPPED state
3166 mState = STOPPED;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003167
Eric Laurentae29b762011-03-28 18:37:07 -07003168 // do not reset the track if it is still in the process of being stopped or paused.
3169 // this will be done by prepareTracks_l() when the track is stopped.
3170 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
3171 if (playbackThread->mActiveTracks.indexOf(this) < 0) {
3172 reset();
3173 }
Eric Laurenta553c252009-07-17 12:17:14 -07003174 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003175}
3176
Eric Laurenta553c252009-07-17 12:17:14 -07003177void AudioFlinger::PlaybackThread::Track::reset()
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003178{
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08003179 // Do not reset twice to avoid discarding data written just after a flush and before
3180 // the audioflinger thread detects the track is stopped.
3181 if (!mResetDone) {
3182 TrackBase::reset();
3183 // Force underrun condition to avoid false underrun callback until first data is
3184 // written to buffer
Eric Laurentae29b762011-03-28 18:37:07 -07003185 android_atomic_and(~CBLK_FORCEREADY_MSK, &mCblk->flags);
3186 android_atomic_or(CBLK_UNDERRUN_ON, &mCblk->flags);
Eric Laurenta553c252009-07-17 12:17:14 -07003187 mFillingUpStatus = FS_FILLING;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08003188 mResetDone = true;
3189 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003190}
3191
Eric Laurenta553c252009-07-17 12:17:14 -07003192void AudioFlinger::PlaybackThread::Track::mute(bool muted)
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003193{
3194 mMute = muted;
3195}
3196
Eric Laurenta553c252009-07-17 12:17:14 -07003197void AudioFlinger::PlaybackThread::Track::setVolume(float left, float right)
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003198{
3199 mVolume[0] = left;
3200 mVolume[1] = right;
3201}
3202
Eric Laurent65b65452010-06-01 23:49:17 -07003203status_t AudioFlinger::PlaybackThread::Track::attachAuxEffect(int EffectId)
3204{
3205 status_t status = DEAD_OBJECT;
3206 sp<ThreadBase> thread = mThread.promote();
3207 if (thread != 0) {
3208 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
3209 status = playbackThread->attachAuxEffect(this, EffectId);
3210 }
3211 return status;
3212}
3213
3214void AudioFlinger::PlaybackThread::Track::setAuxBuffer(int EffectId, int32_t *buffer)
3215{
3216 mAuxEffectId = EffectId;
3217 mAuxBuffer = buffer;
3218}
3219
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003220// ----------------------------------------------------------------------------
3221
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07003222// RecordTrack constructor must be called with AudioFlinger::mLock held
Eric Laurenta553c252009-07-17 12:17:14 -07003223AudioFlinger::RecordThread::RecordTrack::RecordTrack(
3224 const wp<ThreadBase>& thread,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003225 const sp<Client>& client,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003226 uint32_t sampleRate,
Jean-Michel Trivi54392232011-05-24 15:53:33 -07003227 uint32_t format,
3228 uint32_t channelMask,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003229 int frameCount,
Eric Laurent65b65452010-06-01 23:49:17 -07003230 uint32_t flags,
3231 int sessionId)
Eric Laurenta553c252009-07-17 12:17:14 -07003232 : TrackBase(thread, client, sampleRate, format,
Jean-Michel Trivi54392232011-05-24 15:53:33 -07003233 channelMask, frameCount, flags, 0, sessionId),
Eric Laurenta553c252009-07-17 12:17:14 -07003234 mOverflow(false)
3235{
Eric Laurent8a77a992009-09-09 05:16:08 -07003236 if (mCblk != NULL) {
3237 LOGV("RecordTrack constructor, size %d", (int)mBufferEnd - (int)mBuffer);
Dima Zavin24fc2fb2011-04-19 22:30:36 -07003238 if (format == AUDIO_FORMAT_PCM_16_BIT) {
Jean-Michel Trivi54392232011-05-24 15:53:33 -07003239 mCblk->frameSize = mChannelCount * sizeof(int16_t);
Dima Zavin24fc2fb2011-04-19 22:30:36 -07003240 } else if (format == AUDIO_FORMAT_PCM_8_BIT) {
Jean-Michel Trivi54392232011-05-24 15:53:33 -07003241 mCblk->frameSize = mChannelCount * sizeof(int8_t);
Eric Laurent8a77a992009-09-09 05:16:08 -07003242 } else {
3243 mCblk->frameSize = sizeof(int8_t);
3244 }
3245 }
Eric Laurenta553c252009-07-17 12:17:14 -07003246}
3247
3248AudioFlinger::RecordThread::RecordTrack::~RecordTrack()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003249{
Eric Laurent49f02be2009-11-19 09:00:56 -08003250 sp<ThreadBase> thread = mThread.promote();
3251 if (thread != 0) {
3252 AudioSystem::releaseInput(thread->id());
3253 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003254}
3255
Eric Laurenta553c252009-07-17 12:17:14 -07003256status_t AudioFlinger::RecordThread::RecordTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003257{
3258 audio_track_cblk_t* cblk = this->cblk();
3259 uint32_t framesAvail;
3260 uint32_t framesReq = buffer->frameCount;
3261
3262 // Check if last stepServer failed, try to step now
3263 if (mFlags & TrackBase::STEPSERVER_FAILED) {
3264 if (!step()) goto getNextBuffer_exit;
3265 LOGV("stepServer recovered");
3266 mFlags &= ~TrackBase::STEPSERVER_FAILED;
3267 }
3268
3269 framesAvail = cblk->framesAvailable_l();
3270
3271 if (LIKELY(framesAvail)) {
3272 uint32_t s = cblk->server;
3273 uint32_t bufferEnd = cblk->serverBase + cblk->frameCount;
3274
3275 if (framesReq > framesAvail) {
3276 framesReq = framesAvail;
3277 }
3278 if (s + framesReq > bufferEnd) {
3279 framesReq = bufferEnd - s;
3280 }
3281
3282 buffer->raw = getBuffer(s, framesReq);
3283 if (buffer->raw == 0) goto getNextBuffer_exit;
3284
3285 buffer->frameCount = framesReq;
3286 return NO_ERROR;
3287 }
3288
3289getNextBuffer_exit:
3290 buffer->raw = 0;
3291 buffer->frameCount = 0;
3292 return NOT_ENOUGH_DATA;
3293}
3294
Eric Laurenta553c252009-07-17 12:17:14 -07003295status_t AudioFlinger::RecordThread::RecordTrack::start()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003296{
Eric Laurenta553c252009-07-17 12:17:14 -07003297 sp<ThreadBase> thread = mThread.promote();
3298 if (thread != 0) {
3299 RecordThread *recordThread = (RecordThread *)thread.get();
3300 return recordThread->start(this);
Eric Laurent49f02be2009-11-19 09:00:56 -08003301 } else {
3302 return BAD_VALUE;
Eric Laurenta553c252009-07-17 12:17:14 -07003303 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003304}
3305
Eric Laurenta553c252009-07-17 12:17:14 -07003306void AudioFlinger::RecordThread::RecordTrack::stop()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003307{
Eric Laurenta553c252009-07-17 12:17:14 -07003308 sp<ThreadBase> thread = mThread.promote();
3309 if (thread != 0) {
3310 RecordThread *recordThread = (RecordThread *)thread.get();
3311 recordThread->stop(this);
Eric Laurentae29b762011-03-28 18:37:07 -07003312 TrackBase::reset();
3313 // Force overerrun condition to avoid false overrun callback until first data is
3314 // read from buffer
3315 android_atomic_or(CBLK_UNDERRUN_ON, &mCblk->flags);
Eric Laurenta553c252009-07-17 12:17:14 -07003316 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003317}
3318
Eric Laurent3fdb1262009-11-07 00:01:32 -08003319void AudioFlinger::RecordThread::RecordTrack::dump(char* buffer, size_t size)
3320{
Jean-Michel Trivi54392232011-05-24 15:53:33 -07003321 snprintf(buffer, size, " %05d %03u 0x%08x %05d %04u %01d %05u %08x %08x\n",
Eric Laurent3fdb1262009-11-07 00:01:32 -08003322 (mClient == NULL) ? getpid() : mClient->pid(),
3323 mFormat,
Jean-Michel Trivi54392232011-05-24 15:53:33 -07003324 mChannelMask,
Eric Laurent65b65452010-06-01 23:49:17 -07003325 mSessionId,
Eric Laurent3fdb1262009-11-07 00:01:32 -08003326 mFrameCount,
3327 mState,
3328 mCblk->sampleRate,
3329 mCblk->server,
3330 mCblk->user);
3331}
3332
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003333
3334// ----------------------------------------------------------------------------
3335
Eric Laurenta553c252009-07-17 12:17:14 -07003336AudioFlinger::PlaybackThread::OutputTrack::OutputTrack(
3337 const wp<ThreadBase>& thread,
Eric Laurent8ac9f8d2009-12-18 05:47:48 -08003338 DuplicatingThread *sourceThread,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003339 uint32_t sampleRate,
Jean-Michel Trivi54392232011-05-24 15:53:33 -07003340 uint32_t format,
3341 uint32_t channelMask,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003342 int frameCount)
Jean-Michel Trivi54392232011-05-24 15:53:33 -07003343 : Track(thread, NULL, AUDIO_STREAM_CNT, sampleRate, format, channelMask, frameCount, NULL, 0),
Eric Laurent8ac9f8d2009-12-18 05:47:48 -08003344 mActive(false), mSourceThread(sourceThread)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003345{
Eric Laurenta553c252009-07-17 12:17:14 -07003346
3347 PlaybackThread *playbackThread = (PlaybackThread *)thread.unsafe_get();
Eric Laurent6c30a712009-08-10 23:22:32 -07003348 if (mCblk != NULL) {
Eric Laurenteb8f850d2010-05-14 03:26:45 -07003349 mCblk->flags |= CBLK_DIRECTION_OUT;
Eric Laurent6c30a712009-08-10 23:22:32 -07003350 mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t);
3351 mCblk->volume[0] = mCblk->volume[1] = 0x1000;
3352 mOutBuffer.frameCount = 0;
Eric Laurent6c30a712009-08-10 23:22:32 -07003353 playbackThread->mTracks.add(this);
Jean-Michel Trivi54392232011-05-24 15:53:33 -07003354 LOGV("OutputTrack constructor mCblk %p, mBuffer %p, mCblk->buffers %p, " \
3355 "mCblk->frameCount %d, mCblk->sampleRate %d, mChannelMask 0x%08x mBufferEnd %p",
3356 mCblk, mBuffer, mCblk->buffers,
3357 mCblk->frameCount, mCblk->sampleRate, mChannelMask, mBufferEnd);
Eric Laurent6c30a712009-08-10 23:22:32 -07003358 } else {
3359 LOGW("Error creating output track on thread %p", playbackThread);
3360 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003361}
3362
Eric Laurenta553c252009-07-17 12:17:14 -07003363AudioFlinger::PlaybackThread::OutputTrack::~OutputTrack()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003364{
Eric Laurent6c30a712009-08-10 23:22:32 -07003365 clearBufferQueue();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003366}
3367
Eric Laurenta553c252009-07-17 12:17:14 -07003368status_t AudioFlinger::PlaybackThread::OutputTrack::start()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003369{
3370 status_t status = Track::start();
Eric Laurenta553c252009-07-17 12:17:14 -07003371 if (status != NO_ERROR) {
3372 return status;
3373 }
3374
3375 mActive = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003376 mRetryCount = 127;
3377 return status;
3378}
3379
Eric Laurenta553c252009-07-17 12:17:14 -07003380void AudioFlinger::PlaybackThread::OutputTrack::stop()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003381{
3382 Track::stop();
3383 clearBufferQueue();
3384 mOutBuffer.frameCount = 0;
Eric Laurenta553c252009-07-17 12:17:14 -07003385 mActive = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003386}
3387
Eric Laurenta553c252009-07-17 12:17:14 -07003388bool AudioFlinger::PlaybackThread::OutputTrack::write(int16_t* data, uint32_t frames)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003389{
3390 Buffer *pInBuffer;
3391 Buffer inBuffer;
Jean-Michel Trivi54392232011-05-24 15:53:33 -07003392 uint32_t channelCount = mChannelCount;
Eric Laurenta553c252009-07-17 12:17:14 -07003393 bool outputBufferFull = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003394 inBuffer.frameCount = frames;
3395 inBuffer.i16 = data;
Eric Laurenta553c252009-07-17 12:17:14 -07003396
Eric Laurent8ac9f8d2009-12-18 05:47:48 -08003397 uint32_t waitTimeLeftMs = mSourceThread->waitTimeMs();
Eric Laurenta553c252009-07-17 12:17:14 -07003398
Eric Laurent62443f52009-10-05 20:29:18 -07003399 if (!mActive && frames != 0) {
Eric Laurenta553c252009-07-17 12:17:14 -07003400 start();
3401 sp<ThreadBase> thread = mThread.promote();
3402 if (thread != 0) {
3403 MixerThread *mixerThread = (MixerThread *)thread.get();
3404 if (mCblk->frameCount > frames){
3405 if (mBufferQueue.size() < kMaxOverFlowBuffers) {
3406 uint32_t startFrames = (mCblk->frameCount - frames);
3407 pInBuffer = new Buffer;
Eric Laurentb0a01472010-05-14 05:45:46 -07003408 pInBuffer->mBuffer = new int16_t[startFrames * channelCount];
Eric Laurenta553c252009-07-17 12:17:14 -07003409 pInBuffer->frameCount = startFrames;
3410 pInBuffer->i16 = pInBuffer->mBuffer;
Eric Laurentb0a01472010-05-14 05:45:46 -07003411 memset(pInBuffer->raw, 0, startFrames * channelCount * sizeof(int16_t));
Eric Laurenta553c252009-07-17 12:17:14 -07003412 mBufferQueue.add(pInBuffer);
3413 } else {
3414 LOGW ("OutputTrack::write() %p no more buffers in queue", this);
3415 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003416 }
Eric Laurenta553c252009-07-17 12:17:14 -07003417 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003418 }
3419
Eric Laurenta553c252009-07-17 12:17:14 -07003420 while (waitTimeLeftMs) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003421 // First write pending buffers, then new data
3422 if (mBufferQueue.size()) {
3423 pInBuffer = mBufferQueue.itemAt(0);
3424 } else {
3425 pInBuffer = &inBuffer;
3426 }
Eric Laurenta553c252009-07-17 12:17:14 -07003427
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003428 if (pInBuffer->frameCount == 0) {
3429 break;
3430 }
Eric Laurenta553c252009-07-17 12:17:14 -07003431
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003432 if (mOutBuffer.frameCount == 0) {
3433 mOutBuffer.frameCount = pInBuffer->frameCount;
Eric Laurenta553c252009-07-17 12:17:14 -07003434 nsecs_t startTime = systemTime();
3435 if (obtainBuffer(&mOutBuffer, waitTimeLeftMs) == (status_t)AudioTrack::NO_MORE_BUFFERS) {
Eric Laurent8ac9f8d2009-12-18 05:47:48 -08003436 LOGV ("OutputTrack::write() %p thread %p no more output buffers", this, mThread.unsafe_get());
Eric Laurenta553c252009-07-17 12:17:14 -07003437 outputBufferFull = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003438 break;
3439 }
Eric Laurenta553c252009-07-17 12:17:14 -07003440 uint32_t waitTimeMs = (uint32_t)ns2ms(systemTime() - startTime);
Eric Laurenta553c252009-07-17 12:17:14 -07003441 if (waitTimeLeftMs >= waitTimeMs) {
3442 waitTimeLeftMs -= waitTimeMs;
3443 } else {
3444 waitTimeLeftMs = 0;
3445 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003446 }
Eric Laurenta553c252009-07-17 12:17:14 -07003447
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003448 uint32_t outFrames = pInBuffer->frameCount > mOutBuffer.frameCount ? mOutBuffer.frameCount : pInBuffer->frameCount;
Eric Laurentb0a01472010-05-14 05:45:46 -07003449 memcpy(mOutBuffer.raw, pInBuffer->raw, outFrames * channelCount * sizeof(int16_t));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003450 mCblk->stepUser(outFrames);
3451 pInBuffer->frameCount -= outFrames;
Eric Laurentb0a01472010-05-14 05:45:46 -07003452 pInBuffer->i16 += outFrames * channelCount;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003453 mOutBuffer.frameCount -= outFrames;
Eric Laurentb0a01472010-05-14 05:45:46 -07003454 mOutBuffer.i16 += outFrames * channelCount;
Eric Laurenta553c252009-07-17 12:17:14 -07003455
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003456 if (pInBuffer->frameCount == 0) {
3457 if (mBufferQueue.size()) {
3458 mBufferQueue.removeAt(0);
3459 delete [] pInBuffer->mBuffer;
3460 delete pInBuffer;
Eric Laurent8ac9f8d2009-12-18 05:47:48 -08003461 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 -08003462 } else {
3463 break;
3464 }
3465 }
3466 }
Eric Laurenta553c252009-07-17 12:17:14 -07003467
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003468 // If we could not write all frames, allocate a buffer and queue it for next time.
3469 if (inBuffer.frameCount) {
Eric Laurent8ac9f8d2009-12-18 05:47:48 -08003470 sp<ThreadBase> thread = mThread.promote();
3471 if (thread != 0 && !thread->standby()) {
3472 if (mBufferQueue.size() < kMaxOverFlowBuffers) {
3473 pInBuffer = new Buffer;
Eric Laurentb0a01472010-05-14 05:45:46 -07003474 pInBuffer->mBuffer = new int16_t[inBuffer.frameCount * channelCount];
Eric Laurent8ac9f8d2009-12-18 05:47:48 -08003475 pInBuffer->frameCount = inBuffer.frameCount;
3476 pInBuffer->i16 = pInBuffer->mBuffer;
Eric Laurentb0a01472010-05-14 05:45:46 -07003477 memcpy(pInBuffer->raw, inBuffer.raw, inBuffer.frameCount * channelCount * sizeof(int16_t));
Eric Laurent8ac9f8d2009-12-18 05:47:48 -08003478 mBufferQueue.add(pInBuffer);
3479 LOGV("OutputTrack::write() %p thread %p adding overflow buffer %d", this, mThread.unsafe_get(), mBufferQueue.size());
3480 } else {
3481 LOGW("OutputTrack::write() %p thread %p no more overflow buffers", mThread.unsafe_get(), this);
3482 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003483 }
3484 }
Eric Laurenta553c252009-07-17 12:17:14 -07003485
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003486 // Calling write() with a 0 length buffer, means that no more data will be written:
Eric Laurenta553c252009-07-17 12:17:14 -07003487 // 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 -08003488 // by output mixer.
Eric Laurenta553c252009-07-17 12:17:14 -07003489 if (frames == 0 && mBufferQueue.size() == 0) {
3490 if (mCblk->user < mCblk->frameCount) {
3491 frames = mCblk->frameCount - mCblk->user;
3492 pInBuffer = new Buffer;
Eric Laurentb0a01472010-05-14 05:45:46 -07003493 pInBuffer->mBuffer = new int16_t[frames * channelCount];
Eric Laurenta553c252009-07-17 12:17:14 -07003494 pInBuffer->frameCount = frames;
3495 pInBuffer->i16 = pInBuffer->mBuffer;
Eric Laurentb0a01472010-05-14 05:45:46 -07003496 memset(pInBuffer->raw, 0, frames * channelCount * sizeof(int16_t));
Eric Laurenta553c252009-07-17 12:17:14 -07003497 mBufferQueue.add(pInBuffer);
Eric Laurent62443f52009-10-05 20:29:18 -07003498 } else if (mActive) {
Eric Laurenta553c252009-07-17 12:17:14 -07003499 stop();
3500 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003501 }
3502
Eric Laurenta553c252009-07-17 12:17:14 -07003503 return outputBufferFull;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003504}
3505
Eric Laurenta553c252009-07-17 12:17:14 -07003506status_t AudioFlinger::PlaybackThread::OutputTrack::obtainBuffer(AudioBufferProvider::Buffer* buffer, uint32_t waitTimeMs)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003507{
3508 int active;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003509 status_t result;
3510 audio_track_cblk_t* cblk = mCblk;
3511 uint32_t framesReq = buffer->frameCount;
3512
Eric Laurenta553c252009-07-17 12:17:14 -07003513// LOGV("OutputTrack::obtainBuffer user %d, server %d", cblk->user, cblk->server);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003514 buffer->frameCount = 0;
Eric Laurenta553c252009-07-17 12:17:14 -07003515
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003516 uint32_t framesAvail = cblk->framesAvailable();
3517
Eric Laurenta553c252009-07-17 12:17:14 -07003518
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003519 if (framesAvail == 0) {
Eric Laurenta553c252009-07-17 12:17:14 -07003520 Mutex::Autolock _l(cblk->lock);
3521 goto start_loop_here;
3522 while (framesAvail == 0) {
3523 active = mActive;
3524 if (UNLIKELY(!active)) {
3525 LOGV("Not active and NO_MORE_BUFFERS");
3526 return AudioTrack::NO_MORE_BUFFERS;
3527 }
3528 result = cblk->cv.waitRelative(cblk->lock, milliseconds(waitTimeMs));
3529 if (result != NO_ERROR) {
3530 return AudioTrack::NO_MORE_BUFFERS;
3531 }
3532 // read the server count again
3533 start_loop_here:
3534 framesAvail = cblk->framesAvailable_l();
3535 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003536 }
3537
Eric Laurenta553c252009-07-17 12:17:14 -07003538// if (framesAvail < framesReq) {
3539// return AudioTrack::NO_MORE_BUFFERS;
3540// }
3541
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003542 if (framesReq > framesAvail) {
3543 framesReq = framesAvail;
3544 }
3545
3546 uint32_t u = cblk->user;
3547 uint32_t bufferEnd = cblk->userBase + cblk->frameCount;
3548
3549 if (u + framesReq > bufferEnd) {
3550 framesReq = bufferEnd - u;
3551 }
3552
3553 buffer->frameCount = framesReq;
3554 buffer->raw = (void *)cblk->buffer(u);
3555 return NO_ERROR;
3556}
3557
3558
Eric Laurenta553c252009-07-17 12:17:14 -07003559void AudioFlinger::PlaybackThread::OutputTrack::clearBufferQueue()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003560{
3561 size_t size = mBufferQueue.size();
3562 Buffer *pBuffer;
Eric Laurenta553c252009-07-17 12:17:14 -07003563
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003564 for (size_t i = 0; i < size; i++) {
3565 pBuffer = mBufferQueue.itemAt(i);
3566 delete [] pBuffer->mBuffer;
3567 delete pBuffer;
3568 }
3569 mBufferQueue.clear();
3570}
3571
3572// ----------------------------------------------------------------------------
3573
3574AudioFlinger::Client::Client(const sp<AudioFlinger>& audioFlinger, pid_t pid)
3575 : RefBase(),
3576 mAudioFlinger(audioFlinger),
Mathias Agopian6faf7892010-01-25 19:00:00 -08003577 mMemoryDealer(new MemoryDealer(1024*1024, "AudioFlinger::Client")),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003578 mPid(pid)
3579{
3580 // 1 MB of address space is good for 32 tracks, 8 buffers each, 4 KB/buffer
3581}
3582
Eric Laurentb9481d82009-09-17 05:12:56 -07003583// Client destructor must be called with AudioFlinger::mLock held
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003584AudioFlinger::Client::~Client()
3585{
Eric Laurentb9481d82009-09-17 05:12:56 -07003586 mAudioFlinger->removeClient_l(mPid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003587}
3588
3589const sp<MemoryDealer>& AudioFlinger::Client::heap() const
3590{
3591 return mMemoryDealer;
3592}
3593
3594// ----------------------------------------------------------------------------
3595
Eric Laurent4f0f17d2010-05-12 02:05:53 -07003596AudioFlinger::NotificationClient::NotificationClient(const sp<AudioFlinger>& audioFlinger,
3597 const sp<IAudioFlingerClient>& client,
3598 pid_t pid)
3599 : mAudioFlinger(audioFlinger), mPid(pid), mClient(client)
3600{
3601}
3602
3603AudioFlinger::NotificationClient::~NotificationClient()
3604{
3605 mClient.clear();
3606}
3607
3608void AudioFlinger::NotificationClient::binderDied(const wp<IBinder>& who)
3609{
3610 sp<NotificationClient> keep(this);
3611 {
3612 mAudioFlinger->removeNotificationClient(mPid);
3613 }
3614}
3615
3616// ----------------------------------------------------------------------------
3617
Eric Laurenta553c252009-07-17 12:17:14 -07003618AudioFlinger::TrackHandle::TrackHandle(const sp<AudioFlinger::PlaybackThread::Track>& track)
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003619 : BnAudioTrack(),
3620 mTrack(track)
3621{
3622}
3623
3624AudioFlinger::TrackHandle::~TrackHandle() {
3625 // just stop the track on deletion, associated resources
3626 // will be freed from the main thread once all pending buffers have
3627 // been played. Unless it's not in the active track list, in which
3628 // case we free everything now...
3629 mTrack->destroy();
3630}
3631
3632status_t AudioFlinger::TrackHandle::start() {
3633 return mTrack->start();
3634}
3635
3636void AudioFlinger::TrackHandle::stop() {
3637 mTrack->stop();
3638}
3639
3640void AudioFlinger::TrackHandle::flush() {
3641 mTrack->flush();
3642}
3643
3644void AudioFlinger::TrackHandle::mute(bool e) {
3645 mTrack->mute(e);
3646}
3647
3648void AudioFlinger::TrackHandle::pause() {
3649 mTrack->pause();
3650}
3651
3652void AudioFlinger::TrackHandle::setVolume(float left, float right) {
3653 mTrack->setVolume(left, right);
3654}
3655
3656sp<IMemory> AudioFlinger::TrackHandle::getCblk() const {
3657 return mTrack->getCblk();
3658}
3659
Eric Laurent65b65452010-06-01 23:49:17 -07003660status_t AudioFlinger::TrackHandle::attachAuxEffect(int EffectId)
3661{
3662 return mTrack->attachAuxEffect(EffectId);
3663}
3664
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003665status_t AudioFlinger::TrackHandle::onTransact(
3666 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
3667{
3668 return BnAudioTrack::onTransact(code, data, reply, flags);
3669}
3670
3671// ----------------------------------------------------------------------------
3672
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003673sp<IAudioRecord> AudioFlinger::openRecord(
3674 pid_t pid,
Eric Laurentddb78e72009-07-28 08:44:33 -07003675 int input,
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003676 uint32_t sampleRate,
Jean-Michel Trivi54392232011-05-24 15:53:33 -07003677 uint32_t format,
3678 uint32_t channelMask,
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08003679 int frameCount,
3680 uint32_t flags,
Eric Laurent65b65452010-06-01 23:49:17 -07003681 int *sessionId,
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08003682 status_t *status)
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003683{
Eric Laurenta553c252009-07-17 12:17:14 -07003684 sp<RecordThread::RecordTrack> recordTrack;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003685 sp<RecordHandle> recordHandle;
3686 sp<Client> client;
3687 wp<Client> wclient;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08003688 status_t lStatus;
Eric Laurenta553c252009-07-17 12:17:14 -07003689 RecordThread *thread;
3690 size_t inFrameCount;
Eric Laurent65b65452010-06-01 23:49:17 -07003691 int lSessionId;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003692
3693 // check calling permissions
3694 if (!recordingAllowed()) {
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08003695 lStatus = PERMISSION_DENIED;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003696 goto Exit;
3697 }
3698
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003699 // add client to list
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07003700 { // scope for mLock
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003701 Mutex::Autolock _l(mLock);
Eric Laurenta553c252009-07-17 12:17:14 -07003702 thread = checkRecordThread_l(input);
3703 if (thread == NULL) {
3704 lStatus = BAD_VALUE;
3705 goto Exit;
3706 }
3707
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003708 wclient = mClients.valueFor(pid);
3709 if (wclient != NULL) {
3710 client = wclient.promote();
3711 } else {
3712 client = new Client(this, pid);
3713 mClients.add(pid, client);
3714 }
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07003715
Eric Laurent65b65452010-06-01 23:49:17 -07003716 // If no audio session id is provided, create one here
Dima Zavin24fc2fb2011-04-19 22:30:36 -07003717 if (sessionId != NULL && *sessionId != AUDIO_SESSION_OUTPUT_MIX) {
Eric Laurent65b65452010-06-01 23:49:17 -07003718 lSessionId = *sessionId;
3719 } else {
Eric Laurentf3d6dd02010-11-18 08:40:16 -08003720 lSessionId = nextUniqueId_l();
Eric Laurent65b65452010-06-01 23:49:17 -07003721 if (sessionId != NULL) {
3722 *sessionId = lSessionId;
3723 }
3724 }
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07003725 // create new record track. The record track uses one track in mHardwareMixerThread by convention.
Eric Laurenta553c252009-07-17 12:17:14 -07003726 recordTrack = new RecordThread::RecordTrack(thread, client, sampleRate,
Jean-Michel Trivi54392232011-05-24 15:53:33 -07003727 format, channelMask, frameCount, flags, lSessionId);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003728 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003729 if (recordTrack->getCblk() == NULL) {
Eric Laurentb9481d82009-09-17 05:12:56 -07003730 // remove local strong reference to Client before deleting the RecordTrack so that the Client
3731 // destructor is called by the TrackBase destructor with mLock held
3732 client.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003733 recordTrack.clear();
3734 lStatus = NO_MEMORY;
3735 goto Exit;
3736 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003737
3738 // return to handle to client
3739 recordHandle = new RecordHandle(recordTrack);
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08003740 lStatus = NO_ERROR;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003741
3742Exit:
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08003743 if (status) {
3744 *status = lStatus;
3745 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003746 return recordHandle;
3747}
3748
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003749// ----------------------------------------------------------------------------
3750
Eric Laurenta553c252009-07-17 12:17:14 -07003751AudioFlinger::RecordHandle::RecordHandle(const sp<AudioFlinger::RecordThread::RecordTrack>& recordTrack)
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003752 : BnAudioRecord(),
3753 mRecordTrack(recordTrack)
3754{
3755}
3756
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08003757AudioFlinger::RecordHandle::~RecordHandle() {
3758 stop();
3759}
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003760
3761status_t AudioFlinger::RecordHandle::start() {
3762 LOGV("RecordHandle::start()");
3763 return mRecordTrack->start();
3764}
3765
3766void AudioFlinger::RecordHandle::stop() {
3767 LOGV("RecordHandle::stop()");
3768 mRecordTrack->stop();
3769}
3770
3771sp<IMemory> AudioFlinger::RecordHandle::getCblk() const {
3772 return mRecordTrack->getCblk();
3773}
3774
3775status_t AudioFlinger::RecordHandle::onTransact(
3776 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
3777{
3778 return BnAudioRecord::onTransact(code, data, reply, flags);
3779}
3780
3781// ----------------------------------------------------------------------------
3782
Dima Zavin31f188892011-04-18 16:57:27 -07003783AudioFlinger::RecordThread::RecordThread(const sp<AudioFlinger>& audioFlinger, AudioStreamIn *input, uint32_t sampleRate, uint32_t channels, int id) :
Eric Laurent49f02be2009-11-19 09:00:56 -08003784 ThreadBase(audioFlinger, id),
Eric Laurenta553c252009-07-17 12:17:14 -07003785 mInput(input), mResampler(0), mRsmpOutBuffer(0), mRsmpInBuffer(0)
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003786{
Dima Zavin24fc2fb2011-04-19 22:30:36 -07003787 mReqChannelCount = popcount(channels);
Eric Laurenta553c252009-07-17 12:17:14 -07003788 mReqSampleRate = sampleRate;
3789 readInputParameters();
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003790}
3791
Eric Laurenta553c252009-07-17 12:17:14 -07003792
3793AudioFlinger::RecordThread::~RecordThread()
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003794{
Eric Laurenta553c252009-07-17 12:17:14 -07003795 delete[] mRsmpInBuffer;
3796 if (mResampler != 0) {
3797 delete mResampler;
3798 delete[] mRsmpOutBuffer;
3799 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003800}
3801
Eric Laurenta553c252009-07-17 12:17:14 -07003802void AudioFlinger::RecordThread::onFirstRef()
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003803{
Eric Laurenta553c252009-07-17 12:17:14 -07003804 const size_t SIZE = 256;
3805 char buffer[SIZE];
3806
3807 snprintf(buffer, SIZE, "Record Thread %p", this);
3808
3809 run(buffer, PRIORITY_URGENT_AUDIO);
3810}
Eric Laurent49f02be2009-11-19 09:00:56 -08003811
Eric Laurenta553c252009-07-17 12:17:14 -07003812bool AudioFlinger::RecordThread::threadLoop()
3813{
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08003814 AudioBufferProvider::Buffer buffer;
Eric Laurenta553c252009-07-17 12:17:14 -07003815 sp<RecordTrack> activeTrack;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003816
Eric Laurent4712baa2010-09-30 16:12:31 -07003817 nsecs_t lastWarning = 0;
3818
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003819 // start recording
3820 while (!exitPending()) {
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08003821
Eric Laurenta553c252009-07-17 12:17:14 -07003822 processConfigEvents();
3823
3824 { // scope for mLock
3825 Mutex::Autolock _l(mLock);
3826 checkForNewParameters_l();
3827 if (mActiveTrack == 0 && mConfigEvents.isEmpty()) {
3828 if (!mStandby) {
Dima Zavin31f188892011-04-18 16:57:27 -07003829 mInput->stream->common.standby(&mInput->stream->common);
Eric Laurenta553c252009-07-17 12:17:14 -07003830 mStandby = true;
3831 }
3832
3833 if (exitPending()) break;
3834
3835 LOGV("RecordThread: loop stopping");
3836 // go to sleep
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003837 mWaitWorkCV.wait(mLock);
Eric Laurenta553c252009-07-17 12:17:14 -07003838 LOGV("RecordThread: loop starting");
3839 continue;
3840 }
3841 if (mActiveTrack != 0) {
3842 if (mActiveTrack->mState == TrackBase::PAUSING) {
Eric Laurent9cc489a2009-12-05 05:20:01 -08003843 if (!mStandby) {
Dima Zavin31f188892011-04-18 16:57:27 -07003844 mInput->stream->common.standby(&mInput->stream->common);
Eric Laurent9cc489a2009-12-05 05:20:01 -08003845 mStandby = true;
3846 }
Eric Laurenta553c252009-07-17 12:17:14 -07003847 mActiveTrack.clear();
3848 mStartStopCond.broadcast();
3849 } else if (mActiveTrack->mState == TrackBase::RESUMING) {
Eric Laurenta553c252009-07-17 12:17:14 -07003850 if (mReqChannelCount != mActiveTrack->channelCount()) {
3851 mActiveTrack.clear();
Eric Laurent9cc489a2009-12-05 05:20:01 -08003852 mStartStopCond.broadcast();
3853 } else if (mBytesRead != 0) {
3854 // record start succeeds only if first read from audio input
3855 // succeeds
3856 if (mBytesRead > 0) {
3857 mActiveTrack->mState = TrackBase::ACTIVE;
3858 } else {
3859 mActiveTrack.clear();
3860 }
3861 mStartStopCond.broadcast();
Eric Laurenta553c252009-07-17 12:17:14 -07003862 }
Eric Laurent9cc489a2009-12-05 05:20:01 -08003863 mStandby = false;
Eric Laurenta553c252009-07-17 12:17:14 -07003864 }
Eric Laurenta553c252009-07-17 12:17:14 -07003865 }
3866 }
3867
3868 if (mActiveTrack != 0) {
Eric Laurent9cc489a2009-12-05 05:20:01 -08003869 if (mActiveTrack->mState != TrackBase::ACTIVE &&
3870 mActiveTrack->mState != TrackBase::RESUMING) {
Eric Laurent49f02be2009-11-19 09:00:56 -08003871 usleep(5000);
3872 continue;
3873 }
Eric Laurenta553c252009-07-17 12:17:14 -07003874 buffer.frameCount = mFrameCount;
3875 if (LIKELY(mActiveTrack->getNextBuffer(&buffer) == NO_ERROR)) {
3876 size_t framesOut = buffer.frameCount;
3877 if (mResampler == 0) {
3878 // no resampling
3879 while (framesOut) {
3880 size_t framesIn = mFrameCount - mRsmpInIndex;
3881 if (framesIn) {
3882 int8_t *src = (int8_t *)mRsmpInBuffer + mRsmpInIndex * mFrameSize;
3883 int8_t *dst = buffer.i8 + (buffer.frameCount - framesOut) * mActiveTrack->mCblk->frameSize;
3884 if (framesIn > framesOut)
3885 framesIn = framesOut;
3886 mRsmpInIndex += framesIn;
3887 framesOut -= framesIn;
Eric Laurentb0a01472010-05-14 05:45:46 -07003888 if ((int)mChannelCount == mReqChannelCount ||
Dima Zavin24fc2fb2011-04-19 22:30:36 -07003889 mFormat != AUDIO_FORMAT_PCM_16_BIT) {
Eric Laurenta553c252009-07-17 12:17:14 -07003890 memcpy(dst, src, framesIn * mFrameSize);
3891 } else {
3892 int16_t *src16 = (int16_t *)src;
3893 int16_t *dst16 = (int16_t *)dst;
3894 if (mChannelCount == 1) {
3895 while (framesIn--) {
3896 *dst16++ = *src16;
3897 *dst16++ = *src16++;
3898 }
3899 } else {
3900 while (framesIn--) {
3901 *dst16++ = (int16_t)(((int32_t)*src16 + (int32_t)*(src16 + 1)) >> 1);
3902 src16 += 2;
3903 }
3904 }
3905 }
3906 }
3907 if (framesOut && mFrameCount == mRsmpInIndex) {
Eric Laurenta553c252009-07-17 12:17:14 -07003908 if (framesOut == mFrameCount &&
Dima Zavin24fc2fb2011-04-19 22:30:36 -07003909 ((int)mChannelCount == mReqChannelCount || mFormat != AUDIO_FORMAT_PCM_16_BIT)) {
Dima Zavin31f188892011-04-18 16:57:27 -07003910 mBytesRead = mInput->stream->read(mInput->stream, buffer.raw, mInputBytes);
Eric Laurenta553c252009-07-17 12:17:14 -07003911 framesOut = 0;
3912 } else {
Dima Zavin31f188892011-04-18 16:57:27 -07003913 mBytesRead = mInput->stream->read(mInput->stream, mRsmpInBuffer, mInputBytes);
Eric Laurenta553c252009-07-17 12:17:14 -07003914 mRsmpInIndex = 0;
3915 }
Eric Laurent9cc489a2009-12-05 05:20:01 -08003916 if (mBytesRead < 0) {
Eric Laurenta553c252009-07-17 12:17:14 -07003917 LOGE("Error reading audio input");
Eric Laurent9cc489a2009-12-05 05:20:01 -08003918 if (mActiveTrack->mState == TrackBase::ACTIVE) {
Eric Laurentba8811f2010-03-02 18:38:06 -08003919 // Force input into standby so that it tries to
3920 // recover at next read attempt
Dima Zavin31f188892011-04-18 16:57:27 -07003921 mInput->stream->common.standby(&mInput->stream->common);
Eric Laurentba8811f2010-03-02 18:38:06 -08003922 usleep(5000);
Eric Laurent9cc489a2009-12-05 05:20:01 -08003923 }
Eric Laurenta553c252009-07-17 12:17:14 -07003924 mRsmpInIndex = mFrameCount;
3925 framesOut = 0;
3926 buffer.frameCount = 0;
3927 }
3928 }
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08003929 }
3930 } else {
Eric Laurenta553c252009-07-17 12:17:14 -07003931 // resampling
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003932
Eric Laurenta553c252009-07-17 12:17:14 -07003933 memset(mRsmpOutBuffer, 0, framesOut * 2 * sizeof(int32_t));
3934 // alter output frame count as if we were expecting stereo samples
3935 if (mChannelCount == 1 && mReqChannelCount == 1) {
3936 framesOut >>= 1;
3937 }
3938 mResampler->resample(mRsmpOutBuffer, framesOut, this);
3939 // ditherAndClamp() works as long as all buffers returned by mActiveTrack->getNextBuffer()
3940 // are 32 bit aligned which should be always true.
3941 if (mChannelCount == 2 && mReqChannelCount == 1) {
3942 AudioMixer::ditherAndClamp(mRsmpOutBuffer, mRsmpOutBuffer, framesOut);
3943 // the resampler always outputs stereo samples: do post stereo to mono conversion
3944 int16_t *src = (int16_t *)mRsmpOutBuffer;
3945 int16_t *dst = buffer.i16;
3946 while (framesOut--) {
3947 *dst++ = (int16_t)(((int32_t)*src + (int32_t)*(src + 1)) >> 1);
3948 src += 2;
3949 }
3950 } else {
3951 AudioMixer::ditherAndClamp((int32_t *)buffer.raw, mRsmpOutBuffer, framesOut);
3952 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003953
Eric Laurenta553c252009-07-17 12:17:14 -07003954 }
3955 mActiveTrack->releaseBuffer(&buffer);
3956 mActiveTrack->overflow();
3957 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003958 // client isn't retrieving buffers fast enough
3959 else {
Eric Laurent4712baa2010-09-30 16:12:31 -07003960 if (!mActiveTrack->setOverflow()) {
3961 nsecs_t now = systemTime();
3962 if ((now - lastWarning) > kWarningThrottle) {
3963 LOGW("RecordThread: buffer overflow");
3964 lastWarning = now;
3965 }
3966 }
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08003967 // Release the processor for a while before asking for a new buffer.
3968 // This will give the application more chance to read from the buffer and
3969 // clear the overflow.
3970 usleep(5000);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003971 }
3972 }
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08003973 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003974
Eric Laurenta553c252009-07-17 12:17:14 -07003975 if (!mStandby) {
Dima Zavin31f188892011-04-18 16:57:27 -07003976 mInput->stream->common.standby(&mInput->stream->common);
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08003977 }
Eric Laurenta553c252009-07-17 12:17:14 -07003978 mActiveTrack.clear();
3979
Eric Laurent49f02be2009-11-19 09:00:56 -08003980 mStartStopCond.broadcast();
3981
Eric Laurenta553c252009-07-17 12:17:14 -07003982 LOGV("RecordThread %p exiting", this);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003983 return false;
3984}
3985
Eric Laurenta553c252009-07-17 12:17:14 -07003986status_t AudioFlinger::RecordThread::start(RecordThread::RecordTrack* recordTrack)
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003987{
Eric Laurenta553c252009-07-17 12:17:14 -07003988 LOGV("RecordThread::start");
Eric Laurent49f02be2009-11-19 09:00:56 -08003989 sp <ThreadBase> strongMe = this;
3990 status_t status = NO_ERROR;
3991 {
3992 AutoMutex lock(&mLock);
3993 if (mActiveTrack != 0) {
3994 if (recordTrack != mActiveTrack.get()) {
3995 status = -EBUSY;
3996 } else if (mActiveTrack->mState == TrackBase::PAUSING) {
Eric Laurent9cc489a2009-12-05 05:20:01 -08003997 mActiveTrack->mState = TrackBase::ACTIVE;
Eric Laurent49f02be2009-11-19 09:00:56 -08003998 }
3999 return status;
4000 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07004001
Eric Laurent49f02be2009-11-19 09:00:56 -08004002 recordTrack->mState = TrackBase::IDLE;
4003 mActiveTrack = recordTrack;
4004 mLock.unlock();
4005 status_t status = AudioSystem::startInput(mId);
4006 mLock.lock();
4007 if (status != NO_ERROR) {
4008 mActiveTrack.clear();
4009 return status;
4010 }
Eric Laurent9cc489a2009-12-05 05:20:01 -08004011 mRsmpInIndex = mFrameCount;
4012 mBytesRead = 0;
Eric Laurent4bb21c42011-02-28 16:52:51 -08004013 if (mResampler != NULL) {
4014 mResampler->reset();
4015 }
4016 mActiveTrack->mState = TrackBase::RESUMING;
Eric Laurent49f02be2009-11-19 09:00:56 -08004017 // signal thread to start
4018 LOGV("Signal record thread");
4019 mWaitWorkCV.signal();
4020 // do not wait for mStartStopCond if exiting
4021 if (mExiting) {
4022 mActiveTrack.clear();
4023 status = INVALID_OPERATION;
4024 goto startError;
4025 }
4026 mStartStopCond.wait(mLock);
4027 if (mActiveTrack == 0) {
4028 LOGV("Record failed to start");
4029 status = BAD_VALUE;
4030 goto startError;
4031 }
Eric Laurenta553c252009-07-17 12:17:14 -07004032 LOGV("Record started OK");
Eric Laurent49f02be2009-11-19 09:00:56 -08004033 return status;
Eric Laurenta553c252009-07-17 12:17:14 -07004034 }
Eric Laurent49f02be2009-11-19 09:00:56 -08004035startError:
4036 AudioSystem::stopInput(mId);
4037 return status;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07004038}
4039
Eric Laurenta553c252009-07-17 12:17:14 -07004040void AudioFlinger::RecordThread::stop(RecordThread::RecordTrack* recordTrack) {
4041 LOGV("RecordThread::stop");
Eric Laurent49f02be2009-11-19 09:00:56 -08004042 sp <ThreadBase> strongMe = this;
4043 {
4044 AutoMutex lock(&mLock);
4045 if (mActiveTrack != 0 && recordTrack == mActiveTrack.get()) {
4046 mActiveTrack->mState = TrackBase::PAUSING;
4047 // do not wait for mStartStopCond if exiting
4048 if (mExiting) {
4049 return;
4050 }
4051 mStartStopCond.wait(mLock);
4052 // if we have been restarted, recordTrack == mActiveTrack.get() here
4053 if (mActiveTrack == 0 || recordTrack != mActiveTrack.get()) {
4054 mLock.unlock();
4055 AudioSystem::stopInput(mId);
4056 mLock.lock();
Eric Laurent9cc489a2009-12-05 05:20:01 -08004057 LOGV("Record stopped OK");
Eric Laurent49f02be2009-11-19 09:00:56 -08004058 }
4059 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07004060 }
4061}
4062
Eric Laurenta553c252009-07-17 12:17:14 -07004063status_t AudioFlinger::RecordThread::dump(int fd, const Vector<String16>& args)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004064{
4065 const size_t SIZE = 256;
4066 char buffer[SIZE];
4067 String8 result;
4068 pid_t pid = 0;
4069
Eric Laurent3fdb1262009-11-07 00:01:32 -08004070 snprintf(buffer, SIZE, "\nInput thread %p internals\n", this);
4071 result.append(buffer);
4072
4073 if (mActiveTrack != 0) {
4074 result.append("Active Track:\n");
Jean-Michel Trivi54392232011-05-24 15:53:33 -07004075 result.append(" Clien Fmt Chn mask Session Buf S SRate Serv User\n");
Eric Laurent3fdb1262009-11-07 00:01:32 -08004076 mActiveTrack->dump(buffer, SIZE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004077 result.append(buffer);
Eric Laurent3fdb1262009-11-07 00:01:32 -08004078
4079 snprintf(buffer, SIZE, "In index: %d\n", mRsmpInIndex);
4080 result.append(buffer);
4081 snprintf(buffer, SIZE, "In size: %d\n", mInputBytes);
4082 result.append(buffer);
4083 snprintf(buffer, SIZE, "Resampling: %d\n", (mResampler != 0));
4084 result.append(buffer);
4085 snprintf(buffer, SIZE, "Out channel count: %d\n", mReqChannelCount);
4086 result.append(buffer);
4087 snprintf(buffer, SIZE, "Out sample rate: %d\n", mReqSampleRate);
4088 result.append(buffer);
4089
4090
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004091 } else {
4092 result.append("No record client\n");
4093 }
4094 write(fd, result.string(), result.size());
Eric Laurent3fdb1262009-11-07 00:01:32 -08004095
4096 dumpBase(fd, args);
4097
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004098 return NO_ERROR;
4099}
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07004100
Eric Laurenta553c252009-07-17 12:17:14 -07004101status_t AudioFlinger::RecordThread::getNextBuffer(AudioBufferProvider::Buffer* buffer)
4102{
4103 size_t framesReq = buffer->frameCount;
4104 size_t framesReady = mFrameCount - mRsmpInIndex;
4105 int channelCount;
4106
4107 if (framesReady == 0) {
Dima Zavin31f188892011-04-18 16:57:27 -07004108 mBytesRead = mInput->stream->read(mInput->stream, mRsmpInBuffer, mInputBytes);
Eric Laurent9cc489a2009-12-05 05:20:01 -08004109 if (mBytesRead < 0) {
Eric Laurenta553c252009-07-17 12:17:14 -07004110 LOGE("RecordThread::getNextBuffer() Error reading audio input");
Eric Laurent9cc489a2009-12-05 05:20:01 -08004111 if (mActiveTrack->mState == TrackBase::ACTIVE) {
Eric Laurentba8811f2010-03-02 18:38:06 -08004112 // Force input into standby so that it tries to
4113 // recover at next read attempt
Dima Zavin31f188892011-04-18 16:57:27 -07004114 mInput->stream->common.standby(&mInput->stream->common);
Eric Laurentba8811f2010-03-02 18:38:06 -08004115 usleep(5000);
Eric Laurent9cc489a2009-12-05 05:20:01 -08004116 }
Eric Laurenta553c252009-07-17 12:17:14 -07004117 buffer->raw = 0;
4118 buffer->frameCount = 0;
4119 return NOT_ENOUGH_DATA;
4120 }
4121 mRsmpInIndex = 0;
4122 framesReady = mFrameCount;
4123 }
4124
4125 if (framesReq > framesReady) {
4126 framesReq = framesReady;
4127 }
4128
4129 if (mChannelCount == 1 && mReqChannelCount == 2) {
4130 channelCount = 1;
4131 } else {
4132 channelCount = 2;
4133 }
4134 buffer->raw = mRsmpInBuffer + mRsmpInIndex * channelCount;
4135 buffer->frameCount = framesReq;
4136 return NO_ERROR;
4137}
4138
4139void AudioFlinger::RecordThread::releaseBuffer(AudioBufferProvider::Buffer* buffer)
4140{
4141 mRsmpInIndex += buffer->frameCount;
4142 buffer->frameCount = 0;
4143}
4144
4145bool AudioFlinger::RecordThread::checkForNewParameters_l()
4146{
4147 bool reconfig = false;
4148
Eric Laurent8fce46a2009-08-04 09:45:33 -07004149 while (!mNewParameters.isEmpty()) {
Eric Laurenta553c252009-07-17 12:17:14 -07004150 status_t status = NO_ERROR;
Eric Laurent8fce46a2009-08-04 09:45:33 -07004151 String8 keyValuePair = mNewParameters[0];
4152 AudioParameter param = AudioParameter(keyValuePair);
Eric Laurenta553c252009-07-17 12:17:14 -07004153 int value;
4154 int reqFormat = mFormat;
4155 int reqSamplingRate = mReqSampleRate;
4156 int reqChannelCount = mReqChannelCount;
Eric Laurent8fce46a2009-08-04 09:45:33 -07004157
Eric Laurenta553c252009-07-17 12:17:14 -07004158 if (param.getInt(String8(AudioParameter::keySamplingRate), value) == NO_ERROR) {
4159 reqSamplingRate = value;
4160 reconfig = true;
4161 }
4162 if (param.getInt(String8(AudioParameter::keyFormat), value) == NO_ERROR) {
4163 reqFormat = value;
4164 reconfig = true;
4165 }
4166 if (param.getInt(String8(AudioParameter::keyChannels), value) == NO_ERROR) {
Dima Zavin24fc2fb2011-04-19 22:30:36 -07004167 reqChannelCount = popcount(value);
Eric Laurenta553c252009-07-17 12:17:14 -07004168 reconfig = true;
4169 }
4170 if (param.getInt(String8(AudioParameter::keyFrameCount), value) == NO_ERROR) {
4171 // do not accept frame count changes if tracks are open as the track buffer
4172 // size depends on frame count and correct behavior would not be garantied
4173 // if frame count is changed after track creation
4174 if (mActiveTrack != 0) {
4175 status = INVALID_OPERATION;
4176 } else {
4177 reconfig = true;
4178 }
4179 }
4180 if (status == NO_ERROR) {
Dima Zavin31f188892011-04-18 16:57:27 -07004181 status = mInput->stream->common.set_parameters(&mInput->stream->common, keyValuePair.string());
Eric Laurenta553c252009-07-17 12:17:14 -07004182 if (status == INVALID_OPERATION) {
Dima Zavin31f188892011-04-18 16:57:27 -07004183 mInput->stream->common.standby(&mInput->stream->common);
4184 status = mInput->stream->common.set_parameters(&mInput->stream->common, keyValuePair.string());
Eric Laurenta553c252009-07-17 12:17:14 -07004185 }
4186 if (reconfig) {
4187 if (status == BAD_VALUE &&
Dima Zavin31f188892011-04-18 16:57:27 -07004188 reqFormat == mInput->stream->common.get_format(&mInput->stream->common) &&
Dima Zavin24fc2fb2011-04-19 22:30:36 -07004189 reqFormat == AUDIO_FORMAT_PCM_16_BIT &&
Dima Zavin31f188892011-04-18 16:57:27 -07004190 ((int)mInput->stream->common.get_sample_rate(&mInput->stream->common) <= (2 * reqSamplingRate)) &&
4191 (popcount(mInput->stream->common.get_channels(&mInput->stream->common)) < 3) &&
Dima Zavin24fc2fb2011-04-19 22:30:36 -07004192 (reqChannelCount < 3)) {
Eric Laurenta553c252009-07-17 12:17:14 -07004193 status = NO_ERROR;
4194 }
4195 if (status == NO_ERROR) {
4196 readInputParameters();
Eric Laurent8fce46a2009-08-04 09:45:33 -07004197 sendConfigEvent_l(AudioSystem::INPUT_CONFIG_CHANGED);
Eric Laurenta553c252009-07-17 12:17:14 -07004198 }
4199 }
4200 }
Eric Laurent3fdb1262009-11-07 00:01:32 -08004201
4202 mNewParameters.removeAt(0);
4203
Eric Laurenta553c252009-07-17 12:17:14 -07004204 mParamStatus = status;
4205 mParamCond.signal();
Eric Laurent8fce46a2009-08-04 09:45:33 -07004206 mWaitWorkCV.wait(mLock);
Eric Laurenta553c252009-07-17 12:17:14 -07004207 }
4208 return reconfig;
4209}
4210
4211String8 AudioFlinger::RecordThread::getParameters(const String8& keys)
4212{
Dima Zavin24fc2fb2011-04-19 22:30:36 -07004213 char *s;
4214 String8 out_s8;
4215
Dima Zavin31f188892011-04-18 16:57:27 -07004216 s = mInput->stream->common.get_parameters(&mInput->stream->common, keys.string());
Dima Zavin24fc2fb2011-04-19 22:30:36 -07004217 out_s8 = String8(s);
4218 free(s);
4219 return out_s8;
Eric Laurenta553c252009-07-17 12:17:14 -07004220}
4221
Eric Laurenteb8f850d2010-05-14 03:26:45 -07004222void AudioFlinger::RecordThread::audioConfigChanged_l(int event, int param) {
Eric Laurenta553c252009-07-17 12:17:14 -07004223 AudioSystem::OutputDescriptor desc;
4224 void *param2 = 0;
4225
4226 switch (event) {
4227 case AudioSystem::INPUT_OPENED:
4228 case AudioSystem::INPUT_CONFIG_CHANGED:
Jean-Michel Trivi54392232011-05-24 15:53:33 -07004229 desc.channels = mChannelMask;
Eric Laurenta553c252009-07-17 12:17:14 -07004230 desc.samplingRate = mSampleRate;
4231 desc.format = mFormat;
4232 desc.frameCount = mFrameCount;
4233 desc.latency = 0;
4234 param2 = &desc;
4235 break;
4236
4237 case AudioSystem::INPUT_CLOSED:
4238 default:
4239 break;
4240 }
Eric Laurent49f02be2009-11-19 09:00:56 -08004241 mAudioFlinger->audioConfigChanged_l(event, mId, param2);
Eric Laurenta553c252009-07-17 12:17:14 -07004242}
4243
4244void AudioFlinger::RecordThread::readInputParameters()
4245{
4246 if (mRsmpInBuffer) delete mRsmpInBuffer;
4247 if (mRsmpOutBuffer) delete mRsmpOutBuffer;
4248 if (mResampler) delete mResampler;
4249 mResampler = 0;
4250
Dima Zavin31f188892011-04-18 16:57:27 -07004251 mSampleRate = mInput->stream->common.get_sample_rate(&mInput->stream->common);
Jean-Michel Trivi54392232011-05-24 15:53:33 -07004252 mChannelMask = mInput->stream->common.get_channels(&mInput->stream->common);
4253 mChannelCount = (uint16_t)popcount(mChannelMask);
Dima Zavin31f188892011-04-18 16:57:27 -07004254 mFormat = mInput->stream->common.get_format(&mInput->stream->common);
4255 mFrameSize = (uint16_t)audio_stream_frame_size(&mInput->stream->common);
4256 mInputBytes = mInput->stream->common.get_buffer_size(&mInput->stream->common);
Eric Laurenta553c252009-07-17 12:17:14 -07004257 mFrameCount = mInputBytes / mFrameSize;
4258 mRsmpInBuffer = new int16_t[mFrameCount * mChannelCount];
4259
4260 if (mSampleRate != mReqSampleRate && mChannelCount < 3 && mReqChannelCount < 3)
4261 {
4262 int channelCount;
4263 // optmization: if mono to mono, use the resampler in stereo to stereo mode to avoid
4264 // stereo to mono post process as the resampler always outputs stereo.
4265 if (mChannelCount == 1 && mReqChannelCount == 2) {
4266 channelCount = 1;
4267 } else {
4268 channelCount = 2;
4269 }
4270 mResampler = AudioResampler::create(16, channelCount, mReqSampleRate);
4271 mResampler->setSampleRate(mSampleRate);
4272 mResampler->setVolume(AudioMixer::UNITY_GAIN, AudioMixer::UNITY_GAIN);
4273 mRsmpOutBuffer = new int32_t[mFrameCount * 2];
4274
4275 // optmization: if mono to mono, alter input frame count as if we were inputing stereo samples
4276 if (mChannelCount == 1 && mReqChannelCount == 1) {
4277 mFrameCount >>= 1;
4278 }
4279
4280 }
4281 mRsmpInIndex = mFrameCount;
4282}
4283
Eric Laurent47d0a922010-02-26 02:47:27 -08004284unsigned int AudioFlinger::RecordThread::getInputFramesLost()
4285{
Dima Zavin31f188892011-04-18 16:57:27 -07004286 return mInput->stream->get_input_frames_lost(mInput->stream);
Eric Laurent47d0a922010-02-26 02:47:27 -08004287}
4288
Eric Laurenta553c252009-07-17 12:17:14 -07004289// ----------------------------------------------------------------------------
4290
Eric Laurentddb78e72009-07-28 08:44:33 -07004291int AudioFlinger::openOutput(uint32_t *pDevices,
Eric Laurenta553c252009-07-17 12:17:14 -07004292 uint32_t *pSamplingRate,
4293 uint32_t *pFormat,
4294 uint32_t *pChannels,
4295 uint32_t *pLatencyMs,
4296 uint32_t flags)
4297{
4298 status_t status;
4299 PlaybackThread *thread = NULL;
4300 mHardwareStatus = AUDIO_HW_OUTPUT_OPEN;
4301 uint32_t samplingRate = pSamplingRate ? *pSamplingRate : 0;
4302 uint32_t format = pFormat ? *pFormat : 0;
4303 uint32_t channels = pChannels ? *pChannels : 0;
4304 uint32_t latency = pLatencyMs ? *pLatencyMs : 0;
Dima Zavin31f188892011-04-18 16:57:27 -07004305 audio_stream_out_t *outStream;
4306 audio_hw_device_t *outHwDev;
Eric Laurenta553c252009-07-17 12:17:14 -07004307
4308 LOGV("openOutput(), Device %x, SamplingRate %d, Format %d, Channels %x, flags %x",
4309 pDevices ? *pDevices : 0,
4310 samplingRate,
4311 format,
4312 channels,
4313 flags);
4314
4315 if (pDevices == NULL || *pDevices == 0) {
Eric Laurentddb78e72009-07-28 08:44:33 -07004316 return 0;
Eric Laurenta553c252009-07-17 12:17:14 -07004317 }
Dima Zavin31f188892011-04-18 16:57:27 -07004318
Eric Laurenta553c252009-07-17 12:17:14 -07004319 Mutex::Autolock _l(mLock);
4320
Dima Zavin31f188892011-04-18 16:57:27 -07004321 outHwDev = findSuitableHwDev_l(*pDevices);
4322 if (outHwDev == NULL)
4323 return 0;
4324
4325 status = outHwDev->open_output_stream(outHwDev, *pDevices, (int *)&format,
4326 &channels, &samplingRate, &outStream);
Eric Laurenta553c252009-07-17 12:17:14 -07004327 LOGV("openOutput() openOutputStream returned output %p, SamplingRate %d, Format %d, Channels %x, status %d",
Dima Zavin31f188892011-04-18 16:57:27 -07004328 outStream,
Eric Laurenta553c252009-07-17 12:17:14 -07004329 samplingRate,
4330 format,
4331 channels,
4332 status);
4333
4334 mHardwareStatus = AUDIO_HW_IDLE;
Dima Zavin31f188892011-04-18 16:57:27 -07004335 if (outStream != NULL) {
4336 AudioStreamOut *output = new AudioStreamOut(outHwDev, outStream);
Eric Laurentf3d6dd02010-11-18 08:40:16 -08004337 int id = nextUniqueId_l();
Dima Zavin31f188892011-04-18 16:57:27 -07004338
Dima Zavin24fc2fb2011-04-19 22:30:36 -07004339 if ((flags & AUDIO_POLICY_OUTPUT_FLAG_DIRECT) ||
4340 (format != AUDIO_FORMAT_PCM_16_BIT) ||
4341 (channels != AUDIO_CHANNEL_OUT_STEREO)) {
Eric Laurent65b65452010-06-01 23:49:17 -07004342 thread = new DirectOutputThread(this, output, id, *pDevices);
4343 LOGV("openOutput() created direct output: ID %d thread %p", id, thread);
Eric Laurenta553c252009-07-17 12:17:14 -07004344 } else {
Eric Laurent65b65452010-06-01 23:49:17 -07004345 thread = new MixerThread(this, output, id, *pDevices);
4346 LOGV("openOutput() created mixer output: ID %d thread %p", id, thread);
Eric Laurenta553c252009-07-17 12:17:14 -07004347 }
Eric Laurent65b65452010-06-01 23:49:17 -07004348 mPlaybackThreads.add(id, thread);
Eric Laurenta553c252009-07-17 12:17:14 -07004349
4350 if (pSamplingRate) *pSamplingRate = samplingRate;
4351 if (pFormat) *pFormat = format;
4352 if (pChannels) *pChannels = channels;
4353 if (pLatencyMs) *pLatencyMs = thread->latency();
Eric Laurent9cc489a2009-12-05 05:20:01 -08004354
Eric Laurenteb8f850d2010-05-14 03:26:45 -07004355 // notify client processes of the new output creation
4356 thread->audioConfigChanged_l(AudioSystem::OUTPUT_OPENED);
Eric Laurent65b65452010-06-01 23:49:17 -07004357 return id;
Eric Laurenta553c252009-07-17 12:17:14 -07004358 }
4359
Eric Laurent9cc489a2009-12-05 05:20:01 -08004360 return 0;
Eric Laurenta553c252009-07-17 12:17:14 -07004361}
4362
Eric Laurentddb78e72009-07-28 08:44:33 -07004363int AudioFlinger::openDuplicateOutput(int output1, int output2)
Eric Laurenta553c252009-07-17 12:17:14 -07004364{
4365 Mutex::Autolock _l(mLock);
Eric Laurentddb78e72009-07-28 08:44:33 -07004366 MixerThread *thread1 = checkMixerThread_l(output1);
4367 MixerThread *thread2 = checkMixerThread_l(output2);
Eric Laurenta553c252009-07-17 12:17:14 -07004368
Eric Laurentddb78e72009-07-28 08:44:33 -07004369 if (thread1 == NULL || thread2 == NULL) {
4370 LOGW("openDuplicateOutput() wrong output mixer type for output %d or %d", output1, output2);
4371 return 0;
Eric Laurenta553c252009-07-17 12:17:14 -07004372 }
4373
Eric Laurentf3d6dd02010-11-18 08:40:16 -08004374 int id = nextUniqueId_l();
Eric Laurent65b65452010-06-01 23:49:17 -07004375 DuplicatingThread *thread = new DuplicatingThread(this, thread1, id);
Eric Laurentddb78e72009-07-28 08:44:33 -07004376 thread->addOutputTrack(thread2);
Eric Laurent65b65452010-06-01 23:49:17 -07004377 mPlaybackThreads.add(id, thread);
Eric Laurenteb8f850d2010-05-14 03:26:45 -07004378 // notify client processes of the new output creation
4379 thread->audioConfigChanged_l(AudioSystem::OUTPUT_OPENED);
Eric Laurent65b65452010-06-01 23:49:17 -07004380 return id;
Eric Laurenta553c252009-07-17 12:17:14 -07004381}
4382
Eric Laurentddb78e72009-07-28 08:44:33 -07004383status_t AudioFlinger::closeOutput(int output)
Eric Laurenta553c252009-07-17 12:17:14 -07004384{
Eric Laurent49018a52009-08-04 08:37:05 -07004385 // keep strong reference on the playback thread so that
4386 // it is not destroyed while exit() is executed
4387 sp <PlaybackThread> thread;
Eric Laurenta553c252009-07-17 12:17:14 -07004388 {
4389 Mutex::Autolock _l(mLock);
4390 thread = checkPlaybackThread_l(output);
4391 if (thread == NULL) {
4392 return BAD_VALUE;
4393 }
4394
Eric Laurentddb78e72009-07-28 08:44:33 -07004395 LOGV("closeOutput() %d", output);
Eric Laurenta553c252009-07-17 12:17:14 -07004396
4397 if (thread->type() == PlaybackThread::MIXER) {
4398 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
Eric Laurentddb78e72009-07-28 08:44:33 -07004399 if (mPlaybackThreads.valueAt(i)->type() == PlaybackThread::DUPLICATING) {
4400 DuplicatingThread *dupThread = (DuplicatingThread *)mPlaybackThreads.valueAt(i).get();
Eric Laurent49018a52009-08-04 08:37:05 -07004401 dupThread->removeOutputTrack((MixerThread *)thread.get());
Eric Laurenta553c252009-07-17 12:17:14 -07004402 }
4403 }
4404 }
Eric Laurent296a0ec2009-09-15 07:10:12 -07004405 void *param2 = 0;
Eric Laurent49f02be2009-11-19 09:00:56 -08004406 audioConfigChanged_l(AudioSystem::OUTPUT_CLOSED, output, param2);
Eric Laurentddb78e72009-07-28 08:44:33 -07004407 mPlaybackThreads.removeItem(output);
Eric Laurenta553c252009-07-17 12:17:14 -07004408 }
4409 thread->exit();
4410
Eric Laurent49018a52009-08-04 08:37:05 -07004411 if (thread->type() != PlaybackThread::DUPLICATING) {
Dima Zavin31f188892011-04-18 16:57:27 -07004412 AudioStreamOut *out = thread->getOutput();
4413 out->hwDev->close_output_stream(out->hwDev, out->stream);
4414 delete out;
Eric Laurent49018a52009-08-04 08:37:05 -07004415 }
Eric Laurenta553c252009-07-17 12:17:14 -07004416 return NO_ERROR;
4417}
4418
Eric Laurentddb78e72009-07-28 08:44:33 -07004419status_t AudioFlinger::suspendOutput(int output)
Eric Laurenta553c252009-07-17 12:17:14 -07004420{
4421 Mutex::Autolock _l(mLock);
4422 PlaybackThread *thread = checkPlaybackThread_l(output);
4423
4424 if (thread == NULL) {
4425 return BAD_VALUE;
4426 }
4427
Eric Laurentddb78e72009-07-28 08:44:33 -07004428 LOGV("suspendOutput() %d", output);
Eric Laurenta553c252009-07-17 12:17:14 -07004429 thread->suspend();
4430
4431 return NO_ERROR;
4432}
4433
Eric Laurentddb78e72009-07-28 08:44:33 -07004434status_t AudioFlinger::restoreOutput(int output)
Eric Laurenta553c252009-07-17 12:17:14 -07004435{
4436 Mutex::Autolock _l(mLock);
4437 PlaybackThread *thread = checkPlaybackThread_l(output);
4438
4439 if (thread == NULL) {
4440 return BAD_VALUE;
4441 }
4442
Eric Laurentddb78e72009-07-28 08:44:33 -07004443 LOGV("restoreOutput() %d", output);
Eric Laurenta553c252009-07-17 12:17:14 -07004444
4445 thread->restore();
4446
4447 return NO_ERROR;
4448}
4449
Eric Laurentddb78e72009-07-28 08:44:33 -07004450int AudioFlinger::openInput(uint32_t *pDevices,
Eric Laurenta553c252009-07-17 12:17:14 -07004451 uint32_t *pSamplingRate,
4452 uint32_t *pFormat,
4453 uint32_t *pChannels,
4454 uint32_t acoustics)
4455{
4456 status_t status;
4457 RecordThread *thread = NULL;
4458 uint32_t samplingRate = pSamplingRate ? *pSamplingRate : 0;
4459 uint32_t format = pFormat ? *pFormat : 0;
4460 uint32_t channels = pChannels ? *pChannels : 0;
4461 uint32_t reqSamplingRate = samplingRate;
4462 uint32_t reqFormat = format;
4463 uint32_t reqChannels = channels;
Dima Zavin31f188892011-04-18 16:57:27 -07004464 audio_stream_in_t *inStream;
4465 audio_hw_device_t *inHwDev;
Eric Laurenta553c252009-07-17 12:17:14 -07004466
4467 if (pDevices == NULL || *pDevices == 0) {
Eric Laurentddb78e72009-07-28 08:44:33 -07004468 return 0;
Eric Laurenta553c252009-07-17 12:17:14 -07004469 }
Dima Zavin31f188892011-04-18 16:57:27 -07004470
Eric Laurenta553c252009-07-17 12:17:14 -07004471 Mutex::Autolock _l(mLock);
4472
Dima Zavin31f188892011-04-18 16:57:27 -07004473 inHwDev = findSuitableHwDev_l(*pDevices);
4474 if (inHwDev == NULL)
4475 return 0;
4476
4477 status = inHwDev->open_input_stream(inHwDev, *pDevices, (int *)&format,
4478 &channels, &samplingRate,
Dima Zavin24fc2fb2011-04-19 22:30:36 -07004479 (audio_in_acoustics_t)acoustics,
Dima Zavin31f188892011-04-18 16:57:27 -07004480 &inStream);
Eric Laurenta553c252009-07-17 12:17:14 -07004481 LOGV("openInput() openInputStream returned input %p, SamplingRate %d, Format %d, Channels %x, acoustics %x, status %d",
Dima Zavin31f188892011-04-18 16:57:27 -07004482 inStream,
Eric Laurenta553c252009-07-17 12:17:14 -07004483 samplingRate,
4484 format,
4485 channels,
4486 acoustics,
4487 status);
4488
4489 // If the input could not be opened with the requested parameters and we can handle the conversion internally,
4490 // try to open again with the proposed parameters. The AudioFlinger can resample the input and do mono to stereo
4491 // or stereo to mono conversions on 16 bit PCM inputs.
Dima Zavin31f188892011-04-18 16:57:27 -07004492 if (inStream == NULL && status == BAD_VALUE &&
Dima Zavin24fc2fb2011-04-19 22:30:36 -07004493 reqFormat == format && format == AUDIO_FORMAT_PCM_16_BIT &&
Eric Laurenta553c252009-07-17 12:17:14 -07004494 (samplingRate <= 2 * reqSamplingRate) &&
Dima Zavin24fc2fb2011-04-19 22:30:36 -07004495 (popcount(channels) < 3) && (popcount(reqChannels) < 3)) {
Eric Laurenta553c252009-07-17 12:17:14 -07004496 LOGV("openInput() reopening with proposed sampling rate and channels");
Dima Zavin31f188892011-04-18 16:57:27 -07004497 status = inHwDev->open_input_stream(inHwDev, *pDevices, (int *)&format,
4498 &channels, &samplingRate,
Dima Zavin24fc2fb2011-04-19 22:30:36 -07004499 (audio_in_acoustics_t)acoustics,
Dima Zavin31f188892011-04-18 16:57:27 -07004500 &inStream);
Eric Laurenta553c252009-07-17 12:17:14 -07004501 }
4502
Dima Zavin31f188892011-04-18 16:57:27 -07004503 if (inStream != NULL) {
4504 AudioStreamIn *input = new AudioStreamIn(inHwDev, inStream);
4505
Eric Laurentf3d6dd02010-11-18 08:40:16 -08004506 int id = nextUniqueId_l();
Eric Laurenta553c252009-07-17 12:17:14 -07004507 // Start record thread
Eric Laurent65b65452010-06-01 23:49:17 -07004508 thread = new RecordThread(this, input, reqSamplingRate, reqChannels, id);
4509 mRecordThreads.add(id, thread);
4510 LOGV("openInput() created record thread: ID %d thread %p", id, thread);
Eric Laurenta553c252009-07-17 12:17:14 -07004511 if (pSamplingRate) *pSamplingRate = reqSamplingRate;
4512 if (pFormat) *pFormat = format;
4513 if (pChannels) *pChannels = reqChannels;
4514
Dima Zavin31f188892011-04-18 16:57:27 -07004515 input->stream->common.standby(&input->stream->common);
Eric Laurent9cc489a2009-12-05 05:20:01 -08004516
Eric Laurenteb8f850d2010-05-14 03:26:45 -07004517 // notify client processes of the new input creation
4518 thread->audioConfigChanged_l(AudioSystem::INPUT_OPENED);
Eric Laurent65b65452010-06-01 23:49:17 -07004519 return id;
Eric Laurenta553c252009-07-17 12:17:14 -07004520 }
4521
Eric Laurent9cc489a2009-12-05 05:20:01 -08004522 return 0;
Eric Laurenta553c252009-07-17 12:17:14 -07004523}
4524
Eric Laurentddb78e72009-07-28 08:44:33 -07004525status_t AudioFlinger::closeInput(int input)
Eric Laurenta553c252009-07-17 12:17:14 -07004526{
Eric Laurent49018a52009-08-04 08:37:05 -07004527 // keep strong reference on the record thread so that
4528 // it is not destroyed while exit() is executed
4529 sp <RecordThread> thread;
Eric Laurenta553c252009-07-17 12:17:14 -07004530 {
4531 Mutex::Autolock _l(mLock);
4532 thread = checkRecordThread_l(input);
4533 if (thread == NULL) {
4534 return BAD_VALUE;
4535 }
4536
Eric Laurentddb78e72009-07-28 08:44:33 -07004537 LOGV("closeInput() %d", input);
Eric Laurent296a0ec2009-09-15 07:10:12 -07004538 void *param2 = 0;
Eric Laurent49f02be2009-11-19 09:00:56 -08004539 audioConfigChanged_l(AudioSystem::INPUT_CLOSED, input, param2);
Eric Laurentddb78e72009-07-28 08:44:33 -07004540 mRecordThreads.removeItem(input);
Eric Laurenta553c252009-07-17 12:17:14 -07004541 }
4542 thread->exit();
4543
Dima Zavin31f188892011-04-18 16:57:27 -07004544 AudioStreamIn *in = thread->getInput();
4545 in->hwDev->close_input_stream(in->hwDev, in->stream);
4546 delete in;
Eric Laurent49018a52009-08-04 08:37:05 -07004547
Eric Laurenta553c252009-07-17 12:17:14 -07004548 return NO_ERROR;
4549}
4550
Eric Laurentddb78e72009-07-28 08:44:33 -07004551status_t AudioFlinger::setStreamOutput(uint32_t stream, int output)
Eric Laurenta553c252009-07-17 12:17:14 -07004552{
4553 Mutex::Autolock _l(mLock);
4554 MixerThread *dstThread = checkMixerThread_l(output);
4555 if (dstThread == NULL) {
Eric Laurentddb78e72009-07-28 08:44:33 -07004556 LOGW("setStreamOutput() bad output id %d", output);
Eric Laurenta553c252009-07-17 12:17:14 -07004557 return BAD_VALUE;
4558 }
4559
Eric Laurentddb78e72009-07-28 08:44:33 -07004560 LOGV("setStreamOutput() stream %d to output %d", stream, output);
Eric Laurenteb8f850d2010-05-14 03:26:45 -07004561 audioConfigChanged_l(AudioSystem::STREAM_CONFIG_CHANGED, output, &stream);
Eric Laurenta553c252009-07-17 12:17:14 -07004562
4563 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
Eric Laurentddb78e72009-07-28 08:44:33 -07004564 PlaybackThread *thread = mPlaybackThreads.valueAt(i).get();
Eric Laurenta553c252009-07-17 12:17:14 -07004565 if (thread != dstThread &&
4566 thread->type() != PlaybackThread::DIRECT) {
4567 MixerThread *srcThread = (MixerThread *)thread;
Eric Laurenteb8f850d2010-05-14 03:26:45 -07004568 srcThread->invalidateTracks(stream);
Eric Laurenta553c252009-07-17 12:17:14 -07004569 }
Eric Laurent8ed6ed02010-07-13 04:45:46 -07004570 }
Eric Laurentd069f322009-09-01 05:56:26 -07004571
Eric Laurenta553c252009-07-17 12:17:14 -07004572 return NO_ERROR;
4573}
4574
Eric Laurent65b65452010-06-01 23:49:17 -07004575
4576int AudioFlinger::newAudioSessionId()
4577{
Eric Laurentf3d6dd02010-11-18 08:40:16 -08004578 AutoMutex _l(mLock);
4579 return nextUniqueId_l();
Eric Laurent65b65452010-06-01 23:49:17 -07004580}
4581
Eric Laurenta553c252009-07-17 12:17:14 -07004582// checkPlaybackThread_l() must be called with AudioFlinger::mLock held
Eric Laurentddb78e72009-07-28 08:44:33 -07004583AudioFlinger::PlaybackThread *AudioFlinger::checkPlaybackThread_l(int output) const
Eric Laurenta553c252009-07-17 12:17:14 -07004584{
4585 PlaybackThread *thread = NULL;
Eric Laurentddb78e72009-07-28 08:44:33 -07004586 if (mPlaybackThreads.indexOfKey(output) >= 0) {
4587 thread = (PlaybackThread *)mPlaybackThreads.valueFor(output).get();
Eric Laurenta553c252009-07-17 12:17:14 -07004588 }
Eric Laurenta553c252009-07-17 12:17:14 -07004589 return thread;
4590}
4591
4592// checkMixerThread_l() must be called with AudioFlinger::mLock held
Eric Laurentddb78e72009-07-28 08:44:33 -07004593AudioFlinger::MixerThread *AudioFlinger::checkMixerThread_l(int output) const
Eric Laurenta553c252009-07-17 12:17:14 -07004594{
4595 PlaybackThread *thread = checkPlaybackThread_l(output);
4596 if (thread != NULL) {
4597 if (thread->type() == PlaybackThread::DIRECT) {
4598 thread = NULL;
4599 }
4600 }
4601 return (MixerThread *)thread;
4602}
4603
4604// checkRecordThread_l() must be called with AudioFlinger::mLock held
Eric Laurentddb78e72009-07-28 08:44:33 -07004605AudioFlinger::RecordThread *AudioFlinger::checkRecordThread_l(int input) const
Eric Laurenta553c252009-07-17 12:17:14 -07004606{
4607 RecordThread *thread = NULL;
Eric Laurentddb78e72009-07-28 08:44:33 -07004608 if (mRecordThreads.indexOfKey(input) >= 0) {
4609 thread = (RecordThread *)mRecordThreads.valueFor(input).get();
Eric Laurenta553c252009-07-17 12:17:14 -07004610 }
Eric Laurenta553c252009-07-17 12:17:14 -07004611 return thread;
4612}
4613
Eric Laurentf3d6dd02010-11-18 08:40:16 -08004614// nextUniqueId_l() must be called with AudioFlinger::mLock held
4615int AudioFlinger::nextUniqueId_l()
Eric Laurent65b65452010-06-01 23:49:17 -07004616{
Eric Laurentf3d6dd02010-11-18 08:40:16 -08004617 return mNextUniqueId++;
Eric Laurent65b65452010-06-01 23:49:17 -07004618}
4619
4620// ----------------------------------------------------------------------------
4621// Effect management
4622// ----------------------------------------------------------------------------
4623
4624
Eric Laurent65b65452010-06-01 23:49:17 -07004625status_t AudioFlinger::queryNumberEffects(uint32_t *numEffects)
4626{
4627 Mutex::Autolock _l(mLock);
4628 return EffectQueryNumberEffects(numEffects);
4629}
4630
Eric Laurent53334cd2010-06-23 17:38:20 -07004631status_t AudioFlinger::queryEffect(uint32_t index, effect_descriptor_t *descriptor)
Eric Laurent65b65452010-06-01 23:49:17 -07004632{
4633 Mutex::Autolock _l(mLock);
Eric Laurent53334cd2010-06-23 17:38:20 -07004634 return EffectQueryEffect(index, descriptor);
Eric Laurent65b65452010-06-01 23:49:17 -07004635}
4636
4637status_t AudioFlinger::getEffectDescriptor(effect_uuid_t *pUuid, effect_descriptor_t *descriptor)
4638{
4639 Mutex::Autolock _l(mLock);
4640 return EffectGetDescriptor(pUuid, descriptor);
4641}
4642
Eric Laurentdf9b81c2010-07-02 08:12:41 -07004643
4644// this UUID must match the one defined in media/libeffects/EffectVisualizer.cpp
4645static const effect_uuid_t VISUALIZATION_UUID_ =
4646 {0xd069d9e0, 0x8329, 0x11df, 0x9168, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}};
4647
Eric Laurent65b65452010-06-01 23:49:17 -07004648sp<IEffect> AudioFlinger::createEffect(pid_t pid,
4649 effect_descriptor_t *pDesc,
4650 const sp<IEffectClient>& effectClient,
4651 int32_t priority,
4652 int output,
4653 int sessionId,
4654 status_t *status,
4655 int *id,
4656 int *enabled)
4657{
4658 status_t lStatus = NO_ERROR;
4659 sp<EffectHandle> handle;
Eric Laurent65b65452010-06-01 23:49:17 -07004660 effect_descriptor_t desc;
4661 sp<Client> client;
4662 wp<Client> wclient;
4663
Eric Laurent8ed6ed02010-07-13 04:45:46 -07004664 LOGV("createEffect pid %d, client %p, priority %d, sessionId %d, output %d",
4665 pid, effectClient.get(), priority, sessionId, output);
Eric Laurent65b65452010-06-01 23:49:17 -07004666
4667 if (pDesc == NULL) {
4668 lStatus = BAD_VALUE;
4669 goto Exit;
4670 }
4671
Eric Laurent98c92592010-09-23 16:10:16 -07004672 // check audio settings permission for global effects
Dima Zavin24fc2fb2011-04-19 22:30:36 -07004673 if (sessionId == AUDIO_SESSION_OUTPUT_MIX && !settingsAllowed()) {
Eric Laurent98c92592010-09-23 16:10:16 -07004674 lStatus = PERMISSION_DENIED;
4675 goto Exit;
4676 }
4677
Dima Zavin24fc2fb2011-04-19 22:30:36 -07004678 // Session AUDIO_SESSION_OUTPUT_STAGE is reserved for output stage effects
Eric Laurent98c92592010-09-23 16:10:16 -07004679 // that can only be created by audio policy manager (running in same process)
Dima Zavin24fc2fb2011-04-19 22:30:36 -07004680 if (sessionId == AUDIO_SESSION_OUTPUT_STAGE && getpid() != pid) {
Eric Laurent98c92592010-09-23 16:10:16 -07004681 lStatus = PERMISSION_DENIED;
4682 goto Exit;
4683 }
4684
4685 // check recording permission for visualizer
4686 if ((memcmp(&pDesc->type, SL_IID_VISUALIZATION, sizeof(effect_uuid_t)) == 0 ||
4687 memcmp(&pDesc->uuid, &VISUALIZATION_UUID_, sizeof(effect_uuid_t)) == 0) &&
4688 !recordingAllowed()) {
4689 lStatus = PERMISSION_DENIED;
4690 goto Exit;
4691 }
4692
4693 if (output == 0) {
Dima Zavin24fc2fb2011-04-19 22:30:36 -07004694 if (sessionId == AUDIO_SESSION_OUTPUT_STAGE) {
Eric Laurent98c92592010-09-23 16:10:16 -07004695 // output must be specified by AudioPolicyManager when using session
Dima Zavin24fc2fb2011-04-19 22:30:36 -07004696 // AUDIO_SESSION_OUTPUT_STAGE
Eric Laurent98c92592010-09-23 16:10:16 -07004697 lStatus = BAD_VALUE;
4698 goto Exit;
Dima Zavin24fc2fb2011-04-19 22:30:36 -07004699 } else if (sessionId == AUDIO_SESSION_OUTPUT_MIX) {
Eric Laurent98c92592010-09-23 16:10:16 -07004700 // if the output returned by getOutputForEffect() is removed before we lock the
4701 // mutex below, the call to checkPlaybackThread_l(output) below will detect it
4702 // and we will exit safely
4703 output = AudioSystem::getOutputForEffect(&desc);
4704 }
4705 }
4706
Eric Laurent65b65452010-06-01 23:49:17 -07004707 {
4708 Mutex::Autolock _l(mLock);
4709
Eric Laurentdf9b81c2010-07-02 08:12:41 -07004710
Eric Laurent65b65452010-06-01 23:49:17 -07004711 if (!EffectIsNullUuid(&pDesc->uuid)) {
4712 // if uuid is specified, request effect descriptor
4713 lStatus = EffectGetDescriptor(&pDesc->uuid, &desc);
4714 if (lStatus < 0) {
4715 LOGW("createEffect() error %d from EffectGetDescriptor", lStatus);
4716 goto Exit;
4717 }
4718 } else {
4719 // if uuid is not specified, look for an available implementation
4720 // of the required type in effect factory
4721 if (EffectIsNullUuid(&pDesc->type)) {
4722 LOGW("createEffect() no effect type");
4723 lStatus = BAD_VALUE;
4724 goto Exit;
4725 }
4726 uint32_t numEffects = 0;
4727 effect_descriptor_t d;
4728 bool found = false;
4729
4730 lStatus = EffectQueryNumberEffects(&numEffects);
4731 if (lStatus < 0) {
4732 LOGW("createEffect() error %d from EffectQueryNumberEffects", lStatus);
4733 goto Exit;
4734 }
Eric Laurent53334cd2010-06-23 17:38:20 -07004735 for (uint32_t i = 0; i < numEffects; i++) {
4736 lStatus = EffectQueryEffect(i, &desc);
Eric Laurent65b65452010-06-01 23:49:17 -07004737 if (lStatus < 0) {
Eric Laurent53334cd2010-06-23 17:38:20 -07004738 LOGW("createEffect() error %d from EffectQueryEffect", lStatus);
Eric Laurent65b65452010-06-01 23:49:17 -07004739 continue;
4740 }
4741 if (memcmp(&desc.type, &pDesc->type, sizeof(effect_uuid_t)) == 0) {
4742 // If matching type found save effect descriptor. If the session is
4743 // 0 and the effect is not auxiliary, continue enumeration in case
4744 // an auxiliary version of this effect type is available
4745 found = true;
4746 memcpy(&d, &desc, sizeof(effect_descriptor_t));
Dima Zavin24fc2fb2011-04-19 22:30:36 -07004747 if (sessionId != AUDIO_SESSION_OUTPUT_MIX ||
Eric Laurent65b65452010-06-01 23:49:17 -07004748 (desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
4749 break;
4750 }
4751 }
4752 }
4753 if (!found) {
4754 lStatus = BAD_VALUE;
4755 LOGW("createEffect() effect not found");
4756 goto Exit;
4757 }
4758 // For same effect type, chose auxiliary version over insert version if
4759 // connect to output mix (Compliance to OpenSL ES)
Dima Zavin24fc2fb2011-04-19 22:30:36 -07004760 if (sessionId == AUDIO_SESSION_OUTPUT_MIX &&
Eric Laurent65b65452010-06-01 23:49:17 -07004761 (d.flags & EFFECT_FLAG_TYPE_MASK) != EFFECT_FLAG_TYPE_AUXILIARY) {
4762 memcpy(&desc, &d, sizeof(effect_descriptor_t));
4763 }
4764 }
4765
4766 // Do not allow auxiliary effects on a session different from 0 (output mix)
Dima Zavin24fc2fb2011-04-19 22:30:36 -07004767 if (sessionId != AUDIO_SESSION_OUTPUT_MIX &&
Eric Laurent65b65452010-06-01 23:49:17 -07004768 (desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
4769 lStatus = INVALID_OPERATION;
4770 goto Exit;
4771 }
4772
4773 // return effect descriptor
4774 memcpy(pDesc, &desc, sizeof(effect_descriptor_t));
4775
4776 // If output is not specified try to find a matching audio session ID in one of the
4777 // output threads.
Eric Laurent98c92592010-09-23 16:10:16 -07004778 // If output is 0 here, sessionId is neither SESSION_OUTPUT_STAGE nor SESSION_OUTPUT_MIX
4779 // because of code checking output when entering the function.
Eric Laurent65b65452010-06-01 23:49:17 -07004780 if (output == 0) {
Eric Laurent98c92592010-09-23 16:10:16 -07004781 // look for the thread where the specified audio session is present
4782 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
4783 if (mPlaybackThreads.valueAt(i)->hasAudioSession(sessionId) != 0) {
4784 output = mPlaybackThreads.keyAt(i);
4785 break;
Eric Laurent493941b2010-07-28 01:32:47 -07004786 }
Eric Laurent65b65452010-06-01 23:49:17 -07004787 }
Eric Laurent98c92592010-09-23 16:10:16 -07004788 // If no output thread contains the requested session ID, default to
4789 // first output. The effect chain will be moved to the correct output
4790 // thread when a track with the same session ID is created
4791 if (output == 0 && mPlaybackThreads.size()) {
4792 output = mPlaybackThreads.keyAt(0);
4793 }
Eric Laurent65b65452010-06-01 23:49:17 -07004794 }
Eric Laurent98c92592010-09-23 16:10:16 -07004795 LOGV("createEffect() got output %d for effect %s", output, desc.name);
Eric Laurent65b65452010-06-01 23:49:17 -07004796 PlaybackThread *thread = checkPlaybackThread_l(output);
4797 if (thread == NULL) {
Eric Laurent8ed6ed02010-07-13 04:45:46 -07004798 LOGE("createEffect() unknown output thread");
Eric Laurent65b65452010-06-01 23:49:17 -07004799 lStatus = BAD_VALUE;
4800 goto Exit;
4801 }
4802
Eric Laurent98c92592010-09-23 16:10:16 -07004803 // TODO: allow attachment of effect to inputs
4804
Eric Laurent65b65452010-06-01 23:49:17 -07004805 wclient = mClients.valueFor(pid);
4806
4807 if (wclient != NULL) {
4808 client = wclient.promote();
4809 } else {
4810 client = new Client(this, pid);
4811 mClients.add(pid, client);
4812 }
4813
4814 // create effect on selected output trhead
Eric Laurent8ed6ed02010-07-13 04:45:46 -07004815 handle = thread->createEffect_l(client, effectClient, priority, sessionId,
4816 &desc, enabled, &lStatus);
Eric Laurent65b65452010-06-01 23:49:17 -07004817 if (handle != 0 && id != NULL) {
4818 *id = handle->id();
4819 }
4820 }
4821
4822Exit:
4823 if(status) {
4824 *status = lStatus;
4825 }
4826 return handle;
4827}
4828
Eric Laurent8ed6ed02010-07-13 04:45:46 -07004829status_t AudioFlinger::moveEffects(int session, int srcOutput, int dstOutput)
4830{
4831 LOGV("moveEffects() session %d, srcOutput %d, dstOutput %d",
4832 session, srcOutput, dstOutput);
4833 Mutex::Autolock _l(mLock);
4834 if (srcOutput == dstOutput) {
4835 LOGW("moveEffects() same dst and src outputs %d", dstOutput);
4836 return NO_ERROR;
Eric Laurent53334cd2010-06-23 17:38:20 -07004837 }
Eric Laurent8ed6ed02010-07-13 04:45:46 -07004838 PlaybackThread *srcThread = checkPlaybackThread_l(srcOutput);
4839 if (srcThread == NULL) {
4840 LOGW("moveEffects() bad srcOutput %d", srcOutput);
4841 return BAD_VALUE;
Eric Laurent53334cd2010-06-23 17:38:20 -07004842 }
Eric Laurent8ed6ed02010-07-13 04:45:46 -07004843 PlaybackThread *dstThread = checkPlaybackThread_l(dstOutput);
4844 if (dstThread == NULL) {
4845 LOGW("moveEffects() bad dstOutput %d", dstOutput);
4846 return BAD_VALUE;
4847 }
4848
4849 Mutex::Autolock _dl(dstThread->mLock);
4850 Mutex::Autolock _sl(srcThread->mLock);
Eric Laurent493941b2010-07-28 01:32:47 -07004851 moveEffectChain_l(session, srcThread, dstThread, false);
Eric Laurent8ed6ed02010-07-13 04:45:46 -07004852
Eric Laurent53334cd2010-06-23 17:38:20 -07004853 return NO_ERROR;
4854}
4855
Eric Laurent8ed6ed02010-07-13 04:45:46 -07004856// moveEffectChain_l mustbe called with both srcThread and dstThread mLocks held
4857status_t AudioFlinger::moveEffectChain_l(int session,
4858 AudioFlinger::PlaybackThread *srcThread,
Eric Laurent493941b2010-07-28 01:32:47 -07004859 AudioFlinger::PlaybackThread *dstThread,
4860 bool reRegister)
Eric Laurent8ed6ed02010-07-13 04:45:46 -07004861{
4862 LOGV("moveEffectChain_l() session %d from thread %p to thread %p",
4863 session, srcThread, dstThread);
4864
4865 sp<EffectChain> chain = srcThread->getEffectChain_l(session);
4866 if (chain == 0) {
4867 LOGW("moveEffectChain_l() effect chain for session %d not on source thread %p",
4868 session, srcThread);
4869 return INVALID_OPERATION;
4870 }
4871
Eric Laurent493941b2010-07-28 01:32:47 -07004872 // remove chain first. This is useful only if reconfiguring effect chain on same output thread,
Eric Laurent8ed6ed02010-07-13 04:45:46 -07004873 // so that a new chain is created with correct parameters when first effect is added. This is
4874 // otherwise unecessary as removeEffect_l() will remove the chain when last effect is
4875 // removed.
4876 srcThread->removeEffectChain_l(chain);
4877
4878 // transfer all effects one by one so that new effect chain is created on new thread with
4879 // correct buffer sizes and audio parameters and effect engines reconfigured accordingly
Eric Laurent493941b2010-07-28 01:32:47 -07004880 int dstOutput = dstThread->id();
4881 sp<EffectChain> dstChain;
4882 uint32_t strategy;
Eric Laurent8ed6ed02010-07-13 04:45:46 -07004883 sp<EffectModule> effect = chain->getEffectFromId_l(0);
4884 while (effect != 0) {
4885 srcThread->removeEffect_l(effect);
4886 dstThread->addEffect_l(effect);
Eric Laurent493941b2010-07-28 01:32:47 -07004887 // if the move request is not received from audio policy manager, the effect must be
4888 // re-registered with the new strategy and output
4889 if (dstChain == 0) {
4890 dstChain = effect->chain().promote();
4891 if (dstChain == 0) {
4892 LOGW("moveEffectChain_l() cannot get chain from effect %p", effect.get());
4893 srcThread->addEffect_l(effect);
4894 return NO_INIT;
4895 }
4896 strategy = dstChain->strategy();
4897 }
4898 if (reRegister) {
4899 AudioSystem::unregisterEffect(effect->id());
4900 AudioSystem::registerEffect(&effect->desc(),
4901 dstOutput,
4902 strategy,
4903 session,
4904 effect->id());
4905 }
Eric Laurent8ed6ed02010-07-13 04:45:46 -07004906 effect = chain->getEffectFromId_l(0);
4907 }
4908
4909 return NO_ERROR;
Eric Laurent53334cd2010-06-23 17:38:20 -07004910}
4911
Eric Laurent65b65452010-06-01 23:49:17 -07004912// PlaybackThread::createEffect_l() must be called with AudioFlinger::mLock held
4913sp<AudioFlinger::EffectHandle> AudioFlinger::PlaybackThread::createEffect_l(
4914 const sp<AudioFlinger::Client>& client,
4915 const sp<IEffectClient>& effectClient,
4916 int32_t priority,
4917 int sessionId,
4918 effect_descriptor_t *desc,
4919 int *enabled,
4920 status_t *status
4921 )
4922{
4923 sp<EffectModule> effect;
4924 sp<EffectHandle> handle;
4925 status_t lStatus;
4926 sp<Track> track;
4927 sp<EffectChain> chain;
Eric Laurent8ed6ed02010-07-13 04:45:46 -07004928 bool chainCreated = false;
Eric Laurent65b65452010-06-01 23:49:17 -07004929 bool effectCreated = false;
Eric Laurent53334cd2010-06-23 17:38:20 -07004930 bool effectRegistered = false;
Eric Laurent65b65452010-06-01 23:49:17 -07004931
4932 if (mOutput == 0) {
4933 LOGW("createEffect_l() Audio driver not initialized.");
4934 lStatus = NO_INIT;
4935 goto Exit;
4936 }
4937
4938 // Do not allow auxiliary effect on session other than 0
4939 if ((desc->flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY &&
Dima Zavin24fc2fb2011-04-19 22:30:36 -07004940 sessionId != AUDIO_SESSION_OUTPUT_MIX) {
Eric Laurent8ed6ed02010-07-13 04:45:46 -07004941 LOGW("createEffect_l() Cannot add auxiliary effect %s to session %d",
4942 desc->name, sessionId);
Eric Laurent65b65452010-06-01 23:49:17 -07004943 lStatus = BAD_VALUE;
4944 goto Exit;
4945 }
4946
4947 // Do not allow effects with session ID 0 on direct output or duplicating threads
4948 // TODO: add rule for hw accelerated effects on direct outputs with non PCM format
Dima Zavin24fc2fb2011-04-19 22:30:36 -07004949 if (sessionId == AUDIO_SESSION_OUTPUT_MIX && mType != MIXER) {
Eric Laurent8ed6ed02010-07-13 04:45:46 -07004950 LOGW("createEffect_l() Cannot add auxiliary effect %s to session %d",
4951 desc->name, sessionId);
Eric Laurent65b65452010-06-01 23:49:17 -07004952 lStatus = BAD_VALUE;
4953 goto Exit;
4954 }
4955
4956 LOGV("createEffect_l() thread %p effect %s on session %d", this, desc->name, sessionId);
4957
4958 { // scope for mLock
4959 Mutex::Autolock _l(mLock);
4960
4961 // check for existing effect chain with the requested audio session
4962 chain = getEffectChain_l(sessionId);
4963 if (chain == 0) {
4964 // create a new chain for this session
4965 LOGV("createEffect_l() new effect chain for session %d", sessionId);
4966 chain = new EffectChain(this, sessionId);
4967 addEffectChain_l(chain);
Eric Laurent8ed6ed02010-07-13 04:45:46 -07004968 chain->setStrategy(getStrategyForSession_l(sessionId));
4969 chainCreated = true;
Eric Laurent65b65452010-06-01 23:49:17 -07004970 } else {
Eric Laurent76c40f72010-07-15 12:50:15 -07004971 effect = chain->getEffectFromDesc_l(desc);
Eric Laurent65b65452010-06-01 23:49:17 -07004972 }
4973
4974 LOGV("createEffect_l() got effect %p on chain %p", effect == 0 ? 0 : effect.get(), chain.get());
4975
4976 if (effect == 0) {
Eric Laurentf3d6dd02010-11-18 08:40:16 -08004977 int id = mAudioFlinger->nextUniqueId_l();
Eric Laurent53334cd2010-06-23 17:38:20 -07004978 // Check CPU and memory usage
Eric Laurent8ed6ed02010-07-13 04:45:46 -07004979 lStatus = AudioSystem::registerEffect(desc, mId, chain->strategy(), sessionId, id);
Eric Laurent53334cd2010-06-23 17:38:20 -07004980 if (lStatus != NO_ERROR) {
4981 goto Exit;
4982 }
4983 effectRegistered = true;
Eric Laurent65b65452010-06-01 23:49:17 -07004984 // create a new effect module if none present in the chain
Eric Laurent8ed6ed02010-07-13 04:45:46 -07004985 effect = new EffectModule(this, chain, desc, id, sessionId);
Eric Laurent65b65452010-06-01 23:49:17 -07004986 lStatus = effect->status();
4987 if (lStatus != NO_ERROR) {
4988 goto Exit;
4989 }
Eric Laurent76c40f72010-07-15 12:50:15 -07004990 lStatus = chain->addEffect_l(effect);
Eric Laurent65b65452010-06-01 23:49:17 -07004991 if (lStatus != NO_ERROR) {
4992 goto Exit;
4993 }
Eric Laurent53334cd2010-06-23 17:38:20 -07004994 effectCreated = true;
Eric Laurent65b65452010-06-01 23:49:17 -07004995
4996 effect->setDevice(mDevice);
Eric Laurent53334cd2010-06-23 17:38:20 -07004997 effect->setMode(mAudioFlinger->getMode());
Eric Laurent65b65452010-06-01 23:49:17 -07004998 }
4999 // create effect handle and connect it to effect module
5000 handle = new EffectHandle(effect, client, effectClient, priority);
5001 lStatus = effect->addHandle(handle);
5002 if (enabled) {
5003 *enabled = (int)effect->isEnabled();
5004 }
5005 }
5006
5007Exit:
5008 if (lStatus != NO_ERROR && lStatus != ALREADY_EXISTS) {
Eric Laurent8ed6ed02010-07-13 04:45:46 -07005009 Mutex::Autolock _l(mLock);
Eric Laurent53334cd2010-06-23 17:38:20 -07005010 if (effectCreated) {
Eric Laurent8ed6ed02010-07-13 04:45:46 -07005011 chain->removeEffect_l(effect);
Eric Laurent65b65452010-06-01 23:49:17 -07005012 }
Eric Laurent53334cd2010-06-23 17:38:20 -07005013 if (effectRegistered) {
Eric Laurent8ed6ed02010-07-13 04:45:46 -07005014 AudioSystem::unregisterEffect(effect->id());
5015 }
5016 if (chainCreated) {
5017 removeEffectChain_l(chain);
Eric Laurent53334cd2010-06-23 17:38:20 -07005018 }
Eric Laurent65b65452010-06-01 23:49:17 -07005019 handle.clear();
5020 }
5021
5022 if(status) {
5023 *status = lStatus;
5024 }
5025 return handle;
5026}
5027
Eric Laurent8ed6ed02010-07-13 04:45:46 -07005028// PlaybackThread::addEffect_l() must be called with AudioFlinger::mLock and
5029// PlaybackThread::mLock held
5030status_t AudioFlinger::PlaybackThread::addEffect_l(const sp<EffectModule>& effect)
5031{
5032 // check for existing effect chain with the requested audio session
5033 int sessionId = effect->sessionId();
5034 sp<EffectChain> chain = getEffectChain_l(sessionId);
5035 bool chainCreated = false;
5036
5037 if (chain == 0) {
5038 // create a new chain for this session
5039 LOGV("addEffect_l() new effect chain for session %d", sessionId);
5040 chain = new EffectChain(this, sessionId);
5041 addEffectChain_l(chain);
5042 chain->setStrategy(getStrategyForSession_l(sessionId));
5043 chainCreated = true;
5044 }
5045 LOGV("addEffect_l() %p chain %p effect %p", this, chain.get(), effect.get());
5046
5047 if (chain->getEffectFromId_l(effect->id()) != 0) {
5048 LOGW("addEffect_l() %p effect %s already present in chain %p",
5049 this, effect->desc().name, chain.get());
5050 return BAD_VALUE;
5051 }
5052
5053 status_t status = chain->addEffect_l(effect);
5054 if (status != NO_ERROR) {
5055 if (chainCreated) {
5056 removeEffectChain_l(chain);
5057 }
5058 return status;
5059 }
5060
5061 effect->setDevice(mDevice);
5062 effect->setMode(mAudioFlinger->getMode());
5063 return NO_ERROR;
5064}
5065
5066void AudioFlinger::PlaybackThread::removeEffect_l(const sp<EffectModule>& effect) {
5067
5068 LOGV("removeEffect_l() %p effect %p", this, effect.get());
Eric Laurent53334cd2010-06-23 17:38:20 -07005069 effect_descriptor_t desc = effect->desc();
Eric Laurent8ed6ed02010-07-13 04:45:46 -07005070 if ((desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
5071 detachAuxEffect_l(effect->id());
5072 }
5073
5074 sp<EffectChain> chain = effect->chain().promote();
5075 if (chain != 0) {
5076 // remove effect chain if removing last effect
5077 if (chain->removeEffect_l(effect) == 0) {
5078 removeEffectChain_l(chain);
5079 }
5080 } else {
5081 LOGW("removeEffect_l() %p cannot promote chain for effect %p", this, effect.get());
5082 }
5083}
5084
5085void AudioFlinger::PlaybackThread::disconnectEffect(const sp<EffectModule>& effect,
5086 const wp<EffectHandle>& handle) {
Eric Laurent53334cd2010-06-23 17:38:20 -07005087 Mutex::Autolock _l(mLock);
Eric Laurent8ed6ed02010-07-13 04:45:46 -07005088 LOGV("disconnectEffect() %p effect %p", this, effect.get());
Eric Laurent53334cd2010-06-23 17:38:20 -07005089 // delete the effect module if removing last handle on it
5090 if (effect->removeHandle(handle) == 0) {
Eric Laurent8ed6ed02010-07-13 04:45:46 -07005091 removeEffect_l(effect);
5092 AudioSystem::unregisterEffect(effect->id());
Eric Laurent53334cd2010-06-23 17:38:20 -07005093 }
5094}
5095
Eric Laurent65b65452010-06-01 23:49:17 -07005096status_t AudioFlinger::PlaybackThread::addEffectChain_l(const sp<EffectChain>& chain)
5097{
5098 int session = chain->sessionId();
5099 int16_t *buffer = mMixBuffer;
Eric Laurent53334cd2010-06-23 17:38:20 -07005100 bool ownsBuffer = false;
Eric Laurent65b65452010-06-01 23:49:17 -07005101
5102 LOGV("addEffectChain_l() %p on thread %p for session %d", chain.get(), this, session);
Eric Laurent53334cd2010-06-23 17:38:20 -07005103 if (session > 0) {
Eric Laurent65b65452010-06-01 23:49:17 -07005104 // Only one effect chain can be present in direct output thread and it uses
5105 // the mix buffer as input
5106 if (mType != DIRECT) {
5107 size_t numSamples = mFrameCount * mChannelCount;
5108 buffer = new int16_t[numSamples];
5109 memset(buffer, 0, numSamples * sizeof(int16_t));
5110 LOGV("addEffectChain_l() creating new input buffer %p session %d", buffer, session);
5111 ownsBuffer = true;
5112 }
Eric Laurent65b65452010-06-01 23:49:17 -07005113
Eric Laurent53334cd2010-06-23 17:38:20 -07005114 // Attach all tracks with same session ID to this chain.
5115 for (size_t i = 0; i < mTracks.size(); ++i) {
5116 sp<Track> track = mTracks[i];
5117 if (session == track->sessionId()) {
5118 LOGV("addEffectChain_l() track->setMainBuffer track %p buffer %p", track.get(), buffer);
5119 track->setMainBuffer(buffer);
Eric Laurent90681d62011-05-09 12:09:06 -07005120 chain->incTrackCnt();
Eric Laurent53334cd2010-06-23 17:38:20 -07005121 }
5122 }
5123
5124 // indicate all active tracks in the chain
5125 for (size_t i = 0 ; i < mActiveTracks.size() ; ++i) {
5126 sp<Track> track = mActiveTracks[i].promote();
5127 if (track == 0) continue;
5128 if (session == track->sessionId()) {
5129 LOGV("addEffectChain_l() activating track %p on session %d", track.get(), session);
Eric Laurent90681d62011-05-09 12:09:06 -07005130 chain->incActiveTrackCnt();
Eric Laurent53334cd2010-06-23 17:38:20 -07005131 }
Eric Laurent65b65452010-06-01 23:49:17 -07005132 }
5133 }
5134
Eric Laurent53334cd2010-06-23 17:38:20 -07005135 chain->setInBuffer(buffer, ownsBuffer);
5136 chain->setOutBuffer(mMixBuffer);
Dima Zavin24fc2fb2011-04-19 22:30:36 -07005137 // Effect chain for session AUDIO_SESSION_OUTPUT_STAGE is inserted at end of effect
Eric Laurent8ed6ed02010-07-13 04:45:46 -07005138 // chains list in order to be processed last as it contains output stage effects
Dima Zavin24fc2fb2011-04-19 22:30:36 -07005139 // Effect chain for session AUDIO_SESSION_OUTPUT_MIX is inserted before
5140 // session AUDIO_SESSION_OUTPUT_STAGE to be processed
Eric Laurent53334cd2010-06-23 17:38:20 -07005141 // after track specific effects and before output stage
Dima Zavin24fc2fb2011-04-19 22:30:36 -07005142 // It is therefore mandatory that AUDIO_SESSION_OUTPUT_MIX == 0 and
5143 // that AUDIO_SESSION_OUTPUT_STAGE < AUDIO_SESSION_OUTPUT_MIX
Eric Laurent8ed6ed02010-07-13 04:45:46 -07005144 // Effect chain for other sessions are inserted at beginning of effect
5145 // chains list to be processed before output mix effects. Relative order between other
5146 // sessions is not important
Eric Laurent53334cd2010-06-23 17:38:20 -07005147 size_t size = mEffectChains.size();
5148 size_t i = 0;
5149 for (i = 0; i < size; i++) {
5150 if (mEffectChains[i]->sessionId() < session) break;
Eric Laurent65b65452010-06-01 23:49:17 -07005151 }
Eric Laurent53334cd2010-06-23 17:38:20 -07005152 mEffectChains.insertAt(chain, i);
Eric Laurent65b65452010-06-01 23:49:17 -07005153
5154 return NO_ERROR;
5155}
5156
5157size_t AudioFlinger::PlaybackThread::removeEffectChain_l(const sp<EffectChain>& chain)
5158{
5159 int session = chain->sessionId();
5160
5161 LOGV("removeEffectChain_l() %p from thread %p for session %d", chain.get(), this, session);
5162
5163 for (size_t i = 0; i < mEffectChains.size(); i++) {
5164 if (chain == mEffectChains[i]) {
5165 mEffectChains.removeAt(i);
Eric Laurent90681d62011-05-09 12:09:06 -07005166 // detach all active tracks from the chain
5167 for (size_t i = 0 ; i < mActiveTracks.size() ; ++i) {
5168 sp<Track> track = mActiveTracks[i].promote();
5169 if (track == 0) continue;
5170 if (session == track->sessionId()) {
5171 LOGV("removeEffectChain_l(): stopping track on chain %p for session Id: %d",
5172 chain.get(), session);
5173 chain->decActiveTrackCnt();
5174 }
5175 }
5176
Eric Laurent65b65452010-06-01 23:49:17 -07005177 // detach all tracks with same session ID from this chain
5178 for (size_t i = 0; i < mTracks.size(); ++i) {
5179 sp<Track> track = mTracks[i];
5180 if (session == track->sessionId()) {
5181 track->setMainBuffer(mMixBuffer);
Eric Laurent90681d62011-05-09 12:09:06 -07005182 chain->decTrackCnt();
Eric Laurent65b65452010-06-01 23:49:17 -07005183 }
5184 }
Eric Laurent8ed6ed02010-07-13 04:45:46 -07005185 break;
Eric Laurent65b65452010-06-01 23:49:17 -07005186 }
5187 }
5188 return mEffectChains.size();
5189}
5190
Eric Laurent8ed6ed02010-07-13 04:45:46 -07005191void AudioFlinger::PlaybackThread::lockEffectChains_l(
5192 Vector<sp <AudioFlinger::EffectChain> >& effectChains)
Eric Laurent65b65452010-06-01 23:49:17 -07005193{
Eric Laurent8ed6ed02010-07-13 04:45:46 -07005194 effectChains = mEffectChains;
Eric Laurent65b65452010-06-01 23:49:17 -07005195 for (size_t i = 0; i < mEffectChains.size(); i++) {
5196 mEffectChains[i]->lock();
5197 }
5198}
5199
Eric Laurent8ed6ed02010-07-13 04:45:46 -07005200void AudioFlinger::PlaybackThread::unlockEffectChains(
5201 Vector<sp <AudioFlinger::EffectChain> >& effectChains)
Eric Laurent65b65452010-06-01 23:49:17 -07005202{
Eric Laurent8ed6ed02010-07-13 04:45:46 -07005203 for (size_t i = 0; i < effectChains.size(); i++) {
5204 effectChains[i]->unlock();
Eric Laurent65b65452010-06-01 23:49:17 -07005205 }
5206}
5207
Eric Laurent8ed6ed02010-07-13 04:45:46 -07005208
Eric Laurent65b65452010-06-01 23:49:17 -07005209sp<AudioFlinger::EffectModule> AudioFlinger::PlaybackThread::getEffect_l(int sessionId, int effectId)
5210{
5211 sp<EffectModule> effect;
5212
5213 sp<EffectChain> chain = getEffectChain_l(sessionId);
5214 if (chain != 0) {
Eric Laurent76c40f72010-07-15 12:50:15 -07005215 effect = chain->getEffectFromId_l(effectId);
Eric Laurent65b65452010-06-01 23:49:17 -07005216 }
5217 return effect;
5218}
5219
Eric Laurent8ed6ed02010-07-13 04:45:46 -07005220status_t AudioFlinger::PlaybackThread::attachAuxEffect(
5221 const sp<AudioFlinger::PlaybackThread::Track> track, int EffectId)
Eric Laurent65b65452010-06-01 23:49:17 -07005222{
5223 Mutex::Autolock _l(mLock);
5224 return attachAuxEffect_l(track, EffectId);
5225}
5226
Eric Laurent8ed6ed02010-07-13 04:45:46 -07005227status_t AudioFlinger::PlaybackThread::attachAuxEffect_l(
5228 const sp<AudioFlinger::PlaybackThread::Track> track, int EffectId)
Eric Laurent65b65452010-06-01 23:49:17 -07005229{
5230 status_t status = NO_ERROR;
5231
5232 if (EffectId == 0) {
5233 track->setAuxBuffer(0, NULL);
5234 } else {
Dima Zavin24fc2fb2011-04-19 22:30:36 -07005235 // Auxiliary effects are always in audio session AUDIO_SESSION_OUTPUT_MIX
5236 sp<EffectModule> effect = getEffect_l(AUDIO_SESSION_OUTPUT_MIX, EffectId);
Eric Laurent65b65452010-06-01 23:49:17 -07005237 if (effect != 0) {
5238 if ((effect->desc().flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
5239 track->setAuxBuffer(EffectId, (int32_t *)effect->inBuffer());
5240 } else {
5241 status = INVALID_OPERATION;
5242 }
5243 } else {
5244 status = BAD_VALUE;
5245 }
5246 }
5247 return status;
5248}
5249
5250void AudioFlinger::PlaybackThread::detachAuxEffect_l(int effectId)
5251{
5252 for (size_t i = 0; i < mTracks.size(); ++i) {
5253 sp<Track> track = mTracks[i];
5254 if (track->auxEffectId() == effectId) {
5255 attachAuxEffect_l(track, 0);
5256 }
5257 }
5258}
5259
5260// ----------------------------------------------------------------------------
5261// EffectModule implementation
5262// ----------------------------------------------------------------------------
5263
5264#undef LOG_TAG
5265#define LOG_TAG "AudioFlinger::EffectModule"
5266
5267AudioFlinger::EffectModule::EffectModule(const wp<ThreadBase>& wThread,
5268 const wp<AudioFlinger::EffectChain>& chain,
5269 effect_descriptor_t *desc,
5270 int id,
5271 int sessionId)
5272 : mThread(wThread), mChain(chain), mId(id), mSessionId(sessionId), mEffectInterface(NULL),
5273 mStatus(NO_INIT), mState(IDLE)
5274{
5275 LOGV("Constructor %p", this);
5276 int lStatus;
5277 sp<ThreadBase> thread = mThread.promote();
5278 if (thread == 0) {
5279 return;
5280 }
5281 PlaybackThread *p = (PlaybackThread *)thread.get();
5282
5283 memcpy(&mDescriptor, desc, sizeof(effect_descriptor_t));
5284
5285 // create effect engine from effect factory
Eric Laurent53334cd2010-06-23 17:38:20 -07005286 mStatus = EffectCreate(&desc->uuid, sessionId, p->id(), &mEffectInterface);
5287
Eric Laurent65b65452010-06-01 23:49:17 -07005288 if (mStatus != NO_ERROR) {
5289 return;
5290 }
5291 lStatus = init();
5292 if (lStatus < 0) {
5293 mStatus = lStatus;
5294 goto Error;
5295 }
5296
5297 LOGV("Constructor success name %s, Interface %p", mDescriptor.name, mEffectInterface);
5298 return;
5299Error:
5300 EffectRelease(mEffectInterface);
5301 mEffectInterface = NULL;
5302 LOGV("Constructor Error %d", mStatus);
5303}
5304
5305AudioFlinger::EffectModule::~EffectModule()
5306{
5307 LOGV("Destructor %p", this);
5308 if (mEffectInterface != NULL) {
5309 // release effect engine
5310 EffectRelease(mEffectInterface);
5311 }
5312}
5313
5314status_t AudioFlinger::EffectModule::addHandle(sp<EffectHandle>& handle)
5315{
5316 status_t status;
5317
5318 Mutex::Autolock _l(mLock);
5319 // First handle in mHandles has highest priority and controls the effect module
5320 int priority = handle->priority();
5321 size_t size = mHandles.size();
5322 sp<EffectHandle> h;
5323 size_t i;
5324 for (i = 0; i < size; i++) {
5325 h = mHandles[i].promote();
5326 if (h == 0) continue;
5327 if (h->priority() <= priority) break;
5328 }
5329 // if inserted in first place, move effect control from previous owner to this handle
5330 if (i == 0) {
5331 if (h != 0) {
5332 h->setControl(false, true);
5333 }
5334 handle->setControl(true, false);
5335 status = NO_ERROR;
5336 } else {
5337 status = ALREADY_EXISTS;
5338 }
5339 mHandles.insertAt(handle, i);
5340 return status;
5341}
5342
5343size_t AudioFlinger::EffectModule::removeHandle(const wp<EffectHandle>& handle)
5344{
5345 Mutex::Autolock _l(mLock);
5346 size_t size = mHandles.size();
5347 size_t i;
5348 for (i = 0; i < size; i++) {
5349 if (mHandles[i] == handle) break;
5350 }
5351 if (i == size) {
5352 return size;
5353 }
5354 mHandles.removeAt(i);
5355 size = mHandles.size();
5356 // if removed from first place, move effect control from this handle to next in line
5357 if (i == 0 && size != 0) {
5358 sp<EffectHandle> h = mHandles[0].promote();
5359 if (h != 0) {
5360 h->setControl(true, true);
5361 }
5362 }
5363
Eric Laurent4fd3ecc2010-09-28 14:09:57 -07005364 // Release effect engine here so that it is done immediately. Otherwise it will be released
5365 // by the destructor when the last strong reference on the this object is released which can
5366 // happen after next process is called on this effect.
5367 if (size == 0 && mEffectInterface != NULL) {
5368 // release effect engine
5369 EffectRelease(mEffectInterface);
5370 mEffectInterface = NULL;
5371 }
5372
Eric Laurent65b65452010-06-01 23:49:17 -07005373 return size;
5374}
5375
5376void AudioFlinger::EffectModule::disconnect(const wp<EffectHandle>& handle)
5377{
5378 // keep a strong reference on this EffectModule to avoid calling the
5379 // destructor before we exit
5380 sp<EffectModule> keep(this);
Eric Laurent53334cd2010-06-23 17:38:20 -07005381 {
5382 sp<ThreadBase> thread = mThread.promote();
5383 if (thread != 0) {
Eric Laurent65b65452010-06-01 23:49:17 -07005384 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
Eric Laurent53334cd2010-06-23 17:38:20 -07005385 playbackThread->disconnectEffect(keep, handle);
Eric Laurent65b65452010-06-01 23:49:17 -07005386 }
5387 }
5388}
5389
Eric Laurent7d850f22010-07-09 13:34:17 -07005390void AudioFlinger::EffectModule::updateState() {
5391 Mutex::Autolock _l(mLock);
5392
5393 switch (mState) {
5394 case RESTART:
5395 reset_l();
5396 // FALL THROUGH
5397
5398 case STARTING:
5399 // clear auxiliary effect input buffer for next accumulation
5400 if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
5401 memset(mConfig.inputCfg.buffer.raw,
5402 0,
5403 mConfig.inputCfg.buffer.frameCount*sizeof(int32_t));
5404 }
5405 start_l();
5406 mState = ACTIVE;
5407 break;
5408 case STOPPING:
5409 stop_l();
5410 mDisableWaitCnt = mMaxDisableWaitCnt;
5411 mState = STOPPED;
5412 break;
5413 case STOPPED:
5414 // mDisableWaitCnt is forced to 1 by process() when the engine indicates the end of the
5415 // turn off sequence.
5416 if (--mDisableWaitCnt == 0) {
5417 reset_l();
5418 mState = IDLE;
5419 }
5420 break;
5421 default: //IDLE , ACTIVE
5422 break;
5423 }
5424}
5425
Eric Laurent65b65452010-06-01 23:49:17 -07005426void AudioFlinger::EffectModule::process()
5427{
5428 Mutex::Autolock _l(mLock);
5429
Eric Laurent7d850f22010-07-09 13:34:17 -07005430 if (mEffectInterface == NULL ||
5431 mConfig.inputCfg.buffer.raw == NULL ||
5432 mConfig.outputCfg.buffer.raw == NULL) {
Eric Laurent65b65452010-06-01 23:49:17 -07005433 return;
5434 }
5435
Eric Laurenta92ebfa2010-08-31 13:50:07 -07005436 if (isProcessEnabled()) {
Eric Laurent65b65452010-06-01 23:49:17 -07005437 // do 32 bit to 16 bit conversion for auxiliary effect input buffer
5438 if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
5439 AudioMixer::ditherAndClamp(mConfig.inputCfg.buffer.s32,
5440 mConfig.inputCfg.buffer.s32,
Eric Laurent8ed6ed02010-07-13 04:45:46 -07005441 mConfig.inputCfg.buffer.frameCount/2);
Eric Laurent65b65452010-06-01 23:49:17 -07005442 }
5443
Eric Laurent65b65452010-06-01 23:49:17 -07005444 // do the actual processing in the effect engine
Eric Laurent7d850f22010-07-09 13:34:17 -07005445 int ret = (*mEffectInterface)->process(mEffectInterface,
5446 &mConfig.inputCfg.buffer,
5447 &mConfig.outputCfg.buffer);
5448
5449 // force transition to IDLE state when engine is ready
5450 if (mState == STOPPED && ret == -ENODATA) {
5451 mDisableWaitCnt = 1;
5452 }
Eric Laurent65b65452010-06-01 23:49:17 -07005453
5454 // clear auxiliary effect input buffer for next accumulation
5455 if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
Eric Laurent67b5ed32011-01-19 18:36:13 -08005456 memset(mConfig.inputCfg.buffer.raw, 0,
5457 mConfig.inputCfg.buffer.frameCount*sizeof(int32_t));
Eric Laurent65b65452010-06-01 23:49:17 -07005458 }
5459 } else if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_INSERT &&
Eric Laurent67b5ed32011-01-19 18:36:13 -08005460 mConfig.inputCfg.buffer.raw != mConfig.outputCfg.buffer.raw) {
5461 // If an insert effect is idle and input buffer is different from output buffer,
5462 // accumulate input onto output
Eric Laurent65b65452010-06-01 23:49:17 -07005463 sp<EffectChain> chain = mChain.promote();
Eric Laurent90681d62011-05-09 12:09:06 -07005464 if (chain != 0 && chain->activeTrackCnt() != 0) {
Eric Laurent67b5ed32011-01-19 18:36:13 -08005465 size_t frameCnt = mConfig.inputCfg.buffer.frameCount * 2; //always stereo here
5466 int16_t *in = mConfig.inputCfg.buffer.s16;
5467 int16_t *out = mConfig.outputCfg.buffer.s16;
5468 for (size_t i = 0; i < frameCnt; i++) {
5469 out[i] = clamp16((int32_t)out[i] + (int32_t)in[i]);
Eric Laurent65b65452010-06-01 23:49:17 -07005470 }
Eric Laurent65b65452010-06-01 23:49:17 -07005471 }
5472 }
5473}
5474
Eric Laurentdf9b81c2010-07-02 08:12:41 -07005475void AudioFlinger::EffectModule::reset_l()
Eric Laurent65b65452010-06-01 23:49:17 -07005476{
5477 if (mEffectInterface == NULL) {
5478 return;
5479 }
5480 (*mEffectInterface)->command(mEffectInterface, EFFECT_CMD_RESET, 0, NULL, 0, NULL);
5481}
5482
5483status_t AudioFlinger::EffectModule::configure()
5484{
5485 uint32_t channels;
5486 if (mEffectInterface == NULL) {
5487 return NO_INIT;
5488 }
5489
5490 sp<ThreadBase> thread = mThread.promote();
5491 if (thread == 0) {
5492 return DEAD_OBJECT;
5493 }
5494
5495 // TODO: handle configuration of effects replacing track process
5496 if (thread->channelCount() == 1) {
Eric Laurent0fb66c22011-05-17 19:16:02 -07005497 channels = AUDIO_CHANNEL_OUT_MONO;
Eric Laurent65b65452010-06-01 23:49:17 -07005498 } else {
Eric Laurent0fb66c22011-05-17 19:16:02 -07005499 channels = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurent65b65452010-06-01 23:49:17 -07005500 }
5501
5502 if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
Eric Laurent0fb66c22011-05-17 19:16:02 -07005503 mConfig.inputCfg.channels = AUDIO_CHANNEL_OUT_MONO;
Eric Laurent65b65452010-06-01 23:49:17 -07005504 } else {
5505 mConfig.inputCfg.channels = channels;
5506 }
5507 mConfig.outputCfg.channels = channels;
Eric Laurent0fb66c22011-05-17 19:16:02 -07005508 mConfig.inputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
5509 mConfig.outputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
Eric Laurent65b65452010-06-01 23:49:17 -07005510 mConfig.inputCfg.samplingRate = thread->sampleRate();
5511 mConfig.outputCfg.samplingRate = mConfig.inputCfg.samplingRate;
5512 mConfig.inputCfg.bufferProvider.cookie = NULL;
5513 mConfig.inputCfg.bufferProvider.getBuffer = NULL;
5514 mConfig.inputCfg.bufferProvider.releaseBuffer = NULL;
5515 mConfig.outputCfg.bufferProvider.cookie = NULL;
5516 mConfig.outputCfg.bufferProvider.getBuffer = NULL;
5517 mConfig.outputCfg.bufferProvider.releaseBuffer = NULL;
5518 mConfig.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ;
5519 // Insert effect:
Dima Zavin24fc2fb2011-04-19 22:30:36 -07005520 // - in session AUDIO_SESSION_OUTPUT_MIX or AUDIO_SESSION_OUTPUT_STAGE,
Eric Laurent8ed6ed02010-07-13 04:45:46 -07005521 // always overwrites output buffer: input buffer == output buffer
Eric Laurent65b65452010-06-01 23:49:17 -07005522 // - in other sessions:
5523 // last effect in the chain accumulates in output buffer: input buffer != output buffer
5524 // other effect: overwrites output buffer: input buffer == output buffer
5525 // Auxiliary effect:
5526 // accumulates in output buffer: input buffer != output buffer
5527 // Therefore: accumulate <=> input buffer != output buffer
5528 if (mConfig.inputCfg.buffer.raw != mConfig.outputCfg.buffer.raw) {
5529 mConfig.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_ACCUMULATE;
5530 } else {
5531 mConfig.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_WRITE;
5532 }
5533 mConfig.inputCfg.mask = EFFECT_CONFIG_ALL;
5534 mConfig.outputCfg.mask = EFFECT_CONFIG_ALL;
5535 mConfig.inputCfg.buffer.frameCount = thread->frameCount();
5536 mConfig.outputCfg.buffer.frameCount = mConfig.inputCfg.buffer.frameCount;
5537
Eric Laurent8ed6ed02010-07-13 04:45:46 -07005538 LOGV("configure() %p thread %p buffer %p framecount %d",
5539 this, thread.get(), mConfig.inputCfg.buffer.raw, mConfig.inputCfg.buffer.frameCount);
5540
Eric Laurent65b65452010-06-01 23:49:17 -07005541 status_t cmdStatus;
Eric Laurenta4c72ac2010-07-28 05:40:18 -07005542 uint32_t size = sizeof(int);
5543 status_t status = (*mEffectInterface)->command(mEffectInterface,
5544 EFFECT_CMD_CONFIGURE,
5545 sizeof(effect_config_t),
5546 &mConfig,
5547 &size,
5548 &cmdStatus);
Eric Laurent65b65452010-06-01 23:49:17 -07005549 if (status == 0) {
5550 status = cmdStatus;
5551 }
Eric Laurent7d850f22010-07-09 13:34:17 -07005552
5553 mMaxDisableWaitCnt = (MAX_DISABLE_TIME_MS * mConfig.outputCfg.samplingRate) /
5554 (1000 * mConfig.outputCfg.buffer.frameCount);
5555
Eric Laurent65b65452010-06-01 23:49:17 -07005556 return status;
5557}
5558
5559status_t AudioFlinger::EffectModule::init()
5560{
Eric Laurentdf9b81c2010-07-02 08:12:41 -07005561 Mutex::Autolock _l(mLock);
Eric Laurent65b65452010-06-01 23:49:17 -07005562 if (mEffectInterface == NULL) {
5563 return NO_INIT;
5564 }
5565 status_t cmdStatus;
Eric Laurenta4c72ac2010-07-28 05:40:18 -07005566 uint32_t size = sizeof(status_t);
5567 status_t status = (*mEffectInterface)->command(mEffectInterface,
5568 EFFECT_CMD_INIT,
5569 0,
5570 NULL,
5571 &size,
5572 &cmdStatus);
Eric Laurent65b65452010-06-01 23:49:17 -07005573 if (status == 0) {
5574 status = cmdStatus;
5575 }
5576 return status;
5577}
5578
Eric Laurentdf9b81c2010-07-02 08:12:41 -07005579status_t AudioFlinger::EffectModule::start_l()
Eric Laurent65b65452010-06-01 23:49:17 -07005580{
5581 if (mEffectInterface == NULL) {
5582 return NO_INIT;
5583 }
5584 status_t cmdStatus;
Eric Laurenta4c72ac2010-07-28 05:40:18 -07005585 uint32_t size = sizeof(status_t);
5586 status_t status = (*mEffectInterface)->command(mEffectInterface,
5587 EFFECT_CMD_ENABLE,
5588 0,
5589 NULL,
5590 &size,
5591 &cmdStatus);
Eric Laurent65b65452010-06-01 23:49:17 -07005592 if (status == 0) {
5593 status = cmdStatus;
5594 }
5595 return status;
5596}
5597
Eric Laurentdf9b81c2010-07-02 08:12:41 -07005598status_t AudioFlinger::EffectModule::stop_l()
Eric Laurent65b65452010-06-01 23:49:17 -07005599{
5600 if (mEffectInterface == NULL) {
5601 return NO_INIT;
5602 }
5603 status_t cmdStatus;
Eric Laurenta4c72ac2010-07-28 05:40:18 -07005604 uint32_t size = sizeof(status_t);
5605 status_t status = (*mEffectInterface)->command(mEffectInterface,
5606 EFFECT_CMD_DISABLE,
5607 0,
5608 NULL,
5609 &size,
5610 &cmdStatus);
Eric Laurent65b65452010-06-01 23:49:17 -07005611 if (status == 0) {
5612 status = cmdStatus;
5613 }
5614 return status;
5615}
5616
Eric Laurenta4c72ac2010-07-28 05:40:18 -07005617status_t AudioFlinger::EffectModule::command(uint32_t cmdCode,
5618 uint32_t cmdSize,
5619 void *pCmdData,
5620 uint32_t *replySize,
5621 void *pReplyData)
Eric Laurent65b65452010-06-01 23:49:17 -07005622{
Eric Laurentdf9b81c2010-07-02 08:12:41 -07005623 Mutex::Autolock _l(mLock);
5624// LOGV("command(), cmdCode: %d, mEffectInterface: %p", cmdCode, mEffectInterface);
Eric Laurent65b65452010-06-01 23:49:17 -07005625
5626 if (mEffectInterface == NULL) {
5627 return NO_INIT;
5628 }
Eric Laurenta4c72ac2010-07-28 05:40:18 -07005629 status_t status = (*mEffectInterface)->command(mEffectInterface,
5630 cmdCode,
5631 cmdSize,
5632 pCmdData,
5633 replySize,
5634 pReplyData);
Eric Laurent65b65452010-06-01 23:49:17 -07005635 if (cmdCode != EFFECT_CMD_GET_PARAM && status == NO_ERROR) {
Eric Laurenta4c72ac2010-07-28 05:40:18 -07005636 uint32_t size = (replySize == NULL) ? 0 : *replySize;
Eric Laurent65b65452010-06-01 23:49:17 -07005637 for (size_t i = 1; i < mHandles.size(); i++) {
5638 sp<EffectHandle> h = mHandles[i].promote();
5639 if (h != 0) {
5640 h->commandExecuted(cmdCode, cmdSize, pCmdData, size, pReplyData);
5641 }
5642 }
5643 }
5644 return status;
5645}
5646
5647status_t AudioFlinger::EffectModule::setEnabled(bool enabled)
5648{
5649 Mutex::Autolock _l(mLock);
5650 LOGV("setEnabled %p enabled %d", this, enabled);
5651
5652 if (enabled != isEnabled()) {
5653 switch (mState) {
5654 // going from disabled to enabled
5655 case IDLE:
Eric Laurent7d850f22010-07-09 13:34:17 -07005656 mState = STARTING;
5657 break;
5658 case STOPPED:
5659 mState = RESTART;
Eric Laurent65b65452010-06-01 23:49:17 -07005660 break;
5661 case STOPPING:
5662 mState = ACTIVE;
5663 break;
Eric Laurent65b65452010-06-01 23:49:17 -07005664
5665 // going from enabled to disabled
Eric Laurent7d850f22010-07-09 13:34:17 -07005666 case RESTART:
Eric Laurenta92ebfa2010-08-31 13:50:07 -07005667 mState = STOPPED;
5668 break;
Eric Laurent65b65452010-06-01 23:49:17 -07005669 case STARTING:
Eric Laurent7d850f22010-07-09 13:34:17 -07005670 mState = IDLE;
Eric Laurent65b65452010-06-01 23:49:17 -07005671 break;
5672 case ACTIVE:
5673 mState = STOPPING;
5674 break;
5675 }
5676 for (size_t i = 1; i < mHandles.size(); i++) {
5677 sp<EffectHandle> h = mHandles[i].promote();
5678 if (h != 0) {
5679 h->setEnabled(enabled);
5680 }
5681 }
5682 }
5683 return NO_ERROR;
5684}
5685
5686bool AudioFlinger::EffectModule::isEnabled()
5687{
5688 switch (mState) {
Eric Laurent7d850f22010-07-09 13:34:17 -07005689 case RESTART:
Eric Laurent65b65452010-06-01 23:49:17 -07005690 case STARTING:
5691 case ACTIVE:
5692 return true;
5693 case IDLE:
5694 case STOPPING:
5695 case STOPPED:
5696 default:
5697 return false;
5698 }
5699}
5700
Eric Laurenta92ebfa2010-08-31 13:50:07 -07005701bool AudioFlinger::EffectModule::isProcessEnabled()
5702{
5703 switch (mState) {
5704 case RESTART:
5705 case ACTIVE:
5706 case STOPPING:
5707 case STOPPED:
5708 return true;
5709 case IDLE:
5710 case STARTING:
5711 default:
5712 return false;
5713 }
5714}
5715
Eric Laurent65b65452010-06-01 23:49:17 -07005716status_t AudioFlinger::EffectModule::setVolume(uint32_t *left, uint32_t *right, bool controller)
5717{
Eric Laurentdf9b81c2010-07-02 08:12:41 -07005718 Mutex::Autolock _l(mLock);
Eric Laurent65b65452010-06-01 23:49:17 -07005719 status_t status = NO_ERROR;
5720
5721 // Send volume indication if EFFECT_FLAG_VOLUME_IND is set and read back altered volume
5722 // if controller flag is set (Note that controller == TRUE => EFFECT_FLAG_VOLUME_CTRL set)
Eric Laurenta92ebfa2010-08-31 13:50:07 -07005723 if (isProcessEnabled() &&
Eric Laurent0d7e0482010-07-19 06:24:46 -07005724 ((mDescriptor.flags & EFFECT_FLAG_VOLUME_MASK) == EFFECT_FLAG_VOLUME_CTRL ||
5725 (mDescriptor.flags & EFFECT_FLAG_VOLUME_MASK) == EFFECT_FLAG_VOLUME_IND)) {
Eric Laurent65b65452010-06-01 23:49:17 -07005726 status_t cmdStatus;
5727 uint32_t volume[2];
5728 uint32_t *pVolume = NULL;
Eric Laurenta4c72ac2010-07-28 05:40:18 -07005729 uint32_t size = sizeof(volume);
Eric Laurent65b65452010-06-01 23:49:17 -07005730 volume[0] = *left;
5731 volume[1] = *right;
5732 if (controller) {
5733 pVolume = volume;
5734 }
Eric Laurenta4c72ac2010-07-28 05:40:18 -07005735 status = (*mEffectInterface)->command(mEffectInterface,
5736 EFFECT_CMD_SET_VOLUME,
5737 size,
5738 volume,
5739 &size,
5740 pVolume);
Eric Laurent65b65452010-06-01 23:49:17 -07005741 if (controller && status == NO_ERROR && size == sizeof(volume)) {
5742 *left = volume[0];
5743 *right = volume[1];
5744 }
5745 }
5746 return status;
5747}
5748
5749status_t AudioFlinger::EffectModule::setDevice(uint32_t device)
5750{
Eric Laurentdf9b81c2010-07-02 08:12:41 -07005751 Mutex::Autolock _l(mLock);
Eric Laurent65b65452010-06-01 23:49:17 -07005752 status_t status = NO_ERROR;
Eric Laurent53334cd2010-06-23 17:38:20 -07005753 if ((mDescriptor.flags & EFFECT_FLAG_DEVICE_MASK) == EFFECT_FLAG_DEVICE_IND) {
Eric Laurent65b65452010-06-01 23:49:17 -07005754 status_t cmdStatus;
Eric Laurenta4c72ac2010-07-28 05:40:18 -07005755 uint32_t size = sizeof(status_t);
5756 status = (*mEffectInterface)->command(mEffectInterface,
5757 EFFECT_CMD_SET_DEVICE,
5758 sizeof(uint32_t),
5759 &device,
5760 &size,
5761 &cmdStatus);
Eric Laurent65b65452010-06-01 23:49:17 -07005762 if (status == NO_ERROR) {
5763 status = cmdStatus;
5764 }
5765 }
5766 return status;
5767}
5768
Eric Laurent53334cd2010-06-23 17:38:20 -07005769status_t AudioFlinger::EffectModule::setMode(uint32_t mode)
5770{
Eric Laurentdf9b81c2010-07-02 08:12:41 -07005771 Mutex::Autolock _l(mLock);
Eric Laurent53334cd2010-06-23 17:38:20 -07005772 status_t status = NO_ERROR;
5773 if ((mDescriptor.flags & EFFECT_FLAG_AUDIO_MODE_MASK) == EFFECT_FLAG_AUDIO_MODE_IND) {
Eric Laurent53334cd2010-06-23 17:38:20 -07005774 status_t cmdStatus;
Eric Laurenta4c72ac2010-07-28 05:40:18 -07005775 uint32_t size = sizeof(status_t);
5776 status = (*mEffectInterface)->command(mEffectInterface,
5777 EFFECT_CMD_SET_AUDIO_MODE,
5778 sizeof(int),
Eric Laurent0fb66c22011-05-17 19:16:02 -07005779 &mode,
Eric Laurenta4c72ac2010-07-28 05:40:18 -07005780 &size,
5781 &cmdStatus);
Eric Laurent53334cd2010-06-23 17:38:20 -07005782 if (status == NO_ERROR) {
5783 status = cmdStatus;
5784 }
5785 }
5786 return status;
5787}
5788
Eric Laurent65b65452010-06-01 23:49:17 -07005789status_t AudioFlinger::EffectModule::dump(int fd, const Vector<String16>& args)
5790{
5791 const size_t SIZE = 256;
5792 char buffer[SIZE];
5793 String8 result;
5794
5795 snprintf(buffer, SIZE, "\tEffect ID %d:\n", mId);
5796 result.append(buffer);
5797
5798 bool locked = tryLock(mLock);
5799 // failed to lock - AudioFlinger is probably deadlocked
5800 if (!locked) {
5801 result.append("\t\tCould not lock Fx mutex:\n");
5802 }
5803
5804 result.append("\t\tSession Status State Engine:\n");
5805 snprintf(buffer, SIZE, "\t\t%05d %03d %03d 0x%08x\n",
5806 mSessionId, mStatus, mState, (uint32_t)mEffectInterface);
5807 result.append(buffer);
5808
5809 result.append("\t\tDescriptor:\n");
5810 snprintf(buffer, SIZE, "\t\t- UUID: %08X-%04X-%04X-%04X-%02X%02X%02X%02X%02X%02X\n",
5811 mDescriptor.uuid.timeLow, mDescriptor.uuid.timeMid, mDescriptor.uuid.timeHiAndVersion,
5812 mDescriptor.uuid.clockSeq, mDescriptor.uuid.node[0], mDescriptor.uuid.node[1],mDescriptor.uuid.node[2],
5813 mDescriptor.uuid.node[3],mDescriptor.uuid.node[4],mDescriptor.uuid.node[5]);
5814 result.append(buffer);
5815 snprintf(buffer, SIZE, "\t\t- TYPE: %08X-%04X-%04X-%04X-%02X%02X%02X%02X%02X%02X\n",
5816 mDescriptor.type.timeLow, mDescriptor.type.timeMid, mDescriptor.type.timeHiAndVersion,
5817 mDescriptor.type.clockSeq, mDescriptor.type.node[0], mDescriptor.type.node[1],mDescriptor.type.node[2],
5818 mDescriptor.type.node[3],mDescriptor.type.node[4],mDescriptor.type.node[5]);
5819 result.append(buffer);
Eric Laurent0fb66c22011-05-17 19:16:02 -07005820 snprintf(buffer, SIZE, "\t\t- apiVersion: %08X\n\t\t- flags: %08X\n",
Eric Laurent65b65452010-06-01 23:49:17 -07005821 mDescriptor.apiVersion,
5822 mDescriptor.flags);
5823 result.append(buffer);
5824 snprintf(buffer, SIZE, "\t\t- name: %s\n",
5825 mDescriptor.name);
5826 result.append(buffer);
5827 snprintf(buffer, SIZE, "\t\t- implementor: %s\n",
5828 mDescriptor.implementor);
5829 result.append(buffer);
5830
5831 result.append("\t\t- Input configuration:\n");
5832 result.append("\t\t\tBuffer Frames Smp rate Channels Format\n");
5833 snprintf(buffer, SIZE, "\t\t\t0x%08x %05d %05d %08x %d\n",
5834 (uint32_t)mConfig.inputCfg.buffer.raw,
5835 mConfig.inputCfg.buffer.frameCount,
5836 mConfig.inputCfg.samplingRate,
5837 mConfig.inputCfg.channels,
5838 mConfig.inputCfg.format);
5839 result.append(buffer);
5840
5841 result.append("\t\t- Output configuration:\n");
5842 result.append("\t\t\tBuffer Frames Smp rate Channels Format\n");
5843 snprintf(buffer, SIZE, "\t\t\t0x%08x %05d %05d %08x %d\n",
5844 (uint32_t)mConfig.outputCfg.buffer.raw,
5845 mConfig.outputCfg.buffer.frameCount,
5846 mConfig.outputCfg.samplingRate,
5847 mConfig.outputCfg.channels,
5848 mConfig.outputCfg.format);
5849 result.append(buffer);
5850
5851 snprintf(buffer, SIZE, "\t\t%d Clients:\n", mHandles.size());
5852 result.append(buffer);
5853 result.append("\t\t\tPid Priority Ctrl Locked client server\n");
5854 for (size_t i = 0; i < mHandles.size(); ++i) {
5855 sp<EffectHandle> handle = mHandles[i].promote();
5856 if (handle != 0) {
5857 handle->dump(buffer, SIZE);
5858 result.append(buffer);
5859 }
5860 }
5861
5862 result.append("\n");
5863
5864 write(fd, result.string(), result.length());
5865
5866 if (locked) {
5867 mLock.unlock();
5868 }
5869
5870 return NO_ERROR;
5871}
5872
5873// ----------------------------------------------------------------------------
5874// EffectHandle implementation
5875// ----------------------------------------------------------------------------
5876
5877#undef LOG_TAG
5878#define LOG_TAG "AudioFlinger::EffectHandle"
5879
5880AudioFlinger::EffectHandle::EffectHandle(const sp<EffectModule>& effect,
5881 const sp<AudioFlinger::Client>& client,
5882 const sp<IEffectClient>& effectClient,
5883 int32_t priority)
5884 : BnEffect(),
5885 mEffect(effect), mEffectClient(effectClient), mClient(client), mPriority(priority), mHasControl(false)
5886{
5887 LOGV("constructor %p", this);
5888
5889 int bufOffset = ((sizeof(effect_param_cblk_t) - 1) / sizeof(int) + 1) * sizeof(int);
5890 mCblkMemory = client->heap()->allocate(EFFECT_PARAM_BUFFER_SIZE + bufOffset);
5891 if (mCblkMemory != 0) {
5892 mCblk = static_cast<effect_param_cblk_t *>(mCblkMemory->pointer());
5893
5894 if (mCblk) {
5895 new(mCblk) effect_param_cblk_t();
5896 mBuffer = (uint8_t *)mCblk + bufOffset;
5897 }
5898 } else {
5899 LOGE("not enough memory for Effect size=%u", EFFECT_PARAM_BUFFER_SIZE + sizeof(effect_param_cblk_t));
5900 return;
5901 }
5902}
5903
5904AudioFlinger::EffectHandle::~EffectHandle()
5905{
5906 LOGV("Destructor %p", this);
5907 disconnect();
5908}
5909
5910status_t AudioFlinger::EffectHandle::enable()
5911{
5912 if (!mHasControl) return INVALID_OPERATION;
5913 if (mEffect == 0) return DEAD_OBJECT;
5914
5915 return mEffect->setEnabled(true);
5916}
5917
5918status_t AudioFlinger::EffectHandle::disable()
5919{
5920 if (!mHasControl) return INVALID_OPERATION;
5921 if (mEffect == NULL) return DEAD_OBJECT;
5922
5923 return mEffect->setEnabled(false);
5924}
5925
5926void AudioFlinger::EffectHandle::disconnect()
5927{
5928 if (mEffect == 0) {
5929 return;
5930 }
5931 mEffect->disconnect(this);
5932 // release sp on module => module destructor can be called now
5933 mEffect.clear();
5934 if (mCblk) {
5935 mCblk->~effect_param_cblk_t(); // destroy our shared-structure.
5936 }
5937 mCblkMemory.clear(); // and free the shared memory
5938 if (mClient != 0) {
5939 Mutex::Autolock _l(mClient->audioFlinger()->mLock);
5940 mClient.clear();
5941 }
5942}
5943
Eric Laurenta4c72ac2010-07-28 05:40:18 -07005944status_t AudioFlinger::EffectHandle::command(uint32_t cmdCode,
5945 uint32_t cmdSize,
5946 void *pCmdData,
5947 uint32_t *replySize,
5948 void *pReplyData)
Eric Laurent65b65452010-06-01 23:49:17 -07005949{
Eric Laurenta4c72ac2010-07-28 05:40:18 -07005950// LOGV("command(), cmdCode: %d, mHasControl: %d, mEffect: %p",
5951// cmdCode, mHasControl, (mEffect == 0) ? 0 : mEffect.get());
Eric Laurent65b65452010-06-01 23:49:17 -07005952
5953 // only get parameter command is permitted for applications not controlling the effect
5954 if (!mHasControl && cmdCode != EFFECT_CMD_GET_PARAM) {
5955 return INVALID_OPERATION;
5956 }
5957 if (mEffect == 0) return DEAD_OBJECT;
5958
5959 // handle commands that are not forwarded transparently to effect engine
5960 if (cmdCode == EFFECT_CMD_SET_PARAM_COMMIT) {
5961 // No need to trylock() here as this function is executed in the binder thread serving a particular client process:
5962 // no risk to block the whole media server process or mixer threads is we are stuck here
5963 Mutex::Autolock _l(mCblk->lock);
5964 if (mCblk->clientIndex > EFFECT_PARAM_BUFFER_SIZE ||
5965 mCblk->serverIndex > EFFECT_PARAM_BUFFER_SIZE) {
5966 mCblk->serverIndex = 0;
5967 mCblk->clientIndex = 0;
5968 return BAD_VALUE;
5969 }
5970 status_t status = NO_ERROR;
5971 while (mCblk->serverIndex < mCblk->clientIndex) {
5972 int reply;
Eric Laurenta4c72ac2010-07-28 05:40:18 -07005973 uint32_t rsize = sizeof(int);
Eric Laurent65b65452010-06-01 23:49:17 -07005974 int *p = (int *)(mBuffer + mCblk->serverIndex);
5975 int size = *p++;
Eric Laurent53334cd2010-06-23 17:38:20 -07005976 if (((uint8_t *)p + size) > mBuffer + mCblk->clientIndex) {
5977 LOGW("command(): invalid parameter block size");
5978 break;
5979 }
Eric Laurent65b65452010-06-01 23:49:17 -07005980 effect_param_t *param = (effect_param_t *)p;
Eric Laurent53334cd2010-06-23 17:38:20 -07005981 if (param->psize == 0 || param->vsize == 0) {
5982 LOGW("command(): null parameter or value size");
5983 mCblk->serverIndex += size;
5984 continue;
5985 }
Eric Laurenta4c72ac2010-07-28 05:40:18 -07005986 uint32_t psize = sizeof(effect_param_t) +
5987 ((param->psize - 1) / sizeof(int) + 1) * sizeof(int) +
5988 param->vsize;
5989 status_t ret = mEffect->command(EFFECT_CMD_SET_PARAM,
5990 psize,
5991 p,
5992 &rsize,
5993 &reply);
Eric Laurente65280c2010-09-02 11:56:55 -07005994 // stop at first error encountered
5995 if (ret != NO_ERROR) {
Eric Laurent65b65452010-06-01 23:49:17 -07005996 status = ret;
Eric Laurente65280c2010-09-02 11:56:55 -07005997 *(int *)pReplyData = reply;
5998 break;
5999 } else if (reply != NO_ERROR) {
6000 *(int *)pReplyData = reply;
6001 break;
Eric Laurent65b65452010-06-01 23:49:17 -07006002 }
6003 mCblk->serverIndex += size;
6004 }
6005 mCblk->serverIndex = 0;
6006 mCblk->clientIndex = 0;
6007 return status;
6008 } else if (cmdCode == EFFECT_CMD_ENABLE) {
Eric Laurente65280c2010-09-02 11:56:55 -07006009 *(int *)pReplyData = NO_ERROR;
Eric Laurent65b65452010-06-01 23:49:17 -07006010 return enable();
6011 } else if (cmdCode == EFFECT_CMD_DISABLE) {
Eric Laurente65280c2010-09-02 11:56:55 -07006012 *(int *)pReplyData = NO_ERROR;
Eric Laurent65b65452010-06-01 23:49:17 -07006013 return disable();
6014 }
6015
6016 return mEffect->command(cmdCode, cmdSize, pCmdData, replySize, pReplyData);
6017}
6018
6019sp<IMemory> AudioFlinger::EffectHandle::getCblk() const {
6020 return mCblkMemory;
6021}
6022
6023void AudioFlinger::EffectHandle::setControl(bool hasControl, bool signal)
6024{
6025 LOGV("setControl %p control %d", this, hasControl);
6026
6027 mHasControl = hasControl;
6028 if (signal && mEffectClient != 0) {
6029 mEffectClient->controlStatusChanged(hasControl);
6030 }
6031}
6032
Eric Laurenta4c72ac2010-07-28 05:40:18 -07006033void AudioFlinger::EffectHandle::commandExecuted(uint32_t cmdCode,
6034 uint32_t cmdSize,
6035 void *pCmdData,
6036 uint32_t replySize,
6037 void *pReplyData)
Eric Laurent65b65452010-06-01 23:49:17 -07006038{
6039 if (mEffectClient != 0) {
6040 mEffectClient->commandExecuted(cmdCode, cmdSize, pCmdData, replySize, pReplyData);
6041 }
6042}
6043
6044
6045
6046void AudioFlinger::EffectHandle::setEnabled(bool enabled)
6047{
6048 if (mEffectClient != 0) {
6049 mEffectClient->enableStatusChanged(enabled);
6050 }
6051}
6052
6053status_t AudioFlinger::EffectHandle::onTransact(
6054 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
6055{
6056 return BnEffect::onTransact(code, data, reply, flags);
6057}
6058
6059
6060void AudioFlinger::EffectHandle::dump(char* buffer, size_t size)
6061{
6062 bool locked = tryLock(mCblk->lock);
6063
6064 snprintf(buffer, size, "\t\t\t%05d %05d %01u %01u %05u %05u\n",
6065 (mClient == NULL) ? getpid() : mClient->pid(),
6066 mPriority,
6067 mHasControl,
6068 !locked,
6069 mCblk->clientIndex,
6070 mCblk->serverIndex
6071 );
6072
6073 if (locked) {
6074 mCblk->lock.unlock();
6075 }
6076}
6077
6078#undef LOG_TAG
6079#define LOG_TAG "AudioFlinger::EffectChain"
6080
6081AudioFlinger::EffectChain::EffectChain(const wp<ThreadBase>& wThread,
6082 int sessionId)
Eric Laurent90681d62011-05-09 12:09:06 -07006083 : mThread(wThread), mSessionId(sessionId), mActiveTrackCnt(0), mTrackCnt(0),
6084 mOwnInBuffer(false), mVolumeCtrlIdx(-1), mLeftVolume(UINT_MAX), mRightVolume(UINT_MAX),
6085 mNewLeftVolume(UINT_MAX), mNewRightVolume(UINT_MAX)
Eric Laurent65b65452010-06-01 23:49:17 -07006086{
Dima Zavin24fc2fb2011-04-19 22:30:36 -07006087 mStrategy = AudioSystem::getStrategyForStream(AUDIO_STREAM_MUSIC);
Eric Laurent65b65452010-06-01 23:49:17 -07006088}
6089
6090AudioFlinger::EffectChain::~EffectChain()
6091{
6092 if (mOwnInBuffer) {
6093 delete mInBuffer;
6094 }
6095
6096}
6097
Eric Laurent76c40f72010-07-15 12:50:15 -07006098// getEffectFromDesc_l() must be called with PlaybackThread::mLock held
6099sp<AudioFlinger::EffectModule> AudioFlinger::EffectChain::getEffectFromDesc_l(effect_descriptor_t *descriptor)
Eric Laurent65b65452010-06-01 23:49:17 -07006100{
6101 sp<EffectModule> effect;
6102 size_t size = mEffects.size();
6103
6104 for (size_t i = 0; i < size; i++) {
6105 if (memcmp(&mEffects[i]->desc().uuid, &descriptor->uuid, sizeof(effect_uuid_t)) == 0) {
6106 effect = mEffects[i];
6107 break;
6108 }
6109 }
6110 return effect;
6111}
6112
Eric Laurent76c40f72010-07-15 12:50:15 -07006113// getEffectFromId_l() must be called with PlaybackThread::mLock held
6114sp<AudioFlinger::EffectModule> AudioFlinger::EffectChain::getEffectFromId_l(int id)
Eric Laurent65b65452010-06-01 23:49:17 -07006115{
6116 sp<EffectModule> effect;
6117 size_t size = mEffects.size();
6118
6119 for (size_t i = 0; i < size; i++) {
Eric Laurent8ed6ed02010-07-13 04:45:46 -07006120 // by convention, return first effect if id provided is 0 (0 is never a valid id)
6121 if (id == 0 || mEffects[i]->id() == id) {
Eric Laurent65b65452010-06-01 23:49:17 -07006122 effect = mEffects[i];
6123 break;
6124 }
6125 }
6126 return effect;
6127}
6128
6129// Must be called with EffectChain::mLock locked
6130void AudioFlinger::EffectChain::process_l()
6131{
Eric Laurent4fd3ecc2010-09-28 14:09:57 -07006132 sp<ThreadBase> thread = mThread.promote();
6133 if (thread == 0) {
6134 LOGW("process_l(): cannot promote mixer thread");
6135 return;
6136 }
6137 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
Dima Zavin24fc2fb2011-04-19 22:30:36 -07006138 bool isGlobalSession = (mSessionId == AUDIO_SESSION_OUTPUT_MIX) ||
6139 (mSessionId == AUDIO_SESSION_OUTPUT_STAGE);
Eric Laurent4fd3ecc2010-09-28 14:09:57 -07006140 bool tracksOnSession = false;
6141 if (!isGlobalSession) {
Eric Laurent90681d62011-05-09 12:09:06 -07006142 tracksOnSession = (trackCnt() != 0);
6143 }
6144
6145 // if no track is active, input buffer must be cleared here as the mixer process
6146 // will not do it
6147 if (tracksOnSession &&
6148 activeTrackCnt() == 0) {
6149 size_t numSamples = playbackThread->frameCount() * playbackThread->channelCount();
6150 memset(mInBuffer, 0, numSamples * sizeof(int16_t));
Eric Laurent4fd3ecc2010-09-28 14:09:57 -07006151 }
6152
Eric Laurent65b65452010-06-01 23:49:17 -07006153 size_t size = mEffects.size();
Eric Laurent4fd3ecc2010-09-28 14:09:57 -07006154 // do not process effect if no track is present in same audio session
6155 if (isGlobalSession || tracksOnSession) {
6156 for (size_t i = 0; i < size; i++) {
6157 mEffects[i]->process();
6158 }
Eric Laurent65b65452010-06-01 23:49:17 -07006159 }
Eric Laurent7d850f22010-07-09 13:34:17 -07006160 for (size_t i = 0; i < size; i++) {
6161 mEffects[i]->updateState();
6162 }
Eric Laurent65b65452010-06-01 23:49:17 -07006163}
6164
Eric Laurent76c40f72010-07-15 12:50:15 -07006165// addEffect_l() must be called with PlaybackThread::mLock held
Eric Laurent8ed6ed02010-07-13 04:45:46 -07006166status_t AudioFlinger::EffectChain::addEffect_l(const sp<EffectModule>& effect)
Eric Laurent65b65452010-06-01 23:49:17 -07006167{
6168 effect_descriptor_t desc = effect->desc();
6169 uint32_t insertPref = desc.flags & EFFECT_FLAG_INSERT_MASK;
6170
6171 Mutex::Autolock _l(mLock);
Eric Laurent8ed6ed02010-07-13 04:45:46 -07006172 effect->setChain(this);
6173 sp<ThreadBase> thread = mThread.promote();
6174 if (thread == 0) {
6175 return NO_INIT;
6176 }
6177 effect->setThread(thread);
Eric Laurent65b65452010-06-01 23:49:17 -07006178
6179 if ((desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
6180 // Auxiliary effects are inserted at the beginning of mEffects vector as
6181 // they are processed first and accumulated in chain input buffer
6182 mEffects.insertAt(effect, 0);
Eric Laurent8ed6ed02010-07-13 04:45:46 -07006183
Eric Laurent65b65452010-06-01 23:49:17 -07006184 // the input buffer for auxiliary effect contains mono samples in
6185 // 32 bit format. This is to avoid saturation in AudoMixer
6186 // accumulation stage. Saturation is done in EffectModule::process() before
6187 // calling the process in effect engine
6188 size_t numSamples = thread->frameCount();
6189 int32_t *buffer = new int32_t[numSamples];
6190 memset(buffer, 0, numSamples * sizeof(int32_t));
6191 effect->setInBuffer((int16_t *)buffer);
6192 // auxiliary effects output samples to chain input buffer for further processing
6193 // by insert effects
6194 effect->setOutBuffer(mInBuffer);
6195 } else {
6196 // Insert effects are inserted at the end of mEffects vector as they are processed
6197 // after track and auxiliary effects.
Eric Laurent53334cd2010-06-23 17:38:20 -07006198 // Insert effect order as a function of indicated preference:
6199 // if EFFECT_FLAG_INSERT_EXCLUSIVE, insert in first position or reject if
6200 // another effect is present
6201 // else if EFFECT_FLAG_INSERT_FIRST, insert in first position or after the
6202 // last effect claiming first position
6203 // else if EFFECT_FLAG_INSERT_LAST, insert in last position or before the
6204 // first effect claiming last position
Eric Laurent65b65452010-06-01 23:49:17 -07006205 // else if EFFECT_FLAG_INSERT_ANY insert after first or before last
Eric Laurent53334cd2010-06-23 17:38:20 -07006206 // Reject insertion if an effect with EFFECT_FLAG_INSERT_EXCLUSIVE is
6207 // already present
Eric Laurent65b65452010-06-01 23:49:17 -07006208
6209 int size = (int)mEffects.size();
6210 int idx_insert = size;
6211 int idx_insert_first = -1;
6212 int idx_insert_last = -1;
6213
6214 for (int i = 0; i < size; i++) {
6215 effect_descriptor_t d = mEffects[i]->desc();
6216 uint32_t iMode = d.flags & EFFECT_FLAG_TYPE_MASK;
6217 uint32_t iPref = d.flags & EFFECT_FLAG_INSERT_MASK;
6218 if (iMode == EFFECT_FLAG_TYPE_INSERT) {
6219 // check invalid effect chaining combinations
6220 if (insertPref == EFFECT_FLAG_INSERT_EXCLUSIVE ||
Eric Laurent53334cd2010-06-23 17:38:20 -07006221 iPref == EFFECT_FLAG_INSERT_EXCLUSIVE) {
Eric Laurent76c40f72010-07-15 12:50:15 -07006222 LOGW("addEffect_l() could not insert effect %s: exclusive conflict with %s", desc.name, d.name);
Eric Laurent65b65452010-06-01 23:49:17 -07006223 return INVALID_OPERATION;
6224 }
Eric Laurent53334cd2010-06-23 17:38:20 -07006225 // remember position of first insert effect and by default
6226 // select this as insert position for new effect
Eric Laurent65b65452010-06-01 23:49:17 -07006227 if (idx_insert == size) {
6228 idx_insert = i;
6229 }
Eric Laurent53334cd2010-06-23 17:38:20 -07006230 // remember position of last insert effect claiming
6231 // first position
Eric Laurent65b65452010-06-01 23:49:17 -07006232 if (iPref == EFFECT_FLAG_INSERT_FIRST) {
6233 idx_insert_first = i;
6234 }
Eric Laurent53334cd2010-06-23 17:38:20 -07006235 // remember position of first insert effect claiming
6236 // last position
6237 if (iPref == EFFECT_FLAG_INSERT_LAST &&
6238 idx_insert_last == -1) {
Eric Laurent65b65452010-06-01 23:49:17 -07006239 idx_insert_last = i;
6240 }
6241 }
6242 }
6243
Eric Laurent53334cd2010-06-23 17:38:20 -07006244 // modify idx_insert from first position if needed
6245 if (insertPref == EFFECT_FLAG_INSERT_LAST) {
6246 if (idx_insert_last != -1) {
6247 idx_insert = idx_insert_last;
6248 } else {
6249 idx_insert = size;
6250 }
6251 } else {
6252 if (idx_insert_first != -1) {
6253 idx_insert = idx_insert_first + 1;
6254 }
Eric Laurent65b65452010-06-01 23:49:17 -07006255 }
6256
6257 // always read samples from chain input buffer
6258 effect->setInBuffer(mInBuffer);
6259
6260 // if last effect in the chain, output samples to chain
6261 // output buffer, otherwise to chain input buffer
6262 if (idx_insert == size) {
6263 if (idx_insert != 0) {
6264 mEffects[idx_insert-1]->setOutBuffer(mInBuffer);
6265 mEffects[idx_insert-1]->configure();
6266 }
6267 effect->setOutBuffer(mOutBuffer);
6268 } else {
6269 effect->setOutBuffer(mInBuffer);
6270 }
Eric Laurent53334cd2010-06-23 17:38:20 -07006271 mEffects.insertAt(effect, idx_insert);
Eric Laurent65b65452010-06-01 23:49:17 -07006272
Eric Laurent76c40f72010-07-15 12:50:15 -07006273 LOGV("addEffect_l() effect %p, added in chain %p at rank %d", effect.get(), this, idx_insert);
Eric Laurent65b65452010-06-01 23:49:17 -07006274 }
6275 effect->configure();
6276 return NO_ERROR;
6277}
6278
Eric Laurent76c40f72010-07-15 12:50:15 -07006279// removeEffect_l() must be called with PlaybackThread::mLock held
6280size_t AudioFlinger::EffectChain::removeEffect_l(const sp<EffectModule>& effect)
Eric Laurent65b65452010-06-01 23:49:17 -07006281{
6282 Mutex::Autolock _l(mLock);
Eric Laurent65b65452010-06-01 23:49:17 -07006283 int size = (int)mEffects.size();
6284 int i;
6285 uint32_t type = effect->desc().flags & EFFECT_FLAG_TYPE_MASK;
6286
6287 for (i = 0; i < size; i++) {
6288 if (effect == mEffects[i]) {
6289 if (type == EFFECT_FLAG_TYPE_AUXILIARY) {
6290 delete[] effect->inBuffer();
6291 } else {
6292 if (i == size - 1 && i != 0) {
6293 mEffects[i - 1]->setOutBuffer(mOutBuffer);
6294 mEffects[i - 1]->configure();
6295 }
6296 }
6297 mEffects.removeAt(i);
Eric Laurent76c40f72010-07-15 12:50:15 -07006298 LOGV("removeEffect_l() effect %p, removed from chain %p at rank %d", effect.get(), this, i);
Eric Laurent65b65452010-06-01 23:49:17 -07006299 break;
6300 }
6301 }
Eric Laurent65b65452010-06-01 23:49:17 -07006302
6303 return mEffects.size();
6304}
6305
Eric Laurent76c40f72010-07-15 12:50:15 -07006306// setDevice_l() must be called with PlaybackThread::mLock held
6307void AudioFlinger::EffectChain::setDevice_l(uint32_t device)
Eric Laurent65b65452010-06-01 23:49:17 -07006308{
6309 size_t size = mEffects.size();
6310 for (size_t i = 0; i < size; i++) {
6311 mEffects[i]->setDevice(device);
6312 }
6313}
6314
Eric Laurent76c40f72010-07-15 12:50:15 -07006315// setMode_l() must be called with PlaybackThread::mLock held
6316void AudioFlinger::EffectChain::setMode_l(uint32_t mode)
Eric Laurent53334cd2010-06-23 17:38:20 -07006317{
6318 size_t size = mEffects.size();
6319 for (size_t i = 0; i < size; i++) {
6320 mEffects[i]->setMode(mode);
6321 }
6322}
6323
Eric Laurent76c40f72010-07-15 12:50:15 -07006324// setVolume_l() must be called with PlaybackThread::mLock held
6325bool AudioFlinger::EffectChain::setVolume_l(uint32_t *left, uint32_t *right)
Eric Laurent65b65452010-06-01 23:49:17 -07006326{
6327 uint32_t newLeft = *left;
6328 uint32_t newRight = *right;
6329 bool hasControl = false;
Eric Laurent76c40f72010-07-15 12:50:15 -07006330 int ctrlIdx = -1;
6331 size_t size = mEffects.size();
Eric Laurent65b65452010-06-01 23:49:17 -07006332
Eric Laurent76c40f72010-07-15 12:50:15 -07006333 // first update volume controller
6334 for (size_t i = size; i > 0; i--) {
Eric Laurenta92ebfa2010-08-31 13:50:07 -07006335 if (mEffects[i - 1]->isProcessEnabled() &&
Eric Laurent76c40f72010-07-15 12:50:15 -07006336 (mEffects[i - 1]->desc().flags & EFFECT_FLAG_VOLUME_MASK) == EFFECT_FLAG_VOLUME_CTRL) {
6337 ctrlIdx = i - 1;
Eric Laurent0d7e0482010-07-19 06:24:46 -07006338 hasControl = true;
Eric Laurent76c40f72010-07-15 12:50:15 -07006339 break;
6340 }
6341 }
6342
6343 if (ctrlIdx == mVolumeCtrlIdx && *left == mLeftVolume && *right == mRightVolume) {
Eric Laurent0d7e0482010-07-19 06:24:46 -07006344 if (hasControl) {
6345 *left = mNewLeftVolume;
6346 *right = mNewRightVolume;
6347 }
6348 return hasControl;
Eric Laurent76c40f72010-07-15 12:50:15 -07006349 }
6350
6351 mVolumeCtrlIdx = ctrlIdx;
Eric Laurent0d7e0482010-07-19 06:24:46 -07006352 mLeftVolume = newLeft;
6353 mRightVolume = newRight;
Eric Laurent76c40f72010-07-15 12:50:15 -07006354
6355 // second get volume update from volume controller
6356 if (ctrlIdx >= 0) {
6357 mEffects[ctrlIdx]->setVolume(&newLeft, &newRight, true);
Eric Laurent0d7e0482010-07-19 06:24:46 -07006358 mNewLeftVolume = newLeft;
6359 mNewRightVolume = newRight;
Eric Laurent65b65452010-06-01 23:49:17 -07006360 }
6361 // then indicate volume to all other effects in chain.
6362 // Pass altered volume to effects before volume controller
6363 // and requested volume to effects after controller
6364 uint32_t lVol = newLeft;
6365 uint32_t rVol = newRight;
Eric Laurent76c40f72010-07-15 12:50:15 -07006366
Eric Laurent65b65452010-06-01 23:49:17 -07006367 for (size_t i = 0; i < size; i++) {
Eric Laurent76c40f72010-07-15 12:50:15 -07006368 if ((int)i == ctrlIdx) continue;
6369 // this also works for ctrlIdx == -1 when there is no volume controller
6370 if ((int)i > ctrlIdx) {
Eric Laurent65b65452010-06-01 23:49:17 -07006371 lVol = *left;
6372 rVol = *right;
6373 }
6374 mEffects[i]->setVolume(&lVol, &rVol, false);
6375 }
6376 *left = newLeft;
6377 *right = newRight;
6378
6379 return hasControl;
6380}
6381
Eric Laurent65b65452010-06-01 23:49:17 -07006382status_t AudioFlinger::EffectChain::dump(int fd, const Vector<String16>& args)
6383{
6384 const size_t SIZE = 256;
6385 char buffer[SIZE];
6386 String8 result;
6387
6388 snprintf(buffer, SIZE, "Effects for session %d:\n", mSessionId);
6389 result.append(buffer);
6390
6391 bool locked = tryLock(mLock);
6392 // failed to lock - AudioFlinger is probably deadlocked
6393 if (!locked) {
6394 result.append("\tCould not lock mutex:\n");
6395 }
6396
Eric Laurent76c40f72010-07-15 12:50:15 -07006397 result.append("\tNum fx In buffer Out buffer Active tracks:\n");
6398 snprintf(buffer, SIZE, "\t%02d 0x%08x 0x%08x %d\n",
Eric Laurent65b65452010-06-01 23:49:17 -07006399 mEffects.size(),
6400 (uint32_t)mInBuffer,
6401 (uint32_t)mOutBuffer,
Eric Laurent65b65452010-06-01 23:49:17 -07006402 mActiveTrackCnt);
6403 result.append(buffer);
6404 write(fd, result.string(), result.size());
6405
6406 for (size_t i = 0; i < mEffects.size(); ++i) {
6407 sp<EffectModule> effect = mEffects[i];
6408 if (effect != 0) {
6409 effect->dump(fd, args);
6410 }
6411 }
6412
6413 if (locked) {
6414 mLock.unlock();
6415 }
6416
6417 return NO_ERROR;
6418}
6419
6420#undef LOG_TAG
6421#define LOG_TAG "AudioFlinger"
6422
Eric Laurenta553c252009-07-17 12:17:14 -07006423// ----------------------------------------------------------------------------
6424
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07006425status_t AudioFlinger::onTransact(
6426 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
6427{
6428 return BnAudioFlinger::onTransact(code, data, reply, flags);
6429}
6430
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07006431}; // namespace android