blob: 878df2d3e815f0a5b2bb2c5ad73a49dceee2d500 [file] [log] [blame]
Mathias Agopian65ab4712010-07-14 17:59:35 -07001/* //device/include/server/AudioFlinger/AudioFlinger.cpp
2**
3** Copyright 2007, The Android Open Source Project
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9** http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
18
19#define LOG_TAG "AudioFlinger"
20//#define LOG_NDEBUG 0
21
22#include <math.h>
23#include <signal.h>
24#include <sys/time.h>
25#include <sys/resource.h>
26
Gloria Wang9ee159b2011-02-24 14:51:45 -080027#include <binder/IPCThreadState.h>
Mathias Agopian65ab4712010-07-14 17:59:35 -070028#include <binder/IServiceManager.h>
29#include <utils/Log.h>
30#include <binder/Parcel.h>
31#include <binder/IPCThreadState.h>
32#include <utils/String16.h>
33#include <utils/threads.h>
Eric Laurent38ccae22011-03-28 18:37:07 -070034#include <utils/Atomic.h>
Mathias Agopian65ab4712010-07-14 17:59:35 -070035
Dima Zavinfce7a472011-04-19 22:30:36 -070036#include <cutils/bitops.h>
Mathias Agopian65ab4712010-07-14 17:59:35 -070037#include <cutils/properties.h>
Glenn Kastenf6b16782011-12-15 09:51:17 -080038#include <cutils/compiler.h>
Mathias Agopian65ab4712010-07-14 17:59:35 -070039
Gloria Wang9ee159b2011-02-24 14:51:45 -080040#include <media/IMediaPlayerService.h>
Glenn Kasten25b248e2012-01-03 15:28:29 -080041#include <media/IMediaDeathNotifier.h>
Mathias Agopian65ab4712010-07-14 17:59:35 -070042
43#include <private/media/AudioTrackShared.h>
44#include <private/media/AudioEffectShared.h>
Dima Zavinfce7a472011-04-19 22:30:36 -070045
Dima Zavin64760242011-05-11 14:15:23 -070046#include <system/audio.h>
Dima Zavin7394a4f2011-06-13 18:16:26 -070047#include <hardware/audio.h>
Mathias Agopian65ab4712010-07-14 17:59:35 -070048
49#include "AudioMixer.h"
50#include "AudioFlinger.h"
Glenn Kasten44deb052012-02-05 18:09:08 -080051#include "ServiceUtilities.h"
Mathias Agopian65ab4712010-07-14 17:59:35 -070052
Mathias Agopian65ab4712010-07-14 17:59:35 -070053#include <media/EffectsFactoryApi.h>
Eric Laurent6d8b6942011-06-24 07:01:31 -070054#include <audio_effects/effect_visualizer.h>
Eric Laurent59bd0da2011-08-01 09:52:20 -070055#include <audio_effects/effect_ns.h>
56#include <audio_effects/effect_aec.h>
Mathias Agopian65ab4712010-07-14 17:59:35 -070057
Glenn Kasten3b21c502011-12-15 09:52:39 -080058#include <audio_utils/primitives.h>
59
Glenn Kasten4d8d0c32011-07-08 15:26:12 -070060#include <cpustats/ThreadCpuUsage.h>
Eric Laurentfeb0db62011-07-22 09:04:31 -070061#include <powermanager/PowerManager.h>
Glenn Kasten4d8d0c32011-07-08 15:26:12 -070062// #define DEBUG_CPU_USAGE 10 // log statistics every n wall clock seconds
63
Mathias Agopian65ab4712010-07-14 17:59:35 -070064// ----------------------------------------------------------------------------
Mathias Agopian65ab4712010-07-14 17:59:35 -070065
Eric Laurentde070132010-07-13 04:45:46 -070066
Mathias Agopian65ab4712010-07-14 17:59:35 -070067namespace android {
68
Glenn Kastenec1d6b52011-12-12 09:04:45 -080069static const char kDeadlockedString[] = "AudioFlinger may be deadlocked\n";
70static const char kHardwareLockedString[] = "Hardware lock is taken\n";
Mathias Agopian65ab4712010-07-14 17:59:35 -070071
72//static const nsecs_t kStandbyTimeInNsecs = seconds(3);
73static const float MAX_GAIN = 4096.0f;
Glenn Kastenb1cf75c2012-01-17 12:20:54 -080074static const uint32_t MAX_GAIN_INT = 0x1000;
Mathias Agopian65ab4712010-07-14 17:59:35 -070075
76// retry counts for buffer fill timeout
77// 50 * ~20msecs = 1 second
78static const int8_t kMaxTrackRetries = 50;
79static const int8_t kMaxTrackStartupRetries = 50;
80// allow less retry attempts on direct output thread.
81// direct outputs can be a scarce resource in audio hardware and should
82// be released as quickly as possible.
83static const int8_t kMaxTrackRetriesDirect = 2;
84
85static const int kDumpLockRetries = 50;
Glenn Kasten7dede872011-12-13 11:04:14 -080086static const int kDumpLockSleepUs = 20000;
Mathias Agopian65ab4712010-07-14 17:59:35 -070087
Glenn Kasten7dede872011-12-13 11:04:14 -080088// don't warn about blocked writes or record buffer overflows more often than this
89static const nsecs_t kWarningThrottleNs = seconds(5);
Mathias Agopian65ab4712010-07-14 17:59:35 -070090
Eric Laurent7c7f10b2011-06-17 21:29:58 -070091// RecordThread loop sleep time upon application overrun or audio HAL read error
92static const int kRecordThreadSleepUs = 5000;
Mathias Agopian65ab4712010-07-14 17:59:35 -070093
Glenn Kasten7dede872011-12-13 11:04:14 -080094// maximum time to wait for setParameters to complete
95static const nsecs_t kSetParametersTimeoutNs = seconds(2);
Eric Laurent60cd0a02011-09-13 11:40:21 -070096
Eric Laurent7cafbb32011-11-22 18:50:29 -080097// minimum sleep time for the mixer thread loop when tracks are active but in underrun
98static const uint32_t kMinThreadSleepTimeUs = 5000;
99// maximum divider applied to the active sleep time in the mixer thread loop
100static const uint32_t kMaxThreadSleepTimeShift = 2;
101
102
Mathias Agopian65ab4712010-07-14 17:59:35 -0700103// ----------------------------------------------------------------------------
104
Gloria Wang9ee159b2011-02-24 14:51:45 -0800105// To collect the amplifier usage
106static void addBatteryData(uint32_t params) {
Glenn Kasten25b248e2012-01-03 15:28:29 -0800107 sp<IMediaPlayerService> service = IMediaDeathNotifier::getMediaPlayerService();
108 if (service == NULL) {
109 // it already logged
Gloria Wang9ee159b2011-02-24 14:51:45 -0800110 return;
111 }
112
113 service->addBatteryData(params);
114}
115
Dima Zavin799a70e2011-04-18 16:57:27 -0700116static int load_audio_interface(const char *if_name, const hw_module_t **mod,
117 audio_hw_device_t **dev)
118{
119 int rc;
120
121 rc = hw_get_module_by_class(AUDIO_HARDWARE_MODULE_ID, if_name, mod);
122 if (rc)
123 goto out;
124
125 rc = audio_hw_device_open(*mod, dev);
Steve Block29357bc2012-01-06 19:20:56 +0000126 ALOGE_IF(rc, "couldn't open audio hw device in %s.%s (%s)",
Dima Zavin799a70e2011-04-18 16:57:27 -0700127 AUDIO_HARDWARE_MODULE_ID, if_name, strerror(-rc));
128 if (rc)
129 goto out;
130
131 return 0;
132
133out:
134 *mod = NULL;
135 *dev = NULL;
136 return rc;
137}
138
Glenn Kastenec1d6b52011-12-12 09:04:45 -0800139static const char * const audio_interfaces[] = {
Dima Zavin799a70e2011-04-18 16:57:27 -0700140 "primary",
141 "a2dp",
142 "usb",
143};
144#define ARRAY_SIZE(x) (sizeof((x))/sizeof(((x)[0])))
145
Mathias Agopian65ab4712010-07-14 17:59:35 -0700146// ----------------------------------------------------------------------------
147
148AudioFlinger::AudioFlinger()
149 : BnAudioFlinger(),
Glenn Kasten84afa3b2012-01-25 15:28:08 -0800150 mPrimaryHardwareDev(NULL),
151 mHardwareStatus(AUDIO_HW_IDLE), // see also onFirstRef()
152 mMasterVolume(1.0f), mMasterMute(false), mNextUniqueId(1),
153 mMode(AUDIO_MODE_INVALID),
Eric Laurentbee53372011-08-29 12:42:48 -0700154 mBtNrecIsOff(false)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700155{
Dima Zavin5a61d2f2011-04-19 19:04:32 -0700156}
157
158void AudioFlinger::onFirstRef()
159{
Dima Zavin799a70e2011-04-18 16:57:27 -0700160 int rc = 0;
Dima Zavinfce7a472011-04-19 22:30:36 -0700161
Eric Laurent93575202011-01-18 18:39:02 -0800162 Mutex::Autolock _l(mLock);
163
Dima Zavin799a70e2011-04-18 16:57:27 -0700164 /* TODO: move all this work into an Init() function */
Mathias Agopian65ab4712010-07-14 17:59:35 -0700165
Dima Zavin799a70e2011-04-18 16:57:27 -0700166 for (size_t i = 0; i < ARRAY_SIZE(audio_interfaces); i++) {
167 const hw_module_t *mod;
168 audio_hw_device_t *dev;
Dima Zavinfce7a472011-04-19 22:30:36 -0700169
Dima Zavin799a70e2011-04-18 16:57:27 -0700170 rc = load_audio_interface(audio_interfaces[i], &mod, &dev);
171 if (rc)
172 continue;
173
Steve Blockdf64d152012-01-04 20:05:49 +0000174 ALOGI("Loaded %s audio interface from %s (%s)", audio_interfaces[i],
Dima Zavin799a70e2011-04-18 16:57:27 -0700175 mod->name, mod->id);
176 mAudioHwDevs.push(dev);
177
Glenn Kasten2b213bc2012-02-02 14:05:20 -0800178 if (mPrimaryHardwareDev == NULL) {
Dima Zavin799a70e2011-04-18 16:57:27 -0700179 mPrimaryHardwareDev = dev;
Steve Blockdf64d152012-01-04 20:05:49 +0000180 ALOGI("Using '%s' (%s.%s) as the primary audio interface",
Dima Zavin5a61d2f2011-04-19 19:04:32 -0700181 mod->name, mod->id, audio_interfaces[i]);
Dima Zavin799a70e2011-04-18 16:57:27 -0700182 }
183 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700184
Glenn Kasten2b213bc2012-02-02 14:05:20 -0800185 if (mPrimaryHardwareDev == NULL) {
Steve Block29357bc2012-01-06 19:20:56 +0000186 ALOGE("Primary audio interface not found");
Glenn Kasten2b213bc2012-02-02 14:05:20 -0800187 // proceed, all later accesses to mPrimaryHardwareDev verify it's safe with initCheck()
Dima Zavin799a70e2011-04-18 16:57:27 -0700188 }
189
Glenn Kasten2b213bc2012-02-02 14:05:20 -0800190 // Currently (mPrimaryHardwareDev == NULL) == (mAudioHwDevs.size() == 0), but the way the
191 // primary HW dev is selected can change so these conditions might not always be equivalent.
192 // When that happens, re-visit all the code that assumes this.
193
194 AutoMutex lock(mHardwareLock);
195
Dima Zavin799a70e2011-04-18 16:57:27 -0700196 for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
197 audio_hw_device_t *dev = mAudioHwDevs[i];
198
199 mHardwareStatus = AUDIO_HW_INIT;
200 rc = dev->init_check(dev);
Glenn Kasten2b213bc2012-02-02 14:05:20 -0800201 mHardwareStatus = AUDIO_HW_IDLE;
Dima Zavin799a70e2011-04-18 16:57:27 -0700202 if (rc == 0) {
Glenn Kasten2b213bc2012-02-02 14:05:20 -0800203 mMode = AUDIO_MODE_NORMAL; // assigned multiple times with same value
Dima Zavin799a70e2011-04-18 16:57:27 -0700204 mHardwareStatus = AUDIO_HW_SET_MODE;
205 dev->set_mode(dev, mMode);
206 mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
207 dev->set_master_volume(dev, 1.0f);
208 mHardwareStatus = AUDIO_HW_IDLE;
209 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700210 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700211}
212
213AudioFlinger::~AudioFlinger()
214{
Dima Zavin799a70e2011-04-18 16:57:27 -0700215
Mathias Agopian65ab4712010-07-14 17:59:35 -0700216 while (!mRecordThreads.isEmpty()) {
217 // closeInput() will remove first entry from mRecordThreads
218 closeInput(mRecordThreads.keyAt(0));
219 }
220 while (!mPlaybackThreads.isEmpty()) {
221 // closeOutput() will remove first entry from mPlaybackThreads
222 closeOutput(mPlaybackThreads.keyAt(0));
223 }
Dima Zavin799a70e2011-04-18 16:57:27 -0700224
Glenn Kasten2b213bc2012-02-02 14:05:20 -0800225 for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
226 // no mHardwareLock needed, as there are no other references to this
227 audio_hw_device_close(mAudioHwDevs[i]);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700228 }
229}
230
Dima Zavin799a70e2011-04-18 16:57:27 -0700231audio_hw_device_t* AudioFlinger::findSuitableHwDev_l(uint32_t devices)
232{
233 /* first matching HW device is returned */
234 for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
235 audio_hw_device_t *dev = mAudioHwDevs[i];
236 if ((dev->get_supported_devices(dev) & devices) == devices)
237 return dev;
238 }
239 return NULL;
240}
Mathias Agopian65ab4712010-07-14 17:59:35 -0700241
242status_t AudioFlinger::dumpClients(int fd, const Vector<String16>& args)
243{
244 const size_t SIZE = 256;
245 char buffer[SIZE];
246 String8 result;
247
248 result.append("Clients:\n");
249 for (size_t i = 0; i < mClients.size(); ++i) {
Glenn Kasten77c11192012-01-25 14:27:41 -0800250 sp<Client> client = mClients.valueAt(i).promote();
251 if (client != 0) {
252 snprintf(buffer, SIZE, " pid: %d\n", client->pid());
253 result.append(buffer);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700254 }
255 }
Marco Nelissen3a34bef2011-08-02 13:33:41 -0700256
257 result.append("Global session refs:\n");
258 result.append(" session pid cnt\n");
259 for (size_t i = 0; i < mAudioSessionRefs.size(); i++) {
260 AudioSessionRef *r = mAudioSessionRefs[i];
261 snprintf(buffer, SIZE, " %7d %3d %3d\n", r->sessionid, r->pid, r->cnt);
262 result.append(buffer);
263 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700264 write(fd, result.string(), result.size());
265 return NO_ERROR;
266}
267
268
269status_t AudioFlinger::dumpInternals(int fd, const Vector<String16>& args)
270{
271 const size_t SIZE = 256;
272 char buffer[SIZE];
273 String8 result;
Glenn Kastena4454b42012-01-04 11:02:33 -0800274 hardware_call_state hardwareStatus = mHardwareStatus;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700275
276 snprintf(buffer, SIZE, "Hardware status: %d\n", hardwareStatus);
277 result.append(buffer);
278 write(fd, result.string(), result.size());
279 return NO_ERROR;
280}
281
282status_t AudioFlinger::dumpPermissionDenial(int fd, const Vector<String16>& args)
283{
284 const size_t SIZE = 256;
285 char buffer[SIZE];
286 String8 result;
287 snprintf(buffer, SIZE, "Permission Denial: "
288 "can't dump AudioFlinger from pid=%d, uid=%d\n",
289 IPCThreadState::self()->getCallingPid(),
290 IPCThreadState::self()->getCallingUid());
291 result.append(buffer);
292 write(fd, result.string(), result.size());
293 return NO_ERROR;
294}
295
296static bool tryLock(Mutex& mutex)
297{
298 bool locked = false;
299 for (int i = 0; i < kDumpLockRetries; ++i) {
300 if (mutex.tryLock() == NO_ERROR) {
301 locked = true;
302 break;
303 }
Glenn Kasten7dede872011-12-13 11:04:14 -0800304 usleep(kDumpLockSleepUs);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700305 }
306 return locked;
307}
308
309status_t AudioFlinger::dump(int fd, const Vector<String16>& args)
310{
Glenn Kasten44deb052012-02-05 18:09:08 -0800311 if (!dumpAllowed()) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700312 dumpPermissionDenial(fd, args);
313 } else {
314 // get state of hardware lock
315 bool hardwareLocked = tryLock(mHardwareLock);
316 if (!hardwareLocked) {
317 String8 result(kHardwareLockedString);
318 write(fd, result.string(), result.size());
319 } else {
320 mHardwareLock.unlock();
321 }
322
323 bool locked = tryLock(mLock);
324
325 // failed to lock - AudioFlinger is probably deadlocked
326 if (!locked) {
327 String8 result(kDeadlockedString);
328 write(fd, result.string(), result.size());
329 }
330
331 dumpClients(fd, args);
332 dumpInternals(fd, args);
333
334 // dump playback threads
335 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
336 mPlaybackThreads.valueAt(i)->dump(fd, args);
337 }
338
339 // dump record threads
340 for (size_t i = 0; i < mRecordThreads.size(); i++) {
341 mRecordThreads.valueAt(i)->dump(fd, args);
342 }
343
Dima Zavin799a70e2011-04-18 16:57:27 -0700344 // dump all hardware devs
345 for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
346 audio_hw_device_t *dev = mAudioHwDevs[i];
347 dev->dump(dev, fd);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700348 }
349 if (locked) mLock.unlock();
350 }
351 return NO_ERROR;
352}
353
Glenn Kasten98ec94c2012-01-25 14:28:29 -0800354sp<AudioFlinger::Client> AudioFlinger::registerPid_l(pid_t pid)
355{
356 // If pid is already in the mClients wp<> map, then use that entry
357 // (for which promote() is always != 0), otherwise create a new entry and Client.
358 sp<Client> client = mClients.valueFor(pid).promote();
359 if (client == 0) {
360 client = new Client(this, pid);
361 mClients.add(pid, client);
362 }
363
364 return client;
365}
Mathias Agopian65ab4712010-07-14 17:59:35 -0700366
367// IAudioFlinger interface
368
369
370sp<IAudioTrack> AudioFlinger::createTrack(
371 pid_t pid,
Glenn Kastenfff6d712012-01-12 16:38:12 -0800372 audio_stream_type_t streamType,
Mathias Agopian65ab4712010-07-14 17:59:35 -0700373 uint32_t sampleRate,
Glenn Kasten58f30212012-01-12 12:27:51 -0800374 audio_format_t format,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -0700375 uint32_t channelMask,
Mathias Agopian65ab4712010-07-14 17:59:35 -0700376 int frameCount,
377 uint32_t flags,
378 const sp<IMemory>& sharedBuffer,
Glenn Kasten72ef00d2012-01-17 11:09:42 -0800379 audio_io_handle_t output,
Mathias Agopian65ab4712010-07-14 17:59:35 -0700380 int *sessionId,
381 status_t *status)
382{
383 sp<PlaybackThread::Track> track;
384 sp<TrackHandle> trackHandle;
385 sp<Client> client;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700386 status_t lStatus;
387 int lSessionId;
388
Glenn Kasten263709e2012-01-06 08:40:01 -0800389 // client AudioTrack::set already implements AUDIO_STREAM_DEFAULT => AUDIO_STREAM_MUSIC,
390 // but if someone uses binder directly they could bypass that and cause us to crash
391 if (uint32_t(streamType) >= AUDIO_STREAM_CNT) {
Steve Block29357bc2012-01-06 19:20:56 +0000392 ALOGE("createTrack() invalid stream type %d", streamType);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700393 lStatus = BAD_VALUE;
394 goto Exit;
395 }
396
397 {
398 Mutex::Autolock _l(mLock);
399 PlaybackThread *thread = checkPlaybackThread_l(output);
Eric Laurent39e94f82010-07-28 01:32:47 -0700400 PlaybackThread *effectThread = NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700401 if (thread == NULL) {
Steve Block29357bc2012-01-06 19:20:56 +0000402 ALOGE("unknown output thread");
Mathias Agopian65ab4712010-07-14 17:59:35 -0700403 lStatus = BAD_VALUE;
404 goto Exit;
405 }
406
Glenn Kasten98ec94c2012-01-25 14:28:29 -0800407 client = registerPid_l(pid);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700408
Steve Block3856b092011-10-20 11:56:00 +0100409 ALOGV("createTrack() sessionId: %d", (sessionId == NULL) ? -2 : *sessionId);
Dima Zavinfce7a472011-04-19 22:30:36 -0700410 if (sessionId != NULL && *sessionId != AUDIO_SESSION_OUTPUT_MIX) {
Eric Laurentde070132010-07-13 04:45:46 -0700411 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
Eric Laurent39e94f82010-07-28 01:32:47 -0700412 sp<PlaybackThread> t = mPlaybackThreads.valueAt(i);
413 if (mPlaybackThreads.keyAt(i) != output) {
414 // prevent same audio session on different output threads
415 uint32_t sessions = t->hasAudioSession(*sessionId);
416 if (sessions & PlaybackThread::TRACK_SESSION) {
Steve Block29357bc2012-01-06 19:20:56 +0000417 ALOGE("createTrack() session ID %d already in use", *sessionId);
Eric Laurent39e94f82010-07-28 01:32:47 -0700418 lStatus = BAD_VALUE;
419 goto Exit;
420 }
421 // check if an effect with same session ID is waiting for a track to be created
422 if (sessions & PlaybackThread::EFFECT_SESSION) {
423 effectThread = t.get();
424 }
Eric Laurentde070132010-07-13 04:45:46 -0700425 }
426 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700427 lSessionId = *sessionId;
428 } else {
Eric Laurentde070132010-07-13 04:45:46 -0700429 // if no audio session id is provided, create one here
Eric Laurent7c7f10b2011-06-17 21:29:58 -0700430 lSessionId = nextUniqueId();
Mathias Agopian65ab4712010-07-14 17:59:35 -0700431 if (sessionId != NULL) {
432 *sessionId = lSessionId;
433 }
434 }
Steve Block3856b092011-10-20 11:56:00 +0100435 ALOGV("createTrack() lSessionId: %d", lSessionId);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700436
437 track = thread->createTrack_l(client, streamType, sampleRate, format,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -0700438 channelMask, frameCount, sharedBuffer, lSessionId, &lStatus);
Eric Laurent39e94f82010-07-28 01:32:47 -0700439
440 // move effect chain to this output thread if an effect on same session was waiting
441 // for a track to be created
442 if (lStatus == NO_ERROR && effectThread != NULL) {
443 Mutex::Autolock _dl(thread->mLock);
444 Mutex::Autolock _sl(effectThread->mLock);
445 moveEffectChain_l(lSessionId, effectThread, thread, true);
446 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700447 }
448 if (lStatus == NO_ERROR) {
449 trackHandle = new TrackHandle(track);
450 } else {
451 // remove local strong reference to Client before deleting the Track so that the Client
452 // destructor is called by the TrackBase destructor with mLock held
453 client.clear();
454 track.clear();
455 }
456
457Exit:
458 if(status) {
459 *status = lStatus;
460 }
461 return trackHandle;
462}
463
Glenn Kasten72ef00d2012-01-17 11:09:42 -0800464uint32_t AudioFlinger::sampleRate(audio_io_handle_t output) const
Mathias Agopian65ab4712010-07-14 17:59:35 -0700465{
466 Mutex::Autolock _l(mLock);
467 PlaybackThread *thread = checkPlaybackThread_l(output);
468 if (thread == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +0000469 ALOGW("sampleRate() unknown thread %d", output);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700470 return 0;
471 }
472 return thread->sampleRate();
473}
474
Glenn Kasten72ef00d2012-01-17 11:09:42 -0800475int AudioFlinger::channelCount(audio_io_handle_t output) const
Mathias Agopian65ab4712010-07-14 17:59:35 -0700476{
477 Mutex::Autolock _l(mLock);
478 PlaybackThread *thread = checkPlaybackThread_l(output);
479 if (thread == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +0000480 ALOGW("channelCount() unknown thread %d", output);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700481 return 0;
482 }
483 return thread->channelCount();
484}
485
Glenn Kasten72ef00d2012-01-17 11:09:42 -0800486audio_format_t AudioFlinger::format(audio_io_handle_t output) const
Mathias Agopian65ab4712010-07-14 17:59:35 -0700487{
488 Mutex::Autolock _l(mLock);
489 PlaybackThread *thread = checkPlaybackThread_l(output);
490 if (thread == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +0000491 ALOGW("format() unknown thread %d", output);
Glenn Kasten58f30212012-01-12 12:27:51 -0800492 return AUDIO_FORMAT_INVALID;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700493 }
494 return thread->format();
495}
496
Glenn Kasten72ef00d2012-01-17 11:09:42 -0800497size_t AudioFlinger::frameCount(audio_io_handle_t output) const
Mathias Agopian65ab4712010-07-14 17:59:35 -0700498{
499 Mutex::Autolock _l(mLock);
500 PlaybackThread *thread = checkPlaybackThread_l(output);
501 if (thread == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +0000502 ALOGW("frameCount() unknown thread %d", output);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700503 return 0;
504 }
505 return thread->frameCount();
506}
507
Glenn Kasten72ef00d2012-01-17 11:09:42 -0800508uint32_t AudioFlinger::latency(audio_io_handle_t output) const
Mathias Agopian65ab4712010-07-14 17:59:35 -0700509{
510 Mutex::Autolock _l(mLock);
511 PlaybackThread *thread = checkPlaybackThread_l(output);
512 if (thread == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +0000513 ALOGW("latency() unknown thread %d", output);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700514 return 0;
515 }
516 return thread->latency();
517}
518
519status_t AudioFlinger::setMasterVolume(float value)
520{
Eric Laurenta1884f92011-08-23 08:25:03 -0700521 status_t ret = initCheck();
522 if (ret != NO_ERROR) {
523 return ret;
524 }
525
Mathias Agopian65ab4712010-07-14 17:59:35 -0700526 // check calling permissions
527 if (!settingsAllowed()) {
528 return PERMISSION_DENIED;
529 }
530
531 // when hw supports master volume, don't scale in sw mixer
Eric Laurent93575202011-01-18 18:39:02 -0800532 { // scope for the lock
533 AutoMutex lock(mHardwareLock);
534 mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
Dima Zavin799a70e2011-04-18 16:57:27 -0700535 if (mPrimaryHardwareDev->set_master_volume(mPrimaryHardwareDev, value) == NO_ERROR) {
Eric Laurent93575202011-01-18 18:39:02 -0800536 value = 1.0f;
537 }
538 mHardwareStatus = AUDIO_HW_IDLE;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700539 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700540
Eric Laurent93575202011-01-18 18:39:02 -0800541 Mutex::Autolock _l(mLock);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700542 mMasterVolume = value;
Glenn Kasten8d6a2442012-02-08 14:04:28 -0800543 for (size_t i = 0; i < mPlaybackThreads.size(); i++)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700544 mPlaybackThreads.valueAt(i)->setMasterVolume(value);
545
546 return NO_ERROR;
547}
548
Glenn Kastenf78aee72012-01-04 11:00:47 -0800549status_t AudioFlinger::setMode(audio_mode_t mode)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700550{
Eric Laurenta1884f92011-08-23 08:25:03 -0700551 status_t ret = initCheck();
552 if (ret != NO_ERROR) {
553 return ret;
554 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700555
556 // check calling permissions
557 if (!settingsAllowed()) {
558 return PERMISSION_DENIED;
559 }
Glenn Kasten930f4ca2012-01-06 16:47:31 -0800560 if (uint32_t(mode) >= AUDIO_MODE_CNT) {
Steve Block5ff1dd52012-01-05 23:22:43 +0000561 ALOGW("Illegal value: setMode(%d)", mode);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700562 return BAD_VALUE;
563 }
564
565 { // scope for the lock
566 AutoMutex lock(mHardwareLock);
567 mHardwareStatus = AUDIO_HW_SET_MODE;
Dima Zavin799a70e2011-04-18 16:57:27 -0700568 ret = mPrimaryHardwareDev->set_mode(mPrimaryHardwareDev, mode);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700569 mHardwareStatus = AUDIO_HW_IDLE;
570 }
571
572 if (NO_ERROR == ret) {
573 Mutex::Autolock _l(mLock);
574 mMode = mode;
Glenn Kasten8d6a2442012-02-08 14:04:28 -0800575 for (size_t i = 0; i < mPlaybackThreads.size(); i++)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700576 mPlaybackThreads.valueAt(i)->setMode(mode);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700577 }
578
579 return ret;
580}
581
582status_t AudioFlinger::setMicMute(bool state)
583{
Eric Laurenta1884f92011-08-23 08:25:03 -0700584 status_t ret = initCheck();
585 if (ret != NO_ERROR) {
586 return ret;
587 }
588
Mathias Agopian65ab4712010-07-14 17:59:35 -0700589 // check calling permissions
590 if (!settingsAllowed()) {
591 return PERMISSION_DENIED;
592 }
593
594 AutoMutex lock(mHardwareLock);
595 mHardwareStatus = AUDIO_HW_SET_MIC_MUTE;
Eric Laurenta1884f92011-08-23 08:25:03 -0700596 ret = mPrimaryHardwareDev->set_mic_mute(mPrimaryHardwareDev, state);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700597 mHardwareStatus = AUDIO_HW_IDLE;
598 return ret;
599}
600
601bool AudioFlinger::getMicMute() const
602{
Eric Laurenta1884f92011-08-23 08:25:03 -0700603 status_t ret = initCheck();
604 if (ret != NO_ERROR) {
605 return false;
606 }
607
Dima Zavinfce7a472011-04-19 22:30:36 -0700608 bool state = AUDIO_MODE_INVALID;
Glenn Kasten2b213bc2012-02-02 14:05:20 -0800609 AutoMutex lock(mHardwareLock);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700610 mHardwareStatus = AUDIO_HW_GET_MIC_MUTE;
Dima Zavin799a70e2011-04-18 16:57:27 -0700611 mPrimaryHardwareDev->get_mic_mute(mPrimaryHardwareDev, &state);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700612 mHardwareStatus = AUDIO_HW_IDLE;
613 return state;
614}
615
616status_t AudioFlinger::setMasterMute(bool muted)
617{
618 // check calling permissions
619 if (!settingsAllowed()) {
620 return PERMISSION_DENIED;
621 }
622
Eric Laurent93575202011-01-18 18:39:02 -0800623 Mutex::Autolock _l(mLock);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700624 mMasterMute = muted;
Glenn Kasten8d6a2442012-02-08 14:04:28 -0800625 for (size_t i = 0; i < mPlaybackThreads.size(); i++)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700626 mPlaybackThreads.valueAt(i)->setMasterMute(muted);
627
628 return NO_ERROR;
629}
630
631float AudioFlinger::masterVolume() const
632{
Glenn Kasten98067102011-12-13 11:47:54 -0800633 Mutex::Autolock _l(mLock);
634 return masterVolume_l();
Mathias Agopian65ab4712010-07-14 17:59:35 -0700635}
636
637bool AudioFlinger::masterMute() const
638{
Glenn Kasten98067102011-12-13 11:47:54 -0800639 Mutex::Autolock _l(mLock);
640 return masterMute_l();
Mathias Agopian65ab4712010-07-14 17:59:35 -0700641}
642
Glenn Kasten72ef00d2012-01-17 11:09:42 -0800643status_t AudioFlinger::setStreamVolume(audio_stream_type_t stream, float value,
644 audio_io_handle_t output)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700645{
646 // check calling permissions
647 if (!settingsAllowed()) {
648 return PERMISSION_DENIED;
649 }
650
Glenn Kasten263709e2012-01-06 08:40:01 -0800651 if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
Steve Block29357bc2012-01-06 19:20:56 +0000652 ALOGE("setStreamVolume() invalid stream %d", stream);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700653 return BAD_VALUE;
654 }
655
656 AutoMutex lock(mLock);
657 PlaybackThread *thread = NULL;
658 if (output) {
659 thread = checkPlaybackThread_l(output);
660 if (thread == NULL) {
661 return BAD_VALUE;
662 }
663 }
664
665 mStreamTypes[stream].volume = value;
666
667 if (thread == NULL) {
Glenn Kasten8d6a2442012-02-08 14:04:28 -0800668 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700669 mPlaybackThreads.valueAt(i)->setStreamVolume(stream, value);
670 }
671 } else {
672 thread->setStreamVolume(stream, value);
673 }
674
675 return NO_ERROR;
676}
677
Glenn Kastenfff6d712012-01-12 16:38:12 -0800678status_t AudioFlinger::setStreamMute(audio_stream_type_t stream, bool muted)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700679{
680 // check calling permissions
681 if (!settingsAllowed()) {
682 return PERMISSION_DENIED;
683 }
684
Glenn Kasten263709e2012-01-06 08:40:01 -0800685 if (uint32_t(stream) >= AUDIO_STREAM_CNT ||
Dima Zavinfce7a472011-04-19 22:30:36 -0700686 uint32_t(stream) == AUDIO_STREAM_ENFORCED_AUDIBLE) {
Steve Block29357bc2012-01-06 19:20:56 +0000687 ALOGE("setStreamMute() invalid stream %d", stream);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700688 return BAD_VALUE;
689 }
690
Eric Laurent93575202011-01-18 18:39:02 -0800691 AutoMutex lock(mLock);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700692 mStreamTypes[stream].mute = muted;
693 for (uint32_t i = 0; i < mPlaybackThreads.size(); i++)
694 mPlaybackThreads.valueAt(i)->setStreamMute(stream, muted);
695
696 return NO_ERROR;
697}
698
Glenn Kasten72ef00d2012-01-17 11:09:42 -0800699float AudioFlinger::streamVolume(audio_stream_type_t stream, audio_io_handle_t output) const
Mathias Agopian65ab4712010-07-14 17:59:35 -0700700{
Glenn Kasten263709e2012-01-06 08:40:01 -0800701 if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700702 return 0.0f;
703 }
704
705 AutoMutex lock(mLock);
706 float volume;
707 if (output) {
708 PlaybackThread *thread = checkPlaybackThread_l(output);
709 if (thread == NULL) {
710 return 0.0f;
711 }
712 volume = thread->streamVolume(stream);
713 } else {
714 volume = mStreamTypes[stream].volume;
715 }
716
717 return volume;
718}
719
Glenn Kastenfff6d712012-01-12 16:38:12 -0800720bool AudioFlinger::streamMute(audio_stream_type_t stream) const
Mathias Agopian65ab4712010-07-14 17:59:35 -0700721{
Glenn Kasten263709e2012-01-06 08:40:01 -0800722 if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700723 return true;
724 }
725
726 return mStreamTypes[stream].mute;
727}
728
Glenn Kasten72ef00d2012-01-17 11:09:42 -0800729status_t AudioFlinger::setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700730{
731 status_t result;
732
Glenn Kasten23d82a92012-02-03 11:10:00 -0800733 ALOGV("setParameters(): io %d, keyvalue %s, tid %d, calling pid %d",
Mathias Agopian65ab4712010-07-14 17:59:35 -0700734 ioHandle, keyValuePairs.string(), gettid(), IPCThreadState::self()->getCallingPid());
735 // check calling permissions
736 if (!settingsAllowed()) {
737 return PERMISSION_DENIED;
738 }
739
Mathias Agopian65ab4712010-07-14 17:59:35 -0700740 // ioHandle == 0 means the parameters are global to the audio hardware interface
741 if (ioHandle == 0) {
742 AutoMutex lock(mHardwareLock);
743 mHardwareStatus = AUDIO_SET_PARAMETER;
Dima Zavin799a70e2011-04-18 16:57:27 -0700744 status_t final_result = NO_ERROR;
745 for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
746 audio_hw_device_t *dev = mAudioHwDevs[i];
747 result = dev->set_parameters(dev, keyValuePairs.string());
748 final_result = result ?: final_result;
749 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700750 mHardwareStatus = AUDIO_HW_IDLE;
Eric Laurent59bd0da2011-08-01 09:52:20 -0700751 // disable AEC and NS if the device is a BT SCO headset supporting those pre processings
752 AudioParameter param = AudioParameter(keyValuePairs);
753 String8 value;
754 if (param.get(String8(AUDIO_PARAMETER_KEY_BT_NREC), value) == NO_ERROR) {
755 Mutex::Autolock _l(mLock);
Eric Laurentbee53372011-08-29 12:42:48 -0700756 bool btNrecIsOff = (value == AUDIO_PARAMETER_VALUE_OFF);
757 if (mBtNrecIsOff != btNrecIsOff) {
Eric Laurent59bd0da2011-08-01 09:52:20 -0700758 for (size_t i = 0; i < mRecordThreads.size(); i++) {
759 sp<RecordThread> thread = mRecordThreads.valueAt(i);
760 RecordThread::RecordTrack *track = thread->track();
761 if (track != NULL) {
762 audio_devices_t device = (audio_devices_t)(
763 thread->device() & AUDIO_DEVICE_IN_ALL);
Eric Laurentbee53372011-08-29 12:42:48 -0700764 bool suspend = audio_is_bluetooth_sco_device(device) && btNrecIsOff;
Eric Laurent59bd0da2011-08-01 09:52:20 -0700765 thread->setEffectSuspended(FX_IID_AEC,
766 suspend,
767 track->sessionId());
768 thread->setEffectSuspended(FX_IID_NS,
769 suspend,
770 track->sessionId());
771 }
772 }
Eric Laurentbee53372011-08-29 12:42:48 -0700773 mBtNrecIsOff = btNrecIsOff;
Eric Laurent59bd0da2011-08-01 09:52:20 -0700774 }
775 }
Dima Zavin799a70e2011-04-18 16:57:27 -0700776 return final_result;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700777 }
778
779 // hold a strong ref on thread in case closeOutput() or closeInput() is called
780 // and the thread is exited once the lock is released
781 sp<ThreadBase> thread;
782 {
783 Mutex::Autolock _l(mLock);
784 thread = checkPlaybackThread_l(ioHandle);
785 if (thread == NULL) {
786 thread = checkRecordThread_l(ioHandle);
Glenn Kasten7fc9a6f2012-01-10 10:46:34 -0800787 } else if (thread == primaryPlaybackThread_l()) {
Eric Laurent7c7f10b2011-06-17 21:29:58 -0700788 // indicate output device change to all input threads for pre processing
789 AudioParameter param = AudioParameter(keyValuePairs);
790 int value;
791 if (param.getInt(String8(AudioParameter::keyRouting), value) == NO_ERROR) {
792 for (size_t i = 0; i < mRecordThreads.size(); i++) {
793 mRecordThreads.valueAt(i)->setParameters(keyValuePairs);
794 }
795 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700796 }
797 }
Glenn Kasten7378ca52012-01-20 13:44:40 -0800798 if (thread != 0) {
799 return thread->setParameters(keyValuePairs);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700800 }
801 return BAD_VALUE;
802}
803
Glenn Kasten72ef00d2012-01-17 11:09:42 -0800804String8 AudioFlinger::getParameters(audio_io_handle_t ioHandle, const String8& keys) const
Mathias Agopian65ab4712010-07-14 17:59:35 -0700805{
Glenn Kasten23d82a92012-02-03 11:10:00 -0800806// ALOGV("getParameters() io %d, keys %s, tid %d, calling pid %d",
Mathias Agopian65ab4712010-07-14 17:59:35 -0700807// ioHandle, keys.string(), gettid(), IPCThreadState::self()->getCallingPid());
808
809 if (ioHandle == 0) {
Dima Zavinfce7a472011-04-19 22:30:36 -0700810 String8 out_s8;
811
Dima Zavin799a70e2011-04-18 16:57:27 -0700812 for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
813 audio_hw_device_t *dev = mAudioHwDevs[i];
814 char *s = dev->get_parameters(dev, keys.string());
815 out_s8 += String8(s);
816 free(s);
817 }
Dima Zavinfce7a472011-04-19 22:30:36 -0700818 return out_s8;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700819 }
820
821 Mutex::Autolock _l(mLock);
822
823 PlaybackThread *playbackThread = checkPlaybackThread_l(ioHandle);
824 if (playbackThread != NULL) {
825 return playbackThread->getParameters(keys);
826 }
827 RecordThread *recordThread = checkRecordThread_l(ioHandle);
828 if (recordThread != NULL) {
829 return recordThread->getParameters(keys);
830 }
831 return String8("");
832}
833
Glenn Kastenf587ba52012-01-26 16:25:10 -0800834size_t AudioFlinger::getInputBufferSize(uint32_t sampleRate, audio_format_t format, int channelCount) const
Mathias Agopian65ab4712010-07-14 17:59:35 -0700835{
Eric Laurenta1884f92011-08-23 08:25:03 -0700836 status_t ret = initCheck();
837 if (ret != NO_ERROR) {
838 return 0;
839 }
840
Glenn Kasten2b213bc2012-02-02 14:05:20 -0800841 AutoMutex lock(mHardwareLock);
842 mHardwareStatus = AUDIO_HW_GET_INPUT_BUFFER_SIZE;
843 size_t size = mPrimaryHardwareDev->get_input_buffer_size(mPrimaryHardwareDev, sampleRate, format, channelCount);
844 mHardwareStatus = AUDIO_HW_IDLE;
845 return size;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700846}
847
Glenn Kasten72ef00d2012-01-17 11:09:42 -0800848unsigned int AudioFlinger::getInputFramesLost(audio_io_handle_t ioHandle) const
Mathias Agopian65ab4712010-07-14 17:59:35 -0700849{
850 if (ioHandle == 0) {
851 return 0;
852 }
853
854 Mutex::Autolock _l(mLock);
855
856 RecordThread *recordThread = checkRecordThread_l(ioHandle);
857 if (recordThread != NULL) {
858 return recordThread->getInputFramesLost();
859 }
860 return 0;
861}
862
863status_t AudioFlinger::setVoiceVolume(float value)
864{
Eric Laurenta1884f92011-08-23 08:25:03 -0700865 status_t ret = initCheck();
866 if (ret != NO_ERROR) {
867 return ret;
868 }
869
Mathias Agopian65ab4712010-07-14 17:59:35 -0700870 // check calling permissions
871 if (!settingsAllowed()) {
872 return PERMISSION_DENIED;
873 }
874
875 AutoMutex lock(mHardwareLock);
876 mHardwareStatus = AUDIO_SET_VOICE_VOLUME;
Eric Laurenta1884f92011-08-23 08:25:03 -0700877 ret = mPrimaryHardwareDev->set_voice_volume(mPrimaryHardwareDev, value);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700878 mHardwareStatus = AUDIO_HW_IDLE;
879
880 return ret;
881}
882
Glenn Kasten72ef00d2012-01-17 11:09:42 -0800883status_t AudioFlinger::getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames,
884 audio_io_handle_t output) const
Mathias Agopian65ab4712010-07-14 17:59:35 -0700885{
886 status_t status;
887
888 Mutex::Autolock _l(mLock);
889
890 PlaybackThread *playbackThread = checkPlaybackThread_l(output);
891 if (playbackThread != NULL) {
892 return playbackThread->getRenderPosition(halFrames, dspFrames);
893 }
894
895 return BAD_VALUE;
896}
897
898void AudioFlinger::registerClient(const sp<IAudioFlingerClient>& client)
899{
900
901 Mutex::Autolock _l(mLock);
902
Glenn Kastenbb001922012-02-03 11:10:26 -0800903 pid_t pid = IPCThreadState::self()->getCallingPid();
Mathias Agopian65ab4712010-07-14 17:59:35 -0700904 if (mNotificationClients.indexOfKey(pid) < 0) {
905 sp<NotificationClient> notificationClient = new NotificationClient(this,
906 client,
907 pid);
Steve Block3856b092011-10-20 11:56:00 +0100908 ALOGV("registerClient() client %p, pid %d", notificationClient.get(), pid);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700909
910 mNotificationClients.add(pid, notificationClient);
911
912 sp<IBinder> binder = client->asBinder();
913 binder->linkToDeath(notificationClient);
914
915 // the config change is always sent from playback or record threads to avoid deadlock
916 // with AudioSystem::gLock
917 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
918 mPlaybackThreads.valueAt(i)->sendConfigEvent(AudioSystem::OUTPUT_OPENED);
919 }
920
921 for (size_t i = 0; i < mRecordThreads.size(); i++) {
922 mRecordThreads.valueAt(i)->sendConfigEvent(AudioSystem::INPUT_OPENED);
923 }
924 }
925}
926
927void AudioFlinger::removeNotificationClient(pid_t pid)
928{
929 Mutex::Autolock _l(mLock);
930
Glenn Kasten8d6a2442012-02-08 14:04:28 -0800931 ssize_t index = mNotificationClients.indexOfKey(pid);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700932 if (index >= 0) {
933 sp <NotificationClient> client = mNotificationClients.valueFor(pid);
Steve Block3856b092011-10-20 11:56:00 +0100934 ALOGV("removeNotificationClient() %p, pid %d", client.get(), pid);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700935 mNotificationClients.removeItem(pid);
936 }
Marco Nelissen3a34bef2011-08-02 13:33:41 -0700937
Steve Block3856b092011-10-20 11:56:00 +0100938 ALOGV("%d died, releasing its sessions", pid);
Glenn Kasten8d6a2442012-02-08 14:04:28 -0800939 size_t num = mAudioSessionRefs.size();
Marco Nelissen3a34bef2011-08-02 13:33:41 -0700940 bool removed = false;
Glenn Kasten8d6a2442012-02-08 14:04:28 -0800941 for (size_t i = 0; i< num; ) {
Marco Nelissen3a34bef2011-08-02 13:33:41 -0700942 AudioSessionRef *ref = mAudioSessionRefs.itemAt(i);
Steve Block3856b092011-10-20 11:56:00 +0100943 ALOGV(" pid %d @ %d", ref->pid, i);
Marco Nelissen3a34bef2011-08-02 13:33:41 -0700944 if (ref->pid == pid) {
Steve Block3856b092011-10-20 11:56:00 +0100945 ALOGV(" removing entry for pid %d session %d", pid, ref->sessionid);
Marco Nelissen3a34bef2011-08-02 13:33:41 -0700946 mAudioSessionRefs.removeAt(i);
947 delete ref;
948 removed = true;
Marco Nelissen3a34bef2011-08-02 13:33:41 -0700949 num--;
Glenn Kasten8d6a2442012-02-08 14:04:28 -0800950 } else {
951 i++;
Marco Nelissen3a34bef2011-08-02 13:33:41 -0700952 }
953 }
954 if (removed) {
955 purgeStaleEffects_l();
956 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700957}
958
959// audioConfigChanged_l() must be called with AudioFlinger::mLock held
Glenn Kasten72ef00d2012-01-17 11:09:42 -0800960void AudioFlinger::audioConfigChanged_l(int event, audio_io_handle_t ioHandle, void *param2)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700961{
962 size_t size = mNotificationClients.size();
963 for (size_t i = 0; i < size; i++) {
Glenn Kasten84afa3b2012-01-25 15:28:08 -0800964 mNotificationClients.valueAt(i)->audioFlingerClient()->ioConfigChanged(event, ioHandle,
965 param2);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700966 }
967}
968
969// removeClient_l() must be called with AudioFlinger::mLock held
970void AudioFlinger::removeClient_l(pid_t pid)
971{
Steve Block3856b092011-10-20 11:56:00 +0100972 ALOGV("removeClient_l() pid %d, tid %d, calling tid %d", pid, gettid(), IPCThreadState::self()->getCallingPid());
Mathias Agopian65ab4712010-07-14 17:59:35 -0700973 mClients.removeItem(pid);
974}
975
976
977// ----------------------------------------------------------------------------
978
Glenn Kasten72ef00d2012-01-17 11:09:42 -0800979AudioFlinger::ThreadBase::ThreadBase(const sp<AudioFlinger>& audioFlinger, audio_io_handle_t id,
980 uint32_t device, type_t type)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700981 : Thread(false),
Glenn Kasten23bb8be2012-01-26 10:38:26 -0800982 mType(type),
Glenn Kasten84afa3b2012-01-25 15:28:08 -0800983 mAudioFlinger(audioFlinger), mSampleRate(0), mFrameCount(0),
984 // mChannelMask
985 mChannelCount(0),
986 mFrameSize(1), mFormat(AUDIO_FORMAT_INVALID),
987 mParamStatus(NO_ERROR),
Glenn Kastenb28686f2012-01-06 08:39:38 -0800988 mStandby(false), mId(id),
Glenn Kasten84afa3b2012-01-25 15:28:08 -0800989 mDevice(device),
990 mDeathRecipient(new PMDeathRecipient(this))
Mathias Agopian65ab4712010-07-14 17:59:35 -0700991{
992}
993
994AudioFlinger::ThreadBase::~ThreadBase()
995{
996 mParamCond.broadcast();
Eric Laurentfeb0db62011-07-22 09:04:31 -0700997 // do not lock the mutex in destructor
998 releaseWakeLock_l();
Eric Laurent9d18ec52011-09-27 12:07:15 -0700999 if (mPowerManager != 0) {
1000 sp<IBinder> binder = mPowerManager->asBinder();
1001 binder->unlinkToDeath(mDeathRecipient);
1002 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07001003}
1004
1005void AudioFlinger::ThreadBase::exit()
1006{
Steve Block3856b092011-10-20 11:56:00 +01001007 ALOGV("ThreadBase::exit");
Mathias Agopian65ab4712010-07-14 17:59:35 -07001008 {
Glenn Kastenb28686f2012-01-06 08:39:38 -08001009 // This lock prevents the following race in thread (uniprocessor for illustration):
1010 // if (!exitPending()) {
1011 // // context switch from here to exit()
1012 // // exit() calls requestExit(), what exitPending() observes
1013 // // exit() calls signal(), which is dropped since no waiters
1014 // // context switch back from exit() to here
1015 // mWaitWorkCV.wait(...);
1016 // // now thread is hung
1017 // }
Glenn Kastena7d8d6f2012-01-05 15:41:56 -08001018 AutoMutex lock(mLock);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001019 requestExit();
1020 mWaitWorkCV.signal();
1021 }
Glenn Kastenb28686f2012-01-06 08:39:38 -08001022 // When Thread::requestExitAndWait is made virtual and this method is renamed to
1023 // "virtual status_t requestExitAndWait()", replace by "return Thread::requestExitAndWait();"
Mathias Agopian65ab4712010-07-14 17:59:35 -07001024 requestExitAndWait();
1025}
1026
Mathias Agopian65ab4712010-07-14 17:59:35 -07001027status_t AudioFlinger::ThreadBase::setParameters(const String8& keyValuePairs)
1028{
1029 status_t status;
1030
Steve Block3856b092011-10-20 11:56:00 +01001031 ALOGV("ThreadBase::setParameters() %s", keyValuePairs.string());
Mathias Agopian65ab4712010-07-14 17:59:35 -07001032 Mutex::Autolock _l(mLock);
1033
1034 mNewParameters.add(keyValuePairs);
1035 mWaitWorkCV.signal();
1036 // wait condition with timeout in case the thread loop has exited
1037 // before the request could be processed
Glenn Kasten7dede872011-12-13 11:04:14 -08001038 if (mParamCond.waitRelative(mLock, kSetParametersTimeoutNs) == NO_ERROR) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001039 status = mParamStatus;
1040 mWaitWorkCV.signal();
1041 } else {
1042 status = TIMED_OUT;
1043 }
1044 return status;
1045}
1046
1047void AudioFlinger::ThreadBase::sendConfigEvent(int event, int param)
1048{
1049 Mutex::Autolock _l(mLock);
1050 sendConfigEvent_l(event, param);
1051}
1052
1053// sendConfigEvent_l() must be called with ThreadBase::mLock held
1054void AudioFlinger::ThreadBase::sendConfigEvent_l(int event, int param)
1055{
Glenn Kastenf3990f22011-12-13 11:50:00 -08001056 ConfigEvent configEvent;
1057 configEvent.mEvent = event;
1058 configEvent.mParam = param;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001059 mConfigEvents.add(configEvent);
Steve Block3856b092011-10-20 11:56:00 +01001060 ALOGV("sendConfigEvent() num events %d event %d, param %d", mConfigEvents.size(), event, param);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001061 mWaitWorkCV.signal();
1062}
1063
1064void AudioFlinger::ThreadBase::processConfigEvents()
1065{
1066 mLock.lock();
1067 while(!mConfigEvents.isEmpty()) {
Steve Block3856b092011-10-20 11:56:00 +01001068 ALOGV("processConfigEvents() remaining events %d", mConfigEvents.size());
Glenn Kastenf3990f22011-12-13 11:50:00 -08001069 ConfigEvent configEvent = mConfigEvents[0];
Mathias Agopian65ab4712010-07-14 17:59:35 -07001070 mConfigEvents.removeAt(0);
1071 // release mLock before locking AudioFlinger mLock: lock order is always
1072 // AudioFlinger then ThreadBase to avoid cross deadlock
1073 mLock.unlock();
1074 mAudioFlinger->mLock.lock();
Glenn Kastenf3990f22011-12-13 11:50:00 -08001075 audioConfigChanged_l(configEvent.mEvent, configEvent.mParam);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001076 mAudioFlinger->mLock.unlock();
Mathias Agopian65ab4712010-07-14 17:59:35 -07001077 mLock.lock();
1078 }
1079 mLock.unlock();
1080}
1081
1082status_t AudioFlinger::ThreadBase::dumpBase(int fd, const Vector<String16>& args)
1083{
1084 const size_t SIZE = 256;
1085 char buffer[SIZE];
1086 String8 result;
1087
1088 bool locked = tryLock(mLock);
1089 if (!locked) {
1090 snprintf(buffer, SIZE, "thread %p maybe dead locked\n", this);
1091 write(fd, buffer, strlen(buffer));
1092 }
1093
1094 snprintf(buffer, SIZE, "standby: %d\n", mStandby);
1095 result.append(buffer);
1096 snprintf(buffer, SIZE, "Sample rate: %d\n", mSampleRate);
1097 result.append(buffer);
1098 snprintf(buffer, SIZE, "Frame count: %d\n", mFrameCount);
1099 result.append(buffer);
1100 snprintf(buffer, SIZE, "Channel Count: %d\n", mChannelCount);
1101 result.append(buffer);
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07001102 snprintf(buffer, SIZE, "Channel Mask: 0x%08x\n", mChannelMask);
1103 result.append(buffer);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001104 snprintf(buffer, SIZE, "Format: %d\n", mFormat);
1105 result.append(buffer);
Glenn Kastenb9980652012-01-11 09:48:27 -08001106 snprintf(buffer, SIZE, "Frame size: %u\n", mFrameSize);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001107 result.append(buffer);
1108
1109 snprintf(buffer, SIZE, "\nPending setParameters commands: \n");
1110 result.append(buffer);
1111 result.append(" Index Command");
1112 for (size_t i = 0; i < mNewParameters.size(); ++i) {
1113 snprintf(buffer, SIZE, "\n %02d ", i);
1114 result.append(buffer);
1115 result.append(mNewParameters[i]);
1116 }
1117
1118 snprintf(buffer, SIZE, "\n\nPending config events: \n");
1119 result.append(buffer);
1120 snprintf(buffer, SIZE, " Index event param\n");
1121 result.append(buffer);
1122 for (size_t i = 0; i < mConfigEvents.size(); i++) {
Glenn Kastenf3990f22011-12-13 11:50:00 -08001123 snprintf(buffer, SIZE, " %02d %02d %d\n", i, mConfigEvents[i].mEvent, mConfigEvents[i].mParam);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001124 result.append(buffer);
1125 }
1126 result.append("\n");
1127
1128 write(fd, result.string(), result.size());
1129
1130 if (locked) {
1131 mLock.unlock();
1132 }
1133 return NO_ERROR;
1134}
1135
Eric Laurent1d2bff02011-07-24 17:49:51 -07001136status_t AudioFlinger::ThreadBase::dumpEffectChains(int fd, const Vector<String16>& args)
1137{
1138 const size_t SIZE = 256;
1139 char buffer[SIZE];
1140 String8 result;
1141
1142 snprintf(buffer, SIZE, "\n- %d Effect Chains:\n", mEffectChains.size());
1143 write(fd, buffer, strlen(buffer));
1144
1145 for (size_t i = 0; i < mEffectChains.size(); ++i) {
1146 sp<EffectChain> chain = mEffectChains[i];
1147 if (chain != 0) {
1148 chain->dump(fd, args);
1149 }
1150 }
1151 return NO_ERROR;
1152}
1153
Eric Laurentfeb0db62011-07-22 09:04:31 -07001154void AudioFlinger::ThreadBase::acquireWakeLock()
1155{
1156 Mutex::Autolock _l(mLock);
1157 acquireWakeLock_l();
1158}
1159
1160void AudioFlinger::ThreadBase::acquireWakeLock_l()
1161{
1162 if (mPowerManager == 0) {
1163 // use checkService() to avoid blocking if power service is not up yet
1164 sp<IBinder> binder =
1165 defaultServiceManager()->checkService(String16("power"));
1166 if (binder == 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00001167 ALOGW("Thread %s cannot connect to the power manager service", mName);
Eric Laurentfeb0db62011-07-22 09:04:31 -07001168 } else {
1169 mPowerManager = interface_cast<IPowerManager>(binder);
1170 binder->linkToDeath(mDeathRecipient);
1171 }
1172 }
1173 if (mPowerManager != 0) {
1174 sp<IBinder> binder = new BBinder();
1175 status_t status = mPowerManager->acquireWakeLock(POWERMANAGER_PARTIAL_WAKE_LOCK,
1176 binder,
1177 String16(mName));
1178 if (status == NO_ERROR) {
1179 mWakeLockToken = binder;
1180 }
Steve Block3856b092011-10-20 11:56:00 +01001181 ALOGV("acquireWakeLock_l() %s status %d", mName, status);
Eric Laurentfeb0db62011-07-22 09:04:31 -07001182 }
1183}
1184
1185void AudioFlinger::ThreadBase::releaseWakeLock()
1186{
1187 Mutex::Autolock _l(mLock);
Eric Laurent6dbe8832011-07-28 13:59:02 -07001188 releaseWakeLock_l();
Eric Laurentfeb0db62011-07-22 09:04:31 -07001189}
1190
1191void AudioFlinger::ThreadBase::releaseWakeLock_l()
1192{
1193 if (mWakeLockToken != 0) {
Steve Block3856b092011-10-20 11:56:00 +01001194 ALOGV("releaseWakeLock_l() %s", mName);
Eric Laurentfeb0db62011-07-22 09:04:31 -07001195 if (mPowerManager != 0) {
1196 mPowerManager->releaseWakeLock(mWakeLockToken, 0);
1197 }
1198 mWakeLockToken.clear();
1199 }
1200}
1201
1202void AudioFlinger::ThreadBase::clearPowerManager()
1203{
1204 Mutex::Autolock _l(mLock);
1205 releaseWakeLock_l();
1206 mPowerManager.clear();
1207}
1208
1209void AudioFlinger::ThreadBase::PMDeathRecipient::binderDied(const wp<IBinder>& who)
1210{
1211 sp<ThreadBase> thread = mThread.promote();
1212 if (thread != 0) {
1213 thread->clearPowerManager();
1214 }
Steve Block5ff1dd52012-01-05 23:22:43 +00001215 ALOGW("power manager service died !!!");
Eric Laurentfeb0db62011-07-22 09:04:31 -07001216}
Eric Laurent1d2bff02011-07-24 17:49:51 -07001217
Eric Laurent59255e42011-07-27 19:49:51 -07001218void AudioFlinger::ThreadBase::setEffectSuspended(
1219 const effect_uuid_t *type, bool suspend, int sessionId)
1220{
1221 Mutex::Autolock _l(mLock);
1222 setEffectSuspended_l(type, suspend, sessionId);
1223}
1224
1225void AudioFlinger::ThreadBase::setEffectSuspended_l(
1226 const effect_uuid_t *type, bool suspend, int sessionId)
1227{
Glenn Kasten090f0192012-01-30 13:00:02 -08001228 sp<EffectChain> chain = getEffectChain_l(sessionId);
Eric Laurent59255e42011-07-27 19:49:51 -07001229 if (chain != 0) {
1230 if (type != NULL) {
1231 chain->setEffectSuspended_l(type, suspend);
1232 } else {
1233 chain->setEffectSuspendedAll_l(suspend);
1234 }
1235 }
1236
1237 updateSuspendedSessions_l(type, suspend, sessionId);
1238}
1239
1240void AudioFlinger::ThreadBase::checkSuspendOnAddEffectChain_l(const sp<EffectChain>& chain)
1241{
Glenn Kasten8d6a2442012-02-08 14:04:28 -08001242 ssize_t index = mSuspendedSessions.indexOfKey(chain->sessionId());
Eric Laurent59255e42011-07-27 19:49:51 -07001243 if (index < 0) {
1244 return;
1245 }
1246
1247 KeyedVector <int, sp<SuspendedSessionDesc> > sessionEffects =
1248 mSuspendedSessions.editValueAt(index);
1249
1250 for (size_t i = 0; i < sessionEffects.size(); i++) {
1251 sp <SuspendedSessionDesc> desc = sessionEffects.valueAt(i);
1252 for (int j = 0; j < desc->mRefCount; j++) {
1253 if (sessionEffects.keyAt(i) == EffectChain::kKeyForSuspendAll) {
1254 chain->setEffectSuspendedAll_l(true);
1255 } else {
Steve Block3856b092011-10-20 11:56:00 +01001256 ALOGV("checkSuspendOnAddEffectChain_l() suspending effects %08x",
Eric Laurent59255e42011-07-27 19:49:51 -07001257 desc->mType.timeLow);
1258 chain->setEffectSuspended_l(&desc->mType, true);
1259 }
1260 }
1261 }
1262}
1263
Eric Laurent59255e42011-07-27 19:49:51 -07001264void AudioFlinger::ThreadBase::updateSuspendedSessions_l(const effect_uuid_t *type,
1265 bool suspend,
1266 int sessionId)
1267{
Glenn Kasten8d6a2442012-02-08 14:04:28 -08001268 ssize_t index = mSuspendedSessions.indexOfKey(sessionId);
Eric Laurent59255e42011-07-27 19:49:51 -07001269
1270 KeyedVector <int, sp<SuspendedSessionDesc> > sessionEffects;
1271
1272 if (suspend) {
1273 if (index >= 0) {
1274 sessionEffects = mSuspendedSessions.editValueAt(index);
1275 } else {
1276 mSuspendedSessions.add(sessionId, sessionEffects);
1277 }
1278 } else {
1279 if (index < 0) {
1280 return;
1281 }
1282 sessionEffects = mSuspendedSessions.editValueAt(index);
1283 }
1284
1285
1286 int key = EffectChain::kKeyForSuspendAll;
1287 if (type != NULL) {
1288 key = type->timeLow;
1289 }
1290 index = sessionEffects.indexOfKey(key);
1291
1292 sp <SuspendedSessionDesc> desc;
1293 if (suspend) {
1294 if (index >= 0) {
1295 desc = sessionEffects.valueAt(index);
1296 } else {
1297 desc = new SuspendedSessionDesc();
1298 if (type != NULL) {
1299 memcpy(&desc->mType, type, sizeof(effect_uuid_t));
1300 }
1301 sessionEffects.add(key, desc);
Steve Block3856b092011-10-20 11:56:00 +01001302 ALOGV("updateSuspendedSessions_l() suspend adding effect %08x", key);
Eric Laurent59255e42011-07-27 19:49:51 -07001303 }
1304 desc->mRefCount++;
1305 } else {
1306 if (index < 0) {
1307 return;
1308 }
1309 desc = sessionEffects.valueAt(index);
1310 if (--desc->mRefCount == 0) {
Steve Block3856b092011-10-20 11:56:00 +01001311 ALOGV("updateSuspendedSessions_l() restore removing effect %08x", key);
Eric Laurent59255e42011-07-27 19:49:51 -07001312 sessionEffects.removeItemsAt(index);
1313 if (sessionEffects.isEmpty()) {
Steve Block3856b092011-10-20 11:56:00 +01001314 ALOGV("updateSuspendedSessions_l() restore removing session %d",
Eric Laurent59255e42011-07-27 19:49:51 -07001315 sessionId);
1316 mSuspendedSessions.removeItem(sessionId);
1317 }
1318 }
1319 }
1320 if (!sessionEffects.isEmpty()) {
1321 mSuspendedSessions.replaceValueFor(sessionId, sessionEffects);
1322 }
1323}
1324
1325void AudioFlinger::ThreadBase::checkSuspendOnEffectEnabled(const sp<EffectModule>& effect,
1326 bool enabled,
1327 int sessionId)
1328{
1329 Mutex::Autolock _l(mLock);
Eric Laurenta85a74a2011-10-19 11:44:54 -07001330 checkSuspendOnEffectEnabled_l(effect, enabled, sessionId);
1331}
Eric Laurent59255e42011-07-27 19:49:51 -07001332
Eric Laurenta85a74a2011-10-19 11:44:54 -07001333void AudioFlinger::ThreadBase::checkSuspendOnEffectEnabled_l(const sp<EffectModule>& effect,
1334 bool enabled,
1335 int sessionId)
1336{
Eric Laurentdb7c0792011-08-10 10:37:50 -07001337 if (mType != RECORD) {
1338 // suspend all effects in AUDIO_SESSION_OUTPUT_MIX when enabling any effect on
1339 // another session. This gives the priority to well behaved effect control panels
1340 // and applications not using global effects.
1341 if (sessionId != AUDIO_SESSION_OUTPUT_MIX) {
1342 setEffectSuspended_l(NULL, enabled, AUDIO_SESSION_OUTPUT_MIX);
1343 }
1344 }
Eric Laurent59255e42011-07-27 19:49:51 -07001345
1346 sp<EffectChain> chain = getEffectChain_l(sessionId);
1347 if (chain != 0) {
1348 chain->checkSuspendOnEffectEnabled(effect, enabled);
1349 }
1350}
1351
Mathias Agopian65ab4712010-07-14 17:59:35 -07001352// ----------------------------------------------------------------------------
1353
Eric Laurent7c7f10b2011-06-17 21:29:58 -07001354AudioFlinger::PlaybackThread::PlaybackThread(const sp<AudioFlinger>& audioFlinger,
1355 AudioStreamOut* output,
Glenn Kasten72ef00d2012-01-17 11:09:42 -08001356 audio_io_handle_t id,
Glenn Kasten23bb8be2012-01-26 10:38:26 -08001357 uint32_t device,
1358 type_t type)
1359 : ThreadBase(audioFlinger, id, device, type),
Glenn Kasten84afa3b2012-01-25 15:28:08 -08001360 mMixBuffer(NULL), mSuspended(0), mBytesWritten(0),
1361 // Assumes constructor is called by AudioFlinger with it's mLock held,
1362 // but it would be safer to explicitly pass initial masterMute as parameter
1363 mMasterMute(audioFlinger->masterMute_l()),
1364 // mStreamTypes[] initialized in constructor body
1365 mOutput(output),
1366 // Assumes constructor is called by AudioFlinger with it's mLock held,
1367 // but it would be safer to explicitly pass initial masterVolume as parameter
1368 mMasterVolume(audioFlinger->masterVolume_l()),
Eric Laurent7c7f10b2011-06-17 21:29:58 -07001369 mLastWriteTime(0), mNumWrites(0), mNumDelayedWrites(0), mInWrite(false)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001370{
Eric Laurentfeb0db62011-07-22 09:04:31 -07001371 snprintf(mName, kNameLength, "AudioOut_%d", id);
1372
Mathias Agopian65ab4712010-07-14 17:59:35 -07001373 readOutputParameters();
1374
Glenn Kasten263709e2012-01-06 08:40:01 -08001375 // mStreamTypes[AUDIO_STREAM_CNT] is initialized by stream_type_t default constructor
Glenn Kastenfff6d712012-01-12 16:38:12 -08001376 // There is no AUDIO_STREAM_MIN, and ++ operator does not compile
1377 for (audio_stream_type_t stream = (audio_stream_type_t) 0; stream < AUDIO_STREAM_CNT;
1378 stream = (audio_stream_type_t) (stream + 1)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001379 mStreamTypes[stream].volume = mAudioFlinger->streamVolumeInternal(stream);
1380 mStreamTypes[stream].mute = mAudioFlinger->streamMute(stream);
Glenn Kasten263709e2012-01-06 08:40:01 -08001381 // initialized by stream_type_t default constructor
1382 // mStreamTypes[stream].valid = true;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001383 }
1384}
1385
1386AudioFlinger::PlaybackThread::~PlaybackThread()
1387{
1388 delete [] mMixBuffer;
1389}
1390
1391status_t AudioFlinger::PlaybackThread::dump(int fd, const Vector<String16>& args)
1392{
1393 dumpInternals(fd, args);
1394 dumpTracks(fd, args);
1395 dumpEffectChains(fd, args);
1396 return NO_ERROR;
1397}
1398
1399status_t AudioFlinger::PlaybackThread::dumpTracks(int fd, const Vector<String16>& args)
1400{
1401 const size_t SIZE = 256;
1402 char buffer[SIZE];
1403 String8 result;
1404
1405 snprintf(buffer, SIZE, "Output thread %p tracks\n", this);
1406 result.append(buffer);
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07001407 result.append(" Name Clien Typ Fmt Chn mask Session Buf S M F SRate LeftV RighV Serv User Main buf Aux Buf\n");
Mathias Agopian65ab4712010-07-14 17:59:35 -07001408 for (size_t i = 0; i < mTracks.size(); ++i) {
1409 sp<Track> track = mTracks[i];
1410 if (track != 0) {
1411 track->dump(buffer, SIZE);
1412 result.append(buffer);
1413 }
1414 }
1415
1416 snprintf(buffer, SIZE, "Output thread %p active tracks\n", this);
1417 result.append(buffer);
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07001418 result.append(" Name Clien Typ Fmt Chn mask Session Buf S M F SRate LeftV RighV Serv User Main buf Aux Buf\n");
Mathias Agopian65ab4712010-07-14 17:59:35 -07001419 for (size_t i = 0; i < mActiveTracks.size(); ++i) {
Glenn Kasten77c11192012-01-25 14:27:41 -08001420 sp<Track> track = mActiveTracks[i].promote();
1421 if (track != 0) {
1422 track->dump(buffer, SIZE);
1423 result.append(buffer);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001424 }
1425 }
1426 write(fd, result.string(), result.size());
1427 return NO_ERROR;
1428}
1429
Mathias Agopian65ab4712010-07-14 17:59:35 -07001430status_t AudioFlinger::PlaybackThread::dumpInternals(int fd, const Vector<String16>& args)
1431{
1432 const size_t SIZE = 256;
1433 char buffer[SIZE];
1434 String8 result;
1435
1436 snprintf(buffer, SIZE, "\nOutput thread %p internals\n", this);
1437 result.append(buffer);
1438 snprintf(buffer, SIZE, "last write occurred (msecs): %llu\n", ns2ms(systemTime() - mLastWriteTime));
1439 result.append(buffer);
1440 snprintf(buffer, SIZE, "total writes: %d\n", mNumWrites);
1441 result.append(buffer);
1442 snprintf(buffer, SIZE, "delayed writes: %d\n", mNumDelayedWrites);
1443 result.append(buffer);
1444 snprintf(buffer, SIZE, "blocked in write: %d\n", mInWrite);
1445 result.append(buffer);
1446 snprintf(buffer, SIZE, "suspend count: %d\n", mSuspended);
1447 result.append(buffer);
1448 snprintf(buffer, SIZE, "mix buffer : %p\n", mMixBuffer);
1449 result.append(buffer);
1450 write(fd, result.string(), result.size());
1451
1452 dumpBase(fd, args);
1453
1454 return NO_ERROR;
1455}
1456
1457// Thread virtuals
1458status_t AudioFlinger::PlaybackThread::readyToRun()
1459{
Eric Laurentb8ba0a92011-08-07 16:32:26 -07001460 status_t status = initCheck();
1461 if (status == NO_ERROR) {
Steve Blockdf64d152012-01-04 20:05:49 +00001462 ALOGI("AudioFlinger's thread %p ready to run", this);
Eric Laurentb8ba0a92011-08-07 16:32:26 -07001463 } else {
Steve Block29357bc2012-01-06 19:20:56 +00001464 ALOGE("No working audio driver found.");
Mathias Agopian65ab4712010-07-14 17:59:35 -07001465 }
Eric Laurentb8ba0a92011-08-07 16:32:26 -07001466 return status;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001467}
1468
1469void AudioFlinger::PlaybackThread::onFirstRef()
1470{
Eric Laurentfeb0db62011-07-22 09:04:31 -07001471 run(mName, ANDROID_PRIORITY_URGENT_AUDIO);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001472}
1473
1474// PlaybackThread::createTrack_l() must be called with AudioFlinger::mLock held
1475sp<AudioFlinger::PlaybackThread::Track> AudioFlinger::PlaybackThread::createTrack_l(
1476 const sp<AudioFlinger::Client>& client,
Glenn Kastenfff6d712012-01-12 16:38:12 -08001477 audio_stream_type_t streamType,
Mathias Agopian65ab4712010-07-14 17:59:35 -07001478 uint32_t sampleRate,
Glenn Kasten58f30212012-01-12 12:27:51 -08001479 audio_format_t format,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07001480 uint32_t channelMask,
Mathias Agopian65ab4712010-07-14 17:59:35 -07001481 int frameCount,
1482 const sp<IMemory>& sharedBuffer,
1483 int sessionId,
1484 status_t *status)
1485{
1486 sp<Track> track;
1487 status_t lStatus;
1488
1489 if (mType == DIRECT) {
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07001490 if ((format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM) {
1491 if (sampleRate != mSampleRate || format != mFormat || channelMask != mChannelMask) {
Steve Block29357bc2012-01-06 19:20:56 +00001492 ALOGE("createTrack_l() Bad parameter: sampleRate %d format %d, channelMask 0x%08x \""
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07001493 "for output %p with format %d",
1494 sampleRate, format, channelMask, mOutput, mFormat);
1495 lStatus = BAD_VALUE;
1496 goto Exit;
1497 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07001498 }
1499 } else {
1500 // Resampler implementation limits input sampling rate to 2 x output sampling rate.
1501 if (sampleRate > mSampleRate*2) {
Steve Block29357bc2012-01-06 19:20:56 +00001502 ALOGE("Sample rate out of range: %d mSampleRate %d", sampleRate, mSampleRate);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001503 lStatus = BAD_VALUE;
1504 goto Exit;
1505 }
1506 }
1507
Eric Laurent7c7f10b2011-06-17 21:29:58 -07001508 lStatus = initCheck();
1509 if (lStatus != NO_ERROR) {
Steve Block29357bc2012-01-06 19:20:56 +00001510 ALOGE("Audio driver not initialized.");
Mathias Agopian65ab4712010-07-14 17:59:35 -07001511 goto Exit;
1512 }
1513
1514 { // scope for mLock
1515 Mutex::Autolock _l(mLock);
Eric Laurentde070132010-07-13 04:45:46 -07001516
1517 // all tracks in same audio session must share the same routing strategy otherwise
1518 // conflicts will happen when tracks are moved from one output to another by audio policy
1519 // manager
Glenn Kasten02bbd202012-02-08 12:35:35 -08001520 uint32_t strategy = AudioSystem::getStrategyForStream(streamType);
Eric Laurentde070132010-07-13 04:45:46 -07001521 for (size_t i = 0; i < mTracks.size(); ++i) {
1522 sp<Track> t = mTracks[i];
1523 if (t != 0) {
Glenn Kasten02bbd202012-02-08 12:35:35 -08001524 uint32_t actual = AudioSystem::getStrategyForStream(t->streamType());
Glenn Kastend8796012011-10-28 10:31:42 -07001525 if (sessionId == t->sessionId() && strategy != actual) {
Steve Block29357bc2012-01-06 19:20:56 +00001526 ALOGE("createTrack_l() mismatched strategy; expected %u but found %u",
Glenn Kastend8796012011-10-28 10:31:42 -07001527 strategy, actual);
Eric Laurentde070132010-07-13 04:45:46 -07001528 lStatus = BAD_VALUE;
1529 goto Exit;
1530 }
1531 }
1532 }
1533
Mathias Agopian65ab4712010-07-14 17:59:35 -07001534 track = new Track(this, client, streamType, sampleRate, format,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07001535 channelMask, frameCount, sharedBuffer, sessionId);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001536 if (track->getCblk() == NULL || track->name() < 0) {
1537 lStatus = NO_MEMORY;
1538 goto Exit;
1539 }
1540 mTracks.add(track);
1541
1542 sp<EffectChain> chain = getEffectChain_l(sessionId);
1543 if (chain != 0) {
Steve Block3856b092011-10-20 11:56:00 +01001544 ALOGV("createTrack_l() setting main buffer %p", chain->inBuffer());
Mathias Agopian65ab4712010-07-14 17:59:35 -07001545 track->setMainBuffer(chain->inBuffer());
Glenn Kasten02bbd202012-02-08 12:35:35 -08001546 chain->setStrategy(AudioSystem::getStrategyForStream(track->streamType()));
Eric Laurentb469b942011-05-09 12:09:06 -07001547 chain->incTrackCnt();
Mathias Agopian65ab4712010-07-14 17:59:35 -07001548 }
Eric Laurent9f6530f2011-08-30 10:18:54 -07001549
1550 // invalidate track immediately if the stream type was moved to another thread since
1551 // createTrack() was called by the client process.
1552 if (!mStreamTypes[streamType].valid) {
Steve Block5ff1dd52012-01-05 23:22:43 +00001553 ALOGW("createTrack_l() on thread %p: invalidating track on stream %d",
Eric Laurent9f6530f2011-08-30 10:18:54 -07001554 this, streamType);
1555 android_atomic_or(CBLK_INVALID_ON, &track->mCblk->flags);
1556 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07001557 }
1558 lStatus = NO_ERROR;
1559
1560Exit:
1561 if(status) {
1562 *status = lStatus;
1563 }
1564 return track;
1565}
1566
1567uint32_t AudioFlinger::PlaybackThread::latency() const
1568{
Eric Laurentb8ba0a92011-08-07 16:32:26 -07001569 Mutex::Autolock _l(mLock);
1570 if (initCheck() == NO_ERROR) {
Dima Zavin799a70e2011-04-18 16:57:27 -07001571 return mOutput->stream->get_latency(mOutput->stream);
Eric Laurentb8ba0a92011-08-07 16:32:26 -07001572 } else {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001573 return 0;
1574 }
1575}
1576
1577status_t AudioFlinger::PlaybackThread::setMasterVolume(float value)
1578{
Mathias Agopian65ab4712010-07-14 17:59:35 -07001579 mMasterVolume = value;
1580 return NO_ERROR;
1581}
1582
1583status_t AudioFlinger::PlaybackThread::setMasterMute(bool muted)
1584{
Mathias Agopian65ab4712010-07-14 17:59:35 -07001585 mMasterMute = muted;
1586 return NO_ERROR;
1587}
1588
Glenn Kastenfff6d712012-01-12 16:38:12 -08001589status_t AudioFlinger::PlaybackThread::setStreamVolume(audio_stream_type_t stream, float value)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001590{
Mathias Agopian65ab4712010-07-14 17:59:35 -07001591 mStreamTypes[stream].volume = value;
1592 return NO_ERROR;
1593}
1594
Glenn Kastenfff6d712012-01-12 16:38:12 -08001595status_t AudioFlinger::PlaybackThread::setStreamMute(audio_stream_type_t stream, bool muted)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001596{
Mathias Agopian65ab4712010-07-14 17:59:35 -07001597 mStreamTypes[stream].mute = muted;
1598 return NO_ERROR;
1599}
1600
Glenn Kastenfff6d712012-01-12 16:38:12 -08001601float AudioFlinger::PlaybackThread::streamVolume(audio_stream_type_t stream) const
Mathias Agopian65ab4712010-07-14 17:59:35 -07001602{
1603 return mStreamTypes[stream].volume;
1604}
1605
Glenn Kastenfff6d712012-01-12 16:38:12 -08001606bool AudioFlinger::PlaybackThread::streamMute(audio_stream_type_t stream) const
Mathias Agopian65ab4712010-07-14 17:59:35 -07001607{
1608 return mStreamTypes[stream].mute;
1609}
1610
Mathias Agopian65ab4712010-07-14 17:59:35 -07001611// addTrack_l() must be called with ThreadBase::mLock held
1612status_t AudioFlinger::PlaybackThread::addTrack_l(const sp<Track>& track)
1613{
1614 status_t status = ALREADY_EXISTS;
1615
1616 // set retry count for buffer fill
1617 track->mRetryCount = kMaxTrackStartupRetries;
1618 if (mActiveTracks.indexOf(track) < 0) {
1619 // the track is newly added, make sure it fills up all its
1620 // buffers before playing. This is to ensure the client will
1621 // effectively get the latency it requested.
1622 track->mFillingUpStatus = Track::FS_FILLING;
1623 track->mResetDone = false;
1624 mActiveTracks.add(track);
1625 if (track->mainBuffer() != mMixBuffer) {
1626 sp<EffectChain> chain = getEffectChain_l(track->sessionId());
1627 if (chain != 0) {
Steve Block3856b092011-10-20 11:56:00 +01001628 ALOGV("addTrack_l() starting track on chain %p for session %d", chain.get(), track->sessionId());
Eric Laurentb469b942011-05-09 12:09:06 -07001629 chain->incActiveTrackCnt();
Mathias Agopian65ab4712010-07-14 17:59:35 -07001630 }
1631 }
1632
1633 status = NO_ERROR;
1634 }
1635
Steve Block3856b092011-10-20 11:56:00 +01001636 ALOGV("mWaitWorkCV.broadcast");
Mathias Agopian65ab4712010-07-14 17:59:35 -07001637 mWaitWorkCV.broadcast();
1638
1639 return status;
1640}
1641
1642// destroyTrack_l() must be called with ThreadBase::mLock held
1643void AudioFlinger::PlaybackThread::destroyTrack_l(const sp<Track>& track)
1644{
1645 track->mState = TrackBase::TERMINATED;
1646 if (mActiveTracks.indexOf(track) < 0) {
Eric Laurentb469b942011-05-09 12:09:06 -07001647 removeTrack_l(track);
1648 }
1649}
1650
1651void AudioFlinger::PlaybackThread::removeTrack_l(const sp<Track>& track)
1652{
1653 mTracks.remove(track);
1654 deleteTrackName_l(track->name());
1655 sp<EffectChain> chain = getEffectChain_l(track->sessionId());
1656 if (chain != 0) {
1657 chain->decTrackCnt();
Mathias Agopian65ab4712010-07-14 17:59:35 -07001658 }
1659}
1660
1661String8 AudioFlinger::PlaybackThread::getParameters(const String8& keys)
1662{
Eric Laurentb8ba0a92011-08-07 16:32:26 -07001663 String8 out_s8 = String8("");
Dima Zavinfce7a472011-04-19 22:30:36 -07001664 char *s;
1665
Eric Laurentb8ba0a92011-08-07 16:32:26 -07001666 Mutex::Autolock _l(mLock);
1667 if (initCheck() != NO_ERROR) {
1668 return out_s8;
1669 }
1670
Dima Zavin799a70e2011-04-18 16:57:27 -07001671 s = mOutput->stream->common.get_parameters(&mOutput->stream->common, keys.string());
Dima Zavinfce7a472011-04-19 22:30:36 -07001672 out_s8 = String8(s);
1673 free(s);
1674 return out_s8;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001675}
1676
Eric Laurentb8ba0a92011-08-07 16:32:26 -07001677// audioConfigChanged_l() must be called with AudioFlinger::mLock held
Mathias Agopian65ab4712010-07-14 17:59:35 -07001678void AudioFlinger::PlaybackThread::audioConfigChanged_l(int event, int param) {
1679 AudioSystem::OutputDescriptor desc;
Glenn Kastena0d68332012-01-27 16:47:15 -08001680 void *param2 = NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001681
Steve Block3856b092011-10-20 11:56:00 +01001682 ALOGV("PlaybackThread::audioConfigChanged_l, thread %p, event %d, param %d", this, event, param);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001683
1684 switch (event) {
1685 case AudioSystem::OUTPUT_OPENED:
1686 case AudioSystem::OUTPUT_CONFIG_CHANGED:
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07001687 desc.channels = mChannelMask;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001688 desc.samplingRate = mSampleRate;
1689 desc.format = mFormat;
1690 desc.frameCount = mFrameCount;
1691 desc.latency = latency();
1692 param2 = &desc;
1693 break;
1694
1695 case AudioSystem::STREAM_CONFIG_CHANGED:
1696 param2 = &param;
1697 case AudioSystem::OUTPUT_CLOSED:
1698 default:
1699 break;
1700 }
1701 mAudioFlinger->audioConfigChanged_l(event, mId, param2);
1702}
1703
1704void AudioFlinger::PlaybackThread::readOutputParameters()
1705{
Dima Zavin799a70e2011-04-18 16:57:27 -07001706 mSampleRate = mOutput->stream->common.get_sample_rate(&mOutput->stream->common);
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07001707 mChannelMask = mOutput->stream->common.get_channels(&mOutput->stream->common);
1708 mChannelCount = (uint16_t)popcount(mChannelMask);
Dima Zavin799a70e2011-04-18 16:57:27 -07001709 mFormat = mOutput->stream->common.get_format(&mOutput->stream->common);
Glenn Kastenb9980652012-01-11 09:48:27 -08001710 mFrameSize = audio_stream_frame_size(&mOutput->stream->common);
Dima Zavin799a70e2011-04-18 16:57:27 -07001711 mFrameCount = mOutput->stream->common.get_buffer_size(&mOutput->stream->common) / mFrameSize;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001712
1713 // FIXME - Current mixer implementation only supports stereo output: Always
1714 // Allocate a stereo buffer even if HW output is mono.
Glenn Kastene9dd0172012-01-27 18:08:45 -08001715 delete[] mMixBuffer;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001716 mMixBuffer = new int16_t[mFrameCount * 2];
1717 memset(mMixBuffer, 0, mFrameCount * 2 * sizeof(int16_t));
1718
Eric Laurentde070132010-07-13 04:45:46 -07001719 // force reconfiguration of effect chains and engines to take new buffer size and audio
1720 // parameters into account
1721 // Note that mLock is not held when readOutputParameters() is called from the constructor
1722 // but in this case nothing is done below as no audio sessions have effect yet so it doesn't
1723 // matter.
1724 // create a copy of mEffectChains as calling moveEffectChain_l() can reorder some effect chains
1725 Vector< sp<EffectChain> > effectChains = mEffectChains;
1726 for (size_t i = 0; i < effectChains.size(); i ++) {
Eric Laurent39e94f82010-07-28 01:32:47 -07001727 mAudioFlinger->moveEffectChain_l(effectChains[i]->sessionId(), this, this, false);
Eric Laurentde070132010-07-13 04:45:46 -07001728 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07001729}
1730
1731status_t AudioFlinger::PlaybackThread::getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames)
1732{
Glenn Kastena0d68332012-01-27 16:47:15 -08001733 if (halFrames == NULL || dspFrames == NULL) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001734 return BAD_VALUE;
1735 }
Eric Laurentb8ba0a92011-08-07 16:32:26 -07001736 Mutex::Autolock _l(mLock);
Eric Laurent7c7f10b2011-06-17 21:29:58 -07001737 if (initCheck() != NO_ERROR) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001738 return INVALID_OPERATION;
1739 }
Dima Zavin799a70e2011-04-18 16:57:27 -07001740 *halFrames = mBytesWritten / audio_stream_frame_size(&mOutput->stream->common);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001741
Dima Zavin799a70e2011-04-18 16:57:27 -07001742 return mOutput->stream->get_render_position(mOutput->stream, dspFrames);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001743}
1744
Eric Laurent39e94f82010-07-28 01:32:47 -07001745uint32_t AudioFlinger::PlaybackThread::hasAudioSession(int sessionId)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001746{
1747 Mutex::Autolock _l(mLock);
Eric Laurent39e94f82010-07-28 01:32:47 -07001748 uint32_t result = 0;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001749 if (getEffectChain_l(sessionId) != 0) {
Eric Laurent39e94f82010-07-28 01:32:47 -07001750 result = EFFECT_SESSION;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001751 }
1752
1753 for (size_t i = 0; i < mTracks.size(); ++i) {
1754 sp<Track> track = mTracks[i];
Eric Laurentde070132010-07-13 04:45:46 -07001755 if (sessionId == track->sessionId() &&
1756 !(track->mCblk->flags & CBLK_INVALID_MSK)) {
Eric Laurent39e94f82010-07-28 01:32:47 -07001757 result |= TRACK_SESSION;
1758 break;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001759 }
1760 }
1761
Eric Laurent39e94f82010-07-28 01:32:47 -07001762 return result;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001763}
1764
Eric Laurentde070132010-07-13 04:45:46 -07001765uint32_t AudioFlinger::PlaybackThread::getStrategyForSession_l(int sessionId)
1766{
Dima Zavinfce7a472011-04-19 22:30:36 -07001767 // session AUDIO_SESSION_OUTPUT_MIX is placed in same strategy as MUSIC stream so that
Eric Laurentde070132010-07-13 04:45:46 -07001768 // it is moved to correct output by audio policy manager when A2DP is connected or disconnected
Dima Zavinfce7a472011-04-19 22:30:36 -07001769 if (sessionId == AUDIO_SESSION_OUTPUT_MIX) {
1770 return AudioSystem::getStrategyForStream(AUDIO_STREAM_MUSIC);
Eric Laurentde070132010-07-13 04:45:46 -07001771 }
1772 for (size_t i = 0; i < mTracks.size(); i++) {
1773 sp<Track> track = mTracks[i];
1774 if (sessionId == track->sessionId() &&
1775 !(track->mCblk->flags & CBLK_INVALID_MSK)) {
Glenn Kasten02bbd202012-02-08 12:35:35 -08001776 return AudioSystem::getStrategyForStream(track->streamType());
Eric Laurentde070132010-07-13 04:45:46 -07001777 }
1778 }
Dima Zavinfce7a472011-04-19 22:30:36 -07001779 return AudioSystem::getStrategyForStream(AUDIO_STREAM_MUSIC);
Eric Laurentde070132010-07-13 04:45:46 -07001780}
1781
Mathias Agopian65ab4712010-07-14 17:59:35 -07001782
Glenn Kastenaed850d2012-01-26 09:46:34 -08001783AudioFlinger::AudioStreamOut* AudioFlinger::PlaybackThread::getOutput() const
Eric Laurentb8ba0a92011-08-07 16:32:26 -07001784{
1785 Mutex::Autolock _l(mLock);
1786 return mOutput;
1787}
1788
1789AudioFlinger::AudioStreamOut* AudioFlinger::PlaybackThread::clearOutput()
1790{
1791 Mutex::Autolock _l(mLock);
1792 AudioStreamOut *output = mOutput;
1793 mOutput = NULL;
1794 return output;
1795}
1796
1797// this method must always be called either with ThreadBase mLock held or inside the thread loop
1798audio_stream_t* AudioFlinger::PlaybackThread::stream()
1799{
1800 if (mOutput == NULL) {
1801 return NULL;
1802 }
1803 return &mOutput->stream->common;
1804}
1805
Eric Laurent162b40b2011-12-05 09:47:19 -08001806uint32_t AudioFlinger::PlaybackThread::activeSleepTimeUs()
1807{
1808 // A2DP output latency is not due only to buffering capacity. It also reflects encoding,
1809 // decoding and transfer time. So sleeping for half of the latency would likely cause
1810 // underruns
1811 if (audio_is_a2dp_device((audio_devices_t)mDevice)) {
1812 return (uint32_t)((uint32_t)((mFrameCount * 1000) / mSampleRate) * 1000);
1813 } else {
1814 return (uint32_t)(mOutput->stream->get_latency(mOutput->stream) * 1000) / 2;
1815 }
1816}
1817
Mathias Agopian65ab4712010-07-14 17:59:35 -07001818// ----------------------------------------------------------------------------
1819
Glenn Kasten23bb8be2012-01-26 10:38:26 -08001820AudioFlinger::MixerThread::MixerThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output,
Glenn Kasten72ef00d2012-01-17 11:09:42 -08001821 audio_io_handle_t id, uint32_t device, type_t type)
Glenn Kasten23bb8be2012-01-26 10:38:26 -08001822 : PlaybackThread(audioFlinger, output, id, device, type),
Glenn Kasten84afa3b2012-01-25 15:28:08 -08001823 mAudioMixer(new AudioMixer(mFrameCount, mSampleRate)),
1824 mPrevMixerStatus(MIXER_IDLE)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001825{
Mathias Agopian65ab4712010-07-14 17:59:35 -07001826 // FIXME - Current mixer implementation only supports stereo output
1827 if (mChannelCount == 1) {
Steve Block29357bc2012-01-06 19:20:56 +00001828 ALOGE("Invalid audio hardware channel count");
Mathias Agopian65ab4712010-07-14 17:59:35 -07001829 }
1830}
1831
1832AudioFlinger::MixerThread::~MixerThread()
1833{
1834 delete mAudioMixer;
1835}
1836
1837bool AudioFlinger::MixerThread::threadLoop()
1838{
1839 Vector< sp<Track> > tracksToRemove;
Glenn Kasten29c23c32012-01-26 13:37:52 -08001840 mixer_state mixerStatus = MIXER_IDLE;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001841 nsecs_t standbyTime = systemTime();
1842 size_t mixBufferSize = mFrameCount * mFrameSize;
1843 // FIXME: Relaxed timing because of a certain device that can't meet latency
1844 // Should be reduced to 2x after the vendor fixes the driver issue
Eric Laurent5c4e8182011-10-18 15:42:27 -07001845 // increase threshold again due to low power audio mode. The way this warning threshold is
1846 // calculated and its usefulness should be reconsidered anyway.
1847 nsecs_t maxPeriod = seconds(mFrameCount) / mSampleRate * 15;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001848 nsecs_t lastWarning = 0;
1849 bool longStandbyExit = false;
1850 uint32_t activeSleepTime = activeSleepTimeUs();
1851 uint32_t idleSleepTime = idleSleepTimeUs();
1852 uint32_t sleepTime = idleSleepTime;
Eric Laurent7cafbb32011-11-22 18:50:29 -08001853 uint32_t sleepTimeShift = 0;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001854 Vector< sp<EffectChain> > effectChains;
Glenn Kasten4d8d0c32011-07-08 15:26:12 -07001855#ifdef DEBUG_CPU_USAGE
1856 ThreadCpuUsage cpu;
1857 const CentralTendencyStatistics& stats = cpu.statistics();
1858#endif
Mathias Agopian65ab4712010-07-14 17:59:35 -07001859
Eric Laurentfeb0db62011-07-22 09:04:31 -07001860 acquireWakeLock();
1861
Mathias Agopian65ab4712010-07-14 17:59:35 -07001862 while (!exitPending())
1863 {
Glenn Kasten4d8d0c32011-07-08 15:26:12 -07001864#ifdef DEBUG_CPU_USAGE
1865 cpu.sampleAndEnable();
1866 unsigned n = stats.n();
1867 // cpu.elapsed() is expensive, so don't call it every loop
1868 if ((n & 127) == 1) {
1869 long long elapsed = cpu.elapsed();
1870 if (elapsed >= DEBUG_CPU_USAGE * 1000000000LL) {
1871 double perLoop = elapsed / (double) n;
1872 double perLoop100 = perLoop * 0.01;
1873 double mean = stats.mean();
1874 double stddev = stats.stddev();
1875 double minimum = stats.minimum();
1876 double maximum = stats.maximum();
1877 cpu.resetStatistics();
Steve Blockdf64d152012-01-04 20:05:49 +00001878 ALOGI("CPU usage over past %.1f secs (%u mixer loops at %.1f mean ms per loop):\n us per mix loop: mean=%.0f stddev=%.0f min=%.0f max=%.0f\n %% of wall: mean=%.1f stddev=%.1f min=%.1f max=%.1f",
Glenn Kasten4d8d0c32011-07-08 15:26:12 -07001879 elapsed * .000000001, n, perLoop * .000001,
1880 mean * .001,
1881 stddev * .001,
1882 minimum * .001,
1883 maximum * .001,
1884 mean / perLoop100,
1885 stddev / perLoop100,
1886 minimum / perLoop100,
1887 maximum / perLoop100);
1888 }
1889 }
1890#endif
Mathias Agopian65ab4712010-07-14 17:59:35 -07001891 processConfigEvents();
1892
1893 mixerStatus = MIXER_IDLE;
1894 { // scope for mLock
1895
1896 Mutex::Autolock _l(mLock);
1897
1898 if (checkForNewParameters_l()) {
1899 mixBufferSize = mFrameCount * mFrameSize;
1900 // FIXME: Relaxed timing because of a certain device that can't meet latency
1901 // Should be reduced to 2x after the vendor fixes the driver issue
Eric Laurent5c4e8182011-10-18 15:42:27 -07001902 // increase threshold again due to low power audio mode. The way this warning
1903 // threshold is calculated and its usefulness should be reconsidered anyway.
1904 maxPeriod = seconds(mFrameCount) / mSampleRate * 15;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001905 activeSleepTime = activeSleepTimeUs();
1906 idleSleepTime = idleSleepTimeUs();
1907 }
1908
1909 const SortedVector< wp<Track> >& activeTracks = mActiveTracks;
1910
1911 // put audio hardware into standby after short delay
Glenn Kastenf6b16782011-12-15 09:51:17 -08001912 if (CC_UNLIKELY((!activeTracks.size() && systemTime() > standbyTime) ||
1913 mSuspended)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001914 if (!mStandby) {
Glenn Kasten90bebef2012-01-27 15:24:38 -08001915 ALOGV("Audio hardware entering standby, mixer %p, mSuspended %d", this, mSuspended);
Dima Zavin799a70e2011-04-18 16:57:27 -07001916 mOutput->stream->common.standby(&mOutput->stream->common);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001917 mStandby = true;
1918 mBytesWritten = 0;
1919 }
1920
1921 if (!activeTracks.size() && mConfigEvents.isEmpty()) {
1922 // we're about to wait, flush the binder command buffer
1923 IPCThreadState::self()->flushCommands();
1924
1925 if (exitPending()) break;
1926
Eric Laurentfeb0db62011-07-22 09:04:31 -07001927 releaseWakeLock_l();
Mathias Agopian65ab4712010-07-14 17:59:35 -07001928 // wait until we have something to do...
Glenn Kasten90bebef2012-01-27 15:24:38 -08001929 ALOGV("MixerThread %p TID %d going to sleep", this, gettid());
Mathias Agopian65ab4712010-07-14 17:59:35 -07001930 mWaitWorkCV.wait(mLock);
Glenn Kasten90bebef2012-01-27 15:24:38 -08001931 ALOGV("MixerThread %p TID %d waking up", this, gettid());
Eric Laurentfeb0db62011-07-22 09:04:31 -07001932 acquireWakeLock_l();
Mathias Agopian65ab4712010-07-14 17:59:35 -07001933
Eric Laurent27741442012-01-17 19:20:12 -08001934 mPrevMixerStatus = MIXER_IDLE;
Glenn Kastenf1d45922012-01-13 15:54:24 -08001935 if (!mMasterMute) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001936 char value[PROPERTY_VALUE_MAX];
1937 property_get("ro.audio.silent", value, "0");
1938 if (atoi(value)) {
Steve Blockb8a80522011-12-20 16:23:08 +00001939 ALOGD("Silence is golden");
Mathias Agopian65ab4712010-07-14 17:59:35 -07001940 setMasterMute(true);
1941 }
1942 }
1943
1944 standbyTime = systemTime() + kStandbyTimeInNsecs;
1945 sleepTime = idleSleepTime;
Eric Laurent7cafbb32011-11-22 18:50:29 -08001946 sleepTimeShift = 0;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001947 continue;
1948 }
1949 }
1950
1951 mixerStatus = prepareTracks_l(activeTracks, &tracksToRemove);
1952
1953 // prevent any changes in effect chain list and in each effect chain
1954 // during mixing and effect process as the audio buffers could be deleted
1955 // or modified if an effect is created or deleted
Eric Laurentde070132010-07-13 04:45:46 -07001956 lockEffectChains_l(effectChains);
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -08001957 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07001958
Glenn Kastenf6b16782011-12-15 09:51:17 -08001959 if (CC_LIKELY(mixerStatus == MIXER_TRACKS_READY)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001960 // mix buffers...
1961 mAudioMixer->process();
Eric Laurent21e4b6e2012-01-23 18:56:59 -08001962 // increase sleep time progressively when application underrun condition clears.
1963 // Only increase sleep time if the mixer is ready for two consecutive times to avoid
1964 // that a steady state of alternating ready/not ready conditions keeps the sleep time
1965 // such that we would underrun the audio HAL.
1966 if ((sleepTime == 0) && (sleepTimeShift > 0)) {
Eric Laurent7cafbb32011-11-22 18:50:29 -08001967 sleepTimeShift--;
1968 }
Eric Laurent21e4b6e2012-01-23 18:56:59 -08001969 sleepTime = 0;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001970 standbyTime = systemTime() + kStandbyTimeInNsecs;
1971 //TODO: delay standby when effects have a tail
1972 } else {
1973 // If no tracks are ready, sleep once for the duration of an output
1974 // buffer size, then write 0s to the output
1975 if (sleepTime == 0) {
1976 if (mixerStatus == MIXER_TRACKS_ENABLED) {
Eric Laurent7cafbb32011-11-22 18:50:29 -08001977 sleepTime = activeSleepTime >> sleepTimeShift;
1978 if (sleepTime < kMinThreadSleepTimeUs) {
1979 sleepTime = kMinThreadSleepTimeUs;
1980 }
1981 // reduce sleep time in case of consecutive application underruns to avoid
1982 // starving the audio HAL. As activeSleepTimeUs() is larger than a buffer
1983 // duration we would end up writing less data than needed by the audio HAL if
1984 // the condition persists.
1985 if (sleepTimeShift < kMaxThreadSleepTimeShift) {
1986 sleepTimeShift++;
1987 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07001988 } else {
1989 sleepTime = idleSleepTime;
1990 }
1991 } else if (mBytesWritten != 0 ||
1992 (mixerStatus == MIXER_TRACKS_ENABLED && longStandbyExit)) {
1993 memset (mMixBuffer, 0, mixBufferSize);
1994 sleepTime = 0;
Steve Block3856b092011-10-20 11:56:00 +01001995 ALOGV_IF((mBytesWritten == 0 && (mixerStatus == MIXER_TRACKS_ENABLED && longStandbyExit)), "anticipated start");
Mathias Agopian65ab4712010-07-14 17:59:35 -07001996 }
1997 // TODO add standby time extension fct of effect tail
1998 }
1999
2000 if (mSuspended) {
Eric Laurent25cbe0e2010-08-18 18:13:17 -07002001 sleepTime = suspendSleepTimeUs();
Mathias Agopian65ab4712010-07-14 17:59:35 -07002002 }
2003 // sleepTime == 0 means we must write to audio hardware
2004 if (sleepTime == 0) {
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -08002005 for (size_t i = 0; i < effectChains.size(); i ++) {
2006 effectChains[i]->process_l();
2007 }
2008 // enable changes in effect chain
2009 unlockEffectChains(effectChains);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002010 mLastWriteTime = systemTime();
2011 mInWrite = true;
2012 mBytesWritten += mixBufferSize;
2013
Dima Zavin799a70e2011-04-18 16:57:27 -07002014 int bytesWritten = (int)mOutput->stream->write(mOutput->stream, mMixBuffer, mixBufferSize);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002015 if (bytesWritten < 0) mBytesWritten -= mixBufferSize;
2016 mNumWrites++;
2017 mInWrite = false;
2018 nsecs_t now = systemTime();
2019 nsecs_t delta = now - mLastWriteTime;
Eric Laurent5c4e8182011-10-18 15:42:27 -07002020 if (!mStandby && delta > maxPeriod) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07002021 mNumDelayedWrites++;
Glenn Kasten7dede872011-12-13 11:04:14 -08002022 if ((now - lastWarning) > kWarningThrottleNs) {
Steve Block5ff1dd52012-01-05 23:22:43 +00002023 ALOGW("write blocked for %llu msecs, %d delayed writes, thread %p",
Mathias Agopian65ab4712010-07-14 17:59:35 -07002024 ns2ms(delta), mNumDelayedWrites, this);
2025 lastWarning = now;
2026 }
2027 if (mStandby) {
2028 longStandbyExit = true;
2029 }
2030 }
2031 mStandby = false;
2032 } else {
2033 // enable changes in effect chain
Eric Laurentde070132010-07-13 04:45:46 -07002034 unlockEffectChains(effectChains);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002035 usleep(sleepTime);
2036 }
2037
2038 // finally let go of all our tracks, without the lock held
2039 // since we can't guarantee the destructors won't acquire that
2040 // same lock.
2041 tracksToRemove.clear();
2042
2043 // Effect chains will be actually deleted here if they were removed from
2044 // mEffectChains list during mixing or effects processing
2045 effectChains.clear();
2046 }
2047
2048 if (!mStandby) {
Dima Zavin799a70e2011-04-18 16:57:27 -07002049 mOutput->stream->common.standby(&mOutput->stream->common);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002050 }
2051
Eric Laurentfeb0db62011-07-22 09:04:31 -07002052 releaseWakeLock();
2053
Steve Block3856b092011-10-20 11:56:00 +01002054 ALOGV("MixerThread %p exiting", this);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002055 return false;
2056}
2057
2058// prepareTracks_l() must be called with ThreadBase::mLock held
Glenn Kasten29c23c32012-01-26 13:37:52 -08002059AudioFlinger::PlaybackThread::mixer_state AudioFlinger::MixerThread::prepareTracks_l(
2060 const SortedVector< wp<Track> >& activeTracks, Vector< sp<Track> > *tracksToRemove)
Mathias Agopian65ab4712010-07-14 17:59:35 -07002061{
2062
Glenn Kasten29c23c32012-01-26 13:37:52 -08002063 mixer_state mixerStatus = MIXER_IDLE;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002064 // find out which tracks need to be processed
2065 size_t count = activeTracks.size();
2066 size_t mixedTracks = 0;
2067 size_t tracksWithEffect = 0;
2068
2069 float masterVolume = mMasterVolume;
2070 bool masterMute = mMasterMute;
2071
Eric Laurent571d49c2010-08-11 05:20:11 -07002072 if (masterMute) {
2073 masterVolume = 0;
2074 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07002075 // Delegate master volume control to effect in output mix effect chain if needed
Dima Zavinfce7a472011-04-19 22:30:36 -07002076 sp<EffectChain> chain = getEffectChain_l(AUDIO_SESSION_OUTPUT_MIX);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002077 if (chain != 0) {
Eric Laurent571d49c2010-08-11 05:20:11 -07002078 uint32_t v = (uint32_t)(masterVolume * (1 << 24));
Eric Laurentcab11242010-07-15 12:50:15 -07002079 chain->setVolume_l(&v, &v);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002080 masterVolume = (float)((v + (1 << 23)) >> 24);
2081 chain.clear();
2082 }
2083
2084 for (size_t i=0 ; i<count ; i++) {
2085 sp<Track> t = activeTracks[i].promote();
2086 if (t == 0) continue;
2087
Glenn Kasten9c56d4a2011-12-19 15:06:39 -08002088 // this const just means the local variable doesn't change
Mathias Agopian65ab4712010-07-14 17:59:35 -07002089 Track* const track = t.get();
2090 audio_track_cblk_t* cblk = track->cblk();
2091
2092 // The first time a track is added we wait
2093 // for all its buffers to be filled before processing it
Glenn Kasten9c56d4a2011-12-19 15:06:39 -08002094 int name = track->name();
Eric Laurenta47b69c2011-11-08 18:10:16 -08002095 // make sure that we have enough frames to mix one full buffer.
2096 // enforce this condition only once to enable draining the buffer in case the client
2097 // app does not call stop() and relies on underrun to stop:
Eric Laurent27741442012-01-17 19:20:12 -08002098 // hence the test on (mPrevMixerStatus == MIXER_TRACKS_READY) meaning the track was mixed
Eric Laurenta47b69c2011-11-08 18:10:16 -08002099 // during last round
Eric Laurent3dbe3202011-11-03 12:16:05 -07002100 uint32_t minFrames = 1;
Eric Laurenta47b69c2011-11-08 18:10:16 -08002101 if (!track->isStopped() && !track->isPausing() &&
Eric Laurent27741442012-01-17 19:20:12 -08002102 (mPrevMixerStatus == MIXER_TRACKS_READY)) {
Eric Laurent3dbe3202011-11-03 12:16:05 -07002103 if (t->sampleRate() == (int)mSampleRate) {
2104 minFrames = mFrameCount;
2105 } else {
Eric Laurent071ccd52011-12-22 16:08:41 -08002106 // +1 for rounding and +1 for additional sample needed for interpolation
2107 minFrames = (mFrameCount * t->sampleRate()) / mSampleRate + 1 + 1;
2108 // add frames already consumed but not yet released by the resampler
2109 // because cblk->framesReady() will include these frames
2110 minFrames += mAudioMixer->getUnreleasedFrames(track->name());
2111 // the minimum track buffer size is normally twice the number of frames necessary
2112 // to fill one buffer and the resampler should not leave more than one buffer worth
2113 // of unreleased frames after each pass, but just in case...
Steve Blockc1dc1cb2012-01-09 18:35:44 +00002114 ALOG_ASSERT(minFrames <= cblk->frameCount);
Eric Laurent3dbe3202011-11-03 12:16:05 -07002115 }
2116 }
2117 if ((cblk->framesReady() >= minFrames) && track->isReady() &&
Mathias Agopian65ab4712010-07-14 17:59:35 -07002118 !track->isPaused() && !track->isTerminated())
2119 {
Glenn Kasten9c56d4a2011-12-19 15:06:39 -08002120 //ALOGV("track %d u=%08x, s=%08x [OK] on thread %p", name, cblk->user, cblk->server, this);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002121
2122 mixedTracks++;
2123
2124 // track->mainBuffer() != mMixBuffer means there is an effect chain
2125 // connected to the track
2126 chain.clear();
2127 if (track->mainBuffer() != mMixBuffer) {
2128 chain = getEffectChain_l(track->sessionId());
2129 // Delegate volume control to effect in track effect chain if needed
2130 if (chain != 0) {
2131 tracksWithEffect++;
2132 } else {
Steve Block5ff1dd52012-01-05 23:22:43 +00002133 ALOGW("prepareTracks_l(): track %d attached to effect but no chain found on session %d",
Glenn Kasten9c56d4a2011-12-19 15:06:39 -08002134 name, track->sessionId());
Mathias Agopian65ab4712010-07-14 17:59:35 -07002135 }
2136 }
2137
2138
2139 int param = AudioMixer::VOLUME;
2140 if (track->mFillingUpStatus == Track::FS_FILLED) {
2141 // no ramp for the first volume setting
2142 track->mFillingUpStatus = Track::FS_ACTIVE;
2143 if (track->mState == TrackBase::RESUMING) {
2144 track->mState = TrackBase::ACTIVE;
2145 param = AudioMixer::RAMP_VOLUME;
2146 }
Glenn Kasten9c56d4a2011-12-19 15:06:39 -08002147 mAudioMixer->setParameter(name, AudioMixer::RESAMPLE, AudioMixer::RESET, NULL);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002148 } else if (cblk->server != 0) {
2149 // If the track is stopped before the first frame was mixed,
2150 // do not apply ramp
2151 param = AudioMixer::RAMP_VOLUME;
2152 }
2153
2154 // compute volume for this track
Eric Laurente0aed6d2010-09-10 17:44:44 -07002155 uint32_t vl, vr, va;
Eric Laurent8569f0d2010-07-29 23:43:43 -07002156 if (track->isMuted() || track->isPausing() ||
Glenn Kasten02bbd202012-02-08 12:35:35 -08002157 mStreamTypes[track->streamType()].mute) {
Eric Laurente0aed6d2010-09-10 17:44:44 -07002158 vl = vr = va = 0;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002159 if (track->isPausing()) {
2160 track->setPaused();
2161 }
2162 } else {
Eric Laurente0aed6d2010-09-10 17:44:44 -07002163
Mathias Agopian65ab4712010-07-14 17:59:35 -07002164 // read original volumes with volume control
Glenn Kasten02bbd202012-02-08 12:35:35 -08002165 float typeVolume = mStreamTypes[track->streamType()].volume;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002166 float v = masterVolume * typeVolume;
Glenn Kasten83d86532012-01-17 14:39:34 -08002167 uint32_t vlr = cblk->getVolumeLR();
Glenn Kastenb1cf75c2012-01-17 12:20:54 -08002168 vl = vlr & 0xFFFF;
2169 vr = vlr >> 16;
2170 // track volumes come from shared memory, so can't be trusted and must be clamped
2171 if (vl > MAX_GAIN_INT) {
2172 ALOGV("Track left volume out of range: %04X", vl);
2173 vl = MAX_GAIN_INT;
2174 }
2175 if (vr > MAX_GAIN_INT) {
2176 ALOGV("Track right volume out of range: %04X", vr);
2177 vr = MAX_GAIN_INT;
2178 }
2179 // now apply the master volume and stream type volume
2180 vl = (uint32_t)(v * vl) << 12;
2181 vr = (uint32_t)(v * vr) << 12;
2182 // assuming master volume and stream type volume each go up to 1.0,
2183 // vl and vr are now in 8.24 format
Mathias Agopian65ab4712010-07-14 17:59:35 -07002184
Glenn Kasten05632a52012-01-03 14:22:33 -08002185 uint16_t sendLevel = cblk->getSendLevel_U4_12();
2186 // send level comes from shared memory and so may be corrupt
Glenn Kastenb1cf75c2012-01-17 12:20:54 -08002187 if (sendLevel >= MAX_GAIN_INT) {
Glenn Kasten05632a52012-01-03 14:22:33 -08002188 ALOGV("Track send level out of range: %04X", sendLevel);
Glenn Kastenb1cf75c2012-01-17 12:20:54 -08002189 sendLevel = MAX_GAIN_INT;
Glenn Kasten05632a52012-01-03 14:22:33 -08002190 }
2191 va = (uint32_t)(v * sendLevel);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002192 }
Eric Laurente0aed6d2010-09-10 17:44:44 -07002193 // Delegate volume control to effect in track effect chain if needed
2194 if (chain != 0 && chain->setVolume_l(&vl, &vr)) {
2195 // Do not ramp volume if volume is controlled by effect
2196 param = AudioMixer::VOLUME;
2197 track->mHasVolumeController = true;
2198 } else {
2199 // force no volume ramp when volume controller was just disabled or removed
2200 // from effect chain to avoid volume spike
2201 if (track->mHasVolumeController) {
2202 param = AudioMixer::VOLUME;
2203 }
2204 track->mHasVolumeController = false;
2205 }
2206
2207 // Convert volumes from 8.24 to 4.12 format
2208 int16_t left, right, aux;
Glenn Kastenb1cf75c2012-01-17 12:20:54 -08002209 // This additional clamping is needed in case chain->setVolume_l() overshot
Eric Laurente0aed6d2010-09-10 17:44:44 -07002210 uint32_t v_clamped = (vl + (1 << 11)) >> 12;
2211 if (v_clamped > MAX_GAIN_INT) v_clamped = MAX_GAIN_INT;
2212 left = int16_t(v_clamped);
2213 v_clamped = (vr + (1 << 11)) >> 12;
2214 if (v_clamped > MAX_GAIN_INT) v_clamped = MAX_GAIN_INT;
2215 right = int16_t(v_clamped);
2216
2217 if (va > MAX_GAIN_INT) va = MAX_GAIN_INT;
2218 aux = int16_t(va);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002219
Mathias Agopian65ab4712010-07-14 17:59:35 -07002220 // XXX: these things DON'T need to be done each time
Glenn Kasten9c56d4a2011-12-19 15:06:39 -08002221 mAudioMixer->setBufferProvider(name, track);
2222 mAudioMixer->enable(name);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002223
Glenn Kasten9c56d4a2011-12-19 15:06:39 -08002224 mAudioMixer->setParameter(name, param, AudioMixer::VOLUME0, (void *)left);
2225 mAudioMixer->setParameter(name, param, AudioMixer::VOLUME1, (void *)right);
2226 mAudioMixer->setParameter(name, param, AudioMixer::AUXLEVEL, (void *)aux);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002227 mAudioMixer->setParameter(
Glenn Kasten9c56d4a2011-12-19 15:06:39 -08002228 name,
Mathias Agopian65ab4712010-07-14 17:59:35 -07002229 AudioMixer::TRACK,
2230 AudioMixer::FORMAT, (void *)track->format());
2231 mAudioMixer->setParameter(
Glenn Kasten9c56d4a2011-12-19 15:06:39 -08002232 name,
Mathias Agopian65ab4712010-07-14 17:59:35 -07002233 AudioMixer::TRACK,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07002234 AudioMixer::CHANNEL_MASK, (void *)track->channelMask());
Mathias Agopian65ab4712010-07-14 17:59:35 -07002235 mAudioMixer->setParameter(
Glenn Kasten9c56d4a2011-12-19 15:06:39 -08002236 name,
Mathias Agopian65ab4712010-07-14 17:59:35 -07002237 AudioMixer::RESAMPLE,
2238 AudioMixer::SAMPLE_RATE,
2239 (void *)(cblk->sampleRate));
2240 mAudioMixer->setParameter(
Glenn Kasten9c56d4a2011-12-19 15:06:39 -08002241 name,
Mathias Agopian65ab4712010-07-14 17:59:35 -07002242 AudioMixer::TRACK,
2243 AudioMixer::MAIN_BUFFER, (void *)track->mainBuffer());
2244 mAudioMixer->setParameter(
Glenn Kasten9c56d4a2011-12-19 15:06:39 -08002245 name,
Mathias Agopian65ab4712010-07-14 17:59:35 -07002246 AudioMixer::TRACK,
2247 AudioMixer::AUX_BUFFER, (void *)track->auxBuffer());
2248
2249 // reset retry count
2250 track->mRetryCount = kMaxTrackRetries;
Eric Laurent27741442012-01-17 19:20:12 -08002251 // If one track is ready, set the mixer ready if:
2252 // - the mixer was not ready during previous round OR
2253 // - no other track is not ready
2254 if (mPrevMixerStatus != MIXER_TRACKS_READY ||
2255 mixerStatus != MIXER_TRACKS_ENABLED) {
2256 mixerStatus = MIXER_TRACKS_READY;
2257 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07002258 } else {
Glenn Kasten9c56d4a2011-12-19 15:06:39 -08002259 //ALOGV("track %d u=%08x, s=%08x [NOT READY] on thread %p", name, cblk->user, cblk->server, this);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002260 if (track->isStopped()) {
2261 track->reset();
2262 }
2263 if (track->isTerminated() || track->isStopped() || track->isPaused()) {
2264 // We have consumed all the buffers of this track.
2265 // Remove it from the list of active tracks.
2266 tracksToRemove->add(track);
2267 } else {
2268 // No buffers for this track. Give it a few chances to
2269 // fill a buffer, then remove it from active list.
2270 if (--(track->mRetryCount) <= 0) {
Glenn Kasten9c56d4a2011-12-19 15:06:39 -08002271 ALOGV("BUFFER TIMEOUT: remove(%d) from active list on thread %p", name, this);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002272 tracksToRemove->add(track);
Eric Laurent44d98482010-09-30 16:12:31 -07002273 // indicate to client process that the track was disabled because of underrun
Eric Laurent38ccae22011-03-28 18:37:07 -07002274 android_atomic_or(CBLK_DISABLED_ON, &cblk->flags);
Eric Laurent27741442012-01-17 19:20:12 -08002275 // If one track is not ready, mark the mixer also not ready if:
2276 // - the mixer was ready during previous round OR
2277 // - no other track is ready
2278 } else if (mPrevMixerStatus == MIXER_TRACKS_READY ||
2279 mixerStatus != MIXER_TRACKS_READY) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07002280 mixerStatus = MIXER_TRACKS_ENABLED;
2281 }
2282 }
Glenn Kasten9c56d4a2011-12-19 15:06:39 -08002283 mAudioMixer->disable(name);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002284 }
2285 }
2286
2287 // remove all the tracks that need to be...
2288 count = tracksToRemove->size();
Glenn Kastenf6b16782011-12-15 09:51:17 -08002289 if (CC_UNLIKELY(count)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07002290 for (size_t i=0 ; i<count ; i++) {
2291 const sp<Track>& track = tracksToRemove->itemAt(i);
2292 mActiveTracks.remove(track);
2293 if (track->mainBuffer() != mMixBuffer) {
2294 chain = getEffectChain_l(track->sessionId());
2295 if (chain != 0) {
Steve Block3856b092011-10-20 11:56:00 +01002296 ALOGV("stopping track on chain %p for session Id: %d", chain.get(), track->sessionId());
Eric Laurentb469b942011-05-09 12:09:06 -07002297 chain->decActiveTrackCnt();
Mathias Agopian65ab4712010-07-14 17:59:35 -07002298 }
2299 }
2300 if (track->isTerminated()) {
Eric Laurentb469b942011-05-09 12:09:06 -07002301 removeTrack_l(track);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002302 }
2303 }
2304 }
2305
2306 // mix buffer must be cleared if all tracks are connected to an
2307 // effect chain as in this case the mixer will not write to
2308 // mix buffer and track effects will accumulate into it
2309 if (mixedTracks != 0 && mixedTracks == tracksWithEffect) {
2310 memset(mMixBuffer, 0, mFrameCount * mChannelCount * sizeof(int16_t));
2311 }
2312
Eric Laurent27741442012-01-17 19:20:12 -08002313 mPrevMixerStatus = mixerStatus;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002314 return mixerStatus;
2315}
2316
Glenn Kastenfff6d712012-01-12 16:38:12 -08002317void AudioFlinger::MixerThread::invalidateTracks(audio_stream_type_t streamType)
Mathias Agopian65ab4712010-07-14 17:59:35 -07002318{
Steve Block3856b092011-10-20 11:56:00 +01002319 ALOGV ("MixerThread::invalidateTracks() mixer %p, streamType %d, mTracks.size %d",
Eric Laurentde070132010-07-13 04:45:46 -07002320 this, streamType, mTracks.size());
Mathias Agopian65ab4712010-07-14 17:59:35 -07002321 Mutex::Autolock _l(mLock);
Eric Laurentde070132010-07-13 04:45:46 -07002322
Mathias Agopian65ab4712010-07-14 17:59:35 -07002323 size_t size = mTracks.size();
2324 for (size_t i = 0; i < size; i++) {
2325 sp<Track> t = mTracks[i];
Glenn Kasten02bbd202012-02-08 12:35:35 -08002326 if (t->streamType() == streamType) {
Eric Laurent38ccae22011-03-28 18:37:07 -07002327 android_atomic_or(CBLK_INVALID_ON, &t->mCblk->flags);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002328 t->mCblk->cv.signal();
Mathias Agopian65ab4712010-07-14 17:59:35 -07002329 }
2330 }
2331}
2332
Glenn Kastenfff6d712012-01-12 16:38:12 -08002333void AudioFlinger::PlaybackThread::setStreamValid(audio_stream_type_t streamType, bool valid)
Eric Laurent9f6530f2011-08-30 10:18:54 -07002334{
Steve Block3856b092011-10-20 11:56:00 +01002335 ALOGV ("PlaybackThread::setStreamValid() thread %p, streamType %d, valid %d",
Eric Laurent9f6530f2011-08-30 10:18:54 -07002336 this, streamType, valid);
2337 Mutex::Autolock _l(mLock);
2338
2339 mStreamTypes[streamType].valid = valid;
2340}
Mathias Agopian65ab4712010-07-14 17:59:35 -07002341
2342// getTrackName_l() must be called with ThreadBase::mLock held
2343int AudioFlinger::MixerThread::getTrackName_l()
2344{
2345 return mAudioMixer->getTrackName();
2346}
2347
2348// deleteTrackName_l() must be called with ThreadBase::mLock held
2349void AudioFlinger::MixerThread::deleteTrackName_l(int name)
2350{
Steve Block3856b092011-10-20 11:56:00 +01002351 ALOGV("remove track (%d) and delete from mixer", name);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002352 mAudioMixer->deleteTrackName(name);
2353}
2354
2355// checkForNewParameters_l() must be called with ThreadBase::mLock held
2356bool AudioFlinger::MixerThread::checkForNewParameters_l()
2357{
2358 bool reconfig = false;
2359
2360 while (!mNewParameters.isEmpty()) {
2361 status_t status = NO_ERROR;
2362 String8 keyValuePair = mNewParameters[0];
2363 AudioParameter param = AudioParameter(keyValuePair);
2364 int value;
2365
2366 if (param.getInt(String8(AudioParameter::keySamplingRate), value) == NO_ERROR) {
2367 reconfig = true;
2368 }
2369 if (param.getInt(String8(AudioParameter::keyFormat), value) == NO_ERROR) {
Glenn Kasten58f30212012-01-12 12:27:51 -08002370 if ((audio_format_t) value != AUDIO_FORMAT_PCM_16_BIT) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07002371 status = BAD_VALUE;
2372 } else {
2373 reconfig = true;
2374 }
2375 }
2376 if (param.getInt(String8(AudioParameter::keyChannels), value) == NO_ERROR) {
Dima Zavinfce7a472011-04-19 22:30:36 -07002377 if (value != AUDIO_CHANNEL_OUT_STEREO) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07002378 status = BAD_VALUE;
2379 } else {
2380 reconfig = true;
2381 }
2382 }
2383 if (param.getInt(String8(AudioParameter::keyFrameCount), value) == NO_ERROR) {
2384 // do not accept frame count changes if tracks are open as the track buffer
Glenn Kasten362c4e62011-12-14 10:28:06 -08002385 // size depends on frame count and correct behavior would not be guaranteed
Mathias Agopian65ab4712010-07-14 17:59:35 -07002386 // if frame count is changed after track creation
2387 if (!mTracks.isEmpty()) {
2388 status = INVALID_OPERATION;
2389 } else {
2390 reconfig = true;
2391 }
2392 }
2393 if (param.getInt(String8(AudioParameter::keyRouting), value) == NO_ERROR) {
Gloria Wang9ee159b2011-02-24 14:51:45 -08002394 // when changing the audio output device, call addBatteryData to notify
2395 // the change
Eric Laurentb469b942011-05-09 12:09:06 -07002396 if ((int)mDevice != value) {
Gloria Wang9ee159b2011-02-24 14:51:45 -08002397 uint32_t params = 0;
2398 // check whether speaker is on
Dima Zavinfce7a472011-04-19 22:30:36 -07002399 if (value & AUDIO_DEVICE_OUT_SPEAKER) {
Gloria Wang9ee159b2011-02-24 14:51:45 -08002400 params |= IMediaPlayerService::kBatteryDataSpeakerOn;
2401 }
2402
2403 int deviceWithoutSpeaker
Dima Zavinfce7a472011-04-19 22:30:36 -07002404 = AUDIO_DEVICE_OUT_ALL & ~AUDIO_DEVICE_OUT_SPEAKER;
Gloria Wang9ee159b2011-02-24 14:51:45 -08002405 // check if any other device (except speaker) is on
2406 if (value & deviceWithoutSpeaker ) {
2407 params |= IMediaPlayerService::kBatteryDataOtherAudioDeviceOn;
2408 }
2409
2410 if (params != 0) {
2411 addBatteryData(params);
2412 }
2413 }
2414
Mathias Agopian65ab4712010-07-14 17:59:35 -07002415 // forward device change to effects that have requested to be
2416 // aware of attached audio device.
2417 mDevice = (uint32_t)value;
2418 for (size_t i = 0; i < mEffectChains.size(); i++) {
Eric Laurentcab11242010-07-15 12:50:15 -07002419 mEffectChains[i]->setDevice_l(mDevice);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002420 }
2421 }
2422
2423 if (status == NO_ERROR) {
Dima Zavin799a70e2011-04-18 16:57:27 -07002424 status = mOutput->stream->common.set_parameters(&mOutput->stream->common,
Dima Zavinfce7a472011-04-19 22:30:36 -07002425 keyValuePair.string());
Mathias Agopian65ab4712010-07-14 17:59:35 -07002426 if (!mStandby && status == INVALID_OPERATION) {
Dima Zavin799a70e2011-04-18 16:57:27 -07002427 mOutput->stream->common.standby(&mOutput->stream->common);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002428 mStandby = true;
2429 mBytesWritten = 0;
Dima Zavin799a70e2011-04-18 16:57:27 -07002430 status = mOutput->stream->common.set_parameters(&mOutput->stream->common,
Dima Zavinfce7a472011-04-19 22:30:36 -07002431 keyValuePair.string());
Mathias Agopian65ab4712010-07-14 17:59:35 -07002432 }
2433 if (status == NO_ERROR && reconfig) {
2434 delete mAudioMixer;
Glenn Kastene9dd0172012-01-27 18:08:45 -08002435 // for safety in case readOutputParameters() accesses mAudioMixer (it doesn't)
2436 mAudioMixer = NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002437 readOutputParameters();
2438 mAudioMixer = new AudioMixer(mFrameCount, mSampleRate);
2439 for (size_t i = 0; i < mTracks.size() ; i++) {
2440 int name = getTrackName_l();
2441 if (name < 0) break;
2442 mTracks[i]->mName = name;
2443 // limit track sample rate to 2 x new output sample rate
2444 if (mTracks[i]->mCblk->sampleRate > 2 * sampleRate()) {
2445 mTracks[i]->mCblk->sampleRate = 2 * sampleRate();
2446 }
2447 }
2448 sendConfigEvent_l(AudioSystem::OUTPUT_CONFIG_CHANGED);
2449 }
2450 }
2451
2452 mNewParameters.removeAt(0);
2453
2454 mParamStatus = status;
2455 mParamCond.signal();
Eric Laurent60cd0a02011-09-13 11:40:21 -07002456 // wait for condition with time out in case the thread calling ThreadBase::setParameters()
2457 // already timed out waiting for the status and will never signal the condition.
Glenn Kasten7dede872011-12-13 11:04:14 -08002458 mWaitWorkCV.waitRelative(mLock, kSetParametersTimeoutNs);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002459 }
2460 return reconfig;
2461}
2462
2463status_t AudioFlinger::MixerThread::dumpInternals(int fd, const Vector<String16>& args)
2464{
2465 const size_t SIZE = 256;
2466 char buffer[SIZE];
2467 String8 result;
2468
2469 PlaybackThread::dumpInternals(fd, args);
2470
2471 snprintf(buffer, SIZE, "AudioMixer tracks: %08x\n", mAudioMixer->trackNames());
2472 result.append(buffer);
2473 write(fd, result.string(), result.size());
2474 return NO_ERROR;
2475}
2476
Mathias Agopian65ab4712010-07-14 17:59:35 -07002477uint32_t AudioFlinger::MixerThread::idleSleepTimeUs()
2478{
Eric Laurent60e18242010-07-29 06:50:24 -07002479 return (uint32_t)(((mFrameCount * 1000) / mSampleRate) * 1000) / 2;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002480}
2481
Eric Laurent25cbe0e2010-08-18 18:13:17 -07002482uint32_t AudioFlinger::MixerThread::suspendSleepTimeUs()
2483{
2484 return (uint32_t)(((mFrameCount * 1000) / mSampleRate) * 1000);
2485}
2486
Mathias Agopian65ab4712010-07-14 17:59:35 -07002487// ----------------------------------------------------------------------------
Glenn Kasten72ef00d2012-01-17 11:09:42 -08002488AudioFlinger::DirectOutputThread::DirectOutputThread(const sp<AudioFlinger>& audioFlinger,
2489 AudioStreamOut* output, audio_io_handle_t id, uint32_t device)
Glenn Kasten23bb8be2012-01-26 10:38:26 -08002490 : PlaybackThread(audioFlinger, output, id, device, DIRECT)
Glenn Kasten84afa3b2012-01-25 15:28:08 -08002491 // mLeftVolFloat, mRightVolFloat
2492 // mLeftVolShort, mRightVolShort
Mathias Agopian65ab4712010-07-14 17:59:35 -07002493{
Mathias Agopian65ab4712010-07-14 17:59:35 -07002494}
2495
2496AudioFlinger::DirectOutputThread::~DirectOutputThread()
2497{
2498}
2499
Mathias Agopian65ab4712010-07-14 17:59:35 -07002500void AudioFlinger::DirectOutputThread::applyVolume(uint16_t leftVol, uint16_t rightVol, bool ramp)
2501{
2502 // Do not apply volume on compressed audio
Dima Zavinfce7a472011-04-19 22:30:36 -07002503 if (!audio_is_linear_pcm(mFormat)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07002504 return;
2505 }
2506
2507 // convert to signed 16 bit before volume calculation
Dima Zavinfce7a472011-04-19 22:30:36 -07002508 if (mFormat == AUDIO_FORMAT_PCM_8_BIT) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07002509 size_t count = mFrameCount * mChannelCount;
2510 uint8_t *src = (uint8_t *)mMixBuffer + count-1;
2511 int16_t *dst = mMixBuffer + count-1;
2512 while(count--) {
2513 *dst-- = (int16_t)(*src--^0x80) << 8;
2514 }
2515 }
2516
2517 size_t frameCount = mFrameCount;
2518 int16_t *out = mMixBuffer;
2519 if (ramp) {
2520 if (mChannelCount == 1) {
2521 int32_t d = ((int32_t)leftVol - (int32_t)mLeftVolShort) << 16;
2522 int32_t vlInc = d / (int32_t)frameCount;
2523 int32_t vl = ((int32_t)mLeftVolShort << 16);
2524 do {
2525 out[0] = clamp16(mul(out[0], vl >> 16) >> 12);
2526 out++;
2527 vl += vlInc;
2528 } while (--frameCount);
2529
2530 } else {
2531 int32_t d = ((int32_t)leftVol - (int32_t)mLeftVolShort) << 16;
2532 int32_t vlInc = d / (int32_t)frameCount;
2533 d = ((int32_t)rightVol - (int32_t)mRightVolShort) << 16;
2534 int32_t vrInc = d / (int32_t)frameCount;
2535 int32_t vl = ((int32_t)mLeftVolShort << 16);
2536 int32_t vr = ((int32_t)mRightVolShort << 16);
2537 do {
2538 out[0] = clamp16(mul(out[0], vl >> 16) >> 12);
2539 out[1] = clamp16(mul(out[1], vr >> 16) >> 12);
2540 out += 2;
2541 vl += vlInc;
2542 vr += vrInc;
2543 } while (--frameCount);
2544 }
2545 } else {
2546 if (mChannelCount == 1) {
2547 do {
2548 out[0] = clamp16(mul(out[0], leftVol) >> 12);
2549 out++;
2550 } while (--frameCount);
2551 } else {
2552 do {
2553 out[0] = clamp16(mul(out[0], leftVol) >> 12);
2554 out[1] = clamp16(mul(out[1], rightVol) >> 12);
2555 out += 2;
2556 } while (--frameCount);
2557 }
2558 }
2559
2560 // convert back to unsigned 8 bit after volume calculation
Dima Zavinfce7a472011-04-19 22:30:36 -07002561 if (mFormat == AUDIO_FORMAT_PCM_8_BIT) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07002562 size_t count = mFrameCount * mChannelCount;
2563 int16_t *src = mMixBuffer;
2564 uint8_t *dst = (uint8_t *)mMixBuffer;
2565 while(count--) {
2566 *dst++ = (uint8_t)(((int32_t)*src++ + (1<<7)) >> 8)^0x80;
2567 }
2568 }
2569
2570 mLeftVolShort = leftVol;
2571 mRightVolShort = rightVol;
2572}
2573
2574bool AudioFlinger::DirectOutputThread::threadLoop()
2575{
Glenn Kasten29c23c32012-01-26 13:37:52 -08002576 mixer_state mixerStatus = MIXER_IDLE;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002577 sp<Track> trackToRemove;
2578 sp<Track> activeTrack;
2579 nsecs_t standbyTime = systemTime();
2580 int8_t *curBuf;
2581 size_t mixBufferSize = mFrameCount*mFrameSize;
2582 uint32_t activeSleepTime = activeSleepTimeUs();
2583 uint32_t idleSleepTime = idleSleepTimeUs();
2584 uint32_t sleepTime = idleSleepTime;
2585 // use shorter standby delay as on normal output to release
2586 // hardware resources as soon as possible
2587 nsecs_t standbyDelay = microseconds(activeSleepTime*2);
2588
Eric Laurentfeb0db62011-07-22 09:04:31 -07002589 acquireWakeLock();
2590
Mathias Agopian65ab4712010-07-14 17:59:35 -07002591 while (!exitPending())
2592 {
2593 bool rampVolume;
2594 uint16_t leftVol;
2595 uint16_t rightVol;
2596 Vector< sp<EffectChain> > effectChains;
2597
2598 processConfigEvents();
2599
2600 mixerStatus = MIXER_IDLE;
2601
2602 { // scope for the mLock
2603
2604 Mutex::Autolock _l(mLock);
2605
2606 if (checkForNewParameters_l()) {
2607 mixBufferSize = mFrameCount*mFrameSize;
2608 activeSleepTime = activeSleepTimeUs();
2609 idleSleepTime = idleSleepTimeUs();
2610 standbyDelay = microseconds(activeSleepTime*2);
2611 }
2612
2613 // put audio hardware into standby after short delay
Glenn Kastenf6b16782011-12-15 09:51:17 -08002614 if (CC_UNLIKELY((!mActiveTracks.size() && systemTime() > standbyTime) ||
2615 mSuspended)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07002616 // wait until we have something to do...
2617 if (!mStandby) {
Glenn Kasten90bebef2012-01-27 15:24:38 -08002618 ALOGV("Audio hardware entering standby, mixer %p", this);
Dima Zavin799a70e2011-04-18 16:57:27 -07002619 mOutput->stream->common.standby(&mOutput->stream->common);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002620 mStandby = true;
2621 mBytesWritten = 0;
2622 }
2623
2624 if (!mActiveTracks.size() && mConfigEvents.isEmpty()) {
2625 // we're about to wait, flush the binder command buffer
2626 IPCThreadState::self()->flushCommands();
2627
2628 if (exitPending()) break;
2629
Eric Laurentfeb0db62011-07-22 09:04:31 -07002630 releaseWakeLock_l();
Glenn Kasten90bebef2012-01-27 15:24:38 -08002631 ALOGV("DirectOutputThread %p TID %d going to sleep", this, gettid());
Mathias Agopian65ab4712010-07-14 17:59:35 -07002632 mWaitWorkCV.wait(mLock);
Glenn Kasten90bebef2012-01-27 15:24:38 -08002633 ALOGV("DirectOutputThread %p TID %d waking up in active mode", this, gettid());
Eric Laurentfeb0db62011-07-22 09:04:31 -07002634 acquireWakeLock_l();
Mathias Agopian65ab4712010-07-14 17:59:35 -07002635
Glenn Kastenf1d45922012-01-13 15:54:24 -08002636 if (!mMasterMute) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07002637 char value[PROPERTY_VALUE_MAX];
2638 property_get("ro.audio.silent", value, "0");
2639 if (atoi(value)) {
Steve Blockb8a80522011-12-20 16:23:08 +00002640 ALOGD("Silence is golden");
Mathias Agopian65ab4712010-07-14 17:59:35 -07002641 setMasterMute(true);
2642 }
2643 }
2644
2645 standbyTime = systemTime() + standbyDelay;
2646 sleepTime = idleSleepTime;
2647 continue;
2648 }
2649 }
2650
2651 effectChains = mEffectChains;
2652
2653 // find out which tracks need to be processed
2654 if (mActiveTracks.size() != 0) {
2655 sp<Track> t = mActiveTracks[0].promote();
2656 if (t == 0) continue;
2657
2658 Track* const track = t.get();
2659 audio_track_cblk_t* cblk = track->cblk();
2660
2661 // The first time a track is added we wait
2662 // for all its buffers to be filled before processing it
Eric Laurentaf59ce22010-10-05 14:41:42 -07002663 if (cblk->framesReady() && track->isReady() &&
Mathias Agopian65ab4712010-07-14 17:59:35 -07002664 !track->isPaused() && !track->isTerminated())
2665 {
Steve Block3856b092011-10-20 11:56:00 +01002666 //ALOGV("track %d u=%08x, s=%08x [OK]", track->name(), cblk->user, cblk->server);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002667
2668 if (track->mFillingUpStatus == Track::FS_FILLED) {
2669 track->mFillingUpStatus = Track::FS_ACTIVE;
2670 mLeftVolFloat = mRightVolFloat = 0;
2671 mLeftVolShort = mRightVolShort = 0;
2672 if (track->mState == TrackBase::RESUMING) {
2673 track->mState = TrackBase::ACTIVE;
2674 rampVolume = true;
2675 }
2676 } else if (cblk->server != 0) {
2677 // If the track is stopped before the first frame was mixed,
2678 // do not apply ramp
2679 rampVolume = true;
2680 }
2681 // compute volume for this track
2682 float left, right;
2683 if (track->isMuted() || mMasterMute || track->isPausing() ||
Glenn Kasten02bbd202012-02-08 12:35:35 -08002684 mStreamTypes[track->streamType()].mute) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07002685 left = right = 0;
2686 if (track->isPausing()) {
2687 track->setPaused();
2688 }
2689 } else {
Glenn Kasten02bbd202012-02-08 12:35:35 -08002690 float typeVolume = mStreamTypes[track->streamType()].volume;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002691 float v = mMasterVolume * typeVolume;
Glenn Kasten83d86532012-01-17 14:39:34 -08002692 uint32_t vlr = cblk->getVolumeLR();
Glenn Kastenb1cf75c2012-01-17 12:20:54 -08002693 float v_clamped = v * (vlr & 0xFFFF);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002694 if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN;
2695 left = v_clamped/MAX_GAIN;
Glenn Kastenb1cf75c2012-01-17 12:20:54 -08002696 v_clamped = v * (vlr >> 16);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002697 if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN;
2698 right = v_clamped/MAX_GAIN;
2699 }
2700
2701 if (left != mLeftVolFloat || right != mRightVolFloat) {
2702 mLeftVolFloat = left;
2703 mRightVolFloat = right;
2704
2705 // If audio HAL implements volume control,
2706 // force software volume to nominal value
Dima Zavin799a70e2011-04-18 16:57:27 -07002707 if (mOutput->stream->set_volume(mOutput->stream, left, right) == NO_ERROR) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07002708 left = 1.0f;
2709 right = 1.0f;
2710 }
2711
2712 // Convert volumes from float to 8.24
2713 uint32_t vl = (uint32_t)(left * (1 << 24));
2714 uint32_t vr = (uint32_t)(right * (1 << 24));
2715
2716 // Delegate volume control to effect in track effect chain if needed
2717 // only one effect chain can be present on DirectOutputThread, so if
2718 // there is one, the track is connected to it
2719 if (!effectChains.isEmpty()) {
Eric Laurente0aed6d2010-09-10 17:44:44 -07002720 // Do not ramp volume if volume is controlled by effect
Eric Laurentcab11242010-07-15 12:50:15 -07002721 if(effectChains[0]->setVolume_l(&vl, &vr)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07002722 rampVolume = false;
2723 }
2724 }
2725
2726 // Convert volumes from 8.24 to 4.12 format
2727 uint32_t v_clamped = (vl + (1 << 11)) >> 12;
2728 if (v_clamped > MAX_GAIN_INT) v_clamped = MAX_GAIN_INT;
2729 leftVol = (uint16_t)v_clamped;
2730 v_clamped = (vr + (1 << 11)) >> 12;
2731 if (v_clamped > MAX_GAIN_INT) v_clamped = MAX_GAIN_INT;
2732 rightVol = (uint16_t)v_clamped;
2733 } else {
2734 leftVol = mLeftVolShort;
2735 rightVol = mRightVolShort;
2736 rampVolume = false;
2737 }
2738
2739 // reset retry count
2740 track->mRetryCount = kMaxTrackRetriesDirect;
2741 activeTrack = t;
2742 mixerStatus = MIXER_TRACKS_READY;
2743 } else {
Steve Block3856b092011-10-20 11:56:00 +01002744 //ALOGV("track %d u=%08x, s=%08x [NOT READY]", track->name(), cblk->user, cblk->server);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002745 if (track->isStopped()) {
2746 track->reset();
2747 }
2748 if (track->isTerminated() || track->isStopped() || track->isPaused()) {
2749 // We have consumed all the buffers of this track.
2750 // Remove it from the list of active tracks.
2751 trackToRemove = track;
2752 } else {
2753 // No buffers for this track. Give it a few chances to
2754 // fill a buffer, then remove it from active list.
2755 if (--(track->mRetryCount) <= 0) {
Steve Block3856b092011-10-20 11:56:00 +01002756 ALOGV("BUFFER TIMEOUT: remove(%d) from active list", track->name());
Mathias Agopian65ab4712010-07-14 17:59:35 -07002757 trackToRemove = track;
2758 } else {
2759 mixerStatus = MIXER_TRACKS_ENABLED;
2760 }
2761 }
2762 }
2763 }
2764
2765 // remove all the tracks that need to be...
Glenn Kastenf6b16782011-12-15 09:51:17 -08002766 if (CC_UNLIKELY(trackToRemove != 0)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07002767 mActiveTracks.remove(trackToRemove);
2768 if (!effectChains.isEmpty()) {
Steve Block3856b092011-10-20 11:56:00 +01002769 ALOGV("stopping track on chain %p for session Id: %d", effectChains[0].get(),
Eric Laurentde070132010-07-13 04:45:46 -07002770 trackToRemove->sessionId());
Eric Laurentb469b942011-05-09 12:09:06 -07002771 effectChains[0]->decActiveTrackCnt();
Mathias Agopian65ab4712010-07-14 17:59:35 -07002772 }
2773 if (trackToRemove->isTerminated()) {
Eric Laurentb469b942011-05-09 12:09:06 -07002774 removeTrack_l(trackToRemove);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002775 }
2776 }
2777
Eric Laurentde070132010-07-13 04:45:46 -07002778 lockEffectChains_l(effectChains);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002779 }
2780
Glenn Kastenf6b16782011-12-15 09:51:17 -08002781 if (CC_LIKELY(mixerStatus == MIXER_TRACKS_READY)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07002782 AudioBufferProvider::Buffer buffer;
2783 size_t frameCount = mFrameCount;
2784 curBuf = (int8_t *)mMixBuffer;
2785 // output audio to hardware
2786 while (frameCount) {
2787 buffer.frameCount = frameCount;
2788 activeTrack->getNextBuffer(&buffer);
Glenn Kastenf6b16782011-12-15 09:51:17 -08002789 if (CC_UNLIKELY(buffer.raw == NULL)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07002790 memset(curBuf, 0, frameCount * mFrameSize);
2791 break;
2792 }
2793 memcpy(curBuf, buffer.raw, buffer.frameCount * mFrameSize);
2794 frameCount -= buffer.frameCount;
2795 curBuf += buffer.frameCount * mFrameSize;
2796 activeTrack->releaseBuffer(&buffer);
2797 }
2798 sleepTime = 0;
2799 standbyTime = systemTime() + standbyDelay;
2800 } else {
2801 if (sleepTime == 0) {
2802 if (mixerStatus == MIXER_TRACKS_ENABLED) {
2803 sleepTime = activeSleepTime;
2804 } else {
2805 sleepTime = idleSleepTime;
2806 }
Dima Zavinfce7a472011-04-19 22:30:36 -07002807 } else if (mBytesWritten != 0 && audio_is_linear_pcm(mFormat)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07002808 memset (mMixBuffer, 0, mFrameCount * mFrameSize);
2809 sleepTime = 0;
2810 }
2811 }
2812
2813 if (mSuspended) {
Eric Laurent25cbe0e2010-08-18 18:13:17 -07002814 sleepTime = suspendSleepTimeUs();
Mathias Agopian65ab4712010-07-14 17:59:35 -07002815 }
2816 // sleepTime == 0 means we must write to audio hardware
2817 if (sleepTime == 0) {
2818 if (mixerStatus == MIXER_TRACKS_READY) {
2819 applyVolume(leftVol, rightVol, rampVolume);
2820 }
2821 for (size_t i = 0; i < effectChains.size(); i ++) {
2822 effectChains[i]->process_l();
2823 }
Eric Laurentde070132010-07-13 04:45:46 -07002824 unlockEffectChains(effectChains);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002825
2826 mLastWriteTime = systemTime();
2827 mInWrite = true;
2828 mBytesWritten += mixBufferSize;
Dima Zavin799a70e2011-04-18 16:57:27 -07002829 int bytesWritten = (int)mOutput->stream->write(mOutput->stream, mMixBuffer, mixBufferSize);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002830 if (bytesWritten < 0) mBytesWritten -= mixBufferSize;
2831 mNumWrites++;
2832 mInWrite = false;
2833 mStandby = false;
2834 } else {
Eric Laurentde070132010-07-13 04:45:46 -07002835 unlockEffectChains(effectChains);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002836 usleep(sleepTime);
2837 }
2838
2839 // finally let go of removed track, without the lock held
2840 // since we can't guarantee the destructors won't acquire that
2841 // same lock.
2842 trackToRemove.clear();
2843 activeTrack.clear();
2844
2845 // Effect chains will be actually deleted here if they were removed from
2846 // mEffectChains list during mixing or effects processing
2847 effectChains.clear();
2848 }
2849
2850 if (!mStandby) {
Dima Zavin799a70e2011-04-18 16:57:27 -07002851 mOutput->stream->common.standby(&mOutput->stream->common);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002852 }
2853
Eric Laurentfeb0db62011-07-22 09:04:31 -07002854 releaseWakeLock();
2855
Steve Block3856b092011-10-20 11:56:00 +01002856 ALOGV("DirectOutputThread %p exiting", this);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002857 return false;
2858}
2859
2860// getTrackName_l() must be called with ThreadBase::mLock held
2861int AudioFlinger::DirectOutputThread::getTrackName_l()
2862{
2863 return 0;
2864}
2865
2866// deleteTrackName_l() must be called with ThreadBase::mLock held
2867void AudioFlinger::DirectOutputThread::deleteTrackName_l(int name)
2868{
2869}
2870
2871// checkForNewParameters_l() must be called with ThreadBase::mLock held
2872bool AudioFlinger::DirectOutputThread::checkForNewParameters_l()
2873{
2874 bool reconfig = false;
2875
2876 while (!mNewParameters.isEmpty()) {
2877 status_t status = NO_ERROR;
2878 String8 keyValuePair = mNewParameters[0];
2879 AudioParameter param = AudioParameter(keyValuePair);
2880 int value;
2881
2882 if (param.getInt(String8(AudioParameter::keyFrameCount), value) == NO_ERROR) {
2883 // do not accept frame count changes if tracks are open as the track buffer
2884 // size depends on frame count and correct behavior would not be garantied
2885 // if frame count is changed after track creation
2886 if (!mTracks.isEmpty()) {
2887 status = INVALID_OPERATION;
2888 } else {
2889 reconfig = true;
2890 }
2891 }
2892 if (status == NO_ERROR) {
Dima Zavin799a70e2011-04-18 16:57:27 -07002893 status = mOutput->stream->common.set_parameters(&mOutput->stream->common,
Dima Zavinfce7a472011-04-19 22:30:36 -07002894 keyValuePair.string());
Mathias Agopian65ab4712010-07-14 17:59:35 -07002895 if (!mStandby && status == INVALID_OPERATION) {
Dima Zavin799a70e2011-04-18 16:57:27 -07002896 mOutput->stream->common.standby(&mOutput->stream->common);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002897 mStandby = true;
2898 mBytesWritten = 0;
Dima Zavin799a70e2011-04-18 16:57:27 -07002899 status = mOutput->stream->common.set_parameters(&mOutput->stream->common,
Dima Zavinfce7a472011-04-19 22:30:36 -07002900 keyValuePair.string());
Mathias Agopian65ab4712010-07-14 17:59:35 -07002901 }
2902 if (status == NO_ERROR && reconfig) {
2903 readOutputParameters();
2904 sendConfigEvent_l(AudioSystem::OUTPUT_CONFIG_CHANGED);
2905 }
2906 }
2907
2908 mNewParameters.removeAt(0);
2909
2910 mParamStatus = status;
2911 mParamCond.signal();
Eric Laurent60cd0a02011-09-13 11:40:21 -07002912 // wait for condition with time out in case the thread calling ThreadBase::setParameters()
2913 // already timed out waiting for the status and will never signal the condition.
Glenn Kasten7dede872011-12-13 11:04:14 -08002914 mWaitWorkCV.waitRelative(mLock, kSetParametersTimeoutNs);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002915 }
2916 return reconfig;
2917}
2918
2919uint32_t AudioFlinger::DirectOutputThread::activeSleepTimeUs()
2920{
2921 uint32_t time;
Dima Zavinfce7a472011-04-19 22:30:36 -07002922 if (audio_is_linear_pcm(mFormat)) {
Eric Laurent162b40b2011-12-05 09:47:19 -08002923 time = PlaybackThread::activeSleepTimeUs();
Mathias Agopian65ab4712010-07-14 17:59:35 -07002924 } else {
2925 time = 10000;
2926 }
2927 return time;
2928}
2929
2930uint32_t AudioFlinger::DirectOutputThread::idleSleepTimeUs()
2931{
2932 uint32_t time;
Dima Zavinfce7a472011-04-19 22:30:36 -07002933 if (audio_is_linear_pcm(mFormat)) {
Eric Laurent60e18242010-07-29 06:50:24 -07002934 time = (uint32_t)(((mFrameCount * 1000) / mSampleRate) * 1000) / 2;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002935 } else {
2936 time = 10000;
2937 }
2938 return time;
2939}
2940
Eric Laurent25cbe0e2010-08-18 18:13:17 -07002941uint32_t AudioFlinger::DirectOutputThread::suspendSleepTimeUs()
2942{
2943 uint32_t time;
Dima Zavinfce7a472011-04-19 22:30:36 -07002944 if (audio_is_linear_pcm(mFormat)) {
Eric Laurent25cbe0e2010-08-18 18:13:17 -07002945 time = (uint32_t)(((mFrameCount * 1000) / mSampleRate) * 1000);
2946 } else {
2947 time = 10000;
2948 }
2949 return time;
2950}
2951
2952
Mathias Agopian65ab4712010-07-14 17:59:35 -07002953// ----------------------------------------------------------------------------
2954
Glenn Kasten23bb8be2012-01-26 10:38:26 -08002955AudioFlinger::DuplicatingThread::DuplicatingThread(const sp<AudioFlinger>& audioFlinger,
Glenn Kasten72ef00d2012-01-17 11:09:42 -08002956 AudioFlinger::MixerThread* mainThread, audio_io_handle_t id)
Glenn Kasten23bb8be2012-01-26 10:38:26 -08002957 : MixerThread(audioFlinger, mainThread->getOutput(), id, mainThread->device(), DUPLICATING),
2958 mWaitTimeMs(UINT_MAX)
Mathias Agopian65ab4712010-07-14 17:59:35 -07002959{
Mathias Agopian65ab4712010-07-14 17:59:35 -07002960 addOutputTrack(mainThread);
2961}
2962
2963AudioFlinger::DuplicatingThread::~DuplicatingThread()
2964{
2965 for (size_t i = 0; i < mOutputTracks.size(); i++) {
2966 mOutputTracks[i]->destroy();
2967 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07002968}
2969
2970bool AudioFlinger::DuplicatingThread::threadLoop()
2971{
2972 Vector< sp<Track> > tracksToRemove;
Glenn Kasten29c23c32012-01-26 13:37:52 -08002973 mixer_state mixerStatus = MIXER_IDLE;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002974 nsecs_t standbyTime = systemTime();
2975 size_t mixBufferSize = mFrameCount*mFrameSize;
2976 SortedVector< sp<OutputTrack> > outputTracks;
2977 uint32_t writeFrames = 0;
2978 uint32_t activeSleepTime = activeSleepTimeUs();
2979 uint32_t idleSleepTime = idleSleepTimeUs();
2980 uint32_t sleepTime = idleSleepTime;
2981 Vector< sp<EffectChain> > effectChains;
2982
Eric Laurentfeb0db62011-07-22 09:04:31 -07002983 acquireWakeLock();
2984
Mathias Agopian65ab4712010-07-14 17:59:35 -07002985 while (!exitPending())
2986 {
2987 processConfigEvents();
2988
2989 mixerStatus = MIXER_IDLE;
2990 { // scope for the mLock
2991
2992 Mutex::Autolock _l(mLock);
2993
2994 if (checkForNewParameters_l()) {
2995 mixBufferSize = mFrameCount*mFrameSize;
2996 updateWaitTime();
2997 activeSleepTime = activeSleepTimeUs();
2998 idleSleepTime = idleSleepTimeUs();
2999 }
3000
3001 const SortedVector< wp<Track> >& activeTracks = mActiveTracks;
3002
3003 for (size_t i = 0; i < mOutputTracks.size(); i++) {
3004 outputTracks.add(mOutputTracks[i]);
3005 }
3006
3007 // put audio hardware into standby after short delay
Glenn Kastenf6b16782011-12-15 09:51:17 -08003008 if (CC_UNLIKELY((!activeTracks.size() && systemTime() > standbyTime) ||
3009 mSuspended)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07003010 if (!mStandby) {
3011 for (size_t i = 0; i < outputTracks.size(); i++) {
3012 outputTracks[i]->stop();
3013 }
3014 mStandby = true;
3015 mBytesWritten = 0;
3016 }
3017
3018 if (!activeTracks.size() && mConfigEvents.isEmpty()) {
3019 // we're about to wait, flush the binder command buffer
3020 IPCThreadState::self()->flushCommands();
3021 outputTracks.clear();
3022
3023 if (exitPending()) break;
3024
Eric Laurentfeb0db62011-07-22 09:04:31 -07003025 releaseWakeLock_l();
Glenn Kasten90bebef2012-01-27 15:24:38 -08003026 ALOGV("DuplicatingThread %p TID %d going to sleep", this, gettid());
Mathias Agopian65ab4712010-07-14 17:59:35 -07003027 mWaitWorkCV.wait(mLock);
Glenn Kasten90bebef2012-01-27 15:24:38 -08003028 ALOGV("DuplicatingThread %p TID %d waking up", this, gettid());
Eric Laurentfeb0db62011-07-22 09:04:31 -07003029 acquireWakeLock_l();
3030
Eric Laurent27741442012-01-17 19:20:12 -08003031 mPrevMixerStatus = MIXER_IDLE;
Glenn Kastenf1d45922012-01-13 15:54:24 -08003032 if (!mMasterMute) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07003033 char value[PROPERTY_VALUE_MAX];
3034 property_get("ro.audio.silent", value, "0");
3035 if (atoi(value)) {
Steve Blockb8a80522011-12-20 16:23:08 +00003036 ALOGD("Silence is golden");
Mathias Agopian65ab4712010-07-14 17:59:35 -07003037 setMasterMute(true);
3038 }
3039 }
3040
3041 standbyTime = systemTime() + kStandbyTimeInNsecs;
3042 sleepTime = idleSleepTime;
3043 continue;
3044 }
3045 }
3046
3047 mixerStatus = prepareTracks_l(activeTracks, &tracksToRemove);
3048
3049 // prevent any changes in effect chain list and in each effect chain
3050 // during mixing and effect process as the audio buffers could be deleted
3051 // or modified if an effect is created or deleted
Eric Laurentde070132010-07-13 04:45:46 -07003052 lockEffectChains_l(effectChains);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003053 }
3054
Glenn Kastenf6b16782011-12-15 09:51:17 -08003055 if (CC_LIKELY(mixerStatus == MIXER_TRACKS_READY)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07003056 // mix buffers...
3057 if (outputsReady(outputTracks)) {
3058 mAudioMixer->process();
3059 } else {
3060 memset(mMixBuffer, 0, mixBufferSize);
3061 }
3062 sleepTime = 0;
3063 writeFrames = mFrameCount;
3064 } else {
3065 if (sleepTime == 0) {
3066 if (mixerStatus == MIXER_TRACKS_ENABLED) {
3067 sleepTime = activeSleepTime;
3068 } else {
3069 sleepTime = idleSleepTime;
3070 }
3071 } else if (mBytesWritten != 0) {
3072 // flush remaining overflow buffers in output tracks
3073 for (size_t i = 0; i < outputTracks.size(); i++) {
3074 if (outputTracks[i]->isActive()) {
3075 sleepTime = 0;
3076 writeFrames = 0;
3077 memset(mMixBuffer, 0, mixBufferSize);
3078 break;
3079 }
3080 }
3081 }
3082 }
3083
3084 if (mSuspended) {
Eric Laurent25cbe0e2010-08-18 18:13:17 -07003085 sleepTime = suspendSleepTimeUs();
Mathias Agopian65ab4712010-07-14 17:59:35 -07003086 }
3087 // sleepTime == 0 means we must write to audio hardware
3088 if (sleepTime == 0) {
3089 for (size_t i = 0; i < effectChains.size(); i ++) {
3090 effectChains[i]->process_l();
3091 }
3092 // enable changes in effect chain
Eric Laurentde070132010-07-13 04:45:46 -07003093 unlockEffectChains(effectChains);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003094
3095 standbyTime = systemTime() + kStandbyTimeInNsecs;
3096 for (size_t i = 0; i < outputTracks.size(); i++) {
3097 outputTracks[i]->write(mMixBuffer, writeFrames);
3098 }
3099 mStandby = false;
3100 mBytesWritten += mixBufferSize;
3101 } else {
3102 // enable changes in effect chain
Eric Laurentde070132010-07-13 04:45:46 -07003103 unlockEffectChains(effectChains);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003104 usleep(sleepTime);
3105 }
3106
3107 // finally let go of all our tracks, without the lock held
3108 // since we can't guarantee the destructors won't acquire that
3109 // same lock.
3110 tracksToRemove.clear();
3111 outputTracks.clear();
3112
3113 // Effect chains will be actually deleted here if they were removed from
3114 // mEffectChains list during mixing or effects processing
3115 effectChains.clear();
3116 }
3117
Eric Laurentfeb0db62011-07-22 09:04:31 -07003118 releaseWakeLock();
3119
Mathias Agopian65ab4712010-07-14 17:59:35 -07003120 return false;
3121}
3122
3123void AudioFlinger::DuplicatingThread::addOutputTrack(MixerThread *thread)
3124{
3125 int frameCount = (3 * mFrameCount * mSampleRate) / thread->sampleRate();
3126 OutputTrack *outputTrack = new OutputTrack((ThreadBase *)thread,
3127 this,
3128 mSampleRate,
3129 mFormat,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07003130 mChannelMask,
Mathias Agopian65ab4712010-07-14 17:59:35 -07003131 frameCount);
3132 if (outputTrack->cblk() != NULL) {
Dima Zavinfce7a472011-04-19 22:30:36 -07003133 thread->setStreamVolume(AUDIO_STREAM_CNT, 1.0f);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003134 mOutputTracks.add(outputTrack);
Steve Block3856b092011-10-20 11:56:00 +01003135 ALOGV("addOutputTrack() track %p, on thread %p", outputTrack, thread);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003136 updateWaitTime();
3137 }
3138}
3139
3140void AudioFlinger::DuplicatingThread::removeOutputTrack(MixerThread *thread)
3141{
3142 Mutex::Autolock _l(mLock);
3143 for (size_t i = 0; i < mOutputTracks.size(); i++) {
3144 if (mOutputTracks[i]->thread() == (ThreadBase *)thread) {
3145 mOutputTracks[i]->destroy();
3146 mOutputTracks.removeAt(i);
3147 updateWaitTime();
3148 return;
3149 }
3150 }
Steve Block3856b092011-10-20 11:56:00 +01003151 ALOGV("removeOutputTrack(): unkonwn thread: %p", thread);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003152}
3153
3154void AudioFlinger::DuplicatingThread::updateWaitTime()
3155{
3156 mWaitTimeMs = UINT_MAX;
3157 for (size_t i = 0; i < mOutputTracks.size(); i++) {
3158 sp<ThreadBase> strong = mOutputTracks[i]->thread().promote();
Glenn Kasten7378ca52012-01-20 13:44:40 -08003159 if (strong != 0) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07003160 uint32_t waitTimeMs = (strong->frameCount() * 2 * 1000) / strong->sampleRate();
3161 if (waitTimeMs < mWaitTimeMs) {
3162 mWaitTimeMs = waitTimeMs;
3163 }
3164 }
3165 }
3166}
3167
3168
3169bool AudioFlinger::DuplicatingThread::outputsReady(SortedVector< sp<OutputTrack> > &outputTracks)
3170{
3171 for (size_t i = 0; i < outputTracks.size(); i++) {
3172 sp <ThreadBase> thread = outputTracks[i]->thread().promote();
3173 if (thread == 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00003174 ALOGW("DuplicatingThread::outputsReady() could not promote thread on output track %p", outputTracks[i].get());
Mathias Agopian65ab4712010-07-14 17:59:35 -07003175 return false;
3176 }
3177 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
3178 if (playbackThread->standby() && !playbackThread->isSuspended()) {
Steve Block3856b092011-10-20 11:56:00 +01003179 ALOGV("DuplicatingThread output track %p on thread %p Not Ready", outputTracks[i].get(), thread.get());
Mathias Agopian65ab4712010-07-14 17:59:35 -07003180 return false;
3181 }
3182 }
3183 return true;
3184}
3185
3186uint32_t AudioFlinger::DuplicatingThread::activeSleepTimeUs()
3187{
3188 return (mWaitTimeMs * 1000) / 2;
3189}
3190
3191// ----------------------------------------------------------------------------
3192
3193// TrackBase constructor must be called with AudioFlinger::mLock held
3194AudioFlinger::ThreadBase::TrackBase::TrackBase(
3195 const wp<ThreadBase>& thread,
3196 const sp<Client>& client,
3197 uint32_t sampleRate,
Glenn Kasten58f30212012-01-12 12:27:51 -08003198 audio_format_t format,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07003199 uint32_t channelMask,
Mathias Agopian65ab4712010-07-14 17:59:35 -07003200 int frameCount,
3201 uint32_t flags,
3202 const sp<IMemory>& sharedBuffer,
3203 int sessionId)
3204 : RefBase(),
3205 mThread(thread),
3206 mClient(client),
Glenn Kasten84afa3b2012-01-25 15:28:08 -08003207 mCblk(NULL),
3208 // mBuffer
3209 // mBufferEnd
Mathias Agopian65ab4712010-07-14 17:59:35 -07003210 mFrameCount(0),
3211 mState(IDLE),
Mathias Agopian65ab4712010-07-14 17:59:35 -07003212 mFormat(format),
3213 mFlags(flags & ~SYSTEM_FLAGS_MASK),
3214 mSessionId(sessionId)
Glenn Kasten84afa3b2012-01-25 15:28:08 -08003215 // mChannelCount
3216 // mChannelMask
Mathias Agopian65ab4712010-07-14 17:59:35 -07003217{
Steve Block3856b092011-10-20 11:56:00 +01003218 ALOGV_IF(sharedBuffer != 0, "sharedBuffer: %p, size: %d", sharedBuffer->pointer(), sharedBuffer->size());
Mathias Agopian65ab4712010-07-14 17:59:35 -07003219
Steve Blockb8a80522011-12-20 16:23:08 +00003220 // ALOGD("Creating track with %d buffers @ %d bytes", bufferCount, bufferSize);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003221 size_t size = sizeof(audio_track_cblk_t);
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07003222 uint8_t channelCount = popcount(channelMask);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003223 size_t bufferSize = frameCount*channelCount*sizeof(int16_t);
3224 if (sharedBuffer == 0) {
3225 size += bufferSize;
3226 }
3227
3228 if (client != NULL) {
3229 mCblkMemory = client->heap()->allocate(size);
3230 if (mCblkMemory != 0) {
3231 mCblk = static_cast<audio_track_cblk_t *>(mCblkMemory->pointer());
Glenn Kastena0d68332012-01-27 16:47:15 -08003232 if (mCblk != NULL) { // construct the shared structure in-place.
Mathias Agopian65ab4712010-07-14 17:59:35 -07003233 new(mCblk) audio_track_cblk_t();
3234 // clear all buffers
3235 mCblk->frameCount = frameCount;
3236 mCblk->sampleRate = sampleRate;
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07003237 mChannelCount = channelCount;
3238 mChannelMask = channelMask;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003239 if (sharedBuffer == 0) {
3240 mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t);
3241 memset(mBuffer, 0, frameCount*channelCount*sizeof(int16_t));
3242 // Force underrun condition to avoid false underrun callback until first data is
Eric Laurent44d98482010-09-30 16:12:31 -07003243 // written to buffer (other flags are cleared)
Mathias Agopian65ab4712010-07-14 17:59:35 -07003244 mCblk->flags = CBLK_UNDERRUN_ON;
3245 } else {
3246 mBuffer = sharedBuffer->pointer();
3247 }
3248 mBufferEnd = (uint8_t *)mBuffer + bufferSize;
3249 }
3250 } else {
Steve Block29357bc2012-01-06 19:20:56 +00003251 ALOGE("not enough memory for AudioTrack size=%u", size);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003252 client->heap()->dump("AudioTrack");
3253 return;
3254 }
3255 } else {
3256 mCblk = (audio_track_cblk_t *)(new uint8_t[size]);
Glenn Kasten4a6f0282012-01-06 15:03:11 -08003257 // construct the shared structure in-place.
Mathias Agopian65ab4712010-07-14 17:59:35 -07003258 new(mCblk) audio_track_cblk_t();
3259 // clear all buffers
3260 mCblk->frameCount = frameCount;
3261 mCblk->sampleRate = sampleRate;
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07003262 mChannelCount = channelCount;
3263 mChannelMask = channelMask;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003264 mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t);
3265 memset(mBuffer, 0, frameCount*channelCount*sizeof(int16_t));
3266 // Force underrun condition to avoid false underrun callback until first data is
Eric Laurent44d98482010-09-30 16:12:31 -07003267 // written to buffer (other flags are cleared)
Mathias Agopian65ab4712010-07-14 17:59:35 -07003268 mCblk->flags = CBLK_UNDERRUN_ON;
3269 mBufferEnd = (uint8_t *)mBuffer + bufferSize;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003270 }
3271}
3272
3273AudioFlinger::ThreadBase::TrackBase::~TrackBase()
3274{
Glenn Kastena0d68332012-01-27 16:47:15 -08003275 if (mCblk != NULL) {
Glenn Kasten1a0ae5b2012-02-03 10:24:48 -08003276 if (mClient == 0) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07003277 delete mCblk;
Glenn Kasten1a0ae5b2012-02-03 10:24:48 -08003278 } else {
3279 mCblk->~audio_track_cblk_t(); // destroy our shared-structure.
Mathias Agopian65ab4712010-07-14 17:59:35 -07003280 }
3281 }
Glenn Kastendbfafaf2012-01-25 15:27:15 -08003282 mCblkMemory.clear(); // free the shared memory before releasing the heap it belongs to
Glenn Kasten7378ca52012-01-20 13:44:40 -08003283 if (mClient != 0) {
Glenn Kasten84afa3b2012-01-25 15:28:08 -08003284 // Client destructor must run with AudioFlinger mutex locked
Mathias Agopian65ab4712010-07-14 17:59:35 -07003285 Mutex::Autolock _l(mClient->audioFlinger()->mLock);
Glenn Kasten7378ca52012-01-20 13:44:40 -08003286 // If the client's reference count drops to zero, the associated destructor
3287 // must run with AudioFlinger lock held. Thus the explicit clear() rather than
3288 // relying on the automatic clear() at end of scope.
Mathias Agopian65ab4712010-07-14 17:59:35 -07003289 mClient.clear();
3290 }
3291}
3292
3293void AudioFlinger::ThreadBase::TrackBase::releaseBuffer(AudioBufferProvider::Buffer* buffer)
3294{
Glenn Kastene0feee32011-12-13 11:53:26 -08003295 buffer->raw = NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003296 mFrameCount = buffer->frameCount;
3297 step();
3298 buffer->frameCount = 0;
3299}
3300
3301bool AudioFlinger::ThreadBase::TrackBase::step() {
3302 bool result;
3303 audio_track_cblk_t* cblk = this->cblk();
3304
3305 result = cblk->stepServer(mFrameCount);
3306 if (!result) {
Steve Block3856b092011-10-20 11:56:00 +01003307 ALOGV("stepServer failed acquiring cblk mutex");
Mathias Agopian65ab4712010-07-14 17:59:35 -07003308 mFlags |= STEPSERVER_FAILED;
3309 }
3310 return result;
3311}
3312
3313void AudioFlinger::ThreadBase::TrackBase::reset() {
3314 audio_track_cblk_t* cblk = this->cblk();
3315
3316 cblk->user = 0;
3317 cblk->server = 0;
3318 cblk->userBase = 0;
3319 cblk->serverBase = 0;
3320 mFlags &= (uint32_t)(~SYSTEM_FLAGS_MASK);
Steve Block3856b092011-10-20 11:56:00 +01003321 ALOGV("TrackBase::reset");
Mathias Agopian65ab4712010-07-14 17:59:35 -07003322}
3323
Mathias Agopian65ab4712010-07-14 17:59:35 -07003324int AudioFlinger::ThreadBase::TrackBase::sampleRate() const {
3325 return (int)mCblk->sampleRate;
3326}
3327
Mathias Agopian65ab4712010-07-14 17:59:35 -07003328void* AudioFlinger::ThreadBase::TrackBase::getBuffer(uint32_t offset, uint32_t frames) const {
3329 audio_track_cblk_t* cblk = this->cblk();
Glenn Kastenb9980652012-01-11 09:48:27 -08003330 size_t frameSize = cblk->frameSize;
3331 int8_t *bufferStart = (int8_t *)mBuffer + (offset-cblk->serverBase)*frameSize;
3332 int8_t *bufferEnd = bufferStart + frames * frameSize;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003333
3334 // Check validity of returned pointer in case the track control block would have been corrupted.
3335 if (bufferStart < mBuffer || bufferStart > bufferEnd || bufferEnd > mBufferEnd ||
Glenn Kastenb9980652012-01-11 09:48:27 -08003336 ((unsigned long)bufferStart & (unsigned long)(frameSize - 1))) {
Steve Block29357bc2012-01-06 19:20:56 +00003337 ALOGE("TrackBase::getBuffer buffer out of range:\n start: %p, end %p , mBuffer %p mBufferEnd %p\n \
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07003338 server %d, serverBase %d, user %d, userBase %d",
Mathias Agopian65ab4712010-07-14 17:59:35 -07003339 bufferStart, bufferEnd, mBuffer, mBufferEnd,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07003340 cblk->server, cblk->serverBase, cblk->user, cblk->userBase);
Glenn Kastena0d68332012-01-27 16:47:15 -08003341 return NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003342 }
3343
3344 return bufferStart;
3345}
3346
3347// ----------------------------------------------------------------------------
3348
3349// Track constructor must be called with AudioFlinger::mLock and ThreadBase::mLock held
3350AudioFlinger::PlaybackThread::Track::Track(
3351 const wp<ThreadBase>& thread,
3352 const sp<Client>& client,
Glenn Kastenfff6d712012-01-12 16:38:12 -08003353 audio_stream_type_t streamType,
Mathias Agopian65ab4712010-07-14 17:59:35 -07003354 uint32_t sampleRate,
Glenn Kasten58f30212012-01-12 12:27:51 -08003355 audio_format_t format,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07003356 uint32_t channelMask,
Mathias Agopian65ab4712010-07-14 17:59:35 -07003357 int frameCount,
3358 const sp<IMemory>& sharedBuffer,
3359 int sessionId)
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07003360 : TrackBase(thread, client, sampleRate, format, channelMask, frameCount, 0, sharedBuffer, sessionId),
Eric Laurent8f45bd72010-08-31 13:50:07 -07003361 mMute(false), mSharedBuffer(sharedBuffer), mName(-1), mMainBuffer(NULL), mAuxBuffer(NULL),
3362 mAuxEffectId(0), mHasVolumeController(false)
Mathias Agopian65ab4712010-07-14 17:59:35 -07003363{
3364 if (mCblk != NULL) {
3365 sp<ThreadBase> baseThread = thread.promote();
3366 if (baseThread != 0) {
3367 PlaybackThread *playbackThread = (PlaybackThread *)baseThread.get();
3368 mName = playbackThread->getTrackName_l();
3369 mMainBuffer = playbackThread->mixBuffer();
3370 }
Glenn Kasten23d82a92012-02-03 11:10:00 -08003371 ALOGV("Track constructor name %d, calling pid %d", mName, IPCThreadState::self()->getCallingPid());
Mathias Agopian65ab4712010-07-14 17:59:35 -07003372 if (mName < 0) {
Steve Block29357bc2012-01-06 19:20:56 +00003373 ALOGE("no more track names available");
Mathias Agopian65ab4712010-07-14 17:59:35 -07003374 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07003375 mStreamType = streamType;
3376 // NOTE: audio_track_cblk_t::frameSize for 8 bit PCM data is based on a sample size of
3377 // 16 bit because data is converted to 16 bit before being stored in buffer by AudioTrack
Eric Laurentedc15ad2011-07-21 19:35:01 -07003378 mCblk->frameSize = audio_is_linear_pcm(format) ? mChannelCount * sizeof(int16_t) : sizeof(uint8_t);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003379 }
3380}
3381
3382AudioFlinger::PlaybackThread::Track::~Track()
3383{
Steve Block3856b092011-10-20 11:56:00 +01003384 ALOGV("PlaybackThread::Track destructor");
Mathias Agopian65ab4712010-07-14 17:59:35 -07003385 sp<ThreadBase> thread = mThread.promote();
3386 if (thread != 0) {
3387 Mutex::Autolock _l(thread->mLock);
3388 mState = TERMINATED;
3389 }
3390}
3391
3392void AudioFlinger::PlaybackThread::Track::destroy()
3393{
3394 // NOTE: destroyTrack_l() can remove a strong reference to this Track
3395 // by removing it from mTracks vector, so there is a risk that this Tracks's
3396 // desctructor is called. As the destructor needs to lock mLock,
3397 // we must acquire a strong reference on this Track before locking mLock
3398 // here so that the destructor is called only when exiting this function.
3399 // On the other hand, as long as Track::destroy() is only called by
3400 // TrackHandle destructor, the TrackHandle still holds a strong ref on
3401 // this Track with its member mTrack.
3402 sp<Track> keep(this);
3403 { // scope for mLock
3404 sp<ThreadBase> thread = mThread.promote();
3405 if (thread != 0) {
3406 if (!isOutputTrack()) {
3407 if (mState == ACTIVE || mState == RESUMING) {
Glenn Kasten02bbd202012-02-08 12:35:35 -08003408 AudioSystem::stopOutput(thread->id(), mStreamType, mSessionId);
Gloria Wang9ee159b2011-02-24 14:51:45 -08003409
3410 // to track the speaker usage
3411 addBatteryData(IMediaPlayerService::kBatteryDataAudioFlingerStop);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003412 }
3413 AudioSystem::releaseOutput(thread->id());
3414 }
3415 Mutex::Autolock _l(thread->mLock);
3416 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
3417 playbackThread->destroyTrack_l(this);
3418 }
3419 }
3420}
3421
3422void AudioFlinger::PlaybackThread::Track::dump(char* buffer, size_t size)
3423{
Glenn Kasten83d86532012-01-17 14:39:34 -08003424 uint32_t vlr = mCblk->getVolumeLR();
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07003425 snprintf(buffer, size, " %05d %05d %03u %03u 0x%08x %05u %04u %1d %1d %1d %05u %05u %05u 0x%08x 0x%08x 0x%08x 0x%08x\n",
Mathias Agopian65ab4712010-07-14 17:59:35 -07003426 mName - AudioMixer::TRACK0,
Glenn Kasten44deb052012-02-05 18:09:08 -08003427 (mClient == 0) ? getpid_cached : mClient->pid(),
Mathias Agopian65ab4712010-07-14 17:59:35 -07003428 mStreamType,
3429 mFormat,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07003430 mChannelMask,
Mathias Agopian65ab4712010-07-14 17:59:35 -07003431 mSessionId,
3432 mFrameCount,
3433 mState,
3434 mMute,
3435 mFillingUpStatus,
3436 mCblk->sampleRate,
Glenn Kastenb1cf75c2012-01-17 12:20:54 -08003437 vlr & 0xFFFF,
3438 vlr >> 16,
Mathias Agopian65ab4712010-07-14 17:59:35 -07003439 mCblk->server,
3440 mCblk->user,
3441 (int)mMainBuffer,
3442 (int)mAuxBuffer);
3443}
3444
3445status_t AudioFlinger::PlaybackThread::Track::getNextBuffer(AudioBufferProvider::Buffer* buffer)
3446{
3447 audio_track_cblk_t* cblk = this->cblk();
3448 uint32_t framesReady;
3449 uint32_t framesReq = buffer->frameCount;
3450
3451 // Check if last stepServer failed, try to step now
3452 if (mFlags & TrackBase::STEPSERVER_FAILED) {
3453 if (!step()) goto getNextBuffer_exit;
Steve Block3856b092011-10-20 11:56:00 +01003454 ALOGV("stepServer recovered");
Mathias Agopian65ab4712010-07-14 17:59:35 -07003455 mFlags &= ~TrackBase::STEPSERVER_FAILED;
3456 }
3457
3458 framesReady = cblk->framesReady();
3459
Glenn Kastenf6b16782011-12-15 09:51:17 -08003460 if (CC_LIKELY(framesReady)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07003461 uint32_t s = cblk->server;
3462 uint32_t bufferEnd = cblk->serverBase + cblk->frameCount;
3463
3464 bufferEnd = (cblk->loopEnd < bufferEnd) ? cblk->loopEnd : bufferEnd;
3465 if (framesReq > framesReady) {
3466 framesReq = framesReady;
3467 }
3468 if (s + framesReq > bufferEnd) {
3469 framesReq = bufferEnd - s;
3470 }
3471
3472 buffer->raw = getBuffer(s, framesReq);
Glenn Kastene0feee32011-12-13 11:53:26 -08003473 if (buffer->raw == NULL) goto getNextBuffer_exit;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003474
3475 buffer->frameCount = framesReq;
3476 return NO_ERROR;
3477 }
3478
3479getNextBuffer_exit:
Glenn Kastene0feee32011-12-13 11:53:26 -08003480 buffer->raw = NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003481 buffer->frameCount = 0;
Steve Block3856b092011-10-20 11:56:00 +01003482 ALOGV("getNextBuffer() no more data for track %d on thread %p", mName, mThread.unsafe_get());
Mathias Agopian65ab4712010-07-14 17:59:35 -07003483 return NOT_ENOUGH_DATA;
3484}
3485
3486bool AudioFlinger::PlaybackThread::Track::isReady() const {
Eric Laurentaf59ce22010-10-05 14:41:42 -07003487 if (mFillingUpStatus != FS_FILLING || isStopped() || isPausing()) return true;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003488
3489 if (mCblk->framesReady() >= mCblk->frameCount ||
3490 (mCblk->flags & CBLK_FORCEREADY_MSK)) {
3491 mFillingUpStatus = FS_FILLED;
Eric Laurent38ccae22011-03-28 18:37:07 -07003492 android_atomic_and(~CBLK_FORCEREADY_MSK, &mCblk->flags);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003493 return true;
3494 }
3495 return false;
3496}
3497
Glenn Kasten6dbc1352012-02-02 10:56:47 -08003498status_t AudioFlinger::PlaybackThread::Track::start(pid_t tid)
Mathias Agopian65ab4712010-07-14 17:59:35 -07003499{
3500 status_t status = NO_ERROR;
Glenn Kasten6dbc1352012-02-02 10:56:47 -08003501 ALOGV("start(%d), calling pid %d session %d tid %d",
3502 mName, IPCThreadState::self()->getCallingPid(), mSessionId, tid);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003503 sp<ThreadBase> thread = mThread.promote();
3504 if (thread != 0) {
3505 Mutex::Autolock _l(thread->mLock);
Glenn Kastenb853e982012-01-26 13:39:18 -08003506 track_state state = mState;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003507 // here the track could be either new, or restarted
3508 // in both cases "unstop" the track
3509 if (mState == PAUSED) {
3510 mState = TrackBase::RESUMING;
Steve Block3856b092011-10-20 11:56:00 +01003511 ALOGV("PAUSED => RESUMING (%d) on thread %p", mName, this);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003512 } else {
3513 mState = TrackBase::ACTIVE;
Steve Block3856b092011-10-20 11:56:00 +01003514 ALOGV("? => ACTIVE (%d) on thread %p", mName, this);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003515 }
3516
3517 if (!isOutputTrack() && state != ACTIVE && state != RESUMING) {
3518 thread->mLock.unlock();
Glenn Kasten02bbd202012-02-08 12:35:35 -08003519 status = AudioSystem::startOutput(thread->id(), mStreamType, mSessionId);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003520 thread->mLock.lock();
Gloria Wang9ee159b2011-02-24 14:51:45 -08003521
3522 // to track the speaker usage
3523 if (status == NO_ERROR) {
3524 addBatteryData(IMediaPlayerService::kBatteryDataAudioFlingerStart);
3525 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07003526 }
3527 if (status == NO_ERROR) {
3528 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
3529 playbackThread->addTrack_l(this);
3530 } else {
3531 mState = state;
3532 }
3533 } else {
3534 status = BAD_VALUE;
3535 }
3536 return status;
3537}
3538
3539void AudioFlinger::PlaybackThread::Track::stop()
3540{
Glenn Kasten23d82a92012-02-03 11:10:00 -08003541 ALOGV("stop(%d), calling pid %d", mName, IPCThreadState::self()->getCallingPid());
Mathias Agopian65ab4712010-07-14 17:59:35 -07003542 sp<ThreadBase> thread = mThread.promote();
3543 if (thread != 0) {
3544 Mutex::Autolock _l(thread->mLock);
Glenn Kastenb853e982012-01-26 13:39:18 -08003545 track_state state = mState;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003546 if (mState > STOPPED) {
3547 mState = STOPPED;
3548 // If the track is not active (PAUSED and buffers full), flush buffers
3549 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
3550 if (playbackThread->mActiveTracks.indexOf(this) < 0) {
3551 reset();
3552 }
Steve Block3856b092011-10-20 11:56:00 +01003553 ALOGV("(> STOPPED) => STOPPED (%d) on thread %p", mName, playbackThread);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003554 }
3555 if (!isOutputTrack() && (state == ACTIVE || state == RESUMING)) {
3556 thread->mLock.unlock();
Glenn Kasten02bbd202012-02-08 12:35:35 -08003557 AudioSystem::stopOutput(thread->id(), mStreamType, mSessionId);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003558 thread->mLock.lock();
Gloria Wang9ee159b2011-02-24 14:51:45 -08003559
3560 // to track the speaker usage
3561 addBatteryData(IMediaPlayerService::kBatteryDataAudioFlingerStop);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003562 }
3563 }
3564}
3565
3566void AudioFlinger::PlaybackThread::Track::pause()
3567{
Glenn Kasten23d82a92012-02-03 11:10:00 -08003568 ALOGV("pause(%d), calling pid %d", mName, IPCThreadState::self()->getCallingPid());
Mathias Agopian65ab4712010-07-14 17:59:35 -07003569 sp<ThreadBase> thread = mThread.promote();
3570 if (thread != 0) {
3571 Mutex::Autolock _l(thread->mLock);
3572 if (mState == ACTIVE || mState == RESUMING) {
3573 mState = PAUSING;
Steve Block3856b092011-10-20 11:56:00 +01003574 ALOGV("ACTIVE/RESUMING => PAUSING (%d) on thread %p", mName, thread.get());
Mathias Agopian65ab4712010-07-14 17:59:35 -07003575 if (!isOutputTrack()) {
3576 thread->mLock.unlock();
Glenn Kasten02bbd202012-02-08 12:35:35 -08003577 AudioSystem::stopOutput(thread->id(), mStreamType, mSessionId);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003578 thread->mLock.lock();
Gloria Wang9ee159b2011-02-24 14:51:45 -08003579
3580 // to track the speaker usage
3581 addBatteryData(IMediaPlayerService::kBatteryDataAudioFlingerStop);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003582 }
3583 }
3584 }
3585}
3586
3587void AudioFlinger::PlaybackThread::Track::flush()
3588{
Steve Block3856b092011-10-20 11:56:00 +01003589 ALOGV("flush(%d)", mName);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003590 sp<ThreadBase> thread = mThread.promote();
3591 if (thread != 0) {
3592 Mutex::Autolock _l(thread->mLock);
3593 if (mState != STOPPED && mState != PAUSED && mState != PAUSING) {
3594 return;
3595 }
3596 // No point remaining in PAUSED state after a flush => go to
3597 // STOPPED state
3598 mState = STOPPED;
3599
Eric Laurent38ccae22011-03-28 18:37:07 -07003600 // do not reset the track if it is still in the process of being stopped or paused.
3601 // this will be done by prepareTracks_l() when the track is stopped.
3602 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
3603 if (playbackThread->mActiveTracks.indexOf(this) < 0) {
3604 reset();
3605 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07003606 }
3607}
3608
3609void AudioFlinger::PlaybackThread::Track::reset()
3610{
3611 // Do not reset twice to avoid discarding data written just after a flush and before
3612 // the audioflinger thread detects the track is stopped.
3613 if (!mResetDone) {
3614 TrackBase::reset();
3615 // Force underrun condition to avoid false underrun callback until first data is
3616 // written to buffer
Eric Laurent38ccae22011-03-28 18:37:07 -07003617 android_atomic_and(~CBLK_FORCEREADY_MSK, &mCblk->flags);
3618 android_atomic_or(CBLK_UNDERRUN_ON, &mCblk->flags);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003619 mFillingUpStatus = FS_FILLING;
3620 mResetDone = true;
3621 }
3622}
3623
3624void AudioFlinger::PlaybackThread::Track::mute(bool muted)
3625{
3626 mMute = muted;
3627}
3628
Mathias Agopian65ab4712010-07-14 17:59:35 -07003629status_t AudioFlinger::PlaybackThread::Track::attachAuxEffect(int EffectId)
3630{
3631 status_t status = DEAD_OBJECT;
3632 sp<ThreadBase> thread = mThread.promote();
3633 if (thread != 0) {
3634 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
3635 status = playbackThread->attachAuxEffect(this, EffectId);
3636 }
3637 return status;
3638}
3639
3640void AudioFlinger::PlaybackThread::Track::setAuxBuffer(int EffectId, int32_t *buffer)
3641{
3642 mAuxEffectId = EffectId;
3643 mAuxBuffer = buffer;
3644}
3645
3646// ----------------------------------------------------------------------------
3647
3648// RecordTrack constructor must be called with AudioFlinger::mLock held
3649AudioFlinger::RecordThread::RecordTrack::RecordTrack(
3650 const wp<ThreadBase>& thread,
3651 const sp<Client>& client,
3652 uint32_t sampleRate,
Glenn Kasten58f30212012-01-12 12:27:51 -08003653 audio_format_t format,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07003654 uint32_t channelMask,
Mathias Agopian65ab4712010-07-14 17:59:35 -07003655 int frameCount,
3656 uint32_t flags,
3657 int sessionId)
3658 : TrackBase(thread, client, sampleRate, format,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07003659 channelMask, frameCount, flags, 0, sessionId),
Mathias Agopian65ab4712010-07-14 17:59:35 -07003660 mOverflow(false)
3661{
3662 if (mCblk != NULL) {
Steve Block3856b092011-10-20 11:56:00 +01003663 ALOGV("RecordTrack constructor, size %d", (int)mBufferEnd - (int)mBuffer);
Dima Zavinfce7a472011-04-19 22:30:36 -07003664 if (format == AUDIO_FORMAT_PCM_16_BIT) {
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07003665 mCblk->frameSize = mChannelCount * sizeof(int16_t);
Dima Zavinfce7a472011-04-19 22:30:36 -07003666 } else if (format == AUDIO_FORMAT_PCM_8_BIT) {
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07003667 mCblk->frameSize = mChannelCount * sizeof(int8_t);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003668 } else {
3669 mCblk->frameSize = sizeof(int8_t);
3670 }
3671 }
3672}
3673
3674AudioFlinger::RecordThread::RecordTrack::~RecordTrack()
3675{
3676 sp<ThreadBase> thread = mThread.promote();
3677 if (thread != 0) {
3678 AudioSystem::releaseInput(thread->id());
3679 }
3680}
3681
3682status_t AudioFlinger::RecordThread::RecordTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer)
3683{
3684 audio_track_cblk_t* cblk = this->cblk();
3685 uint32_t framesAvail;
3686 uint32_t framesReq = buffer->frameCount;
3687
3688 // Check if last stepServer failed, try to step now
3689 if (mFlags & TrackBase::STEPSERVER_FAILED) {
3690 if (!step()) goto getNextBuffer_exit;
Steve Block3856b092011-10-20 11:56:00 +01003691 ALOGV("stepServer recovered");
Mathias Agopian65ab4712010-07-14 17:59:35 -07003692 mFlags &= ~TrackBase::STEPSERVER_FAILED;
3693 }
3694
3695 framesAvail = cblk->framesAvailable_l();
3696
Glenn Kastenf6b16782011-12-15 09:51:17 -08003697 if (CC_LIKELY(framesAvail)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07003698 uint32_t s = cblk->server;
3699 uint32_t bufferEnd = cblk->serverBase + cblk->frameCount;
3700
3701 if (framesReq > framesAvail) {
3702 framesReq = framesAvail;
3703 }
3704 if (s + framesReq > bufferEnd) {
3705 framesReq = bufferEnd - s;
3706 }
3707
3708 buffer->raw = getBuffer(s, framesReq);
Glenn Kastene0feee32011-12-13 11:53:26 -08003709 if (buffer->raw == NULL) goto getNextBuffer_exit;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003710
3711 buffer->frameCount = framesReq;
3712 return NO_ERROR;
3713 }
3714
3715getNextBuffer_exit:
Glenn Kastene0feee32011-12-13 11:53:26 -08003716 buffer->raw = NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003717 buffer->frameCount = 0;
3718 return NOT_ENOUGH_DATA;
3719}
3720
Glenn Kasten6dbc1352012-02-02 10:56:47 -08003721status_t AudioFlinger::RecordThread::RecordTrack::start(pid_t tid)
Mathias Agopian65ab4712010-07-14 17:59:35 -07003722{
3723 sp<ThreadBase> thread = mThread.promote();
3724 if (thread != 0) {
3725 RecordThread *recordThread = (RecordThread *)thread.get();
Glenn Kasten6dbc1352012-02-02 10:56:47 -08003726 return recordThread->start(this, tid);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003727 } else {
3728 return BAD_VALUE;
3729 }
3730}
3731
3732void AudioFlinger::RecordThread::RecordTrack::stop()
3733{
3734 sp<ThreadBase> thread = mThread.promote();
3735 if (thread != 0) {
3736 RecordThread *recordThread = (RecordThread *)thread.get();
3737 recordThread->stop(this);
Eric Laurent38ccae22011-03-28 18:37:07 -07003738 TrackBase::reset();
3739 // Force overerrun condition to avoid false overrun callback until first data is
3740 // read from buffer
3741 android_atomic_or(CBLK_UNDERRUN_ON, &mCblk->flags);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003742 }
3743}
3744
3745void AudioFlinger::RecordThread::RecordTrack::dump(char* buffer, size_t size)
3746{
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07003747 snprintf(buffer, size, " %05d %03u 0x%08x %05d %04u %01d %05u %08x %08x\n",
Glenn Kasten44deb052012-02-05 18:09:08 -08003748 (mClient == 0) ? getpid_cached : mClient->pid(),
Mathias Agopian65ab4712010-07-14 17:59:35 -07003749 mFormat,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07003750 mChannelMask,
Mathias Agopian65ab4712010-07-14 17:59:35 -07003751 mSessionId,
3752 mFrameCount,
3753 mState,
3754 mCblk->sampleRate,
3755 mCblk->server,
3756 mCblk->user);
3757}
3758
3759
3760// ----------------------------------------------------------------------------
3761
3762AudioFlinger::PlaybackThread::OutputTrack::OutputTrack(
3763 const wp<ThreadBase>& thread,
3764 DuplicatingThread *sourceThread,
3765 uint32_t sampleRate,
Glenn Kasten58f30212012-01-12 12:27:51 -08003766 audio_format_t format,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07003767 uint32_t channelMask,
Mathias Agopian65ab4712010-07-14 17:59:35 -07003768 int frameCount)
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07003769 : Track(thread, NULL, AUDIO_STREAM_CNT, sampleRate, format, channelMask, frameCount, NULL, 0),
Mathias Agopian65ab4712010-07-14 17:59:35 -07003770 mActive(false), mSourceThread(sourceThread)
3771{
3772
3773 PlaybackThread *playbackThread = (PlaybackThread *)thread.unsafe_get();
3774 if (mCblk != NULL) {
3775 mCblk->flags |= CBLK_DIRECTION_OUT;
3776 mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003777 mOutBuffer.frameCount = 0;
3778 playbackThread->mTracks.add(this);
Steve Block3856b092011-10-20 11:56:00 +01003779 ALOGV("OutputTrack constructor mCblk %p, mBuffer %p, mCblk->buffers %p, " \
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07003780 "mCblk->frameCount %d, mCblk->sampleRate %d, mChannelMask 0x%08x mBufferEnd %p",
3781 mCblk, mBuffer, mCblk->buffers,
3782 mCblk->frameCount, mCblk->sampleRate, mChannelMask, mBufferEnd);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003783 } else {
Steve Block5ff1dd52012-01-05 23:22:43 +00003784 ALOGW("Error creating output track on thread %p", playbackThread);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003785 }
3786}
3787
3788AudioFlinger::PlaybackThread::OutputTrack::~OutputTrack()
3789{
3790 clearBufferQueue();
3791}
3792
Glenn Kasten6dbc1352012-02-02 10:56:47 -08003793status_t AudioFlinger::PlaybackThread::OutputTrack::start(pid_t tid)
Mathias Agopian65ab4712010-07-14 17:59:35 -07003794{
Glenn Kasten6dbc1352012-02-02 10:56:47 -08003795 status_t status = Track::start(tid);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003796 if (status != NO_ERROR) {
3797 return status;
3798 }
3799
3800 mActive = true;
3801 mRetryCount = 127;
3802 return status;
3803}
3804
3805void AudioFlinger::PlaybackThread::OutputTrack::stop()
3806{
3807 Track::stop();
3808 clearBufferQueue();
3809 mOutBuffer.frameCount = 0;
3810 mActive = false;
3811}
3812
3813bool AudioFlinger::PlaybackThread::OutputTrack::write(int16_t* data, uint32_t frames)
3814{
3815 Buffer *pInBuffer;
3816 Buffer inBuffer;
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07003817 uint32_t channelCount = mChannelCount;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003818 bool outputBufferFull = false;
3819 inBuffer.frameCount = frames;
3820 inBuffer.i16 = data;
3821
3822 uint32_t waitTimeLeftMs = mSourceThread->waitTimeMs();
3823
3824 if (!mActive && frames != 0) {
Glenn Kasten6dbc1352012-02-02 10:56:47 -08003825 start(0);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003826 sp<ThreadBase> thread = mThread.promote();
3827 if (thread != 0) {
3828 MixerThread *mixerThread = (MixerThread *)thread.get();
3829 if (mCblk->frameCount > frames){
3830 if (mBufferQueue.size() < kMaxOverFlowBuffers) {
3831 uint32_t startFrames = (mCblk->frameCount - frames);
3832 pInBuffer = new Buffer;
3833 pInBuffer->mBuffer = new int16_t[startFrames * channelCount];
3834 pInBuffer->frameCount = startFrames;
3835 pInBuffer->i16 = pInBuffer->mBuffer;
3836 memset(pInBuffer->raw, 0, startFrames * channelCount * sizeof(int16_t));
3837 mBufferQueue.add(pInBuffer);
3838 } else {
Steve Block5ff1dd52012-01-05 23:22:43 +00003839 ALOGW ("OutputTrack::write() %p no more buffers in queue", this);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003840 }
3841 }
3842 }
3843 }
3844
3845 while (waitTimeLeftMs) {
3846 // First write pending buffers, then new data
3847 if (mBufferQueue.size()) {
3848 pInBuffer = mBufferQueue.itemAt(0);
3849 } else {
3850 pInBuffer = &inBuffer;
3851 }
3852
3853 if (pInBuffer->frameCount == 0) {
3854 break;
3855 }
3856
3857 if (mOutBuffer.frameCount == 0) {
3858 mOutBuffer.frameCount = pInBuffer->frameCount;
3859 nsecs_t startTime = systemTime();
Glenn Kasten335787f2012-01-20 17:00:00 -08003860 if (obtainBuffer(&mOutBuffer, waitTimeLeftMs) == (status_t)NO_MORE_BUFFERS) {
Steve Block3856b092011-10-20 11:56:00 +01003861 ALOGV ("OutputTrack::write() %p thread %p no more output buffers", this, mThread.unsafe_get());
Mathias Agopian65ab4712010-07-14 17:59:35 -07003862 outputBufferFull = true;
3863 break;
3864 }
3865 uint32_t waitTimeMs = (uint32_t)ns2ms(systemTime() - startTime);
3866 if (waitTimeLeftMs >= waitTimeMs) {
3867 waitTimeLeftMs -= waitTimeMs;
3868 } else {
3869 waitTimeLeftMs = 0;
3870 }
3871 }
3872
3873 uint32_t outFrames = pInBuffer->frameCount > mOutBuffer.frameCount ? mOutBuffer.frameCount : pInBuffer->frameCount;
3874 memcpy(mOutBuffer.raw, pInBuffer->raw, outFrames * channelCount * sizeof(int16_t));
3875 mCblk->stepUser(outFrames);
3876 pInBuffer->frameCount -= outFrames;
3877 pInBuffer->i16 += outFrames * channelCount;
3878 mOutBuffer.frameCount -= outFrames;
3879 mOutBuffer.i16 += outFrames * channelCount;
3880
3881 if (pInBuffer->frameCount == 0) {
3882 if (mBufferQueue.size()) {
3883 mBufferQueue.removeAt(0);
3884 delete [] pInBuffer->mBuffer;
3885 delete pInBuffer;
Steve Block3856b092011-10-20 11:56:00 +01003886 ALOGV("OutputTrack::write() %p thread %p released overflow buffer %d", this, mThread.unsafe_get(), mBufferQueue.size());
Mathias Agopian65ab4712010-07-14 17:59:35 -07003887 } else {
3888 break;
3889 }
3890 }
3891 }
3892
3893 // If we could not write all frames, allocate a buffer and queue it for next time.
3894 if (inBuffer.frameCount) {
3895 sp<ThreadBase> thread = mThread.promote();
3896 if (thread != 0 && !thread->standby()) {
3897 if (mBufferQueue.size() < kMaxOverFlowBuffers) {
3898 pInBuffer = new Buffer;
3899 pInBuffer->mBuffer = new int16_t[inBuffer.frameCount * channelCount];
3900 pInBuffer->frameCount = inBuffer.frameCount;
3901 pInBuffer->i16 = pInBuffer->mBuffer;
3902 memcpy(pInBuffer->raw, inBuffer.raw, inBuffer.frameCount * channelCount * sizeof(int16_t));
3903 mBufferQueue.add(pInBuffer);
Steve Block3856b092011-10-20 11:56:00 +01003904 ALOGV("OutputTrack::write() %p thread %p adding overflow buffer %d", this, mThread.unsafe_get(), mBufferQueue.size());
Mathias Agopian65ab4712010-07-14 17:59:35 -07003905 } else {
Steve Block5ff1dd52012-01-05 23:22:43 +00003906 ALOGW("OutputTrack::write() %p thread %p no more overflow buffers", mThread.unsafe_get(), this);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003907 }
3908 }
3909 }
3910
3911 // Calling write() with a 0 length buffer, means that no more data will be written:
3912 // If no more buffers are pending, fill output track buffer to make sure it is started
3913 // by output mixer.
3914 if (frames == 0 && mBufferQueue.size() == 0) {
3915 if (mCblk->user < mCblk->frameCount) {
3916 frames = mCblk->frameCount - mCblk->user;
3917 pInBuffer = new Buffer;
3918 pInBuffer->mBuffer = new int16_t[frames * channelCount];
3919 pInBuffer->frameCount = frames;
3920 pInBuffer->i16 = pInBuffer->mBuffer;
3921 memset(pInBuffer->raw, 0, frames * channelCount * sizeof(int16_t));
3922 mBufferQueue.add(pInBuffer);
3923 } else if (mActive) {
3924 stop();
3925 }
3926 }
3927
3928 return outputBufferFull;
3929}
3930
3931status_t AudioFlinger::PlaybackThread::OutputTrack::obtainBuffer(AudioBufferProvider::Buffer* buffer, uint32_t waitTimeMs)
3932{
3933 int active;
3934 status_t result;
3935 audio_track_cblk_t* cblk = mCblk;
3936 uint32_t framesReq = buffer->frameCount;
3937
Steve Block3856b092011-10-20 11:56:00 +01003938// ALOGV("OutputTrack::obtainBuffer user %d, server %d", cblk->user, cblk->server);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003939 buffer->frameCount = 0;
3940
3941 uint32_t framesAvail = cblk->framesAvailable();
3942
3943
3944 if (framesAvail == 0) {
3945 Mutex::Autolock _l(cblk->lock);
3946 goto start_loop_here;
3947 while (framesAvail == 0) {
3948 active = mActive;
Glenn Kastenf6b16782011-12-15 09:51:17 -08003949 if (CC_UNLIKELY(!active)) {
Steve Block3856b092011-10-20 11:56:00 +01003950 ALOGV("Not active and NO_MORE_BUFFERS");
Glenn Kasten335787f2012-01-20 17:00:00 -08003951 return NO_MORE_BUFFERS;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003952 }
3953 result = cblk->cv.waitRelative(cblk->lock, milliseconds(waitTimeMs));
3954 if (result != NO_ERROR) {
Glenn Kasten335787f2012-01-20 17:00:00 -08003955 return NO_MORE_BUFFERS;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003956 }
3957 // read the server count again
3958 start_loop_here:
3959 framesAvail = cblk->framesAvailable_l();
3960 }
3961 }
3962
3963// if (framesAvail < framesReq) {
Glenn Kasten335787f2012-01-20 17:00:00 -08003964// return NO_MORE_BUFFERS;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003965// }
3966
3967 if (framesReq > framesAvail) {
3968 framesReq = framesAvail;
3969 }
3970
3971 uint32_t u = cblk->user;
3972 uint32_t bufferEnd = cblk->userBase + cblk->frameCount;
3973
3974 if (u + framesReq > bufferEnd) {
3975 framesReq = bufferEnd - u;
3976 }
3977
3978 buffer->frameCount = framesReq;
3979 buffer->raw = (void *)cblk->buffer(u);
3980 return NO_ERROR;
3981}
3982
3983
3984void AudioFlinger::PlaybackThread::OutputTrack::clearBufferQueue()
3985{
3986 size_t size = mBufferQueue.size();
3987 Buffer *pBuffer;
3988
3989 for (size_t i = 0; i < size; i++) {
3990 pBuffer = mBufferQueue.itemAt(i);
3991 delete [] pBuffer->mBuffer;
3992 delete pBuffer;
3993 }
3994 mBufferQueue.clear();
3995}
3996
3997// ----------------------------------------------------------------------------
3998
3999AudioFlinger::Client::Client(const sp<AudioFlinger>& audioFlinger, pid_t pid)
4000 : RefBase(),
4001 mAudioFlinger(audioFlinger),
4002 mMemoryDealer(new MemoryDealer(1024*1024, "AudioFlinger::Client")),
4003 mPid(pid)
4004{
4005 // 1 MB of address space is good for 32 tracks, 8 buffers each, 4 KB/buffer
4006}
4007
4008// Client destructor must be called with AudioFlinger::mLock held
4009AudioFlinger::Client::~Client()
4010{
4011 mAudioFlinger->removeClient_l(mPid);
4012}
4013
Glenn Kasten435dbe62012-01-30 10:15:48 -08004014sp<MemoryDealer> AudioFlinger::Client::heap() const
Mathias Agopian65ab4712010-07-14 17:59:35 -07004015{
4016 return mMemoryDealer;
4017}
4018
4019// ----------------------------------------------------------------------------
4020
4021AudioFlinger::NotificationClient::NotificationClient(const sp<AudioFlinger>& audioFlinger,
4022 const sp<IAudioFlingerClient>& client,
4023 pid_t pid)
Glenn Kasten84afa3b2012-01-25 15:28:08 -08004024 : mAudioFlinger(audioFlinger), mPid(pid), mAudioFlingerClient(client)
Mathias Agopian65ab4712010-07-14 17:59:35 -07004025{
4026}
4027
4028AudioFlinger::NotificationClient::~NotificationClient()
4029{
Mathias Agopian65ab4712010-07-14 17:59:35 -07004030}
4031
4032void AudioFlinger::NotificationClient::binderDied(const wp<IBinder>& who)
4033{
4034 sp<NotificationClient> keep(this);
4035 {
4036 mAudioFlinger->removeNotificationClient(mPid);
4037 }
4038}
4039
4040// ----------------------------------------------------------------------------
4041
4042AudioFlinger::TrackHandle::TrackHandle(const sp<AudioFlinger::PlaybackThread::Track>& track)
4043 : BnAudioTrack(),
4044 mTrack(track)
4045{
4046}
4047
4048AudioFlinger::TrackHandle::~TrackHandle() {
4049 // just stop the track on deletion, associated resources
4050 // will be freed from the main thread once all pending buffers have
4051 // been played. Unless it's not in the active track list, in which
4052 // case we free everything now...
4053 mTrack->destroy();
4054}
4055
Glenn Kasten90716c52012-01-26 13:40:12 -08004056sp<IMemory> AudioFlinger::TrackHandle::getCblk() const {
4057 return mTrack->getCblk();
4058}
4059
Glenn Kasten6dbc1352012-02-02 10:56:47 -08004060status_t AudioFlinger::TrackHandle::start(pid_t tid) {
4061 return mTrack->start(tid);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004062}
4063
4064void AudioFlinger::TrackHandle::stop() {
4065 mTrack->stop();
4066}
4067
4068void AudioFlinger::TrackHandle::flush() {
4069 mTrack->flush();
4070}
4071
4072void AudioFlinger::TrackHandle::mute(bool e) {
4073 mTrack->mute(e);
4074}
4075
4076void AudioFlinger::TrackHandle::pause() {
4077 mTrack->pause();
4078}
4079
Mathias Agopian65ab4712010-07-14 17:59:35 -07004080status_t AudioFlinger::TrackHandle::attachAuxEffect(int EffectId)
4081{
4082 return mTrack->attachAuxEffect(EffectId);
4083}
4084
4085status_t AudioFlinger::TrackHandle::onTransact(
4086 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
4087{
4088 return BnAudioTrack::onTransact(code, data, reply, flags);
4089}
4090
4091// ----------------------------------------------------------------------------
4092
4093sp<IAudioRecord> AudioFlinger::openRecord(
4094 pid_t pid,
Glenn Kasten72ef00d2012-01-17 11:09:42 -08004095 audio_io_handle_t input,
Mathias Agopian65ab4712010-07-14 17:59:35 -07004096 uint32_t sampleRate,
Glenn Kasten58f30212012-01-12 12:27:51 -08004097 audio_format_t format,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07004098 uint32_t channelMask,
Mathias Agopian65ab4712010-07-14 17:59:35 -07004099 int frameCount,
4100 uint32_t flags,
4101 int *sessionId,
4102 status_t *status)
4103{
4104 sp<RecordThread::RecordTrack> recordTrack;
4105 sp<RecordHandle> recordHandle;
4106 sp<Client> client;
Mathias Agopian65ab4712010-07-14 17:59:35 -07004107 status_t lStatus;
4108 RecordThread *thread;
4109 size_t inFrameCount;
4110 int lSessionId;
4111
4112 // check calling permissions
4113 if (!recordingAllowed()) {
4114 lStatus = PERMISSION_DENIED;
4115 goto Exit;
4116 }
4117
4118 // add client to list
4119 { // scope for mLock
4120 Mutex::Autolock _l(mLock);
4121 thread = checkRecordThread_l(input);
4122 if (thread == NULL) {
4123 lStatus = BAD_VALUE;
4124 goto Exit;
4125 }
4126
Glenn Kasten98ec94c2012-01-25 14:28:29 -08004127 client = registerPid_l(pid);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004128
4129 // If no audio session id is provided, create one here
Dima Zavinfce7a472011-04-19 22:30:36 -07004130 if (sessionId != NULL && *sessionId != AUDIO_SESSION_OUTPUT_MIX) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07004131 lSessionId = *sessionId;
4132 } else {
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004133 lSessionId = nextUniqueId();
Mathias Agopian65ab4712010-07-14 17:59:35 -07004134 if (sessionId != NULL) {
4135 *sessionId = lSessionId;
4136 }
4137 }
4138 // create new record track. The record track uses one track in mHardwareMixerThread by convention.
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004139 recordTrack = thread->createRecordTrack_l(client,
4140 sampleRate,
4141 format,
4142 channelMask,
4143 frameCount,
4144 flags,
4145 lSessionId,
4146 &lStatus);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004147 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004148 if (lStatus != NO_ERROR) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07004149 // remove local strong reference to Client before deleting the RecordTrack so that the Client
4150 // destructor is called by the TrackBase destructor with mLock held
4151 client.clear();
4152 recordTrack.clear();
Mathias Agopian65ab4712010-07-14 17:59:35 -07004153 goto Exit;
4154 }
4155
4156 // return to handle to client
4157 recordHandle = new RecordHandle(recordTrack);
4158 lStatus = NO_ERROR;
4159
4160Exit:
4161 if (status) {
4162 *status = lStatus;
4163 }
4164 return recordHandle;
4165}
4166
4167// ----------------------------------------------------------------------------
4168
4169AudioFlinger::RecordHandle::RecordHandle(const sp<AudioFlinger::RecordThread::RecordTrack>& recordTrack)
4170 : BnAudioRecord(),
4171 mRecordTrack(recordTrack)
4172{
4173}
4174
4175AudioFlinger::RecordHandle::~RecordHandle() {
4176 stop();
4177}
4178
Glenn Kasten90716c52012-01-26 13:40:12 -08004179sp<IMemory> AudioFlinger::RecordHandle::getCblk() const {
4180 return mRecordTrack->getCblk();
4181}
4182
Glenn Kasten6dbc1352012-02-02 10:56:47 -08004183status_t AudioFlinger::RecordHandle::start(pid_t tid) {
Steve Block3856b092011-10-20 11:56:00 +01004184 ALOGV("RecordHandle::start()");
Glenn Kasten6dbc1352012-02-02 10:56:47 -08004185 return mRecordTrack->start(tid);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004186}
4187
4188void AudioFlinger::RecordHandle::stop() {
Steve Block3856b092011-10-20 11:56:00 +01004189 ALOGV("RecordHandle::stop()");
Mathias Agopian65ab4712010-07-14 17:59:35 -07004190 mRecordTrack->stop();
4191}
4192
Mathias Agopian65ab4712010-07-14 17:59:35 -07004193status_t AudioFlinger::RecordHandle::onTransact(
4194 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
4195{
4196 return BnAudioRecord::onTransact(code, data, reply, flags);
4197}
4198
4199// ----------------------------------------------------------------------------
4200
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004201AudioFlinger::RecordThread::RecordThread(const sp<AudioFlinger>& audioFlinger,
4202 AudioStreamIn *input,
4203 uint32_t sampleRate,
4204 uint32_t channels,
Glenn Kasten72ef00d2012-01-17 11:09:42 -08004205 audio_io_handle_t id,
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004206 uint32_t device) :
Glenn Kasten23bb8be2012-01-26 10:38:26 -08004207 ThreadBase(audioFlinger, id, device, RECORD),
Glenn Kasten84afa3b2012-01-25 15:28:08 -08004208 mInput(input), mTrack(NULL), mResampler(NULL), mRsmpOutBuffer(NULL), mRsmpInBuffer(NULL),
4209 // mRsmpInIndex and mInputBytes set by readInputParameters()
4210 mReqChannelCount(popcount(channels)),
4211 mReqSampleRate(sampleRate)
4212 // mBytesRead is only meaningful while active, and so is cleared in start()
4213 // (but might be better to also clear here for dump?)
Mathias Agopian65ab4712010-07-14 17:59:35 -07004214{
Eric Laurentfeb0db62011-07-22 09:04:31 -07004215 snprintf(mName, kNameLength, "AudioIn_%d", id);
4216
Mathias Agopian65ab4712010-07-14 17:59:35 -07004217 readInputParameters();
4218}
4219
4220
4221AudioFlinger::RecordThread::~RecordThread()
4222{
4223 delete[] mRsmpInBuffer;
Glenn Kastene9dd0172012-01-27 18:08:45 -08004224 delete mResampler;
4225 delete[] mRsmpOutBuffer;
Mathias Agopian65ab4712010-07-14 17:59:35 -07004226}
4227
4228void AudioFlinger::RecordThread::onFirstRef()
4229{
Eric Laurentfeb0db62011-07-22 09:04:31 -07004230 run(mName, PRIORITY_URGENT_AUDIO);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004231}
4232
Eric Laurentb8ba0a92011-08-07 16:32:26 -07004233status_t AudioFlinger::RecordThread::readyToRun()
4234{
4235 status_t status = initCheck();
Steve Block5ff1dd52012-01-05 23:22:43 +00004236 ALOGW_IF(status != NO_ERROR,"RecordThread %p could not initialize", this);
Eric Laurentb8ba0a92011-08-07 16:32:26 -07004237 return status;
4238}
4239
Mathias Agopian65ab4712010-07-14 17:59:35 -07004240bool AudioFlinger::RecordThread::threadLoop()
4241{
4242 AudioBufferProvider::Buffer buffer;
4243 sp<RecordTrack> activeTrack;
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004244 Vector< sp<EffectChain> > effectChains;
Mathias Agopian65ab4712010-07-14 17:59:35 -07004245
Eric Laurent44d98482010-09-30 16:12:31 -07004246 nsecs_t lastWarning = 0;
4247
Eric Laurentfeb0db62011-07-22 09:04:31 -07004248 acquireWakeLock();
4249
Mathias Agopian65ab4712010-07-14 17:59:35 -07004250 // start recording
4251 while (!exitPending()) {
4252
4253 processConfigEvents();
4254
4255 { // scope for mLock
4256 Mutex::Autolock _l(mLock);
4257 checkForNewParameters_l();
4258 if (mActiveTrack == 0 && mConfigEvents.isEmpty()) {
4259 if (!mStandby) {
Dima Zavin799a70e2011-04-18 16:57:27 -07004260 mInput->stream->common.standby(&mInput->stream->common);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004261 mStandby = true;
4262 }
4263
4264 if (exitPending()) break;
4265
Eric Laurentfeb0db62011-07-22 09:04:31 -07004266 releaseWakeLock_l();
Steve Block3856b092011-10-20 11:56:00 +01004267 ALOGV("RecordThread: loop stopping");
Mathias Agopian65ab4712010-07-14 17:59:35 -07004268 // go to sleep
4269 mWaitWorkCV.wait(mLock);
Steve Block3856b092011-10-20 11:56:00 +01004270 ALOGV("RecordThread: loop starting");
Eric Laurentfeb0db62011-07-22 09:04:31 -07004271 acquireWakeLock_l();
Mathias Agopian65ab4712010-07-14 17:59:35 -07004272 continue;
4273 }
4274 if (mActiveTrack != 0) {
4275 if (mActiveTrack->mState == TrackBase::PAUSING) {
4276 if (!mStandby) {
Dima Zavin799a70e2011-04-18 16:57:27 -07004277 mInput->stream->common.standby(&mInput->stream->common);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004278 mStandby = true;
4279 }
4280 mActiveTrack.clear();
4281 mStartStopCond.broadcast();
4282 } else if (mActiveTrack->mState == TrackBase::RESUMING) {
4283 if (mReqChannelCount != mActiveTrack->channelCount()) {
4284 mActiveTrack.clear();
4285 mStartStopCond.broadcast();
4286 } else if (mBytesRead != 0) {
4287 // record start succeeds only if first read from audio input
4288 // succeeds
4289 if (mBytesRead > 0) {
4290 mActiveTrack->mState = TrackBase::ACTIVE;
4291 } else {
4292 mActiveTrack.clear();
4293 }
4294 mStartStopCond.broadcast();
4295 }
4296 mStandby = false;
4297 }
4298 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004299 lockEffectChains_l(effectChains);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004300 }
4301
4302 if (mActiveTrack != 0) {
4303 if (mActiveTrack->mState != TrackBase::ACTIVE &&
4304 mActiveTrack->mState != TrackBase::RESUMING) {
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004305 unlockEffectChains(effectChains);
4306 usleep(kRecordThreadSleepUs);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004307 continue;
4308 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004309 for (size_t i = 0; i < effectChains.size(); i ++) {
4310 effectChains[i]->process_l();
4311 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004312
Mathias Agopian65ab4712010-07-14 17:59:35 -07004313 buffer.frameCount = mFrameCount;
Glenn Kastenf6b16782011-12-15 09:51:17 -08004314 if (CC_LIKELY(mActiveTrack->getNextBuffer(&buffer) == NO_ERROR)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07004315 size_t framesOut = buffer.frameCount;
Glenn Kastene0feee32011-12-13 11:53:26 -08004316 if (mResampler == NULL) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07004317 // no resampling
4318 while (framesOut) {
4319 size_t framesIn = mFrameCount - mRsmpInIndex;
4320 if (framesIn) {
4321 int8_t *src = (int8_t *)mRsmpInBuffer + mRsmpInIndex * mFrameSize;
4322 int8_t *dst = buffer.i8 + (buffer.frameCount - framesOut) * mActiveTrack->mCblk->frameSize;
4323 if (framesIn > framesOut)
4324 framesIn = framesOut;
4325 mRsmpInIndex += framesIn;
4326 framesOut -= framesIn;
4327 if ((int)mChannelCount == mReqChannelCount ||
Dima Zavinfce7a472011-04-19 22:30:36 -07004328 mFormat != AUDIO_FORMAT_PCM_16_BIT) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07004329 memcpy(dst, src, framesIn * mFrameSize);
4330 } else {
4331 int16_t *src16 = (int16_t *)src;
4332 int16_t *dst16 = (int16_t *)dst;
4333 if (mChannelCount == 1) {
4334 while (framesIn--) {
4335 *dst16++ = *src16;
4336 *dst16++ = *src16++;
4337 }
4338 } else {
4339 while (framesIn--) {
4340 *dst16++ = (int16_t)(((int32_t)*src16 + (int32_t)*(src16 + 1)) >> 1);
4341 src16 += 2;
4342 }
4343 }
4344 }
4345 }
4346 if (framesOut && mFrameCount == mRsmpInIndex) {
4347 if (framesOut == mFrameCount &&
Dima Zavinfce7a472011-04-19 22:30:36 -07004348 ((int)mChannelCount == mReqChannelCount || mFormat != AUDIO_FORMAT_PCM_16_BIT)) {
Dima Zavin799a70e2011-04-18 16:57:27 -07004349 mBytesRead = mInput->stream->read(mInput->stream, buffer.raw, mInputBytes);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004350 framesOut = 0;
4351 } else {
Dima Zavin799a70e2011-04-18 16:57:27 -07004352 mBytesRead = mInput->stream->read(mInput->stream, mRsmpInBuffer, mInputBytes);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004353 mRsmpInIndex = 0;
4354 }
4355 if (mBytesRead < 0) {
Steve Block29357bc2012-01-06 19:20:56 +00004356 ALOGE("Error reading audio input");
Mathias Agopian65ab4712010-07-14 17:59:35 -07004357 if (mActiveTrack->mState == TrackBase::ACTIVE) {
4358 // Force input into standby so that it tries to
4359 // recover at next read attempt
Dima Zavin799a70e2011-04-18 16:57:27 -07004360 mInput->stream->common.standby(&mInput->stream->common);
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004361 usleep(kRecordThreadSleepUs);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004362 }
4363 mRsmpInIndex = mFrameCount;
4364 framesOut = 0;
4365 buffer.frameCount = 0;
4366 }
4367 }
4368 }
4369 } else {
4370 // resampling
4371
4372 memset(mRsmpOutBuffer, 0, framesOut * 2 * sizeof(int32_t));
4373 // alter output frame count as if we were expecting stereo samples
4374 if (mChannelCount == 1 && mReqChannelCount == 1) {
4375 framesOut >>= 1;
4376 }
4377 mResampler->resample(mRsmpOutBuffer, framesOut, this);
4378 // ditherAndClamp() works as long as all buffers returned by mActiveTrack->getNextBuffer()
4379 // are 32 bit aligned which should be always true.
4380 if (mChannelCount == 2 && mReqChannelCount == 1) {
Glenn Kasten3b21c502011-12-15 09:52:39 -08004381 ditherAndClamp(mRsmpOutBuffer, mRsmpOutBuffer, framesOut);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004382 // the resampler always outputs stereo samples: do post stereo to mono conversion
4383 int16_t *src = (int16_t *)mRsmpOutBuffer;
4384 int16_t *dst = buffer.i16;
4385 while (framesOut--) {
4386 *dst++ = (int16_t)(((int32_t)*src + (int32_t)*(src + 1)) >> 1);
4387 src += 2;
4388 }
4389 } else {
Glenn Kasten3b21c502011-12-15 09:52:39 -08004390 ditherAndClamp((int32_t *)buffer.raw, mRsmpOutBuffer, framesOut);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004391 }
4392
4393 }
4394 mActiveTrack->releaseBuffer(&buffer);
4395 mActiveTrack->overflow();
4396 }
4397 // client isn't retrieving buffers fast enough
4398 else {
Eric Laurent44d98482010-09-30 16:12:31 -07004399 if (!mActiveTrack->setOverflow()) {
4400 nsecs_t now = systemTime();
Glenn Kasten7dede872011-12-13 11:04:14 -08004401 if ((now - lastWarning) > kWarningThrottleNs) {
Steve Block5ff1dd52012-01-05 23:22:43 +00004402 ALOGW("RecordThread: buffer overflow");
Eric Laurent44d98482010-09-30 16:12:31 -07004403 lastWarning = now;
4404 }
4405 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07004406 // Release the processor for a while before asking for a new buffer.
4407 // This will give the application more chance to read from the buffer and
4408 // clear the overflow.
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004409 usleep(kRecordThreadSleepUs);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004410 }
4411 }
Eric Laurentec437d82011-07-26 20:54:46 -07004412 // enable changes in effect chain
4413 unlockEffectChains(effectChains);
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004414 effectChains.clear();
Mathias Agopian65ab4712010-07-14 17:59:35 -07004415 }
4416
4417 if (!mStandby) {
Dima Zavin799a70e2011-04-18 16:57:27 -07004418 mInput->stream->common.standby(&mInput->stream->common);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004419 }
4420 mActiveTrack.clear();
4421
4422 mStartStopCond.broadcast();
4423
Eric Laurentfeb0db62011-07-22 09:04:31 -07004424 releaseWakeLock();
4425
Steve Block3856b092011-10-20 11:56:00 +01004426 ALOGV("RecordThread %p exiting", this);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004427 return false;
4428}
4429
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004430
4431sp<AudioFlinger::RecordThread::RecordTrack> AudioFlinger::RecordThread::createRecordTrack_l(
4432 const sp<AudioFlinger::Client>& client,
4433 uint32_t sampleRate,
Glenn Kasten58f30212012-01-12 12:27:51 -08004434 audio_format_t format,
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004435 int channelMask,
4436 int frameCount,
4437 uint32_t flags,
4438 int sessionId,
4439 status_t *status)
4440{
4441 sp<RecordTrack> track;
4442 status_t lStatus;
4443
4444 lStatus = initCheck();
4445 if (lStatus != NO_ERROR) {
Steve Block29357bc2012-01-06 19:20:56 +00004446 ALOGE("Audio driver not initialized.");
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004447 goto Exit;
4448 }
4449
4450 { // scope for mLock
4451 Mutex::Autolock _l(mLock);
4452
4453 track = new RecordTrack(this, client, sampleRate,
4454 format, channelMask, frameCount, flags, sessionId);
4455
Glenn Kasten7378ca52012-01-20 13:44:40 -08004456 if (track->getCblk() == 0) {
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004457 lStatus = NO_MEMORY;
4458 goto Exit;
4459 }
4460
4461 mTrack = track.get();
Eric Laurent59bd0da2011-08-01 09:52:20 -07004462 // disable AEC and NS if the device is a BT SCO headset supporting those pre processings
4463 bool suspend = audio_is_bluetooth_sco_device(
Eric Laurentbee53372011-08-29 12:42:48 -07004464 (audio_devices_t)(mDevice & AUDIO_DEVICE_IN_ALL)) && mAudioFlinger->btNrecIsOff();
Eric Laurent59bd0da2011-08-01 09:52:20 -07004465 setEffectSuspended_l(FX_IID_AEC, suspend, sessionId);
4466 setEffectSuspended_l(FX_IID_NS, suspend, sessionId);
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004467 }
4468 lStatus = NO_ERROR;
4469
4470Exit:
4471 if (status) {
4472 *status = lStatus;
4473 }
4474 return track;
4475}
4476
Glenn Kasten6dbc1352012-02-02 10:56:47 -08004477status_t AudioFlinger::RecordThread::start(RecordThread::RecordTrack* recordTrack, pid_t tid)
Mathias Agopian65ab4712010-07-14 17:59:35 -07004478{
Glenn Kasten6dbc1352012-02-02 10:56:47 -08004479 ALOGV("RecordThread::start tid=%d", tid);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004480 sp <ThreadBase> strongMe = this;
4481 status_t status = NO_ERROR;
4482 {
Glenn Kastena7d8d6f2012-01-05 15:41:56 -08004483 AutoMutex lock(mLock);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004484 if (mActiveTrack != 0) {
4485 if (recordTrack != mActiveTrack.get()) {
4486 status = -EBUSY;
4487 } else if (mActiveTrack->mState == TrackBase::PAUSING) {
4488 mActiveTrack->mState = TrackBase::ACTIVE;
4489 }
4490 return status;
4491 }
4492
4493 recordTrack->mState = TrackBase::IDLE;
4494 mActiveTrack = recordTrack;
4495 mLock.unlock();
4496 status_t status = AudioSystem::startInput(mId);
4497 mLock.lock();
4498 if (status != NO_ERROR) {
4499 mActiveTrack.clear();
4500 return status;
4501 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07004502 mRsmpInIndex = mFrameCount;
4503 mBytesRead = 0;
Eric Laurent243f5f92011-02-28 16:52:51 -08004504 if (mResampler != NULL) {
4505 mResampler->reset();
4506 }
4507 mActiveTrack->mState = TrackBase::RESUMING;
Mathias Agopian65ab4712010-07-14 17:59:35 -07004508 // signal thread to start
Steve Block3856b092011-10-20 11:56:00 +01004509 ALOGV("Signal record thread");
Mathias Agopian65ab4712010-07-14 17:59:35 -07004510 mWaitWorkCV.signal();
4511 // do not wait for mStartStopCond if exiting
Glenn Kastenb28686f2012-01-06 08:39:38 -08004512 if (exitPending()) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07004513 mActiveTrack.clear();
4514 status = INVALID_OPERATION;
4515 goto startError;
4516 }
4517 mStartStopCond.wait(mLock);
4518 if (mActiveTrack == 0) {
Steve Block3856b092011-10-20 11:56:00 +01004519 ALOGV("Record failed to start");
Mathias Agopian65ab4712010-07-14 17:59:35 -07004520 status = BAD_VALUE;
4521 goto startError;
4522 }
Steve Block3856b092011-10-20 11:56:00 +01004523 ALOGV("Record started OK");
Mathias Agopian65ab4712010-07-14 17:59:35 -07004524 return status;
4525 }
4526startError:
4527 AudioSystem::stopInput(mId);
4528 return status;
4529}
4530
4531void AudioFlinger::RecordThread::stop(RecordThread::RecordTrack* recordTrack) {
Steve Block3856b092011-10-20 11:56:00 +01004532 ALOGV("RecordThread::stop");
Mathias Agopian65ab4712010-07-14 17:59:35 -07004533 sp <ThreadBase> strongMe = this;
4534 {
Glenn Kastena7d8d6f2012-01-05 15:41:56 -08004535 AutoMutex lock(mLock);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004536 if (mActiveTrack != 0 && recordTrack == mActiveTrack.get()) {
4537 mActiveTrack->mState = TrackBase::PAUSING;
4538 // do not wait for mStartStopCond if exiting
Glenn Kastenb28686f2012-01-06 08:39:38 -08004539 if (exitPending()) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07004540 return;
4541 }
4542 mStartStopCond.wait(mLock);
4543 // if we have been restarted, recordTrack == mActiveTrack.get() here
4544 if (mActiveTrack == 0 || recordTrack != mActiveTrack.get()) {
4545 mLock.unlock();
4546 AudioSystem::stopInput(mId);
4547 mLock.lock();
Steve Block3856b092011-10-20 11:56:00 +01004548 ALOGV("Record stopped OK");
Mathias Agopian65ab4712010-07-14 17:59:35 -07004549 }
4550 }
4551 }
4552}
4553
4554status_t AudioFlinger::RecordThread::dump(int fd, const Vector<String16>& args)
4555{
4556 const size_t SIZE = 256;
4557 char buffer[SIZE];
4558 String8 result;
Mathias Agopian65ab4712010-07-14 17:59:35 -07004559
4560 snprintf(buffer, SIZE, "\nInput thread %p internals\n", this);
4561 result.append(buffer);
4562
4563 if (mActiveTrack != 0) {
4564 result.append("Active Track:\n");
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07004565 result.append(" Clien Fmt Chn mask Session Buf S SRate Serv User\n");
Mathias Agopian65ab4712010-07-14 17:59:35 -07004566 mActiveTrack->dump(buffer, SIZE);
4567 result.append(buffer);
4568
4569 snprintf(buffer, SIZE, "In index: %d\n", mRsmpInIndex);
4570 result.append(buffer);
4571 snprintf(buffer, SIZE, "In size: %d\n", mInputBytes);
4572 result.append(buffer);
Glenn Kastene0feee32011-12-13 11:53:26 -08004573 snprintf(buffer, SIZE, "Resampling: %d\n", (mResampler != NULL));
Mathias Agopian65ab4712010-07-14 17:59:35 -07004574 result.append(buffer);
4575 snprintf(buffer, SIZE, "Out channel count: %d\n", mReqChannelCount);
4576 result.append(buffer);
4577 snprintf(buffer, SIZE, "Out sample rate: %d\n", mReqSampleRate);
4578 result.append(buffer);
4579
4580
4581 } else {
4582 result.append("No record client\n");
4583 }
4584 write(fd, result.string(), result.size());
4585
4586 dumpBase(fd, args);
Eric Laurent1d2bff02011-07-24 17:49:51 -07004587 dumpEffectChains(fd, args);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004588
4589 return NO_ERROR;
4590}
4591
4592status_t AudioFlinger::RecordThread::getNextBuffer(AudioBufferProvider::Buffer* buffer)
4593{
4594 size_t framesReq = buffer->frameCount;
4595 size_t framesReady = mFrameCount - mRsmpInIndex;
4596 int channelCount;
4597
4598 if (framesReady == 0) {
Dima Zavin799a70e2011-04-18 16:57:27 -07004599 mBytesRead = mInput->stream->read(mInput->stream, mRsmpInBuffer, mInputBytes);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004600 if (mBytesRead < 0) {
Steve Block29357bc2012-01-06 19:20:56 +00004601 ALOGE("RecordThread::getNextBuffer() Error reading audio input");
Mathias Agopian65ab4712010-07-14 17:59:35 -07004602 if (mActiveTrack->mState == TrackBase::ACTIVE) {
4603 // Force input into standby so that it tries to
4604 // recover at next read attempt
Dima Zavin799a70e2011-04-18 16:57:27 -07004605 mInput->stream->common.standby(&mInput->stream->common);
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004606 usleep(kRecordThreadSleepUs);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004607 }
Glenn Kastene0feee32011-12-13 11:53:26 -08004608 buffer->raw = NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -07004609 buffer->frameCount = 0;
4610 return NOT_ENOUGH_DATA;
4611 }
4612 mRsmpInIndex = 0;
4613 framesReady = mFrameCount;
4614 }
4615
4616 if (framesReq > framesReady) {
4617 framesReq = framesReady;
4618 }
4619
4620 if (mChannelCount == 1 && mReqChannelCount == 2) {
4621 channelCount = 1;
4622 } else {
4623 channelCount = 2;
4624 }
4625 buffer->raw = mRsmpInBuffer + mRsmpInIndex * channelCount;
4626 buffer->frameCount = framesReq;
4627 return NO_ERROR;
4628}
4629
4630void AudioFlinger::RecordThread::releaseBuffer(AudioBufferProvider::Buffer* buffer)
4631{
4632 mRsmpInIndex += buffer->frameCount;
4633 buffer->frameCount = 0;
4634}
4635
4636bool AudioFlinger::RecordThread::checkForNewParameters_l()
4637{
4638 bool reconfig = false;
4639
4640 while (!mNewParameters.isEmpty()) {
4641 status_t status = NO_ERROR;
4642 String8 keyValuePair = mNewParameters[0];
4643 AudioParameter param = AudioParameter(keyValuePair);
4644 int value;
Glenn Kasten58f30212012-01-12 12:27:51 -08004645 audio_format_t reqFormat = mFormat;
Mathias Agopian65ab4712010-07-14 17:59:35 -07004646 int reqSamplingRate = mReqSampleRate;
4647 int reqChannelCount = mReqChannelCount;
4648
4649 if (param.getInt(String8(AudioParameter::keySamplingRate), value) == NO_ERROR) {
4650 reqSamplingRate = value;
4651 reconfig = true;
4652 }
4653 if (param.getInt(String8(AudioParameter::keyFormat), value) == NO_ERROR) {
Glenn Kasten58f30212012-01-12 12:27:51 -08004654 reqFormat = (audio_format_t) value;
Mathias Agopian65ab4712010-07-14 17:59:35 -07004655 reconfig = true;
4656 }
4657 if (param.getInt(String8(AudioParameter::keyChannels), value) == NO_ERROR) {
Dima Zavinfce7a472011-04-19 22:30:36 -07004658 reqChannelCount = popcount(value);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004659 reconfig = true;
4660 }
4661 if (param.getInt(String8(AudioParameter::keyFrameCount), value) == NO_ERROR) {
4662 // do not accept frame count changes if tracks are open as the track buffer
4663 // size depends on frame count and correct behavior would not be garantied
4664 // if frame count is changed after track creation
4665 if (mActiveTrack != 0) {
4666 status = INVALID_OPERATION;
4667 } else {
4668 reconfig = true;
4669 }
4670 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004671 if (param.getInt(String8(AudioParameter::keyRouting), value) == NO_ERROR) {
4672 // forward device change to effects that have requested to be
4673 // aware of attached audio device.
4674 for (size_t i = 0; i < mEffectChains.size(); i++) {
4675 mEffectChains[i]->setDevice_l(value);
4676 }
4677 // store input device and output device but do not forward output device to audio HAL.
4678 // Note that status is ignored by the caller for output device
4679 // (see AudioFlinger::setParameters()
4680 if (value & AUDIO_DEVICE_OUT_ALL) {
4681 mDevice &= (uint32_t)~(value & AUDIO_DEVICE_OUT_ALL);
4682 status = BAD_VALUE;
4683 } else {
4684 mDevice &= (uint32_t)~(value & AUDIO_DEVICE_IN_ALL);
Eric Laurent59bd0da2011-08-01 09:52:20 -07004685 // disable AEC and NS if the device is a BT SCO headset supporting those pre processings
4686 if (mTrack != NULL) {
4687 bool suspend = audio_is_bluetooth_sco_device(
Eric Laurentbee53372011-08-29 12:42:48 -07004688 (audio_devices_t)value) && mAudioFlinger->btNrecIsOff();
Eric Laurent59bd0da2011-08-01 09:52:20 -07004689 setEffectSuspended_l(FX_IID_AEC, suspend, mTrack->sessionId());
4690 setEffectSuspended_l(FX_IID_NS, suspend, mTrack->sessionId());
4691 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004692 }
4693 mDevice |= (uint32_t)value;
4694 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07004695 if (status == NO_ERROR) {
Dima Zavin799a70e2011-04-18 16:57:27 -07004696 status = mInput->stream->common.set_parameters(&mInput->stream->common, keyValuePair.string());
Mathias Agopian65ab4712010-07-14 17:59:35 -07004697 if (status == INVALID_OPERATION) {
Dima Zavin799a70e2011-04-18 16:57:27 -07004698 mInput->stream->common.standby(&mInput->stream->common);
4699 status = mInput->stream->common.set_parameters(&mInput->stream->common, keyValuePair.string());
Mathias Agopian65ab4712010-07-14 17:59:35 -07004700 }
4701 if (reconfig) {
4702 if (status == BAD_VALUE &&
Dima Zavin799a70e2011-04-18 16:57:27 -07004703 reqFormat == mInput->stream->common.get_format(&mInput->stream->common) &&
Dima Zavinfce7a472011-04-19 22:30:36 -07004704 reqFormat == AUDIO_FORMAT_PCM_16_BIT &&
Dima Zavin799a70e2011-04-18 16:57:27 -07004705 ((int)mInput->stream->common.get_sample_rate(&mInput->stream->common) <= (2 * reqSamplingRate)) &&
4706 (popcount(mInput->stream->common.get_channels(&mInput->stream->common)) < 3) &&
Dima Zavinfce7a472011-04-19 22:30:36 -07004707 (reqChannelCount < 3)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07004708 status = NO_ERROR;
4709 }
4710 if (status == NO_ERROR) {
4711 readInputParameters();
4712 sendConfigEvent_l(AudioSystem::INPUT_CONFIG_CHANGED);
4713 }
4714 }
4715 }
4716
4717 mNewParameters.removeAt(0);
4718
4719 mParamStatus = status;
4720 mParamCond.signal();
Eric Laurent60cd0a02011-09-13 11:40:21 -07004721 // wait for condition with time out in case the thread calling ThreadBase::setParameters()
4722 // already timed out waiting for the status and will never signal the condition.
Glenn Kasten7dede872011-12-13 11:04:14 -08004723 mWaitWorkCV.waitRelative(mLock, kSetParametersTimeoutNs);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004724 }
4725 return reconfig;
4726}
4727
4728String8 AudioFlinger::RecordThread::getParameters(const String8& keys)
4729{
Dima Zavinfce7a472011-04-19 22:30:36 -07004730 char *s;
Eric Laurentb8ba0a92011-08-07 16:32:26 -07004731 String8 out_s8 = String8();
4732
4733 Mutex::Autolock _l(mLock);
4734 if (initCheck() != NO_ERROR) {
4735 return out_s8;
4736 }
Dima Zavinfce7a472011-04-19 22:30:36 -07004737
Dima Zavin799a70e2011-04-18 16:57:27 -07004738 s = mInput->stream->common.get_parameters(&mInput->stream->common, keys.string());
Dima Zavinfce7a472011-04-19 22:30:36 -07004739 out_s8 = String8(s);
4740 free(s);
4741 return out_s8;
Mathias Agopian65ab4712010-07-14 17:59:35 -07004742}
4743
4744void AudioFlinger::RecordThread::audioConfigChanged_l(int event, int param) {
4745 AudioSystem::OutputDescriptor desc;
Glenn Kastena0d68332012-01-27 16:47:15 -08004746 void *param2 = NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -07004747
4748 switch (event) {
4749 case AudioSystem::INPUT_OPENED:
4750 case AudioSystem::INPUT_CONFIG_CHANGED:
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07004751 desc.channels = mChannelMask;
Mathias Agopian65ab4712010-07-14 17:59:35 -07004752 desc.samplingRate = mSampleRate;
4753 desc.format = mFormat;
4754 desc.frameCount = mFrameCount;
4755 desc.latency = 0;
4756 param2 = &desc;
4757 break;
4758
4759 case AudioSystem::INPUT_CLOSED:
4760 default:
4761 break;
4762 }
4763 mAudioFlinger->audioConfigChanged_l(event, mId, param2);
4764}
4765
4766void AudioFlinger::RecordThread::readInputParameters()
4767{
Glenn Kastene9dd0172012-01-27 18:08:45 -08004768 delete mRsmpInBuffer;
4769 // mRsmpInBuffer is always assigned a new[] below
4770 delete mRsmpOutBuffer;
4771 mRsmpOutBuffer = NULL;
4772 delete mResampler;
Glenn Kastene0feee32011-12-13 11:53:26 -08004773 mResampler = NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -07004774
Dima Zavin799a70e2011-04-18 16:57:27 -07004775 mSampleRate = mInput->stream->common.get_sample_rate(&mInput->stream->common);
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07004776 mChannelMask = mInput->stream->common.get_channels(&mInput->stream->common);
4777 mChannelCount = (uint16_t)popcount(mChannelMask);
Dima Zavin799a70e2011-04-18 16:57:27 -07004778 mFormat = mInput->stream->common.get_format(&mInput->stream->common);
Glenn Kastenb9980652012-01-11 09:48:27 -08004779 mFrameSize = audio_stream_frame_size(&mInput->stream->common);
Dima Zavin799a70e2011-04-18 16:57:27 -07004780 mInputBytes = mInput->stream->common.get_buffer_size(&mInput->stream->common);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004781 mFrameCount = mInputBytes / mFrameSize;
4782 mRsmpInBuffer = new int16_t[mFrameCount * mChannelCount];
4783
4784 if (mSampleRate != mReqSampleRate && mChannelCount < 3 && mReqChannelCount < 3)
4785 {
4786 int channelCount;
4787 // optmization: if mono to mono, use the resampler in stereo to stereo mode to avoid
4788 // stereo to mono post process as the resampler always outputs stereo.
4789 if (mChannelCount == 1 && mReqChannelCount == 2) {
4790 channelCount = 1;
4791 } else {
4792 channelCount = 2;
4793 }
4794 mResampler = AudioResampler::create(16, channelCount, mReqSampleRate);
4795 mResampler->setSampleRate(mSampleRate);
4796 mResampler->setVolume(AudioMixer::UNITY_GAIN, AudioMixer::UNITY_GAIN);
4797 mRsmpOutBuffer = new int32_t[mFrameCount * 2];
4798
4799 // optmization: if mono to mono, alter input frame count as if we were inputing stereo samples
4800 if (mChannelCount == 1 && mReqChannelCount == 1) {
4801 mFrameCount >>= 1;
4802 }
4803
4804 }
4805 mRsmpInIndex = mFrameCount;
4806}
4807
4808unsigned int AudioFlinger::RecordThread::getInputFramesLost()
4809{
Eric Laurentb8ba0a92011-08-07 16:32:26 -07004810 Mutex::Autolock _l(mLock);
4811 if (initCheck() != NO_ERROR) {
4812 return 0;
4813 }
4814
Dima Zavin799a70e2011-04-18 16:57:27 -07004815 return mInput->stream->get_input_frames_lost(mInput->stream);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004816}
4817
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004818uint32_t AudioFlinger::RecordThread::hasAudioSession(int sessionId)
4819{
4820 Mutex::Autolock _l(mLock);
4821 uint32_t result = 0;
4822 if (getEffectChain_l(sessionId) != 0) {
4823 result = EFFECT_SESSION;
4824 }
4825
4826 if (mTrack != NULL && sessionId == mTrack->sessionId()) {
4827 result |= TRACK_SESSION;
4828 }
4829
4830 return result;
4831}
4832
Eric Laurent59bd0da2011-08-01 09:52:20 -07004833AudioFlinger::RecordThread::RecordTrack* AudioFlinger::RecordThread::track()
4834{
4835 Mutex::Autolock _l(mLock);
4836 return mTrack;
4837}
4838
Glenn Kastenaed850d2012-01-26 09:46:34 -08004839AudioFlinger::AudioStreamIn* AudioFlinger::RecordThread::getInput() const
Eric Laurentb8ba0a92011-08-07 16:32:26 -07004840{
4841 Mutex::Autolock _l(mLock);
4842 return mInput;
4843}
4844
4845AudioFlinger::AudioStreamIn* AudioFlinger::RecordThread::clearInput()
4846{
4847 Mutex::Autolock _l(mLock);
4848 AudioStreamIn *input = mInput;
4849 mInput = NULL;
4850 return input;
4851}
4852
4853// this method must always be called either with ThreadBase mLock held or inside the thread loop
4854audio_stream_t* AudioFlinger::RecordThread::stream()
4855{
4856 if (mInput == NULL) {
4857 return NULL;
4858 }
4859 return &mInput->stream->common;
4860}
4861
4862
Mathias Agopian65ab4712010-07-14 17:59:35 -07004863// ----------------------------------------------------------------------------
4864
Glenn Kasten72ef00d2012-01-17 11:09:42 -08004865audio_io_handle_t AudioFlinger::openOutput(uint32_t *pDevices,
Mathias Agopian65ab4712010-07-14 17:59:35 -07004866 uint32_t *pSamplingRate,
Glenn Kasten58f30212012-01-12 12:27:51 -08004867 audio_format_t *pFormat,
Mathias Agopian65ab4712010-07-14 17:59:35 -07004868 uint32_t *pChannels,
4869 uint32_t *pLatencyMs,
4870 uint32_t flags)
4871{
4872 status_t status;
4873 PlaybackThread *thread = NULL;
4874 mHardwareStatus = AUDIO_HW_OUTPUT_OPEN;
4875 uint32_t samplingRate = pSamplingRate ? *pSamplingRate : 0;
Glenn Kasten58f30212012-01-12 12:27:51 -08004876 audio_format_t format = pFormat ? *pFormat : AUDIO_FORMAT_DEFAULT;
Mathias Agopian65ab4712010-07-14 17:59:35 -07004877 uint32_t channels = pChannels ? *pChannels : 0;
4878 uint32_t latency = pLatencyMs ? *pLatencyMs : 0;
Dima Zavin799a70e2011-04-18 16:57:27 -07004879 audio_stream_out_t *outStream;
4880 audio_hw_device_t *outHwDev;
Mathias Agopian65ab4712010-07-14 17:59:35 -07004881
Steve Block3856b092011-10-20 11:56:00 +01004882 ALOGV("openOutput(), Device %x, SamplingRate %d, Format %d, Channels %x, flags %x",
Mathias Agopian65ab4712010-07-14 17:59:35 -07004883 pDevices ? *pDevices : 0,
4884 samplingRate,
4885 format,
4886 channels,
4887 flags);
4888
4889 if (pDevices == NULL || *pDevices == 0) {
4890 return 0;
4891 }
Dima Zavin799a70e2011-04-18 16:57:27 -07004892
Mathias Agopian65ab4712010-07-14 17:59:35 -07004893 Mutex::Autolock _l(mLock);
4894
Dima Zavin799a70e2011-04-18 16:57:27 -07004895 outHwDev = findSuitableHwDev_l(*pDevices);
4896 if (outHwDev == NULL)
4897 return 0;
4898
Glenn Kasten58f30212012-01-12 12:27:51 -08004899 status = outHwDev->open_output_stream(outHwDev, *pDevices, &format,
Dima Zavin799a70e2011-04-18 16:57:27 -07004900 &channels, &samplingRate, &outStream);
Steve Block3856b092011-10-20 11:56:00 +01004901 ALOGV("openOutput() openOutputStream returned output %p, SamplingRate %d, Format %d, Channels %x, status %d",
Dima Zavin799a70e2011-04-18 16:57:27 -07004902 outStream,
Mathias Agopian65ab4712010-07-14 17:59:35 -07004903 samplingRate,
4904 format,
4905 channels,
4906 status);
4907
4908 mHardwareStatus = AUDIO_HW_IDLE;
Dima Zavin799a70e2011-04-18 16:57:27 -07004909 if (outStream != NULL) {
4910 AudioStreamOut *output = new AudioStreamOut(outHwDev, outStream);
Glenn Kasten72ef00d2012-01-17 11:09:42 -08004911 audio_io_handle_t id = nextUniqueId();
Dima Zavin799a70e2011-04-18 16:57:27 -07004912
Dima Zavinfce7a472011-04-19 22:30:36 -07004913 if ((flags & AUDIO_POLICY_OUTPUT_FLAG_DIRECT) ||
4914 (format != AUDIO_FORMAT_PCM_16_BIT) ||
4915 (channels != AUDIO_CHANNEL_OUT_STEREO)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07004916 thread = new DirectOutputThread(this, output, id, *pDevices);
Steve Block3856b092011-10-20 11:56:00 +01004917 ALOGV("openOutput() created direct output: ID %d thread %p", id, thread);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004918 } else {
4919 thread = new MixerThread(this, output, id, *pDevices);
Steve Block3856b092011-10-20 11:56:00 +01004920 ALOGV("openOutput() created mixer output: ID %d thread %p", id, thread);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004921 }
4922 mPlaybackThreads.add(id, thread);
4923
Glenn Kastena0d68332012-01-27 16:47:15 -08004924 if (pSamplingRate != NULL) *pSamplingRate = samplingRate;
4925 if (pFormat != NULL) *pFormat = format;
4926 if (pChannels != NULL) *pChannels = channels;
4927 if (pLatencyMs != NULL) *pLatencyMs = thread->latency();
Mathias Agopian65ab4712010-07-14 17:59:35 -07004928
4929 // notify client processes of the new output creation
4930 thread->audioConfigChanged_l(AudioSystem::OUTPUT_OPENED);
4931 return id;
4932 }
4933
4934 return 0;
4935}
4936
Glenn Kasten72ef00d2012-01-17 11:09:42 -08004937audio_io_handle_t AudioFlinger::openDuplicateOutput(audio_io_handle_t output1,
4938 audio_io_handle_t output2)
Mathias Agopian65ab4712010-07-14 17:59:35 -07004939{
4940 Mutex::Autolock _l(mLock);
4941 MixerThread *thread1 = checkMixerThread_l(output1);
4942 MixerThread *thread2 = checkMixerThread_l(output2);
4943
4944 if (thread1 == NULL || thread2 == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +00004945 ALOGW("openDuplicateOutput() wrong output mixer type for output %d or %d", output1, output2);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004946 return 0;
4947 }
4948
Glenn Kasten72ef00d2012-01-17 11:09:42 -08004949 audio_io_handle_t id = nextUniqueId();
Mathias Agopian65ab4712010-07-14 17:59:35 -07004950 DuplicatingThread *thread = new DuplicatingThread(this, thread1, id);
4951 thread->addOutputTrack(thread2);
4952 mPlaybackThreads.add(id, thread);
4953 // notify client processes of the new output creation
4954 thread->audioConfigChanged_l(AudioSystem::OUTPUT_OPENED);
4955 return id;
4956}
4957
Glenn Kasten72ef00d2012-01-17 11:09:42 -08004958status_t AudioFlinger::closeOutput(audio_io_handle_t output)
Mathias Agopian65ab4712010-07-14 17:59:35 -07004959{
4960 // keep strong reference on the playback thread so that
4961 // it is not destroyed while exit() is executed
4962 sp <PlaybackThread> thread;
4963 {
4964 Mutex::Autolock _l(mLock);
4965 thread = checkPlaybackThread_l(output);
4966 if (thread == NULL) {
4967 return BAD_VALUE;
4968 }
4969
Steve Block3856b092011-10-20 11:56:00 +01004970 ALOGV("closeOutput() %d", output);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004971
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004972 if (thread->type() == ThreadBase::MIXER) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07004973 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004974 if (mPlaybackThreads.valueAt(i)->type() == ThreadBase::DUPLICATING) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07004975 DuplicatingThread *dupThread = (DuplicatingThread *)mPlaybackThreads.valueAt(i).get();
4976 dupThread->removeOutputTrack((MixerThread *)thread.get());
4977 }
4978 }
4979 }
Glenn Kastena0d68332012-01-27 16:47:15 -08004980 void *param2 = NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -07004981 audioConfigChanged_l(AudioSystem::OUTPUT_CLOSED, output, param2);
4982 mPlaybackThreads.removeItem(output);
4983 }
4984 thread->exit();
Glenn Kastenb28686f2012-01-06 08:39:38 -08004985 // The thread entity (active unit of execution) is no longer running here,
4986 // but the ThreadBase container still exists.
Mathias Agopian65ab4712010-07-14 17:59:35 -07004987
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004988 if (thread->type() != ThreadBase::DUPLICATING) {
Eric Laurentb8ba0a92011-08-07 16:32:26 -07004989 AudioStreamOut *out = thread->clearOutput();
Glenn Kastenaed850d2012-01-26 09:46:34 -08004990 assert(out != NULL);
Eric Laurentb8ba0a92011-08-07 16:32:26 -07004991 // from now on thread->mOutput is NULL
Dima Zavin799a70e2011-04-18 16:57:27 -07004992 out->hwDev->close_output_stream(out->hwDev, out->stream);
4993 delete out;
Mathias Agopian65ab4712010-07-14 17:59:35 -07004994 }
4995 return NO_ERROR;
4996}
4997
Glenn Kasten72ef00d2012-01-17 11:09:42 -08004998status_t AudioFlinger::suspendOutput(audio_io_handle_t output)
Mathias Agopian65ab4712010-07-14 17:59:35 -07004999{
5000 Mutex::Autolock _l(mLock);
5001 PlaybackThread *thread = checkPlaybackThread_l(output);
5002
5003 if (thread == NULL) {
5004 return BAD_VALUE;
5005 }
5006
Steve Block3856b092011-10-20 11:56:00 +01005007 ALOGV("suspendOutput() %d", output);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005008 thread->suspend();
5009
5010 return NO_ERROR;
5011}
5012
Glenn Kasten72ef00d2012-01-17 11:09:42 -08005013status_t AudioFlinger::restoreOutput(audio_io_handle_t output)
Mathias Agopian65ab4712010-07-14 17:59:35 -07005014{
5015 Mutex::Autolock _l(mLock);
5016 PlaybackThread *thread = checkPlaybackThread_l(output);
5017
5018 if (thread == NULL) {
5019 return BAD_VALUE;
5020 }
5021
Steve Block3856b092011-10-20 11:56:00 +01005022 ALOGV("restoreOutput() %d", output);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005023
5024 thread->restore();
5025
5026 return NO_ERROR;
5027}
5028
Glenn Kasten72ef00d2012-01-17 11:09:42 -08005029audio_io_handle_t AudioFlinger::openInput(uint32_t *pDevices,
Mathias Agopian65ab4712010-07-14 17:59:35 -07005030 uint32_t *pSamplingRate,
Glenn Kasten58f30212012-01-12 12:27:51 -08005031 audio_format_t *pFormat,
Mathias Agopian65ab4712010-07-14 17:59:35 -07005032 uint32_t *pChannels,
Glenn Kastende9719b2012-01-27 12:32:34 -08005033 audio_in_acoustics_t acoustics)
Mathias Agopian65ab4712010-07-14 17:59:35 -07005034{
5035 status_t status;
5036 RecordThread *thread = NULL;
5037 uint32_t samplingRate = pSamplingRate ? *pSamplingRate : 0;
Glenn Kasten58f30212012-01-12 12:27:51 -08005038 audio_format_t format = pFormat ? *pFormat : AUDIO_FORMAT_DEFAULT;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005039 uint32_t channels = pChannels ? *pChannels : 0;
5040 uint32_t reqSamplingRate = samplingRate;
Glenn Kasten58f30212012-01-12 12:27:51 -08005041 audio_format_t reqFormat = format;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005042 uint32_t reqChannels = channels;
Dima Zavin799a70e2011-04-18 16:57:27 -07005043 audio_stream_in_t *inStream;
5044 audio_hw_device_t *inHwDev;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005045
5046 if (pDevices == NULL || *pDevices == 0) {
5047 return 0;
5048 }
Dima Zavin799a70e2011-04-18 16:57:27 -07005049
Mathias Agopian65ab4712010-07-14 17:59:35 -07005050 Mutex::Autolock _l(mLock);
5051
Dima Zavin799a70e2011-04-18 16:57:27 -07005052 inHwDev = findSuitableHwDev_l(*pDevices);
5053 if (inHwDev == NULL)
5054 return 0;
5055
Glenn Kasten58f30212012-01-12 12:27:51 -08005056 status = inHwDev->open_input_stream(inHwDev, *pDevices, &format,
Dima Zavin799a70e2011-04-18 16:57:27 -07005057 &channels, &samplingRate,
Glenn Kastende9719b2012-01-27 12:32:34 -08005058 acoustics,
Dima Zavin799a70e2011-04-18 16:57:27 -07005059 &inStream);
Steve Block3856b092011-10-20 11:56:00 +01005060 ALOGV("openInput() openInputStream returned input %p, SamplingRate %d, Format %d, Channels %x, acoustics %x, status %d",
Dima Zavin799a70e2011-04-18 16:57:27 -07005061 inStream,
Mathias Agopian65ab4712010-07-14 17:59:35 -07005062 samplingRate,
5063 format,
5064 channels,
5065 acoustics,
5066 status);
5067
5068 // If the input could not be opened with the requested parameters and we can handle the conversion internally,
5069 // try to open again with the proposed parameters. The AudioFlinger can resample the input and do mono to stereo
5070 // or stereo to mono conversions on 16 bit PCM inputs.
Dima Zavin799a70e2011-04-18 16:57:27 -07005071 if (inStream == NULL && status == BAD_VALUE &&
Dima Zavinfce7a472011-04-19 22:30:36 -07005072 reqFormat == format && format == AUDIO_FORMAT_PCM_16_BIT &&
Mathias Agopian65ab4712010-07-14 17:59:35 -07005073 (samplingRate <= 2 * reqSamplingRate) &&
Dima Zavinfce7a472011-04-19 22:30:36 -07005074 (popcount(channels) < 3) && (popcount(reqChannels) < 3)) {
Steve Block3856b092011-10-20 11:56:00 +01005075 ALOGV("openInput() reopening with proposed sampling rate and channels");
Glenn Kasten58f30212012-01-12 12:27:51 -08005076 status = inHwDev->open_input_stream(inHwDev, *pDevices, &format,
Dima Zavin799a70e2011-04-18 16:57:27 -07005077 &channels, &samplingRate,
Glenn Kastende9719b2012-01-27 12:32:34 -08005078 acoustics,
Dima Zavin799a70e2011-04-18 16:57:27 -07005079 &inStream);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005080 }
5081
Dima Zavin799a70e2011-04-18 16:57:27 -07005082 if (inStream != NULL) {
5083 AudioStreamIn *input = new AudioStreamIn(inHwDev, inStream);
5084
Glenn Kasten72ef00d2012-01-17 11:09:42 -08005085 audio_io_handle_t id = nextUniqueId();
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005086 // Start record thread
5087 // RecorThread require both input and output device indication to forward to audio
5088 // pre processing modules
5089 uint32_t device = (*pDevices) | primaryOutputDevice_l();
5090 thread = new RecordThread(this,
5091 input,
5092 reqSamplingRate,
5093 reqChannels,
5094 id,
5095 device);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005096 mRecordThreads.add(id, thread);
Steve Block3856b092011-10-20 11:56:00 +01005097 ALOGV("openInput() created record thread: ID %d thread %p", id, thread);
Glenn Kastena0d68332012-01-27 16:47:15 -08005098 if (pSamplingRate != NULL) *pSamplingRate = reqSamplingRate;
5099 if (pFormat != NULL) *pFormat = format;
5100 if (pChannels != NULL) *pChannels = reqChannels;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005101
Dima Zavin799a70e2011-04-18 16:57:27 -07005102 input->stream->common.standby(&input->stream->common);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005103
5104 // notify client processes of the new input creation
5105 thread->audioConfigChanged_l(AudioSystem::INPUT_OPENED);
5106 return id;
5107 }
5108
5109 return 0;
5110}
5111
Glenn Kasten72ef00d2012-01-17 11:09:42 -08005112status_t AudioFlinger::closeInput(audio_io_handle_t input)
Mathias Agopian65ab4712010-07-14 17:59:35 -07005113{
5114 // keep strong reference on the record thread so that
5115 // it is not destroyed while exit() is executed
5116 sp <RecordThread> thread;
5117 {
5118 Mutex::Autolock _l(mLock);
5119 thread = checkRecordThread_l(input);
5120 if (thread == NULL) {
5121 return BAD_VALUE;
5122 }
5123
Steve Block3856b092011-10-20 11:56:00 +01005124 ALOGV("closeInput() %d", input);
Glenn Kastena0d68332012-01-27 16:47:15 -08005125 void *param2 = NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005126 audioConfigChanged_l(AudioSystem::INPUT_CLOSED, input, param2);
5127 mRecordThreads.removeItem(input);
5128 }
5129 thread->exit();
Glenn Kastenb28686f2012-01-06 08:39:38 -08005130 // The thread entity (active unit of execution) is no longer running here,
5131 // but the ThreadBase container still exists.
Mathias Agopian65ab4712010-07-14 17:59:35 -07005132
Eric Laurentb8ba0a92011-08-07 16:32:26 -07005133 AudioStreamIn *in = thread->clearInput();
Glenn Kastenaed850d2012-01-26 09:46:34 -08005134 assert(in != NULL);
Eric Laurentb8ba0a92011-08-07 16:32:26 -07005135 // from now on thread->mInput is NULL
Dima Zavin799a70e2011-04-18 16:57:27 -07005136 in->hwDev->close_input_stream(in->hwDev, in->stream);
5137 delete in;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005138
5139 return NO_ERROR;
5140}
5141
Glenn Kasten72ef00d2012-01-17 11:09:42 -08005142status_t AudioFlinger::setStreamOutput(audio_stream_type_t stream, audio_io_handle_t output)
Mathias Agopian65ab4712010-07-14 17:59:35 -07005143{
5144 Mutex::Autolock _l(mLock);
5145 MixerThread *dstThread = checkMixerThread_l(output);
5146 if (dstThread == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +00005147 ALOGW("setStreamOutput() bad output id %d", output);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005148 return BAD_VALUE;
5149 }
5150
Steve Block3856b092011-10-20 11:56:00 +01005151 ALOGV("setStreamOutput() stream %d to output %d", stream, output);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005152 audioConfigChanged_l(AudioSystem::STREAM_CONFIG_CHANGED, output, &stream);
5153
Eric Laurent9f6530f2011-08-30 10:18:54 -07005154 dstThread->setStreamValid(stream, true);
5155
Mathias Agopian65ab4712010-07-14 17:59:35 -07005156 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
5157 PlaybackThread *thread = mPlaybackThreads.valueAt(i).get();
5158 if (thread != dstThread &&
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005159 thread->type() != ThreadBase::DIRECT) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07005160 MixerThread *srcThread = (MixerThread *)thread;
Eric Laurent9f6530f2011-08-30 10:18:54 -07005161 srcThread->setStreamValid(stream, false);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005162 srcThread->invalidateTracks(stream);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005163 }
Eric Laurentde070132010-07-13 04:45:46 -07005164 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07005165
5166 return NO_ERROR;
5167}
5168
5169
5170int AudioFlinger::newAudioSessionId()
5171{
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005172 return nextUniqueId();
Mathias Agopian65ab4712010-07-14 17:59:35 -07005173}
5174
Marco Nelissen3a34bef2011-08-02 13:33:41 -07005175void AudioFlinger::acquireAudioSessionId(int audioSession)
5176{
5177 Mutex::Autolock _l(mLock);
Glenn Kastenbb001922012-02-03 11:10:26 -08005178 pid_t caller = IPCThreadState::self()->getCallingPid();
Steve Block3856b092011-10-20 11:56:00 +01005179 ALOGV("acquiring %d from %d", audioSession, caller);
Glenn Kasten8d6a2442012-02-08 14:04:28 -08005180 size_t num = mAudioSessionRefs.size();
5181 for (size_t i = 0; i< num; i++) {
Marco Nelissen3a34bef2011-08-02 13:33:41 -07005182 AudioSessionRef *ref = mAudioSessionRefs.editItemAt(i);
5183 if (ref->sessionid == audioSession && ref->pid == caller) {
5184 ref->cnt++;
Steve Block3856b092011-10-20 11:56:00 +01005185 ALOGV(" incremented refcount to %d", ref->cnt);
Marco Nelissen3a34bef2011-08-02 13:33:41 -07005186 return;
5187 }
5188 }
Glenn Kasten84afa3b2012-01-25 15:28:08 -08005189 mAudioSessionRefs.push(new AudioSessionRef(audioSession, caller));
5190 ALOGV(" added new entry for %d", audioSession);
Marco Nelissen3a34bef2011-08-02 13:33:41 -07005191}
5192
5193void AudioFlinger::releaseAudioSessionId(int audioSession)
5194{
5195 Mutex::Autolock _l(mLock);
Glenn Kastenbb001922012-02-03 11:10:26 -08005196 pid_t caller = IPCThreadState::self()->getCallingPid();
Steve Block3856b092011-10-20 11:56:00 +01005197 ALOGV("releasing %d from %d", audioSession, caller);
Glenn Kasten8d6a2442012-02-08 14:04:28 -08005198 size_t num = mAudioSessionRefs.size();
5199 for (size_t i = 0; i< num; i++) {
Marco Nelissen3a34bef2011-08-02 13:33:41 -07005200 AudioSessionRef *ref = mAudioSessionRefs.itemAt(i);
5201 if (ref->sessionid == audioSession && ref->pid == caller) {
5202 ref->cnt--;
Steve Block3856b092011-10-20 11:56:00 +01005203 ALOGV(" decremented refcount to %d", ref->cnt);
Marco Nelissen3a34bef2011-08-02 13:33:41 -07005204 if (ref->cnt == 0) {
5205 mAudioSessionRefs.removeAt(i);
5206 delete ref;
5207 purgeStaleEffects_l();
5208 }
5209 return;
5210 }
5211 }
Steve Block5ff1dd52012-01-05 23:22:43 +00005212 ALOGW("session id %d not found for pid %d", audioSession, caller);
Marco Nelissen3a34bef2011-08-02 13:33:41 -07005213}
5214
5215void AudioFlinger::purgeStaleEffects_l() {
5216
Steve Block3856b092011-10-20 11:56:00 +01005217 ALOGV("purging stale effects");
Marco Nelissen3a34bef2011-08-02 13:33:41 -07005218
5219 Vector< sp<EffectChain> > chains;
5220
5221 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
5222 sp<PlaybackThread> t = mPlaybackThreads.valueAt(i);
5223 for (size_t j = 0; j < t->mEffectChains.size(); j++) {
5224 sp<EffectChain> ec = t->mEffectChains[j];
Marco Nelissen0270b182011-08-12 14:14:39 -07005225 if (ec->sessionId() > AUDIO_SESSION_OUTPUT_MIX) {
5226 chains.push(ec);
5227 }
Marco Nelissen3a34bef2011-08-02 13:33:41 -07005228 }
5229 }
5230 for (size_t i = 0; i < mRecordThreads.size(); i++) {
5231 sp<RecordThread> t = mRecordThreads.valueAt(i);
5232 for (size_t j = 0; j < t->mEffectChains.size(); j++) {
5233 sp<EffectChain> ec = t->mEffectChains[j];
5234 chains.push(ec);
5235 }
5236 }
5237
5238 for (size_t i = 0; i < chains.size(); i++) {
5239 sp<EffectChain> ec = chains[i];
5240 int sessionid = ec->sessionId();
5241 sp<ThreadBase> t = ec->mThread.promote();
5242 if (t == 0) {
5243 continue;
5244 }
5245 size_t numsessionrefs = mAudioSessionRefs.size();
5246 bool found = false;
5247 for (size_t k = 0; k < numsessionrefs; k++) {
5248 AudioSessionRef *ref = mAudioSessionRefs.itemAt(k);
5249 if (ref->sessionid == sessionid) {
Steve Block3856b092011-10-20 11:56:00 +01005250 ALOGV(" session %d still exists for %d with %d refs",
Marco Nelissen3a34bef2011-08-02 13:33:41 -07005251 sessionid, ref->pid, ref->cnt);
5252 found = true;
5253 break;
5254 }
5255 }
5256 if (!found) {
5257 // remove all effects from the chain
5258 while (ec->mEffects.size()) {
5259 sp<EffectModule> effect = ec->mEffects[0];
5260 effect->unPin();
5261 Mutex::Autolock _l (t->mLock);
5262 t->removeEffect_l(effect);
5263 for (size_t j = 0; j < effect->mHandles.size(); j++) {
5264 sp<EffectHandle> handle = effect->mHandles[j].promote();
5265 if (handle != 0) {
5266 handle->mEffect.clear();
Eric Laurenta85a74a2011-10-19 11:44:54 -07005267 if (handle->mHasControl && handle->mEnabled) {
5268 t->checkSuspendOnEffectEnabled_l(effect, false, effect->sessionId());
5269 }
Marco Nelissen3a34bef2011-08-02 13:33:41 -07005270 }
5271 }
5272 AudioSystem::unregisterEffect(effect->id());
5273 }
5274 }
5275 }
5276 return;
5277}
5278
Mathias Agopian65ab4712010-07-14 17:59:35 -07005279// checkPlaybackThread_l() must be called with AudioFlinger::mLock held
Glenn Kasten72ef00d2012-01-17 11:09:42 -08005280AudioFlinger::PlaybackThread *AudioFlinger::checkPlaybackThread_l(audio_io_handle_t output) const
Mathias Agopian65ab4712010-07-14 17:59:35 -07005281{
5282 PlaybackThread *thread = NULL;
5283 if (mPlaybackThreads.indexOfKey(output) >= 0) {
5284 thread = (PlaybackThread *)mPlaybackThreads.valueFor(output).get();
5285 }
5286 return thread;
5287}
5288
5289// checkMixerThread_l() must be called with AudioFlinger::mLock held
Glenn Kasten72ef00d2012-01-17 11:09:42 -08005290AudioFlinger::MixerThread *AudioFlinger::checkMixerThread_l(audio_io_handle_t output) const
Mathias Agopian65ab4712010-07-14 17:59:35 -07005291{
5292 PlaybackThread *thread = checkPlaybackThread_l(output);
5293 if (thread != NULL) {
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005294 if (thread->type() == ThreadBase::DIRECT) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07005295 thread = NULL;
5296 }
5297 }
5298 return (MixerThread *)thread;
5299}
5300
5301// checkRecordThread_l() must be called with AudioFlinger::mLock held
Glenn Kasten72ef00d2012-01-17 11:09:42 -08005302AudioFlinger::RecordThread *AudioFlinger::checkRecordThread_l(audio_io_handle_t input) const
Mathias Agopian65ab4712010-07-14 17:59:35 -07005303{
5304 RecordThread *thread = NULL;
5305 if (mRecordThreads.indexOfKey(input) >= 0) {
5306 thread = (RecordThread *)mRecordThreads.valueFor(input).get();
5307 }
5308 return thread;
5309}
5310
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005311uint32_t AudioFlinger::nextUniqueId()
Mathias Agopian65ab4712010-07-14 17:59:35 -07005312{
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005313 return android_atomic_inc(&mNextUniqueId);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005314}
5315
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005316AudioFlinger::PlaybackThread *AudioFlinger::primaryPlaybackThread_l()
5317{
5318 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
5319 PlaybackThread *thread = mPlaybackThreads.valueAt(i).get();
Eric Laurentb8ba0a92011-08-07 16:32:26 -07005320 AudioStreamOut *output = thread->getOutput();
5321 if (output != NULL && output->hwDev == mPrimaryHardwareDev) {
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005322 return thread;
5323 }
5324 }
5325 return NULL;
5326}
5327
5328uint32_t AudioFlinger::primaryOutputDevice_l()
5329{
5330 PlaybackThread *thread = primaryPlaybackThread_l();
5331
5332 if (thread == NULL) {
5333 return 0;
5334 }
5335
5336 return thread->device();
5337}
5338
5339
Mathias Agopian65ab4712010-07-14 17:59:35 -07005340// ----------------------------------------------------------------------------
5341// Effect management
5342// ----------------------------------------------------------------------------
5343
5344
Glenn Kastenf587ba52012-01-26 16:25:10 -08005345status_t AudioFlinger::queryNumberEffects(uint32_t *numEffects) const
Mathias Agopian65ab4712010-07-14 17:59:35 -07005346{
5347 Mutex::Autolock _l(mLock);
5348 return EffectQueryNumberEffects(numEffects);
5349}
5350
Glenn Kastenf587ba52012-01-26 16:25:10 -08005351status_t AudioFlinger::queryEffect(uint32_t index, effect_descriptor_t *descriptor) const
Mathias Agopian65ab4712010-07-14 17:59:35 -07005352{
5353 Mutex::Autolock _l(mLock);
5354 return EffectQueryEffect(index, descriptor);
5355}
5356
Glenn Kasten5e92a782012-01-30 07:40:52 -08005357status_t AudioFlinger::getEffectDescriptor(const effect_uuid_t *pUuid,
Glenn Kastenf587ba52012-01-26 16:25:10 -08005358 effect_descriptor_t *descriptor) const
Mathias Agopian65ab4712010-07-14 17:59:35 -07005359{
5360 Mutex::Autolock _l(mLock);
5361 return EffectGetDescriptor(pUuid, descriptor);
5362}
5363
5364
Mathias Agopian65ab4712010-07-14 17:59:35 -07005365sp<IEffect> AudioFlinger::createEffect(pid_t pid,
5366 effect_descriptor_t *pDesc,
5367 const sp<IEffectClient>& effectClient,
5368 int32_t priority,
Glenn Kasten72ef00d2012-01-17 11:09:42 -08005369 audio_io_handle_t io,
Mathias Agopian65ab4712010-07-14 17:59:35 -07005370 int sessionId,
5371 status_t *status,
5372 int *id,
5373 int *enabled)
5374{
5375 status_t lStatus = NO_ERROR;
5376 sp<EffectHandle> handle;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005377 effect_descriptor_t desc;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005378
Glenn Kasten98ec94c2012-01-25 14:28:29 -08005379 ALOGV("createEffect pid %d, effectClient %p, priority %d, sessionId %d, io %d",
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005380 pid, effectClient.get(), priority, sessionId, io);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005381
5382 if (pDesc == NULL) {
5383 lStatus = BAD_VALUE;
5384 goto Exit;
5385 }
5386
Eric Laurent84e9a102010-09-23 16:10:16 -07005387 // check audio settings permission for global effects
Dima Zavinfce7a472011-04-19 22:30:36 -07005388 if (sessionId == AUDIO_SESSION_OUTPUT_MIX && !settingsAllowed()) {
Eric Laurent84e9a102010-09-23 16:10:16 -07005389 lStatus = PERMISSION_DENIED;
5390 goto Exit;
5391 }
5392
Dima Zavinfce7a472011-04-19 22:30:36 -07005393 // Session AUDIO_SESSION_OUTPUT_STAGE is reserved for output stage effects
Eric Laurent84e9a102010-09-23 16:10:16 -07005394 // that can only be created by audio policy manager (running in same process)
Glenn Kasten44deb052012-02-05 18:09:08 -08005395 if (sessionId == AUDIO_SESSION_OUTPUT_STAGE && getpid_cached != pid) {
Eric Laurent84e9a102010-09-23 16:10:16 -07005396 lStatus = PERMISSION_DENIED;
5397 goto Exit;
5398 }
5399
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005400 if (io == 0) {
Dima Zavinfce7a472011-04-19 22:30:36 -07005401 if (sessionId == AUDIO_SESSION_OUTPUT_STAGE) {
Eric Laurent84e9a102010-09-23 16:10:16 -07005402 // output must be specified by AudioPolicyManager when using session
Dima Zavinfce7a472011-04-19 22:30:36 -07005403 // AUDIO_SESSION_OUTPUT_STAGE
Eric Laurent84e9a102010-09-23 16:10:16 -07005404 lStatus = BAD_VALUE;
5405 goto Exit;
Dima Zavinfce7a472011-04-19 22:30:36 -07005406 } else if (sessionId == AUDIO_SESSION_OUTPUT_MIX) {
Eric Laurent84e9a102010-09-23 16:10:16 -07005407 // if the output returned by getOutputForEffect() is removed before we lock the
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005408 // mutex below, the call to checkPlaybackThread_l(io) below will detect it
Eric Laurent84e9a102010-09-23 16:10:16 -07005409 // and we will exit safely
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005410 io = AudioSystem::getOutputForEffect(&desc);
Eric Laurent84e9a102010-09-23 16:10:16 -07005411 }
5412 }
5413
Mathias Agopian65ab4712010-07-14 17:59:35 -07005414 {
5415 Mutex::Autolock _l(mLock);
5416
Mathias Agopian65ab4712010-07-14 17:59:35 -07005417
5418 if (!EffectIsNullUuid(&pDesc->uuid)) {
5419 // if uuid is specified, request effect descriptor
5420 lStatus = EffectGetDescriptor(&pDesc->uuid, &desc);
5421 if (lStatus < 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00005422 ALOGW("createEffect() error %d from EffectGetDescriptor", lStatus);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005423 goto Exit;
5424 }
5425 } else {
5426 // if uuid is not specified, look for an available implementation
5427 // of the required type in effect factory
5428 if (EffectIsNullUuid(&pDesc->type)) {
Steve Block5ff1dd52012-01-05 23:22:43 +00005429 ALOGW("createEffect() no effect type");
Mathias Agopian65ab4712010-07-14 17:59:35 -07005430 lStatus = BAD_VALUE;
5431 goto Exit;
5432 }
5433 uint32_t numEffects = 0;
5434 effect_descriptor_t d;
Marco Nelissen3a34bef2011-08-02 13:33:41 -07005435 d.flags = 0; // prevent compiler warning
Mathias Agopian65ab4712010-07-14 17:59:35 -07005436 bool found = false;
5437
5438 lStatus = EffectQueryNumberEffects(&numEffects);
5439 if (lStatus < 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00005440 ALOGW("createEffect() error %d from EffectQueryNumberEffects", lStatus);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005441 goto Exit;
5442 }
5443 for (uint32_t i = 0; i < numEffects; i++) {
5444 lStatus = EffectQueryEffect(i, &desc);
5445 if (lStatus < 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00005446 ALOGW("createEffect() error %d from EffectQueryEffect", lStatus);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005447 continue;
5448 }
5449 if (memcmp(&desc.type, &pDesc->type, sizeof(effect_uuid_t)) == 0) {
5450 // If matching type found save effect descriptor. If the session is
5451 // 0 and the effect is not auxiliary, continue enumeration in case
5452 // an auxiliary version of this effect type is available
5453 found = true;
5454 memcpy(&d, &desc, sizeof(effect_descriptor_t));
Dima Zavinfce7a472011-04-19 22:30:36 -07005455 if (sessionId != AUDIO_SESSION_OUTPUT_MIX ||
Mathias Agopian65ab4712010-07-14 17:59:35 -07005456 (desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
5457 break;
5458 }
5459 }
5460 }
5461 if (!found) {
5462 lStatus = BAD_VALUE;
Steve Block5ff1dd52012-01-05 23:22:43 +00005463 ALOGW("createEffect() effect not found");
Mathias Agopian65ab4712010-07-14 17:59:35 -07005464 goto Exit;
5465 }
5466 // For same effect type, chose auxiliary version over insert version if
5467 // connect to output mix (Compliance to OpenSL ES)
Dima Zavinfce7a472011-04-19 22:30:36 -07005468 if (sessionId == AUDIO_SESSION_OUTPUT_MIX &&
Mathias Agopian65ab4712010-07-14 17:59:35 -07005469 (d.flags & EFFECT_FLAG_TYPE_MASK) != EFFECT_FLAG_TYPE_AUXILIARY) {
5470 memcpy(&desc, &d, sizeof(effect_descriptor_t));
5471 }
5472 }
5473
5474 // Do not allow auxiliary effects on a session different from 0 (output mix)
Dima Zavinfce7a472011-04-19 22:30:36 -07005475 if (sessionId != AUDIO_SESSION_OUTPUT_MIX &&
Mathias Agopian65ab4712010-07-14 17:59:35 -07005476 (desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
5477 lStatus = INVALID_OPERATION;
5478 goto Exit;
5479 }
5480
Eric Laurent59255e42011-07-27 19:49:51 -07005481 // check recording permission for visualizer
5482 if ((memcmp(&desc.type, SL_IID_VISUALIZATION, sizeof(effect_uuid_t)) == 0) &&
5483 !recordingAllowed()) {
5484 lStatus = PERMISSION_DENIED;
5485 goto Exit;
5486 }
5487
Mathias Agopian65ab4712010-07-14 17:59:35 -07005488 // return effect descriptor
5489 memcpy(pDesc, &desc, sizeof(effect_descriptor_t));
5490
5491 // If output is not specified try to find a matching audio session ID in one of the
5492 // output threads.
Eric Laurent84e9a102010-09-23 16:10:16 -07005493 // If output is 0 here, sessionId is neither SESSION_OUTPUT_STAGE nor SESSION_OUTPUT_MIX
5494 // because of code checking output when entering the function.
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005495 // Note: io is never 0 when creating an effect on an input
5496 if (io == 0) {
Eric Laurent84e9a102010-09-23 16:10:16 -07005497 // look for the thread where the specified audio session is present
5498 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
5499 if (mPlaybackThreads.valueAt(i)->hasAudioSession(sessionId) != 0) {
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005500 io = mPlaybackThreads.keyAt(i);
Eric Laurent84e9a102010-09-23 16:10:16 -07005501 break;
Eric Laurent39e94f82010-07-28 01:32:47 -07005502 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07005503 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005504 if (io == 0) {
5505 for (size_t i = 0; i < mRecordThreads.size(); i++) {
5506 if (mRecordThreads.valueAt(i)->hasAudioSession(sessionId) != 0) {
5507 io = mRecordThreads.keyAt(i);
5508 break;
5509 }
5510 }
5511 }
Eric Laurent84e9a102010-09-23 16:10:16 -07005512 // If no output thread contains the requested session ID, default to
5513 // first output. The effect chain will be moved to the correct output
5514 // thread when a track with the same session ID is created
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005515 if (io == 0 && mPlaybackThreads.size()) {
5516 io = mPlaybackThreads.keyAt(0);
5517 }
Steve Block3856b092011-10-20 11:56:00 +01005518 ALOGV("createEffect() got io %d for effect %s", io, desc.name);
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005519 }
5520 ThreadBase *thread = checkRecordThread_l(io);
5521 if (thread == NULL) {
5522 thread = checkPlaybackThread_l(io);
5523 if (thread == NULL) {
Steve Block29357bc2012-01-06 19:20:56 +00005524 ALOGE("createEffect() unknown output thread");
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005525 lStatus = BAD_VALUE;
5526 goto Exit;
Eric Laurent84e9a102010-09-23 16:10:16 -07005527 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07005528 }
Eric Laurent84e9a102010-09-23 16:10:16 -07005529
Glenn Kasten98ec94c2012-01-25 14:28:29 -08005530 sp<Client> client = registerPid_l(pid);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005531
Marco Nelissen3a34bef2011-08-02 13:33:41 -07005532 // create effect on selected output thread
Eric Laurentde070132010-07-13 04:45:46 -07005533 handle = thread->createEffect_l(client, effectClient, priority, sessionId,
5534 &desc, enabled, &lStatus);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005535 if (handle != 0 && id != NULL) {
5536 *id = handle->id();
5537 }
5538 }
5539
5540Exit:
5541 if(status) {
5542 *status = lStatus;
5543 }
5544 return handle;
5545}
5546
Glenn Kasten72ef00d2012-01-17 11:09:42 -08005547status_t AudioFlinger::moveEffects(int sessionId, audio_io_handle_t srcOutput,
5548 audio_io_handle_t dstOutput)
Eric Laurentde070132010-07-13 04:45:46 -07005549{
Steve Block3856b092011-10-20 11:56:00 +01005550 ALOGV("moveEffects() session %d, srcOutput %d, dstOutput %d",
Eric Laurent59255e42011-07-27 19:49:51 -07005551 sessionId, srcOutput, dstOutput);
Eric Laurentde070132010-07-13 04:45:46 -07005552 Mutex::Autolock _l(mLock);
5553 if (srcOutput == dstOutput) {
Steve Block5ff1dd52012-01-05 23:22:43 +00005554 ALOGW("moveEffects() same dst and src outputs %d", dstOutput);
Eric Laurentde070132010-07-13 04:45:46 -07005555 return NO_ERROR;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005556 }
Eric Laurentde070132010-07-13 04:45:46 -07005557 PlaybackThread *srcThread = checkPlaybackThread_l(srcOutput);
5558 if (srcThread == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +00005559 ALOGW("moveEffects() bad srcOutput %d", srcOutput);
Eric Laurentde070132010-07-13 04:45:46 -07005560 return BAD_VALUE;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005561 }
Eric Laurentde070132010-07-13 04:45:46 -07005562 PlaybackThread *dstThread = checkPlaybackThread_l(dstOutput);
5563 if (dstThread == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +00005564 ALOGW("moveEffects() bad dstOutput %d", dstOutput);
Eric Laurentde070132010-07-13 04:45:46 -07005565 return BAD_VALUE;
5566 }
5567
5568 Mutex::Autolock _dl(dstThread->mLock);
5569 Mutex::Autolock _sl(srcThread->mLock);
Eric Laurent59255e42011-07-27 19:49:51 -07005570 moveEffectChain_l(sessionId, srcThread, dstThread, false);
Eric Laurentde070132010-07-13 04:45:46 -07005571
Mathias Agopian65ab4712010-07-14 17:59:35 -07005572 return NO_ERROR;
5573}
5574
Marco Nelissen3a34bef2011-08-02 13:33:41 -07005575// moveEffectChain_l must be called with both srcThread and dstThread mLocks held
Eric Laurent59255e42011-07-27 19:49:51 -07005576status_t AudioFlinger::moveEffectChain_l(int sessionId,
Eric Laurentde070132010-07-13 04:45:46 -07005577 AudioFlinger::PlaybackThread *srcThread,
Eric Laurent39e94f82010-07-28 01:32:47 -07005578 AudioFlinger::PlaybackThread *dstThread,
5579 bool reRegister)
Eric Laurentde070132010-07-13 04:45:46 -07005580{
Steve Block3856b092011-10-20 11:56:00 +01005581 ALOGV("moveEffectChain_l() session %d from thread %p to thread %p",
Eric Laurent59255e42011-07-27 19:49:51 -07005582 sessionId, srcThread, dstThread);
Eric Laurentde070132010-07-13 04:45:46 -07005583
Eric Laurent59255e42011-07-27 19:49:51 -07005584 sp<EffectChain> chain = srcThread->getEffectChain_l(sessionId);
Eric Laurentde070132010-07-13 04:45:46 -07005585 if (chain == 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00005586 ALOGW("moveEffectChain_l() effect chain for session %d not on source thread %p",
Eric Laurent59255e42011-07-27 19:49:51 -07005587 sessionId, srcThread);
Eric Laurentde070132010-07-13 04:45:46 -07005588 return INVALID_OPERATION;
5589 }
5590
Eric Laurent39e94f82010-07-28 01:32:47 -07005591 // remove chain first. This is useful only if reconfiguring effect chain on same output thread,
Eric Laurentde070132010-07-13 04:45:46 -07005592 // so that a new chain is created with correct parameters when first effect is added. This is
Eric Laurentec35a142011-10-05 17:42:25 -07005593 // otherwise unnecessary as removeEffect_l() will remove the chain when last effect is
Eric Laurentde070132010-07-13 04:45:46 -07005594 // removed.
5595 srcThread->removeEffectChain_l(chain);
5596
5597 // transfer all effects one by one so that new effect chain is created on new thread with
5598 // correct buffer sizes and audio parameters and effect engines reconfigured accordingly
Glenn Kasten72ef00d2012-01-17 11:09:42 -08005599 audio_io_handle_t dstOutput = dstThread->id();
Eric Laurent39e94f82010-07-28 01:32:47 -07005600 sp<EffectChain> dstChain;
Marco Nelissen3a34bef2011-08-02 13:33:41 -07005601 uint32_t strategy = 0; // prevent compiler warning
Eric Laurentde070132010-07-13 04:45:46 -07005602 sp<EffectModule> effect = chain->getEffectFromId_l(0);
5603 while (effect != 0) {
5604 srcThread->removeEffect_l(effect);
5605 dstThread->addEffect_l(effect);
Eric Laurentec35a142011-10-05 17:42:25 -07005606 // removeEffect_l() has stopped the effect if it was active so it must be restarted
5607 if (effect->state() == EffectModule::ACTIVE ||
5608 effect->state() == EffectModule::STOPPING) {
5609 effect->start();
5610 }
Eric Laurent39e94f82010-07-28 01:32:47 -07005611 // if the move request is not received from audio policy manager, the effect must be
5612 // re-registered with the new strategy and output
5613 if (dstChain == 0) {
5614 dstChain = effect->chain().promote();
5615 if (dstChain == 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00005616 ALOGW("moveEffectChain_l() cannot get chain from effect %p", effect.get());
Eric Laurent39e94f82010-07-28 01:32:47 -07005617 srcThread->addEffect_l(effect);
5618 return NO_INIT;
5619 }
5620 strategy = dstChain->strategy();
5621 }
5622 if (reRegister) {
5623 AudioSystem::unregisterEffect(effect->id());
5624 AudioSystem::registerEffect(&effect->desc(),
5625 dstOutput,
5626 strategy,
Eric Laurent59255e42011-07-27 19:49:51 -07005627 sessionId,
Eric Laurent39e94f82010-07-28 01:32:47 -07005628 effect->id());
5629 }
Eric Laurentde070132010-07-13 04:45:46 -07005630 effect = chain->getEffectFromId_l(0);
5631 }
5632
5633 return NO_ERROR;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005634}
5635
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005636
Mathias Agopian65ab4712010-07-14 17:59:35 -07005637// PlaybackThread::createEffect_l() must be called with AudioFlinger::mLock held
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005638sp<AudioFlinger::EffectHandle> AudioFlinger::ThreadBase::createEffect_l(
Mathias Agopian65ab4712010-07-14 17:59:35 -07005639 const sp<AudioFlinger::Client>& client,
5640 const sp<IEffectClient>& effectClient,
5641 int32_t priority,
5642 int sessionId,
5643 effect_descriptor_t *desc,
5644 int *enabled,
5645 status_t *status
5646 )
5647{
5648 sp<EffectModule> effect;
5649 sp<EffectHandle> handle;
5650 status_t lStatus;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005651 sp<EffectChain> chain;
Eric Laurentde070132010-07-13 04:45:46 -07005652 bool chainCreated = false;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005653 bool effectCreated = false;
5654 bool effectRegistered = false;
5655
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005656 lStatus = initCheck();
5657 if (lStatus != NO_ERROR) {
Steve Block5ff1dd52012-01-05 23:22:43 +00005658 ALOGW("createEffect_l() Audio driver not initialized.");
Mathias Agopian65ab4712010-07-14 17:59:35 -07005659 goto Exit;
5660 }
5661
5662 // Do not allow effects with session ID 0 on direct output or duplicating threads
5663 // TODO: add rule for hw accelerated effects on direct outputs with non PCM format
Dima Zavinfce7a472011-04-19 22:30:36 -07005664 if (sessionId == AUDIO_SESSION_OUTPUT_MIX && mType != MIXER) {
Steve Block5ff1dd52012-01-05 23:22:43 +00005665 ALOGW("createEffect_l() Cannot add auxiliary effect %s to session %d",
Eric Laurentde070132010-07-13 04:45:46 -07005666 desc->name, sessionId);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005667 lStatus = BAD_VALUE;
5668 goto Exit;
5669 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005670 // Only Pre processor effects are allowed on input threads and only on input threads
5671 if ((mType == RECORD &&
5672 (desc->flags & EFFECT_FLAG_TYPE_MASK) != EFFECT_FLAG_TYPE_PRE_PROC) ||
5673 (mType != RECORD &&
5674 (desc->flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC)) {
Steve Block5ff1dd52012-01-05 23:22:43 +00005675 ALOGW("createEffect_l() effect %s (flags %08x) created on wrong thread type %d",
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005676 desc->name, desc->flags, mType);
5677 lStatus = BAD_VALUE;
5678 goto Exit;
5679 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07005680
Steve Block3856b092011-10-20 11:56:00 +01005681 ALOGV("createEffect_l() thread %p effect %s on session %d", this, desc->name, sessionId);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005682
5683 { // scope for mLock
5684 Mutex::Autolock _l(mLock);
5685
5686 // check for existing effect chain with the requested audio session
5687 chain = getEffectChain_l(sessionId);
5688 if (chain == 0) {
5689 // create a new chain for this session
Steve Block3856b092011-10-20 11:56:00 +01005690 ALOGV("createEffect_l() new effect chain for session %d", sessionId);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005691 chain = new EffectChain(this, sessionId);
5692 addEffectChain_l(chain);
Eric Laurentde070132010-07-13 04:45:46 -07005693 chain->setStrategy(getStrategyForSession_l(sessionId));
5694 chainCreated = true;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005695 } else {
Eric Laurentcab11242010-07-15 12:50:15 -07005696 effect = chain->getEffectFromDesc_l(desc);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005697 }
5698
Glenn Kasten7fc9a6f2012-01-10 10:46:34 -08005699 ALOGV("createEffect_l() got effect %p on chain %p", effect.get(), chain.get());
Mathias Agopian65ab4712010-07-14 17:59:35 -07005700
5701 if (effect == 0) {
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005702 int id = mAudioFlinger->nextUniqueId();
Mathias Agopian65ab4712010-07-14 17:59:35 -07005703 // Check CPU and memory usage
Eric Laurentde070132010-07-13 04:45:46 -07005704 lStatus = AudioSystem::registerEffect(desc, mId, chain->strategy(), sessionId, id);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005705 if (lStatus != NO_ERROR) {
5706 goto Exit;
5707 }
5708 effectRegistered = true;
5709 // create a new effect module if none present in the chain
Eric Laurentde070132010-07-13 04:45:46 -07005710 effect = new EffectModule(this, chain, desc, id, sessionId);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005711 lStatus = effect->status();
5712 if (lStatus != NO_ERROR) {
5713 goto Exit;
5714 }
Eric Laurentcab11242010-07-15 12:50:15 -07005715 lStatus = chain->addEffect_l(effect);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005716 if (lStatus != NO_ERROR) {
5717 goto Exit;
5718 }
5719 effectCreated = true;
5720
5721 effect->setDevice(mDevice);
5722 effect->setMode(mAudioFlinger->getMode());
5723 }
5724 // create effect handle and connect it to effect module
5725 handle = new EffectHandle(effect, client, effectClient, priority);
5726 lStatus = effect->addHandle(handle);
Glenn Kastena0d68332012-01-27 16:47:15 -08005727 if (enabled != NULL) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07005728 *enabled = (int)effect->isEnabled();
5729 }
5730 }
5731
5732Exit:
5733 if (lStatus != NO_ERROR && lStatus != ALREADY_EXISTS) {
Eric Laurentde070132010-07-13 04:45:46 -07005734 Mutex::Autolock _l(mLock);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005735 if (effectCreated) {
Eric Laurentde070132010-07-13 04:45:46 -07005736 chain->removeEffect_l(effect);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005737 }
5738 if (effectRegistered) {
Eric Laurentde070132010-07-13 04:45:46 -07005739 AudioSystem::unregisterEffect(effect->id());
5740 }
5741 if (chainCreated) {
5742 removeEffectChain_l(chain);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005743 }
5744 handle.clear();
5745 }
5746
5747 if(status) {
5748 *status = lStatus;
5749 }
5750 return handle;
5751}
5752
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005753sp<AudioFlinger::EffectModule> AudioFlinger::ThreadBase::getEffect_l(int sessionId, int effectId)
5754{
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005755 sp<EffectChain> chain = getEffectChain_l(sessionId);
Glenn Kasten090f0192012-01-30 13:00:02 -08005756 return chain != 0 ? chain->getEffectFromId_l(effectId) : 0;
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005757}
5758
Eric Laurentde070132010-07-13 04:45:46 -07005759// PlaybackThread::addEffect_l() must be called with AudioFlinger::mLock and
5760// PlaybackThread::mLock held
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005761status_t AudioFlinger::ThreadBase::addEffect_l(const sp<EffectModule>& effect)
Eric Laurentde070132010-07-13 04:45:46 -07005762{
5763 // check for existing effect chain with the requested audio session
5764 int sessionId = effect->sessionId();
5765 sp<EffectChain> chain = getEffectChain_l(sessionId);
5766 bool chainCreated = false;
5767
5768 if (chain == 0) {
5769 // create a new chain for this session
Steve Block3856b092011-10-20 11:56:00 +01005770 ALOGV("addEffect_l() new effect chain for session %d", sessionId);
Eric Laurentde070132010-07-13 04:45:46 -07005771 chain = new EffectChain(this, sessionId);
5772 addEffectChain_l(chain);
5773 chain->setStrategy(getStrategyForSession_l(sessionId));
5774 chainCreated = true;
5775 }
Steve Block3856b092011-10-20 11:56:00 +01005776 ALOGV("addEffect_l() %p chain %p effect %p", this, chain.get(), effect.get());
Eric Laurentde070132010-07-13 04:45:46 -07005777
5778 if (chain->getEffectFromId_l(effect->id()) != 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00005779 ALOGW("addEffect_l() %p effect %s already present in chain %p",
Eric Laurentde070132010-07-13 04:45:46 -07005780 this, effect->desc().name, chain.get());
5781 return BAD_VALUE;
5782 }
5783
5784 status_t status = chain->addEffect_l(effect);
5785 if (status != NO_ERROR) {
5786 if (chainCreated) {
5787 removeEffectChain_l(chain);
5788 }
5789 return status;
5790 }
5791
5792 effect->setDevice(mDevice);
5793 effect->setMode(mAudioFlinger->getMode());
5794 return NO_ERROR;
5795}
5796
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005797void AudioFlinger::ThreadBase::removeEffect_l(const sp<EffectModule>& effect) {
Eric Laurentde070132010-07-13 04:45:46 -07005798
Steve Block3856b092011-10-20 11:56:00 +01005799 ALOGV("removeEffect_l() %p effect %p", this, effect.get());
Mathias Agopian65ab4712010-07-14 17:59:35 -07005800 effect_descriptor_t desc = effect->desc();
Eric Laurentde070132010-07-13 04:45:46 -07005801 if ((desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
5802 detachAuxEffect_l(effect->id());
5803 }
5804
5805 sp<EffectChain> chain = effect->chain().promote();
5806 if (chain != 0) {
5807 // remove effect chain if removing last effect
5808 if (chain->removeEffect_l(effect) == 0) {
5809 removeEffectChain_l(chain);
5810 }
5811 } else {
Steve Block5ff1dd52012-01-05 23:22:43 +00005812 ALOGW("removeEffect_l() %p cannot promote chain for effect %p", this, effect.get());
Eric Laurentde070132010-07-13 04:45:46 -07005813 }
5814}
5815
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005816void AudioFlinger::ThreadBase::lockEffectChains_l(
5817 Vector<sp <AudioFlinger::EffectChain> >& effectChains)
5818{
5819 effectChains = mEffectChains;
5820 for (size_t i = 0; i < mEffectChains.size(); i++) {
5821 mEffectChains[i]->lock();
5822 }
5823}
5824
5825void AudioFlinger::ThreadBase::unlockEffectChains(
5826 Vector<sp <AudioFlinger::EffectChain> >& effectChains)
5827{
5828 for (size_t i = 0; i < effectChains.size(); i++) {
5829 effectChains[i]->unlock();
5830 }
5831}
5832
5833sp<AudioFlinger::EffectChain> AudioFlinger::ThreadBase::getEffectChain(int sessionId)
5834{
5835 Mutex::Autolock _l(mLock);
5836 return getEffectChain_l(sessionId);
5837}
5838
5839sp<AudioFlinger::EffectChain> AudioFlinger::ThreadBase::getEffectChain_l(int sessionId)
5840{
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005841 size_t size = mEffectChains.size();
5842 for (size_t i = 0; i < size; i++) {
5843 if (mEffectChains[i]->sessionId() == sessionId) {
Glenn Kasten090f0192012-01-30 13:00:02 -08005844 return mEffectChains[i];
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005845 }
5846 }
Glenn Kasten090f0192012-01-30 13:00:02 -08005847 return 0;
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005848}
5849
Glenn Kastenf78aee72012-01-04 11:00:47 -08005850void AudioFlinger::ThreadBase::setMode(audio_mode_t mode)
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005851{
5852 Mutex::Autolock _l(mLock);
5853 size_t size = mEffectChains.size();
5854 for (size_t i = 0; i < size; i++) {
5855 mEffectChains[i]->setMode_l(mode);
5856 }
5857}
5858
5859void AudioFlinger::ThreadBase::disconnectEffect(const sp<EffectModule>& effect,
Marco Nelissen3a34bef2011-08-02 13:33:41 -07005860 const wp<EffectHandle>& handle,
Glenn Kasten58123c32012-02-03 10:32:24 -08005861 bool unpinIfLast) {
Eric Laurent59255e42011-07-27 19:49:51 -07005862
Mathias Agopian65ab4712010-07-14 17:59:35 -07005863 Mutex::Autolock _l(mLock);
Steve Block3856b092011-10-20 11:56:00 +01005864 ALOGV("disconnectEffect() %p effect %p", this, effect.get());
Mathias Agopian65ab4712010-07-14 17:59:35 -07005865 // delete the effect module if removing last handle on it
5866 if (effect->removeHandle(handle) == 0) {
Glenn Kasten58123c32012-02-03 10:32:24 -08005867 if (!effect->isPinned() || unpinIfLast) {
Marco Nelissen3a34bef2011-08-02 13:33:41 -07005868 removeEffect_l(effect);
5869 AudioSystem::unregisterEffect(effect->id());
5870 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07005871 }
5872}
5873
5874status_t AudioFlinger::PlaybackThread::addEffectChain_l(const sp<EffectChain>& chain)
5875{
5876 int session = chain->sessionId();
5877 int16_t *buffer = mMixBuffer;
5878 bool ownsBuffer = false;
5879
Steve Block3856b092011-10-20 11:56:00 +01005880 ALOGV("addEffectChain_l() %p on thread %p for session %d", chain.get(), this, session);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005881 if (session > 0) {
5882 // Only one effect chain can be present in direct output thread and it uses
5883 // the mix buffer as input
5884 if (mType != DIRECT) {
5885 size_t numSamples = mFrameCount * mChannelCount;
5886 buffer = new int16_t[numSamples];
5887 memset(buffer, 0, numSamples * sizeof(int16_t));
Steve Block3856b092011-10-20 11:56:00 +01005888 ALOGV("addEffectChain_l() creating new input buffer %p session %d", buffer, session);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005889 ownsBuffer = true;
5890 }
5891
5892 // Attach all tracks with same session ID to this chain.
5893 for (size_t i = 0; i < mTracks.size(); ++i) {
5894 sp<Track> track = mTracks[i];
5895 if (session == track->sessionId()) {
Steve Block3856b092011-10-20 11:56:00 +01005896 ALOGV("addEffectChain_l() track->setMainBuffer track %p buffer %p", track.get(), buffer);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005897 track->setMainBuffer(buffer);
Eric Laurentb469b942011-05-09 12:09:06 -07005898 chain->incTrackCnt();
Mathias Agopian65ab4712010-07-14 17:59:35 -07005899 }
5900 }
5901
5902 // indicate all active tracks in the chain
5903 for (size_t i = 0 ; i < mActiveTracks.size() ; ++i) {
5904 sp<Track> track = mActiveTracks[i].promote();
5905 if (track == 0) continue;
5906 if (session == track->sessionId()) {
Steve Block3856b092011-10-20 11:56:00 +01005907 ALOGV("addEffectChain_l() activating track %p on session %d", track.get(), session);
Eric Laurentb469b942011-05-09 12:09:06 -07005908 chain->incActiveTrackCnt();
Mathias Agopian65ab4712010-07-14 17:59:35 -07005909 }
5910 }
5911 }
5912
5913 chain->setInBuffer(buffer, ownsBuffer);
5914 chain->setOutBuffer(mMixBuffer);
Dima Zavinfce7a472011-04-19 22:30:36 -07005915 // Effect chain for session AUDIO_SESSION_OUTPUT_STAGE is inserted at end of effect
Eric Laurentde070132010-07-13 04:45:46 -07005916 // chains list in order to be processed last as it contains output stage effects
Dima Zavinfce7a472011-04-19 22:30:36 -07005917 // Effect chain for session AUDIO_SESSION_OUTPUT_MIX is inserted before
5918 // session AUDIO_SESSION_OUTPUT_STAGE to be processed
Mathias Agopian65ab4712010-07-14 17:59:35 -07005919 // after track specific effects and before output stage
Dima Zavinfce7a472011-04-19 22:30:36 -07005920 // It is therefore mandatory that AUDIO_SESSION_OUTPUT_MIX == 0 and
5921 // that AUDIO_SESSION_OUTPUT_STAGE < AUDIO_SESSION_OUTPUT_MIX
Eric Laurentde070132010-07-13 04:45:46 -07005922 // Effect chain for other sessions are inserted at beginning of effect
5923 // chains list to be processed before output mix effects. Relative order between other
5924 // sessions is not important
Mathias Agopian65ab4712010-07-14 17:59:35 -07005925 size_t size = mEffectChains.size();
5926 size_t i = 0;
5927 for (i = 0; i < size; i++) {
5928 if (mEffectChains[i]->sessionId() < session) break;
5929 }
5930 mEffectChains.insertAt(chain, i);
Eric Laurent59255e42011-07-27 19:49:51 -07005931 checkSuspendOnAddEffectChain_l(chain);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005932
5933 return NO_ERROR;
5934}
5935
5936size_t AudioFlinger::PlaybackThread::removeEffectChain_l(const sp<EffectChain>& chain)
5937{
5938 int session = chain->sessionId();
5939
Steve Block3856b092011-10-20 11:56:00 +01005940 ALOGV("removeEffectChain_l() %p from thread %p for session %d", chain.get(), this, session);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005941
5942 for (size_t i = 0; i < mEffectChains.size(); i++) {
5943 if (chain == mEffectChains[i]) {
5944 mEffectChains.removeAt(i);
Eric Laurentb469b942011-05-09 12:09:06 -07005945 // detach all active tracks from the chain
5946 for (size_t i = 0 ; i < mActiveTracks.size() ; ++i) {
5947 sp<Track> track = mActiveTracks[i].promote();
5948 if (track == 0) continue;
5949 if (session == track->sessionId()) {
Steve Block3856b092011-10-20 11:56:00 +01005950 ALOGV("removeEffectChain_l(): stopping track on chain %p for session Id: %d",
Eric Laurentb469b942011-05-09 12:09:06 -07005951 chain.get(), session);
5952 chain->decActiveTrackCnt();
5953 }
5954 }
5955
Mathias Agopian65ab4712010-07-14 17:59:35 -07005956 // detach all tracks with same session ID from this chain
5957 for (size_t i = 0; i < mTracks.size(); ++i) {
5958 sp<Track> track = mTracks[i];
5959 if (session == track->sessionId()) {
5960 track->setMainBuffer(mMixBuffer);
Eric Laurentb469b942011-05-09 12:09:06 -07005961 chain->decTrackCnt();
Mathias Agopian65ab4712010-07-14 17:59:35 -07005962 }
5963 }
Eric Laurentde070132010-07-13 04:45:46 -07005964 break;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005965 }
5966 }
5967 return mEffectChains.size();
5968}
5969
Eric Laurentde070132010-07-13 04:45:46 -07005970status_t AudioFlinger::PlaybackThread::attachAuxEffect(
5971 const sp<AudioFlinger::PlaybackThread::Track> track, int EffectId)
Mathias Agopian65ab4712010-07-14 17:59:35 -07005972{
5973 Mutex::Autolock _l(mLock);
5974 return attachAuxEffect_l(track, EffectId);
5975}
5976
Eric Laurentde070132010-07-13 04:45:46 -07005977status_t AudioFlinger::PlaybackThread::attachAuxEffect_l(
5978 const sp<AudioFlinger::PlaybackThread::Track> track, int EffectId)
Mathias Agopian65ab4712010-07-14 17:59:35 -07005979{
5980 status_t status = NO_ERROR;
5981
5982 if (EffectId == 0) {
5983 track->setAuxBuffer(0, NULL);
5984 } else {
Dima Zavinfce7a472011-04-19 22:30:36 -07005985 // Auxiliary effects are always in audio session AUDIO_SESSION_OUTPUT_MIX
5986 sp<EffectModule> effect = getEffect_l(AUDIO_SESSION_OUTPUT_MIX, EffectId);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005987 if (effect != 0) {
5988 if ((effect->desc().flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
5989 track->setAuxBuffer(EffectId, (int32_t *)effect->inBuffer());
5990 } else {
5991 status = INVALID_OPERATION;
5992 }
5993 } else {
5994 status = BAD_VALUE;
5995 }
5996 }
5997 return status;
5998}
5999
6000void AudioFlinger::PlaybackThread::detachAuxEffect_l(int effectId)
6001{
6002 for (size_t i = 0; i < mTracks.size(); ++i) {
6003 sp<Track> track = mTracks[i];
6004 if (track->auxEffectId() == effectId) {
6005 attachAuxEffect_l(track, 0);
6006 }
6007 }
6008}
6009
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006010status_t AudioFlinger::RecordThread::addEffectChain_l(const sp<EffectChain>& chain)
6011{
6012 // only one chain per input thread
6013 if (mEffectChains.size() != 0) {
6014 return INVALID_OPERATION;
6015 }
Steve Block3856b092011-10-20 11:56:00 +01006016 ALOGV("addEffectChain_l() %p on thread %p", chain.get(), this);
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006017
6018 chain->setInBuffer(NULL);
6019 chain->setOutBuffer(NULL);
6020
Eric Laurent59255e42011-07-27 19:49:51 -07006021 checkSuspendOnAddEffectChain_l(chain);
6022
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006023 mEffectChains.add(chain);
6024
6025 return NO_ERROR;
6026}
6027
6028size_t AudioFlinger::RecordThread::removeEffectChain_l(const sp<EffectChain>& chain)
6029{
Steve Block3856b092011-10-20 11:56:00 +01006030 ALOGV("removeEffectChain_l() %p from thread %p", chain.get(), this);
Steve Block5ff1dd52012-01-05 23:22:43 +00006031 ALOGW_IF(mEffectChains.size() != 1,
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006032 "removeEffectChain_l() %p invalid chain size %d on thread %p",
6033 chain.get(), mEffectChains.size(), this);
6034 if (mEffectChains.size() == 1) {
6035 mEffectChains.removeAt(0);
6036 }
6037 return 0;
6038}
6039
Mathias Agopian65ab4712010-07-14 17:59:35 -07006040// ----------------------------------------------------------------------------
6041// EffectModule implementation
6042// ----------------------------------------------------------------------------
6043
6044#undef LOG_TAG
6045#define LOG_TAG "AudioFlinger::EffectModule"
6046
6047AudioFlinger::EffectModule::EffectModule(const wp<ThreadBase>& wThread,
6048 const wp<AudioFlinger::EffectChain>& chain,
6049 effect_descriptor_t *desc,
6050 int id,
6051 int sessionId)
6052 : mThread(wThread), mChain(chain), mId(id), mSessionId(sessionId), mEffectInterface(NULL),
Eric Laurent59255e42011-07-27 19:49:51 -07006053 mStatus(NO_INIT), mState(IDLE), mSuspended(false)
Mathias Agopian65ab4712010-07-14 17:59:35 -07006054{
Steve Block3856b092011-10-20 11:56:00 +01006055 ALOGV("Constructor %p", this);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006056 int lStatus;
6057 sp<ThreadBase> thread = mThread.promote();
6058 if (thread == 0) {
6059 return;
6060 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07006061
6062 memcpy(&mDescriptor, desc, sizeof(effect_descriptor_t));
6063
6064 // create effect engine from effect factory
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006065 mStatus = EffectCreate(&desc->uuid, sessionId, thread->id(), &mEffectInterface);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006066
6067 if (mStatus != NO_ERROR) {
6068 return;
6069 }
6070 lStatus = init();
6071 if (lStatus < 0) {
6072 mStatus = lStatus;
6073 goto Error;
6074 }
6075
Marco Nelissen3a34bef2011-08-02 13:33:41 -07006076 if (mSessionId > AUDIO_SESSION_OUTPUT_MIX) {
6077 mPinned = true;
6078 }
Steve Block3856b092011-10-20 11:56:00 +01006079 ALOGV("Constructor success name %s, Interface %p", mDescriptor.name, mEffectInterface);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006080 return;
6081Error:
6082 EffectRelease(mEffectInterface);
6083 mEffectInterface = NULL;
Steve Block3856b092011-10-20 11:56:00 +01006084 ALOGV("Constructor Error %d", mStatus);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006085}
6086
6087AudioFlinger::EffectModule::~EffectModule()
6088{
Steve Block3856b092011-10-20 11:56:00 +01006089 ALOGV("Destructor %p", this);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006090 if (mEffectInterface != NULL) {
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006091 if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC ||
6092 (mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_POST_PROC) {
6093 sp<ThreadBase> thread = mThread.promote();
6094 if (thread != 0) {
Eric Laurentb8ba0a92011-08-07 16:32:26 -07006095 audio_stream_t *stream = thread->stream();
6096 if (stream != NULL) {
6097 stream->remove_audio_effect(stream, mEffectInterface);
6098 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006099 }
6100 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07006101 // release effect engine
6102 EffectRelease(mEffectInterface);
6103 }
6104}
6105
Glenn Kasten435dbe62012-01-30 10:15:48 -08006106status_t AudioFlinger::EffectModule::addHandle(const sp<EffectHandle>& handle)
Mathias Agopian65ab4712010-07-14 17:59:35 -07006107{
6108 status_t status;
6109
6110 Mutex::Autolock _l(mLock);
6111 // First handle in mHandles has highest priority and controls the effect module
6112 int priority = handle->priority();
6113 size_t size = mHandles.size();
6114 sp<EffectHandle> h;
6115 size_t i;
6116 for (i = 0; i < size; i++) {
6117 h = mHandles[i].promote();
6118 if (h == 0) continue;
6119 if (h->priority() <= priority) break;
6120 }
6121 // if inserted in first place, move effect control from previous owner to this handle
6122 if (i == 0) {
Eric Laurent59255e42011-07-27 19:49:51 -07006123 bool enabled = false;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006124 if (h != 0) {
Eric Laurent59255e42011-07-27 19:49:51 -07006125 enabled = h->enabled();
6126 h->setControl(false/*hasControl*/, true /*signal*/, enabled /*enabled*/);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006127 }
Eric Laurent59255e42011-07-27 19:49:51 -07006128 handle->setControl(true /*hasControl*/, false /*signal*/, enabled /*enabled*/);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006129 status = NO_ERROR;
6130 } else {
6131 status = ALREADY_EXISTS;
6132 }
Steve Block3856b092011-10-20 11:56:00 +01006133 ALOGV("addHandle() %p added handle %p in position %d", this, handle.get(), i);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006134 mHandles.insertAt(handle, i);
6135 return status;
6136}
6137
6138size_t AudioFlinger::EffectModule::removeHandle(const wp<EffectHandle>& handle)
6139{
6140 Mutex::Autolock _l(mLock);
6141 size_t size = mHandles.size();
6142 size_t i;
6143 for (i = 0; i < size; i++) {
6144 if (mHandles[i] == handle) break;
6145 }
6146 if (i == size) {
6147 return size;
6148 }
Steve Block3856b092011-10-20 11:56:00 +01006149 ALOGV("removeHandle() %p removed handle %p in position %d", this, handle.unsafe_get(), i);
Eric Laurent59255e42011-07-27 19:49:51 -07006150
6151 bool enabled = false;
6152 EffectHandle *hdl = handle.unsafe_get();
Glenn Kastena0d68332012-01-27 16:47:15 -08006153 if (hdl != NULL) {
Steve Block3856b092011-10-20 11:56:00 +01006154 ALOGV("removeHandle() unsafe_get OK");
Eric Laurent59255e42011-07-27 19:49:51 -07006155 enabled = hdl->enabled();
6156 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07006157 mHandles.removeAt(i);
6158 size = mHandles.size();
6159 // if removed from first place, move effect control from this handle to next in line
6160 if (i == 0 && size != 0) {
6161 sp<EffectHandle> h = mHandles[0].promote();
6162 if (h != 0) {
Eric Laurent59255e42011-07-27 19:49:51 -07006163 h->setControl(true /*hasControl*/, true /*signal*/ , enabled /*enabled*/);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006164 }
6165 }
6166
Eric Laurentec437d82011-07-26 20:54:46 -07006167 // Prevent calls to process() and other functions on effect interface from now on.
6168 // The effect engine will be released by the destructor when the last strong reference on
6169 // this object is released which can happen after next process is called.
Marco Nelissen3a34bef2011-08-02 13:33:41 -07006170 if (size == 0 && !mPinned) {
Eric Laurentec437d82011-07-26 20:54:46 -07006171 mState = DESTROYED;
Eric Laurentdac69112010-09-28 14:09:57 -07006172 }
6173
Mathias Agopian65ab4712010-07-14 17:59:35 -07006174 return size;
6175}
6176
Eric Laurent59255e42011-07-27 19:49:51 -07006177sp<AudioFlinger::EffectHandle> AudioFlinger::EffectModule::controlHandle()
6178{
6179 Mutex::Autolock _l(mLock);
Glenn Kasten090f0192012-01-30 13:00:02 -08006180 return mHandles.size() != 0 ? mHandles[0].promote() : 0;
Eric Laurent59255e42011-07-27 19:49:51 -07006181}
6182
Glenn Kasten58123c32012-02-03 10:32:24 -08006183void AudioFlinger::EffectModule::disconnect(const wp<EffectHandle>& handle, bool unpinIfLast)
Mathias Agopian65ab4712010-07-14 17:59:35 -07006184{
Glenn Kasten90bebef2012-01-27 15:24:38 -08006185 ALOGV("disconnect() %p handle %p", this, handle.unsafe_get());
Mathias Agopian65ab4712010-07-14 17:59:35 -07006186 // keep a strong reference on this EffectModule to avoid calling the
6187 // destructor before we exit
6188 sp<EffectModule> keep(this);
6189 {
6190 sp<ThreadBase> thread = mThread.promote();
6191 if (thread != 0) {
Glenn Kasten58123c32012-02-03 10:32:24 -08006192 thread->disconnectEffect(keep, handle, unpinIfLast);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006193 }
6194 }
6195}
6196
6197void AudioFlinger::EffectModule::updateState() {
6198 Mutex::Autolock _l(mLock);
6199
6200 switch (mState) {
6201 case RESTART:
6202 reset_l();
6203 // FALL THROUGH
6204
6205 case STARTING:
6206 // clear auxiliary effect input buffer for next accumulation
6207 if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
6208 memset(mConfig.inputCfg.buffer.raw,
6209 0,
6210 mConfig.inputCfg.buffer.frameCount*sizeof(int32_t));
6211 }
6212 start_l();
6213 mState = ACTIVE;
6214 break;
6215 case STOPPING:
6216 stop_l();
6217 mDisableWaitCnt = mMaxDisableWaitCnt;
6218 mState = STOPPED;
6219 break;
6220 case STOPPED:
6221 // mDisableWaitCnt is forced to 1 by process() when the engine indicates the end of the
6222 // turn off sequence.
6223 if (--mDisableWaitCnt == 0) {
6224 reset_l();
6225 mState = IDLE;
6226 }
6227 break;
Eric Laurentec437d82011-07-26 20:54:46 -07006228 default: //IDLE , ACTIVE, DESTROYED
Mathias Agopian65ab4712010-07-14 17:59:35 -07006229 break;
6230 }
6231}
6232
6233void AudioFlinger::EffectModule::process()
6234{
6235 Mutex::Autolock _l(mLock);
6236
Eric Laurentec437d82011-07-26 20:54:46 -07006237 if (mState == DESTROYED || mEffectInterface == NULL ||
Mathias Agopian65ab4712010-07-14 17:59:35 -07006238 mConfig.inputCfg.buffer.raw == NULL ||
6239 mConfig.outputCfg.buffer.raw == NULL) {
6240 return;
6241 }
6242
Eric Laurent8f45bd72010-08-31 13:50:07 -07006243 if (isProcessEnabled()) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07006244 // do 32 bit to 16 bit conversion for auxiliary effect input buffer
6245 if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
Glenn Kasten3b21c502011-12-15 09:52:39 -08006246 ditherAndClamp(mConfig.inputCfg.buffer.s32,
Mathias Agopian65ab4712010-07-14 17:59:35 -07006247 mConfig.inputCfg.buffer.s32,
Eric Laurentde070132010-07-13 04:45:46 -07006248 mConfig.inputCfg.buffer.frameCount/2);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006249 }
6250
6251 // do the actual processing in the effect engine
6252 int ret = (*mEffectInterface)->process(mEffectInterface,
6253 &mConfig.inputCfg.buffer,
6254 &mConfig.outputCfg.buffer);
6255
6256 // force transition to IDLE state when engine is ready
6257 if (mState == STOPPED && ret == -ENODATA) {
6258 mDisableWaitCnt = 1;
6259 }
6260
6261 // clear auxiliary effect input buffer for next accumulation
6262 if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
Eric Laurent73337482011-01-19 18:36:13 -08006263 memset(mConfig.inputCfg.buffer.raw, 0,
6264 mConfig.inputCfg.buffer.frameCount*sizeof(int32_t));
Mathias Agopian65ab4712010-07-14 17:59:35 -07006265 }
6266 } else if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_INSERT &&
Eric Laurent73337482011-01-19 18:36:13 -08006267 mConfig.inputCfg.buffer.raw != mConfig.outputCfg.buffer.raw) {
6268 // If an insert effect is idle and input buffer is different from output buffer,
6269 // accumulate input onto output
Mathias Agopian65ab4712010-07-14 17:59:35 -07006270 sp<EffectChain> chain = mChain.promote();
Eric Laurentb469b942011-05-09 12:09:06 -07006271 if (chain != 0 && chain->activeTrackCnt() != 0) {
Eric Laurent73337482011-01-19 18:36:13 -08006272 size_t frameCnt = mConfig.inputCfg.buffer.frameCount * 2; //always stereo here
6273 int16_t *in = mConfig.inputCfg.buffer.s16;
6274 int16_t *out = mConfig.outputCfg.buffer.s16;
6275 for (size_t i = 0; i < frameCnt; i++) {
6276 out[i] = clamp16((int32_t)out[i] + (int32_t)in[i]);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006277 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07006278 }
6279 }
6280}
6281
6282void AudioFlinger::EffectModule::reset_l()
6283{
6284 if (mEffectInterface == NULL) {
6285 return;
6286 }
6287 (*mEffectInterface)->command(mEffectInterface, EFFECT_CMD_RESET, 0, NULL, 0, NULL);
6288}
6289
6290status_t AudioFlinger::EffectModule::configure()
6291{
6292 uint32_t channels;
6293 if (mEffectInterface == NULL) {
6294 return NO_INIT;
6295 }
6296
6297 sp<ThreadBase> thread = mThread.promote();
6298 if (thread == 0) {
6299 return DEAD_OBJECT;
6300 }
6301
6302 // TODO: handle configuration of effects replacing track process
6303 if (thread->channelCount() == 1) {
Eric Laurente1315cf2011-05-17 19:16:02 -07006304 channels = AUDIO_CHANNEL_OUT_MONO;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006305 } else {
Eric Laurente1315cf2011-05-17 19:16:02 -07006306 channels = AUDIO_CHANNEL_OUT_STEREO;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006307 }
6308
6309 if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
Eric Laurente1315cf2011-05-17 19:16:02 -07006310 mConfig.inputCfg.channels = AUDIO_CHANNEL_OUT_MONO;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006311 } else {
6312 mConfig.inputCfg.channels = channels;
6313 }
6314 mConfig.outputCfg.channels = channels;
Eric Laurente1315cf2011-05-17 19:16:02 -07006315 mConfig.inputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
6316 mConfig.outputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006317 mConfig.inputCfg.samplingRate = thread->sampleRate();
6318 mConfig.outputCfg.samplingRate = mConfig.inputCfg.samplingRate;
6319 mConfig.inputCfg.bufferProvider.cookie = NULL;
6320 mConfig.inputCfg.bufferProvider.getBuffer = NULL;
6321 mConfig.inputCfg.bufferProvider.releaseBuffer = NULL;
6322 mConfig.outputCfg.bufferProvider.cookie = NULL;
6323 mConfig.outputCfg.bufferProvider.getBuffer = NULL;
6324 mConfig.outputCfg.bufferProvider.releaseBuffer = NULL;
6325 mConfig.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ;
6326 // Insert effect:
Dima Zavinfce7a472011-04-19 22:30:36 -07006327 // - in session AUDIO_SESSION_OUTPUT_MIX or AUDIO_SESSION_OUTPUT_STAGE,
Eric Laurentde070132010-07-13 04:45:46 -07006328 // always overwrites output buffer: input buffer == output buffer
Mathias Agopian65ab4712010-07-14 17:59:35 -07006329 // - in other sessions:
6330 // last effect in the chain accumulates in output buffer: input buffer != output buffer
6331 // other effect: overwrites output buffer: input buffer == output buffer
6332 // Auxiliary effect:
6333 // accumulates in output buffer: input buffer != output buffer
6334 // Therefore: accumulate <=> input buffer != output buffer
6335 if (mConfig.inputCfg.buffer.raw != mConfig.outputCfg.buffer.raw) {
6336 mConfig.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_ACCUMULATE;
6337 } else {
6338 mConfig.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_WRITE;
6339 }
6340 mConfig.inputCfg.mask = EFFECT_CONFIG_ALL;
6341 mConfig.outputCfg.mask = EFFECT_CONFIG_ALL;
6342 mConfig.inputCfg.buffer.frameCount = thread->frameCount();
6343 mConfig.outputCfg.buffer.frameCount = mConfig.inputCfg.buffer.frameCount;
6344
Steve Block3856b092011-10-20 11:56:00 +01006345 ALOGV("configure() %p thread %p buffer %p framecount %d",
Eric Laurentde070132010-07-13 04:45:46 -07006346 this, thread.get(), mConfig.inputCfg.buffer.raw, mConfig.inputCfg.buffer.frameCount);
6347
Mathias Agopian65ab4712010-07-14 17:59:35 -07006348 status_t cmdStatus;
Eric Laurent25f43952010-07-28 05:40:18 -07006349 uint32_t size = sizeof(int);
6350 status_t status = (*mEffectInterface)->command(mEffectInterface,
Eric Laurent3d5188b2011-12-16 15:30:36 -08006351 EFFECT_CMD_SET_CONFIG,
Eric Laurent25f43952010-07-28 05:40:18 -07006352 sizeof(effect_config_t),
6353 &mConfig,
6354 &size,
6355 &cmdStatus);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006356 if (status == 0) {
6357 status = cmdStatus;
6358 }
6359
6360 mMaxDisableWaitCnt = (MAX_DISABLE_TIME_MS * mConfig.outputCfg.samplingRate) /
6361 (1000 * mConfig.outputCfg.buffer.frameCount);
6362
6363 return status;
6364}
6365
6366status_t AudioFlinger::EffectModule::init()
6367{
6368 Mutex::Autolock _l(mLock);
6369 if (mEffectInterface == NULL) {
6370 return NO_INIT;
6371 }
6372 status_t cmdStatus;
Eric Laurent25f43952010-07-28 05:40:18 -07006373 uint32_t size = sizeof(status_t);
6374 status_t status = (*mEffectInterface)->command(mEffectInterface,
6375 EFFECT_CMD_INIT,
6376 0,
6377 NULL,
6378 &size,
6379 &cmdStatus);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006380 if (status == 0) {
6381 status = cmdStatus;
6382 }
6383 return status;
6384}
6385
Eric Laurentec35a142011-10-05 17:42:25 -07006386status_t AudioFlinger::EffectModule::start()
6387{
6388 Mutex::Autolock _l(mLock);
6389 return start_l();
6390}
6391
Mathias Agopian65ab4712010-07-14 17:59:35 -07006392status_t AudioFlinger::EffectModule::start_l()
6393{
6394 if (mEffectInterface == NULL) {
6395 return NO_INIT;
6396 }
6397 status_t cmdStatus;
Eric Laurent25f43952010-07-28 05:40:18 -07006398 uint32_t size = sizeof(status_t);
6399 status_t status = (*mEffectInterface)->command(mEffectInterface,
6400 EFFECT_CMD_ENABLE,
6401 0,
6402 NULL,
6403 &size,
6404 &cmdStatus);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006405 if (status == 0) {
6406 status = cmdStatus;
6407 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006408 if (status == 0 &&
6409 ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC ||
6410 (mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_POST_PROC)) {
6411 sp<ThreadBase> thread = mThread.promote();
6412 if (thread != 0) {
Eric Laurentb8ba0a92011-08-07 16:32:26 -07006413 audio_stream_t *stream = thread->stream();
6414 if (stream != NULL) {
6415 stream->add_audio_effect(stream, mEffectInterface);
6416 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006417 }
6418 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07006419 return status;
6420}
6421
Eric Laurentec437d82011-07-26 20:54:46 -07006422status_t AudioFlinger::EffectModule::stop()
6423{
6424 Mutex::Autolock _l(mLock);
6425 return stop_l();
6426}
6427
Mathias Agopian65ab4712010-07-14 17:59:35 -07006428status_t AudioFlinger::EffectModule::stop_l()
6429{
6430 if (mEffectInterface == NULL) {
6431 return NO_INIT;
6432 }
6433 status_t cmdStatus;
Eric Laurent25f43952010-07-28 05:40:18 -07006434 uint32_t size = sizeof(status_t);
6435 status_t status = (*mEffectInterface)->command(mEffectInterface,
6436 EFFECT_CMD_DISABLE,
6437 0,
6438 NULL,
6439 &size,
6440 &cmdStatus);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006441 if (status == 0) {
6442 status = cmdStatus;
6443 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006444 if (status == 0 &&
6445 ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC ||
6446 (mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_POST_PROC)) {
6447 sp<ThreadBase> thread = mThread.promote();
6448 if (thread != 0) {
Eric Laurentb8ba0a92011-08-07 16:32:26 -07006449 audio_stream_t *stream = thread->stream();
6450 if (stream != NULL) {
6451 stream->remove_audio_effect(stream, mEffectInterface);
6452 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006453 }
6454 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07006455 return status;
6456}
6457
Eric Laurent25f43952010-07-28 05:40:18 -07006458status_t AudioFlinger::EffectModule::command(uint32_t cmdCode,
6459 uint32_t cmdSize,
6460 void *pCmdData,
6461 uint32_t *replySize,
6462 void *pReplyData)
Mathias Agopian65ab4712010-07-14 17:59:35 -07006463{
6464 Mutex::Autolock _l(mLock);
Steve Block3856b092011-10-20 11:56:00 +01006465// ALOGV("command(), cmdCode: %d, mEffectInterface: %p", cmdCode, mEffectInterface);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006466
Eric Laurentec437d82011-07-26 20:54:46 -07006467 if (mState == DESTROYED || mEffectInterface == NULL) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07006468 return NO_INIT;
6469 }
Eric Laurent25f43952010-07-28 05:40:18 -07006470 status_t status = (*mEffectInterface)->command(mEffectInterface,
6471 cmdCode,
6472 cmdSize,
6473 pCmdData,
6474 replySize,
6475 pReplyData);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006476 if (cmdCode != EFFECT_CMD_GET_PARAM && status == NO_ERROR) {
Eric Laurent25f43952010-07-28 05:40:18 -07006477 uint32_t size = (replySize == NULL) ? 0 : *replySize;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006478 for (size_t i = 1; i < mHandles.size(); i++) {
6479 sp<EffectHandle> h = mHandles[i].promote();
6480 if (h != 0) {
6481 h->commandExecuted(cmdCode, cmdSize, pCmdData, size, pReplyData);
6482 }
6483 }
6484 }
6485 return status;
6486}
6487
6488status_t AudioFlinger::EffectModule::setEnabled(bool enabled)
6489{
Eric Laurentdb7c0792011-08-10 10:37:50 -07006490
Mathias Agopian65ab4712010-07-14 17:59:35 -07006491 Mutex::Autolock _l(mLock);
Steve Block3856b092011-10-20 11:56:00 +01006492 ALOGV("setEnabled %p enabled %d", this, enabled);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006493
6494 if (enabled != isEnabled()) {
Eric Laurentdb7c0792011-08-10 10:37:50 -07006495 status_t status = AudioSystem::setEffectEnabled(mId, enabled);
6496 if (enabled && status != NO_ERROR) {
6497 return status;
6498 }
6499
Mathias Agopian65ab4712010-07-14 17:59:35 -07006500 switch (mState) {
6501 // going from disabled to enabled
6502 case IDLE:
6503 mState = STARTING;
6504 break;
6505 case STOPPED:
6506 mState = RESTART;
6507 break;
6508 case STOPPING:
6509 mState = ACTIVE;
6510 break;
6511
6512 // going from enabled to disabled
6513 case RESTART:
Eric Laurent8f45bd72010-08-31 13:50:07 -07006514 mState = STOPPED;
6515 break;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006516 case STARTING:
6517 mState = IDLE;
6518 break;
6519 case ACTIVE:
6520 mState = STOPPING;
6521 break;
Eric Laurentec437d82011-07-26 20:54:46 -07006522 case DESTROYED:
6523 return NO_ERROR; // simply ignore as we are being destroyed
Mathias Agopian65ab4712010-07-14 17:59:35 -07006524 }
6525 for (size_t i = 1; i < mHandles.size(); i++) {
6526 sp<EffectHandle> h = mHandles[i].promote();
6527 if (h != 0) {
6528 h->setEnabled(enabled);
6529 }
6530 }
6531 }
6532 return NO_ERROR;
6533}
6534
Glenn Kastenc59c0042012-02-02 14:06:11 -08006535bool AudioFlinger::EffectModule::isEnabled() const
Mathias Agopian65ab4712010-07-14 17:59:35 -07006536{
6537 switch (mState) {
6538 case RESTART:
6539 case STARTING:
6540 case ACTIVE:
6541 return true;
6542 case IDLE:
6543 case STOPPING:
6544 case STOPPED:
Eric Laurentec437d82011-07-26 20:54:46 -07006545 case DESTROYED:
Mathias Agopian65ab4712010-07-14 17:59:35 -07006546 default:
6547 return false;
6548 }
6549}
6550
Glenn Kastenc59c0042012-02-02 14:06:11 -08006551bool AudioFlinger::EffectModule::isProcessEnabled() const
Eric Laurent8f45bd72010-08-31 13:50:07 -07006552{
6553 switch (mState) {
6554 case RESTART:
6555 case ACTIVE:
6556 case STOPPING:
6557 case STOPPED:
6558 return true;
6559 case IDLE:
6560 case STARTING:
Eric Laurentec437d82011-07-26 20:54:46 -07006561 case DESTROYED:
Eric Laurent8f45bd72010-08-31 13:50:07 -07006562 default:
6563 return false;
6564 }
6565}
6566
Mathias Agopian65ab4712010-07-14 17:59:35 -07006567status_t AudioFlinger::EffectModule::setVolume(uint32_t *left, uint32_t *right, bool controller)
6568{
6569 Mutex::Autolock _l(mLock);
6570 status_t status = NO_ERROR;
6571
6572 // Send volume indication if EFFECT_FLAG_VOLUME_IND is set and read back altered volume
6573 // if controller flag is set (Note that controller == TRUE => EFFECT_FLAG_VOLUME_CTRL set)
Eric Laurent8f45bd72010-08-31 13:50:07 -07006574 if (isProcessEnabled() &&
Eric Laurentf997cab2010-07-19 06:24:46 -07006575 ((mDescriptor.flags & EFFECT_FLAG_VOLUME_MASK) == EFFECT_FLAG_VOLUME_CTRL ||
6576 (mDescriptor.flags & EFFECT_FLAG_VOLUME_MASK) == EFFECT_FLAG_VOLUME_IND)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07006577 status_t cmdStatus;
6578 uint32_t volume[2];
6579 uint32_t *pVolume = NULL;
Eric Laurent25f43952010-07-28 05:40:18 -07006580 uint32_t size = sizeof(volume);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006581 volume[0] = *left;
6582 volume[1] = *right;
6583 if (controller) {
6584 pVolume = volume;
6585 }
Eric Laurent25f43952010-07-28 05:40:18 -07006586 status = (*mEffectInterface)->command(mEffectInterface,
6587 EFFECT_CMD_SET_VOLUME,
6588 size,
6589 volume,
6590 &size,
6591 pVolume);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006592 if (controller && status == NO_ERROR && size == sizeof(volume)) {
6593 *left = volume[0];
6594 *right = volume[1];
6595 }
6596 }
6597 return status;
6598}
6599
6600status_t AudioFlinger::EffectModule::setDevice(uint32_t device)
6601{
6602 Mutex::Autolock _l(mLock);
6603 status_t status = NO_ERROR;
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006604 if (device && (mDescriptor.flags & EFFECT_FLAG_DEVICE_MASK) == EFFECT_FLAG_DEVICE_IND) {
6605 // audio pre processing modules on RecordThread can receive both output and
6606 // input device indication in the same call
6607 uint32_t dev = device & AUDIO_DEVICE_OUT_ALL;
6608 if (dev) {
6609 status_t cmdStatus;
6610 uint32_t size = sizeof(status_t);
6611
6612 status = (*mEffectInterface)->command(mEffectInterface,
6613 EFFECT_CMD_SET_DEVICE,
6614 sizeof(uint32_t),
6615 &dev,
6616 &size,
6617 &cmdStatus);
6618 if (status == NO_ERROR) {
6619 status = cmdStatus;
6620 }
6621 }
6622 dev = device & AUDIO_DEVICE_IN_ALL;
6623 if (dev) {
6624 status_t cmdStatus;
6625 uint32_t size = sizeof(status_t);
6626
6627 status_t status2 = (*mEffectInterface)->command(mEffectInterface,
6628 EFFECT_CMD_SET_INPUT_DEVICE,
6629 sizeof(uint32_t),
6630 &dev,
6631 &size,
6632 &cmdStatus);
6633 if (status2 == NO_ERROR) {
6634 status2 = cmdStatus;
6635 }
6636 if (status == NO_ERROR) {
6637 status = status2;
6638 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07006639 }
6640 }
6641 return status;
6642}
6643
Glenn Kastenf78aee72012-01-04 11:00:47 -08006644status_t AudioFlinger::EffectModule::setMode(audio_mode_t mode)
Mathias Agopian65ab4712010-07-14 17:59:35 -07006645{
6646 Mutex::Autolock _l(mLock);
6647 status_t status = NO_ERROR;
6648 if ((mDescriptor.flags & EFFECT_FLAG_AUDIO_MODE_MASK) == EFFECT_FLAG_AUDIO_MODE_IND) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07006649 status_t cmdStatus;
Eric Laurent25f43952010-07-28 05:40:18 -07006650 uint32_t size = sizeof(status_t);
6651 status = (*mEffectInterface)->command(mEffectInterface,
6652 EFFECT_CMD_SET_AUDIO_MODE,
Glenn Kastenf78aee72012-01-04 11:00:47 -08006653 sizeof(audio_mode_t),
Eric Laurente1315cf2011-05-17 19:16:02 -07006654 &mode,
Eric Laurent25f43952010-07-28 05:40:18 -07006655 &size,
6656 &cmdStatus);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006657 if (status == NO_ERROR) {
6658 status = cmdStatus;
6659 }
6660 }
6661 return status;
6662}
6663
Eric Laurent59255e42011-07-27 19:49:51 -07006664void AudioFlinger::EffectModule::setSuspended(bool suspended)
6665{
6666 Mutex::Autolock _l(mLock);
6667 mSuspended = suspended;
6668}
Glenn Kastena3a85482012-01-04 11:01:11 -08006669
6670bool AudioFlinger::EffectModule::suspended() const
Eric Laurent59255e42011-07-27 19:49:51 -07006671{
6672 Mutex::Autolock _l(mLock);
6673 return mSuspended;
6674}
6675
Mathias Agopian65ab4712010-07-14 17:59:35 -07006676status_t AudioFlinger::EffectModule::dump(int fd, const Vector<String16>& args)
6677{
6678 const size_t SIZE = 256;
6679 char buffer[SIZE];
6680 String8 result;
6681
6682 snprintf(buffer, SIZE, "\tEffect ID %d:\n", mId);
6683 result.append(buffer);
6684
6685 bool locked = tryLock(mLock);
6686 // failed to lock - AudioFlinger is probably deadlocked
6687 if (!locked) {
6688 result.append("\t\tCould not lock Fx mutex:\n");
6689 }
6690
6691 result.append("\t\tSession Status State Engine:\n");
6692 snprintf(buffer, SIZE, "\t\t%05d %03d %03d 0x%08x\n",
6693 mSessionId, mStatus, mState, (uint32_t)mEffectInterface);
6694 result.append(buffer);
6695
6696 result.append("\t\tDescriptor:\n");
6697 snprintf(buffer, SIZE, "\t\t- UUID: %08X-%04X-%04X-%04X-%02X%02X%02X%02X%02X%02X\n",
6698 mDescriptor.uuid.timeLow, mDescriptor.uuid.timeMid, mDescriptor.uuid.timeHiAndVersion,
6699 mDescriptor.uuid.clockSeq, mDescriptor.uuid.node[0], mDescriptor.uuid.node[1],mDescriptor.uuid.node[2],
6700 mDescriptor.uuid.node[3],mDescriptor.uuid.node[4],mDescriptor.uuid.node[5]);
6701 result.append(buffer);
6702 snprintf(buffer, SIZE, "\t\t- TYPE: %08X-%04X-%04X-%04X-%02X%02X%02X%02X%02X%02X\n",
6703 mDescriptor.type.timeLow, mDescriptor.type.timeMid, mDescriptor.type.timeHiAndVersion,
6704 mDescriptor.type.clockSeq, mDescriptor.type.node[0], mDescriptor.type.node[1],mDescriptor.type.node[2],
6705 mDescriptor.type.node[3],mDescriptor.type.node[4],mDescriptor.type.node[5]);
6706 result.append(buffer);
Eric Laurente1315cf2011-05-17 19:16:02 -07006707 snprintf(buffer, SIZE, "\t\t- apiVersion: %08X\n\t\t- flags: %08X\n",
Mathias Agopian65ab4712010-07-14 17:59:35 -07006708 mDescriptor.apiVersion,
6709 mDescriptor.flags);
6710 result.append(buffer);
6711 snprintf(buffer, SIZE, "\t\t- name: %s\n",
6712 mDescriptor.name);
6713 result.append(buffer);
6714 snprintf(buffer, SIZE, "\t\t- implementor: %s\n",
6715 mDescriptor.implementor);
6716 result.append(buffer);
6717
6718 result.append("\t\t- Input configuration:\n");
6719 result.append("\t\t\tBuffer Frames Smp rate Channels Format\n");
6720 snprintf(buffer, SIZE, "\t\t\t0x%08x %05d %05d %08x %d\n",
6721 (uint32_t)mConfig.inputCfg.buffer.raw,
6722 mConfig.inputCfg.buffer.frameCount,
6723 mConfig.inputCfg.samplingRate,
6724 mConfig.inputCfg.channels,
6725 mConfig.inputCfg.format);
6726 result.append(buffer);
6727
6728 result.append("\t\t- Output configuration:\n");
6729 result.append("\t\t\tBuffer Frames Smp rate Channels Format\n");
6730 snprintf(buffer, SIZE, "\t\t\t0x%08x %05d %05d %08x %d\n",
6731 (uint32_t)mConfig.outputCfg.buffer.raw,
6732 mConfig.outputCfg.buffer.frameCount,
6733 mConfig.outputCfg.samplingRate,
6734 mConfig.outputCfg.channels,
6735 mConfig.outputCfg.format);
6736 result.append(buffer);
6737
6738 snprintf(buffer, SIZE, "\t\t%d Clients:\n", mHandles.size());
6739 result.append(buffer);
6740 result.append("\t\t\tPid Priority Ctrl Locked client server\n");
6741 for (size_t i = 0; i < mHandles.size(); ++i) {
6742 sp<EffectHandle> handle = mHandles[i].promote();
6743 if (handle != 0) {
6744 handle->dump(buffer, SIZE);
6745 result.append(buffer);
6746 }
6747 }
6748
6749 result.append("\n");
6750
6751 write(fd, result.string(), result.length());
6752
6753 if (locked) {
6754 mLock.unlock();
6755 }
6756
6757 return NO_ERROR;
6758}
6759
6760// ----------------------------------------------------------------------------
6761// EffectHandle implementation
6762// ----------------------------------------------------------------------------
6763
6764#undef LOG_TAG
6765#define LOG_TAG "AudioFlinger::EffectHandle"
6766
6767AudioFlinger::EffectHandle::EffectHandle(const sp<EffectModule>& effect,
6768 const sp<AudioFlinger::Client>& client,
6769 const sp<IEffectClient>& effectClient,
6770 int32_t priority)
6771 : BnEffect(),
Marco Nelissen3a34bef2011-08-02 13:33:41 -07006772 mEffect(effect), mEffectClient(effectClient), mClient(client), mCblk(NULL),
Eric Laurent59255e42011-07-27 19:49:51 -07006773 mPriority(priority), mHasControl(false), mEnabled(false)
Mathias Agopian65ab4712010-07-14 17:59:35 -07006774{
Steve Block3856b092011-10-20 11:56:00 +01006775 ALOGV("constructor %p", this);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006776
Marco Nelissen3a34bef2011-08-02 13:33:41 -07006777 if (client == 0) {
6778 return;
6779 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07006780 int bufOffset = ((sizeof(effect_param_cblk_t) - 1) / sizeof(int) + 1) * sizeof(int);
6781 mCblkMemory = client->heap()->allocate(EFFECT_PARAM_BUFFER_SIZE + bufOffset);
6782 if (mCblkMemory != 0) {
6783 mCblk = static_cast<effect_param_cblk_t *>(mCblkMemory->pointer());
6784
Glenn Kastena0d68332012-01-27 16:47:15 -08006785 if (mCblk != NULL) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07006786 new(mCblk) effect_param_cblk_t();
6787 mBuffer = (uint8_t *)mCblk + bufOffset;
6788 }
6789 } else {
Steve Block29357bc2012-01-06 19:20:56 +00006790 ALOGE("not enough memory for Effect size=%u", EFFECT_PARAM_BUFFER_SIZE + sizeof(effect_param_cblk_t));
Mathias Agopian65ab4712010-07-14 17:59:35 -07006791 return;
6792 }
6793}
6794
6795AudioFlinger::EffectHandle::~EffectHandle()
6796{
Steve Block3856b092011-10-20 11:56:00 +01006797 ALOGV("Destructor %p", this);
Marco Nelissen3a34bef2011-08-02 13:33:41 -07006798 disconnect(false);
Steve Block3856b092011-10-20 11:56:00 +01006799 ALOGV("Destructor DONE %p", this);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006800}
6801
6802status_t AudioFlinger::EffectHandle::enable()
6803{
Steve Block3856b092011-10-20 11:56:00 +01006804 ALOGV("enable %p", this);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006805 if (!mHasControl) return INVALID_OPERATION;
6806 if (mEffect == 0) return DEAD_OBJECT;
6807
Eric Laurentdb7c0792011-08-10 10:37:50 -07006808 if (mEnabled) {
6809 return NO_ERROR;
6810 }
6811
Eric Laurent59255e42011-07-27 19:49:51 -07006812 mEnabled = true;
6813
6814 sp<ThreadBase> thread = mEffect->thread().promote();
6815 if (thread != 0) {
6816 thread->checkSuspendOnEffectEnabled(mEffect, true, mEffect->sessionId());
6817 }
6818
6819 // checkSuspendOnEffectEnabled() can suspend this same effect when enabled
6820 if (mEffect->suspended()) {
6821 return NO_ERROR;
6822 }
6823
Eric Laurentdb7c0792011-08-10 10:37:50 -07006824 status_t status = mEffect->setEnabled(true);
6825 if (status != NO_ERROR) {
6826 if (thread != 0) {
6827 thread->checkSuspendOnEffectEnabled(mEffect, false, mEffect->sessionId());
6828 }
6829 mEnabled = false;
6830 }
6831 return status;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006832}
6833
6834status_t AudioFlinger::EffectHandle::disable()
6835{
Steve Block3856b092011-10-20 11:56:00 +01006836 ALOGV("disable %p", this);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006837 if (!mHasControl) return INVALID_OPERATION;
Eric Laurent59255e42011-07-27 19:49:51 -07006838 if (mEffect == 0) return DEAD_OBJECT;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006839
Eric Laurentdb7c0792011-08-10 10:37:50 -07006840 if (!mEnabled) {
6841 return NO_ERROR;
6842 }
Eric Laurent59255e42011-07-27 19:49:51 -07006843 mEnabled = false;
6844
6845 if (mEffect->suspended()) {
6846 return NO_ERROR;
6847 }
6848
6849 status_t status = mEffect->setEnabled(false);
6850
6851 sp<ThreadBase> thread = mEffect->thread().promote();
6852 if (thread != 0) {
6853 thread->checkSuspendOnEffectEnabled(mEffect, false, mEffect->sessionId());
6854 }
6855
6856 return status;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006857}
6858
6859void AudioFlinger::EffectHandle::disconnect()
6860{
Marco Nelissen3a34bef2011-08-02 13:33:41 -07006861 disconnect(true);
6862}
6863
Glenn Kasten58123c32012-02-03 10:32:24 -08006864void AudioFlinger::EffectHandle::disconnect(bool unpinIfLast)
Marco Nelissen3a34bef2011-08-02 13:33:41 -07006865{
Glenn Kasten58123c32012-02-03 10:32:24 -08006866 ALOGV("disconnect(%s)", unpinIfLast ? "true" : "false");
Mathias Agopian65ab4712010-07-14 17:59:35 -07006867 if (mEffect == 0) {
6868 return;
6869 }
Glenn Kasten58123c32012-02-03 10:32:24 -08006870 mEffect->disconnect(this, unpinIfLast);
Eric Laurent59255e42011-07-27 19:49:51 -07006871
Eric Laurenta85a74a2011-10-19 11:44:54 -07006872 if (mHasControl && mEnabled) {
Eric Laurentdb7c0792011-08-10 10:37:50 -07006873 sp<ThreadBase> thread = mEffect->thread().promote();
6874 if (thread != 0) {
6875 thread->checkSuspendOnEffectEnabled(mEffect, false, mEffect->sessionId());
6876 }
Eric Laurent59255e42011-07-27 19:49:51 -07006877 }
6878
Mathias Agopian65ab4712010-07-14 17:59:35 -07006879 // release sp on module => module destructor can be called now
6880 mEffect.clear();
Mathias Agopian65ab4712010-07-14 17:59:35 -07006881 if (mClient != 0) {
Glenn Kastena0d68332012-01-27 16:47:15 -08006882 if (mCblk != NULL) {
Glenn Kasten1a0ae5b2012-02-03 10:24:48 -08006883 // unlike ~TrackBase(), mCblk is never a local new, so don't delete
Marco Nelissen3a34bef2011-08-02 13:33:41 -07006884 mCblk->~effect_param_cblk_t(); // destroy our shared-structure.
6885 }
Glenn Kastendbfafaf2012-01-25 15:27:15 -08006886 mCblkMemory.clear(); // free the shared memory before releasing the heap it belongs to
Glenn Kasten98ec94c2012-01-25 14:28:29 -08006887 // Client destructor must run with AudioFlinger mutex locked
Mathias Agopian65ab4712010-07-14 17:59:35 -07006888 Mutex::Autolock _l(mClient->audioFlinger()->mLock);
6889 mClient.clear();
6890 }
6891}
6892
Eric Laurent25f43952010-07-28 05:40:18 -07006893status_t AudioFlinger::EffectHandle::command(uint32_t cmdCode,
6894 uint32_t cmdSize,
6895 void *pCmdData,
6896 uint32_t *replySize,
6897 void *pReplyData)
Mathias Agopian65ab4712010-07-14 17:59:35 -07006898{
Steve Block3856b092011-10-20 11:56:00 +01006899// ALOGV("command(), cmdCode: %d, mHasControl: %d, mEffect: %p",
Eric Laurent25f43952010-07-28 05:40:18 -07006900// cmdCode, mHasControl, (mEffect == 0) ? 0 : mEffect.get());
Mathias Agopian65ab4712010-07-14 17:59:35 -07006901
6902 // only get parameter command is permitted for applications not controlling the effect
6903 if (!mHasControl && cmdCode != EFFECT_CMD_GET_PARAM) {
6904 return INVALID_OPERATION;
6905 }
6906 if (mEffect == 0) return DEAD_OBJECT;
Marco Nelissen3a34bef2011-08-02 13:33:41 -07006907 if (mClient == 0) return INVALID_OPERATION;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006908
6909 // handle commands that are not forwarded transparently to effect engine
6910 if (cmdCode == EFFECT_CMD_SET_PARAM_COMMIT) {
6911 // No need to trylock() here as this function is executed in the binder thread serving a particular client process:
6912 // no risk to block the whole media server process or mixer threads is we are stuck here
6913 Mutex::Autolock _l(mCblk->lock);
6914 if (mCblk->clientIndex > EFFECT_PARAM_BUFFER_SIZE ||
6915 mCblk->serverIndex > EFFECT_PARAM_BUFFER_SIZE) {
6916 mCblk->serverIndex = 0;
6917 mCblk->clientIndex = 0;
6918 return BAD_VALUE;
6919 }
6920 status_t status = NO_ERROR;
6921 while (mCblk->serverIndex < mCblk->clientIndex) {
6922 int reply;
Eric Laurent25f43952010-07-28 05:40:18 -07006923 uint32_t rsize = sizeof(int);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006924 int *p = (int *)(mBuffer + mCblk->serverIndex);
6925 int size = *p++;
6926 if (((uint8_t *)p + size) > mBuffer + mCblk->clientIndex) {
Steve Block5ff1dd52012-01-05 23:22:43 +00006927 ALOGW("command(): invalid parameter block size");
Mathias Agopian65ab4712010-07-14 17:59:35 -07006928 break;
6929 }
6930 effect_param_t *param = (effect_param_t *)p;
6931 if (param->psize == 0 || param->vsize == 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00006932 ALOGW("command(): null parameter or value size");
Mathias Agopian65ab4712010-07-14 17:59:35 -07006933 mCblk->serverIndex += size;
6934 continue;
6935 }
Eric Laurent25f43952010-07-28 05:40:18 -07006936 uint32_t psize = sizeof(effect_param_t) +
6937 ((param->psize - 1) / sizeof(int) + 1) * sizeof(int) +
6938 param->vsize;
6939 status_t ret = mEffect->command(EFFECT_CMD_SET_PARAM,
6940 psize,
6941 p,
6942 &rsize,
6943 &reply);
Eric Laurentaeae3de2010-09-02 11:56:55 -07006944 // stop at first error encountered
6945 if (ret != NO_ERROR) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07006946 status = ret;
Eric Laurentaeae3de2010-09-02 11:56:55 -07006947 *(int *)pReplyData = reply;
6948 break;
6949 } else if (reply != NO_ERROR) {
6950 *(int *)pReplyData = reply;
6951 break;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006952 }
6953 mCblk->serverIndex += size;
6954 }
6955 mCblk->serverIndex = 0;
6956 mCblk->clientIndex = 0;
6957 return status;
6958 } else if (cmdCode == EFFECT_CMD_ENABLE) {
Eric Laurentaeae3de2010-09-02 11:56:55 -07006959 *(int *)pReplyData = NO_ERROR;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006960 return enable();
6961 } else if (cmdCode == EFFECT_CMD_DISABLE) {
Eric Laurentaeae3de2010-09-02 11:56:55 -07006962 *(int *)pReplyData = NO_ERROR;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006963 return disable();
6964 }
6965
6966 return mEffect->command(cmdCode, cmdSize, pCmdData, replySize, pReplyData);
6967}
6968
Eric Laurent59255e42011-07-27 19:49:51 -07006969void AudioFlinger::EffectHandle::setControl(bool hasControl, bool signal, bool enabled)
Mathias Agopian65ab4712010-07-14 17:59:35 -07006970{
Steve Block3856b092011-10-20 11:56:00 +01006971 ALOGV("setControl %p control %d", this, hasControl);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006972
6973 mHasControl = hasControl;
Eric Laurent59255e42011-07-27 19:49:51 -07006974 mEnabled = enabled;
6975
Mathias Agopian65ab4712010-07-14 17:59:35 -07006976 if (signal && mEffectClient != 0) {
6977 mEffectClient->controlStatusChanged(hasControl);
6978 }
6979}
6980
Eric Laurent25f43952010-07-28 05:40:18 -07006981void AudioFlinger::EffectHandle::commandExecuted(uint32_t cmdCode,
6982 uint32_t cmdSize,
6983 void *pCmdData,
6984 uint32_t replySize,
6985 void *pReplyData)
Mathias Agopian65ab4712010-07-14 17:59:35 -07006986{
6987 if (mEffectClient != 0) {
6988 mEffectClient->commandExecuted(cmdCode, cmdSize, pCmdData, replySize, pReplyData);
6989 }
6990}
6991
6992
6993
6994void AudioFlinger::EffectHandle::setEnabled(bool enabled)
6995{
6996 if (mEffectClient != 0) {
6997 mEffectClient->enableStatusChanged(enabled);
6998 }
6999}
7000
7001status_t AudioFlinger::EffectHandle::onTransact(
7002 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
7003{
7004 return BnEffect::onTransact(code, data, reply, flags);
7005}
7006
7007
7008void AudioFlinger::EffectHandle::dump(char* buffer, size_t size)
7009{
Glenn Kastena0d68332012-01-27 16:47:15 -08007010 bool locked = mCblk != NULL && tryLock(mCblk->lock);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007011
7012 snprintf(buffer, size, "\t\t\t%05d %05d %01u %01u %05u %05u\n",
Glenn Kasten44deb052012-02-05 18:09:08 -08007013 (mClient == 0) ? getpid_cached : mClient->pid(),
Mathias Agopian65ab4712010-07-14 17:59:35 -07007014 mPriority,
7015 mHasControl,
7016 !locked,
Marco Nelissen3a34bef2011-08-02 13:33:41 -07007017 mCblk ? mCblk->clientIndex : 0,
7018 mCblk ? mCblk->serverIndex : 0
Mathias Agopian65ab4712010-07-14 17:59:35 -07007019 );
7020
7021 if (locked) {
7022 mCblk->lock.unlock();
7023 }
7024}
7025
7026#undef LOG_TAG
7027#define LOG_TAG "AudioFlinger::EffectChain"
7028
7029AudioFlinger::EffectChain::EffectChain(const wp<ThreadBase>& wThread,
7030 int sessionId)
Eric Laurent544fe9b2011-11-11 15:42:52 -08007031 : mThread(wThread), mSessionId(sessionId), mActiveTrackCnt(0), mTrackCnt(0), mTailBufferCount(0),
Eric Laurentb469b942011-05-09 12:09:06 -07007032 mOwnInBuffer(false), mVolumeCtrlIdx(-1), mLeftVolume(UINT_MAX), mRightVolume(UINT_MAX),
7033 mNewLeftVolume(UINT_MAX), mNewRightVolume(UINT_MAX)
Mathias Agopian65ab4712010-07-14 17:59:35 -07007034{
Dima Zavinfce7a472011-04-19 22:30:36 -07007035 mStrategy = AudioSystem::getStrategyForStream(AUDIO_STREAM_MUSIC);
Eric Laurent544fe9b2011-11-11 15:42:52 -08007036 sp<ThreadBase> thread = mThread.promote();
7037 if (thread == 0) {
7038 return;
7039 }
7040 mMaxTailBuffers = ((kProcessTailDurationMs * thread->sampleRate()) / 1000) /
7041 thread->frameCount();
Mathias Agopian65ab4712010-07-14 17:59:35 -07007042}
7043
7044AudioFlinger::EffectChain::~EffectChain()
7045{
7046 if (mOwnInBuffer) {
7047 delete mInBuffer;
7048 }
7049
7050}
7051
Eric Laurent59255e42011-07-27 19:49:51 -07007052// getEffectFromDesc_l() must be called with ThreadBase::mLock held
Eric Laurentcab11242010-07-15 12:50:15 -07007053sp<AudioFlinger::EffectModule> AudioFlinger::EffectChain::getEffectFromDesc_l(effect_descriptor_t *descriptor)
Mathias Agopian65ab4712010-07-14 17:59:35 -07007054{
Mathias Agopian65ab4712010-07-14 17:59:35 -07007055 size_t size = mEffects.size();
7056
7057 for (size_t i = 0; i < size; i++) {
7058 if (memcmp(&mEffects[i]->desc().uuid, &descriptor->uuid, sizeof(effect_uuid_t)) == 0) {
Glenn Kasten090f0192012-01-30 13:00:02 -08007059 return mEffects[i];
Mathias Agopian65ab4712010-07-14 17:59:35 -07007060 }
7061 }
Glenn Kasten090f0192012-01-30 13:00:02 -08007062 return 0;
Mathias Agopian65ab4712010-07-14 17:59:35 -07007063}
7064
Eric Laurent59255e42011-07-27 19:49:51 -07007065// getEffectFromId_l() must be called with ThreadBase::mLock held
Eric Laurentcab11242010-07-15 12:50:15 -07007066sp<AudioFlinger::EffectModule> AudioFlinger::EffectChain::getEffectFromId_l(int id)
Mathias Agopian65ab4712010-07-14 17:59:35 -07007067{
Mathias Agopian65ab4712010-07-14 17:59:35 -07007068 size_t size = mEffects.size();
7069
7070 for (size_t i = 0; i < size; i++) {
Eric Laurentde070132010-07-13 04:45:46 -07007071 // by convention, return first effect if id provided is 0 (0 is never a valid id)
7072 if (id == 0 || mEffects[i]->id() == id) {
Glenn Kasten090f0192012-01-30 13:00:02 -08007073 return mEffects[i];
Mathias Agopian65ab4712010-07-14 17:59:35 -07007074 }
7075 }
Glenn Kasten090f0192012-01-30 13:00:02 -08007076 return 0;
Mathias Agopian65ab4712010-07-14 17:59:35 -07007077}
7078
Eric Laurent59255e42011-07-27 19:49:51 -07007079// getEffectFromType_l() must be called with ThreadBase::mLock held
7080sp<AudioFlinger::EffectModule> AudioFlinger::EffectChain::getEffectFromType_l(
7081 const effect_uuid_t *type)
7082{
Eric Laurent59255e42011-07-27 19:49:51 -07007083 size_t size = mEffects.size();
7084
7085 for (size_t i = 0; i < size; i++) {
7086 if (memcmp(&mEffects[i]->desc().type, type, sizeof(effect_uuid_t)) == 0) {
Glenn Kasten090f0192012-01-30 13:00:02 -08007087 return mEffects[i];
Eric Laurent59255e42011-07-27 19:49:51 -07007088 }
7089 }
Glenn Kasten090f0192012-01-30 13:00:02 -08007090 return 0;
Eric Laurent59255e42011-07-27 19:49:51 -07007091}
7092
Mathias Agopian65ab4712010-07-14 17:59:35 -07007093// Must be called with EffectChain::mLock locked
7094void AudioFlinger::EffectChain::process_l()
7095{
Eric Laurentdac69112010-09-28 14:09:57 -07007096 sp<ThreadBase> thread = mThread.promote();
7097 if (thread == 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00007098 ALOGW("process_l(): cannot promote mixer thread");
Eric Laurentdac69112010-09-28 14:09:57 -07007099 return;
7100 }
Dima Zavinfce7a472011-04-19 22:30:36 -07007101 bool isGlobalSession = (mSessionId == AUDIO_SESSION_OUTPUT_MIX) ||
7102 (mSessionId == AUDIO_SESSION_OUTPUT_STAGE);
Eric Laurent544fe9b2011-11-11 15:42:52 -08007103 // always process effects unless no more tracks are on the session and the effect tail
7104 // has been rendered
7105 bool doProcess = true;
Eric Laurentdac69112010-09-28 14:09:57 -07007106 if (!isGlobalSession) {
Eric Laurent544fe9b2011-11-11 15:42:52 -08007107 bool tracksOnSession = (trackCnt() != 0);
Eric Laurentb469b942011-05-09 12:09:06 -07007108
Eric Laurent544fe9b2011-11-11 15:42:52 -08007109 if (!tracksOnSession && mTailBufferCount == 0) {
7110 doProcess = false;
7111 }
7112
7113 if (activeTrackCnt() == 0) {
7114 // if no track is active and the effect tail has not been rendered,
7115 // the input buffer must be cleared here as the mixer process will not do it
7116 if (tracksOnSession || mTailBufferCount > 0) {
7117 size_t numSamples = thread->frameCount() * thread->channelCount();
7118 memset(mInBuffer, 0, numSamples * sizeof(int16_t));
7119 if (mTailBufferCount > 0) {
7120 mTailBufferCount--;
7121 }
7122 }
7123 }
Eric Laurentdac69112010-09-28 14:09:57 -07007124 }
7125
Mathias Agopian65ab4712010-07-14 17:59:35 -07007126 size_t size = mEffects.size();
Eric Laurent544fe9b2011-11-11 15:42:52 -08007127 if (doProcess) {
Eric Laurentdac69112010-09-28 14:09:57 -07007128 for (size_t i = 0; i < size; i++) {
7129 mEffects[i]->process();
7130 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07007131 }
7132 for (size_t i = 0; i < size; i++) {
7133 mEffects[i]->updateState();
7134 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07007135}
7136
Eric Laurentcab11242010-07-15 12:50:15 -07007137// addEffect_l() must be called with PlaybackThread::mLock held
Eric Laurentde070132010-07-13 04:45:46 -07007138status_t AudioFlinger::EffectChain::addEffect_l(const sp<EffectModule>& effect)
Mathias Agopian65ab4712010-07-14 17:59:35 -07007139{
7140 effect_descriptor_t desc = effect->desc();
7141 uint32_t insertPref = desc.flags & EFFECT_FLAG_INSERT_MASK;
7142
7143 Mutex::Autolock _l(mLock);
Eric Laurentde070132010-07-13 04:45:46 -07007144 effect->setChain(this);
7145 sp<ThreadBase> thread = mThread.promote();
7146 if (thread == 0) {
7147 return NO_INIT;
7148 }
7149 effect->setThread(thread);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007150
7151 if ((desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
7152 // Auxiliary effects are inserted at the beginning of mEffects vector as
7153 // they are processed first and accumulated in chain input buffer
7154 mEffects.insertAt(effect, 0);
Eric Laurentde070132010-07-13 04:45:46 -07007155
Mathias Agopian65ab4712010-07-14 17:59:35 -07007156 // the input buffer for auxiliary effect contains mono samples in
7157 // 32 bit format. This is to avoid saturation in AudoMixer
7158 // accumulation stage. Saturation is done in EffectModule::process() before
7159 // calling the process in effect engine
7160 size_t numSamples = thread->frameCount();
7161 int32_t *buffer = new int32_t[numSamples];
7162 memset(buffer, 0, numSamples * sizeof(int32_t));
7163 effect->setInBuffer((int16_t *)buffer);
7164 // auxiliary effects output samples to chain input buffer for further processing
7165 // by insert effects
7166 effect->setOutBuffer(mInBuffer);
7167 } else {
7168 // Insert effects are inserted at the end of mEffects vector as they are processed
7169 // after track and auxiliary effects.
7170 // Insert effect order as a function of indicated preference:
7171 // if EFFECT_FLAG_INSERT_EXCLUSIVE, insert in first position or reject if
7172 // another effect is present
7173 // else if EFFECT_FLAG_INSERT_FIRST, insert in first position or after the
7174 // last effect claiming first position
7175 // else if EFFECT_FLAG_INSERT_LAST, insert in last position or before the
7176 // first effect claiming last position
7177 // else if EFFECT_FLAG_INSERT_ANY insert after first or before last
7178 // Reject insertion if an effect with EFFECT_FLAG_INSERT_EXCLUSIVE is
7179 // already present
7180
Glenn Kasten8d6a2442012-02-08 14:04:28 -08007181 size_t size = mEffects.size();
7182 size_t idx_insert = size;
7183 ssize_t idx_insert_first = -1;
7184 ssize_t idx_insert_last = -1;
Mathias Agopian65ab4712010-07-14 17:59:35 -07007185
Glenn Kasten8d6a2442012-02-08 14:04:28 -08007186 for (size_t i = 0; i < size; i++) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07007187 effect_descriptor_t d = mEffects[i]->desc();
7188 uint32_t iMode = d.flags & EFFECT_FLAG_TYPE_MASK;
7189 uint32_t iPref = d.flags & EFFECT_FLAG_INSERT_MASK;
7190 if (iMode == EFFECT_FLAG_TYPE_INSERT) {
7191 // check invalid effect chaining combinations
7192 if (insertPref == EFFECT_FLAG_INSERT_EXCLUSIVE ||
7193 iPref == EFFECT_FLAG_INSERT_EXCLUSIVE) {
Steve Block5ff1dd52012-01-05 23:22:43 +00007194 ALOGW("addEffect_l() could not insert effect %s: exclusive conflict with %s", desc.name, d.name);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007195 return INVALID_OPERATION;
7196 }
7197 // remember position of first insert effect and by default
7198 // select this as insert position for new effect
7199 if (idx_insert == size) {
7200 idx_insert = i;
7201 }
7202 // remember position of last insert effect claiming
7203 // first position
7204 if (iPref == EFFECT_FLAG_INSERT_FIRST) {
7205 idx_insert_first = i;
7206 }
7207 // remember position of first insert effect claiming
7208 // last position
7209 if (iPref == EFFECT_FLAG_INSERT_LAST &&
7210 idx_insert_last == -1) {
7211 idx_insert_last = i;
7212 }
7213 }
7214 }
7215
7216 // modify idx_insert from first position if needed
7217 if (insertPref == EFFECT_FLAG_INSERT_LAST) {
7218 if (idx_insert_last != -1) {
7219 idx_insert = idx_insert_last;
7220 } else {
7221 idx_insert = size;
7222 }
7223 } else {
7224 if (idx_insert_first != -1) {
7225 idx_insert = idx_insert_first + 1;
7226 }
7227 }
7228
7229 // always read samples from chain input buffer
7230 effect->setInBuffer(mInBuffer);
7231
7232 // if last effect in the chain, output samples to chain
7233 // output buffer, otherwise to chain input buffer
7234 if (idx_insert == size) {
7235 if (idx_insert != 0) {
7236 mEffects[idx_insert-1]->setOutBuffer(mInBuffer);
7237 mEffects[idx_insert-1]->configure();
7238 }
7239 effect->setOutBuffer(mOutBuffer);
7240 } else {
7241 effect->setOutBuffer(mInBuffer);
7242 }
7243 mEffects.insertAt(effect, idx_insert);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007244
Steve Block3856b092011-10-20 11:56:00 +01007245 ALOGV("addEffect_l() effect %p, added in chain %p at rank %d", effect.get(), this, idx_insert);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007246 }
7247 effect->configure();
7248 return NO_ERROR;
7249}
7250
Eric Laurentcab11242010-07-15 12:50:15 -07007251// removeEffect_l() must be called with PlaybackThread::mLock held
7252size_t AudioFlinger::EffectChain::removeEffect_l(const sp<EffectModule>& effect)
Mathias Agopian65ab4712010-07-14 17:59:35 -07007253{
7254 Mutex::Autolock _l(mLock);
Glenn Kasten8d6a2442012-02-08 14:04:28 -08007255 size_t size = mEffects.size();
Mathias Agopian65ab4712010-07-14 17:59:35 -07007256 uint32_t type = effect->desc().flags & EFFECT_FLAG_TYPE_MASK;
7257
Glenn Kasten8d6a2442012-02-08 14:04:28 -08007258 for (size_t i = 0; i < size; i++) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07007259 if (effect == mEffects[i]) {
Eric Laurentec437d82011-07-26 20:54:46 -07007260 // calling stop here will remove pre-processing effect from the audio HAL.
7261 // This is safe as we hold the EffectChain mutex which guarantees that we are not in
7262 // the middle of a read from audio HAL
Eric Laurentec35a142011-10-05 17:42:25 -07007263 if (mEffects[i]->state() == EffectModule::ACTIVE ||
7264 mEffects[i]->state() == EffectModule::STOPPING) {
7265 mEffects[i]->stop();
7266 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07007267 if (type == EFFECT_FLAG_TYPE_AUXILIARY) {
7268 delete[] effect->inBuffer();
7269 } else {
7270 if (i == size - 1 && i != 0) {
7271 mEffects[i - 1]->setOutBuffer(mOutBuffer);
7272 mEffects[i - 1]->configure();
7273 }
7274 }
7275 mEffects.removeAt(i);
Steve Block3856b092011-10-20 11:56:00 +01007276 ALOGV("removeEffect_l() effect %p, removed from chain %p at rank %d", effect.get(), this, i);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007277 break;
7278 }
7279 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07007280
7281 return mEffects.size();
7282}
7283
Eric Laurentcab11242010-07-15 12:50:15 -07007284// setDevice_l() must be called with PlaybackThread::mLock held
7285void AudioFlinger::EffectChain::setDevice_l(uint32_t device)
Mathias Agopian65ab4712010-07-14 17:59:35 -07007286{
7287 size_t size = mEffects.size();
7288 for (size_t i = 0; i < size; i++) {
7289 mEffects[i]->setDevice(device);
7290 }
7291}
7292
Eric Laurentcab11242010-07-15 12:50:15 -07007293// setMode_l() must be called with PlaybackThread::mLock held
Glenn Kastenf78aee72012-01-04 11:00:47 -08007294void AudioFlinger::EffectChain::setMode_l(audio_mode_t mode)
Mathias Agopian65ab4712010-07-14 17:59:35 -07007295{
7296 size_t size = mEffects.size();
7297 for (size_t i = 0; i < size; i++) {
7298 mEffects[i]->setMode(mode);
7299 }
7300}
7301
Eric Laurentcab11242010-07-15 12:50:15 -07007302// setVolume_l() must be called with PlaybackThread::mLock held
7303bool AudioFlinger::EffectChain::setVolume_l(uint32_t *left, uint32_t *right)
Mathias Agopian65ab4712010-07-14 17:59:35 -07007304{
7305 uint32_t newLeft = *left;
7306 uint32_t newRight = *right;
7307 bool hasControl = false;
Eric Laurentcab11242010-07-15 12:50:15 -07007308 int ctrlIdx = -1;
7309 size_t size = mEffects.size();
Mathias Agopian65ab4712010-07-14 17:59:35 -07007310
Eric Laurentcab11242010-07-15 12:50:15 -07007311 // first update volume controller
7312 for (size_t i = size; i > 0; i--) {
Eric Laurent8f45bd72010-08-31 13:50:07 -07007313 if (mEffects[i - 1]->isProcessEnabled() &&
Eric Laurentcab11242010-07-15 12:50:15 -07007314 (mEffects[i - 1]->desc().flags & EFFECT_FLAG_VOLUME_MASK) == EFFECT_FLAG_VOLUME_CTRL) {
7315 ctrlIdx = i - 1;
Eric Laurentf997cab2010-07-19 06:24:46 -07007316 hasControl = true;
Eric Laurentcab11242010-07-15 12:50:15 -07007317 break;
7318 }
7319 }
7320
7321 if (ctrlIdx == mVolumeCtrlIdx && *left == mLeftVolume && *right == mRightVolume) {
Eric Laurentf997cab2010-07-19 06:24:46 -07007322 if (hasControl) {
7323 *left = mNewLeftVolume;
7324 *right = mNewRightVolume;
7325 }
7326 return hasControl;
Eric Laurentcab11242010-07-15 12:50:15 -07007327 }
7328
7329 mVolumeCtrlIdx = ctrlIdx;
Eric Laurentf997cab2010-07-19 06:24:46 -07007330 mLeftVolume = newLeft;
7331 mRightVolume = newRight;
Eric Laurentcab11242010-07-15 12:50:15 -07007332
7333 // second get volume update from volume controller
7334 if (ctrlIdx >= 0) {
7335 mEffects[ctrlIdx]->setVolume(&newLeft, &newRight, true);
Eric Laurentf997cab2010-07-19 06:24:46 -07007336 mNewLeftVolume = newLeft;
7337 mNewRightVolume = newRight;
Mathias Agopian65ab4712010-07-14 17:59:35 -07007338 }
7339 // then indicate volume to all other effects in chain.
7340 // Pass altered volume to effects before volume controller
7341 // and requested volume to effects after controller
7342 uint32_t lVol = newLeft;
7343 uint32_t rVol = newRight;
Eric Laurentcab11242010-07-15 12:50:15 -07007344
Mathias Agopian65ab4712010-07-14 17:59:35 -07007345 for (size_t i = 0; i < size; i++) {
Eric Laurentcab11242010-07-15 12:50:15 -07007346 if ((int)i == ctrlIdx) continue;
7347 // this also works for ctrlIdx == -1 when there is no volume controller
7348 if ((int)i > ctrlIdx) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07007349 lVol = *left;
7350 rVol = *right;
7351 }
7352 mEffects[i]->setVolume(&lVol, &rVol, false);
7353 }
7354 *left = newLeft;
7355 *right = newRight;
7356
7357 return hasControl;
7358}
7359
Mathias Agopian65ab4712010-07-14 17:59:35 -07007360status_t AudioFlinger::EffectChain::dump(int fd, const Vector<String16>& args)
7361{
7362 const size_t SIZE = 256;
7363 char buffer[SIZE];
7364 String8 result;
7365
7366 snprintf(buffer, SIZE, "Effects for session %d:\n", mSessionId);
7367 result.append(buffer);
7368
7369 bool locked = tryLock(mLock);
7370 // failed to lock - AudioFlinger is probably deadlocked
7371 if (!locked) {
7372 result.append("\tCould not lock mutex:\n");
7373 }
7374
Eric Laurentcab11242010-07-15 12:50:15 -07007375 result.append("\tNum fx In buffer Out buffer Active tracks:\n");
7376 snprintf(buffer, SIZE, "\t%02d 0x%08x 0x%08x %d\n",
Mathias Agopian65ab4712010-07-14 17:59:35 -07007377 mEffects.size(),
7378 (uint32_t)mInBuffer,
7379 (uint32_t)mOutBuffer,
Mathias Agopian65ab4712010-07-14 17:59:35 -07007380 mActiveTrackCnt);
7381 result.append(buffer);
7382 write(fd, result.string(), result.size());
7383
7384 for (size_t i = 0; i < mEffects.size(); ++i) {
7385 sp<EffectModule> effect = mEffects[i];
7386 if (effect != 0) {
7387 effect->dump(fd, args);
7388 }
7389 }
7390
7391 if (locked) {
7392 mLock.unlock();
7393 }
7394
7395 return NO_ERROR;
7396}
7397
Eric Laurent59255e42011-07-27 19:49:51 -07007398// must be called with ThreadBase::mLock held
7399void AudioFlinger::EffectChain::setEffectSuspended_l(
7400 const effect_uuid_t *type, bool suspend)
7401{
7402 sp<SuspendedEffectDesc> desc;
7403 // use effect type UUID timelow as key as there is no real risk of identical
7404 // timeLow fields among effect type UUIDs.
Glenn Kasten8d6a2442012-02-08 14:04:28 -08007405 ssize_t index = mSuspendedEffects.indexOfKey(type->timeLow);
Eric Laurent59255e42011-07-27 19:49:51 -07007406 if (suspend) {
7407 if (index >= 0) {
7408 desc = mSuspendedEffects.valueAt(index);
7409 } else {
7410 desc = new SuspendedEffectDesc();
7411 memcpy(&desc->mType, type, sizeof(effect_uuid_t));
7412 mSuspendedEffects.add(type->timeLow, desc);
Steve Block3856b092011-10-20 11:56:00 +01007413 ALOGV("setEffectSuspended_l() add entry for %08x", type->timeLow);
Eric Laurent59255e42011-07-27 19:49:51 -07007414 }
7415 if (desc->mRefCount++ == 0) {
7416 sp<EffectModule> effect = getEffectIfEnabled(type);
7417 if (effect != 0) {
7418 desc->mEffect = effect;
7419 effect->setSuspended(true);
7420 effect->setEnabled(false);
7421 }
7422 }
7423 } else {
7424 if (index < 0) {
7425 return;
7426 }
7427 desc = mSuspendedEffects.valueAt(index);
7428 if (desc->mRefCount <= 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00007429 ALOGW("setEffectSuspended_l() restore refcount should not be 0 %d", desc->mRefCount);
Eric Laurent59255e42011-07-27 19:49:51 -07007430 desc->mRefCount = 1;
7431 }
7432 if (--desc->mRefCount == 0) {
Steve Block3856b092011-10-20 11:56:00 +01007433 ALOGV("setEffectSuspended_l() remove entry for %08x", mSuspendedEffects.keyAt(index));
Eric Laurent59255e42011-07-27 19:49:51 -07007434 if (desc->mEffect != 0) {
7435 sp<EffectModule> effect = desc->mEffect.promote();
7436 if (effect != 0) {
7437 effect->setSuspended(false);
7438 sp<EffectHandle> handle = effect->controlHandle();
7439 if (handle != 0) {
7440 effect->setEnabled(handle->enabled());
7441 }
7442 }
7443 desc->mEffect.clear();
7444 }
7445 mSuspendedEffects.removeItemsAt(index);
7446 }
7447 }
7448}
7449
7450// must be called with ThreadBase::mLock held
7451void AudioFlinger::EffectChain::setEffectSuspendedAll_l(bool suspend)
7452{
7453 sp<SuspendedEffectDesc> desc;
7454
Glenn Kasten8d6a2442012-02-08 14:04:28 -08007455 ssize_t index = mSuspendedEffects.indexOfKey((int)kKeyForSuspendAll);
Eric Laurent59255e42011-07-27 19:49:51 -07007456 if (suspend) {
7457 if (index >= 0) {
7458 desc = mSuspendedEffects.valueAt(index);
7459 } else {
7460 desc = new SuspendedEffectDesc();
7461 mSuspendedEffects.add((int)kKeyForSuspendAll, desc);
Steve Block3856b092011-10-20 11:56:00 +01007462 ALOGV("setEffectSuspendedAll_l() add entry for 0");
Eric Laurent59255e42011-07-27 19:49:51 -07007463 }
7464 if (desc->mRefCount++ == 0) {
Glenn Kastend0539712012-01-30 12:56:03 -08007465 Vector< sp<EffectModule> > effects;
7466 getSuspendEligibleEffects(effects);
Eric Laurent59255e42011-07-27 19:49:51 -07007467 for (size_t i = 0; i < effects.size(); i++) {
7468 setEffectSuspended_l(&effects[i]->desc().type, true);
7469 }
7470 }
7471 } else {
7472 if (index < 0) {
7473 return;
7474 }
7475 desc = mSuspendedEffects.valueAt(index);
7476 if (desc->mRefCount <= 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00007477 ALOGW("setEffectSuspendedAll_l() restore refcount should not be 0 %d", desc->mRefCount);
Eric Laurent59255e42011-07-27 19:49:51 -07007478 desc->mRefCount = 1;
7479 }
7480 if (--desc->mRefCount == 0) {
7481 Vector<const effect_uuid_t *> types;
7482 for (size_t i = 0; i < mSuspendedEffects.size(); i++) {
7483 if (mSuspendedEffects.keyAt(i) == (int)kKeyForSuspendAll) {
7484 continue;
7485 }
7486 types.add(&mSuspendedEffects.valueAt(i)->mType);
7487 }
7488 for (size_t i = 0; i < types.size(); i++) {
7489 setEffectSuspended_l(types[i], false);
7490 }
Steve Block3856b092011-10-20 11:56:00 +01007491 ALOGV("setEffectSuspendedAll_l() remove entry for %08x", mSuspendedEffects.keyAt(index));
Eric Laurent59255e42011-07-27 19:49:51 -07007492 mSuspendedEffects.removeItem((int)kKeyForSuspendAll);
7493 }
7494 }
7495}
7496
Eric Laurent6bffdb82011-09-23 08:40:41 -07007497
7498// The volume effect is used for automated tests only
7499#ifndef OPENSL_ES_H_
7500static const effect_uuid_t SL_IID_VOLUME_ = { 0x09e8ede0, 0xddde, 0x11db, 0xb4f6,
7501 { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } };
7502const effect_uuid_t * const SL_IID_VOLUME = &SL_IID_VOLUME_;
7503#endif //OPENSL_ES_H_
7504
Eric Laurentdb7c0792011-08-10 10:37:50 -07007505bool AudioFlinger::EffectChain::isEffectEligibleForSuspend(const effect_descriptor_t& desc)
7506{
7507 // auxiliary effects and visualizer are never suspended on output mix
7508 if ((mSessionId == AUDIO_SESSION_OUTPUT_MIX) &&
7509 (((desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) ||
Eric Laurent6bffdb82011-09-23 08:40:41 -07007510 (memcmp(&desc.type, SL_IID_VISUALIZATION, sizeof(effect_uuid_t)) == 0) ||
7511 (memcmp(&desc.type, SL_IID_VOLUME, sizeof(effect_uuid_t)) == 0))) {
Eric Laurentdb7c0792011-08-10 10:37:50 -07007512 return false;
7513 }
7514 return true;
7515}
7516
Glenn Kastend0539712012-01-30 12:56:03 -08007517void AudioFlinger::EffectChain::getSuspendEligibleEffects(Vector< sp<AudioFlinger::EffectModule> > &effects)
Eric Laurent59255e42011-07-27 19:49:51 -07007518{
Glenn Kastend0539712012-01-30 12:56:03 -08007519 effects.clear();
Eric Laurent59255e42011-07-27 19:49:51 -07007520 for (size_t i = 0; i < mEffects.size(); i++) {
Glenn Kastend0539712012-01-30 12:56:03 -08007521 if (isEffectEligibleForSuspend(mEffects[i]->desc())) {
7522 effects.add(mEffects[i]);
Eric Laurent59255e42011-07-27 19:49:51 -07007523 }
Eric Laurent59255e42011-07-27 19:49:51 -07007524 }
Eric Laurent59255e42011-07-27 19:49:51 -07007525}
7526
7527sp<AudioFlinger::EffectModule> AudioFlinger::EffectChain::getEffectIfEnabled(
7528 const effect_uuid_t *type)
7529{
Glenn Kasten090f0192012-01-30 13:00:02 -08007530 sp<EffectModule> effect = getEffectFromType_l(type);
7531 return effect != 0 && effect->isEnabled() ? effect : 0;
Eric Laurent59255e42011-07-27 19:49:51 -07007532}
7533
7534void AudioFlinger::EffectChain::checkSuspendOnEffectEnabled(const sp<EffectModule>& effect,
7535 bool enabled)
7536{
Glenn Kasten8d6a2442012-02-08 14:04:28 -08007537 ssize_t index = mSuspendedEffects.indexOfKey(effect->desc().type.timeLow);
Eric Laurent59255e42011-07-27 19:49:51 -07007538 if (enabled) {
7539 if (index < 0) {
7540 // if the effect is not suspend check if all effects are suspended
7541 index = mSuspendedEffects.indexOfKey((int)kKeyForSuspendAll);
7542 if (index < 0) {
7543 return;
7544 }
Eric Laurentdb7c0792011-08-10 10:37:50 -07007545 if (!isEffectEligibleForSuspend(effect->desc())) {
7546 return;
7547 }
Eric Laurent59255e42011-07-27 19:49:51 -07007548 setEffectSuspended_l(&effect->desc().type, enabled);
7549 index = mSuspendedEffects.indexOfKey(effect->desc().type.timeLow);
Eric Laurentdb7c0792011-08-10 10:37:50 -07007550 if (index < 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00007551 ALOGW("checkSuspendOnEffectEnabled() Fx should be suspended here!");
Eric Laurentdb7c0792011-08-10 10:37:50 -07007552 return;
7553 }
Eric Laurent59255e42011-07-27 19:49:51 -07007554 }
Steve Block3856b092011-10-20 11:56:00 +01007555 ALOGV("checkSuspendOnEffectEnabled() enable suspending fx %08x",
Eric Laurent59255e42011-07-27 19:49:51 -07007556 effect->desc().type.timeLow);
7557 sp<SuspendedEffectDesc> desc = mSuspendedEffects.valueAt(index);
7558 // if effect is requested to suspended but was not yet enabled, supend it now.
7559 if (desc->mEffect == 0) {
7560 desc->mEffect = effect;
7561 effect->setEnabled(false);
7562 effect->setSuspended(true);
7563 }
7564 } else {
7565 if (index < 0) {
7566 return;
7567 }
Steve Block3856b092011-10-20 11:56:00 +01007568 ALOGV("checkSuspendOnEffectEnabled() disable restoring fx %08x",
Eric Laurent59255e42011-07-27 19:49:51 -07007569 effect->desc().type.timeLow);
7570 sp<SuspendedEffectDesc> desc = mSuspendedEffects.valueAt(index);
7571 desc->mEffect.clear();
7572 effect->setSuspended(false);
7573 }
7574}
7575
Mathias Agopian65ab4712010-07-14 17:59:35 -07007576#undef LOG_TAG
7577#define LOG_TAG "AudioFlinger"
7578
7579// ----------------------------------------------------------------------------
7580
7581status_t AudioFlinger::onTransact(
7582 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
7583{
7584 return BnAudioFlinger::onTransact(code, data, reply, flags);
7585}
7586
Mathias Agopian65ab4712010-07-14 17:59:35 -07007587}; // namespace android