blob: d0611b0e0145b327b994155c32bc73dcc005844d [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
Glenn Kastend3cee2f2012-03-13 17:55:35 -070040#undef ADD_BATTERY_DATA
41
42#ifdef ADD_BATTERY_DATA
Gloria Wang9ee159b2011-02-24 14:51:45 -080043#include <media/IMediaPlayerService.h>
Glenn Kasten25b248e2012-01-03 15:28:29 -080044#include <media/IMediaDeathNotifier.h>
Glenn Kastend3cee2f2012-03-13 17:55:35 -070045#endif
Mathias Agopian65ab4712010-07-14 17:59:35 -070046
47#include <private/media/AudioTrackShared.h>
48#include <private/media/AudioEffectShared.h>
Dima Zavinfce7a472011-04-19 22:30:36 -070049
Dima Zavin64760242011-05-11 14:15:23 -070050#include <system/audio.h>
Dima Zavin7394a4f2011-06-13 18:16:26 -070051#include <hardware/audio.h>
Mathias Agopian65ab4712010-07-14 17:59:35 -070052
53#include "AudioMixer.h"
54#include "AudioFlinger.h"
Glenn Kasten44deb052012-02-05 18:09:08 -080055#include "ServiceUtilities.h"
Mathias Agopian65ab4712010-07-14 17:59:35 -070056
Mathias Agopian65ab4712010-07-14 17:59:35 -070057#include <media/EffectsFactoryApi.h>
Eric Laurent6d8b6942011-06-24 07:01:31 -070058#include <audio_effects/effect_visualizer.h>
Eric Laurent59bd0da2011-08-01 09:52:20 -070059#include <audio_effects/effect_ns.h>
60#include <audio_effects/effect_aec.h>
Mathias Agopian65ab4712010-07-14 17:59:35 -070061
Glenn Kasten3b21c502011-12-15 09:52:39 -080062#include <audio_utils/primitives.h>
63
Eric Laurentfeb0db62011-07-22 09:04:31 -070064#include <powermanager/PowerManager.h>
Glenn Kasten190a46f2012-03-06 11:27:10 -080065
Glenn Kasten4d8d0c32011-07-08 15:26:12 -070066// #define DEBUG_CPU_USAGE 10 // log statistics every n wall clock seconds
Glenn Kasten190a46f2012-03-06 11:27:10 -080067#ifdef DEBUG_CPU_USAGE
68#include <cpustats/CentralTendencyStatistics.h>
69#include <cpustats/ThreadCpuUsage.h>
70#endif
Glenn Kasten4d8d0c32011-07-08 15:26:12 -070071
John Grossman4ff14ba2012-02-08 16:37:41 -080072#include <common_time/cc_helper.h>
73#include <common_time/local_clock.h>
74
Mathias Agopian65ab4712010-07-14 17:59:35 -070075// ----------------------------------------------------------------------------
Mathias Agopian65ab4712010-07-14 17:59:35 -070076
John Grossman1c345192012-03-27 14:00:17 -070077// Note: the following macro is used for extremely verbose logging message. In
78// order to run with ALOG_ASSERT turned on, we need to have LOG_NDEBUG set to
79// 0; but one side effect of this is to turn all LOGV's as well. Some messages
80// are so verbose that we want to suppress them even when we have ALOG_ASSERT
81// turned on. Do not uncomment the #def below unless you really know what you
82// are doing and want to see all of the extremely verbose messages.
83//#define VERY_VERY_VERBOSE_LOGGING
84#ifdef VERY_VERY_VERBOSE_LOGGING
85#define ALOGVV ALOGV
86#else
87#define ALOGVV(a...) do { } while(0)
88#endif
Eric Laurentde070132010-07-13 04:45:46 -070089
Mathias Agopian65ab4712010-07-14 17:59:35 -070090namespace android {
91
Glenn Kastenec1d6b52011-12-12 09:04:45 -080092static const char kDeadlockedString[] = "AudioFlinger may be deadlocked\n";
93static const char kHardwareLockedString[] = "Hardware lock is taken\n";
Mathias Agopian65ab4712010-07-14 17:59:35 -070094
Mathias Agopian65ab4712010-07-14 17:59:35 -070095static const float MAX_GAIN = 4096.0f;
Glenn Kastenb1cf75c2012-01-17 12:20:54 -080096static const uint32_t MAX_GAIN_INT = 0x1000;
Mathias Agopian65ab4712010-07-14 17:59:35 -070097
98// retry counts for buffer fill timeout
99// 50 * ~20msecs = 1 second
100static const int8_t kMaxTrackRetries = 50;
101static const int8_t kMaxTrackStartupRetries = 50;
102// allow less retry attempts on direct output thread.
103// direct outputs can be a scarce resource in audio hardware and should
104// be released as quickly as possible.
105static const int8_t kMaxTrackRetriesDirect = 2;
106
107static const int kDumpLockRetries = 50;
Glenn Kasten7dede872011-12-13 11:04:14 -0800108static const int kDumpLockSleepUs = 20000;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700109
Glenn Kasten7dede872011-12-13 11:04:14 -0800110// don't warn about blocked writes or record buffer overflows more often than this
111static const nsecs_t kWarningThrottleNs = seconds(5);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700112
Eric Laurent7c7f10b2011-06-17 21:29:58 -0700113// RecordThread loop sleep time upon application overrun or audio HAL read error
114static const int kRecordThreadSleepUs = 5000;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700115
Glenn Kasten7dede872011-12-13 11:04:14 -0800116// maximum time to wait for setParameters to complete
117static const nsecs_t kSetParametersTimeoutNs = seconds(2);
Eric Laurent60cd0a02011-09-13 11:40:21 -0700118
Eric Laurent7cafbb32011-11-22 18:50:29 -0800119// minimum sleep time for the mixer thread loop when tracks are active but in underrun
120static const uint32_t kMinThreadSleepTimeUs = 5000;
121// maximum divider applied to the active sleep time in the mixer thread loop
122static const uint32_t kMaxThreadSleepTimeShift = 2;
123
John Grossman4ff14ba2012-02-08 16:37:41 -0800124nsecs_t AudioFlinger::mStandbyTimeInNsecs = kDefaultStandbyTimeInNsecs;
Eric Laurent7cafbb32011-11-22 18:50:29 -0800125
Mathias Agopian65ab4712010-07-14 17:59:35 -0700126// ----------------------------------------------------------------------------
127
Glenn Kastend3cee2f2012-03-13 17:55:35 -0700128#ifdef ADD_BATTERY_DATA
Gloria Wang9ee159b2011-02-24 14:51:45 -0800129// To collect the amplifier usage
130static void addBatteryData(uint32_t params) {
Glenn Kasten25b248e2012-01-03 15:28:29 -0800131 sp<IMediaPlayerService> service = IMediaDeathNotifier::getMediaPlayerService();
132 if (service == NULL) {
133 // it already logged
Gloria Wang9ee159b2011-02-24 14:51:45 -0800134 return;
135 }
136
137 service->addBatteryData(params);
138}
Glenn Kastend3cee2f2012-03-13 17:55:35 -0700139#endif
Gloria Wang9ee159b2011-02-24 14:51:45 -0800140
Dima Zavin799a70e2011-04-18 16:57:27 -0700141static int load_audio_interface(const char *if_name, const hw_module_t **mod,
142 audio_hw_device_t **dev)
143{
144 int rc;
145
146 rc = hw_get_module_by_class(AUDIO_HARDWARE_MODULE_ID, if_name, mod);
147 if (rc)
148 goto out;
149
150 rc = audio_hw_device_open(*mod, dev);
Steve Block29357bc2012-01-06 19:20:56 +0000151 ALOGE_IF(rc, "couldn't open audio hw device in %s.%s (%s)",
Dima Zavin799a70e2011-04-18 16:57:27 -0700152 AUDIO_HARDWARE_MODULE_ID, if_name, strerror(-rc));
153 if (rc)
154 goto out;
155
156 return 0;
157
158out:
159 *mod = NULL;
160 *dev = NULL;
161 return rc;
162}
163
Mathias Agopian65ab4712010-07-14 17:59:35 -0700164// ----------------------------------------------------------------------------
165
166AudioFlinger::AudioFlinger()
167 : BnAudioFlinger(),
John Grossman4ff14ba2012-02-08 16:37:41 -0800168 mPrimaryHardwareDev(NULL),
169 mHardwareStatus(AUDIO_HW_IDLE), // see also onFirstRef()
170 mMasterVolume(1.0f),
171 mMasterVolumeSupportLvl(MVS_NONE),
172 mMasterMute(false),
173 mNextUniqueId(1),
174 mMode(AUDIO_MODE_INVALID),
175 mBtNrecIsOff(false)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700176{
Dima Zavin5a61d2f2011-04-19 19:04:32 -0700177}
178
179void AudioFlinger::onFirstRef()
180{
Dima Zavin799a70e2011-04-18 16:57:27 -0700181 int rc = 0;
Dima Zavinfce7a472011-04-19 22:30:36 -0700182
Eric Laurent93575202011-01-18 18:39:02 -0800183 Mutex::Autolock _l(mLock);
184
Dima Zavin799a70e2011-04-18 16:57:27 -0700185 /* TODO: move all this work into an Init() function */
John Grossman4ff14ba2012-02-08 16:37:41 -0800186 char val_str[PROPERTY_VALUE_MAX] = { 0 };
187 if (property_get("ro.audio.flinger_standbytime_ms", val_str, NULL) >= 0) {
188 uint32_t int_val;
189 if (1 == sscanf(val_str, "%u", &int_val)) {
190 mStandbyTimeInNsecs = milliseconds(int_val);
191 ALOGI("Using %u mSec as standby time.", int_val);
192 } else {
193 mStandbyTimeInNsecs = kDefaultStandbyTimeInNsecs;
194 ALOGI("Using default %u mSec as standby time.",
195 (uint32_t)(mStandbyTimeInNsecs / 1000000));
196 }
197 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700198
Eric Laurenta4c5a552012-03-29 10:12:40 -0700199 mMode = AUDIO_MODE_NORMAL;
200 mMasterVolumeSW = 1.0;
201 mMasterVolume = 1.0;
John Grossman4ff14ba2012-02-08 16:37:41 -0800202 mHardwareStatus = AUDIO_HW_IDLE;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700203}
204
205AudioFlinger::~AudioFlinger()
206{
Dima Zavin799a70e2011-04-18 16:57:27 -0700207
Mathias Agopian65ab4712010-07-14 17:59:35 -0700208 while (!mRecordThreads.isEmpty()) {
209 // closeInput() will remove first entry from mRecordThreads
210 closeInput(mRecordThreads.keyAt(0));
211 }
212 while (!mPlaybackThreads.isEmpty()) {
213 // closeOutput() will remove first entry from mPlaybackThreads
214 closeOutput(mPlaybackThreads.keyAt(0));
215 }
Dima Zavin799a70e2011-04-18 16:57:27 -0700216
Glenn Kasten2b213bc2012-02-02 14:05:20 -0800217 for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
218 // no mHardwareLock needed, as there are no other references to this
Eric Laurenta4c5a552012-03-29 10:12:40 -0700219 audio_hw_device_close(mAudioHwDevs.valueAt(i)->hwDevice());
220 delete mAudioHwDevs.valueAt(i);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700221 }
222}
223
Eric Laurenta4c5a552012-03-29 10:12:40 -0700224static const char * const audio_interfaces[] = {
225 AUDIO_HARDWARE_MODULE_ID_PRIMARY,
226 AUDIO_HARDWARE_MODULE_ID_A2DP,
227 AUDIO_HARDWARE_MODULE_ID_USB,
228};
229#define ARRAY_SIZE(x) (sizeof((x))/sizeof(((x)[0])))
230
231audio_hw_device_t* AudioFlinger::findSuitableHwDev_l(audio_module_handle_t module, uint32_t devices)
Dima Zavin799a70e2011-04-18 16:57:27 -0700232{
Eric Laurenta4c5a552012-03-29 10:12:40 -0700233 // if module is 0, the request comes from an old policy manager and we should load
234 // well known modules
235 if (module == 0) {
236 ALOGW("findSuitableHwDev_l() loading well know audio hw modules");
237 for (size_t i = 0; i < ARRAY_SIZE(audio_interfaces); i++) {
238 loadHwModule_l(audio_interfaces[i]);
239 }
240 } else {
241 // check a match for the requested module handle
242 AudioHwDevice *audioHwdevice = mAudioHwDevs.valueFor(module);
243 if (audioHwdevice != NULL) {
244 return audioHwdevice->hwDevice();
245 }
246 }
247 // then try to find a module supporting the requested device.
Dima Zavin799a70e2011-04-18 16:57:27 -0700248 for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
Eric Laurenta4c5a552012-03-29 10:12:40 -0700249 audio_hw_device_t *dev = mAudioHwDevs.valueAt(i)->hwDevice();
Dima Zavin799a70e2011-04-18 16:57:27 -0700250 if ((dev->get_supported_devices(dev) & devices) == devices)
251 return dev;
252 }
Eric Laurenta4c5a552012-03-29 10:12:40 -0700253
Dima Zavin799a70e2011-04-18 16:57:27 -0700254 return NULL;
255}
Mathias Agopian65ab4712010-07-14 17:59:35 -0700256
257status_t AudioFlinger::dumpClients(int fd, const Vector<String16>& args)
258{
259 const size_t SIZE = 256;
260 char buffer[SIZE];
261 String8 result;
262
263 result.append("Clients:\n");
264 for (size_t i = 0; i < mClients.size(); ++i) {
Glenn Kasten77c11192012-01-25 14:27:41 -0800265 sp<Client> client = mClients.valueAt(i).promote();
266 if (client != 0) {
267 snprintf(buffer, SIZE, " pid: %d\n", client->pid());
268 result.append(buffer);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700269 }
270 }
Marco Nelissen3a34bef2011-08-02 13:33:41 -0700271
272 result.append("Global session refs:\n");
Glenn Kasten012ca6b2012-03-06 11:22:01 -0800273 result.append(" session pid count\n");
Marco Nelissen3a34bef2011-08-02 13:33:41 -0700274 for (size_t i = 0; i < mAudioSessionRefs.size(); i++) {
275 AudioSessionRef *r = mAudioSessionRefs[i];
Glenn Kasten012ca6b2012-03-06 11:22:01 -0800276 snprintf(buffer, SIZE, " %7d %3d %3d\n", r->mSessionid, r->mPid, r->mCnt);
Marco Nelissen3a34bef2011-08-02 13:33:41 -0700277 result.append(buffer);
278 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700279 write(fd, result.string(), result.size());
280 return NO_ERROR;
281}
282
283
284status_t AudioFlinger::dumpInternals(int fd, const Vector<String16>& args)
285{
286 const size_t SIZE = 256;
287 char buffer[SIZE];
288 String8 result;
Glenn Kastena4454b42012-01-04 11:02:33 -0800289 hardware_call_state hardwareStatus = mHardwareStatus;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700290
John Grossman4ff14ba2012-02-08 16:37:41 -0800291 snprintf(buffer, SIZE, "Hardware status: %d\n"
292 "Standby Time mSec: %u\n",
293 hardwareStatus,
294 (uint32_t)(mStandbyTimeInNsecs / 1000000));
Mathias Agopian65ab4712010-07-14 17:59:35 -0700295 result.append(buffer);
296 write(fd, result.string(), result.size());
297 return NO_ERROR;
298}
299
300status_t AudioFlinger::dumpPermissionDenial(int fd, const Vector<String16>& args)
301{
302 const size_t SIZE = 256;
303 char buffer[SIZE];
304 String8 result;
305 snprintf(buffer, SIZE, "Permission Denial: "
306 "can't dump AudioFlinger from pid=%d, uid=%d\n",
307 IPCThreadState::self()->getCallingPid(),
308 IPCThreadState::self()->getCallingUid());
309 result.append(buffer);
310 write(fd, result.string(), result.size());
311 return NO_ERROR;
312}
313
314static bool tryLock(Mutex& mutex)
315{
316 bool locked = false;
317 for (int i = 0; i < kDumpLockRetries; ++i) {
318 if (mutex.tryLock() == NO_ERROR) {
319 locked = true;
320 break;
321 }
Glenn Kasten7dede872011-12-13 11:04:14 -0800322 usleep(kDumpLockSleepUs);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700323 }
324 return locked;
325}
326
327status_t AudioFlinger::dump(int fd, const Vector<String16>& args)
328{
Glenn Kasten44deb052012-02-05 18:09:08 -0800329 if (!dumpAllowed()) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700330 dumpPermissionDenial(fd, args);
331 } else {
332 // get state of hardware lock
333 bool hardwareLocked = tryLock(mHardwareLock);
334 if (!hardwareLocked) {
335 String8 result(kHardwareLockedString);
336 write(fd, result.string(), result.size());
337 } else {
338 mHardwareLock.unlock();
339 }
340
341 bool locked = tryLock(mLock);
342
343 // failed to lock - AudioFlinger is probably deadlocked
344 if (!locked) {
345 String8 result(kDeadlockedString);
346 write(fd, result.string(), result.size());
347 }
348
349 dumpClients(fd, args);
350 dumpInternals(fd, args);
351
352 // dump playback threads
353 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
354 mPlaybackThreads.valueAt(i)->dump(fd, args);
355 }
356
357 // dump record threads
358 for (size_t i = 0; i < mRecordThreads.size(); i++) {
359 mRecordThreads.valueAt(i)->dump(fd, args);
360 }
361
Dima Zavin799a70e2011-04-18 16:57:27 -0700362 // dump all hardware devs
363 for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
Eric Laurenta4c5a552012-03-29 10:12:40 -0700364 audio_hw_device_t *dev = mAudioHwDevs.valueAt(i)->hwDevice();
Dima Zavin799a70e2011-04-18 16:57:27 -0700365 dev->dump(dev, fd);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700366 }
367 if (locked) mLock.unlock();
368 }
369 return NO_ERROR;
370}
371
Glenn Kasten98ec94c2012-01-25 14:28:29 -0800372sp<AudioFlinger::Client> AudioFlinger::registerPid_l(pid_t pid)
373{
374 // If pid is already in the mClients wp<> map, then use that entry
375 // (for which promote() is always != 0), otherwise create a new entry and Client.
376 sp<Client> client = mClients.valueFor(pid).promote();
377 if (client == 0) {
378 client = new Client(this, pid);
379 mClients.add(pid, client);
380 }
381
382 return client;
383}
Mathias Agopian65ab4712010-07-14 17:59:35 -0700384
385// IAudioFlinger interface
386
387
388sp<IAudioTrack> AudioFlinger::createTrack(
389 pid_t pid,
Glenn Kastenfff6d712012-01-12 16:38:12 -0800390 audio_stream_type_t streamType,
Mathias Agopian65ab4712010-07-14 17:59:35 -0700391 uint32_t sampleRate,
Glenn Kasten58f30212012-01-12 12:27:51 -0800392 audio_format_t format,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -0700393 uint32_t channelMask,
Mathias Agopian65ab4712010-07-14 17:59:35 -0700394 int frameCount,
Glenn Kastena075db42012-03-06 11:22:44 -0800395 IAudioFlinger::track_flags_t flags,
Mathias Agopian65ab4712010-07-14 17:59:35 -0700396 const sp<IMemory>& sharedBuffer,
Glenn Kasten72ef00d2012-01-17 11:09:42 -0800397 audio_io_handle_t output,
Mathias Agopian65ab4712010-07-14 17:59:35 -0700398 int *sessionId,
399 status_t *status)
400{
401 sp<PlaybackThread::Track> track;
402 sp<TrackHandle> trackHandle;
403 sp<Client> client;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700404 status_t lStatus;
405 int lSessionId;
406
Glenn Kasten263709e2012-01-06 08:40:01 -0800407 // client AudioTrack::set already implements AUDIO_STREAM_DEFAULT => AUDIO_STREAM_MUSIC,
408 // but if someone uses binder directly they could bypass that and cause us to crash
409 if (uint32_t(streamType) >= AUDIO_STREAM_CNT) {
Steve Block29357bc2012-01-06 19:20:56 +0000410 ALOGE("createTrack() invalid stream type %d", streamType);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700411 lStatus = BAD_VALUE;
412 goto Exit;
413 }
414
415 {
416 Mutex::Autolock _l(mLock);
417 PlaybackThread *thread = checkPlaybackThread_l(output);
Eric Laurent39e94f82010-07-28 01:32:47 -0700418 PlaybackThread *effectThread = NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700419 if (thread == NULL) {
Steve Block29357bc2012-01-06 19:20:56 +0000420 ALOGE("unknown output thread");
Mathias Agopian65ab4712010-07-14 17:59:35 -0700421 lStatus = BAD_VALUE;
422 goto Exit;
423 }
424
Glenn Kasten98ec94c2012-01-25 14:28:29 -0800425 client = registerPid_l(pid);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700426
Steve Block3856b092011-10-20 11:56:00 +0100427 ALOGV("createTrack() sessionId: %d", (sessionId == NULL) ? -2 : *sessionId);
Dima Zavinfce7a472011-04-19 22:30:36 -0700428 if (sessionId != NULL && *sessionId != AUDIO_SESSION_OUTPUT_MIX) {
Eric Laurentde070132010-07-13 04:45:46 -0700429 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
Eric Laurent39e94f82010-07-28 01:32:47 -0700430 sp<PlaybackThread> t = mPlaybackThreads.valueAt(i);
431 if (mPlaybackThreads.keyAt(i) != output) {
432 // prevent same audio session on different output threads
433 uint32_t sessions = t->hasAudioSession(*sessionId);
434 if (sessions & PlaybackThread::TRACK_SESSION) {
Steve Block29357bc2012-01-06 19:20:56 +0000435 ALOGE("createTrack() session ID %d already in use", *sessionId);
Eric Laurent39e94f82010-07-28 01:32:47 -0700436 lStatus = BAD_VALUE;
437 goto Exit;
438 }
439 // check if an effect with same session ID is waiting for a track to be created
440 if (sessions & PlaybackThread::EFFECT_SESSION) {
441 effectThread = t.get();
442 }
Eric Laurentde070132010-07-13 04:45:46 -0700443 }
444 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700445 lSessionId = *sessionId;
446 } else {
Eric Laurentde070132010-07-13 04:45:46 -0700447 // if no audio session id is provided, create one here
Eric Laurent7c7f10b2011-06-17 21:29:58 -0700448 lSessionId = nextUniqueId();
Mathias Agopian65ab4712010-07-14 17:59:35 -0700449 if (sessionId != NULL) {
450 *sessionId = lSessionId;
451 }
452 }
Steve Block3856b092011-10-20 11:56:00 +0100453 ALOGV("createTrack() lSessionId: %d", lSessionId);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700454
Glenn Kastena075db42012-03-06 11:22:44 -0800455 bool isTimed = (flags & IAudioFlinger::TRACK_TIMED) != 0;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700456 track = thread->createTrack_l(client, streamType, sampleRate, format,
Glenn Kasten73d22752012-03-19 13:38:30 -0700457 channelMask, frameCount, sharedBuffer, lSessionId, flags, &lStatus);
Eric Laurent39e94f82010-07-28 01:32:47 -0700458
459 // move effect chain to this output thread if an effect on same session was waiting
460 // for a track to be created
461 if (lStatus == NO_ERROR && effectThread != NULL) {
462 Mutex::Autolock _dl(thread->mLock);
463 Mutex::Autolock _sl(effectThread->mLock);
464 moveEffectChain_l(lSessionId, effectThread, thread, true);
465 }
Eric Laurenta011e352012-03-29 15:51:43 -0700466
467 // Look for sync events awaiting for a session to be used.
468 for (int i = 0; i < (int)mPendingSyncEvents.size(); i++) {
469 if (mPendingSyncEvents[i]->triggerSession() == lSessionId) {
470 if (thread->isValidSyncEvent(mPendingSyncEvents[i])) {
471 track->setSyncEvent(mPendingSyncEvents[i]);
472 mPendingSyncEvents.removeAt(i);
473 i--;
474 }
475 }
476 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700477 }
478 if (lStatus == NO_ERROR) {
479 trackHandle = new TrackHandle(track);
480 } else {
481 // remove local strong reference to Client before deleting the Track so that the Client
482 // destructor is called by the TrackBase destructor with mLock held
483 client.clear();
484 track.clear();
485 }
486
487Exit:
Glenn Kastene53b9ea2012-03-12 16:29:55 -0700488 if (status != NULL) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700489 *status = lStatus;
490 }
491 return trackHandle;
492}
493
Glenn Kasten72ef00d2012-01-17 11:09:42 -0800494uint32_t AudioFlinger::sampleRate(audio_io_handle_t output) const
Mathias Agopian65ab4712010-07-14 17:59:35 -0700495{
496 Mutex::Autolock _l(mLock);
497 PlaybackThread *thread = checkPlaybackThread_l(output);
498 if (thread == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +0000499 ALOGW("sampleRate() unknown thread %d", output);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700500 return 0;
501 }
502 return thread->sampleRate();
503}
504
Glenn Kasten72ef00d2012-01-17 11:09:42 -0800505int AudioFlinger::channelCount(audio_io_handle_t output) const
Mathias Agopian65ab4712010-07-14 17:59:35 -0700506{
507 Mutex::Autolock _l(mLock);
508 PlaybackThread *thread = checkPlaybackThread_l(output);
509 if (thread == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +0000510 ALOGW("channelCount() unknown thread %d", output);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700511 return 0;
512 }
513 return thread->channelCount();
514}
515
Glenn Kasten72ef00d2012-01-17 11:09:42 -0800516audio_format_t AudioFlinger::format(audio_io_handle_t output) const
Mathias Agopian65ab4712010-07-14 17:59:35 -0700517{
518 Mutex::Autolock _l(mLock);
519 PlaybackThread *thread = checkPlaybackThread_l(output);
520 if (thread == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +0000521 ALOGW("format() unknown thread %d", output);
Glenn Kasten58f30212012-01-12 12:27:51 -0800522 return AUDIO_FORMAT_INVALID;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700523 }
524 return thread->format();
525}
526
Glenn Kasten72ef00d2012-01-17 11:09:42 -0800527size_t AudioFlinger::frameCount(audio_io_handle_t output) const
Mathias Agopian65ab4712010-07-14 17:59:35 -0700528{
529 Mutex::Autolock _l(mLock);
530 PlaybackThread *thread = checkPlaybackThread_l(output);
531 if (thread == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +0000532 ALOGW("frameCount() unknown thread %d", output);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700533 return 0;
534 }
535 return thread->frameCount();
536}
537
Glenn Kasten72ef00d2012-01-17 11:09:42 -0800538uint32_t AudioFlinger::latency(audio_io_handle_t output) const
Mathias Agopian65ab4712010-07-14 17:59:35 -0700539{
540 Mutex::Autolock _l(mLock);
541 PlaybackThread *thread = checkPlaybackThread_l(output);
542 if (thread == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +0000543 ALOGW("latency() unknown thread %d", output);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700544 return 0;
545 }
546 return thread->latency();
547}
548
549status_t AudioFlinger::setMasterVolume(float value)
550{
Eric Laurenta1884f92011-08-23 08:25:03 -0700551 status_t ret = initCheck();
552 if (ret != NO_ERROR) {
553 return ret;
554 }
555
Mathias Agopian65ab4712010-07-14 17:59:35 -0700556 // check calling permissions
557 if (!settingsAllowed()) {
558 return PERMISSION_DENIED;
559 }
560
John Grossman4ff14ba2012-02-08 16:37:41 -0800561 float swmv = value;
562
Eric Laurenta4c5a552012-03-29 10:12:40 -0700563 Mutex::Autolock _l(mLock);
564
Mathias Agopian65ab4712010-07-14 17:59:35 -0700565 // when hw supports master volume, don't scale in sw mixer
John Grossman4ff14ba2012-02-08 16:37:41 -0800566 if (MVS_NONE != mMasterVolumeSupportLvl) {
567 for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
568 AutoMutex lock(mHardwareLock);
Eric Laurenta4c5a552012-03-29 10:12:40 -0700569 audio_hw_device_t *dev = mAudioHwDevs.valueAt(i)->hwDevice();
John Grossman4ff14ba2012-02-08 16:37:41 -0800570
571 mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
572 if (NULL != dev->set_master_volume) {
573 dev->set_master_volume(dev, value);
574 }
575 mHardwareStatus = AUDIO_HW_IDLE;
Eric Laurent93575202011-01-18 18:39:02 -0800576 }
John Grossman4ff14ba2012-02-08 16:37:41 -0800577
578 swmv = 1.0;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700579 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700580
John Grossman4ff14ba2012-02-08 16:37:41 -0800581 mMasterVolume = value;
582 mMasterVolumeSW = swmv;
Glenn Kasten8d6a2442012-02-08 14:04:28 -0800583 for (size_t i = 0; i < mPlaybackThreads.size(); i++)
Glenn Kastene53b9ea2012-03-12 16:29:55 -0700584 mPlaybackThreads.valueAt(i)->setMasterVolume(swmv);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700585
586 return NO_ERROR;
587}
588
Glenn Kastenf78aee72012-01-04 11:00:47 -0800589status_t AudioFlinger::setMode(audio_mode_t mode)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700590{
Eric Laurenta1884f92011-08-23 08:25:03 -0700591 status_t ret = initCheck();
592 if (ret != NO_ERROR) {
593 return ret;
594 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700595
596 // check calling permissions
597 if (!settingsAllowed()) {
598 return PERMISSION_DENIED;
599 }
Glenn Kasten930f4ca2012-01-06 16:47:31 -0800600 if (uint32_t(mode) >= AUDIO_MODE_CNT) {
Steve Block5ff1dd52012-01-05 23:22:43 +0000601 ALOGW("Illegal value: setMode(%d)", mode);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700602 return BAD_VALUE;
603 }
604
605 { // scope for the lock
606 AutoMutex lock(mHardwareLock);
607 mHardwareStatus = AUDIO_HW_SET_MODE;
Dima Zavin799a70e2011-04-18 16:57:27 -0700608 ret = mPrimaryHardwareDev->set_mode(mPrimaryHardwareDev, mode);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700609 mHardwareStatus = AUDIO_HW_IDLE;
610 }
611
612 if (NO_ERROR == ret) {
613 Mutex::Autolock _l(mLock);
614 mMode = mode;
Glenn Kasten8d6a2442012-02-08 14:04:28 -0800615 for (size_t i = 0; i < mPlaybackThreads.size(); i++)
Glenn Kastene53b9ea2012-03-12 16:29:55 -0700616 mPlaybackThreads.valueAt(i)->setMode(mode);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700617 }
618
619 return ret;
620}
621
622status_t AudioFlinger::setMicMute(bool state)
623{
Eric Laurenta1884f92011-08-23 08:25:03 -0700624 status_t ret = initCheck();
625 if (ret != NO_ERROR) {
626 return ret;
627 }
628
Mathias Agopian65ab4712010-07-14 17:59:35 -0700629 // check calling permissions
630 if (!settingsAllowed()) {
631 return PERMISSION_DENIED;
632 }
633
634 AutoMutex lock(mHardwareLock);
635 mHardwareStatus = AUDIO_HW_SET_MIC_MUTE;
Eric Laurenta1884f92011-08-23 08:25:03 -0700636 ret = mPrimaryHardwareDev->set_mic_mute(mPrimaryHardwareDev, state);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700637 mHardwareStatus = AUDIO_HW_IDLE;
638 return ret;
639}
640
641bool AudioFlinger::getMicMute() const
642{
Eric Laurenta1884f92011-08-23 08:25:03 -0700643 status_t ret = initCheck();
644 if (ret != NO_ERROR) {
645 return false;
646 }
647
Dima Zavinfce7a472011-04-19 22:30:36 -0700648 bool state = AUDIO_MODE_INVALID;
Glenn Kasten2b213bc2012-02-02 14:05:20 -0800649 AutoMutex lock(mHardwareLock);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700650 mHardwareStatus = AUDIO_HW_GET_MIC_MUTE;
Dima Zavin799a70e2011-04-18 16:57:27 -0700651 mPrimaryHardwareDev->get_mic_mute(mPrimaryHardwareDev, &state);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700652 mHardwareStatus = AUDIO_HW_IDLE;
653 return state;
654}
655
656status_t AudioFlinger::setMasterMute(bool muted)
657{
658 // check calling permissions
659 if (!settingsAllowed()) {
660 return PERMISSION_DENIED;
661 }
662
Eric Laurent93575202011-01-18 18:39:02 -0800663 Mutex::Autolock _l(mLock);
Glenn Kasten99e53b82012-01-19 08:59:58 -0800664 // This is an optimization, so PlaybackThread doesn't have to look at the one from AudioFlinger
Mathias Agopian65ab4712010-07-14 17:59:35 -0700665 mMasterMute = muted;
Glenn Kasten8d6a2442012-02-08 14:04:28 -0800666 for (size_t i = 0; i < mPlaybackThreads.size(); i++)
Glenn Kastene53b9ea2012-03-12 16:29:55 -0700667 mPlaybackThreads.valueAt(i)->setMasterMute(muted);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700668
669 return NO_ERROR;
670}
671
672float AudioFlinger::masterVolume() const
673{
Glenn Kasten98067102011-12-13 11:47:54 -0800674 Mutex::Autolock _l(mLock);
675 return masterVolume_l();
Mathias Agopian65ab4712010-07-14 17:59:35 -0700676}
677
John Grossman4ff14ba2012-02-08 16:37:41 -0800678float AudioFlinger::masterVolumeSW() const
679{
680 Mutex::Autolock _l(mLock);
681 return masterVolumeSW_l();
682}
683
Mathias Agopian65ab4712010-07-14 17:59:35 -0700684bool AudioFlinger::masterMute() const
685{
Glenn Kasten98067102011-12-13 11:47:54 -0800686 Mutex::Autolock _l(mLock);
687 return masterMute_l();
Mathias Agopian65ab4712010-07-14 17:59:35 -0700688}
689
John Grossman4ff14ba2012-02-08 16:37:41 -0800690float AudioFlinger::masterVolume_l() const
691{
692 if (MVS_FULL == mMasterVolumeSupportLvl) {
693 float ret_val;
694 AutoMutex lock(mHardwareLock);
695
696 mHardwareStatus = AUDIO_HW_GET_MASTER_VOLUME;
Glenn Kasten5798d4e2012-03-08 12:18:35 -0800697 ALOG_ASSERT((NULL != mPrimaryHardwareDev) &&
698 (NULL != mPrimaryHardwareDev->get_master_volume),
699 "can't get master volume");
John Grossman4ff14ba2012-02-08 16:37:41 -0800700
701 mPrimaryHardwareDev->get_master_volume(mPrimaryHardwareDev, &ret_val);
702 mHardwareStatus = AUDIO_HW_IDLE;
703 return ret_val;
704 }
705
706 return mMasterVolume;
707}
708
Glenn Kasten72ef00d2012-01-17 11:09:42 -0800709status_t AudioFlinger::setStreamVolume(audio_stream_type_t stream, float value,
710 audio_io_handle_t output)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700711{
712 // check calling permissions
713 if (!settingsAllowed()) {
714 return PERMISSION_DENIED;
715 }
716
Glenn Kasten263709e2012-01-06 08:40:01 -0800717 if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
Steve Block29357bc2012-01-06 19:20:56 +0000718 ALOGE("setStreamVolume() invalid stream %d", stream);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700719 return BAD_VALUE;
720 }
721
722 AutoMutex lock(mLock);
723 PlaybackThread *thread = NULL;
724 if (output) {
725 thread = checkPlaybackThread_l(output);
726 if (thread == NULL) {
727 return BAD_VALUE;
728 }
729 }
730
731 mStreamTypes[stream].volume = value;
732
733 if (thread == NULL) {
Glenn Kasten8d6a2442012-02-08 14:04:28 -0800734 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
Glenn Kastene53b9ea2012-03-12 16:29:55 -0700735 mPlaybackThreads.valueAt(i)->setStreamVolume(stream, value);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700736 }
737 } else {
738 thread->setStreamVolume(stream, value);
739 }
740
741 return NO_ERROR;
742}
743
Glenn Kastenfff6d712012-01-12 16:38:12 -0800744status_t AudioFlinger::setStreamMute(audio_stream_type_t stream, bool muted)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700745{
746 // check calling permissions
747 if (!settingsAllowed()) {
748 return PERMISSION_DENIED;
749 }
750
Glenn Kasten263709e2012-01-06 08:40:01 -0800751 if (uint32_t(stream) >= AUDIO_STREAM_CNT ||
Dima Zavinfce7a472011-04-19 22:30:36 -0700752 uint32_t(stream) == AUDIO_STREAM_ENFORCED_AUDIBLE) {
Steve Block29357bc2012-01-06 19:20:56 +0000753 ALOGE("setStreamMute() invalid stream %d", stream);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700754 return BAD_VALUE;
755 }
756
Eric Laurent93575202011-01-18 18:39:02 -0800757 AutoMutex lock(mLock);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700758 mStreamTypes[stream].mute = muted;
759 for (uint32_t i = 0; i < mPlaybackThreads.size(); i++)
Glenn Kastene53b9ea2012-03-12 16:29:55 -0700760 mPlaybackThreads.valueAt(i)->setStreamMute(stream, muted);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700761
762 return NO_ERROR;
763}
764
Glenn Kasten72ef00d2012-01-17 11:09:42 -0800765float AudioFlinger::streamVolume(audio_stream_type_t stream, audio_io_handle_t output) const
Mathias Agopian65ab4712010-07-14 17:59:35 -0700766{
Glenn Kasten263709e2012-01-06 08:40:01 -0800767 if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700768 return 0.0f;
769 }
770
771 AutoMutex lock(mLock);
772 float volume;
773 if (output) {
774 PlaybackThread *thread = checkPlaybackThread_l(output);
775 if (thread == NULL) {
776 return 0.0f;
777 }
778 volume = thread->streamVolume(stream);
779 } else {
Glenn Kasten6637baa2012-01-09 09:40:36 -0800780 volume = streamVolume_l(stream);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700781 }
782
783 return volume;
784}
785
Glenn Kastenfff6d712012-01-12 16:38:12 -0800786bool AudioFlinger::streamMute(audio_stream_type_t stream) const
Mathias Agopian65ab4712010-07-14 17:59:35 -0700787{
Glenn Kasten263709e2012-01-06 08:40:01 -0800788 if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700789 return true;
790 }
791
Glenn Kasten6637baa2012-01-09 09:40:36 -0800792 AutoMutex lock(mLock);
793 return streamMute_l(stream);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700794}
795
Glenn Kasten72ef00d2012-01-17 11:09:42 -0800796status_t AudioFlinger::setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700797{
Glenn Kasten23d82a92012-02-03 11:10:00 -0800798 ALOGV("setParameters(): io %d, keyvalue %s, tid %d, calling pid %d",
Mathias Agopian65ab4712010-07-14 17:59:35 -0700799 ioHandle, keyValuePairs.string(), gettid(), IPCThreadState::self()->getCallingPid());
800 // check calling permissions
801 if (!settingsAllowed()) {
802 return PERMISSION_DENIED;
803 }
804
Mathias Agopian65ab4712010-07-14 17:59:35 -0700805 // ioHandle == 0 means the parameters are global to the audio hardware interface
806 if (ioHandle == 0) {
Eric Laurenta4c5a552012-03-29 10:12:40 -0700807 Mutex::Autolock _l(mLock);
Dima Zavin799a70e2011-04-18 16:57:27 -0700808 status_t final_result = NO_ERROR;
Glenn Kasten8abf44d2012-02-02 14:16:03 -0800809 {
Eric Laurenta4c5a552012-03-29 10:12:40 -0700810 AutoMutex lock(mHardwareLock);
811 mHardwareStatus = AUDIO_HW_SET_PARAMETER;
812 for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
813 audio_hw_device_t *dev = mAudioHwDevs.valueAt(i)->hwDevice();
814 status_t result = dev->set_parameters(dev, keyValuePairs.string());
815 final_result = result ?: final_result;
816 }
817 mHardwareStatus = AUDIO_HW_IDLE;
Glenn Kasten8abf44d2012-02-02 14:16:03 -0800818 }
Eric Laurent59bd0da2011-08-01 09:52:20 -0700819 // disable AEC and NS if the device is a BT SCO headset supporting those pre processings
820 AudioParameter param = AudioParameter(keyValuePairs);
821 String8 value;
822 if (param.get(String8(AUDIO_PARAMETER_KEY_BT_NREC), value) == NO_ERROR) {
Eric Laurentbee53372011-08-29 12:42:48 -0700823 bool btNrecIsOff = (value == AUDIO_PARAMETER_VALUE_OFF);
824 if (mBtNrecIsOff != btNrecIsOff) {
Eric Laurent59bd0da2011-08-01 09:52:20 -0700825 for (size_t i = 0; i < mRecordThreads.size(); i++) {
826 sp<RecordThread> thread = mRecordThreads.valueAt(i);
827 RecordThread::RecordTrack *track = thread->track();
828 if (track != NULL) {
829 audio_devices_t device = (audio_devices_t)(
830 thread->device() & AUDIO_DEVICE_IN_ALL);
Eric Laurentbee53372011-08-29 12:42:48 -0700831 bool suspend = audio_is_bluetooth_sco_device(device) && btNrecIsOff;
Eric Laurent59bd0da2011-08-01 09:52:20 -0700832 thread->setEffectSuspended(FX_IID_AEC,
833 suspend,
834 track->sessionId());
835 thread->setEffectSuspended(FX_IID_NS,
836 suspend,
837 track->sessionId());
838 }
839 }
Eric Laurentbee53372011-08-29 12:42:48 -0700840 mBtNrecIsOff = btNrecIsOff;
Eric Laurent59bd0da2011-08-01 09:52:20 -0700841 }
842 }
Dima Zavin799a70e2011-04-18 16:57:27 -0700843 return final_result;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700844 }
845
846 // hold a strong ref on thread in case closeOutput() or closeInput() is called
847 // and the thread is exited once the lock is released
848 sp<ThreadBase> thread;
849 {
850 Mutex::Autolock _l(mLock);
851 thread = checkPlaybackThread_l(ioHandle);
852 if (thread == NULL) {
853 thread = checkRecordThread_l(ioHandle);
Glenn Kasten7fc9a6f2012-01-10 10:46:34 -0800854 } else if (thread == primaryPlaybackThread_l()) {
Eric Laurent7c7f10b2011-06-17 21:29:58 -0700855 // indicate output device change to all input threads for pre processing
856 AudioParameter param = AudioParameter(keyValuePairs);
857 int value;
Eric Laurent89d94e72012-03-16 20:37:59 -0700858 if ((param.getInt(String8(AudioParameter::keyRouting), value) == NO_ERROR) &&
859 (value != 0)) {
Eric Laurent7c7f10b2011-06-17 21:29:58 -0700860 for (size_t i = 0; i < mRecordThreads.size(); i++) {
861 mRecordThreads.valueAt(i)->setParameters(keyValuePairs);
862 }
863 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700864 }
865 }
Glenn Kasten7378ca52012-01-20 13:44:40 -0800866 if (thread != 0) {
867 return thread->setParameters(keyValuePairs);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700868 }
869 return BAD_VALUE;
870}
871
Glenn Kasten72ef00d2012-01-17 11:09:42 -0800872String8 AudioFlinger::getParameters(audio_io_handle_t ioHandle, const String8& keys) const
Mathias Agopian65ab4712010-07-14 17:59:35 -0700873{
Glenn Kasten23d82a92012-02-03 11:10:00 -0800874// ALOGV("getParameters() io %d, keys %s, tid %d, calling pid %d",
Mathias Agopian65ab4712010-07-14 17:59:35 -0700875// ioHandle, keys.string(), gettid(), IPCThreadState::self()->getCallingPid());
876
Eric Laurenta4c5a552012-03-29 10:12:40 -0700877 Mutex::Autolock _l(mLock);
878
Mathias Agopian65ab4712010-07-14 17:59:35 -0700879 if (ioHandle == 0) {
Dima Zavinfce7a472011-04-19 22:30:36 -0700880 String8 out_s8;
881
Dima Zavin799a70e2011-04-18 16:57:27 -0700882 for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
Glenn Kasten8abf44d2012-02-02 14:16:03 -0800883 char *s;
884 {
885 AutoMutex lock(mHardwareLock);
886 mHardwareStatus = AUDIO_HW_GET_PARAMETER;
Eric Laurenta4c5a552012-03-29 10:12:40 -0700887 audio_hw_device_t *dev = mAudioHwDevs.valueAt(i)->hwDevice();
Glenn Kasten8abf44d2012-02-02 14:16:03 -0800888 s = dev->get_parameters(dev, keys.string());
889 mHardwareStatus = AUDIO_HW_IDLE;
890 }
John Grossmanef7740b2012-02-09 11:28:36 -0800891 out_s8 += String8(s ? s : "");
Dima Zavin799a70e2011-04-18 16:57:27 -0700892 free(s);
893 }
Dima Zavinfce7a472011-04-19 22:30:36 -0700894 return out_s8;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700895 }
896
Mathias Agopian65ab4712010-07-14 17:59:35 -0700897 PlaybackThread *playbackThread = checkPlaybackThread_l(ioHandle);
898 if (playbackThread != NULL) {
899 return playbackThread->getParameters(keys);
900 }
901 RecordThread *recordThread = checkRecordThread_l(ioHandle);
902 if (recordThread != NULL) {
903 return recordThread->getParameters(keys);
904 }
905 return String8("");
906}
907
Glenn Kastenf587ba52012-01-26 16:25:10 -0800908size_t AudioFlinger::getInputBufferSize(uint32_t sampleRate, audio_format_t format, int channelCount) const
Mathias Agopian65ab4712010-07-14 17:59:35 -0700909{
Eric Laurenta1884f92011-08-23 08:25:03 -0700910 status_t ret = initCheck();
911 if (ret != NO_ERROR) {
912 return 0;
913 }
914
Glenn Kasten2b213bc2012-02-02 14:05:20 -0800915 AutoMutex lock(mHardwareLock);
916 mHardwareStatus = AUDIO_HW_GET_INPUT_BUFFER_SIZE;
917 size_t size = mPrimaryHardwareDev->get_input_buffer_size(mPrimaryHardwareDev, sampleRate, format, channelCount);
918 mHardwareStatus = AUDIO_HW_IDLE;
919 return size;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700920}
921
Glenn Kasten72ef00d2012-01-17 11:09:42 -0800922unsigned int AudioFlinger::getInputFramesLost(audio_io_handle_t ioHandle) const
Mathias Agopian65ab4712010-07-14 17:59:35 -0700923{
924 if (ioHandle == 0) {
925 return 0;
926 }
927
928 Mutex::Autolock _l(mLock);
929
930 RecordThread *recordThread = checkRecordThread_l(ioHandle);
931 if (recordThread != NULL) {
932 return recordThread->getInputFramesLost();
933 }
934 return 0;
935}
936
937status_t AudioFlinger::setVoiceVolume(float value)
938{
Eric Laurenta1884f92011-08-23 08:25:03 -0700939 status_t ret = initCheck();
940 if (ret != NO_ERROR) {
941 return ret;
942 }
943
Mathias Agopian65ab4712010-07-14 17:59:35 -0700944 // check calling permissions
945 if (!settingsAllowed()) {
946 return PERMISSION_DENIED;
947 }
948
949 AutoMutex lock(mHardwareLock);
Glenn Kasten8abf44d2012-02-02 14:16:03 -0800950 mHardwareStatus = AUDIO_HW_SET_VOICE_VOLUME;
Eric Laurenta1884f92011-08-23 08:25:03 -0700951 ret = mPrimaryHardwareDev->set_voice_volume(mPrimaryHardwareDev, value);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700952 mHardwareStatus = AUDIO_HW_IDLE;
953
954 return ret;
955}
956
Glenn Kasten72ef00d2012-01-17 11:09:42 -0800957status_t AudioFlinger::getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames,
958 audio_io_handle_t output) const
Mathias Agopian65ab4712010-07-14 17:59:35 -0700959{
960 status_t status;
961
962 Mutex::Autolock _l(mLock);
963
964 PlaybackThread *playbackThread = checkPlaybackThread_l(output);
965 if (playbackThread != NULL) {
966 return playbackThread->getRenderPosition(halFrames, dspFrames);
967 }
968
969 return BAD_VALUE;
970}
971
972void AudioFlinger::registerClient(const sp<IAudioFlingerClient>& client)
973{
974
975 Mutex::Autolock _l(mLock);
976
Glenn Kastenbb001922012-02-03 11:10:26 -0800977 pid_t pid = IPCThreadState::self()->getCallingPid();
Mathias Agopian65ab4712010-07-14 17:59:35 -0700978 if (mNotificationClients.indexOfKey(pid) < 0) {
979 sp<NotificationClient> notificationClient = new NotificationClient(this,
980 client,
981 pid);
Steve Block3856b092011-10-20 11:56:00 +0100982 ALOGV("registerClient() client %p, pid %d", notificationClient.get(), pid);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700983
984 mNotificationClients.add(pid, notificationClient);
985
986 sp<IBinder> binder = client->asBinder();
987 binder->linkToDeath(notificationClient);
988
989 // the config change is always sent from playback or record threads to avoid deadlock
990 // with AudioSystem::gLock
991 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
992 mPlaybackThreads.valueAt(i)->sendConfigEvent(AudioSystem::OUTPUT_OPENED);
993 }
994
995 for (size_t i = 0; i < mRecordThreads.size(); i++) {
996 mRecordThreads.valueAt(i)->sendConfigEvent(AudioSystem::INPUT_OPENED);
997 }
998 }
999}
1000
1001void AudioFlinger::removeNotificationClient(pid_t pid)
1002{
1003 Mutex::Autolock _l(mLock);
1004
Glenn Kastena3b09252012-01-20 09:19:01 -08001005 mNotificationClients.removeItem(pid);
Marco Nelissen3a34bef2011-08-02 13:33:41 -07001006
Steve Block3856b092011-10-20 11:56:00 +01001007 ALOGV("%d died, releasing its sessions", pid);
Glenn Kasten8d6a2442012-02-08 14:04:28 -08001008 size_t num = mAudioSessionRefs.size();
Marco Nelissen3a34bef2011-08-02 13:33:41 -07001009 bool removed = false;
Glenn Kasten8d6a2442012-02-08 14:04:28 -08001010 for (size_t i = 0; i< num; ) {
Marco Nelissen3a34bef2011-08-02 13:33:41 -07001011 AudioSessionRef *ref = mAudioSessionRefs.itemAt(i);
Glenn Kasten012ca6b2012-03-06 11:22:01 -08001012 ALOGV(" pid %d @ %d", ref->mPid, i);
1013 if (ref->mPid == pid) {
1014 ALOGV(" removing entry for pid %d session %d", pid, ref->mSessionid);
Marco Nelissen3a34bef2011-08-02 13:33:41 -07001015 mAudioSessionRefs.removeAt(i);
1016 delete ref;
1017 removed = true;
Marco Nelissen3a34bef2011-08-02 13:33:41 -07001018 num--;
Glenn Kasten8d6a2442012-02-08 14:04:28 -08001019 } else {
1020 i++;
Marco Nelissen3a34bef2011-08-02 13:33:41 -07001021 }
1022 }
1023 if (removed) {
1024 purgeStaleEffects_l();
1025 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07001026}
1027
1028// audioConfigChanged_l() must be called with AudioFlinger::mLock held
Glenn Kastenb81cc8c2012-03-01 09:14:51 -08001029void AudioFlinger::audioConfigChanged_l(int event, audio_io_handle_t ioHandle, const void *param2)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001030{
1031 size_t size = mNotificationClients.size();
1032 for (size_t i = 0; i < size; i++) {
Glenn Kasten84afa3b2012-01-25 15:28:08 -08001033 mNotificationClients.valueAt(i)->audioFlingerClient()->ioConfigChanged(event, ioHandle,
1034 param2);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001035 }
1036}
1037
1038// removeClient_l() must be called with AudioFlinger::mLock held
1039void AudioFlinger::removeClient_l(pid_t pid)
1040{
Steve Block3856b092011-10-20 11:56:00 +01001041 ALOGV("removeClient_l() pid %d, tid %d, calling tid %d", pid, gettid(), IPCThreadState::self()->getCallingPid());
Mathias Agopian65ab4712010-07-14 17:59:35 -07001042 mClients.removeItem(pid);
1043}
1044
1045
1046// ----------------------------------------------------------------------------
1047
Glenn Kasten72ef00d2012-01-17 11:09:42 -08001048AudioFlinger::ThreadBase::ThreadBase(const sp<AudioFlinger>& audioFlinger, audio_io_handle_t id,
1049 uint32_t device, type_t type)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001050 : Thread(false),
Glenn Kasten23bb8be2012-01-26 10:38:26 -08001051 mType(type),
Glenn Kasten84afa3b2012-01-25 15:28:08 -08001052 mAudioFlinger(audioFlinger), mSampleRate(0), mFrameCount(0),
1053 // mChannelMask
1054 mChannelCount(0),
1055 mFrameSize(1), mFormat(AUDIO_FORMAT_INVALID),
1056 mParamStatus(NO_ERROR),
Glenn Kastenb28686f2012-01-06 08:39:38 -08001057 mStandby(false), mId(id),
Glenn Kasten84afa3b2012-01-25 15:28:08 -08001058 mDevice(device),
1059 mDeathRecipient(new PMDeathRecipient(this))
Mathias Agopian65ab4712010-07-14 17:59:35 -07001060{
1061}
1062
1063AudioFlinger::ThreadBase::~ThreadBase()
1064{
1065 mParamCond.broadcast();
Eric Laurentfeb0db62011-07-22 09:04:31 -07001066 // do not lock the mutex in destructor
1067 releaseWakeLock_l();
Eric Laurent9d18ec52011-09-27 12:07:15 -07001068 if (mPowerManager != 0) {
1069 sp<IBinder> binder = mPowerManager->asBinder();
1070 binder->unlinkToDeath(mDeathRecipient);
1071 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07001072}
1073
1074void AudioFlinger::ThreadBase::exit()
1075{
Steve Block3856b092011-10-20 11:56:00 +01001076 ALOGV("ThreadBase::exit");
Mathias Agopian65ab4712010-07-14 17:59:35 -07001077 {
Glenn Kastenb28686f2012-01-06 08:39:38 -08001078 // This lock prevents the following race in thread (uniprocessor for illustration):
1079 // if (!exitPending()) {
1080 // // context switch from here to exit()
1081 // // exit() calls requestExit(), what exitPending() observes
1082 // // exit() calls signal(), which is dropped since no waiters
1083 // // context switch back from exit() to here
1084 // mWaitWorkCV.wait(...);
1085 // // now thread is hung
1086 // }
Glenn Kastena7d8d6f2012-01-05 15:41:56 -08001087 AutoMutex lock(mLock);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001088 requestExit();
1089 mWaitWorkCV.signal();
1090 }
Glenn Kastenb28686f2012-01-06 08:39:38 -08001091 // When Thread::requestExitAndWait is made virtual and this method is renamed to
1092 // "virtual status_t requestExitAndWait()", replace by "return Thread::requestExitAndWait();"
Mathias Agopian65ab4712010-07-14 17:59:35 -07001093 requestExitAndWait();
1094}
1095
Mathias Agopian65ab4712010-07-14 17:59:35 -07001096status_t AudioFlinger::ThreadBase::setParameters(const String8& keyValuePairs)
1097{
1098 status_t status;
1099
Steve Block3856b092011-10-20 11:56:00 +01001100 ALOGV("ThreadBase::setParameters() %s", keyValuePairs.string());
Mathias Agopian65ab4712010-07-14 17:59:35 -07001101 Mutex::Autolock _l(mLock);
1102
1103 mNewParameters.add(keyValuePairs);
1104 mWaitWorkCV.signal();
1105 // wait condition with timeout in case the thread loop has exited
1106 // before the request could be processed
Glenn Kasten7dede872011-12-13 11:04:14 -08001107 if (mParamCond.waitRelative(mLock, kSetParametersTimeoutNs) == NO_ERROR) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001108 status = mParamStatus;
1109 mWaitWorkCV.signal();
1110 } else {
1111 status = TIMED_OUT;
1112 }
1113 return status;
1114}
1115
1116void AudioFlinger::ThreadBase::sendConfigEvent(int event, int param)
1117{
1118 Mutex::Autolock _l(mLock);
1119 sendConfigEvent_l(event, param);
1120}
1121
1122// sendConfigEvent_l() must be called with ThreadBase::mLock held
1123void AudioFlinger::ThreadBase::sendConfigEvent_l(int event, int param)
1124{
Glenn Kastenf3990f22011-12-13 11:50:00 -08001125 ConfigEvent configEvent;
1126 configEvent.mEvent = event;
1127 configEvent.mParam = param;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001128 mConfigEvents.add(configEvent);
Steve Block3856b092011-10-20 11:56:00 +01001129 ALOGV("sendConfigEvent() num events %d event %d, param %d", mConfigEvents.size(), event, param);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001130 mWaitWorkCV.signal();
1131}
1132
1133void AudioFlinger::ThreadBase::processConfigEvents()
1134{
1135 mLock.lock();
Glenn Kastene53b9ea2012-03-12 16:29:55 -07001136 while (!mConfigEvents.isEmpty()) {
Steve Block3856b092011-10-20 11:56:00 +01001137 ALOGV("processConfigEvents() remaining events %d", mConfigEvents.size());
Glenn Kastenf3990f22011-12-13 11:50:00 -08001138 ConfigEvent configEvent = mConfigEvents[0];
Mathias Agopian65ab4712010-07-14 17:59:35 -07001139 mConfigEvents.removeAt(0);
1140 // release mLock before locking AudioFlinger mLock: lock order is always
1141 // AudioFlinger then ThreadBase to avoid cross deadlock
1142 mLock.unlock();
1143 mAudioFlinger->mLock.lock();
Glenn Kastenf3990f22011-12-13 11:50:00 -08001144 audioConfigChanged_l(configEvent.mEvent, configEvent.mParam);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001145 mAudioFlinger->mLock.unlock();
Mathias Agopian65ab4712010-07-14 17:59:35 -07001146 mLock.lock();
1147 }
1148 mLock.unlock();
1149}
1150
1151status_t AudioFlinger::ThreadBase::dumpBase(int fd, const Vector<String16>& args)
1152{
1153 const size_t SIZE = 256;
1154 char buffer[SIZE];
1155 String8 result;
1156
1157 bool locked = tryLock(mLock);
1158 if (!locked) {
1159 snprintf(buffer, SIZE, "thread %p maybe dead locked\n", this);
1160 write(fd, buffer, strlen(buffer));
1161 }
1162
Eric Laurent612bbb52012-03-14 15:03:26 -07001163 snprintf(buffer, SIZE, "io handle: %d\n", mId);
1164 result.append(buffer);
1165 snprintf(buffer, SIZE, "TID: %d\n", getTid());
1166 result.append(buffer);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001167 snprintf(buffer, SIZE, "standby: %d\n", mStandby);
1168 result.append(buffer);
1169 snprintf(buffer, SIZE, "Sample rate: %d\n", mSampleRate);
1170 result.append(buffer);
1171 snprintf(buffer, SIZE, "Frame count: %d\n", mFrameCount);
1172 result.append(buffer);
1173 snprintf(buffer, SIZE, "Channel Count: %d\n", mChannelCount);
1174 result.append(buffer);
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07001175 snprintf(buffer, SIZE, "Channel Mask: 0x%08x\n", mChannelMask);
1176 result.append(buffer);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001177 snprintf(buffer, SIZE, "Format: %d\n", mFormat);
1178 result.append(buffer);
Glenn Kastenb9980652012-01-11 09:48:27 -08001179 snprintf(buffer, SIZE, "Frame size: %u\n", mFrameSize);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001180 result.append(buffer);
1181
1182 snprintf(buffer, SIZE, "\nPending setParameters commands: \n");
1183 result.append(buffer);
1184 result.append(" Index Command");
1185 for (size_t i = 0; i < mNewParameters.size(); ++i) {
1186 snprintf(buffer, SIZE, "\n %02d ", i);
1187 result.append(buffer);
1188 result.append(mNewParameters[i]);
1189 }
1190
1191 snprintf(buffer, SIZE, "\n\nPending config events: \n");
1192 result.append(buffer);
1193 snprintf(buffer, SIZE, " Index event param\n");
1194 result.append(buffer);
1195 for (size_t i = 0; i < mConfigEvents.size(); i++) {
Glenn Kastenf3990f22011-12-13 11:50:00 -08001196 snprintf(buffer, SIZE, " %02d %02d %d\n", i, mConfigEvents[i].mEvent, mConfigEvents[i].mParam);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001197 result.append(buffer);
1198 }
1199 result.append("\n");
1200
1201 write(fd, result.string(), result.size());
1202
1203 if (locked) {
1204 mLock.unlock();
1205 }
1206 return NO_ERROR;
1207}
1208
Eric Laurent1d2bff02011-07-24 17:49:51 -07001209status_t AudioFlinger::ThreadBase::dumpEffectChains(int fd, const Vector<String16>& args)
1210{
1211 const size_t SIZE = 256;
1212 char buffer[SIZE];
1213 String8 result;
1214
1215 snprintf(buffer, SIZE, "\n- %d Effect Chains:\n", mEffectChains.size());
1216 write(fd, buffer, strlen(buffer));
1217
1218 for (size_t i = 0; i < mEffectChains.size(); ++i) {
1219 sp<EffectChain> chain = mEffectChains[i];
1220 if (chain != 0) {
1221 chain->dump(fd, args);
1222 }
1223 }
1224 return NO_ERROR;
1225}
1226
Eric Laurentfeb0db62011-07-22 09:04:31 -07001227void AudioFlinger::ThreadBase::acquireWakeLock()
1228{
1229 Mutex::Autolock _l(mLock);
1230 acquireWakeLock_l();
1231}
1232
1233void AudioFlinger::ThreadBase::acquireWakeLock_l()
1234{
1235 if (mPowerManager == 0) {
1236 // use checkService() to avoid blocking if power service is not up yet
1237 sp<IBinder> binder =
1238 defaultServiceManager()->checkService(String16("power"));
1239 if (binder == 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00001240 ALOGW("Thread %s cannot connect to the power manager service", mName);
Eric Laurentfeb0db62011-07-22 09:04:31 -07001241 } else {
1242 mPowerManager = interface_cast<IPowerManager>(binder);
1243 binder->linkToDeath(mDeathRecipient);
1244 }
1245 }
1246 if (mPowerManager != 0) {
1247 sp<IBinder> binder = new BBinder();
1248 status_t status = mPowerManager->acquireWakeLock(POWERMANAGER_PARTIAL_WAKE_LOCK,
1249 binder,
1250 String16(mName));
1251 if (status == NO_ERROR) {
1252 mWakeLockToken = binder;
1253 }
Steve Block3856b092011-10-20 11:56:00 +01001254 ALOGV("acquireWakeLock_l() %s status %d", mName, status);
Eric Laurentfeb0db62011-07-22 09:04:31 -07001255 }
1256}
1257
1258void AudioFlinger::ThreadBase::releaseWakeLock()
1259{
1260 Mutex::Autolock _l(mLock);
Eric Laurent6dbe8832011-07-28 13:59:02 -07001261 releaseWakeLock_l();
Eric Laurentfeb0db62011-07-22 09:04:31 -07001262}
1263
1264void AudioFlinger::ThreadBase::releaseWakeLock_l()
1265{
1266 if (mWakeLockToken != 0) {
Steve Block3856b092011-10-20 11:56:00 +01001267 ALOGV("releaseWakeLock_l() %s", mName);
Eric Laurentfeb0db62011-07-22 09:04:31 -07001268 if (mPowerManager != 0) {
1269 mPowerManager->releaseWakeLock(mWakeLockToken, 0);
1270 }
1271 mWakeLockToken.clear();
1272 }
1273}
1274
1275void AudioFlinger::ThreadBase::clearPowerManager()
1276{
1277 Mutex::Autolock _l(mLock);
1278 releaseWakeLock_l();
1279 mPowerManager.clear();
1280}
1281
1282void AudioFlinger::ThreadBase::PMDeathRecipient::binderDied(const wp<IBinder>& who)
1283{
1284 sp<ThreadBase> thread = mThread.promote();
1285 if (thread != 0) {
1286 thread->clearPowerManager();
1287 }
Steve Block5ff1dd52012-01-05 23:22:43 +00001288 ALOGW("power manager service died !!!");
Eric Laurentfeb0db62011-07-22 09:04:31 -07001289}
Eric Laurent1d2bff02011-07-24 17:49:51 -07001290
Eric Laurent59255e42011-07-27 19:49:51 -07001291void AudioFlinger::ThreadBase::setEffectSuspended(
1292 const effect_uuid_t *type, bool suspend, int sessionId)
1293{
1294 Mutex::Autolock _l(mLock);
1295 setEffectSuspended_l(type, suspend, sessionId);
1296}
1297
1298void AudioFlinger::ThreadBase::setEffectSuspended_l(
1299 const effect_uuid_t *type, bool suspend, int sessionId)
1300{
Glenn Kasten090f0192012-01-30 13:00:02 -08001301 sp<EffectChain> chain = getEffectChain_l(sessionId);
Eric Laurent59255e42011-07-27 19:49:51 -07001302 if (chain != 0) {
1303 if (type != NULL) {
1304 chain->setEffectSuspended_l(type, suspend);
1305 } else {
1306 chain->setEffectSuspendedAll_l(suspend);
1307 }
1308 }
1309
1310 updateSuspendedSessions_l(type, suspend, sessionId);
1311}
1312
1313void AudioFlinger::ThreadBase::checkSuspendOnAddEffectChain_l(const sp<EffectChain>& chain)
1314{
Glenn Kasten8d6a2442012-02-08 14:04:28 -08001315 ssize_t index = mSuspendedSessions.indexOfKey(chain->sessionId());
Eric Laurent59255e42011-07-27 19:49:51 -07001316 if (index < 0) {
1317 return;
1318 }
1319
1320 KeyedVector <int, sp<SuspendedSessionDesc> > sessionEffects =
1321 mSuspendedSessions.editValueAt(index);
1322
1323 for (size_t i = 0; i < sessionEffects.size(); i++) {
Glenn Kastene53b9ea2012-03-12 16:29:55 -07001324 sp<SuspendedSessionDesc> desc = sessionEffects.valueAt(i);
Eric Laurent59255e42011-07-27 19:49:51 -07001325 for (int j = 0; j < desc->mRefCount; j++) {
1326 if (sessionEffects.keyAt(i) == EffectChain::kKeyForSuspendAll) {
1327 chain->setEffectSuspendedAll_l(true);
1328 } else {
Steve Block3856b092011-10-20 11:56:00 +01001329 ALOGV("checkSuspendOnAddEffectChain_l() suspending effects %08x",
Glenn Kastene53b9ea2012-03-12 16:29:55 -07001330 desc->mType.timeLow);
Eric Laurent59255e42011-07-27 19:49:51 -07001331 chain->setEffectSuspended_l(&desc->mType, true);
1332 }
1333 }
1334 }
1335}
1336
Eric Laurent59255e42011-07-27 19:49:51 -07001337void AudioFlinger::ThreadBase::updateSuspendedSessions_l(const effect_uuid_t *type,
1338 bool suspend,
1339 int sessionId)
1340{
Glenn Kasten8d6a2442012-02-08 14:04:28 -08001341 ssize_t index = mSuspendedSessions.indexOfKey(sessionId);
Eric Laurent59255e42011-07-27 19:49:51 -07001342
1343 KeyedVector <int, sp<SuspendedSessionDesc> > sessionEffects;
1344
1345 if (suspend) {
1346 if (index >= 0) {
1347 sessionEffects = mSuspendedSessions.editValueAt(index);
1348 } else {
1349 mSuspendedSessions.add(sessionId, sessionEffects);
1350 }
1351 } else {
1352 if (index < 0) {
1353 return;
1354 }
1355 sessionEffects = mSuspendedSessions.editValueAt(index);
1356 }
1357
1358
1359 int key = EffectChain::kKeyForSuspendAll;
1360 if (type != NULL) {
1361 key = type->timeLow;
1362 }
1363 index = sessionEffects.indexOfKey(key);
1364
Glenn Kastene53b9ea2012-03-12 16:29:55 -07001365 sp<SuspendedSessionDesc> desc;
Eric Laurent59255e42011-07-27 19:49:51 -07001366 if (suspend) {
1367 if (index >= 0) {
1368 desc = sessionEffects.valueAt(index);
1369 } else {
1370 desc = new SuspendedSessionDesc();
1371 if (type != NULL) {
1372 memcpy(&desc->mType, type, sizeof(effect_uuid_t));
1373 }
1374 sessionEffects.add(key, desc);
Steve Block3856b092011-10-20 11:56:00 +01001375 ALOGV("updateSuspendedSessions_l() suspend adding effect %08x", key);
Eric Laurent59255e42011-07-27 19:49:51 -07001376 }
1377 desc->mRefCount++;
1378 } else {
1379 if (index < 0) {
1380 return;
1381 }
1382 desc = sessionEffects.valueAt(index);
1383 if (--desc->mRefCount == 0) {
Steve Block3856b092011-10-20 11:56:00 +01001384 ALOGV("updateSuspendedSessions_l() restore removing effect %08x", key);
Eric Laurent59255e42011-07-27 19:49:51 -07001385 sessionEffects.removeItemsAt(index);
1386 if (sessionEffects.isEmpty()) {
Steve Block3856b092011-10-20 11:56:00 +01001387 ALOGV("updateSuspendedSessions_l() restore removing session %d",
Eric Laurent59255e42011-07-27 19:49:51 -07001388 sessionId);
1389 mSuspendedSessions.removeItem(sessionId);
1390 }
1391 }
1392 }
1393 if (!sessionEffects.isEmpty()) {
1394 mSuspendedSessions.replaceValueFor(sessionId, sessionEffects);
1395 }
1396}
1397
1398void AudioFlinger::ThreadBase::checkSuspendOnEffectEnabled(const sp<EffectModule>& effect,
1399 bool enabled,
1400 int sessionId)
1401{
1402 Mutex::Autolock _l(mLock);
Eric Laurenta85a74a2011-10-19 11:44:54 -07001403 checkSuspendOnEffectEnabled_l(effect, enabled, sessionId);
1404}
Eric Laurent59255e42011-07-27 19:49:51 -07001405
Eric Laurenta85a74a2011-10-19 11:44:54 -07001406void AudioFlinger::ThreadBase::checkSuspendOnEffectEnabled_l(const sp<EffectModule>& effect,
1407 bool enabled,
1408 int sessionId)
1409{
Eric Laurentdb7c0792011-08-10 10:37:50 -07001410 if (mType != RECORD) {
1411 // suspend all effects in AUDIO_SESSION_OUTPUT_MIX when enabling any effect on
1412 // another session. This gives the priority to well behaved effect control panels
1413 // and applications not using global effects.
1414 if (sessionId != AUDIO_SESSION_OUTPUT_MIX) {
1415 setEffectSuspended_l(NULL, enabled, AUDIO_SESSION_OUTPUT_MIX);
1416 }
1417 }
Eric Laurent59255e42011-07-27 19:49:51 -07001418
1419 sp<EffectChain> chain = getEffectChain_l(sessionId);
1420 if (chain != 0) {
1421 chain->checkSuspendOnEffectEnabled(effect, enabled);
1422 }
1423}
1424
Mathias Agopian65ab4712010-07-14 17:59:35 -07001425// ----------------------------------------------------------------------------
1426
Eric Laurent7c7f10b2011-06-17 21:29:58 -07001427AudioFlinger::PlaybackThread::PlaybackThread(const sp<AudioFlinger>& audioFlinger,
1428 AudioStreamOut* output,
Glenn Kasten72ef00d2012-01-17 11:09:42 -08001429 audio_io_handle_t id,
Glenn Kasten23bb8be2012-01-26 10:38:26 -08001430 uint32_t device,
1431 type_t type)
1432 : ThreadBase(audioFlinger, id, device, type),
Glenn Kasten84afa3b2012-01-25 15:28:08 -08001433 mMixBuffer(NULL), mSuspended(0), mBytesWritten(0),
1434 // Assumes constructor is called by AudioFlinger with it's mLock held,
1435 // but it would be safer to explicitly pass initial masterMute as parameter
1436 mMasterMute(audioFlinger->masterMute_l()),
1437 // mStreamTypes[] initialized in constructor body
1438 mOutput(output),
1439 // Assumes constructor is called by AudioFlinger with it's mLock held,
1440 // but it would be safer to explicitly pass initial masterVolume as parameter
John Grossman4ff14ba2012-02-08 16:37:41 -08001441 mMasterVolume(audioFlinger->masterVolumeSW_l()),
Glenn Kastenfec279f2012-03-08 07:47:15 -08001442 mLastWriteTime(0), mNumWrites(0), mNumDelayedWrites(0), mInWrite(false),
Glenn Kastenaa4397f2012-03-12 18:13:59 -07001443 mMixerStatus(MIXER_IDLE),
Glenn Kasten66fcab92012-02-24 14:59:21 -08001444 mPrevMixerStatus(MIXER_IDLE),
1445 standbyDelay(AudioFlinger::mStandbyTimeInNsecs)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001446{
Glenn Kasten480b4682012-02-28 12:30:08 -08001447 snprintf(mName, kNameLength, "AudioOut_%X", id);
Eric Laurentfeb0db62011-07-22 09:04:31 -07001448
Mathias Agopian65ab4712010-07-14 17:59:35 -07001449 readOutputParameters();
1450
Glenn Kasten263709e2012-01-06 08:40:01 -08001451 // mStreamTypes[AUDIO_STREAM_CNT] is initialized by stream_type_t default constructor
Glenn Kastenfff6d712012-01-12 16:38:12 -08001452 // There is no AUDIO_STREAM_MIN, and ++ operator does not compile
1453 for (audio_stream_type_t stream = (audio_stream_type_t) 0; stream < AUDIO_STREAM_CNT;
1454 stream = (audio_stream_type_t) (stream + 1)) {
Glenn Kasten6637baa2012-01-09 09:40:36 -08001455 mStreamTypes[stream].volume = mAudioFlinger->streamVolume_l(stream);
1456 mStreamTypes[stream].mute = mAudioFlinger->streamMute_l(stream);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001457 }
Glenn Kasten6637baa2012-01-09 09:40:36 -08001458 // mStreamTypes[AUDIO_STREAM_CNT] exists but isn't explicitly initialized here,
1459 // because mAudioFlinger doesn't have one to copy from
Mathias Agopian65ab4712010-07-14 17:59:35 -07001460}
1461
1462AudioFlinger::PlaybackThread::~PlaybackThread()
1463{
1464 delete [] mMixBuffer;
1465}
1466
1467status_t AudioFlinger::PlaybackThread::dump(int fd, const Vector<String16>& args)
1468{
1469 dumpInternals(fd, args);
1470 dumpTracks(fd, args);
1471 dumpEffectChains(fd, args);
1472 return NO_ERROR;
1473}
1474
1475status_t AudioFlinger::PlaybackThread::dumpTracks(int fd, const Vector<String16>& args)
1476{
1477 const size_t SIZE = 256;
1478 char buffer[SIZE];
1479 String8 result;
1480
1481 snprintf(buffer, SIZE, "Output thread %p tracks\n", this);
1482 result.append(buffer);
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07001483 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 -07001484 for (size_t i = 0; i < mTracks.size(); ++i) {
1485 sp<Track> track = mTracks[i];
1486 if (track != 0) {
1487 track->dump(buffer, SIZE);
1488 result.append(buffer);
1489 }
1490 }
1491
1492 snprintf(buffer, SIZE, "Output thread %p active tracks\n", this);
1493 result.append(buffer);
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07001494 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 -07001495 for (size_t i = 0; i < mActiveTracks.size(); ++i) {
Glenn Kasten77c11192012-01-25 14:27:41 -08001496 sp<Track> track = mActiveTracks[i].promote();
1497 if (track != 0) {
1498 track->dump(buffer, SIZE);
1499 result.append(buffer);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001500 }
1501 }
1502 write(fd, result.string(), result.size());
1503 return NO_ERROR;
1504}
1505
Mathias Agopian65ab4712010-07-14 17:59:35 -07001506status_t AudioFlinger::PlaybackThread::dumpInternals(int fd, const Vector<String16>& args)
1507{
1508 const size_t SIZE = 256;
1509 char buffer[SIZE];
1510 String8 result;
1511
1512 snprintf(buffer, SIZE, "\nOutput thread %p internals\n", this);
1513 result.append(buffer);
1514 snprintf(buffer, SIZE, "last write occurred (msecs): %llu\n", ns2ms(systemTime() - mLastWriteTime));
1515 result.append(buffer);
1516 snprintf(buffer, SIZE, "total writes: %d\n", mNumWrites);
1517 result.append(buffer);
1518 snprintf(buffer, SIZE, "delayed writes: %d\n", mNumDelayedWrites);
1519 result.append(buffer);
1520 snprintf(buffer, SIZE, "blocked in write: %d\n", mInWrite);
1521 result.append(buffer);
1522 snprintf(buffer, SIZE, "suspend count: %d\n", mSuspended);
1523 result.append(buffer);
1524 snprintf(buffer, SIZE, "mix buffer : %p\n", mMixBuffer);
1525 result.append(buffer);
1526 write(fd, result.string(), result.size());
1527
1528 dumpBase(fd, args);
1529
1530 return NO_ERROR;
1531}
1532
1533// Thread virtuals
1534status_t AudioFlinger::PlaybackThread::readyToRun()
1535{
Eric Laurentb8ba0a92011-08-07 16:32:26 -07001536 status_t status = initCheck();
1537 if (status == NO_ERROR) {
Steve Blockdf64d152012-01-04 20:05:49 +00001538 ALOGI("AudioFlinger's thread %p ready to run", this);
Eric Laurentb8ba0a92011-08-07 16:32:26 -07001539 } else {
Steve Block29357bc2012-01-06 19:20:56 +00001540 ALOGE("No working audio driver found.");
Mathias Agopian65ab4712010-07-14 17:59:35 -07001541 }
Eric Laurentb8ba0a92011-08-07 16:32:26 -07001542 return status;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001543}
1544
1545void AudioFlinger::PlaybackThread::onFirstRef()
1546{
Eric Laurentfeb0db62011-07-22 09:04:31 -07001547 run(mName, ANDROID_PRIORITY_URGENT_AUDIO);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001548}
1549
1550// PlaybackThread::createTrack_l() must be called with AudioFlinger::mLock held
Glenn Kastenea7939a2012-03-14 12:56:26 -07001551sp<AudioFlinger::PlaybackThread::Track> AudioFlinger::PlaybackThread::createTrack_l(
Mathias Agopian65ab4712010-07-14 17:59:35 -07001552 const sp<AudioFlinger::Client>& client,
Glenn Kastenfff6d712012-01-12 16:38:12 -08001553 audio_stream_type_t streamType,
Mathias Agopian65ab4712010-07-14 17:59:35 -07001554 uint32_t sampleRate,
Glenn Kasten58f30212012-01-12 12:27:51 -08001555 audio_format_t format,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07001556 uint32_t channelMask,
Mathias Agopian65ab4712010-07-14 17:59:35 -07001557 int frameCount,
1558 const sp<IMemory>& sharedBuffer,
1559 int sessionId,
Glenn Kasten73d22752012-03-19 13:38:30 -07001560 IAudioFlinger::track_flags_t flags,
Mathias Agopian65ab4712010-07-14 17:59:35 -07001561 status_t *status)
1562{
1563 sp<Track> track;
1564 status_t lStatus;
1565
Glenn Kasten73d22752012-03-19 13:38:30 -07001566 bool isTimed = (flags & IAudioFlinger::TRACK_TIMED) != 0;
1567
1568 // client expresses a preference for FAST, but we get the final say
1569 if ((flags & IAudioFlinger::TRACK_FAST) &&
1570 !(
1571 // not timed
1572 (!isTimed) &&
1573 // either of these use cases:
1574 (
1575 // use case 1: shared buffer with any frame count
1576 (
1577 (sharedBuffer != 0)
1578 ) ||
1579 // use case 2: callback handler and small power-of-2 frame count
1580 (
1581 // unfortunately we can't verify that there's a callback until start()
1582 // FIXME supported frame counts should not be hard-coded
1583 (
1584 (frameCount == 128) ||
1585 (frameCount == 256) ||
1586 (frameCount == 512)
1587 )
1588 )
1589 ) &&
1590 // PCM data
1591 audio_is_linear_pcm(format) &&
1592 // mono or stereo
1593 ( (channelMask == AUDIO_CHANNEL_OUT_MONO) ||
1594 (channelMask == AUDIO_CHANNEL_OUT_STEREO) ) &&
1595 // hardware sample rate
1596 (sampleRate == mSampleRate)
1597 // FIXME test that MixerThread for this fast track has a capable output HAL
1598 // FIXME add a permission test also?
1599 ) ) {
1600 ALOGW("AUDIO_POLICY_OUTPUT_FLAG_FAST denied");
1601 flags &= ~IAudioFlinger::TRACK_FAST;
1602 }
1603
Mathias Agopian65ab4712010-07-14 17:59:35 -07001604 if (mType == DIRECT) {
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07001605 if ((format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM) {
1606 if (sampleRate != mSampleRate || format != mFormat || channelMask != mChannelMask) {
Steve Block29357bc2012-01-06 19:20:56 +00001607 ALOGE("createTrack_l() Bad parameter: sampleRate %d format %d, channelMask 0x%08x \""
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07001608 "for output %p with format %d",
1609 sampleRate, format, channelMask, mOutput, mFormat);
1610 lStatus = BAD_VALUE;
1611 goto Exit;
1612 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07001613 }
1614 } else {
1615 // Resampler implementation limits input sampling rate to 2 x output sampling rate.
1616 if (sampleRate > mSampleRate*2) {
Steve Block29357bc2012-01-06 19:20:56 +00001617 ALOGE("Sample rate out of range: %d mSampleRate %d", sampleRate, mSampleRate);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001618 lStatus = BAD_VALUE;
1619 goto Exit;
1620 }
1621 }
1622
Eric Laurent7c7f10b2011-06-17 21:29:58 -07001623 lStatus = initCheck();
1624 if (lStatus != NO_ERROR) {
Steve Block29357bc2012-01-06 19:20:56 +00001625 ALOGE("Audio driver not initialized.");
Mathias Agopian65ab4712010-07-14 17:59:35 -07001626 goto Exit;
1627 }
1628
1629 { // scope for mLock
1630 Mutex::Autolock _l(mLock);
Eric Laurentde070132010-07-13 04:45:46 -07001631
1632 // all tracks in same audio session must share the same routing strategy otherwise
1633 // conflicts will happen when tracks are moved from one output to another by audio policy
1634 // manager
Glenn Kasten02bbd202012-02-08 12:35:35 -08001635 uint32_t strategy = AudioSystem::getStrategyForStream(streamType);
Eric Laurentde070132010-07-13 04:45:46 -07001636 for (size_t i = 0; i < mTracks.size(); ++i) {
1637 sp<Track> t = mTracks[i];
Glenn Kasten639dbee2012-03-07 12:26:34 -08001638 if (t != 0 && !t->isOutputTrack()) {
Glenn Kasten02bbd202012-02-08 12:35:35 -08001639 uint32_t actual = AudioSystem::getStrategyForStream(t->streamType());
Glenn Kastend8796012011-10-28 10:31:42 -07001640 if (sessionId == t->sessionId() && strategy != actual) {
Steve Block29357bc2012-01-06 19:20:56 +00001641 ALOGE("createTrack_l() mismatched strategy; expected %u but found %u",
Glenn Kastend8796012011-10-28 10:31:42 -07001642 strategy, actual);
Eric Laurentde070132010-07-13 04:45:46 -07001643 lStatus = BAD_VALUE;
1644 goto Exit;
1645 }
1646 }
1647 }
1648
John Grossman4ff14ba2012-02-08 16:37:41 -08001649 if (!isTimed) {
1650 track = new Track(this, client, streamType, sampleRate, format,
Glenn Kasten73d22752012-03-19 13:38:30 -07001651 channelMask, frameCount, sharedBuffer, sessionId, flags);
John Grossman4ff14ba2012-02-08 16:37:41 -08001652 } else {
1653 track = TimedTrack::create(this, client, streamType, sampleRate, format,
1654 channelMask, frameCount, sharedBuffer, sessionId);
1655 }
1656 if (track == NULL || track->getCblk() == NULL || track->name() < 0) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001657 lStatus = NO_MEMORY;
1658 goto Exit;
1659 }
1660 mTracks.add(track);
1661
1662 sp<EffectChain> chain = getEffectChain_l(sessionId);
1663 if (chain != 0) {
Steve Block3856b092011-10-20 11:56:00 +01001664 ALOGV("createTrack_l() setting main buffer %p", chain->inBuffer());
Mathias Agopian65ab4712010-07-14 17:59:35 -07001665 track->setMainBuffer(chain->inBuffer());
Glenn Kasten02bbd202012-02-08 12:35:35 -08001666 chain->setStrategy(AudioSystem::getStrategyForStream(track->streamType()));
Eric Laurentb469b942011-05-09 12:09:06 -07001667 chain->incTrackCnt();
Mathias Agopian65ab4712010-07-14 17:59:35 -07001668 }
1669 }
1670 lStatus = NO_ERROR;
1671
1672Exit:
Glenn Kastene53b9ea2012-03-12 16:29:55 -07001673 if (status) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001674 *status = lStatus;
1675 }
1676 return track;
1677}
1678
1679uint32_t AudioFlinger::PlaybackThread::latency() const
1680{
Eric Laurentb8ba0a92011-08-07 16:32:26 -07001681 Mutex::Autolock _l(mLock);
1682 if (initCheck() == NO_ERROR) {
Dima Zavin799a70e2011-04-18 16:57:27 -07001683 return mOutput->stream->get_latency(mOutput->stream);
Eric Laurentb8ba0a92011-08-07 16:32:26 -07001684 } else {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001685 return 0;
1686 }
1687}
1688
Glenn Kasten6637baa2012-01-09 09:40:36 -08001689void AudioFlinger::PlaybackThread::setMasterVolume(float value)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001690{
Glenn Kasten6637baa2012-01-09 09:40:36 -08001691 Mutex::Autolock _l(mLock);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001692 mMasterVolume = value;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001693}
1694
Glenn Kasten6637baa2012-01-09 09:40:36 -08001695void AudioFlinger::PlaybackThread::setMasterMute(bool muted)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001696{
Glenn Kasten6637baa2012-01-09 09:40:36 -08001697 Mutex::Autolock _l(mLock);
1698 setMasterMute_l(muted);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001699}
1700
Glenn Kasten6637baa2012-01-09 09:40:36 -08001701void AudioFlinger::PlaybackThread::setStreamVolume(audio_stream_type_t stream, float value)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001702{
Glenn Kasten6637baa2012-01-09 09:40:36 -08001703 Mutex::Autolock _l(mLock);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001704 mStreamTypes[stream].volume = value;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001705}
1706
Glenn Kasten6637baa2012-01-09 09:40:36 -08001707void AudioFlinger::PlaybackThread::setStreamMute(audio_stream_type_t stream, bool muted)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001708{
Glenn Kasten6637baa2012-01-09 09:40:36 -08001709 Mutex::Autolock _l(mLock);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001710 mStreamTypes[stream].mute = muted;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001711}
1712
Glenn Kastenfff6d712012-01-12 16:38:12 -08001713float AudioFlinger::PlaybackThread::streamVolume(audio_stream_type_t stream) const
Mathias Agopian65ab4712010-07-14 17:59:35 -07001714{
Glenn Kasten6637baa2012-01-09 09:40:36 -08001715 Mutex::Autolock _l(mLock);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001716 return mStreamTypes[stream].volume;
1717}
1718
Mathias Agopian65ab4712010-07-14 17:59:35 -07001719// addTrack_l() must be called with ThreadBase::mLock held
1720status_t AudioFlinger::PlaybackThread::addTrack_l(const sp<Track>& track)
1721{
1722 status_t status = ALREADY_EXISTS;
1723
1724 // set retry count for buffer fill
1725 track->mRetryCount = kMaxTrackStartupRetries;
1726 if (mActiveTracks.indexOf(track) < 0) {
1727 // the track is newly added, make sure it fills up all its
1728 // buffers before playing. This is to ensure the client will
1729 // effectively get the latency it requested.
1730 track->mFillingUpStatus = Track::FS_FILLING;
1731 track->mResetDone = false;
1732 mActiveTracks.add(track);
1733 if (track->mainBuffer() != mMixBuffer) {
1734 sp<EffectChain> chain = getEffectChain_l(track->sessionId());
1735 if (chain != 0) {
Steve Block3856b092011-10-20 11:56:00 +01001736 ALOGV("addTrack_l() starting track on chain %p for session %d", chain.get(), track->sessionId());
Eric Laurentb469b942011-05-09 12:09:06 -07001737 chain->incActiveTrackCnt();
Mathias Agopian65ab4712010-07-14 17:59:35 -07001738 }
1739 }
1740
1741 status = NO_ERROR;
1742 }
1743
Steve Block3856b092011-10-20 11:56:00 +01001744 ALOGV("mWaitWorkCV.broadcast");
Mathias Agopian65ab4712010-07-14 17:59:35 -07001745 mWaitWorkCV.broadcast();
1746
1747 return status;
1748}
1749
1750// destroyTrack_l() must be called with ThreadBase::mLock held
1751void AudioFlinger::PlaybackThread::destroyTrack_l(const sp<Track>& track)
1752{
1753 track->mState = TrackBase::TERMINATED;
1754 if (mActiveTracks.indexOf(track) < 0) {
Eric Laurentb469b942011-05-09 12:09:06 -07001755 removeTrack_l(track);
1756 }
1757}
1758
1759void AudioFlinger::PlaybackThread::removeTrack_l(const sp<Track>& track)
1760{
1761 mTracks.remove(track);
1762 deleteTrackName_l(track->name());
1763 sp<EffectChain> chain = getEffectChain_l(track->sessionId());
1764 if (chain != 0) {
1765 chain->decTrackCnt();
Mathias Agopian65ab4712010-07-14 17:59:35 -07001766 }
1767}
1768
1769String8 AudioFlinger::PlaybackThread::getParameters(const String8& keys)
1770{
Eric Laurentb8ba0a92011-08-07 16:32:26 -07001771 String8 out_s8 = String8("");
Dima Zavinfce7a472011-04-19 22:30:36 -07001772 char *s;
1773
Eric Laurentb8ba0a92011-08-07 16:32:26 -07001774 Mutex::Autolock _l(mLock);
1775 if (initCheck() != NO_ERROR) {
1776 return out_s8;
1777 }
1778
Dima Zavin799a70e2011-04-18 16:57:27 -07001779 s = mOutput->stream->common.get_parameters(&mOutput->stream->common, keys.string());
Dima Zavinfce7a472011-04-19 22:30:36 -07001780 out_s8 = String8(s);
1781 free(s);
1782 return out_s8;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001783}
1784
Eric Laurentb8ba0a92011-08-07 16:32:26 -07001785// audioConfigChanged_l() must be called with AudioFlinger::mLock held
Mathias Agopian65ab4712010-07-14 17:59:35 -07001786void AudioFlinger::PlaybackThread::audioConfigChanged_l(int event, int param) {
1787 AudioSystem::OutputDescriptor desc;
Glenn Kastena0d68332012-01-27 16:47:15 -08001788 void *param2 = NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001789
Steve Block3856b092011-10-20 11:56:00 +01001790 ALOGV("PlaybackThread::audioConfigChanged_l, thread %p, event %d, param %d", this, event, param);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001791
1792 switch (event) {
1793 case AudioSystem::OUTPUT_OPENED:
1794 case AudioSystem::OUTPUT_CONFIG_CHANGED:
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07001795 desc.channels = mChannelMask;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001796 desc.samplingRate = mSampleRate;
1797 desc.format = mFormat;
1798 desc.frameCount = mFrameCount;
1799 desc.latency = latency();
1800 param2 = &desc;
1801 break;
1802
1803 case AudioSystem::STREAM_CONFIG_CHANGED:
1804 param2 = &param;
1805 case AudioSystem::OUTPUT_CLOSED:
1806 default:
1807 break;
1808 }
1809 mAudioFlinger->audioConfigChanged_l(event, mId, param2);
1810}
1811
1812void AudioFlinger::PlaybackThread::readOutputParameters()
1813{
Dima Zavin799a70e2011-04-18 16:57:27 -07001814 mSampleRate = mOutput->stream->common.get_sample_rate(&mOutput->stream->common);
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07001815 mChannelMask = mOutput->stream->common.get_channels(&mOutput->stream->common);
1816 mChannelCount = (uint16_t)popcount(mChannelMask);
Dima Zavin799a70e2011-04-18 16:57:27 -07001817 mFormat = mOutput->stream->common.get_format(&mOutput->stream->common);
Glenn Kastenb9980652012-01-11 09:48:27 -08001818 mFrameSize = audio_stream_frame_size(&mOutput->stream->common);
Dima Zavin799a70e2011-04-18 16:57:27 -07001819 mFrameCount = mOutput->stream->common.get_buffer_size(&mOutput->stream->common) / mFrameSize;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001820
1821 // FIXME - Current mixer implementation only supports stereo output: Always
1822 // Allocate a stereo buffer even if HW output is mono.
Glenn Kastene9dd0172012-01-27 18:08:45 -08001823 delete[] mMixBuffer;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001824 mMixBuffer = new int16_t[mFrameCount * 2];
1825 memset(mMixBuffer, 0, mFrameCount * 2 * sizeof(int16_t));
1826
Eric Laurentde070132010-07-13 04:45:46 -07001827 // force reconfiguration of effect chains and engines to take new buffer size and audio
1828 // parameters into account
1829 // Note that mLock is not held when readOutputParameters() is called from the constructor
1830 // but in this case nothing is done below as no audio sessions have effect yet so it doesn't
1831 // matter.
1832 // create a copy of mEffectChains as calling moveEffectChain_l() can reorder some effect chains
1833 Vector< sp<EffectChain> > effectChains = mEffectChains;
1834 for (size_t i = 0; i < effectChains.size(); i ++) {
Eric Laurent39e94f82010-07-28 01:32:47 -07001835 mAudioFlinger->moveEffectChain_l(effectChains[i]->sessionId(), this, this, false);
Eric Laurentde070132010-07-13 04:45:46 -07001836 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07001837}
1838
1839status_t AudioFlinger::PlaybackThread::getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames)
1840{
Glenn Kastena0d68332012-01-27 16:47:15 -08001841 if (halFrames == NULL || dspFrames == NULL) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001842 return BAD_VALUE;
1843 }
Eric Laurentb8ba0a92011-08-07 16:32:26 -07001844 Mutex::Autolock _l(mLock);
Eric Laurent7c7f10b2011-06-17 21:29:58 -07001845 if (initCheck() != NO_ERROR) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001846 return INVALID_OPERATION;
1847 }
Dima Zavin799a70e2011-04-18 16:57:27 -07001848 *halFrames = mBytesWritten / audio_stream_frame_size(&mOutput->stream->common);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001849
Dima Zavin799a70e2011-04-18 16:57:27 -07001850 return mOutput->stream->get_render_position(mOutput->stream, dspFrames);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001851}
1852
Eric Laurent39e94f82010-07-28 01:32:47 -07001853uint32_t AudioFlinger::PlaybackThread::hasAudioSession(int sessionId)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001854{
1855 Mutex::Autolock _l(mLock);
Eric Laurent39e94f82010-07-28 01:32:47 -07001856 uint32_t result = 0;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001857 if (getEffectChain_l(sessionId) != 0) {
Eric Laurent39e94f82010-07-28 01:32:47 -07001858 result = EFFECT_SESSION;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001859 }
1860
1861 for (size_t i = 0; i < mTracks.size(); ++i) {
1862 sp<Track> track = mTracks[i];
Eric Laurentde070132010-07-13 04:45:46 -07001863 if (sessionId == track->sessionId() &&
1864 !(track->mCblk->flags & CBLK_INVALID_MSK)) {
Eric Laurent39e94f82010-07-28 01:32:47 -07001865 result |= TRACK_SESSION;
1866 break;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001867 }
1868 }
1869
Eric Laurent39e94f82010-07-28 01:32:47 -07001870 return result;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001871}
1872
Eric Laurentde070132010-07-13 04:45:46 -07001873uint32_t AudioFlinger::PlaybackThread::getStrategyForSession_l(int sessionId)
1874{
Dima Zavinfce7a472011-04-19 22:30:36 -07001875 // session AUDIO_SESSION_OUTPUT_MIX is placed in same strategy as MUSIC stream so that
Eric Laurentde070132010-07-13 04:45:46 -07001876 // it is moved to correct output by audio policy manager when A2DP is connected or disconnected
Dima Zavinfce7a472011-04-19 22:30:36 -07001877 if (sessionId == AUDIO_SESSION_OUTPUT_MIX) {
1878 return AudioSystem::getStrategyForStream(AUDIO_STREAM_MUSIC);
Eric Laurentde070132010-07-13 04:45:46 -07001879 }
1880 for (size_t i = 0; i < mTracks.size(); i++) {
1881 sp<Track> track = mTracks[i];
1882 if (sessionId == track->sessionId() &&
1883 !(track->mCblk->flags & CBLK_INVALID_MSK)) {
Glenn Kasten02bbd202012-02-08 12:35:35 -08001884 return AudioSystem::getStrategyForStream(track->streamType());
Eric Laurentde070132010-07-13 04:45:46 -07001885 }
1886 }
Dima Zavinfce7a472011-04-19 22:30:36 -07001887 return AudioSystem::getStrategyForStream(AUDIO_STREAM_MUSIC);
Eric Laurentde070132010-07-13 04:45:46 -07001888}
1889
Mathias Agopian65ab4712010-07-14 17:59:35 -07001890
Glenn Kastenaed850d2012-01-26 09:46:34 -08001891AudioFlinger::AudioStreamOut* AudioFlinger::PlaybackThread::getOutput() const
Eric Laurentb8ba0a92011-08-07 16:32:26 -07001892{
1893 Mutex::Autolock _l(mLock);
1894 return mOutput;
1895}
1896
1897AudioFlinger::AudioStreamOut* AudioFlinger::PlaybackThread::clearOutput()
1898{
1899 Mutex::Autolock _l(mLock);
1900 AudioStreamOut *output = mOutput;
1901 mOutput = NULL;
1902 return output;
1903}
1904
1905// this method must always be called either with ThreadBase mLock held or inside the thread loop
Glenn Kasten0bf65bd2012-02-28 18:32:53 -08001906audio_stream_t* AudioFlinger::PlaybackThread::stream() const
Eric Laurentb8ba0a92011-08-07 16:32:26 -07001907{
1908 if (mOutput == NULL) {
1909 return NULL;
1910 }
1911 return &mOutput->stream->common;
1912}
1913
Glenn Kasten0bf65bd2012-02-28 18:32:53 -08001914uint32_t AudioFlinger::PlaybackThread::activeSleepTimeUs() const
Eric Laurent162b40b2011-12-05 09:47:19 -08001915{
1916 // A2DP output latency is not due only to buffering capacity. It also reflects encoding,
1917 // decoding and transfer time. So sleeping for half of the latency would likely cause
1918 // underruns
1919 if (audio_is_a2dp_device((audio_devices_t)mDevice)) {
1920 return (uint32_t)((uint32_t)((mFrameCount * 1000) / mSampleRate) * 1000);
1921 } else {
1922 return (uint32_t)(mOutput->stream->get_latency(mOutput->stream) * 1000) / 2;
1923 }
1924}
1925
Eric Laurenta011e352012-03-29 15:51:43 -07001926status_t AudioFlinger::PlaybackThread::setSyncEvent(const sp<SyncEvent>& event)
1927{
1928 if (!isValidSyncEvent(event)) {
1929 return BAD_VALUE;
1930 }
1931
1932 Mutex::Autolock _l(mLock);
1933
1934 for (size_t i = 0; i < mTracks.size(); ++i) {
1935 sp<Track> track = mTracks[i];
1936 if (event->triggerSession() == track->sessionId()) {
1937 track->setSyncEvent(event);
1938 return NO_ERROR;
1939 }
1940 }
1941
1942 return NAME_NOT_FOUND;
1943}
1944
1945bool AudioFlinger::PlaybackThread::isValidSyncEvent(const sp<SyncEvent>& event)
1946{
1947 switch (event->type()) {
1948 case AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE:
1949 return true;
1950 default:
1951 break;
1952 }
1953 return false;
1954}
1955
Mathias Agopian65ab4712010-07-14 17:59:35 -07001956// ----------------------------------------------------------------------------
1957
Glenn Kasten23bb8be2012-01-26 10:38:26 -08001958AudioFlinger::MixerThread::MixerThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output,
Glenn Kasten72ef00d2012-01-17 11:09:42 -08001959 audio_io_handle_t id, uint32_t device, type_t type)
Glenn Kasten000f0e32012-03-01 17:10:56 -08001960 : PlaybackThread(audioFlinger, output, id, device, type)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001961{
Glenn Kasten000f0e32012-03-01 17:10:56 -08001962 mAudioMixer = new AudioMixer(mFrameCount, mSampleRate);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001963 // FIXME - Current mixer implementation only supports stereo output
1964 if (mChannelCount == 1) {
Steve Block29357bc2012-01-06 19:20:56 +00001965 ALOGE("Invalid audio hardware channel count");
Mathias Agopian65ab4712010-07-14 17:59:35 -07001966 }
1967}
1968
1969AudioFlinger::MixerThread::~MixerThread()
1970{
1971 delete mAudioMixer;
1972}
1973
Glenn Kasten83efdd02012-02-24 07:21:32 -08001974class CpuStats {
1975public:
Glenn Kasten190a46f2012-03-06 11:27:10 -08001976 CpuStats();
1977 void sample(const String8 &title);
Glenn Kasten83efdd02012-02-24 07:21:32 -08001978#ifdef DEBUG_CPU_USAGE
1979private:
Glenn Kasten190a46f2012-03-06 11:27:10 -08001980 ThreadCpuUsage mCpuUsage; // instantaneous thread CPU usage in wall clock ns
1981 CentralTendencyStatistics mWcStats; // statistics on thread CPU usage in wall clock ns
1982
1983 CentralTendencyStatistics mHzStats; // statistics on thread CPU usage in cycles
1984
1985 int mCpuNum; // thread's current CPU number
1986 int mCpukHz; // frequency of thread's current CPU in kHz
Glenn Kasten83efdd02012-02-24 07:21:32 -08001987#endif
1988};
1989
Glenn Kasten190a46f2012-03-06 11:27:10 -08001990CpuStats::CpuStats()
Glenn Kasten83efdd02012-02-24 07:21:32 -08001991#ifdef DEBUG_CPU_USAGE
Glenn Kasten190a46f2012-03-06 11:27:10 -08001992 : mCpuNum(-1), mCpukHz(-1)
1993#endif
1994{
1995}
1996
1997void CpuStats::sample(const String8 &title) {
1998#ifdef DEBUG_CPU_USAGE
1999 // get current thread's delta CPU time in wall clock ns
2000 double wcNs;
2001 bool valid = mCpuUsage.sampleAndEnable(wcNs);
2002
2003 // record sample for wall clock statistics
2004 if (valid) {
2005 mWcStats.sample(wcNs);
2006 }
2007
2008 // get the current CPU number
2009 int cpuNum = sched_getcpu();
2010
2011 // get the current CPU frequency in kHz
2012 int cpukHz = mCpuUsage.getCpukHz(cpuNum);
2013
2014 // check if either CPU number or frequency changed
2015 if (cpuNum != mCpuNum || cpukHz != mCpukHz) {
2016 mCpuNum = cpuNum;
2017 mCpukHz = cpukHz;
2018 // ignore sample for purposes of cycles
2019 valid = false;
2020 }
2021
2022 // if no change in CPU number or frequency, then record sample for cycle statistics
2023 if (valid && mCpukHz > 0) {
2024 double cycles = wcNs * cpukHz * 0.000001;
2025 mHzStats.sample(cycles);
2026 }
2027
2028 unsigned n = mWcStats.n();
2029 // mCpuUsage.elapsed() is expensive, so don't call it every loop
Glenn Kasten83efdd02012-02-24 07:21:32 -08002030 if ((n & 127) == 1) {
Glenn Kasten190a46f2012-03-06 11:27:10 -08002031 long long elapsed = mCpuUsage.elapsed();
Glenn Kasten83efdd02012-02-24 07:21:32 -08002032 if (elapsed >= DEBUG_CPU_USAGE * 1000000000LL) {
2033 double perLoop = elapsed / (double) n;
2034 double perLoop100 = perLoop * 0.01;
Glenn Kasten190a46f2012-03-06 11:27:10 -08002035 double perLoop1k = perLoop * 0.001;
2036 double mean = mWcStats.mean();
2037 double stddev = mWcStats.stddev();
2038 double minimum = mWcStats.minimum();
2039 double maximum = mWcStats.maximum();
2040 double meanCycles = mHzStats.mean();
2041 double stddevCycles = mHzStats.stddev();
2042 double minCycles = mHzStats.minimum();
2043 double maxCycles = mHzStats.maximum();
2044 mCpuUsage.resetElapsed();
2045 mWcStats.reset();
2046 mHzStats.reset();
2047 ALOGD("CPU usage for %s over past %.1f secs\n"
2048 " (%u mixer loops at %.1f mean ms per loop):\n"
2049 " us per mix loop: mean=%.0f stddev=%.0f min=%.0f max=%.0f\n"
2050 " %% of wall: mean=%.1f stddev=%.1f min=%.1f max=%.1f\n"
2051 " MHz: mean=%.1f, stddev=%.1f, min=%.1f max=%.1f",
2052 title.string(),
Glenn Kasten83efdd02012-02-24 07:21:32 -08002053 elapsed * .000000001, n, perLoop * .000001,
2054 mean * .001,
2055 stddev * .001,
2056 minimum * .001,
2057 maximum * .001,
2058 mean / perLoop100,
2059 stddev / perLoop100,
2060 minimum / perLoop100,
Glenn Kasten190a46f2012-03-06 11:27:10 -08002061 maximum / perLoop100,
2062 meanCycles / perLoop1k,
2063 stddevCycles / perLoop1k,
2064 minCycles / perLoop1k,
2065 maxCycles / perLoop1k);
2066
Glenn Kasten83efdd02012-02-24 07:21:32 -08002067 }
2068 }
2069#endif
2070};
2071
Glenn Kasten37d825e2012-02-24 07:21:48 -08002072void AudioFlinger::PlaybackThread::checkSilentMode_l()
2073{
2074 if (!mMasterMute) {
2075 char value[PROPERTY_VALUE_MAX];
2076 if (property_get("ro.audio.silent", value, "0") > 0) {
2077 char *endptr;
2078 unsigned long ul = strtoul(value, &endptr, 0);
2079 if (*endptr == '\0' && ul != 0) {
2080 ALOGD("Silence is golden");
2081 // The setprop command will not allow a property to be changed after
2082 // the first time it is set, so we don't have to worry about un-muting.
2083 setMasterMute_l(true);
2084 }
2085 }
2086 }
2087}
2088
Glenn Kasten000f0e32012-03-01 17:10:56 -08002089bool AudioFlinger::PlaybackThread::threadLoop()
Mathias Agopian65ab4712010-07-14 17:59:35 -07002090{
2091 Vector< sp<Track> > tracksToRemove;
Glenn Kasten688a6402012-02-29 07:57:06 -08002092
Glenn Kasten000f0e32012-03-01 17:10:56 -08002093 standbyTime = systemTime();
Glenn Kasten000f0e32012-03-01 17:10:56 -08002094
2095 // MIXER
Mathias Agopian65ab4712010-07-14 17:59:35 -07002096 nsecs_t lastWarning = 0;
Glenn Kasten000f0e32012-03-01 17:10:56 -08002097if (mType == MIXER) {
2098 longStandbyExit = false;
2099}
Glenn Kasten688a6402012-02-29 07:57:06 -08002100
Glenn Kasten000f0e32012-03-01 17:10:56 -08002101 // DUPLICATING
2102 // FIXME could this be made local to while loop?
2103 writeFrames = 0;
Glenn Kasten688a6402012-02-29 07:57:06 -08002104
Glenn Kasten66fcab92012-02-24 14:59:21 -08002105 cacheParameters_l();
Glenn Kasten000f0e32012-03-01 17:10:56 -08002106 sleepTime = idleSleepTime;
2107
2108if (mType == MIXER) {
2109 sleepTimeShift = 0;
2110}
2111
Glenn Kasten83efdd02012-02-24 07:21:32 -08002112 CpuStats cpuStats;
Glenn Kasten190a46f2012-03-06 11:27:10 -08002113 const String8 myName(String8::format("thread %p type %d TID %d", this, mType, gettid()));
Mathias Agopian65ab4712010-07-14 17:59:35 -07002114
Eric Laurentfeb0db62011-07-22 09:04:31 -07002115 acquireWakeLock();
2116
Mathias Agopian65ab4712010-07-14 17:59:35 -07002117 while (!exitPending())
2118 {
Glenn Kasten190a46f2012-03-06 11:27:10 -08002119 cpuStats.sample(myName);
Glenn Kasten688a6402012-02-29 07:57:06 -08002120
Glenn Kasten73ca0f52012-02-29 07:56:15 -08002121 Vector< sp<EffectChain> > effectChains;
2122
Mathias Agopian65ab4712010-07-14 17:59:35 -07002123 processConfigEvents();
2124
Mathias Agopian65ab4712010-07-14 17:59:35 -07002125 { // scope for mLock
2126
2127 Mutex::Autolock _l(mLock);
2128
2129 if (checkForNewParameters_l()) {
Glenn Kasten66fcab92012-02-24 14:59:21 -08002130 cacheParameters_l();
Mathias Agopian65ab4712010-07-14 17:59:35 -07002131 }
2132
Glenn Kastenfa26a852012-03-06 11:28:04 -08002133 saveOutputTracks();
Glenn Kasten000f0e32012-03-01 17:10:56 -08002134
Mathias Agopian65ab4712010-07-14 17:59:35 -07002135 // put audio hardware into standby after short delay
Glenn Kasten3e074702012-02-28 18:40:35 -08002136 if (CC_UNLIKELY((!mActiveTracks.size() && systemTime() > standbyTime) ||
Glenn Kastenc455fe92012-02-29 07:07:30 -08002137 mSuspended > 0)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07002138 if (!mStandby) {
Glenn Kasten000f0e32012-03-01 17:10:56 -08002139
2140 threadLoop_standby();
2141
Mathias Agopian65ab4712010-07-14 17:59:35 -07002142 mStandby = true;
2143 mBytesWritten = 0;
2144 }
2145
Glenn Kasten3e074702012-02-28 18:40:35 -08002146 if (!mActiveTracks.size() && mConfigEvents.isEmpty()) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07002147 // we're about to wait, flush the binder command buffer
2148 IPCThreadState::self()->flushCommands();
2149
Glenn Kastenfa26a852012-03-06 11:28:04 -08002150 clearOutputTracks();
Glenn Kasten000f0e32012-03-01 17:10:56 -08002151
Mathias Agopian65ab4712010-07-14 17:59:35 -07002152 if (exitPending()) break;
2153
Eric Laurentfeb0db62011-07-22 09:04:31 -07002154 releaseWakeLock_l();
Mathias Agopian65ab4712010-07-14 17:59:35 -07002155 // wait until we have something to do...
Glenn Kasten190a46f2012-03-06 11:27:10 -08002156 ALOGV("%s going to sleep", myName.string());
Mathias Agopian65ab4712010-07-14 17:59:35 -07002157 mWaitWorkCV.wait(mLock);
Glenn Kasten190a46f2012-03-06 11:27:10 -08002158 ALOGV("%s waking up", myName.string());
Eric Laurentfeb0db62011-07-22 09:04:31 -07002159 acquireWakeLock_l();
Mathias Agopian65ab4712010-07-14 17:59:35 -07002160
Eric Laurent27741442012-01-17 19:20:12 -08002161 mPrevMixerStatus = MIXER_IDLE;
Glenn Kasten000f0e32012-03-01 17:10:56 -08002162
Glenn Kasten37d825e2012-02-24 07:21:48 -08002163 checkSilentMode_l();
Mathias Agopian65ab4712010-07-14 17:59:35 -07002164
Glenn Kasten000f0e32012-03-01 17:10:56 -08002165 standbyTime = systemTime() + standbyDelay;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002166 sleepTime = idleSleepTime;
Glenn Kasten66fcab92012-02-24 14:59:21 -08002167 if (mType == MIXER) {
2168 sleepTimeShift = 0;
2169 }
Glenn Kasten000f0e32012-03-01 17:10:56 -08002170
Mathias Agopian65ab4712010-07-14 17:59:35 -07002171 continue;
2172 }
2173 }
2174
Glenn Kastenfec279f2012-03-08 07:47:15 -08002175 mixer_state newMixerStatus = prepareTracks_l(&tracksToRemove);
2176 // Shift in the new status; this could be a queue if it's
2177 // useful to filter the mixer status over several cycles.
2178 mPrevMixerStatus = mMixerStatus;
2179 mMixerStatus = newMixerStatus;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002180
2181 // prevent any changes in effect chain list and in each effect chain
2182 // during mixing and effect process as the audio buffers could be deleted
2183 // or modified if an effect is created or deleted
Eric Laurentde070132010-07-13 04:45:46 -07002184 lockEffectChains_l(effectChains);
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -08002185 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07002186
Glenn Kastenfec279f2012-03-08 07:47:15 -08002187 if (CC_LIKELY(mMixerStatus == MIXER_TRACKS_READY)) {
Glenn Kasten000f0e32012-03-01 17:10:56 -08002188 threadLoop_mix();
2189 } else {
2190 threadLoop_sleepTime();
2191 }
2192
2193 if (mSuspended > 0) {
2194 sleepTime = suspendSleepTimeUs();
2195 }
2196
2197 // only process effects if we're going to write
2198 if (sleepTime == 0) {
Glenn Kasten000f0e32012-03-01 17:10:56 -08002199 for (size_t i = 0; i < effectChains.size(); i ++) {
2200 effectChains[i]->process_l();
2201 }
2202 }
2203
2204 // enable changes in effect chain
2205 unlockEffectChains(effectChains);
2206
2207 // sleepTime == 0 means we must write to audio hardware
2208 if (sleepTime == 0) {
2209
2210 threadLoop_write();
2211
2212if (mType == MIXER) {
2213 // write blocked detection
2214 nsecs_t now = systemTime();
2215 nsecs_t delta = now - mLastWriteTime;
2216 if (!mStandby && delta > maxPeriod) {
2217 mNumDelayedWrites++;
2218 if ((now - lastWarning) > kWarningThrottleNs) {
2219 ALOGW("write blocked for %llu msecs, %d delayed writes, thread %p",
2220 ns2ms(delta), mNumDelayedWrites, this);
2221 lastWarning = now;
2222 }
2223 // FIXME this is broken: longStandbyExit should be handled out of the if() and with
2224 // a different threshold. Or completely removed for what it is worth anyway...
2225 if (mStandby) {
2226 longStandbyExit = true;
2227 }
2228 }
2229}
2230
2231 mStandby = false;
2232 } else {
2233 usleep(sleepTime);
2234 }
2235
2236 // finally let go of removed track(s), without the lock held
2237 // since we can't guarantee the destructors won't acquire that
2238 // same lock.
Glenn Kasten1465f0c2012-03-06 11:23:32 -08002239 tracksToRemove.clear();
Glenn Kasten000f0e32012-03-01 17:10:56 -08002240
Glenn Kastenfa26a852012-03-06 11:28:04 -08002241 // FIXME I don't understand the need for this here;
2242 // it was in the original code but maybe the
2243 // assignment in saveOutputTracks() makes this unnecessary?
2244 clearOutputTracks();
Glenn Kasten000f0e32012-03-01 17:10:56 -08002245
2246 // Effect chains will be actually deleted here if they were removed from
2247 // mEffectChains list during mixing or effects processing
2248 effectChains.clear();
2249
2250 // FIXME Note that the above .clear() is no longer necessary since effectChains
2251 // is now local to this block, but will keep it for now (at least until merge done).
2252 }
2253
2254if (mType == MIXER || mType == DIRECT) {
2255 // put output stream into standby mode
2256 if (!mStandby) {
2257 mOutput->stream->common.standby(&mOutput->stream->common);
2258 }
2259}
2260if (mType == DUPLICATING) {
2261 // for DuplicatingThread, standby mode is handled by the outputTracks
2262}
2263
2264 releaseWakeLock();
2265
2266 ALOGV("Thread %p type %d exiting", this, mType);
2267 return false;
2268}
2269
2270// shared by MIXER and DIRECT, overridden by DUPLICATING
2271void AudioFlinger::PlaybackThread::threadLoop_write()
2272{
Glenn Kasten952eeb22012-03-06 11:30:57 -08002273 // FIXME rewrite to reduce number of system calls
2274 mLastWriteTime = systemTime();
2275 mInWrite = true;
2276 mBytesWritten += mixBufferSize;
2277 int bytesWritten = (int)mOutput->stream->write(mOutput->stream, mMixBuffer, mixBufferSize);
2278 if (bytesWritten < 0) mBytesWritten -= mixBufferSize;
2279 mNumWrites++;
2280 mInWrite = false;
Glenn Kasten000f0e32012-03-01 17:10:56 -08002281}
2282
2283// shared by MIXER and DIRECT, overridden by DUPLICATING
2284void AudioFlinger::PlaybackThread::threadLoop_standby()
2285{
Glenn Kasten952eeb22012-03-06 11:30:57 -08002286 ALOGV("Audio hardware entering standby, mixer %p, suspend count %u", this, mSuspended);
2287 mOutput->stream->common.standby(&mOutput->stream->common);
Glenn Kasten000f0e32012-03-01 17:10:56 -08002288}
2289
2290void AudioFlinger::MixerThread::threadLoop_mix()
2291{
Glenn Kasten952eeb22012-03-06 11:30:57 -08002292 // obtain the presentation timestamp of the next output buffer
2293 int64_t pts;
2294 status_t status = INVALID_OPERATION;
John Grossman4ff14ba2012-02-08 16:37:41 -08002295
Glenn Kasten952eeb22012-03-06 11:30:57 -08002296 if (NULL != mOutput->stream->get_next_write_timestamp) {
2297 status = mOutput->stream->get_next_write_timestamp(
2298 mOutput->stream, &pts);
2299 }
John Grossman4ff14ba2012-02-08 16:37:41 -08002300
Glenn Kasten952eeb22012-03-06 11:30:57 -08002301 if (status != NO_ERROR) {
2302 pts = AudioBufferProvider::kInvalidPTS;
2303 }
John Grossman4ff14ba2012-02-08 16:37:41 -08002304
Glenn Kasten952eeb22012-03-06 11:30:57 -08002305 // mix buffers...
2306 mAudioMixer->process(pts);
2307 // increase sleep time progressively when application underrun condition clears.
2308 // Only increase sleep time if the mixer is ready for two consecutive times to avoid
2309 // that a steady state of alternating ready/not ready conditions keeps the sleep time
2310 // such that we would underrun the audio HAL.
2311 if ((sleepTime == 0) && (sleepTimeShift > 0)) {
2312 sleepTimeShift--;
2313 }
2314 sleepTime = 0;
Glenn Kasten66fcab92012-02-24 14:59:21 -08002315 standbyTime = systemTime() + standbyDelay;
Glenn Kasten952eeb22012-03-06 11:30:57 -08002316 //TODO: delay standby when effects have a tail
Glenn Kasten000f0e32012-03-01 17:10:56 -08002317}
2318
2319void AudioFlinger::MixerThread::threadLoop_sleepTime()
2320{
Glenn Kasten952eeb22012-03-06 11:30:57 -08002321 // If no tracks are ready, sleep once for the duration of an output
2322 // buffer size, then write 0s to the output
2323 if (sleepTime == 0) {
Glenn Kastenfec279f2012-03-08 07:47:15 -08002324 if (mMixerStatus == MIXER_TRACKS_ENABLED) {
Glenn Kasten952eeb22012-03-06 11:30:57 -08002325 sleepTime = activeSleepTime >> sleepTimeShift;
2326 if (sleepTime < kMinThreadSleepTimeUs) {
2327 sleepTime = kMinThreadSleepTimeUs;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002328 }
Glenn Kasten952eeb22012-03-06 11:30:57 -08002329 // reduce sleep time in case of consecutive application underruns to avoid
2330 // starving the audio HAL. As activeSleepTimeUs() is larger than a buffer
2331 // duration we would end up writing less data than needed by the audio HAL if
2332 // the condition persists.
2333 if (sleepTimeShift < kMaxThreadSleepTimeShift) {
2334 sleepTimeShift++;
2335 }
2336 } else {
2337 sleepTime = idleSleepTime;
2338 }
2339 } else if (mBytesWritten != 0 ||
Glenn Kastenfec279f2012-03-08 07:47:15 -08002340 (mMixerStatus == MIXER_TRACKS_ENABLED && longStandbyExit)) {
Glenn Kasten952eeb22012-03-06 11:30:57 -08002341 memset (mMixBuffer, 0, mixBufferSize);
2342 sleepTime = 0;
Glenn Kastenfec279f2012-03-08 07:47:15 -08002343 ALOGV_IF((mBytesWritten == 0 && (mMixerStatus == MIXER_TRACKS_ENABLED && longStandbyExit)), "anticipated start");
Glenn Kasten952eeb22012-03-06 11:30:57 -08002344 }
2345 // TODO add standby time extension fct of effect tail
Mathias Agopian65ab4712010-07-14 17:59:35 -07002346}
2347
2348// prepareTracks_l() must be called with ThreadBase::mLock held
Glenn Kasten29c23c32012-01-26 13:37:52 -08002349AudioFlinger::PlaybackThread::mixer_state AudioFlinger::MixerThread::prepareTracks_l(
Glenn Kasten3e074702012-02-28 18:40:35 -08002350 Vector< sp<Track> > *tracksToRemove)
Mathias Agopian65ab4712010-07-14 17:59:35 -07002351{
2352
Glenn Kasten29c23c32012-01-26 13:37:52 -08002353 mixer_state mixerStatus = MIXER_IDLE;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002354 // find out which tracks need to be processed
Glenn Kasten3e074702012-02-28 18:40:35 -08002355 size_t count = mActiveTracks.size();
Mathias Agopian65ab4712010-07-14 17:59:35 -07002356 size_t mixedTracks = 0;
2357 size_t tracksWithEffect = 0;
2358
2359 float masterVolume = mMasterVolume;
Glenn Kastenea7939a2012-03-14 12:56:26 -07002360 bool masterMute = mMasterMute;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002361
Eric Laurent571d49c2010-08-11 05:20:11 -07002362 if (masterMute) {
2363 masterVolume = 0;
2364 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07002365 // Delegate master volume control to effect in output mix effect chain if needed
Dima Zavinfce7a472011-04-19 22:30:36 -07002366 sp<EffectChain> chain = getEffectChain_l(AUDIO_SESSION_OUTPUT_MIX);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002367 if (chain != 0) {
Eric Laurent571d49c2010-08-11 05:20:11 -07002368 uint32_t v = (uint32_t)(masterVolume * (1 << 24));
Eric Laurentcab11242010-07-15 12:50:15 -07002369 chain->setVolume_l(&v, &v);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002370 masterVolume = (float)((v + (1 << 23)) >> 24);
2371 chain.clear();
2372 }
2373
2374 for (size_t i=0 ; i<count ; i++) {
Glenn Kasten3e074702012-02-28 18:40:35 -08002375 sp<Track> t = mActiveTracks[i].promote();
Mathias Agopian65ab4712010-07-14 17:59:35 -07002376 if (t == 0) continue;
2377
Glenn Kasten9c56d4a2011-12-19 15:06:39 -08002378 // this const just means the local variable doesn't change
Mathias Agopian65ab4712010-07-14 17:59:35 -07002379 Track* const track = t.get();
2380 audio_track_cblk_t* cblk = track->cblk();
2381
2382 // The first time a track is added we wait
2383 // for all its buffers to be filled before processing it
Glenn Kasten9c56d4a2011-12-19 15:06:39 -08002384 int name = track->name();
Eric Laurenta47b69c2011-11-08 18:10:16 -08002385 // make sure that we have enough frames to mix one full buffer.
2386 // enforce this condition only once to enable draining the buffer in case the client
2387 // app does not call stop() and relies on underrun to stop:
Eric Laurent27741442012-01-17 19:20:12 -08002388 // hence the test on (mPrevMixerStatus == MIXER_TRACKS_READY) meaning the track was mixed
Eric Laurenta47b69c2011-11-08 18:10:16 -08002389 // during last round
Eric Laurent3dbe3202011-11-03 12:16:05 -07002390 uint32_t minFrames = 1;
Eric Laurenta47b69c2011-11-08 18:10:16 -08002391 if (!track->isStopped() && !track->isPausing() &&
Eric Laurent27741442012-01-17 19:20:12 -08002392 (mPrevMixerStatus == MIXER_TRACKS_READY)) {
Eric Laurent3dbe3202011-11-03 12:16:05 -07002393 if (t->sampleRate() == (int)mSampleRate) {
2394 minFrames = mFrameCount;
2395 } else {
Eric Laurent071ccd52011-12-22 16:08:41 -08002396 // +1 for rounding and +1 for additional sample needed for interpolation
2397 minFrames = (mFrameCount * t->sampleRate()) / mSampleRate + 1 + 1;
2398 // add frames already consumed but not yet released by the resampler
Glenn Kastenea7939a2012-03-14 12:56:26 -07002399 // because cblk->framesReady() will include these frames
Eric Laurent071ccd52011-12-22 16:08:41 -08002400 minFrames += mAudioMixer->getUnreleasedFrames(track->name());
2401 // the minimum track buffer size is normally twice the number of frames necessary
2402 // to fill one buffer and the resampler should not leave more than one buffer worth
2403 // of unreleased frames after each pass, but just in case...
Steve Blockc1dc1cb2012-01-09 18:35:44 +00002404 ALOG_ASSERT(minFrames <= cblk->frameCount);
Eric Laurent3dbe3202011-11-03 12:16:05 -07002405 }
2406 }
John Grossman4ff14ba2012-02-08 16:37:41 -08002407 if ((track->framesReady() >= minFrames) && track->isReady() &&
Mathias Agopian65ab4712010-07-14 17:59:35 -07002408 !track->isPaused() && !track->isTerminated())
2409 {
Glenn Kasten9c56d4a2011-12-19 15:06:39 -08002410 //ALOGV("track %d u=%08x, s=%08x [OK] on thread %p", name, cblk->user, cblk->server, this);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002411
2412 mixedTracks++;
2413
2414 // track->mainBuffer() != mMixBuffer means there is an effect chain
2415 // connected to the track
2416 chain.clear();
2417 if (track->mainBuffer() != mMixBuffer) {
2418 chain = getEffectChain_l(track->sessionId());
2419 // Delegate volume control to effect in track effect chain if needed
2420 if (chain != 0) {
2421 tracksWithEffect++;
2422 } else {
Steve Block5ff1dd52012-01-05 23:22:43 +00002423 ALOGW("prepareTracks_l(): track %d attached to effect but no chain found on session %d",
Glenn Kasten9c56d4a2011-12-19 15:06:39 -08002424 name, track->sessionId());
Mathias Agopian65ab4712010-07-14 17:59:35 -07002425 }
2426 }
2427
2428
2429 int param = AudioMixer::VOLUME;
2430 if (track->mFillingUpStatus == Track::FS_FILLED) {
2431 // no ramp for the first volume setting
2432 track->mFillingUpStatus = Track::FS_ACTIVE;
2433 if (track->mState == TrackBase::RESUMING) {
2434 track->mState = TrackBase::ACTIVE;
2435 param = AudioMixer::RAMP_VOLUME;
2436 }
Glenn Kasten9c56d4a2011-12-19 15:06:39 -08002437 mAudioMixer->setParameter(name, AudioMixer::RESAMPLE, AudioMixer::RESET, NULL);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002438 } else if (cblk->server != 0) {
2439 // If the track is stopped before the first frame was mixed,
2440 // do not apply ramp
2441 param = AudioMixer::RAMP_VOLUME;
2442 }
2443
2444 // compute volume for this track
Eric Laurente0aed6d2010-09-10 17:44:44 -07002445 uint32_t vl, vr, va;
Eric Laurent8569f0d2010-07-29 23:43:43 -07002446 if (track->isMuted() || track->isPausing() ||
Glenn Kasten02bbd202012-02-08 12:35:35 -08002447 mStreamTypes[track->streamType()].mute) {
Eric Laurente0aed6d2010-09-10 17:44:44 -07002448 vl = vr = va = 0;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002449 if (track->isPausing()) {
2450 track->setPaused();
2451 }
2452 } else {
Eric Laurente0aed6d2010-09-10 17:44:44 -07002453
Mathias Agopian65ab4712010-07-14 17:59:35 -07002454 // read original volumes with volume control
Glenn Kasten02bbd202012-02-08 12:35:35 -08002455 float typeVolume = mStreamTypes[track->streamType()].volume;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002456 float v = masterVolume * typeVolume;
Glenn Kasten83d86532012-01-17 14:39:34 -08002457 uint32_t vlr = cblk->getVolumeLR();
Glenn Kastenb1cf75c2012-01-17 12:20:54 -08002458 vl = vlr & 0xFFFF;
2459 vr = vlr >> 16;
2460 // track volumes come from shared memory, so can't be trusted and must be clamped
2461 if (vl > MAX_GAIN_INT) {
2462 ALOGV("Track left volume out of range: %04X", vl);
2463 vl = MAX_GAIN_INT;
2464 }
2465 if (vr > MAX_GAIN_INT) {
2466 ALOGV("Track right volume out of range: %04X", vr);
2467 vr = MAX_GAIN_INT;
2468 }
2469 // now apply the master volume and stream type volume
2470 vl = (uint32_t)(v * vl) << 12;
2471 vr = (uint32_t)(v * vr) << 12;
2472 // assuming master volume and stream type volume each go up to 1.0,
2473 // vl and vr are now in 8.24 format
Mathias Agopian65ab4712010-07-14 17:59:35 -07002474
Glenn Kasten05632a52012-01-03 14:22:33 -08002475 uint16_t sendLevel = cblk->getSendLevel_U4_12();
2476 // send level comes from shared memory and so may be corrupt
Glenn Kasten3b81aca2012-01-27 15:26:23 -08002477 if (sendLevel > MAX_GAIN_INT) {
Glenn Kasten05632a52012-01-03 14:22:33 -08002478 ALOGV("Track send level out of range: %04X", sendLevel);
Glenn Kastenb1cf75c2012-01-17 12:20:54 -08002479 sendLevel = MAX_GAIN_INT;
Glenn Kasten05632a52012-01-03 14:22:33 -08002480 }
2481 va = (uint32_t)(v * sendLevel);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002482 }
Eric Laurente0aed6d2010-09-10 17:44:44 -07002483 // Delegate volume control to effect in track effect chain if needed
2484 if (chain != 0 && chain->setVolume_l(&vl, &vr)) {
2485 // Do not ramp volume if volume is controlled by effect
2486 param = AudioMixer::VOLUME;
2487 track->mHasVolumeController = true;
2488 } else {
2489 // force no volume ramp when volume controller was just disabled or removed
2490 // from effect chain to avoid volume spike
2491 if (track->mHasVolumeController) {
2492 param = AudioMixer::VOLUME;
2493 }
2494 track->mHasVolumeController = false;
2495 }
2496
2497 // Convert volumes from 8.24 to 4.12 format
Glenn Kastenb1cf75c2012-01-17 12:20:54 -08002498 // This additional clamping is needed in case chain->setVolume_l() overshot
Glenn Kasten3b81aca2012-01-27 15:26:23 -08002499 vl = (vl + (1 << 11)) >> 12;
2500 if (vl > MAX_GAIN_INT) vl = MAX_GAIN_INT;
2501 vr = (vr + (1 << 11)) >> 12;
2502 if (vr > MAX_GAIN_INT) vr = MAX_GAIN_INT;
Eric Laurente0aed6d2010-09-10 17:44:44 -07002503
Glenn Kasten3b81aca2012-01-27 15:26:23 -08002504 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 -07002505
Mathias Agopian65ab4712010-07-14 17:59:35 -07002506 // XXX: these things DON'T need to be done each time
Glenn Kasten9c56d4a2011-12-19 15:06:39 -08002507 mAudioMixer->setBufferProvider(name, track);
2508 mAudioMixer->enable(name);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002509
Glenn Kasten3b81aca2012-01-27 15:26:23 -08002510 mAudioMixer->setParameter(name, param, AudioMixer::VOLUME0, (void *)vl);
2511 mAudioMixer->setParameter(name, param, AudioMixer::VOLUME1, (void *)vr);
2512 mAudioMixer->setParameter(name, param, AudioMixer::AUXLEVEL, (void *)va);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002513 mAudioMixer->setParameter(
Glenn Kasten9c56d4a2011-12-19 15:06:39 -08002514 name,
Mathias Agopian65ab4712010-07-14 17:59:35 -07002515 AudioMixer::TRACK,
2516 AudioMixer::FORMAT, (void *)track->format());
2517 mAudioMixer->setParameter(
Glenn Kasten9c56d4a2011-12-19 15:06:39 -08002518 name,
Mathias Agopian65ab4712010-07-14 17:59:35 -07002519 AudioMixer::TRACK,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07002520 AudioMixer::CHANNEL_MASK, (void *)track->channelMask());
Mathias Agopian65ab4712010-07-14 17:59:35 -07002521 mAudioMixer->setParameter(
Glenn Kasten9c56d4a2011-12-19 15:06:39 -08002522 name,
Mathias Agopian65ab4712010-07-14 17:59:35 -07002523 AudioMixer::RESAMPLE,
2524 AudioMixer::SAMPLE_RATE,
2525 (void *)(cblk->sampleRate));
2526 mAudioMixer->setParameter(
Glenn Kasten9c56d4a2011-12-19 15:06:39 -08002527 name,
Mathias Agopian65ab4712010-07-14 17:59:35 -07002528 AudioMixer::TRACK,
2529 AudioMixer::MAIN_BUFFER, (void *)track->mainBuffer());
2530 mAudioMixer->setParameter(
Glenn Kasten9c56d4a2011-12-19 15:06:39 -08002531 name,
Mathias Agopian65ab4712010-07-14 17:59:35 -07002532 AudioMixer::TRACK,
2533 AudioMixer::AUX_BUFFER, (void *)track->auxBuffer());
2534
2535 // reset retry count
2536 track->mRetryCount = kMaxTrackRetries;
Glenn Kastenea7939a2012-03-14 12:56:26 -07002537
Eric Laurent27741442012-01-17 19:20:12 -08002538 // If one track is ready, set the mixer ready if:
2539 // - the mixer was not ready during previous round OR
2540 // - no other track is not ready
2541 if (mPrevMixerStatus != MIXER_TRACKS_READY ||
2542 mixerStatus != MIXER_TRACKS_ENABLED) {
2543 mixerStatus = MIXER_TRACKS_READY;
2544 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07002545 } else {
Glenn Kasten9c56d4a2011-12-19 15:06:39 -08002546 //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 -07002547 if (track->isStopped()) {
2548 track->reset();
2549 }
2550 if (track->isTerminated() || track->isStopped() || track->isPaused()) {
2551 // We have consumed all the buffers of this track.
2552 // Remove it from the list of active tracks.
Eric Laurenta011e352012-03-29 15:51:43 -07002553 // TODO: use actual buffer filling status instead of latency when available from
2554 // audio HAL
2555 size_t audioHALFrames =
2556 (mOutput->stream->get_latency(mOutput->stream)*mSampleRate) / 1000;
2557 size_t framesWritten =
2558 mBytesWritten / audio_stream_frame_size(&mOutput->stream->common);
2559 if (track->presentationComplete(framesWritten, audioHALFrames)) {
2560 tracksToRemove->add(track);
2561 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07002562 } else {
2563 // No buffers for this track. Give it a few chances to
2564 // fill a buffer, then remove it from active list.
2565 if (--(track->mRetryCount) <= 0) {
Glenn Kasten9c56d4a2011-12-19 15:06:39 -08002566 ALOGV("BUFFER TIMEOUT: remove(%d) from active list on thread %p", name, this);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002567 tracksToRemove->add(track);
Eric Laurent44d98482010-09-30 16:12:31 -07002568 // indicate to client process that the track was disabled because of underrun
Eric Laurent38ccae22011-03-28 18:37:07 -07002569 android_atomic_or(CBLK_DISABLED_ON, &cblk->flags);
Eric Laurent27741442012-01-17 19:20:12 -08002570 // If one track is not ready, mark the mixer also not ready if:
2571 // - the mixer was ready during previous round OR
2572 // - no other track is ready
2573 } else if (mPrevMixerStatus == MIXER_TRACKS_READY ||
2574 mixerStatus != MIXER_TRACKS_READY) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07002575 mixerStatus = MIXER_TRACKS_ENABLED;
2576 }
2577 }
Glenn Kasten9c56d4a2011-12-19 15:06:39 -08002578 mAudioMixer->disable(name);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002579 }
2580 }
2581
2582 // remove all the tracks that need to be...
2583 count = tracksToRemove->size();
Glenn Kastenf6b16782011-12-15 09:51:17 -08002584 if (CC_UNLIKELY(count)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07002585 for (size_t i=0 ; i<count ; i++) {
2586 const sp<Track>& track = tracksToRemove->itemAt(i);
2587 mActiveTracks.remove(track);
2588 if (track->mainBuffer() != mMixBuffer) {
2589 chain = getEffectChain_l(track->sessionId());
2590 if (chain != 0) {
Steve Block3856b092011-10-20 11:56:00 +01002591 ALOGV("stopping track on chain %p for session Id: %d", chain.get(), track->sessionId());
Eric Laurentb469b942011-05-09 12:09:06 -07002592 chain->decActiveTrackCnt();
Mathias Agopian65ab4712010-07-14 17:59:35 -07002593 }
2594 }
2595 if (track->isTerminated()) {
Eric Laurentb469b942011-05-09 12:09:06 -07002596 removeTrack_l(track);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002597 }
2598 }
2599 }
2600
2601 // mix buffer must be cleared if all tracks are connected to an
2602 // effect chain as in this case the mixer will not write to
2603 // mix buffer and track effects will accumulate into it
2604 if (mixedTracks != 0 && mixedTracks == tracksWithEffect) {
2605 memset(mMixBuffer, 0, mFrameCount * mChannelCount * sizeof(int16_t));
2606 }
2607
2608 return mixerStatus;
2609}
2610
Glenn Kasten66fcab92012-02-24 14:59:21 -08002611/*
2612The derived values that are cached:
2613 - mixBufferSize from frame count * frame size
2614 - activeSleepTime from activeSleepTimeUs()
2615 - idleSleepTime from idleSleepTimeUs()
2616 - standbyDelay from mActiveSleepTimeUs (DIRECT only)
2617 - maxPeriod from frame count and sample rate (MIXER only)
2618
2619The parameters that affect these derived values are:
2620 - frame count
2621 - frame size
2622 - sample rate
2623 - device type: A2DP or not
2624 - device latency
2625 - format: PCM or not
2626 - active sleep time
2627 - idle sleep time
2628*/
2629
2630void AudioFlinger::PlaybackThread::cacheParameters_l()
2631{
2632 mixBufferSize = mFrameCount * mFrameSize;
2633 activeSleepTime = activeSleepTimeUs();
2634 idleSleepTime = idleSleepTimeUs();
2635}
2636
Glenn Kastenfff6d712012-01-12 16:38:12 -08002637void AudioFlinger::MixerThread::invalidateTracks(audio_stream_type_t streamType)
Mathias Agopian65ab4712010-07-14 17:59:35 -07002638{
Steve Block3856b092011-10-20 11:56:00 +01002639 ALOGV ("MixerThread::invalidateTracks() mixer %p, streamType %d, mTracks.size %d",
Eric Laurentde070132010-07-13 04:45:46 -07002640 this, streamType, mTracks.size());
Mathias Agopian65ab4712010-07-14 17:59:35 -07002641 Mutex::Autolock _l(mLock);
Eric Laurentde070132010-07-13 04:45:46 -07002642
Mathias Agopian65ab4712010-07-14 17:59:35 -07002643 size_t size = mTracks.size();
2644 for (size_t i = 0; i < size; i++) {
2645 sp<Track> t = mTracks[i];
Glenn Kasten02bbd202012-02-08 12:35:35 -08002646 if (t->streamType() == streamType) {
Eric Laurent38ccae22011-03-28 18:37:07 -07002647 android_atomic_or(CBLK_INVALID_ON, &t->mCblk->flags);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002648 t->mCblk->cv.signal();
Mathias Agopian65ab4712010-07-14 17:59:35 -07002649 }
2650 }
2651}
2652
Mathias Agopian65ab4712010-07-14 17:59:35 -07002653// getTrackName_l() must be called with ThreadBase::mLock held
Jean-Michel Trivi7d5b2622012-04-04 18:54:36 -07002654int AudioFlinger::MixerThread::getTrackName_l(audio_channel_mask_t channelMask)
Mathias Agopian65ab4712010-07-14 17:59:35 -07002655{
Jean-Michel Trivi7d5b2622012-04-04 18:54:36 -07002656 int name = mAudioMixer->getTrackName();
2657 if (name >= 0) {
2658 mAudioMixer->setParameter(name,
2659 AudioMixer::TRACK,
2660 AudioMixer::CHANNEL_MASK, (void *)channelMask);
2661 }
2662 return name;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002663}
2664
2665// deleteTrackName_l() must be called with ThreadBase::mLock held
2666void AudioFlinger::MixerThread::deleteTrackName_l(int name)
2667{
Steve Block3856b092011-10-20 11:56:00 +01002668 ALOGV("remove track (%d) and delete from mixer", name);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002669 mAudioMixer->deleteTrackName(name);
2670}
2671
2672// checkForNewParameters_l() must be called with ThreadBase::mLock held
2673bool AudioFlinger::MixerThread::checkForNewParameters_l()
2674{
2675 bool reconfig = false;
2676
2677 while (!mNewParameters.isEmpty()) {
2678 status_t status = NO_ERROR;
2679 String8 keyValuePair = mNewParameters[0];
2680 AudioParameter param = AudioParameter(keyValuePair);
2681 int value;
2682
2683 if (param.getInt(String8(AudioParameter::keySamplingRate), value) == NO_ERROR) {
2684 reconfig = true;
2685 }
2686 if (param.getInt(String8(AudioParameter::keyFormat), value) == NO_ERROR) {
Glenn Kasten58f30212012-01-12 12:27:51 -08002687 if ((audio_format_t) value != AUDIO_FORMAT_PCM_16_BIT) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07002688 status = BAD_VALUE;
2689 } else {
2690 reconfig = true;
2691 }
2692 }
2693 if (param.getInt(String8(AudioParameter::keyChannels), value) == NO_ERROR) {
Dima Zavinfce7a472011-04-19 22:30:36 -07002694 if (value != AUDIO_CHANNEL_OUT_STEREO) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07002695 status = BAD_VALUE;
2696 } else {
2697 reconfig = true;
2698 }
2699 }
2700 if (param.getInt(String8(AudioParameter::keyFrameCount), value) == NO_ERROR) {
2701 // do not accept frame count changes if tracks are open as the track buffer
Glenn Kasten362c4e62011-12-14 10:28:06 -08002702 // size depends on frame count and correct behavior would not be guaranteed
Mathias Agopian65ab4712010-07-14 17:59:35 -07002703 // if frame count is changed after track creation
2704 if (!mTracks.isEmpty()) {
2705 status = INVALID_OPERATION;
2706 } else {
2707 reconfig = true;
2708 }
2709 }
2710 if (param.getInt(String8(AudioParameter::keyRouting), value) == NO_ERROR) {
Glenn Kastend3cee2f2012-03-13 17:55:35 -07002711#ifdef ADD_BATTERY_DATA
Gloria Wang9ee159b2011-02-24 14:51:45 -08002712 // when changing the audio output device, call addBatteryData to notify
2713 // the change
Eric Laurentb469b942011-05-09 12:09:06 -07002714 if ((int)mDevice != value) {
Gloria Wang9ee159b2011-02-24 14:51:45 -08002715 uint32_t params = 0;
2716 // check whether speaker is on
Dima Zavinfce7a472011-04-19 22:30:36 -07002717 if (value & AUDIO_DEVICE_OUT_SPEAKER) {
Gloria Wang9ee159b2011-02-24 14:51:45 -08002718 params |= IMediaPlayerService::kBatteryDataSpeakerOn;
2719 }
2720
2721 int deviceWithoutSpeaker
Dima Zavinfce7a472011-04-19 22:30:36 -07002722 = AUDIO_DEVICE_OUT_ALL & ~AUDIO_DEVICE_OUT_SPEAKER;
Gloria Wang9ee159b2011-02-24 14:51:45 -08002723 // check if any other device (except speaker) is on
2724 if (value & deviceWithoutSpeaker ) {
2725 params |= IMediaPlayerService::kBatteryDataOtherAudioDeviceOn;
2726 }
2727
2728 if (params != 0) {
2729 addBatteryData(params);
2730 }
2731 }
Glenn Kastend3cee2f2012-03-13 17:55:35 -07002732#endif
Gloria Wang9ee159b2011-02-24 14:51:45 -08002733
Mathias Agopian65ab4712010-07-14 17:59:35 -07002734 // forward device change to effects that have requested to be
2735 // aware of attached audio device.
2736 mDevice = (uint32_t)value;
2737 for (size_t i = 0; i < mEffectChains.size(); i++) {
Eric Laurentcab11242010-07-15 12:50:15 -07002738 mEffectChains[i]->setDevice_l(mDevice);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002739 }
2740 }
2741
2742 if (status == NO_ERROR) {
Dima Zavin799a70e2011-04-18 16:57:27 -07002743 status = mOutput->stream->common.set_parameters(&mOutput->stream->common,
Dima Zavinfce7a472011-04-19 22:30:36 -07002744 keyValuePair.string());
Mathias Agopian65ab4712010-07-14 17:59:35 -07002745 if (!mStandby && status == INVALID_OPERATION) {
Glenn Kastene53b9ea2012-03-12 16:29:55 -07002746 mOutput->stream->common.standby(&mOutput->stream->common);
2747 mStandby = true;
2748 mBytesWritten = 0;
2749 status = mOutput->stream->common.set_parameters(&mOutput->stream->common,
Dima Zavinfce7a472011-04-19 22:30:36 -07002750 keyValuePair.string());
Mathias Agopian65ab4712010-07-14 17:59:35 -07002751 }
2752 if (status == NO_ERROR && reconfig) {
2753 delete mAudioMixer;
Glenn Kastene9dd0172012-01-27 18:08:45 -08002754 // for safety in case readOutputParameters() accesses mAudioMixer (it doesn't)
2755 mAudioMixer = NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002756 readOutputParameters();
2757 mAudioMixer = new AudioMixer(mFrameCount, mSampleRate);
2758 for (size_t i = 0; i < mTracks.size() ; i++) {
Jean-Michel Trivi7d5b2622012-04-04 18:54:36 -07002759 int name = getTrackName_l((audio_channel_mask_t)mTracks[i]->mChannelMask);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002760 if (name < 0) break;
2761 mTracks[i]->mName = name;
2762 // limit track sample rate to 2 x new output sample rate
2763 if (mTracks[i]->mCblk->sampleRate > 2 * sampleRate()) {
2764 mTracks[i]->mCblk->sampleRate = 2 * sampleRate();
2765 }
2766 }
2767 sendConfigEvent_l(AudioSystem::OUTPUT_CONFIG_CHANGED);
2768 }
2769 }
2770
2771 mNewParameters.removeAt(0);
2772
2773 mParamStatus = status;
2774 mParamCond.signal();
Eric Laurent60cd0a02011-09-13 11:40:21 -07002775 // wait for condition with time out in case the thread calling ThreadBase::setParameters()
2776 // already timed out waiting for the status and will never signal the condition.
Glenn Kasten7dede872011-12-13 11:04:14 -08002777 mWaitWorkCV.waitRelative(mLock, kSetParametersTimeoutNs);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002778 }
2779 return reconfig;
2780}
2781
2782status_t AudioFlinger::MixerThread::dumpInternals(int fd, const Vector<String16>& args)
2783{
2784 const size_t SIZE = 256;
2785 char buffer[SIZE];
2786 String8 result;
2787
2788 PlaybackThread::dumpInternals(fd, args);
2789
2790 snprintf(buffer, SIZE, "AudioMixer tracks: %08x\n", mAudioMixer->trackNames());
2791 result.append(buffer);
2792 write(fd, result.string(), result.size());
2793 return NO_ERROR;
2794}
2795
Glenn Kasten0bf65bd2012-02-28 18:32:53 -08002796uint32_t AudioFlinger::MixerThread::idleSleepTimeUs() const
Mathias Agopian65ab4712010-07-14 17:59:35 -07002797{
Eric Laurent60e18242010-07-29 06:50:24 -07002798 return (uint32_t)(((mFrameCount * 1000) / mSampleRate) * 1000) / 2;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002799}
2800
Glenn Kasten0bf65bd2012-02-28 18:32:53 -08002801uint32_t AudioFlinger::MixerThread::suspendSleepTimeUs() const
Eric Laurent25cbe0e2010-08-18 18:13:17 -07002802{
2803 return (uint32_t)(((mFrameCount * 1000) / mSampleRate) * 1000);
2804}
2805
Glenn Kasten66fcab92012-02-24 14:59:21 -08002806void AudioFlinger::MixerThread::cacheParameters_l()
2807{
2808 PlaybackThread::cacheParameters_l();
2809
2810 // FIXME: Relaxed timing because of a certain device that can't meet latency
2811 // Should be reduced to 2x after the vendor fixes the driver issue
2812 // increase threshold again due to low power audio mode. The way this warning
2813 // threshold is calculated and its usefulness should be reconsidered anyway.
2814 maxPeriod = seconds(mFrameCount) / mSampleRate * 15;
2815}
2816
Mathias Agopian65ab4712010-07-14 17:59:35 -07002817// ----------------------------------------------------------------------------
Glenn Kasten72ef00d2012-01-17 11:09:42 -08002818AudioFlinger::DirectOutputThread::DirectOutputThread(const sp<AudioFlinger>& audioFlinger,
2819 AudioStreamOut* output, audio_io_handle_t id, uint32_t device)
Glenn Kasten23bb8be2012-01-26 10:38:26 -08002820 : PlaybackThread(audioFlinger, output, id, device, DIRECT)
Glenn Kasten84afa3b2012-01-25 15:28:08 -08002821 // mLeftVolFloat, mRightVolFloat
2822 // mLeftVolShort, mRightVolShort
Mathias Agopian65ab4712010-07-14 17:59:35 -07002823{
Mathias Agopian65ab4712010-07-14 17:59:35 -07002824}
2825
2826AudioFlinger::DirectOutputThread::~DirectOutputThread()
2827{
2828}
2829
Glenn Kasten1465f0c2012-03-06 11:23:32 -08002830AudioFlinger::PlaybackThread::mixer_state AudioFlinger::DirectOutputThread::prepareTracks_l(
2831 Vector< sp<Track> > *tracksToRemove
Glenn Kasten000f0e32012-03-01 17:10:56 -08002832)
Mathias Agopian65ab4712010-07-14 17:59:35 -07002833{
Glenn Kasten1465f0c2012-03-06 11:23:32 -08002834 sp<Track> trackToRemove;
2835
Glenn Kastenfec279f2012-03-08 07:47:15 -08002836 mixer_state mixerStatus = MIXER_IDLE;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002837
Glenn Kasten952eeb22012-03-06 11:30:57 -08002838 // find out which tracks need to be processed
2839 if (mActiveTracks.size() != 0) {
2840 sp<Track> t = mActiveTracks[0].promote();
Glenn Kastenfec279f2012-03-08 07:47:15 -08002841 // The track died recently
2842 if (t == 0) return MIXER_IDLE;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002843
Glenn Kasten952eeb22012-03-06 11:30:57 -08002844 Track* const track = t.get();
2845 audio_track_cblk_t* cblk = track->cblk();
Mathias Agopian65ab4712010-07-14 17:59:35 -07002846
Glenn Kasten952eeb22012-03-06 11:30:57 -08002847 // The first time a track is added we wait
2848 // for all its buffers to be filled before processing it
2849 if (cblk->framesReady() && track->isReady() &&
2850 !track->isPaused() && !track->isTerminated())
2851 {
2852 //ALOGV("track %d u=%08x, s=%08x [OK]", track->name(), cblk->user, cblk->server);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002853
Glenn Kasten952eeb22012-03-06 11:30:57 -08002854 if (track->mFillingUpStatus == Track::FS_FILLED) {
2855 track->mFillingUpStatus = Track::FS_ACTIVE;
2856 mLeftVolFloat = mRightVolFloat = 0;
2857 mLeftVolShort = mRightVolShort = 0;
2858 if (track->mState == TrackBase::RESUMING) {
2859 track->mState = TrackBase::ACTIVE;
2860 rampVolume = true;
2861 }
2862 } else if (cblk->server != 0) {
2863 // If the track is stopped before the first frame was mixed,
2864 // do not apply ramp
2865 rampVolume = true;
2866 }
2867 // compute volume for this track
2868 float left, right;
2869 if (track->isMuted() || mMasterMute || track->isPausing() ||
2870 mStreamTypes[track->streamType()].mute) {
2871 left = right = 0;
2872 if (track->isPausing()) {
2873 track->setPaused();
2874 }
2875 } else {
2876 float typeVolume = mStreamTypes[track->streamType()].volume;
2877 float v = mMasterVolume * typeVolume;
2878 uint32_t vlr = cblk->getVolumeLR();
2879 float v_clamped = v * (vlr & 0xFFFF);
2880 if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN;
2881 left = v_clamped/MAX_GAIN;
2882 v_clamped = v * (vlr >> 16);
2883 if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN;
2884 right = v_clamped/MAX_GAIN;
2885 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07002886
Glenn Kasten952eeb22012-03-06 11:30:57 -08002887 if (left != mLeftVolFloat || right != mRightVolFloat) {
2888 mLeftVolFloat = left;
2889 mRightVolFloat = right;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002890
Glenn Kasten952eeb22012-03-06 11:30:57 -08002891 // If audio HAL implements volume control,
2892 // force software volume to nominal value
2893 if (mOutput->stream->set_volume(mOutput->stream, left, right) == NO_ERROR) {
2894 left = 1.0f;
2895 right = 1.0f;
2896 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07002897
Glenn Kasten952eeb22012-03-06 11:30:57 -08002898 // Convert volumes from float to 8.24
2899 uint32_t vl = (uint32_t)(left * (1 << 24));
2900 uint32_t vr = (uint32_t)(right * (1 << 24));
Mathias Agopian65ab4712010-07-14 17:59:35 -07002901
Glenn Kasten952eeb22012-03-06 11:30:57 -08002902 // Delegate volume control to effect in track effect chain if needed
2903 // only one effect chain can be present on DirectOutputThread, so if
2904 // there is one, the track is connected to it
2905 if (!mEffectChains.isEmpty()) {
2906 // Do not ramp volume if volume is controlled by effect
2907 if (mEffectChains[0]->setVolume_l(&vl, &vr)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07002908 rampVolume = false;
2909 }
Glenn Kasten952eeb22012-03-06 11:30:57 -08002910 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07002911
Glenn Kasten952eeb22012-03-06 11:30:57 -08002912 // Convert volumes from 8.24 to 4.12 format
2913 uint32_t v_clamped = (vl + (1 << 11)) >> 12;
2914 if (v_clamped > MAX_GAIN_INT) v_clamped = MAX_GAIN_INT;
2915 leftVol = (uint16_t)v_clamped;
2916 v_clamped = (vr + (1 << 11)) >> 12;
2917 if (v_clamped > MAX_GAIN_INT) v_clamped = MAX_GAIN_INT;
2918 rightVol = (uint16_t)v_clamped;
2919 } else {
2920 leftVol = mLeftVolShort;
2921 rightVol = mRightVolShort;
2922 rampVolume = false;
2923 }
2924
2925 // reset retry count
2926 track->mRetryCount = kMaxTrackRetriesDirect;
Glenn Kastenb071e9b2012-03-07 17:05:59 -08002927 mActiveTrack = t;
Glenn Kastenfec279f2012-03-08 07:47:15 -08002928 mixerStatus = MIXER_TRACKS_READY;
Glenn Kasten952eeb22012-03-06 11:30:57 -08002929 } else {
2930 //ALOGV("track %d u=%08x, s=%08x [NOT READY]", track->name(), cblk->user, cblk->server);
2931 if (track->isStopped()) {
2932 track->reset();
2933 }
2934 if (track->isTerminated() || track->isStopped() || track->isPaused()) {
2935 // We have consumed all the buffers of this track.
2936 // Remove it from the list of active tracks.
Eric Laurenta011e352012-03-29 15:51:43 -07002937 // TODO: implement behavior for compressed audio
2938 size_t audioHALFrames =
2939 (mOutput->stream->get_latency(mOutput->stream)*mSampleRate) / 1000;
2940 size_t framesWritten =
2941 mBytesWritten / audio_stream_frame_size(&mOutput->stream->common);
2942 if (track->presentationComplete(framesWritten, audioHALFrames)) {
2943 trackToRemove = track;
2944 }
Glenn Kasten952eeb22012-03-06 11:30:57 -08002945 } else {
2946 // No buffers for this track. Give it a few chances to
2947 // fill a buffer, then remove it from active list.
2948 if (--(track->mRetryCount) <= 0) {
2949 ALOGV("BUFFER TIMEOUT: remove(%d) from active list", track->name());
2950 trackToRemove = track;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002951 } else {
Glenn Kastenfec279f2012-03-08 07:47:15 -08002952 mixerStatus = MIXER_TRACKS_ENABLED;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002953 }
2954 }
Glenn Kasten952eeb22012-03-06 11:30:57 -08002955 }
2956 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07002957
Glenn Kasten1465f0c2012-03-06 11:23:32 -08002958 // FIXME merge this with similar code for removing multiple tracks
Glenn Kasten952eeb22012-03-06 11:30:57 -08002959 // remove all the tracks that need to be...
2960 if (CC_UNLIKELY(trackToRemove != 0)) {
Glenn Kasten1465f0c2012-03-06 11:23:32 -08002961 tracksToRemove->add(trackToRemove);
Glenn Kasten952eeb22012-03-06 11:30:57 -08002962 mActiveTracks.remove(trackToRemove);
2963 if (!mEffectChains.isEmpty()) {
Glenn Kasten5798d4e2012-03-08 12:18:35 -08002964 ALOGV("stopping track on chain %p for session Id: %d", mEffectChains[0].get(),
Glenn Kasten952eeb22012-03-06 11:30:57 -08002965 trackToRemove->sessionId());
2966 mEffectChains[0]->decActiveTrackCnt();
2967 }
2968 if (trackToRemove->isTerminated()) {
2969 removeTrack_l(trackToRemove);
2970 }
2971 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07002972
Glenn Kastenfec279f2012-03-08 07:47:15 -08002973 return mixerStatus;
Glenn Kasten000f0e32012-03-01 17:10:56 -08002974}
Mathias Agopian65ab4712010-07-14 17:59:35 -07002975
Glenn Kasten000f0e32012-03-01 17:10:56 -08002976void AudioFlinger::DirectOutputThread::threadLoop_mix()
2977{
Glenn Kasten952eeb22012-03-06 11:30:57 -08002978 AudioBufferProvider::Buffer buffer;
2979 size_t frameCount = mFrameCount;
2980 int8_t *curBuf = (int8_t *)mMixBuffer;
2981 // output audio to hardware
2982 while (frameCount) {
2983 buffer.frameCount = frameCount;
Glenn Kastenb071e9b2012-03-07 17:05:59 -08002984 mActiveTrack->getNextBuffer(&buffer);
Glenn Kasten952eeb22012-03-06 11:30:57 -08002985 if (CC_UNLIKELY(buffer.raw == NULL)) {
2986 memset(curBuf, 0, frameCount * mFrameSize);
2987 break;
2988 }
2989 memcpy(curBuf, buffer.raw, buffer.frameCount * mFrameSize);
2990 frameCount -= buffer.frameCount;
2991 curBuf += buffer.frameCount * mFrameSize;
Glenn Kastenb071e9b2012-03-07 17:05:59 -08002992 mActiveTrack->releaseBuffer(&buffer);
Glenn Kasten952eeb22012-03-06 11:30:57 -08002993 }
2994 sleepTime = 0;
2995 standbyTime = systemTime() + standbyDelay;
Glenn Kastenb071e9b2012-03-07 17:05:59 -08002996 mActiveTrack.clear();
Glenn Kasten73f4bc32012-03-09 12:08:48 -08002997
2998 // apply volume
2999
3000 // Do not apply volume on compressed audio
3001 if (!audio_is_linear_pcm(mFormat)) {
3002 return;
3003 }
3004
3005 // convert to signed 16 bit before volume calculation
3006 if (mFormat == AUDIO_FORMAT_PCM_8_BIT) {
3007 size_t count = mFrameCount * mChannelCount;
3008 uint8_t *src = (uint8_t *)mMixBuffer + count-1;
3009 int16_t *dst = mMixBuffer + count-1;
Glenn Kastene53b9ea2012-03-12 16:29:55 -07003010 while (count--) {
Glenn Kasten73f4bc32012-03-09 12:08:48 -08003011 *dst-- = (int16_t)(*src--^0x80) << 8;
3012 }
3013 }
3014
3015 frameCount = mFrameCount;
3016 int16_t *out = mMixBuffer;
3017 if (rampVolume) {
3018 if (mChannelCount == 1) {
3019 int32_t d = ((int32_t)leftVol - (int32_t)mLeftVolShort) << 16;
3020 int32_t vlInc = d / (int32_t)frameCount;
3021 int32_t vl = ((int32_t)mLeftVolShort << 16);
3022 do {
3023 out[0] = clamp16(mul(out[0], vl >> 16) >> 12);
3024 out++;
3025 vl += vlInc;
3026 } while (--frameCount);
3027
3028 } else {
3029 int32_t d = ((int32_t)leftVol - (int32_t)mLeftVolShort) << 16;
3030 int32_t vlInc = d / (int32_t)frameCount;
3031 d = ((int32_t)rightVol - (int32_t)mRightVolShort) << 16;
3032 int32_t vrInc = d / (int32_t)frameCount;
3033 int32_t vl = ((int32_t)mLeftVolShort << 16);
3034 int32_t vr = ((int32_t)mRightVolShort << 16);
3035 do {
3036 out[0] = clamp16(mul(out[0], vl >> 16) >> 12);
3037 out[1] = clamp16(mul(out[1], vr >> 16) >> 12);
3038 out += 2;
3039 vl += vlInc;
3040 vr += vrInc;
3041 } while (--frameCount);
3042 }
3043 } else {
3044 if (mChannelCount == 1) {
3045 do {
3046 out[0] = clamp16(mul(out[0], leftVol) >> 12);
3047 out++;
3048 } while (--frameCount);
3049 } else {
3050 do {
3051 out[0] = clamp16(mul(out[0], leftVol) >> 12);
3052 out[1] = clamp16(mul(out[1], rightVol) >> 12);
3053 out += 2;
3054 } while (--frameCount);
3055 }
3056 }
3057
3058 // convert back to unsigned 8 bit after volume calculation
3059 if (mFormat == AUDIO_FORMAT_PCM_8_BIT) {
3060 size_t count = mFrameCount * mChannelCount;
3061 int16_t *src = mMixBuffer;
3062 uint8_t *dst = (uint8_t *)mMixBuffer;
Glenn Kastene53b9ea2012-03-12 16:29:55 -07003063 while (count--) {
Glenn Kasten73f4bc32012-03-09 12:08:48 -08003064 *dst++ = (uint8_t)(((int32_t)*src++ + (1<<7)) >> 8)^0x80;
3065 }
3066 }
3067
3068 mLeftVolShort = leftVol;
3069 mRightVolShort = rightVol;
Glenn Kasten000f0e32012-03-01 17:10:56 -08003070}
3071
3072void AudioFlinger::DirectOutputThread::threadLoop_sleepTime()
3073{
Glenn Kasten952eeb22012-03-06 11:30:57 -08003074 if (sleepTime == 0) {
Glenn Kastenfec279f2012-03-08 07:47:15 -08003075 if (mMixerStatus == MIXER_TRACKS_ENABLED) {
Glenn Kasten952eeb22012-03-06 11:30:57 -08003076 sleepTime = activeSleepTime;
3077 } else {
3078 sleepTime = idleSleepTime;
3079 }
3080 } else if (mBytesWritten != 0 && audio_is_linear_pcm(mFormat)) {
3081 memset (mMixBuffer, 0, mFrameCount * mFrameSize);
3082 sleepTime = 0;
3083 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07003084}
3085
3086// getTrackName_l() must be called with ThreadBase::mLock held
Jean-Michel Trivi7d5b2622012-04-04 18:54:36 -07003087int AudioFlinger::DirectOutputThread::getTrackName_l(audio_channel_mask_t channelMask)
Mathias Agopian65ab4712010-07-14 17:59:35 -07003088{
3089 return 0;
3090}
3091
3092// deleteTrackName_l() must be called with ThreadBase::mLock held
3093void AudioFlinger::DirectOutputThread::deleteTrackName_l(int name)
3094{
3095}
3096
3097// checkForNewParameters_l() must be called with ThreadBase::mLock held
3098bool AudioFlinger::DirectOutputThread::checkForNewParameters_l()
3099{
3100 bool reconfig = false;
3101
3102 while (!mNewParameters.isEmpty()) {
3103 status_t status = NO_ERROR;
3104 String8 keyValuePair = mNewParameters[0];
3105 AudioParameter param = AudioParameter(keyValuePair);
3106 int value;
3107
3108 if (param.getInt(String8(AudioParameter::keyFrameCount), value) == NO_ERROR) {
3109 // do not accept frame count changes if tracks are open as the track buffer
3110 // size depends on frame count and correct behavior would not be garantied
3111 // if frame count is changed after track creation
3112 if (!mTracks.isEmpty()) {
3113 status = INVALID_OPERATION;
3114 } else {
3115 reconfig = true;
3116 }
3117 }
3118 if (status == NO_ERROR) {
Dima Zavin799a70e2011-04-18 16:57:27 -07003119 status = mOutput->stream->common.set_parameters(&mOutput->stream->common,
Dima Zavinfce7a472011-04-19 22:30:36 -07003120 keyValuePair.string());
Mathias Agopian65ab4712010-07-14 17:59:35 -07003121 if (!mStandby && status == INVALID_OPERATION) {
Glenn Kastene53b9ea2012-03-12 16:29:55 -07003122 mOutput->stream->common.standby(&mOutput->stream->common);
3123 mStandby = true;
3124 mBytesWritten = 0;
3125 status = mOutput->stream->common.set_parameters(&mOutput->stream->common,
Dima Zavinfce7a472011-04-19 22:30:36 -07003126 keyValuePair.string());
Mathias Agopian65ab4712010-07-14 17:59:35 -07003127 }
3128 if (status == NO_ERROR && reconfig) {
3129 readOutputParameters();
3130 sendConfigEvent_l(AudioSystem::OUTPUT_CONFIG_CHANGED);
3131 }
3132 }
3133
3134 mNewParameters.removeAt(0);
3135
3136 mParamStatus = status;
3137 mParamCond.signal();
Eric Laurent60cd0a02011-09-13 11:40:21 -07003138 // wait for condition with time out in case the thread calling ThreadBase::setParameters()
3139 // already timed out waiting for the status and will never signal the condition.
Glenn Kasten7dede872011-12-13 11:04:14 -08003140 mWaitWorkCV.waitRelative(mLock, kSetParametersTimeoutNs);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003141 }
3142 return reconfig;
3143}
3144
Glenn Kasten0bf65bd2012-02-28 18:32:53 -08003145uint32_t AudioFlinger::DirectOutputThread::activeSleepTimeUs() const
Mathias Agopian65ab4712010-07-14 17:59:35 -07003146{
3147 uint32_t time;
Dima Zavinfce7a472011-04-19 22:30:36 -07003148 if (audio_is_linear_pcm(mFormat)) {
Eric Laurent162b40b2011-12-05 09:47:19 -08003149 time = PlaybackThread::activeSleepTimeUs();
Mathias Agopian65ab4712010-07-14 17:59:35 -07003150 } else {
3151 time = 10000;
3152 }
3153 return time;
3154}
3155
Glenn Kasten0bf65bd2012-02-28 18:32:53 -08003156uint32_t AudioFlinger::DirectOutputThread::idleSleepTimeUs() const
Mathias Agopian65ab4712010-07-14 17:59:35 -07003157{
3158 uint32_t time;
Dima Zavinfce7a472011-04-19 22:30:36 -07003159 if (audio_is_linear_pcm(mFormat)) {
Eric Laurent60e18242010-07-29 06:50:24 -07003160 time = (uint32_t)(((mFrameCount * 1000) / mSampleRate) * 1000) / 2;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003161 } else {
3162 time = 10000;
3163 }
3164 return time;
3165}
3166
Glenn Kasten0bf65bd2012-02-28 18:32:53 -08003167uint32_t AudioFlinger::DirectOutputThread::suspendSleepTimeUs() const
Eric Laurent25cbe0e2010-08-18 18:13:17 -07003168{
3169 uint32_t time;
Dima Zavinfce7a472011-04-19 22:30:36 -07003170 if (audio_is_linear_pcm(mFormat)) {
Eric Laurent25cbe0e2010-08-18 18:13:17 -07003171 time = (uint32_t)(((mFrameCount * 1000) / mSampleRate) * 1000);
3172 } else {
3173 time = 10000;
3174 }
3175 return time;
3176}
3177
Glenn Kasten66fcab92012-02-24 14:59:21 -08003178void AudioFlinger::DirectOutputThread::cacheParameters_l()
3179{
3180 PlaybackThread::cacheParameters_l();
3181
3182 // use shorter standby delay as on normal output to release
3183 // hardware resources as soon as possible
3184 standbyDelay = microseconds(activeSleepTime*2);
3185}
Eric Laurent25cbe0e2010-08-18 18:13:17 -07003186
Mathias Agopian65ab4712010-07-14 17:59:35 -07003187// ----------------------------------------------------------------------------
3188
Glenn Kasten23bb8be2012-01-26 10:38:26 -08003189AudioFlinger::DuplicatingThread::DuplicatingThread(const sp<AudioFlinger>& audioFlinger,
Glenn Kasten72ef00d2012-01-17 11:09:42 -08003190 AudioFlinger::MixerThread* mainThread, audio_io_handle_t id)
Glenn Kasten23bb8be2012-01-26 10:38:26 -08003191 : MixerThread(audioFlinger, mainThread->getOutput(), id, mainThread->device(), DUPLICATING),
3192 mWaitTimeMs(UINT_MAX)
Mathias Agopian65ab4712010-07-14 17:59:35 -07003193{
Mathias Agopian65ab4712010-07-14 17:59:35 -07003194 addOutputTrack(mainThread);
3195}
3196
3197AudioFlinger::DuplicatingThread::~DuplicatingThread()
3198{
3199 for (size_t i = 0; i < mOutputTracks.size(); i++) {
3200 mOutputTracks[i]->destroy();
3201 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07003202}
3203
Glenn Kasten000f0e32012-03-01 17:10:56 -08003204void AudioFlinger::DuplicatingThread::threadLoop_mix()
Mathias Agopian65ab4712010-07-14 17:59:35 -07003205{
Glenn Kasten952eeb22012-03-06 11:30:57 -08003206 // mix buffers...
3207 if (outputsReady(outputTracks)) {
3208 mAudioMixer->process(AudioBufferProvider::kInvalidPTS);
3209 } else {
3210 memset(mMixBuffer, 0, mixBufferSize);
3211 }
3212 sleepTime = 0;
3213 writeFrames = mFrameCount;
Glenn Kasten000f0e32012-03-01 17:10:56 -08003214}
3215
3216void AudioFlinger::DuplicatingThread::threadLoop_sleepTime()
3217{
Glenn Kasten952eeb22012-03-06 11:30:57 -08003218 if (sleepTime == 0) {
Glenn Kastenfec279f2012-03-08 07:47:15 -08003219 if (mMixerStatus == MIXER_TRACKS_ENABLED) {
Glenn Kasten952eeb22012-03-06 11:30:57 -08003220 sleepTime = activeSleepTime;
3221 } else {
3222 sleepTime = idleSleepTime;
3223 }
3224 } else if (mBytesWritten != 0) {
3225 // flush remaining overflow buffers in output tracks
3226 for (size_t i = 0; i < outputTracks.size(); i++) {
3227 if (outputTracks[i]->isActive()) {
3228 sleepTime = 0;
3229 writeFrames = 0;
3230 memset(mMixBuffer, 0, mixBufferSize);
3231 break;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003232 }
Glenn Kasten952eeb22012-03-06 11:30:57 -08003233 }
3234 }
Glenn Kasten000f0e32012-03-01 17:10:56 -08003235}
Mathias Agopian65ab4712010-07-14 17:59:35 -07003236
Glenn Kasten000f0e32012-03-01 17:10:56 -08003237void AudioFlinger::DuplicatingThread::threadLoop_write()
3238{
Glenn Kasten66fcab92012-02-24 14:59:21 -08003239 standbyTime = systemTime() + standbyDelay;
Glenn Kasten952eeb22012-03-06 11:30:57 -08003240 for (size_t i = 0; i < outputTracks.size(); i++) {
3241 outputTracks[i]->write(mMixBuffer, writeFrames);
3242 }
3243 mBytesWritten += mixBufferSize;
Glenn Kasten000f0e32012-03-01 17:10:56 -08003244}
Glenn Kasten688a6402012-02-29 07:57:06 -08003245
Glenn Kasten000f0e32012-03-01 17:10:56 -08003246void AudioFlinger::DuplicatingThread::threadLoop_standby()
3247{
Glenn Kasten952eeb22012-03-06 11:30:57 -08003248 // DuplicatingThread implements standby by stopping all tracks
3249 for (size_t i = 0; i < outputTracks.size(); i++) {
3250 outputTracks[i]->stop();
3251 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07003252}
3253
Glenn Kastenfa26a852012-03-06 11:28:04 -08003254void AudioFlinger::DuplicatingThread::saveOutputTracks()
3255{
3256 outputTracks = mOutputTracks;
3257}
3258
3259void AudioFlinger::DuplicatingThread::clearOutputTracks()
3260{
3261 outputTracks.clear();
3262}
3263
Mathias Agopian65ab4712010-07-14 17:59:35 -07003264void AudioFlinger::DuplicatingThread::addOutputTrack(MixerThread *thread)
3265{
Glenn Kastenb6b74062012-02-24 14:12:20 -08003266 Mutex::Autolock _l(mLock);
Glenn Kasten99e53b82012-01-19 08:59:58 -08003267 // FIXME explain this formula
Mathias Agopian65ab4712010-07-14 17:59:35 -07003268 int frameCount = (3 * mFrameCount * mSampleRate) / thread->sampleRate();
Glenn Kasten9eaa5572012-01-20 13:32:16 -08003269 OutputTrack *outputTrack = new OutputTrack(thread,
Mathias Agopian65ab4712010-07-14 17:59:35 -07003270 this,
3271 mSampleRate,
3272 mFormat,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07003273 mChannelMask,
Mathias Agopian65ab4712010-07-14 17:59:35 -07003274 frameCount);
3275 if (outputTrack->cblk() != NULL) {
Dima Zavinfce7a472011-04-19 22:30:36 -07003276 thread->setStreamVolume(AUDIO_STREAM_CNT, 1.0f);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003277 mOutputTracks.add(outputTrack);
Steve Block3856b092011-10-20 11:56:00 +01003278 ALOGV("addOutputTrack() track %p, on thread %p", outputTrack, thread);
Glenn Kasten438b0362012-03-06 11:24:48 -08003279 updateWaitTime_l();
Mathias Agopian65ab4712010-07-14 17:59:35 -07003280 }
3281}
3282
3283void AudioFlinger::DuplicatingThread::removeOutputTrack(MixerThread *thread)
3284{
3285 Mutex::Autolock _l(mLock);
3286 for (size_t i = 0; i < mOutputTracks.size(); i++) {
Glenn Kastena1117922012-01-26 10:53:32 -08003287 if (mOutputTracks[i]->thread() == thread) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07003288 mOutputTracks[i]->destroy();
3289 mOutputTracks.removeAt(i);
Glenn Kasten438b0362012-03-06 11:24:48 -08003290 updateWaitTime_l();
Mathias Agopian65ab4712010-07-14 17:59:35 -07003291 return;
3292 }
3293 }
Steve Block3856b092011-10-20 11:56:00 +01003294 ALOGV("removeOutputTrack(): unkonwn thread: %p", thread);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003295}
3296
Glenn Kasten438b0362012-03-06 11:24:48 -08003297// caller must hold mLock
3298void AudioFlinger::DuplicatingThread::updateWaitTime_l()
Mathias Agopian65ab4712010-07-14 17:59:35 -07003299{
3300 mWaitTimeMs = UINT_MAX;
3301 for (size_t i = 0; i < mOutputTracks.size(); i++) {
3302 sp<ThreadBase> strong = mOutputTracks[i]->thread().promote();
Glenn Kasten7378ca52012-01-20 13:44:40 -08003303 if (strong != 0) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07003304 uint32_t waitTimeMs = (strong->frameCount() * 2 * 1000) / strong->sampleRate();
3305 if (waitTimeMs < mWaitTimeMs) {
3306 mWaitTimeMs = waitTimeMs;
3307 }
3308 }
3309 }
3310}
3311
3312
Glenn Kasten02fe1bf2012-02-24 15:42:17 -08003313bool AudioFlinger::DuplicatingThread::outputsReady(const SortedVector< sp<OutputTrack> > &outputTracks)
Mathias Agopian65ab4712010-07-14 17:59:35 -07003314{
3315 for (size_t i = 0; i < outputTracks.size(); i++) {
Glenn Kastene53b9ea2012-03-12 16:29:55 -07003316 sp<ThreadBase> thread = outputTracks[i]->thread().promote();
Mathias Agopian65ab4712010-07-14 17:59:35 -07003317 if (thread == 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00003318 ALOGW("DuplicatingThread::outputsReady() could not promote thread on output track %p", outputTracks[i].get());
Mathias Agopian65ab4712010-07-14 17:59:35 -07003319 return false;
3320 }
3321 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
3322 if (playbackThread->standby() && !playbackThread->isSuspended()) {
Steve Block3856b092011-10-20 11:56:00 +01003323 ALOGV("DuplicatingThread output track %p on thread %p Not Ready", outputTracks[i].get(), thread.get());
Mathias Agopian65ab4712010-07-14 17:59:35 -07003324 return false;
3325 }
3326 }
3327 return true;
3328}
3329
Glenn Kasten0bf65bd2012-02-28 18:32:53 -08003330uint32_t AudioFlinger::DuplicatingThread::activeSleepTimeUs() const
Mathias Agopian65ab4712010-07-14 17:59:35 -07003331{
3332 return (mWaitTimeMs * 1000) / 2;
3333}
3334
Glenn Kasten66fcab92012-02-24 14:59:21 -08003335void AudioFlinger::DuplicatingThread::cacheParameters_l()
3336{
3337 // updateWaitTime_l() sets mWaitTimeMs, which affects activeSleepTimeUs(), so call it first
3338 updateWaitTime_l();
3339
3340 MixerThread::cacheParameters_l();
3341}
3342
Mathias Agopian65ab4712010-07-14 17:59:35 -07003343// ----------------------------------------------------------------------------
3344
3345// TrackBase constructor must be called with AudioFlinger::mLock held
3346AudioFlinger::ThreadBase::TrackBase::TrackBase(
Glenn Kasten9eaa5572012-01-20 13:32:16 -08003347 ThreadBase *thread,
Mathias Agopian65ab4712010-07-14 17:59:35 -07003348 const sp<Client>& client,
3349 uint32_t sampleRate,
Glenn Kasten58f30212012-01-12 12:27:51 -08003350 audio_format_t format,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07003351 uint32_t channelMask,
Mathias Agopian65ab4712010-07-14 17:59:35 -07003352 int frameCount,
Mathias Agopian65ab4712010-07-14 17:59:35 -07003353 const sp<IMemory>& sharedBuffer,
3354 int sessionId)
3355 : RefBase(),
3356 mThread(thread),
3357 mClient(client),
Glenn Kasten84afa3b2012-01-25 15:28:08 -08003358 mCblk(NULL),
3359 // mBuffer
3360 // mBufferEnd
Mathias Agopian65ab4712010-07-14 17:59:35 -07003361 mFrameCount(0),
3362 mState(IDLE),
Mathias Agopian65ab4712010-07-14 17:59:35 -07003363 mFormat(format),
Glenn Kasten5cf034d2012-02-21 10:35:56 -08003364 mStepServerFailed(false),
Mathias Agopian65ab4712010-07-14 17:59:35 -07003365 mSessionId(sessionId)
Glenn Kasten84afa3b2012-01-25 15:28:08 -08003366 // mChannelCount
3367 // mChannelMask
Mathias Agopian65ab4712010-07-14 17:59:35 -07003368{
Steve Block3856b092011-10-20 11:56:00 +01003369 ALOGV_IF(sharedBuffer != 0, "sharedBuffer: %p, size: %d", sharedBuffer->pointer(), sharedBuffer->size());
Mathias Agopian65ab4712010-07-14 17:59:35 -07003370
Steve Blockb8a80522011-12-20 16:23:08 +00003371 // ALOGD("Creating track with %d buffers @ %d bytes", bufferCount, bufferSize);
Glenn Kastene53b9ea2012-03-12 16:29:55 -07003372 size_t size = sizeof(audio_track_cblk_t);
3373 uint8_t channelCount = popcount(channelMask);
3374 size_t bufferSize = frameCount*channelCount*sizeof(int16_t);
3375 if (sharedBuffer == 0) {
3376 size += bufferSize;
3377 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07003378
Glenn Kastene53b9ea2012-03-12 16:29:55 -07003379 if (client != NULL) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07003380 mCblkMemory = client->heap()->allocate(size);
3381 if (mCblkMemory != 0) {
3382 mCblk = static_cast<audio_track_cblk_t *>(mCblkMemory->pointer());
Glenn Kastena0d68332012-01-27 16:47:15 -08003383 if (mCblk != NULL) { // construct the shared structure in-place.
Mathias Agopian65ab4712010-07-14 17:59:35 -07003384 new(mCblk) audio_track_cblk_t();
3385 // clear all buffers
3386 mCblk->frameCount = frameCount;
3387 mCblk->sampleRate = sampleRate;
Marco Nelissena1472d92012-03-30 14:36:54 -07003388// uncomment the following lines to quickly test 32-bit wraparound
3389// mCblk->user = 0xffff0000;
3390// mCblk->server = 0xffff0000;
3391// mCblk->userBase = 0xffff0000;
3392// mCblk->serverBase = 0xffff0000;
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07003393 mChannelCount = channelCount;
3394 mChannelMask = channelMask;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003395 if (sharedBuffer == 0) {
3396 mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t);
3397 memset(mBuffer, 0, frameCount*channelCount*sizeof(int16_t));
3398 // Force underrun condition to avoid false underrun callback until first data is
Eric Laurent44d98482010-09-30 16:12:31 -07003399 // written to buffer (other flags are cleared)
Mathias Agopian65ab4712010-07-14 17:59:35 -07003400 mCblk->flags = CBLK_UNDERRUN_ON;
3401 } else {
3402 mBuffer = sharedBuffer->pointer();
3403 }
3404 mBufferEnd = (uint8_t *)mBuffer + bufferSize;
3405 }
3406 } else {
Steve Block29357bc2012-01-06 19:20:56 +00003407 ALOGE("not enough memory for AudioTrack size=%u", size);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003408 client->heap()->dump("AudioTrack");
3409 return;
3410 }
Glenn Kastene53b9ea2012-03-12 16:29:55 -07003411 } else {
3412 mCblk = (audio_track_cblk_t *)(new uint8_t[size]);
Glenn Kastenea7939a2012-03-14 12:56:26 -07003413 // construct the shared structure in-place.
3414 new(mCblk) audio_track_cblk_t();
3415 // clear all buffers
3416 mCblk->frameCount = frameCount;
3417 mCblk->sampleRate = sampleRate;
Marco Nelissena1472d92012-03-30 14:36:54 -07003418// uncomment the following lines to quickly test 32-bit wraparound
3419// mCblk->user = 0xffff0000;
3420// mCblk->server = 0xffff0000;
3421// mCblk->userBase = 0xffff0000;
3422// mCblk->serverBase = 0xffff0000;
Glenn Kastenea7939a2012-03-14 12:56:26 -07003423 mChannelCount = channelCount;
3424 mChannelMask = channelMask;
3425 mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t);
3426 memset(mBuffer, 0, frameCount*channelCount*sizeof(int16_t));
3427 // Force underrun condition to avoid false underrun callback until first data is
3428 // written to buffer (other flags are cleared)
3429 mCblk->flags = CBLK_UNDERRUN_ON;
3430 mBufferEnd = (uint8_t *)mBuffer + bufferSize;
Glenn Kastene53b9ea2012-03-12 16:29:55 -07003431 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07003432}
3433
3434AudioFlinger::ThreadBase::TrackBase::~TrackBase()
3435{
Glenn Kastena0d68332012-01-27 16:47:15 -08003436 if (mCblk != NULL) {
Glenn Kasten1a0ae5b2012-02-03 10:24:48 -08003437 if (mClient == 0) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07003438 delete mCblk;
Glenn Kasten1a0ae5b2012-02-03 10:24:48 -08003439 } else {
3440 mCblk->~audio_track_cblk_t(); // destroy our shared-structure.
Mathias Agopian65ab4712010-07-14 17:59:35 -07003441 }
3442 }
Glenn Kastendbfafaf2012-01-25 15:27:15 -08003443 mCblkMemory.clear(); // free the shared memory before releasing the heap it belongs to
Glenn Kasten7378ca52012-01-20 13:44:40 -08003444 if (mClient != 0) {
Glenn Kasten84afa3b2012-01-25 15:28:08 -08003445 // Client destructor must run with AudioFlinger mutex locked
Mathias Agopian65ab4712010-07-14 17:59:35 -07003446 Mutex::Autolock _l(mClient->audioFlinger()->mLock);
Glenn Kasten7378ca52012-01-20 13:44:40 -08003447 // If the client's reference count drops to zero, the associated destructor
3448 // must run with AudioFlinger lock held. Thus the explicit clear() rather than
3449 // relying on the automatic clear() at end of scope.
Mathias Agopian65ab4712010-07-14 17:59:35 -07003450 mClient.clear();
3451 }
3452}
3453
Glenn Kasten01c4ebf2012-02-22 10:47:35 -08003454// AudioBufferProvider interface
3455// getNextBuffer() = 0;
3456// This implementation of releaseBuffer() is used by Track and RecordTrack, but not TimedTrack
Mathias Agopian65ab4712010-07-14 17:59:35 -07003457void AudioFlinger::ThreadBase::TrackBase::releaseBuffer(AudioBufferProvider::Buffer* buffer)
3458{
Glenn Kastene0feee32011-12-13 11:53:26 -08003459 buffer->raw = NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003460 mFrameCount = buffer->frameCount;
Glenn Kasten01c4ebf2012-02-22 10:47:35 -08003461 (void) step(); // ignore return value of step()
Mathias Agopian65ab4712010-07-14 17:59:35 -07003462 buffer->frameCount = 0;
3463}
3464
3465bool AudioFlinger::ThreadBase::TrackBase::step() {
3466 bool result;
3467 audio_track_cblk_t* cblk = this->cblk();
3468
3469 result = cblk->stepServer(mFrameCount);
3470 if (!result) {
Steve Block3856b092011-10-20 11:56:00 +01003471 ALOGV("stepServer failed acquiring cblk mutex");
Glenn Kasten5cf034d2012-02-21 10:35:56 -08003472 mStepServerFailed = true;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003473 }
3474 return result;
3475}
3476
3477void AudioFlinger::ThreadBase::TrackBase::reset() {
3478 audio_track_cblk_t* cblk = this->cblk();
3479
3480 cblk->user = 0;
3481 cblk->server = 0;
3482 cblk->userBase = 0;
3483 cblk->serverBase = 0;
Glenn Kasten5cf034d2012-02-21 10:35:56 -08003484 mStepServerFailed = false;
Steve Block3856b092011-10-20 11:56:00 +01003485 ALOGV("TrackBase::reset");
Mathias Agopian65ab4712010-07-14 17:59:35 -07003486}
3487
Mathias Agopian65ab4712010-07-14 17:59:35 -07003488int AudioFlinger::ThreadBase::TrackBase::sampleRate() const {
3489 return (int)mCblk->sampleRate;
3490}
3491
Mathias Agopian65ab4712010-07-14 17:59:35 -07003492void* AudioFlinger::ThreadBase::TrackBase::getBuffer(uint32_t offset, uint32_t frames) const {
3493 audio_track_cblk_t* cblk = this->cblk();
Glenn Kastenb9980652012-01-11 09:48:27 -08003494 size_t frameSize = cblk->frameSize;
3495 int8_t *bufferStart = (int8_t *)mBuffer + (offset-cblk->serverBase)*frameSize;
3496 int8_t *bufferEnd = bufferStart + frames * frameSize;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003497
3498 // Check validity of returned pointer in case the track control block would have been corrupted.
3499 if (bufferStart < mBuffer || bufferStart > bufferEnd || bufferEnd > mBufferEnd ||
Glenn Kastenb9980652012-01-11 09:48:27 -08003500 ((unsigned long)bufferStart & (unsigned long)(frameSize - 1))) {
Steve Block29357bc2012-01-06 19:20:56 +00003501 ALOGE("TrackBase::getBuffer buffer out of range:\n start: %p, end %p , mBuffer %p mBufferEnd %p\n \
Marco Nelissena1472d92012-03-30 14:36:54 -07003502 server %u, serverBase %u, user %u, userBase %u",
Mathias Agopian65ab4712010-07-14 17:59:35 -07003503 bufferStart, bufferEnd, mBuffer, mBufferEnd,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07003504 cblk->server, cblk->serverBase, cblk->user, cblk->userBase);
Glenn Kastena0d68332012-01-27 16:47:15 -08003505 return NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003506 }
3507
3508 return bufferStart;
3509}
3510
Eric Laurenta011e352012-03-29 15:51:43 -07003511status_t AudioFlinger::ThreadBase::TrackBase::setSyncEvent(const sp<SyncEvent>& event)
3512{
3513 mSyncEvents.add(event);
3514 return NO_ERROR;
3515}
3516
Mathias Agopian65ab4712010-07-14 17:59:35 -07003517// ----------------------------------------------------------------------------
3518
3519// Track constructor must be called with AudioFlinger::mLock and ThreadBase::mLock held
3520AudioFlinger::PlaybackThread::Track::Track(
Glenn Kasten9eaa5572012-01-20 13:32:16 -08003521 PlaybackThread *thread,
Mathias Agopian65ab4712010-07-14 17:59:35 -07003522 const sp<Client>& client,
Glenn Kastenfff6d712012-01-12 16:38:12 -08003523 audio_stream_type_t streamType,
Mathias Agopian65ab4712010-07-14 17:59:35 -07003524 uint32_t sampleRate,
Glenn Kasten58f30212012-01-12 12:27:51 -08003525 audio_format_t format,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07003526 uint32_t channelMask,
Mathias Agopian65ab4712010-07-14 17:59:35 -07003527 int frameCount,
3528 const sp<IMemory>& sharedBuffer,
Glenn Kasten73d22752012-03-19 13:38:30 -07003529 int sessionId,
3530 IAudioFlinger::track_flags_t flags)
Glenn Kasten5cf034d2012-02-21 10:35:56 -08003531 : TrackBase(thread, client, sampleRate, format, channelMask, frameCount, sharedBuffer, sessionId),
Glenn Kastenf9959012012-03-19 11:14:37 -07003532 mMute(false),
3533 // mFillingUpStatus ?
3534 // mRetryCount initialized later when needed
3535 mSharedBuffer(sharedBuffer),
3536 mStreamType(streamType),
3537 mName(-1), // see note below
3538 mMainBuffer(thread->mixBuffer()),
3539 mAuxBuffer(NULL),
Eric Laurenta011e352012-03-29 15:51:43 -07003540 mAuxEffectId(0), mHasVolumeController(false),
Glenn Kasten73d22752012-03-19 13:38:30 -07003541 mPresentationCompleteFrames(0),
3542 mFlags(flags)
Mathias Agopian65ab4712010-07-14 17:59:35 -07003543{
3544 if (mCblk != NULL) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07003545 // NOTE: audio_track_cblk_t::frameSize for 8 bit PCM data is based on a sample size of
3546 // 16 bit because data is converted to 16 bit before being stored in buffer by AudioTrack
Eric Laurentedc15ad2011-07-21 19:35:01 -07003547 mCblk->frameSize = audio_is_linear_pcm(format) ? mChannelCount * sizeof(int16_t) : sizeof(uint8_t);
Glenn Kastenf9959012012-03-19 11:14:37 -07003548 // to avoid leaking a track name, do not allocate one unless there is an mCblk
Jean-Michel Trivi7d5b2622012-04-04 18:54:36 -07003549 mName = thread->getTrackName_l((audio_channel_mask_t)channelMask);
Glenn Kastenf9959012012-03-19 11:14:37 -07003550 if (mName < 0) {
3551 ALOGE("no more track names available");
3552 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07003553 }
Glenn Kastenf9959012012-03-19 11:14:37 -07003554 ALOGV("Track constructor name %d, calling pid %d", mName, IPCThreadState::self()->getCallingPid());
Mathias Agopian65ab4712010-07-14 17:59:35 -07003555}
3556
3557AudioFlinger::PlaybackThread::Track::~Track()
3558{
Steve Block3856b092011-10-20 11:56:00 +01003559 ALOGV("PlaybackThread::Track destructor");
Mathias Agopian65ab4712010-07-14 17:59:35 -07003560 sp<ThreadBase> thread = mThread.promote();
3561 if (thread != 0) {
3562 Mutex::Autolock _l(thread->mLock);
3563 mState = TERMINATED;
3564 }
3565}
3566
3567void AudioFlinger::PlaybackThread::Track::destroy()
3568{
3569 // NOTE: destroyTrack_l() can remove a strong reference to this Track
3570 // by removing it from mTracks vector, so there is a risk that this Tracks's
Glenn Kasten99e53b82012-01-19 08:59:58 -08003571 // destructor is called. As the destructor needs to lock mLock,
Mathias Agopian65ab4712010-07-14 17:59:35 -07003572 // we must acquire a strong reference on this Track before locking mLock
3573 // here so that the destructor is called only when exiting this function.
3574 // On the other hand, as long as Track::destroy() is only called by
3575 // TrackHandle destructor, the TrackHandle still holds a strong ref on
3576 // this Track with its member mTrack.
3577 sp<Track> keep(this);
3578 { // scope for mLock
3579 sp<ThreadBase> thread = mThread.promote();
3580 if (thread != 0) {
3581 if (!isOutputTrack()) {
3582 if (mState == ACTIVE || mState == RESUMING) {
Glenn Kasten02bbd202012-02-08 12:35:35 -08003583 AudioSystem::stopOutput(thread->id(), mStreamType, mSessionId);
Gloria Wang9ee159b2011-02-24 14:51:45 -08003584
Glenn Kastend3cee2f2012-03-13 17:55:35 -07003585#ifdef ADD_BATTERY_DATA
Gloria Wang9ee159b2011-02-24 14:51:45 -08003586 // to track the speaker usage
3587 addBatteryData(IMediaPlayerService::kBatteryDataAudioFlingerStop);
Glenn Kastend3cee2f2012-03-13 17:55:35 -07003588#endif
Mathias Agopian65ab4712010-07-14 17:59:35 -07003589 }
3590 AudioSystem::releaseOutput(thread->id());
3591 }
3592 Mutex::Autolock _l(thread->mLock);
3593 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
3594 playbackThread->destroyTrack_l(this);
3595 }
3596 }
3597}
3598
3599void AudioFlinger::PlaybackThread::Track::dump(char* buffer, size_t size)
3600{
Glenn Kasten83d86532012-01-17 14:39:34 -08003601 uint32_t vlr = mCblk->getVolumeLR();
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07003602 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 -07003603 mName - AudioMixer::TRACK0,
Glenn Kasten44deb052012-02-05 18:09:08 -08003604 (mClient == 0) ? getpid_cached : mClient->pid(),
Mathias Agopian65ab4712010-07-14 17:59:35 -07003605 mStreamType,
3606 mFormat,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07003607 mChannelMask,
Mathias Agopian65ab4712010-07-14 17:59:35 -07003608 mSessionId,
3609 mFrameCount,
3610 mState,
3611 mMute,
3612 mFillingUpStatus,
3613 mCblk->sampleRate,
Glenn Kastenb1cf75c2012-01-17 12:20:54 -08003614 vlr & 0xFFFF,
3615 vlr >> 16,
Mathias Agopian65ab4712010-07-14 17:59:35 -07003616 mCblk->server,
3617 mCblk->user,
3618 (int)mMainBuffer,
3619 (int)mAuxBuffer);
3620}
3621
Glenn Kasten01c4ebf2012-02-22 10:47:35 -08003622// AudioBufferProvider interface
John Grossman4ff14ba2012-02-08 16:37:41 -08003623status_t AudioFlinger::PlaybackThread::Track::getNextBuffer(
Glenn Kastene53b9ea2012-03-12 16:29:55 -07003624 AudioBufferProvider::Buffer* buffer, int64_t pts)
Mathias Agopian65ab4712010-07-14 17:59:35 -07003625{
Glenn Kastene53b9ea2012-03-12 16:29:55 -07003626 audio_track_cblk_t* cblk = this->cblk();
3627 uint32_t framesReady;
3628 uint32_t framesReq = buffer->frameCount;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003629
Glenn Kastene53b9ea2012-03-12 16:29:55 -07003630 // Check if last stepServer failed, try to step now
3631 if (mStepServerFailed) {
3632 if (!step()) goto getNextBuffer_exit;
3633 ALOGV("stepServer recovered");
3634 mStepServerFailed = false;
3635 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07003636
Glenn Kastene53b9ea2012-03-12 16:29:55 -07003637 framesReady = cblk->framesReady();
Mathias Agopian65ab4712010-07-14 17:59:35 -07003638
Glenn Kastene53b9ea2012-03-12 16:29:55 -07003639 if (CC_LIKELY(framesReady)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07003640 uint32_t s = cblk->server;
3641 uint32_t bufferEnd = cblk->serverBase + cblk->frameCount;
3642
3643 bufferEnd = (cblk->loopEnd < bufferEnd) ? cblk->loopEnd : bufferEnd;
3644 if (framesReq > framesReady) {
3645 framesReq = framesReady;
3646 }
Marco Nelissena1472d92012-03-30 14:36:54 -07003647 if (framesReq > bufferEnd - s) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07003648 framesReq = bufferEnd - s;
3649 }
3650
Glenn Kastene53b9ea2012-03-12 16:29:55 -07003651 buffer->raw = getBuffer(s, framesReq);
3652 if (buffer->raw == NULL) goto getNextBuffer_exit;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003653
Glenn Kastene53b9ea2012-03-12 16:29:55 -07003654 buffer->frameCount = framesReq;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003655 return NO_ERROR;
Glenn Kastene53b9ea2012-03-12 16:29:55 -07003656 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07003657
3658getNextBuffer_exit:
Glenn Kastene53b9ea2012-03-12 16:29:55 -07003659 buffer->raw = NULL;
3660 buffer->frameCount = 0;
3661 ALOGV("getNextBuffer() no more data for track %d on thread %p", mName, mThread.unsafe_get());
3662 return NOT_ENOUGH_DATA;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003663}
3664
Glenn Kastene53b9ea2012-03-12 16:29:55 -07003665uint32_t AudioFlinger::PlaybackThread::Track::framesReady() const {
John Grossman4ff14ba2012-02-08 16:37:41 -08003666 return mCblk->framesReady();
3667}
3668
Mathias Agopian65ab4712010-07-14 17:59:35 -07003669bool AudioFlinger::PlaybackThread::Track::isReady() const {
Eric Laurentaf59ce22010-10-05 14:41:42 -07003670 if (mFillingUpStatus != FS_FILLING || isStopped() || isPausing()) return true;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003671
John Grossman4ff14ba2012-02-08 16:37:41 -08003672 if (framesReady() >= mCblk->frameCount ||
Mathias Agopian65ab4712010-07-14 17:59:35 -07003673 (mCblk->flags & CBLK_FORCEREADY_MSK)) {
3674 mFillingUpStatus = FS_FILLED;
Eric Laurent38ccae22011-03-28 18:37:07 -07003675 android_atomic_and(~CBLK_FORCEREADY_MSK, &mCblk->flags);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003676 return true;
3677 }
3678 return false;
3679}
3680
Eric Laurenta011e352012-03-29 15:51:43 -07003681status_t AudioFlinger::PlaybackThread::Track::start(pid_t tid,
3682 AudioSystem::sync_event_t event,
3683 int triggerSession)
Mathias Agopian65ab4712010-07-14 17:59:35 -07003684{
3685 status_t status = NO_ERROR;
Glenn Kasten6dbc1352012-02-02 10:56:47 -08003686 ALOGV("start(%d), calling pid %d session %d tid %d",
3687 mName, IPCThreadState::self()->getCallingPid(), mSessionId, tid);
Glenn Kasten73d22752012-03-19 13:38:30 -07003688 // check for use case 2 with missing callback
3689 if (isFastTrack() && (mSharedBuffer == 0) && (tid == 0)) {
3690 ALOGW("AUDIO_POLICY_OUTPUT_FLAG_FAST denied");
3691 mFlags &= ~IAudioFlinger::TRACK_FAST;
3692 // FIXME the track must be invalidated and moved to another thread or
3693 // attached directly to the normal mixer now
3694 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07003695 sp<ThreadBase> thread = mThread.promote();
3696 if (thread != 0) {
3697 Mutex::Autolock _l(thread->mLock);
Glenn Kastenb853e982012-01-26 13:39:18 -08003698 track_state state = mState;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003699 // here the track could be either new, or restarted
3700 // in both cases "unstop" the track
3701 if (mState == PAUSED) {
3702 mState = TrackBase::RESUMING;
Steve Block3856b092011-10-20 11:56:00 +01003703 ALOGV("PAUSED => RESUMING (%d) on thread %p", mName, this);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003704 } else {
3705 mState = TrackBase::ACTIVE;
Steve Block3856b092011-10-20 11:56:00 +01003706 ALOGV("? => ACTIVE (%d) on thread %p", mName, this);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003707 }
3708
3709 if (!isOutputTrack() && state != ACTIVE && state != RESUMING) {
3710 thread->mLock.unlock();
Glenn Kasten02bbd202012-02-08 12:35:35 -08003711 status = AudioSystem::startOutput(thread->id(), mStreamType, mSessionId);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003712 thread->mLock.lock();
Gloria Wang9ee159b2011-02-24 14:51:45 -08003713
Glenn Kastend3cee2f2012-03-13 17:55:35 -07003714#ifdef ADD_BATTERY_DATA
Gloria Wang9ee159b2011-02-24 14:51:45 -08003715 // to track the speaker usage
3716 if (status == NO_ERROR) {
3717 addBatteryData(IMediaPlayerService::kBatteryDataAudioFlingerStart);
3718 }
Glenn Kastend3cee2f2012-03-13 17:55:35 -07003719#endif
Mathias Agopian65ab4712010-07-14 17:59:35 -07003720 }
3721 if (status == NO_ERROR) {
3722 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
3723 playbackThread->addTrack_l(this);
3724 } else {
3725 mState = state;
3726 }
3727 } else {
3728 status = BAD_VALUE;
3729 }
3730 return status;
3731}
3732
3733void AudioFlinger::PlaybackThread::Track::stop()
3734{
Glenn Kasten23d82a92012-02-03 11:10:00 -08003735 ALOGV("stop(%d), calling pid %d", mName, IPCThreadState::self()->getCallingPid());
Mathias Agopian65ab4712010-07-14 17:59:35 -07003736 sp<ThreadBase> thread = mThread.promote();
3737 if (thread != 0) {
3738 Mutex::Autolock _l(thread->mLock);
Glenn Kastenb853e982012-01-26 13:39:18 -08003739 track_state state = mState;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003740 if (mState > STOPPED) {
3741 mState = STOPPED;
3742 // If the track is not active (PAUSED and buffers full), flush buffers
3743 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
3744 if (playbackThread->mActiveTracks.indexOf(this) < 0) {
3745 reset();
3746 }
Steve Block3856b092011-10-20 11:56:00 +01003747 ALOGV("(> STOPPED) => STOPPED (%d) on thread %p", mName, playbackThread);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003748 }
3749 if (!isOutputTrack() && (state == ACTIVE || state == RESUMING)) {
3750 thread->mLock.unlock();
Glenn Kasten02bbd202012-02-08 12:35:35 -08003751 AudioSystem::stopOutput(thread->id(), mStreamType, mSessionId);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003752 thread->mLock.lock();
Gloria Wang9ee159b2011-02-24 14:51:45 -08003753
Glenn Kastend3cee2f2012-03-13 17:55:35 -07003754#ifdef ADD_BATTERY_DATA
Gloria Wang9ee159b2011-02-24 14:51:45 -08003755 // to track the speaker usage
3756 addBatteryData(IMediaPlayerService::kBatteryDataAudioFlingerStop);
Glenn Kastend3cee2f2012-03-13 17:55:35 -07003757#endif
Mathias Agopian65ab4712010-07-14 17:59:35 -07003758 }
3759 }
3760}
3761
3762void AudioFlinger::PlaybackThread::Track::pause()
3763{
Glenn Kasten23d82a92012-02-03 11:10:00 -08003764 ALOGV("pause(%d), calling pid %d", mName, IPCThreadState::self()->getCallingPid());
Mathias Agopian65ab4712010-07-14 17:59:35 -07003765 sp<ThreadBase> thread = mThread.promote();
3766 if (thread != 0) {
3767 Mutex::Autolock _l(thread->mLock);
3768 if (mState == ACTIVE || mState == RESUMING) {
3769 mState = PAUSING;
Steve Block3856b092011-10-20 11:56:00 +01003770 ALOGV("ACTIVE/RESUMING => PAUSING (%d) on thread %p", mName, thread.get());
Mathias Agopian65ab4712010-07-14 17:59:35 -07003771 if (!isOutputTrack()) {
3772 thread->mLock.unlock();
Glenn Kasten02bbd202012-02-08 12:35:35 -08003773 AudioSystem::stopOutput(thread->id(), mStreamType, mSessionId);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003774 thread->mLock.lock();
Gloria Wang9ee159b2011-02-24 14:51:45 -08003775
Glenn Kastend3cee2f2012-03-13 17:55:35 -07003776#ifdef ADD_BATTERY_DATA
Gloria Wang9ee159b2011-02-24 14:51:45 -08003777 // to track the speaker usage
3778 addBatteryData(IMediaPlayerService::kBatteryDataAudioFlingerStop);
Glenn Kastend3cee2f2012-03-13 17:55:35 -07003779#endif
Mathias Agopian65ab4712010-07-14 17:59:35 -07003780 }
3781 }
3782 }
3783}
3784
3785void AudioFlinger::PlaybackThread::Track::flush()
3786{
Steve Block3856b092011-10-20 11:56:00 +01003787 ALOGV("flush(%d)", mName);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003788 sp<ThreadBase> thread = mThread.promote();
3789 if (thread != 0) {
3790 Mutex::Autolock _l(thread->mLock);
3791 if (mState != STOPPED && mState != PAUSED && mState != PAUSING) {
3792 return;
3793 }
3794 // No point remaining in PAUSED state after a flush => go to
3795 // STOPPED state
3796 mState = STOPPED;
3797
Eric Laurent38ccae22011-03-28 18:37:07 -07003798 // do not reset the track if it is still in the process of being stopped or paused.
3799 // this will be done by prepareTracks_l() when the track is stopped.
3800 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
3801 if (playbackThread->mActiveTracks.indexOf(this) < 0) {
3802 reset();
3803 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07003804 }
3805}
3806
3807void AudioFlinger::PlaybackThread::Track::reset()
3808{
3809 // Do not reset twice to avoid discarding data written just after a flush and before
3810 // the audioflinger thread detects the track is stopped.
3811 if (!mResetDone) {
3812 TrackBase::reset();
3813 // Force underrun condition to avoid false underrun callback until first data is
3814 // written to buffer
Eric Laurent38ccae22011-03-28 18:37:07 -07003815 android_atomic_and(~CBLK_FORCEREADY_MSK, &mCblk->flags);
3816 android_atomic_or(CBLK_UNDERRUN_ON, &mCblk->flags);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003817 mFillingUpStatus = FS_FILLING;
3818 mResetDone = true;
Eric Laurenta011e352012-03-29 15:51:43 -07003819 mPresentationCompleteFrames = 0;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003820 }
3821}
3822
3823void AudioFlinger::PlaybackThread::Track::mute(bool muted)
3824{
3825 mMute = muted;
3826}
3827
Mathias Agopian65ab4712010-07-14 17:59:35 -07003828status_t AudioFlinger::PlaybackThread::Track::attachAuxEffect(int EffectId)
3829{
3830 status_t status = DEAD_OBJECT;
3831 sp<ThreadBase> thread = mThread.promote();
3832 if (thread != 0) {
Glenn Kastene53b9ea2012-03-12 16:29:55 -07003833 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
3834 status = playbackThread->attachAuxEffect(this, EffectId);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003835 }
3836 return status;
3837}
3838
3839void AudioFlinger::PlaybackThread::Track::setAuxBuffer(int EffectId, int32_t *buffer)
3840{
3841 mAuxEffectId = EffectId;
3842 mAuxBuffer = buffer;
3843}
3844
Eric Laurenta011e352012-03-29 15:51:43 -07003845bool AudioFlinger::PlaybackThread::Track::presentationComplete(size_t framesWritten,
3846 size_t audioHalFrames)
3847{
3848 // a track is considered presented when the total number of frames written to audio HAL
3849 // corresponds to the number of frames written when presentationComplete() is called for the
3850 // first time (mPresentationCompleteFrames == 0) plus the buffer filling status at that time.
3851 if (mPresentationCompleteFrames == 0) {
3852 mPresentationCompleteFrames = framesWritten + audioHalFrames;
3853 ALOGV("presentationComplete() reset: mPresentationCompleteFrames %d audioHalFrames %d",
3854 mPresentationCompleteFrames, audioHalFrames);
3855 }
3856 if (framesWritten >= mPresentationCompleteFrames) {
3857 ALOGV("presentationComplete() session %d complete: framesWritten %d",
3858 mSessionId, framesWritten);
3859 triggerEvents(AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE);
3860 mPresentationCompleteFrames = 0;
3861 return true;
3862 }
3863 return false;
3864}
3865
3866void AudioFlinger::PlaybackThread::Track::triggerEvents(AudioSystem::sync_event_t type)
3867{
3868 for (int i = 0; i < (int)mSyncEvents.size(); i++) {
3869 if (mSyncEvents[i]->type() == type) {
3870 mSyncEvents[i]->trigger();
3871 mSyncEvents.removeAt(i);
3872 i--;
3873 }
3874 }
3875}
3876
3877
John Grossman4ff14ba2012-02-08 16:37:41 -08003878// timed audio tracks
3879
3880sp<AudioFlinger::PlaybackThread::TimedTrack>
3881AudioFlinger::PlaybackThread::TimedTrack::create(
Glenn Kasten9eaa5572012-01-20 13:32:16 -08003882 PlaybackThread *thread,
John Grossman4ff14ba2012-02-08 16:37:41 -08003883 const sp<Client>& client,
3884 audio_stream_type_t streamType,
3885 uint32_t sampleRate,
3886 audio_format_t format,
3887 uint32_t channelMask,
3888 int frameCount,
3889 const sp<IMemory>& sharedBuffer,
3890 int sessionId) {
3891 if (!client->reserveTimedTrack())
3892 return NULL;
3893
Glenn Kastena0356762012-03-19 10:38:51 -07003894 return new TimedTrack(
John Grossman4ff14ba2012-02-08 16:37:41 -08003895 thread, client, streamType, sampleRate, format, channelMask, frameCount,
3896 sharedBuffer, sessionId);
John Grossman4ff14ba2012-02-08 16:37:41 -08003897}
3898
3899AudioFlinger::PlaybackThread::TimedTrack::TimedTrack(
Glenn Kasten9eaa5572012-01-20 13:32:16 -08003900 PlaybackThread *thread,
John Grossman4ff14ba2012-02-08 16:37:41 -08003901 const sp<Client>& client,
3902 audio_stream_type_t streamType,
3903 uint32_t sampleRate,
3904 audio_format_t format,
3905 uint32_t channelMask,
3906 int frameCount,
3907 const sp<IMemory>& sharedBuffer,
3908 int sessionId)
3909 : Track(thread, client, streamType, sampleRate, format, channelMask,
Glenn Kasten73d22752012-03-19 13:38:30 -07003910 frameCount, sharedBuffer, sessionId, IAudioFlinger::TRACK_TIMED),
John Grossman9fbdee12012-03-26 17:51:46 -07003911 mQueueHeadInFlight(false),
3912 mTrimQueueHeadOnRelease(false),
John Grossman1c345192012-03-27 14:00:17 -07003913 mFramesPendingInQueue(0),
John Grossman4ff14ba2012-02-08 16:37:41 -08003914 mTimedSilenceBuffer(NULL),
3915 mTimedSilenceBufferSize(0),
3916 mTimedAudioOutputOnTime(false),
3917 mMediaTimeTransformValid(false)
3918{
3919 LocalClock lc;
3920 mLocalTimeFreq = lc.getLocalFreq();
3921
3922 mLocalTimeToSampleTransform.a_zero = 0;
3923 mLocalTimeToSampleTransform.b_zero = 0;
3924 mLocalTimeToSampleTransform.a_to_b_numer = sampleRate;
3925 mLocalTimeToSampleTransform.a_to_b_denom = mLocalTimeFreq;
3926 LinearTransform::reduce(&mLocalTimeToSampleTransform.a_to_b_numer,
3927 &mLocalTimeToSampleTransform.a_to_b_denom);
John Grossman9fbdee12012-03-26 17:51:46 -07003928
3929 mMediaTimeToSampleTransform.a_zero = 0;
3930 mMediaTimeToSampleTransform.b_zero = 0;
3931 mMediaTimeToSampleTransform.a_to_b_numer = sampleRate;
3932 mMediaTimeToSampleTransform.a_to_b_denom = 1000000;
3933 LinearTransform::reduce(&mMediaTimeToSampleTransform.a_to_b_numer,
3934 &mMediaTimeToSampleTransform.a_to_b_denom);
John Grossman4ff14ba2012-02-08 16:37:41 -08003935}
3936
3937AudioFlinger::PlaybackThread::TimedTrack::~TimedTrack() {
3938 mClient->releaseTimedTrack();
3939 delete [] mTimedSilenceBuffer;
3940}
3941
3942status_t AudioFlinger::PlaybackThread::TimedTrack::allocateTimedBuffer(
3943 size_t size, sp<IMemory>* buffer) {
3944
3945 Mutex::Autolock _l(mTimedBufferQueueLock);
3946
3947 trimTimedBufferQueue_l();
3948
3949 // lazily initialize the shared memory heap for timed buffers
3950 if (mTimedMemoryDealer == NULL) {
3951 const int kTimedBufferHeapSize = 512 << 10;
3952
3953 mTimedMemoryDealer = new MemoryDealer(kTimedBufferHeapSize,
3954 "AudioFlingerTimed");
3955 if (mTimedMemoryDealer == NULL)
3956 return NO_MEMORY;
3957 }
3958
3959 sp<IMemory> newBuffer = mTimedMemoryDealer->allocate(size);
3960 if (newBuffer == NULL) {
3961 newBuffer = mTimedMemoryDealer->allocate(size);
3962 if (newBuffer == NULL)
3963 return NO_MEMORY;
3964 }
3965
3966 *buffer = newBuffer;
3967 return NO_ERROR;
3968}
3969
3970// caller must hold mTimedBufferQueueLock
3971void AudioFlinger::PlaybackThread::TimedTrack::trimTimedBufferQueue_l() {
3972 int64_t mediaTimeNow;
3973 {
3974 Mutex::Autolock mttLock(mMediaTimeTransformLock);
3975 if (!mMediaTimeTransformValid)
3976 return;
3977
3978 int64_t targetTimeNow;
3979 status_t res = (mMediaTimeTransformTarget == TimedAudioTrack::COMMON_TIME)
3980 ? mCCHelper.getCommonTime(&targetTimeNow)
3981 : mCCHelper.getLocalTime(&targetTimeNow);
3982
3983 if (OK != res)
3984 return;
3985
3986 if (!mMediaTimeTransform.doReverseTransform(targetTimeNow,
3987 &mediaTimeNow)) {
3988 return;
3989 }
3990 }
3991
John Grossman1c345192012-03-27 14:00:17 -07003992 size_t trimEnd;
3993 for (trimEnd = 0; trimEnd < mTimedBufferQueue.size(); trimEnd++) {
3994 int64_t frameCount = mTimedBufferQueue[trimEnd].buffer()->size()
John Grossman9fbdee12012-03-26 17:51:46 -07003995 / mCblk->frameSize;
3996 int64_t bufEnd;
3997
3998 if (!mMediaTimeToSampleTransform.doReverseTransform(frameCount,
3999 &bufEnd)) {
4000 ALOGE("Failed to convert frame count of %lld to media time duration"
4001 " (scale factor %d/%u) in %s", frameCount,
4002 mMediaTimeToSampleTransform.a_to_b_numer,
4003 mMediaTimeToSampleTransform.a_to_b_denom,
4004 __PRETTY_FUNCTION__);
John Grossman4ff14ba2012-02-08 16:37:41 -08004005 break;
John Grossman9fbdee12012-03-26 17:51:46 -07004006 }
John Grossman1c345192012-03-27 14:00:17 -07004007 bufEnd += mTimedBufferQueue[trimEnd].pts();
John Grossman9fbdee12012-03-26 17:51:46 -07004008
4009 if (bufEnd > mediaTimeNow)
4010 break;
4011
4012 // Is the buffer we want to use in the middle of a mix operation right
4013 // now? If so, don't actually trim it. Just wait for the releaseBuffer
4014 // from the mixer which should be coming back shortly.
John Grossman1c345192012-03-27 14:00:17 -07004015 if (!trimEnd && mQueueHeadInFlight) {
John Grossman9fbdee12012-03-26 17:51:46 -07004016 mTrimQueueHeadOnRelease = true;
4017 }
John Grossman4ff14ba2012-02-08 16:37:41 -08004018 }
4019
John Grossman9fbdee12012-03-26 17:51:46 -07004020 size_t trimStart = mTrimQueueHeadOnRelease ? 1 : 0;
John Grossman1c345192012-03-27 14:00:17 -07004021 if (trimStart < trimEnd) {
4022 // Update the bookkeeping for framesReady()
4023 for (size_t i = trimStart; i < trimEnd; ++i) {
4024 updateFramesPendingAfterTrim_l(mTimedBufferQueue[i], "trim");
4025 }
4026
4027 // Now actually remove the buffers from the queue.
4028 mTimedBufferQueue.removeItemsAt(trimStart, trimEnd);
John Grossman4ff14ba2012-02-08 16:37:41 -08004029 }
4030}
4031
John Grossman1c345192012-03-27 14:00:17 -07004032void AudioFlinger::PlaybackThread::TimedTrack::trimTimedBufferQueueHead_l(
4033 const char* logTag) {
John Grossmand3030da2012-04-12 11:56:36 -07004034 ALOG_ASSERT(mTimedBufferQueue.size() > 0,
4035 "%s called (reason \"%s\"), but timed buffer queue has no"
4036 " elements to trim.", __FUNCTION__, logTag);
John Grossman1c345192012-03-27 14:00:17 -07004037
4038 updateFramesPendingAfterTrim_l(mTimedBufferQueue[0], logTag);
4039 mTimedBufferQueue.removeAt(0);
4040}
4041
4042void AudioFlinger::PlaybackThread::TimedTrack::updateFramesPendingAfterTrim_l(
4043 const TimedBuffer& buf,
4044 const char* logTag) {
4045 uint32_t bufBytes = buf.buffer()->size();
4046 uint32_t consumedAlready = buf.position();
4047
Eric Laurentb388e532012-04-14 13:32:48 -07004048 ALOG_ASSERT(consumedAlready <= bufBytes,
John Grossmand3030da2012-04-12 11:56:36 -07004049 "Bad bookkeeping while updating frames pending. Timed buffer is"
4050 " only %u bytes long, but claims to have consumed %u"
4051 " bytes. (update reason: \"%s\")",
Eric Laurentb388e532012-04-14 13:32:48 -07004052 bufBytes, consumedAlready, logTag);
John Grossman1c345192012-03-27 14:00:17 -07004053
4054 uint32_t bufFrames = (bufBytes - consumedAlready) / mCblk->frameSize;
John Grossmand3030da2012-04-12 11:56:36 -07004055 ALOG_ASSERT(mFramesPendingInQueue >= bufFrames,
4056 "Bad bookkeeping while updating frames pending. Should have at"
4057 " least %u queued frames, but we think we have only %u. (update"
4058 " reason: \"%s\")",
4059 bufFrames, mFramesPendingInQueue, logTag);
John Grossman1c345192012-03-27 14:00:17 -07004060
4061 mFramesPendingInQueue -= bufFrames;
4062}
4063
John Grossman4ff14ba2012-02-08 16:37:41 -08004064status_t AudioFlinger::PlaybackThread::TimedTrack::queueTimedBuffer(
4065 const sp<IMemory>& buffer, int64_t pts) {
4066
4067 {
4068 Mutex::Autolock mttLock(mMediaTimeTransformLock);
4069 if (!mMediaTimeTransformValid)
4070 return INVALID_OPERATION;
4071 }
4072
4073 Mutex::Autolock _l(mTimedBufferQueueLock);
4074
John Grossman1c345192012-03-27 14:00:17 -07004075 uint32_t bufFrames = buffer->size() / mCblk->frameSize;
4076 mFramesPendingInQueue += bufFrames;
John Grossman4ff14ba2012-02-08 16:37:41 -08004077 mTimedBufferQueue.add(TimedBuffer(buffer, pts));
4078
4079 return NO_ERROR;
4080}
4081
4082status_t AudioFlinger::PlaybackThread::TimedTrack::setMediaTimeTransform(
4083 const LinearTransform& xform, TimedAudioTrack::TargetTimeline target) {
4084
John Grossman1c345192012-03-27 14:00:17 -07004085 ALOGVV("setMediaTimeTransform az=%lld bz=%lld n=%d d=%u tgt=%d",
4086 xform.a_zero, xform.b_zero, xform.a_to_b_numer, xform.a_to_b_denom,
4087 target);
John Grossman4ff14ba2012-02-08 16:37:41 -08004088
4089 if (!(target == TimedAudioTrack::LOCAL_TIME ||
4090 target == TimedAudioTrack::COMMON_TIME)) {
4091 return BAD_VALUE;
4092 }
4093
4094 Mutex::Autolock lock(mMediaTimeTransformLock);
4095 mMediaTimeTransform = xform;
4096 mMediaTimeTransformTarget = target;
4097 mMediaTimeTransformValid = true;
4098
4099 return NO_ERROR;
4100}
4101
4102#define min(a, b) ((a) < (b) ? (a) : (b))
4103
4104// implementation of getNextBuffer for tracks whose buffers have timestamps
4105status_t AudioFlinger::PlaybackThread::TimedTrack::getNextBuffer(
4106 AudioBufferProvider::Buffer* buffer, int64_t pts)
4107{
4108 if (pts == AudioBufferProvider::kInvalidPTS) {
4109 buffer->raw = 0;
4110 buffer->frameCount = 0;
4111 return INVALID_OPERATION;
4112 }
4113
John Grossman4ff14ba2012-02-08 16:37:41 -08004114 Mutex::Autolock _l(mTimedBufferQueueLock);
4115
John Grossman9fbdee12012-03-26 17:51:46 -07004116 ALOG_ASSERT(!mQueueHeadInFlight,
4117 "getNextBuffer called without releaseBuffer!");
4118
John Grossman4ff14ba2012-02-08 16:37:41 -08004119 while (true) {
4120
4121 // if we have no timed buffers, then fail
4122 if (mTimedBufferQueue.isEmpty()) {
4123 buffer->raw = 0;
4124 buffer->frameCount = 0;
4125 return NOT_ENOUGH_DATA;
4126 }
4127
4128 TimedBuffer& head = mTimedBufferQueue.editItemAt(0);
4129
4130 // calculate the PTS of the head of the timed buffer queue expressed in
4131 // local time
4132 int64_t headLocalPTS;
4133 {
4134 Mutex::Autolock mttLock(mMediaTimeTransformLock);
4135
Glenn Kasten5798d4e2012-03-08 12:18:35 -08004136 ALOG_ASSERT(mMediaTimeTransformValid, "media time transform invalid");
John Grossman4ff14ba2012-02-08 16:37:41 -08004137
4138 if (mMediaTimeTransform.a_to_b_denom == 0) {
4139 // the transform represents a pause, so yield silence
John Grossman9fbdee12012-03-26 17:51:46 -07004140 timedYieldSilence_l(buffer->frameCount, buffer);
John Grossman4ff14ba2012-02-08 16:37:41 -08004141 return NO_ERROR;
4142 }
4143
4144 int64_t transformedPTS;
4145 if (!mMediaTimeTransform.doForwardTransform(head.pts(),
4146 &transformedPTS)) {
4147 // the transform failed. this shouldn't happen, but if it does
4148 // then just drop this buffer
4149 ALOGW("timedGetNextBuffer transform failed");
4150 buffer->raw = 0;
4151 buffer->frameCount = 0;
John Grossman1c345192012-03-27 14:00:17 -07004152 trimTimedBufferQueueHead_l("getNextBuffer; no transform");
John Grossman4ff14ba2012-02-08 16:37:41 -08004153 return NO_ERROR;
4154 }
4155
4156 if (mMediaTimeTransformTarget == TimedAudioTrack::COMMON_TIME) {
4157 if (OK != mCCHelper.commonTimeToLocalTime(transformedPTS,
4158 &headLocalPTS)) {
4159 buffer->raw = 0;
4160 buffer->frameCount = 0;
4161 return INVALID_OPERATION;
4162 }
4163 } else {
4164 headLocalPTS = transformedPTS;
4165 }
4166 }
4167
4168 // adjust the head buffer's PTS to reflect the portion of the head buffer
4169 // that has already been consumed
4170 int64_t effectivePTS = headLocalPTS +
4171 ((head.position() / mCblk->frameSize) * mLocalTimeFreq / sampleRate());
4172
4173 // Calculate the delta in samples between the head of the input buffer
4174 // queue and the start of the next output buffer that will be written.
4175 // If the transformation fails because of over or underflow, it means
4176 // that the sample's position in the output stream is so far out of
4177 // whack that it should just be dropped.
4178 int64_t sampleDelta;
4179 if (llabs(effectivePTS - pts) >= (static_cast<int64_t>(1) << 31)) {
4180 ALOGV("*** head buffer is too far from PTS: dropped buffer");
John Grossman1c345192012-03-27 14:00:17 -07004181 trimTimedBufferQueueHead_l("getNextBuffer, buf pts too far from"
4182 " mix");
John Grossman4ff14ba2012-02-08 16:37:41 -08004183 continue;
4184 }
4185 if (!mLocalTimeToSampleTransform.doForwardTransform(
4186 (effectivePTS - pts) << 32, &sampleDelta)) {
John Grossmand3030da2012-04-12 11:56:36 -07004187 ALOGV("*** too late during sample rate transform: dropped buffer");
John Grossman1c345192012-03-27 14:00:17 -07004188 trimTimedBufferQueueHead_l("getNextBuffer, bad local to sample");
John Grossman4ff14ba2012-02-08 16:37:41 -08004189 continue;
4190 }
4191
John Grossman1c345192012-03-27 14:00:17 -07004192 ALOGVV("*** getNextBuffer head.pts=%lld head.pos=%d pts=%lld"
4193 " sampleDelta=[%d.%08x]",
4194 head.pts(), head.position(), pts,
4195 static_cast<int32_t>((sampleDelta >= 0 ? 0 : 1)
4196 + (sampleDelta >> 32)),
4197 static_cast<uint32_t>(sampleDelta & 0xFFFFFFFF));
John Grossman4ff14ba2012-02-08 16:37:41 -08004198
4199 // if the delta between the ideal placement for the next input sample and
4200 // the current output position is within this threshold, then we will
4201 // concatenate the next input samples to the previous output
4202 const int64_t kSampleContinuityThreshold =
4203 (static_cast<int64_t>(sampleRate()) << 32) / 10;
4204
4205 // if this is the first buffer of audio that we're emitting from this track
4206 // then it should be almost exactly on time.
4207 const int64_t kSampleStartupThreshold = 1LL << 32;
4208
4209 if ((mTimedAudioOutputOnTime && llabs(sampleDelta) <= kSampleContinuityThreshold) ||
4210 (!mTimedAudioOutputOnTime && llabs(sampleDelta) <= kSampleStartupThreshold)) {
4211 // the next input is close enough to being on time, so concatenate it
4212 // with the last output
John Grossman9fbdee12012-03-26 17:51:46 -07004213 timedYieldSamples_l(buffer);
John Grossman4ff14ba2012-02-08 16:37:41 -08004214
John Grossman1c345192012-03-27 14:00:17 -07004215 ALOGVV("*** on time: head.pos=%d frameCount=%u",
4216 head.position(), buffer->frameCount);
John Grossman4ff14ba2012-02-08 16:37:41 -08004217 return NO_ERROR;
4218 } else if (sampleDelta > 0) {
4219 // the gap between the current output position and the proper start of
4220 // the next input sample is too big, so fill it with silence
4221 uint32_t framesUntilNextInput = (sampleDelta + 0x80000000) >> 32;
4222
John Grossman9fbdee12012-03-26 17:51:46 -07004223 timedYieldSilence_l(framesUntilNextInput, buffer);
John Grossman4ff14ba2012-02-08 16:37:41 -08004224 ALOGV("*** silence: frameCount=%u", buffer->frameCount);
4225 return NO_ERROR;
4226 } else {
4227 // the next input sample is late
4228 uint32_t lateFrames = static_cast<uint32_t>(-((sampleDelta + 0x80000000) >> 32));
4229 size_t onTimeSamplePosition =
4230 head.position() + lateFrames * mCblk->frameSize;
4231
4232 if (onTimeSamplePosition > head.buffer()->size()) {
4233 // all the remaining samples in the head are too late, so
4234 // drop it and move on
4235 ALOGV("*** too late: dropped buffer");
John Grossman1c345192012-03-27 14:00:17 -07004236 trimTimedBufferQueueHead_l("getNextBuffer, dropped late buffer");
John Grossman4ff14ba2012-02-08 16:37:41 -08004237 continue;
4238 } else {
4239 // skip over the late samples
4240 head.setPosition(onTimeSamplePosition);
4241
4242 // yield the available samples
John Grossman9fbdee12012-03-26 17:51:46 -07004243 timedYieldSamples_l(buffer);
John Grossman4ff14ba2012-02-08 16:37:41 -08004244
4245 ALOGV("*** late: head.pos=%d frameCount=%u", head.position(), buffer->frameCount);
4246 return NO_ERROR;
4247 }
4248 }
4249 }
4250}
4251
4252// Yield samples from the timed buffer queue head up to the given output
4253// buffer's capacity.
4254//
4255// Caller must hold mTimedBufferQueueLock
John Grossman9fbdee12012-03-26 17:51:46 -07004256void AudioFlinger::PlaybackThread::TimedTrack::timedYieldSamples_l(
John Grossman4ff14ba2012-02-08 16:37:41 -08004257 AudioBufferProvider::Buffer* buffer) {
4258
4259 const TimedBuffer& head = mTimedBufferQueue[0];
4260
4261 buffer->raw = (static_cast<uint8_t*>(head.buffer()->pointer()) +
4262 head.position());
4263
4264 uint32_t framesLeftInHead = ((head.buffer()->size() - head.position()) /
4265 mCblk->frameSize);
4266 size_t framesRequested = buffer->frameCount;
4267 buffer->frameCount = min(framesLeftInHead, framesRequested);
4268
John Grossman9fbdee12012-03-26 17:51:46 -07004269 mQueueHeadInFlight = true;
John Grossman4ff14ba2012-02-08 16:37:41 -08004270 mTimedAudioOutputOnTime = true;
4271}
4272
4273// Yield samples of silence up to the given output buffer's capacity
4274//
4275// Caller must hold mTimedBufferQueueLock
John Grossman9fbdee12012-03-26 17:51:46 -07004276void AudioFlinger::PlaybackThread::TimedTrack::timedYieldSilence_l(
John Grossman4ff14ba2012-02-08 16:37:41 -08004277 uint32_t numFrames, AudioBufferProvider::Buffer* buffer) {
4278
4279 // lazily allocate a buffer filled with silence
4280 if (mTimedSilenceBufferSize < numFrames * mCblk->frameSize) {
4281 delete [] mTimedSilenceBuffer;
4282 mTimedSilenceBufferSize = numFrames * mCblk->frameSize;
4283 mTimedSilenceBuffer = new uint8_t[mTimedSilenceBufferSize];
4284 memset(mTimedSilenceBuffer, 0, mTimedSilenceBufferSize);
4285 }
4286
4287 buffer->raw = mTimedSilenceBuffer;
4288 size_t framesRequested = buffer->frameCount;
4289 buffer->frameCount = min(numFrames, framesRequested);
4290
4291 mTimedAudioOutputOnTime = false;
4292}
4293
Glenn Kasten01c4ebf2012-02-22 10:47:35 -08004294// AudioBufferProvider interface
John Grossman4ff14ba2012-02-08 16:37:41 -08004295void AudioFlinger::PlaybackThread::TimedTrack::releaseBuffer(
4296 AudioBufferProvider::Buffer* buffer) {
4297
4298 Mutex::Autolock _l(mTimedBufferQueueLock);
4299
John Grossmanfe5b3ba2012-02-12 17:51:21 -08004300 // If the buffer which was just released is part of the buffer at the head
4301 // of the queue, be sure to update the amt of the buffer which has been
4302 // consumed. If the buffer being returned is not part of the head of the
4303 // queue, its either because the buffer is part of the silence buffer, or
4304 // because the head of the timed queue was trimmed after the mixer called
4305 // getNextBuffer but before the mixer called releaseBuffer.
John Grossman9fbdee12012-03-26 17:51:46 -07004306 if (buffer->raw == mTimedSilenceBuffer) {
4307 ALOG_ASSERT(!mQueueHeadInFlight,
4308 "Queue head in flight during release of silence buffer!");
4309 goto done;
4310 }
4311
4312 ALOG_ASSERT(mQueueHeadInFlight,
4313 "TimedTrack::releaseBuffer of non-silence buffer, but no queue"
4314 " head in flight.");
4315
4316 if (mTimedBufferQueue.size()) {
John Grossman4ff14ba2012-02-08 16:37:41 -08004317 TimedBuffer& head = mTimedBufferQueue.editItemAt(0);
John Grossmanfe5b3ba2012-02-12 17:51:21 -08004318
4319 void* start = head.buffer()->pointer();
John Grossman9fbdee12012-03-26 17:51:46 -07004320 void* end = reinterpret_cast<void*>(
4321 reinterpret_cast<uint8_t*>(head.buffer()->pointer())
4322 + head.buffer()->size());
John Grossmanfe5b3ba2012-02-12 17:51:21 -08004323
John Grossman9fbdee12012-03-26 17:51:46 -07004324 ALOG_ASSERT((buffer->raw >= start) && (buffer->raw < end),
4325 "released buffer not within the head of the timed buffer"
4326 " queue; qHead = [%p, %p], released buffer = %p",
4327 start, end, buffer->raw);
4328
4329 head.setPosition(head.position() +
4330 (buffer->frameCount * mCblk->frameSize));
4331 mQueueHeadInFlight = false;
4332
John Grossman1c345192012-03-27 14:00:17 -07004333 ALOG_ASSERT(mFramesPendingInQueue >= buffer->frameCount,
4334 "Bad bookkeeping during releaseBuffer! Should have at"
4335 " least %u queued frames, but we think we have only %u",
4336 buffer->frameCount, mFramesPendingInQueue);
4337
4338 mFramesPendingInQueue -= buffer->frameCount;
4339
John Grossman9fbdee12012-03-26 17:51:46 -07004340 if ((static_cast<size_t>(head.position()) >= head.buffer()->size())
4341 || mTrimQueueHeadOnRelease) {
John Grossman1c345192012-03-27 14:00:17 -07004342 trimTimedBufferQueueHead_l("releaseBuffer");
John Grossman9fbdee12012-03-26 17:51:46 -07004343 mTrimQueueHeadOnRelease = false;
John Grossman4ff14ba2012-02-08 16:37:41 -08004344 }
John Grossman9fbdee12012-03-26 17:51:46 -07004345 } else {
4346 LOG_FATAL("TimedTrack::releaseBuffer of non-silence buffer with no"
4347 " buffers in the timed buffer queue");
John Grossman4ff14ba2012-02-08 16:37:41 -08004348 }
4349
John Grossman9fbdee12012-03-26 17:51:46 -07004350done:
John Grossman4ff14ba2012-02-08 16:37:41 -08004351 buffer->raw = 0;
4352 buffer->frameCount = 0;
4353}
4354
4355uint32_t AudioFlinger::PlaybackThread::TimedTrack::framesReady() const {
4356 Mutex::Autolock _l(mTimedBufferQueueLock);
John Grossman1c345192012-03-27 14:00:17 -07004357 return mFramesPendingInQueue;
John Grossman4ff14ba2012-02-08 16:37:41 -08004358}
4359
4360AudioFlinger::PlaybackThread::TimedTrack::TimedBuffer::TimedBuffer()
4361 : mPTS(0), mPosition(0) {}
4362
4363AudioFlinger::PlaybackThread::TimedTrack::TimedBuffer::TimedBuffer(
4364 const sp<IMemory>& buffer, int64_t pts)
4365 : mBuffer(buffer), mPTS(pts), mPosition(0) {}
4366
Mathias Agopian65ab4712010-07-14 17:59:35 -07004367// ----------------------------------------------------------------------------
4368
4369// RecordTrack constructor must be called with AudioFlinger::mLock held
4370AudioFlinger::RecordThread::RecordTrack::RecordTrack(
Glenn Kasten9eaa5572012-01-20 13:32:16 -08004371 RecordThread *thread,
Mathias Agopian65ab4712010-07-14 17:59:35 -07004372 const sp<Client>& client,
4373 uint32_t sampleRate,
Glenn Kasten58f30212012-01-12 12:27:51 -08004374 audio_format_t format,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07004375 uint32_t channelMask,
Mathias Agopian65ab4712010-07-14 17:59:35 -07004376 int frameCount,
Mathias Agopian65ab4712010-07-14 17:59:35 -07004377 int sessionId)
4378 : TrackBase(thread, client, sampleRate, format,
Glenn Kasten5cf034d2012-02-21 10:35:56 -08004379 channelMask, frameCount, 0 /*sharedBuffer*/, sessionId),
Mathias Agopian65ab4712010-07-14 17:59:35 -07004380 mOverflow(false)
4381{
4382 if (mCblk != NULL) {
Glenn Kastene53b9ea2012-03-12 16:29:55 -07004383 ALOGV("RecordTrack constructor, size %d", (int)mBufferEnd - (int)mBuffer);
4384 if (format == AUDIO_FORMAT_PCM_16_BIT) {
4385 mCblk->frameSize = mChannelCount * sizeof(int16_t);
4386 } else if (format == AUDIO_FORMAT_PCM_8_BIT) {
4387 mCblk->frameSize = mChannelCount * sizeof(int8_t);
4388 } else {
4389 mCblk->frameSize = sizeof(int8_t);
4390 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07004391 }
4392}
4393
4394AudioFlinger::RecordThread::RecordTrack::~RecordTrack()
4395{
4396 sp<ThreadBase> thread = mThread.promote();
4397 if (thread != 0) {
4398 AudioSystem::releaseInput(thread->id());
4399 }
4400}
4401
Glenn Kasten01c4ebf2012-02-22 10:47:35 -08004402// AudioBufferProvider interface
John Grossman4ff14ba2012-02-08 16:37:41 -08004403status_t AudioFlinger::RecordThread::RecordTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer, int64_t pts)
Mathias Agopian65ab4712010-07-14 17:59:35 -07004404{
4405 audio_track_cblk_t* cblk = this->cblk();
4406 uint32_t framesAvail;
4407 uint32_t framesReq = buffer->frameCount;
4408
Glenn Kastene53b9ea2012-03-12 16:29:55 -07004409 // Check if last stepServer failed, try to step now
Glenn Kasten5cf034d2012-02-21 10:35:56 -08004410 if (mStepServerFailed) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07004411 if (!step()) goto getNextBuffer_exit;
Steve Block3856b092011-10-20 11:56:00 +01004412 ALOGV("stepServer recovered");
Glenn Kasten5cf034d2012-02-21 10:35:56 -08004413 mStepServerFailed = false;
Mathias Agopian65ab4712010-07-14 17:59:35 -07004414 }
4415
4416 framesAvail = cblk->framesAvailable_l();
4417
Glenn Kastenf6b16782011-12-15 09:51:17 -08004418 if (CC_LIKELY(framesAvail)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07004419 uint32_t s = cblk->server;
4420 uint32_t bufferEnd = cblk->serverBase + cblk->frameCount;
4421
4422 if (framesReq > framesAvail) {
4423 framesReq = framesAvail;
4424 }
Marco Nelissena1472d92012-03-30 14:36:54 -07004425 if (framesReq > bufferEnd - s) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07004426 framesReq = bufferEnd - s;
4427 }
4428
4429 buffer->raw = getBuffer(s, framesReq);
Glenn Kastene0feee32011-12-13 11:53:26 -08004430 if (buffer->raw == NULL) goto getNextBuffer_exit;
Mathias Agopian65ab4712010-07-14 17:59:35 -07004431
4432 buffer->frameCount = framesReq;
4433 return NO_ERROR;
4434 }
4435
4436getNextBuffer_exit:
Glenn Kastene0feee32011-12-13 11:53:26 -08004437 buffer->raw = NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -07004438 buffer->frameCount = 0;
4439 return NOT_ENOUGH_DATA;
4440}
4441
Eric Laurenta011e352012-03-29 15:51:43 -07004442status_t AudioFlinger::RecordThread::RecordTrack::start(pid_t tid,
4443 AudioSystem::sync_event_t event,
4444 int triggerSession)
Mathias Agopian65ab4712010-07-14 17:59:35 -07004445{
4446 sp<ThreadBase> thread = mThread.promote();
4447 if (thread != 0) {
4448 RecordThread *recordThread = (RecordThread *)thread.get();
Eric Laurenta011e352012-03-29 15:51:43 -07004449 return recordThread->start(this, tid, event, triggerSession);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004450 } else {
4451 return BAD_VALUE;
4452 }
4453}
4454
4455void AudioFlinger::RecordThread::RecordTrack::stop()
4456{
4457 sp<ThreadBase> thread = mThread.promote();
4458 if (thread != 0) {
4459 RecordThread *recordThread = (RecordThread *)thread.get();
4460 recordThread->stop(this);
Eric Laurent38ccae22011-03-28 18:37:07 -07004461 TrackBase::reset();
Glenn Kasten17a736c2012-02-14 08:52:15 -08004462 // Force overrun condition to avoid false overrun callback until first data is
Eric Laurent38ccae22011-03-28 18:37:07 -07004463 // read from buffer
4464 android_atomic_or(CBLK_UNDERRUN_ON, &mCblk->flags);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004465 }
4466}
4467
4468void AudioFlinger::RecordThread::RecordTrack::dump(char* buffer, size_t size)
4469{
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07004470 snprintf(buffer, size, " %05d %03u 0x%08x %05d %04u %01d %05u %08x %08x\n",
Glenn Kasten44deb052012-02-05 18:09:08 -08004471 (mClient == 0) ? getpid_cached : mClient->pid(),
Mathias Agopian65ab4712010-07-14 17:59:35 -07004472 mFormat,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07004473 mChannelMask,
Mathias Agopian65ab4712010-07-14 17:59:35 -07004474 mSessionId,
4475 mFrameCount,
4476 mState,
4477 mCblk->sampleRate,
4478 mCblk->server,
4479 mCblk->user);
4480}
4481
4482
4483// ----------------------------------------------------------------------------
4484
4485AudioFlinger::PlaybackThread::OutputTrack::OutputTrack(
Glenn Kasten9eaa5572012-01-20 13:32:16 -08004486 PlaybackThread *playbackThread,
Mathias Agopian65ab4712010-07-14 17:59:35 -07004487 DuplicatingThread *sourceThread,
4488 uint32_t sampleRate,
Glenn Kasten58f30212012-01-12 12:27:51 -08004489 audio_format_t format,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07004490 uint32_t channelMask,
Mathias Agopian65ab4712010-07-14 17:59:35 -07004491 int frameCount)
Glenn Kasten73d22752012-03-19 13:38:30 -07004492 : Track(playbackThread, NULL, AUDIO_STREAM_CNT, sampleRate, format, channelMask, frameCount,
4493 NULL, 0, IAudioFlinger::TRACK_DEFAULT),
Mathias Agopian65ab4712010-07-14 17:59:35 -07004494 mActive(false), mSourceThread(sourceThread)
4495{
4496
Mathias Agopian65ab4712010-07-14 17:59:35 -07004497 if (mCblk != NULL) {
4498 mCblk->flags |= CBLK_DIRECTION_OUT;
4499 mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004500 mOutBuffer.frameCount = 0;
4501 playbackThread->mTracks.add(this);
Steve Block3856b092011-10-20 11:56:00 +01004502 ALOGV("OutputTrack constructor mCblk %p, mBuffer %p, mCblk->buffers %p, " \
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07004503 "mCblk->frameCount %d, mCblk->sampleRate %d, mChannelMask 0x%08x mBufferEnd %p",
4504 mCblk, mBuffer, mCblk->buffers,
4505 mCblk->frameCount, mCblk->sampleRate, mChannelMask, mBufferEnd);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004506 } else {
Steve Block5ff1dd52012-01-05 23:22:43 +00004507 ALOGW("Error creating output track on thread %p", playbackThread);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004508 }
4509}
4510
4511AudioFlinger::PlaybackThread::OutputTrack::~OutputTrack()
4512{
4513 clearBufferQueue();
4514}
4515
Eric Laurenta011e352012-03-29 15:51:43 -07004516status_t AudioFlinger::PlaybackThread::OutputTrack::start(pid_t tid,
4517 AudioSystem::sync_event_t event,
4518 int triggerSession)
Mathias Agopian65ab4712010-07-14 17:59:35 -07004519{
Eric Laurenta011e352012-03-29 15:51:43 -07004520 status_t status = Track::start(tid, event, triggerSession);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004521 if (status != NO_ERROR) {
4522 return status;
4523 }
4524
4525 mActive = true;
4526 mRetryCount = 127;
4527 return status;
4528}
4529
4530void AudioFlinger::PlaybackThread::OutputTrack::stop()
4531{
4532 Track::stop();
4533 clearBufferQueue();
4534 mOutBuffer.frameCount = 0;
4535 mActive = false;
4536}
4537
4538bool AudioFlinger::PlaybackThread::OutputTrack::write(int16_t* data, uint32_t frames)
4539{
4540 Buffer *pInBuffer;
4541 Buffer inBuffer;
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07004542 uint32_t channelCount = mChannelCount;
Mathias Agopian65ab4712010-07-14 17:59:35 -07004543 bool outputBufferFull = false;
4544 inBuffer.frameCount = frames;
4545 inBuffer.i16 = data;
4546
4547 uint32_t waitTimeLeftMs = mSourceThread->waitTimeMs();
4548
4549 if (!mActive && frames != 0) {
Glenn Kasten6dbc1352012-02-02 10:56:47 -08004550 start(0);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004551 sp<ThreadBase> thread = mThread.promote();
4552 if (thread != 0) {
4553 MixerThread *mixerThread = (MixerThread *)thread.get();
4554 if (mCblk->frameCount > frames){
4555 if (mBufferQueue.size() < kMaxOverFlowBuffers) {
4556 uint32_t startFrames = (mCblk->frameCount - frames);
4557 pInBuffer = new Buffer;
4558 pInBuffer->mBuffer = new int16_t[startFrames * channelCount];
4559 pInBuffer->frameCount = startFrames;
4560 pInBuffer->i16 = pInBuffer->mBuffer;
4561 memset(pInBuffer->raw, 0, startFrames * channelCount * sizeof(int16_t));
4562 mBufferQueue.add(pInBuffer);
4563 } else {
Steve Block5ff1dd52012-01-05 23:22:43 +00004564 ALOGW ("OutputTrack::write() %p no more buffers in queue", this);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004565 }
4566 }
4567 }
4568 }
4569
4570 while (waitTimeLeftMs) {
4571 // First write pending buffers, then new data
4572 if (mBufferQueue.size()) {
4573 pInBuffer = mBufferQueue.itemAt(0);
4574 } else {
4575 pInBuffer = &inBuffer;
4576 }
4577
4578 if (pInBuffer->frameCount == 0) {
4579 break;
4580 }
4581
4582 if (mOutBuffer.frameCount == 0) {
4583 mOutBuffer.frameCount = pInBuffer->frameCount;
4584 nsecs_t startTime = systemTime();
Glenn Kasten335787f2012-01-20 17:00:00 -08004585 if (obtainBuffer(&mOutBuffer, waitTimeLeftMs) == (status_t)NO_MORE_BUFFERS) {
Steve Block3856b092011-10-20 11:56:00 +01004586 ALOGV ("OutputTrack::write() %p thread %p no more output buffers", this, mThread.unsafe_get());
Mathias Agopian65ab4712010-07-14 17:59:35 -07004587 outputBufferFull = true;
4588 break;
4589 }
4590 uint32_t waitTimeMs = (uint32_t)ns2ms(systemTime() - startTime);
4591 if (waitTimeLeftMs >= waitTimeMs) {
4592 waitTimeLeftMs -= waitTimeMs;
4593 } else {
4594 waitTimeLeftMs = 0;
4595 }
4596 }
4597
4598 uint32_t outFrames = pInBuffer->frameCount > mOutBuffer.frameCount ? mOutBuffer.frameCount : pInBuffer->frameCount;
4599 memcpy(mOutBuffer.raw, pInBuffer->raw, outFrames * channelCount * sizeof(int16_t));
4600 mCblk->stepUser(outFrames);
4601 pInBuffer->frameCount -= outFrames;
4602 pInBuffer->i16 += outFrames * channelCount;
4603 mOutBuffer.frameCount -= outFrames;
4604 mOutBuffer.i16 += outFrames * channelCount;
4605
4606 if (pInBuffer->frameCount == 0) {
4607 if (mBufferQueue.size()) {
4608 mBufferQueue.removeAt(0);
4609 delete [] pInBuffer->mBuffer;
4610 delete pInBuffer;
Steve Block3856b092011-10-20 11:56:00 +01004611 ALOGV("OutputTrack::write() %p thread %p released overflow buffer %d", this, mThread.unsafe_get(), mBufferQueue.size());
Mathias Agopian65ab4712010-07-14 17:59:35 -07004612 } else {
4613 break;
4614 }
4615 }
4616 }
4617
4618 // If we could not write all frames, allocate a buffer and queue it for next time.
4619 if (inBuffer.frameCount) {
4620 sp<ThreadBase> thread = mThread.promote();
4621 if (thread != 0 && !thread->standby()) {
4622 if (mBufferQueue.size() < kMaxOverFlowBuffers) {
4623 pInBuffer = new Buffer;
4624 pInBuffer->mBuffer = new int16_t[inBuffer.frameCount * channelCount];
4625 pInBuffer->frameCount = inBuffer.frameCount;
4626 pInBuffer->i16 = pInBuffer->mBuffer;
4627 memcpy(pInBuffer->raw, inBuffer.raw, inBuffer.frameCount * channelCount * sizeof(int16_t));
4628 mBufferQueue.add(pInBuffer);
Steve Block3856b092011-10-20 11:56:00 +01004629 ALOGV("OutputTrack::write() %p thread %p adding overflow buffer %d", this, mThread.unsafe_get(), mBufferQueue.size());
Mathias Agopian65ab4712010-07-14 17:59:35 -07004630 } else {
Steve Block5ff1dd52012-01-05 23:22:43 +00004631 ALOGW("OutputTrack::write() %p thread %p no more overflow buffers", mThread.unsafe_get(), this);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004632 }
4633 }
4634 }
4635
4636 // Calling write() with a 0 length buffer, means that no more data will be written:
4637 // If no more buffers are pending, fill output track buffer to make sure it is started
4638 // by output mixer.
4639 if (frames == 0 && mBufferQueue.size() == 0) {
4640 if (mCblk->user < mCblk->frameCount) {
4641 frames = mCblk->frameCount - mCblk->user;
4642 pInBuffer = new Buffer;
4643 pInBuffer->mBuffer = new int16_t[frames * channelCount];
4644 pInBuffer->frameCount = frames;
4645 pInBuffer->i16 = pInBuffer->mBuffer;
4646 memset(pInBuffer->raw, 0, frames * channelCount * sizeof(int16_t));
4647 mBufferQueue.add(pInBuffer);
4648 } else if (mActive) {
4649 stop();
4650 }
4651 }
4652
4653 return outputBufferFull;
4654}
4655
4656status_t AudioFlinger::PlaybackThread::OutputTrack::obtainBuffer(AudioBufferProvider::Buffer* buffer, uint32_t waitTimeMs)
4657{
4658 int active;
4659 status_t result;
4660 audio_track_cblk_t* cblk = mCblk;
4661 uint32_t framesReq = buffer->frameCount;
4662
Steve Block3856b092011-10-20 11:56:00 +01004663// ALOGV("OutputTrack::obtainBuffer user %d, server %d", cblk->user, cblk->server);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004664 buffer->frameCount = 0;
4665
4666 uint32_t framesAvail = cblk->framesAvailable();
4667
4668
4669 if (framesAvail == 0) {
4670 Mutex::Autolock _l(cblk->lock);
4671 goto start_loop_here;
4672 while (framesAvail == 0) {
4673 active = mActive;
Glenn Kastenf6b16782011-12-15 09:51:17 -08004674 if (CC_UNLIKELY(!active)) {
Steve Block3856b092011-10-20 11:56:00 +01004675 ALOGV("Not active and NO_MORE_BUFFERS");
Glenn Kasten335787f2012-01-20 17:00:00 -08004676 return NO_MORE_BUFFERS;
Mathias Agopian65ab4712010-07-14 17:59:35 -07004677 }
4678 result = cblk->cv.waitRelative(cblk->lock, milliseconds(waitTimeMs));
4679 if (result != NO_ERROR) {
Glenn Kasten335787f2012-01-20 17:00:00 -08004680 return NO_MORE_BUFFERS;
Mathias Agopian65ab4712010-07-14 17:59:35 -07004681 }
4682 // read the server count again
4683 start_loop_here:
4684 framesAvail = cblk->framesAvailable_l();
4685 }
4686 }
4687
4688// if (framesAvail < framesReq) {
Glenn Kasten335787f2012-01-20 17:00:00 -08004689// return NO_MORE_BUFFERS;
Mathias Agopian65ab4712010-07-14 17:59:35 -07004690// }
4691
4692 if (framesReq > framesAvail) {
4693 framesReq = framesAvail;
4694 }
4695
4696 uint32_t u = cblk->user;
4697 uint32_t bufferEnd = cblk->userBase + cblk->frameCount;
4698
Marco Nelissena1472d92012-03-30 14:36:54 -07004699 if (framesReq > bufferEnd - u) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07004700 framesReq = bufferEnd - u;
4701 }
4702
4703 buffer->frameCount = framesReq;
4704 buffer->raw = (void *)cblk->buffer(u);
4705 return NO_ERROR;
4706}
4707
4708
4709void AudioFlinger::PlaybackThread::OutputTrack::clearBufferQueue()
4710{
4711 size_t size = mBufferQueue.size();
Mathias Agopian65ab4712010-07-14 17:59:35 -07004712
4713 for (size_t i = 0; i < size; i++) {
Glenn Kastena1117922012-01-26 10:53:32 -08004714 Buffer *pBuffer = mBufferQueue.itemAt(i);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004715 delete [] pBuffer->mBuffer;
4716 delete pBuffer;
4717 }
4718 mBufferQueue.clear();
4719}
4720
4721// ----------------------------------------------------------------------------
4722
4723AudioFlinger::Client::Client(const sp<AudioFlinger>& audioFlinger, pid_t pid)
4724 : RefBase(),
4725 mAudioFlinger(audioFlinger),
Glenn Kasten99e53b82012-01-19 08:59:58 -08004726 // 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 -07004727 mMemoryDealer(new MemoryDealer(1024*1024, "AudioFlinger::Client")),
John Grossman4ff14ba2012-02-08 16:37:41 -08004728 mPid(pid),
4729 mTimedTrackCount(0)
Mathias Agopian65ab4712010-07-14 17:59:35 -07004730{
4731 // 1 MB of address space is good for 32 tracks, 8 buffers each, 4 KB/buffer
4732}
4733
4734// Client destructor must be called with AudioFlinger::mLock held
4735AudioFlinger::Client::~Client()
4736{
4737 mAudioFlinger->removeClient_l(mPid);
4738}
4739
Glenn Kasten435dbe62012-01-30 10:15:48 -08004740sp<MemoryDealer> AudioFlinger::Client::heap() const
Mathias Agopian65ab4712010-07-14 17:59:35 -07004741{
4742 return mMemoryDealer;
4743}
4744
John Grossman4ff14ba2012-02-08 16:37:41 -08004745// Reserve one of the limited slots for a timed audio track associated
4746// with this client
4747bool AudioFlinger::Client::reserveTimedTrack()
4748{
4749 const int kMaxTimedTracksPerClient = 4;
4750
4751 Mutex::Autolock _l(mTimedTrackLock);
4752
4753 if (mTimedTrackCount >= kMaxTimedTracksPerClient) {
4754 ALOGW("can not create timed track - pid %d has exceeded the limit",
4755 mPid);
4756 return false;
4757 }
4758
4759 mTimedTrackCount++;
4760 return true;
4761}
4762
4763// Release a slot for a timed audio track
4764void AudioFlinger::Client::releaseTimedTrack()
4765{
4766 Mutex::Autolock _l(mTimedTrackLock);
4767 mTimedTrackCount--;
4768}
4769
Mathias Agopian65ab4712010-07-14 17:59:35 -07004770// ----------------------------------------------------------------------------
4771
4772AudioFlinger::NotificationClient::NotificationClient(const sp<AudioFlinger>& audioFlinger,
4773 const sp<IAudioFlingerClient>& client,
4774 pid_t pid)
Glenn Kasten84afa3b2012-01-25 15:28:08 -08004775 : mAudioFlinger(audioFlinger), mPid(pid), mAudioFlingerClient(client)
Mathias Agopian65ab4712010-07-14 17:59:35 -07004776{
4777}
4778
4779AudioFlinger::NotificationClient::~NotificationClient()
4780{
Mathias Agopian65ab4712010-07-14 17:59:35 -07004781}
4782
4783void AudioFlinger::NotificationClient::binderDied(const wp<IBinder>& who)
4784{
4785 sp<NotificationClient> keep(this);
Glenn Kastena1117922012-01-26 10:53:32 -08004786 mAudioFlinger->removeNotificationClient(mPid);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004787}
4788
4789// ----------------------------------------------------------------------------
4790
4791AudioFlinger::TrackHandle::TrackHandle(const sp<AudioFlinger::PlaybackThread::Track>& track)
4792 : BnAudioTrack(),
4793 mTrack(track)
4794{
4795}
4796
4797AudioFlinger::TrackHandle::~TrackHandle() {
4798 // just stop the track on deletion, associated resources
4799 // will be freed from the main thread once all pending buffers have
4800 // been played. Unless it's not in the active track list, in which
4801 // case we free everything now...
4802 mTrack->destroy();
4803}
4804
Glenn Kasten90716c52012-01-26 13:40:12 -08004805sp<IMemory> AudioFlinger::TrackHandle::getCblk() const {
4806 return mTrack->getCblk();
4807}
4808
Glenn Kasten6dbc1352012-02-02 10:56:47 -08004809status_t AudioFlinger::TrackHandle::start(pid_t tid) {
4810 return mTrack->start(tid);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004811}
4812
4813void AudioFlinger::TrackHandle::stop() {
4814 mTrack->stop();
4815}
4816
4817void AudioFlinger::TrackHandle::flush() {
4818 mTrack->flush();
4819}
4820
4821void AudioFlinger::TrackHandle::mute(bool e) {
4822 mTrack->mute(e);
4823}
4824
4825void AudioFlinger::TrackHandle::pause() {
4826 mTrack->pause();
4827}
4828
Mathias Agopian65ab4712010-07-14 17:59:35 -07004829status_t AudioFlinger::TrackHandle::attachAuxEffect(int EffectId)
4830{
4831 return mTrack->attachAuxEffect(EffectId);
4832}
4833
John Grossman4ff14ba2012-02-08 16:37:41 -08004834status_t AudioFlinger::TrackHandle::allocateTimedBuffer(size_t size,
4835 sp<IMemory>* buffer) {
4836 if (!mTrack->isTimedTrack())
4837 return INVALID_OPERATION;
4838
4839 PlaybackThread::TimedTrack* tt =
4840 reinterpret_cast<PlaybackThread::TimedTrack*>(mTrack.get());
4841 return tt->allocateTimedBuffer(size, buffer);
4842}
4843
4844status_t AudioFlinger::TrackHandle::queueTimedBuffer(const sp<IMemory>& buffer,
4845 int64_t pts) {
4846 if (!mTrack->isTimedTrack())
4847 return INVALID_OPERATION;
4848
4849 PlaybackThread::TimedTrack* tt =
4850 reinterpret_cast<PlaybackThread::TimedTrack*>(mTrack.get());
4851 return tt->queueTimedBuffer(buffer, pts);
4852}
4853
4854status_t AudioFlinger::TrackHandle::setMediaTimeTransform(
4855 const LinearTransform& xform, int target) {
4856
4857 if (!mTrack->isTimedTrack())
4858 return INVALID_OPERATION;
4859
4860 PlaybackThread::TimedTrack* tt =
4861 reinterpret_cast<PlaybackThread::TimedTrack*>(mTrack.get());
4862 return tt->setMediaTimeTransform(
4863 xform, static_cast<TimedAudioTrack::TargetTimeline>(target));
4864}
4865
Mathias Agopian65ab4712010-07-14 17:59:35 -07004866status_t AudioFlinger::TrackHandle::onTransact(
4867 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
4868{
4869 return BnAudioTrack::onTransact(code, data, reply, flags);
4870}
4871
4872// ----------------------------------------------------------------------------
4873
4874sp<IAudioRecord> AudioFlinger::openRecord(
4875 pid_t pid,
Glenn Kasten72ef00d2012-01-17 11:09:42 -08004876 audio_io_handle_t input,
Mathias Agopian65ab4712010-07-14 17:59:35 -07004877 uint32_t sampleRate,
Glenn Kasten58f30212012-01-12 12:27:51 -08004878 audio_format_t format,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07004879 uint32_t channelMask,
Mathias Agopian65ab4712010-07-14 17:59:35 -07004880 int frameCount,
Glenn Kastena075db42012-03-06 11:22:44 -08004881 IAudioFlinger::track_flags_t flags,
Mathias Agopian65ab4712010-07-14 17:59:35 -07004882 int *sessionId,
4883 status_t *status)
4884{
4885 sp<RecordThread::RecordTrack> recordTrack;
4886 sp<RecordHandle> recordHandle;
4887 sp<Client> client;
Mathias Agopian65ab4712010-07-14 17:59:35 -07004888 status_t lStatus;
4889 RecordThread *thread;
4890 size_t inFrameCount;
4891 int lSessionId;
4892
4893 // check calling permissions
4894 if (!recordingAllowed()) {
4895 lStatus = PERMISSION_DENIED;
4896 goto Exit;
4897 }
4898
4899 // add client to list
4900 { // scope for mLock
4901 Mutex::Autolock _l(mLock);
4902 thread = checkRecordThread_l(input);
4903 if (thread == NULL) {
4904 lStatus = BAD_VALUE;
4905 goto Exit;
4906 }
4907
Glenn Kasten98ec94c2012-01-25 14:28:29 -08004908 client = registerPid_l(pid);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004909
4910 // If no audio session id is provided, create one here
Dima Zavinfce7a472011-04-19 22:30:36 -07004911 if (sessionId != NULL && *sessionId != AUDIO_SESSION_OUTPUT_MIX) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07004912 lSessionId = *sessionId;
4913 } else {
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004914 lSessionId = nextUniqueId();
Mathias Agopian65ab4712010-07-14 17:59:35 -07004915 if (sessionId != NULL) {
4916 *sessionId = lSessionId;
4917 }
4918 }
4919 // create new record track. The record track uses one track in mHardwareMixerThread by convention.
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004920 recordTrack = thread->createRecordTrack_l(client,
4921 sampleRate,
4922 format,
4923 channelMask,
4924 frameCount,
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004925 lSessionId,
4926 &lStatus);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004927 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004928 if (lStatus != NO_ERROR) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07004929 // remove local strong reference to Client before deleting the RecordTrack so that the Client
4930 // destructor is called by the TrackBase destructor with mLock held
4931 client.clear();
4932 recordTrack.clear();
Mathias Agopian65ab4712010-07-14 17:59:35 -07004933 goto Exit;
4934 }
4935
4936 // return to handle to client
4937 recordHandle = new RecordHandle(recordTrack);
4938 lStatus = NO_ERROR;
4939
4940Exit:
4941 if (status) {
4942 *status = lStatus;
4943 }
4944 return recordHandle;
4945}
4946
4947// ----------------------------------------------------------------------------
4948
4949AudioFlinger::RecordHandle::RecordHandle(const sp<AudioFlinger::RecordThread::RecordTrack>& recordTrack)
4950 : BnAudioRecord(),
4951 mRecordTrack(recordTrack)
4952{
4953}
4954
4955AudioFlinger::RecordHandle::~RecordHandle() {
4956 stop();
4957}
4958
Glenn Kasten90716c52012-01-26 13:40:12 -08004959sp<IMemory> AudioFlinger::RecordHandle::getCblk() const {
4960 return mRecordTrack->getCblk();
4961}
4962
Eric Laurenta011e352012-03-29 15:51:43 -07004963status_t AudioFlinger::RecordHandle::start(pid_t tid, int event, int triggerSession) {
Steve Block3856b092011-10-20 11:56:00 +01004964 ALOGV("RecordHandle::start()");
Eric Laurenta011e352012-03-29 15:51:43 -07004965 return mRecordTrack->start(tid, (AudioSystem::sync_event_t)event, triggerSession);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004966}
4967
4968void AudioFlinger::RecordHandle::stop() {
Steve Block3856b092011-10-20 11:56:00 +01004969 ALOGV("RecordHandle::stop()");
Mathias Agopian65ab4712010-07-14 17:59:35 -07004970 mRecordTrack->stop();
4971}
4972
Mathias Agopian65ab4712010-07-14 17:59:35 -07004973status_t AudioFlinger::RecordHandle::onTransact(
4974 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
4975{
4976 return BnAudioRecord::onTransact(code, data, reply, flags);
4977}
4978
4979// ----------------------------------------------------------------------------
4980
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004981AudioFlinger::RecordThread::RecordThread(const sp<AudioFlinger>& audioFlinger,
4982 AudioStreamIn *input,
4983 uint32_t sampleRate,
4984 uint32_t channels,
Glenn Kasten72ef00d2012-01-17 11:09:42 -08004985 audio_io_handle_t id,
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004986 uint32_t device) :
Glenn Kasten23bb8be2012-01-26 10:38:26 -08004987 ThreadBase(audioFlinger, id, device, RECORD),
Glenn Kasten84afa3b2012-01-25 15:28:08 -08004988 mInput(input), mTrack(NULL), mResampler(NULL), mRsmpOutBuffer(NULL), mRsmpInBuffer(NULL),
4989 // mRsmpInIndex and mInputBytes set by readInputParameters()
4990 mReqChannelCount(popcount(channels)),
4991 mReqSampleRate(sampleRate)
4992 // mBytesRead is only meaningful while active, and so is cleared in start()
4993 // (but might be better to also clear here for dump?)
Mathias Agopian65ab4712010-07-14 17:59:35 -07004994{
Glenn Kasten480b4682012-02-28 12:30:08 -08004995 snprintf(mName, kNameLength, "AudioIn_%X", id);
Eric Laurentfeb0db62011-07-22 09:04:31 -07004996
Mathias Agopian65ab4712010-07-14 17:59:35 -07004997 readInputParameters();
4998}
4999
5000
5001AudioFlinger::RecordThread::~RecordThread()
5002{
5003 delete[] mRsmpInBuffer;
Glenn Kastene9dd0172012-01-27 18:08:45 -08005004 delete mResampler;
5005 delete[] mRsmpOutBuffer;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005006}
5007
5008void AudioFlinger::RecordThread::onFirstRef()
5009{
Eric Laurentfeb0db62011-07-22 09:04:31 -07005010 run(mName, PRIORITY_URGENT_AUDIO);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005011}
5012
Eric Laurentb8ba0a92011-08-07 16:32:26 -07005013status_t AudioFlinger::RecordThread::readyToRun()
5014{
5015 status_t status = initCheck();
Steve Block5ff1dd52012-01-05 23:22:43 +00005016 ALOGW_IF(status != NO_ERROR,"RecordThread %p could not initialize", this);
Eric Laurentb8ba0a92011-08-07 16:32:26 -07005017 return status;
5018}
5019
Mathias Agopian65ab4712010-07-14 17:59:35 -07005020bool AudioFlinger::RecordThread::threadLoop()
5021{
5022 AudioBufferProvider::Buffer buffer;
5023 sp<RecordTrack> activeTrack;
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005024 Vector< sp<EffectChain> > effectChains;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005025
Eric Laurent44d98482010-09-30 16:12:31 -07005026 nsecs_t lastWarning = 0;
5027
Eric Laurentfeb0db62011-07-22 09:04:31 -07005028 acquireWakeLock();
5029
Mathias Agopian65ab4712010-07-14 17:59:35 -07005030 // start recording
5031 while (!exitPending()) {
5032
5033 processConfigEvents();
5034
5035 { // scope for mLock
5036 Mutex::Autolock _l(mLock);
5037 checkForNewParameters_l();
5038 if (mActiveTrack == 0 && mConfigEvents.isEmpty()) {
5039 if (!mStandby) {
Dima Zavin799a70e2011-04-18 16:57:27 -07005040 mInput->stream->common.standby(&mInput->stream->common);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005041 mStandby = true;
5042 }
5043
5044 if (exitPending()) break;
5045
Eric Laurentfeb0db62011-07-22 09:04:31 -07005046 releaseWakeLock_l();
Steve Block3856b092011-10-20 11:56:00 +01005047 ALOGV("RecordThread: loop stopping");
Mathias Agopian65ab4712010-07-14 17:59:35 -07005048 // go to sleep
5049 mWaitWorkCV.wait(mLock);
Steve Block3856b092011-10-20 11:56:00 +01005050 ALOGV("RecordThread: loop starting");
Eric Laurentfeb0db62011-07-22 09:04:31 -07005051 acquireWakeLock_l();
Mathias Agopian65ab4712010-07-14 17:59:35 -07005052 continue;
5053 }
5054 if (mActiveTrack != 0) {
5055 if (mActiveTrack->mState == TrackBase::PAUSING) {
5056 if (!mStandby) {
Dima Zavin799a70e2011-04-18 16:57:27 -07005057 mInput->stream->common.standby(&mInput->stream->common);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005058 mStandby = true;
5059 }
5060 mActiveTrack.clear();
5061 mStartStopCond.broadcast();
5062 } else if (mActiveTrack->mState == TrackBase::RESUMING) {
5063 if (mReqChannelCount != mActiveTrack->channelCount()) {
5064 mActiveTrack.clear();
5065 mStartStopCond.broadcast();
5066 } else if (mBytesRead != 0) {
5067 // record start succeeds only if first read from audio input
5068 // succeeds
5069 if (mBytesRead > 0) {
5070 mActiveTrack->mState = TrackBase::ACTIVE;
5071 } else {
5072 mActiveTrack.clear();
5073 }
5074 mStartStopCond.broadcast();
5075 }
5076 mStandby = false;
5077 }
5078 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005079 lockEffectChains_l(effectChains);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005080 }
5081
5082 if (mActiveTrack != 0) {
5083 if (mActiveTrack->mState != TrackBase::ACTIVE &&
5084 mActiveTrack->mState != TrackBase::RESUMING) {
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005085 unlockEffectChains(effectChains);
5086 usleep(kRecordThreadSleepUs);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005087 continue;
5088 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005089 for (size_t i = 0; i < effectChains.size(); i ++) {
5090 effectChains[i]->process_l();
5091 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005092
Mathias Agopian65ab4712010-07-14 17:59:35 -07005093 buffer.frameCount = mFrameCount;
Glenn Kasten01c4ebf2012-02-22 10:47:35 -08005094 if (CC_LIKELY(mActiveTrack->getNextBuffer(&buffer) == NO_ERROR)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07005095 size_t framesOut = buffer.frameCount;
Glenn Kastene0feee32011-12-13 11:53:26 -08005096 if (mResampler == NULL) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07005097 // no resampling
5098 while (framesOut) {
5099 size_t framesIn = mFrameCount - mRsmpInIndex;
5100 if (framesIn) {
5101 int8_t *src = (int8_t *)mRsmpInBuffer + mRsmpInIndex * mFrameSize;
5102 int8_t *dst = buffer.i8 + (buffer.frameCount - framesOut) * mActiveTrack->mCblk->frameSize;
5103 if (framesIn > framesOut)
5104 framesIn = framesOut;
5105 mRsmpInIndex += framesIn;
5106 framesOut -= framesIn;
5107 if ((int)mChannelCount == mReqChannelCount ||
Dima Zavinfce7a472011-04-19 22:30:36 -07005108 mFormat != AUDIO_FORMAT_PCM_16_BIT) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07005109 memcpy(dst, src, framesIn * mFrameSize);
5110 } else {
5111 int16_t *src16 = (int16_t *)src;
5112 int16_t *dst16 = (int16_t *)dst;
5113 if (mChannelCount == 1) {
5114 while (framesIn--) {
5115 *dst16++ = *src16;
5116 *dst16++ = *src16++;
5117 }
5118 } else {
5119 while (framesIn--) {
5120 *dst16++ = (int16_t)(((int32_t)*src16 + (int32_t)*(src16 + 1)) >> 1);
5121 src16 += 2;
5122 }
5123 }
5124 }
5125 }
5126 if (framesOut && mFrameCount == mRsmpInIndex) {
5127 if (framesOut == mFrameCount &&
Dima Zavinfce7a472011-04-19 22:30:36 -07005128 ((int)mChannelCount == mReqChannelCount || mFormat != AUDIO_FORMAT_PCM_16_BIT)) {
Dima Zavin799a70e2011-04-18 16:57:27 -07005129 mBytesRead = mInput->stream->read(mInput->stream, buffer.raw, mInputBytes);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005130 framesOut = 0;
5131 } else {
Dima Zavin799a70e2011-04-18 16:57:27 -07005132 mBytesRead = mInput->stream->read(mInput->stream, mRsmpInBuffer, mInputBytes);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005133 mRsmpInIndex = 0;
5134 }
5135 if (mBytesRead < 0) {
Steve Block29357bc2012-01-06 19:20:56 +00005136 ALOGE("Error reading audio input");
Mathias Agopian65ab4712010-07-14 17:59:35 -07005137 if (mActiveTrack->mState == TrackBase::ACTIVE) {
5138 // Force input into standby so that it tries to
5139 // recover at next read attempt
Dima Zavin799a70e2011-04-18 16:57:27 -07005140 mInput->stream->common.standby(&mInput->stream->common);
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005141 usleep(kRecordThreadSleepUs);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005142 }
5143 mRsmpInIndex = mFrameCount;
5144 framesOut = 0;
5145 buffer.frameCount = 0;
5146 }
5147 }
5148 }
5149 } else {
5150 // resampling
5151
5152 memset(mRsmpOutBuffer, 0, framesOut * 2 * sizeof(int32_t));
5153 // alter output frame count as if we were expecting stereo samples
5154 if (mChannelCount == 1 && mReqChannelCount == 1) {
5155 framesOut >>= 1;
5156 }
5157 mResampler->resample(mRsmpOutBuffer, framesOut, this);
5158 // ditherAndClamp() works as long as all buffers returned by mActiveTrack->getNextBuffer()
5159 // are 32 bit aligned which should be always true.
5160 if (mChannelCount == 2 && mReqChannelCount == 1) {
Glenn Kasten3b21c502011-12-15 09:52:39 -08005161 ditherAndClamp(mRsmpOutBuffer, mRsmpOutBuffer, framesOut);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005162 // the resampler always outputs stereo samples: do post stereo to mono conversion
5163 int16_t *src = (int16_t *)mRsmpOutBuffer;
5164 int16_t *dst = buffer.i16;
5165 while (framesOut--) {
5166 *dst++ = (int16_t)(((int32_t)*src + (int32_t)*(src + 1)) >> 1);
5167 src += 2;
5168 }
5169 } else {
Glenn Kasten3b21c502011-12-15 09:52:39 -08005170 ditherAndClamp((int32_t *)buffer.raw, mRsmpOutBuffer, framesOut);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005171 }
5172
5173 }
Eric Laurenta011e352012-03-29 15:51:43 -07005174 if (mFramestoDrop == 0) {
5175 mActiveTrack->releaseBuffer(&buffer);
5176 } else {
5177 if (mFramestoDrop > 0) {
5178 mFramestoDrop -= buffer.frameCount;
5179 if (mFramestoDrop < 0) {
5180 mFramestoDrop = 0;
5181 }
5182 }
5183 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07005184 mActiveTrack->overflow();
5185 }
5186 // client isn't retrieving buffers fast enough
5187 else {
Eric Laurent44d98482010-09-30 16:12:31 -07005188 if (!mActiveTrack->setOverflow()) {
5189 nsecs_t now = systemTime();
Glenn Kasten7dede872011-12-13 11:04:14 -08005190 if ((now - lastWarning) > kWarningThrottleNs) {
Steve Block5ff1dd52012-01-05 23:22:43 +00005191 ALOGW("RecordThread: buffer overflow");
Eric Laurent44d98482010-09-30 16:12:31 -07005192 lastWarning = now;
5193 }
5194 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07005195 // Release the processor for a while before asking for a new buffer.
5196 // This will give the application more chance to read from the buffer and
5197 // clear the overflow.
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005198 usleep(kRecordThreadSleepUs);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005199 }
5200 }
Eric Laurentec437d82011-07-26 20:54:46 -07005201 // enable changes in effect chain
5202 unlockEffectChains(effectChains);
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005203 effectChains.clear();
Mathias Agopian65ab4712010-07-14 17:59:35 -07005204 }
5205
5206 if (!mStandby) {
Dima Zavin799a70e2011-04-18 16:57:27 -07005207 mInput->stream->common.standby(&mInput->stream->common);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005208 }
5209 mActiveTrack.clear();
5210
5211 mStartStopCond.broadcast();
5212
Eric Laurentfeb0db62011-07-22 09:04:31 -07005213 releaseWakeLock();
5214
Steve Block3856b092011-10-20 11:56:00 +01005215 ALOGV("RecordThread %p exiting", this);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005216 return false;
5217}
5218
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005219
5220sp<AudioFlinger::RecordThread::RecordTrack> AudioFlinger::RecordThread::createRecordTrack_l(
5221 const sp<AudioFlinger::Client>& client,
5222 uint32_t sampleRate,
Glenn Kasten58f30212012-01-12 12:27:51 -08005223 audio_format_t format,
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005224 int channelMask,
5225 int frameCount,
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005226 int sessionId,
5227 status_t *status)
5228{
5229 sp<RecordTrack> track;
5230 status_t lStatus;
5231
5232 lStatus = initCheck();
5233 if (lStatus != NO_ERROR) {
Steve Block29357bc2012-01-06 19:20:56 +00005234 ALOGE("Audio driver not initialized.");
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005235 goto Exit;
5236 }
5237
5238 { // scope for mLock
5239 Mutex::Autolock _l(mLock);
5240
5241 track = new RecordTrack(this, client, sampleRate,
Glenn Kasten5cf034d2012-02-21 10:35:56 -08005242 format, channelMask, frameCount, sessionId);
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005243
Glenn Kasten7378ca52012-01-20 13:44:40 -08005244 if (track->getCblk() == 0) {
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005245 lStatus = NO_MEMORY;
5246 goto Exit;
5247 }
5248
5249 mTrack = track.get();
Eric Laurent59bd0da2011-08-01 09:52:20 -07005250 // disable AEC and NS if the device is a BT SCO headset supporting those pre processings
5251 bool suspend = audio_is_bluetooth_sco_device(
Eric Laurentbee53372011-08-29 12:42:48 -07005252 (audio_devices_t)(mDevice & AUDIO_DEVICE_IN_ALL)) && mAudioFlinger->btNrecIsOff();
Eric Laurent59bd0da2011-08-01 09:52:20 -07005253 setEffectSuspended_l(FX_IID_AEC, suspend, sessionId);
5254 setEffectSuspended_l(FX_IID_NS, suspend, sessionId);
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005255 }
5256 lStatus = NO_ERROR;
5257
5258Exit:
5259 if (status) {
5260 *status = lStatus;
5261 }
5262 return track;
5263}
5264
Eric Laurenta011e352012-03-29 15:51:43 -07005265status_t AudioFlinger::RecordThread::start(RecordThread::RecordTrack* recordTrack,
5266 pid_t tid, AudioSystem::sync_event_t event,
5267 int triggerSession)
Mathias Agopian65ab4712010-07-14 17:59:35 -07005268{
Eric Laurenta011e352012-03-29 15:51:43 -07005269 ALOGV("RecordThread::start tid=%d, event %d, triggerSession %d", tid, event, triggerSession);
Glenn Kastene53b9ea2012-03-12 16:29:55 -07005270 sp<ThreadBase> strongMe = this;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005271 status_t status = NO_ERROR;
Eric Laurenta011e352012-03-29 15:51:43 -07005272
5273 if (event == AudioSystem::SYNC_EVENT_NONE) {
5274 mSyncStartEvent.clear();
5275 mFramestoDrop = 0;
5276 } else if (event != AudioSystem::SYNC_EVENT_SAME) {
5277 mSyncStartEvent = mAudioFlinger->createSyncEvent(event,
5278 triggerSession,
5279 recordTrack->sessionId(),
5280 syncStartEventCallback,
5281 this);
5282 mFramestoDrop = -1;
5283 }
5284
Mathias Agopian65ab4712010-07-14 17:59:35 -07005285 {
Glenn Kastena7d8d6f2012-01-05 15:41:56 -08005286 AutoMutex lock(mLock);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005287 if (mActiveTrack != 0) {
5288 if (recordTrack != mActiveTrack.get()) {
5289 status = -EBUSY;
5290 } else if (mActiveTrack->mState == TrackBase::PAUSING) {
5291 mActiveTrack->mState = TrackBase::ACTIVE;
5292 }
5293 return status;
5294 }
5295
5296 recordTrack->mState = TrackBase::IDLE;
5297 mActiveTrack = recordTrack;
5298 mLock.unlock();
5299 status_t status = AudioSystem::startInput(mId);
5300 mLock.lock();
5301 if (status != NO_ERROR) {
5302 mActiveTrack.clear();
Eric Laurenta011e352012-03-29 15:51:43 -07005303 clearSyncStartEvent();
Mathias Agopian65ab4712010-07-14 17:59:35 -07005304 return status;
5305 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07005306 mRsmpInIndex = mFrameCount;
5307 mBytesRead = 0;
Eric Laurent243f5f92011-02-28 16:52:51 -08005308 if (mResampler != NULL) {
5309 mResampler->reset();
5310 }
5311 mActiveTrack->mState = TrackBase::RESUMING;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005312 // signal thread to start
Steve Block3856b092011-10-20 11:56:00 +01005313 ALOGV("Signal record thread");
Mathias Agopian65ab4712010-07-14 17:59:35 -07005314 mWaitWorkCV.signal();
5315 // do not wait for mStartStopCond if exiting
Glenn Kastenb28686f2012-01-06 08:39:38 -08005316 if (exitPending()) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07005317 mActiveTrack.clear();
5318 status = INVALID_OPERATION;
5319 goto startError;
5320 }
5321 mStartStopCond.wait(mLock);
5322 if (mActiveTrack == 0) {
Steve Block3856b092011-10-20 11:56:00 +01005323 ALOGV("Record failed to start");
Mathias Agopian65ab4712010-07-14 17:59:35 -07005324 status = BAD_VALUE;
5325 goto startError;
5326 }
Steve Block3856b092011-10-20 11:56:00 +01005327 ALOGV("Record started OK");
Mathias Agopian65ab4712010-07-14 17:59:35 -07005328 return status;
5329 }
5330startError:
5331 AudioSystem::stopInput(mId);
Eric Laurenta011e352012-03-29 15:51:43 -07005332 clearSyncStartEvent();
Mathias Agopian65ab4712010-07-14 17:59:35 -07005333 return status;
5334}
5335
Eric Laurenta011e352012-03-29 15:51:43 -07005336void AudioFlinger::RecordThread::clearSyncStartEvent()
5337{
5338 if (mSyncStartEvent != 0) {
5339 mSyncStartEvent->cancel();
5340 }
5341 mSyncStartEvent.clear();
5342}
5343
5344void AudioFlinger::RecordThread::syncStartEventCallback(const wp<SyncEvent>& event)
5345{
5346 sp<SyncEvent> strongEvent = event.promote();
5347
5348 if (strongEvent != 0) {
5349 RecordThread *me = (RecordThread *)strongEvent->cookie();
5350 me->handleSyncStartEvent(strongEvent);
5351 }
5352}
5353
5354void AudioFlinger::RecordThread::handleSyncStartEvent(const sp<SyncEvent>& event)
5355{
5356 ALOGV("handleSyncStartEvent() mActiveTrack %p session %d event->listenerSession() %d",
5357 mActiveTrack.get(),
5358 mActiveTrack.get() ? mActiveTrack->sessionId() : 0,
5359 event->listenerSession());
5360
5361 if (mActiveTrack != 0 &&
5362 event == mSyncStartEvent) {
5363 // TODO: use actual buffer filling status instead of 2 buffers when info is available
5364 // from audio HAL
5365 mFramestoDrop = mFrameCount * 2;
5366 mSyncStartEvent.clear();
5367 }
5368}
5369
Mathias Agopian65ab4712010-07-14 17:59:35 -07005370void AudioFlinger::RecordThread::stop(RecordThread::RecordTrack* recordTrack) {
Steve Block3856b092011-10-20 11:56:00 +01005371 ALOGV("RecordThread::stop");
Glenn Kastene53b9ea2012-03-12 16:29:55 -07005372 sp<ThreadBase> strongMe = this;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005373 {
Glenn Kastena7d8d6f2012-01-05 15:41:56 -08005374 AutoMutex lock(mLock);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005375 if (mActiveTrack != 0 && recordTrack == mActiveTrack.get()) {
5376 mActiveTrack->mState = TrackBase::PAUSING;
5377 // do not wait for mStartStopCond if exiting
Glenn Kastenb28686f2012-01-06 08:39:38 -08005378 if (exitPending()) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07005379 return;
5380 }
5381 mStartStopCond.wait(mLock);
5382 // if we have been restarted, recordTrack == mActiveTrack.get() here
5383 if (mActiveTrack == 0 || recordTrack != mActiveTrack.get()) {
5384 mLock.unlock();
5385 AudioSystem::stopInput(mId);
5386 mLock.lock();
Steve Block3856b092011-10-20 11:56:00 +01005387 ALOGV("Record stopped OK");
Mathias Agopian65ab4712010-07-14 17:59:35 -07005388 }
5389 }
5390 }
5391}
5392
Eric Laurenta011e352012-03-29 15:51:43 -07005393bool AudioFlinger::RecordThread::isValidSyncEvent(const sp<SyncEvent>& event)
5394{
5395 return false;
5396}
5397
5398status_t AudioFlinger::RecordThread::setSyncEvent(const sp<SyncEvent>& event)
5399{
5400 if (!isValidSyncEvent(event)) {
5401 return BAD_VALUE;
5402 }
5403
5404 Mutex::Autolock _l(mLock);
5405
5406 if (mTrack != NULL && event->triggerSession() == mTrack->sessionId()) {
5407 mTrack->setSyncEvent(event);
5408 return NO_ERROR;
5409 }
5410 return NAME_NOT_FOUND;
5411}
5412
Mathias Agopian65ab4712010-07-14 17:59:35 -07005413status_t AudioFlinger::RecordThread::dump(int fd, const Vector<String16>& args)
5414{
5415 const size_t SIZE = 256;
5416 char buffer[SIZE];
5417 String8 result;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005418
5419 snprintf(buffer, SIZE, "\nInput thread %p internals\n", this);
5420 result.append(buffer);
5421
5422 if (mActiveTrack != 0) {
5423 result.append("Active Track:\n");
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07005424 result.append(" Clien Fmt Chn mask Session Buf S SRate Serv User\n");
Mathias Agopian65ab4712010-07-14 17:59:35 -07005425 mActiveTrack->dump(buffer, SIZE);
5426 result.append(buffer);
5427
5428 snprintf(buffer, SIZE, "In index: %d\n", mRsmpInIndex);
5429 result.append(buffer);
5430 snprintf(buffer, SIZE, "In size: %d\n", mInputBytes);
5431 result.append(buffer);
Glenn Kastene0feee32011-12-13 11:53:26 -08005432 snprintf(buffer, SIZE, "Resampling: %d\n", (mResampler != NULL));
Mathias Agopian65ab4712010-07-14 17:59:35 -07005433 result.append(buffer);
5434 snprintf(buffer, SIZE, "Out channel count: %d\n", mReqChannelCount);
5435 result.append(buffer);
5436 snprintf(buffer, SIZE, "Out sample rate: %d\n", mReqSampleRate);
5437 result.append(buffer);
5438
5439
5440 } else {
5441 result.append("No record client\n");
5442 }
5443 write(fd, result.string(), result.size());
5444
5445 dumpBase(fd, args);
Eric Laurent1d2bff02011-07-24 17:49:51 -07005446 dumpEffectChains(fd, args);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005447
5448 return NO_ERROR;
5449}
5450
Glenn Kasten01c4ebf2012-02-22 10:47:35 -08005451// AudioBufferProvider interface
John Grossman4ff14ba2012-02-08 16:37:41 -08005452status_t AudioFlinger::RecordThread::getNextBuffer(AudioBufferProvider::Buffer* buffer, int64_t pts)
Mathias Agopian65ab4712010-07-14 17:59:35 -07005453{
5454 size_t framesReq = buffer->frameCount;
5455 size_t framesReady = mFrameCount - mRsmpInIndex;
5456 int channelCount;
5457
5458 if (framesReady == 0) {
Dima Zavin799a70e2011-04-18 16:57:27 -07005459 mBytesRead = mInput->stream->read(mInput->stream, mRsmpInBuffer, mInputBytes);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005460 if (mBytesRead < 0) {
Steve Block29357bc2012-01-06 19:20:56 +00005461 ALOGE("RecordThread::getNextBuffer() Error reading audio input");
Mathias Agopian65ab4712010-07-14 17:59:35 -07005462 if (mActiveTrack->mState == TrackBase::ACTIVE) {
5463 // Force input into standby so that it tries to
5464 // recover at next read attempt
Dima Zavin799a70e2011-04-18 16:57:27 -07005465 mInput->stream->common.standby(&mInput->stream->common);
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005466 usleep(kRecordThreadSleepUs);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005467 }
Glenn Kastene0feee32011-12-13 11:53:26 -08005468 buffer->raw = NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005469 buffer->frameCount = 0;
5470 return NOT_ENOUGH_DATA;
5471 }
5472 mRsmpInIndex = 0;
5473 framesReady = mFrameCount;
5474 }
5475
5476 if (framesReq > framesReady) {
5477 framesReq = framesReady;
5478 }
5479
5480 if (mChannelCount == 1 && mReqChannelCount == 2) {
5481 channelCount = 1;
5482 } else {
5483 channelCount = 2;
5484 }
5485 buffer->raw = mRsmpInBuffer + mRsmpInIndex * channelCount;
5486 buffer->frameCount = framesReq;
5487 return NO_ERROR;
5488}
5489
Glenn Kasten01c4ebf2012-02-22 10:47:35 -08005490// AudioBufferProvider interface
Mathias Agopian65ab4712010-07-14 17:59:35 -07005491void AudioFlinger::RecordThread::releaseBuffer(AudioBufferProvider::Buffer* buffer)
5492{
5493 mRsmpInIndex += buffer->frameCount;
5494 buffer->frameCount = 0;
5495}
5496
5497bool AudioFlinger::RecordThread::checkForNewParameters_l()
5498{
5499 bool reconfig = false;
5500
5501 while (!mNewParameters.isEmpty()) {
5502 status_t status = NO_ERROR;
5503 String8 keyValuePair = mNewParameters[0];
5504 AudioParameter param = AudioParameter(keyValuePair);
5505 int value;
Glenn Kasten58f30212012-01-12 12:27:51 -08005506 audio_format_t reqFormat = mFormat;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005507 int reqSamplingRate = mReqSampleRate;
5508 int reqChannelCount = mReqChannelCount;
5509
5510 if (param.getInt(String8(AudioParameter::keySamplingRate), value) == NO_ERROR) {
5511 reqSamplingRate = value;
5512 reconfig = true;
5513 }
5514 if (param.getInt(String8(AudioParameter::keyFormat), value) == NO_ERROR) {
Glenn Kasten58f30212012-01-12 12:27:51 -08005515 reqFormat = (audio_format_t) value;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005516 reconfig = true;
5517 }
5518 if (param.getInt(String8(AudioParameter::keyChannels), value) == NO_ERROR) {
Dima Zavinfce7a472011-04-19 22:30:36 -07005519 reqChannelCount = popcount(value);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005520 reconfig = true;
5521 }
5522 if (param.getInt(String8(AudioParameter::keyFrameCount), value) == NO_ERROR) {
5523 // do not accept frame count changes if tracks are open as the track buffer
Glenn Kasten99e53b82012-01-19 08:59:58 -08005524 // size depends on frame count and correct behavior would not be guaranteed
Mathias Agopian65ab4712010-07-14 17:59:35 -07005525 // if frame count is changed after track creation
5526 if (mActiveTrack != 0) {
5527 status = INVALID_OPERATION;
5528 } else {
5529 reconfig = true;
5530 }
5531 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005532 if (param.getInt(String8(AudioParameter::keyRouting), value) == NO_ERROR) {
5533 // forward device change to effects that have requested to be
5534 // aware of attached audio device.
5535 for (size_t i = 0; i < mEffectChains.size(); i++) {
5536 mEffectChains[i]->setDevice_l(value);
5537 }
5538 // store input device and output device but do not forward output device to audio HAL.
5539 // Note that status is ignored by the caller for output device
5540 // (see AudioFlinger::setParameters()
5541 if (value & AUDIO_DEVICE_OUT_ALL) {
5542 mDevice &= (uint32_t)~(value & AUDIO_DEVICE_OUT_ALL);
5543 status = BAD_VALUE;
5544 } else {
5545 mDevice &= (uint32_t)~(value & AUDIO_DEVICE_IN_ALL);
Eric Laurent59bd0da2011-08-01 09:52:20 -07005546 // disable AEC and NS if the device is a BT SCO headset supporting those pre processings
5547 if (mTrack != NULL) {
5548 bool suspend = audio_is_bluetooth_sco_device(
Eric Laurentbee53372011-08-29 12:42:48 -07005549 (audio_devices_t)value) && mAudioFlinger->btNrecIsOff();
Eric Laurent59bd0da2011-08-01 09:52:20 -07005550 setEffectSuspended_l(FX_IID_AEC, suspend, mTrack->sessionId());
5551 setEffectSuspended_l(FX_IID_NS, suspend, mTrack->sessionId());
5552 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005553 }
5554 mDevice |= (uint32_t)value;
5555 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07005556 if (status == NO_ERROR) {
Dima Zavin799a70e2011-04-18 16:57:27 -07005557 status = mInput->stream->common.set_parameters(&mInput->stream->common, keyValuePair.string());
Mathias Agopian65ab4712010-07-14 17:59:35 -07005558 if (status == INVALID_OPERATION) {
Glenn Kastene53b9ea2012-03-12 16:29:55 -07005559 mInput->stream->common.standby(&mInput->stream->common);
5560 status = mInput->stream->common.set_parameters(&mInput->stream->common,
5561 keyValuePair.string());
Mathias Agopian65ab4712010-07-14 17:59:35 -07005562 }
5563 if (reconfig) {
5564 if (status == BAD_VALUE &&
Dima Zavin799a70e2011-04-18 16:57:27 -07005565 reqFormat == mInput->stream->common.get_format(&mInput->stream->common) &&
Dima Zavinfce7a472011-04-19 22:30:36 -07005566 reqFormat == AUDIO_FORMAT_PCM_16_BIT &&
Dima Zavin799a70e2011-04-18 16:57:27 -07005567 ((int)mInput->stream->common.get_sample_rate(&mInput->stream->common) <= (2 * reqSamplingRate)) &&
Glenn Kasten53d76db2012-03-08 12:32:47 -08005568 popcount(mInput->stream->common.get_channels(&mInput->stream->common)) <= FCC_2 &&
5569 (reqChannelCount <= FCC_2)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07005570 status = NO_ERROR;
5571 }
5572 if (status == NO_ERROR) {
5573 readInputParameters();
5574 sendConfigEvent_l(AudioSystem::INPUT_CONFIG_CHANGED);
5575 }
5576 }
5577 }
5578
5579 mNewParameters.removeAt(0);
5580
5581 mParamStatus = status;
5582 mParamCond.signal();
Eric Laurent60cd0a02011-09-13 11:40:21 -07005583 // wait for condition with time out in case the thread calling ThreadBase::setParameters()
5584 // already timed out waiting for the status and will never signal the condition.
Glenn Kasten7dede872011-12-13 11:04:14 -08005585 mWaitWorkCV.waitRelative(mLock, kSetParametersTimeoutNs);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005586 }
5587 return reconfig;
5588}
5589
5590String8 AudioFlinger::RecordThread::getParameters(const String8& keys)
5591{
Dima Zavinfce7a472011-04-19 22:30:36 -07005592 char *s;
Eric Laurentb8ba0a92011-08-07 16:32:26 -07005593 String8 out_s8 = String8();
5594
5595 Mutex::Autolock _l(mLock);
5596 if (initCheck() != NO_ERROR) {
5597 return out_s8;
5598 }
Dima Zavinfce7a472011-04-19 22:30:36 -07005599
Dima Zavin799a70e2011-04-18 16:57:27 -07005600 s = mInput->stream->common.get_parameters(&mInput->stream->common, keys.string());
Dima Zavinfce7a472011-04-19 22:30:36 -07005601 out_s8 = String8(s);
5602 free(s);
5603 return out_s8;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005604}
5605
5606void AudioFlinger::RecordThread::audioConfigChanged_l(int event, int param) {
5607 AudioSystem::OutputDescriptor desc;
Glenn Kastena0d68332012-01-27 16:47:15 -08005608 void *param2 = NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005609
5610 switch (event) {
5611 case AudioSystem::INPUT_OPENED:
5612 case AudioSystem::INPUT_CONFIG_CHANGED:
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07005613 desc.channels = mChannelMask;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005614 desc.samplingRate = mSampleRate;
5615 desc.format = mFormat;
5616 desc.frameCount = mFrameCount;
5617 desc.latency = 0;
5618 param2 = &desc;
5619 break;
5620
5621 case AudioSystem::INPUT_CLOSED:
5622 default:
5623 break;
5624 }
5625 mAudioFlinger->audioConfigChanged_l(event, mId, param2);
5626}
5627
5628void AudioFlinger::RecordThread::readInputParameters()
5629{
Glenn Kastene9dd0172012-01-27 18:08:45 -08005630 delete mRsmpInBuffer;
5631 // mRsmpInBuffer is always assigned a new[] below
5632 delete mRsmpOutBuffer;
5633 mRsmpOutBuffer = NULL;
5634 delete mResampler;
Glenn Kastene0feee32011-12-13 11:53:26 -08005635 mResampler = NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005636
Dima Zavin799a70e2011-04-18 16:57:27 -07005637 mSampleRate = mInput->stream->common.get_sample_rate(&mInput->stream->common);
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07005638 mChannelMask = mInput->stream->common.get_channels(&mInput->stream->common);
5639 mChannelCount = (uint16_t)popcount(mChannelMask);
Dima Zavin799a70e2011-04-18 16:57:27 -07005640 mFormat = mInput->stream->common.get_format(&mInput->stream->common);
Glenn Kastenb9980652012-01-11 09:48:27 -08005641 mFrameSize = audio_stream_frame_size(&mInput->stream->common);
Dima Zavin799a70e2011-04-18 16:57:27 -07005642 mInputBytes = mInput->stream->common.get_buffer_size(&mInput->stream->common);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005643 mFrameCount = mInputBytes / mFrameSize;
5644 mRsmpInBuffer = new int16_t[mFrameCount * mChannelCount];
5645
Glenn Kasten53d76db2012-03-08 12:32:47 -08005646 if (mSampleRate != mReqSampleRate && mChannelCount <= FCC_2 && mReqChannelCount <= FCC_2)
Mathias Agopian65ab4712010-07-14 17:59:35 -07005647 {
5648 int channelCount;
Glenn Kastene53b9ea2012-03-12 16:29:55 -07005649 // optimization: if mono to mono, use the resampler in stereo to stereo mode to avoid
5650 // stereo to mono post process as the resampler always outputs stereo.
Mathias Agopian65ab4712010-07-14 17:59:35 -07005651 if (mChannelCount == 1 && mReqChannelCount == 2) {
5652 channelCount = 1;
5653 } else {
5654 channelCount = 2;
5655 }
5656 mResampler = AudioResampler::create(16, channelCount, mReqSampleRate);
5657 mResampler->setSampleRate(mSampleRate);
5658 mResampler->setVolume(AudioMixer::UNITY_GAIN, AudioMixer::UNITY_GAIN);
5659 mRsmpOutBuffer = new int32_t[mFrameCount * 2];
5660
5661 // optmization: if mono to mono, alter input frame count as if we were inputing stereo samples
5662 if (mChannelCount == 1 && mReqChannelCount == 1) {
5663 mFrameCount >>= 1;
5664 }
5665
5666 }
5667 mRsmpInIndex = mFrameCount;
5668}
5669
5670unsigned int AudioFlinger::RecordThread::getInputFramesLost()
5671{
Eric Laurentb8ba0a92011-08-07 16:32:26 -07005672 Mutex::Autolock _l(mLock);
5673 if (initCheck() != NO_ERROR) {
5674 return 0;
5675 }
5676
Dima Zavin799a70e2011-04-18 16:57:27 -07005677 return mInput->stream->get_input_frames_lost(mInput->stream);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005678}
5679
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005680uint32_t AudioFlinger::RecordThread::hasAudioSession(int sessionId)
5681{
5682 Mutex::Autolock _l(mLock);
5683 uint32_t result = 0;
5684 if (getEffectChain_l(sessionId) != 0) {
5685 result = EFFECT_SESSION;
5686 }
5687
5688 if (mTrack != NULL && sessionId == mTrack->sessionId()) {
5689 result |= TRACK_SESSION;
5690 }
5691
5692 return result;
5693}
5694
Eric Laurent59bd0da2011-08-01 09:52:20 -07005695AudioFlinger::RecordThread::RecordTrack* AudioFlinger::RecordThread::track()
5696{
5697 Mutex::Autolock _l(mLock);
5698 return mTrack;
5699}
5700
Glenn Kastenaed850d2012-01-26 09:46:34 -08005701AudioFlinger::AudioStreamIn* AudioFlinger::RecordThread::getInput() const
Eric Laurentb8ba0a92011-08-07 16:32:26 -07005702{
5703 Mutex::Autolock _l(mLock);
5704 return mInput;
5705}
5706
5707AudioFlinger::AudioStreamIn* AudioFlinger::RecordThread::clearInput()
5708{
5709 Mutex::Autolock _l(mLock);
5710 AudioStreamIn *input = mInput;
5711 mInput = NULL;
5712 return input;
5713}
5714
5715// this method must always be called either with ThreadBase mLock held or inside the thread loop
Glenn Kasten0bf65bd2012-02-28 18:32:53 -08005716audio_stream_t* AudioFlinger::RecordThread::stream() const
Eric Laurentb8ba0a92011-08-07 16:32:26 -07005717{
5718 if (mInput == NULL) {
5719 return NULL;
5720 }
5721 return &mInput->stream->common;
5722}
5723
5724
Mathias Agopian65ab4712010-07-14 17:59:35 -07005725// ----------------------------------------------------------------------------
5726
Eric Laurenta4c5a552012-03-29 10:12:40 -07005727audio_module_handle_t AudioFlinger::loadHwModule(const char *name)
5728{
5729 if (!settingsAllowed()) {
5730 return 0;
5731 }
5732 Mutex::Autolock _l(mLock);
5733 return loadHwModule_l(name);
5734}
5735
5736// loadHwModule_l() must be called with AudioFlinger::mLock held
5737audio_module_handle_t AudioFlinger::loadHwModule_l(const char *name)
5738{
5739 for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
5740 if (strncmp(mAudioHwDevs.valueAt(i)->moduleName(), name, strlen(name)) == 0) {
5741 ALOGW("loadHwModule() module %s already loaded", name);
5742 return mAudioHwDevs.keyAt(i);
5743 }
5744 }
5745
5746 const hw_module_t *mod;
5747 audio_hw_device_t *dev;
5748
5749 int rc = load_audio_interface(name, &mod, &dev);
5750 if (rc) {
5751 ALOGI("loadHwModule() error %d loading module %s ", rc, name);
5752 return 0;
5753 }
5754
5755 mHardwareStatus = AUDIO_HW_INIT;
5756 rc = dev->init_check(dev);
5757 mHardwareStatus = AUDIO_HW_IDLE;
5758 if (rc) {
5759 ALOGI("loadHwModule() init check error %d for module %s ", rc, name);
5760 return 0;
5761 }
5762
5763 if ((mMasterVolumeSupportLvl != MVS_NONE) &&
5764 (NULL != dev->set_master_volume)) {
5765 AutoMutex lock(mHardwareLock);
5766 mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
5767 dev->set_master_volume(dev, mMasterVolume);
5768 mHardwareStatus = AUDIO_HW_IDLE;
5769 }
5770
5771 audio_module_handle_t handle = nextUniqueId();
5772 mAudioHwDevs.add(handle, new AudioHwDevice(name, dev));
5773
5774 ALOGI("loadHwModule() Loaded %s audio interface from %s (%s) handle %d",
5775 name, mod->name, mod->id, handle);
5776
5777 return handle;
5778
5779}
5780
5781audio_io_handle_t AudioFlinger::openOutput(audio_module_handle_t module,
5782 audio_devices_t *pDevices,
5783 uint32_t *pSamplingRate,
5784 audio_format_t *pFormat,
5785 audio_channel_mask_t *pChannelMask,
5786 uint32_t *pLatencyMs,
5787 audio_policy_output_flags_t flags)
Mathias Agopian65ab4712010-07-14 17:59:35 -07005788{
5789 status_t status;
5790 PlaybackThread *thread = NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005791 uint32_t samplingRate = pSamplingRate ? *pSamplingRate : 0;
Glenn Kasten58f30212012-01-12 12:27:51 -08005792 audio_format_t format = pFormat ? *pFormat : AUDIO_FORMAT_DEFAULT;
Eric Laurenta4c5a552012-03-29 10:12:40 -07005793 audio_channel_mask_t channelMask = pChannelMask ? *pChannelMask : 0;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005794 uint32_t latency = pLatencyMs ? *pLatencyMs : 0;
Dima Zavin799a70e2011-04-18 16:57:27 -07005795 audio_stream_out_t *outStream;
5796 audio_hw_device_t *outHwDev;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005797
Eric Laurenta4c5a552012-03-29 10:12:40 -07005798 ALOGV("openOutput(), module %d Device %x, SamplingRate %d, Format %d, Channels %x, flags %x",
5799 module,
Eric Laurent3f9c84c2012-04-03 15:36:53 -07005800 (pDevices != NULL) ? (int)*pDevices : 0,
Eric Laurenta4c5a552012-03-29 10:12:40 -07005801 samplingRate,
5802 format,
5803 channelMask,
5804 flags);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005805
5806 if (pDevices == NULL || *pDevices == 0) {
5807 return 0;
5808 }
Dima Zavin799a70e2011-04-18 16:57:27 -07005809
Mathias Agopian65ab4712010-07-14 17:59:35 -07005810 Mutex::Autolock _l(mLock);
5811
Eric Laurenta4c5a552012-03-29 10:12:40 -07005812 outHwDev = findSuitableHwDev_l(module, *pDevices);
Dima Zavin799a70e2011-04-18 16:57:27 -07005813 if (outHwDev == NULL)
5814 return 0;
5815
Glenn Kasten8abf44d2012-02-02 14:16:03 -08005816 mHardwareStatus = AUDIO_HW_OUTPUT_OPEN;
Glenn Kasten58f30212012-01-12 12:27:51 -08005817 status = outHwDev->open_output_stream(outHwDev, *pDevices, &format,
Eric Laurenta4c5a552012-03-29 10:12:40 -07005818 &channelMask, &samplingRate, &outStream);
Glenn Kasten8abf44d2012-02-02 14:16:03 -08005819 mHardwareStatus = AUDIO_HW_IDLE;
Steve Block3856b092011-10-20 11:56:00 +01005820 ALOGV("openOutput() openOutputStream returned output %p, SamplingRate %d, Format %d, Channels %x, status %d",
Dima Zavin799a70e2011-04-18 16:57:27 -07005821 outStream,
Mathias Agopian65ab4712010-07-14 17:59:35 -07005822 samplingRate,
5823 format,
Eric Laurenta4c5a552012-03-29 10:12:40 -07005824 channelMask,
Mathias Agopian65ab4712010-07-14 17:59:35 -07005825 status);
5826
Dima Zavin799a70e2011-04-18 16:57:27 -07005827 if (outStream != NULL) {
5828 AudioStreamOut *output = new AudioStreamOut(outHwDev, outStream);
Glenn Kasten72ef00d2012-01-17 11:09:42 -08005829 audio_io_handle_t id = nextUniqueId();
Dima Zavin799a70e2011-04-18 16:57:27 -07005830
Dima Zavinfce7a472011-04-19 22:30:36 -07005831 if ((flags & AUDIO_POLICY_OUTPUT_FLAG_DIRECT) ||
5832 (format != AUDIO_FORMAT_PCM_16_BIT) ||
Eric Laurenta4c5a552012-03-29 10:12:40 -07005833 (channelMask != AUDIO_CHANNEL_OUT_STEREO)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07005834 thread = new DirectOutputThread(this, output, id, *pDevices);
Steve Block3856b092011-10-20 11:56:00 +01005835 ALOGV("openOutput() created direct output: ID %d thread %p", id, thread);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005836 } else {
5837 thread = new MixerThread(this, output, id, *pDevices);
Steve Block3856b092011-10-20 11:56:00 +01005838 ALOGV("openOutput() created mixer output: ID %d thread %p", id, thread);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005839 }
5840 mPlaybackThreads.add(id, thread);
5841
Glenn Kastena0d68332012-01-27 16:47:15 -08005842 if (pSamplingRate != NULL) *pSamplingRate = samplingRate;
5843 if (pFormat != NULL) *pFormat = format;
Eric Laurenta4c5a552012-03-29 10:12:40 -07005844 if (pChannelMask != NULL) *pChannelMask = channelMask;
Glenn Kastena0d68332012-01-27 16:47:15 -08005845 if (pLatencyMs != NULL) *pLatencyMs = thread->latency();
Mathias Agopian65ab4712010-07-14 17:59:35 -07005846
5847 // notify client processes of the new output creation
5848 thread->audioConfigChanged_l(AudioSystem::OUTPUT_OPENED);
Eric Laurenta4c5a552012-03-29 10:12:40 -07005849
5850 // the first primary output opened designates the primary hw device
5851 if ((mPrimaryHardwareDev == NULL) && (flags & AUDIO_POLICY_OUTPUT_FLAG_PRIMARY)) {
5852 ALOGI("Using module %d has the primary audio interface", module);
5853 mPrimaryHardwareDev = outHwDev;
5854
5855 AutoMutex lock(mHardwareLock);
5856 mHardwareStatus = AUDIO_HW_SET_MODE;
5857 outHwDev->set_mode(outHwDev, mMode);
5858
5859 // Determine the level of master volume support the primary audio HAL has,
5860 // and set the initial master volume at the same time.
5861 float initialVolume = 1.0;
5862 mMasterVolumeSupportLvl = MVS_NONE;
5863
5864 mHardwareStatus = AUDIO_HW_GET_MASTER_VOLUME;
5865 if ((NULL != outHwDev->get_master_volume) &&
5866 (NO_ERROR == outHwDev->get_master_volume(outHwDev, &initialVolume))) {
5867 mMasterVolumeSupportLvl = MVS_FULL;
5868 } else {
5869 mMasterVolumeSupportLvl = MVS_SETONLY;
5870 initialVolume = 1.0;
5871 }
5872
5873 mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
5874 if ((NULL == outHwDev->set_master_volume) ||
5875 (NO_ERROR != outHwDev->set_master_volume(outHwDev, initialVolume))) {
5876 mMasterVolumeSupportLvl = MVS_NONE;
5877 }
5878 // now that we have a primary device, initialize master volume on other devices
5879 for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
5880 audio_hw_device_t *dev = mAudioHwDevs.valueAt(i)->hwDevice();
5881
5882 if ((dev != mPrimaryHardwareDev) &&
5883 (NULL != dev->set_master_volume)) {
5884 dev->set_master_volume(dev, initialVolume);
5885 }
5886 }
5887 mHardwareStatus = AUDIO_HW_IDLE;
5888 mMasterVolumeSW = (MVS_NONE == mMasterVolumeSupportLvl)
5889 ? initialVolume
5890 : 1.0;
5891 mMasterVolume = initialVolume;
5892 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07005893 return id;
5894 }
5895
5896 return 0;
5897}
5898
Glenn Kasten72ef00d2012-01-17 11:09:42 -08005899audio_io_handle_t AudioFlinger::openDuplicateOutput(audio_io_handle_t output1,
5900 audio_io_handle_t output2)
Mathias Agopian65ab4712010-07-14 17:59:35 -07005901{
5902 Mutex::Autolock _l(mLock);
5903 MixerThread *thread1 = checkMixerThread_l(output1);
5904 MixerThread *thread2 = checkMixerThread_l(output2);
5905
5906 if (thread1 == NULL || thread2 == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +00005907 ALOGW("openDuplicateOutput() wrong output mixer type for output %d or %d", output1, output2);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005908 return 0;
5909 }
5910
Glenn Kasten72ef00d2012-01-17 11:09:42 -08005911 audio_io_handle_t id = nextUniqueId();
Mathias Agopian65ab4712010-07-14 17:59:35 -07005912 DuplicatingThread *thread = new DuplicatingThread(this, thread1, id);
5913 thread->addOutputTrack(thread2);
5914 mPlaybackThreads.add(id, thread);
5915 // notify client processes of the new output creation
5916 thread->audioConfigChanged_l(AudioSystem::OUTPUT_OPENED);
5917 return id;
5918}
5919
Glenn Kasten72ef00d2012-01-17 11:09:42 -08005920status_t AudioFlinger::closeOutput(audio_io_handle_t output)
Mathias Agopian65ab4712010-07-14 17:59:35 -07005921{
5922 // keep strong reference on the playback thread so that
5923 // it is not destroyed while exit() is executed
Glenn Kastene53b9ea2012-03-12 16:29:55 -07005924 sp<PlaybackThread> thread;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005925 {
5926 Mutex::Autolock _l(mLock);
5927 thread = checkPlaybackThread_l(output);
5928 if (thread == NULL) {
5929 return BAD_VALUE;
5930 }
5931
Steve Block3856b092011-10-20 11:56:00 +01005932 ALOGV("closeOutput() %d", output);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005933
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005934 if (thread->type() == ThreadBase::MIXER) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07005935 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005936 if (mPlaybackThreads.valueAt(i)->type() == ThreadBase::DUPLICATING) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07005937 DuplicatingThread *dupThread = (DuplicatingThread *)mPlaybackThreads.valueAt(i).get();
5938 dupThread->removeOutputTrack((MixerThread *)thread.get());
5939 }
5940 }
5941 }
Glenn Kastena1117922012-01-26 10:53:32 -08005942 audioConfigChanged_l(AudioSystem::OUTPUT_CLOSED, output, NULL);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005943 mPlaybackThreads.removeItem(output);
5944 }
5945 thread->exit();
Glenn Kastenb28686f2012-01-06 08:39:38 -08005946 // The thread entity (active unit of execution) is no longer running here,
5947 // but the ThreadBase container still exists.
Mathias Agopian65ab4712010-07-14 17:59:35 -07005948
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005949 if (thread->type() != ThreadBase::DUPLICATING) {
Eric Laurentb8ba0a92011-08-07 16:32:26 -07005950 AudioStreamOut *out = thread->clearOutput();
Glenn Kasten5798d4e2012-03-08 12:18:35 -08005951 ALOG_ASSERT(out != NULL, "out shouldn't be NULL");
Eric Laurentb8ba0a92011-08-07 16:32:26 -07005952 // from now on thread->mOutput is NULL
Dima Zavin799a70e2011-04-18 16:57:27 -07005953 out->hwDev->close_output_stream(out->hwDev, out->stream);
5954 delete out;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005955 }
5956 return NO_ERROR;
5957}
5958
Glenn Kasten72ef00d2012-01-17 11:09:42 -08005959status_t AudioFlinger::suspendOutput(audio_io_handle_t output)
Mathias Agopian65ab4712010-07-14 17:59:35 -07005960{
5961 Mutex::Autolock _l(mLock);
5962 PlaybackThread *thread = checkPlaybackThread_l(output);
5963
5964 if (thread == NULL) {
5965 return BAD_VALUE;
5966 }
5967
Steve Block3856b092011-10-20 11:56:00 +01005968 ALOGV("suspendOutput() %d", output);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005969 thread->suspend();
5970
5971 return NO_ERROR;
5972}
5973
Glenn Kasten72ef00d2012-01-17 11:09:42 -08005974status_t AudioFlinger::restoreOutput(audio_io_handle_t output)
Mathias Agopian65ab4712010-07-14 17:59:35 -07005975{
5976 Mutex::Autolock _l(mLock);
5977 PlaybackThread *thread = checkPlaybackThread_l(output);
5978
5979 if (thread == NULL) {
5980 return BAD_VALUE;
5981 }
5982
Steve Block3856b092011-10-20 11:56:00 +01005983 ALOGV("restoreOutput() %d", output);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005984
5985 thread->restore();
5986
5987 return NO_ERROR;
5988}
5989
Eric Laurenta4c5a552012-03-29 10:12:40 -07005990audio_io_handle_t AudioFlinger::openInput(audio_module_handle_t module,
5991 audio_devices_t *pDevices,
5992 uint32_t *pSamplingRate,
5993 audio_format_t *pFormat,
5994 uint32_t *pChannelMask)
Mathias Agopian65ab4712010-07-14 17:59:35 -07005995{
5996 status_t status;
5997 RecordThread *thread = NULL;
5998 uint32_t samplingRate = pSamplingRate ? *pSamplingRate : 0;
Glenn Kasten58f30212012-01-12 12:27:51 -08005999 audio_format_t format = pFormat ? *pFormat : AUDIO_FORMAT_DEFAULT;
Eric Laurenta4c5a552012-03-29 10:12:40 -07006000 audio_channel_mask_t channelMask = pChannelMask ? *pChannelMask : 0;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006001 uint32_t reqSamplingRate = samplingRate;
Glenn Kasten58f30212012-01-12 12:27:51 -08006002 audio_format_t reqFormat = format;
Eric Laurenta4c5a552012-03-29 10:12:40 -07006003 audio_channel_mask_t reqChannels = channelMask;
Dima Zavin799a70e2011-04-18 16:57:27 -07006004 audio_stream_in_t *inStream;
6005 audio_hw_device_t *inHwDev;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006006
6007 if (pDevices == NULL || *pDevices == 0) {
6008 return 0;
6009 }
Dima Zavin799a70e2011-04-18 16:57:27 -07006010
Mathias Agopian65ab4712010-07-14 17:59:35 -07006011 Mutex::Autolock _l(mLock);
6012
Eric Laurenta4c5a552012-03-29 10:12:40 -07006013 inHwDev = findSuitableHwDev_l(module, *pDevices);
Dima Zavin799a70e2011-04-18 16:57:27 -07006014 if (inHwDev == NULL)
6015 return 0;
6016
Glenn Kasten58f30212012-01-12 12:27:51 -08006017 status = inHwDev->open_input_stream(inHwDev, *pDevices, &format,
Eric Laurenta4c5a552012-03-29 10:12:40 -07006018 &channelMask, &samplingRate,
6019 (audio_in_acoustics_t)0,
Dima Zavin799a70e2011-04-18 16:57:27 -07006020 &inStream);
Eric Laurenta4c5a552012-03-29 10:12:40 -07006021 ALOGV("openInput() openInputStream returned input %p, SamplingRate %d, Format %d, Channels %x, status %d",
Dima Zavin799a70e2011-04-18 16:57:27 -07006022 inStream,
Mathias Agopian65ab4712010-07-14 17:59:35 -07006023 samplingRate,
6024 format,
Eric Laurenta4c5a552012-03-29 10:12:40 -07006025 channelMask,
Mathias Agopian65ab4712010-07-14 17:59:35 -07006026 status);
6027
6028 // If the input could not be opened with the requested parameters and we can handle the conversion internally,
6029 // try to open again with the proposed parameters. The AudioFlinger can resample the input and do mono to stereo
6030 // or stereo to mono conversions on 16 bit PCM inputs.
Dima Zavin799a70e2011-04-18 16:57:27 -07006031 if (inStream == NULL && status == BAD_VALUE &&
Dima Zavinfce7a472011-04-19 22:30:36 -07006032 reqFormat == format && format == AUDIO_FORMAT_PCM_16_BIT &&
Mathias Agopian65ab4712010-07-14 17:59:35 -07006033 (samplingRate <= 2 * reqSamplingRate) &&
Eric Laurenta4c5a552012-03-29 10:12:40 -07006034 (popcount(channelMask) <= FCC_2) && (popcount(reqChannels) <= FCC_2)) {
Steve Block3856b092011-10-20 11:56:00 +01006035 ALOGV("openInput() reopening with proposed sampling rate and channels");
Glenn Kasten58f30212012-01-12 12:27:51 -08006036 status = inHwDev->open_input_stream(inHwDev, *pDevices, &format,
Eric Laurenta4c5a552012-03-29 10:12:40 -07006037 &channelMask, &samplingRate,
6038 (audio_in_acoustics_t)0,
Dima Zavin799a70e2011-04-18 16:57:27 -07006039 &inStream);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006040 }
6041
Dima Zavin799a70e2011-04-18 16:57:27 -07006042 if (inStream != NULL) {
6043 AudioStreamIn *input = new AudioStreamIn(inHwDev, inStream);
6044
Glenn Kasten72ef00d2012-01-17 11:09:42 -08006045 audio_io_handle_t id = nextUniqueId();
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006046 // Start record thread
6047 // RecorThread require both input and output device indication to forward to audio
6048 // pre processing modules
6049 uint32_t device = (*pDevices) | primaryOutputDevice_l();
6050 thread = new RecordThread(this,
6051 input,
6052 reqSamplingRate,
6053 reqChannels,
6054 id,
6055 device);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006056 mRecordThreads.add(id, thread);
Steve Block3856b092011-10-20 11:56:00 +01006057 ALOGV("openInput() created record thread: ID %d thread %p", id, thread);
Glenn Kastena0d68332012-01-27 16:47:15 -08006058 if (pSamplingRate != NULL) *pSamplingRate = reqSamplingRate;
6059 if (pFormat != NULL) *pFormat = format;
Eric Laurenta4c5a552012-03-29 10:12:40 -07006060 if (pChannelMask != NULL) *pChannelMask = reqChannels;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006061
Dima Zavin799a70e2011-04-18 16:57:27 -07006062 input->stream->common.standby(&input->stream->common);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006063
6064 // notify client processes of the new input creation
6065 thread->audioConfigChanged_l(AudioSystem::INPUT_OPENED);
6066 return id;
6067 }
6068
6069 return 0;
6070}
6071
Glenn Kasten72ef00d2012-01-17 11:09:42 -08006072status_t AudioFlinger::closeInput(audio_io_handle_t input)
Mathias Agopian65ab4712010-07-14 17:59:35 -07006073{
6074 // keep strong reference on the record thread so that
6075 // it is not destroyed while exit() is executed
Glenn Kastene53b9ea2012-03-12 16:29:55 -07006076 sp<RecordThread> thread;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006077 {
6078 Mutex::Autolock _l(mLock);
6079 thread = checkRecordThread_l(input);
6080 if (thread == NULL) {
6081 return BAD_VALUE;
6082 }
6083
Steve Block3856b092011-10-20 11:56:00 +01006084 ALOGV("closeInput() %d", input);
Glenn Kastena1117922012-01-26 10:53:32 -08006085 audioConfigChanged_l(AudioSystem::INPUT_CLOSED, input, NULL);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006086 mRecordThreads.removeItem(input);
6087 }
6088 thread->exit();
Glenn Kastenb28686f2012-01-06 08:39:38 -08006089 // The thread entity (active unit of execution) is no longer running here,
6090 // but the ThreadBase container still exists.
Mathias Agopian65ab4712010-07-14 17:59:35 -07006091
Eric Laurentb8ba0a92011-08-07 16:32:26 -07006092 AudioStreamIn *in = thread->clearInput();
Glenn Kasten5798d4e2012-03-08 12:18:35 -08006093 ALOG_ASSERT(in != NULL, "in shouldn't be NULL");
Eric Laurentb8ba0a92011-08-07 16:32:26 -07006094 // from now on thread->mInput is NULL
Dima Zavin799a70e2011-04-18 16:57:27 -07006095 in->hwDev->close_input_stream(in->hwDev, in->stream);
6096 delete in;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006097
6098 return NO_ERROR;
6099}
6100
Glenn Kasten72ef00d2012-01-17 11:09:42 -08006101status_t AudioFlinger::setStreamOutput(audio_stream_type_t stream, audio_io_handle_t output)
Mathias Agopian65ab4712010-07-14 17:59:35 -07006102{
6103 Mutex::Autolock _l(mLock);
6104 MixerThread *dstThread = checkMixerThread_l(output);
6105 if (dstThread == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +00006106 ALOGW("setStreamOutput() bad output id %d", output);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006107 return BAD_VALUE;
6108 }
6109
Steve Block3856b092011-10-20 11:56:00 +01006110 ALOGV("setStreamOutput() stream %d to output %d", stream, output);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006111 audioConfigChanged_l(AudioSystem::STREAM_CONFIG_CHANGED, output, &stream);
6112
6113 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
6114 PlaybackThread *thread = mPlaybackThreads.valueAt(i).get();
Glenn Kastena1117922012-01-26 10:53:32 -08006115 if (thread != dstThread && thread->type() != ThreadBase::DIRECT) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07006116 MixerThread *srcThread = (MixerThread *)thread;
6117 srcThread->invalidateTracks(stream);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006118 }
Eric Laurentde070132010-07-13 04:45:46 -07006119 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07006120
6121 return NO_ERROR;
6122}
6123
6124
6125int AudioFlinger::newAudioSessionId()
6126{
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006127 return nextUniqueId();
Mathias Agopian65ab4712010-07-14 17:59:35 -07006128}
6129
Marco Nelissen3a34bef2011-08-02 13:33:41 -07006130void AudioFlinger::acquireAudioSessionId(int audioSession)
6131{
6132 Mutex::Autolock _l(mLock);
Glenn Kastenbb001922012-02-03 11:10:26 -08006133 pid_t caller = IPCThreadState::self()->getCallingPid();
Steve Block3856b092011-10-20 11:56:00 +01006134 ALOGV("acquiring %d from %d", audioSession, caller);
Glenn Kasten8d6a2442012-02-08 14:04:28 -08006135 size_t num = mAudioSessionRefs.size();
6136 for (size_t i = 0; i< num; i++) {
Marco Nelissen3a34bef2011-08-02 13:33:41 -07006137 AudioSessionRef *ref = mAudioSessionRefs.editItemAt(i);
Glenn Kasten012ca6b2012-03-06 11:22:01 -08006138 if (ref->mSessionid == audioSession && ref->mPid == caller) {
6139 ref->mCnt++;
6140 ALOGV(" incremented refcount to %d", ref->mCnt);
Marco Nelissen3a34bef2011-08-02 13:33:41 -07006141 return;
6142 }
6143 }
Glenn Kasten84afa3b2012-01-25 15:28:08 -08006144 mAudioSessionRefs.push(new AudioSessionRef(audioSession, caller));
6145 ALOGV(" added new entry for %d", audioSession);
Marco Nelissen3a34bef2011-08-02 13:33:41 -07006146}
6147
6148void AudioFlinger::releaseAudioSessionId(int audioSession)
6149{
6150 Mutex::Autolock _l(mLock);
Glenn Kastenbb001922012-02-03 11:10:26 -08006151 pid_t caller = IPCThreadState::self()->getCallingPid();
Steve Block3856b092011-10-20 11:56:00 +01006152 ALOGV("releasing %d from %d", audioSession, caller);
Glenn Kasten8d6a2442012-02-08 14:04:28 -08006153 size_t num = mAudioSessionRefs.size();
6154 for (size_t i = 0; i< num; i++) {
Marco Nelissen3a34bef2011-08-02 13:33:41 -07006155 AudioSessionRef *ref = mAudioSessionRefs.itemAt(i);
Glenn Kasten012ca6b2012-03-06 11:22:01 -08006156 if (ref->mSessionid == audioSession && ref->mPid == caller) {
6157 ref->mCnt--;
6158 ALOGV(" decremented refcount to %d", ref->mCnt);
6159 if (ref->mCnt == 0) {
Marco Nelissen3a34bef2011-08-02 13:33:41 -07006160 mAudioSessionRefs.removeAt(i);
6161 delete ref;
6162 purgeStaleEffects_l();
6163 }
6164 return;
6165 }
6166 }
Steve Block5ff1dd52012-01-05 23:22:43 +00006167 ALOGW("session id %d not found for pid %d", audioSession, caller);
Marco Nelissen3a34bef2011-08-02 13:33:41 -07006168}
6169
6170void AudioFlinger::purgeStaleEffects_l() {
6171
Steve Block3856b092011-10-20 11:56:00 +01006172 ALOGV("purging stale effects");
Marco Nelissen3a34bef2011-08-02 13:33:41 -07006173
6174 Vector< sp<EffectChain> > chains;
6175
6176 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
6177 sp<PlaybackThread> t = mPlaybackThreads.valueAt(i);
6178 for (size_t j = 0; j < t->mEffectChains.size(); j++) {
6179 sp<EffectChain> ec = t->mEffectChains[j];
Marco Nelissen0270b182011-08-12 14:14:39 -07006180 if (ec->sessionId() > AUDIO_SESSION_OUTPUT_MIX) {
6181 chains.push(ec);
6182 }
Marco Nelissen3a34bef2011-08-02 13:33:41 -07006183 }
6184 }
6185 for (size_t i = 0; i < mRecordThreads.size(); i++) {
6186 sp<RecordThread> t = mRecordThreads.valueAt(i);
6187 for (size_t j = 0; j < t->mEffectChains.size(); j++) {
6188 sp<EffectChain> ec = t->mEffectChains[j];
6189 chains.push(ec);
6190 }
6191 }
6192
6193 for (size_t i = 0; i < chains.size(); i++) {
6194 sp<EffectChain> ec = chains[i];
6195 int sessionid = ec->sessionId();
6196 sp<ThreadBase> t = ec->mThread.promote();
6197 if (t == 0) {
6198 continue;
6199 }
6200 size_t numsessionrefs = mAudioSessionRefs.size();
6201 bool found = false;
6202 for (size_t k = 0; k < numsessionrefs; k++) {
6203 AudioSessionRef *ref = mAudioSessionRefs.itemAt(k);
Glenn Kasten012ca6b2012-03-06 11:22:01 -08006204 if (ref->mSessionid == sessionid) {
Steve Block3856b092011-10-20 11:56:00 +01006205 ALOGV(" session %d still exists for %d with %d refs",
Glenn Kastene53b9ea2012-03-12 16:29:55 -07006206 sessionid, ref->mPid, ref->mCnt);
Marco Nelissen3a34bef2011-08-02 13:33:41 -07006207 found = true;
6208 break;
6209 }
6210 }
6211 if (!found) {
6212 // remove all effects from the chain
6213 while (ec->mEffects.size()) {
6214 sp<EffectModule> effect = ec->mEffects[0];
6215 effect->unPin();
6216 Mutex::Autolock _l (t->mLock);
6217 t->removeEffect_l(effect);
6218 for (size_t j = 0; j < effect->mHandles.size(); j++) {
6219 sp<EffectHandle> handle = effect->mHandles[j].promote();
6220 if (handle != 0) {
6221 handle->mEffect.clear();
Eric Laurenta85a74a2011-10-19 11:44:54 -07006222 if (handle->mHasControl && handle->mEnabled) {
6223 t->checkSuspendOnEffectEnabled_l(effect, false, effect->sessionId());
6224 }
Marco Nelissen3a34bef2011-08-02 13:33:41 -07006225 }
6226 }
6227 AudioSystem::unregisterEffect(effect->id());
6228 }
6229 }
6230 }
6231 return;
6232}
6233
Mathias Agopian65ab4712010-07-14 17:59:35 -07006234// checkPlaybackThread_l() must be called with AudioFlinger::mLock held
Glenn Kasten72ef00d2012-01-17 11:09:42 -08006235AudioFlinger::PlaybackThread *AudioFlinger::checkPlaybackThread_l(audio_io_handle_t output) const
Mathias Agopian65ab4712010-07-14 17:59:35 -07006236{
Glenn Kastena1117922012-01-26 10:53:32 -08006237 return mPlaybackThreads.valueFor(output).get();
Mathias Agopian65ab4712010-07-14 17:59:35 -07006238}
6239
6240// checkMixerThread_l() must be called with AudioFlinger::mLock held
Glenn Kasten72ef00d2012-01-17 11:09:42 -08006241AudioFlinger::MixerThread *AudioFlinger::checkMixerThread_l(audio_io_handle_t output) const
Mathias Agopian65ab4712010-07-14 17:59:35 -07006242{
6243 PlaybackThread *thread = checkPlaybackThread_l(output);
Glenn Kastena1117922012-01-26 10:53:32 -08006244 return thread != NULL && thread->type() != ThreadBase::DIRECT ? (MixerThread *) thread : NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006245}
6246
6247// checkRecordThread_l() must be called with AudioFlinger::mLock held
Glenn Kasten72ef00d2012-01-17 11:09:42 -08006248AudioFlinger::RecordThread *AudioFlinger::checkRecordThread_l(audio_io_handle_t input) const
Mathias Agopian65ab4712010-07-14 17:59:35 -07006249{
Glenn Kastena1117922012-01-26 10:53:32 -08006250 return mRecordThreads.valueFor(input).get();
Mathias Agopian65ab4712010-07-14 17:59:35 -07006251}
6252
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006253uint32_t AudioFlinger::nextUniqueId()
Mathias Agopian65ab4712010-07-14 17:59:35 -07006254{
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006255 return android_atomic_inc(&mNextUniqueId);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006256}
6257
Glenn Kasten02fe1bf2012-02-24 15:42:17 -08006258AudioFlinger::PlaybackThread *AudioFlinger::primaryPlaybackThread_l() const
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006259{
6260 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
6261 PlaybackThread *thread = mPlaybackThreads.valueAt(i).get();
Eric Laurentb8ba0a92011-08-07 16:32:26 -07006262 AudioStreamOut *output = thread->getOutput();
6263 if (output != NULL && output->hwDev == mPrimaryHardwareDev) {
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006264 return thread;
6265 }
6266 }
6267 return NULL;
6268}
6269
Glenn Kasten02fe1bf2012-02-24 15:42:17 -08006270uint32_t AudioFlinger::primaryOutputDevice_l() const
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006271{
6272 PlaybackThread *thread = primaryPlaybackThread_l();
6273
6274 if (thread == NULL) {
6275 return 0;
6276 }
6277
6278 return thread->device();
6279}
6280
Eric Laurenta011e352012-03-29 15:51:43 -07006281sp<AudioFlinger::SyncEvent> AudioFlinger::createSyncEvent(AudioSystem::sync_event_t type,
6282 int triggerSession,
6283 int listenerSession,
6284 sync_event_callback_t callBack,
6285 void *cookie)
6286{
6287 Mutex::Autolock _l(mLock);
6288
6289 sp<SyncEvent> event = new SyncEvent(type, triggerSession, listenerSession, callBack, cookie);
6290 status_t playStatus = NAME_NOT_FOUND;
6291 status_t recStatus = NAME_NOT_FOUND;
6292 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
6293 playStatus = mPlaybackThreads.valueAt(i)->setSyncEvent(event);
6294 if (playStatus == NO_ERROR) {
6295 return event;
6296 }
6297 }
6298 for (size_t i = 0; i < mRecordThreads.size(); i++) {
6299 recStatus = mRecordThreads.valueAt(i)->setSyncEvent(event);
6300 if (recStatus == NO_ERROR) {
6301 return event;
6302 }
6303 }
6304 if (playStatus == NAME_NOT_FOUND || recStatus == NAME_NOT_FOUND) {
6305 mPendingSyncEvents.add(event);
6306 } else {
6307 ALOGV("createSyncEvent() invalid event %d", event->type());
6308 event.clear();
6309 }
6310 return event;
6311}
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006312
Mathias Agopian65ab4712010-07-14 17:59:35 -07006313// ----------------------------------------------------------------------------
6314// Effect management
6315// ----------------------------------------------------------------------------
6316
6317
Glenn Kastenf587ba52012-01-26 16:25:10 -08006318status_t AudioFlinger::queryNumberEffects(uint32_t *numEffects) const
Mathias Agopian65ab4712010-07-14 17:59:35 -07006319{
6320 Mutex::Autolock _l(mLock);
6321 return EffectQueryNumberEffects(numEffects);
6322}
6323
Glenn Kastenf587ba52012-01-26 16:25:10 -08006324status_t AudioFlinger::queryEffect(uint32_t index, effect_descriptor_t *descriptor) const
Mathias Agopian65ab4712010-07-14 17:59:35 -07006325{
6326 Mutex::Autolock _l(mLock);
6327 return EffectQueryEffect(index, descriptor);
6328}
6329
Glenn Kasten5e92a782012-01-30 07:40:52 -08006330status_t AudioFlinger::getEffectDescriptor(const effect_uuid_t *pUuid,
Glenn Kastenf587ba52012-01-26 16:25:10 -08006331 effect_descriptor_t *descriptor) const
Mathias Agopian65ab4712010-07-14 17:59:35 -07006332{
6333 Mutex::Autolock _l(mLock);
6334 return EffectGetDescriptor(pUuid, descriptor);
6335}
6336
6337
Mathias Agopian65ab4712010-07-14 17:59:35 -07006338sp<IEffect> AudioFlinger::createEffect(pid_t pid,
6339 effect_descriptor_t *pDesc,
6340 const sp<IEffectClient>& effectClient,
6341 int32_t priority,
Glenn Kasten72ef00d2012-01-17 11:09:42 -08006342 audio_io_handle_t io,
Mathias Agopian65ab4712010-07-14 17:59:35 -07006343 int sessionId,
6344 status_t *status,
6345 int *id,
6346 int *enabled)
6347{
6348 status_t lStatus = NO_ERROR;
6349 sp<EffectHandle> handle;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006350 effect_descriptor_t desc;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006351
Glenn Kasten98ec94c2012-01-25 14:28:29 -08006352 ALOGV("createEffect pid %d, effectClient %p, priority %d, sessionId %d, io %d",
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006353 pid, effectClient.get(), priority, sessionId, io);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006354
6355 if (pDesc == NULL) {
6356 lStatus = BAD_VALUE;
6357 goto Exit;
6358 }
6359
Eric Laurent84e9a102010-09-23 16:10:16 -07006360 // check audio settings permission for global effects
Dima Zavinfce7a472011-04-19 22:30:36 -07006361 if (sessionId == AUDIO_SESSION_OUTPUT_MIX && !settingsAllowed()) {
Eric Laurent84e9a102010-09-23 16:10:16 -07006362 lStatus = PERMISSION_DENIED;
6363 goto Exit;
6364 }
6365
Dima Zavinfce7a472011-04-19 22:30:36 -07006366 // Session AUDIO_SESSION_OUTPUT_STAGE is reserved for output stage effects
Eric Laurent84e9a102010-09-23 16:10:16 -07006367 // that can only be created by audio policy manager (running in same process)
Glenn Kasten44deb052012-02-05 18:09:08 -08006368 if (sessionId == AUDIO_SESSION_OUTPUT_STAGE && getpid_cached != pid) {
Eric Laurent84e9a102010-09-23 16:10:16 -07006369 lStatus = PERMISSION_DENIED;
6370 goto Exit;
6371 }
6372
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006373 if (io == 0) {
Dima Zavinfce7a472011-04-19 22:30:36 -07006374 if (sessionId == AUDIO_SESSION_OUTPUT_STAGE) {
Eric Laurent84e9a102010-09-23 16:10:16 -07006375 // output must be specified by AudioPolicyManager when using session
Dima Zavinfce7a472011-04-19 22:30:36 -07006376 // AUDIO_SESSION_OUTPUT_STAGE
Eric Laurent84e9a102010-09-23 16:10:16 -07006377 lStatus = BAD_VALUE;
6378 goto Exit;
Dima Zavinfce7a472011-04-19 22:30:36 -07006379 } else if (sessionId == AUDIO_SESSION_OUTPUT_MIX) {
Eric Laurent84e9a102010-09-23 16:10:16 -07006380 // if the output returned by getOutputForEffect() is removed before we lock the
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006381 // mutex below, the call to checkPlaybackThread_l(io) below will detect it
Eric Laurent84e9a102010-09-23 16:10:16 -07006382 // and we will exit safely
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006383 io = AudioSystem::getOutputForEffect(&desc);
Eric Laurent84e9a102010-09-23 16:10:16 -07006384 }
6385 }
6386
Mathias Agopian65ab4712010-07-14 17:59:35 -07006387 {
6388 Mutex::Autolock _l(mLock);
6389
Mathias Agopian65ab4712010-07-14 17:59:35 -07006390
6391 if (!EffectIsNullUuid(&pDesc->uuid)) {
6392 // if uuid is specified, request effect descriptor
6393 lStatus = EffectGetDescriptor(&pDesc->uuid, &desc);
6394 if (lStatus < 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00006395 ALOGW("createEffect() error %d from EffectGetDescriptor", lStatus);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006396 goto Exit;
6397 }
6398 } else {
6399 // if uuid is not specified, look for an available implementation
6400 // of the required type in effect factory
6401 if (EffectIsNullUuid(&pDesc->type)) {
Steve Block5ff1dd52012-01-05 23:22:43 +00006402 ALOGW("createEffect() no effect type");
Mathias Agopian65ab4712010-07-14 17:59:35 -07006403 lStatus = BAD_VALUE;
6404 goto Exit;
6405 }
6406 uint32_t numEffects = 0;
6407 effect_descriptor_t d;
Marco Nelissen3a34bef2011-08-02 13:33:41 -07006408 d.flags = 0; // prevent compiler warning
Mathias Agopian65ab4712010-07-14 17:59:35 -07006409 bool found = false;
6410
6411 lStatus = EffectQueryNumberEffects(&numEffects);
6412 if (lStatus < 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00006413 ALOGW("createEffect() error %d from EffectQueryNumberEffects", lStatus);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006414 goto Exit;
6415 }
6416 for (uint32_t i = 0; i < numEffects; i++) {
6417 lStatus = EffectQueryEffect(i, &desc);
6418 if (lStatus < 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00006419 ALOGW("createEffect() error %d from EffectQueryEffect", lStatus);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006420 continue;
6421 }
6422 if (memcmp(&desc.type, &pDesc->type, sizeof(effect_uuid_t)) == 0) {
6423 // If matching type found save effect descriptor. If the session is
6424 // 0 and the effect is not auxiliary, continue enumeration in case
6425 // an auxiliary version of this effect type is available
6426 found = true;
6427 memcpy(&d, &desc, sizeof(effect_descriptor_t));
Dima Zavinfce7a472011-04-19 22:30:36 -07006428 if (sessionId != AUDIO_SESSION_OUTPUT_MIX ||
Mathias Agopian65ab4712010-07-14 17:59:35 -07006429 (desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
6430 break;
6431 }
6432 }
6433 }
6434 if (!found) {
6435 lStatus = BAD_VALUE;
Steve Block5ff1dd52012-01-05 23:22:43 +00006436 ALOGW("createEffect() effect not found");
Mathias Agopian65ab4712010-07-14 17:59:35 -07006437 goto Exit;
6438 }
6439 // For same effect type, chose auxiliary version over insert version if
6440 // connect to output mix (Compliance to OpenSL ES)
Dima Zavinfce7a472011-04-19 22:30:36 -07006441 if (sessionId == AUDIO_SESSION_OUTPUT_MIX &&
Mathias Agopian65ab4712010-07-14 17:59:35 -07006442 (d.flags & EFFECT_FLAG_TYPE_MASK) != EFFECT_FLAG_TYPE_AUXILIARY) {
6443 memcpy(&desc, &d, sizeof(effect_descriptor_t));
6444 }
6445 }
6446
6447 // Do not allow auxiliary effects on a session different from 0 (output mix)
Dima Zavinfce7a472011-04-19 22:30:36 -07006448 if (sessionId != AUDIO_SESSION_OUTPUT_MIX &&
Mathias Agopian65ab4712010-07-14 17:59:35 -07006449 (desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
6450 lStatus = INVALID_OPERATION;
6451 goto Exit;
6452 }
6453
Eric Laurent59255e42011-07-27 19:49:51 -07006454 // check recording permission for visualizer
6455 if ((memcmp(&desc.type, SL_IID_VISUALIZATION, sizeof(effect_uuid_t)) == 0) &&
6456 !recordingAllowed()) {
6457 lStatus = PERMISSION_DENIED;
6458 goto Exit;
6459 }
6460
Mathias Agopian65ab4712010-07-14 17:59:35 -07006461 // return effect descriptor
6462 memcpy(pDesc, &desc, sizeof(effect_descriptor_t));
6463
6464 // If output is not specified try to find a matching audio session ID in one of the
6465 // output threads.
Eric Laurent84e9a102010-09-23 16:10:16 -07006466 // If output is 0 here, sessionId is neither SESSION_OUTPUT_STAGE nor SESSION_OUTPUT_MIX
6467 // because of code checking output when entering the function.
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006468 // Note: io is never 0 when creating an effect on an input
6469 if (io == 0) {
Glenn Kastene53b9ea2012-03-12 16:29:55 -07006470 // look for the thread where the specified audio session is present
Eric Laurent84e9a102010-09-23 16:10:16 -07006471 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
6472 if (mPlaybackThreads.valueAt(i)->hasAudioSession(sessionId) != 0) {
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006473 io = mPlaybackThreads.keyAt(i);
Eric Laurent84e9a102010-09-23 16:10:16 -07006474 break;
Eric Laurent39e94f82010-07-28 01:32:47 -07006475 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07006476 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006477 if (io == 0) {
Glenn Kastene53b9ea2012-03-12 16:29:55 -07006478 for (size_t i = 0; i < mRecordThreads.size(); i++) {
6479 if (mRecordThreads.valueAt(i)->hasAudioSession(sessionId) != 0) {
6480 io = mRecordThreads.keyAt(i);
6481 break;
6482 }
6483 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006484 }
Eric Laurent84e9a102010-09-23 16:10:16 -07006485 // If no output thread contains the requested session ID, default to
6486 // first output. The effect chain will be moved to the correct output
6487 // thread when a track with the same session ID is created
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006488 if (io == 0 && mPlaybackThreads.size()) {
6489 io = mPlaybackThreads.keyAt(0);
6490 }
Steve Block3856b092011-10-20 11:56:00 +01006491 ALOGV("createEffect() got io %d for effect %s", io, desc.name);
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006492 }
6493 ThreadBase *thread = checkRecordThread_l(io);
6494 if (thread == NULL) {
6495 thread = checkPlaybackThread_l(io);
6496 if (thread == NULL) {
Steve Block29357bc2012-01-06 19:20:56 +00006497 ALOGE("createEffect() unknown output thread");
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006498 lStatus = BAD_VALUE;
6499 goto Exit;
Eric Laurent84e9a102010-09-23 16:10:16 -07006500 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07006501 }
Eric Laurent84e9a102010-09-23 16:10:16 -07006502
Glenn Kasten98ec94c2012-01-25 14:28:29 -08006503 sp<Client> client = registerPid_l(pid);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006504
Marco Nelissen3a34bef2011-08-02 13:33:41 -07006505 // create effect on selected output thread
Eric Laurentde070132010-07-13 04:45:46 -07006506 handle = thread->createEffect_l(client, effectClient, priority, sessionId,
6507 &desc, enabled, &lStatus);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006508 if (handle != 0 && id != NULL) {
6509 *id = handle->id();
6510 }
6511 }
6512
6513Exit:
Glenn Kastene53b9ea2012-03-12 16:29:55 -07006514 if (status != NULL) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07006515 *status = lStatus;
6516 }
6517 return handle;
6518}
6519
Glenn Kasten72ef00d2012-01-17 11:09:42 -08006520status_t AudioFlinger::moveEffects(int sessionId, audio_io_handle_t srcOutput,
6521 audio_io_handle_t dstOutput)
Eric Laurentde070132010-07-13 04:45:46 -07006522{
Steve Block3856b092011-10-20 11:56:00 +01006523 ALOGV("moveEffects() session %d, srcOutput %d, dstOutput %d",
Eric Laurent59255e42011-07-27 19:49:51 -07006524 sessionId, srcOutput, dstOutput);
Eric Laurentde070132010-07-13 04:45:46 -07006525 Mutex::Autolock _l(mLock);
6526 if (srcOutput == dstOutput) {
Steve Block5ff1dd52012-01-05 23:22:43 +00006527 ALOGW("moveEffects() same dst and src outputs %d", dstOutput);
Eric Laurentde070132010-07-13 04:45:46 -07006528 return NO_ERROR;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006529 }
Eric Laurentde070132010-07-13 04:45:46 -07006530 PlaybackThread *srcThread = checkPlaybackThread_l(srcOutput);
6531 if (srcThread == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +00006532 ALOGW("moveEffects() bad srcOutput %d", srcOutput);
Eric Laurentde070132010-07-13 04:45:46 -07006533 return BAD_VALUE;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006534 }
Eric Laurentde070132010-07-13 04:45:46 -07006535 PlaybackThread *dstThread = checkPlaybackThread_l(dstOutput);
6536 if (dstThread == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +00006537 ALOGW("moveEffects() bad dstOutput %d", dstOutput);
Eric Laurentde070132010-07-13 04:45:46 -07006538 return BAD_VALUE;
6539 }
6540
6541 Mutex::Autolock _dl(dstThread->mLock);
6542 Mutex::Autolock _sl(srcThread->mLock);
Eric Laurent59255e42011-07-27 19:49:51 -07006543 moveEffectChain_l(sessionId, srcThread, dstThread, false);
Eric Laurentde070132010-07-13 04:45:46 -07006544
Mathias Agopian65ab4712010-07-14 17:59:35 -07006545 return NO_ERROR;
6546}
6547
Marco Nelissen3a34bef2011-08-02 13:33:41 -07006548// moveEffectChain_l must be called with both srcThread and dstThread mLocks held
Eric Laurent59255e42011-07-27 19:49:51 -07006549status_t AudioFlinger::moveEffectChain_l(int sessionId,
Eric Laurentde070132010-07-13 04:45:46 -07006550 AudioFlinger::PlaybackThread *srcThread,
Eric Laurent39e94f82010-07-28 01:32:47 -07006551 AudioFlinger::PlaybackThread *dstThread,
6552 bool reRegister)
Eric Laurentde070132010-07-13 04:45:46 -07006553{
Steve Block3856b092011-10-20 11:56:00 +01006554 ALOGV("moveEffectChain_l() session %d from thread %p to thread %p",
Eric Laurent59255e42011-07-27 19:49:51 -07006555 sessionId, srcThread, dstThread);
Eric Laurentde070132010-07-13 04:45:46 -07006556
Eric Laurent59255e42011-07-27 19:49:51 -07006557 sp<EffectChain> chain = srcThread->getEffectChain_l(sessionId);
Eric Laurentde070132010-07-13 04:45:46 -07006558 if (chain == 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00006559 ALOGW("moveEffectChain_l() effect chain for session %d not on source thread %p",
Eric Laurent59255e42011-07-27 19:49:51 -07006560 sessionId, srcThread);
Eric Laurentde070132010-07-13 04:45:46 -07006561 return INVALID_OPERATION;
6562 }
6563
Eric Laurent39e94f82010-07-28 01:32:47 -07006564 // remove chain first. This is useful only if reconfiguring effect chain on same output thread,
Eric Laurentde070132010-07-13 04:45:46 -07006565 // so that a new chain is created with correct parameters when first effect is added. This is
Eric Laurentec35a142011-10-05 17:42:25 -07006566 // otherwise unnecessary as removeEffect_l() will remove the chain when last effect is
Eric Laurentde070132010-07-13 04:45:46 -07006567 // removed.
6568 srcThread->removeEffectChain_l(chain);
6569
6570 // transfer all effects one by one so that new effect chain is created on new thread with
6571 // correct buffer sizes and audio parameters and effect engines reconfigured accordingly
Glenn Kasten72ef00d2012-01-17 11:09:42 -08006572 audio_io_handle_t dstOutput = dstThread->id();
Eric Laurent39e94f82010-07-28 01:32:47 -07006573 sp<EffectChain> dstChain;
Marco Nelissen3a34bef2011-08-02 13:33:41 -07006574 uint32_t strategy = 0; // prevent compiler warning
Eric Laurentde070132010-07-13 04:45:46 -07006575 sp<EffectModule> effect = chain->getEffectFromId_l(0);
6576 while (effect != 0) {
6577 srcThread->removeEffect_l(effect);
6578 dstThread->addEffect_l(effect);
Eric Laurentec35a142011-10-05 17:42:25 -07006579 // removeEffect_l() has stopped the effect if it was active so it must be restarted
6580 if (effect->state() == EffectModule::ACTIVE ||
6581 effect->state() == EffectModule::STOPPING) {
6582 effect->start();
6583 }
Eric Laurent39e94f82010-07-28 01:32:47 -07006584 // if the move request is not received from audio policy manager, the effect must be
6585 // re-registered with the new strategy and output
6586 if (dstChain == 0) {
6587 dstChain = effect->chain().promote();
6588 if (dstChain == 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00006589 ALOGW("moveEffectChain_l() cannot get chain from effect %p", effect.get());
Eric Laurent39e94f82010-07-28 01:32:47 -07006590 srcThread->addEffect_l(effect);
6591 return NO_INIT;
6592 }
6593 strategy = dstChain->strategy();
6594 }
6595 if (reRegister) {
6596 AudioSystem::unregisterEffect(effect->id());
6597 AudioSystem::registerEffect(&effect->desc(),
6598 dstOutput,
6599 strategy,
Eric Laurent59255e42011-07-27 19:49:51 -07006600 sessionId,
Eric Laurent39e94f82010-07-28 01:32:47 -07006601 effect->id());
6602 }
Eric Laurentde070132010-07-13 04:45:46 -07006603 effect = chain->getEffectFromId_l(0);
6604 }
6605
6606 return NO_ERROR;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006607}
6608
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006609
Mathias Agopian65ab4712010-07-14 17:59:35 -07006610// PlaybackThread::createEffect_l() must be called with AudioFlinger::mLock held
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006611sp<AudioFlinger::EffectHandle> AudioFlinger::ThreadBase::createEffect_l(
Mathias Agopian65ab4712010-07-14 17:59:35 -07006612 const sp<AudioFlinger::Client>& client,
6613 const sp<IEffectClient>& effectClient,
6614 int32_t priority,
6615 int sessionId,
6616 effect_descriptor_t *desc,
6617 int *enabled,
6618 status_t *status
6619 )
6620{
6621 sp<EffectModule> effect;
6622 sp<EffectHandle> handle;
6623 status_t lStatus;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006624 sp<EffectChain> chain;
Eric Laurentde070132010-07-13 04:45:46 -07006625 bool chainCreated = false;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006626 bool effectCreated = false;
6627 bool effectRegistered = false;
6628
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006629 lStatus = initCheck();
6630 if (lStatus != NO_ERROR) {
Steve Block5ff1dd52012-01-05 23:22:43 +00006631 ALOGW("createEffect_l() Audio driver not initialized.");
Mathias Agopian65ab4712010-07-14 17:59:35 -07006632 goto Exit;
6633 }
6634
6635 // Do not allow effects with session ID 0 on direct output or duplicating threads
6636 // TODO: add rule for hw accelerated effects on direct outputs with non PCM format
Dima Zavinfce7a472011-04-19 22:30:36 -07006637 if (sessionId == AUDIO_SESSION_OUTPUT_MIX && mType != MIXER) {
Steve Block5ff1dd52012-01-05 23:22:43 +00006638 ALOGW("createEffect_l() Cannot add auxiliary effect %s to session %d",
Eric Laurentde070132010-07-13 04:45:46 -07006639 desc->name, sessionId);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006640 lStatus = BAD_VALUE;
6641 goto Exit;
6642 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006643 // Only Pre processor effects are allowed on input threads and only on input threads
Glenn Kastena1117922012-01-26 10:53:32 -08006644 if ((mType == RECORD) != ((desc->flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC)) {
Steve Block5ff1dd52012-01-05 23:22:43 +00006645 ALOGW("createEffect_l() effect %s (flags %08x) created on wrong thread type %d",
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006646 desc->name, desc->flags, mType);
6647 lStatus = BAD_VALUE;
6648 goto Exit;
6649 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07006650
Steve Block3856b092011-10-20 11:56:00 +01006651 ALOGV("createEffect_l() thread %p effect %s on session %d", this, desc->name, sessionId);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006652
6653 { // scope for mLock
6654 Mutex::Autolock _l(mLock);
6655
6656 // check for existing effect chain with the requested audio session
6657 chain = getEffectChain_l(sessionId);
6658 if (chain == 0) {
6659 // create a new chain for this session
Steve Block3856b092011-10-20 11:56:00 +01006660 ALOGV("createEffect_l() new effect chain for session %d", sessionId);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006661 chain = new EffectChain(this, sessionId);
6662 addEffectChain_l(chain);
Eric Laurentde070132010-07-13 04:45:46 -07006663 chain->setStrategy(getStrategyForSession_l(sessionId));
6664 chainCreated = true;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006665 } else {
Eric Laurentcab11242010-07-15 12:50:15 -07006666 effect = chain->getEffectFromDesc_l(desc);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006667 }
6668
Glenn Kasten7fc9a6f2012-01-10 10:46:34 -08006669 ALOGV("createEffect_l() got effect %p on chain %p", effect.get(), chain.get());
Mathias Agopian65ab4712010-07-14 17:59:35 -07006670
6671 if (effect == 0) {
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006672 int id = mAudioFlinger->nextUniqueId();
Mathias Agopian65ab4712010-07-14 17:59:35 -07006673 // Check CPU and memory usage
Eric Laurentde070132010-07-13 04:45:46 -07006674 lStatus = AudioSystem::registerEffect(desc, mId, chain->strategy(), sessionId, id);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006675 if (lStatus != NO_ERROR) {
6676 goto Exit;
6677 }
6678 effectRegistered = true;
6679 // create a new effect module if none present in the chain
Eric Laurentde070132010-07-13 04:45:46 -07006680 effect = new EffectModule(this, chain, desc, id, sessionId);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006681 lStatus = effect->status();
6682 if (lStatus != NO_ERROR) {
6683 goto Exit;
6684 }
Eric Laurentcab11242010-07-15 12:50:15 -07006685 lStatus = chain->addEffect_l(effect);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006686 if (lStatus != NO_ERROR) {
6687 goto Exit;
6688 }
6689 effectCreated = true;
6690
6691 effect->setDevice(mDevice);
6692 effect->setMode(mAudioFlinger->getMode());
6693 }
6694 // create effect handle and connect it to effect module
6695 handle = new EffectHandle(effect, client, effectClient, priority);
6696 lStatus = effect->addHandle(handle);
Glenn Kastena0d68332012-01-27 16:47:15 -08006697 if (enabled != NULL) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07006698 *enabled = (int)effect->isEnabled();
6699 }
6700 }
6701
6702Exit:
6703 if (lStatus != NO_ERROR && lStatus != ALREADY_EXISTS) {
Eric Laurentde070132010-07-13 04:45:46 -07006704 Mutex::Autolock _l(mLock);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006705 if (effectCreated) {
Eric Laurentde070132010-07-13 04:45:46 -07006706 chain->removeEffect_l(effect);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006707 }
6708 if (effectRegistered) {
Eric Laurentde070132010-07-13 04:45:46 -07006709 AudioSystem::unregisterEffect(effect->id());
6710 }
6711 if (chainCreated) {
6712 removeEffectChain_l(chain);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006713 }
6714 handle.clear();
6715 }
6716
Glenn Kastene53b9ea2012-03-12 16:29:55 -07006717 if (status != NULL) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07006718 *status = lStatus;
6719 }
6720 return handle;
6721}
6722
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006723sp<AudioFlinger::EffectModule> AudioFlinger::ThreadBase::getEffect_l(int sessionId, int effectId)
6724{
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006725 sp<EffectChain> chain = getEffectChain_l(sessionId);
Glenn Kasten090f0192012-01-30 13:00:02 -08006726 return chain != 0 ? chain->getEffectFromId_l(effectId) : 0;
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006727}
6728
Eric Laurentde070132010-07-13 04:45:46 -07006729// PlaybackThread::addEffect_l() must be called with AudioFlinger::mLock and
6730// PlaybackThread::mLock held
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006731status_t AudioFlinger::ThreadBase::addEffect_l(const sp<EffectModule>& effect)
Eric Laurentde070132010-07-13 04:45:46 -07006732{
6733 // check for existing effect chain with the requested audio session
6734 int sessionId = effect->sessionId();
6735 sp<EffectChain> chain = getEffectChain_l(sessionId);
6736 bool chainCreated = false;
6737
6738 if (chain == 0) {
6739 // create a new chain for this session
Steve Block3856b092011-10-20 11:56:00 +01006740 ALOGV("addEffect_l() new effect chain for session %d", sessionId);
Eric Laurentde070132010-07-13 04:45:46 -07006741 chain = new EffectChain(this, sessionId);
6742 addEffectChain_l(chain);
6743 chain->setStrategy(getStrategyForSession_l(sessionId));
6744 chainCreated = true;
6745 }
Steve Block3856b092011-10-20 11:56:00 +01006746 ALOGV("addEffect_l() %p chain %p effect %p", this, chain.get(), effect.get());
Eric Laurentde070132010-07-13 04:45:46 -07006747
6748 if (chain->getEffectFromId_l(effect->id()) != 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00006749 ALOGW("addEffect_l() %p effect %s already present in chain %p",
Eric Laurentde070132010-07-13 04:45:46 -07006750 this, effect->desc().name, chain.get());
6751 return BAD_VALUE;
6752 }
6753
6754 status_t status = chain->addEffect_l(effect);
6755 if (status != NO_ERROR) {
6756 if (chainCreated) {
6757 removeEffectChain_l(chain);
6758 }
6759 return status;
6760 }
6761
6762 effect->setDevice(mDevice);
6763 effect->setMode(mAudioFlinger->getMode());
6764 return NO_ERROR;
6765}
6766
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006767void AudioFlinger::ThreadBase::removeEffect_l(const sp<EffectModule>& effect) {
Eric Laurentde070132010-07-13 04:45:46 -07006768
Steve Block3856b092011-10-20 11:56:00 +01006769 ALOGV("removeEffect_l() %p effect %p", this, effect.get());
Mathias Agopian65ab4712010-07-14 17:59:35 -07006770 effect_descriptor_t desc = effect->desc();
Eric Laurentde070132010-07-13 04:45:46 -07006771 if ((desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
6772 detachAuxEffect_l(effect->id());
6773 }
6774
6775 sp<EffectChain> chain = effect->chain().promote();
6776 if (chain != 0) {
6777 // remove effect chain if removing last effect
6778 if (chain->removeEffect_l(effect) == 0) {
6779 removeEffectChain_l(chain);
6780 }
6781 } else {
Steve Block5ff1dd52012-01-05 23:22:43 +00006782 ALOGW("removeEffect_l() %p cannot promote chain for effect %p", this, effect.get());
Eric Laurentde070132010-07-13 04:45:46 -07006783 }
6784}
6785
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006786void AudioFlinger::ThreadBase::lockEffectChains_l(
Glenn Kastene53b9ea2012-03-12 16:29:55 -07006787 Vector< sp<AudioFlinger::EffectChain> >& effectChains)
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006788{
6789 effectChains = mEffectChains;
6790 for (size_t i = 0; i < mEffectChains.size(); i++) {
6791 mEffectChains[i]->lock();
6792 }
6793}
6794
6795void AudioFlinger::ThreadBase::unlockEffectChains(
Glenn Kastene53b9ea2012-03-12 16:29:55 -07006796 const Vector< sp<AudioFlinger::EffectChain> >& effectChains)
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006797{
6798 for (size_t i = 0; i < effectChains.size(); i++) {
6799 effectChains[i]->unlock();
6800 }
6801}
6802
6803sp<AudioFlinger::EffectChain> AudioFlinger::ThreadBase::getEffectChain(int sessionId)
6804{
6805 Mutex::Autolock _l(mLock);
6806 return getEffectChain_l(sessionId);
6807}
6808
6809sp<AudioFlinger::EffectChain> AudioFlinger::ThreadBase::getEffectChain_l(int sessionId)
6810{
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006811 size_t size = mEffectChains.size();
6812 for (size_t i = 0; i < size; i++) {
6813 if (mEffectChains[i]->sessionId() == sessionId) {
Glenn Kasten090f0192012-01-30 13:00:02 -08006814 return mEffectChains[i];
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006815 }
6816 }
Glenn Kasten090f0192012-01-30 13:00:02 -08006817 return 0;
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006818}
6819
Glenn Kastenf78aee72012-01-04 11:00:47 -08006820void AudioFlinger::ThreadBase::setMode(audio_mode_t mode)
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006821{
6822 Mutex::Autolock _l(mLock);
6823 size_t size = mEffectChains.size();
6824 for (size_t i = 0; i < size; i++) {
6825 mEffectChains[i]->setMode_l(mode);
6826 }
6827}
6828
6829void AudioFlinger::ThreadBase::disconnectEffect(const sp<EffectModule>& effect,
Marco Nelissen3a34bef2011-08-02 13:33:41 -07006830 const wp<EffectHandle>& handle,
Glenn Kasten58123c32012-02-03 10:32:24 -08006831 bool unpinIfLast) {
Eric Laurent59255e42011-07-27 19:49:51 -07006832
Mathias Agopian65ab4712010-07-14 17:59:35 -07006833 Mutex::Autolock _l(mLock);
Steve Block3856b092011-10-20 11:56:00 +01006834 ALOGV("disconnectEffect() %p effect %p", this, effect.get());
Mathias Agopian65ab4712010-07-14 17:59:35 -07006835 // delete the effect module if removing last handle on it
6836 if (effect->removeHandle(handle) == 0) {
Glenn Kasten58123c32012-02-03 10:32:24 -08006837 if (!effect->isPinned() || unpinIfLast) {
Marco Nelissen3a34bef2011-08-02 13:33:41 -07006838 removeEffect_l(effect);
6839 AudioSystem::unregisterEffect(effect->id());
6840 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07006841 }
6842}
6843
6844status_t AudioFlinger::PlaybackThread::addEffectChain_l(const sp<EffectChain>& chain)
6845{
6846 int session = chain->sessionId();
6847 int16_t *buffer = mMixBuffer;
6848 bool ownsBuffer = false;
6849
Steve Block3856b092011-10-20 11:56:00 +01006850 ALOGV("addEffectChain_l() %p on thread %p for session %d", chain.get(), this, session);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006851 if (session > 0) {
6852 // Only one effect chain can be present in direct output thread and it uses
6853 // the mix buffer as input
6854 if (mType != DIRECT) {
6855 size_t numSamples = mFrameCount * mChannelCount;
6856 buffer = new int16_t[numSamples];
6857 memset(buffer, 0, numSamples * sizeof(int16_t));
Steve Block3856b092011-10-20 11:56:00 +01006858 ALOGV("addEffectChain_l() creating new input buffer %p session %d", buffer, session);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006859 ownsBuffer = true;
6860 }
6861
6862 // Attach all tracks with same session ID to this chain.
6863 for (size_t i = 0; i < mTracks.size(); ++i) {
6864 sp<Track> track = mTracks[i];
6865 if (session == track->sessionId()) {
Steve Block3856b092011-10-20 11:56:00 +01006866 ALOGV("addEffectChain_l() track->setMainBuffer track %p buffer %p", track.get(), buffer);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006867 track->setMainBuffer(buffer);
Eric Laurentb469b942011-05-09 12:09:06 -07006868 chain->incTrackCnt();
Mathias Agopian65ab4712010-07-14 17:59:35 -07006869 }
6870 }
6871
6872 // indicate all active tracks in the chain
6873 for (size_t i = 0 ; i < mActiveTracks.size() ; ++i) {
6874 sp<Track> track = mActiveTracks[i].promote();
6875 if (track == 0) continue;
6876 if (session == track->sessionId()) {
Steve Block3856b092011-10-20 11:56:00 +01006877 ALOGV("addEffectChain_l() activating track %p on session %d", track.get(), session);
Eric Laurentb469b942011-05-09 12:09:06 -07006878 chain->incActiveTrackCnt();
Mathias Agopian65ab4712010-07-14 17:59:35 -07006879 }
6880 }
6881 }
6882
6883 chain->setInBuffer(buffer, ownsBuffer);
6884 chain->setOutBuffer(mMixBuffer);
Dima Zavinfce7a472011-04-19 22:30:36 -07006885 // Effect chain for session AUDIO_SESSION_OUTPUT_STAGE is inserted at end of effect
Eric Laurentde070132010-07-13 04:45:46 -07006886 // chains list in order to be processed last as it contains output stage effects
Dima Zavinfce7a472011-04-19 22:30:36 -07006887 // Effect chain for session AUDIO_SESSION_OUTPUT_MIX is inserted before
6888 // session AUDIO_SESSION_OUTPUT_STAGE to be processed
Mathias Agopian65ab4712010-07-14 17:59:35 -07006889 // after track specific effects and before output stage
Dima Zavinfce7a472011-04-19 22:30:36 -07006890 // It is therefore mandatory that AUDIO_SESSION_OUTPUT_MIX == 0 and
6891 // that AUDIO_SESSION_OUTPUT_STAGE < AUDIO_SESSION_OUTPUT_MIX
Eric Laurentde070132010-07-13 04:45:46 -07006892 // Effect chain for other sessions are inserted at beginning of effect
6893 // chains list to be processed before output mix effects. Relative order between other
6894 // sessions is not important
Mathias Agopian65ab4712010-07-14 17:59:35 -07006895 size_t size = mEffectChains.size();
6896 size_t i = 0;
6897 for (i = 0; i < size; i++) {
6898 if (mEffectChains[i]->sessionId() < session) break;
6899 }
6900 mEffectChains.insertAt(chain, i);
Eric Laurent59255e42011-07-27 19:49:51 -07006901 checkSuspendOnAddEffectChain_l(chain);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006902
6903 return NO_ERROR;
6904}
6905
6906size_t AudioFlinger::PlaybackThread::removeEffectChain_l(const sp<EffectChain>& chain)
6907{
6908 int session = chain->sessionId();
6909
Steve Block3856b092011-10-20 11:56:00 +01006910 ALOGV("removeEffectChain_l() %p from thread %p for session %d", chain.get(), this, session);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006911
6912 for (size_t i = 0; i < mEffectChains.size(); i++) {
6913 if (chain == mEffectChains[i]) {
6914 mEffectChains.removeAt(i);
Eric Laurentb469b942011-05-09 12:09:06 -07006915 // detach all active tracks from the chain
6916 for (size_t i = 0 ; i < mActiveTracks.size() ; ++i) {
6917 sp<Track> track = mActiveTracks[i].promote();
6918 if (track == 0) continue;
6919 if (session == track->sessionId()) {
Steve Block3856b092011-10-20 11:56:00 +01006920 ALOGV("removeEffectChain_l(): stopping track on chain %p for session Id: %d",
Eric Laurentb469b942011-05-09 12:09:06 -07006921 chain.get(), session);
6922 chain->decActiveTrackCnt();
6923 }
6924 }
6925
Mathias Agopian65ab4712010-07-14 17:59:35 -07006926 // detach all tracks with same session ID from this chain
6927 for (size_t i = 0; i < mTracks.size(); ++i) {
6928 sp<Track> track = mTracks[i];
6929 if (session == track->sessionId()) {
6930 track->setMainBuffer(mMixBuffer);
Eric Laurentb469b942011-05-09 12:09:06 -07006931 chain->decTrackCnt();
Mathias Agopian65ab4712010-07-14 17:59:35 -07006932 }
6933 }
Eric Laurentde070132010-07-13 04:45:46 -07006934 break;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006935 }
6936 }
6937 return mEffectChains.size();
6938}
6939
Eric Laurentde070132010-07-13 04:45:46 -07006940status_t AudioFlinger::PlaybackThread::attachAuxEffect(
6941 const sp<AudioFlinger::PlaybackThread::Track> track, int EffectId)
Mathias Agopian65ab4712010-07-14 17:59:35 -07006942{
6943 Mutex::Autolock _l(mLock);
6944 return attachAuxEffect_l(track, EffectId);
6945}
6946
Eric Laurentde070132010-07-13 04:45:46 -07006947status_t AudioFlinger::PlaybackThread::attachAuxEffect_l(
6948 const sp<AudioFlinger::PlaybackThread::Track> track, int EffectId)
Mathias Agopian65ab4712010-07-14 17:59:35 -07006949{
6950 status_t status = NO_ERROR;
6951
6952 if (EffectId == 0) {
6953 track->setAuxBuffer(0, NULL);
6954 } else {
Dima Zavinfce7a472011-04-19 22:30:36 -07006955 // Auxiliary effects are always in audio session AUDIO_SESSION_OUTPUT_MIX
6956 sp<EffectModule> effect = getEffect_l(AUDIO_SESSION_OUTPUT_MIX, EffectId);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006957 if (effect != 0) {
6958 if ((effect->desc().flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
6959 track->setAuxBuffer(EffectId, (int32_t *)effect->inBuffer());
6960 } else {
6961 status = INVALID_OPERATION;
6962 }
6963 } else {
6964 status = BAD_VALUE;
6965 }
6966 }
6967 return status;
6968}
6969
6970void AudioFlinger::PlaybackThread::detachAuxEffect_l(int effectId)
6971{
Glenn Kastene53b9ea2012-03-12 16:29:55 -07006972 for (size_t i = 0; i < mTracks.size(); ++i) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07006973 sp<Track> track = mTracks[i];
6974 if (track->auxEffectId() == effectId) {
6975 attachAuxEffect_l(track, 0);
6976 }
6977 }
6978}
6979
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006980status_t AudioFlinger::RecordThread::addEffectChain_l(const sp<EffectChain>& chain)
6981{
6982 // only one chain per input thread
6983 if (mEffectChains.size() != 0) {
6984 return INVALID_OPERATION;
6985 }
Steve Block3856b092011-10-20 11:56:00 +01006986 ALOGV("addEffectChain_l() %p on thread %p", chain.get(), this);
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006987
6988 chain->setInBuffer(NULL);
6989 chain->setOutBuffer(NULL);
6990
Eric Laurent59255e42011-07-27 19:49:51 -07006991 checkSuspendOnAddEffectChain_l(chain);
6992
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006993 mEffectChains.add(chain);
6994
6995 return NO_ERROR;
6996}
6997
6998size_t AudioFlinger::RecordThread::removeEffectChain_l(const sp<EffectChain>& chain)
6999{
Steve Block3856b092011-10-20 11:56:00 +01007000 ALOGV("removeEffectChain_l() %p from thread %p", chain.get(), this);
Steve Block5ff1dd52012-01-05 23:22:43 +00007001 ALOGW_IF(mEffectChains.size() != 1,
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007002 "removeEffectChain_l() %p invalid chain size %d on thread %p",
7003 chain.get(), mEffectChains.size(), this);
7004 if (mEffectChains.size() == 1) {
7005 mEffectChains.removeAt(0);
7006 }
7007 return 0;
7008}
7009
Mathias Agopian65ab4712010-07-14 17:59:35 -07007010// ----------------------------------------------------------------------------
7011// EffectModule implementation
7012// ----------------------------------------------------------------------------
7013
7014#undef LOG_TAG
7015#define LOG_TAG "AudioFlinger::EffectModule"
7016
Glenn Kasten9eaa5572012-01-20 13:32:16 -08007017AudioFlinger::EffectModule::EffectModule(ThreadBase *thread,
Mathias Agopian65ab4712010-07-14 17:59:35 -07007018 const wp<AudioFlinger::EffectChain>& chain,
7019 effect_descriptor_t *desc,
7020 int id,
7021 int sessionId)
Glenn Kasten9eaa5572012-01-20 13:32:16 -08007022 : mThread(thread), mChain(chain), mId(id), mSessionId(sessionId), mEffectInterface(NULL),
Eric Laurent59255e42011-07-27 19:49:51 -07007023 mStatus(NO_INIT), mState(IDLE), mSuspended(false)
Mathias Agopian65ab4712010-07-14 17:59:35 -07007024{
Steve Block3856b092011-10-20 11:56:00 +01007025 ALOGV("Constructor %p", this);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007026 int lStatus;
Glenn Kasten9eaa5572012-01-20 13:32:16 -08007027 if (thread == NULL) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07007028 return;
7029 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07007030
7031 memcpy(&mDescriptor, desc, sizeof(effect_descriptor_t));
7032
7033 // create effect engine from effect factory
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007034 mStatus = EffectCreate(&desc->uuid, sessionId, thread->id(), &mEffectInterface);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007035
7036 if (mStatus != NO_ERROR) {
7037 return;
7038 }
7039 lStatus = init();
7040 if (lStatus < 0) {
7041 mStatus = lStatus;
7042 goto Error;
7043 }
7044
Marco Nelissen3a34bef2011-08-02 13:33:41 -07007045 if (mSessionId > AUDIO_SESSION_OUTPUT_MIX) {
7046 mPinned = true;
7047 }
Steve Block3856b092011-10-20 11:56:00 +01007048 ALOGV("Constructor success name %s, Interface %p", mDescriptor.name, mEffectInterface);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007049 return;
7050Error:
7051 EffectRelease(mEffectInterface);
7052 mEffectInterface = NULL;
Steve Block3856b092011-10-20 11:56:00 +01007053 ALOGV("Constructor Error %d", mStatus);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007054}
7055
7056AudioFlinger::EffectModule::~EffectModule()
7057{
Steve Block3856b092011-10-20 11:56:00 +01007058 ALOGV("Destructor %p", this);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007059 if (mEffectInterface != NULL) {
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007060 if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC ||
7061 (mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_POST_PROC) {
7062 sp<ThreadBase> thread = mThread.promote();
7063 if (thread != 0) {
Eric Laurentb8ba0a92011-08-07 16:32:26 -07007064 audio_stream_t *stream = thread->stream();
7065 if (stream != NULL) {
7066 stream->remove_audio_effect(stream, mEffectInterface);
7067 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007068 }
7069 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07007070 // release effect engine
7071 EffectRelease(mEffectInterface);
7072 }
7073}
7074
Glenn Kasten435dbe62012-01-30 10:15:48 -08007075status_t AudioFlinger::EffectModule::addHandle(const sp<EffectHandle>& handle)
Mathias Agopian65ab4712010-07-14 17:59:35 -07007076{
7077 status_t status;
7078
7079 Mutex::Autolock _l(mLock);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007080 int priority = handle->priority();
7081 size_t size = mHandles.size();
7082 sp<EffectHandle> h;
7083 size_t i;
7084 for (i = 0; i < size; i++) {
7085 h = mHandles[i].promote();
7086 if (h == 0) continue;
7087 if (h->priority() <= priority) break;
7088 }
7089 // if inserted in first place, move effect control from previous owner to this handle
7090 if (i == 0) {
Eric Laurent59255e42011-07-27 19:49:51 -07007091 bool enabled = false;
Mathias Agopian65ab4712010-07-14 17:59:35 -07007092 if (h != 0) {
Eric Laurent59255e42011-07-27 19:49:51 -07007093 enabled = h->enabled();
7094 h->setControl(false/*hasControl*/, true /*signal*/, enabled /*enabled*/);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007095 }
Eric Laurent59255e42011-07-27 19:49:51 -07007096 handle->setControl(true /*hasControl*/, false /*signal*/, enabled /*enabled*/);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007097 status = NO_ERROR;
7098 } else {
7099 status = ALREADY_EXISTS;
7100 }
Steve Block3856b092011-10-20 11:56:00 +01007101 ALOGV("addHandle() %p added handle %p in position %d", this, handle.get(), i);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007102 mHandles.insertAt(handle, i);
7103 return status;
7104}
7105
7106size_t AudioFlinger::EffectModule::removeHandle(const wp<EffectHandle>& handle)
7107{
7108 Mutex::Autolock _l(mLock);
7109 size_t size = mHandles.size();
7110 size_t i;
7111 for (i = 0; i < size; i++) {
7112 if (mHandles[i] == handle) break;
7113 }
7114 if (i == size) {
7115 return size;
7116 }
Steve Block3856b092011-10-20 11:56:00 +01007117 ALOGV("removeHandle() %p removed handle %p in position %d", this, handle.unsafe_get(), i);
Eric Laurent59255e42011-07-27 19:49:51 -07007118
7119 bool enabled = false;
7120 EffectHandle *hdl = handle.unsafe_get();
Glenn Kastena0d68332012-01-27 16:47:15 -08007121 if (hdl != NULL) {
Steve Block3856b092011-10-20 11:56:00 +01007122 ALOGV("removeHandle() unsafe_get OK");
Eric Laurent59255e42011-07-27 19:49:51 -07007123 enabled = hdl->enabled();
7124 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07007125 mHandles.removeAt(i);
7126 size = mHandles.size();
7127 // if removed from first place, move effect control from this handle to next in line
7128 if (i == 0 && size != 0) {
7129 sp<EffectHandle> h = mHandles[0].promote();
7130 if (h != 0) {
Eric Laurent59255e42011-07-27 19:49:51 -07007131 h->setControl(true /*hasControl*/, true /*signal*/ , enabled /*enabled*/);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007132 }
7133 }
7134
Eric Laurentec437d82011-07-26 20:54:46 -07007135 // Prevent calls to process() and other functions on effect interface from now on.
7136 // The effect engine will be released by the destructor when the last strong reference on
7137 // this object is released which can happen after next process is called.
Marco Nelissen3a34bef2011-08-02 13:33:41 -07007138 if (size == 0 && !mPinned) {
Eric Laurentec437d82011-07-26 20:54:46 -07007139 mState = DESTROYED;
Eric Laurentdac69112010-09-28 14:09:57 -07007140 }
7141
Mathias Agopian65ab4712010-07-14 17:59:35 -07007142 return size;
7143}
7144
Eric Laurent59255e42011-07-27 19:49:51 -07007145sp<AudioFlinger::EffectHandle> AudioFlinger::EffectModule::controlHandle()
7146{
7147 Mutex::Autolock _l(mLock);
Glenn Kasten090f0192012-01-30 13:00:02 -08007148 return mHandles.size() != 0 ? mHandles[0].promote() : 0;
Eric Laurent59255e42011-07-27 19:49:51 -07007149}
7150
Glenn Kasten58123c32012-02-03 10:32:24 -08007151void AudioFlinger::EffectModule::disconnect(const wp<EffectHandle>& handle, bool unpinIfLast)
Mathias Agopian65ab4712010-07-14 17:59:35 -07007152{
Glenn Kasten90bebef2012-01-27 15:24:38 -08007153 ALOGV("disconnect() %p handle %p", this, handle.unsafe_get());
Mathias Agopian65ab4712010-07-14 17:59:35 -07007154 // keep a strong reference on this EffectModule to avoid calling the
7155 // destructor before we exit
7156 sp<EffectModule> keep(this);
7157 {
7158 sp<ThreadBase> thread = mThread.promote();
7159 if (thread != 0) {
Glenn Kasten58123c32012-02-03 10:32:24 -08007160 thread->disconnectEffect(keep, handle, unpinIfLast);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007161 }
7162 }
7163}
7164
7165void AudioFlinger::EffectModule::updateState() {
7166 Mutex::Autolock _l(mLock);
7167
7168 switch (mState) {
7169 case RESTART:
7170 reset_l();
7171 // FALL THROUGH
7172
7173 case STARTING:
7174 // clear auxiliary effect input buffer for next accumulation
7175 if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
7176 memset(mConfig.inputCfg.buffer.raw,
7177 0,
7178 mConfig.inputCfg.buffer.frameCount*sizeof(int32_t));
7179 }
7180 start_l();
7181 mState = ACTIVE;
7182 break;
7183 case STOPPING:
7184 stop_l();
7185 mDisableWaitCnt = mMaxDisableWaitCnt;
7186 mState = STOPPED;
7187 break;
7188 case STOPPED:
7189 // mDisableWaitCnt is forced to 1 by process() when the engine indicates the end of the
7190 // turn off sequence.
7191 if (--mDisableWaitCnt == 0) {
7192 reset_l();
7193 mState = IDLE;
7194 }
7195 break;
Eric Laurentec437d82011-07-26 20:54:46 -07007196 default: //IDLE , ACTIVE, DESTROYED
Mathias Agopian65ab4712010-07-14 17:59:35 -07007197 break;
7198 }
7199}
7200
7201void AudioFlinger::EffectModule::process()
7202{
7203 Mutex::Autolock _l(mLock);
7204
Eric Laurentec437d82011-07-26 20:54:46 -07007205 if (mState == DESTROYED || mEffectInterface == NULL ||
Mathias Agopian65ab4712010-07-14 17:59:35 -07007206 mConfig.inputCfg.buffer.raw == NULL ||
7207 mConfig.outputCfg.buffer.raw == NULL) {
7208 return;
7209 }
7210
Eric Laurent8f45bd72010-08-31 13:50:07 -07007211 if (isProcessEnabled()) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07007212 // do 32 bit to 16 bit conversion for auxiliary effect input buffer
7213 if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
Glenn Kasten3b21c502011-12-15 09:52:39 -08007214 ditherAndClamp(mConfig.inputCfg.buffer.s32,
Mathias Agopian65ab4712010-07-14 17:59:35 -07007215 mConfig.inputCfg.buffer.s32,
Eric Laurentde070132010-07-13 04:45:46 -07007216 mConfig.inputCfg.buffer.frameCount/2);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007217 }
7218
7219 // do the actual processing in the effect engine
7220 int ret = (*mEffectInterface)->process(mEffectInterface,
7221 &mConfig.inputCfg.buffer,
7222 &mConfig.outputCfg.buffer);
7223
7224 // force transition to IDLE state when engine is ready
7225 if (mState == STOPPED && ret == -ENODATA) {
7226 mDisableWaitCnt = 1;
7227 }
7228
7229 // clear auxiliary effect input buffer for next accumulation
7230 if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
Eric Laurent73337482011-01-19 18:36:13 -08007231 memset(mConfig.inputCfg.buffer.raw, 0,
7232 mConfig.inputCfg.buffer.frameCount*sizeof(int32_t));
Mathias Agopian65ab4712010-07-14 17:59:35 -07007233 }
7234 } else if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_INSERT &&
Eric Laurent73337482011-01-19 18:36:13 -08007235 mConfig.inputCfg.buffer.raw != mConfig.outputCfg.buffer.raw) {
7236 // If an insert effect is idle and input buffer is different from output buffer,
7237 // accumulate input onto output
Mathias Agopian65ab4712010-07-14 17:59:35 -07007238 sp<EffectChain> chain = mChain.promote();
Eric Laurentb469b942011-05-09 12:09:06 -07007239 if (chain != 0 && chain->activeTrackCnt() != 0) {
Eric Laurent73337482011-01-19 18:36:13 -08007240 size_t frameCnt = mConfig.inputCfg.buffer.frameCount * 2; //always stereo here
7241 int16_t *in = mConfig.inputCfg.buffer.s16;
7242 int16_t *out = mConfig.outputCfg.buffer.s16;
7243 for (size_t i = 0; i < frameCnt; i++) {
7244 out[i] = clamp16((int32_t)out[i] + (int32_t)in[i]);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007245 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07007246 }
7247 }
7248}
7249
7250void AudioFlinger::EffectModule::reset_l()
7251{
7252 if (mEffectInterface == NULL) {
7253 return;
7254 }
7255 (*mEffectInterface)->command(mEffectInterface, EFFECT_CMD_RESET, 0, NULL, 0, NULL);
7256}
7257
7258status_t AudioFlinger::EffectModule::configure()
7259{
7260 uint32_t channels;
7261 if (mEffectInterface == NULL) {
7262 return NO_INIT;
7263 }
7264
7265 sp<ThreadBase> thread = mThread.promote();
7266 if (thread == 0) {
7267 return DEAD_OBJECT;
7268 }
7269
7270 // TODO: handle configuration of effects replacing track process
7271 if (thread->channelCount() == 1) {
Eric Laurente1315cf2011-05-17 19:16:02 -07007272 channels = AUDIO_CHANNEL_OUT_MONO;
Mathias Agopian65ab4712010-07-14 17:59:35 -07007273 } else {
Eric Laurente1315cf2011-05-17 19:16:02 -07007274 channels = AUDIO_CHANNEL_OUT_STEREO;
Mathias Agopian65ab4712010-07-14 17:59:35 -07007275 }
7276
7277 if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
Eric Laurente1315cf2011-05-17 19:16:02 -07007278 mConfig.inputCfg.channels = AUDIO_CHANNEL_OUT_MONO;
Mathias Agopian65ab4712010-07-14 17:59:35 -07007279 } else {
7280 mConfig.inputCfg.channels = channels;
7281 }
7282 mConfig.outputCfg.channels = channels;
Eric Laurente1315cf2011-05-17 19:16:02 -07007283 mConfig.inputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
7284 mConfig.outputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
Mathias Agopian65ab4712010-07-14 17:59:35 -07007285 mConfig.inputCfg.samplingRate = thread->sampleRate();
7286 mConfig.outputCfg.samplingRate = mConfig.inputCfg.samplingRate;
7287 mConfig.inputCfg.bufferProvider.cookie = NULL;
7288 mConfig.inputCfg.bufferProvider.getBuffer = NULL;
7289 mConfig.inputCfg.bufferProvider.releaseBuffer = NULL;
7290 mConfig.outputCfg.bufferProvider.cookie = NULL;
7291 mConfig.outputCfg.bufferProvider.getBuffer = NULL;
7292 mConfig.outputCfg.bufferProvider.releaseBuffer = NULL;
7293 mConfig.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ;
7294 // Insert effect:
Dima Zavinfce7a472011-04-19 22:30:36 -07007295 // - in session AUDIO_SESSION_OUTPUT_MIX or AUDIO_SESSION_OUTPUT_STAGE,
Eric Laurentde070132010-07-13 04:45:46 -07007296 // always overwrites output buffer: input buffer == output buffer
Mathias Agopian65ab4712010-07-14 17:59:35 -07007297 // - in other sessions:
7298 // last effect in the chain accumulates in output buffer: input buffer != output buffer
7299 // other effect: overwrites output buffer: input buffer == output buffer
7300 // Auxiliary effect:
7301 // accumulates in output buffer: input buffer != output buffer
7302 // Therefore: accumulate <=> input buffer != output buffer
7303 if (mConfig.inputCfg.buffer.raw != mConfig.outputCfg.buffer.raw) {
7304 mConfig.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_ACCUMULATE;
7305 } else {
7306 mConfig.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_WRITE;
7307 }
7308 mConfig.inputCfg.mask = EFFECT_CONFIG_ALL;
7309 mConfig.outputCfg.mask = EFFECT_CONFIG_ALL;
7310 mConfig.inputCfg.buffer.frameCount = thread->frameCount();
7311 mConfig.outputCfg.buffer.frameCount = mConfig.inputCfg.buffer.frameCount;
7312
Steve Block3856b092011-10-20 11:56:00 +01007313 ALOGV("configure() %p thread %p buffer %p framecount %d",
Eric Laurentde070132010-07-13 04:45:46 -07007314 this, thread.get(), mConfig.inputCfg.buffer.raw, mConfig.inputCfg.buffer.frameCount);
7315
Mathias Agopian65ab4712010-07-14 17:59:35 -07007316 status_t cmdStatus;
Eric Laurent25f43952010-07-28 05:40:18 -07007317 uint32_t size = sizeof(int);
7318 status_t status = (*mEffectInterface)->command(mEffectInterface,
Eric Laurent3d5188b2011-12-16 15:30:36 -08007319 EFFECT_CMD_SET_CONFIG,
Eric Laurent25f43952010-07-28 05:40:18 -07007320 sizeof(effect_config_t),
7321 &mConfig,
7322 &size,
7323 &cmdStatus);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007324 if (status == 0) {
7325 status = cmdStatus;
7326 }
7327
7328 mMaxDisableWaitCnt = (MAX_DISABLE_TIME_MS * mConfig.outputCfg.samplingRate) /
7329 (1000 * mConfig.outputCfg.buffer.frameCount);
7330
7331 return status;
7332}
7333
7334status_t AudioFlinger::EffectModule::init()
7335{
7336 Mutex::Autolock _l(mLock);
7337 if (mEffectInterface == NULL) {
7338 return NO_INIT;
7339 }
7340 status_t cmdStatus;
Eric Laurent25f43952010-07-28 05:40:18 -07007341 uint32_t size = sizeof(status_t);
7342 status_t status = (*mEffectInterface)->command(mEffectInterface,
7343 EFFECT_CMD_INIT,
7344 0,
7345 NULL,
7346 &size,
7347 &cmdStatus);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007348 if (status == 0) {
7349 status = cmdStatus;
7350 }
7351 return status;
7352}
7353
Eric Laurentec35a142011-10-05 17:42:25 -07007354status_t AudioFlinger::EffectModule::start()
7355{
7356 Mutex::Autolock _l(mLock);
7357 return start_l();
7358}
7359
Mathias Agopian65ab4712010-07-14 17:59:35 -07007360status_t AudioFlinger::EffectModule::start_l()
7361{
7362 if (mEffectInterface == NULL) {
7363 return NO_INIT;
7364 }
7365 status_t cmdStatus;
Eric Laurent25f43952010-07-28 05:40:18 -07007366 uint32_t size = sizeof(status_t);
7367 status_t status = (*mEffectInterface)->command(mEffectInterface,
7368 EFFECT_CMD_ENABLE,
7369 0,
7370 NULL,
7371 &size,
7372 &cmdStatus);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007373 if (status == 0) {
7374 status = cmdStatus;
7375 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007376 if (status == 0 &&
7377 ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC ||
7378 (mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_POST_PROC)) {
7379 sp<ThreadBase> thread = mThread.promote();
7380 if (thread != 0) {
Eric Laurentb8ba0a92011-08-07 16:32:26 -07007381 audio_stream_t *stream = thread->stream();
7382 if (stream != NULL) {
7383 stream->add_audio_effect(stream, mEffectInterface);
7384 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007385 }
7386 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07007387 return status;
7388}
7389
Eric Laurentec437d82011-07-26 20:54:46 -07007390status_t AudioFlinger::EffectModule::stop()
7391{
7392 Mutex::Autolock _l(mLock);
7393 return stop_l();
7394}
7395
Mathias Agopian65ab4712010-07-14 17:59:35 -07007396status_t AudioFlinger::EffectModule::stop_l()
7397{
7398 if (mEffectInterface == NULL) {
7399 return NO_INIT;
7400 }
7401 status_t cmdStatus;
Eric Laurent25f43952010-07-28 05:40:18 -07007402 uint32_t size = sizeof(status_t);
7403 status_t status = (*mEffectInterface)->command(mEffectInterface,
7404 EFFECT_CMD_DISABLE,
7405 0,
7406 NULL,
7407 &size,
7408 &cmdStatus);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007409 if (status == 0) {
7410 status = cmdStatus;
7411 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007412 if (status == 0 &&
7413 ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC ||
7414 (mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_POST_PROC)) {
7415 sp<ThreadBase> thread = mThread.promote();
7416 if (thread != 0) {
Eric Laurentb8ba0a92011-08-07 16:32:26 -07007417 audio_stream_t *stream = thread->stream();
7418 if (stream != NULL) {
7419 stream->remove_audio_effect(stream, mEffectInterface);
7420 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007421 }
7422 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07007423 return status;
7424}
7425
Eric Laurent25f43952010-07-28 05:40:18 -07007426status_t AudioFlinger::EffectModule::command(uint32_t cmdCode,
7427 uint32_t cmdSize,
7428 void *pCmdData,
7429 uint32_t *replySize,
7430 void *pReplyData)
Mathias Agopian65ab4712010-07-14 17:59:35 -07007431{
7432 Mutex::Autolock _l(mLock);
Steve Block3856b092011-10-20 11:56:00 +01007433// ALOGV("command(), cmdCode: %d, mEffectInterface: %p", cmdCode, mEffectInterface);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007434
Eric Laurentec437d82011-07-26 20:54:46 -07007435 if (mState == DESTROYED || mEffectInterface == NULL) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07007436 return NO_INIT;
7437 }
Eric Laurent25f43952010-07-28 05:40:18 -07007438 status_t status = (*mEffectInterface)->command(mEffectInterface,
7439 cmdCode,
7440 cmdSize,
7441 pCmdData,
7442 replySize,
7443 pReplyData);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007444 if (cmdCode != EFFECT_CMD_GET_PARAM && status == NO_ERROR) {
Eric Laurent25f43952010-07-28 05:40:18 -07007445 uint32_t size = (replySize == NULL) ? 0 : *replySize;
Mathias Agopian65ab4712010-07-14 17:59:35 -07007446 for (size_t i = 1; i < mHandles.size(); i++) {
7447 sp<EffectHandle> h = mHandles[i].promote();
7448 if (h != 0) {
7449 h->commandExecuted(cmdCode, cmdSize, pCmdData, size, pReplyData);
7450 }
7451 }
7452 }
7453 return status;
7454}
7455
7456status_t AudioFlinger::EffectModule::setEnabled(bool enabled)
7457{
Eric Laurentdb7c0792011-08-10 10:37:50 -07007458
Mathias Agopian65ab4712010-07-14 17:59:35 -07007459 Mutex::Autolock _l(mLock);
Steve Block3856b092011-10-20 11:56:00 +01007460 ALOGV("setEnabled %p enabled %d", this, enabled);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007461
7462 if (enabled != isEnabled()) {
Eric Laurentdb7c0792011-08-10 10:37:50 -07007463 status_t status = AudioSystem::setEffectEnabled(mId, enabled);
7464 if (enabled && status != NO_ERROR) {
7465 return status;
7466 }
7467
Mathias Agopian65ab4712010-07-14 17:59:35 -07007468 switch (mState) {
7469 // going from disabled to enabled
7470 case IDLE:
7471 mState = STARTING;
7472 break;
7473 case STOPPED:
7474 mState = RESTART;
7475 break;
7476 case STOPPING:
7477 mState = ACTIVE;
7478 break;
7479
7480 // going from enabled to disabled
7481 case RESTART:
Eric Laurent8f45bd72010-08-31 13:50:07 -07007482 mState = STOPPED;
7483 break;
Mathias Agopian65ab4712010-07-14 17:59:35 -07007484 case STARTING:
7485 mState = IDLE;
7486 break;
7487 case ACTIVE:
7488 mState = STOPPING;
7489 break;
Eric Laurentec437d82011-07-26 20:54:46 -07007490 case DESTROYED:
7491 return NO_ERROR; // simply ignore as we are being destroyed
Mathias Agopian65ab4712010-07-14 17:59:35 -07007492 }
7493 for (size_t i = 1; i < mHandles.size(); i++) {
7494 sp<EffectHandle> h = mHandles[i].promote();
7495 if (h != 0) {
7496 h->setEnabled(enabled);
7497 }
7498 }
7499 }
7500 return NO_ERROR;
7501}
7502
Glenn Kastenc59c0042012-02-02 14:06:11 -08007503bool AudioFlinger::EffectModule::isEnabled() const
Mathias Agopian65ab4712010-07-14 17:59:35 -07007504{
7505 switch (mState) {
7506 case RESTART:
7507 case STARTING:
7508 case ACTIVE:
7509 return true;
7510 case IDLE:
7511 case STOPPING:
7512 case STOPPED:
Eric Laurentec437d82011-07-26 20:54:46 -07007513 case DESTROYED:
Mathias Agopian65ab4712010-07-14 17:59:35 -07007514 default:
7515 return false;
7516 }
7517}
7518
Glenn Kastenc59c0042012-02-02 14:06:11 -08007519bool AudioFlinger::EffectModule::isProcessEnabled() const
Eric Laurent8f45bd72010-08-31 13:50:07 -07007520{
7521 switch (mState) {
7522 case RESTART:
7523 case ACTIVE:
7524 case STOPPING:
7525 case STOPPED:
7526 return true;
7527 case IDLE:
7528 case STARTING:
Eric Laurentec437d82011-07-26 20:54:46 -07007529 case DESTROYED:
Eric Laurent8f45bd72010-08-31 13:50:07 -07007530 default:
7531 return false;
7532 }
7533}
7534
Mathias Agopian65ab4712010-07-14 17:59:35 -07007535status_t AudioFlinger::EffectModule::setVolume(uint32_t *left, uint32_t *right, bool controller)
7536{
7537 Mutex::Autolock _l(mLock);
7538 status_t status = NO_ERROR;
7539
7540 // Send volume indication if EFFECT_FLAG_VOLUME_IND is set and read back altered volume
7541 // if controller flag is set (Note that controller == TRUE => EFFECT_FLAG_VOLUME_CTRL set)
Eric Laurent8f45bd72010-08-31 13:50:07 -07007542 if (isProcessEnabled() &&
Eric Laurentf997cab2010-07-19 06:24:46 -07007543 ((mDescriptor.flags & EFFECT_FLAG_VOLUME_MASK) == EFFECT_FLAG_VOLUME_CTRL ||
7544 (mDescriptor.flags & EFFECT_FLAG_VOLUME_MASK) == EFFECT_FLAG_VOLUME_IND)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07007545 status_t cmdStatus;
7546 uint32_t volume[2];
7547 uint32_t *pVolume = NULL;
Eric Laurent25f43952010-07-28 05:40:18 -07007548 uint32_t size = sizeof(volume);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007549 volume[0] = *left;
7550 volume[1] = *right;
7551 if (controller) {
7552 pVolume = volume;
7553 }
Eric Laurent25f43952010-07-28 05:40:18 -07007554 status = (*mEffectInterface)->command(mEffectInterface,
7555 EFFECT_CMD_SET_VOLUME,
7556 size,
7557 volume,
7558 &size,
7559 pVolume);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007560 if (controller && status == NO_ERROR && size == sizeof(volume)) {
7561 *left = volume[0];
7562 *right = volume[1];
7563 }
7564 }
7565 return status;
7566}
7567
7568status_t AudioFlinger::EffectModule::setDevice(uint32_t device)
7569{
7570 Mutex::Autolock _l(mLock);
7571 status_t status = NO_ERROR;
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007572 if (device && (mDescriptor.flags & EFFECT_FLAG_DEVICE_MASK) == EFFECT_FLAG_DEVICE_IND) {
7573 // audio pre processing modules on RecordThread can receive both output and
7574 // input device indication in the same call
7575 uint32_t dev = device & AUDIO_DEVICE_OUT_ALL;
7576 if (dev) {
7577 status_t cmdStatus;
7578 uint32_t size = sizeof(status_t);
7579
7580 status = (*mEffectInterface)->command(mEffectInterface,
7581 EFFECT_CMD_SET_DEVICE,
7582 sizeof(uint32_t),
7583 &dev,
7584 &size,
7585 &cmdStatus);
7586 if (status == NO_ERROR) {
7587 status = cmdStatus;
7588 }
7589 }
7590 dev = device & AUDIO_DEVICE_IN_ALL;
7591 if (dev) {
7592 status_t cmdStatus;
7593 uint32_t size = sizeof(status_t);
7594
7595 status_t status2 = (*mEffectInterface)->command(mEffectInterface,
7596 EFFECT_CMD_SET_INPUT_DEVICE,
7597 sizeof(uint32_t),
7598 &dev,
7599 &size,
7600 &cmdStatus);
7601 if (status2 == NO_ERROR) {
7602 status2 = cmdStatus;
7603 }
7604 if (status == NO_ERROR) {
7605 status = status2;
7606 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07007607 }
7608 }
7609 return status;
7610}
7611
Glenn Kastenf78aee72012-01-04 11:00:47 -08007612status_t AudioFlinger::EffectModule::setMode(audio_mode_t mode)
Mathias Agopian65ab4712010-07-14 17:59:35 -07007613{
7614 Mutex::Autolock _l(mLock);
7615 status_t status = NO_ERROR;
7616 if ((mDescriptor.flags & EFFECT_FLAG_AUDIO_MODE_MASK) == EFFECT_FLAG_AUDIO_MODE_IND) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07007617 status_t cmdStatus;
Eric Laurent25f43952010-07-28 05:40:18 -07007618 uint32_t size = sizeof(status_t);
7619 status = (*mEffectInterface)->command(mEffectInterface,
7620 EFFECT_CMD_SET_AUDIO_MODE,
Glenn Kastenf78aee72012-01-04 11:00:47 -08007621 sizeof(audio_mode_t),
Eric Laurente1315cf2011-05-17 19:16:02 -07007622 &mode,
Eric Laurent25f43952010-07-28 05:40:18 -07007623 &size,
7624 &cmdStatus);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007625 if (status == NO_ERROR) {
7626 status = cmdStatus;
7627 }
7628 }
7629 return status;
7630}
7631
Eric Laurent59255e42011-07-27 19:49:51 -07007632void AudioFlinger::EffectModule::setSuspended(bool suspended)
7633{
7634 Mutex::Autolock _l(mLock);
7635 mSuspended = suspended;
7636}
Glenn Kastena3a85482012-01-04 11:01:11 -08007637
7638bool AudioFlinger::EffectModule::suspended() const
Eric Laurent59255e42011-07-27 19:49:51 -07007639{
7640 Mutex::Autolock _l(mLock);
7641 return mSuspended;
7642}
7643
Mathias Agopian65ab4712010-07-14 17:59:35 -07007644status_t AudioFlinger::EffectModule::dump(int fd, const Vector<String16>& args)
7645{
7646 const size_t SIZE = 256;
7647 char buffer[SIZE];
7648 String8 result;
7649
7650 snprintf(buffer, SIZE, "\tEffect ID %d:\n", mId);
7651 result.append(buffer);
7652
7653 bool locked = tryLock(mLock);
7654 // failed to lock - AudioFlinger is probably deadlocked
7655 if (!locked) {
7656 result.append("\t\tCould not lock Fx mutex:\n");
7657 }
7658
7659 result.append("\t\tSession Status State Engine:\n");
7660 snprintf(buffer, SIZE, "\t\t%05d %03d %03d 0x%08x\n",
7661 mSessionId, mStatus, mState, (uint32_t)mEffectInterface);
7662 result.append(buffer);
7663
7664 result.append("\t\tDescriptor:\n");
7665 snprintf(buffer, SIZE, "\t\t- UUID: %08X-%04X-%04X-%04X-%02X%02X%02X%02X%02X%02X\n",
7666 mDescriptor.uuid.timeLow, mDescriptor.uuid.timeMid, mDescriptor.uuid.timeHiAndVersion,
7667 mDescriptor.uuid.clockSeq, mDescriptor.uuid.node[0], mDescriptor.uuid.node[1],mDescriptor.uuid.node[2],
7668 mDescriptor.uuid.node[3],mDescriptor.uuid.node[4],mDescriptor.uuid.node[5]);
7669 result.append(buffer);
7670 snprintf(buffer, SIZE, "\t\t- TYPE: %08X-%04X-%04X-%04X-%02X%02X%02X%02X%02X%02X\n",
7671 mDescriptor.type.timeLow, mDescriptor.type.timeMid, mDescriptor.type.timeHiAndVersion,
7672 mDescriptor.type.clockSeq, mDescriptor.type.node[0], mDescriptor.type.node[1],mDescriptor.type.node[2],
7673 mDescriptor.type.node[3],mDescriptor.type.node[4],mDescriptor.type.node[5]);
7674 result.append(buffer);
Eric Laurente1315cf2011-05-17 19:16:02 -07007675 snprintf(buffer, SIZE, "\t\t- apiVersion: %08X\n\t\t- flags: %08X\n",
Mathias Agopian65ab4712010-07-14 17:59:35 -07007676 mDescriptor.apiVersion,
7677 mDescriptor.flags);
7678 result.append(buffer);
7679 snprintf(buffer, SIZE, "\t\t- name: %s\n",
7680 mDescriptor.name);
7681 result.append(buffer);
7682 snprintf(buffer, SIZE, "\t\t- implementor: %s\n",
7683 mDescriptor.implementor);
7684 result.append(buffer);
7685
7686 result.append("\t\t- Input configuration:\n");
7687 result.append("\t\t\tBuffer Frames Smp rate Channels Format\n");
7688 snprintf(buffer, SIZE, "\t\t\t0x%08x %05d %05d %08x %d\n",
7689 (uint32_t)mConfig.inputCfg.buffer.raw,
7690 mConfig.inputCfg.buffer.frameCount,
7691 mConfig.inputCfg.samplingRate,
7692 mConfig.inputCfg.channels,
7693 mConfig.inputCfg.format);
7694 result.append(buffer);
7695
7696 result.append("\t\t- Output configuration:\n");
7697 result.append("\t\t\tBuffer Frames Smp rate Channels Format\n");
7698 snprintf(buffer, SIZE, "\t\t\t0x%08x %05d %05d %08x %d\n",
7699 (uint32_t)mConfig.outputCfg.buffer.raw,
7700 mConfig.outputCfg.buffer.frameCount,
7701 mConfig.outputCfg.samplingRate,
7702 mConfig.outputCfg.channels,
7703 mConfig.outputCfg.format);
7704 result.append(buffer);
7705
7706 snprintf(buffer, SIZE, "\t\t%d Clients:\n", mHandles.size());
7707 result.append(buffer);
7708 result.append("\t\t\tPid Priority Ctrl Locked client server\n");
7709 for (size_t i = 0; i < mHandles.size(); ++i) {
7710 sp<EffectHandle> handle = mHandles[i].promote();
7711 if (handle != 0) {
7712 handle->dump(buffer, SIZE);
7713 result.append(buffer);
7714 }
7715 }
7716
7717 result.append("\n");
7718
7719 write(fd, result.string(), result.length());
7720
7721 if (locked) {
7722 mLock.unlock();
7723 }
7724
7725 return NO_ERROR;
7726}
7727
7728// ----------------------------------------------------------------------------
7729// EffectHandle implementation
7730// ----------------------------------------------------------------------------
7731
7732#undef LOG_TAG
7733#define LOG_TAG "AudioFlinger::EffectHandle"
7734
7735AudioFlinger::EffectHandle::EffectHandle(const sp<EffectModule>& effect,
7736 const sp<AudioFlinger::Client>& client,
7737 const sp<IEffectClient>& effectClient,
7738 int32_t priority)
7739 : BnEffect(),
Marco Nelissen3a34bef2011-08-02 13:33:41 -07007740 mEffect(effect), mEffectClient(effectClient), mClient(client), mCblk(NULL),
Eric Laurent59255e42011-07-27 19:49:51 -07007741 mPriority(priority), mHasControl(false), mEnabled(false)
Mathias Agopian65ab4712010-07-14 17:59:35 -07007742{
Steve Block3856b092011-10-20 11:56:00 +01007743 ALOGV("constructor %p", this);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007744
Marco Nelissen3a34bef2011-08-02 13:33:41 -07007745 if (client == 0) {
7746 return;
7747 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07007748 int bufOffset = ((sizeof(effect_param_cblk_t) - 1) / sizeof(int) + 1) * sizeof(int);
7749 mCblkMemory = client->heap()->allocate(EFFECT_PARAM_BUFFER_SIZE + bufOffset);
7750 if (mCblkMemory != 0) {
7751 mCblk = static_cast<effect_param_cblk_t *>(mCblkMemory->pointer());
7752
Glenn Kastena0d68332012-01-27 16:47:15 -08007753 if (mCblk != NULL) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07007754 new(mCblk) effect_param_cblk_t();
7755 mBuffer = (uint8_t *)mCblk + bufOffset;
Glenn Kastene53b9ea2012-03-12 16:29:55 -07007756 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07007757 } else {
Steve Block29357bc2012-01-06 19:20:56 +00007758 ALOGE("not enough memory for Effect size=%u", EFFECT_PARAM_BUFFER_SIZE + sizeof(effect_param_cblk_t));
Mathias Agopian65ab4712010-07-14 17:59:35 -07007759 return;
7760 }
7761}
7762
7763AudioFlinger::EffectHandle::~EffectHandle()
7764{
Steve Block3856b092011-10-20 11:56:00 +01007765 ALOGV("Destructor %p", this);
Marco Nelissen3a34bef2011-08-02 13:33:41 -07007766 disconnect(false);
Steve Block3856b092011-10-20 11:56:00 +01007767 ALOGV("Destructor DONE %p", this);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007768}
7769
7770status_t AudioFlinger::EffectHandle::enable()
7771{
Steve Block3856b092011-10-20 11:56:00 +01007772 ALOGV("enable %p", this);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007773 if (!mHasControl) return INVALID_OPERATION;
7774 if (mEffect == 0) return DEAD_OBJECT;
7775
Eric Laurentdb7c0792011-08-10 10:37:50 -07007776 if (mEnabled) {
7777 return NO_ERROR;
7778 }
7779
Eric Laurent59255e42011-07-27 19:49:51 -07007780 mEnabled = true;
7781
7782 sp<ThreadBase> thread = mEffect->thread().promote();
7783 if (thread != 0) {
7784 thread->checkSuspendOnEffectEnabled(mEffect, true, mEffect->sessionId());
7785 }
7786
7787 // checkSuspendOnEffectEnabled() can suspend this same effect when enabled
7788 if (mEffect->suspended()) {
7789 return NO_ERROR;
7790 }
7791
Eric Laurentdb7c0792011-08-10 10:37:50 -07007792 status_t status = mEffect->setEnabled(true);
7793 if (status != NO_ERROR) {
7794 if (thread != 0) {
7795 thread->checkSuspendOnEffectEnabled(mEffect, false, mEffect->sessionId());
7796 }
7797 mEnabled = false;
7798 }
7799 return status;
Mathias Agopian65ab4712010-07-14 17:59:35 -07007800}
7801
7802status_t AudioFlinger::EffectHandle::disable()
7803{
Steve Block3856b092011-10-20 11:56:00 +01007804 ALOGV("disable %p", this);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007805 if (!mHasControl) return INVALID_OPERATION;
Eric Laurent59255e42011-07-27 19:49:51 -07007806 if (mEffect == 0) return DEAD_OBJECT;
Mathias Agopian65ab4712010-07-14 17:59:35 -07007807
Eric Laurentdb7c0792011-08-10 10:37:50 -07007808 if (!mEnabled) {
7809 return NO_ERROR;
7810 }
Eric Laurent59255e42011-07-27 19:49:51 -07007811 mEnabled = false;
7812
7813 if (mEffect->suspended()) {
7814 return NO_ERROR;
7815 }
7816
7817 status_t status = mEffect->setEnabled(false);
7818
7819 sp<ThreadBase> thread = mEffect->thread().promote();
7820 if (thread != 0) {
7821 thread->checkSuspendOnEffectEnabled(mEffect, false, mEffect->sessionId());
7822 }
7823
7824 return status;
Mathias Agopian65ab4712010-07-14 17:59:35 -07007825}
7826
7827void AudioFlinger::EffectHandle::disconnect()
7828{
Marco Nelissen3a34bef2011-08-02 13:33:41 -07007829 disconnect(true);
7830}
7831
Glenn Kasten58123c32012-02-03 10:32:24 -08007832void AudioFlinger::EffectHandle::disconnect(bool unpinIfLast)
Marco Nelissen3a34bef2011-08-02 13:33:41 -07007833{
Glenn Kasten58123c32012-02-03 10:32:24 -08007834 ALOGV("disconnect(%s)", unpinIfLast ? "true" : "false");
Mathias Agopian65ab4712010-07-14 17:59:35 -07007835 if (mEffect == 0) {
7836 return;
7837 }
Glenn Kasten58123c32012-02-03 10:32:24 -08007838 mEffect->disconnect(this, unpinIfLast);
Eric Laurent59255e42011-07-27 19:49:51 -07007839
Eric Laurenta85a74a2011-10-19 11:44:54 -07007840 if (mHasControl && mEnabled) {
Eric Laurentdb7c0792011-08-10 10:37:50 -07007841 sp<ThreadBase> thread = mEffect->thread().promote();
7842 if (thread != 0) {
7843 thread->checkSuspendOnEffectEnabled(mEffect, false, mEffect->sessionId());
7844 }
Eric Laurent59255e42011-07-27 19:49:51 -07007845 }
7846
Mathias Agopian65ab4712010-07-14 17:59:35 -07007847 // release sp on module => module destructor can be called now
7848 mEffect.clear();
Mathias Agopian65ab4712010-07-14 17:59:35 -07007849 if (mClient != 0) {
Glenn Kastena0d68332012-01-27 16:47:15 -08007850 if (mCblk != NULL) {
Glenn Kasten1a0ae5b2012-02-03 10:24:48 -08007851 // unlike ~TrackBase(), mCblk is never a local new, so don't delete
Marco Nelissen3a34bef2011-08-02 13:33:41 -07007852 mCblk->~effect_param_cblk_t(); // destroy our shared-structure.
7853 }
Glenn Kastendbfafaf2012-01-25 15:27:15 -08007854 mCblkMemory.clear(); // free the shared memory before releasing the heap it belongs to
Glenn Kasten98ec94c2012-01-25 14:28:29 -08007855 // Client destructor must run with AudioFlinger mutex locked
Mathias Agopian65ab4712010-07-14 17:59:35 -07007856 Mutex::Autolock _l(mClient->audioFlinger()->mLock);
7857 mClient.clear();
7858 }
7859}
7860
Eric Laurent25f43952010-07-28 05:40:18 -07007861status_t AudioFlinger::EffectHandle::command(uint32_t cmdCode,
7862 uint32_t cmdSize,
7863 void *pCmdData,
7864 uint32_t *replySize,
7865 void *pReplyData)
Mathias Agopian65ab4712010-07-14 17:59:35 -07007866{
Steve Block3856b092011-10-20 11:56:00 +01007867// ALOGV("command(), cmdCode: %d, mHasControl: %d, mEffect: %p",
Eric Laurent25f43952010-07-28 05:40:18 -07007868// cmdCode, mHasControl, (mEffect == 0) ? 0 : mEffect.get());
Mathias Agopian65ab4712010-07-14 17:59:35 -07007869
7870 // only get parameter command is permitted for applications not controlling the effect
7871 if (!mHasControl && cmdCode != EFFECT_CMD_GET_PARAM) {
7872 return INVALID_OPERATION;
7873 }
7874 if (mEffect == 0) return DEAD_OBJECT;
Marco Nelissen3a34bef2011-08-02 13:33:41 -07007875 if (mClient == 0) return INVALID_OPERATION;
Mathias Agopian65ab4712010-07-14 17:59:35 -07007876
7877 // handle commands that are not forwarded transparently to effect engine
7878 if (cmdCode == EFFECT_CMD_SET_PARAM_COMMIT) {
7879 // No need to trylock() here as this function is executed in the binder thread serving a particular client process:
7880 // no risk to block the whole media server process or mixer threads is we are stuck here
7881 Mutex::Autolock _l(mCblk->lock);
7882 if (mCblk->clientIndex > EFFECT_PARAM_BUFFER_SIZE ||
7883 mCblk->serverIndex > EFFECT_PARAM_BUFFER_SIZE) {
7884 mCblk->serverIndex = 0;
7885 mCblk->clientIndex = 0;
7886 return BAD_VALUE;
7887 }
7888 status_t status = NO_ERROR;
7889 while (mCblk->serverIndex < mCblk->clientIndex) {
7890 int reply;
Eric Laurent25f43952010-07-28 05:40:18 -07007891 uint32_t rsize = sizeof(int);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007892 int *p = (int *)(mBuffer + mCblk->serverIndex);
7893 int size = *p++;
7894 if (((uint8_t *)p + size) > mBuffer + mCblk->clientIndex) {
Steve Block5ff1dd52012-01-05 23:22:43 +00007895 ALOGW("command(): invalid parameter block size");
Mathias Agopian65ab4712010-07-14 17:59:35 -07007896 break;
7897 }
7898 effect_param_t *param = (effect_param_t *)p;
7899 if (param->psize == 0 || param->vsize == 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00007900 ALOGW("command(): null parameter or value size");
Mathias Agopian65ab4712010-07-14 17:59:35 -07007901 mCblk->serverIndex += size;
7902 continue;
7903 }
Eric Laurent25f43952010-07-28 05:40:18 -07007904 uint32_t psize = sizeof(effect_param_t) +
7905 ((param->psize - 1) / sizeof(int) + 1) * sizeof(int) +
7906 param->vsize;
7907 status_t ret = mEffect->command(EFFECT_CMD_SET_PARAM,
7908 psize,
7909 p,
7910 &rsize,
7911 &reply);
Eric Laurentaeae3de2010-09-02 11:56:55 -07007912 // stop at first error encountered
7913 if (ret != NO_ERROR) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07007914 status = ret;
Eric Laurentaeae3de2010-09-02 11:56:55 -07007915 *(int *)pReplyData = reply;
7916 break;
7917 } else if (reply != NO_ERROR) {
7918 *(int *)pReplyData = reply;
7919 break;
Mathias Agopian65ab4712010-07-14 17:59:35 -07007920 }
7921 mCblk->serverIndex += size;
7922 }
7923 mCblk->serverIndex = 0;
7924 mCblk->clientIndex = 0;
7925 return status;
7926 } else if (cmdCode == EFFECT_CMD_ENABLE) {
Eric Laurentaeae3de2010-09-02 11:56:55 -07007927 *(int *)pReplyData = NO_ERROR;
Mathias Agopian65ab4712010-07-14 17:59:35 -07007928 return enable();
7929 } else if (cmdCode == EFFECT_CMD_DISABLE) {
Eric Laurentaeae3de2010-09-02 11:56:55 -07007930 *(int *)pReplyData = NO_ERROR;
Mathias Agopian65ab4712010-07-14 17:59:35 -07007931 return disable();
7932 }
7933
7934 return mEffect->command(cmdCode, cmdSize, pCmdData, replySize, pReplyData);
7935}
7936
Eric Laurent59255e42011-07-27 19:49:51 -07007937void AudioFlinger::EffectHandle::setControl(bool hasControl, bool signal, bool enabled)
Mathias Agopian65ab4712010-07-14 17:59:35 -07007938{
Steve Block3856b092011-10-20 11:56:00 +01007939 ALOGV("setControl %p control %d", this, hasControl);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007940
7941 mHasControl = hasControl;
Eric Laurent59255e42011-07-27 19:49:51 -07007942 mEnabled = enabled;
7943
Mathias Agopian65ab4712010-07-14 17:59:35 -07007944 if (signal && mEffectClient != 0) {
7945 mEffectClient->controlStatusChanged(hasControl);
7946 }
7947}
7948
Eric Laurent25f43952010-07-28 05:40:18 -07007949void AudioFlinger::EffectHandle::commandExecuted(uint32_t cmdCode,
7950 uint32_t cmdSize,
7951 void *pCmdData,
7952 uint32_t replySize,
7953 void *pReplyData)
Mathias Agopian65ab4712010-07-14 17:59:35 -07007954{
7955 if (mEffectClient != 0) {
7956 mEffectClient->commandExecuted(cmdCode, cmdSize, pCmdData, replySize, pReplyData);
7957 }
7958}
7959
7960
7961
7962void AudioFlinger::EffectHandle::setEnabled(bool enabled)
7963{
7964 if (mEffectClient != 0) {
7965 mEffectClient->enableStatusChanged(enabled);
7966 }
7967}
7968
7969status_t AudioFlinger::EffectHandle::onTransact(
7970 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
7971{
7972 return BnEffect::onTransact(code, data, reply, flags);
7973}
7974
7975
7976void AudioFlinger::EffectHandle::dump(char* buffer, size_t size)
7977{
Glenn Kastena0d68332012-01-27 16:47:15 -08007978 bool locked = mCblk != NULL && tryLock(mCblk->lock);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007979
7980 snprintf(buffer, size, "\t\t\t%05d %05d %01u %01u %05u %05u\n",
Glenn Kasten44deb052012-02-05 18:09:08 -08007981 (mClient == 0) ? getpid_cached : mClient->pid(),
Mathias Agopian65ab4712010-07-14 17:59:35 -07007982 mPriority,
7983 mHasControl,
7984 !locked,
Marco Nelissen3a34bef2011-08-02 13:33:41 -07007985 mCblk ? mCblk->clientIndex : 0,
7986 mCblk ? mCblk->serverIndex : 0
Mathias Agopian65ab4712010-07-14 17:59:35 -07007987 );
7988
7989 if (locked) {
7990 mCblk->lock.unlock();
7991 }
7992}
7993
7994#undef LOG_TAG
7995#define LOG_TAG "AudioFlinger::EffectChain"
7996
Glenn Kasten9eaa5572012-01-20 13:32:16 -08007997AudioFlinger::EffectChain::EffectChain(ThreadBase *thread,
Mathias Agopian65ab4712010-07-14 17:59:35 -07007998 int sessionId)
Glenn Kasten9eaa5572012-01-20 13:32:16 -08007999 : mThread(thread), mSessionId(sessionId), mActiveTrackCnt(0), mTrackCnt(0), mTailBufferCount(0),
Eric Laurentb469b942011-05-09 12:09:06 -07008000 mOwnInBuffer(false), mVolumeCtrlIdx(-1), mLeftVolume(UINT_MAX), mRightVolume(UINT_MAX),
8001 mNewLeftVolume(UINT_MAX), mNewRightVolume(UINT_MAX)
Mathias Agopian65ab4712010-07-14 17:59:35 -07008002{
Dima Zavinfce7a472011-04-19 22:30:36 -07008003 mStrategy = AudioSystem::getStrategyForStream(AUDIO_STREAM_MUSIC);
Glenn Kasten9eaa5572012-01-20 13:32:16 -08008004 if (thread == NULL) {
Eric Laurent544fe9b2011-11-11 15:42:52 -08008005 return;
8006 }
8007 mMaxTailBuffers = ((kProcessTailDurationMs * thread->sampleRate()) / 1000) /
8008 thread->frameCount();
Mathias Agopian65ab4712010-07-14 17:59:35 -07008009}
8010
8011AudioFlinger::EffectChain::~EffectChain()
8012{
8013 if (mOwnInBuffer) {
8014 delete mInBuffer;
8015 }
8016
8017}
8018
Eric Laurent59255e42011-07-27 19:49:51 -07008019// getEffectFromDesc_l() must be called with ThreadBase::mLock held
Eric Laurentcab11242010-07-15 12:50:15 -07008020sp<AudioFlinger::EffectModule> AudioFlinger::EffectChain::getEffectFromDesc_l(effect_descriptor_t *descriptor)
Mathias Agopian65ab4712010-07-14 17:59:35 -07008021{
Mathias Agopian65ab4712010-07-14 17:59:35 -07008022 size_t size = mEffects.size();
8023
8024 for (size_t i = 0; i < size; i++) {
8025 if (memcmp(&mEffects[i]->desc().uuid, &descriptor->uuid, sizeof(effect_uuid_t)) == 0) {
Glenn Kasten090f0192012-01-30 13:00:02 -08008026 return mEffects[i];
Mathias Agopian65ab4712010-07-14 17:59:35 -07008027 }
8028 }
Glenn Kasten090f0192012-01-30 13:00:02 -08008029 return 0;
Mathias Agopian65ab4712010-07-14 17:59:35 -07008030}
8031
Eric Laurent59255e42011-07-27 19:49:51 -07008032// getEffectFromId_l() must be called with ThreadBase::mLock held
Eric Laurentcab11242010-07-15 12:50:15 -07008033sp<AudioFlinger::EffectModule> AudioFlinger::EffectChain::getEffectFromId_l(int id)
Mathias Agopian65ab4712010-07-14 17:59:35 -07008034{
Mathias Agopian65ab4712010-07-14 17:59:35 -07008035 size_t size = mEffects.size();
8036
8037 for (size_t i = 0; i < size; i++) {
Eric Laurentde070132010-07-13 04:45:46 -07008038 // by convention, return first effect if id provided is 0 (0 is never a valid id)
8039 if (id == 0 || mEffects[i]->id() == id) {
Glenn Kasten090f0192012-01-30 13:00:02 -08008040 return mEffects[i];
Mathias Agopian65ab4712010-07-14 17:59:35 -07008041 }
8042 }
Glenn Kasten090f0192012-01-30 13:00:02 -08008043 return 0;
Mathias Agopian65ab4712010-07-14 17:59:35 -07008044}
8045
Eric Laurent59255e42011-07-27 19:49:51 -07008046// getEffectFromType_l() must be called with ThreadBase::mLock held
8047sp<AudioFlinger::EffectModule> AudioFlinger::EffectChain::getEffectFromType_l(
8048 const effect_uuid_t *type)
8049{
Eric Laurent59255e42011-07-27 19:49:51 -07008050 size_t size = mEffects.size();
8051
8052 for (size_t i = 0; i < size; i++) {
8053 if (memcmp(&mEffects[i]->desc().type, type, sizeof(effect_uuid_t)) == 0) {
Glenn Kasten090f0192012-01-30 13:00:02 -08008054 return mEffects[i];
Eric Laurent59255e42011-07-27 19:49:51 -07008055 }
8056 }
Glenn Kasten090f0192012-01-30 13:00:02 -08008057 return 0;
Eric Laurent59255e42011-07-27 19:49:51 -07008058}
8059
Mathias Agopian65ab4712010-07-14 17:59:35 -07008060// Must be called with EffectChain::mLock locked
8061void AudioFlinger::EffectChain::process_l()
8062{
Eric Laurentdac69112010-09-28 14:09:57 -07008063 sp<ThreadBase> thread = mThread.promote();
8064 if (thread == 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00008065 ALOGW("process_l(): cannot promote mixer thread");
Eric Laurentdac69112010-09-28 14:09:57 -07008066 return;
8067 }
Dima Zavinfce7a472011-04-19 22:30:36 -07008068 bool isGlobalSession = (mSessionId == AUDIO_SESSION_OUTPUT_MIX) ||
8069 (mSessionId == AUDIO_SESSION_OUTPUT_STAGE);
Eric Laurent544fe9b2011-11-11 15:42:52 -08008070 // always process effects unless no more tracks are on the session and the effect tail
8071 // has been rendered
8072 bool doProcess = true;
Eric Laurentdac69112010-09-28 14:09:57 -07008073 if (!isGlobalSession) {
Eric Laurent544fe9b2011-11-11 15:42:52 -08008074 bool tracksOnSession = (trackCnt() != 0);
Eric Laurentb469b942011-05-09 12:09:06 -07008075
Eric Laurent544fe9b2011-11-11 15:42:52 -08008076 if (!tracksOnSession && mTailBufferCount == 0) {
8077 doProcess = false;
8078 }
8079
8080 if (activeTrackCnt() == 0) {
8081 // if no track is active and the effect tail has not been rendered,
8082 // the input buffer must be cleared here as the mixer process will not do it
8083 if (tracksOnSession || mTailBufferCount > 0) {
8084 size_t numSamples = thread->frameCount() * thread->channelCount();
8085 memset(mInBuffer, 0, numSamples * sizeof(int16_t));
8086 if (mTailBufferCount > 0) {
8087 mTailBufferCount--;
8088 }
8089 }
8090 }
Eric Laurentdac69112010-09-28 14:09:57 -07008091 }
8092
Mathias Agopian65ab4712010-07-14 17:59:35 -07008093 size_t size = mEffects.size();
Eric Laurent544fe9b2011-11-11 15:42:52 -08008094 if (doProcess) {
Eric Laurentdac69112010-09-28 14:09:57 -07008095 for (size_t i = 0; i < size; i++) {
8096 mEffects[i]->process();
8097 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07008098 }
8099 for (size_t i = 0; i < size; i++) {
8100 mEffects[i]->updateState();
8101 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07008102}
8103
Eric Laurentcab11242010-07-15 12:50:15 -07008104// addEffect_l() must be called with PlaybackThread::mLock held
Eric Laurentde070132010-07-13 04:45:46 -07008105status_t AudioFlinger::EffectChain::addEffect_l(const sp<EffectModule>& effect)
Mathias Agopian65ab4712010-07-14 17:59:35 -07008106{
8107 effect_descriptor_t desc = effect->desc();
8108 uint32_t insertPref = desc.flags & EFFECT_FLAG_INSERT_MASK;
8109
8110 Mutex::Autolock _l(mLock);
Eric Laurentde070132010-07-13 04:45:46 -07008111 effect->setChain(this);
8112 sp<ThreadBase> thread = mThread.promote();
8113 if (thread == 0) {
8114 return NO_INIT;
8115 }
8116 effect->setThread(thread);
Mathias Agopian65ab4712010-07-14 17:59:35 -07008117
8118 if ((desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
8119 // Auxiliary effects are inserted at the beginning of mEffects vector as
8120 // they are processed first and accumulated in chain input buffer
8121 mEffects.insertAt(effect, 0);
Eric Laurentde070132010-07-13 04:45:46 -07008122
Mathias Agopian65ab4712010-07-14 17:59:35 -07008123 // the input buffer for auxiliary effect contains mono samples in
8124 // 32 bit format. This is to avoid saturation in AudoMixer
8125 // accumulation stage. Saturation is done in EffectModule::process() before
8126 // calling the process in effect engine
8127 size_t numSamples = thread->frameCount();
8128 int32_t *buffer = new int32_t[numSamples];
8129 memset(buffer, 0, numSamples * sizeof(int32_t));
8130 effect->setInBuffer((int16_t *)buffer);
8131 // auxiliary effects output samples to chain input buffer for further processing
8132 // by insert effects
8133 effect->setOutBuffer(mInBuffer);
8134 } else {
8135 // Insert effects are inserted at the end of mEffects vector as they are processed
8136 // after track and auxiliary effects.
8137 // Insert effect order as a function of indicated preference:
8138 // if EFFECT_FLAG_INSERT_EXCLUSIVE, insert in first position or reject if
8139 // another effect is present
8140 // else if EFFECT_FLAG_INSERT_FIRST, insert in first position or after the
8141 // last effect claiming first position
8142 // else if EFFECT_FLAG_INSERT_LAST, insert in last position or before the
8143 // first effect claiming last position
8144 // else if EFFECT_FLAG_INSERT_ANY insert after first or before last
8145 // Reject insertion if an effect with EFFECT_FLAG_INSERT_EXCLUSIVE is
8146 // already present
8147
Glenn Kasten8d6a2442012-02-08 14:04:28 -08008148 size_t size = mEffects.size();
8149 size_t idx_insert = size;
8150 ssize_t idx_insert_first = -1;
8151 ssize_t idx_insert_last = -1;
Mathias Agopian65ab4712010-07-14 17:59:35 -07008152
Glenn Kasten8d6a2442012-02-08 14:04:28 -08008153 for (size_t i = 0; i < size; i++) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07008154 effect_descriptor_t d = mEffects[i]->desc();
8155 uint32_t iMode = d.flags & EFFECT_FLAG_TYPE_MASK;
8156 uint32_t iPref = d.flags & EFFECT_FLAG_INSERT_MASK;
8157 if (iMode == EFFECT_FLAG_TYPE_INSERT) {
8158 // check invalid effect chaining combinations
8159 if (insertPref == EFFECT_FLAG_INSERT_EXCLUSIVE ||
8160 iPref == EFFECT_FLAG_INSERT_EXCLUSIVE) {
Steve Block5ff1dd52012-01-05 23:22:43 +00008161 ALOGW("addEffect_l() could not insert effect %s: exclusive conflict with %s", desc.name, d.name);
Mathias Agopian65ab4712010-07-14 17:59:35 -07008162 return INVALID_OPERATION;
8163 }
8164 // remember position of first insert effect and by default
8165 // select this as insert position for new effect
8166 if (idx_insert == size) {
8167 idx_insert = i;
8168 }
8169 // remember position of last insert effect claiming
8170 // first position
8171 if (iPref == EFFECT_FLAG_INSERT_FIRST) {
8172 idx_insert_first = i;
8173 }
8174 // remember position of first insert effect claiming
8175 // last position
8176 if (iPref == EFFECT_FLAG_INSERT_LAST &&
8177 idx_insert_last == -1) {
8178 idx_insert_last = i;
8179 }
8180 }
8181 }
8182
8183 // modify idx_insert from first position if needed
8184 if (insertPref == EFFECT_FLAG_INSERT_LAST) {
8185 if (idx_insert_last != -1) {
8186 idx_insert = idx_insert_last;
8187 } else {
8188 idx_insert = size;
8189 }
8190 } else {
8191 if (idx_insert_first != -1) {
8192 idx_insert = idx_insert_first + 1;
8193 }
8194 }
8195
8196 // always read samples from chain input buffer
8197 effect->setInBuffer(mInBuffer);
8198
8199 // if last effect in the chain, output samples to chain
8200 // output buffer, otherwise to chain input buffer
8201 if (idx_insert == size) {
8202 if (idx_insert != 0) {
8203 mEffects[idx_insert-1]->setOutBuffer(mInBuffer);
8204 mEffects[idx_insert-1]->configure();
8205 }
8206 effect->setOutBuffer(mOutBuffer);
8207 } else {
8208 effect->setOutBuffer(mInBuffer);
8209 }
8210 mEffects.insertAt(effect, idx_insert);
Mathias Agopian65ab4712010-07-14 17:59:35 -07008211
Steve Block3856b092011-10-20 11:56:00 +01008212 ALOGV("addEffect_l() effect %p, added in chain %p at rank %d", effect.get(), this, idx_insert);
Mathias Agopian65ab4712010-07-14 17:59:35 -07008213 }
8214 effect->configure();
8215 return NO_ERROR;
8216}
8217
Eric Laurentcab11242010-07-15 12:50:15 -07008218// removeEffect_l() must be called with PlaybackThread::mLock held
8219size_t AudioFlinger::EffectChain::removeEffect_l(const sp<EffectModule>& effect)
Mathias Agopian65ab4712010-07-14 17:59:35 -07008220{
8221 Mutex::Autolock _l(mLock);
Glenn Kasten8d6a2442012-02-08 14:04:28 -08008222 size_t size = mEffects.size();
Mathias Agopian65ab4712010-07-14 17:59:35 -07008223 uint32_t type = effect->desc().flags & EFFECT_FLAG_TYPE_MASK;
8224
Glenn Kasten8d6a2442012-02-08 14:04:28 -08008225 for (size_t i = 0; i < size; i++) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07008226 if (effect == mEffects[i]) {
Eric Laurentec437d82011-07-26 20:54:46 -07008227 // calling stop here will remove pre-processing effect from the audio HAL.
8228 // This is safe as we hold the EffectChain mutex which guarantees that we are not in
8229 // the middle of a read from audio HAL
Eric Laurentec35a142011-10-05 17:42:25 -07008230 if (mEffects[i]->state() == EffectModule::ACTIVE ||
8231 mEffects[i]->state() == EffectModule::STOPPING) {
8232 mEffects[i]->stop();
8233 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07008234 if (type == EFFECT_FLAG_TYPE_AUXILIARY) {
8235 delete[] effect->inBuffer();
8236 } else {
8237 if (i == size - 1 && i != 0) {
8238 mEffects[i - 1]->setOutBuffer(mOutBuffer);
8239 mEffects[i - 1]->configure();
8240 }
8241 }
8242 mEffects.removeAt(i);
Steve Block3856b092011-10-20 11:56:00 +01008243 ALOGV("removeEffect_l() effect %p, removed from chain %p at rank %d", effect.get(), this, i);
Mathias Agopian65ab4712010-07-14 17:59:35 -07008244 break;
8245 }
8246 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07008247
8248 return mEffects.size();
8249}
8250
Eric Laurentcab11242010-07-15 12:50:15 -07008251// setDevice_l() must be called with PlaybackThread::mLock held
8252void AudioFlinger::EffectChain::setDevice_l(uint32_t device)
Mathias Agopian65ab4712010-07-14 17:59:35 -07008253{
8254 size_t size = mEffects.size();
8255 for (size_t i = 0; i < size; i++) {
8256 mEffects[i]->setDevice(device);
8257 }
8258}
8259
Eric Laurentcab11242010-07-15 12:50:15 -07008260// setMode_l() must be called with PlaybackThread::mLock held
Glenn Kastenf78aee72012-01-04 11:00:47 -08008261void AudioFlinger::EffectChain::setMode_l(audio_mode_t mode)
Mathias Agopian65ab4712010-07-14 17:59:35 -07008262{
8263 size_t size = mEffects.size();
8264 for (size_t i = 0; i < size; i++) {
8265 mEffects[i]->setMode(mode);
8266 }
8267}
8268
Eric Laurentcab11242010-07-15 12:50:15 -07008269// setVolume_l() must be called with PlaybackThread::mLock held
8270bool AudioFlinger::EffectChain::setVolume_l(uint32_t *left, uint32_t *right)
Mathias Agopian65ab4712010-07-14 17:59:35 -07008271{
8272 uint32_t newLeft = *left;
8273 uint32_t newRight = *right;
8274 bool hasControl = false;
Eric Laurentcab11242010-07-15 12:50:15 -07008275 int ctrlIdx = -1;
8276 size_t size = mEffects.size();
Mathias Agopian65ab4712010-07-14 17:59:35 -07008277
Eric Laurentcab11242010-07-15 12:50:15 -07008278 // first update volume controller
8279 for (size_t i = size; i > 0; i--) {
Eric Laurent8f45bd72010-08-31 13:50:07 -07008280 if (mEffects[i - 1]->isProcessEnabled() &&
Eric Laurentcab11242010-07-15 12:50:15 -07008281 (mEffects[i - 1]->desc().flags & EFFECT_FLAG_VOLUME_MASK) == EFFECT_FLAG_VOLUME_CTRL) {
8282 ctrlIdx = i - 1;
Eric Laurentf997cab2010-07-19 06:24:46 -07008283 hasControl = true;
Eric Laurentcab11242010-07-15 12:50:15 -07008284 break;
8285 }
8286 }
8287
8288 if (ctrlIdx == mVolumeCtrlIdx && *left == mLeftVolume && *right == mRightVolume) {
Eric Laurentf997cab2010-07-19 06:24:46 -07008289 if (hasControl) {
8290 *left = mNewLeftVolume;
8291 *right = mNewRightVolume;
8292 }
8293 return hasControl;
Eric Laurentcab11242010-07-15 12:50:15 -07008294 }
8295
8296 mVolumeCtrlIdx = ctrlIdx;
Eric Laurentf997cab2010-07-19 06:24:46 -07008297 mLeftVolume = newLeft;
8298 mRightVolume = newRight;
Eric Laurentcab11242010-07-15 12:50:15 -07008299
8300 // second get volume update from volume controller
8301 if (ctrlIdx >= 0) {
8302 mEffects[ctrlIdx]->setVolume(&newLeft, &newRight, true);
Eric Laurentf997cab2010-07-19 06:24:46 -07008303 mNewLeftVolume = newLeft;
8304 mNewRightVolume = newRight;
Mathias Agopian65ab4712010-07-14 17:59:35 -07008305 }
8306 // then indicate volume to all other effects in chain.
8307 // Pass altered volume to effects before volume controller
8308 // and requested volume to effects after controller
8309 uint32_t lVol = newLeft;
8310 uint32_t rVol = newRight;
Eric Laurentcab11242010-07-15 12:50:15 -07008311
Mathias Agopian65ab4712010-07-14 17:59:35 -07008312 for (size_t i = 0; i < size; i++) {
Eric Laurentcab11242010-07-15 12:50:15 -07008313 if ((int)i == ctrlIdx) continue;
8314 // this also works for ctrlIdx == -1 when there is no volume controller
8315 if ((int)i > ctrlIdx) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07008316 lVol = *left;
8317 rVol = *right;
8318 }
8319 mEffects[i]->setVolume(&lVol, &rVol, false);
8320 }
8321 *left = newLeft;
8322 *right = newRight;
8323
8324 return hasControl;
8325}
8326
Mathias Agopian65ab4712010-07-14 17:59:35 -07008327status_t AudioFlinger::EffectChain::dump(int fd, const Vector<String16>& args)
8328{
8329 const size_t SIZE = 256;
8330 char buffer[SIZE];
8331 String8 result;
8332
8333 snprintf(buffer, SIZE, "Effects for session %d:\n", mSessionId);
8334 result.append(buffer);
8335
8336 bool locked = tryLock(mLock);
8337 // failed to lock - AudioFlinger is probably deadlocked
8338 if (!locked) {
8339 result.append("\tCould not lock mutex:\n");
8340 }
8341
Eric Laurentcab11242010-07-15 12:50:15 -07008342 result.append("\tNum fx In buffer Out buffer Active tracks:\n");
8343 snprintf(buffer, SIZE, "\t%02d 0x%08x 0x%08x %d\n",
Mathias Agopian65ab4712010-07-14 17:59:35 -07008344 mEffects.size(),
8345 (uint32_t)mInBuffer,
8346 (uint32_t)mOutBuffer,
Mathias Agopian65ab4712010-07-14 17:59:35 -07008347 mActiveTrackCnt);
8348 result.append(buffer);
8349 write(fd, result.string(), result.size());
8350
8351 for (size_t i = 0; i < mEffects.size(); ++i) {
8352 sp<EffectModule> effect = mEffects[i];
8353 if (effect != 0) {
8354 effect->dump(fd, args);
8355 }
8356 }
8357
8358 if (locked) {
8359 mLock.unlock();
8360 }
8361
8362 return NO_ERROR;
8363}
8364
Eric Laurent59255e42011-07-27 19:49:51 -07008365// must be called with ThreadBase::mLock held
8366void AudioFlinger::EffectChain::setEffectSuspended_l(
8367 const effect_uuid_t *type, bool suspend)
8368{
8369 sp<SuspendedEffectDesc> desc;
8370 // use effect type UUID timelow as key as there is no real risk of identical
8371 // timeLow fields among effect type UUIDs.
Glenn Kasten8d6a2442012-02-08 14:04:28 -08008372 ssize_t index = mSuspendedEffects.indexOfKey(type->timeLow);
Eric Laurent59255e42011-07-27 19:49:51 -07008373 if (suspend) {
8374 if (index >= 0) {
8375 desc = mSuspendedEffects.valueAt(index);
8376 } else {
8377 desc = new SuspendedEffectDesc();
8378 memcpy(&desc->mType, type, sizeof(effect_uuid_t));
8379 mSuspendedEffects.add(type->timeLow, desc);
Steve Block3856b092011-10-20 11:56:00 +01008380 ALOGV("setEffectSuspended_l() add entry for %08x", type->timeLow);
Eric Laurent59255e42011-07-27 19:49:51 -07008381 }
8382 if (desc->mRefCount++ == 0) {
8383 sp<EffectModule> effect = getEffectIfEnabled(type);
8384 if (effect != 0) {
8385 desc->mEffect = effect;
8386 effect->setSuspended(true);
8387 effect->setEnabled(false);
8388 }
8389 }
8390 } else {
8391 if (index < 0) {
8392 return;
8393 }
8394 desc = mSuspendedEffects.valueAt(index);
8395 if (desc->mRefCount <= 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00008396 ALOGW("setEffectSuspended_l() restore refcount should not be 0 %d", desc->mRefCount);
Eric Laurent59255e42011-07-27 19:49:51 -07008397 desc->mRefCount = 1;
8398 }
8399 if (--desc->mRefCount == 0) {
Steve Block3856b092011-10-20 11:56:00 +01008400 ALOGV("setEffectSuspended_l() remove entry for %08x", mSuspendedEffects.keyAt(index));
Eric Laurent59255e42011-07-27 19:49:51 -07008401 if (desc->mEffect != 0) {
8402 sp<EffectModule> effect = desc->mEffect.promote();
8403 if (effect != 0) {
8404 effect->setSuspended(false);
8405 sp<EffectHandle> handle = effect->controlHandle();
8406 if (handle != 0) {
8407 effect->setEnabled(handle->enabled());
8408 }
8409 }
8410 desc->mEffect.clear();
8411 }
8412 mSuspendedEffects.removeItemsAt(index);
8413 }
8414 }
8415}
8416
8417// must be called with ThreadBase::mLock held
8418void AudioFlinger::EffectChain::setEffectSuspendedAll_l(bool suspend)
8419{
8420 sp<SuspendedEffectDesc> desc;
8421
Glenn Kasten8d6a2442012-02-08 14:04:28 -08008422 ssize_t index = mSuspendedEffects.indexOfKey((int)kKeyForSuspendAll);
Eric Laurent59255e42011-07-27 19:49:51 -07008423 if (suspend) {
8424 if (index >= 0) {
8425 desc = mSuspendedEffects.valueAt(index);
8426 } else {
8427 desc = new SuspendedEffectDesc();
8428 mSuspendedEffects.add((int)kKeyForSuspendAll, desc);
Steve Block3856b092011-10-20 11:56:00 +01008429 ALOGV("setEffectSuspendedAll_l() add entry for 0");
Eric Laurent59255e42011-07-27 19:49:51 -07008430 }
8431 if (desc->mRefCount++ == 0) {
Glenn Kastend0539712012-01-30 12:56:03 -08008432 Vector< sp<EffectModule> > effects;
8433 getSuspendEligibleEffects(effects);
Eric Laurent59255e42011-07-27 19:49:51 -07008434 for (size_t i = 0; i < effects.size(); i++) {
8435 setEffectSuspended_l(&effects[i]->desc().type, true);
8436 }
8437 }
8438 } else {
8439 if (index < 0) {
8440 return;
8441 }
8442 desc = mSuspendedEffects.valueAt(index);
8443 if (desc->mRefCount <= 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00008444 ALOGW("setEffectSuspendedAll_l() restore refcount should not be 0 %d", desc->mRefCount);
Eric Laurent59255e42011-07-27 19:49:51 -07008445 desc->mRefCount = 1;
8446 }
8447 if (--desc->mRefCount == 0) {
8448 Vector<const effect_uuid_t *> types;
8449 for (size_t i = 0; i < mSuspendedEffects.size(); i++) {
8450 if (mSuspendedEffects.keyAt(i) == (int)kKeyForSuspendAll) {
8451 continue;
8452 }
8453 types.add(&mSuspendedEffects.valueAt(i)->mType);
8454 }
8455 for (size_t i = 0; i < types.size(); i++) {
8456 setEffectSuspended_l(types[i], false);
8457 }
Steve Block3856b092011-10-20 11:56:00 +01008458 ALOGV("setEffectSuspendedAll_l() remove entry for %08x", mSuspendedEffects.keyAt(index));
Eric Laurent59255e42011-07-27 19:49:51 -07008459 mSuspendedEffects.removeItem((int)kKeyForSuspendAll);
8460 }
8461 }
8462}
8463
Eric Laurent6bffdb82011-09-23 08:40:41 -07008464
8465// The volume effect is used for automated tests only
8466#ifndef OPENSL_ES_H_
8467static const effect_uuid_t SL_IID_VOLUME_ = { 0x09e8ede0, 0xddde, 0x11db, 0xb4f6,
8468 { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } };
8469const effect_uuid_t * const SL_IID_VOLUME = &SL_IID_VOLUME_;
8470#endif //OPENSL_ES_H_
8471
Eric Laurentdb7c0792011-08-10 10:37:50 -07008472bool AudioFlinger::EffectChain::isEffectEligibleForSuspend(const effect_descriptor_t& desc)
8473{
8474 // auxiliary effects and visualizer are never suspended on output mix
8475 if ((mSessionId == AUDIO_SESSION_OUTPUT_MIX) &&
8476 (((desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) ||
Eric Laurent6bffdb82011-09-23 08:40:41 -07008477 (memcmp(&desc.type, SL_IID_VISUALIZATION, sizeof(effect_uuid_t)) == 0) ||
8478 (memcmp(&desc.type, SL_IID_VOLUME, sizeof(effect_uuid_t)) == 0))) {
Eric Laurentdb7c0792011-08-10 10:37:50 -07008479 return false;
8480 }
8481 return true;
8482}
8483
Glenn Kastend0539712012-01-30 12:56:03 -08008484void AudioFlinger::EffectChain::getSuspendEligibleEffects(Vector< sp<AudioFlinger::EffectModule> > &effects)
Eric Laurent59255e42011-07-27 19:49:51 -07008485{
Glenn Kastend0539712012-01-30 12:56:03 -08008486 effects.clear();
Eric Laurent59255e42011-07-27 19:49:51 -07008487 for (size_t i = 0; i < mEffects.size(); i++) {
Glenn Kastend0539712012-01-30 12:56:03 -08008488 if (isEffectEligibleForSuspend(mEffects[i]->desc())) {
8489 effects.add(mEffects[i]);
Eric Laurent59255e42011-07-27 19:49:51 -07008490 }
Eric Laurent59255e42011-07-27 19:49:51 -07008491 }
Eric Laurent59255e42011-07-27 19:49:51 -07008492}
8493
8494sp<AudioFlinger::EffectModule> AudioFlinger::EffectChain::getEffectIfEnabled(
8495 const effect_uuid_t *type)
8496{
Glenn Kasten090f0192012-01-30 13:00:02 -08008497 sp<EffectModule> effect = getEffectFromType_l(type);
8498 return effect != 0 && effect->isEnabled() ? effect : 0;
Eric Laurent59255e42011-07-27 19:49:51 -07008499}
8500
8501void AudioFlinger::EffectChain::checkSuspendOnEffectEnabled(const sp<EffectModule>& effect,
8502 bool enabled)
8503{
Glenn Kasten8d6a2442012-02-08 14:04:28 -08008504 ssize_t index = mSuspendedEffects.indexOfKey(effect->desc().type.timeLow);
Eric Laurent59255e42011-07-27 19:49:51 -07008505 if (enabled) {
8506 if (index < 0) {
8507 // if the effect is not suspend check if all effects are suspended
8508 index = mSuspendedEffects.indexOfKey((int)kKeyForSuspendAll);
8509 if (index < 0) {
8510 return;
8511 }
Eric Laurentdb7c0792011-08-10 10:37:50 -07008512 if (!isEffectEligibleForSuspend(effect->desc())) {
8513 return;
8514 }
Eric Laurent59255e42011-07-27 19:49:51 -07008515 setEffectSuspended_l(&effect->desc().type, enabled);
8516 index = mSuspendedEffects.indexOfKey(effect->desc().type.timeLow);
Eric Laurentdb7c0792011-08-10 10:37:50 -07008517 if (index < 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00008518 ALOGW("checkSuspendOnEffectEnabled() Fx should be suspended here!");
Eric Laurentdb7c0792011-08-10 10:37:50 -07008519 return;
8520 }
Eric Laurent59255e42011-07-27 19:49:51 -07008521 }
Steve Block3856b092011-10-20 11:56:00 +01008522 ALOGV("checkSuspendOnEffectEnabled() enable suspending fx %08x",
Glenn Kastene53b9ea2012-03-12 16:29:55 -07008523 effect->desc().type.timeLow);
Eric Laurent59255e42011-07-27 19:49:51 -07008524 sp<SuspendedEffectDesc> desc = mSuspendedEffects.valueAt(index);
8525 // if effect is requested to suspended but was not yet enabled, supend it now.
8526 if (desc->mEffect == 0) {
8527 desc->mEffect = effect;
8528 effect->setEnabled(false);
8529 effect->setSuspended(true);
8530 }
8531 } else {
8532 if (index < 0) {
8533 return;
8534 }
Steve Block3856b092011-10-20 11:56:00 +01008535 ALOGV("checkSuspendOnEffectEnabled() disable restoring fx %08x",
Glenn Kastene53b9ea2012-03-12 16:29:55 -07008536 effect->desc().type.timeLow);
Eric Laurent59255e42011-07-27 19:49:51 -07008537 sp<SuspendedEffectDesc> desc = mSuspendedEffects.valueAt(index);
8538 desc->mEffect.clear();
8539 effect->setSuspended(false);
8540 }
8541}
8542
Mathias Agopian65ab4712010-07-14 17:59:35 -07008543#undef LOG_TAG
8544#define LOG_TAG "AudioFlinger"
8545
8546// ----------------------------------------------------------------------------
8547
8548status_t AudioFlinger::onTransact(
8549 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
8550{
8551 return BnAudioFlinger::onTransact(code, data, reply, flags);
8552}
8553
Mathias Agopian65ab4712010-07-14 17:59:35 -07008554}; // namespace android