blob: 7e7ee3fb271f6f6e66fb1306f1ff22cfac3d1c61 [file] [log] [blame]
Glenn Kasten99e53b82012-01-19 08:59:58 -08001/*
Mathias Agopian65ab4712010-07-14 17:59:35 -07002**
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"
20//#define LOG_NDEBUG 0
21
22#include <math.h>
23#include <signal.h>
24#include <sys/time.h>
25#include <sys/resource.h>
26
Gloria Wang9ee159b2011-02-24 14:51:45 -080027#include <binder/IPCThreadState.h>
Mathias Agopian65ab4712010-07-14 17:59:35 -070028#include <binder/IServiceManager.h>
29#include <utils/Log.h>
30#include <binder/Parcel.h>
31#include <binder/IPCThreadState.h>
32#include <utils/String16.h>
33#include <utils/threads.h>
Eric Laurent38ccae22011-03-28 18:37:07 -070034#include <utils/Atomic.h>
Mathias Agopian65ab4712010-07-14 17:59:35 -070035
Dima Zavinfce7a472011-04-19 22:30:36 -070036#include <cutils/bitops.h>
Mathias Agopian65ab4712010-07-14 17:59:35 -070037#include <cutils/properties.h>
Glenn Kastenf6b16782011-12-15 09:51:17 -080038#include <cutils/compiler.h>
Mathias Agopian65ab4712010-07-14 17:59:35 -070039
Gloria Wang9ee159b2011-02-24 14:51:45 -080040#include <media/IMediaPlayerService.h>
Glenn Kasten25b248e2012-01-03 15:28:29 -080041#include <media/IMediaDeathNotifier.h>
Mathias Agopian65ab4712010-07-14 17:59:35 -070042
43#include <private/media/AudioTrackShared.h>
44#include <private/media/AudioEffectShared.h>
Dima Zavinfce7a472011-04-19 22:30:36 -070045
Dima Zavin64760242011-05-11 14:15:23 -070046#include <system/audio.h>
Dima Zavin7394a4f2011-06-13 18:16:26 -070047#include <hardware/audio.h>
Mathias Agopian65ab4712010-07-14 17:59:35 -070048
49#include "AudioMixer.h"
50#include "AudioFlinger.h"
Glenn Kasten44deb052012-02-05 18:09:08 -080051#include "ServiceUtilities.h"
Mathias Agopian65ab4712010-07-14 17:59:35 -070052
Mathias Agopian65ab4712010-07-14 17:59:35 -070053#include <media/EffectsFactoryApi.h>
Eric Laurent6d8b6942011-06-24 07:01:31 -070054#include <audio_effects/effect_visualizer.h>
Eric Laurent59bd0da2011-08-01 09:52:20 -070055#include <audio_effects/effect_ns.h>
56#include <audio_effects/effect_aec.h>
Mathias Agopian65ab4712010-07-14 17:59:35 -070057
Glenn Kasten3b21c502011-12-15 09:52:39 -080058#include <audio_utils/primitives.h>
59
Glenn Kasten4d8d0c32011-07-08 15:26:12 -070060#include <cpustats/ThreadCpuUsage.h>
Eric Laurentfeb0db62011-07-22 09:04:31 -070061#include <powermanager/PowerManager.h>
Glenn Kasten4d8d0c32011-07-08 15:26:12 -070062// #define DEBUG_CPU_USAGE 10 // log statistics every n wall clock seconds
63
John Grossman4ff14ba2012-02-08 16:37:41 -080064#include <common_time/cc_helper.h>
65#include <common_time/local_clock.h>
66
Mathias Agopian65ab4712010-07-14 17:59:35 -070067// ----------------------------------------------------------------------------
Mathias Agopian65ab4712010-07-14 17:59:35 -070068
Eric Laurentde070132010-07-13 04:45:46 -070069
Mathias Agopian65ab4712010-07-14 17:59:35 -070070namespace android {
71
Glenn Kastenec1d6b52011-12-12 09:04:45 -080072static const char kDeadlockedString[] = "AudioFlinger may be deadlocked\n";
73static const char kHardwareLockedString[] = "Hardware lock is taken\n";
Mathias Agopian65ab4712010-07-14 17:59:35 -070074
Mathias Agopian65ab4712010-07-14 17:59:35 -070075static const float MAX_GAIN = 4096.0f;
Glenn Kastenb1cf75c2012-01-17 12:20:54 -080076static const uint32_t MAX_GAIN_INT = 0x1000;
Mathias Agopian65ab4712010-07-14 17:59:35 -070077
78// retry counts for buffer fill timeout
79// 50 * ~20msecs = 1 second
80static const int8_t kMaxTrackRetries = 50;
81static const int8_t kMaxTrackStartupRetries = 50;
82// allow less retry attempts on direct output thread.
83// direct outputs can be a scarce resource in audio hardware and should
84// be released as quickly as possible.
85static const int8_t kMaxTrackRetriesDirect = 2;
86
87static const int kDumpLockRetries = 50;
Glenn Kasten7dede872011-12-13 11:04:14 -080088static const int kDumpLockSleepUs = 20000;
Mathias Agopian65ab4712010-07-14 17:59:35 -070089
Glenn Kasten7dede872011-12-13 11:04:14 -080090// don't warn about blocked writes or record buffer overflows more often than this
91static const nsecs_t kWarningThrottleNs = seconds(5);
Mathias Agopian65ab4712010-07-14 17:59:35 -070092
Eric Laurent7c7f10b2011-06-17 21:29:58 -070093// RecordThread loop sleep time upon application overrun or audio HAL read error
94static const int kRecordThreadSleepUs = 5000;
Mathias Agopian65ab4712010-07-14 17:59:35 -070095
Glenn Kasten7dede872011-12-13 11:04:14 -080096// maximum time to wait for setParameters to complete
97static const nsecs_t kSetParametersTimeoutNs = seconds(2);
Eric Laurent60cd0a02011-09-13 11:40:21 -070098
Eric Laurent7cafbb32011-11-22 18:50:29 -080099// minimum sleep time for the mixer thread loop when tracks are active but in underrun
100static const uint32_t kMinThreadSleepTimeUs = 5000;
101// maximum divider applied to the active sleep time in the mixer thread loop
102static const uint32_t kMaxThreadSleepTimeShift = 2;
103
John Grossman4ff14ba2012-02-08 16:37:41 -0800104nsecs_t AudioFlinger::mStandbyTimeInNsecs = kDefaultStandbyTimeInNsecs;
Eric Laurent7cafbb32011-11-22 18:50:29 -0800105
Mathias Agopian65ab4712010-07-14 17:59:35 -0700106// ----------------------------------------------------------------------------
107
Gloria Wang9ee159b2011-02-24 14:51:45 -0800108// To collect the amplifier usage
109static void addBatteryData(uint32_t params) {
Glenn Kasten25b248e2012-01-03 15:28:29 -0800110 sp<IMediaPlayerService> service = IMediaDeathNotifier::getMediaPlayerService();
111 if (service == NULL) {
112 // it already logged
Gloria Wang9ee159b2011-02-24 14:51:45 -0800113 return;
114 }
115
116 service->addBatteryData(params);
117}
118
Dima Zavin799a70e2011-04-18 16:57:27 -0700119static int load_audio_interface(const char *if_name, const hw_module_t **mod,
120 audio_hw_device_t **dev)
121{
122 int rc;
123
124 rc = hw_get_module_by_class(AUDIO_HARDWARE_MODULE_ID, if_name, mod);
125 if (rc)
126 goto out;
127
128 rc = audio_hw_device_open(*mod, dev);
Steve Block29357bc2012-01-06 19:20:56 +0000129 ALOGE_IF(rc, "couldn't open audio hw device in %s.%s (%s)",
Dima Zavin799a70e2011-04-18 16:57:27 -0700130 AUDIO_HARDWARE_MODULE_ID, if_name, strerror(-rc));
131 if (rc)
132 goto out;
133
134 return 0;
135
136out:
137 *mod = NULL;
138 *dev = NULL;
139 return rc;
140}
141
Glenn Kastenec1d6b52011-12-12 09:04:45 -0800142static const char * const audio_interfaces[] = {
Dima Zavin799a70e2011-04-18 16:57:27 -0700143 "primary",
144 "a2dp",
145 "usb",
146};
147#define ARRAY_SIZE(x) (sizeof((x))/sizeof(((x)[0])))
148
Mathias Agopian65ab4712010-07-14 17:59:35 -0700149// ----------------------------------------------------------------------------
150
151AudioFlinger::AudioFlinger()
152 : BnAudioFlinger(),
John Grossman4ff14ba2012-02-08 16:37:41 -0800153 mPrimaryHardwareDev(NULL),
154 mHardwareStatus(AUDIO_HW_IDLE), // see also onFirstRef()
155 mMasterVolume(1.0f),
156 mMasterVolumeSupportLvl(MVS_NONE),
157 mMasterMute(false),
158 mNextUniqueId(1),
159 mMode(AUDIO_MODE_INVALID),
160 mBtNrecIsOff(false)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700161{
Dima Zavin5a61d2f2011-04-19 19:04:32 -0700162}
163
164void AudioFlinger::onFirstRef()
165{
Dima Zavin799a70e2011-04-18 16:57:27 -0700166 int rc = 0;
Dima Zavinfce7a472011-04-19 22:30:36 -0700167
Eric Laurent93575202011-01-18 18:39:02 -0800168 Mutex::Autolock _l(mLock);
169
Dima Zavin799a70e2011-04-18 16:57:27 -0700170 /* TODO: move all this work into an Init() function */
John Grossman4ff14ba2012-02-08 16:37:41 -0800171 char val_str[PROPERTY_VALUE_MAX] = { 0 };
172 if (property_get("ro.audio.flinger_standbytime_ms", val_str, NULL) >= 0) {
173 uint32_t int_val;
174 if (1 == sscanf(val_str, "%u", &int_val)) {
175 mStandbyTimeInNsecs = milliseconds(int_val);
176 ALOGI("Using %u mSec as standby time.", int_val);
177 } else {
178 mStandbyTimeInNsecs = kDefaultStandbyTimeInNsecs;
179 ALOGI("Using default %u mSec as standby time.",
180 (uint32_t)(mStandbyTimeInNsecs / 1000000));
181 }
182 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700183
Dima Zavin799a70e2011-04-18 16:57:27 -0700184 for (size_t i = 0; i < ARRAY_SIZE(audio_interfaces); i++) {
185 const hw_module_t *mod;
186 audio_hw_device_t *dev;
Dima Zavinfce7a472011-04-19 22:30:36 -0700187
Dima Zavin799a70e2011-04-18 16:57:27 -0700188 rc = load_audio_interface(audio_interfaces[i], &mod, &dev);
189 if (rc)
190 continue;
191
Steve Blockdf64d152012-01-04 20:05:49 +0000192 ALOGI("Loaded %s audio interface from %s (%s)", audio_interfaces[i],
Dima Zavin799a70e2011-04-18 16:57:27 -0700193 mod->name, mod->id);
194 mAudioHwDevs.push(dev);
195
Glenn Kasten2b213bc2012-02-02 14:05:20 -0800196 if (mPrimaryHardwareDev == NULL) {
Dima Zavin799a70e2011-04-18 16:57:27 -0700197 mPrimaryHardwareDev = dev;
Steve Blockdf64d152012-01-04 20:05:49 +0000198 ALOGI("Using '%s' (%s.%s) as the primary audio interface",
Dima Zavin5a61d2f2011-04-19 19:04:32 -0700199 mod->name, mod->id, audio_interfaces[i]);
Dima Zavin799a70e2011-04-18 16:57:27 -0700200 }
201 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700202
Glenn Kasten2b213bc2012-02-02 14:05:20 -0800203 if (mPrimaryHardwareDev == NULL) {
Steve Block29357bc2012-01-06 19:20:56 +0000204 ALOGE("Primary audio interface not found");
Glenn Kasten2b213bc2012-02-02 14:05:20 -0800205 // proceed, all later accesses to mPrimaryHardwareDev verify it's safe with initCheck()
Dima Zavin799a70e2011-04-18 16:57:27 -0700206 }
207
Glenn Kasten2b213bc2012-02-02 14:05:20 -0800208 // Currently (mPrimaryHardwareDev == NULL) == (mAudioHwDevs.size() == 0), but the way the
209 // primary HW dev is selected can change so these conditions might not always be equivalent.
210 // When that happens, re-visit all the code that assumes this.
211
212 AutoMutex lock(mHardwareLock);
213
John Grossman4ff14ba2012-02-08 16:37:41 -0800214 // Determine the level of master volume support the primary audio HAL has,
215 // and set the initial master volume at the same time.
216 float initialVolume = 1.0;
217 mMasterVolumeSupportLvl = MVS_NONE;
218 if (0 == mPrimaryHardwareDev->init_check(mPrimaryHardwareDev)) {
219 audio_hw_device_t *dev = mPrimaryHardwareDev;
220
221 mHardwareStatus = AUDIO_HW_GET_MASTER_VOLUME;
222 if ((NULL != dev->get_master_volume) &&
223 (NO_ERROR == dev->get_master_volume(dev, &initialVolume))) {
224 mMasterVolumeSupportLvl = MVS_FULL;
225 } else {
226 mMasterVolumeSupportLvl = MVS_SETONLY;
227 initialVolume = 1.0;
228 }
229
230 mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
231 if ((NULL == dev->set_master_volume) ||
232 (NO_ERROR != dev->set_master_volume(dev, initialVolume))) {
233 mMasterVolumeSupportLvl = MVS_NONE;
234 }
Glenn Kasten8abf44d2012-02-02 14:16:03 -0800235 mHardwareStatus = AUDIO_HW_IDLE;
John Grossman4ff14ba2012-02-08 16:37:41 -0800236 }
237
238 // Set the mode for each audio HAL, and try to set the initial volume (if
239 // supported) for all of the non-primary audio HALs.
Dima Zavin799a70e2011-04-18 16:57:27 -0700240 for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
241 audio_hw_device_t *dev = mAudioHwDevs[i];
242
243 mHardwareStatus = AUDIO_HW_INIT;
244 rc = dev->init_check(dev);
Glenn Kasten2b213bc2012-02-02 14:05:20 -0800245 mHardwareStatus = AUDIO_HW_IDLE;
Dima Zavin799a70e2011-04-18 16:57:27 -0700246 if (rc == 0) {
Glenn Kasten2b213bc2012-02-02 14:05:20 -0800247 mMode = AUDIO_MODE_NORMAL; // assigned multiple times with same value
Dima Zavin799a70e2011-04-18 16:57:27 -0700248 mHardwareStatus = AUDIO_HW_SET_MODE;
249 dev->set_mode(dev, mMode);
John Grossman4ff14ba2012-02-08 16:37:41 -0800250
251 if ((dev != mPrimaryHardwareDev) &&
252 (NULL != dev->set_master_volume)) {
253 mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
254 dev->set_master_volume(dev, initialVolume);
255 }
256
Glenn Kasten8abf44d2012-02-02 14:16:03 -0800257 mHardwareStatus = AUDIO_HW_IDLE;
Dima Zavin799a70e2011-04-18 16:57:27 -0700258 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700259 }
John Grossman4ff14ba2012-02-08 16:37:41 -0800260
261 mMasterVolumeSW = (MVS_NONE == mMasterVolumeSupportLvl)
262 ? initialVolume
263 : 1.0;
264 mMasterVolume = initialVolume;
265 mHardwareStatus = AUDIO_HW_IDLE;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700266}
267
268AudioFlinger::~AudioFlinger()
269{
Dima Zavin799a70e2011-04-18 16:57:27 -0700270
Mathias Agopian65ab4712010-07-14 17:59:35 -0700271 while (!mRecordThreads.isEmpty()) {
272 // closeInput() will remove first entry from mRecordThreads
273 closeInput(mRecordThreads.keyAt(0));
274 }
275 while (!mPlaybackThreads.isEmpty()) {
276 // closeOutput() will remove first entry from mPlaybackThreads
277 closeOutput(mPlaybackThreads.keyAt(0));
278 }
Dima Zavin799a70e2011-04-18 16:57:27 -0700279
Glenn Kasten2b213bc2012-02-02 14:05:20 -0800280 for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
281 // no mHardwareLock needed, as there are no other references to this
282 audio_hw_device_close(mAudioHwDevs[i]);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700283 }
284}
285
Dima Zavin799a70e2011-04-18 16:57:27 -0700286audio_hw_device_t* AudioFlinger::findSuitableHwDev_l(uint32_t devices)
287{
288 /* first matching HW device is returned */
289 for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
290 audio_hw_device_t *dev = mAudioHwDevs[i];
291 if ((dev->get_supported_devices(dev) & devices) == devices)
292 return dev;
293 }
294 return NULL;
295}
Mathias Agopian65ab4712010-07-14 17:59:35 -0700296
297status_t AudioFlinger::dumpClients(int fd, const Vector<String16>& args)
298{
299 const size_t SIZE = 256;
300 char buffer[SIZE];
301 String8 result;
302
303 result.append("Clients:\n");
304 for (size_t i = 0; i < mClients.size(); ++i) {
Glenn Kasten77c11192012-01-25 14:27:41 -0800305 sp<Client> client = mClients.valueAt(i).promote();
306 if (client != 0) {
307 snprintf(buffer, SIZE, " pid: %d\n", client->pid());
308 result.append(buffer);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700309 }
310 }
Marco Nelissen3a34bef2011-08-02 13:33:41 -0700311
312 result.append("Global session refs:\n");
Glenn Kasten012ca6b2012-03-06 11:22:01 -0800313 result.append(" session pid count\n");
Marco Nelissen3a34bef2011-08-02 13:33:41 -0700314 for (size_t i = 0; i < mAudioSessionRefs.size(); i++) {
315 AudioSessionRef *r = mAudioSessionRefs[i];
Glenn Kasten012ca6b2012-03-06 11:22:01 -0800316 snprintf(buffer, SIZE, " %7d %3d %3d\n", r->mSessionid, r->mPid, r->mCnt);
Marco Nelissen3a34bef2011-08-02 13:33:41 -0700317 result.append(buffer);
318 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700319 write(fd, result.string(), result.size());
320 return NO_ERROR;
321}
322
323
324status_t AudioFlinger::dumpInternals(int fd, const Vector<String16>& args)
325{
326 const size_t SIZE = 256;
327 char buffer[SIZE];
328 String8 result;
Glenn Kastena4454b42012-01-04 11:02:33 -0800329 hardware_call_state hardwareStatus = mHardwareStatus;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700330
John Grossman4ff14ba2012-02-08 16:37:41 -0800331 snprintf(buffer, SIZE, "Hardware status: %d\n"
332 "Standby Time mSec: %u\n",
333 hardwareStatus,
334 (uint32_t)(mStandbyTimeInNsecs / 1000000));
Mathias Agopian65ab4712010-07-14 17:59:35 -0700335 result.append(buffer);
336 write(fd, result.string(), result.size());
337 return NO_ERROR;
338}
339
340status_t AudioFlinger::dumpPermissionDenial(int fd, const Vector<String16>& args)
341{
342 const size_t SIZE = 256;
343 char buffer[SIZE];
344 String8 result;
345 snprintf(buffer, SIZE, "Permission Denial: "
346 "can't dump AudioFlinger from pid=%d, uid=%d\n",
347 IPCThreadState::self()->getCallingPid(),
348 IPCThreadState::self()->getCallingUid());
349 result.append(buffer);
350 write(fd, result.string(), result.size());
351 return NO_ERROR;
352}
353
354static bool tryLock(Mutex& mutex)
355{
356 bool locked = false;
357 for (int i = 0; i < kDumpLockRetries; ++i) {
358 if (mutex.tryLock() == NO_ERROR) {
359 locked = true;
360 break;
361 }
Glenn Kasten7dede872011-12-13 11:04:14 -0800362 usleep(kDumpLockSleepUs);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700363 }
364 return locked;
365}
366
367status_t AudioFlinger::dump(int fd, const Vector<String16>& args)
368{
Glenn Kasten44deb052012-02-05 18:09:08 -0800369 if (!dumpAllowed()) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700370 dumpPermissionDenial(fd, args);
371 } else {
372 // get state of hardware lock
373 bool hardwareLocked = tryLock(mHardwareLock);
374 if (!hardwareLocked) {
375 String8 result(kHardwareLockedString);
376 write(fd, result.string(), result.size());
377 } else {
378 mHardwareLock.unlock();
379 }
380
381 bool locked = tryLock(mLock);
382
383 // failed to lock - AudioFlinger is probably deadlocked
384 if (!locked) {
385 String8 result(kDeadlockedString);
386 write(fd, result.string(), result.size());
387 }
388
389 dumpClients(fd, args);
390 dumpInternals(fd, args);
391
392 // dump playback threads
393 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
394 mPlaybackThreads.valueAt(i)->dump(fd, args);
395 }
396
397 // dump record threads
398 for (size_t i = 0; i < mRecordThreads.size(); i++) {
399 mRecordThreads.valueAt(i)->dump(fd, args);
400 }
401
Dima Zavin799a70e2011-04-18 16:57:27 -0700402 // dump all hardware devs
403 for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
404 audio_hw_device_t *dev = mAudioHwDevs[i];
405 dev->dump(dev, fd);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700406 }
407 if (locked) mLock.unlock();
408 }
409 return NO_ERROR;
410}
411
Glenn Kasten98ec94c2012-01-25 14:28:29 -0800412sp<AudioFlinger::Client> AudioFlinger::registerPid_l(pid_t pid)
413{
414 // If pid is already in the mClients wp<> map, then use that entry
415 // (for which promote() is always != 0), otherwise create a new entry and Client.
416 sp<Client> client = mClients.valueFor(pid).promote();
417 if (client == 0) {
418 client = new Client(this, pid);
419 mClients.add(pid, client);
420 }
421
422 return client;
423}
Mathias Agopian65ab4712010-07-14 17:59:35 -0700424
425// IAudioFlinger interface
426
427
428sp<IAudioTrack> AudioFlinger::createTrack(
429 pid_t pid,
Glenn Kastenfff6d712012-01-12 16:38:12 -0800430 audio_stream_type_t streamType,
Mathias Agopian65ab4712010-07-14 17:59:35 -0700431 uint32_t sampleRate,
Glenn Kasten58f30212012-01-12 12:27:51 -0800432 audio_format_t format,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -0700433 uint32_t channelMask,
Mathias Agopian65ab4712010-07-14 17:59:35 -0700434 int frameCount,
Glenn Kasten5cf034d2012-02-21 10:35:56 -0800435 // FIXME dead, remove from IAudioFlinger
Mathias Agopian65ab4712010-07-14 17:59:35 -0700436 uint32_t flags,
437 const sp<IMemory>& sharedBuffer,
Glenn Kasten72ef00d2012-01-17 11:09:42 -0800438 audio_io_handle_t output,
John Grossman4ff14ba2012-02-08 16:37:41 -0800439 bool isTimed,
Mathias Agopian65ab4712010-07-14 17:59:35 -0700440 int *sessionId,
441 status_t *status)
442{
443 sp<PlaybackThread::Track> track;
444 sp<TrackHandle> trackHandle;
445 sp<Client> client;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700446 status_t lStatus;
447 int lSessionId;
448
Glenn Kasten263709e2012-01-06 08:40:01 -0800449 // client AudioTrack::set already implements AUDIO_STREAM_DEFAULT => AUDIO_STREAM_MUSIC,
450 // but if someone uses binder directly they could bypass that and cause us to crash
451 if (uint32_t(streamType) >= AUDIO_STREAM_CNT) {
Steve Block29357bc2012-01-06 19:20:56 +0000452 ALOGE("createTrack() invalid stream type %d", streamType);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700453 lStatus = BAD_VALUE;
454 goto Exit;
455 }
456
457 {
458 Mutex::Autolock _l(mLock);
459 PlaybackThread *thread = checkPlaybackThread_l(output);
Eric Laurent39e94f82010-07-28 01:32:47 -0700460 PlaybackThread *effectThread = NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700461 if (thread == NULL) {
Steve Block29357bc2012-01-06 19:20:56 +0000462 ALOGE("unknown output thread");
Mathias Agopian65ab4712010-07-14 17:59:35 -0700463 lStatus = BAD_VALUE;
464 goto Exit;
465 }
466
Glenn Kasten98ec94c2012-01-25 14:28:29 -0800467 client = registerPid_l(pid);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700468
Steve Block3856b092011-10-20 11:56:00 +0100469 ALOGV("createTrack() sessionId: %d", (sessionId == NULL) ? -2 : *sessionId);
Dima Zavinfce7a472011-04-19 22:30:36 -0700470 if (sessionId != NULL && *sessionId != AUDIO_SESSION_OUTPUT_MIX) {
Eric Laurentde070132010-07-13 04:45:46 -0700471 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
Eric Laurent39e94f82010-07-28 01:32:47 -0700472 sp<PlaybackThread> t = mPlaybackThreads.valueAt(i);
473 if (mPlaybackThreads.keyAt(i) != output) {
474 // prevent same audio session on different output threads
475 uint32_t sessions = t->hasAudioSession(*sessionId);
476 if (sessions & PlaybackThread::TRACK_SESSION) {
Steve Block29357bc2012-01-06 19:20:56 +0000477 ALOGE("createTrack() session ID %d already in use", *sessionId);
Eric Laurent39e94f82010-07-28 01:32:47 -0700478 lStatus = BAD_VALUE;
479 goto Exit;
480 }
481 // check if an effect with same session ID is waiting for a track to be created
482 if (sessions & PlaybackThread::EFFECT_SESSION) {
483 effectThread = t.get();
484 }
Eric Laurentde070132010-07-13 04:45:46 -0700485 }
486 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700487 lSessionId = *sessionId;
488 } else {
Eric Laurentde070132010-07-13 04:45:46 -0700489 // if no audio session id is provided, create one here
Eric Laurent7c7f10b2011-06-17 21:29:58 -0700490 lSessionId = nextUniqueId();
Mathias Agopian65ab4712010-07-14 17:59:35 -0700491 if (sessionId != NULL) {
492 *sessionId = lSessionId;
493 }
494 }
Steve Block3856b092011-10-20 11:56:00 +0100495 ALOGV("createTrack() lSessionId: %d", lSessionId);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700496
497 track = thread->createTrack_l(client, streamType, sampleRate, format,
John Grossman4ff14ba2012-02-08 16:37:41 -0800498 channelMask, frameCount, sharedBuffer, lSessionId, isTimed, &lStatus);
Eric Laurent39e94f82010-07-28 01:32:47 -0700499
500 // move effect chain to this output thread if an effect on same session was waiting
501 // for a track to be created
502 if (lStatus == NO_ERROR && effectThread != NULL) {
503 Mutex::Autolock _dl(thread->mLock);
504 Mutex::Autolock _sl(effectThread->mLock);
505 moveEffectChain_l(lSessionId, effectThread, thread, true);
506 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700507 }
508 if (lStatus == NO_ERROR) {
509 trackHandle = new TrackHandle(track);
510 } else {
511 // remove local strong reference to Client before deleting the Track so that the Client
512 // destructor is called by the TrackBase destructor with mLock held
513 client.clear();
514 track.clear();
515 }
516
517Exit:
518 if(status) {
519 *status = lStatus;
520 }
521 return trackHandle;
522}
523
Glenn Kasten72ef00d2012-01-17 11:09:42 -0800524uint32_t AudioFlinger::sampleRate(audio_io_handle_t output) const
Mathias Agopian65ab4712010-07-14 17:59:35 -0700525{
526 Mutex::Autolock _l(mLock);
527 PlaybackThread *thread = checkPlaybackThread_l(output);
528 if (thread == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +0000529 ALOGW("sampleRate() unknown thread %d", output);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700530 return 0;
531 }
532 return thread->sampleRate();
533}
534
Glenn Kasten72ef00d2012-01-17 11:09:42 -0800535int AudioFlinger::channelCount(audio_io_handle_t output) const
Mathias Agopian65ab4712010-07-14 17:59:35 -0700536{
537 Mutex::Autolock _l(mLock);
538 PlaybackThread *thread = checkPlaybackThread_l(output);
539 if (thread == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +0000540 ALOGW("channelCount() unknown thread %d", output);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700541 return 0;
542 }
543 return thread->channelCount();
544}
545
Glenn Kasten72ef00d2012-01-17 11:09:42 -0800546audio_format_t AudioFlinger::format(audio_io_handle_t output) const
Mathias Agopian65ab4712010-07-14 17:59:35 -0700547{
548 Mutex::Autolock _l(mLock);
549 PlaybackThread *thread = checkPlaybackThread_l(output);
550 if (thread == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +0000551 ALOGW("format() unknown thread %d", output);
Glenn Kasten58f30212012-01-12 12:27:51 -0800552 return AUDIO_FORMAT_INVALID;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700553 }
554 return thread->format();
555}
556
Glenn Kasten72ef00d2012-01-17 11:09:42 -0800557size_t AudioFlinger::frameCount(audio_io_handle_t output) const
Mathias Agopian65ab4712010-07-14 17:59:35 -0700558{
559 Mutex::Autolock _l(mLock);
560 PlaybackThread *thread = checkPlaybackThread_l(output);
561 if (thread == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +0000562 ALOGW("frameCount() unknown thread %d", output);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700563 return 0;
564 }
565 return thread->frameCount();
566}
567
Glenn Kasten72ef00d2012-01-17 11:09:42 -0800568uint32_t AudioFlinger::latency(audio_io_handle_t output) const
Mathias Agopian65ab4712010-07-14 17:59:35 -0700569{
570 Mutex::Autolock _l(mLock);
571 PlaybackThread *thread = checkPlaybackThread_l(output);
572 if (thread == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +0000573 ALOGW("latency() unknown thread %d", output);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700574 return 0;
575 }
576 return thread->latency();
577}
578
579status_t AudioFlinger::setMasterVolume(float value)
580{
Eric Laurenta1884f92011-08-23 08:25:03 -0700581 status_t ret = initCheck();
582 if (ret != NO_ERROR) {
583 return ret;
584 }
585
Mathias Agopian65ab4712010-07-14 17:59:35 -0700586 // check calling permissions
587 if (!settingsAllowed()) {
588 return PERMISSION_DENIED;
589 }
590
John Grossman4ff14ba2012-02-08 16:37:41 -0800591 float swmv = value;
592
Mathias Agopian65ab4712010-07-14 17:59:35 -0700593 // when hw supports master volume, don't scale in sw mixer
John Grossman4ff14ba2012-02-08 16:37:41 -0800594 if (MVS_NONE != mMasterVolumeSupportLvl) {
595 for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
596 AutoMutex lock(mHardwareLock);
597 audio_hw_device_t *dev = mAudioHwDevs[i];
598
599 mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
600 if (NULL != dev->set_master_volume) {
601 dev->set_master_volume(dev, value);
602 }
603 mHardwareStatus = AUDIO_HW_IDLE;
Eric Laurent93575202011-01-18 18:39:02 -0800604 }
John Grossman4ff14ba2012-02-08 16:37:41 -0800605
606 swmv = 1.0;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700607 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700608
Eric Laurent93575202011-01-18 18:39:02 -0800609 Mutex::Autolock _l(mLock);
John Grossman4ff14ba2012-02-08 16:37:41 -0800610 mMasterVolume = value;
611 mMasterVolumeSW = swmv;
Glenn Kasten8d6a2442012-02-08 14:04:28 -0800612 for (size_t i = 0; i < mPlaybackThreads.size(); i++)
John Grossman4ff14ba2012-02-08 16:37:41 -0800613 mPlaybackThreads.valueAt(i)->setMasterVolume(swmv);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700614
615 return NO_ERROR;
616}
617
Glenn Kastenf78aee72012-01-04 11:00:47 -0800618status_t AudioFlinger::setMode(audio_mode_t mode)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700619{
Eric Laurenta1884f92011-08-23 08:25:03 -0700620 status_t ret = initCheck();
621 if (ret != NO_ERROR) {
622 return ret;
623 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700624
625 // check calling permissions
626 if (!settingsAllowed()) {
627 return PERMISSION_DENIED;
628 }
Glenn Kasten930f4ca2012-01-06 16:47:31 -0800629 if (uint32_t(mode) >= AUDIO_MODE_CNT) {
Steve Block5ff1dd52012-01-05 23:22:43 +0000630 ALOGW("Illegal value: setMode(%d)", mode);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700631 return BAD_VALUE;
632 }
633
634 { // scope for the lock
635 AutoMutex lock(mHardwareLock);
636 mHardwareStatus = AUDIO_HW_SET_MODE;
Dima Zavin799a70e2011-04-18 16:57:27 -0700637 ret = mPrimaryHardwareDev->set_mode(mPrimaryHardwareDev, mode);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700638 mHardwareStatus = AUDIO_HW_IDLE;
639 }
640
641 if (NO_ERROR == ret) {
642 Mutex::Autolock _l(mLock);
643 mMode = mode;
Glenn Kasten8d6a2442012-02-08 14:04:28 -0800644 for (size_t i = 0; i < mPlaybackThreads.size(); i++)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700645 mPlaybackThreads.valueAt(i)->setMode(mode);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700646 }
647
648 return ret;
649}
650
651status_t AudioFlinger::setMicMute(bool state)
652{
Eric Laurenta1884f92011-08-23 08:25:03 -0700653 status_t ret = initCheck();
654 if (ret != NO_ERROR) {
655 return ret;
656 }
657
Mathias Agopian65ab4712010-07-14 17:59:35 -0700658 // check calling permissions
659 if (!settingsAllowed()) {
660 return PERMISSION_DENIED;
661 }
662
663 AutoMutex lock(mHardwareLock);
664 mHardwareStatus = AUDIO_HW_SET_MIC_MUTE;
Eric Laurenta1884f92011-08-23 08:25:03 -0700665 ret = mPrimaryHardwareDev->set_mic_mute(mPrimaryHardwareDev, state);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700666 mHardwareStatus = AUDIO_HW_IDLE;
667 return ret;
668}
669
670bool AudioFlinger::getMicMute() const
671{
Eric Laurenta1884f92011-08-23 08:25:03 -0700672 status_t ret = initCheck();
673 if (ret != NO_ERROR) {
674 return false;
675 }
676
Dima Zavinfce7a472011-04-19 22:30:36 -0700677 bool state = AUDIO_MODE_INVALID;
Glenn Kasten2b213bc2012-02-02 14:05:20 -0800678 AutoMutex lock(mHardwareLock);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700679 mHardwareStatus = AUDIO_HW_GET_MIC_MUTE;
Dima Zavin799a70e2011-04-18 16:57:27 -0700680 mPrimaryHardwareDev->get_mic_mute(mPrimaryHardwareDev, &state);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700681 mHardwareStatus = AUDIO_HW_IDLE;
682 return state;
683}
684
685status_t AudioFlinger::setMasterMute(bool muted)
686{
687 // check calling permissions
688 if (!settingsAllowed()) {
689 return PERMISSION_DENIED;
690 }
691
Eric Laurent93575202011-01-18 18:39:02 -0800692 Mutex::Autolock _l(mLock);
Glenn Kasten99e53b82012-01-19 08:59:58 -0800693 // This is an optimization, so PlaybackThread doesn't have to look at the one from AudioFlinger
Mathias Agopian65ab4712010-07-14 17:59:35 -0700694 mMasterMute = muted;
Glenn Kasten8d6a2442012-02-08 14:04:28 -0800695 for (size_t i = 0; i < mPlaybackThreads.size(); i++)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700696 mPlaybackThreads.valueAt(i)->setMasterMute(muted);
697
698 return NO_ERROR;
699}
700
701float AudioFlinger::masterVolume() const
702{
Glenn Kasten98067102011-12-13 11:47:54 -0800703 Mutex::Autolock _l(mLock);
704 return masterVolume_l();
Mathias Agopian65ab4712010-07-14 17:59:35 -0700705}
706
John Grossman4ff14ba2012-02-08 16:37:41 -0800707float AudioFlinger::masterVolumeSW() const
708{
709 Mutex::Autolock _l(mLock);
710 return masterVolumeSW_l();
711}
712
Mathias Agopian65ab4712010-07-14 17:59:35 -0700713bool AudioFlinger::masterMute() const
714{
Glenn Kasten98067102011-12-13 11:47:54 -0800715 Mutex::Autolock _l(mLock);
716 return masterMute_l();
Mathias Agopian65ab4712010-07-14 17:59:35 -0700717}
718
John Grossman4ff14ba2012-02-08 16:37:41 -0800719float AudioFlinger::masterVolume_l() const
720{
721 if (MVS_FULL == mMasterVolumeSupportLvl) {
722 float ret_val;
723 AutoMutex lock(mHardwareLock);
724
725 mHardwareStatus = AUDIO_HW_GET_MASTER_VOLUME;
726 assert(NULL != mPrimaryHardwareDev);
727 assert(NULL != mPrimaryHardwareDev->get_master_volume);
728
729 mPrimaryHardwareDev->get_master_volume(mPrimaryHardwareDev, &ret_val);
730 mHardwareStatus = AUDIO_HW_IDLE;
731 return ret_val;
732 }
733
734 return mMasterVolume;
735}
736
Glenn Kasten72ef00d2012-01-17 11:09:42 -0800737status_t AudioFlinger::setStreamVolume(audio_stream_type_t stream, float value,
738 audio_io_handle_t output)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700739{
740 // check calling permissions
741 if (!settingsAllowed()) {
742 return PERMISSION_DENIED;
743 }
744
Glenn Kasten263709e2012-01-06 08:40:01 -0800745 if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
Steve Block29357bc2012-01-06 19:20:56 +0000746 ALOGE("setStreamVolume() invalid stream %d", stream);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700747 return BAD_VALUE;
748 }
749
750 AutoMutex lock(mLock);
751 PlaybackThread *thread = NULL;
752 if (output) {
753 thread = checkPlaybackThread_l(output);
754 if (thread == NULL) {
755 return BAD_VALUE;
756 }
757 }
758
759 mStreamTypes[stream].volume = value;
760
761 if (thread == NULL) {
Glenn Kasten8d6a2442012-02-08 14:04:28 -0800762 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700763 mPlaybackThreads.valueAt(i)->setStreamVolume(stream, value);
764 }
765 } else {
766 thread->setStreamVolume(stream, value);
767 }
768
769 return NO_ERROR;
770}
771
Glenn Kastenfff6d712012-01-12 16:38:12 -0800772status_t AudioFlinger::setStreamMute(audio_stream_type_t stream, bool muted)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700773{
774 // check calling permissions
775 if (!settingsAllowed()) {
776 return PERMISSION_DENIED;
777 }
778
Glenn Kasten263709e2012-01-06 08:40:01 -0800779 if (uint32_t(stream) >= AUDIO_STREAM_CNT ||
Dima Zavinfce7a472011-04-19 22:30:36 -0700780 uint32_t(stream) == AUDIO_STREAM_ENFORCED_AUDIBLE) {
Steve Block29357bc2012-01-06 19:20:56 +0000781 ALOGE("setStreamMute() invalid stream %d", stream);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700782 return BAD_VALUE;
783 }
784
Eric Laurent93575202011-01-18 18:39:02 -0800785 AutoMutex lock(mLock);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700786 mStreamTypes[stream].mute = muted;
787 for (uint32_t i = 0; i < mPlaybackThreads.size(); i++)
788 mPlaybackThreads.valueAt(i)->setStreamMute(stream, muted);
789
790 return NO_ERROR;
791}
792
Glenn Kasten72ef00d2012-01-17 11:09:42 -0800793float AudioFlinger::streamVolume(audio_stream_type_t stream, audio_io_handle_t output) const
Mathias Agopian65ab4712010-07-14 17:59:35 -0700794{
Glenn Kasten263709e2012-01-06 08:40:01 -0800795 if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700796 return 0.0f;
797 }
798
799 AutoMutex lock(mLock);
800 float volume;
801 if (output) {
802 PlaybackThread *thread = checkPlaybackThread_l(output);
803 if (thread == NULL) {
804 return 0.0f;
805 }
806 volume = thread->streamVolume(stream);
807 } else {
Glenn Kasten6637baa2012-01-09 09:40:36 -0800808 volume = streamVolume_l(stream);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700809 }
810
811 return volume;
812}
813
Glenn Kastenfff6d712012-01-12 16:38:12 -0800814bool AudioFlinger::streamMute(audio_stream_type_t stream) const
Mathias Agopian65ab4712010-07-14 17:59:35 -0700815{
Glenn Kasten263709e2012-01-06 08:40:01 -0800816 if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700817 return true;
818 }
819
Glenn Kasten6637baa2012-01-09 09:40:36 -0800820 AutoMutex lock(mLock);
821 return streamMute_l(stream);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700822}
823
Glenn Kasten72ef00d2012-01-17 11:09:42 -0800824status_t AudioFlinger::setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700825{
Glenn Kasten23d82a92012-02-03 11:10:00 -0800826 ALOGV("setParameters(): io %d, keyvalue %s, tid %d, calling pid %d",
Mathias Agopian65ab4712010-07-14 17:59:35 -0700827 ioHandle, keyValuePairs.string(), gettid(), IPCThreadState::self()->getCallingPid());
828 // check calling permissions
829 if (!settingsAllowed()) {
830 return PERMISSION_DENIED;
831 }
832
Mathias Agopian65ab4712010-07-14 17:59:35 -0700833 // ioHandle == 0 means the parameters are global to the audio hardware interface
834 if (ioHandle == 0) {
Dima Zavin799a70e2011-04-18 16:57:27 -0700835 status_t final_result = NO_ERROR;
Glenn Kasten8abf44d2012-02-02 14:16:03 -0800836 {
837 AutoMutex lock(mHardwareLock);
838 mHardwareStatus = AUDIO_HW_SET_PARAMETER;
Dima Zavin799a70e2011-04-18 16:57:27 -0700839 for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
840 audio_hw_device_t *dev = mAudioHwDevs[i];
Glenn Kasten8abf44d2012-02-02 14:16:03 -0800841 status_t result = dev->set_parameters(dev, keyValuePairs.string());
Dima Zavin799a70e2011-04-18 16:57:27 -0700842 final_result = result ?: final_result;
843 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700844 mHardwareStatus = AUDIO_HW_IDLE;
Glenn Kasten8abf44d2012-02-02 14:16:03 -0800845 }
Eric Laurent59bd0da2011-08-01 09:52:20 -0700846 // disable AEC and NS if the device is a BT SCO headset supporting those pre processings
847 AudioParameter param = AudioParameter(keyValuePairs);
848 String8 value;
849 if (param.get(String8(AUDIO_PARAMETER_KEY_BT_NREC), value) == NO_ERROR) {
850 Mutex::Autolock _l(mLock);
Eric Laurentbee53372011-08-29 12:42:48 -0700851 bool btNrecIsOff = (value == AUDIO_PARAMETER_VALUE_OFF);
852 if (mBtNrecIsOff != btNrecIsOff) {
Eric Laurent59bd0da2011-08-01 09:52:20 -0700853 for (size_t i = 0; i < mRecordThreads.size(); i++) {
854 sp<RecordThread> thread = mRecordThreads.valueAt(i);
855 RecordThread::RecordTrack *track = thread->track();
856 if (track != NULL) {
857 audio_devices_t device = (audio_devices_t)(
858 thread->device() & AUDIO_DEVICE_IN_ALL);
Eric Laurentbee53372011-08-29 12:42:48 -0700859 bool suspend = audio_is_bluetooth_sco_device(device) && btNrecIsOff;
Eric Laurent59bd0da2011-08-01 09:52:20 -0700860 thread->setEffectSuspended(FX_IID_AEC,
861 suspend,
862 track->sessionId());
863 thread->setEffectSuspended(FX_IID_NS,
864 suspend,
865 track->sessionId());
866 }
867 }
Eric Laurentbee53372011-08-29 12:42:48 -0700868 mBtNrecIsOff = btNrecIsOff;
Eric Laurent59bd0da2011-08-01 09:52:20 -0700869 }
870 }
Dima Zavin799a70e2011-04-18 16:57:27 -0700871 return final_result;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700872 }
873
874 // hold a strong ref on thread in case closeOutput() or closeInput() is called
875 // and the thread is exited once the lock is released
876 sp<ThreadBase> thread;
877 {
878 Mutex::Autolock _l(mLock);
879 thread = checkPlaybackThread_l(ioHandle);
880 if (thread == NULL) {
881 thread = checkRecordThread_l(ioHandle);
Glenn Kasten7fc9a6f2012-01-10 10:46:34 -0800882 } else if (thread == primaryPlaybackThread_l()) {
Eric Laurent7c7f10b2011-06-17 21:29:58 -0700883 // indicate output device change to all input threads for pre processing
884 AudioParameter param = AudioParameter(keyValuePairs);
885 int value;
886 if (param.getInt(String8(AudioParameter::keyRouting), value) == NO_ERROR) {
887 for (size_t i = 0; i < mRecordThreads.size(); i++) {
888 mRecordThreads.valueAt(i)->setParameters(keyValuePairs);
889 }
890 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700891 }
892 }
Glenn Kasten7378ca52012-01-20 13:44:40 -0800893 if (thread != 0) {
894 return thread->setParameters(keyValuePairs);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700895 }
896 return BAD_VALUE;
897}
898
Glenn Kasten72ef00d2012-01-17 11:09:42 -0800899String8 AudioFlinger::getParameters(audio_io_handle_t ioHandle, const String8& keys) const
Mathias Agopian65ab4712010-07-14 17:59:35 -0700900{
Glenn Kasten23d82a92012-02-03 11:10:00 -0800901// ALOGV("getParameters() io %d, keys %s, tid %d, calling pid %d",
Mathias Agopian65ab4712010-07-14 17:59:35 -0700902// ioHandle, keys.string(), gettid(), IPCThreadState::self()->getCallingPid());
903
904 if (ioHandle == 0) {
Dima Zavinfce7a472011-04-19 22:30:36 -0700905 String8 out_s8;
906
Dima Zavin799a70e2011-04-18 16:57:27 -0700907 for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
Glenn Kasten8abf44d2012-02-02 14:16:03 -0800908 char *s;
909 {
910 AutoMutex lock(mHardwareLock);
911 mHardwareStatus = AUDIO_HW_GET_PARAMETER;
Dima Zavin799a70e2011-04-18 16:57:27 -0700912 audio_hw_device_t *dev = mAudioHwDevs[i];
Glenn Kasten8abf44d2012-02-02 14:16:03 -0800913 s = dev->get_parameters(dev, keys.string());
914 mHardwareStatus = AUDIO_HW_IDLE;
915 }
John Grossmanef7740b2012-02-09 11:28:36 -0800916 out_s8 += String8(s ? s : "");
Dima Zavin799a70e2011-04-18 16:57:27 -0700917 free(s);
918 }
Dima Zavinfce7a472011-04-19 22:30:36 -0700919 return out_s8;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700920 }
921
922 Mutex::Autolock _l(mLock);
923
924 PlaybackThread *playbackThread = checkPlaybackThread_l(ioHandle);
925 if (playbackThread != NULL) {
926 return playbackThread->getParameters(keys);
927 }
928 RecordThread *recordThread = checkRecordThread_l(ioHandle);
929 if (recordThread != NULL) {
930 return recordThread->getParameters(keys);
931 }
932 return String8("");
933}
934
Glenn Kastenf587ba52012-01-26 16:25:10 -0800935size_t AudioFlinger::getInputBufferSize(uint32_t sampleRate, audio_format_t format, int channelCount) const
Mathias Agopian65ab4712010-07-14 17:59:35 -0700936{
Eric Laurenta1884f92011-08-23 08:25:03 -0700937 status_t ret = initCheck();
938 if (ret != NO_ERROR) {
939 return 0;
940 }
941
Glenn Kasten2b213bc2012-02-02 14:05:20 -0800942 AutoMutex lock(mHardwareLock);
943 mHardwareStatus = AUDIO_HW_GET_INPUT_BUFFER_SIZE;
944 size_t size = mPrimaryHardwareDev->get_input_buffer_size(mPrimaryHardwareDev, sampleRate, format, channelCount);
945 mHardwareStatus = AUDIO_HW_IDLE;
946 return size;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700947}
948
Glenn Kasten72ef00d2012-01-17 11:09:42 -0800949unsigned int AudioFlinger::getInputFramesLost(audio_io_handle_t ioHandle) const
Mathias Agopian65ab4712010-07-14 17:59:35 -0700950{
951 if (ioHandle == 0) {
952 return 0;
953 }
954
955 Mutex::Autolock _l(mLock);
956
957 RecordThread *recordThread = checkRecordThread_l(ioHandle);
958 if (recordThread != NULL) {
959 return recordThread->getInputFramesLost();
960 }
961 return 0;
962}
963
964status_t AudioFlinger::setVoiceVolume(float value)
965{
Eric Laurenta1884f92011-08-23 08:25:03 -0700966 status_t ret = initCheck();
967 if (ret != NO_ERROR) {
968 return ret;
969 }
970
Mathias Agopian65ab4712010-07-14 17:59:35 -0700971 // check calling permissions
972 if (!settingsAllowed()) {
973 return PERMISSION_DENIED;
974 }
975
976 AutoMutex lock(mHardwareLock);
Glenn Kasten8abf44d2012-02-02 14:16:03 -0800977 mHardwareStatus = AUDIO_HW_SET_VOICE_VOLUME;
Eric Laurenta1884f92011-08-23 08:25:03 -0700978 ret = mPrimaryHardwareDev->set_voice_volume(mPrimaryHardwareDev, value);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700979 mHardwareStatus = AUDIO_HW_IDLE;
980
981 return ret;
982}
983
Glenn Kasten72ef00d2012-01-17 11:09:42 -0800984status_t AudioFlinger::getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames,
985 audio_io_handle_t output) const
Mathias Agopian65ab4712010-07-14 17:59:35 -0700986{
987 status_t status;
988
989 Mutex::Autolock _l(mLock);
990
991 PlaybackThread *playbackThread = checkPlaybackThread_l(output);
992 if (playbackThread != NULL) {
993 return playbackThread->getRenderPosition(halFrames, dspFrames);
994 }
995
996 return BAD_VALUE;
997}
998
999void AudioFlinger::registerClient(const sp<IAudioFlingerClient>& client)
1000{
1001
1002 Mutex::Autolock _l(mLock);
1003
Glenn Kastenbb001922012-02-03 11:10:26 -08001004 pid_t pid = IPCThreadState::self()->getCallingPid();
Mathias Agopian65ab4712010-07-14 17:59:35 -07001005 if (mNotificationClients.indexOfKey(pid) < 0) {
1006 sp<NotificationClient> notificationClient = new NotificationClient(this,
1007 client,
1008 pid);
Steve Block3856b092011-10-20 11:56:00 +01001009 ALOGV("registerClient() client %p, pid %d", notificationClient.get(), pid);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001010
1011 mNotificationClients.add(pid, notificationClient);
1012
1013 sp<IBinder> binder = client->asBinder();
1014 binder->linkToDeath(notificationClient);
1015
1016 // the config change is always sent from playback or record threads to avoid deadlock
1017 // with AudioSystem::gLock
1018 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
1019 mPlaybackThreads.valueAt(i)->sendConfigEvent(AudioSystem::OUTPUT_OPENED);
1020 }
1021
1022 for (size_t i = 0; i < mRecordThreads.size(); i++) {
1023 mRecordThreads.valueAt(i)->sendConfigEvent(AudioSystem::INPUT_OPENED);
1024 }
1025 }
1026}
1027
1028void AudioFlinger::removeNotificationClient(pid_t pid)
1029{
1030 Mutex::Autolock _l(mLock);
1031
Glenn Kastena3b09252012-01-20 09:19:01 -08001032 mNotificationClients.removeItem(pid);
Marco Nelissen3a34bef2011-08-02 13:33:41 -07001033
Steve Block3856b092011-10-20 11:56:00 +01001034 ALOGV("%d died, releasing its sessions", pid);
Glenn Kasten8d6a2442012-02-08 14:04:28 -08001035 size_t num = mAudioSessionRefs.size();
Marco Nelissen3a34bef2011-08-02 13:33:41 -07001036 bool removed = false;
Glenn Kasten8d6a2442012-02-08 14:04:28 -08001037 for (size_t i = 0; i< num; ) {
Marco Nelissen3a34bef2011-08-02 13:33:41 -07001038 AudioSessionRef *ref = mAudioSessionRefs.itemAt(i);
Glenn Kasten012ca6b2012-03-06 11:22:01 -08001039 ALOGV(" pid %d @ %d", ref->mPid, i);
1040 if (ref->mPid == pid) {
1041 ALOGV(" removing entry for pid %d session %d", pid, ref->mSessionid);
Marco Nelissen3a34bef2011-08-02 13:33:41 -07001042 mAudioSessionRefs.removeAt(i);
1043 delete ref;
1044 removed = true;
Marco Nelissen3a34bef2011-08-02 13:33:41 -07001045 num--;
Glenn Kasten8d6a2442012-02-08 14:04:28 -08001046 } else {
1047 i++;
Marco Nelissen3a34bef2011-08-02 13:33:41 -07001048 }
1049 }
1050 if (removed) {
1051 purgeStaleEffects_l();
1052 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07001053}
1054
1055// audioConfigChanged_l() must be called with AudioFlinger::mLock held
Glenn Kastenb81cc8c2012-03-01 09:14:51 -08001056void AudioFlinger::audioConfigChanged_l(int event, audio_io_handle_t ioHandle, const void *param2)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001057{
1058 size_t size = mNotificationClients.size();
1059 for (size_t i = 0; i < size; i++) {
Glenn Kasten84afa3b2012-01-25 15:28:08 -08001060 mNotificationClients.valueAt(i)->audioFlingerClient()->ioConfigChanged(event, ioHandle,
1061 param2);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001062 }
1063}
1064
1065// removeClient_l() must be called with AudioFlinger::mLock held
1066void AudioFlinger::removeClient_l(pid_t pid)
1067{
Steve Block3856b092011-10-20 11:56:00 +01001068 ALOGV("removeClient_l() pid %d, tid %d, calling tid %d", pid, gettid(), IPCThreadState::self()->getCallingPid());
Mathias Agopian65ab4712010-07-14 17:59:35 -07001069 mClients.removeItem(pid);
1070}
1071
1072
1073// ----------------------------------------------------------------------------
1074
Glenn Kasten72ef00d2012-01-17 11:09:42 -08001075AudioFlinger::ThreadBase::ThreadBase(const sp<AudioFlinger>& audioFlinger, audio_io_handle_t id,
1076 uint32_t device, type_t type)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001077 : Thread(false),
Glenn Kasten23bb8be2012-01-26 10:38:26 -08001078 mType(type),
Glenn Kasten84afa3b2012-01-25 15:28:08 -08001079 mAudioFlinger(audioFlinger), mSampleRate(0), mFrameCount(0),
1080 // mChannelMask
1081 mChannelCount(0),
1082 mFrameSize(1), mFormat(AUDIO_FORMAT_INVALID),
1083 mParamStatus(NO_ERROR),
Glenn Kastenb28686f2012-01-06 08:39:38 -08001084 mStandby(false), mId(id),
Glenn Kasten84afa3b2012-01-25 15:28:08 -08001085 mDevice(device),
1086 mDeathRecipient(new PMDeathRecipient(this))
Mathias Agopian65ab4712010-07-14 17:59:35 -07001087{
1088}
1089
1090AudioFlinger::ThreadBase::~ThreadBase()
1091{
1092 mParamCond.broadcast();
Eric Laurentfeb0db62011-07-22 09:04:31 -07001093 // do not lock the mutex in destructor
1094 releaseWakeLock_l();
Eric Laurent9d18ec52011-09-27 12:07:15 -07001095 if (mPowerManager != 0) {
1096 sp<IBinder> binder = mPowerManager->asBinder();
1097 binder->unlinkToDeath(mDeathRecipient);
1098 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07001099}
1100
1101void AudioFlinger::ThreadBase::exit()
1102{
Steve Block3856b092011-10-20 11:56:00 +01001103 ALOGV("ThreadBase::exit");
Mathias Agopian65ab4712010-07-14 17:59:35 -07001104 {
Glenn Kastenb28686f2012-01-06 08:39:38 -08001105 // This lock prevents the following race in thread (uniprocessor for illustration):
1106 // if (!exitPending()) {
1107 // // context switch from here to exit()
1108 // // exit() calls requestExit(), what exitPending() observes
1109 // // exit() calls signal(), which is dropped since no waiters
1110 // // context switch back from exit() to here
1111 // mWaitWorkCV.wait(...);
1112 // // now thread is hung
1113 // }
Glenn Kastena7d8d6f2012-01-05 15:41:56 -08001114 AutoMutex lock(mLock);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001115 requestExit();
1116 mWaitWorkCV.signal();
1117 }
Glenn Kastenb28686f2012-01-06 08:39:38 -08001118 // When Thread::requestExitAndWait is made virtual and this method is renamed to
1119 // "virtual status_t requestExitAndWait()", replace by "return Thread::requestExitAndWait();"
Mathias Agopian65ab4712010-07-14 17:59:35 -07001120 requestExitAndWait();
1121}
1122
Mathias Agopian65ab4712010-07-14 17:59:35 -07001123status_t AudioFlinger::ThreadBase::setParameters(const String8& keyValuePairs)
1124{
1125 status_t status;
1126
Steve Block3856b092011-10-20 11:56:00 +01001127 ALOGV("ThreadBase::setParameters() %s", keyValuePairs.string());
Mathias Agopian65ab4712010-07-14 17:59:35 -07001128 Mutex::Autolock _l(mLock);
1129
1130 mNewParameters.add(keyValuePairs);
1131 mWaitWorkCV.signal();
1132 // wait condition with timeout in case the thread loop has exited
1133 // before the request could be processed
Glenn Kasten7dede872011-12-13 11:04:14 -08001134 if (mParamCond.waitRelative(mLock, kSetParametersTimeoutNs) == NO_ERROR) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001135 status = mParamStatus;
1136 mWaitWorkCV.signal();
1137 } else {
1138 status = TIMED_OUT;
1139 }
1140 return status;
1141}
1142
1143void AudioFlinger::ThreadBase::sendConfigEvent(int event, int param)
1144{
1145 Mutex::Autolock _l(mLock);
1146 sendConfigEvent_l(event, param);
1147}
1148
1149// sendConfigEvent_l() must be called with ThreadBase::mLock held
1150void AudioFlinger::ThreadBase::sendConfigEvent_l(int event, int param)
1151{
Glenn Kastenf3990f22011-12-13 11:50:00 -08001152 ConfigEvent configEvent;
1153 configEvent.mEvent = event;
1154 configEvent.mParam = param;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001155 mConfigEvents.add(configEvent);
Steve Block3856b092011-10-20 11:56:00 +01001156 ALOGV("sendConfigEvent() num events %d event %d, param %d", mConfigEvents.size(), event, param);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001157 mWaitWorkCV.signal();
1158}
1159
1160void AudioFlinger::ThreadBase::processConfigEvents()
1161{
1162 mLock.lock();
1163 while(!mConfigEvents.isEmpty()) {
Steve Block3856b092011-10-20 11:56:00 +01001164 ALOGV("processConfigEvents() remaining events %d", mConfigEvents.size());
Glenn Kastenf3990f22011-12-13 11:50:00 -08001165 ConfigEvent configEvent = mConfigEvents[0];
Mathias Agopian65ab4712010-07-14 17:59:35 -07001166 mConfigEvents.removeAt(0);
1167 // release mLock before locking AudioFlinger mLock: lock order is always
1168 // AudioFlinger then ThreadBase to avoid cross deadlock
1169 mLock.unlock();
1170 mAudioFlinger->mLock.lock();
Glenn Kastenf3990f22011-12-13 11:50:00 -08001171 audioConfigChanged_l(configEvent.mEvent, configEvent.mParam);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001172 mAudioFlinger->mLock.unlock();
Mathias Agopian65ab4712010-07-14 17:59:35 -07001173 mLock.lock();
1174 }
1175 mLock.unlock();
1176}
1177
1178status_t AudioFlinger::ThreadBase::dumpBase(int fd, const Vector<String16>& args)
1179{
1180 const size_t SIZE = 256;
1181 char buffer[SIZE];
1182 String8 result;
1183
1184 bool locked = tryLock(mLock);
1185 if (!locked) {
1186 snprintf(buffer, SIZE, "thread %p maybe dead locked\n", this);
1187 write(fd, buffer, strlen(buffer));
1188 }
1189
1190 snprintf(buffer, SIZE, "standby: %d\n", mStandby);
1191 result.append(buffer);
1192 snprintf(buffer, SIZE, "Sample rate: %d\n", mSampleRate);
1193 result.append(buffer);
1194 snprintf(buffer, SIZE, "Frame count: %d\n", mFrameCount);
1195 result.append(buffer);
1196 snprintf(buffer, SIZE, "Channel Count: %d\n", mChannelCount);
1197 result.append(buffer);
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07001198 snprintf(buffer, SIZE, "Channel Mask: 0x%08x\n", mChannelMask);
1199 result.append(buffer);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001200 snprintf(buffer, SIZE, "Format: %d\n", mFormat);
1201 result.append(buffer);
Glenn Kastenb9980652012-01-11 09:48:27 -08001202 snprintf(buffer, SIZE, "Frame size: %u\n", mFrameSize);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001203 result.append(buffer);
1204
1205 snprintf(buffer, SIZE, "\nPending setParameters commands: \n");
1206 result.append(buffer);
1207 result.append(" Index Command");
1208 for (size_t i = 0; i < mNewParameters.size(); ++i) {
1209 snprintf(buffer, SIZE, "\n %02d ", i);
1210 result.append(buffer);
1211 result.append(mNewParameters[i]);
1212 }
1213
1214 snprintf(buffer, SIZE, "\n\nPending config events: \n");
1215 result.append(buffer);
1216 snprintf(buffer, SIZE, " Index event param\n");
1217 result.append(buffer);
1218 for (size_t i = 0; i < mConfigEvents.size(); i++) {
Glenn Kastenf3990f22011-12-13 11:50:00 -08001219 snprintf(buffer, SIZE, " %02d %02d %d\n", i, mConfigEvents[i].mEvent, mConfigEvents[i].mParam);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001220 result.append(buffer);
1221 }
1222 result.append("\n");
1223
1224 write(fd, result.string(), result.size());
1225
1226 if (locked) {
1227 mLock.unlock();
1228 }
1229 return NO_ERROR;
1230}
1231
Eric Laurent1d2bff02011-07-24 17:49:51 -07001232status_t AudioFlinger::ThreadBase::dumpEffectChains(int fd, const Vector<String16>& args)
1233{
1234 const size_t SIZE = 256;
1235 char buffer[SIZE];
1236 String8 result;
1237
1238 snprintf(buffer, SIZE, "\n- %d Effect Chains:\n", mEffectChains.size());
1239 write(fd, buffer, strlen(buffer));
1240
1241 for (size_t i = 0; i < mEffectChains.size(); ++i) {
1242 sp<EffectChain> chain = mEffectChains[i];
1243 if (chain != 0) {
1244 chain->dump(fd, args);
1245 }
1246 }
1247 return NO_ERROR;
1248}
1249
Eric Laurentfeb0db62011-07-22 09:04:31 -07001250void AudioFlinger::ThreadBase::acquireWakeLock()
1251{
1252 Mutex::Autolock _l(mLock);
1253 acquireWakeLock_l();
1254}
1255
1256void AudioFlinger::ThreadBase::acquireWakeLock_l()
1257{
1258 if (mPowerManager == 0) {
1259 // use checkService() to avoid blocking if power service is not up yet
1260 sp<IBinder> binder =
1261 defaultServiceManager()->checkService(String16("power"));
1262 if (binder == 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00001263 ALOGW("Thread %s cannot connect to the power manager service", mName);
Eric Laurentfeb0db62011-07-22 09:04:31 -07001264 } else {
1265 mPowerManager = interface_cast<IPowerManager>(binder);
1266 binder->linkToDeath(mDeathRecipient);
1267 }
1268 }
1269 if (mPowerManager != 0) {
1270 sp<IBinder> binder = new BBinder();
1271 status_t status = mPowerManager->acquireWakeLock(POWERMANAGER_PARTIAL_WAKE_LOCK,
1272 binder,
1273 String16(mName));
1274 if (status == NO_ERROR) {
1275 mWakeLockToken = binder;
1276 }
Steve Block3856b092011-10-20 11:56:00 +01001277 ALOGV("acquireWakeLock_l() %s status %d", mName, status);
Eric Laurentfeb0db62011-07-22 09:04:31 -07001278 }
1279}
1280
1281void AudioFlinger::ThreadBase::releaseWakeLock()
1282{
1283 Mutex::Autolock _l(mLock);
Eric Laurent6dbe8832011-07-28 13:59:02 -07001284 releaseWakeLock_l();
Eric Laurentfeb0db62011-07-22 09:04:31 -07001285}
1286
1287void AudioFlinger::ThreadBase::releaseWakeLock_l()
1288{
1289 if (mWakeLockToken != 0) {
Steve Block3856b092011-10-20 11:56:00 +01001290 ALOGV("releaseWakeLock_l() %s", mName);
Eric Laurentfeb0db62011-07-22 09:04:31 -07001291 if (mPowerManager != 0) {
1292 mPowerManager->releaseWakeLock(mWakeLockToken, 0);
1293 }
1294 mWakeLockToken.clear();
1295 }
1296}
1297
1298void AudioFlinger::ThreadBase::clearPowerManager()
1299{
1300 Mutex::Autolock _l(mLock);
1301 releaseWakeLock_l();
1302 mPowerManager.clear();
1303}
1304
1305void AudioFlinger::ThreadBase::PMDeathRecipient::binderDied(const wp<IBinder>& who)
1306{
1307 sp<ThreadBase> thread = mThread.promote();
1308 if (thread != 0) {
1309 thread->clearPowerManager();
1310 }
Steve Block5ff1dd52012-01-05 23:22:43 +00001311 ALOGW("power manager service died !!!");
Eric Laurentfeb0db62011-07-22 09:04:31 -07001312}
Eric Laurent1d2bff02011-07-24 17:49:51 -07001313
Eric Laurent59255e42011-07-27 19:49:51 -07001314void AudioFlinger::ThreadBase::setEffectSuspended(
1315 const effect_uuid_t *type, bool suspend, int sessionId)
1316{
1317 Mutex::Autolock _l(mLock);
1318 setEffectSuspended_l(type, suspend, sessionId);
1319}
1320
1321void AudioFlinger::ThreadBase::setEffectSuspended_l(
1322 const effect_uuid_t *type, bool suspend, int sessionId)
1323{
Glenn Kasten090f0192012-01-30 13:00:02 -08001324 sp<EffectChain> chain = getEffectChain_l(sessionId);
Eric Laurent59255e42011-07-27 19:49:51 -07001325 if (chain != 0) {
1326 if (type != NULL) {
1327 chain->setEffectSuspended_l(type, suspend);
1328 } else {
1329 chain->setEffectSuspendedAll_l(suspend);
1330 }
1331 }
1332
1333 updateSuspendedSessions_l(type, suspend, sessionId);
1334}
1335
1336void AudioFlinger::ThreadBase::checkSuspendOnAddEffectChain_l(const sp<EffectChain>& chain)
1337{
Glenn Kasten8d6a2442012-02-08 14:04:28 -08001338 ssize_t index = mSuspendedSessions.indexOfKey(chain->sessionId());
Eric Laurent59255e42011-07-27 19:49:51 -07001339 if (index < 0) {
1340 return;
1341 }
1342
1343 KeyedVector <int, sp<SuspendedSessionDesc> > sessionEffects =
1344 mSuspendedSessions.editValueAt(index);
1345
1346 for (size_t i = 0; i < sessionEffects.size(); i++) {
1347 sp <SuspendedSessionDesc> desc = sessionEffects.valueAt(i);
1348 for (int j = 0; j < desc->mRefCount; j++) {
1349 if (sessionEffects.keyAt(i) == EffectChain::kKeyForSuspendAll) {
1350 chain->setEffectSuspendedAll_l(true);
1351 } else {
Steve Block3856b092011-10-20 11:56:00 +01001352 ALOGV("checkSuspendOnAddEffectChain_l() suspending effects %08x",
Eric Laurent59255e42011-07-27 19:49:51 -07001353 desc->mType.timeLow);
1354 chain->setEffectSuspended_l(&desc->mType, true);
1355 }
1356 }
1357 }
1358}
1359
Eric Laurent59255e42011-07-27 19:49:51 -07001360void AudioFlinger::ThreadBase::updateSuspendedSessions_l(const effect_uuid_t *type,
1361 bool suspend,
1362 int sessionId)
1363{
Glenn Kasten8d6a2442012-02-08 14:04:28 -08001364 ssize_t index = mSuspendedSessions.indexOfKey(sessionId);
Eric Laurent59255e42011-07-27 19:49:51 -07001365
1366 KeyedVector <int, sp<SuspendedSessionDesc> > sessionEffects;
1367
1368 if (suspend) {
1369 if (index >= 0) {
1370 sessionEffects = mSuspendedSessions.editValueAt(index);
1371 } else {
1372 mSuspendedSessions.add(sessionId, sessionEffects);
1373 }
1374 } else {
1375 if (index < 0) {
1376 return;
1377 }
1378 sessionEffects = mSuspendedSessions.editValueAt(index);
1379 }
1380
1381
1382 int key = EffectChain::kKeyForSuspendAll;
1383 if (type != NULL) {
1384 key = type->timeLow;
1385 }
1386 index = sessionEffects.indexOfKey(key);
1387
1388 sp <SuspendedSessionDesc> desc;
1389 if (suspend) {
1390 if (index >= 0) {
1391 desc = sessionEffects.valueAt(index);
1392 } else {
1393 desc = new SuspendedSessionDesc();
1394 if (type != NULL) {
1395 memcpy(&desc->mType, type, sizeof(effect_uuid_t));
1396 }
1397 sessionEffects.add(key, desc);
Steve Block3856b092011-10-20 11:56:00 +01001398 ALOGV("updateSuspendedSessions_l() suspend adding effect %08x", key);
Eric Laurent59255e42011-07-27 19:49:51 -07001399 }
1400 desc->mRefCount++;
1401 } else {
1402 if (index < 0) {
1403 return;
1404 }
1405 desc = sessionEffects.valueAt(index);
1406 if (--desc->mRefCount == 0) {
Steve Block3856b092011-10-20 11:56:00 +01001407 ALOGV("updateSuspendedSessions_l() restore removing effect %08x", key);
Eric Laurent59255e42011-07-27 19:49:51 -07001408 sessionEffects.removeItemsAt(index);
1409 if (sessionEffects.isEmpty()) {
Steve Block3856b092011-10-20 11:56:00 +01001410 ALOGV("updateSuspendedSessions_l() restore removing session %d",
Eric Laurent59255e42011-07-27 19:49:51 -07001411 sessionId);
1412 mSuspendedSessions.removeItem(sessionId);
1413 }
1414 }
1415 }
1416 if (!sessionEffects.isEmpty()) {
1417 mSuspendedSessions.replaceValueFor(sessionId, sessionEffects);
1418 }
1419}
1420
1421void AudioFlinger::ThreadBase::checkSuspendOnEffectEnabled(const sp<EffectModule>& effect,
1422 bool enabled,
1423 int sessionId)
1424{
1425 Mutex::Autolock _l(mLock);
Eric Laurenta85a74a2011-10-19 11:44:54 -07001426 checkSuspendOnEffectEnabled_l(effect, enabled, sessionId);
1427}
Eric Laurent59255e42011-07-27 19:49:51 -07001428
Eric Laurenta85a74a2011-10-19 11:44:54 -07001429void AudioFlinger::ThreadBase::checkSuspendOnEffectEnabled_l(const sp<EffectModule>& effect,
1430 bool enabled,
1431 int sessionId)
1432{
Eric Laurentdb7c0792011-08-10 10:37:50 -07001433 if (mType != RECORD) {
1434 // suspend all effects in AUDIO_SESSION_OUTPUT_MIX when enabling any effect on
1435 // another session. This gives the priority to well behaved effect control panels
1436 // and applications not using global effects.
1437 if (sessionId != AUDIO_SESSION_OUTPUT_MIX) {
1438 setEffectSuspended_l(NULL, enabled, AUDIO_SESSION_OUTPUT_MIX);
1439 }
1440 }
Eric Laurent59255e42011-07-27 19:49:51 -07001441
1442 sp<EffectChain> chain = getEffectChain_l(sessionId);
1443 if (chain != 0) {
1444 chain->checkSuspendOnEffectEnabled(effect, enabled);
1445 }
1446}
1447
Mathias Agopian65ab4712010-07-14 17:59:35 -07001448// ----------------------------------------------------------------------------
1449
Eric Laurent7c7f10b2011-06-17 21:29:58 -07001450AudioFlinger::PlaybackThread::PlaybackThread(const sp<AudioFlinger>& audioFlinger,
1451 AudioStreamOut* output,
Glenn Kasten72ef00d2012-01-17 11:09:42 -08001452 audio_io_handle_t id,
Glenn Kasten23bb8be2012-01-26 10:38:26 -08001453 uint32_t device,
1454 type_t type)
1455 : ThreadBase(audioFlinger, id, device, type),
Glenn Kasten84afa3b2012-01-25 15:28:08 -08001456 mMixBuffer(NULL), mSuspended(0), mBytesWritten(0),
1457 // Assumes constructor is called by AudioFlinger with it's mLock held,
1458 // but it would be safer to explicitly pass initial masterMute as parameter
1459 mMasterMute(audioFlinger->masterMute_l()),
1460 // mStreamTypes[] initialized in constructor body
1461 mOutput(output),
1462 // Assumes constructor is called by AudioFlinger with it's mLock held,
1463 // but it would be safer to explicitly pass initial masterVolume as parameter
John Grossman4ff14ba2012-02-08 16:37:41 -08001464 mMasterVolume(audioFlinger->masterVolumeSW_l()),
Eric Laurent7c7f10b2011-06-17 21:29:58 -07001465 mLastWriteTime(0), mNumWrites(0), mNumDelayedWrites(0), mInWrite(false)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001466{
Glenn Kasten480b4682012-02-28 12:30:08 -08001467 snprintf(mName, kNameLength, "AudioOut_%X", id);
Eric Laurentfeb0db62011-07-22 09:04:31 -07001468
Mathias Agopian65ab4712010-07-14 17:59:35 -07001469 readOutputParameters();
1470
Glenn Kasten263709e2012-01-06 08:40:01 -08001471 // mStreamTypes[AUDIO_STREAM_CNT] is initialized by stream_type_t default constructor
Glenn Kastenfff6d712012-01-12 16:38:12 -08001472 // There is no AUDIO_STREAM_MIN, and ++ operator does not compile
1473 for (audio_stream_type_t stream = (audio_stream_type_t) 0; stream < AUDIO_STREAM_CNT;
1474 stream = (audio_stream_type_t) (stream + 1)) {
Glenn Kasten6637baa2012-01-09 09:40:36 -08001475 mStreamTypes[stream].volume = mAudioFlinger->streamVolume_l(stream);
1476 mStreamTypes[stream].mute = mAudioFlinger->streamMute_l(stream);
Glenn Kasten263709e2012-01-06 08:40:01 -08001477 // initialized by stream_type_t default constructor
1478 // mStreamTypes[stream].valid = true;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001479 }
Glenn Kasten6637baa2012-01-09 09:40:36 -08001480 // mStreamTypes[AUDIO_STREAM_CNT] exists but isn't explicitly initialized here,
1481 // because mAudioFlinger doesn't have one to copy from
Mathias Agopian65ab4712010-07-14 17:59:35 -07001482}
1483
1484AudioFlinger::PlaybackThread::~PlaybackThread()
1485{
1486 delete [] mMixBuffer;
1487}
1488
1489status_t AudioFlinger::PlaybackThread::dump(int fd, const Vector<String16>& args)
1490{
1491 dumpInternals(fd, args);
1492 dumpTracks(fd, args);
1493 dumpEffectChains(fd, args);
1494 return NO_ERROR;
1495}
1496
1497status_t AudioFlinger::PlaybackThread::dumpTracks(int fd, const Vector<String16>& args)
1498{
1499 const size_t SIZE = 256;
1500 char buffer[SIZE];
1501 String8 result;
1502
1503 snprintf(buffer, SIZE, "Output thread %p tracks\n", this);
1504 result.append(buffer);
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07001505 result.append(" Name Clien Typ Fmt Chn mask Session Buf S M F SRate LeftV RighV Serv User Main buf Aux Buf\n");
Mathias Agopian65ab4712010-07-14 17:59:35 -07001506 for (size_t i = 0; i < mTracks.size(); ++i) {
1507 sp<Track> track = mTracks[i];
1508 if (track != 0) {
1509 track->dump(buffer, SIZE);
1510 result.append(buffer);
1511 }
1512 }
1513
1514 snprintf(buffer, SIZE, "Output thread %p active tracks\n", this);
1515 result.append(buffer);
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07001516 result.append(" Name Clien Typ Fmt Chn mask Session Buf S M F SRate LeftV RighV Serv User Main buf Aux Buf\n");
Mathias Agopian65ab4712010-07-14 17:59:35 -07001517 for (size_t i = 0; i < mActiveTracks.size(); ++i) {
Glenn Kasten77c11192012-01-25 14:27:41 -08001518 sp<Track> track = mActiveTracks[i].promote();
1519 if (track != 0) {
1520 track->dump(buffer, SIZE);
1521 result.append(buffer);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001522 }
1523 }
1524 write(fd, result.string(), result.size());
1525 return NO_ERROR;
1526}
1527
Mathias Agopian65ab4712010-07-14 17:59:35 -07001528status_t AudioFlinger::PlaybackThread::dumpInternals(int fd, const Vector<String16>& args)
1529{
1530 const size_t SIZE = 256;
1531 char buffer[SIZE];
1532 String8 result;
1533
1534 snprintf(buffer, SIZE, "\nOutput thread %p internals\n", this);
1535 result.append(buffer);
1536 snprintf(buffer, SIZE, "last write occurred (msecs): %llu\n", ns2ms(systemTime() - mLastWriteTime));
1537 result.append(buffer);
1538 snprintf(buffer, SIZE, "total writes: %d\n", mNumWrites);
1539 result.append(buffer);
1540 snprintf(buffer, SIZE, "delayed writes: %d\n", mNumDelayedWrites);
1541 result.append(buffer);
1542 snprintf(buffer, SIZE, "blocked in write: %d\n", mInWrite);
1543 result.append(buffer);
1544 snprintf(buffer, SIZE, "suspend count: %d\n", mSuspended);
1545 result.append(buffer);
1546 snprintf(buffer, SIZE, "mix buffer : %p\n", mMixBuffer);
1547 result.append(buffer);
1548 write(fd, result.string(), result.size());
1549
1550 dumpBase(fd, args);
1551
1552 return NO_ERROR;
1553}
1554
1555// Thread virtuals
1556status_t AudioFlinger::PlaybackThread::readyToRun()
1557{
Eric Laurentb8ba0a92011-08-07 16:32:26 -07001558 status_t status = initCheck();
1559 if (status == NO_ERROR) {
Steve Blockdf64d152012-01-04 20:05:49 +00001560 ALOGI("AudioFlinger's thread %p ready to run", this);
Eric Laurentb8ba0a92011-08-07 16:32:26 -07001561 } else {
Steve Block29357bc2012-01-06 19:20:56 +00001562 ALOGE("No working audio driver found.");
Mathias Agopian65ab4712010-07-14 17:59:35 -07001563 }
Eric Laurentb8ba0a92011-08-07 16:32:26 -07001564 return status;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001565}
1566
1567void AudioFlinger::PlaybackThread::onFirstRef()
1568{
Eric Laurentfeb0db62011-07-22 09:04:31 -07001569 run(mName, ANDROID_PRIORITY_URGENT_AUDIO);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001570}
1571
1572// PlaybackThread::createTrack_l() must be called with AudioFlinger::mLock held
1573sp<AudioFlinger::PlaybackThread::Track> AudioFlinger::PlaybackThread::createTrack_l(
1574 const sp<AudioFlinger::Client>& client,
Glenn Kastenfff6d712012-01-12 16:38:12 -08001575 audio_stream_type_t streamType,
Mathias Agopian65ab4712010-07-14 17:59:35 -07001576 uint32_t sampleRate,
Glenn Kasten58f30212012-01-12 12:27:51 -08001577 audio_format_t format,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07001578 uint32_t channelMask,
Mathias Agopian65ab4712010-07-14 17:59:35 -07001579 int frameCount,
1580 const sp<IMemory>& sharedBuffer,
1581 int sessionId,
John Grossman4ff14ba2012-02-08 16:37:41 -08001582 bool isTimed,
Mathias Agopian65ab4712010-07-14 17:59:35 -07001583 status_t *status)
1584{
1585 sp<Track> track;
1586 status_t lStatus;
1587
1588 if (mType == DIRECT) {
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07001589 if ((format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM) {
1590 if (sampleRate != mSampleRate || format != mFormat || channelMask != mChannelMask) {
Steve Block29357bc2012-01-06 19:20:56 +00001591 ALOGE("createTrack_l() Bad parameter: sampleRate %d format %d, channelMask 0x%08x \""
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07001592 "for output %p with format %d",
1593 sampleRate, format, channelMask, mOutput, mFormat);
1594 lStatus = BAD_VALUE;
1595 goto Exit;
1596 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07001597 }
1598 } else {
1599 // Resampler implementation limits input sampling rate to 2 x output sampling rate.
1600 if (sampleRate > mSampleRate*2) {
Steve Block29357bc2012-01-06 19:20:56 +00001601 ALOGE("Sample rate out of range: %d mSampleRate %d", sampleRate, mSampleRate);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001602 lStatus = BAD_VALUE;
1603 goto Exit;
1604 }
1605 }
1606
Eric Laurent7c7f10b2011-06-17 21:29:58 -07001607 lStatus = initCheck();
1608 if (lStatus != NO_ERROR) {
Steve Block29357bc2012-01-06 19:20:56 +00001609 ALOGE("Audio driver not initialized.");
Mathias Agopian65ab4712010-07-14 17:59:35 -07001610 goto Exit;
1611 }
1612
1613 { // scope for mLock
1614 Mutex::Autolock _l(mLock);
Eric Laurentde070132010-07-13 04:45:46 -07001615
1616 // all tracks in same audio session must share the same routing strategy otherwise
1617 // conflicts will happen when tracks are moved from one output to another by audio policy
1618 // manager
Glenn Kasten02bbd202012-02-08 12:35:35 -08001619 uint32_t strategy = AudioSystem::getStrategyForStream(streamType);
Eric Laurentde070132010-07-13 04:45:46 -07001620 for (size_t i = 0; i < mTracks.size(); ++i) {
1621 sp<Track> t = mTracks[i];
1622 if (t != 0) {
Glenn Kasten02bbd202012-02-08 12:35:35 -08001623 uint32_t actual = AudioSystem::getStrategyForStream(t->streamType());
Glenn Kastend8796012011-10-28 10:31:42 -07001624 if (sessionId == t->sessionId() && strategy != actual) {
Steve Block29357bc2012-01-06 19:20:56 +00001625 ALOGE("createTrack_l() mismatched strategy; expected %u but found %u",
Glenn Kastend8796012011-10-28 10:31:42 -07001626 strategy, actual);
Eric Laurentde070132010-07-13 04:45:46 -07001627 lStatus = BAD_VALUE;
1628 goto Exit;
1629 }
1630 }
1631 }
1632
John Grossman4ff14ba2012-02-08 16:37:41 -08001633 if (!isTimed) {
1634 track = new Track(this, client, streamType, sampleRate, format,
1635 channelMask, frameCount, sharedBuffer, sessionId);
1636 } else {
1637 track = TimedTrack::create(this, client, streamType, sampleRate, format,
1638 channelMask, frameCount, sharedBuffer, sessionId);
1639 }
1640 if (track == NULL || track->getCblk() == NULL || track->name() < 0) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001641 lStatus = NO_MEMORY;
1642 goto Exit;
1643 }
1644 mTracks.add(track);
1645
1646 sp<EffectChain> chain = getEffectChain_l(sessionId);
1647 if (chain != 0) {
Steve Block3856b092011-10-20 11:56:00 +01001648 ALOGV("createTrack_l() setting main buffer %p", chain->inBuffer());
Mathias Agopian65ab4712010-07-14 17:59:35 -07001649 track->setMainBuffer(chain->inBuffer());
Glenn Kasten02bbd202012-02-08 12:35:35 -08001650 chain->setStrategy(AudioSystem::getStrategyForStream(track->streamType()));
Eric Laurentb469b942011-05-09 12:09:06 -07001651 chain->incTrackCnt();
Mathias Agopian65ab4712010-07-14 17:59:35 -07001652 }
Eric Laurent9f6530f2011-08-30 10:18:54 -07001653
1654 // invalidate track immediately if the stream type was moved to another thread since
1655 // createTrack() was called by the client process.
1656 if (!mStreamTypes[streamType].valid) {
Steve Block5ff1dd52012-01-05 23:22:43 +00001657 ALOGW("createTrack_l() on thread %p: invalidating track on stream %d",
Eric Laurent9f6530f2011-08-30 10:18:54 -07001658 this, streamType);
1659 android_atomic_or(CBLK_INVALID_ON, &track->mCblk->flags);
1660 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07001661 }
1662 lStatus = NO_ERROR;
1663
1664Exit:
1665 if(status) {
1666 *status = lStatus;
1667 }
1668 return track;
1669}
1670
1671uint32_t AudioFlinger::PlaybackThread::latency() const
1672{
Eric Laurentb8ba0a92011-08-07 16:32:26 -07001673 Mutex::Autolock _l(mLock);
1674 if (initCheck() == NO_ERROR) {
Dima Zavin799a70e2011-04-18 16:57:27 -07001675 return mOutput->stream->get_latency(mOutput->stream);
Eric Laurentb8ba0a92011-08-07 16:32:26 -07001676 } else {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001677 return 0;
1678 }
1679}
1680
Glenn Kasten6637baa2012-01-09 09:40:36 -08001681void AudioFlinger::PlaybackThread::setMasterVolume(float value)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001682{
Glenn Kasten6637baa2012-01-09 09:40:36 -08001683 Mutex::Autolock _l(mLock);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001684 mMasterVolume = value;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001685}
1686
Glenn Kasten6637baa2012-01-09 09:40:36 -08001687void AudioFlinger::PlaybackThread::setMasterMute(bool muted)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001688{
Glenn Kasten6637baa2012-01-09 09:40:36 -08001689 Mutex::Autolock _l(mLock);
1690 setMasterMute_l(muted);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001691}
1692
Glenn Kasten6637baa2012-01-09 09:40:36 -08001693void AudioFlinger::PlaybackThread::setStreamVolume(audio_stream_type_t stream, float value)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001694{
Glenn Kasten6637baa2012-01-09 09:40:36 -08001695 Mutex::Autolock _l(mLock);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001696 mStreamTypes[stream].volume = value;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001697}
1698
Glenn Kasten6637baa2012-01-09 09:40:36 -08001699void AudioFlinger::PlaybackThread::setStreamMute(audio_stream_type_t stream, bool muted)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001700{
Glenn Kasten6637baa2012-01-09 09:40:36 -08001701 Mutex::Autolock _l(mLock);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001702 mStreamTypes[stream].mute = muted;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001703}
1704
Glenn Kastenfff6d712012-01-12 16:38:12 -08001705float AudioFlinger::PlaybackThread::streamVolume(audio_stream_type_t stream) const
Mathias Agopian65ab4712010-07-14 17:59:35 -07001706{
Glenn Kasten6637baa2012-01-09 09:40:36 -08001707 Mutex::Autolock _l(mLock);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001708 return mStreamTypes[stream].volume;
1709}
1710
Mathias Agopian65ab4712010-07-14 17:59:35 -07001711// addTrack_l() must be called with ThreadBase::mLock held
1712status_t AudioFlinger::PlaybackThread::addTrack_l(const sp<Track>& track)
1713{
1714 status_t status = ALREADY_EXISTS;
1715
1716 // set retry count for buffer fill
1717 track->mRetryCount = kMaxTrackStartupRetries;
1718 if (mActiveTracks.indexOf(track) < 0) {
1719 // the track is newly added, make sure it fills up all its
1720 // buffers before playing. This is to ensure the client will
1721 // effectively get the latency it requested.
1722 track->mFillingUpStatus = Track::FS_FILLING;
1723 track->mResetDone = false;
1724 mActiveTracks.add(track);
1725 if (track->mainBuffer() != mMixBuffer) {
1726 sp<EffectChain> chain = getEffectChain_l(track->sessionId());
1727 if (chain != 0) {
Steve Block3856b092011-10-20 11:56:00 +01001728 ALOGV("addTrack_l() starting track on chain %p for session %d", chain.get(), track->sessionId());
Eric Laurentb469b942011-05-09 12:09:06 -07001729 chain->incActiveTrackCnt();
Mathias Agopian65ab4712010-07-14 17:59:35 -07001730 }
1731 }
1732
1733 status = NO_ERROR;
1734 }
1735
Steve Block3856b092011-10-20 11:56:00 +01001736 ALOGV("mWaitWorkCV.broadcast");
Mathias Agopian65ab4712010-07-14 17:59:35 -07001737 mWaitWorkCV.broadcast();
1738
1739 return status;
1740}
1741
1742// destroyTrack_l() must be called with ThreadBase::mLock held
1743void AudioFlinger::PlaybackThread::destroyTrack_l(const sp<Track>& track)
1744{
1745 track->mState = TrackBase::TERMINATED;
1746 if (mActiveTracks.indexOf(track) < 0) {
Eric Laurentb469b942011-05-09 12:09:06 -07001747 removeTrack_l(track);
1748 }
1749}
1750
1751void AudioFlinger::PlaybackThread::removeTrack_l(const sp<Track>& track)
1752{
1753 mTracks.remove(track);
1754 deleteTrackName_l(track->name());
1755 sp<EffectChain> chain = getEffectChain_l(track->sessionId());
1756 if (chain != 0) {
1757 chain->decTrackCnt();
Mathias Agopian65ab4712010-07-14 17:59:35 -07001758 }
1759}
1760
1761String8 AudioFlinger::PlaybackThread::getParameters(const String8& keys)
1762{
Eric Laurentb8ba0a92011-08-07 16:32:26 -07001763 String8 out_s8 = String8("");
Dima Zavinfce7a472011-04-19 22:30:36 -07001764 char *s;
1765
Eric Laurentb8ba0a92011-08-07 16:32:26 -07001766 Mutex::Autolock _l(mLock);
1767 if (initCheck() != NO_ERROR) {
1768 return out_s8;
1769 }
1770
Dima Zavin799a70e2011-04-18 16:57:27 -07001771 s = mOutput->stream->common.get_parameters(&mOutput->stream->common, keys.string());
Dima Zavinfce7a472011-04-19 22:30:36 -07001772 out_s8 = String8(s);
1773 free(s);
1774 return out_s8;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001775}
1776
Eric Laurentb8ba0a92011-08-07 16:32:26 -07001777// audioConfigChanged_l() must be called with AudioFlinger::mLock held
Mathias Agopian65ab4712010-07-14 17:59:35 -07001778void AudioFlinger::PlaybackThread::audioConfigChanged_l(int event, int param) {
1779 AudioSystem::OutputDescriptor desc;
Glenn Kastena0d68332012-01-27 16:47:15 -08001780 void *param2 = NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001781
Steve Block3856b092011-10-20 11:56:00 +01001782 ALOGV("PlaybackThread::audioConfigChanged_l, thread %p, event %d, param %d", this, event, param);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001783
1784 switch (event) {
1785 case AudioSystem::OUTPUT_OPENED:
1786 case AudioSystem::OUTPUT_CONFIG_CHANGED:
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07001787 desc.channels = mChannelMask;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001788 desc.samplingRate = mSampleRate;
1789 desc.format = mFormat;
1790 desc.frameCount = mFrameCount;
1791 desc.latency = latency();
1792 param2 = &desc;
1793 break;
1794
1795 case AudioSystem::STREAM_CONFIG_CHANGED:
1796 param2 = &param;
1797 case AudioSystem::OUTPUT_CLOSED:
1798 default:
1799 break;
1800 }
1801 mAudioFlinger->audioConfigChanged_l(event, mId, param2);
1802}
1803
1804void AudioFlinger::PlaybackThread::readOutputParameters()
1805{
Dima Zavin799a70e2011-04-18 16:57:27 -07001806 mSampleRate = mOutput->stream->common.get_sample_rate(&mOutput->stream->common);
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07001807 mChannelMask = mOutput->stream->common.get_channels(&mOutput->stream->common);
1808 mChannelCount = (uint16_t)popcount(mChannelMask);
Dima Zavin799a70e2011-04-18 16:57:27 -07001809 mFormat = mOutput->stream->common.get_format(&mOutput->stream->common);
Glenn Kastenb9980652012-01-11 09:48:27 -08001810 mFrameSize = audio_stream_frame_size(&mOutput->stream->common);
Dima Zavin799a70e2011-04-18 16:57:27 -07001811 mFrameCount = mOutput->stream->common.get_buffer_size(&mOutput->stream->common) / mFrameSize;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001812
1813 // FIXME - Current mixer implementation only supports stereo output: Always
1814 // Allocate a stereo buffer even if HW output is mono.
Glenn Kastene9dd0172012-01-27 18:08:45 -08001815 delete[] mMixBuffer;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001816 mMixBuffer = new int16_t[mFrameCount * 2];
1817 memset(mMixBuffer, 0, mFrameCount * 2 * sizeof(int16_t));
1818
Eric Laurentde070132010-07-13 04:45:46 -07001819 // force reconfiguration of effect chains and engines to take new buffer size and audio
1820 // parameters into account
1821 // Note that mLock is not held when readOutputParameters() is called from the constructor
1822 // but in this case nothing is done below as no audio sessions have effect yet so it doesn't
1823 // matter.
1824 // create a copy of mEffectChains as calling moveEffectChain_l() can reorder some effect chains
1825 Vector< sp<EffectChain> > effectChains = mEffectChains;
1826 for (size_t i = 0; i < effectChains.size(); i ++) {
Eric Laurent39e94f82010-07-28 01:32:47 -07001827 mAudioFlinger->moveEffectChain_l(effectChains[i]->sessionId(), this, this, false);
Eric Laurentde070132010-07-13 04:45:46 -07001828 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07001829}
1830
1831status_t AudioFlinger::PlaybackThread::getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames)
1832{
Glenn Kastena0d68332012-01-27 16:47:15 -08001833 if (halFrames == NULL || dspFrames == NULL) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001834 return BAD_VALUE;
1835 }
Eric Laurentb8ba0a92011-08-07 16:32:26 -07001836 Mutex::Autolock _l(mLock);
Eric Laurent7c7f10b2011-06-17 21:29:58 -07001837 if (initCheck() != NO_ERROR) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001838 return INVALID_OPERATION;
1839 }
Dima Zavin799a70e2011-04-18 16:57:27 -07001840 *halFrames = mBytesWritten / audio_stream_frame_size(&mOutput->stream->common);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001841
Dima Zavin799a70e2011-04-18 16:57:27 -07001842 return mOutput->stream->get_render_position(mOutput->stream, dspFrames);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001843}
1844
Eric Laurent39e94f82010-07-28 01:32:47 -07001845uint32_t AudioFlinger::PlaybackThread::hasAudioSession(int sessionId)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001846{
1847 Mutex::Autolock _l(mLock);
Eric Laurent39e94f82010-07-28 01:32:47 -07001848 uint32_t result = 0;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001849 if (getEffectChain_l(sessionId) != 0) {
Eric Laurent39e94f82010-07-28 01:32:47 -07001850 result = EFFECT_SESSION;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001851 }
1852
1853 for (size_t i = 0; i < mTracks.size(); ++i) {
1854 sp<Track> track = mTracks[i];
Eric Laurentde070132010-07-13 04:45:46 -07001855 if (sessionId == track->sessionId() &&
1856 !(track->mCblk->flags & CBLK_INVALID_MSK)) {
Eric Laurent39e94f82010-07-28 01:32:47 -07001857 result |= TRACK_SESSION;
1858 break;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001859 }
1860 }
1861
Eric Laurent39e94f82010-07-28 01:32:47 -07001862 return result;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001863}
1864
Eric Laurentde070132010-07-13 04:45:46 -07001865uint32_t AudioFlinger::PlaybackThread::getStrategyForSession_l(int sessionId)
1866{
Dima Zavinfce7a472011-04-19 22:30:36 -07001867 // session AUDIO_SESSION_OUTPUT_MIX is placed in same strategy as MUSIC stream so that
Eric Laurentde070132010-07-13 04:45:46 -07001868 // it is moved to correct output by audio policy manager when A2DP is connected or disconnected
Dima Zavinfce7a472011-04-19 22:30:36 -07001869 if (sessionId == AUDIO_SESSION_OUTPUT_MIX) {
1870 return AudioSystem::getStrategyForStream(AUDIO_STREAM_MUSIC);
Eric Laurentde070132010-07-13 04:45:46 -07001871 }
1872 for (size_t i = 0; i < mTracks.size(); i++) {
1873 sp<Track> track = mTracks[i];
1874 if (sessionId == track->sessionId() &&
1875 !(track->mCblk->flags & CBLK_INVALID_MSK)) {
Glenn Kasten02bbd202012-02-08 12:35:35 -08001876 return AudioSystem::getStrategyForStream(track->streamType());
Eric Laurentde070132010-07-13 04:45:46 -07001877 }
1878 }
Dima Zavinfce7a472011-04-19 22:30:36 -07001879 return AudioSystem::getStrategyForStream(AUDIO_STREAM_MUSIC);
Eric Laurentde070132010-07-13 04:45:46 -07001880}
1881
Mathias Agopian65ab4712010-07-14 17:59:35 -07001882
Glenn Kastenaed850d2012-01-26 09:46:34 -08001883AudioFlinger::AudioStreamOut* AudioFlinger::PlaybackThread::getOutput() const
Eric Laurentb8ba0a92011-08-07 16:32:26 -07001884{
1885 Mutex::Autolock _l(mLock);
1886 return mOutput;
1887}
1888
1889AudioFlinger::AudioStreamOut* AudioFlinger::PlaybackThread::clearOutput()
1890{
1891 Mutex::Autolock _l(mLock);
1892 AudioStreamOut *output = mOutput;
1893 mOutput = NULL;
1894 return output;
1895}
1896
1897// this method must always be called either with ThreadBase mLock held or inside the thread loop
1898audio_stream_t* AudioFlinger::PlaybackThread::stream()
1899{
1900 if (mOutput == NULL) {
1901 return NULL;
1902 }
1903 return &mOutput->stream->common;
1904}
1905
Eric Laurent162b40b2011-12-05 09:47:19 -08001906uint32_t AudioFlinger::PlaybackThread::activeSleepTimeUs()
1907{
1908 // A2DP output latency is not due only to buffering capacity. It also reflects encoding,
1909 // decoding and transfer time. So sleeping for half of the latency would likely cause
1910 // underruns
1911 if (audio_is_a2dp_device((audio_devices_t)mDevice)) {
1912 return (uint32_t)((uint32_t)((mFrameCount * 1000) / mSampleRate) * 1000);
1913 } else {
1914 return (uint32_t)(mOutput->stream->get_latency(mOutput->stream) * 1000) / 2;
1915 }
1916}
1917
Mathias Agopian65ab4712010-07-14 17:59:35 -07001918// ----------------------------------------------------------------------------
1919
Glenn Kasten23bb8be2012-01-26 10:38:26 -08001920AudioFlinger::MixerThread::MixerThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output,
Glenn Kasten72ef00d2012-01-17 11:09:42 -08001921 audio_io_handle_t id, uint32_t device, type_t type)
Glenn Kasten000f0e32012-03-01 17:10:56 -08001922 : PlaybackThread(audioFlinger, output, id, device, type)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001923{
Glenn Kasten000f0e32012-03-01 17:10:56 -08001924 mAudioMixer = new AudioMixer(mFrameCount, mSampleRate);
1925 mPrevMixerStatus = MIXER_IDLE;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001926 // FIXME - Current mixer implementation only supports stereo output
1927 if (mChannelCount == 1) {
Steve Block29357bc2012-01-06 19:20:56 +00001928 ALOGE("Invalid audio hardware channel count");
Mathias Agopian65ab4712010-07-14 17:59:35 -07001929 }
1930}
1931
1932AudioFlinger::MixerThread::~MixerThread()
1933{
1934 delete mAudioMixer;
1935}
1936
Glenn Kasten83efdd02012-02-24 07:21:32 -08001937class CpuStats {
1938public:
1939 void sample();
1940#ifdef DEBUG_CPU_USAGE
1941private:
1942 ThreadCpuUsage mCpu;
1943#endif
1944};
1945
1946void CpuStats::sample() {
1947#ifdef DEBUG_CPU_USAGE
1948 const CentralTendencyStatistics& stats = mCpu.statistics();
1949 mCpu.sampleAndEnable();
1950 unsigned n = stats.n();
1951 // mCpu.elapsed() is expensive, so don't call it every loop
1952 if ((n & 127) == 1) {
1953 long long elapsed = mCpu.elapsed();
1954 if (elapsed >= DEBUG_CPU_USAGE * 1000000000LL) {
1955 double perLoop = elapsed / (double) n;
1956 double perLoop100 = perLoop * 0.01;
1957 double mean = stats.mean();
1958 double stddev = stats.stddev();
1959 double minimum = stats.minimum();
1960 double maximum = stats.maximum();
1961 mCpu.resetStatistics();
1962 ALOGI("CPU usage over past %.1f secs (%u mixer loops at %.1f mean ms per loop):\n us per mix loop: mean=%.0f stddev=%.0f min=%.0f max=%.0f\n %% of wall: mean=%.1f stddev=%.1f min=%.1f max=%.1f",
1963 elapsed * .000000001, n, perLoop * .000001,
1964 mean * .001,
1965 stddev * .001,
1966 minimum * .001,
1967 maximum * .001,
1968 mean / perLoop100,
1969 stddev / perLoop100,
1970 minimum / perLoop100,
1971 maximum / perLoop100);
1972 }
1973 }
1974#endif
1975};
1976
Glenn Kasten37d825e2012-02-24 07:21:48 -08001977void AudioFlinger::PlaybackThread::checkSilentMode_l()
1978{
1979 if (!mMasterMute) {
1980 char value[PROPERTY_VALUE_MAX];
1981 if (property_get("ro.audio.silent", value, "0") > 0) {
1982 char *endptr;
1983 unsigned long ul = strtoul(value, &endptr, 0);
1984 if (*endptr == '\0' && ul != 0) {
1985 ALOGD("Silence is golden");
1986 // The setprop command will not allow a property to be changed after
1987 // the first time it is set, so we don't have to worry about un-muting.
1988 setMasterMute_l(true);
1989 }
1990 }
1991 }
1992}
1993
Glenn Kasten000f0e32012-03-01 17:10:56 -08001994bool AudioFlinger::PlaybackThread::threadLoop()
Mathias Agopian65ab4712010-07-14 17:59:35 -07001995{
1996 Vector< sp<Track> > tracksToRemove;
Glenn Kasten688a6402012-02-29 07:57:06 -08001997
Glenn Kasten000f0e32012-03-01 17:10:56 -08001998 standbyTime = systemTime();
1999 mixBufferSize = mFrameCount * mFrameSize;
2000
2001 // MIXER
Mathias Agopian65ab4712010-07-14 17:59:35 -07002002 // FIXME: Relaxed timing because of a certain device that can't meet latency
2003 // Should be reduced to 2x after the vendor fixes the driver issue
Eric Laurent5c4e8182011-10-18 15:42:27 -07002004 // increase threshold again due to low power audio mode. The way this warning threshold is
2005 // calculated and its usefulness should be reconsidered anyway.
2006 nsecs_t maxPeriod = seconds(mFrameCount) / mSampleRate * 15;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002007 nsecs_t lastWarning = 0;
Glenn Kasten000f0e32012-03-01 17:10:56 -08002008if (mType == MIXER) {
2009 longStandbyExit = false;
2010}
Glenn Kasten688a6402012-02-29 07:57:06 -08002011
Glenn Kasten000f0e32012-03-01 17:10:56 -08002012 // DUPLICATING
2013 // FIXME could this be made local to while loop?
2014 writeFrames = 0;
Glenn Kasten688a6402012-02-29 07:57:06 -08002015
Glenn Kasten000f0e32012-03-01 17:10:56 -08002016 activeSleepTime = activeSleepTimeUs();
2017 idleSleepTime = idleSleepTimeUs();
2018 sleepTime = idleSleepTime;
2019
2020if (mType == MIXER) {
2021 sleepTimeShift = 0;
2022}
2023
2024 // MIXER
Glenn Kasten83efdd02012-02-24 07:21:32 -08002025 CpuStats cpuStats;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002026
Glenn Kasten000f0e32012-03-01 17:10:56 -08002027 // DIRECT
2028if (mType == DIRECT) {
2029 // use shorter standby delay as on normal output to release
2030 // hardware resources as soon as possible
2031 standbyDelay = microseconds(activeSleepTime*2);
2032}
Glenn Kasten688a6402012-02-29 07:57:06 -08002033
Eric Laurentfeb0db62011-07-22 09:04:31 -07002034 acquireWakeLock();
2035
Mathias Agopian65ab4712010-07-14 17:59:35 -07002036 while (!exitPending())
2037 {
Glenn Kasten000f0e32012-03-01 17:10:56 -08002038if (mType == MIXER) {
Glenn Kasten83efdd02012-02-24 07:21:32 -08002039 cpuStats.sample();
Glenn Kasten000f0e32012-03-01 17:10:56 -08002040}
Glenn Kasten688a6402012-02-29 07:57:06 -08002041
Glenn Kasten73ca0f52012-02-29 07:56:15 -08002042 Vector< sp<EffectChain> > effectChains;
2043
Mathias Agopian65ab4712010-07-14 17:59:35 -07002044 processConfigEvents();
2045
Glenn Kasten000f0e32012-03-01 17:10:56 -08002046 mixerStatus = MIXER_IDLE;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002047 { // scope for mLock
2048
2049 Mutex::Autolock _l(mLock);
2050
2051 if (checkForNewParameters_l()) {
2052 mixBufferSize = mFrameCount * mFrameSize;
Glenn Kasten688a6402012-02-29 07:57:06 -08002053
Glenn Kasten000f0e32012-03-01 17:10:56 -08002054if (mType == MIXER) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07002055 // FIXME: Relaxed timing because of a certain device that can't meet latency
2056 // Should be reduced to 2x after the vendor fixes the driver issue
Eric Laurent5c4e8182011-10-18 15:42:27 -07002057 // increase threshold again due to low power audio mode. The way this warning
2058 // threshold is calculated and its usefulness should be reconsidered anyway.
2059 maxPeriod = seconds(mFrameCount) / mSampleRate * 15;
Glenn Kasten000f0e32012-03-01 17:10:56 -08002060}
2061
Glenn Kasten438b0362012-03-06 11:24:48 -08002062 updateWaitTime_l();
Glenn Kasten688a6402012-02-29 07:57:06 -08002063
Mathias Agopian65ab4712010-07-14 17:59:35 -07002064 activeSleepTime = activeSleepTimeUs();
2065 idleSleepTime = idleSleepTimeUs();
Glenn Kasten000f0e32012-03-01 17:10:56 -08002066
2067if (mType == DIRECT) {
2068 standbyDelay = microseconds(activeSleepTime*2);
2069}
2070
Mathias Agopian65ab4712010-07-14 17:59:35 -07002071 }
2072
Glenn Kastenfa26a852012-03-06 11:28:04 -08002073 saveOutputTracks();
Glenn Kasten000f0e32012-03-01 17:10:56 -08002074
Mathias Agopian65ab4712010-07-14 17:59:35 -07002075 // put audio hardware into standby after short delay
Glenn Kasten3e074702012-02-28 18:40:35 -08002076 if (CC_UNLIKELY((!mActiveTracks.size() && systemTime() > standbyTime) ||
Glenn Kastenc455fe92012-02-29 07:07:30 -08002077 mSuspended > 0)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07002078 if (!mStandby) {
Glenn Kasten000f0e32012-03-01 17:10:56 -08002079
2080 threadLoop_standby();
2081
Mathias Agopian65ab4712010-07-14 17:59:35 -07002082 mStandby = true;
2083 mBytesWritten = 0;
2084 }
2085
Glenn Kasten3e074702012-02-28 18:40:35 -08002086 if (!mActiveTracks.size() && mConfigEvents.isEmpty()) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07002087 // we're about to wait, flush the binder command buffer
2088 IPCThreadState::self()->flushCommands();
2089
Glenn Kastenfa26a852012-03-06 11:28:04 -08002090 clearOutputTracks();
Glenn Kasten000f0e32012-03-01 17:10:56 -08002091
Mathias Agopian65ab4712010-07-14 17:59:35 -07002092 if (exitPending()) break;
2093
Eric Laurentfeb0db62011-07-22 09:04:31 -07002094 releaseWakeLock_l();
Mathias Agopian65ab4712010-07-14 17:59:35 -07002095 // wait until we have something to do...
Glenn Kastenc0b52832012-02-24 11:18:09 -08002096 ALOGV("Thread %p type %d TID %d going to sleep", this, mType, gettid());
Mathias Agopian65ab4712010-07-14 17:59:35 -07002097 mWaitWorkCV.wait(mLock);
Glenn Kastenc0b52832012-02-24 11:18:09 -08002098 ALOGV("Thread %p type %d TID %d waking up", this, mType, gettid());
Eric Laurentfeb0db62011-07-22 09:04:31 -07002099 acquireWakeLock_l();
Mathias Agopian65ab4712010-07-14 17:59:35 -07002100
Glenn Kasten000f0e32012-03-01 17:10:56 -08002101if (mType == MIXER || mType == DUPLICATING) {
Eric Laurent27741442012-01-17 19:20:12 -08002102 mPrevMixerStatus = MIXER_IDLE;
Glenn Kasten000f0e32012-03-01 17:10:56 -08002103}
2104
Glenn Kasten37d825e2012-02-24 07:21:48 -08002105 checkSilentMode_l();
Mathias Agopian65ab4712010-07-14 17:59:35 -07002106
Glenn Kasten000f0e32012-03-01 17:10:56 -08002107if (mType == MIXER || mType == DUPLICATING) {
John Grossman4ff14ba2012-02-08 16:37:41 -08002108 standbyTime = systemTime() + mStandbyTimeInNsecs;
Glenn Kasten000f0e32012-03-01 17:10:56 -08002109}
2110
2111if (mType == DIRECT) {
2112 standbyTime = systemTime() + standbyDelay;
2113}
2114
Mathias Agopian65ab4712010-07-14 17:59:35 -07002115 sleepTime = idleSleepTime;
Glenn Kasten000f0e32012-03-01 17:10:56 -08002116
2117if (mType == MIXER) {
Eric Laurent7cafbb32011-11-22 18:50:29 -08002118 sleepTimeShift = 0;
Glenn Kasten000f0e32012-03-01 17:10:56 -08002119}
2120
Mathias Agopian65ab4712010-07-14 17:59:35 -07002121 continue;
2122 }
2123 }
2124
Glenn Kasten3e074702012-02-28 18:40:35 -08002125 mixerStatus = prepareTracks_l(&tracksToRemove);
Glenn Kasten000f0e32012-03-01 17:10:56 -08002126 // see FIXME in AudioFlinger.h
2127 if (mixerStatus == MIXER_CONTINUE) {
2128 continue;
2129 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07002130
2131 // prevent any changes in effect chain list and in each effect chain
2132 // during mixing and effect process as the audio buffers could be deleted
2133 // or modified if an effect is created or deleted
Eric Laurentde070132010-07-13 04:45:46 -07002134 lockEffectChains_l(effectChains);
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -08002135 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07002136
Glenn Kastenf6b16782011-12-15 09:51:17 -08002137 if (CC_LIKELY(mixerStatus == MIXER_TRACKS_READY)) {
Glenn Kasten000f0e32012-03-01 17:10:56 -08002138 threadLoop_mix();
2139 } else {
2140 threadLoop_sleepTime();
2141 }
2142
2143 if (mSuspended > 0) {
2144 sleepTime = suspendSleepTimeUs();
2145 }
2146
2147 // only process effects if we're going to write
2148 if (sleepTime == 0) {
Glenn Kasten000f0e32012-03-01 17:10:56 -08002149 for (size_t i = 0; i < effectChains.size(); i ++) {
2150 effectChains[i]->process_l();
2151 }
2152 }
2153
2154 // enable changes in effect chain
2155 unlockEffectChains(effectChains);
2156
2157 // sleepTime == 0 means we must write to audio hardware
2158 if (sleepTime == 0) {
2159
2160 threadLoop_write();
2161
2162if (mType == MIXER) {
2163 // write blocked detection
2164 nsecs_t now = systemTime();
2165 nsecs_t delta = now - mLastWriteTime;
2166 if (!mStandby && delta > maxPeriod) {
2167 mNumDelayedWrites++;
2168 if ((now - lastWarning) > kWarningThrottleNs) {
2169 ALOGW("write blocked for %llu msecs, %d delayed writes, thread %p",
2170 ns2ms(delta), mNumDelayedWrites, this);
2171 lastWarning = now;
2172 }
2173 // FIXME this is broken: longStandbyExit should be handled out of the if() and with
2174 // a different threshold. Or completely removed for what it is worth anyway...
2175 if (mStandby) {
2176 longStandbyExit = true;
2177 }
2178 }
2179}
2180
2181 mStandby = false;
2182 } else {
2183 usleep(sleepTime);
2184 }
2185
2186 // finally let go of removed track(s), without the lock held
2187 // since we can't guarantee the destructors won't acquire that
2188 // same lock.
Glenn Kasten1465f0c2012-03-06 11:23:32 -08002189 tracksToRemove.clear();
Glenn Kasten000f0e32012-03-01 17:10:56 -08002190
Glenn Kastenfa26a852012-03-06 11:28:04 -08002191 // FIXME I don't understand the need for this here;
2192 // it was in the original code but maybe the
2193 // assignment in saveOutputTracks() makes this unnecessary?
2194 clearOutputTracks();
Glenn Kasten000f0e32012-03-01 17:10:56 -08002195
2196 // Effect chains will be actually deleted here if they were removed from
2197 // mEffectChains list during mixing or effects processing
2198 effectChains.clear();
2199
2200 // FIXME Note that the above .clear() is no longer necessary since effectChains
2201 // is now local to this block, but will keep it for now (at least until merge done).
2202 }
2203
2204if (mType == MIXER || mType == DIRECT) {
2205 // put output stream into standby mode
2206 if (!mStandby) {
2207 mOutput->stream->common.standby(&mOutput->stream->common);
2208 }
2209}
2210if (mType == DUPLICATING) {
2211 // for DuplicatingThread, standby mode is handled by the outputTracks
2212}
2213
2214 releaseWakeLock();
2215
2216 ALOGV("Thread %p type %d exiting", this, mType);
2217 return false;
2218}
2219
2220// shared by MIXER and DIRECT, overridden by DUPLICATING
2221void AudioFlinger::PlaybackThread::threadLoop_write()
2222{
Glenn Kasten952eeb22012-03-06 11:30:57 -08002223 // FIXME rewrite to reduce number of system calls
2224 mLastWriteTime = systemTime();
2225 mInWrite = true;
2226 mBytesWritten += mixBufferSize;
2227 int bytesWritten = (int)mOutput->stream->write(mOutput->stream, mMixBuffer, mixBufferSize);
2228 if (bytesWritten < 0) mBytesWritten -= mixBufferSize;
2229 mNumWrites++;
2230 mInWrite = false;
Glenn Kasten000f0e32012-03-01 17:10:56 -08002231}
2232
2233// shared by MIXER and DIRECT, overridden by DUPLICATING
2234void AudioFlinger::PlaybackThread::threadLoop_standby()
2235{
Glenn Kasten952eeb22012-03-06 11:30:57 -08002236 ALOGV("Audio hardware entering standby, mixer %p, suspend count %u", this, mSuspended);
2237 mOutput->stream->common.standby(&mOutput->stream->common);
Glenn Kasten000f0e32012-03-01 17:10:56 -08002238}
2239
2240void AudioFlinger::MixerThread::threadLoop_mix()
2241{
Glenn Kasten952eeb22012-03-06 11:30:57 -08002242 // obtain the presentation timestamp of the next output buffer
2243 int64_t pts;
2244 status_t status = INVALID_OPERATION;
John Grossman4ff14ba2012-02-08 16:37:41 -08002245
Glenn Kasten952eeb22012-03-06 11:30:57 -08002246 if (NULL != mOutput->stream->get_next_write_timestamp) {
2247 status = mOutput->stream->get_next_write_timestamp(
2248 mOutput->stream, &pts);
2249 }
John Grossman4ff14ba2012-02-08 16:37:41 -08002250
Glenn Kasten952eeb22012-03-06 11:30:57 -08002251 if (status != NO_ERROR) {
2252 pts = AudioBufferProvider::kInvalidPTS;
2253 }
John Grossman4ff14ba2012-02-08 16:37:41 -08002254
Glenn Kasten952eeb22012-03-06 11:30:57 -08002255 // mix buffers...
2256 mAudioMixer->process(pts);
2257 // increase sleep time progressively when application underrun condition clears.
2258 // Only increase sleep time if the mixer is ready for two consecutive times to avoid
2259 // that a steady state of alternating ready/not ready conditions keeps the sleep time
2260 // such that we would underrun the audio HAL.
2261 if ((sleepTime == 0) && (sleepTimeShift > 0)) {
2262 sleepTimeShift--;
2263 }
2264 sleepTime = 0;
2265 standbyTime = systemTime() + mStandbyTimeInNsecs;
2266 //TODO: delay standby when effects have a tail
Glenn Kasten000f0e32012-03-01 17:10:56 -08002267}
2268
2269void AudioFlinger::MixerThread::threadLoop_sleepTime()
2270{
Glenn Kasten952eeb22012-03-06 11:30:57 -08002271 // If no tracks are ready, sleep once for the duration of an output
2272 // buffer size, then write 0s to the output
2273 if (sleepTime == 0) {
2274 if (mixerStatus == MIXER_TRACKS_ENABLED) {
2275 sleepTime = activeSleepTime >> sleepTimeShift;
2276 if (sleepTime < kMinThreadSleepTimeUs) {
2277 sleepTime = kMinThreadSleepTimeUs;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002278 }
Glenn Kasten952eeb22012-03-06 11:30:57 -08002279 // reduce sleep time in case of consecutive application underruns to avoid
2280 // starving the audio HAL. As activeSleepTimeUs() is larger than a buffer
2281 // duration we would end up writing less data than needed by the audio HAL if
2282 // the condition persists.
2283 if (sleepTimeShift < kMaxThreadSleepTimeShift) {
2284 sleepTimeShift++;
2285 }
2286 } else {
2287 sleepTime = idleSleepTime;
2288 }
2289 } else if (mBytesWritten != 0 ||
2290 (mixerStatus == MIXER_TRACKS_ENABLED && longStandbyExit)) {
2291 memset (mMixBuffer, 0, mixBufferSize);
2292 sleepTime = 0;
2293 ALOGV_IF((mBytesWritten == 0 && (mixerStatus == MIXER_TRACKS_ENABLED && longStandbyExit)), "anticipated start");
2294 }
2295 // TODO add standby time extension fct of effect tail
Mathias Agopian65ab4712010-07-14 17:59:35 -07002296}
2297
2298// prepareTracks_l() must be called with ThreadBase::mLock held
Glenn Kasten29c23c32012-01-26 13:37:52 -08002299AudioFlinger::PlaybackThread::mixer_state AudioFlinger::MixerThread::prepareTracks_l(
Glenn Kasten3e074702012-02-28 18:40:35 -08002300 Vector< sp<Track> > *tracksToRemove)
Mathias Agopian65ab4712010-07-14 17:59:35 -07002301{
2302
Glenn Kasten29c23c32012-01-26 13:37:52 -08002303 mixer_state mixerStatus = MIXER_IDLE;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002304 // find out which tracks need to be processed
Glenn Kasten3e074702012-02-28 18:40:35 -08002305 size_t count = mActiveTracks.size();
Mathias Agopian65ab4712010-07-14 17:59:35 -07002306 size_t mixedTracks = 0;
2307 size_t tracksWithEffect = 0;
2308
2309 float masterVolume = mMasterVolume;
2310 bool masterMute = mMasterMute;
2311
Eric Laurent571d49c2010-08-11 05:20:11 -07002312 if (masterMute) {
2313 masterVolume = 0;
2314 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07002315 // Delegate master volume control to effect in output mix effect chain if needed
Dima Zavinfce7a472011-04-19 22:30:36 -07002316 sp<EffectChain> chain = getEffectChain_l(AUDIO_SESSION_OUTPUT_MIX);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002317 if (chain != 0) {
Eric Laurent571d49c2010-08-11 05:20:11 -07002318 uint32_t v = (uint32_t)(masterVolume * (1 << 24));
Eric Laurentcab11242010-07-15 12:50:15 -07002319 chain->setVolume_l(&v, &v);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002320 masterVolume = (float)((v + (1 << 23)) >> 24);
2321 chain.clear();
2322 }
2323
2324 for (size_t i=0 ; i<count ; i++) {
Glenn Kasten3e074702012-02-28 18:40:35 -08002325 sp<Track> t = mActiveTracks[i].promote();
Mathias Agopian65ab4712010-07-14 17:59:35 -07002326 if (t == 0) continue;
2327
Glenn Kasten9c56d4a2011-12-19 15:06:39 -08002328 // this const just means the local variable doesn't change
Mathias Agopian65ab4712010-07-14 17:59:35 -07002329 Track* const track = t.get();
2330 audio_track_cblk_t* cblk = track->cblk();
2331
2332 // The first time a track is added we wait
2333 // for all its buffers to be filled before processing it
Glenn Kasten9c56d4a2011-12-19 15:06:39 -08002334 int name = track->name();
Eric Laurenta47b69c2011-11-08 18:10:16 -08002335 // make sure that we have enough frames to mix one full buffer.
2336 // enforce this condition only once to enable draining the buffer in case the client
2337 // app does not call stop() and relies on underrun to stop:
Eric Laurent27741442012-01-17 19:20:12 -08002338 // hence the test on (mPrevMixerStatus == MIXER_TRACKS_READY) meaning the track was mixed
Eric Laurenta47b69c2011-11-08 18:10:16 -08002339 // during last round
Eric Laurent3dbe3202011-11-03 12:16:05 -07002340 uint32_t minFrames = 1;
Eric Laurenta47b69c2011-11-08 18:10:16 -08002341 if (!track->isStopped() && !track->isPausing() &&
Eric Laurent27741442012-01-17 19:20:12 -08002342 (mPrevMixerStatus == MIXER_TRACKS_READY)) {
Eric Laurent3dbe3202011-11-03 12:16:05 -07002343 if (t->sampleRate() == (int)mSampleRate) {
2344 minFrames = mFrameCount;
2345 } else {
Eric Laurent071ccd52011-12-22 16:08:41 -08002346 // +1 for rounding and +1 for additional sample needed for interpolation
2347 minFrames = (mFrameCount * t->sampleRate()) / mSampleRate + 1 + 1;
2348 // add frames already consumed but not yet released by the resampler
2349 // because cblk->framesReady() will include these frames
2350 minFrames += mAudioMixer->getUnreleasedFrames(track->name());
2351 // the minimum track buffer size is normally twice the number of frames necessary
2352 // to fill one buffer and the resampler should not leave more than one buffer worth
2353 // of unreleased frames after each pass, but just in case...
Steve Blockc1dc1cb2012-01-09 18:35:44 +00002354 ALOG_ASSERT(minFrames <= cblk->frameCount);
Eric Laurent3dbe3202011-11-03 12:16:05 -07002355 }
2356 }
John Grossman4ff14ba2012-02-08 16:37:41 -08002357 if ((track->framesReady() >= minFrames) && track->isReady() &&
Mathias Agopian65ab4712010-07-14 17:59:35 -07002358 !track->isPaused() && !track->isTerminated())
2359 {
Glenn Kasten9c56d4a2011-12-19 15:06:39 -08002360 //ALOGV("track %d u=%08x, s=%08x [OK] on thread %p", name, cblk->user, cblk->server, this);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002361
2362 mixedTracks++;
2363
2364 // track->mainBuffer() != mMixBuffer means there is an effect chain
2365 // connected to the track
2366 chain.clear();
2367 if (track->mainBuffer() != mMixBuffer) {
2368 chain = getEffectChain_l(track->sessionId());
2369 // Delegate volume control to effect in track effect chain if needed
2370 if (chain != 0) {
2371 tracksWithEffect++;
2372 } else {
Steve Block5ff1dd52012-01-05 23:22:43 +00002373 ALOGW("prepareTracks_l(): track %d attached to effect but no chain found on session %d",
Glenn Kasten9c56d4a2011-12-19 15:06:39 -08002374 name, track->sessionId());
Mathias Agopian65ab4712010-07-14 17:59:35 -07002375 }
2376 }
2377
2378
2379 int param = AudioMixer::VOLUME;
2380 if (track->mFillingUpStatus == Track::FS_FILLED) {
2381 // no ramp for the first volume setting
2382 track->mFillingUpStatus = Track::FS_ACTIVE;
2383 if (track->mState == TrackBase::RESUMING) {
2384 track->mState = TrackBase::ACTIVE;
2385 param = AudioMixer::RAMP_VOLUME;
2386 }
Glenn Kasten9c56d4a2011-12-19 15:06:39 -08002387 mAudioMixer->setParameter(name, AudioMixer::RESAMPLE, AudioMixer::RESET, NULL);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002388 } else if (cblk->server != 0) {
2389 // If the track is stopped before the first frame was mixed,
2390 // do not apply ramp
2391 param = AudioMixer::RAMP_VOLUME;
2392 }
2393
2394 // compute volume for this track
Eric Laurente0aed6d2010-09-10 17:44:44 -07002395 uint32_t vl, vr, va;
Eric Laurent8569f0d2010-07-29 23:43:43 -07002396 if (track->isMuted() || track->isPausing() ||
Glenn Kasten02bbd202012-02-08 12:35:35 -08002397 mStreamTypes[track->streamType()].mute) {
Eric Laurente0aed6d2010-09-10 17:44:44 -07002398 vl = vr = va = 0;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002399 if (track->isPausing()) {
2400 track->setPaused();
2401 }
2402 } else {
Eric Laurente0aed6d2010-09-10 17:44:44 -07002403
Mathias Agopian65ab4712010-07-14 17:59:35 -07002404 // read original volumes with volume control
Glenn Kasten02bbd202012-02-08 12:35:35 -08002405 float typeVolume = mStreamTypes[track->streamType()].volume;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002406 float v = masterVolume * typeVolume;
Glenn Kasten83d86532012-01-17 14:39:34 -08002407 uint32_t vlr = cblk->getVolumeLR();
Glenn Kastenb1cf75c2012-01-17 12:20:54 -08002408 vl = vlr & 0xFFFF;
2409 vr = vlr >> 16;
2410 // track volumes come from shared memory, so can't be trusted and must be clamped
2411 if (vl > MAX_GAIN_INT) {
2412 ALOGV("Track left volume out of range: %04X", vl);
2413 vl = MAX_GAIN_INT;
2414 }
2415 if (vr > MAX_GAIN_INT) {
2416 ALOGV("Track right volume out of range: %04X", vr);
2417 vr = MAX_GAIN_INT;
2418 }
2419 // now apply the master volume and stream type volume
2420 vl = (uint32_t)(v * vl) << 12;
2421 vr = (uint32_t)(v * vr) << 12;
2422 // assuming master volume and stream type volume each go up to 1.0,
2423 // vl and vr are now in 8.24 format
Mathias Agopian65ab4712010-07-14 17:59:35 -07002424
Glenn Kasten05632a52012-01-03 14:22:33 -08002425 uint16_t sendLevel = cblk->getSendLevel_U4_12();
2426 // send level comes from shared memory and so may be corrupt
Glenn Kasten3b81aca2012-01-27 15:26:23 -08002427 if (sendLevel > MAX_GAIN_INT) {
Glenn Kasten05632a52012-01-03 14:22:33 -08002428 ALOGV("Track send level out of range: %04X", sendLevel);
Glenn Kastenb1cf75c2012-01-17 12:20:54 -08002429 sendLevel = MAX_GAIN_INT;
Glenn Kasten05632a52012-01-03 14:22:33 -08002430 }
2431 va = (uint32_t)(v * sendLevel);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002432 }
Eric Laurente0aed6d2010-09-10 17:44:44 -07002433 // Delegate volume control to effect in track effect chain if needed
2434 if (chain != 0 && chain->setVolume_l(&vl, &vr)) {
2435 // Do not ramp volume if volume is controlled by effect
2436 param = AudioMixer::VOLUME;
2437 track->mHasVolumeController = true;
2438 } else {
2439 // force no volume ramp when volume controller was just disabled or removed
2440 // from effect chain to avoid volume spike
2441 if (track->mHasVolumeController) {
2442 param = AudioMixer::VOLUME;
2443 }
2444 track->mHasVolumeController = false;
2445 }
2446
2447 // Convert volumes from 8.24 to 4.12 format
Glenn Kastenb1cf75c2012-01-17 12:20:54 -08002448 // This additional clamping is needed in case chain->setVolume_l() overshot
Glenn Kasten3b81aca2012-01-27 15:26:23 -08002449 vl = (vl + (1 << 11)) >> 12;
2450 if (vl > MAX_GAIN_INT) vl = MAX_GAIN_INT;
2451 vr = (vr + (1 << 11)) >> 12;
2452 if (vr > MAX_GAIN_INT) vr = MAX_GAIN_INT;
Eric Laurente0aed6d2010-09-10 17:44:44 -07002453
Glenn Kasten3b81aca2012-01-27 15:26:23 -08002454 if (va > MAX_GAIN_INT) va = MAX_GAIN_INT; // va is uint32_t, so no need to check for -
Mathias Agopian65ab4712010-07-14 17:59:35 -07002455
Mathias Agopian65ab4712010-07-14 17:59:35 -07002456 // XXX: these things DON'T need to be done each time
Glenn Kasten9c56d4a2011-12-19 15:06:39 -08002457 mAudioMixer->setBufferProvider(name, track);
2458 mAudioMixer->enable(name);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002459
Glenn Kasten3b81aca2012-01-27 15:26:23 -08002460 mAudioMixer->setParameter(name, param, AudioMixer::VOLUME0, (void *)vl);
2461 mAudioMixer->setParameter(name, param, AudioMixer::VOLUME1, (void *)vr);
2462 mAudioMixer->setParameter(name, param, AudioMixer::AUXLEVEL, (void *)va);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002463 mAudioMixer->setParameter(
Glenn Kasten9c56d4a2011-12-19 15:06:39 -08002464 name,
Mathias Agopian65ab4712010-07-14 17:59:35 -07002465 AudioMixer::TRACK,
2466 AudioMixer::FORMAT, (void *)track->format());
2467 mAudioMixer->setParameter(
Glenn Kasten9c56d4a2011-12-19 15:06:39 -08002468 name,
Mathias Agopian65ab4712010-07-14 17:59:35 -07002469 AudioMixer::TRACK,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07002470 AudioMixer::CHANNEL_MASK, (void *)track->channelMask());
Mathias Agopian65ab4712010-07-14 17:59:35 -07002471 mAudioMixer->setParameter(
Glenn Kasten9c56d4a2011-12-19 15:06:39 -08002472 name,
Mathias Agopian65ab4712010-07-14 17:59:35 -07002473 AudioMixer::RESAMPLE,
2474 AudioMixer::SAMPLE_RATE,
2475 (void *)(cblk->sampleRate));
2476 mAudioMixer->setParameter(
Glenn Kasten9c56d4a2011-12-19 15:06:39 -08002477 name,
Mathias Agopian65ab4712010-07-14 17:59:35 -07002478 AudioMixer::TRACK,
2479 AudioMixer::MAIN_BUFFER, (void *)track->mainBuffer());
2480 mAudioMixer->setParameter(
Glenn Kasten9c56d4a2011-12-19 15:06:39 -08002481 name,
Mathias Agopian65ab4712010-07-14 17:59:35 -07002482 AudioMixer::TRACK,
2483 AudioMixer::AUX_BUFFER, (void *)track->auxBuffer());
2484
2485 // reset retry count
2486 track->mRetryCount = kMaxTrackRetries;
Eric Laurent27741442012-01-17 19:20:12 -08002487 // If one track is ready, set the mixer ready if:
2488 // - the mixer was not ready during previous round OR
2489 // - no other track is not ready
2490 if (mPrevMixerStatus != MIXER_TRACKS_READY ||
2491 mixerStatus != MIXER_TRACKS_ENABLED) {
2492 mixerStatus = MIXER_TRACKS_READY;
2493 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07002494 } else {
Glenn Kasten9c56d4a2011-12-19 15:06:39 -08002495 //ALOGV("track %d u=%08x, s=%08x [NOT READY] on thread %p", name, cblk->user, cblk->server, this);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002496 if (track->isStopped()) {
2497 track->reset();
2498 }
2499 if (track->isTerminated() || track->isStopped() || track->isPaused()) {
2500 // We have consumed all the buffers of this track.
2501 // Remove it from the list of active tracks.
2502 tracksToRemove->add(track);
2503 } else {
2504 // No buffers for this track. Give it a few chances to
2505 // fill a buffer, then remove it from active list.
2506 if (--(track->mRetryCount) <= 0) {
Glenn Kasten9c56d4a2011-12-19 15:06:39 -08002507 ALOGV("BUFFER TIMEOUT: remove(%d) from active list on thread %p", name, this);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002508 tracksToRemove->add(track);
Eric Laurent44d98482010-09-30 16:12:31 -07002509 // indicate to client process that the track was disabled because of underrun
Eric Laurent38ccae22011-03-28 18:37:07 -07002510 android_atomic_or(CBLK_DISABLED_ON, &cblk->flags);
Eric Laurent27741442012-01-17 19:20:12 -08002511 // If one track is not ready, mark the mixer also not ready if:
2512 // - the mixer was ready during previous round OR
2513 // - no other track is ready
2514 } else if (mPrevMixerStatus == MIXER_TRACKS_READY ||
2515 mixerStatus != MIXER_TRACKS_READY) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07002516 mixerStatus = MIXER_TRACKS_ENABLED;
2517 }
2518 }
Glenn Kasten9c56d4a2011-12-19 15:06:39 -08002519 mAudioMixer->disable(name);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002520 }
2521 }
2522
2523 // remove all the tracks that need to be...
2524 count = tracksToRemove->size();
Glenn Kastenf6b16782011-12-15 09:51:17 -08002525 if (CC_UNLIKELY(count)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07002526 for (size_t i=0 ; i<count ; i++) {
2527 const sp<Track>& track = tracksToRemove->itemAt(i);
2528 mActiveTracks.remove(track);
2529 if (track->mainBuffer() != mMixBuffer) {
2530 chain = getEffectChain_l(track->sessionId());
2531 if (chain != 0) {
Steve Block3856b092011-10-20 11:56:00 +01002532 ALOGV("stopping track on chain %p for session Id: %d", chain.get(), track->sessionId());
Eric Laurentb469b942011-05-09 12:09:06 -07002533 chain->decActiveTrackCnt();
Mathias Agopian65ab4712010-07-14 17:59:35 -07002534 }
2535 }
2536 if (track->isTerminated()) {
Eric Laurentb469b942011-05-09 12:09:06 -07002537 removeTrack_l(track);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002538 }
2539 }
2540 }
2541
2542 // mix buffer must be cleared if all tracks are connected to an
2543 // effect chain as in this case the mixer will not write to
2544 // mix buffer and track effects will accumulate into it
2545 if (mixedTracks != 0 && mixedTracks == tracksWithEffect) {
2546 memset(mMixBuffer, 0, mFrameCount * mChannelCount * sizeof(int16_t));
2547 }
2548
Eric Laurent27741442012-01-17 19:20:12 -08002549 mPrevMixerStatus = mixerStatus;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002550 return mixerStatus;
2551}
2552
Glenn Kastenfff6d712012-01-12 16:38:12 -08002553void AudioFlinger::MixerThread::invalidateTracks(audio_stream_type_t streamType)
Mathias Agopian65ab4712010-07-14 17:59:35 -07002554{
Steve Block3856b092011-10-20 11:56:00 +01002555 ALOGV ("MixerThread::invalidateTracks() mixer %p, streamType %d, mTracks.size %d",
Eric Laurentde070132010-07-13 04:45:46 -07002556 this, streamType, mTracks.size());
Mathias Agopian65ab4712010-07-14 17:59:35 -07002557 Mutex::Autolock _l(mLock);
Eric Laurentde070132010-07-13 04:45:46 -07002558
Mathias Agopian65ab4712010-07-14 17:59:35 -07002559 size_t size = mTracks.size();
2560 for (size_t i = 0; i < size; i++) {
2561 sp<Track> t = mTracks[i];
Glenn Kasten02bbd202012-02-08 12:35:35 -08002562 if (t->streamType() == streamType) {
Eric Laurent38ccae22011-03-28 18:37:07 -07002563 android_atomic_or(CBLK_INVALID_ON, &t->mCblk->flags);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002564 t->mCblk->cv.signal();
Mathias Agopian65ab4712010-07-14 17:59:35 -07002565 }
2566 }
2567}
2568
Glenn Kastenfff6d712012-01-12 16:38:12 -08002569void AudioFlinger::PlaybackThread::setStreamValid(audio_stream_type_t streamType, bool valid)
Eric Laurent9f6530f2011-08-30 10:18:54 -07002570{
Steve Block3856b092011-10-20 11:56:00 +01002571 ALOGV ("PlaybackThread::setStreamValid() thread %p, streamType %d, valid %d",
Eric Laurent9f6530f2011-08-30 10:18:54 -07002572 this, streamType, valid);
2573 Mutex::Autolock _l(mLock);
2574
2575 mStreamTypes[streamType].valid = valid;
2576}
Mathias Agopian65ab4712010-07-14 17:59:35 -07002577
2578// getTrackName_l() must be called with ThreadBase::mLock held
2579int AudioFlinger::MixerThread::getTrackName_l()
2580{
2581 return mAudioMixer->getTrackName();
2582}
2583
2584// deleteTrackName_l() must be called with ThreadBase::mLock held
2585void AudioFlinger::MixerThread::deleteTrackName_l(int name)
2586{
Steve Block3856b092011-10-20 11:56:00 +01002587 ALOGV("remove track (%d) and delete from mixer", name);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002588 mAudioMixer->deleteTrackName(name);
2589}
2590
2591// checkForNewParameters_l() must be called with ThreadBase::mLock held
2592bool AudioFlinger::MixerThread::checkForNewParameters_l()
2593{
2594 bool reconfig = false;
2595
2596 while (!mNewParameters.isEmpty()) {
2597 status_t status = NO_ERROR;
2598 String8 keyValuePair = mNewParameters[0];
2599 AudioParameter param = AudioParameter(keyValuePair);
2600 int value;
2601
2602 if (param.getInt(String8(AudioParameter::keySamplingRate), value) == NO_ERROR) {
2603 reconfig = true;
2604 }
2605 if (param.getInt(String8(AudioParameter::keyFormat), value) == NO_ERROR) {
Glenn Kasten58f30212012-01-12 12:27:51 -08002606 if ((audio_format_t) value != AUDIO_FORMAT_PCM_16_BIT) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07002607 status = BAD_VALUE;
2608 } else {
2609 reconfig = true;
2610 }
2611 }
2612 if (param.getInt(String8(AudioParameter::keyChannels), value) == NO_ERROR) {
Dima Zavinfce7a472011-04-19 22:30:36 -07002613 if (value != AUDIO_CHANNEL_OUT_STEREO) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07002614 status = BAD_VALUE;
2615 } else {
2616 reconfig = true;
2617 }
2618 }
2619 if (param.getInt(String8(AudioParameter::keyFrameCount), value) == NO_ERROR) {
2620 // do not accept frame count changes if tracks are open as the track buffer
Glenn Kasten362c4e62011-12-14 10:28:06 -08002621 // size depends on frame count and correct behavior would not be guaranteed
Mathias Agopian65ab4712010-07-14 17:59:35 -07002622 // if frame count is changed after track creation
2623 if (!mTracks.isEmpty()) {
2624 status = INVALID_OPERATION;
2625 } else {
2626 reconfig = true;
2627 }
2628 }
2629 if (param.getInt(String8(AudioParameter::keyRouting), value) == NO_ERROR) {
Gloria Wang9ee159b2011-02-24 14:51:45 -08002630 // when changing the audio output device, call addBatteryData to notify
2631 // the change
Eric Laurentb469b942011-05-09 12:09:06 -07002632 if ((int)mDevice != value) {
Gloria Wang9ee159b2011-02-24 14:51:45 -08002633 uint32_t params = 0;
2634 // check whether speaker is on
Dima Zavinfce7a472011-04-19 22:30:36 -07002635 if (value & AUDIO_DEVICE_OUT_SPEAKER) {
Gloria Wang9ee159b2011-02-24 14:51:45 -08002636 params |= IMediaPlayerService::kBatteryDataSpeakerOn;
2637 }
2638
2639 int deviceWithoutSpeaker
Dima Zavinfce7a472011-04-19 22:30:36 -07002640 = AUDIO_DEVICE_OUT_ALL & ~AUDIO_DEVICE_OUT_SPEAKER;
Gloria Wang9ee159b2011-02-24 14:51:45 -08002641 // check if any other device (except speaker) is on
2642 if (value & deviceWithoutSpeaker ) {
2643 params |= IMediaPlayerService::kBatteryDataOtherAudioDeviceOn;
2644 }
2645
2646 if (params != 0) {
2647 addBatteryData(params);
2648 }
2649 }
2650
Mathias Agopian65ab4712010-07-14 17:59:35 -07002651 // forward device change to effects that have requested to be
2652 // aware of attached audio device.
2653 mDevice = (uint32_t)value;
2654 for (size_t i = 0; i < mEffectChains.size(); i++) {
Eric Laurentcab11242010-07-15 12:50:15 -07002655 mEffectChains[i]->setDevice_l(mDevice);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002656 }
2657 }
2658
2659 if (status == NO_ERROR) {
Dima Zavin799a70e2011-04-18 16:57:27 -07002660 status = mOutput->stream->common.set_parameters(&mOutput->stream->common,
Dima Zavinfce7a472011-04-19 22:30:36 -07002661 keyValuePair.string());
Mathias Agopian65ab4712010-07-14 17:59:35 -07002662 if (!mStandby && status == INVALID_OPERATION) {
Dima Zavin799a70e2011-04-18 16:57:27 -07002663 mOutput->stream->common.standby(&mOutput->stream->common);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002664 mStandby = true;
2665 mBytesWritten = 0;
Dima Zavin799a70e2011-04-18 16:57:27 -07002666 status = mOutput->stream->common.set_parameters(&mOutput->stream->common,
Dima Zavinfce7a472011-04-19 22:30:36 -07002667 keyValuePair.string());
Mathias Agopian65ab4712010-07-14 17:59:35 -07002668 }
2669 if (status == NO_ERROR && reconfig) {
2670 delete mAudioMixer;
Glenn Kastene9dd0172012-01-27 18:08:45 -08002671 // for safety in case readOutputParameters() accesses mAudioMixer (it doesn't)
2672 mAudioMixer = NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002673 readOutputParameters();
2674 mAudioMixer = new AudioMixer(mFrameCount, mSampleRate);
2675 for (size_t i = 0; i < mTracks.size() ; i++) {
2676 int name = getTrackName_l();
2677 if (name < 0) break;
2678 mTracks[i]->mName = name;
2679 // limit track sample rate to 2 x new output sample rate
2680 if (mTracks[i]->mCblk->sampleRate > 2 * sampleRate()) {
2681 mTracks[i]->mCblk->sampleRate = 2 * sampleRate();
2682 }
2683 }
2684 sendConfigEvent_l(AudioSystem::OUTPUT_CONFIG_CHANGED);
2685 }
2686 }
2687
2688 mNewParameters.removeAt(0);
2689
2690 mParamStatus = status;
2691 mParamCond.signal();
Eric Laurent60cd0a02011-09-13 11:40:21 -07002692 // wait for condition with time out in case the thread calling ThreadBase::setParameters()
2693 // already timed out waiting for the status and will never signal the condition.
Glenn Kasten7dede872011-12-13 11:04:14 -08002694 mWaitWorkCV.waitRelative(mLock, kSetParametersTimeoutNs);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002695 }
2696 return reconfig;
2697}
2698
2699status_t AudioFlinger::MixerThread::dumpInternals(int fd, const Vector<String16>& args)
2700{
2701 const size_t SIZE = 256;
2702 char buffer[SIZE];
2703 String8 result;
2704
2705 PlaybackThread::dumpInternals(fd, args);
2706
2707 snprintf(buffer, SIZE, "AudioMixer tracks: %08x\n", mAudioMixer->trackNames());
2708 result.append(buffer);
2709 write(fd, result.string(), result.size());
2710 return NO_ERROR;
2711}
2712
Mathias Agopian65ab4712010-07-14 17:59:35 -07002713uint32_t AudioFlinger::MixerThread::idleSleepTimeUs()
2714{
Eric Laurent60e18242010-07-29 06:50:24 -07002715 return (uint32_t)(((mFrameCount * 1000) / mSampleRate) * 1000) / 2;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002716}
2717
Eric Laurent25cbe0e2010-08-18 18:13:17 -07002718uint32_t AudioFlinger::MixerThread::suspendSleepTimeUs()
2719{
2720 return (uint32_t)(((mFrameCount * 1000) / mSampleRate) * 1000);
2721}
2722
Mathias Agopian65ab4712010-07-14 17:59:35 -07002723// ----------------------------------------------------------------------------
Glenn Kasten72ef00d2012-01-17 11:09:42 -08002724AudioFlinger::DirectOutputThread::DirectOutputThread(const sp<AudioFlinger>& audioFlinger,
2725 AudioStreamOut* output, audio_io_handle_t id, uint32_t device)
Glenn Kasten23bb8be2012-01-26 10:38:26 -08002726 : PlaybackThread(audioFlinger, output, id, device, DIRECT)
Glenn Kasten84afa3b2012-01-25 15:28:08 -08002727 // mLeftVolFloat, mRightVolFloat
2728 // mLeftVolShort, mRightVolShort
Mathias Agopian65ab4712010-07-14 17:59:35 -07002729{
Mathias Agopian65ab4712010-07-14 17:59:35 -07002730}
2731
2732AudioFlinger::DirectOutputThread::~DirectOutputThread()
2733{
2734}
2735
Glenn Kasten000f0e32012-03-01 17:10:56 -08002736void AudioFlinger::DirectOutputThread::applyVolume()
Mathias Agopian65ab4712010-07-14 17:59:35 -07002737{
2738 // Do not apply volume on compressed audio
Dima Zavinfce7a472011-04-19 22:30:36 -07002739 if (!audio_is_linear_pcm(mFormat)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07002740 return;
2741 }
2742
2743 // convert to signed 16 bit before volume calculation
Dima Zavinfce7a472011-04-19 22:30:36 -07002744 if (mFormat == AUDIO_FORMAT_PCM_8_BIT) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07002745 size_t count = mFrameCount * mChannelCount;
2746 uint8_t *src = (uint8_t *)mMixBuffer + count-1;
2747 int16_t *dst = mMixBuffer + count-1;
2748 while(count--) {
2749 *dst-- = (int16_t)(*src--^0x80) << 8;
2750 }
2751 }
2752
2753 size_t frameCount = mFrameCount;
2754 int16_t *out = mMixBuffer;
Glenn Kasten000f0e32012-03-01 17:10:56 -08002755 if (rampVolume) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07002756 if (mChannelCount == 1) {
2757 int32_t d = ((int32_t)leftVol - (int32_t)mLeftVolShort) << 16;
2758 int32_t vlInc = d / (int32_t)frameCount;
2759 int32_t vl = ((int32_t)mLeftVolShort << 16);
2760 do {
2761 out[0] = clamp16(mul(out[0], vl >> 16) >> 12);
2762 out++;
2763 vl += vlInc;
2764 } while (--frameCount);
2765
2766 } else {
2767 int32_t d = ((int32_t)leftVol - (int32_t)mLeftVolShort) << 16;
2768 int32_t vlInc = d / (int32_t)frameCount;
2769 d = ((int32_t)rightVol - (int32_t)mRightVolShort) << 16;
2770 int32_t vrInc = d / (int32_t)frameCount;
2771 int32_t vl = ((int32_t)mLeftVolShort << 16);
2772 int32_t vr = ((int32_t)mRightVolShort << 16);
2773 do {
2774 out[0] = clamp16(mul(out[0], vl >> 16) >> 12);
2775 out[1] = clamp16(mul(out[1], vr >> 16) >> 12);
2776 out += 2;
2777 vl += vlInc;
2778 vr += vrInc;
2779 } while (--frameCount);
2780 }
2781 } else {
2782 if (mChannelCount == 1) {
2783 do {
2784 out[0] = clamp16(mul(out[0], leftVol) >> 12);
2785 out++;
2786 } while (--frameCount);
2787 } else {
2788 do {
2789 out[0] = clamp16(mul(out[0], leftVol) >> 12);
2790 out[1] = clamp16(mul(out[1], rightVol) >> 12);
2791 out += 2;
2792 } while (--frameCount);
2793 }
2794 }
2795
2796 // convert back to unsigned 8 bit after volume calculation
Dima Zavinfce7a472011-04-19 22:30:36 -07002797 if (mFormat == AUDIO_FORMAT_PCM_8_BIT) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07002798 size_t count = mFrameCount * mChannelCount;
2799 int16_t *src = mMixBuffer;
2800 uint8_t *dst = (uint8_t *)mMixBuffer;
2801 while(count--) {
2802 *dst++ = (uint8_t)(((int32_t)*src++ + (1<<7)) >> 8)^0x80;
2803 }
2804 }
2805
2806 mLeftVolShort = leftVol;
2807 mRightVolShort = rightVol;
2808}
2809
Glenn Kasten1465f0c2012-03-06 11:23:32 -08002810AudioFlinger::PlaybackThread::mixer_state AudioFlinger::DirectOutputThread::prepareTracks_l(
2811 Vector< sp<Track> > *tracksToRemove
Glenn Kasten000f0e32012-03-01 17:10:56 -08002812)
Mathias Agopian65ab4712010-07-14 17:59:35 -07002813{
Glenn Kasten1465f0c2012-03-06 11:23:32 -08002814 sp<Track> trackToRemove;
2815
Glenn Kasten952eeb22012-03-06 11:30:57 -08002816 // FIXME Temporarily renamed to avoid confusion with the member "mixerStatus"
2817 mixer_state mixerStatus_ = MIXER_IDLE;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002818
Glenn Kasten952eeb22012-03-06 11:30:57 -08002819 // find out which tracks need to be processed
2820 if (mActiveTracks.size() != 0) {
2821 sp<Track> t = mActiveTracks[0].promote();
2822 // see FIXME in AudioFlinger.h, return MIXER_IDLE might also work
2823 if (t == 0) return MIXER_CONTINUE;
2824 //if (t == 0) continue;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002825
Glenn Kasten952eeb22012-03-06 11:30:57 -08002826 Track* const track = t.get();
2827 audio_track_cblk_t* cblk = track->cblk();
Mathias Agopian65ab4712010-07-14 17:59:35 -07002828
Glenn Kasten952eeb22012-03-06 11:30:57 -08002829 // The first time a track is added we wait
2830 // for all its buffers to be filled before processing it
2831 if (cblk->framesReady() && track->isReady() &&
2832 !track->isPaused() && !track->isTerminated())
2833 {
2834 //ALOGV("track %d u=%08x, s=%08x [OK]", track->name(), cblk->user, cblk->server);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002835
Glenn Kasten952eeb22012-03-06 11:30:57 -08002836 if (track->mFillingUpStatus == Track::FS_FILLED) {
2837 track->mFillingUpStatus = Track::FS_ACTIVE;
2838 mLeftVolFloat = mRightVolFloat = 0;
2839 mLeftVolShort = mRightVolShort = 0;
2840 if (track->mState == TrackBase::RESUMING) {
2841 track->mState = TrackBase::ACTIVE;
2842 rampVolume = true;
2843 }
2844 } else if (cblk->server != 0) {
2845 // If the track is stopped before the first frame was mixed,
2846 // do not apply ramp
2847 rampVolume = true;
2848 }
2849 // compute volume for this track
2850 float left, right;
2851 if (track->isMuted() || mMasterMute || track->isPausing() ||
2852 mStreamTypes[track->streamType()].mute) {
2853 left = right = 0;
2854 if (track->isPausing()) {
2855 track->setPaused();
2856 }
2857 } else {
2858 float typeVolume = mStreamTypes[track->streamType()].volume;
2859 float v = mMasterVolume * typeVolume;
2860 uint32_t vlr = cblk->getVolumeLR();
2861 float v_clamped = v * (vlr & 0xFFFF);
2862 if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN;
2863 left = v_clamped/MAX_GAIN;
2864 v_clamped = v * (vlr >> 16);
2865 if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN;
2866 right = v_clamped/MAX_GAIN;
2867 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07002868
Glenn Kasten952eeb22012-03-06 11:30:57 -08002869 if (left != mLeftVolFloat || right != mRightVolFloat) {
2870 mLeftVolFloat = left;
2871 mRightVolFloat = right;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002872
Glenn Kasten952eeb22012-03-06 11:30:57 -08002873 // If audio HAL implements volume control,
2874 // force software volume to nominal value
2875 if (mOutput->stream->set_volume(mOutput->stream, left, right) == NO_ERROR) {
2876 left = 1.0f;
2877 right = 1.0f;
2878 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07002879
Glenn Kasten952eeb22012-03-06 11:30:57 -08002880 // Convert volumes from float to 8.24
2881 uint32_t vl = (uint32_t)(left * (1 << 24));
2882 uint32_t vr = (uint32_t)(right * (1 << 24));
Mathias Agopian65ab4712010-07-14 17:59:35 -07002883
Glenn Kasten952eeb22012-03-06 11:30:57 -08002884 // Delegate volume control to effect in track effect chain if needed
2885 // only one effect chain can be present on DirectOutputThread, so if
2886 // there is one, the track is connected to it
2887 if (!mEffectChains.isEmpty()) {
2888 // Do not ramp volume if volume is controlled by effect
2889 if (mEffectChains[0]->setVolume_l(&vl, &vr)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07002890 rampVolume = false;
2891 }
Glenn Kasten952eeb22012-03-06 11:30:57 -08002892 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07002893
Glenn Kasten952eeb22012-03-06 11:30:57 -08002894 // Convert volumes from 8.24 to 4.12 format
2895 uint32_t v_clamped = (vl + (1 << 11)) >> 12;
2896 if (v_clamped > MAX_GAIN_INT) v_clamped = MAX_GAIN_INT;
2897 leftVol = (uint16_t)v_clamped;
2898 v_clamped = (vr + (1 << 11)) >> 12;
2899 if (v_clamped > MAX_GAIN_INT) v_clamped = MAX_GAIN_INT;
2900 rightVol = (uint16_t)v_clamped;
2901 } else {
2902 leftVol = mLeftVolShort;
2903 rightVol = mRightVolShort;
2904 rampVolume = false;
2905 }
2906
2907 // reset retry count
2908 track->mRetryCount = kMaxTrackRetriesDirect;
Glenn Kastenb071e9b2012-03-07 17:05:59 -08002909 mActiveTrack = t;
Glenn Kasten952eeb22012-03-06 11:30:57 -08002910 mixerStatus_ = MIXER_TRACKS_READY;
2911 } else {
2912 //ALOGV("track %d u=%08x, s=%08x [NOT READY]", track->name(), cblk->user, cblk->server);
2913 if (track->isStopped()) {
2914 track->reset();
2915 }
2916 if (track->isTerminated() || track->isStopped() || track->isPaused()) {
2917 // We have consumed all the buffers of this track.
2918 // Remove it from the list of active tracks.
2919 trackToRemove = track;
2920 } else {
2921 // No buffers for this track. Give it a few chances to
2922 // fill a buffer, then remove it from active list.
2923 if (--(track->mRetryCount) <= 0) {
2924 ALOGV("BUFFER TIMEOUT: remove(%d) from active list", track->name());
2925 trackToRemove = track;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002926 } else {
Glenn Kasten952eeb22012-03-06 11:30:57 -08002927 mixerStatus_ = MIXER_TRACKS_ENABLED;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002928 }
2929 }
Glenn Kasten952eeb22012-03-06 11:30:57 -08002930 }
2931 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07002932
Glenn Kasten1465f0c2012-03-06 11:23:32 -08002933 // FIXME merge this with similar code for removing multiple tracks
Glenn Kasten952eeb22012-03-06 11:30:57 -08002934 // remove all the tracks that need to be...
2935 if (CC_UNLIKELY(trackToRemove != 0)) {
Glenn Kasten1465f0c2012-03-06 11:23:32 -08002936 tracksToRemove->add(trackToRemove);
Glenn Kasten952eeb22012-03-06 11:30:57 -08002937 mActiveTracks.remove(trackToRemove);
2938 if (!mEffectChains.isEmpty()) {
2939 ALOGV("stopping track on chain %p for session Id: %d", effectChains[0].get(),
2940 trackToRemove->sessionId());
2941 mEffectChains[0]->decActiveTrackCnt();
2942 }
2943 if (trackToRemove->isTerminated()) {
2944 removeTrack_l(trackToRemove);
2945 }
2946 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07002947
Glenn Kasten952eeb22012-03-06 11:30:57 -08002948 return mixerStatus_;
Glenn Kasten000f0e32012-03-01 17:10:56 -08002949}
Mathias Agopian65ab4712010-07-14 17:59:35 -07002950
Glenn Kasten000f0e32012-03-01 17:10:56 -08002951void AudioFlinger::DirectOutputThread::threadLoop_mix()
2952{
Glenn Kasten952eeb22012-03-06 11:30:57 -08002953 AudioBufferProvider::Buffer buffer;
2954 size_t frameCount = mFrameCount;
2955 int8_t *curBuf = (int8_t *)mMixBuffer;
2956 // output audio to hardware
2957 while (frameCount) {
2958 buffer.frameCount = frameCount;
Glenn Kastenb071e9b2012-03-07 17:05:59 -08002959 mActiveTrack->getNextBuffer(&buffer);
Glenn Kasten952eeb22012-03-06 11:30:57 -08002960 if (CC_UNLIKELY(buffer.raw == NULL)) {
2961 memset(curBuf, 0, frameCount * mFrameSize);
2962 break;
2963 }
2964 memcpy(curBuf, buffer.raw, buffer.frameCount * mFrameSize);
2965 frameCount -= buffer.frameCount;
2966 curBuf += buffer.frameCount * mFrameSize;
Glenn Kastenb071e9b2012-03-07 17:05:59 -08002967 mActiveTrack->releaseBuffer(&buffer);
Glenn Kasten952eeb22012-03-06 11:30:57 -08002968 }
2969 sleepTime = 0;
2970 standbyTime = systemTime() + standbyDelay;
Glenn Kastenb071e9b2012-03-07 17:05:59 -08002971 mActiveTrack.clear();
Glenn Kastend4513b02012-03-06 15:52:35 -08002972 applyVolume();
Glenn Kasten000f0e32012-03-01 17:10:56 -08002973}
2974
2975void AudioFlinger::DirectOutputThread::threadLoop_sleepTime()
2976{
Glenn Kasten952eeb22012-03-06 11:30:57 -08002977 if (sleepTime == 0) {
2978 if (mixerStatus == MIXER_TRACKS_ENABLED) {
2979 sleepTime = activeSleepTime;
2980 } else {
2981 sleepTime = idleSleepTime;
2982 }
2983 } else if (mBytesWritten != 0 && audio_is_linear_pcm(mFormat)) {
2984 memset (mMixBuffer, 0, mFrameCount * mFrameSize);
2985 sleepTime = 0;
2986 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07002987}
2988
2989// getTrackName_l() must be called with ThreadBase::mLock held
2990int AudioFlinger::DirectOutputThread::getTrackName_l()
2991{
2992 return 0;
2993}
2994
2995// deleteTrackName_l() must be called with ThreadBase::mLock held
2996void AudioFlinger::DirectOutputThread::deleteTrackName_l(int name)
2997{
2998}
2999
3000// checkForNewParameters_l() must be called with ThreadBase::mLock held
3001bool AudioFlinger::DirectOutputThread::checkForNewParameters_l()
3002{
3003 bool reconfig = false;
3004
3005 while (!mNewParameters.isEmpty()) {
3006 status_t status = NO_ERROR;
3007 String8 keyValuePair = mNewParameters[0];
3008 AudioParameter param = AudioParameter(keyValuePair);
3009 int value;
3010
3011 if (param.getInt(String8(AudioParameter::keyFrameCount), value) == NO_ERROR) {
3012 // do not accept frame count changes if tracks are open as the track buffer
3013 // size depends on frame count and correct behavior would not be garantied
3014 // if frame count is changed after track creation
3015 if (!mTracks.isEmpty()) {
3016 status = INVALID_OPERATION;
3017 } else {
3018 reconfig = true;
3019 }
3020 }
3021 if (status == NO_ERROR) {
Dima Zavin799a70e2011-04-18 16:57:27 -07003022 status = mOutput->stream->common.set_parameters(&mOutput->stream->common,
Dima Zavinfce7a472011-04-19 22:30:36 -07003023 keyValuePair.string());
Mathias Agopian65ab4712010-07-14 17:59:35 -07003024 if (!mStandby && status == INVALID_OPERATION) {
Dima Zavin799a70e2011-04-18 16:57:27 -07003025 mOutput->stream->common.standby(&mOutput->stream->common);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003026 mStandby = true;
3027 mBytesWritten = 0;
Dima Zavin799a70e2011-04-18 16:57:27 -07003028 status = mOutput->stream->common.set_parameters(&mOutput->stream->common,
Dima Zavinfce7a472011-04-19 22:30:36 -07003029 keyValuePair.string());
Mathias Agopian65ab4712010-07-14 17:59:35 -07003030 }
3031 if (status == NO_ERROR && reconfig) {
3032 readOutputParameters();
3033 sendConfigEvent_l(AudioSystem::OUTPUT_CONFIG_CHANGED);
3034 }
3035 }
3036
3037 mNewParameters.removeAt(0);
3038
3039 mParamStatus = status;
3040 mParamCond.signal();
Eric Laurent60cd0a02011-09-13 11:40:21 -07003041 // wait for condition with time out in case the thread calling ThreadBase::setParameters()
3042 // already timed out waiting for the status and will never signal the condition.
Glenn Kasten7dede872011-12-13 11:04:14 -08003043 mWaitWorkCV.waitRelative(mLock, kSetParametersTimeoutNs);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003044 }
3045 return reconfig;
3046}
3047
3048uint32_t AudioFlinger::DirectOutputThread::activeSleepTimeUs()
3049{
3050 uint32_t time;
Dima Zavinfce7a472011-04-19 22:30:36 -07003051 if (audio_is_linear_pcm(mFormat)) {
Eric Laurent162b40b2011-12-05 09:47:19 -08003052 time = PlaybackThread::activeSleepTimeUs();
Mathias Agopian65ab4712010-07-14 17:59:35 -07003053 } else {
3054 time = 10000;
3055 }
3056 return time;
3057}
3058
3059uint32_t AudioFlinger::DirectOutputThread::idleSleepTimeUs()
3060{
3061 uint32_t time;
Dima Zavinfce7a472011-04-19 22:30:36 -07003062 if (audio_is_linear_pcm(mFormat)) {
Eric Laurent60e18242010-07-29 06:50:24 -07003063 time = (uint32_t)(((mFrameCount * 1000) / mSampleRate) * 1000) / 2;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003064 } else {
3065 time = 10000;
3066 }
3067 return time;
3068}
3069
Eric Laurent25cbe0e2010-08-18 18:13:17 -07003070uint32_t AudioFlinger::DirectOutputThread::suspendSleepTimeUs()
3071{
3072 uint32_t time;
Dima Zavinfce7a472011-04-19 22:30:36 -07003073 if (audio_is_linear_pcm(mFormat)) {
Eric Laurent25cbe0e2010-08-18 18:13:17 -07003074 time = (uint32_t)(((mFrameCount * 1000) / mSampleRate) * 1000);
3075 } else {
3076 time = 10000;
3077 }
3078 return time;
3079}
3080
3081
Mathias Agopian65ab4712010-07-14 17:59:35 -07003082// ----------------------------------------------------------------------------
3083
Glenn Kasten23bb8be2012-01-26 10:38:26 -08003084AudioFlinger::DuplicatingThread::DuplicatingThread(const sp<AudioFlinger>& audioFlinger,
Glenn Kasten72ef00d2012-01-17 11:09:42 -08003085 AudioFlinger::MixerThread* mainThread, audio_io_handle_t id)
Glenn Kasten23bb8be2012-01-26 10:38:26 -08003086 : MixerThread(audioFlinger, mainThread->getOutput(), id, mainThread->device(), DUPLICATING),
3087 mWaitTimeMs(UINT_MAX)
Mathias Agopian65ab4712010-07-14 17:59:35 -07003088{
Mathias Agopian65ab4712010-07-14 17:59:35 -07003089 addOutputTrack(mainThread);
3090}
3091
3092AudioFlinger::DuplicatingThread::~DuplicatingThread()
3093{
3094 for (size_t i = 0; i < mOutputTracks.size(); i++) {
3095 mOutputTracks[i]->destroy();
3096 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07003097}
3098
Glenn Kasten000f0e32012-03-01 17:10:56 -08003099void AudioFlinger::DuplicatingThread::threadLoop_mix()
Mathias Agopian65ab4712010-07-14 17:59:35 -07003100{
Glenn Kasten952eeb22012-03-06 11:30:57 -08003101 // mix buffers...
3102 if (outputsReady(outputTracks)) {
3103 mAudioMixer->process(AudioBufferProvider::kInvalidPTS);
3104 } else {
3105 memset(mMixBuffer, 0, mixBufferSize);
3106 }
3107 sleepTime = 0;
3108 writeFrames = mFrameCount;
Glenn Kasten000f0e32012-03-01 17:10:56 -08003109}
3110
3111void AudioFlinger::DuplicatingThread::threadLoop_sleepTime()
3112{
Glenn Kasten952eeb22012-03-06 11:30:57 -08003113 if (sleepTime == 0) {
3114 if (mixerStatus == MIXER_TRACKS_ENABLED) {
3115 sleepTime = activeSleepTime;
3116 } else {
3117 sleepTime = idleSleepTime;
3118 }
3119 } else if (mBytesWritten != 0) {
3120 // flush remaining overflow buffers in output tracks
3121 for (size_t i = 0; i < outputTracks.size(); i++) {
3122 if (outputTracks[i]->isActive()) {
3123 sleepTime = 0;
3124 writeFrames = 0;
3125 memset(mMixBuffer, 0, mixBufferSize);
3126 break;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003127 }
Glenn Kasten952eeb22012-03-06 11:30:57 -08003128 }
3129 }
Glenn Kasten000f0e32012-03-01 17:10:56 -08003130}
Mathias Agopian65ab4712010-07-14 17:59:35 -07003131
Glenn Kasten000f0e32012-03-01 17:10:56 -08003132void AudioFlinger::DuplicatingThread::threadLoop_write()
3133{
Glenn Kasten952eeb22012-03-06 11:30:57 -08003134 standbyTime = systemTime() + mStandbyTimeInNsecs;
3135 for (size_t i = 0; i < outputTracks.size(); i++) {
3136 outputTracks[i]->write(mMixBuffer, writeFrames);
3137 }
3138 mBytesWritten += mixBufferSize;
Glenn Kasten000f0e32012-03-01 17:10:56 -08003139}
Glenn Kasten688a6402012-02-29 07:57:06 -08003140
Glenn Kasten000f0e32012-03-01 17:10:56 -08003141void AudioFlinger::DuplicatingThread::threadLoop_standby()
3142{
Glenn Kasten952eeb22012-03-06 11:30:57 -08003143 // DuplicatingThread implements standby by stopping all tracks
3144 for (size_t i = 0; i < outputTracks.size(); i++) {
3145 outputTracks[i]->stop();
3146 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07003147}
3148
Glenn Kastenfa26a852012-03-06 11:28:04 -08003149void AudioFlinger::DuplicatingThread::saveOutputTracks()
3150{
3151 outputTracks = mOutputTracks;
3152}
3153
3154void AudioFlinger::DuplicatingThread::clearOutputTracks()
3155{
3156 outputTracks.clear();
3157}
3158
Mathias Agopian65ab4712010-07-14 17:59:35 -07003159void AudioFlinger::DuplicatingThread::addOutputTrack(MixerThread *thread)
3160{
Glenn Kastenb6b74062012-02-24 14:12:20 -08003161 Mutex::Autolock _l(mLock);
Glenn Kasten99e53b82012-01-19 08:59:58 -08003162 // FIXME explain this formula
Mathias Agopian65ab4712010-07-14 17:59:35 -07003163 int frameCount = (3 * mFrameCount * mSampleRate) / thread->sampleRate();
Glenn Kasten9eaa5572012-01-20 13:32:16 -08003164 OutputTrack *outputTrack = new OutputTrack(thread,
Mathias Agopian65ab4712010-07-14 17:59:35 -07003165 this,
3166 mSampleRate,
3167 mFormat,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07003168 mChannelMask,
Mathias Agopian65ab4712010-07-14 17:59:35 -07003169 frameCount);
3170 if (outputTrack->cblk() != NULL) {
Dima Zavinfce7a472011-04-19 22:30:36 -07003171 thread->setStreamVolume(AUDIO_STREAM_CNT, 1.0f);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003172 mOutputTracks.add(outputTrack);
Steve Block3856b092011-10-20 11:56:00 +01003173 ALOGV("addOutputTrack() track %p, on thread %p", outputTrack, thread);
Glenn Kasten438b0362012-03-06 11:24:48 -08003174 updateWaitTime_l();
Mathias Agopian65ab4712010-07-14 17:59:35 -07003175 }
3176}
3177
3178void AudioFlinger::DuplicatingThread::removeOutputTrack(MixerThread *thread)
3179{
3180 Mutex::Autolock _l(mLock);
3181 for (size_t i = 0; i < mOutputTracks.size(); i++) {
Glenn Kastena1117922012-01-26 10:53:32 -08003182 if (mOutputTracks[i]->thread() == thread) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07003183 mOutputTracks[i]->destroy();
3184 mOutputTracks.removeAt(i);
Glenn Kasten438b0362012-03-06 11:24:48 -08003185 updateWaitTime_l();
Mathias Agopian65ab4712010-07-14 17:59:35 -07003186 return;
3187 }
3188 }
Steve Block3856b092011-10-20 11:56:00 +01003189 ALOGV("removeOutputTrack(): unkonwn thread: %p", thread);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003190}
3191
Glenn Kasten438b0362012-03-06 11:24:48 -08003192// caller must hold mLock
3193void AudioFlinger::DuplicatingThread::updateWaitTime_l()
Mathias Agopian65ab4712010-07-14 17:59:35 -07003194{
3195 mWaitTimeMs = UINT_MAX;
3196 for (size_t i = 0; i < mOutputTracks.size(); i++) {
3197 sp<ThreadBase> strong = mOutputTracks[i]->thread().promote();
Glenn Kasten7378ca52012-01-20 13:44:40 -08003198 if (strong != 0) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07003199 uint32_t waitTimeMs = (strong->frameCount() * 2 * 1000) / strong->sampleRate();
3200 if (waitTimeMs < mWaitTimeMs) {
3201 mWaitTimeMs = waitTimeMs;
3202 }
3203 }
3204 }
3205}
3206
3207
Glenn Kasten02fe1bf2012-02-24 15:42:17 -08003208bool AudioFlinger::DuplicatingThread::outputsReady(const SortedVector< sp<OutputTrack> > &outputTracks)
Mathias Agopian65ab4712010-07-14 17:59:35 -07003209{
3210 for (size_t i = 0; i < outputTracks.size(); i++) {
3211 sp <ThreadBase> thread = outputTracks[i]->thread().promote();
3212 if (thread == 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00003213 ALOGW("DuplicatingThread::outputsReady() could not promote thread on output track %p", outputTracks[i].get());
Mathias Agopian65ab4712010-07-14 17:59:35 -07003214 return false;
3215 }
3216 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
3217 if (playbackThread->standby() && !playbackThread->isSuspended()) {
Steve Block3856b092011-10-20 11:56:00 +01003218 ALOGV("DuplicatingThread output track %p on thread %p Not Ready", outputTracks[i].get(), thread.get());
Mathias Agopian65ab4712010-07-14 17:59:35 -07003219 return false;
3220 }
3221 }
3222 return true;
3223}
3224
3225uint32_t AudioFlinger::DuplicatingThread::activeSleepTimeUs()
3226{
3227 return (mWaitTimeMs * 1000) / 2;
3228}
3229
3230// ----------------------------------------------------------------------------
3231
3232// TrackBase constructor must be called with AudioFlinger::mLock held
3233AudioFlinger::ThreadBase::TrackBase::TrackBase(
Glenn Kasten9eaa5572012-01-20 13:32:16 -08003234 ThreadBase *thread,
Mathias Agopian65ab4712010-07-14 17:59:35 -07003235 const sp<Client>& client,
3236 uint32_t sampleRate,
Glenn Kasten58f30212012-01-12 12:27:51 -08003237 audio_format_t format,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07003238 uint32_t channelMask,
Mathias Agopian65ab4712010-07-14 17:59:35 -07003239 int frameCount,
Mathias Agopian65ab4712010-07-14 17:59:35 -07003240 const sp<IMemory>& sharedBuffer,
3241 int sessionId)
3242 : RefBase(),
3243 mThread(thread),
3244 mClient(client),
Glenn Kasten84afa3b2012-01-25 15:28:08 -08003245 mCblk(NULL),
3246 // mBuffer
3247 // mBufferEnd
Mathias Agopian65ab4712010-07-14 17:59:35 -07003248 mFrameCount(0),
3249 mState(IDLE),
Mathias Agopian65ab4712010-07-14 17:59:35 -07003250 mFormat(format),
Glenn Kasten5cf034d2012-02-21 10:35:56 -08003251 mStepServerFailed(false),
Mathias Agopian65ab4712010-07-14 17:59:35 -07003252 mSessionId(sessionId)
Glenn Kasten84afa3b2012-01-25 15:28:08 -08003253 // mChannelCount
3254 // mChannelMask
Mathias Agopian65ab4712010-07-14 17:59:35 -07003255{
Steve Block3856b092011-10-20 11:56:00 +01003256 ALOGV_IF(sharedBuffer != 0, "sharedBuffer: %p, size: %d", sharedBuffer->pointer(), sharedBuffer->size());
Mathias Agopian65ab4712010-07-14 17:59:35 -07003257
Steve Blockb8a80522011-12-20 16:23:08 +00003258 // ALOGD("Creating track with %d buffers @ %d bytes", bufferCount, bufferSize);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003259 size_t size = sizeof(audio_track_cblk_t);
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07003260 uint8_t channelCount = popcount(channelMask);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003261 size_t bufferSize = frameCount*channelCount*sizeof(int16_t);
3262 if (sharedBuffer == 0) {
3263 size += bufferSize;
3264 }
3265
3266 if (client != NULL) {
3267 mCblkMemory = client->heap()->allocate(size);
3268 if (mCblkMemory != 0) {
3269 mCblk = static_cast<audio_track_cblk_t *>(mCblkMemory->pointer());
Glenn Kastena0d68332012-01-27 16:47:15 -08003270 if (mCblk != NULL) { // construct the shared structure in-place.
Mathias Agopian65ab4712010-07-14 17:59:35 -07003271 new(mCblk) audio_track_cblk_t();
3272 // clear all buffers
3273 mCblk->frameCount = frameCount;
3274 mCblk->sampleRate = sampleRate;
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07003275 mChannelCount = channelCount;
3276 mChannelMask = channelMask;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003277 if (sharedBuffer == 0) {
3278 mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t);
3279 memset(mBuffer, 0, frameCount*channelCount*sizeof(int16_t));
3280 // Force underrun condition to avoid false underrun callback until first data is
Eric Laurent44d98482010-09-30 16:12:31 -07003281 // written to buffer (other flags are cleared)
Mathias Agopian65ab4712010-07-14 17:59:35 -07003282 mCblk->flags = CBLK_UNDERRUN_ON;
3283 } else {
3284 mBuffer = sharedBuffer->pointer();
3285 }
3286 mBufferEnd = (uint8_t *)mBuffer + bufferSize;
3287 }
3288 } else {
Steve Block29357bc2012-01-06 19:20:56 +00003289 ALOGE("not enough memory for AudioTrack size=%u", size);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003290 client->heap()->dump("AudioTrack");
3291 return;
3292 }
3293 } else {
3294 mCblk = (audio_track_cblk_t *)(new uint8_t[size]);
Glenn Kasten4a6f0282012-01-06 15:03:11 -08003295 // construct the shared structure in-place.
Mathias Agopian65ab4712010-07-14 17:59:35 -07003296 new(mCblk) audio_track_cblk_t();
3297 // clear all buffers
3298 mCblk->frameCount = frameCount;
3299 mCblk->sampleRate = sampleRate;
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07003300 mChannelCount = channelCount;
3301 mChannelMask = channelMask;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003302 mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t);
3303 memset(mBuffer, 0, frameCount*channelCount*sizeof(int16_t));
3304 // Force underrun condition to avoid false underrun callback until first data is
Eric Laurent44d98482010-09-30 16:12:31 -07003305 // written to buffer (other flags are cleared)
Mathias Agopian65ab4712010-07-14 17:59:35 -07003306 mCblk->flags = CBLK_UNDERRUN_ON;
3307 mBufferEnd = (uint8_t *)mBuffer + bufferSize;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003308 }
3309}
3310
3311AudioFlinger::ThreadBase::TrackBase::~TrackBase()
3312{
Glenn Kastena0d68332012-01-27 16:47:15 -08003313 if (mCblk != NULL) {
Glenn Kasten1a0ae5b2012-02-03 10:24:48 -08003314 if (mClient == 0) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07003315 delete mCblk;
Glenn Kasten1a0ae5b2012-02-03 10:24:48 -08003316 } else {
3317 mCblk->~audio_track_cblk_t(); // destroy our shared-structure.
Mathias Agopian65ab4712010-07-14 17:59:35 -07003318 }
3319 }
Glenn Kastendbfafaf2012-01-25 15:27:15 -08003320 mCblkMemory.clear(); // free the shared memory before releasing the heap it belongs to
Glenn Kasten7378ca52012-01-20 13:44:40 -08003321 if (mClient != 0) {
Glenn Kasten84afa3b2012-01-25 15:28:08 -08003322 // Client destructor must run with AudioFlinger mutex locked
Mathias Agopian65ab4712010-07-14 17:59:35 -07003323 Mutex::Autolock _l(mClient->audioFlinger()->mLock);
Glenn Kasten7378ca52012-01-20 13:44:40 -08003324 // If the client's reference count drops to zero, the associated destructor
3325 // must run with AudioFlinger lock held. Thus the explicit clear() rather than
3326 // relying on the automatic clear() at end of scope.
Mathias Agopian65ab4712010-07-14 17:59:35 -07003327 mClient.clear();
3328 }
3329}
3330
Glenn Kasten01c4ebf2012-02-22 10:47:35 -08003331// AudioBufferProvider interface
3332// getNextBuffer() = 0;
3333// This implementation of releaseBuffer() is used by Track and RecordTrack, but not TimedTrack
Mathias Agopian65ab4712010-07-14 17:59:35 -07003334void AudioFlinger::ThreadBase::TrackBase::releaseBuffer(AudioBufferProvider::Buffer* buffer)
3335{
Glenn Kastene0feee32011-12-13 11:53:26 -08003336 buffer->raw = NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003337 mFrameCount = buffer->frameCount;
Glenn Kasten01c4ebf2012-02-22 10:47:35 -08003338 (void) step(); // ignore return value of step()
Mathias Agopian65ab4712010-07-14 17:59:35 -07003339 buffer->frameCount = 0;
3340}
3341
3342bool AudioFlinger::ThreadBase::TrackBase::step() {
3343 bool result;
3344 audio_track_cblk_t* cblk = this->cblk();
3345
3346 result = cblk->stepServer(mFrameCount);
3347 if (!result) {
Steve Block3856b092011-10-20 11:56:00 +01003348 ALOGV("stepServer failed acquiring cblk mutex");
Glenn Kasten5cf034d2012-02-21 10:35:56 -08003349 mStepServerFailed = true;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003350 }
3351 return result;
3352}
3353
3354void AudioFlinger::ThreadBase::TrackBase::reset() {
3355 audio_track_cblk_t* cblk = this->cblk();
3356
3357 cblk->user = 0;
3358 cblk->server = 0;
3359 cblk->userBase = 0;
3360 cblk->serverBase = 0;
Glenn Kasten5cf034d2012-02-21 10:35:56 -08003361 mStepServerFailed = false;
Steve Block3856b092011-10-20 11:56:00 +01003362 ALOGV("TrackBase::reset");
Mathias Agopian65ab4712010-07-14 17:59:35 -07003363}
3364
Mathias Agopian65ab4712010-07-14 17:59:35 -07003365int AudioFlinger::ThreadBase::TrackBase::sampleRate() const {
3366 return (int)mCblk->sampleRate;
3367}
3368
Mathias Agopian65ab4712010-07-14 17:59:35 -07003369void* AudioFlinger::ThreadBase::TrackBase::getBuffer(uint32_t offset, uint32_t frames) const {
3370 audio_track_cblk_t* cblk = this->cblk();
Glenn Kastenb9980652012-01-11 09:48:27 -08003371 size_t frameSize = cblk->frameSize;
3372 int8_t *bufferStart = (int8_t *)mBuffer + (offset-cblk->serverBase)*frameSize;
3373 int8_t *bufferEnd = bufferStart + frames * frameSize;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003374
3375 // Check validity of returned pointer in case the track control block would have been corrupted.
3376 if (bufferStart < mBuffer || bufferStart > bufferEnd || bufferEnd > mBufferEnd ||
Glenn Kastenb9980652012-01-11 09:48:27 -08003377 ((unsigned long)bufferStart & (unsigned long)(frameSize - 1))) {
Steve Block29357bc2012-01-06 19:20:56 +00003378 ALOGE("TrackBase::getBuffer buffer out of range:\n start: %p, end %p , mBuffer %p mBufferEnd %p\n \
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07003379 server %d, serverBase %d, user %d, userBase %d",
Mathias Agopian65ab4712010-07-14 17:59:35 -07003380 bufferStart, bufferEnd, mBuffer, mBufferEnd,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07003381 cblk->server, cblk->serverBase, cblk->user, cblk->userBase);
Glenn Kastena0d68332012-01-27 16:47:15 -08003382 return NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003383 }
3384
3385 return bufferStart;
3386}
3387
3388// ----------------------------------------------------------------------------
3389
3390// Track constructor must be called with AudioFlinger::mLock and ThreadBase::mLock held
3391AudioFlinger::PlaybackThread::Track::Track(
Glenn Kasten9eaa5572012-01-20 13:32:16 -08003392 PlaybackThread *thread,
Mathias Agopian65ab4712010-07-14 17:59:35 -07003393 const sp<Client>& client,
Glenn Kastenfff6d712012-01-12 16:38:12 -08003394 audio_stream_type_t streamType,
Mathias Agopian65ab4712010-07-14 17:59:35 -07003395 uint32_t sampleRate,
Glenn Kasten58f30212012-01-12 12:27:51 -08003396 audio_format_t format,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07003397 uint32_t channelMask,
Mathias Agopian65ab4712010-07-14 17:59:35 -07003398 int frameCount,
3399 const sp<IMemory>& sharedBuffer,
3400 int sessionId)
Glenn Kasten5cf034d2012-02-21 10:35:56 -08003401 : TrackBase(thread, client, sampleRate, format, channelMask, frameCount, sharedBuffer, sessionId),
Eric Laurent8f45bd72010-08-31 13:50:07 -07003402 mMute(false), mSharedBuffer(sharedBuffer), mName(-1), mMainBuffer(NULL), mAuxBuffer(NULL),
3403 mAuxEffectId(0), mHasVolumeController(false)
Mathias Agopian65ab4712010-07-14 17:59:35 -07003404{
3405 if (mCblk != NULL) {
Glenn Kasten9eaa5572012-01-20 13:32:16 -08003406 if (thread != NULL) {
3407 mName = thread->getTrackName_l();
3408 mMainBuffer = thread->mixBuffer();
Mathias Agopian65ab4712010-07-14 17:59:35 -07003409 }
Glenn Kasten23d82a92012-02-03 11:10:00 -08003410 ALOGV("Track constructor name %d, calling pid %d", mName, IPCThreadState::self()->getCallingPid());
Mathias Agopian65ab4712010-07-14 17:59:35 -07003411 if (mName < 0) {
Steve Block29357bc2012-01-06 19:20:56 +00003412 ALOGE("no more track names available");
Mathias Agopian65ab4712010-07-14 17:59:35 -07003413 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07003414 mStreamType = streamType;
3415 // NOTE: audio_track_cblk_t::frameSize for 8 bit PCM data is based on a sample size of
3416 // 16 bit because data is converted to 16 bit before being stored in buffer by AudioTrack
Eric Laurentedc15ad2011-07-21 19:35:01 -07003417 mCblk->frameSize = audio_is_linear_pcm(format) ? mChannelCount * sizeof(int16_t) : sizeof(uint8_t);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003418 }
3419}
3420
3421AudioFlinger::PlaybackThread::Track::~Track()
3422{
Steve Block3856b092011-10-20 11:56:00 +01003423 ALOGV("PlaybackThread::Track destructor");
Mathias Agopian65ab4712010-07-14 17:59:35 -07003424 sp<ThreadBase> thread = mThread.promote();
3425 if (thread != 0) {
3426 Mutex::Autolock _l(thread->mLock);
3427 mState = TERMINATED;
3428 }
3429}
3430
3431void AudioFlinger::PlaybackThread::Track::destroy()
3432{
3433 // NOTE: destroyTrack_l() can remove a strong reference to this Track
3434 // by removing it from mTracks vector, so there is a risk that this Tracks's
Glenn Kasten99e53b82012-01-19 08:59:58 -08003435 // destructor is called. As the destructor needs to lock mLock,
Mathias Agopian65ab4712010-07-14 17:59:35 -07003436 // we must acquire a strong reference on this Track before locking mLock
3437 // here so that the destructor is called only when exiting this function.
3438 // On the other hand, as long as Track::destroy() is only called by
3439 // TrackHandle destructor, the TrackHandle still holds a strong ref on
3440 // this Track with its member mTrack.
3441 sp<Track> keep(this);
3442 { // scope for mLock
3443 sp<ThreadBase> thread = mThread.promote();
3444 if (thread != 0) {
3445 if (!isOutputTrack()) {
3446 if (mState == ACTIVE || mState == RESUMING) {
Glenn Kasten02bbd202012-02-08 12:35:35 -08003447 AudioSystem::stopOutput(thread->id(), mStreamType, mSessionId);
Gloria Wang9ee159b2011-02-24 14:51:45 -08003448
3449 // to track the speaker usage
3450 addBatteryData(IMediaPlayerService::kBatteryDataAudioFlingerStop);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003451 }
3452 AudioSystem::releaseOutput(thread->id());
3453 }
3454 Mutex::Autolock _l(thread->mLock);
3455 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
3456 playbackThread->destroyTrack_l(this);
3457 }
3458 }
3459}
3460
3461void AudioFlinger::PlaybackThread::Track::dump(char* buffer, size_t size)
3462{
Glenn Kasten83d86532012-01-17 14:39:34 -08003463 uint32_t vlr = mCblk->getVolumeLR();
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07003464 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",
Mathias Agopian65ab4712010-07-14 17:59:35 -07003465 mName - AudioMixer::TRACK0,
Glenn Kasten44deb052012-02-05 18:09:08 -08003466 (mClient == 0) ? getpid_cached : mClient->pid(),
Mathias Agopian65ab4712010-07-14 17:59:35 -07003467 mStreamType,
3468 mFormat,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07003469 mChannelMask,
Mathias Agopian65ab4712010-07-14 17:59:35 -07003470 mSessionId,
3471 mFrameCount,
3472 mState,
3473 mMute,
3474 mFillingUpStatus,
3475 mCblk->sampleRate,
Glenn Kastenb1cf75c2012-01-17 12:20:54 -08003476 vlr & 0xFFFF,
3477 vlr >> 16,
Mathias Agopian65ab4712010-07-14 17:59:35 -07003478 mCblk->server,
3479 mCblk->user,
3480 (int)mMainBuffer,
3481 (int)mAuxBuffer);
3482}
3483
Glenn Kasten01c4ebf2012-02-22 10:47:35 -08003484// AudioBufferProvider interface
John Grossman4ff14ba2012-02-08 16:37:41 -08003485status_t AudioFlinger::PlaybackThread::Track::getNextBuffer(
3486 AudioBufferProvider::Buffer* buffer, int64_t pts)
Mathias Agopian65ab4712010-07-14 17:59:35 -07003487{
3488 audio_track_cblk_t* cblk = this->cblk();
3489 uint32_t framesReady;
3490 uint32_t framesReq = buffer->frameCount;
3491
3492 // Check if last stepServer failed, try to step now
Glenn Kasten5cf034d2012-02-21 10:35:56 -08003493 if (mStepServerFailed) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07003494 if (!step()) goto getNextBuffer_exit;
Steve Block3856b092011-10-20 11:56:00 +01003495 ALOGV("stepServer recovered");
Glenn Kasten5cf034d2012-02-21 10:35:56 -08003496 mStepServerFailed = false;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003497 }
3498
3499 framesReady = cblk->framesReady();
3500
Glenn Kastenf6b16782011-12-15 09:51:17 -08003501 if (CC_LIKELY(framesReady)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07003502 uint32_t s = cblk->server;
3503 uint32_t bufferEnd = cblk->serverBase + cblk->frameCount;
3504
3505 bufferEnd = (cblk->loopEnd < bufferEnd) ? cblk->loopEnd : bufferEnd;
3506 if (framesReq > framesReady) {
3507 framesReq = framesReady;
3508 }
3509 if (s + framesReq > bufferEnd) {
3510 framesReq = bufferEnd - s;
3511 }
3512
3513 buffer->raw = getBuffer(s, framesReq);
Glenn Kastene0feee32011-12-13 11:53:26 -08003514 if (buffer->raw == NULL) goto getNextBuffer_exit;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003515
3516 buffer->frameCount = framesReq;
3517 return NO_ERROR;
3518 }
3519
3520getNextBuffer_exit:
Glenn Kastene0feee32011-12-13 11:53:26 -08003521 buffer->raw = NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003522 buffer->frameCount = 0;
Steve Block3856b092011-10-20 11:56:00 +01003523 ALOGV("getNextBuffer() no more data for track %d on thread %p", mName, mThread.unsafe_get());
Mathias Agopian65ab4712010-07-14 17:59:35 -07003524 return NOT_ENOUGH_DATA;
3525}
3526
John Grossman4ff14ba2012-02-08 16:37:41 -08003527uint32_t AudioFlinger::PlaybackThread::Track::framesReady() const{
3528 return mCblk->framesReady();
3529}
3530
Mathias Agopian65ab4712010-07-14 17:59:35 -07003531bool AudioFlinger::PlaybackThread::Track::isReady() const {
Eric Laurentaf59ce22010-10-05 14:41:42 -07003532 if (mFillingUpStatus != FS_FILLING || isStopped() || isPausing()) return true;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003533
John Grossman4ff14ba2012-02-08 16:37:41 -08003534 if (framesReady() >= mCblk->frameCount ||
Mathias Agopian65ab4712010-07-14 17:59:35 -07003535 (mCblk->flags & CBLK_FORCEREADY_MSK)) {
3536 mFillingUpStatus = FS_FILLED;
Eric Laurent38ccae22011-03-28 18:37:07 -07003537 android_atomic_and(~CBLK_FORCEREADY_MSK, &mCblk->flags);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003538 return true;
3539 }
3540 return false;
3541}
3542
Glenn Kasten6dbc1352012-02-02 10:56:47 -08003543status_t AudioFlinger::PlaybackThread::Track::start(pid_t tid)
Mathias Agopian65ab4712010-07-14 17:59:35 -07003544{
3545 status_t status = NO_ERROR;
Glenn Kasten6dbc1352012-02-02 10:56:47 -08003546 ALOGV("start(%d), calling pid %d session %d tid %d",
3547 mName, IPCThreadState::self()->getCallingPid(), mSessionId, tid);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003548 sp<ThreadBase> thread = mThread.promote();
3549 if (thread != 0) {
3550 Mutex::Autolock _l(thread->mLock);
Glenn Kastenb853e982012-01-26 13:39:18 -08003551 track_state state = mState;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003552 // here the track could be either new, or restarted
3553 // in both cases "unstop" the track
3554 if (mState == PAUSED) {
3555 mState = TrackBase::RESUMING;
Steve Block3856b092011-10-20 11:56:00 +01003556 ALOGV("PAUSED => RESUMING (%d) on thread %p", mName, this);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003557 } else {
3558 mState = TrackBase::ACTIVE;
Steve Block3856b092011-10-20 11:56:00 +01003559 ALOGV("? => ACTIVE (%d) on thread %p", mName, this);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003560 }
3561
3562 if (!isOutputTrack() && state != ACTIVE && state != RESUMING) {
3563 thread->mLock.unlock();
Glenn Kasten02bbd202012-02-08 12:35:35 -08003564 status = AudioSystem::startOutput(thread->id(), mStreamType, mSessionId);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003565 thread->mLock.lock();
Gloria Wang9ee159b2011-02-24 14:51:45 -08003566
3567 // to track the speaker usage
3568 if (status == NO_ERROR) {
3569 addBatteryData(IMediaPlayerService::kBatteryDataAudioFlingerStart);
3570 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07003571 }
3572 if (status == NO_ERROR) {
3573 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
3574 playbackThread->addTrack_l(this);
3575 } else {
3576 mState = state;
3577 }
3578 } else {
3579 status = BAD_VALUE;
3580 }
3581 return status;
3582}
3583
3584void AudioFlinger::PlaybackThread::Track::stop()
3585{
Glenn Kasten23d82a92012-02-03 11:10:00 -08003586 ALOGV("stop(%d), calling pid %d", mName, IPCThreadState::self()->getCallingPid());
Mathias Agopian65ab4712010-07-14 17:59:35 -07003587 sp<ThreadBase> thread = mThread.promote();
3588 if (thread != 0) {
3589 Mutex::Autolock _l(thread->mLock);
Glenn Kastenb853e982012-01-26 13:39:18 -08003590 track_state state = mState;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003591 if (mState > STOPPED) {
3592 mState = STOPPED;
3593 // If the track is not active (PAUSED and buffers full), flush buffers
3594 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
3595 if (playbackThread->mActiveTracks.indexOf(this) < 0) {
3596 reset();
3597 }
Steve Block3856b092011-10-20 11:56:00 +01003598 ALOGV("(> STOPPED) => STOPPED (%d) on thread %p", mName, playbackThread);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003599 }
3600 if (!isOutputTrack() && (state == ACTIVE || state == RESUMING)) {
3601 thread->mLock.unlock();
Glenn Kasten02bbd202012-02-08 12:35:35 -08003602 AudioSystem::stopOutput(thread->id(), mStreamType, mSessionId);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003603 thread->mLock.lock();
Gloria Wang9ee159b2011-02-24 14:51:45 -08003604
3605 // to track the speaker usage
3606 addBatteryData(IMediaPlayerService::kBatteryDataAudioFlingerStop);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003607 }
3608 }
3609}
3610
3611void AudioFlinger::PlaybackThread::Track::pause()
3612{
Glenn Kasten23d82a92012-02-03 11:10:00 -08003613 ALOGV("pause(%d), calling pid %d", mName, IPCThreadState::self()->getCallingPid());
Mathias Agopian65ab4712010-07-14 17:59:35 -07003614 sp<ThreadBase> thread = mThread.promote();
3615 if (thread != 0) {
3616 Mutex::Autolock _l(thread->mLock);
3617 if (mState == ACTIVE || mState == RESUMING) {
3618 mState = PAUSING;
Steve Block3856b092011-10-20 11:56:00 +01003619 ALOGV("ACTIVE/RESUMING => PAUSING (%d) on thread %p", mName, thread.get());
Mathias Agopian65ab4712010-07-14 17:59:35 -07003620 if (!isOutputTrack()) {
3621 thread->mLock.unlock();
Glenn Kasten02bbd202012-02-08 12:35:35 -08003622 AudioSystem::stopOutput(thread->id(), mStreamType, mSessionId);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003623 thread->mLock.lock();
Gloria Wang9ee159b2011-02-24 14:51:45 -08003624
3625 // to track the speaker usage
3626 addBatteryData(IMediaPlayerService::kBatteryDataAudioFlingerStop);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003627 }
3628 }
3629 }
3630}
3631
3632void AudioFlinger::PlaybackThread::Track::flush()
3633{
Steve Block3856b092011-10-20 11:56:00 +01003634 ALOGV("flush(%d)", mName);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003635 sp<ThreadBase> thread = mThread.promote();
3636 if (thread != 0) {
3637 Mutex::Autolock _l(thread->mLock);
3638 if (mState != STOPPED && mState != PAUSED && mState != PAUSING) {
3639 return;
3640 }
3641 // No point remaining in PAUSED state after a flush => go to
3642 // STOPPED state
3643 mState = STOPPED;
3644
Eric Laurent38ccae22011-03-28 18:37:07 -07003645 // do not reset the track if it is still in the process of being stopped or paused.
3646 // this will be done by prepareTracks_l() when the track is stopped.
3647 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
3648 if (playbackThread->mActiveTracks.indexOf(this) < 0) {
3649 reset();
3650 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07003651 }
3652}
3653
3654void AudioFlinger::PlaybackThread::Track::reset()
3655{
3656 // Do not reset twice to avoid discarding data written just after a flush and before
3657 // the audioflinger thread detects the track is stopped.
3658 if (!mResetDone) {
3659 TrackBase::reset();
3660 // Force underrun condition to avoid false underrun callback until first data is
3661 // written to buffer
Eric Laurent38ccae22011-03-28 18:37:07 -07003662 android_atomic_and(~CBLK_FORCEREADY_MSK, &mCblk->flags);
3663 android_atomic_or(CBLK_UNDERRUN_ON, &mCblk->flags);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003664 mFillingUpStatus = FS_FILLING;
3665 mResetDone = true;
3666 }
3667}
3668
3669void AudioFlinger::PlaybackThread::Track::mute(bool muted)
3670{
3671 mMute = muted;
3672}
3673
Mathias Agopian65ab4712010-07-14 17:59:35 -07003674status_t AudioFlinger::PlaybackThread::Track::attachAuxEffect(int EffectId)
3675{
3676 status_t status = DEAD_OBJECT;
3677 sp<ThreadBase> thread = mThread.promote();
3678 if (thread != 0) {
3679 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
3680 status = playbackThread->attachAuxEffect(this, EffectId);
3681 }
3682 return status;
3683}
3684
3685void AudioFlinger::PlaybackThread::Track::setAuxBuffer(int EffectId, int32_t *buffer)
3686{
3687 mAuxEffectId = EffectId;
3688 mAuxBuffer = buffer;
3689}
3690
John Grossman4ff14ba2012-02-08 16:37:41 -08003691// timed audio tracks
3692
3693sp<AudioFlinger::PlaybackThread::TimedTrack>
3694AudioFlinger::PlaybackThread::TimedTrack::create(
Glenn Kasten9eaa5572012-01-20 13:32:16 -08003695 PlaybackThread *thread,
John Grossman4ff14ba2012-02-08 16:37:41 -08003696 const sp<Client>& client,
3697 audio_stream_type_t streamType,
3698 uint32_t sampleRate,
3699 audio_format_t format,
3700 uint32_t channelMask,
3701 int frameCount,
3702 const sp<IMemory>& sharedBuffer,
3703 int sessionId) {
3704 if (!client->reserveTimedTrack())
3705 return NULL;
3706
3707 sp<TimedTrack> track = new TimedTrack(
3708 thread, client, streamType, sampleRate, format, channelMask, frameCount,
3709 sharedBuffer, sessionId);
3710
3711 if (track == NULL) {
3712 client->releaseTimedTrack();
3713 return NULL;
3714 }
3715
3716 return track;
3717}
3718
3719AudioFlinger::PlaybackThread::TimedTrack::TimedTrack(
Glenn Kasten9eaa5572012-01-20 13:32:16 -08003720 PlaybackThread *thread,
John Grossman4ff14ba2012-02-08 16:37:41 -08003721 const sp<Client>& client,
3722 audio_stream_type_t streamType,
3723 uint32_t sampleRate,
3724 audio_format_t format,
3725 uint32_t channelMask,
3726 int frameCount,
3727 const sp<IMemory>& sharedBuffer,
3728 int sessionId)
3729 : Track(thread, client, streamType, sampleRate, format, channelMask,
3730 frameCount, sharedBuffer, sessionId),
3731 mTimedSilenceBuffer(NULL),
3732 mTimedSilenceBufferSize(0),
3733 mTimedAudioOutputOnTime(false),
3734 mMediaTimeTransformValid(false)
3735{
3736 LocalClock lc;
3737 mLocalTimeFreq = lc.getLocalFreq();
3738
3739 mLocalTimeToSampleTransform.a_zero = 0;
3740 mLocalTimeToSampleTransform.b_zero = 0;
3741 mLocalTimeToSampleTransform.a_to_b_numer = sampleRate;
3742 mLocalTimeToSampleTransform.a_to_b_denom = mLocalTimeFreq;
3743 LinearTransform::reduce(&mLocalTimeToSampleTransform.a_to_b_numer,
3744 &mLocalTimeToSampleTransform.a_to_b_denom);
3745}
3746
3747AudioFlinger::PlaybackThread::TimedTrack::~TimedTrack() {
3748 mClient->releaseTimedTrack();
3749 delete [] mTimedSilenceBuffer;
3750}
3751
3752status_t AudioFlinger::PlaybackThread::TimedTrack::allocateTimedBuffer(
3753 size_t size, sp<IMemory>* buffer) {
3754
3755 Mutex::Autolock _l(mTimedBufferQueueLock);
3756
3757 trimTimedBufferQueue_l();
3758
3759 // lazily initialize the shared memory heap for timed buffers
3760 if (mTimedMemoryDealer == NULL) {
3761 const int kTimedBufferHeapSize = 512 << 10;
3762
3763 mTimedMemoryDealer = new MemoryDealer(kTimedBufferHeapSize,
3764 "AudioFlingerTimed");
3765 if (mTimedMemoryDealer == NULL)
3766 return NO_MEMORY;
3767 }
3768
3769 sp<IMemory> newBuffer = mTimedMemoryDealer->allocate(size);
3770 if (newBuffer == NULL) {
3771 newBuffer = mTimedMemoryDealer->allocate(size);
3772 if (newBuffer == NULL)
3773 return NO_MEMORY;
3774 }
3775
3776 *buffer = newBuffer;
3777 return NO_ERROR;
3778}
3779
3780// caller must hold mTimedBufferQueueLock
3781void AudioFlinger::PlaybackThread::TimedTrack::trimTimedBufferQueue_l() {
3782 int64_t mediaTimeNow;
3783 {
3784 Mutex::Autolock mttLock(mMediaTimeTransformLock);
3785 if (!mMediaTimeTransformValid)
3786 return;
3787
3788 int64_t targetTimeNow;
3789 status_t res = (mMediaTimeTransformTarget == TimedAudioTrack::COMMON_TIME)
3790 ? mCCHelper.getCommonTime(&targetTimeNow)
3791 : mCCHelper.getLocalTime(&targetTimeNow);
3792
3793 if (OK != res)
3794 return;
3795
3796 if (!mMediaTimeTransform.doReverseTransform(targetTimeNow,
3797 &mediaTimeNow)) {
3798 return;
3799 }
3800 }
3801
3802 size_t trimIndex;
3803 for (trimIndex = 0; trimIndex < mTimedBufferQueue.size(); trimIndex++) {
3804 if (mTimedBufferQueue[trimIndex].pts() > mediaTimeNow)
3805 break;
3806 }
3807
3808 if (trimIndex) {
3809 mTimedBufferQueue.removeItemsAt(0, trimIndex);
3810 }
3811}
3812
3813status_t AudioFlinger::PlaybackThread::TimedTrack::queueTimedBuffer(
3814 const sp<IMemory>& buffer, int64_t pts) {
3815
3816 {
3817 Mutex::Autolock mttLock(mMediaTimeTransformLock);
3818 if (!mMediaTimeTransformValid)
3819 return INVALID_OPERATION;
3820 }
3821
3822 Mutex::Autolock _l(mTimedBufferQueueLock);
3823
3824 mTimedBufferQueue.add(TimedBuffer(buffer, pts));
3825
3826 return NO_ERROR;
3827}
3828
3829status_t AudioFlinger::PlaybackThread::TimedTrack::setMediaTimeTransform(
3830 const LinearTransform& xform, TimedAudioTrack::TargetTimeline target) {
3831
3832 ALOGV("%s az=%lld bz=%lld n=%d d=%u tgt=%d", __PRETTY_FUNCTION__,
3833 xform.a_zero, xform.b_zero, xform.a_to_b_numer, xform.a_to_b_denom,
3834 target);
3835
3836 if (!(target == TimedAudioTrack::LOCAL_TIME ||
3837 target == TimedAudioTrack::COMMON_TIME)) {
3838 return BAD_VALUE;
3839 }
3840
3841 Mutex::Autolock lock(mMediaTimeTransformLock);
3842 mMediaTimeTransform = xform;
3843 mMediaTimeTransformTarget = target;
3844 mMediaTimeTransformValid = true;
3845
3846 return NO_ERROR;
3847}
3848
3849#define min(a, b) ((a) < (b) ? (a) : (b))
3850
3851// implementation of getNextBuffer for tracks whose buffers have timestamps
3852status_t AudioFlinger::PlaybackThread::TimedTrack::getNextBuffer(
3853 AudioBufferProvider::Buffer* buffer, int64_t pts)
3854{
3855 if (pts == AudioBufferProvider::kInvalidPTS) {
3856 buffer->raw = 0;
3857 buffer->frameCount = 0;
3858 return INVALID_OPERATION;
3859 }
3860
John Grossman4ff14ba2012-02-08 16:37:41 -08003861 Mutex::Autolock _l(mTimedBufferQueueLock);
3862
3863 while (true) {
3864
3865 // if we have no timed buffers, then fail
3866 if (mTimedBufferQueue.isEmpty()) {
3867 buffer->raw = 0;
3868 buffer->frameCount = 0;
3869 return NOT_ENOUGH_DATA;
3870 }
3871
3872 TimedBuffer& head = mTimedBufferQueue.editItemAt(0);
3873
3874 // calculate the PTS of the head of the timed buffer queue expressed in
3875 // local time
3876 int64_t headLocalPTS;
3877 {
3878 Mutex::Autolock mttLock(mMediaTimeTransformLock);
3879
3880 assert(mMediaTimeTransformValid);
3881
3882 if (mMediaTimeTransform.a_to_b_denom == 0) {
3883 // the transform represents a pause, so yield silence
3884 timedYieldSilence(buffer->frameCount, buffer);
3885 return NO_ERROR;
3886 }
3887
3888 int64_t transformedPTS;
3889 if (!mMediaTimeTransform.doForwardTransform(head.pts(),
3890 &transformedPTS)) {
3891 // the transform failed. this shouldn't happen, but if it does
3892 // then just drop this buffer
3893 ALOGW("timedGetNextBuffer transform failed");
3894 buffer->raw = 0;
3895 buffer->frameCount = 0;
3896 mTimedBufferQueue.removeAt(0);
3897 return NO_ERROR;
3898 }
3899
3900 if (mMediaTimeTransformTarget == TimedAudioTrack::COMMON_TIME) {
3901 if (OK != mCCHelper.commonTimeToLocalTime(transformedPTS,
3902 &headLocalPTS)) {
3903 buffer->raw = 0;
3904 buffer->frameCount = 0;
3905 return INVALID_OPERATION;
3906 }
3907 } else {
3908 headLocalPTS = transformedPTS;
3909 }
3910 }
3911
3912 // adjust the head buffer's PTS to reflect the portion of the head buffer
3913 // that has already been consumed
3914 int64_t effectivePTS = headLocalPTS +
3915 ((head.position() / mCblk->frameSize) * mLocalTimeFreq / sampleRate());
3916
3917 // Calculate the delta in samples between the head of the input buffer
3918 // queue and the start of the next output buffer that will be written.
3919 // If the transformation fails because of over or underflow, it means
3920 // that the sample's position in the output stream is so far out of
3921 // whack that it should just be dropped.
3922 int64_t sampleDelta;
3923 if (llabs(effectivePTS - pts) >= (static_cast<int64_t>(1) << 31)) {
3924 ALOGV("*** head buffer is too far from PTS: dropped buffer");
3925 mTimedBufferQueue.removeAt(0);
3926 continue;
3927 }
3928 if (!mLocalTimeToSampleTransform.doForwardTransform(
3929 (effectivePTS - pts) << 32, &sampleDelta)) {
3930 ALOGV("*** too late during sample rate transform: dropped buffer");
3931 mTimedBufferQueue.removeAt(0);
3932 continue;
3933 }
3934
3935 ALOGV("*** %s head.pts=%lld head.pos=%d pts=%lld sampleDelta=[%d.%08x]",
3936 __PRETTY_FUNCTION__, head.pts(), head.position(), pts,
3937 static_cast<int32_t>((sampleDelta >= 0 ? 0 : 1) + (sampleDelta >> 32)),
3938 static_cast<uint32_t>(sampleDelta & 0xFFFFFFFF));
3939
3940 // if the delta between the ideal placement for the next input sample and
3941 // the current output position is within this threshold, then we will
3942 // concatenate the next input samples to the previous output
3943 const int64_t kSampleContinuityThreshold =
3944 (static_cast<int64_t>(sampleRate()) << 32) / 10;
3945
3946 // if this is the first buffer of audio that we're emitting from this track
3947 // then it should be almost exactly on time.
3948 const int64_t kSampleStartupThreshold = 1LL << 32;
3949
3950 if ((mTimedAudioOutputOnTime && llabs(sampleDelta) <= kSampleContinuityThreshold) ||
3951 (!mTimedAudioOutputOnTime && llabs(sampleDelta) <= kSampleStartupThreshold)) {
3952 // the next input is close enough to being on time, so concatenate it
3953 // with the last output
3954 timedYieldSamples(buffer);
3955
3956 ALOGV("*** on time: head.pos=%d frameCount=%u", head.position(), buffer->frameCount);
3957 return NO_ERROR;
3958 } else if (sampleDelta > 0) {
3959 // the gap between the current output position and the proper start of
3960 // the next input sample is too big, so fill it with silence
3961 uint32_t framesUntilNextInput = (sampleDelta + 0x80000000) >> 32;
3962
3963 timedYieldSilence(framesUntilNextInput, buffer);
3964 ALOGV("*** silence: frameCount=%u", buffer->frameCount);
3965 return NO_ERROR;
3966 } else {
3967 // the next input sample is late
3968 uint32_t lateFrames = static_cast<uint32_t>(-((sampleDelta + 0x80000000) >> 32));
3969 size_t onTimeSamplePosition =
3970 head.position() + lateFrames * mCblk->frameSize;
3971
3972 if (onTimeSamplePosition > head.buffer()->size()) {
3973 // all the remaining samples in the head are too late, so
3974 // drop it and move on
3975 ALOGV("*** too late: dropped buffer");
3976 mTimedBufferQueue.removeAt(0);
3977 continue;
3978 } else {
3979 // skip over the late samples
3980 head.setPosition(onTimeSamplePosition);
3981
3982 // yield the available samples
3983 timedYieldSamples(buffer);
3984
3985 ALOGV("*** late: head.pos=%d frameCount=%u", head.position(), buffer->frameCount);
3986 return NO_ERROR;
3987 }
3988 }
3989 }
3990}
3991
3992// Yield samples from the timed buffer queue head up to the given output
3993// buffer's capacity.
3994//
3995// Caller must hold mTimedBufferQueueLock
3996void AudioFlinger::PlaybackThread::TimedTrack::timedYieldSamples(
3997 AudioBufferProvider::Buffer* buffer) {
3998
3999 const TimedBuffer& head = mTimedBufferQueue[0];
4000
4001 buffer->raw = (static_cast<uint8_t*>(head.buffer()->pointer()) +
4002 head.position());
4003
4004 uint32_t framesLeftInHead = ((head.buffer()->size() - head.position()) /
4005 mCblk->frameSize);
4006 size_t framesRequested = buffer->frameCount;
4007 buffer->frameCount = min(framesLeftInHead, framesRequested);
4008
4009 mTimedAudioOutputOnTime = true;
4010}
4011
4012// Yield samples of silence up to the given output buffer's capacity
4013//
4014// Caller must hold mTimedBufferQueueLock
4015void AudioFlinger::PlaybackThread::TimedTrack::timedYieldSilence(
4016 uint32_t numFrames, AudioBufferProvider::Buffer* buffer) {
4017
4018 // lazily allocate a buffer filled with silence
4019 if (mTimedSilenceBufferSize < numFrames * mCblk->frameSize) {
4020 delete [] mTimedSilenceBuffer;
4021 mTimedSilenceBufferSize = numFrames * mCblk->frameSize;
4022 mTimedSilenceBuffer = new uint8_t[mTimedSilenceBufferSize];
4023 memset(mTimedSilenceBuffer, 0, mTimedSilenceBufferSize);
4024 }
4025
4026 buffer->raw = mTimedSilenceBuffer;
4027 size_t framesRequested = buffer->frameCount;
4028 buffer->frameCount = min(numFrames, framesRequested);
4029
4030 mTimedAudioOutputOnTime = false;
4031}
4032
Glenn Kasten01c4ebf2012-02-22 10:47:35 -08004033// AudioBufferProvider interface
John Grossman4ff14ba2012-02-08 16:37:41 -08004034void AudioFlinger::PlaybackThread::TimedTrack::releaseBuffer(
4035 AudioBufferProvider::Buffer* buffer) {
4036
4037 Mutex::Autolock _l(mTimedBufferQueueLock);
4038
John Grossmanfe5b3ba2012-02-12 17:51:21 -08004039 // If the buffer which was just released is part of the buffer at the head
4040 // of the queue, be sure to update the amt of the buffer which has been
4041 // consumed. If the buffer being returned is not part of the head of the
4042 // queue, its either because the buffer is part of the silence buffer, or
4043 // because the head of the timed queue was trimmed after the mixer called
4044 // getNextBuffer but before the mixer called releaseBuffer.
4045 if ((buffer->raw != mTimedSilenceBuffer) && mTimedBufferQueue.size()) {
John Grossman4ff14ba2012-02-08 16:37:41 -08004046 TimedBuffer& head = mTimedBufferQueue.editItemAt(0);
John Grossmanfe5b3ba2012-02-12 17:51:21 -08004047
4048 void* start = head.buffer()->pointer();
Glenn Kastenf063b492012-02-17 16:24:10 -08004049 void* end = (char *) head.buffer()->pointer() + head.buffer()->size();
John Grossmanfe5b3ba2012-02-12 17:51:21 -08004050
4051 if ((buffer->raw >= start) && (buffer->raw <= end)) {
4052 head.setPosition(head.position() +
4053 (buffer->frameCount * mCblk->frameSize));
4054 if (static_cast<size_t>(head.position()) >= head.buffer()->size()) {
4055 mTimedBufferQueue.removeAt(0);
4056 }
John Grossman4ff14ba2012-02-08 16:37:41 -08004057 }
4058 }
4059
4060 buffer->raw = 0;
4061 buffer->frameCount = 0;
4062}
4063
4064uint32_t AudioFlinger::PlaybackThread::TimedTrack::framesReady() const {
4065 Mutex::Autolock _l(mTimedBufferQueueLock);
4066
4067 uint32_t frames = 0;
4068 for (size_t i = 0; i < mTimedBufferQueue.size(); i++) {
4069 const TimedBuffer& tb = mTimedBufferQueue[i];
4070 frames += (tb.buffer()->size() - tb.position()) / mCblk->frameSize;
4071 }
4072
4073 return frames;
4074}
4075
4076AudioFlinger::PlaybackThread::TimedTrack::TimedBuffer::TimedBuffer()
4077 : mPTS(0), mPosition(0) {}
4078
4079AudioFlinger::PlaybackThread::TimedTrack::TimedBuffer::TimedBuffer(
4080 const sp<IMemory>& buffer, int64_t pts)
4081 : mBuffer(buffer), mPTS(pts), mPosition(0) {}
4082
Mathias Agopian65ab4712010-07-14 17:59:35 -07004083// ----------------------------------------------------------------------------
4084
4085// RecordTrack constructor must be called with AudioFlinger::mLock held
4086AudioFlinger::RecordThread::RecordTrack::RecordTrack(
Glenn Kasten9eaa5572012-01-20 13:32:16 -08004087 RecordThread *thread,
Mathias Agopian65ab4712010-07-14 17:59:35 -07004088 const sp<Client>& client,
4089 uint32_t sampleRate,
Glenn Kasten58f30212012-01-12 12:27:51 -08004090 audio_format_t format,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07004091 uint32_t channelMask,
Mathias Agopian65ab4712010-07-14 17:59:35 -07004092 int frameCount,
Mathias Agopian65ab4712010-07-14 17:59:35 -07004093 int sessionId)
4094 : TrackBase(thread, client, sampleRate, format,
Glenn Kasten5cf034d2012-02-21 10:35:56 -08004095 channelMask, frameCount, 0 /*sharedBuffer*/, sessionId),
Mathias Agopian65ab4712010-07-14 17:59:35 -07004096 mOverflow(false)
4097{
4098 if (mCblk != NULL) {
Steve Block3856b092011-10-20 11:56:00 +01004099 ALOGV("RecordTrack constructor, size %d", (int)mBufferEnd - (int)mBuffer);
Dima Zavinfce7a472011-04-19 22:30:36 -07004100 if (format == AUDIO_FORMAT_PCM_16_BIT) {
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07004101 mCblk->frameSize = mChannelCount * sizeof(int16_t);
Dima Zavinfce7a472011-04-19 22:30:36 -07004102 } else if (format == AUDIO_FORMAT_PCM_8_BIT) {
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07004103 mCblk->frameSize = mChannelCount * sizeof(int8_t);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004104 } else {
4105 mCblk->frameSize = sizeof(int8_t);
4106 }
4107 }
4108}
4109
4110AudioFlinger::RecordThread::RecordTrack::~RecordTrack()
4111{
4112 sp<ThreadBase> thread = mThread.promote();
4113 if (thread != 0) {
4114 AudioSystem::releaseInput(thread->id());
4115 }
4116}
4117
Glenn Kasten01c4ebf2012-02-22 10:47:35 -08004118// AudioBufferProvider interface
John Grossman4ff14ba2012-02-08 16:37:41 -08004119status_t AudioFlinger::RecordThread::RecordTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer, int64_t pts)
Mathias Agopian65ab4712010-07-14 17:59:35 -07004120{
4121 audio_track_cblk_t* cblk = this->cblk();
4122 uint32_t framesAvail;
4123 uint32_t framesReq = buffer->frameCount;
4124
4125 // Check if last stepServer failed, try to step now
Glenn Kasten5cf034d2012-02-21 10:35:56 -08004126 if (mStepServerFailed) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07004127 if (!step()) goto getNextBuffer_exit;
Steve Block3856b092011-10-20 11:56:00 +01004128 ALOGV("stepServer recovered");
Glenn Kasten5cf034d2012-02-21 10:35:56 -08004129 mStepServerFailed = false;
Mathias Agopian65ab4712010-07-14 17:59:35 -07004130 }
4131
4132 framesAvail = cblk->framesAvailable_l();
4133
Glenn Kastenf6b16782011-12-15 09:51:17 -08004134 if (CC_LIKELY(framesAvail)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07004135 uint32_t s = cblk->server;
4136 uint32_t bufferEnd = cblk->serverBase + cblk->frameCount;
4137
4138 if (framesReq > framesAvail) {
4139 framesReq = framesAvail;
4140 }
4141 if (s + framesReq > bufferEnd) {
4142 framesReq = bufferEnd - s;
4143 }
4144
4145 buffer->raw = getBuffer(s, framesReq);
Glenn Kastene0feee32011-12-13 11:53:26 -08004146 if (buffer->raw == NULL) goto getNextBuffer_exit;
Mathias Agopian65ab4712010-07-14 17:59:35 -07004147
4148 buffer->frameCount = framesReq;
4149 return NO_ERROR;
4150 }
4151
4152getNextBuffer_exit:
Glenn Kastene0feee32011-12-13 11:53:26 -08004153 buffer->raw = NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -07004154 buffer->frameCount = 0;
4155 return NOT_ENOUGH_DATA;
4156}
4157
Glenn Kasten6dbc1352012-02-02 10:56:47 -08004158status_t AudioFlinger::RecordThread::RecordTrack::start(pid_t tid)
Mathias Agopian65ab4712010-07-14 17:59:35 -07004159{
4160 sp<ThreadBase> thread = mThread.promote();
4161 if (thread != 0) {
4162 RecordThread *recordThread = (RecordThread *)thread.get();
Glenn Kasten6dbc1352012-02-02 10:56:47 -08004163 return recordThread->start(this, tid);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004164 } else {
4165 return BAD_VALUE;
4166 }
4167}
4168
4169void AudioFlinger::RecordThread::RecordTrack::stop()
4170{
4171 sp<ThreadBase> thread = mThread.promote();
4172 if (thread != 0) {
4173 RecordThread *recordThread = (RecordThread *)thread.get();
4174 recordThread->stop(this);
Eric Laurent38ccae22011-03-28 18:37:07 -07004175 TrackBase::reset();
4176 // Force overerrun condition to avoid false overrun callback until first data is
4177 // read from buffer
4178 android_atomic_or(CBLK_UNDERRUN_ON, &mCblk->flags);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004179 }
4180}
4181
4182void AudioFlinger::RecordThread::RecordTrack::dump(char* buffer, size_t size)
4183{
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07004184 snprintf(buffer, size, " %05d %03u 0x%08x %05d %04u %01d %05u %08x %08x\n",
Glenn Kasten44deb052012-02-05 18:09:08 -08004185 (mClient == 0) ? getpid_cached : mClient->pid(),
Mathias Agopian65ab4712010-07-14 17:59:35 -07004186 mFormat,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07004187 mChannelMask,
Mathias Agopian65ab4712010-07-14 17:59:35 -07004188 mSessionId,
4189 mFrameCount,
4190 mState,
4191 mCblk->sampleRate,
4192 mCblk->server,
4193 mCblk->user);
4194}
4195
4196
4197// ----------------------------------------------------------------------------
4198
4199AudioFlinger::PlaybackThread::OutputTrack::OutputTrack(
Glenn Kasten9eaa5572012-01-20 13:32:16 -08004200 PlaybackThread *playbackThread,
Mathias Agopian65ab4712010-07-14 17:59:35 -07004201 DuplicatingThread *sourceThread,
4202 uint32_t sampleRate,
Glenn Kasten58f30212012-01-12 12:27:51 -08004203 audio_format_t format,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07004204 uint32_t channelMask,
Mathias Agopian65ab4712010-07-14 17:59:35 -07004205 int frameCount)
Glenn Kasten9eaa5572012-01-20 13:32:16 -08004206 : Track(playbackThread, NULL, AUDIO_STREAM_CNT, sampleRate, format, channelMask, frameCount, NULL, 0),
Mathias Agopian65ab4712010-07-14 17:59:35 -07004207 mActive(false), mSourceThread(sourceThread)
4208{
4209
Mathias Agopian65ab4712010-07-14 17:59:35 -07004210 if (mCblk != NULL) {
4211 mCblk->flags |= CBLK_DIRECTION_OUT;
4212 mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004213 mOutBuffer.frameCount = 0;
4214 playbackThread->mTracks.add(this);
Steve Block3856b092011-10-20 11:56:00 +01004215 ALOGV("OutputTrack constructor mCblk %p, mBuffer %p, mCblk->buffers %p, " \
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07004216 "mCblk->frameCount %d, mCblk->sampleRate %d, mChannelMask 0x%08x mBufferEnd %p",
4217 mCblk, mBuffer, mCblk->buffers,
4218 mCblk->frameCount, mCblk->sampleRate, mChannelMask, mBufferEnd);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004219 } else {
Steve Block5ff1dd52012-01-05 23:22:43 +00004220 ALOGW("Error creating output track on thread %p", playbackThread);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004221 }
4222}
4223
4224AudioFlinger::PlaybackThread::OutputTrack::~OutputTrack()
4225{
4226 clearBufferQueue();
4227}
4228
Glenn Kasten6dbc1352012-02-02 10:56:47 -08004229status_t AudioFlinger::PlaybackThread::OutputTrack::start(pid_t tid)
Mathias Agopian65ab4712010-07-14 17:59:35 -07004230{
Glenn Kasten6dbc1352012-02-02 10:56:47 -08004231 status_t status = Track::start(tid);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004232 if (status != NO_ERROR) {
4233 return status;
4234 }
4235
4236 mActive = true;
4237 mRetryCount = 127;
4238 return status;
4239}
4240
4241void AudioFlinger::PlaybackThread::OutputTrack::stop()
4242{
4243 Track::stop();
4244 clearBufferQueue();
4245 mOutBuffer.frameCount = 0;
4246 mActive = false;
4247}
4248
4249bool AudioFlinger::PlaybackThread::OutputTrack::write(int16_t* data, uint32_t frames)
4250{
4251 Buffer *pInBuffer;
4252 Buffer inBuffer;
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07004253 uint32_t channelCount = mChannelCount;
Mathias Agopian65ab4712010-07-14 17:59:35 -07004254 bool outputBufferFull = false;
4255 inBuffer.frameCount = frames;
4256 inBuffer.i16 = data;
4257
4258 uint32_t waitTimeLeftMs = mSourceThread->waitTimeMs();
4259
4260 if (!mActive && frames != 0) {
Glenn Kasten6dbc1352012-02-02 10:56:47 -08004261 start(0);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004262 sp<ThreadBase> thread = mThread.promote();
4263 if (thread != 0) {
4264 MixerThread *mixerThread = (MixerThread *)thread.get();
4265 if (mCblk->frameCount > frames){
4266 if (mBufferQueue.size() < kMaxOverFlowBuffers) {
4267 uint32_t startFrames = (mCblk->frameCount - frames);
4268 pInBuffer = new Buffer;
4269 pInBuffer->mBuffer = new int16_t[startFrames * channelCount];
4270 pInBuffer->frameCount = startFrames;
4271 pInBuffer->i16 = pInBuffer->mBuffer;
4272 memset(pInBuffer->raw, 0, startFrames * channelCount * sizeof(int16_t));
4273 mBufferQueue.add(pInBuffer);
4274 } else {
Steve Block5ff1dd52012-01-05 23:22:43 +00004275 ALOGW ("OutputTrack::write() %p no more buffers in queue", this);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004276 }
4277 }
4278 }
4279 }
4280
4281 while (waitTimeLeftMs) {
4282 // First write pending buffers, then new data
4283 if (mBufferQueue.size()) {
4284 pInBuffer = mBufferQueue.itemAt(0);
4285 } else {
4286 pInBuffer = &inBuffer;
4287 }
4288
4289 if (pInBuffer->frameCount == 0) {
4290 break;
4291 }
4292
4293 if (mOutBuffer.frameCount == 0) {
4294 mOutBuffer.frameCount = pInBuffer->frameCount;
4295 nsecs_t startTime = systemTime();
Glenn Kasten335787f2012-01-20 17:00:00 -08004296 if (obtainBuffer(&mOutBuffer, waitTimeLeftMs) == (status_t)NO_MORE_BUFFERS) {
Steve Block3856b092011-10-20 11:56:00 +01004297 ALOGV ("OutputTrack::write() %p thread %p no more output buffers", this, mThread.unsafe_get());
Mathias Agopian65ab4712010-07-14 17:59:35 -07004298 outputBufferFull = true;
4299 break;
4300 }
4301 uint32_t waitTimeMs = (uint32_t)ns2ms(systemTime() - startTime);
4302 if (waitTimeLeftMs >= waitTimeMs) {
4303 waitTimeLeftMs -= waitTimeMs;
4304 } else {
4305 waitTimeLeftMs = 0;
4306 }
4307 }
4308
4309 uint32_t outFrames = pInBuffer->frameCount > mOutBuffer.frameCount ? mOutBuffer.frameCount : pInBuffer->frameCount;
4310 memcpy(mOutBuffer.raw, pInBuffer->raw, outFrames * channelCount * sizeof(int16_t));
4311 mCblk->stepUser(outFrames);
4312 pInBuffer->frameCount -= outFrames;
4313 pInBuffer->i16 += outFrames * channelCount;
4314 mOutBuffer.frameCount -= outFrames;
4315 mOutBuffer.i16 += outFrames * channelCount;
4316
4317 if (pInBuffer->frameCount == 0) {
4318 if (mBufferQueue.size()) {
4319 mBufferQueue.removeAt(0);
4320 delete [] pInBuffer->mBuffer;
4321 delete pInBuffer;
Steve Block3856b092011-10-20 11:56:00 +01004322 ALOGV("OutputTrack::write() %p thread %p released overflow buffer %d", this, mThread.unsafe_get(), mBufferQueue.size());
Mathias Agopian65ab4712010-07-14 17:59:35 -07004323 } else {
4324 break;
4325 }
4326 }
4327 }
4328
4329 // If we could not write all frames, allocate a buffer and queue it for next time.
4330 if (inBuffer.frameCount) {
4331 sp<ThreadBase> thread = mThread.promote();
4332 if (thread != 0 && !thread->standby()) {
4333 if (mBufferQueue.size() < kMaxOverFlowBuffers) {
4334 pInBuffer = new Buffer;
4335 pInBuffer->mBuffer = new int16_t[inBuffer.frameCount * channelCount];
4336 pInBuffer->frameCount = inBuffer.frameCount;
4337 pInBuffer->i16 = pInBuffer->mBuffer;
4338 memcpy(pInBuffer->raw, inBuffer.raw, inBuffer.frameCount * channelCount * sizeof(int16_t));
4339 mBufferQueue.add(pInBuffer);
Steve Block3856b092011-10-20 11:56:00 +01004340 ALOGV("OutputTrack::write() %p thread %p adding overflow buffer %d", this, mThread.unsafe_get(), mBufferQueue.size());
Mathias Agopian65ab4712010-07-14 17:59:35 -07004341 } else {
Steve Block5ff1dd52012-01-05 23:22:43 +00004342 ALOGW("OutputTrack::write() %p thread %p no more overflow buffers", mThread.unsafe_get(), this);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004343 }
4344 }
4345 }
4346
4347 // Calling write() with a 0 length buffer, means that no more data will be written:
4348 // If no more buffers are pending, fill output track buffer to make sure it is started
4349 // by output mixer.
4350 if (frames == 0 && mBufferQueue.size() == 0) {
4351 if (mCblk->user < mCblk->frameCount) {
4352 frames = mCblk->frameCount - mCblk->user;
4353 pInBuffer = new Buffer;
4354 pInBuffer->mBuffer = new int16_t[frames * channelCount];
4355 pInBuffer->frameCount = frames;
4356 pInBuffer->i16 = pInBuffer->mBuffer;
4357 memset(pInBuffer->raw, 0, frames * channelCount * sizeof(int16_t));
4358 mBufferQueue.add(pInBuffer);
4359 } else if (mActive) {
4360 stop();
4361 }
4362 }
4363
4364 return outputBufferFull;
4365}
4366
4367status_t AudioFlinger::PlaybackThread::OutputTrack::obtainBuffer(AudioBufferProvider::Buffer* buffer, uint32_t waitTimeMs)
4368{
4369 int active;
4370 status_t result;
4371 audio_track_cblk_t* cblk = mCblk;
4372 uint32_t framesReq = buffer->frameCount;
4373
Steve Block3856b092011-10-20 11:56:00 +01004374// ALOGV("OutputTrack::obtainBuffer user %d, server %d", cblk->user, cblk->server);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004375 buffer->frameCount = 0;
4376
4377 uint32_t framesAvail = cblk->framesAvailable();
4378
4379
4380 if (framesAvail == 0) {
4381 Mutex::Autolock _l(cblk->lock);
4382 goto start_loop_here;
4383 while (framesAvail == 0) {
4384 active = mActive;
Glenn Kastenf6b16782011-12-15 09:51:17 -08004385 if (CC_UNLIKELY(!active)) {
Steve Block3856b092011-10-20 11:56:00 +01004386 ALOGV("Not active and NO_MORE_BUFFERS");
Glenn Kasten335787f2012-01-20 17:00:00 -08004387 return NO_MORE_BUFFERS;
Mathias Agopian65ab4712010-07-14 17:59:35 -07004388 }
4389 result = cblk->cv.waitRelative(cblk->lock, milliseconds(waitTimeMs));
4390 if (result != NO_ERROR) {
Glenn Kasten335787f2012-01-20 17:00:00 -08004391 return NO_MORE_BUFFERS;
Mathias Agopian65ab4712010-07-14 17:59:35 -07004392 }
4393 // read the server count again
4394 start_loop_here:
4395 framesAvail = cblk->framesAvailable_l();
4396 }
4397 }
4398
4399// if (framesAvail < framesReq) {
Glenn Kasten335787f2012-01-20 17:00:00 -08004400// return NO_MORE_BUFFERS;
Mathias Agopian65ab4712010-07-14 17:59:35 -07004401// }
4402
4403 if (framesReq > framesAvail) {
4404 framesReq = framesAvail;
4405 }
4406
4407 uint32_t u = cblk->user;
4408 uint32_t bufferEnd = cblk->userBase + cblk->frameCount;
4409
4410 if (u + framesReq > bufferEnd) {
4411 framesReq = bufferEnd - u;
4412 }
4413
4414 buffer->frameCount = framesReq;
4415 buffer->raw = (void *)cblk->buffer(u);
4416 return NO_ERROR;
4417}
4418
4419
4420void AudioFlinger::PlaybackThread::OutputTrack::clearBufferQueue()
4421{
4422 size_t size = mBufferQueue.size();
Mathias Agopian65ab4712010-07-14 17:59:35 -07004423
4424 for (size_t i = 0; i < size; i++) {
Glenn Kastena1117922012-01-26 10:53:32 -08004425 Buffer *pBuffer = mBufferQueue.itemAt(i);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004426 delete [] pBuffer->mBuffer;
4427 delete pBuffer;
4428 }
4429 mBufferQueue.clear();
4430}
4431
4432// ----------------------------------------------------------------------------
4433
4434AudioFlinger::Client::Client(const sp<AudioFlinger>& audioFlinger, pid_t pid)
4435 : RefBase(),
4436 mAudioFlinger(audioFlinger),
Glenn Kasten99e53b82012-01-19 08:59:58 -08004437 // FIXME should be a "k" constant not hard-coded, in .h or ro. property, see 4 lines below
Mathias Agopian65ab4712010-07-14 17:59:35 -07004438 mMemoryDealer(new MemoryDealer(1024*1024, "AudioFlinger::Client")),
John Grossman4ff14ba2012-02-08 16:37:41 -08004439 mPid(pid),
4440 mTimedTrackCount(0)
Mathias Agopian65ab4712010-07-14 17:59:35 -07004441{
4442 // 1 MB of address space is good for 32 tracks, 8 buffers each, 4 KB/buffer
4443}
4444
4445// Client destructor must be called with AudioFlinger::mLock held
4446AudioFlinger::Client::~Client()
4447{
4448 mAudioFlinger->removeClient_l(mPid);
4449}
4450
Glenn Kasten435dbe62012-01-30 10:15:48 -08004451sp<MemoryDealer> AudioFlinger::Client::heap() const
Mathias Agopian65ab4712010-07-14 17:59:35 -07004452{
4453 return mMemoryDealer;
4454}
4455
John Grossman4ff14ba2012-02-08 16:37:41 -08004456// Reserve one of the limited slots for a timed audio track associated
4457// with this client
4458bool AudioFlinger::Client::reserveTimedTrack()
4459{
4460 const int kMaxTimedTracksPerClient = 4;
4461
4462 Mutex::Autolock _l(mTimedTrackLock);
4463
4464 if (mTimedTrackCount >= kMaxTimedTracksPerClient) {
4465 ALOGW("can not create timed track - pid %d has exceeded the limit",
4466 mPid);
4467 return false;
4468 }
4469
4470 mTimedTrackCount++;
4471 return true;
4472}
4473
4474// Release a slot for a timed audio track
4475void AudioFlinger::Client::releaseTimedTrack()
4476{
4477 Mutex::Autolock _l(mTimedTrackLock);
4478 mTimedTrackCount--;
4479}
4480
Mathias Agopian65ab4712010-07-14 17:59:35 -07004481// ----------------------------------------------------------------------------
4482
4483AudioFlinger::NotificationClient::NotificationClient(const sp<AudioFlinger>& audioFlinger,
4484 const sp<IAudioFlingerClient>& client,
4485 pid_t pid)
Glenn Kasten84afa3b2012-01-25 15:28:08 -08004486 : mAudioFlinger(audioFlinger), mPid(pid), mAudioFlingerClient(client)
Mathias Agopian65ab4712010-07-14 17:59:35 -07004487{
4488}
4489
4490AudioFlinger::NotificationClient::~NotificationClient()
4491{
Mathias Agopian65ab4712010-07-14 17:59:35 -07004492}
4493
4494void AudioFlinger::NotificationClient::binderDied(const wp<IBinder>& who)
4495{
4496 sp<NotificationClient> keep(this);
Glenn Kastena1117922012-01-26 10:53:32 -08004497 mAudioFlinger->removeNotificationClient(mPid);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004498}
4499
4500// ----------------------------------------------------------------------------
4501
4502AudioFlinger::TrackHandle::TrackHandle(const sp<AudioFlinger::PlaybackThread::Track>& track)
4503 : BnAudioTrack(),
4504 mTrack(track)
4505{
4506}
4507
4508AudioFlinger::TrackHandle::~TrackHandle() {
4509 // just stop the track on deletion, associated resources
4510 // will be freed from the main thread once all pending buffers have
4511 // been played. Unless it's not in the active track list, in which
4512 // case we free everything now...
4513 mTrack->destroy();
4514}
4515
Glenn Kasten90716c52012-01-26 13:40:12 -08004516sp<IMemory> AudioFlinger::TrackHandle::getCblk() const {
4517 return mTrack->getCblk();
4518}
4519
Glenn Kasten6dbc1352012-02-02 10:56:47 -08004520status_t AudioFlinger::TrackHandle::start(pid_t tid) {
4521 return mTrack->start(tid);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004522}
4523
4524void AudioFlinger::TrackHandle::stop() {
4525 mTrack->stop();
4526}
4527
4528void AudioFlinger::TrackHandle::flush() {
4529 mTrack->flush();
4530}
4531
4532void AudioFlinger::TrackHandle::mute(bool e) {
4533 mTrack->mute(e);
4534}
4535
4536void AudioFlinger::TrackHandle::pause() {
4537 mTrack->pause();
4538}
4539
Mathias Agopian65ab4712010-07-14 17:59:35 -07004540status_t AudioFlinger::TrackHandle::attachAuxEffect(int EffectId)
4541{
4542 return mTrack->attachAuxEffect(EffectId);
4543}
4544
John Grossman4ff14ba2012-02-08 16:37:41 -08004545status_t AudioFlinger::TrackHandle::allocateTimedBuffer(size_t size,
4546 sp<IMemory>* buffer) {
4547 if (!mTrack->isTimedTrack())
4548 return INVALID_OPERATION;
4549
4550 PlaybackThread::TimedTrack* tt =
4551 reinterpret_cast<PlaybackThread::TimedTrack*>(mTrack.get());
4552 return tt->allocateTimedBuffer(size, buffer);
4553}
4554
4555status_t AudioFlinger::TrackHandle::queueTimedBuffer(const sp<IMemory>& buffer,
4556 int64_t pts) {
4557 if (!mTrack->isTimedTrack())
4558 return INVALID_OPERATION;
4559
4560 PlaybackThread::TimedTrack* tt =
4561 reinterpret_cast<PlaybackThread::TimedTrack*>(mTrack.get());
4562 return tt->queueTimedBuffer(buffer, pts);
4563}
4564
4565status_t AudioFlinger::TrackHandle::setMediaTimeTransform(
4566 const LinearTransform& xform, int target) {
4567
4568 if (!mTrack->isTimedTrack())
4569 return INVALID_OPERATION;
4570
4571 PlaybackThread::TimedTrack* tt =
4572 reinterpret_cast<PlaybackThread::TimedTrack*>(mTrack.get());
4573 return tt->setMediaTimeTransform(
4574 xform, static_cast<TimedAudioTrack::TargetTimeline>(target));
4575}
4576
Mathias Agopian65ab4712010-07-14 17:59:35 -07004577status_t AudioFlinger::TrackHandle::onTransact(
4578 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
4579{
4580 return BnAudioTrack::onTransact(code, data, reply, flags);
4581}
4582
4583// ----------------------------------------------------------------------------
4584
4585sp<IAudioRecord> AudioFlinger::openRecord(
4586 pid_t pid,
Glenn Kasten72ef00d2012-01-17 11:09:42 -08004587 audio_io_handle_t input,
Mathias Agopian65ab4712010-07-14 17:59:35 -07004588 uint32_t sampleRate,
Glenn Kasten58f30212012-01-12 12:27:51 -08004589 audio_format_t format,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07004590 uint32_t channelMask,
Mathias Agopian65ab4712010-07-14 17:59:35 -07004591 int frameCount,
Glenn Kasten5cf034d2012-02-21 10:35:56 -08004592 // FIXME dead, remove from IAudioFlinger
Mathias Agopian65ab4712010-07-14 17:59:35 -07004593 uint32_t flags,
4594 int *sessionId,
4595 status_t *status)
4596{
4597 sp<RecordThread::RecordTrack> recordTrack;
4598 sp<RecordHandle> recordHandle;
4599 sp<Client> client;
Mathias Agopian65ab4712010-07-14 17:59:35 -07004600 status_t lStatus;
4601 RecordThread *thread;
4602 size_t inFrameCount;
4603 int lSessionId;
4604
4605 // check calling permissions
4606 if (!recordingAllowed()) {
4607 lStatus = PERMISSION_DENIED;
4608 goto Exit;
4609 }
4610
4611 // add client to list
4612 { // scope for mLock
4613 Mutex::Autolock _l(mLock);
4614 thread = checkRecordThread_l(input);
4615 if (thread == NULL) {
4616 lStatus = BAD_VALUE;
4617 goto Exit;
4618 }
4619
Glenn Kasten98ec94c2012-01-25 14:28:29 -08004620 client = registerPid_l(pid);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004621
4622 // If no audio session id is provided, create one here
Dima Zavinfce7a472011-04-19 22:30:36 -07004623 if (sessionId != NULL && *sessionId != AUDIO_SESSION_OUTPUT_MIX) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07004624 lSessionId = *sessionId;
4625 } else {
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004626 lSessionId = nextUniqueId();
Mathias Agopian65ab4712010-07-14 17:59:35 -07004627 if (sessionId != NULL) {
4628 *sessionId = lSessionId;
4629 }
4630 }
4631 // create new record track. The record track uses one track in mHardwareMixerThread by convention.
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004632 recordTrack = thread->createRecordTrack_l(client,
4633 sampleRate,
4634 format,
4635 channelMask,
4636 frameCount,
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004637 lSessionId,
4638 &lStatus);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004639 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004640 if (lStatus != NO_ERROR) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07004641 // remove local strong reference to Client before deleting the RecordTrack so that the Client
4642 // destructor is called by the TrackBase destructor with mLock held
4643 client.clear();
4644 recordTrack.clear();
Mathias Agopian65ab4712010-07-14 17:59:35 -07004645 goto Exit;
4646 }
4647
4648 // return to handle to client
4649 recordHandle = new RecordHandle(recordTrack);
4650 lStatus = NO_ERROR;
4651
4652Exit:
4653 if (status) {
4654 *status = lStatus;
4655 }
4656 return recordHandle;
4657}
4658
4659// ----------------------------------------------------------------------------
4660
4661AudioFlinger::RecordHandle::RecordHandle(const sp<AudioFlinger::RecordThread::RecordTrack>& recordTrack)
4662 : BnAudioRecord(),
4663 mRecordTrack(recordTrack)
4664{
4665}
4666
4667AudioFlinger::RecordHandle::~RecordHandle() {
4668 stop();
4669}
4670
Glenn Kasten90716c52012-01-26 13:40:12 -08004671sp<IMemory> AudioFlinger::RecordHandle::getCblk() const {
4672 return mRecordTrack->getCblk();
4673}
4674
Glenn Kasten6dbc1352012-02-02 10:56:47 -08004675status_t AudioFlinger::RecordHandle::start(pid_t tid) {
Steve Block3856b092011-10-20 11:56:00 +01004676 ALOGV("RecordHandle::start()");
Glenn Kasten6dbc1352012-02-02 10:56:47 -08004677 return mRecordTrack->start(tid);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004678}
4679
4680void AudioFlinger::RecordHandle::stop() {
Steve Block3856b092011-10-20 11:56:00 +01004681 ALOGV("RecordHandle::stop()");
Mathias Agopian65ab4712010-07-14 17:59:35 -07004682 mRecordTrack->stop();
4683}
4684
Mathias Agopian65ab4712010-07-14 17:59:35 -07004685status_t AudioFlinger::RecordHandle::onTransact(
4686 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
4687{
4688 return BnAudioRecord::onTransact(code, data, reply, flags);
4689}
4690
4691// ----------------------------------------------------------------------------
4692
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004693AudioFlinger::RecordThread::RecordThread(const sp<AudioFlinger>& audioFlinger,
4694 AudioStreamIn *input,
4695 uint32_t sampleRate,
4696 uint32_t channels,
Glenn Kasten72ef00d2012-01-17 11:09:42 -08004697 audio_io_handle_t id,
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004698 uint32_t device) :
Glenn Kasten23bb8be2012-01-26 10:38:26 -08004699 ThreadBase(audioFlinger, id, device, RECORD),
Glenn Kasten84afa3b2012-01-25 15:28:08 -08004700 mInput(input), mTrack(NULL), mResampler(NULL), mRsmpOutBuffer(NULL), mRsmpInBuffer(NULL),
4701 // mRsmpInIndex and mInputBytes set by readInputParameters()
4702 mReqChannelCount(popcount(channels)),
4703 mReqSampleRate(sampleRate)
4704 // mBytesRead is only meaningful while active, and so is cleared in start()
4705 // (but might be better to also clear here for dump?)
Mathias Agopian65ab4712010-07-14 17:59:35 -07004706{
Glenn Kasten480b4682012-02-28 12:30:08 -08004707 snprintf(mName, kNameLength, "AudioIn_%X", id);
Eric Laurentfeb0db62011-07-22 09:04:31 -07004708
Mathias Agopian65ab4712010-07-14 17:59:35 -07004709 readInputParameters();
4710}
4711
4712
4713AudioFlinger::RecordThread::~RecordThread()
4714{
4715 delete[] mRsmpInBuffer;
Glenn Kastene9dd0172012-01-27 18:08:45 -08004716 delete mResampler;
4717 delete[] mRsmpOutBuffer;
Mathias Agopian65ab4712010-07-14 17:59:35 -07004718}
4719
4720void AudioFlinger::RecordThread::onFirstRef()
4721{
Eric Laurentfeb0db62011-07-22 09:04:31 -07004722 run(mName, PRIORITY_URGENT_AUDIO);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004723}
4724
Eric Laurentb8ba0a92011-08-07 16:32:26 -07004725status_t AudioFlinger::RecordThread::readyToRun()
4726{
4727 status_t status = initCheck();
Steve Block5ff1dd52012-01-05 23:22:43 +00004728 ALOGW_IF(status != NO_ERROR,"RecordThread %p could not initialize", this);
Eric Laurentb8ba0a92011-08-07 16:32:26 -07004729 return status;
4730}
4731
Mathias Agopian65ab4712010-07-14 17:59:35 -07004732bool AudioFlinger::RecordThread::threadLoop()
4733{
4734 AudioBufferProvider::Buffer buffer;
4735 sp<RecordTrack> activeTrack;
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004736 Vector< sp<EffectChain> > effectChains;
Mathias Agopian65ab4712010-07-14 17:59:35 -07004737
Eric Laurent44d98482010-09-30 16:12:31 -07004738 nsecs_t lastWarning = 0;
4739
Eric Laurentfeb0db62011-07-22 09:04:31 -07004740 acquireWakeLock();
4741
Mathias Agopian65ab4712010-07-14 17:59:35 -07004742 // start recording
4743 while (!exitPending()) {
4744
4745 processConfigEvents();
4746
4747 { // scope for mLock
4748 Mutex::Autolock _l(mLock);
4749 checkForNewParameters_l();
4750 if (mActiveTrack == 0 && mConfigEvents.isEmpty()) {
4751 if (!mStandby) {
Dima Zavin799a70e2011-04-18 16:57:27 -07004752 mInput->stream->common.standby(&mInput->stream->common);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004753 mStandby = true;
4754 }
4755
4756 if (exitPending()) break;
4757
Eric Laurentfeb0db62011-07-22 09:04:31 -07004758 releaseWakeLock_l();
Steve Block3856b092011-10-20 11:56:00 +01004759 ALOGV("RecordThread: loop stopping");
Mathias Agopian65ab4712010-07-14 17:59:35 -07004760 // go to sleep
4761 mWaitWorkCV.wait(mLock);
Steve Block3856b092011-10-20 11:56:00 +01004762 ALOGV("RecordThread: loop starting");
Eric Laurentfeb0db62011-07-22 09:04:31 -07004763 acquireWakeLock_l();
Mathias Agopian65ab4712010-07-14 17:59:35 -07004764 continue;
4765 }
4766 if (mActiveTrack != 0) {
4767 if (mActiveTrack->mState == TrackBase::PAUSING) {
4768 if (!mStandby) {
Dima Zavin799a70e2011-04-18 16:57:27 -07004769 mInput->stream->common.standby(&mInput->stream->common);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004770 mStandby = true;
4771 }
4772 mActiveTrack.clear();
4773 mStartStopCond.broadcast();
4774 } else if (mActiveTrack->mState == TrackBase::RESUMING) {
4775 if (mReqChannelCount != mActiveTrack->channelCount()) {
4776 mActiveTrack.clear();
4777 mStartStopCond.broadcast();
4778 } else if (mBytesRead != 0) {
4779 // record start succeeds only if first read from audio input
4780 // succeeds
4781 if (mBytesRead > 0) {
4782 mActiveTrack->mState = TrackBase::ACTIVE;
4783 } else {
4784 mActiveTrack.clear();
4785 }
4786 mStartStopCond.broadcast();
4787 }
4788 mStandby = false;
4789 }
4790 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004791 lockEffectChains_l(effectChains);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004792 }
4793
4794 if (mActiveTrack != 0) {
4795 if (mActiveTrack->mState != TrackBase::ACTIVE &&
4796 mActiveTrack->mState != TrackBase::RESUMING) {
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004797 unlockEffectChains(effectChains);
4798 usleep(kRecordThreadSleepUs);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004799 continue;
4800 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004801 for (size_t i = 0; i < effectChains.size(); i ++) {
4802 effectChains[i]->process_l();
4803 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004804
Mathias Agopian65ab4712010-07-14 17:59:35 -07004805 buffer.frameCount = mFrameCount;
Glenn Kasten01c4ebf2012-02-22 10:47:35 -08004806 if (CC_LIKELY(mActiveTrack->getNextBuffer(&buffer) == NO_ERROR)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07004807 size_t framesOut = buffer.frameCount;
Glenn Kastene0feee32011-12-13 11:53:26 -08004808 if (mResampler == NULL) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07004809 // no resampling
4810 while (framesOut) {
4811 size_t framesIn = mFrameCount - mRsmpInIndex;
4812 if (framesIn) {
4813 int8_t *src = (int8_t *)mRsmpInBuffer + mRsmpInIndex * mFrameSize;
4814 int8_t *dst = buffer.i8 + (buffer.frameCount - framesOut) * mActiveTrack->mCblk->frameSize;
4815 if (framesIn > framesOut)
4816 framesIn = framesOut;
4817 mRsmpInIndex += framesIn;
4818 framesOut -= framesIn;
4819 if ((int)mChannelCount == mReqChannelCount ||
Dima Zavinfce7a472011-04-19 22:30:36 -07004820 mFormat != AUDIO_FORMAT_PCM_16_BIT) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07004821 memcpy(dst, src, framesIn * mFrameSize);
4822 } else {
4823 int16_t *src16 = (int16_t *)src;
4824 int16_t *dst16 = (int16_t *)dst;
4825 if (mChannelCount == 1) {
4826 while (framesIn--) {
4827 *dst16++ = *src16;
4828 *dst16++ = *src16++;
4829 }
4830 } else {
4831 while (framesIn--) {
4832 *dst16++ = (int16_t)(((int32_t)*src16 + (int32_t)*(src16 + 1)) >> 1);
4833 src16 += 2;
4834 }
4835 }
4836 }
4837 }
4838 if (framesOut && mFrameCount == mRsmpInIndex) {
4839 if (framesOut == mFrameCount &&
Dima Zavinfce7a472011-04-19 22:30:36 -07004840 ((int)mChannelCount == mReqChannelCount || mFormat != AUDIO_FORMAT_PCM_16_BIT)) {
Dima Zavin799a70e2011-04-18 16:57:27 -07004841 mBytesRead = mInput->stream->read(mInput->stream, buffer.raw, mInputBytes);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004842 framesOut = 0;
4843 } else {
Dima Zavin799a70e2011-04-18 16:57:27 -07004844 mBytesRead = mInput->stream->read(mInput->stream, mRsmpInBuffer, mInputBytes);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004845 mRsmpInIndex = 0;
4846 }
4847 if (mBytesRead < 0) {
Steve Block29357bc2012-01-06 19:20:56 +00004848 ALOGE("Error reading audio input");
Mathias Agopian65ab4712010-07-14 17:59:35 -07004849 if (mActiveTrack->mState == TrackBase::ACTIVE) {
4850 // Force input into standby so that it tries to
4851 // recover at next read attempt
Dima Zavin799a70e2011-04-18 16:57:27 -07004852 mInput->stream->common.standby(&mInput->stream->common);
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004853 usleep(kRecordThreadSleepUs);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004854 }
4855 mRsmpInIndex = mFrameCount;
4856 framesOut = 0;
4857 buffer.frameCount = 0;
4858 }
4859 }
4860 }
4861 } else {
4862 // resampling
4863
4864 memset(mRsmpOutBuffer, 0, framesOut * 2 * sizeof(int32_t));
4865 // alter output frame count as if we were expecting stereo samples
4866 if (mChannelCount == 1 && mReqChannelCount == 1) {
4867 framesOut >>= 1;
4868 }
4869 mResampler->resample(mRsmpOutBuffer, framesOut, this);
4870 // ditherAndClamp() works as long as all buffers returned by mActiveTrack->getNextBuffer()
4871 // are 32 bit aligned which should be always true.
4872 if (mChannelCount == 2 && mReqChannelCount == 1) {
Glenn Kasten3b21c502011-12-15 09:52:39 -08004873 ditherAndClamp(mRsmpOutBuffer, mRsmpOutBuffer, framesOut);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004874 // the resampler always outputs stereo samples: do post stereo to mono conversion
4875 int16_t *src = (int16_t *)mRsmpOutBuffer;
4876 int16_t *dst = buffer.i16;
4877 while (framesOut--) {
4878 *dst++ = (int16_t)(((int32_t)*src + (int32_t)*(src + 1)) >> 1);
4879 src += 2;
4880 }
4881 } else {
Glenn Kasten3b21c502011-12-15 09:52:39 -08004882 ditherAndClamp((int32_t *)buffer.raw, mRsmpOutBuffer, framesOut);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004883 }
4884
4885 }
4886 mActiveTrack->releaseBuffer(&buffer);
4887 mActiveTrack->overflow();
4888 }
4889 // client isn't retrieving buffers fast enough
4890 else {
Eric Laurent44d98482010-09-30 16:12:31 -07004891 if (!mActiveTrack->setOverflow()) {
4892 nsecs_t now = systemTime();
Glenn Kasten7dede872011-12-13 11:04:14 -08004893 if ((now - lastWarning) > kWarningThrottleNs) {
Steve Block5ff1dd52012-01-05 23:22:43 +00004894 ALOGW("RecordThread: buffer overflow");
Eric Laurent44d98482010-09-30 16:12:31 -07004895 lastWarning = now;
4896 }
4897 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07004898 // Release the processor for a while before asking for a new buffer.
4899 // This will give the application more chance to read from the buffer and
4900 // clear the overflow.
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004901 usleep(kRecordThreadSleepUs);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004902 }
4903 }
Eric Laurentec437d82011-07-26 20:54:46 -07004904 // enable changes in effect chain
4905 unlockEffectChains(effectChains);
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004906 effectChains.clear();
Mathias Agopian65ab4712010-07-14 17:59:35 -07004907 }
4908
4909 if (!mStandby) {
Dima Zavin799a70e2011-04-18 16:57:27 -07004910 mInput->stream->common.standby(&mInput->stream->common);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004911 }
4912 mActiveTrack.clear();
4913
4914 mStartStopCond.broadcast();
4915
Eric Laurentfeb0db62011-07-22 09:04:31 -07004916 releaseWakeLock();
4917
Steve Block3856b092011-10-20 11:56:00 +01004918 ALOGV("RecordThread %p exiting", this);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004919 return false;
4920}
4921
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004922
4923sp<AudioFlinger::RecordThread::RecordTrack> AudioFlinger::RecordThread::createRecordTrack_l(
4924 const sp<AudioFlinger::Client>& client,
4925 uint32_t sampleRate,
Glenn Kasten58f30212012-01-12 12:27:51 -08004926 audio_format_t format,
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004927 int channelMask,
4928 int frameCount,
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004929 int sessionId,
4930 status_t *status)
4931{
4932 sp<RecordTrack> track;
4933 status_t lStatus;
4934
4935 lStatus = initCheck();
4936 if (lStatus != NO_ERROR) {
Steve Block29357bc2012-01-06 19:20:56 +00004937 ALOGE("Audio driver not initialized.");
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004938 goto Exit;
4939 }
4940
4941 { // scope for mLock
4942 Mutex::Autolock _l(mLock);
4943
4944 track = new RecordTrack(this, client, sampleRate,
Glenn Kasten5cf034d2012-02-21 10:35:56 -08004945 format, channelMask, frameCount, sessionId);
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004946
Glenn Kasten7378ca52012-01-20 13:44:40 -08004947 if (track->getCblk() == 0) {
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004948 lStatus = NO_MEMORY;
4949 goto Exit;
4950 }
4951
4952 mTrack = track.get();
Eric Laurent59bd0da2011-08-01 09:52:20 -07004953 // disable AEC and NS if the device is a BT SCO headset supporting those pre processings
4954 bool suspend = audio_is_bluetooth_sco_device(
Eric Laurentbee53372011-08-29 12:42:48 -07004955 (audio_devices_t)(mDevice & AUDIO_DEVICE_IN_ALL)) && mAudioFlinger->btNrecIsOff();
Eric Laurent59bd0da2011-08-01 09:52:20 -07004956 setEffectSuspended_l(FX_IID_AEC, suspend, sessionId);
4957 setEffectSuspended_l(FX_IID_NS, suspend, sessionId);
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004958 }
4959 lStatus = NO_ERROR;
4960
4961Exit:
4962 if (status) {
4963 *status = lStatus;
4964 }
4965 return track;
4966}
4967
Glenn Kasten6dbc1352012-02-02 10:56:47 -08004968status_t AudioFlinger::RecordThread::start(RecordThread::RecordTrack* recordTrack, pid_t tid)
Mathias Agopian65ab4712010-07-14 17:59:35 -07004969{
Glenn Kasten6dbc1352012-02-02 10:56:47 -08004970 ALOGV("RecordThread::start tid=%d", tid);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004971 sp <ThreadBase> strongMe = this;
4972 status_t status = NO_ERROR;
4973 {
Glenn Kastena7d8d6f2012-01-05 15:41:56 -08004974 AutoMutex lock(mLock);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004975 if (mActiveTrack != 0) {
4976 if (recordTrack != mActiveTrack.get()) {
4977 status = -EBUSY;
4978 } else if (mActiveTrack->mState == TrackBase::PAUSING) {
4979 mActiveTrack->mState = TrackBase::ACTIVE;
4980 }
4981 return status;
4982 }
4983
4984 recordTrack->mState = TrackBase::IDLE;
4985 mActiveTrack = recordTrack;
4986 mLock.unlock();
4987 status_t status = AudioSystem::startInput(mId);
4988 mLock.lock();
4989 if (status != NO_ERROR) {
4990 mActiveTrack.clear();
4991 return status;
4992 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07004993 mRsmpInIndex = mFrameCount;
4994 mBytesRead = 0;
Eric Laurent243f5f92011-02-28 16:52:51 -08004995 if (mResampler != NULL) {
4996 mResampler->reset();
4997 }
4998 mActiveTrack->mState = TrackBase::RESUMING;
Mathias Agopian65ab4712010-07-14 17:59:35 -07004999 // signal thread to start
Steve Block3856b092011-10-20 11:56:00 +01005000 ALOGV("Signal record thread");
Mathias Agopian65ab4712010-07-14 17:59:35 -07005001 mWaitWorkCV.signal();
5002 // do not wait for mStartStopCond if exiting
Glenn Kastenb28686f2012-01-06 08:39:38 -08005003 if (exitPending()) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07005004 mActiveTrack.clear();
5005 status = INVALID_OPERATION;
5006 goto startError;
5007 }
5008 mStartStopCond.wait(mLock);
5009 if (mActiveTrack == 0) {
Steve Block3856b092011-10-20 11:56:00 +01005010 ALOGV("Record failed to start");
Mathias Agopian65ab4712010-07-14 17:59:35 -07005011 status = BAD_VALUE;
5012 goto startError;
5013 }
Steve Block3856b092011-10-20 11:56:00 +01005014 ALOGV("Record started OK");
Mathias Agopian65ab4712010-07-14 17:59:35 -07005015 return status;
5016 }
5017startError:
5018 AudioSystem::stopInput(mId);
5019 return status;
5020}
5021
5022void AudioFlinger::RecordThread::stop(RecordThread::RecordTrack* recordTrack) {
Steve Block3856b092011-10-20 11:56:00 +01005023 ALOGV("RecordThread::stop");
Mathias Agopian65ab4712010-07-14 17:59:35 -07005024 sp <ThreadBase> strongMe = this;
5025 {
Glenn Kastena7d8d6f2012-01-05 15:41:56 -08005026 AutoMutex lock(mLock);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005027 if (mActiveTrack != 0 && recordTrack == mActiveTrack.get()) {
5028 mActiveTrack->mState = TrackBase::PAUSING;
5029 // do not wait for mStartStopCond if exiting
Glenn Kastenb28686f2012-01-06 08:39:38 -08005030 if (exitPending()) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07005031 return;
5032 }
5033 mStartStopCond.wait(mLock);
5034 // if we have been restarted, recordTrack == mActiveTrack.get() here
5035 if (mActiveTrack == 0 || recordTrack != mActiveTrack.get()) {
5036 mLock.unlock();
5037 AudioSystem::stopInput(mId);
5038 mLock.lock();
Steve Block3856b092011-10-20 11:56:00 +01005039 ALOGV("Record stopped OK");
Mathias Agopian65ab4712010-07-14 17:59:35 -07005040 }
5041 }
5042 }
5043}
5044
5045status_t AudioFlinger::RecordThread::dump(int fd, const Vector<String16>& args)
5046{
5047 const size_t SIZE = 256;
5048 char buffer[SIZE];
5049 String8 result;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005050
5051 snprintf(buffer, SIZE, "\nInput thread %p internals\n", this);
5052 result.append(buffer);
5053
5054 if (mActiveTrack != 0) {
5055 result.append("Active Track:\n");
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07005056 result.append(" Clien Fmt Chn mask Session Buf S SRate Serv User\n");
Mathias Agopian65ab4712010-07-14 17:59:35 -07005057 mActiveTrack->dump(buffer, SIZE);
5058 result.append(buffer);
5059
5060 snprintf(buffer, SIZE, "In index: %d\n", mRsmpInIndex);
5061 result.append(buffer);
5062 snprintf(buffer, SIZE, "In size: %d\n", mInputBytes);
5063 result.append(buffer);
Glenn Kastene0feee32011-12-13 11:53:26 -08005064 snprintf(buffer, SIZE, "Resampling: %d\n", (mResampler != NULL));
Mathias Agopian65ab4712010-07-14 17:59:35 -07005065 result.append(buffer);
5066 snprintf(buffer, SIZE, "Out channel count: %d\n", mReqChannelCount);
5067 result.append(buffer);
5068 snprintf(buffer, SIZE, "Out sample rate: %d\n", mReqSampleRate);
5069 result.append(buffer);
5070
5071
5072 } else {
5073 result.append("No record client\n");
5074 }
5075 write(fd, result.string(), result.size());
5076
5077 dumpBase(fd, args);
Eric Laurent1d2bff02011-07-24 17:49:51 -07005078 dumpEffectChains(fd, args);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005079
5080 return NO_ERROR;
5081}
5082
Glenn Kasten01c4ebf2012-02-22 10:47:35 -08005083// AudioBufferProvider interface
John Grossman4ff14ba2012-02-08 16:37:41 -08005084status_t AudioFlinger::RecordThread::getNextBuffer(AudioBufferProvider::Buffer* buffer, int64_t pts)
Mathias Agopian65ab4712010-07-14 17:59:35 -07005085{
5086 size_t framesReq = buffer->frameCount;
5087 size_t framesReady = mFrameCount - mRsmpInIndex;
5088 int channelCount;
5089
5090 if (framesReady == 0) {
Dima Zavin799a70e2011-04-18 16:57:27 -07005091 mBytesRead = mInput->stream->read(mInput->stream, mRsmpInBuffer, mInputBytes);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005092 if (mBytesRead < 0) {
Steve Block29357bc2012-01-06 19:20:56 +00005093 ALOGE("RecordThread::getNextBuffer() Error reading audio input");
Mathias Agopian65ab4712010-07-14 17:59:35 -07005094 if (mActiveTrack->mState == TrackBase::ACTIVE) {
5095 // Force input into standby so that it tries to
5096 // recover at next read attempt
Dima Zavin799a70e2011-04-18 16:57:27 -07005097 mInput->stream->common.standby(&mInput->stream->common);
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005098 usleep(kRecordThreadSleepUs);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005099 }
Glenn Kastene0feee32011-12-13 11:53:26 -08005100 buffer->raw = NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005101 buffer->frameCount = 0;
5102 return NOT_ENOUGH_DATA;
5103 }
5104 mRsmpInIndex = 0;
5105 framesReady = mFrameCount;
5106 }
5107
5108 if (framesReq > framesReady) {
5109 framesReq = framesReady;
5110 }
5111
5112 if (mChannelCount == 1 && mReqChannelCount == 2) {
5113 channelCount = 1;
5114 } else {
5115 channelCount = 2;
5116 }
5117 buffer->raw = mRsmpInBuffer + mRsmpInIndex * channelCount;
5118 buffer->frameCount = framesReq;
5119 return NO_ERROR;
5120}
5121
Glenn Kasten01c4ebf2012-02-22 10:47:35 -08005122// AudioBufferProvider interface
Mathias Agopian65ab4712010-07-14 17:59:35 -07005123void AudioFlinger::RecordThread::releaseBuffer(AudioBufferProvider::Buffer* buffer)
5124{
5125 mRsmpInIndex += buffer->frameCount;
5126 buffer->frameCount = 0;
5127}
5128
5129bool AudioFlinger::RecordThread::checkForNewParameters_l()
5130{
5131 bool reconfig = false;
5132
5133 while (!mNewParameters.isEmpty()) {
5134 status_t status = NO_ERROR;
5135 String8 keyValuePair = mNewParameters[0];
5136 AudioParameter param = AudioParameter(keyValuePair);
5137 int value;
Glenn Kasten58f30212012-01-12 12:27:51 -08005138 audio_format_t reqFormat = mFormat;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005139 int reqSamplingRate = mReqSampleRate;
5140 int reqChannelCount = mReqChannelCount;
5141
5142 if (param.getInt(String8(AudioParameter::keySamplingRate), value) == NO_ERROR) {
5143 reqSamplingRate = value;
5144 reconfig = true;
5145 }
5146 if (param.getInt(String8(AudioParameter::keyFormat), value) == NO_ERROR) {
Glenn Kasten58f30212012-01-12 12:27:51 -08005147 reqFormat = (audio_format_t) value;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005148 reconfig = true;
5149 }
5150 if (param.getInt(String8(AudioParameter::keyChannels), value) == NO_ERROR) {
Dima Zavinfce7a472011-04-19 22:30:36 -07005151 reqChannelCount = popcount(value);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005152 reconfig = true;
5153 }
5154 if (param.getInt(String8(AudioParameter::keyFrameCount), value) == NO_ERROR) {
5155 // do not accept frame count changes if tracks are open as the track buffer
Glenn Kasten99e53b82012-01-19 08:59:58 -08005156 // size depends on frame count and correct behavior would not be guaranteed
Mathias Agopian65ab4712010-07-14 17:59:35 -07005157 // if frame count is changed after track creation
5158 if (mActiveTrack != 0) {
5159 status = INVALID_OPERATION;
5160 } else {
5161 reconfig = true;
5162 }
5163 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005164 if (param.getInt(String8(AudioParameter::keyRouting), value) == NO_ERROR) {
5165 // forward device change to effects that have requested to be
5166 // aware of attached audio device.
5167 for (size_t i = 0; i < mEffectChains.size(); i++) {
5168 mEffectChains[i]->setDevice_l(value);
5169 }
5170 // store input device and output device but do not forward output device to audio HAL.
5171 // Note that status is ignored by the caller for output device
5172 // (see AudioFlinger::setParameters()
5173 if (value & AUDIO_DEVICE_OUT_ALL) {
5174 mDevice &= (uint32_t)~(value & AUDIO_DEVICE_OUT_ALL);
5175 status = BAD_VALUE;
5176 } else {
5177 mDevice &= (uint32_t)~(value & AUDIO_DEVICE_IN_ALL);
Eric Laurent59bd0da2011-08-01 09:52:20 -07005178 // disable AEC and NS if the device is a BT SCO headset supporting those pre processings
5179 if (mTrack != NULL) {
5180 bool suspend = audio_is_bluetooth_sco_device(
Eric Laurentbee53372011-08-29 12:42:48 -07005181 (audio_devices_t)value) && mAudioFlinger->btNrecIsOff();
Eric Laurent59bd0da2011-08-01 09:52:20 -07005182 setEffectSuspended_l(FX_IID_AEC, suspend, mTrack->sessionId());
5183 setEffectSuspended_l(FX_IID_NS, suspend, mTrack->sessionId());
5184 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005185 }
5186 mDevice |= (uint32_t)value;
5187 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07005188 if (status == NO_ERROR) {
Dima Zavin799a70e2011-04-18 16:57:27 -07005189 status = mInput->stream->common.set_parameters(&mInput->stream->common, keyValuePair.string());
Mathias Agopian65ab4712010-07-14 17:59:35 -07005190 if (status == INVALID_OPERATION) {
Dima Zavin799a70e2011-04-18 16:57:27 -07005191 mInput->stream->common.standby(&mInput->stream->common);
5192 status = mInput->stream->common.set_parameters(&mInput->stream->common, keyValuePair.string());
Mathias Agopian65ab4712010-07-14 17:59:35 -07005193 }
5194 if (reconfig) {
5195 if (status == BAD_VALUE &&
Dima Zavin799a70e2011-04-18 16:57:27 -07005196 reqFormat == mInput->stream->common.get_format(&mInput->stream->common) &&
Dima Zavinfce7a472011-04-19 22:30:36 -07005197 reqFormat == AUDIO_FORMAT_PCM_16_BIT &&
Dima Zavin799a70e2011-04-18 16:57:27 -07005198 ((int)mInput->stream->common.get_sample_rate(&mInput->stream->common) <= (2 * reqSamplingRate)) &&
5199 (popcount(mInput->stream->common.get_channels(&mInput->stream->common)) < 3) &&
Dima Zavinfce7a472011-04-19 22:30:36 -07005200 (reqChannelCount < 3)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07005201 status = NO_ERROR;
5202 }
5203 if (status == NO_ERROR) {
5204 readInputParameters();
5205 sendConfigEvent_l(AudioSystem::INPUT_CONFIG_CHANGED);
5206 }
5207 }
5208 }
5209
5210 mNewParameters.removeAt(0);
5211
5212 mParamStatus = status;
5213 mParamCond.signal();
Eric Laurent60cd0a02011-09-13 11:40:21 -07005214 // wait for condition with time out in case the thread calling ThreadBase::setParameters()
5215 // already timed out waiting for the status and will never signal the condition.
Glenn Kasten7dede872011-12-13 11:04:14 -08005216 mWaitWorkCV.waitRelative(mLock, kSetParametersTimeoutNs);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005217 }
5218 return reconfig;
5219}
5220
5221String8 AudioFlinger::RecordThread::getParameters(const String8& keys)
5222{
Dima Zavinfce7a472011-04-19 22:30:36 -07005223 char *s;
Eric Laurentb8ba0a92011-08-07 16:32:26 -07005224 String8 out_s8 = String8();
5225
5226 Mutex::Autolock _l(mLock);
5227 if (initCheck() != NO_ERROR) {
5228 return out_s8;
5229 }
Dima Zavinfce7a472011-04-19 22:30:36 -07005230
Dima Zavin799a70e2011-04-18 16:57:27 -07005231 s = mInput->stream->common.get_parameters(&mInput->stream->common, keys.string());
Dima Zavinfce7a472011-04-19 22:30:36 -07005232 out_s8 = String8(s);
5233 free(s);
5234 return out_s8;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005235}
5236
5237void AudioFlinger::RecordThread::audioConfigChanged_l(int event, int param) {
5238 AudioSystem::OutputDescriptor desc;
Glenn Kastena0d68332012-01-27 16:47:15 -08005239 void *param2 = NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005240
5241 switch (event) {
5242 case AudioSystem::INPUT_OPENED:
5243 case AudioSystem::INPUT_CONFIG_CHANGED:
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07005244 desc.channels = mChannelMask;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005245 desc.samplingRate = mSampleRate;
5246 desc.format = mFormat;
5247 desc.frameCount = mFrameCount;
5248 desc.latency = 0;
5249 param2 = &desc;
5250 break;
5251
5252 case AudioSystem::INPUT_CLOSED:
5253 default:
5254 break;
5255 }
5256 mAudioFlinger->audioConfigChanged_l(event, mId, param2);
5257}
5258
5259void AudioFlinger::RecordThread::readInputParameters()
5260{
Glenn Kastene9dd0172012-01-27 18:08:45 -08005261 delete mRsmpInBuffer;
5262 // mRsmpInBuffer is always assigned a new[] below
5263 delete mRsmpOutBuffer;
5264 mRsmpOutBuffer = NULL;
5265 delete mResampler;
Glenn Kastene0feee32011-12-13 11:53:26 -08005266 mResampler = NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005267
Dima Zavin799a70e2011-04-18 16:57:27 -07005268 mSampleRate = mInput->stream->common.get_sample_rate(&mInput->stream->common);
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07005269 mChannelMask = mInput->stream->common.get_channels(&mInput->stream->common);
5270 mChannelCount = (uint16_t)popcount(mChannelMask);
Dima Zavin799a70e2011-04-18 16:57:27 -07005271 mFormat = mInput->stream->common.get_format(&mInput->stream->common);
Glenn Kastenb9980652012-01-11 09:48:27 -08005272 mFrameSize = audio_stream_frame_size(&mInput->stream->common);
Dima Zavin799a70e2011-04-18 16:57:27 -07005273 mInputBytes = mInput->stream->common.get_buffer_size(&mInput->stream->common);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005274 mFrameCount = mInputBytes / mFrameSize;
5275 mRsmpInBuffer = new int16_t[mFrameCount * mChannelCount];
5276
5277 if (mSampleRate != mReqSampleRate && mChannelCount < 3 && mReqChannelCount < 3)
5278 {
5279 int channelCount;
5280 // optmization: if mono to mono, use the resampler in stereo to stereo mode to avoid
5281 // stereo to mono post process as the resampler always outputs stereo.
5282 if (mChannelCount == 1 && mReqChannelCount == 2) {
5283 channelCount = 1;
5284 } else {
5285 channelCount = 2;
5286 }
5287 mResampler = AudioResampler::create(16, channelCount, mReqSampleRate);
5288 mResampler->setSampleRate(mSampleRate);
5289 mResampler->setVolume(AudioMixer::UNITY_GAIN, AudioMixer::UNITY_GAIN);
5290 mRsmpOutBuffer = new int32_t[mFrameCount * 2];
5291
5292 // optmization: if mono to mono, alter input frame count as if we were inputing stereo samples
5293 if (mChannelCount == 1 && mReqChannelCount == 1) {
5294 mFrameCount >>= 1;
5295 }
5296
5297 }
5298 mRsmpInIndex = mFrameCount;
5299}
5300
5301unsigned int AudioFlinger::RecordThread::getInputFramesLost()
5302{
Eric Laurentb8ba0a92011-08-07 16:32:26 -07005303 Mutex::Autolock _l(mLock);
5304 if (initCheck() != NO_ERROR) {
5305 return 0;
5306 }
5307
Dima Zavin799a70e2011-04-18 16:57:27 -07005308 return mInput->stream->get_input_frames_lost(mInput->stream);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005309}
5310
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005311uint32_t AudioFlinger::RecordThread::hasAudioSession(int sessionId)
5312{
5313 Mutex::Autolock _l(mLock);
5314 uint32_t result = 0;
5315 if (getEffectChain_l(sessionId) != 0) {
5316 result = EFFECT_SESSION;
5317 }
5318
5319 if (mTrack != NULL && sessionId == mTrack->sessionId()) {
5320 result |= TRACK_SESSION;
5321 }
5322
5323 return result;
5324}
5325
Eric Laurent59bd0da2011-08-01 09:52:20 -07005326AudioFlinger::RecordThread::RecordTrack* AudioFlinger::RecordThread::track()
5327{
5328 Mutex::Autolock _l(mLock);
5329 return mTrack;
5330}
5331
Glenn Kastenaed850d2012-01-26 09:46:34 -08005332AudioFlinger::AudioStreamIn* AudioFlinger::RecordThread::getInput() const
Eric Laurentb8ba0a92011-08-07 16:32:26 -07005333{
5334 Mutex::Autolock _l(mLock);
5335 return mInput;
5336}
5337
5338AudioFlinger::AudioStreamIn* AudioFlinger::RecordThread::clearInput()
5339{
5340 Mutex::Autolock _l(mLock);
5341 AudioStreamIn *input = mInput;
5342 mInput = NULL;
5343 return input;
5344}
5345
5346// this method must always be called either with ThreadBase mLock held or inside the thread loop
5347audio_stream_t* AudioFlinger::RecordThread::stream()
5348{
5349 if (mInput == NULL) {
5350 return NULL;
5351 }
5352 return &mInput->stream->common;
5353}
5354
5355
Mathias Agopian65ab4712010-07-14 17:59:35 -07005356// ----------------------------------------------------------------------------
5357
Glenn Kasten72ef00d2012-01-17 11:09:42 -08005358audio_io_handle_t AudioFlinger::openOutput(uint32_t *pDevices,
Mathias Agopian65ab4712010-07-14 17:59:35 -07005359 uint32_t *pSamplingRate,
Glenn Kasten58f30212012-01-12 12:27:51 -08005360 audio_format_t *pFormat,
Mathias Agopian65ab4712010-07-14 17:59:35 -07005361 uint32_t *pChannels,
5362 uint32_t *pLatencyMs,
5363 uint32_t flags)
5364{
5365 status_t status;
5366 PlaybackThread *thread = NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005367 uint32_t samplingRate = pSamplingRate ? *pSamplingRate : 0;
Glenn Kasten58f30212012-01-12 12:27:51 -08005368 audio_format_t format = pFormat ? *pFormat : AUDIO_FORMAT_DEFAULT;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005369 uint32_t channels = pChannels ? *pChannels : 0;
5370 uint32_t latency = pLatencyMs ? *pLatencyMs : 0;
Dima Zavin799a70e2011-04-18 16:57:27 -07005371 audio_stream_out_t *outStream;
5372 audio_hw_device_t *outHwDev;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005373
Steve Block3856b092011-10-20 11:56:00 +01005374 ALOGV("openOutput(), Device %x, SamplingRate %d, Format %d, Channels %x, flags %x",
Mathias Agopian65ab4712010-07-14 17:59:35 -07005375 pDevices ? *pDevices : 0,
5376 samplingRate,
5377 format,
5378 channels,
5379 flags);
5380
5381 if (pDevices == NULL || *pDevices == 0) {
5382 return 0;
5383 }
Dima Zavin799a70e2011-04-18 16:57:27 -07005384
Mathias Agopian65ab4712010-07-14 17:59:35 -07005385 Mutex::Autolock _l(mLock);
5386
Dima Zavin799a70e2011-04-18 16:57:27 -07005387 outHwDev = findSuitableHwDev_l(*pDevices);
5388 if (outHwDev == NULL)
5389 return 0;
5390
Glenn Kasten8abf44d2012-02-02 14:16:03 -08005391 mHardwareStatus = AUDIO_HW_OUTPUT_OPEN;
Glenn Kasten58f30212012-01-12 12:27:51 -08005392 status = outHwDev->open_output_stream(outHwDev, *pDevices, &format,
Dima Zavin799a70e2011-04-18 16:57:27 -07005393 &channels, &samplingRate, &outStream);
Glenn Kasten8abf44d2012-02-02 14:16:03 -08005394 mHardwareStatus = AUDIO_HW_IDLE;
Steve Block3856b092011-10-20 11:56:00 +01005395 ALOGV("openOutput() openOutputStream returned output %p, SamplingRate %d, Format %d, Channels %x, status %d",
Dima Zavin799a70e2011-04-18 16:57:27 -07005396 outStream,
Mathias Agopian65ab4712010-07-14 17:59:35 -07005397 samplingRate,
5398 format,
5399 channels,
5400 status);
5401
Dima Zavin799a70e2011-04-18 16:57:27 -07005402 if (outStream != NULL) {
5403 AudioStreamOut *output = new AudioStreamOut(outHwDev, outStream);
Glenn Kasten72ef00d2012-01-17 11:09:42 -08005404 audio_io_handle_t id = nextUniqueId();
Dima Zavin799a70e2011-04-18 16:57:27 -07005405
Dima Zavinfce7a472011-04-19 22:30:36 -07005406 if ((flags & AUDIO_POLICY_OUTPUT_FLAG_DIRECT) ||
5407 (format != AUDIO_FORMAT_PCM_16_BIT) ||
5408 (channels != AUDIO_CHANNEL_OUT_STEREO)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07005409 thread = new DirectOutputThread(this, output, id, *pDevices);
Steve Block3856b092011-10-20 11:56:00 +01005410 ALOGV("openOutput() created direct output: ID %d thread %p", id, thread);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005411 } else {
5412 thread = new MixerThread(this, output, id, *pDevices);
Steve Block3856b092011-10-20 11:56:00 +01005413 ALOGV("openOutput() created mixer output: ID %d thread %p", id, thread);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005414 }
5415 mPlaybackThreads.add(id, thread);
5416
Glenn Kastena0d68332012-01-27 16:47:15 -08005417 if (pSamplingRate != NULL) *pSamplingRate = samplingRate;
5418 if (pFormat != NULL) *pFormat = format;
5419 if (pChannels != NULL) *pChannels = channels;
5420 if (pLatencyMs != NULL) *pLatencyMs = thread->latency();
Mathias Agopian65ab4712010-07-14 17:59:35 -07005421
5422 // notify client processes of the new output creation
5423 thread->audioConfigChanged_l(AudioSystem::OUTPUT_OPENED);
5424 return id;
5425 }
5426
5427 return 0;
5428}
5429
Glenn Kasten72ef00d2012-01-17 11:09:42 -08005430audio_io_handle_t AudioFlinger::openDuplicateOutput(audio_io_handle_t output1,
5431 audio_io_handle_t output2)
Mathias Agopian65ab4712010-07-14 17:59:35 -07005432{
5433 Mutex::Autolock _l(mLock);
5434 MixerThread *thread1 = checkMixerThread_l(output1);
5435 MixerThread *thread2 = checkMixerThread_l(output2);
5436
5437 if (thread1 == NULL || thread2 == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +00005438 ALOGW("openDuplicateOutput() wrong output mixer type for output %d or %d", output1, output2);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005439 return 0;
5440 }
5441
Glenn Kasten72ef00d2012-01-17 11:09:42 -08005442 audio_io_handle_t id = nextUniqueId();
Mathias Agopian65ab4712010-07-14 17:59:35 -07005443 DuplicatingThread *thread = new DuplicatingThread(this, thread1, id);
5444 thread->addOutputTrack(thread2);
5445 mPlaybackThreads.add(id, thread);
5446 // notify client processes of the new output creation
5447 thread->audioConfigChanged_l(AudioSystem::OUTPUT_OPENED);
5448 return id;
5449}
5450
Glenn Kasten72ef00d2012-01-17 11:09:42 -08005451status_t AudioFlinger::closeOutput(audio_io_handle_t output)
Mathias Agopian65ab4712010-07-14 17:59:35 -07005452{
5453 // keep strong reference on the playback thread so that
5454 // it is not destroyed while exit() is executed
5455 sp <PlaybackThread> thread;
5456 {
5457 Mutex::Autolock _l(mLock);
5458 thread = checkPlaybackThread_l(output);
5459 if (thread == NULL) {
5460 return BAD_VALUE;
5461 }
5462
Steve Block3856b092011-10-20 11:56:00 +01005463 ALOGV("closeOutput() %d", output);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005464
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005465 if (thread->type() == ThreadBase::MIXER) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07005466 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005467 if (mPlaybackThreads.valueAt(i)->type() == ThreadBase::DUPLICATING) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07005468 DuplicatingThread *dupThread = (DuplicatingThread *)mPlaybackThreads.valueAt(i).get();
5469 dupThread->removeOutputTrack((MixerThread *)thread.get());
5470 }
5471 }
5472 }
Glenn Kastena1117922012-01-26 10:53:32 -08005473 audioConfigChanged_l(AudioSystem::OUTPUT_CLOSED, output, NULL);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005474 mPlaybackThreads.removeItem(output);
5475 }
5476 thread->exit();
Glenn Kastenb28686f2012-01-06 08:39:38 -08005477 // The thread entity (active unit of execution) is no longer running here,
5478 // but the ThreadBase container still exists.
Mathias Agopian65ab4712010-07-14 17:59:35 -07005479
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005480 if (thread->type() != ThreadBase::DUPLICATING) {
Eric Laurentb8ba0a92011-08-07 16:32:26 -07005481 AudioStreamOut *out = thread->clearOutput();
Glenn Kastenaed850d2012-01-26 09:46:34 -08005482 assert(out != NULL);
Eric Laurentb8ba0a92011-08-07 16:32:26 -07005483 // from now on thread->mOutput is NULL
Dima Zavin799a70e2011-04-18 16:57:27 -07005484 out->hwDev->close_output_stream(out->hwDev, out->stream);
5485 delete out;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005486 }
5487 return NO_ERROR;
5488}
5489
Glenn Kasten72ef00d2012-01-17 11:09:42 -08005490status_t AudioFlinger::suspendOutput(audio_io_handle_t output)
Mathias Agopian65ab4712010-07-14 17:59:35 -07005491{
5492 Mutex::Autolock _l(mLock);
5493 PlaybackThread *thread = checkPlaybackThread_l(output);
5494
5495 if (thread == NULL) {
5496 return BAD_VALUE;
5497 }
5498
Steve Block3856b092011-10-20 11:56:00 +01005499 ALOGV("suspendOutput() %d", output);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005500 thread->suspend();
5501
5502 return NO_ERROR;
5503}
5504
Glenn Kasten72ef00d2012-01-17 11:09:42 -08005505status_t AudioFlinger::restoreOutput(audio_io_handle_t output)
Mathias Agopian65ab4712010-07-14 17:59:35 -07005506{
5507 Mutex::Autolock _l(mLock);
5508 PlaybackThread *thread = checkPlaybackThread_l(output);
5509
5510 if (thread == NULL) {
5511 return BAD_VALUE;
5512 }
5513
Steve Block3856b092011-10-20 11:56:00 +01005514 ALOGV("restoreOutput() %d", output);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005515
5516 thread->restore();
5517
5518 return NO_ERROR;
5519}
5520
Glenn Kasten72ef00d2012-01-17 11:09:42 -08005521audio_io_handle_t AudioFlinger::openInput(uint32_t *pDevices,
Mathias Agopian65ab4712010-07-14 17:59:35 -07005522 uint32_t *pSamplingRate,
Glenn Kasten58f30212012-01-12 12:27:51 -08005523 audio_format_t *pFormat,
Mathias Agopian65ab4712010-07-14 17:59:35 -07005524 uint32_t *pChannels,
Glenn Kastende9719b2012-01-27 12:32:34 -08005525 audio_in_acoustics_t acoustics)
Mathias Agopian65ab4712010-07-14 17:59:35 -07005526{
5527 status_t status;
5528 RecordThread *thread = NULL;
5529 uint32_t samplingRate = pSamplingRate ? *pSamplingRate : 0;
Glenn Kasten58f30212012-01-12 12:27:51 -08005530 audio_format_t format = pFormat ? *pFormat : AUDIO_FORMAT_DEFAULT;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005531 uint32_t channels = pChannels ? *pChannels : 0;
5532 uint32_t reqSamplingRate = samplingRate;
Glenn Kasten58f30212012-01-12 12:27:51 -08005533 audio_format_t reqFormat = format;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005534 uint32_t reqChannels = channels;
Dima Zavin799a70e2011-04-18 16:57:27 -07005535 audio_stream_in_t *inStream;
5536 audio_hw_device_t *inHwDev;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005537
5538 if (pDevices == NULL || *pDevices == 0) {
5539 return 0;
5540 }
Dima Zavin799a70e2011-04-18 16:57:27 -07005541
Mathias Agopian65ab4712010-07-14 17:59:35 -07005542 Mutex::Autolock _l(mLock);
5543
Dima Zavin799a70e2011-04-18 16:57:27 -07005544 inHwDev = findSuitableHwDev_l(*pDevices);
5545 if (inHwDev == NULL)
5546 return 0;
5547
Glenn Kasten58f30212012-01-12 12:27:51 -08005548 status = inHwDev->open_input_stream(inHwDev, *pDevices, &format,
Dima Zavin799a70e2011-04-18 16:57:27 -07005549 &channels, &samplingRate,
Glenn Kastende9719b2012-01-27 12:32:34 -08005550 acoustics,
Dima Zavin799a70e2011-04-18 16:57:27 -07005551 &inStream);
Steve Block3856b092011-10-20 11:56:00 +01005552 ALOGV("openInput() openInputStream returned input %p, SamplingRate %d, Format %d, Channels %x, acoustics %x, status %d",
Dima Zavin799a70e2011-04-18 16:57:27 -07005553 inStream,
Mathias Agopian65ab4712010-07-14 17:59:35 -07005554 samplingRate,
5555 format,
5556 channels,
5557 acoustics,
5558 status);
5559
5560 // If the input could not be opened with the requested parameters and we can handle the conversion internally,
5561 // try to open again with the proposed parameters. The AudioFlinger can resample the input and do mono to stereo
5562 // or stereo to mono conversions on 16 bit PCM inputs.
Dima Zavin799a70e2011-04-18 16:57:27 -07005563 if (inStream == NULL && status == BAD_VALUE &&
Dima Zavinfce7a472011-04-19 22:30:36 -07005564 reqFormat == format && format == AUDIO_FORMAT_PCM_16_BIT &&
Mathias Agopian65ab4712010-07-14 17:59:35 -07005565 (samplingRate <= 2 * reqSamplingRate) &&
Dima Zavinfce7a472011-04-19 22:30:36 -07005566 (popcount(channels) < 3) && (popcount(reqChannels) < 3)) {
Steve Block3856b092011-10-20 11:56:00 +01005567 ALOGV("openInput() reopening with proposed sampling rate and channels");
Glenn Kasten58f30212012-01-12 12:27:51 -08005568 status = inHwDev->open_input_stream(inHwDev, *pDevices, &format,
Dima Zavin799a70e2011-04-18 16:57:27 -07005569 &channels, &samplingRate,
Glenn Kastende9719b2012-01-27 12:32:34 -08005570 acoustics,
Dima Zavin799a70e2011-04-18 16:57:27 -07005571 &inStream);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005572 }
5573
Dima Zavin799a70e2011-04-18 16:57:27 -07005574 if (inStream != NULL) {
5575 AudioStreamIn *input = new AudioStreamIn(inHwDev, inStream);
5576
Glenn Kasten72ef00d2012-01-17 11:09:42 -08005577 audio_io_handle_t id = nextUniqueId();
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005578 // Start record thread
5579 // RecorThread require both input and output device indication to forward to audio
5580 // pre processing modules
5581 uint32_t device = (*pDevices) | primaryOutputDevice_l();
5582 thread = new RecordThread(this,
5583 input,
5584 reqSamplingRate,
5585 reqChannels,
5586 id,
5587 device);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005588 mRecordThreads.add(id, thread);
Steve Block3856b092011-10-20 11:56:00 +01005589 ALOGV("openInput() created record thread: ID %d thread %p", id, thread);
Glenn Kastena0d68332012-01-27 16:47:15 -08005590 if (pSamplingRate != NULL) *pSamplingRate = reqSamplingRate;
5591 if (pFormat != NULL) *pFormat = format;
5592 if (pChannels != NULL) *pChannels = reqChannels;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005593
Dima Zavin799a70e2011-04-18 16:57:27 -07005594 input->stream->common.standby(&input->stream->common);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005595
5596 // notify client processes of the new input creation
5597 thread->audioConfigChanged_l(AudioSystem::INPUT_OPENED);
5598 return id;
5599 }
5600
5601 return 0;
5602}
5603
Glenn Kasten72ef00d2012-01-17 11:09:42 -08005604status_t AudioFlinger::closeInput(audio_io_handle_t input)
Mathias Agopian65ab4712010-07-14 17:59:35 -07005605{
5606 // keep strong reference on the record thread so that
5607 // it is not destroyed while exit() is executed
5608 sp <RecordThread> thread;
5609 {
5610 Mutex::Autolock _l(mLock);
5611 thread = checkRecordThread_l(input);
5612 if (thread == NULL) {
5613 return BAD_VALUE;
5614 }
5615
Steve Block3856b092011-10-20 11:56:00 +01005616 ALOGV("closeInput() %d", input);
Glenn Kastena1117922012-01-26 10:53:32 -08005617 audioConfigChanged_l(AudioSystem::INPUT_CLOSED, input, NULL);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005618 mRecordThreads.removeItem(input);
5619 }
5620 thread->exit();
Glenn Kastenb28686f2012-01-06 08:39:38 -08005621 // The thread entity (active unit of execution) is no longer running here,
5622 // but the ThreadBase container still exists.
Mathias Agopian65ab4712010-07-14 17:59:35 -07005623
Eric Laurentb8ba0a92011-08-07 16:32:26 -07005624 AudioStreamIn *in = thread->clearInput();
Glenn Kastenaed850d2012-01-26 09:46:34 -08005625 assert(in != NULL);
Eric Laurentb8ba0a92011-08-07 16:32:26 -07005626 // from now on thread->mInput is NULL
Dima Zavin799a70e2011-04-18 16:57:27 -07005627 in->hwDev->close_input_stream(in->hwDev, in->stream);
5628 delete in;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005629
5630 return NO_ERROR;
5631}
5632
Glenn Kasten72ef00d2012-01-17 11:09:42 -08005633status_t AudioFlinger::setStreamOutput(audio_stream_type_t stream, audio_io_handle_t output)
Mathias Agopian65ab4712010-07-14 17:59:35 -07005634{
5635 Mutex::Autolock _l(mLock);
5636 MixerThread *dstThread = checkMixerThread_l(output);
5637 if (dstThread == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +00005638 ALOGW("setStreamOutput() bad output id %d", output);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005639 return BAD_VALUE;
5640 }
5641
Steve Block3856b092011-10-20 11:56:00 +01005642 ALOGV("setStreamOutput() stream %d to output %d", stream, output);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005643 audioConfigChanged_l(AudioSystem::STREAM_CONFIG_CHANGED, output, &stream);
5644
Eric Laurent9f6530f2011-08-30 10:18:54 -07005645 dstThread->setStreamValid(stream, true);
5646
Mathias Agopian65ab4712010-07-14 17:59:35 -07005647 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
5648 PlaybackThread *thread = mPlaybackThreads.valueAt(i).get();
Glenn Kastena1117922012-01-26 10:53:32 -08005649 if (thread != dstThread && thread->type() != ThreadBase::DIRECT) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07005650 MixerThread *srcThread = (MixerThread *)thread;
Eric Laurent9f6530f2011-08-30 10:18:54 -07005651 srcThread->setStreamValid(stream, false);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005652 srcThread->invalidateTracks(stream);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005653 }
Eric Laurentde070132010-07-13 04:45:46 -07005654 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07005655
5656 return NO_ERROR;
5657}
5658
5659
5660int AudioFlinger::newAudioSessionId()
5661{
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005662 return nextUniqueId();
Mathias Agopian65ab4712010-07-14 17:59:35 -07005663}
5664
Marco Nelissen3a34bef2011-08-02 13:33:41 -07005665void AudioFlinger::acquireAudioSessionId(int audioSession)
5666{
5667 Mutex::Autolock _l(mLock);
Glenn Kastenbb001922012-02-03 11:10:26 -08005668 pid_t caller = IPCThreadState::self()->getCallingPid();
Steve Block3856b092011-10-20 11:56:00 +01005669 ALOGV("acquiring %d from %d", audioSession, caller);
Glenn Kasten8d6a2442012-02-08 14:04:28 -08005670 size_t num = mAudioSessionRefs.size();
5671 for (size_t i = 0; i< num; i++) {
Marco Nelissen3a34bef2011-08-02 13:33:41 -07005672 AudioSessionRef *ref = mAudioSessionRefs.editItemAt(i);
Glenn Kasten012ca6b2012-03-06 11:22:01 -08005673 if (ref->mSessionid == audioSession && ref->mPid == caller) {
5674 ref->mCnt++;
5675 ALOGV(" incremented refcount to %d", ref->mCnt);
Marco Nelissen3a34bef2011-08-02 13:33:41 -07005676 return;
5677 }
5678 }
Glenn Kasten84afa3b2012-01-25 15:28:08 -08005679 mAudioSessionRefs.push(new AudioSessionRef(audioSession, caller));
5680 ALOGV(" added new entry for %d", audioSession);
Marco Nelissen3a34bef2011-08-02 13:33:41 -07005681}
5682
5683void AudioFlinger::releaseAudioSessionId(int audioSession)
5684{
5685 Mutex::Autolock _l(mLock);
Glenn Kastenbb001922012-02-03 11:10:26 -08005686 pid_t caller = IPCThreadState::self()->getCallingPid();
Steve Block3856b092011-10-20 11:56:00 +01005687 ALOGV("releasing %d from %d", audioSession, caller);
Glenn Kasten8d6a2442012-02-08 14:04:28 -08005688 size_t num = mAudioSessionRefs.size();
5689 for (size_t i = 0; i< num; i++) {
Marco Nelissen3a34bef2011-08-02 13:33:41 -07005690 AudioSessionRef *ref = mAudioSessionRefs.itemAt(i);
Glenn Kasten012ca6b2012-03-06 11:22:01 -08005691 if (ref->mSessionid == audioSession && ref->mPid == caller) {
5692 ref->mCnt--;
5693 ALOGV(" decremented refcount to %d", ref->mCnt);
5694 if (ref->mCnt == 0) {
Marco Nelissen3a34bef2011-08-02 13:33:41 -07005695 mAudioSessionRefs.removeAt(i);
5696 delete ref;
5697 purgeStaleEffects_l();
5698 }
5699 return;
5700 }
5701 }
Steve Block5ff1dd52012-01-05 23:22:43 +00005702 ALOGW("session id %d not found for pid %d", audioSession, caller);
Marco Nelissen3a34bef2011-08-02 13:33:41 -07005703}
5704
5705void AudioFlinger::purgeStaleEffects_l() {
5706
Steve Block3856b092011-10-20 11:56:00 +01005707 ALOGV("purging stale effects");
Marco Nelissen3a34bef2011-08-02 13:33:41 -07005708
5709 Vector< sp<EffectChain> > chains;
5710
5711 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
5712 sp<PlaybackThread> t = mPlaybackThreads.valueAt(i);
5713 for (size_t j = 0; j < t->mEffectChains.size(); j++) {
5714 sp<EffectChain> ec = t->mEffectChains[j];
Marco Nelissen0270b182011-08-12 14:14:39 -07005715 if (ec->sessionId() > AUDIO_SESSION_OUTPUT_MIX) {
5716 chains.push(ec);
5717 }
Marco Nelissen3a34bef2011-08-02 13:33:41 -07005718 }
5719 }
5720 for (size_t i = 0; i < mRecordThreads.size(); i++) {
5721 sp<RecordThread> t = mRecordThreads.valueAt(i);
5722 for (size_t j = 0; j < t->mEffectChains.size(); j++) {
5723 sp<EffectChain> ec = t->mEffectChains[j];
5724 chains.push(ec);
5725 }
5726 }
5727
5728 for (size_t i = 0; i < chains.size(); i++) {
5729 sp<EffectChain> ec = chains[i];
5730 int sessionid = ec->sessionId();
5731 sp<ThreadBase> t = ec->mThread.promote();
5732 if (t == 0) {
5733 continue;
5734 }
5735 size_t numsessionrefs = mAudioSessionRefs.size();
5736 bool found = false;
5737 for (size_t k = 0; k < numsessionrefs; k++) {
5738 AudioSessionRef *ref = mAudioSessionRefs.itemAt(k);
Glenn Kasten012ca6b2012-03-06 11:22:01 -08005739 if (ref->mSessionid == sessionid) {
Steve Block3856b092011-10-20 11:56:00 +01005740 ALOGV(" session %d still exists for %d with %d refs",
Glenn Kasten012ca6b2012-03-06 11:22:01 -08005741 sessionid, ref->mPid, ref->mCnt);
Marco Nelissen3a34bef2011-08-02 13:33:41 -07005742 found = true;
5743 break;
5744 }
5745 }
5746 if (!found) {
5747 // remove all effects from the chain
5748 while (ec->mEffects.size()) {
5749 sp<EffectModule> effect = ec->mEffects[0];
5750 effect->unPin();
5751 Mutex::Autolock _l (t->mLock);
5752 t->removeEffect_l(effect);
5753 for (size_t j = 0; j < effect->mHandles.size(); j++) {
5754 sp<EffectHandle> handle = effect->mHandles[j].promote();
5755 if (handle != 0) {
5756 handle->mEffect.clear();
Eric Laurenta85a74a2011-10-19 11:44:54 -07005757 if (handle->mHasControl && handle->mEnabled) {
5758 t->checkSuspendOnEffectEnabled_l(effect, false, effect->sessionId());
5759 }
Marco Nelissen3a34bef2011-08-02 13:33:41 -07005760 }
5761 }
5762 AudioSystem::unregisterEffect(effect->id());
5763 }
5764 }
5765 }
5766 return;
5767}
5768
Mathias Agopian65ab4712010-07-14 17:59:35 -07005769// checkPlaybackThread_l() must be called with AudioFlinger::mLock held
Glenn Kasten72ef00d2012-01-17 11:09:42 -08005770AudioFlinger::PlaybackThread *AudioFlinger::checkPlaybackThread_l(audio_io_handle_t output) const
Mathias Agopian65ab4712010-07-14 17:59:35 -07005771{
Glenn Kastena1117922012-01-26 10:53:32 -08005772 return mPlaybackThreads.valueFor(output).get();
Mathias Agopian65ab4712010-07-14 17:59:35 -07005773}
5774
5775// checkMixerThread_l() must be called with AudioFlinger::mLock held
Glenn Kasten72ef00d2012-01-17 11:09:42 -08005776AudioFlinger::MixerThread *AudioFlinger::checkMixerThread_l(audio_io_handle_t output) const
Mathias Agopian65ab4712010-07-14 17:59:35 -07005777{
5778 PlaybackThread *thread = checkPlaybackThread_l(output);
Glenn Kastena1117922012-01-26 10:53:32 -08005779 return thread != NULL && thread->type() != ThreadBase::DIRECT ? (MixerThread *) thread : NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005780}
5781
5782// checkRecordThread_l() must be called with AudioFlinger::mLock held
Glenn Kasten72ef00d2012-01-17 11:09:42 -08005783AudioFlinger::RecordThread *AudioFlinger::checkRecordThread_l(audio_io_handle_t input) const
Mathias Agopian65ab4712010-07-14 17:59:35 -07005784{
Glenn Kastena1117922012-01-26 10:53:32 -08005785 return mRecordThreads.valueFor(input).get();
Mathias Agopian65ab4712010-07-14 17:59:35 -07005786}
5787
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005788uint32_t AudioFlinger::nextUniqueId()
Mathias Agopian65ab4712010-07-14 17:59:35 -07005789{
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005790 return android_atomic_inc(&mNextUniqueId);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005791}
5792
Glenn Kasten02fe1bf2012-02-24 15:42:17 -08005793AudioFlinger::PlaybackThread *AudioFlinger::primaryPlaybackThread_l() const
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005794{
5795 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
5796 PlaybackThread *thread = mPlaybackThreads.valueAt(i).get();
Eric Laurentb8ba0a92011-08-07 16:32:26 -07005797 AudioStreamOut *output = thread->getOutput();
5798 if (output != NULL && output->hwDev == mPrimaryHardwareDev) {
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005799 return thread;
5800 }
5801 }
5802 return NULL;
5803}
5804
Glenn Kasten02fe1bf2012-02-24 15:42:17 -08005805uint32_t AudioFlinger::primaryOutputDevice_l() const
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005806{
5807 PlaybackThread *thread = primaryPlaybackThread_l();
5808
5809 if (thread == NULL) {
5810 return 0;
5811 }
5812
5813 return thread->device();
5814}
5815
5816
Mathias Agopian65ab4712010-07-14 17:59:35 -07005817// ----------------------------------------------------------------------------
5818// Effect management
5819// ----------------------------------------------------------------------------
5820
5821
Glenn Kastenf587ba52012-01-26 16:25:10 -08005822status_t AudioFlinger::queryNumberEffects(uint32_t *numEffects) const
Mathias Agopian65ab4712010-07-14 17:59:35 -07005823{
5824 Mutex::Autolock _l(mLock);
5825 return EffectQueryNumberEffects(numEffects);
5826}
5827
Glenn Kastenf587ba52012-01-26 16:25:10 -08005828status_t AudioFlinger::queryEffect(uint32_t index, effect_descriptor_t *descriptor) const
Mathias Agopian65ab4712010-07-14 17:59:35 -07005829{
5830 Mutex::Autolock _l(mLock);
5831 return EffectQueryEffect(index, descriptor);
5832}
5833
Glenn Kasten5e92a782012-01-30 07:40:52 -08005834status_t AudioFlinger::getEffectDescriptor(const effect_uuid_t *pUuid,
Glenn Kastenf587ba52012-01-26 16:25:10 -08005835 effect_descriptor_t *descriptor) const
Mathias Agopian65ab4712010-07-14 17:59:35 -07005836{
5837 Mutex::Autolock _l(mLock);
5838 return EffectGetDescriptor(pUuid, descriptor);
5839}
5840
5841
Mathias Agopian65ab4712010-07-14 17:59:35 -07005842sp<IEffect> AudioFlinger::createEffect(pid_t pid,
5843 effect_descriptor_t *pDesc,
5844 const sp<IEffectClient>& effectClient,
5845 int32_t priority,
Glenn Kasten72ef00d2012-01-17 11:09:42 -08005846 audio_io_handle_t io,
Mathias Agopian65ab4712010-07-14 17:59:35 -07005847 int sessionId,
5848 status_t *status,
5849 int *id,
5850 int *enabled)
5851{
5852 status_t lStatus = NO_ERROR;
5853 sp<EffectHandle> handle;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005854 effect_descriptor_t desc;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005855
Glenn Kasten98ec94c2012-01-25 14:28:29 -08005856 ALOGV("createEffect pid %d, effectClient %p, priority %d, sessionId %d, io %d",
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005857 pid, effectClient.get(), priority, sessionId, io);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005858
5859 if (pDesc == NULL) {
5860 lStatus = BAD_VALUE;
5861 goto Exit;
5862 }
5863
Eric Laurent84e9a102010-09-23 16:10:16 -07005864 // check audio settings permission for global effects
Dima Zavinfce7a472011-04-19 22:30:36 -07005865 if (sessionId == AUDIO_SESSION_OUTPUT_MIX && !settingsAllowed()) {
Eric Laurent84e9a102010-09-23 16:10:16 -07005866 lStatus = PERMISSION_DENIED;
5867 goto Exit;
5868 }
5869
Dima Zavinfce7a472011-04-19 22:30:36 -07005870 // Session AUDIO_SESSION_OUTPUT_STAGE is reserved for output stage effects
Eric Laurent84e9a102010-09-23 16:10:16 -07005871 // that can only be created by audio policy manager (running in same process)
Glenn Kasten44deb052012-02-05 18:09:08 -08005872 if (sessionId == AUDIO_SESSION_OUTPUT_STAGE && getpid_cached != pid) {
Eric Laurent84e9a102010-09-23 16:10:16 -07005873 lStatus = PERMISSION_DENIED;
5874 goto Exit;
5875 }
5876
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005877 if (io == 0) {
Dima Zavinfce7a472011-04-19 22:30:36 -07005878 if (sessionId == AUDIO_SESSION_OUTPUT_STAGE) {
Eric Laurent84e9a102010-09-23 16:10:16 -07005879 // output must be specified by AudioPolicyManager when using session
Dima Zavinfce7a472011-04-19 22:30:36 -07005880 // AUDIO_SESSION_OUTPUT_STAGE
Eric Laurent84e9a102010-09-23 16:10:16 -07005881 lStatus = BAD_VALUE;
5882 goto Exit;
Dima Zavinfce7a472011-04-19 22:30:36 -07005883 } else if (sessionId == AUDIO_SESSION_OUTPUT_MIX) {
Eric Laurent84e9a102010-09-23 16:10:16 -07005884 // if the output returned by getOutputForEffect() is removed before we lock the
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005885 // mutex below, the call to checkPlaybackThread_l(io) below will detect it
Eric Laurent84e9a102010-09-23 16:10:16 -07005886 // and we will exit safely
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005887 io = AudioSystem::getOutputForEffect(&desc);
Eric Laurent84e9a102010-09-23 16:10:16 -07005888 }
5889 }
5890
Mathias Agopian65ab4712010-07-14 17:59:35 -07005891 {
5892 Mutex::Autolock _l(mLock);
5893
Mathias Agopian65ab4712010-07-14 17:59:35 -07005894
5895 if (!EffectIsNullUuid(&pDesc->uuid)) {
5896 // if uuid is specified, request effect descriptor
5897 lStatus = EffectGetDescriptor(&pDesc->uuid, &desc);
5898 if (lStatus < 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00005899 ALOGW("createEffect() error %d from EffectGetDescriptor", lStatus);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005900 goto Exit;
5901 }
5902 } else {
5903 // if uuid is not specified, look for an available implementation
5904 // of the required type in effect factory
5905 if (EffectIsNullUuid(&pDesc->type)) {
Steve Block5ff1dd52012-01-05 23:22:43 +00005906 ALOGW("createEffect() no effect type");
Mathias Agopian65ab4712010-07-14 17:59:35 -07005907 lStatus = BAD_VALUE;
5908 goto Exit;
5909 }
5910 uint32_t numEffects = 0;
5911 effect_descriptor_t d;
Marco Nelissen3a34bef2011-08-02 13:33:41 -07005912 d.flags = 0; // prevent compiler warning
Mathias Agopian65ab4712010-07-14 17:59:35 -07005913 bool found = false;
5914
5915 lStatus = EffectQueryNumberEffects(&numEffects);
5916 if (lStatus < 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00005917 ALOGW("createEffect() error %d from EffectQueryNumberEffects", lStatus);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005918 goto Exit;
5919 }
5920 for (uint32_t i = 0; i < numEffects; i++) {
5921 lStatus = EffectQueryEffect(i, &desc);
5922 if (lStatus < 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00005923 ALOGW("createEffect() error %d from EffectQueryEffect", lStatus);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005924 continue;
5925 }
5926 if (memcmp(&desc.type, &pDesc->type, sizeof(effect_uuid_t)) == 0) {
5927 // If matching type found save effect descriptor. If the session is
5928 // 0 and the effect is not auxiliary, continue enumeration in case
5929 // an auxiliary version of this effect type is available
5930 found = true;
5931 memcpy(&d, &desc, sizeof(effect_descriptor_t));
Dima Zavinfce7a472011-04-19 22:30:36 -07005932 if (sessionId != AUDIO_SESSION_OUTPUT_MIX ||
Mathias Agopian65ab4712010-07-14 17:59:35 -07005933 (desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
5934 break;
5935 }
5936 }
5937 }
5938 if (!found) {
5939 lStatus = BAD_VALUE;
Steve Block5ff1dd52012-01-05 23:22:43 +00005940 ALOGW("createEffect() effect not found");
Mathias Agopian65ab4712010-07-14 17:59:35 -07005941 goto Exit;
5942 }
5943 // For same effect type, chose auxiliary version over insert version if
5944 // connect to output mix (Compliance to OpenSL ES)
Dima Zavinfce7a472011-04-19 22:30:36 -07005945 if (sessionId == AUDIO_SESSION_OUTPUT_MIX &&
Mathias Agopian65ab4712010-07-14 17:59:35 -07005946 (d.flags & EFFECT_FLAG_TYPE_MASK) != EFFECT_FLAG_TYPE_AUXILIARY) {
5947 memcpy(&desc, &d, sizeof(effect_descriptor_t));
5948 }
5949 }
5950
5951 // Do not allow auxiliary effects on a session different from 0 (output mix)
Dima Zavinfce7a472011-04-19 22:30:36 -07005952 if (sessionId != AUDIO_SESSION_OUTPUT_MIX &&
Mathias Agopian65ab4712010-07-14 17:59:35 -07005953 (desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
5954 lStatus = INVALID_OPERATION;
5955 goto Exit;
5956 }
5957
Eric Laurent59255e42011-07-27 19:49:51 -07005958 // check recording permission for visualizer
5959 if ((memcmp(&desc.type, SL_IID_VISUALIZATION, sizeof(effect_uuid_t)) == 0) &&
5960 !recordingAllowed()) {
5961 lStatus = PERMISSION_DENIED;
5962 goto Exit;
5963 }
5964
Mathias Agopian65ab4712010-07-14 17:59:35 -07005965 // return effect descriptor
5966 memcpy(pDesc, &desc, sizeof(effect_descriptor_t));
5967
5968 // If output is not specified try to find a matching audio session ID in one of the
5969 // output threads.
Eric Laurent84e9a102010-09-23 16:10:16 -07005970 // If output is 0 here, sessionId is neither SESSION_OUTPUT_STAGE nor SESSION_OUTPUT_MIX
5971 // because of code checking output when entering the function.
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005972 // Note: io is never 0 when creating an effect on an input
5973 if (io == 0) {
Eric Laurent84e9a102010-09-23 16:10:16 -07005974 // look for the thread where the specified audio session is present
5975 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
5976 if (mPlaybackThreads.valueAt(i)->hasAudioSession(sessionId) != 0) {
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005977 io = mPlaybackThreads.keyAt(i);
Eric Laurent84e9a102010-09-23 16:10:16 -07005978 break;
Eric Laurent39e94f82010-07-28 01:32:47 -07005979 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07005980 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005981 if (io == 0) {
5982 for (size_t i = 0; i < mRecordThreads.size(); i++) {
5983 if (mRecordThreads.valueAt(i)->hasAudioSession(sessionId) != 0) {
5984 io = mRecordThreads.keyAt(i);
5985 break;
5986 }
5987 }
5988 }
Eric Laurent84e9a102010-09-23 16:10:16 -07005989 // If no output thread contains the requested session ID, default to
5990 // first output. The effect chain will be moved to the correct output
5991 // thread when a track with the same session ID is created
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005992 if (io == 0 && mPlaybackThreads.size()) {
5993 io = mPlaybackThreads.keyAt(0);
5994 }
Steve Block3856b092011-10-20 11:56:00 +01005995 ALOGV("createEffect() got io %d for effect %s", io, desc.name);
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005996 }
5997 ThreadBase *thread = checkRecordThread_l(io);
5998 if (thread == NULL) {
5999 thread = checkPlaybackThread_l(io);
6000 if (thread == NULL) {
Steve Block29357bc2012-01-06 19:20:56 +00006001 ALOGE("createEffect() unknown output thread");
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006002 lStatus = BAD_VALUE;
6003 goto Exit;
Eric Laurent84e9a102010-09-23 16:10:16 -07006004 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07006005 }
Eric Laurent84e9a102010-09-23 16:10:16 -07006006
Glenn Kasten98ec94c2012-01-25 14:28:29 -08006007 sp<Client> client = registerPid_l(pid);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006008
Marco Nelissen3a34bef2011-08-02 13:33:41 -07006009 // create effect on selected output thread
Eric Laurentde070132010-07-13 04:45:46 -07006010 handle = thread->createEffect_l(client, effectClient, priority, sessionId,
6011 &desc, enabled, &lStatus);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006012 if (handle != 0 && id != NULL) {
6013 *id = handle->id();
6014 }
6015 }
6016
6017Exit:
6018 if(status) {
6019 *status = lStatus;
6020 }
6021 return handle;
6022}
6023
Glenn Kasten72ef00d2012-01-17 11:09:42 -08006024status_t AudioFlinger::moveEffects(int sessionId, audio_io_handle_t srcOutput,
6025 audio_io_handle_t dstOutput)
Eric Laurentde070132010-07-13 04:45:46 -07006026{
Steve Block3856b092011-10-20 11:56:00 +01006027 ALOGV("moveEffects() session %d, srcOutput %d, dstOutput %d",
Eric Laurent59255e42011-07-27 19:49:51 -07006028 sessionId, srcOutput, dstOutput);
Eric Laurentde070132010-07-13 04:45:46 -07006029 Mutex::Autolock _l(mLock);
6030 if (srcOutput == dstOutput) {
Steve Block5ff1dd52012-01-05 23:22:43 +00006031 ALOGW("moveEffects() same dst and src outputs %d", dstOutput);
Eric Laurentde070132010-07-13 04:45:46 -07006032 return NO_ERROR;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006033 }
Eric Laurentde070132010-07-13 04:45:46 -07006034 PlaybackThread *srcThread = checkPlaybackThread_l(srcOutput);
6035 if (srcThread == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +00006036 ALOGW("moveEffects() bad srcOutput %d", srcOutput);
Eric Laurentde070132010-07-13 04:45:46 -07006037 return BAD_VALUE;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006038 }
Eric Laurentde070132010-07-13 04:45:46 -07006039 PlaybackThread *dstThread = checkPlaybackThread_l(dstOutput);
6040 if (dstThread == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +00006041 ALOGW("moveEffects() bad dstOutput %d", dstOutput);
Eric Laurentde070132010-07-13 04:45:46 -07006042 return BAD_VALUE;
6043 }
6044
6045 Mutex::Autolock _dl(dstThread->mLock);
6046 Mutex::Autolock _sl(srcThread->mLock);
Eric Laurent59255e42011-07-27 19:49:51 -07006047 moveEffectChain_l(sessionId, srcThread, dstThread, false);
Eric Laurentde070132010-07-13 04:45:46 -07006048
Mathias Agopian65ab4712010-07-14 17:59:35 -07006049 return NO_ERROR;
6050}
6051
Marco Nelissen3a34bef2011-08-02 13:33:41 -07006052// moveEffectChain_l must be called with both srcThread and dstThread mLocks held
Eric Laurent59255e42011-07-27 19:49:51 -07006053status_t AudioFlinger::moveEffectChain_l(int sessionId,
Eric Laurentde070132010-07-13 04:45:46 -07006054 AudioFlinger::PlaybackThread *srcThread,
Eric Laurent39e94f82010-07-28 01:32:47 -07006055 AudioFlinger::PlaybackThread *dstThread,
6056 bool reRegister)
Eric Laurentde070132010-07-13 04:45:46 -07006057{
Steve Block3856b092011-10-20 11:56:00 +01006058 ALOGV("moveEffectChain_l() session %d from thread %p to thread %p",
Eric Laurent59255e42011-07-27 19:49:51 -07006059 sessionId, srcThread, dstThread);
Eric Laurentde070132010-07-13 04:45:46 -07006060
Eric Laurent59255e42011-07-27 19:49:51 -07006061 sp<EffectChain> chain = srcThread->getEffectChain_l(sessionId);
Eric Laurentde070132010-07-13 04:45:46 -07006062 if (chain == 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00006063 ALOGW("moveEffectChain_l() effect chain for session %d not on source thread %p",
Eric Laurent59255e42011-07-27 19:49:51 -07006064 sessionId, srcThread);
Eric Laurentde070132010-07-13 04:45:46 -07006065 return INVALID_OPERATION;
6066 }
6067
Eric Laurent39e94f82010-07-28 01:32:47 -07006068 // remove chain first. This is useful only if reconfiguring effect chain on same output thread,
Eric Laurentde070132010-07-13 04:45:46 -07006069 // so that a new chain is created with correct parameters when first effect is added. This is
Eric Laurentec35a142011-10-05 17:42:25 -07006070 // otherwise unnecessary as removeEffect_l() will remove the chain when last effect is
Eric Laurentde070132010-07-13 04:45:46 -07006071 // removed.
6072 srcThread->removeEffectChain_l(chain);
6073
6074 // transfer all effects one by one so that new effect chain is created on new thread with
6075 // correct buffer sizes and audio parameters and effect engines reconfigured accordingly
Glenn Kasten72ef00d2012-01-17 11:09:42 -08006076 audio_io_handle_t dstOutput = dstThread->id();
Eric Laurent39e94f82010-07-28 01:32:47 -07006077 sp<EffectChain> dstChain;
Marco Nelissen3a34bef2011-08-02 13:33:41 -07006078 uint32_t strategy = 0; // prevent compiler warning
Eric Laurentde070132010-07-13 04:45:46 -07006079 sp<EffectModule> effect = chain->getEffectFromId_l(0);
6080 while (effect != 0) {
6081 srcThread->removeEffect_l(effect);
6082 dstThread->addEffect_l(effect);
Eric Laurentec35a142011-10-05 17:42:25 -07006083 // removeEffect_l() has stopped the effect if it was active so it must be restarted
6084 if (effect->state() == EffectModule::ACTIVE ||
6085 effect->state() == EffectModule::STOPPING) {
6086 effect->start();
6087 }
Eric Laurent39e94f82010-07-28 01:32:47 -07006088 // if the move request is not received from audio policy manager, the effect must be
6089 // re-registered with the new strategy and output
6090 if (dstChain == 0) {
6091 dstChain = effect->chain().promote();
6092 if (dstChain == 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00006093 ALOGW("moveEffectChain_l() cannot get chain from effect %p", effect.get());
Eric Laurent39e94f82010-07-28 01:32:47 -07006094 srcThread->addEffect_l(effect);
6095 return NO_INIT;
6096 }
6097 strategy = dstChain->strategy();
6098 }
6099 if (reRegister) {
6100 AudioSystem::unregisterEffect(effect->id());
6101 AudioSystem::registerEffect(&effect->desc(),
6102 dstOutput,
6103 strategy,
Eric Laurent59255e42011-07-27 19:49:51 -07006104 sessionId,
Eric Laurent39e94f82010-07-28 01:32:47 -07006105 effect->id());
6106 }
Eric Laurentde070132010-07-13 04:45:46 -07006107 effect = chain->getEffectFromId_l(0);
6108 }
6109
6110 return NO_ERROR;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006111}
6112
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006113
Mathias Agopian65ab4712010-07-14 17:59:35 -07006114// PlaybackThread::createEffect_l() must be called with AudioFlinger::mLock held
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006115sp<AudioFlinger::EffectHandle> AudioFlinger::ThreadBase::createEffect_l(
Mathias Agopian65ab4712010-07-14 17:59:35 -07006116 const sp<AudioFlinger::Client>& client,
6117 const sp<IEffectClient>& effectClient,
6118 int32_t priority,
6119 int sessionId,
6120 effect_descriptor_t *desc,
6121 int *enabled,
6122 status_t *status
6123 )
6124{
6125 sp<EffectModule> effect;
6126 sp<EffectHandle> handle;
6127 status_t lStatus;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006128 sp<EffectChain> chain;
Eric Laurentde070132010-07-13 04:45:46 -07006129 bool chainCreated = false;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006130 bool effectCreated = false;
6131 bool effectRegistered = false;
6132
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006133 lStatus = initCheck();
6134 if (lStatus != NO_ERROR) {
Steve Block5ff1dd52012-01-05 23:22:43 +00006135 ALOGW("createEffect_l() Audio driver not initialized.");
Mathias Agopian65ab4712010-07-14 17:59:35 -07006136 goto Exit;
6137 }
6138
6139 // Do not allow effects with session ID 0 on direct output or duplicating threads
6140 // TODO: add rule for hw accelerated effects on direct outputs with non PCM format
Dima Zavinfce7a472011-04-19 22:30:36 -07006141 if (sessionId == AUDIO_SESSION_OUTPUT_MIX && mType != MIXER) {
Steve Block5ff1dd52012-01-05 23:22:43 +00006142 ALOGW("createEffect_l() Cannot add auxiliary effect %s to session %d",
Eric Laurentde070132010-07-13 04:45:46 -07006143 desc->name, sessionId);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006144 lStatus = BAD_VALUE;
6145 goto Exit;
6146 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006147 // Only Pre processor effects are allowed on input threads and only on input threads
Glenn Kastena1117922012-01-26 10:53:32 -08006148 if ((mType == RECORD) != ((desc->flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC)) {
Steve Block5ff1dd52012-01-05 23:22:43 +00006149 ALOGW("createEffect_l() effect %s (flags %08x) created on wrong thread type %d",
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006150 desc->name, desc->flags, mType);
6151 lStatus = BAD_VALUE;
6152 goto Exit;
6153 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07006154
Steve Block3856b092011-10-20 11:56:00 +01006155 ALOGV("createEffect_l() thread %p effect %s on session %d", this, desc->name, sessionId);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006156
6157 { // scope for mLock
6158 Mutex::Autolock _l(mLock);
6159
6160 // check for existing effect chain with the requested audio session
6161 chain = getEffectChain_l(sessionId);
6162 if (chain == 0) {
6163 // create a new chain for this session
Steve Block3856b092011-10-20 11:56:00 +01006164 ALOGV("createEffect_l() new effect chain for session %d", sessionId);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006165 chain = new EffectChain(this, sessionId);
6166 addEffectChain_l(chain);
Eric Laurentde070132010-07-13 04:45:46 -07006167 chain->setStrategy(getStrategyForSession_l(sessionId));
6168 chainCreated = true;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006169 } else {
Eric Laurentcab11242010-07-15 12:50:15 -07006170 effect = chain->getEffectFromDesc_l(desc);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006171 }
6172
Glenn Kasten7fc9a6f2012-01-10 10:46:34 -08006173 ALOGV("createEffect_l() got effect %p on chain %p", effect.get(), chain.get());
Mathias Agopian65ab4712010-07-14 17:59:35 -07006174
6175 if (effect == 0) {
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006176 int id = mAudioFlinger->nextUniqueId();
Mathias Agopian65ab4712010-07-14 17:59:35 -07006177 // Check CPU and memory usage
Eric Laurentde070132010-07-13 04:45:46 -07006178 lStatus = AudioSystem::registerEffect(desc, mId, chain->strategy(), sessionId, id);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006179 if (lStatus != NO_ERROR) {
6180 goto Exit;
6181 }
6182 effectRegistered = true;
6183 // create a new effect module if none present in the chain
Eric Laurentde070132010-07-13 04:45:46 -07006184 effect = new EffectModule(this, chain, desc, id, sessionId);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006185 lStatus = effect->status();
6186 if (lStatus != NO_ERROR) {
6187 goto Exit;
6188 }
Eric Laurentcab11242010-07-15 12:50:15 -07006189 lStatus = chain->addEffect_l(effect);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006190 if (lStatus != NO_ERROR) {
6191 goto Exit;
6192 }
6193 effectCreated = true;
6194
6195 effect->setDevice(mDevice);
6196 effect->setMode(mAudioFlinger->getMode());
6197 }
6198 // create effect handle and connect it to effect module
6199 handle = new EffectHandle(effect, client, effectClient, priority);
6200 lStatus = effect->addHandle(handle);
Glenn Kastena0d68332012-01-27 16:47:15 -08006201 if (enabled != NULL) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07006202 *enabled = (int)effect->isEnabled();
6203 }
6204 }
6205
6206Exit:
6207 if (lStatus != NO_ERROR && lStatus != ALREADY_EXISTS) {
Eric Laurentde070132010-07-13 04:45:46 -07006208 Mutex::Autolock _l(mLock);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006209 if (effectCreated) {
Eric Laurentde070132010-07-13 04:45:46 -07006210 chain->removeEffect_l(effect);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006211 }
6212 if (effectRegistered) {
Eric Laurentde070132010-07-13 04:45:46 -07006213 AudioSystem::unregisterEffect(effect->id());
6214 }
6215 if (chainCreated) {
6216 removeEffectChain_l(chain);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006217 }
6218 handle.clear();
6219 }
6220
6221 if(status) {
6222 *status = lStatus;
6223 }
6224 return handle;
6225}
6226
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006227sp<AudioFlinger::EffectModule> AudioFlinger::ThreadBase::getEffect_l(int sessionId, int effectId)
6228{
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006229 sp<EffectChain> chain = getEffectChain_l(sessionId);
Glenn Kasten090f0192012-01-30 13:00:02 -08006230 return chain != 0 ? chain->getEffectFromId_l(effectId) : 0;
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006231}
6232
Eric Laurentde070132010-07-13 04:45:46 -07006233// PlaybackThread::addEffect_l() must be called with AudioFlinger::mLock and
6234// PlaybackThread::mLock held
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006235status_t AudioFlinger::ThreadBase::addEffect_l(const sp<EffectModule>& effect)
Eric Laurentde070132010-07-13 04:45:46 -07006236{
6237 // check for existing effect chain with the requested audio session
6238 int sessionId = effect->sessionId();
6239 sp<EffectChain> chain = getEffectChain_l(sessionId);
6240 bool chainCreated = false;
6241
6242 if (chain == 0) {
6243 // create a new chain for this session
Steve Block3856b092011-10-20 11:56:00 +01006244 ALOGV("addEffect_l() new effect chain for session %d", sessionId);
Eric Laurentde070132010-07-13 04:45:46 -07006245 chain = new EffectChain(this, sessionId);
6246 addEffectChain_l(chain);
6247 chain->setStrategy(getStrategyForSession_l(sessionId));
6248 chainCreated = true;
6249 }
Steve Block3856b092011-10-20 11:56:00 +01006250 ALOGV("addEffect_l() %p chain %p effect %p", this, chain.get(), effect.get());
Eric Laurentde070132010-07-13 04:45:46 -07006251
6252 if (chain->getEffectFromId_l(effect->id()) != 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00006253 ALOGW("addEffect_l() %p effect %s already present in chain %p",
Eric Laurentde070132010-07-13 04:45:46 -07006254 this, effect->desc().name, chain.get());
6255 return BAD_VALUE;
6256 }
6257
6258 status_t status = chain->addEffect_l(effect);
6259 if (status != NO_ERROR) {
6260 if (chainCreated) {
6261 removeEffectChain_l(chain);
6262 }
6263 return status;
6264 }
6265
6266 effect->setDevice(mDevice);
6267 effect->setMode(mAudioFlinger->getMode());
6268 return NO_ERROR;
6269}
6270
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006271void AudioFlinger::ThreadBase::removeEffect_l(const sp<EffectModule>& effect) {
Eric Laurentde070132010-07-13 04:45:46 -07006272
Steve Block3856b092011-10-20 11:56:00 +01006273 ALOGV("removeEffect_l() %p effect %p", this, effect.get());
Mathias Agopian65ab4712010-07-14 17:59:35 -07006274 effect_descriptor_t desc = effect->desc();
Eric Laurentde070132010-07-13 04:45:46 -07006275 if ((desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
6276 detachAuxEffect_l(effect->id());
6277 }
6278
6279 sp<EffectChain> chain = effect->chain().promote();
6280 if (chain != 0) {
6281 // remove effect chain if removing last effect
6282 if (chain->removeEffect_l(effect) == 0) {
6283 removeEffectChain_l(chain);
6284 }
6285 } else {
Steve Block5ff1dd52012-01-05 23:22:43 +00006286 ALOGW("removeEffect_l() %p cannot promote chain for effect %p", this, effect.get());
Eric Laurentde070132010-07-13 04:45:46 -07006287 }
6288}
6289
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006290void AudioFlinger::ThreadBase::lockEffectChains_l(
6291 Vector<sp <AudioFlinger::EffectChain> >& effectChains)
6292{
6293 effectChains = mEffectChains;
6294 for (size_t i = 0; i < mEffectChains.size(); i++) {
6295 mEffectChains[i]->lock();
6296 }
6297}
6298
6299void AudioFlinger::ThreadBase::unlockEffectChains(
Glenn Kasten02fe1bf2012-02-24 15:42:17 -08006300 const Vector<sp <AudioFlinger::EffectChain> >& effectChains)
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006301{
6302 for (size_t i = 0; i < effectChains.size(); i++) {
6303 effectChains[i]->unlock();
6304 }
6305}
6306
6307sp<AudioFlinger::EffectChain> AudioFlinger::ThreadBase::getEffectChain(int sessionId)
6308{
6309 Mutex::Autolock _l(mLock);
6310 return getEffectChain_l(sessionId);
6311}
6312
6313sp<AudioFlinger::EffectChain> AudioFlinger::ThreadBase::getEffectChain_l(int sessionId)
6314{
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006315 size_t size = mEffectChains.size();
6316 for (size_t i = 0; i < size; i++) {
6317 if (mEffectChains[i]->sessionId() == sessionId) {
Glenn Kasten090f0192012-01-30 13:00:02 -08006318 return mEffectChains[i];
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006319 }
6320 }
Glenn Kasten090f0192012-01-30 13:00:02 -08006321 return 0;
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006322}
6323
Glenn Kastenf78aee72012-01-04 11:00:47 -08006324void AudioFlinger::ThreadBase::setMode(audio_mode_t mode)
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006325{
6326 Mutex::Autolock _l(mLock);
6327 size_t size = mEffectChains.size();
6328 for (size_t i = 0; i < size; i++) {
6329 mEffectChains[i]->setMode_l(mode);
6330 }
6331}
6332
6333void AudioFlinger::ThreadBase::disconnectEffect(const sp<EffectModule>& effect,
Marco Nelissen3a34bef2011-08-02 13:33:41 -07006334 const wp<EffectHandle>& handle,
Glenn Kasten58123c32012-02-03 10:32:24 -08006335 bool unpinIfLast) {
Eric Laurent59255e42011-07-27 19:49:51 -07006336
Mathias Agopian65ab4712010-07-14 17:59:35 -07006337 Mutex::Autolock _l(mLock);
Steve Block3856b092011-10-20 11:56:00 +01006338 ALOGV("disconnectEffect() %p effect %p", this, effect.get());
Mathias Agopian65ab4712010-07-14 17:59:35 -07006339 // delete the effect module if removing last handle on it
6340 if (effect->removeHandle(handle) == 0) {
Glenn Kasten58123c32012-02-03 10:32:24 -08006341 if (!effect->isPinned() || unpinIfLast) {
Marco Nelissen3a34bef2011-08-02 13:33:41 -07006342 removeEffect_l(effect);
6343 AudioSystem::unregisterEffect(effect->id());
6344 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07006345 }
6346}
6347
6348status_t AudioFlinger::PlaybackThread::addEffectChain_l(const sp<EffectChain>& chain)
6349{
6350 int session = chain->sessionId();
6351 int16_t *buffer = mMixBuffer;
6352 bool ownsBuffer = false;
6353
Steve Block3856b092011-10-20 11:56:00 +01006354 ALOGV("addEffectChain_l() %p on thread %p for session %d", chain.get(), this, session);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006355 if (session > 0) {
6356 // Only one effect chain can be present in direct output thread and it uses
6357 // the mix buffer as input
6358 if (mType != DIRECT) {
6359 size_t numSamples = mFrameCount * mChannelCount;
6360 buffer = new int16_t[numSamples];
6361 memset(buffer, 0, numSamples * sizeof(int16_t));
Steve Block3856b092011-10-20 11:56:00 +01006362 ALOGV("addEffectChain_l() creating new input buffer %p session %d", buffer, session);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006363 ownsBuffer = true;
6364 }
6365
6366 // Attach all tracks with same session ID to this chain.
6367 for (size_t i = 0; i < mTracks.size(); ++i) {
6368 sp<Track> track = mTracks[i];
6369 if (session == track->sessionId()) {
Steve Block3856b092011-10-20 11:56:00 +01006370 ALOGV("addEffectChain_l() track->setMainBuffer track %p buffer %p", track.get(), buffer);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006371 track->setMainBuffer(buffer);
Eric Laurentb469b942011-05-09 12:09:06 -07006372 chain->incTrackCnt();
Mathias Agopian65ab4712010-07-14 17:59:35 -07006373 }
6374 }
6375
6376 // indicate all active tracks in the chain
6377 for (size_t i = 0 ; i < mActiveTracks.size() ; ++i) {
6378 sp<Track> track = mActiveTracks[i].promote();
6379 if (track == 0) continue;
6380 if (session == track->sessionId()) {
Steve Block3856b092011-10-20 11:56:00 +01006381 ALOGV("addEffectChain_l() activating track %p on session %d", track.get(), session);
Eric Laurentb469b942011-05-09 12:09:06 -07006382 chain->incActiveTrackCnt();
Mathias Agopian65ab4712010-07-14 17:59:35 -07006383 }
6384 }
6385 }
6386
6387 chain->setInBuffer(buffer, ownsBuffer);
6388 chain->setOutBuffer(mMixBuffer);
Dima Zavinfce7a472011-04-19 22:30:36 -07006389 // Effect chain for session AUDIO_SESSION_OUTPUT_STAGE is inserted at end of effect
Eric Laurentde070132010-07-13 04:45:46 -07006390 // chains list in order to be processed last as it contains output stage effects
Dima Zavinfce7a472011-04-19 22:30:36 -07006391 // Effect chain for session AUDIO_SESSION_OUTPUT_MIX is inserted before
6392 // session AUDIO_SESSION_OUTPUT_STAGE to be processed
Mathias Agopian65ab4712010-07-14 17:59:35 -07006393 // after track specific effects and before output stage
Dima Zavinfce7a472011-04-19 22:30:36 -07006394 // It is therefore mandatory that AUDIO_SESSION_OUTPUT_MIX == 0 and
6395 // that AUDIO_SESSION_OUTPUT_STAGE < AUDIO_SESSION_OUTPUT_MIX
Eric Laurentde070132010-07-13 04:45:46 -07006396 // Effect chain for other sessions are inserted at beginning of effect
6397 // chains list to be processed before output mix effects. Relative order between other
6398 // sessions is not important
Mathias Agopian65ab4712010-07-14 17:59:35 -07006399 size_t size = mEffectChains.size();
6400 size_t i = 0;
6401 for (i = 0; i < size; i++) {
6402 if (mEffectChains[i]->sessionId() < session) break;
6403 }
6404 mEffectChains.insertAt(chain, i);
Eric Laurent59255e42011-07-27 19:49:51 -07006405 checkSuspendOnAddEffectChain_l(chain);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006406
6407 return NO_ERROR;
6408}
6409
6410size_t AudioFlinger::PlaybackThread::removeEffectChain_l(const sp<EffectChain>& chain)
6411{
6412 int session = chain->sessionId();
6413
Steve Block3856b092011-10-20 11:56:00 +01006414 ALOGV("removeEffectChain_l() %p from thread %p for session %d", chain.get(), this, session);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006415
6416 for (size_t i = 0; i < mEffectChains.size(); i++) {
6417 if (chain == mEffectChains[i]) {
6418 mEffectChains.removeAt(i);
Eric Laurentb469b942011-05-09 12:09:06 -07006419 // detach all active tracks from the chain
6420 for (size_t i = 0 ; i < mActiveTracks.size() ; ++i) {
6421 sp<Track> track = mActiveTracks[i].promote();
6422 if (track == 0) continue;
6423 if (session == track->sessionId()) {
Steve Block3856b092011-10-20 11:56:00 +01006424 ALOGV("removeEffectChain_l(): stopping track on chain %p for session Id: %d",
Eric Laurentb469b942011-05-09 12:09:06 -07006425 chain.get(), session);
6426 chain->decActiveTrackCnt();
6427 }
6428 }
6429
Mathias Agopian65ab4712010-07-14 17:59:35 -07006430 // detach all tracks with same session ID from this chain
6431 for (size_t i = 0; i < mTracks.size(); ++i) {
6432 sp<Track> track = mTracks[i];
6433 if (session == track->sessionId()) {
6434 track->setMainBuffer(mMixBuffer);
Eric Laurentb469b942011-05-09 12:09:06 -07006435 chain->decTrackCnt();
Mathias Agopian65ab4712010-07-14 17:59:35 -07006436 }
6437 }
Eric Laurentde070132010-07-13 04:45:46 -07006438 break;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006439 }
6440 }
6441 return mEffectChains.size();
6442}
6443
Eric Laurentde070132010-07-13 04:45:46 -07006444status_t AudioFlinger::PlaybackThread::attachAuxEffect(
6445 const sp<AudioFlinger::PlaybackThread::Track> track, int EffectId)
Mathias Agopian65ab4712010-07-14 17:59:35 -07006446{
6447 Mutex::Autolock _l(mLock);
6448 return attachAuxEffect_l(track, EffectId);
6449}
6450
Eric Laurentde070132010-07-13 04:45:46 -07006451status_t AudioFlinger::PlaybackThread::attachAuxEffect_l(
6452 const sp<AudioFlinger::PlaybackThread::Track> track, int EffectId)
Mathias Agopian65ab4712010-07-14 17:59:35 -07006453{
6454 status_t status = NO_ERROR;
6455
6456 if (EffectId == 0) {
6457 track->setAuxBuffer(0, NULL);
6458 } else {
Dima Zavinfce7a472011-04-19 22:30:36 -07006459 // Auxiliary effects are always in audio session AUDIO_SESSION_OUTPUT_MIX
6460 sp<EffectModule> effect = getEffect_l(AUDIO_SESSION_OUTPUT_MIX, EffectId);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006461 if (effect != 0) {
6462 if ((effect->desc().flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
6463 track->setAuxBuffer(EffectId, (int32_t *)effect->inBuffer());
6464 } else {
6465 status = INVALID_OPERATION;
6466 }
6467 } else {
6468 status = BAD_VALUE;
6469 }
6470 }
6471 return status;
6472}
6473
6474void AudioFlinger::PlaybackThread::detachAuxEffect_l(int effectId)
6475{
6476 for (size_t i = 0; i < mTracks.size(); ++i) {
6477 sp<Track> track = mTracks[i];
6478 if (track->auxEffectId() == effectId) {
6479 attachAuxEffect_l(track, 0);
6480 }
6481 }
6482}
6483
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006484status_t AudioFlinger::RecordThread::addEffectChain_l(const sp<EffectChain>& chain)
6485{
6486 // only one chain per input thread
6487 if (mEffectChains.size() != 0) {
6488 return INVALID_OPERATION;
6489 }
Steve Block3856b092011-10-20 11:56:00 +01006490 ALOGV("addEffectChain_l() %p on thread %p", chain.get(), this);
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006491
6492 chain->setInBuffer(NULL);
6493 chain->setOutBuffer(NULL);
6494
Eric Laurent59255e42011-07-27 19:49:51 -07006495 checkSuspendOnAddEffectChain_l(chain);
6496
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006497 mEffectChains.add(chain);
6498
6499 return NO_ERROR;
6500}
6501
6502size_t AudioFlinger::RecordThread::removeEffectChain_l(const sp<EffectChain>& chain)
6503{
Steve Block3856b092011-10-20 11:56:00 +01006504 ALOGV("removeEffectChain_l() %p from thread %p", chain.get(), this);
Steve Block5ff1dd52012-01-05 23:22:43 +00006505 ALOGW_IF(mEffectChains.size() != 1,
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006506 "removeEffectChain_l() %p invalid chain size %d on thread %p",
6507 chain.get(), mEffectChains.size(), this);
6508 if (mEffectChains.size() == 1) {
6509 mEffectChains.removeAt(0);
6510 }
6511 return 0;
6512}
6513
Mathias Agopian65ab4712010-07-14 17:59:35 -07006514// ----------------------------------------------------------------------------
6515// EffectModule implementation
6516// ----------------------------------------------------------------------------
6517
6518#undef LOG_TAG
6519#define LOG_TAG "AudioFlinger::EffectModule"
6520
Glenn Kasten9eaa5572012-01-20 13:32:16 -08006521AudioFlinger::EffectModule::EffectModule(ThreadBase *thread,
Mathias Agopian65ab4712010-07-14 17:59:35 -07006522 const wp<AudioFlinger::EffectChain>& chain,
6523 effect_descriptor_t *desc,
6524 int id,
6525 int sessionId)
Glenn Kasten9eaa5572012-01-20 13:32:16 -08006526 : mThread(thread), mChain(chain), mId(id), mSessionId(sessionId), mEffectInterface(NULL),
Eric Laurent59255e42011-07-27 19:49:51 -07006527 mStatus(NO_INIT), mState(IDLE), mSuspended(false)
Mathias Agopian65ab4712010-07-14 17:59:35 -07006528{
Steve Block3856b092011-10-20 11:56:00 +01006529 ALOGV("Constructor %p", this);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006530 int lStatus;
Glenn Kasten9eaa5572012-01-20 13:32:16 -08006531 if (thread == NULL) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07006532 return;
6533 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07006534
6535 memcpy(&mDescriptor, desc, sizeof(effect_descriptor_t));
6536
6537 // create effect engine from effect factory
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006538 mStatus = EffectCreate(&desc->uuid, sessionId, thread->id(), &mEffectInterface);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006539
6540 if (mStatus != NO_ERROR) {
6541 return;
6542 }
6543 lStatus = init();
6544 if (lStatus < 0) {
6545 mStatus = lStatus;
6546 goto Error;
6547 }
6548
Marco Nelissen3a34bef2011-08-02 13:33:41 -07006549 if (mSessionId > AUDIO_SESSION_OUTPUT_MIX) {
6550 mPinned = true;
6551 }
Steve Block3856b092011-10-20 11:56:00 +01006552 ALOGV("Constructor success name %s, Interface %p", mDescriptor.name, mEffectInterface);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006553 return;
6554Error:
6555 EffectRelease(mEffectInterface);
6556 mEffectInterface = NULL;
Steve Block3856b092011-10-20 11:56:00 +01006557 ALOGV("Constructor Error %d", mStatus);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006558}
6559
6560AudioFlinger::EffectModule::~EffectModule()
6561{
Steve Block3856b092011-10-20 11:56:00 +01006562 ALOGV("Destructor %p", this);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006563 if (mEffectInterface != NULL) {
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006564 if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC ||
6565 (mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_POST_PROC) {
6566 sp<ThreadBase> thread = mThread.promote();
6567 if (thread != 0) {
Eric Laurentb8ba0a92011-08-07 16:32:26 -07006568 audio_stream_t *stream = thread->stream();
6569 if (stream != NULL) {
6570 stream->remove_audio_effect(stream, mEffectInterface);
6571 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006572 }
6573 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07006574 // release effect engine
6575 EffectRelease(mEffectInterface);
6576 }
6577}
6578
Glenn Kasten435dbe62012-01-30 10:15:48 -08006579status_t AudioFlinger::EffectModule::addHandle(const sp<EffectHandle>& handle)
Mathias Agopian65ab4712010-07-14 17:59:35 -07006580{
6581 status_t status;
6582
6583 Mutex::Autolock _l(mLock);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006584 int priority = handle->priority();
6585 size_t size = mHandles.size();
6586 sp<EffectHandle> h;
6587 size_t i;
6588 for (i = 0; i < size; i++) {
6589 h = mHandles[i].promote();
6590 if (h == 0) continue;
6591 if (h->priority() <= priority) break;
6592 }
6593 // if inserted in first place, move effect control from previous owner to this handle
6594 if (i == 0) {
Eric Laurent59255e42011-07-27 19:49:51 -07006595 bool enabled = false;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006596 if (h != 0) {
Eric Laurent59255e42011-07-27 19:49:51 -07006597 enabled = h->enabled();
6598 h->setControl(false/*hasControl*/, true /*signal*/, enabled /*enabled*/);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006599 }
Eric Laurent59255e42011-07-27 19:49:51 -07006600 handle->setControl(true /*hasControl*/, false /*signal*/, enabled /*enabled*/);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006601 status = NO_ERROR;
6602 } else {
6603 status = ALREADY_EXISTS;
6604 }
Steve Block3856b092011-10-20 11:56:00 +01006605 ALOGV("addHandle() %p added handle %p in position %d", this, handle.get(), i);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006606 mHandles.insertAt(handle, i);
6607 return status;
6608}
6609
6610size_t AudioFlinger::EffectModule::removeHandle(const wp<EffectHandle>& handle)
6611{
6612 Mutex::Autolock _l(mLock);
6613 size_t size = mHandles.size();
6614 size_t i;
6615 for (i = 0; i < size; i++) {
6616 if (mHandles[i] == handle) break;
6617 }
6618 if (i == size) {
6619 return size;
6620 }
Steve Block3856b092011-10-20 11:56:00 +01006621 ALOGV("removeHandle() %p removed handle %p in position %d", this, handle.unsafe_get(), i);
Eric Laurent59255e42011-07-27 19:49:51 -07006622
6623 bool enabled = false;
6624 EffectHandle *hdl = handle.unsafe_get();
Glenn Kastena0d68332012-01-27 16:47:15 -08006625 if (hdl != NULL) {
Steve Block3856b092011-10-20 11:56:00 +01006626 ALOGV("removeHandle() unsafe_get OK");
Eric Laurent59255e42011-07-27 19:49:51 -07006627 enabled = hdl->enabled();
6628 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07006629 mHandles.removeAt(i);
6630 size = mHandles.size();
6631 // if removed from first place, move effect control from this handle to next in line
6632 if (i == 0 && size != 0) {
6633 sp<EffectHandle> h = mHandles[0].promote();
6634 if (h != 0) {
Eric Laurent59255e42011-07-27 19:49:51 -07006635 h->setControl(true /*hasControl*/, true /*signal*/ , enabled /*enabled*/);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006636 }
6637 }
6638
Eric Laurentec437d82011-07-26 20:54:46 -07006639 // Prevent calls to process() and other functions on effect interface from now on.
6640 // The effect engine will be released by the destructor when the last strong reference on
6641 // this object is released which can happen after next process is called.
Marco Nelissen3a34bef2011-08-02 13:33:41 -07006642 if (size == 0 && !mPinned) {
Eric Laurentec437d82011-07-26 20:54:46 -07006643 mState = DESTROYED;
Eric Laurentdac69112010-09-28 14:09:57 -07006644 }
6645
Mathias Agopian65ab4712010-07-14 17:59:35 -07006646 return size;
6647}
6648
Eric Laurent59255e42011-07-27 19:49:51 -07006649sp<AudioFlinger::EffectHandle> AudioFlinger::EffectModule::controlHandle()
6650{
6651 Mutex::Autolock _l(mLock);
Glenn Kasten090f0192012-01-30 13:00:02 -08006652 return mHandles.size() != 0 ? mHandles[0].promote() : 0;
Eric Laurent59255e42011-07-27 19:49:51 -07006653}
6654
Glenn Kasten58123c32012-02-03 10:32:24 -08006655void AudioFlinger::EffectModule::disconnect(const wp<EffectHandle>& handle, bool unpinIfLast)
Mathias Agopian65ab4712010-07-14 17:59:35 -07006656{
Glenn Kasten90bebef2012-01-27 15:24:38 -08006657 ALOGV("disconnect() %p handle %p", this, handle.unsafe_get());
Mathias Agopian65ab4712010-07-14 17:59:35 -07006658 // keep a strong reference on this EffectModule to avoid calling the
6659 // destructor before we exit
6660 sp<EffectModule> keep(this);
6661 {
6662 sp<ThreadBase> thread = mThread.promote();
6663 if (thread != 0) {
Glenn Kasten58123c32012-02-03 10:32:24 -08006664 thread->disconnectEffect(keep, handle, unpinIfLast);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006665 }
6666 }
6667}
6668
6669void AudioFlinger::EffectModule::updateState() {
6670 Mutex::Autolock _l(mLock);
6671
6672 switch (mState) {
6673 case RESTART:
6674 reset_l();
6675 // FALL THROUGH
6676
6677 case STARTING:
6678 // clear auxiliary effect input buffer for next accumulation
6679 if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
6680 memset(mConfig.inputCfg.buffer.raw,
6681 0,
6682 mConfig.inputCfg.buffer.frameCount*sizeof(int32_t));
6683 }
6684 start_l();
6685 mState = ACTIVE;
6686 break;
6687 case STOPPING:
6688 stop_l();
6689 mDisableWaitCnt = mMaxDisableWaitCnt;
6690 mState = STOPPED;
6691 break;
6692 case STOPPED:
6693 // mDisableWaitCnt is forced to 1 by process() when the engine indicates the end of the
6694 // turn off sequence.
6695 if (--mDisableWaitCnt == 0) {
6696 reset_l();
6697 mState = IDLE;
6698 }
6699 break;
Eric Laurentec437d82011-07-26 20:54:46 -07006700 default: //IDLE , ACTIVE, DESTROYED
Mathias Agopian65ab4712010-07-14 17:59:35 -07006701 break;
6702 }
6703}
6704
6705void AudioFlinger::EffectModule::process()
6706{
6707 Mutex::Autolock _l(mLock);
6708
Eric Laurentec437d82011-07-26 20:54:46 -07006709 if (mState == DESTROYED || mEffectInterface == NULL ||
Mathias Agopian65ab4712010-07-14 17:59:35 -07006710 mConfig.inputCfg.buffer.raw == NULL ||
6711 mConfig.outputCfg.buffer.raw == NULL) {
6712 return;
6713 }
6714
Eric Laurent8f45bd72010-08-31 13:50:07 -07006715 if (isProcessEnabled()) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07006716 // do 32 bit to 16 bit conversion for auxiliary effect input buffer
6717 if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
Glenn Kasten3b21c502011-12-15 09:52:39 -08006718 ditherAndClamp(mConfig.inputCfg.buffer.s32,
Mathias Agopian65ab4712010-07-14 17:59:35 -07006719 mConfig.inputCfg.buffer.s32,
Eric Laurentde070132010-07-13 04:45:46 -07006720 mConfig.inputCfg.buffer.frameCount/2);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006721 }
6722
6723 // do the actual processing in the effect engine
6724 int ret = (*mEffectInterface)->process(mEffectInterface,
6725 &mConfig.inputCfg.buffer,
6726 &mConfig.outputCfg.buffer);
6727
6728 // force transition to IDLE state when engine is ready
6729 if (mState == STOPPED && ret == -ENODATA) {
6730 mDisableWaitCnt = 1;
6731 }
6732
6733 // clear auxiliary effect input buffer for next accumulation
6734 if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
Eric Laurent73337482011-01-19 18:36:13 -08006735 memset(mConfig.inputCfg.buffer.raw, 0,
6736 mConfig.inputCfg.buffer.frameCount*sizeof(int32_t));
Mathias Agopian65ab4712010-07-14 17:59:35 -07006737 }
6738 } else if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_INSERT &&
Eric Laurent73337482011-01-19 18:36:13 -08006739 mConfig.inputCfg.buffer.raw != mConfig.outputCfg.buffer.raw) {
6740 // If an insert effect is idle and input buffer is different from output buffer,
6741 // accumulate input onto output
Mathias Agopian65ab4712010-07-14 17:59:35 -07006742 sp<EffectChain> chain = mChain.promote();
Eric Laurentb469b942011-05-09 12:09:06 -07006743 if (chain != 0 && chain->activeTrackCnt() != 0) {
Eric Laurent73337482011-01-19 18:36:13 -08006744 size_t frameCnt = mConfig.inputCfg.buffer.frameCount * 2; //always stereo here
6745 int16_t *in = mConfig.inputCfg.buffer.s16;
6746 int16_t *out = mConfig.outputCfg.buffer.s16;
6747 for (size_t i = 0; i < frameCnt; i++) {
6748 out[i] = clamp16((int32_t)out[i] + (int32_t)in[i]);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006749 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07006750 }
6751 }
6752}
6753
6754void AudioFlinger::EffectModule::reset_l()
6755{
6756 if (mEffectInterface == NULL) {
6757 return;
6758 }
6759 (*mEffectInterface)->command(mEffectInterface, EFFECT_CMD_RESET, 0, NULL, 0, NULL);
6760}
6761
6762status_t AudioFlinger::EffectModule::configure()
6763{
6764 uint32_t channels;
6765 if (mEffectInterface == NULL) {
6766 return NO_INIT;
6767 }
6768
6769 sp<ThreadBase> thread = mThread.promote();
6770 if (thread == 0) {
6771 return DEAD_OBJECT;
6772 }
6773
6774 // TODO: handle configuration of effects replacing track process
6775 if (thread->channelCount() == 1) {
Eric Laurente1315cf2011-05-17 19:16:02 -07006776 channels = AUDIO_CHANNEL_OUT_MONO;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006777 } else {
Eric Laurente1315cf2011-05-17 19:16:02 -07006778 channels = AUDIO_CHANNEL_OUT_STEREO;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006779 }
6780
6781 if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
Eric Laurente1315cf2011-05-17 19:16:02 -07006782 mConfig.inputCfg.channels = AUDIO_CHANNEL_OUT_MONO;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006783 } else {
6784 mConfig.inputCfg.channels = channels;
6785 }
6786 mConfig.outputCfg.channels = channels;
Eric Laurente1315cf2011-05-17 19:16:02 -07006787 mConfig.inputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
6788 mConfig.outputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006789 mConfig.inputCfg.samplingRate = thread->sampleRate();
6790 mConfig.outputCfg.samplingRate = mConfig.inputCfg.samplingRate;
6791 mConfig.inputCfg.bufferProvider.cookie = NULL;
6792 mConfig.inputCfg.bufferProvider.getBuffer = NULL;
6793 mConfig.inputCfg.bufferProvider.releaseBuffer = NULL;
6794 mConfig.outputCfg.bufferProvider.cookie = NULL;
6795 mConfig.outputCfg.bufferProvider.getBuffer = NULL;
6796 mConfig.outputCfg.bufferProvider.releaseBuffer = NULL;
6797 mConfig.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ;
6798 // Insert effect:
Dima Zavinfce7a472011-04-19 22:30:36 -07006799 // - in session AUDIO_SESSION_OUTPUT_MIX or AUDIO_SESSION_OUTPUT_STAGE,
Eric Laurentde070132010-07-13 04:45:46 -07006800 // always overwrites output buffer: input buffer == output buffer
Mathias Agopian65ab4712010-07-14 17:59:35 -07006801 // - in other sessions:
6802 // last effect in the chain accumulates in output buffer: input buffer != output buffer
6803 // other effect: overwrites output buffer: input buffer == output buffer
6804 // Auxiliary effect:
6805 // accumulates in output buffer: input buffer != output buffer
6806 // Therefore: accumulate <=> input buffer != output buffer
6807 if (mConfig.inputCfg.buffer.raw != mConfig.outputCfg.buffer.raw) {
6808 mConfig.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_ACCUMULATE;
6809 } else {
6810 mConfig.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_WRITE;
6811 }
6812 mConfig.inputCfg.mask = EFFECT_CONFIG_ALL;
6813 mConfig.outputCfg.mask = EFFECT_CONFIG_ALL;
6814 mConfig.inputCfg.buffer.frameCount = thread->frameCount();
6815 mConfig.outputCfg.buffer.frameCount = mConfig.inputCfg.buffer.frameCount;
6816
Steve Block3856b092011-10-20 11:56:00 +01006817 ALOGV("configure() %p thread %p buffer %p framecount %d",
Eric Laurentde070132010-07-13 04:45:46 -07006818 this, thread.get(), mConfig.inputCfg.buffer.raw, mConfig.inputCfg.buffer.frameCount);
6819
Mathias Agopian65ab4712010-07-14 17:59:35 -07006820 status_t cmdStatus;
Eric Laurent25f43952010-07-28 05:40:18 -07006821 uint32_t size = sizeof(int);
6822 status_t status = (*mEffectInterface)->command(mEffectInterface,
Eric Laurent3d5188b2011-12-16 15:30:36 -08006823 EFFECT_CMD_SET_CONFIG,
Eric Laurent25f43952010-07-28 05:40:18 -07006824 sizeof(effect_config_t),
6825 &mConfig,
6826 &size,
6827 &cmdStatus);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006828 if (status == 0) {
6829 status = cmdStatus;
6830 }
6831
6832 mMaxDisableWaitCnt = (MAX_DISABLE_TIME_MS * mConfig.outputCfg.samplingRate) /
6833 (1000 * mConfig.outputCfg.buffer.frameCount);
6834
6835 return status;
6836}
6837
6838status_t AudioFlinger::EffectModule::init()
6839{
6840 Mutex::Autolock _l(mLock);
6841 if (mEffectInterface == NULL) {
6842 return NO_INIT;
6843 }
6844 status_t cmdStatus;
Eric Laurent25f43952010-07-28 05:40:18 -07006845 uint32_t size = sizeof(status_t);
6846 status_t status = (*mEffectInterface)->command(mEffectInterface,
6847 EFFECT_CMD_INIT,
6848 0,
6849 NULL,
6850 &size,
6851 &cmdStatus);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006852 if (status == 0) {
6853 status = cmdStatus;
6854 }
6855 return status;
6856}
6857
Eric Laurentec35a142011-10-05 17:42:25 -07006858status_t AudioFlinger::EffectModule::start()
6859{
6860 Mutex::Autolock _l(mLock);
6861 return start_l();
6862}
6863
Mathias Agopian65ab4712010-07-14 17:59:35 -07006864status_t AudioFlinger::EffectModule::start_l()
6865{
6866 if (mEffectInterface == NULL) {
6867 return NO_INIT;
6868 }
6869 status_t cmdStatus;
Eric Laurent25f43952010-07-28 05:40:18 -07006870 uint32_t size = sizeof(status_t);
6871 status_t status = (*mEffectInterface)->command(mEffectInterface,
6872 EFFECT_CMD_ENABLE,
6873 0,
6874 NULL,
6875 &size,
6876 &cmdStatus);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006877 if (status == 0) {
6878 status = cmdStatus;
6879 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006880 if (status == 0 &&
6881 ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC ||
6882 (mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_POST_PROC)) {
6883 sp<ThreadBase> thread = mThread.promote();
6884 if (thread != 0) {
Eric Laurentb8ba0a92011-08-07 16:32:26 -07006885 audio_stream_t *stream = thread->stream();
6886 if (stream != NULL) {
6887 stream->add_audio_effect(stream, mEffectInterface);
6888 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006889 }
6890 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07006891 return status;
6892}
6893
Eric Laurentec437d82011-07-26 20:54:46 -07006894status_t AudioFlinger::EffectModule::stop()
6895{
6896 Mutex::Autolock _l(mLock);
6897 return stop_l();
6898}
6899
Mathias Agopian65ab4712010-07-14 17:59:35 -07006900status_t AudioFlinger::EffectModule::stop_l()
6901{
6902 if (mEffectInterface == NULL) {
6903 return NO_INIT;
6904 }
6905 status_t cmdStatus;
Eric Laurent25f43952010-07-28 05:40:18 -07006906 uint32_t size = sizeof(status_t);
6907 status_t status = (*mEffectInterface)->command(mEffectInterface,
6908 EFFECT_CMD_DISABLE,
6909 0,
6910 NULL,
6911 &size,
6912 &cmdStatus);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006913 if (status == 0) {
6914 status = cmdStatus;
6915 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006916 if (status == 0 &&
6917 ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC ||
6918 (mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_POST_PROC)) {
6919 sp<ThreadBase> thread = mThread.promote();
6920 if (thread != 0) {
Eric Laurentb8ba0a92011-08-07 16:32:26 -07006921 audio_stream_t *stream = thread->stream();
6922 if (stream != NULL) {
6923 stream->remove_audio_effect(stream, mEffectInterface);
6924 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006925 }
6926 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07006927 return status;
6928}
6929
Eric Laurent25f43952010-07-28 05:40:18 -07006930status_t AudioFlinger::EffectModule::command(uint32_t cmdCode,
6931 uint32_t cmdSize,
6932 void *pCmdData,
6933 uint32_t *replySize,
6934 void *pReplyData)
Mathias Agopian65ab4712010-07-14 17:59:35 -07006935{
6936 Mutex::Autolock _l(mLock);
Steve Block3856b092011-10-20 11:56:00 +01006937// ALOGV("command(), cmdCode: %d, mEffectInterface: %p", cmdCode, mEffectInterface);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006938
Eric Laurentec437d82011-07-26 20:54:46 -07006939 if (mState == DESTROYED || mEffectInterface == NULL) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07006940 return NO_INIT;
6941 }
Eric Laurent25f43952010-07-28 05:40:18 -07006942 status_t status = (*mEffectInterface)->command(mEffectInterface,
6943 cmdCode,
6944 cmdSize,
6945 pCmdData,
6946 replySize,
6947 pReplyData);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006948 if (cmdCode != EFFECT_CMD_GET_PARAM && status == NO_ERROR) {
Eric Laurent25f43952010-07-28 05:40:18 -07006949 uint32_t size = (replySize == NULL) ? 0 : *replySize;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006950 for (size_t i = 1; i < mHandles.size(); i++) {
6951 sp<EffectHandle> h = mHandles[i].promote();
6952 if (h != 0) {
6953 h->commandExecuted(cmdCode, cmdSize, pCmdData, size, pReplyData);
6954 }
6955 }
6956 }
6957 return status;
6958}
6959
6960status_t AudioFlinger::EffectModule::setEnabled(bool enabled)
6961{
Eric Laurentdb7c0792011-08-10 10:37:50 -07006962
Mathias Agopian65ab4712010-07-14 17:59:35 -07006963 Mutex::Autolock _l(mLock);
Steve Block3856b092011-10-20 11:56:00 +01006964 ALOGV("setEnabled %p enabled %d", this, enabled);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006965
6966 if (enabled != isEnabled()) {
Eric Laurentdb7c0792011-08-10 10:37:50 -07006967 status_t status = AudioSystem::setEffectEnabled(mId, enabled);
6968 if (enabled && status != NO_ERROR) {
6969 return status;
6970 }
6971
Mathias Agopian65ab4712010-07-14 17:59:35 -07006972 switch (mState) {
6973 // going from disabled to enabled
6974 case IDLE:
6975 mState = STARTING;
6976 break;
6977 case STOPPED:
6978 mState = RESTART;
6979 break;
6980 case STOPPING:
6981 mState = ACTIVE;
6982 break;
6983
6984 // going from enabled to disabled
6985 case RESTART:
Eric Laurent8f45bd72010-08-31 13:50:07 -07006986 mState = STOPPED;
6987 break;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006988 case STARTING:
6989 mState = IDLE;
6990 break;
6991 case ACTIVE:
6992 mState = STOPPING;
6993 break;
Eric Laurentec437d82011-07-26 20:54:46 -07006994 case DESTROYED:
6995 return NO_ERROR; // simply ignore as we are being destroyed
Mathias Agopian65ab4712010-07-14 17:59:35 -07006996 }
6997 for (size_t i = 1; i < mHandles.size(); i++) {
6998 sp<EffectHandle> h = mHandles[i].promote();
6999 if (h != 0) {
7000 h->setEnabled(enabled);
7001 }
7002 }
7003 }
7004 return NO_ERROR;
7005}
7006
Glenn Kastenc59c0042012-02-02 14:06:11 -08007007bool AudioFlinger::EffectModule::isEnabled() const
Mathias Agopian65ab4712010-07-14 17:59:35 -07007008{
7009 switch (mState) {
7010 case RESTART:
7011 case STARTING:
7012 case ACTIVE:
7013 return true;
7014 case IDLE:
7015 case STOPPING:
7016 case STOPPED:
Eric Laurentec437d82011-07-26 20:54:46 -07007017 case DESTROYED:
Mathias Agopian65ab4712010-07-14 17:59:35 -07007018 default:
7019 return false;
7020 }
7021}
7022
Glenn Kastenc59c0042012-02-02 14:06:11 -08007023bool AudioFlinger::EffectModule::isProcessEnabled() const
Eric Laurent8f45bd72010-08-31 13:50:07 -07007024{
7025 switch (mState) {
7026 case RESTART:
7027 case ACTIVE:
7028 case STOPPING:
7029 case STOPPED:
7030 return true;
7031 case IDLE:
7032 case STARTING:
Eric Laurentec437d82011-07-26 20:54:46 -07007033 case DESTROYED:
Eric Laurent8f45bd72010-08-31 13:50:07 -07007034 default:
7035 return false;
7036 }
7037}
7038
Mathias Agopian65ab4712010-07-14 17:59:35 -07007039status_t AudioFlinger::EffectModule::setVolume(uint32_t *left, uint32_t *right, bool controller)
7040{
7041 Mutex::Autolock _l(mLock);
7042 status_t status = NO_ERROR;
7043
7044 // Send volume indication if EFFECT_FLAG_VOLUME_IND is set and read back altered volume
7045 // if controller flag is set (Note that controller == TRUE => EFFECT_FLAG_VOLUME_CTRL set)
Eric Laurent8f45bd72010-08-31 13:50:07 -07007046 if (isProcessEnabled() &&
Eric Laurentf997cab2010-07-19 06:24:46 -07007047 ((mDescriptor.flags & EFFECT_FLAG_VOLUME_MASK) == EFFECT_FLAG_VOLUME_CTRL ||
7048 (mDescriptor.flags & EFFECT_FLAG_VOLUME_MASK) == EFFECT_FLAG_VOLUME_IND)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07007049 status_t cmdStatus;
7050 uint32_t volume[2];
7051 uint32_t *pVolume = NULL;
Eric Laurent25f43952010-07-28 05:40:18 -07007052 uint32_t size = sizeof(volume);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007053 volume[0] = *left;
7054 volume[1] = *right;
7055 if (controller) {
7056 pVolume = volume;
7057 }
Eric Laurent25f43952010-07-28 05:40:18 -07007058 status = (*mEffectInterface)->command(mEffectInterface,
7059 EFFECT_CMD_SET_VOLUME,
7060 size,
7061 volume,
7062 &size,
7063 pVolume);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007064 if (controller && status == NO_ERROR && size == sizeof(volume)) {
7065 *left = volume[0];
7066 *right = volume[1];
7067 }
7068 }
7069 return status;
7070}
7071
7072status_t AudioFlinger::EffectModule::setDevice(uint32_t device)
7073{
7074 Mutex::Autolock _l(mLock);
7075 status_t status = NO_ERROR;
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007076 if (device && (mDescriptor.flags & EFFECT_FLAG_DEVICE_MASK) == EFFECT_FLAG_DEVICE_IND) {
7077 // audio pre processing modules on RecordThread can receive both output and
7078 // input device indication in the same call
7079 uint32_t dev = device & AUDIO_DEVICE_OUT_ALL;
7080 if (dev) {
7081 status_t cmdStatus;
7082 uint32_t size = sizeof(status_t);
7083
7084 status = (*mEffectInterface)->command(mEffectInterface,
7085 EFFECT_CMD_SET_DEVICE,
7086 sizeof(uint32_t),
7087 &dev,
7088 &size,
7089 &cmdStatus);
7090 if (status == NO_ERROR) {
7091 status = cmdStatus;
7092 }
7093 }
7094 dev = device & AUDIO_DEVICE_IN_ALL;
7095 if (dev) {
7096 status_t cmdStatus;
7097 uint32_t size = sizeof(status_t);
7098
7099 status_t status2 = (*mEffectInterface)->command(mEffectInterface,
7100 EFFECT_CMD_SET_INPUT_DEVICE,
7101 sizeof(uint32_t),
7102 &dev,
7103 &size,
7104 &cmdStatus);
7105 if (status2 == NO_ERROR) {
7106 status2 = cmdStatus;
7107 }
7108 if (status == NO_ERROR) {
7109 status = status2;
7110 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07007111 }
7112 }
7113 return status;
7114}
7115
Glenn Kastenf78aee72012-01-04 11:00:47 -08007116status_t AudioFlinger::EffectModule::setMode(audio_mode_t mode)
Mathias Agopian65ab4712010-07-14 17:59:35 -07007117{
7118 Mutex::Autolock _l(mLock);
7119 status_t status = NO_ERROR;
7120 if ((mDescriptor.flags & EFFECT_FLAG_AUDIO_MODE_MASK) == EFFECT_FLAG_AUDIO_MODE_IND) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07007121 status_t cmdStatus;
Eric Laurent25f43952010-07-28 05:40:18 -07007122 uint32_t size = sizeof(status_t);
7123 status = (*mEffectInterface)->command(mEffectInterface,
7124 EFFECT_CMD_SET_AUDIO_MODE,
Glenn Kastenf78aee72012-01-04 11:00:47 -08007125 sizeof(audio_mode_t),
Eric Laurente1315cf2011-05-17 19:16:02 -07007126 &mode,
Eric Laurent25f43952010-07-28 05:40:18 -07007127 &size,
7128 &cmdStatus);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007129 if (status == NO_ERROR) {
7130 status = cmdStatus;
7131 }
7132 }
7133 return status;
7134}
7135
Eric Laurent59255e42011-07-27 19:49:51 -07007136void AudioFlinger::EffectModule::setSuspended(bool suspended)
7137{
7138 Mutex::Autolock _l(mLock);
7139 mSuspended = suspended;
7140}
Glenn Kastena3a85482012-01-04 11:01:11 -08007141
7142bool AudioFlinger::EffectModule::suspended() const
Eric Laurent59255e42011-07-27 19:49:51 -07007143{
7144 Mutex::Autolock _l(mLock);
7145 return mSuspended;
7146}
7147
Mathias Agopian65ab4712010-07-14 17:59:35 -07007148status_t AudioFlinger::EffectModule::dump(int fd, const Vector<String16>& args)
7149{
7150 const size_t SIZE = 256;
7151 char buffer[SIZE];
7152 String8 result;
7153
7154 snprintf(buffer, SIZE, "\tEffect ID %d:\n", mId);
7155 result.append(buffer);
7156
7157 bool locked = tryLock(mLock);
7158 // failed to lock - AudioFlinger is probably deadlocked
7159 if (!locked) {
7160 result.append("\t\tCould not lock Fx mutex:\n");
7161 }
7162
7163 result.append("\t\tSession Status State Engine:\n");
7164 snprintf(buffer, SIZE, "\t\t%05d %03d %03d 0x%08x\n",
7165 mSessionId, mStatus, mState, (uint32_t)mEffectInterface);
7166 result.append(buffer);
7167
7168 result.append("\t\tDescriptor:\n");
7169 snprintf(buffer, SIZE, "\t\t- UUID: %08X-%04X-%04X-%04X-%02X%02X%02X%02X%02X%02X\n",
7170 mDescriptor.uuid.timeLow, mDescriptor.uuid.timeMid, mDescriptor.uuid.timeHiAndVersion,
7171 mDescriptor.uuid.clockSeq, mDescriptor.uuid.node[0], mDescriptor.uuid.node[1],mDescriptor.uuid.node[2],
7172 mDescriptor.uuid.node[3],mDescriptor.uuid.node[4],mDescriptor.uuid.node[5]);
7173 result.append(buffer);
7174 snprintf(buffer, SIZE, "\t\t- TYPE: %08X-%04X-%04X-%04X-%02X%02X%02X%02X%02X%02X\n",
7175 mDescriptor.type.timeLow, mDescriptor.type.timeMid, mDescriptor.type.timeHiAndVersion,
7176 mDescriptor.type.clockSeq, mDescriptor.type.node[0], mDescriptor.type.node[1],mDescriptor.type.node[2],
7177 mDescriptor.type.node[3],mDescriptor.type.node[4],mDescriptor.type.node[5]);
7178 result.append(buffer);
Eric Laurente1315cf2011-05-17 19:16:02 -07007179 snprintf(buffer, SIZE, "\t\t- apiVersion: %08X\n\t\t- flags: %08X\n",
Mathias Agopian65ab4712010-07-14 17:59:35 -07007180 mDescriptor.apiVersion,
7181 mDescriptor.flags);
7182 result.append(buffer);
7183 snprintf(buffer, SIZE, "\t\t- name: %s\n",
7184 mDescriptor.name);
7185 result.append(buffer);
7186 snprintf(buffer, SIZE, "\t\t- implementor: %s\n",
7187 mDescriptor.implementor);
7188 result.append(buffer);
7189
7190 result.append("\t\t- Input configuration:\n");
7191 result.append("\t\t\tBuffer Frames Smp rate Channels Format\n");
7192 snprintf(buffer, SIZE, "\t\t\t0x%08x %05d %05d %08x %d\n",
7193 (uint32_t)mConfig.inputCfg.buffer.raw,
7194 mConfig.inputCfg.buffer.frameCount,
7195 mConfig.inputCfg.samplingRate,
7196 mConfig.inputCfg.channels,
7197 mConfig.inputCfg.format);
7198 result.append(buffer);
7199
7200 result.append("\t\t- Output configuration:\n");
7201 result.append("\t\t\tBuffer Frames Smp rate Channels Format\n");
7202 snprintf(buffer, SIZE, "\t\t\t0x%08x %05d %05d %08x %d\n",
7203 (uint32_t)mConfig.outputCfg.buffer.raw,
7204 mConfig.outputCfg.buffer.frameCount,
7205 mConfig.outputCfg.samplingRate,
7206 mConfig.outputCfg.channels,
7207 mConfig.outputCfg.format);
7208 result.append(buffer);
7209
7210 snprintf(buffer, SIZE, "\t\t%d Clients:\n", mHandles.size());
7211 result.append(buffer);
7212 result.append("\t\t\tPid Priority Ctrl Locked client server\n");
7213 for (size_t i = 0; i < mHandles.size(); ++i) {
7214 sp<EffectHandle> handle = mHandles[i].promote();
7215 if (handle != 0) {
7216 handle->dump(buffer, SIZE);
7217 result.append(buffer);
7218 }
7219 }
7220
7221 result.append("\n");
7222
7223 write(fd, result.string(), result.length());
7224
7225 if (locked) {
7226 mLock.unlock();
7227 }
7228
7229 return NO_ERROR;
7230}
7231
7232// ----------------------------------------------------------------------------
7233// EffectHandle implementation
7234// ----------------------------------------------------------------------------
7235
7236#undef LOG_TAG
7237#define LOG_TAG "AudioFlinger::EffectHandle"
7238
7239AudioFlinger::EffectHandle::EffectHandle(const sp<EffectModule>& effect,
7240 const sp<AudioFlinger::Client>& client,
7241 const sp<IEffectClient>& effectClient,
7242 int32_t priority)
7243 : BnEffect(),
Marco Nelissen3a34bef2011-08-02 13:33:41 -07007244 mEffect(effect), mEffectClient(effectClient), mClient(client), mCblk(NULL),
Eric Laurent59255e42011-07-27 19:49:51 -07007245 mPriority(priority), mHasControl(false), mEnabled(false)
Mathias Agopian65ab4712010-07-14 17:59:35 -07007246{
Steve Block3856b092011-10-20 11:56:00 +01007247 ALOGV("constructor %p", this);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007248
Marco Nelissen3a34bef2011-08-02 13:33:41 -07007249 if (client == 0) {
7250 return;
7251 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07007252 int bufOffset = ((sizeof(effect_param_cblk_t) - 1) / sizeof(int) + 1) * sizeof(int);
7253 mCblkMemory = client->heap()->allocate(EFFECT_PARAM_BUFFER_SIZE + bufOffset);
7254 if (mCblkMemory != 0) {
7255 mCblk = static_cast<effect_param_cblk_t *>(mCblkMemory->pointer());
7256
Glenn Kastena0d68332012-01-27 16:47:15 -08007257 if (mCblk != NULL) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07007258 new(mCblk) effect_param_cblk_t();
7259 mBuffer = (uint8_t *)mCblk + bufOffset;
7260 }
7261 } else {
Steve Block29357bc2012-01-06 19:20:56 +00007262 ALOGE("not enough memory for Effect size=%u", EFFECT_PARAM_BUFFER_SIZE + sizeof(effect_param_cblk_t));
Mathias Agopian65ab4712010-07-14 17:59:35 -07007263 return;
7264 }
7265}
7266
7267AudioFlinger::EffectHandle::~EffectHandle()
7268{
Steve Block3856b092011-10-20 11:56:00 +01007269 ALOGV("Destructor %p", this);
Marco Nelissen3a34bef2011-08-02 13:33:41 -07007270 disconnect(false);
Steve Block3856b092011-10-20 11:56:00 +01007271 ALOGV("Destructor DONE %p", this);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007272}
7273
7274status_t AudioFlinger::EffectHandle::enable()
7275{
Steve Block3856b092011-10-20 11:56:00 +01007276 ALOGV("enable %p", this);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007277 if (!mHasControl) return INVALID_OPERATION;
7278 if (mEffect == 0) return DEAD_OBJECT;
7279
Eric Laurentdb7c0792011-08-10 10:37:50 -07007280 if (mEnabled) {
7281 return NO_ERROR;
7282 }
7283
Eric Laurent59255e42011-07-27 19:49:51 -07007284 mEnabled = true;
7285
7286 sp<ThreadBase> thread = mEffect->thread().promote();
7287 if (thread != 0) {
7288 thread->checkSuspendOnEffectEnabled(mEffect, true, mEffect->sessionId());
7289 }
7290
7291 // checkSuspendOnEffectEnabled() can suspend this same effect when enabled
7292 if (mEffect->suspended()) {
7293 return NO_ERROR;
7294 }
7295
Eric Laurentdb7c0792011-08-10 10:37:50 -07007296 status_t status = mEffect->setEnabled(true);
7297 if (status != NO_ERROR) {
7298 if (thread != 0) {
7299 thread->checkSuspendOnEffectEnabled(mEffect, false, mEffect->sessionId());
7300 }
7301 mEnabled = false;
7302 }
7303 return status;
Mathias Agopian65ab4712010-07-14 17:59:35 -07007304}
7305
7306status_t AudioFlinger::EffectHandle::disable()
7307{
Steve Block3856b092011-10-20 11:56:00 +01007308 ALOGV("disable %p", this);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007309 if (!mHasControl) return INVALID_OPERATION;
Eric Laurent59255e42011-07-27 19:49:51 -07007310 if (mEffect == 0) return DEAD_OBJECT;
Mathias Agopian65ab4712010-07-14 17:59:35 -07007311
Eric Laurentdb7c0792011-08-10 10:37:50 -07007312 if (!mEnabled) {
7313 return NO_ERROR;
7314 }
Eric Laurent59255e42011-07-27 19:49:51 -07007315 mEnabled = false;
7316
7317 if (mEffect->suspended()) {
7318 return NO_ERROR;
7319 }
7320
7321 status_t status = mEffect->setEnabled(false);
7322
7323 sp<ThreadBase> thread = mEffect->thread().promote();
7324 if (thread != 0) {
7325 thread->checkSuspendOnEffectEnabled(mEffect, false, mEffect->sessionId());
7326 }
7327
7328 return status;
Mathias Agopian65ab4712010-07-14 17:59:35 -07007329}
7330
7331void AudioFlinger::EffectHandle::disconnect()
7332{
Marco Nelissen3a34bef2011-08-02 13:33:41 -07007333 disconnect(true);
7334}
7335
Glenn Kasten58123c32012-02-03 10:32:24 -08007336void AudioFlinger::EffectHandle::disconnect(bool unpinIfLast)
Marco Nelissen3a34bef2011-08-02 13:33:41 -07007337{
Glenn Kasten58123c32012-02-03 10:32:24 -08007338 ALOGV("disconnect(%s)", unpinIfLast ? "true" : "false");
Mathias Agopian65ab4712010-07-14 17:59:35 -07007339 if (mEffect == 0) {
7340 return;
7341 }
Glenn Kasten58123c32012-02-03 10:32:24 -08007342 mEffect->disconnect(this, unpinIfLast);
Eric Laurent59255e42011-07-27 19:49:51 -07007343
Eric Laurenta85a74a2011-10-19 11:44:54 -07007344 if (mHasControl && mEnabled) {
Eric Laurentdb7c0792011-08-10 10:37:50 -07007345 sp<ThreadBase> thread = mEffect->thread().promote();
7346 if (thread != 0) {
7347 thread->checkSuspendOnEffectEnabled(mEffect, false, mEffect->sessionId());
7348 }
Eric Laurent59255e42011-07-27 19:49:51 -07007349 }
7350
Mathias Agopian65ab4712010-07-14 17:59:35 -07007351 // release sp on module => module destructor can be called now
7352 mEffect.clear();
Mathias Agopian65ab4712010-07-14 17:59:35 -07007353 if (mClient != 0) {
Glenn Kastena0d68332012-01-27 16:47:15 -08007354 if (mCblk != NULL) {
Glenn Kasten1a0ae5b2012-02-03 10:24:48 -08007355 // unlike ~TrackBase(), mCblk is never a local new, so don't delete
Marco Nelissen3a34bef2011-08-02 13:33:41 -07007356 mCblk->~effect_param_cblk_t(); // destroy our shared-structure.
7357 }
Glenn Kastendbfafaf2012-01-25 15:27:15 -08007358 mCblkMemory.clear(); // free the shared memory before releasing the heap it belongs to
Glenn Kasten98ec94c2012-01-25 14:28:29 -08007359 // Client destructor must run with AudioFlinger mutex locked
Mathias Agopian65ab4712010-07-14 17:59:35 -07007360 Mutex::Autolock _l(mClient->audioFlinger()->mLock);
7361 mClient.clear();
7362 }
7363}
7364
Eric Laurent25f43952010-07-28 05:40:18 -07007365status_t AudioFlinger::EffectHandle::command(uint32_t cmdCode,
7366 uint32_t cmdSize,
7367 void *pCmdData,
7368 uint32_t *replySize,
7369 void *pReplyData)
Mathias Agopian65ab4712010-07-14 17:59:35 -07007370{
Steve Block3856b092011-10-20 11:56:00 +01007371// ALOGV("command(), cmdCode: %d, mHasControl: %d, mEffect: %p",
Eric Laurent25f43952010-07-28 05:40:18 -07007372// cmdCode, mHasControl, (mEffect == 0) ? 0 : mEffect.get());
Mathias Agopian65ab4712010-07-14 17:59:35 -07007373
7374 // only get parameter command is permitted for applications not controlling the effect
7375 if (!mHasControl && cmdCode != EFFECT_CMD_GET_PARAM) {
7376 return INVALID_OPERATION;
7377 }
7378 if (mEffect == 0) return DEAD_OBJECT;
Marco Nelissen3a34bef2011-08-02 13:33:41 -07007379 if (mClient == 0) return INVALID_OPERATION;
Mathias Agopian65ab4712010-07-14 17:59:35 -07007380
7381 // handle commands that are not forwarded transparently to effect engine
7382 if (cmdCode == EFFECT_CMD_SET_PARAM_COMMIT) {
7383 // No need to trylock() here as this function is executed in the binder thread serving a particular client process:
7384 // no risk to block the whole media server process or mixer threads is we are stuck here
7385 Mutex::Autolock _l(mCblk->lock);
7386 if (mCblk->clientIndex > EFFECT_PARAM_BUFFER_SIZE ||
7387 mCblk->serverIndex > EFFECT_PARAM_BUFFER_SIZE) {
7388 mCblk->serverIndex = 0;
7389 mCblk->clientIndex = 0;
7390 return BAD_VALUE;
7391 }
7392 status_t status = NO_ERROR;
7393 while (mCblk->serverIndex < mCblk->clientIndex) {
7394 int reply;
Eric Laurent25f43952010-07-28 05:40:18 -07007395 uint32_t rsize = sizeof(int);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007396 int *p = (int *)(mBuffer + mCblk->serverIndex);
7397 int size = *p++;
7398 if (((uint8_t *)p + size) > mBuffer + mCblk->clientIndex) {
Steve Block5ff1dd52012-01-05 23:22:43 +00007399 ALOGW("command(): invalid parameter block size");
Mathias Agopian65ab4712010-07-14 17:59:35 -07007400 break;
7401 }
7402 effect_param_t *param = (effect_param_t *)p;
7403 if (param->psize == 0 || param->vsize == 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00007404 ALOGW("command(): null parameter or value size");
Mathias Agopian65ab4712010-07-14 17:59:35 -07007405 mCblk->serverIndex += size;
7406 continue;
7407 }
Eric Laurent25f43952010-07-28 05:40:18 -07007408 uint32_t psize = sizeof(effect_param_t) +
7409 ((param->psize - 1) / sizeof(int) + 1) * sizeof(int) +
7410 param->vsize;
7411 status_t ret = mEffect->command(EFFECT_CMD_SET_PARAM,
7412 psize,
7413 p,
7414 &rsize,
7415 &reply);
Eric Laurentaeae3de2010-09-02 11:56:55 -07007416 // stop at first error encountered
7417 if (ret != NO_ERROR) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07007418 status = ret;
Eric Laurentaeae3de2010-09-02 11:56:55 -07007419 *(int *)pReplyData = reply;
7420 break;
7421 } else if (reply != NO_ERROR) {
7422 *(int *)pReplyData = reply;
7423 break;
Mathias Agopian65ab4712010-07-14 17:59:35 -07007424 }
7425 mCblk->serverIndex += size;
7426 }
7427 mCblk->serverIndex = 0;
7428 mCblk->clientIndex = 0;
7429 return status;
7430 } else if (cmdCode == EFFECT_CMD_ENABLE) {
Eric Laurentaeae3de2010-09-02 11:56:55 -07007431 *(int *)pReplyData = NO_ERROR;
Mathias Agopian65ab4712010-07-14 17:59:35 -07007432 return enable();
7433 } else if (cmdCode == EFFECT_CMD_DISABLE) {
Eric Laurentaeae3de2010-09-02 11:56:55 -07007434 *(int *)pReplyData = NO_ERROR;
Mathias Agopian65ab4712010-07-14 17:59:35 -07007435 return disable();
7436 }
7437
7438 return mEffect->command(cmdCode, cmdSize, pCmdData, replySize, pReplyData);
7439}
7440
Eric Laurent59255e42011-07-27 19:49:51 -07007441void AudioFlinger::EffectHandle::setControl(bool hasControl, bool signal, bool enabled)
Mathias Agopian65ab4712010-07-14 17:59:35 -07007442{
Steve Block3856b092011-10-20 11:56:00 +01007443 ALOGV("setControl %p control %d", this, hasControl);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007444
7445 mHasControl = hasControl;
Eric Laurent59255e42011-07-27 19:49:51 -07007446 mEnabled = enabled;
7447
Mathias Agopian65ab4712010-07-14 17:59:35 -07007448 if (signal && mEffectClient != 0) {
7449 mEffectClient->controlStatusChanged(hasControl);
7450 }
7451}
7452
Eric Laurent25f43952010-07-28 05:40:18 -07007453void AudioFlinger::EffectHandle::commandExecuted(uint32_t cmdCode,
7454 uint32_t cmdSize,
7455 void *pCmdData,
7456 uint32_t replySize,
7457 void *pReplyData)
Mathias Agopian65ab4712010-07-14 17:59:35 -07007458{
7459 if (mEffectClient != 0) {
7460 mEffectClient->commandExecuted(cmdCode, cmdSize, pCmdData, replySize, pReplyData);
7461 }
7462}
7463
7464
7465
7466void AudioFlinger::EffectHandle::setEnabled(bool enabled)
7467{
7468 if (mEffectClient != 0) {
7469 mEffectClient->enableStatusChanged(enabled);
7470 }
7471}
7472
7473status_t AudioFlinger::EffectHandle::onTransact(
7474 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
7475{
7476 return BnEffect::onTransact(code, data, reply, flags);
7477}
7478
7479
7480void AudioFlinger::EffectHandle::dump(char* buffer, size_t size)
7481{
Glenn Kastena0d68332012-01-27 16:47:15 -08007482 bool locked = mCblk != NULL && tryLock(mCblk->lock);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007483
7484 snprintf(buffer, size, "\t\t\t%05d %05d %01u %01u %05u %05u\n",
Glenn Kasten44deb052012-02-05 18:09:08 -08007485 (mClient == 0) ? getpid_cached : mClient->pid(),
Mathias Agopian65ab4712010-07-14 17:59:35 -07007486 mPriority,
7487 mHasControl,
7488 !locked,
Marco Nelissen3a34bef2011-08-02 13:33:41 -07007489 mCblk ? mCblk->clientIndex : 0,
7490 mCblk ? mCblk->serverIndex : 0
Mathias Agopian65ab4712010-07-14 17:59:35 -07007491 );
7492
7493 if (locked) {
7494 mCblk->lock.unlock();
7495 }
7496}
7497
7498#undef LOG_TAG
7499#define LOG_TAG "AudioFlinger::EffectChain"
7500
Glenn Kasten9eaa5572012-01-20 13:32:16 -08007501AudioFlinger::EffectChain::EffectChain(ThreadBase *thread,
Mathias Agopian65ab4712010-07-14 17:59:35 -07007502 int sessionId)
Glenn Kasten9eaa5572012-01-20 13:32:16 -08007503 : mThread(thread), mSessionId(sessionId), mActiveTrackCnt(0), mTrackCnt(0), mTailBufferCount(0),
Eric Laurentb469b942011-05-09 12:09:06 -07007504 mOwnInBuffer(false), mVolumeCtrlIdx(-1), mLeftVolume(UINT_MAX), mRightVolume(UINT_MAX),
7505 mNewLeftVolume(UINT_MAX), mNewRightVolume(UINT_MAX)
Mathias Agopian65ab4712010-07-14 17:59:35 -07007506{
Dima Zavinfce7a472011-04-19 22:30:36 -07007507 mStrategy = AudioSystem::getStrategyForStream(AUDIO_STREAM_MUSIC);
Glenn Kasten9eaa5572012-01-20 13:32:16 -08007508 if (thread == NULL) {
Eric Laurent544fe9b2011-11-11 15:42:52 -08007509 return;
7510 }
7511 mMaxTailBuffers = ((kProcessTailDurationMs * thread->sampleRate()) / 1000) /
7512 thread->frameCount();
Mathias Agopian65ab4712010-07-14 17:59:35 -07007513}
7514
7515AudioFlinger::EffectChain::~EffectChain()
7516{
7517 if (mOwnInBuffer) {
7518 delete mInBuffer;
7519 }
7520
7521}
7522
Eric Laurent59255e42011-07-27 19:49:51 -07007523// getEffectFromDesc_l() must be called with ThreadBase::mLock held
Eric Laurentcab11242010-07-15 12:50:15 -07007524sp<AudioFlinger::EffectModule> AudioFlinger::EffectChain::getEffectFromDesc_l(effect_descriptor_t *descriptor)
Mathias Agopian65ab4712010-07-14 17:59:35 -07007525{
Mathias Agopian65ab4712010-07-14 17:59:35 -07007526 size_t size = mEffects.size();
7527
7528 for (size_t i = 0; i < size; i++) {
7529 if (memcmp(&mEffects[i]->desc().uuid, &descriptor->uuid, sizeof(effect_uuid_t)) == 0) {
Glenn Kasten090f0192012-01-30 13:00:02 -08007530 return mEffects[i];
Mathias Agopian65ab4712010-07-14 17:59:35 -07007531 }
7532 }
Glenn Kasten090f0192012-01-30 13:00:02 -08007533 return 0;
Mathias Agopian65ab4712010-07-14 17:59:35 -07007534}
7535
Eric Laurent59255e42011-07-27 19:49:51 -07007536// getEffectFromId_l() must be called with ThreadBase::mLock held
Eric Laurentcab11242010-07-15 12:50:15 -07007537sp<AudioFlinger::EffectModule> AudioFlinger::EffectChain::getEffectFromId_l(int id)
Mathias Agopian65ab4712010-07-14 17:59:35 -07007538{
Mathias Agopian65ab4712010-07-14 17:59:35 -07007539 size_t size = mEffects.size();
7540
7541 for (size_t i = 0; i < size; i++) {
Eric Laurentde070132010-07-13 04:45:46 -07007542 // by convention, return first effect if id provided is 0 (0 is never a valid id)
7543 if (id == 0 || mEffects[i]->id() == id) {
Glenn Kasten090f0192012-01-30 13:00:02 -08007544 return mEffects[i];
Mathias Agopian65ab4712010-07-14 17:59:35 -07007545 }
7546 }
Glenn Kasten090f0192012-01-30 13:00:02 -08007547 return 0;
Mathias Agopian65ab4712010-07-14 17:59:35 -07007548}
7549
Eric Laurent59255e42011-07-27 19:49:51 -07007550// getEffectFromType_l() must be called with ThreadBase::mLock held
7551sp<AudioFlinger::EffectModule> AudioFlinger::EffectChain::getEffectFromType_l(
7552 const effect_uuid_t *type)
7553{
Eric Laurent59255e42011-07-27 19:49:51 -07007554 size_t size = mEffects.size();
7555
7556 for (size_t i = 0; i < size; i++) {
7557 if (memcmp(&mEffects[i]->desc().type, type, sizeof(effect_uuid_t)) == 0) {
Glenn Kasten090f0192012-01-30 13:00:02 -08007558 return mEffects[i];
Eric Laurent59255e42011-07-27 19:49:51 -07007559 }
7560 }
Glenn Kasten090f0192012-01-30 13:00:02 -08007561 return 0;
Eric Laurent59255e42011-07-27 19:49:51 -07007562}
7563
Mathias Agopian65ab4712010-07-14 17:59:35 -07007564// Must be called with EffectChain::mLock locked
7565void AudioFlinger::EffectChain::process_l()
7566{
Eric Laurentdac69112010-09-28 14:09:57 -07007567 sp<ThreadBase> thread = mThread.promote();
7568 if (thread == 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00007569 ALOGW("process_l(): cannot promote mixer thread");
Eric Laurentdac69112010-09-28 14:09:57 -07007570 return;
7571 }
Dima Zavinfce7a472011-04-19 22:30:36 -07007572 bool isGlobalSession = (mSessionId == AUDIO_SESSION_OUTPUT_MIX) ||
7573 (mSessionId == AUDIO_SESSION_OUTPUT_STAGE);
Eric Laurent544fe9b2011-11-11 15:42:52 -08007574 // always process effects unless no more tracks are on the session and the effect tail
7575 // has been rendered
7576 bool doProcess = true;
Eric Laurentdac69112010-09-28 14:09:57 -07007577 if (!isGlobalSession) {
Eric Laurent544fe9b2011-11-11 15:42:52 -08007578 bool tracksOnSession = (trackCnt() != 0);
Eric Laurentb469b942011-05-09 12:09:06 -07007579
Eric Laurent544fe9b2011-11-11 15:42:52 -08007580 if (!tracksOnSession && mTailBufferCount == 0) {
7581 doProcess = false;
7582 }
7583
7584 if (activeTrackCnt() == 0) {
7585 // if no track is active and the effect tail has not been rendered,
7586 // the input buffer must be cleared here as the mixer process will not do it
7587 if (tracksOnSession || mTailBufferCount > 0) {
7588 size_t numSamples = thread->frameCount() * thread->channelCount();
7589 memset(mInBuffer, 0, numSamples * sizeof(int16_t));
7590 if (mTailBufferCount > 0) {
7591 mTailBufferCount--;
7592 }
7593 }
7594 }
Eric Laurentdac69112010-09-28 14:09:57 -07007595 }
7596
Mathias Agopian65ab4712010-07-14 17:59:35 -07007597 size_t size = mEffects.size();
Eric Laurent544fe9b2011-11-11 15:42:52 -08007598 if (doProcess) {
Eric Laurentdac69112010-09-28 14:09:57 -07007599 for (size_t i = 0; i < size; i++) {
7600 mEffects[i]->process();
7601 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07007602 }
7603 for (size_t i = 0; i < size; i++) {
7604 mEffects[i]->updateState();
7605 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07007606}
7607
Eric Laurentcab11242010-07-15 12:50:15 -07007608// addEffect_l() must be called with PlaybackThread::mLock held
Eric Laurentde070132010-07-13 04:45:46 -07007609status_t AudioFlinger::EffectChain::addEffect_l(const sp<EffectModule>& effect)
Mathias Agopian65ab4712010-07-14 17:59:35 -07007610{
7611 effect_descriptor_t desc = effect->desc();
7612 uint32_t insertPref = desc.flags & EFFECT_FLAG_INSERT_MASK;
7613
7614 Mutex::Autolock _l(mLock);
Eric Laurentde070132010-07-13 04:45:46 -07007615 effect->setChain(this);
7616 sp<ThreadBase> thread = mThread.promote();
7617 if (thread == 0) {
7618 return NO_INIT;
7619 }
7620 effect->setThread(thread);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007621
7622 if ((desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
7623 // Auxiliary effects are inserted at the beginning of mEffects vector as
7624 // they are processed first and accumulated in chain input buffer
7625 mEffects.insertAt(effect, 0);
Eric Laurentde070132010-07-13 04:45:46 -07007626
Mathias Agopian65ab4712010-07-14 17:59:35 -07007627 // the input buffer for auxiliary effect contains mono samples in
7628 // 32 bit format. This is to avoid saturation in AudoMixer
7629 // accumulation stage. Saturation is done in EffectModule::process() before
7630 // calling the process in effect engine
7631 size_t numSamples = thread->frameCount();
7632 int32_t *buffer = new int32_t[numSamples];
7633 memset(buffer, 0, numSamples * sizeof(int32_t));
7634 effect->setInBuffer((int16_t *)buffer);
7635 // auxiliary effects output samples to chain input buffer for further processing
7636 // by insert effects
7637 effect->setOutBuffer(mInBuffer);
7638 } else {
7639 // Insert effects are inserted at the end of mEffects vector as they are processed
7640 // after track and auxiliary effects.
7641 // Insert effect order as a function of indicated preference:
7642 // if EFFECT_FLAG_INSERT_EXCLUSIVE, insert in first position or reject if
7643 // another effect is present
7644 // else if EFFECT_FLAG_INSERT_FIRST, insert in first position or after the
7645 // last effect claiming first position
7646 // else if EFFECT_FLAG_INSERT_LAST, insert in last position or before the
7647 // first effect claiming last position
7648 // else if EFFECT_FLAG_INSERT_ANY insert after first or before last
7649 // Reject insertion if an effect with EFFECT_FLAG_INSERT_EXCLUSIVE is
7650 // already present
7651
Glenn Kasten8d6a2442012-02-08 14:04:28 -08007652 size_t size = mEffects.size();
7653 size_t idx_insert = size;
7654 ssize_t idx_insert_first = -1;
7655 ssize_t idx_insert_last = -1;
Mathias Agopian65ab4712010-07-14 17:59:35 -07007656
Glenn Kasten8d6a2442012-02-08 14:04:28 -08007657 for (size_t i = 0; i < size; i++) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07007658 effect_descriptor_t d = mEffects[i]->desc();
7659 uint32_t iMode = d.flags & EFFECT_FLAG_TYPE_MASK;
7660 uint32_t iPref = d.flags & EFFECT_FLAG_INSERT_MASK;
7661 if (iMode == EFFECT_FLAG_TYPE_INSERT) {
7662 // check invalid effect chaining combinations
7663 if (insertPref == EFFECT_FLAG_INSERT_EXCLUSIVE ||
7664 iPref == EFFECT_FLAG_INSERT_EXCLUSIVE) {
Steve Block5ff1dd52012-01-05 23:22:43 +00007665 ALOGW("addEffect_l() could not insert effect %s: exclusive conflict with %s", desc.name, d.name);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007666 return INVALID_OPERATION;
7667 }
7668 // remember position of first insert effect and by default
7669 // select this as insert position for new effect
7670 if (idx_insert == size) {
7671 idx_insert = i;
7672 }
7673 // remember position of last insert effect claiming
7674 // first position
7675 if (iPref == EFFECT_FLAG_INSERT_FIRST) {
7676 idx_insert_first = i;
7677 }
7678 // remember position of first insert effect claiming
7679 // last position
7680 if (iPref == EFFECT_FLAG_INSERT_LAST &&
7681 idx_insert_last == -1) {
7682 idx_insert_last = i;
7683 }
7684 }
7685 }
7686
7687 // modify idx_insert from first position if needed
7688 if (insertPref == EFFECT_FLAG_INSERT_LAST) {
7689 if (idx_insert_last != -1) {
7690 idx_insert = idx_insert_last;
7691 } else {
7692 idx_insert = size;
7693 }
7694 } else {
7695 if (idx_insert_first != -1) {
7696 idx_insert = idx_insert_first + 1;
7697 }
7698 }
7699
7700 // always read samples from chain input buffer
7701 effect->setInBuffer(mInBuffer);
7702
7703 // if last effect in the chain, output samples to chain
7704 // output buffer, otherwise to chain input buffer
7705 if (idx_insert == size) {
7706 if (idx_insert != 0) {
7707 mEffects[idx_insert-1]->setOutBuffer(mInBuffer);
7708 mEffects[idx_insert-1]->configure();
7709 }
7710 effect->setOutBuffer(mOutBuffer);
7711 } else {
7712 effect->setOutBuffer(mInBuffer);
7713 }
7714 mEffects.insertAt(effect, idx_insert);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007715
Steve Block3856b092011-10-20 11:56:00 +01007716 ALOGV("addEffect_l() effect %p, added in chain %p at rank %d", effect.get(), this, idx_insert);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007717 }
7718 effect->configure();
7719 return NO_ERROR;
7720}
7721
Eric Laurentcab11242010-07-15 12:50:15 -07007722// removeEffect_l() must be called with PlaybackThread::mLock held
7723size_t AudioFlinger::EffectChain::removeEffect_l(const sp<EffectModule>& effect)
Mathias Agopian65ab4712010-07-14 17:59:35 -07007724{
7725 Mutex::Autolock _l(mLock);
Glenn Kasten8d6a2442012-02-08 14:04:28 -08007726 size_t size = mEffects.size();
Mathias Agopian65ab4712010-07-14 17:59:35 -07007727 uint32_t type = effect->desc().flags & EFFECT_FLAG_TYPE_MASK;
7728
Glenn Kasten8d6a2442012-02-08 14:04:28 -08007729 for (size_t i = 0; i < size; i++) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07007730 if (effect == mEffects[i]) {
Eric Laurentec437d82011-07-26 20:54:46 -07007731 // calling stop here will remove pre-processing effect from the audio HAL.
7732 // This is safe as we hold the EffectChain mutex which guarantees that we are not in
7733 // the middle of a read from audio HAL
Eric Laurentec35a142011-10-05 17:42:25 -07007734 if (mEffects[i]->state() == EffectModule::ACTIVE ||
7735 mEffects[i]->state() == EffectModule::STOPPING) {
7736 mEffects[i]->stop();
7737 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07007738 if (type == EFFECT_FLAG_TYPE_AUXILIARY) {
7739 delete[] effect->inBuffer();
7740 } else {
7741 if (i == size - 1 && i != 0) {
7742 mEffects[i - 1]->setOutBuffer(mOutBuffer);
7743 mEffects[i - 1]->configure();
7744 }
7745 }
7746 mEffects.removeAt(i);
Steve Block3856b092011-10-20 11:56:00 +01007747 ALOGV("removeEffect_l() effect %p, removed from chain %p at rank %d", effect.get(), this, i);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007748 break;
7749 }
7750 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07007751
7752 return mEffects.size();
7753}
7754
Eric Laurentcab11242010-07-15 12:50:15 -07007755// setDevice_l() must be called with PlaybackThread::mLock held
7756void AudioFlinger::EffectChain::setDevice_l(uint32_t device)
Mathias Agopian65ab4712010-07-14 17:59:35 -07007757{
7758 size_t size = mEffects.size();
7759 for (size_t i = 0; i < size; i++) {
7760 mEffects[i]->setDevice(device);
7761 }
7762}
7763
Eric Laurentcab11242010-07-15 12:50:15 -07007764// setMode_l() must be called with PlaybackThread::mLock held
Glenn Kastenf78aee72012-01-04 11:00:47 -08007765void AudioFlinger::EffectChain::setMode_l(audio_mode_t mode)
Mathias Agopian65ab4712010-07-14 17:59:35 -07007766{
7767 size_t size = mEffects.size();
7768 for (size_t i = 0; i < size; i++) {
7769 mEffects[i]->setMode(mode);
7770 }
7771}
7772
Eric Laurentcab11242010-07-15 12:50:15 -07007773// setVolume_l() must be called with PlaybackThread::mLock held
7774bool AudioFlinger::EffectChain::setVolume_l(uint32_t *left, uint32_t *right)
Mathias Agopian65ab4712010-07-14 17:59:35 -07007775{
7776 uint32_t newLeft = *left;
7777 uint32_t newRight = *right;
7778 bool hasControl = false;
Eric Laurentcab11242010-07-15 12:50:15 -07007779 int ctrlIdx = -1;
7780 size_t size = mEffects.size();
Mathias Agopian65ab4712010-07-14 17:59:35 -07007781
Eric Laurentcab11242010-07-15 12:50:15 -07007782 // first update volume controller
7783 for (size_t i = size; i > 0; i--) {
Eric Laurent8f45bd72010-08-31 13:50:07 -07007784 if (mEffects[i - 1]->isProcessEnabled() &&
Eric Laurentcab11242010-07-15 12:50:15 -07007785 (mEffects[i - 1]->desc().flags & EFFECT_FLAG_VOLUME_MASK) == EFFECT_FLAG_VOLUME_CTRL) {
7786 ctrlIdx = i - 1;
Eric Laurentf997cab2010-07-19 06:24:46 -07007787 hasControl = true;
Eric Laurentcab11242010-07-15 12:50:15 -07007788 break;
7789 }
7790 }
7791
7792 if (ctrlIdx == mVolumeCtrlIdx && *left == mLeftVolume && *right == mRightVolume) {
Eric Laurentf997cab2010-07-19 06:24:46 -07007793 if (hasControl) {
7794 *left = mNewLeftVolume;
7795 *right = mNewRightVolume;
7796 }
7797 return hasControl;
Eric Laurentcab11242010-07-15 12:50:15 -07007798 }
7799
7800 mVolumeCtrlIdx = ctrlIdx;
Eric Laurentf997cab2010-07-19 06:24:46 -07007801 mLeftVolume = newLeft;
7802 mRightVolume = newRight;
Eric Laurentcab11242010-07-15 12:50:15 -07007803
7804 // second get volume update from volume controller
7805 if (ctrlIdx >= 0) {
7806 mEffects[ctrlIdx]->setVolume(&newLeft, &newRight, true);
Eric Laurentf997cab2010-07-19 06:24:46 -07007807 mNewLeftVolume = newLeft;
7808 mNewRightVolume = newRight;
Mathias Agopian65ab4712010-07-14 17:59:35 -07007809 }
7810 // then indicate volume to all other effects in chain.
7811 // Pass altered volume to effects before volume controller
7812 // and requested volume to effects after controller
7813 uint32_t lVol = newLeft;
7814 uint32_t rVol = newRight;
Eric Laurentcab11242010-07-15 12:50:15 -07007815
Mathias Agopian65ab4712010-07-14 17:59:35 -07007816 for (size_t i = 0; i < size; i++) {
Eric Laurentcab11242010-07-15 12:50:15 -07007817 if ((int)i == ctrlIdx) continue;
7818 // this also works for ctrlIdx == -1 when there is no volume controller
7819 if ((int)i > ctrlIdx) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07007820 lVol = *left;
7821 rVol = *right;
7822 }
7823 mEffects[i]->setVolume(&lVol, &rVol, false);
7824 }
7825 *left = newLeft;
7826 *right = newRight;
7827
7828 return hasControl;
7829}
7830
Mathias Agopian65ab4712010-07-14 17:59:35 -07007831status_t AudioFlinger::EffectChain::dump(int fd, const Vector<String16>& args)
7832{
7833 const size_t SIZE = 256;
7834 char buffer[SIZE];
7835 String8 result;
7836
7837 snprintf(buffer, SIZE, "Effects for session %d:\n", mSessionId);
7838 result.append(buffer);
7839
7840 bool locked = tryLock(mLock);
7841 // failed to lock - AudioFlinger is probably deadlocked
7842 if (!locked) {
7843 result.append("\tCould not lock mutex:\n");
7844 }
7845
Eric Laurentcab11242010-07-15 12:50:15 -07007846 result.append("\tNum fx In buffer Out buffer Active tracks:\n");
7847 snprintf(buffer, SIZE, "\t%02d 0x%08x 0x%08x %d\n",
Mathias Agopian65ab4712010-07-14 17:59:35 -07007848 mEffects.size(),
7849 (uint32_t)mInBuffer,
7850 (uint32_t)mOutBuffer,
Mathias Agopian65ab4712010-07-14 17:59:35 -07007851 mActiveTrackCnt);
7852 result.append(buffer);
7853 write(fd, result.string(), result.size());
7854
7855 for (size_t i = 0; i < mEffects.size(); ++i) {
7856 sp<EffectModule> effect = mEffects[i];
7857 if (effect != 0) {
7858 effect->dump(fd, args);
7859 }
7860 }
7861
7862 if (locked) {
7863 mLock.unlock();
7864 }
7865
7866 return NO_ERROR;
7867}
7868
Eric Laurent59255e42011-07-27 19:49:51 -07007869// must be called with ThreadBase::mLock held
7870void AudioFlinger::EffectChain::setEffectSuspended_l(
7871 const effect_uuid_t *type, bool suspend)
7872{
7873 sp<SuspendedEffectDesc> desc;
7874 // use effect type UUID timelow as key as there is no real risk of identical
7875 // timeLow fields among effect type UUIDs.
Glenn Kasten8d6a2442012-02-08 14:04:28 -08007876 ssize_t index = mSuspendedEffects.indexOfKey(type->timeLow);
Eric Laurent59255e42011-07-27 19:49:51 -07007877 if (suspend) {
7878 if (index >= 0) {
7879 desc = mSuspendedEffects.valueAt(index);
7880 } else {
7881 desc = new SuspendedEffectDesc();
7882 memcpy(&desc->mType, type, sizeof(effect_uuid_t));
7883 mSuspendedEffects.add(type->timeLow, desc);
Steve Block3856b092011-10-20 11:56:00 +01007884 ALOGV("setEffectSuspended_l() add entry for %08x", type->timeLow);
Eric Laurent59255e42011-07-27 19:49:51 -07007885 }
7886 if (desc->mRefCount++ == 0) {
7887 sp<EffectModule> effect = getEffectIfEnabled(type);
7888 if (effect != 0) {
7889 desc->mEffect = effect;
7890 effect->setSuspended(true);
7891 effect->setEnabled(false);
7892 }
7893 }
7894 } else {
7895 if (index < 0) {
7896 return;
7897 }
7898 desc = mSuspendedEffects.valueAt(index);
7899 if (desc->mRefCount <= 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00007900 ALOGW("setEffectSuspended_l() restore refcount should not be 0 %d", desc->mRefCount);
Eric Laurent59255e42011-07-27 19:49:51 -07007901 desc->mRefCount = 1;
7902 }
7903 if (--desc->mRefCount == 0) {
Steve Block3856b092011-10-20 11:56:00 +01007904 ALOGV("setEffectSuspended_l() remove entry for %08x", mSuspendedEffects.keyAt(index));
Eric Laurent59255e42011-07-27 19:49:51 -07007905 if (desc->mEffect != 0) {
7906 sp<EffectModule> effect = desc->mEffect.promote();
7907 if (effect != 0) {
7908 effect->setSuspended(false);
7909 sp<EffectHandle> handle = effect->controlHandle();
7910 if (handle != 0) {
7911 effect->setEnabled(handle->enabled());
7912 }
7913 }
7914 desc->mEffect.clear();
7915 }
7916 mSuspendedEffects.removeItemsAt(index);
7917 }
7918 }
7919}
7920
7921// must be called with ThreadBase::mLock held
7922void AudioFlinger::EffectChain::setEffectSuspendedAll_l(bool suspend)
7923{
7924 sp<SuspendedEffectDesc> desc;
7925
Glenn Kasten8d6a2442012-02-08 14:04:28 -08007926 ssize_t index = mSuspendedEffects.indexOfKey((int)kKeyForSuspendAll);
Eric Laurent59255e42011-07-27 19:49:51 -07007927 if (suspend) {
7928 if (index >= 0) {
7929 desc = mSuspendedEffects.valueAt(index);
7930 } else {
7931 desc = new SuspendedEffectDesc();
7932 mSuspendedEffects.add((int)kKeyForSuspendAll, desc);
Steve Block3856b092011-10-20 11:56:00 +01007933 ALOGV("setEffectSuspendedAll_l() add entry for 0");
Eric Laurent59255e42011-07-27 19:49:51 -07007934 }
7935 if (desc->mRefCount++ == 0) {
Glenn Kastend0539712012-01-30 12:56:03 -08007936 Vector< sp<EffectModule> > effects;
7937 getSuspendEligibleEffects(effects);
Eric Laurent59255e42011-07-27 19:49:51 -07007938 for (size_t i = 0; i < effects.size(); i++) {
7939 setEffectSuspended_l(&effects[i]->desc().type, true);
7940 }
7941 }
7942 } else {
7943 if (index < 0) {
7944 return;
7945 }
7946 desc = mSuspendedEffects.valueAt(index);
7947 if (desc->mRefCount <= 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00007948 ALOGW("setEffectSuspendedAll_l() restore refcount should not be 0 %d", desc->mRefCount);
Eric Laurent59255e42011-07-27 19:49:51 -07007949 desc->mRefCount = 1;
7950 }
7951 if (--desc->mRefCount == 0) {
7952 Vector<const effect_uuid_t *> types;
7953 for (size_t i = 0; i < mSuspendedEffects.size(); i++) {
7954 if (mSuspendedEffects.keyAt(i) == (int)kKeyForSuspendAll) {
7955 continue;
7956 }
7957 types.add(&mSuspendedEffects.valueAt(i)->mType);
7958 }
7959 for (size_t i = 0; i < types.size(); i++) {
7960 setEffectSuspended_l(types[i], false);
7961 }
Steve Block3856b092011-10-20 11:56:00 +01007962 ALOGV("setEffectSuspendedAll_l() remove entry for %08x", mSuspendedEffects.keyAt(index));
Eric Laurent59255e42011-07-27 19:49:51 -07007963 mSuspendedEffects.removeItem((int)kKeyForSuspendAll);
7964 }
7965 }
7966}
7967
Eric Laurent6bffdb82011-09-23 08:40:41 -07007968
7969// The volume effect is used for automated tests only
7970#ifndef OPENSL_ES_H_
7971static const effect_uuid_t SL_IID_VOLUME_ = { 0x09e8ede0, 0xddde, 0x11db, 0xb4f6,
7972 { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } };
7973const effect_uuid_t * const SL_IID_VOLUME = &SL_IID_VOLUME_;
7974#endif //OPENSL_ES_H_
7975
Eric Laurentdb7c0792011-08-10 10:37:50 -07007976bool AudioFlinger::EffectChain::isEffectEligibleForSuspend(const effect_descriptor_t& desc)
7977{
7978 // auxiliary effects and visualizer are never suspended on output mix
7979 if ((mSessionId == AUDIO_SESSION_OUTPUT_MIX) &&
7980 (((desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) ||
Eric Laurent6bffdb82011-09-23 08:40:41 -07007981 (memcmp(&desc.type, SL_IID_VISUALIZATION, sizeof(effect_uuid_t)) == 0) ||
7982 (memcmp(&desc.type, SL_IID_VOLUME, sizeof(effect_uuid_t)) == 0))) {
Eric Laurentdb7c0792011-08-10 10:37:50 -07007983 return false;
7984 }
7985 return true;
7986}
7987
Glenn Kastend0539712012-01-30 12:56:03 -08007988void AudioFlinger::EffectChain::getSuspendEligibleEffects(Vector< sp<AudioFlinger::EffectModule> > &effects)
Eric Laurent59255e42011-07-27 19:49:51 -07007989{
Glenn Kastend0539712012-01-30 12:56:03 -08007990 effects.clear();
Eric Laurent59255e42011-07-27 19:49:51 -07007991 for (size_t i = 0; i < mEffects.size(); i++) {
Glenn Kastend0539712012-01-30 12:56:03 -08007992 if (isEffectEligibleForSuspend(mEffects[i]->desc())) {
7993 effects.add(mEffects[i]);
Eric Laurent59255e42011-07-27 19:49:51 -07007994 }
Eric Laurent59255e42011-07-27 19:49:51 -07007995 }
Eric Laurent59255e42011-07-27 19:49:51 -07007996}
7997
7998sp<AudioFlinger::EffectModule> AudioFlinger::EffectChain::getEffectIfEnabled(
7999 const effect_uuid_t *type)
8000{
Glenn Kasten090f0192012-01-30 13:00:02 -08008001 sp<EffectModule> effect = getEffectFromType_l(type);
8002 return effect != 0 && effect->isEnabled() ? effect : 0;
Eric Laurent59255e42011-07-27 19:49:51 -07008003}
8004
8005void AudioFlinger::EffectChain::checkSuspendOnEffectEnabled(const sp<EffectModule>& effect,
8006 bool enabled)
8007{
Glenn Kasten8d6a2442012-02-08 14:04:28 -08008008 ssize_t index = mSuspendedEffects.indexOfKey(effect->desc().type.timeLow);
Eric Laurent59255e42011-07-27 19:49:51 -07008009 if (enabled) {
8010 if (index < 0) {
8011 // if the effect is not suspend check if all effects are suspended
8012 index = mSuspendedEffects.indexOfKey((int)kKeyForSuspendAll);
8013 if (index < 0) {
8014 return;
8015 }
Eric Laurentdb7c0792011-08-10 10:37:50 -07008016 if (!isEffectEligibleForSuspend(effect->desc())) {
8017 return;
8018 }
Eric Laurent59255e42011-07-27 19:49:51 -07008019 setEffectSuspended_l(&effect->desc().type, enabled);
8020 index = mSuspendedEffects.indexOfKey(effect->desc().type.timeLow);
Eric Laurentdb7c0792011-08-10 10:37:50 -07008021 if (index < 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00008022 ALOGW("checkSuspendOnEffectEnabled() Fx should be suspended here!");
Eric Laurentdb7c0792011-08-10 10:37:50 -07008023 return;
8024 }
Eric Laurent59255e42011-07-27 19:49:51 -07008025 }
Steve Block3856b092011-10-20 11:56:00 +01008026 ALOGV("checkSuspendOnEffectEnabled() enable suspending fx %08x",
Eric Laurent59255e42011-07-27 19:49:51 -07008027 effect->desc().type.timeLow);
8028 sp<SuspendedEffectDesc> desc = mSuspendedEffects.valueAt(index);
8029 // if effect is requested to suspended but was not yet enabled, supend it now.
8030 if (desc->mEffect == 0) {
8031 desc->mEffect = effect;
8032 effect->setEnabled(false);
8033 effect->setSuspended(true);
8034 }
8035 } else {
8036 if (index < 0) {
8037 return;
8038 }
Steve Block3856b092011-10-20 11:56:00 +01008039 ALOGV("checkSuspendOnEffectEnabled() disable restoring fx %08x",
Eric Laurent59255e42011-07-27 19:49:51 -07008040 effect->desc().type.timeLow);
8041 sp<SuspendedEffectDesc> desc = mSuspendedEffects.valueAt(index);
8042 desc->mEffect.clear();
8043 effect->setSuspended(false);
8044 }
8045}
8046
Mathias Agopian65ab4712010-07-14 17:59:35 -07008047#undef LOG_TAG
8048#define LOG_TAG "AudioFlinger"
8049
8050// ----------------------------------------------------------------------------
8051
8052status_t AudioFlinger::onTransact(
8053 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
8054{
8055 return BnAudioFlinger::onTransact(code, data, reply, flags);
8056}
8057
Mathias Agopian65ab4712010-07-14 17:59:35 -07008058}; // namespace android