blob: 75e8cca98eca5b8f80c8d73b10568616e8036833 [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
Glenn Kastend8e6fd32012-05-07 11:07:57 -070022//#define ATRACE_TAG ATRACE_TAG_AUDIO
23
Mathias Agopian65ab4712010-07-14 17:59:35 -070024#include <math.h>
25#include <signal.h>
26#include <sys/time.h>
27#include <sys/resource.h>
28
Gloria Wang9ee159b2011-02-24 14:51:45 -080029#include <binder/IPCThreadState.h>
Mathias Agopian65ab4712010-07-14 17:59:35 -070030#include <binder/IServiceManager.h>
31#include <utils/Log.h>
Glenn Kastend8e6fd32012-05-07 11:07:57 -070032#include <utils/Trace.h>
Mathias Agopian65ab4712010-07-14 17:59:35 -070033#include <binder/Parcel.h>
34#include <binder/IPCThreadState.h>
35#include <utils/String16.h>
36#include <utils/threads.h>
Eric Laurent38ccae22011-03-28 18:37:07 -070037#include <utils/Atomic.h>
Mathias Agopian65ab4712010-07-14 17:59:35 -070038
Dima Zavinfce7a472011-04-19 22:30:36 -070039#include <cutils/bitops.h>
Mathias Agopian65ab4712010-07-14 17:59:35 -070040#include <cutils/properties.h>
Glenn Kastenf6b16782011-12-15 09:51:17 -080041#include <cutils/compiler.h>
Mathias Agopian65ab4712010-07-14 17:59:35 -070042
Glenn Kastend3cee2f2012-03-13 17:55:35 -070043#undef ADD_BATTERY_DATA
44
45#ifdef ADD_BATTERY_DATA
Gloria Wang9ee159b2011-02-24 14:51:45 -080046#include <media/IMediaPlayerService.h>
Glenn Kasten25b248e2012-01-03 15:28:29 -080047#include <media/IMediaDeathNotifier.h>
Glenn Kastend3cee2f2012-03-13 17:55:35 -070048#endif
Mathias Agopian65ab4712010-07-14 17:59:35 -070049
50#include <private/media/AudioTrackShared.h>
51#include <private/media/AudioEffectShared.h>
Dima Zavinfce7a472011-04-19 22:30:36 -070052
Dima Zavin64760242011-05-11 14:15:23 -070053#include <system/audio.h>
Dima Zavin7394a4f2011-06-13 18:16:26 -070054#include <hardware/audio.h>
Mathias Agopian65ab4712010-07-14 17:59:35 -070055
56#include "AudioMixer.h"
57#include "AudioFlinger.h"
Glenn Kasten44deb052012-02-05 18:09:08 -080058#include "ServiceUtilities.h"
Mathias Agopian65ab4712010-07-14 17:59:35 -070059
Mathias Agopian65ab4712010-07-14 17:59:35 -070060#include <media/EffectsFactoryApi.h>
Eric Laurent6d8b6942011-06-24 07:01:31 -070061#include <audio_effects/effect_visualizer.h>
Eric Laurent59bd0da2011-08-01 09:52:20 -070062#include <audio_effects/effect_ns.h>
63#include <audio_effects/effect_aec.h>
Mathias Agopian65ab4712010-07-14 17:59:35 -070064
Glenn Kasten3b21c502011-12-15 09:52:39 -080065#include <audio_utils/primitives.h>
66
Eric Laurentfeb0db62011-07-22 09:04:31 -070067#include <powermanager/PowerManager.h>
Glenn Kasten190a46f2012-03-06 11:27:10 -080068
Glenn Kasten4d8d0c32011-07-08 15:26:12 -070069// #define DEBUG_CPU_USAGE 10 // log statistics every n wall clock seconds
Glenn Kasten190a46f2012-03-06 11:27:10 -080070#ifdef DEBUG_CPU_USAGE
71#include <cpustats/CentralTendencyStatistics.h>
72#include <cpustats/ThreadCpuUsage.h>
73#endif
Glenn Kasten4d8d0c32011-07-08 15:26:12 -070074
John Grossman4ff14ba2012-02-08 16:37:41 -080075#include <common_time/cc_helper.h>
76#include <common_time/local_clock.h>
77
Glenn Kasten58912562012-04-03 10:45:00 -070078#include "FastMixer.h"
79
80// NBAIO implementations
81#include "AudioStreamOutSink.h"
82#include "MonoPipe.h"
83#include "MonoPipeReader.h"
84#include "SourceAudioBufferProvider.h"
85
Glenn Kasten1dc28b72012-04-24 10:01:03 -070086#ifdef HAVE_REQUEST_PRIORITY
87#include "SchedulingPolicyService.h"
88#endif
89
Glenn Kasten58912562012-04-03 10:45:00 -070090#ifdef SOAKER
91#include "Soaker.h"
92#endif
93
Mathias Agopian65ab4712010-07-14 17:59:35 -070094// ----------------------------------------------------------------------------
Mathias Agopian65ab4712010-07-14 17:59:35 -070095
John Grossman1c345192012-03-27 14:00:17 -070096// Note: the following macro is used for extremely verbose logging message. In
97// order to run with ALOG_ASSERT turned on, we need to have LOG_NDEBUG set to
98// 0; but one side effect of this is to turn all LOGV's as well. Some messages
99// are so verbose that we want to suppress them even when we have ALOG_ASSERT
100// turned on. Do not uncomment the #def below unless you really know what you
101// are doing and want to see all of the extremely verbose messages.
102//#define VERY_VERY_VERBOSE_LOGGING
103#ifdef VERY_VERY_VERBOSE_LOGGING
104#define ALOGVV ALOGV
105#else
106#define ALOGVV(a...) do { } while(0)
107#endif
Eric Laurentde070132010-07-13 04:45:46 -0700108
Mathias Agopian65ab4712010-07-14 17:59:35 -0700109namespace android {
110
Glenn Kastenec1d6b52011-12-12 09:04:45 -0800111static const char kDeadlockedString[] = "AudioFlinger may be deadlocked\n";
112static const char kHardwareLockedString[] = "Hardware lock is taken\n";
Mathias Agopian65ab4712010-07-14 17:59:35 -0700113
Mathias Agopian65ab4712010-07-14 17:59:35 -0700114static const float MAX_GAIN = 4096.0f;
Glenn Kastenb1cf75c2012-01-17 12:20:54 -0800115static const uint32_t MAX_GAIN_INT = 0x1000;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700116
117// retry counts for buffer fill timeout
118// 50 * ~20msecs = 1 second
119static const int8_t kMaxTrackRetries = 50;
120static const int8_t kMaxTrackStartupRetries = 50;
121// allow less retry attempts on direct output thread.
122// direct outputs can be a scarce resource in audio hardware and should
123// be released as quickly as possible.
124static const int8_t kMaxTrackRetriesDirect = 2;
125
126static const int kDumpLockRetries = 50;
Glenn Kasten7dede872011-12-13 11:04:14 -0800127static const int kDumpLockSleepUs = 20000;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700128
Glenn Kasten7dede872011-12-13 11:04:14 -0800129// don't warn about blocked writes or record buffer overflows more often than this
130static const nsecs_t kWarningThrottleNs = seconds(5);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700131
Eric Laurent7c7f10b2011-06-17 21:29:58 -0700132// RecordThread loop sleep time upon application overrun or audio HAL read error
133static const int kRecordThreadSleepUs = 5000;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700134
Glenn Kasten7dede872011-12-13 11:04:14 -0800135// maximum time to wait for setParameters to complete
136static const nsecs_t kSetParametersTimeoutNs = seconds(2);
Eric Laurent60cd0a02011-09-13 11:40:21 -0700137
Eric Laurent7cafbb32011-11-22 18:50:29 -0800138// minimum sleep time for the mixer thread loop when tracks are active but in underrun
139static const uint32_t kMinThreadSleepTimeUs = 5000;
140// maximum divider applied to the active sleep time in the mixer thread loop
141static const uint32_t kMaxThreadSleepTimeShift = 2;
142
Glenn Kasten58912562012-04-03 10:45:00 -0700143// minimum normal mix buffer size, expressed in milliseconds rather than frames
144static const uint32_t kMinNormalMixBufferSizeMs = 20;
Glenn Kasten4adcede2012-05-14 12:26:02 -0700145// maximum normal mix buffer size
146static const uint32_t kMaxNormalMixBufferSizeMs = 24;
Glenn Kasten58912562012-04-03 10:45:00 -0700147
John Grossman4ff14ba2012-02-08 16:37:41 -0800148nsecs_t AudioFlinger::mStandbyTimeInNsecs = kDefaultStandbyTimeInNsecs;
Eric Laurent7cafbb32011-11-22 18:50:29 -0800149
Glenn Kasten300a2ee2012-04-25 13:47:36 -0700150// Whether to use fast mixer
151static const enum {
152 FastMixer_Never, // never initialize or use: for debugging only
153 FastMixer_Always, // always initialize and use, even if not needed: for debugging only
154 // normal mixer multiplier is 1
155 FastMixer_Static, // initialize if needed, then use all the time if initialized,
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 FastMixer_Dynamic, // initialize if needed, then use dynamically depending on track load,
Glenn Kasten4adcede2012-05-14 12:26:02 -0700158 // multiplier is calculated based on min & max normal mixer buffer size
Glenn Kasten300a2ee2012-04-25 13:47:36 -0700159 // FIXME for FastMixer_Dynamic:
160 // Supporting this option will require fixing HALs that can't handle large writes.
161 // For example, one HAL implementation returns an error from a large write,
162 // and another HAL implementation corrupts memory, possibly in the sample rate converter.
163 // We could either fix the HAL implementations, or provide a wrapper that breaks
164 // up large writes into smaller ones, and the wrapper would need to deal with scheduler.
165} kUseFastMixer = FastMixer_Static;
166
Mathias Agopian65ab4712010-07-14 17:59:35 -0700167// ----------------------------------------------------------------------------
168
Glenn Kastend3cee2f2012-03-13 17:55:35 -0700169#ifdef ADD_BATTERY_DATA
Gloria Wang9ee159b2011-02-24 14:51:45 -0800170// To collect the amplifier usage
171static void addBatteryData(uint32_t params) {
Glenn Kasten25b248e2012-01-03 15:28:29 -0800172 sp<IMediaPlayerService> service = IMediaDeathNotifier::getMediaPlayerService();
173 if (service == NULL) {
174 // it already logged
Gloria Wang9ee159b2011-02-24 14:51:45 -0800175 return;
176 }
177
178 service->addBatteryData(params);
179}
Glenn Kastend3cee2f2012-03-13 17:55:35 -0700180#endif
Gloria Wang9ee159b2011-02-24 14:51:45 -0800181
Eric Laurentf7ffb8b2012-04-14 09:06:57 -0700182static int load_audio_interface(const char *if_name, audio_hw_device_t **dev)
Dima Zavin799a70e2011-04-18 16:57:27 -0700183{
Eric Laurentf7ffb8b2012-04-14 09:06:57 -0700184 const hw_module_t *mod;
Dima Zavin799a70e2011-04-18 16:57:27 -0700185 int rc;
186
Eric Laurentf7ffb8b2012-04-14 09:06:57 -0700187 rc = hw_get_module_by_class(AUDIO_HARDWARE_MODULE_ID, if_name, &mod);
188 ALOGE_IF(rc, "%s couldn't load audio hw module %s.%s (%s)", __func__,
189 AUDIO_HARDWARE_MODULE_ID, if_name, strerror(-rc));
190 if (rc) {
Dima Zavin799a70e2011-04-18 16:57:27 -0700191 goto out;
Eric Laurentf7ffb8b2012-04-14 09:06:57 -0700192 }
193 rc = audio_hw_device_open(mod, dev);
194 ALOGE_IF(rc, "%s couldn't open audio hw device in %s.%s (%s)", __func__,
195 AUDIO_HARDWARE_MODULE_ID, if_name, strerror(-rc));
196 if (rc) {
Dima Zavin799a70e2011-04-18 16:57:27 -0700197 goto out;
Eric Laurentf7ffb8b2012-04-14 09:06:57 -0700198 }
199 if ((*dev)->common.version != AUDIO_DEVICE_API_VERSION_CURRENT) {
200 ALOGE("%s wrong audio hw device version %04x", __func__, (*dev)->common.version);
201 rc = BAD_VALUE;
202 goto out;
203 }
Dima Zavin799a70e2011-04-18 16:57:27 -0700204 return 0;
205
206out:
Dima Zavin799a70e2011-04-18 16:57:27 -0700207 *dev = NULL;
208 return rc;
209}
210
Mathias Agopian65ab4712010-07-14 17:59:35 -0700211// ----------------------------------------------------------------------------
212
213AudioFlinger::AudioFlinger()
214 : BnAudioFlinger(),
John Grossman4ff14ba2012-02-08 16:37:41 -0800215 mPrimaryHardwareDev(NULL),
216 mHardwareStatus(AUDIO_HW_IDLE), // see also onFirstRef()
217 mMasterVolume(1.0f),
218 mMasterVolumeSupportLvl(MVS_NONE),
219 mMasterMute(false),
220 mNextUniqueId(1),
221 mMode(AUDIO_MODE_INVALID),
222 mBtNrecIsOff(false)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700223{
Dima Zavin5a61d2f2011-04-19 19:04:32 -0700224}
225
226void AudioFlinger::onFirstRef()
227{
Dima Zavin799a70e2011-04-18 16:57:27 -0700228 int rc = 0;
Dima Zavinfce7a472011-04-19 22:30:36 -0700229
Eric Laurent93575202011-01-18 18:39:02 -0800230 Mutex::Autolock _l(mLock);
231
Dima Zavin799a70e2011-04-18 16:57:27 -0700232 /* TODO: move all this work into an Init() function */
John Grossman4ff14ba2012-02-08 16:37:41 -0800233 char val_str[PROPERTY_VALUE_MAX] = { 0 };
234 if (property_get("ro.audio.flinger_standbytime_ms", val_str, NULL) >= 0) {
235 uint32_t int_val;
236 if (1 == sscanf(val_str, "%u", &int_val)) {
237 mStandbyTimeInNsecs = milliseconds(int_val);
238 ALOGI("Using %u mSec as standby time.", int_val);
239 } else {
240 mStandbyTimeInNsecs = kDefaultStandbyTimeInNsecs;
241 ALOGI("Using default %u mSec as standby time.",
242 (uint32_t)(mStandbyTimeInNsecs / 1000000));
243 }
244 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700245
Eric Laurenta4c5a552012-03-29 10:12:40 -0700246 mMode = AUDIO_MODE_NORMAL;
247 mMasterVolumeSW = 1.0;
248 mMasterVolume = 1.0;
John Grossman4ff14ba2012-02-08 16:37:41 -0800249 mHardwareStatus = AUDIO_HW_IDLE;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700250}
251
252AudioFlinger::~AudioFlinger()
253{
Dima Zavin799a70e2011-04-18 16:57:27 -0700254
Mathias Agopian65ab4712010-07-14 17:59:35 -0700255 while (!mRecordThreads.isEmpty()) {
256 // closeInput() will remove first entry from mRecordThreads
257 closeInput(mRecordThreads.keyAt(0));
258 }
259 while (!mPlaybackThreads.isEmpty()) {
260 // closeOutput() will remove first entry from mPlaybackThreads
261 closeOutput(mPlaybackThreads.keyAt(0));
262 }
Dima Zavin799a70e2011-04-18 16:57:27 -0700263
Glenn Kasten2b213bc2012-02-02 14:05:20 -0800264 for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
265 // no mHardwareLock needed, as there are no other references to this
Eric Laurenta4c5a552012-03-29 10:12:40 -0700266 audio_hw_device_close(mAudioHwDevs.valueAt(i)->hwDevice());
267 delete mAudioHwDevs.valueAt(i);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700268 }
269}
270
Eric Laurenta4c5a552012-03-29 10:12:40 -0700271static const char * const audio_interfaces[] = {
272 AUDIO_HARDWARE_MODULE_ID_PRIMARY,
273 AUDIO_HARDWARE_MODULE_ID_A2DP,
274 AUDIO_HARDWARE_MODULE_ID_USB,
275};
276#define ARRAY_SIZE(x) (sizeof((x))/sizeof(((x)[0])))
277
278audio_hw_device_t* AudioFlinger::findSuitableHwDev_l(audio_module_handle_t module, uint32_t devices)
Dima Zavin799a70e2011-04-18 16:57:27 -0700279{
Eric Laurenta4c5a552012-03-29 10:12:40 -0700280 // if module is 0, the request comes from an old policy manager and we should load
281 // well known modules
282 if (module == 0) {
283 ALOGW("findSuitableHwDev_l() loading well know audio hw modules");
284 for (size_t i = 0; i < ARRAY_SIZE(audio_interfaces); i++) {
285 loadHwModule_l(audio_interfaces[i]);
286 }
287 } else {
288 // check a match for the requested module handle
289 AudioHwDevice *audioHwdevice = mAudioHwDevs.valueFor(module);
290 if (audioHwdevice != NULL) {
291 return audioHwdevice->hwDevice();
292 }
293 }
294 // then try to find a module supporting the requested device.
Dima Zavin799a70e2011-04-18 16:57:27 -0700295 for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
Eric Laurenta4c5a552012-03-29 10:12:40 -0700296 audio_hw_device_t *dev = mAudioHwDevs.valueAt(i)->hwDevice();
Dima Zavin799a70e2011-04-18 16:57:27 -0700297 if ((dev->get_supported_devices(dev) & devices) == devices)
298 return dev;
299 }
Eric Laurenta4c5a552012-03-29 10:12:40 -0700300
Dima Zavin799a70e2011-04-18 16:57:27 -0700301 return NULL;
302}
Mathias Agopian65ab4712010-07-14 17:59:35 -0700303
304status_t AudioFlinger::dumpClients(int fd, const Vector<String16>& args)
305{
306 const size_t SIZE = 256;
307 char buffer[SIZE];
308 String8 result;
309
310 result.append("Clients:\n");
311 for (size_t i = 0; i < mClients.size(); ++i) {
Glenn Kasten77c11192012-01-25 14:27:41 -0800312 sp<Client> client = mClients.valueAt(i).promote();
313 if (client != 0) {
314 snprintf(buffer, SIZE, " pid: %d\n", client->pid());
315 result.append(buffer);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700316 }
317 }
Marco Nelissen3a34bef2011-08-02 13:33:41 -0700318
319 result.append("Global session refs:\n");
Glenn Kasten012ca6b2012-03-06 11:22:01 -0800320 result.append(" session pid count\n");
Marco Nelissen3a34bef2011-08-02 13:33:41 -0700321 for (size_t i = 0; i < mAudioSessionRefs.size(); i++) {
322 AudioSessionRef *r = mAudioSessionRefs[i];
Glenn Kasten012ca6b2012-03-06 11:22:01 -0800323 snprintf(buffer, SIZE, " %7d %3d %3d\n", r->mSessionid, r->mPid, r->mCnt);
Marco Nelissen3a34bef2011-08-02 13:33:41 -0700324 result.append(buffer);
325 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700326 write(fd, result.string(), result.size());
327 return NO_ERROR;
328}
329
330
331status_t AudioFlinger::dumpInternals(int fd, const Vector<String16>& args)
332{
333 const size_t SIZE = 256;
334 char buffer[SIZE];
335 String8 result;
Glenn Kastena4454b42012-01-04 11:02:33 -0800336 hardware_call_state hardwareStatus = mHardwareStatus;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700337
John Grossman4ff14ba2012-02-08 16:37:41 -0800338 snprintf(buffer, SIZE, "Hardware status: %d\n"
339 "Standby Time mSec: %u\n",
340 hardwareStatus,
341 (uint32_t)(mStandbyTimeInNsecs / 1000000));
Mathias Agopian65ab4712010-07-14 17:59:35 -0700342 result.append(buffer);
343 write(fd, result.string(), result.size());
344 return NO_ERROR;
345}
346
347status_t AudioFlinger::dumpPermissionDenial(int fd, const Vector<String16>& args)
348{
349 const size_t SIZE = 256;
350 char buffer[SIZE];
351 String8 result;
352 snprintf(buffer, SIZE, "Permission Denial: "
353 "can't dump AudioFlinger from pid=%d, uid=%d\n",
354 IPCThreadState::self()->getCallingPid(),
355 IPCThreadState::self()->getCallingUid());
356 result.append(buffer);
357 write(fd, result.string(), result.size());
358 return NO_ERROR;
359}
360
361static bool tryLock(Mutex& mutex)
362{
363 bool locked = false;
364 for (int i = 0; i < kDumpLockRetries; ++i) {
365 if (mutex.tryLock() == NO_ERROR) {
366 locked = true;
367 break;
368 }
Glenn Kasten7dede872011-12-13 11:04:14 -0800369 usleep(kDumpLockSleepUs);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700370 }
371 return locked;
372}
373
374status_t AudioFlinger::dump(int fd, const Vector<String16>& args)
375{
Glenn Kasten44deb052012-02-05 18:09:08 -0800376 if (!dumpAllowed()) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700377 dumpPermissionDenial(fd, args);
378 } else {
379 // get state of hardware lock
380 bool hardwareLocked = tryLock(mHardwareLock);
381 if (!hardwareLocked) {
382 String8 result(kHardwareLockedString);
383 write(fd, result.string(), result.size());
384 } else {
385 mHardwareLock.unlock();
386 }
387
388 bool locked = tryLock(mLock);
389
390 // failed to lock - AudioFlinger is probably deadlocked
391 if (!locked) {
392 String8 result(kDeadlockedString);
393 write(fd, result.string(), result.size());
394 }
395
396 dumpClients(fd, args);
397 dumpInternals(fd, args);
398
399 // dump playback threads
400 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
401 mPlaybackThreads.valueAt(i)->dump(fd, args);
402 }
403
404 // dump record threads
405 for (size_t i = 0; i < mRecordThreads.size(); i++) {
406 mRecordThreads.valueAt(i)->dump(fd, args);
407 }
408
Dima Zavin799a70e2011-04-18 16:57:27 -0700409 // dump all hardware devs
410 for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
Eric Laurenta4c5a552012-03-29 10:12:40 -0700411 audio_hw_device_t *dev = mAudioHwDevs.valueAt(i)->hwDevice();
Dima Zavin799a70e2011-04-18 16:57:27 -0700412 dev->dump(dev, fd);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700413 }
414 if (locked) mLock.unlock();
415 }
416 return NO_ERROR;
417}
418
Glenn Kasten98ec94c2012-01-25 14:28:29 -0800419sp<AudioFlinger::Client> AudioFlinger::registerPid_l(pid_t pid)
420{
421 // If pid is already in the mClients wp<> map, then use that entry
422 // (for which promote() is always != 0), otherwise create a new entry and Client.
423 sp<Client> client = mClients.valueFor(pid).promote();
424 if (client == 0) {
425 client = new Client(this, pid);
426 mClients.add(pid, client);
427 }
428
429 return client;
430}
Mathias Agopian65ab4712010-07-14 17:59:35 -0700431
432// IAudioFlinger interface
433
434
435sp<IAudioTrack> AudioFlinger::createTrack(
436 pid_t pid,
Glenn Kastenfff6d712012-01-12 16:38:12 -0800437 audio_stream_type_t streamType,
Mathias Agopian65ab4712010-07-14 17:59:35 -0700438 uint32_t sampleRate,
Glenn Kasten58f30212012-01-12 12:27:51 -0800439 audio_format_t format,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -0700440 uint32_t channelMask,
Mathias Agopian65ab4712010-07-14 17:59:35 -0700441 int frameCount,
Glenn Kastena075db42012-03-06 11:22:44 -0800442 IAudioFlinger::track_flags_t flags,
Mathias Agopian65ab4712010-07-14 17:59:35 -0700443 const sp<IMemory>& sharedBuffer,
Glenn Kasten72ef00d2012-01-17 11:09:42 -0800444 audio_io_handle_t output,
Glenn Kasten3acbd052012-02-28 10:39:56 -0800445 pid_t tid,
Mathias Agopian65ab4712010-07-14 17:59:35 -0700446 int *sessionId,
447 status_t *status)
448{
449 sp<PlaybackThread::Track> track;
450 sp<TrackHandle> trackHandle;
451 sp<Client> client;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700452 status_t lStatus;
453 int lSessionId;
454
Glenn Kasten263709e2012-01-06 08:40:01 -0800455 // client AudioTrack::set already implements AUDIO_STREAM_DEFAULT => AUDIO_STREAM_MUSIC,
456 // but if someone uses binder directly they could bypass that and cause us to crash
457 if (uint32_t(streamType) >= AUDIO_STREAM_CNT) {
Steve Block29357bc2012-01-06 19:20:56 +0000458 ALOGE("createTrack() invalid stream type %d", streamType);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700459 lStatus = BAD_VALUE;
460 goto Exit;
461 }
462
463 {
464 Mutex::Autolock _l(mLock);
465 PlaybackThread *thread = checkPlaybackThread_l(output);
Eric Laurent39e94f82010-07-28 01:32:47 -0700466 PlaybackThread *effectThread = NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700467 if (thread == NULL) {
Steve Block29357bc2012-01-06 19:20:56 +0000468 ALOGE("unknown output thread");
Mathias Agopian65ab4712010-07-14 17:59:35 -0700469 lStatus = BAD_VALUE;
470 goto Exit;
471 }
472
Glenn Kasten98ec94c2012-01-25 14:28:29 -0800473 client = registerPid_l(pid);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700474
Steve Block3856b092011-10-20 11:56:00 +0100475 ALOGV("createTrack() sessionId: %d", (sessionId == NULL) ? -2 : *sessionId);
Dima Zavinfce7a472011-04-19 22:30:36 -0700476 if (sessionId != NULL && *sessionId != AUDIO_SESSION_OUTPUT_MIX) {
Eric Laurentde070132010-07-13 04:45:46 -0700477 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
Eric Laurent39e94f82010-07-28 01:32:47 -0700478 sp<PlaybackThread> t = mPlaybackThreads.valueAt(i);
479 if (mPlaybackThreads.keyAt(i) != output) {
480 // prevent same audio session on different output threads
481 uint32_t sessions = t->hasAudioSession(*sessionId);
482 if (sessions & PlaybackThread::TRACK_SESSION) {
Steve Block29357bc2012-01-06 19:20:56 +0000483 ALOGE("createTrack() session ID %d already in use", *sessionId);
Eric Laurent39e94f82010-07-28 01:32:47 -0700484 lStatus = BAD_VALUE;
485 goto Exit;
486 }
487 // check if an effect with same session ID is waiting for a track to be created
488 if (sessions & PlaybackThread::EFFECT_SESSION) {
489 effectThread = t.get();
490 }
Eric Laurentde070132010-07-13 04:45:46 -0700491 }
492 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700493 lSessionId = *sessionId;
494 } else {
Eric Laurentde070132010-07-13 04:45:46 -0700495 // if no audio session id is provided, create one here
Eric Laurent7c7f10b2011-06-17 21:29:58 -0700496 lSessionId = nextUniqueId();
Mathias Agopian65ab4712010-07-14 17:59:35 -0700497 if (sessionId != NULL) {
498 *sessionId = lSessionId;
499 }
500 }
Steve Block3856b092011-10-20 11:56:00 +0100501 ALOGV("createTrack() lSessionId: %d", lSessionId);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700502
503 track = thread->createTrack_l(client, streamType, sampleRate, format,
Glenn Kasten3acbd052012-02-28 10:39:56 -0800504 channelMask, frameCount, sharedBuffer, lSessionId, flags, tid, &lStatus);
Eric Laurent39e94f82010-07-28 01:32:47 -0700505
506 // move effect chain to this output thread if an effect on same session was waiting
507 // for a track to be created
508 if (lStatus == NO_ERROR && effectThread != NULL) {
509 Mutex::Autolock _dl(thread->mLock);
510 Mutex::Autolock _sl(effectThread->mLock);
511 moveEffectChain_l(lSessionId, effectThread, thread, true);
512 }
Eric Laurenta011e352012-03-29 15:51:43 -0700513
514 // Look for sync events awaiting for a session to be used.
515 for (int i = 0; i < (int)mPendingSyncEvents.size(); i++) {
516 if (mPendingSyncEvents[i]->triggerSession() == lSessionId) {
517 if (thread->isValidSyncEvent(mPendingSyncEvents[i])) {
Eric Laurent29864602012-05-08 18:57:51 -0700518 if (lStatus == NO_ERROR) {
519 track->setSyncEvent(mPendingSyncEvents[i]);
520 } else {
521 mPendingSyncEvents[i]->cancel();
522 }
Eric Laurenta011e352012-03-29 15:51:43 -0700523 mPendingSyncEvents.removeAt(i);
524 i--;
525 }
526 }
527 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700528 }
529 if (lStatus == NO_ERROR) {
530 trackHandle = new TrackHandle(track);
531 } else {
532 // remove local strong reference to Client before deleting the Track so that the Client
533 // destructor is called by the TrackBase destructor with mLock held
534 client.clear();
535 track.clear();
536 }
537
538Exit:
Glenn Kastene53b9ea2012-03-12 16:29:55 -0700539 if (status != NULL) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700540 *status = lStatus;
541 }
542 return trackHandle;
543}
544
Glenn Kasten72ef00d2012-01-17 11:09:42 -0800545uint32_t AudioFlinger::sampleRate(audio_io_handle_t output) const
Mathias Agopian65ab4712010-07-14 17:59:35 -0700546{
547 Mutex::Autolock _l(mLock);
548 PlaybackThread *thread = checkPlaybackThread_l(output);
549 if (thread == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +0000550 ALOGW("sampleRate() unknown thread %d", output);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700551 return 0;
552 }
553 return thread->sampleRate();
554}
555
Glenn Kasten72ef00d2012-01-17 11:09:42 -0800556int AudioFlinger::channelCount(audio_io_handle_t output) const
Mathias Agopian65ab4712010-07-14 17:59:35 -0700557{
558 Mutex::Autolock _l(mLock);
559 PlaybackThread *thread = checkPlaybackThread_l(output);
560 if (thread == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +0000561 ALOGW("channelCount() unknown thread %d", output);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700562 return 0;
563 }
564 return thread->channelCount();
565}
566
Glenn Kasten72ef00d2012-01-17 11:09:42 -0800567audio_format_t AudioFlinger::format(audio_io_handle_t output) const
Mathias Agopian65ab4712010-07-14 17:59:35 -0700568{
569 Mutex::Autolock _l(mLock);
570 PlaybackThread *thread = checkPlaybackThread_l(output);
571 if (thread == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +0000572 ALOGW("format() unknown thread %d", output);
Glenn Kasten58f30212012-01-12 12:27:51 -0800573 return AUDIO_FORMAT_INVALID;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700574 }
575 return thread->format();
576}
577
Glenn Kasten72ef00d2012-01-17 11:09:42 -0800578size_t AudioFlinger::frameCount(audio_io_handle_t output) const
Mathias Agopian65ab4712010-07-14 17:59:35 -0700579{
580 Mutex::Autolock _l(mLock);
581 PlaybackThread *thread = checkPlaybackThread_l(output);
582 if (thread == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +0000583 ALOGW("frameCount() unknown thread %d", output);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700584 return 0;
585 }
Glenn Kasten58912562012-04-03 10:45:00 -0700586 // FIXME currently returns the normal mixer's frame count to avoid confusing legacy callers;
587 // should examine all callers and fix them to handle smaller counts
Mathias Agopian65ab4712010-07-14 17:59:35 -0700588 return thread->frameCount();
589}
590
Glenn Kasten72ef00d2012-01-17 11:09:42 -0800591uint32_t AudioFlinger::latency(audio_io_handle_t output) const
Mathias Agopian65ab4712010-07-14 17:59:35 -0700592{
593 Mutex::Autolock _l(mLock);
594 PlaybackThread *thread = checkPlaybackThread_l(output);
595 if (thread == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +0000596 ALOGW("latency() unknown thread %d", output);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700597 return 0;
598 }
599 return thread->latency();
600}
601
602status_t AudioFlinger::setMasterVolume(float value)
603{
Eric Laurenta1884f92011-08-23 08:25:03 -0700604 status_t ret = initCheck();
605 if (ret != NO_ERROR) {
606 return ret;
607 }
608
Mathias Agopian65ab4712010-07-14 17:59:35 -0700609 // check calling permissions
610 if (!settingsAllowed()) {
611 return PERMISSION_DENIED;
612 }
613
John Grossman4ff14ba2012-02-08 16:37:41 -0800614 float swmv = value;
615
Eric Laurenta4c5a552012-03-29 10:12:40 -0700616 Mutex::Autolock _l(mLock);
617
Mathias Agopian65ab4712010-07-14 17:59:35 -0700618 // when hw supports master volume, don't scale in sw mixer
John Grossman4ff14ba2012-02-08 16:37:41 -0800619 if (MVS_NONE != mMasterVolumeSupportLvl) {
620 for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
621 AutoMutex lock(mHardwareLock);
Eric Laurenta4c5a552012-03-29 10:12:40 -0700622 audio_hw_device_t *dev = mAudioHwDevs.valueAt(i)->hwDevice();
John Grossman4ff14ba2012-02-08 16:37:41 -0800623
624 mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
625 if (NULL != dev->set_master_volume) {
626 dev->set_master_volume(dev, value);
627 }
628 mHardwareStatus = AUDIO_HW_IDLE;
Eric Laurent93575202011-01-18 18:39:02 -0800629 }
John Grossman4ff14ba2012-02-08 16:37:41 -0800630
631 swmv = 1.0;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700632 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700633
John Grossman4ff14ba2012-02-08 16:37:41 -0800634 mMasterVolume = value;
635 mMasterVolumeSW = swmv;
Glenn Kasten8d6a2442012-02-08 14:04:28 -0800636 for (size_t i = 0; i < mPlaybackThreads.size(); i++)
Glenn Kastene53b9ea2012-03-12 16:29:55 -0700637 mPlaybackThreads.valueAt(i)->setMasterVolume(swmv);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700638
639 return NO_ERROR;
640}
641
Glenn Kastenf78aee72012-01-04 11:00:47 -0800642status_t AudioFlinger::setMode(audio_mode_t mode)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700643{
Eric Laurenta1884f92011-08-23 08:25:03 -0700644 status_t ret = initCheck();
645 if (ret != NO_ERROR) {
646 return ret;
647 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700648
649 // check calling permissions
650 if (!settingsAllowed()) {
651 return PERMISSION_DENIED;
652 }
Glenn Kasten930f4ca2012-01-06 16:47:31 -0800653 if (uint32_t(mode) >= AUDIO_MODE_CNT) {
Steve Block5ff1dd52012-01-05 23:22:43 +0000654 ALOGW("Illegal value: setMode(%d)", mode);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700655 return BAD_VALUE;
656 }
657
658 { // scope for the lock
659 AutoMutex lock(mHardwareLock);
660 mHardwareStatus = AUDIO_HW_SET_MODE;
Dima Zavin799a70e2011-04-18 16:57:27 -0700661 ret = mPrimaryHardwareDev->set_mode(mPrimaryHardwareDev, mode);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700662 mHardwareStatus = AUDIO_HW_IDLE;
663 }
664
665 if (NO_ERROR == ret) {
666 Mutex::Autolock _l(mLock);
667 mMode = mode;
Glenn Kasten8d6a2442012-02-08 14:04:28 -0800668 for (size_t i = 0; i < mPlaybackThreads.size(); i++)
Glenn Kastene53b9ea2012-03-12 16:29:55 -0700669 mPlaybackThreads.valueAt(i)->setMode(mode);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700670 }
671
672 return ret;
673}
674
675status_t AudioFlinger::setMicMute(bool state)
676{
Eric Laurenta1884f92011-08-23 08:25:03 -0700677 status_t ret = initCheck();
678 if (ret != NO_ERROR) {
679 return ret;
680 }
681
Mathias Agopian65ab4712010-07-14 17:59:35 -0700682 // check calling permissions
683 if (!settingsAllowed()) {
684 return PERMISSION_DENIED;
685 }
686
687 AutoMutex lock(mHardwareLock);
688 mHardwareStatus = AUDIO_HW_SET_MIC_MUTE;
Eric Laurenta1884f92011-08-23 08:25:03 -0700689 ret = mPrimaryHardwareDev->set_mic_mute(mPrimaryHardwareDev, state);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700690 mHardwareStatus = AUDIO_HW_IDLE;
691 return ret;
692}
693
694bool AudioFlinger::getMicMute() const
695{
Eric Laurenta1884f92011-08-23 08:25:03 -0700696 status_t ret = initCheck();
697 if (ret != NO_ERROR) {
698 return false;
699 }
700
Dima Zavinfce7a472011-04-19 22:30:36 -0700701 bool state = AUDIO_MODE_INVALID;
Glenn Kasten2b213bc2012-02-02 14:05:20 -0800702 AutoMutex lock(mHardwareLock);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700703 mHardwareStatus = AUDIO_HW_GET_MIC_MUTE;
Dima Zavin799a70e2011-04-18 16:57:27 -0700704 mPrimaryHardwareDev->get_mic_mute(mPrimaryHardwareDev, &state);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700705 mHardwareStatus = AUDIO_HW_IDLE;
706 return state;
707}
708
709status_t AudioFlinger::setMasterMute(bool muted)
710{
711 // check calling permissions
712 if (!settingsAllowed()) {
713 return PERMISSION_DENIED;
714 }
715
Eric Laurent93575202011-01-18 18:39:02 -0800716 Mutex::Autolock _l(mLock);
Glenn Kasten99e53b82012-01-19 08:59:58 -0800717 // This is an optimization, so PlaybackThread doesn't have to look at the one from AudioFlinger
Mathias Agopian65ab4712010-07-14 17:59:35 -0700718 mMasterMute = muted;
Glenn Kasten8d6a2442012-02-08 14:04:28 -0800719 for (size_t i = 0; i < mPlaybackThreads.size(); i++)
Glenn Kastene53b9ea2012-03-12 16:29:55 -0700720 mPlaybackThreads.valueAt(i)->setMasterMute(muted);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700721
722 return NO_ERROR;
723}
724
725float AudioFlinger::masterVolume() const
726{
Glenn Kasten98067102011-12-13 11:47:54 -0800727 Mutex::Autolock _l(mLock);
728 return masterVolume_l();
Mathias Agopian65ab4712010-07-14 17:59:35 -0700729}
730
John Grossman4ff14ba2012-02-08 16:37:41 -0800731float AudioFlinger::masterVolumeSW() const
732{
733 Mutex::Autolock _l(mLock);
734 return masterVolumeSW_l();
735}
736
Mathias Agopian65ab4712010-07-14 17:59:35 -0700737bool AudioFlinger::masterMute() const
738{
Glenn Kasten98067102011-12-13 11:47:54 -0800739 Mutex::Autolock _l(mLock);
740 return masterMute_l();
Mathias Agopian65ab4712010-07-14 17:59:35 -0700741}
742
John Grossman4ff14ba2012-02-08 16:37:41 -0800743float AudioFlinger::masterVolume_l() const
744{
745 if (MVS_FULL == mMasterVolumeSupportLvl) {
746 float ret_val;
747 AutoMutex lock(mHardwareLock);
748
749 mHardwareStatus = AUDIO_HW_GET_MASTER_VOLUME;
Glenn Kasten5798d4e2012-03-08 12:18:35 -0800750 ALOG_ASSERT((NULL != mPrimaryHardwareDev) &&
751 (NULL != mPrimaryHardwareDev->get_master_volume),
752 "can't get master volume");
John Grossman4ff14ba2012-02-08 16:37:41 -0800753
754 mPrimaryHardwareDev->get_master_volume(mPrimaryHardwareDev, &ret_val);
755 mHardwareStatus = AUDIO_HW_IDLE;
756 return ret_val;
757 }
758
759 return mMasterVolume;
760}
761
Glenn Kasten72ef00d2012-01-17 11:09:42 -0800762status_t AudioFlinger::setStreamVolume(audio_stream_type_t stream, float value,
763 audio_io_handle_t output)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700764{
765 // check calling permissions
766 if (!settingsAllowed()) {
767 return PERMISSION_DENIED;
768 }
769
Glenn Kasten263709e2012-01-06 08:40:01 -0800770 if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
Steve Block29357bc2012-01-06 19:20:56 +0000771 ALOGE("setStreamVolume() invalid stream %d", stream);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700772 return BAD_VALUE;
773 }
774
775 AutoMutex lock(mLock);
776 PlaybackThread *thread = NULL;
777 if (output) {
778 thread = checkPlaybackThread_l(output);
779 if (thread == NULL) {
780 return BAD_VALUE;
781 }
782 }
783
784 mStreamTypes[stream].volume = value;
785
786 if (thread == NULL) {
Glenn Kasten8d6a2442012-02-08 14:04:28 -0800787 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
Glenn Kastene53b9ea2012-03-12 16:29:55 -0700788 mPlaybackThreads.valueAt(i)->setStreamVolume(stream, value);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700789 }
790 } else {
791 thread->setStreamVolume(stream, value);
792 }
793
794 return NO_ERROR;
795}
796
Glenn Kastenfff6d712012-01-12 16:38:12 -0800797status_t AudioFlinger::setStreamMute(audio_stream_type_t stream, bool muted)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700798{
799 // check calling permissions
800 if (!settingsAllowed()) {
801 return PERMISSION_DENIED;
802 }
803
Glenn Kasten263709e2012-01-06 08:40:01 -0800804 if (uint32_t(stream) >= AUDIO_STREAM_CNT ||
Dima Zavinfce7a472011-04-19 22:30:36 -0700805 uint32_t(stream) == AUDIO_STREAM_ENFORCED_AUDIBLE) {
Steve Block29357bc2012-01-06 19:20:56 +0000806 ALOGE("setStreamMute() invalid stream %d", stream);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700807 return BAD_VALUE;
808 }
809
Eric Laurent93575202011-01-18 18:39:02 -0800810 AutoMutex lock(mLock);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700811 mStreamTypes[stream].mute = muted;
812 for (uint32_t i = 0; i < mPlaybackThreads.size(); i++)
Glenn Kastene53b9ea2012-03-12 16:29:55 -0700813 mPlaybackThreads.valueAt(i)->setStreamMute(stream, muted);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700814
815 return NO_ERROR;
816}
817
Glenn Kasten72ef00d2012-01-17 11:09:42 -0800818float AudioFlinger::streamVolume(audio_stream_type_t stream, audio_io_handle_t output) const
Mathias Agopian65ab4712010-07-14 17:59:35 -0700819{
Glenn Kasten263709e2012-01-06 08:40:01 -0800820 if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700821 return 0.0f;
822 }
823
824 AutoMutex lock(mLock);
825 float volume;
826 if (output) {
827 PlaybackThread *thread = checkPlaybackThread_l(output);
828 if (thread == NULL) {
829 return 0.0f;
830 }
831 volume = thread->streamVolume(stream);
832 } else {
Glenn Kasten6637baa2012-01-09 09:40:36 -0800833 volume = streamVolume_l(stream);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700834 }
835
836 return volume;
837}
838
Glenn Kastenfff6d712012-01-12 16:38:12 -0800839bool AudioFlinger::streamMute(audio_stream_type_t stream) const
Mathias Agopian65ab4712010-07-14 17:59:35 -0700840{
Glenn Kasten263709e2012-01-06 08:40:01 -0800841 if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700842 return true;
843 }
844
Glenn Kasten6637baa2012-01-09 09:40:36 -0800845 AutoMutex lock(mLock);
846 return streamMute_l(stream);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700847}
848
Glenn Kasten72ef00d2012-01-17 11:09:42 -0800849status_t AudioFlinger::setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700850{
Glenn Kasten23d82a92012-02-03 11:10:00 -0800851 ALOGV("setParameters(): io %d, keyvalue %s, tid %d, calling pid %d",
Mathias Agopian65ab4712010-07-14 17:59:35 -0700852 ioHandle, keyValuePairs.string(), gettid(), IPCThreadState::self()->getCallingPid());
853 // check calling permissions
854 if (!settingsAllowed()) {
855 return PERMISSION_DENIED;
856 }
857
Mathias Agopian65ab4712010-07-14 17:59:35 -0700858 // ioHandle == 0 means the parameters are global to the audio hardware interface
859 if (ioHandle == 0) {
Eric Laurenta4c5a552012-03-29 10:12:40 -0700860 Mutex::Autolock _l(mLock);
Dima Zavin799a70e2011-04-18 16:57:27 -0700861 status_t final_result = NO_ERROR;
Glenn Kasten8abf44d2012-02-02 14:16:03 -0800862 {
Eric Laurenta4c5a552012-03-29 10:12:40 -0700863 AutoMutex lock(mHardwareLock);
864 mHardwareStatus = AUDIO_HW_SET_PARAMETER;
865 for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
866 audio_hw_device_t *dev = mAudioHwDevs.valueAt(i)->hwDevice();
867 status_t result = dev->set_parameters(dev, keyValuePairs.string());
868 final_result = result ?: final_result;
869 }
870 mHardwareStatus = AUDIO_HW_IDLE;
Glenn Kasten8abf44d2012-02-02 14:16:03 -0800871 }
Eric Laurent59bd0da2011-08-01 09:52:20 -0700872 // disable AEC and NS if the device is a BT SCO headset supporting those pre processings
873 AudioParameter param = AudioParameter(keyValuePairs);
874 String8 value;
875 if (param.get(String8(AUDIO_PARAMETER_KEY_BT_NREC), value) == NO_ERROR) {
Eric Laurentbee53372011-08-29 12:42:48 -0700876 bool btNrecIsOff = (value == AUDIO_PARAMETER_VALUE_OFF);
877 if (mBtNrecIsOff != btNrecIsOff) {
Eric Laurent59bd0da2011-08-01 09:52:20 -0700878 for (size_t i = 0; i < mRecordThreads.size(); i++) {
879 sp<RecordThread> thread = mRecordThreads.valueAt(i);
880 RecordThread::RecordTrack *track = thread->track();
881 if (track != NULL) {
882 audio_devices_t device = (audio_devices_t)(
883 thread->device() & AUDIO_DEVICE_IN_ALL);
Eric Laurentbee53372011-08-29 12:42:48 -0700884 bool suspend = audio_is_bluetooth_sco_device(device) && btNrecIsOff;
Eric Laurent59bd0da2011-08-01 09:52:20 -0700885 thread->setEffectSuspended(FX_IID_AEC,
886 suspend,
887 track->sessionId());
888 thread->setEffectSuspended(FX_IID_NS,
889 suspend,
890 track->sessionId());
891 }
892 }
Eric Laurentbee53372011-08-29 12:42:48 -0700893 mBtNrecIsOff = btNrecIsOff;
Eric Laurent59bd0da2011-08-01 09:52:20 -0700894 }
895 }
Dima Zavin799a70e2011-04-18 16:57:27 -0700896 return final_result;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700897 }
898
899 // hold a strong ref on thread in case closeOutput() or closeInput() is called
900 // and the thread is exited once the lock is released
901 sp<ThreadBase> thread;
902 {
903 Mutex::Autolock _l(mLock);
904 thread = checkPlaybackThread_l(ioHandle);
905 if (thread == NULL) {
906 thread = checkRecordThread_l(ioHandle);
Glenn Kasten7fc9a6f2012-01-10 10:46:34 -0800907 } else if (thread == primaryPlaybackThread_l()) {
Eric Laurent7c7f10b2011-06-17 21:29:58 -0700908 // indicate output device change to all input threads for pre processing
909 AudioParameter param = AudioParameter(keyValuePairs);
910 int value;
Eric Laurent89d94e72012-03-16 20:37:59 -0700911 if ((param.getInt(String8(AudioParameter::keyRouting), value) == NO_ERROR) &&
912 (value != 0)) {
Eric Laurent7c7f10b2011-06-17 21:29:58 -0700913 for (size_t i = 0; i < mRecordThreads.size(); i++) {
914 mRecordThreads.valueAt(i)->setParameters(keyValuePairs);
915 }
916 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700917 }
918 }
Glenn Kasten7378ca52012-01-20 13:44:40 -0800919 if (thread != 0) {
920 return thread->setParameters(keyValuePairs);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700921 }
922 return BAD_VALUE;
923}
924
Glenn Kasten72ef00d2012-01-17 11:09:42 -0800925String8 AudioFlinger::getParameters(audio_io_handle_t ioHandle, const String8& keys) const
Mathias Agopian65ab4712010-07-14 17:59:35 -0700926{
Glenn Kasten23d82a92012-02-03 11:10:00 -0800927// ALOGV("getParameters() io %d, keys %s, tid %d, calling pid %d",
Mathias Agopian65ab4712010-07-14 17:59:35 -0700928// ioHandle, keys.string(), gettid(), IPCThreadState::self()->getCallingPid());
929
Eric Laurenta4c5a552012-03-29 10:12:40 -0700930 Mutex::Autolock _l(mLock);
931
Mathias Agopian65ab4712010-07-14 17:59:35 -0700932 if (ioHandle == 0) {
Dima Zavinfce7a472011-04-19 22:30:36 -0700933 String8 out_s8;
934
Dima Zavin799a70e2011-04-18 16:57:27 -0700935 for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
Glenn Kasten8abf44d2012-02-02 14:16:03 -0800936 char *s;
937 {
938 AutoMutex lock(mHardwareLock);
939 mHardwareStatus = AUDIO_HW_GET_PARAMETER;
Eric Laurenta4c5a552012-03-29 10:12:40 -0700940 audio_hw_device_t *dev = mAudioHwDevs.valueAt(i)->hwDevice();
Glenn Kasten8abf44d2012-02-02 14:16:03 -0800941 s = dev->get_parameters(dev, keys.string());
942 mHardwareStatus = AUDIO_HW_IDLE;
943 }
John Grossmanef7740b2012-02-09 11:28:36 -0800944 out_s8 += String8(s ? s : "");
Dima Zavin799a70e2011-04-18 16:57:27 -0700945 free(s);
946 }
Dima Zavinfce7a472011-04-19 22:30:36 -0700947 return out_s8;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700948 }
949
Mathias Agopian65ab4712010-07-14 17:59:35 -0700950 PlaybackThread *playbackThread = checkPlaybackThread_l(ioHandle);
951 if (playbackThread != NULL) {
952 return playbackThread->getParameters(keys);
953 }
954 RecordThread *recordThread = checkRecordThread_l(ioHandle);
955 if (recordThread != NULL) {
956 return recordThread->getParameters(keys);
957 }
958 return String8("");
959}
960
Glenn Kastenf587ba52012-01-26 16:25:10 -0800961size_t AudioFlinger::getInputBufferSize(uint32_t sampleRate, audio_format_t format, int channelCount) const
Mathias Agopian65ab4712010-07-14 17:59:35 -0700962{
Eric Laurenta1884f92011-08-23 08:25:03 -0700963 status_t ret = initCheck();
964 if (ret != NO_ERROR) {
965 return 0;
966 }
967
Glenn Kasten2b213bc2012-02-02 14:05:20 -0800968 AutoMutex lock(mHardwareLock);
969 mHardwareStatus = AUDIO_HW_GET_INPUT_BUFFER_SIZE;
Eric Laurentf7ffb8b2012-04-14 09:06:57 -0700970 struct audio_config config = {
971 sample_rate: sampleRate,
972 channel_mask: audio_channel_in_mask_from_count(channelCount),
973 format: format,
974 };
975 size_t size = mPrimaryHardwareDev->get_input_buffer_size(mPrimaryHardwareDev, &config);
Glenn Kasten2b213bc2012-02-02 14:05:20 -0800976 mHardwareStatus = AUDIO_HW_IDLE;
977 return size;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700978}
979
Glenn Kasten72ef00d2012-01-17 11:09:42 -0800980unsigned int AudioFlinger::getInputFramesLost(audio_io_handle_t ioHandle) const
Mathias Agopian65ab4712010-07-14 17:59:35 -0700981{
982 if (ioHandle == 0) {
983 return 0;
984 }
985
986 Mutex::Autolock _l(mLock);
987
988 RecordThread *recordThread = checkRecordThread_l(ioHandle);
989 if (recordThread != NULL) {
990 return recordThread->getInputFramesLost();
991 }
992 return 0;
993}
994
995status_t AudioFlinger::setVoiceVolume(float value)
996{
Eric Laurenta1884f92011-08-23 08:25:03 -0700997 status_t ret = initCheck();
998 if (ret != NO_ERROR) {
999 return ret;
1000 }
1001
Mathias Agopian65ab4712010-07-14 17:59:35 -07001002 // check calling permissions
1003 if (!settingsAllowed()) {
1004 return PERMISSION_DENIED;
1005 }
1006
1007 AutoMutex lock(mHardwareLock);
Glenn Kasten8abf44d2012-02-02 14:16:03 -08001008 mHardwareStatus = AUDIO_HW_SET_VOICE_VOLUME;
Eric Laurenta1884f92011-08-23 08:25:03 -07001009 ret = mPrimaryHardwareDev->set_voice_volume(mPrimaryHardwareDev, value);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001010 mHardwareStatus = AUDIO_HW_IDLE;
1011
1012 return ret;
1013}
1014
Glenn Kasten72ef00d2012-01-17 11:09:42 -08001015status_t AudioFlinger::getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames,
1016 audio_io_handle_t output) const
Mathias Agopian65ab4712010-07-14 17:59:35 -07001017{
1018 status_t status;
1019
1020 Mutex::Autolock _l(mLock);
1021
1022 PlaybackThread *playbackThread = checkPlaybackThread_l(output);
1023 if (playbackThread != NULL) {
1024 return playbackThread->getRenderPosition(halFrames, dspFrames);
1025 }
1026
1027 return BAD_VALUE;
1028}
1029
1030void AudioFlinger::registerClient(const sp<IAudioFlingerClient>& client)
1031{
1032
1033 Mutex::Autolock _l(mLock);
1034
Glenn Kastenbb001922012-02-03 11:10:26 -08001035 pid_t pid = IPCThreadState::self()->getCallingPid();
Mathias Agopian65ab4712010-07-14 17:59:35 -07001036 if (mNotificationClients.indexOfKey(pid) < 0) {
1037 sp<NotificationClient> notificationClient = new NotificationClient(this,
1038 client,
1039 pid);
Steve Block3856b092011-10-20 11:56:00 +01001040 ALOGV("registerClient() client %p, pid %d", notificationClient.get(), pid);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001041
1042 mNotificationClients.add(pid, notificationClient);
1043
1044 sp<IBinder> binder = client->asBinder();
1045 binder->linkToDeath(notificationClient);
1046
1047 // the config change is always sent from playback or record threads to avoid deadlock
1048 // with AudioSystem::gLock
1049 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
1050 mPlaybackThreads.valueAt(i)->sendConfigEvent(AudioSystem::OUTPUT_OPENED);
1051 }
1052
1053 for (size_t i = 0; i < mRecordThreads.size(); i++) {
1054 mRecordThreads.valueAt(i)->sendConfigEvent(AudioSystem::INPUT_OPENED);
1055 }
1056 }
1057}
1058
1059void AudioFlinger::removeNotificationClient(pid_t pid)
1060{
1061 Mutex::Autolock _l(mLock);
1062
Glenn Kastena3b09252012-01-20 09:19:01 -08001063 mNotificationClients.removeItem(pid);
Marco Nelissen3a34bef2011-08-02 13:33:41 -07001064
Steve Block3856b092011-10-20 11:56:00 +01001065 ALOGV("%d died, releasing its sessions", pid);
Glenn Kasten8d6a2442012-02-08 14:04:28 -08001066 size_t num = mAudioSessionRefs.size();
Marco Nelissen3a34bef2011-08-02 13:33:41 -07001067 bool removed = false;
Glenn Kasten8d6a2442012-02-08 14:04:28 -08001068 for (size_t i = 0; i< num; ) {
Marco Nelissen3a34bef2011-08-02 13:33:41 -07001069 AudioSessionRef *ref = mAudioSessionRefs.itemAt(i);
Glenn Kasten012ca6b2012-03-06 11:22:01 -08001070 ALOGV(" pid %d @ %d", ref->mPid, i);
1071 if (ref->mPid == pid) {
1072 ALOGV(" removing entry for pid %d session %d", pid, ref->mSessionid);
Marco Nelissen3a34bef2011-08-02 13:33:41 -07001073 mAudioSessionRefs.removeAt(i);
1074 delete ref;
1075 removed = true;
Marco Nelissen3a34bef2011-08-02 13:33:41 -07001076 num--;
Glenn Kasten8d6a2442012-02-08 14:04:28 -08001077 } else {
1078 i++;
Marco Nelissen3a34bef2011-08-02 13:33:41 -07001079 }
1080 }
1081 if (removed) {
1082 purgeStaleEffects_l();
1083 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07001084}
1085
1086// audioConfigChanged_l() must be called with AudioFlinger::mLock held
Glenn Kastenb81cc8c2012-03-01 09:14:51 -08001087void AudioFlinger::audioConfigChanged_l(int event, audio_io_handle_t ioHandle, const void *param2)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001088{
1089 size_t size = mNotificationClients.size();
1090 for (size_t i = 0; i < size; i++) {
Glenn Kasten84afa3b2012-01-25 15:28:08 -08001091 mNotificationClients.valueAt(i)->audioFlingerClient()->ioConfigChanged(event, ioHandle,
1092 param2);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001093 }
1094}
1095
1096// removeClient_l() must be called with AudioFlinger::mLock held
1097void AudioFlinger::removeClient_l(pid_t pid)
1098{
Steve Block3856b092011-10-20 11:56:00 +01001099 ALOGV("removeClient_l() pid %d, tid %d, calling tid %d", pid, gettid(), IPCThreadState::self()->getCallingPid());
Mathias Agopian65ab4712010-07-14 17:59:35 -07001100 mClients.removeItem(pid);
1101}
1102
1103
1104// ----------------------------------------------------------------------------
1105
Glenn Kasten72ef00d2012-01-17 11:09:42 -08001106AudioFlinger::ThreadBase::ThreadBase(const sp<AudioFlinger>& audioFlinger, audio_io_handle_t id,
1107 uint32_t device, type_t type)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001108 : Thread(false),
Glenn Kasten23bb8be2012-01-26 10:38:26 -08001109 mType(type),
Glenn Kasten58912562012-04-03 10:45:00 -07001110 mAudioFlinger(audioFlinger), mSampleRate(0), mFrameCount(0), mNormalFrameCount(0),
Glenn Kasten84afa3b2012-01-25 15:28:08 -08001111 // mChannelMask
1112 mChannelCount(0),
1113 mFrameSize(1), mFormat(AUDIO_FORMAT_INVALID),
1114 mParamStatus(NO_ERROR),
Glenn Kastenb28686f2012-01-06 08:39:38 -08001115 mStandby(false), mId(id),
Glenn Kasten84afa3b2012-01-25 15:28:08 -08001116 mDevice(device),
1117 mDeathRecipient(new PMDeathRecipient(this))
Mathias Agopian65ab4712010-07-14 17:59:35 -07001118{
1119}
1120
1121AudioFlinger::ThreadBase::~ThreadBase()
1122{
1123 mParamCond.broadcast();
Eric Laurentfeb0db62011-07-22 09:04:31 -07001124 // do not lock the mutex in destructor
1125 releaseWakeLock_l();
Eric Laurent9d18ec52011-09-27 12:07:15 -07001126 if (mPowerManager != 0) {
1127 sp<IBinder> binder = mPowerManager->asBinder();
1128 binder->unlinkToDeath(mDeathRecipient);
1129 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07001130}
1131
1132void AudioFlinger::ThreadBase::exit()
1133{
Steve Block3856b092011-10-20 11:56:00 +01001134 ALOGV("ThreadBase::exit");
Mathias Agopian65ab4712010-07-14 17:59:35 -07001135 {
Glenn Kastenb28686f2012-01-06 08:39:38 -08001136 // This lock prevents the following race in thread (uniprocessor for illustration):
1137 // if (!exitPending()) {
1138 // // context switch from here to exit()
1139 // // exit() calls requestExit(), what exitPending() observes
1140 // // exit() calls signal(), which is dropped since no waiters
1141 // // context switch back from exit() to here
1142 // mWaitWorkCV.wait(...);
1143 // // now thread is hung
1144 // }
Glenn Kastena7d8d6f2012-01-05 15:41:56 -08001145 AutoMutex lock(mLock);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001146 requestExit();
1147 mWaitWorkCV.signal();
1148 }
Glenn Kastenb28686f2012-01-06 08:39:38 -08001149 // When Thread::requestExitAndWait is made virtual and this method is renamed to
1150 // "virtual status_t requestExitAndWait()", replace by "return Thread::requestExitAndWait();"
Mathias Agopian65ab4712010-07-14 17:59:35 -07001151 requestExitAndWait();
1152}
1153
Mathias Agopian65ab4712010-07-14 17:59:35 -07001154status_t AudioFlinger::ThreadBase::setParameters(const String8& keyValuePairs)
1155{
1156 status_t status;
1157
Steve Block3856b092011-10-20 11:56:00 +01001158 ALOGV("ThreadBase::setParameters() %s", keyValuePairs.string());
Mathias Agopian65ab4712010-07-14 17:59:35 -07001159 Mutex::Autolock _l(mLock);
1160
1161 mNewParameters.add(keyValuePairs);
1162 mWaitWorkCV.signal();
1163 // wait condition with timeout in case the thread loop has exited
1164 // before the request could be processed
Glenn Kasten7dede872011-12-13 11:04:14 -08001165 if (mParamCond.waitRelative(mLock, kSetParametersTimeoutNs) == NO_ERROR) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001166 status = mParamStatus;
1167 mWaitWorkCV.signal();
1168 } else {
1169 status = TIMED_OUT;
1170 }
1171 return status;
1172}
1173
1174void AudioFlinger::ThreadBase::sendConfigEvent(int event, int param)
1175{
1176 Mutex::Autolock _l(mLock);
1177 sendConfigEvent_l(event, param);
1178}
1179
1180// sendConfigEvent_l() must be called with ThreadBase::mLock held
1181void AudioFlinger::ThreadBase::sendConfigEvent_l(int event, int param)
1182{
Glenn Kastenf3990f22011-12-13 11:50:00 -08001183 ConfigEvent configEvent;
1184 configEvent.mEvent = event;
1185 configEvent.mParam = param;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001186 mConfigEvents.add(configEvent);
Steve Block3856b092011-10-20 11:56:00 +01001187 ALOGV("sendConfigEvent() num events %d event %d, param %d", mConfigEvents.size(), event, param);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001188 mWaitWorkCV.signal();
1189}
1190
1191void AudioFlinger::ThreadBase::processConfigEvents()
1192{
1193 mLock.lock();
Glenn Kastene53b9ea2012-03-12 16:29:55 -07001194 while (!mConfigEvents.isEmpty()) {
Steve Block3856b092011-10-20 11:56:00 +01001195 ALOGV("processConfigEvents() remaining events %d", mConfigEvents.size());
Glenn Kastenf3990f22011-12-13 11:50:00 -08001196 ConfigEvent configEvent = mConfigEvents[0];
Mathias Agopian65ab4712010-07-14 17:59:35 -07001197 mConfigEvents.removeAt(0);
1198 // release mLock before locking AudioFlinger mLock: lock order is always
1199 // AudioFlinger then ThreadBase to avoid cross deadlock
1200 mLock.unlock();
1201 mAudioFlinger->mLock.lock();
Glenn Kastenf3990f22011-12-13 11:50:00 -08001202 audioConfigChanged_l(configEvent.mEvent, configEvent.mParam);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001203 mAudioFlinger->mLock.unlock();
Mathias Agopian65ab4712010-07-14 17:59:35 -07001204 mLock.lock();
1205 }
1206 mLock.unlock();
1207}
1208
1209status_t AudioFlinger::ThreadBase::dumpBase(int fd, const Vector<String16>& args)
1210{
1211 const size_t SIZE = 256;
1212 char buffer[SIZE];
1213 String8 result;
1214
1215 bool locked = tryLock(mLock);
1216 if (!locked) {
1217 snprintf(buffer, SIZE, "thread %p maybe dead locked\n", this);
1218 write(fd, buffer, strlen(buffer));
1219 }
1220
Eric Laurent612bbb52012-03-14 15:03:26 -07001221 snprintf(buffer, SIZE, "io handle: %d\n", mId);
1222 result.append(buffer);
1223 snprintf(buffer, SIZE, "TID: %d\n", getTid());
1224 result.append(buffer);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001225 snprintf(buffer, SIZE, "standby: %d\n", mStandby);
1226 result.append(buffer);
1227 snprintf(buffer, SIZE, "Sample rate: %d\n", mSampleRate);
1228 result.append(buffer);
Glenn Kasten58912562012-04-03 10:45:00 -07001229 snprintf(buffer, SIZE, "HAL frame count: %d\n", mFrameCount);
1230 result.append(buffer);
1231 snprintf(buffer, SIZE, "Normal frame count: %d\n", mNormalFrameCount);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001232 result.append(buffer);
1233 snprintf(buffer, SIZE, "Channel Count: %d\n", mChannelCount);
1234 result.append(buffer);
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07001235 snprintf(buffer, SIZE, "Channel Mask: 0x%08x\n", mChannelMask);
1236 result.append(buffer);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001237 snprintf(buffer, SIZE, "Format: %d\n", mFormat);
1238 result.append(buffer);
Glenn Kastenb9980652012-01-11 09:48:27 -08001239 snprintf(buffer, SIZE, "Frame size: %u\n", mFrameSize);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001240 result.append(buffer);
1241
1242 snprintf(buffer, SIZE, "\nPending setParameters commands: \n");
1243 result.append(buffer);
1244 result.append(" Index Command");
1245 for (size_t i = 0; i < mNewParameters.size(); ++i) {
1246 snprintf(buffer, SIZE, "\n %02d ", i);
1247 result.append(buffer);
1248 result.append(mNewParameters[i]);
1249 }
1250
1251 snprintf(buffer, SIZE, "\n\nPending config events: \n");
1252 result.append(buffer);
1253 snprintf(buffer, SIZE, " Index event param\n");
1254 result.append(buffer);
1255 for (size_t i = 0; i < mConfigEvents.size(); i++) {
Glenn Kastenf3990f22011-12-13 11:50:00 -08001256 snprintf(buffer, SIZE, " %02d %02d %d\n", i, mConfigEvents[i].mEvent, mConfigEvents[i].mParam);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001257 result.append(buffer);
1258 }
1259 result.append("\n");
1260
1261 write(fd, result.string(), result.size());
1262
1263 if (locked) {
1264 mLock.unlock();
1265 }
1266 return NO_ERROR;
1267}
1268
Eric Laurent1d2bff02011-07-24 17:49:51 -07001269status_t AudioFlinger::ThreadBase::dumpEffectChains(int fd, const Vector<String16>& args)
1270{
1271 const size_t SIZE = 256;
1272 char buffer[SIZE];
1273 String8 result;
1274
1275 snprintf(buffer, SIZE, "\n- %d Effect Chains:\n", mEffectChains.size());
1276 write(fd, buffer, strlen(buffer));
1277
1278 for (size_t i = 0; i < mEffectChains.size(); ++i) {
1279 sp<EffectChain> chain = mEffectChains[i];
1280 if (chain != 0) {
1281 chain->dump(fd, args);
1282 }
1283 }
1284 return NO_ERROR;
1285}
1286
Eric Laurentfeb0db62011-07-22 09:04:31 -07001287void AudioFlinger::ThreadBase::acquireWakeLock()
1288{
1289 Mutex::Autolock _l(mLock);
1290 acquireWakeLock_l();
1291}
1292
1293void AudioFlinger::ThreadBase::acquireWakeLock_l()
1294{
1295 if (mPowerManager == 0) {
1296 // use checkService() to avoid blocking if power service is not up yet
1297 sp<IBinder> binder =
1298 defaultServiceManager()->checkService(String16("power"));
1299 if (binder == 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00001300 ALOGW("Thread %s cannot connect to the power manager service", mName);
Eric Laurentfeb0db62011-07-22 09:04:31 -07001301 } else {
1302 mPowerManager = interface_cast<IPowerManager>(binder);
1303 binder->linkToDeath(mDeathRecipient);
1304 }
1305 }
1306 if (mPowerManager != 0) {
1307 sp<IBinder> binder = new BBinder();
1308 status_t status = mPowerManager->acquireWakeLock(POWERMANAGER_PARTIAL_WAKE_LOCK,
1309 binder,
1310 String16(mName));
1311 if (status == NO_ERROR) {
1312 mWakeLockToken = binder;
1313 }
Steve Block3856b092011-10-20 11:56:00 +01001314 ALOGV("acquireWakeLock_l() %s status %d", mName, status);
Eric Laurentfeb0db62011-07-22 09:04:31 -07001315 }
1316}
1317
1318void AudioFlinger::ThreadBase::releaseWakeLock()
1319{
1320 Mutex::Autolock _l(mLock);
Eric Laurent6dbe8832011-07-28 13:59:02 -07001321 releaseWakeLock_l();
Eric Laurentfeb0db62011-07-22 09:04:31 -07001322}
1323
1324void AudioFlinger::ThreadBase::releaseWakeLock_l()
1325{
1326 if (mWakeLockToken != 0) {
Steve Block3856b092011-10-20 11:56:00 +01001327 ALOGV("releaseWakeLock_l() %s", mName);
Eric Laurentfeb0db62011-07-22 09:04:31 -07001328 if (mPowerManager != 0) {
1329 mPowerManager->releaseWakeLock(mWakeLockToken, 0);
1330 }
1331 mWakeLockToken.clear();
1332 }
1333}
1334
1335void AudioFlinger::ThreadBase::clearPowerManager()
1336{
1337 Mutex::Autolock _l(mLock);
1338 releaseWakeLock_l();
1339 mPowerManager.clear();
1340}
1341
1342void AudioFlinger::ThreadBase::PMDeathRecipient::binderDied(const wp<IBinder>& who)
1343{
1344 sp<ThreadBase> thread = mThread.promote();
1345 if (thread != 0) {
1346 thread->clearPowerManager();
1347 }
Steve Block5ff1dd52012-01-05 23:22:43 +00001348 ALOGW("power manager service died !!!");
Eric Laurentfeb0db62011-07-22 09:04:31 -07001349}
Eric Laurent1d2bff02011-07-24 17:49:51 -07001350
Eric Laurent59255e42011-07-27 19:49:51 -07001351void AudioFlinger::ThreadBase::setEffectSuspended(
1352 const effect_uuid_t *type, bool suspend, int sessionId)
1353{
1354 Mutex::Autolock _l(mLock);
1355 setEffectSuspended_l(type, suspend, sessionId);
1356}
1357
1358void AudioFlinger::ThreadBase::setEffectSuspended_l(
1359 const effect_uuid_t *type, bool suspend, int sessionId)
1360{
Glenn Kasten090f0192012-01-30 13:00:02 -08001361 sp<EffectChain> chain = getEffectChain_l(sessionId);
Eric Laurent59255e42011-07-27 19:49:51 -07001362 if (chain != 0) {
1363 if (type != NULL) {
1364 chain->setEffectSuspended_l(type, suspend);
1365 } else {
1366 chain->setEffectSuspendedAll_l(suspend);
1367 }
1368 }
1369
1370 updateSuspendedSessions_l(type, suspend, sessionId);
1371}
1372
1373void AudioFlinger::ThreadBase::checkSuspendOnAddEffectChain_l(const sp<EffectChain>& chain)
1374{
Glenn Kasten8d6a2442012-02-08 14:04:28 -08001375 ssize_t index = mSuspendedSessions.indexOfKey(chain->sessionId());
Eric Laurent59255e42011-07-27 19:49:51 -07001376 if (index < 0) {
1377 return;
1378 }
1379
1380 KeyedVector <int, sp<SuspendedSessionDesc> > sessionEffects =
1381 mSuspendedSessions.editValueAt(index);
1382
1383 for (size_t i = 0; i < sessionEffects.size(); i++) {
Glenn Kastene53b9ea2012-03-12 16:29:55 -07001384 sp<SuspendedSessionDesc> desc = sessionEffects.valueAt(i);
Eric Laurent59255e42011-07-27 19:49:51 -07001385 for (int j = 0; j < desc->mRefCount; j++) {
1386 if (sessionEffects.keyAt(i) == EffectChain::kKeyForSuspendAll) {
1387 chain->setEffectSuspendedAll_l(true);
1388 } else {
Steve Block3856b092011-10-20 11:56:00 +01001389 ALOGV("checkSuspendOnAddEffectChain_l() suspending effects %08x",
Glenn Kastene53b9ea2012-03-12 16:29:55 -07001390 desc->mType.timeLow);
Eric Laurent59255e42011-07-27 19:49:51 -07001391 chain->setEffectSuspended_l(&desc->mType, true);
1392 }
1393 }
1394 }
1395}
1396
Eric Laurent59255e42011-07-27 19:49:51 -07001397void AudioFlinger::ThreadBase::updateSuspendedSessions_l(const effect_uuid_t *type,
1398 bool suspend,
1399 int sessionId)
1400{
Glenn Kasten8d6a2442012-02-08 14:04:28 -08001401 ssize_t index = mSuspendedSessions.indexOfKey(sessionId);
Eric Laurent59255e42011-07-27 19:49:51 -07001402
1403 KeyedVector <int, sp<SuspendedSessionDesc> > sessionEffects;
1404
1405 if (suspend) {
1406 if (index >= 0) {
1407 sessionEffects = mSuspendedSessions.editValueAt(index);
1408 } else {
1409 mSuspendedSessions.add(sessionId, sessionEffects);
1410 }
1411 } else {
1412 if (index < 0) {
1413 return;
1414 }
1415 sessionEffects = mSuspendedSessions.editValueAt(index);
1416 }
1417
1418
1419 int key = EffectChain::kKeyForSuspendAll;
1420 if (type != NULL) {
1421 key = type->timeLow;
1422 }
1423 index = sessionEffects.indexOfKey(key);
1424
Glenn Kastene53b9ea2012-03-12 16:29:55 -07001425 sp<SuspendedSessionDesc> desc;
Eric Laurent59255e42011-07-27 19:49:51 -07001426 if (suspend) {
1427 if (index >= 0) {
1428 desc = sessionEffects.valueAt(index);
1429 } else {
1430 desc = new SuspendedSessionDesc();
1431 if (type != NULL) {
1432 memcpy(&desc->mType, type, sizeof(effect_uuid_t));
1433 }
1434 sessionEffects.add(key, desc);
Steve Block3856b092011-10-20 11:56:00 +01001435 ALOGV("updateSuspendedSessions_l() suspend adding effect %08x", key);
Eric Laurent59255e42011-07-27 19:49:51 -07001436 }
1437 desc->mRefCount++;
1438 } else {
1439 if (index < 0) {
1440 return;
1441 }
1442 desc = sessionEffects.valueAt(index);
1443 if (--desc->mRefCount == 0) {
Steve Block3856b092011-10-20 11:56:00 +01001444 ALOGV("updateSuspendedSessions_l() restore removing effect %08x", key);
Eric Laurent59255e42011-07-27 19:49:51 -07001445 sessionEffects.removeItemsAt(index);
1446 if (sessionEffects.isEmpty()) {
Steve Block3856b092011-10-20 11:56:00 +01001447 ALOGV("updateSuspendedSessions_l() restore removing session %d",
Eric Laurent59255e42011-07-27 19:49:51 -07001448 sessionId);
1449 mSuspendedSessions.removeItem(sessionId);
1450 }
1451 }
1452 }
1453 if (!sessionEffects.isEmpty()) {
1454 mSuspendedSessions.replaceValueFor(sessionId, sessionEffects);
1455 }
1456}
1457
1458void AudioFlinger::ThreadBase::checkSuspendOnEffectEnabled(const sp<EffectModule>& effect,
1459 bool enabled,
1460 int sessionId)
1461{
1462 Mutex::Autolock _l(mLock);
Eric Laurenta85a74a2011-10-19 11:44:54 -07001463 checkSuspendOnEffectEnabled_l(effect, enabled, sessionId);
1464}
Eric Laurent59255e42011-07-27 19:49:51 -07001465
Eric Laurenta85a74a2011-10-19 11:44:54 -07001466void AudioFlinger::ThreadBase::checkSuspendOnEffectEnabled_l(const sp<EffectModule>& effect,
1467 bool enabled,
1468 int sessionId)
1469{
Eric Laurentdb7c0792011-08-10 10:37:50 -07001470 if (mType != RECORD) {
1471 // suspend all effects in AUDIO_SESSION_OUTPUT_MIX when enabling any effect on
1472 // another session. This gives the priority to well behaved effect control panels
1473 // and applications not using global effects.
Eric Laurent808e7d12012-05-11 19:44:09 -07001474 // Enabling post processing in AUDIO_SESSION_OUTPUT_STAGE session does not affect
1475 // global effects
1476 if ((sessionId != AUDIO_SESSION_OUTPUT_MIX) && (sessionId != AUDIO_SESSION_OUTPUT_STAGE)) {
Eric Laurentdb7c0792011-08-10 10:37:50 -07001477 setEffectSuspended_l(NULL, enabled, AUDIO_SESSION_OUTPUT_MIX);
1478 }
1479 }
Eric Laurent59255e42011-07-27 19:49:51 -07001480
1481 sp<EffectChain> chain = getEffectChain_l(sessionId);
1482 if (chain != 0) {
1483 chain->checkSuspendOnEffectEnabled(effect, enabled);
1484 }
1485}
1486
Mathias Agopian65ab4712010-07-14 17:59:35 -07001487// ----------------------------------------------------------------------------
1488
Eric Laurent7c7f10b2011-06-17 21:29:58 -07001489AudioFlinger::PlaybackThread::PlaybackThread(const sp<AudioFlinger>& audioFlinger,
1490 AudioStreamOut* output,
Glenn Kasten72ef00d2012-01-17 11:09:42 -08001491 audio_io_handle_t id,
Glenn Kasten23bb8be2012-01-26 10:38:26 -08001492 uint32_t device,
1493 type_t type)
1494 : ThreadBase(audioFlinger, id, device, type),
Glenn Kasten84afa3b2012-01-25 15:28:08 -08001495 mMixBuffer(NULL), mSuspended(0), mBytesWritten(0),
1496 // Assumes constructor is called by AudioFlinger with it's mLock held,
1497 // but it would be safer to explicitly pass initial masterMute as parameter
1498 mMasterMute(audioFlinger->masterMute_l()),
1499 // mStreamTypes[] initialized in constructor body
1500 mOutput(output),
1501 // Assumes constructor is called by AudioFlinger with it's mLock held,
1502 // but it would be safer to explicitly pass initial masterVolume as parameter
John Grossman4ff14ba2012-02-08 16:37:41 -08001503 mMasterVolume(audioFlinger->masterVolumeSW_l()),
Glenn Kastenfec279f2012-03-08 07:47:15 -08001504 mLastWriteTime(0), mNumWrites(0), mNumDelayedWrites(0), mInWrite(false),
Glenn Kastenaa4397f2012-03-12 18:13:59 -07001505 mMixerStatus(MIXER_IDLE),
Glenn Kasten81028042012-04-30 18:15:12 -07001506 mMixerStatusIgnoringFastTracks(MIXER_IDLE),
Glenn Kasten58912562012-04-03 10:45:00 -07001507 standbyDelay(AudioFlinger::mStandbyTimeInNsecs),
Glenn Kasten288ed212012-04-25 17:52:27 -07001508 // index 0 is reserved for normal mixer's submix
1509 mFastTrackAvailMask(((1 << FastMixerState::kMaxFastTracks) - 1) & ~1)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001510{
Glenn Kasten480b4682012-02-28 12:30:08 -08001511 snprintf(mName, kNameLength, "AudioOut_%X", id);
Eric Laurentfeb0db62011-07-22 09:04:31 -07001512
Mathias Agopian65ab4712010-07-14 17:59:35 -07001513 readOutputParameters();
1514
Glenn Kasten263709e2012-01-06 08:40:01 -08001515 // mStreamTypes[AUDIO_STREAM_CNT] is initialized by stream_type_t default constructor
Glenn Kastenfff6d712012-01-12 16:38:12 -08001516 // There is no AUDIO_STREAM_MIN, and ++ operator does not compile
1517 for (audio_stream_type_t stream = (audio_stream_type_t) 0; stream < AUDIO_STREAM_CNT;
1518 stream = (audio_stream_type_t) (stream + 1)) {
Glenn Kasten6637baa2012-01-09 09:40:36 -08001519 mStreamTypes[stream].volume = mAudioFlinger->streamVolume_l(stream);
1520 mStreamTypes[stream].mute = mAudioFlinger->streamMute_l(stream);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001521 }
Glenn Kasten6637baa2012-01-09 09:40:36 -08001522 // mStreamTypes[AUDIO_STREAM_CNT] exists but isn't explicitly initialized here,
1523 // because mAudioFlinger doesn't have one to copy from
Mathias Agopian65ab4712010-07-14 17:59:35 -07001524}
1525
1526AudioFlinger::PlaybackThread::~PlaybackThread()
1527{
1528 delete [] mMixBuffer;
1529}
1530
1531status_t AudioFlinger::PlaybackThread::dump(int fd, const Vector<String16>& args)
1532{
1533 dumpInternals(fd, args);
1534 dumpTracks(fd, args);
1535 dumpEffectChains(fd, args);
1536 return NO_ERROR;
1537}
1538
1539status_t AudioFlinger::PlaybackThread::dumpTracks(int fd, const Vector<String16>& args)
1540{
1541 const size_t SIZE = 256;
1542 char buffer[SIZE];
1543 String8 result;
1544
Glenn Kasten58912562012-04-03 10:45:00 -07001545 result.appendFormat("Output thread %p stream volumes in dB:\n ", this);
1546 for (int i = 0; i < AUDIO_STREAM_CNT; ++i) {
1547 const stream_type_t *st = &mStreamTypes[i];
1548 if (i > 0) {
1549 result.appendFormat(", ");
1550 }
1551 result.appendFormat("%d:%.2g", i, 20.0 * log10(st->volume));
1552 if (st->mute) {
1553 result.append("M");
1554 }
1555 }
1556 result.append("\n");
1557 write(fd, result.string(), result.length());
1558 result.clear();
1559
Mathias Agopian65ab4712010-07-14 17:59:35 -07001560 snprintf(buffer, SIZE, "Output thread %p tracks\n", this);
1561 result.append(buffer);
Glenn Kasten288ed212012-04-25 17:52:27 -07001562 Track::appendDumpHeader(result);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001563 for (size_t i = 0; i < mTracks.size(); ++i) {
1564 sp<Track> track = mTracks[i];
1565 if (track != 0) {
1566 track->dump(buffer, SIZE);
1567 result.append(buffer);
1568 }
1569 }
1570
1571 snprintf(buffer, SIZE, "Output thread %p active tracks\n", this);
1572 result.append(buffer);
Glenn Kasten288ed212012-04-25 17:52:27 -07001573 Track::appendDumpHeader(result);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001574 for (size_t i = 0; i < mActiveTracks.size(); ++i) {
Glenn Kasten77c11192012-01-25 14:27:41 -08001575 sp<Track> track = mActiveTracks[i].promote();
1576 if (track != 0) {
1577 track->dump(buffer, SIZE);
1578 result.append(buffer);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001579 }
1580 }
1581 write(fd, result.string(), result.size());
1582 return NO_ERROR;
1583}
1584
Mathias Agopian65ab4712010-07-14 17:59:35 -07001585status_t AudioFlinger::PlaybackThread::dumpInternals(int fd, const Vector<String16>& args)
1586{
1587 const size_t SIZE = 256;
1588 char buffer[SIZE];
1589 String8 result;
1590
1591 snprintf(buffer, SIZE, "\nOutput thread %p internals\n", this);
1592 result.append(buffer);
1593 snprintf(buffer, SIZE, "last write occurred (msecs): %llu\n", ns2ms(systemTime() - mLastWriteTime));
1594 result.append(buffer);
1595 snprintf(buffer, SIZE, "total writes: %d\n", mNumWrites);
1596 result.append(buffer);
1597 snprintf(buffer, SIZE, "delayed writes: %d\n", mNumDelayedWrites);
1598 result.append(buffer);
1599 snprintf(buffer, SIZE, "blocked in write: %d\n", mInWrite);
1600 result.append(buffer);
1601 snprintf(buffer, SIZE, "suspend count: %d\n", mSuspended);
1602 result.append(buffer);
1603 snprintf(buffer, SIZE, "mix buffer : %p\n", mMixBuffer);
1604 result.append(buffer);
1605 write(fd, result.string(), result.size());
1606
1607 dumpBase(fd, args);
1608
1609 return NO_ERROR;
1610}
1611
1612// Thread virtuals
1613status_t AudioFlinger::PlaybackThread::readyToRun()
1614{
Eric Laurentb8ba0a92011-08-07 16:32:26 -07001615 status_t status = initCheck();
1616 if (status == NO_ERROR) {
Steve Blockdf64d152012-01-04 20:05:49 +00001617 ALOGI("AudioFlinger's thread %p ready to run", this);
Eric Laurentb8ba0a92011-08-07 16:32:26 -07001618 } else {
Steve Block29357bc2012-01-06 19:20:56 +00001619 ALOGE("No working audio driver found.");
Mathias Agopian65ab4712010-07-14 17:59:35 -07001620 }
Eric Laurentb8ba0a92011-08-07 16:32:26 -07001621 return status;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001622}
1623
1624void AudioFlinger::PlaybackThread::onFirstRef()
1625{
Eric Laurentfeb0db62011-07-22 09:04:31 -07001626 run(mName, ANDROID_PRIORITY_URGENT_AUDIO);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001627}
1628
1629// PlaybackThread::createTrack_l() must be called with AudioFlinger::mLock held
Glenn Kastenea7939a2012-03-14 12:56:26 -07001630sp<AudioFlinger::PlaybackThread::Track> AudioFlinger::PlaybackThread::createTrack_l(
Mathias Agopian65ab4712010-07-14 17:59:35 -07001631 const sp<AudioFlinger::Client>& client,
Glenn Kastenfff6d712012-01-12 16:38:12 -08001632 audio_stream_type_t streamType,
Mathias Agopian65ab4712010-07-14 17:59:35 -07001633 uint32_t sampleRate,
Glenn Kasten58f30212012-01-12 12:27:51 -08001634 audio_format_t format,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07001635 uint32_t channelMask,
Mathias Agopian65ab4712010-07-14 17:59:35 -07001636 int frameCount,
1637 const sp<IMemory>& sharedBuffer,
1638 int sessionId,
Glenn Kasten73d22752012-03-19 13:38:30 -07001639 IAudioFlinger::track_flags_t flags,
Glenn Kasten3acbd052012-02-28 10:39:56 -08001640 pid_t tid,
Mathias Agopian65ab4712010-07-14 17:59:35 -07001641 status_t *status)
1642{
1643 sp<Track> track;
1644 status_t lStatus;
1645
Glenn Kasten73d22752012-03-19 13:38:30 -07001646 bool isTimed = (flags & IAudioFlinger::TRACK_TIMED) != 0;
1647
1648 // client expresses a preference for FAST, but we get the final say
Glenn Kastene0fa4672012-04-24 14:35:14 -07001649 if (flags & IAudioFlinger::TRACK_FAST) {
1650 if (
Glenn Kasten73d22752012-03-19 13:38:30 -07001651 // not timed
1652 (!isTimed) &&
1653 // either of these use cases:
1654 (
1655 // use case 1: shared buffer with any frame count
1656 (
1657 (sharedBuffer != 0)
1658 ) ||
Glenn Kastene0fa4672012-04-24 14:35:14 -07001659 // use case 2: callback handler and frame count is default or at least as large as HAL
Glenn Kasten73d22752012-03-19 13:38:30 -07001660 (
Glenn Kasten3acbd052012-02-28 10:39:56 -08001661 (tid != -1) &&
Glenn Kastene0fa4672012-04-24 14:35:14 -07001662 ((frameCount == 0) ||
Glenn Kasten300a2ee2012-04-25 13:47:36 -07001663 (frameCount >= (int) (mFrameCount * 2))) // * 2 is due to SRC jitter, see below
Glenn Kasten73d22752012-03-19 13:38:30 -07001664 )
1665 ) &&
1666 // PCM data
1667 audio_is_linear_pcm(format) &&
1668 // mono or stereo
1669 ( (channelMask == AUDIO_CHANNEL_OUT_MONO) ||
1670 (channelMask == AUDIO_CHANNEL_OUT_STEREO) ) &&
Glenn Kasten58912562012-04-03 10:45:00 -07001671#ifndef FAST_TRACKS_AT_NON_NATIVE_SAMPLE_RATE
Glenn Kasten73d22752012-03-19 13:38:30 -07001672 // hardware sample rate
Glenn Kasten58912562012-04-03 10:45:00 -07001673 (sampleRate == mSampleRate) &&
1674#endif
1675 // normal mixer has an associated fast mixer
1676 hasFastMixer() &&
1677 // there are sufficient fast track slots available
1678 (mFastTrackAvailMask != 0)
Glenn Kasten73d22752012-03-19 13:38:30 -07001679 // FIXME test that MixerThread for this fast track has a capable output HAL
1680 // FIXME add a permission test also?
Glenn Kastene0fa4672012-04-24 14:35:14 -07001681 ) {
Glenn Kastene0fa4672012-04-24 14:35:14 -07001682 // if frameCount not specified, then it defaults to fast mixer (HAL) frame count
1683 if (frameCount == 0) {
Glenn Kasten300a2ee2012-04-25 13:47:36 -07001684 frameCount = mFrameCount * 2; // FIXME * 2 is due to SRC jitter, should be computed
Glenn Kastene0fa4672012-04-24 14:35:14 -07001685 }
Glenn Kasten31dfd1d2012-05-01 11:07:08 -07001686 ALOGV("AUDIO_OUTPUT_FLAG_FAST accepted: frameCount=%d mFrameCount=%d",
Glenn Kasten300a2ee2012-04-25 13:47:36 -07001687 frameCount, mFrameCount);
Glenn Kastene0fa4672012-04-24 14:35:14 -07001688 } else {
1689 ALOGW("AUDIO_OUTPUT_FLAG_FAST denied: isTimed=%d sharedBuffer=%p frameCount=%d "
Glenn Kasten58912562012-04-03 10:45:00 -07001690 "mFrameCount=%d format=%d isLinear=%d channelMask=%d sampleRate=%d mSampleRate=%d "
1691 "hasFastMixer=%d tid=%d fastTrackAvailMask=%#x",
1692 isTimed, sharedBuffer.get(), frameCount, mFrameCount, format,
1693 audio_is_linear_pcm(format),
1694 channelMask, sampleRate, mSampleRate, hasFastMixer(), tid, mFastTrackAvailMask);
Glenn Kasten73d22752012-03-19 13:38:30 -07001695 flags &= ~IAudioFlinger::TRACK_FAST;
Glenn Kastene0fa4672012-04-24 14:35:14 -07001696 // For compatibility with AudioTrack calculation, buffer depth is forced
1697 // to be at least 2 x the normal mixer frame count and cover audio hardware latency.
1698 // This is probably too conservative, but legacy application code may depend on it.
1699 // If you change this calculation, also review the start threshold which is related.
1700 uint32_t latencyMs = mOutput->stream->get_latency(mOutput->stream);
1701 uint32_t minBufCount = latencyMs / ((1000 * mNormalFrameCount) / mSampleRate);
1702 if (minBufCount < 2) {
1703 minBufCount = 2;
Glenn Kasten58912562012-04-03 10:45:00 -07001704 }
Glenn Kastene0fa4672012-04-24 14:35:14 -07001705 int minFrameCount = mNormalFrameCount * minBufCount;
1706 if (frameCount < minFrameCount) {
1707 frameCount = minFrameCount;
1708 }
1709 }
Glenn Kasten73d22752012-03-19 13:38:30 -07001710 }
1711
Mathias Agopian65ab4712010-07-14 17:59:35 -07001712 if (mType == DIRECT) {
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07001713 if ((format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM) {
1714 if (sampleRate != mSampleRate || format != mFormat || channelMask != mChannelMask) {
Steve Block29357bc2012-01-06 19:20:56 +00001715 ALOGE("createTrack_l() Bad parameter: sampleRate %d format %d, channelMask 0x%08x \""
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07001716 "for output %p with format %d",
1717 sampleRate, format, channelMask, mOutput, mFormat);
1718 lStatus = BAD_VALUE;
1719 goto Exit;
1720 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07001721 }
1722 } else {
1723 // Resampler implementation limits input sampling rate to 2 x output sampling rate.
1724 if (sampleRate > mSampleRate*2) {
Steve Block29357bc2012-01-06 19:20:56 +00001725 ALOGE("Sample rate out of range: %d mSampleRate %d", sampleRate, mSampleRate);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001726 lStatus = BAD_VALUE;
1727 goto Exit;
1728 }
1729 }
1730
Eric Laurent7c7f10b2011-06-17 21:29:58 -07001731 lStatus = initCheck();
1732 if (lStatus != NO_ERROR) {
Steve Block29357bc2012-01-06 19:20:56 +00001733 ALOGE("Audio driver not initialized.");
Mathias Agopian65ab4712010-07-14 17:59:35 -07001734 goto Exit;
1735 }
1736
1737 { // scope for mLock
1738 Mutex::Autolock _l(mLock);
Eric Laurentde070132010-07-13 04:45:46 -07001739
1740 // all tracks in same audio session must share the same routing strategy otherwise
1741 // conflicts will happen when tracks are moved from one output to another by audio policy
1742 // manager
Glenn Kasten02bbd202012-02-08 12:35:35 -08001743 uint32_t strategy = AudioSystem::getStrategyForStream(streamType);
Eric Laurentde070132010-07-13 04:45:46 -07001744 for (size_t i = 0; i < mTracks.size(); ++i) {
1745 sp<Track> t = mTracks[i];
Glenn Kasten639dbee2012-03-07 12:26:34 -08001746 if (t != 0 && !t->isOutputTrack()) {
Glenn Kasten02bbd202012-02-08 12:35:35 -08001747 uint32_t actual = AudioSystem::getStrategyForStream(t->streamType());
Glenn Kastend8796012011-10-28 10:31:42 -07001748 if (sessionId == t->sessionId() && strategy != actual) {
Steve Block29357bc2012-01-06 19:20:56 +00001749 ALOGE("createTrack_l() mismatched strategy; expected %u but found %u",
Glenn Kastend8796012011-10-28 10:31:42 -07001750 strategy, actual);
Eric Laurentde070132010-07-13 04:45:46 -07001751 lStatus = BAD_VALUE;
1752 goto Exit;
1753 }
1754 }
1755 }
1756
John Grossman4ff14ba2012-02-08 16:37:41 -08001757 if (!isTimed) {
1758 track = new Track(this, client, streamType, sampleRate, format,
Glenn Kasten73d22752012-03-19 13:38:30 -07001759 channelMask, frameCount, sharedBuffer, sessionId, flags);
John Grossman4ff14ba2012-02-08 16:37:41 -08001760 } else {
1761 track = TimedTrack::create(this, client, streamType, sampleRate, format,
1762 channelMask, frameCount, sharedBuffer, sessionId);
1763 }
1764 if (track == NULL || track->getCblk() == NULL || track->name() < 0) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001765 lStatus = NO_MEMORY;
1766 goto Exit;
1767 }
1768 mTracks.add(track);
1769
1770 sp<EffectChain> chain = getEffectChain_l(sessionId);
1771 if (chain != 0) {
Steve Block3856b092011-10-20 11:56:00 +01001772 ALOGV("createTrack_l() setting main buffer %p", chain->inBuffer());
Mathias Agopian65ab4712010-07-14 17:59:35 -07001773 track->setMainBuffer(chain->inBuffer());
Glenn Kasten02bbd202012-02-08 12:35:35 -08001774 chain->setStrategy(AudioSystem::getStrategyForStream(track->streamType()));
Eric Laurentb469b942011-05-09 12:09:06 -07001775 chain->incTrackCnt();
Mathias Agopian65ab4712010-07-14 17:59:35 -07001776 }
1777 }
Glenn Kasten3acbd052012-02-28 10:39:56 -08001778
1779#ifdef HAVE_REQUEST_PRIORITY
1780 if ((flags & IAudioFlinger::TRACK_FAST) && (tid != -1)) {
1781 pid_t callingPid = IPCThreadState::self()->getCallingPid();
1782 // we don't have CAP_SYS_NICE, nor do we want to have it as it's too powerful,
1783 // so ask activity manager to do this on our behalf
1784 int err = requestPriority(callingPid, tid, 1);
1785 if (err != 0) {
1786 ALOGW("Policy SCHED_FIFO priority %d is unavailable for pid %d tid %d; error %d",
1787 1, callingPid, tid, err);
1788 }
1789 }
1790#endif
1791
Mathias Agopian65ab4712010-07-14 17:59:35 -07001792 lStatus = NO_ERROR;
1793
1794Exit:
Glenn Kastene53b9ea2012-03-12 16:29:55 -07001795 if (status) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001796 *status = lStatus;
1797 }
1798 return track;
1799}
1800
1801uint32_t AudioFlinger::PlaybackThread::latency() const
1802{
Eric Laurentb8ba0a92011-08-07 16:32:26 -07001803 Mutex::Autolock _l(mLock);
1804 if (initCheck() == NO_ERROR) {
Dima Zavin799a70e2011-04-18 16:57:27 -07001805 return mOutput->stream->get_latency(mOutput->stream);
Eric Laurentb8ba0a92011-08-07 16:32:26 -07001806 } else {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001807 return 0;
1808 }
1809}
1810
Glenn Kasten6637baa2012-01-09 09:40:36 -08001811void AudioFlinger::PlaybackThread::setMasterVolume(float value)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001812{
Glenn Kasten6637baa2012-01-09 09:40:36 -08001813 Mutex::Autolock _l(mLock);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001814 mMasterVolume = value;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001815}
1816
Glenn Kasten6637baa2012-01-09 09:40:36 -08001817void AudioFlinger::PlaybackThread::setMasterMute(bool muted)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001818{
Glenn Kasten6637baa2012-01-09 09:40:36 -08001819 Mutex::Autolock _l(mLock);
1820 setMasterMute_l(muted);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001821}
1822
Glenn Kasten6637baa2012-01-09 09:40:36 -08001823void AudioFlinger::PlaybackThread::setStreamVolume(audio_stream_type_t stream, float value)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001824{
Glenn Kasten6637baa2012-01-09 09:40:36 -08001825 Mutex::Autolock _l(mLock);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001826 mStreamTypes[stream].volume = value;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001827}
1828
Glenn Kasten6637baa2012-01-09 09:40:36 -08001829void AudioFlinger::PlaybackThread::setStreamMute(audio_stream_type_t stream, bool muted)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001830{
Glenn Kasten6637baa2012-01-09 09:40:36 -08001831 Mutex::Autolock _l(mLock);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001832 mStreamTypes[stream].mute = muted;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001833}
1834
Glenn Kastenfff6d712012-01-12 16:38:12 -08001835float AudioFlinger::PlaybackThread::streamVolume(audio_stream_type_t stream) const
Mathias Agopian65ab4712010-07-14 17:59:35 -07001836{
Glenn Kasten6637baa2012-01-09 09:40:36 -08001837 Mutex::Autolock _l(mLock);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001838 return mStreamTypes[stream].volume;
1839}
1840
Mathias Agopian65ab4712010-07-14 17:59:35 -07001841// addTrack_l() must be called with ThreadBase::mLock held
1842status_t AudioFlinger::PlaybackThread::addTrack_l(const sp<Track>& track)
1843{
1844 status_t status = ALREADY_EXISTS;
1845
1846 // set retry count for buffer fill
1847 track->mRetryCount = kMaxTrackStartupRetries;
1848 if (mActiveTracks.indexOf(track) < 0) {
1849 // the track is newly added, make sure it fills up all its
1850 // buffers before playing. This is to ensure the client will
1851 // effectively get the latency it requested.
1852 track->mFillingUpStatus = Track::FS_FILLING;
1853 track->mResetDone = false;
Eric Laurent29864602012-05-08 18:57:51 -07001854 track->mPresentationCompleteFrames = 0;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001855 mActiveTracks.add(track);
1856 if (track->mainBuffer() != mMixBuffer) {
1857 sp<EffectChain> chain = getEffectChain_l(track->sessionId());
1858 if (chain != 0) {
Steve Block3856b092011-10-20 11:56:00 +01001859 ALOGV("addTrack_l() starting track on chain %p for session %d", chain.get(), track->sessionId());
Eric Laurentb469b942011-05-09 12:09:06 -07001860 chain->incActiveTrackCnt();
Mathias Agopian65ab4712010-07-14 17:59:35 -07001861 }
1862 }
1863
1864 status = NO_ERROR;
1865 }
1866
Steve Block3856b092011-10-20 11:56:00 +01001867 ALOGV("mWaitWorkCV.broadcast");
Mathias Agopian65ab4712010-07-14 17:59:35 -07001868 mWaitWorkCV.broadcast();
1869
1870 return status;
1871}
1872
1873// destroyTrack_l() must be called with ThreadBase::mLock held
1874void AudioFlinger::PlaybackThread::destroyTrack_l(const sp<Track>& track)
1875{
1876 track->mState = TrackBase::TERMINATED;
Glenn Kasten288ed212012-04-25 17:52:27 -07001877 // active tracks are removed by threadLoop()
Mathias Agopian65ab4712010-07-14 17:59:35 -07001878 if (mActiveTracks.indexOf(track) < 0) {
Eric Laurentb469b942011-05-09 12:09:06 -07001879 removeTrack_l(track);
1880 }
1881}
1882
1883void AudioFlinger::PlaybackThread::removeTrack_l(const sp<Track>& track)
1884{
Eric Laurent29864602012-05-08 18:57:51 -07001885 track->triggerEvents(AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE);
Eric Laurentb469b942011-05-09 12:09:06 -07001886 mTracks.remove(track);
1887 deleteTrackName_l(track->name());
Glenn Kasten288ed212012-04-25 17:52:27 -07001888 // redundant as track is about to be destroyed, for dumpsys only
1889 track->mName = -1;
1890 if (track->isFastTrack()) {
1891 int index = track->mFastIndex;
Eric Laurent29864602012-05-08 18:57:51 -07001892 ALOG_ASSERT(0 < index && index < (int)FastMixerState::kMaxFastTracks);
Glenn Kasten288ed212012-04-25 17:52:27 -07001893 ALOG_ASSERT(!(mFastTrackAvailMask & (1 << index)));
1894 mFastTrackAvailMask |= 1 << index;
1895 // redundant as track is about to be destroyed, for dumpsys only
1896 track->mFastIndex = -1;
1897 }
Eric Laurentb469b942011-05-09 12:09:06 -07001898 sp<EffectChain> chain = getEffectChain_l(track->sessionId());
1899 if (chain != 0) {
1900 chain->decTrackCnt();
Mathias Agopian65ab4712010-07-14 17:59:35 -07001901 }
1902}
1903
1904String8 AudioFlinger::PlaybackThread::getParameters(const String8& keys)
1905{
Eric Laurentb8ba0a92011-08-07 16:32:26 -07001906 String8 out_s8 = String8("");
Dima Zavinfce7a472011-04-19 22:30:36 -07001907 char *s;
1908
Eric Laurentb8ba0a92011-08-07 16:32:26 -07001909 Mutex::Autolock _l(mLock);
1910 if (initCheck() != NO_ERROR) {
1911 return out_s8;
1912 }
1913
Dima Zavin799a70e2011-04-18 16:57:27 -07001914 s = mOutput->stream->common.get_parameters(&mOutput->stream->common, keys.string());
Dima Zavinfce7a472011-04-19 22:30:36 -07001915 out_s8 = String8(s);
1916 free(s);
1917 return out_s8;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001918}
1919
Eric Laurentb8ba0a92011-08-07 16:32:26 -07001920// audioConfigChanged_l() must be called with AudioFlinger::mLock held
Mathias Agopian65ab4712010-07-14 17:59:35 -07001921void AudioFlinger::PlaybackThread::audioConfigChanged_l(int event, int param) {
1922 AudioSystem::OutputDescriptor desc;
Glenn Kastena0d68332012-01-27 16:47:15 -08001923 void *param2 = NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001924
Steve Block3856b092011-10-20 11:56:00 +01001925 ALOGV("PlaybackThread::audioConfigChanged_l, thread %p, event %d, param %d", this, event, param);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001926
1927 switch (event) {
1928 case AudioSystem::OUTPUT_OPENED:
1929 case AudioSystem::OUTPUT_CONFIG_CHANGED:
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07001930 desc.channels = mChannelMask;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001931 desc.samplingRate = mSampleRate;
1932 desc.format = mFormat;
Glenn Kasten58912562012-04-03 10:45:00 -07001933 desc.frameCount = mNormalFrameCount; // FIXME see AudioFlinger::frameCount(audio_io_handle_t)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001934 desc.latency = latency();
1935 param2 = &desc;
1936 break;
1937
1938 case AudioSystem::STREAM_CONFIG_CHANGED:
1939 param2 = &param;
1940 case AudioSystem::OUTPUT_CLOSED:
1941 default:
1942 break;
1943 }
1944 mAudioFlinger->audioConfigChanged_l(event, mId, param2);
1945}
1946
1947void AudioFlinger::PlaybackThread::readOutputParameters()
1948{
Dima Zavin799a70e2011-04-18 16:57:27 -07001949 mSampleRate = mOutput->stream->common.get_sample_rate(&mOutput->stream->common);
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07001950 mChannelMask = mOutput->stream->common.get_channels(&mOutput->stream->common);
1951 mChannelCount = (uint16_t)popcount(mChannelMask);
Dima Zavin799a70e2011-04-18 16:57:27 -07001952 mFormat = mOutput->stream->common.get_format(&mOutput->stream->common);
Glenn Kastenb9980652012-01-11 09:48:27 -08001953 mFrameSize = audio_stream_frame_size(&mOutput->stream->common);
Dima Zavin799a70e2011-04-18 16:57:27 -07001954 mFrameCount = mOutput->stream->common.get_buffer_size(&mOutput->stream->common) / mFrameSize;
Glenn Kasten58912562012-04-03 10:45:00 -07001955 if (mFrameCount & 15) {
1956 ALOGW("HAL output buffer size is %u frames but AudioMixer requires multiples of 16 frames",
1957 mFrameCount);
1958 }
1959
Glenn Kasten300a2ee2012-04-25 13:47:36 -07001960 // Calculate size of normal mix buffer relative to the HAL output buffer size
Glenn Kasten4adcede2012-05-14 12:26:02 -07001961 double multiplier = 1.0;
Glenn Kasten300a2ee2012-04-25 13:47:36 -07001962 if (mType == MIXER && (kUseFastMixer == FastMixer_Static || kUseFastMixer == FastMixer_Dynamic)) {
Glenn Kasten58912562012-04-03 10:45:00 -07001963 size_t minNormalFrameCount = (kMinNormalMixBufferSizeMs * mSampleRate) / 1000;
Glenn Kasten4adcede2012-05-14 12:26:02 -07001964 size_t maxNormalFrameCount = (kMaxNormalMixBufferSizeMs * mSampleRate) / 1000;
1965 // round up minimum and round down maximum to nearest 16 frames to satisfy AudioMixer
1966 minNormalFrameCount = (minNormalFrameCount + 15) & ~15;
1967 maxNormalFrameCount = maxNormalFrameCount & ~15;
1968 if (maxNormalFrameCount < minNormalFrameCount) {
1969 maxNormalFrameCount = minNormalFrameCount;
1970 }
1971 multiplier = (double) minNormalFrameCount / (double) mFrameCount;
1972 if (multiplier <= 1.0) {
1973 multiplier = 1.0;
1974 } else if (multiplier <= 2.0) {
1975 if (2 * mFrameCount <= maxNormalFrameCount) {
1976 multiplier = 2.0;
1977 } else {
1978 multiplier = (double) maxNormalFrameCount / (double) mFrameCount;
1979 }
1980 } else {
1981 // prefer an even multiplier, for compatibility with doubling of fast tracks due to HAL SRC
1982 // (it would be unusual for the normal mix buffer size to not be a multiple of fast
1983 // track, but we sometimes have to do this to satisfy the maximum frame count constraint)
1984 // FIXME this rounding up should not be done if no HAL SRC
1985 uint32_t truncMult = (uint32_t) multiplier;
1986 if ((truncMult & 1)) {
1987 if ((truncMult + 1) * mFrameCount <= maxNormalFrameCount) {
1988 ++truncMult;
1989 }
1990 }
1991 multiplier = (double) truncMult;
Glenn Kasten58912562012-04-03 10:45:00 -07001992 }
Glenn Kasten58912562012-04-03 10:45:00 -07001993 }
Glenn Kasten4adcede2012-05-14 12:26:02 -07001994 mNormalFrameCount = multiplier * mFrameCount;
1995 // round up to nearest 16 frames to satisfy AudioMixer
1996 mNormalFrameCount = (mNormalFrameCount + 15) & ~15;
Glenn Kasten58912562012-04-03 10:45:00 -07001997 ALOGI("HAL output buffer size %u frames, normal mix buffer size %u frames", mFrameCount, mNormalFrameCount);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001998
1999 // FIXME - Current mixer implementation only supports stereo output: Always
2000 // Allocate a stereo buffer even if HW output is mono.
Glenn Kastene9dd0172012-01-27 18:08:45 -08002001 delete[] mMixBuffer;
Glenn Kasten58912562012-04-03 10:45:00 -07002002 mMixBuffer = new int16_t[mNormalFrameCount * 2];
2003 memset(mMixBuffer, 0, mNormalFrameCount * 2 * sizeof(int16_t));
Mathias Agopian65ab4712010-07-14 17:59:35 -07002004
Eric Laurentde070132010-07-13 04:45:46 -07002005 // force reconfiguration of effect chains and engines to take new buffer size and audio
2006 // parameters into account
2007 // Note that mLock is not held when readOutputParameters() is called from the constructor
2008 // but in this case nothing is done below as no audio sessions have effect yet so it doesn't
2009 // matter.
2010 // create a copy of mEffectChains as calling moveEffectChain_l() can reorder some effect chains
2011 Vector< sp<EffectChain> > effectChains = mEffectChains;
2012 for (size_t i = 0; i < effectChains.size(); i ++) {
Eric Laurent39e94f82010-07-28 01:32:47 -07002013 mAudioFlinger->moveEffectChain_l(effectChains[i]->sessionId(), this, this, false);
Eric Laurentde070132010-07-13 04:45:46 -07002014 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07002015}
2016
2017status_t AudioFlinger::PlaybackThread::getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames)
2018{
Glenn Kastena0d68332012-01-27 16:47:15 -08002019 if (halFrames == NULL || dspFrames == NULL) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07002020 return BAD_VALUE;
2021 }
Eric Laurentb8ba0a92011-08-07 16:32:26 -07002022 Mutex::Autolock _l(mLock);
Eric Laurent7c7f10b2011-06-17 21:29:58 -07002023 if (initCheck() != NO_ERROR) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07002024 return INVALID_OPERATION;
2025 }
Dima Zavin799a70e2011-04-18 16:57:27 -07002026 *halFrames = mBytesWritten / audio_stream_frame_size(&mOutput->stream->common);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002027
Dima Zavin799a70e2011-04-18 16:57:27 -07002028 return mOutput->stream->get_render_position(mOutput->stream, dspFrames);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002029}
2030
Eric Laurent39e94f82010-07-28 01:32:47 -07002031uint32_t AudioFlinger::PlaybackThread::hasAudioSession(int sessionId)
Mathias Agopian65ab4712010-07-14 17:59:35 -07002032{
2033 Mutex::Autolock _l(mLock);
Eric Laurent39e94f82010-07-28 01:32:47 -07002034 uint32_t result = 0;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002035 if (getEffectChain_l(sessionId) != 0) {
Eric Laurent39e94f82010-07-28 01:32:47 -07002036 result = EFFECT_SESSION;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002037 }
2038
2039 for (size_t i = 0; i < mTracks.size(); ++i) {
2040 sp<Track> track = mTracks[i];
Eric Laurentde070132010-07-13 04:45:46 -07002041 if (sessionId == track->sessionId() &&
2042 !(track->mCblk->flags & CBLK_INVALID_MSK)) {
Eric Laurent39e94f82010-07-28 01:32:47 -07002043 result |= TRACK_SESSION;
2044 break;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002045 }
2046 }
2047
Eric Laurent39e94f82010-07-28 01:32:47 -07002048 return result;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002049}
2050
Eric Laurentde070132010-07-13 04:45:46 -07002051uint32_t AudioFlinger::PlaybackThread::getStrategyForSession_l(int sessionId)
2052{
Dima Zavinfce7a472011-04-19 22:30:36 -07002053 // session AUDIO_SESSION_OUTPUT_MIX is placed in same strategy as MUSIC stream so that
Eric Laurentde070132010-07-13 04:45:46 -07002054 // it is moved to correct output by audio policy manager when A2DP is connected or disconnected
Dima Zavinfce7a472011-04-19 22:30:36 -07002055 if (sessionId == AUDIO_SESSION_OUTPUT_MIX) {
2056 return AudioSystem::getStrategyForStream(AUDIO_STREAM_MUSIC);
Eric Laurentde070132010-07-13 04:45:46 -07002057 }
2058 for (size_t i = 0; i < mTracks.size(); i++) {
2059 sp<Track> track = mTracks[i];
2060 if (sessionId == track->sessionId() &&
2061 !(track->mCblk->flags & CBLK_INVALID_MSK)) {
Glenn Kasten02bbd202012-02-08 12:35:35 -08002062 return AudioSystem::getStrategyForStream(track->streamType());
Eric Laurentde070132010-07-13 04:45:46 -07002063 }
2064 }
Dima Zavinfce7a472011-04-19 22:30:36 -07002065 return AudioSystem::getStrategyForStream(AUDIO_STREAM_MUSIC);
Eric Laurentde070132010-07-13 04:45:46 -07002066}
2067
Mathias Agopian65ab4712010-07-14 17:59:35 -07002068
Glenn Kastenaed850d2012-01-26 09:46:34 -08002069AudioFlinger::AudioStreamOut* AudioFlinger::PlaybackThread::getOutput() const
Eric Laurentb8ba0a92011-08-07 16:32:26 -07002070{
2071 Mutex::Autolock _l(mLock);
2072 return mOutput;
2073}
2074
2075AudioFlinger::AudioStreamOut* AudioFlinger::PlaybackThread::clearOutput()
2076{
2077 Mutex::Autolock _l(mLock);
2078 AudioStreamOut *output = mOutput;
2079 mOutput = NULL;
Glenn Kasten58912562012-04-03 10:45:00 -07002080 // FIXME FastMixer might also have a raw ptr to mOutputSink;
2081 // must push a NULL and wait for ack
2082 mOutputSink.clear();
2083 mPipeSink.clear();
2084 mNormalSink.clear();
Eric Laurentb8ba0a92011-08-07 16:32:26 -07002085 return output;
2086}
2087
2088// this method must always be called either with ThreadBase mLock held or inside the thread loop
Glenn Kasten0bf65bd2012-02-28 18:32:53 -08002089audio_stream_t* AudioFlinger::PlaybackThread::stream() const
Eric Laurentb8ba0a92011-08-07 16:32:26 -07002090{
2091 if (mOutput == NULL) {
2092 return NULL;
2093 }
2094 return &mOutput->stream->common;
2095}
2096
Glenn Kasten0bf65bd2012-02-28 18:32:53 -08002097uint32_t AudioFlinger::PlaybackThread::activeSleepTimeUs() const
Eric Laurent162b40b2011-12-05 09:47:19 -08002098{
2099 // A2DP output latency is not due only to buffering capacity. It also reflects encoding,
2100 // decoding and transfer time. So sleeping for half of the latency would likely cause
2101 // underruns
2102 if (audio_is_a2dp_device((audio_devices_t)mDevice)) {
Glenn Kasten58912562012-04-03 10:45:00 -07002103 return (uint32_t)((uint32_t)((mNormalFrameCount * 1000) / mSampleRate) * 1000);
Eric Laurent162b40b2011-12-05 09:47:19 -08002104 } else {
2105 return (uint32_t)(mOutput->stream->get_latency(mOutput->stream) * 1000) / 2;
2106 }
2107}
2108
Eric Laurenta011e352012-03-29 15:51:43 -07002109status_t AudioFlinger::PlaybackThread::setSyncEvent(const sp<SyncEvent>& event)
2110{
2111 if (!isValidSyncEvent(event)) {
2112 return BAD_VALUE;
2113 }
2114
2115 Mutex::Autolock _l(mLock);
2116
2117 for (size_t i = 0; i < mTracks.size(); ++i) {
2118 sp<Track> track = mTracks[i];
2119 if (event->triggerSession() == track->sessionId()) {
2120 track->setSyncEvent(event);
2121 return NO_ERROR;
2122 }
2123 }
2124
2125 return NAME_NOT_FOUND;
2126}
2127
2128bool AudioFlinger::PlaybackThread::isValidSyncEvent(const sp<SyncEvent>& event)
2129{
2130 switch (event->type()) {
2131 case AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE:
2132 return true;
2133 default:
2134 break;
2135 }
2136 return false;
2137}
2138
Eric Laurent44a957f2012-05-15 15:26:05 -07002139void AudioFlinger::PlaybackThread::threadLoop_removeTracks(const Vector< sp<Track> >& tracksToRemove)
2140{
2141 size_t count = tracksToRemove.size();
2142 if (CC_UNLIKELY(count)) {
2143 for (size_t i = 0 ; i < count ; i++) {
2144 const sp<Track>& track = tracksToRemove.itemAt(i);
2145 if ((track->sharedBuffer() != 0) &&
2146 (track->mState == TrackBase::ACTIVE || track->mState == TrackBase::RESUMING)) {
2147 AudioSystem::stopOutput(mId, track->streamType(), track->sessionId());
2148 }
2149 }
2150 }
2151
2152}
2153
Mathias Agopian65ab4712010-07-14 17:59:35 -07002154// ----------------------------------------------------------------------------
2155
Glenn Kasten23bb8be2012-01-26 10:38:26 -08002156AudioFlinger::MixerThread::MixerThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output,
Glenn Kasten72ef00d2012-01-17 11:09:42 -08002157 audio_io_handle_t id, uint32_t device, type_t type)
Glenn Kasten58912562012-04-03 10:45:00 -07002158 : PlaybackThread(audioFlinger, output, id, device, type),
2159 // mAudioMixer below
2160#ifdef SOAKER
2161 mSoaker(NULL),
2162#endif
2163 // mFastMixer below
2164 mFastMixerFutex(0)
2165 // mOutputSink below
2166 // mPipeSink below
2167 // mNormalSink below
Mathias Agopian65ab4712010-07-14 17:59:35 -07002168{
Glenn Kasten58912562012-04-03 10:45:00 -07002169 ALOGV("MixerThread() id=%d device=%d type=%d", id, device, type);
2170 ALOGV("mSampleRate=%d, mChannelMask=%d, mChannelCount=%d, mFormat=%d, mFrameSize=%d, "
2171 "mFrameCount=%d, mNormalFrameCount=%d",
2172 mSampleRate, mChannelMask, mChannelCount, mFormat, mFrameSize, mFrameCount,
2173 mNormalFrameCount);
2174 mAudioMixer = new AudioMixer(mNormalFrameCount, mSampleRate);
2175
Mathias Agopian65ab4712010-07-14 17:59:35 -07002176 // FIXME - Current mixer implementation only supports stereo output
2177 if (mChannelCount == 1) {
Steve Block29357bc2012-01-06 19:20:56 +00002178 ALOGE("Invalid audio hardware channel count");
Mathias Agopian65ab4712010-07-14 17:59:35 -07002179 }
Glenn Kasten58912562012-04-03 10:45:00 -07002180
2181 // create an NBAIO sink for the HAL output stream, and negotiate
2182 mOutputSink = new AudioStreamOutSink(output->stream);
2183 size_t numCounterOffers = 0;
2184 const NBAIO_Format offers[1] = {Format_from_SR_C(mSampleRate, mChannelCount)};
2185 ssize_t index = mOutputSink->negotiate(offers, 1, NULL, numCounterOffers);
2186 ALOG_ASSERT(index == 0);
2187
Glenn Kasten300a2ee2012-04-25 13:47:36 -07002188 // initialize fast mixer depending on configuration
2189 bool initFastMixer;
2190 switch (kUseFastMixer) {
2191 case FastMixer_Never:
2192 initFastMixer = false;
2193 break;
2194 case FastMixer_Always:
2195 initFastMixer = true;
2196 break;
2197 case FastMixer_Static:
2198 case FastMixer_Dynamic:
2199 initFastMixer = mFrameCount < mNormalFrameCount;
2200 break;
2201 }
2202 if (initFastMixer) {
Glenn Kasten58912562012-04-03 10:45:00 -07002203
2204 // create a MonoPipe to connect our submix to FastMixer
2205 NBAIO_Format format = mOutputSink->format();
2206 // frame count will be rounded up to a power of 2, so this formula should work well
2207 MonoPipe *monoPipe = new MonoPipe((mNormalFrameCount * 3) / 2, format,
2208 true /*writeCanBlock*/);
2209 const NBAIO_Format offers[1] = {format};
2210 size_t numCounterOffers = 0;
2211 ssize_t index = monoPipe->negotiate(offers, 1, NULL, numCounterOffers);
2212 ALOG_ASSERT(index == 0);
2213 mPipeSink = monoPipe;
2214
2215#ifdef SOAKER
2216 // create a soaker as workaround for governor issues
2217 mSoaker = new Soaker();
2218 // FIXME Soaker should only run when needed, i.e. when FastMixer is not in COLD_IDLE
2219 mSoaker->run("Soaker", PRIORITY_LOWEST);
2220#endif
2221
2222 // create fast mixer and configure it initially with just one fast track for our submix
2223 mFastMixer = new FastMixer();
2224 FastMixerStateQueue *sq = mFastMixer->sq();
2225 FastMixerState *state = sq->begin();
2226 FastTrack *fastTrack = &state->mFastTracks[0];
2227 // wrap the source side of the MonoPipe to make it an AudioBufferProvider
2228 fastTrack->mBufferProvider = new SourceAudioBufferProvider(new MonoPipeReader(monoPipe));
2229 fastTrack->mVolumeProvider = NULL;
2230 fastTrack->mGeneration++;
2231 state->mFastTracksGen++;
2232 state->mTrackMask = 1;
2233 // fast mixer will use the HAL output sink
2234 state->mOutputSink = mOutputSink.get();
2235 state->mOutputSinkGen++;
2236 state->mFrameCount = mFrameCount;
2237 state->mCommand = FastMixerState::COLD_IDLE;
2238 // already done in constructor initialization list
2239 //mFastMixerFutex = 0;
2240 state->mColdFutexAddr = &mFastMixerFutex;
2241 state->mColdGen++;
2242 state->mDumpState = &mFastMixerDumpState;
2243 sq->end();
2244 sq->push(FastMixerStateQueue::BLOCK_UNTIL_PUSHED);
2245
2246 // start the fast mixer
2247 mFastMixer->run("FastMixer", PRIORITY_URGENT_AUDIO);
2248#ifdef HAVE_REQUEST_PRIORITY
2249 pid_t tid = mFastMixer->getTid();
2250 int err = requestPriority(getpid_cached, tid, 2);
2251 if (err != 0) {
2252 ALOGW("Policy SCHED_FIFO priority %d is unavailable for pid %d tid %d; error %d",
2253 2, getpid_cached, tid, err);
2254 }
2255#endif
2256
2257 } else {
2258 mFastMixer = NULL;
2259 }
Glenn Kasten300a2ee2012-04-25 13:47:36 -07002260
2261 switch (kUseFastMixer) {
2262 case FastMixer_Never:
2263 case FastMixer_Dynamic:
2264 mNormalSink = mOutputSink;
2265 break;
2266 case FastMixer_Always:
2267 mNormalSink = mPipeSink;
2268 break;
2269 case FastMixer_Static:
2270 mNormalSink = initFastMixer ? mPipeSink : mOutputSink;
2271 break;
2272 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07002273}
2274
2275AudioFlinger::MixerThread::~MixerThread()
2276{
Glenn Kasten58912562012-04-03 10:45:00 -07002277 if (mFastMixer != NULL) {
2278 FastMixerStateQueue *sq = mFastMixer->sq();
2279 FastMixerState *state = sq->begin();
2280 if (state->mCommand == FastMixerState::COLD_IDLE) {
2281 int32_t old = android_atomic_inc(&mFastMixerFutex);
2282 if (old == -1) {
2283 __futex_syscall3(&mFastMixerFutex, FUTEX_WAKE_PRIVATE, 1);
2284 }
2285 }
2286 state->mCommand = FastMixerState::EXIT;
2287 sq->end();
2288 sq->push(FastMixerStateQueue::BLOCK_UNTIL_PUSHED);
2289 mFastMixer->join();
2290 // Though the fast mixer thread has exited, it's state queue is still valid.
2291 // We'll use that extract the final state which contains one remaining fast track
2292 // corresponding to our sub-mix.
2293 state = sq->begin();
2294 ALOG_ASSERT(state->mTrackMask == 1);
2295 FastTrack *fastTrack = &state->mFastTracks[0];
2296 ALOG_ASSERT(fastTrack->mBufferProvider != NULL);
2297 delete fastTrack->mBufferProvider;
2298 sq->end(false /*didModify*/);
2299 delete mFastMixer;
2300#ifdef SOAKER
2301 if (mSoaker != NULL) {
2302 mSoaker->requestExitAndWait();
2303 }
2304 delete mSoaker;
2305#endif
2306 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07002307 delete mAudioMixer;
2308}
2309
Glenn Kasten83efdd02012-02-24 07:21:32 -08002310class CpuStats {
2311public:
Glenn Kasten190a46f2012-03-06 11:27:10 -08002312 CpuStats();
2313 void sample(const String8 &title);
Glenn Kasten83efdd02012-02-24 07:21:32 -08002314#ifdef DEBUG_CPU_USAGE
2315private:
Glenn Kasten190a46f2012-03-06 11:27:10 -08002316 ThreadCpuUsage mCpuUsage; // instantaneous thread CPU usage in wall clock ns
2317 CentralTendencyStatistics mWcStats; // statistics on thread CPU usage in wall clock ns
2318
2319 CentralTendencyStatistics mHzStats; // statistics on thread CPU usage in cycles
2320
2321 int mCpuNum; // thread's current CPU number
2322 int mCpukHz; // frequency of thread's current CPU in kHz
Glenn Kasten83efdd02012-02-24 07:21:32 -08002323#endif
2324};
2325
Glenn Kasten190a46f2012-03-06 11:27:10 -08002326CpuStats::CpuStats()
Glenn Kasten83efdd02012-02-24 07:21:32 -08002327#ifdef DEBUG_CPU_USAGE
Glenn Kasten190a46f2012-03-06 11:27:10 -08002328 : mCpuNum(-1), mCpukHz(-1)
2329#endif
2330{
2331}
2332
2333void CpuStats::sample(const String8 &title) {
2334#ifdef DEBUG_CPU_USAGE
2335 // get current thread's delta CPU time in wall clock ns
2336 double wcNs;
2337 bool valid = mCpuUsage.sampleAndEnable(wcNs);
2338
2339 // record sample for wall clock statistics
2340 if (valid) {
2341 mWcStats.sample(wcNs);
2342 }
2343
2344 // get the current CPU number
2345 int cpuNum = sched_getcpu();
2346
2347 // get the current CPU frequency in kHz
2348 int cpukHz = mCpuUsage.getCpukHz(cpuNum);
2349
2350 // check if either CPU number or frequency changed
2351 if (cpuNum != mCpuNum || cpukHz != mCpukHz) {
2352 mCpuNum = cpuNum;
2353 mCpukHz = cpukHz;
2354 // ignore sample for purposes of cycles
2355 valid = false;
2356 }
2357
2358 // if no change in CPU number or frequency, then record sample for cycle statistics
2359 if (valid && mCpukHz > 0) {
2360 double cycles = wcNs * cpukHz * 0.000001;
2361 mHzStats.sample(cycles);
2362 }
2363
2364 unsigned n = mWcStats.n();
2365 // mCpuUsage.elapsed() is expensive, so don't call it every loop
Glenn Kasten83efdd02012-02-24 07:21:32 -08002366 if ((n & 127) == 1) {
Glenn Kasten190a46f2012-03-06 11:27:10 -08002367 long long elapsed = mCpuUsage.elapsed();
Glenn Kasten83efdd02012-02-24 07:21:32 -08002368 if (elapsed >= DEBUG_CPU_USAGE * 1000000000LL) {
2369 double perLoop = elapsed / (double) n;
2370 double perLoop100 = perLoop * 0.01;
Glenn Kasten190a46f2012-03-06 11:27:10 -08002371 double perLoop1k = perLoop * 0.001;
2372 double mean = mWcStats.mean();
2373 double stddev = mWcStats.stddev();
2374 double minimum = mWcStats.minimum();
2375 double maximum = mWcStats.maximum();
2376 double meanCycles = mHzStats.mean();
2377 double stddevCycles = mHzStats.stddev();
2378 double minCycles = mHzStats.minimum();
2379 double maxCycles = mHzStats.maximum();
2380 mCpuUsage.resetElapsed();
2381 mWcStats.reset();
2382 mHzStats.reset();
2383 ALOGD("CPU usage for %s over past %.1f secs\n"
2384 " (%u mixer loops at %.1f mean ms per loop):\n"
2385 " us per mix loop: mean=%.0f stddev=%.0f min=%.0f max=%.0f\n"
2386 " %% of wall: mean=%.1f stddev=%.1f min=%.1f max=%.1f\n"
2387 " MHz: mean=%.1f, stddev=%.1f, min=%.1f max=%.1f",
2388 title.string(),
Glenn Kasten83efdd02012-02-24 07:21:32 -08002389 elapsed * .000000001, n, perLoop * .000001,
2390 mean * .001,
2391 stddev * .001,
2392 minimum * .001,
2393 maximum * .001,
2394 mean / perLoop100,
2395 stddev / perLoop100,
2396 minimum / perLoop100,
Glenn Kasten190a46f2012-03-06 11:27:10 -08002397 maximum / perLoop100,
2398 meanCycles / perLoop1k,
2399 stddevCycles / perLoop1k,
2400 minCycles / perLoop1k,
2401 maxCycles / perLoop1k);
2402
Glenn Kasten83efdd02012-02-24 07:21:32 -08002403 }
2404 }
2405#endif
2406};
2407
Glenn Kasten37d825e2012-02-24 07:21:48 -08002408void AudioFlinger::PlaybackThread::checkSilentMode_l()
2409{
2410 if (!mMasterMute) {
2411 char value[PROPERTY_VALUE_MAX];
2412 if (property_get("ro.audio.silent", value, "0") > 0) {
2413 char *endptr;
2414 unsigned long ul = strtoul(value, &endptr, 0);
2415 if (*endptr == '\0' && ul != 0) {
2416 ALOGD("Silence is golden");
2417 // The setprop command will not allow a property to be changed after
2418 // the first time it is set, so we don't have to worry about un-muting.
2419 setMasterMute_l(true);
2420 }
2421 }
2422 }
2423}
2424
Glenn Kasten000f0e32012-03-01 17:10:56 -08002425bool AudioFlinger::PlaybackThread::threadLoop()
Mathias Agopian65ab4712010-07-14 17:59:35 -07002426{
2427 Vector< sp<Track> > tracksToRemove;
Glenn Kasten688a6402012-02-29 07:57:06 -08002428
Glenn Kasten000f0e32012-03-01 17:10:56 -08002429 standbyTime = systemTime();
Glenn Kasten000f0e32012-03-01 17:10:56 -08002430
2431 // MIXER
Mathias Agopian65ab4712010-07-14 17:59:35 -07002432 nsecs_t lastWarning = 0;
Glenn Kasten000f0e32012-03-01 17:10:56 -08002433if (mType == MIXER) {
2434 longStandbyExit = false;
2435}
Glenn Kasten688a6402012-02-29 07:57:06 -08002436
Glenn Kasten000f0e32012-03-01 17:10:56 -08002437 // DUPLICATING
2438 // FIXME could this be made local to while loop?
2439 writeFrames = 0;
Glenn Kasten688a6402012-02-29 07:57:06 -08002440
Glenn Kasten66fcab92012-02-24 14:59:21 -08002441 cacheParameters_l();
Glenn Kasten000f0e32012-03-01 17:10:56 -08002442 sleepTime = idleSleepTime;
2443
2444if (mType == MIXER) {
2445 sleepTimeShift = 0;
2446}
2447
Glenn Kasten83efdd02012-02-24 07:21:32 -08002448 CpuStats cpuStats;
Glenn Kasten190a46f2012-03-06 11:27:10 -08002449 const String8 myName(String8::format("thread %p type %d TID %d", this, mType, gettid()));
Mathias Agopian65ab4712010-07-14 17:59:35 -07002450
Eric Laurentfeb0db62011-07-22 09:04:31 -07002451 acquireWakeLock();
2452
Mathias Agopian65ab4712010-07-14 17:59:35 -07002453 while (!exitPending())
2454 {
Glenn Kasten190a46f2012-03-06 11:27:10 -08002455 cpuStats.sample(myName);
Glenn Kasten688a6402012-02-29 07:57:06 -08002456
Glenn Kasten73ca0f52012-02-29 07:56:15 -08002457 Vector< sp<EffectChain> > effectChains;
2458
Mathias Agopian65ab4712010-07-14 17:59:35 -07002459 processConfigEvents();
2460
Mathias Agopian65ab4712010-07-14 17:59:35 -07002461 { // scope for mLock
2462
2463 Mutex::Autolock _l(mLock);
2464
2465 if (checkForNewParameters_l()) {
Glenn Kasten66fcab92012-02-24 14:59:21 -08002466 cacheParameters_l();
Mathias Agopian65ab4712010-07-14 17:59:35 -07002467 }
2468
Glenn Kastenfa26a852012-03-06 11:28:04 -08002469 saveOutputTracks();
Glenn Kasten000f0e32012-03-01 17:10:56 -08002470
Mathias Agopian65ab4712010-07-14 17:59:35 -07002471 // put audio hardware into standby after short delay
Glenn Kasten3e074702012-02-28 18:40:35 -08002472 if (CC_UNLIKELY((!mActiveTracks.size() && systemTime() > standbyTime) ||
Glenn Kastenc455fe92012-02-29 07:07:30 -08002473 mSuspended > 0)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07002474 if (!mStandby) {
Glenn Kasten000f0e32012-03-01 17:10:56 -08002475
2476 threadLoop_standby();
2477
Mathias Agopian65ab4712010-07-14 17:59:35 -07002478 mStandby = true;
2479 mBytesWritten = 0;
2480 }
2481
Glenn Kasten3e074702012-02-28 18:40:35 -08002482 if (!mActiveTracks.size() && mConfigEvents.isEmpty()) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07002483 // we're about to wait, flush the binder command buffer
2484 IPCThreadState::self()->flushCommands();
2485
Glenn Kastenfa26a852012-03-06 11:28:04 -08002486 clearOutputTracks();
Glenn Kasten000f0e32012-03-01 17:10:56 -08002487
Mathias Agopian65ab4712010-07-14 17:59:35 -07002488 if (exitPending()) break;
2489
Eric Laurentfeb0db62011-07-22 09:04:31 -07002490 releaseWakeLock_l();
Mathias Agopian65ab4712010-07-14 17:59:35 -07002491 // wait until we have something to do...
Glenn Kasten190a46f2012-03-06 11:27:10 -08002492 ALOGV("%s going to sleep", myName.string());
Mathias Agopian65ab4712010-07-14 17:59:35 -07002493 mWaitWorkCV.wait(mLock);
Glenn Kasten190a46f2012-03-06 11:27:10 -08002494 ALOGV("%s waking up", myName.string());
Eric Laurentfeb0db62011-07-22 09:04:31 -07002495 acquireWakeLock_l();
Mathias Agopian65ab4712010-07-14 17:59:35 -07002496
Eric Laurentda747442012-04-25 18:53:13 -07002497 mMixerStatus = MIXER_IDLE;
Glenn Kasten81028042012-04-30 18:15:12 -07002498 mMixerStatusIgnoringFastTracks = MIXER_IDLE;
Glenn Kasten000f0e32012-03-01 17:10:56 -08002499
Glenn Kasten37d825e2012-02-24 07:21:48 -08002500 checkSilentMode_l();
Mathias Agopian65ab4712010-07-14 17:59:35 -07002501
Glenn Kasten000f0e32012-03-01 17:10:56 -08002502 standbyTime = systemTime() + standbyDelay;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002503 sleepTime = idleSleepTime;
Glenn Kasten66fcab92012-02-24 14:59:21 -08002504 if (mType == MIXER) {
2505 sleepTimeShift = 0;
2506 }
Glenn Kasten000f0e32012-03-01 17:10:56 -08002507
Mathias Agopian65ab4712010-07-14 17:59:35 -07002508 continue;
2509 }
2510 }
2511
Glenn Kasten81028042012-04-30 18:15:12 -07002512 // mMixerStatusIgnoringFastTracks is also updated internally
Eric Laurentda747442012-04-25 18:53:13 -07002513 mMixerStatus = prepareTracks_l(&tracksToRemove);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002514
2515 // prevent any changes in effect chain list and in each effect chain
2516 // during mixing and effect process as the audio buffers could be deleted
2517 // or modified if an effect is created or deleted
Eric Laurentde070132010-07-13 04:45:46 -07002518 lockEffectChains_l(effectChains);
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -08002519 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07002520
Glenn Kastenfec279f2012-03-08 07:47:15 -08002521 if (CC_LIKELY(mMixerStatus == MIXER_TRACKS_READY)) {
Glenn Kasten000f0e32012-03-01 17:10:56 -08002522 threadLoop_mix();
2523 } else {
2524 threadLoop_sleepTime();
2525 }
2526
2527 if (mSuspended > 0) {
2528 sleepTime = suspendSleepTimeUs();
2529 }
2530
2531 // only process effects if we're going to write
2532 if (sleepTime == 0) {
Glenn Kasten000f0e32012-03-01 17:10:56 -08002533 for (size_t i = 0; i < effectChains.size(); i ++) {
2534 effectChains[i]->process_l();
2535 }
2536 }
2537
2538 // enable changes in effect chain
2539 unlockEffectChains(effectChains);
2540
2541 // sleepTime == 0 means we must write to audio hardware
2542 if (sleepTime == 0) {
2543
2544 threadLoop_write();
2545
2546if (mType == MIXER) {
2547 // write blocked detection
2548 nsecs_t now = systemTime();
2549 nsecs_t delta = now - mLastWriteTime;
2550 if (!mStandby && delta > maxPeriod) {
2551 mNumDelayedWrites++;
2552 if ((now - lastWarning) > kWarningThrottleNs) {
Glenn Kastend8e6fd32012-05-07 11:07:57 -07002553 ScopedTrace st(ATRACE_TAG, "underrun");
Glenn Kasten000f0e32012-03-01 17:10:56 -08002554 ALOGW("write blocked for %llu msecs, %d delayed writes, thread %p",
2555 ns2ms(delta), mNumDelayedWrites, this);
2556 lastWarning = now;
2557 }
2558 // FIXME this is broken: longStandbyExit should be handled out of the if() and with
2559 // a different threshold. Or completely removed for what it is worth anyway...
2560 if (mStandby) {
2561 longStandbyExit = true;
2562 }
2563 }
2564}
2565
2566 mStandby = false;
2567 } else {
2568 usleep(sleepTime);
2569 }
2570
Glenn Kasten58912562012-04-03 10:45:00 -07002571 // Finally let go of removed track(s), without the lock held
Glenn Kasten000f0e32012-03-01 17:10:56 -08002572 // since we can't guarantee the destructors won't acquire that
Glenn Kasten58912562012-04-03 10:45:00 -07002573 // same lock. This will also mutate and push a new fast mixer state.
2574 threadLoop_removeTracks(tracksToRemove);
Glenn Kasten1465f0c2012-03-06 11:23:32 -08002575 tracksToRemove.clear();
Glenn Kasten000f0e32012-03-01 17:10:56 -08002576
Glenn Kastenfa26a852012-03-06 11:28:04 -08002577 // FIXME I don't understand the need for this here;
2578 // it was in the original code but maybe the
2579 // assignment in saveOutputTracks() makes this unnecessary?
2580 clearOutputTracks();
Glenn Kasten000f0e32012-03-01 17:10:56 -08002581
2582 // Effect chains will be actually deleted here if they were removed from
2583 // mEffectChains list during mixing or effects processing
2584 effectChains.clear();
2585
2586 // FIXME Note that the above .clear() is no longer necessary since effectChains
2587 // is now local to this block, but will keep it for now (at least until merge done).
2588 }
2589
2590if (mType == MIXER || mType == DIRECT) {
2591 // put output stream into standby mode
2592 if (!mStandby) {
2593 mOutput->stream->common.standby(&mOutput->stream->common);
2594 }
2595}
2596if (mType == DUPLICATING) {
2597 // for DuplicatingThread, standby mode is handled by the outputTracks
2598}
2599
2600 releaseWakeLock();
2601
2602 ALOGV("Thread %p type %d exiting", this, mType);
2603 return false;
2604}
2605
Glenn Kasten58912562012-04-03 10:45:00 -07002606void AudioFlinger::MixerThread::threadLoop_removeTracks(const Vector< sp<Track> >& tracksToRemove)
2607{
Glenn Kasten58912562012-04-03 10:45:00 -07002608 PlaybackThread::threadLoop_removeTracks(tracksToRemove);
2609}
2610
2611void AudioFlinger::MixerThread::threadLoop_write()
2612{
2613 // FIXME we should only do one push per cycle; confirm this is true
2614 // Start the fast mixer if it's not already running
2615 if (mFastMixer != NULL) {
2616 FastMixerStateQueue *sq = mFastMixer->sq();
2617 FastMixerState *state = sq->begin();
Glenn Kasten300a2ee2012-04-25 13:47:36 -07002618 if (state->mCommand != FastMixerState::MIX_WRITE &&
2619 (kUseFastMixer != FastMixer_Dynamic || state->mTrackMask > 1)) {
Glenn Kasten58912562012-04-03 10:45:00 -07002620 if (state->mCommand == FastMixerState::COLD_IDLE) {
2621 int32_t old = android_atomic_inc(&mFastMixerFutex);
2622 if (old == -1) {
2623 __futex_syscall3(&mFastMixerFutex, FUTEX_WAKE_PRIVATE, 1);
2624 }
2625 }
2626 state->mCommand = FastMixerState::MIX_WRITE;
2627 sq->end();
2628 sq->push(FastMixerStateQueue::BLOCK_UNTIL_PUSHED);
Glenn Kasten300a2ee2012-04-25 13:47:36 -07002629 if (kUseFastMixer == FastMixer_Dynamic) {
2630 mNormalSink = mPipeSink;
2631 }
Glenn Kasten58912562012-04-03 10:45:00 -07002632 } else {
2633 sq->end(false /*didModify*/);
2634 }
2635 }
2636 PlaybackThread::threadLoop_write();
2637}
2638
Glenn Kasten000f0e32012-03-01 17:10:56 -08002639// shared by MIXER and DIRECT, overridden by DUPLICATING
2640void AudioFlinger::PlaybackThread::threadLoop_write()
2641{
Glenn Kasten952eeb22012-03-06 11:30:57 -08002642 // FIXME rewrite to reduce number of system calls
2643 mLastWriteTime = systemTime();
2644 mInWrite = true;
Glenn Kasten58912562012-04-03 10:45:00 -07002645
Glenn Kasten58912562012-04-03 10:45:00 -07002646#define mBitShift 2 // FIXME
Glenn Kasten300a2ee2012-04-25 13:47:36 -07002647 size_t count = mixBufferSize >> mBitShift;
Glenn Kastend8e6fd32012-05-07 11:07:57 -07002648 Tracer::traceBegin(ATRACE_TAG, "write");
Glenn Kasten300a2ee2012-04-25 13:47:36 -07002649 ssize_t framesWritten = mNormalSink->write(mMixBuffer, count);
Glenn Kastend8e6fd32012-05-07 11:07:57 -07002650 Tracer::traceEnd(ATRACE_TAG);
Glenn Kasten300a2ee2012-04-25 13:47:36 -07002651 if (framesWritten > 0) {
2652 size_t bytesWritten = framesWritten << mBitShift;
2653 mBytesWritten += bytesWritten;
Glenn Kasten58912562012-04-03 10:45:00 -07002654 }
2655
Glenn Kasten952eeb22012-03-06 11:30:57 -08002656 mNumWrites++;
2657 mInWrite = false;
Glenn Kasten000f0e32012-03-01 17:10:56 -08002658}
2659
Glenn Kasten58912562012-04-03 10:45:00 -07002660void AudioFlinger::MixerThread::threadLoop_standby()
2661{
2662 // Idle the fast mixer if it's currently running
2663 if (mFastMixer != NULL) {
2664 FastMixerStateQueue *sq = mFastMixer->sq();
2665 FastMixerState *state = sq->begin();
2666 if (!(state->mCommand & FastMixerState::IDLE)) {
2667 state->mCommand = FastMixerState::COLD_IDLE;
2668 state->mColdFutexAddr = &mFastMixerFutex;
2669 state->mColdGen++;
2670 mFastMixerFutex = 0;
2671 sq->end();
2672 // BLOCK_UNTIL_PUSHED would be insufficient, as we need it to stop doing I/O now
2673 sq->push(FastMixerStateQueue::BLOCK_UNTIL_ACKED);
Glenn Kasten300a2ee2012-04-25 13:47:36 -07002674 if (kUseFastMixer == FastMixer_Dynamic) {
2675 mNormalSink = mOutputSink;
2676 }
Glenn Kasten58912562012-04-03 10:45:00 -07002677 } else {
2678 sq->end(false /*didModify*/);
2679 }
2680 }
2681 PlaybackThread::threadLoop_standby();
2682}
2683
Glenn Kasten000f0e32012-03-01 17:10:56 -08002684// shared by MIXER and DIRECT, overridden by DUPLICATING
2685void AudioFlinger::PlaybackThread::threadLoop_standby()
2686{
Glenn Kasten952eeb22012-03-06 11:30:57 -08002687 ALOGV("Audio hardware entering standby, mixer %p, suspend count %u", this, mSuspended);
2688 mOutput->stream->common.standby(&mOutput->stream->common);
Glenn Kasten000f0e32012-03-01 17:10:56 -08002689}
2690
2691void AudioFlinger::MixerThread::threadLoop_mix()
2692{
Glenn Kasten952eeb22012-03-06 11:30:57 -08002693 // obtain the presentation timestamp of the next output buffer
2694 int64_t pts;
2695 status_t status = INVALID_OPERATION;
John Grossman4ff14ba2012-02-08 16:37:41 -08002696
Glenn Kasten952eeb22012-03-06 11:30:57 -08002697 if (NULL != mOutput->stream->get_next_write_timestamp) {
2698 status = mOutput->stream->get_next_write_timestamp(
2699 mOutput->stream, &pts);
2700 }
John Grossman4ff14ba2012-02-08 16:37:41 -08002701
Glenn Kasten952eeb22012-03-06 11:30:57 -08002702 if (status != NO_ERROR) {
2703 pts = AudioBufferProvider::kInvalidPTS;
2704 }
John Grossman4ff14ba2012-02-08 16:37:41 -08002705
Glenn Kasten952eeb22012-03-06 11:30:57 -08002706 // mix buffers...
2707 mAudioMixer->process(pts);
2708 // increase sleep time progressively when application underrun condition clears.
2709 // Only increase sleep time if the mixer is ready for two consecutive times to avoid
2710 // that a steady state of alternating ready/not ready conditions keeps the sleep time
2711 // such that we would underrun the audio HAL.
2712 if ((sleepTime == 0) && (sleepTimeShift > 0)) {
2713 sleepTimeShift--;
2714 }
2715 sleepTime = 0;
Glenn Kasten66fcab92012-02-24 14:59:21 -08002716 standbyTime = systemTime() + standbyDelay;
Glenn Kasten952eeb22012-03-06 11:30:57 -08002717 //TODO: delay standby when effects have a tail
Glenn Kasten000f0e32012-03-01 17:10:56 -08002718}
2719
2720void AudioFlinger::MixerThread::threadLoop_sleepTime()
2721{
Glenn Kasten952eeb22012-03-06 11:30:57 -08002722 // If no tracks are ready, sleep once for the duration of an output
2723 // buffer size, then write 0s to the output
2724 if (sleepTime == 0) {
Glenn Kastenfec279f2012-03-08 07:47:15 -08002725 if (mMixerStatus == MIXER_TRACKS_ENABLED) {
Glenn Kasten952eeb22012-03-06 11:30:57 -08002726 sleepTime = activeSleepTime >> sleepTimeShift;
2727 if (sleepTime < kMinThreadSleepTimeUs) {
2728 sleepTime = kMinThreadSleepTimeUs;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002729 }
Glenn Kasten952eeb22012-03-06 11:30:57 -08002730 // reduce sleep time in case of consecutive application underruns to avoid
2731 // starving the audio HAL. As activeSleepTimeUs() is larger than a buffer
2732 // duration we would end up writing less data than needed by the audio HAL if
2733 // the condition persists.
2734 if (sleepTimeShift < kMaxThreadSleepTimeShift) {
2735 sleepTimeShift++;
2736 }
2737 } else {
2738 sleepTime = idleSleepTime;
2739 }
2740 } else if (mBytesWritten != 0 ||
Glenn Kastenfec279f2012-03-08 07:47:15 -08002741 (mMixerStatus == MIXER_TRACKS_ENABLED && longStandbyExit)) {
Glenn Kasten952eeb22012-03-06 11:30:57 -08002742 memset (mMixBuffer, 0, mixBufferSize);
2743 sleepTime = 0;
Glenn Kastenfec279f2012-03-08 07:47:15 -08002744 ALOGV_IF((mBytesWritten == 0 && (mMixerStatus == MIXER_TRACKS_ENABLED && longStandbyExit)), "anticipated start");
Glenn Kasten952eeb22012-03-06 11:30:57 -08002745 }
2746 // TODO add standby time extension fct of effect tail
Mathias Agopian65ab4712010-07-14 17:59:35 -07002747}
2748
2749// prepareTracks_l() must be called with ThreadBase::mLock held
Glenn Kasten29c23c32012-01-26 13:37:52 -08002750AudioFlinger::PlaybackThread::mixer_state AudioFlinger::MixerThread::prepareTracks_l(
Glenn Kasten3e074702012-02-28 18:40:35 -08002751 Vector< sp<Track> > *tracksToRemove)
Mathias Agopian65ab4712010-07-14 17:59:35 -07002752{
2753
Glenn Kasten29c23c32012-01-26 13:37:52 -08002754 mixer_state mixerStatus = MIXER_IDLE;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002755 // find out which tracks need to be processed
Glenn Kasten3e074702012-02-28 18:40:35 -08002756 size_t count = mActiveTracks.size();
Mathias Agopian65ab4712010-07-14 17:59:35 -07002757 size_t mixedTracks = 0;
2758 size_t tracksWithEffect = 0;
Glenn Kasten288ed212012-04-25 17:52:27 -07002759 // counts only _active_ fast tracks
Glenn Kasten58912562012-04-03 10:45:00 -07002760 size_t fastTracks = 0;
Glenn Kasten288ed212012-04-25 17:52:27 -07002761 uint32_t resetMask = 0; // bit mask of fast tracks that need to be reset
Mathias Agopian65ab4712010-07-14 17:59:35 -07002762
2763 float masterVolume = mMasterVolume;
Glenn Kastenea7939a2012-03-14 12:56:26 -07002764 bool masterMute = mMasterMute;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002765
Eric Laurent571d49c2010-08-11 05:20:11 -07002766 if (masterMute) {
2767 masterVolume = 0;
2768 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07002769 // Delegate master volume control to effect in output mix effect chain if needed
Dima Zavinfce7a472011-04-19 22:30:36 -07002770 sp<EffectChain> chain = getEffectChain_l(AUDIO_SESSION_OUTPUT_MIX);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002771 if (chain != 0) {
Eric Laurent571d49c2010-08-11 05:20:11 -07002772 uint32_t v = (uint32_t)(masterVolume * (1 << 24));
Eric Laurentcab11242010-07-15 12:50:15 -07002773 chain->setVolume_l(&v, &v);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002774 masterVolume = (float)((v + (1 << 23)) >> 24);
2775 chain.clear();
2776 }
2777
Glenn Kasten288ed212012-04-25 17:52:27 -07002778 // prepare a new state to push
2779 FastMixerStateQueue *sq = NULL;
2780 FastMixerState *state = NULL;
2781 bool didModify = false;
2782 FastMixerStateQueue::block_t block = FastMixerStateQueue::BLOCK_UNTIL_PUSHED;
2783 if (mFastMixer != NULL) {
2784 sq = mFastMixer->sq();
2785 state = sq->begin();
2786 }
2787
Mathias Agopian65ab4712010-07-14 17:59:35 -07002788 for (size_t i=0 ; i<count ; i++) {
Glenn Kasten3e074702012-02-28 18:40:35 -08002789 sp<Track> t = mActiveTracks[i].promote();
Mathias Agopian65ab4712010-07-14 17:59:35 -07002790 if (t == 0) continue;
2791
Glenn Kasten9c56d4a2011-12-19 15:06:39 -08002792 // this const just means the local variable doesn't change
Mathias Agopian65ab4712010-07-14 17:59:35 -07002793 Track* const track = t.get();
Glenn Kasten58912562012-04-03 10:45:00 -07002794
Glenn Kasten288ed212012-04-25 17:52:27 -07002795 // process fast tracks
Glenn Kasten58912562012-04-03 10:45:00 -07002796 if (track->isFastTrack()) {
Glenn Kasten288ed212012-04-25 17:52:27 -07002797
2798 // It's theoretically possible (though unlikely) for a fast track to be created
2799 // and then removed within the same normal mix cycle. This is not a problem, as
2800 // the track never becomes active so it's fast mixer slot is never touched.
2801 // The converse, of removing an (active) track and then creating a new track
2802 // at the identical fast mixer slot within the same normal mix cycle,
2803 // is impossible because the slot isn't marked available until the end of each cycle.
2804 int j = track->mFastIndex;
2805 FastTrack *fastTrack = &state->mFastTracks[j];
2806
2807 // Determine whether the track is currently in underrun condition,
2808 // and whether it had a recent underrun.
Glenn Kasten09474df2012-05-10 14:48:07 -07002809 FastTrackUnderruns underruns = mFastMixerDumpState.mTracks[j].mUnderruns;
2810 uint32_t recentFull = (underruns.mBitFields.mFull -
2811 track->mObservedUnderruns.mBitFields.mFull) & UNDERRUN_MASK;
2812 uint32_t recentPartial = (underruns.mBitFields.mPartial -
2813 track->mObservedUnderruns.mBitFields.mPartial) & UNDERRUN_MASK;
2814 uint32_t recentEmpty = (underruns.mBitFields.mEmpty -
2815 track->mObservedUnderruns.mBitFields.mEmpty) & UNDERRUN_MASK;
2816 uint32_t recentUnderruns = recentPartial + recentEmpty;
2817 track->mObservedUnderruns = underruns;
Glenn Kasten288ed212012-04-25 17:52:27 -07002818 // don't count underruns that occur while stopping or pausing
Glenn Kastend08f48c2012-05-01 18:14:02 -07002819 // or stopped which can occur when flush() is called while active
2820 if (!(track->isStopping() || track->isPausing() || track->isStopped())) {
Glenn Kasten288ed212012-04-25 17:52:27 -07002821 track->mUnderrunCount += recentUnderruns;
2822 }
Glenn Kasten288ed212012-04-25 17:52:27 -07002823
Glenn Kastend08f48c2012-05-01 18:14:02 -07002824 // This is similar to the state machine for normal tracks,
Glenn Kasten288ed212012-04-25 17:52:27 -07002825 // with a few modifications for fast tracks.
Glenn Kastend08f48c2012-05-01 18:14:02 -07002826 bool isActive = true;
2827 switch (track->mState) {
2828 case TrackBase::STOPPING_1:
2829 // track stays active in STOPPING_1 state until first underrun
2830 if (recentUnderruns > 0) {
2831 track->mState = TrackBase::STOPPING_2;
2832 }
2833 break;
2834 case TrackBase::PAUSING:
Glenn Kasten288ed212012-04-25 17:52:27 -07002835 // ramp down is not yet implemented
Glenn Kasten288ed212012-04-25 17:52:27 -07002836 track->setPaused();
Glenn Kastend08f48c2012-05-01 18:14:02 -07002837 break;
2838 case TrackBase::RESUMING:
Glenn Kasten288ed212012-04-25 17:52:27 -07002839 // ramp up is not yet implemented
Glenn Kasten288ed212012-04-25 17:52:27 -07002840 track->mState = TrackBase::ACTIVE;
Glenn Kastend08f48c2012-05-01 18:14:02 -07002841 break;
2842 case TrackBase::ACTIVE:
Glenn Kasten09474df2012-05-10 14:48:07 -07002843 if (recentFull > 0 || recentPartial > 0) {
2844 // track has provided at least some frames recently: reset retry count
2845 track->mRetryCount = kMaxTrackRetries;
2846 }
2847 if (recentUnderruns == 0) {
2848 // no recent underruns: stay active
2849 break;
2850 }
2851 // there has recently been an underrun of some kind
2852 if (track->sharedBuffer() == 0) {
2853 // were any of the recent underruns "empty" (no frames available)?
2854 if (recentEmpty == 0) {
2855 // no, then ignore the partial underruns as they are allowed indefinitely
2856 break;
2857 }
2858 // there has recently been an "empty" underrun: decrement the retry counter
2859 if (--(track->mRetryCount) > 0) {
2860 break;
2861 }
2862 // indicate to client process that the track was disabled because of underrun;
2863 // it will then automatically call start() when data is available
2864 android_atomic_or(CBLK_DISABLED_ON, &track->mCblk->flags);
2865 // remove from active list, but state remains ACTIVE [confusing but true]
2866 isActive = false;
Glenn Kastend08f48c2012-05-01 18:14:02 -07002867 break;
2868 }
2869 // fall through
2870 case TrackBase::STOPPING_2:
2871 case TrackBase::PAUSED:
2872 case TrackBase::TERMINATED:
Eric Laurent29864602012-05-08 18:57:51 -07002873 case TrackBase::STOPPED:
2874 case TrackBase::FLUSHED: // flush() while active
Glenn Kastend08f48c2012-05-01 18:14:02 -07002875 // Check for presentation complete if track is inactive
2876 // We have consumed all the buffers of this track.
2877 // This would be incomplete if we auto-paused on underrun
2878 {
2879 size_t audioHALFrames =
2880 (mOutput->stream->get_latency(mOutput->stream)*mSampleRate) / 1000;
2881 size_t framesWritten =
2882 mBytesWritten / audio_stream_frame_size(&mOutput->stream->common);
2883 if (!track->presentationComplete(framesWritten, audioHALFrames)) {
2884 // track stays in active list until presentation is complete
2885 break;
2886 }
2887 }
2888 if (track->isStopping_2()) {
2889 track->mState = TrackBase::STOPPED;
2890 }
2891 if (track->isStopped()) {
2892 // Can't reset directly, as fast mixer is still polling this track
2893 // track->reset();
2894 // So instead mark this track as needing to be reset after push with ack
2895 resetMask |= 1 << i;
2896 }
2897 isActive = false;
2898 break;
2899 case TrackBase::IDLE:
2900 default:
2901 LOG_FATAL("unexpected track state %d", track->mState);
Glenn Kasten288ed212012-04-25 17:52:27 -07002902 }
2903
2904 if (isActive) {
2905 // was it previously inactive?
2906 if (!(state->mTrackMask & (1 << j))) {
2907 ExtendedAudioBufferProvider *eabp = track;
2908 VolumeProvider *vp = track;
2909 fastTrack->mBufferProvider = eabp;
2910 fastTrack->mVolumeProvider = vp;
2911 fastTrack->mSampleRate = track->mSampleRate;
2912 fastTrack->mChannelMask = track->mChannelMask;
2913 fastTrack->mGeneration++;
2914 state->mTrackMask |= 1 << j;
2915 didModify = true;
2916 // no acknowledgement required for newly active tracks
2917 }
2918 // cache the combined master volume and stream type volume for fast mixer; this
2919 // lacks any synchronization or barrier so VolumeProvider may read a stale value
2920 track->mCachedVolume = track->isMuted() ?
2921 0 : masterVolume * mStreamTypes[track->streamType()].volume;
2922 ++fastTracks;
2923 } else {
2924 // was it previously active?
2925 if (state->mTrackMask & (1 << j)) {
2926 fastTrack->mBufferProvider = NULL;
2927 fastTrack->mGeneration++;
2928 state->mTrackMask &= ~(1 << j);
2929 didModify = true;
2930 // If any fast tracks were removed, we must wait for acknowledgement
2931 // because we're about to decrement the last sp<> on those tracks.
2932 block = FastMixerStateQueue::BLOCK_UNTIL_ACKED;
Glenn Kastend08f48c2012-05-01 18:14:02 -07002933 } else {
2934 LOG_FATAL("fast track %d should have been active", j);
Glenn Kasten288ed212012-04-25 17:52:27 -07002935 }
Glenn Kastend08f48c2012-05-01 18:14:02 -07002936 tracksToRemove->add(track);
Glenn Kasten288ed212012-04-25 17:52:27 -07002937 // Avoids a misleading display in dumpsys
Glenn Kasten09474df2012-05-10 14:48:07 -07002938 track->mObservedUnderruns.mBitFields.mMostRecent = UNDERRUN_FULL;
Glenn Kasten58912562012-04-03 10:45:00 -07002939 }
2940 continue;
2941 }
2942
2943 { // local variable scope to avoid goto warning
2944
Mathias Agopian65ab4712010-07-14 17:59:35 -07002945 audio_track_cblk_t* cblk = track->cblk();
2946
2947 // The first time a track is added we wait
2948 // for all its buffers to be filled before processing it
Glenn Kasten9c56d4a2011-12-19 15:06:39 -08002949 int name = track->name();
Eric Laurenta47b69c2011-11-08 18:10:16 -08002950 // make sure that we have enough frames to mix one full buffer.
2951 // enforce this condition only once to enable draining the buffer in case the client
2952 // app does not call stop() and relies on underrun to stop:
Eric Laurentda747442012-04-25 18:53:13 -07002953 // hence the test on (mMixerStatus == MIXER_TRACKS_READY) meaning the track was mixed
Eric Laurenta47b69c2011-11-08 18:10:16 -08002954 // during last round
Eric Laurent3dbe3202011-11-03 12:16:05 -07002955 uint32_t minFrames = 1;
Eric Laurent83faee02012-04-27 18:24:29 -07002956 if ((track->sharedBuffer() == 0) && !track->isStopped() && !track->isPausing() &&
Glenn Kasten81028042012-04-30 18:15:12 -07002957 (mMixerStatusIgnoringFastTracks == MIXER_TRACKS_READY)) {
Eric Laurent3dbe3202011-11-03 12:16:05 -07002958 if (t->sampleRate() == (int)mSampleRate) {
Glenn Kasten58912562012-04-03 10:45:00 -07002959 minFrames = mNormalFrameCount;
Eric Laurent3dbe3202011-11-03 12:16:05 -07002960 } else {
Eric Laurent071ccd52011-12-22 16:08:41 -08002961 // +1 for rounding and +1 for additional sample needed for interpolation
Glenn Kasten58912562012-04-03 10:45:00 -07002962 minFrames = (mNormalFrameCount * t->sampleRate()) / mSampleRate + 1 + 1;
Eric Laurent071ccd52011-12-22 16:08:41 -08002963 // add frames already consumed but not yet released by the resampler
Glenn Kastenea7939a2012-03-14 12:56:26 -07002964 // because cblk->framesReady() will include these frames
Eric Laurent071ccd52011-12-22 16:08:41 -08002965 minFrames += mAudioMixer->getUnreleasedFrames(track->name());
2966 // the minimum track buffer size is normally twice the number of frames necessary
2967 // to fill one buffer and the resampler should not leave more than one buffer worth
2968 // of unreleased frames after each pass, but just in case...
Steve Blockc1dc1cb2012-01-09 18:35:44 +00002969 ALOG_ASSERT(minFrames <= cblk->frameCount);
Eric Laurent3dbe3202011-11-03 12:16:05 -07002970 }
2971 }
John Grossman4ff14ba2012-02-08 16:37:41 -08002972 if ((track->framesReady() >= minFrames) && track->isReady() &&
Mathias Agopian65ab4712010-07-14 17:59:35 -07002973 !track->isPaused() && !track->isTerminated())
2974 {
Glenn Kasten9c56d4a2011-12-19 15:06:39 -08002975 //ALOGV("track %d u=%08x, s=%08x [OK] on thread %p", name, cblk->user, cblk->server, this);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002976
2977 mixedTracks++;
2978
2979 // track->mainBuffer() != mMixBuffer means there is an effect chain
2980 // connected to the track
2981 chain.clear();
2982 if (track->mainBuffer() != mMixBuffer) {
2983 chain = getEffectChain_l(track->sessionId());
2984 // Delegate volume control to effect in track effect chain if needed
2985 if (chain != 0) {
2986 tracksWithEffect++;
2987 } else {
Steve Block5ff1dd52012-01-05 23:22:43 +00002988 ALOGW("prepareTracks_l(): track %d attached to effect but no chain found on session %d",
Glenn Kasten9c56d4a2011-12-19 15:06:39 -08002989 name, track->sessionId());
Mathias Agopian65ab4712010-07-14 17:59:35 -07002990 }
2991 }
2992
2993
2994 int param = AudioMixer::VOLUME;
2995 if (track->mFillingUpStatus == Track::FS_FILLED) {
2996 // no ramp for the first volume setting
2997 track->mFillingUpStatus = Track::FS_ACTIVE;
2998 if (track->mState == TrackBase::RESUMING) {
2999 track->mState = TrackBase::ACTIVE;
3000 param = AudioMixer::RAMP_VOLUME;
3001 }
Glenn Kasten9c56d4a2011-12-19 15:06:39 -08003002 mAudioMixer->setParameter(name, AudioMixer::RESAMPLE, AudioMixer::RESET, NULL);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003003 } else if (cblk->server != 0) {
3004 // If the track is stopped before the first frame was mixed,
3005 // do not apply ramp
3006 param = AudioMixer::RAMP_VOLUME;
3007 }
3008
3009 // compute volume for this track
Eric Laurente0aed6d2010-09-10 17:44:44 -07003010 uint32_t vl, vr, va;
Eric Laurent8569f0d2010-07-29 23:43:43 -07003011 if (track->isMuted() || track->isPausing() ||
Glenn Kasten02bbd202012-02-08 12:35:35 -08003012 mStreamTypes[track->streamType()].mute) {
Eric Laurente0aed6d2010-09-10 17:44:44 -07003013 vl = vr = va = 0;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003014 if (track->isPausing()) {
3015 track->setPaused();
3016 }
3017 } else {
Eric Laurente0aed6d2010-09-10 17:44:44 -07003018
Mathias Agopian65ab4712010-07-14 17:59:35 -07003019 // read original volumes with volume control
Glenn Kasten02bbd202012-02-08 12:35:35 -08003020 float typeVolume = mStreamTypes[track->streamType()].volume;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003021 float v = masterVolume * typeVolume;
Glenn Kasten83d86532012-01-17 14:39:34 -08003022 uint32_t vlr = cblk->getVolumeLR();
Glenn Kastenb1cf75c2012-01-17 12:20:54 -08003023 vl = vlr & 0xFFFF;
3024 vr = vlr >> 16;
3025 // track volumes come from shared memory, so can't be trusted and must be clamped
3026 if (vl > MAX_GAIN_INT) {
3027 ALOGV("Track left volume out of range: %04X", vl);
3028 vl = MAX_GAIN_INT;
3029 }
3030 if (vr > MAX_GAIN_INT) {
3031 ALOGV("Track right volume out of range: %04X", vr);
3032 vr = MAX_GAIN_INT;
3033 }
3034 // now apply the master volume and stream type volume
3035 vl = (uint32_t)(v * vl) << 12;
3036 vr = (uint32_t)(v * vr) << 12;
3037 // assuming master volume and stream type volume each go up to 1.0,
3038 // vl and vr are now in 8.24 format
Mathias Agopian65ab4712010-07-14 17:59:35 -07003039
Glenn Kasten05632a52012-01-03 14:22:33 -08003040 uint16_t sendLevel = cblk->getSendLevel_U4_12();
3041 // send level comes from shared memory and so may be corrupt
Glenn Kasten3b81aca2012-01-27 15:26:23 -08003042 if (sendLevel > MAX_GAIN_INT) {
Glenn Kasten05632a52012-01-03 14:22:33 -08003043 ALOGV("Track send level out of range: %04X", sendLevel);
Glenn Kastenb1cf75c2012-01-17 12:20:54 -08003044 sendLevel = MAX_GAIN_INT;
Glenn Kasten05632a52012-01-03 14:22:33 -08003045 }
3046 va = (uint32_t)(v * sendLevel);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003047 }
Eric Laurente0aed6d2010-09-10 17:44:44 -07003048 // Delegate volume control to effect in track effect chain if needed
3049 if (chain != 0 && chain->setVolume_l(&vl, &vr)) {
3050 // Do not ramp volume if volume is controlled by effect
3051 param = AudioMixer::VOLUME;
3052 track->mHasVolumeController = true;
3053 } else {
3054 // force no volume ramp when volume controller was just disabled or removed
3055 // from effect chain to avoid volume spike
3056 if (track->mHasVolumeController) {
3057 param = AudioMixer::VOLUME;
3058 }
3059 track->mHasVolumeController = false;
3060 }
3061
3062 // Convert volumes from 8.24 to 4.12 format
Glenn Kastenb1cf75c2012-01-17 12:20:54 -08003063 // This additional clamping is needed in case chain->setVolume_l() overshot
Glenn Kasten3b81aca2012-01-27 15:26:23 -08003064 vl = (vl + (1 << 11)) >> 12;
3065 if (vl > MAX_GAIN_INT) vl = MAX_GAIN_INT;
3066 vr = (vr + (1 << 11)) >> 12;
3067 if (vr > MAX_GAIN_INT) vr = MAX_GAIN_INT;
Eric Laurente0aed6d2010-09-10 17:44:44 -07003068
Glenn Kasten3b81aca2012-01-27 15:26:23 -08003069 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 -07003070
Mathias Agopian65ab4712010-07-14 17:59:35 -07003071 // XXX: these things DON'T need to be done each time
Glenn Kasten9c56d4a2011-12-19 15:06:39 -08003072 mAudioMixer->setBufferProvider(name, track);
3073 mAudioMixer->enable(name);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003074
Glenn Kasten3b81aca2012-01-27 15:26:23 -08003075 mAudioMixer->setParameter(name, param, AudioMixer::VOLUME0, (void *)vl);
3076 mAudioMixer->setParameter(name, param, AudioMixer::VOLUME1, (void *)vr);
3077 mAudioMixer->setParameter(name, param, AudioMixer::AUXLEVEL, (void *)va);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003078 mAudioMixer->setParameter(
Glenn Kasten9c56d4a2011-12-19 15:06:39 -08003079 name,
Mathias Agopian65ab4712010-07-14 17:59:35 -07003080 AudioMixer::TRACK,
3081 AudioMixer::FORMAT, (void *)track->format());
3082 mAudioMixer->setParameter(
Glenn Kasten9c56d4a2011-12-19 15:06:39 -08003083 name,
Mathias Agopian65ab4712010-07-14 17:59:35 -07003084 AudioMixer::TRACK,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07003085 AudioMixer::CHANNEL_MASK, (void *)track->channelMask());
Mathias Agopian65ab4712010-07-14 17:59:35 -07003086 mAudioMixer->setParameter(
Glenn Kasten9c56d4a2011-12-19 15:06:39 -08003087 name,
Mathias Agopian65ab4712010-07-14 17:59:35 -07003088 AudioMixer::RESAMPLE,
3089 AudioMixer::SAMPLE_RATE,
3090 (void *)(cblk->sampleRate));
3091 mAudioMixer->setParameter(
Glenn Kasten9c56d4a2011-12-19 15:06:39 -08003092 name,
Mathias Agopian65ab4712010-07-14 17:59:35 -07003093 AudioMixer::TRACK,
3094 AudioMixer::MAIN_BUFFER, (void *)track->mainBuffer());
3095 mAudioMixer->setParameter(
Glenn Kasten9c56d4a2011-12-19 15:06:39 -08003096 name,
Mathias Agopian65ab4712010-07-14 17:59:35 -07003097 AudioMixer::TRACK,
3098 AudioMixer::AUX_BUFFER, (void *)track->auxBuffer());
3099
3100 // reset retry count
3101 track->mRetryCount = kMaxTrackRetries;
Glenn Kastenea7939a2012-03-14 12:56:26 -07003102
Eric Laurent27741442012-01-17 19:20:12 -08003103 // If one track is ready, set the mixer ready if:
3104 // - the mixer was not ready during previous round OR
3105 // - no other track is not ready
Glenn Kasten81028042012-04-30 18:15:12 -07003106 if (mMixerStatusIgnoringFastTracks != MIXER_TRACKS_READY ||
Eric Laurent27741442012-01-17 19:20:12 -08003107 mixerStatus != MIXER_TRACKS_ENABLED) {
3108 mixerStatus = MIXER_TRACKS_READY;
3109 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07003110 } else {
Glenn Kasten9c56d4a2011-12-19 15:06:39 -08003111 //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 -07003112 if ((track->sharedBuffer() != 0) || track->isTerminated() ||
3113 track->isStopped() || track->isPaused()) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07003114 // We have consumed all the buffers of this track.
3115 // Remove it from the list of active tracks.
Eric Laurenta011e352012-03-29 15:51:43 -07003116 // TODO: use actual buffer filling status instead of latency when available from
3117 // audio HAL
3118 size_t audioHALFrames =
3119 (mOutput->stream->get_latency(mOutput->stream)*mSampleRate) / 1000;
3120 size_t framesWritten =
3121 mBytesWritten / audio_stream_frame_size(&mOutput->stream->common);
3122 if (track->presentationComplete(framesWritten, audioHALFrames)) {
Eric Laurent29864602012-05-08 18:57:51 -07003123 if (track->isStopped()) {
3124 track->reset();
3125 }
Eric Laurenta011e352012-03-29 15:51:43 -07003126 tracksToRemove->add(track);
3127 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07003128 } else {
3129 // No buffers for this track. Give it a few chances to
3130 // fill a buffer, then remove it from active list.
3131 if (--(track->mRetryCount) <= 0) {
Glenn Kasten9c56d4a2011-12-19 15:06:39 -08003132 ALOGV("BUFFER TIMEOUT: remove(%d) from active list on thread %p", name, this);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003133 tracksToRemove->add(track);
Glenn Kasten288ed212012-04-25 17:52:27 -07003134 // indicate to client process that the track was disabled because of underrun;
3135 // it will then automatically call start() when data is available
Eric Laurent38ccae22011-03-28 18:37:07 -07003136 android_atomic_or(CBLK_DISABLED_ON, &cblk->flags);
Eric Laurent27741442012-01-17 19:20:12 -08003137 // If one track is not ready, mark the mixer also not ready if:
3138 // - the mixer was ready during previous round OR
3139 // - no other track is ready
Glenn Kasten81028042012-04-30 18:15:12 -07003140 } else if (mMixerStatusIgnoringFastTracks == MIXER_TRACKS_READY ||
Eric Laurent27741442012-01-17 19:20:12 -08003141 mixerStatus != MIXER_TRACKS_READY) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07003142 mixerStatus = MIXER_TRACKS_ENABLED;
3143 }
3144 }
Glenn Kasten9c56d4a2011-12-19 15:06:39 -08003145 mAudioMixer->disable(name);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003146 }
Glenn Kasten58912562012-04-03 10:45:00 -07003147
3148 } // local variable scope to avoid goto warning
3149track_is_ready: ;
3150
Mathias Agopian65ab4712010-07-14 17:59:35 -07003151 }
3152
Glenn Kasten288ed212012-04-25 17:52:27 -07003153 // Push the new FastMixer state if necessary
3154 if (didModify) {
3155 state->mFastTracksGen++;
3156 // if the fast mixer was active, but now there are no fast tracks, then put it in cold idle
3157 if (kUseFastMixer == FastMixer_Dynamic &&
3158 state->mCommand == FastMixerState::MIX_WRITE && state->mTrackMask <= 1) {
3159 state->mCommand = FastMixerState::COLD_IDLE;
3160 state->mColdFutexAddr = &mFastMixerFutex;
3161 state->mColdGen++;
3162 mFastMixerFutex = 0;
3163 if (kUseFastMixer == FastMixer_Dynamic) {
3164 mNormalSink = mOutputSink;
3165 }
3166 // If we go into cold idle, need to wait for acknowledgement
3167 // so that fast mixer stops doing I/O.
3168 block = FastMixerStateQueue::BLOCK_UNTIL_ACKED;
3169 }
3170 sq->end();
3171 }
3172 if (sq != NULL) {
3173 sq->end(didModify);
3174 sq->push(block);
3175 }
3176
3177 // Now perform the deferred reset on fast tracks that have stopped
3178 while (resetMask != 0) {
3179 size_t i = __builtin_ctz(resetMask);
3180 ALOG_ASSERT(i < count);
3181 resetMask &= ~(1 << i);
3182 sp<Track> t = mActiveTracks[i].promote();
3183 if (t == 0) continue;
3184 Track* track = t.get();
3185 ALOG_ASSERT(track->isFastTrack() && track->isStopped());
3186 track->reset();
3187 }
Glenn Kasten58912562012-04-03 10:45:00 -07003188
Mathias Agopian65ab4712010-07-14 17:59:35 -07003189 // remove all the tracks that need to be...
3190 count = tracksToRemove->size();
Glenn Kastenf6b16782011-12-15 09:51:17 -08003191 if (CC_UNLIKELY(count)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07003192 for (size_t i=0 ; i<count ; i++) {
3193 const sp<Track>& track = tracksToRemove->itemAt(i);
3194 mActiveTracks.remove(track);
3195 if (track->mainBuffer() != mMixBuffer) {
3196 chain = getEffectChain_l(track->sessionId());
3197 if (chain != 0) {
Steve Block3856b092011-10-20 11:56:00 +01003198 ALOGV("stopping track on chain %p for session Id: %d", chain.get(), track->sessionId());
Eric Laurentb469b942011-05-09 12:09:06 -07003199 chain->decActiveTrackCnt();
Mathias Agopian65ab4712010-07-14 17:59:35 -07003200 }
3201 }
3202 if (track->isTerminated()) {
Eric Laurentb469b942011-05-09 12:09:06 -07003203 removeTrack_l(track);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003204 }
3205 }
3206 }
3207
3208 // mix buffer must be cleared if all tracks are connected to an
3209 // effect chain as in this case the mixer will not write to
3210 // mix buffer and track effects will accumulate into it
Glenn Kasten58912562012-04-03 10:45:00 -07003211 if ((mixedTracks != 0 && mixedTracks == tracksWithEffect) || (mixedTracks == 0 && fastTracks > 0)) {
3212 // FIXME as a performance optimization, should remember previous zero status
3213 memset(mMixBuffer, 0, mNormalFrameCount * mChannelCount * sizeof(int16_t));
Mathias Agopian65ab4712010-07-14 17:59:35 -07003214 }
3215
Glenn Kasten58912562012-04-03 10:45:00 -07003216 // if any fast tracks, then status is ready
Glenn Kasten81028042012-04-30 18:15:12 -07003217 mMixerStatusIgnoringFastTracks = mixerStatus;
Glenn Kasten58912562012-04-03 10:45:00 -07003218 if (fastTracks > 0) {
3219 mixerStatus = MIXER_TRACKS_READY;
3220 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07003221 return mixerStatus;
3222}
3223
Glenn Kasten66fcab92012-02-24 14:59:21 -08003224/*
3225The derived values that are cached:
3226 - mixBufferSize from frame count * frame size
3227 - activeSleepTime from activeSleepTimeUs()
3228 - idleSleepTime from idleSleepTimeUs()
3229 - standbyDelay from mActiveSleepTimeUs (DIRECT only)
3230 - maxPeriod from frame count and sample rate (MIXER only)
3231
3232The parameters that affect these derived values are:
3233 - frame count
3234 - frame size
3235 - sample rate
3236 - device type: A2DP or not
3237 - device latency
3238 - format: PCM or not
3239 - active sleep time
3240 - idle sleep time
3241*/
3242
3243void AudioFlinger::PlaybackThread::cacheParameters_l()
3244{
Glenn Kasten58912562012-04-03 10:45:00 -07003245 mixBufferSize = mNormalFrameCount * mFrameSize;
Glenn Kasten66fcab92012-02-24 14:59:21 -08003246 activeSleepTime = activeSleepTimeUs();
3247 idleSleepTime = idleSleepTimeUs();
3248}
3249
Glenn Kastenfff6d712012-01-12 16:38:12 -08003250void AudioFlinger::MixerThread::invalidateTracks(audio_stream_type_t streamType)
Mathias Agopian65ab4712010-07-14 17:59:35 -07003251{
Steve Block3856b092011-10-20 11:56:00 +01003252 ALOGV ("MixerThread::invalidateTracks() mixer %p, streamType %d, mTracks.size %d",
Eric Laurentde070132010-07-13 04:45:46 -07003253 this, streamType, mTracks.size());
Mathias Agopian65ab4712010-07-14 17:59:35 -07003254 Mutex::Autolock _l(mLock);
Eric Laurentde070132010-07-13 04:45:46 -07003255
Mathias Agopian65ab4712010-07-14 17:59:35 -07003256 size_t size = mTracks.size();
3257 for (size_t i = 0; i < size; i++) {
3258 sp<Track> t = mTracks[i];
Glenn Kasten02bbd202012-02-08 12:35:35 -08003259 if (t->streamType() == streamType) {
Eric Laurent38ccae22011-03-28 18:37:07 -07003260 android_atomic_or(CBLK_INVALID_ON, &t->mCblk->flags);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003261 t->mCblk->cv.signal();
Mathias Agopian65ab4712010-07-14 17:59:35 -07003262 }
3263 }
3264}
3265
Mathias Agopian65ab4712010-07-14 17:59:35 -07003266// getTrackName_l() must be called with ThreadBase::mLock held
Jean-Michel Trivi7d5b2622012-04-04 18:54:36 -07003267int AudioFlinger::MixerThread::getTrackName_l(audio_channel_mask_t channelMask)
Mathias Agopian65ab4712010-07-14 17:59:35 -07003268{
Jean-Michel Trivi9bd23222012-04-16 13:43:48 -07003269 return mAudioMixer->getTrackName(channelMask);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003270}
3271
3272// deleteTrackName_l() must be called with ThreadBase::mLock held
3273void AudioFlinger::MixerThread::deleteTrackName_l(int name)
3274{
Steve Block3856b092011-10-20 11:56:00 +01003275 ALOGV("remove track (%d) and delete from mixer", name);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003276 mAudioMixer->deleteTrackName(name);
3277}
3278
3279// checkForNewParameters_l() must be called with ThreadBase::mLock held
3280bool AudioFlinger::MixerThread::checkForNewParameters_l()
3281{
Glenn Kasten58912562012-04-03 10:45:00 -07003282 // if !&IDLE, holds the FastMixer state to restore after new parameters processed
3283 FastMixerState::Command previousCommand = FastMixerState::HOT_IDLE;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003284 bool reconfig = false;
3285
3286 while (!mNewParameters.isEmpty()) {
Glenn Kasten58912562012-04-03 10:45:00 -07003287
3288 if (mFastMixer != NULL) {
3289 FastMixerStateQueue *sq = mFastMixer->sq();
3290 FastMixerState *state = sq->begin();
3291 if (!(state->mCommand & FastMixerState::IDLE)) {
3292 previousCommand = state->mCommand;
3293 state->mCommand = FastMixerState::HOT_IDLE;
3294 sq->end();
3295 sq->push(FastMixerStateQueue::BLOCK_UNTIL_ACKED);
3296 } else {
3297 sq->end(false /*didModify*/);
3298 }
3299 }
3300
Mathias Agopian65ab4712010-07-14 17:59:35 -07003301 status_t status = NO_ERROR;
3302 String8 keyValuePair = mNewParameters[0];
3303 AudioParameter param = AudioParameter(keyValuePair);
3304 int value;
3305
3306 if (param.getInt(String8(AudioParameter::keySamplingRate), value) == NO_ERROR) {
3307 reconfig = true;
3308 }
3309 if (param.getInt(String8(AudioParameter::keyFormat), value) == NO_ERROR) {
Glenn Kasten58f30212012-01-12 12:27:51 -08003310 if ((audio_format_t) value != AUDIO_FORMAT_PCM_16_BIT) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07003311 status = BAD_VALUE;
3312 } else {
3313 reconfig = true;
3314 }
3315 }
3316 if (param.getInt(String8(AudioParameter::keyChannels), value) == NO_ERROR) {
Dima Zavinfce7a472011-04-19 22:30:36 -07003317 if (value != AUDIO_CHANNEL_OUT_STEREO) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07003318 status = BAD_VALUE;
3319 } else {
3320 reconfig = true;
3321 }
3322 }
3323 if (param.getInt(String8(AudioParameter::keyFrameCount), value) == NO_ERROR) {
3324 // do not accept frame count changes if tracks are open as the track buffer
Glenn Kasten362c4e62011-12-14 10:28:06 -08003325 // size depends on frame count and correct behavior would not be guaranteed
Mathias Agopian65ab4712010-07-14 17:59:35 -07003326 // if frame count is changed after track creation
3327 if (!mTracks.isEmpty()) {
3328 status = INVALID_OPERATION;
3329 } else {
3330 reconfig = true;
3331 }
3332 }
3333 if (param.getInt(String8(AudioParameter::keyRouting), value) == NO_ERROR) {
Glenn Kastend3cee2f2012-03-13 17:55:35 -07003334#ifdef ADD_BATTERY_DATA
Gloria Wang9ee159b2011-02-24 14:51:45 -08003335 // when changing the audio output device, call addBatteryData to notify
3336 // the change
Eric Laurentb469b942011-05-09 12:09:06 -07003337 if ((int)mDevice != value) {
Gloria Wang9ee159b2011-02-24 14:51:45 -08003338 uint32_t params = 0;
3339 // check whether speaker is on
Dima Zavinfce7a472011-04-19 22:30:36 -07003340 if (value & AUDIO_DEVICE_OUT_SPEAKER) {
Gloria Wang9ee159b2011-02-24 14:51:45 -08003341 params |= IMediaPlayerService::kBatteryDataSpeakerOn;
3342 }
3343
3344 int deviceWithoutSpeaker
Dima Zavinfce7a472011-04-19 22:30:36 -07003345 = AUDIO_DEVICE_OUT_ALL & ~AUDIO_DEVICE_OUT_SPEAKER;
Gloria Wang9ee159b2011-02-24 14:51:45 -08003346 // check if any other device (except speaker) is on
3347 if (value & deviceWithoutSpeaker ) {
3348 params |= IMediaPlayerService::kBatteryDataOtherAudioDeviceOn;
3349 }
3350
3351 if (params != 0) {
3352 addBatteryData(params);
3353 }
3354 }
Glenn Kastend3cee2f2012-03-13 17:55:35 -07003355#endif
Gloria Wang9ee159b2011-02-24 14:51:45 -08003356
Mathias Agopian65ab4712010-07-14 17:59:35 -07003357 // forward device change to effects that have requested to be
3358 // aware of attached audio device.
3359 mDevice = (uint32_t)value;
3360 for (size_t i = 0; i < mEffectChains.size(); i++) {
Eric Laurentcab11242010-07-15 12:50:15 -07003361 mEffectChains[i]->setDevice_l(mDevice);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003362 }
3363 }
3364
3365 if (status == NO_ERROR) {
Dima Zavin799a70e2011-04-18 16:57:27 -07003366 status = mOutput->stream->common.set_parameters(&mOutput->stream->common,
Dima Zavinfce7a472011-04-19 22:30:36 -07003367 keyValuePair.string());
Mathias Agopian65ab4712010-07-14 17:59:35 -07003368 if (!mStandby && status == INVALID_OPERATION) {
Glenn Kastene53b9ea2012-03-12 16:29:55 -07003369 mOutput->stream->common.standby(&mOutput->stream->common);
3370 mStandby = true;
3371 mBytesWritten = 0;
3372 status = mOutput->stream->common.set_parameters(&mOutput->stream->common,
Dima Zavinfce7a472011-04-19 22:30:36 -07003373 keyValuePair.string());
Mathias Agopian65ab4712010-07-14 17:59:35 -07003374 }
3375 if (status == NO_ERROR && reconfig) {
3376 delete mAudioMixer;
Glenn Kastene9dd0172012-01-27 18:08:45 -08003377 // for safety in case readOutputParameters() accesses mAudioMixer (it doesn't)
3378 mAudioMixer = NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003379 readOutputParameters();
Glenn Kasten58912562012-04-03 10:45:00 -07003380 mAudioMixer = new AudioMixer(mNormalFrameCount, mSampleRate);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003381 for (size_t i = 0; i < mTracks.size() ; i++) {
Jean-Michel Trivi7d5b2622012-04-04 18:54:36 -07003382 int name = getTrackName_l((audio_channel_mask_t)mTracks[i]->mChannelMask);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003383 if (name < 0) break;
3384 mTracks[i]->mName = name;
3385 // limit track sample rate to 2 x new output sample rate
3386 if (mTracks[i]->mCblk->sampleRate > 2 * sampleRate()) {
3387 mTracks[i]->mCblk->sampleRate = 2 * sampleRate();
3388 }
3389 }
3390 sendConfigEvent_l(AudioSystem::OUTPUT_CONFIG_CHANGED);
3391 }
3392 }
3393
3394 mNewParameters.removeAt(0);
3395
3396 mParamStatus = status;
3397 mParamCond.signal();
Eric Laurent60cd0a02011-09-13 11:40:21 -07003398 // wait for condition with time out in case the thread calling ThreadBase::setParameters()
3399 // already timed out waiting for the status and will never signal the condition.
Glenn Kasten7dede872011-12-13 11:04:14 -08003400 mWaitWorkCV.waitRelative(mLock, kSetParametersTimeoutNs);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003401 }
Glenn Kasten58912562012-04-03 10:45:00 -07003402
3403 if (!(previousCommand & FastMixerState::IDLE)) {
3404 ALOG_ASSERT(mFastMixer != NULL);
3405 FastMixerStateQueue *sq = mFastMixer->sq();
3406 FastMixerState *state = sq->begin();
3407 ALOG_ASSERT(state->mCommand == FastMixerState::HOT_IDLE);
3408 state->mCommand = previousCommand;
3409 sq->end();
3410 sq->push(FastMixerStateQueue::BLOCK_UNTIL_PUSHED);
3411 }
3412
Mathias Agopian65ab4712010-07-14 17:59:35 -07003413 return reconfig;
3414}
3415
3416status_t AudioFlinger::MixerThread::dumpInternals(int fd, const Vector<String16>& args)
3417{
3418 const size_t SIZE = 256;
3419 char buffer[SIZE];
3420 String8 result;
3421
3422 PlaybackThread::dumpInternals(fd, args);
3423
3424 snprintf(buffer, SIZE, "AudioMixer tracks: %08x\n", mAudioMixer->trackNames());
3425 result.append(buffer);
3426 write(fd, result.string(), result.size());
Glenn Kasten58912562012-04-03 10:45:00 -07003427
3428 // Make a non-atomic copy of fast mixer dump state so it won't change underneath us
3429 FastMixerDumpState copy = mFastMixerDumpState;
3430 copy.dump(fd);
3431
Mathias Agopian65ab4712010-07-14 17:59:35 -07003432 return NO_ERROR;
3433}
3434
Glenn Kasten0bf65bd2012-02-28 18:32:53 -08003435uint32_t AudioFlinger::MixerThread::idleSleepTimeUs() const
Mathias Agopian65ab4712010-07-14 17:59:35 -07003436{
Glenn Kasten58912562012-04-03 10:45:00 -07003437 return (uint32_t)(((mNormalFrameCount * 1000) / mSampleRate) * 1000) / 2;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003438}
3439
Glenn Kasten0bf65bd2012-02-28 18:32:53 -08003440uint32_t AudioFlinger::MixerThread::suspendSleepTimeUs() const
Eric Laurent25cbe0e2010-08-18 18:13:17 -07003441{
Glenn Kasten58912562012-04-03 10:45:00 -07003442 return (uint32_t)(((mNormalFrameCount * 1000) / mSampleRate) * 1000);
Eric Laurent25cbe0e2010-08-18 18:13:17 -07003443}
3444
Glenn Kasten66fcab92012-02-24 14:59:21 -08003445void AudioFlinger::MixerThread::cacheParameters_l()
3446{
3447 PlaybackThread::cacheParameters_l();
3448
3449 // FIXME: Relaxed timing because of a certain device that can't meet latency
3450 // Should be reduced to 2x after the vendor fixes the driver issue
3451 // increase threshold again due to low power audio mode. The way this warning
3452 // threshold is calculated and its usefulness should be reconsidered anyway.
Glenn Kasten58912562012-04-03 10:45:00 -07003453 maxPeriod = seconds(mNormalFrameCount) / mSampleRate * 15;
Glenn Kasten66fcab92012-02-24 14:59:21 -08003454}
3455
Mathias Agopian65ab4712010-07-14 17:59:35 -07003456// ----------------------------------------------------------------------------
Glenn Kasten72ef00d2012-01-17 11:09:42 -08003457AudioFlinger::DirectOutputThread::DirectOutputThread(const sp<AudioFlinger>& audioFlinger,
3458 AudioStreamOut* output, audio_io_handle_t id, uint32_t device)
Glenn Kasten23bb8be2012-01-26 10:38:26 -08003459 : PlaybackThread(audioFlinger, output, id, device, DIRECT)
Glenn Kasten84afa3b2012-01-25 15:28:08 -08003460 // mLeftVolFloat, mRightVolFloat
3461 // mLeftVolShort, mRightVolShort
Mathias Agopian65ab4712010-07-14 17:59:35 -07003462{
Mathias Agopian65ab4712010-07-14 17:59:35 -07003463}
3464
3465AudioFlinger::DirectOutputThread::~DirectOutputThread()
3466{
3467}
3468
Glenn Kasten1465f0c2012-03-06 11:23:32 -08003469AudioFlinger::PlaybackThread::mixer_state AudioFlinger::DirectOutputThread::prepareTracks_l(
3470 Vector< sp<Track> > *tracksToRemove
Glenn Kasten000f0e32012-03-01 17:10:56 -08003471)
Mathias Agopian65ab4712010-07-14 17:59:35 -07003472{
Glenn Kasten1465f0c2012-03-06 11:23:32 -08003473 sp<Track> trackToRemove;
3474
Glenn Kastenfec279f2012-03-08 07:47:15 -08003475 mixer_state mixerStatus = MIXER_IDLE;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003476
Glenn Kasten952eeb22012-03-06 11:30:57 -08003477 // find out which tracks need to be processed
3478 if (mActiveTracks.size() != 0) {
3479 sp<Track> t = mActiveTracks[0].promote();
Glenn Kastenfec279f2012-03-08 07:47:15 -08003480 // The track died recently
3481 if (t == 0) return MIXER_IDLE;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003482
Glenn Kasten952eeb22012-03-06 11:30:57 -08003483 Track* const track = t.get();
3484 audio_track_cblk_t* cblk = track->cblk();
Mathias Agopian65ab4712010-07-14 17:59:35 -07003485
Glenn Kasten952eeb22012-03-06 11:30:57 -08003486 // The first time a track is added we wait
3487 // for all its buffers to be filled before processing it
3488 if (cblk->framesReady() && track->isReady() &&
3489 !track->isPaused() && !track->isTerminated())
3490 {
3491 //ALOGV("track %d u=%08x, s=%08x [OK]", track->name(), cblk->user, cblk->server);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003492
Glenn Kasten952eeb22012-03-06 11:30:57 -08003493 if (track->mFillingUpStatus == Track::FS_FILLED) {
3494 track->mFillingUpStatus = Track::FS_ACTIVE;
3495 mLeftVolFloat = mRightVolFloat = 0;
3496 mLeftVolShort = mRightVolShort = 0;
3497 if (track->mState == TrackBase::RESUMING) {
3498 track->mState = TrackBase::ACTIVE;
3499 rampVolume = true;
3500 }
3501 } else if (cblk->server != 0) {
3502 // If the track is stopped before the first frame was mixed,
3503 // do not apply ramp
3504 rampVolume = true;
3505 }
3506 // compute volume for this track
3507 float left, right;
3508 if (track->isMuted() || mMasterMute || track->isPausing() ||
3509 mStreamTypes[track->streamType()].mute) {
3510 left = right = 0;
3511 if (track->isPausing()) {
3512 track->setPaused();
3513 }
3514 } else {
3515 float typeVolume = mStreamTypes[track->streamType()].volume;
3516 float v = mMasterVolume * typeVolume;
3517 uint32_t vlr = cblk->getVolumeLR();
3518 float v_clamped = v * (vlr & 0xFFFF);
3519 if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN;
3520 left = v_clamped/MAX_GAIN;
3521 v_clamped = v * (vlr >> 16);
3522 if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN;
3523 right = v_clamped/MAX_GAIN;
3524 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07003525
Glenn Kasten952eeb22012-03-06 11:30:57 -08003526 if (left != mLeftVolFloat || right != mRightVolFloat) {
3527 mLeftVolFloat = left;
3528 mRightVolFloat = right;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003529
Glenn Kasten952eeb22012-03-06 11:30:57 -08003530 // If audio HAL implements volume control,
3531 // force software volume to nominal value
3532 if (mOutput->stream->set_volume(mOutput->stream, left, right) == NO_ERROR) {
3533 left = 1.0f;
3534 right = 1.0f;
3535 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07003536
Glenn Kasten952eeb22012-03-06 11:30:57 -08003537 // Convert volumes from float to 8.24
3538 uint32_t vl = (uint32_t)(left * (1 << 24));
3539 uint32_t vr = (uint32_t)(right * (1 << 24));
Mathias Agopian65ab4712010-07-14 17:59:35 -07003540
Glenn Kasten952eeb22012-03-06 11:30:57 -08003541 // Delegate volume control to effect in track effect chain if needed
3542 // only one effect chain can be present on DirectOutputThread, so if
3543 // there is one, the track is connected to it
3544 if (!mEffectChains.isEmpty()) {
3545 // Do not ramp volume if volume is controlled by effect
3546 if (mEffectChains[0]->setVolume_l(&vl, &vr)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07003547 rampVolume = false;
3548 }
Glenn Kasten952eeb22012-03-06 11:30:57 -08003549 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07003550
Glenn Kasten952eeb22012-03-06 11:30:57 -08003551 // Convert volumes from 8.24 to 4.12 format
3552 uint32_t v_clamped = (vl + (1 << 11)) >> 12;
3553 if (v_clamped > MAX_GAIN_INT) v_clamped = MAX_GAIN_INT;
3554 leftVol = (uint16_t)v_clamped;
3555 v_clamped = (vr + (1 << 11)) >> 12;
3556 if (v_clamped > MAX_GAIN_INT) v_clamped = MAX_GAIN_INT;
3557 rightVol = (uint16_t)v_clamped;
3558 } else {
3559 leftVol = mLeftVolShort;
3560 rightVol = mRightVolShort;
3561 rampVolume = false;
3562 }
3563
3564 // reset retry count
3565 track->mRetryCount = kMaxTrackRetriesDirect;
Glenn Kastenb071e9b2012-03-07 17:05:59 -08003566 mActiveTrack = t;
Glenn Kastenfec279f2012-03-08 07:47:15 -08003567 mixerStatus = MIXER_TRACKS_READY;
Glenn Kasten952eeb22012-03-06 11:30:57 -08003568 } else {
3569 //ALOGV("track %d u=%08x, s=%08x [NOT READY]", track->name(), cblk->user, cblk->server);
Glenn Kasten952eeb22012-03-06 11:30:57 -08003570 if (track->isTerminated() || track->isStopped() || track->isPaused()) {
3571 // We have consumed all the buffers of this track.
3572 // Remove it from the list of active tracks.
Eric Laurenta011e352012-03-29 15:51:43 -07003573 // TODO: implement behavior for compressed audio
3574 size_t audioHALFrames =
3575 (mOutput->stream->get_latency(mOutput->stream)*mSampleRate) / 1000;
3576 size_t framesWritten =
3577 mBytesWritten / audio_stream_frame_size(&mOutput->stream->common);
3578 if (track->presentationComplete(framesWritten, audioHALFrames)) {
Eric Laurent29864602012-05-08 18:57:51 -07003579 if (track->isStopped()) {
3580 track->reset();
3581 }
Eric Laurenta011e352012-03-29 15:51:43 -07003582 trackToRemove = track;
3583 }
Glenn Kasten952eeb22012-03-06 11:30:57 -08003584 } else {
3585 // No buffers for this track. Give it a few chances to
3586 // fill a buffer, then remove it from active list.
3587 if (--(track->mRetryCount) <= 0) {
3588 ALOGV("BUFFER TIMEOUT: remove(%d) from active list", track->name());
3589 trackToRemove = track;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003590 } else {
Glenn Kastenfec279f2012-03-08 07:47:15 -08003591 mixerStatus = MIXER_TRACKS_ENABLED;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003592 }
3593 }
Glenn Kasten952eeb22012-03-06 11:30:57 -08003594 }
3595 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07003596
Glenn Kasten1465f0c2012-03-06 11:23:32 -08003597 // FIXME merge this with similar code for removing multiple tracks
Glenn Kasten952eeb22012-03-06 11:30:57 -08003598 // remove all the tracks that need to be...
3599 if (CC_UNLIKELY(trackToRemove != 0)) {
Glenn Kasten1465f0c2012-03-06 11:23:32 -08003600 tracksToRemove->add(trackToRemove);
Glenn Kasten952eeb22012-03-06 11:30:57 -08003601 mActiveTracks.remove(trackToRemove);
3602 if (!mEffectChains.isEmpty()) {
Glenn Kasten5798d4e2012-03-08 12:18:35 -08003603 ALOGV("stopping track on chain %p for session Id: %d", mEffectChains[0].get(),
Glenn Kasten952eeb22012-03-06 11:30:57 -08003604 trackToRemove->sessionId());
3605 mEffectChains[0]->decActiveTrackCnt();
3606 }
3607 if (trackToRemove->isTerminated()) {
3608 removeTrack_l(trackToRemove);
3609 }
3610 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07003611
Glenn Kastenfec279f2012-03-08 07:47:15 -08003612 return mixerStatus;
Glenn Kasten000f0e32012-03-01 17:10:56 -08003613}
Mathias Agopian65ab4712010-07-14 17:59:35 -07003614
Glenn Kasten000f0e32012-03-01 17:10:56 -08003615void AudioFlinger::DirectOutputThread::threadLoop_mix()
3616{
Glenn Kasten952eeb22012-03-06 11:30:57 -08003617 AudioBufferProvider::Buffer buffer;
3618 size_t frameCount = mFrameCount;
3619 int8_t *curBuf = (int8_t *)mMixBuffer;
3620 // output audio to hardware
3621 while (frameCount) {
3622 buffer.frameCount = frameCount;
Glenn Kastenb071e9b2012-03-07 17:05:59 -08003623 mActiveTrack->getNextBuffer(&buffer);
Glenn Kasten952eeb22012-03-06 11:30:57 -08003624 if (CC_UNLIKELY(buffer.raw == NULL)) {
3625 memset(curBuf, 0, frameCount * mFrameSize);
3626 break;
3627 }
3628 memcpy(curBuf, buffer.raw, buffer.frameCount * mFrameSize);
3629 frameCount -= buffer.frameCount;
3630 curBuf += buffer.frameCount * mFrameSize;
Glenn Kastenb071e9b2012-03-07 17:05:59 -08003631 mActiveTrack->releaseBuffer(&buffer);
Glenn Kasten952eeb22012-03-06 11:30:57 -08003632 }
3633 sleepTime = 0;
3634 standbyTime = systemTime() + standbyDelay;
Glenn Kastenb071e9b2012-03-07 17:05:59 -08003635 mActiveTrack.clear();
Glenn Kasten73f4bc32012-03-09 12:08:48 -08003636
3637 // apply volume
3638
3639 // Do not apply volume on compressed audio
3640 if (!audio_is_linear_pcm(mFormat)) {
3641 return;
3642 }
3643
3644 // convert to signed 16 bit before volume calculation
3645 if (mFormat == AUDIO_FORMAT_PCM_8_BIT) {
3646 size_t count = mFrameCount * mChannelCount;
3647 uint8_t *src = (uint8_t *)mMixBuffer + count-1;
3648 int16_t *dst = mMixBuffer + count-1;
Glenn Kastene53b9ea2012-03-12 16:29:55 -07003649 while (count--) {
Glenn Kasten73f4bc32012-03-09 12:08:48 -08003650 *dst-- = (int16_t)(*src--^0x80) << 8;
3651 }
3652 }
3653
3654 frameCount = mFrameCount;
3655 int16_t *out = mMixBuffer;
3656 if (rampVolume) {
3657 if (mChannelCount == 1) {
3658 int32_t d = ((int32_t)leftVol - (int32_t)mLeftVolShort) << 16;
3659 int32_t vlInc = d / (int32_t)frameCount;
3660 int32_t vl = ((int32_t)mLeftVolShort << 16);
3661 do {
3662 out[0] = clamp16(mul(out[0], vl >> 16) >> 12);
3663 out++;
3664 vl += vlInc;
3665 } while (--frameCount);
3666
3667 } else {
3668 int32_t d = ((int32_t)leftVol - (int32_t)mLeftVolShort) << 16;
3669 int32_t vlInc = d / (int32_t)frameCount;
3670 d = ((int32_t)rightVol - (int32_t)mRightVolShort) << 16;
3671 int32_t vrInc = d / (int32_t)frameCount;
3672 int32_t vl = ((int32_t)mLeftVolShort << 16);
3673 int32_t vr = ((int32_t)mRightVolShort << 16);
3674 do {
3675 out[0] = clamp16(mul(out[0], vl >> 16) >> 12);
3676 out[1] = clamp16(mul(out[1], vr >> 16) >> 12);
3677 out += 2;
3678 vl += vlInc;
3679 vr += vrInc;
3680 } while (--frameCount);
3681 }
3682 } else {
3683 if (mChannelCount == 1) {
3684 do {
3685 out[0] = clamp16(mul(out[0], leftVol) >> 12);
3686 out++;
3687 } while (--frameCount);
3688 } else {
3689 do {
3690 out[0] = clamp16(mul(out[0], leftVol) >> 12);
3691 out[1] = clamp16(mul(out[1], rightVol) >> 12);
3692 out += 2;
3693 } while (--frameCount);
3694 }
3695 }
3696
3697 // convert back to unsigned 8 bit after volume calculation
3698 if (mFormat == AUDIO_FORMAT_PCM_8_BIT) {
3699 size_t count = mFrameCount * mChannelCount;
3700 int16_t *src = mMixBuffer;
3701 uint8_t *dst = (uint8_t *)mMixBuffer;
Glenn Kastene53b9ea2012-03-12 16:29:55 -07003702 while (count--) {
Glenn Kasten73f4bc32012-03-09 12:08:48 -08003703 *dst++ = (uint8_t)(((int32_t)*src++ + (1<<7)) >> 8)^0x80;
3704 }
3705 }
3706
3707 mLeftVolShort = leftVol;
3708 mRightVolShort = rightVol;
Glenn Kasten000f0e32012-03-01 17:10:56 -08003709}
3710
3711void AudioFlinger::DirectOutputThread::threadLoop_sleepTime()
3712{
Glenn Kasten952eeb22012-03-06 11:30:57 -08003713 if (sleepTime == 0) {
Glenn Kastenfec279f2012-03-08 07:47:15 -08003714 if (mMixerStatus == MIXER_TRACKS_ENABLED) {
Glenn Kasten952eeb22012-03-06 11:30:57 -08003715 sleepTime = activeSleepTime;
3716 } else {
3717 sleepTime = idleSleepTime;
3718 }
3719 } else if (mBytesWritten != 0 && audio_is_linear_pcm(mFormat)) {
Glenn Kasten58912562012-04-03 10:45:00 -07003720 memset(mMixBuffer, 0, mFrameCount * mFrameSize);
Glenn Kasten952eeb22012-03-06 11:30:57 -08003721 sleepTime = 0;
3722 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07003723}
3724
3725// getTrackName_l() must be called with ThreadBase::mLock held
Jean-Michel Trivi7d5b2622012-04-04 18:54:36 -07003726int AudioFlinger::DirectOutputThread::getTrackName_l(audio_channel_mask_t channelMask)
Mathias Agopian65ab4712010-07-14 17:59:35 -07003727{
3728 return 0;
3729}
3730
3731// deleteTrackName_l() must be called with ThreadBase::mLock held
3732void AudioFlinger::DirectOutputThread::deleteTrackName_l(int name)
3733{
3734}
3735
3736// checkForNewParameters_l() must be called with ThreadBase::mLock held
3737bool AudioFlinger::DirectOutputThread::checkForNewParameters_l()
3738{
3739 bool reconfig = false;
3740
3741 while (!mNewParameters.isEmpty()) {
3742 status_t status = NO_ERROR;
3743 String8 keyValuePair = mNewParameters[0];
3744 AudioParameter param = AudioParameter(keyValuePair);
3745 int value;
3746
3747 if (param.getInt(String8(AudioParameter::keyFrameCount), value) == NO_ERROR) {
3748 // do not accept frame count changes if tracks are open as the track buffer
3749 // size depends on frame count and correct behavior would not be garantied
3750 // if frame count is changed after track creation
3751 if (!mTracks.isEmpty()) {
3752 status = INVALID_OPERATION;
3753 } else {
3754 reconfig = true;
3755 }
3756 }
3757 if (status == NO_ERROR) {
Dima Zavin799a70e2011-04-18 16:57:27 -07003758 status = mOutput->stream->common.set_parameters(&mOutput->stream->common,
Dima Zavinfce7a472011-04-19 22:30:36 -07003759 keyValuePair.string());
Mathias Agopian65ab4712010-07-14 17:59:35 -07003760 if (!mStandby && status == INVALID_OPERATION) {
Glenn Kastene53b9ea2012-03-12 16:29:55 -07003761 mOutput->stream->common.standby(&mOutput->stream->common);
3762 mStandby = true;
3763 mBytesWritten = 0;
3764 status = mOutput->stream->common.set_parameters(&mOutput->stream->common,
Dima Zavinfce7a472011-04-19 22:30:36 -07003765 keyValuePair.string());
Mathias Agopian65ab4712010-07-14 17:59:35 -07003766 }
3767 if (status == NO_ERROR && reconfig) {
3768 readOutputParameters();
3769 sendConfigEvent_l(AudioSystem::OUTPUT_CONFIG_CHANGED);
3770 }
3771 }
3772
3773 mNewParameters.removeAt(0);
3774
3775 mParamStatus = status;
3776 mParamCond.signal();
Eric Laurent60cd0a02011-09-13 11:40:21 -07003777 // wait for condition with time out in case the thread calling ThreadBase::setParameters()
3778 // already timed out waiting for the status and will never signal the condition.
Glenn Kasten7dede872011-12-13 11:04:14 -08003779 mWaitWorkCV.waitRelative(mLock, kSetParametersTimeoutNs);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003780 }
3781 return reconfig;
3782}
3783
Glenn Kasten0bf65bd2012-02-28 18:32:53 -08003784uint32_t AudioFlinger::DirectOutputThread::activeSleepTimeUs() const
Mathias Agopian65ab4712010-07-14 17:59:35 -07003785{
3786 uint32_t time;
Dima Zavinfce7a472011-04-19 22:30:36 -07003787 if (audio_is_linear_pcm(mFormat)) {
Eric Laurent162b40b2011-12-05 09:47:19 -08003788 time = PlaybackThread::activeSleepTimeUs();
Mathias Agopian65ab4712010-07-14 17:59:35 -07003789 } else {
3790 time = 10000;
3791 }
3792 return time;
3793}
3794
Glenn Kasten0bf65bd2012-02-28 18:32:53 -08003795uint32_t AudioFlinger::DirectOutputThread::idleSleepTimeUs() 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 Laurent60e18242010-07-29 06:50:24 -07003799 time = (uint32_t)(((mFrameCount * 1000) / mSampleRate) * 1000) / 2;
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::suspendSleepTimeUs() const
Eric Laurent25cbe0e2010-08-18 18:13:17 -07003807{
3808 uint32_t time;
Dima Zavinfce7a472011-04-19 22:30:36 -07003809 if (audio_is_linear_pcm(mFormat)) {
Eric Laurent25cbe0e2010-08-18 18:13:17 -07003810 time = (uint32_t)(((mFrameCount * 1000) / mSampleRate) * 1000);
3811 } else {
3812 time = 10000;
3813 }
3814 return time;
3815}
3816
Glenn Kasten66fcab92012-02-24 14:59:21 -08003817void AudioFlinger::DirectOutputThread::cacheParameters_l()
3818{
3819 PlaybackThread::cacheParameters_l();
3820
3821 // use shorter standby delay as on normal output to release
3822 // hardware resources as soon as possible
3823 standbyDelay = microseconds(activeSleepTime*2);
3824}
Eric Laurent25cbe0e2010-08-18 18:13:17 -07003825
Mathias Agopian65ab4712010-07-14 17:59:35 -07003826// ----------------------------------------------------------------------------
3827
Glenn Kasten23bb8be2012-01-26 10:38:26 -08003828AudioFlinger::DuplicatingThread::DuplicatingThread(const sp<AudioFlinger>& audioFlinger,
Glenn Kasten72ef00d2012-01-17 11:09:42 -08003829 AudioFlinger::MixerThread* mainThread, audio_io_handle_t id)
Glenn Kasten23bb8be2012-01-26 10:38:26 -08003830 : MixerThread(audioFlinger, mainThread->getOutput(), id, mainThread->device(), DUPLICATING),
3831 mWaitTimeMs(UINT_MAX)
Mathias Agopian65ab4712010-07-14 17:59:35 -07003832{
Mathias Agopian65ab4712010-07-14 17:59:35 -07003833 addOutputTrack(mainThread);
3834}
3835
3836AudioFlinger::DuplicatingThread::~DuplicatingThread()
3837{
3838 for (size_t i = 0; i < mOutputTracks.size(); i++) {
3839 mOutputTracks[i]->destroy();
3840 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07003841}
3842
Glenn Kasten000f0e32012-03-01 17:10:56 -08003843void AudioFlinger::DuplicatingThread::threadLoop_mix()
Mathias Agopian65ab4712010-07-14 17:59:35 -07003844{
Glenn Kasten952eeb22012-03-06 11:30:57 -08003845 // mix buffers...
3846 if (outputsReady(outputTracks)) {
3847 mAudioMixer->process(AudioBufferProvider::kInvalidPTS);
3848 } else {
3849 memset(mMixBuffer, 0, mixBufferSize);
3850 }
3851 sleepTime = 0;
Glenn Kasten58912562012-04-03 10:45:00 -07003852 writeFrames = mNormalFrameCount;
Glenn Kasten000f0e32012-03-01 17:10:56 -08003853}
3854
3855void AudioFlinger::DuplicatingThread::threadLoop_sleepTime()
3856{
Glenn Kasten952eeb22012-03-06 11:30:57 -08003857 if (sleepTime == 0) {
Glenn Kastenfec279f2012-03-08 07:47:15 -08003858 if (mMixerStatus == MIXER_TRACKS_ENABLED) {
Glenn Kasten952eeb22012-03-06 11:30:57 -08003859 sleepTime = activeSleepTime;
3860 } else {
3861 sleepTime = idleSleepTime;
3862 }
3863 } else if (mBytesWritten != 0) {
3864 // flush remaining overflow buffers in output tracks
3865 for (size_t i = 0; i < outputTracks.size(); i++) {
3866 if (outputTracks[i]->isActive()) {
3867 sleepTime = 0;
3868 writeFrames = 0;
3869 memset(mMixBuffer, 0, mixBufferSize);
3870 break;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003871 }
Glenn Kasten952eeb22012-03-06 11:30:57 -08003872 }
3873 }
Glenn Kasten000f0e32012-03-01 17:10:56 -08003874}
Mathias Agopian65ab4712010-07-14 17:59:35 -07003875
Glenn Kasten000f0e32012-03-01 17:10:56 -08003876void AudioFlinger::DuplicatingThread::threadLoop_write()
3877{
Glenn Kasten66fcab92012-02-24 14:59:21 -08003878 standbyTime = systemTime() + standbyDelay;
Glenn Kasten952eeb22012-03-06 11:30:57 -08003879 for (size_t i = 0; i < outputTracks.size(); i++) {
3880 outputTracks[i]->write(mMixBuffer, writeFrames);
3881 }
3882 mBytesWritten += mixBufferSize;
Glenn Kasten000f0e32012-03-01 17:10:56 -08003883}
Glenn Kasten688a6402012-02-29 07:57:06 -08003884
Glenn Kasten000f0e32012-03-01 17:10:56 -08003885void AudioFlinger::DuplicatingThread::threadLoop_standby()
3886{
Glenn Kasten952eeb22012-03-06 11:30:57 -08003887 // DuplicatingThread implements standby by stopping all tracks
3888 for (size_t i = 0; i < outputTracks.size(); i++) {
3889 outputTracks[i]->stop();
3890 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07003891}
3892
Glenn Kastenfa26a852012-03-06 11:28:04 -08003893void AudioFlinger::DuplicatingThread::saveOutputTracks()
3894{
3895 outputTracks = mOutputTracks;
3896}
3897
3898void AudioFlinger::DuplicatingThread::clearOutputTracks()
3899{
3900 outputTracks.clear();
3901}
3902
Mathias Agopian65ab4712010-07-14 17:59:35 -07003903void AudioFlinger::DuplicatingThread::addOutputTrack(MixerThread *thread)
3904{
Glenn Kastenb6b74062012-02-24 14:12:20 -08003905 Mutex::Autolock _l(mLock);
Glenn Kasten99e53b82012-01-19 08:59:58 -08003906 // FIXME explain this formula
Glenn Kasten58912562012-04-03 10:45:00 -07003907 int frameCount = (3 * mNormalFrameCount * mSampleRate) / thread->sampleRate();
Glenn Kasten9eaa5572012-01-20 13:32:16 -08003908 OutputTrack *outputTrack = new OutputTrack(thread,
Mathias Agopian65ab4712010-07-14 17:59:35 -07003909 this,
3910 mSampleRate,
3911 mFormat,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07003912 mChannelMask,
Mathias Agopian65ab4712010-07-14 17:59:35 -07003913 frameCount);
3914 if (outputTrack->cblk() != NULL) {
Dima Zavinfce7a472011-04-19 22:30:36 -07003915 thread->setStreamVolume(AUDIO_STREAM_CNT, 1.0f);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003916 mOutputTracks.add(outputTrack);
Steve Block3856b092011-10-20 11:56:00 +01003917 ALOGV("addOutputTrack() track %p, on thread %p", outputTrack, thread);
Glenn Kasten438b0362012-03-06 11:24:48 -08003918 updateWaitTime_l();
Mathias Agopian65ab4712010-07-14 17:59:35 -07003919 }
3920}
3921
3922void AudioFlinger::DuplicatingThread::removeOutputTrack(MixerThread *thread)
3923{
3924 Mutex::Autolock _l(mLock);
3925 for (size_t i = 0; i < mOutputTracks.size(); i++) {
Glenn Kastena1117922012-01-26 10:53:32 -08003926 if (mOutputTracks[i]->thread() == thread) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07003927 mOutputTracks[i]->destroy();
3928 mOutputTracks.removeAt(i);
Glenn Kasten438b0362012-03-06 11:24:48 -08003929 updateWaitTime_l();
Mathias Agopian65ab4712010-07-14 17:59:35 -07003930 return;
3931 }
3932 }
Steve Block3856b092011-10-20 11:56:00 +01003933 ALOGV("removeOutputTrack(): unkonwn thread: %p", thread);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003934}
3935
Glenn Kasten438b0362012-03-06 11:24:48 -08003936// caller must hold mLock
3937void AudioFlinger::DuplicatingThread::updateWaitTime_l()
Mathias Agopian65ab4712010-07-14 17:59:35 -07003938{
3939 mWaitTimeMs = UINT_MAX;
3940 for (size_t i = 0; i < mOutputTracks.size(); i++) {
3941 sp<ThreadBase> strong = mOutputTracks[i]->thread().promote();
Glenn Kasten7378ca52012-01-20 13:44:40 -08003942 if (strong != 0) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07003943 uint32_t waitTimeMs = (strong->frameCount() * 2 * 1000) / strong->sampleRate();
3944 if (waitTimeMs < mWaitTimeMs) {
3945 mWaitTimeMs = waitTimeMs;
3946 }
3947 }
3948 }
3949}
3950
3951
Glenn Kasten02fe1bf2012-02-24 15:42:17 -08003952bool AudioFlinger::DuplicatingThread::outputsReady(const SortedVector< sp<OutputTrack> > &outputTracks)
Mathias Agopian65ab4712010-07-14 17:59:35 -07003953{
3954 for (size_t i = 0; i < outputTracks.size(); i++) {
Glenn Kastene53b9ea2012-03-12 16:29:55 -07003955 sp<ThreadBase> thread = outputTracks[i]->thread().promote();
Mathias Agopian65ab4712010-07-14 17:59:35 -07003956 if (thread == 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00003957 ALOGW("DuplicatingThread::outputsReady() could not promote thread on output track %p", outputTracks[i].get());
Mathias Agopian65ab4712010-07-14 17:59:35 -07003958 return false;
3959 }
3960 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
3961 if (playbackThread->standby() && !playbackThread->isSuspended()) {
Steve Block3856b092011-10-20 11:56:00 +01003962 ALOGV("DuplicatingThread output track %p on thread %p Not Ready", outputTracks[i].get(), thread.get());
Mathias Agopian65ab4712010-07-14 17:59:35 -07003963 return false;
3964 }
3965 }
3966 return true;
3967}
3968
Glenn Kasten0bf65bd2012-02-28 18:32:53 -08003969uint32_t AudioFlinger::DuplicatingThread::activeSleepTimeUs() const
Mathias Agopian65ab4712010-07-14 17:59:35 -07003970{
3971 return (mWaitTimeMs * 1000) / 2;
3972}
3973
Glenn Kasten66fcab92012-02-24 14:59:21 -08003974void AudioFlinger::DuplicatingThread::cacheParameters_l()
3975{
3976 // updateWaitTime_l() sets mWaitTimeMs, which affects activeSleepTimeUs(), so call it first
3977 updateWaitTime_l();
3978
3979 MixerThread::cacheParameters_l();
3980}
3981
Mathias Agopian65ab4712010-07-14 17:59:35 -07003982// ----------------------------------------------------------------------------
3983
3984// TrackBase constructor must be called with AudioFlinger::mLock held
3985AudioFlinger::ThreadBase::TrackBase::TrackBase(
Glenn Kasten9eaa5572012-01-20 13:32:16 -08003986 ThreadBase *thread,
Mathias Agopian65ab4712010-07-14 17:59:35 -07003987 const sp<Client>& client,
3988 uint32_t sampleRate,
Glenn Kasten58f30212012-01-12 12:27:51 -08003989 audio_format_t format,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07003990 uint32_t channelMask,
Mathias Agopian65ab4712010-07-14 17:59:35 -07003991 int frameCount,
Mathias Agopian65ab4712010-07-14 17:59:35 -07003992 const sp<IMemory>& sharedBuffer,
3993 int sessionId)
3994 : RefBase(),
3995 mThread(thread),
3996 mClient(client),
Glenn Kasten84afa3b2012-01-25 15:28:08 -08003997 mCblk(NULL),
3998 // mBuffer
3999 // mBufferEnd
Mathias Agopian65ab4712010-07-14 17:59:35 -07004000 mFrameCount(0),
4001 mState(IDLE),
Glenn Kasten58912562012-04-03 10:45:00 -07004002 mSampleRate(sampleRate),
Mathias Agopian65ab4712010-07-14 17:59:35 -07004003 mFormat(format),
Glenn Kasten5cf034d2012-02-21 10:35:56 -08004004 mStepServerFailed(false),
Mathias Agopian65ab4712010-07-14 17:59:35 -07004005 mSessionId(sessionId)
Glenn Kasten84afa3b2012-01-25 15:28:08 -08004006 // mChannelCount
4007 // mChannelMask
Mathias Agopian65ab4712010-07-14 17:59:35 -07004008{
Steve Block3856b092011-10-20 11:56:00 +01004009 ALOGV_IF(sharedBuffer != 0, "sharedBuffer: %p, size: %d", sharedBuffer->pointer(), sharedBuffer->size());
Mathias Agopian65ab4712010-07-14 17:59:35 -07004010
Steve Blockb8a80522011-12-20 16:23:08 +00004011 // ALOGD("Creating track with %d buffers @ %d bytes", bufferCount, bufferSize);
Glenn Kastene53b9ea2012-03-12 16:29:55 -07004012 size_t size = sizeof(audio_track_cblk_t);
4013 uint8_t channelCount = popcount(channelMask);
4014 size_t bufferSize = frameCount*channelCount*sizeof(int16_t);
4015 if (sharedBuffer == 0) {
4016 size += bufferSize;
4017 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07004018
Glenn Kastene53b9ea2012-03-12 16:29:55 -07004019 if (client != NULL) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07004020 mCblkMemory = client->heap()->allocate(size);
4021 if (mCblkMemory != 0) {
4022 mCblk = static_cast<audio_track_cblk_t *>(mCblkMemory->pointer());
Glenn Kastena0d68332012-01-27 16:47:15 -08004023 if (mCblk != NULL) { // construct the shared structure in-place.
Mathias Agopian65ab4712010-07-14 17:59:35 -07004024 new(mCblk) audio_track_cblk_t();
4025 // clear all buffers
4026 mCblk->frameCount = frameCount;
4027 mCblk->sampleRate = sampleRate;
Marco Nelissena1472d92012-03-30 14:36:54 -07004028// uncomment the following lines to quickly test 32-bit wraparound
4029// mCblk->user = 0xffff0000;
4030// mCblk->server = 0xffff0000;
4031// mCblk->userBase = 0xffff0000;
4032// mCblk->serverBase = 0xffff0000;
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07004033 mChannelCount = channelCount;
4034 mChannelMask = channelMask;
Mathias Agopian65ab4712010-07-14 17:59:35 -07004035 if (sharedBuffer == 0) {
4036 mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t);
4037 memset(mBuffer, 0, frameCount*channelCount*sizeof(int16_t));
4038 // Force underrun condition to avoid false underrun callback until first data is
Eric Laurent44d98482010-09-30 16:12:31 -07004039 // written to buffer (other flags are cleared)
Mathias Agopian65ab4712010-07-14 17:59:35 -07004040 mCblk->flags = CBLK_UNDERRUN_ON;
4041 } else {
4042 mBuffer = sharedBuffer->pointer();
4043 }
4044 mBufferEnd = (uint8_t *)mBuffer + bufferSize;
4045 }
4046 } else {
Steve Block29357bc2012-01-06 19:20:56 +00004047 ALOGE("not enough memory for AudioTrack size=%u", size);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004048 client->heap()->dump("AudioTrack");
4049 return;
4050 }
Glenn Kastene53b9ea2012-03-12 16:29:55 -07004051 } else {
4052 mCblk = (audio_track_cblk_t *)(new uint8_t[size]);
Glenn Kastenea7939a2012-03-14 12:56:26 -07004053 // construct the shared structure in-place.
4054 new(mCblk) audio_track_cblk_t();
4055 // clear all buffers
4056 mCblk->frameCount = frameCount;
4057 mCblk->sampleRate = sampleRate;
Marco Nelissena1472d92012-03-30 14:36:54 -07004058// uncomment the following lines to quickly test 32-bit wraparound
4059// mCblk->user = 0xffff0000;
4060// mCblk->server = 0xffff0000;
4061// mCblk->userBase = 0xffff0000;
4062// mCblk->serverBase = 0xffff0000;
Glenn Kastenea7939a2012-03-14 12:56:26 -07004063 mChannelCount = channelCount;
4064 mChannelMask = channelMask;
4065 mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t);
4066 memset(mBuffer, 0, frameCount*channelCount*sizeof(int16_t));
4067 // Force underrun condition to avoid false underrun callback until first data is
4068 // written to buffer (other flags are cleared)
4069 mCblk->flags = CBLK_UNDERRUN_ON;
4070 mBufferEnd = (uint8_t *)mBuffer + bufferSize;
Glenn Kastene53b9ea2012-03-12 16:29:55 -07004071 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07004072}
4073
4074AudioFlinger::ThreadBase::TrackBase::~TrackBase()
4075{
Glenn Kastena0d68332012-01-27 16:47:15 -08004076 if (mCblk != NULL) {
Glenn Kasten1a0ae5b2012-02-03 10:24:48 -08004077 if (mClient == 0) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07004078 delete mCblk;
Glenn Kasten1a0ae5b2012-02-03 10:24:48 -08004079 } else {
4080 mCblk->~audio_track_cblk_t(); // destroy our shared-structure.
Mathias Agopian65ab4712010-07-14 17:59:35 -07004081 }
4082 }
Glenn Kastendbfafaf2012-01-25 15:27:15 -08004083 mCblkMemory.clear(); // free the shared memory before releasing the heap it belongs to
Glenn Kasten7378ca52012-01-20 13:44:40 -08004084 if (mClient != 0) {
Glenn Kasten84afa3b2012-01-25 15:28:08 -08004085 // Client destructor must run with AudioFlinger mutex locked
Mathias Agopian65ab4712010-07-14 17:59:35 -07004086 Mutex::Autolock _l(mClient->audioFlinger()->mLock);
Glenn Kasten7378ca52012-01-20 13:44:40 -08004087 // If the client's reference count drops to zero, the associated destructor
4088 // must run with AudioFlinger lock held. Thus the explicit clear() rather than
4089 // relying on the automatic clear() at end of scope.
Mathias Agopian65ab4712010-07-14 17:59:35 -07004090 mClient.clear();
4091 }
4092}
4093
Glenn Kasten01c4ebf2012-02-22 10:47:35 -08004094// AudioBufferProvider interface
4095// getNextBuffer() = 0;
4096// This implementation of releaseBuffer() is used by Track and RecordTrack, but not TimedTrack
Mathias Agopian65ab4712010-07-14 17:59:35 -07004097void AudioFlinger::ThreadBase::TrackBase::releaseBuffer(AudioBufferProvider::Buffer* buffer)
4098{
Glenn Kastene0feee32011-12-13 11:53:26 -08004099 buffer->raw = NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -07004100 mFrameCount = buffer->frameCount;
Glenn Kasten288ed212012-04-25 17:52:27 -07004101 // FIXME See note at getNextBuffer()
Glenn Kasten01c4ebf2012-02-22 10:47:35 -08004102 (void) step(); // ignore return value of step()
Mathias Agopian65ab4712010-07-14 17:59:35 -07004103 buffer->frameCount = 0;
4104}
4105
4106bool AudioFlinger::ThreadBase::TrackBase::step() {
4107 bool result;
4108 audio_track_cblk_t* cblk = this->cblk();
4109
4110 result = cblk->stepServer(mFrameCount);
4111 if (!result) {
Steve Block3856b092011-10-20 11:56:00 +01004112 ALOGV("stepServer failed acquiring cblk mutex");
Glenn Kasten5cf034d2012-02-21 10:35:56 -08004113 mStepServerFailed = true;
Mathias Agopian65ab4712010-07-14 17:59:35 -07004114 }
4115 return result;
4116}
4117
4118void AudioFlinger::ThreadBase::TrackBase::reset() {
4119 audio_track_cblk_t* cblk = this->cblk();
4120
4121 cblk->user = 0;
4122 cblk->server = 0;
4123 cblk->userBase = 0;
4124 cblk->serverBase = 0;
Glenn Kasten5cf034d2012-02-21 10:35:56 -08004125 mStepServerFailed = false;
Steve Block3856b092011-10-20 11:56:00 +01004126 ALOGV("TrackBase::reset");
Mathias Agopian65ab4712010-07-14 17:59:35 -07004127}
4128
Mathias Agopian65ab4712010-07-14 17:59:35 -07004129int AudioFlinger::ThreadBase::TrackBase::sampleRate() const {
4130 return (int)mCblk->sampleRate;
4131}
4132
Mathias Agopian65ab4712010-07-14 17:59:35 -07004133void* AudioFlinger::ThreadBase::TrackBase::getBuffer(uint32_t offset, uint32_t frames) const {
4134 audio_track_cblk_t* cblk = this->cblk();
Glenn Kastenb9980652012-01-11 09:48:27 -08004135 size_t frameSize = cblk->frameSize;
4136 int8_t *bufferStart = (int8_t *)mBuffer + (offset-cblk->serverBase)*frameSize;
4137 int8_t *bufferEnd = bufferStart + frames * frameSize;
Mathias Agopian65ab4712010-07-14 17:59:35 -07004138
4139 // Check validity of returned pointer in case the track control block would have been corrupted.
Jean-Michel Triviacb86cc2012-04-16 12:43:57 -07004140 ALOG_ASSERT(!(bufferStart < mBuffer || bufferStart > bufferEnd || bufferEnd > mBufferEnd),
4141 "TrackBase::getBuffer buffer out of range:\n"
4142 " start: %p, end %p , mBuffer %p mBufferEnd %p\n"
4143 " server %u, serverBase %u, user %u, userBase %u, frameSize %d",
Mathias Agopian65ab4712010-07-14 17:59:35 -07004144 bufferStart, bufferEnd, mBuffer, mBufferEnd,
Jean-Michel Triviacb86cc2012-04-16 12:43:57 -07004145 cblk->server, cblk->serverBase, cblk->user, cblk->userBase, frameSize);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004146
4147 return bufferStart;
4148}
4149
Eric Laurenta011e352012-03-29 15:51:43 -07004150status_t AudioFlinger::ThreadBase::TrackBase::setSyncEvent(const sp<SyncEvent>& event)
4151{
4152 mSyncEvents.add(event);
4153 return NO_ERROR;
4154}
4155
Mathias Agopian65ab4712010-07-14 17:59:35 -07004156// ----------------------------------------------------------------------------
4157
4158// Track constructor must be called with AudioFlinger::mLock and ThreadBase::mLock held
4159AudioFlinger::PlaybackThread::Track::Track(
Glenn Kasten9eaa5572012-01-20 13:32:16 -08004160 PlaybackThread *thread,
Mathias Agopian65ab4712010-07-14 17:59:35 -07004161 const sp<Client>& client,
Glenn Kastenfff6d712012-01-12 16:38:12 -08004162 audio_stream_type_t streamType,
Mathias Agopian65ab4712010-07-14 17:59:35 -07004163 uint32_t sampleRate,
Glenn Kasten58f30212012-01-12 12:27:51 -08004164 audio_format_t format,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07004165 uint32_t channelMask,
Mathias Agopian65ab4712010-07-14 17:59:35 -07004166 int frameCount,
4167 const sp<IMemory>& sharedBuffer,
Glenn Kasten73d22752012-03-19 13:38:30 -07004168 int sessionId,
4169 IAudioFlinger::track_flags_t flags)
Glenn Kasten5cf034d2012-02-21 10:35:56 -08004170 : TrackBase(thread, client, sampleRate, format, channelMask, frameCount, sharedBuffer, sessionId),
Glenn Kastenf9959012012-03-19 11:14:37 -07004171 mMute(false),
Glenn Kasten58912562012-04-03 10:45:00 -07004172 mFillingUpStatus(FS_INVALID),
Glenn Kastenf9959012012-03-19 11:14:37 -07004173 // mRetryCount initialized later when needed
4174 mSharedBuffer(sharedBuffer),
4175 mStreamType(streamType),
4176 mName(-1), // see note below
4177 mMainBuffer(thread->mixBuffer()),
4178 mAuxBuffer(NULL),
Eric Laurenta011e352012-03-29 15:51:43 -07004179 mAuxEffectId(0), mHasVolumeController(false),
Glenn Kasten73d22752012-03-19 13:38:30 -07004180 mPresentationCompleteFrames(0),
Glenn Kasten58912562012-04-03 10:45:00 -07004181 mFlags(flags),
4182 mFastIndex(-1),
Glenn Kasten288ed212012-04-25 17:52:27 -07004183 mUnderrunCount(0),
Glenn Kasten58912562012-04-03 10:45:00 -07004184 mCachedVolume(1.0)
Mathias Agopian65ab4712010-07-14 17:59:35 -07004185{
4186 if (mCblk != NULL) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07004187 // NOTE: audio_track_cblk_t::frameSize for 8 bit PCM data is based on a sample size of
4188 // 16 bit because data is converted to 16 bit before being stored in buffer by AudioTrack
Eric Laurentedc15ad2011-07-21 19:35:01 -07004189 mCblk->frameSize = audio_is_linear_pcm(format) ? mChannelCount * sizeof(int16_t) : sizeof(uint8_t);
Glenn Kasten58912562012-04-03 10:45:00 -07004190 if (flags & IAudioFlinger::TRACK_FAST) {
4191 mCblk->flags |= CBLK_FAST; // atomic op not needed yet
4192 ALOG_ASSERT(thread->mFastTrackAvailMask != 0);
4193 int i = __builtin_ctz(thread->mFastTrackAvailMask);
Eric Laurent29864602012-05-08 18:57:51 -07004194 ALOG_ASSERT(0 < i && i < (int)FastMixerState::kMaxFastTracks);
Glenn Kasten288ed212012-04-25 17:52:27 -07004195 // FIXME This is too eager. We allocate a fast track index before the
4196 // fast track becomes active. Since fast tracks are a scarce resource,
4197 // this means we are potentially denying other more important fast tracks from
4198 // being created. It would be better to allocate the index dynamically.
Glenn Kasten58912562012-04-03 10:45:00 -07004199 mFastIndex = i;
Glenn Kasten288ed212012-04-25 17:52:27 -07004200 // Read the initial underruns because this field is never cleared by the fast mixer
Glenn Kasten09474df2012-05-10 14:48:07 -07004201 mObservedUnderruns = thread->getFastTrackUnderruns(i);
Glenn Kasten58912562012-04-03 10:45:00 -07004202 thread->mFastTrackAvailMask &= ~(1 << i);
Glenn Kasten58912562012-04-03 10:45:00 -07004203 }
Glenn Kastenf9959012012-03-19 11:14:37 -07004204 // to avoid leaking a track name, do not allocate one unless there is an mCblk
Jean-Michel Trivi7d5b2622012-04-04 18:54:36 -07004205 mName = thread->getTrackName_l((audio_channel_mask_t)channelMask);
Glenn Kastenf9959012012-03-19 11:14:37 -07004206 if (mName < 0) {
4207 ALOGE("no more track names available");
Glenn Kasten288ed212012-04-25 17:52:27 -07004208 // FIXME bug - if sufficient fast track indices, but insufficient normal mixer names,
4209 // then we leak a fast track index. Should swap these two sections, or better yet
4210 // only allocate a normal mixer name for normal tracks.
Glenn Kastenf9959012012-03-19 11:14:37 -07004211 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07004212 }
Glenn Kastenf9959012012-03-19 11:14:37 -07004213 ALOGV("Track constructor name %d, calling pid %d", mName, IPCThreadState::self()->getCallingPid());
Mathias Agopian65ab4712010-07-14 17:59:35 -07004214}
4215
4216AudioFlinger::PlaybackThread::Track::~Track()
4217{
Steve Block3856b092011-10-20 11:56:00 +01004218 ALOGV("PlaybackThread::Track destructor");
Mathias Agopian65ab4712010-07-14 17:59:35 -07004219 sp<ThreadBase> thread = mThread.promote();
4220 if (thread != 0) {
4221 Mutex::Autolock _l(thread->mLock);
4222 mState = TERMINATED;
4223 }
4224}
4225
4226void AudioFlinger::PlaybackThread::Track::destroy()
4227{
4228 // NOTE: destroyTrack_l() can remove a strong reference to this Track
4229 // by removing it from mTracks vector, so there is a risk that this Tracks's
Glenn Kasten99e53b82012-01-19 08:59:58 -08004230 // destructor is called. As the destructor needs to lock mLock,
Mathias Agopian65ab4712010-07-14 17:59:35 -07004231 // we must acquire a strong reference on this Track before locking mLock
4232 // here so that the destructor is called only when exiting this function.
4233 // On the other hand, as long as Track::destroy() is only called by
4234 // TrackHandle destructor, the TrackHandle still holds a strong ref on
4235 // this Track with its member mTrack.
4236 sp<Track> keep(this);
4237 { // scope for mLock
4238 sp<ThreadBase> thread = mThread.promote();
4239 if (thread != 0) {
4240 if (!isOutputTrack()) {
4241 if (mState == ACTIVE || mState == RESUMING) {
Glenn Kasten02bbd202012-02-08 12:35:35 -08004242 AudioSystem::stopOutput(thread->id(), mStreamType, mSessionId);
Gloria Wang9ee159b2011-02-24 14:51:45 -08004243
Glenn Kastend3cee2f2012-03-13 17:55:35 -07004244#ifdef ADD_BATTERY_DATA
Gloria Wang9ee159b2011-02-24 14:51:45 -08004245 // to track the speaker usage
4246 addBatteryData(IMediaPlayerService::kBatteryDataAudioFlingerStop);
Glenn Kastend3cee2f2012-03-13 17:55:35 -07004247#endif
Mathias Agopian65ab4712010-07-14 17:59:35 -07004248 }
4249 AudioSystem::releaseOutput(thread->id());
4250 }
4251 Mutex::Autolock _l(thread->mLock);
4252 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
4253 playbackThread->destroyTrack_l(this);
4254 }
4255 }
4256}
4257
Glenn Kasten288ed212012-04-25 17:52:27 -07004258/*static*/ void AudioFlinger::PlaybackThread::Track::appendDumpHeader(String8& result)
4259{
Glenn Kastene213c862012-04-25 13:46:15 -07004260 result.append(" Name Client Type Fmt Chn mask Session mFrCnt fCount S M F SRate L dB R dB "
4261 " Server User Main buf Aux Buf Flags FastUnder\n");
Glenn Kasten288ed212012-04-25 17:52:27 -07004262}
4263
Mathias Agopian65ab4712010-07-14 17:59:35 -07004264void AudioFlinger::PlaybackThread::Track::dump(char* buffer, size_t size)
4265{
Glenn Kasten83d86532012-01-17 14:39:34 -08004266 uint32_t vlr = mCblk->getVolumeLR();
Glenn Kasten58912562012-04-03 10:45:00 -07004267 if (isFastTrack()) {
Glenn Kasten288ed212012-04-25 17:52:27 -07004268 sprintf(buffer, " F %2d", mFastIndex);
Glenn Kasten58912562012-04-03 10:45:00 -07004269 } else {
4270 sprintf(buffer, " %4d", mName - AudioMixer::TRACK0);
4271 }
Glenn Kasten288ed212012-04-25 17:52:27 -07004272 track_state state = mState;
4273 char stateChar;
4274 switch (state) {
4275 case IDLE:
4276 stateChar = 'I';
4277 break;
4278 case TERMINATED:
4279 stateChar = 'T';
4280 break;
Glenn Kastend08f48c2012-05-01 18:14:02 -07004281 case STOPPING_1:
4282 stateChar = 's';
4283 break;
4284 case STOPPING_2:
4285 stateChar = '5';
4286 break;
Glenn Kasten288ed212012-04-25 17:52:27 -07004287 case STOPPED:
4288 stateChar = 'S';
4289 break;
4290 case RESUMING:
4291 stateChar = 'R';
4292 break;
4293 case ACTIVE:
4294 stateChar = 'A';
4295 break;
4296 case PAUSING:
4297 stateChar = 'p';
4298 break;
4299 case PAUSED:
4300 stateChar = 'P';
4301 break;
Eric Laurent29864602012-05-08 18:57:51 -07004302 case FLUSHED:
4303 stateChar = 'F';
4304 break;
Glenn Kasten288ed212012-04-25 17:52:27 -07004305 default:
4306 stateChar = '?';
4307 break;
4308 }
Glenn Kasten09474df2012-05-10 14:48:07 -07004309 char nowInUnderrun;
4310 switch (mObservedUnderruns.mBitFields.mMostRecent) {
4311 case UNDERRUN_FULL:
4312 nowInUnderrun = ' ';
4313 break;
4314 case UNDERRUN_PARTIAL:
4315 nowInUnderrun = '<';
4316 break;
4317 case UNDERRUN_EMPTY:
4318 nowInUnderrun = '*';
4319 break;
4320 default:
4321 nowInUnderrun = '?';
4322 break;
4323 }
Glenn Kastene213c862012-04-25 13:46:15 -07004324 snprintf(&buffer[7], size-7, " %6d %4u %3u 0x%08x %7u %6u %6u %1c %1d %1d %5u %5.2g %5.2g "
4325 "0x%08x 0x%08x 0x%08x 0x%08x %#5x %9u%c\n",
Glenn Kasten44deb052012-02-05 18:09:08 -08004326 (mClient == 0) ? getpid_cached : mClient->pid(),
Mathias Agopian65ab4712010-07-14 17:59:35 -07004327 mStreamType,
4328 mFormat,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07004329 mChannelMask,
Mathias Agopian65ab4712010-07-14 17:59:35 -07004330 mSessionId,
4331 mFrameCount,
Glenn Kastene213c862012-04-25 13:46:15 -07004332 mCblk->frameCount,
Glenn Kasten288ed212012-04-25 17:52:27 -07004333 stateChar,
Mathias Agopian65ab4712010-07-14 17:59:35 -07004334 mMute,
4335 mFillingUpStatus,
4336 mCblk->sampleRate,
Glenn Kasten58912562012-04-03 10:45:00 -07004337 20.0 * log10((vlr & 0xFFFF) / 4096.0),
4338 20.0 * log10((vlr >> 16) / 4096.0),
Mathias Agopian65ab4712010-07-14 17:59:35 -07004339 mCblk->server,
4340 mCblk->user,
4341 (int)mMainBuffer,
Glenn Kasten288ed212012-04-25 17:52:27 -07004342 (int)mAuxBuffer,
Glenn Kastene213c862012-04-25 13:46:15 -07004343 mCblk->flags,
Glenn Kasten288ed212012-04-25 17:52:27 -07004344 mUnderrunCount,
Glenn Kasten09474df2012-05-10 14:48:07 -07004345 nowInUnderrun);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004346}
4347
Glenn Kasten01c4ebf2012-02-22 10:47:35 -08004348// AudioBufferProvider interface
John Grossman4ff14ba2012-02-08 16:37:41 -08004349status_t AudioFlinger::PlaybackThread::Track::getNextBuffer(
Glenn Kastene53b9ea2012-03-12 16:29:55 -07004350 AudioBufferProvider::Buffer* buffer, int64_t pts)
Mathias Agopian65ab4712010-07-14 17:59:35 -07004351{
Glenn Kastene53b9ea2012-03-12 16:29:55 -07004352 audio_track_cblk_t* cblk = this->cblk();
4353 uint32_t framesReady;
4354 uint32_t framesReq = buffer->frameCount;
Mathias Agopian65ab4712010-07-14 17:59:35 -07004355
Glenn Kastene53b9ea2012-03-12 16:29:55 -07004356 // Check if last stepServer failed, try to step now
4357 if (mStepServerFailed) {
Glenn Kasten288ed212012-04-25 17:52:27 -07004358 // FIXME When called by fast mixer, this takes a mutex with tryLock().
4359 // Since the fast mixer is higher priority than client callback thread,
4360 // it does not result in priority inversion for client.
4361 // But a non-blocking solution would be preferable to avoid
4362 // fast mixer being unable to tryLock(), and
4363 // to avoid the extra context switches if the client wakes up,
4364 // discovers the mutex is locked, then has to wait for fast mixer to unlock.
Glenn Kastene53b9ea2012-03-12 16:29:55 -07004365 if (!step()) goto getNextBuffer_exit;
4366 ALOGV("stepServer recovered");
4367 mStepServerFailed = false;
4368 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07004369
Glenn Kasten288ed212012-04-25 17:52:27 -07004370 // FIXME Same as above
Glenn Kastene53b9ea2012-03-12 16:29:55 -07004371 framesReady = cblk->framesReady();
Mathias Agopian65ab4712010-07-14 17:59:35 -07004372
Glenn Kastene53b9ea2012-03-12 16:29:55 -07004373 if (CC_LIKELY(framesReady)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07004374 uint32_t s = cblk->server;
4375 uint32_t bufferEnd = cblk->serverBase + cblk->frameCount;
4376
4377 bufferEnd = (cblk->loopEnd < bufferEnd) ? cblk->loopEnd : bufferEnd;
4378 if (framesReq > framesReady) {
4379 framesReq = framesReady;
4380 }
Marco Nelissena1472d92012-03-30 14:36:54 -07004381 if (framesReq > bufferEnd - s) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07004382 framesReq = bufferEnd - s;
4383 }
4384
Glenn Kastene53b9ea2012-03-12 16:29:55 -07004385 buffer->raw = getBuffer(s, framesReq);
4386 if (buffer->raw == NULL) goto getNextBuffer_exit;
Mathias Agopian65ab4712010-07-14 17:59:35 -07004387
Glenn Kastene53b9ea2012-03-12 16:29:55 -07004388 buffer->frameCount = framesReq;
Mathias Agopian65ab4712010-07-14 17:59:35 -07004389 return NO_ERROR;
Glenn Kastene53b9ea2012-03-12 16:29:55 -07004390 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07004391
4392getNextBuffer_exit:
Glenn Kastene53b9ea2012-03-12 16:29:55 -07004393 buffer->raw = NULL;
4394 buffer->frameCount = 0;
4395 ALOGV("getNextBuffer() no more data for track %d on thread %p", mName, mThread.unsafe_get());
4396 return NOT_ENOUGH_DATA;
Mathias Agopian65ab4712010-07-14 17:59:35 -07004397}
4398
Glenn Kasten288ed212012-04-25 17:52:27 -07004399// Note that framesReady() takes a mutex on the control block using tryLock().
4400// This could result in priority inversion if framesReady() is called by the normal mixer,
4401// as the normal mixer thread runs at lower
4402// priority than the client's callback thread: there is a short window within framesReady()
4403// during which the normal mixer could be preempted, and the client callback would block.
4404// Another problem can occur if framesReady() is called by the fast mixer:
4405// the tryLock() could block for up to 1 ms, and a sequence of these could delay fast mixer.
4406// FIXME Replace AudioTrackShared control block implementation by a non-blocking FIFO queue.
4407size_t AudioFlinger::PlaybackThread::Track::framesReady() const {
John Grossman4ff14ba2012-02-08 16:37:41 -08004408 return mCblk->framesReady();
4409}
4410
Glenn Kasten288ed212012-04-25 17:52:27 -07004411// Don't call for fast tracks; the framesReady() could result in priority inversion
Mathias Agopian65ab4712010-07-14 17:59:35 -07004412bool AudioFlinger::PlaybackThread::Track::isReady() const {
Eric Laurentaf59ce22010-10-05 14:41:42 -07004413 if (mFillingUpStatus != FS_FILLING || isStopped() || isPausing()) return true;
Mathias Agopian65ab4712010-07-14 17:59:35 -07004414
John Grossman4ff14ba2012-02-08 16:37:41 -08004415 if (framesReady() >= mCblk->frameCount ||
Mathias Agopian65ab4712010-07-14 17:59:35 -07004416 (mCblk->flags & CBLK_FORCEREADY_MSK)) {
4417 mFillingUpStatus = FS_FILLED;
Eric Laurent38ccae22011-03-28 18:37:07 -07004418 android_atomic_and(~CBLK_FORCEREADY_MSK, &mCblk->flags);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004419 return true;
4420 }
4421 return false;
4422}
4423
Glenn Kasten3acbd052012-02-28 10:39:56 -08004424status_t AudioFlinger::PlaybackThread::Track::start(AudioSystem::sync_event_t event,
Eric Laurenta011e352012-03-29 15:51:43 -07004425 int triggerSession)
Mathias Agopian65ab4712010-07-14 17:59:35 -07004426{
4427 status_t status = NO_ERROR;
Glenn Kasten58912562012-04-03 10:45:00 -07004428 ALOGV("start(%d), calling pid %d session %d",
4429 mName, IPCThreadState::self()->getCallingPid(), mSessionId);
Glenn Kasten3acbd052012-02-28 10:39:56 -08004430
Mathias Agopian65ab4712010-07-14 17:59:35 -07004431 sp<ThreadBase> thread = mThread.promote();
4432 if (thread != 0) {
4433 Mutex::Autolock _l(thread->mLock);
Glenn Kastenb853e982012-01-26 13:39:18 -08004434 track_state state = mState;
Mathias Agopian65ab4712010-07-14 17:59:35 -07004435 // here the track could be either new, or restarted
4436 // in both cases "unstop" the track
4437 if (mState == PAUSED) {
4438 mState = TrackBase::RESUMING;
Steve Block3856b092011-10-20 11:56:00 +01004439 ALOGV("PAUSED => RESUMING (%d) on thread %p", mName, this);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004440 } else {
4441 mState = TrackBase::ACTIVE;
Steve Block3856b092011-10-20 11:56:00 +01004442 ALOGV("? => ACTIVE (%d) on thread %p", mName, this);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004443 }
4444
4445 if (!isOutputTrack() && state != ACTIVE && state != RESUMING) {
4446 thread->mLock.unlock();
Glenn Kasten02bbd202012-02-08 12:35:35 -08004447 status = AudioSystem::startOutput(thread->id(), mStreamType, mSessionId);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004448 thread->mLock.lock();
Gloria Wang9ee159b2011-02-24 14:51:45 -08004449
Glenn Kastend3cee2f2012-03-13 17:55:35 -07004450#ifdef ADD_BATTERY_DATA
Gloria Wang9ee159b2011-02-24 14:51:45 -08004451 // to track the speaker usage
4452 if (status == NO_ERROR) {
4453 addBatteryData(IMediaPlayerService::kBatteryDataAudioFlingerStart);
4454 }
Glenn Kastend3cee2f2012-03-13 17:55:35 -07004455#endif
Mathias Agopian65ab4712010-07-14 17:59:35 -07004456 }
4457 if (status == NO_ERROR) {
4458 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
4459 playbackThread->addTrack_l(this);
4460 } else {
4461 mState = state;
Eric Laurent29864602012-05-08 18:57:51 -07004462 triggerEvents(AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004463 }
4464 } else {
4465 status = BAD_VALUE;
4466 }
4467 return status;
4468}
4469
4470void AudioFlinger::PlaybackThread::Track::stop()
4471{
Glenn Kasten23d82a92012-02-03 11:10:00 -08004472 ALOGV("stop(%d), calling pid %d", mName, IPCThreadState::self()->getCallingPid());
Mathias Agopian65ab4712010-07-14 17:59:35 -07004473 sp<ThreadBase> thread = mThread.promote();
4474 if (thread != 0) {
4475 Mutex::Autolock _l(thread->mLock);
Glenn Kastenb853e982012-01-26 13:39:18 -08004476 track_state state = mState;
Glenn Kastend08f48c2012-05-01 18:14:02 -07004477 if (state == RESUMING || state == ACTIVE || state == PAUSING || state == PAUSED) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07004478 // If the track is not active (PAUSED and buffers full), flush buffers
4479 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
4480 if (playbackThread->mActiveTracks.indexOf(this) < 0) {
4481 reset();
Glenn Kastend08f48c2012-05-01 18:14:02 -07004482 mState = STOPPED;
4483 } else if (!isFastTrack()) {
4484 mState = STOPPED;
4485 } else {
4486 // prepareTracks_l() will set state to STOPPING_2 after next underrun,
4487 // and then to STOPPED and reset() when presentation is complete
4488 mState = STOPPING_1;
Mathias Agopian65ab4712010-07-14 17:59:35 -07004489 }
Glenn Kastend08f48c2012-05-01 18:14:02 -07004490 ALOGV("not stopping/stopped => stopping/stopped (%d) on thread %p", mName, playbackThread);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004491 }
4492 if (!isOutputTrack() && (state == ACTIVE || state == RESUMING)) {
4493 thread->mLock.unlock();
Glenn Kasten02bbd202012-02-08 12:35:35 -08004494 AudioSystem::stopOutput(thread->id(), mStreamType, mSessionId);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004495 thread->mLock.lock();
Gloria Wang9ee159b2011-02-24 14:51:45 -08004496
Glenn Kastend3cee2f2012-03-13 17:55:35 -07004497#ifdef ADD_BATTERY_DATA
Gloria Wang9ee159b2011-02-24 14:51:45 -08004498 // to track the speaker usage
4499 addBatteryData(IMediaPlayerService::kBatteryDataAudioFlingerStop);
Glenn Kastend3cee2f2012-03-13 17:55:35 -07004500#endif
Mathias Agopian65ab4712010-07-14 17:59:35 -07004501 }
4502 }
4503}
4504
4505void AudioFlinger::PlaybackThread::Track::pause()
4506{
Glenn Kasten23d82a92012-02-03 11:10:00 -08004507 ALOGV("pause(%d), calling pid %d", mName, IPCThreadState::self()->getCallingPid());
Mathias Agopian65ab4712010-07-14 17:59:35 -07004508 sp<ThreadBase> thread = mThread.promote();
4509 if (thread != 0) {
4510 Mutex::Autolock _l(thread->mLock);
4511 if (mState == ACTIVE || mState == RESUMING) {
4512 mState = PAUSING;
Steve Block3856b092011-10-20 11:56:00 +01004513 ALOGV("ACTIVE/RESUMING => PAUSING (%d) on thread %p", mName, thread.get());
Mathias Agopian65ab4712010-07-14 17:59:35 -07004514 if (!isOutputTrack()) {
4515 thread->mLock.unlock();
Glenn Kasten02bbd202012-02-08 12:35:35 -08004516 AudioSystem::stopOutput(thread->id(), mStreamType, mSessionId);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004517 thread->mLock.lock();
Gloria Wang9ee159b2011-02-24 14:51:45 -08004518
Glenn Kastend3cee2f2012-03-13 17:55:35 -07004519#ifdef ADD_BATTERY_DATA
Gloria Wang9ee159b2011-02-24 14:51:45 -08004520 // to track the speaker usage
4521 addBatteryData(IMediaPlayerService::kBatteryDataAudioFlingerStop);
Glenn Kastend3cee2f2012-03-13 17:55:35 -07004522#endif
Mathias Agopian65ab4712010-07-14 17:59:35 -07004523 }
4524 }
4525 }
4526}
4527
4528void AudioFlinger::PlaybackThread::Track::flush()
4529{
Steve Block3856b092011-10-20 11:56:00 +01004530 ALOGV("flush(%d)", mName);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004531 sp<ThreadBase> thread = mThread.promote();
4532 if (thread != 0) {
4533 Mutex::Autolock _l(thread->mLock);
Glenn Kastend08f48c2012-05-01 18:14:02 -07004534 if (mState != STOPPING_1 && mState != STOPPING_2 && mState != STOPPED && mState != PAUSED &&
4535 mState != PAUSING) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07004536 return;
4537 }
4538 // No point remaining in PAUSED state after a flush => go to
Eric Laurent29864602012-05-08 18:57:51 -07004539 // FLUSHED state
4540 mState = FLUSHED;
Eric Laurent38ccae22011-03-28 18:37:07 -07004541 // do not reset the track if it is still in the process of being stopped or paused.
4542 // this will be done by prepareTracks_l() when the track is stopped.
Eric Laurent29864602012-05-08 18:57:51 -07004543 // prepareTracks_l() will see mState == FLUSHED, then
Glenn Kastend08f48c2012-05-01 18:14:02 -07004544 // remove from active track list, reset(), and trigger presentation complete
Eric Laurent38ccae22011-03-28 18:37:07 -07004545 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
4546 if (playbackThread->mActiveTracks.indexOf(this) < 0) {
4547 reset();
4548 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07004549 }
4550}
4551
4552void AudioFlinger::PlaybackThread::Track::reset()
4553{
4554 // Do not reset twice to avoid discarding data written just after a flush and before
4555 // the audioflinger thread detects the track is stopped.
4556 if (!mResetDone) {
4557 TrackBase::reset();
4558 // Force underrun condition to avoid false underrun callback until first data is
4559 // written to buffer
Eric Laurent38ccae22011-03-28 18:37:07 -07004560 android_atomic_and(~CBLK_FORCEREADY_MSK, &mCblk->flags);
4561 android_atomic_or(CBLK_UNDERRUN_ON, &mCblk->flags);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004562 mFillingUpStatus = FS_FILLING;
4563 mResetDone = true;
Eric Laurent29864602012-05-08 18:57:51 -07004564 if (mState == FLUSHED) {
4565 mState = IDLE;
4566 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07004567 }
4568}
4569
4570void AudioFlinger::PlaybackThread::Track::mute(bool muted)
4571{
4572 mMute = muted;
4573}
4574
Mathias Agopian65ab4712010-07-14 17:59:35 -07004575status_t AudioFlinger::PlaybackThread::Track::attachAuxEffect(int EffectId)
4576{
4577 status_t status = DEAD_OBJECT;
4578 sp<ThreadBase> thread = mThread.promote();
4579 if (thread != 0) {
Glenn Kastene53b9ea2012-03-12 16:29:55 -07004580 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
4581 status = playbackThread->attachAuxEffect(this, EffectId);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004582 }
4583 return status;
4584}
4585
4586void AudioFlinger::PlaybackThread::Track::setAuxBuffer(int EffectId, int32_t *buffer)
4587{
4588 mAuxEffectId = EffectId;
4589 mAuxBuffer = buffer;
4590}
4591
Eric Laurenta011e352012-03-29 15:51:43 -07004592bool AudioFlinger::PlaybackThread::Track::presentationComplete(size_t framesWritten,
4593 size_t audioHalFrames)
4594{
4595 // a track is considered presented when the total number of frames written to audio HAL
4596 // corresponds to the number of frames written when presentationComplete() is called for the
4597 // first time (mPresentationCompleteFrames == 0) plus the buffer filling status at that time.
4598 if (mPresentationCompleteFrames == 0) {
4599 mPresentationCompleteFrames = framesWritten + audioHalFrames;
4600 ALOGV("presentationComplete() reset: mPresentationCompleteFrames %d audioHalFrames %d",
4601 mPresentationCompleteFrames, audioHalFrames);
4602 }
4603 if (framesWritten >= mPresentationCompleteFrames) {
4604 ALOGV("presentationComplete() session %d complete: framesWritten %d",
4605 mSessionId, framesWritten);
4606 triggerEvents(AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE);
Eric Laurenta011e352012-03-29 15:51:43 -07004607 return true;
4608 }
4609 return false;
4610}
4611
4612void AudioFlinger::PlaybackThread::Track::triggerEvents(AudioSystem::sync_event_t type)
4613{
4614 for (int i = 0; i < (int)mSyncEvents.size(); i++) {
4615 if (mSyncEvents[i]->type() == type) {
4616 mSyncEvents[i]->trigger();
4617 mSyncEvents.removeAt(i);
4618 i--;
4619 }
4620 }
4621}
4622
Glenn Kasten58912562012-04-03 10:45:00 -07004623// implement VolumeBufferProvider interface
4624
4625uint32_t AudioFlinger::PlaybackThread::Track::getVolumeLR()
4626{
4627 // called by FastMixer, so not allowed to take any locks, block, or do I/O including logs
4628 ALOG_ASSERT(isFastTrack() && (mCblk != NULL));
4629 uint32_t vlr = mCblk->getVolumeLR();
4630 uint32_t vl = vlr & 0xFFFF;
4631 uint32_t vr = vlr >> 16;
4632 // track volumes come from shared memory, so can't be trusted and must be clamped
4633 if (vl > MAX_GAIN_INT) {
4634 vl = MAX_GAIN_INT;
4635 }
4636 if (vr > MAX_GAIN_INT) {
4637 vr = MAX_GAIN_INT;
4638 }
4639 // now apply the cached master volume and stream type volume;
4640 // this is trusted but lacks any synchronization or barrier so may be stale
4641 float v = mCachedVolume;
4642 vl *= v;
4643 vr *= v;
4644 // re-combine into U4.16
4645 vlr = (vr << 16) | (vl & 0xFFFF);
4646 // FIXME look at mute, pause, and stop flags
4647 return vlr;
4648}
Eric Laurenta011e352012-03-29 15:51:43 -07004649
Eric Laurent29864602012-05-08 18:57:51 -07004650status_t AudioFlinger::PlaybackThread::Track::setSyncEvent(const sp<SyncEvent>& event)
4651{
4652 if (mState == TERMINATED || mState == PAUSED ||
4653 ((framesReady() == 0) && ((mSharedBuffer != 0) ||
4654 (mState == STOPPED)))) {
4655 ALOGW("Track::setSyncEvent() in invalid state %d on session %d %s mode, framesReady %d ",
4656 mState, mSessionId, (mSharedBuffer != 0) ? "static" : "stream", framesReady());
4657 event->cancel();
4658 return INVALID_OPERATION;
4659 }
4660 TrackBase::setSyncEvent(event);
4661 return NO_ERROR;
4662}
4663
John Grossman4ff14ba2012-02-08 16:37:41 -08004664// timed audio tracks
4665
4666sp<AudioFlinger::PlaybackThread::TimedTrack>
4667AudioFlinger::PlaybackThread::TimedTrack::create(
Glenn Kasten9eaa5572012-01-20 13:32:16 -08004668 PlaybackThread *thread,
John Grossman4ff14ba2012-02-08 16:37:41 -08004669 const sp<Client>& client,
4670 audio_stream_type_t streamType,
4671 uint32_t sampleRate,
4672 audio_format_t format,
4673 uint32_t channelMask,
4674 int frameCount,
4675 const sp<IMemory>& sharedBuffer,
4676 int sessionId) {
4677 if (!client->reserveTimedTrack())
4678 return NULL;
4679
Glenn Kastena0356762012-03-19 10:38:51 -07004680 return new TimedTrack(
John Grossman4ff14ba2012-02-08 16:37:41 -08004681 thread, client, streamType, sampleRate, format, channelMask, frameCount,
4682 sharedBuffer, sessionId);
John Grossman4ff14ba2012-02-08 16:37:41 -08004683}
4684
4685AudioFlinger::PlaybackThread::TimedTrack::TimedTrack(
Glenn Kasten9eaa5572012-01-20 13:32:16 -08004686 PlaybackThread *thread,
John Grossman4ff14ba2012-02-08 16:37:41 -08004687 const sp<Client>& client,
4688 audio_stream_type_t streamType,
4689 uint32_t sampleRate,
4690 audio_format_t format,
4691 uint32_t channelMask,
4692 int frameCount,
4693 const sp<IMemory>& sharedBuffer,
4694 int sessionId)
4695 : Track(thread, client, streamType, sampleRate, format, channelMask,
Glenn Kasten73d22752012-03-19 13:38:30 -07004696 frameCount, sharedBuffer, sessionId, IAudioFlinger::TRACK_TIMED),
John Grossman9fbdee12012-03-26 17:51:46 -07004697 mQueueHeadInFlight(false),
4698 mTrimQueueHeadOnRelease(false),
John Grossman1c345192012-03-27 14:00:17 -07004699 mFramesPendingInQueue(0),
John Grossman4ff14ba2012-02-08 16:37:41 -08004700 mTimedSilenceBuffer(NULL),
4701 mTimedSilenceBufferSize(0),
4702 mTimedAudioOutputOnTime(false),
4703 mMediaTimeTransformValid(false)
4704{
4705 LocalClock lc;
4706 mLocalTimeFreq = lc.getLocalFreq();
4707
4708 mLocalTimeToSampleTransform.a_zero = 0;
4709 mLocalTimeToSampleTransform.b_zero = 0;
4710 mLocalTimeToSampleTransform.a_to_b_numer = sampleRate;
4711 mLocalTimeToSampleTransform.a_to_b_denom = mLocalTimeFreq;
4712 LinearTransform::reduce(&mLocalTimeToSampleTransform.a_to_b_numer,
4713 &mLocalTimeToSampleTransform.a_to_b_denom);
John Grossman9fbdee12012-03-26 17:51:46 -07004714
4715 mMediaTimeToSampleTransform.a_zero = 0;
4716 mMediaTimeToSampleTransform.b_zero = 0;
4717 mMediaTimeToSampleTransform.a_to_b_numer = sampleRate;
4718 mMediaTimeToSampleTransform.a_to_b_denom = 1000000;
4719 LinearTransform::reduce(&mMediaTimeToSampleTransform.a_to_b_numer,
4720 &mMediaTimeToSampleTransform.a_to_b_denom);
John Grossman4ff14ba2012-02-08 16:37:41 -08004721}
4722
4723AudioFlinger::PlaybackThread::TimedTrack::~TimedTrack() {
4724 mClient->releaseTimedTrack();
4725 delete [] mTimedSilenceBuffer;
4726}
4727
4728status_t AudioFlinger::PlaybackThread::TimedTrack::allocateTimedBuffer(
4729 size_t size, sp<IMemory>* buffer) {
4730
4731 Mutex::Autolock _l(mTimedBufferQueueLock);
4732
4733 trimTimedBufferQueue_l();
4734
4735 // lazily initialize the shared memory heap for timed buffers
4736 if (mTimedMemoryDealer == NULL) {
4737 const int kTimedBufferHeapSize = 512 << 10;
4738
4739 mTimedMemoryDealer = new MemoryDealer(kTimedBufferHeapSize,
4740 "AudioFlingerTimed");
4741 if (mTimedMemoryDealer == NULL)
4742 return NO_MEMORY;
4743 }
4744
4745 sp<IMemory> newBuffer = mTimedMemoryDealer->allocate(size);
4746 if (newBuffer == NULL) {
4747 newBuffer = mTimedMemoryDealer->allocate(size);
4748 if (newBuffer == NULL)
4749 return NO_MEMORY;
4750 }
4751
4752 *buffer = newBuffer;
4753 return NO_ERROR;
4754}
4755
4756// caller must hold mTimedBufferQueueLock
4757void AudioFlinger::PlaybackThread::TimedTrack::trimTimedBufferQueue_l() {
4758 int64_t mediaTimeNow;
4759 {
4760 Mutex::Autolock mttLock(mMediaTimeTransformLock);
4761 if (!mMediaTimeTransformValid)
4762 return;
4763
4764 int64_t targetTimeNow;
4765 status_t res = (mMediaTimeTransformTarget == TimedAudioTrack::COMMON_TIME)
4766 ? mCCHelper.getCommonTime(&targetTimeNow)
4767 : mCCHelper.getLocalTime(&targetTimeNow);
4768
4769 if (OK != res)
4770 return;
4771
4772 if (!mMediaTimeTransform.doReverseTransform(targetTimeNow,
4773 &mediaTimeNow)) {
4774 return;
4775 }
4776 }
4777
John Grossman1c345192012-03-27 14:00:17 -07004778 size_t trimEnd;
4779 for (trimEnd = 0; trimEnd < mTimedBufferQueue.size(); trimEnd++) {
John Grossman9fbdee12012-03-26 17:51:46 -07004780 int64_t bufEnd;
4781
John Grossmanc95cfbb2012-04-12 11:53:11 -07004782 if ((trimEnd + 1) < mTimedBufferQueue.size()) {
4783 // We have a next buffer. Just use its PTS as the PTS of the frame
4784 // following the last frame in this buffer. If the stream is sparse
4785 // (ie, there are deliberate gaps left in the stream which should be
4786 // filled with silence by the TimedAudioTrack), then this can result
4787 // in one extra buffer being left un-trimmed when it could have
4788 // been. In general, this is not typical, and we would rather
4789 // optimized away the TS calculation below for the more common case
4790 // where PTSes are contiguous.
4791 bufEnd = mTimedBufferQueue[trimEnd + 1].pts();
4792 } else {
4793 // We have no next buffer. Compute the PTS of the frame following
4794 // the last frame in this buffer by computing the duration of of
4795 // this frame in media time units and adding it to the PTS of the
4796 // buffer.
4797 int64_t frameCount = mTimedBufferQueue[trimEnd].buffer()->size()
4798 / mCblk->frameSize;
4799
4800 if (!mMediaTimeToSampleTransform.doReverseTransform(frameCount,
4801 &bufEnd)) {
4802 ALOGE("Failed to convert frame count of %lld to media time"
4803 " duration" " (scale factor %d/%u) in %s",
4804 frameCount,
4805 mMediaTimeToSampleTransform.a_to_b_numer,
4806 mMediaTimeToSampleTransform.a_to_b_denom,
4807 __PRETTY_FUNCTION__);
4808 break;
4809 }
4810 bufEnd += mTimedBufferQueue[trimEnd].pts();
John Grossman9fbdee12012-03-26 17:51:46 -07004811 }
John Grossman9fbdee12012-03-26 17:51:46 -07004812
4813 if (bufEnd > mediaTimeNow)
4814 break;
4815
4816 // Is the buffer we want to use in the middle of a mix operation right
4817 // now? If so, don't actually trim it. Just wait for the releaseBuffer
4818 // from the mixer which should be coming back shortly.
John Grossman1c345192012-03-27 14:00:17 -07004819 if (!trimEnd && mQueueHeadInFlight) {
John Grossman9fbdee12012-03-26 17:51:46 -07004820 mTrimQueueHeadOnRelease = true;
4821 }
John Grossman4ff14ba2012-02-08 16:37:41 -08004822 }
4823
John Grossman9fbdee12012-03-26 17:51:46 -07004824 size_t trimStart = mTrimQueueHeadOnRelease ? 1 : 0;
John Grossman1c345192012-03-27 14:00:17 -07004825 if (trimStart < trimEnd) {
4826 // Update the bookkeeping for framesReady()
4827 for (size_t i = trimStart; i < trimEnd; ++i) {
4828 updateFramesPendingAfterTrim_l(mTimedBufferQueue[i], "trim");
4829 }
4830
4831 // Now actually remove the buffers from the queue.
4832 mTimedBufferQueue.removeItemsAt(trimStart, trimEnd);
John Grossman4ff14ba2012-02-08 16:37:41 -08004833 }
4834}
4835
John Grossman1c345192012-03-27 14:00:17 -07004836void AudioFlinger::PlaybackThread::TimedTrack::trimTimedBufferQueueHead_l(
4837 const char* logTag) {
John Grossmand3030da2012-04-12 11:56:36 -07004838 ALOG_ASSERT(mTimedBufferQueue.size() > 0,
4839 "%s called (reason \"%s\"), but timed buffer queue has no"
4840 " elements to trim.", __FUNCTION__, logTag);
John Grossman1c345192012-03-27 14:00:17 -07004841
4842 updateFramesPendingAfterTrim_l(mTimedBufferQueue[0], logTag);
4843 mTimedBufferQueue.removeAt(0);
4844}
4845
4846void AudioFlinger::PlaybackThread::TimedTrack::updateFramesPendingAfterTrim_l(
4847 const TimedBuffer& buf,
4848 const char* logTag) {
4849 uint32_t bufBytes = buf.buffer()->size();
4850 uint32_t consumedAlready = buf.position();
4851
Eric Laurentb388e532012-04-14 13:32:48 -07004852 ALOG_ASSERT(consumedAlready <= bufBytes,
John Grossmand3030da2012-04-12 11:56:36 -07004853 "Bad bookkeeping while updating frames pending. Timed buffer is"
4854 " only %u bytes long, but claims to have consumed %u"
4855 " bytes. (update reason: \"%s\")",
Eric Laurentb388e532012-04-14 13:32:48 -07004856 bufBytes, consumedAlready, logTag);
John Grossman1c345192012-03-27 14:00:17 -07004857
4858 uint32_t bufFrames = (bufBytes - consumedAlready) / mCblk->frameSize;
John Grossmand3030da2012-04-12 11:56:36 -07004859 ALOG_ASSERT(mFramesPendingInQueue >= bufFrames,
4860 "Bad bookkeeping while updating frames pending. Should have at"
4861 " least %u queued frames, but we think we have only %u. (update"
4862 " reason: \"%s\")",
4863 bufFrames, mFramesPendingInQueue, logTag);
John Grossman1c345192012-03-27 14:00:17 -07004864
4865 mFramesPendingInQueue -= bufFrames;
4866}
4867
John Grossman4ff14ba2012-02-08 16:37:41 -08004868status_t AudioFlinger::PlaybackThread::TimedTrack::queueTimedBuffer(
4869 const sp<IMemory>& buffer, int64_t pts) {
4870
4871 {
4872 Mutex::Autolock mttLock(mMediaTimeTransformLock);
4873 if (!mMediaTimeTransformValid)
4874 return INVALID_OPERATION;
4875 }
4876
4877 Mutex::Autolock _l(mTimedBufferQueueLock);
4878
John Grossman1c345192012-03-27 14:00:17 -07004879 uint32_t bufFrames = buffer->size() / mCblk->frameSize;
4880 mFramesPendingInQueue += bufFrames;
John Grossman4ff14ba2012-02-08 16:37:41 -08004881 mTimedBufferQueue.add(TimedBuffer(buffer, pts));
4882
4883 return NO_ERROR;
4884}
4885
4886status_t AudioFlinger::PlaybackThread::TimedTrack::setMediaTimeTransform(
4887 const LinearTransform& xform, TimedAudioTrack::TargetTimeline target) {
4888
John Grossman1c345192012-03-27 14:00:17 -07004889 ALOGVV("setMediaTimeTransform az=%lld bz=%lld n=%d d=%u tgt=%d",
4890 xform.a_zero, xform.b_zero, xform.a_to_b_numer, xform.a_to_b_denom,
4891 target);
John Grossman4ff14ba2012-02-08 16:37:41 -08004892
4893 if (!(target == TimedAudioTrack::LOCAL_TIME ||
4894 target == TimedAudioTrack::COMMON_TIME)) {
4895 return BAD_VALUE;
4896 }
4897
4898 Mutex::Autolock lock(mMediaTimeTransformLock);
4899 mMediaTimeTransform = xform;
4900 mMediaTimeTransformTarget = target;
4901 mMediaTimeTransformValid = true;
4902
4903 return NO_ERROR;
4904}
4905
4906#define min(a, b) ((a) < (b) ? (a) : (b))
4907
4908// implementation of getNextBuffer for tracks whose buffers have timestamps
4909status_t AudioFlinger::PlaybackThread::TimedTrack::getNextBuffer(
4910 AudioBufferProvider::Buffer* buffer, int64_t pts)
4911{
4912 if (pts == AudioBufferProvider::kInvalidPTS) {
4913 buffer->raw = 0;
4914 buffer->frameCount = 0;
John Grossman8d314b72012-04-19 12:08:17 -07004915 mTimedAudioOutputOnTime = false;
John Grossman4ff14ba2012-02-08 16:37:41 -08004916 return INVALID_OPERATION;
4917 }
4918
John Grossman4ff14ba2012-02-08 16:37:41 -08004919 Mutex::Autolock _l(mTimedBufferQueueLock);
4920
John Grossman9fbdee12012-03-26 17:51:46 -07004921 ALOG_ASSERT(!mQueueHeadInFlight,
4922 "getNextBuffer called without releaseBuffer!");
4923
John Grossman4ff14ba2012-02-08 16:37:41 -08004924 while (true) {
4925
4926 // if we have no timed buffers, then fail
4927 if (mTimedBufferQueue.isEmpty()) {
4928 buffer->raw = 0;
4929 buffer->frameCount = 0;
4930 return NOT_ENOUGH_DATA;
4931 }
4932
4933 TimedBuffer& head = mTimedBufferQueue.editItemAt(0);
4934
4935 // calculate the PTS of the head of the timed buffer queue expressed in
4936 // local time
4937 int64_t headLocalPTS;
4938 {
4939 Mutex::Autolock mttLock(mMediaTimeTransformLock);
4940
Glenn Kasten5798d4e2012-03-08 12:18:35 -08004941 ALOG_ASSERT(mMediaTimeTransformValid, "media time transform invalid");
John Grossman4ff14ba2012-02-08 16:37:41 -08004942
4943 if (mMediaTimeTransform.a_to_b_denom == 0) {
4944 // the transform represents a pause, so yield silence
John Grossman9fbdee12012-03-26 17:51:46 -07004945 timedYieldSilence_l(buffer->frameCount, buffer);
John Grossman4ff14ba2012-02-08 16:37:41 -08004946 return NO_ERROR;
4947 }
4948
4949 int64_t transformedPTS;
4950 if (!mMediaTimeTransform.doForwardTransform(head.pts(),
4951 &transformedPTS)) {
4952 // the transform failed. this shouldn't happen, but if it does
4953 // then just drop this buffer
4954 ALOGW("timedGetNextBuffer transform failed");
4955 buffer->raw = 0;
4956 buffer->frameCount = 0;
John Grossman1c345192012-03-27 14:00:17 -07004957 trimTimedBufferQueueHead_l("getNextBuffer; no transform");
John Grossman4ff14ba2012-02-08 16:37:41 -08004958 return NO_ERROR;
4959 }
4960
4961 if (mMediaTimeTransformTarget == TimedAudioTrack::COMMON_TIME) {
4962 if (OK != mCCHelper.commonTimeToLocalTime(transformedPTS,
4963 &headLocalPTS)) {
4964 buffer->raw = 0;
4965 buffer->frameCount = 0;
4966 return INVALID_OPERATION;
4967 }
4968 } else {
4969 headLocalPTS = transformedPTS;
4970 }
4971 }
4972
4973 // adjust the head buffer's PTS to reflect the portion of the head buffer
4974 // that has already been consumed
4975 int64_t effectivePTS = headLocalPTS +
4976 ((head.position() / mCblk->frameSize) * mLocalTimeFreq / sampleRate());
4977
4978 // Calculate the delta in samples between the head of the input buffer
4979 // queue and the start of the next output buffer that will be written.
4980 // If the transformation fails because of over or underflow, it means
4981 // that the sample's position in the output stream is so far out of
4982 // whack that it should just be dropped.
4983 int64_t sampleDelta;
4984 if (llabs(effectivePTS - pts) >= (static_cast<int64_t>(1) << 31)) {
4985 ALOGV("*** head buffer is too far from PTS: dropped buffer");
John Grossman1c345192012-03-27 14:00:17 -07004986 trimTimedBufferQueueHead_l("getNextBuffer, buf pts too far from"
4987 " mix");
John Grossman4ff14ba2012-02-08 16:37:41 -08004988 continue;
4989 }
4990 if (!mLocalTimeToSampleTransform.doForwardTransform(
4991 (effectivePTS - pts) << 32, &sampleDelta)) {
John Grossmand3030da2012-04-12 11:56:36 -07004992 ALOGV("*** too late during sample rate transform: dropped buffer");
John Grossman1c345192012-03-27 14:00:17 -07004993 trimTimedBufferQueueHead_l("getNextBuffer, bad local to sample");
John Grossman4ff14ba2012-02-08 16:37:41 -08004994 continue;
4995 }
4996
John Grossman1c345192012-03-27 14:00:17 -07004997 ALOGVV("*** getNextBuffer head.pts=%lld head.pos=%d pts=%lld"
4998 " sampleDelta=[%d.%08x]",
4999 head.pts(), head.position(), pts,
5000 static_cast<int32_t>((sampleDelta >= 0 ? 0 : 1)
5001 + (sampleDelta >> 32)),
5002 static_cast<uint32_t>(sampleDelta & 0xFFFFFFFF));
John Grossman4ff14ba2012-02-08 16:37:41 -08005003
5004 // if the delta between the ideal placement for the next input sample and
5005 // the current output position is within this threshold, then we will
5006 // concatenate the next input samples to the previous output
5007 const int64_t kSampleContinuityThreshold =
John Grossman8d314b72012-04-19 12:08:17 -07005008 (static_cast<int64_t>(sampleRate()) << 32) / 250;
John Grossman4ff14ba2012-02-08 16:37:41 -08005009
5010 // if this is the first buffer of audio that we're emitting from this track
5011 // then it should be almost exactly on time.
5012 const int64_t kSampleStartupThreshold = 1LL << 32;
5013
5014 if ((mTimedAudioOutputOnTime && llabs(sampleDelta) <= kSampleContinuityThreshold) ||
John Grossman8d314b72012-04-19 12:08:17 -07005015 (!mTimedAudioOutputOnTime && llabs(sampleDelta) <= kSampleStartupThreshold)) {
John Grossman4ff14ba2012-02-08 16:37:41 -08005016 // the next input is close enough to being on time, so concatenate it
5017 // with the last output
John Grossman9fbdee12012-03-26 17:51:46 -07005018 timedYieldSamples_l(buffer);
John Grossman4ff14ba2012-02-08 16:37:41 -08005019
John Grossman1c345192012-03-27 14:00:17 -07005020 ALOGVV("*** on time: head.pos=%d frameCount=%u",
5021 head.position(), buffer->frameCount);
John Grossman4ff14ba2012-02-08 16:37:41 -08005022 return NO_ERROR;
John Grossman8d314b72012-04-19 12:08:17 -07005023 }
5024
5025 // Looks like our output is not on time. Reset our on timed status.
5026 // Next time we mix samples from our input queue, then should be within
5027 // the StartupThreshold.
5028 mTimedAudioOutputOnTime = false;
5029 if (sampleDelta > 0) {
John Grossman4ff14ba2012-02-08 16:37:41 -08005030 // the gap between the current output position and the proper start of
5031 // the next input sample is too big, so fill it with silence
5032 uint32_t framesUntilNextInput = (sampleDelta + 0x80000000) >> 32;
5033
John Grossman9fbdee12012-03-26 17:51:46 -07005034 timedYieldSilence_l(framesUntilNextInput, buffer);
John Grossman4ff14ba2012-02-08 16:37:41 -08005035 ALOGV("*** silence: frameCount=%u", buffer->frameCount);
5036 return NO_ERROR;
5037 } else {
5038 // the next input sample is late
5039 uint32_t lateFrames = static_cast<uint32_t>(-((sampleDelta + 0x80000000) >> 32));
5040 size_t onTimeSamplePosition =
5041 head.position() + lateFrames * mCblk->frameSize;
5042
5043 if (onTimeSamplePosition > head.buffer()->size()) {
5044 // all the remaining samples in the head are too late, so
5045 // drop it and move on
5046 ALOGV("*** too late: dropped buffer");
John Grossman1c345192012-03-27 14:00:17 -07005047 trimTimedBufferQueueHead_l("getNextBuffer, dropped late buffer");
John Grossman4ff14ba2012-02-08 16:37:41 -08005048 continue;
5049 } else {
5050 // skip over the late samples
5051 head.setPosition(onTimeSamplePosition);
5052
5053 // yield the available samples
John Grossman9fbdee12012-03-26 17:51:46 -07005054 timedYieldSamples_l(buffer);
John Grossman4ff14ba2012-02-08 16:37:41 -08005055
5056 ALOGV("*** late: head.pos=%d frameCount=%u", head.position(), buffer->frameCount);
5057 return NO_ERROR;
5058 }
5059 }
5060 }
5061}
5062
5063// Yield samples from the timed buffer queue head up to the given output
5064// buffer's capacity.
5065//
5066// Caller must hold mTimedBufferQueueLock
John Grossman9fbdee12012-03-26 17:51:46 -07005067void AudioFlinger::PlaybackThread::TimedTrack::timedYieldSamples_l(
John Grossman4ff14ba2012-02-08 16:37:41 -08005068 AudioBufferProvider::Buffer* buffer) {
5069
5070 const TimedBuffer& head = mTimedBufferQueue[0];
5071
5072 buffer->raw = (static_cast<uint8_t*>(head.buffer()->pointer()) +
5073 head.position());
5074
5075 uint32_t framesLeftInHead = ((head.buffer()->size() - head.position()) /
5076 mCblk->frameSize);
5077 size_t framesRequested = buffer->frameCount;
5078 buffer->frameCount = min(framesLeftInHead, framesRequested);
5079
John Grossman9fbdee12012-03-26 17:51:46 -07005080 mQueueHeadInFlight = true;
John Grossman4ff14ba2012-02-08 16:37:41 -08005081 mTimedAudioOutputOnTime = true;
5082}
5083
5084// Yield samples of silence up to the given output buffer's capacity
5085//
5086// Caller must hold mTimedBufferQueueLock
John Grossman9fbdee12012-03-26 17:51:46 -07005087void AudioFlinger::PlaybackThread::TimedTrack::timedYieldSilence_l(
John Grossman4ff14ba2012-02-08 16:37:41 -08005088 uint32_t numFrames, AudioBufferProvider::Buffer* buffer) {
5089
5090 // lazily allocate a buffer filled with silence
5091 if (mTimedSilenceBufferSize < numFrames * mCblk->frameSize) {
5092 delete [] mTimedSilenceBuffer;
5093 mTimedSilenceBufferSize = numFrames * mCblk->frameSize;
5094 mTimedSilenceBuffer = new uint8_t[mTimedSilenceBufferSize];
5095 memset(mTimedSilenceBuffer, 0, mTimedSilenceBufferSize);
5096 }
5097
5098 buffer->raw = mTimedSilenceBuffer;
5099 size_t framesRequested = buffer->frameCount;
5100 buffer->frameCount = min(numFrames, framesRequested);
5101
5102 mTimedAudioOutputOnTime = false;
5103}
5104
Glenn Kasten01c4ebf2012-02-22 10:47:35 -08005105// AudioBufferProvider interface
John Grossman4ff14ba2012-02-08 16:37:41 -08005106void AudioFlinger::PlaybackThread::TimedTrack::releaseBuffer(
5107 AudioBufferProvider::Buffer* buffer) {
5108
5109 Mutex::Autolock _l(mTimedBufferQueueLock);
5110
John Grossmanfe5b3ba2012-02-12 17:51:21 -08005111 // If the buffer which was just released is part of the buffer at the head
5112 // of the queue, be sure to update the amt of the buffer which has been
5113 // consumed. If the buffer being returned is not part of the head of the
5114 // queue, its either because the buffer is part of the silence buffer, or
5115 // because the head of the timed queue was trimmed after the mixer called
5116 // getNextBuffer but before the mixer called releaseBuffer.
John Grossman9fbdee12012-03-26 17:51:46 -07005117 if (buffer->raw == mTimedSilenceBuffer) {
5118 ALOG_ASSERT(!mQueueHeadInFlight,
5119 "Queue head in flight during release of silence buffer!");
5120 goto done;
5121 }
5122
5123 ALOG_ASSERT(mQueueHeadInFlight,
5124 "TimedTrack::releaseBuffer of non-silence buffer, but no queue"
5125 " head in flight.");
5126
5127 if (mTimedBufferQueue.size()) {
John Grossman4ff14ba2012-02-08 16:37:41 -08005128 TimedBuffer& head = mTimedBufferQueue.editItemAt(0);
John Grossmanfe5b3ba2012-02-12 17:51:21 -08005129
5130 void* start = head.buffer()->pointer();
John Grossman9fbdee12012-03-26 17:51:46 -07005131 void* end = reinterpret_cast<void*>(
5132 reinterpret_cast<uint8_t*>(head.buffer()->pointer())
5133 + head.buffer()->size());
John Grossmanfe5b3ba2012-02-12 17:51:21 -08005134
John Grossman9fbdee12012-03-26 17:51:46 -07005135 ALOG_ASSERT((buffer->raw >= start) && (buffer->raw < end),
5136 "released buffer not within the head of the timed buffer"
5137 " queue; qHead = [%p, %p], released buffer = %p",
5138 start, end, buffer->raw);
5139
5140 head.setPosition(head.position() +
5141 (buffer->frameCount * mCblk->frameSize));
5142 mQueueHeadInFlight = false;
5143
John Grossman1c345192012-03-27 14:00:17 -07005144 ALOG_ASSERT(mFramesPendingInQueue >= buffer->frameCount,
5145 "Bad bookkeeping during releaseBuffer! Should have at"
5146 " least %u queued frames, but we think we have only %u",
5147 buffer->frameCount, mFramesPendingInQueue);
5148
5149 mFramesPendingInQueue -= buffer->frameCount;
5150
John Grossman9fbdee12012-03-26 17:51:46 -07005151 if ((static_cast<size_t>(head.position()) >= head.buffer()->size())
5152 || mTrimQueueHeadOnRelease) {
John Grossman1c345192012-03-27 14:00:17 -07005153 trimTimedBufferQueueHead_l("releaseBuffer");
John Grossman9fbdee12012-03-26 17:51:46 -07005154 mTrimQueueHeadOnRelease = false;
John Grossman4ff14ba2012-02-08 16:37:41 -08005155 }
John Grossman9fbdee12012-03-26 17:51:46 -07005156 } else {
5157 LOG_FATAL("TimedTrack::releaseBuffer of non-silence buffer with no"
5158 " buffers in the timed buffer queue");
John Grossman4ff14ba2012-02-08 16:37:41 -08005159 }
5160
John Grossman9fbdee12012-03-26 17:51:46 -07005161done:
John Grossman4ff14ba2012-02-08 16:37:41 -08005162 buffer->raw = 0;
5163 buffer->frameCount = 0;
5164}
5165
Glenn Kasten288ed212012-04-25 17:52:27 -07005166size_t AudioFlinger::PlaybackThread::TimedTrack::framesReady() const {
John Grossman4ff14ba2012-02-08 16:37:41 -08005167 Mutex::Autolock _l(mTimedBufferQueueLock);
John Grossman1c345192012-03-27 14:00:17 -07005168 return mFramesPendingInQueue;
John Grossman4ff14ba2012-02-08 16:37:41 -08005169}
5170
5171AudioFlinger::PlaybackThread::TimedTrack::TimedBuffer::TimedBuffer()
5172 : mPTS(0), mPosition(0) {}
5173
5174AudioFlinger::PlaybackThread::TimedTrack::TimedBuffer::TimedBuffer(
5175 const sp<IMemory>& buffer, int64_t pts)
5176 : mBuffer(buffer), mPTS(pts), mPosition(0) {}
5177
Mathias Agopian65ab4712010-07-14 17:59:35 -07005178// ----------------------------------------------------------------------------
5179
5180// RecordTrack constructor must be called with AudioFlinger::mLock held
5181AudioFlinger::RecordThread::RecordTrack::RecordTrack(
Glenn Kasten9eaa5572012-01-20 13:32:16 -08005182 RecordThread *thread,
Mathias Agopian65ab4712010-07-14 17:59:35 -07005183 const sp<Client>& client,
5184 uint32_t sampleRate,
Glenn Kasten58f30212012-01-12 12:27:51 -08005185 audio_format_t format,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07005186 uint32_t channelMask,
Mathias Agopian65ab4712010-07-14 17:59:35 -07005187 int frameCount,
Mathias Agopian65ab4712010-07-14 17:59:35 -07005188 int sessionId)
5189 : TrackBase(thread, client, sampleRate, format,
Glenn Kasten5cf034d2012-02-21 10:35:56 -08005190 channelMask, frameCount, 0 /*sharedBuffer*/, sessionId),
Mathias Agopian65ab4712010-07-14 17:59:35 -07005191 mOverflow(false)
5192{
5193 if (mCblk != NULL) {
Glenn Kastene53b9ea2012-03-12 16:29:55 -07005194 ALOGV("RecordTrack constructor, size %d", (int)mBufferEnd - (int)mBuffer);
5195 if (format == AUDIO_FORMAT_PCM_16_BIT) {
5196 mCblk->frameSize = mChannelCount * sizeof(int16_t);
5197 } else if (format == AUDIO_FORMAT_PCM_8_BIT) {
5198 mCblk->frameSize = mChannelCount * sizeof(int8_t);
5199 } else {
5200 mCblk->frameSize = sizeof(int8_t);
5201 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07005202 }
5203}
5204
5205AudioFlinger::RecordThread::RecordTrack::~RecordTrack()
5206{
5207 sp<ThreadBase> thread = mThread.promote();
5208 if (thread != 0) {
5209 AudioSystem::releaseInput(thread->id());
5210 }
5211}
5212
Glenn Kasten01c4ebf2012-02-22 10:47:35 -08005213// AudioBufferProvider interface
John Grossman4ff14ba2012-02-08 16:37:41 -08005214status_t AudioFlinger::RecordThread::RecordTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer, int64_t pts)
Mathias Agopian65ab4712010-07-14 17:59:35 -07005215{
5216 audio_track_cblk_t* cblk = this->cblk();
5217 uint32_t framesAvail;
5218 uint32_t framesReq = buffer->frameCount;
5219
Glenn Kastene53b9ea2012-03-12 16:29:55 -07005220 // Check if last stepServer failed, try to step now
Glenn Kasten5cf034d2012-02-21 10:35:56 -08005221 if (mStepServerFailed) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07005222 if (!step()) goto getNextBuffer_exit;
Steve Block3856b092011-10-20 11:56:00 +01005223 ALOGV("stepServer recovered");
Glenn Kasten5cf034d2012-02-21 10:35:56 -08005224 mStepServerFailed = false;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005225 }
5226
5227 framesAvail = cblk->framesAvailable_l();
5228
Glenn Kastenf6b16782011-12-15 09:51:17 -08005229 if (CC_LIKELY(framesAvail)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07005230 uint32_t s = cblk->server;
5231 uint32_t bufferEnd = cblk->serverBase + cblk->frameCount;
5232
5233 if (framesReq > framesAvail) {
5234 framesReq = framesAvail;
5235 }
Marco Nelissena1472d92012-03-30 14:36:54 -07005236 if (framesReq > bufferEnd - s) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07005237 framesReq = bufferEnd - s;
5238 }
5239
5240 buffer->raw = getBuffer(s, framesReq);
Glenn Kastene0feee32011-12-13 11:53:26 -08005241 if (buffer->raw == NULL) goto getNextBuffer_exit;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005242
5243 buffer->frameCount = framesReq;
5244 return NO_ERROR;
5245 }
5246
5247getNextBuffer_exit:
Glenn Kastene0feee32011-12-13 11:53:26 -08005248 buffer->raw = NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005249 buffer->frameCount = 0;
5250 return NOT_ENOUGH_DATA;
5251}
5252
Glenn Kasten3acbd052012-02-28 10:39:56 -08005253status_t AudioFlinger::RecordThread::RecordTrack::start(AudioSystem::sync_event_t event,
Eric Laurenta011e352012-03-29 15:51:43 -07005254 int triggerSession)
Mathias Agopian65ab4712010-07-14 17:59:35 -07005255{
5256 sp<ThreadBase> thread = mThread.promote();
5257 if (thread != 0) {
5258 RecordThread *recordThread = (RecordThread *)thread.get();
Glenn Kasten3acbd052012-02-28 10:39:56 -08005259 return recordThread->start(this, event, triggerSession);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005260 } else {
5261 return BAD_VALUE;
5262 }
5263}
5264
5265void AudioFlinger::RecordThread::RecordTrack::stop()
5266{
5267 sp<ThreadBase> thread = mThread.promote();
5268 if (thread != 0) {
5269 RecordThread *recordThread = (RecordThread *)thread.get();
5270 recordThread->stop(this);
Eric Laurent38ccae22011-03-28 18:37:07 -07005271 TrackBase::reset();
Glenn Kasten17a736c2012-02-14 08:52:15 -08005272 // Force overrun condition to avoid false overrun callback until first data is
Eric Laurent38ccae22011-03-28 18:37:07 -07005273 // read from buffer
5274 android_atomic_or(CBLK_UNDERRUN_ON, &mCblk->flags);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005275 }
5276}
5277
5278void AudioFlinger::RecordThread::RecordTrack::dump(char* buffer, size_t size)
5279{
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07005280 snprintf(buffer, size, " %05d %03u 0x%08x %05d %04u %01d %05u %08x %08x\n",
Glenn Kasten44deb052012-02-05 18:09:08 -08005281 (mClient == 0) ? getpid_cached : mClient->pid(),
Mathias Agopian65ab4712010-07-14 17:59:35 -07005282 mFormat,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07005283 mChannelMask,
Mathias Agopian65ab4712010-07-14 17:59:35 -07005284 mSessionId,
5285 mFrameCount,
5286 mState,
5287 mCblk->sampleRate,
5288 mCblk->server,
5289 mCblk->user);
5290}
5291
5292
5293// ----------------------------------------------------------------------------
5294
5295AudioFlinger::PlaybackThread::OutputTrack::OutputTrack(
Glenn Kasten9eaa5572012-01-20 13:32:16 -08005296 PlaybackThread *playbackThread,
Mathias Agopian65ab4712010-07-14 17:59:35 -07005297 DuplicatingThread *sourceThread,
5298 uint32_t sampleRate,
Glenn Kasten58f30212012-01-12 12:27:51 -08005299 audio_format_t format,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07005300 uint32_t channelMask,
Mathias Agopian65ab4712010-07-14 17:59:35 -07005301 int frameCount)
Glenn Kasten73d22752012-03-19 13:38:30 -07005302 : Track(playbackThread, NULL, AUDIO_STREAM_CNT, sampleRate, format, channelMask, frameCount,
5303 NULL, 0, IAudioFlinger::TRACK_DEFAULT),
Mathias Agopian65ab4712010-07-14 17:59:35 -07005304 mActive(false), mSourceThread(sourceThread)
5305{
5306
Mathias Agopian65ab4712010-07-14 17:59:35 -07005307 if (mCblk != NULL) {
5308 mCblk->flags |= CBLK_DIRECTION_OUT;
5309 mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005310 mOutBuffer.frameCount = 0;
5311 playbackThread->mTracks.add(this);
Steve Block3856b092011-10-20 11:56:00 +01005312 ALOGV("OutputTrack constructor mCblk %p, mBuffer %p, mCblk->buffers %p, " \
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07005313 "mCblk->frameCount %d, mCblk->sampleRate %d, mChannelMask 0x%08x mBufferEnd %p",
5314 mCblk, mBuffer, mCblk->buffers,
5315 mCblk->frameCount, mCblk->sampleRate, mChannelMask, mBufferEnd);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005316 } else {
Steve Block5ff1dd52012-01-05 23:22:43 +00005317 ALOGW("Error creating output track on thread %p", playbackThread);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005318 }
5319}
5320
5321AudioFlinger::PlaybackThread::OutputTrack::~OutputTrack()
5322{
5323 clearBufferQueue();
5324}
5325
Glenn Kasten3acbd052012-02-28 10:39:56 -08005326status_t AudioFlinger::PlaybackThread::OutputTrack::start(AudioSystem::sync_event_t event,
Eric Laurenta011e352012-03-29 15:51:43 -07005327 int triggerSession)
Mathias Agopian65ab4712010-07-14 17:59:35 -07005328{
Glenn Kasten3acbd052012-02-28 10:39:56 -08005329 status_t status = Track::start(event, triggerSession);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005330 if (status != NO_ERROR) {
5331 return status;
5332 }
5333
5334 mActive = true;
5335 mRetryCount = 127;
5336 return status;
5337}
5338
5339void AudioFlinger::PlaybackThread::OutputTrack::stop()
5340{
5341 Track::stop();
5342 clearBufferQueue();
5343 mOutBuffer.frameCount = 0;
5344 mActive = false;
5345}
5346
5347bool AudioFlinger::PlaybackThread::OutputTrack::write(int16_t* data, uint32_t frames)
5348{
5349 Buffer *pInBuffer;
5350 Buffer inBuffer;
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07005351 uint32_t channelCount = mChannelCount;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005352 bool outputBufferFull = false;
5353 inBuffer.frameCount = frames;
5354 inBuffer.i16 = data;
5355
5356 uint32_t waitTimeLeftMs = mSourceThread->waitTimeMs();
5357
5358 if (!mActive && frames != 0) {
Glenn Kasten3acbd052012-02-28 10:39:56 -08005359 start();
Mathias Agopian65ab4712010-07-14 17:59:35 -07005360 sp<ThreadBase> thread = mThread.promote();
5361 if (thread != 0) {
5362 MixerThread *mixerThread = (MixerThread *)thread.get();
5363 if (mCblk->frameCount > frames){
5364 if (mBufferQueue.size() < kMaxOverFlowBuffers) {
5365 uint32_t startFrames = (mCblk->frameCount - frames);
5366 pInBuffer = new Buffer;
5367 pInBuffer->mBuffer = new int16_t[startFrames * channelCount];
5368 pInBuffer->frameCount = startFrames;
5369 pInBuffer->i16 = pInBuffer->mBuffer;
5370 memset(pInBuffer->raw, 0, startFrames * channelCount * sizeof(int16_t));
5371 mBufferQueue.add(pInBuffer);
5372 } else {
Steve Block5ff1dd52012-01-05 23:22:43 +00005373 ALOGW ("OutputTrack::write() %p no more buffers in queue", this);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005374 }
5375 }
5376 }
5377 }
5378
5379 while (waitTimeLeftMs) {
5380 // First write pending buffers, then new data
5381 if (mBufferQueue.size()) {
5382 pInBuffer = mBufferQueue.itemAt(0);
5383 } else {
5384 pInBuffer = &inBuffer;
5385 }
5386
5387 if (pInBuffer->frameCount == 0) {
5388 break;
5389 }
5390
5391 if (mOutBuffer.frameCount == 0) {
5392 mOutBuffer.frameCount = pInBuffer->frameCount;
5393 nsecs_t startTime = systemTime();
Glenn Kasten335787f2012-01-20 17:00:00 -08005394 if (obtainBuffer(&mOutBuffer, waitTimeLeftMs) == (status_t)NO_MORE_BUFFERS) {
Steve Block3856b092011-10-20 11:56:00 +01005395 ALOGV ("OutputTrack::write() %p thread %p no more output buffers", this, mThread.unsafe_get());
Mathias Agopian65ab4712010-07-14 17:59:35 -07005396 outputBufferFull = true;
5397 break;
5398 }
5399 uint32_t waitTimeMs = (uint32_t)ns2ms(systemTime() - startTime);
5400 if (waitTimeLeftMs >= waitTimeMs) {
5401 waitTimeLeftMs -= waitTimeMs;
5402 } else {
5403 waitTimeLeftMs = 0;
5404 }
5405 }
5406
5407 uint32_t outFrames = pInBuffer->frameCount > mOutBuffer.frameCount ? mOutBuffer.frameCount : pInBuffer->frameCount;
5408 memcpy(mOutBuffer.raw, pInBuffer->raw, outFrames * channelCount * sizeof(int16_t));
5409 mCblk->stepUser(outFrames);
5410 pInBuffer->frameCount -= outFrames;
5411 pInBuffer->i16 += outFrames * channelCount;
5412 mOutBuffer.frameCount -= outFrames;
5413 mOutBuffer.i16 += outFrames * channelCount;
5414
5415 if (pInBuffer->frameCount == 0) {
5416 if (mBufferQueue.size()) {
5417 mBufferQueue.removeAt(0);
5418 delete [] pInBuffer->mBuffer;
5419 delete pInBuffer;
Steve Block3856b092011-10-20 11:56:00 +01005420 ALOGV("OutputTrack::write() %p thread %p released overflow buffer %d", this, mThread.unsafe_get(), mBufferQueue.size());
Mathias Agopian65ab4712010-07-14 17:59:35 -07005421 } else {
5422 break;
5423 }
5424 }
5425 }
5426
5427 // If we could not write all frames, allocate a buffer and queue it for next time.
5428 if (inBuffer.frameCount) {
5429 sp<ThreadBase> thread = mThread.promote();
5430 if (thread != 0 && !thread->standby()) {
5431 if (mBufferQueue.size() < kMaxOverFlowBuffers) {
5432 pInBuffer = new Buffer;
5433 pInBuffer->mBuffer = new int16_t[inBuffer.frameCount * channelCount];
5434 pInBuffer->frameCount = inBuffer.frameCount;
5435 pInBuffer->i16 = pInBuffer->mBuffer;
5436 memcpy(pInBuffer->raw, inBuffer.raw, inBuffer.frameCount * channelCount * sizeof(int16_t));
5437 mBufferQueue.add(pInBuffer);
Steve Block3856b092011-10-20 11:56:00 +01005438 ALOGV("OutputTrack::write() %p thread %p adding overflow buffer %d", this, mThread.unsafe_get(), mBufferQueue.size());
Mathias Agopian65ab4712010-07-14 17:59:35 -07005439 } else {
Steve Block5ff1dd52012-01-05 23:22:43 +00005440 ALOGW("OutputTrack::write() %p thread %p no more overflow buffers", mThread.unsafe_get(), this);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005441 }
5442 }
5443 }
5444
5445 // Calling write() with a 0 length buffer, means that no more data will be written:
5446 // If no more buffers are pending, fill output track buffer to make sure it is started
5447 // by output mixer.
5448 if (frames == 0 && mBufferQueue.size() == 0) {
5449 if (mCblk->user < mCblk->frameCount) {
5450 frames = mCblk->frameCount - mCblk->user;
5451 pInBuffer = new Buffer;
5452 pInBuffer->mBuffer = new int16_t[frames * channelCount];
5453 pInBuffer->frameCount = frames;
5454 pInBuffer->i16 = pInBuffer->mBuffer;
5455 memset(pInBuffer->raw, 0, frames * channelCount * sizeof(int16_t));
5456 mBufferQueue.add(pInBuffer);
5457 } else if (mActive) {
5458 stop();
5459 }
5460 }
5461
5462 return outputBufferFull;
5463}
5464
5465status_t AudioFlinger::PlaybackThread::OutputTrack::obtainBuffer(AudioBufferProvider::Buffer* buffer, uint32_t waitTimeMs)
5466{
5467 int active;
5468 status_t result;
5469 audio_track_cblk_t* cblk = mCblk;
5470 uint32_t framesReq = buffer->frameCount;
5471
Steve Block3856b092011-10-20 11:56:00 +01005472// ALOGV("OutputTrack::obtainBuffer user %d, server %d", cblk->user, cblk->server);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005473 buffer->frameCount = 0;
5474
5475 uint32_t framesAvail = cblk->framesAvailable();
5476
5477
5478 if (framesAvail == 0) {
5479 Mutex::Autolock _l(cblk->lock);
5480 goto start_loop_here;
5481 while (framesAvail == 0) {
5482 active = mActive;
Glenn Kastenf6b16782011-12-15 09:51:17 -08005483 if (CC_UNLIKELY(!active)) {
Steve Block3856b092011-10-20 11:56:00 +01005484 ALOGV("Not active and NO_MORE_BUFFERS");
Glenn Kasten335787f2012-01-20 17:00:00 -08005485 return NO_MORE_BUFFERS;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005486 }
5487 result = cblk->cv.waitRelative(cblk->lock, milliseconds(waitTimeMs));
5488 if (result != NO_ERROR) {
Glenn Kasten335787f2012-01-20 17:00:00 -08005489 return NO_MORE_BUFFERS;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005490 }
5491 // read the server count again
5492 start_loop_here:
5493 framesAvail = cblk->framesAvailable_l();
5494 }
5495 }
5496
5497// if (framesAvail < framesReq) {
Glenn Kasten335787f2012-01-20 17:00:00 -08005498// return NO_MORE_BUFFERS;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005499// }
5500
5501 if (framesReq > framesAvail) {
5502 framesReq = framesAvail;
5503 }
5504
5505 uint32_t u = cblk->user;
5506 uint32_t bufferEnd = cblk->userBase + cblk->frameCount;
5507
Marco Nelissena1472d92012-03-30 14:36:54 -07005508 if (framesReq > bufferEnd - u) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07005509 framesReq = bufferEnd - u;
5510 }
5511
5512 buffer->frameCount = framesReq;
5513 buffer->raw = (void *)cblk->buffer(u);
5514 return NO_ERROR;
5515}
5516
5517
5518void AudioFlinger::PlaybackThread::OutputTrack::clearBufferQueue()
5519{
5520 size_t size = mBufferQueue.size();
Mathias Agopian65ab4712010-07-14 17:59:35 -07005521
5522 for (size_t i = 0; i < size; i++) {
Glenn Kastena1117922012-01-26 10:53:32 -08005523 Buffer *pBuffer = mBufferQueue.itemAt(i);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005524 delete [] pBuffer->mBuffer;
5525 delete pBuffer;
5526 }
5527 mBufferQueue.clear();
5528}
5529
5530// ----------------------------------------------------------------------------
5531
5532AudioFlinger::Client::Client(const sp<AudioFlinger>& audioFlinger, pid_t pid)
5533 : RefBase(),
5534 mAudioFlinger(audioFlinger),
Glenn Kasten99e53b82012-01-19 08:59:58 -08005535 // 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 -07005536 mMemoryDealer(new MemoryDealer(1024*1024, "AudioFlinger::Client")),
John Grossman4ff14ba2012-02-08 16:37:41 -08005537 mPid(pid),
5538 mTimedTrackCount(0)
Mathias Agopian65ab4712010-07-14 17:59:35 -07005539{
5540 // 1 MB of address space is good for 32 tracks, 8 buffers each, 4 KB/buffer
5541}
5542
5543// Client destructor must be called with AudioFlinger::mLock held
5544AudioFlinger::Client::~Client()
5545{
5546 mAudioFlinger->removeClient_l(mPid);
5547}
5548
Glenn Kasten435dbe62012-01-30 10:15:48 -08005549sp<MemoryDealer> AudioFlinger::Client::heap() const
Mathias Agopian65ab4712010-07-14 17:59:35 -07005550{
5551 return mMemoryDealer;
5552}
5553
John Grossman4ff14ba2012-02-08 16:37:41 -08005554// Reserve one of the limited slots for a timed audio track associated
5555// with this client
5556bool AudioFlinger::Client::reserveTimedTrack()
5557{
5558 const int kMaxTimedTracksPerClient = 4;
5559
5560 Mutex::Autolock _l(mTimedTrackLock);
5561
5562 if (mTimedTrackCount >= kMaxTimedTracksPerClient) {
5563 ALOGW("can not create timed track - pid %d has exceeded the limit",
5564 mPid);
5565 return false;
5566 }
5567
5568 mTimedTrackCount++;
5569 return true;
5570}
5571
5572// Release a slot for a timed audio track
5573void AudioFlinger::Client::releaseTimedTrack()
5574{
5575 Mutex::Autolock _l(mTimedTrackLock);
5576 mTimedTrackCount--;
5577}
5578
Mathias Agopian65ab4712010-07-14 17:59:35 -07005579// ----------------------------------------------------------------------------
5580
5581AudioFlinger::NotificationClient::NotificationClient(const sp<AudioFlinger>& audioFlinger,
5582 const sp<IAudioFlingerClient>& client,
5583 pid_t pid)
Glenn Kasten84afa3b2012-01-25 15:28:08 -08005584 : mAudioFlinger(audioFlinger), mPid(pid), mAudioFlingerClient(client)
Mathias Agopian65ab4712010-07-14 17:59:35 -07005585{
5586}
5587
5588AudioFlinger::NotificationClient::~NotificationClient()
5589{
Mathias Agopian65ab4712010-07-14 17:59:35 -07005590}
5591
5592void AudioFlinger::NotificationClient::binderDied(const wp<IBinder>& who)
5593{
5594 sp<NotificationClient> keep(this);
Glenn Kastena1117922012-01-26 10:53:32 -08005595 mAudioFlinger->removeNotificationClient(mPid);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005596}
5597
5598// ----------------------------------------------------------------------------
5599
5600AudioFlinger::TrackHandle::TrackHandle(const sp<AudioFlinger::PlaybackThread::Track>& track)
5601 : BnAudioTrack(),
5602 mTrack(track)
5603{
5604}
5605
5606AudioFlinger::TrackHandle::~TrackHandle() {
5607 // just stop the track on deletion, associated resources
5608 // will be freed from the main thread once all pending buffers have
5609 // been played. Unless it's not in the active track list, in which
5610 // case we free everything now...
5611 mTrack->destroy();
5612}
5613
Glenn Kasten90716c52012-01-26 13:40:12 -08005614sp<IMemory> AudioFlinger::TrackHandle::getCblk() const {
5615 return mTrack->getCblk();
5616}
5617
Glenn Kasten3acbd052012-02-28 10:39:56 -08005618status_t AudioFlinger::TrackHandle::start() {
5619 return mTrack->start();
Mathias Agopian65ab4712010-07-14 17:59:35 -07005620}
5621
5622void AudioFlinger::TrackHandle::stop() {
5623 mTrack->stop();
5624}
5625
5626void AudioFlinger::TrackHandle::flush() {
5627 mTrack->flush();
5628}
5629
5630void AudioFlinger::TrackHandle::mute(bool e) {
5631 mTrack->mute(e);
5632}
5633
5634void AudioFlinger::TrackHandle::pause() {
5635 mTrack->pause();
5636}
5637
Mathias Agopian65ab4712010-07-14 17:59:35 -07005638status_t AudioFlinger::TrackHandle::attachAuxEffect(int EffectId)
5639{
5640 return mTrack->attachAuxEffect(EffectId);
5641}
5642
John Grossman4ff14ba2012-02-08 16:37:41 -08005643status_t AudioFlinger::TrackHandle::allocateTimedBuffer(size_t size,
5644 sp<IMemory>* buffer) {
5645 if (!mTrack->isTimedTrack())
5646 return INVALID_OPERATION;
5647
5648 PlaybackThread::TimedTrack* tt =
5649 reinterpret_cast<PlaybackThread::TimedTrack*>(mTrack.get());
5650 return tt->allocateTimedBuffer(size, buffer);
5651}
5652
5653status_t AudioFlinger::TrackHandle::queueTimedBuffer(const sp<IMemory>& buffer,
5654 int64_t pts) {
5655 if (!mTrack->isTimedTrack())
5656 return INVALID_OPERATION;
5657
5658 PlaybackThread::TimedTrack* tt =
5659 reinterpret_cast<PlaybackThread::TimedTrack*>(mTrack.get());
5660 return tt->queueTimedBuffer(buffer, pts);
5661}
5662
5663status_t AudioFlinger::TrackHandle::setMediaTimeTransform(
5664 const LinearTransform& xform, int target) {
5665
5666 if (!mTrack->isTimedTrack())
5667 return INVALID_OPERATION;
5668
5669 PlaybackThread::TimedTrack* tt =
5670 reinterpret_cast<PlaybackThread::TimedTrack*>(mTrack.get());
5671 return tt->setMediaTimeTransform(
5672 xform, static_cast<TimedAudioTrack::TargetTimeline>(target));
5673}
5674
Mathias Agopian65ab4712010-07-14 17:59:35 -07005675status_t AudioFlinger::TrackHandle::onTransact(
5676 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
5677{
5678 return BnAudioTrack::onTransact(code, data, reply, flags);
5679}
5680
5681// ----------------------------------------------------------------------------
5682
5683sp<IAudioRecord> AudioFlinger::openRecord(
5684 pid_t pid,
Glenn Kasten72ef00d2012-01-17 11:09:42 -08005685 audio_io_handle_t input,
Mathias Agopian65ab4712010-07-14 17:59:35 -07005686 uint32_t sampleRate,
Glenn Kasten58f30212012-01-12 12:27:51 -08005687 audio_format_t format,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07005688 uint32_t channelMask,
Mathias Agopian65ab4712010-07-14 17:59:35 -07005689 int frameCount,
Glenn Kastena075db42012-03-06 11:22:44 -08005690 IAudioFlinger::track_flags_t flags,
Mathias Agopian65ab4712010-07-14 17:59:35 -07005691 int *sessionId,
5692 status_t *status)
5693{
5694 sp<RecordThread::RecordTrack> recordTrack;
5695 sp<RecordHandle> recordHandle;
5696 sp<Client> client;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005697 status_t lStatus;
5698 RecordThread *thread;
5699 size_t inFrameCount;
5700 int lSessionId;
5701
5702 // check calling permissions
5703 if (!recordingAllowed()) {
5704 lStatus = PERMISSION_DENIED;
5705 goto Exit;
5706 }
5707
5708 // add client to list
5709 { // scope for mLock
5710 Mutex::Autolock _l(mLock);
5711 thread = checkRecordThread_l(input);
5712 if (thread == NULL) {
5713 lStatus = BAD_VALUE;
5714 goto Exit;
5715 }
5716
Glenn Kasten98ec94c2012-01-25 14:28:29 -08005717 client = registerPid_l(pid);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005718
5719 // If no audio session id is provided, create one here
Dima Zavinfce7a472011-04-19 22:30:36 -07005720 if (sessionId != NULL && *sessionId != AUDIO_SESSION_OUTPUT_MIX) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07005721 lSessionId = *sessionId;
5722 } else {
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005723 lSessionId = nextUniqueId();
Mathias Agopian65ab4712010-07-14 17:59:35 -07005724 if (sessionId != NULL) {
5725 *sessionId = lSessionId;
5726 }
5727 }
5728 // create new record track. The record track uses one track in mHardwareMixerThread by convention.
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005729 recordTrack = thread->createRecordTrack_l(client,
5730 sampleRate,
5731 format,
5732 channelMask,
5733 frameCount,
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005734 lSessionId,
5735 &lStatus);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005736 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005737 if (lStatus != NO_ERROR) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07005738 // remove local strong reference to Client before deleting the RecordTrack so that the Client
5739 // destructor is called by the TrackBase destructor with mLock held
5740 client.clear();
5741 recordTrack.clear();
Mathias Agopian65ab4712010-07-14 17:59:35 -07005742 goto Exit;
5743 }
5744
5745 // return to handle to client
5746 recordHandle = new RecordHandle(recordTrack);
5747 lStatus = NO_ERROR;
5748
5749Exit:
5750 if (status) {
5751 *status = lStatus;
5752 }
5753 return recordHandle;
5754}
5755
5756// ----------------------------------------------------------------------------
5757
5758AudioFlinger::RecordHandle::RecordHandle(const sp<AudioFlinger::RecordThread::RecordTrack>& recordTrack)
5759 : BnAudioRecord(),
5760 mRecordTrack(recordTrack)
5761{
5762}
5763
5764AudioFlinger::RecordHandle::~RecordHandle() {
5765 stop();
5766}
5767
Glenn Kasten90716c52012-01-26 13:40:12 -08005768sp<IMemory> AudioFlinger::RecordHandle::getCblk() const {
5769 return mRecordTrack->getCblk();
5770}
5771
Glenn Kasten3acbd052012-02-28 10:39:56 -08005772status_t AudioFlinger::RecordHandle::start(int event, int triggerSession) {
Steve Block3856b092011-10-20 11:56:00 +01005773 ALOGV("RecordHandle::start()");
Glenn Kasten3acbd052012-02-28 10:39:56 -08005774 return mRecordTrack->start((AudioSystem::sync_event_t)event, triggerSession);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005775}
5776
5777void AudioFlinger::RecordHandle::stop() {
Steve Block3856b092011-10-20 11:56:00 +01005778 ALOGV("RecordHandle::stop()");
Mathias Agopian65ab4712010-07-14 17:59:35 -07005779 mRecordTrack->stop();
5780}
5781
Mathias Agopian65ab4712010-07-14 17:59:35 -07005782status_t AudioFlinger::RecordHandle::onTransact(
5783 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
5784{
5785 return BnAudioRecord::onTransact(code, data, reply, flags);
5786}
5787
5788// ----------------------------------------------------------------------------
5789
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005790AudioFlinger::RecordThread::RecordThread(const sp<AudioFlinger>& audioFlinger,
5791 AudioStreamIn *input,
5792 uint32_t sampleRate,
5793 uint32_t channels,
Glenn Kasten72ef00d2012-01-17 11:09:42 -08005794 audio_io_handle_t id,
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005795 uint32_t device) :
Glenn Kasten23bb8be2012-01-26 10:38:26 -08005796 ThreadBase(audioFlinger, id, device, RECORD),
Glenn Kasten84afa3b2012-01-25 15:28:08 -08005797 mInput(input), mTrack(NULL), mResampler(NULL), mRsmpOutBuffer(NULL), mRsmpInBuffer(NULL),
5798 // mRsmpInIndex and mInputBytes set by readInputParameters()
5799 mReqChannelCount(popcount(channels)),
5800 mReqSampleRate(sampleRate)
5801 // mBytesRead is only meaningful while active, and so is cleared in start()
5802 // (but might be better to also clear here for dump?)
Mathias Agopian65ab4712010-07-14 17:59:35 -07005803{
Glenn Kasten480b4682012-02-28 12:30:08 -08005804 snprintf(mName, kNameLength, "AudioIn_%X", id);
Eric Laurentfeb0db62011-07-22 09:04:31 -07005805
Mathias Agopian65ab4712010-07-14 17:59:35 -07005806 readInputParameters();
5807}
5808
5809
5810AudioFlinger::RecordThread::~RecordThread()
5811{
5812 delete[] mRsmpInBuffer;
Glenn Kastene9dd0172012-01-27 18:08:45 -08005813 delete mResampler;
5814 delete[] mRsmpOutBuffer;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005815}
5816
5817void AudioFlinger::RecordThread::onFirstRef()
5818{
Eric Laurentfeb0db62011-07-22 09:04:31 -07005819 run(mName, PRIORITY_URGENT_AUDIO);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005820}
5821
Eric Laurentb8ba0a92011-08-07 16:32:26 -07005822status_t AudioFlinger::RecordThread::readyToRun()
5823{
5824 status_t status = initCheck();
Steve Block5ff1dd52012-01-05 23:22:43 +00005825 ALOGW_IF(status != NO_ERROR,"RecordThread %p could not initialize", this);
Eric Laurentb8ba0a92011-08-07 16:32:26 -07005826 return status;
5827}
5828
Mathias Agopian65ab4712010-07-14 17:59:35 -07005829bool AudioFlinger::RecordThread::threadLoop()
5830{
5831 AudioBufferProvider::Buffer buffer;
5832 sp<RecordTrack> activeTrack;
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005833 Vector< sp<EffectChain> > effectChains;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005834
Eric Laurent44d98482010-09-30 16:12:31 -07005835 nsecs_t lastWarning = 0;
5836
Eric Laurentfeb0db62011-07-22 09:04:31 -07005837 acquireWakeLock();
5838
Mathias Agopian65ab4712010-07-14 17:59:35 -07005839 // start recording
5840 while (!exitPending()) {
5841
5842 processConfigEvents();
5843
5844 { // scope for mLock
5845 Mutex::Autolock _l(mLock);
5846 checkForNewParameters_l();
5847 if (mActiveTrack == 0 && mConfigEvents.isEmpty()) {
5848 if (!mStandby) {
Dima Zavin799a70e2011-04-18 16:57:27 -07005849 mInput->stream->common.standby(&mInput->stream->common);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005850 mStandby = true;
5851 }
5852
5853 if (exitPending()) break;
5854
Eric Laurentfeb0db62011-07-22 09:04:31 -07005855 releaseWakeLock_l();
Steve Block3856b092011-10-20 11:56:00 +01005856 ALOGV("RecordThread: loop stopping");
Mathias Agopian65ab4712010-07-14 17:59:35 -07005857 // go to sleep
5858 mWaitWorkCV.wait(mLock);
Steve Block3856b092011-10-20 11:56:00 +01005859 ALOGV("RecordThread: loop starting");
Eric Laurentfeb0db62011-07-22 09:04:31 -07005860 acquireWakeLock_l();
Mathias Agopian65ab4712010-07-14 17:59:35 -07005861 continue;
5862 }
5863 if (mActiveTrack != 0) {
5864 if (mActiveTrack->mState == TrackBase::PAUSING) {
5865 if (!mStandby) {
Dima Zavin799a70e2011-04-18 16:57:27 -07005866 mInput->stream->common.standby(&mInput->stream->common);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005867 mStandby = true;
5868 }
5869 mActiveTrack.clear();
5870 mStartStopCond.broadcast();
5871 } else if (mActiveTrack->mState == TrackBase::RESUMING) {
5872 if (mReqChannelCount != mActiveTrack->channelCount()) {
5873 mActiveTrack.clear();
5874 mStartStopCond.broadcast();
5875 } else if (mBytesRead != 0) {
5876 // record start succeeds only if first read from audio input
5877 // succeeds
5878 if (mBytesRead > 0) {
5879 mActiveTrack->mState = TrackBase::ACTIVE;
5880 } else {
5881 mActiveTrack.clear();
5882 }
5883 mStartStopCond.broadcast();
5884 }
5885 mStandby = false;
5886 }
5887 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005888 lockEffectChains_l(effectChains);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005889 }
5890
5891 if (mActiveTrack != 0) {
5892 if (mActiveTrack->mState != TrackBase::ACTIVE &&
5893 mActiveTrack->mState != TrackBase::RESUMING) {
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005894 unlockEffectChains(effectChains);
5895 usleep(kRecordThreadSleepUs);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005896 continue;
5897 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005898 for (size_t i = 0; i < effectChains.size(); i ++) {
5899 effectChains[i]->process_l();
5900 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005901
Mathias Agopian65ab4712010-07-14 17:59:35 -07005902 buffer.frameCount = mFrameCount;
Glenn Kasten01c4ebf2012-02-22 10:47:35 -08005903 if (CC_LIKELY(mActiveTrack->getNextBuffer(&buffer) == NO_ERROR)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07005904 size_t framesOut = buffer.frameCount;
Glenn Kastene0feee32011-12-13 11:53:26 -08005905 if (mResampler == NULL) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07005906 // no resampling
5907 while (framesOut) {
5908 size_t framesIn = mFrameCount - mRsmpInIndex;
5909 if (framesIn) {
5910 int8_t *src = (int8_t *)mRsmpInBuffer + mRsmpInIndex * mFrameSize;
5911 int8_t *dst = buffer.i8 + (buffer.frameCount - framesOut) * mActiveTrack->mCblk->frameSize;
5912 if (framesIn > framesOut)
5913 framesIn = framesOut;
5914 mRsmpInIndex += framesIn;
5915 framesOut -= framesIn;
5916 if ((int)mChannelCount == mReqChannelCount ||
Dima Zavinfce7a472011-04-19 22:30:36 -07005917 mFormat != AUDIO_FORMAT_PCM_16_BIT) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07005918 memcpy(dst, src, framesIn * mFrameSize);
5919 } else {
5920 int16_t *src16 = (int16_t *)src;
5921 int16_t *dst16 = (int16_t *)dst;
5922 if (mChannelCount == 1) {
5923 while (framesIn--) {
5924 *dst16++ = *src16;
5925 *dst16++ = *src16++;
5926 }
5927 } else {
5928 while (framesIn--) {
5929 *dst16++ = (int16_t)(((int32_t)*src16 + (int32_t)*(src16 + 1)) >> 1);
5930 src16 += 2;
5931 }
5932 }
5933 }
5934 }
5935 if (framesOut && mFrameCount == mRsmpInIndex) {
5936 if (framesOut == mFrameCount &&
Dima Zavinfce7a472011-04-19 22:30:36 -07005937 ((int)mChannelCount == mReqChannelCount || mFormat != AUDIO_FORMAT_PCM_16_BIT)) {
Dima Zavin799a70e2011-04-18 16:57:27 -07005938 mBytesRead = mInput->stream->read(mInput->stream, buffer.raw, mInputBytes);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005939 framesOut = 0;
5940 } else {
Dima Zavin799a70e2011-04-18 16:57:27 -07005941 mBytesRead = mInput->stream->read(mInput->stream, mRsmpInBuffer, mInputBytes);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005942 mRsmpInIndex = 0;
5943 }
5944 if (mBytesRead < 0) {
Steve Block29357bc2012-01-06 19:20:56 +00005945 ALOGE("Error reading audio input");
Mathias Agopian65ab4712010-07-14 17:59:35 -07005946 if (mActiveTrack->mState == TrackBase::ACTIVE) {
5947 // Force input into standby so that it tries to
5948 // recover at next read attempt
Dima Zavin799a70e2011-04-18 16:57:27 -07005949 mInput->stream->common.standby(&mInput->stream->common);
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005950 usleep(kRecordThreadSleepUs);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005951 }
5952 mRsmpInIndex = mFrameCount;
5953 framesOut = 0;
5954 buffer.frameCount = 0;
5955 }
5956 }
5957 }
5958 } else {
5959 // resampling
5960
5961 memset(mRsmpOutBuffer, 0, framesOut * 2 * sizeof(int32_t));
5962 // alter output frame count as if we were expecting stereo samples
5963 if (mChannelCount == 1 && mReqChannelCount == 1) {
5964 framesOut >>= 1;
5965 }
5966 mResampler->resample(mRsmpOutBuffer, framesOut, this);
5967 // ditherAndClamp() works as long as all buffers returned by mActiveTrack->getNextBuffer()
5968 // are 32 bit aligned which should be always true.
5969 if (mChannelCount == 2 && mReqChannelCount == 1) {
Glenn Kasten3b21c502011-12-15 09:52:39 -08005970 ditherAndClamp(mRsmpOutBuffer, mRsmpOutBuffer, framesOut);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005971 // the resampler always outputs stereo samples: do post stereo to mono conversion
5972 int16_t *src = (int16_t *)mRsmpOutBuffer;
5973 int16_t *dst = buffer.i16;
5974 while (framesOut--) {
5975 *dst++ = (int16_t)(((int32_t)*src + (int32_t)*(src + 1)) >> 1);
5976 src += 2;
5977 }
5978 } else {
Glenn Kasten3b21c502011-12-15 09:52:39 -08005979 ditherAndClamp((int32_t *)buffer.raw, mRsmpOutBuffer, framesOut);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005980 }
5981
5982 }
Eric Laurenta011e352012-03-29 15:51:43 -07005983 if (mFramestoDrop == 0) {
5984 mActiveTrack->releaseBuffer(&buffer);
5985 } else {
5986 if (mFramestoDrop > 0) {
5987 mFramestoDrop -= buffer.frameCount;
Eric Laurent29864602012-05-08 18:57:51 -07005988 if (mFramestoDrop <= 0) {
5989 clearSyncStartEvent();
5990 }
5991 } else {
5992 mFramestoDrop += buffer.frameCount;
5993 if (mFramestoDrop >= 0 || mSyncStartEvent == 0 ||
5994 mSyncStartEvent->isCancelled()) {
5995 ALOGW("Synced record %s, session %d, trigger session %d",
5996 (mFramestoDrop >= 0) ? "timed out" : "cancelled",
5997 mActiveTrack->sessionId(),
5998 (mSyncStartEvent != 0) ? mSyncStartEvent->triggerSession() : 0);
5999 clearSyncStartEvent();
Eric Laurenta011e352012-03-29 15:51:43 -07006000 }
6001 }
6002 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07006003 mActiveTrack->overflow();
6004 }
6005 // client isn't retrieving buffers fast enough
6006 else {
Eric Laurent44d98482010-09-30 16:12:31 -07006007 if (!mActiveTrack->setOverflow()) {
6008 nsecs_t now = systemTime();
Glenn Kasten7dede872011-12-13 11:04:14 -08006009 if ((now - lastWarning) > kWarningThrottleNs) {
Steve Block5ff1dd52012-01-05 23:22:43 +00006010 ALOGW("RecordThread: buffer overflow");
Eric Laurent44d98482010-09-30 16:12:31 -07006011 lastWarning = now;
6012 }
6013 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07006014 // Release the processor for a while before asking for a new buffer.
6015 // This will give the application more chance to read from the buffer and
6016 // clear the overflow.
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006017 usleep(kRecordThreadSleepUs);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006018 }
6019 }
Eric Laurentec437d82011-07-26 20:54:46 -07006020 // enable changes in effect chain
6021 unlockEffectChains(effectChains);
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006022 effectChains.clear();
Mathias Agopian65ab4712010-07-14 17:59:35 -07006023 }
6024
6025 if (!mStandby) {
Dima Zavin799a70e2011-04-18 16:57:27 -07006026 mInput->stream->common.standby(&mInput->stream->common);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006027 }
6028 mActiveTrack.clear();
6029
6030 mStartStopCond.broadcast();
6031
Eric Laurentfeb0db62011-07-22 09:04:31 -07006032 releaseWakeLock();
6033
Steve Block3856b092011-10-20 11:56:00 +01006034 ALOGV("RecordThread %p exiting", this);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006035 return false;
6036}
6037
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006038
6039sp<AudioFlinger::RecordThread::RecordTrack> AudioFlinger::RecordThread::createRecordTrack_l(
6040 const sp<AudioFlinger::Client>& client,
6041 uint32_t sampleRate,
Glenn Kasten58f30212012-01-12 12:27:51 -08006042 audio_format_t format,
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006043 int channelMask,
6044 int frameCount,
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006045 int sessionId,
6046 status_t *status)
6047{
6048 sp<RecordTrack> track;
6049 status_t lStatus;
6050
6051 lStatus = initCheck();
6052 if (lStatus != NO_ERROR) {
Steve Block29357bc2012-01-06 19:20:56 +00006053 ALOGE("Audio driver not initialized.");
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006054 goto Exit;
6055 }
6056
6057 { // scope for mLock
6058 Mutex::Autolock _l(mLock);
6059
6060 track = new RecordTrack(this, client, sampleRate,
Glenn Kasten5cf034d2012-02-21 10:35:56 -08006061 format, channelMask, frameCount, sessionId);
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006062
Glenn Kasten7378ca52012-01-20 13:44:40 -08006063 if (track->getCblk() == 0) {
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006064 lStatus = NO_MEMORY;
6065 goto Exit;
6066 }
6067
6068 mTrack = track.get();
Eric Laurent59bd0da2011-08-01 09:52:20 -07006069 // disable AEC and NS if the device is a BT SCO headset supporting those pre processings
6070 bool suspend = audio_is_bluetooth_sco_device(
Eric Laurentbee53372011-08-29 12:42:48 -07006071 (audio_devices_t)(mDevice & AUDIO_DEVICE_IN_ALL)) && mAudioFlinger->btNrecIsOff();
Eric Laurent59bd0da2011-08-01 09:52:20 -07006072 setEffectSuspended_l(FX_IID_AEC, suspend, sessionId);
6073 setEffectSuspended_l(FX_IID_NS, suspend, sessionId);
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006074 }
6075 lStatus = NO_ERROR;
6076
6077Exit:
6078 if (status) {
6079 *status = lStatus;
6080 }
6081 return track;
6082}
6083
Eric Laurenta011e352012-03-29 15:51:43 -07006084status_t AudioFlinger::RecordThread::start(RecordThread::RecordTrack* recordTrack,
Glenn Kasten3acbd052012-02-28 10:39:56 -08006085 AudioSystem::sync_event_t event,
Eric Laurenta011e352012-03-29 15:51:43 -07006086 int triggerSession)
Mathias Agopian65ab4712010-07-14 17:59:35 -07006087{
Glenn Kasten58912562012-04-03 10:45:00 -07006088 ALOGV("RecordThread::start event %d, triggerSession %d", event, triggerSession);
Glenn Kastene53b9ea2012-03-12 16:29:55 -07006089 sp<ThreadBase> strongMe = this;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006090 status_t status = NO_ERROR;
Eric Laurenta011e352012-03-29 15:51:43 -07006091
6092 if (event == AudioSystem::SYNC_EVENT_NONE) {
Eric Laurent29864602012-05-08 18:57:51 -07006093 clearSyncStartEvent();
Eric Laurenta011e352012-03-29 15:51:43 -07006094 } else if (event != AudioSystem::SYNC_EVENT_SAME) {
6095 mSyncStartEvent = mAudioFlinger->createSyncEvent(event,
6096 triggerSession,
6097 recordTrack->sessionId(),
6098 syncStartEventCallback,
6099 this);
Eric Laurent29864602012-05-08 18:57:51 -07006100 // Sync event can be cancelled by the trigger session if the track is not in a
6101 // compatible state in which case we start record immediately
6102 if (mSyncStartEvent->isCancelled()) {
6103 clearSyncStartEvent();
6104 } else {
6105 // do not wait for the event for more than AudioSystem::kSyncRecordStartTimeOutMs
6106 mFramestoDrop = - ((AudioSystem::kSyncRecordStartTimeOutMs * mReqSampleRate) / 1000);
6107 }
Eric Laurenta011e352012-03-29 15:51:43 -07006108 }
6109
Mathias Agopian65ab4712010-07-14 17:59:35 -07006110 {
Glenn Kastena7d8d6f2012-01-05 15:41:56 -08006111 AutoMutex lock(mLock);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006112 if (mActiveTrack != 0) {
6113 if (recordTrack != mActiveTrack.get()) {
6114 status = -EBUSY;
6115 } else if (mActiveTrack->mState == TrackBase::PAUSING) {
6116 mActiveTrack->mState = TrackBase::ACTIVE;
6117 }
6118 return status;
6119 }
6120
6121 recordTrack->mState = TrackBase::IDLE;
6122 mActiveTrack = recordTrack;
6123 mLock.unlock();
6124 status_t status = AudioSystem::startInput(mId);
6125 mLock.lock();
6126 if (status != NO_ERROR) {
6127 mActiveTrack.clear();
Eric Laurenta011e352012-03-29 15:51:43 -07006128 clearSyncStartEvent();
Mathias Agopian65ab4712010-07-14 17:59:35 -07006129 return status;
6130 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07006131 mRsmpInIndex = mFrameCount;
6132 mBytesRead = 0;
Eric Laurent243f5f92011-02-28 16:52:51 -08006133 if (mResampler != NULL) {
6134 mResampler->reset();
6135 }
6136 mActiveTrack->mState = TrackBase::RESUMING;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006137 // signal thread to start
Steve Block3856b092011-10-20 11:56:00 +01006138 ALOGV("Signal record thread");
Mathias Agopian65ab4712010-07-14 17:59:35 -07006139 mWaitWorkCV.signal();
6140 // do not wait for mStartStopCond if exiting
Glenn Kastenb28686f2012-01-06 08:39:38 -08006141 if (exitPending()) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07006142 mActiveTrack.clear();
6143 status = INVALID_OPERATION;
6144 goto startError;
6145 }
6146 mStartStopCond.wait(mLock);
6147 if (mActiveTrack == 0) {
Steve Block3856b092011-10-20 11:56:00 +01006148 ALOGV("Record failed to start");
Mathias Agopian65ab4712010-07-14 17:59:35 -07006149 status = BAD_VALUE;
6150 goto startError;
6151 }
Steve Block3856b092011-10-20 11:56:00 +01006152 ALOGV("Record started OK");
Mathias Agopian65ab4712010-07-14 17:59:35 -07006153 return status;
6154 }
6155startError:
6156 AudioSystem::stopInput(mId);
Eric Laurenta011e352012-03-29 15:51:43 -07006157 clearSyncStartEvent();
Mathias Agopian65ab4712010-07-14 17:59:35 -07006158 return status;
6159}
6160
Eric Laurenta011e352012-03-29 15:51:43 -07006161void AudioFlinger::RecordThread::clearSyncStartEvent()
6162{
6163 if (mSyncStartEvent != 0) {
6164 mSyncStartEvent->cancel();
6165 }
6166 mSyncStartEvent.clear();
Eric Laurent29864602012-05-08 18:57:51 -07006167 mFramestoDrop = 0;
Eric Laurenta011e352012-03-29 15:51:43 -07006168}
6169
6170void AudioFlinger::RecordThread::syncStartEventCallback(const wp<SyncEvent>& event)
6171{
6172 sp<SyncEvent> strongEvent = event.promote();
6173
6174 if (strongEvent != 0) {
6175 RecordThread *me = (RecordThread *)strongEvent->cookie();
6176 me->handleSyncStartEvent(strongEvent);
6177 }
6178}
6179
6180void AudioFlinger::RecordThread::handleSyncStartEvent(const sp<SyncEvent>& event)
6181{
Eric Laurent29864602012-05-08 18:57:51 -07006182 if (event == mSyncStartEvent) {
Eric Laurenta011e352012-03-29 15:51:43 -07006183 // TODO: use actual buffer filling status instead of 2 buffers when info is available
6184 // from audio HAL
6185 mFramestoDrop = mFrameCount * 2;
Eric Laurenta011e352012-03-29 15:51:43 -07006186 }
6187}
6188
Mathias Agopian65ab4712010-07-14 17:59:35 -07006189void AudioFlinger::RecordThread::stop(RecordThread::RecordTrack* recordTrack) {
Steve Block3856b092011-10-20 11:56:00 +01006190 ALOGV("RecordThread::stop");
Glenn Kastene53b9ea2012-03-12 16:29:55 -07006191 sp<ThreadBase> strongMe = this;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006192 {
Glenn Kastena7d8d6f2012-01-05 15:41:56 -08006193 AutoMutex lock(mLock);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006194 if (mActiveTrack != 0 && recordTrack == mActiveTrack.get()) {
6195 mActiveTrack->mState = TrackBase::PAUSING;
6196 // do not wait for mStartStopCond if exiting
Glenn Kastenb28686f2012-01-06 08:39:38 -08006197 if (exitPending()) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07006198 return;
6199 }
6200 mStartStopCond.wait(mLock);
6201 // if we have been restarted, recordTrack == mActiveTrack.get() here
6202 if (mActiveTrack == 0 || recordTrack != mActiveTrack.get()) {
6203 mLock.unlock();
6204 AudioSystem::stopInput(mId);
6205 mLock.lock();
Steve Block3856b092011-10-20 11:56:00 +01006206 ALOGV("Record stopped OK");
Mathias Agopian65ab4712010-07-14 17:59:35 -07006207 }
6208 }
6209 }
6210}
6211
Eric Laurenta011e352012-03-29 15:51:43 -07006212bool AudioFlinger::RecordThread::isValidSyncEvent(const sp<SyncEvent>& event)
6213{
6214 return false;
6215}
6216
6217status_t AudioFlinger::RecordThread::setSyncEvent(const sp<SyncEvent>& event)
6218{
6219 if (!isValidSyncEvent(event)) {
6220 return BAD_VALUE;
6221 }
6222
6223 Mutex::Autolock _l(mLock);
6224
6225 if (mTrack != NULL && event->triggerSession() == mTrack->sessionId()) {
6226 mTrack->setSyncEvent(event);
6227 return NO_ERROR;
6228 }
6229 return NAME_NOT_FOUND;
6230}
6231
Mathias Agopian65ab4712010-07-14 17:59:35 -07006232status_t AudioFlinger::RecordThread::dump(int fd, const Vector<String16>& args)
6233{
6234 const size_t SIZE = 256;
6235 char buffer[SIZE];
6236 String8 result;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006237
6238 snprintf(buffer, SIZE, "\nInput thread %p internals\n", this);
6239 result.append(buffer);
6240
6241 if (mActiveTrack != 0) {
6242 result.append("Active Track:\n");
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07006243 result.append(" Clien Fmt Chn mask Session Buf S SRate Serv User\n");
Mathias Agopian65ab4712010-07-14 17:59:35 -07006244 mActiveTrack->dump(buffer, SIZE);
6245 result.append(buffer);
6246
6247 snprintf(buffer, SIZE, "In index: %d\n", mRsmpInIndex);
6248 result.append(buffer);
6249 snprintf(buffer, SIZE, "In size: %d\n", mInputBytes);
6250 result.append(buffer);
Glenn Kastene0feee32011-12-13 11:53:26 -08006251 snprintf(buffer, SIZE, "Resampling: %d\n", (mResampler != NULL));
Mathias Agopian65ab4712010-07-14 17:59:35 -07006252 result.append(buffer);
6253 snprintf(buffer, SIZE, "Out channel count: %d\n", mReqChannelCount);
6254 result.append(buffer);
6255 snprintf(buffer, SIZE, "Out sample rate: %d\n", mReqSampleRate);
6256 result.append(buffer);
6257
6258
6259 } else {
6260 result.append("No record client\n");
6261 }
6262 write(fd, result.string(), result.size());
6263
6264 dumpBase(fd, args);
Eric Laurent1d2bff02011-07-24 17:49:51 -07006265 dumpEffectChains(fd, args);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006266
6267 return NO_ERROR;
6268}
6269
Glenn Kasten01c4ebf2012-02-22 10:47:35 -08006270// AudioBufferProvider interface
John Grossman4ff14ba2012-02-08 16:37:41 -08006271status_t AudioFlinger::RecordThread::getNextBuffer(AudioBufferProvider::Buffer* buffer, int64_t pts)
Mathias Agopian65ab4712010-07-14 17:59:35 -07006272{
6273 size_t framesReq = buffer->frameCount;
6274 size_t framesReady = mFrameCount - mRsmpInIndex;
6275 int channelCount;
6276
6277 if (framesReady == 0) {
Dima Zavin799a70e2011-04-18 16:57:27 -07006278 mBytesRead = mInput->stream->read(mInput->stream, mRsmpInBuffer, mInputBytes);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006279 if (mBytesRead < 0) {
Steve Block29357bc2012-01-06 19:20:56 +00006280 ALOGE("RecordThread::getNextBuffer() Error reading audio input");
Mathias Agopian65ab4712010-07-14 17:59:35 -07006281 if (mActiveTrack->mState == TrackBase::ACTIVE) {
6282 // Force input into standby so that it tries to
6283 // recover at next read attempt
Dima Zavin799a70e2011-04-18 16:57:27 -07006284 mInput->stream->common.standby(&mInput->stream->common);
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006285 usleep(kRecordThreadSleepUs);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006286 }
Glenn Kastene0feee32011-12-13 11:53:26 -08006287 buffer->raw = NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006288 buffer->frameCount = 0;
6289 return NOT_ENOUGH_DATA;
6290 }
6291 mRsmpInIndex = 0;
6292 framesReady = mFrameCount;
6293 }
6294
6295 if (framesReq > framesReady) {
6296 framesReq = framesReady;
6297 }
6298
6299 if (mChannelCount == 1 && mReqChannelCount == 2) {
6300 channelCount = 1;
6301 } else {
6302 channelCount = 2;
6303 }
6304 buffer->raw = mRsmpInBuffer + mRsmpInIndex * channelCount;
6305 buffer->frameCount = framesReq;
6306 return NO_ERROR;
6307}
6308
Glenn Kasten01c4ebf2012-02-22 10:47:35 -08006309// AudioBufferProvider interface
Mathias Agopian65ab4712010-07-14 17:59:35 -07006310void AudioFlinger::RecordThread::releaseBuffer(AudioBufferProvider::Buffer* buffer)
6311{
6312 mRsmpInIndex += buffer->frameCount;
6313 buffer->frameCount = 0;
6314}
6315
6316bool AudioFlinger::RecordThread::checkForNewParameters_l()
6317{
6318 bool reconfig = false;
6319
6320 while (!mNewParameters.isEmpty()) {
6321 status_t status = NO_ERROR;
6322 String8 keyValuePair = mNewParameters[0];
6323 AudioParameter param = AudioParameter(keyValuePair);
6324 int value;
Glenn Kasten58f30212012-01-12 12:27:51 -08006325 audio_format_t reqFormat = mFormat;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006326 int reqSamplingRate = mReqSampleRate;
6327 int reqChannelCount = mReqChannelCount;
6328
6329 if (param.getInt(String8(AudioParameter::keySamplingRate), value) == NO_ERROR) {
6330 reqSamplingRate = value;
6331 reconfig = true;
6332 }
6333 if (param.getInt(String8(AudioParameter::keyFormat), value) == NO_ERROR) {
Glenn Kasten58f30212012-01-12 12:27:51 -08006334 reqFormat = (audio_format_t) value;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006335 reconfig = true;
6336 }
6337 if (param.getInt(String8(AudioParameter::keyChannels), value) == NO_ERROR) {
Dima Zavinfce7a472011-04-19 22:30:36 -07006338 reqChannelCount = popcount(value);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006339 reconfig = true;
6340 }
6341 if (param.getInt(String8(AudioParameter::keyFrameCount), value) == NO_ERROR) {
6342 // do not accept frame count changes if tracks are open as the track buffer
Glenn Kasten99e53b82012-01-19 08:59:58 -08006343 // size depends on frame count and correct behavior would not be guaranteed
Mathias Agopian65ab4712010-07-14 17:59:35 -07006344 // if frame count is changed after track creation
6345 if (mActiveTrack != 0) {
6346 status = INVALID_OPERATION;
6347 } else {
6348 reconfig = true;
6349 }
6350 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006351 if (param.getInt(String8(AudioParameter::keyRouting), value) == NO_ERROR) {
6352 // forward device change to effects that have requested to be
6353 // aware of attached audio device.
6354 for (size_t i = 0; i < mEffectChains.size(); i++) {
6355 mEffectChains[i]->setDevice_l(value);
6356 }
6357 // store input device and output device but do not forward output device to audio HAL.
6358 // Note that status is ignored by the caller for output device
6359 // (see AudioFlinger::setParameters()
6360 if (value & AUDIO_DEVICE_OUT_ALL) {
6361 mDevice &= (uint32_t)~(value & AUDIO_DEVICE_OUT_ALL);
6362 status = BAD_VALUE;
6363 } else {
6364 mDevice &= (uint32_t)~(value & AUDIO_DEVICE_IN_ALL);
Eric Laurent59bd0da2011-08-01 09:52:20 -07006365 // disable AEC and NS if the device is a BT SCO headset supporting those pre processings
6366 if (mTrack != NULL) {
6367 bool suspend = audio_is_bluetooth_sco_device(
Eric Laurentbee53372011-08-29 12:42:48 -07006368 (audio_devices_t)value) && mAudioFlinger->btNrecIsOff();
Eric Laurent59bd0da2011-08-01 09:52:20 -07006369 setEffectSuspended_l(FX_IID_AEC, suspend, mTrack->sessionId());
6370 setEffectSuspended_l(FX_IID_NS, suspend, mTrack->sessionId());
6371 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006372 }
6373 mDevice |= (uint32_t)value;
6374 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07006375 if (status == NO_ERROR) {
Dima Zavin799a70e2011-04-18 16:57:27 -07006376 status = mInput->stream->common.set_parameters(&mInput->stream->common, keyValuePair.string());
Mathias Agopian65ab4712010-07-14 17:59:35 -07006377 if (status == INVALID_OPERATION) {
Glenn Kastene53b9ea2012-03-12 16:29:55 -07006378 mInput->stream->common.standby(&mInput->stream->common);
6379 status = mInput->stream->common.set_parameters(&mInput->stream->common,
6380 keyValuePair.string());
Mathias Agopian65ab4712010-07-14 17:59:35 -07006381 }
6382 if (reconfig) {
6383 if (status == BAD_VALUE &&
Dima Zavin799a70e2011-04-18 16:57:27 -07006384 reqFormat == mInput->stream->common.get_format(&mInput->stream->common) &&
Dima Zavinfce7a472011-04-19 22:30:36 -07006385 reqFormat == AUDIO_FORMAT_PCM_16_BIT &&
Dima Zavin799a70e2011-04-18 16:57:27 -07006386 ((int)mInput->stream->common.get_sample_rate(&mInput->stream->common) <= (2 * reqSamplingRate)) &&
Glenn Kasten53d76db2012-03-08 12:32:47 -08006387 popcount(mInput->stream->common.get_channels(&mInput->stream->common)) <= FCC_2 &&
6388 (reqChannelCount <= FCC_2)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07006389 status = NO_ERROR;
6390 }
6391 if (status == NO_ERROR) {
6392 readInputParameters();
6393 sendConfigEvent_l(AudioSystem::INPUT_CONFIG_CHANGED);
6394 }
6395 }
6396 }
6397
6398 mNewParameters.removeAt(0);
6399
6400 mParamStatus = status;
6401 mParamCond.signal();
Eric Laurent60cd0a02011-09-13 11:40:21 -07006402 // wait for condition with time out in case the thread calling ThreadBase::setParameters()
6403 // already timed out waiting for the status and will never signal the condition.
Glenn Kasten7dede872011-12-13 11:04:14 -08006404 mWaitWorkCV.waitRelative(mLock, kSetParametersTimeoutNs);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006405 }
6406 return reconfig;
6407}
6408
6409String8 AudioFlinger::RecordThread::getParameters(const String8& keys)
6410{
Dima Zavinfce7a472011-04-19 22:30:36 -07006411 char *s;
Eric Laurentb8ba0a92011-08-07 16:32:26 -07006412 String8 out_s8 = String8();
6413
6414 Mutex::Autolock _l(mLock);
6415 if (initCheck() != NO_ERROR) {
6416 return out_s8;
6417 }
Dima Zavinfce7a472011-04-19 22:30:36 -07006418
Dima Zavin799a70e2011-04-18 16:57:27 -07006419 s = mInput->stream->common.get_parameters(&mInput->stream->common, keys.string());
Dima Zavinfce7a472011-04-19 22:30:36 -07006420 out_s8 = String8(s);
6421 free(s);
6422 return out_s8;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006423}
6424
6425void AudioFlinger::RecordThread::audioConfigChanged_l(int event, int param) {
6426 AudioSystem::OutputDescriptor desc;
Glenn Kastena0d68332012-01-27 16:47:15 -08006427 void *param2 = NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006428
6429 switch (event) {
6430 case AudioSystem::INPUT_OPENED:
6431 case AudioSystem::INPUT_CONFIG_CHANGED:
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07006432 desc.channels = mChannelMask;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006433 desc.samplingRate = mSampleRate;
6434 desc.format = mFormat;
6435 desc.frameCount = mFrameCount;
6436 desc.latency = 0;
6437 param2 = &desc;
6438 break;
6439
6440 case AudioSystem::INPUT_CLOSED:
6441 default:
6442 break;
6443 }
6444 mAudioFlinger->audioConfigChanged_l(event, mId, param2);
6445}
6446
6447void AudioFlinger::RecordThread::readInputParameters()
6448{
Glenn Kastene9dd0172012-01-27 18:08:45 -08006449 delete mRsmpInBuffer;
6450 // mRsmpInBuffer is always assigned a new[] below
6451 delete mRsmpOutBuffer;
6452 mRsmpOutBuffer = NULL;
6453 delete mResampler;
Glenn Kastene0feee32011-12-13 11:53:26 -08006454 mResampler = NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006455
Dima Zavin799a70e2011-04-18 16:57:27 -07006456 mSampleRate = mInput->stream->common.get_sample_rate(&mInput->stream->common);
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07006457 mChannelMask = mInput->stream->common.get_channels(&mInput->stream->common);
6458 mChannelCount = (uint16_t)popcount(mChannelMask);
Dima Zavin799a70e2011-04-18 16:57:27 -07006459 mFormat = mInput->stream->common.get_format(&mInput->stream->common);
Glenn Kastenb9980652012-01-11 09:48:27 -08006460 mFrameSize = audio_stream_frame_size(&mInput->stream->common);
Dima Zavin799a70e2011-04-18 16:57:27 -07006461 mInputBytes = mInput->stream->common.get_buffer_size(&mInput->stream->common);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006462 mFrameCount = mInputBytes / mFrameSize;
Glenn Kasten58912562012-04-03 10:45:00 -07006463 mNormalFrameCount = mFrameCount; // not used by record, but used by input effects
Mathias Agopian65ab4712010-07-14 17:59:35 -07006464 mRsmpInBuffer = new int16_t[mFrameCount * mChannelCount];
6465
Glenn Kasten53d76db2012-03-08 12:32:47 -08006466 if (mSampleRate != mReqSampleRate && mChannelCount <= FCC_2 && mReqChannelCount <= FCC_2)
Mathias Agopian65ab4712010-07-14 17:59:35 -07006467 {
6468 int channelCount;
Glenn Kastene53b9ea2012-03-12 16:29:55 -07006469 // optimization: if mono to mono, use the resampler in stereo to stereo mode to avoid
6470 // stereo to mono post process as the resampler always outputs stereo.
Mathias Agopian65ab4712010-07-14 17:59:35 -07006471 if (mChannelCount == 1 && mReqChannelCount == 2) {
6472 channelCount = 1;
6473 } else {
6474 channelCount = 2;
6475 }
6476 mResampler = AudioResampler::create(16, channelCount, mReqSampleRate);
6477 mResampler->setSampleRate(mSampleRate);
6478 mResampler->setVolume(AudioMixer::UNITY_GAIN, AudioMixer::UNITY_GAIN);
6479 mRsmpOutBuffer = new int32_t[mFrameCount * 2];
6480
6481 // optmization: if mono to mono, alter input frame count as if we were inputing stereo samples
6482 if (mChannelCount == 1 && mReqChannelCount == 1) {
6483 mFrameCount >>= 1;
6484 }
6485
6486 }
6487 mRsmpInIndex = mFrameCount;
6488}
6489
6490unsigned int AudioFlinger::RecordThread::getInputFramesLost()
6491{
Eric Laurentb8ba0a92011-08-07 16:32:26 -07006492 Mutex::Autolock _l(mLock);
6493 if (initCheck() != NO_ERROR) {
6494 return 0;
6495 }
6496
Dima Zavin799a70e2011-04-18 16:57:27 -07006497 return mInput->stream->get_input_frames_lost(mInput->stream);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006498}
6499
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006500uint32_t AudioFlinger::RecordThread::hasAudioSession(int sessionId)
6501{
6502 Mutex::Autolock _l(mLock);
6503 uint32_t result = 0;
6504 if (getEffectChain_l(sessionId) != 0) {
6505 result = EFFECT_SESSION;
6506 }
6507
6508 if (mTrack != NULL && sessionId == mTrack->sessionId()) {
6509 result |= TRACK_SESSION;
6510 }
6511
6512 return result;
6513}
6514
Eric Laurent59bd0da2011-08-01 09:52:20 -07006515AudioFlinger::RecordThread::RecordTrack* AudioFlinger::RecordThread::track()
6516{
6517 Mutex::Autolock _l(mLock);
6518 return mTrack;
6519}
6520
Glenn Kastenaed850d2012-01-26 09:46:34 -08006521AudioFlinger::AudioStreamIn* AudioFlinger::RecordThread::getInput() const
Eric Laurentb8ba0a92011-08-07 16:32:26 -07006522{
6523 Mutex::Autolock _l(mLock);
6524 return mInput;
6525}
6526
6527AudioFlinger::AudioStreamIn* AudioFlinger::RecordThread::clearInput()
6528{
6529 Mutex::Autolock _l(mLock);
6530 AudioStreamIn *input = mInput;
6531 mInput = NULL;
6532 return input;
6533}
6534
6535// this method must always be called either with ThreadBase mLock held or inside the thread loop
Glenn Kasten0bf65bd2012-02-28 18:32:53 -08006536audio_stream_t* AudioFlinger::RecordThread::stream() const
Eric Laurentb8ba0a92011-08-07 16:32:26 -07006537{
6538 if (mInput == NULL) {
6539 return NULL;
6540 }
6541 return &mInput->stream->common;
6542}
6543
6544
Mathias Agopian65ab4712010-07-14 17:59:35 -07006545// ----------------------------------------------------------------------------
6546
Eric Laurenta4c5a552012-03-29 10:12:40 -07006547audio_module_handle_t AudioFlinger::loadHwModule(const char *name)
6548{
6549 if (!settingsAllowed()) {
6550 return 0;
6551 }
6552 Mutex::Autolock _l(mLock);
6553 return loadHwModule_l(name);
6554}
6555
6556// loadHwModule_l() must be called with AudioFlinger::mLock held
6557audio_module_handle_t AudioFlinger::loadHwModule_l(const char *name)
6558{
6559 for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
6560 if (strncmp(mAudioHwDevs.valueAt(i)->moduleName(), name, strlen(name)) == 0) {
6561 ALOGW("loadHwModule() module %s already loaded", name);
6562 return mAudioHwDevs.keyAt(i);
6563 }
6564 }
6565
Eric Laurenta4c5a552012-03-29 10:12:40 -07006566 audio_hw_device_t *dev;
6567
Eric Laurentf7ffb8b2012-04-14 09:06:57 -07006568 int rc = load_audio_interface(name, &dev);
Eric Laurenta4c5a552012-03-29 10:12:40 -07006569 if (rc) {
6570 ALOGI("loadHwModule() error %d loading module %s ", rc, name);
6571 return 0;
6572 }
6573
6574 mHardwareStatus = AUDIO_HW_INIT;
6575 rc = dev->init_check(dev);
6576 mHardwareStatus = AUDIO_HW_IDLE;
6577 if (rc) {
6578 ALOGI("loadHwModule() init check error %d for module %s ", rc, name);
6579 return 0;
6580 }
6581
6582 if ((mMasterVolumeSupportLvl != MVS_NONE) &&
6583 (NULL != dev->set_master_volume)) {
6584 AutoMutex lock(mHardwareLock);
6585 mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
6586 dev->set_master_volume(dev, mMasterVolume);
6587 mHardwareStatus = AUDIO_HW_IDLE;
6588 }
6589
6590 audio_module_handle_t handle = nextUniqueId();
6591 mAudioHwDevs.add(handle, new AudioHwDevice(name, dev));
6592
6593 ALOGI("loadHwModule() Loaded %s audio interface from %s (%s) handle %d",
Eric Laurentf7ffb8b2012-04-14 09:06:57 -07006594 name, dev->common.module->name, dev->common.module->id, handle);
Eric Laurenta4c5a552012-03-29 10:12:40 -07006595
6596 return handle;
6597
6598}
6599
6600audio_io_handle_t AudioFlinger::openOutput(audio_module_handle_t module,
6601 audio_devices_t *pDevices,
6602 uint32_t *pSamplingRate,
6603 audio_format_t *pFormat,
6604 audio_channel_mask_t *pChannelMask,
6605 uint32_t *pLatencyMs,
Eric Laurent0ca3cf92012-04-18 09:24:29 -07006606 audio_output_flags_t flags)
Mathias Agopian65ab4712010-07-14 17:59:35 -07006607{
6608 status_t status;
6609 PlaybackThread *thread = NULL;
Eric Laurentf7ffb8b2012-04-14 09:06:57 -07006610 struct audio_config config = {
6611 sample_rate: pSamplingRate ? *pSamplingRate : 0,
6612 channel_mask: pChannelMask ? *pChannelMask : 0,
6613 format: pFormat ? *pFormat : AUDIO_FORMAT_DEFAULT,
6614 };
6615 audio_stream_out_t *outStream = NULL;
Dima Zavin799a70e2011-04-18 16:57:27 -07006616 audio_hw_device_t *outHwDev;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006617
Eric Laurenta4c5a552012-03-29 10:12:40 -07006618 ALOGV("openOutput(), module %d Device %x, SamplingRate %d, Format %d, Channels %x, flags %x",
6619 module,
Eric Laurent3f9c84c2012-04-03 15:36:53 -07006620 (pDevices != NULL) ? (int)*pDevices : 0,
Eric Laurentf7ffb8b2012-04-14 09:06:57 -07006621 config.sample_rate,
6622 config.format,
6623 config.channel_mask,
Eric Laurenta4c5a552012-03-29 10:12:40 -07006624 flags);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006625
6626 if (pDevices == NULL || *pDevices == 0) {
6627 return 0;
6628 }
Dima Zavin799a70e2011-04-18 16:57:27 -07006629
Mathias Agopian65ab4712010-07-14 17:59:35 -07006630 Mutex::Autolock _l(mLock);
6631
Eric Laurenta4c5a552012-03-29 10:12:40 -07006632 outHwDev = findSuitableHwDev_l(module, *pDevices);
Dima Zavin799a70e2011-04-18 16:57:27 -07006633 if (outHwDev == NULL)
6634 return 0;
6635
Eric Laurentf7ffb8b2012-04-14 09:06:57 -07006636 audio_io_handle_t id = nextUniqueId();
6637
Glenn Kasten8abf44d2012-02-02 14:16:03 -08006638 mHardwareStatus = AUDIO_HW_OUTPUT_OPEN;
Eric Laurentf7ffb8b2012-04-14 09:06:57 -07006639
6640 status = outHwDev->open_output_stream(outHwDev,
6641 id,
6642 *pDevices,
6643 (audio_output_flags_t)flags,
6644 &config,
6645 &outStream);
6646
Glenn Kasten8abf44d2012-02-02 14:16:03 -08006647 mHardwareStatus = AUDIO_HW_IDLE;
Steve Block3856b092011-10-20 11:56:00 +01006648 ALOGV("openOutput() openOutputStream returned output %p, SamplingRate %d, Format %d, Channels %x, status %d",
Dima Zavin799a70e2011-04-18 16:57:27 -07006649 outStream,
Eric Laurentf7ffb8b2012-04-14 09:06:57 -07006650 config.sample_rate,
6651 config.format,
6652 config.channel_mask,
Mathias Agopian65ab4712010-07-14 17:59:35 -07006653 status);
6654
Eric Laurentf7ffb8b2012-04-14 09:06:57 -07006655 if (status == NO_ERROR && outStream != NULL) {
Dima Zavin799a70e2011-04-18 16:57:27 -07006656 AudioStreamOut *output = new AudioStreamOut(outHwDev, outStream);
Dima Zavin799a70e2011-04-18 16:57:27 -07006657
Eric Laurent0ca3cf92012-04-18 09:24:29 -07006658 if ((flags & AUDIO_OUTPUT_FLAG_DIRECT) ||
Eric Laurentf7ffb8b2012-04-14 09:06:57 -07006659 (config.format != AUDIO_FORMAT_PCM_16_BIT) ||
6660 (config.channel_mask != AUDIO_CHANNEL_OUT_STEREO)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07006661 thread = new DirectOutputThread(this, output, id, *pDevices);
Steve Block3856b092011-10-20 11:56:00 +01006662 ALOGV("openOutput() created direct output: ID %d thread %p", id, thread);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006663 } else {
6664 thread = new MixerThread(this, output, id, *pDevices);
Steve Block3856b092011-10-20 11:56:00 +01006665 ALOGV("openOutput() created mixer output: ID %d thread %p", id, thread);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006666 }
6667 mPlaybackThreads.add(id, thread);
6668
Eric Laurentf7ffb8b2012-04-14 09:06:57 -07006669 if (pSamplingRate != NULL) *pSamplingRate = config.sample_rate;
6670 if (pFormat != NULL) *pFormat = config.format;
6671 if (pChannelMask != NULL) *pChannelMask = config.channel_mask;
Glenn Kastena0d68332012-01-27 16:47:15 -08006672 if (pLatencyMs != NULL) *pLatencyMs = thread->latency();
Mathias Agopian65ab4712010-07-14 17:59:35 -07006673
6674 // notify client processes of the new output creation
6675 thread->audioConfigChanged_l(AudioSystem::OUTPUT_OPENED);
Eric Laurenta4c5a552012-03-29 10:12:40 -07006676
6677 // the first primary output opened designates the primary hw device
Eric Laurent0ca3cf92012-04-18 09:24:29 -07006678 if ((mPrimaryHardwareDev == NULL) && (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
Eric Laurenta4c5a552012-03-29 10:12:40 -07006679 ALOGI("Using module %d has the primary audio interface", module);
6680 mPrimaryHardwareDev = outHwDev;
6681
6682 AutoMutex lock(mHardwareLock);
6683 mHardwareStatus = AUDIO_HW_SET_MODE;
6684 outHwDev->set_mode(outHwDev, mMode);
6685
6686 // Determine the level of master volume support the primary audio HAL has,
6687 // and set the initial master volume at the same time.
6688 float initialVolume = 1.0;
6689 mMasterVolumeSupportLvl = MVS_NONE;
6690
6691 mHardwareStatus = AUDIO_HW_GET_MASTER_VOLUME;
6692 if ((NULL != outHwDev->get_master_volume) &&
6693 (NO_ERROR == outHwDev->get_master_volume(outHwDev, &initialVolume))) {
6694 mMasterVolumeSupportLvl = MVS_FULL;
6695 } else {
6696 mMasterVolumeSupportLvl = MVS_SETONLY;
6697 initialVolume = 1.0;
6698 }
6699
6700 mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
6701 if ((NULL == outHwDev->set_master_volume) ||
6702 (NO_ERROR != outHwDev->set_master_volume(outHwDev, initialVolume))) {
6703 mMasterVolumeSupportLvl = MVS_NONE;
6704 }
6705 // now that we have a primary device, initialize master volume on other devices
6706 for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
6707 audio_hw_device_t *dev = mAudioHwDevs.valueAt(i)->hwDevice();
6708
6709 if ((dev != mPrimaryHardwareDev) &&
6710 (NULL != dev->set_master_volume)) {
6711 dev->set_master_volume(dev, initialVolume);
6712 }
6713 }
6714 mHardwareStatus = AUDIO_HW_IDLE;
6715 mMasterVolumeSW = (MVS_NONE == mMasterVolumeSupportLvl)
6716 ? initialVolume
6717 : 1.0;
6718 mMasterVolume = initialVolume;
6719 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07006720 return id;
6721 }
6722
6723 return 0;
6724}
6725
Glenn Kasten72ef00d2012-01-17 11:09:42 -08006726audio_io_handle_t AudioFlinger::openDuplicateOutput(audio_io_handle_t output1,
6727 audio_io_handle_t output2)
Mathias Agopian65ab4712010-07-14 17:59:35 -07006728{
6729 Mutex::Autolock _l(mLock);
6730 MixerThread *thread1 = checkMixerThread_l(output1);
6731 MixerThread *thread2 = checkMixerThread_l(output2);
6732
6733 if (thread1 == NULL || thread2 == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +00006734 ALOGW("openDuplicateOutput() wrong output mixer type for output %d or %d", output1, output2);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006735 return 0;
6736 }
6737
Glenn Kasten72ef00d2012-01-17 11:09:42 -08006738 audio_io_handle_t id = nextUniqueId();
Mathias Agopian65ab4712010-07-14 17:59:35 -07006739 DuplicatingThread *thread = new DuplicatingThread(this, thread1, id);
6740 thread->addOutputTrack(thread2);
6741 mPlaybackThreads.add(id, thread);
6742 // notify client processes of the new output creation
6743 thread->audioConfigChanged_l(AudioSystem::OUTPUT_OPENED);
6744 return id;
6745}
6746
Glenn Kasten72ef00d2012-01-17 11:09:42 -08006747status_t AudioFlinger::closeOutput(audio_io_handle_t output)
Mathias Agopian65ab4712010-07-14 17:59:35 -07006748{
6749 // keep strong reference on the playback thread so that
6750 // it is not destroyed while exit() is executed
Glenn Kastene53b9ea2012-03-12 16:29:55 -07006751 sp<PlaybackThread> thread;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006752 {
6753 Mutex::Autolock _l(mLock);
6754 thread = checkPlaybackThread_l(output);
6755 if (thread == NULL) {
6756 return BAD_VALUE;
6757 }
6758
Steve Block3856b092011-10-20 11:56:00 +01006759 ALOGV("closeOutput() %d", output);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006760
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006761 if (thread->type() == ThreadBase::MIXER) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07006762 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006763 if (mPlaybackThreads.valueAt(i)->type() == ThreadBase::DUPLICATING) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07006764 DuplicatingThread *dupThread = (DuplicatingThread *)mPlaybackThreads.valueAt(i).get();
6765 dupThread->removeOutputTrack((MixerThread *)thread.get());
6766 }
6767 }
6768 }
Glenn Kastena1117922012-01-26 10:53:32 -08006769 audioConfigChanged_l(AudioSystem::OUTPUT_CLOSED, output, NULL);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006770 mPlaybackThreads.removeItem(output);
6771 }
6772 thread->exit();
Glenn Kastenb28686f2012-01-06 08:39:38 -08006773 // The thread entity (active unit of execution) is no longer running here,
6774 // but the ThreadBase container still exists.
Mathias Agopian65ab4712010-07-14 17:59:35 -07006775
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006776 if (thread->type() != ThreadBase::DUPLICATING) {
Eric Laurentb8ba0a92011-08-07 16:32:26 -07006777 AudioStreamOut *out = thread->clearOutput();
Glenn Kasten5798d4e2012-03-08 12:18:35 -08006778 ALOG_ASSERT(out != NULL, "out shouldn't be NULL");
Eric Laurentb8ba0a92011-08-07 16:32:26 -07006779 // from now on thread->mOutput is NULL
Dima Zavin799a70e2011-04-18 16:57:27 -07006780 out->hwDev->close_output_stream(out->hwDev, out->stream);
6781 delete out;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006782 }
6783 return NO_ERROR;
6784}
6785
Glenn Kasten72ef00d2012-01-17 11:09:42 -08006786status_t AudioFlinger::suspendOutput(audio_io_handle_t output)
Mathias Agopian65ab4712010-07-14 17:59:35 -07006787{
6788 Mutex::Autolock _l(mLock);
6789 PlaybackThread *thread = checkPlaybackThread_l(output);
6790
6791 if (thread == NULL) {
6792 return BAD_VALUE;
6793 }
6794
Steve Block3856b092011-10-20 11:56:00 +01006795 ALOGV("suspendOutput() %d", output);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006796 thread->suspend();
6797
6798 return NO_ERROR;
6799}
6800
Glenn Kasten72ef00d2012-01-17 11:09:42 -08006801status_t AudioFlinger::restoreOutput(audio_io_handle_t output)
Mathias Agopian65ab4712010-07-14 17:59:35 -07006802{
6803 Mutex::Autolock _l(mLock);
6804 PlaybackThread *thread = checkPlaybackThread_l(output);
6805
6806 if (thread == NULL) {
6807 return BAD_VALUE;
6808 }
6809
Steve Block3856b092011-10-20 11:56:00 +01006810 ALOGV("restoreOutput() %d", output);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006811
6812 thread->restore();
6813
6814 return NO_ERROR;
6815}
6816
Eric Laurenta4c5a552012-03-29 10:12:40 -07006817audio_io_handle_t AudioFlinger::openInput(audio_module_handle_t module,
6818 audio_devices_t *pDevices,
6819 uint32_t *pSamplingRate,
6820 audio_format_t *pFormat,
6821 uint32_t *pChannelMask)
Mathias Agopian65ab4712010-07-14 17:59:35 -07006822{
6823 status_t status;
6824 RecordThread *thread = NULL;
Eric Laurentf7ffb8b2012-04-14 09:06:57 -07006825 struct audio_config config = {
6826 sample_rate: pSamplingRate ? *pSamplingRate : 0,
6827 channel_mask: pChannelMask ? *pChannelMask : 0,
6828 format: pFormat ? *pFormat : AUDIO_FORMAT_DEFAULT,
6829 };
6830 uint32_t reqSamplingRate = config.sample_rate;
6831 audio_format_t reqFormat = config.format;
6832 audio_channel_mask_t reqChannels = config.channel_mask;
6833 audio_stream_in_t *inStream = NULL;
Dima Zavin799a70e2011-04-18 16:57:27 -07006834 audio_hw_device_t *inHwDev;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006835
6836 if (pDevices == NULL || *pDevices == 0) {
6837 return 0;
6838 }
Dima Zavin799a70e2011-04-18 16:57:27 -07006839
Mathias Agopian65ab4712010-07-14 17:59:35 -07006840 Mutex::Autolock _l(mLock);
6841
Eric Laurenta4c5a552012-03-29 10:12:40 -07006842 inHwDev = findSuitableHwDev_l(module, *pDevices);
Dima Zavin799a70e2011-04-18 16:57:27 -07006843 if (inHwDev == NULL)
6844 return 0;
6845
Eric Laurentf7ffb8b2012-04-14 09:06:57 -07006846 audio_io_handle_t id = nextUniqueId();
6847
6848 status = inHwDev->open_input_stream(inHwDev, id, *pDevices, &config,
Dima Zavin799a70e2011-04-18 16:57:27 -07006849 &inStream);
Eric Laurenta4c5a552012-03-29 10:12:40 -07006850 ALOGV("openInput() openInputStream returned input %p, SamplingRate %d, Format %d, Channels %x, status %d",
Dima Zavin799a70e2011-04-18 16:57:27 -07006851 inStream,
Eric Laurentf7ffb8b2012-04-14 09:06:57 -07006852 config.sample_rate,
6853 config.format,
6854 config.channel_mask,
Mathias Agopian65ab4712010-07-14 17:59:35 -07006855 status);
6856
6857 // If the input could not be opened with the requested parameters and we can handle the conversion internally,
6858 // try to open again with the proposed parameters. The AudioFlinger can resample the input and do mono to stereo
6859 // or stereo to mono conversions on 16 bit PCM inputs.
Eric Laurentf7ffb8b2012-04-14 09:06:57 -07006860 if (status == BAD_VALUE &&
6861 reqFormat == config.format && config.format == AUDIO_FORMAT_PCM_16_BIT &&
6862 (config.sample_rate <= 2 * reqSamplingRate) &&
6863 (popcount(config.channel_mask) <= FCC_2) && (popcount(reqChannels) <= FCC_2)) {
Steve Block3856b092011-10-20 11:56:00 +01006864 ALOGV("openInput() reopening with proposed sampling rate and channels");
Eric Laurentf7ffb8b2012-04-14 09:06:57 -07006865 inStream = NULL;
6866 status = inHwDev->open_input_stream(inHwDev, id, *pDevices, &config, &inStream);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006867 }
6868
Eric Laurentf7ffb8b2012-04-14 09:06:57 -07006869 if (status == NO_ERROR && inStream != NULL) {
Dima Zavin799a70e2011-04-18 16:57:27 -07006870 AudioStreamIn *input = new AudioStreamIn(inHwDev, inStream);
6871
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006872 // Start record thread
6873 // RecorThread require both input and output device indication to forward to audio
6874 // pre processing modules
6875 uint32_t device = (*pDevices) | primaryOutputDevice_l();
6876 thread = new RecordThread(this,
6877 input,
6878 reqSamplingRate,
6879 reqChannels,
6880 id,
6881 device);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006882 mRecordThreads.add(id, thread);
Steve Block3856b092011-10-20 11:56:00 +01006883 ALOGV("openInput() created record thread: ID %d thread %p", id, thread);
Glenn Kastena0d68332012-01-27 16:47:15 -08006884 if (pSamplingRate != NULL) *pSamplingRate = reqSamplingRate;
Eric Laurentf7ffb8b2012-04-14 09:06:57 -07006885 if (pFormat != NULL) *pFormat = config.format;
Eric Laurenta4c5a552012-03-29 10:12:40 -07006886 if (pChannelMask != NULL) *pChannelMask = reqChannels;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006887
Dima Zavin799a70e2011-04-18 16:57:27 -07006888 input->stream->common.standby(&input->stream->common);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006889
6890 // notify client processes of the new input creation
6891 thread->audioConfigChanged_l(AudioSystem::INPUT_OPENED);
6892 return id;
6893 }
6894
6895 return 0;
6896}
6897
Glenn Kasten72ef00d2012-01-17 11:09:42 -08006898status_t AudioFlinger::closeInput(audio_io_handle_t input)
Mathias Agopian65ab4712010-07-14 17:59:35 -07006899{
6900 // keep strong reference on the record thread so that
6901 // it is not destroyed while exit() is executed
Glenn Kastene53b9ea2012-03-12 16:29:55 -07006902 sp<RecordThread> thread;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006903 {
6904 Mutex::Autolock _l(mLock);
6905 thread = checkRecordThread_l(input);
6906 if (thread == NULL) {
6907 return BAD_VALUE;
6908 }
6909
Steve Block3856b092011-10-20 11:56:00 +01006910 ALOGV("closeInput() %d", input);
Glenn Kastena1117922012-01-26 10:53:32 -08006911 audioConfigChanged_l(AudioSystem::INPUT_CLOSED, input, NULL);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006912 mRecordThreads.removeItem(input);
6913 }
6914 thread->exit();
Glenn Kastenb28686f2012-01-06 08:39:38 -08006915 // The thread entity (active unit of execution) is no longer running here,
6916 // but the ThreadBase container still exists.
Mathias Agopian65ab4712010-07-14 17:59:35 -07006917
Eric Laurentb8ba0a92011-08-07 16:32:26 -07006918 AudioStreamIn *in = thread->clearInput();
Glenn Kasten5798d4e2012-03-08 12:18:35 -08006919 ALOG_ASSERT(in != NULL, "in shouldn't be NULL");
Eric Laurentb8ba0a92011-08-07 16:32:26 -07006920 // from now on thread->mInput is NULL
Dima Zavin799a70e2011-04-18 16:57:27 -07006921 in->hwDev->close_input_stream(in->hwDev, in->stream);
6922 delete in;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006923
6924 return NO_ERROR;
6925}
6926
Glenn Kasten72ef00d2012-01-17 11:09:42 -08006927status_t AudioFlinger::setStreamOutput(audio_stream_type_t stream, audio_io_handle_t output)
Mathias Agopian65ab4712010-07-14 17:59:35 -07006928{
6929 Mutex::Autolock _l(mLock);
6930 MixerThread *dstThread = checkMixerThread_l(output);
6931 if (dstThread == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +00006932 ALOGW("setStreamOutput() bad output id %d", output);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006933 return BAD_VALUE;
6934 }
6935
Steve Block3856b092011-10-20 11:56:00 +01006936 ALOGV("setStreamOutput() stream %d to output %d", stream, output);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006937 audioConfigChanged_l(AudioSystem::STREAM_CONFIG_CHANGED, output, &stream);
6938
6939 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
6940 PlaybackThread *thread = mPlaybackThreads.valueAt(i).get();
Glenn Kastena1117922012-01-26 10:53:32 -08006941 if (thread != dstThread && thread->type() != ThreadBase::DIRECT) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07006942 MixerThread *srcThread = (MixerThread *)thread;
6943 srcThread->invalidateTracks(stream);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006944 }
Eric Laurentde070132010-07-13 04:45:46 -07006945 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07006946
6947 return NO_ERROR;
6948}
6949
6950
6951int AudioFlinger::newAudioSessionId()
6952{
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006953 return nextUniqueId();
Mathias Agopian65ab4712010-07-14 17:59:35 -07006954}
6955
Marco Nelissen3a34bef2011-08-02 13:33:41 -07006956void AudioFlinger::acquireAudioSessionId(int audioSession)
6957{
6958 Mutex::Autolock _l(mLock);
Glenn Kastenbb001922012-02-03 11:10:26 -08006959 pid_t caller = IPCThreadState::self()->getCallingPid();
Steve Block3856b092011-10-20 11:56:00 +01006960 ALOGV("acquiring %d from %d", audioSession, caller);
Glenn Kasten8d6a2442012-02-08 14:04:28 -08006961 size_t num = mAudioSessionRefs.size();
6962 for (size_t i = 0; i< num; i++) {
Marco Nelissen3a34bef2011-08-02 13:33:41 -07006963 AudioSessionRef *ref = mAudioSessionRefs.editItemAt(i);
Glenn Kasten012ca6b2012-03-06 11:22:01 -08006964 if (ref->mSessionid == audioSession && ref->mPid == caller) {
6965 ref->mCnt++;
6966 ALOGV(" incremented refcount to %d", ref->mCnt);
Marco Nelissen3a34bef2011-08-02 13:33:41 -07006967 return;
6968 }
6969 }
Glenn Kasten84afa3b2012-01-25 15:28:08 -08006970 mAudioSessionRefs.push(new AudioSessionRef(audioSession, caller));
6971 ALOGV(" added new entry for %d", audioSession);
Marco Nelissen3a34bef2011-08-02 13:33:41 -07006972}
6973
6974void AudioFlinger::releaseAudioSessionId(int audioSession)
6975{
6976 Mutex::Autolock _l(mLock);
Glenn Kastenbb001922012-02-03 11:10:26 -08006977 pid_t caller = IPCThreadState::self()->getCallingPid();
Steve Block3856b092011-10-20 11:56:00 +01006978 ALOGV("releasing %d from %d", audioSession, caller);
Glenn Kasten8d6a2442012-02-08 14:04:28 -08006979 size_t num = mAudioSessionRefs.size();
6980 for (size_t i = 0; i< num; i++) {
Marco Nelissen3a34bef2011-08-02 13:33:41 -07006981 AudioSessionRef *ref = mAudioSessionRefs.itemAt(i);
Glenn Kasten012ca6b2012-03-06 11:22:01 -08006982 if (ref->mSessionid == audioSession && ref->mPid == caller) {
6983 ref->mCnt--;
6984 ALOGV(" decremented refcount to %d", ref->mCnt);
6985 if (ref->mCnt == 0) {
Marco Nelissen3a34bef2011-08-02 13:33:41 -07006986 mAudioSessionRefs.removeAt(i);
6987 delete ref;
6988 purgeStaleEffects_l();
6989 }
6990 return;
6991 }
6992 }
Steve Block5ff1dd52012-01-05 23:22:43 +00006993 ALOGW("session id %d not found for pid %d", audioSession, caller);
Marco Nelissen3a34bef2011-08-02 13:33:41 -07006994}
6995
6996void AudioFlinger::purgeStaleEffects_l() {
6997
Steve Block3856b092011-10-20 11:56:00 +01006998 ALOGV("purging stale effects");
Marco Nelissen3a34bef2011-08-02 13:33:41 -07006999
7000 Vector< sp<EffectChain> > chains;
7001
7002 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
7003 sp<PlaybackThread> t = mPlaybackThreads.valueAt(i);
7004 for (size_t j = 0; j < t->mEffectChains.size(); j++) {
7005 sp<EffectChain> ec = t->mEffectChains[j];
Marco Nelissen0270b182011-08-12 14:14:39 -07007006 if (ec->sessionId() > AUDIO_SESSION_OUTPUT_MIX) {
7007 chains.push(ec);
7008 }
Marco Nelissen3a34bef2011-08-02 13:33:41 -07007009 }
7010 }
7011 for (size_t i = 0; i < mRecordThreads.size(); i++) {
7012 sp<RecordThread> t = mRecordThreads.valueAt(i);
7013 for (size_t j = 0; j < t->mEffectChains.size(); j++) {
7014 sp<EffectChain> ec = t->mEffectChains[j];
7015 chains.push(ec);
7016 }
7017 }
7018
7019 for (size_t i = 0; i < chains.size(); i++) {
7020 sp<EffectChain> ec = chains[i];
7021 int sessionid = ec->sessionId();
7022 sp<ThreadBase> t = ec->mThread.promote();
7023 if (t == 0) {
7024 continue;
7025 }
7026 size_t numsessionrefs = mAudioSessionRefs.size();
7027 bool found = false;
7028 for (size_t k = 0; k < numsessionrefs; k++) {
7029 AudioSessionRef *ref = mAudioSessionRefs.itemAt(k);
Glenn Kasten012ca6b2012-03-06 11:22:01 -08007030 if (ref->mSessionid == sessionid) {
Steve Block3856b092011-10-20 11:56:00 +01007031 ALOGV(" session %d still exists for %d with %d refs",
Glenn Kastene53b9ea2012-03-12 16:29:55 -07007032 sessionid, ref->mPid, ref->mCnt);
Marco Nelissen3a34bef2011-08-02 13:33:41 -07007033 found = true;
7034 break;
7035 }
7036 }
7037 if (!found) {
7038 // remove all effects from the chain
7039 while (ec->mEffects.size()) {
7040 sp<EffectModule> effect = ec->mEffects[0];
7041 effect->unPin();
7042 Mutex::Autolock _l (t->mLock);
7043 t->removeEffect_l(effect);
7044 for (size_t j = 0; j < effect->mHandles.size(); j++) {
7045 sp<EffectHandle> handle = effect->mHandles[j].promote();
7046 if (handle != 0) {
7047 handle->mEffect.clear();
Eric Laurenta85a74a2011-10-19 11:44:54 -07007048 if (handle->mHasControl && handle->mEnabled) {
7049 t->checkSuspendOnEffectEnabled_l(effect, false, effect->sessionId());
7050 }
Marco Nelissen3a34bef2011-08-02 13:33:41 -07007051 }
7052 }
7053 AudioSystem::unregisterEffect(effect->id());
7054 }
7055 }
7056 }
7057 return;
7058}
7059
Mathias Agopian65ab4712010-07-14 17:59:35 -07007060// checkPlaybackThread_l() must be called with AudioFlinger::mLock held
Glenn Kasten72ef00d2012-01-17 11:09:42 -08007061AudioFlinger::PlaybackThread *AudioFlinger::checkPlaybackThread_l(audio_io_handle_t output) const
Mathias Agopian65ab4712010-07-14 17:59:35 -07007062{
Glenn Kastena1117922012-01-26 10:53:32 -08007063 return mPlaybackThreads.valueFor(output).get();
Mathias Agopian65ab4712010-07-14 17:59:35 -07007064}
7065
7066// checkMixerThread_l() must be called with AudioFlinger::mLock held
Glenn Kasten72ef00d2012-01-17 11:09:42 -08007067AudioFlinger::MixerThread *AudioFlinger::checkMixerThread_l(audio_io_handle_t output) const
Mathias Agopian65ab4712010-07-14 17:59:35 -07007068{
7069 PlaybackThread *thread = checkPlaybackThread_l(output);
Glenn Kastena1117922012-01-26 10:53:32 -08007070 return thread != NULL && thread->type() != ThreadBase::DIRECT ? (MixerThread *) thread : NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -07007071}
7072
7073// checkRecordThread_l() must be called with AudioFlinger::mLock held
Glenn Kasten72ef00d2012-01-17 11:09:42 -08007074AudioFlinger::RecordThread *AudioFlinger::checkRecordThread_l(audio_io_handle_t input) const
Mathias Agopian65ab4712010-07-14 17:59:35 -07007075{
Glenn Kastena1117922012-01-26 10:53:32 -08007076 return mRecordThreads.valueFor(input).get();
Mathias Agopian65ab4712010-07-14 17:59:35 -07007077}
7078
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007079uint32_t AudioFlinger::nextUniqueId()
Mathias Agopian65ab4712010-07-14 17:59:35 -07007080{
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007081 return android_atomic_inc(&mNextUniqueId);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007082}
7083
Glenn Kasten02fe1bf2012-02-24 15:42:17 -08007084AudioFlinger::PlaybackThread *AudioFlinger::primaryPlaybackThread_l() const
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007085{
7086 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
7087 PlaybackThread *thread = mPlaybackThreads.valueAt(i).get();
Eric Laurentb8ba0a92011-08-07 16:32:26 -07007088 AudioStreamOut *output = thread->getOutput();
7089 if (output != NULL && output->hwDev == mPrimaryHardwareDev) {
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007090 return thread;
7091 }
7092 }
7093 return NULL;
7094}
7095
Glenn Kasten02fe1bf2012-02-24 15:42:17 -08007096uint32_t AudioFlinger::primaryOutputDevice_l() const
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007097{
7098 PlaybackThread *thread = primaryPlaybackThread_l();
7099
7100 if (thread == NULL) {
7101 return 0;
7102 }
7103
7104 return thread->device();
7105}
7106
Eric Laurenta011e352012-03-29 15:51:43 -07007107sp<AudioFlinger::SyncEvent> AudioFlinger::createSyncEvent(AudioSystem::sync_event_t type,
7108 int triggerSession,
7109 int listenerSession,
7110 sync_event_callback_t callBack,
7111 void *cookie)
7112{
7113 Mutex::Autolock _l(mLock);
7114
7115 sp<SyncEvent> event = new SyncEvent(type, triggerSession, listenerSession, callBack, cookie);
7116 status_t playStatus = NAME_NOT_FOUND;
7117 status_t recStatus = NAME_NOT_FOUND;
7118 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
7119 playStatus = mPlaybackThreads.valueAt(i)->setSyncEvent(event);
7120 if (playStatus == NO_ERROR) {
7121 return event;
7122 }
7123 }
7124 for (size_t i = 0; i < mRecordThreads.size(); i++) {
7125 recStatus = mRecordThreads.valueAt(i)->setSyncEvent(event);
7126 if (recStatus == NO_ERROR) {
7127 return event;
7128 }
7129 }
7130 if (playStatus == NAME_NOT_FOUND || recStatus == NAME_NOT_FOUND) {
7131 mPendingSyncEvents.add(event);
7132 } else {
7133 ALOGV("createSyncEvent() invalid event %d", event->type());
7134 event.clear();
7135 }
7136 return event;
7137}
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007138
Mathias Agopian65ab4712010-07-14 17:59:35 -07007139// ----------------------------------------------------------------------------
7140// Effect management
7141// ----------------------------------------------------------------------------
7142
7143
Glenn Kastenf587ba52012-01-26 16:25:10 -08007144status_t AudioFlinger::queryNumberEffects(uint32_t *numEffects) const
Mathias Agopian65ab4712010-07-14 17:59:35 -07007145{
7146 Mutex::Autolock _l(mLock);
7147 return EffectQueryNumberEffects(numEffects);
7148}
7149
Glenn Kastenf587ba52012-01-26 16:25:10 -08007150status_t AudioFlinger::queryEffect(uint32_t index, effect_descriptor_t *descriptor) const
Mathias Agopian65ab4712010-07-14 17:59:35 -07007151{
7152 Mutex::Autolock _l(mLock);
7153 return EffectQueryEffect(index, descriptor);
7154}
7155
Glenn Kasten5e92a782012-01-30 07:40:52 -08007156status_t AudioFlinger::getEffectDescriptor(const effect_uuid_t *pUuid,
Glenn Kastenf587ba52012-01-26 16:25:10 -08007157 effect_descriptor_t *descriptor) const
Mathias Agopian65ab4712010-07-14 17:59:35 -07007158{
7159 Mutex::Autolock _l(mLock);
7160 return EffectGetDescriptor(pUuid, descriptor);
7161}
7162
7163
Mathias Agopian65ab4712010-07-14 17:59:35 -07007164sp<IEffect> AudioFlinger::createEffect(pid_t pid,
7165 effect_descriptor_t *pDesc,
7166 const sp<IEffectClient>& effectClient,
7167 int32_t priority,
Glenn Kasten72ef00d2012-01-17 11:09:42 -08007168 audio_io_handle_t io,
Mathias Agopian65ab4712010-07-14 17:59:35 -07007169 int sessionId,
7170 status_t *status,
7171 int *id,
7172 int *enabled)
7173{
7174 status_t lStatus = NO_ERROR;
7175 sp<EffectHandle> handle;
Mathias Agopian65ab4712010-07-14 17:59:35 -07007176 effect_descriptor_t desc;
Mathias Agopian65ab4712010-07-14 17:59:35 -07007177
Glenn Kasten98ec94c2012-01-25 14:28:29 -08007178 ALOGV("createEffect pid %d, effectClient %p, priority %d, sessionId %d, io %d",
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007179 pid, effectClient.get(), priority, sessionId, io);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007180
7181 if (pDesc == NULL) {
7182 lStatus = BAD_VALUE;
7183 goto Exit;
7184 }
7185
Eric Laurent84e9a102010-09-23 16:10:16 -07007186 // check audio settings permission for global effects
Dima Zavinfce7a472011-04-19 22:30:36 -07007187 if (sessionId == AUDIO_SESSION_OUTPUT_MIX && !settingsAllowed()) {
Eric Laurent84e9a102010-09-23 16:10:16 -07007188 lStatus = PERMISSION_DENIED;
7189 goto Exit;
7190 }
7191
Dima Zavinfce7a472011-04-19 22:30:36 -07007192 // Session AUDIO_SESSION_OUTPUT_STAGE is reserved for output stage effects
Eric Laurent84e9a102010-09-23 16:10:16 -07007193 // that can only be created by audio policy manager (running in same process)
Glenn Kasten44deb052012-02-05 18:09:08 -08007194 if (sessionId == AUDIO_SESSION_OUTPUT_STAGE && getpid_cached != pid) {
Eric Laurent84e9a102010-09-23 16:10:16 -07007195 lStatus = PERMISSION_DENIED;
7196 goto Exit;
7197 }
7198
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007199 if (io == 0) {
Dima Zavinfce7a472011-04-19 22:30:36 -07007200 if (sessionId == AUDIO_SESSION_OUTPUT_STAGE) {
Eric Laurent84e9a102010-09-23 16:10:16 -07007201 // output must be specified by AudioPolicyManager when using session
Dima Zavinfce7a472011-04-19 22:30:36 -07007202 // AUDIO_SESSION_OUTPUT_STAGE
Eric Laurent84e9a102010-09-23 16:10:16 -07007203 lStatus = BAD_VALUE;
7204 goto Exit;
Dima Zavinfce7a472011-04-19 22:30:36 -07007205 } else if (sessionId == AUDIO_SESSION_OUTPUT_MIX) {
Eric Laurent84e9a102010-09-23 16:10:16 -07007206 // if the output returned by getOutputForEffect() is removed before we lock the
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007207 // mutex below, the call to checkPlaybackThread_l(io) below will detect it
Eric Laurent84e9a102010-09-23 16:10:16 -07007208 // and we will exit safely
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007209 io = AudioSystem::getOutputForEffect(&desc);
Eric Laurent84e9a102010-09-23 16:10:16 -07007210 }
7211 }
7212
Mathias Agopian65ab4712010-07-14 17:59:35 -07007213 {
7214 Mutex::Autolock _l(mLock);
7215
Mathias Agopian65ab4712010-07-14 17:59:35 -07007216
7217 if (!EffectIsNullUuid(&pDesc->uuid)) {
7218 // if uuid is specified, request effect descriptor
7219 lStatus = EffectGetDescriptor(&pDesc->uuid, &desc);
7220 if (lStatus < 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00007221 ALOGW("createEffect() error %d from EffectGetDescriptor", lStatus);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007222 goto Exit;
7223 }
7224 } else {
7225 // if uuid is not specified, look for an available implementation
7226 // of the required type in effect factory
7227 if (EffectIsNullUuid(&pDesc->type)) {
Steve Block5ff1dd52012-01-05 23:22:43 +00007228 ALOGW("createEffect() no effect type");
Mathias Agopian65ab4712010-07-14 17:59:35 -07007229 lStatus = BAD_VALUE;
7230 goto Exit;
7231 }
7232 uint32_t numEffects = 0;
7233 effect_descriptor_t d;
Marco Nelissen3a34bef2011-08-02 13:33:41 -07007234 d.flags = 0; // prevent compiler warning
Mathias Agopian65ab4712010-07-14 17:59:35 -07007235 bool found = false;
7236
7237 lStatus = EffectQueryNumberEffects(&numEffects);
7238 if (lStatus < 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00007239 ALOGW("createEffect() error %d from EffectQueryNumberEffects", lStatus);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007240 goto Exit;
7241 }
7242 for (uint32_t i = 0; i < numEffects; i++) {
7243 lStatus = EffectQueryEffect(i, &desc);
7244 if (lStatus < 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00007245 ALOGW("createEffect() error %d from EffectQueryEffect", lStatus);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007246 continue;
7247 }
7248 if (memcmp(&desc.type, &pDesc->type, sizeof(effect_uuid_t)) == 0) {
7249 // If matching type found save effect descriptor. If the session is
7250 // 0 and the effect is not auxiliary, continue enumeration in case
7251 // an auxiliary version of this effect type is available
7252 found = true;
7253 memcpy(&d, &desc, sizeof(effect_descriptor_t));
Dima Zavinfce7a472011-04-19 22:30:36 -07007254 if (sessionId != AUDIO_SESSION_OUTPUT_MIX ||
Mathias Agopian65ab4712010-07-14 17:59:35 -07007255 (desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
7256 break;
7257 }
7258 }
7259 }
7260 if (!found) {
7261 lStatus = BAD_VALUE;
Steve Block5ff1dd52012-01-05 23:22:43 +00007262 ALOGW("createEffect() effect not found");
Mathias Agopian65ab4712010-07-14 17:59:35 -07007263 goto Exit;
7264 }
7265 // For same effect type, chose auxiliary version over insert version if
7266 // connect to output mix (Compliance to OpenSL ES)
Dima Zavinfce7a472011-04-19 22:30:36 -07007267 if (sessionId == AUDIO_SESSION_OUTPUT_MIX &&
Mathias Agopian65ab4712010-07-14 17:59:35 -07007268 (d.flags & EFFECT_FLAG_TYPE_MASK) != EFFECT_FLAG_TYPE_AUXILIARY) {
7269 memcpy(&desc, &d, sizeof(effect_descriptor_t));
7270 }
7271 }
7272
7273 // Do not allow auxiliary effects on a session different from 0 (output mix)
Dima Zavinfce7a472011-04-19 22:30:36 -07007274 if (sessionId != AUDIO_SESSION_OUTPUT_MIX &&
Mathias Agopian65ab4712010-07-14 17:59:35 -07007275 (desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
7276 lStatus = INVALID_OPERATION;
7277 goto Exit;
7278 }
7279
Eric Laurent59255e42011-07-27 19:49:51 -07007280 // check recording permission for visualizer
7281 if ((memcmp(&desc.type, SL_IID_VISUALIZATION, sizeof(effect_uuid_t)) == 0) &&
7282 !recordingAllowed()) {
7283 lStatus = PERMISSION_DENIED;
7284 goto Exit;
7285 }
7286
Mathias Agopian65ab4712010-07-14 17:59:35 -07007287 // return effect descriptor
7288 memcpy(pDesc, &desc, sizeof(effect_descriptor_t));
7289
7290 // If output is not specified try to find a matching audio session ID in one of the
7291 // output threads.
Eric Laurent84e9a102010-09-23 16:10:16 -07007292 // If output is 0 here, sessionId is neither SESSION_OUTPUT_STAGE nor SESSION_OUTPUT_MIX
7293 // because of code checking output when entering the function.
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007294 // Note: io is never 0 when creating an effect on an input
7295 if (io == 0) {
Glenn Kastene53b9ea2012-03-12 16:29:55 -07007296 // look for the thread where the specified audio session is present
Eric Laurent84e9a102010-09-23 16:10:16 -07007297 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
7298 if (mPlaybackThreads.valueAt(i)->hasAudioSession(sessionId) != 0) {
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007299 io = mPlaybackThreads.keyAt(i);
Eric Laurent84e9a102010-09-23 16:10:16 -07007300 break;
Eric Laurent39e94f82010-07-28 01:32:47 -07007301 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07007302 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007303 if (io == 0) {
Glenn Kastene53b9ea2012-03-12 16:29:55 -07007304 for (size_t i = 0; i < mRecordThreads.size(); i++) {
7305 if (mRecordThreads.valueAt(i)->hasAudioSession(sessionId) != 0) {
7306 io = mRecordThreads.keyAt(i);
7307 break;
7308 }
7309 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007310 }
Eric Laurent84e9a102010-09-23 16:10:16 -07007311 // If no output thread contains the requested session ID, default to
7312 // first output. The effect chain will be moved to the correct output
7313 // thread when a track with the same session ID is created
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007314 if (io == 0 && mPlaybackThreads.size()) {
7315 io = mPlaybackThreads.keyAt(0);
7316 }
Steve Block3856b092011-10-20 11:56:00 +01007317 ALOGV("createEffect() got io %d for effect %s", io, desc.name);
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007318 }
7319 ThreadBase *thread = checkRecordThread_l(io);
7320 if (thread == NULL) {
7321 thread = checkPlaybackThread_l(io);
7322 if (thread == NULL) {
Steve Block29357bc2012-01-06 19:20:56 +00007323 ALOGE("createEffect() unknown output thread");
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007324 lStatus = BAD_VALUE;
7325 goto Exit;
Eric Laurent84e9a102010-09-23 16:10:16 -07007326 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07007327 }
Eric Laurent84e9a102010-09-23 16:10:16 -07007328
Glenn Kasten98ec94c2012-01-25 14:28:29 -08007329 sp<Client> client = registerPid_l(pid);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007330
Marco Nelissen3a34bef2011-08-02 13:33:41 -07007331 // create effect on selected output thread
Eric Laurentde070132010-07-13 04:45:46 -07007332 handle = thread->createEffect_l(client, effectClient, priority, sessionId,
7333 &desc, enabled, &lStatus);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007334 if (handle != 0 && id != NULL) {
7335 *id = handle->id();
7336 }
7337 }
7338
7339Exit:
Glenn Kastene53b9ea2012-03-12 16:29:55 -07007340 if (status != NULL) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07007341 *status = lStatus;
7342 }
7343 return handle;
7344}
7345
Glenn Kasten72ef00d2012-01-17 11:09:42 -08007346status_t AudioFlinger::moveEffects(int sessionId, audio_io_handle_t srcOutput,
7347 audio_io_handle_t dstOutput)
Eric Laurentde070132010-07-13 04:45:46 -07007348{
Steve Block3856b092011-10-20 11:56:00 +01007349 ALOGV("moveEffects() session %d, srcOutput %d, dstOutput %d",
Eric Laurent59255e42011-07-27 19:49:51 -07007350 sessionId, srcOutput, dstOutput);
Eric Laurentde070132010-07-13 04:45:46 -07007351 Mutex::Autolock _l(mLock);
7352 if (srcOutput == dstOutput) {
Steve Block5ff1dd52012-01-05 23:22:43 +00007353 ALOGW("moveEffects() same dst and src outputs %d", dstOutput);
Eric Laurentde070132010-07-13 04:45:46 -07007354 return NO_ERROR;
Mathias Agopian65ab4712010-07-14 17:59:35 -07007355 }
Eric Laurentde070132010-07-13 04:45:46 -07007356 PlaybackThread *srcThread = checkPlaybackThread_l(srcOutput);
7357 if (srcThread == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +00007358 ALOGW("moveEffects() bad srcOutput %d", srcOutput);
Eric Laurentde070132010-07-13 04:45:46 -07007359 return BAD_VALUE;
Mathias Agopian65ab4712010-07-14 17:59:35 -07007360 }
Eric Laurentde070132010-07-13 04:45:46 -07007361 PlaybackThread *dstThread = checkPlaybackThread_l(dstOutput);
7362 if (dstThread == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +00007363 ALOGW("moveEffects() bad dstOutput %d", dstOutput);
Eric Laurentde070132010-07-13 04:45:46 -07007364 return BAD_VALUE;
7365 }
7366
7367 Mutex::Autolock _dl(dstThread->mLock);
7368 Mutex::Autolock _sl(srcThread->mLock);
Eric Laurent59255e42011-07-27 19:49:51 -07007369 moveEffectChain_l(sessionId, srcThread, dstThread, false);
Eric Laurentde070132010-07-13 04:45:46 -07007370
Mathias Agopian65ab4712010-07-14 17:59:35 -07007371 return NO_ERROR;
7372}
7373
Marco Nelissen3a34bef2011-08-02 13:33:41 -07007374// moveEffectChain_l must be called with both srcThread and dstThread mLocks held
Eric Laurent59255e42011-07-27 19:49:51 -07007375status_t AudioFlinger::moveEffectChain_l(int sessionId,
Eric Laurentde070132010-07-13 04:45:46 -07007376 AudioFlinger::PlaybackThread *srcThread,
Eric Laurent39e94f82010-07-28 01:32:47 -07007377 AudioFlinger::PlaybackThread *dstThread,
7378 bool reRegister)
Eric Laurentde070132010-07-13 04:45:46 -07007379{
Steve Block3856b092011-10-20 11:56:00 +01007380 ALOGV("moveEffectChain_l() session %d from thread %p to thread %p",
Eric Laurent59255e42011-07-27 19:49:51 -07007381 sessionId, srcThread, dstThread);
Eric Laurentde070132010-07-13 04:45:46 -07007382
Eric Laurent59255e42011-07-27 19:49:51 -07007383 sp<EffectChain> chain = srcThread->getEffectChain_l(sessionId);
Eric Laurentde070132010-07-13 04:45:46 -07007384 if (chain == 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00007385 ALOGW("moveEffectChain_l() effect chain for session %d not on source thread %p",
Eric Laurent59255e42011-07-27 19:49:51 -07007386 sessionId, srcThread);
Eric Laurentde070132010-07-13 04:45:46 -07007387 return INVALID_OPERATION;
7388 }
7389
Eric Laurent39e94f82010-07-28 01:32:47 -07007390 // remove chain first. This is useful only if reconfiguring effect chain on same output thread,
Eric Laurentde070132010-07-13 04:45:46 -07007391 // so that a new chain is created with correct parameters when first effect is added. This is
Eric Laurentec35a142011-10-05 17:42:25 -07007392 // otherwise unnecessary as removeEffect_l() will remove the chain when last effect is
Eric Laurentde070132010-07-13 04:45:46 -07007393 // removed.
7394 srcThread->removeEffectChain_l(chain);
7395
7396 // transfer all effects one by one so that new effect chain is created on new thread with
7397 // correct buffer sizes and audio parameters and effect engines reconfigured accordingly
Glenn Kasten72ef00d2012-01-17 11:09:42 -08007398 audio_io_handle_t dstOutput = dstThread->id();
Eric Laurent39e94f82010-07-28 01:32:47 -07007399 sp<EffectChain> dstChain;
Marco Nelissen3a34bef2011-08-02 13:33:41 -07007400 uint32_t strategy = 0; // prevent compiler warning
Eric Laurentde070132010-07-13 04:45:46 -07007401 sp<EffectModule> effect = chain->getEffectFromId_l(0);
7402 while (effect != 0) {
7403 srcThread->removeEffect_l(effect);
7404 dstThread->addEffect_l(effect);
Eric Laurentec35a142011-10-05 17:42:25 -07007405 // removeEffect_l() has stopped the effect if it was active so it must be restarted
7406 if (effect->state() == EffectModule::ACTIVE ||
7407 effect->state() == EffectModule::STOPPING) {
7408 effect->start();
7409 }
Eric Laurent39e94f82010-07-28 01:32:47 -07007410 // if the move request is not received from audio policy manager, the effect must be
7411 // re-registered with the new strategy and output
7412 if (dstChain == 0) {
7413 dstChain = effect->chain().promote();
7414 if (dstChain == 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00007415 ALOGW("moveEffectChain_l() cannot get chain from effect %p", effect.get());
Eric Laurent39e94f82010-07-28 01:32:47 -07007416 srcThread->addEffect_l(effect);
7417 return NO_INIT;
7418 }
7419 strategy = dstChain->strategy();
7420 }
7421 if (reRegister) {
7422 AudioSystem::unregisterEffect(effect->id());
7423 AudioSystem::registerEffect(&effect->desc(),
7424 dstOutput,
7425 strategy,
Eric Laurent59255e42011-07-27 19:49:51 -07007426 sessionId,
Eric Laurent39e94f82010-07-28 01:32:47 -07007427 effect->id());
7428 }
Eric Laurentde070132010-07-13 04:45:46 -07007429 effect = chain->getEffectFromId_l(0);
7430 }
7431
7432 return NO_ERROR;
Mathias Agopian65ab4712010-07-14 17:59:35 -07007433}
7434
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007435
Mathias Agopian65ab4712010-07-14 17:59:35 -07007436// PlaybackThread::createEffect_l() must be called with AudioFlinger::mLock held
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007437sp<AudioFlinger::EffectHandle> AudioFlinger::ThreadBase::createEffect_l(
Mathias Agopian65ab4712010-07-14 17:59:35 -07007438 const sp<AudioFlinger::Client>& client,
7439 const sp<IEffectClient>& effectClient,
7440 int32_t priority,
7441 int sessionId,
7442 effect_descriptor_t *desc,
7443 int *enabled,
7444 status_t *status
7445 )
7446{
7447 sp<EffectModule> effect;
7448 sp<EffectHandle> handle;
7449 status_t lStatus;
Mathias Agopian65ab4712010-07-14 17:59:35 -07007450 sp<EffectChain> chain;
Eric Laurentde070132010-07-13 04:45:46 -07007451 bool chainCreated = false;
Mathias Agopian65ab4712010-07-14 17:59:35 -07007452 bool effectCreated = false;
7453 bool effectRegistered = false;
7454
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007455 lStatus = initCheck();
7456 if (lStatus != NO_ERROR) {
Steve Block5ff1dd52012-01-05 23:22:43 +00007457 ALOGW("createEffect_l() Audio driver not initialized.");
Mathias Agopian65ab4712010-07-14 17:59:35 -07007458 goto Exit;
7459 }
7460
7461 // Do not allow effects with session ID 0 on direct output or duplicating threads
7462 // TODO: add rule for hw accelerated effects on direct outputs with non PCM format
Dima Zavinfce7a472011-04-19 22:30:36 -07007463 if (sessionId == AUDIO_SESSION_OUTPUT_MIX && mType != MIXER) {
Steve Block5ff1dd52012-01-05 23:22:43 +00007464 ALOGW("createEffect_l() Cannot add auxiliary effect %s to session %d",
Eric Laurentde070132010-07-13 04:45:46 -07007465 desc->name, sessionId);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007466 lStatus = BAD_VALUE;
7467 goto Exit;
7468 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007469 // Only Pre processor effects are allowed on input threads and only on input threads
Glenn Kastena1117922012-01-26 10:53:32 -08007470 if ((mType == RECORD) != ((desc->flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC)) {
Steve Block5ff1dd52012-01-05 23:22:43 +00007471 ALOGW("createEffect_l() effect %s (flags %08x) created on wrong thread type %d",
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007472 desc->name, desc->flags, mType);
7473 lStatus = BAD_VALUE;
7474 goto Exit;
7475 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07007476
Steve Block3856b092011-10-20 11:56:00 +01007477 ALOGV("createEffect_l() thread %p effect %s on session %d", this, desc->name, sessionId);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007478
7479 { // scope for mLock
7480 Mutex::Autolock _l(mLock);
7481
7482 // check for existing effect chain with the requested audio session
7483 chain = getEffectChain_l(sessionId);
7484 if (chain == 0) {
7485 // create a new chain for this session
Steve Block3856b092011-10-20 11:56:00 +01007486 ALOGV("createEffect_l() new effect chain for session %d", sessionId);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007487 chain = new EffectChain(this, sessionId);
7488 addEffectChain_l(chain);
Eric Laurentde070132010-07-13 04:45:46 -07007489 chain->setStrategy(getStrategyForSession_l(sessionId));
7490 chainCreated = true;
Mathias Agopian65ab4712010-07-14 17:59:35 -07007491 } else {
Eric Laurentcab11242010-07-15 12:50:15 -07007492 effect = chain->getEffectFromDesc_l(desc);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007493 }
7494
Glenn Kasten7fc9a6f2012-01-10 10:46:34 -08007495 ALOGV("createEffect_l() got effect %p on chain %p", effect.get(), chain.get());
Mathias Agopian65ab4712010-07-14 17:59:35 -07007496
7497 if (effect == 0) {
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007498 int id = mAudioFlinger->nextUniqueId();
Mathias Agopian65ab4712010-07-14 17:59:35 -07007499 // Check CPU and memory usage
Eric Laurentde070132010-07-13 04:45:46 -07007500 lStatus = AudioSystem::registerEffect(desc, mId, chain->strategy(), sessionId, id);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007501 if (lStatus != NO_ERROR) {
7502 goto Exit;
7503 }
7504 effectRegistered = true;
7505 // create a new effect module if none present in the chain
Eric Laurentde070132010-07-13 04:45:46 -07007506 effect = new EffectModule(this, chain, desc, id, sessionId);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007507 lStatus = effect->status();
7508 if (lStatus != NO_ERROR) {
7509 goto Exit;
7510 }
Eric Laurentcab11242010-07-15 12:50:15 -07007511 lStatus = chain->addEffect_l(effect);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007512 if (lStatus != NO_ERROR) {
7513 goto Exit;
7514 }
7515 effectCreated = true;
7516
7517 effect->setDevice(mDevice);
7518 effect->setMode(mAudioFlinger->getMode());
7519 }
7520 // create effect handle and connect it to effect module
7521 handle = new EffectHandle(effect, client, effectClient, priority);
7522 lStatus = effect->addHandle(handle);
Glenn Kastena0d68332012-01-27 16:47:15 -08007523 if (enabled != NULL) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07007524 *enabled = (int)effect->isEnabled();
7525 }
7526 }
7527
7528Exit:
7529 if (lStatus != NO_ERROR && lStatus != ALREADY_EXISTS) {
Eric Laurentde070132010-07-13 04:45:46 -07007530 Mutex::Autolock _l(mLock);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007531 if (effectCreated) {
Eric Laurentde070132010-07-13 04:45:46 -07007532 chain->removeEffect_l(effect);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007533 }
7534 if (effectRegistered) {
Eric Laurentde070132010-07-13 04:45:46 -07007535 AudioSystem::unregisterEffect(effect->id());
7536 }
7537 if (chainCreated) {
7538 removeEffectChain_l(chain);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007539 }
7540 handle.clear();
7541 }
7542
Glenn Kastene53b9ea2012-03-12 16:29:55 -07007543 if (status != NULL) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07007544 *status = lStatus;
7545 }
7546 return handle;
7547}
7548
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007549sp<AudioFlinger::EffectModule> AudioFlinger::ThreadBase::getEffect_l(int sessionId, int effectId)
7550{
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007551 sp<EffectChain> chain = getEffectChain_l(sessionId);
Glenn Kasten090f0192012-01-30 13:00:02 -08007552 return chain != 0 ? chain->getEffectFromId_l(effectId) : 0;
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007553}
7554
Eric Laurentde070132010-07-13 04:45:46 -07007555// PlaybackThread::addEffect_l() must be called with AudioFlinger::mLock and
7556// PlaybackThread::mLock held
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007557status_t AudioFlinger::ThreadBase::addEffect_l(const sp<EffectModule>& effect)
Eric Laurentde070132010-07-13 04:45:46 -07007558{
7559 // check for existing effect chain with the requested audio session
7560 int sessionId = effect->sessionId();
7561 sp<EffectChain> chain = getEffectChain_l(sessionId);
7562 bool chainCreated = false;
7563
7564 if (chain == 0) {
7565 // create a new chain for this session
Steve Block3856b092011-10-20 11:56:00 +01007566 ALOGV("addEffect_l() new effect chain for session %d", sessionId);
Eric Laurentde070132010-07-13 04:45:46 -07007567 chain = new EffectChain(this, sessionId);
7568 addEffectChain_l(chain);
7569 chain->setStrategy(getStrategyForSession_l(sessionId));
7570 chainCreated = true;
7571 }
Steve Block3856b092011-10-20 11:56:00 +01007572 ALOGV("addEffect_l() %p chain %p effect %p", this, chain.get(), effect.get());
Eric Laurentde070132010-07-13 04:45:46 -07007573
7574 if (chain->getEffectFromId_l(effect->id()) != 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00007575 ALOGW("addEffect_l() %p effect %s already present in chain %p",
Eric Laurentde070132010-07-13 04:45:46 -07007576 this, effect->desc().name, chain.get());
7577 return BAD_VALUE;
7578 }
7579
7580 status_t status = chain->addEffect_l(effect);
7581 if (status != NO_ERROR) {
7582 if (chainCreated) {
7583 removeEffectChain_l(chain);
7584 }
7585 return status;
7586 }
7587
7588 effect->setDevice(mDevice);
7589 effect->setMode(mAudioFlinger->getMode());
7590 return NO_ERROR;
7591}
7592
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007593void AudioFlinger::ThreadBase::removeEffect_l(const sp<EffectModule>& effect) {
Eric Laurentde070132010-07-13 04:45:46 -07007594
Steve Block3856b092011-10-20 11:56:00 +01007595 ALOGV("removeEffect_l() %p effect %p", this, effect.get());
Mathias Agopian65ab4712010-07-14 17:59:35 -07007596 effect_descriptor_t desc = effect->desc();
Eric Laurentde070132010-07-13 04:45:46 -07007597 if ((desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
7598 detachAuxEffect_l(effect->id());
7599 }
7600
7601 sp<EffectChain> chain = effect->chain().promote();
7602 if (chain != 0) {
7603 // remove effect chain if removing last effect
7604 if (chain->removeEffect_l(effect) == 0) {
7605 removeEffectChain_l(chain);
7606 }
7607 } else {
Steve Block5ff1dd52012-01-05 23:22:43 +00007608 ALOGW("removeEffect_l() %p cannot promote chain for effect %p", this, effect.get());
Eric Laurentde070132010-07-13 04:45:46 -07007609 }
7610}
7611
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007612void AudioFlinger::ThreadBase::lockEffectChains_l(
Glenn Kastene53b9ea2012-03-12 16:29:55 -07007613 Vector< sp<AudioFlinger::EffectChain> >& effectChains)
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007614{
7615 effectChains = mEffectChains;
7616 for (size_t i = 0; i < mEffectChains.size(); i++) {
7617 mEffectChains[i]->lock();
7618 }
7619}
7620
7621void AudioFlinger::ThreadBase::unlockEffectChains(
Glenn Kastene53b9ea2012-03-12 16:29:55 -07007622 const Vector< sp<AudioFlinger::EffectChain> >& effectChains)
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007623{
7624 for (size_t i = 0; i < effectChains.size(); i++) {
7625 effectChains[i]->unlock();
7626 }
7627}
7628
7629sp<AudioFlinger::EffectChain> AudioFlinger::ThreadBase::getEffectChain(int sessionId)
7630{
7631 Mutex::Autolock _l(mLock);
7632 return getEffectChain_l(sessionId);
7633}
7634
7635sp<AudioFlinger::EffectChain> AudioFlinger::ThreadBase::getEffectChain_l(int sessionId)
7636{
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007637 size_t size = mEffectChains.size();
7638 for (size_t i = 0; i < size; i++) {
7639 if (mEffectChains[i]->sessionId() == sessionId) {
Glenn Kasten090f0192012-01-30 13:00:02 -08007640 return mEffectChains[i];
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007641 }
7642 }
Glenn Kasten090f0192012-01-30 13:00:02 -08007643 return 0;
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007644}
7645
Glenn Kastenf78aee72012-01-04 11:00:47 -08007646void AudioFlinger::ThreadBase::setMode(audio_mode_t mode)
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007647{
7648 Mutex::Autolock _l(mLock);
7649 size_t size = mEffectChains.size();
7650 for (size_t i = 0; i < size; i++) {
7651 mEffectChains[i]->setMode_l(mode);
7652 }
7653}
7654
7655void AudioFlinger::ThreadBase::disconnectEffect(const sp<EffectModule>& effect,
Marco Nelissen3a34bef2011-08-02 13:33:41 -07007656 const wp<EffectHandle>& handle,
Glenn Kasten58123c32012-02-03 10:32:24 -08007657 bool unpinIfLast) {
Eric Laurent59255e42011-07-27 19:49:51 -07007658
Mathias Agopian65ab4712010-07-14 17:59:35 -07007659 Mutex::Autolock _l(mLock);
Steve Block3856b092011-10-20 11:56:00 +01007660 ALOGV("disconnectEffect() %p effect %p", this, effect.get());
Mathias Agopian65ab4712010-07-14 17:59:35 -07007661 // delete the effect module if removing last handle on it
7662 if (effect->removeHandle(handle) == 0) {
Glenn Kasten58123c32012-02-03 10:32:24 -08007663 if (!effect->isPinned() || unpinIfLast) {
Marco Nelissen3a34bef2011-08-02 13:33:41 -07007664 removeEffect_l(effect);
7665 AudioSystem::unregisterEffect(effect->id());
7666 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07007667 }
7668}
7669
7670status_t AudioFlinger::PlaybackThread::addEffectChain_l(const sp<EffectChain>& chain)
7671{
7672 int session = chain->sessionId();
7673 int16_t *buffer = mMixBuffer;
7674 bool ownsBuffer = false;
7675
Steve Block3856b092011-10-20 11:56:00 +01007676 ALOGV("addEffectChain_l() %p on thread %p for session %d", chain.get(), this, session);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007677 if (session > 0) {
7678 // Only one effect chain can be present in direct output thread and it uses
7679 // the mix buffer as input
7680 if (mType != DIRECT) {
Glenn Kasten58912562012-04-03 10:45:00 -07007681 size_t numSamples = mNormalFrameCount * mChannelCount;
Mathias Agopian65ab4712010-07-14 17:59:35 -07007682 buffer = new int16_t[numSamples];
7683 memset(buffer, 0, numSamples * sizeof(int16_t));
Steve Block3856b092011-10-20 11:56:00 +01007684 ALOGV("addEffectChain_l() creating new input buffer %p session %d", buffer, session);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007685 ownsBuffer = true;
7686 }
7687
7688 // Attach all tracks with same session ID to this chain.
7689 for (size_t i = 0; i < mTracks.size(); ++i) {
7690 sp<Track> track = mTracks[i];
7691 if (session == track->sessionId()) {
Steve Block3856b092011-10-20 11:56:00 +01007692 ALOGV("addEffectChain_l() track->setMainBuffer track %p buffer %p", track.get(), buffer);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007693 track->setMainBuffer(buffer);
Eric Laurentb469b942011-05-09 12:09:06 -07007694 chain->incTrackCnt();
Mathias Agopian65ab4712010-07-14 17:59:35 -07007695 }
7696 }
7697
7698 // indicate all active tracks in the chain
7699 for (size_t i = 0 ; i < mActiveTracks.size() ; ++i) {
7700 sp<Track> track = mActiveTracks[i].promote();
7701 if (track == 0) continue;
7702 if (session == track->sessionId()) {
Steve Block3856b092011-10-20 11:56:00 +01007703 ALOGV("addEffectChain_l() activating track %p on session %d", track.get(), session);
Eric Laurentb469b942011-05-09 12:09:06 -07007704 chain->incActiveTrackCnt();
Mathias Agopian65ab4712010-07-14 17:59:35 -07007705 }
7706 }
7707 }
7708
7709 chain->setInBuffer(buffer, ownsBuffer);
7710 chain->setOutBuffer(mMixBuffer);
Dima Zavinfce7a472011-04-19 22:30:36 -07007711 // Effect chain for session AUDIO_SESSION_OUTPUT_STAGE is inserted at end of effect
Eric Laurentde070132010-07-13 04:45:46 -07007712 // chains list in order to be processed last as it contains output stage effects
Dima Zavinfce7a472011-04-19 22:30:36 -07007713 // Effect chain for session AUDIO_SESSION_OUTPUT_MIX is inserted before
7714 // session AUDIO_SESSION_OUTPUT_STAGE to be processed
Mathias Agopian65ab4712010-07-14 17:59:35 -07007715 // after track specific effects and before output stage
Dima Zavinfce7a472011-04-19 22:30:36 -07007716 // It is therefore mandatory that AUDIO_SESSION_OUTPUT_MIX == 0 and
7717 // that AUDIO_SESSION_OUTPUT_STAGE < AUDIO_SESSION_OUTPUT_MIX
Eric Laurentde070132010-07-13 04:45:46 -07007718 // Effect chain for other sessions are inserted at beginning of effect
7719 // chains list to be processed before output mix effects. Relative order between other
7720 // sessions is not important
Mathias Agopian65ab4712010-07-14 17:59:35 -07007721 size_t size = mEffectChains.size();
7722 size_t i = 0;
7723 for (i = 0; i < size; i++) {
7724 if (mEffectChains[i]->sessionId() < session) break;
7725 }
7726 mEffectChains.insertAt(chain, i);
Eric Laurent59255e42011-07-27 19:49:51 -07007727 checkSuspendOnAddEffectChain_l(chain);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007728
7729 return NO_ERROR;
7730}
7731
7732size_t AudioFlinger::PlaybackThread::removeEffectChain_l(const sp<EffectChain>& chain)
7733{
7734 int session = chain->sessionId();
7735
Steve Block3856b092011-10-20 11:56:00 +01007736 ALOGV("removeEffectChain_l() %p from thread %p for session %d", chain.get(), this, session);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007737
7738 for (size_t i = 0; i < mEffectChains.size(); i++) {
7739 if (chain == mEffectChains[i]) {
7740 mEffectChains.removeAt(i);
Eric Laurentb469b942011-05-09 12:09:06 -07007741 // detach all active tracks from the chain
7742 for (size_t i = 0 ; i < mActiveTracks.size() ; ++i) {
7743 sp<Track> track = mActiveTracks[i].promote();
7744 if (track == 0) continue;
7745 if (session == track->sessionId()) {
Steve Block3856b092011-10-20 11:56:00 +01007746 ALOGV("removeEffectChain_l(): stopping track on chain %p for session Id: %d",
Eric Laurentb469b942011-05-09 12:09:06 -07007747 chain.get(), session);
7748 chain->decActiveTrackCnt();
7749 }
7750 }
7751
Mathias Agopian65ab4712010-07-14 17:59:35 -07007752 // detach all tracks with same session ID from this chain
7753 for (size_t i = 0; i < mTracks.size(); ++i) {
7754 sp<Track> track = mTracks[i];
7755 if (session == track->sessionId()) {
7756 track->setMainBuffer(mMixBuffer);
Eric Laurentb469b942011-05-09 12:09:06 -07007757 chain->decTrackCnt();
Mathias Agopian65ab4712010-07-14 17:59:35 -07007758 }
7759 }
Eric Laurentde070132010-07-13 04:45:46 -07007760 break;
Mathias Agopian65ab4712010-07-14 17:59:35 -07007761 }
7762 }
7763 return mEffectChains.size();
7764}
7765
Eric Laurentde070132010-07-13 04:45:46 -07007766status_t AudioFlinger::PlaybackThread::attachAuxEffect(
7767 const sp<AudioFlinger::PlaybackThread::Track> track, int EffectId)
Mathias Agopian65ab4712010-07-14 17:59:35 -07007768{
7769 Mutex::Autolock _l(mLock);
7770 return attachAuxEffect_l(track, EffectId);
7771}
7772
Eric Laurentde070132010-07-13 04:45:46 -07007773status_t AudioFlinger::PlaybackThread::attachAuxEffect_l(
7774 const sp<AudioFlinger::PlaybackThread::Track> track, int EffectId)
Mathias Agopian65ab4712010-07-14 17:59:35 -07007775{
7776 status_t status = NO_ERROR;
7777
7778 if (EffectId == 0) {
7779 track->setAuxBuffer(0, NULL);
7780 } else {
Dima Zavinfce7a472011-04-19 22:30:36 -07007781 // Auxiliary effects are always in audio session AUDIO_SESSION_OUTPUT_MIX
7782 sp<EffectModule> effect = getEffect_l(AUDIO_SESSION_OUTPUT_MIX, EffectId);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007783 if (effect != 0) {
7784 if ((effect->desc().flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
7785 track->setAuxBuffer(EffectId, (int32_t *)effect->inBuffer());
7786 } else {
7787 status = INVALID_OPERATION;
7788 }
7789 } else {
7790 status = BAD_VALUE;
7791 }
7792 }
7793 return status;
7794}
7795
7796void AudioFlinger::PlaybackThread::detachAuxEffect_l(int effectId)
7797{
Glenn Kastene53b9ea2012-03-12 16:29:55 -07007798 for (size_t i = 0; i < mTracks.size(); ++i) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07007799 sp<Track> track = mTracks[i];
7800 if (track->auxEffectId() == effectId) {
7801 attachAuxEffect_l(track, 0);
7802 }
7803 }
7804}
7805
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007806status_t AudioFlinger::RecordThread::addEffectChain_l(const sp<EffectChain>& chain)
7807{
7808 // only one chain per input thread
7809 if (mEffectChains.size() != 0) {
7810 return INVALID_OPERATION;
7811 }
Steve Block3856b092011-10-20 11:56:00 +01007812 ALOGV("addEffectChain_l() %p on thread %p", chain.get(), this);
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007813
7814 chain->setInBuffer(NULL);
7815 chain->setOutBuffer(NULL);
7816
Eric Laurent59255e42011-07-27 19:49:51 -07007817 checkSuspendOnAddEffectChain_l(chain);
7818
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007819 mEffectChains.add(chain);
7820
7821 return NO_ERROR;
7822}
7823
7824size_t AudioFlinger::RecordThread::removeEffectChain_l(const sp<EffectChain>& chain)
7825{
Steve Block3856b092011-10-20 11:56:00 +01007826 ALOGV("removeEffectChain_l() %p from thread %p", chain.get(), this);
Steve Block5ff1dd52012-01-05 23:22:43 +00007827 ALOGW_IF(mEffectChains.size() != 1,
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007828 "removeEffectChain_l() %p invalid chain size %d on thread %p",
7829 chain.get(), mEffectChains.size(), this);
7830 if (mEffectChains.size() == 1) {
7831 mEffectChains.removeAt(0);
7832 }
7833 return 0;
7834}
7835
Mathias Agopian65ab4712010-07-14 17:59:35 -07007836// ----------------------------------------------------------------------------
7837// EffectModule implementation
7838// ----------------------------------------------------------------------------
7839
7840#undef LOG_TAG
7841#define LOG_TAG "AudioFlinger::EffectModule"
7842
Glenn Kasten9eaa5572012-01-20 13:32:16 -08007843AudioFlinger::EffectModule::EffectModule(ThreadBase *thread,
Mathias Agopian65ab4712010-07-14 17:59:35 -07007844 const wp<AudioFlinger::EffectChain>& chain,
7845 effect_descriptor_t *desc,
7846 int id,
7847 int sessionId)
Glenn Kasten9eaa5572012-01-20 13:32:16 -08007848 : mThread(thread), mChain(chain), mId(id), mSessionId(sessionId), mEffectInterface(NULL),
Eric Laurent59255e42011-07-27 19:49:51 -07007849 mStatus(NO_INIT), mState(IDLE), mSuspended(false)
Mathias Agopian65ab4712010-07-14 17:59:35 -07007850{
Steve Block3856b092011-10-20 11:56:00 +01007851 ALOGV("Constructor %p", this);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007852 int lStatus;
Glenn Kasten9eaa5572012-01-20 13:32:16 -08007853 if (thread == NULL) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07007854 return;
7855 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07007856
7857 memcpy(&mDescriptor, desc, sizeof(effect_descriptor_t));
7858
7859 // create effect engine from effect factory
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007860 mStatus = EffectCreate(&desc->uuid, sessionId, thread->id(), &mEffectInterface);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007861
7862 if (mStatus != NO_ERROR) {
7863 return;
7864 }
7865 lStatus = init();
7866 if (lStatus < 0) {
7867 mStatus = lStatus;
7868 goto Error;
7869 }
7870
Marco Nelissen3a34bef2011-08-02 13:33:41 -07007871 if (mSessionId > AUDIO_SESSION_OUTPUT_MIX) {
7872 mPinned = true;
7873 }
Steve Block3856b092011-10-20 11:56:00 +01007874 ALOGV("Constructor success name %s, Interface %p", mDescriptor.name, mEffectInterface);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007875 return;
7876Error:
7877 EffectRelease(mEffectInterface);
7878 mEffectInterface = NULL;
Steve Block3856b092011-10-20 11:56:00 +01007879 ALOGV("Constructor Error %d", mStatus);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007880}
7881
7882AudioFlinger::EffectModule::~EffectModule()
7883{
Steve Block3856b092011-10-20 11:56:00 +01007884 ALOGV("Destructor %p", this);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007885 if (mEffectInterface != NULL) {
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007886 if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC ||
7887 (mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_POST_PROC) {
7888 sp<ThreadBase> thread = mThread.promote();
7889 if (thread != 0) {
Eric Laurentb8ba0a92011-08-07 16:32:26 -07007890 audio_stream_t *stream = thread->stream();
7891 if (stream != NULL) {
7892 stream->remove_audio_effect(stream, mEffectInterface);
7893 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007894 }
7895 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07007896 // release effect engine
7897 EffectRelease(mEffectInterface);
7898 }
7899}
7900
Glenn Kasten435dbe62012-01-30 10:15:48 -08007901status_t AudioFlinger::EffectModule::addHandle(const sp<EffectHandle>& handle)
Mathias Agopian65ab4712010-07-14 17:59:35 -07007902{
7903 status_t status;
7904
7905 Mutex::Autolock _l(mLock);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007906 int priority = handle->priority();
7907 size_t size = mHandles.size();
7908 sp<EffectHandle> h;
7909 size_t i;
7910 for (i = 0; i < size; i++) {
7911 h = mHandles[i].promote();
7912 if (h == 0) continue;
7913 if (h->priority() <= priority) break;
7914 }
7915 // if inserted in first place, move effect control from previous owner to this handle
7916 if (i == 0) {
Eric Laurent59255e42011-07-27 19:49:51 -07007917 bool enabled = false;
Mathias Agopian65ab4712010-07-14 17:59:35 -07007918 if (h != 0) {
Eric Laurent59255e42011-07-27 19:49:51 -07007919 enabled = h->enabled();
7920 h->setControl(false/*hasControl*/, true /*signal*/, enabled /*enabled*/);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007921 }
Eric Laurent59255e42011-07-27 19:49:51 -07007922 handle->setControl(true /*hasControl*/, false /*signal*/, enabled /*enabled*/);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007923 status = NO_ERROR;
7924 } else {
7925 status = ALREADY_EXISTS;
7926 }
Steve Block3856b092011-10-20 11:56:00 +01007927 ALOGV("addHandle() %p added handle %p in position %d", this, handle.get(), i);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007928 mHandles.insertAt(handle, i);
7929 return status;
7930}
7931
7932size_t AudioFlinger::EffectModule::removeHandle(const wp<EffectHandle>& handle)
7933{
7934 Mutex::Autolock _l(mLock);
7935 size_t size = mHandles.size();
7936 size_t i;
7937 for (i = 0; i < size; i++) {
7938 if (mHandles[i] == handle) break;
7939 }
7940 if (i == size) {
7941 return size;
7942 }
Steve Block3856b092011-10-20 11:56:00 +01007943 ALOGV("removeHandle() %p removed handle %p in position %d", this, handle.unsafe_get(), i);
Eric Laurent59255e42011-07-27 19:49:51 -07007944
7945 bool enabled = false;
7946 EffectHandle *hdl = handle.unsafe_get();
Glenn Kastena0d68332012-01-27 16:47:15 -08007947 if (hdl != NULL) {
Steve Block3856b092011-10-20 11:56:00 +01007948 ALOGV("removeHandle() unsafe_get OK");
Eric Laurent59255e42011-07-27 19:49:51 -07007949 enabled = hdl->enabled();
7950 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07007951 mHandles.removeAt(i);
7952 size = mHandles.size();
7953 // if removed from first place, move effect control from this handle to next in line
7954 if (i == 0 && size != 0) {
7955 sp<EffectHandle> h = mHandles[0].promote();
7956 if (h != 0) {
Eric Laurent59255e42011-07-27 19:49:51 -07007957 h->setControl(true /*hasControl*/, true /*signal*/ , enabled /*enabled*/);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007958 }
7959 }
7960
Eric Laurentec437d82011-07-26 20:54:46 -07007961 // Prevent calls to process() and other functions on effect interface from now on.
7962 // The effect engine will be released by the destructor when the last strong reference on
7963 // this object is released which can happen after next process is called.
Marco Nelissen3a34bef2011-08-02 13:33:41 -07007964 if (size == 0 && !mPinned) {
Eric Laurentec437d82011-07-26 20:54:46 -07007965 mState = DESTROYED;
Eric Laurentdac69112010-09-28 14:09:57 -07007966 }
7967
Mathias Agopian65ab4712010-07-14 17:59:35 -07007968 return size;
7969}
7970
Eric Laurent59255e42011-07-27 19:49:51 -07007971sp<AudioFlinger::EffectHandle> AudioFlinger::EffectModule::controlHandle()
7972{
7973 Mutex::Autolock _l(mLock);
Glenn Kasten090f0192012-01-30 13:00:02 -08007974 return mHandles.size() != 0 ? mHandles[0].promote() : 0;
Eric Laurent59255e42011-07-27 19:49:51 -07007975}
7976
Glenn Kasten58123c32012-02-03 10:32:24 -08007977void AudioFlinger::EffectModule::disconnect(const wp<EffectHandle>& handle, bool unpinIfLast)
Mathias Agopian65ab4712010-07-14 17:59:35 -07007978{
Glenn Kasten90bebef2012-01-27 15:24:38 -08007979 ALOGV("disconnect() %p handle %p", this, handle.unsafe_get());
Mathias Agopian65ab4712010-07-14 17:59:35 -07007980 // keep a strong reference on this EffectModule to avoid calling the
7981 // destructor before we exit
7982 sp<EffectModule> keep(this);
7983 {
7984 sp<ThreadBase> thread = mThread.promote();
7985 if (thread != 0) {
Glenn Kasten58123c32012-02-03 10:32:24 -08007986 thread->disconnectEffect(keep, handle, unpinIfLast);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007987 }
7988 }
7989}
7990
7991void AudioFlinger::EffectModule::updateState() {
7992 Mutex::Autolock _l(mLock);
7993
7994 switch (mState) {
7995 case RESTART:
7996 reset_l();
7997 // FALL THROUGH
7998
7999 case STARTING:
8000 // clear auxiliary effect input buffer for next accumulation
8001 if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
8002 memset(mConfig.inputCfg.buffer.raw,
8003 0,
8004 mConfig.inputCfg.buffer.frameCount*sizeof(int32_t));
8005 }
8006 start_l();
8007 mState = ACTIVE;
8008 break;
8009 case STOPPING:
8010 stop_l();
8011 mDisableWaitCnt = mMaxDisableWaitCnt;
8012 mState = STOPPED;
8013 break;
8014 case STOPPED:
8015 // mDisableWaitCnt is forced to 1 by process() when the engine indicates the end of the
8016 // turn off sequence.
8017 if (--mDisableWaitCnt == 0) {
8018 reset_l();
8019 mState = IDLE;
8020 }
8021 break;
Eric Laurentec437d82011-07-26 20:54:46 -07008022 default: //IDLE , ACTIVE, DESTROYED
Mathias Agopian65ab4712010-07-14 17:59:35 -07008023 break;
8024 }
8025}
8026
8027void AudioFlinger::EffectModule::process()
8028{
8029 Mutex::Autolock _l(mLock);
8030
Eric Laurentec437d82011-07-26 20:54:46 -07008031 if (mState == DESTROYED || mEffectInterface == NULL ||
Mathias Agopian65ab4712010-07-14 17:59:35 -07008032 mConfig.inputCfg.buffer.raw == NULL ||
8033 mConfig.outputCfg.buffer.raw == NULL) {
8034 return;
8035 }
8036
Eric Laurent8f45bd72010-08-31 13:50:07 -07008037 if (isProcessEnabled()) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07008038 // do 32 bit to 16 bit conversion for auxiliary effect input buffer
8039 if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
Glenn Kasten3b21c502011-12-15 09:52:39 -08008040 ditherAndClamp(mConfig.inputCfg.buffer.s32,
Mathias Agopian65ab4712010-07-14 17:59:35 -07008041 mConfig.inputCfg.buffer.s32,
Eric Laurentde070132010-07-13 04:45:46 -07008042 mConfig.inputCfg.buffer.frameCount/2);
Mathias Agopian65ab4712010-07-14 17:59:35 -07008043 }
8044
8045 // do the actual processing in the effect engine
8046 int ret = (*mEffectInterface)->process(mEffectInterface,
8047 &mConfig.inputCfg.buffer,
8048 &mConfig.outputCfg.buffer);
8049
8050 // force transition to IDLE state when engine is ready
8051 if (mState == STOPPED && ret == -ENODATA) {
8052 mDisableWaitCnt = 1;
8053 }
8054
8055 // clear auxiliary effect input buffer for next accumulation
8056 if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
Eric Laurent73337482011-01-19 18:36:13 -08008057 memset(mConfig.inputCfg.buffer.raw, 0,
8058 mConfig.inputCfg.buffer.frameCount*sizeof(int32_t));
Mathias Agopian65ab4712010-07-14 17:59:35 -07008059 }
8060 } else if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_INSERT &&
Eric Laurent73337482011-01-19 18:36:13 -08008061 mConfig.inputCfg.buffer.raw != mConfig.outputCfg.buffer.raw) {
8062 // If an insert effect is idle and input buffer is different from output buffer,
8063 // accumulate input onto output
Mathias Agopian65ab4712010-07-14 17:59:35 -07008064 sp<EffectChain> chain = mChain.promote();
Eric Laurentb469b942011-05-09 12:09:06 -07008065 if (chain != 0 && chain->activeTrackCnt() != 0) {
Eric Laurent73337482011-01-19 18:36:13 -08008066 size_t frameCnt = mConfig.inputCfg.buffer.frameCount * 2; //always stereo here
8067 int16_t *in = mConfig.inputCfg.buffer.s16;
8068 int16_t *out = mConfig.outputCfg.buffer.s16;
8069 for (size_t i = 0; i < frameCnt; i++) {
8070 out[i] = clamp16((int32_t)out[i] + (int32_t)in[i]);
Mathias Agopian65ab4712010-07-14 17:59:35 -07008071 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07008072 }
8073 }
8074}
8075
8076void AudioFlinger::EffectModule::reset_l()
8077{
8078 if (mEffectInterface == NULL) {
8079 return;
8080 }
8081 (*mEffectInterface)->command(mEffectInterface, EFFECT_CMD_RESET, 0, NULL, 0, NULL);
8082}
8083
8084status_t AudioFlinger::EffectModule::configure()
8085{
8086 uint32_t channels;
8087 if (mEffectInterface == NULL) {
8088 return NO_INIT;
8089 }
8090
8091 sp<ThreadBase> thread = mThread.promote();
8092 if (thread == 0) {
8093 return DEAD_OBJECT;
8094 }
8095
8096 // TODO: handle configuration of effects replacing track process
8097 if (thread->channelCount() == 1) {
Eric Laurente1315cf2011-05-17 19:16:02 -07008098 channels = AUDIO_CHANNEL_OUT_MONO;
Mathias Agopian65ab4712010-07-14 17:59:35 -07008099 } else {
Eric Laurente1315cf2011-05-17 19:16:02 -07008100 channels = AUDIO_CHANNEL_OUT_STEREO;
Mathias Agopian65ab4712010-07-14 17:59:35 -07008101 }
8102
8103 if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
Eric Laurente1315cf2011-05-17 19:16:02 -07008104 mConfig.inputCfg.channels = AUDIO_CHANNEL_OUT_MONO;
Mathias Agopian65ab4712010-07-14 17:59:35 -07008105 } else {
8106 mConfig.inputCfg.channels = channels;
8107 }
8108 mConfig.outputCfg.channels = channels;
Eric Laurente1315cf2011-05-17 19:16:02 -07008109 mConfig.inputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
8110 mConfig.outputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
Mathias Agopian65ab4712010-07-14 17:59:35 -07008111 mConfig.inputCfg.samplingRate = thread->sampleRate();
8112 mConfig.outputCfg.samplingRate = mConfig.inputCfg.samplingRate;
8113 mConfig.inputCfg.bufferProvider.cookie = NULL;
8114 mConfig.inputCfg.bufferProvider.getBuffer = NULL;
8115 mConfig.inputCfg.bufferProvider.releaseBuffer = NULL;
8116 mConfig.outputCfg.bufferProvider.cookie = NULL;
8117 mConfig.outputCfg.bufferProvider.getBuffer = NULL;
8118 mConfig.outputCfg.bufferProvider.releaseBuffer = NULL;
8119 mConfig.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ;
8120 // Insert effect:
Dima Zavinfce7a472011-04-19 22:30:36 -07008121 // - in session AUDIO_SESSION_OUTPUT_MIX or AUDIO_SESSION_OUTPUT_STAGE,
Eric Laurentde070132010-07-13 04:45:46 -07008122 // always overwrites output buffer: input buffer == output buffer
Mathias Agopian65ab4712010-07-14 17:59:35 -07008123 // - in other sessions:
8124 // last effect in the chain accumulates in output buffer: input buffer != output buffer
8125 // other effect: overwrites output buffer: input buffer == output buffer
8126 // Auxiliary effect:
8127 // accumulates in output buffer: input buffer != output buffer
8128 // Therefore: accumulate <=> input buffer != output buffer
8129 if (mConfig.inputCfg.buffer.raw != mConfig.outputCfg.buffer.raw) {
8130 mConfig.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_ACCUMULATE;
8131 } else {
8132 mConfig.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_WRITE;
8133 }
8134 mConfig.inputCfg.mask = EFFECT_CONFIG_ALL;
8135 mConfig.outputCfg.mask = EFFECT_CONFIG_ALL;
8136 mConfig.inputCfg.buffer.frameCount = thread->frameCount();
8137 mConfig.outputCfg.buffer.frameCount = mConfig.inputCfg.buffer.frameCount;
8138
Steve Block3856b092011-10-20 11:56:00 +01008139 ALOGV("configure() %p thread %p buffer %p framecount %d",
Eric Laurentde070132010-07-13 04:45:46 -07008140 this, thread.get(), mConfig.inputCfg.buffer.raw, mConfig.inputCfg.buffer.frameCount);
8141
Mathias Agopian65ab4712010-07-14 17:59:35 -07008142 status_t cmdStatus;
Eric Laurent25f43952010-07-28 05:40:18 -07008143 uint32_t size = sizeof(int);
8144 status_t status = (*mEffectInterface)->command(mEffectInterface,
Eric Laurent3d5188b2011-12-16 15:30:36 -08008145 EFFECT_CMD_SET_CONFIG,
Eric Laurent25f43952010-07-28 05:40:18 -07008146 sizeof(effect_config_t),
8147 &mConfig,
8148 &size,
8149 &cmdStatus);
Mathias Agopian65ab4712010-07-14 17:59:35 -07008150 if (status == 0) {
8151 status = cmdStatus;
8152 }
8153
8154 mMaxDisableWaitCnt = (MAX_DISABLE_TIME_MS * mConfig.outputCfg.samplingRate) /
8155 (1000 * mConfig.outputCfg.buffer.frameCount);
8156
8157 return status;
8158}
8159
8160status_t AudioFlinger::EffectModule::init()
8161{
8162 Mutex::Autolock _l(mLock);
8163 if (mEffectInterface == NULL) {
8164 return NO_INIT;
8165 }
8166 status_t cmdStatus;
Eric Laurent25f43952010-07-28 05:40:18 -07008167 uint32_t size = sizeof(status_t);
8168 status_t status = (*mEffectInterface)->command(mEffectInterface,
8169 EFFECT_CMD_INIT,
8170 0,
8171 NULL,
8172 &size,
8173 &cmdStatus);
Mathias Agopian65ab4712010-07-14 17:59:35 -07008174 if (status == 0) {
8175 status = cmdStatus;
8176 }
8177 return status;
8178}
8179
Eric Laurentec35a142011-10-05 17:42:25 -07008180status_t AudioFlinger::EffectModule::start()
8181{
8182 Mutex::Autolock _l(mLock);
8183 return start_l();
8184}
8185
Mathias Agopian65ab4712010-07-14 17:59:35 -07008186status_t AudioFlinger::EffectModule::start_l()
8187{
8188 if (mEffectInterface == NULL) {
8189 return NO_INIT;
8190 }
8191 status_t cmdStatus;
Eric Laurent25f43952010-07-28 05:40:18 -07008192 uint32_t size = sizeof(status_t);
8193 status_t status = (*mEffectInterface)->command(mEffectInterface,
8194 EFFECT_CMD_ENABLE,
8195 0,
8196 NULL,
8197 &size,
8198 &cmdStatus);
Mathias Agopian65ab4712010-07-14 17:59:35 -07008199 if (status == 0) {
8200 status = cmdStatus;
8201 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07008202 if (status == 0 &&
8203 ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC ||
8204 (mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_POST_PROC)) {
8205 sp<ThreadBase> thread = mThread.promote();
8206 if (thread != 0) {
Eric Laurentb8ba0a92011-08-07 16:32:26 -07008207 audio_stream_t *stream = thread->stream();
8208 if (stream != NULL) {
8209 stream->add_audio_effect(stream, mEffectInterface);
8210 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07008211 }
8212 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07008213 return status;
8214}
8215
Eric Laurentec437d82011-07-26 20:54:46 -07008216status_t AudioFlinger::EffectModule::stop()
8217{
8218 Mutex::Autolock _l(mLock);
8219 return stop_l();
8220}
8221
Mathias Agopian65ab4712010-07-14 17:59:35 -07008222status_t AudioFlinger::EffectModule::stop_l()
8223{
8224 if (mEffectInterface == NULL) {
8225 return NO_INIT;
8226 }
8227 status_t cmdStatus;
Eric Laurent25f43952010-07-28 05:40:18 -07008228 uint32_t size = sizeof(status_t);
8229 status_t status = (*mEffectInterface)->command(mEffectInterface,
8230 EFFECT_CMD_DISABLE,
8231 0,
8232 NULL,
8233 &size,
8234 &cmdStatus);
Mathias Agopian65ab4712010-07-14 17:59:35 -07008235 if (status == 0) {
8236 status = cmdStatus;
8237 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07008238 if (status == 0 &&
8239 ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC ||
8240 (mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_POST_PROC)) {
8241 sp<ThreadBase> thread = mThread.promote();
8242 if (thread != 0) {
Eric Laurentb8ba0a92011-08-07 16:32:26 -07008243 audio_stream_t *stream = thread->stream();
8244 if (stream != NULL) {
8245 stream->remove_audio_effect(stream, mEffectInterface);
8246 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07008247 }
8248 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07008249 return status;
8250}
8251
Eric Laurent25f43952010-07-28 05:40:18 -07008252status_t AudioFlinger::EffectModule::command(uint32_t cmdCode,
8253 uint32_t cmdSize,
8254 void *pCmdData,
8255 uint32_t *replySize,
8256 void *pReplyData)
Mathias Agopian65ab4712010-07-14 17:59:35 -07008257{
8258 Mutex::Autolock _l(mLock);
Steve Block3856b092011-10-20 11:56:00 +01008259// ALOGV("command(), cmdCode: %d, mEffectInterface: %p", cmdCode, mEffectInterface);
Mathias Agopian65ab4712010-07-14 17:59:35 -07008260
Eric Laurentec437d82011-07-26 20:54:46 -07008261 if (mState == DESTROYED || mEffectInterface == NULL) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07008262 return NO_INIT;
8263 }
Eric Laurent25f43952010-07-28 05:40:18 -07008264 status_t status = (*mEffectInterface)->command(mEffectInterface,
8265 cmdCode,
8266 cmdSize,
8267 pCmdData,
8268 replySize,
8269 pReplyData);
Mathias Agopian65ab4712010-07-14 17:59:35 -07008270 if (cmdCode != EFFECT_CMD_GET_PARAM && status == NO_ERROR) {
Eric Laurent25f43952010-07-28 05:40:18 -07008271 uint32_t size = (replySize == NULL) ? 0 : *replySize;
Mathias Agopian65ab4712010-07-14 17:59:35 -07008272 for (size_t i = 1; i < mHandles.size(); i++) {
8273 sp<EffectHandle> h = mHandles[i].promote();
8274 if (h != 0) {
8275 h->commandExecuted(cmdCode, cmdSize, pCmdData, size, pReplyData);
8276 }
8277 }
8278 }
8279 return status;
8280}
8281
8282status_t AudioFlinger::EffectModule::setEnabled(bool enabled)
8283{
Eric Laurentdb7c0792011-08-10 10:37:50 -07008284
Mathias Agopian65ab4712010-07-14 17:59:35 -07008285 Mutex::Autolock _l(mLock);
Steve Block3856b092011-10-20 11:56:00 +01008286 ALOGV("setEnabled %p enabled %d", this, enabled);
Mathias Agopian65ab4712010-07-14 17:59:35 -07008287
8288 if (enabled != isEnabled()) {
Eric Laurentdb7c0792011-08-10 10:37:50 -07008289 status_t status = AudioSystem::setEffectEnabled(mId, enabled);
8290 if (enabled && status != NO_ERROR) {
8291 return status;
8292 }
8293
Mathias Agopian65ab4712010-07-14 17:59:35 -07008294 switch (mState) {
8295 // going from disabled to enabled
8296 case IDLE:
8297 mState = STARTING;
8298 break;
8299 case STOPPED:
8300 mState = RESTART;
8301 break;
8302 case STOPPING:
8303 mState = ACTIVE;
8304 break;
8305
8306 // going from enabled to disabled
8307 case RESTART:
Eric Laurent8f45bd72010-08-31 13:50:07 -07008308 mState = STOPPED;
8309 break;
Mathias Agopian65ab4712010-07-14 17:59:35 -07008310 case STARTING:
8311 mState = IDLE;
8312 break;
8313 case ACTIVE:
8314 mState = STOPPING;
8315 break;
Eric Laurentec437d82011-07-26 20:54:46 -07008316 case DESTROYED:
8317 return NO_ERROR; // simply ignore as we are being destroyed
Mathias Agopian65ab4712010-07-14 17:59:35 -07008318 }
8319 for (size_t i = 1; i < mHandles.size(); i++) {
8320 sp<EffectHandle> h = mHandles[i].promote();
8321 if (h != 0) {
8322 h->setEnabled(enabled);
8323 }
8324 }
8325 }
8326 return NO_ERROR;
8327}
8328
Glenn Kastenc59c0042012-02-02 14:06:11 -08008329bool AudioFlinger::EffectModule::isEnabled() const
Mathias Agopian65ab4712010-07-14 17:59:35 -07008330{
8331 switch (mState) {
8332 case RESTART:
8333 case STARTING:
8334 case ACTIVE:
8335 return true;
8336 case IDLE:
8337 case STOPPING:
8338 case STOPPED:
Eric Laurentec437d82011-07-26 20:54:46 -07008339 case DESTROYED:
Mathias Agopian65ab4712010-07-14 17:59:35 -07008340 default:
8341 return false;
8342 }
8343}
8344
Glenn Kastenc59c0042012-02-02 14:06:11 -08008345bool AudioFlinger::EffectModule::isProcessEnabled() const
Eric Laurent8f45bd72010-08-31 13:50:07 -07008346{
8347 switch (mState) {
8348 case RESTART:
8349 case ACTIVE:
8350 case STOPPING:
8351 case STOPPED:
8352 return true;
8353 case IDLE:
8354 case STARTING:
Eric Laurentec437d82011-07-26 20:54:46 -07008355 case DESTROYED:
Eric Laurent8f45bd72010-08-31 13:50:07 -07008356 default:
8357 return false;
8358 }
8359}
8360
Mathias Agopian65ab4712010-07-14 17:59:35 -07008361status_t AudioFlinger::EffectModule::setVolume(uint32_t *left, uint32_t *right, bool controller)
8362{
8363 Mutex::Autolock _l(mLock);
8364 status_t status = NO_ERROR;
8365
8366 // Send volume indication if EFFECT_FLAG_VOLUME_IND is set and read back altered volume
8367 // if controller flag is set (Note that controller == TRUE => EFFECT_FLAG_VOLUME_CTRL set)
Eric Laurent8f45bd72010-08-31 13:50:07 -07008368 if (isProcessEnabled() &&
Eric Laurentf997cab2010-07-19 06:24:46 -07008369 ((mDescriptor.flags & EFFECT_FLAG_VOLUME_MASK) == EFFECT_FLAG_VOLUME_CTRL ||
8370 (mDescriptor.flags & EFFECT_FLAG_VOLUME_MASK) == EFFECT_FLAG_VOLUME_IND)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07008371 status_t cmdStatus;
8372 uint32_t volume[2];
8373 uint32_t *pVolume = NULL;
Eric Laurent25f43952010-07-28 05:40:18 -07008374 uint32_t size = sizeof(volume);
Mathias Agopian65ab4712010-07-14 17:59:35 -07008375 volume[0] = *left;
8376 volume[1] = *right;
8377 if (controller) {
8378 pVolume = volume;
8379 }
Eric Laurent25f43952010-07-28 05:40:18 -07008380 status = (*mEffectInterface)->command(mEffectInterface,
8381 EFFECT_CMD_SET_VOLUME,
8382 size,
8383 volume,
8384 &size,
8385 pVolume);
Mathias Agopian65ab4712010-07-14 17:59:35 -07008386 if (controller && status == NO_ERROR && size == sizeof(volume)) {
8387 *left = volume[0];
8388 *right = volume[1];
8389 }
8390 }
8391 return status;
8392}
8393
8394status_t AudioFlinger::EffectModule::setDevice(uint32_t device)
8395{
8396 Mutex::Autolock _l(mLock);
8397 status_t status = NO_ERROR;
Eric Laurent7c7f10b2011-06-17 21:29:58 -07008398 if (device && (mDescriptor.flags & EFFECT_FLAG_DEVICE_MASK) == EFFECT_FLAG_DEVICE_IND) {
8399 // audio pre processing modules on RecordThread can receive both output and
8400 // input device indication in the same call
8401 uint32_t dev = device & AUDIO_DEVICE_OUT_ALL;
8402 if (dev) {
8403 status_t cmdStatus;
8404 uint32_t size = sizeof(status_t);
8405
8406 status = (*mEffectInterface)->command(mEffectInterface,
8407 EFFECT_CMD_SET_DEVICE,
8408 sizeof(uint32_t),
8409 &dev,
8410 &size,
8411 &cmdStatus);
8412 if (status == NO_ERROR) {
8413 status = cmdStatus;
8414 }
8415 }
8416 dev = device & AUDIO_DEVICE_IN_ALL;
8417 if (dev) {
8418 status_t cmdStatus;
8419 uint32_t size = sizeof(status_t);
8420
8421 status_t status2 = (*mEffectInterface)->command(mEffectInterface,
8422 EFFECT_CMD_SET_INPUT_DEVICE,
8423 sizeof(uint32_t),
8424 &dev,
8425 &size,
8426 &cmdStatus);
8427 if (status2 == NO_ERROR) {
8428 status2 = cmdStatus;
8429 }
8430 if (status == NO_ERROR) {
8431 status = status2;
8432 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07008433 }
8434 }
8435 return status;
8436}
8437
Glenn Kastenf78aee72012-01-04 11:00:47 -08008438status_t AudioFlinger::EffectModule::setMode(audio_mode_t mode)
Mathias Agopian65ab4712010-07-14 17:59:35 -07008439{
8440 Mutex::Autolock _l(mLock);
8441 status_t status = NO_ERROR;
8442 if ((mDescriptor.flags & EFFECT_FLAG_AUDIO_MODE_MASK) == EFFECT_FLAG_AUDIO_MODE_IND) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07008443 status_t cmdStatus;
Eric Laurent25f43952010-07-28 05:40:18 -07008444 uint32_t size = sizeof(status_t);
8445 status = (*mEffectInterface)->command(mEffectInterface,
8446 EFFECT_CMD_SET_AUDIO_MODE,
Glenn Kastenf78aee72012-01-04 11:00:47 -08008447 sizeof(audio_mode_t),
Eric Laurente1315cf2011-05-17 19:16:02 -07008448 &mode,
Eric Laurent25f43952010-07-28 05:40:18 -07008449 &size,
8450 &cmdStatus);
Mathias Agopian65ab4712010-07-14 17:59:35 -07008451 if (status == NO_ERROR) {
8452 status = cmdStatus;
8453 }
8454 }
8455 return status;
8456}
8457
Eric Laurent59255e42011-07-27 19:49:51 -07008458void AudioFlinger::EffectModule::setSuspended(bool suspended)
8459{
8460 Mutex::Autolock _l(mLock);
8461 mSuspended = suspended;
8462}
Glenn Kastena3a85482012-01-04 11:01:11 -08008463
8464bool AudioFlinger::EffectModule::suspended() const
Eric Laurent59255e42011-07-27 19:49:51 -07008465{
8466 Mutex::Autolock _l(mLock);
8467 return mSuspended;
8468}
8469
Mathias Agopian65ab4712010-07-14 17:59:35 -07008470status_t AudioFlinger::EffectModule::dump(int fd, const Vector<String16>& args)
8471{
8472 const size_t SIZE = 256;
8473 char buffer[SIZE];
8474 String8 result;
8475
8476 snprintf(buffer, SIZE, "\tEffect ID %d:\n", mId);
8477 result.append(buffer);
8478
8479 bool locked = tryLock(mLock);
8480 // failed to lock - AudioFlinger is probably deadlocked
8481 if (!locked) {
8482 result.append("\t\tCould not lock Fx mutex:\n");
8483 }
8484
8485 result.append("\t\tSession Status State Engine:\n");
8486 snprintf(buffer, SIZE, "\t\t%05d %03d %03d 0x%08x\n",
8487 mSessionId, mStatus, mState, (uint32_t)mEffectInterface);
8488 result.append(buffer);
8489
8490 result.append("\t\tDescriptor:\n");
8491 snprintf(buffer, SIZE, "\t\t- UUID: %08X-%04X-%04X-%04X-%02X%02X%02X%02X%02X%02X\n",
8492 mDescriptor.uuid.timeLow, mDescriptor.uuid.timeMid, mDescriptor.uuid.timeHiAndVersion,
8493 mDescriptor.uuid.clockSeq, mDescriptor.uuid.node[0], mDescriptor.uuid.node[1],mDescriptor.uuid.node[2],
8494 mDescriptor.uuid.node[3],mDescriptor.uuid.node[4],mDescriptor.uuid.node[5]);
8495 result.append(buffer);
8496 snprintf(buffer, SIZE, "\t\t- TYPE: %08X-%04X-%04X-%04X-%02X%02X%02X%02X%02X%02X\n",
8497 mDescriptor.type.timeLow, mDescriptor.type.timeMid, mDescriptor.type.timeHiAndVersion,
8498 mDescriptor.type.clockSeq, mDescriptor.type.node[0], mDescriptor.type.node[1],mDescriptor.type.node[2],
8499 mDescriptor.type.node[3],mDescriptor.type.node[4],mDescriptor.type.node[5]);
8500 result.append(buffer);
Eric Laurente1315cf2011-05-17 19:16:02 -07008501 snprintf(buffer, SIZE, "\t\t- apiVersion: %08X\n\t\t- flags: %08X\n",
Mathias Agopian65ab4712010-07-14 17:59:35 -07008502 mDescriptor.apiVersion,
8503 mDescriptor.flags);
8504 result.append(buffer);
8505 snprintf(buffer, SIZE, "\t\t- name: %s\n",
8506 mDescriptor.name);
8507 result.append(buffer);
8508 snprintf(buffer, SIZE, "\t\t- implementor: %s\n",
8509 mDescriptor.implementor);
8510 result.append(buffer);
8511
8512 result.append("\t\t- Input configuration:\n");
8513 result.append("\t\t\tBuffer Frames Smp rate Channels Format\n");
8514 snprintf(buffer, SIZE, "\t\t\t0x%08x %05d %05d %08x %d\n",
8515 (uint32_t)mConfig.inputCfg.buffer.raw,
8516 mConfig.inputCfg.buffer.frameCount,
8517 mConfig.inputCfg.samplingRate,
8518 mConfig.inputCfg.channels,
8519 mConfig.inputCfg.format);
8520 result.append(buffer);
8521
8522 result.append("\t\t- Output configuration:\n");
8523 result.append("\t\t\tBuffer Frames Smp rate Channels Format\n");
8524 snprintf(buffer, SIZE, "\t\t\t0x%08x %05d %05d %08x %d\n",
8525 (uint32_t)mConfig.outputCfg.buffer.raw,
8526 mConfig.outputCfg.buffer.frameCount,
8527 mConfig.outputCfg.samplingRate,
8528 mConfig.outputCfg.channels,
8529 mConfig.outputCfg.format);
8530 result.append(buffer);
8531
8532 snprintf(buffer, SIZE, "\t\t%d Clients:\n", mHandles.size());
8533 result.append(buffer);
8534 result.append("\t\t\tPid Priority Ctrl Locked client server\n");
8535 for (size_t i = 0; i < mHandles.size(); ++i) {
8536 sp<EffectHandle> handle = mHandles[i].promote();
8537 if (handle != 0) {
8538 handle->dump(buffer, SIZE);
8539 result.append(buffer);
8540 }
8541 }
8542
8543 result.append("\n");
8544
8545 write(fd, result.string(), result.length());
8546
8547 if (locked) {
8548 mLock.unlock();
8549 }
8550
8551 return NO_ERROR;
8552}
8553
8554// ----------------------------------------------------------------------------
8555// EffectHandle implementation
8556// ----------------------------------------------------------------------------
8557
8558#undef LOG_TAG
8559#define LOG_TAG "AudioFlinger::EffectHandle"
8560
8561AudioFlinger::EffectHandle::EffectHandle(const sp<EffectModule>& effect,
8562 const sp<AudioFlinger::Client>& client,
8563 const sp<IEffectClient>& effectClient,
8564 int32_t priority)
8565 : BnEffect(),
Marco Nelissen3a34bef2011-08-02 13:33:41 -07008566 mEffect(effect), mEffectClient(effectClient), mClient(client), mCblk(NULL),
Eric Laurent59255e42011-07-27 19:49:51 -07008567 mPriority(priority), mHasControl(false), mEnabled(false)
Mathias Agopian65ab4712010-07-14 17:59:35 -07008568{
Steve Block3856b092011-10-20 11:56:00 +01008569 ALOGV("constructor %p", this);
Mathias Agopian65ab4712010-07-14 17:59:35 -07008570
Marco Nelissen3a34bef2011-08-02 13:33:41 -07008571 if (client == 0) {
8572 return;
8573 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07008574 int bufOffset = ((sizeof(effect_param_cblk_t) - 1) / sizeof(int) + 1) * sizeof(int);
8575 mCblkMemory = client->heap()->allocate(EFFECT_PARAM_BUFFER_SIZE + bufOffset);
8576 if (mCblkMemory != 0) {
8577 mCblk = static_cast<effect_param_cblk_t *>(mCblkMemory->pointer());
8578
Glenn Kastena0d68332012-01-27 16:47:15 -08008579 if (mCblk != NULL) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07008580 new(mCblk) effect_param_cblk_t();
8581 mBuffer = (uint8_t *)mCblk + bufOffset;
Glenn Kastene53b9ea2012-03-12 16:29:55 -07008582 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07008583 } else {
Steve Block29357bc2012-01-06 19:20:56 +00008584 ALOGE("not enough memory for Effect size=%u", EFFECT_PARAM_BUFFER_SIZE + sizeof(effect_param_cblk_t));
Mathias Agopian65ab4712010-07-14 17:59:35 -07008585 return;
8586 }
8587}
8588
8589AudioFlinger::EffectHandle::~EffectHandle()
8590{
Steve Block3856b092011-10-20 11:56:00 +01008591 ALOGV("Destructor %p", this);
Marco Nelissen3a34bef2011-08-02 13:33:41 -07008592 disconnect(false);
Steve Block3856b092011-10-20 11:56:00 +01008593 ALOGV("Destructor DONE %p", this);
Mathias Agopian65ab4712010-07-14 17:59:35 -07008594}
8595
8596status_t AudioFlinger::EffectHandle::enable()
8597{
Steve Block3856b092011-10-20 11:56:00 +01008598 ALOGV("enable %p", this);
Mathias Agopian65ab4712010-07-14 17:59:35 -07008599 if (!mHasControl) return INVALID_OPERATION;
8600 if (mEffect == 0) return DEAD_OBJECT;
8601
Eric Laurentdb7c0792011-08-10 10:37:50 -07008602 if (mEnabled) {
8603 return NO_ERROR;
8604 }
8605
Eric Laurent59255e42011-07-27 19:49:51 -07008606 mEnabled = true;
8607
8608 sp<ThreadBase> thread = mEffect->thread().promote();
8609 if (thread != 0) {
8610 thread->checkSuspendOnEffectEnabled(mEffect, true, mEffect->sessionId());
8611 }
8612
8613 // checkSuspendOnEffectEnabled() can suspend this same effect when enabled
8614 if (mEffect->suspended()) {
8615 return NO_ERROR;
8616 }
8617
Eric Laurentdb7c0792011-08-10 10:37:50 -07008618 status_t status = mEffect->setEnabled(true);
8619 if (status != NO_ERROR) {
8620 if (thread != 0) {
8621 thread->checkSuspendOnEffectEnabled(mEffect, false, mEffect->sessionId());
8622 }
8623 mEnabled = false;
8624 }
8625 return status;
Mathias Agopian65ab4712010-07-14 17:59:35 -07008626}
8627
8628status_t AudioFlinger::EffectHandle::disable()
8629{
Steve Block3856b092011-10-20 11:56:00 +01008630 ALOGV("disable %p", this);
Mathias Agopian65ab4712010-07-14 17:59:35 -07008631 if (!mHasControl) return INVALID_OPERATION;
Eric Laurent59255e42011-07-27 19:49:51 -07008632 if (mEffect == 0) return DEAD_OBJECT;
Mathias Agopian65ab4712010-07-14 17:59:35 -07008633
Eric Laurentdb7c0792011-08-10 10:37:50 -07008634 if (!mEnabled) {
8635 return NO_ERROR;
8636 }
Eric Laurent59255e42011-07-27 19:49:51 -07008637 mEnabled = false;
8638
8639 if (mEffect->suspended()) {
8640 return NO_ERROR;
8641 }
8642
8643 status_t status = mEffect->setEnabled(false);
8644
8645 sp<ThreadBase> thread = mEffect->thread().promote();
8646 if (thread != 0) {
8647 thread->checkSuspendOnEffectEnabled(mEffect, false, mEffect->sessionId());
8648 }
8649
8650 return status;
Mathias Agopian65ab4712010-07-14 17:59:35 -07008651}
8652
8653void AudioFlinger::EffectHandle::disconnect()
8654{
Marco Nelissen3a34bef2011-08-02 13:33:41 -07008655 disconnect(true);
8656}
8657
Glenn Kasten58123c32012-02-03 10:32:24 -08008658void AudioFlinger::EffectHandle::disconnect(bool unpinIfLast)
Marco Nelissen3a34bef2011-08-02 13:33:41 -07008659{
Glenn Kasten58123c32012-02-03 10:32:24 -08008660 ALOGV("disconnect(%s)", unpinIfLast ? "true" : "false");
Mathias Agopian65ab4712010-07-14 17:59:35 -07008661 if (mEffect == 0) {
8662 return;
8663 }
Glenn Kasten58123c32012-02-03 10:32:24 -08008664 mEffect->disconnect(this, unpinIfLast);
Eric Laurent59255e42011-07-27 19:49:51 -07008665
Eric Laurenta85a74a2011-10-19 11:44:54 -07008666 if (mHasControl && mEnabled) {
Eric Laurentdb7c0792011-08-10 10:37:50 -07008667 sp<ThreadBase> thread = mEffect->thread().promote();
8668 if (thread != 0) {
8669 thread->checkSuspendOnEffectEnabled(mEffect, false, mEffect->sessionId());
8670 }
Eric Laurent59255e42011-07-27 19:49:51 -07008671 }
8672
Mathias Agopian65ab4712010-07-14 17:59:35 -07008673 // release sp on module => module destructor can be called now
8674 mEffect.clear();
Mathias Agopian65ab4712010-07-14 17:59:35 -07008675 if (mClient != 0) {
Glenn Kastena0d68332012-01-27 16:47:15 -08008676 if (mCblk != NULL) {
Glenn Kasten1a0ae5b2012-02-03 10:24:48 -08008677 // unlike ~TrackBase(), mCblk is never a local new, so don't delete
Marco Nelissen3a34bef2011-08-02 13:33:41 -07008678 mCblk->~effect_param_cblk_t(); // destroy our shared-structure.
8679 }
Glenn Kastendbfafaf2012-01-25 15:27:15 -08008680 mCblkMemory.clear(); // free the shared memory before releasing the heap it belongs to
Glenn Kasten98ec94c2012-01-25 14:28:29 -08008681 // Client destructor must run with AudioFlinger mutex locked
Mathias Agopian65ab4712010-07-14 17:59:35 -07008682 Mutex::Autolock _l(mClient->audioFlinger()->mLock);
8683 mClient.clear();
8684 }
8685}
8686
Eric Laurent25f43952010-07-28 05:40:18 -07008687status_t AudioFlinger::EffectHandle::command(uint32_t cmdCode,
8688 uint32_t cmdSize,
8689 void *pCmdData,
8690 uint32_t *replySize,
8691 void *pReplyData)
Mathias Agopian65ab4712010-07-14 17:59:35 -07008692{
Steve Block3856b092011-10-20 11:56:00 +01008693// ALOGV("command(), cmdCode: %d, mHasControl: %d, mEffect: %p",
Eric Laurent25f43952010-07-28 05:40:18 -07008694// cmdCode, mHasControl, (mEffect == 0) ? 0 : mEffect.get());
Mathias Agopian65ab4712010-07-14 17:59:35 -07008695
8696 // only get parameter command is permitted for applications not controlling the effect
8697 if (!mHasControl && cmdCode != EFFECT_CMD_GET_PARAM) {
8698 return INVALID_OPERATION;
8699 }
8700 if (mEffect == 0) return DEAD_OBJECT;
Marco Nelissen3a34bef2011-08-02 13:33:41 -07008701 if (mClient == 0) return INVALID_OPERATION;
Mathias Agopian65ab4712010-07-14 17:59:35 -07008702
8703 // handle commands that are not forwarded transparently to effect engine
8704 if (cmdCode == EFFECT_CMD_SET_PARAM_COMMIT) {
8705 // No need to trylock() here as this function is executed in the binder thread serving a particular client process:
8706 // no risk to block the whole media server process or mixer threads is we are stuck here
8707 Mutex::Autolock _l(mCblk->lock);
8708 if (mCblk->clientIndex > EFFECT_PARAM_BUFFER_SIZE ||
8709 mCblk->serverIndex > EFFECT_PARAM_BUFFER_SIZE) {
8710 mCblk->serverIndex = 0;
8711 mCblk->clientIndex = 0;
8712 return BAD_VALUE;
8713 }
8714 status_t status = NO_ERROR;
8715 while (mCblk->serverIndex < mCblk->clientIndex) {
8716 int reply;
Eric Laurent25f43952010-07-28 05:40:18 -07008717 uint32_t rsize = sizeof(int);
Mathias Agopian65ab4712010-07-14 17:59:35 -07008718 int *p = (int *)(mBuffer + mCblk->serverIndex);
8719 int size = *p++;
8720 if (((uint8_t *)p + size) > mBuffer + mCblk->clientIndex) {
Steve Block5ff1dd52012-01-05 23:22:43 +00008721 ALOGW("command(): invalid parameter block size");
Mathias Agopian65ab4712010-07-14 17:59:35 -07008722 break;
8723 }
8724 effect_param_t *param = (effect_param_t *)p;
8725 if (param->psize == 0 || param->vsize == 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00008726 ALOGW("command(): null parameter or value size");
Mathias Agopian65ab4712010-07-14 17:59:35 -07008727 mCblk->serverIndex += size;
8728 continue;
8729 }
Eric Laurent25f43952010-07-28 05:40:18 -07008730 uint32_t psize = sizeof(effect_param_t) +
8731 ((param->psize - 1) / sizeof(int) + 1) * sizeof(int) +
8732 param->vsize;
8733 status_t ret = mEffect->command(EFFECT_CMD_SET_PARAM,
8734 psize,
8735 p,
8736 &rsize,
8737 &reply);
Eric Laurentaeae3de2010-09-02 11:56:55 -07008738 // stop at first error encountered
8739 if (ret != NO_ERROR) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07008740 status = ret;
Eric Laurentaeae3de2010-09-02 11:56:55 -07008741 *(int *)pReplyData = reply;
8742 break;
8743 } else if (reply != NO_ERROR) {
8744 *(int *)pReplyData = reply;
8745 break;
Mathias Agopian65ab4712010-07-14 17:59:35 -07008746 }
8747 mCblk->serverIndex += size;
8748 }
8749 mCblk->serverIndex = 0;
8750 mCblk->clientIndex = 0;
8751 return status;
8752 } else if (cmdCode == EFFECT_CMD_ENABLE) {
Eric Laurentaeae3de2010-09-02 11:56:55 -07008753 *(int *)pReplyData = NO_ERROR;
Mathias Agopian65ab4712010-07-14 17:59:35 -07008754 return enable();
8755 } else if (cmdCode == EFFECT_CMD_DISABLE) {
Eric Laurentaeae3de2010-09-02 11:56:55 -07008756 *(int *)pReplyData = NO_ERROR;
Mathias Agopian65ab4712010-07-14 17:59:35 -07008757 return disable();
8758 }
8759
8760 return mEffect->command(cmdCode, cmdSize, pCmdData, replySize, pReplyData);
8761}
8762
Eric Laurent59255e42011-07-27 19:49:51 -07008763void AudioFlinger::EffectHandle::setControl(bool hasControl, bool signal, bool enabled)
Mathias Agopian65ab4712010-07-14 17:59:35 -07008764{
Steve Block3856b092011-10-20 11:56:00 +01008765 ALOGV("setControl %p control %d", this, hasControl);
Mathias Agopian65ab4712010-07-14 17:59:35 -07008766
8767 mHasControl = hasControl;
Eric Laurent59255e42011-07-27 19:49:51 -07008768 mEnabled = enabled;
8769
Mathias Agopian65ab4712010-07-14 17:59:35 -07008770 if (signal && mEffectClient != 0) {
8771 mEffectClient->controlStatusChanged(hasControl);
8772 }
8773}
8774
Eric Laurent25f43952010-07-28 05:40:18 -07008775void AudioFlinger::EffectHandle::commandExecuted(uint32_t cmdCode,
8776 uint32_t cmdSize,
8777 void *pCmdData,
8778 uint32_t replySize,
8779 void *pReplyData)
Mathias Agopian65ab4712010-07-14 17:59:35 -07008780{
8781 if (mEffectClient != 0) {
8782 mEffectClient->commandExecuted(cmdCode, cmdSize, pCmdData, replySize, pReplyData);
8783 }
8784}
8785
8786
8787
8788void AudioFlinger::EffectHandle::setEnabled(bool enabled)
8789{
8790 if (mEffectClient != 0) {
8791 mEffectClient->enableStatusChanged(enabled);
8792 }
8793}
8794
8795status_t AudioFlinger::EffectHandle::onTransact(
8796 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
8797{
8798 return BnEffect::onTransact(code, data, reply, flags);
8799}
8800
8801
8802void AudioFlinger::EffectHandle::dump(char* buffer, size_t size)
8803{
Glenn Kastena0d68332012-01-27 16:47:15 -08008804 bool locked = mCblk != NULL && tryLock(mCblk->lock);
Mathias Agopian65ab4712010-07-14 17:59:35 -07008805
8806 snprintf(buffer, size, "\t\t\t%05d %05d %01u %01u %05u %05u\n",
Glenn Kasten44deb052012-02-05 18:09:08 -08008807 (mClient == 0) ? getpid_cached : mClient->pid(),
Mathias Agopian65ab4712010-07-14 17:59:35 -07008808 mPriority,
8809 mHasControl,
8810 !locked,
Marco Nelissen3a34bef2011-08-02 13:33:41 -07008811 mCblk ? mCblk->clientIndex : 0,
8812 mCblk ? mCblk->serverIndex : 0
Mathias Agopian65ab4712010-07-14 17:59:35 -07008813 );
8814
8815 if (locked) {
8816 mCblk->lock.unlock();
8817 }
8818}
8819
8820#undef LOG_TAG
8821#define LOG_TAG "AudioFlinger::EffectChain"
8822
Glenn Kasten9eaa5572012-01-20 13:32:16 -08008823AudioFlinger::EffectChain::EffectChain(ThreadBase *thread,
Mathias Agopian65ab4712010-07-14 17:59:35 -07008824 int sessionId)
Glenn Kasten9eaa5572012-01-20 13:32:16 -08008825 : mThread(thread), mSessionId(sessionId), mActiveTrackCnt(0), mTrackCnt(0), mTailBufferCount(0),
Eric Laurentb469b942011-05-09 12:09:06 -07008826 mOwnInBuffer(false), mVolumeCtrlIdx(-1), mLeftVolume(UINT_MAX), mRightVolume(UINT_MAX),
8827 mNewLeftVolume(UINT_MAX), mNewRightVolume(UINT_MAX)
Mathias Agopian65ab4712010-07-14 17:59:35 -07008828{
Dima Zavinfce7a472011-04-19 22:30:36 -07008829 mStrategy = AudioSystem::getStrategyForStream(AUDIO_STREAM_MUSIC);
Glenn Kasten9eaa5572012-01-20 13:32:16 -08008830 if (thread == NULL) {
Eric Laurent544fe9b2011-11-11 15:42:52 -08008831 return;
8832 }
8833 mMaxTailBuffers = ((kProcessTailDurationMs * thread->sampleRate()) / 1000) /
8834 thread->frameCount();
Mathias Agopian65ab4712010-07-14 17:59:35 -07008835}
8836
8837AudioFlinger::EffectChain::~EffectChain()
8838{
8839 if (mOwnInBuffer) {
8840 delete mInBuffer;
8841 }
8842
8843}
8844
Eric Laurent59255e42011-07-27 19:49:51 -07008845// getEffectFromDesc_l() must be called with ThreadBase::mLock held
Eric Laurentcab11242010-07-15 12:50:15 -07008846sp<AudioFlinger::EffectModule> AudioFlinger::EffectChain::getEffectFromDesc_l(effect_descriptor_t *descriptor)
Mathias Agopian65ab4712010-07-14 17:59:35 -07008847{
Mathias Agopian65ab4712010-07-14 17:59:35 -07008848 size_t size = mEffects.size();
8849
8850 for (size_t i = 0; i < size; i++) {
8851 if (memcmp(&mEffects[i]->desc().uuid, &descriptor->uuid, sizeof(effect_uuid_t)) == 0) {
Glenn Kasten090f0192012-01-30 13:00:02 -08008852 return mEffects[i];
Mathias Agopian65ab4712010-07-14 17:59:35 -07008853 }
8854 }
Glenn Kasten090f0192012-01-30 13:00:02 -08008855 return 0;
Mathias Agopian65ab4712010-07-14 17:59:35 -07008856}
8857
Eric Laurent59255e42011-07-27 19:49:51 -07008858// getEffectFromId_l() must be called with ThreadBase::mLock held
Eric Laurentcab11242010-07-15 12:50:15 -07008859sp<AudioFlinger::EffectModule> AudioFlinger::EffectChain::getEffectFromId_l(int id)
Mathias Agopian65ab4712010-07-14 17:59:35 -07008860{
Mathias Agopian65ab4712010-07-14 17:59:35 -07008861 size_t size = mEffects.size();
8862
8863 for (size_t i = 0; i < size; i++) {
Eric Laurentde070132010-07-13 04:45:46 -07008864 // by convention, return first effect if id provided is 0 (0 is never a valid id)
8865 if (id == 0 || mEffects[i]->id() == id) {
Glenn Kasten090f0192012-01-30 13:00:02 -08008866 return mEffects[i];
Mathias Agopian65ab4712010-07-14 17:59:35 -07008867 }
8868 }
Glenn Kasten090f0192012-01-30 13:00:02 -08008869 return 0;
Mathias Agopian65ab4712010-07-14 17:59:35 -07008870}
8871
Eric Laurent59255e42011-07-27 19:49:51 -07008872// getEffectFromType_l() must be called with ThreadBase::mLock held
8873sp<AudioFlinger::EffectModule> AudioFlinger::EffectChain::getEffectFromType_l(
8874 const effect_uuid_t *type)
8875{
Eric Laurent59255e42011-07-27 19:49:51 -07008876 size_t size = mEffects.size();
8877
8878 for (size_t i = 0; i < size; i++) {
8879 if (memcmp(&mEffects[i]->desc().type, type, sizeof(effect_uuid_t)) == 0) {
Glenn Kasten090f0192012-01-30 13:00:02 -08008880 return mEffects[i];
Eric Laurent59255e42011-07-27 19:49:51 -07008881 }
8882 }
Glenn Kasten090f0192012-01-30 13:00:02 -08008883 return 0;
Eric Laurent59255e42011-07-27 19:49:51 -07008884}
8885
Mathias Agopian65ab4712010-07-14 17:59:35 -07008886// Must be called with EffectChain::mLock locked
8887void AudioFlinger::EffectChain::process_l()
8888{
Eric Laurentdac69112010-09-28 14:09:57 -07008889 sp<ThreadBase> thread = mThread.promote();
8890 if (thread == 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00008891 ALOGW("process_l(): cannot promote mixer thread");
Eric Laurentdac69112010-09-28 14:09:57 -07008892 return;
8893 }
Dima Zavinfce7a472011-04-19 22:30:36 -07008894 bool isGlobalSession = (mSessionId == AUDIO_SESSION_OUTPUT_MIX) ||
8895 (mSessionId == AUDIO_SESSION_OUTPUT_STAGE);
Eric Laurent544fe9b2011-11-11 15:42:52 -08008896 // always process effects unless no more tracks are on the session and the effect tail
8897 // has been rendered
8898 bool doProcess = true;
Eric Laurentdac69112010-09-28 14:09:57 -07008899 if (!isGlobalSession) {
Eric Laurent544fe9b2011-11-11 15:42:52 -08008900 bool tracksOnSession = (trackCnt() != 0);
Eric Laurentb469b942011-05-09 12:09:06 -07008901
Eric Laurent544fe9b2011-11-11 15:42:52 -08008902 if (!tracksOnSession && mTailBufferCount == 0) {
8903 doProcess = false;
8904 }
8905
8906 if (activeTrackCnt() == 0) {
8907 // if no track is active and the effect tail has not been rendered,
8908 // the input buffer must be cleared here as the mixer process will not do it
8909 if (tracksOnSession || mTailBufferCount > 0) {
8910 size_t numSamples = thread->frameCount() * thread->channelCount();
8911 memset(mInBuffer, 0, numSamples * sizeof(int16_t));
8912 if (mTailBufferCount > 0) {
8913 mTailBufferCount--;
8914 }
8915 }
8916 }
Eric Laurentdac69112010-09-28 14:09:57 -07008917 }
8918
Mathias Agopian65ab4712010-07-14 17:59:35 -07008919 size_t size = mEffects.size();
Eric Laurent544fe9b2011-11-11 15:42:52 -08008920 if (doProcess) {
Eric Laurentdac69112010-09-28 14:09:57 -07008921 for (size_t i = 0; i < size; i++) {
8922 mEffects[i]->process();
8923 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07008924 }
8925 for (size_t i = 0; i < size; i++) {
8926 mEffects[i]->updateState();
8927 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07008928}
8929
Eric Laurentcab11242010-07-15 12:50:15 -07008930// addEffect_l() must be called with PlaybackThread::mLock held
Eric Laurentde070132010-07-13 04:45:46 -07008931status_t AudioFlinger::EffectChain::addEffect_l(const sp<EffectModule>& effect)
Mathias Agopian65ab4712010-07-14 17:59:35 -07008932{
8933 effect_descriptor_t desc = effect->desc();
8934 uint32_t insertPref = desc.flags & EFFECT_FLAG_INSERT_MASK;
8935
8936 Mutex::Autolock _l(mLock);
Eric Laurentde070132010-07-13 04:45:46 -07008937 effect->setChain(this);
8938 sp<ThreadBase> thread = mThread.promote();
8939 if (thread == 0) {
8940 return NO_INIT;
8941 }
8942 effect->setThread(thread);
Mathias Agopian65ab4712010-07-14 17:59:35 -07008943
8944 if ((desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
8945 // Auxiliary effects are inserted at the beginning of mEffects vector as
8946 // they are processed first and accumulated in chain input buffer
8947 mEffects.insertAt(effect, 0);
Eric Laurentde070132010-07-13 04:45:46 -07008948
Mathias Agopian65ab4712010-07-14 17:59:35 -07008949 // the input buffer for auxiliary effect contains mono samples in
8950 // 32 bit format. This is to avoid saturation in AudoMixer
8951 // accumulation stage. Saturation is done in EffectModule::process() before
8952 // calling the process in effect engine
8953 size_t numSamples = thread->frameCount();
8954 int32_t *buffer = new int32_t[numSamples];
8955 memset(buffer, 0, numSamples * sizeof(int32_t));
8956 effect->setInBuffer((int16_t *)buffer);
8957 // auxiliary effects output samples to chain input buffer for further processing
8958 // by insert effects
8959 effect->setOutBuffer(mInBuffer);
8960 } else {
8961 // Insert effects are inserted at the end of mEffects vector as they are processed
8962 // after track and auxiliary effects.
8963 // Insert effect order as a function of indicated preference:
8964 // if EFFECT_FLAG_INSERT_EXCLUSIVE, insert in first position or reject if
8965 // another effect is present
8966 // else if EFFECT_FLAG_INSERT_FIRST, insert in first position or after the
8967 // last effect claiming first position
8968 // else if EFFECT_FLAG_INSERT_LAST, insert in last position or before the
8969 // first effect claiming last position
8970 // else if EFFECT_FLAG_INSERT_ANY insert after first or before last
8971 // Reject insertion if an effect with EFFECT_FLAG_INSERT_EXCLUSIVE is
8972 // already present
8973
Glenn Kasten8d6a2442012-02-08 14:04:28 -08008974 size_t size = mEffects.size();
8975 size_t idx_insert = size;
8976 ssize_t idx_insert_first = -1;
8977 ssize_t idx_insert_last = -1;
Mathias Agopian65ab4712010-07-14 17:59:35 -07008978
Glenn Kasten8d6a2442012-02-08 14:04:28 -08008979 for (size_t i = 0; i < size; i++) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07008980 effect_descriptor_t d = mEffects[i]->desc();
8981 uint32_t iMode = d.flags & EFFECT_FLAG_TYPE_MASK;
8982 uint32_t iPref = d.flags & EFFECT_FLAG_INSERT_MASK;
8983 if (iMode == EFFECT_FLAG_TYPE_INSERT) {
8984 // check invalid effect chaining combinations
8985 if (insertPref == EFFECT_FLAG_INSERT_EXCLUSIVE ||
8986 iPref == EFFECT_FLAG_INSERT_EXCLUSIVE) {
Steve Block5ff1dd52012-01-05 23:22:43 +00008987 ALOGW("addEffect_l() could not insert effect %s: exclusive conflict with %s", desc.name, d.name);
Mathias Agopian65ab4712010-07-14 17:59:35 -07008988 return INVALID_OPERATION;
8989 }
8990 // remember position of first insert effect and by default
8991 // select this as insert position for new effect
8992 if (idx_insert == size) {
8993 idx_insert = i;
8994 }
8995 // remember position of last insert effect claiming
8996 // first position
8997 if (iPref == EFFECT_FLAG_INSERT_FIRST) {
8998 idx_insert_first = i;
8999 }
9000 // remember position of first insert effect claiming
9001 // last position
9002 if (iPref == EFFECT_FLAG_INSERT_LAST &&
9003 idx_insert_last == -1) {
9004 idx_insert_last = i;
9005 }
9006 }
9007 }
9008
9009 // modify idx_insert from first position if needed
9010 if (insertPref == EFFECT_FLAG_INSERT_LAST) {
9011 if (idx_insert_last != -1) {
9012 idx_insert = idx_insert_last;
9013 } else {
9014 idx_insert = size;
9015 }
9016 } else {
9017 if (idx_insert_first != -1) {
9018 idx_insert = idx_insert_first + 1;
9019 }
9020 }
9021
9022 // always read samples from chain input buffer
9023 effect->setInBuffer(mInBuffer);
9024
9025 // if last effect in the chain, output samples to chain
9026 // output buffer, otherwise to chain input buffer
9027 if (idx_insert == size) {
9028 if (idx_insert != 0) {
9029 mEffects[idx_insert-1]->setOutBuffer(mInBuffer);
9030 mEffects[idx_insert-1]->configure();
9031 }
9032 effect->setOutBuffer(mOutBuffer);
9033 } else {
9034 effect->setOutBuffer(mInBuffer);
9035 }
9036 mEffects.insertAt(effect, idx_insert);
Mathias Agopian65ab4712010-07-14 17:59:35 -07009037
Steve Block3856b092011-10-20 11:56:00 +01009038 ALOGV("addEffect_l() effect %p, added in chain %p at rank %d", effect.get(), this, idx_insert);
Mathias Agopian65ab4712010-07-14 17:59:35 -07009039 }
9040 effect->configure();
9041 return NO_ERROR;
9042}
9043
Eric Laurentcab11242010-07-15 12:50:15 -07009044// removeEffect_l() must be called with PlaybackThread::mLock held
9045size_t AudioFlinger::EffectChain::removeEffect_l(const sp<EffectModule>& effect)
Mathias Agopian65ab4712010-07-14 17:59:35 -07009046{
9047 Mutex::Autolock _l(mLock);
Glenn Kasten8d6a2442012-02-08 14:04:28 -08009048 size_t size = mEffects.size();
Mathias Agopian65ab4712010-07-14 17:59:35 -07009049 uint32_t type = effect->desc().flags & EFFECT_FLAG_TYPE_MASK;
9050
Glenn Kasten8d6a2442012-02-08 14:04:28 -08009051 for (size_t i = 0; i < size; i++) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07009052 if (effect == mEffects[i]) {
Eric Laurentec437d82011-07-26 20:54:46 -07009053 // calling stop here will remove pre-processing effect from the audio HAL.
9054 // This is safe as we hold the EffectChain mutex which guarantees that we are not in
9055 // the middle of a read from audio HAL
Eric Laurentec35a142011-10-05 17:42:25 -07009056 if (mEffects[i]->state() == EffectModule::ACTIVE ||
9057 mEffects[i]->state() == EffectModule::STOPPING) {
9058 mEffects[i]->stop();
9059 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07009060 if (type == EFFECT_FLAG_TYPE_AUXILIARY) {
9061 delete[] effect->inBuffer();
9062 } else {
9063 if (i == size - 1 && i != 0) {
9064 mEffects[i - 1]->setOutBuffer(mOutBuffer);
9065 mEffects[i - 1]->configure();
9066 }
9067 }
9068 mEffects.removeAt(i);
Steve Block3856b092011-10-20 11:56:00 +01009069 ALOGV("removeEffect_l() effect %p, removed from chain %p at rank %d", effect.get(), this, i);
Mathias Agopian65ab4712010-07-14 17:59:35 -07009070 break;
9071 }
9072 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07009073
9074 return mEffects.size();
9075}
9076
Eric Laurentcab11242010-07-15 12:50:15 -07009077// setDevice_l() must be called with PlaybackThread::mLock held
9078void AudioFlinger::EffectChain::setDevice_l(uint32_t device)
Mathias Agopian65ab4712010-07-14 17:59:35 -07009079{
9080 size_t size = mEffects.size();
9081 for (size_t i = 0; i < size; i++) {
9082 mEffects[i]->setDevice(device);
9083 }
9084}
9085
Eric Laurentcab11242010-07-15 12:50:15 -07009086// setMode_l() must be called with PlaybackThread::mLock held
Glenn Kastenf78aee72012-01-04 11:00:47 -08009087void AudioFlinger::EffectChain::setMode_l(audio_mode_t mode)
Mathias Agopian65ab4712010-07-14 17:59:35 -07009088{
9089 size_t size = mEffects.size();
9090 for (size_t i = 0; i < size; i++) {
9091 mEffects[i]->setMode(mode);
9092 }
9093}
9094
Eric Laurentcab11242010-07-15 12:50:15 -07009095// setVolume_l() must be called with PlaybackThread::mLock held
9096bool AudioFlinger::EffectChain::setVolume_l(uint32_t *left, uint32_t *right)
Mathias Agopian65ab4712010-07-14 17:59:35 -07009097{
9098 uint32_t newLeft = *left;
9099 uint32_t newRight = *right;
9100 bool hasControl = false;
Eric Laurentcab11242010-07-15 12:50:15 -07009101 int ctrlIdx = -1;
9102 size_t size = mEffects.size();
Mathias Agopian65ab4712010-07-14 17:59:35 -07009103
Eric Laurentcab11242010-07-15 12:50:15 -07009104 // first update volume controller
9105 for (size_t i = size; i > 0; i--) {
Eric Laurent8f45bd72010-08-31 13:50:07 -07009106 if (mEffects[i - 1]->isProcessEnabled() &&
Eric Laurentcab11242010-07-15 12:50:15 -07009107 (mEffects[i - 1]->desc().flags & EFFECT_FLAG_VOLUME_MASK) == EFFECT_FLAG_VOLUME_CTRL) {
9108 ctrlIdx = i - 1;
Eric Laurentf997cab2010-07-19 06:24:46 -07009109 hasControl = true;
Eric Laurentcab11242010-07-15 12:50:15 -07009110 break;
9111 }
9112 }
9113
9114 if (ctrlIdx == mVolumeCtrlIdx && *left == mLeftVolume && *right == mRightVolume) {
Eric Laurentf997cab2010-07-19 06:24:46 -07009115 if (hasControl) {
9116 *left = mNewLeftVolume;
9117 *right = mNewRightVolume;
9118 }
9119 return hasControl;
Eric Laurentcab11242010-07-15 12:50:15 -07009120 }
9121
9122 mVolumeCtrlIdx = ctrlIdx;
Eric Laurentf997cab2010-07-19 06:24:46 -07009123 mLeftVolume = newLeft;
9124 mRightVolume = newRight;
Eric Laurentcab11242010-07-15 12:50:15 -07009125
9126 // second get volume update from volume controller
9127 if (ctrlIdx >= 0) {
9128 mEffects[ctrlIdx]->setVolume(&newLeft, &newRight, true);
Eric Laurentf997cab2010-07-19 06:24:46 -07009129 mNewLeftVolume = newLeft;
9130 mNewRightVolume = newRight;
Mathias Agopian65ab4712010-07-14 17:59:35 -07009131 }
9132 // then indicate volume to all other effects in chain.
9133 // Pass altered volume to effects before volume controller
9134 // and requested volume to effects after controller
9135 uint32_t lVol = newLeft;
9136 uint32_t rVol = newRight;
Eric Laurentcab11242010-07-15 12:50:15 -07009137
Mathias Agopian65ab4712010-07-14 17:59:35 -07009138 for (size_t i = 0; i < size; i++) {
Eric Laurentcab11242010-07-15 12:50:15 -07009139 if ((int)i == ctrlIdx) continue;
9140 // this also works for ctrlIdx == -1 when there is no volume controller
9141 if ((int)i > ctrlIdx) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07009142 lVol = *left;
9143 rVol = *right;
9144 }
9145 mEffects[i]->setVolume(&lVol, &rVol, false);
9146 }
9147 *left = newLeft;
9148 *right = newRight;
9149
9150 return hasControl;
9151}
9152
Mathias Agopian65ab4712010-07-14 17:59:35 -07009153status_t AudioFlinger::EffectChain::dump(int fd, const Vector<String16>& args)
9154{
9155 const size_t SIZE = 256;
9156 char buffer[SIZE];
9157 String8 result;
9158
9159 snprintf(buffer, SIZE, "Effects for session %d:\n", mSessionId);
9160 result.append(buffer);
9161
9162 bool locked = tryLock(mLock);
9163 // failed to lock - AudioFlinger is probably deadlocked
9164 if (!locked) {
9165 result.append("\tCould not lock mutex:\n");
9166 }
9167
Eric Laurentcab11242010-07-15 12:50:15 -07009168 result.append("\tNum fx In buffer Out buffer Active tracks:\n");
9169 snprintf(buffer, SIZE, "\t%02d 0x%08x 0x%08x %d\n",
Mathias Agopian65ab4712010-07-14 17:59:35 -07009170 mEffects.size(),
9171 (uint32_t)mInBuffer,
9172 (uint32_t)mOutBuffer,
Mathias Agopian65ab4712010-07-14 17:59:35 -07009173 mActiveTrackCnt);
9174 result.append(buffer);
9175 write(fd, result.string(), result.size());
9176
9177 for (size_t i = 0; i < mEffects.size(); ++i) {
9178 sp<EffectModule> effect = mEffects[i];
9179 if (effect != 0) {
9180 effect->dump(fd, args);
9181 }
9182 }
9183
9184 if (locked) {
9185 mLock.unlock();
9186 }
9187
9188 return NO_ERROR;
9189}
9190
Eric Laurent59255e42011-07-27 19:49:51 -07009191// must be called with ThreadBase::mLock held
9192void AudioFlinger::EffectChain::setEffectSuspended_l(
9193 const effect_uuid_t *type, bool suspend)
9194{
9195 sp<SuspendedEffectDesc> desc;
9196 // use effect type UUID timelow as key as there is no real risk of identical
9197 // timeLow fields among effect type UUIDs.
Glenn Kasten8d6a2442012-02-08 14:04:28 -08009198 ssize_t index = mSuspendedEffects.indexOfKey(type->timeLow);
Eric Laurent59255e42011-07-27 19:49:51 -07009199 if (suspend) {
9200 if (index >= 0) {
9201 desc = mSuspendedEffects.valueAt(index);
9202 } else {
9203 desc = new SuspendedEffectDesc();
9204 memcpy(&desc->mType, type, sizeof(effect_uuid_t));
9205 mSuspendedEffects.add(type->timeLow, desc);
Steve Block3856b092011-10-20 11:56:00 +01009206 ALOGV("setEffectSuspended_l() add entry for %08x", type->timeLow);
Eric Laurent59255e42011-07-27 19:49:51 -07009207 }
9208 if (desc->mRefCount++ == 0) {
9209 sp<EffectModule> effect = getEffectIfEnabled(type);
9210 if (effect != 0) {
9211 desc->mEffect = effect;
9212 effect->setSuspended(true);
9213 effect->setEnabled(false);
9214 }
9215 }
9216 } else {
9217 if (index < 0) {
9218 return;
9219 }
9220 desc = mSuspendedEffects.valueAt(index);
9221 if (desc->mRefCount <= 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00009222 ALOGW("setEffectSuspended_l() restore refcount should not be 0 %d", desc->mRefCount);
Eric Laurent59255e42011-07-27 19:49:51 -07009223 desc->mRefCount = 1;
9224 }
9225 if (--desc->mRefCount == 0) {
Steve Block3856b092011-10-20 11:56:00 +01009226 ALOGV("setEffectSuspended_l() remove entry for %08x", mSuspendedEffects.keyAt(index));
Eric Laurent59255e42011-07-27 19:49:51 -07009227 if (desc->mEffect != 0) {
9228 sp<EffectModule> effect = desc->mEffect.promote();
9229 if (effect != 0) {
9230 effect->setSuspended(false);
9231 sp<EffectHandle> handle = effect->controlHandle();
9232 if (handle != 0) {
9233 effect->setEnabled(handle->enabled());
9234 }
9235 }
9236 desc->mEffect.clear();
9237 }
9238 mSuspendedEffects.removeItemsAt(index);
9239 }
9240 }
9241}
9242
9243// must be called with ThreadBase::mLock held
9244void AudioFlinger::EffectChain::setEffectSuspendedAll_l(bool suspend)
9245{
9246 sp<SuspendedEffectDesc> desc;
9247
Glenn Kasten8d6a2442012-02-08 14:04:28 -08009248 ssize_t index = mSuspendedEffects.indexOfKey((int)kKeyForSuspendAll);
Eric Laurent59255e42011-07-27 19:49:51 -07009249 if (suspend) {
9250 if (index >= 0) {
9251 desc = mSuspendedEffects.valueAt(index);
9252 } else {
9253 desc = new SuspendedEffectDesc();
9254 mSuspendedEffects.add((int)kKeyForSuspendAll, desc);
Steve Block3856b092011-10-20 11:56:00 +01009255 ALOGV("setEffectSuspendedAll_l() add entry for 0");
Eric Laurent59255e42011-07-27 19:49:51 -07009256 }
9257 if (desc->mRefCount++ == 0) {
Glenn Kastend0539712012-01-30 12:56:03 -08009258 Vector< sp<EffectModule> > effects;
9259 getSuspendEligibleEffects(effects);
Eric Laurent59255e42011-07-27 19:49:51 -07009260 for (size_t i = 0; i < effects.size(); i++) {
9261 setEffectSuspended_l(&effects[i]->desc().type, true);
9262 }
9263 }
9264 } else {
9265 if (index < 0) {
9266 return;
9267 }
9268 desc = mSuspendedEffects.valueAt(index);
9269 if (desc->mRefCount <= 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00009270 ALOGW("setEffectSuspendedAll_l() restore refcount should not be 0 %d", desc->mRefCount);
Eric Laurent59255e42011-07-27 19:49:51 -07009271 desc->mRefCount = 1;
9272 }
9273 if (--desc->mRefCount == 0) {
9274 Vector<const effect_uuid_t *> types;
9275 for (size_t i = 0; i < mSuspendedEffects.size(); i++) {
9276 if (mSuspendedEffects.keyAt(i) == (int)kKeyForSuspendAll) {
9277 continue;
9278 }
9279 types.add(&mSuspendedEffects.valueAt(i)->mType);
9280 }
9281 for (size_t i = 0; i < types.size(); i++) {
9282 setEffectSuspended_l(types[i], false);
9283 }
Steve Block3856b092011-10-20 11:56:00 +01009284 ALOGV("setEffectSuspendedAll_l() remove entry for %08x", mSuspendedEffects.keyAt(index));
Eric Laurent59255e42011-07-27 19:49:51 -07009285 mSuspendedEffects.removeItem((int)kKeyForSuspendAll);
9286 }
9287 }
9288}
9289
Eric Laurent6bffdb82011-09-23 08:40:41 -07009290
9291// The volume effect is used for automated tests only
9292#ifndef OPENSL_ES_H_
9293static const effect_uuid_t SL_IID_VOLUME_ = { 0x09e8ede0, 0xddde, 0x11db, 0xb4f6,
9294 { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } };
9295const effect_uuid_t * const SL_IID_VOLUME = &SL_IID_VOLUME_;
9296#endif //OPENSL_ES_H_
9297
Eric Laurentdb7c0792011-08-10 10:37:50 -07009298bool AudioFlinger::EffectChain::isEffectEligibleForSuspend(const effect_descriptor_t& desc)
9299{
9300 // auxiliary effects and visualizer are never suspended on output mix
9301 if ((mSessionId == AUDIO_SESSION_OUTPUT_MIX) &&
9302 (((desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) ||
Eric Laurent6bffdb82011-09-23 08:40:41 -07009303 (memcmp(&desc.type, SL_IID_VISUALIZATION, sizeof(effect_uuid_t)) == 0) ||
9304 (memcmp(&desc.type, SL_IID_VOLUME, sizeof(effect_uuid_t)) == 0))) {
Eric Laurentdb7c0792011-08-10 10:37:50 -07009305 return false;
9306 }
9307 return true;
9308}
9309
Glenn Kastend0539712012-01-30 12:56:03 -08009310void AudioFlinger::EffectChain::getSuspendEligibleEffects(Vector< sp<AudioFlinger::EffectModule> > &effects)
Eric Laurent59255e42011-07-27 19:49:51 -07009311{
Glenn Kastend0539712012-01-30 12:56:03 -08009312 effects.clear();
Eric Laurent59255e42011-07-27 19:49:51 -07009313 for (size_t i = 0; i < mEffects.size(); i++) {
Glenn Kastend0539712012-01-30 12:56:03 -08009314 if (isEffectEligibleForSuspend(mEffects[i]->desc())) {
9315 effects.add(mEffects[i]);
Eric Laurent59255e42011-07-27 19:49:51 -07009316 }
Eric Laurent59255e42011-07-27 19:49:51 -07009317 }
Eric Laurent59255e42011-07-27 19:49:51 -07009318}
9319
9320sp<AudioFlinger::EffectModule> AudioFlinger::EffectChain::getEffectIfEnabled(
9321 const effect_uuid_t *type)
9322{
Glenn Kasten090f0192012-01-30 13:00:02 -08009323 sp<EffectModule> effect = getEffectFromType_l(type);
9324 return effect != 0 && effect->isEnabled() ? effect : 0;
Eric Laurent59255e42011-07-27 19:49:51 -07009325}
9326
9327void AudioFlinger::EffectChain::checkSuspendOnEffectEnabled(const sp<EffectModule>& effect,
9328 bool enabled)
9329{
Glenn Kasten8d6a2442012-02-08 14:04:28 -08009330 ssize_t index = mSuspendedEffects.indexOfKey(effect->desc().type.timeLow);
Eric Laurent59255e42011-07-27 19:49:51 -07009331 if (enabled) {
9332 if (index < 0) {
9333 // if the effect is not suspend check if all effects are suspended
9334 index = mSuspendedEffects.indexOfKey((int)kKeyForSuspendAll);
9335 if (index < 0) {
9336 return;
9337 }
Eric Laurentdb7c0792011-08-10 10:37:50 -07009338 if (!isEffectEligibleForSuspend(effect->desc())) {
9339 return;
9340 }
Eric Laurent59255e42011-07-27 19:49:51 -07009341 setEffectSuspended_l(&effect->desc().type, enabled);
9342 index = mSuspendedEffects.indexOfKey(effect->desc().type.timeLow);
Eric Laurentdb7c0792011-08-10 10:37:50 -07009343 if (index < 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00009344 ALOGW("checkSuspendOnEffectEnabled() Fx should be suspended here!");
Eric Laurentdb7c0792011-08-10 10:37:50 -07009345 return;
9346 }
Eric Laurent59255e42011-07-27 19:49:51 -07009347 }
Steve Block3856b092011-10-20 11:56:00 +01009348 ALOGV("checkSuspendOnEffectEnabled() enable suspending fx %08x",
Glenn Kastene53b9ea2012-03-12 16:29:55 -07009349 effect->desc().type.timeLow);
Eric Laurent59255e42011-07-27 19:49:51 -07009350 sp<SuspendedEffectDesc> desc = mSuspendedEffects.valueAt(index);
9351 // if effect is requested to suspended but was not yet enabled, supend it now.
9352 if (desc->mEffect == 0) {
9353 desc->mEffect = effect;
9354 effect->setEnabled(false);
9355 effect->setSuspended(true);
9356 }
9357 } else {
9358 if (index < 0) {
9359 return;
9360 }
Steve Block3856b092011-10-20 11:56:00 +01009361 ALOGV("checkSuspendOnEffectEnabled() disable restoring fx %08x",
Glenn Kastene53b9ea2012-03-12 16:29:55 -07009362 effect->desc().type.timeLow);
Eric Laurent59255e42011-07-27 19:49:51 -07009363 sp<SuspendedEffectDesc> desc = mSuspendedEffects.valueAt(index);
9364 desc->mEffect.clear();
9365 effect->setSuspended(false);
9366 }
9367}
9368
Mathias Agopian65ab4712010-07-14 17:59:35 -07009369#undef LOG_TAG
9370#define LOG_TAG "AudioFlinger"
9371
9372// ----------------------------------------------------------------------------
9373
9374status_t AudioFlinger::onTransact(
9375 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
9376{
9377 return BnAudioFlinger::onTransact(code, data, reply, flags);
9378}
9379
Mathias Agopian65ab4712010-07-14 17:59:35 -07009380}; // namespace android