blob: 339f6ea488b6d64aeccc716311e48187db6bd352 [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>
Glenn Kastend8e6fd32012-05-07 11:07:57 -070030#include <utils/Trace.h>
Mathias Agopian65ab4712010-07-14 17:59:35 -070031#include <binder/Parcel.h>
32#include <binder/IPCThreadState.h>
33#include <utils/String16.h>
34#include <utils/threads.h>
Eric Laurent38ccae22011-03-28 18:37:07 -070035#include <utils/Atomic.h>
Mathias Agopian65ab4712010-07-14 17:59:35 -070036
Dima Zavinfce7a472011-04-19 22:30:36 -070037#include <cutils/bitops.h>
Mathias Agopian65ab4712010-07-14 17:59:35 -070038#include <cutils/properties.h>
Glenn Kastenf6b16782011-12-15 09:51:17 -080039#include <cutils/compiler.h>
Mathias Agopian65ab4712010-07-14 17:59:35 -070040
Glenn Kastend3cee2f2012-03-13 17:55:35 -070041#undef ADD_BATTERY_DATA
42
43#ifdef ADD_BATTERY_DATA
Gloria Wang9ee159b2011-02-24 14:51:45 -080044#include <media/IMediaPlayerService.h>
Glenn Kasten25b248e2012-01-03 15:28:29 -080045#include <media/IMediaDeathNotifier.h>
Glenn Kastend3cee2f2012-03-13 17:55:35 -070046#endif
Mathias Agopian65ab4712010-07-14 17:59:35 -070047
48#include <private/media/AudioTrackShared.h>
49#include <private/media/AudioEffectShared.h>
Dima Zavinfce7a472011-04-19 22:30:36 -070050
Dima Zavin64760242011-05-11 14:15:23 -070051#include <system/audio.h>
Dima Zavin7394a4f2011-06-13 18:16:26 -070052#include <hardware/audio.h>
Mathias Agopian65ab4712010-07-14 17:59:35 -070053
54#include "AudioMixer.h"
55#include "AudioFlinger.h"
Glenn Kasten44deb052012-02-05 18:09:08 -080056#include "ServiceUtilities.h"
Mathias Agopian65ab4712010-07-14 17:59:35 -070057
Mathias Agopian65ab4712010-07-14 17:59:35 -070058#include <media/EffectsFactoryApi.h>
Eric Laurent6d8b6942011-06-24 07:01:31 -070059#include <audio_effects/effect_visualizer.h>
Eric Laurent59bd0da2011-08-01 09:52:20 -070060#include <audio_effects/effect_ns.h>
61#include <audio_effects/effect_aec.h>
Mathias Agopian65ab4712010-07-14 17:59:35 -070062
Glenn Kasten3b21c502011-12-15 09:52:39 -080063#include <audio_utils/primitives.h>
64
Eric Laurentfeb0db62011-07-22 09:04:31 -070065#include <powermanager/PowerManager.h>
Glenn Kasten190a46f2012-03-06 11:27:10 -080066
Glenn Kasten4d8d0c32011-07-08 15:26:12 -070067// #define DEBUG_CPU_USAGE 10 // log statistics every n wall clock seconds
Glenn Kasten190a46f2012-03-06 11:27:10 -080068#ifdef DEBUG_CPU_USAGE
69#include <cpustats/CentralTendencyStatistics.h>
70#include <cpustats/ThreadCpuUsage.h>
71#endif
Glenn Kasten4d8d0c32011-07-08 15:26:12 -070072
John Grossman4ff14ba2012-02-08 16:37:41 -080073#include <common_time/cc_helper.h>
74#include <common_time/local_clock.h>
75
Glenn Kasten58912562012-04-03 10:45:00 -070076#include "FastMixer.h"
77
78// NBAIO implementations
79#include "AudioStreamOutSink.h"
80#include "MonoPipe.h"
81#include "MonoPipeReader.h"
82#include "SourceAudioBufferProvider.h"
83
Glenn Kasten1dc28b72012-04-24 10:01:03 -070084#ifdef HAVE_REQUEST_PRIORITY
85#include "SchedulingPolicyService.h"
86#endif
87
Glenn Kasten58912562012-04-03 10:45:00 -070088#ifdef SOAKER
89#include "Soaker.h"
90#endif
91
Mathias Agopian65ab4712010-07-14 17:59:35 -070092// ----------------------------------------------------------------------------
Mathias Agopian65ab4712010-07-14 17:59:35 -070093
John Grossman1c345192012-03-27 14:00:17 -070094// Note: the following macro is used for extremely verbose logging message. In
95// order to run with ALOG_ASSERT turned on, we need to have LOG_NDEBUG set to
96// 0; but one side effect of this is to turn all LOGV's as well. Some messages
97// are so verbose that we want to suppress them even when we have ALOG_ASSERT
98// turned on. Do not uncomment the #def below unless you really know what you
99// are doing and want to see all of the extremely verbose messages.
100//#define VERY_VERY_VERBOSE_LOGGING
101#ifdef VERY_VERY_VERBOSE_LOGGING
102#define ALOGVV ALOGV
103#else
104#define ALOGVV(a...) do { } while(0)
105#endif
Eric Laurentde070132010-07-13 04:45:46 -0700106
Mathias Agopian65ab4712010-07-14 17:59:35 -0700107namespace android {
108
Glenn Kastenec1d6b52011-12-12 09:04:45 -0800109static const char kDeadlockedString[] = "AudioFlinger may be deadlocked\n";
110static const char kHardwareLockedString[] = "Hardware lock is taken\n";
Mathias Agopian65ab4712010-07-14 17:59:35 -0700111
Mathias Agopian65ab4712010-07-14 17:59:35 -0700112static const float MAX_GAIN = 4096.0f;
Glenn Kastenb1cf75c2012-01-17 12:20:54 -0800113static const uint32_t MAX_GAIN_INT = 0x1000;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700114
115// retry counts for buffer fill timeout
116// 50 * ~20msecs = 1 second
117static const int8_t kMaxTrackRetries = 50;
118static const int8_t kMaxTrackStartupRetries = 50;
119// allow less retry attempts on direct output thread.
120// direct outputs can be a scarce resource in audio hardware and should
121// be released as quickly as possible.
122static const int8_t kMaxTrackRetriesDirect = 2;
123
124static const int kDumpLockRetries = 50;
Glenn Kasten7dede872011-12-13 11:04:14 -0800125static const int kDumpLockSleepUs = 20000;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700126
Glenn Kasten7dede872011-12-13 11:04:14 -0800127// don't warn about blocked writes or record buffer overflows more often than this
128static const nsecs_t kWarningThrottleNs = seconds(5);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700129
Eric Laurent7c7f10b2011-06-17 21:29:58 -0700130// RecordThread loop sleep time upon application overrun or audio HAL read error
131static const int kRecordThreadSleepUs = 5000;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700132
Glenn Kasten7dede872011-12-13 11:04:14 -0800133// maximum time to wait for setParameters to complete
134static const nsecs_t kSetParametersTimeoutNs = seconds(2);
Eric Laurent60cd0a02011-09-13 11:40:21 -0700135
Eric Laurent7cafbb32011-11-22 18:50:29 -0800136// minimum sleep time for the mixer thread loop when tracks are active but in underrun
137static const uint32_t kMinThreadSleepTimeUs = 5000;
138// maximum divider applied to the active sleep time in the mixer thread loop
139static const uint32_t kMaxThreadSleepTimeShift = 2;
140
Glenn Kasten58912562012-04-03 10:45:00 -0700141// minimum normal mix buffer size, expressed in milliseconds rather than frames
142static const uint32_t kMinNormalMixBufferSizeMs = 20;
Glenn Kasten4adcede2012-05-14 12:26:02 -0700143// maximum normal mix buffer size
144static const uint32_t kMaxNormalMixBufferSizeMs = 24;
Glenn Kasten58912562012-04-03 10:45:00 -0700145
John Grossman4ff14ba2012-02-08 16:37:41 -0800146nsecs_t AudioFlinger::mStandbyTimeInNsecs = kDefaultStandbyTimeInNsecs;
Eric Laurent7cafbb32011-11-22 18:50:29 -0800147
Glenn Kasten300a2ee2012-04-25 13:47:36 -0700148// Whether to use fast mixer
149static const enum {
150 FastMixer_Never, // never initialize or use: for debugging only
151 FastMixer_Always, // always initialize and use, even if not needed: for debugging only
152 // normal mixer multiplier is 1
153 FastMixer_Static, // initialize if needed, then use all the time if initialized,
Glenn Kasten4adcede2012-05-14 12:26:02 -0700154 // multiplier is calculated based on min & max normal mixer buffer size
Glenn Kasten300a2ee2012-04-25 13:47:36 -0700155 FastMixer_Dynamic, // initialize if needed, then use dynamically depending on track load,
Glenn Kasten4adcede2012-05-14 12:26:02 -0700156 // multiplier is calculated based on min & max normal mixer buffer size
Glenn Kasten300a2ee2012-04-25 13:47:36 -0700157 // FIXME for FastMixer_Dynamic:
158 // Supporting this option will require fixing HALs that can't handle large writes.
159 // For example, one HAL implementation returns an error from a large write,
160 // and another HAL implementation corrupts memory, possibly in the sample rate converter.
161 // We could either fix the HAL implementations, or provide a wrapper that breaks
162 // up large writes into smaller ones, and the wrapper would need to deal with scheduler.
163} kUseFastMixer = FastMixer_Static;
164
Mathias Agopian65ab4712010-07-14 17:59:35 -0700165// ----------------------------------------------------------------------------
166
Glenn Kastend3cee2f2012-03-13 17:55:35 -0700167#ifdef ADD_BATTERY_DATA
Gloria Wang9ee159b2011-02-24 14:51:45 -0800168// To collect the amplifier usage
169static void addBatteryData(uint32_t params) {
Glenn Kasten25b248e2012-01-03 15:28:29 -0800170 sp<IMediaPlayerService> service = IMediaDeathNotifier::getMediaPlayerService();
171 if (service == NULL) {
172 // it already logged
Gloria Wang9ee159b2011-02-24 14:51:45 -0800173 return;
174 }
175
176 service->addBatteryData(params);
177}
Glenn Kastend3cee2f2012-03-13 17:55:35 -0700178#endif
Gloria Wang9ee159b2011-02-24 14:51:45 -0800179
Eric Laurentf7ffb8b2012-04-14 09:06:57 -0700180static int load_audio_interface(const char *if_name, audio_hw_device_t **dev)
Dima Zavin799a70e2011-04-18 16:57:27 -0700181{
Eric Laurentf7ffb8b2012-04-14 09:06:57 -0700182 const hw_module_t *mod;
Dima Zavin799a70e2011-04-18 16:57:27 -0700183 int rc;
184
Eric Laurentf7ffb8b2012-04-14 09:06:57 -0700185 rc = hw_get_module_by_class(AUDIO_HARDWARE_MODULE_ID, if_name, &mod);
186 ALOGE_IF(rc, "%s couldn't load audio hw module %s.%s (%s)", __func__,
187 AUDIO_HARDWARE_MODULE_ID, if_name, strerror(-rc));
188 if (rc) {
Dima Zavin799a70e2011-04-18 16:57:27 -0700189 goto out;
Eric Laurentf7ffb8b2012-04-14 09:06:57 -0700190 }
191 rc = audio_hw_device_open(mod, dev);
192 ALOGE_IF(rc, "%s couldn't open audio hw device in %s.%s (%s)", __func__,
193 AUDIO_HARDWARE_MODULE_ID, if_name, strerror(-rc));
194 if (rc) {
Dima Zavin799a70e2011-04-18 16:57:27 -0700195 goto out;
Eric Laurentf7ffb8b2012-04-14 09:06:57 -0700196 }
197 if ((*dev)->common.version != AUDIO_DEVICE_API_VERSION_CURRENT) {
198 ALOGE("%s wrong audio hw device version %04x", __func__, (*dev)->common.version);
199 rc = BAD_VALUE;
200 goto out;
201 }
Dima Zavin799a70e2011-04-18 16:57:27 -0700202 return 0;
203
204out:
Dima Zavin799a70e2011-04-18 16:57:27 -0700205 *dev = NULL;
206 return rc;
207}
208
Mathias Agopian65ab4712010-07-14 17:59:35 -0700209// ----------------------------------------------------------------------------
210
211AudioFlinger::AudioFlinger()
212 : BnAudioFlinger(),
John Grossman4ff14ba2012-02-08 16:37:41 -0800213 mPrimaryHardwareDev(NULL),
214 mHardwareStatus(AUDIO_HW_IDLE), // see also onFirstRef()
215 mMasterVolume(1.0f),
216 mMasterVolumeSupportLvl(MVS_NONE),
217 mMasterMute(false),
218 mNextUniqueId(1),
219 mMode(AUDIO_MODE_INVALID),
220 mBtNrecIsOff(false)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700221{
Dima Zavin5a61d2f2011-04-19 19:04:32 -0700222}
223
224void AudioFlinger::onFirstRef()
225{
Dima Zavin799a70e2011-04-18 16:57:27 -0700226 int rc = 0;
Dima Zavinfce7a472011-04-19 22:30:36 -0700227
Eric Laurent93575202011-01-18 18:39:02 -0800228 Mutex::Autolock _l(mLock);
229
Dima Zavin799a70e2011-04-18 16:57:27 -0700230 /* TODO: move all this work into an Init() function */
John Grossman4ff14ba2012-02-08 16:37:41 -0800231 char val_str[PROPERTY_VALUE_MAX] = { 0 };
232 if (property_get("ro.audio.flinger_standbytime_ms", val_str, NULL) >= 0) {
233 uint32_t int_val;
234 if (1 == sscanf(val_str, "%u", &int_val)) {
235 mStandbyTimeInNsecs = milliseconds(int_val);
236 ALOGI("Using %u mSec as standby time.", int_val);
237 } else {
238 mStandbyTimeInNsecs = kDefaultStandbyTimeInNsecs;
239 ALOGI("Using default %u mSec as standby time.",
240 (uint32_t)(mStandbyTimeInNsecs / 1000000));
241 }
242 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700243
Eric Laurenta4c5a552012-03-29 10:12:40 -0700244 mMode = AUDIO_MODE_NORMAL;
245 mMasterVolumeSW = 1.0;
246 mMasterVolume = 1.0;
John Grossman4ff14ba2012-02-08 16:37:41 -0800247 mHardwareStatus = AUDIO_HW_IDLE;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700248}
249
250AudioFlinger::~AudioFlinger()
251{
Dima Zavin799a70e2011-04-18 16:57:27 -0700252
Mathias Agopian65ab4712010-07-14 17:59:35 -0700253 while (!mRecordThreads.isEmpty()) {
254 // closeInput() will remove first entry from mRecordThreads
255 closeInput(mRecordThreads.keyAt(0));
256 }
257 while (!mPlaybackThreads.isEmpty()) {
258 // closeOutput() will remove first entry from mPlaybackThreads
259 closeOutput(mPlaybackThreads.keyAt(0));
260 }
Dima Zavin799a70e2011-04-18 16:57:27 -0700261
Glenn Kasten2b213bc2012-02-02 14:05:20 -0800262 for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
263 // no mHardwareLock needed, as there are no other references to this
Eric Laurenta4c5a552012-03-29 10:12:40 -0700264 audio_hw_device_close(mAudioHwDevs.valueAt(i)->hwDevice());
265 delete mAudioHwDevs.valueAt(i);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700266 }
267}
268
Eric Laurenta4c5a552012-03-29 10:12:40 -0700269static const char * const audio_interfaces[] = {
270 AUDIO_HARDWARE_MODULE_ID_PRIMARY,
271 AUDIO_HARDWARE_MODULE_ID_A2DP,
272 AUDIO_HARDWARE_MODULE_ID_USB,
273};
274#define ARRAY_SIZE(x) (sizeof((x))/sizeof(((x)[0])))
275
276audio_hw_device_t* AudioFlinger::findSuitableHwDev_l(audio_module_handle_t module, uint32_t devices)
Dima Zavin799a70e2011-04-18 16:57:27 -0700277{
Eric Laurenta4c5a552012-03-29 10:12:40 -0700278 // if module is 0, the request comes from an old policy manager and we should load
279 // well known modules
280 if (module == 0) {
281 ALOGW("findSuitableHwDev_l() loading well know audio hw modules");
282 for (size_t i = 0; i < ARRAY_SIZE(audio_interfaces); i++) {
283 loadHwModule_l(audio_interfaces[i]);
284 }
285 } else {
286 // check a match for the requested module handle
287 AudioHwDevice *audioHwdevice = mAudioHwDevs.valueFor(module);
288 if (audioHwdevice != NULL) {
289 return audioHwdevice->hwDevice();
290 }
291 }
292 // then try to find a module supporting the requested device.
Dima Zavin799a70e2011-04-18 16:57:27 -0700293 for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
Eric Laurenta4c5a552012-03-29 10:12:40 -0700294 audio_hw_device_t *dev = mAudioHwDevs.valueAt(i)->hwDevice();
Dima Zavin799a70e2011-04-18 16:57:27 -0700295 if ((dev->get_supported_devices(dev) & devices) == devices)
296 return dev;
297 }
Eric Laurenta4c5a552012-03-29 10:12:40 -0700298
Dima Zavin799a70e2011-04-18 16:57:27 -0700299 return NULL;
300}
Mathias Agopian65ab4712010-07-14 17:59:35 -0700301
302status_t AudioFlinger::dumpClients(int fd, const Vector<String16>& args)
303{
304 const size_t SIZE = 256;
305 char buffer[SIZE];
306 String8 result;
307
308 result.append("Clients:\n");
309 for (size_t i = 0; i < mClients.size(); ++i) {
Glenn Kasten77c11192012-01-25 14:27:41 -0800310 sp<Client> client = mClients.valueAt(i).promote();
311 if (client != 0) {
312 snprintf(buffer, SIZE, " pid: %d\n", client->pid());
313 result.append(buffer);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700314 }
315 }
Marco Nelissen3a34bef2011-08-02 13:33:41 -0700316
317 result.append("Global session refs:\n");
Glenn Kasten012ca6b2012-03-06 11:22:01 -0800318 result.append(" session pid count\n");
Marco Nelissen3a34bef2011-08-02 13:33:41 -0700319 for (size_t i = 0; i < mAudioSessionRefs.size(); i++) {
320 AudioSessionRef *r = mAudioSessionRefs[i];
Glenn Kasten012ca6b2012-03-06 11:22:01 -0800321 snprintf(buffer, SIZE, " %7d %3d %3d\n", r->mSessionid, r->mPid, r->mCnt);
Marco Nelissen3a34bef2011-08-02 13:33:41 -0700322 result.append(buffer);
323 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700324 write(fd, result.string(), result.size());
325 return NO_ERROR;
326}
327
328
329status_t AudioFlinger::dumpInternals(int fd, const Vector<String16>& args)
330{
331 const size_t SIZE = 256;
332 char buffer[SIZE];
333 String8 result;
Glenn Kastena4454b42012-01-04 11:02:33 -0800334 hardware_call_state hardwareStatus = mHardwareStatus;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700335
John Grossman4ff14ba2012-02-08 16:37:41 -0800336 snprintf(buffer, SIZE, "Hardware status: %d\n"
337 "Standby Time mSec: %u\n",
338 hardwareStatus,
339 (uint32_t)(mStandbyTimeInNsecs / 1000000));
Mathias Agopian65ab4712010-07-14 17:59:35 -0700340 result.append(buffer);
341 write(fd, result.string(), result.size());
342 return NO_ERROR;
343}
344
345status_t AudioFlinger::dumpPermissionDenial(int fd, const Vector<String16>& args)
346{
347 const size_t SIZE = 256;
348 char buffer[SIZE];
349 String8 result;
350 snprintf(buffer, SIZE, "Permission Denial: "
351 "can't dump AudioFlinger from pid=%d, uid=%d\n",
352 IPCThreadState::self()->getCallingPid(),
353 IPCThreadState::self()->getCallingUid());
354 result.append(buffer);
355 write(fd, result.string(), result.size());
356 return NO_ERROR;
357}
358
359static bool tryLock(Mutex& mutex)
360{
361 bool locked = false;
362 for (int i = 0; i < kDumpLockRetries; ++i) {
363 if (mutex.tryLock() == NO_ERROR) {
364 locked = true;
365 break;
366 }
Glenn Kasten7dede872011-12-13 11:04:14 -0800367 usleep(kDumpLockSleepUs);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700368 }
369 return locked;
370}
371
372status_t AudioFlinger::dump(int fd, const Vector<String16>& args)
373{
Glenn Kasten44deb052012-02-05 18:09:08 -0800374 if (!dumpAllowed()) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700375 dumpPermissionDenial(fd, args);
376 } else {
377 // get state of hardware lock
378 bool hardwareLocked = tryLock(mHardwareLock);
379 if (!hardwareLocked) {
380 String8 result(kHardwareLockedString);
381 write(fd, result.string(), result.size());
382 } else {
383 mHardwareLock.unlock();
384 }
385
386 bool locked = tryLock(mLock);
387
388 // failed to lock - AudioFlinger is probably deadlocked
389 if (!locked) {
390 String8 result(kDeadlockedString);
391 write(fd, result.string(), result.size());
392 }
393
394 dumpClients(fd, args);
395 dumpInternals(fd, args);
396
397 // dump playback threads
398 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
399 mPlaybackThreads.valueAt(i)->dump(fd, args);
400 }
401
402 // dump record threads
403 for (size_t i = 0; i < mRecordThreads.size(); i++) {
404 mRecordThreads.valueAt(i)->dump(fd, args);
405 }
406
Dima Zavin799a70e2011-04-18 16:57:27 -0700407 // dump all hardware devs
408 for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
Eric Laurenta4c5a552012-03-29 10:12:40 -0700409 audio_hw_device_t *dev = mAudioHwDevs.valueAt(i)->hwDevice();
Dima Zavin799a70e2011-04-18 16:57:27 -0700410 dev->dump(dev, fd);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700411 }
412 if (locked) mLock.unlock();
413 }
414 return NO_ERROR;
415}
416
Glenn Kasten98ec94c2012-01-25 14:28:29 -0800417sp<AudioFlinger::Client> AudioFlinger::registerPid_l(pid_t pid)
418{
419 // If pid is already in the mClients wp<> map, then use that entry
420 // (for which promote() is always != 0), otherwise create a new entry and Client.
421 sp<Client> client = mClients.valueFor(pid).promote();
422 if (client == 0) {
423 client = new Client(this, pid);
424 mClients.add(pid, client);
425 }
426
427 return client;
428}
Mathias Agopian65ab4712010-07-14 17:59:35 -0700429
430// IAudioFlinger interface
431
432
433sp<IAudioTrack> AudioFlinger::createTrack(
434 pid_t pid,
Glenn Kastenfff6d712012-01-12 16:38:12 -0800435 audio_stream_type_t streamType,
Mathias Agopian65ab4712010-07-14 17:59:35 -0700436 uint32_t sampleRate,
Glenn Kasten58f30212012-01-12 12:27:51 -0800437 audio_format_t format,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -0700438 uint32_t channelMask,
Mathias Agopian65ab4712010-07-14 17:59:35 -0700439 int frameCount,
Glenn Kastena075db42012-03-06 11:22:44 -0800440 IAudioFlinger::track_flags_t flags,
Mathias Agopian65ab4712010-07-14 17:59:35 -0700441 const sp<IMemory>& sharedBuffer,
Glenn Kasten72ef00d2012-01-17 11:09:42 -0800442 audio_io_handle_t output,
Glenn Kasten3acbd052012-02-28 10:39:56 -0800443 pid_t tid,
Mathias Agopian65ab4712010-07-14 17:59:35 -0700444 int *sessionId,
445 status_t *status)
446{
447 sp<PlaybackThread::Track> track;
448 sp<TrackHandle> trackHandle;
449 sp<Client> client;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700450 status_t lStatus;
451 int lSessionId;
452
Glenn Kasten263709e2012-01-06 08:40:01 -0800453 // client AudioTrack::set already implements AUDIO_STREAM_DEFAULT => AUDIO_STREAM_MUSIC,
454 // but if someone uses binder directly they could bypass that and cause us to crash
455 if (uint32_t(streamType) >= AUDIO_STREAM_CNT) {
Steve Block29357bc2012-01-06 19:20:56 +0000456 ALOGE("createTrack() invalid stream type %d", streamType);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700457 lStatus = BAD_VALUE;
458 goto Exit;
459 }
460
461 {
462 Mutex::Autolock _l(mLock);
463 PlaybackThread *thread = checkPlaybackThread_l(output);
Eric Laurent39e94f82010-07-28 01:32:47 -0700464 PlaybackThread *effectThread = NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700465 if (thread == NULL) {
Steve Block29357bc2012-01-06 19:20:56 +0000466 ALOGE("unknown output thread");
Mathias Agopian65ab4712010-07-14 17:59:35 -0700467 lStatus = BAD_VALUE;
468 goto Exit;
469 }
470
Glenn Kasten98ec94c2012-01-25 14:28:29 -0800471 client = registerPid_l(pid);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700472
Steve Block3856b092011-10-20 11:56:00 +0100473 ALOGV("createTrack() sessionId: %d", (sessionId == NULL) ? -2 : *sessionId);
Dima Zavinfce7a472011-04-19 22:30:36 -0700474 if (sessionId != NULL && *sessionId != AUDIO_SESSION_OUTPUT_MIX) {
Eric Laurentde070132010-07-13 04:45:46 -0700475 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
Eric Laurent39e94f82010-07-28 01:32:47 -0700476 sp<PlaybackThread> t = mPlaybackThreads.valueAt(i);
477 if (mPlaybackThreads.keyAt(i) != output) {
478 // prevent same audio session on different output threads
479 uint32_t sessions = t->hasAudioSession(*sessionId);
480 if (sessions & PlaybackThread::TRACK_SESSION) {
Steve Block29357bc2012-01-06 19:20:56 +0000481 ALOGE("createTrack() session ID %d already in use", *sessionId);
Eric Laurent39e94f82010-07-28 01:32:47 -0700482 lStatus = BAD_VALUE;
483 goto Exit;
484 }
485 // check if an effect with same session ID is waiting for a track to be created
486 if (sessions & PlaybackThread::EFFECT_SESSION) {
487 effectThread = t.get();
488 }
Eric Laurentde070132010-07-13 04:45:46 -0700489 }
490 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700491 lSessionId = *sessionId;
492 } else {
Eric Laurentde070132010-07-13 04:45:46 -0700493 // if no audio session id is provided, create one here
Eric Laurent7c7f10b2011-06-17 21:29:58 -0700494 lSessionId = nextUniqueId();
Mathias Agopian65ab4712010-07-14 17:59:35 -0700495 if (sessionId != NULL) {
496 *sessionId = lSessionId;
497 }
498 }
Steve Block3856b092011-10-20 11:56:00 +0100499 ALOGV("createTrack() lSessionId: %d", lSessionId);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700500
501 track = thread->createTrack_l(client, streamType, sampleRate, format,
Glenn Kasten3acbd052012-02-28 10:39:56 -0800502 channelMask, frameCount, sharedBuffer, lSessionId, flags, tid, &lStatus);
Eric Laurent39e94f82010-07-28 01:32:47 -0700503
504 // move effect chain to this output thread if an effect on same session was waiting
505 // for a track to be created
506 if (lStatus == NO_ERROR && effectThread != NULL) {
507 Mutex::Autolock _dl(thread->mLock);
508 Mutex::Autolock _sl(effectThread->mLock);
509 moveEffectChain_l(lSessionId, effectThread, thread, true);
510 }
Eric Laurenta011e352012-03-29 15:51:43 -0700511
512 // Look for sync events awaiting for a session to be used.
513 for (int i = 0; i < (int)mPendingSyncEvents.size(); i++) {
514 if (mPendingSyncEvents[i]->triggerSession() == lSessionId) {
515 if (thread->isValidSyncEvent(mPendingSyncEvents[i])) {
Eric Laurent29864602012-05-08 18:57:51 -0700516 if (lStatus == NO_ERROR) {
517 track->setSyncEvent(mPendingSyncEvents[i]);
518 } else {
519 mPendingSyncEvents[i]->cancel();
520 }
Eric Laurenta011e352012-03-29 15:51:43 -0700521 mPendingSyncEvents.removeAt(i);
522 i--;
523 }
524 }
525 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700526 }
527 if (lStatus == NO_ERROR) {
528 trackHandle = new TrackHandle(track);
529 } else {
530 // remove local strong reference to Client before deleting the Track so that the Client
531 // destructor is called by the TrackBase destructor with mLock held
532 client.clear();
533 track.clear();
534 }
535
536Exit:
Glenn Kastene53b9ea2012-03-12 16:29:55 -0700537 if (status != NULL) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700538 *status = lStatus;
539 }
540 return trackHandle;
541}
542
Glenn Kasten72ef00d2012-01-17 11:09:42 -0800543uint32_t AudioFlinger::sampleRate(audio_io_handle_t output) const
Mathias Agopian65ab4712010-07-14 17:59:35 -0700544{
545 Mutex::Autolock _l(mLock);
546 PlaybackThread *thread = checkPlaybackThread_l(output);
547 if (thread == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +0000548 ALOGW("sampleRate() unknown thread %d", output);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700549 return 0;
550 }
551 return thread->sampleRate();
552}
553
Glenn Kasten72ef00d2012-01-17 11:09:42 -0800554int AudioFlinger::channelCount(audio_io_handle_t output) const
Mathias Agopian65ab4712010-07-14 17:59:35 -0700555{
556 Mutex::Autolock _l(mLock);
557 PlaybackThread *thread = checkPlaybackThread_l(output);
558 if (thread == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +0000559 ALOGW("channelCount() unknown thread %d", output);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700560 return 0;
561 }
562 return thread->channelCount();
563}
564
Glenn Kasten72ef00d2012-01-17 11:09:42 -0800565audio_format_t AudioFlinger::format(audio_io_handle_t output) const
Mathias Agopian65ab4712010-07-14 17:59:35 -0700566{
567 Mutex::Autolock _l(mLock);
568 PlaybackThread *thread = checkPlaybackThread_l(output);
569 if (thread == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +0000570 ALOGW("format() unknown thread %d", output);
Glenn Kasten58f30212012-01-12 12:27:51 -0800571 return AUDIO_FORMAT_INVALID;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700572 }
573 return thread->format();
574}
575
Glenn Kasten72ef00d2012-01-17 11:09:42 -0800576size_t AudioFlinger::frameCount(audio_io_handle_t output) const
Mathias Agopian65ab4712010-07-14 17:59:35 -0700577{
578 Mutex::Autolock _l(mLock);
579 PlaybackThread *thread = checkPlaybackThread_l(output);
580 if (thread == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +0000581 ALOGW("frameCount() unknown thread %d", output);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700582 return 0;
583 }
Glenn Kasten58912562012-04-03 10:45:00 -0700584 // FIXME currently returns the normal mixer's frame count to avoid confusing legacy callers;
585 // should examine all callers and fix them to handle smaller counts
Mathias Agopian65ab4712010-07-14 17:59:35 -0700586 return thread->frameCount();
587}
588
Glenn Kasten72ef00d2012-01-17 11:09:42 -0800589uint32_t AudioFlinger::latency(audio_io_handle_t output) const
Mathias Agopian65ab4712010-07-14 17:59:35 -0700590{
591 Mutex::Autolock _l(mLock);
592 PlaybackThread *thread = checkPlaybackThread_l(output);
593 if (thread == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +0000594 ALOGW("latency() unknown thread %d", output);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700595 return 0;
596 }
597 return thread->latency();
598}
599
600status_t AudioFlinger::setMasterVolume(float value)
601{
Eric Laurenta1884f92011-08-23 08:25:03 -0700602 status_t ret = initCheck();
603 if (ret != NO_ERROR) {
604 return ret;
605 }
606
Mathias Agopian65ab4712010-07-14 17:59:35 -0700607 // check calling permissions
608 if (!settingsAllowed()) {
609 return PERMISSION_DENIED;
610 }
611
John Grossman4ff14ba2012-02-08 16:37:41 -0800612 float swmv = value;
613
Eric Laurenta4c5a552012-03-29 10:12:40 -0700614 Mutex::Autolock _l(mLock);
615
Mathias Agopian65ab4712010-07-14 17:59:35 -0700616 // when hw supports master volume, don't scale in sw mixer
John Grossman4ff14ba2012-02-08 16:37:41 -0800617 if (MVS_NONE != mMasterVolumeSupportLvl) {
618 for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
619 AutoMutex lock(mHardwareLock);
Eric Laurenta4c5a552012-03-29 10:12:40 -0700620 audio_hw_device_t *dev = mAudioHwDevs.valueAt(i)->hwDevice();
John Grossman4ff14ba2012-02-08 16:37:41 -0800621
622 mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
623 if (NULL != dev->set_master_volume) {
624 dev->set_master_volume(dev, value);
625 }
626 mHardwareStatus = AUDIO_HW_IDLE;
Eric Laurent93575202011-01-18 18:39:02 -0800627 }
John Grossman4ff14ba2012-02-08 16:37:41 -0800628
629 swmv = 1.0;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700630 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700631
John Grossman4ff14ba2012-02-08 16:37:41 -0800632 mMasterVolume = value;
633 mMasterVolumeSW = swmv;
Glenn Kasten8d6a2442012-02-08 14:04:28 -0800634 for (size_t i = 0; i < mPlaybackThreads.size(); i++)
Glenn Kastene53b9ea2012-03-12 16:29:55 -0700635 mPlaybackThreads.valueAt(i)->setMasterVolume(swmv);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700636
637 return NO_ERROR;
638}
639
Glenn Kastenf78aee72012-01-04 11:00:47 -0800640status_t AudioFlinger::setMode(audio_mode_t mode)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700641{
Eric Laurenta1884f92011-08-23 08:25:03 -0700642 status_t ret = initCheck();
643 if (ret != NO_ERROR) {
644 return ret;
645 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700646
647 // check calling permissions
648 if (!settingsAllowed()) {
649 return PERMISSION_DENIED;
650 }
Glenn Kasten930f4ca2012-01-06 16:47:31 -0800651 if (uint32_t(mode) >= AUDIO_MODE_CNT) {
Steve Block5ff1dd52012-01-05 23:22:43 +0000652 ALOGW("Illegal value: setMode(%d)", mode);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700653 return BAD_VALUE;
654 }
655
656 { // scope for the lock
657 AutoMutex lock(mHardwareLock);
658 mHardwareStatus = AUDIO_HW_SET_MODE;
Dima Zavin799a70e2011-04-18 16:57:27 -0700659 ret = mPrimaryHardwareDev->set_mode(mPrimaryHardwareDev, mode);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700660 mHardwareStatus = AUDIO_HW_IDLE;
661 }
662
663 if (NO_ERROR == ret) {
664 Mutex::Autolock _l(mLock);
665 mMode = mode;
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)->setMode(mode);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700668 }
669
670 return ret;
671}
672
673status_t AudioFlinger::setMicMute(bool state)
674{
Eric Laurenta1884f92011-08-23 08:25:03 -0700675 status_t ret = initCheck();
676 if (ret != NO_ERROR) {
677 return ret;
678 }
679
Mathias Agopian65ab4712010-07-14 17:59:35 -0700680 // check calling permissions
681 if (!settingsAllowed()) {
682 return PERMISSION_DENIED;
683 }
684
685 AutoMutex lock(mHardwareLock);
686 mHardwareStatus = AUDIO_HW_SET_MIC_MUTE;
Eric Laurenta1884f92011-08-23 08:25:03 -0700687 ret = mPrimaryHardwareDev->set_mic_mute(mPrimaryHardwareDev, state);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700688 mHardwareStatus = AUDIO_HW_IDLE;
689 return ret;
690}
691
692bool AudioFlinger::getMicMute() const
693{
Eric Laurenta1884f92011-08-23 08:25:03 -0700694 status_t ret = initCheck();
695 if (ret != NO_ERROR) {
696 return false;
697 }
698
Dima Zavinfce7a472011-04-19 22:30:36 -0700699 bool state = AUDIO_MODE_INVALID;
Glenn Kasten2b213bc2012-02-02 14:05:20 -0800700 AutoMutex lock(mHardwareLock);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700701 mHardwareStatus = AUDIO_HW_GET_MIC_MUTE;
Dima Zavin799a70e2011-04-18 16:57:27 -0700702 mPrimaryHardwareDev->get_mic_mute(mPrimaryHardwareDev, &state);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700703 mHardwareStatus = AUDIO_HW_IDLE;
704 return state;
705}
706
707status_t AudioFlinger::setMasterMute(bool muted)
708{
709 // check calling permissions
710 if (!settingsAllowed()) {
711 return PERMISSION_DENIED;
712 }
713
Eric Laurent93575202011-01-18 18:39:02 -0800714 Mutex::Autolock _l(mLock);
Glenn Kasten99e53b82012-01-19 08:59:58 -0800715 // This is an optimization, so PlaybackThread doesn't have to look at the one from AudioFlinger
Mathias Agopian65ab4712010-07-14 17:59:35 -0700716 mMasterMute = muted;
Glenn Kasten8d6a2442012-02-08 14:04:28 -0800717 for (size_t i = 0; i < mPlaybackThreads.size(); i++)
Glenn Kastene53b9ea2012-03-12 16:29:55 -0700718 mPlaybackThreads.valueAt(i)->setMasterMute(muted);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700719
720 return NO_ERROR;
721}
722
723float AudioFlinger::masterVolume() const
724{
Glenn Kasten98067102011-12-13 11:47:54 -0800725 Mutex::Autolock _l(mLock);
726 return masterVolume_l();
Mathias Agopian65ab4712010-07-14 17:59:35 -0700727}
728
John Grossman4ff14ba2012-02-08 16:37:41 -0800729float AudioFlinger::masterVolumeSW() const
730{
731 Mutex::Autolock _l(mLock);
732 return masterVolumeSW_l();
733}
734
Mathias Agopian65ab4712010-07-14 17:59:35 -0700735bool AudioFlinger::masterMute() const
736{
Glenn Kasten98067102011-12-13 11:47:54 -0800737 Mutex::Autolock _l(mLock);
738 return masterMute_l();
Mathias Agopian65ab4712010-07-14 17:59:35 -0700739}
740
John Grossman4ff14ba2012-02-08 16:37:41 -0800741float AudioFlinger::masterVolume_l() const
742{
743 if (MVS_FULL == mMasterVolumeSupportLvl) {
744 float ret_val;
745 AutoMutex lock(mHardwareLock);
746
747 mHardwareStatus = AUDIO_HW_GET_MASTER_VOLUME;
Glenn Kasten5798d4e2012-03-08 12:18:35 -0800748 ALOG_ASSERT((NULL != mPrimaryHardwareDev) &&
749 (NULL != mPrimaryHardwareDev->get_master_volume),
750 "can't get master volume");
John Grossman4ff14ba2012-02-08 16:37:41 -0800751
752 mPrimaryHardwareDev->get_master_volume(mPrimaryHardwareDev, &ret_val);
753 mHardwareStatus = AUDIO_HW_IDLE;
754 return ret_val;
755 }
756
757 return mMasterVolume;
758}
759
Glenn Kasten72ef00d2012-01-17 11:09:42 -0800760status_t AudioFlinger::setStreamVolume(audio_stream_type_t stream, float value,
761 audio_io_handle_t output)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700762{
763 // check calling permissions
764 if (!settingsAllowed()) {
765 return PERMISSION_DENIED;
766 }
767
Glenn Kasten263709e2012-01-06 08:40:01 -0800768 if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
Steve Block29357bc2012-01-06 19:20:56 +0000769 ALOGE("setStreamVolume() invalid stream %d", stream);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700770 return BAD_VALUE;
771 }
772
773 AutoMutex lock(mLock);
774 PlaybackThread *thread = NULL;
775 if (output) {
776 thread = checkPlaybackThread_l(output);
777 if (thread == NULL) {
778 return BAD_VALUE;
779 }
780 }
781
782 mStreamTypes[stream].volume = value;
783
784 if (thread == NULL) {
Glenn Kasten8d6a2442012-02-08 14:04:28 -0800785 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
Glenn Kastene53b9ea2012-03-12 16:29:55 -0700786 mPlaybackThreads.valueAt(i)->setStreamVolume(stream, value);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700787 }
788 } else {
789 thread->setStreamVolume(stream, value);
790 }
791
792 return NO_ERROR;
793}
794
Glenn Kastenfff6d712012-01-12 16:38:12 -0800795status_t AudioFlinger::setStreamMute(audio_stream_type_t stream, bool muted)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700796{
797 // check calling permissions
798 if (!settingsAllowed()) {
799 return PERMISSION_DENIED;
800 }
801
Glenn Kasten263709e2012-01-06 08:40:01 -0800802 if (uint32_t(stream) >= AUDIO_STREAM_CNT ||
Dima Zavinfce7a472011-04-19 22:30:36 -0700803 uint32_t(stream) == AUDIO_STREAM_ENFORCED_AUDIBLE) {
Steve Block29357bc2012-01-06 19:20:56 +0000804 ALOGE("setStreamMute() invalid stream %d", stream);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700805 return BAD_VALUE;
806 }
807
Eric Laurent93575202011-01-18 18:39:02 -0800808 AutoMutex lock(mLock);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700809 mStreamTypes[stream].mute = muted;
810 for (uint32_t i = 0; i < mPlaybackThreads.size(); i++)
Glenn Kastene53b9ea2012-03-12 16:29:55 -0700811 mPlaybackThreads.valueAt(i)->setStreamMute(stream, muted);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700812
813 return NO_ERROR;
814}
815
Glenn Kasten72ef00d2012-01-17 11:09:42 -0800816float AudioFlinger::streamVolume(audio_stream_type_t stream, audio_io_handle_t output) const
Mathias Agopian65ab4712010-07-14 17:59:35 -0700817{
Glenn Kasten263709e2012-01-06 08:40:01 -0800818 if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700819 return 0.0f;
820 }
821
822 AutoMutex lock(mLock);
823 float volume;
824 if (output) {
825 PlaybackThread *thread = checkPlaybackThread_l(output);
826 if (thread == NULL) {
827 return 0.0f;
828 }
829 volume = thread->streamVolume(stream);
830 } else {
Glenn Kasten6637baa2012-01-09 09:40:36 -0800831 volume = streamVolume_l(stream);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700832 }
833
834 return volume;
835}
836
Glenn Kastenfff6d712012-01-12 16:38:12 -0800837bool AudioFlinger::streamMute(audio_stream_type_t stream) const
Mathias Agopian65ab4712010-07-14 17:59:35 -0700838{
Glenn Kasten263709e2012-01-06 08:40:01 -0800839 if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700840 return true;
841 }
842
Glenn Kasten6637baa2012-01-09 09:40:36 -0800843 AutoMutex lock(mLock);
844 return streamMute_l(stream);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700845}
846
Glenn Kasten72ef00d2012-01-17 11:09:42 -0800847status_t AudioFlinger::setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700848{
Glenn Kasten23d82a92012-02-03 11:10:00 -0800849 ALOGV("setParameters(): io %d, keyvalue %s, tid %d, calling pid %d",
Mathias Agopian65ab4712010-07-14 17:59:35 -0700850 ioHandle, keyValuePairs.string(), gettid(), IPCThreadState::self()->getCallingPid());
851 // check calling permissions
852 if (!settingsAllowed()) {
853 return PERMISSION_DENIED;
854 }
855
Mathias Agopian65ab4712010-07-14 17:59:35 -0700856 // ioHandle == 0 means the parameters are global to the audio hardware interface
857 if (ioHandle == 0) {
Eric Laurenta4c5a552012-03-29 10:12:40 -0700858 Mutex::Autolock _l(mLock);
Dima Zavin799a70e2011-04-18 16:57:27 -0700859 status_t final_result = NO_ERROR;
Glenn Kasten8abf44d2012-02-02 14:16:03 -0800860 {
Eric Laurenta4c5a552012-03-29 10:12:40 -0700861 AutoMutex lock(mHardwareLock);
862 mHardwareStatus = AUDIO_HW_SET_PARAMETER;
863 for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
864 audio_hw_device_t *dev = mAudioHwDevs.valueAt(i)->hwDevice();
865 status_t result = dev->set_parameters(dev, keyValuePairs.string());
866 final_result = result ?: final_result;
867 }
868 mHardwareStatus = AUDIO_HW_IDLE;
Glenn Kasten8abf44d2012-02-02 14:16:03 -0800869 }
Eric Laurent59bd0da2011-08-01 09:52:20 -0700870 // disable AEC and NS if the device is a BT SCO headset supporting those pre processings
871 AudioParameter param = AudioParameter(keyValuePairs);
872 String8 value;
873 if (param.get(String8(AUDIO_PARAMETER_KEY_BT_NREC), value) == NO_ERROR) {
Eric Laurentbee53372011-08-29 12:42:48 -0700874 bool btNrecIsOff = (value == AUDIO_PARAMETER_VALUE_OFF);
875 if (mBtNrecIsOff != btNrecIsOff) {
Eric Laurent59bd0da2011-08-01 09:52:20 -0700876 for (size_t i = 0; i < mRecordThreads.size(); i++) {
877 sp<RecordThread> thread = mRecordThreads.valueAt(i);
878 RecordThread::RecordTrack *track = thread->track();
879 if (track != NULL) {
880 audio_devices_t device = (audio_devices_t)(
881 thread->device() & AUDIO_DEVICE_IN_ALL);
Eric Laurentbee53372011-08-29 12:42:48 -0700882 bool suspend = audio_is_bluetooth_sco_device(device) && btNrecIsOff;
Eric Laurent59bd0da2011-08-01 09:52:20 -0700883 thread->setEffectSuspended(FX_IID_AEC,
884 suspend,
885 track->sessionId());
886 thread->setEffectSuspended(FX_IID_NS,
887 suspend,
888 track->sessionId());
889 }
890 }
Eric Laurentbee53372011-08-29 12:42:48 -0700891 mBtNrecIsOff = btNrecIsOff;
Eric Laurent59bd0da2011-08-01 09:52:20 -0700892 }
893 }
Dima Zavin799a70e2011-04-18 16:57:27 -0700894 return final_result;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700895 }
896
897 // hold a strong ref on thread in case closeOutput() or closeInput() is called
898 // and the thread is exited once the lock is released
899 sp<ThreadBase> thread;
900 {
901 Mutex::Autolock _l(mLock);
902 thread = checkPlaybackThread_l(ioHandle);
903 if (thread == NULL) {
904 thread = checkRecordThread_l(ioHandle);
Glenn Kasten7fc9a6f2012-01-10 10:46:34 -0800905 } else if (thread == primaryPlaybackThread_l()) {
Eric Laurent7c7f10b2011-06-17 21:29:58 -0700906 // indicate output device change to all input threads for pre processing
907 AudioParameter param = AudioParameter(keyValuePairs);
908 int value;
Eric Laurent89d94e72012-03-16 20:37:59 -0700909 if ((param.getInt(String8(AudioParameter::keyRouting), value) == NO_ERROR) &&
910 (value != 0)) {
Eric Laurent7c7f10b2011-06-17 21:29:58 -0700911 for (size_t i = 0; i < mRecordThreads.size(); i++) {
912 mRecordThreads.valueAt(i)->setParameters(keyValuePairs);
913 }
914 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700915 }
916 }
Glenn Kasten7378ca52012-01-20 13:44:40 -0800917 if (thread != 0) {
918 return thread->setParameters(keyValuePairs);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700919 }
920 return BAD_VALUE;
921}
922
Glenn Kasten72ef00d2012-01-17 11:09:42 -0800923String8 AudioFlinger::getParameters(audio_io_handle_t ioHandle, const String8& keys) const
Mathias Agopian65ab4712010-07-14 17:59:35 -0700924{
Glenn Kasten23d82a92012-02-03 11:10:00 -0800925// ALOGV("getParameters() io %d, keys %s, tid %d, calling pid %d",
Mathias Agopian65ab4712010-07-14 17:59:35 -0700926// ioHandle, keys.string(), gettid(), IPCThreadState::self()->getCallingPid());
927
Eric Laurenta4c5a552012-03-29 10:12:40 -0700928 Mutex::Autolock _l(mLock);
929
Mathias Agopian65ab4712010-07-14 17:59:35 -0700930 if (ioHandle == 0) {
Dima Zavinfce7a472011-04-19 22:30:36 -0700931 String8 out_s8;
932
Dima Zavin799a70e2011-04-18 16:57:27 -0700933 for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
Glenn Kasten8abf44d2012-02-02 14:16:03 -0800934 char *s;
935 {
936 AutoMutex lock(mHardwareLock);
937 mHardwareStatus = AUDIO_HW_GET_PARAMETER;
Eric Laurenta4c5a552012-03-29 10:12:40 -0700938 audio_hw_device_t *dev = mAudioHwDevs.valueAt(i)->hwDevice();
Glenn Kasten8abf44d2012-02-02 14:16:03 -0800939 s = dev->get_parameters(dev, keys.string());
940 mHardwareStatus = AUDIO_HW_IDLE;
941 }
John Grossmanef7740b2012-02-09 11:28:36 -0800942 out_s8 += String8(s ? s : "");
Dima Zavin799a70e2011-04-18 16:57:27 -0700943 free(s);
944 }
Dima Zavinfce7a472011-04-19 22:30:36 -0700945 return out_s8;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700946 }
947
Mathias Agopian65ab4712010-07-14 17:59:35 -0700948 PlaybackThread *playbackThread = checkPlaybackThread_l(ioHandle);
949 if (playbackThread != NULL) {
950 return playbackThread->getParameters(keys);
951 }
952 RecordThread *recordThread = checkRecordThread_l(ioHandle);
953 if (recordThread != NULL) {
954 return recordThread->getParameters(keys);
955 }
956 return String8("");
957}
958
Glenn Kastenf587ba52012-01-26 16:25:10 -0800959size_t AudioFlinger::getInputBufferSize(uint32_t sampleRate, audio_format_t format, int channelCount) const
Mathias Agopian65ab4712010-07-14 17:59:35 -0700960{
Eric Laurenta1884f92011-08-23 08:25:03 -0700961 status_t ret = initCheck();
962 if (ret != NO_ERROR) {
963 return 0;
964 }
965
Glenn Kasten2b213bc2012-02-02 14:05:20 -0800966 AutoMutex lock(mHardwareLock);
967 mHardwareStatus = AUDIO_HW_GET_INPUT_BUFFER_SIZE;
Eric Laurentf7ffb8b2012-04-14 09:06:57 -0700968 struct audio_config config = {
969 sample_rate: sampleRate,
970 channel_mask: audio_channel_in_mask_from_count(channelCount),
971 format: format,
972 };
973 size_t size = mPrimaryHardwareDev->get_input_buffer_size(mPrimaryHardwareDev, &config);
Glenn Kasten2b213bc2012-02-02 14:05:20 -0800974 mHardwareStatus = AUDIO_HW_IDLE;
975 return size;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700976}
977
Glenn Kasten72ef00d2012-01-17 11:09:42 -0800978unsigned int AudioFlinger::getInputFramesLost(audio_io_handle_t ioHandle) const
Mathias Agopian65ab4712010-07-14 17:59:35 -0700979{
980 if (ioHandle == 0) {
981 return 0;
982 }
983
984 Mutex::Autolock _l(mLock);
985
986 RecordThread *recordThread = checkRecordThread_l(ioHandle);
987 if (recordThread != NULL) {
988 return recordThread->getInputFramesLost();
989 }
990 return 0;
991}
992
993status_t AudioFlinger::setVoiceVolume(float value)
994{
Eric Laurenta1884f92011-08-23 08:25:03 -0700995 status_t ret = initCheck();
996 if (ret != NO_ERROR) {
997 return ret;
998 }
999
Mathias Agopian65ab4712010-07-14 17:59:35 -07001000 // check calling permissions
1001 if (!settingsAllowed()) {
1002 return PERMISSION_DENIED;
1003 }
1004
1005 AutoMutex lock(mHardwareLock);
Glenn Kasten8abf44d2012-02-02 14:16:03 -08001006 mHardwareStatus = AUDIO_HW_SET_VOICE_VOLUME;
Eric Laurenta1884f92011-08-23 08:25:03 -07001007 ret = mPrimaryHardwareDev->set_voice_volume(mPrimaryHardwareDev, value);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001008 mHardwareStatus = AUDIO_HW_IDLE;
1009
1010 return ret;
1011}
1012
Glenn Kasten72ef00d2012-01-17 11:09:42 -08001013status_t AudioFlinger::getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames,
1014 audio_io_handle_t output) const
Mathias Agopian65ab4712010-07-14 17:59:35 -07001015{
1016 status_t status;
1017
1018 Mutex::Autolock _l(mLock);
1019
1020 PlaybackThread *playbackThread = checkPlaybackThread_l(output);
1021 if (playbackThread != NULL) {
1022 return playbackThread->getRenderPosition(halFrames, dspFrames);
1023 }
1024
1025 return BAD_VALUE;
1026}
1027
1028void AudioFlinger::registerClient(const sp<IAudioFlingerClient>& client)
1029{
1030
1031 Mutex::Autolock _l(mLock);
1032
Glenn Kastenbb001922012-02-03 11:10:26 -08001033 pid_t pid = IPCThreadState::self()->getCallingPid();
Mathias Agopian65ab4712010-07-14 17:59:35 -07001034 if (mNotificationClients.indexOfKey(pid) < 0) {
1035 sp<NotificationClient> notificationClient = new NotificationClient(this,
1036 client,
1037 pid);
Steve Block3856b092011-10-20 11:56:00 +01001038 ALOGV("registerClient() client %p, pid %d", notificationClient.get(), pid);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001039
1040 mNotificationClients.add(pid, notificationClient);
1041
1042 sp<IBinder> binder = client->asBinder();
1043 binder->linkToDeath(notificationClient);
1044
1045 // the config change is always sent from playback or record threads to avoid deadlock
1046 // with AudioSystem::gLock
1047 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
1048 mPlaybackThreads.valueAt(i)->sendConfigEvent(AudioSystem::OUTPUT_OPENED);
1049 }
1050
1051 for (size_t i = 0; i < mRecordThreads.size(); i++) {
1052 mRecordThreads.valueAt(i)->sendConfigEvent(AudioSystem::INPUT_OPENED);
1053 }
1054 }
1055}
1056
1057void AudioFlinger::removeNotificationClient(pid_t pid)
1058{
1059 Mutex::Autolock _l(mLock);
1060
Glenn Kastena3b09252012-01-20 09:19:01 -08001061 mNotificationClients.removeItem(pid);
Marco Nelissen3a34bef2011-08-02 13:33:41 -07001062
Steve Block3856b092011-10-20 11:56:00 +01001063 ALOGV("%d died, releasing its sessions", pid);
Glenn Kasten8d6a2442012-02-08 14:04:28 -08001064 size_t num = mAudioSessionRefs.size();
Marco Nelissen3a34bef2011-08-02 13:33:41 -07001065 bool removed = false;
Glenn Kasten8d6a2442012-02-08 14:04:28 -08001066 for (size_t i = 0; i< num; ) {
Marco Nelissen3a34bef2011-08-02 13:33:41 -07001067 AudioSessionRef *ref = mAudioSessionRefs.itemAt(i);
Glenn Kasten012ca6b2012-03-06 11:22:01 -08001068 ALOGV(" pid %d @ %d", ref->mPid, i);
1069 if (ref->mPid == pid) {
1070 ALOGV(" removing entry for pid %d session %d", pid, ref->mSessionid);
Marco Nelissen3a34bef2011-08-02 13:33:41 -07001071 mAudioSessionRefs.removeAt(i);
1072 delete ref;
1073 removed = true;
Marco Nelissen3a34bef2011-08-02 13:33:41 -07001074 num--;
Glenn Kasten8d6a2442012-02-08 14:04:28 -08001075 } else {
1076 i++;
Marco Nelissen3a34bef2011-08-02 13:33:41 -07001077 }
1078 }
1079 if (removed) {
1080 purgeStaleEffects_l();
1081 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07001082}
1083
1084// audioConfigChanged_l() must be called with AudioFlinger::mLock held
Glenn Kastenb81cc8c2012-03-01 09:14:51 -08001085void AudioFlinger::audioConfigChanged_l(int event, audio_io_handle_t ioHandle, const void *param2)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001086{
1087 size_t size = mNotificationClients.size();
1088 for (size_t i = 0; i < size; i++) {
Glenn Kasten84afa3b2012-01-25 15:28:08 -08001089 mNotificationClients.valueAt(i)->audioFlingerClient()->ioConfigChanged(event, ioHandle,
1090 param2);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001091 }
1092}
1093
1094// removeClient_l() must be called with AudioFlinger::mLock held
1095void AudioFlinger::removeClient_l(pid_t pid)
1096{
Steve Block3856b092011-10-20 11:56:00 +01001097 ALOGV("removeClient_l() pid %d, tid %d, calling tid %d", pid, gettid(), IPCThreadState::self()->getCallingPid());
Mathias Agopian65ab4712010-07-14 17:59:35 -07001098 mClients.removeItem(pid);
1099}
1100
1101
1102// ----------------------------------------------------------------------------
1103
Glenn Kasten72ef00d2012-01-17 11:09:42 -08001104AudioFlinger::ThreadBase::ThreadBase(const sp<AudioFlinger>& audioFlinger, audio_io_handle_t id,
1105 uint32_t device, type_t type)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001106 : Thread(false),
Glenn Kasten23bb8be2012-01-26 10:38:26 -08001107 mType(type),
Glenn Kasten58912562012-04-03 10:45:00 -07001108 mAudioFlinger(audioFlinger), mSampleRate(0), mFrameCount(0), mNormalFrameCount(0),
Glenn Kasten84afa3b2012-01-25 15:28:08 -08001109 // mChannelMask
1110 mChannelCount(0),
1111 mFrameSize(1), mFormat(AUDIO_FORMAT_INVALID),
1112 mParamStatus(NO_ERROR),
Glenn Kastenb28686f2012-01-06 08:39:38 -08001113 mStandby(false), mId(id),
Glenn Kasten84afa3b2012-01-25 15:28:08 -08001114 mDevice(device),
1115 mDeathRecipient(new PMDeathRecipient(this))
Mathias Agopian65ab4712010-07-14 17:59:35 -07001116{
1117}
1118
1119AudioFlinger::ThreadBase::~ThreadBase()
1120{
1121 mParamCond.broadcast();
Eric Laurentfeb0db62011-07-22 09:04:31 -07001122 // do not lock the mutex in destructor
1123 releaseWakeLock_l();
Eric Laurent9d18ec52011-09-27 12:07:15 -07001124 if (mPowerManager != 0) {
1125 sp<IBinder> binder = mPowerManager->asBinder();
1126 binder->unlinkToDeath(mDeathRecipient);
1127 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07001128}
1129
1130void AudioFlinger::ThreadBase::exit()
1131{
Steve Block3856b092011-10-20 11:56:00 +01001132 ALOGV("ThreadBase::exit");
Mathias Agopian65ab4712010-07-14 17:59:35 -07001133 {
Glenn Kastenb28686f2012-01-06 08:39:38 -08001134 // This lock prevents the following race in thread (uniprocessor for illustration):
1135 // if (!exitPending()) {
1136 // // context switch from here to exit()
1137 // // exit() calls requestExit(), what exitPending() observes
1138 // // exit() calls signal(), which is dropped since no waiters
1139 // // context switch back from exit() to here
1140 // mWaitWorkCV.wait(...);
1141 // // now thread is hung
1142 // }
Glenn Kastena7d8d6f2012-01-05 15:41:56 -08001143 AutoMutex lock(mLock);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001144 requestExit();
1145 mWaitWorkCV.signal();
1146 }
Glenn Kastenb28686f2012-01-06 08:39:38 -08001147 // When Thread::requestExitAndWait is made virtual and this method is renamed to
1148 // "virtual status_t requestExitAndWait()", replace by "return Thread::requestExitAndWait();"
Mathias Agopian65ab4712010-07-14 17:59:35 -07001149 requestExitAndWait();
1150}
1151
Mathias Agopian65ab4712010-07-14 17:59:35 -07001152status_t AudioFlinger::ThreadBase::setParameters(const String8& keyValuePairs)
1153{
1154 status_t status;
1155
Steve Block3856b092011-10-20 11:56:00 +01001156 ALOGV("ThreadBase::setParameters() %s", keyValuePairs.string());
Mathias Agopian65ab4712010-07-14 17:59:35 -07001157 Mutex::Autolock _l(mLock);
1158
1159 mNewParameters.add(keyValuePairs);
1160 mWaitWorkCV.signal();
1161 // wait condition with timeout in case the thread loop has exited
1162 // before the request could be processed
Glenn Kasten7dede872011-12-13 11:04:14 -08001163 if (mParamCond.waitRelative(mLock, kSetParametersTimeoutNs) == NO_ERROR) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001164 status = mParamStatus;
1165 mWaitWorkCV.signal();
1166 } else {
1167 status = TIMED_OUT;
1168 }
1169 return status;
1170}
1171
1172void AudioFlinger::ThreadBase::sendConfigEvent(int event, int param)
1173{
1174 Mutex::Autolock _l(mLock);
1175 sendConfigEvent_l(event, param);
1176}
1177
1178// sendConfigEvent_l() must be called with ThreadBase::mLock held
1179void AudioFlinger::ThreadBase::sendConfigEvent_l(int event, int param)
1180{
Glenn Kastenf3990f22011-12-13 11:50:00 -08001181 ConfigEvent configEvent;
1182 configEvent.mEvent = event;
1183 configEvent.mParam = param;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001184 mConfigEvents.add(configEvent);
Steve Block3856b092011-10-20 11:56:00 +01001185 ALOGV("sendConfigEvent() num events %d event %d, param %d", mConfigEvents.size(), event, param);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001186 mWaitWorkCV.signal();
1187}
1188
1189void AudioFlinger::ThreadBase::processConfigEvents()
1190{
1191 mLock.lock();
Glenn Kastene53b9ea2012-03-12 16:29:55 -07001192 while (!mConfigEvents.isEmpty()) {
Steve Block3856b092011-10-20 11:56:00 +01001193 ALOGV("processConfigEvents() remaining events %d", mConfigEvents.size());
Glenn Kastenf3990f22011-12-13 11:50:00 -08001194 ConfigEvent configEvent = mConfigEvents[0];
Mathias Agopian65ab4712010-07-14 17:59:35 -07001195 mConfigEvents.removeAt(0);
1196 // release mLock before locking AudioFlinger mLock: lock order is always
1197 // AudioFlinger then ThreadBase to avoid cross deadlock
1198 mLock.unlock();
1199 mAudioFlinger->mLock.lock();
Glenn Kastenf3990f22011-12-13 11:50:00 -08001200 audioConfigChanged_l(configEvent.mEvent, configEvent.mParam);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001201 mAudioFlinger->mLock.unlock();
Mathias Agopian65ab4712010-07-14 17:59:35 -07001202 mLock.lock();
1203 }
1204 mLock.unlock();
1205}
1206
1207status_t AudioFlinger::ThreadBase::dumpBase(int fd, const Vector<String16>& args)
1208{
1209 const size_t SIZE = 256;
1210 char buffer[SIZE];
1211 String8 result;
1212
1213 bool locked = tryLock(mLock);
1214 if (!locked) {
1215 snprintf(buffer, SIZE, "thread %p maybe dead locked\n", this);
1216 write(fd, buffer, strlen(buffer));
1217 }
1218
Eric Laurent612bbb52012-03-14 15:03:26 -07001219 snprintf(buffer, SIZE, "io handle: %d\n", mId);
1220 result.append(buffer);
1221 snprintf(buffer, SIZE, "TID: %d\n", getTid());
1222 result.append(buffer);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001223 snprintf(buffer, SIZE, "standby: %d\n", mStandby);
1224 result.append(buffer);
1225 snprintf(buffer, SIZE, "Sample rate: %d\n", mSampleRate);
1226 result.append(buffer);
Glenn Kasten58912562012-04-03 10:45:00 -07001227 snprintf(buffer, SIZE, "HAL frame count: %d\n", mFrameCount);
1228 result.append(buffer);
1229 snprintf(buffer, SIZE, "Normal frame count: %d\n", mNormalFrameCount);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001230 result.append(buffer);
1231 snprintf(buffer, SIZE, "Channel Count: %d\n", mChannelCount);
1232 result.append(buffer);
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07001233 snprintf(buffer, SIZE, "Channel Mask: 0x%08x\n", mChannelMask);
1234 result.append(buffer);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001235 snprintf(buffer, SIZE, "Format: %d\n", mFormat);
1236 result.append(buffer);
Glenn Kastenb9980652012-01-11 09:48:27 -08001237 snprintf(buffer, SIZE, "Frame size: %u\n", mFrameSize);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001238 result.append(buffer);
1239
1240 snprintf(buffer, SIZE, "\nPending setParameters commands: \n");
1241 result.append(buffer);
1242 result.append(" Index Command");
1243 for (size_t i = 0; i < mNewParameters.size(); ++i) {
1244 snprintf(buffer, SIZE, "\n %02d ", i);
1245 result.append(buffer);
1246 result.append(mNewParameters[i]);
1247 }
1248
1249 snprintf(buffer, SIZE, "\n\nPending config events: \n");
1250 result.append(buffer);
1251 snprintf(buffer, SIZE, " Index event param\n");
1252 result.append(buffer);
1253 for (size_t i = 0; i < mConfigEvents.size(); i++) {
Glenn Kastenf3990f22011-12-13 11:50:00 -08001254 snprintf(buffer, SIZE, " %02d %02d %d\n", i, mConfigEvents[i].mEvent, mConfigEvents[i].mParam);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001255 result.append(buffer);
1256 }
1257 result.append("\n");
1258
1259 write(fd, result.string(), result.size());
1260
1261 if (locked) {
1262 mLock.unlock();
1263 }
1264 return NO_ERROR;
1265}
1266
Eric Laurent1d2bff02011-07-24 17:49:51 -07001267status_t AudioFlinger::ThreadBase::dumpEffectChains(int fd, const Vector<String16>& args)
1268{
1269 const size_t SIZE = 256;
1270 char buffer[SIZE];
1271 String8 result;
1272
1273 snprintf(buffer, SIZE, "\n- %d Effect Chains:\n", mEffectChains.size());
1274 write(fd, buffer, strlen(buffer));
1275
1276 for (size_t i = 0; i < mEffectChains.size(); ++i) {
1277 sp<EffectChain> chain = mEffectChains[i];
1278 if (chain != 0) {
1279 chain->dump(fd, args);
1280 }
1281 }
1282 return NO_ERROR;
1283}
1284
Eric Laurentfeb0db62011-07-22 09:04:31 -07001285void AudioFlinger::ThreadBase::acquireWakeLock()
1286{
1287 Mutex::Autolock _l(mLock);
1288 acquireWakeLock_l();
1289}
1290
1291void AudioFlinger::ThreadBase::acquireWakeLock_l()
1292{
1293 if (mPowerManager == 0) {
1294 // use checkService() to avoid blocking if power service is not up yet
1295 sp<IBinder> binder =
1296 defaultServiceManager()->checkService(String16("power"));
1297 if (binder == 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00001298 ALOGW("Thread %s cannot connect to the power manager service", mName);
Eric Laurentfeb0db62011-07-22 09:04:31 -07001299 } else {
1300 mPowerManager = interface_cast<IPowerManager>(binder);
1301 binder->linkToDeath(mDeathRecipient);
1302 }
1303 }
1304 if (mPowerManager != 0) {
1305 sp<IBinder> binder = new BBinder();
1306 status_t status = mPowerManager->acquireWakeLock(POWERMANAGER_PARTIAL_WAKE_LOCK,
1307 binder,
1308 String16(mName));
1309 if (status == NO_ERROR) {
1310 mWakeLockToken = binder;
1311 }
Steve Block3856b092011-10-20 11:56:00 +01001312 ALOGV("acquireWakeLock_l() %s status %d", mName, status);
Eric Laurentfeb0db62011-07-22 09:04:31 -07001313 }
1314}
1315
1316void AudioFlinger::ThreadBase::releaseWakeLock()
1317{
1318 Mutex::Autolock _l(mLock);
Eric Laurent6dbe8832011-07-28 13:59:02 -07001319 releaseWakeLock_l();
Eric Laurentfeb0db62011-07-22 09:04:31 -07001320}
1321
1322void AudioFlinger::ThreadBase::releaseWakeLock_l()
1323{
1324 if (mWakeLockToken != 0) {
Steve Block3856b092011-10-20 11:56:00 +01001325 ALOGV("releaseWakeLock_l() %s", mName);
Eric Laurentfeb0db62011-07-22 09:04:31 -07001326 if (mPowerManager != 0) {
1327 mPowerManager->releaseWakeLock(mWakeLockToken, 0);
1328 }
1329 mWakeLockToken.clear();
1330 }
1331}
1332
1333void AudioFlinger::ThreadBase::clearPowerManager()
1334{
1335 Mutex::Autolock _l(mLock);
1336 releaseWakeLock_l();
1337 mPowerManager.clear();
1338}
1339
1340void AudioFlinger::ThreadBase::PMDeathRecipient::binderDied(const wp<IBinder>& who)
1341{
1342 sp<ThreadBase> thread = mThread.promote();
1343 if (thread != 0) {
1344 thread->clearPowerManager();
1345 }
Steve Block5ff1dd52012-01-05 23:22:43 +00001346 ALOGW("power manager service died !!!");
Eric Laurentfeb0db62011-07-22 09:04:31 -07001347}
Eric Laurent1d2bff02011-07-24 17:49:51 -07001348
Eric Laurent59255e42011-07-27 19:49:51 -07001349void AudioFlinger::ThreadBase::setEffectSuspended(
1350 const effect_uuid_t *type, bool suspend, int sessionId)
1351{
1352 Mutex::Autolock _l(mLock);
1353 setEffectSuspended_l(type, suspend, sessionId);
1354}
1355
1356void AudioFlinger::ThreadBase::setEffectSuspended_l(
1357 const effect_uuid_t *type, bool suspend, int sessionId)
1358{
Glenn Kasten090f0192012-01-30 13:00:02 -08001359 sp<EffectChain> chain = getEffectChain_l(sessionId);
Eric Laurent59255e42011-07-27 19:49:51 -07001360 if (chain != 0) {
1361 if (type != NULL) {
1362 chain->setEffectSuspended_l(type, suspend);
1363 } else {
1364 chain->setEffectSuspendedAll_l(suspend);
1365 }
1366 }
1367
1368 updateSuspendedSessions_l(type, suspend, sessionId);
1369}
1370
1371void AudioFlinger::ThreadBase::checkSuspendOnAddEffectChain_l(const sp<EffectChain>& chain)
1372{
Glenn Kasten8d6a2442012-02-08 14:04:28 -08001373 ssize_t index = mSuspendedSessions.indexOfKey(chain->sessionId());
Eric Laurent59255e42011-07-27 19:49:51 -07001374 if (index < 0) {
1375 return;
1376 }
1377
1378 KeyedVector <int, sp<SuspendedSessionDesc> > sessionEffects =
1379 mSuspendedSessions.editValueAt(index);
1380
1381 for (size_t i = 0; i < sessionEffects.size(); i++) {
Glenn Kastene53b9ea2012-03-12 16:29:55 -07001382 sp<SuspendedSessionDesc> desc = sessionEffects.valueAt(i);
Eric Laurent59255e42011-07-27 19:49:51 -07001383 for (int j = 0; j < desc->mRefCount; j++) {
1384 if (sessionEffects.keyAt(i) == EffectChain::kKeyForSuspendAll) {
1385 chain->setEffectSuspendedAll_l(true);
1386 } else {
Steve Block3856b092011-10-20 11:56:00 +01001387 ALOGV("checkSuspendOnAddEffectChain_l() suspending effects %08x",
Glenn Kastene53b9ea2012-03-12 16:29:55 -07001388 desc->mType.timeLow);
Eric Laurent59255e42011-07-27 19:49:51 -07001389 chain->setEffectSuspended_l(&desc->mType, true);
1390 }
1391 }
1392 }
1393}
1394
Eric Laurent59255e42011-07-27 19:49:51 -07001395void AudioFlinger::ThreadBase::updateSuspendedSessions_l(const effect_uuid_t *type,
1396 bool suspend,
1397 int sessionId)
1398{
Glenn Kasten8d6a2442012-02-08 14:04:28 -08001399 ssize_t index = mSuspendedSessions.indexOfKey(sessionId);
Eric Laurent59255e42011-07-27 19:49:51 -07001400
1401 KeyedVector <int, sp<SuspendedSessionDesc> > sessionEffects;
1402
1403 if (suspend) {
1404 if (index >= 0) {
1405 sessionEffects = mSuspendedSessions.editValueAt(index);
1406 } else {
1407 mSuspendedSessions.add(sessionId, sessionEffects);
1408 }
1409 } else {
1410 if (index < 0) {
1411 return;
1412 }
1413 sessionEffects = mSuspendedSessions.editValueAt(index);
1414 }
1415
1416
1417 int key = EffectChain::kKeyForSuspendAll;
1418 if (type != NULL) {
1419 key = type->timeLow;
1420 }
1421 index = sessionEffects.indexOfKey(key);
1422
Glenn Kastene53b9ea2012-03-12 16:29:55 -07001423 sp<SuspendedSessionDesc> desc;
Eric Laurent59255e42011-07-27 19:49:51 -07001424 if (suspend) {
1425 if (index >= 0) {
1426 desc = sessionEffects.valueAt(index);
1427 } else {
1428 desc = new SuspendedSessionDesc();
1429 if (type != NULL) {
1430 memcpy(&desc->mType, type, sizeof(effect_uuid_t));
1431 }
1432 sessionEffects.add(key, desc);
Steve Block3856b092011-10-20 11:56:00 +01001433 ALOGV("updateSuspendedSessions_l() suspend adding effect %08x", key);
Eric Laurent59255e42011-07-27 19:49:51 -07001434 }
1435 desc->mRefCount++;
1436 } else {
1437 if (index < 0) {
1438 return;
1439 }
1440 desc = sessionEffects.valueAt(index);
1441 if (--desc->mRefCount == 0) {
Steve Block3856b092011-10-20 11:56:00 +01001442 ALOGV("updateSuspendedSessions_l() restore removing effect %08x", key);
Eric Laurent59255e42011-07-27 19:49:51 -07001443 sessionEffects.removeItemsAt(index);
1444 if (sessionEffects.isEmpty()) {
Steve Block3856b092011-10-20 11:56:00 +01001445 ALOGV("updateSuspendedSessions_l() restore removing session %d",
Eric Laurent59255e42011-07-27 19:49:51 -07001446 sessionId);
1447 mSuspendedSessions.removeItem(sessionId);
1448 }
1449 }
1450 }
1451 if (!sessionEffects.isEmpty()) {
1452 mSuspendedSessions.replaceValueFor(sessionId, sessionEffects);
1453 }
1454}
1455
1456void AudioFlinger::ThreadBase::checkSuspendOnEffectEnabled(const sp<EffectModule>& effect,
1457 bool enabled,
1458 int sessionId)
1459{
1460 Mutex::Autolock _l(mLock);
Eric Laurenta85a74a2011-10-19 11:44:54 -07001461 checkSuspendOnEffectEnabled_l(effect, enabled, sessionId);
1462}
Eric Laurent59255e42011-07-27 19:49:51 -07001463
Eric Laurenta85a74a2011-10-19 11:44:54 -07001464void AudioFlinger::ThreadBase::checkSuspendOnEffectEnabled_l(const sp<EffectModule>& effect,
1465 bool enabled,
1466 int sessionId)
1467{
Eric Laurentdb7c0792011-08-10 10:37:50 -07001468 if (mType != RECORD) {
1469 // suspend all effects in AUDIO_SESSION_OUTPUT_MIX when enabling any effect on
1470 // another session. This gives the priority to well behaved effect control panels
1471 // and applications not using global effects.
Eric Laurent808e7d12012-05-11 19:44:09 -07001472 // Enabling post processing in AUDIO_SESSION_OUTPUT_STAGE session does not affect
1473 // global effects
1474 if ((sessionId != AUDIO_SESSION_OUTPUT_MIX) && (sessionId != AUDIO_SESSION_OUTPUT_STAGE)) {
Eric Laurentdb7c0792011-08-10 10:37:50 -07001475 setEffectSuspended_l(NULL, enabled, AUDIO_SESSION_OUTPUT_MIX);
1476 }
1477 }
Eric Laurent59255e42011-07-27 19:49:51 -07001478
1479 sp<EffectChain> chain = getEffectChain_l(sessionId);
1480 if (chain != 0) {
1481 chain->checkSuspendOnEffectEnabled(effect, enabled);
1482 }
1483}
1484
Mathias Agopian65ab4712010-07-14 17:59:35 -07001485// ----------------------------------------------------------------------------
1486
Eric Laurent7c7f10b2011-06-17 21:29:58 -07001487AudioFlinger::PlaybackThread::PlaybackThread(const sp<AudioFlinger>& audioFlinger,
1488 AudioStreamOut* output,
Glenn Kasten72ef00d2012-01-17 11:09:42 -08001489 audio_io_handle_t id,
Glenn Kasten23bb8be2012-01-26 10:38:26 -08001490 uint32_t device,
1491 type_t type)
1492 : ThreadBase(audioFlinger, id, device, type),
Glenn Kasten84afa3b2012-01-25 15:28:08 -08001493 mMixBuffer(NULL), mSuspended(0), mBytesWritten(0),
1494 // Assumes constructor is called by AudioFlinger with it's mLock held,
1495 // but it would be safer to explicitly pass initial masterMute as parameter
1496 mMasterMute(audioFlinger->masterMute_l()),
1497 // mStreamTypes[] initialized in constructor body
1498 mOutput(output),
1499 // Assumes constructor is called by AudioFlinger with it's mLock held,
1500 // but it would be safer to explicitly pass initial masterVolume as parameter
John Grossman4ff14ba2012-02-08 16:37:41 -08001501 mMasterVolume(audioFlinger->masterVolumeSW_l()),
Glenn Kastenfec279f2012-03-08 07:47:15 -08001502 mLastWriteTime(0), mNumWrites(0), mNumDelayedWrites(0), mInWrite(false),
Glenn Kastenaa4397f2012-03-12 18:13:59 -07001503 mMixerStatus(MIXER_IDLE),
Glenn Kasten81028042012-04-30 18:15:12 -07001504 mMixerStatusIgnoringFastTracks(MIXER_IDLE),
Glenn Kasten58912562012-04-03 10:45:00 -07001505 standbyDelay(AudioFlinger::mStandbyTimeInNsecs),
Glenn Kasten288ed212012-04-25 17:52:27 -07001506 // index 0 is reserved for normal mixer's submix
1507 mFastTrackAvailMask(((1 << FastMixerState::kMaxFastTracks) - 1) & ~1)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001508{
Glenn Kasten480b4682012-02-28 12:30:08 -08001509 snprintf(mName, kNameLength, "AudioOut_%X", id);
Eric Laurentfeb0db62011-07-22 09:04:31 -07001510
Mathias Agopian65ab4712010-07-14 17:59:35 -07001511 readOutputParameters();
1512
Glenn Kasten263709e2012-01-06 08:40:01 -08001513 // mStreamTypes[AUDIO_STREAM_CNT] is initialized by stream_type_t default constructor
Glenn Kastenfff6d712012-01-12 16:38:12 -08001514 // There is no AUDIO_STREAM_MIN, and ++ operator does not compile
1515 for (audio_stream_type_t stream = (audio_stream_type_t) 0; stream < AUDIO_STREAM_CNT;
1516 stream = (audio_stream_type_t) (stream + 1)) {
Glenn Kasten6637baa2012-01-09 09:40:36 -08001517 mStreamTypes[stream].volume = mAudioFlinger->streamVolume_l(stream);
1518 mStreamTypes[stream].mute = mAudioFlinger->streamMute_l(stream);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001519 }
Glenn Kasten6637baa2012-01-09 09:40:36 -08001520 // mStreamTypes[AUDIO_STREAM_CNT] exists but isn't explicitly initialized here,
1521 // because mAudioFlinger doesn't have one to copy from
Mathias Agopian65ab4712010-07-14 17:59:35 -07001522}
1523
1524AudioFlinger::PlaybackThread::~PlaybackThread()
1525{
1526 delete [] mMixBuffer;
1527}
1528
1529status_t AudioFlinger::PlaybackThread::dump(int fd, const Vector<String16>& args)
1530{
1531 dumpInternals(fd, args);
1532 dumpTracks(fd, args);
1533 dumpEffectChains(fd, args);
1534 return NO_ERROR;
1535}
1536
1537status_t AudioFlinger::PlaybackThread::dumpTracks(int fd, const Vector<String16>& args)
1538{
1539 const size_t SIZE = 256;
1540 char buffer[SIZE];
1541 String8 result;
1542
Glenn Kasten58912562012-04-03 10:45:00 -07001543 result.appendFormat("Output thread %p stream volumes in dB:\n ", this);
1544 for (int i = 0; i < AUDIO_STREAM_CNT; ++i) {
1545 const stream_type_t *st = &mStreamTypes[i];
1546 if (i > 0) {
1547 result.appendFormat(", ");
1548 }
1549 result.appendFormat("%d:%.2g", i, 20.0 * log10(st->volume));
1550 if (st->mute) {
1551 result.append("M");
1552 }
1553 }
1554 result.append("\n");
1555 write(fd, result.string(), result.length());
1556 result.clear();
1557
Mathias Agopian65ab4712010-07-14 17:59:35 -07001558 snprintf(buffer, SIZE, "Output thread %p tracks\n", this);
1559 result.append(buffer);
Glenn Kasten288ed212012-04-25 17:52:27 -07001560 Track::appendDumpHeader(result);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001561 for (size_t i = 0; i < mTracks.size(); ++i) {
1562 sp<Track> track = mTracks[i];
1563 if (track != 0) {
1564 track->dump(buffer, SIZE);
1565 result.append(buffer);
1566 }
1567 }
1568
1569 snprintf(buffer, SIZE, "Output thread %p active tracks\n", this);
1570 result.append(buffer);
Glenn Kasten288ed212012-04-25 17:52:27 -07001571 Track::appendDumpHeader(result);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001572 for (size_t i = 0; i < mActiveTracks.size(); ++i) {
Glenn Kasten77c11192012-01-25 14:27:41 -08001573 sp<Track> track = mActiveTracks[i].promote();
1574 if (track != 0) {
1575 track->dump(buffer, SIZE);
1576 result.append(buffer);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001577 }
1578 }
1579 write(fd, result.string(), result.size());
Glenn Kasten88cbea82012-05-15 07:39:27 -07001580
1581 // These values are "raw"; they will wrap around. See prepareTracks_l() for a better way.
1582 FastTrackUnderruns underruns = getFastTrackUnderruns(0);
1583 fdprintf(fd, "Normal mixer raw underrun counters: partial=%u empty=%u\n",
1584 underruns.mBitFields.mPartial, underruns.mBitFields.mEmpty);
1585
Mathias Agopian65ab4712010-07-14 17:59:35 -07001586 return NO_ERROR;
1587}
1588
Mathias Agopian65ab4712010-07-14 17:59:35 -07001589status_t AudioFlinger::PlaybackThread::dumpInternals(int fd, const Vector<String16>& args)
1590{
1591 const size_t SIZE = 256;
1592 char buffer[SIZE];
1593 String8 result;
1594
1595 snprintf(buffer, SIZE, "\nOutput thread %p internals\n", this);
1596 result.append(buffer);
1597 snprintf(buffer, SIZE, "last write occurred (msecs): %llu\n", ns2ms(systemTime() - mLastWriteTime));
1598 result.append(buffer);
1599 snprintf(buffer, SIZE, "total writes: %d\n", mNumWrites);
1600 result.append(buffer);
1601 snprintf(buffer, SIZE, "delayed writes: %d\n", mNumDelayedWrites);
1602 result.append(buffer);
1603 snprintf(buffer, SIZE, "blocked in write: %d\n", mInWrite);
1604 result.append(buffer);
1605 snprintf(buffer, SIZE, "suspend count: %d\n", mSuspended);
1606 result.append(buffer);
1607 snprintf(buffer, SIZE, "mix buffer : %p\n", mMixBuffer);
1608 result.append(buffer);
1609 write(fd, result.string(), result.size());
1610
1611 dumpBase(fd, args);
1612
1613 return NO_ERROR;
1614}
1615
1616// Thread virtuals
1617status_t AudioFlinger::PlaybackThread::readyToRun()
1618{
Eric Laurentb8ba0a92011-08-07 16:32:26 -07001619 status_t status = initCheck();
1620 if (status == NO_ERROR) {
Steve Blockdf64d152012-01-04 20:05:49 +00001621 ALOGI("AudioFlinger's thread %p ready to run", this);
Eric Laurentb8ba0a92011-08-07 16:32:26 -07001622 } else {
Steve Block29357bc2012-01-06 19:20:56 +00001623 ALOGE("No working audio driver found.");
Mathias Agopian65ab4712010-07-14 17:59:35 -07001624 }
Eric Laurentb8ba0a92011-08-07 16:32:26 -07001625 return status;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001626}
1627
1628void AudioFlinger::PlaybackThread::onFirstRef()
1629{
Eric Laurentfeb0db62011-07-22 09:04:31 -07001630 run(mName, ANDROID_PRIORITY_URGENT_AUDIO);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001631}
1632
1633// PlaybackThread::createTrack_l() must be called with AudioFlinger::mLock held
Glenn Kastenea7939a2012-03-14 12:56:26 -07001634sp<AudioFlinger::PlaybackThread::Track> AudioFlinger::PlaybackThread::createTrack_l(
Mathias Agopian65ab4712010-07-14 17:59:35 -07001635 const sp<AudioFlinger::Client>& client,
Glenn Kastenfff6d712012-01-12 16:38:12 -08001636 audio_stream_type_t streamType,
Mathias Agopian65ab4712010-07-14 17:59:35 -07001637 uint32_t sampleRate,
Glenn Kasten58f30212012-01-12 12:27:51 -08001638 audio_format_t format,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07001639 uint32_t channelMask,
Mathias Agopian65ab4712010-07-14 17:59:35 -07001640 int frameCount,
1641 const sp<IMemory>& sharedBuffer,
1642 int sessionId,
Glenn Kasten73d22752012-03-19 13:38:30 -07001643 IAudioFlinger::track_flags_t flags,
Glenn Kasten3acbd052012-02-28 10:39:56 -08001644 pid_t tid,
Mathias Agopian65ab4712010-07-14 17:59:35 -07001645 status_t *status)
1646{
1647 sp<Track> track;
1648 status_t lStatus;
1649
Glenn Kasten73d22752012-03-19 13:38:30 -07001650 bool isTimed = (flags & IAudioFlinger::TRACK_TIMED) != 0;
1651
1652 // client expresses a preference for FAST, but we get the final say
Glenn Kastene0fa4672012-04-24 14:35:14 -07001653 if (flags & IAudioFlinger::TRACK_FAST) {
1654 if (
Glenn Kasten73d22752012-03-19 13:38:30 -07001655 // not timed
1656 (!isTimed) &&
1657 // either of these use cases:
1658 (
1659 // use case 1: shared buffer with any frame count
1660 (
1661 (sharedBuffer != 0)
1662 ) ||
Glenn Kastene0fa4672012-04-24 14:35:14 -07001663 // use case 2: callback handler and frame count is default or at least as large as HAL
Glenn Kasten73d22752012-03-19 13:38:30 -07001664 (
Glenn Kasten3acbd052012-02-28 10:39:56 -08001665 (tid != -1) &&
Glenn Kastene0fa4672012-04-24 14:35:14 -07001666 ((frameCount == 0) ||
Glenn Kasten300a2ee2012-04-25 13:47:36 -07001667 (frameCount >= (int) (mFrameCount * 2))) // * 2 is due to SRC jitter, see below
Glenn Kasten73d22752012-03-19 13:38:30 -07001668 )
1669 ) &&
1670 // PCM data
1671 audio_is_linear_pcm(format) &&
1672 // mono or stereo
1673 ( (channelMask == AUDIO_CHANNEL_OUT_MONO) ||
1674 (channelMask == AUDIO_CHANNEL_OUT_STEREO) ) &&
Glenn Kasten58912562012-04-03 10:45:00 -07001675#ifndef FAST_TRACKS_AT_NON_NATIVE_SAMPLE_RATE
Glenn Kasten73d22752012-03-19 13:38:30 -07001676 // hardware sample rate
Glenn Kasten58912562012-04-03 10:45:00 -07001677 (sampleRate == mSampleRate) &&
1678#endif
1679 // normal mixer has an associated fast mixer
1680 hasFastMixer() &&
1681 // there are sufficient fast track slots available
1682 (mFastTrackAvailMask != 0)
Glenn Kasten73d22752012-03-19 13:38:30 -07001683 // FIXME test that MixerThread for this fast track has a capable output HAL
1684 // FIXME add a permission test also?
Glenn Kastene0fa4672012-04-24 14:35:14 -07001685 ) {
Glenn Kastene0fa4672012-04-24 14:35:14 -07001686 // if frameCount not specified, then it defaults to fast mixer (HAL) frame count
1687 if (frameCount == 0) {
Glenn Kasten300a2ee2012-04-25 13:47:36 -07001688 frameCount = mFrameCount * 2; // FIXME * 2 is due to SRC jitter, should be computed
Glenn Kastene0fa4672012-04-24 14:35:14 -07001689 }
Glenn Kasten31dfd1d2012-05-01 11:07:08 -07001690 ALOGV("AUDIO_OUTPUT_FLAG_FAST accepted: frameCount=%d mFrameCount=%d",
Glenn Kasten300a2ee2012-04-25 13:47:36 -07001691 frameCount, mFrameCount);
Glenn Kastene0fa4672012-04-24 14:35:14 -07001692 } else {
1693 ALOGW("AUDIO_OUTPUT_FLAG_FAST denied: isTimed=%d sharedBuffer=%p frameCount=%d "
Glenn Kasten58912562012-04-03 10:45:00 -07001694 "mFrameCount=%d format=%d isLinear=%d channelMask=%d sampleRate=%d mSampleRate=%d "
1695 "hasFastMixer=%d tid=%d fastTrackAvailMask=%#x",
1696 isTimed, sharedBuffer.get(), frameCount, mFrameCount, format,
1697 audio_is_linear_pcm(format),
1698 channelMask, sampleRate, mSampleRate, hasFastMixer(), tid, mFastTrackAvailMask);
Glenn Kasten73d22752012-03-19 13:38:30 -07001699 flags &= ~IAudioFlinger::TRACK_FAST;
Glenn Kastene0fa4672012-04-24 14:35:14 -07001700 // For compatibility with AudioTrack calculation, buffer depth is forced
1701 // to be at least 2 x the normal mixer frame count and cover audio hardware latency.
1702 // This is probably too conservative, but legacy application code may depend on it.
1703 // If you change this calculation, also review the start threshold which is related.
1704 uint32_t latencyMs = mOutput->stream->get_latency(mOutput->stream);
1705 uint32_t minBufCount = latencyMs / ((1000 * mNormalFrameCount) / mSampleRate);
1706 if (minBufCount < 2) {
1707 minBufCount = 2;
Glenn Kasten58912562012-04-03 10:45:00 -07001708 }
Glenn Kastene0fa4672012-04-24 14:35:14 -07001709 int minFrameCount = mNormalFrameCount * minBufCount;
1710 if (frameCount < minFrameCount) {
1711 frameCount = minFrameCount;
1712 }
1713 }
Glenn Kasten73d22752012-03-19 13:38:30 -07001714 }
1715
Mathias Agopian65ab4712010-07-14 17:59:35 -07001716 if (mType == DIRECT) {
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07001717 if ((format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM) {
1718 if (sampleRate != mSampleRate || format != mFormat || channelMask != mChannelMask) {
Steve Block29357bc2012-01-06 19:20:56 +00001719 ALOGE("createTrack_l() Bad parameter: sampleRate %d format %d, channelMask 0x%08x \""
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07001720 "for output %p with format %d",
1721 sampleRate, format, channelMask, mOutput, mFormat);
1722 lStatus = BAD_VALUE;
1723 goto Exit;
1724 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07001725 }
1726 } else {
1727 // Resampler implementation limits input sampling rate to 2 x output sampling rate.
1728 if (sampleRate > mSampleRate*2) {
Steve Block29357bc2012-01-06 19:20:56 +00001729 ALOGE("Sample rate out of range: %d mSampleRate %d", sampleRate, mSampleRate);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001730 lStatus = BAD_VALUE;
1731 goto Exit;
1732 }
1733 }
1734
Eric Laurent7c7f10b2011-06-17 21:29:58 -07001735 lStatus = initCheck();
1736 if (lStatus != NO_ERROR) {
Steve Block29357bc2012-01-06 19:20:56 +00001737 ALOGE("Audio driver not initialized.");
Mathias Agopian65ab4712010-07-14 17:59:35 -07001738 goto Exit;
1739 }
1740
1741 { // scope for mLock
1742 Mutex::Autolock _l(mLock);
Eric Laurentde070132010-07-13 04:45:46 -07001743
1744 // all tracks in same audio session must share the same routing strategy otherwise
1745 // conflicts will happen when tracks are moved from one output to another by audio policy
1746 // manager
Glenn Kasten02bbd202012-02-08 12:35:35 -08001747 uint32_t strategy = AudioSystem::getStrategyForStream(streamType);
Eric Laurentde070132010-07-13 04:45:46 -07001748 for (size_t i = 0; i < mTracks.size(); ++i) {
1749 sp<Track> t = mTracks[i];
Glenn Kasten639dbee2012-03-07 12:26:34 -08001750 if (t != 0 && !t->isOutputTrack()) {
Glenn Kasten02bbd202012-02-08 12:35:35 -08001751 uint32_t actual = AudioSystem::getStrategyForStream(t->streamType());
Glenn Kastend8796012011-10-28 10:31:42 -07001752 if (sessionId == t->sessionId() && strategy != actual) {
Steve Block29357bc2012-01-06 19:20:56 +00001753 ALOGE("createTrack_l() mismatched strategy; expected %u but found %u",
Glenn Kastend8796012011-10-28 10:31:42 -07001754 strategy, actual);
Eric Laurentde070132010-07-13 04:45:46 -07001755 lStatus = BAD_VALUE;
1756 goto Exit;
1757 }
1758 }
1759 }
1760
John Grossman4ff14ba2012-02-08 16:37:41 -08001761 if (!isTimed) {
1762 track = new Track(this, client, streamType, sampleRate, format,
Glenn Kasten73d22752012-03-19 13:38:30 -07001763 channelMask, frameCount, sharedBuffer, sessionId, flags);
John Grossman4ff14ba2012-02-08 16:37:41 -08001764 } else {
1765 track = TimedTrack::create(this, client, streamType, sampleRate, format,
1766 channelMask, frameCount, sharedBuffer, sessionId);
1767 }
1768 if (track == NULL || track->getCblk() == NULL || track->name() < 0) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001769 lStatus = NO_MEMORY;
1770 goto Exit;
1771 }
1772 mTracks.add(track);
1773
1774 sp<EffectChain> chain = getEffectChain_l(sessionId);
1775 if (chain != 0) {
Steve Block3856b092011-10-20 11:56:00 +01001776 ALOGV("createTrack_l() setting main buffer %p", chain->inBuffer());
Mathias Agopian65ab4712010-07-14 17:59:35 -07001777 track->setMainBuffer(chain->inBuffer());
Glenn Kasten02bbd202012-02-08 12:35:35 -08001778 chain->setStrategy(AudioSystem::getStrategyForStream(track->streamType()));
Eric Laurentb469b942011-05-09 12:09:06 -07001779 chain->incTrackCnt();
Mathias Agopian65ab4712010-07-14 17:59:35 -07001780 }
1781 }
Glenn Kasten3acbd052012-02-28 10:39:56 -08001782
1783#ifdef HAVE_REQUEST_PRIORITY
1784 if ((flags & IAudioFlinger::TRACK_FAST) && (tid != -1)) {
1785 pid_t callingPid = IPCThreadState::self()->getCallingPid();
1786 // we don't have CAP_SYS_NICE, nor do we want to have it as it's too powerful,
1787 // so ask activity manager to do this on our behalf
1788 int err = requestPriority(callingPid, tid, 1);
1789 if (err != 0) {
1790 ALOGW("Policy SCHED_FIFO priority %d is unavailable for pid %d tid %d; error %d",
1791 1, callingPid, tid, err);
1792 }
1793 }
1794#endif
1795
Mathias Agopian65ab4712010-07-14 17:59:35 -07001796 lStatus = NO_ERROR;
1797
1798Exit:
Glenn Kastene53b9ea2012-03-12 16:29:55 -07001799 if (status) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001800 *status = lStatus;
1801 }
1802 return track;
1803}
1804
1805uint32_t AudioFlinger::PlaybackThread::latency() const
1806{
Eric Laurentb8ba0a92011-08-07 16:32:26 -07001807 Mutex::Autolock _l(mLock);
1808 if (initCheck() == NO_ERROR) {
Dima Zavin799a70e2011-04-18 16:57:27 -07001809 return mOutput->stream->get_latency(mOutput->stream);
Eric Laurentb8ba0a92011-08-07 16:32:26 -07001810 } else {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001811 return 0;
1812 }
1813}
1814
Glenn Kasten6637baa2012-01-09 09:40:36 -08001815void AudioFlinger::PlaybackThread::setMasterVolume(float value)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001816{
Glenn Kasten6637baa2012-01-09 09:40:36 -08001817 Mutex::Autolock _l(mLock);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001818 mMasterVolume = value;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001819}
1820
Glenn Kasten6637baa2012-01-09 09:40:36 -08001821void AudioFlinger::PlaybackThread::setMasterMute(bool muted)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001822{
Glenn Kasten6637baa2012-01-09 09:40:36 -08001823 Mutex::Autolock _l(mLock);
1824 setMasterMute_l(muted);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001825}
1826
Glenn Kasten6637baa2012-01-09 09:40:36 -08001827void AudioFlinger::PlaybackThread::setStreamVolume(audio_stream_type_t stream, float value)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001828{
Glenn Kasten6637baa2012-01-09 09:40:36 -08001829 Mutex::Autolock _l(mLock);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001830 mStreamTypes[stream].volume = value;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001831}
1832
Glenn Kasten6637baa2012-01-09 09:40:36 -08001833void AudioFlinger::PlaybackThread::setStreamMute(audio_stream_type_t stream, bool muted)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001834{
Glenn Kasten6637baa2012-01-09 09:40:36 -08001835 Mutex::Autolock _l(mLock);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001836 mStreamTypes[stream].mute = muted;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001837}
1838
Glenn Kastenfff6d712012-01-12 16:38:12 -08001839float AudioFlinger::PlaybackThread::streamVolume(audio_stream_type_t stream) const
Mathias Agopian65ab4712010-07-14 17:59:35 -07001840{
Glenn Kasten6637baa2012-01-09 09:40:36 -08001841 Mutex::Autolock _l(mLock);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001842 return mStreamTypes[stream].volume;
1843}
1844
Mathias Agopian65ab4712010-07-14 17:59:35 -07001845// addTrack_l() must be called with ThreadBase::mLock held
1846status_t AudioFlinger::PlaybackThread::addTrack_l(const sp<Track>& track)
1847{
1848 status_t status = ALREADY_EXISTS;
1849
1850 // set retry count for buffer fill
1851 track->mRetryCount = kMaxTrackStartupRetries;
1852 if (mActiveTracks.indexOf(track) < 0) {
1853 // the track is newly added, make sure it fills up all its
1854 // buffers before playing. This is to ensure the client will
1855 // effectively get the latency it requested.
1856 track->mFillingUpStatus = Track::FS_FILLING;
1857 track->mResetDone = false;
Eric Laurent29864602012-05-08 18:57:51 -07001858 track->mPresentationCompleteFrames = 0;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001859 mActiveTracks.add(track);
1860 if (track->mainBuffer() != mMixBuffer) {
1861 sp<EffectChain> chain = getEffectChain_l(track->sessionId());
1862 if (chain != 0) {
Steve Block3856b092011-10-20 11:56:00 +01001863 ALOGV("addTrack_l() starting track on chain %p for session %d", chain.get(), track->sessionId());
Eric Laurentb469b942011-05-09 12:09:06 -07001864 chain->incActiveTrackCnt();
Mathias Agopian65ab4712010-07-14 17:59:35 -07001865 }
1866 }
1867
1868 status = NO_ERROR;
1869 }
1870
Steve Block3856b092011-10-20 11:56:00 +01001871 ALOGV("mWaitWorkCV.broadcast");
Mathias Agopian65ab4712010-07-14 17:59:35 -07001872 mWaitWorkCV.broadcast();
1873
1874 return status;
1875}
1876
1877// destroyTrack_l() must be called with ThreadBase::mLock held
1878void AudioFlinger::PlaybackThread::destroyTrack_l(const sp<Track>& track)
1879{
1880 track->mState = TrackBase::TERMINATED;
Glenn Kasten288ed212012-04-25 17:52:27 -07001881 // active tracks are removed by threadLoop()
Mathias Agopian65ab4712010-07-14 17:59:35 -07001882 if (mActiveTracks.indexOf(track) < 0) {
Eric Laurentb469b942011-05-09 12:09:06 -07001883 removeTrack_l(track);
1884 }
1885}
1886
1887void AudioFlinger::PlaybackThread::removeTrack_l(const sp<Track>& track)
1888{
Eric Laurent29864602012-05-08 18:57:51 -07001889 track->triggerEvents(AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE);
Eric Laurentb469b942011-05-09 12:09:06 -07001890 mTracks.remove(track);
1891 deleteTrackName_l(track->name());
Glenn Kasten288ed212012-04-25 17:52:27 -07001892 // redundant as track is about to be destroyed, for dumpsys only
1893 track->mName = -1;
1894 if (track->isFastTrack()) {
1895 int index = track->mFastIndex;
Eric Laurent29864602012-05-08 18:57:51 -07001896 ALOG_ASSERT(0 < index && index < (int)FastMixerState::kMaxFastTracks);
Glenn Kasten288ed212012-04-25 17:52:27 -07001897 ALOG_ASSERT(!(mFastTrackAvailMask & (1 << index)));
1898 mFastTrackAvailMask |= 1 << index;
1899 // redundant as track is about to be destroyed, for dumpsys only
1900 track->mFastIndex = -1;
1901 }
Eric Laurentb469b942011-05-09 12:09:06 -07001902 sp<EffectChain> chain = getEffectChain_l(track->sessionId());
1903 if (chain != 0) {
1904 chain->decTrackCnt();
Mathias Agopian65ab4712010-07-14 17:59:35 -07001905 }
1906}
1907
1908String8 AudioFlinger::PlaybackThread::getParameters(const String8& keys)
1909{
Eric Laurentb8ba0a92011-08-07 16:32:26 -07001910 String8 out_s8 = String8("");
Dima Zavinfce7a472011-04-19 22:30:36 -07001911 char *s;
1912
Eric Laurentb8ba0a92011-08-07 16:32:26 -07001913 Mutex::Autolock _l(mLock);
1914 if (initCheck() != NO_ERROR) {
1915 return out_s8;
1916 }
1917
Dima Zavin799a70e2011-04-18 16:57:27 -07001918 s = mOutput->stream->common.get_parameters(&mOutput->stream->common, keys.string());
Dima Zavinfce7a472011-04-19 22:30:36 -07001919 out_s8 = String8(s);
1920 free(s);
1921 return out_s8;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001922}
1923
Eric Laurentb8ba0a92011-08-07 16:32:26 -07001924// audioConfigChanged_l() must be called with AudioFlinger::mLock held
Mathias Agopian65ab4712010-07-14 17:59:35 -07001925void AudioFlinger::PlaybackThread::audioConfigChanged_l(int event, int param) {
1926 AudioSystem::OutputDescriptor desc;
Glenn Kastena0d68332012-01-27 16:47:15 -08001927 void *param2 = NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001928
Steve Block3856b092011-10-20 11:56:00 +01001929 ALOGV("PlaybackThread::audioConfigChanged_l, thread %p, event %d, param %d", this, event, param);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001930
1931 switch (event) {
1932 case AudioSystem::OUTPUT_OPENED:
1933 case AudioSystem::OUTPUT_CONFIG_CHANGED:
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07001934 desc.channels = mChannelMask;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001935 desc.samplingRate = mSampleRate;
1936 desc.format = mFormat;
Glenn Kasten58912562012-04-03 10:45:00 -07001937 desc.frameCount = mNormalFrameCount; // FIXME see AudioFlinger::frameCount(audio_io_handle_t)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001938 desc.latency = latency();
1939 param2 = &desc;
1940 break;
1941
1942 case AudioSystem::STREAM_CONFIG_CHANGED:
1943 param2 = &param;
1944 case AudioSystem::OUTPUT_CLOSED:
1945 default:
1946 break;
1947 }
1948 mAudioFlinger->audioConfigChanged_l(event, mId, param2);
1949}
1950
1951void AudioFlinger::PlaybackThread::readOutputParameters()
1952{
Dima Zavin799a70e2011-04-18 16:57:27 -07001953 mSampleRate = mOutput->stream->common.get_sample_rate(&mOutput->stream->common);
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07001954 mChannelMask = mOutput->stream->common.get_channels(&mOutput->stream->common);
1955 mChannelCount = (uint16_t)popcount(mChannelMask);
Dima Zavin799a70e2011-04-18 16:57:27 -07001956 mFormat = mOutput->stream->common.get_format(&mOutput->stream->common);
Glenn Kastenb9980652012-01-11 09:48:27 -08001957 mFrameSize = audio_stream_frame_size(&mOutput->stream->common);
Dima Zavin799a70e2011-04-18 16:57:27 -07001958 mFrameCount = mOutput->stream->common.get_buffer_size(&mOutput->stream->common) / mFrameSize;
Glenn Kasten58912562012-04-03 10:45:00 -07001959 if (mFrameCount & 15) {
1960 ALOGW("HAL output buffer size is %u frames but AudioMixer requires multiples of 16 frames",
1961 mFrameCount);
1962 }
1963
Glenn Kasten300a2ee2012-04-25 13:47:36 -07001964 // Calculate size of normal mix buffer relative to the HAL output buffer size
Glenn Kasten4adcede2012-05-14 12:26:02 -07001965 double multiplier = 1.0;
Glenn Kasten300a2ee2012-04-25 13:47:36 -07001966 if (mType == MIXER && (kUseFastMixer == FastMixer_Static || kUseFastMixer == FastMixer_Dynamic)) {
Glenn Kasten58912562012-04-03 10:45:00 -07001967 size_t minNormalFrameCount = (kMinNormalMixBufferSizeMs * mSampleRate) / 1000;
Glenn Kasten4adcede2012-05-14 12:26:02 -07001968 size_t maxNormalFrameCount = (kMaxNormalMixBufferSizeMs * mSampleRate) / 1000;
1969 // round up minimum and round down maximum to nearest 16 frames to satisfy AudioMixer
1970 minNormalFrameCount = (minNormalFrameCount + 15) & ~15;
1971 maxNormalFrameCount = maxNormalFrameCount & ~15;
1972 if (maxNormalFrameCount < minNormalFrameCount) {
1973 maxNormalFrameCount = minNormalFrameCount;
1974 }
1975 multiplier = (double) minNormalFrameCount / (double) mFrameCount;
1976 if (multiplier <= 1.0) {
1977 multiplier = 1.0;
1978 } else if (multiplier <= 2.0) {
1979 if (2 * mFrameCount <= maxNormalFrameCount) {
1980 multiplier = 2.0;
1981 } else {
1982 multiplier = (double) maxNormalFrameCount / (double) mFrameCount;
1983 }
1984 } else {
1985 // prefer an even multiplier, for compatibility with doubling of fast tracks due to HAL SRC
1986 // (it would be unusual for the normal mix buffer size to not be a multiple of fast
1987 // track, but we sometimes have to do this to satisfy the maximum frame count constraint)
1988 // FIXME this rounding up should not be done if no HAL SRC
1989 uint32_t truncMult = (uint32_t) multiplier;
1990 if ((truncMult & 1)) {
1991 if ((truncMult + 1) * mFrameCount <= maxNormalFrameCount) {
1992 ++truncMult;
1993 }
1994 }
1995 multiplier = (double) truncMult;
Glenn Kasten58912562012-04-03 10:45:00 -07001996 }
Glenn Kasten58912562012-04-03 10:45:00 -07001997 }
Glenn Kasten4adcede2012-05-14 12:26:02 -07001998 mNormalFrameCount = multiplier * mFrameCount;
1999 // round up to nearest 16 frames to satisfy AudioMixer
2000 mNormalFrameCount = (mNormalFrameCount + 15) & ~15;
Glenn Kasten58912562012-04-03 10:45:00 -07002001 ALOGI("HAL output buffer size %u frames, normal mix buffer size %u frames", mFrameCount, mNormalFrameCount);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002002
2003 // FIXME - Current mixer implementation only supports stereo output: Always
2004 // Allocate a stereo buffer even if HW output is mono.
Glenn Kastene9dd0172012-01-27 18:08:45 -08002005 delete[] mMixBuffer;
Glenn Kasten58912562012-04-03 10:45:00 -07002006 mMixBuffer = new int16_t[mNormalFrameCount * 2];
2007 memset(mMixBuffer, 0, mNormalFrameCount * 2 * sizeof(int16_t));
Mathias Agopian65ab4712010-07-14 17:59:35 -07002008
Eric Laurentde070132010-07-13 04:45:46 -07002009 // force reconfiguration of effect chains and engines to take new buffer size and audio
2010 // parameters into account
2011 // Note that mLock is not held when readOutputParameters() is called from the constructor
2012 // but in this case nothing is done below as no audio sessions have effect yet so it doesn't
2013 // matter.
2014 // create a copy of mEffectChains as calling moveEffectChain_l() can reorder some effect chains
2015 Vector< sp<EffectChain> > effectChains = mEffectChains;
2016 for (size_t i = 0; i < effectChains.size(); i ++) {
Eric Laurent39e94f82010-07-28 01:32:47 -07002017 mAudioFlinger->moveEffectChain_l(effectChains[i]->sessionId(), this, this, false);
Eric Laurentde070132010-07-13 04:45:46 -07002018 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07002019}
2020
2021status_t AudioFlinger::PlaybackThread::getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames)
2022{
Glenn Kastena0d68332012-01-27 16:47:15 -08002023 if (halFrames == NULL || dspFrames == NULL) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07002024 return BAD_VALUE;
2025 }
Eric Laurentb8ba0a92011-08-07 16:32:26 -07002026 Mutex::Autolock _l(mLock);
Eric Laurent7c7f10b2011-06-17 21:29:58 -07002027 if (initCheck() != NO_ERROR) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07002028 return INVALID_OPERATION;
2029 }
Dima Zavin799a70e2011-04-18 16:57:27 -07002030 *halFrames = mBytesWritten / audio_stream_frame_size(&mOutput->stream->common);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002031
Dima Zavin799a70e2011-04-18 16:57:27 -07002032 return mOutput->stream->get_render_position(mOutput->stream, dspFrames);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002033}
2034
Eric Laurent39e94f82010-07-28 01:32:47 -07002035uint32_t AudioFlinger::PlaybackThread::hasAudioSession(int sessionId)
Mathias Agopian65ab4712010-07-14 17:59:35 -07002036{
2037 Mutex::Autolock _l(mLock);
Eric Laurent39e94f82010-07-28 01:32:47 -07002038 uint32_t result = 0;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002039 if (getEffectChain_l(sessionId) != 0) {
Eric Laurent39e94f82010-07-28 01:32:47 -07002040 result = EFFECT_SESSION;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002041 }
2042
2043 for (size_t i = 0; i < mTracks.size(); ++i) {
2044 sp<Track> track = mTracks[i];
Eric Laurentde070132010-07-13 04:45:46 -07002045 if (sessionId == track->sessionId() &&
2046 !(track->mCblk->flags & CBLK_INVALID_MSK)) {
Eric Laurent39e94f82010-07-28 01:32:47 -07002047 result |= TRACK_SESSION;
2048 break;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002049 }
2050 }
2051
Eric Laurent39e94f82010-07-28 01:32:47 -07002052 return result;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002053}
2054
Eric Laurentde070132010-07-13 04:45:46 -07002055uint32_t AudioFlinger::PlaybackThread::getStrategyForSession_l(int sessionId)
2056{
Dima Zavinfce7a472011-04-19 22:30:36 -07002057 // session AUDIO_SESSION_OUTPUT_MIX is placed in same strategy as MUSIC stream so that
Eric Laurentde070132010-07-13 04:45:46 -07002058 // it is moved to correct output by audio policy manager when A2DP is connected or disconnected
Dima Zavinfce7a472011-04-19 22:30:36 -07002059 if (sessionId == AUDIO_SESSION_OUTPUT_MIX) {
2060 return AudioSystem::getStrategyForStream(AUDIO_STREAM_MUSIC);
Eric Laurentde070132010-07-13 04:45:46 -07002061 }
2062 for (size_t i = 0; i < mTracks.size(); i++) {
2063 sp<Track> track = mTracks[i];
2064 if (sessionId == track->sessionId() &&
2065 !(track->mCblk->flags & CBLK_INVALID_MSK)) {
Glenn Kasten02bbd202012-02-08 12:35:35 -08002066 return AudioSystem::getStrategyForStream(track->streamType());
Eric Laurentde070132010-07-13 04:45:46 -07002067 }
2068 }
Dima Zavinfce7a472011-04-19 22:30:36 -07002069 return AudioSystem::getStrategyForStream(AUDIO_STREAM_MUSIC);
Eric Laurentde070132010-07-13 04:45:46 -07002070}
2071
Mathias Agopian65ab4712010-07-14 17:59:35 -07002072
Glenn Kastenaed850d2012-01-26 09:46:34 -08002073AudioFlinger::AudioStreamOut* AudioFlinger::PlaybackThread::getOutput() const
Eric Laurentb8ba0a92011-08-07 16:32:26 -07002074{
2075 Mutex::Autolock _l(mLock);
2076 return mOutput;
2077}
2078
2079AudioFlinger::AudioStreamOut* AudioFlinger::PlaybackThread::clearOutput()
2080{
2081 Mutex::Autolock _l(mLock);
2082 AudioStreamOut *output = mOutput;
2083 mOutput = NULL;
Glenn Kasten58912562012-04-03 10:45:00 -07002084 // FIXME FastMixer might also have a raw ptr to mOutputSink;
2085 // must push a NULL and wait for ack
2086 mOutputSink.clear();
2087 mPipeSink.clear();
2088 mNormalSink.clear();
Eric Laurentb8ba0a92011-08-07 16:32:26 -07002089 return output;
2090}
2091
2092// this method must always be called either with ThreadBase mLock held or inside the thread loop
Glenn Kasten0bf65bd2012-02-28 18:32:53 -08002093audio_stream_t* AudioFlinger::PlaybackThread::stream() const
Eric Laurentb8ba0a92011-08-07 16:32:26 -07002094{
2095 if (mOutput == NULL) {
2096 return NULL;
2097 }
2098 return &mOutput->stream->common;
2099}
2100
Glenn Kasten0bf65bd2012-02-28 18:32:53 -08002101uint32_t AudioFlinger::PlaybackThread::activeSleepTimeUs() const
Eric Laurent162b40b2011-12-05 09:47:19 -08002102{
2103 // A2DP output latency is not due only to buffering capacity. It also reflects encoding,
2104 // decoding and transfer time. So sleeping for half of the latency would likely cause
2105 // underruns
2106 if (audio_is_a2dp_device((audio_devices_t)mDevice)) {
Glenn Kasten58912562012-04-03 10:45:00 -07002107 return (uint32_t)((uint32_t)((mNormalFrameCount * 1000) / mSampleRate) * 1000);
Eric Laurent162b40b2011-12-05 09:47:19 -08002108 } else {
2109 return (uint32_t)(mOutput->stream->get_latency(mOutput->stream) * 1000) / 2;
2110 }
2111}
2112
Eric Laurenta011e352012-03-29 15:51:43 -07002113status_t AudioFlinger::PlaybackThread::setSyncEvent(const sp<SyncEvent>& event)
2114{
2115 if (!isValidSyncEvent(event)) {
2116 return BAD_VALUE;
2117 }
2118
2119 Mutex::Autolock _l(mLock);
2120
2121 for (size_t i = 0; i < mTracks.size(); ++i) {
2122 sp<Track> track = mTracks[i];
2123 if (event->triggerSession() == track->sessionId()) {
2124 track->setSyncEvent(event);
2125 return NO_ERROR;
2126 }
2127 }
2128
2129 return NAME_NOT_FOUND;
2130}
2131
2132bool AudioFlinger::PlaybackThread::isValidSyncEvent(const sp<SyncEvent>& event)
2133{
2134 switch (event->type()) {
2135 case AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE:
2136 return true;
2137 default:
2138 break;
2139 }
2140 return false;
2141}
2142
Eric Laurent44a957f2012-05-15 15:26:05 -07002143void AudioFlinger::PlaybackThread::threadLoop_removeTracks(const Vector< sp<Track> >& tracksToRemove)
2144{
2145 size_t count = tracksToRemove.size();
2146 if (CC_UNLIKELY(count)) {
2147 for (size_t i = 0 ; i < count ; i++) {
2148 const sp<Track>& track = tracksToRemove.itemAt(i);
2149 if ((track->sharedBuffer() != 0) &&
2150 (track->mState == TrackBase::ACTIVE || track->mState == TrackBase::RESUMING)) {
2151 AudioSystem::stopOutput(mId, track->streamType(), track->sessionId());
2152 }
2153 }
2154 }
2155
2156}
2157
Mathias Agopian65ab4712010-07-14 17:59:35 -07002158// ----------------------------------------------------------------------------
2159
Glenn Kasten23bb8be2012-01-26 10:38:26 -08002160AudioFlinger::MixerThread::MixerThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output,
Glenn Kasten72ef00d2012-01-17 11:09:42 -08002161 audio_io_handle_t id, uint32_t device, type_t type)
Glenn Kasten58912562012-04-03 10:45:00 -07002162 : PlaybackThread(audioFlinger, output, id, device, type),
2163 // mAudioMixer below
2164#ifdef SOAKER
2165 mSoaker(NULL),
2166#endif
2167 // mFastMixer below
2168 mFastMixerFutex(0)
2169 // mOutputSink below
2170 // mPipeSink below
2171 // mNormalSink below
Mathias Agopian65ab4712010-07-14 17:59:35 -07002172{
Glenn Kasten58912562012-04-03 10:45:00 -07002173 ALOGV("MixerThread() id=%d device=%d type=%d", id, device, type);
2174 ALOGV("mSampleRate=%d, mChannelMask=%d, mChannelCount=%d, mFormat=%d, mFrameSize=%d, "
2175 "mFrameCount=%d, mNormalFrameCount=%d",
2176 mSampleRate, mChannelMask, mChannelCount, mFormat, mFrameSize, mFrameCount,
2177 mNormalFrameCount);
2178 mAudioMixer = new AudioMixer(mNormalFrameCount, mSampleRate);
2179
Mathias Agopian65ab4712010-07-14 17:59:35 -07002180 // FIXME - Current mixer implementation only supports stereo output
2181 if (mChannelCount == 1) {
Steve Block29357bc2012-01-06 19:20:56 +00002182 ALOGE("Invalid audio hardware channel count");
Mathias Agopian65ab4712010-07-14 17:59:35 -07002183 }
Glenn Kasten58912562012-04-03 10:45:00 -07002184
2185 // create an NBAIO sink for the HAL output stream, and negotiate
2186 mOutputSink = new AudioStreamOutSink(output->stream);
2187 size_t numCounterOffers = 0;
2188 const NBAIO_Format offers[1] = {Format_from_SR_C(mSampleRate, mChannelCount)};
2189 ssize_t index = mOutputSink->negotiate(offers, 1, NULL, numCounterOffers);
2190 ALOG_ASSERT(index == 0);
2191
Glenn Kasten300a2ee2012-04-25 13:47:36 -07002192 // initialize fast mixer depending on configuration
2193 bool initFastMixer;
2194 switch (kUseFastMixer) {
2195 case FastMixer_Never:
2196 initFastMixer = false;
2197 break;
2198 case FastMixer_Always:
2199 initFastMixer = true;
2200 break;
2201 case FastMixer_Static:
2202 case FastMixer_Dynamic:
2203 initFastMixer = mFrameCount < mNormalFrameCount;
2204 break;
2205 }
2206 if (initFastMixer) {
Glenn Kasten58912562012-04-03 10:45:00 -07002207
2208 // create a MonoPipe to connect our submix to FastMixer
2209 NBAIO_Format format = mOutputSink->format();
Glenn Kasten9017e5e2012-05-15 07:39:52 -07002210 // This pipe depth compensates for scheduling latency of the normal mixer thread.
2211 // When it wakes up after a maximum latency, it runs a few cycles quickly before
2212 // finally blocking. Note the pipe implementation rounds up the request to a power of 2.
2213 MonoPipe *monoPipe = new MonoPipe(mNormalFrameCount * 4, format, true /*writeCanBlock*/);
Glenn Kasten58912562012-04-03 10:45:00 -07002214 const NBAIO_Format offers[1] = {format};
2215 size_t numCounterOffers = 0;
2216 ssize_t index = monoPipe->negotiate(offers, 1, NULL, numCounterOffers);
2217 ALOG_ASSERT(index == 0);
2218 mPipeSink = monoPipe;
2219
2220#ifdef SOAKER
2221 // create a soaker as workaround for governor issues
2222 mSoaker = new Soaker();
2223 // FIXME Soaker should only run when needed, i.e. when FastMixer is not in COLD_IDLE
2224 mSoaker->run("Soaker", PRIORITY_LOWEST);
2225#endif
2226
2227 // create fast mixer and configure it initially with just one fast track for our submix
2228 mFastMixer = new FastMixer();
2229 FastMixerStateQueue *sq = mFastMixer->sq();
2230 FastMixerState *state = sq->begin();
2231 FastTrack *fastTrack = &state->mFastTracks[0];
2232 // wrap the source side of the MonoPipe to make it an AudioBufferProvider
2233 fastTrack->mBufferProvider = new SourceAudioBufferProvider(new MonoPipeReader(monoPipe));
2234 fastTrack->mVolumeProvider = NULL;
2235 fastTrack->mGeneration++;
2236 state->mFastTracksGen++;
2237 state->mTrackMask = 1;
2238 // fast mixer will use the HAL output sink
2239 state->mOutputSink = mOutputSink.get();
2240 state->mOutputSinkGen++;
2241 state->mFrameCount = mFrameCount;
2242 state->mCommand = FastMixerState::COLD_IDLE;
2243 // already done in constructor initialization list
2244 //mFastMixerFutex = 0;
2245 state->mColdFutexAddr = &mFastMixerFutex;
2246 state->mColdGen++;
2247 state->mDumpState = &mFastMixerDumpState;
2248 sq->end();
2249 sq->push(FastMixerStateQueue::BLOCK_UNTIL_PUSHED);
2250
2251 // start the fast mixer
2252 mFastMixer->run("FastMixer", PRIORITY_URGENT_AUDIO);
2253#ifdef HAVE_REQUEST_PRIORITY
2254 pid_t tid = mFastMixer->getTid();
2255 int err = requestPriority(getpid_cached, tid, 2);
2256 if (err != 0) {
2257 ALOGW("Policy SCHED_FIFO priority %d is unavailable for pid %d tid %d; error %d",
2258 2, getpid_cached, tid, err);
2259 }
2260#endif
2261
2262 } else {
2263 mFastMixer = NULL;
2264 }
Glenn Kasten300a2ee2012-04-25 13:47:36 -07002265
2266 switch (kUseFastMixer) {
2267 case FastMixer_Never:
2268 case FastMixer_Dynamic:
2269 mNormalSink = mOutputSink;
2270 break;
2271 case FastMixer_Always:
2272 mNormalSink = mPipeSink;
2273 break;
2274 case FastMixer_Static:
2275 mNormalSink = initFastMixer ? mPipeSink : mOutputSink;
2276 break;
2277 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07002278}
2279
2280AudioFlinger::MixerThread::~MixerThread()
2281{
Glenn Kasten58912562012-04-03 10:45:00 -07002282 if (mFastMixer != NULL) {
2283 FastMixerStateQueue *sq = mFastMixer->sq();
2284 FastMixerState *state = sq->begin();
2285 if (state->mCommand == FastMixerState::COLD_IDLE) {
2286 int32_t old = android_atomic_inc(&mFastMixerFutex);
2287 if (old == -1) {
2288 __futex_syscall3(&mFastMixerFutex, FUTEX_WAKE_PRIVATE, 1);
2289 }
2290 }
2291 state->mCommand = FastMixerState::EXIT;
2292 sq->end();
2293 sq->push(FastMixerStateQueue::BLOCK_UNTIL_PUSHED);
2294 mFastMixer->join();
2295 // Though the fast mixer thread has exited, it's state queue is still valid.
2296 // We'll use that extract the final state which contains one remaining fast track
2297 // corresponding to our sub-mix.
2298 state = sq->begin();
2299 ALOG_ASSERT(state->mTrackMask == 1);
2300 FastTrack *fastTrack = &state->mFastTracks[0];
2301 ALOG_ASSERT(fastTrack->mBufferProvider != NULL);
2302 delete fastTrack->mBufferProvider;
2303 sq->end(false /*didModify*/);
2304 delete mFastMixer;
2305#ifdef SOAKER
2306 if (mSoaker != NULL) {
2307 mSoaker->requestExitAndWait();
2308 }
2309 delete mSoaker;
2310#endif
2311 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07002312 delete mAudioMixer;
2313}
2314
Glenn Kasten83efdd02012-02-24 07:21:32 -08002315class CpuStats {
2316public:
Glenn Kasten190a46f2012-03-06 11:27:10 -08002317 CpuStats();
2318 void sample(const String8 &title);
Glenn Kasten83efdd02012-02-24 07:21:32 -08002319#ifdef DEBUG_CPU_USAGE
2320private:
Glenn Kasten190a46f2012-03-06 11:27:10 -08002321 ThreadCpuUsage mCpuUsage; // instantaneous thread CPU usage in wall clock ns
2322 CentralTendencyStatistics mWcStats; // statistics on thread CPU usage in wall clock ns
2323
2324 CentralTendencyStatistics mHzStats; // statistics on thread CPU usage in cycles
2325
2326 int mCpuNum; // thread's current CPU number
2327 int mCpukHz; // frequency of thread's current CPU in kHz
Glenn Kasten83efdd02012-02-24 07:21:32 -08002328#endif
2329};
2330
Glenn Kasten190a46f2012-03-06 11:27:10 -08002331CpuStats::CpuStats()
Glenn Kasten83efdd02012-02-24 07:21:32 -08002332#ifdef DEBUG_CPU_USAGE
Glenn Kasten190a46f2012-03-06 11:27:10 -08002333 : mCpuNum(-1), mCpukHz(-1)
2334#endif
2335{
2336}
2337
2338void CpuStats::sample(const String8 &title) {
2339#ifdef DEBUG_CPU_USAGE
2340 // get current thread's delta CPU time in wall clock ns
2341 double wcNs;
2342 bool valid = mCpuUsage.sampleAndEnable(wcNs);
2343
2344 // record sample for wall clock statistics
2345 if (valid) {
2346 mWcStats.sample(wcNs);
2347 }
2348
2349 // get the current CPU number
2350 int cpuNum = sched_getcpu();
2351
2352 // get the current CPU frequency in kHz
2353 int cpukHz = mCpuUsage.getCpukHz(cpuNum);
2354
2355 // check if either CPU number or frequency changed
2356 if (cpuNum != mCpuNum || cpukHz != mCpukHz) {
2357 mCpuNum = cpuNum;
2358 mCpukHz = cpukHz;
2359 // ignore sample for purposes of cycles
2360 valid = false;
2361 }
2362
2363 // if no change in CPU number or frequency, then record sample for cycle statistics
2364 if (valid && mCpukHz > 0) {
2365 double cycles = wcNs * cpukHz * 0.000001;
2366 mHzStats.sample(cycles);
2367 }
2368
2369 unsigned n = mWcStats.n();
2370 // mCpuUsage.elapsed() is expensive, so don't call it every loop
Glenn Kasten83efdd02012-02-24 07:21:32 -08002371 if ((n & 127) == 1) {
Glenn Kasten190a46f2012-03-06 11:27:10 -08002372 long long elapsed = mCpuUsage.elapsed();
Glenn Kasten83efdd02012-02-24 07:21:32 -08002373 if (elapsed >= DEBUG_CPU_USAGE * 1000000000LL) {
2374 double perLoop = elapsed / (double) n;
2375 double perLoop100 = perLoop * 0.01;
Glenn Kasten190a46f2012-03-06 11:27:10 -08002376 double perLoop1k = perLoop * 0.001;
2377 double mean = mWcStats.mean();
2378 double stddev = mWcStats.stddev();
2379 double minimum = mWcStats.minimum();
2380 double maximum = mWcStats.maximum();
2381 double meanCycles = mHzStats.mean();
2382 double stddevCycles = mHzStats.stddev();
2383 double minCycles = mHzStats.minimum();
2384 double maxCycles = mHzStats.maximum();
2385 mCpuUsage.resetElapsed();
2386 mWcStats.reset();
2387 mHzStats.reset();
2388 ALOGD("CPU usage for %s over past %.1f secs\n"
2389 " (%u mixer loops at %.1f mean ms per loop):\n"
2390 " us per mix loop: mean=%.0f stddev=%.0f min=%.0f max=%.0f\n"
2391 " %% of wall: mean=%.1f stddev=%.1f min=%.1f max=%.1f\n"
2392 " MHz: mean=%.1f, stddev=%.1f, min=%.1f max=%.1f",
2393 title.string(),
Glenn Kasten83efdd02012-02-24 07:21:32 -08002394 elapsed * .000000001, n, perLoop * .000001,
2395 mean * .001,
2396 stddev * .001,
2397 minimum * .001,
2398 maximum * .001,
2399 mean / perLoop100,
2400 stddev / perLoop100,
2401 minimum / perLoop100,
Glenn Kasten190a46f2012-03-06 11:27:10 -08002402 maximum / perLoop100,
2403 meanCycles / perLoop1k,
2404 stddevCycles / perLoop1k,
2405 minCycles / perLoop1k,
2406 maxCycles / perLoop1k);
2407
Glenn Kasten83efdd02012-02-24 07:21:32 -08002408 }
2409 }
2410#endif
2411};
2412
Glenn Kasten37d825e2012-02-24 07:21:48 -08002413void AudioFlinger::PlaybackThread::checkSilentMode_l()
2414{
2415 if (!mMasterMute) {
2416 char value[PROPERTY_VALUE_MAX];
2417 if (property_get("ro.audio.silent", value, "0") > 0) {
2418 char *endptr;
2419 unsigned long ul = strtoul(value, &endptr, 0);
2420 if (*endptr == '\0' && ul != 0) {
2421 ALOGD("Silence is golden");
2422 // The setprop command will not allow a property to be changed after
2423 // the first time it is set, so we don't have to worry about un-muting.
2424 setMasterMute_l(true);
2425 }
2426 }
2427 }
2428}
2429
Glenn Kasten000f0e32012-03-01 17:10:56 -08002430bool AudioFlinger::PlaybackThread::threadLoop()
Mathias Agopian65ab4712010-07-14 17:59:35 -07002431{
2432 Vector< sp<Track> > tracksToRemove;
Glenn Kasten688a6402012-02-29 07:57:06 -08002433
Glenn Kasten000f0e32012-03-01 17:10:56 -08002434 standbyTime = systemTime();
Glenn Kasten000f0e32012-03-01 17:10:56 -08002435
2436 // MIXER
Mathias Agopian65ab4712010-07-14 17:59:35 -07002437 nsecs_t lastWarning = 0;
Glenn Kasten000f0e32012-03-01 17:10:56 -08002438if (mType == MIXER) {
2439 longStandbyExit = false;
2440}
Glenn Kasten688a6402012-02-29 07:57:06 -08002441
Glenn Kasten000f0e32012-03-01 17:10:56 -08002442 // DUPLICATING
2443 // FIXME could this be made local to while loop?
2444 writeFrames = 0;
Glenn Kasten688a6402012-02-29 07:57:06 -08002445
Glenn Kasten66fcab92012-02-24 14:59:21 -08002446 cacheParameters_l();
Glenn Kasten000f0e32012-03-01 17:10:56 -08002447 sleepTime = idleSleepTime;
2448
2449if (mType == MIXER) {
2450 sleepTimeShift = 0;
2451}
2452
Glenn Kasten83efdd02012-02-24 07:21:32 -08002453 CpuStats cpuStats;
Glenn Kasten190a46f2012-03-06 11:27:10 -08002454 const String8 myName(String8::format("thread %p type %d TID %d", this, mType, gettid()));
Mathias Agopian65ab4712010-07-14 17:59:35 -07002455
Eric Laurentfeb0db62011-07-22 09:04:31 -07002456 acquireWakeLock();
2457
Mathias Agopian65ab4712010-07-14 17:59:35 -07002458 while (!exitPending())
2459 {
Glenn Kasten190a46f2012-03-06 11:27:10 -08002460 cpuStats.sample(myName);
Glenn Kasten688a6402012-02-29 07:57:06 -08002461
Glenn Kasten73ca0f52012-02-29 07:56:15 -08002462 Vector< sp<EffectChain> > effectChains;
2463
Mathias Agopian65ab4712010-07-14 17:59:35 -07002464 processConfigEvents();
2465
Mathias Agopian65ab4712010-07-14 17:59:35 -07002466 { // scope for mLock
2467
2468 Mutex::Autolock _l(mLock);
2469
2470 if (checkForNewParameters_l()) {
Glenn Kasten66fcab92012-02-24 14:59:21 -08002471 cacheParameters_l();
Mathias Agopian65ab4712010-07-14 17:59:35 -07002472 }
2473
Glenn Kastenfa26a852012-03-06 11:28:04 -08002474 saveOutputTracks();
Glenn Kasten000f0e32012-03-01 17:10:56 -08002475
Mathias Agopian65ab4712010-07-14 17:59:35 -07002476 // put audio hardware into standby after short delay
Glenn Kasten3e074702012-02-28 18:40:35 -08002477 if (CC_UNLIKELY((!mActiveTracks.size() && systemTime() > standbyTime) ||
Glenn Kastenc455fe92012-02-29 07:07:30 -08002478 mSuspended > 0)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07002479 if (!mStandby) {
Glenn Kasten000f0e32012-03-01 17:10:56 -08002480
2481 threadLoop_standby();
2482
Mathias Agopian65ab4712010-07-14 17:59:35 -07002483 mStandby = true;
2484 mBytesWritten = 0;
2485 }
2486
Glenn Kasten3e074702012-02-28 18:40:35 -08002487 if (!mActiveTracks.size() && mConfigEvents.isEmpty()) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07002488 // we're about to wait, flush the binder command buffer
2489 IPCThreadState::self()->flushCommands();
2490
Glenn Kastenfa26a852012-03-06 11:28:04 -08002491 clearOutputTracks();
Glenn Kasten000f0e32012-03-01 17:10:56 -08002492
Mathias Agopian65ab4712010-07-14 17:59:35 -07002493 if (exitPending()) break;
2494
Eric Laurentfeb0db62011-07-22 09:04:31 -07002495 releaseWakeLock_l();
Mathias Agopian65ab4712010-07-14 17:59:35 -07002496 // wait until we have something to do...
Glenn Kasten190a46f2012-03-06 11:27:10 -08002497 ALOGV("%s going to sleep", myName.string());
Mathias Agopian65ab4712010-07-14 17:59:35 -07002498 mWaitWorkCV.wait(mLock);
Glenn Kasten190a46f2012-03-06 11:27:10 -08002499 ALOGV("%s waking up", myName.string());
Eric Laurentfeb0db62011-07-22 09:04:31 -07002500 acquireWakeLock_l();
Mathias Agopian65ab4712010-07-14 17:59:35 -07002501
Eric Laurentda747442012-04-25 18:53:13 -07002502 mMixerStatus = MIXER_IDLE;
Glenn Kasten81028042012-04-30 18:15:12 -07002503 mMixerStatusIgnoringFastTracks = MIXER_IDLE;
Glenn Kasten000f0e32012-03-01 17:10:56 -08002504
Glenn Kasten37d825e2012-02-24 07:21:48 -08002505 checkSilentMode_l();
Mathias Agopian65ab4712010-07-14 17:59:35 -07002506
Glenn Kasten000f0e32012-03-01 17:10:56 -08002507 standbyTime = systemTime() + standbyDelay;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002508 sleepTime = idleSleepTime;
Glenn Kasten66fcab92012-02-24 14:59:21 -08002509 if (mType == MIXER) {
2510 sleepTimeShift = 0;
2511 }
Glenn Kasten000f0e32012-03-01 17:10:56 -08002512
Mathias Agopian65ab4712010-07-14 17:59:35 -07002513 continue;
2514 }
2515 }
2516
Glenn Kasten81028042012-04-30 18:15:12 -07002517 // mMixerStatusIgnoringFastTracks is also updated internally
Eric Laurentda747442012-04-25 18:53:13 -07002518 mMixerStatus = prepareTracks_l(&tracksToRemove);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002519
2520 // prevent any changes in effect chain list and in each effect chain
2521 // during mixing and effect process as the audio buffers could be deleted
2522 // or modified if an effect is created or deleted
Eric Laurentde070132010-07-13 04:45:46 -07002523 lockEffectChains_l(effectChains);
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -08002524 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07002525
Glenn Kastenfec279f2012-03-08 07:47:15 -08002526 if (CC_LIKELY(mMixerStatus == MIXER_TRACKS_READY)) {
Glenn Kasten000f0e32012-03-01 17:10:56 -08002527 threadLoop_mix();
2528 } else {
2529 threadLoop_sleepTime();
2530 }
2531
2532 if (mSuspended > 0) {
2533 sleepTime = suspendSleepTimeUs();
2534 }
2535
2536 // only process effects if we're going to write
2537 if (sleepTime == 0) {
Glenn Kasten000f0e32012-03-01 17:10:56 -08002538 for (size_t i = 0; i < effectChains.size(); i ++) {
2539 effectChains[i]->process_l();
2540 }
2541 }
2542
2543 // enable changes in effect chain
2544 unlockEffectChains(effectChains);
2545
2546 // sleepTime == 0 means we must write to audio hardware
2547 if (sleepTime == 0) {
2548
2549 threadLoop_write();
2550
2551if (mType == MIXER) {
2552 // write blocked detection
2553 nsecs_t now = systemTime();
2554 nsecs_t delta = now - mLastWriteTime;
2555 if (!mStandby && delta > maxPeriod) {
2556 mNumDelayedWrites++;
2557 if ((now - lastWarning) > kWarningThrottleNs) {
Glenn Kasten99c99d02012-05-14 16:37:13 -07002558#if defined(ATRACE_TAG) && (ATRACE_TAG != ATRACE_TAG_NEVER)
Glenn Kastend8e6fd32012-05-07 11:07:57 -07002559 ScopedTrace st(ATRACE_TAG, "underrun");
Glenn Kasten99c99d02012-05-14 16:37:13 -07002560#endif
Glenn Kasten000f0e32012-03-01 17:10:56 -08002561 ALOGW("write blocked for %llu msecs, %d delayed writes, thread %p",
2562 ns2ms(delta), mNumDelayedWrites, this);
2563 lastWarning = now;
2564 }
2565 // FIXME this is broken: longStandbyExit should be handled out of the if() and with
2566 // a different threshold. Or completely removed for what it is worth anyway...
2567 if (mStandby) {
2568 longStandbyExit = true;
2569 }
2570 }
2571}
2572
2573 mStandby = false;
2574 } else {
2575 usleep(sleepTime);
2576 }
2577
Glenn Kasten58912562012-04-03 10:45:00 -07002578 // Finally let go of removed track(s), without the lock held
Glenn Kasten000f0e32012-03-01 17:10:56 -08002579 // since we can't guarantee the destructors won't acquire that
Glenn Kasten58912562012-04-03 10:45:00 -07002580 // same lock. This will also mutate and push a new fast mixer state.
2581 threadLoop_removeTracks(tracksToRemove);
Glenn Kasten1465f0c2012-03-06 11:23:32 -08002582 tracksToRemove.clear();
Glenn Kasten000f0e32012-03-01 17:10:56 -08002583
Glenn Kastenfa26a852012-03-06 11:28:04 -08002584 // FIXME I don't understand the need for this here;
2585 // it was in the original code but maybe the
2586 // assignment in saveOutputTracks() makes this unnecessary?
2587 clearOutputTracks();
Glenn Kasten000f0e32012-03-01 17:10:56 -08002588
2589 // Effect chains will be actually deleted here if they were removed from
2590 // mEffectChains list during mixing or effects processing
2591 effectChains.clear();
2592
2593 // FIXME Note that the above .clear() is no longer necessary since effectChains
2594 // is now local to this block, but will keep it for now (at least until merge done).
2595 }
2596
2597if (mType == MIXER || mType == DIRECT) {
2598 // put output stream into standby mode
2599 if (!mStandby) {
2600 mOutput->stream->common.standby(&mOutput->stream->common);
2601 }
2602}
2603if (mType == DUPLICATING) {
2604 // for DuplicatingThread, standby mode is handled by the outputTracks
2605}
2606
2607 releaseWakeLock();
2608
2609 ALOGV("Thread %p type %d exiting", this, mType);
2610 return false;
2611}
2612
Glenn Kasten58912562012-04-03 10:45:00 -07002613void AudioFlinger::MixerThread::threadLoop_removeTracks(const Vector< sp<Track> >& tracksToRemove)
2614{
Glenn Kasten58912562012-04-03 10:45:00 -07002615 PlaybackThread::threadLoop_removeTracks(tracksToRemove);
2616}
2617
2618void AudioFlinger::MixerThread::threadLoop_write()
2619{
2620 // FIXME we should only do one push per cycle; confirm this is true
2621 // Start the fast mixer if it's not already running
2622 if (mFastMixer != NULL) {
2623 FastMixerStateQueue *sq = mFastMixer->sq();
2624 FastMixerState *state = sq->begin();
Glenn Kasten300a2ee2012-04-25 13:47:36 -07002625 if (state->mCommand != FastMixerState::MIX_WRITE &&
2626 (kUseFastMixer != FastMixer_Dynamic || state->mTrackMask > 1)) {
Glenn Kasten58912562012-04-03 10:45:00 -07002627 if (state->mCommand == FastMixerState::COLD_IDLE) {
2628 int32_t old = android_atomic_inc(&mFastMixerFutex);
2629 if (old == -1) {
2630 __futex_syscall3(&mFastMixerFutex, FUTEX_WAKE_PRIVATE, 1);
2631 }
2632 }
2633 state->mCommand = FastMixerState::MIX_WRITE;
2634 sq->end();
2635 sq->push(FastMixerStateQueue::BLOCK_UNTIL_PUSHED);
Glenn Kasten300a2ee2012-04-25 13:47:36 -07002636 if (kUseFastMixer == FastMixer_Dynamic) {
2637 mNormalSink = mPipeSink;
2638 }
Glenn Kasten58912562012-04-03 10:45:00 -07002639 } else {
2640 sq->end(false /*didModify*/);
2641 }
2642 }
2643 PlaybackThread::threadLoop_write();
2644}
2645
Glenn Kasten000f0e32012-03-01 17:10:56 -08002646// shared by MIXER and DIRECT, overridden by DUPLICATING
2647void AudioFlinger::PlaybackThread::threadLoop_write()
2648{
Glenn Kasten952eeb22012-03-06 11:30:57 -08002649 // FIXME rewrite to reduce number of system calls
2650 mLastWriteTime = systemTime();
2651 mInWrite = true;
Glenn Kasten58912562012-04-03 10:45:00 -07002652
Glenn Kasten58912562012-04-03 10:45:00 -07002653#define mBitShift 2 // FIXME
Glenn Kasten300a2ee2012-04-25 13:47:36 -07002654 size_t count = mixBufferSize >> mBitShift;
Glenn Kasten99c99d02012-05-14 16:37:13 -07002655#if defined(ATRACE_TAG) && (ATRACE_TAG != ATRACE_TAG_NEVER)
Glenn Kastend8e6fd32012-05-07 11:07:57 -07002656 Tracer::traceBegin(ATRACE_TAG, "write");
Glenn Kasten99c99d02012-05-14 16:37:13 -07002657#endif
Glenn Kasten300a2ee2012-04-25 13:47:36 -07002658 ssize_t framesWritten = mNormalSink->write(mMixBuffer, count);
Glenn Kasten99c99d02012-05-14 16:37:13 -07002659#if defined(ATRACE_TAG) && (ATRACE_TAG != ATRACE_TAG_NEVER)
Glenn Kastend8e6fd32012-05-07 11:07:57 -07002660 Tracer::traceEnd(ATRACE_TAG);
Glenn Kasten99c99d02012-05-14 16:37:13 -07002661#endif
Glenn Kasten300a2ee2012-04-25 13:47:36 -07002662 if (framesWritten > 0) {
2663 size_t bytesWritten = framesWritten << mBitShift;
2664 mBytesWritten += bytesWritten;
Glenn Kasten58912562012-04-03 10:45:00 -07002665 }
2666
Glenn Kasten952eeb22012-03-06 11:30:57 -08002667 mNumWrites++;
2668 mInWrite = false;
Glenn Kasten000f0e32012-03-01 17:10:56 -08002669}
2670
Glenn Kasten58912562012-04-03 10:45:00 -07002671void AudioFlinger::MixerThread::threadLoop_standby()
2672{
2673 // Idle the fast mixer if it's currently running
2674 if (mFastMixer != NULL) {
2675 FastMixerStateQueue *sq = mFastMixer->sq();
2676 FastMixerState *state = sq->begin();
2677 if (!(state->mCommand & FastMixerState::IDLE)) {
2678 state->mCommand = FastMixerState::COLD_IDLE;
2679 state->mColdFutexAddr = &mFastMixerFutex;
2680 state->mColdGen++;
2681 mFastMixerFutex = 0;
2682 sq->end();
2683 // BLOCK_UNTIL_PUSHED would be insufficient, as we need it to stop doing I/O now
2684 sq->push(FastMixerStateQueue::BLOCK_UNTIL_ACKED);
Glenn Kasten300a2ee2012-04-25 13:47:36 -07002685 if (kUseFastMixer == FastMixer_Dynamic) {
2686 mNormalSink = mOutputSink;
2687 }
Glenn Kasten58912562012-04-03 10:45:00 -07002688 } else {
2689 sq->end(false /*didModify*/);
2690 }
2691 }
2692 PlaybackThread::threadLoop_standby();
2693}
2694
Glenn Kasten000f0e32012-03-01 17:10:56 -08002695// shared by MIXER and DIRECT, overridden by DUPLICATING
2696void AudioFlinger::PlaybackThread::threadLoop_standby()
2697{
Glenn Kasten952eeb22012-03-06 11:30:57 -08002698 ALOGV("Audio hardware entering standby, mixer %p, suspend count %u", this, mSuspended);
2699 mOutput->stream->common.standby(&mOutput->stream->common);
Glenn Kasten000f0e32012-03-01 17:10:56 -08002700}
2701
2702void AudioFlinger::MixerThread::threadLoop_mix()
2703{
Glenn Kasten952eeb22012-03-06 11:30:57 -08002704 // obtain the presentation timestamp of the next output buffer
2705 int64_t pts;
2706 status_t status = INVALID_OPERATION;
John Grossman4ff14ba2012-02-08 16:37:41 -08002707
Glenn Kasten952eeb22012-03-06 11:30:57 -08002708 if (NULL != mOutput->stream->get_next_write_timestamp) {
2709 status = mOutput->stream->get_next_write_timestamp(
2710 mOutput->stream, &pts);
2711 }
John Grossman4ff14ba2012-02-08 16:37:41 -08002712
Glenn Kasten952eeb22012-03-06 11:30:57 -08002713 if (status != NO_ERROR) {
2714 pts = AudioBufferProvider::kInvalidPTS;
2715 }
John Grossman4ff14ba2012-02-08 16:37:41 -08002716
Glenn Kasten952eeb22012-03-06 11:30:57 -08002717 // mix buffers...
2718 mAudioMixer->process(pts);
2719 // increase sleep time progressively when application underrun condition clears.
2720 // Only increase sleep time if the mixer is ready for two consecutive times to avoid
2721 // that a steady state of alternating ready/not ready conditions keeps the sleep time
2722 // such that we would underrun the audio HAL.
2723 if ((sleepTime == 0) && (sleepTimeShift > 0)) {
2724 sleepTimeShift--;
2725 }
2726 sleepTime = 0;
Glenn Kasten66fcab92012-02-24 14:59:21 -08002727 standbyTime = systemTime() + standbyDelay;
Glenn Kasten952eeb22012-03-06 11:30:57 -08002728 //TODO: delay standby when effects have a tail
Glenn Kasten000f0e32012-03-01 17:10:56 -08002729}
2730
2731void AudioFlinger::MixerThread::threadLoop_sleepTime()
2732{
Glenn Kasten952eeb22012-03-06 11:30:57 -08002733 // If no tracks are ready, sleep once for the duration of an output
2734 // buffer size, then write 0s to the output
2735 if (sleepTime == 0) {
Glenn Kastenfec279f2012-03-08 07:47:15 -08002736 if (mMixerStatus == MIXER_TRACKS_ENABLED) {
Glenn Kasten952eeb22012-03-06 11:30:57 -08002737 sleepTime = activeSleepTime >> sleepTimeShift;
2738 if (sleepTime < kMinThreadSleepTimeUs) {
2739 sleepTime = kMinThreadSleepTimeUs;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002740 }
Glenn Kasten952eeb22012-03-06 11:30:57 -08002741 // reduce sleep time in case of consecutive application underruns to avoid
2742 // starving the audio HAL. As activeSleepTimeUs() is larger than a buffer
2743 // duration we would end up writing less data than needed by the audio HAL if
2744 // the condition persists.
2745 if (sleepTimeShift < kMaxThreadSleepTimeShift) {
2746 sleepTimeShift++;
2747 }
2748 } else {
2749 sleepTime = idleSleepTime;
2750 }
2751 } else if (mBytesWritten != 0 ||
Glenn Kastenfec279f2012-03-08 07:47:15 -08002752 (mMixerStatus == MIXER_TRACKS_ENABLED && longStandbyExit)) {
Glenn Kasten952eeb22012-03-06 11:30:57 -08002753 memset (mMixBuffer, 0, mixBufferSize);
2754 sleepTime = 0;
Glenn Kastenfec279f2012-03-08 07:47:15 -08002755 ALOGV_IF((mBytesWritten == 0 && (mMixerStatus == MIXER_TRACKS_ENABLED && longStandbyExit)), "anticipated start");
Glenn Kasten952eeb22012-03-06 11:30:57 -08002756 }
2757 // TODO add standby time extension fct of effect tail
Mathias Agopian65ab4712010-07-14 17:59:35 -07002758}
2759
2760// prepareTracks_l() must be called with ThreadBase::mLock held
Glenn Kasten29c23c32012-01-26 13:37:52 -08002761AudioFlinger::PlaybackThread::mixer_state AudioFlinger::MixerThread::prepareTracks_l(
Glenn Kasten3e074702012-02-28 18:40:35 -08002762 Vector< sp<Track> > *tracksToRemove)
Mathias Agopian65ab4712010-07-14 17:59:35 -07002763{
2764
Glenn Kasten29c23c32012-01-26 13:37:52 -08002765 mixer_state mixerStatus = MIXER_IDLE;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002766 // find out which tracks need to be processed
Glenn Kasten3e074702012-02-28 18:40:35 -08002767 size_t count = mActiveTracks.size();
Mathias Agopian65ab4712010-07-14 17:59:35 -07002768 size_t mixedTracks = 0;
2769 size_t tracksWithEffect = 0;
Glenn Kasten288ed212012-04-25 17:52:27 -07002770 // counts only _active_ fast tracks
Glenn Kasten58912562012-04-03 10:45:00 -07002771 size_t fastTracks = 0;
Glenn Kasten288ed212012-04-25 17:52:27 -07002772 uint32_t resetMask = 0; // bit mask of fast tracks that need to be reset
Mathias Agopian65ab4712010-07-14 17:59:35 -07002773
2774 float masterVolume = mMasterVolume;
Glenn Kastenea7939a2012-03-14 12:56:26 -07002775 bool masterMute = mMasterMute;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002776
Eric Laurent571d49c2010-08-11 05:20:11 -07002777 if (masterMute) {
2778 masterVolume = 0;
2779 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07002780 // Delegate master volume control to effect in output mix effect chain if needed
Dima Zavinfce7a472011-04-19 22:30:36 -07002781 sp<EffectChain> chain = getEffectChain_l(AUDIO_SESSION_OUTPUT_MIX);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002782 if (chain != 0) {
Eric Laurent571d49c2010-08-11 05:20:11 -07002783 uint32_t v = (uint32_t)(masterVolume * (1 << 24));
Eric Laurentcab11242010-07-15 12:50:15 -07002784 chain->setVolume_l(&v, &v);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002785 masterVolume = (float)((v + (1 << 23)) >> 24);
2786 chain.clear();
2787 }
2788
Glenn Kasten288ed212012-04-25 17:52:27 -07002789 // prepare a new state to push
2790 FastMixerStateQueue *sq = NULL;
2791 FastMixerState *state = NULL;
2792 bool didModify = false;
2793 FastMixerStateQueue::block_t block = FastMixerStateQueue::BLOCK_UNTIL_PUSHED;
2794 if (mFastMixer != NULL) {
2795 sq = mFastMixer->sq();
2796 state = sq->begin();
2797 }
2798
Mathias Agopian65ab4712010-07-14 17:59:35 -07002799 for (size_t i=0 ; i<count ; i++) {
Glenn Kasten3e074702012-02-28 18:40:35 -08002800 sp<Track> t = mActiveTracks[i].promote();
Mathias Agopian65ab4712010-07-14 17:59:35 -07002801 if (t == 0) continue;
2802
Glenn Kasten9c56d4a2011-12-19 15:06:39 -08002803 // this const just means the local variable doesn't change
Mathias Agopian65ab4712010-07-14 17:59:35 -07002804 Track* const track = t.get();
Glenn Kasten58912562012-04-03 10:45:00 -07002805
Glenn Kasten288ed212012-04-25 17:52:27 -07002806 // process fast tracks
Glenn Kasten58912562012-04-03 10:45:00 -07002807 if (track->isFastTrack()) {
Glenn Kasten288ed212012-04-25 17:52:27 -07002808
2809 // It's theoretically possible (though unlikely) for a fast track to be created
2810 // and then removed within the same normal mix cycle. This is not a problem, as
2811 // the track never becomes active so it's fast mixer slot is never touched.
2812 // The converse, of removing an (active) track and then creating a new track
2813 // at the identical fast mixer slot within the same normal mix cycle,
2814 // is impossible because the slot isn't marked available until the end of each cycle.
2815 int j = track->mFastIndex;
2816 FastTrack *fastTrack = &state->mFastTracks[j];
2817
2818 // Determine whether the track is currently in underrun condition,
2819 // and whether it had a recent underrun.
Glenn Kasten09474df2012-05-10 14:48:07 -07002820 FastTrackUnderruns underruns = mFastMixerDumpState.mTracks[j].mUnderruns;
2821 uint32_t recentFull = (underruns.mBitFields.mFull -
2822 track->mObservedUnderruns.mBitFields.mFull) & UNDERRUN_MASK;
2823 uint32_t recentPartial = (underruns.mBitFields.mPartial -
2824 track->mObservedUnderruns.mBitFields.mPartial) & UNDERRUN_MASK;
2825 uint32_t recentEmpty = (underruns.mBitFields.mEmpty -
2826 track->mObservedUnderruns.mBitFields.mEmpty) & UNDERRUN_MASK;
2827 uint32_t recentUnderruns = recentPartial + recentEmpty;
2828 track->mObservedUnderruns = underruns;
Glenn Kasten288ed212012-04-25 17:52:27 -07002829 // don't count underruns that occur while stopping or pausing
Glenn Kastend08f48c2012-05-01 18:14:02 -07002830 // or stopped which can occur when flush() is called while active
2831 if (!(track->isStopping() || track->isPausing() || track->isStopped())) {
Glenn Kasten288ed212012-04-25 17:52:27 -07002832 track->mUnderrunCount += recentUnderruns;
2833 }
Glenn Kasten288ed212012-04-25 17:52:27 -07002834
Glenn Kastend08f48c2012-05-01 18:14:02 -07002835 // This is similar to the state machine for normal tracks,
Glenn Kasten288ed212012-04-25 17:52:27 -07002836 // with a few modifications for fast tracks.
Glenn Kastend08f48c2012-05-01 18:14:02 -07002837 bool isActive = true;
2838 switch (track->mState) {
2839 case TrackBase::STOPPING_1:
2840 // track stays active in STOPPING_1 state until first underrun
2841 if (recentUnderruns > 0) {
2842 track->mState = TrackBase::STOPPING_2;
2843 }
2844 break;
2845 case TrackBase::PAUSING:
Glenn Kasten288ed212012-04-25 17:52:27 -07002846 // ramp down is not yet implemented
Glenn Kasten288ed212012-04-25 17:52:27 -07002847 track->setPaused();
Glenn Kastend08f48c2012-05-01 18:14:02 -07002848 break;
2849 case TrackBase::RESUMING:
Glenn Kasten288ed212012-04-25 17:52:27 -07002850 // ramp up is not yet implemented
Glenn Kasten288ed212012-04-25 17:52:27 -07002851 track->mState = TrackBase::ACTIVE;
Glenn Kastend08f48c2012-05-01 18:14:02 -07002852 break;
2853 case TrackBase::ACTIVE:
Glenn Kasten09474df2012-05-10 14:48:07 -07002854 if (recentFull > 0 || recentPartial > 0) {
2855 // track has provided at least some frames recently: reset retry count
2856 track->mRetryCount = kMaxTrackRetries;
2857 }
2858 if (recentUnderruns == 0) {
2859 // no recent underruns: stay active
2860 break;
2861 }
2862 // there has recently been an underrun of some kind
2863 if (track->sharedBuffer() == 0) {
2864 // were any of the recent underruns "empty" (no frames available)?
2865 if (recentEmpty == 0) {
2866 // no, then ignore the partial underruns as they are allowed indefinitely
2867 break;
2868 }
2869 // there has recently been an "empty" underrun: decrement the retry counter
2870 if (--(track->mRetryCount) > 0) {
2871 break;
2872 }
2873 // indicate to client process that the track was disabled because of underrun;
2874 // it will then automatically call start() when data is available
2875 android_atomic_or(CBLK_DISABLED_ON, &track->mCblk->flags);
2876 // remove from active list, but state remains ACTIVE [confusing but true]
2877 isActive = false;
Glenn Kastend08f48c2012-05-01 18:14:02 -07002878 break;
2879 }
2880 // fall through
2881 case TrackBase::STOPPING_2:
2882 case TrackBase::PAUSED:
2883 case TrackBase::TERMINATED:
Eric Laurent29864602012-05-08 18:57:51 -07002884 case TrackBase::STOPPED:
2885 case TrackBase::FLUSHED: // flush() while active
Glenn Kastend08f48c2012-05-01 18:14:02 -07002886 // Check for presentation complete if track is inactive
2887 // We have consumed all the buffers of this track.
2888 // This would be incomplete if we auto-paused on underrun
2889 {
2890 size_t audioHALFrames =
2891 (mOutput->stream->get_latency(mOutput->stream)*mSampleRate) / 1000;
2892 size_t framesWritten =
2893 mBytesWritten / audio_stream_frame_size(&mOutput->stream->common);
2894 if (!track->presentationComplete(framesWritten, audioHALFrames)) {
2895 // track stays in active list until presentation is complete
2896 break;
2897 }
2898 }
2899 if (track->isStopping_2()) {
2900 track->mState = TrackBase::STOPPED;
2901 }
2902 if (track->isStopped()) {
2903 // Can't reset directly, as fast mixer is still polling this track
2904 // track->reset();
2905 // So instead mark this track as needing to be reset after push with ack
2906 resetMask |= 1 << i;
2907 }
2908 isActive = false;
2909 break;
2910 case TrackBase::IDLE:
2911 default:
2912 LOG_FATAL("unexpected track state %d", track->mState);
Glenn Kasten288ed212012-04-25 17:52:27 -07002913 }
2914
2915 if (isActive) {
2916 // was it previously inactive?
2917 if (!(state->mTrackMask & (1 << j))) {
2918 ExtendedAudioBufferProvider *eabp = track;
2919 VolumeProvider *vp = track;
2920 fastTrack->mBufferProvider = eabp;
2921 fastTrack->mVolumeProvider = vp;
2922 fastTrack->mSampleRate = track->mSampleRate;
2923 fastTrack->mChannelMask = track->mChannelMask;
2924 fastTrack->mGeneration++;
2925 state->mTrackMask |= 1 << j;
2926 didModify = true;
2927 // no acknowledgement required for newly active tracks
2928 }
2929 // cache the combined master volume and stream type volume for fast mixer; this
2930 // lacks any synchronization or barrier so VolumeProvider may read a stale value
2931 track->mCachedVolume = track->isMuted() ?
2932 0 : masterVolume * mStreamTypes[track->streamType()].volume;
2933 ++fastTracks;
2934 } else {
2935 // was it previously active?
2936 if (state->mTrackMask & (1 << j)) {
2937 fastTrack->mBufferProvider = NULL;
2938 fastTrack->mGeneration++;
2939 state->mTrackMask &= ~(1 << j);
2940 didModify = true;
2941 // If any fast tracks were removed, we must wait for acknowledgement
2942 // because we're about to decrement the last sp<> on those tracks.
2943 block = FastMixerStateQueue::BLOCK_UNTIL_ACKED;
Glenn Kastend08f48c2012-05-01 18:14:02 -07002944 } else {
2945 LOG_FATAL("fast track %d should have been active", j);
Glenn Kasten288ed212012-04-25 17:52:27 -07002946 }
Glenn Kastend08f48c2012-05-01 18:14:02 -07002947 tracksToRemove->add(track);
Glenn Kasten288ed212012-04-25 17:52:27 -07002948 // Avoids a misleading display in dumpsys
Glenn Kasten09474df2012-05-10 14:48:07 -07002949 track->mObservedUnderruns.mBitFields.mMostRecent = UNDERRUN_FULL;
Glenn Kasten58912562012-04-03 10:45:00 -07002950 }
2951 continue;
2952 }
2953
2954 { // local variable scope to avoid goto warning
2955
Mathias Agopian65ab4712010-07-14 17:59:35 -07002956 audio_track_cblk_t* cblk = track->cblk();
2957
2958 // The first time a track is added we wait
2959 // for all its buffers to be filled before processing it
Glenn Kasten9c56d4a2011-12-19 15:06:39 -08002960 int name = track->name();
Eric Laurenta47b69c2011-11-08 18:10:16 -08002961 // make sure that we have enough frames to mix one full buffer.
2962 // enforce this condition only once to enable draining the buffer in case the client
2963 // app does not call stop() and relies on underrun to stop:
Eric Laurentda747442012-04-25 18:53:13 -07002964 // hence the test on (mMixerStatus == MIXER_TRACKS_READY) meaning the track was mixed
Eric Laurenta47b69c2011-11-08 18:10:16 -08002965 // during last round
Eric Laurent3dbe3202011-11-03 12:16:05 -07002966 uint32_t minFrames = 1;
Eric Laurent83faee02012-04-27 18:24:29 -07002967 if ((track->sharedBuffer() == 0) && !track->isStopped() && !track->isPausing() &&
Glenn Kasten81028042012-04-30 18:15:12 -07002968 (mMixerStatusIgnoringFastTracks == MIXER_TRACKS_READY)) {
Eric Laurent3dbe3202011-11-03 12:16:05 -07002969 if (t->sampleRate() == (int)mSampleRate) {
Glenn Kasten58912562012-04-03 10:45:00 -07002970 minFrames = mNormalFrameCount;
Eric Laurent3dbe3202011-11-03 12:16:05 -07002971 } else {
Eric Laurent071ccd52011-12-22 16:08:41 -08002972 // +1 for rounding and +1 for additional sample needed for interpolation
Glenn Kasten58912562012-04-03 10:45:00 -07002973 minFrames = (mNormalFrameCount * t->sampleRate()) / mSampleRate + 1 + 1;
Eric Laurent071ccd52011-12-22 16:08:41 -08002974 // add frames already consumed but not yet released by the resampler
Glenn Kastenea7939a2012-03-14 12:56:26 -07002975 // because cblk->framesReady() will include these frames
Eric Laurent071ccd52011-12-22 16:08:41 -08002976 minFrames += mAudioMixer->getUnreleasedFrames(track->name());
2977 // the minimum track buffer size is normally twice the number of frames necessary
2978 // to fill one buffer and the resampler should not leave more than one buffer worth
2979 // of unreleased frames after each pass, but just in case...
Steve Blockc1dc1cb2012-01-09 18:35:44 +00002980 ALOG_ASSERT(minFrames <= cblk->frameCount);
Eric Laurent3dbe3202011-11-03 12:16:05 -07002981 }
2982 }
John Grossman4ff14ba2012-02-08 16:37:41 -08002983 if ((track->framesReady() >= minFrames) && track->isReady() &&
Mathias Agopian65ab4712010-07-14 17:59:35 -07002984 !track->isPaused() && !track->isTerminated())
2985 {
Glenn Kasten9c56d4a2011-12-19 15:06:39 -08002986 //ALOGV("track %d u=%08x, s=%08x [OK] on thread %p", name, cblk->user, cblk->server, this);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002987
2988 mixedTracks++;
2989
2990 // track->mainBuffer() != mMixBuffer means there is an effect chain
2991 // connected to the track
2992 chain.clear();
2993 if (track->mainBuffer() != mMixBuffer) {
2994 chain = getEffectChain_l(track->sessionId());
2995 // Delegate volume control to effect in track effect chain if needed
2996 if (chain != 0) {
2997 tracksWithEffect++;
2998 } else {
Steve Block5ff1dd52012-01-05 23:22:43 +00002999 ALOGW("prepareTracks_l(): track %d attached to effect but no chain found on session %d",
Glenn Kasten9c56d4a2011-12-19 15:06:39 -08003000 name, track->sessionId());
Mathias Agopian65ab4712010-07-14 17:59:35 -07003001 }
3002 }
3003
3004
3005 int param = AudioMixer::VOLUME;
3006 if (track->mFillingUpStatus == Track::FS_FILLED) {
3007 // no ramp for the first volume setting
3008 track->mFillingUpStatus = Track::FS_ACTIVE;
3009 if (track->mState == TrackBase::RESUMING) {
3010 track->mState = TrackBase::ACTIVE;
3011 param = AudioMixer::RAMP_VOLUME;
3012 }
Glenn Kasten9c56d4a2011-12-19 15:06:39 -08003013 mAudioMixer->setParameter(name, AudioMixer::RESAMPLE, AudioMixer::RESET, NULL);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003014 } else if (cblk->server != 0) {
3015 // If the track is stopped before the first frame was mixed,
3016 // do not apply ramp
3017 param = AudioMixer::RAMP_VOLUME;
3018 }
3019
3020 // compute volume for this track
Eric Laurente0aed6d2010-09-10 17:44:44 -07003021 uint32_t vl, vr, va;
Eric Laurent8569f0d2010-07-29 23:43:43 -07003022 if (track->isMuted() || track->isPausing() ||
Glenn Kasten02bbd202012-02-08 12:35:35 -08003023 mStreamTypes[track->streamType()].mute) {
Eric Laurente0aed6d2010-09-10 17:44:44 -07003024 vl = vr = va = 0;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003025 if (track->isPausing()) {
3026 track->setPaused();
3027 }
3028 } else {
Eric Laurente0aed6d2010-09-10 17:44:44 -07003029
Mathias Agopian65ab4712010-07-14 17:59:35 -07003030 // read original volumes with volume control
Glenn Kasten02bbd202012-02-08 12:35:35 -08003031 float typeVolume = mStreamTypes[track->streamType()].volume;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003032 float v = masterVolume * typeVolume;
Glenn Kasten83d86532012-01-17 14:39:34 -08003033 uint32_t vlr = cblk->getVolumeLR();
Glenn Kastenb1cf75c2012-01-17 12:20:54 -08003034 vl = vlr & 0xFFFF;
3035 vr = vlr >> 16;
3036 // track volumes come from shared memory, so can't be trusted and must be clamped
3037 if (vl > MAX_GAIN_INT) {
3038 ALOGV("Track left volume out of range: %04X", vl);
3039 vl = MAX_GAIN_INT;
3040 }
3041 if (vr > MAX_GAIN_INT) {
3042 ALOGV("Track right volume out of range: %04X", vr);
3043 vr = MAX_GAIN_INT;
3044 }
3045 // now apply the master volume and stream type volume
3046 vl = (uint32_t)(v * vl) << 12;
3047 vr = (uint32_t)(v * vr) << 12;
3048 // assuming master volume and stream type volume each go up to 1.0,
3049 // vl and vr are now in 8.24 format
Mathias Agopian65ab4712010-07-14 17:59:35 -07003050
Glenn Kasten05632a52012-01-03 14:22:33 -08003051 uint16_t sendLevel = cblk->getSendLevel_U4_12();
3052 // send level comes from shared memory and so may be corrupt
Glenn Kasten3b81aca2012-01-27 15:26:23 -08003053 if (sendLevel > MAX_GAIN_INT) {
Glenn Kasten05632a52012-01-03 14:22:33 -08003054 ALOGV("Track send level out of range: %04X", sendLevel);
Glenn Kastenb1cf75c2012-01-17 12:20:54 -08003055 sendLevel = MAX_GAIN_INT;
Glenn Kasten05632a52012-01-03 14:22:33 -08003056 }
3057 va = (uint32_t)(v * sendLevel);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003058 }
Eric Laurente0aed6d2010-09-10 17:44:44 -07003059 // Delegate volume control to effect in track effect chain if needed
3060 if (chain != 0 && chain->setVolume_l(&vl, &vr)) {
3061 // Do not ramp volume if volume is controlled by effect
3062 param = AudioMixer::VOLUME;
3063 track->mHasVolumeController = true;
3064 } else {
3065 // force no volume ramp when volume controller was just disabled or removed
3066 // from effect chain to avoid volume spike
3067 if (track->mHasVolumeController) {
3068 param = AudioMixer::VOLUME;
3069 }
3070 track->mHasVolumeController = false;
3071 }
3072
3073 // Convert volumes from 8.24 to 4.12 format
Glenn Kastenb1cf75c2012-01-17 12:20:54 -08003074 // This additional clamping is needed in case chain->setVolume_l() overshot
Glenn Kasten3b81aca2012-01-27 15:26:23 -08003075 vl = (vl + (1 << 11)) >> 12;
3076 if (vl > MAX_GAIN_INT) vl = MAX_GAIN_INT;
3077 vr = (vr + (1 << 11)) >> 12;
3078 if (vr > MAX_GAIN_INT) vr = MAX_GAIN_INT;
Eric Laurente0aed6d2010-09-10 17:44:44 -07003079
Glenn Kasten3b81aca2012-01-27 15:26:23 -08003080 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 -07003081
Mathias Agopian65ab4712010-07-14 17:59:35 -07003082 // XXX: these things DON'T need to be done each time
Glenn Kasten9c56d4a2011-12-19 15:06:39 -08003083 mAudioMixer->setBufferProvider(name, track);
3084 mAudioMixer->enable(name);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003085
Glenn Kasten3b81aca2012-01-27 15:26:23 -08003086 mAudioMixer->setParameter(name, param, AudioMixer::VOLUME0, (void *)vl);
3087 mAudioMixer->setParameter(name, param, AudioMixer::VOLUME1, (void *)vr);
3088 mAudioMixer->setParameter(name, param, AudioMixer::AUXLEVEL, (void *)va);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003089 mAudioMixer->setParameter(
Glenn Kasten9c56d4a2011-12-19 15:06:39 -08003090 name,
Mathias Agopian65ab4712010-07-14 17:59:35 -07003091 AudioMixer::TRACK,
3092 AudioMixer::FORMAT, (void *)track->format());
3093 mAudioMixer->setParameter(
Glenn Kasten9c56d4a2011-12-19 15:06:39 -08003094 name,
Mathias Agopian65ab4712010-07-14 17:59:35 -07003095 AudioMixer::TRACK,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07003096 AudioMixer::CHANNEL_MASK, (void *)track->channelMask());
Mathias Agopian65ab4712010-07-14 17:59:35 -07003097 mAudioMixer->setParameter(
Glenn Kasten9c56d4a2011-12-19 15:06:39 -08003098 name,
Mathias Agopian65ab4712010-07-14 17:59:35 -07003099 AudioMixer::RESAMPLE,
3100 AudioMixer::SAMPLE_RATE,
3101 (void *)(cblk->sampleRate));
3102 mAudioMixer->setParameter(
Glenn Kasten9c56d4a2011-12-19 15:06:39 -08003103 name,
Mathias Agopian65ab4712010-07-14 17:59:35 -07003104 AudioMixer::TRACK,
3105 AudioMixer::MAIN_BUFFER, (void *)track->mainBuffer());
3106 mAudioMixer->setParameter(
Glenn Kasten9c56d4a2011-12-19 15:06:39 -08003107 name,
Mathias Agopian65ab4712010-07-14 17:59:35 -07003108 AudioMixer::TRACK,
3109 AudioMixer::AUX_BUFFER, (void *)track->auxBuffer());
3110
3111 // reset retry count
3112 track->mRetryCount = kMaxTrackRetries;
Glenn Kastenea7939a2012-03-14 12:56:26 -07003113
Eric Laurent27741442012-01-17 19:20:12 -08003114 // If one track is ready, set the mixer ready if:
3115 // - the mixer was not ready during previous round OR
3116 // - no other track is not ready
Glenn Kasten81028042012-04-30 18:15:12 -07003117 if (mMixerStatusIgnoringFastTracks != MIXER_TRACKS_READY ||
Eric Laurent27741442012-01-17 19:20:12 -08003118 mixerStatus != MIXER_TRACKS_ENABLED) {
3119 mixerStatus = MIXER_TRACKS_READY;
3120 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07003121 } else {
Glenn Kasten9c56d4a2011-12-19 15:06:39 -08003122 //ALOGV("track %d u=%08x, s=%08x [NOT READY] on thread %p", name, cblk->user, cblk->server, this);
Eric Laurent83faee02012-04-27 18:24:29 -07003123 if ((track->sharedBuffer() != 0) || track->isTerminated() ||
3124 track->isStopped() || track->isPaused()) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07003125 // We have consumed all the buffers of this track.
3126 // Remove it from the list of active tracks.
Eric Laurenta011e352012-03-29 15:51:43 -07003127 // TODO: use actual buffer filling status instead of latency when available from
3128 // audio HAL
3129 size_t audioHALFrames =
3130 (mOutput->stream->get_latency(mOutput->stream)*mSampleRate) / 1000;
3131 size_t framesWritten =
3132 mBytesWritten / audio_stream_frame_size(&mOutput->stream->common);
3133 if (track->presentationComplete(framesWritten, audioHALFrames)) {
Eric Laurent29864602012-05-08 18:57:51 -07003134 if (track->isStopped()) {
3135 track->reset();
3136 }
Eric Laurenta011e352012-03-29 15:51:43 -07003137 tracksToRemove->add(track);
3138 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07003139 } else {
3140 // No buffers for this track. Give it a few chances to
3141 // fill a buffer, then remove it from active list.
3142 if (--(track->mRetryCount) <= 0) {
Glenn Kasten9c56d4a2011-12-19 15:06:39 -08003143 ALOGV("BUFFER TIMEOUT: remove(%d) from active list on thread %p", name, this);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003144 tracksToRemove->add(track);
Glenn Kasten288ed212012-04-25 17:52:27 -07003145 // indicate to client process that the track was disabled because of underrun;
3146 // it will then automatically call start() when data is available
Eric Laurent38ccae22011-03-28 18:37:07 -07003147 android_atomic_or(CBLK_DISABLED_ON, &cblk->flags);
Eric Laurent27741442012-01-17 19:20:12 -08003148 // If one track is not ready, mark the mixer also not ready if:
3149 // - the mixer was ready during previous round OR
3150 // - no other track is ready
Glenn Kasten81028042012-04-30 18:15:12 -07003151 } else if (mMixerStatusIgnoringFastTracks == MIXER_TRACKS_READY ||
Eric Laurent27741442012-01-17 19:20:12 -08003152 mixerStatus != MIXER_TRACKS_READY) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07003153 mixerStatus = MIXER_TRACKS_ENABLED;
3154 }
3155 }
Glenn Kasten9c56d4a2011-12-19 15:06:39 -08003156 mAudioMixer->disable(name);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003157 }
Glenn Kasten58912562012-04-03 10:45:00 -07003158
3159 } // local variable scope to avoid goto warning
3160track_is_ready: ;
3161
Mathias Agopian65ab4712010-07-14 17:59:35 -07003162 }
3163
Glenn Kasten288ed212012-04-25 17:52:27 -07003164 // Push the new FastMixer state if necessary
3165 if (didModify) {
3166 state->mFastTracksGen++;
3167 // if the fast mixer was active, but now there are no fast tracks, then put it in cold idle
3168 if (kUseFastMixer == FastMixer_Dynamic &&
3169 state->mCommand == FastMixerState::MIX_WRITE && state->mTrackMask <= 1) {
3170 state->mCommand = FastMixerState::COLD_IDLE;
3171 state->mColdFutexAddr = &mFastMixerFutex;
3172 state->mColdGen++;
3173 mFastMixerFutex = 0;
3174 if (kUseFastMixer == FastMixer_Dynamic) {
3175 mNormalSink = mOutputSink;
3176 }
3177 // If we go into cold idle, need to wait for acknowledgement
3178 // so that fast mixer stops doing I/O.
3179 block = FastMixerStateQueue::BLOCK_UNTIL_ACKED;
3180 }
3181 sq->end();
3182 }
3183 if (sq != NULL) {
3184 sq->end(didModify);
3185 sq->push(block);
3186 }
3187
3188 // Now perform the deferred reset on fast tracks that have stopped
3189 while (resetMask != 0) {
3190 size_t i = __builtin_ctz(resetMask);
3191 ALOG_ASSERT(i < count);
3192 resetMask &= ~(1 << i);
3193 sp<Track> t = mActiveTracks[i].promote();
3194 if (t == 0) continue;
3195 Track* track = t.get();
3196 ALOG_ASSERT(track->isFastTrack() && track->isStopped());
3197 track->reset();
3198 }
Glenn Kasten58912562012-04-03 10:45:00 -07003199
Mathias Agopian65ab4712010-07-14 17:59:35 -07003200 // remove all the tracks that need to be...
3201 count = tracksToRemove->size();
Glenn Kastenf6b16782011-12-15 09:51:17 -08003202 if (CC_UNLIKELY(count)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07003203 for (size_t i=0 ; i<count ; i++) {
3204 const sp<Track>& track = tracksToRemove->itemAt(i);
3205 mActiveTracks.remove(track);
3206 if (track->mainBuffer() != mMixBuffer) {
3207 chain = getEffectChain_l(track->sessionId());
3208 if (chain != 0) {
Steve Block3856b092011-10-20 11:56:00 +01003209 ALOGV("stopping track on chain %p for session Id: %d", chain.get(), track->sessionId());
Eric Laurentb469b942011-05-09 12:09:06 -07003210 chain->decActiveTrackCnt();
Mathias Agopian65ab4712010-07-14 17:59:35 -07003211 }
3212 }
3213 if (track->isTerminated()) {
Eric Laurentb469b942011-05-09 12:09:06 -07003214 removeTrack_l(track);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003215 }
3216 }
3217 }
3218
3219 // mix buffer must be cleared if all tracks are connected to an
3220 // effect chain as in this case the mixer will not write to
3221 // mix buffer and track effects will accumulate into it
Glenn Kasten58912562012-04-03 10:45:00 -07003222 if ((mixedTracks != 0 && mixedTracks == tracksWithEffect) || (mixedTracks == 0 && fastTracks > 0)) {
3223 // FIXME as a performance optimization, should remember previous zero status
3224 memset(mMixBuffer, 0, mNormalFrameCount * mChannelCount * sizeof(int16_t));
Mathias Agopian65ab4712010-07-14 17:59:35 -07003225 }
3226
Glenn Kasten58912562012-04-03 10:45:00 -07003227 // if any fast tracks, then status is ready
Glenn Kasten81028042012-04-30 18:15:12 -07003228 mMixerStatusIgnoringFastTracks = mixerStatus;
Glenn Kasten58912562012-04-03 10:45:00 -07003229 if (fastTracks > 0) {
3230 mixerStatus = MIXER_TRACKS_READY;
3231 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07003232 return mixerStatus;
3233}
3234
Glenn Kasten66fcab92012-02-24 14:59:21 -08003235/*
3236The derived values that are cached:
3237 - mixBufferSize from frame count * frame size
3238 - activeSleepTime from activeSleepTimeUs()
3239 - idleSleepTime from idleSleepTimeUs()
3240 - standbyDelay from mActiveSleepTimeUs (DIRECT only)
3241 - maxPeriod from frame count and sample rate (MIXER only)
3242
3243The parameters that affect these derived values are:
3244 - frame count
3245 - frame size
3246 - sample rate
3247 - device type: A2DP or not
3248 - device latency
3249 - format: PCM or not
3250 - active sleep time
3251 - idle sleep time
3252*/
3253
3254void AudioFlinger::PlaybackThread::cacheParameters_l()
3255{
Glenn Kasten58912562012-04-03 10:45:00 -07003256 mixBufferSize = mNormalFrameCount * mFrameSize;
Glenn Kasten66fcab92012-02-24 14:59:21 -08003257 activeSleepTime = activeSleepTimeUs();
3258 idleSleepTime = idleSleepTimeUs();
3259}
3260
Glenn Kastenfff6d712012-01-12 16:38:12 -08003261void AudioFlinger::MixerThread::invalidateTracks(audio_stream_type_t streamType)
Mathias Agopian65ab4712010-07-14 17:59:35 -07003262{
Steve Block3856b092011-10-20 11:56:00 +01003263 ALOGV ("MixerThread::invalidateTracks() mixer %p, streamType %d, mTracks.size %d",
Eric Laurentde070132010-07-13 04:45:46 -07003264 this, streamType, mTracks.size());
Mathias Agopian65ab4712010-07-14 17:59:35 -07003265 Mutex::Autolock _l(mLock);
Eric Laurentde070132010-07-13 04:45:46 -07003266
Mathias Agopian65ab4712010-07-14 17:59:35 -07003267 size_t size = mTracks.size();
3268 for (size_t i = 0; i < size; i++) {
3269 sp<Track> t = mTracks[i];
Glenn Kasten02bbd202012-02-08 12:35:35 -08003270 if (t->streamType() == streamType) {
Eric Laurent38ccae22011-03-28 18:37:07 -07003271 android_atomic_or(CBLK_INVALID_ON, &t->mCblk->flags);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003272 t->mCblk->cv.signal();
Mathias Agopian65ab4712010-07-14 17:59:35 -07003273 }
3274 }
3275}
3276
Mathias Agopian65ab4712010-07-14 17:59:35 -07003277// getTrackName_l() must be called with ThreadBase::mLock held
Jean-Michel Trivi7d5b2622012-04-04 18:54:36 -07003278int AudioFlinger::MixerThread::getTrackName_l(audio_channel_mask_t channelMask)
Mathias Agopian65ab4712010-07-14 17:59:35 -07003279{
Jean-Michel Trivi9bd23222012-04-16 13:43:48 -07003280 return mAudioMixer->getTrackName(channelMask);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003281}
3282
3283// deleteTrackName_l() must be called with ThreadBase::mLock held
3284void AudioFlinger::MixerThread::deleteTrackName_l(int name)
3285{
Steve Block3856b092011-10-20 11:56:00 +01003286 ALOGV("remove track (%d) and delete from mixer", name);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003287 mAudioMixer->deleteTrackName(name);
3288}
3289
3290// checkForNewParameters_l() must be called with ThreadBase::mLock held
3291bool AudioFlinger::MixerThread::checkForNewParameters_l()
3292{
Glenn Kasten58912562012-04-03 10:45:00 -07003293 // if !&IDLE, holds the FastMixer state to restore after new parameters processed
3294 FastMixerState::Command previousCommand = FastMixerState::HOT_IDLE;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003295 bool reconfig = false;
3296
3297 while (!mNewParameters.isEmpty()) {
Glenn Kasten58912562012-04-03 10:45:00 -07003298
3299 if (mFastMixer != NULL) {
3300 FastMixerStateQueue *sq = mFastMixer->sq();
3301 FastMixerState *state = sq->begin();
3302 if (!(state->mCommand & FastMixerState::IDLE)) {
3303 previousCommand = state->mCommand;
3304 state->mCommand = FastMixerState::HOT_IDLE;
3305 sq->end();
3306 sq->push(FastMixerStateQueue::BLOCK_UNTIL_ACKED);
3307 } else {
3308 sq->end(false /*didModify*/);
3309 }
3310 }
3311
Mathias Agopian65ab4712010-07-14 17:59:35 -07003312 status_t status = NO_ERROR;
3313 String8 keyValuePair = mNewParameters[0];
3314 AudioParameter param = AudioParameter(keyValuePair);
3315 int value;
3316
3317 if (param.getInt(String8(AudioParameter::keySamplingRate), value) == NO_ERROR) {
3318 reconfig = true;
3319 }
3320 if (param.getInt(String8(AudioParameter::keyFormat), value) == NO_ERROR) {
Glenn Kasten58f30212012-01-12 12:27:51 -08003321 if ((audio_format_t) value != AUDIO_FORMAT_PCM_16_BIT) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07003322 status = BAD_VALUE;
3323 } else {
3324 reconfig = true;
3325 }
3326 }
3327 if (param.getInt(String8(AudioParameter::keyChannels), value) == NO_ERROR) {
Dima Zavinfce7a472011-04-19 22:30:36 -07003328 if (value != AUDIO_CHANNEL_OUT_STEREO) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07003329 status = BAD_VALUE;
3330 } else {
3331 reconfig = true;
3332 }
3333 }
3334 if (param.getInt(String8(AudioParameter::keyFrameCount), value) == NO_ERROR) {
3335 // do not accept frame count changes if tracks are open as the track buffer
Glenn Kasten362c4e62011-12-14 10:28:06 -08003336 // size depends on frame count and correct behavior would not be guaranteed
Mathias Agopian65ab4712010-07-14 17:59:35 -07003337 // if frame count is changed after track creation
3338 if (!mTracks.isEmpty()) {
3339 status = INVALID_OPERATION;
3340 } else {
3341 reconfig = true;
3342 }
3343 }
3344 if (param.getInt(String8(AudioParameter::keyRouting), value) == NO_ERROR) {
Glenn Kastend3cee2f2012-03-13 17:55:35 -07003345#ifdef ADD_BATTERY_DATA
Gloria Wang9ee159b2011-02-24 14:51:45 -08003346 // when changing the audio output device, call addBatteryData to notify
3347 // the change
Eric Laurentb469b942011-05-09 12:09:06 -07003348 if ((int)mDevice != value) {
Gloria Wang9ee159b2011-02-24 14:51:45 -08003349 uint32_t params = 0;
3350 // check whether speaker is on
Dima Zavinfce7a472011-04-19 22:30:36 -07003351 if (value & AUDIO_DEVICE_OUT_SPEAKER) {
Gloria Wang9ee159b2011-02-24 14:51:45 -08003352 params |= IMediaPlayerService::kBatteryDataSpeakerOn;
3353 }
3354
3355 int deviceWithoutSpeaker
Dima Zavinfce7a472011-04-19 22:30:36 -07003356 = AUDIO_DEVICE_OUT_ALL & ~AUDIO_DEVICE_OUT_SPEAKER;
Gloria Wang9ee159b2011-02-24 14:51:45 -08003357 // check if any other device (except speaker) is on
3358 if (value & deviceWithoutSpeaker ) {
3359 params |= IMediaPlayerService::kBatteryDataOtherAudioDeviceOn;
3360 }
3361
3362 if (params != 0) {
3363 addBatteryData(params);
3364 }
3365 }
Glenn Kastend3cee2f2012-03-13 17:55:35 -07003366#endif
Gloria Wang9ee159b2011-02-24 14:51:45 -08003367
Mathias Agopian65ab4712010-07-14 17:59:35 -07003368 // forward device change to effects that have requested to be
3369 // aware of attached audio device.
3370 mDevice = (uint32_t)value;
3371 for (size_t i = 0; i < mEffectChains.size(); i++) {
Eric Laurentcab11242010-07-15 12:50:15 -07003372 mEffectChains[i]->setDevice_l(mDevice);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003373 }
3374 }
3375
3376 if (status == NO_ERROR) {
Dima Zavin799a70e2011-04-18 16:57:27 -07003377 status = mOutput->stream->common.set_parameters(&mOutput->stream->common,
Dima Zavinfce7a472011-04-19 22:30:36 -07003378 keyValuePair.string());
Mathias Agopian65ab4712010-07-14 17:59:35 -07003379 if (!mStandby && status == INVALID_OPERATION) {
Glenn Kastene53b9ea2012-03-12 16:29:55 -07003380 mOutput->stream->common.standby(&mOutput->stream->common);
3381 mStandby = true;
3382 mBytesWritten = 0;
3383 status = mOutput->stream->common.set_parameters(&mOutput->stream->common,
Dima Zavinfce7a472011-04-19 22:30:36 -07003384 keyValuePair.string());
Mathias Agopian65ab4712010-07-14 17:59:35 -07003385 }
3386 if (status == NO_ERROR && reconfig) {
3387 delete mAudioMixer;
Glenn Kastene9dd0172012-01-27 18:08:45 -08003388 // for safety in case readOutputParameters() accesses mAudioMixer (it doesn't)
3389 mAudioMixer = NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003390 readOutputParameters();
Glenn Kasten58912562012-04-03 10:45:00 -07003391 mAudioMixer = new AudioMixer(mNormalFrameCount, mSampleRate);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003392 for (size_t i = 0; i < mTracks.size() ; i++) {
Jean-Michel Trivi7d5b2622012-04-04 18:54:36 -07003393 int name = getTrackName_l((audio_channel_mask_t)mTracks[i]->mChannelMask);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003394 if (name < 0) break;
3395 mTracks[i]->mName = name;
3396 // limit track sample rate to 2 x new output sample rate
3397 if (mTracks[i]->mCblk->sampleRate > 2 * sampleRate()) {
3398 mTracks[i]->mCblk->sampleRate = 2 * sampleRate();
3399 }
3400 }
3401 sendConfigEvent_l(AudioSystem::OUTPUT_CONFIG_CHANGED);
3402 }
3403 }
3404
3405 mNewParameters.removeAt(0);
3406
3407 mParamStatus = status;
3408 mParamCond.signal();
Eric Laurent60cd0a02011-09-13 11:40:21 -07003409 // wait for condition with time out in case the thread calling ThreadBase::setParameters()
3410 // already timed out waiting for the status and will never signal the condition.
Glenn Kasten7dede872011-12-13 11:04:14 -08003411 mWaitWorkCV.waitRelative(mLock, kSetParametersTimeoutNs);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003412 }
Glenn Kasten58912562012-04-03 10:45:00 -07003413
3414 if (!(previousCommand & FastMixerState::IDLE)) {
3415 ALOG_ASSERT(mFastMixer != NULL);
3416 FastMixerStateQueue *sq = mFastMixer->sq();
3417 FastMixerState *state = sq->begin();
3418 ALOG_ASSERT(state->mCommand == FastMixerState::HOT_IDLE);
3419 state->mCommand = previousCommand;
3420 sq->end();
3421 sq->push(FastMixerStateQueue::BLOCK_UNTIL_PUSHED);
3422 }
3423
Mathias Agopian65ab4712010-07-14 17:59:35 -07003424 return reconfig;
3425}
3426
3427status_t AudioFlinger::MixerThread::dumpInternals(int fd, const Vector<String16>& args)
3428{
3429 const size_t SIZE = 256;
3430 char buffer[SIZE];
3431 String8 result;
3432
3433 PlaybackThread::dumpInternals(fd, args);
3434
3435 snprintf(buffer, SIZE, "AudioMixer tracks: %08x\n", mAudioMixer->trackNames());
3436 result.append(buffer);
3437 write(fd, result.string(), result.size());
Glenn Kasten58912562012-04-03 10:45:00 -07003438
3439 // Make a non-atomic copy of fast mixer dump state so it won't change underneath us
3440 FastMixerDumpState copy = mFastMixerDumpState;
3441 copy.dump(fd);
3442
Mathias Agopian65ab4712010-07-14 17:59:35 -07003443 return NO_ERROR;
3444}
3445
Glenn Kasten0bf65bd2012-02-28 18:32:53 -08003446uint32_t AudioFlinger::MixerThread::idleSleepTimeUs() const
Mathias Agopian65ab4712010-07-14 17:59:35 -07003447{
Glenn Kasten58912562012-04-03 10:45:00 -07003448 return (uint32_t)(((mNormalFrameCount * 1000) / mSampleRate) * 1000) / 2;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003449}
3450
Glenn Kasten0bf65bd2012-02-28 18:32:53 -08003451uint32_t AudioFlinger::MixerThread::suspendSleepTimeUs() const
Eric Laurent25cbe0e2010-08-18 18:13:17 -07003452{
Glenn Kasten58912562012-04-03 10:45:00 -07003453 return (uint32_t)(((mNormalFrameCount * 1000) / mSampleRate) * 1000);
Eric Laurent25cbe0e2010-08-18 18:13:17 -07003454}
3455
Glenn Kasten66fcab92012-02-24 14:59:21 -08003456void AudioFlinger::MixerThread::cacheParameters_l()
3457{
3458 PlaybackThread::cacheParameters_l();
3459
3460 // FIXME: Relaxed timing because of a certain device that can't meet latency
3461 // Should be reduced to 2x after the vendor fixes the driver issue
3462 // increase threshold again due to low power audio mode. The way this warning
3463 // threshold is calculated and its usefulness should be reconsidered anyway.
Glenn Kasten58912562012-04-03 10:45:00 -07003464 maxPeriod = seconds(mNormalFrameCount) / mSampleRate * 15;
Glenn Kasten66fcab92012-02-24 14:59:21 -08003465}
3466
Mathias Agopian65ab4712010-07-14 17:59:35 -07003467// ----------------------------------------------------------------------------
Glenn Kasten72ef00d2012-01-17 11:09:42 -08003468AudioFlinger::DirectOutputThread::DirectOutputThread(const sp<AudioFlinger>& audioFlinger,
3469 AudioStreamOut* output, audio_io_handle_t id, uint32_t device)
Glenn Kasten23bb8be2012-01-26 10:38:26 -08003470 : PlaybackThread(audioFlinger, output, id, device, DIRECT)
Glenn Kasten84afa3b2012-01-25 15:28:08 -08003471 // mLeftVolFloat, mRightVolFloat
3472 // mLeftVolShort, mRightVolShort
Mathias Agopian65ab4712010-07-14 17:59:35 -07003473{
Mathias Agopian65ab4712010-07-14 17:59:35 -07003474}
3475
3476AudioFlinger::DirectOutputThread::~DirectOutputThread()
3477{
3478}
3479
Glenn Kasten1465f0c2012-03-06 11:23:32 -08003480AudioFlinger::PlaybackThread::mixer_state AudioFlinger::DirectOutputThread::prepareTracks_l(
3481 Vector< sp<Track> > *tracksToRemove
Glenn Kasten000f0e32012-03-01 17:10:56 -08003482)
Mathias Agopian65ab4712010-07-14 17:59:35 -07003483{
Glenn Kasten1465f0c2012-03-06 11:23:32 -08003484 sp<Track> trackToRemove;
3485
Glenn Kastenfec279f2012-03-08 07:47:15 -08003486 mixer_state mixerStatus = MIXER_IDLE;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003487
Glenn Kasten952eeb22012-03-06 11:30:57 -08003488 // find out which tracks need to be processed
3489 if (mActiveTracks.size() != 0) {
3490 sp<Track> t = mActiveTracks[0].promote();
Glenn Kastenfec279f2012-03-08 07:47:15 -08003491 // The track died recently
3492 if (t == 0) return MIXER_IDLE;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003493
Glenn Kasten952eeb22012-03-06 11:30:57 -08003494 Track* const track = t.get();
3495 audio_track_cblk_t* cblk = track->cblk();
Mathias Agopian65ab4712010-07-14 17:59:35 -07003496
Glenn Kasten952eeb22012-03-06 11:30:57 -08003497 // The first time a track is added we wait
3498 // for all its buffers to be filled before processing it
3499 if (cblk->framesReady() && track->isReady() &&
3500 !track->isPaused() && !track->isTerminated())
3501 {
3502 //ALOGV("track %d u=%08x, s=%08x [OK]", track->name(), cblk->user, cblk->server);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003503
Glenn Kasten952eeb22012-03-06 11:30:57 -08003504 if (track->mFillingUpStatus == Track::FS_FILLED) {
3505 track->mFillingUpStatus = Track::FS_ACTIVE;
3506 mLeftVolFloat = mRightVolFloat = 0;
3507 mLeftVolShort = mRightVolShort = 0;
3508 if (track->mState == TrackBase::RESUMING) {
3509 track->mState = TrackBase::ACTIVE;
3510 rampVolume = true;
3511 }
3512 } else if (cblk->server != 0) {
3513 // If the track is stopped before the first frame was mixed,
3514 // do not apply ramp
3515 rampVolume = true;
3516 }
3517 // compute volume for this track
3518 float left, right;
3519 if (track->isMuted() || mMasterMute || track->isPausing() ||
3520 mStreamTypes[track->streamType()].mute) {
3521 left = right = 0;
3522 if (track->isPausing()) {
3523 track->setPaused();
3524 }
3525 } else {
3526 float typeVolume = mStreamTypes[track->streamType()].volume;
3527 float v = mMasterVolume * typeVolume;
3528 uint32_t vlr = cblk->getVolumeLR();
3529 float v_clamped = v * (vlr & 0xFFFF);
3530 if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN;
3531 left = v_clamped/MAX_GAIN;
3532 v_clamped = v * (vlr >> 16);
3533 if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN;
3534 right = v_clamped/MAX_GAIN;
3535 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07003536
Glenn Kasten952eeb22012-03-06 11:30:57 -08003537 if (left != mLeftVolFloat || right != mRightVolFloat) {
3538 mLeftVolFloat = left;
3539 mRightVolFloat = right;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003540
Glenn Kasten952eeb22012-03-06 11:30:57 -08003541 // If audio HAL implements volume control,
3542 // force software volume to nominal value
3543 if (mOutput->stream->set_volume(mOutput->stream, left, right) == NO_ERROR) {
3544 left = 1.0f;
3545 right = 1.0f;
3546 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07003547
Glenn Kasten952eeb22012-03-06 11:30:57 -08003548 // Convert volumes from float to 8.24
3549 uint32_t vl = (uint32_t)(left * (1 << 24));
3550 uint32_t vr = (uint32_t)(right * (1 << 24));
Mathias Agopian65ab4712010-07-14 17:59:35 -07003551
Glenn Kasten952eeb22012-03-06 11:30:57 -08003552 // Delegate volume control to effect in track effect chain if needed
3553 // only one effect chain can be present on DirectOutputThread, so if
3554 // there is one, the track is connected to it
3555 if (!mEffectChains.isEmpty()) {
3556 // Do not ramp volume if volume is controlled by effect
3557 if (mEffectChains[0]->setVolume_l(&vl, &vr)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07003558 rampVolume = false;
3559 }
Glenn Kasten952eeb22012-03-06 11:30:57 -08003560 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07003561
Glenn Kasten952eeb22012-03-06 11:30:57 -08003562 // Convert volumes from 8.24 to 4.12 format
3563 uint32_t v_clamped = (vl + (1 << 11)) >> 12;
3564 if (v_clamped > MAX_GAIN_INT) v_clamped = MAX_GAIN_INT;
3565 leftVol = (uint16_t)v_clamped;
3566 v_clamped = (vr + (1 << 11)) >> 12;
3567 if (v_clamped > MAX_GAIN_INT) v_clamped = MAX_GAIN_INT;
3568 rightVol = (uint16_t)v_clamped;
3569 } else {
3570 leftVol = mLeftVolShort;
3571 rightVol = mRightVolShort;
3572 rampVolume = false;
3573 }
3574
3575 // reset retry count
3576 track->mRetryCount = kMaxTrackRetriesDirect;
Glenn Kastenb071e9b2012-03-07 17:05:59 -08003577 mActiveTrack = t;
Glenn Kastenfec279f2012-03-08 07:47:15 -08003578 mixerStatus = MIXER_TRACKS_READY;
Glenn Kasten952eeb22012-03-06 11:30:57 -08003579 } else {
3580 //ALOGV("track %d u=%08x, s=%08x [NOT READY]", track->name(), cblk->user, cblk->server);
Glenn Kasten952eeb22012-03-06 11:30:57 -08003581 if (track->isTerminated() || track->isStopped() || track->isPaused()) {
3582 // We have consumed all the buffers of this track.
3583 // Remove it from the list of active tracks.
Eric Laurenta011e352012-03-29 15:51:43 -07003584 // TODO: implement behavior for compressed audio
3585 size_t audioHALFrames =
3586 (mOutput->stream->get_latency(mOutput->stream)*mSampleRate) / 1000;
3587 size_t framesWritten =
3588 mBytesWritten / audio_stream_frame_size(&mOutput->stream->common);
3589 if (track->presentationComplete(framesWritten, audioHALFrames)) {
Eric Laurent29864602012-05-08 18:57:51 -07003590 if (track->isStopped()) {
3591 track->reset();
3592 }
Eric Laurenta011e352012-03-29 15:51:43 -07003593 trackToRemove = track;
3594 }
Glenn Kasten952eeb22012-03-06 11:30:57 -08003595 } else {
3596 // No buffers for this track. Give it a few chances to
3597 // fill a buffer, then remove it from active list.
3598 if (--(track->mRetryCount) <= 0) {
3599 ALOGV("BUFFER TIMEOUT: remove(%d) from active list", track->name());
3600 trackToRemove = track;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003601 } else {
Glenn Kastenfec279f2012-03-08 07:47:15 -08003602 mixerStatus = MIXER_TRACKS_ENABLED;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003603 }
3604 }
Glenn Kasten952eeb22012-03-06 11:30:57 -08003605 }
3606 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07003607
Glenn Kasten1465f0c2012-03-06 11:23:32 -08003608 // FIXME merge this with similar code for removing multiple tracks
Glenn Kasten952eeb22012-03-06 11:30:57 -08003609 // remove all the tracks that need to be...
3610 if (CC_UNLIKELY(trackToRemove != 0)) {
Glenn Kasten1465f0c2012-03-06 11:23:32 -08003611 tracksToRemove->add(trackToRemove);
Glenn Kasten952eeb22012-03-06 11:30:57 -08003612 mActiveTracks.remove(trackToRemove);
3613 if (!mEffectChains.isEmpty()) {
Glenn Kasten5798d4e2012-03-08 12:18:35 -08003614 ALOGV("stopping track on chain %p for session Id: %d", mEffectChains[0].get(),
Glenn Kasten952eeb22012-03-06 11:30:57 -08003615 trackToRemove->sessionId());
3616 mEffectChains[0]->decActiveTrackCnt();
3617 }
3618 if (trackToRemove->isTerminated()) {
3619 removeTrack_l(trackToRemove);
3620 }
3621 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07003622
Glenn Kastenfec279f2012-03-08 07:47:15 -08003623 return mixerStatus;
Glenn Kasten000f0e32012-03-01 17:10:56 -08003624}
Mathias Agopian65ab4712010-07-14 17:59:35 -07003625
Glenn Kasten000f0e32012-03-01 17:10:56 -08003626void AudioFlinger::DirectOutputThread::threadLoop_mix()
3627{
Glenn Kasten952eeb22012-03-06 11:30:57 -08003628 AudioBufferProvider::Buffer buffer;
3629 size_t frameCount = mFrameCount;
3630 int8_t *curBuf = (int8_t *)mMixBuffer;
3631 // output audio to hardware
3632 while (frameCount) {
3633 buffer.frameCount = frameCount;
Glenn Kastenb071e9b2012-03-07 17:05:59 -08003634 mActiveTrack->getNextBuffer(&buffer);
Glenn Kasten952eeb22012-03-06 11:30:57 -08003635 if (CC_UNLIKELY(buffer.raw == NULL)) {
3636 memset(curBuf, 0, frameCount * mFrameSize);
3637 break;
3638 }
3639 memcpy(curBuf, buffer.raw, buffer.frameCount * mFrameSize);
3640 frameCount -= buffer.frameCount;
3641 curBuf += buffer.frameCount * mFrameSize;
Glenn Kastenb071e9b2012-03-07 17:05:59 -08003642 mActiveTrack->releaseBuffer(&buffer);
Glenn Kasten952eeb22012-03-06 11:30:57 -08003643 }
3644 sleepTime = 0;
3645 standbyTime = systemTime() + standbyDelay;
Glenn Kastenb071e9b2012-03-07 17:05:59 -08003646 mActiveTrack.clear();
Glenn Kasten73f4bc32012-03-09 12:08:48 -08003647
3648 // apply volume
3649
3650 // Do not apply volume on compressed audio
3651 if (!audio_is_linear_pcm(mFormat)) {
3652 return;
3653 }
3654
3655 // convert to signed 16 bit before volume calculation
3656 if (mFormat == AUDIO_FORMAT_PCM_8_BIT) {
3657 size_t count = mFrameCount * mChannelCount;
3658 uint8_t *src = (uint8_t *)mMixBuffer + count-1;
3659 int16_t *dst = mMixBuffer + count-1;
Glenn Kastene53b9ea2012-03-12 16:29:55 -07003660 while (count--) {
Glenn Kasten73f4bc32012-03-09 12:08:48 -08003661 *dst-- = (int16_t)(*src--^0x80) << 8;
3662 }
3663 }
3664
3665 frameCount = mFrameCount;
3666 int16_t *out = mMixBuffer;
3667 if (rampVolume) {
3668 if (mChannelCount == 1) {
3669 int32_t d = ((int32_t)leftVol - (int32_t)mLeftVolShort) << 16;
3670 int32_t vlInc = d / (int32_t)frameCount;
3671 int32_t vl = ((int32_t)mLeftVolShort << 16);
3672 do {
3673 out[0] = clamp16(mul(out[0], vl >> 16) >> 12);
3674 out++;
3675 vl += vlInc;
3676 } while (--frameCount);
3677
3678 } else {
3679 int32_t d = ((int32_t)leftVol - (int32_t)mLeftVolShort) << 16;
3680 int32_t vlInc = d / (int32_t)frameCount;
3681 d = ((int32_t)rightVol - (int32_t)mRightVolShort) << 16;
3682 int32_t vrInc = d / (int32_t)frameCount;
3683 int32_t vl = ((int32_t)mLeftVolShort << 16);
3684 int32_t vr = ((int32_t)mRightVolShort << 16);
3685 do {
3686 out[0] = clamp16(mul(out[0], vl >> 16) >> 12);
3687 out[1] = clamp16(mul(out[1], vr >> 16) >> 12);
3688 out += 2;
3689 vl += vlInc;
3690 vr += vrInc;
3691 } while (--frameCount);
3692 }
3693 } else {
3694 if (mChannelCount == 1) {
3695 do {
3696 out[0] = clamp16(mul(out[0], leftVol) >> 12);
3697 out++;
3698 } while (--frameCount);
3699 } else {
3700 do {
3701 out[0] = clamp16(mul(out[0], leftVol) >> 12);
3702 out[1] = clamp16(mul(out[1], rightVol) >> 12);
3703 out += 2;
3704 } while (--frameCount);
3705 }
3706 }
3707
3708 // convert back to unsigned 8 bit after volume calculation
3709 if (mFormat == AUDIO_FORMAT_PCM_8_BIT) {
3710 size_t count = mFrameCount * mChannelCount;
3711 int16_t *src = mMixBuffer;
3712 uint8_t *dst = (uint8_t *)mMixBuffer;
Glenn Kastene53b9ea2012-03-12 16:29:55 -07003713 while (count--) {
Glenn Kasten73f4bc32012-03-09 12:08:48 -08003714 *dst++ = (uint8_t)(((int32_t)*src++ + (1<<7)) >> 8)^0x80;
3715 }
3716 }
3717
3718 mLeftVolShort = leftVol;
3719 mRightVolShort = rightVol;
Glenn Kasten000f0e32012-03-01 17:10:56 -08003720}
3721
3722void AudioFlinger::DirectOutputThread::threadLoop_sleepTime()
3723{
Glenn Kasten952eeb22012-03-06 11:30:57 -08003724 if (sleepTime == 0) {
Glenn Kastenfec279f2012-03-08 07:47:15 -08003725 if (mMixerStatus == MIXER_TRACKS_ENABLED) {
Glenn Kasten952eeb22012-03-06 11:30:57 -08003726 sleepTime = activeSleepTime;
3727 } else {
3728 sleepTime = idleSleepTime;
3729 }
3730 } else if (mBytesWritten != 0 && audio_is_linear_pcm(mFormat)) {
Glenn Kasten58912562012-04-03 10:45:00 -07003731 memset(mMixBuffer, 0, mFrameCount * mFrameSize);
Glenn Kasten952eeb22012-03-06 11:30:57 -08003732 sleepTime = 0;
3733 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07003734}
3735
3736// getTrackName_l() must be called with ThreadBase::mLock held
Jean-Michel Trivi7d5b2622012-04-04 18:54:36 -07003737int AudioFlinger::DirectOutputThread::getTrackName_l(audio_channel_mask_t channelMask)
Mathias Agopian65ab4712010-07-14 17:59:35 -07003738{
3739 return 0;
3740}
3741
3742// deleteTrackName_l() must be called with ThreadBase::mLock held
3743void AudioFlinger::DirectOutputThread::deleteTrackName_l(int name)
3744{
3745}
3746
3747// checkForNewParameters_l() must be called with ThreadBase::mLock held
3748bool AudioFlinger::DirectOutputThread::checkForNewParameters_l()
3749{
3750 bool reconfig = false;
3751
3752 while (!mNewParameters.isEmpty()) {
3753 status_t status = NO_ERROR;
3754 String8 keyValuePair = mNewParameters[0];
3755 AudioParameter param = AudioParameter(keyValuePair);
3756 int value;
3757
3758 if (param.getInt(String8(AudioParameter::keyFrameCount), value) == NO_ERROR) {
3759 // do not accept frame count changes if tracks are open as the track buffer
3760 // size depends on frame count and correct behavior would not be garantied
3761 // if frame count is changed after track creation
3762 if (!mTracks.isEmpty()) {
3763 status = INVALID_OPERATION;
3764 } else {
3765 reconfig = true;
3766 }
3767 }
3768 if (status == NO_ERROR) {
Dima Zavin799a70e2011-04-18 16:57:27 -07003769 status = mOutput->stream->common.set_parameters(&mOutput->stream->common,
Dima Zavinfce7a472011-04-19 22:30:36 -07003770 keyValuePair.string());
Mathias Agopian65ab4712010-07-14 17:59:35 -07003771 if (!mStandby && status == INVALID_OPERATION) {
Glenn Kastene53b9ea2012-03-12 16:29:55 -07003772 mOutput->stream->common.standby(&mOutput->stream->common);
3773 mStandby = true;
3774 mBytesWritten = 0;
3775 status = mOutput->stream->common.set_parameters(&mOutput->stream->common,
Dima Zavinfce7a472011-04-19 22:30:36 -07003776 keyValuePair.string());
Mathias Agopian65ab4712010-07-14 17:59:35 -07003777 }
3778 if (status == NO_ERROR && reconfig) {
3779 readOutputParameters();
3780 sendConfigEvent_l(AudioSystem::OUTPUT_CONFIG_CHANGED);
3781 }
3782 }
3783
3784 mNewParameters.removeAt(0);
3785
3786 mParamStatus = status;
3787 mParamCond.signal();
Eric Laurent60cd0a02011-09-13 11:40:21 -07003788 // wait for condition with time out in case the thread calling ThreadBase::setParameters()
3789 // already timed out waiting for the status and will never signal the condition.
Glenn Kasten7dede872011-12-13 11:04:14 -08003790 mWaitWorkCV.waitRelative(mLock, kSetParametersTimeoutNs);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003791 }
3792 return reconfig;
3793}
3794
Glenn Kasten0bf65bd2012-02-28 18:32:53 -08003795uint32_t AudioFlinger::DirectOutputThread::activeSleepTimeUs() const
Mathias Agopian65ab4712010-07-14 17:59:35 -07003796{
3797 uint32_t time;
Dima Zavinfce7a472011-04-19 22:30:36 -07003798 if (audio_is_linear_pcm(mFormat)) {
Eric Laurent162b40b2011-12-05 09:47:19 -08003799 time = PlaybackThread::activeSleepTimeUs();
Mathias Agopian65ab4712010-07-14 17:59:35 -07003800 } else {
3801 time = 10000;
3802 }
3803 return time;
3804}
3805
Glenn Kasten0bf65bd2012-02-28 18:32:53 -08003806uint32_t AudioFlinger::DirectOutputThread::idleSleepTimeUs() const
Mathias Agopian65ab4712010-07-14 17:59:35 -07003807{
3808 uint32_t time;
Dima Zavinfce7a472011-04-19 22:30:36 -07003809 if (audio_is_linear_pcm(mFormat)) {
Eric Laurent60e18242010-07-29 06:50:24 -07003810 time = (uint32_t)(((mFrameCount * 1000) / mSampleRate) * 1000) / 2;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003811 } else {
3812 time = 10000;
3813 }
3814 return time;
3815}
3816
Glenn Kasten0bf65bd2012-02-28 18:32:53 -08003817uint32_t AudioFlinger::DirectOutputThread::suspendSleepTimeUs() const
Eric Laurent25cbe0e2010-08-18 18:13:17 -07003818{
3819 uint32_t time;
Dima Zavinfce7a472011-04-19 22:30:36 -07003820 if (audio_is_linear_pcm(mFormat)) {
Eric Laurent25cbe0e2010-08-18 18:13:17 -07003821 time = (uint32_t)(((mFrameCount * 1000) / mSampleRate) * 1000);
3822 } else {
3823 time = 10000;
3824 }
3825 return time;
3826}
3827
Glenn Kasten66fcab92012-02-24 14:59:21 -08003828void AudioFlinger::DirectOutputThread::cacheParameters_l()
3829{
3830 PlaybackThread::cacheParameters_l();
3831
3832 // use shorter standby delay as on normal output to release
3833 // hardware resources as soon as possible
3834 standbyDelay = microseconds(activeSleepTime*2);
3835}
Eric Laurent25cbe0e2010-08-18 18:13:17 -07003836
Mathias Agopian65ab4712010-07-14 17:59:35 -07003837// ----------------------------------------------------------------------------
3838
Glenn Kasten23bb8be2012-01-26 10:38:26 -08003839AudioFlinger::DuplicatingThread::DuplicatingThread(const sp<AudioFlinger>& audioFlinger,
Glenn Kasten72ef00d2012-01-17 11:09:42 -08003840 AudioFlinger::MixerThread* mainThread, audio_io_handle_t id)
Glenn Kasten23bb8be2012-01-26 10:38:26 -08003841 : MixerThread(audioFlinger, mainThread->getOutput(), id, mainThread->device(), DUPLICATING),
3842 mWaitTimeMs(UINT_MAX)
Mathias Agopian65ab4712010-07-14 17:59:35 -07003843{
Mathias Agopian65ab4712010-07-14 17:59:35 -07003844 addOutputTrack(mainThread);
3845}
3846
3847AudioFlinger::DuplicatingThread::~DuplicatingThread()
3848{
3849 for (size_t i = 0; i < mOutputTracks.size(); i++) {
3850 mOutputTracks[i]->destroy();
3851 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07003852}
3853
Glenn Kasten000f0e32012-03-01 17:10:56 -08003854void AudioFlinger::DuplicatingThread::threadLoop_mix()
Mathias Agopian65ab4712010-07-14 17:59:35 -07003855{
Glenn Kasten952eeb22012-03-06 11:30:57 -08003856 // mix buffers...
3857 if (outputsReady(outputTracks)) {
3858 mAudioMixer->process(AudioBufferProvider::kInvalidPTS);
3859 } else {
3860 memset(mMixBuffer, 0, mixBufferSize);
3861 }
3862 sleepTime = 0;
Glenn Kasten58912562012-04-03 10:45:00 -07003863 writeFrames = mNormalFrameCount;
Glenn Kasten000f0e32012-03-01 17:10:56 -08003864}
3865
3866void AudioFlinger::DuplicatingThread::threadLoop_sleepTime()
3867{
Glenn Kasten952eeb22012-03-06 11:30:57 -08003868 if (sleepTime == 0) {
Glenn Kastenfec279f2012-03-08 07:47:15 -08003869 if (mMixerStatus == MIXER_TRACKS_ENABLED) {
Glenn Kasten952eeb22012-03-06 11:30:57 -08003870 sleepTime = activeSleepTime;
3871 } else {
3872 sleepTime = idleSleepTime;
3873 }
3874 } else if (mBytesWritten != 0) {
3875 // flush remaining overflow buffers in output tracks
3876 for (size_t i = 0; i < outputTracks.size(); i++) {
3877 if (outputTracks[i]->isActive()) {
3878 sleepTime = 0;
3879 writeFrames = 0;
3880 memset(mMixBuffer, 0, mixBufferSize);
3881 break;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003882 }
Glenn Kasten952eeb22012-03-06 11:30:57 -08003883 }
3884 }
Glenn Kasten000f0e32012-03-01 17:10:56 -08003885}
Mathias Agopian65ab4712010-07-14 17:59:35 -07003886
Glenn Kasten000f0e32012-03-01 17:10:56 -08003887void AudioFlinger::DuplicatingThread::threadLoop_write()
3888{
Glenn Kasten66fcab92012-02-24 14:59:21 -08003889 standbyTime = systemTime() + standbyDelay;
Glenn Kasten952eeb22012-03-06 11:30:57 -08003890 for (size_t i = 0; i < outputTracks.size(); i++) {
3891 outputTracks[i]->write(mMixBuffer, writeFrames);
3892 }
3893 mBytesWritten += mixBufferSize;
Glenn Kasten000f0e32012-03-01 17:10:56 -08003894}
Glenn Kasten688a6402012-02-29 07:57:06 -08003895
Glenn Kasten000f0e32012-03-01 17:10:56 -08003896void AudioFlinger::DuplicatingThread::threadLoop_standby()
3897{
Glenn Kasten952eeb22012-03-06 11:30:57 -08003898 // DuplicatingThread implements standby by stopping all tracks
3899 for (size_t i = 0; i < outputTracks.size(); i++) {
3900 outputTracks[i]->stop();
3901 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07003902}
3903
Glenn Kastenfa26a852012-03-06 11:28:04 -08003904void AudioFlinger::DuplicatingThread::saveOutputTracks()
3905{
3906 outputTracks = mOutputTracks;
3907}
3908
3909void AudioFlinger::DuplicatingThread::clearOutputTracks()
3910{
3911 outputTracks.clear();
3912}
3913
Mathias Agopian65ab4712010-07-14 17:59:35 -07003914void AudioFlinger::DuplicatingThread::addOutputTrack(MixerThread *thread)
3915{
Glenn Kastenb6b74062012-02-24 14:12:20 -08003916 Mutex::Autolock _l(mLock);
Glenn Kasten99e53b82012-01-19 08:59:58 -08003917 // FIXME explain this formula
Glenn Kasten58912562012-04-03 10:45:00 -07003918 int frameCount = (3 * mNormalFrameCount * mSampleRate) / thread->sampleRate();
Glenn Kasten9eaa5572012-01-20 13:32:16 -08003919 OutputTrack *outputTrack = new OutputTrack(thread,
Mathias Agopian65ab4712010-07-14 17:59:35 -07003920 this,
3921 mSampleRate,
3922 mFormat,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07003923 mChannelMask,
Mathias Agopian65ab4712010-07-14 17:59:35 -07003924 frameCount);
3925 if (outputTrack->cblk() != NULL) {
Dima Zavinfce7a472011-04-19 22:30:36 -07003926 thread->setStreamVolume(AUDIO_STREAM_CNT, 1.0f);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003927 mOutputTracks.add(outputTrack);
Steve Block3856b092011-10-20 11:56:00 +01003928 ALOGV("addOutputTrack() track %p, on thread %p", outputTrack, thread);
Glenn Kasten438b0362012-03-06 11:24:48 -08003929 updateWaitTime_l();
Mathias Agopian65ab4712010-07-14 17:59:35 -07003930 }
3931}
3932
3933void AudioFlinger::DuplicatingThread::removeOutputTrack(MixerThread *thread)
3934{
3935 Mutex::Autolock _l(mLock);
3936 for (size_t i = 0; i < mOutputTracks.size(); i++) {
Glenn Kastena1117922012-01-26 10:53:32 -08003937 if (mOutputTracks[i]->thread() == thread) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07003938 mOutputTracks[i]->destroy();
3939 mOutputTracks.removeAt(i);
Glenn Kasten438b0362012-03-06 11:24:48 -08003940 updateWaitTime_l();
Mathias Agopian65ab4712010-07-14 17:59:35 -07003941 return;
3942 }
3943 }
Steve Block3856b092011-10-20 11:56:00 +01003944 ALOGV("removeOutputTrack(): unkonwn thread: %p", thread);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003945}
3946
Glenn Kasten438b0362012-03-06 11:24:48 -08003947// caller must hold mLock
3948void AudioFlinger::DuplicatingThread::updateWaitTime_l()
Mathias Agopian65ab4712010-07-14 17:59:35 -07003949{
3950 mWaitTimeMs = UINT_MAX;
3951 for (size_t i = 0; i < mOutputTracks.size(); i++) {
3952 sp<ThreadBase> strong = mOutputTracks[i]->thread().promote();
Glenn Kasten7378ca52012-01-20 13:44:40 -08003953 if (strong != 0) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07003954 uint32_t waitTimeMs = (strong->frameCount() * 2 * 1000) / strong->sampleRate();
3955 if (waitTimeMs < mWaitTimeMs) {
3956 mWaitTimeMs = waitTimeMs;
3957 }
3958 }
3959 }
3960}
3961
3962
Glenn Kasten02fe1bf2012-02-24 15:42:17 -08003963bool AudioFlinger::DuplicatingThread::outputsReady(const SortedVector< sp<OutputTrack> > &outputTracks)
Mathias Agopian65ab4712010-07-14 17:59:35 -07003964{
3965 for (size_t i = 0; i < outputTracks.size(); i++) {
Glenn Kastene53b9ea2012-03-12 16:29:55 -07003966 sp<ThreadBase> thread = outputTracks[i]->thread().promote();
Mathias Agopian65ab4712010-07-14 17:59:35 -07003967 if (thread == 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00003968 ALOGW("DuplicatingThread::outputsReady() could not promote thread on output track %p", outputTracks[i].get());
Mathias Agopian65ab4712010-07-14 17:59:35 -07003969 return false;
3970 }
3971 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
3972 if (playbackThread->standby() && !playbackThread->isSuspended()) {
Steve Block3856b092011-10-20 11:56:00 +01003973 ALOGV("DuplicatingThread output track %p on thread %p Not Ready", outputTracks[i].get(), thread.get());
Mathias Agopian65ab4712010-07-14 17:59:35 -07003974 return false;
3975 }
3976 }
3977 return true;
3978}
3979
Glenn Kasten0bf65bd2012-02-28 18:32:53 -08003980uint32_t AudioFlinger::DuplicatingThread::activeSleepTimeUs() const
Mathias Agopian65ab4712010-07-14 17:59:35 -07003981{
3982 return (mWaitTimeMs * 1000) / 2;
3983}
3984
Glenn Kasten66fcab92012-02-24 14:59:21 -08003985void AudioFlinger::DuplicatingThread::cacheParameters_l()
3986{
3987 // updateWaitTime_l() sets mWaitTimeMs, which affects activeSleepTimeUs(), so call it first
3988 updateWaitTime_l();
3989
3990 MixerThread::cacheParameters_l();
3991}
3992
Mathias Agopian65ab4712010-07-14 17:59:35 -07003993// ----------------------------------------------------------------------------
3994
3995// TrackBase constructor must be called with AudioFlinger::mLock held
3996AudioFlinger::ThreadBase::TrackBase::TrackBase(
Glenn Kasten9eaa5572012-01-20 13:32:16 -08003997 ThreadBase *thread,
Mathias Agopian65ab4712010-07-14 17:59:35 -07003998 const sp<Client>& client,
3999 uint32_t sampleRate,
Glenn Kasten58f30212012-01-12 12:27:51 -08004000 audio_format_t format,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07004001 uint32_t channelMask,
Mathias Agopian65ab4712010-07-14 17:59:35 -07004002 int frameCount,
Mathias Agopian65ab4712010-07-14 17:59:35 -07004003 const sp<IMemory>& sharedBuffer,
4004 int sessionId)
4005 : RefBase(),
4006 mThread(thread),
4007 mClient(client),
Glenn Kasten84afa3b2012-01-25 15:28:08 -08004008 mCblk(NULL),
4009 // mBuffer
4010 // mBufferEnd
Mathias Agopian65ab4712010-07-14 17:59:35 -07004011 mFrameCount(0),
4012 mState(IDLE),
Glenn Kasten58912562012-04-03 10:45:00 -07004013 mSampleRate(sampleRate),
Mathias Agopian65ab4712010-07-14 17:59:35 -07004014 mFormat(format),
Glenn Kasten5cf034d2012-02-21 10:35:56 -08004015 mStepServerFailed(false),
Mathias Agopian65ab4712010-07-14 17:59:35 -07004016 mSessionId(sessionId)
Glenn Kasten84afa3b2012-01-25 15:28:08 -08004017 // mChannelCount
4018 // mChannelMask
Mathias Agopian65ab4712010-07-14 17:59:35 -07004019{
Steve Block3856b092011-10-20 11:56:00 +01004020 ALOGV_IF(sharedBuffer != 0, "sharedBuffer: %p, size: %d", sharedBuffer->pointer(), sharedBuffer->size());
Mathias Agopian65ab4712010-07-14 17:59:35 -07004021
Steve Blockb8a80522011-12-20 16:23:08 +00004022 // ALOGD("Creating track with %d buffers @ %d bytes", bufferCount, bufferSize);
Glenn Kastene53b9ea2012-03-12 16:29:55 -07004023 size_t size = sizeof(audio_track_cblk_t);
4024 uint8_t channelCount = popcount(channelMask);
4025 size_t bufferSize = frameCount*channelCount*sizeof(int16_t);
4026 if (sharedBuffer == 0) {
4027 size += bufferSize;
4028 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07004029
Glenn Kastene53b9ea2012-03-12 16:29:55 -07004030 if (client != NULL) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07004031 mCblkMemory = client->heap()->allocate(size);
4032 if (mCblkMemory != 0) {
4033 mCblk = static_cast<audio_track_cblk_t *>(mCblkMemory->pointer());
Glenn Kastena0d68332012-01-27 16:47:15 -08004034 if (mCblk != NULL) { // construct the shared structure in-place.
Mathias Agopian65ab4712010-07-14 17:59:35 -07004035 new(mCblk) audio_track_cblk_t();
4036 // clear all buffers
4037 mCblk->frameCount = frameCount;
4038 mCblk->sampleRate = sampleRate;
Marco Nelissena1472d92012-03-30 14:36:54 -07004039// uncomment the following lines to quickly test 32-bit wraparound
4040// mCblk->user = 0xffff0000;
4041// mCblk->server = 0xffff0000;
4042// mCblk->userBase = 0xffff0000;
4043// mCblk->serverBase = 0xffff0000;
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07004044 mChannelCount = channelCount;
4045 mChannelMask = channelMask;
Mathias Agopian65ab4712010-07-14 17:59:35 -07004046 if (sharedBuffer == 0) {
4047 mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t);
4048 memset(mBuffer, 0, frameCount*channelCount*sizeof(int16_t));
4049 // Force underrun condition to avoid false underrun callback until first data is
Eric Laurent44d98482010-09-30 16:12:31 -07004050 // written to buffer (other flags are cleared)
Mathias Agopian65ab4712010-07-14 17:59:35 -07004051 mCblk->flags = CBLK_UNDERRUN_ON;
4052 } else {
4053 mBuffer = sharedBuffer->pointer();
4054 }
4055 mBufferEnd = (uint8_t *)mBuffer + bufferSize;
4056 }
4057 } else {
Steve Block29357bc2012-01-06 19:20:56 +00004058 ALOGE("not enough memory for AudioTrack size=%u", size);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004059 client->heap()->dump("AudioTrack");
4060 return;
4061 }
Glenn Kastene53b9ea2012-03-12 16:29:55 -07004062 } else {
4063 mCblk = (audio_track_cblk_t *)(new uint8_t[size]);
Glenn Kastenea7939a2012-03-14 12:56:26 -07004064 // construct the shared structure in-place.
4065 new(mCblk) audio_track_cblk_t();
4066 // clear all buffers
4067 mCblk->frameCount = frameCount;
4068 mCblk->sampleRate = sampleRate;
Marco Nelissena1472d92012-03-30 14:36:54 -07004069// uncomment the following lines to quickly test 32-bit wraparound
4070// mCblk->user = 0xffff0000;
4071// mCblk->server = 0xffff0000;
4072// mCblk->userBase = 0xffff0000;
4073// mCblk->serverBase = 0xffff0000;
Glenn Kastenea7939a2012-03-14 12:56:26 -07004074 mChannelCount = channelCount;
4075 mChannelMask = channelMask;
4076 mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t);
4077 memset(mBuffer, 0, frameCount*channelCount*sizeof(int16_t));
4078 // Force underrun condition to avoid false underrun callback until first data is
4079 // written to buffer (other flags are cleared)
4080 mCblk->flags = CBLK_UNDERRUN_ON;
4081 mBufferEnd = (uint8_t *)mBuffer + bufferSize;
Glenn Kastene53b9ea2012-03-12 16:29:55 -07004082 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07004083}
4084
4085AudioFlinger::ThreadBase::TrackBase::~TrackBase()
4086{
Glenn Kastena0d68332012-01-27 16:47:15 -08004087 if (mCblk != NULL) {
Glenn Kasten1a0ae5b2012-02-03 10:24:48 -08004088 if (mClient == 0) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07004089 delete mCblk;
Glenn Kasten1a0ae5b2012-02-03 10:24:48 -08004090 } else {
4091 mCblk->~audio_track_cblk_t(); // destroy our shared-structure.
Mathias Agopian65ab4712010-07-14 17:59:35 -07004092 }
4093 }
Glenn Kastendbfafaf2012-01-25 15:27:15 -08004094 mCblkMemory.clear(); // free the shared memory before releasing the heap it belongs to
Glenn Kasten7378ca52012-01-20 13:44:40 -08004095 if (mClient != 0) {
Glenn Kasten84afa3b2012-01-25 15:28:08 -08004096 // Client destructor must run with AudioFlinger mutex locked
Mathias Agopian65ab4712010-07-14 17:59:35 -07004097 Mutex::Autolock _l(mClient->audioFlinger()->mLock);
Glenn Kasten7378ca52012-01-20 13:44:40 -08004098 // If the client's reference count drops to zero, the associated destructor
4099 // must run with AudioFlinger lock held. Thus the explicit clear() rather than
4100 // relying on the automatic clear() at end of scope.
Mathias Agopian65ab4712010-07-14 17:59:35 -07004101 mClient.clear();
4102 }
4103}
4104
Glenn Kasten01c4ebf2012-02-22 10:47:35 -08004105// AudioBufferProvider interface
4106// getNextBuffer() = 0;
4107// This implementation of releaseBuffer() is used by Track and RecordTrack, but not TimedTrack
Mathias Agopian65ab4712010-07-14 17:59:35 -07004108void AudioFlinger::ThreadBase::TrackBase::releaseBuffer(AudioBufferProvider::Buffer* buffer)
4109{
Glenn Kastene0feee32011-12-13 11:53:26 -08004110 buffer->raw = NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -07004111 mFrameCount = buffer->frameCount;
Glenn Kasten288ed212012-04-25 17:52:27 -07004112 // FIXME See note at getNextBuffer()
Glenn Kasten01c4ebf2012-02-22 10:47:35 -08004113 (void) step(); // ignore return value of step()
Mathias Agopian65ab4712010-07-14 17:59:35 -07004114 buffer->frameCount = 0;
4115}
4116
4117bool AudioFlinger::ThreadBase::TrackBase::step() {
4118 bool result;
4119 audio_track_cblk_t* cblk = this->cblk();
4120
4121 result = cblk->stepServer(mFrameCount);
4122 if (!result) {
Steve Block3856b092011-10-20 11:56:00 +01004123 ALOGV("stepServer failed acquiring cblk mutex");
Glenn Kasten5cf034d2012-02-21 10:35:56 -08004124 mStepServerFailed = true;
Mathias Agopian65ab4712010-07-14 17:59:35 -07004125 }
4126 return result;
4127}
4128
4129void AudioFlinger::ThreadBase::TrackBase::reset() {
4130 audio_track_cblk_t* cblk = this->cblk();
4131
4132 cblk->user = 0;
4133 cblk->server = 0;
4134 cblk->userBase = 0;
4135 cblk->serverBase = 0;
Glenn Kasten5cf034d2012-02-21 10:35:56 -08004136 mStepServerFailed = false;
Steve Block3856b092011-10-20 11:56:00 +01004137 ALOGV("TrackBase::reset");
Mathias Agopian65ab4712010-07-14 17:59:35 -07004138}
4139
Mathias Agopian65ab4712010-07-14 17:59:35 -07004140int AudioFlinger::ThreadBase::TrackBase::sampleRate() const {
4141 return (int)mCblk->sampleRate;
4142}
4143
Mathias Agopian65ab4712010-07-14 17:59:35 -07004144void* AudioFlinger::ThreadBase::TrackBase::getBuffer(uint32_t offset, uint32_t frames) const {
4145 audio_track_cblk_t* cblk = this->cblk();
Glenn Kastenb9980652012-01-11 09:48:27 -08004146 size_t frameSize = cblk->frameSize;
4147 int8_t *bufferStart = (int8_t *)mBuffer + (offset-cblk->serverBase)*frameSize;
4148 int8_t *bufferEnd = bufferStart + frames * frameSize;
Mathias Agopian65ab4712010-07-14 17:59:35 -07004149
4150 // Check validity of returned pointer in case the track control block would have been corrupted.
Jean-Michel Triviacb86cc2012-04-16 12:43:57 -07004151 ALOG_ASSERT(!(bufferStart < mBuffer || bufferStart > bufferEnd || bufferEnd > mBufferEnd),
4152 "TrackBase::getBuffer buffer out of range:\n"
4153 " start: %p, end %p , mBuffer %p mBufferEnd %p\n"
4154 " server %u, serverBase %u, user %u, userBase %u, frameSize %d",
Mathias Agopian65ab4712010-07-14 17:59:35 -07004155 bufferStart, bufferEnd, mBuffer, mBufferEnd,
Jean-Michel Triviacb86cc2012-04-16 12:43:57 -07004156 cblk->server, cblk->serverBase, cblk->user, cblk->userBase, frameSize);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004157
4158 return bufferStart;
4159}
4160
Eric Laurenta011e352012-03-29 15:51:43 -07004161status_t AudioFlinger::ThreadBase::TrackBase::setSyncEvent(const sp<SyncEvent>& event)
4162{
4163 mSyncEvents.add(event);
4164 return NO_ERROR;
4165}
4166
Mathias Agopian65ab4712010-07-14 17:59:35 -07004167// ----------------------------------------------------------------------------
4168
4169// Track constructor must be called with AudioFlinger::mLock and ThreadBase::mLock held
4170AudioFlinger::PlaybackThread::Track::Track(
Glenn Kasten9eaa5572012-01-20 13:32:16 -08004171 PlaybackThread *thread,
Mathias Agopian65ab4712010-07-14 17:59:35 -07004172 const sp<Client>& client,
Glenn Kastenfff6d712012-01-12 16:38:12 -08004173 audio_stream_type_t streamType,
Mathias Agopian65ab4712010-07-14 17:59:35 -07004174 uint32_t sampleRate,
Glenn Kasten58f30212012-01-12 12:27:51 -08004175 audio_format_t format,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07004176 uint32_t channelMask,
Mathias Agopian65ab4712010-07-14 17:59:35 -07004177 int frameCount,
4178 const sp<IMemory>& sharedBuffer,
Glenn Kasten73d22752012-03-19 13:38:30 -07004179 int sessionId,
4180 IAudioFlinger::track_flags_t flags)
Glenn Kasten5cf034d2012-02-21 10:35:56 -08004181 : TrackBase(thread, client, sampleRate, format, channelMask, frameCount, sharedBuffer, sessionId),
Glenn Kastenf9959012012-03-19 11:14:37 -07004182 mMute(false),
Glenn Kasten58912562012-04-03 10:45:00 -07004183 mFillingUpStatus(FS_INVALID),
Glenn Kastenf9959012012-03-19 11:14:37 -07004184 // mRetryCount initialized later when needed
4185 mSharedBuffer(sharedBuffer),
4186 mStreamType(streamType),
4187 mName(-1), // see note below
4188 mMainBuffer(thread->mixBuffer()),
4189 mAuxBuffer(NULL),
Eric Laurenta011e352012-03-29 15:51:43 -07004190 mAuxEffectId(0), mHasVolumeController(false),
Glenn Kasten73d22752012-03-19 13:38:30 -07004191 mPresentationCompleteFrames(0),
Glenn Kasten58912562012-04-03 10:45:00 -07004192 mFlags(flags),
4193 mFastIndex(-1),
Glenn Kasten288ed212012-04-25 17:52:27 -07004194 mUnderrunCount(0),
Glenn Kasten58912562012-04-03 10:45:00 -07004195 mCachedVolume(1.0)
Mathias Agopian65ab4712010-07-14 17:59:35 -07004196{
4197 if (mCblk != NULL) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07004198 // NOTE: audio_track_cblk_t::frameSize for 8 bit PCM data is based on a sample size of
4199 // 16 bit because data is converted to 16 bit before being stored in buffer by AudioTrack
Eric Laurentedc15ad2011-07-21 19:35:01 -07004200 mCblk->frameSize = audio_is_linear_pcm(format) ? mChannelCount * sizeof(int16_t) : sizeof(uint8_t);
Glenn Kasten58912562012-04-03 10:45:00 -07004201 if (flags & IAudioFlinger::TRACK_FAST) {
4202 mCblk->flags |= CBLK_FAST; // atomic op not needed yet
4203 ALOG_ASSERT(thread->mFastTrackAvailMask != 0);
4204 int i = __builtin_ctz(thread->mFastTrackAvailMask);
Eric Laurent29864602012-05-08 18:57:51 -07004205 ALOG_ASSERT(0 < i && i < (int)FastMixerState::kMaxFastTracks);
Glenn Kasten288ed212012-04-25 17:52:27 -07004206 // FIXME This is too eager. We allocate a fast track index before the
4207 // fast track becomes active. Since fast tracks are a scarce resource,
4208 // this means we are potentially denying other more important fast tracks from
4209 // being created. It would be better to allocate the index dynamically.
Glenn Kasten58912562012-04-03 10:45:00 -07004210 mFastIndex = i;
Glenn Kasten288ed212012-04-25 17:52:27 -07004211 // Read the initial underruns because this field is never cleared by the fast mixer
Glenn Kasten09474df2012-05-10 14:48:07 -07004212 mObservedUnderruns = thread->getFastTrackUnderruns(i);
Glenn Kasten58912562012-04-03 10:45:00 -07004213 thread->mFastTrackAvailMask &= ~(1 << i);
Glenn Kasten58912562012-04-03 10:45:00 -07004214 }
Glenn Kastenf9959012012-03-19 11:14:37 -07004215 // to avoid leaking a track name, do not allocate one unless there is an mCblk
Jean-Michel Trivi7d5b2622012-04-04 18:54:36 -07004216 mName = thread->getTrackName_l((audio_channel_mask_t)channelMask);
Glenn Kastenf9959012012-03-19 11:14:37 -07004217 if (mName < 0) {
4218 ALOGE("no more track names available");
Glenn Kasten288ed212012-04-25 17:52:27 -07004219 // FIXME bug - if sufficient fast track indices, but insufficient normal mixer names,
4220 // then we leak a fast track index. Should swap these two sections, or better yet
4221 // only allocate a normal mixer name for normal tracks.
Glenn Kastenf9959012012-03-19 11:14:37 -07004222 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07004223 }
Glenn Kastenf9959012012-03-19 11:14:37 -07004224 ALOGV("Track constructor name %d, calling pid %d", mName, IPCThreadState::self()->getCallingPid());
Mathias Agopian65ab4712010-07-14 17:59:35 -07004225}
4226
4227AudioFlinger::PlaybackThread::Track::~Track()
4228{
Steve Block3856b092011-10-20 11:56:00 +01004229 ALOGV("PlaybackThread::Track destructor");
Mathias Agopian65ab4712010-07-14 17:59:35 -07004230 sp<ThreadBase> thread = mThread.promote();
4231 if (thread != 0) {
4232 Mutex::Autolock _l(thread->mLock);
4233 mState = TERMINATED;
4234 }
4235}
4236
4237void AudioFlinger::PlaybackThread::Track::destroy()
4238{
4239 // NOTE: destroyTrack_l() can remove a strong reference to this Track
4240 // by removing it from mTracks vector, so there is a risk that this Tracks's
Glenn Kasten99e53b82012-01-19 08:59:58 -08004241 // destructor is called. As the destructor needs to lock mLock,
Mathias Agopian65ab4712010-07-14 17:59:35 -07004242 // we must acquire a strong reference on this Track before locking mLock
4243 // here so that the destructor is called only when exiting this function.
4244 // On the other hand, as long as Track::destroy() is only called by
4245 // TrackHandle destructor, the TrackHandle still holds a strong ref on
4246 // this Track with its member mTrack.
4247 sp<Track> keep(this);
4248 { // scope for mLock
4249 sp<ThreadBase> thread = mThread.promote();
4250 if (thread != 0) {
4251 if (!isOutputTrack()) {
4252 if (mState == ACTIVE || mState == RESUMING) {
Glenn Kasten02bbd202012-02-08 12:35:35 -08004253 AudioSystem::stopOutput(thread->id(), mStreamType, mSessionId);
Gloria Wang9ee159b2011-02-24 14:51:45 -08004254
Glenn Kastend3cee2f2012-03-13 17:55:35 -07004255#ifdef ADD_BATTERY_DATA
Gloria Wang9ee159b2011-02-24 14:51:45 -08004256 // to track the speaker usage
4257 addBatteryData(IMediaPlayerService::kBatteryDataAudioFlingerStop);
Glenn Kastend3cee2f2012-03-13 17:55:35 -07004258#endif
Mathias Agopian65ab4712010-07-14 17:59:35 -07004259 }
4260 AudioSystem::releaseOutput(thread->id());
4261 }
4262 Mutex::Autolock _l(thread->mLock);
4263 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
4264 playbackThread->destroyTrack_l(this);
4265 }
4266 }
4267}
4268
Glenn Kasten288ed212012-04-25 17:52:27 -07004269/*static*/ void AudioFlinger::PlaybackThread::Track::appendDumpHeader(String8& result)
4270{
Glenn Kastene213c862012-04-25 13:46:15 -07004271 result.append(" Name Client Type Fmt Chn mask Session mFrCnt fCount S M F SRate L dB R dB "
4272 " Server User Main buf Aux Buf Flags FastUnder\n");
Glenn Kasten288ed212012-04-25 17:52:27 -07004273}
4274
Mathias Agopian65ab4712010-07-14 17:59:35 -07004275void AudioFlinger::PlaybackThread::Track::dump(char* buffer, size_t size)
4276{
Glenn Kasten83d86532012-01-17 14:39:34 -08004277 uint32_t vlr = mCblk->getVolumeLR();
Glenn Kasten58912562012-04-03 10:45:00 -07004278 if (isFastTrack()) {
Glenn Kasten288ed212012-04-25 17:52:27 -07004279 sprintf(buffer, " F %2d", mFastIndex);
Glenn Kasten58912562012-04-03 10:45:00 -07004280 } else {
4281 sprintf(buffer, " %4d", mName - AudioMixer::TRACK0);
4282 }
Glenn Kasten288ed212012-04-25 17:52:27 -07004283 track_state state = mState;
4284 char stateChar;
4285 switch (state) {
4286 case IDLE:
4287 stateChar = 'I';
4288 break;
4289 case TERMINATED:
4290 stateChar = 'T';
4291 break;
Glenn Kastend08f48c2012-05-01 18:14:02 -07004292 case STOPPING_1:
4293 stateChar = 's';
4294 break;
4295 case STOPPING_2:
4296 stateChar = '5';
4297 break;
Glenn Kasten288ed212012-04-25 17:52:27 -07004298 case STOPPED:
4299 stateChar = 'S';
4300 break;
4301 case RESUMING:
4302 stateChar = 'R';
4303 break;
4304 case ACTIVE:
4305 stateChar = 'A';
4306 break;
4307 case PAUSING:
4308 stateChar = 'p';
4309 break;
4310 case PAUSED:
4311 stateChar = 'P';
4312 break;
Eric Laurent29864602012-05-08 18:57:51 -07004313 case FLUSHED:
4314 stateChar = 'F';
4315 break;
Glenn Kasten288ed212012-04-25 17:52:27 -07004316 default:
4317 stateChar = '?';
4318 break;
4319 }
Glenn Kasten09474df2012-05-10 14:48:07 -07004320 char nowInUnderrun;
4321 switch (mObservedUnderruns.mBitFields.mMostRecent) {
4322 case UNDERRUN_FULL:
4323 nowInUnderrun = ' ';
4324 break;
4325 case UNDERRUN_PARTIAL:
4326 nowInUnderrun = '<';
4327 break;
4328 case UNDERRUN_EMPTY:
4329 nowInUnderrun = '*';
4330 break;
4331 default:
4332 nowInUnderrun = '?';
4333 break;
4334 }
Glenn Kastene213c862012-04-25 13:46:15 -07004335 snprintf(&buffer[7], size-7, " %6d %4u %3u 0x%08x %7u %6u %6u %1c %1d %1d %5u %5.2g %5.2g "
4336 "0x%08x 0x%08x 0x%08x 0x%08x %#5x %9u%c\n",
Glenn Kasten44deb052012-02-05 18:09:08 -08004337 (mClient == 0) ? getpid_cached : mClient->pid(),
Mathias Agopian65ab4712010-07-14 17:59:35 -07004338 mStreamType,
4339 mFormat,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07004340 mChannelMask,
Mathias Agopian65ab4712010-07-14 17:59:35 -07004341 mSessionId,
4342 mFrameCount,
Glenn Kastene213c862012-04-25 13:46:15 -07004343 mCblk->frameCount,
Glenn Kasten288ed212012-04-25 17:52:27 -07004344 stateChar,
Mathias Agopian65ab4712010-07-14 17:59:35 -07004345 mMute,
4346 mFillingUpStatus,
4347 mCblk->sampleRate,
Glenn Kasten58912562012-04-03 10:45:00 -07004348 20.0 * log10((vlr & 0xFFFF) / 4096.0),
4349 20.0 * log10((vlr >> 16) / 4096.0),
Mathias Agopian65ab4712010-07-14 17:59:35 -07004350 mCblk->server,
4351 mCblk->user,
4352 (int)mMainBuffer,
Glenn Kasten288ed212012-04-25 17:52:27 -07004353 (int)mAuxBuffer,
Glenn Kastene213c862012-04-25 13:46:15 -07004354 mCblk->flags,
Glenn Kasten288ed212012-04-25 17:52:27 -07004355 mUnderrunCount,
Glenn Kasten09474df2012-05-10 14:48:07 -07004356 nowInUnderrun);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004357}
4358
Glenn Kasten01c4ebf2012-02-22 10:47:35 -08004359// AudioBufferProvider interface
John Grossman4ff14ba2012-02-08 16:37:41 -08004360status_t AudioFlinger::PlaybackThread::Track::getNextBuffer(
Glenn Kastene53b9ea2012-03-12 16:29:55 -07004361 AudioBufferProvider::Buffer* buffer, int64_t pts)
Mathias Agopian65ab4712010-07-14 17:59:35 -07004362{
Glenn Kastene53b9ea2012-03-12 16:29:55 -07004363 audio_track_cblk_t* cblk = this->cblk();
4364 uint32_t framesReady;
4365 uint32_t framesReq = buffer->frameCount;
Mathias Agopian65ab4712010-07-14 17:59:35 -07004366
Glenn Kastene53b9ea2012-03-12 16:29:55 -07004367 // Check if last stepServer failed, try to step now
4368 if (mStepServerFailed) {
Glenn Kasten288ed212012-04-25 17:52:27 -07004369 // FIXME When called by fast mixer, this takes a mutex with tryLock().
4370 // Since the fast mixer is higher priority than client callback thread,
4371 // it does not result in priority inversion for client.
4372 // But a non-blocking solution would be preferable to avoid
4373 // fast mixer being unable to tryLock(), and
4374 // to avoid the extra context switches if the client wakes up,
4375 // discovers the mutex is locked, then has to wait for fast mixer to unlock.
Glenn Kastene53b9ea2012-03-12 16:29:55 -07004376 if (!step()) goto getNextBuffer_exit;
4377 ALOGV("stepServer recovered");
4378 mStepServerFailed = false;
4379 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07004380
Glenn Kasten288ed212012-04-25 17:52:27 -07004381 // FIXME Same as above
Glenn Kastene53b9ea2012-03-12 16:29:55 -07004382 framesReady = cblk->framesReady();
Mathias Agopian65ab4712010-07-14 17:59:35 -07004383
Glenn Kastene53b9ea2012-03-12 16:29:55 -07004384 if (CC_LIKELY(framesReady)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07004385 uint32_t s = cblk->server;
4386 uint32_t bufferEnd = cblk->serverBase + cblk->frameCount;
4387
4388 bufferEnd = (cblk->loopEnd < bufferEnd) ? cblk->loopEnd : bufferEnd;
4389 if (framesReq > framesReady) {
4390 framesReq = framesReady;
4391 }
Marco Nelissena1472d92012-03-30 14:36:54 -07004392 if (framesReq > bufferEnd - s) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07004393 framesReq = bufferEnd - s;
4394 }
4395
Glenn Kastene53b9ea2012-03-12 16:29:55 -07004396 buffer->raw = getBuffer(s, framesReq);
4397 if (buffer->raw == NULL) goto getNextBuffer_exit;
Mathias Agopian65ab4712010-07-14 17:59:35 -07004398
Glenn Kastene53b9ea2012-03-12 16:29:55 -07004399 buffer->frameCount = framesReq;
Mathias Agopian65ab4712010-07-14 17:59:35 -07004400 return NO_ERROR;
Glenn Kastene53b9ea2012-03-12 16:29:55 -07004401 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07004402
4403getNextBuffer_exit:
Glenn Kastene53b9ea2012-03-12 16:29:55 -07004404 buffer->raw = NULL;
4405 buffer->frameCount = 0;
4406 ALOGV("getNextBuffer() no more data for track %d on thread %p", mName, mThread.unsafe_get());
4407 return NOT_ENOUGH_DATA;
Mathias Agopian65ab4712010-07-14 17:59:35 -07004408}
4409
Glenn Kasten288ed212012-04-25 17:52:27 -07004410// Note that framesReady() takes a mutex on the control block using tryLock().
4411// This could result in priority inversion if framesReady() is called by the normal mixer,
4412// as the normal mixer thread runs at lower
4413// priority than the client's callback thread: there is a short window within framesReady()
4414// during which the normal mixer could be preempted, and the client callback would block.
4415// Another problem can occur if framesReady() is called by the fast mixer:
4416// the tryLock() could block for up to 1 ms, and a sequence of these could delay fast mixer.
4417// FIXME Replace AudioTrackShared control block implementation by a non-blocking FIFO queue.
4418size_t AudioFlinger::PlaybackThread::Track::framesReady() const {
John Grossman4ff14ba2012-02-08 16:37:41 -08004419 return mCblk->framesReady();
4420}
4421
Glenn Kasten288ed212012-04-25 17:52:27 -07004422// Don't call for fast tracks; the framesReady() could result in priority inversion
Mathias Agopian65ab4712010-07-14 17:59:35 -07004423bool AudioFlinger::PlaybackThread::Track::isReady() const {
Eric Laurentaf59ce22010-10-05 14:41:42 -07004424 if (mFillingUpStatus != FS_FILLING || isStopped() || isPausing()) return true;
Mathias Agopian65ab4712010-07-14 17:59:35 -07004425
John Grossman4ff14ba2012-02-08 16:37:41 -08004426 if (framesReady() >= mCblk->frameCount ||
Mathias Agopian65ab4712010-07-14 17:59:35 -07004427 (mCblk->flags & CBLK_FORCEREADY_MSK)) {
4428 mFillingUpStatus = FS_FILLED;
Eric Laurent38ccae22011-03-28 18:37:07 -07004429 android_atomic_and(~CBLK_FORCEREADY_MSK, &mCblk->flags);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004430 return true;
4431 }
4432 return false;
4433}
4434
Glenn Kasten3acbd052012-02-28 10:39:56 -08004435status_t AudioFlinger::PlaybackThread::Track::start(AudioSystem::sync_event_t event,
Eric Laurenta011e352012-03-29 15:51:43 -07004436 int triggerSession)
Mathias Agopian65ab4712010-07-14 17:59:35 -07004437{
4438 status_t status = NO_ERROR;
Glenn Kasten58912562012-04-03 10:45:00 -07004439 ALOGV("start(%d), calling pid %d session %d",
4440 mName, IPCThreadState::self()->getCallingPid(), mSessionId);
Glenn Kasten3acbd052012-02-28 10:39:56 -08004441
Mathias Agopian65ab4712010-07-14 17:59:35 -07004442 sp<ThreadBase> thread = mThread.promote();
4443 if (thread != 0) {
4444 Mutex::Autolock _l(thread->mLock);
Glenn Kastenb853e982012-01-26 13:39:18 -08004445 track_state state = mState;
Mathias Agopian65ab4712010-07-14 17:59:35 -07004446 // here the track could be either new, or restarted
4447 // in both cases "unstop" the track
4448 if (mState == PAUSED) {
4449 mState = TrackBase::RESUMING;
Steve Block3856b092011-10-20 11:56:00 +01004450 ALOGV("PAUSED => RESUMING (%d) on thread %p", mName, this);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004451 } else {
4452 mState = TrackBase::ACTIVE;
Steve Block3856b092011-10-20 11:56:00 +01004453 ALOGV("? => ACTIVE (%d) on thread %p", mName, this);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004454 }
4455
4456 if (!isOutputTrack() && state != ACTIVE && state != RESUMING) {
4457 thread->mLock.unlock();
Glenn Kasten02bbd202012-02-08 12:35:35 -08004458 status = AudioSystem::startOutput(thread->id(), mStreamType, mSessionId);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004459 thread->mLock.lock();
Gloria Wang9ee159b2011-02-24 14:51:45 -08004460
Glenn Kastend3cee2f2012-03-13 17:55:35 -07004461#ifdef ADD_BATTERY_DATA
Gloria Wang9ee159b2011-02-24 14:51:45 -08004462 // to track the speaker usage
4463 if (status == NO_ERROR) {
4464 addBatteryData(IMediaPlayerService::kBatteryDataAudioFlingerStart);
4465 }
Glenn Kastend3cee2f2012-03-13 17:55:35 -07004466#endif
Mathias Agopian65ab4712010-07-14 17:59:35 -07004467 }
4468 if (status == NO_ERROR) {
4469 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
4470 playbackThread->addTrack_l(this);
4471 } else {
4472 mState = state;
Eric Laurent29864602012-05-08 18:57:51 -07004473 triggerEvents(AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004474 }
4475 } else {
4476 status = BAD_VALUE;
4477 }
4478 return status;
4479}
4480
4481void AudioFlinger::PlaybackThread::Track::stop()
4482{
Glenn Kasten23d82a92012-02-03 11:10:00 -08004483 ALOGV("stop(%d), calling pid %d", mName, IPCThreadState::self()->getCallingPid());
Mathias Agopian65ab4712010-07-14 17:59:35 -07004484 sp<ThreadBase> thread = mThread.promote();
4485 if (thread != 0) {
4486 Mutex::Autolock _l(thread->mLock);
Glenn Kastenb853e982012-01-26 13:39:18 -08004487 track_state state = mState;
Glenn Kastend08f48c2012-05-01 18:14:02 -07004488 if (state == RESUMING || state == ACTIVE || state == PAUSING || state == PAUSED) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07004489 // If the track is not active (PAUSED and buffers full), flush buffers
4490 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
4491 if (playbackThread->mActiveTracks.indexOf(this) < 0) {
4492 reset();
Glenn Kastend08f48c2012-05-01 18:14:02 -07004493 mState = STOPPED;
4494 } else if (!isFastTrack()) {
4495 mState = STOPPED;
4496 } else {
4497 // prepareTracks_l() will set state to STOPPING_2 after next underrun,
4498 // and then to STOPPED and reset() when presentation is complete
4499 mState = STOPPING_1;
Mathias Agopian65ab4712010-07-14 17:59:35 -07004500 }
Glenn Kastend08f48c2012-05-01 18:14:02 -07004501 ALOGV("not stopping/stopped => stopping/stopped (%d) on thread %p", mName, playbackThread);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004502 }
4503 if (!isOutputTrack() && (state == ACTIVE || state == RESUMING)) {
4504 thread->mLock.unlock();
Glenn Kasten02bbd202012-02-08 12:35:35 -08004505 AudioSystem::stopOutput(thread->id(), mStreamType, mSessionId);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004506 thread->mLock.lock();
Gloria Wang9ee159b2011-02-24 14:51:45 -08004507
Glenn Kastend3cee2f2012-03-13 17:55:35 -07004508#ifdef ADD_BATTERY_DATA
Gloria Wang9ee159b2011-02-24 14:51:45 -08004509 // to track the speaker usage
4510 addBatteryData(IMediaPlayerService::kBatteryDataAudioFlingerStop);
Glenn Kastend3cee2f2012-03-13 17:55:35 -07004511#endif
Mathias Agopian65ab4712010-07-14 17:59:35 -07004512 }
4513 }
4514}
4515
4516void AudioFlinger::PlaybackThread::Track::pause()
4517{
Glenn Kasten23d82a92012-02-03 11:10:00 -08004518 ALOGV("pause(%d), calling pid %d", mName, IPCThreadState::self()->getCallingPid());
Mathias Agopian65ab4712010-07-14 17:59:35 -07004519 sp<ThreadBase> thread = mThread.promote();
4520 if (thread != 0) {
4521 Mutex::Autolock _l(thread->mLock);
4522 if (mState == ACTIVE || mState == RESUMING) {
4523 mState = PAUSING;
Steve Block3856b092011-10-20 11:56:00 +01004524 ALOGV("ACTIVE/RESUMING => PAUSING (%d) on thread %p", mName, thread.get());
Mathias Agopian65ab4712010-07-14 17:59:35 -07004525 if (!isOutputTrack()) {
4526 thread->mLock.unlock();
Glenn Kasten02bbd202012-02-08 12:35:35 -08004527 AudioSystem::stopOutput(thread->id(), mStreamType, mSessionId);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004528 thread->mLock.lock();
Gloria Wang9ee159b2011-02-24 14:51:45 -08004529
Glenn Kastend3cee2f2012-03-13 17:55:35 -07004530#ifdef ADD_BATTERY_DATA
Gloria Wang9ee159b2011-02-24 14:51:45 -08004531 // to track the speaker usage
4532 addBatteryData(IMediaPlayerService::kBatteryDataAudioFlingerStop);
Glenn Kastend3cee2f2012-03-13 17:55:35 -07004533#endif
Mathias Agopian65ab4712010-07-14 17:59:35 -07004534 }
4535 }
4536 }
4537}
4538
4539void AudioFlinger::PlaybackThread::Track::flush()
4540{
Steve Block3856b092011-10-20 11:56:00 +01004541 ALOGV("flush(%d)", mName);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004542 sp<ThreadBase> thread = mThread.promote();
4543 if (thread != 0) {
4544 Mutex::Autolock _l(thread->mLock);
Glenn Kastend08f48c2012-05-01 18:14:02 -07004545 if (mState != STOPPING_1 && mState != STOPPING_2 && mState != STOPPED && mState != PAUSED &&
4546 mState != PAUSING) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07004547 return;
4548 }
4549 // No point remaining in PAUSED state after a flush => go to
Eric Laurent29864602012-05-08 18:57:51 -07004550 // FLUSHED state
4551 mState = FLUSHED;
Eric Laurent38ccae22011-03-28 18:37:07 -07004552 // do not reset the track if it is still in the process of being stopped or paused.
4553 // this will be done by prepareTracks_l() when the track is stopped.
Eric Laurent29864602012-05-08 18:57:51 -07004554 // prepareTracks_l() will see mState == FLUSHED, then
Glenn Kastend08f48c2012-05-01 18:14:02 -07004555 // remove from active track list, reset(), and trigger presentation complete
Eric Laurent38ccae22011-03-28 18:37:07 -07004556 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
4557 if (playbackThread->mActiveTracks.indexOf(this) < 0) {
4558 reset();
4559 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07004560 }
4561}
4562
4563void AudioFlinger::PlaybackThread::Track::reset()
4564{
4565 // Do not reset twice to avoid discarding data written just after a flush and before
4566 // the audioflinger thread detects the track is stopped.
4567 if (!mResetDone) {
4568 TrackBase::reset();
4569 // Force underrun condition to avoid false underrun callback until first data is
4570 // written to buffer
Eric Laurent38ccae22011-03-28 18:37:07 -07004571 android_atomic_and(~CBLK_FORCEREADY_MSK, &mCblk->flags);
4572 android_atomic_or(CBLK_UNDERRUN_ON, &mCblk->flags);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004573 mFillingUpStatus = FS_FILLING;
4574 mResetDone = true;
Eric Laurent29864602012-05-08 18:57:51 -07004575 if (mState == FLUSHED) {
4576 mState = IDLE;
4577 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07004578 }
4579}
4580
4581void AudioFlinger::PlaybackThread::Track::mute(bool muted)
4582{
4583 mMute = muted;
4584}
4585
Mathias Agopian65ab4712010-07-14 17:59:35 -07004586status_t AudioFlinger::PlaybackThread::Track::attachAuxEffect(int EffectId)
4587{
4588 status_t status = DEAD_OBJECT;
4589 sp<ThreadBase> thread = mThread.promote();
4590 if (thread != 0) {
Glenn Kastene53b9ea2012-03-12 16:29:55 -07004591 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
4592 status = playbackThread->attachAuxEffect(this, EffectId);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004593 }
4594 return status;
4595}
4596
4597void AudioFlinger::PlaybackThread::Track::setAuxBuffer(int EffectId, int32_t *buffer)
4598{
4599 mAuxEffectId = EffectId;
4600 mAuxBuffer = buffer;
4601}
4602
Eric Laurenta011e352012-03-29 15:51:43 -07004603bool AudioFlinger::PlaybackThread::Track::presentationComplete(size_t framesWritten,
4604 size_t audioHalFrames)
4605{
4606 // a track is considered presented when the total number of frames written to audio HAL
4607 // corresponds to the number of frames written when presentationComplete() is called for the
4608 // first time (mPresentationCompleteFrames == 0) plus the buffer filling status at that time.
4609 if (mPresentationCompleteFrames == 0) {
4610 mPresentationCompleteFrames = framesWritten + audioHalFrames;
4611 ALOGV("presentationComplete() reset: mPresentationCompleteFrames %d audioHalFrames %d",
4612 mPresentationCompleteFrames, audioHalFrames);
4613 }
4614 if (framesWritten >= mPresentationCompleteFrames) {
4615 ALOGV("presentationComplete() session %d complete: framesWritten %d",
4616 mSessionId, framesWritten);
4617 triggerEvents(AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE);
Eric Laurenta011e352012-03-29 15:51:43 -07004618 return true;
4619 }
4620 return false;
4621}
4622
4623void AudioFlinger::PlaybackThread::Track::triggerEvents(AudioSystem::sync_event_t type)
4624{
4625 for (int i = 0; i < (int)mSyncEvents.size(); i++) {
4626 if (mSyncEvents[i]->type() == type) {
4627 mSyncEvents[i]->trigger();
4628 mSyncEvents.removeAt(i);
4629 i--;
4630 }
4631 }
4632}
4633
Glenn Kasten58912562012-04-03 10:45:00 -07004634// implement VolumeBufferProvider interface
4635
4636uint32_t AudioFlinger::PlaybackThread::Track::getVolumeLR()
4637{
4638 // called by FastMixer, so not allowed to take any locks, block, or do I/O including logs
4639 ALOG_ASSERT(isFastTrack() && (mCblk != NULL));
4640 uint32_t vlr = mCblk->getVolumeLR();
4641 uint32_t vl = vlr & 0xFFFF;
4642 uint32_t vr = vlr >> 16;
4643 // track volumes come from shared memory, so can't be trusted and must be clamped
4644 if (vl > MAX_GAIN_INT) {
4645 vl = MAX_GAIN_INT;
4646 }
4647 if (vr > MAX_GAIN_INT) {
4648 vr = MAX_GAIN_INT;
4649 }
4650 // now apply the cached master volume and stream type volume;
4651 // this is trusted but lacks any synchronization or barrier so may be stale
4652 float v = mCachedVolume;
4653 vl *= v;
4654 vr *= v;
4655 // re-combine into U4.16
4656 vlr = (vr << 16) | (vl & 0xFFFF);
4657 // FIXME look at mute, pause, and stop flags
4658 return vlr;
4659}
Eric Laurenta011e352012-03-29 15:51:43 -07004660
Eric Laurent29864602012-05-08 18:57:51 -07004661status_t AudioFlinger::PlaybackThread::Track::setSyncEvent(const sp<SyncEvent>& event)
4662{
4663 if (mState == TERMINATED || mState == PAUSED ||
4664 ((framesReady() == 0) && ((mSharedBuffer != 0) ||
4665 (mState == STOPPED)))) {
4666 ALOGW("Track::setSyncEvent() in invalid state %d on session %d %s mode, framesReady %d ",
4667 mState, mSessionId, (mSharedBuffer != 0) ? "static" : "stream", framesReady());
4668 event->cancel();
4669 return INVALID_OPERATION;
4670 }
4671 TrackBase::setSyncEvent(event);
4672 return NO_ERROR;
4673}
4674
John Grossman4ff14ba2012-02-08 16:37:41 -08004675// timed audio tracks
4676
4677sp<AudioFlinger::PlaybackThread::TimedTrack>
4678AudioFlinger::PlaybackThread::TimedTrack::create(
Glenn Kasten9eaa5572012-01-20 13:32:16 -08004679 PlaybackThread *thread,
John Grossman4ff14ba2012-02-08 16:37:41 -08004680 const sp<Client>& client,
4681 audio_stream_type_t streamType,
4682 uint32_t sampleRate,
4683 audio_format_t format,
4684 uint32_t channelMask,
4685 int frameCount,
4686 const sp<IMemory>& sharedBuffer,
4687 int sessionId) {
4688 if (!client->reserveTimedTrack())
4689 return NULL;
4690
Glenn Kastena0356762012-03-19 10:38:51 -07004691 return new TimedTrack(
John Grossman4ff14ba2012-02-08 16:37:41 -08004692 thread, client, streamType, sampleRate, format, channelMask, frameCount,
4693 sharedBuffer, sessionId);
John Grossman4ff14ba2012-02-08 16:37:41 -08004694}
4695
4696AudioFlinger::PlaybackThread::TimedTrack::TimedTrack(
Glenn Kasten9eaa5572012-01-20 13:32:16 -08004697 PlaybackThread *thread,
John Grossman4ff14ba2012-02-08 16:37:41 -08004698 const sp<Client>& client,
4699 audio_stream_type_t streamType,
4700 uint32_t sampleRate,
4701 audio_format_t format,
4702 uint32_t channelMask,
4703 int frameCount,
4704 const sp<IMemory>& sharedBuffer,
4705 int sessionId)
4706 : Track(thread, client, streamType, sampleRate, format, channelMask,
Glenn Kasten73d22752012-03-19 13:38:30 -07004707 frameCount, sharedBuffer, sessionId, IAudioFlinger::TRACK_TIMED),
John Grossman9fbdee12012-03-26 17:51:46 -07004708 mQueueHeadInFlight(false),
4709 mTrimQueueHeadOnRelease(false),
John Grossman1c345192012-03-27 14:00:17 -07004710 mFramesPendingInQueue(0),
John Grossman4ff14ba2012-02-08 16:37:41 -08004711 mTimedSilenceBuffer(NULL),
4712 mTimedSilenceBufferSize(0),
4713 mTimedAudioOutputOnTime(false),
4714 mMediaTimeTransformValid(false)
4715{
4716 LocalClock lc;
4717 mLocalTimeFreq = lc.getLocalFreq();
4718
4719 mLocalTimeToSampleTransform.a_zero = 0;
4720 mLocalTimeToSampleTransform.b_zero = 0;
4721 mLocalTimeToSampleTransform.a_to_b_numer = sampleRate;
4722 mLocalTimeToSampleTransform.a_to_b_denom = mLocalTimeFreq;
4723 LinearTransform::reduce(&mLocalTimeToSampleTransform.a_to_b_numer,
4724 &mLocalTimeToSampleTransform.a_to_b_denom);
John Grossman9fbdee12012-03-26 17:51:46 -07004725
4726 mMediaTimeToSampleTransform.a_zero = 0;
4727 mMediaTimeToSampleTransform.b_zero = 0;
4728 mMediaTimeToSampleTransform.a_to_b_numer = sampleRate;
4729 mMediaTimeToSampleTransform.a_to_b_denom = 1000000;
4730 LinearTransform::reduce(&mMediaTimeToSampleTransform.a_to_b_numer,
4731 &mMediaTimeToSampleTransform.a_to_b_denom);
John Grossman4ff14ba2012-02-08 16:37:41 -08004732}
4733
4734AudioFlinger::PlaybackThread::TimedTrack::~TimedTrack() {
4735 mClient->releaseTimedTrack();
4736 delete [] mTimedSilenceBuffer;
4737}
4738
4739status_t AudioFlinger::PlaybackThread::TimedTrack::allocateTimedBuffer(
4740 size_t size, sp<IMemory>* buffer) {
4741
4742 Mutex::Autolock _l(mTimedBufferQueueLock);
4743
4744 trimTimedBufferQueue_l();
4745
4746 // lazily initialize the shared memory heap for timed buffers
4747 if (mTimedMemoryDealer == NULL) {
4748 const int kTimedBufferHeapSize = 512 << 10;
4749
4750 mTimedMemoryDealer = new MemoryDealer(kTimedBufferHeapSize,
4751 "AudioFlingerTimed");
4752 if (mTimedMemoryDealer == NULL)
4753 return NO_MEMORY;
4754 }
4755
4756 sp<IMemory> newBuffer = mTimedMemoryDealer->allocate(size);
4757 if (newBuffer == NULL) {
4758 newBuffer = mTimedMemoryDealer->allocate(size);
4759 if (newBuffer == NULL)
4760 return NO_MEMORY;
4761 }
4762
4763 *buffer = newBuffer;
4764 return NO_ERROR;
4765}
4766
4767// caller must hold mTimedBufferQueueLock
4768void AudioFlinger::PlaybackThread::TimedTrack::trimTimedBufferQueue_l() {
4769 int64_t mediaTimeNow;
4770 {
4771 Mutex::Autolock mttLock(mMediaTimeTransformLock);
4772 if (!mMediaTimeTransformValid)
4773 return;
4774
4775 int64_t targetTimeNow;
4776 status_t res = (mMediaTimeTransformTarget == TimedAudioTrack::COMMON_TIME)
4777 ? mCCHelper.getCommonTime(&targetTimeNow)
4778 : mCCHelper.getLocalTime(&targetTimeNow);
4779
4780 if (OK != res)
4781 return;
4782
4783 if (!mMediaTimeTransform.doReverseTransform(targetTimeNow,
4784 &mediaTimeNow)) {
4785 return;
4786 }
4787 }
4788
John Grossman1c345192012-03-27 14:00:17 -07004789 size_t trimEnd;
4790 for (trimEnd = 0; trimEnd < mTimedBufferQueue.size(); trimEnd++) {
John Grossman9fbdee12012-03-26 17:51:46 -07004791 int64_t bufEnd;
4792
John Grossmanc95cfbb2012-04-12 11:53:11 -07004793 if ((trimEnd + 1) < mTimedBufferQueue.size()) {
4794 // We have a next buffer. Just use its PTS as the PTS of the frame
4795 // following the last frame in this buffer. If the stream is sparse
4796 // (ie, there are deliberate gaps left in the stream which should be
4797 // filled with silence by the TimedAudioTrack), then this can result
4798 // in one extra buffer being left un-trimmed when it could have
4799 // been. In general, this is not typical, and we would rather
4800 // optimized away the TS calculation below for the more common case
4801 // where PTSes are contiguous.
4802 bufEnd = mTimedBufferQueue[trimEnd + 1].pts();
4803 } else {
4804 // We have no next buffer. Compute the PTS of the frame following
4805 // the last frame in this buffer by computing the duration of of
4806 // this frame in media time units and adding it to the PTS of the
4807 // buffer.
4808 int64_t frameCount = mTimedBufferQueue[trimEnd].buffer()->size()
4809 / mCblk->frameSize;
4810
4811 if (!mMediaTimeToSampleTransform.doReverseTransform(frameCount,
4812 &bufEnd)) {
4813 ALOGE("Failed to convert frame count of %lld to media time"
4814 " duration" " (scale factor %d/%u) in %s",
4815 frameCount,
4816 mMediaTimeToSampleTransform.a_to_b_numer,
4817 mMediaTimeToSampleTransform.a_to_b_denom,
4818 __PRETTY_FUNCTION__);
4819 break;
4820 }
4821 bufEnd += mTimedBufferQueue[trimEnd].pts();
John Grossman9fbdee12012-03-26 17:51:46 -07004822 }
John Grossman9fbdee12012-03-26 17:51:46 -07004823
4824 if (bufEnd > mediaTimeNow)
4825 break;
4826
4827 // Is the buffer we want to use in the middle of a mix operation right
4828 // now? If so, don't actually trim it. Just wait for the releaseBuffer
4829 // from the mixer which should be coming back shortly.
John Grossman1c345192012-03-27 14:00:17 -07004830 if (!trimEnd && mQueueHeadInFlight) {
John Grossman9fbdee12012-03-26 17:51:46 -07004831 mTrimQueueHeadOnRelease = true;
4832 }
John Grossman4ff14ba2012-02-08 16:37:41 -08004833 }
4834
John Grossman9fbdee12012-03-26 17:51:46 -07004835 size_t trimStart = mTrimQueueHeadOnRelease ? 1 : 0;
John Grossman1c345192012-03-27 14:00:17 -07004836 if (trimStart < trimEnd) {
4837 // Update the bookkeeping for framesReady()
4838 for (size_t i = trimStart; i < trimEnd; ++i) {
4839 updateFramesPendingAfterTrim_l(mTimedBufferQueue[i], "trim");
4840 }
4841
4842 // Now actually remove the buffers from the queue.
4843 mTimedBufferQueue.removeItemsAt(trimStart, trimEnd);
John Grossman4ff14ba2012-02-08 16:37:41 -08004844 }
4845}
4846
John Grossman1c345192012-03-27 14:00:17 -07004847void AudioFlinger::PlaybackThread::TimedTrack::trimTimedBufferQueueHead_l(
4848 const char* logTag) {
John Grossmand3030da2012-04-12 11:56:36 -07004849 ALOG_ASSERT(mTimedBufferQueue.size() > 0,
4850 "%s called (reason \"%s\"), but timed buffer queue has no"
4851 " elements to trim.", __FUNCTION__, logTag);
John Grossman1c345192012-03-27 14:00:17 -07004852
4853 updateFramesPendingAfterTrim_l(mTimedBufferQueue[0], logTag);
4854 mTimedBufferQueue.removeAt(0);
4855}
4856
4857void AudioFlinger::PlaybackThread::TimedTrack::updateFramesPendingAfterTrim_l(
4858 const TimedBuffer& buf,
4859 const char* logTag) {
4860 uint32_t bufBytes = buf.buffer()->size();
4861 uint32_t consumedAlready = buf.position();
4862
Eric Laurentb388e532012-04-14 13:32:48 -07004863 ALOG_ASSERT(consumedAlready <= bufBytes,
John Grossmand3030da2012-04-12 11:56:36 -07004864 "Bad bookkeeping while updating frames pending. Timed buffer is"
4865 " only %u bytes long, but claims to have consumed %u"
4866 " bytes. (update reason: \"%s\")",
Eric Laurentb388e532012-04-14 13:32:48 -07004867 bufBytes, consumedAlready, logTag);
John Grossman1c345192012-03-27 14:00:17 -07004868
4869 uint32_t bufFrames = (bufBytes - consumedAlready) / mCblk->frameSize;
John Grossmand3030da2012-04-12 11:56:36 -07004870 ALOG_ASSERT(mFramesPendingInQueue >= bufFrames,
4871 "Bad bookkeeping while updating frames pending. Should have at"
4872 " least %u queued frames, but we think we have only %u. (update"
4873 " reason: \"%s\")",
4874 bufFrames, mFramesPendingInQueue, logTag);
John Grossman1c345192012-03-27 14:00:17 -07004875
4876 mFramesPendingInQueue -= bufFrames;
4877}
4878
John Grossman4ff14ba2012-02-08 16:37:41 -08004879status_t AudioFlinger::PlaybackThread::TimedTrack::queueTimedBuffer(
4880 const sp<IMemory>& buffer, int64_t pts) {
4881
4882 {
4883 Mutex::Autolock mttLock(mMediaTimeTransformLock);
4884 if (!mMediaTimeTransformValid)
4885 return INVALID_OPERATION;
4886 }
4887
4888 Mutex::Autolock _l(mTimedBufferQueueLock);
4889
John Grossman1c345192012-03-27 14:00:17 -07004890 uint32_t bufFrames = buffer->size() / mCblk->frameSize;
4891 mFramesPendingInQueue += bufFrames;
John Grossman4ff14ba2012-02-08 16:37:41 -08004892 mTimedBufferQueue.add(TimedBuffer(buffer, pts));
4893
4894 return NO_ERROR;
4895}
4896
4897status_t AudioFlinger::PlaybackThread::TimedTrack::setMediaTimeTransform(
4898 const LinearTransform& xform, TimedAudioTrack::TargetTimeline target) {
4899
John Grossman1c345192012-03-27 14:00:17 -07004900 ALOGVV("setMediaTimeTransform az=%lld bz=%lld n=%d d=%u tgt=%d",
4901 xform.a_zero, xform.b_zero, xform.a_to_b_numer, xform.a_to_b_denom,
4902 target);
John Grossman4ff14ba2012-02-08 16:37:41 -08004903
4904 if (!(target == TimedAudioTrack::LOCAL_TIME ||
4905 target == TimedAudioTrack::COMMON_TIME)) {
4906 return BAD_VALUE;
4907 }
4908
4909 Mutex::Autolock lock(mMediaTimeTransformLock);
4910 mMediaTimeTransform = xform;
4911 mMediaTimeTransformTarget = target;
4912 mMediaTimeTransformValid = true;
4913
4914 return NO_ERROR;
4915}
4916
4917#define min(a, b) ((a) < (b) ? (a) : (b))
4918
4919// implementation of getNextBuffer for tracks whose buffers have timestamps
4920status_t AudioFlinger::PlaybackThread::TimedTrack::getNextBuffer(
4921 AudioBufferProvider::Buffer* buffer, int64_t pts)
4922{
4923 if (pts == AudioBufferProvider::kInvalidPTS) {
4924 buffer->raw = 0;
4925 buffer->frameCount = 0;
John Grossman8d314b72012-04-19 12:08:17 -07004926 mTimedAudioOutputOnTime = false;
John Grossman4ff14ba2012-02-08 16:37:41 -08004927 return INVALID_OPERATION;
4928 }
4929
John Grossman4ff14ba2012-02-08 16:37:41 -08004930 Mutex::Autolock _l(mTimedBufferQueueLock);
4931
John Grossman9fbdee12012-03-26 17:51:46 -07004932 ALOG_ASSERT(!mQueueHeadInFlight,
4933 "getNextBuffer called without releaseBuffer!");
4934
John Grossman4ff14ba2012-02-08 16:37:41 -08004935 while (true) {
4936
4937 // if we have no timed buffers, then fail
4938 if (mTimedBufferQueue.isEmpty()) {
4939 buffer->raw = 0;
4940 buffer->frameCount = 0;
4941 return NOT_ENOUGH_DATA;
4942 }
4943
4944 TimedBuffer& head = mTimedBufferQueue.editItemAt(0);
4945
4946 // calculate the PTS of the head of the timed buffer queue expressed in
4947 // local time
4948 int64_t headLocalPTS;
4949 {
4950 Mutex::Autolock mttLock(mMediaTimeTransformLock);
4951
Glenn Kasten5798d4e2012-03-08 12:18:35 -08004952 ALOG_ASSERT(mMediaTimeTransformValid, "media time transform invalid");
John Grossman4ff14ba2012-02-08 16:37:41 -08004953
4954 if (mMediaTimeTransform.a_to_b_denom == 0) {
4955 // the transform represents a pause, so yield silence
John Grossman9fbdee12012-03-26 17:51:46 -07004956 timedYieldSilence_l(buffer->frameCount, buffer);
John Grossman4ff14ba2012-02-08 16:37:41 -08004957 return NO_ERROR;
4958 }
4959
4960 int64_t transformedPTS;
4961 if (!mMediaTimeTransform.doForwardTransform(head.pts(),
4962 &transformedPTS)) {
4963 // the transform failed. this shouldn't happen, but if it does
4964 // then just drop this buffer
4965 ALOGW("timedGetNextBuffer transform failed");
4966 buffer->raw = 0;
4967 buffer->frameCount = 0;
John Grossman1c345192012-03-27 14:00:17 -07004968 trimTimedBufferQueueHead_l("getNextBuffer; no transform");
John Grossman4ff14ba2012-02-08 16:37:41 -08004969 return NO_ERROR;
4970 }
4971
4972 if (mMediaTimeTransformTarget == TimedAudioTrack::COMMON_TIME) {
4973 if (OK != mCCHelper.commonTimeToLocalTime(transformedPTS,
4974 &headLocalPTS)) {
4975 buffer->raw = 0;
4976 buffer->frameCount = 0;
4977 return INVALID_OPERATION;
4978 }
4979 } else {
4980 headLocalPTS = transformedPTS;
4981 }
4982 }
4983
4984 // adjust the head buffer's PTS to reflect the portion of the head buffer
4985 // that has already been consumed
4986 int64_t effectivePTS = headLocalPTS +
4987 ((head.position() / mCblk->frameSize) * mLocalTimeFreq / sampleRate());
4988
4989 // Calculate the delta in samples between the head of the input buffer
4990 // queue and the start of the next output buffer that will be written.
4991 // If the transformation fails because of over or underflow, it means
4992 // that the sample's position in the output stream is so far out of
4993 // whack that it should just be dropped.
4994 int64_t sampleDelta;
4995 if (llabs(effectivePTS - pts) >= (static_cast<int64_t>(1) << 31)) {
4996 ALOGV("*** head buffer is too far from PTS: dropped buffer");
John Grossman1c345192012-03-27 14:00:17 -07004997 trimTimedBufferQueueHead_l("getNextBuffer, buf pts too far from"
4998 " mix");
John Grossman4ff14ba2012-02-08 16:37:41 -08004999 continue;
5000 }
5001 if (!mLocalTimeToSampleTransform.doForwardTransform(
5002 (effectivePTS - pts) << 32, &sampleDelta)) {
John Grossmand3030da2012-04-12 11:56:36 -07005003 ALOGV("*** too late during sample rate transform: dropped buffer");
John Grossman1c345192012-03-27 14:00:17 -07005004 trimTimedBufferQueueHead_l("getNextBuffer, bad local to sample");
John Grossman4ff14ba2012-02-08 16:37:41 -08005005 continue;
5006 }
5007
John Grossman1c345192012-03-27 14:00:17 -07005008 ALOGVV("*** getNextBuffer head.pts=%lld head.pos=%d pts=%lld"
5009 " sampleDelta=[%d.%08x]",
5010 head.pts(), head.position(), pts,
5011 static_cast<int32_t>((sampleDelta >= 0 ? 0 : 1)
5012 + (sampleDelta >> 32)),
5013 static_cast<uint32_t>(sampleDelta & 0xFFFFFFFF));
John Grossman4ff14ba2012-02-08 16:37:41 -08005014
5015 // if the delta between the ideal placement for the next input sample and
5016 // the current output position is within this threshold, then we will
5017 // concatenate the next input samples to the previous output
5018 const int64_t kSampleContinuityThreshold =
John Grossman8d314b72012-04-19 12:08:17 -07005019 (static_cast<int64_t>(sampleRate()) << 32) / 250;
John Grossman4ff14ba2012-02-08 16:37:41 -08005020
5021 // if this is the first buffer of audio that we're emitting from this track
5022 // then it should be almost exactly on time.
5023 const int64_t kSampleStartupThreshold = 1LL << 32;
5024
5025 if ((mTimedAudioOutputOnTime && llabs(sampleDelta) <= kSampleContinuityThreshold) ||
John Grossman8d314b72012-04-19 12:08:17 -07005026 (!mTimedAudioOutputOnTime && llabs(sampleDelta) <= kSampleStartupThreshold)) {
John Grossman4ff14ba2012-02-08 16:37:41 -08005027 // the next input is close enough to being on time, so concatenate it
5028 // with the last output
John Grossman9fbdee12012-03-26 17:51:46 -07005029 timedYieldSamples_l(buffer);
John Grossman4ff14ba2012-02-08 16:37:41 -08005030
John Grossman1c345192012-03-27 14:00:17 -07005031 ALOGVV("*** on time: head.pos=%d frameCount=%u",
5032 head.position(), buffer->frameCount);
John Grossman4ff14ba2012-02-08 16:37:41 -08005033 return NO_ERROR;
John Grossman8d314b72012-04-19 12:08:17 -07005034 }
5035
5036 // Looks like our output is not on time. Reset our on timed status.
5037 // Next time we mix samples from our input queue, then should be within
5038 // the StartupThreshold.
5039 mTimedAudioOutputOnTime = false;
5040 if (sampleDelta > 0) {
John Grossman4ff14ba2012-02-08 16:37:41 -08005041 // the gap between the current output position and the proper start of
5042 // the next input sample is too big, so fill it with silence
5043 uint32_t framesUntilNextInput = (sampleDelta + 0x80000000) >> 32;
5044
John Grossman9fbdee12012-03-26 17:51:46 -07005045 timedYieldSilence_l(framesUntilNextInput, buffer);
John Grossman4ff14ba2012-02-08 16:37:41 -08005046 ALOGV("*** silence: frameCount=%u", buffer->frameCount);
5047 return NO_ERROR;
5048 } else {
5049 // the next input sample is late
5050 uint32_t lateFrames = static_cast<uint32_t>(-((sampleDelta + 0x80000000) >> 32));
5051 size_t onTimeSamplePosition =
5052 head.position() + lateFrames * mCblk->frameSize;
5053
5054 if (onTimeSamplePosition > head.buffer()->size()) {
5055 // all the remaining samples in the head are too late, so
5056 // drop it and move on
5057 ALOGV("*** too late: dropped buffer");
John Grossman1c345192012-03-27 14:00:17 -07005058 trimTimedBufferQueueHead_l("getNextBuffer, dropped late buffer");
John Grossman4ff14ba2012-02-08 16:37:41 -08005059 continue;
5060 } else {
5061 // skip over the late samples
5062 head.setPosition(onTimeSamplePosition);
5063
5064 // yield the available samples
John Grossman9fbdee12012-03-26 17:51:46 -07005065 timedYieldSamples_l(buffer);
John Grossman4ff14ba2012-02-08 16:37:41 -08005066
5067 ALOGV("*** late: head.pos=%d frameCount=%u", head.position(), buffer->frameCount);
5068 return NO_ERROR;
5069 }
5070 }
5071 }
5072}
5073
5074// Yield samples from the timed buffer queue head up to the given output
5075// buffer's capacity.
5076//
5077// Caller must hold mTimedBufferQueueLock
John Grossman9fbdee12012-03-26 17:51:46 -07005078void AudioFlinger::PlaybackThread::TimedTrack::timedYieldSamples_l(
John Grossman4ff14ba2012-02-08 16:37:41 -08005079 AudioBufferProvider::Buffer* buffer) {
5080
5081 const TimedBuffer& head = mTimedBufferQueue[0];
5082
5083 buffer->raw = (static_cast<uint8_t*>(head.buffer()->pointer()) +
5084 head.position());
5085
5086 uint32_t framesLeftInHead = ((head.buffer()->size() - head.position()) /
5087 mCblk->frameSize);
5088 size_t framesRequested = buffer->frameCount;
5089 buffer->frameCount = min(framesLeftInHead, framesRequested);
5090
John Grossman9fbdee12012-03-26 17:51:46 -07005091 mQueueHeadInFlight = true;
John Grossman4ff14ba2012-02-08 16:37:41 -08005092 mTimedAudioOutputOnTime = true;
5093}
5094
5095// Yield samples of silence up to the given output buffer's capacity
5096//
5097// Caller must hold mTimedBufferQueueLock
John Grossman9fbdee12012-03-26 17:51:46 -07005098void AudioFlinger::PlaybackThread::TimedTrack::timedYieldSilence_l(
John Grossman4ff14ba2012-02-08 16:37:41 -08005099 uint32_t numFrames, AudioBufferProvider::Buffer* buffer) {
5100
5101 // lazily allocate a buffer filled with silence
5102 if (mTimedSilenceBufferSize < numFrames * mCblk->frameSize) {
5103 delete [] mTimedSilenceBuffer;
5104 mTimedSilenceBufferSize = numFrames * mCblk->frameSize;
5105 mTimedSilenceBuffer = new uint8_t[mTimedSilenceBufferSize];
5106 memset(mTimedSilenceBuffer, 0, mTimedSilenceBufferSize);
5107 }
5108
5109 buffer->raw = mTimedSilenceBuffer;
5110 size_t framesRequested = buffer->frameCount;
5111 buffer->frameCount = min(numFrames, framesRequested);
5112
5113 mTimedAudioOutputOnTime = false;
5114}
5115
Glenn Kasten01c4ebf2012-02-22 10:47:35 -08005116// AudioBufferProvider interface
John Grossman4ff14ba2012-02-08 16:37:41 -08005117void AudioFlinger::PlaybackThread::TimedTrack::releaseBuffer(
5118 AudioBufferProvider::Buffer* buffer) {
5119
5120 Mutex::Autolock _l(mTimedBufferQueueLock);
5121
John Grossmanfe5b3ba2012-02-12 17:51:21 -08005122 // If the buffer which was just released is part of the buffer at the head
5123 // of the queue, be sure to update the amt of the buffer which has been
5124 // consumed. If the buffer being returned is not part of the head of the
5125 // queue, its either because the buffer is part of the silence buffer, or
5126 // because the head of the timed queue was trimmed after the mixer called
5127 // getNextBuffer but before the mixer called releaseBuffer.
John Grossman9fbdee12012-03-26 17:51:46 -07005128 if (buffer->raw == mTimedSilenceBuffer) {
5129 ALOG_ASSERT(!mQueueHeadInFlight,
5130 "Queue head in flight during release of silence buffer!");
5131 goto done;
5132 }
5133
5134 ALOG_ASSERT(mQueueHeadInFlight,
5135 "TimedTrack::releaseBuffer of non-silence buffer, but no queue"
5136 " head in flight.");
5137
5138 if (mTimedBufferQueue.size()) {
John Grossman4ff14ba2012-02-08 16:37:41 -08005139 TimedBuffer& head = mTimedBufferQueue.editItemAt(0);
John Grossmanfe5b3ba2012-02-12 17:51:21 -08005140
5141 void* start = head.buffer()->pointer();
John Grossman9fbdee12012-03-26 17:51:46 -07005142 void* end = reinterpret_cast<void*>(
5143 reinterpret_cast<uint8_t*>(head.buffer()->pointer())
5144 + head.buffer()->size());
John Grossmanfe5b3ba2012-02-12 17:51:21 -08005145
John Grossman9fbdee12012-03-26 17:51:46 -07005146 ALOG_ASSERT((buffer->raw >= start) && (buffer->raw < end),
5147 "released buffer not within the head of the timed buffer"
5148 " queue; qHead = [%p, %p], released buffer = %p",
5149 start, end, buffer->raw);
5150
5151 head.setPosition(head.position() +
5152 (buffer->frameCount * mCblk->frameSize));
5153 mQueueHeadInFlight = false;
5154
John Grossman1c345192012-03-27 14:00:17 -07005155 ALOG_ASSERT(mFramesPendingInQueue >= buffer->frameCount,
5156 "Bad bookkeeping during releaseBuffer! Should have at"
5157 " least %u queued frames, but we think we have only %u",
5158 buffer->frameCount, mFramesPendingInQueue);
5159
5160 mFramesPendingInQueue -= buffer->frameCount;
5161
John Grossman9fbdee12012-03-26 17:51:46 -07005162 if ((static_cast<size_t>(head.position()) >= head.buffer()->size())
5163 || mTrimQueueHeadOnRelease) {
John Grossman1c345192012-03-27 14:00:17 -07005164 trimTimedBufferQueueHead_l("releaseBuffer");
John Grossman9fbdee12012-03-26 17:51:46 -07005165 mTrimQueueHeadOnRelease = false;
John Grossman4ff14ba2012-02-08 16:37:41 -08005166 }
John Grossman9fbdee12012-03-26 17:51:46 -07005167 } else {
5168 LOG_FATAL("TimedTrack::releaseBuffer of non-silence buffer with no"
5169 " buffers in the timed buffer queue");
John Grossman4ff14ba2012-02-08 16:37:41 -08005170 }
5171
John Grossman9fbdee12012-03-26 17:51:46 -07005172done:
John Grossman4ff14ba2012-02-08 16:37:41 -08005173 buffer->raw = 0;
5174 buffer->frameCount = 0;
5175}
5176
Glenn Kasten288ed212012-04-25 17:52:27 -07005177size_t AudioFlinger::PlaybackThread::TimedTrack::framesReady() const {
John Grossman4ff14ba2012-02-08 16:37:41 -08005178 Mutex::Autolock _l(mTimedBufferQueueLock);
John Grossman1c345192012-03-27 14:00:17 -07005179 return mFramesPendingInQueue;
John Grossman4ff14ba2012-02-08 16:37:41 -08005180}
5181
5182AudioFlinger::PlaybackThread::TimedTrack::TimedBuffer::TimedBuffer()
5183 : mPTS(0), mPosition(0) {}
5184
5185AudioFlinger::PlaybackThread::TimedTrack::TimedBuffer::TimedBuffer(
5186 const sp<IMemory>& buffer, int64_t pts)
5187 : mBuffer(buffer), mPTS(pts), mPosition(0) {}
5188
Mathias Agopian65ab4712010-07-14 17:59:35 -07005189// ----------------------------------------------------------------------------
5190
5191// RecordTrack constructor must be called with AudioFlinger::mLock held
5192AudioFlinger::RecordThread::RecordTrack::RecordTrack(
Glenn Kasten9eaa5572012-01-20 13:32:16 -08005193 RecordThread *thread,
Mathias Agopian65ab4712010-07-14 17:59:35 -07005194 const sp<Client>& client,
5195 uint32_t sampleRate,
Glenn Kasten58f30212012-01-12 12:27:51 -08005196 audio_format_t format,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07005197 uint32_t channelMask,
Mathias Agopian65ab4712010-07-14 17:59:35 -07005198 int frameCount,
Mathias Agopian65ab4712010-07-14 17:59:35 -07005199 int sessionId)
5200 : TrackBase(thread, client, sampleRate, format,
Glenn Kasten5cf034d2012-02-21 10:35:56 -08005201 channelMask, frameCount, 0 /*sharedBuffer*/, sessionId),
Mathias Agopian65ab4712010-07-14 17:59:35 -07005202 mOverflow(false)
5203{
5204 if (mCblk != NULL) {
Glenn Kastene53b9ea2012-03-12 16:29:55 -07005205 ALOGV("RecordTrack constructor, size %d", (int)mBufferEnd - (int)mBuffer);
5206 if (format == AUDIO_FORMAT_PCM_16_BIT) {
5207 mCblk->frameSize = mChannelCount * sizeof(int16_t);
5208 } else if (format == AUDIO_FORMAT_PCM_8_BIT) {
5209 mCblk->frameSize = mChannelCount * sizeof(int8_t);
5210 } else {
5211 mCblk->frameSize = sizeof(int8_t);
5212 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07005213 }
5214}
5215
5216AudioFlinger::RecordThread::RecordTrack::~RecordTrack()
5217{
5218 sp<ThreadBase> thread = mThread.promote();
5219 if (thread != 0) {
5220 AudioSystem::releaseInput(thread->id());
5221 }
5222}
5223
Glenn Kasten01c4ebf2012-02-22 10:47:35 -08005224// AudioBufferProvider interface
John Grossman4ff14ba2012-02-08 16:37:41 -08005225status_t AudioFlinger::RecordThread::RecordTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer, int64_t pts)
Mathias Agopian65ab4712010-07-14 17:59:35 -07005226{
5227 audio_track_cblk_t* cblk = this->cblk();
5228 uint32_t framesAvail;
5229 uint32_t framesReq = buffer->frameCount;
5230
Glenn Kastene53b9ea2012-03-12 16:29:55 -07005231 // Check if last stepServer failed, try to step now
Glenn Kasten5cf034d2012-02-21 10:35:56 -08005232 if (mStepServerFailed) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07005233 if (!step()) goto getNextBuffer_exit;
Steve Block3856b092011-10-20 11:56:00 +01005234 ALOGV("stepServer recovered");
Glenn Kasten5cf034d2012-02-21 10:35:56 -08005235 mStepServerFailed = false;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005236 }
5237
5238 framesAvail = cblk->framesAvailable_l();
5239
Glenn Kastenf6b16782011-12-15 09:51:17 -08005240 if (CC_LIKELY(framesAvail)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07005241 uint32_t s = cblk->server;
5242 uint32_t bufferEnd = cblk->serverBase + cblk->frameCount;
5243
5244 if (framesReq > framesAvail) {
5245 framesReq = framesAvail;
5246 }
Marco Nelissena1472d92012-03-30 14:36:54 -07005247 if (framesReq > bufferEnd - s) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07005248 framesReq = bufferEnd - s;
5249 }
5250
5251 buffer->raw = getBuffer(s, framesReq);
Glenn Kastene0feee32011-12-13 11:53:26 -08005252 if (buffer->raw == NULL) goto getNextBuffer_exit;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005253
5254 buffer->frameCount = framesReq;
5255 return NO_ERROR;
5256 }
5257
5258getNextBuffer_exit:
Glenn Kastene0feee32011-12-13 11:53:26 -08005259 buffer->raw = NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005260 buffer->frameCount = 0;
5261 return NOT_ENOUGH_DATA;
5262}
5263
Glenn Kasten3acbd052012-02-28 10:39:56 -08005264status_t AudioFlinger::RecordThread::RecordTrack::start(AudioSystem::sync_event_t event,
Eric Laurenta011e352012-03-29 15:51:43 -07005265 int triggerSession)
Mathias Agopian65ab4712010-07-14 17:59:35 -07005266{
5267 sp<ThreadBase> thread = mThread.promote();
5268 if (thread != 0) {
5269 RecordThread *recordThread = (RecordThread *)thread.get();
Glenn Kasten3acbd052012-02-28 10:39:56 -08005270 return recordThread->start(this, event, triggerSession);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005271 } else {
5272 return BAD_VALUE;
5273 }
5274}
5275
5276void AudioFlinger::RecordThread::RecordTrack::stop()
5277{
5278 sp<ThreadBase> thread = mThread.promote();
5279 if (thread != 0) {
5280 RecordThread *recordThread = (RecordThread *)thread.get();
5281 recordThread->stop(this);
Eric Laurent38ccae22011-03-28 18:37:07 -07005282 TrackBase::reset();
Glenn Kasten17a736c2012-02-14 08:52:15 -08005283 // Force overrun condition to avoid false overrun callback until first data is
Eric Laurent38ccae22011-03-28 18:37:07 -07005284 // read from buffer
5285 android_atomic_or(CBLK_UNDERRUN_ON, &mCblk->flags);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005286 }
5287}
5288
5289void AudioFlinger::RecordThread::RecordTrack::dump(char* buffer, size_t size)
5290{
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07005291 snprintf(buffer, size, " %05d %03u 0x%08x %05d %04u %01d %05u %08x %08x\n",
Glenn Kasten44deb052012-02-05 18:09:08 -08005292 (mClient == 0) ? getpid_cached : mClient->pid(),
Mathias Agopian65ab4712010-07-14 17:59:35 -07005293 mFormat,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07005294 mChannelMask,
Mathias Agopian65ab4712010-07-14 17:59:35 -07005295 mSessionId,
5296 mFrameCount,
5297 mState,
5298 mCblk->sampleRate,
5299 mCblk->server,
5300 mCblk->user);
5301}
5302
5303
5304// ----------------------------------------------------------------------------
5305
5306AudioFlinger::PlaybackThread::OutputTrack::OutputTrack(
Glenn Kasten9eaa5572012-01-20 13:32:16 -08005307 PlaybackThread *playbackThread,
Mathias Agopian65ab4712010-07-14 17:59:35 -07005308 DuplicatingThread *sourceThread,
5309 uint32_t sampleRate,
Glenn Kasten58f30212012-01-12 12:27:51 -08005310 audio_format_t format,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07005311 uint32_t channelMask,
Mathias Agopian65ab4712010-07-14 17:59:35 -07005312 int frameCount)
Glenn Kasten73d22752012-03-19 13:38:30 -07005313 : Track(playbackThread, NULL, AUDIO_STREAM_CNT, sampleRate, format, channelMask, frameCount,
5314 NULL, 0, IAudioFlinger::TRACK_DEFAULT),
Mathias Agopian65ab4712010-07-14 17:59:35 -07005315 mActive(false), mSourceThread(sourceThread)
5316{
5317
Mathias Agopian65ab4712010-07-14 17:59:35 -07005318 if (mCblk != NULL) {
5319 mCblk->flags |= CBLK_DIRECTION_OUT;
5320 mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005321 mOutBuffer.frameCount = 0;
5322 playbackThread->mTracks.add(this);
Steve Block3856b092011-10-20 11:56:00 +01005323 ALOGV("OutputTrack constructor mCblk %p, mBuffer %p, mCblk->buffers %p, " \
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07005324 "mCblk->frameCount %d, mCblk->sampleRate %d, mChannelMask 0x%08x mBufferEnd %p",
5325 mCblk, mBuffer, mCblk->buffers,
5326 mCblk->frameCount, mCblk->sampleRate, mChannelMask, mBufferEnd);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005327 } else {
Steve Block5ff1dd52012-01-05 23:22:43 +00005328 ALOGW("Error creating output track on thread %p", playbackThread);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005329 }
5330}
5331
5332AudioFlinger::PlaybackThread::OutputTrack::~OutputTrack()
5333{
5334 clearBufferQueue();
5335}
5336
Glenn Kasten3acbd052012-02-28 10:39:56 -08005337status_t AudioFlinger::PlaybackThread::OutputTrack::start(AudioSystem::sync_event_t event,
Eric Laurenta011e352012-03-29 15:51:43 -07005338 int triggerSession)
Mathias Agopian65ab4712010-07-14 17:59:35 -07005339{
Glenn Kasten3acbd052012-02-28 10:39:56 -08005340 status_t status = Track::start(event, triggerSession);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005341 if (status != NO_ERROR) {
5342 return status;
5343 }
5344
5345 mActive = true;
5346 mRetryCount = 127;
5347 return status;
5348}
5349
5350void AudioFlinger::PlaybackThread::OutputTrack::stop()
5351{
5352 Track::stop();
5353 clearBufferQueue();
5354 mOutBuffer.frameCount = 0;
5355 mActive = false;
5356}
5357
5358bool AudioFlinger::PlaybackThread::OutputTrack::write(int16_t* data, uint32_t frames)
5359{
5360 Buffer *pInBuffer;
5361 Buffer inBuffer;
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07005362 uint32_t channelCount = mChannelCount;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005363 bool outputBufferFull = false;
5364 inBuffer.frameCount = frames;
5365 inBuffer.i16 = data;
5366
5367 uint32_t waitTimeLeftMs = mSourceThread->waitTimeMs();
5368
5369 if (!mActive && frames != 0) {
Glenn Kasten3acbd052012-02-28 10:39:56 -08005370 start();
Mathias Agopian65ab4712010-07-14 17:59:35 -07005371 sp<ThreadBase> thread = mThread.promote();
5372 if (thread != 0) {
5373 MixerThread *mixerThread = (MixerThread *)thread.get();
5374 if (mCblk->frameCount > frames){
5375 if (mBufferQueue.size() < kMaxOverFlowBuffers) {
5376 uint32_t startFrames = (mCblk->frameCount - frames);
5377 pInBuffer = new Buffer;
5378 pInBuffer->mBuffer = new int16_t[startFrames * channelCount];
5379 pInBuffer->frameCount = startFrames;
5380 pInBuffer->i16 = pInBuffer->mBuffer;
5381 memset(pInBuffer->raw, 0, startFrames * channelCount * sizeof(int16_t));
5382 mBufferQueue.add(pInBuffer);
5383 } else {
Steve Block5ff1dd52012-01-05 23:22:43 +00005384 ALOGW ("OutputTrack::write() %p no more buffers in queue", this);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005385 }
5386 }
5387 }
5388 }
5389
5390 while (waitTimeLeftMs) {
5391 // First write pending buffers, then new data
5392 if (mBufferQueue.size()) {
5393 pInBuffer = mBufferQueue.itemAt(0);
5394 } else {
5395 pInBuffer = &inBuffer;
5396 }
5397
5398 if (pInBuffer->frameCount == 0) {
5399 break;
5400 }
5401
5402 if (mOutBuffer.frameCount == 0) {
5403 mOutBuffer.frameCount = pInBuffer->frameCount;
5404 nsecs_t startTime = systemTime();
Glenn Kasten335787f2012-01-20 17:00:00 -08005405 if (obtainBuffer(&mOutBuffer, waitTimeLeftMs) == (status_t)NO_MORE_BUFFERS) {
Steve Block3856b092011-10-20 11:56:00 +01005406 ALOGV ("OutputTrack::write() %p thread %p no more output buffers", this, mThread.unsafe_get());
Mathias Agopian65ab4712010-07-14 17:59:35 -07005407 outputBufferFull = true;
5408 break;
5409 }
5410 uint32_t waitTimeMs = (uint32_t)ns2ms(systemTime() - startTime);
5411 if (waitTimeLeftMs >= waitTimeMs) {
5412 waitTimeLeftMs -= waitTimeMs;
5413 } else {
5414 waitTimeLeftMs = 0;
5415 }
5416 }
5417
5418 uint32_t outFrames = pInBuffer->frameCount > mOutBuffer.frameCount ? mOutBuffer.frameCount : pInBuffer->frameCount;
5419 memcpy(mOutBuffer.raw, pInBuffer->raw, outFrames * channelCount * sizeof(int16_t));
5420 mCblk->stepUser(outFrames);
5421 pInBuffer->frameCount -= outFrames;
5422 pInBuffer->i16 += outFrames * channelCount;
5423 mOutBuffer.frameCount -= outFrames;
5424 mOutBuffer.i16 += outFrames * channelCount;
5425
5426 if (pInBuffer->frameCount == 0) {
5427 if (mBufferQueue.size()) {
5428 mBufferQueue.removeAt(0);
5429 delete [] pInBuffer->mBuffer;
5430 delete pInBuffer;
Steve Block3856b092011-10-20 11:56:00 +01005431 ALOGV("OutputTrack::write() %p thread %p released overflow buffer %d", this, mThread.unsafe_get(), mBufferQueue.size());
Mathias Agopian65ab4712010-07-14 17:59:35 -07005432 } else {
5433 break;
5434 }
5435 }
5436 }
5437
5438 // If we could not write all frames, allocate a buffer and queue it for next time.
5439 if (inBuffer.frameCount) {
5440 sp<ThreadBase> thread = mThread.promote();
5441 if (thread != 0 && !thread->standby()) {
5442 if (mBufferQueue.size() < kMaxOverFlowBuffers) {
5443 pInBuffer = new Buffer;
5444 pInBuffer->mBuffer = new int16_t[inBuffer.frameCount * channelCount];
5445 pInBuffer->frameCount = inBuffer.frameCount;
5446 pInBuffer->i16 = pInBuffer->mBuffer;
5447 memcpy(pInBuffer->raw, inBuffer.raw, inBuffer.frameCount * channelCount * sizeof(int16_t));
5448 mBufferQueue.add(pInBuffer);
Steve Block3856b092011-10-20 11:56:00 +01005449 ALOGV("OutputTrack::write() %p thread %p adding overflow buffer %d", this, mThread.unsafe_get(), mBufferQueue.size());
Mathias Agopian65ab4712010-07-14 17:59:35 -07005450 } else {
Steve Block5ff1dd52012-01-05 23:22:43 +00005451 ALOGW("OutputTrack::write() %p thread %p no more overflow buffers", mThread.unsafe_get(), this);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005452 }
5453 }
5454 }
5455
5456 // Calling write() with a 0 length buffer, means that no more data will be written:
5457 // If no more buffers are pending, fill output track buffer to make sure it is started
5458 // by output mixer.
5459 if (frames == 0 && mBufferQueue.size() == 0) {
5460 if (mCblk->user < mCblk->frameCount) {
5461 frames = mCblk->frameCount - mCblk->user;
5462 pInBuffer = new Buffer;
5463 pInBuffer->mBuffer = new int16_t[frames * channelCount];
5464 pInBuffer->frameCount = frames;
5465 pInBuffer->i16 = pInBuffer->mBuffer;
5466 memset(pInBuffer->raw, 0, frames * channelCount * sizeof(int16_t));
5467 mBufferQueue.add(pInBuffer);
5468 } else if (mActive) {
5469 stop();
5470 }
5471 }
5472
5473 return outputBufferFull;
5474}
5475
5476status_t AudioFlinger::PlaybackThread::OutputTrack::obtainBuffer(AudioBufferProvider::Buffer* buffer, uint32_t waitTimeMs)
5477{
5478 int active;
5479 status_t result;
5480 audio_track_cblk_t* cblk = mCblk;
5481 uint32_t framesReq = buffer->frameCount;
5482
Steve Block3856b092011-10-20 11:56:00 +01005483// ALOGV("OutputTrack::obtainBuffer user %d, server %d", cblk->user, cblk->server);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005484 buffer->frameCount = 0;
5485
5486 uint32_t framesAvail = cblk->framesAvailable();
5487
5488
5489 if (framesAvail == 0) {
5490 Mutex::Autolock _l(cblk->lock);
5491 goto start_loop_here;
5492 while (framesAvail == 0) {
5493 active = mActive;
Glenn Kastenf6b16782011-12-15 09:51:17 -08005494 if (CC_UNLIKELY(!active)) {
Steve Block3856b092011-10-20 11:56:00 +01005495 ALOGV("Not active and NO_MORE_BUFFERS");
Glenn Kasten335787f2012-01-20 17:00:00 -08005496 return NO_MORE_BUFFERS;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005497 }
5498 result = cblk->cv.waitRelative(cblk->lock, milliseconds(waitTimeMs));
5499 if (result != NO_ERROR) {
Glenn Kasten335787f2012-01-20 17:00:00 -08005500 return NO_MORE_BUFFERS;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005501 }
5502 // read the server count again
5503 start_loop_here:
5504 framesAvail = cblk->framesAvailable_l();
5505 }
5506 }
5507
5508// if (framesAvail < framesReq) {
Glenn Kasten335787f2012-01-20 17:00:00 -08005509// return NO_MORE_BUFFERS;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005510// }
5511
5512 if (framesReq > framesAvail) {
5513 framesReq = framesAvail;
5514 }
5515
5516 uint32_t u = cblk->user;
5517 uint32_t bufferEnd = cblk->userBase + cblk->frameCount;
5518
Marco Nelissena1472d92012-03-30 14:36:54 -07005519 if (framesReq > bufferEnd - u) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07005520 framesReq = bufferEnd - u;
5521 }
5522
5523 buffer->frameCount = framesReq;
5524 buffer->raw = (void *)cblk->buffer(u);
5525 return NO_ERROR;
5526}
5527
5528
5529void AudioFlinger::PlaybackThread::OutputTrack::clearBufferQueue()
5530{
5531 size_t size = mBufferQueue.size();
Mathias Agopian65ab4712010-07-14 17:59:35 -07005532
5533 for (size_t i = 0; i < size; i++) {
Glenn Kastena1117922012-01-26 10:53:32 -08005534 Buffer *pBuffer = mBufferQueue.itemAt(i);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005535 delete [] pBuffer->mBuffer;
5536 delete pBuffer;
5537 }
5538 mBufferQueue.clear();
5539}
5540
5541// ----------------------------------------------------------------------------
5542
5543AudioFlinger::Client::Client(const sp<AudioFlinger>& audioFlinger, pid_t pid)
5544 : RefBase(),
5545 mAudioFlinger(audioFlinger),
Glenn Kasten99e53b82012-01-19 08:59:58 -08005546 // 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 -07005547 mMemoryDealer(new MemoryDealer(1024*1024, "AudioFlinger::Client")),
John Grossman4ff14ba2012-02-08 16:37:41 -08005548 mPid(pid),
5549 mTimedTrackCount(0)
Mathias Agopian65ab4712010-07-14 17:59:35 -07005550{
5551 // 1 MB of address space is good for 32 tracks, 8 buffers each, 4 KB/buffer
5552}
5553
5554// Client destructor must be called with AudioFlinger::mLock held
5555AudioFlinger::Client::~Client()
5556{
5557 mAudioFlinger->removeClient_l(mPid);
5558}
5559
Glenn Kasten435dbe62012-01-30 10:15:48 -08005560sp<MemoryDealer> AudioFlinger::Client::heap() const
Mathias Agopian65ab4712010-07-14 17:59:35 -07005561{
5562 return mMemoryDealer;
5563}
5564
John Grossman4ff14ba2012-02-08 16:37:41 -08005565// Reserve one of the limited slots for a timed audio track associated
5566// with this client
5567bool AudioFlinger::Client::reserveTimedTrack()
5568{
5569 const int kMaxTimedTracksPerClient = 4;
5570
5571 Mutex::Autolock _l(mTimedTrackLock);
5572
5573 if (mTimedTrackCount >= kMaxTimedTracksPerClient) {
5574 ALOGW("can not create timed track - pid %d has exceeded the limit",
5575 mPid);
5576 return false;
5577 }
5578
5579 mTimedTrackCount++;
5580 return true;
5581}
5582
5583// Release a slot for a timed audio track
5584void AudioFlinger::Client::releaseTimedTrack()
5585{
5586 Mutex::Autolock _l(mTimedTrackLock);
5587 mTimedTrackCount--;
5588}
5589
Mathias Agopian65ab4712010-07-14 17:59:35 -07005590// ----------------------------------------------------------------------------
5591
5592AudioFlinger::NotificationClient::NotificationClient(const sp<AudioFlinger>& audioFlinger,
5593 const sp<IAudioFlingerClient>& client,
5594 pid_t pid)
Glenn Kasten84afa3b2012-01-25 15:28:08 -08005595 : mAudioFlinger(audioFlinger), mPid(pid), mAudioFlingerClient(client)
Mathias Agopian65ab4712010-07-14 17:59:35 -07005596{
5597}
5598
5599AudioFlinger::NotificationClient::~NotificationClient()
5600{
Mathias Agopian65ab4712010-07-14 17:59:35 -07005601}
5602
5603void AudioFlinger::NotificationClient::binderDied(const wp<IBinder>& who)
5604{
5605 sp<NotificationClient> keep(this);
Glenn Kastena1117922012-01-26 10:53:32 -08005606 mAudioFlinger->removeNotificationClient(mPid);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005607}
5608
5609// ----------------------------------------------------------------------------
5610
5611AudioFlinger::TrackHandle::TrackHandle(const sp<AudioFlinger::PlaybackThread::Track>& track)
5612 : BnAudioTrack(),
5613 mTrack(track)
5614{
5615}
5616
5617AudioFlinger::TrackHandle::~TrackHandle() {
5618 // just stop the track on deletion, associated resources
5619 // will be freed from the main thread once all pending buffers have
5620 // been played. Unless it's not in the active track list, in which
5621 // case we free everything now...
5622 mTrack->destroy();
5623}
5624
Glenn Kasten90716c52012-01-26 13:40:12 -08005625sp<IMemory> AudioFlinger::TrackHandle::getCblk() const {
5626 return mTrack->getCblk();
5627}
5628
Glenn Kasten3acbd052012-02-28 10:39:56 -08005629status_t AudioFlinger::TrackHandle::start() {
5630 return mTrack->start();
Mathias Agopian65ab4712010-07-14 17:59:35 -07005631}
5632
5633void AudioFlinger::TrackHandle::stop() {
5634 mTrack->stop();
5635}
5636
5637void AudioFlinger::TrackHandle::flush() {
5638 mTrack->flush();
5639}
5640
5641void AudioFlinger::TrackHandle::mute(bool e) {
5642 mTrack->mute(e);
5643}
5644
5645void AudioFlinger::TrackHandle::pause() {
5646 mTrack->pause();
5647}
5648
Mathias Agopian65ab4712010-07-14 17:59:35 -07005649status_t AudioFlinger::TrackHandle::attachAuxEffect(int EffectId)
5650{
5651 return mTrack->attachAuxEffect(EffectId);
5652}
5653
John Grossman4ff14ba2012-02-08 16:37:41 -08005654status_t AudioFlinger::TrackHandle::allocateTimedBuffer(size_t size,
5655 sp<IMemory>* buffer) {
5656 if (!mTrack->isTimedTrack())
5657 return INVALID_OPERATION;
5658
5659 PlaybackThread::TimedTrack* tt =
5660 reinterpret_cast<PlaybackThread::TimedTrack*>(mTrack.get());
5661 return tt->allocateTimedBuffer(size, buffer);
5662}
5663
5664status_t AudioFlinger::TrackHandle::queueTimedBuffer(const sp<IMemory>& buffer,
5665 int64_t pts) {
5666 if (!mTrack->isTimedTrack())
5667 return INVALID_OPERATION;
5668
5669 PlaybackThread::TimedTrack* tt =
5670 reinterpret_cast<PlaybackThread::TimedTrack*>(mTrack.get());
5671 return tt->queueTimedBuffer(buffer, pts);
5672}
5673
5674status_t AudioFlinger::TrackHandle::setMediaTimeTransform(
5675 const LinearTransform& xform, int target) {
5676
5677 if (!mTrack->isTimedTrack())
5678 return INVALID_OPERATION;
5679
5680 PlaybackThread::TimedTrack* tt =
5681 reinterpret_cast<PlaybackThread::TimedTrack*>(mTrack.get());
5682 return tt->setMediaTimeTransform(
5683 xform, static_cast<TimedAudioTrack::TargetTimeline>(target));
5684}
5685
Mathias Agopian65ab4712010-07-14 17:59:35 -07005686status_t AudioFlinger::TrackHandle::onTransact(
5687 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
5688{
5689 return BnAudioTrack::onTransact(code, data, reply, flags);
5690}
5691
5692// ----------------------------------------------------------------------------
5693
5694sp<IAudioRecord> AudioFlinger::openRecord(
5695 pid_t pid,
Glenn Kasten72ef00d2012-01-17 11:09:42 -08005696 audio_io_handle_t input,
Mathias Agopian65ab4712010-07-14 17:59:35 -07005697 uint32_t sampleRate,
Glenn Kasten58f30212012-01-12 12:27:51 -08005698 audio_format_t format,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07005699 uint32_t channelMask,
Mathias Agopian65ab4712010-07-14 17:59:35 -07005700 int frameCount,
Glenn Kastena075db42012-03-06 11:22:44 -08005701 IAudioFlinger::track_flags_t flags,
Mathias Agopian65ab4712010-07-14 17:59:35 -07005702 int *sessionId,
5703 status_t *status)
5704{
5705 sp<RecordThread::RecordTrack> recordTrack;
5706 sp<RecordHandle> recordHandle;
5707 sp<Client> client;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005708 status_t lStatus;
5709 RecordThread *thread;
5710 size_t inFrameCount;
5711 int lSessionId;
5712
5713 // check calling permissions
5714 if (!recordingAllowed()) {
5715 lStatus = PERMISSION_DENIED;
5716 goto Exit;
5717 }
5718
5719 // add client to list
5720 { // scope for mLock
5721 Mutex::Autolock _l(mLock);
5722 thread = checkRecordThread_l(input);
5723 if (thread == NULL) {
5724 lStatus = BAD_VALUE;
5725 goto Exit;
5726 }
5727
Glenn Kasten98ec94c2012-01-25 14:28:29 -08005728 client = registerPid_l(pid);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005729
5730 // If no audio session id is provided, create one here
Dima Zavinfce7a472011-04-19 22:30:36 -07005731 if (sessionId != NULL && *sessionId != AUDIO_SESSION_OUTPUT_MIX) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07005732 lSessionId = *sessionId;
5733 } else {
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005734 lSessionId = nextUniqueId();
Mathias Agopian65ab4712010-07-14 17:59:35 -07005735 if (sessionId != NULL) {
5736 *sessionId = lSessionId;
5737 }
5738 }
5739 // create new record track. The record track uses one track in mHardwareMixerThread by convention.
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005740 recordTrack = thread->createRecordTrack_l(client,
5741 sampleRate,
5742 format,
5743 channelMask,
5744 frameCount,
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005745 lSessionId,
5746 &lStatus);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005747 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005748 if (lStatus != NO_ERROR) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07005749 // remove local strong reference to Client before deleting the RecordTrack so that the Client
5750 // destructor is called by the TrackBase destructor with mLock held
5751 client.clear();
5752 recordTrack.clear();
Mathias Agopian65ab4712010-07-14 17:59:35 -07005753 goto Exit;
5754 }
5755
5756 // return to handle to client
5757 recordHandle = new RecordHandle(recordTrack);
5758 lStatus = NO_ERROR;
5759
5760Exit:
5761 if (status) {
5762 *status = lStatus;
5763 }
5764 return recordHandle;
5765}
5766
5767// ----------------------------------------------------------------------------
5768
5769AudioFlinger::RecordHandle::RecordHandle(const sp<AudioFlinger::RecordThread::RecordTrack>& recordTrack)
5770 : BnAudioRecord(),
5771 mRecordTrack(recordTrack)
5772{
5773}
5774
5775AudioFlinger::RecordHandle::~RecordHandle() {
5776 stop();
5777}
5778
Glenn Kasten90716c52012-01-26 13:40:12 -08005779sp<IMemory> AudioFlinger::RecordHandle::getCblk() const {
5780 return mRecordTrack->getCblk();
5781}
5782
Glenn Kasten3acbd052012-02-28 10:39:56 -08005783status_t AudioFlinger::RecordHandle::start(int event, int triggerSession) {
Steve Block3856b092011-10-20 11:56:00 +01005784 ALOGV("RecordHandle::start()");
Glenn Kasten3acbd052012-02-28 10:39:56 -08005785 return mRecordTrack->start((AudioSystem::sync_event_t)event, triggerSession);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005786}
5787
5788void AudioFlinger::RecordHandle::stop() {
Steve Block3856b092011-10-20 11:56:00 +01005789 ALOGV("RecordHandle::stop()");
Mathias Agopian65ab4712010-07-14 17:59:35 -07005790 mRecordTrack->stop();
5791}
5792
Mathias Agopian65ab4712010-07-14 17:59:35 -07005793status_t AudioFlinger::RecordHandle::onTransact(
5794 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
5795{
5796 return BnAudioRecord::onTransact(code, data, reply, flags);
5797}
5798
5799// ----------------------------------------------------------------------------
5800
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005801AudioFlinger::RecordThread::RecordThread(const sp<AudioFlinger>& audioFlinger,
5802 AudioStreamIn *input,
5803 uint32_t sampleRate,
5804 uint32_t channels,
Glenn Kasten72ef00d2012-01-17 11:09:42 -08005805 audio_io_handle_t id,
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005806 uint32_t device) :
Glenn Kasten23bb8be2012-01-26 10:38:26 -08005807 ThreadBase(audioFlinger, id, device, RECORD),
Glenn Kasten84afa3b2012-01-25 15:28:08 -08005808 mInput(input), mTrack(NULL), mResampler(NULL), mRsmpOutBuffer(NULL), mRsmpInBuffer(NULL),
5809 // mRsmpInIndex and mInputBytes set by readInputParameters()
5810 mReqChannelCount(popcount(channels)),
5811 mReqSampleRate(sampleRate)
5812 // mBytesRead is only meaningful while active, and so is cleared in start()
5813 // (but might be better to also clear here for dump?)
Mathias Agopian65ab4712010-07-14 17:59:35 -07005814{
Glenn Kasten480b4682012-02-28 12:30:08 -08005815 snprintf(mName, kNameLength, "AudioIn_%X", id);
Eric Laurentfeb0db62011-07-22 09:04:31 -07005816
Mathias Agopian65ab4712010-07-14 17:59:35 -07005817 readInputParameters();
5818}
5819
5820
5821AudioFlinger::RecordThread::~RecordThread()
5822{
5823 delete[] mRsmpInBuffer;
Glenn Kastene9dd0172012-01-27 18:08:45 -08005824 delete mResampler;
5825 delete[] mRsmpOutBuffer;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005826}
5827
5828void AudioFlinger::RecordThread::onFirstRef()
5829{
Eric Laurentfeb0db62011-07-22 09:04:31 -07005830 run(mName, PRIORITY_URGENT_AUDIO);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005831}
5832
Eric Laurentb8ba0a92011-08-07 16:32:26 -07005833status_t AudioFlinger::RecordThread::readyToRun()
5834{
5835 status_t status = initCheck();
Steve Block5ff1dd52012-01-05 23:22:43 +00005836 ALOGW_IF(status != NO_ERROR,"RecordThread %p could not initialize", this);
Eric Laurentb8ba0a92011-08-07 16:32:26 -07005837 return status;
5838}
5839
Mathias Agopian65ab4712010-07-14 17:59:35 -07005840bool AudioFlinger::RecordThread::threadLoop()
5841{
5842 AudioBufferProvider::Buffer buffer;
5843 sp<RecordTrack> activeTrack;
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005844 Vector< sp<EffectChain> > effectChains;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005845
Eric Laurent44d98482010-09-30 16:12:31 -07005846 nsecs_t lastWarning = 0;
5847
Eric Laurentfeb0db62011-07-22 09:04:31 -07005848 acquireWakeLock();
5849
Mathias Agopian65ab4712010-07-14 17:59:35 -07005850 // start recording
5851 while (!exitPending()) {
5852
5853 processConfigEvents();
5854
5855 { // scope for mLock
5856 Mutex::Autolock _l(mLock);
5857 checkForNewParameters_l();
5858 if (mActiveTrack == 0 && mConfigEvents.isEmpty()) {
5859 if (!mStandby) {
Dima Zavin799a70e2011-04-18 16:57:27 -07005860 mInput->stream->common.standby(&mInput->stream->common);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005861 mStandby = true;
5862 }
5863
5864 if (exitPending()) break;
5865
Eric Laurentfeb0db62011-07-22 09:04:31 -07005866 releaseWakeLock_l();
Steve Block3856b092011-10-20 11:56:00 +01005867 ALOGV("RecordThread: loop stopping");
Mathias Agopian65ab4712010-07-14 17:59:35 -07005868 // go to sleep
5869 mWaitWorkCV.wait(mLock);
Steve Block3856b092011-10-20 11:56:00 +01005870 ALOGV("RecordThread: loop starting");
Eric Laurentfeb0db62011-07-22 09:04:31 -07005871 acquireWakeLock_l();
Mathias Agopian65ab4712010-07-14 17:59:35 -07005872 continue;
5873 }
5874 if (mActiveTrack != 0) {
5875 if (mActiveTrack->mState == TrackBase::PAUSING) {
5876 if (!mStandby) {
Dima Zavin799a70e2011-04-18 16:57:27 -07005877 mInput->stream->common.standby(&mInput->stream->common);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005878 mStandby = true;
5879 }
5880 mActiveTrack.clear();
5881 mStartStopCond.broadcast();
5882 } else if (mActiveTrack->mState == TrackBase::RESUMING) {
5883 if (mReqChannelCount != mActiveTrack->channelCount()) {
5884 mActiveTrack.clear();
5885 mStartStopCond.broadcast();
5886 } else if (mBytesRead != 0) {
5887 // record start succeeds only if first read from audio input
5888 // succeeds
5889 if (mBytesRead > 0) {
5890 mActiveTrack->mState = TrackBase::ACTIVE;
5891 } else {
5892 mActiveTrack.clear();
5893 }
5894 mStartStopCond.broadcast();
5895 }
5896 mStandby = false;
5897 }
5898 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005899 lockEffectChains_l(effectChains);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005900 }
5901
5902 if (mActiveTrack != 0) {
5903 if (mActiveTrack->mState != TrackBase::ACTIVE &&
5904 mActiveTrack->mState != TrackBase::RESUMING) {
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005905 unlockEffectChains(effectChains);
5906 usleep(kRecordThreadSleepUs);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005907 continue;
5908 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005909 for (size_t i = 0; i < effectChains.size(); i ++) {
5910 effectChains[i]->process_l();
5911 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005912
Mathias Agopian65ab4712010-07-14 17:59:35 -07005913 buffer.frameCount = mFrameCount;
Glenn Kasten01c4ebf2012-02-22 10:47:35 -08005914 if (CC_LIKELY(mActiveTrack->getNextBuffer(&buffer) == NO_ERROR)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07005915 size_t framesOut = buffer.frameCount;
Glenn Kastene0feee32011-12-13 11:53:26 -08005916 if (mResampler == NULL) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07005917 // no resampling
5918 while (framesOut) {
5919 size_t framesIn = mFrameCount - mRsmpInIndex;
5920 if (framesIn) {
5921 int8_t *src = (int8_t *)mRsmpInBuffer + mRsmpInIndex * mFrameSize;
5922 int8_t *dst = buffer.i8 + (buffer.frameCount - framesOut) * mActiveTrack->mCblk->frameSize;
5923 if (framesIn > framesOut)
5924 framesIn = framesOut;
5925 mRsmpInIndex += framesIn;
5926 framesOut -= framesIn;
5927 if ((int)mChannelCount == mReqChannelCount ||
Dima Zavinfce7a472011-04-19 22:30:36 -07005928 mFormat != AUDIO_FORMAT_PCM_16_BIT) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07005929 memcpy(dst, src, framesIn * mFrameSize);
5930 } else {
5931 int16_t *src16 = (int16_t *)src;
5932 int16_t *dst16 = (int16_t *)dst;
5933 if (mChannelCount == 1) {
5934 while (framesIn--) {
5935 *dst16++ = *src16;
5936 *dst16++ = *src16++;
5937 }
5938 } else {
5939 while (framesIn--) {
5940 *dst16++ = (int16_t)(((int32_t)*src16 + (int32_t)*(src16 + 1)) >> 1);
5941 src16 += 2;
5942 }
5943 }
5944 }
5945 }
5946 if (framesOut && mFrameCount == mRsmpInIndex) {
5947 if (framesOut == mFrameCount &&
Dima Zavinfce7a472011-04-19 22:30:36 -07005948 ((int)mChannelCount == mReqChannelCount || mFormat != AUDIO_FORMAT_PCM_16_BIT)) {
Dima Zavin799a70e2011-04-18 16:57:27 -07005949 mBytesRead = mInput->stream->read(mInput->stream, buffer.raw, mInputBytes);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005950 framesOut = 0;
5951 } else {
Dima Zavin799a70e2011-04-18 16:57:27 -07005952 mBytesRead = mInput->stream->read(mInput->stream, mRsmpInBuffer, mInputBytes);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005953 mRsmpInIndex = 0;
5954 }
5955 if (mBytesRead < 0) {
Steve Block29357bc2012-01-06 19:20:56 +00005956 ALOGE("Error reading audio input");
Mathias Agopian65ab4712010-07-14 17:59:35 -07005957 if (mActiveTrack->mState == TrackBase::ACTIVE) {
5958 // Force input into standby so that it tries to
5959 // recover at next read attempt
Dima Zavin799a70e2011-04-18 16:57:27 -07005960 mInput->stream->common.standby(&mInput->stream->common);
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005961 usleep(kRecordThreadSleepUs);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005962 }
5963 mRsmpInIndex = mFrameCount;
5964 framesOut = 0;
5965 buffer.frameCount = 0;
5966 }
5967 }
5968 }
5969 } else {
5970 // resampling
5971
5972 memset(mRsmpOutBuffer, 0, framesOut * 2 * sizeof(int32_t));
5973 // alter output frame count as if we were expecting stereo samples
5974 if (mChannelCount == 1 && mReqChannelCount == 1) {
5975 framesOut >>= 1;
5976 }
5977 mResampler->resample(mRsmpOutBuffer, framesOut, this);
5978 // ditherAndClamp() works as long as all buffers returned by mActiveTrack->getNextBuffer()
5979 // are 32 bit aligned which should be always true.
5980 if (mChannelCount == 2 && mReqChannelCount == 1) {
Glenn Kasten3b21c502011-12-15 09:52:39 -08005981 ditherAndClamp(mRsmpOutBuffer, mRsmpOutBuffer, framesOut);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005982 // the resampler always outputs stereo samples: do post stereo to mono conversion
5983 int16_t *src = (int16_t *)mRsmpOutBuffer;
5984 int16_t *dst = buffer.i16;
5985 while (framesOut--) {
5986 *dst++ = (int16_t)(((int32_t)*src + (int32_t)*(src + 1)) >> 1);
5987 src += 2;
5988 }
5989 } else {
Glenn Kasten3b21c502011-12-15 09:52:39 -08005990 ditherAndClamp((int32_t *)buffer.raw, mRsmpOutBuffer, framesOut);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005991 }
5992
5993 }
Eric Laurenta011e352012-03-29 15:51:43 -07005994 if (mFramestoDrop == 0) {
5995 mActiveTrack->releaseBuffer(&buffer);
5996 } else {
5997 if (mFramestoDrop > 0) {
5998 mFramestoDrop -= buffer.frameCount;
Eric Laurent29864602012-05-08 18:57:51 -07005999 if (mFramestoDrop <= 0) {
6000 clearSyncStartEvent();
6001 }
6002 } else {
6003 mFramestoDrop += buffer.frameCount;
6004 if (mFramestoDrop >= 0 || mSyncStartEvent == 0 ||
6005 mSyncStartEvent->isCancelled()) {
6006 ALOGW("Synced record %s, session %d, trigger session %d",
6007 (mFramestoDrop >= 0) ? "timed out" : "cancelled",
6008 mActiveTrack->sessionId(),
6009 (mSyncStartEvent != 0) ? mSyncStartEvent->triggerSession() : 0);
6010 clearSyncStartEvent();
Eric Laurenta011e352012-03-29 15:51:43 -07006011 }
6012 }
6013 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07006014 mActiveTrack->overflow();
6015 }
6016 // client isn't retrieving buffers fast enough
6017 else {
Eric Laurent44d98482010-09-30 16:12:31 -07006018 if (!mActiveTrack->setOverflow()) {
6019 nsecs_t now = systemTime();
Glenn Kasten7dede872011-12-13 11:04:14 -08006020 if ((now - lastWarning) > kWarningThrottleNs) {
Steve Block5ff1dd52012-01-05 23:22:43 +00006021 ALOGW("RecordThread: buffer overflow");
Eric Laurent44d98482010-09-30 16:12:31 -07006022 lastWarning = now;
6023 }
6024 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07006025 // Release the processor for a while before asking for a new buffer.
6026 // This will give the application more chance to read from the buffer and
6027 // clear the overflow.
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006028 usleep(kRecordThreadSleepUs);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006029 }
6030 }
Eric Laurentec437d82011-07-26 20:54:46 -07006031 // enable changes in effect chain
6032 unlockEffectChains(effectChains);
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006033 effectChains.clear();
Mathias Agopian65ab4712010-07-14 17:59:35 -07006034 }
6035
6036 if (!mStandby) {
Dima Zavin799a70e2011-04-18 16:57:27 -07006037 mInput->stream->common.standby(&mInput->stream->common);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006038 }
6039 mActiveTrack.clear();
6040
6041 mStartStopCond.broadcast();
6042
Eric Laurentfeb0db62011-07-22 09:04:31 -07006043 releaseWakeLock();
6044
Steve Block3856b092011-10-20 11:56:00 +01006045 ALOGV("RecordThread %p exiting", this);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006046 return false;
6047}
6048
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006049
6050sp<AudioFlinger::RecordThread::RecordTrack> AudioFlinger::RecordThread::createRecordTrack_l(
6051 const sp<AudioFlinger::Client>& client,
6052 uint32_t sampleRate,
Glenn Kasten58f30212012-01-12 12:27:51 -08006053 audio_format_t format,
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006054 int channelMask,
6055 int frameCount,
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006056 int sessionId,
6057 status_t *status)
6058{
6059 sp<RecordTrack> track;
6060 status_t lStatus;
6061
6062 lStatus = initCheck();
6063 if (lStatus != NO_ERROR) {
Steve Block29357bc2012-01-06 19:20:56 +00006064 ALOGE("Audio driver not initialized.");
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006065 goto Exit;
6066 }
6067
6068 { // scope for mLock
6069 Mutex::Autolock _l(mLock);
6070
6071 track = new RecordTrack(this, client, sampleRate,
Glenn Kasten5cf034d2012-02-21 10:35:56 -08006072 format, channelMask, frameCount, sessionId);
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006073
Glenn Kasten7378ca52012-01-20 13:44:40 -08006074 if (track->getCblk() == 0) {
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006075 lStatus = NO_MEMORY;
6076 goto Exit;
6077 }
6078
6079 mTrack = track.get();
Eric Laurent59bd0da2011-08-01 09:52:20 -07006080 // disable AEC and NS if the device is a BT SCO headset supporting those pre processings
6081 bool suspend = audio_is_bluetooth_sco_device(
Eric Laurentbee53372011-08-29 12:42:48 -07006082 (audio_devices_t)(mDevice & AUDIO_DEVICE_IN_ALL)) && mAudioFlinger->btNrecIsOff();
Eric Laurent59bd0da2011-08-01 09:52:20 -07006083 setEffectSuspended_l(FX_IID_AEC, suspend, sessionId);
6084 setEffectSuspended_l(FX_IID_NS, suspend, sessionId);
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006085 }
6086 lStatus = NO_ERROR;
6087
6088Exit:
6089 if (status) {
6090 *status = lStatus;
6091 }
6092 return track;
6093}
6094
Eric Laurenta011e352012-03-29 15:51:43 -07006095status_t AudioFlinger::RecordThread::start(RecordThread::RecordTrack* recordTrack,
Glenn Kasten3acbd052012-02-28 10:39:56 -08006096 AudioSystem::sync_event_t event,
Eric Laurenta011e352012-03-29 15:51:43 -07006097 int triggerSession)
Mathias Agopian65ab4712010-07-14 17:59:35 -07006098{
Glenn Kasten58912562012-04-03 10:45:00 -07006099 ALOGV("RecordThread::start event %d, triggerSession %d", event, triggerSession);
Glenn Kastene53b9ea2012-03-12 16:29:55 -07006100 sp<ThreadBase> strongMe = this;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006101 status_t status = NO_ERROR;
Eric Laurenta011e352012-03-29 15:51:43 -07006102
6103 if (event == AudioSystem::SYNC_EVENT_NONE) {
Eric Laurent29864602012-05-08 18:57:51 -07006104 clearSyncStartEvent();
Eric Laurenta011e352012-03-29 15:51:43 -07006105 } else if (event != AudioSystem::SYNC_EVENT_SAME) {
6106 mSyncStartEvent = mAudioFlinger->createSyncEvent(event,
6107 triggerSession,
6108 recordTrack->sessionId(),
6109 syncStartEventCallback,
6110 this);
Eric Laurent29864602012-05-08 18:57:51 -07006111 // Sync event can be cancelled by the trigger session if the track is not in a
6112 // compatible state in which case we start record immediately
6113 if (mSyncStartEvent->isCancelled()) {
6114 clearSyncStartEvent();
6115 } else {
6116 // do not wait for the event for more than AudioSystem::kSyncRecordStartTimeOutMs
6117 mFramestoDrop = - ((AudioSystem::kSyncRecordStartTimeOutMs * mReqSampleRate) / 1000);
6118 }
Eric Laurenta011e352012-03-29 15:51:43 -07006119 }
6120
Mathias Agopian65ab4712010-07-14 17:59:35 -07006121 {
Glenn Kastena7d8d6f2012-01-05 15:41:56 -08006122 AutoMutex lock(mLock);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006123 if (mActiveTrack != 0) {
6124 if (recordTrack != mActiveTrack.get()) {
6125 status = -EBUSY;
6126 } else if (mActiveTrack->mState == TrackBase::PAUSING) {
6127 mActiveTrack->mState = TrackBase::ACTIVE;
6128 }
6129 return status;
6130 }
6131
6132 recordTrack->mState = TrackBase::IDLE;
6133 mActiveTrack = recordTrack;
6134 mLock.unlock();
6135 status_t status = AudioSystem::startInput(mId);
6136 mLock.lock();
6137 if (status != NO_ERROR) {
6138 mActiveTrack.clear();
Eric Laurenta011e352012-03-29 15:51:43 -07006139 clearSyncStartEvent();
Mathias Agopian65ab4712010-07-14 17:59:35 -07006140 return status;
6141 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07006142 mRsmpInIndex = mFrameCount;
6143 mBytesRead = 0;
Eric Laurent243f5f92011-02-28 16:52:51 -08006144 if (mResampler != NULL) {
6145 mResampler->reset();
6146 }
6147 mActiveTrack->mState = TrackBase::RESUMING;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006148 // signal thread to start
Steve Block3856b092011-10-20 11:56:00 +01006149 ALOGV("Signal record thread");
Mathias Agopian65ab4712010-07-14 17:59:35 -07006150 mWaitWorkCV.signal();
6151 // do not wait for mStartStopCond if exiting
Glenn Kastenb28686f2012-01-06 08:39:38 -08006152 if (exitPending()) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07006153 mActiveTrack.clear();
6154 status = INVALID_OPERATION;
6155 goto startError;
6156 }
6157 mStartStopCond.wait(mLock);
6158 if (mActiveTrack == 0) {
Steve Block3856b092011-10-20 11:56:00 +01006159 ALOGV("Record failed to start");
Mathias Agopian65ab4712010-07-14 17:59:35 -07006160 status = BAD_VALUE;
6161 goto startError;
6162 }
Steve Block3856b092011-10-20 11:56:00 +01006163 ALOGV("Record started OK");
Mathias Agopian65ab4712010-07-14 17:59:35 -07006164 return status;
6165 }
6166startError:
6167 AudioSystem::stopInput(mId);
Eric Laurenta011e352012-03-29 15:51:43 -07006168 clearSyncStartEvent();
Mathias Agopian65ab4712010-07-14 17:59:35 -07006169 return status;
6170}
6171
Eric Laurenta011e352012-03-29 15:51:43 -07006172void AudioFlinger::RecordThread::clearSyncStartEvent()
6173{
6174 if (mSyncStartEvent != 0) {
6175 mSyncStartEvent->cancel();
6176 }
6177 mSyncStartEvent.clear();
Eric Laurent29864602012-05-08 18:57:51 -07006178 mFramestoDrop = 0;
Eric Laurenta011e352012-03-29 15:51:43 -07006179}
6180
6181void AudioFlinger::RecordThread::syncStartEventCallback(const wp<SyncEvent>& event)
6182{
6183 sp<SyncEvent> strongEvent = event.promote();
6184
6185 if (strongEvent != 0) {
6186 RecordThread *me = (RecordThread *)strongEvent->cookie();
6187 me->handleSyncStartEvent(strongEvent);
6188 }
6189}
6190
6191void AudioFlinger::RecordThread::handleSyncStartEvent(const sp<SyncEvent>& event)
6192{
Eric Laurent29864602012-05-08 18:57:51 -07006193 if (event == mSyncStartEvent) {
Eric Laurenta011e352012-03-29 15:51:43 -07006194 // TODO: use actual buffer filling status instead of 2 buffers when info is available
6195 // from audio HAL
6196 mFramestoDrop = mFrameCount * 2;
Eric Laurenta011e352012-03-29 15:51:43 -07006197 }
6198}
6199
Mathias Agopian65ab4712010-07-14 17:59:35 -07006200void AudioFlinger::RecordThread::stop(RecordThread::RecordTrack* recordTrack) {
Steve Block3856b092011-10-20 11:56:00 +01006201 ALOGV("RecordThread::stop");
Glenn Kastene53b9ea2012-03-12 16:29:55 -07006202 sp<ThreadBase> strongMe = this;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006203 {
Glenn Kastena7d8d6f2012-01-05 15:41:56 -08006204 AutoMutex lock(mLock);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006205 if (mActiveTrack != 0 && recordTrack == mActiveTrack.get()) {
6206 mActiveTrack->mState = TrackBase::PAUSING;
6207 // do not wait for mStartStopCond if exiting
Glenn Kastenb28686f2012-01-06 08:39:38 -08006208 if (exitPending()) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07006209 return;
6210 }
6211 mStartStopCond.wait(mLock);
6212 // if we have been restarted, recordTrack == mActiveTrack.get() here
6213 if (mActiveTrack == 0 || recordTrack != mActiveTrack.get()) {
6214 mLock.unlock();
6215 AudioSystem::stopInput(mId);
6216 mLock.lock();
Steve Block3856b092011-10-20 11:56:00 +01006217 ALOGV("Record stopped OK");
Mathias Agopian65ab4712010-07-14 17:59:35 -07006218 }
6219 }
6220 }
6221}
6222
Eric Laurenta011e352012-03-29 15:51:43 -07006223bool AudioFlinger::RecordThread::isValidSyncEvent(const sp<SyncEvent>& event)
6224{
6225 return false;
6226}
6227
6228status_t AudioFlinger::RecordThread::setSyncEvent(const sp<SyncEvent>& event)
6229{
6230 if (!isValidSyncEvent(event)) {
6231 return BAD_VALUE;
6232 }
6233
6234 Mutex::Autolock _l(mLock);
6235
6236 if (mTrack != NULL && event->triggerSession() == mTrack->sessionId()) {
6237 mTrack->setSyncEvent(event);
6238 return NO_ERROR;
6239 }
6240 return NAME_NOT_FOUND;
6241}
6242
Mathias Agopian65ab4712010-07-14 17:59:35 -07006243status_t AudioFlinger::RecordThread::dump(int fd, const Vector<String16>& args)
6244{
6245 const size_t SIZE = 256;
6246 char buffer[SIZE];
6247 String8 result;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006248
6249 snprintf(buffer, SIZE, "\nInput thread %p internals\n", this);
6250 result.append(buffer);
6251
6252 if (mActiveTrack != 0) {
6253 result.append("Active Track:\n");
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07006254 result.append(" Clien Fmt Chn mask Session Buf S SRate Serv User\n");
Mathias Agopian65ab4712010-07-14 17:59:35 -07006255 mActiveTrack->dump(buffer, SIZE);
6256 result.append(buffer);
6257
6258 snprintf(buffer, SIZE, "In index: %d\n", mRsmpInIndex);
6259 result.append(buffer);
6260 snprintf(buffer, SIZE, "In size: %d\n", mInputBytes);
6261 result.append(buffer);
Glenn Kastene0feee32011-12-13 11:53:26 -08006262 snprintf(buffer, SIZE, "Resampling: %d\n", (mResampler != NULL));
Mathias Agopian65ab4712010-07-14 17:59:35 -07006263 result.append(buffer);
6264 snprintf(buffer, SIZE, "Out channel count: %d\n", mReqChannelCount);
6265 result.append(buffer);
6266 snprintf(buffer, SIZE, "Out sample rate: %d\n", mReqSampleRate);
6267 result.append(buffer);
6268
6269
6270 } else {
6271 result.append("No record client\n");
6272 }
6273 write(fd, result.string(), result.size());
6274
6275 dumpBase(fd, args);
Eric Laurent1d2bff02011-07-24 17:49:51 -07006276 dumpEffectChains(fd, args);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006277
6278 return NO_ERROR;
6279}
6280
Glenn Kasten01c4ebf2012-02-22 10:47:35 -08006281// AudioBufferProvider interface
John Grossman4ff14ba2012-02-08 16:37:41 -08006282status_t AudioFlinger::RecordThread::getNextBuffer(AudioBufferProvider::Buffer* buffer, int64_t pts)
Mathias Agopian65ab4712010-07-14 17:59:35 -07006283{
6284 size_t framesReq = buffer->frameCount;
6285 size_t framesReady = mFrameCount - mRsmpInIndex;
6286 int channelCount;
6287
6288 if (framesReady == 0) {
Dima Zavin799a70e2011-04-18 16:57:27 -07006289 mBytesRead = mInput->stream->read(mInput->stream, mRsmpInBuffer, mInputBytes);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006290 if (mBytesRead < 0) {
Steve Block29357bc2012-01-06 19:20:56 +00006291 ALOGE("RecordThread::getNextBuffer() Error reading audio input");
Mathias Agopian65ab4712010-07-14 17:59:35 -07006292 if (mActiveTrack->mState == TrackBase::ACTIVE) {
6293 // Force input into standby so that it tries to
6294 // recover at next read attempt
Dima Zavin799a70e2011-04-18 16:57:27 -07006295 mInput->stream->common.standby(&mInput->stream->common);
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006296 usleep(kRecordThreadSleepUs);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006297 }
Glenn Kastene0feee32011-12-13 11:53:26 -08006298 buffer->raw = NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006299 buffer->frameCount = 0;
6300 return NOT_ENOUGH_DATA;
6301 }
6302 mRsmpInIndex = 0;
6303 framesReady = mFrameCount;
6304 }
6305
6306 if (framesReq > framesReady) {
6307 framesReq = framesReady;
6308 }
6309
6310 if (mChannelCount == 1 && mReqChannelCount == 2) {
6311 channelCount = 1;
6312 } else {
6313 channelCount = 2;
6314 }
6315 buffer->raw = mRsmpInBuffer + mRsmpInIndex * channelCount;
6316 buffer->frameCount = framesReq;
6317 return NO_ERROR;
6318}
6319
Glenn Kasten01c4ebf2012-02-22 10:47:35 -08006320// AudioBufferProvider interface
Mathias Agopian65ab4712010-07-14 17:59:35 -07006321void AudioFlinger::RecordThread::releaseBuffer(AudioBufferProvider::Buffer* buffer)
6322{
6323 mRsmpInIndex += buffer->frameCount;
6324 buffer->frameCount = 0;
6325}
6326
6327bool AudioFlinger::RecordThread::checkForNewParameters_l()
6328{
6329 bool reconfig = false;
6330
6331 while (!mNewParameters.isEmpty()) {
6332 status_t status = NO_ERROR;
6333 String8 keyValuePair = mNewParameters[0];
6334 AudioParameter param = AudioParameter(keyValuePair);
6335 int value;
Glenn Kasten58f30212012-01-12 12:27:51 -08006336 audio_format_t reqFormat = mFormat;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006337 int reqSamplingRate = mReqSampleRate;
6338 int reqChannelCount = mReqChannelCount;
6339
6340 if (param.getInt(String8(AudioParameter::keySamplingRate), value) == NO_ERROR) {
6341 reqSamplingRate = value;
6342 reconfig = true;
6343 }
6344 if (param.getInt(String8(AudioParameter::keyFormat), value) == NO_ERROR) {
Glenn Kasten58f30212012-01-12 12:27:51 -08006345 reqFormat = (audio_format_t) value;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006346 reconfig = true;
6347 }
6348 if (param.getInt(String8(AudioParameter::keyChannels), value) == NO_ERROR) {
Dima Zavinfce7a472011-04-19 22:30:36 -07006349 reqChannelCount = popcount(value);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006350 reconfig = true;
6351 }
6352 if (param.getInt(String8(AudioParameter::keyFrameCount), value) == NO_ERROR) {
6353 // do not accept frame count changes if tracks are open as the track buffer
Glenn Kasten99e53b82012-01-19 08:59:58 -08006354 // size depends on frame count and correct behavior would not be guaranteed
Mathias Agopian65ab4712010-07-14 17:59:35 -07006355 // if frame count is changed after track creation
6356 if (mActiveTrack != 0) {
6357 status = INVALID_OPERATION;
6358 } else {
6359 reconfig = true;
6360 }
6361 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006362 if (param.getInt(String8(AudioParameter::keyRouting), value) == NO_ERROR) {
6363 // forward device change to effects that have requested to be
6364 // aware of attached audio device.
6365 for (size_t i = 0; i < mEffectChains.size(); i++) {
6366 mEffectChains[i]->setDevice_l(value);
6367 }
6368 // store input device and output device but do not forward output device to audio HAL.
6369 // Note that status is ignored by the caller for output device
6370 // (see AudioFlinger::setParameters()
6371 if (value & AUDIO_DEVICE_OUT_ALL) {
6372 mDevice &= (uint32_t)~(value & AUDIO_DEVICE_OUT_ALL);
6373 status = BAD_VALUE;
6374 } else {
6375 mDevice &= (uint32_t)~(value & AUDIO_DEVICE_IN_ALL);
Eric Laurent59bd0da2011-08-01 09:52:20 -07006376 // disable AEC and NS if the device is a BT SCO headset supporting those pre processings
6377 if (mTrack != NULL) {
6378 bool suspend = audio_is_bluetooth_sco_device(
Eric Laurentbee53372011-08-29 12:42:48 -07006379 (audio_devices_t)value) && mAudioFlinger->btNrecIsOff();
Eric Laurent59bd0da2011-08-01 09:52:20 -07006380 setEffectSuspended_l(FX_IID_AEC, suspend, mTrack->sessionId());
6381 setEffectSuspended_l(FX_IID_NS, suspend, mTrack->sessionId());
6382 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006383 }
6384 mDevice |= (uint32_t)value;
6385 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07006386 if (status == NO_ERROR) {
Dima Zavin799a70e2011-04-18 16:57:27 -07006387 status = mInput->stream->common.set_parameters(&mInput->stream->common, keyValuePair.string());
Mathias Agopian65ab4712010-07-14 17:59:35 -07006388 if (status == INVALID_OPERATION) {
Glenn Kastene53b9ea2012-03-12 16:29:55 -07006389 mInput->stream->common.standby(&mInput->stream->common);
6390 status = mInput->stream->common.set_parameters(&mInput->stream->common,
6391 keyValuePair.string());
Mathias Agopian65ab4712010-07-14 17:59:35 -07006392 }
6393 if (reconfig) {
6394 if (status == BAD_VALUE &&
Dima Zavin799a70e2011-04-18 16:57:27 -07006395 reqFormat == mInput->stream->common.get_format(&mInput->stream->common) &&
Dima Zavinfce7a472011-04-19 22:30:36 -07006396 reqFormat == AUDIO_FORMAT_PCM_16_BIT &&
Dima Zavin799a70e2011-04-18 16:57:27 -07006397 ((int)mInput->stream->common.get_sample_rate(&mInput->stream->common) <= (2 * reqSamplingRate)) &&
Glenn Kasten53d76db2012-03-08 12:32:47 -08006398 popcount(mInput->stream->common.get_channels(&mInput->stream->common)) <= FCC_2 &&
6399 (reqChannelCount <= FCC_2)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07006400 status = NO_ERROR;
6401 }
6402 if (status == NO_ERROR) {
6403 readInputParameters();
6404 sendConfigEvent_l(AudioSystem::INPUT_CONFIG_CHANGED);
6405 }
6406 }
6407 }
6408
6409 mNewParameters.removeAt(0);
6410
6411 mParamStatus = status;
6412 mParamCond.signal();
Eric Laurent60cd0a02011-09-13 11:40:21 -07006413 // wait for condition with time out in case the thread calling ThreadBase::setParameters()
6414 // already timed out waiting for the status and will never signal the condition.
Glenn Kasten7dede872011-12-13 11:04:14 -08006415 mWaitWorkCV.waitRelative(mLock, kSetParametersTimeoutNs);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006416 }
6417 return reconfig;
6418}
6419
6420String8 AudioFlinger::RecordThread::getParameters(const String8& keys)
6421{
Dima Zavinfce7a472011-04-19 22:30:36 -07006422 char *s;
Eric Laurentb8ba0a92011-08-07 16:32:26 -07006423 String8 out_s8 = String8();
6424
6425 Mutex::Autolock _l(mLock);
6426 if (initCheck() != NO_ERROR) {
6427 return out_s8;
6428 }
Dima Zavinfce7a472011-04-19 22:30:36 -07006429
Dima Zavin799a70e2011-04-18 16:57:27 -07006430 s = mInput->stream->common.get_parameters(&mInput->stream->common, keys.string());
Dima Zavinfce7a472011-04-19 22:30:36 -07006431 out_s8 = String8(s);
6432 free(s);
6433 return out_s8;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006434}
6435
6436void AudioFlinger::RecordThread::audioConfigChanged_l(int event, int param) {
6437 AudioSystem::OutputDescriptor desc;
Glenn Kastena0d68332012-01-27 16:47:15 -08006438 void *param2 = NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006439
6440 switch (event) {
6441 case AudioSystem::INPUT_OPENED:
6442 case AudioSystem::INPUT_CONFIG_CHANGED:
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07006443 desc.channels = mChannelMask;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006444 desc.samplingRate = mSampleRate;
6445 desc.format = mFormat;
6446 desc.frameCount = mFrameCount;
6447 desc.latency = 0;
6448 param2 = &desc;
6449 break;
6450
6451 case AudioSystem::INPUT_CLOSED:
6452 default:
6453 break;
6454 }
6455 mAudioFlinger->audioConfigChanged_l(event, mId, param2);
6456}
6457
6458void AudioFlinger::RecordThread::readInputParameters()
6459{
Glenn Kastene9dd0172012-01-27 18:08:45 -08006460 delete mRsmpInBuffer;
6461 // mRsmpInBuffer is always assigned a new[] below
6462 delete mRsmpOutBuffer;
6463 mRsmpOutBuffer = NULL;
6464 delete mResampler;
Glenn Kastene0feee32011-12-13 11:53:26 -08006465 mResampler = NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006466
Dima Zavin799a70e2011-04-18 16:57:27 -07006467 mSampleRate = mInput->stream->common.get_sample_rate(&mInput->stream->common);
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07006468 mChannelMask = mInput->stream->common.get_channels(&mInput->stream->common);
6469 mChannelCount = (uint16_t)popcount(mChannelMask);
Dima Zavin799a70e2011-04-18 16:57:27 -07006470 mFormat = mInput->stream->common.get_format(&mInput->stream->common);
Glenn Kastenb9980652012-01-11 09:48:27 -08006471 mFrameSize = audio_stream_frame_size(&mInput->stream->common);
Dima Zavin799a70e2011-04-18 16:57:27 -07006472 mInputBytes = mInput->stream->common.get_buffer_size(&mInput->stream->common);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006473 mFrameCount = mInputBytes / mFrameSize;
Glenn Kasten58912562012-04-03 10:45:00 -07006474 mNormalFrameCount = mFrameCount; // not used by record, but used by input effects
Mathias Agopian65ab4712010-07-14 17:59:35 -07006475 mRsmpInBuffer = new int16_t[mFrameCount * mChannelCount];
6476
Glenn Kasten53d76db2012-03-08 12:32:47 -08006477 if (mSampleRate != mReqSampleRate && mChannelCount <= FCC_2 && mReqChannelCount <= FCC_2)
Mathias Agopian65ab4712010-07-14 17:59:35 -07006478 {
6479 int channelCount;
Glenn Kastene53b9ea2012-03-12 16:29:55 -07006480 // optimization: if mono to mono, use the resampler in stereo to stereo mode to avoid
6481 // stereo to mono post process as the resampler always outputs stereo.
Mathias Agopian65ab4712010-07-14 17:59:35 -07006482 if (mChannelCount == 1 && mReqChannelCount == 2) {
6483 channelCount = 1;
6484 } else {
6485 channelCount = 2;
6486 }
6487 mResampler = AudioResampler::create(16, channelCount, mReqSampleRate);
6488 mResampler->setSampleRate(mSampleRate);
6489 mResampler->setVolume(AudioMixer::UNITY_GAIN, AudioMixer::UNITY_GAIN);
6490 mRsmpOutBuffer = new int32_t[mFrameCount * 2];
6491
6492 // optmization: if mono to mono, alter input frame count as if we were inputing stereo samples
6493 if (mChannelCount == 1 && mReqChannelCount == 1) {
6494 mFrameCount >>= 1;
6495 }
6496
6497 }
6498 mRsmpInIndex = mFrameCount;
6499}
6500
6501unsigned int AudioFlinger::RecordThread::getInputFramesLost()
6502{
Eric Laurentb8ba0a92011-08-07 16:32:26 -07006503 Mutex::Autolock _l(mLock);
6504 if (initCheck() != NO_ERROR) {
6505 return 0;
6506 }
6507
Dima Zavin799a70e2011-04-18 16:57:27 -07006508 return mInput->stream->get_input_frames_lost(mInput->stream);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006509}
6510
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006511uint32_t AudioFlinger::RecordThread::hasAudioSession(int sessionId)
6512{
6513 Mutex::Autolock _l(mLock);
6514 uint32_t result = 0;
6515 if (getEffectChain_l(sessionId) != 0) {
6516 result = EFFECT_SESSION;
6517 }
6518
6519 if (mTrack != NULL && sessionId == mTrack->sessionId()) {
6520 result |= TRACK_SESSION;
6521 }
6522
6523 return result;
6524}
6525
Eric Laurent59bd0da2011-08-01 09:52:20 -07006526AudioFlinger::RecordThread::RecordTrack* AudioFlinger::RecordThread::track()
6527{
6528 Mutex::Autolock _l(mLock);
6529 return mTrack;
6530}
6531
Glenn Kastenaed850d2012-01-26 09:46:34 -08006532AudioFlinger::AudioStreamIn* AudioFlinger::RecordThread::getInput() const
Eric Laurentb8ba0a92011-08-07 16:32:26 -07006533{
6534 Mutex::Autolock _l(mLock);
6535 return mInput;
6536}
6537
6538AudioFlinger::AudioStreamIn* AudioFlinger::RecordThread::clearInput()
6539{
6540 Mutex::Autolock _l(mLock);
6541 AudioStreamIn *input = mInput;
6542 mInput = NULL;
6543 return input;
6544}
6545
6546// this method must always be called either with ThreadBase mLock held or inside the thread loop
Glenn Kasten0bf65bd2012-02-28 18:32:53 -08006547audio_stream_t* AudioFlinger::RecordThread::stream() const
Eric Laurentb8ba0a92011-08-07 16:32:26 -07006548{
6549 if (mInput == NULL) {
6550 return NULL;
6551 }
6552 return &mInput->stream->common;
6553}
6554
6555
Mathias Agopian65ab4712010-07-14 17:59:35 -07006556// ----------------------------------------------------------------------------
6557
Eric Laurenta4c5a552012-03-29 10:12:40 -07006558audio_module_handle_t AudioFlinger::loadHwModule(const char *name)
6559{
6560 if (!settingsAllowed()) {
6561 return 0;
6562 }
6563 Mutex::Autolock _l(mLock);
6564 return loadHwModule_l(name);
6565}
6566
6567// loadHwModule_l() must be called with AudioFlinger::mLock held
6568audio_module_handle_t AudioFlinger::loadHwModule_l(const char *name)
6569{
6570 for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
6571 if (strncmp(mAudioHwDevs.valueAt(i)->moduleName(), name, strlen(name)) == 0) {
6572 ALOGW("loadHwModule() module %s already loaded", name);
6573 return mAudioHwDevs.keyAt(i);
6574 }
6575 }
6576
Eric Laurenta4c5a552012-03-29 10:12:40 -07006577 audio_hw_device_t *dev;
6578
Eric Laurentf7ffb8b2012-04-14 09:06:57 -07006579 int rc = load_audio_interface(name, &dev);
Eric Laurenta4c5a552012-03-29 10:12:40 -07006580 if (rc) {
6581 ALOGI("loadHwModule() error %d loading module %s ", rc, name);
6582 return 0;
6583 }
6584
6585 mHardwareStatus = AUDIO_HW_INIT;
6586 rc = dev->init_check(dev);
6587 mHardwareStatus = AUDIO_HW_IDLE;
6588 if (rc) {
6589 ALOGI("loadHwModule() init check error %d for module %s ", rc, name);
6590 return 0;
6591 }
6592
6593 if ((mMasterVolumeSupportLvl != MVS_NONE) &&
6594 (NULL != dev->set_master_volume)) {
6595 AutoMutex lock(mHardwareLock);
6596 mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
6597 dev->set_master_volume(dev, mMasterVolume);
6598 mHardwareStatus = AUDIO_HW_IDLE;
6599 }
6600
6601 audio_module_handle_t handle = nextUniqueId();
6602 mAudioHwDevs.add(handle, new AudioHwDevice(name, dev));
6603
6604 ALOGI("loadHwModule() Loaded %s audio interface from %s (%s) handle %d",
Eric Laurentf7ffb8b2012-04-14 09:06:57 -07006605 name, dev->common.module->name, dev->common.module->id, handle);
Eric Laurenta4c5a552012-03-29 10:12:40 -07006606
6607 return handle;
6608
6609}
6610
6611audio_io_handle_t AudioFlinger::openOutput(audio_module_handle_t module,
6612 audio_devices_t *pDevices,
6613 uint32_t *pSamplingRate,
6614 audio_format_t *pFormat,
6615 audio_channel_mask_t *pChannelMask,
6616 uint32_t *pLatencyMs,
Eric Laurent0ca3cf92012-04-18 09:24:29 -07006617 audio_output_flags_t flags)
Mathias Agopian65ab4712010-07-14 17:59:35 -07006618{
6619 status_t status;
6620 PlaybackThread *thread = NULL;
Eric Laurentf7ffb8b2012-04-14 09:06:57 -07006621 struct audio_config config = {
6622 sample_rate: pSamplingRate ? *pSamplingRate : 0,
6623 channel_mask: pChannelMask ? *pChannelMask : 0,
6624 format: pFormat ? *pFormat : AUDIO_FORMAT_DEFAULT,
6625 };
6626 audio_stream_out_t *outStream = NULL;
Dima Zavin799a70e2011-04-18 16:57:27 -07006627 audio_hw_device_t *outHwDev;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006628
Eric Laurenta4c5a552012-03-29 10:12:40 -07006629 ALOGV("openOutput(), module %d Device %x, SamplingRate %d, Format %d, Channels %x, flags %x",
6630 module,
Eric Laurent3f9c84c2012-04-03 15:36:53 -07006631 (pDevices != NULL) ? (int)*pDevices : 0,
Eric Laurentf7ffb8b2012-04-14 09:06:57 -07006632 config.sample_rate,
6633 config.format,
6634 config.channel_mask,
Eric Laurenta4c5a552012-03-29 10:12:40 -07006635 flags);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006636
6637 if (pDevices == NULL || *pDevices == 0) {
6638 return 0;
6639 }
Dima Zavin799a70e2011-04-18 16:57:27 -07006640
Mathias Agopian65ab4712010-07-14 17:59:35 -07006641 Mutex::Autolock _l(mLock);
6642
Eric Laurenta4c5a552012-03-29 10:12:40 -07006643 outHwDev = findSuitableHwDev_l(module, *pDevices);
Dima Zavin799a70e2011-04-18 16:57:27 -07006644 if (outHwDev == NULL)
6645 return 0;
6646
Eric Laurentf7ffb8b2012-04-14 09:06:57 -07006647 audio_io_handle_t id = nextUniqueId();
6648
Glenn Kasten8abf44d2012-02-02 14:16:03 -08006649 mHardwareStatus = AUDIO_HW_OUTPUT_OPEN;
Eric Laurentf7ffb8b2012-04-14 09:06:57 -07006650
6651 status = outHwDev->open_output_stream(outHwDev,
6652 id,
6653 *pDevices,
6654 (audio_output_flags_t)flags,
6655 &config,
6656 &outStream);
6657
Glenn Kasten8abf44d2012-02-02 14:16:03 -08006658 mHardwareStatus = AUDIO_HW_IDLE;
Steve Block3856b092011-10-20 11:56:00 +01006659 ALOGV("openOutput() openOutputStream returned output %p, SamplingRate %d, Format %d, Channels %x, status %d",
Dima Zavin799a70e2011-04-18 16:57:27 -07006660 outStream,
Eric Laurentf7ffb8b2012-04-14 09:06:57 -07006661 config.sample_rate,
6662 config.format,
6663 config.channel_mask,
Mathias Agopian65ab4712010-07-14 17:59:35 -07006664 status);
6665
Eric Laurentf7ffb8b2012-04-14 09:06:57 -07006666 if (status == NO_ERROR && outStream != NULL) {
Dima Zavin799a70e2011-04-18 16:57:27 -07006667 AudioStreamOut *output = new AudioStreamOut(outHwDev, outStream);
Dima Zavin799a70e2011-04-18 16:57:27 -07006668
Eric Laurent0ca3cf92012-04-18 09:24:29 -07006669 if ((flags & AUDIO_OUTPUT_FLAG_DIRECT) ||
Eric Laurentf7ffb8b2012-04-14 09:06:57 -07006670 (config.format != AUDIO_FORMAT_PCM_16_BIT) ||
6671 (config.channel_mask != AUDIO_CHANNEL_OUT_STEREO)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07006672 thread = new DirectOutputThread(this, output, id, *pDevices);
Steve Block3856b092011-10-20 11:56:00 +01006673 ALOGV("openOutput() created direct output: ID %d thread %p", id, thread);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006674 } else {
6675 thread = new MixerThread(this, output, id, *pDevices);
Steve Block3856b092011-10-20 11:56:00 +01006676 ALOGV("openOutput() created mixer output: ID %d thread %p", id, thread);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006677 }
6678 mPlaybackThreads.add(id, thread);
6679
Eric Laurentf7ffb8b2012-04-14 09:06:57 -07006680 if (pSamplingRate != NULL) *pSamplingRate = config.sample_rate;
6681 if (pFormat != NULL) *pFormat = config.format;
6682 if (pChannelMask != NULL) *pChannelMask = config.channel_mask;
Glenn Kastena0d68332012-01-27 16:47:15 -08006683 if (pLatencyMs != NULL) *pLatencyMs = thread->latency();
Mathias Agopian65ab4712010-07-14 17:59:35 -07006684
6685 // notify client processes of the new output creation
6686 thread->audioConfigChanged_l(AudioSystem::OUTPUT_OPENED);
Eric Laurenta4c5a552012-03-29 10:12:40 -07006687
6688 // the first primary output opened designates the primary hw device
Eric Laurent0ca3cf92012-04-18 09:24:29 -07006689 if ((mPrimaryHardwareDev == NULL) && (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
Eric Laurenta4c5a552012-03-29 10:12:40 -07006690 ALOGI("Using module %d has the primary audio interface", module);
6691 mPrimaryHardwareDev = outHwDev;
6692
6693 AutoMutex lock(mHardwareLock);
6694 mHardwareStatus = AUDIO_HW_SET_MODE;
6695 outHwDev->set_mode(outHwDev, mMode);
6696
6697 // Determine the level of master volume support the primary audio HAL has,
6698 // and set the initial master volume at the same time.
6699 float initialVolume = 1.0;
6700 mMasterVolumeSupportLvl = MVS_NONE;
6701
6702 mHardwareStatus = AUDIO_HW_GET_MASTER_VOLUME;
6703 if ((NULL != outHwDev->get_master_volume) &&
6704 (NO_ERROR == outHwDev->get_master_volume(outHwDev, &initialVolume))) {
6705 mMasterVolumeSupportLvl = MVS_FULL;
6706 } else {
6707 mMasterVolumeSupportLvl = MVS_SETONLY;
6708 initialVolume = 1.0;
6709 }
6710
6711 mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
6712 if ((NULL == outHwDev->set_master_volume) ||
6713 (NO_ERROR != outHwDev->set_master_volume(outHwDev, initialVolume))) {
6714 mMasterVolumeSupportLvl = MVS_NONE;
6715 }
6716 // now that we have a primary device, initialize master volume on other devices
6717 for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
6718 audio_hw_device_t *dev = mAudioHwDevs.valueAt(i)->hwDevice();
6719
6720 if ((dev != mPrimaryHardwareDev) &&
6721 (NULL != dev->set_master_volume)) {
6722 dev->set_master_volume(dev, initialVolume);
6723 }
6724 }
6725 mHardwareStatus = AUDIO_HW_IDLE;
6726 mMasterVolumeSW = (MVS_NONE == mMasterVolumeSupportLvl)
6727 ? initialVolume
6728 : 1.0;
6729 mMasterVolume = initialVolume;
6730 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07006731 return id;
6732 }
6733
6734 return 0;
6735}
6736
Glenn Kasten72ef00d2012-01-17 11:09:42 -08006737audio_io_handle_t AudioFlinger::openDuplicateOutput(audio_io_handle_t output1,
6738 audio_io_handle_t output2)
Mathias Agopian65ab4712010-07-14 17:59:35 -07006739{
6740 Mutex::Autolock _l(mLock);
6741 MixerThread *thread1 = checkMixerThread_l(output1);
6742 MixerThread *thread2 = checkMixerThread_l(output2);
6743
6744 if (thread1 == NULL || thread2 == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +00006745 ALOGW("openDuplicateOutput() wrong output mixer type for output %d or %d", output1, output2);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006746 return 0;
6747 }
6748
Glenn Kasten72ef00d2012-01-17 11:09:42 -08006749 audio_io_handle_t id = nextUniqueId();
Mathias Agopian65ab4712010-07-14 17:59:35 -07006750 DuplicatingThread *thread = new DuplicatingThread(this, thread1, id);
6751 thread->addOutputTrack(thread2);
6752 mPlaybackThreads.add(id, thread);
6753 // notify client processes of the new output creation
6754 thread->audioConfigChanged_l(AudioSystem::OUTPUT_OPENED);
6755 return id;
6756}
6757
Glenn Kasten72ef00d2012-01-17 11:09:42 -08006758status_t AudioFlinger::closeOutput(audio_io_handle_t output)
Mathias Agopian65ab4712010-07-14 17:59:35 -07006759{
6760 // keep strong reference on the playback thread so that
6761 // it is not destroyed while exit() is executed
Glenn Kastene53b9ea2012-03-12 16:29:55 -07006762 sp<PlaybackThread> thread;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006763 {
6764 Mutex::Autolock _l(mLock);
6765 thread = checkPlaybackThread_l(output);
6766 if (thread == NULL) {
6767 return BAD_VALUE;
6768 }
6769
Steve Block3856b092011-10-20 11:56:00 +01006770 ALOGV("closeOutput() %d", output);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006771
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006772 if (thread->type() == ThreadBase::MIXER) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07006773 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006774 if (mPlaybackThreads.valueAt(i)->type() == ThreadBase::DUPLICATING) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07006775 DuplicatingThread *dupThread = (DuplicatingThread *)mPlaybackThreads.valueAt(i).get();
6776 dupThread->removeOutputTrack((MixerThread *)thread.get());
6777 }
6778 }
6779 }
Glenn Kastena1117922012-01-26 10:53:32 -08006780 audioConfigChanged_l(AudioSystem::OUTPUT_CLOSED, output, NULL);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006781 mPlaybackThreads.removeItem(output);
6782 }
6783 thread->exit();
Glenn Kastenb28686f2012-01-06 08:39:38 -08006784 // The thread entity (active unit of execution) is no longer running here,
6785 // but the ThreadBase container still exists.
Mathias Agopian65ab4712010-07-14 17:59:35 -07006786
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006787 if (thread->type() != ThreadBase::DUPLICATING) {
Eric Laurentb8ba0a92011-08-07 16:32:26 -07006788 AudioStreamOut *out = thread->clearOutput();
Glenn Kasten5798d4e2012-03-08 12:18:35 -08006789 ALOG_ASSERT(out != NULL, "out shouldn't be NULL");
Eric Laurentb8ba0a92011-08-07 16:32:26 -07006790 // from now on thread->mOutput is NULL
Dima Zavin799a70e2011-04-18 16:57:27 -07006791 out->hwDev->close_output_stream(out->hwDev, out->stream);
6792 delete out;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006793 }
6794 return NO_ERROR;
6795}
6796
Glenn Kasten72ef00d2012-01-17 11:09:42 -08006797status_t AudioFlinger::suspendOutput(audio_io_handle_t output)
Mathias Agopian65ab4712010-07-14 17:59:35 -07006798{
6799 Mutex::Autolock _l(mLock);
6800 PlaybackThread *thread = checkPlaybackThread_l(output);
6801
6802 if (thread == NULL) {
6803 return BAD_VALUE;
6804 }
6805
Steve Block3856b092011-10-20 11:56:00 +01006806 ALOGV("suspendOutput() %d", output);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006807 thread->suspend();
6808
6809 return NO_ERROR;
6810}
6811
Glenn Kasten72ef00d2012-01-17 11:09:42 -08006812status_t AudioFlinger::restoreOutput(audio_io_handle_t output)
Mathias Agopian65ab4712010-07-14 17:59:35 -07006813{
6814 Mutex::Autolock _l(mLock);
6815 PlaybackThread *thread = checkPlaybackThread_l(output);
6816
6817 if (thread == NULL) {
6818 return BAD_VALUE;
6819 }
6820
Steve Block3856b092011-10-20 11:56:00 +01006821 ALOGV("restoreOutput() %d", output);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006822
6823 thread->restore();
6824
6825 return NO_ERROR;
6826}
6827
Eric Laurenta4c5a552012-03-29 10:12:40 -07006828audio_io_handle_t AudioFlinger::openInput(audio_module_handle_t module,
6829 audio_devices_t *pDevices,
6830 uint32_t *pSamplingRate,
6831 audio_format_t *pFormat,
6832 uint32_t *pChannelMask)
Mathias Agopian65ab4712010-07-14 17:59:35 -07006833{
6834 status_t status;
6835 RecordThread *thread = NULL;
Eric Laurentf7ffb8b2012-04-14 09:06:57 -07006836 struct audio_config config = {
6837 sample_rate: pSamplingRate ? *pSamplingRate : 0,
6838 channel_mask: pChannelMask ? *pChannelMask : 0,
6839 format: pFormat ? *pFormat : AUDIO_FORMAT_DEFAULT,
6840 };
6841 uint32_t reqSamplingRate = config.sample_rate;
6842 audio_format_t reqFormat = config.format;
6843 audio_channel_mask_t reqChannels = config.channel_mask;
6844 audio_stream_in_t *inStream = NULL;
Dima Zavin799a70e2011-04-18 16:57:27 -07006845 audio_hw_device_t *inHwDev;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006846
6847 if (pDevices == NULL || *pDevices == 0) {
6848 return 0;
6849 }
Dima Zavin799a70e2011-04-18 16:57:27 -07006850
Mathias Agopian65ab4712010-07-14 17:59:35 -07006851 Mutex::Autolock _l(mLock);
6852
Eric Laurenta4c5a552012-03-29 10:12:40 -07006853 inHwDev = findSuitableHwDev_l(module, *pDevices);
Dima Zavin799a70e2011-04-18 16:57:27 -07006854 if (inHwDev == NULL)
6855 return 0;
6856
Eric Laurentf7ffb8b2012-04-14 09:06:57 -07006857 audio_io_handle_t id = nextUniqueId();
6858
6859 status = inHwDev->open_input_stream(inHwDev, id, *pDevices, &config,
Dima Zavin799a70e2011-04-18 16:57:27 -07006860 &inStream);
Eric Laurenta4c5a552012-03-29 10:12:40 -07006861 ALOGV("openInput() openInputStream returned input %p, SamplingRate %d, Format %d, Channels %x, status %d",
Dima Zavin799a70e2011-04-18 16:57:27 -07006862 inStream,
Eric Laurentf7ffb8b2012-04-14 09:06:57 -07006863 config.sample_rate,
6864 config.format,
6865 config.channel_mask,
Mathias Agopian65ab4712010-07-14 17:59:35 -07006866 status);
6867
6868 // If the input could not be opened with the requested parameters and we can handle the conversion internally,
6869 // try to open again with the proposed parameters. The AudioFlinger can resample the input and do mono to stereo
6870 // or stereo to mono conversions on 16 bit PCM inputs.
Eric Laurentf7ffb8b2012-04-14 09:06:57 -07006871 if (status == BAD_VALUE &&
6872 reqFormat == config.format && config.format == AUDIO_FORMAT_PCM_16_BIT &&
6873 (config.sample_rate <= 2 * reqSamplingRate) &&
6874 (popcount(config.channel_mask) <= FCC_2) && (popcount(reqChannels) <= FCC_2)) {
Steve Block3856b092011-10-20 11:56:00 +01006875 ALOGV("openInput() reopening with proposed sampling rate and channels");
Eric Laurentf7ffb8b2012-04-14 09:06:57 -07006876 inStream = NULL;
6877 status = inHwDev->open_input_stream(inHwDev, id, *pDevices, &config, &inStream);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006878 }
6879
Eric Laurentf7ffb8b2012-04-14 09:06:57 -07006880 if (status == NO_ERROR && inStream != NULL) {
Dima Zavin799a70e2011-04-18 16:57:27 -07006881 AudioStreamIn *input = new AudioStreamIn(inHwDev, inStream);
6882
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006883 // Start record thread
6884 // RecorThread require both input and output device indication to forward to audio
6885 // pre processing modules
6886 uint32_t device = (*pDevices) | primaryOutputDevice_l();
6887 thread = new RecordThread(this,
6888 input,
6889 reqSamplingRate,
6890 reqChannels,
6891 id,
6892 device);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006893 mRecordThreads.add(id, thread);
Steve Block3856b092011-10-20 11:56:00 +01006894 ALOGV("openInput() created record thread: ID %d thread %p", id, thread);
Glenn Kastena0d68332012-01-27 16:47:15 -08006895 if (pSamplingRate != NULL) *pSamplingRate = reqSamplingRate;
Eric Laurentf7ffb8b2012-04-14 09:06:57 -07006896 if (pFormat != NULL) *pFormat = config.format;
Eric Laurenta4c5a552012-03-29 10:12:40 -07006897 if (pChannelMask != NULL) *pChannelMask = reqChannels;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006898
Dima Zavin799a70e2011-04-18 16:57:27 -07006899 input->stream->common.standby(&input->stream->common);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006900
6901 // notify client processes of the new input creation
6902 thread->audioConfigChanged_l(AudioSystem::INPUT_OPENED);
6903 return id;
6904 }
6905
6906 return 0;
6907}
6908
Glenn Kasten72ef00d2012-01-17 11:09:42 -08006909status_t AudioFlinger::closeInput(audio_io_handle_t input)
Mathias Agopian65ab4712010-07-14 17:59:35 -07006910{
6911 // keep strong reference on the record thread so that
6912 // it is not destroyed while exit() is executed
Glenn Kastene53b9ea2012-03-12 16:29:55 -07006913 sp<RecordThread> thread;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006914 {
6915 Mutex::Autolock _l(mLock);
6916 thread = checkRecordThread_l(input);
6917 if (thread == NULL) {
6918 return BAD_VALUE;
6919 }
6920
Steve Block3856b092011-10-20 11:56:00 +01006921 ALOGV("closeInput() %d", input);
Glenn Kastena1117922012-01-26 10:53:32 -08006922 audioConfigChanged_l(AudioSystem::INPUT_CLOSED, input, NULL);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006923 mRecordThreads.removeItem(input);
6924 }
6925 thread->exit();
Glenn Kastenb28686f2012-01-06 08:39:38 -08006926 // The thread entity (active unit of execution) is no longer running here,
6927 // but the ThreadBase container still exists.
Mathias Agopian65ab4712010-07-14 17:59:35 -07006928
Eric Laurentb8ba0a92011-08-07 16:32:26 -07006929 AudioStreamIn *in = thread->clearInput();
Glenn Kasten5798d4e2012-03-08 12:18:35 -08006930 ALOG_ASSERT(in != NULL, "in shouldn't be NULL");
Eric Laurentb8ba0a92011-08-07 16:32:26 -07006931 // from now on thread->mInput is NULL
Dima Zavin799a70e2011-04-18 16:57:27 -07006932 in->hwDev->close_input_stream(in->hwDev, in->stream);
6933 delete in;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006934
6935 return NO_ERROR;
6936}
6937
Glenn Kasten72ef00d2012-01-17 11:09:42 -08006938status_t AudioFlinger::setStreamOutput(audio_stream_type_t stream, audio_io_handle_t output)
Mathias Agopian65ab4712010-07-14 17:59:35 -07006939{
6940 Mutex::Autolock _l(mLock);
6941 MixerThread *dstThread = checkMixerThread_l(output);
6942 if (dstThread == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +00006943 ALOGW("setStreamOutput() bad output id %d", output);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006944 return BAD_VALUE;
6945 }
6946
Steve Block3856b092011-10-20 11:56:00 +01006947 ALOGV("setStreamOutput() stream %d to output %d", stream, output);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006948 audioConfigChanged_l(AudioSystem::STREAM_CONFIG_CHANGED, output, &stream);
6949
6950 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
6951 PlaybackThread *thread = mPlaybackThreads.valueAt(i).get();
Glenn Kastena1117922012-01-26 10:53:32 -08006952 if (thread != dstThread && thread->type() != ThreadBase::DIRECT) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07006953 MixerThread *srcThread = (MixerThread *)thread;
6954 srcThread->invalidateTracks(stream);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006955 }
Eric Laurentde070132010-07-13 04:45:46 -07006956 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07006957
6958 return NO_ERROR;
6959}
6960
6961
6962int AudioFlinger::newAudioSessionId()
6963{
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006964 return nextUniqueId();
Mathias Agopian65ab4712010-07-14 17:59:35 -07006965}
6966
Marco Nelissen3a34bef2011-08-02 13:33:41 -07006967void AudioFlinger::acquireAudioSessionId(int audioSession)
6968{
6969 Mutex::Autolock _l(mLock);
Glenn Kastenbb001922012-02-03 11:10:26 -08006970 pid_t caller = IPCThreadState::self()->getCallingPid();
Steve Block3856b092011-10-20 11:56:00 +01006971 ALOGV("acquiring %d from %d", audioSession, caller);
Glenn Kasten8d6a2442012-02-08 14:04:28 -08006972 size_t num = mAudioSessionRefs.size();
6973 for (size_t i = 0; i< num; i++) {
Marco Nelissen3a34bef2011-08-02 13:33:41 -07006974 AudioSessionRef *ref = mAudioSessionRefs.editItemAt(i);
Glenn Kasten012ca6b2012-03-06 11:22:01 -08006975 if (ref->mSessionid == audioSession && ref->mPid == caller) {
6976 ref->mCnt++;
6977 ALOGV(" incremented refcount to %d", ref->mCnt);
Marco Nelissen3a34bef2011-08-02 13:33:41 -07006978 return;
6979 }
6980 }
Glenn Kasten84afa3b2012-01-25 15:28:08 -08006981 mAudioSessionRefs.push(new AudioSessionRef(audioSession, caller));
6982 ALOGV(" added new entry for %d", audioSession);
Marco Nelissen3a34bef2011-08-02 13:33:41 -07006983}
6984
6985void AudioFlinger::releaseAudioSessionId(int audioSession)
6986{
6987 Mutex::Autolock _l(mLock);
Glenn Kastenbb001922012-02-03 11:10:26 -08006988 pid_t caller = IPCThreadState::self()->getCallingPid();
Steve Block3856b092011-10-20 11:56:00 +01006989 ALOGV("releasing %d from %d", audioSession, caller);
Glenn Kasten8d6a2442012-02-08 14:04:28 -08006990 size_t num = mAudioSessionRefs.size();
6991 for (size_t i = 0; i< num; i++) {
Marco Nelissen3a34bef2011-08-02 13:33:41 -07006992 AudioSessionRef *ref = mAudioSessionRefs.itemAt(i);
Glenn Kasten012ca6b2012-03-06 11:22:01 -08006993 if (ref->mSessionid == audioSession && ref->mPid == caller) {
6994 ref->mCnt--;
6995 ALOGV(" decremented refcount to %d", ref->mCnt);
6996 if (ref->mCnt == 0) {
Marco Nelissen3a34bef2011-08-02 13:33:41 -07006997 mAudioSessionRefs.removeAt(i);
6998 delete ref;
6999 purgeStaleEffects_l();
7000 }
7001 return;
7002 }
7003 }
Steve Block5ff1dd52012-01-05 23:22:43 +00007004 ALOGW("session id %d not found for pid %d", audioSession, caller);
Marco Nelissen3a34bef2011-08-02 13:33:41 -07007005}
7006
7007void AudioFlinger::purgeStaleEffects_l() {
7008
Steve Block3856b092011-10-20 11:56:00 +01007009 ALOGV("purging stale effects");
Marco Nelissen3a34bef2011-08-02 13:33:41 -07007010
7011 Vector< sp<EffectChain> > chains;
7012
7013 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
7014 sp<PlaybackThread> t = mPlaybackThreads.valueAt(i);
7015 for (size_t j = 0; j < t->mEffectChains.size(); j++) {
7016 sp<EffectChain> ec = t->mEffectChains[j];
Marco Nelissen0270b182011-08-12 14:14:39 -07007017 if (ec->sessionId() > AUDIO_SESSION_OUTPUT_MIX) {
7018 chains.push(ec);
7019 }
Marco Nelissen3a34bef2011-08-02 13:33:41 -07007020 }
7021 }
7022 for (size_t i = 0; i < mRecordThreads.size(); i++) {
7023 sp<RecordThread> t = mRecordThreads.valueAt(i);
7024 for (size_t j = 0; j < t->mEffectChains.size(); j++) {
7025 sp<EffectChain> ec = t->mEffectChains[j];
7026 chains.push(ec);
7027 }
7028 }
7029
7030 for (size_t i = 0; i < chains.size(); i++) {
7031 sp<EffectChain> ec = chains[i];
7032 int sessionid = ec->sessionId();
7033 sp<ThreadBase> t = ec->mThread.promote();
7034 if (t == 0) {
7035 continue;
7036 }
7037 size_t numsessionrefs = mAudioSessionRefs.size();
7038 bool found = false;
7039 for (size_t k = 0; k < numsessionrefs; k++) {
7040 AudioSessionRef *ref = mAudioSessionRefs.itemAt(k);
Glenn Kasten012ca6b2012-03-06 11:22:01 -08007041 if (ref->mSessionid == sessionid) {
Steve Block3856b092011-10-20 11:56:00 +01007042 ALOGV(" session %d still exists for %d with %d refs",
Glenn Kastene53b9ea2012-03-12 16:29:55 -07007043 sessionid, ref->mPid, ref->mCnt);
Marco Nelissen3a34bef2011-08-02 13:33:41 -07007044 found = true;
7045 break;
7046 }
7047 }
7048 if (!found) {
7049 // remove all effects from the chain
7050 while (ec->mEffects.size()) {
7051 sp<EffectModule> effect = ec->mEffects[0];
7052 effect->unPin();
7053 Mutex::Autolock _l (t->mLock);
7054 t->removeEffect_l(effect);
7055 for (size_t j = 0; j < effect->mHandles.size(); j++) {
7056 sp<EffectHandle> handle = effect->mHandles[j].promote();
7057 if (handle != 0) {
7058 handle->mEffect.clear();
Eric Laurenta85a74a2011-10-19 11:44:54 -07007059 if (handle->mHasControl && handle->mEnabled) {
7060 t->checkSuspendOnEffectEnabled_l(effect, false, effect->sessionId());
7061 }
Marco Nelissen3a34bef2011-08-02 13:33:41 -07007062 }
7063 }
7064 AudioSystem::unregisterEffect(effect->id());
7065 }
7066 }
7067 }
7068 return;
7069}
7070
Mathias Agopian65ab4712010-07-14 17:59:35 -07007071// checkPlaybackThread_l() must be called with AudioFlinger::mLock held
Glenn Kasten72ef00d2012-01-17 11:09:42 -08007072AudioFlinger::PlaybackThread *AudioFlinger::checkPlaybackThread_l(audio_io_handle_t output) const
Mathias Agopian65ab4712010-07-14 17:59:35 -07007073{
Glenn Kastena1117922012-01-26 10:53:32 -08007074 return mPlaybackThreads.valueFor(output).get();
Mathias Agopian65ab4712010-07-14 17:59:35 -07007075}
7076
7077// checkMixerThread_l() must be called with AudioFlinger::mLock held
Glenn Kasten72ef00d2012-01-17 11:09:42 -08007078AudioFlinger::MixerThread *AudioFlinger::checkMixerThread_l(audio_io_handle_t output) const
Mathias Agopian65ab4712010-07-14 17:59:35 -07007079{
7080 PlaybackThread *thread = checkPlaybackThread_l(output);
Glenn Kastena1117922012-01-26 10:53:32 -08007081 return thread != NULL && thread->type() != ThreadBase::DIRECT ? (MixerThread *) thread : NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -07007082}
7083
7084// checkRecordThread_l() must be called with AudioFlinger::mLock held
Glenn Kasten72ef00d2012-01-17 11:09:42 -08007085AudioFlinger::RecordThread *AudioFlinger::checkRecordThread_l(audio_io_handle_t input) const
Mathias Agopian65ab4712010-07-14 17:59:35 -07007086{
Glenn Kastena1117922012-01-26 10:53:32 -08007087 return mRecordThreads.valueFor(input).get();
Mathias Agopian65ab4712010-07-14 17:59:35 -07007088}
7089
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007090uint32_t AudioFlinger::nextUniqueId()
Mathias Agopian65ab4712010-07-14 17:59:35 -07007091{
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007092 return android_atomic_inc(&mNextUniqueId);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007093}
7094
Glenn Kasten02fe1bf2012-02-24 15:42:17 -08007095AudioFlinger::PlaybackThread *AudioFlinger::primaryPlaybackThread_l() const
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007096{
7097 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
7098 PlaybackThread *thread = mPlaybackThreads.valueAt(i).get();
Eric Laurentb8ba0a92011-08-07 16:32:26 -07007099 AudioStreamOut *output = thread->getOutput();
7100 if (output != NULL && output->hwDev == mPrimaryHardwareDev) {
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007101 return thread;
7102 }
7103 }
7104 return NULL;
7105}
7106
Glenn Kasten02fe1bf2012-02-24 15:42:17 -08007107uint32_t AudioFlinger::primaryOutputDevice_l() const
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007108{
7109 PlaybackThread *thread = primaryPlaybackThread_l();
7110
7111 if (thread == NULL) {
7112 return 0;
7113 }
7114
7115 return thread->device();
7116}
7117
Eric Laurenta011e352012-03-29 15:51:43 -07007118sp<AudioFlinger::SyncEvent> AudioFlinger::createSyncEvent(AudioSystem::sync_event_t type,
7119 int triggerSession,
7120 int listenerSession,
7121 sync_event_callback_t callBack,
7122 void *cookie)
7123{
7124 Mutex::Autolock _l(mLock);
7125
7126 sp<SyncEvent> event = new SyncEvent(type, triggerSession, listenerSession, callBack, cookie);
7127 status_t playStatus = NAME_NOT_FOUND;
7128 status_t recStatus = NAME_NOT_FOUND;
7129 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
7130 playStatus = mPlaybackThreads.valueAt(i)->setSyncEvent(event);
7131 if (playStatus == NO_ERROR) {
7132 return event;
7133 }
7134 }
7135 for (size_t i = 0; i < mRecordThreads.size(); i++) {
7136 recStatus = mRecordThreads.valueAt(i)->setSyncEvent(event);
7137 if (recStatus == NO_ERROR) {
7138 return event;
7139 }
7140 }
7141 if (playStatus == NAME_NOT_FOUND || recStatus == NAME_NOT_FOUND) {
7142 mPendingSyncEvents.add(event);
7143 } else {
7144 ALOGV("createSyncEvent() invalid event %d", event->type());
7145 event.clear();
7146 }
7147 return event;
7148}
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007149
Mathias Agopian65ab4712010-07-14 17:59:35 -07007150// ----------------------------------------------------------------------------
7151// Effect management
7152// ----------------------------------------------------------------------------
7153
7154
Glenn Kastenf587ba52012-01-26 16:25:10 -08007155status_t AudioFlinger::queryNumberEffects(uint32_t *numEffects) const
Mathias Agopian65ab4712010-07-14 17:59:35 -07007156{
7157 Mutex::Autolock _l(mLock);
7158 return EffectQueryNumberEffects(numEffects);
7159}
7160
Glenn Kastenf587ba52012-01-26 16:25:10 -08007161status_t AudioFlinger::queryEffect(uint32_t index, effect_descriptor_t *descriptor) const
Mathias Agopian65ab4712010-07-14 17:59:35 -07007162{
7163 Mutex::Autolock _l(mLock);
7164 return EffectQueryEffect(index, descriptor);
7165}
7166
Glenn Kasten5e92a782012-01-30 07:40:52 -08007167status_t AudioFlinger::getEffectDescriptor(const effect_uuid_t *pUuid,
Glenn Kastenf587ba52012-01-26 16:25:10 -08007168 effect_descriptor_t *descriptor) const
Mathias Agopian65ab4712010-07-14 17:59:35 -07007169{
7170 Mutex::Autolock _l(mLock);
7171 return EffectGetDescriptor(pUuid, descriptor);
7172}
7173
7174
Mathias Agopian65ab4712010-07-14 17:59:35 -07007175sp<IEffect> AudioFlinger::createEffect(pid_t pid,
7176 effect_descriptor_t *pDesc,
7177 const sp<IEffectClient>& effectClient,
7178 int32_t priority,
Glenn Kasten72ef00d2012-01-17 11:09:42 -08007179 audio_io_handle_t io,
Mathias Agopian65ab4712010-07-14 17:59:35 -07007180 int sessionId,
7181 status_t *status,
7182 int *id,
7183 int *enabled)
7184{
7185 status_t lStatus = NO_ERROR;
7186 sp<EffectHandle> handle;
Mathias Agopian65ab4712010-07-14 17:59:35 -07007187 effect_descriptor_t desc;
Mathias Agopian65ab4712010-07-14 17:59:35 -07007188
Glenn Kasten98ec94c2012-01-25 14:28:29 -08007189 ALOGV("createEffect pid %d, effectClient %p, priority %d, sessionId %d, io %d",
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007190 pid, effectClient.get(), priority, sessionId, io);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007191
7192 if (pDesc == NULL) {
7193 lStatus = BAD_VALUE;
7194 goto Exit;
7195 }
7196
Eric Laurent84e9a102010-09-23 16:10:16 -07007197 // check audio settings permission for global effects
Dima Zavinfce7a472011-04-19 22:30:36 -07007198 if (sessionId == AUDIO_SESSION_OUTPUT_MIX && !settingsAllowed()) {
Eric Laurent84e9a102010-09-23 16:10:16 -07007199 lStatus = PERMISSION_DENIED;
7200 goto Exit;
7201 }
7202
Dima Zavinfce7a472011-04-19 22:30:36 -07007203 // Session AUDIO_SESSION_OUTPUT_STAGE is reserved for output stage effects
Eric Laurent84e9a102010-09-23 16:10:16 -07007204 // that can only be created by audio policy manager (running in same process)
Glenn Kasten44deb052012-02-05 18:09:08 -08007205 if (sessionId == AUDIO_SESSION_OUTPUT_STAGE && getpid_cached != pid) {
Eric Laurent84e9a102010-09-23 16:10:16 -07007206 lStatus = PERMISSION_DENIED;
7207 goto Exit;
7208 }
7209
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007210 if (io == 0) {
Dima Zavinfce7a472011-04-19 22:30:36 -07007211 if (sessionId == AUDIO_SESSION_OUTPUT_STAGE) {
Eric Laurent84e9a102010-09-23 16:10:16 -07007212 // output must be specified by AudioPolicyManager when using session
Dima Zavinfce7a472011-04-19 22:30:36 -07007213 // AUDIO_SESSION_OUTPUT_STAGE
Eric Laurent84e9a102010-09-23 16:10:16 -07007214 lStatus = BAD_VALUE;
7215 goto Exit;
Dima Zavinfce7a472011-04-19 22:30:36 -07007216 } else if (sessionId == AUDIO_SESSION_OUTPUT_MIX) {
Eric Laurent84e9a102010-09-23 16:10:16 -07007217 // if the output returned by getOutputForEffect() is removed before we lock the
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007218 // mutex below, the call to checkPlaybackThread_l(io) below will detect it
Eric Laurent84e9a102010-09-23 16:10:16 -07007219 // and we will exit safely
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007220 io = AudioSystem::getOutputForEffect(&desc);
Eric Laurent84e9a102010-09-23 16:10:16 -07007221 }
7222 }
7223
Mathias Agopian65ab4712010-07-14 17:59:35 -07007224 {
7225 Mutex::Autolock _l(mLock);
7226
Mathias Agopian65ab4712010-07-14 17:59:35 -07007227
7228 if (!EffectIsNullUuid(&pDesc->uuid)) {
7229 // if uuid is specified, request effect descriptor
7230 lStatus = EffectGetDescriptor(&pDesc->uuid, &desc);
7231 if (lStatus < 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00007232 ALOGW("createEffect() error %d from EffectGetDescriptor", lStatus);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007233 goto Exit;
7234 }
7235 } else {
7236 // if uuid is not specified, look for an available implementation
7237 // of the required type in effect factory
7238 if (EffectIsNullUuid(&pDesc->type)) {
Steve Block5ff1dd52012-01-05 23:22:43 +00007239 ALOGW("createEffect() no effect type");
Mathias Agopian65ab4712010-07-14 17:59:35 -07007240 lStatus = BAD_VALUE;
7241 goto Exit;
7242 }
7243 uint32_t numEffects = 0;
7244 effect_descriptor_t d;
Marco Nelissen3a34bef2011-08-02 13:33:41 -07007245 d.flags = 0; // prevent compiler warning
Mathias Agopian65ab4712010-07-14 17:59:35 -07007246 bool found = false;
7247
7248 lStatus = EffectQueryNumberEffects(&numEffects);
7249 if (lStatus < 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00007250 ALOGW("createEffect() error %d from EffectQueryNumberEffects", lStatus);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007251 goto Exit;
7252 }
7253 for (uint32_t i = 0; i < numEffects; i++) {
7254 lStatus = EffectQueryEffect(i, &desc);
7255 if (lStatus < 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00007256 ALOGW("createEffect() error %d from EffectQueryEffect", lStatus);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007257 continue;
7258 }
7259 if (memcmp(&desc.type, &pDesc->type, sizeof(effect_uuid_t)) == 0) {
7260 // If matching type found save effect descriptor. If the session is
7261 // 0 and the effect is not auxiliary, continue enumeration in case
7262 // an auxiliary version of this effect type is available
7263 found = true;
7264 memcpy(&d, &desc, sizeof(effect_descriptor_t));
Dima Zavinfce7a472011-04-19 22:30:36 -07007265 if (sessionId != AUDIO_SESSION_OUTPUT_MIX ||
Mathias Agopian65ab4712010-07-14 17:59:35 -07007266 (desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
7267 break;
7268 }
7269 }
7270 }
7271 if (!found) {
7272 lStatus = BAD_VALUE;
Steve Block5ff1dd52012-01-05 23:22:43 +00007273 ALOGW("createEffect() effect not found");
Mathias Agopian65ab4712010-07-14 17:59:35 -07007274 goto Exit;
7275 }
7276 // For same effect type, chose auxiliary version over insert version if
7277 // connect to output mix (Compliance to OpenSL ES)
Dima Zavinfce7a472011-04-19 22:30:36 -07007278 if (sessionId == AUDIO_SESSION_OUTPUT_MIX &&
Mathias Agopian65ab4712010-07-14 17:59:35 -07007279 (d.flags & EFFECT_FLAG_TYPE_MASK) != EFFECT_FLAG_TYPE_AUXILIARY) {
7280 memcpy(&desc, &d, sizeof(effect_descriptor_t));
7281 }
7282 }
7283
7284 // Do not allow auxiliary effects on a session different from 0 (output mix)
Dima Zavinfce7a472011-04-19 22:30:36 -07007285 if (sessionId != AUDIO_SESSION_OUTPUT_MIX &&
Mathias Agopian65ab4712010-07-14 17:59:35 -07007286 (desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
7287 lStatus = INVALID_OPERATION;
7288 goto Exit;
7289 }
7290
Eric Laurent59255e42011-07-27 19:49:51 -07007291 // check recording permission for visualizer
7292 if ((memcmp(&desc.type, SL_IID_VISUALIZATION, sizeof(effect_uuid_t)) == 0) &&
7293 !recordingAllowed()) {
7294 lStatus = PERMISSION_DENIED;
7295 goto Exit;
7296 }
7297
Mathias Agopian65ab4712010-07-14 17:59:35 -07007298 // return effect descriptor
7299 memcpy(pDesc, &desc, sizeof(effect_descriptor_t));
7300
7301 // If output is not specified try to find a matching audio session ID in one of the
7302 // output threads.
Eric Laurent84e9a102010-09-23 16:10:16 -07007303 // If output is 0 here, sessionId is neither SESSION_OUTPUT_STAGE nor SESSION_OUTPUT_MIX
7304 // because of code checking output when entering the function.
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007305 // Note: io is never 0 when creating an effect on an input
7306 if (io == 0) {
Glenn Kastene53b9ea2012-03-12 16:29:55 -07007307 // look for the thread where the specified audio session is present
Eric Laurent84e9a102010-09-23 16:10:16 -07007308 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
7309 if (mPlaybackThreads.valueAt(i)->hasAudioSession(sessionId) != 0) {
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007310 io = mPlaybackThreads.keyAt(i);
Eric Laurent84e9a102010-09-23 16:10:16 -07007311 break;
Eric Laurent39e94f82010-07-28 01:32:47 -07007312 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07007313 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007314 if (io == 0) {
Glenn Kastene53b9ea2012-03-12 16:29:55 -07007315 for (size_t i = 0; i < mRecordThreads.size(); i++) {
7316 if (mRecordThreads.valueAt(i)->hasAudioSession(sessionId) != 0) {
7317 io = mRecordThreads.keyAt(i);
7318 break;
7319 }
7320 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007321 }
Eric Laurent84e9a102010-09-23 16:10:16 -07007322 // If no output thread contains the requested session ID, default to
7323 // first output. The effect chain will be moved to the correct output
7324 // thread when a track with the same session ID is created
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007325 if (io == 0 && mPlaybackThreads.size()) {
7326 io = mPlaybackThreads.keyAt(0);
7327 }
Steve Block3856b092011-10-20 11:56:00 +01007328 ALOGV("createEffect() got io %d for effect %s", io, desc.name);
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007329 }
7330 ThreadBase *thread = checkRecordThread_l(io);
7331 if (thread == NULL) {
7332 thread = checkPlaybackThread_l(io);
7333 if (thread == NULL) {
Steve Block29357bc2012-01-06 19:20:56 +00007334 ALOGE("createEffect() unknown output thread");
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007335 lStatus = BAD_VALUE;
7336 goto Exit;
Eric Laurent84e9a102010-09-23 16:10:16 -07007337 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07007338 }
Eric Laurent84e9a102010-09-23 16:10:16 -07007339
Glenn Kasten98ec94c2012-01-25 14:28:29 -08007340 sp<Client> client = registerPid_l(pid);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007341
Marco Nelissen3a34bef2011-08-02 13:33:41 -07007342 // create effect on selected output thread
Eric Laurentde070132010-07-13 04:45:46 -07007343 handle = thread->createEffect_l(client, effectClient, priority, sessionId,
7344 &desc, enabled, &lStatus);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007345 if (handle != 0 && id != NULL) {
7346 *id = handle->id();
7347 }
7348 }
7349
7350Exit:
Glenn Kastene53b9ea2012-03-12 16:29:55 -07007351 if (status != NULL) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07007352 *status = lStatus;
7353 }
7354 return handle;
7355}
7356
Glenn Kasten72ef00d2012-01-17 11:09:42 -08007357status_t AudioFlinger::moveEffects(int sessionId, audio_io_handle_t srcOutput,
7358 audio_io_handle_t dstOutput)
Eric Laurentde070132010-07-13 04:45:46 -07007359{
Steve Block3856b092011-10-20 11:56:00 +01007360 ALOGV("moveEffects() session %d, srcOutput %d, dstOutput %d",
Eric Laurent59255e42011-07-27 19:49:51 -07007361 sessionId, srcOutput, dstOutput);
Eric Laurentde070132010-07-13 04:45:46 -07007362 Mutex::Autolock _l(mLock);
7363 if (srcOutput == dstOutput) {
Steve Block5ff1dd52012-01-05 23:22:43 +00007364 ALOGW("moveEffects() same dst and src outputs %d", dstOutput);
Eric Laurentde070132010-07-13 04:45:46 -07007365 return NO_ERROR;
Mathias Agopian65ab4712010-07-14 17:59:35 -07007366 }
Eric Laurentde070132010-07-13 04:45:46 -07007367 PlaybackThread *srcThread = checkPlaybackThread_l(srcOutput);
7368 if (srcThread == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +00007369 ALOGW("moveEffects() bad srcOutput %d", srcOutput);
Eric Laurentde070132010-07-13 04:45:46 -07007370 return BAD_VALUE;
Mathias Agopian65ab4712010-07-14 17:59:35 -07007371 }
Eric Laurentde070132010-07-13 04:45:46 -07007372 PlaybackThread *dstThread = checkPlaybackThread_l(dstOutput);
7373 if (dstThread == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +00007374 ALOGW("moveEffects() bad dstOutput %d", dstOutput);
Eric Laurentde070132010-07-13 04:45:46 -07007375 return BAD_VALUE;
7376 }
7377
7378 Mutex::Autolock _dl(dstThread->mLock);
7379 Mutex::Autolock _sl(srcThread->mLock);
Eric Laurent59255e42011-07-27 19:49:51 -07007380 moveEffectChain_l(sessionId, srcThread, dstThread, false);
Eric Laurentde070132010-07-13 04:45:46 -07007381
Mathias Agopian65ab4712010-07-14 17:59:35 -07007382 return NO_ERROR;
7383}
7384
Marco Nelissen3a34bef2011-08-02 13:33:41 -07007385// moveEffectChain_l must be called with both srcThread and dstThread mLocks held
Eric Laurent59255e42011-07-27 19:49:51 -07007386status_t AudioFlinger::moveEffectChain_l(int sessionId,
Eric Laurentde070132010-07-13 04:45:46 -07007387 AudioFlinger::PlaybackThread *srcThread,
Eric Laurent39e94f82010-07-28 01:32:47 -07007388 AudioFlinger::PlaybackThread *dstThread,
7389 bool reRegister)
Eric Laurentde070132010-07-13 04:45:46 -07007390{
Steve Block3856b092011-10-20 11:56:00 +01007391 ALOGV("moveEffectChain_l() session %d from thread %p to thread %p",
Eric Laurent59255e42011-07-27 19:49:51 -07007392 sessionId, srcThread, dstThread);
Eric Laurentde070132010-07-13 04:45:46 -07007393
Eric Laurent59255e42011-07-27 19:49:51 -07007394 sp<EffectChain> chain = srcThread->getEffectChain_l(sessionId);
Eric Laurentde070132010-07-13 04:45:46 -07007395 if (chain == 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00007396 ALOGW("moveEffectChain_l() effect chain for session %d not on source thread %p",
Eric Laurent59255e42011-07-27 19:49:51 -07007397 sessionId, srcThread);
Eric Laurentde070132010-07-13 04:45:46 -07007398 return INVALID_OPERATION;
7399 }
7400
Eric Laurent39e94f82010-07-28 01:32:47 -07007401 // remove chain first. This is useful only if reconfiguring effect chain on same output thread,
Eric Laurentde070132010-07-13 04:45:46 -07007402 // so that a new chain is created with correct parameters when first effect is added. This is
Eric Laurentec35a142011-10-05 17:42:25 -07007403 // otherwise unnecessary as removeEffect_l() will remove the chain when last effect is
Eric Laurentde070132010-07-13 04:45:46 -07007404 // removed.
7405 srcThread->removeEffectChain_l(chain);
7406
7407 // transfer all effects one by one so that new effect chain is created on new thread with
7408 // correct buffer sizes and audio parameters and effect engines reconfigured accordingly
Glenn Kasten72ef00d2012-01-17 11:09:42 -08007409 audio_io_handle_t dstOutput = dstThread->id();
Eric Laurent39e94f82010-07-28 01:32:47 -07007410 sp<EffectChain> dstChain;
Marco Nelissen3a34bef2011-08-02 13:33:41 -07007411 uint32_t strategy = 0; // prevent compiler warning
Eric Laurentde070132010-07-13 04:45:46 -07007412 sp<EffectModule> effect = chain->getEffectFromId_l(0);
7413 while (effect != 0) {
7414 srcThread->removeEffect_l(effect);
7415 dstThread->addEffect_l(effect);
Eric Laurentec35a142011-10-05 17:42:25 -07007416 // removeEffect_l() has stopped the effect if it was active so it must be restarted
7417 if (effect->state() == EffectModule::ACTIVE ||
7418 effect->state() == EffectModule::STOPPING) {
7419 effect->start();
7420 }
Eric Laurent39e94f82010-07-28 01:32:47 -07007421 // if the move request is not received from audio policy manager, the effect must be
7422 // re-registered with the new strategy and output
7423 if (dstChain == 0) {
7424 dstChain = effect->chain().promote();
7425 if (dstChain == 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00007426 ALOGW("moveEffectChain_l() cannot get chain from effect %p", effect.get());
Eric Laurent39e94f82010-07-28 01:32:47 -07007427 srcThread->addEffect_l(effect);
7428 return NO_INIT;
7429 }
7430 strategy = dstChain->strategy();
7431 }
7432 if (reRegister) {
7433 AudioSystem::unregisterEffect(effect->id());
7434 AudioSystem::registerEffect(&effect->desc(),
7435 dstOutput,
7436 strategy,
Eric Laurent59255e42011-07-27 19:49:51 -07007437 sessionId,
Eric Laurent39e94f82010-07-28 01:32:47 -07007438 effect->id());
7439 }
Eric Laurentde070132010-07-13 04:45:46 -07007440 effect = chain->getEffectFromId_l(0);
7441 }
7442
7443 return NO_ERROR;
Mathias Agopian65ab4712010-07-14 17:59:35 -07007444}
7445
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007446
Mathias Agopian65ab4712010-07-14 17:59:35 -07007447// PlaybackThread::createEffect_l() must be called with AudioFlinger::mLock held
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007448sp<AudioFlinger::EffectHandle> AudioFlinger::ThreadBase::createEffect_l(
Mathias Agopian65ab4712010-07-14 17:59:35 -07007449 const sp<AudioFlinger::Client>& client,
7450 const sp<IEffectClient>& effectClient,
7451 int32_t priority,
7452 int sessionId,
7453 effect_descriptor_t *desc,
7454 int *enabled,
7455 status_t *status
7456 )
7457{
7458 sp<EffectModule> effect;
7459 sp<EffectHandle> handle;
7460 status_t lStatus;
Mathias Agopian65ab4712010-07-14 17:59:35 -07007461 sp<EffectChain> chain;
Eric Laurentde070132010-07-13 04:45:46 -07007462 bool chainCreated = false;
Mathias Agopian65ab4712010-07-14 17:59:35 -07007463 bool effectCreated = false;
7464 bool effectRegistered = false;
7465
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007466 lStatus = initCheck();
7467 if (lStatus != NO_ERROR) {
Steve Block5ff1dd52012-01-05 23:22:43 +00007468 ALOGW("createEffect_l() Audio driver not initialized.");
Mathias Agopian65ab4712010-07-14 17:59:35 -07007469 goto Exit;
7470 }
7471
7472 // Do not allow effects with session ID 0 on direct output or duplicating threads
7473 // TODO: add rule for hw accelerated effects on direct outputs with non PCM format
Dima Zavinfce7a472011-04-19 22:30:36 -07007474 if (sessionId == AUDIO_SESSION_OUTPUT_MIX && mType != MIXER) {
Steve Block5ff1dd52012-01-05 23:22:43 +00007475 ALOGW("createEffect_l() Cannot add auxiliary effect %s to session %d",
Eric Laurentde070132010-07-13 04:45:46 -07007476 desc->name, sessionId);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007477 lStatus = BAD_VALUE;
7478 goto Exit;
7479 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007480 // Only Pre processor effects are allowed on input threads and only on input threads
Glenn Kastena1117922012-01-26 10:53:32 -08007481 if ((mType == RECORD) != ((desc->flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC)) {
Steve Block5ff1dd52012-01-05 23:22:43 +00007482 ALOGW("createEffect_l() effect %s (flags %08x) created on wrong thread type %d",
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007483 desc->name, desc->flags, mType);
7484 lStatus = BAD_VALUE;
7485 goto Exit;
7486 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07007487
Steve Block3856b092011-10-20 11:56:00 +01007488 ALOGV("createEffect_l() thread %p effect %s on session %d", this, desc->name, sessionId);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007489
7490 { // scope for mLock
7491 Mutex::Autolock _l(mLock);
7492
7493 // check for existing effect chain with the requested audio session
7494 chain = getEffectChain_l(sessionId);
7495 if (chain == 0) {
7496 // create a new chain for this session
Steve Block3856b092011-10-20 11:56:00 +01007497 ALOGV("createEffect_l() new effect chain for session %d", sessionId);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007498 chain = new EffectChain(this, sessionId);
7499 addEffectChain_l(chain);
Eric Laurentde070132010-07-13 04:45:46 -07007500 chain->setStrategy(getStrategyForSession_l(sessionId));
7501 chainCreated = true;
Mathias Agopian65ab4712010-07-14 17:59:35 -07007502 } else {
Eric Laurentcab11242010-07-15 12:50:15 -07007503 effect = chain->getEffectFromDesc_l(desc);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007504 }
7505
Glenn Kasten7fc9a6f2012-01-10 10:46:34 -08007506 ALOGV("createEffect_l() got effect %p on chain %p", effect.get(), chain.get());
Mathias Agopian65ab4712010-07-14 17:59:35 -07007507
7508 if (effect == 0) {
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007509 int id = mAudioFlinger->nextUniqueId();
Mathias Agopian65ab4712010-07-14 17:59:35 -07007510 // Check CPU and memory usage
Eric Laurentde070132010-07-13 04:45:46 -07007511 lStatus = AudioSystem::registerEffect(desc, mId, chain->strategy(), sessionId, id);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007512 if (lStatus != NO_ERROR) {
7513 goto Exit;
7514 }
7515 effectRegistered = true;
7516 // create a new effect module if none present in the chain
Eric Laurentde070132010-07-13 04:45:46 -07007517 effect = new EffectModule(this, chain, desc, id, sessionId);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007518 lStatus = effect->status();
7519 if (lStatus != NO_ERROR) {
7520 goto Exit;
7521 }
Eric Laurentcab11242010-07-15 12:50:15 -07007522 lStatus = chain->addEffect_l(effect);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007523 if (lStatus != NO_ERROR) {
7524 goto Exit;
7525 }
7526 effectCreated = true;
7527
7528 effect->setDevice(mDevice);
7529 effect->setMode(mAudioFlinger->getMode());
7530 }
7531 // create effect handle and connect it to effect module
7532 handle = new EffectHandle(effect, client, effectClient, priority);
7533 lStatus = effect->addHandle(handle);
Glenn Kastena0d68332012-01-27 16:47:15 -08007534 if (enabled != NULL) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07007535 *enabled = (int)effect->isEnabled();
7536 }
7537 }
7538
7539Exit:
7540 if (lStatus != NO_ERROR && lStatus != ALREADY_EXISTS) {
Eric Laurentde070132010-07-13 04:45:46 -07007541 Mutex::Autolock _l(mLock);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007542 if (effectCreated) {
Eric Laurentde070132010-07-13 04:45:46 -07007543 chain->removeEffect_l(effect);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007544 }
7545 if (effectRegistered) {
Eric Laurentde070132010-07-13 04:45:46 -07007546 AudioSystem::unregisterEffect(effect->id());
7547 }
7548 if (chainCreated) {
7549 removeEffectChain_l(chain);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007550 }
7551 handle.clear();
7552 }
7553
Glenn Kastene53b9ea2012-03-12 16:29:55 -07007554 if (status != NULL) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07007555 *status = lStatus;
7556 }
7557 return handle;
7558}
7559
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007560sp<AudioFlinger::EffectModule> AudioFlinger::ThreadBase::getEffect_l(int sessionId, int effectId)
7561{
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007562 sp<EffectChain> chain = getEffectChain_l(sessionId);
Glenn Kasten090f0192012-01-30 13:00:02 -08007563 return chain != 0 ? chain->getEffectFromId_l(effectId) : 0;
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007564}
7565
Eric Laurentde070132010-07-13 04:45:46 -07007566// PlaybackThread::addEffect_l() must be called with AudioFlinger::mLock and
7567// PlaybackThread::mLock held
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007568status_t AudioFlinger::ThreadBase::addEffect_l(const sp<EffectModule>& effect)
Eric Laurentde070132010-07-13 04:45:46 -07007569{
7570 // check for existing effect chain with the requested audio session
7571 int sessionId = effect->sessionId();
7572 sp<EffectChain> chain = getEffectChain_l(sessionId);
7573 bool chainCreated = false;
7574
7575 if (chain == 0) {
7576 // create a new chain for this session
Steve Block3856b092011-10-20 11:56:00 +01007577 ALOGV("addEffect_l() new effect chain for session %d", sessionId);
Eric Laurentde070132010-07-13 04:45:46 -07007578 chain = new EffectChain(this, sessionId);
7579 addEffectChain_l(chain);
7580 chain->setStrategy(getStrategyForSession_l(sessionId));
7581 chainCreated = true;
7582 }
Steve Block3856b092011-10-20 11:56:00 +01007583 ALOGV("addEffect_l() %p chain %p effect %p", this, chain.get(), effect.get());
Eric Laurentde070132010-07-13 04:45:46 -07007584
7585 if (chain->getEffectFromId_l(effect->id()) != 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00007586 ALOGW("addEffect_l() %p effect %s already present in chain %p",
Eric Laurentde070132010-07-13 04:45:46 -07007587 this, effect->desc().name, chain.get());
7588 return BAD_VALUE;
7589 }
7590
7591 status_t status = chain->addEffect_l(effect);
7592 if (status != NO_ERROR) {
7593 if (chainCreated) {
7594 removeEffectChain_l(chain);
7595 }
7596 return status;
7597 }
7598
7599 effect->setDevice(mDevice);
7600 effect->setMode(mAudioFlinger->getMode());
7601 return NO_ERROR;
7602}
7603
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007604void AudioFlinger::ThreadBase::removeEffect_l(const sp<EffectModule>& effect) {
Eric Laurentde070132010-07-13 04:45:46 -07007605
Steve Block3856b092011-10-20 11:56:00 +01007606 ALOGV("removeEffect_l() %p effect %p", this, effect.get());
Mathias Agopian65ab4712010-07-14 17:59:35 -07007607 effect_descriptor_t desc = effect->desc();
Eric Laurentde070132010-07-13 04:45:46 -07007608 if ((desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
7609 detachAuxEffect_l(effect->id());
7610 }
7611
7612 sp<EffectChain> chain = effect->chain().promote();
7613 if (chain != 0) {
7614 // remove effect chain if removing last effect
7615 if (chain->removeEffect_l(effect) == 0) {
7616 removeEffectChain_l(chain);
7617 }
7618 } else {
Steve Block5ff1dd52012-01-05 23:22:43 +00007619 ALOGW("removeEffect_l() %p cannot promote chain for effect %p", this, effect.get());
Eric Laurentde070132010-07-13 04:45:46 -07007620 }
7621}
7622
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007623void AudioFlinger::ThreadBase::lockEffectChains_l(
Glenn Kastene53b9ea2012-03-12 16:29:55 -07007624 Vector< sp<AudioFlinger::EffectChain> >& effectChains)
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007625{
7626 effectChains = mEffectChains;
7627 for (size_t i = 0; i < mEffectChains.size(); i++) {
7628 mEffectChains[i]->lock();
7629 }
7630}
7631
7632void AudioFlinger::ThreadBase::unlockEffectChains(
Glenn Kastene53b9ea2012-03-12 16:29:55 -07007633 const Vector< sp<AudioFlinger::EffectChain> >& effectChains)
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007634{
7635 for (size_t i = 0; i < effectChains.size(); i++) {
7636 effectChains[i]->unlock();
7637 }
7638}
7639
7640sp<AudioFlinger::EffectChain> AudioFlinger::ThreadBase::getEffectChain(int sessionId)
7641{
7642 Mutex::Autolock _l(mLock);
7643 return getEffectChain_l(sessionId);
7644}
7645
7646sp<AudioFlinger::EffectChain> AudioFlinger::ThreadBase::getEffectChain_l(int sessionId)
7647{
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007648 size_t size = mEffectChains.size();
7649 for (size_t i = 0; i < size; i++) {
7650 if (mEffectChains[i]->sessionId() == sessionId) {
Glenn Kasten090f0192012-01-30 13:00:02 -08007651 return mEffectChains[i];
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007652 }
7653 }
Glenn Kasten090f0192012-01-30 13:00:02 -08007654 return 0;
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007655}
7656
Glenn Kastenf78aee72012-01-04 11:00:47 -08007657void AudioFlinger::ThreadBase::setMode(audio_mode_t mode)
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007658{
7659 Mutex::Autolock _l(mLock);
7660 size_t size = mEffectChains.size();
7661 for (size_t i = 0; i < size; i++) {
7662 mEffectChains[i]->setMode_l(mode);
7663 }
7664}
7665
7666void AudioFlinger::ThreadBase::disconnectEffect(const sp<EffectModule>& effect,
Marco Nelissen3a34bef2011-08-02 13:33:41 -07007667 const wp<EffectHandle>& handle,
Glenn Kasten58123c32012-02-03 10:32:24 -08007668 bool unpinIfLast) {
Eric Laurent59255e42011-07-27 19:49:51 -07007669
Mathias Agopian65ab4712010-07-14 17:59:35 -07007670 Mutex::Autolock _l(mLock);
Steve Block3856b092011-10-20 11:56:00 +01007671 ALOGV("disconnectEffect() %p effect %p", this, effect.get());
Mathias Agopian65ab4712010-07-14 17:59:35 -07007672 // delete the effect module if removing last handle on it
7673 if (effect->removeHandle(handle) == 0) {
Glenn Kasten58123c32012-02-03 10:32:24 -08007674 if (!effect->isPinned() || unpinIfLast) {
Marco Nelissen3a34bef2011-08-02 13:33:41 -07007675 removeEffect_l(effect);
7676 AudioSystem::unregisterEffect(effect->id());
7677 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07007678 }
7679}
7680
7681status_t AudioFlinger::PlaybackThread::addEffectChain_l(const sp<EffectChain>& chain)
7682{
7683 int session = chain->sessionId();
7684 int16_t *buffer = mMixBuffer;
7685 bool ownsBuffer = false;
7686
Steve Block3856b092011-10-20 11:56:00 +01007687 ALOGV("addEffectChain_l() %p on thread %p for session %d", chain.get(), this, session);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007688 if (session > 0) {
7689 // Only one effect chain can be present in direct output thread and it uses
7690 // the mix buffer as input
7691 if (mType != DIRECT) {
Glenn Kasten58912562012-04-03 10:45:00 -07007692 size_t numSamples = mNormalFrameCount * mChannelCount;
Mathias Agopian65ab4712010-07-14 17:59:35 -07007693 buffer = new int16_t[numSamples];
7694 memset(buffer, 0, numSamples * sizeof(int16_t));
Steve Block3856b092011-10-20 11:56:00 +01007695 ALOGV("addEffectChain_l() creating new input buffer %p session %d", buffer, session);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007696 ownsBuffer = true;
7697 }
7698
7699 // Attach all tracks with same session ID to this chain.
7700 for (size_t i = 0; i < mTracks.size(); ++i) {
7701 sp<Track> track = mTracks[i];
7702 if (session == track->sessionId()) {
Steve Block3856b092011-10-20 11:56:00 +01007703 ALOGV("addEffectChain_l() track->setMainBuffer track %p buffer %p", track.get(), buffer);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007704 track->setMainBuffer(buffer);
Eric Laurentb469b942011-05-09 12:09:06 -07007705 chain->incTrackCnt();
Mathias Agopian65ab4712010-07-14 17:59:35 -07007706 }
7707 }
7708
7709 // indicate all active tracks in the chain
7710 for (size_t i = 0 ; i < mActiveTracks.size() ; ++i) {
7711 sp<Track> track = mActiveTracks[i].promote();
7712 if (track == 0) continue;
7713 if (session == track->sessionId()) {
Steve Block3856b092011-10-20 11:56:00 +01007714 ALOGV("addEffectChain_l() activating track %p on session %d", track.get(), session);
Eric Laurentb469b942011-05-09 12:09:06 -07007715 chain->incActiveTrackCnt();
Mathias Agopian65ab4712010-07-14 17:59:35 -07007716 }
7717 }
7718 }
7719
7720 chain->setInBuffer(buffer, ownsBuffer);
7721 chain->setOutBuffer(mMixBuffer);
Dima Zavinfce7a472011-04-19 22:30:36 -07007722 // Effect chain for session AUDIO_SESSION_OUTPUT_STAGE is inserted at end of effect
Eric Laurentde070132010-07-13 04:45:46 -07007723 // chains list in order to be processed last as it contains output stage effects
Dima Zavinfce7a472011-04-19 22:30:36 -07007724 // Effect chain for session AUDIO_SESSION_OUTPUT_MIX is inserted before
7725 // session AUDIO_SESSION_OUTPUT_STAGE to be processed
Mathias Agopian65ab4712010-07-14 17:59:35 -07007726 // after track specific effects and before output stage
Dima Zavinfce7a472011-04-19 22:30:36 -07007727 // It is therefore mandatory that AUDIO_SESSION_OUTPUT_MIX == 0 and
7728 // that AUDIO_SESSION_OUTPUT_STAGE < AUDIO_SESSION_OUTPUT_MIX
Eric Laurentde070132010-07-13 04:45:46 -07007729 // Effect chain for other sessions are inserted at beginning of effect
7730 // chains list to be processed before output mix effects. Relative order between other
7731 // sessions is not important
Mathias Agopian65ab4712010-07-14 17:59:35 -07007732 size_t size = mEffectChains.size();
7733 size_t i = 0;
7734 for (i = 0; i < size; i++) {
7735 if (mEffectChains[i]->sessionId() < session) break;
7736 }
7737 mEffectChains.insertAt(chain, i);
Eric Laurent59255e42011-07-27 19:49:51 -07007738 checkSuspendOnAddEffectChain_l(chain);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007739
7740 return NO_ERROR;
7741}
7742
7743size_t AudioFlinger::PlaybackThread::removeEffectChain_l(const sp<EffectChain>& chain)
7744{
7745 int session = chain->sessionId();
7746
Steve Block3856b092011-10-20 11:56:00 +01007747 ALOGV("removeEffectChain_l() %p from thread %p for session %d", chain.get(), this, session);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007748
7749 for (size_t i = 0; i < mEffectChains.size(); i++) {
7750 if (chain == mEffectChains[i]) {
7751 mEffectChains.removeAt(i);
Eric Laurentb469b942011-05-09 12:09:06 -07007752 // detach all active tracks from the chain
7753 for (size_t i = 0 ; i < mActiveTracks.size() ; ++i) {
7754 sp<Track> track = mActiveTracks[i].promote();
7755 if (track == 0) continue;
7756 if (session == track->sessionId()) {
Steve Block3856b092011-10-20 11:56:00 +01007757 ALOGV("removeEffectChain_l(): stopping track on chain %p for session Id: %d",
Eric Laurentb469b942011-05-09 12:09:06 -07007758 chain.get(), session);
7759 chain->decActiveTrackCnt();
7760 }
7761 }
7762
Mathias Agopian65ab4712010-07-14 17:59:35 -07007763 // detach all tracks with same session ID from this chain
7764 for (size_t i = 0; i < mTracks.size(); ++i) {
7765 sp<Track> track = mTracks[i];
7766 if (session == track->sessionId()) {
7767 track->setMainBuffer(mMixBuffer);
Eric Laurentb469b942011-05-09 12:09:06 -07007768 chain->decTrackCnt();
Mathias Agopian65ab4712010-07-14 17:59:35 -07007769 }
7770 }
Eric Laurentde070132010-07-13 04:45:46 -07007771 break;
Mathias Agopian65ab4712010-07-14 17:59:35 -07007772 }
7773 }
7774 return mEffectChains.size();
7775}
7776
Eric Laurentde070132010-07-13 04:45:46 -07007777status_t AudioFlinger::PlaybackThread::attachAuxEffect(
7778 const sp<AudioFlinger::PlaybackThread::Track> track, int EffectId)
Mathias Agopian65ab4712010-07-14 17:59:35 -07007779{
7780 Mutex::Autolock _l(mLock);
7781 return attachAuxEffect_l(track, EffectId);
7782}
7783
Eric Laurentde070132010-07-13 04:45:46 -07007784status_t AudioFlinger::PlaybackThread::attachAuxEffect_l(
7785 const sp<AudioFlinger::PlaybackThread::Track> track, int EffectId)
Mathias Agopian65ab4712010-07-14 17:59:35 -07007786{
7787 status_t status = NO_ERROR;
7788
7789 if (EffectId == 0) {
7790 track->setAuxBuffer(0, NULL);
7791 } else {
Dima Zavinfce7a472011-04-19 22:30:36 -07007792 // Auxiliary effects are always in audio session AUDIO_SESSION_OUTPUT_MIX
7793 sp<EffectModule> effect = getEffect_l(AUDIO_SESSION_OUTPUT_MIX, EffectId);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007794 if (effect != 0) {
7795 if ((effect->desc().flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
7796 track->setAuxBuffer(EffectId, (int32_t *)effect->inBuffer());
7797 } else {
7798 status = INVALID_OPERATION;
7799 }
7800 } else {
7801 status = BAD_VALUE;
7802 }
7803 }
7804 return status;
7805}
7806
7807void AudioFlinger::PlaybackThread::detachAuxEffect_l(int effectId)
7808{
Glenn Kastene53b9ea2012-03-12 16:29:55 -07007809 for (size_t i = 0; i < mTracks.size(); ++i) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07007810 sp<Track> track = mTracks[i];
7811 if (track->auxEffectId() == effectId) {
7812 attachAuxEffect_l(track, 0);
7813 }
7814 }
7815}
7816
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007817status_t AudioFlinger::RecordThread::addEffectChain_l(const sp<EffectChain>& chain)
7818{
7819 // only one chain per input thread
7820 if (mEffectChains.size() != 0) {
7821 return INVALID_OPERATION;
7822 }
Steve Block3856b092011-10-20 11:56:00 +01007823 ALOGV("addEffectChain_l() %p on thread %p", chain.get(), this);
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007824
7825 chain->setInBuffer(NULL);
7826 chain->setOutBuffer(NULL);
7827
Eric Laurent59255e42011-07-27 19:49:51 -07007828 checkSuspendOnAddEffectChain_l(chain);
7829
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007830 mEffectChains.add(chain);
7831
7832 return NO_ERROR;
7833}
7834
7835size_t AudioFlinger::RecordThread::removeEffectChain_l(const sp<EffectChain>& chain)
7836{
Steve Block3856b092011-10-20 11:56:00 +01007837 ALOGV("removeEffectChain_l() %p from thread %p", chain.get(), this);
Steve Block5ff1dd52012-01-05 23:22:43 +00007838 ALOGW_IF(mEffectChains.size() != 1,
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007839 "removeEffectChain_l() %p invalid chain size %d on thread %p",
7840 chain.get(), mEffectChains.size(), this);
7841 if (mEffectChains.size() == 1) {
7842 mEffectChains.removeAt(0);
7843 }
7844 return 0;
7845}
7846
Mathias Agopian65ab4712010-07-14 17:59:35 -07007847// ----------------------------------------------------------------------------
7848// EffectModule implementation
7849// ----------------------------------------------------------------------------
7850
7851#undef LOG_TAG
7852#define LOG_TAG "AudioFlinger::EffectModule"
7853
Glenn Kasten9eaa5572012-01-20 13:32:16 -08007854AudioFlinger::EffectModule::EffectModule(ThreadBase *thread,
Mathias Agopian65ab4712010-07-14 17:59:35 -07007855 const wp<AudioFlinger::EffectChain>& chain,
7856 effect_descriptor_t *desc,
7857 int id,
7858 int sessionId)
Glenn Kasten9eaa5572012-01-20 13:32:16 -08007859 : mThread(thread), mChain(chain), mId(id), mSessionId(sessionId), mEffectInterface(NULL),
Eric Laurent59255e42011-07-27 19:49:51 -07007860 mStatus(NO_INIT), mState(IDLE), mSuspended(false)
Mathias Agopian65ab4712010-07-14 17:59:35 -07007861{
Steve Block3856b092011-10-20 11:56:00 +01007862 ALOGV("Constructor %p", this);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007863 int lStatus;
Glenn Kasten9eaa5572012-01-20 13:32:16 -08007864 if (thread == NULL) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07007865 return;
7866 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07007867
7868 memcpy(&mDescriptor, desc, sizeof(effect_descriptor_t));
7869
7870 // create effect engine from effect factory
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007871 mStatus = EffectCreate(&desc->uuid, sessionId, thread->id(), &mEffectInterface);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007872
7873 if (mStatus != NO_ERROR) {
7874 return;
7875 }
7876 lStatus = init();
7877 if (lStatus < 0) {
7878 mStatus = lStatus;
7879 goto Error;
7880 }
7881
Marco Nelissen3a34bef2011-08-02 13:33:41 -07007882 if (mSessionId > AUDIO_SESSION_OUTPUT_MIX) {
7883 mPinned = true;
7884 }
Steve Block3856b092011-10-20 11:56:00 +01007885 ALOGV("Constructor success name %s, Interface %p", mDescriptor.name, mEffectInterface);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007886 return;
7887Error:
7888 EffectRelease(mEffectInterface);
7889 mEffectInterface = NULL;
Steve Block3856b092011-10-20 11:56:00 +01007890 ALOGV("Constructor Error %d", mStatus);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007891}
7892
7893AudioFlinger::EffectModule::~EffectModule()
7894{
Steve Block3856b092011-10-20 11:56:00 +01007895 ALOGV("Destructor %p", this);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007896 if (mEffectInterface != NULL) {
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007897 if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC ||
7898 (mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_POST_PROC) {
7899 sp<ThreadBase> thread = mThread.promote();
7900 if (thread != 0) {
Eric Laurentb8ba0a92011-08-07 16:32:26 -07007901 audio_stream_t *stream = thread->stream();
7902 if (stream != NULL) {
7903 stream->remove_audio_effect(stream, mEffectInterface);
7904 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007905 }
7906 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07007907 // release effect engine
7908 EffectRelease(mEffectInterface);
7909 }
7910}
7911
Glenn Kasten435dbe62012-01-30 10:15:48 -08007912status_t AudioFlinger::EffectModule::addHandle(const sp<EffectHandle>& handle)
Mathias Agopian65ab4712010-07-14 17:59:35 -07007913{
7914 status_t status;
7915
7916 Mutex::Autolock _l(mLock);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007917 int priority = handle->priority();
7918 size_t size = mHandles.size();
7919 sp<EffectHandle> h;
7920 size_t i;
7921 for (i = 0; i < size; i++) {
7922 h = mHandles[i].promote();
7923 if (h == 0) continue;
7924 if (h->priority() <= priority) break;
7925 }
7926 // if inserted in first place, move effect control from previous owner to this handle
7927 if (i == 0) {
Eric Laurent59255e42011-07-27 19:49:51 -07007928 bool enabled = false;
Mathias Agopian65ab4712010-07-14 17:59:35 -07007929 if (h != 0) {
Eric Laurent59255e42011-07-27 19:49:51 -07007930 enabled = h->enabled();
7931 h->setControl(false/*hasControl*/, true /*signal*/, enabled /*enabled*/);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007932 }
Eric Laurent59255e42011-07-27 19:49:51 -07007933 handle->setControl(true /*hasControl*/, false /*signal*/, enabled /*enabled*/);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007934 status = NO_ERROR;
7935 } else {
7936 status = ALREADY_EXISTS;
7937 }
Steve Block3856b092011-10-20 11:56:00 +01007938 ALOGV("addHandle() %p added handle %p in position %d", this, handle.get(), i);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007939 mHandles.insertAt(handle, i);
7940 return status;
7941}
7942
7943size_t AudioFlinger::EffectModule::removeHandle(const wp<EffectHandle>& handle)
7944{
7945 Mutex::Autolock _l(mLock);
7946 size_t size = mHandles.size();
7947 size_t i;
7948 for (i = 0; i < size; i++) {
7949 if (mHandles[i] == handle) break;
7950 }
7951 if (i == size) {
7952 return size;
7953 }
Steve Block3856b092011-10-20 11:56:00 +01007954 ALOGV("removeHandle() %p removed handle %p in position %d", this, handle.unsafe_get(), i);
Eric Laurent59255e42011-07-27 19:49:51 -07007955
7956 bool enabled = false;
7957 EffectHandle *hdl = handle.unsafe_get();
Glenn Kastena0d68332012-01-27 16:47:15 -08007958 if (hdl != NULL) {
Steve Block3856b092011-10-20 11:56:00 +01007959 ALOGV("removeHandle() unsafe_get OK");
Eric Laurent59255e42011-07-27 19:49:51 -07007960 enabled = hdl->enabled();
7961 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07007962 mHandles.removeAt(i);
7963 size = mHandles.size();
7964 // if removed from first place, move effect control from this handle to next in line
7965 if (i == 0 && size != 0) {
7966 sp<EffectHandle> h = mHandles[0].promote();
7967 if (h != 0) {
Eric Laurent59255e42011-07-27 19:49:51 -07007968 h->setControl(true /*hasControl*/, true /*signal*/ , enabled /*enabled*/);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007969 }
7970 }
7971
Eric Laurentec437d82011-07-26 20:54:46 -07007972 // Prevent calls to process() and other functions on effect interface from now on.
7973 // The effect engine will be released by the destructor when the last strong reference on
7974 // this object is released which can happen after next process is called.
Marco Nelissen3a34bef2011-08-02 13:33:41 -07007975 if (size == 0 && !mPinned) {
Eric Laurentec437d82011-07-26 20:54:46 -07007976 mState = DESTROYED;
Eric Laurentdac69112010-09-28 14:09:57 -07007977 }
7978
Mathias Agopian65ab4712010-07-14 17:59:35 -07007979 return size;
7980}
7981
Eric Laurent59255e42011-07-27 19:49:51 -07007982sp<AudioFlinger::EffectHandle> AudioFlinger::EffectModule::controlHandle()
7983{
7984 Mutex::Autolock _l(mLock);
Glenn Kasten090f0192012-01-30 13:00:02 -08007985 return mHandles.size() != 0 ? mHandles[0].promote() : 0;
Eric Laurent59255e42011-07-27 19:49:51 -07007986}
7987
Glenn Kasten58123c32012-02-03 10:32:24 -08007988void AudioFlinger::EffectModule::disconnect(const wp<EffectHandle>& handle, bool unpinIfLast)
Mathias Agopian65ab4712010-07-14 17:59:35 -07007989{
Glenn Kasten90bebef2012-01-27 15:24:38 -08007990 ALOGV("disconnect() %p handle %p", this, handle.unsafe_get());
Mathias Agopian65ab4712010-07-14 17:59:35 -07007991 // keep a strong reference on this EffectModule to avoid calling the
7992 // destructor before we exit
7993 sp<EffectModule> keep(this);
7994 {
7995 sp<ThreadBase> thread = mThread.promote();
7996 if (thread != 0) {
Glenn Kasten58123c32012-02-03 10:32:24 -08007997 thread->disconnectEffect(keep, handle, unpinIfLast);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007998 }
7999 }
8000}
8001
8002void AudioFlinger::EffectModule::updateState() {
8003 Mutex::Autolock _l(mLock);
8004
8005 switch (mState) {
8006 case RESTART:
8007 reset_l();
8008 // FALL THROUGH
8009
8010 case STARTING:
8011 // clear auxiliary effect input buffer for next accumulation
8012 if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
8013 memset(mConfig.inputCfg.buffer.raw,
8014 0,
8015 mConfig.inputCfg.buffer.frameCount*sizeof(int32_t));
8016 }
8017 start_l();
8018 mState = ACTIVE;
8019 break;
8020 case STOPPING:
8021 stop_l();
8022 mDisableWaitCnt = mMaxDisableWaitCnt;
8023 mState = STOPPED;
8024 break;
8025 case STOPPED:
8026 // mDisableWaitCnt is forced to 1 by process() when the engine indicates the end of the
8027 // turn off sequence.
8028 if (--mDisableWaitCnt == 0) {
8029 reset_l();
8030 mState = IDLE;
8031 }
8032 break;
Eric Laurentec437d82011-07-26 20:54:46 -07008033 default: //IDLE , ACTIVE, DESTROYED
Mathias Agopian65ab4712010-07-14 17:59:35 -07008034 break;
8035 }
8036}
8037
8038void AudioFlinger::EffectModule::process()
8039{
8040 Mutex::Autolock _l(mLock);
8041
Eric Laurentec437d82011-07-26 20:54:46 -07008042 if (mState == DESTROYED || mEffectInterface == NULL ||
Mathias Agopian65ab4712010-07-14 17:59:35 -07008043 mConfig.inputCfg.buffer.raw == NULL ||
8044 mConfig.outputCfg.buffer.raw == NULL) {
8045 return;
8046 }
8047
Eric Laurent8f45bd72010-08-31 13:50:07 -07008048 if (isProcessEnabled()) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07008049 // do 32 bit to 16 bit conversion for auxiliary effect input buffer
8050 if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
Glenn Kasten3b21c502011-12-15 09:52:39 -08008051 ditherAndClamp(mConfig.inputCfg.buffer.s32,
Mathias Agopian65ab4712010-07-14 17:59:35 -07008052 mConfig.inputCfg.buffer.s32,
Eric Laurentde070132010-07-13 04:45:46 -07008053 mConfig.inputCfg.buffer.frameCount/2);
Mathias Agopian65ab4712010-07-14 17:59:35 -07008054 }
8055
8056 // do the actual processing in the effect engine
8057 int ret = (*mEffectInterface)->process(mEffectInterface,
8058 &mConfig.inputCfg.buffer,
8059 &mConfig.outputCfg.buffer);
8060
8061 // force transition to IDLE state when engine is ready
8062 if (mState == STOPPED && ret == -ENODATA) {
8063 mDisableWaitCnt = 1;
8064 }
8065
8066 // clear auxiliary effect input buffer for next accumulation
8067 if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
Eric Laurent73337482011-01-19 18:36:13 -08008068 memset(mConfig.inputCfg.buffer.raw, 0,
8069 mConfig.inputCfg.buffer.frameCount*sizeof(int32_t));
Mathias Agopian65ab4712010-07-14 17:59:35 -07008070 }
8071 } else if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_INSERT &&
Eric Laurent73337482011-01-19 18:36:13 -08008072 mConfig.inputCfg.buffer.raw != mConfig.outputCfg.buffer.raw) {
8073 // If an insert effect is idle and input buffer is different from output buffer,
8074 // accumulate input onto output
Mathias Agopian65ab4712010-07-14 17:59:35 -07008075 sp<EffectChain> chain = mChain.promote();
Eric Laurentb469b942011-05-09 12:09:06 -07008076 if (chain != 0 && chain->activeTrackCnt() != 0) {
Eric Laurent73337482011-01-19 18:36:13 -08008077 size_t frameCnt = mConfig.inputCfg.buffer.frameCount * 2; //always stereo here
8078 int16_t *in = mConfig.inputCfg.buffer.s16;
8079 int16_t *out = mConfig.outputCfg.buffer.s16;
8080 for (size_t i = 0; i < frameCnt; i++) {
8081 out[i] = clamp16((int32_t)out[i] + (int32_t)in[i]);
Mathias Agopian65ab4712010-07-14 17:59:35 -07008082 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07008083 }
8084 }
8085}
8086
8087void AudioFlinger::EffectModule::reset_l()
8088{
8089 if (mEffectInterface == NULL) {
8090 return;
8091 }
8092 (*mEffectInterface)->command(mEffectInterface, EFFECT_CMD_RESET, 0, NULL, 0, NULL);
8093}
8094
8095status_t AudioFlinger::EffectModule::configure()
8096{
8097 uint32_t channels;
8098 if (mEffectInterface == NULL) {
8099 return NO_INIT;
8100 }
8101
8102 sp<ThreadBase> thread = mThread.promote();
8103 if (thread == 0) {
8104 return DEAD_OBJECT;
8105 }
8106
8107 // TODO: handle configuration of effects replacing track process
8108 if (thread->channelCount() == 1) {
Eric Laurente1315cf2011-05-17 19:16:02 -07008109 channels = AUDIO_CHANNEL_OUT_MONO;
Mathias Agopian65ab4712010-07-14 17:59:35 -07008110 } else {
Eric Laurente1315cf2011-05-17 19:16:02 -07008111 channels = AUDIO_CHANNEL_OUT_STEREO;
Mathias Agopian65ab4712010-07-14 17:59:35 -07008112 }
8113
8114 if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
Eric Laurente1315cf2011-05-17 19:16:02 -07008115 mConfig.inputCfg.channels = AUDIO_CHANNEL_OUT_MONO;
Mathias Agopian65ab4712010-07-14 17:59:35 -07008116 } else {
8117 mConfig.inputCfg.channels = channels;
8118 }
8119 mConfig.outputCfg.channels = channels;
Eric Laurente1315cf2011-05-17 19:16:02 -07008120 mConfig.inputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
8121 mConfig.outputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
Mathias Agopian65ab4712010-07-14 17:59:35 -07008122 mConfig.inputCfg.samplingRate = thread->sampleRate();
8123 mConfig.outputCfg.samplingRate = mConfig.inputCfg.samplingRate;
8124 mConfig.inputCfg.bufferProvider.cookie = NULL;
8125 mConfig.inputCfg.bufferProvider.getBuffer = NULL;
8126 mConfig.inputCfg.bufferProvider.releaseBuffer = NULL;
8127 mConfig.outputCfg.bufferProvider.cookie = NULL;
8128 mConfig.outputCfg.bufferProvider.getBuffer = NULL;
8129 mConfig.outputCfg.bufferProvider.releaseBuffer = NULL;
8130 mConfig.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ;
8131 // Insert effect:
Dima Zavinfce7a472011-04-19 22:30:36 -07008132 // - in session AUDIO_SESSION_OUTPUT_MIX or AUDIO_SESSION_OUTPUT_STAGE,
Eric Laurentde070132010-07-13 04:45:46 -07008133 // always overwrites output buffer: input buffer == output buffer
Mathias Agopian65ab4712010-07-14 17:59:35 -07008134 // - in other sessions:
8135 // last effect in the chain accumulates in output buffer: input buffer != output buffer
8136 // other effect: overwrites output buffer: input buffer == output buffer
8137 // Auxiliary effect:
8138 // accumulates in output buffer: input buffer != output buffer
8139 // Therefore: accumulate <=> input buffer != output buffer
8140 if (mConfig.inputCfg.buffer.raw != mConfig.outputCfg.buffer.raw) {
8141 mConfig.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_ACCUMULATE;
8142 } else {
8143 mConfig.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_WRITE;
8144 }
8145 mConfig.inputCfg.mask = EFFECT_CONFIG_ALL;
8146 mConfig.outputCfg.mask = EFFECT_CONFIG_ALL;
8147 mConfig.inputCfg.buffer.frameCount = thread->frameCount();
8148 mConfig.outputCfg.buffer.frameCount = mConfig.inputCfg.buffer.frameCount;
8149
Steve Block3856b092011-10-20 11:56:00 +01008150 ALOGV("configure() %p thread %p buffer %p framecount %d",
Eric Laurentde070132010-07-13 04:45:46 -07008151 this, thread.get(), mConfig.inputCfg.buffer.raw, mConfig.inputCfg.buffer.frameCount);
8152
Mathias Agopian65ab4712010-07-14 17:59:35 -07008153 status_t cmdStatus;
Eric Laurent25f43952010-07-28 05:40:18 -07008154 uint32_t size = sizeof(int);
8155 status_t status = (*mEffectInterface)->command(mEffectInterface,
Eric Laurent3d5188b2011-12-16 15:30:36 -08008156 EFFECT_CMD_SET_CONFIG,
Eric Laurent25f43952010-07-28 05:40:18 -07008157 sizeof(effect_config_t),
8158 &mConfig,
8159 &size,
8160 &cmdStatus);
Mathias Agopian65ab4712010-07-14 17:59:35 -07008161 if (status == 0) {
8162 status = cmdStatus;
8163 }
8164
8165 mMaxDisableWaitCnt = (MAX_DISABLE_TIME_MS * mConfig.outputCfg.samplingRate) /
8166 (1000 * mConfig.outputCfg.buffer.frameCount);
8167
8168 return status;
8169}
8170
8171status_t AudioFlinger::EffectModule::init()
8172{
8173 Mutex::Autolock _l(mLock);
8174 if (mEffectInterface == NULL) {
8175 return NO_INIT;
8176 }
8177 status_t cmdStatus;
Eric Laurent25f43952010-07-28 05:40:18 -07008178 uint32_t size = sizeof(status_t);
8179 status_t status = (*mEffectInterface)->command(mEffectInterface,
8180 EFFECT_CMD_INIT,
8181 0,
8182 NULL,
8183 &size,
8184 &cmdStatus);
Mathias Agopian65ab4712010-07-14 17:59:35 -07008185 if (status == 0) {
8186 status = cmdStatus;
8187 }
8188 return status;
8189}
8190
Eric Laurentec35a142011-10-05 17:42:25 -07008191status_t AudioFlinger::EffectModule::start()
8192{
8193 Mutex::Autolock _l(mLock);
8194 return start_l();
8195}
8196
Mathias Agopian65ab4712010-07-14 17:59:35 -07008197status_t AudioFlinger::EffectModule::start_l()
8198{
8199 if (mEffectInterface == NULL) {
8200 return NO_INIT;
8201 }
8202 status_t cmdStatus;
Eric Laurent25f43952010-07-28 05:40:18 -07008203 uint32_t size = sizeof(status_t);
8204 status_t status = (*mEffectInterface)->command(mEffectInterface,
8205 EFFECT_CMD_ENABLE,
8206 0,
8207 NULL,
8208 &size,
8209 &cmdStatus);
Mathias Agopian65ab4712010-07-14 17:59:35 -07008210 if (status == 0) {
8211 status = cmdStatus;
8212 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07008213 if (status == 0 &&
8214 ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC ||
8215 (mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_POST_PROC)) {
8216 sp<ThreadBase> thread = mThread.promote();
8217 if (thread != 0) {
Eric Laurentb8ba0a92011-08-07 16:32:26 -07008218 audio_stream_t *stream = thread->stream();
8219 if (stream != NULL) {
8220 stream->add_audio_effect(stream, mEffectInterface);
8221 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07008222 }
8223 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07008224 return status;
8225}
8226
Eric Laurentec437d82011-07-26 20:54:46 -07008227status_t AudioFlinger::EffectModule::stop()
8228{
8229 Mutex::Autolock _l(mLock);
8230 return stop_l();
8231}
8232
Mathias Agopian65ab4712010-07-14 17:59:35 -07008233status_t AudioFlinger::EffectModule::stop_l()
8234{
8235 if (mEffectInterface == NULL) {
8236 return NO_INIT;
8237 }
8238 status_t cmdStatus;
Eric Laurent25f43952010-07-28 05:40:18 -07008239 uint32_t size = sizeof(status_t);
8240 status_t status = (*mEffectInterface)->command(mEffectInterface,
8241 EFFECT_CMD_DISABLE,
8242 0,
8243 NULL,
8244 &size,
8245 &cmdStatus);
Mathias Agopian65ab4712010-07-14 17:59:35 -07008246 if (status == 0) {
8247 status = cmdStatus;
8248 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07008249 if (status == 0 &&
8250 ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC ||
8251 (mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_POST_PROC)) {
8252 sp<ThreadBase> thread = mThread.promote();
8253 if (thread != 0) {
Eric Laurentb8ba0a92011-08-07 16:32:26 -07008254 audio_stream_t *stream = thread->stream();
8255 if (stream != NULL) {
8256 stream->remove_audio_effect(stream, mEffectInterface);
8257 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07008258 }
8259 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07008260 return status;
8261}
8262
Eric Laurent25f43952010-07-28 05:40:18 -07008263status_t AudioFlinger::EffectModule::command(uint32_t cmdCode,
8264 uint32_t cmdSize,
8265 void *pCmdData,
8266 uint32_t *replySize,
8267 void *pReplyData)
Mathias Agopian65ab4712010-07-14 17:59:35 -07008268{
8269 Mutex::Autolock _l(mLock);
Steve Block3856b092011-10-20 11:56:00 +01008270// ALOGV("command(), cmdCode: %d, mEffectInterface: %p", cmdCode, mEffectInterface);
Mathias Agopian65ab4712010-07-14 17:59:35 -07008271
Eric Laurentec437d82011-07-26 20:54:46 -07008272 if (mState == DESTROYED || mEffectInterface == NULL) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07008273 return NO_INIT;
8274 }
Eric Laurent25f43952010-07-28 05:40:18 -07008275 status_t status = (*mEffectInterface)->command(mEffectInterface,
8276 cmdCode,
8277 cmdSize,
8278 pCmdData,
8279 replySize,
8280 pReplyData);
Mathias Agopian65ab4712010-07-14 17:59:35 -07008281 if (cmdCode != EFFECT_CMD_GET_PARAM && status == NO_ERROR) {
Eric Laurent25f43952010-07-28 05:40:18 -07008282 uint32_t size = (replySize == NULL) ? 0 : *replySize;
Mathias Agopian65ab4712010-07-14 17:59:35 -07008283 for (size_t i = 1; i < mHandles.size(); i++) {
8284 sp<EffectHandle> h = mHandles[i].promote();
8285 if (h != 0) {
8286 h->commandExecuted(cmdCode, cmdSize, pCmdData, size, pReplyData);
8287 }
8288 }
8289 }
8290 return status;
8291}
8292
8293status_t AudioFlinger::EffectModule::setEnabled(bool enabled)
8294{
Eric Laurentdb7c0792011-08-10 10:37:50 -07008295
Mathias Agopian65ab4712010-07-14 17:59:35 -07008296 Mutex::Autolock _l(mLock);
Steve Block3856b092011-10-20 11:56:00 +01008297 ALOGV("setEnabled %p enabled %d", this, enabled);
Mathias Agopian65ab4712010-07-14 17:59:35 -07008298
8299 if (enabled != isEnabled()) {
Eric Laurentdb7c0792011-08-10 10:37:50 -07008300 status_t status = AudioSystem::setEffectEnabled(mId, enabled);
8301 if (enabled && status != NO_ERROR) {
8302 return status;
8303 }
8304
Mathias Agopian65ab4712010-07-14 17:59:35 -07008305 switch (mState) {
8306 // going from disabled to enabled
8307 case IDLE:
8308 mState = STARTING;
8309 break;
8310 case STOPPED:
8311 mState = RESTART;
8312 break;
8313 case STOPPING:
8314 mState = ACTIVE;
8315 break;
8316
8317 // going from enabled to disabled
8318 case RESTART:
Eric Laurent8f45bd72010-08-31 13:50:07 -07008319 mState = STOPPED;
8320 break;
Mathias Agopian65ab4712010-07-14 17:59:35 -07008321 case STARTING:
8322 mState = IDLE;
8323 break;
8324 case ACTIVE:
8325 mState = STOPPING;
8326 break;
Eric Laurentec437d82011-07-26 20:54:46 -07008327 case DESTROYED:
8328 return NO_ERROR; // simply ignore as we are being destroyed
Mathias Agopian65ab4712010-07-14 17:59:35 -07008329 }
8330 for (size_t i = 1; i < mHandles.size(); i++) {
8331 sp<EffectHandle> h = mHandles[i].promote();
8332 if (h != 0) {
8333 h->setEnabled(enabled);
8334 }
8335 }
8336 }
8337 return NO_ERROR;
8338}
8339
Glenn Kastenc59c0042012-02-02 14:06:11 -08008340bool AudioFlinger::EffectModule::isEnabled() const
Mathias Agopian65ab4712010-07-14 17:59:35 -07008341{
8342 switch (mState) {
8343 case RESTART:
8344 case STARTING:
8345 case ACTIVE:
8346 return true;
8347 case IDLE:
8348 case STOPPING:
8349 case STOPPED:
Eric Laurentec437d82011-07-26 20:54:46 -07008350 case DESTROYED:
Mathias Agopian65ab4712010-07-14 17:59:35 -07008351 default:
8352 return false;
8353 }
8354}
8355
Glenn Kastenc59c0042012-02-02 14:06:11 -08008356bool AudioFlinger::EffectModule::isProcessEnabled() const
Eric Laurent8f45bd72010-08-31 13:50:07 -07008357{
8358 switch (mState) {
8359 case RESTART:
8360 case ACTIVE:
8361 case STOPPING:
8362 case STOPPED:
8363 return true;
8364 case IDLE:
8365 case STARTING:
Eric Laurentec437d82011-07-26 20:54:46 -07008366 case DESTROYED:
Eric Laurent8f45bd72010-08-31 13:50:07 -07008367 default:
8368 return false;
8369 }
8370}
8371
Mathias Agopian65ab4712010-07-14 17:59:35 -07008372status_t AudioFlinger::EffectModule::setVolume(uint32_t *left, uint32_t *right, bool controller)
8373{
8374 Mutex::Autolock _l(mLock);
8375 status_t status = NO_ERROR;
8376
8377 // Send volume indication if EFFECT_FLAG_VOLUME_IND is set and read back altered volume
8378 // if controller flag is set (Note that controller == TRUE => EFFECT_FLAG_VOLUME_CTRL set)
Eric Laurent8f45bd72010-08-31 13:50:07 -07008379 if (isProcessEnabled() &&
Eric Laurentf997cab2010-07-19 06:24:46 -07008380 ((mDescriptor.flags & EFFECT_FLAG_VOLUME_MASK) == EFFECT_FLAG_VOLUME_CTRL ||
8381 (mDescriptor.flags & EFFECT_FLAG_VOLUME_MASK) == EFFECT_FLAG_VOLUME_IND)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07008382 status_t cmdStatus;
8383 uint32_t volume[2];
8384 uint32_t *pVolume = NULL;
Eric Laurent25f43952010-07-28 05:40:18 -07008385 uint32_t size = sizeof(volume);
Mathias Agopian65ab4712010-07-14 17:59:35 -07008386 volume[0] = *left;
8387 volume[1] = *right;
8388 if (controller) {
8389 pVolume = volume;
8390 }
Eric Laurent25f43952010-07-28 05:40:18 -07008391 status = (*mEffectInterface)->command(mEffectInterface,
8392 EFFECT_CMD_SET_VOLUME,
8393 size,
8394 volume,
8395 &size,
8396 pVolume);
Mathias Agopian65ab4712010-07-14 17:59:35 -07008397 if (controller && status == NO_ERROR && size == sizeof(volume)) {
8398 *left = volume[0];
8399 *right = volume[1];
8400 }
8401 }
8402 return status;
8403}
8404
8405status_t AudioFlinger::EffectModule::setDevice(uint32_t device)
8406{
8407 Mutex::Autolock _l(mLock);
8408 status_t status = NO_ERROR;
Eric Laurent7c7f10b2011-06-17 21:29:58 -07008409 if (device && (mDescriptor.flags & EFFECT_FLAG_DEVICE_MASK) == EFFECT_FLAG_DEVICE_IND) {
8410 // audio pre processing modules on RecordThread can receive both output and
8411 // input device indication in the same call
8412 uint32_t dev = device & AUDIO_DEVICE_OUT_ALL;
8413 if (dev) {
8414 status_t cmdStatus;
8415 uint32_t size = sizeof(status_t);
8416
8417 status = (*mEffectInterface)->command(mEffectInterface,
8418 EFFECT_CMD_SET_DEVICE,
8419 sizeof(uint32_t),
8420 &dev,
8421 &size,
8422 &cmdStatus);
8423 if (status == NO_ERROR) {
8424 status = cmdStatus;
8425 }
8426 }
8427 dev = device & AUDIO_DEVICE_IN_ALL;
8428 if (dev) {
8429 status_t cmdStatus;
8430 uint32_t size = sizeof(status_t);
8431
8432 status_t status2 = (*mEffectInterface)->command(mEffectInterface,
8433 EFFECT_CMD_SET_INPUT_DEVICE,
8434 sizeof(uint32_t),
8435 &dev,
8436 &size,
8437 &cmdStatus);
8438 if (status2 == NO_ERROR) {
8439 status2 = cmdStatus;
8440 }
8441 if (status == NO_ERROR) {
8442 status = status2;
8443 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07008444 }
8445 }
8446 return status;
8447}
8448
Glenn Kastenf78aee72012-01-04 11:00:47 -08008449status_t AudioFlinger::EffectModule::setMode(audio_mode_t mode)
Mathias Agopian65ab4712010-07-14 17:59:35 -07008450{
8451 Mutex::Autolock _l(mLock);
8452 status_t status = NO_ERROR;
8453 if ((mDescriptor.flags & EFFECT_FLAG_AUDIO_MODE_MASK) == EFFECT_FLAG_AUDIO_MODE_IND) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07008454 status_t cmdStatus;
Eric Laurent25f43952010-07-28 05:40:18 -07008455 uint32_t size = sizeof(status_t);
8456 status = (*mEffectInterface)->command(mEffectInterface,
8457 EFFECT_CMD_SET_AUDIO_MODE,
Glenn Kastenf78aee72012-01-04 11:00:47 -08008458 sizeof(audio_mode_t),
Eric Laurente1315cf2011-05-17 19:16:02 -07008459 &mode,
Eric Laurent25f43952010-07-28 05:40:18 -07008460 &size,
8461 &cmdStatus);
Mathias Agopian65ab4712010-07-14 17:59:35 -07008462 if (status == NO_ERROR) {
8463 status = cmdStatus;
8464 }
8465 }
8466 return status;
8467}
8468
Eric Laurent59255e42011-07-27 19:49:51 -07008469void AudioFlinger::EffectModule::setSuspended(bool suspended)
8470{
8471 Mutex::Autolock _l(mLock);
8472 mSuspended = suspended;
8473}
Glenn Kastena3a85482012-01-04 11:01:11 -08008474
8475bool AudioFlinger::EffectModule::suspended() const
Eric Laurent59255e42011-07-27 19:49:51 -07008476{
8477 Mutex::Autolock _l(mLock);
8478 return mSuspended;
8479}
8480
Mathias Agopian65ab4712010-07-14 17:59:35 -07008481status_t AudioFlinger::EffectModule::dump(int fd, const Vector<String16>& args)
8482{
8483 const size_t SIZE = 256;
8484 char buffer[SIZE];
8485 String8 result;
8486
8487 snprintf(buffer, SIZE, "\tEffect ID %d:\n", mId);
8488 result.append(buffer);
8489
8490 bool locked = tryLock(mLock);
8491 // failed to lock - AudioFlinger is probably deadlocked
8492 if (!locked) {
8493 result.append("\t\tCould not lock Fx mutex:\n");
8494 }
8495
8496 result.append("\t\tSession Status State Engine:\n");
8497 snprintf(buffer, SIZE, "\t\t%05d %03d %03d 0x%08x\n",
8498 mSessionId, mStatus, mState, (uint32_t)mEffectInterface);
8499 result.append(buffer);
8500
8501 result.append("\t\tDescriptor:\n");
8502 snprintf(buffer, SIZE, "\t\t- UUID: %08X-%04X-%04X-%04X-%02X%02X%02X%02X%02X%02X\n",
8503 mDescriptor.uuid.timeLow, mDescriptor.uuid.timeMid, mDescriptor.uuid.timeHiAndVersion,
8504 mDescriptor.uuid.clockSeq, mDescriptor.uuid.node[0], mDescriptor.uuid.node[1],mDescriptor.uuid.node[2],
8505 mDescriptor.uuid.node[3],mDescriptor.uuid.node[4],mDescriptor.uuid.node[5]);
8506 result.append(buffer);
8507 snprintf(buffer, SIZE, "\t\t- TYPE: %08X-%04X-%04X-%04X-%02X%02X%02X%02X%02X%02X\n",
8508 mDescriptor.type.timeLow, mDescriptor.type.timeMid, mDescriptor.type.timeHiAndVersion,
8509 mDescriptor.type.clockSeq, mDescriptor.type.node[0], mDescriptor.type.node[1],mDescriptor.type.node[2],
8510 mDescriptor.type.node[3],mDescriptor.type.node[4],mDescriptor.type.node[5]);
8511 result.append(buffer);
Eric Laurente1315cf2011-05-17 19:16:02 -07008512 snprintf(buffer, SIZE, "\t\t- apiVersion: %08X\n\t\t- flags: %08X\n",
Mathias Agopian65ab4712010-07-14 17:59:35 -07008513 mDescriptor.apiVersion,
8514 mDescriptor.flags);
8515 result.append(buffer);
8516 snprintf(buffer, SIZE, "\t\t- name: %s\n",
8517 mDescriptor.name);
8518 result.append(buffer);
8519 snprintf(buffer, SIZE, "\t\t- implementor: %s\n",
8520 mDescriptor.implementor);
8521 result.append(buffer);
8522
8523 result.append("\t\t- Input configuration:\n");
8524 result.append("\t\t\tBuffer Frames Smp rate Channels Format\n");
8525 snprintf(buffer, SIZE, "\t\t\t0x%08x %05d %05d %08x %d\n",
8526 (uint32_t)mConfig.inputCfg.buffer.raw,
8527 mConfig.inputCfg.buffer.frameCount,
8528 mConfig.inputCfg.samplingRate,
8529 mConfig.inputCfg.channels,
8530 mConfig.inputCfg.format);
8531 result.append(buffer);
8532
8533 result.append("\t\t- Output configuration:\n");
8534 result.append("\t\t\tBuffer Frames Smp rate Channels Format\n");
8535 snprintf(buffer, SIZE, "\t\t\t0x%08x %05d %05d %08x %d\n",
8536 (uint32_t)mConfig.outputCfg.buffer.raw,
8537 mConfig.outputCfg.buffer.frameCount,
8538 mConfig.outputCfg.samplingRate,
8539 mConfig.outputCfg.channels,
8540 mConfig.outputCfg.format);
8541 result.append(buffer);
8542
8543 snprintf(buffer, SIZE, "\t\t%d Clients:\n", mHandles.size());
8544 result.append(buffer);
8545 result.append("\t\t\tPid Priority Ctrl Locked client server\n");
8546 for (size_t i = 0; i < mHandles.size(); ++i) {
8547 sp<EffectHandle> handle = mHandles[i].promote();
8548 if (handle != 0) {
8549 handle->dump(buffer, SIZE);
8550 result.append(buffer);
8551 }
8552 }
8553
8554 result.append("\n");
8555
8556 write(fd, result.string(), result.length());
8557
8558 if (locked) {
8559 mLock.unlock();
8560 }
8561
8562 return NO_ERROR;
8563}
8564
8565// ----------------------------------------------------------------------------
8566// EffectHandle implementation
8567// ----------------------------------------------------------------------------
8568
8569#undef LOG_TAG
8570#define LOG_TAG "AudioFlinger::EffectHandle"
8571
8572AudioFlinger::EffectHandle::EffectHandle(const sp<EffectModule>& effect,
8573 const sp<AudioFlinger::Client>& client,
8574 const sp<IEffectClient>& effectClient,
8575 int32_t priority)
8576 : BnEffect(),
Marco Nelissen3a34bef2011-08-02 13:33:41 -07008577 mEffect(effect), mEffectClient(effectClient), mClient(client), mCblk(NULL),
Eric Laurent59255e42011-07-27 19:49:51 -07008578 mPriority(priority), mHasControl(false), mEnabled(false)
Mathias Agopian65ab4712010-07-14 17:59:35 -07008579{
Steve Block3856b092011-10-20 11:56:00 +01008580 ALOGV("constructor %p", this);
Mathias Agopian65ab4712010-07-14 17:59:35 -07008581
Marco Nelissen3a34bef2011-08-02 13:33:41 -07008582 if (client == 0) {
8583 return;
8584 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07008585 int bufOffset = ((sizeof(effect_param_cblk_t) - 1) / sizeof(int) + 1) * sizeof(int);
8586 mCblkMemory = client->heap()->allocate(EFFECT_PARAM_BUFFER_SIZE + bufOffset);
8587 if (mCblkMemory != 0) {
8588 mCblk = static_cast<effect_param_cblk_t *>(mCblkMemory->pointer());
8589
Glenn Kastena0d68332012-01-27 16:47:15 -08008590 if (mCblk != NULL) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07008591 new(mCblk) effect_param_cblk_t();
8592 mBuffer = (uint8_t *)mCblk + bufOffset;
Glenn Kastene53b9ea2012-03-12 16:29:55 -07008593 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07008594 } else {
Steve Block29357bc2012-01-06 19:20:56 +00008595 ALOGE("not enough memory for Effect size=%u", EFFECT_PARAM_BUFFER_SIZE + sizeof(effect_param_cblk_t));
Mathias Agopian65ab4712010-07-14 17:59:35 -07008596 return;
8597 }
8598}
8599
8600AudioFlinger::EffectHandle::~EffectHandle()
8601{
Steve Block3856b092011-10-20 11:56:00 +01008602 ALOGV("Destructor %p", this);
Marco Nelissen3a34bef2011-08-02 13:33:41 -07008603 disconnect(false);
Steve Block3856b092011-10-20 11:56:00 +01008604 ALOGV("Destructor DONE %p", this);
Mathias Agopian65ab4712010-07-14 17:59:35 -07008605}
8606
8607status_t AudioFlinger::EffectHandle::enable()
8608{
Steve Block3856b092011-10-20 11:56:00 +01008609 ALOGV("enable %p", this);
Mathias Agopian65ab4712010-07-14 17:59:35 -07008610 if (!mHasControl) return INVALID_OPERATION;
8611 if (mEffect == 0) return DEAD_OBJECT;
8612
Eric Laurentdb7c0792011-08-10 10:37:50 -07008613 if (mEnabled) {
8614 return NO_ERROR;
8615 }
8616
Eric Laurent59255e42011-07-27 19:49:51 -07008617 mEnabled = true;
8618
8619 sp<ThreadBase> thread = mEffect->thread().promote();
8620 if (thread != 0) {
8621 thread->checkSuspendOnEffectEnabled(mEffect, true, mEffect->sessionId());
8622 }
8623
8624 // checkSuspendOnEffectEnabled() can suspend this same effect when enabled
8625 if (mEffect->suspended()) {
8626 return NO_ERROR;
8627 }
8628
Eric Laurentdb7c0792011-08-10 10:37:50 -07008629 status_t status = mEffect->setEnabled(true);
8630 if (status != NO_ERROR) {
8631 if (thread != 0) {
8632 thread->checkSuspendOnEffectEnabled(mEffect, false, mEffect->sessionId());
8633 }
8634 mEnabled = false;
8635 }
8636 return status;
Mathias Agopian65ab4712010-07-14 17:59:35 -07008637}
8638
8639status_t AudioFlinger::EffectHandle::disable()
8640{
Steve Block3856b092011-10-20 11:56:00 +01008641 ALOGV("disable %p", this);
Mathias Agopian65ab4712010-07-14 17:59:35 -07008642 if (!mHasControl) return INVALID_OPERATION;
Eric Laurent59255e42011-07-27 19:49:51 -07008643 if (mEffect == 0) return DEAD_OBJECT;
Mathias Agopian65ab4712010-07-14 17:59:35 -07008644
Eric Laurentdb7c0792011-08-10 10:37:50 -07008645 if (!mEnabled) {
8646 return NO_ERROR;
8647 }
Eric Laurent59255e42011-07-27 19:49:51 -07008648 mEnabled = false;
8649
8650 if (mEffect->suspended()) {
8651 return NO_ERROR;
8652 }
8653
8654 status_t status = mEffect->setEnabled(false);
8655
8656 sp<ThreadBase> thread = mEffect->thread().promote();
8657 if (thread != 0) {
8658 thread->checkSuspendOnEffectEnabled(mEffect, false, mEffect->sessionId());
8659 }
8660
8661 return status;
Mathias Agopian65ab4712010-07-14 17:59:35 -07008662}
8663
8664void AudioFlinger::EffectHandle::disconnect()
8665{
Marco Nelissen3a34bef2011-08-02 13:33:41 -07008666 disconnect(true);
8667}
8668
Glenn Kasten58123c32012-02-03 10:32:24 -08008669void AudioFlinger::EffectHandle::disconnect(bool unpinIfLast)
Marco Nelissen3a34bef2011-08-02 13:33:41 -07008670{
Glenn Kasten58123c32012-02-03 10:32:24 -08008671 ALOGV("disconnect(%s)", unpinIfLast ? "true" : "false");
Mathias Agopian65ab4712010-07-14 17:59:35 -07008672 if (mEffect == 0) {
8673 return;
8674 }
Glenn Kasten58123c32012-02-03 10:32:24 -08008675 mEffect->disconnect(this, unpinIfLast);
Eric Laurent59255e42011-07-27 19:49:51 -07008676
Eric Laurenta85a74a2011-10-19 11:44:54 -07008677 if (mHasControl && mEnabled) {
Eric Laurentdb7c0792011-08-10 10:37:50 -07008678 sp<ThreadBase> thread = mEffect->thread().promote();
8679 if (thread != 0) {
8680 thread->checkSuspendOnEffectEnabled(mEffect, false, mEffect->sessionId());
8681 }
Eric Laurent59255e42011-07-27 19:49:51 -07008682 }
8683
Mathias Agopian65ab4712010-07-14 17:59:35 -07008684 // release sp on module => module destructor can be called now
8685 mEffect.clear();
Mathias Agopian65ab4712010-07-14 17:59:35 -07008686 if (mClient != 0) {
Glenn Kastena0d68332012-01-27 16:47:15 -08008687 if (mCblk != NULL) {
Glenn Kasten1a0ae5b2012-02-03 10:24:48 -08008688 // unlike ~TrackBase(), mCblk is never a local new, so don't delete
Marco Nelissen3a34bef2011-08-02 13:33:41 -07008689 mCblk->~effect_param_cblk_t(); // destroy our shared-structure.
8690 }
Glenn Kastendbfafaf2012-01-25 15:27:15 -08008691 mCblkMemory.clear(); // free the shared memory before releasing the heap it belongs to
Glenn Kasten98ec94c2012-01-25 14:28:29 -08008692 // Client destructor must run with AudioFlinger mutex locked
Mathias Agopian65ab4712010-07-14 17:59:35 -07008693 Mutex::Autolock _l(mClient->audioFlinger()->mLock);
8694 mClient.clear();
8695 }
8696}
8697
Eric Laurent25f43952010-07-28 05:40:18 -07008698status_t AudioFlinger::EffectHandle::command(uint32_t cmdCode,
8699 uint32_t cmdSize,
8700 void *pCmdData,
8701 uint32_t *replySize,
8702 void *pReplyData)
Mathias Agopian65ab4712010-07-14 17:59:35 -07008703{
Steve Block3856b092011-10-20 11:56:00 +01008704// ALOGV("command(), cmdCode: %d, mHasControl: %d, mEffect: %p",
Eric Laurent25f43952010-07-28 05:40:18 -07008705// cmdCode, mHasControl, (mEffect == 0) ? 0 : mEffect.get());
Mathias Agopian65ab4712010-07-14 17:59:35 -07008706
8707 // only get parameter command is permitted for applications not controlling the effect
8708 if (!mHasControl && cmdCode != EFFECT_CMD_GET_PARAM) {
8709 return INVALID_OPERATION;
8710 }
8711 if (mEffect == 0) return DEAD_OBJECT;
Marco Nelissen3a34bef2011-08-02 13:33:41 -07008712 if (mClient == 0) return INVALID_OPERATION;
Mathias Agopian65ab4712010-07-14 17:59:35 -07008713
8714 // handle commands that are not forwarded transparently to effect engine
8715 if (cmdCode == EFFECT_CMD_SET_PARAM_COMMIT) {
8716 // No need to trylock() here as this function is executed in the binder thread serving a particular client process:
8717 // no risk to block the whole media server process or mixer threads is we are stuck here
8718 Mutex::Autolock _l(mCblk->lock);
8719 if (mCblk->clientIndex > EFFECT_PARAM_BUFFER_SIZE ||
8720 mCblk->serverIndex > EFFECT_PARAM_BUFFER_SIZE) {
8721 mCblk->serverIndex = 0;
8722 mCblk->clientIndex = 0;
8723 return BAD_VALUE;
8724 }
8725 status_t status = NO_ERROR;
8726 while (mCblk->serverIndex < mCblk->clientIndex) {
8727 int reply;
Eric Laurent25f43952010-07-28 05:40:18 -07008728 uint32_t rsize = sizeof(int);
Mathias Agopian65ab4712010-07-14 17:59:35 -07008729 int *p = (int *)(mBuffer + mCblk->serverIndex);
8730 int size = *p++;
8731 if (((uint8_t *)p + size) > mBuffer + mCblk->clientIndex) {
Steve Block5ff1dd52012-01-05 23:22:43 +00008732 ALOGW("command(): invalid parameter block size");
Mathias Agopian65ab4712010-07-14 17:59:35 -07008733 break;
8734 }
8735 effect_param_t *param = (effect_param_t *)p;
8736 if (param->psize == 0 || param->vsize == 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00008737 ALOGW("command(): null parameter or value size");
Mathias Agopian65ab4712010-07-14 17:59:35 -07008738 mCblk->serverIndex += size;
8739 continue;
8740 }
Eric Laurent25f43952010-07-28 05:40:18 -07008741 uint32_t psize = sizeof(effect_param_t) +
8742 ((param->psize - 1) / sizeof(int) + 1) * sizeof(int) +
8743 param->vsize;
8744 status_t ret = mEffect->command(EFFECT_CMD_SET_PARAM,
8745 psize,
8746 p,
8747 &rsize,
8748 &reply);
Eric Laurentaeae3de2010-09-02 11:56:55 -07008749 // stop at first error encountered
8750 if (ret != NO_ERROR) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07008751 status = ret;
Eric Laurentaeae3de2010-09-02 11:56:55 -07008752 *(int *)pReplyData = reply;
8753 break;
8754 } else if (reply != NO_ERROR) {
8755 *(int *)pReplyData = reply;
8756 break;
Mathias Agopian65ab4712010-07-14 17:59:35 -07008757 }
8758 mCblk->serverIndex += size;
8759 }
8760 mCblk->serverIndex = 0;
8761 mCblk->clientIndex = 0;
8762 return status;
8763 } else if (cmdCode == EFFECT_CMD_ENABLE) {
Eric Laurentaeae3de2010-09-02 11:56:55 -07008764 *(int *)pReplyData = NO_ERROR;
Mathias Agopian65ab4712010-07-14 17:59:35 -07008765 return enable();
8766 } else if (cmdCode == EFFECT_CMD_DISABLE) {
Eric Laurentaeae3de2010-09-02 11:56:55 -07008767 *(int *)pReplyData = NO_ERROR;
Mathias Agopian65ab4712010-07-14 17:59:35 -07008768 return disable();
8769 }
8770
8771 return mEffect->command(cmdCode, cmdSize, pCmdData, replySize, pReplyData);
8772}
8773
Eric Laurent59255e42011-07-27 19:49:51 -07008774void AudioFlinger::EffectHandle::setControl(bool hasControl, bool signal, bool enabled)
Mathias Agopian65ab4712010-07-14 17:59:35 -07008775{
Steve Block3856b092011-10-20 11:56:00 +01008776 ALOGV("setControl %p control %d", this, hasControl);
Mathias Agopian65ab4712010-07-14 17:59:35 -07008777
8778 mHasControl = hasControl;
Eric Laurent59255e42011-07-27 19:49:51 -07008779 mEnabled = enabled;
8780
Mathias Agopian65ab4712010-07-14 17:59:35 -07008781 if (signal && mEffectClient != 0) {
8782 mEffectClient->controlStatusChanged(hasControl);
8783 }
8784}
8785
Eric Laurent25f43952010-07-28 05:40:18 -07008786void AudioFlinger::EffectHandle::commandExecuted(uint32_t cmdCode,
8787 uint32_t cmdSize,
8788 void *pCmdData,
8789 uint32_t replySize,
8790 void *pReplyData)
Mathias Agopian65ab4712010-07-14 17:59:35 -07008791{
8792 if (mEffectClient != 0) {
8793 mEffectClient->commandExecuted(cmdCode, cmdSize, pCmdData, replySize, pReplyData);
8794 }
8795}
8796
8797
8798
8799void AudioFlinger::EffectHandle::setEnabled(bool enabled)
8800{
8801 if (mEffectClient != 0) {
8802 mEffectClient->enableStatusChanged(enabled);
8803 }
8804}
8805
8806status_t AudioFlinger::EffectHandle::onTransact(
8807 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
8808{
8809 return BnEffect::onTransact(code, data, reply, flags);
8810}
8811
8812
8813void AudioFlinger::EffectHandle::dump(char* buffer, size_t size)
8814{
Glenn Kastena0d68332012-01-27 16:47:15 -08008815 bool locked = mCblk != NULL && tryLock(mCblk->lock);
Mathias Agopian65ab4712010-07-14 17:59:35 -07008816
8817 snprintf(buffer, size, "\t\t\t%05d %05d %01u %01u %05u %05u\n",
Glenn Kasten44deb052012-02-05 18:09:08 -08008818 (mClient == 0) ? getpid_cached : mClient->pid(),
Mathias Agopian65ab4712010-07-14 17:59:35 -07008819 mPriority,
8820 mHasControl,
8821 !locked,
Marco Nelissen3a34bef2011-08-02 13:33:41 -07008822 mCblk ? mCblk->clientIndex : 0,
8823 mCblk ? mCblk->serverIndex : 0
Mathias Agopian65ab4712010-07-14 17:59:35 -07008824 );
8825
8826 if (locked) {
8827 mCblk->lock.unlock();
8828 }
8829}
8830
8831#undef LOG_TAG
8832#define LOG_TAG "AudioFlinger::EffectChain"
8833
Glenn Kasten9eaa5572012-01-20 13:32:16 -08008834AudioFlinger::EffectChain::EffectChain(ThreadBase *thread,
Mathias Agopian65ab4712010-07-14 17:59:35 -07008835 int sessionId)
Glenn Kasten9eaa5572012-01-20 13:32:16 -08008836 : mThread(thread), mSessionId(sessionId), mActiveTrackCnt(0), mTrackCnt(0), mTailBufferCount(0),
Eric Laurentb469b942011-05-09 12:09:06 -07008837 mOwnInBuffer(false), mVolumeCtrlIdx(-1), mLeftVolume(UINT_MAX), mRightVolume(UINT_MAX),
8838 mNewLeftVolume(UINT_MAX), mNewRightVolume(UINT_MAX)
Mathias Agopian65ab4712010-07-14 17:59:35 -07008839{
Dima Zavinfce7a472011-04-19 22:30:36 -07008840 mStrategy = AudioSystem::getStrategyForStream(AUDIO_STREAM_MUSIC);
Glenn Kasten9eaa5572012-01-20 13:32:16 -08008841 if (thread == NULL) {
Eric Laurent544fe9b2011-11-11 15:42:52 -08008842 return;
8843 }
8844 mMaxTailBuffers = ((kProcessTailDurationMs * thread->sampleRate()) / 1000) /
8845 thread->frameCount();
Mathias Agopian65ab4712010-07-14 17:59:35 -07008846}
8847
8848AudioFlinger::EffectChain::~EffectChain()
8849{
8850 if (mOwnInBuffer) {
8851 delete mInBuffer;
8852 }
8853
8854}
8855
Eric Laurent59255e42011-07-27 19:49:51 -07008856// getEffectFromDesc_l() must be called with ThreadBase::mLock held
Eric Laurentcab11242010-07-15 12:50:15 -07008857sp<AudioFlinger::EffectModule> AudioFlinger::EffectChain::getEffectFromDesc_l(effect_descriptor_t *descriptor)
Mathias Agopian65ab4712010-07-14 17:59:35 -07008858{
Mathias Agopian65ab4712010-07-14 17:59:35 -07008859 size_t size = mEffects.size();
8860
8861 for (size_t i = 0; i < size; i++) {
8862 if (memcmp(&mEffects[i]->desc().uuid, &descriptor->uuid, sizeof(effect_uuid_t)) == 0) {
Glenn Kasten090f0192012-01-30 13:00:02 -08008863 return mEffects[i];
Mathias Agopian65ab4712010-07-14 17:59:35 -07008864 }
8865 }
Glenn Kasten090f0192012-01-30 13:00:02 -08008866 return 0;
Mathias Agopian65ab4712010-07-14 17:59:35 -07008867}
8868
Eric Laurent59255e42011-07-27 19:49:51 -07008869// getEffectFromId_l() must be called with ThreadBase::mLock held
Eric Laurentcab11242010-07-15 12:50:15 -07008870sp<AudioFlinger::EffectModule> AudioFlinger::EffectChain::getEffectFromId_l(int id)
Mathias Agopian65ab4712010-07-14 17:59:35 -07008871{
Mathias Agopian65ab4712010-07-14 17:59:35 -07008872 size_t size = mEffects.size();
8873
8874 for (size_t i = 0; i < size; i++) {
Eric Laurentde070132010-07-13 04:45:46 -07008875 // by convention, return first effect if id provided is 0 (0 is never a valid id)
8876 if (id == 0 || mEffects[i]->id() == id) {
Glenn Kasten090f0192012-01-30 13:00:02 -08008877 return mEffects[i];
Mathias Agopian65ab4712010-07-14 17:59:35 -07008878 }
8879 }
Glenn Kasten090f0192012-01-30 13:00:02 -08008880 return 0;
Mathias Agopian65ab4712010-07-14 17:59:35 -07008881}
8882
Eric Laurent59255e42011-07-27 19:49:51 -07008883// getEffectFromType_l() must be called with ThreadBase::mLock held
8884sp<AudioFlinger::EffectModule> AudioFlinger::EffectChain::getEffectFromType_l(
8885 const effect_uuid_t *type)
8886{
Eric Laurent59255e42011-07-27 19:49:51 -07008887 size_t size = mEffects.size();
8888
8889 for (size_t i = 0; i < size; i++) {
8890 if (memcmp(&mEffects[i]->desc().type, type, sizeof(effect_uuid_t)) == 0) {
Glenn Kasten090f0192012-01-30 13:00:02 -08008891 return mEffects[i];
Eric Laurent59255e42011-07-27 19:49:51 -07008892 }
8893 }
Glenn Kasten090f0192012-01-30 13:00:02 -08008894 return 0;
Eric Laurent59255e42011-07-27 19:49:51 -07008895}
8896
Mathias Agopian65ab4712010-07-14 17:59:35 -07008897// Must be called with EffectChain::mLock locked
8898void AudioFlinger::EffectChain::process_l()
8899{
Eric Laurentdac69112010-09-28 14:09:57 -07008900 sp<ThreadBase> thread = mThread.promote();
8901 if (thread == 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00008902 ALOGW("process_l(): cannot promote mixer thread");
Eric Laurentdac69112010-09-28 14:09:57 -07008903 return;
8904 }
Dima Zavinfce7a472011-04-19 22:30:36 -07008905 bool isGlobalSession = (mSessionId == AUDIO_SESSION_OUTPUT_MIX) ||
8906 (mSessionId == AUDIO_SESSION_OUTPUT_STAGE);
Eric Laurent544fe9b2011-11-11 15:42:52 -08008907 // always process effects unless no more tracks are on the session and the effect tail
8908 // has been rendered
8909 bool doProcess = true;
Eric Laurentdac69112010-09-28 14:09:57 -07008910 if (!isGlobalSession) {
Eric Laurent544fe9b2011-11-11 15:42:52 -08008911 bool tracksOnSession = (trackCnt() != 0);
Eric Laurentb469b942011-05-09 12:09:06 -07008912
Eric Laurent544fe9b2011-11-11 15:42:52 -08008913 if (!tracksOnSession && mTailBufferCount == 0) {
8914 doProcess = false;
8915 }
8916
8917 if (activeTrackCnt() == 0) {
8918 // if no track is active and the effect tail has not been rendered,
8919 // the input buffer must be cleared here as the mixer process will not do it
8920 if (tracksOnSession || mTailBufferCount > 0) {
8921 size_t numSamples = thread->frameCount() * thread->channelCount();
8922 memset(mInBuffer, 0, numSamples * sizeof(int16_t));
8923 if (mTailBufferCount > 0) {
8924 mTailBufferCount--;
8925 }
8926 }
8927 }
Eric Laurentdac69112010-09-28 14:09:57 -07008928 }
8929
Mathias Agopian65ab4712010-07-14 17:59:35 -07008930 size_t size = mEffects.size();
Eric Laurent544fe9b2011-11-11 15:42:52 -08008931 if (doProcess) {
Eric Laurentdac69112010-09-28 14:09:57 -07008932 for (size_t i = 0; i < size; i++) {
8933 mEffects[i]->process();
8934 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07008935 }
8936 for (size_t i = 0; i < size; i++) {
8937 mEffects[i]->updateState();
8938 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07008939}
8940
Eric Laurentcab11242010-07-15 12:50:15 -07008941// addEffect_l() must be called with PlaybackThread::mLock held
Eric Laurentde070132010-07-13 04:45:46 -07008942status_t AudioFlinger::EffectChain::addEffect_l(const sp<EffectModule>& effect)
Mathias Agopian65ab4712010-07-14 17:59:35 -07008943{
8944 effect_descriptor_t desc = effect->desc();
8945 uint32_t insertPref = desc.flags & EFFECT_FLAG_INSERT_MASK;
8946
8947 Mutex::Autolock _l(mLock);
Eric Laurentde070132010-07-13 04:45:46 -07008948 effect->setChain(this);
8949 sp<ThreadBase> thread = mThread.promote();
8950 if (thread == 0) {
8951 return NO_INIT;
8952 }
8953 effect->setThread(thread);
Mathias Agopian65ab4712010-07-14 17:59:35 -07008954
8955 if ((desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
8956 // Auxiliary effects are inserted at the beginning of mEffects vector as
8957 // they are processed first and accumulated in chain input buffer
8958 mEffects.insertAt(effect, 0);
Eric Laurentde070132010-07-13 04:45:46 -07008959
Mathias Agopian65ab4712010-07-14 17:59:35 -07008960 // the input buffer for auxiliary effect contains mono samples in
8961 // 32 bit format. This is to avoid saturation in AudoMixer
8962 // accumulation stage. Saturation is done in EffectModule::process() before
8963 // calling the process in effect engine
8964 size_t numSamples = thread->frameCount();
8965 int32_t *buffer = new int32_t[numSamples];
8966 memset(buffer, 0, numSamples * sizeof(int32_t));
8967 effect->setInBuffer((int16_t *)buffer);
8968 // auxiliary effects output samples to chain input buffer for further processing
8969 // by insert effects
8970 effect->setOutBuffer(mInBuffer);
8971 } else {
8972 // Insert effects are inserted at the end of mEffects vector as they are processed
8973 // after track and auxiliary effects.
8974 // Insert effect order as a function of indicated preference:
8975 // if EFFECT_FLAG_INSERT_EXCLUSIVE, insert in first position or reject if
8976 // another effect is present
8977 // else if EFFECT_FLAG_INSERT_FIRST, insert in first position or after the
8978 // last effect claiming first position
8979 // else if EFFECT_FLAG_INSERT_LAST, insert in last position or before the
8980 // first effect claiming last position
8981 // else if EFFECT_FLAG_INSERT_ANY insert after first or before last
8982 // Reject insertion if an effect with EFFECT_FLAG_INSERT_EXCLUSIVE is
8983 // already present
8984
Glenn Kasten8d6a2442012-02-08 14:04:28 -08008985 size_t size = mEffects.size();
8986 size_t idx_insert = size;
8987 ssize_t idx_insert_first = -1;
8988 ssize_t idx_insert_last = -1;
Mathias Agopian65ab4712010-07-14 17:59:35 -07008989
Glenn Kasten8d6a2442012-02-08 14:04:28 -08008990 for (size_t i = 0; i < size; i++) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07008991 effect_descriptor_t d = mEffects[i]->desc();
8992 uint32_t iMode = d.flags & EFFECT_FLAG_TYPE_MASK;
8993 uint32_t iPref = d.flags & EFFECT_FLAG_INSERT_MASK;
8994 if (iMode == EFFECT_FLAG_TYPE_INSERT) {
8995 // check invalid effect chaining combinations
8996 if (insertPref == EFFECT_FLAG_INSERT_EXCLUSIVE ||
8997 iPref == EFFECT_FLAG_INSERT_EXCLUSIVE) {
Steve Block5ff1dd52012-01-05 23:22:43 +00008998 ALOGW("addEffect_l() could not insert effect %s: exclusive conflict with %s", desc.name, d.name);
Mathias Agopian65ab4712010-07-14 17:59:35 -07008999 return INVALID_OPERATION;
9000 }
9001 // remember position of first insert effect and by default
9002 // select this as insert position for new effect
9003 if (idx_insert == size) {
9004 idx_insert = i;
9005 }
9006 // remember position of last insert effect claiming
9007 // first position
9008 if (iPref == EFFECT_FLAG_INSERT_FIRST) {
9009 idx_insert_first = i;
9010 }
9011 // remember position of first insert effect claiming
9012 // last position
9013 if (iPref == EFFECT_FLAG_INSERT_LAST &&
9014 idx_insert_last == -1) {
9015 idx_insert_last = i;
9016 }
9017 }
9018 }
9019
9020 // modify idx_insert from first position if needed
9021 if (insertPref == EFFECT_FLAG_INSERT_LAST) {
9022 if (idx_insert_last != -1) {
9023 idx_insert = idx_insert_last;
9024 } else {
9025 idx_insert = size;
9026 }
9027 } else {
9028 if (idx_insert_first != -1) {
9029 idx_insert = idx_insert_first + 1;
9030 }
9031 }
9032
9033 // always read samples from chain input buffer
9034 effect->setInBuffer(mInBuffer);
9035
9036 // if last effect in the chain, output samples to chain
9037 // output buffer, otherwise to chain input buffer
9038 if (idx_insert == size) {
9039 if (idx_insert != 0) {
9040 mEffects[idx_insert-1]->setOutBuffer(mInBuffer);
9041 mEffects[idx_insert-1]->configure();
9042 }
9043 effect->setOutBuffer(mOutBuffer);
9044 } else {
9045 effect->setOutBuffer(mInBuffer);
9046 }
9047 mEffects.insertAt(effect, idx_insert);
Mathias Agopian65ab4712010-07-14 17:59:35 -07009048
Steve Block3856b092011-10-20 11:56:00 +01009049 ALOGV("addEffect_l() effect %p, added in chain %p at rank %d", effect.get(), this, idx_insert);
Mathias Agopian65ab4712010-07-14 17:59:35 -07009050 }
9051 effect->configure();
9052 return NO_ERROR;
9053}
9054
Eric Laurentcab11242010-07-15 12:50:15 -07009055// removeEffect_l() must be called with PlaybackThread::mLock held
9056size_t AudioFlinger::EffectChain::removeEffect_l(const sp<EffectModule>& effect)
Mathias Agopian65ab4712010-07-14 17:59:35 -07009057{
9058 Mutex::Autolock _l(mLock);
Glenn Kasten8d6a2442012-02-08 14:04:28 -08009059 size_t size = mEffects.size();
Mathias Agopian65ab4712010-07-14 17:59:35 -07009060 uint32_t type = effect->desc().flags & EFFECT_FLAG_TYPE_MASK;
9061
Glenn Kasten8d6a2442012-02-08 14:04:28 -08009062 for (size_t i = 0; i < size; i++) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07009063 if (effect == mEffects[i]) {
Eric Laurentec437d82011-07-26 20:54:46 -07009064 // calling stop here will remove pre-processing effect from the audio HAL.
9065 // This is safe as we hold the EffectChain mutex which guarantees that we are not in
9066 // the middle of a read from audio HAL
Eric Laurentec35a142011-10-05 17:42:25 -07009067 if (mEffects[i]->state() == EffectModule::ACTIVE ||
9068 mEffects[i]->state() == EffectModule::STOPPING) {
9069 mEffects[i]->stop();
9070 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07009071 if (type == EFFECT_FLAG_TYPE_AUXILIARY) {
9072 delete[] effect->inBuffer();
9073 } else {
9074 if (i == size - 1 && i != 0) {
9075 mEffects[i - 1]->setOutBuffer(mOutBuffer);
9076 mEffects[i - 1]->configure();
9077 }
9078 }
9079 mEffects.removeAt(i);
Steve Block3856b092011-10-20 11:56:00 +01009080 ALOGV("removeEffect_l() effect %p, removed from chain %p at rank %d", effect.get(), this, i);
Mathias Agopian65ab4712010-07-14 17:59:35 -07009081 break;
9082 }
9083 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07009084
9085 return mEffects.size();
9086}
9087
Eric Laurentcab11242010-07-15 12:50:15 -07009088// setDevice_l() must be called with PlaybackThread::mLock held
9089void AudioFlinger::EffectChain::setDevice_l(uint32_t device)
Mathias Agopian65ab4712010-07-14 17:59:35 -07009090{
9091 size_t size = mEffects.size();
9092 for (size_t i = 0; i < size; i++) {
9093 mEffects[i]->setDevice(device);
9094 }
9095}
9096
Eric Laurentcab11242010-07-15 12:50:15 -07009097// setMode_l() must be called with PlaybackThread::mLock held
Glenn Kastenf78aee72012-01-04 11:00:47 -08009098void AudioFlinger::EffectChain::setMode_l(audio_mode_t mode)
Mathias Agopian65ab4712010-07-14 17:59:35 -07009099{
9100 size_t size = mEffects.size();
9101 for (size_t i = 0; i < size; i++) {
9102 mEffects[i]->setMode(mode);
9103 }
9104}
9105
Eric Laurentcab11242010-07-15 12:50:15 -07009106// setVolume_l() must be called with PlaybackThread::mLock held
9107bool AudioFlinger::EffectChain::setVolume_l(uint32_t *left, uint32_t *right)
Mathias Agopian65ab4712010-07-14 17:59:35 -07009108{
9109 uint32_t newLeft = *left;
9110 uint32_t newRight = *right;
9111 bool hasControl = false;
Eric Laurentcab11242010-07-15 12:50:15 -07009112 int ctrlIdx = -1;
9113 size_t size = mEffects.size();
Mathias Agopian65ab4712010-07-14 17:59:35 -07009114
Eric Laurentcab11242010-07-15 12:50:15 -07009115 // first update volume controller
9116 for (size_t i = size; i > 0; i--) {
Eric Laurent8f45bd72010-08-31 13:50:07 -07009117 if (mEffects[i - 1]->isProcessEnabled() &&
Eric Laurentcab11242010-07-15 12:50:15 -07009118 (mEffects[i - 1]->desc().flags & EFFECT_FLAG_VOLUME_MASK) == EFFECT_FLAG_VOLUME_CTRL) {
9119 ctrlIdx = i - 1;
Eric Laurentf997cab2010-07-19 06:24:46 -07009120 hasControl = true;
Eric Laurentcab11242010-07-15 12:50:15 -07009121 break;
9122 }
9123 }
9124
9125 if (ctrlIdx == mVolumeCtrlIdx && *left == mLeftVolume && *right == mRightVolume) {
Eric Laurentf997cab2010-07-19 06:24:46 -07009126 if (hasControl) {
9127 *left = mNewLeftVolume;
9128 *right = mNewRightVolume;
9129 }
9130 return hasControl;
Eric Laurentcab11242010-07-15 12:50:15 -07009131 }
9132
9133 mVolumeCtrlIdx = ctrlIdx;
Eric Laurentf997cab2010-07-19 06:24:46 -07009134 mLeftVolume = newLeft;
9135 mRightVolume = newRight;
Eric Laurentcab11242010-07-15 12:50:15 -07009136
9137 // second get volume update from volume controller
9138 if (ctrlIdx >= 0) {
9139 mEffects[ctrlIdx]->setVolume(&newLeft, &newRight, true);
Eric Laurentf997cab2010-07-19 06:24:46 -07009140 mNewLeftVolume = newLeft;
9141 mNewRightVolume = newRight;
Mathias Agopian65ab4712010-07-14 17:59:35 -07009142 }
9143 // then indicate volume to all other effects in chain.
9144 // Pass altered volume to effects before volume controller
9145 // and requested volume to effects after controller
9146 uint32_t lVol = newLeft;
9147 uint32_t rVol = newRight;
Eric Laurentcab11242010-07-15 12:50:15 -07009148
Mathias Agopian65ab4712010-07-14 17:59:35 -07009149 for (size_t i = 0; i < size; i++) {
Eric Laurentcab11242010-07-15 12:50:15 -07009150 if ((int)i == ctrlIdx) continue;
9151 // this also works for ctrlIdx == -1 when there is no volume controller
9152 if ((int)i > ctrlIdx) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07009153 lVol = *left;
9154 rVol = *right;
9155 }
9156 mEffects[i]->setVolume(&lVol, &rVol, false);
9157 }
9158 *left = newLeft;
9159 *right = newRight;
9160
9161 return hasControl;
9162}
9163
Mathias Agopian65ab4712010-07-14 17:59:35 -07009164status_t AudioFlinger::EffectChain::dump(int fd, const Vector<String16>& args)
9165{
9166 const size_t SIZE = 256;
9167 char buffer[SIZE];
9168 String8 result;
9169
9170 snprintf(buffer, SIZE, "Effects for session %d:\n", mSessionId);
9171 result.append(buffer);
9172
9173 bool locked = tryLock(mLock);
9174 // failed to lock - AudioFlinger is probably deadlocked
9175 if (!locked) {
9176 result.append("\tCould not lock mutex:\n");
9177 }
9178
Eric Laurentcab11242010-07-15 12:50:15 -07009179 result.append("\tNum fx In buffer Out buffer Active tracks:\n");
9180 snprintf(buffer, SIZE, "\t%02d 0x%08x 0x%08x %d\n",
Mathias Agopian65ab4712010-07-14 17:59:35 -07009181 mEffects.size(),
9182 (uint32_t)mInBuffer,
9183 (uint32_t)mOutBuffer,
Mathias Agopian65ab4712010-07-14 17:59:35 -07009184 mActiveTrackCnt);
9185 result.append(buffer);
9186 write(fd, result.string(), result.size());
9187
9188 for (size_t i = 0; i < mEffects.size(); ++i) {
9189 sp<EffectModule> effect = mEffects[i];
9190 if (effect != 0) {
9191 effect->dump(fd, args);
9192 }
9193 }
9194
9195 if (locked) {
9196 mLock.unlock();
9197 }
9198
9199 return NO_ERROR;
9200}
9201
Eric Laurent59255e42011-07-27 19:49:51 -07009202// must be called with ThreadBase::mLock held
9203void AudioFlinger::EffectChain::setEffectSuspended_l(
9204 const effect_uuid_t *type, bool suspend)
9205{
9206 sp<SuspendedEffectDesc> desc;
9207 // use effect type UUID timelow as key as there is no real risk of identical
9208 // timeLow fields among effect type UUIDs.
Glenn Kasten8d6a2442012-02-08 14:04:28 -08009209 ssize_t index = mSuspendedEffects.indexOfKey(type->timeLow);
Eric Laurent59255e42011-07-27 19:49:51 -07009210 if (suspend) {
9211 if (index >= 0) {
9212 desc = mSuspendedEffects.valueAt(index);
9213 } else {
9214 desc = new SuspendedEffectDesc();
9215 memcpy(&desc->mType, type, sizeof(effect_uuid_t));
9216 mSuspendedEffects.add(type->timeLow, desc);
Steve Block3856b092011-10-20 11:56:00 +01009217 ALOGV("setEffectSuspended_l() add entry for %08x", type->timeLow);
Eric Laurent59255e42011-07-27 19:49:51 -07009218 }
9219 if (desc->mRefCount++ == 0) {
9220 sp<EffectModule> effect = getEffectIfEnabled(type);
9221 if (effect != 0) {
9222 desc->mEffect = effect;
9223 effect->setSuspended(true);
9224 effect->setEnabled(false);
9225 }
9226 }
9227 } else {
9228 if (index < 0) {
9229 return;
9230 }
9231 desc = mSuspendedEffects.valueAt(index);
9232 if (desc->mRefCount <= 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00009233 ALOGW("setEffectSuspended_l() restore refcount should not be 0 %d", desc->mRefCount);
Eric Laurent59255e42011-07-27 19:49:51 -07009234 desc->mRefCount = 1;
9235 }
9236 if (--desc->mRefCount == 0) {
Steve Block3856b092011-10-20 11:56:00 +01009237 ALOGV("setEffectSuspended_l() remove entry for %08x", mSuspendedEffects.keyAt(index));
Eric Laurent59255e42011-07-27 19:49:51 -07009238 if (desc->mEffect != 0) {
9239 sp<EffectModule> effect = desc->mEffect.promote();
9240 if (effect != 0) {
9241 effect->setSuspended(false);
9242 sp<EffectHandle> handle = effect->controlHandle();
9243 if (handle != 0) {
9244 effect->setEnabled(handle->enabled());
9245 }
9246 }
9247 desc->mEffect.clear();
9248 }
9249 mSuspendedEffects.removeItemsAt(index);
9250 }
9251 }
9252}
9253
9254// must be called with ThreadBase::mLock held
9255void AudioFlinger::EffectChain::setEffectSuspendedAll_l(bool suspend)
9256{
9257 sp<SuspendedEffectDesc> desc;
9258
Glenn Kasten8d6a2442012-02-08 14:04:28 -08009259 ssize_t index = mSuspendedEffects.indexOfKey((int)kKeyForSuspendAll);
Eric Laurent59255e42011-07-27 19:49:51 -07009260 if (suspend) {
9261 if (index >= 0) {
9262 desc = mSuspendedEffects.valueAt(index);
9263 } else {
9264 desc = new SuspendedEffectDesc();
9265 mSuspendedEffects.add((int)kKeyForSuspendAll, desc);
Steve Block3856b092011-10-20 11:56:00 +01009266 ALOGV("setEffectSuspendedAll_l() add entry for 0");
Eric Laurent59255e42011-07-27 19:49:51 -07009267 }
9268 if (desc->mRefCount++ == 0) {
Glenn Kastend0539712012-01-30 12:56:03 -08009269 Vector< sp<EffectModule> > effects;
9270 getSuspendEligibleEffects(effects);
Eric Laurent59255e42011-07-27 19:49:51 -07009271 for (size_t i = 0; i < effects.size(); i++) {
9272 setEffectSuspended_l(&effects[i]->desc().type, true);
9273 }
9274 }
9275 } else {
9276 if (index < 0) {
9277 return;
9278 }
9279 desc = mSuspendedEffects.valueAt(index);
9280 if (desc->mRefCount <= 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00009281 ALOGW("setEffectSuspendedAll_l() restore refcount should not be 0 %d", desc->mRefCount);
Eric Laurent59255e42011-07-27 19:49:51 -07009282 desc->mRefCount = 1;
9283 }
9284 if (--desc->mRefCount == 0) {
9285 Vector<const effect_uuid_t *> types;
9286 for (size_t i = 0; i < mSuspendedEffects.size(); i++) {
9287 if (mSuspendedEffects.keyAt(i) == (int)kKeyForSuspendAll) {
9288 continue;
9289 }
9290 types.add(&mSuspendedEffects.valueAt(i)->mType);
9291 }
9292 for (size_t i = 0; i < types.size(); i++) {
9293 setEffectSuspended_l(types[i], false);
9294 }
Steve Block3856b092011-10-20 11:56:00 +01009295 ALOGV("setEffectSuspendedAll_l() remove entry for %08x", mSuspendedEffects.keyAt(index));
Eric Laurent59255e42011-07-27 19:49:51 -07009296 mSuspendedEffects.removeItem((int)kKeyForSuspendAll);
9297 }
9298 }
9299}
9300
Eric Laurent6bffdb82011-09-23 08:40:41 -07009301
9302// The volume effect is used for automated tests only
9303#ifndef OPENSL_ES_H_
9304static const effect_uuid_t SL_IID_VOLUME_ = { 0x09e8ede0, 0xddde, 0x11db, 0xb4f6,
9305 { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } };
9306const effect_uuid_t * const SL_IID_VOLUME = &SL_IID_VOLUME_;
9307#endif //OPENSL_ES_H_
9308
Eric Laurentdb7c0792011-08-10 10:37:50 -07009309bool AudioFlinger::EffectChain::isEffectEligibleForSuspend(const effect_descriptor_t& desc)
9310{
9311 // auxiliary effects and visualizer are never suspended on output mix
9312 if ((mSessionId == AUDIO_SESSION_OUTPUT_MIX) &&
9313 (((desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) ||
Eric Laurent6bffdb82011-09-23 08:40:41 -07009314 (memcmp(&desc.type, SL_IID_VISUALIZATION, sizeof(effect_uuid_t)) == 0) ||
9315 (memcmp(&desc.type, SL_IID_VOLUME, sizeof(effect_uuid_t)) == 0))) {
Eric Laurentdb7c0792011-08-10 10:37:50 -07009316 return false;
9317 }
9318 return true;
9319}
9320
Glenn Kastend0539712012-01-30 12:56:03 -08009321void AudioFlinger::EffectChain::getSuspendEligibleEffects(Vector< sp<AudioFlinger::EffectModule> > &effects)
Eric Laurent59255e42011-07-27 19:49:51 -07009322{
Glenn Kastend0539712012-01-30 12:56:03 -08009323 effects.clear();
Eric Laurent59255e42011-07-27 19:49:51 -07009324 for (size_t i = 0; i < mEffects.size(); i++) {
Glenn Kastend0539712012-01-30 12:56:03 -08009325 if (isEffectEligibleForSuspend(mEffects[i]->desc())) {
9326 effects.add(mEffects[i]);
Eric Laurent59255e42011-07-27 19:49:51 -07009327 }
Eric Laurent59255e42011-07-27 19:49:51 -07009328 }
Eric Laurent59255e42011-07-27 19:49:51 -07009329}
9330
9331sp<AudioFlinger::EffectModule> AudioFlinger::EffectChain::getEffectIfEnabled(
9332 const effect_uuid_t *type)
9333{
Glenn Kasten090f0192012-01-30 13:00:02 -08009334 sp<EffectModule> effect = getEffectFromType_l(type);
9335 return effect != 0 && effect->isEnabled() ? effect : 0;
Eric Laurent59255e42011-07-27 19:49:51 -07009336}
9337
9338void AudioFlinger::EffectChain::checkSuspendOnEffectEnabled(const sp<EffectModule>& effect,
9339 bool enabled)
9340{
Glenn Kasten8d6a2442012-02-08 14:04:28 -08009341 ssize_t index = mSuspendedEffects.indexOfKey(effect->desc().type.timeLow);
Eric Laurent59255e42011-07-27 19:49:51 -07009342 if (enabled) {
9343 if (index < 0) {
9344 // if the effect is not suspend check if all effects are suspended
9345 index = mSuspendedEffects.indexOfKey((int)kKeyForSuspendAll);
9346 if (index < 0) {
9347 return;
9348 }
Eric Laurentdb7c0792011-08-10 10:37:50 -07009349 if (!isEffectEligibleForSuspend(effect->desc())) {
9350 return;
9351 }
Eric Laurent59255e42011-07-27 19:49:51 -07009352 setEffectSuspended_l(&effect->desc().type, enabled);
9353 index = mSuspendedEffects.indexOfKey(effect->desc().type.timeLow);
Eric Laurentdb7c0792011-08-10 10:37:50 -07009354 if (index < 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00009355 ALOGW("checkSuspendOnEffectEnabled() Fx should be suspended here!");
Eric Laurentdb7c0792011-08-10 10:37:50 -07009356 return;
9357 }
Eric Laurent59255e42011-07-27 19:49:51 -07009358 }
Steve Block3856b092011-10-20 11:56:00 +01009359 ALOGV("checkSuspendOnEffectEnabled() enable suspending fx %08x",
Glenn Kastene53b9ea2012-03-12 16:29:55 -07009360 effect->desc().type.timeLow);
Eric Laurent59255e42011-07-27 19:49:51 -07009361 sp<SuspendedEffectDesc> desc = mSuspendedEffects.valueAt(index);
9362 // if effect is requested to suspended but was not yet enabled, supend it now.
9363 if (desc->mEffect == 0) {
9364 desc->mEffect = effect;
9365 effect->setEnabled(false);
9366 effect->setSuspended(true);
9367 }
9368 } else {
9369 if (index < 0) {
9370 return;
9371 }
Steve Block3856b092011-10-20 11:56:00 +01009372 ALOGV("checkSuspendOnEffectEnabled() disable restoring fx %08x",
Glenn Kastene53b9ea2012-03-12 16:29:55 -07009373 effect->desc().type.timeLow);
Eric Laurent59255e42011-07-27 19:49:51 -07009374 sp<SuspendedEffectDesc> desc = mSuspendedEffects.valueAt(index);
9375 desc->mEffect.clear();
9376 effect->setSuspended(false);
9377 }
9378}
9379
Mathias Agopian65ab4712010-07-14 17:59:35 -07009380#undef LOG_TAG
9381#define LOG_TAG "AudioFlinger"
9382
9383// ----------------------------------------------------------------------------
9384
9385status_t AudioFlinger::onTransact(
9386 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
9387{
9388 return BnAudioFlinger::onTransact(code, data, reply, flags);
9389}
9390
Mathias Agopian65ab4712010-07-14 17:59:35 -07009391}; // namespace android