blob: 69560e5743c9c9e5ec70ba1f6d026894bae3d19b [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>
38
39#include <media/AudioTrack.h>
40#include <media/AudioRecord.h>
Gloria Wang9ee159b2011-02-24 14:51:45 -080041#include <media/IMediaPlayerService.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"
51
Mathias Agopian65ab4712010-07-14 17:59:35 -070052#include <media/EffectsFactoryApi.h>
Eric Laurent6d8b6942011-06-24 07:01:31 -070053#include <audio_effects/effect_visualizer.h>
Eric Laurent59bd0da2011-08-01 09:52:20 -070054#include <audio_effects/effect_ns.h>
55#include <audio_effects/effect_aec.h>
Mathias Agopian65ab4712010-07-14 17:59:35 -070056
Glenn Kasten4d8d0c32011-07-08 15:26:12 -070057#include <cpustats/ThreadCpuUsage.h>
Eric Laurentfeb0db62011-07-22 09:04:31 -070058#include <powermanager/PowerManager.h>
Glenn Kasten4d8d0c32011-07-08 15:26:12 -070059// #define DEBUG_CPU_USAGE 10 // log statistics every n wall clock seconds
60
Mathias Agopian65ab4712010-07-14 17:59:35 -070061// ----------------------------------------------------------------------------
Mathias Agopian65ab4712010-07-14 17:59:35 -070062
Eric Laurentde070132010-07-13 04:45:46 -070063
Mathias Agopian65ab4712010-07-14 17:59:35 -070064namespace android {
65
66static const char* kDeadlockedString = "AudioFlinger may be deadlocked\n";
67static const char* kHardwareLockedString = "Hardware lock is taken\n";
68
69//static const nsecs_t kStandbyTimeInNsecs = seconds(3);
70static const float MAX_GAIN = 4096.0f;
71static const float MAX_GAIN_INT = 0x1000;
72
73// retry counts for buffer fill timeout
74// 50 * ~20msecs = 1 second
75static const int8_t kMaxTrackRetries = 50;
76static const int8_t kMaxTrackStartupRetries = 50;
77// allow less retry attempts on direct output thread.
78// direct outputs can be a scarce resource in audio hardware and should
79// be released as quickly as possible.
80static const int8_t kMaxTrackRetriesDirect = 2;
81
82static const int kDumpLockRetries = 50;
83static const int kDumpLockSleep = 20000;
84
85static const nsecs_t kWarningThrottle = seconds(5);
86
Eric Laurent7c7f10b2011-06-17 21:29:58 -070087// RecordThread loop sleep time upon application overrun or audio HAL read error
88static const int kRecordThreadSleepUs = 5000;
Mathias Agopian65ab4712010-07-14 17:59:35 -070089
Eric Laurent60cd0a02011-09-13 11:40:21 -070090static const nsecs_t kSetParametersTimeout = seconds(2);
91
Mathias Agopian65ab4712010-07-14 17:59:35 -070092// ----------------------------------------------------------------------------
93
94static bool recordingAllowed() {
Mathias Agopian65ab4712010-07-14 17:59:35 -070095 if (getpid() == IPCThreadState::self()->getCallingPid()) return true;
96 bool ok = checkCallingPermission(String16("android.permission.RECORD_AUDIO"));
97 if (!ok) LOGE("Request requires android.permission.RECORD_AUDIO");
98 return ok;
Mathias Agopian65ab4712010-07-14 17:59:35 -070099}
100
101static bool settingsAllowed() {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700102 if (getpid() == IPCThreadState::self()->getCallingPid()) return true;
103 bool ok = checkCallingPermission(String16("android.permission.MODIFY_AUDIO_SETTINGS"));
104 if (!ok) LOGE("Request requires android.permission.MODIFY_AUDIO_SETTINGS");
105 return ok;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700106}
107
Gloria Wang9ee159b2011-02-24 14:51:45 -0800108// To collect the amplifier usage
109static void addBatteryData(uint32_t params) {
110 sp<IBinder> binder =
111 defaultServiceManager()->getService(String16("media.player"));
112 sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder);
113 if (service.get() == NULL) {
114 LOGW("Cannot connect to the MediaPlayerService for battery tracking");
115 return;
116 }
117
118 service->addBatteryData(params);
119}
120
Dima Zavin799a70e2011-04-18 16:57:27 -0700121static int load_audio_interface(const char *if_name, const hw_module_t **mod,
122 audio_hw_device_t **dev)
123{
124 int rc;
125
126 rc = hw_get_module_by_class(AUDIO_HARDWARE_MODULE_ID, if_name, mod);
127 if (rc)
128 goto out;
129
130 rc = audio_hw_device_open(*mod, dev);
131 LOGE_IF(rc, "couldn't open audio hw device in %s.%s (%s)",
132 AUDIO_HARDWARE_MODULE_ID, if_name, strerror(-rc));
133 if (rc)
134 goto out;
135
136 return 0;
137
138out:
139 *mod = NULL;
140 *dev = NULL;
141 return rc;
142}
143
144static const char *audio_interfaces[] = {
145 "primary",
146 "a2dp",
147 "usb",
148};
149#define ARRAY_SIZE(x) (sizeof((x))/sizeof(((x)[0])))
150
Mathias Agopian65ab4712010-07-14 17:59:35 -0700151// ----------------------------------------------------------------------------
152
153AudioFlinger::AudioFlinger()
154 : BnAudioFlinger(),
Eric Laurent59bd0da2011-08-01 09:52:20 -0700155 mPrimaryHardwareDev(0), mMasterVolume(1.0f), mMasterMute(false), mNextUniqueId(1),
Eric Laurentbee53372011-08-29 12:42:48 -0700156 mBtNrecIsOff(false)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700157{
Dima Zavin5a61d2f2011-04-19 19:04:32 -0700158}
159
160void AudioFlinger::onFirstRef()
161{
Dima Zavin799a70e2011-04-18 16:57:27 -0700162 int rc = 0;
Dima Zavinfce7a472011-04-19 22:30:36 -0700163
Eric Laurent93575202011-01-18 18:39:02 -0800164 Mutex::Autolock _l(mLock);
165
Dima Zavin799a70e2011-04-18 16:57:27 -0700166 /* TODO: move all this work into an Init() function */
Mathias Agopian65ab4712010-07-14 17:59:35 -0700167 mHardwareStatus = AUDIO_HW_IDLE;
168
Dima Zavin799a70e2011-04-18 16:57:27 -0700169 for (size_t i = 0; i < ARRAY_SIZE(audio_interfaces); i++) {
170 const hw_module_t *mod;
171 audio_hw_device_t *dev;
Dima Zavinfce7a472011-04-19 22:30:36 -0700172
Dima Zavin799a70e2011-04-18 16:57:27 -0700173 rc = load_audio_interface(audio_interfaces[i], &mod, &dev);
174 if (rc)
175 continue;
176
177 LOGI("Loaded %s audio interface from %s (%s)", audio_interfaces[i],
178 mod->name, mod->id);
179 mAudioHwDevs.push(dev);
180
181 if (!mPrimaryHardwareDev) {
182 mPrimaryHardwareDev = dev;
183 LOGI("Using '%s' (%s.%s) as the primary audio interface",
Dima Zavin5a61d2f2011-04-19 19:04:32 -0700184 mod->name, mod->id, audio_interfaces[i]);
Dima Zavin799a70e2011-04-18 16:57:27 -0700185 }
186 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700187
188 mHardwareStatus = AUDIO_HW_INIT;
Dima Zavinfce7a472011-04-19 22:30:36 -0700189
Dima Zavin799a70e2011-04-18 16:57:27 -0700190 if (!mPrimaryHardwareDev || mAudioHwDevs.size() == 0) {
191 LOGE("Primary audio interface not found");
192 return;
193 }
194
195 for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
196 audio_hw_device_t *dev = mAudioHwDevs[i];
197
198 mHardwareStatus = AUDIO_HW_INIT;
199 rc = dev->init_check(dev);
200 if (rc == 0) {
201 AutoMutex lock(mHardwareLock);
202
203 mMode = AUDIO_MODE_NORMAL;
204 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
Dima Zavin5a61d2f2011-04-19 19:04:32 -0700213status_t AudioFlinger::initCheck() const
214{
215 Mutex::Autolock _l(mLock);
216 if (mPrimaryHardwareDev == NULL || mAudioHwDevs.size() == 0)
217 return NO_INIT;
218 return NO_ERROR;
219}
220
Mathias Agopian65ab4712010-07-14 17:59:35 -0700221AudioFlinger::~AudioFlinger()
222{
Dima Zavin799a70e2011-04-18 16:57:27 -0700223 int num_devs = mAudioHwDevs.size();
224
Mathias Agopian65ab4712010-07-14 17:59:35 -0700225 while (!mRecordThreads.isEmpty()) {
226 // closeInput() will remove first entry from mRecordThreads
227 closeInput(mRecordThreads.keyAt(0));
228 }
229 while (!mPlaybackThreads.isEmpty()) {
230 // closeOutput() will remove first entry from mPlaybackThreads
231 closeOutput(mPlaybackThreads.keyAt(0));
232 }
Dima Zavin799a70e2011-04-18 16:57:27 -0700233
234 for (int i = 0; i < num_devs; i++) {
235 audio_hw_device_t *dev = mAudioHwDevs[i];
236 audio_hw_device_close(dev);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700237 }
Dima Zavin799a70e2011-04-18 16:57:27 -0700238 mAudioHwDevs.clear();
Mathias Agopian65ab4712010-07-14 17:59:35 -0700239}
240
Dima Zavin799a70e2011-04-18 16:57:27 -0700241audio_hw_device_t* AudioFlinger::findSuitableHwDev_l(uint32_t devices)
242{
243 /* first matching HW device is returned */
244 for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
245 audio_hw_device_t *dev = mAudioHwDevs[i];
246 if ((dev->get_supported_devices(dev) & devices) == devices)
247 return dev;
248 }
249 return NULL;
250}
Mathias Agopian65ab4712010-07-14 17:59:35 -0700251
252status_t AudioFlinger::dumpClients(int fd, const Vector<String16>& args)
253{
254 const size_t SIZE = 256;
255 char buffer[SIZE];
256 String8 result;
257
258 result.append("Clients:\n");
259 for (size_t i = 0; i < mClients.size(); ++i) {
260 wp<Client> wClient = mClients.valueAt(i);
261 if (wClient != 0) {
262 sp<Client> client = wClient.promote();
263 if (client != 0) {
264 snprintf(buffer, SIZE, " pid: %d\n", client->pid());
265 result.append(buffer);
266 }
267 }
268 }
Marco Nelissen3a34bef2011-08-02 13:33:41 -0700269
270 result.append("Global session refs:\n");
271 result.append(" session pid cnt\n");
272 for (size_t i = 0; i < mAudioSessionRefs.size(); i++) {
273 AudioSessionRef *r = mAudioSessionRefs[i];
274 snprintf(buffer, SIZE, " %7d %3d %3d\n", r->sessionid, r->pid, r->cnt);
275 result.append(buffer);
276 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700277 write(fd, result.string(), result.size());
278 return NO_ERROR;
279}
280
281
282status_t AudioFlinger::dumpInternals(int fd, const Vector<String16>& args)
283{
284 const size_t SIZE = 256;
285 char buffer[SIZE];
286 String8 result;
287 int hardwareStatus = mHardwareStatus;
288
289 snprintf(buffer, SIZE, "Hardware status: %d\n", hardwareStatus);
290 result.append(buffer);
291 write(fd, result.string(), result.size());
292 return NO_ERROR;
293}
294
295status_t AudioFlinger::dumpPermissionDenial(int fd, const Vector<String16>& args)
296{
297 const size_t SIZE = 256;
298 char buffer[SIZE];
299 String8 result;
300 snprintf(buffer, SIZE, "Permission Denial: "
301 "can't dump AudioFlinger from pid=%d, uid=%d\n",
302 IPCThreadState::self()->getCallingPid(),
303 IPCThreadState::self()->getCallingUid());
304 result.append(buffer);
305 write(fd, result.string(), result.size());
306 return NO_ERROR;
307}
308
309static bool tryLock(Mutex& mutex)
310{
311 bool locked = false;
312 for (int i = 0; i < kDumpLockRetries; ++i) {
313 if (mutex.tryLock() == NO_ERROR) {
314 locked = true;
315 break;
316 }
317 usleep(kDumpLockSleep);
318 }
319 return locked;
320}
321
322status_t AudioFlinger::dump(int fd, const Vector<String16>& args)
323{
324 if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
325 dumpPermissionDenial(fd, args);
326 } else {
327 // get state of hardware lock
328 bool hardwareLocked = tryLock(mHardwareLock);
329 if (!hardwareLocked) {
330 String8 result(kHardwareLockedString);
331 write(fd, result.string(), result.size());
332 } else {
333 mHardwareLock.unlock();
334 }
335
336 bool locked = tryLock(mLock);
337
338 // failed to lock - AudioFlinger is probably deadlocked
339 if (!locked) {
340 String8 result(kDeadlockedString);
341 write(fd, result.string(), result.size());
342 }
343
344 dumpClients(fd, args);
345 dumpInternals(fd, args);
346
347 // dump playback threads
348 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
349 mPlaybackThreads.valueAt(i)->dump(fd, args);
350 }
351
352 // dump record threads
353 for (size_t i = 0; i < mRecordThreads.size(); i++) {
354 mRecordThreads.valueAt(i)->dump(fd, args);
355 }
356
Dima Zavin799a70e2011-04-18 16:57:27 -0700357 // dump all hardware devs
358 for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
359 audio_hw_device_t *dev = mAudioHwDevs[i];
360 dev->dump(dev, fd);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700361 }
362 if (locked) mLock.unlock();
363 }
364 return NO_ERROR;
365}
366
367
368// IAudioFlinger interface
369
370
371sp<IAudioTrack> AudioFlinger::createTrack(
372 pid_t pid,
373 int streamType,
374 uint32_t sampleRate,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -0700375 uint32_t format,
376 uint32_t channelMask,
Mathias Agopian65ab4712010-07-14 17:59:35 -0700377 int frameCount,
378 uint32_t flags,
379 const sp<IMemory>& sharedBuffer,
380 int output,
381 int *sessionId,
382 status_t *status)
383{
384 sp<PlaybackThread::Track> track;
385 sp<TrackHandle> trackHandle;
386 sp<Client> client;
387 wp<Client> wclient;
388 status_t lStatus;
389 int lSessionId;
390
Dima Zavinfce7a472011-04-19 22:30:36 -0700391 if (streamType >= AUDIO_STREAM_CNT) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700392 LOGE("invalid stream type");
393 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) {
402 LOGE("unknown output thread");
403 lStatus = BAD_VALUE;
404 goto Exit;
405 }
406
407 wclient = mClients.valueFor(pid);
408
409 if (wclient != NULL) {
410 client = wclient.promote();
411 } else {
412 client = new Client(this, pid);
413 mClients.add(pid, client);
414 }
415
Mathias Agopian65ab4712010-07-14 17:59:35 -0700416 LOGV("createTrack() sessionId: %d", (sessionId == NULL) ? -2 : *sessionId);
Dima Zavinfce7a472011-04-19 22:30:36 -0700417 if (sessionId != NULL && *sessionId != AUDIO_SESSION_OUTPUT_MIX) {
Eric Laurentde070132010-07-13 04:45:46 -0700418 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
Eric Laurent39e94f82010-07-28 01:32:47 -0700419 sp<PlaybackThread> t = mPlaybackThreads.valueAt(i);
420 if (mPlaybackThreads.keyAt(i) != output) {
421 // prevent same audio session on different output threads
422 uint32_t sessions = t->hasAudioSession(*sessionId);
423 if (sessions & PlaybackThread::TRACK_SESSION) {
424 lStatus = BAD_VALUE;
425 goto Exit;
426 }
427 // check if an effect with same session ID is waiting for a track to be created
428 if (sessions & PlaybackThread::EFFECT_SESSION) {
429 effectThread = t.get();
430 }
Eric Laurentde070132010-07-13 04:45:46 -0700431 }
432 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700433 lSessionId = *sessionId;
434 } else {
Eric Laurentde070132010-07-13 04:45:46 -0700435 // if no audio session id is provided, create one here
Eric Laurent7c7f10b2011-06-17 21:29:58 -0700436 lSessionId = nextUniqueId();
Mathias Agopian65ab4712010-07-14 17:59:35 -0700437 if (sessionId != NULL) {
438 *sessionId = lSessionId;
439 }
440 }
441 LOGV("createTrack() lSessionId: %d", lSessionId);
442
443 track = thread->createTrack_l(client, streamType, sampleRate, format,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -0700444 channelMask, frameCount, sharedBuffer, lSessionId, &lStatus);
Eric Laurent39e94f82010-07-28 01:32:47 -0700445
446 // move effect chain to this output thread if an effect on same session was waiting
447 // for a track to be created
448 if (lStatus == NO_ERROR && effectThread != NULL) {
449 Mutex::Autolock _dl(thread->mLock);
450 Mutex::Autolock _sl(effectThread->mLock);
451 moveEffectChain_l(lSessionId, effectThread, thread, true);
452 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700453 }
454 if (lStatus == NO_ERROR) {
455 trackHandle = new TrackHandle(track);
456 } else {
457 // remove local strong reference to Client before deleting the Track so that the Client
458 // destructor is called by the TrackBase destructor with mLock held
459 client.clear();
460 track.clear();
461 }
462
463Exit:
464 if(status) {
465 *status = lStatus;
466 }
467 return trackHandle;
468}
469
470uint32_t AudioFlinger::sampleRate(int output) const
471{
472 Mutex::Autolock _l(mLock);
473 PlaybackThread *thread = checkPlaybackThread_l(output);
474 if (thread == NULL) {
475 LOGW("sampleRate() unknown thread %d", output);
476 return 0;
477 }
478 return thread->sampleRate();
479}
480
481int AudioFlinger::channelCount(int output) const
482{
483 Mutex::Autolock _l(mLock);
484 PlaybackThread *thread = checkPlaybackThread_l(output);
485 if (thread == NULL) {
486 LOGW("channelCount() unknown thread %d", output);
487 return 0;
488 }
489 return thread->channelCount();
490}
491
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -0700492uint32_t AudioFlinger::format(int output) const
Mathias Agopian65ab4712010-07-14 17:59:35 -0700493{
494 Mutex::Autolock _l(mLock);
495 PlaybackThread *thread = checkPlaybackThread_l(output);
496 if (thread == NULL) {
497 LOGW("format() unknown thread %d", output);
498 return 0;
499 }
500 return thread->format();
501}
502
503size_t AudioFlinger::frameCount(int output) const
504{
505 Mutex::Autolock _l(mLock);
506 PlaybackThread *thread = checkPlaybackThread_l(output);
507 if (thread == NULL) {
508 LOGW("frameCount() unknown thread %d", output);
509 return 0;
510 }
511 return thread->frameCount();
512}
513
514uint32_t AudioFlinger::latency(int output) const
515{
516 Mutex::Autolock _l(mLock);
517 PlaybackThread *thread = checkPlaybackThread_l(output);
518 if (thread == NULL) {
519 LOGW("latency() unknown thread %d", output);
520 return 0;
521 }
522 return thread->latency();
523}
524
525status_t AudioFlinger::setMasterVolume(float value)
526{
Eric Laurenta1884f92011-08-23 08:25:03 -0700527 status_t ret = initCheck();
528 if (ret != NO_ERROR) {
529 return ret;
530 }
531
Mathias Agopian65ab4712010-07-14 17:59:35 -0700532 // check calling permissions
533 if (!settingsAllowed()) {
534 return PERMISSION_DENIED;
535 }
536
537 // when hw supports master volume, don't scale in sw mixer
Eric Laurent93575202011-01-18 18:39:02 -0800538 { // scope for the lock
539 AutoMutex lock(mHardwareLock);
540 mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
Dima Zavin799a70e2011-04-18 16:57:27 -0700541 if (mPrimaryHardwareDev->set_master_volume(mPrimaryHardwareDev, value) == NO_ERROR) {
Eric Laurent93575202011-01-18 18:39:02 -0800542 value = 1.0f;
543 }
544 mHardwareStatus = AUDIO_HW_IDLE;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700545 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700546
Eric Laurent93575202011-01-18 18:39:02 -0800547 Mutex::Autolock _l(mLock);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700548 mMasterVolume = value;
549 for (uint32_t i = 0; i < mPlaybackThreads.size(); i++)
550 mPlaybackThreads.valueAt(i)->setMasterVolume(value);
551
552 return NO_ERROR;
553}
554
555status_t AudioFlinger::setMode(int mode)
556{
Eric Laurenta1884f92011-08-23 08:25:03 -0700557 status_t ret = initCheck();
558 if (ret != NO_ERROR) {
559 return ret;
560 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700561
562 // check calling permissions
563 if (!settingsAllowed()) {
564 return PERMISSION_DENIED;
565 }
Dima Zavinfce7a472011-04-19 22:30:36 -0700566 if ((mode < 0) || (mode >= AUDIO_MODE_CNT)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700567 LOGW("Illegal value: setMode(%d)", mode);
568 return BAD_VALUE;
569 }
570
571 { // scope for the lock
572 AutoMutex lock(mHardwareLock);
573 mHardwareStatus = AUDIO_HW_SET_MODE;
Dima Zavin799a70e2011-04-18 16:57:27 -0700574 ret = mPrimaryHardwareDev->set_mode(mPrimaryHardwareDev, mode);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700575 mHardwareStatus = AUDIO_HW_IDLE;
576 }
577
578 if (NO_ERROR == ret) {
579 Mutex::Autolock _l(mLock);
580 mMode = mode;
581 for (uint32_t i = 0; i < mPlaybackThreads.size(); i++)
582 mPlaybackThreads.valueAt(i)->setMode(mode);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700583 }
584
585 return ret;
586}
587
588status_t AudioFlinger::setMicMute(bool state)
589{
Eric Laurenta1884f92011-08-23 08:25:03 -0700590 status_t ret = initCheck();
591 if (ret != NO_ERROR) {
592 return ret;
593 }
594
Mathias Agopian65ab4712010-07-14 17:59:35 -0700595 // check calling permissions
596 if (!settingsAllowed()) {
597 return PERMISSION_DENIED;
598 }
599
600 AutoMutex lock(mHardwareLock);
601 mHardwareStatus = AUDIO_HW_SET_MIC_MUTE;
Eric Laurenta1884f92011-08-23 08:25:03 -0700602 ret = mPrimaryHardwareDev->set_mic_mute(mPrimaryHardwareDev, state);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700603 mHardwareStatus = AUDIO_HW_IDLE;
604 return ret;
605}
606
607bool AudioFlinger::getMicMute() const
608{
Eric Laurenta1884f92011-08-23 08:25:03 -0700609 status_t ret = initCheck();
610 if (ret != NO_ERROR) {
611 return false;
612 }
613
Dima Zavinfce7a472011-04-19 22:30:36 -0700614 bool state = AUDIO_MODE_INVALID;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700615 mHardwareStatus = AUDIO_HW_GET_MIC_MUTE;
Dima Zavin799a70e2011-04-18 16:57:27 -0700616 mPrimaryHardwareDev->get_mic_mute(mPrimaryHardwareDev, &state);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700617 mHardwareStatus = AUDIO_HW_IDLE;
618 return state;
619}
620
621status_t AudioFlinger::setMasterMute(bool muted)
622{
623 // check calling permissions
624 if (!settingsAllowed()) {
625 return PERMISSION_DENIED;
626 }
627
Eric Laurent93575202011-01-18 18:39:02 -0800628 Mutex::Autolock _l(mLock);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700629 mMasterMute = muted;
630 for (uint32_t i = 0; i < mPlaybackThreads.size(); i++)
631 mPlaybackThreads.valueAt(i)->setMasterMute(muted);
632
633 return NO_ERROR;
634}
635
636float AudioFlinger::masterVolume() const
637{
638 return mMasterVolume;
639}
640
641bool AudioFlinger::masterMute() const
642{
643 return mMasterMute;
644}
645
646status_t AudioFlinger::setStreamVolume(int stream, float value, int output)
647{
648 // check calling permissions
649 if (!settingsAllowed()) {
650 return PERMISSION_DENIED;
651 }
652
Dima Zavinfce7a472011-04-19 22:30:36 -0700653 if (stream < 0 || uint32_t(stream) >= AUDIO_STREAM_CNT) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700654 return BAD_VALUE;
655 }
656
657 AutoMutex lock(mLock);
658 PlaybackThread *thread = NULL;
659 if (output) {
660 thread = checkPlaybackThread_l(output);
661 if (thread == NULL) {
662 return BAD_VALUE;
663 }
664 }
665
666 mStreamTypes[stream].volume = value;
667
668 if (thread == NULL) {
669 for (uint32_t i = 0; i < mPlaybackThreads.size(); i++) {
670 mPlaybackThreads.valueAt(i)->setStreamVolume(stream, value);
671 }
672 } else {
673 thread->setStreamVolume(stream, value);
674 }
675
676 return NO_ERROR;
677}
678
679status_t AudioFlinger::setStreamMute(int stream, bool muted)
680{
681 // check calling permissions
682 if (!settingsAllowed()) {
683 return PERMISSION_DENIED;
684 }
685
Dima Zavinfce7a472011-04-19 22:30:36 -0700686 if (stream < 0 || uint32_t(stream) >= AUDIO_STREAM_CNT ||
687 uint32_t(stream) == AUDIO_STREAM_ENFORCED_AUDIBLE) {
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
699float AudioFlinger::streamVolume(int stream, int output) const
700{
Dima Zavinfce7a472011-04-19 22:30:36 -0700701 if (stream < 0 || 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
720bool AudioFlinger::streamMute(int stream) const
721{
Dima Zavinfce7a472011-04-19 22:30:36 -0700722 if (stream < 0 || stream >= (int)AUDIO_STREAM_CNT) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700723 return true;
724 }
725
726 return mStreamTypes[stream].mute;
727}
728
Mathias Agopian65ab4712010-07-14 17:59:35 -0700729status_t AudioFlinger::setParameters(int ioHandle, const String8& keyValuePairs)
730{
731 status_t result;
732
733 LOGV("setParameters(): io %d, keyvalue %s, tid %d, calling tid %d",
734 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);
Eric Laurent7c7f10b2011-06-17 21:29:58 -0700787 } else if (thread.get() == primaryPlaybackThread_l()) {
788 // 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 }
798 if (thread != NULL) {
799 result = thread->setParameters(keyValuePairs);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700800 return result;
801 }
802 return BAD_VALUE;
803}
804
805String8 AudioFlinger::getParameters(int ioHandle, const String8& keys)
806{
807// LOGV("getParameters() io %d, keys %s, tid %d, calling tid %d",
808// ioHandle, keys.string(), gettid(), IPCThreadState::self()->getCallingPid());
809
810 if (ioHandle == 0) {
Dima Zavinfce7a472011-04-19 22:30:36 -0700811 String8 out_s8;
812
Dima Zavin799a70e2011-04-18 16:57:27 -0700813 for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
814 audio_hw_device_t *dev = mAudioHwDevs[i];
815 char *s = dev->get_parameters(dev, keys.string());
816 out_s8 += String8(s);
817 free(s);
818 }
Dima Zavinfce7a472011-04-19 22:30:36 -0700819 return out_s8;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700820 }
821
822 Mutex::Autolock _l(mLock);
823
824 PlaybackThread *playbackThread = checkPlaybackThread_l(ioHandle);
825 if (playbackThread != NULL) {
826 return playbackThread->getParameters(keys);
827 }
828 RecordThread *recordThread = checkRecordThread_l(ioHandle);
829 if (recordThread != NULL) {
830 return recordThread->getParameters(keys);
831 }
832 return String8("");
833}
834
835size_t AudioFlinger::getInputBufferSize(uint32_t sampleRate, int format, int channelCount)
836{
Eric Laurenta1884f92011-08-23 08:25:03 -0700837 status_t ret = initCheck();
838 if (ret != NO_ERROR) {
839 return 0;
840 }
841
Dima Zavin799a70e2011-04-18 16:57:27 -0700842 return mPrimaryHardwareDev->get_input_buffer_size(mPrimaryHardwareDev, sampleRate, format, channelCount);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700843}
844
845unsigned int AudioFlinger::getInputFramesLost(int ioHandle)
846{
847 if (ioHandle == 0) {
848 return 0;
849 }
850
851 Mutex::Autolock _l(mLock);
852
853 RecordThread *recordThread = checkRecordThread_l(ioHandle);
854 if (recordThread != NULL) {
855 return recordThread->getInputFramesLost();
856 }
857 return 0;
858}
859
860status_t AudioFlinger::setVoiceVolume(float value)
861{
Eric Laurenta1884f92011-08-23 08:25:03 -0700862 status_t ret = initCheck();
863 if (ret != NO_ERROR) {
864 return ret;
865 }
866
Mathias Agopian65ab4712010-07-14 17:59:35 -0700867 // check calling permissions
868 if (!settingsAllowed()) {
869 return PERMISSION_DENIED;
870 }
871
872 AutoMutex lock(mHardwareLock);
873 mHardwareStatus = AUDIO_SET_VOICE_VOLUME;
Eric Laurenta1884f92011-08-23 08:25:03 -0700874 ret = mPrimaryHardwareDev->set_voice_volume(mPrimaryHardwareDev, value);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700875 mHardwareStatus = AUDIO_HW_IDLE;
876
877 return ret;
878}
879
880status_t AudioFlinger::getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames, int output)
881{
882 status_t status;
883
884 Mutex::Autolock _l(mLock);
885
886 PlaybackThread *playbackThread = checkPlaybackThread_l(output);
887 if (playbackThread != NULL) {
888 return playbackThread->getRenderPosition(halFrames, dspFrames);
889 }
890
891 return BAD_VALUE;
892}
893
894void AudioFlinger::registerClient(const sp<IAudioFlingerClient>& client)
895{
896
897 Mutex::Autolock _l(mLock);
898
899 int pid = IPCThreadState::self()->getCallingPid();
900 if (mNotificationClients.indexOfKey(pid) < 0) {
901 sp<NotificationClient> notificationClient = new NotificationClient(this,
902 client,
903 pid);
904 LOGV("registerClient() client %p, pid %d", notificationClient.get(), pid);
905
906 mNotificationClients.add(pid, notificationClient);
907
908 sp<IBinder> binder = client->asBinder();
909 binder->linkToDeath(notificationClient);
910
911 // the config change is always sent from playback or record threads to avoid deadlock
912 // with AudioSystem::gLock
913 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
914 mPlaybackThreads.valueAt(i)->sendConfigEvent(AudioSystem::OUTPUT_OPENED);
915 }
916
917 for (size_t i = 0; i < mRecordThreads.size(); i++) {
918 mRecordThreads.valueAt(i)->sendConfigEvent(AudioSystem::INPUT_OPENED);
919 }
920 }
921}
922
923void AudioFlinger::removeNotificationClient(pid_t pid)
924{
925 Mutex::Autolock _l(mLock);
926
927 int index = mNotificationClients.indexOfKey(pid);
928 if (index >= 0) {
929 sp <NotificationClient> client = mNotificationClients.valueFor(pid);
930 LOGV("removeNotificationClient() %p, pid %d", client.get(), pid);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700931 mNotificationClients.removeItem(pid);
932 }
Marco Nelissen3a34bef2011-08-02 13:33:41 -0700933
934 LOGV("%d died, releasing its sessions", pid);
935 int num = mAudioSessionRefs.size();
936 bool removed = false;
937 for (int i = 0; i< num; i++) {
938 AudioSessionRef *ref = mAudioSessionRefs.itemAt(i);
939 LOGV(" pid %d @ %d", ref->pid, i);
940 if (ref->pid == pid) {
941 LOGV(" removing entry for pid %d session %d", pid, ref->sessionid);
942 mAudioSessionRefs.removeAt(i);
943 delete ref;
944 removed = true;
945 i--;
946 num--;
947 }
948 }
949 if (removed) {
950 purgeStaleEffects_l();
951 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700952}
953
954// audioConfigChanged_l() must be called with AudioFlinger::mLock held
955void AudioFlinger::audioConfigChanged_l(int event, int ioHandle, void *param2)
956{
957 size_t size = mNotificationClients.size();
958 for (size_t i = 0; i < size; i++) {
959 mNotificationClients.valueAt(i)->client()->ioConfigChanged(event, ioHandle, param2);
960 }
961}
962
963// removeClient_l() must be called with AudioFlinger::mLock held
964void AudioFlinger::removeClient_l(pid_t pid)
965{
966 LOGV("removeClient_l() pid %d, tid %d, calling tid %d", pid, gettid(), IPCThreadState::self()->getCallingPid());
967 mClients.removeItem(pid);
968}
969
970
971// ----------------------------------------------------------------------------
972
Eric Laurent7c7f10b2011-06-17 21:29:58 -0700973AudioFlinger::ThreadBase::ThreadBase(const sp<AudioFlinger>& audioFlinger, int id, uint32_t device)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700974 : Thread(false),
975 mAudioFlinger(audioFlinger), mSampleRate(0), mFrameCount(0), mChannelCount(0),
Eric Laurentfeb0db62011-07-22 09:04:31 -0700976 mFrameSize(1), mFormat(0), mStandby(false), mId(id), mExiting(false),
977 mDevice(device)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700978{
Eric Laurentfeb0db62011-07-22 09:04:31 -0700979 mDeathRecipient = new PMDeathRecipient(this);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700980}
981
982AudioFlinger::ThreadBase::~ThreadBase()
983{
984 mParamCond.broadcast();
985 mNewParameters.clear();
Eric Laurentfeb0db62011-07-22 09:04:31 -0700986 // do not lock the mutex in destructor
987 releaseWakeLock_l();
Eric Laurent9d18ec52011-09-27 12:07:15 -0700988 if (mPowerManager != 0) {
989 sp<IBinder> binder = mPowerManager->asBinder();
990 binder->unlinkToDeath(mDeathRecipient);
991 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700992}
993
994void AudioFlinger::ThreadBase::exit()
995{
996 // keep a strong ref on ourself so that we wont get
997 // destroyed in the middle of requestExitAndWait()
998 sp <ThreadBase> strongMe = this;
999
1000 LOGV("ThreadBase::exit");
1001 {
1002 AutoMutex lock(&mLock);
1003 mExiting = true;
1004 requestExit();
1005 mWaitWorkCV.signal();
1006 }
1007 requestExitAndWait();
1008}
1009
1010uint32_t AudioFlinger::ThreadBase::sampleRate() const
1011{
1012 return mSampleRate;
1013}
1014
1015int AudioFlinger::ThreadBase::channelCount() const
1016{
1017 return (int)mChannelCount;
1018}
1019
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07001020uint32_t AudioFlinger::ThreadBase::format() const
Mathias Agopian65ab4712010-07-14 17:59:35 -07001021{
1022 return mFormat;
1023}
1024
1025size_t AudioFlinger::ThreadBase::frameCount() const
1026{
1027 return mFrameCount;
1028}
1029
1030status_t AudioFlinger::ThreadBase::setParameters(const String8& keyValuePairs)
1031{
1032 status_t status;
1033
1034 LOGV("ThreadBase::setParameters() %s", keyValuePairs.string());
1035 Mutex::Autolock _l(mLock);
1036
1037 mNewParameters.add(keyValuePairs);
1038 mWaitWorkCV.signal();
1039 // wait condition with timeout in case the thread loop has exited
1040 // before the request could be processed
Eric Laurent60cd0a02011-09-13 11:40:21 -07001041 if (mParamCond.waitRelative(mLock, kSetParametersTimeout) == NO_ERROR) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001042 status = mParamStatus;
1043 mWaitWorkCV.signal();
1044 } else {
1045 status = TIMED_OUT;
1046 }
1047 return status;
1048}
1049
1050void AudioFlinger::ThreadBase::sendConfigEvent(int event, int param)
1051{
1052 Mutex::Autolock _l(mLock);
1053 sendConfigEvent_l(event, param);
1054}
1055
1056// sendConfigEvent_l() must be called with ThreadBase::mLock held
1057void AudioFlinger::ThreadBase::sendConfigEvent_l(int event, int param)
1058{
1059 ConfigEvent *configEvent = new ConfigEvent();
1060 configEvent->mEvent = event;
1061 configEvent->mParam = param;
1062 mConfigEvents.add(configEvent);
1063 LOGV("sendConfigEvent() num events %d event %d, param %d", mConfigEvents.size(), event, param);
1064 mWaitWorkCV.signal();
1065}
1066
1067void AudioFlinger::ThreadBase::processConfigEvents()
1068{
1069 mLock.lock();
1070 while(!mConfigEvents.isEmpty()) {
1071 LOGV("processConfigEvents() remaining events %d", mConfigEvents.size());
1072 ConfigEvent *configEvent = mConfigEvents[0];
1073 mConfigEvents.removeAt(0);
1074 // release mLock before locking AudioFlinger mLock: lock order is always
1075 // AudioFlinger then ThreadBase to avoid cross deadlock
1076 mLock.unlock();
1077 mAudioFlinger->mLock.lock();
1078 audioConfigChanged_l(configEvent->mEvent, configEvent->mParam);
1079 mAudioFlinger->mLock.unlock();
1080 delete configEvent;
1081 mLock.lock();
1082 }
1083 mLock.unlock();
1084}
1085
1086status_t AudioFlinger::ThreadBase::dumpBase(int fd, const Vector<String16>& args)
1087{
1088 const size_t SIZE = 256;
1089 char buffer[SIZE];
1090 String8 result;
1091
1092 bool locked = tryLock(mLock);
1093 if (!locked) {
1094 snprintf(buffer, SIZE, "thread %p maybe dead locked\n", this);
1095 write(fd, buffer, strlen(buffer));
1096 }
1097
1098 snprintf(buffer, SIZE, "standby: %d\n", mStandby);
1099 result.append(buffer);
1100 snprintf(buffer, SIZE, "Sample rate: %d\n", mSampleRate);
1101 result.append(buffer);
1102 snprintf(buffer, SIZE, "Frame count: %d\n", mFrameCount);
1103 result.append(buffer);
1104 snprintf(buffer, SIZE, "Channel Count: %d\n", mChannelCount);
1105 result.append(buffer);
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07001106 snprintf(buffer, SIZE, "Channel Mask: 0x%08x\n", mChannelMask);
1107 result.append(buffer);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001108 snprintf(buffer, SIZE, "Format: %d\n", mFormat);
1109 result.append(buffer);
1110 snprintf(buffer, SIZE, "Frame size: %d\n", mFrameSize);
1111 result.append(buffer);
1112
1113 snprintf(buffer, SIZE, "\nPending setParameters commands: \n");
1114 result.append(buffer);
1115 result.append(" Index Command");
1116 for (size_t i = 0; i < mNewParameters.size(); ++i) {
1117 snprintf(buffer, SIZE, "\n %02d ", i);
1118 result.append(buffer);
1119 result.append(mNewParameters[i]);
1120 }
1121
1122 snprintf(buffer, SIZE, "\n\nPending config events: \n");
1123 result.append(buffer);
1124 snprintf(buffer, SIZE, " Index event param\n");
1125 result.append(buffer);
1126 for (size_t i = 0; i < mConfigEvents.size(); i++) {
1127 snprintf(buffer, SIZE, " %02d %02d %d\n", i, mConfigEvents[i]->mEvent, mConfigEvents[i]->mParam);
1128 result.append(buffer);
1129 }
1130 result.append("\n");
1131
1132 write(fd, result.string(), result.size());
1133
1134 if (locked) {
1135 mLock.unlock();
1136 }
1137 return NO_ERROR;
1138}
1139
Eric Laurent1d2bff02011-07-24 17:49:51 -07001140status_t AudioFlinger::ThreadBase::dumpEffectChains(int fd, const Vector<String16>& args)
1141{
1142 const size_t SIZE = 256;
1143 char buffer[SIZE];
1144 String8 result;
1145
1146 snprintf(buffer, SIZE, "\n- %d Effect Chains:\n", mEffectChains.size());
1147 write(fd, buffer, strlen(buffer));
1148
1149 for (size_t i = 0; i < mEffectChains.size(); ++i) {
1150 sp<EffectChain> chain = mEffectChains[i];
1151 if (chain != 0) {
1152 chain->dump(fd, args);
1153 }
1154 }
1155 return NO_ERROR;
1156}
1157
Eric Laurentfeb0db62011-07-22 09:04:31 -07001158void AudioFlinger::ThreadBase::acquireWakeLock()
1159{
1160 Mutex::Autolock _l(mLock);
1161 acquireWakeLock_l();
1162}
1163
1164void AudioFlinger::ThreadBase::acquireWakeLock_l()
1165{
1166 if (mPowerManager == 0) {
1167 // use checkService() to avoid blocking if power service is not up yet
1168 sp<IBinder> binder =
1169 defaultServiceManager()->checkService(String16("power"));
1170 if (binder == 0) {
1171 LOGW("Thread %s cannot connect to the power manager service", mName);
1172 } else {
1173 mPowerManager = interface_cast<IPowerManager>(binder);
1174 binder->linkToDeath(mDeathRecipient);
1175 }
1176 }
1177 if (mPowerManager != 0) {
1178 sp<IBinder> binder = new BBinder();
1179 status_t status = mPowerManager->acquireWakeLock(POWERMANAGER_PARTIAL_WAKE_LOCK,
1180 binder,
1181 String16(mName));
1182 if (status == NO_ERROR) {
1183 mWakeLockToken = binder;
1184 }
1185 LOGV("acquireWakeLock_l() %s status %d", mName, status);
1186 }
1187}
1188
1189void AudioFlinger::ThreadBase::releaseWakeLock()
1190{
1191 Mutex::Autolock _l(mLock);
Eric Laurent6dbe8832011-07-28 13:59:02 -07001192 releaseWakeLock_l();
Eric Laurentfeb0db62011-07-22 09:04:31 -07001193}
1194
1195void AudioFlinger::ThreadBase::releaseWakeLock_l()
1196{
1197 if (mWakeLockToken != 0) {
1198 LOGV("releaseWakeLock_l() %s", mName);
1199 if (mPowerManager != 0) {
1200 mPowerManager->releaseWakeLock(mWakeLockToken, 0);
1201 }
1202 mWakeLockToken.clear();
1203 }
1204}
1205
1206void AudioFlinger::ThreadBase::clearPowerManager()
1207{
1208 Mutex::Autolock _l(mLock);
1209 releaseWakeLock_l();
1210 mPowerManager.clear();
1211}
1212
1213void AudioFlinger::ThreadBase::PMDeathRecipient::binderDied(const wp<IBinder>& who)
1214{
1215 sp<ThreadBase> thread = mThread.promote();
1216 if (thread != 0) {
1217 thread->clearPowerManager();
1218 }
1219 LOGW("power manager service died !!!");
1220}
Eric Laurent1d2bff02011-07-24 17:49:51 -07001221
Eric Laurent59255e42011-07-27 19:49:51 -07001222void AudioFlinger::ThreadBase::setEffectSuspended(
1223 const effect_uuid_t *type, bool suspend, int sessionId)
1224{
1225 Mutex::Autolock _l(mLock);
1226 setEffectSuspended_l(type, suspend, sessionId);
1227}
1228
1229void AudioFlinger::ThreadBase::setEffectSuspended_l(
1230 const effect_uuid_t *type, bool suspend, int sessionId)
1231{
1232 sp<EffectChain> chain;
1233 chain = getEffectChain_l(sessionId);
1234 if (chain != 0) {
1235 if (type != NULL) {
1236 chain->setEffectSuspended_l(type, suspend);
1237 } else {
1238 chain->setEffectSuspendedAll_l(suspend);
1239 }
1240 }
1241
1242 updateSuspendedSessions_l(type, suspend, sessionId);
1243}
1244
1245void AudioFlinger::ThreadBase::checkSuspendOnAddEffectChain_l(const sp<EffectChain>& chain)
1246{
1247 int index = mSuspendedSessions.indexOfKey(chain->sessionId());
1248 if (index < 0) {
1249 return;
1250 }
1251
1252 KeyedVector <int, sp<SuspendedSessionDesc> > sessionEffects =
1253 mSuspendedSessions.editValueAt(index);
1254
1255 for (size_t i = 0; i < sessionEffects.size(); i++) {
1256 sp <SuspendedSessionDesc> desc = sessionEffects.valueAt(i);
1257 for (int j = 0; j < desc->mRefCount; j++) {
1258 if (sessionEffects.keyAt(i) == EffectChain::kKeyForSuspendAll) {
1259 chain->setEffectSuspendedAll_l(true);
1260 } else {
1261 LOGV("checkSuspendOnAddEffectChain_l() suspending effects %08x",
1262 desc->mType.timeLow);
1263 chain->setEffectSuspended_l(&desc->mType, true);
1264 }
1265 }
1266 }
1267}
1268
Eric Laurent59255e42011-07-27 19:49:51 -07001269void AudioFlinger::ThreadBase::updateSuspendedSessions_l(const effect_uuid_t *type,
1270 bool suspend,
1271 int sessionId)
1272{
1273 int index = mSuspendedSessions.indexOfKey(sessionId);
1274
1275 KeyedVector <int, sp<SuspendedSessionDesc> > sessionEffects;
1276
1277 if (suspend) {
1278 if (index >= 0) {
1279 sessionEffects = mSuspendedSessions.editValueAt(index);
1280 } else {
1281 mSuspendedSessions.add(sessionId, sessionEffects);
1282 }
1283 } else {
1284 if (index < 0) {
1285 return;
1286 }
1287 sessionEffects = mSuspendedSessions.editValueAt(index);
1288 }
1289
1290
1291 int key = EffectChain::kKeyForSuspendAll;
1292 if (type != NULL) {
1293 key = type->timeLow;
1294 }
1295 index = sessionEffects.indexOfKey(key);
1296
1297 sp <SuspendedSessionDesc> desc;
1298 if (suspend) {
1299 if (index >= 0) {
1300 desc = sessionEffects.valueAt(index);
1301 } else {
1302 desc = new SuspendedSessionDesc();
1303 if (type != NULL) {
1304 memcpy(&desc->mType, type, sizeof(effect_uuid_t));
1305 }
1306 sessionEffects.add(key, desc);
1307 LOGV("updateSuspendedSessions_l() suspend adding effect %08x", key);
1308 }
1309 desc->mRefCount++;
1310 } else {
1311 if (index < 0) {
1312 return;
1313 }
1314 desc = sessionEffects.valueAt(index);
1315 if (--desc->mRefCount == 0) {
1316 LOGV("updateSuspendedSessions_l() restore removing effect %08x", key);
1317 sessionEffects.removeItemsAt(index);
1318 if (sessionEffects.isEmpty()) {
1319 LOGV("updateSuspendedSessions_l() restore removing session %d",
1320 sessionId);
1321 mSuspendedSessions.removeItem(sessionId);
1322 }
1323 }
1324 }
1325 if (!sessionEffects.isEmpty()) {
1326 mSuspendedSessions.replaceValueFor(sessionId, sessionEffects);
1327 }
1328}
1329
1330void AudioFlinger::ThreadBase::checkSuspendOnEffectEnabled(const sp<EffectModule>& effect,
1331 bool enabled,
1332 int sessionId)
1333{
1334 Mutex::Autolock _l(mLock);
Eric Laurenta85a74a2011-10-19 11:44:54 -07001335 checkSuspendOnEffectEnabled_l(effect, enabled, sessionId);
1336}
Eric Laurent59255e42011-07-27 19:49:51 -07001337
Eric Laurenta85a74a2011-10-19 11:44:54 -07001338void AudioFlinger::ThreadBase::checkSuspendOnEffectEnabled_l(const sp<EffectModule>& effect,
1339 bool enabled,
1340 int sessionId)
1341{
Eric Laurentdb7c0792011-08-10 10:37:50 -07001342 if (mType != RECORD) {
1343 // suspend all effects in AUDIO_SESSION_OUTPUT_MIX when enabling any effect on
1344 // another session. This gives the priority to well behaved effect control panels
1345 // and applications not using global effects.
1346 if (sessionId != AUDIO_SESSION_OUTPUT_MIX) {
1347 setEffectSuspended_l(NULL, enabled, AUDIO_SESSION_OUTPUT_MIX);
1348 }
1349 }
Eric Laurent59255e42011-07-27 19:49:51 -07001350
1351 sp<EffectChain> chain = getEffectChain_l(sessionId);
1352 if (chain != 0) {
1353 chain->checkSuspendOnEffectEnabled(effect, enabled);
1354 }
1355}
1356
Mathias Agopian65ab4712010-07-14 17:59:35 -07001357// ----------------------------------------------------------------------------
1358
Eric Laurent7c7f10b2011-06-17 21:29:58 -07001359AudioFlinger::PlaybackThread::PlaybackThread(const sp<AudioFlinger>& audioFlinger,
1360 AudioStreamOut* output,
1361 int id,
1362 uint32_t device)
1363 : ThreadBase(audioFlinger, id, device),
Mathias Agopian65ab4712010-07-14 17:59:35 -07001364 mMixBuffer(0), mSuspended(0), mBytesWritten(0), mOutput(output),
Eric Laurent7c7f10b2011-06-17 21:29:58 -07001365 mLastWriteTime(0), mNumWrites(0), mNumDelayedWrites(0), mInWrite(false)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001366{
Eric Laurentfeb0db62011-07-22 09:04:31 -07001367 snprintf(mName, kNameLength, "AudioOut_%d", id);
1368
Mathias Agopian65ab4712010-07-14 17:59:35 -07001369 readOutputParameters();
1370
1371 mMasterVolume = mAudioFlinger->masterVolume();
1372 mMasterMute = mAudioFlinger->masterMute();
1373
Dima Zavinfce7a472011-04-19 22:30:36 -07001374 for (int stream = 0; stream < AUDIO_STREAM_CNT; stream++) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001375 mStreamTypes[stream].volume = mAudioFlinger->streamVolumeInternal(stream);
1376 mStreamTypes[stream].mute = mAudioFlinger->streamMute(stream);
Eric Laurent9f6530f2011-08-30 10:18:54 -07001377 mStreamTypes[stream].valid = true;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001378 }
1379}
1380
1381AudioFlinger::PlaybackThread::~PlaybackThread()
1382{
1383 delete [] mMixBuffer;
1384}
1385
1386status_t AudioFlinger::PlaybackThread::dump(int fd, const Vector<String16>& args)
1387{
1388 dumpInternals(fd, args);
1389 dumpTracks(fd, args);
1390 dumpEffectChains(fd, args);
1391 return NO_ERROR;
1392}
1393
1394status_t AudioFlinger::PlaybackThread::dumpTracks(int fd, const Vector<String16>& args)
1395{
1396 const size_t SIZE = 256;
1397 char buffer[SIZE];
1398 String8 result;
1399
1400 snprintf(buffer, SIZE, "Output thread %p tracks\n", this);
1401 result.append(buffer);
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07001402 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 -07001403 for (size_t i = 0; i < mTracks.size(); ++i) {
1404 sp<Track> track = mTracks[i];
1405 if (track != 0) {
1406 track->dump(buffer, SIZE);
1407 result.append(buffer);
1408 }
1409 }
1410
1411 snprintf(buffer, SIZE, "Output thread %p active tracks\n", this);
1412 result.append(buffer);
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07001413 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 -07001414 for (size_t i = 0; i < mActiveTracks.size(); ++i) {
1415 wp<Track> wTrack = mActiveTracks[i];
1416 if (wTrack != 0) {
1417 sp<Track> track = wTrack.promote();
1418 if (track != 0) {
1419 track->dump(buffer, SIZE);
1420 result.append(buffer);
1421 }
1422 }
1423 }
1424 write(fd, result.string(), result.size());
1425 return NO_ERROR;
1426}
1427
Mathias Agopian65ab4712010-07-14 17:59:35 -07001428status_t AudioFlinger::PlaybackThread::dumpInternals(int fd, const Vector<String16>& args)
1429{
1430 const size_t SIZE = 256;
1431 char buffer[SIZE];
1432 String8 result;
1433
1434 snprintf(buffer, SIZE, "\nOutput thread %p internals\n", this);
1435 result.append(buffer);
1436 snprintf(buffer, SIZE, "last write occurred (msecs): %llu\n", ns2ms(systemTime() - mLastWriteTime));
1437 result.append(buffer);
1438 snprintf(buffer, SIZE, "total writes: %d\n", mNumWrites);
1439 result.append(buffer);
1440 snprintf(buffer, SIZE, "delayed writes: %d\n", mNumDelayedWrites);
1441 result.append(buffer);
1442 snprintf(buffer, SIZE, "blocked in write: %d\n", mInWrite);
1443 result.append(buffer);
1444 snprintf(buffer, SIZE, "suspend count: %d\n", mSuspended);
1445 result.append(buffer);
1446 snprintf(buffer, SIZE, "mix buffer : %p\n", mMixBuffer);
1447 result.append(buffer);
1448 write(fd, result.string(), result.size());
1449
1450 dumpBase(fd, args);
1451
1452 return NO_ERROR;
1453}
1454
1455// Thread virtuals
1456status_t AudioFlinger::PlaybackThread::readyToRun()
1457{
Eric Laurentb8ba0a92011-08-07 16:32:26 -07001458 status_t status = initCheck();
1459 if (status == NO_ERROR) {
1460 LOGI("AudioFlinger's thread %p ready to run", this);
1461 } else {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001462 LOGE("No working audio driver found.");
Mathias Agopian65ab4712010-07-14 17:59:35 -07001463 }
Eric Laurentb8ba0a92011-08-07 16:32:26 -07001464 return status;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001465}
1466
1467void AudioFlinger::PlaybackThread::onFirstRef()
1468{
Eric Laurentfeb0db62011-07-22 09:04:31 -07001469 run(mName, ANDROID_PRIORITY_URGENT_AUDIO);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001470}
1471
1472// PlaybackThread::createTrack_l() must be called with AudioFlinger::mLock held
1473sp<AudioFlinger::PlaybackThread::Track> AudioFlinger::PlaybackThread::createTrack_l(
1474 const sp<AudioFlinger::Client>& client,
1475 int streamType,
1476 uint32_t sampleRate,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07001477 uint32_t format,
1478 uint32_t channelMask,
Mathias Agopian65ab4712010-07-14 17:59:35 -07001479 int frameCount,
1480 const sp<IMemory>& sharedBuffer,
1481 int sessionId,
1482 status_t *status)
1483{
1484 sp<Track> track;
1485 status_t lStatus;
1486
1487 if (mType == DIRECT) {
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07001488 if ((format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM) {
1489 if (sampleRate != mSampleRate || format != mFormat || channelMask != mChannelMask) {
1490 LOGE("createTrack_l() Bad parameter: sampleRate %d format %d, channelMask 0x%08x \""
1491 "for output %p with format %d",
1492 sampleRate, format, channelMask, mOutput, mFormat);
1493 lStatus = BAD_VALUE;
1494 goto Exit;
1495 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07001496 }
1497 } else {
1498 // Resampler implementation limits input sampling rate to 2 x output sampling rate.
1499 if (sampleRate > mSampleRate*2) {
1500 LOGE("Sample rate out of range: %d mSampleRate %d", sampleRate, mSampleRate);
1501 lStatus = BAD_VALUE;
1502 goto Exit;
1503 }
1504 }
1505
Eric Laurent7c7f10b2011-06-17 21:29:58 -07001506 lStatus = initCheck();
1507 if (lStatus != NO_ERROR) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001508 LOGE("Audio driver not initialized.");
Mathias Agopian65ab4712010-07-14 17:59:35 -07001509 goto Exit;
1510 }
1511
1512 { // scope for mLock
1513 Mutex::Autolock _l(mLock);
Eric Laurentde070132010-07-13 04:45:46 -07001514
1515 // all tracks in same audio session must share the same routing strategy otherwise
1516 // conflicts will happen when tracks are moved from one output to another by audio policy
1517 // manager
1518 uint32_t strategy =
Dima Zavinfce7a472011-04-19 22:30:36 -07001519 AudioSystem::getStrategyForStream((audio_stream_type_t)streamType);
Eric Laurentde070132010-07-13 04:45:46 -07001520 for (size_t i = 0; i < mTracks.size(); ++i) {
1521 sp<Track> t = mTracks[i];
1522 if (t != 0) {
1523 if (sessionId == t->sessionId() &&
Dima Zavinfce7a472011-04-19 22:30:36 -07001524 strategy != AudioSystem::getStrategyForStream((audio_stream_type_t)t->type())) {
Eric Laurentde070132010-07-13 04:45:46 -07001525 lStatus = BAD_VALUE;
1526 goto Exit;
1527 }
1528 }
1529 }
1530
Mathias Agopian65ab4712010-07-14 17:59:35 -07001531 track = new Track(this, client, streamType, sampleRate, format,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07001532 channelMask, frameCount, sharedBuffer, sessionId);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001533 if (track->getCblk() == NULL || track->name() < 0) {
1534 lStatus = NO_MEMORY;
1535 goto Exit;
1536 }
1537 mTracks.add(track);
1538
1539 sp<EffectChain> chain = getEffectChain_l(sessionId);
1540 if (chain != 0) {
1541 LOGV("createTrack_l() setting main buffer %p", chain->inBuffer());
1542 track->setMainBuffer(chain->inBuffer());
Dima Zavinfce7a472011-04-19 22:30:36 -07001543 chain->setStrategy(AudioSystem::getStrategyForStream((audio_stream_type_t)track->type()));
Eric Laurentb469b942011-05-09 12:09:06 -07001544 chain->incTrackCnt();
Mathias Agopian65ab4712010-07-14 17:59:35 -07001545 }
Eric Laurent9f6530f2011-08-30 10:18:54 -07001546
1547 // invalidate track immediately if the stream type was moved to another thread since
1548 // createTrack() was called by the client process.
1549 if (!mStreamTypes[streamType].valid) {
1550 LOGW("createTrack_l() on thread %p: invalidating track on stream %d",
1551 this, streamType);
1552 android_atomic_or(CBLK_INVALID_ON, &track->mCblk->flags);
1553 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07001554 }
1555 lStatus = NO_ERROR;
1556
1557Exit:
1558 if(status) {
1559 *status = lStatus;
1560 }
1561 return track;
1562}
1563
1564uint32_t AudioFlinger::PlaybackThread::latency() const
1565{
Eric Laurentb8ba0a92011-08-07 16:32:26 -07001566 Mutex::Autolock _l(mLock);
1567 if (initCheck() == NO_ERROR) {
Dima Zavin799a70e2011-04-18 16:57:27 -07001568 return mOutput->stream->get_latency(mOutput->stream);
Eric Laurentb8ba0a92011-08-07 16:32:26 -07001569 } else {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001570 return 0;
1571 }
1572}
1573
1574status_t AudioFlinger::PlaybackThread::setMasterVolume(float value)
1575{
Mathias Agopian65ab4712010-07-14 17:59:35 -07001576 mMasterVolume = value;
1577 return NO_ERROR;
1578}
1579
1580status_t AudioFlinger::PlaybackThread::setMasterMute(bool muted)
1581{
Mathias Agopian65ab4712010-07-14 17:59:35 -07001582 mMasterMute = muted;
1583 return NO_ERROR;
1584}
1585
1586float AudioFlinger::PlaybackThread::masterVolume() const
1587{
1588 return mMasterVolume;
1589}
1590
1591bool AudioFlinger::PlaybackThread::masterMute() const
1592{
1593 return mMasterMute;
1594}
1595
1596status_t AudioFlinger::PlaybackThread::setStreamVolume(int stream, float value)
1597{
Mathias Agopian65ab4712010-07-14 17:59:35 -07001598 mStreamTypes[stream].volume = value;
1599 return NO_ERROR;
1600}
1601
1602status_t AudioFlinger::PlaybackThread::setStreamMute(int stream, bool muted)
1603{
Mathias Agopian65ab4712010-07-14 17:59:35 -07001604 mStreamTypes[stream].mute = muted;
1605 return NO_ERROR;
1606}
1607
1608float AudioFlinger::PlaybackThread::streamVolume(int stream) const
1609{
1610 return mStreamTypes[stream].volume;
1611}
1612
1613bool AudioFlinger::PlaybackThread::streamMute(int stream) const
1614{
1615 return mStreamTypes[stream].mute;
1616}
1617
Mathias Agopian65ab4712010-07-14 17:59:35 -07001618// addTrack_l() must be called with ThreadBase::mLock held
1619status_t AudioFlinger::PlaybackThread::addTrack_l(const sp<Track>& track)
1620{
1621 status_t status = ALREADY_EXISTS;
1622
1623 // set retry count for buffer fill
1624 track->mRetryCount = kMaxTrackStartupRetries;
1625 if (mActiveTracks.indexOf(track) < 0) {
1626 // the track is newly added, make sure it fills up all its
1627 // buffers before playing. This is to ensure the client will
1628 // effectively get the latency it requested.
1629 track->mFillingUpStatus = Track::FS_FILLING;
1630 track->mResetDone = false;
1631 mActiveTracks.add(track);
1632 if (track->mainBuffer() != mMixBuffer) {
1633 sp<EffectChain> chain = getEffectChain_l(track->sessionId());
1634 if (chain != 0) {
1635 LOGV("addTrack_l() starting track on chain %p for session %d", chain.get(), track->sessionId());
Eric Laurentb469b942011-05-09 12:09:06 -07001636 chain->incActiveTrackCnt();
Mathias Agopian65ab4712010-07-14 17:59:35 -07001637 }
1638 }
1639
1640 status = NO_ERROR;
1641 }
1642
1643 LOGV("mWaitWorkCV.broadcast");
1644 mWaitWorkCV.broadcast();
1645
1646 return status;
1647}
1648
1649// destroyTrack_l() must be called with ThreadBase::mLock held
1650void AudioFlinger::PlaybackThread::destroyTrack_l(const sp<Track>& track)
1651{
1652 track->mState = TrackBase::TERMINATED;
1653 if (mActiveTracks.indexOf(track) < 0) {
Eric Laurentb469b942011-05-09 12:09:06 -07001654 removeTrack_l(track);
1655 }
1656}
1657
1658void AudioFlinger::PlaybackThread::removeTrack_l(const sp<Track>& track)
1659{
1660 mTracks.remove(track);
1661 deleteTrackName_l(track->name());
1662 sp<EffectChain> chain = getEffectChain_l(track->sessionId());
1663 if (chain != 0) {
1664 chain->decTrackCnt();
Mathias Agopian65ab4712010-07-14 17:59:35 -07001665 }
1666}
1667
1668String8 AudioFlinger::PlaybackThread::getParameters(const String8& keys)
1669{
Eric Laurentb8ba0a92011-08-07 16:32:26 -07001670 String8 out_s8 = String8("");
Dima Zavinfce7a472011-04-19 22:30:36 -07001671 char *s;
1672
Eric Laurentb8ba0a92011-08-07 16:32:26 -07001673 Mutex::Autolock _l(mLock);
1674 if (initCheck() != NO_ERROR) {
1675 return out_s8;
1676 }
1677
Dima Zavin799a70e2011-04-18 16:57:27 -07001678 s = mOutput->stream->common.get_parameters(&mOutput->stream->common, keys.string());
Dima Zavinfce7a472011-04-19 22:30:36 -07001679 out_s8 = String8(s);
1680 free(s);
1681 return out_s8;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001682}
1683
Eric Laurentb8ba0a92011-08-07 16:32:26 -07001684// audioConfigChanged_l() must be called with AudioFlinger::mLock held
Mathias Agopian65ab4712010-07-14 17:59:35 -07001685void AudioFlinger::PlaybackThread::audioConfigChanged_l(int event, int param) {
1686 AudioSystem::OutputDescriptor desc;
1687 void *param2 = 0;
1688
1689 LOGV("PlaybackThread::audioConfigChanged_l, thread %p, event %d, param %d", this, event, param);
1690
1691 switch (event) {
1692 case AudioSystem::OUTPUT_OPENED:
1693 case AudioSystem::OUTPUT_CONFIG_CHANGED:
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07001694 desc.channels = mChannelMask;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001695 desc.samplingRate = mSampleRate;
1696 desc.format = mFormat;
1697 desc.frameCount = mFrameCount;
1698 desc.latency = latency();
1699 param2 = &desc;
1700 break;
1701
1702 case AudioSystem::STREAM_CONFIG_CHANGED:
1703 param2 = &param;
1704 case AudioSystem::OUTPUT_CLOSED:
1705 default:
1706 break;
1707 }
1708 mAudioFlinger->audioConfigChanged_l(event, mId, param2);
1709}
1710
1711void AudioFlinger::PlaybackThread::readOutputParameters()
1712{
Dima Zavin799a70e2011-04-18 16:57:27 -07001713 mSampleRate = mOutput->stream->common.get_sample_rate(&mOutput->stream->common);
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07001714 mChannelMask = mOutput->stream->common.get_channels(&mOutput->stream->common);
1715 mChannelCount = (uint16_t)popcount(mChannelMask);
Dima Zavin799a70e2011-04-18 16:57:27 -07001716 mFormat = mOutput->stream->common.get_format(&mOutput->stream->common);
1717 mFrameSize = (uint16_t)audio_stream_frame_size(&mOutput->stream->common);
1718 mFrameCount = mOutput->stream->common.get_buffer_size(&mOutput->stream->common) / mFrameSize;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001719
1720 // FIXME - Current mixer implementation only supports stereo output: Always
1721 // Allocate a stereo buffer even if HW output is mono.
1722 if (mMixBuffer != NULL) delete[] mMixBuffer;
1723 mMixBuffer = new int16_t[mFrameCount * 2];
1724 memset(mMixBuffer, 0, mFrameCount * 2 * sizeof(int16_t));
1725
Eric Laurentde070132010-07-13 04:45:46 -07001726 // force reconfiguration of effect chains and engines to take new buffer size and audio
1727 // parameters into account
1728 // Note that mLock is not held when readOutputParameters() is called from the constructor
1729 // but in this case nothing is done below as no audio sessions have effect yet so it doesn't
1730 // matter.
1731 // create a copy of mEffectChains as calling moveEffectChain_l() can reorder some effect chains
1732 Vector< sp<EffectChain> > effectChains = mEffectChains;
1733 for (size_t i = 0; i < effectChains.size(); i ++) {
Eric Laurent39e94f82010-07-28 01:32:47 -07001734 mAudioFlinger->moveEffectChain_l(effectChains[i]->sessionId(), this, this, false);
Eric Laurentde070132010-07-13 04:45:46 -07001735 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07001736}
1737
1738status_t AudioFlinger::PlaybackThread::getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames)
1739{
1740 if (halFrames == 0 || dspFrames == 0) {
1741 return BAD_VALUE;
1742 }
Eric Laurentb8ba0a92011-08-07 16:32:26 -07001743 Mutex::Autolock _l(mLock);
Eric Laurent7c7f10b2011-06-17 21:29:58 -07001744 if (initCheck() != NO_ERROR) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001745 return INVALID_OPERATION;
1746 }
Dima Zavin799a70e2011-04-18 16:57:27 -07001747 *halFrames = mBytesWritten / audio_stream_frame_size(&mOutput->stream->common);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001748
Dima Zavin799a70e2011-04-18 16:57:27 -07001749 return mOutput->stream->get_render_position(mOutput->stream, dspFrames);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001750}
1751
Eric Laurent39e94f82010-07-28 01:32:47 -07001752uint32_t AudioFlinger::PlaybackThread::hasAudioSession(int sessionId)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001753{
1754 Mutex::Autolock _l(mLock);
Eric Laurent39e94f82010-07-28 01:32:47 -07001755 uint32_t result = 0;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001756 if (getEffectChain_l(sessionId) != 0) {
Eric Laurent39e94f82010-07-28 01:32:47 -07001757 result = EFFECT_SESSION;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001758 }
1759
1760 for (size_t i = 0; i < mTracks.size(); ++i) {
1761 sp<Track> track = mTracks[i];
Eric Laurentde070132010-07-13 04:45:46 -07001762 if (sessionId == track->sessionId() &&
1763 !(track->mCblk->flags & CBLK_INVALID_MSK)) {
Eric Laurent39e94f82010-07-28 01:32:47 -07001764 result |= TRACK_SESSION;
1765 break;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001766 }
1767 }
1768
Eric Laurent39e94f82010-07-28 01:32:47 -07001769 return result;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001770}
1771
Eric Laurentde070132010-07-13 04:45:46 -07001772uint32_t AudioFlinger::PlaybackThread::getStrategyForSession_l(int sessionId)
1773{
Dima Zavinfce7a472011-04-19 22:30:36 -07001774 // session AUDIO_SESSION_OUTPUT_MIX is placed in same strategy as MUSIC stream so that
Eric Laurentde070132010-07-13 04:45:46 -07001775 // it is moved to correct output by audio policy manager when A2DP is connected or disconnected
Dima Zavinfce7a472011-04-19 22:30:36 -07001776 if (sessionId == AUDIO_SESSION_OUTPUT_MIX) {
1777 return AudioSystem::getStrategyForStream(AUDIO_STREAM_MUSIC);
Eric Laurentde070132010-07-13 04:45:46 -07001778 }
1779 for (size_t i = 0; i < mTracks.size(); i++) {
1780 sp<Track> track = mTracks[i];
1781 if (sessionId == track->sessionId() &&
1782 !(track->mCblk->flags & CBLK_INVALID_MSK)) {
Dima Zavinfce7a472011-04-19 22:30:36 -07001783 return AudioSystem::getStrategyForStream((audio_stream_type_t) track->type());
Eric Laurentde070132010-07-13 04:45:46 -07001784 }
1785 }
Dima Zavinfce7a472011-04-19 22:30:36 -07001786 return AudioSystem::getStrategyForStream(AUDIO_STREAM_MUSIC);
Eric Laurentde070132010-07-13 04:45:46 -07001787}
1788
Mathias Agopian65ab4712010-07-14 17:59:35 -07001789
Eric Laurentb8ba0a92011-08-07 16:32:26 -07001790AudioFlinger::AudioStreamOut* AudioFlinger::PlaybackThread::getOutput()
1791{
1792 Mutex::Autolock _l(mLock);
1793 return mOutput;
1794}
1795
1796AudioFlinger::AudioStreamOut* AudioFlinger::PlaybackThread::clearOutput()
1797{
1798 Mutex::Autolock _l(mLock);
1799 AudioStreamOut *output = mOutput;
1800 mOutput = NULL;
1801 return output;
1802}
1803
1804// this method must always be called either with ThreadBase mLock held or inside the thread loop
1805audio_stream_t* AudioFlinger::PlaybackThread::stream()
1806{
1807 if (mOutput == NULL) {
1808 return NULL;
1809 }
1810 return &mOutput->stream->common;
1811}
1812
Mathias Agopian65ab4712010-07-14 17:59:35 -07001813// ----------------------------------------------------------------------------
1814
Dima Zavin799a70e2011-04-18 16:57:27 -07001815AudioFlinger::MixerThread::MixerThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id, uint32_t device)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001816 : PlaybackThread(audioFlinger, output, id, device),
1817 mAudioMixer(0)
1818{
Eric Laurent7c7f10b2011-06-17 21:29:58 -07001819 mType = ThreadBase::MIXER;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001820 mAudioMixer = new AudioMixer(mFrameCount, mSampleRate);
1821
1822 // FIXME - Current mixer implementation only supports stereo output
1823 if (mChannelCount == 1) {
1824 LOGE("Invalid audio hardware channel count");
1825 }
1826}
1827
1828AudioFlinger::MixerThread::~MixerThread()
1829{
1830 delete mAudioMixer;
1831}
1832
1833bool AudioFlinger::MixerThread::threadLoop()
1834{
1835 Vector< sp<Track> > tracksToRemove;
1836 uint32_t mixerStatus = MIXER_IDLE;
1837 nsecs_t standbyTime = systemTime();
1838 size_t mixBufferSize = mFrameCount * mFrameSize;
1839 // FIXME: Relaxed timing because of a certain device that can't meet latency
1840 // Should be reduced to 2x after the vendor fixes the driver issue
Eric Laurent5c4e8182011-10-18 15:42:27 -07001841 // increase threshold again due to low power audio mode. The way this warning threshold is
1842 // calculated and its usefulness should be reconsidered anyway.
1843 nsecs_t maxPeriod = seconds(mFrameCount) / mSampleRate * 15;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001844 nsecs_t lastWarning = 0;
1845 bool longStandbyExit = false;
1846 uint32_t activeSleepTime = activeSleepTimeUs();
1847 uint32_t idleSleepTime = idleSleepTimeUs();
1848 uint32_t sleepTime = idleSleepTime;
1849 Vector< sp<EffectChain> > effectChains;
Glenn Kasten4d8d0c32011-07-08 15:26:12 -07001850#ifdef DEBUG_CPU_USAGE
1851 ThreadCpuUsage cpu;
1852 const CentralTendencyStatistics& stats = cpu.statistics();
1853#endif
Mathias Agopian65ab4712010-07-14 17:59:35 -07001854
Eric Laurentfeb0db62011-07-22 09:04:31 -07001855 acquireWakeLock();
1856
Mathias Agopian65ab4712010-07-14 17:59:35 -07001857 while (!exitPending())
1858 {
Glenn Kasten4d8d0c32011-07-08 15:26:12 -07001859#ifdef DEBUG_CPU_USAGE
1860 cpu.sampleAndEnable();
1861 unsigned n = stats.n();
1862 // cpu.elapsed() is expensive, so don't call it every loop
1863 if ((n & 127) == 1) {
1864 long long elapsed = cpu.elapsed();
1865 if (elapsed >= DEBUG_CPU_USAGE * 1000000000LL) {
1866 double perLoop = elapsed / (double) n;
1867 double perLoop100 = perLoop * 0.01;
1868 double mean = stats.mean();
1869 double stddev = stats.stddev();
1870 double minimum = stats.minimum();
1871 double maximum = stats.maximum();
1872 cpu.resetStatistics();
1873 LOGI("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",
1874 elapsed * .000000001, n, perLoop * .000001,
1875 mean * .001,
1876 stddev * .001,
1877 minimum * .001,
1878 maximum * .001,
1879 mean / perLoop100,
1880 stddev / perLoop100,
1881 minimum / perLoop100,
1882 maximum / perLoop100);
1883 }
1884 }
1885#endif
Mathias Agopian65ab4712010-07-14 17:59:35 -07001886 processConfigEvents();
1887
1888 mixerStatus = MIXER_IDLE;
1889 { // scope for mLock
1890
1891 Mutex::Autolock _l(mLock);
1892
1893 if (checkForNewParameters_l()) {
1894 mixBufferSize = mFrameCount * mFrameSize;
1895 // FIXME: Relaxed timing because of a certain device that can't meet latency
1896 // Should be reduced to 2x after the vendor fixes the driver issue
Eric Laurent5c4e8182011-10-18 15:42:27 -07001897 // increase threshold again due to low power audio mode. The way this warning
1898 // threshold is calculated and its usefulness should be reconsidered anyway.
1899 maxPeriod = seconds(mFrameCount) / mSampleRate * 15;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001900 activeSleepTime = activeSleepTimeUs();
1901 idleSleepTime = idleSleepTimeUs();
1902 }
1903
1904 const SortedVector< wp<Track> >& activeTracks = mActiveTracks;
1905
1906 // put audio hardware into standby after short delay
1907 if UNLIKELY((!activeTracks.size() && systemTime() > standbyTime) ||
1908 mSuspended) {
1909 if (!mStandby) {
1910 LOGV("Audio hardware entering standby, mixer %p, mSuspended %d\n", this, mSuspended);
Dima Zavin799a70e2011-04-18 16:57:27 -07001911 mOutput->stream->common.standby(&mOutput->stream->common);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001912 mStandby = true;
1913 mBytesWritten = 0;
1914 }
1915
1916 if (!activeTracks.size() && mConfigEvents.isEmpty()) {
1917 // we're about to wait, flush the binder command buffer
1918 IPCThreadState::self()->flushCommands();
1919
1920 if (exitPending()) break;
1921
Eric Laurentfeb0db62011-07-22 09:04:31 -07001922 releaseWakeLock_l();
Mathias Agopian65ab4712010-07-14 17:59:35 -07001923 // wait until we have something to do...
1924 LOGV("MixerThread %p TID %d going to sleep\n", this, gettid());
1925 mWaitWorkCV.wait(mLock);
1926 LOGV("MixerThread %p TID %d waking up\n", this, gettid());
Eric Laurentfeb0db62011-07-22 09:04:31 -07001927 acquireWakeLock_l();
Mathias Agopian65ab4712010-07-14 17:59:35 -07001928
1929 if (mMasterMute == false) {
1930 char value[PROPERTY_VALUE_MAX];
1931 property_get("ro.audio.silent", value, "0");
1932 if (atoi(value)) {
1933 LOGD("Silence is golden");
1934 setMasterMute(true);
1935 }
1936 }
1937
1938 standbyTime = systemTime() + kStandbyTimeInNsecs;
1939 sleepTime = idleSleepTime;
1940 continue;
1941 }
1942 }
1943
1944 mixerStatus = prepareTracks_l(activeTracks, &tracksToRemove);
1945
1946 // prevent any changes in effect chain list and in each effect chain
1947 // during mixing and effect process as the audio buffers could be deleted
1948 // or modified if an effect is created or deleted
Eric Laurentde070132010-07-13 04:45:46 -07001949 lockEffectChains_l(effectChains);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001950 }
1951
1952 if (LIKELY(mixerStatus == MIXER_TRACKS_READY)) {
1953 // mix buffers...
1954 mAudioMixer->process();
1955 sleepTime = 0;
1956 standbyTime = systemTime() + kStandbyTimeInNsecs;
1957 //TODO: delay standby when effects have a tail
1958 } else {
1959 // If no tracks are ready, sleep once for the duration of an output
1960 // buffer size, then write 0s to the output
1961 if (sleepTime == 0) {
1962 if (mixerStatus == MIXER_TRACKS_ENABLED) {
1963 sleepTime = activeSleepTime;
1964 } else {
1965 sleepTime = idleSleepTime;
1966 }
1967 } else if (mBytesWritten != 0 ||
1968 (mixerStatus == MIXER_TRACKS_ENABLED && longStandbyExit)) {
1969 memset (mMixBuffer, 0, mixBufferSize);
1970 sleepTime = 0;
1971 LOGV_IF((mBytesWritten == 0 && (mixerStatus == MIXER_TRACKS_ENABLED && longStandbyExit)), "anticipated start");
1972 }
1973 // TODO add standby time extension fct of effect tail
1974 }
1975
1976 if (mSuspended) {
Eric Laurent25cbe0e2010-08-18 18:13:17 -07001977 sleepTime = suspendSleepTimeUs();
Mathias Agopian65ab4712010-07-14 17:59:35 -07001978 }
1979 // sleepTime == 0 means we must write to audio hardware
1980 if (sleepTime == 0) {
1981 for (size_t i = 0; i < effectChains.size(); i ++) {
1982 effectChains[i]->process_l();
1983 }
1984 // enable changes in effect chain
Eric Laurentde070132010-07-13 04:45:46 -07001985 unlockEffectChains(effectChains);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001986 mLastWriteTime = systemTime();
1987 mInWrite = true;
1988 mBytesWritten += mixBufferSize;
1989
Dima Zavin799a70e2011-04-18 16:57:27 -07001990 int bytesWritten = (int)mOutput->stream->write(mOutput->stream, mMixBuffer, mixBufferSize);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001991 if (bytesWritten < 0) mBytesWritten -= mixBufferSize;
1992 mNumWrites++;
1993 mInWrite = false;
1994 nsecs_t now = systemTime();
1995 nsecs_t delta = now - mLastWriteTime;
Eric Laurent5c4e8182011-10-18 15:42:27 -07001996 if (!mStandby && delta > maxPeriod) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001997 mNumDelayedWrites++;
1998 if ((now - lastWarning) > kWarningThrottle) {
1999 LOGW("write blocked for %llu msecs, %d delayed writes, thread %p",
2000 ns2ms(delta), mNumDelayedWrites, this);
2001 lastWarning = now;
2002 }
2003 if (mStandby) {
2004 longStandbyExit = true;
2005 }
2006 }
2007 mStandby = false;
2008 } else {
2009 // enable changes in effect chain
Eric Laurentde070132010-07-13 04:45:46 -07002010 unlockEffectChains(effectChains);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002011 usleep(sleepTime);
2012 }
2013
2014 // finally let go of all our tracks, without the lock held
2015 // since we can't guarantee the destructors won't acquire that
2016 // same lock.
2017 tracksToRemove.clear();
2018
2019 // Effect chains will be actually deleted here if they were removed from
2020 // mEffectChains list during mixing or effects processing
2021 effectChains.clear();
2022 }
2023
2024 if (!mStandby) {
Dima Zavin799a70e2011-04-18 16:57:27 -07002025 mOutput->stream->common.standby(&mOutput->stream->common);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002026 }
2027
Eric Laurentfeb0db62011-07-22 09:04:31 -07002028 releaseWakeLock();
2029
Mathias Agopian65ab4712010-07-14 17:59:35 -07002030 LOGV("MixerThread %p exiting", this);
2031 return false;
2032}
2033
2034// prepareTracks_l() must be called with ThreadBase::mLock held
2035uint32_t AudioFlinger::MixerThread::prepareTracks_l(const SortedVector< wp<Track> >& activeTracks, Vector< sp<Track> > *tracksToRemove)
2036{
2037
2038 uint32_t mixerStatus = MIXER_IDLE;
2039 // find out which tracks need to be processed
2040 size_t count = activeTracks.size();
2041 size_t mixedTracks = 0;
2042 size_t tracksWithEffect = 0;
2043
2044 float masterVolume = mMasterVolume;
2045 bool masterMute = mMasterMute;
2046
Eric Laurent571d49c2010-08-11 05:20:11 -07002047 if (masterMute) {
2048 masterVolume = 0;
2049 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07002050 // Delegate master volume control to effect in output mix effect chain if needed
Dima Zavinfce7a472011-04-19 22:30:36 -07002051 sp<EffectChain> chain = getEffectChain_l(AUDIO_SESSION_OUTPUT_MIX);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002052 if (chain != 0) {
Eric Laurent571d49c2010-08-11 05:20:11 -07002053 uint32_t v = (uint32_t)(masterVolume * (1 << 24));
Eric Laurentcab11242010-07-15 12:50:15 -07002054 chain->setVolume_l(&v, &v);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002055 masterVolume = (float)((v + (1 << 23)) >> 24);
2056 chain.clear();
2057 }
2058
2059 for (size_t i=0 ; i<count ; i++) {
2060 sp<Track> t = activeTracks[i].promote();
2061 if (t == 0) continue;
2062
2063 Track* const track = t.get();
2064 audio_track_cblk_t* cblk = track->cblk();
2065
2066 // The first time a track is added we wait
2067 // for all its buffers to be filled before processing it
2068 mAudioMixer->setActiveTrack(track->name());
Eric Laurentaf59ce22010-10-05 14:41:42 -07002069 if (cblk->framesReady() && track->isReady() &&
Mathias Agopian65ab4712010-07-14 17:59:35 -07002070 !track->isPaused() && !track->isTerminated())
2071 {
2072 //LOGV("track %d u=%08x, s=%08x [OK] on thread %p", track->name(), cblk->user, cblk->server, this);
2073
2074 mixedTracks++;
2075
2076 // track->mainBuffer() != mMixBuffer means there is an effect chain
2077 // connected to the track
2078 chain.clear();
2079 if (track->mainBuffer() != mMixBuffer) {
2080 chain = getEffectChain_l(track->sessionId());
2081 // Delegate volume control to effect in track effect chain if needed
2082 if (chain != 0) {
2083 tracksWithEffect++;
2084 } else {
2085 LOGW("prepareTracks_l(): track %08x attached to effect but no chain found on session %d",
2086 track->name(), track->sessionId());
2087 }
2088 }
2089
2090
2091 int param = AudioMixer::VOLUME;
2092 if (track->mFillingUpStatus == Track::FS_FILLED) {
2093 // no ramp for the first volume setting
2094 track->mFillingUpStatus = Track::FS_ACTIVE;
2095 if (track->mState == TrackBase::RESUMING) {
2096 track->mState = TrackBase::ACTIVE;
2097 param = AudioMixer::RAMP_VOLUME;
2098 }
Eric Laurent243f5f92011-02-28 16:52:51 -08002099 mAudioMixer->setParameter(AudioMixer::RESAMPLE, AudioMixer::RESET, NULL);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002100 } else if (cblk->server != 0) {
2101 // If the track is stopped before the first frame was mixed,
2102 // do not apply ramp
2103 param = AudioMixer::RAMP_VOLUME;
2104 }
2105
2106 // compute volume for this track
Eric Laurente0aed6d2010-09-10 17:44:44 -07002107 uint32_t vl, vr, va;
Eric Laurent8569f0d2010-07-29 23:43:43 -07002108 if (track->isMuted() || track->isPausing() ||
Mathias Agopian65ab4712010-07-14 17:59:35 -07002109 mStreamTypes[track->type()].mute) {
Eric Laurente0aed6d2010-09-10 17:44:44 -07002110 vl = vr = va = 0;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002111 if (track->isPausing()) {
2112 track->setPaused();
2113 }
2114 } else {
Eric Laurente0aed6d2010-09-10 17:44:44 -07002115
Mathias Agopian65ab4712010-07-14 17:59:35 -07002116 // read original volumes with volume control
2117 float typeVolume = mStreamTypes[track->type()].volume;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002118 float v = masterVolume * typeVolume;
Eric Laurente0aed6d2010-09-10 17:44:44 -07002119 vl = (uint32_t)(v * cblk->volume[0]) << 12;
2120 vr = (uint32_t)(v * cblk->volume[1]) << 12;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002121
Eric Laurente0aed6d2010-09-10 17:44:44 -07002122 va = (uint32_t)(v * cblk->sendLevel);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002123 }
Eric Laurente0aed6d2010-09-10 17:44:44 -07002124 // Delegate volume control to effect in track effect chain if needed
2125 if (chain != 0 && chain->setVolume_l(&vl, &vr)) {
2126 // Do not ramp volume if volume is controlled by effect
2127 param = AudioMixer::VOLUME;
2128 track->mHasVolumeController = true;
2129 } else {
2130 // force no volume ramp when volume controller was just disabled or removed
2131 // from effect chain to avoid volume spike
2132 if (track->mHasVolumeController) {
2133 param = AudioMixer::VOLUME;
2134 }
2135 track->mHasVolumeController = false;
2136 }
2137
2138 // Convert volumes from 8.24 to 4.12 format
2139 int16_t left, right, aux;
2140 uint32_t v_clamped = (vl + (1 << 11)) >> 12;
2141 if (v_clamped > MAX_GAIN_INT) v_clamped = MAX_GAIN_INT;
2142 left = int16_t(v_clamped);
2143 v_clamped = (vr + (1 << 11)) >> 12;
2144 if (v_clamped > MAX_GAIN_INT) v_clamped = MAX_GAIN_INT;
2145 right = int16_t(v_clamped);
2146
2147 if (va > MAX_GAIN_INT) va = MAX_GAIN_INT;
2148 aux = int16_t(va);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002149
Mathias Agopian65ab4712010-07-14 17:59:35 -07002150 // XXX: these things DON'T need to be done each time
2151 mAudioMixer->setBufferProvider(track);
2152 mAudioMixer->enable(AudioMixer::MIXING);
2153
2154 mAudioMixer->setParameter(param, AudioMixer::VOLUME0, (void *)left);
2155 mAudioMixer->setParameter(param, AudioMixer::VOLUME1, (void *)right);
2156 mAudioMixer->setParameter(param, AudioMixer::AUXLEVEL, (void *)aux);
2157 mAudioMixer->setParameter(
2158 AudioMixer::TRACK,
2159 AudioMixer::FORMAT, (void *)track->format());
2160 mAudioMixer->setParameter(
2161 AudioMixer::TRACK,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07002162 AudioMixer::CHANNEL_MASK, (void *)track->channelMask());
Mathias Agopian65ab4712010-07-14 17:59:35 -07002163 mAudioMixer->setParameter(
2164 AudioMixer::RESAMPLE,
2165 AudioMixer::SAMPLE_RATE,
2166 (void *)(cblk->sampleRate));
2167 mAudioMixer->setParameter(
2168 AudioMixer::TRACK,
2169 AudioMixer::MAIN_BUFFER, (void *)track->mainBuffer());
2170 mAudioMixer->setParameter(
2171 AudioMixer::TRACK,
2172 AudioMixer::AUX_BUFFER, (void *)track->auxBuffer());
2173
2174 // reset retry count
2175 track->mRetryCount = kMaxTrackRetries;
2176 mixerStatus = MIXER_TRACKS_READY;
2177 } else {
2178 //LOGV("track %d u=%08x, s=%08x [NOT READY] on thread %p", track->name(), cblk->user, cblk->server, this);
2179 if (track->isStopped()) {
2180 track->reset();
2181 }
2182 if (track->isTerminated() || track->isStopped() || track->isPaused()) {
2183 // We have consumed all the buffers of this track.
2184 // Remove it from the list of active tracks.
2185 tracksToRemove->add(track);
2186 } else {
2187 // No buffers for this track. Give it a few chances to
2188 // fill a buffer, then remove it from active list.
2189 if (--(track->mRetryCount) <= 0) {
2190 LOGV("BUFFER TIMEOUT: remove(%d) from active list on thread %p", track->name(), this);
2191 tracksToRemove->add(track);
Eric Laurent44d98482010-09-30 16:12:31 -07002192 // indicate to client process that the track was disabled because of underrun
Eric Laurent38ccae22011-03-28 18:37:07 -07002193 android_atomic_or(CBLK_DISABLED_ON, &cblk->flags);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002194 } else if (mixerStatus != MIXER_TRACKS_READY) {
2195 mixerStatus = MIXER_TRACKS_ENABLED;
2196 }
2197 }
2198 mAudioMixer->disable(AudioMixer::MIXING);
2199 }
2200 }
2201
2202 // remove all the tracks that need to be...
2203 count = tracksToRemove->size();
2204 if (UNLIKELY(count)) {
2205 for (size_t i=0 ; i<count ; i++) {
2206 const sp<Track>& track = tracksToRemove->itemAt(i);
2207 mActiveTracks.remove(track);
2208 if (track->mainBuffer() != mMixBuffer) {
2209 chain = getEffectChain_l(track->sessionId());
2210 if (chain != 0) {
2211 LOGV("stopping track on chain %p for session Id: %d", chain.get(), track->sessionId());
Eric Laurentb469b942011-05-09 12:09:06 -07002212 chain->decActiveTrackCnt();
Mathias Agopian65ab4712010-07-14 17:59:35 -07002213 }
2214 }
2215 if (track->isTerminated()) {
Eric Laurentb469b942011-05-09 12:09:06 -07002216 removeTrack_l(track);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002217 }
2218 }
2219 }
2220
2221 // mix buffer must be cleared if all tracks are connected to an
2222 // effect chain as in this case the mixer will not write to
2223 // mix buffer and track effects will accumulate into it
2224 if (mixedTracks != 0 && mixedTracks == tracksWithEffect) {
2225 memset(mMixBuffer, 0, mFrameCount * mChannelCount * sizeof(int16_t));
2226 }
2227
2228 return mixerStatus;
2229}
2230
2231void AudioFlinger::MixerThread::invalidateTracks(int streamType)
2232{
Eric Laurentde070132010-07-13 04:45:46 -07002233 LOGV ("MixerThread::invalidateTracks() mixer %p, streamType %d, mTracks.size %d",
2234 this, streamType, mTracks.size());
Mathias Agopian65ab4712010-07-14 17:59:35 -07002235 Mutex::Autolock _l(mLock);
Eric Laurentde070132010-07-13 04:45:46 -07002236
Mathias Agopian65ab4712010-07-14 17:59:35 -07002237 size_t size = mTracks.size();
2238 for (size_t i = 0; i < size; i++) {
2239 sp<Track> t = mTracks[i];
2240 if (t->type() == streamType) {
Eric Laurent38ccae22011-03-28 18:37:07 -07002241 android_atomic_or(CBLK_INVALID_ON, &t->mCblk->flags);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002242 t->mCblk->cv.signal();
Mathias Agopian65ab4712010-07-14 17:59:35 -07002243 }
2244 }
2245}
2246
Eric Laurent9f6530f2011-08-30 10:18:54 -07002247void AudioFlinger::PlaybackThread::setStreamValid(int streamType, bool valid)
2248{
2249 LOGV ("PlaybackThread::setStreamValid() thread %p, streamType %d, valid %d",
2250 this, streamType, valid);
2251 Mutex::Autolock _l(mLock);
2252
2253 mStreamTypes[streamType].valid = valid;
2254}
Mathias Agopian65ab4712010-07-14 17:59:35 -07002255
2256// getTrackName_l() must be called with ThreadBase::mLock held
2257int AudioFlinger::MixerThread::getTrackName_l()
2258{
2259 return mAudioMixer->getTrackName();
2260}
2261
2262// deleteTrackName_l() must be called with ThreadBase::mLock held
2263void AudioFlinger::MixerThread::deleteTrackName_l(int name)
2264{
2265 LOGV("remove track (%d) and delete from mixer", name);
2266 mAudioMixer->deleteTrackName(name);
2267}
2268
2269// checkForNewParameters_l() must be called with ThreadBase::mLock held
2270bool AudioFlinger::MixerThread::checkForNewParameters_l()
2271{
2272 bool reconfig = false;
2273
2274 while (!mNewParameters.isEmpty()) {
2275 status_t status = NO_ERROR;
2276 String8 keyValuePair = mNewParameters[0];
2277 AudioParameter param = AudioParameter(keyValuePair);
2278 int value;
2279
2280 if (param.getInt(String8(AudioParameter::keySamplingRate), value) == NO_ERROR) {
2281 reconfig = true;
2282 }
2283 if (param.getInt(String8(AudioParameter::keyFormat), value) == NO_ERROR) {
Dima Zavinfce7a472011-04-19 22:30:36 -07002284 if (value != AUDIO_FORMAT_PCM_16_BIT) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07002285 status = BAD_VALUE;
2286 } else {
2287 reconfig = true;
2288 }
2289 }
2290 if (param.getInt(String8(AudioParameter::keyChannels), value) == NO_ERROR) {
Dima Zavinfce7a472011-04-19 22:30:36 -07002291 if (value != AUDIO_CHANNEL_OUT_STEREO) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07002292 status = BAD_VALUE;
2293 } else {
2294 reconfig = true;
2295 }
2296 }
2297 if (param.getInt(String8(AudioParameter::keyFrameCount), value) == NO_ERROR) {
2298 // do not accept frame count changes if tracks are open as the track buffer
2299 // size depends on frame count and correct behavior would not be garantied
2300 // if frame count is changed after track creation
2301 if (!mTracks.isEmpty()) {
2302 status = INVALID_OPERATION;
2303 } else {
2304 reconfig = true;
2305 }
2306 }
2307 if (param.getInt(String8(AudioParameter::keyRouting), value) == NO_ERROR) {
Gloria Wang9ee159b2011-02-24 14:51:45 -08002308 // when changing the audio output device, call addBatteryData to notify
2309 // the change
Eric Laurentb469b942011-05-09 12:09:06 -07002310 if ((int)mDevice != value) {
Gloria Wang9ee159b2011-02-24 14:51:45 -08002311 uint32_t params = 0;
2312 // check whether speaker is on
Dima Zavinfce7a472011-04-19 22:30:36 -07002313 if (value & AUDIO_DEVICE_OUT_SPEAKER) {
Gloria Wang9ee159b2011-02-24 14:51:45 -08002314 params |= IMediaPlayerService::kBatteryDataSpeakerOn;
2315 }
2316
2317 int deviceWithoutSpeaker
Dima Zavinfce7a472011-04-19 22:30:36 -07002318 = AUDIO_DEVICE_OUT_ALL & ~AUDIO_DEVICE_OUT_SPEAKER;
Gloria Wang9ee159b2011-02-24 14:51:45 -08002319 // check if any other device (except speaker) is on
2320 if (value & deviceWithoutSpeaker ) {
2321 params |= IMediaPlayerService::kBatteryDataOtherAudioDeviceOn;
2322 }
2323
2324 if (params != 0) {
2325 addBatteryData(params);
2326 }
2327 }
2328
Mathias Agopian65ab4712010-07-14 17:59:35 -07002329 // forward device change to effects that have requested to be
2330 // aware of attached audio device.
2331 mDevice = (uint32_t)value;
2332 for (size_t i = 0; i < mEffectChains.size(); i++) {
Eric Laurentcab11242010-07-15 12:50:15 -07002333 mEffectChains[i]->setDevice_l(mDevice);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002334 }
2335 }
2336
2337 if (status == NO_ERROR) {
Dima Zavin799a70e2011-04-18 16:57:27 -07002338 status = mOutput->stream->common.set_parameters(&mOutput->stream->common,
Dima Zavinfce7a472011-04-19 22:30:36 -07002339 keyValuePair.string());
Mathias Agopian65ab4712010-07-14 17:59:35 -07002340 if (!mStandby && status == INVALID_OPERATION) {
Dima Zavin799a70e2011-04-18 16:57:27 -07002341 mOutput->stream->common.standby(&mOutput->stream->common);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002342 mStandby = true;
2343 mBytesWritten = 0;
Dima Zavin799a70e2011-04-18 16:57:27 -07002344 status = mOutput->stream->common.set_parameters(&mOutput->stream->common,
Dima Zavinfce7a472011-04-19 22:30:36 -07002345 keyValuePair.string());
Mathias Agopian65ab4712010-07-14 17:59:35 -07002346 }
2347 if (status == NO_ERROR && reconfig) {
2348 delete mAudioMixer;
2349 readOutputParameters();
2350 mAudioMixer = new AudioMixer(mFrameCount, mSampleRate);
2351 for (size_t i = 0; i < mTracks.size() ; i++) {
2352 int name = getTrackName_l();
2353 if (name < 0) break;
2354 mTracks[i]->mName = name;
2355 // limit track sample rate to 2 x new output sample rate
2356 if (mTracks[i]->mCblk->sampleRate > 2 * sampleRate()) {
2357 mTracks[i]->mCblk->sampleRate = 2 * sampleRate();
2358 }
2359 }
2360 sendConfigEvent_l(AudioSystem::OUTPUT_CONFIG_CHANGED);
2361 }
2362 }
2363
2364 mNewParameters.removeAt(0);
2365
2366 mParamStatus = status;
2367 mParamCond.signal();
Eric Laurent60cd0a02011-09-13 11:40:21 -07002368 // wait for condition with time out in case the thread calling ThreadBase::setParameters()
2369 // already timed out waiting for the status and will never signal the condition.
2370 mWaitWorkCV.waitRelative(mLock, kSetParametersTimeout);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002371 }
2372 return reconfig;
2373}
2374
2375status_t AudioFlinger::MixerThread::dumpInternals(int fd, const Vector<String16>& args)
2376{
2377 const size_t SIZE = 256;
2378 char buffer[SIZE];
2379 String8 result;
2380
2381 PlaybackThread::dumpInternals(fd, args);
2382
2383 snprintf(buffer, SIZE, "AudioMixer tracks: %08x\n", mAudioMixer->trackNames());
2384 result.append(buffer);
2385 write(fd, result.string(), result.size());
2386 return NO_ERROR;
2387}
2388
2389uint32_t AudioFlinger::MixerThread::activeSleepTimeUs()
2390{
Dima Zavin799a70e2011-04-18 16:57:27 -07002391 return (uint32_t)(mOutput->stream->get_latency(mOutput->stream) * 1000) / 2;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002392}
2393
2394uint32_t AudioFlinger::MixerThread::idleSleepTimeUs()
2395{
Eric Laurent60e18242010-07-29 06:50:24 -07002396 return (uint32_t)(((mFrameCount * 1000) / mSampleRate) * 1000) / 2;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002397}
2398
Eric Laurent25cbe0e2010-08-18 18:13:17 -07002399uint32_t AudioFlinger::MixerThread::suspendSleepTimeUs()
2400{
2401 return (uint32_t)(((mFrameCount * 1000) / mSampleRate) * 1000);
2402}
2403
Mathias Agopian65ab4712010-07-14 17:59:35 -07002404// ----------------------------------------------------------------------------
Dima Zavin799a70e2011-04-18 16:57:27 -07002405AudioFlinger::DirectOutputThread::DirectOutputThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id, uint32_t device)
Mathias Agopian65ab4712010-07-14 17:59:35 -07002406 : PlaybackThread(audioFlinger, output, id, device)
2407{
Eric Laurent7c7f10b2011-06-17 21:29:58 -07002408 mType = ThreadBase::DIRECT;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002409}
2410
2411AudioFlinger::DirectOutputThread::~DirectOutputThread()
2412{
2413}
2414
2415
2416static inline int16_t clamp16(int32_t sample)
2417{
2418 if ((sample>>15) ^ (sample>>31))
2419 sample = 0x7FFF ^ (sample>>31);
2420 return sample;
2421}
2422
2423static inline
2424int32_t mul(int16_t in, int16_t v)
2425{
2426#if defined(__arm__) && !defined(__thumb__)
2427 int32_t out;
2428 asm( "smulbb %[out], %[in], %[v] \n"
2429 : [out]"=r"(out)
2430 : [in]"%r"(in), [v]"r"(v)
2431 : );
2432 return out;
2433#else
2434 return in * int32_t(v);
2435#endif
2436}
2437
2438void AudioFlinger::DirectOutputThread::applyVolume(uint16_t leftVol, uint16_t rightVol, bool ramp)
2439{
2440 // Do not apply volume on compressed audio
Dima Zavinfce7a472011-04-19 22:30:36 -07002441 if (!audio_is_linear_pcm(mFormat)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07002442 return;
2443 }
2444
2445 // convert to signed 16 bit before volume calculation
Dima Zavinfce7a472011-04-19 22:30:36 -07002446 if (mFormat == AUDIO_FORMAT_PCM_8_BIT) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07002447 size_t count = mFrameCount * mChannelCount;
2448 uint8_t *src = (uint8_t *)mMixBuffer + count-1;
2449 int16_t *dst = mMixBuffer + count-1;
2450 while(count--) {
2451 *dst-- = (int16_t)(*src--^0x80) << 8;
2452 }
2453 }
2454
2455 size_t frameCount = mFrameCount;
2456 int16_t *out = mMixBuffer;
2457 if (ramp) {
2458 if (mChannelCount == 1) {
2459 int32_t d = ((int32_t)leftVol - (int32_t)mLeftVolShort) << 16;
2460 int32_t vlInc = d / (int32_t)frameCount;
2461 int32_t vl = ((int32_t)mLeftVolShort << 16);
2462 do {
2463 out[0] = clamp16(mul(out[0], vl >> 16) >> 12);
2464 out++;
2465 vl += vlInc;
2466 } while (--frameCount);
2467
2468 } else {
2469 int32_t d = ((int32_t)leftVol - (int32_t)mLeftVolShort) << 16;
2470 int32_t vlInc = d / (int32_t)frameCount;
2471 d = ((int32_t)rightVol - (int32_t)mRightVolShort) << 16;
2472 int32_t vrInc = d / (int32_t)frameCount;
2473 int32_t vl = ((int32_t)mLeftVolShort << 16);
2474 int32_t vr = ((int32_t)mRightVolShort << 16);
2475 do {
2476 out[0] = clamp16(mul(out[0], vl >> 16) >> 12);
2477 out[1] = clamp16(mul(out[1], vr >> 16) >> 12);
2478 out += 2;
2479 vl += vlInc;
2480 vr += vrInc;
2481 } while (--frameCount);
2482 }
2483 } else {
2484 if (mChannelCount == 1) {
2485 do {
2486 out[0] = clamp16(mul(out[0], leftVol) >> 12);
2487 out++;
2488 } while (--frameCount);
2489 } else {
2490 do {
2491 out[0] = clamp16(mul(out[0], leftVol) >> 12);
2492 out[1] = clamp16(mul(out[1], rightVol) >> 12);
2493 out += 2;
2494 } while (--frameCount);
2495 }
2496 }
2497
2498 // convert back to unsigned 8 bit after volume calculation
Dima Zavinfce7a472011-04-19 22:30:36 -07002499 if (mFormat == AUDIO_FORMAT_PCM_8_BIT) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07002500 size_t count = mFrameCount * mChannelCount;
2501 int16_t *src = mMixBuffer;
2502 uint8_t *dst = (uint8_t *)mMixBuffer;
2503 while(count--) {
2504 *dst++ = (uint8_t)(((int32_t)*src++ + (1<<7)) >> 8)^0x80;
2505 }
2506 }
2507
2508 mLeftVolShort = leftVol;
2509 mRightVolShort = rightVol;
2510}
2511
2512bool AudioFlinger::DirectOutputThread::threadLoop()
2513{
2514 uint32_t mixerStatus = MIXER_IDLE;
2515 sp<Track> trackToRemove;
2516 sp<Track> activeTrack;
2517 nsecs_t standbyTime = systemTime();
2518 int8_t *curBuf;
2519 size_t mixBufferSize = mFrameCount*mFrameSize;
2520 uint32_t activeSleepTime = activeSleepTimeUs();
2521 uint32_t idleSleepTime = idleSleepTimeUs();
2522 uint32_t sleepTime = idleSleepTime;
2523 // use shorter standby delay as on normal output to release
2524 // hardware resources as soon as possible
2525 nsecs_t standbyDelay = microseconds(activeSleepTime*2);
2526
Eric Laurentfeb0db62011-07-22 09:04:31 -07002527 acquireWakeLock();
2528
Mathias Agopian65ab4712010-07-14 17:59:35 -07002529 while (!exitPending())
2530 {
2531 bool rampVolume;
2532 uint16_t leftVol;
2533 uint16_t rightVol;
2534 Vector< sp<EffectChain> > effectChains;
2535
2536 processConfigEvents();
2537
2538 mixerStatus = MIXER_IDLE;
2539
2540 { // scope for the mLock
2541
2542 Mutex::Autolock _l(mLock);
2543
2544 if (checkForNewParameters_l()) {
2545 mixBufferSize = mFrameCount*mFrameSize;
2546 activeSleepTime = activeSleepTimeUs();
2547 idleSleepTime = idleSleepTimeUs();
2548 standbyDelay = microseconds(activeSleepTime*2);
2549 }
2550
2551 // put audio hardware into standby after short delay
2552 if UNLIKELY((!mActiveTracks.size() && systemTime() > standbyTime) ||
2553 mSuspended) {
2554 // wait until we have something to do...
2555 if (!mStandby) {
2556 LOGV("Audio hardware entering standby, mixer %p\n", this);
Dima Zavin799a70e2011-04-18 16:57:27 -07002557 mOutput->stream->common.standby(&mOutput->stream->common);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002558 mStandby = true;
2559 mBytesWritten = 0;
2560 }
2561
2562 if (!mActiveTracks.size() && mConfigEvents.isEmpty()) {
2563 // we're about to wait, flush the binder command buffer
2564 IPCThreadState::self()->flushCommands();
2565
2566 if (exitPending()) break;
2567
Eric Laurentfeb0db62011-07-22 09:04:31 -07002568 releaseWakeLock_l();
Mathias Agopian65ab4712010-07-14 17:59:35 -07002569 LOGV("DirectOutputThread %p TID %d going to sleep\n", this, gettid());
2570 mWaitWorkCV.wait(mLock);
2571 LOGV("DirectOutputThread %p TID %d waking up in active mode\n", this, gettid());
Eric Laurentfeb0db62011-07-22 09:04:31 -07002572 acquireWakeLock_l();
Mathias Agopian65ab4712010-07-14 17:59:35 -07002573
2574 if (mMasterMute == false) {
2575 char value[PROPERTY_VALUE_MAX];
2576 property_get("ro.audio.silent", value, "0");
2577 if (atoi(value)) {
2578 LOGD("Silence is golden");
2579 setMasterMute(true);
2580 }
2581 }
2582
2583 standbyTime = systemTime() + standbyDelay;
2584 sleepTime = idleSleepTime;
2585 continue;
2586 }
2587 }
2588
2589 effectChains = mEffectChains;
2590
2591 // find out which tracks need to be processed
2592 if (mActiveTracks.size() != 0) {
2593 sp<Track> t = mActiveTracks[0].promote();
2594 if (t == 0) continue;
2595
2596 Track* const track = t.get();
2597 audio_track_cblk_t* cblk = track->cblk();
2598
2599 // The first time a track is added we wait
2600 // for all its buffers to be filled before processing it
Eric Laurentaf59ce22010-10-05 14:41:42 -07002601 if (cblk->framesReady() && track->isReady() &&
Mathias Agopian65ab4712010-07-14 17:59:35 -07002602 !track->isPaused() && !track->isTerminated())
2603 {
2604 //LOGV("track %d u=%08x, s=%08x [OK]", track->name(), cblk->user, cblk->server);
2605
2606 if (track->mFillingUpStatus == Track::FS_FILLED) {
2607 track->mFillingUpStatus = Track::FS_ACTIVE;
2608 mLeftVolFloat = mRightVolFloat = 0;
2609 mLeftVolShort = mRightVolShort = 0;
2610 if (track->mState == TrackBase::RESUMING) {
2611 track->mState = TrackBase::ACTIVE;
2612 rampVolume = true;
2613 }
2614 } else if (cblk->server != 0) {
2615 // If the track is stopped before the first frame was mixed,
2616 // do not apply ramp
2617 rampVolume = true;
2618 }
2619 // compute volume for this track
2620 float left, right;
2621 if (track->isMuted() || mMasterMute || track->isPausing() ||
2622 mStreamTypes[track->type()].mute) {
2623 left = right = 0;
2624 if (track->isPausing()) {
2625 track->setPaused();
2626 }
2627 } else {
2628 float typeVolume = mStreamTypes[track->type()].volume;
2629 float v = mMasterVolume * typeVolume;
2630 float v_clamped = v * cblk->volume[0];
2631 if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN;
2632 left = v_clamped/MAX_GAIN;
2633 v_clamped = v * cblk->volume[1];
2634 if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN;
2635 right = v_clamped/MAX_GAIN;
2636 }
2637
2638 if (left != mLeftVolFloat || right != mRightVolFloat) {
2639 mLeftVolFloat = left;
2640 mRightVolFloat = right;
2641
2642 // If audio HAL implements volume control,
2643 // force software volume to nominal value
Dima Zavin799a70e2011-04-18 16:57:27 -07002644 if (mOutput->stream->set_volume(mOutput->stream, left, right) == NO_ERROR) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07002645 left = 1.0f;
2646 right = 1.0f;
2647 }
2648
2649 // Convert volumes from float to 8.24
2650 uint32_t vl = (uint32_t)(left * (1 << 24));
2651 uint32_t vr = (uint32_t)(right * (1 << 24));
2652
2653 // Delegate volume control to effect in track effect chain if needed
2654 // only one effect chain can be present on DirectOutputThread, so if
2655 // there is one, the track is connected to it
2656 if (!effectChains.isEmpty()) {
Eric Laurente0aed6d2010-09-10 17:44:44 -07002657 // Do not ramp volume if volume is controlled by effect
Eric Laurentcab11242010-07-15 12:50:15 -07002658 if(effectChains[0]->setVolume_l(&vl, &vr)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07002659 rampVolume = false;
2660 }
2661 }
2662
2663 // Convert volumes from 8.24 to 4.12 format
2664 uint32_t v_clamped = (vl + (1 << 11)) >> 12;
2665 if (v_clamped > MAX_GAIN_INT) v_clamped = MAX_GAIN_INT;
2666 leftVol = (uint16_t)v_clamped;
2667 v_clamped = (vr + (1 << 11)) >> 12;
2668 if (v_clamped > MAX_GAIN_INT) v_clamped = MAX_GAIN_INT;
2669 rightVol = (uint16_t)v_clamped;
2670 } else {
2671 leftVol = mLeftVolShort;
2672 rightVol = mRightVolShort;
2673 rampVolume = false;
2674 }
2675
2676 // reset retry count
2677 track->mRetryCount = kMaxTrackRetriesDirect;
2678 activeTrack = t;
2679 mixerStatus = MIXER_TRACKS_READY;
2680 } else {
2681 //LOGV("track %d u=%08x, s=%08x [NOT READY]", track->name(), cblk->user, cblk->server);
2682 if (track->isStopped()) {
2683 track->reset();
2684 }
2685 if (track->isTerminated() || track->isStopped() || track->isPaused()) {
2686 // We have consumed all the buffers of this track.
2687 // Remove it from the list of active tracks.
2688 trackToRemove = track;
2689 } else {
2690 // No buffers for this track. Give it a few chances to
2691 // fill a buffer, then remove it from active list.
2692 if (--(track->mRetryCount) <= 0) {
2693 LOGV("BUFFER TIMEOUT: remove(%d) from active list", track->name());
2694 trackToRemove = track;
2695 } else {
2696 mixerStatus = MIXER_TRACKS_ENABLED;
2697 }
2698 }
2699 }
2700 }
2701
2702 // remove all the tracks that need to be...
2703 if (UNLIKELY(trackToRemove != 0)) {
2704 mActiveTracks.remove(trackToRemove);
2705 if (!effectChains.isEmpty()) {
Eric Laurentde070132010-07-13 04:45:46 -07002706 LOGV("stopping track on chain %p for session Id: %d", effectChains[0].get(),
2707 trackToRemove->sessionId());
Eric Laurentb469b942011-05-09 12:09:06 -07002708 effectChains[0]->decActiveTrackCnt();
Mathias Agopian65ab4712010-07-14 17:59:35 -07002709 }
2710 if (trackToRemove->isTerminated()) {
Eric Laurentb469b942011-05-09 12:09:06 -07002711 removeTrack_l(trackToRemove);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002712 }
2713 }
2714
Eric Laurentde070132010-07-13 04:45:46 -07002715 lockEffectChains_l(effectChains);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002716 }
2717
2718 if (LIKELY(mixerStatus == MIXER_TRACKS_READY)) {
2719 AudioBufferProvider::Buffer buffer;
2720 size_t frameCount = mFrameCount;
2721 curBuf = (int8_t *)mMixBuffer;
2722 // output audio to hardware
2723 while (frameCount) {
2724 buffer.frameCount = frameCount;
2725 activeTrack->getNextBuffer(&buffer);
2726 if (UNLIKELY(buffer.raw == 0)) {
2727 memset(curBuf, 0, frameCount * mFrameSize);
2728 break;
2729 }
2730 memcpy(curBuf, buffer.raw, buffer.frameCount * mFrameSize);
2731 frameCount -= buffer.frameCount;
2732 curBuf += buffer.frameCount * mFrameSize;
2733 activeTrack->releaseBuffer(&buffer);
2734 }
2735 sleepTime = 0;
2736 standbyTime = systemTime() + standbyDelay;
2737 } else {
2738 if (sleepTime == 0) {
2739 if (mixerStatus == MIXER_TRACKS_ENABLED) {
2740 sleepTime = activeSleepTime;
2741 } else {
2742 sleepTime = idleSleepTime;
2743 }
Dima Zavinfce7a472011-04-19 22:30:36 -07002744 } else if (mBytesWritten != 0 && audio_is_linear_pcm(mFormat)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07002745 memset (mMixBuffer, 0, mFrameCount * mFrameSize);
2746 sleepTime = 0;
2747 }
2748 }
2749
2750 if (mSuspended) {
Eric Laurent25cbe0e2010-08-18 18:13:17 -07002751 sleepTime = suspendSleepTimeUs();
Mathias Agopian65ab4712010-07-14 17:59:35 -07002752 }
2753 // sleepTime == 0 means we must write to audio hardware
2754 if (sleepTime == 0) {
2755 if (mixerStatus == MIXER_TRACKS_READY) {
2756 applyVolume(leftVol, rightVol, rampVolume);
2757 }
2758 for (size_t i = 0; i < effectChains.size(); i ++) {
2759 effectChains[i]->process_l();
2760 }
Eric Laurentde070132010-07-13 04:45:46 -07002761 unlockEffectChains(effectChains);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002762
2763 mLastWriteTime = systemTime();
2764 mInWrite = true;
2765 mBytesWritten += mixBufferSize;
Dima Zavin799a70e2011-04-18 16:57:27 -07002766 int bytesWritten = (int)mOutput->stream->write(mOutput->stream, mMixBuffer, mixBufferSize);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002767 if (bytesWritten < 0) mBytesWritten -= mixBufferSize;
2768 mNumWrites++;
2769 mInWrite = false;
2770 mStandby = false;
2771 } else {
Eric Laurentde070132010-07-13 04:45:46 -07002772 unlockEffectChains(effectChains);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002773 usleep(sleepTime);
2774 }
2775
2776 // finally let go of removed track, without the lock held
2777 // since we can't guarantee the destructors won't acquire that
2778 // same lock.
2779 trackToRemove.clear();
2780 activeTrack.clear();
2781
2782 // Effect chains will be actually deleted here if they were removed from
2783 // mEffectChains list during mixing or effects processing
2784 effectChains.clear();
2785 }
2786
2787 if (!mStandby) {
Dima Zavin799a70e2011-04-18 16:57:27 -07002788 mOutput->stream->common.standby(&mOutput->stream->common);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002789 }
2790
Eric Laurentfeb0db62011-07-22 09:04:31 -07002791 releaseWakeLock();
2792
Mathias Agopian65ab4712010-07-14 17:59:35 -07002793 LOGV("DirectOutputThread %p exiting", this);
2794 return false;
2795}
2796
2797// getTrackName_l() must be called with ThreadBase::mLock held
2798int AudioFlinger::DirectOutputThread::getTrackName_l()
2799{
2800 return 0;
2801}
2802
2803// deleteTrackName_l() must be called with ThreadBase::mLock held
2804void AudioFlinger::DirectOutputThread::deleteTrackName_l(int name)
2805{
2806}
2807
2808// checkForNewParameters_l() must be called with ThreadBase::mLock held
2809bool AudioFlinger::DirectOutputThread::checkForNewParameters_l()
2810{
2811 bool reconfig = false;
2812
2813 while (!mNewParameters.isEmpty()) {
2814 status_t status = NO_ERROR;
2815 String8 keyValuePair = mNewParameters[0];
2816 AudioParameter param = AudioParameter(keyValuePair);
2817 int value;
2818
2819 if (param.getInt(String8(AudioParameter::keyFrameCount), value) == NO_ERROR) {
2820 // do not accept frame count changes if tracks are open as the track buffer
2821 // size depends on frame count and correct behavior would not be garantied
2822 // if frame count is changed after track creation
2823 if (!mTracks.isEmpty()) {
2824 status = INVALID_OPERATION;
2825 } else {
2826 reconfig = true;
2827 }
2828 }
2829 if (status == NO_ERROR) {
Dima Zavin799a70e2011-04-18 16:57:27 -07002830 status = mOutput->stream->common.set_parameters(&mOutput->stream->common,
Dima Zavinfce7a472011-04-19 22:30:36 -07002831 keyValuePair.string());
Mathias Agopian65ab4712010-07-14 17:59:35 -07002832 if (!mStandby && status == INVALID_OPERATION) {
Dima Zavin799a70e2011-04-18 16:57:27 -07002833 mOutput->stream->common.standby(&mOutput->stream->common);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002834 mStandby = true;
2835 mBytesWritten = 0;
Dima Zavin799a70e2011-04-18 16:57:27 -07002836 status = mOutput->stream->common.set_parameters(&mOutput->stream->common,
Dima Zavinfce7a472011-04-19 22:30:36 -07002837 keyValuePair.string());
Mathias Agopian65ab4712010-07-14 17:59:35 -07002838 }
2839 if (status == NO_ERROR && reconfig) {
2840 readOutputParameters();
2841 sendConfigEvent_l(AudioSystem::OUTPUT_CONFIG_CHANGED);
2842 }
2843 }
2844
2845 mNewParameters.removeAt(0);
2846
2847 mParamStatus = status;
2848 mParamCond.signal();
Eric Laurent60cd0a02011-09-13 11:40:21 -07002849 // wait for condition with time out in case the thread calling ThreadBase::setParameters()
2850 // already timed out waiting for the status and will never signal the condition.
2851 mWaitWorkCV.waitRelative(mLock, kSetParametersTimeout);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002852 }
2853 return reconfig;
2854}
2855
2856uint32_t AudioFlinger::DirectOutputThread::activeSleepTimeUs()
2857{
2858 uint32_t time;
Dima Zavinfce7a472011-04-19 22:30:36 -07002859 if (audio_is_linear_pcm(mFormat)) {
Dima Zavin799a70e2011-04-18 16:57:27 -07002860 time = (uint32_t)(mOutput->stream->get_latency(mOutput->stream) * 1000) / 2;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002861 } else {
2862 time = 10000;
2863 }
2864 return time;
2865}
2866
2867uint32_t AudioFlinger::DirectOutputThread::idleSleepTimeUs()
2868{
2869 uint32_t time;
Dima Zavinfce7a472011-04-19 22:30:36 -07002870 if (audio_is_linear_pcm(mFormat)) {
Eric Laurent60e18242010-07-29 06:50:24 -07002871 time = (uint32_t)(((mFrameCount * 1000) / mSampleRate) * 1000) / 2;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002872 } else {
2873 time = 10000;
2874 }
2875 return time;
2876}
2877
Eric Laurent25cbe0e2010-08-18 18:13:17 -07002878uint32_t AudioFlinger::DirectOutputThread::suspendSleepTimeUs()
2879{
2880 uint32_t time;
Dima Zavinfce7a472011-04-19 22:30:36 -07002881 if (audio_is_linear_pcm(mFormat)) {
Eric Laurent25cbe0e2010-08-18 18:13:17 -07002882 time = (uint32_t)(((mFrameCount * 1000) / mSampleRate) * 1000);
2883 } else {
2884 time = 10000;
2885 }
2886 return time;
2887}
2888
2889
Mathias Agopian65ab4712010-07-14 17:59:35 -07002890// ----------------------------------------------------------------------------
2891
2892AudioFlinger::DuplicatingThread::DuplicatingThread(const sp<AudioFlinger>& audioFlinger, AudioFlinger::MixerThread* mainThread, int id)
2893 : MixerThread(audioFlinger, mainThread->getOutput(), id, mainThread->device()), mWaitTimeMs(UINT_MAX)
2894{
Eric Laurent7c7f10b2011-06-17 21:29:58 -07002895 mType = ThreadBase::DUPLICATING;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002896 addOutputTrack(mainThread);
2897}
2898
2899AudioFlinger::DuplicatingThread::~DuplicatingThread()
2900{
2901 for (size_t i = 0; i < mOutputTracks.size(); i++) {
2902 mOutputTracks[i]->destroy();
2903 }
2904 mOutputTracks.clear();
2905}
2906
2907bool AudioFlinger::DuplicatingThread::threadLoop()
2908{
2909 Vector< sp<Track> > tracksToRemove;
2910 uint32_t mixerStatus = MIXER_IDLE;
2911 nsecs_t standbyTime = systemTime();
2912 size_t mixBufferSize = mFrameCount*mFrameSize;
2913 SortedVector< sp<OutputTrack> > outputTracks;
2914 uint32_t writeFrames = 0;
2915 uint32_t activeSleepTime = activeSleepTimeUs();
2916 uint32_t idleSleepTime = idleSleepTimeUs();
2917 uint32_t sleepTime = idleSleepTime;
2918 Vector< sp<EffectChain> > effectChains;
2919
Eric Laurentfeb0db62011-07-22 09:04:31 -07002920 acquireWakeLock();
2921
Mathias Agopian65ab4712010-07-14 17:59:35 -07002922 while (!exitPending())
2923 {
2924 processConfigEvents();
2925
2926 mixerStatus = MIXER_IDLE;
2927 { // scope for the mLock
2928
2929 Mutex::Autolock _l(mLock);
2930
2931 if (checkForNewParameters_l()) {
2932 mixBufferSize = mFrameCount*mFrameSize;
2933 updateWaitTime();
2934 activeSleepTime = activeSleepTimeUs();
2935 idleSleepTime = idleSleepTimeUs();
2936 }
2937
2938 const SortedVector< wp<Track> >& activeTracks = mActiveTracks;
2939
2940 for (size_t i = 0; i < mOutputTracks.size(); i++) {
2941 outputTracks.add(mOutputTracks[i]);
2942 }
2943
2944 // put audio hardware into standby after short delay
2945 if UNLIKELY((!activeTracks.size() && systemTime() > standbyTime) ||
2946 mSuspended) {
2947 if (!mStandby) {
2948 for (size_t i = 0; i < outputTracks.size(); i++) {
2949 outputTracks[i]->stop();
2950 }
2951 mStandby = true;
2952 mBytesWritten = 0;
2953 }
2954
2955 if (!activeTracks.size() && mConfigEvents.isEmpty()) {
2956 // we're about to wait, flush the binder command buffer
2957 IPCThreadState::self()->flushCommands();
2958 outputTracks.clear();
2959
2960 if (exitPending()) break;
2961
Eric Laurentfeb0db62011-07-22 09:04:31 -07002962 releaseWakeLock_l();
Mathias Agopian65ab4712010-07-14 17:59:35 -07002963 LOGV("DuplicatingThread %p TID %d going to sleep\n", this, gettid());
2964 mWaitWorkCV.wait(mLock);
2965 LOGV("DuplicatingThread %p TID %d waking up\n", this, gettid());
Eric Laurentfeb0db62011-07-22 09:04:31 -07002966 acquireWakeLock_l();
2967
Mathias Agopian65ab4712010-07-14 17:59:35 -07002968 if (mMasterMute == false) {
2969 char value[PROPERTY_VALUE_MAX];
2970 property_get("ro.audio.silent", value, "0");
2971 if (atoi(value)) {
2972 LOGD("Silence is golden");
2973 setMasterMute(true);
2974 }
2975 }
2976
2977 standbyTime = systemTime() + kStandbyTimeInNsecs;
2978 sleepTime = idleSleepTime;
2979 continue;
2980 }
2981 }
2982
2983 mixerStatus = prepareTracks_l(activeTracks, &tracksToRemove);
2984
2985 // prevent any changes in effect chain list and in each effect chain
2986 // during mixing and effect process as the audio buffers could be deleted
2987 // or modified if an effect is created or deleted
Eric Laurentde070132010-07-13 04:45:46 -07002988 lockEffectChains_l(effectChains);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002989 }
2990
2991 if (LIKELY(mixerStatus == MIXER_TRACKS_READY)) {
2992 // mix buffers...
2993 if (outputsReady(outputTracks)) {
2994 mAudioMixer->process();
2995 } else {
2996 memset(mMixBuffer, 0, mixBufferSize);
2997 }
2998 sleepTime = 0;
2999 writeFrames = mFrameCount;
3000 } else {
3001 if (sleepTime == 0) {
3002 if (mixerStatus == MIXER_TRACKS_ENABLED) {
3003 sleepTime = activeSleepTime;
3004 } else {
3005 sleepTime = idleSleepTime;
3006 }
3007 } else if (mBytesWritten != 0) {
3008 // flush remaining overflow buffers in output tracks
3009 for (size_t i = 0; i < outputTracks.size(); i++) {
3010 if (outputTracks[i]->isActive()) {
3011 sleepTime = 0;
3012 writeFrames = 0;
3013 memset(mMixBuffer, 0, mixBufferSize);
3014 break;
3015 }
3016 }
3017 }
3018 }
3019
3020 if (mSuspended) {
Eric Laurent25cbe0e2010-08-18 18:13:17 -07003021 sleepTime = suspendSleepTimeUs();
Mathias Agopian65ab4712010-07-14 17:59:35 -07003022 }
3023 // sleepTime == 0 means we must write to audio hardware
3024 if (sleepTime == 0) {
3025 for (size_t i = 0; i < effectChains.size(); i ++) {
3026 effectChains[i]->process_l();
3027 }
3028 // enable changes in effect chain
Eric Laurentde070132010-07-13 04:45:46 -07003029 unlockEffectChains(effectChains);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003030
3031 standbyTime = systemTime() + kStandbyTimeInNsecs;
3032 for (size_t i = 0; i < outputTracks.size(); i++) {
3033 outputTracks[i]->write(mMixBuffer, writeFrames);
3034 }
3035 mStandby = false;
3036 mBytesWritten += mixBufferSize;
3037 } else {
3038 // enable changes in effect chain
Eric Laurentde070132010-07-13 04:45:46 -07003039 unlockEffectChains(effectChains);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003040 usleep(sleepTime);
3041 }
3042
3043 // finally let go of all our tracks, without the lock held
3044 // since we can't guarantee the destructors won't acquire that
3045 // same lock.
3046 tracksToRemove.clear();
3047 outputTracks.clear();
3048
3049 // Effect chains will be actually deleted here if they were removed from
3050 // mEffectChains list during mixing or effects processing
3051 effectChains.clear();
3052 }
3053
Eric Laurentfeb0db62011-07-22 09:04:31 -07003054 releaseWakeLock();
3055
Mathias Agopian65ab4712010-07-14 17:59:35 -07003056 return false;
3057}
3058
3059void AudioFlinger::DuplicatingThread::addOutputTrack(MixerThread *thread)
3060{
3061 int frameCount = (3 * mFrameCount * mSampleRate) / thread->sampleRate();
3062 OutputTrack *outputTrack = new OutputTrack((ThreadBase *)thread,
3063 this,
3064 mSampleRate,
3065 mFormat,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07003066 mChannelMask,
Mathias Agopian65ab4712010-07-14 17:59:35 -07003067 frameCount);
3068 if (outputTrack->cblk() != NULL) {
Dima Zavinfce7a472011-04-19 22:30:36 -07003069 thread->setStreamVolume(AUDIO_STREAM_CNT, 1.0f);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003070 mOutputTracks.add(outputTrack);
3071 LOGV("addOutputTrack() track %p, on thread %p", outputTrack, thread);
3072 updateWaitTime();
3073 }
3074}
3075
3076void AudioFlinger::DuplicatingThread::removeOutputTrack(MixerThread *thread)
3077{
3078 Mutex::Autolock _l(mLock);
3079 for (size_t i = 0; i < mOutputTracks.size(); i++) {
3080 if (mOutputTracks[i]->thread() == (ThreadBase *)thread) {
3081 mOutputTracks[i]->destroy();
3082 mOutputTracks.removeAt(i);
3083 updateWaitTime();
3084 return;
3085 }
3086 }
3087 LOGV("removeOutputTrack(): unkonwn thread: %p", thread);
3088}
3089
3090void AudioFlinger::DuplicatingThread::updateWaitTime()
3091{
3092 mWaitTimeMs = UINT_MAX;
3093 for (size_t i = 0; i < mOutputTracks.size(); i++) {
3094 sp<ThreadBase> strong = mOutputTracks[i]->thread().promote();
3095 if (strong != NULL) {
3096 uint32_t waitTimeMs = (strong->frameCount() * 2 * 1000) / strong->sampleRate();
3097 if (waitTimeMs < mWaitTimeMs) {
3098 mWaitTimeMs = waitTimeMs;
3099 }
3100 }
3101 }
3102}
3103
3104
3105bool AudioFlinger::DuplicatingThread::outputsReady(SortedVector< sp<OutputTrack> > &outputTracks)
3106{
3107 for (size_t i = 0; i < outputTracks.size(); i++) {
3108 sp <ThreadBase> thread = outputTracks[i]->thread().promote();
3109 if (thread == 0) {
3110 LOGW("DuplicatingThread::outputsReady() could not promote thread on output track %p", outputTracks[i].get());
3111 return false;
3112 }
3113 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
3114 if (playbackThread->standby() && !playbackThread->isSuspended()) {
3115 LOGV("DuplicatingThread output track %p on thread %p Not Ready", outputTracks[i].get(), thread.get());
3116 return false;
3117 }
3118 }
3119 return true;
3120}
3121
3122uint32_t AudioFlinger::DuplicatingThread::activeSleepTimeUs()
3123{
3124 return (mWaitTimeMs * 1000) / 2;
3125}
3126
3127// ----------------------------------------------------------------------------
3128
3129// TrackBase constructor must be called with AudioFlinger::mLock held
3130AudioFlinger::ThreadBase::TrackBase::TrackBase(
3131 const wp<ThreadBase>& thread,
3132 const sp<Client>& client,
3133 uint32_t sampleRate,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07003134 uint32_t format,
3135 uint32_t channelMask,
Mathias Agopian65ab4712010-07-14 17:59:35 -07003136 int frameCount,
3137 uint32_t flags,
3138 const sp<IMemory>& sharedBuffer,
3139 int sessionId)
3140 : RefBase(),
3141 mThread(thread),
3142 mClient(client),
3143 mCblk(0),
3144 mFrameCount(0),
3145 mState(IDLE),
3146 mClientTid(-1),
3147 mFormat(format),
3148 mFlags(flags & ~SYSTEM_FLAGS_MASK),
3149 mSessionId(sessionId)
3150{
3151 LOGV_IF(sharedBuffer != 0, "sharedBuffer: %p, size: %d", sharedBuffer->pointer(), sharedBuffer->size());
3152
3153 // LOGD("Creating track with %d buffers @ %d bytes", bufferCount, bufferSize);
3154 size_t size = sizeof(audio_track_cblk_t);
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07003155 uint8_t channelCount = popcount(channelMask);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003156 size_t bufferSize = frameCount*channelCount*sizeof(int16_t);
3157 if (sharedBuffer == 0) {
3158 size += bufferSize;
3159 }
3160
3161 if (client != NULL) {
3162 mCblkMemory = client->heap()->allocate(size);
3163 if (mCblkMemory != 0) {
3164 mCblk = static_cast<audio_track_cblk_t *>(mCblkMemory->pointer());
3165 if (mCblk) { // construct the shared structure in-place.
3166 new(mCblk) audio_track_cblk_t();
3167 // clear all buffers
3168 mCblk->frameCount = frameCount;
3169 mCblk->sampleRate = sampleRate;
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07003170 mChannelCount = channelCount;
3171 mChannelMask = channelMask;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003172 if (sharedBuffer == 0) {
3173 mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t);
3174 memset(mBuffer, 0, frameCount*channelCount*sizeof(int16_t));
3175 // Force underrun condition to avoid false underrun callback until first data is
Eric Laurent44d98482010-09-30 16:12:31 -07003176 // written to buffer (other flags are cleared)
Mathias Agopian65ab4712010-07-14 17:59:35 -07003177 mCblk->flags = CBLK_UNDERRUN_ON;
3178 } else {
3179 mBuffer = sharedBuffer->pointer();
3180 }
3181 mBufferEnd = (uint8_t *)mBuffer + bufferSize;
3182 }
3183 } else {
3184 LOGE("not enough memory for AudioTrack size=%u", size);
3185 client->heap()->dump("AudioTrack");
3186 return;
3187 }
3188 } else {
3189 mCblk = (audio_track_cblk_t *)(new uint8_t[size]);
3190 if (mCblk) { // construct the shared structure in-place.
3191 new(mCblk) audio_track_cblk_t();
3192 // clear all buffers
3193 mCblk->frameCount = frameCount;
3194 mCblk->sampleRate = sampleRate;
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07003195 mChannelCount = channelCount;
3196 mChannelMask = channelMask;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003197 mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t);
3198 memset(mBuffer, 0, frameCount*channelCount*sizeof(int16_t));
3199 // Force underrun condition to avoid false underrun callback until first data is
Eric Laurent44d98482010-09-30 16:12:31 -07003200 // written to buffer (other flags are cleared)
Mathias Agopian65ab4712010-07-14 17:59:35 -07003201 mCblk->flags = CBLK_UNDERRUN_ON;
3202 mBufferEnd = (uint8_t *)mBuffer + bufferSize;
3203 }
3204 }
3205}
3206
3207AudioFlinger::ThreadBase::TrackBase::~TrackBase()
3208{
3209 if (mCblk) {
3210 mCblk->~audio_track_cblk_t(); // destroy our shared-structure.
3211 if (mClient == NULL) {
3212 delete mCblk;
3213 }
3214 }
3215 mCblkMemory.clear(); // and free the shared memory
3216 if (mClient != NULL) {
3217 Mutex::Autolock _l(mClient->audioFlinger()->mLock);
3218 mClient.clear();
3219 }
3220}
3221
3222void AudioFlinger::ThreadBase::TrackBase::releaseBuffer(AudioBufferProvider::Buffer* buffer)
3223{
3224 buffer->raw = 0;
3225 mFrameCount = buffer->frameCount;
3226 step();
3227 buffer->frameCount = 0;
3228}
3229
3230bool AudioFlinger::ThreadBase::TrackBase::step() {
3231 bool result;
3232 audio_track_cblk_t* cblk = this->cblk();
3233
3234 result = cblk->stepServer(mFrameCount);
3235 if (!result) {
3236 LOGV("stepServer failed acquiring cblk mutex");
3237 mFlags |= STEPSERVER_FAILED;
3238 }
3239 return result;
3240}
3241
3242void AudioFlinger::ThreadBase::TrackBase::reset() {
3243 audio_track_cblk_t* cblk = this->cblk();
3244
3245 cblk->user = 0;
3246 cblk->server = 0;
3247 cblk->userBase = 0;
3248 cblk->serverBase = 0;
3249 mFlags &= (uint32_t)(~SYSTEM_FLAGS_MASK);
3250 LOGV("TrackBase::reset");
3251}
3252
3253sp<IMemory> AudioFlinger::ThreadBase::TrackBase::getCblk() const
3254{
3255 return mCblkMemory;
3256}
3257
3258int AudioFlinger::ThreadBase::TrackBase::sampleRate() const {
3259 return (int)mCblk->sampleRate;
3260}
3261
3262int AudioFlinger::ThreadBase::TrackBase::channelCount() const {
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07003263 return (const int)mChannelCount;
3264}
3265
3266uint32_t AudioFlinger::ThreadBase::TrackBase::channelMask() const {
3267 return mChannelMask;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003268}
3269
3270void* AudioFlinger::ThreadBase::TrackBase::getBuffer(uint32_t offset, uint32_t frames) const {
3271 audio_track_cblk_t* cblk = this->cblk();
3272 int8_t *bufferStart = (int8_t *)mBuffer + (offset-cblk->serverBase)*cblk->frameSize;
3273 int8_t *bufferEnd = bufferStart + frames * cblk->frameSize;
3274
3275 // Check validity of returned pointer in case the track control block would have been corrupted.
3276 if (bufferStart < mBuffer || bufferStart > bufferEnd || bufferEnd > mBufferEnd ||
3277 ((unsigned long)bufferStart & (unsigned long)(cblk->frameSize - 1))) {
3278 LOGE("TrackBase::getBuffer buffer out of range:\n start: %p, end %p , mBuffer %p mBufferEnd %p\n \
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07003279 server %d, serverBase %d, user %d, userBase %d",
Mathias Agopian65ab4712010-07-14 17:59:35 -07003280 bufferStart, bufferEnd, mBuffer, mBufferEnd,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07003281 cblk->server, cblk->serverBase, cblk->user, cblk->userBase);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003282 return 0;
3283 }
3284
3285 return bufferStart;
3286}
3287
3288// ----------------------------------------------------------------------------
3289
3290// Track constructor must be called with AudioFlinger::mLock and ThreadBase::mLock held
3291AudioFlinger::PlaybackThread::Track::Track(
3292 const wp<ThreadBase>& thread,
3293 const sp<Client>& client,
3294 int streamType,
3295 uint32_t sampleRate,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07003296 uint32_t format,
3297 uint32_t channelMask,
Mathias Agopian65ab4712010-07-14 17:59:35 -07003298 int frameCount,
3299 const sp<IMemory>& sharedBuffer,
3300 int sessionId)
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07003301 : TrackBase(thread, client, sampleRate, format, channelMask, frameCount, 0, sharedBuffer, sessionId),
Eric Laurent8f45bd72010-08-31 13:50:07 -07003302 mMute(false), mSharedBuffer(sharedBuffer), mName(-1), mMainBuffer(NULL), mAuxBuffer(NULL),
3303 mAuxEffectId(0), mHasVolumeController(false)
Mathias Agopian65ab4712010-07-14 17:59:35 -07003304{
3305 if (mCblk != NULL) {
3306 sp<ThreadBase> baseThread = thread.promote();
3307 if (baseThread != 0) {
3308 PlaybackThread *playbackThread = (PlaybackThread *)baseThread.get();
3309 mName = playbackThread->getTrackName_l();
3310 mMainBuffer = playbackThread->mixBuffer();
3311 }
3312 LOGV("Track constructor name %d, calling thread %d", mName, IPCThreadState::self()->getCallingPid());
3313 if (mName < 0) {
3314 LOGE("no more track names available");
3315 }
3316 mVolume[0] = 1.0f;
3317 mVolume[1] = 1.0f;
3318 mStreamType = streamType;
3319 // NOTE: audio_track_cblk_t::frameSize for 8 bit PCM data is based on a sample size of
3320 // 16 bit because data is converted to 16 bit before being stored in buffer by AudioTrack
Eric Laurentedc15ad2011-07-21 19:35:01 -07003321 mCblk->frameSize = audio_is_linear_pcm(format) ? mChannelCount * sizeof(int16_t) : sizeof(uint8_t);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003322 }
3323}
3324
3325AudioFlinger::PlaybackThread::Track::~Track()
3326{
3327 LOGV("PlaybackThread::Track destructor");
3328 sp<ThreadBase> thread = mThread.promote();
3329 if (thread != 0) {
3330 Mutex::Autolock _l(thread->mLock);
3331 mState = TERMINATED;
3332 }
3333}
3334
3335void AudioFlinger::PlaybackThread::Track::destroy()
3336{
3337 // NOTE: destroyTrack_l() can remove a strong reference to this Track
3338 // by removing it from mTracks vector, so there is a risk that this Tracks's
3339 // desctructor is called. As the destructor needs to lock mLock,
3340 // we must acquire a strong reference on this Track before locking mLock
3341 // here so that the destructor is called only when exiting this function.
3342 // On the other hand, as long as Track::destroy() is only called by
3343 // TrackHandle destructor, the TrackHandle still holds a strong ref on
3344 // this Track with its member mTrack.
3345 sp<Track> keep(this);
3346 { // scope for mLock
3347 sp<ThreadBase> thread = mThread.promote();
3348 if (thread != 0) {
3349 if (!isOutputTrack()) {
3350 if (mState == ACTIVE || mState == RESUMING) {
Eric Laurentde070132010-07-13 04:45:46 -07003351 AudioSystem::stopOutput(thread->id(),
Dima Zavinfce7a472011-04-19 22:30:36 -07003352 (audio_stream_type_t)mStreamType,
Eric Laurentde070132010-07-13 04:45:46 -07003353 mSessionId);
Gloria Wang9ee159b2011-02-24 14:51:45 -08003354
3355 // to track the speaker usage
3356 addBatteryData(IMediaPlayerService::kBatteryDataAudioFlingerStop);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003357 }
3358 AudioSystem::releaseOutput(thread->id());
3359 }
3360 Mutex::Autolock _l(thread->mLock);
3361 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
3362 playbackThread->destroyTrack_l(this);
3363 }
3364 }
3365}
3366
3367void AudioFlinger::PlaybackThread::Track::dump(char* buffer, size_t size)
3368{
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07003369 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 -07003370 mName - AudioMixer::TRACK0,
3371 (mClient == NULL) ? getpid() : mClient->pid(),
3372 mStreamType,
3373 mFormat,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07003374 mChannelMask,
Mathias Agopian65ab4712010-07-14 17:59:35 -07003375 mSessionId,
3376 mFrameCount,
3377 mState,
3378 mMute,
3379 mFillingUpStatus,
3380 mCblk->sampleRate,
3381 mCblk->volume[0],
3382 mCblk->volume[1],
3383 mCblk->server,
3384 mCblk->user,
3385 (int)mMainBuffer,
3386 (int)mAuxBuffer);
3387}
3388
3389status_t AudioFlinger::PlaybackThread::Track::getNextBuffer(AudioBufferProvider::Buffer* buffer)
3390{
3391 audio_track_cblk_t* cblk = this->cblk();
3392 uint32_t framesReady;
3393 uint32_t framesReq = buffer->frameCount;
3394
3395 // Check if last stepServer failed, try to step now
3396 if (mFlags & TrackBase::STEPSERVER_FAILED) {
3397 if (!step()) goto getNextBuffer_exit;
3398 LOGV("stepServer recovered");
3399 mFlags &= ~TrackBase::STEPSERVER_FAILED;
3400 }
3401
3402 framesReady = cblk->framesReady();
3403
3404 if (LIKELY(framesReady)) {
3405 uint32_t s = cblk->server;
3406 uint32_t bufferEnd = cblk->serverBase + cblk->frameCount;
3407
3408 bufferEnd = (cblk->loopEnd < bufferEnd) ? cblk->loopEnd : bufferEnd;
3409 if (framesReq > framesReady) {
3410 framesReq = framesReady;
3411 }
3412 if (s + framesReq > bufferEnd) {
3413 framesReq = bufferEnd - s;
3414 }
3415
3416 buffer->raw = getBuffer(s, framesReq);
3417 if (buffer->raw == 0) goto getNextBuffer_exit;
3418
3419 buffer->frameCount = framesReq;
3420 return NO_ERROR;
3421 }
3422
3423getNextBuffer_exit:
3424 buffer->raw = 0;
3425 buffer->frameCount = 0;
3426 LOGV("getNextBuffer() no more data for track %d on thread %p", mName, mThread.unsafe_get());
3427 return NOT_ENOUGH_DATA;
3428}
3429
3430bool AudioFlinger::PlaybackThread::Track::isReady() const {
Eric Laurentaf59ce22010-10-05 14:41:42 -07003431 if (mFillingUpStatus != FS_FILLING || isStopped() || isPausing()) return true;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003432
3433 if (mCblk->framesReady() >= mCblk->frameCount ||
3434 (mCblk->flags & CBLK_FORCEREADY_MSK)) {
3435 mFillingUpStatus = FS_FILLED;
Eric Laurent38ccae22011-03-28 18:37:07 -07003436 android_atomic_and(~CBLK_FORCEREADY_MSK, &mCblk->flags);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003437 return true;
3438 }
3439 return false;
3440}
3441
3442status_t AudioFlinger::PlaybackThread::Track::start()
3443{
3444 status_t status = NO_ERROR;
Eric Laurentf997cab2010-07-19 06:24:46 -07003445 LOGV("start(%d), calling thread %d session %d",
3446 mName, IPCThreadState::self()->getCallingPid(), mSessionId);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003447 sp<ThreadBase> thread = mThread.promote();
3448 if (thread != 0) {
3449 Mutex::Autolock _l(thread->mLock);
3450 int state = mState;
3451 // here the track could be either new, or restarted
3452 // in both cases "unstop" the track
3453 if (mState == PAUSED) {
3454 mState = TrackBase::RESUMING;
3455 LOGV("PAUSED => RESUMING (%d) on thread %p", mName, this);
3456 } else {
3457 mState = TrackBase::ACTIVE;
3458 LOGV("? => ACTIVE (%d) on thread %p", mName, this);
3459 }
3460
3461 if (!isOutputTrack() && state != ACTIVE && state != RESUMING) {
3462 thread->mLock.unlock();
Eric Laurentde070132010-07-13 04:45:46 -07003463 status = AudioSystem::startOutput(thread->id(),
Dima Zavinfce7a472011-04-19 22:30:36 -07003464 (audio_stream_type_t)mStreamType,
Eric Laurentde070132010-07-13 04:45:46 -07003465 mSessionId);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003466 thread->mLock.lock();
Gloria Wang9ee159b2011-02-24 14:51:45 -08003467
3468 // to track the speaker usage
3469 if (status == NO_ERROR) {
3470 addBatteryData(IMediaPlayerService::kBatteryDataAudioFlingerStart);
3471 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07003472 }
3473 if (status == NO_ERROR) {
3474 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
3475 playbackThread->addTrack_l(this);
3476 } else {
3477 mState = state;
3478 }
3479 } else {
3480 status = BAD_VALUE;
3481 }
3482 return status;
3483}
3484
3485void AudioFlinger::PlaybackThread::Track::stop()
3486{
3487 LOGV("stop(%d), calling thread %d", mName, IPCThreadState::self()->getCallingPid());
3488 sp<ThreadBase> thread = mThread.promote();
3489 if (thread != 0) {
3490 Mutex::Autolock _l(thread->mLock);
3491 int state = mState;
3492 if (mState > STOPPED) {
3493 mState = STOPPED;
3494 // If the track is not active (PAUSED and buffers full), flush buffers
3495 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
3496 if (playbackThread->mActiveTracks.indexOf(this) < 0) {
3497 reset();
3498 }
3499 LOGV("(> STOPPED) => STOPPED (%d) on thread %p", mName, playbackThread);
3500 }
3501 if (!isOutputTrack() && (state == ACTIVE || state == RESUMING)) {
3502 thread->mLock.unlock();
Eric Laurentde070132010-07-13 04:45:46 -07003503 AudioSystem::stopOutput(thread->id(),
Dima Zavinfce7a472011-04-19 22:30:36 -07003504 (audio_stream_type_t)mStreamType,
Eric Laurentde070132010-07-13 04:45:46 -07003505 mSessionId);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003506 thread->mLock.lock();
Gloria Wang9ee159b2011-02-24 14:51:45 -08003507
3508 // to track the speaker usage
3509 addBatteryData(IMediaPlayerService::kBatteryDataAudioFlingerStop);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003510 }
3511 }
3512}
3513
3514void AudioFlinger::PlaybackThread::Track::pause()
3515{
3516 LOGV("pause(%d), calling thread %d", mName, IPCThreadState::self()->getCallingPid());
3517 sp<ThreadBase> thread = mThread.promote();
3518 if (thread != 0) {
3519 Mutex::Autolock _l(thread->mLock);
3520 if (mState == ACTIVE || mState == RESUMING) {
3521 mState = PAUSING;
3522 LOGV("ACTIVE/RESUMING => PAUSING (%d) on thread %p", mName, thread.get());
3523 if (!isOutputTrack()) {
3524 thread->mLock.unlock();
Eric Laurentde070132010-07-13 04:45:46 -07003525 AudioSystem::stopOutput(thread->id(),
Dima Zavinfce7a472011-04-19 22:30:36 -07003526 (audio_stream_type_t)mStreamType,
Eric Laurentde070132010-07-13 04:45:46 -07003527 mSessionId);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003528 thread->mLock.lock();
Gloria Wang9ee159b2011-02-24 14:51:45 -08003529
3530 // to track the speaker usage
3531 addBatteryData(IMediaPlayerService::kBatteryDataAudioFlingerStop);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003532 }
3533 }
3534 }
3535}
3536
3537void AudioFlinger::PlaybackThread::Track::flush()
3538{
3539 LOGV("flush(%d)", mName);
3540 sp<ThreadBase> thread = mThread.promote();
3541 if (thread != 0) {
3542 Mutex::Autolock _l(thread->mLock);
3543 if (mState != STOPPED && mState != PAUSED && mState != PAUSING) {
3544 return;
3545 }
3546 // No point remaining in PAUSED state after a flush => go to
3547 // STOPPED state
3548 mState = STOPPED;
3549
Eric Laurent38ccae22011-03-28 18:37:07 -07003550 // do not reset the track if it is still in the process of being stopped or paused.
3551 // this will be done by prepareTracks_l() when the track is stopped.
3552 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
3553 if (playbackThread->mActiveTracks.indexOf(this) < 0) {
3554 reset();
3555 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07003556 }
3557}
3558
3559void AudioFlinger::PlaybackThread::Track::reset()
3560{
3561 // Do not reset twice to avoid discarding data written just after a flush and before
3562 // the audioflinger thread detects the track is stopped.
3563 if (!mResetDone) {
3564 TrackBase::reset();
3565 // Force underrun condition to avoid false underrun callback until first data is
3566 // written to buffer
Eric Laurent38ccae22011-03-28 18:37:07 -07003567 android_atomic_and(~CBLK_FORCEREADY_MSK, &mCblk->flags);
3568 android_atomic_or(CBLK_UNDERRUN_ON, &mCblk->flags);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003569 mFillingUpStatus = FS_FILLING;
3570 mResetDone = true;
3571 }
3572}
3573
3574void AudioFlinger::PlaybackThread::Track::mute(bool muted)
3575{
3576 mMute = muted;
3577}
3578
3579void AudioFlinger::PlaybackThread::Track::setVolume(float left, float right)
3580{
3581 mVolume[0] = left;
3582 mVolume[1] = right;
3583}
3584
3585status_t AudioFlinger::PlaybackThread::Track::attachAuxEffect(int EffectId)
3586{
3587 status_t status = DEAD_OBJECT;
3588 sp<ThreadBase> thread = mThread.promote();
3589 if (thread != 0) {
3590 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
3591 status = playbackThread->attachAuxEffect(this, EffectId);
3592 }
3593 return status;
3594}
3595
3596void AudioFlinger::PlaybackThread::Track::setAuxBuffer(int EffectId, int32_t *buffer)
3597{
3598 mAuxEffectId = EffectId;
3599 mAuxBuffer = buffer;
3600}
3601
3602// ----------------------------------------------------------------------------
3603
3604// RecordTrack constructor must be called with AudioFlinger::mLock held
3605AudioFlinger::RecordThread::RecordTrack::RecordTrack(
3606 const wp<ThreadBase>& thread,
3607 const sp<Client>& client,
3608 uint32_t sampleRate,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07003609 uint32_t format,
3610 uint32_t channelMask,
Mathias Agopian65ab4712010-07-14 17:59:35 -07003611 int frameCount,
3612 uint32_t flags,
3613 int sessionId)
3614 : TrackBase(thread, client, sampleRate, format,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07003615 channelMask, frameCount, flags, 0, sessionId),
Mathias Agopian65ab4712010-07-14 17:59:35 -07003616 mOverflow(false)
3617{
3618 if (mCblk != NULL) {
3619 LOGV("RecordTrack constructor, size %d", (int)mBufferEnd - (int)mBuffer);
Dima Zavinfce7a472011-04-19 22:30:36 -07003620 if (format == AUDIO_FORMAT_PCM_16_BIT) {
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07003621 mCblk->frameSize = mChannelCount * sizeof(int16_t);
Dima Zavinfce7a472011-04-19 22:30:36 -07003622 } else if (format == AUDIO_FORMAT_PCM_8_BIT) {
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07003623 mCblk->frameSize = mChannelCount * sizeof(int8_t);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003624 } else {
3625 mCblk->frameSize = sizeof(int8_t);
3626 }
3627 }
3628}
3629
3630AudioFlinger::RecordThread::RecordTrack::~RecordTrack()
3631{
3632 sp<ThreadBase> thread = mThread.promote();
3633 if (thread != 0) {
3634 AudioSystem::releaseInput(thread->id());
3635 }
3636}
3637
3638status_t AudioFlinger::RecordThread::RecordTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer)
3639{
3640 audio_track_cblk_t* cblk = this->cblk();
3641 uint32_t framesAvail;
3642 uint32_t framesReq = buffer->frameCount;
3643
3644 // Check if last stepServer failed, try to step now
3645 if (mFlags & TrackBase::STEPSERVER_FAILED) {
3646 if (!step()) goto getNextBuffer_exit;
3647 LOGV("stepServer recovered");
3648 mFlags &= ~TrackBase::STEPSERVER_FAILED;
3649 }
3650
3651 framesAvail = cblk->framesAvailable_l();
3652
3653 if (LIKELY(framesAvail)) {
3654 uint32_t s = cblk->server;
3655 uint32_t bufferEnd = cblk->serverBase + cblk->frameCount;
3656
3657 if (framesReq > framesAvail) {
3658 framesReq = framesAvail;
3659 }
3660 if (s + framesReq > bufferEnd) {
3661 framesReq = bufferEnd - s;
3662 }
3663
3664 buffer->raw = getBuffer(s, framesReq);
3665 if (buffer->raw == 0) goto getNextBuffer_exit;
3666
3667 buffer->frameCount = framesReq;
3668 return NO_ERROR;
3669 }
3670
3671getNextBuffer_exit:
3672 buffer->raw = 0;
3673 buffer->frameCount = 0;
3674 return NOT_ENOUGH_DATA;
3675}
3676
3677status_t AudioFlinger::RecordThread::RecordTrack::start()
3678{
3679 sp<ThreadBase> thread = mThread.promote();
3680 if (thread != 0) {
3681 RecordThread *recordThread = (RecordThread *)thread.get();
3682 return recordThread->start(this);
3683 } else {
3684 return BAD_VALUE;
3685 }
3686}
3687
3688void AudioFlinger::RecordThread::RecordTrack::stop()
3689{
3690 sp<ThreadBase> thread = mThread.promote();
3691 if (thread != 0) {
3692 RecordThread *recordThread = (RecordThread *)thread.get();
3693 recordThread->stop(this);
Eric Laurent38ccae22011-03-28 18:37:07 -07003694 TrackBase::reset();
3695 // Force overerrun condition to avoid false overrun callback until first data is
3696 // read from buffer
3697 android_atomic_or(CBLK_UNDERRUN_ON, &mCblk->flags);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003698 }
3699}
3700
3701void AudioFlinger::RecordThread::RecordTrack::dump(char* buffer, size_t size)
3702{
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07003703 snprintf(buffer, size, " %05d %03u 0x%08x %05d %04u %01d %05u %08x %08x\n",
Mathias Agopian65ab4712010-07-14 17:59:35 -07003704 (mClient == NULL) ? getpid() : mClient->pid(),
3705 mFormat,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07003706 mChannelMask,
Mathias Agopian65ab4712010-07-14 17:59:35 -07003707 mSessionId,
3708 mFrameCount,
3709 mState,
3710 mCblk->sampleRate,
3711 mCblk->server,
3712 mCblk->user);
3713}
3714
3715
3716// ----------------------------------------------------------------------------
3717
3718AudioFlinger::PlaybackThread::OutputTrack::OutputTrack(
3719 const wp<ThreadBase>& thread,
3720 DuplicatingThread *sourceThread,
3721 uint32_t sampleRate,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07003722 uint32_t format,
3723 uint32_t channelMask,
Mathias Agopian65ab4712010-07-14 17:59:35 -07003724 int frameCount)
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07003725 : Track(thread, NULL, AUDIO_STREAM_CNT, sampleRate, format, channelMask, frameCount, NULL, 0),
Mathias Agopian65ab4712010-07-14 17:59:35 -07003726 mActive(false), mSourceThread(sourceThread)
3727{
3728
3729 PlaybackThread *playbackThread = (PlaybackThread *)thread.unsafe_get();
3730 if (mCblk != NULL) {
3731 mCblk->flags |= CBLK_DIRECTION_OUT;
3732 mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t);
3733 mCblk->volume[0] = mCblk->volume[1] = 0x1000;
3734 mOutBuffer.frameCount = 0;
3735 playbackThread->mTracks.add(this);
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07003736 LOGV("OutputTrack constructor mCblk %p, mBuffer %p, mCblk->buffers %p, " \
3737 "mCblk->frameCount %d, mCblk->sampleRate %d, mChannelMask 0x%08x mBufferEnd %p",
3738 mCblk, mBuffer, mCblk->buffers,
3739 mCblk->frameCount, mCblk->sampleRate, mChannelMask, mBufferEnd);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003740 } else {
3741 LOGW("Error creating output track on thread %p", playbackThread);
3742 }
3743}
3744
3745AudioFlinger::PlaybackThread::OutputTrack::~OutputTrack()
3746{
3747 clearBufferQueue();
3748}
3749
3750status_t AudioFlinger::PlaybackThread::OutputTrack::start()
3751{
3752 status_t status = Track::start();
3753 if (status != NO_ERROR) {
3754 return status;
3755 }
3756
3757 mActive = true;
3758 mRetryCount = 127;
3759 return status;
3760}
3761
3762void AudioFlinger::PlaybackThread::OutputTrack::stop()
3763{
3764 Track::stop();
3765 clearBufferQueue();
3766 mOutBuffer.frameCount = 0;
3767 mActive = false;
3768}
3769
3770bool AudioFlinger::PlaybackThread::OutputTrack::write(int16_t* data, uint32_t frames)
3771{
3772 Buffer *pInBuffer;
3773 Buffer inBuffer;
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07003774 uint32_t channelCount = mChannelCount;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003775 bool outputBufferFull = false;
3776 inBuffer.frameCount = frames;
3777 inBuffer.i16 = data;
3778
3779 uint32_t waitTimeLeftMs = mSourceThread->waitTimeMs();
3780
3781 if (!mActive && frames != 0) {
3782 start();
3783 sp<ThreadBase> thread = mThread.promote();
3784 if (thread != 0) {
3785 MixerThread *mixerThread = (MixerThread *)thread.get();
3786 if (mCblk->frameCount > frames){
3787 if (mBufferQueue.size() < kMaxOverFlowBuffers) {
3788 uint32_t startFrames = (mCblk->frameCount - frames);
3789 pInBuffer = new Buffer;
3790 pInBuffer->mBuffer = new int16_t[startFrames * channelCount];
3791 pInBuffer->frameCount = startFrames;
3792 pInBuffer->i16 = pInBuffer->mBuffer;
3793 memset(pInBuffer->raw, 0, startFrames * channelCount * sizeof(int16_t));
3794 mBufferQueue.add(pInBuffer);
3795 } else {
3796 LOGW ("OutputTrack::write() %p no more buffers in queue", this);
3797 }
3798 }
3799 }
3800 }
3801
3802 while (waitTimeLeftMs) {
3803 // First write pending buffers, then new data
3804 if (mBufferQueue.size()) {
3805 pInBuffer = mBufferQueue.itemAt(0);
3806 } else {
3807 pInBuffer = &inBuffer;
3808 }
3809
3810 if (pInBuffer->frameCount == 0) {
3811 break;
3812 }
3813
3814 if (mOutBuffer.frameCount == 0) {
3815 mOutBuffer.frameCount = pInBuffer->frameCount;
3816 nsecs_t startTime = systemTime();
3817 if (obtainBuffer(&mOutBuffer, waitTimeLeftMs) == (status_t)AudioTrack::NO_MORE_BUFFERS) {
3818 LOGV ("OutputTrack::write() %p thread %p no more output buffers", this, mThread.unsafe_get());
3819 outputBufferFull = true;
3820 break;
3821 }
3822 uint32_t waitTimeMs = (uint32_t)ns2ms(systemTime() - startTime);
3823 if (waitTimeLeftMs >= waitTimeMs) {
3824 waitTimeLeftMs -= waitTimeMs;
3825 } else {
3826 waitTimeLeftMs = 0;
3827 }
3828 }
3829
3830 uint32_t outFrames = pInBuffer->frameCount > mOutBuffer.frameCount ? mOutBuffer.frameCount : pInBuffer->frameCount;
3831 memcpy(mOutBuffer.raw, pInBuffer->raw, outFrames * channelCount * sizeof(int16_t));
3832 mCblk->stepUser(outFrames);
3833 pInBuffer->frameCount -= outFrames;
3834 pInBuffer->i16 += outFrames * channelCount;
3835 mOutBuffer.frameCount -= outFrames;
3836 mOutBuffer.i16 += outFrames * channelCount;
3837
3838 if (pInBuffer->frameCount == 0) {
3839 if (mBufferQueue.size()) {
3840 mBufferQueue.removeAt(0);
3841 delete [] pInBuffer->mBuffer;
3842 delete pInBuffer;
3843 LOGV("OutputTrack::write() %p thread %p released overflow buffer %d", this, mThread.unsafe_get(), mBufferQueue.size());
3844 } else {
3845 break;
3846 }
3847 }
3848 }
3849
3850 // If we could not write all frames, allocate a buffer and queue it for next time.
3851 if (inBuffer.frameCount) {
3852 sp<ThreadBase> thread = mThread.promote();
3853 if (thread != 0 && !thread->standby()) {
3854 if (mBufferQueue.size() < kMaxOverFlowBuffers) {
3855 pInBuffer = new Buffer;
3856 pInBuffer->mBuffer = new int16_t[inBuffer.frameCount * channelCount];
3857 pInBuffer->frameCount = inBuffer.frameCount;
3858 pInBuffer->i16 = pInBuffer->mBuffer;
3859 memcpy(pInBuffer->raw, inBuffer.raw, inBuffer.frameCount * channelCount * sizeof(int16_t));
3860 mBufferQueue.add(pInBuffer);
3861 LOGV("OutputTrack::write() %p thread %p adding overflow buffer %d", this, mThread.unsafe_get(), mBufferQueue.size());
3862 } else {
3863 LOGW("OutputTrack::write() %p thread %p no more overflow buffers", mThread.unsafe_get(), this);
3864 }
3865 }
3866 }
3867
3868 // Calling write() with a 0 length buffer, means that no more data will be written:
3869 // If no more buffers are pending, fill output track buffer to make sure it is started
3870 // by output mixer.
3871 if (frames == 0 && mBufferQueue.size() == 0) {
3872 if (mCblk->user < mCblk->frameCount) {
3873 frames = mCblk->frameCount - mCblk->user;
3874 pInBuffer = new Buffer;
3875 pInBuffer->mBuffer = new int16_t[frames * channelCount];
3876 pInBuffer->frameCount = frames;
3877 pInBuffer->i16 = pInBuffer->mBuffer;
3878 memset(pInBuffer->raw, 0, frames * channelCount * sizeof(int16_t));
3879 mBufferQueue.add(pInBuffer);
3880 } else if (mActive) {
3881 stop();
3882 }
3883 }
3884
3885 return outputBufferFull;
3886}
3887
3888status_t AudioFlinger::PlaybackThread::OutputTrack::obtainBuffer(AudioBufferProvider::Buffer* buffer, uint32_t waitTimeMs)
3889{
3890 int active;
3891 status_t result;
3892 audio_track_cblk_t* cblk = mCblk;
3893 uint32_t framesReq = buffer->frameCount;
3894
3895// LOGV("OutputTrack::obtainBuffer user %d, server %d", cblk->user, cblk->server);
3896 buffer->frameCount = 0;
3897
3898 uint32_t framesAvail = cblk->framesAvailable();
3899
3900
3901 if (framesAvail == 0) {
3902 Mutex::Autolock _l(cblk->lock);
3903 goto start_loop_here;
3904 while (framesAvail == 0) {
3905 active = mActive;
3906 if (UNLIKELY(!active)) {
3907 LOGV("Not active and NO_MORE_BUFFERS");
3908 return AudioTrack::NO_MORE_BUFFERS;
3909 }
3910 result = cblk->cv.waitRelative(cblk->lock, milliseconds(waitTimeMs));
3911 if (result != NO_ERROR) {
3912 return AudioTrack::NO_MORE_BUFFERS;
3913 }
3914 // read the server count again
3915 start_loop_here:
3916 framesAvail = cblk->framesAvailable_l();
3917 }
3918 }
3919
3920// if (framesAvail < framesReq) {
3921// return AudioTrack::NO_MORE_BUFFERS;
3922// }
3923
3924 if (framesReq > framesAvail) {
3925 framesReq = framesAvail;
3926 }
3927
3928 uint32_t u = cblk->user;
3929 uint32_t bufferEnd = cblk->userBase + cblk->frameCount;
3930
3931 if (u + framesReq > bufferEnd) {
3932 framesReq = bufferEnd - u;
3933 }
3934
3935 buffer->frameCount = framesReq;
3936 buffer->raw = (void *)cblk->buffer(u);
3937 return NO_ERROR;
3938}
3939
3940
3941void AudioFlinger::PlaybackThread::OutputTrack::clearBufferQueue()
3942{
3943 size_t size = mBufferQueue.size();
3944 Buffer *pBuffer;
3945
3946 for (size_t i = 0; i < size; i++) {
3947 pBuffer = mBufferQueue.itemAt(i);
3948 delete [] pBuffer->mBuffer;
3949 delete pBuffer;
3950 }
3951 mBufferQueue.clear();
3952}
3953
3954// ----------------------------------------------------------------------------
3955
3956AudioFlinger::Client::Client(const sp<AudioFlinger>& audioFlinger, pid_t pid)
3957 : RefBase(),
3958 mAudioFlinger(audioFlinger),
3959 mMemoryDealer(new MemoryDealer(1024*1024, "AudioFlinger::Client")),
3960 mPid(pid)
3961{
3962 // 1 MB of address space is good for 32 tracks, 8 buffers each, 4 KB/buffer
3963}
3964
3965// Client destructor must be called with AudioFlinger::mLock held
3966AudioFlinger::Client::~Client()
3967{
3968 mAudioFlinger->removeClient_l(mPid);
3969}
3970
3971const sp<MemoryDealer>& AudioFlinger::Client::heap() const
3972{
3973 return mMemoryDealer;
3974}
3975
3976// ----------------------------------------------------------------------------
3977
3978AudioFlinger::NotificationClient::NotificationClient(const sp<AudioFlinger>& audioFlinger,
3979 const sp<IAudioFlingerClient>& client,
3980 pid_t pid)
3981 : mAudioFlinger(audioFlinger), mPid(pid), mClient(client)
3982{
3983}
3984
3985AudioFlinger::NotificationClient::~NotificationClient()
3986{
3987 mClient.clear();
3988}
3989
3990void AudioFlinger::NotificationClient::binderDied(const wp<IBinder>& who)
3991{
3992 sp<NotificationClient> keep(this);
3993 {
3994 mAudioFlinger->removeNotificationClient(mPid);
3995 }
3996}
3997
3998// ----------------------------------------------------------------------------
3999
4000AudioFlinger::TrackHandle::TrackHandle(const sp<AudioFlinger::PlaybackThread::Track>& track)
4001 : BnAudioTrack(),
4002 mTrack(track)
4003{
4004}
4005
4006AudioFlinger::TrackHandle::~TrackHandle() {
4007 // just stop the track on deletion, associated resources
4008 // will be freed from the main thread once all pending buffers have
4009 // been played. Unless it's not in the active track list, in which
4010 // case we free everything now...
4011 mTrack->destroy();
4012}
4013
4014status_t AudioFlinger::TrackHandle::start() {
4015 return mTrack->start();
4016}
4017
4018void AudioFlinger::TrackHandle::stop() {
4019 mTrack->stop();
4020}
4021
4022void AudioFlinger::TrackHandle::flush() {
4023 mTrack->flush();
4024}
4025
4026void AudioFlinger::TrackHandle::mute(bool e) {
4027 mTrack->mute(e);
4028}
4029
4030void AudioFlinger::TrackHandle::pause() {
4031 mTrack->pause();
4032}
4033
4034void AudioFlinger::TrackHandle::setVolume(float left, float right) {
4035 mTrack->setVolume(left, right);
4036}
4037
4038sp<IMemory> AudioFlinger::TrackHandle::getCblk() const {
4039 return mTrack->getCblk();
4040}
4041
4042status_t AudioFlinger::TrackHandle::attachAuxEffect(int EffectId)
4043{
4044 return mTrack->attachAuxEffect(EffectId);
4045}
4046
4047status_t AudioFlinger::TrackHandle::onTransact(
4048 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
4049{
4050 return BnAudioTrack::onTransact(code, data, reply, flags);
4051}
4052
4053// ----------------------------------------------------------------------------
4054
4055sp<IAudioRecord> AudioFlinger::openRecord(
4056 pid_t pid,
4057 int input,
4058 uint32_t sampleRate,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07004059 uint32_t format,
4060 uint32_t channelMask,
Mathias Agopian65ab4712010-07-14 17:59:35 -07004061 int frameCount,
4062 uint32_t flags,
4063 int *sessionId,
4064 status_t *status)
4065{
4066 sp<RecordThread::RecordTrack> recordTrack;
4067 sp<RecordHandle> recordHandle;
4068 sp<Client> client;
4069 wp<Client> wclient;
4070 status_t lStatus;
4071 RecordThread *thread;
4072 size_t inFrameCount;
4073 int lSessionId;
4074
4075 // check calling permissions
4076 if (!recordingAllowed()) {
4077 lStatus = PERMISSION_DENIED;
4078 goto Exit;
4079 }
4080
4081 // add client to list
4082 { // scope for mLock
4083 Mutex::Autolock _l(mLock);
4084 thread = checkRecordThread_l(input);
4085 if (thread == NULL) {
4086 lStatus = BAD_VALUE;
4087 goto Exit;
4088 }
4089
4090 wclient = mClients.valueFor(pid);
4091 if (wclient != NULL) {
4092 client = wclient.promote();
4093 } else {
4094 client = new Client(this, pid);
4095 mClients.add(pid, client);
4096 }
4097
4098 // If no audio session id is provided, create one here
Dima Zavinfce7a472011-04-19 22:30:36 -07004099 if (sessionId != NULL && *sessionId != AUDIO_SESSION_OUTPUT_MIX) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07004100 lSessionId = *sessionId;
4101 } else {
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004102 lSessionId = nextUniqueId();
Mathias Agopian65ab4712010-07-14 17:59:35 -07004103 if (sessionId != NULL) {
4104 *sessionId = lSessionId;
4105 }
4106 }
4107 // create new record track. The record track uses one track in mHardwareMixerThread by convention.
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004108 recordTrack = thread->createRecordTrack_l(client,
4109 sampleRate,
4110 format,
4111 channelMask,
4112 frameCount,
4113 flags,
4114 lSessionId,
4115 &lStatus);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004116 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004117 if (lStatus != NO_ERROR) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07004118 // remove local strong reference to Client before deleting the RecordTrack so that the Client
4119 // destructor is called by the TrackBase destructor with mLock held
4120 client.clear();
4121 recordTrack.clear();
Mathias Agopian65ab4712010-07-14 17:59:35 -07004122 goto Exit;
4123 }
4124
4125 // return to handle to client
4126 recordHandle = new RecordHandle(recordTrack);
4127 lStatus = NO_ERROR;
4128
4129Exit:
4130 if (status) {
4131 *status = lStatus;
4132 }
4133 return recordHandle;
4134}
4135
4136// ----------------------------------------------------------------------------
4137
4138AudioFlinger::RecordHandle::RecordHandle(const sp<AudioFlinger::RecordThread::RecordTrack>& recordTrack)
4139 : BnAudioRecord(),
4140 mRecordTrack(recordTrack)
4141{
4142}
4143
4144AudioFlinger::RecordHandle::~RecordHandle() {
4145 stop();
4146}
4147
4148status_t AudioFlinger::RecordHandle::start() {
4149 LOGV("RecordHandle::start()");
4150 return mRecordTrack->start();
4151}
4152
4153void AudioFlinger::RecordHandle::stop() {
4154 LOGV("RecordHandle::stop()");
4155 mRecordTrack->stop();
4156}
4157
4158sp<IMemory> AudioFlinger::RecordHandle::getCblk() const {
4159 return mRecordTrack->getCblk();
4160}
4161
4162status_t AudioFlinger::RecordHandle::onTransact(
4163 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
4164{
4165 return BnAudioRecord::onTransact(code, data, reply, flags);
4166}
4167
4168// ----------------------------------------------------------------------------
4169
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004170AudioFlinger::RecordThread::RecordThread(const sp<AudioFlinger>& audioFlinger,
4171 AudioStreamIn *input,
4172 uint32_t sampleRate,
4173 uint32_t channels,
4174 int id,
4175 uint32_t device) :
4176 ThreadBase(audioFlinger, id, device),
4177 mInput(input), mTrack(NULL), mResampler(0), mRsmpOutBuffer(0), mRsmpInBuffer(0)
Mathias Agopian65ab4712010-07-14 17:59:35 -07004178{
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004179 mType = ThreadBase::RECORD;
Eric Laurentfeb0db62011-07-22 09:04:31 -07004180
4181 snprintf(mName, kNameLength, "AudioIn_%d", id);
4182
Dima Zavinfce7a472011-04-19 22:30:36 -07004183 mReqChannelCount = popcount(channels);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004184 mReqSampleRate = sampleRate;
4185 readInputParameters();
4186}
4187
4188
4189AudioFlinger::RecordThread::~RecordThread()
4190{
4191 delete[] mRsmpInBuffer;
4192 if (mResampler != 0) {
4193 delete mResampler;
4194 delete[] mRsmpOutBuffer;
4195 }
4196}
4197
4198void AudioFlinger::RecordThread::onFirstRef()
4199{
Eric Laurentfeb0db62011-07-22 09:04:31 -07004200 run(mName, PRIORITY_URGENT_AUDIO);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004201}
4202
Eric Laurentb8ba0a92011-08-07 16:32:26 -07004203status_t AudioFlinger::RecordThread::readyToRun()
4204{
4205 status_t status = initCheck();
4206 LOGW_IF(status != NO_ERROR,"RecordThread %p could not initialize", this);
4207 return status;
4208}
4209
Mathias Agopian65ab4712010-07-14 17:59:35 -07004210bool AudioFlinger::RecordThread::threadLoop()
4211{
4212 AudioBufferProvider::Buffer buffer;
4213 sp<RecordTrack> activeTrack;
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004214 Vector< sp<EffectChain> > effectChains;
Mathias Agopian65ab4712010-07-14 17:59:35 -07004215
Eric Laurent44d98482010-09-30 16:12:31 -07004216 nsecs_t lastWarning = 0;
4217
Eric Laurentfeb0db62011-07-22 09:04:31 -07004218 acquireWakeLock();
4219
Mathias Agopian65ab4712010-07-14 17:59:35 -07004220 // start recording
4221 while (!exitPending()) {
4222
4223 processConfigEvents();
4224
4225 { // scope for mLock
4226 Mutex::Autolock _l(mLock);
4227 checkForNewParameters_l();
4228 if (mActiveTrack == 0 && mConfigEvents.isEmpty()) {
4229 if (!mStandby) {
Dima Zavin799a70e2011-04-18 16:57:27 -07004230 mInput->stream->common.standby(&mInput->stream->common);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004231 mStandby = true;
4232 }
4233
4234 if (exitPending()) break;
4235
Eric Laurentfeb0db62011-07-22 09:04:31 -07004236 releaseWakeLock_l();
Mathias Agopian65ab4712010-07-14 17:59:35 -07004237 LOGV("RecordThread: loop stopping");
4238 // go to sleep
4239 mWaitWorkCV.wait(mLock);
4240 LOGV("RecordThread: loop starting");
Eric Laurentfeb0db62011-07-22 09:04:31 -07004241 acquireWakeLock_l();
Mathias Agopian65ab4712010-07-14 17:59:35 -07004242 continue;
4243 }
4244 if (mActiveTrack != 0) {
4245 if (mActiveTrack->mState == TrackBase::PAUSING) {
4246 if (!mStandby) {
Dima Zavin799a70e2011-04-18 16:57:27 -07004247 mInput->stream->common.standby(&mInput->stream->common);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004248 mStandby = true;
4249 }
4250 mActiveTrack.clear();
4251 mStartStopCond.broadcast();
4252 } else if (mActiveTrack->mState == TrackBase::RESUMING) {
4253 if (mReqChannelCount != mActiveTrack->channelCount()) {
4254 mActiveTrack.clear();
4255 mStartStopCond.broadcast();
4256 } else if (mBytesRead != 0) {
4257 // record start succeeds only if first read from audio input
4258 // succeeds
4259 if (mBytesRead > 0) {
4260 mActiveTrack->mState = TrackBase::ACTIVE;
4261 } else {
4262 mActiveTrack.clear();
4263 }
4264 mStartStopCond.broadcast();
4265 }
4266 mStandby = false;
4267 }
4268 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004269 lockEffectChains_l(effectChains);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004270 }
4271
4272 if (mActiveTrack != 0) {
4273 if (mActiveTrack->mState != TrackBase::ACTIVE &&
4274 mActiveTrack->mState != TrackBase::RESUMING) {
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004275 unlockEffectChains(effectChains);
4276 usleep(kRecordThreadSleepUs);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004277 continue;
4278 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004279 for (size_t i = 0; i < effectChains.size(); i ++) {
4280 effectChains[i]->process_l();
4281 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004282
Mathias Agopian65ab4712010-07-14 17:59:35 -07004283 buffer.frameCount = mFrameCount;
4284 if (LIKELY(mActiveTrack->getNextBuffer(&buffer) == NO_ERROR)) {
4285 size_t framesOut = buffer.frameCount;
4286 if (mResampler == 0) {
4287 // no resampling
4288 while (framesOut) {
4289 size_t framesIn = mFrameCount - mRsmpInIndex;
4290 if (framesIn) {
4291 int8_t *src = (int8_t *)mRsmpInBuffer + mRsmpInIndex * mFrameSize;
4292 int8_t *dst = buffer.i8 + (buffer.frameCount - framesOut) * mActiveTrack->mCblk->frameSize;
4293 if (framesIn > framesOut)
4294 framesIn = framesOut;
4295 mRsmpInIndex += framesIn;
4296 framesOut -= framesIn;
4297 if ((int)mChannelCount == mReqChannelCount ||
Dima Zavinfce7a472011-04-19 22:30:36 -07004298 mFormat != AUDIO_FORMAT_PCM_16_BIT) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07004299 memcpy(dst, src, framesIn * mFrameSize);
4300 } else {
4301 int16_t *src16 = (int16_t *)src;
4302 int16_t *dst16 = (int16_t *)dst;
4303 if (mChannelCount == 1) {
4304 while (framesIn--) {
4305 *dst16++ = *src16;
4306 *dst16++ = *src16++;
4307 }
4308 } else {
4309 while (framesIn--) {
4310 *dst16++ = (int16_t)(((int32_t)*src16 + (int32_t)*(src16 + 1)) >> 1);
4311 src16 += 2;
4312 }
4313 }
4314 }
4315 }
4316 if (framesOut && mFrameCount == mRsmpInIndex) {
4317 if (framesOut == mFrameCount &&
Dima Zavinfce7a472011-04-19 22:30:36 -07004318 ((int)mChannelCount == mReqChannelCount || mFormat != AUDIO_FORMAT_PCM_16_BIT)) {
Dima Zavin799a70e2011-04-18 16:57:27 -07004319 mBytesRead = mInput->stream->read(mInput->stream, buffer.raw, mInputBytes);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004320 framesOut = 0;
4321 } else {
Dima Zavin799a70e2011-04-18 16:57:27 -07004322 mBytesRead = mInput->stream->read(mInput->stream, mRsmpInBuffer, mInputBytes);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004323 mRsmpInIndex = 0;
4324 }
4325 if (mBytesRead < 0) {
4326 LOGE("Error reading audio input");
4327 if (mActiveTrack->mState == TrackBase::ACTIVE) {
4328 // Force input into standby so that it tries to
4329 // recover at next read attempt
Dima Zavin799a70e2011-04-18 16:57:27 -07004330 mInput->stream->common.standby(&mInput->stream->common);
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004331 usleep(kRecordThreadSleepUs);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004332 }
4333 mRsmpInIndex = mFrameCount;
4334 framesOut = 0;
4335 buffer.frameCount = 0;
4336 }
4337 }
4338 }
4339 } else {
4340 // resampling
4341
4342 memset(mRsmpOutBuffer, 0, framesOut * 2 * sizeof(int32_t));
4343 // alter output frame count as if we were expecting stereo samples
4344 if (mChannelCount == 1 && mReqChannelCount == 1) {
4345 framesOut >>= 1;
4346 }
4347 mResampler->resample(mRsmpOutBuffer, framesOut, this);
4348 // ditherAndClamp() works as long as all buffers returned by mActiveTrack->getNextBuffer()
4349 // are 32 bit aligned which should be always true.
4350 if (mChannelCount == 2 && mReqChannelCount == 1) {
4351 AudioMixer::ditherAndClamp(mRsmpOutBuffer, mRsmpOutBuffer, framesOut);
4352 // the resampler always outputs stereo samples: do post stereo to mono conversion
4353 int16_t *src = (int16_t *)mRsmpOutBuffer;
4354 int16_t *dst = buffer.i16;
4355 while (framesOut--) {
4356 *dst++ = (int16_t)(((int32_t)*src + (int32_t)*(src + 1)) >> 1);
4357 src += 2;
4358 }
4359 } else {
4360 AudioMixer::ditherAndClamp((int32_t *)buffer.raw, mRsmpOutBuffer, framesOut);
4361 }
4362
4363 }
4364 mActiveTrack->releaseBuffer(&buffer);
4365 mActiveTrack->overflow();
4366 }
4367 // client isn't retrieving buffers fast enough
4368 else {
Eric Laurent44d98482010-09-30 16:12:31 -07004369 if (!mActiveTrack->setOverflow()) {
4370 nsecs_t now = systemTime();
4371 if ((now - lastWarning) > kWarningThrottle) {
4372 LOGW("RecordThread: buffer overflow");
4373 lastWarning = now;
4374 }
4375 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07004376 // Release the processor for a while before asking for a new buffer.
4377 // This will give the application more chance to read from the buffer and
4378 // clear the overflow.
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004379 usleep(kRecordThreadSleepUs);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004380 }
4381 }
Eric Laurentec437d82011-07-26 20:54:46 -07004382 // enable changes in effect chain
4383 unlockEffectChains(effectChains);
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004384 effectChains.clear();
Mathias Agopian65ab4712010-07-14 17:59:35 -07004385 }
4386
4387 if (!mStandby) {
Dima Zavin799a70e2011-04-18 16:57:27 -07004388 mInput->stream->common.standby(&mInput->stream->common);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004389 }
4390 mActiveTrack.clear();
4391
4392 mStartStopCond.broadcast();
4393
Eric Laurentfeb0db62011-07-22 09:04:31 -07004394 releaseWakeLock();
4395
Mathias Agopian65ab4712010-07-14 17:59:35 -07004396 LOGV("RecordThread %p exiting", this);
4397 return false;
4398}
4399
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004400
4401sp<AudioFlinger::RecordThread::RecordTrack> AudioFlinger::RecordThread::createRecordTrack_l(
4402 const sp<AudioFlinger::Client>& client,
4403 uint32_t sampleRate,
4404 int format,
4405 int channelMask,
4406 int frameCount,
4407 uint32_t flags,
4408 int sessionId,
4409 status_t *status)
4410{
4411 sp<RecordTrack> track;
4412 status_t lStatus;
4413
4414 lStatus = initCheck();
4415 if (lStatus != NO_ERROR) {
4416 LOGE("Audio driver not initialized.");
4417 goto Exit;
4418 }
4419
4420 { // scope for mLock
4421 Mutex::Autolock _l(mLock);
4422
4423 track = new RecordTrack(this, client, sampleRate,
4424 format, channelMask, frameCount, flags, sessionId);
4425
4426 if (track->getCblk() == NULL) {
4427 lStatus = NO_MEMORY;
4428 goto Exit;
4429 }
4430
4431 mTrack = track.get();
Eric Laurent59bd0da2011-08-01 09:52:20 -07004432 // disable AEC and NS if the device is a BT SCO headset supporting those pre processings
4433 bool suspend = audio_is_bluetooth_sco_device(
Eric Laurentbee53372011-08-29 12:42:48 -07004434 (audio_devices_t)(mDevice & AUDIO_DEVICE_IN_ALL)) && mAudioFlinger->btNrecIsOff();
Eric Laurent59bd0da2011-08-01 09:52:20 -07004435 setEffectSuspended_l(FX_IID_AEC, suspend, sessionId);
4436 setEffectSuspended_l(FX_IID_NS, suspend, sessionId);
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004437 }
4438 lStatus = NO_ERROR;
4439
4440Exit:
4441 if (status) {
4442 *status = lStatus;
4443 }
4444 return track;
4445}
4446
Mathias Agopian65ab4712010-07-14 17:59:35 -07004447status_t AudioFlinger::RecordThread::start(RecordThread::RecordTrack* recordTrack)
4448{
4449 LOGV("RecordThread::start");
4450 sp <ThreadBase> strongMe = this;
4451 status_t status = NO_ERROR;
4452 {
4453 AutoMutex lock(&mLock);
4454 if (mActiveTrack != 0) {
4455 if (recordTrack != mActiveTrack.get()) {
4456 status = -EBUSY;
4457 } else if (mActiveTrack->mState == TrackBase::PAUSING) {
4458 mActiveTrack->mState = TrackBase::ACTIVE;
4459 }
4460 return status;
4461 }
4462
4463 recordTrack->mState = TrackBase::IDLE;
4464 mActiveTrack = recordTrack;
4465 mLock.unlock();
4466 status_t status = AudioSystem::startInput(mId);
4467 mLock.lock();
4468 if (status != NO_ERROR) {
4469 mActiveTrack.clear();
4470 return status;
4471 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07004472 mRsmpInIndex = mFrameCount;
4473 mBytesRead = 0;
Eric Laurent243f5f92011-02-28 16:52:51 -08004474 if (mResampler != NULL) {
4475 mResampler->reset();
4476 }
4477 mActiveTrack->mState = TrackBase::RESUMING;
Mathias Agopian65ab4712010-07-14 17:59:35 -07004478 // signal thread to start
4479 LOGV("Signal record thread");
4480 mWaitWorkCV.signal();
4481 // do not wait for mStartStopCond if exiting
4482 if (mExiting) {
4483 mActiveTrack.clear();
4484 status = INVALID_OPERATION;
4485 goto startError;
4486 }
4487 mStartStopCond.wait(mLock);
4488 if (mActiveTrack == 0) {
4489 LOGV("Record failed to start");
4490 status = BAD_VALUE;
4491 goto startError;
4492 }
4493 LOGV("Record started OK");
4494 return status;
4495 }
4496startError:
4497 AudioSystem::stopInput(mId);
4498 return status;
4499}
4500
4501void AudioFlinger::RecordThread::stop(RecordThread::RecordTrack* recordTrack) {
4502 LOGV("RecordThread::stop");
4503 sp <ThreadBase> strongMe = this;
4504 {
4505 AutoMutex lock(&mLock);
4506 if (mActiveTrack != 0 && recordTrack == mActiveTrack.get()) {
4507 mActiveTrack->mState = TrackBase::PAUSING;
4508 // do not wait for mStartStopCond if exiting
4509 if (mExiting) {
4510 return;
4511 }
4512 mStartStopCond.wait(mLock);
4513 // if we have been restarted, recordTrack == mActiveTrack.get() here
4514 if (mActiveTrack == 0 || recordTrack != mActiveTrack.get()) {
4515 mLock.unlock();
4516 AudioSystem::stopInput(mId);
4517 mLock.lock();
4518 LOGV("Record stopped OK");
4519 }
4520 }
4521 }
4522}
4523
4524status_t AudioFlinger::RecordThread::dump(int fd, const Vector<String16>& args)
4525{
4526 const size_t SIZE = 256;
4527 char buffer[SIZE];
4528 String8 result;
4529 pid_t pid = 0;
4530
4531 snprintf(buffer, SIZE, "\nInput thread %p internals\n", this);
4532 result.append(buffer);
4533
4534 if (mActiveTrack != 0) {
4535 result.append("Active Track:\n");
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07004536 result.append(" Clien Fmt Chn mask Session Buf S SRate Serv User\n");
Mathias Agopian65ab4712010-07-14 17:59:35 -07004537 mActiveTrack->dump(buffer, SIZE);
4538 result.append(buffer);
4539
4540 snprintf(buffer, SIZE, "In index: %d\n", mRsmpInIndex);
4541 result.append(buffer);
4542 snprintf(buffer, SIZE, "In size: %d\n", mInputBytes);
4543 result.append(buffer);
4544 snprintf(buffer, SIZE, "Resampling: %d\n", (mResampler != 0));
4545 result.append(buffer);
4546 snprintf(buffer, SIZE, "Out channel count: %d\n", mReqChannelCount);
4547 result.append(buffer);
4548 snprintf(buffer, SIZE, "Out sample rate: %d\n", mReqSampleRate);
4549 result.append(buffer);
4550
4551
4552 } else {
4553 result.append("No record client\n");
4554 }
4555 write(fd, result.string(), result.size());
4556
4557 dumpBase(fd, args);
Eric Laurent1d2bff02011-07-24 17:49:51 -07004558 dumpEffectChains(fd, args);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004559
4560 return NO_ERROR;
4561}
4562
4563status_t AudioFlinger::RecordThread::getNextBuffer(AudioBufferProvider::Buffer* buffer)
4564{
4565 size_t framesReq = buffer->frameCount;
4566 size_t framesReady = mFrameCount - mRsmpInIndex;
4567 int channelCount;
4568
4569 if (framesReady == 0) {
Dima Zavin799a70e2011-04-18 16:57:27 -07004570 mBytesRead = mInput->stream->read(mInput->stream, mRsmpInBuffer, mInputBytes);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004571 if (mBytesRead < 0) {
4572 LOGE("RecordThread::getNextBuffer() Error reading audio input");
4573 if (mActiveTrack->mState == TrackBase::ACTIVE) {
4574 // Force input into standby so that it tries to
4575 // recover at next read attempt
Dima Zavin799a70e2011-04-18 16:57:27 -07004576 mInput->stream->common.standby(&mInput->stream->common);
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004577 usleep(kRecordThreadSleepUs);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004578 }
4579 buffer->raw = 0;
4580 buffer->frameCount = 0;
4581 return NOT_ENOUGH_DATA;
4582 }
4583 mRsmpInIndex = 0;
4584 framesReady = mFrameCount;
4585 }
4586
4587 if (framesReq > framesReady) {
4588 framesReq = framesReady;
4589 }
4590
4591 if (mChannelCount == 1 && mReqChannelCount == 2) {
4592 channelCount = 1;
4593 } else {
4594 channelCount = 2;
4595 }
4596 buffer->raw = mRsmpInBuffer + mRsmpInIndex * channelCount;
4597 buffer->frameCount = framesReq;
4598 return NO_ERROR;
4599}
4600
4601void AudioFlinger::RecordThread::releaseBuffer(AudioBufferProvider::Buffer* buffer)
4602{
4603 mRsmpInIndex += buffer->frameCount;
4604 buffer->frameCount = 0;
4605}
4606
4607bool AudioFlinger::RecordThread::checkForNewParameters_l()
4608{
4609 bool reconfig = false;
4610
4611 while (!mNewParameters.isEmpty()) {
4612 status_t status = NO_ERROR;
4613 String8 keyValuePair = mNewParameters[0];
4614 AudioParameter param = AudioParameter(keyValuePair);
4615 int value;
4616 int reqFormat = mFormat;
4617 int reqSamplingRate = mReqSampleRate;
4618 int reqChannelCount = mReqChannelCount;
4619
4620 if (param.getInt(String8(AudioParameter::keySamplingRate), value) == NO_ERROR) {
4621 reqSamplingRate = value;
4622 reconfig = true;
4623 }
4624 if (param.getInt(String8(AudioParameter::keyFormat), value) == NO_ERROR) {
4625 reqFormat = value;
4626 reconfig = true;
4627 }
4628 if (param.getInt(String8(AudioParameter::keyChannels), value) == NO_ERROR) {
Dima Zavinfce7a472011-04-19 22:30:36 -07004629 reqChannelCount = popcount(value);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004630 reconfig = true;
4631 }
4632 if (param.getInt(String8(AudioParameter::keyFrameCount), value) == NO_ERROR) {
4633 // do not accept frame count changes if tracks are open as the track buffer
4634 // size depends on frame count and correct behavior would not be garantied
4635 // if frame count is changed after track creation
4636 if (mActiveTrack != 0) {
4637 status = INVALID_OPERATION;
4638 } else {
4639 reconfig = true;
4640 }
4641 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004642 if (param.getInt(String8(AudioParameter::keyRouting), value) == NO_ERROR) {
4643 // forward device change to effects that have requested to be
4644 // aware of attached audio device.
4645 for (size_t i = 0; i < mEffectChains.size(); i++) {
4646 mEffectChains[i]->setDevice_l(value);
4647 }
4648 // store input device and output device but do not forward output device to audio HAL.
4649 // Note that status is ignored by the caller for output device
4650 // (see AudioFlinger::setParameters()
4651 if (value & AUDIO_DEVICE_OUT_ALL) {
4652 mDevice &= (uint32_t)~(value & AUDIO_DEVICE_OUT_ALL);
4653 status = BAD_VALUE;
4654 } else {
4655 mDevice &= (uint32_t)~(value & AUDIO_DEVICE_IN_ALL);
Eric Laurent59bd0da2011-08-01 09:52:20 -07004656 // disable AEC and NS if the device is a BT SCO headset supporting those pre processings
4657 if (mTrack != NULL) {
4658 bool suspend = audio_is_bluetooth_sco_device(
Eric Laurentbee53372011-08-29 12:42:48 -07004659 (audio_devices_t)value) && mAudioFlinger->btNrecIsOff();
Eric Laurent59bd0da2011-08-01 09:52:20 -07004660 setEffectSuspended_l(FX_IID_AEC, suspend, mTrack->sessionId());
4661 setEffectSuspended_l(FX_IID_NS, suspend, mTrack->sessionId());
4662 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004663 }
4664 mDevice |= (uint32_t)value;
4665 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07004666 if (status == NO_ERROR) {
Dima Zavin799a70e2011-04-18 16:57:27 -07004667 status = mInput->stream->common.set_parameters(&mInput->stream->common, keyValuePair.string());
Mathias Agopian65ab4712010-07-14 17:59:35 -07004668 if (status == INVALID_OPERATION) {
Dima Zavin799a70e2011-04-18 16:57:27 -07004669 mInput->stream->common.standby(&mInput->stream->common);
4670 status = mInput->stream->common.set_parameters(&mInput->stream->common, keyValuePair.string());
Mathias Agopian65ab4712010-07-14 17:59:35 -07004671 }
4672 if (reconfig) {
4673 if (status == BAD_VALUE &&
Dima Zavin799a70e2011-04-18 16:57:27 -07004674 reqFormat == mInput->stream->common.get_format(&mInput->stream->common) &&
Dima Zavinfce7a472011-04-19 22:30:36 -07004675 reqFormat == AUDIO_FORMAT_PCM_16_BIT &&
Dima Zavin799a70e2011-04-18 16:57:27 -07004676 ((int)mInput->stream->common.get_sample_rate(&mInput->stream->common) <= (2 * reqSamplingRate)) &&
4677 (popcount(mInput->stream->common.get_channels(&mInput->stream->common)) < 3) &&
Dima Zavinfce7a472011-04-19 22:30:36 -07004678 (reqChannelCount < 3)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07004679 status = NO_ERROR;
4680 }
4681 if (status == NO_ERROR) {
4682 readInputParameters();
4683 sendConfigEvent_l(AudioSystem::INPUT_CONFIG_CHANGED);
4684 }
4685 }
4686 }
4687
4688 mNewParameters.removeAt(0);
4689
4690 mParamStatus = status;
4691 mParamCond.signal();
Eric Laurent60cd0a02011-09-13 11:40:21 -07004692 // wait for condition with time out in case the thread calling ThreadBase::setParameters()
4693 // already timed out waiting for the status and will never signal the condition.
4694 mWaitWorkCV.waitRelative(mLock, kSetParametersTimeout);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004695 }
4696 return reconfig;
4697}
4698
4699String8 AudioFlinger::RecordThread::getParameters(const String8& keys)
4700{
Dima Zavinfce7a472011-04-19 22:30:36 -07004701 char *s;
Eric Laurentb8ba0a92011-08-07 16:32:26 -07004702 String8 out_s8 = String8();
4703
4704 Mutex::Autolock _l(mLock);
4705 if (initCheck() != NO_ERROR) {
4706 return out_s8;
4707 }
Dima Zavinfce7a472011-04-19 22:30:36 -07004708
Dima Zavin799a70e2011-04-18 16:57:27 -07004709 s = mInput->stream->common.get_parameters(&mInput->stream->common, keys.string());
Dima Zavinfce7a472011-04-19 22:30:36 -07004710 out_s8 = String8(s);
4711 free(s);
4712 return out_s8;
Mathias Agopian65ab4712010-07-14 17:59:35 -07004713}
4714
4715void AudioFlinger::RecordThread::audioConfigChanged_l(int event, int param) {
4716 AudioSystem::OutputDescriptor desc;
4717 void *param2 = 0;
4718
4719 switch (event) {
4720 case AudioSystem::INPUT_OPENED:
4721 case AudioSystem::INPUT_CONFIG_CHANGED:
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07004722 desc.channels = mChannelMask;
Mathias Agopian65ab4712010-07-14 17:59:35 -07004723 desc.samplingRate = mSampleRate;
4724 desc.format = mFormat;
4725 desc.frameCount = mFrameCount;
4726 desc.latency = 0;
4727 param2 = &desc;
4728 break;
4729
4730 case AudioSystem::INPUT_CLOSED:
4731 default:
4732 break;
4733 }
4734 mAudioFlinger->audioConfigChanged_l(event, mId, param2);
4735}
4736
4737void AudioFlinger::RecordThread::readInputParameters()
4738{
4739 if (mRsmpInBuffer) delete mRsmpInBuffer;
4740 if (mRsmpOutBuffer) delete mRsmpOutBuffer;
4741 if (mResampler) delete mResampler;
4742 mResampler = 0;
4743
Dima Zavin799a70e2011-04-18 16:57:27 -07004744 mSampleRate = mInput->stream->common.get_sample_rate(&mInput->stream->common);
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07004745 mChannelMask = mInput->stream->common.get_channels(&mInput->stream->common);
4746 mChannelCount = (uint16_t)popcount(mChannelMask);
Dima Zavin799a70e2011-04-18 16:57:27 -07004747 mFormat = mInput->stream->common.get_format(&mInput->stream->common);
4748 mFrameSize = (uint16_t)audio_stream_frame_size(&mInput->stream->common);
4749 mInputBytes = mInput->stream->common.get_buffer_size(&mInput->stream->common);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004750 mFrameCount = mInputBytes / mFrameSize;
4751 mRsmpInBuffer = new int16_t[mFrameCount * mChannelCount];
4752
4753 if (mSampleRate != mReqSampleRate && mChannelCount < 3 && mReqChannelCount < 3)
4754 {
4755 int channelCount;
4756 // optmization: if mono to mono, use the resampler in stereo to stereo mode to avoid
4757 // stereo to mono post process as the resampler always outputs stereo.
4758 if (mChannelCount == 1 && mReqChannelCount == 2) {
4759 channelCount = 1;
4760 } else {
4761 channelCount = 2;
4762 }
4763 mResampler = AudioResampler::create(16, channelCount, mReqSampleRate);
4764 mResampler->setSampleRate(mSampleRate);
4765 mResampler->setVolume(AudioMixer::UNITY_GAIN, AudioMixer::UNITY_GAIN);
4766 mRsmpOutBuffer = new int32_t[mFrameCount * 2];
4767
4768 // optmization: if mono to mono, alter input frame count as if we were inputing stereo samples
4769 if (mChannelCount == 1 && mReqChannelCount == 1) {
4770 mFrameCount >>= 1;
4771 }
4772
4773 }
4774 mRsmpInIndex = mFrameCount;
4775}
4776
4777unsigned int AudioFlinger::RecordThread::getInputFramesLost()
4778{
Eric Laurentb8ba0a92011-08-07 16:32:26 -07004779 Mutex::Autolock _l(mLock);
4780 if (initCheck() != NO_ERROR) {
4781 return 0;
4782 }
4783
Dima Zavin799a70e2011-04-18 16:57:27 -07004784 return mInput->stream->get_input_frames_lost(mInput->stream);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004785}
4786
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004787uint32_t AudioFlinger::RecordThread::hasAudioSession(int sessionId)
4788{
4789 Mutex::Autolock _l(mLock);
4790 uint32_t result = 0;
4791 if (getEffectChain_l(sessionId) != 0) {
4792 result = EFFECT_SESSION;
4793 }
4794
4795 if (mTrack != NULL && sessionId == mTrack->sessionId()) {
4796 result |= TRACK_SESSION;
4797 }
4798
4799 return result;
4800}
4801
Eric Laurent59bd0da2011-08-01 09:52:20 -07004802AudioFlinger::RecordThread::RecordTrack* AudioFlinger::RecordThread::track()
4803{
4804 Mutex::Autolock _l(mLock);
4805 return mTrack;
4806}
4807
Eric Laurentb8ba0a92011-08-07 16:32:26 -07004808AudioFlinger::AudioStreamIn* AudioFlinger::RecordThread::getInput()
4809{
4810 Mutex::Autolock _l(mLock);
4811 return mInput;
4812}
4813
4814AudioFlinger::AudioStreamIn* AudioFlinger::RecordThread::clearInput()
4815{
4816 Mutex::Autolock _l(mLock);
4817 AudioStreamIn *input = mInput;
4818 mInput = NULL;
4819 return input;
4820}
4821
4822// this method must always be called either with ThreadBase mLock held or inside the thread loop
4823audio_stream_t* AudioFlinger::RecordThread::stream()
4824{
4825 if (mInput == NULL) {
4826 return NULL;
4827 }
4828 return &mInput->stream->common;
4829}
4830
4831
Mathias Agopian65ab4712010-07-14 17:59:35 -07004832// ----------------------------------------------------------------------------
4833
4834int AudioFlinger::openOutput(uint32_t *pDevices,
4835 uint32_t *pSamplingRate,
4836 uint32_t *pFormat,
4837 uint32_t *pChannels,
4838 uint32_t *pLatencyMs,
4839 uint32_t flags)
4840{
4841 status_t status;
4842 PlaybackThread *thread = NULL;
4843 mHardwareStatus = AUDIO_HW_OUTPUT_OPEN;
4844 uint32_t samplingRate = pSamplingRate ? *pSamplingRate : 0;
4845 uint32_t format = pFormat ? *pFormat : 0;
4846 uint32_t channels = pChannels ? *pChannels : 0;
4847 uint32_t latency = pLatencyMs ? *pLatencyMs : 0;
Dima Zavin799a70e2011-04-18 16:57:27 -07004848 audio_stream_out_t *outStream;
4849 audio_hw_device_t *outHwDev;
Mathias Agopian65ab4712010-07-14 17:59:35 -07004850
4851 LOGV("openOutput(), Device %x, SamplingRate %d, Format %d, Channels %x, flags %x",
4852 pDevices ? *pDevices : 0,
4853 samplingRate,
4854 format,
4855 channels,
4856 flags);
4857
4858 if (pDevices == NULL || *pDevices == 0) {
4859 return 0;
4860 }
Dima Zavin799a70e2011-04-18 16:57:27 -07004861
Mathias Agopian65ab4712010-07-14 17:59:35 -07004862 Mutex::Autolock _l(mLock);
4863
Dima Zavin799a70e2011-04-18 16:57:27 -07004864 outHwDev = findSuitableHwDev_l(*pDevices);
4865 if (outHwDev == NULL)
4866 return 0;
4867
4868 status = outHwDev->open_output_stream(outHwDev, *pDevices, (int *)&format,
4869 &channels, &samplingRate, &outStream);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004870 LOGV("openOutput() openOutputStream returned output %p, SamplingRate %d, Format %d, Channels %x, status %d",
Dima Zavin799a70e2011-04-18 16:57:27 -07004871 outStream,
Mathias Agopian65ab4712010-07-14 17:59:35 -07004872 samplingRate,
4873 format,
4874 channels,
4875 status);
4876
4877 mHardwareStatus = AUDIO_HW_IDLE;
Dima Zavin799a70e2011-04-18 16:57:27 -07004878 if (outStream != NULL) {
4879 AudioStreamOut *output = new AudioStreamOut(outHwDev, outStream);
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004880 int id = nextUniqueId();
Dima Zavin799a70e2011-04-18 16:57:27 -07004881
Dima Zavinfce7a472011-04-19 22:30:36 -07004882 if ((flags & AUDIO_POLICY_OUTPUT_FLAG_DIRECT) ||
4883 (format != AUDIO_FORMAT_PCM_16_BIT) ||
4884 (channels != AUDIO_CHANNEL_OUT_STEREO)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07004885 thread = new DirectOutputThread(this, output, id, *pDevices);
4886 LOGV("openOutput() created direct output: ID %d thread %p", id, thread);
4887 } else {
4888 thread = new MixerThread(this, output, id, *pDevices);
4889 LOGV("openOutput() created mixer output: ID %d thread %p", id, thread);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004890 }
4891 mPlaybackThreads.add(id, thread);
4892
4893 if (pSamplingRate) *pSamplingRate = samplingRate;
4894 if (pFormat) *pFormat = format;
4895 if (pChannels) *pChannels = channels;
4896 if (pLatencyMs) *pLatencyMs = thread->latency();
4897
4898 // notify client processes of the new output creation
4899 thread->audioConfigChanged_l(AudioSystem::OUTPUT_OPENED);
4900 return id;
4901 }
4902
4903 return 0;
4904}
4905
4906int AudioFlinger::openDuplicateOutput(int output1, int output2)
4907{
4908 Mutex::Autolock _l(mLock);
4909 MixerThread *thread1 = checkMixerThread_l(output1);
4910 MixerThread *thread2 = checkMixerThread_l(output2);
4911
4912 if (thread1 == NULL || thread2 == NULL) {
4913 LOGW("openDuplicateOutput() wrong output mixer type for output %d or %d", output1, output2);
4914 return 0;
4915 }
4916
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004917 int id = nextUniqueId();
Mathias Agopian65ab4712010-07-14 17:59:35 -07004918 DuplicatingThread *thread = new DuplicatingThread(this, thread1, id);
4919 thread->addOutputTrack(thread2);
4920 mPlaybackThreads.add(id, thread);
4921 // notify client processes of the new output creation
4922 thread->audioConfigChanged_l(AudioSystem::OUTPUT_OPENED);
4923 return id;
4924}
4925
4926status_t AudioFlinger::closeOutput(int output)
4927{
4928 // keep strong reference on the playback thread so that
4929 // it is not destroyed while exit() is executed
4930 sp <PlaybackThread> thread;
4931 {
4932 Mutex::Autolock _l(mLock);
4933 thread = checkPlaybackThread_l(output);
4934 if (thread == NULL) {
4935 return BAD_VALUE;
4936 }
4937
4938 LOGV("closeOutput() %d", output);
4939
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004940 if (thread->type() == ThreadBase::MIXER) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07004941 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004942 if (mPlaybackThreads.valueAt(i)->type() == ThreadBase::DUPLICATING) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07004943 DuplicatingThread *dupThread = (DuplicatingThread *)mPlaybackThreads.valueAt(i).get();
4944 dupThread->removeOutputTrack((MixerThread *)thread.get());
4945 }
4946 }
4947 }
4948 void *param2 = 0;
4949 audioConfigChanged_l(AudioSystem::OUTPUT_CLOSED, output, param2);
4950 mPlaybackThreads.removeItem(output);
4951 }
4952 thread->exit();
4953
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004954 if (thread->type() != ThreadBase::DUPLICATING) {
Eric Laurentb8ba0a92011-08-07 16:32:26 -07004955 AudioStreamOut *out = thread->clearOutput();
4956 // from now on thread->mOutput is NULL
Dima Zavin799a70e2011-04-18 16:57:27 -07004957 out->hwDev->close_output_stream(out->hwDev, out->stream);
4958 delete out;
Mathias Agopian65ab4712010-07-14 17:59:35 -07004959 }
4960 return NO_ERROR;
4961}
4962
4963status_t AudioFlinger::suspendOutput(int output)
4964{
4965 Mutex::Autolock _l(mLock);
4966 PlaybackThread *thread = checkPlaybackThread_l(output);
4967
4968 if (thread == NULL) {
4969 return BAD_VALUE;
4970 }
4971
4972 LOGV("suspendOutput() %d", output);
4973 thread->suspend();
4974
4975 return NO_ERROR;
4976}
4977
4978status_t AudioFlinger::restoreOutput(int output)
4979{
4980 Mutex::Autolock _l(mLock);
4981 PlaybackThread *thread = checkPlaybackThread_l(output);
4982
4983 if (thread == NULL) {
4984 return BAD_VALUE;
4985 }
4986
4987 LOGV("restoreOutput() %d", output);
4988
4989 thread->restore();
4990
4991 return NO_ERROR;
4992}
4993
4994int AudioFlinger::openInput(uint32_t *pDevices,
4995 uint32_t *pSamplingRate,
4996 uint32_t *pFormat,
4997 uint32_t *pChannels,
4998 uint32_t acoustics)
4999{
5000 status_t status;
5001 RecordThread *thread = NULL;
5002 uint32_t samplingRate = pSamplingRate ? *pSamplingRate : 0;
5003 uint32_t format = pFormat ? *pFormat : 0;
5004 uint32_t channels = pChannels ? *pChannels : 0;
5005 uint32_t reqSamplingRate = samplingRate;
5006 uint32_t reqFormat = format;
5007 uint32_t reqChannels = channels;
Dima Zavin799a70e2011-04-18 16:57:27 -07005008 audio_stream_in_t *inStream;
5009 audio_hw_device_t *inHwDev;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005010
5011 if (pDevices == NULL || *pDevices == 0) {
5012 return 0;
5013 }
Dima Zavin799a70e2011-04-18 16:57:27 -07005014
Mathias Agopian65ab4712010-07-14 17:59:35 -07005015 Mutex::Autolock _l(mLock);
5016
Dima Zavin799a70e2011-04-18 16:57:27 -07005017 inHwDev = findSuitableHwDev_l(*pDevices);
5018 if (inHwDev == NULL)
5019 return 0;
5020
5021 status = inHwDev->open_input_stream(inHwDev, *pDevices, (int *)&format,
5022 &channels, &samplingRate,
Dima Zavinfce7a472011-04-19 22:30:36 -07005023 (audio_in_acoustics_t)acoustics,
Dima Zavin799a70e2011-04-18 16:57:27 -07005024 &inStream);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005025 LOGV("openInput() openInputStream returned input %p, SamplingRate %d, Format %d, Channels %x, acoustics %x, status %d",
Dima Zavin799a70e2011-04-18 16:57:27 -07005026 inStream,
Mathias Agopian65ab4712010-07-14 17:59:35 -07005027 samplingRate,
5028 format,
5029 channels,
5030 acoustics,
5031 status);
5032
5033 // If the input could not be opened with the requested parameters and we can handle the conversion internally,
5034 // try to open again with the proposed parameters. The AudioFlinger can resample the input and do mono to stereo
5035 // or stereo to mono conversions on 16 bit PCM inputs.
Dima Zavin799a70e2011-04-18 16:57:27 -07005036 if (inStream == NULL && status == BAD_VALUE &&
Dima Zavinfce7a472011-04-19 22:30:36 -07005037 reqFormat == format && format == AUDIO_FORMAT_PCM_16_BIT &&
Mathias Agopian65ab4712010-07-14 17:59:35 -07005038 (samplingRate <= 2 * reqSamplingRate) &&
Dima Zavinfce7a472011-04-19 22:30:36 -07005039 (popcount(channels) < 3) && (popcount(reqChannels) < 3)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07005040 LOGV("openInput() reopening with proposed sampling rate and channels");
Dima Zavin799a70e2011-04-18 16:57:27 -07005041 status = inHwDev->open_input_stream(inHwDev, *pDevices, (int *)&format,
5042 &channels, &samplingRate,
Dima Zavinfce7a472011-04-19 22:30:36 -07005043 (audio_in_acoustics_t)acoustics,
Dima Zavin799a70e2011-04-18 16:57:27 -07005044 &inStream);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005045 }
5046
Dima Zavin799a70e2011-04-18 16:57:27 -07005047 if (inStream != NULL) {
5048 AudioStreamIn *input = new AudioStreamIn(inHwDev, inStream);
5049
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005050 int id = nextUniqueId();
5051 // Start record thread
5052 // RecorThread require both input and output device indication to forward to audio
5053 // pre processing modules
5054 uint32_t device = (*pDevices) | primaryOutputDevice_l();
5055 thread = new RecordThread(this,
5056 input,
5057 reqSamplingRate,
5058 reqChannels,
5059 id,
5060 device);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005061 mRecordThreads.add(id, thread);
5062 LOGV("openInput() created record thread: ID %d thread %p", id, thread);
5063 if (pSamplingRate) *pSamplingRate = reqSamplingRate;
5064 if (pFormat) *pFormat = format;
5065 if (pChannels) *pChannels = reqChannels;
5066
Dima Zavin799a70e2011-04-18 16:57:27 -07005067 input->stream->common.standby(&input->stream->common);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005068
5069 // notify client processes of the new input creation
5070 thread->audioConfigChanged_l(AudioSystem::INPUT_OPENED);
5071 return id;
5072 }
5073
5074 return 0;
5075}
5076
5077status_t AudioFlinger::closeInput(int input)
5078{
5079 // keep strong reference on the record thread so that
5080 // it is not destroyed while exit() is executed
5081 sp <RecordThread> thread;
5082 {
5083 Mutex::Autolock _l(mLock);
5084 thread = checkRecordThread_l(input);
5085 if (thread == NULL) {
5086 return BAD_VALUE;
5087 }
5088
5089 LOGV("closeInput() %d", input);
5090 void *param2 = 0;
5091 audioConfigChanged_l(AudioSystem::INPUT_CLOSED, input, param2);
5092 mRecordThreads.removeItem(input);
5093 }
5094 thread->exit();
5095
Eric Laurentb8ba0a92011-08-07 16:32:26 -07005096 AudioStreamIn *in = thread->clearInput();
5097 // from now on thread->mInput is NULL
Dima Zavin799a70e2011-04-18 16:57:27 -07005098 in->hwDev->close_input_stream(in->hwDev, in->stream);
5099 delete in;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005100
5101 return NO_ERROR;
5102}
5103
5104status_t AudioFlinger::setStreamOutput(uint32_t stream, int output)
5105{
5106 Mutex::Autolock _l(mLock);
5107 MixerThread *dstThread = checkMixerThread_l(output);
5108 if (dstThread == NULL) {
5109 LOGW("setStreamOutput() bad output id %d", output);
5110 return BAD_VALUE;
5111 }
5112
5113 LOGV("setStreamOutput() stream %d to output %d", stream, output);
5114 audioConfigChanged_l(AudioSystem::STREAM_CONFIG_CHANGED, output, &stream);
5115
Eric Laurent9f6530f2011-08-30 10:18:54 -07005116 dstThread->setStreamValid(stream, true);
5117
Mathias Agopian65ab4712010-07-14 17:59:35 -07005118 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
5119 PlaybackThread *thread = mPlaybackThreads.valueAt(i).get();
5120 if (thread != dstThread &&
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005121 thread->type() != ThreadBase::DIRECT) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07005122 MixerThread *srcThread = (MixerThread *)thread;
Eric Laurent9f6530f2011-08-30 10:18:54 -07005123 srcThread->setStreamValid(stream, false);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005124 srcThread->invalidateTracks(stream);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005125 }
Eric Laurentde070132010-07-13 04:45:46 -07005126 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07005127
5128 return NO_ERROR;
5129}
5130
5131
5132int AudioFlinger::newAudioSessionId()
5133{
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005134 return nextUniqueId();
Mathias Agopian65ab4712010-07-14 17:59:35 -07005135}
5136
Marco Nelissen3a34bef2011-08-02 13:33:41 -07005137void AudioFlinger::acquireAudioSessionId(int audioSession)
5138{
5139 Mutex::Autolock _l(mLock);
5140 int caller = IPCThreadState::self()->getCallingPid();
5141 LOGV("acquiring %d from %d", audioSession, caller);
5142 int num = mAudioSessionRefs.size();
5143 for (int i = 0; i< num; i++) {
5144 AudioSessionRef *ref = mAudioSessionRefs.editItemAt(i);
5145 if (ref->sessionid == audioSession && ref->pid == caller) {
5146 ref->cnt++;
5147 LOGV(" incremented refcount to %d", ref->cnt);
5148 return;
5149 }
5150 }
5151 AudioSessionRef *ref = new AudioSessionRef();
5152 ref->sessionid = audioSession;
5153 ref->pid = caller;
5154 ref->cnt = 1;
5155 mAudioSessionRefs.push(ref);
5156 LOGV(" added new entry for %d", ref->sessionid);
5157}
5158
5159void AudioFlinger::releaseAudioSessionId(int audioSession)
5160{
5161 Mutex::Autolock _l(mLock);
5162 int caller = IPCThreadState::self()->getCallingPid();
5163 LOGV("releasing %d from %d", audioSession, caller);
5164 int num = mAudioSessionRefs.size();
5165 for (int i = 0; i< num; i++) {
5166 AudioSessionRef *ref = mAudioSessionRefs.itemAt(i);
5167 if (ref->sessionid == audioSession && ref->pid == caller) {
5168 ref->cnt--;
5169 LOGV(" decremented refcount to %d", ref->cnt);
5170 if (ref->cnt == 0) {
5171 mAudioSessionRefs.removeAt(i);
5172 delete ref;
5173 purgeStaleEffects_l();
5174 }
5175 return;
5176 }
5177 }
5178 LOGW("session id %d not found for pid %d", audioSession, caller);
5179}
5180
5181void AudioFlinger::purgeStaleEffects_l() {
5182
5183 LOGV("purging stale effects");
5184
5185 Vector< sp<EffectChain> > chains;
5186
5187 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
5188 sp<PlaybackThread> t = mPlaybackThreads.valueAt(i);
5189 for (size_t j = 0; j < t->mEffectChains.size(); j++) {
5190 sp<EffectChain> ec = t->mEffectChains[j];
Marco Nelissen0270b182011-08-12 14:14:39 -07005191 if (ec->sessionId() > AUDIO_SESSION_OUTPUT_MIX) {
5192 chains.push(ec);
5193 }
Marco Nelissen3a34bef2011-08-02 13:33:41 -07005194 }
5195 }
5196 for (size_t i = 0; i < mRecordThreads.size(); i++) {
5197 sp<RecordThread> t = mRecordThreads.valueAt(i);
5198 for (size_t j = 0; j < t->mEffectChains.size(); j++) {
5199 sp<EffectChain> ec = t->mEffectChains[j];
5200 chains.push(ec);
5201 }
5202 }
5203
5204 for (size_t i = 0; i < chains.size(); i++) {
5205 sp<EffectChain> ec = chains[i];
5206 int sessionid = ec->sessionId();
5207 sp<ThreadBase> t = ec->mThread.promote();
5208 if (t == 0) {
5209 continue;
5210 }
5211 size_t numsessionrefs = mAudioSessionRefs.size();
5212 bool found = false;
5213 for (size_t k = 0; k < numsessionrefs; k++) {
5214 AudioSessionRef *ref = mAudioSessionRefs.itemAt(k);
5215 if (ref->sessionid == sessionid) {
5216 LOGV(" session %d still exists for %d with %d refs",
5217 sessionid, ref->pid, ref->cnt);
5218 found = true;
5219 break;
5220 }
5221 }
5222 if (!found) {
5223 // remove all effects from the chain
5224 while (ec->mEffects.size()) {
5225 sp<EffectModule> effect = ec->mEffects[0];
5226 effect->unPin();
5227 Mutex::Autolock _l (t->mLock);
5228 t->removeEffect_l(effect);
5229 for (size_t j = 0; j < effect->mHandles.size(); j++) {
5230 sp<EffectHandle> handle = effect->mHandles[j].promote();
5231 if (handle != 0) {
5232 handle->mEffect.clear();
Eric Laurenta85a74a2011-10-19 11:44:54 -07005233 if (handle->mHasControl && handle->mEnabled) {
5234 t->checkSuspendOnEffectEnabled_l(effect, false, effect->sessionId());
5235 }
Marco Nelissen3a34bef2011-08-02 13:33:41 -07005236 }
5237 }
5238 AudioSystem::unregisterEffect(effect->id());
5239 }
5240 }
5241 }
5242 return;
5243}
5244
Mathias Agopian65ab4712010-07-14 17:59:35 -07005245// checkPlaybackThread_l() must be called with AudioFlinger::mLock held
5246AudioFlinger::PlaybackThread *AudioFlinger::checkPlaybackThread_l(int output) const
5247{
5248 PlaybackThread *thread = NULL;
5249 if (mPlaybackThreads.indexOfKey(output) >= 0) {
5250 thread = (PlaybackThread *)mPlaybackThreads.valueFor(output).get();
5251 }
5252 return thread;
5253}
5254
5255// checkMixerThread_l() must be called with AudioFlinger::mLock held
5256AudioFlinger::MixerThread *AudioFlinger::checkMixerThread_l(int output) const
5257{
5258 PlaybackThread *thread = checkPlaybackThread_l(output);
5259 if (thread != NULL) {
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005260 if (thread->type() == ThreadBase::DIRECT) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07005261 thread = NULL;
5262 }
5263 }
5264 return (MixerThread *)thread;
5265}
5266
5267// checkRecordThread_l() must be called with AudioFlinger::mLock held
5268AudioFlinger::RecordThread *AudioFlinger::checkRecordThread_l(int input) const
5269{
5270 RecordThread *thread = NULL;
5271 if (mRecordThreads.indexOfKey(input) >= 0) {
5272 thread = (RecordThread *)mRecordThreads.valueFor(input).get();
5273 }
5274 return thread;
5275}
5276
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005277uint32_t AudioFlinger::nextUniqueId()
Mathias Agopian65ab4712010-07-14 17:59:35 -07005278{
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005279 return android_atomic_inc(&mNextUniqueId);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005280}
5281
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005282AudioFlinger::PlaybackThread *AudioFlinger::primaryPlaybackThread_l()
5283{
5284 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
5285 PlaybackThread *thread = mPlaybackThreads.valueAt(i).get();
Eric Laurentb8ba0a92011-08-07 16:32:26 -07005286 AudioStreamOut *output = thread->getOutput();
5287 if (output != NULL && output->hwDev == mPrimaryHardwareDev) {
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005288 return thread;
5289 }
5290 }
5291 return NULL;
5292}
5293
5294uint32_t AudioFlinger::primaryOutputDevice_l()
5295{
5296 PlaybackThread *thread = primaryPlaybackThread_l();
5297
5298 if (thread == NULL) {
5299 return 0;
5300 }
5301
5302 return thread->device();
5303}
5304
5305
Mathias Agopian65ab4712010-07-14 17:59:35 -07005306// ----------------------------------------------------------------------------
5307// Effect management
5308// ----------------------------------------------------------------------------
5309
5310
Mathias Agopian65ab4712010-07-14 17:59:35 -07005311status_t AudioFlinger::queryNumberEffects(uint32_t *numEffects)
5312{
5313 Mutex::Autolock _l(mLock);
5314 return EffectQueryNumberEffects(numEffects);
5315}
5316
5317status_t AudioFlinger::queryEffect(uint32_t index, effect_descriptor_t *descriptor)
5318{
5319 Mutex::Autolock _l(mLock);
5320 return EffectQueryEffect(index, descriptor);
5321}
5322
5323status_t AudioFlinger::getEffectDescriptor(effect_uuid_t *pUuid, effect_descriptor_t *descriptor)
5324{
5325 Mutex::Autolock _l(mLock);
5326 return EffectGetDescriptor(pUuid, descriptor);
5327}
5328
5329
Mathias Agopian65ab4712010-07-14 17:59:35 -07005330sp<IEffect> AudioFlinger::createEffect(pid_t pid,
5331 effect_descriptor_t *pDesc,
5332 const sp<IEffectClient>& effectClient,
5333 int32_t priority,
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005334 int io,
Mathias Agopian65ab4712010-07-14 17:59:35 -07005335 int sessionId,
5336 status_t *status,
5337 int *id,
5338 int *enabled)
5339{
5340 status_t lStatus = NO_ERROR;
5341 sp<EffectHandle> handle;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005342 effect_descriptor_t desc;
5343 sp<Client> client;
5344 wp<Client> wclient;
5345
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005346 LOGV("createEffect pid %d, client %p, priority %d, sessionId %d, io %d",
5347 pid, effectClient.get(), priority, sessionId, io);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005348
5349 if (pDesc == NULL) {
5350 lStatus = BAD_VALUE;
5351 goto Exit;
5352 }
5353
Eric Laurent84e9a102010-09-23 16:10:16 -07005354 // check audio settings permission for global effects
Dima Zavinfce7a472011-04-19 22:30:36 -07005355 if (sessionId == AUDIO_SESSION_OUTPUT_MIX && !settingsAllowed()) {
Eric Laurent84e9a102010-09-23 16:10:16 -07005356 lStatus = PERMISSION_DENIED;
5357 goto Exit;
5358 }
5359
Dima Zavinfce7a472011-04-19 22:30:36 -07005360 // Session AUDIO_SESSION_OUTPUT_STAGE is reserved for output stage effects
Eric Laurent84e9a102010-09-23 16:10:16 -07005361 // that can only be created by audio policy manager (running in same process)
Dima Zavinfce7a472011-04-19 22:30:36 -07005362 if (sessionId == AUDIO_SESSION_OUTPUT_STAGE && getpid() != pid) {
Eric Laurent84e9a102010-09-23 16:10:16 -07005363 lStatus = PERMISSION_DENIED;
5364 goto Exit;
5365 }
5366
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005367 if (io == 0) {
Dima Zavinfce7a472011-04-19 22:30:36 -07005368 if (sessionId == AUDIO_SESSION_OUTPUT_STAGE) {
Eric Laurent84e9a102010-09-23 16:10:16 -07005369 // output must be specified by AudioPolicyManager when using session
Dima Zavinfce7a472011-04-19 22:30:36 -07005370 // AUDIO_SESSION_OUTPUT_STAGE
Eric Laurent84e9a102010-09-23 16:10:16 -07005371 lStatus = BAD_VALUE;
5372 goto Exit;
Dima Zavinfce7a472011-04-19 22:30:36 -07005373 } else if (sessionId == AUDIO_SESSION_OUTPUT_MIX) {
Eric Laurent84e9a102010-09-23 16:10:16 -07005374 // if the output returned by getOutputForEffect() is removed before we lock the
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005375 // mutex below, the call to checkPlaybackThread_l(io) below will detect it
Eric Laurent84e9a102010-09-23 16:10:16 -07005376 // and we will exit safely
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005377 io = AudioSystem::getOutputForEffect(&desc);
Eric Laurent84e9a102010-09-23 16:10:16 -07005378 }
5379 }
5380
Mathias Agopian65ab4712010-07-14 17:59:35 -07005381 {
5382 Mutex::Autolock _l(mLock);
5383
Mathias Agopian65ab4712010-07-14 17:59:35 -07005384
5385 if (!EffectIsNullUuid(&pDesc->uuid)) {
5386 // if uuid is specified, request effect descriptor
5387 lStatus = EffectGetDescriptor(&pDesc->uuid, &desc);
5388 if (lStatus < 0) {
5389 LOGW("createEffect() error %d from EffectGetDescriptor", lStatus);
5390 goto Exit;
5391 }
5392 } else {
5393 // if uuid is not specified, look for an available implementation
5394 // of the required type in effect factory
5395 if (EffectIsNullUuid(&pDesc->type)) {
5396 LOGW("createEffect() no effect type");
5397 lStatus = BAD_VALUE;
5398 goto Exit;
5399 }
5400 uint32_t numEffects = 0;
5401 effect_descriptor_t d;
Marco Nelissen3a34bef2011-08-02 13:33:41 -07005402 d.flags = 0; // prevent compiler warning
Mathias Agopian65ab4712010-07-14 17:59:35 -07005403 bool found = false;
5404
5405 lStatus = EffectQueryNumberEffects(&numEffects);
5406 if (lStatus < 0) {
5407 LOGW("createEffect() error %d from EffectQueryNumberEffects", lStatus);
5408 goto Exit;
5409 }
5410 for (uint32_t i = 0; i < numEffects; i++) {
5411 lStatus = EffectQueryEffect(i, &desc);
5412 if (lStatus < 0) {
5413 LOGW("createEffect() error %d from EffectQueryEffect", lStatus);
5414 continue;
5415 }
5416 if (memcmp(&desc.type, &pDesc->type, sizeof(effect_uuid_t)) == 0) {
5417 // If matching type found save effect descriptor. If the session is
5418 // 0 and the effect is not auxiliary, continue enumeration in case
5419 // an auxiliary version of this effect type is available
5420 found = true;
5421 memcpy(&d, &desc, sizeof(effect_descriptor_t));
Dima Zavinfce7a472011-04-19 22:30:36 -07005422 if (sessionId != AUDIO_SESSION_OUTPUT_MIX ||
Mathias Agopian65ab4712010-07-14 17:59:35 -07005423 (desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
5424 break;
5425 }
5426 }
5427 }
5428 if (!found) {
5429 lStatus = BAD_VALUE;
5430 LOGW("createEffect() effect not found");
5431 goto Exit;
5432 }
5433 // For same effect type, chose auxiliary version over insert version if
5434 // connect to output mix (Compliance to OpenSL ES)
Dima Zavinfce7a472011-04-19 22:30:36 -07005435 if (sessionId == AUDIO_SESSION_OUTPUT_MIX &&
Mathias Agopian65ab4712010-07-14 17:59:35 -07005436 (d.flags & EFFECT_FLAG_TYPE_MASK) != EFFECT_FLAG_TYPE_AUXILIARY) {
5437 memcpy(&desc, &d, sizeof(effect_descriptor_t));
5438 }
5439 }
5440
5441 // Do not allow auxiliary effects on a session different from 0 (output mix)
Dima Zavinfce7a472011-04-19 22:30:36 -07005442 if (sessionId != AUDIO_SESSION_OUTPUT_MIX &&
Mathias Agopian65ab4712010-07-14 17:59:35 -07005443 (desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
5444 lStatus = INVALID_OPERATION;
5445 goto Exit;
5446 }
5447
Eric Laurent59255e42011-07-27 19:49:51 -07005448 // check recording permission for visualizer
5449 if ((memcmp(&desc.type, SL_IID_VISUALIZATION, sizeof(effect_uuid_t)) == 0) &&
5450 !recordingAllowed()) {
5451 lStatus = PERMISSION_DENIED;
5452 goto Exit;
5453 }
5454
Mathias Agopian65ab4712010-07-14 17:59:35 -07005455 // return effect descriptor
5456 memcpy(pDesc, &desc, sizeof(effect_descriptor_t));
5457
5458 // If output is not specified try to find a matching audio session ID in one of the
5459 // output threads.
Eric Laurent84e9a102010-09-23 16:10:16 -07005460 // If output is 0 here, sessionId is neither SESSION_OUTPUT_STAGE nor SESSION_OUTPUT_MIX
5461 // because of code checking output when entering the function.
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005462 // Note: io is never 0 when creating an effect on an input
5463 if (io == 0) {
Eric Laurent84e9a102010-09-23 16:10:16 -07005464 // look for the thread where the specified audio session is present
5465 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
5466 if (mPlaybackThreads.valueAt(i)->hasAudioSession(sessionId) != 0) {
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005467 io = mPlaybackThreads.keyAt(i);
Eric Laurent84e9a102010-09-23 16:10:16 -07005468 break;
Eric Laurent39e94f82010-07-28 01:32:47 -07005469 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07005470 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005471 if (io == 0) {
5472 for (size_t i = 0; i < mRecordThreads.size(); i++) {
5473 if (mRecordThreads.valueAt(i)->hasAudioSession(sessionId) != 0) {
5474 io = mRecordThreads.keyAt(i);
5475 break;
5476 }
5477 }
5478 }
Eric Laurent84e9a102010-09-23 16:10:16 -07005479 // If no output thread contains the requested session ID, default to
5480 // first output. The effect chain will be moved to the correct output
5481 // thread when a track with the same session ID is created
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005482 if (io == 0 && mPlaybackThreads.size()) {
5483 io = mPlaybackThreads.keyAt(0);
5484 }
5485 LOGV("createEffect() got io %d for effect %s", io, desc.name);
5486 }
5487 ThreadBase *thread = checkRecordThread_l(io);
5488 if (thread == NULL) {
5489 thread = checkPlaybackThread_l(io);
5490 if (thread == NULL) {
5491 LOGE("createEffect() unknown output thread");
5492 lStatus = BAD_VALUE;
5493 goto Exit;
Eric Laurent84e9a102010-09-23 16:10:16 -07005494 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07005495 }
Eric Laurent84e9a102010-09-23 16:10:16 -07005496
Mathias Agopian65ab4712010-07-14 17:59:35 -07005497 wclient = mClients.valueFor(pid);
5498
5499 if (wclient != NULL) {
5500 client = wclient.promote();
5501 } else {
5502 client = new Client(this, pid);
5503 mClients.add(pid, client);
5504 }
5505
Marco Nelissen3a34bef2011-08-02 13:33:41 -07005506 // create effect on selected output thread
Eric Laurentde070132010-07-13 04:45:46 -07005507 handle = thread->createEffect_l(client, effectClient, priority, sessionId,
5508 &desc, enabled, &lStatus);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005509 if (handle != 0 && id != NULL) {
5510 *id = handle->id();
5511 }
5512 }
5513
5514Exit:
5515 if(status) {
5516 *status = lStatus;
5517 }
5518 return handle;
5519}
5520
Eric Laurent59255e42011-07-27 19:49:51 -07005521status_t AudioFlinger::moveEffects(int sessionId, int srcOutput, int dstOutput)
Eric Laurentde070132010-07-13 04:45:46 -07005522{
5523 LOGV("moveEffects() session %d, srcOutput %d, dstOutput %d",
Eric Laurent59255e42011-07-27 19:49:51 -07005524 sessionId, srcOutput, dstOutput);
Eric Laurentde070132010-07-13 04:45:46 -07005525 Mutex::Autolock _l(mLock);
5526 if (srcOutput == dstOutput) {
5527 LOGW("moveEffects() same dst and src outputs %d", dstOutput);
5528 return NO_ERROR;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005529 }
Eric Laurentde070132010-07-13 04:45:46 -07005530 PlaybackThread *srcThread = checkPlaybackThread_l(srcOutput);
5531 if (srcThread == NULL) {
5532 LOGW("moveEffects() bad srcOutput %d", srcOutput);
5533 return BAD_VALUE;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005534 }
Eric Laurentde070132010-07-13 04:45:46 -07005535 PlaybackThread *dstThread = checkPlaybackThread_l(dstOutput);
5536 if (dstThread == NULL) {
5537 LOGW("moveEffects() bad dstOutput %d", dstOutput);
5538 return BAD_VALUE;
5539 }
5540
5541 Mutex::Autolock _dl(dstThread->mLock);
5542 Mutex::Autolock _sl(srcThread->mLock);
Eric Laurent59255e42011-07-27 19:49:51 -07005543 moveEffectChain_l(sessionId, srcThread, dstThread, false);
Eric Laurentde070132010-07-13 04:45:46 -07005544
Mathias Agopian65ab4712010-07-14 17:59:35 -07005545 return NO_ERROR;
5546}
5547
Marco Nelissen3a34bef2011-08-02 13:33:41 -07005548// moveEffectChain_l must be called with both srcThread and dstThread mLocks held
Eric Laurent59255e42011-07-27 19:49:51 -07005549status_t AudioFlinger::moveEffectChain_l(int sessionId,
Eric Laurentde070132010-07-13 04:45:46 -07005550 AudioFlinger::PlaybackThread *srcThread,
Eric Laurent39e94f82010-07-28 01:32:47 -07005551 AudioFlinger::PlaybackThread *dstThread,
5552 bool reRegister)
Eric Laurentde070132010-07-13 04:45:46 -07005553{
5554 LOGV("moveEffectChain_l() session %d from thread %p to thread %p",
Eric Laurent59255e42011-07-27 19:49:51 -07005555 sessionId, srcThread, dstThread);
Eric Laurentde070132010-07-13 04:45:46 -07005556
Eric Laurent59255e42011-07-27 19:49:51 -07005557 sp<EffectChain> chain = srcThread->getEffectChain_l(sessionId);
Eric Laurentde070132010-07-13 04:45:46 -07005558 if (chain == 0) {
5559 LOGW("moveEffectChain_l() effect chain for session %d not on source thread %p",
Eric Laurent59255e42011-07-27 19:49:51 -07005560 sessionId, srcThread);
Eric Laurentde070132010-07-13 04:45:46 -07005561 return INVALID_OPERATION;
5562 }
5563
Eric Laurent39e94f82010-07-28 01:32:47 -07005564 // remove chain first. This is useful only if reconfiguring effect chain on same output thread,
Eric Laurentde070132010-07-13 04:45:46 -07005565 // so that a new chain is created with correct parameters when first effect is added. This is
Eric Laurentec35a142011-10-05 17:42:25 -07005566 // otherwise unnecessary as removeEffect_l() will remove the chain when last effect is
Eric Laurentde070132010-07-13 04:45:46 -07005567 // removed.
5568 srcThread->removeEffectChain_l(chain);
5569
5570 // transfer all effects one by one so that new effect chain is created on new thread with
5571 // correct buffer sizes and audio parameters and effect engines reconfigured accordingly
Eric Laurent39e94f82010-07-28 01:32:47 -07005572 int dstOutput = dstThread->id();
5573 sp<EffectChain> dstChain;
Marco Nelissen3a34bef2011-08-02 13:33:41 -07005574 uint32_t strategy = 0; // prevent compiler warning
Eric Laurentde070132010-07-13 04:45:46 -07005575 sp<EffectModule> effect = chain->getEffectFromId_l(0);
5576 while (effect != 0) {
5577 srcThread->removeEffect_l(effect);
5578 dstThread->addEffect_l(effect);
Eric Laurentec35a142011-10-05 17:42:25 -07005579 // removeEffect_l() has stopped the effect if it was active so it must be restarted
5580 if (effect->state() == EffectModule::ACTIVE ||
5581 effect->state() == EffectModule::STOPPING) {
5582 effect->start();
5583 }
Eric Laurent39e94f82010-07-28 01:32:47 -07005584 // if the move request is not received from audio policy manager, the effect must be
5585 // re-registered with the new strategy and output
5586 if (dstChain == 0) {
5587 dstChain = effect->chain().promote();
5588 if (dstChain == 0) {
5589 LOGW("moveEffectChain_l() cannot get chain from effect %p", effect.get());
5590 srcThread->addEffect_l(effect);
5591 return NO_INIT;
5592 }
5593 strategy = dstChain->strategy();
5594 }
5595 if (reRegister) {
5596 AudioSystem::unregisterEffect(effect->id());
5597 AudioSystem::registerEffect(&effect->desc(),
5598 dstOutput,
5599 strategy,
Eric Laurent59255e42011-07-27 19:49:51 -07005600 sessionId,
Eric Laurent39e94f82010-07-28 01:32:47 -07005601 effect->id());
5602 }
Eric Laurentde070132010-07-13 04:45:46 -07005603 effect = chain->getEffectFromId_l(0);
5604 }
5605
5606 return NO_ERROR;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005607}
5608
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005609
Mathias Agopian65ab4712010-07-14 17:59:35 -07005610// PlaybackThread::createEffect_l() must be called with AudioFlinger::mLock held
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005611sp<AudioFlinger::EffectHandle> AudioFlinger::ThreadBase::createEffect_l(
Mathias Agopian65ab4712010-07-14 17:59:35 -07005612 const sp<AudioFlinger::Client>& client,
5613 const sp<IEffectClient>& effectClient,
5614 int32_t priority,
5615 int sessionId,
5616 effect_descriptor_t *desc,
5617 int *enabled,
5618 status_t *status
5619 )
5620{
5621 sp<EffectModule> effect;
5622 sp<EffectHandle> handle;
5623 status_t lStatus;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005624 sp<EffectChain> chain;
Eric Laurentde070132010-07-13 04:45:46 -07005625 bool chainCreated = false;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005626 bool effectCreated = false;
5627 bool effectRegistered = false;
5628
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005629 lStatus = initCheck();
5630 if (lStatus != NO_ERROR) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07005631 LOGW("createEffect_l() Audio driver not initialized.");
Mathias Agopian65ab4712010-07-14 17:59:35 -07005632 goto Exit;
5633 }
5634
5635 // Do not allow effects with session ID 0 on direct output or duplicating threads
5636 // TODO: add rule for hw accelerated effects on direct outputs with non PCM format
Dima Zavinfce7a472011-04-19 22:30:36 -07005637 if (sessionId == AUDIO_SESSION_OUTPUT_MIX && mType != MIXER) {
Eric Laurentde070132010-07-13 04:45:46 -07005638 LOGW("createEffect_l() Cannot add auxiliary effect %s to session %d",
5639 desc->name, sessionId);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005640 lStatus = BAD_VALUE;
5641 goto Exit;
5642 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005643 // Only Pre processor effects are allowed on input threads and only on input threads
5644 if ((mType == RECORD &&
5645 (desc->flags & EFFECT_FLAG_TYPE_MASK) != EFFECT_FLAG_TYPE_PRE_PROC) ||
5646 (mType != RECORD &&
5647 (desc->flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC)) {
5648 LOGW("createEffect_l() effect %s (flags %08x) created on wrong thread type %d",
5649 desc->name, desc->flags, mType);
5650 lStatus = BAD_VALUE;
5651 goto Exit;
5652 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07005653
5654 LOGV("createEffect_l() thread %p effect %s on session %d", this, desc->name, sessionId);
5655
5656 { // scope for mLock
5657 Mutex::Autolock _l(mLock);
5658
5659 // check for existing effect chain with the requested audio session
5660 chain = getEffectChain_l(sessionId);
5661 if (chain == 0) {
5662 // create a new chain for this session
5663 LOGV("createEffect_l() new effect chain for session %d", sessionId);
5664 chain = new EffectChain(this, sessionId);
5665 addEffectChain_l(chain);
Eric Laurentde070132010-07-13 04:45:46 -07005666 chain->setStrategy(getStrategyForSession_l(sessionId));
5667 chainCreated = true;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005668 } else {
Eric Laurentcab11242010-07-15 12:50:15 -07005669 effect = chain->getEffectFromDesc_l(desc);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005670 }
5671
5672 LOGV("createEffect_l() got effect %p on chain %p", effect == 0 ? 0 : effect.get(), chain.get());
5673
5674 if (effect == 0) {
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005675 int id = mAudioFlinger->nextUniqueId();
Mathias Agopian65ab4712010-07-14 17:59:35 -07005676 // Check CPU and memory usage
Eric Laurentde070132010-07-13 04:45:46 -07005677 lStatus = AudioSystem::registerEffect(desc, mId, chain->strategy(), sessionId, id);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005678 if (lStatus != NO_ERROR) {
5679 goto Exit;
5680 }
5681 effectRegistered = true;
5682 // create a new effect module if none present in the chain
Eric Laurentde070132010-07-13 04:45:46 -07005683 effect = new EffectModule(this, chain, desc, id, sessionId);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005684 lStatus = effect->status();
5685 if (lStatus != NO_ERROR) {
5686 goto Exit;
5687 }
Eric Laurentcab11242010-07-15 12:50:15 -07005688 lStatus = chain->addEffect_l(effect);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005689 if (lStatus != NO_ERROR) {
5690 goto Exit;
5691 }
5692 effectCreated = true;
5693
5694 effect->setDevice(mDevice);
5695 effect->setMode(mAudioFlinger->getMode());
5696 }
5697 // create effect handle and connect it to effect module
5698 handle = new EffectHandle(effect, client, effectClient, priority);
5699 lStatus = effect->addHandle(handle);
5700 if (enabled) {
5701 *enabled = (int)effect->isEnabled();
5702 }
5703 }
5704
5705Exit:
5706 if (lStatus != NO_ERROR && lStatus != ALREADY_EXISTS) {
Eric Laurentde070132010-07-13 04:45:46 -07005707 Mutex::Autolock _l(mLock);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005708 if (effectCreated) {
Eric Laurentde070132010-07-13 04:45:46 -07005709 chain->removeEffect_l(effect);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005710 }
5711 if (effectRegistered) {
Eric Laurentde070132010-07-13 04:45:46 -07005712 AudioSystem::unregisterEffect(effect->id());
5713 }
5714 if (chainCreated) {
5715 removeEffectChain_l(chain);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005716 }
5717 handle.clear();
5718 }
5719
5720 if(status) {
5721 *status = lStatus;
5722 }
5723 return handle;
5724}
5725
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005726sp<AudioFlinger::EffectModule> AudioFlinger::ThreadBase::getEffect_l(int sessionId, int effectId)
5727{
5728 sp<EffectModule> effect;
5729
5730 sp<EffectChain> chain = getEffectChain_l(sessionId);
5731 if (chain != 0) {
5732 effect = chain->getEffectFromId_l(effectId);
5733 }
5734 return effect;
5735}
5736
Eric Laurentde070132010-07-13 04:45:46 -07005737// PlaybackThread::addEffect_l() must be called with AudioFlinger::mLock and
5738// PlaybackThread::mLock held
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005739status_t AudioFlinger::ThreadBase::addEffect_l(const sp<EffectModule>& effect)
Eric Laurentde070132010-07-13 04:45:46 -07005740{
5741 // check for existing effect chain with the requested audio session
5742 int sessionId = effect->sessionId();
5743 sp<EffectChain> chain = getEffectChain_l(sessionId);
5744 bool chainCreated = false;
5745
5746 if (chain == 0) {
5747 // create a new chain for this session
5748 LOGV("addEffect_l() new effect chain for session %d", sessionId);
5749 chain = new EffectChain(this, sessionId);
5750 addEffectChain_l(chain);
5751 chain->setStrategy(getStrategyForSession_l(sessionId));
5752 chainCreated = true;
5753 }
5754 LOGV("addEffect_l() %p chain %p effect %p", this, chain.get(), effect.get());
5755
5756 if (chain->getEffectFromId_l(effect->id()) != 0) {
5757 LOGW("addEffect_l() %p effect %s already present in chain %p",
5758 this, effect->desc().name, chain.get());
5759 return BAD_VALUE;
5760 }
5761
5762 status_t status = chain->addEffect_l(effect);
5763 if (status != NO_ERROR) {
5764 if (chainCreated) {
5765 removeEffectChain_l(chain);
5766 }
5767 return status;
5768 }
5769
5770 effect->setDevice(mDevice);
5771 effect->setMode(mAudioFlinger->getMode());
5772 return NO_ERROR;
5773}
5774
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005775void AudioFlinger::ThreadBase::removeEffect_l(const sp<EffectModule>& effect) {
Eric Laurentde070132010-07-13 04:45:46 -07005776
5777 LOGV("removeEffect_l() %p effect %p", this, effect.get());
Mathias Agopian65ab4712010-07-14 17:59:35 -07005778 effect_descriptor_t desc = effect->desc();
Eric Laurentde070132010-07-13 04:45:46 -07005779 if ((desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
5780 detachAuxEffect_l(effect->id());
5781 }
5782
5783 sp<EffectChain> chain = effect->chain().promote();
5784 if (chain != 0) {
5785 // remove effect chain if removing last effect
5786 if (chain->removeEffect_l(effect) == 0) {
5787 removeEffectChain_l(chain);
5788 }
5789 } else {
5790 LOGW("removeEffect_l() %p cannot promote chain for effect %p", this, effect.get());
5791 }
5792}
5793
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005794void AudioFlinger::ThreadBase::lockEffectChains_l(
5795 Vector<sp <AudioFlinger::EffectChain> >& effectChains)
5796{
5797 effectChains = mEffectChains;
5798 for (size_t i = 0; i < mEffectChains.size(); i++) {
5799 mEffectChains[i]->lock();
5800 }
5801}
5802
5803void AudioFlinger::ThreadBase::unlockEffectChains(
5804 Vector<sp <AudioFlinger::EffectChain> >& effectChains)
5805{
5806 for (size_t i = 0; i < effectChains.size(); i++) {
5807 effectChains[i]->unlock();
5808 }
5809}
5810
5811sp<AudioFlinger::EffectChain> AudioFlinger::ThreadBase::getEffectChain(int sessionId)
5812{
5813 Mutex::Autolock _l(mLock);
5814 return getEffectChain_l(sessionId);
5815}
5816
5817sp<AudioFlinger::EffectChain> AudioFlinger::ThreadBase::getEffectChain_l(int sessionId)
5818{
5819 sp<EffectChain> chain;
5820
5821 size_t size = mEffectChains.size();
5822 for (size_t i = 0; i < size; i++) {
5823 if (mEffectChains[i]->sessionId() == sessionId) {
5824 chain = mEffectChains[i];
5825 break;
5826 }
5827 }
5828 return chain;
5829}
5830
5831void AudioFlinger::ThreadBase::setMode(uint32_t mode)
5832{
5833 Mutex::Autolock _l(mLock);
5834 size_t size = mEffectChains.size();
5835 for (size_t i = 0; i < size; i++) {
5836 mEffectChains[i]->setMode_l(mode);
5837 }
5838}
5839
5840void AudioFlinger::ThreadBase::disconnectEffect(const sp<EffectModule>& effect,
Marco Nelissen3a34bef2011-08-02 13:33:41 -07005841 const wp<EffectHandle>& handle,
5842 bool unpiniflast) {
Eric Laurent59255e42011-07-27 19:49:51 -07005843
Mathias Agopian65ab4712010-07-14 17:59:35 -07005844 Mutex::Autolock _l(mLock);
Eric Laurentde070132010-07-13 04:45:46 -07005845 LOGV("disconnectEffect() %p effect %p", this, effect.get());
Mathias Agopian65ab4712010-07-14 17:59:35 -07005846 // delete the effect module if removing last handle on it
5847 if (effect->removeHandle(handle) == 0) {
Marco Nelissen3a34bef2011-08-02 13:33:41 -07005848 if (!effect->isPinned() || unpiniflast) {
5849 removeEffect_l(effect);
5850 AudioSystem::unregisterEffect(effect->id());
5851 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07005852 }
5853}
5854
5855status_t AudioFlinger::PlaybackThread::addEffectChain_l(const sp<EffectChain>& chain)
5856{
5857 int session = chain->sessionId();
5858 int16_t *buffer = mMixBuffer;
5859 bool ownsBuffer = false;
5860
5861 LOGV("addEffectChain_l() %p on thread %p for session %d", chain.get(), this, session);
5862 if (session > 0) {
5863 // Only one effect chain can be present in direct output thread and it uses
5864 // the mix buffer as input
5865 if (mType != DIRECT) {
5866 size_t numSamples = mFrameCount * mChannelCount;
5867 buffer = new int16_t[numSamples];
5868 memset(buffer, 0, numSamples * sizeof(int16_t));
5869 LOGV("addEffectChain_l() creating new input buffer %p session %d", buffer, session);
5870 ownsBuffer = true;
5871 }
5872
5873 // Attach all tracks with same session ID to this chain.
5874 for (size_t i = 0; i < mTracks.size(); ++i) {
5875 sp<Track> track = mTracks[i];
5876 if (session == track->sessionId()) {
5877 LOGV("addEffectChain_l() track->setMainBuffer track %p buffer %p", track.get(), buffer);
5878 track->setMainBuffer(buffer);
Eric Laurentb469b942011-05-09 12:09:06 -07005879 chain->incTrackCnt();
Mathias Agopian65ab4712010-07-14 17:59:35 -07005880 }
5881 }
5882
5883 // indicate all active tracks in the chain
5884 for (size_t i = 0 ; i < mActiveTracks.size() ; ++i) {
5885 sp<Track> track = mActiveTracks[i].promote();
5886 if (track == 0) continue;
5887 if (session == track->sessionId()) {
5888 LOGV("addEffectChain_l() activating track %p on session %d", track.get(), session);
Eric Laurentb469b942011-05-09 12:09:06 -07005889 chain->incActiveTrackCnt();
Mathias Agopian65ab4712010-07-14 17:59:35 -07005890 }
5891 }
5892 }
5893
5894 chain->setInBuffer(buffer, ownsBuffer);
5895 chain->setOutBuffer(mMixBuffer);
Dima Zavinfce7a472011-04-19 22:30:36 -07005896 // Effect chain for session AUDIO_SESSION_OUTPUT_STAGE is inserted at end of effect
Eric Laurentde070132010-07-13 04:45:46 -07005897 // chains list in order to be processed last as it contains output stage effects
Dima Zavinfce7a472011-04-19 22:30:36 -07005898 // Effect chain for session AUDIO_SESSION_OUTPUT_MIX is inserted before
5899 // session AUDIO_SESSION_OUTPUT_STAGE to be processed
Mathias Agopian65ab4712010-07-14 17:59:35 -07005900 // after track specific effects and before output stage
Dima Zavinfce7a472011-04-19 22:30:36 -07005901 // It is therefore mandatory that AUDIO_SESSION_OUTPUT_MIX == 0 and
5902 // that AUDIO_SESSION_OUTPUT_STAGE < AUDIO_SESSION_OUTPUT_MIX
Eric Laurentde070132010-07-13 04:45:46 -07005903 // Effect chain for other sessions are inserted at beginning of effect
5904 // chains list to be processed before output mix effects. Relative order between other
5905 // sessions is not important
Mathias Agopian65ab4712010-07-14 17:59:35 -07005906 size_t size = mEffectChains.size();
5907 size_t i = 0;
5908 for (i = 0; i < size; i++) {
5909 if (mEffectChains[i]->sessionId() < session) break;
5910 }
5911 mEffectChains.insertAt(chain, i);
Eric Laurent59255e42011-07-27 19:49:51 -07005912 checkSuspendOnAddEffectChain_l(chain);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005913
5914 return NO_ERROR;
5915}
5916
5917size_t AudioFlinger::PlaybackThread::removeEffectChain_l(const sp<EffectChain>& chain)
5918{
5919 int session = chain->sessionId();
5920
5921 LOGV("removeEffectChain_l() %p from thread %p for session %d", chain.get(), this, session);
5922
5923 for (size_t i = 0; i < mEffectChains.size(); i++) {
5924 if (chain == mEffectChains[i]) {
5925 mEffectChains.removeAt(i);
Eric Laurentb469b942011-05-09 12:09:06 -07005926 // detach all active tracks from the chain
5927 for (size_t i = 0 ; i < mActiveTracks.size() ; ++i) {
5928 sp<Track> track = mActiveTracks[i].promote();
5929 if (track == 0) continue;
5930 if (session == track->sessionId()) {
5931 LOGV("removeEffectChain_l(): stopping track on chain %p for session Id: %d",
5932 chain.get(), session);
5933 chain->decActiveTrackCnt();
5934 }
5935 }
5936
Mathias Agopian65ab4712010-07-14 17:59:35 -07005937 // detach all tracks with same session ID from this chain
5938 for (size_t i = 0; i < mTracks.size(); ++i) {
5939 sp<Track> track = mTracks[i];
5940 if (session == track->sessionId()) {
5941 track->setMainBuffer(mMixBuffer);
Eric Laurentb469b942011-05-09 12:09:06 -07005942 chain->decTrackCnt();
Mathias Agopian65ab4712010-07-14 17:59:35 -07005943 }
5944 }
Eric Laurentde070132010-07-13 04:45:46 -07005945 break;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005946 }
5947 }
5948 return mEffectChains.size();
5949}
5950
Eric Laurentde070132010-07-13 04:45:46 -07005951status_t AudioFlinger::PlaybackThread::attachAuxEffect(
5952 const sp<AudioFlinger::PlaybackThread::Track> track, int EffectId)
Mathias Agopian65ab4712010-07-14 17:59:35 -07005953{
5954 Mutex::Autolock _l(mLock);
5955 return attachAuxEffect_l(track, EffectId);
5956}
5957
Eric Laurentde070132010-07-13 04:45:46 -07005958status_t AudioFlinger::PlaybackThread::attachAuxEffect_l(
5959 const sp<AudioFlinger::PlaybackThread::Track> track, int EffectId)
Mathias Agopian65ab4712010-07-14 17:59:35 -07005960{
5961 status_t status = NO_ERROR;
5962
5963 if (EffectId == 0) {
5964 track->setAuxBuffer(0, NULL);
5965 } else {
Dima Zavinfce7a472011-04-19 22:30:36 -07005966 // Auxiliary effects are always in audio session AUDIO_SESSION_OUTPUT_MIX
5967 sp<EffectModule> effect = getEffect_l(AUDIO_SESSION_OUTPUT_MIX, EffectId);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005968 if (effect != 0) {
5969 if ((effect->desc().flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
5970 track->setAuxBuffer(EffectId, (int32_t *)effect->inBuffer());
5971 } else {
5972 status = INVALID_OPERATION;
5973 }
5974 } else {
5975 status = BAD_VALUE;
5976 }
5977 }
5978 return status;
5979}
5980
5981void AudioFlinger::PlaybackThread::detachAuxEffect_l(int effectId)
5982{
5983 for (size_t i = 0; i < mTracks.size(); ++i) {
5984 sp<Track> track = mTracks[i];
5985 if (track->auxEffectId() == effectId) {
5986 attachAuxEffect_l(track, 0);
5987 }
5988 }
5989}
5990
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005991status_t AudioFlinger::RecordThread::addEffectChain_l(const sp<EffectChain>& chain)
5992{
5993 // only one chain per input thread
5994 if (mEffectChains.size() != 0) {
5995 return INVALID_OPERATION;
5996 }
5997 LOGV("addEffectChain_l() %p on thread %p", chain.get(), this);
5998
5999 chain->setInBuffer(NULL);
6000 chain->setOutBuffer(NULL);
6001
Eric Laurent59255e42011-07-27 19:49:51 -07006002 checkSuspendOnAddEffectChain_l(chain);
6003
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006004 mEffectChains.add(chain);
6005
6006 return NO_ERROR;
6007}
6008
6009size_t AudioFlinger::RecordThread::removeEffectChain_l(const sp<EffectChain>& chain)
6010{
6011 LOGV("removeEffectChain_l() %p from thread %p", chain.get(), this);
6012 LOGW_IF(mEffectChains.size() != 1,
6013 "removeEffectChain_l() %p invalid chain size %d on thread %p",
6014 chain.get(), mEffectChains.size(), this);
6015 if (mEffectChains.size() == 1) {
6016 mEffectChains.removeAt(0);
6017 }
6018 return 0;
6019}
6020
Mathias Agopian65ab4712010-07-14 17:59:35 -07006021// ----------------------------------------------------------------------------
6022// EffectModule implementation
6023// ----------------------------------------------------------------------------
6024
6025#undef LOG_TAG
6026#define LOG_TAG "AudioFlinger::EffectModule"
6027
6028AudioFlinger::EffectModule::EffectModule(const wp<ThreadBase>& wThread,
6029 const wp<AudioFlinger::EffectChain>& chain,
6030 effect_descriptor_t *desc,
6031 int id,
6032 int sessionId)
6033 : mThread(wThread), mChain(chain), mId(id), mSessionId(sessionId), mEffectInterface(NULL),
Eric Laurent59255e42011-07-27 19:49:51 -07006034 mStatus(NO_INIT), mState(IDLE), mSuspended(false)
Mathias Agopian65ab4712010-07-14 17:59:35 -07006035{
6036 LOGV("Constructor %p", this);
6037 int lStatus;
6038 sp<ThreadBase> thread = mThread.promote();
6039 if (thread == 0) {
6040 return;
6041 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07006042
6043 memcpy(&mDescriptor, desc, sizeof(effect_descriptor_t));
6044
6045 // create effect engine from effect factory
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006046 mStatus = EffectCreate(&desc->uuid, sessionId, thread->id(), &mEffectInterface);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006047
6048 if (mStatus != NO_ERROR) {
6049 return;
6050 }
6051 lStatus = init();
6052 if (lStatus < 0) {
6053 mStatus = lStatus;
6054 goto Error;
6055 }
6056
Marco Nelissen3a34bef2011-08-02 13:33:41 -07006057 if (mSessionId > AUDIO_SESSION_OUTPUT_MIX) {
6058 mPinned = true;
6059 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07006060 LOGV("Constructor success name %s, Interface %p", mDescriptor.name, mEffectInterface);
6061 return;
6062Error:
6063 EffectRelease(mEffectInterface);
6064 mEffectInterface = NULL;
6065 LOGV("Constructor Error %d", mStatus);
6066}
6067
6068AudioFlinger::EffectModule::~EffectModule()
6069{
6070 LOGV("Destructor %p", this);
6071 if (mEffectInterface != NULL) {
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006072 if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC ||
6073 (mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_POST_PROC) {
6074 sp<ThreadBase> thread = mThread.promote();
6075 if (thread != 0) {
Eric Laurentb8ba0a92011-08-07 16:32:26 -07006076 audio_stream_t *stream = thread->stream();
6077 if (stream != NULL) {
6078 stream->remove_audio_effect(stream, mEffectInterface);
6079 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006080 }
6081 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07006082 // release effect engine
6083 EffectRelease(mEffectInterface);
6084 }
6085}
6086
6087status_t AudioFlinger::EffectModule::addHandle(sp<EffectHandle>& handle)
6088{
6089 status_t status;
6090
6091 Mutex::Autolock _l(mLock);
6092 // First handle in mHandles has highest priority and controls the effect module
6093 int priority = handle->priority();
6094 size_t size = mHandles.size();
6095 sp<EffectHandle> h;
6096 size_t i;
6097 for (i = 0; i < size; i++) {
6098 h = mHandles[i].promote();
6099 if (h == 0) continue;
6100 if (h->priority() <= priority) break;
6101 }
6102 // if inserted in first place, move effect control from previous owner to this handle
6103 if (i == 0) {
Eric Laurent59255e42011-07-27 19:49:51 -07006104 bool enabled = false;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006105 if (h != 0) {
Eric Laurent59255e42011-07-27 19:49:51 -07006106 enabled = h->enabled();
6107 h->setControl(false/*hasControl*/, true /*signal*/, enabled /*enabled*/);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006108 }
Eric Laurent59255e42011-07-27 19:49:51 -07006109 handle->setControl(true /*hasControl*/, false /*signal*/, enabled /*enabled*/);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006110 status = NO_ERROR;
6111 } else {
6112 status = ALREADY_EXISTS;
6113 }
Eric Laurent59255e42011-07-27 19:49:51 -07006114 LOGV("addHandle() %p added handle %p in position %d", this, handle.get(), i);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006115 mHandles.insertAt(handle, i);
6116 return status;
6117}
6118
6119size_t AudioFlinger::EffectModule::removeHandle(const wp<EffectHandle>& handle)
6120{
6121 Mutex::Autolock _l(mLock);
6122 size_t size = mHandles.size();
6123 size_t i;
6124 for (i = 0; i < size; i++) {
6125 if (mHandles[i] == handle) break;
6126 }
6127 if (i == size) {
6128 return size;
6129 }
Eric Laurent59255e42011-07-27 19:49:51 -07006130 LOGV("removeHandle() %p removed handle %p in position %d", this, handle.unsafe_get(), i);
6131
6132 bool enabled = false;
6133 EffectHandle *hdl = handle.unsafe_get();
6134 if (hdl) {
6135 LOGV("removeHandle() unsafe_get OK");
6136 enabled = hdl->enabled();
6137 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07006138 mHandles.removeAt(i);
6139 size = mHandles.size();
6140 // if removed from first place, move effect control from this handle to next in line
6141 if (i == 0 && size != 0) {
6142 sp<EffectHandle> h = mHandles[0].promote();
6143 if (h != 0) {
Eric Laurent59255e42011-07-27 19:49:51 -07006144 h->setControl(true /*hasControl*/, true /*signal*/ , enabled /*enabled*/);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006145 }
6146 }
6147
Eric Laurentec437d82011-07-26 20:54:46 -07006148 // Prevent calls to process() and other functions on effect interface from now on.
6149 // The effect engine will be released by the destructor when the last strong reference on
6150 // this object is released which can happen after next process is called.
Marco Nelissen3a34bef2011-08-02 13:33:41 -07006151 if (size == 0 && !mPinned) {
Eric Laurentec437d82011-07-26 20:54:46 -07006152 mState = DESTROYED;
Eric Laurentdac69112010-09-28 14:09:57 -07006153 }
6154
Mathias Agopian65ab4712010-07-14 17:59:35 -07006155 return size;
6156}
6157
Eric Laurent59255e42011-07-27 19:49:51 -07006158sp<AudioFlinger::EffectHandle> AudioFlinger::EffectModule::controlHandle()
6159{
6160 Mutex::Autolock _l(mLock);
6161 sp<EffectHandle> handle;
6162 if (mHandles.size() != 0) {
6163 handle = mHandles[0].promote();
6164 }
6165 return handle;
6166}
6167
Marco Nelissen3a34bef2011-08-02 13:33:41 -07006168void AudioFlinger::EffectModule::disconnect(const wp<EffectHandle>& handle, bool unpiniflast)
Mathias Agopian65ab4712010-07-14 17:59:35 -07006169{
Eric Laurent59255e42011-07-27 19:49:51 -07006170 LOGV("disconnect() %p handle %p ", this, handle.unsafe_get());
Mathias Agopian65ab4712010-07-14 17:59:35 -07006171 // keep a strong reference on this EffectModule to avoid calling the
6172 // destructor before we exit
6173 sp<EffectModule> keep(this);
6174 {
6175 sp<ThreadBase> thread = mThread.promote();
6176 if (thread != 0) {
Marco Nelissen3a34bef2011-08-02 13:33:41 -07006177 thread->disconnectEffect(keep, handle, unpiniflast);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006178 }
6179 }
6180}
6181
6182void AudioFlinger::EffectModule::updateState() {
6183 Mutex::Autolock _l(mLock);
6184
6185 switch (mState) {
6186 case RESTART:
6187 reset_l();
6188 // FALL THROUGH
6189
6190 case STARTING:
6191 // clear auxiliary effect input buffer for next accumulation
6192 if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
6193 memset(mConfig.inputCfg.buffer.raw,
6194 0,
6195 mConfig.inputCfg.buffer.frameCount*sizeof(int32_t));
6196 }
6197 start_l();
6198 mState = ACTIVE;
6199 break;
6200 case STOPPING:
6201 stop_l();
6202 mDisableWaitCnt = mMaxDisableWaitCnt;
6203 mState = STOPPED;
6204 break;
6205 case STOPPED:
6206 // mDisableWaitCnt is forced to 1 by process() when the engine indicates the end of the
6207 // turn off sequence.
6208 if (--mDisableWaitCnt == 0) {
6209 reset_l();
6210 mState = IDLE;
6211 }
6212 break;
Eric Laurentec437d82011-07-26 20:54:46 -07006213 default: //IDLE , ACTIVE, DESTROYED
Mathias Agopian65ab4712010-07-14 17:59:35 -07006214 break;
6215 }
6216}
6217
6218void AudioFlinger::EffectModule::process()
6219{
6220 Mutex::Autolock _l(mLock);
6221
Eric Laurentec437d82011-07-26 20:54:46 -07006222 if (mState == DESTROYED || mEffectInterface == NULL ||
Mathias Agopian65ab4712010-07-14 17:59:35 -07006223 mConfig.inputCfg.buffer.raw == NULL ||
6224 mConfig.outputCfg.buffer.raw == NULL) {
6225 return;
6226 }
6227
Eric Laurent8f45bd72010-08-31 13:50:07 -07006228 if (isProcessEnabled()) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07006229 // do 32 bit to 16 bit conversion for auxiliary effect input buffer
6230 if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
6231 AudioMixer::ditherAndClamp(mConfig.inputCfg.buffer.s32,
6232 mConfig.inputCfg.buffer.s32,
Eric Laurentde070132010-07-13 04:45:46 -07006233 mConfig.inputCfg.buffer.frameCount/2);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006234 }
6235
6236 // do the actual processing in the effect engine
6237 int ret = (*mEffectInterface)->process(mEffectInterface,
6238 &mConfig.inputCfg.buffer,
6239 &mConfig.outputCfg.buffer);
6240
6241 // force transition to IDLE state when engine is ready
6242 if (mState == STOPPED && ret == -ENODATA) {
6243 mDisableWaitCnt = 1;
6244 }
6245
6246 // clear auxiliary effect input buffer for next accumulation
6247 if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
Eric Laurent73337482011-01-19 18:36:13 -08006248 memset(mConfig.inputCfg.buffer.raw, 0,
6249 mConfig.inputCfg.buffer.frameCount*sizeof(int32_t));
Mathias Agopian65ab4712010-07-14 17:59:35 -07006250 }
6251 } else if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_INSERT &&
Eric Laurent73337482011-01-19 18:36:13 -08006252 mConfig.inputCfg.buffer.raw != mConfig.outputCfg.buffer.raw) {
6253 // If an insert effect is idle and input buffer is different from output buffer,
6254 // accumulate input onto output
Mathias Agopian65ab4712010-07-14 17:59:35 -07006255 sp<EffectChain> chain = mChain.promote();
Eric Laurentb469b942011-05-09 12:09:06 -07006256 if (chain != 0 && chain->activeTrackCnt() != 0) {
Eric Laurent73337482011-01-19 18:36:13 -08006257 size_t frameCnt = mConfig.inputCfg.buffer.frameCount * 2; //always stereo here
6258 int16_t *in = mConfig.inputCfg.buffer.s16;
6259 int16_t *out = mConfig.outputCfg.buffer.s16;
6260 for (size_t i = 0; i < frameCnt; i++) {
6261 out[i] = clamp16((int32_t)out[i] + (int32_t)in[i]);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006262 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07006263 }
6264 }
6265}
6266
6267void AudioFlinger::EffectModule::reset_l()
6268{
6269 if (mEffectInterface == NULL) {
6270 return;
6271 }
6272 (*mEffectInterface)->command(mEffectInterface, EFFECT_CMD_RESET, 0, NULL, 0, NULL);
6273}
6274
6275status_t AudioFlinger::EffectModule::configure()
6276{
6277 uint32_t channels;
6278 if (mEffectInterface == NULL) {
6279 return NO_INIT;
6280 }
6281
6282 sp<ThreadBase> thread = mThread.promote();
6283 if (thread == 0) {
6284 return DEAD_OBJECT;
6285 }
6286
6287 // TODO: handle configuration of effects replacing track process
6288 if (thread->channelCount() == 1) {
Eric Laurente1315cf2011-05-17 19:16:02 -07006289 channels = AUDIO_CHANNEL_OUT_MONO;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006290 } else {
Eric Laurente1315cf2011-05-17 19:16:02 -07006291 channels = AUDIO_CHANNEL_OUT_STEREO;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006292 }
6293
6294 if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
Eric Laurente1315cf2011-05-17 19:16:02 -07006295 mConfig.inputCfg.channels = AUDIO_CHANNEL_OUT_MONO;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006296 } else {
6297 mConfig.inputCfg.channels = channels;
6298 }
6299 mConfig.outputCfg.channels = channels;
Eric Laurente1315cf2011-05-17 19:16:02 -07006300 mConfig.inputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
6301 mConfig.outputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006302 mConfig.inputCfg.samplingRate = thread->sampleRate();
6303 mConfig.outputCfg.samplingRate = mConfig.inputCfg.samplingRate;
6304 mConfig.inputCfg.bufferProvider.cookie = NULL;
6305 mConfig.inputCfg.bufferProvider.getBuffer = NULL;
6306 mConfig.inputCfg.bufferProvider.releaseBuffer = NULL;
6307 mConfig.outputCfg.bufferProvider.cookie = NULL;
6308 mConfig.outputCfg.bufferProvider.getBuffer = NULL;
6309 mConfig.outputCfg.bufferProvider.releaseBuffer = NULL;
6310 mConfig.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ;
6311 // Insert effect:
Dima Zavinfce7a472011-04-19 22:30:36 -07006312 // - in session AUDIO_SESSION_OUTPUT_MIX or AUDIO_SESSION_OUTPUT_STAGE,
Eric Laurentde070132010-07-13 04:45:46 -07006313 // always overwrites output buffer: input buffer == output buffer
Mathias Agopian65ab4712010-07-14 17:59:35 -07006314 // - in other sessions:
6315 // last effect in the chain accumulates in output buffer: input buffer != output buffer
6316 // other effect: overwrites output buffer: input buffer == output buffer
6317 // Auxiliary effect:
6318 // accumulates in output buffer: input buffer != output buffer
6319 // Therefore: accumulate <=> input buffer != output buffer
6320 if (mConfig.inputCfg.buffer.raw != mConfig.outputCfg.buffer.raw) {
6321 mConfig.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_ACCUMULATE;
6322 } else {
6323 mConfig.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_WRITE;
6324 }
6325 mConfig.inputCfg.mask = EFFECT_CONFIG_ALL;
6326 mConfig.outputCfg.mask = EFFECT_CONFIG_ALL;
6327 mConfig.inputCfg.buffer.frameCount = thread->frameCount();
6328 mConfig.outputCfg.buffer.frameCount = mConfig.inputCfg.buffer.frameCount;
6329
Eric Laurentde070132010-07-13 04:45:46 -07006330 LOGV("configure() %p thread %p buffer %p framecount %d",
6331 this, thread.get(), mConfig.inputCfg.buffer.raw, mConfig.inputCfg.buffer.frameCount);
6332
Mathias Agopian65ab4712010-07-14 17:59:35 -07006333 status_t cmdStatus;
Eric Laurent25f43952010-07-28 05:40:18 -07006334 uint32_t size = sizeof(int);
6335 status_t status = (*mEffectInterface)->command(mEffectInterface,
6336 EFFECT_CMD_CONFIGURE,
6337 sizeof(effect_config_t),
6338 &mConfig,
6339 &size,
6340 &cmdStatus);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006341 if (status == 0) {
6342 status = cmdStatus;
6343 }
6344
6345 mMaxDisableWaitCnt = (MAX_DISABLE_TIME_MS * mConfig.outputCfg.samplingRate) /
6346 (1000 * mConfig.outputCfg.buffer.frameCount);
6347
6348 return status;
6349}
6350
6351status_t AudioFlinger::EffectModule::init()
6352{
6353 Mutex::Autolock _l(mLock);
6354 if (mEffectInterface == NULL) {
6355 return NO_INIT;
6356 }
6357 status_t cmdStatus;
Eric Laurent25f43952010-07-28 05:40:18 -07006358 uint32_t size = sizeof(status_t);
6359 status_t status = (*mEffectInterface)->command(mEffectInterface,
6360 EFFECT_CMD_INIT,
6361 0,
6362 NULL,
6363 &size,
6364 &cmdStatus);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006365 if (status == 0) {
6366 status = cmdStatus;
6367 }
6368 return status;
6369}
6370
Eric Laurentec35a142011-10-05 17:42:25 -07006371status_t AudioFlinger::EffectModule::start()
6372{
6373 Mutex::Autolock _l(mLock);
6374 return start_l();
6375}
6376
Mathias Agopian65ab4712010-07-14 17:59:35 -07006377status_t AudioFlinger::EffectModule::start_l()
6378{
6379 if (mEffectInterface == NULL) {
6380 return NO_INIT;
6381 }
6382 status_t cmdStatus;
Eric Laurent25f43952010-07-28 05:40:18 -07006383 uint32_t size = sizeof(status_t);
6384 status_t status = (*mEffectInterface)->command(mEffectInterface,
6385 EFFECT_CMD_ENABLE,
6386 0,
6387 NULL,
6388 &size,
6389 &cmdStatus);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006390 if (status == 0) {
6391 status = cmdStatus;
6392 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006393 if (status == 0 &&
6394 ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC ||
6395 (mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_POST_PROC)) {
6396 sp<ThreadBase> thread = mThread.promote();
6397 if (thread != 0) {
Eric Laurentb8ba0a92011-08-07 16:32:26 -07006398 audio_stream_t *stream = thread->stream();
6399 if (stream != NULL) {
6400 stream->add_audio_effect(stream, mEffectInterface);
6401 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006402 }
6403 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07006404 return status;
6405}
6406
Eric Laurentec437d82011-07-26 20:54:46 -07006407status_t AudioFlinger::EffectModule::stop()
6408{
6409 Mutex::Autolock _l(mLock);
6410 return stop_l();
6411}
6412
Mathias Agopian65ab4712010-07-14 17:59:35 -07006413status_t AudioFlinger::EffectModule::stop_l()
6414{
6415 if (mEffectInterface == NULL) {
6416 return NO_INIT;
6417 }
6418 status_t cmdStatus;
Eric Laurent25f43952010-07-28 05:40:18 -07006419 uint32_t size = sizeof(status_t);
6420 status_t status = (*mEffectInterface)->command(mEffectInterface,
6421 EFFECT_CMD_DISABLE,
6422 0,
6423 NULL,
6424 &size,
6425 &cmdStatus);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006426 if (status == 0) {
6427 status = cmdStatus;
6428 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006429 if (status == 0 &&
6430 ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC ||
6431 (mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_POST_PROC)) {
6432 sp<ThreadBase> thread = mThread.promote();
6433 if (thread != 0) {
Eric Laurentb8ba0a92011-08-07 16:32:26 -07006434 audio_stream_t *stream = thread->stream();
6435 if (stream != NULL) {
6436 stream->remove_audio_effect(stream, mEffectInterface);
6437 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006438 }
6439 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07006440 return status;
6441}
6442
Eric Laurent25f43952010-07-28 05:40:18 -07006443status_t AudioFlinger::EffectModule::command(uint32_t cmdCode,
6444 uint32_t cmdSize,
6445 void *pCmdData,
6446 uint32_t *replySize,
6447 void *pReplyData)
Mathias Agopian65ab4712010-07-14 17:59:35 -07006448{
6449 Mutex::Autolock _l(mLock);
6450// LOGV("command(), cmdCode: %d, mEffectInterface: %p", cmdCode, mEffectInterface);
6451
Eric Laurentec437d82011-07-26 20:54:46 -07006452 if (mState == DESTROYED || mEffectInterface == NULL) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07006453 return NO_INIT;
6454 }
Eric Laurent25f43952010-07-28 05:40:18 -07006455 status_t status = (*mEffectInterface)->command(mEffectInterface,
6456 cmdCode,
6457 cmdSize,
6458 pCmdData,
6459 replySize,
6460 pReplyData);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006461 if (cmdCode != EFFECT_CMD_GET_PARAM && status == NO_ERROR) {
Eric Laurent25f43952010-07-28 05:40:18 -07006462 uint32_t size = (replySize == NULL) ? 0 : *replySize;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006463 for (size_t i = 1; i < mHandles.size(); i++) {
6464 sp<EffectHandle> h = mHandles[i].promote();
6465 if (h != 0) {
6466 h->commandExecuted(cmdCode, cmdSize, pCmdData, size, pReplyData);
6467 }
6468 }
6469 }
6470 return status;
6471}
6472
6473status_t AudioFlinger::EffectModule::setEnabled(bool enabled)
6474{
Eric Laurentdb7c0792011-08-10 10:37:50 -07006475
Mathias Agopian65ab4712010-07-14 17:59:35 -07006476 Mutex::Autolock _l(mLock);
6477 LOGV("setEnabled %p enabled %d", this, enabled);
6478
6479 if (enabled != isEnabled()) {
Eric Laurentdb7c0792011-08-10 10:37:50 -07006480 status_t status = AudioSystem::setEffectEnabled(mId, enabled);
6481 if (enabled && status != NO_ERROR) {
6482 return status;
6483 }
6484
Mathias Agopian65ab4712010-07-14 17:59:35 -07006485 switch (mState) {
6486 // going from disabled to enabled
6487 case IDLE:
6488 mState = STARTING;
6489 break;
6490 case STOPPED:
6491 mState = RESTART;
6492 break;
6493 case STOPPING:
6494 mState = ACTIVE;
6495 break;
6496
6497 // going from enabled to disabled
6498 case RESTART:
Eric Laurent8f45bd72010-08-31 13:50:07 -07006499 mState = STOPPED;
6500 break;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006501 case STARTING:
6502 mState = IDLE;
6503 break;
6504 case ACTIVE:
6505 mState = STOPPING;
6506 break;
Eric Laurentec437d82011-07-26 20:54:46 -07006507 case DESTROYED:
6508 return NO_ERROR; // simply ignore as we are being destroyed
Mathias Agopian65ab4712010-07-14 17:59:35 -07006509 }
6510 for (size_t i = 1; i < mHandles.size(); i++) {
6511 sp<EffectHandle> h = mHandles[i].promote();
6512 if (h != 0) {
6513 h->setEnabled(enabled);
6514 }
6515 }
6516 }
6517 return NO_ERROR;
6518}
6519
6520bool AudioFlinger::EffectModule::isEnabled()
6521{
6522 switch (mState) {
6523 case RESTART:
6524 case STARTING:
6525 case ACTIVE:
6526 return true;
6527 case IDLE:
6528 case STOPPING:
6529 case STOPPED:
Eric Laurentec437d82011-07-26 20:54:46 -07006530 case DESTROYED:
Mathias Agopian65ab4712010-07-14 17:59:35 -07006531 default:
6532 return false;
6533 }
6534}
6535
Eric Laurent8f45bd72010-08-31 13:50:07 -07006536bool AudioFlinger::EffectModule::isProcessEnabled()
6537{
6538 switch (mState) {
6539 case RESTART:
6540 case ACTIVE:
6541 case STOPPING:
6542 case STOPPED:
6543 return true;
6544 case IDLE:
6545 case STARTING:
Eric Laurentec437d82011-07-26 20:54:46 -07006546 case DESTROYED:
Eric Laurent8f45bd72010-08-31 13:50:07 -07006547 default:
6548 return false;
6549 }
6550}
6551
Mathias Agopian65ab4712010-07-14 17:59:35 -07006552status_t AudioFlinger::EffectModule::setVolume(uint32_t *left, uint32_t *right, bool controller)
6553{
6554 Mutex::Autolock _l(mLock);
6555 status_t status = NO_ERROR;
6556
6557 // Send volume indication if EFFECT_FLAG_VOLUME_IND is set and read back altered volume
6558 // if controller flag is set (Note that controller == TRUE => EFFECT_FLAG_VOLUME_CTRL set)
Eric Laurent8f45bd72010-08-31 13:50:07 -07006559 if (isProcessEnabled() &&
Eric Laurentf997cab2010-07-19 06:24:46 -07006560 ((mDescriptor.flags & EFFECT_FLAG_VOLUME_MASK) == EFFECT_FLAG_VOLUME_CTRL ||
6561 (mDescriptor.flags & EFFECT_FLAG_VOLUME_MASK) == EFFECT_FLAG_VOLUME_IND)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07006562 status_t cmdStatus;
6563 uint32_t volume[2];
6564 uint32_t *pVolume = NULL;
Eric Laurent25f43952010-07-28 05:40:18 -07006565 uint32_t size = sizeof(volume);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006566 volume[0] = *left;
6567 volume[1] = *right;
6568 if (controller) {
6569 pVolume = volume;
6570 }
Eric Laurent25f43952010-07-28 05:40:18 -07006571 status = (*mEffectInterface)->command(mEffectInterface,
6572 EFFECT_CMD_SET_VOLUME,
6573 size,
6574 volume,
6575 &size,
6576 pVolume);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006577 if (controller && status == NO_ERROR && size == sizeof(volume)) {
6578 *left = volume[0];
6579 *right = volume[1];
6580 }
6581 }
6582 return status;
6583}
6584
6585status_t AudioFlinger::EffectModule::setDevice(uint32_t device)
6586{
6587 Mutex::Autolock _l(mLock);
6588 status_t status = NO_ERROR;
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006589 if (device && (mDescriptor.flags & EFFECT_FLAG_DEVICE_MASK) == EFFECT_FLAG_DEVICE_IND) {
6590 // audio pre processing modules on RecordThread can receive both output and
6591 // input device indication in the same call
6592 uint32_t dev = device & AUDIO_DEVICE_OUT_ALL;
6593 if (dev) {
6594 status_t cmdStatus;
6595 uint32_t size = sizeof(status_t);
6596
6597 status = (*mEffectInterface)->command(mEffectInterface,
6598 EFFECT_CMD_SET_DEVICE,
6599 sizeof(uint32_t),
6600 &dev,
6601 &size,
6602 &cmdStatus);
6603 if (status == NO_ERROR) {
6604 status = cmdStatus;
6605 }
6606 }
6607 dev = device & AUDIO_DEVICE_IN_ALL;
6608 if (dev) {
6609 status_t cmdStatus;
6610 uint32_t size = sizeof(status_t);
6611
6612 status_t status2 = (*mEffectInterface)->command(mEffectInterface,
6613 EFFECT_CMD_SET_INPUT_DEVICE,
6614 sizeof(uint32_t),
6615 &dev,
6616 &size,
6617 &cmdStatus);
6618 if (status2 == NO_ERROR) {
6619 status2 = cmdStatus;
6620 }
6621 if (status == NO_ERROR) {
6622 status = status2;
6623 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07006624 }
6625 }
6626 return status;
6627}
6628
6629status_t AudioFlinger::EffectModule::setMode(uint32_t mode)
6630{
6631 Mutex::Autolock _l(mLock);
6632 status_t status = NO_ERROR;
6633 if ((mDescriptor.flags & EFFECT_FLAG_AUDIO_MODE_MASK) == EFFECT_FLAG_AUDIO_MODE_IND) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07006634 status_t cmdStatus;
Eric Laurent25f43952010-07-28 05:40:18 -07006635 uint32_t size = sizeof(status_t);
6636 status = (*mEffectInterface)->command(mEffectInterface,
6637 EFFECT_CMD_SET_AUDIO_MODE,
6638 sizeof(int),
Eric Laurente1315cf2011-05-17 19:16:02 -07006639 &mode,
Eric Laurent25f43952010-07-28 05:40:18 -07006640 &size,
6641 &cmdStatus);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006642 if (status == NO_ERROR) {
6643 status = cmdStatus;
6644 }
6645 }
6646 return status;
6647}
6648
Eric Laurent59255e42011-07-27 19:49:51 -07006649void AudioFlinger::EffectModule::setSuspended(bool suspended)
6650{
6651 Mutex::Autolock _l(mLock);
6652 mSuspended = suspended;
6653}
6654bool AudioFlinger::EffectModule::suspended()
6655{
6656 Mutex::Autolock _l(mLock);
6657 return mSuspended;
6658}
6659
Mathias Agopian65ab4712010-07-14 17:59:35 -07006660status_t AudioFlinger::EffectModule::dump(int fd, const Vector<String16>& args)
6661{
6662 const size_t SIZE = 256;
6663 char buffer[SIZE];
6664 String8 result;
6665
6666 snprintf(buffer, SIZE, "\tEffect ID %d:\n", mId);
6667 result.append(buffer);
6668
6669 bool locked = tryLock(mLock);
6670 // failed to lock - AudioFlinger is probably deadlocked
6671 if (!locked) {
6672 result.append("\t\tCould not lock Fx mutex:\n");
6673 }
6674
6675 result.append("\t\tSession Status State Engine:\n");
6676 snprintf(buffer, SIZE, "\t\t%05d %03d %03d 0x%08x\n",
6677 mSessionId, mStatus, mState, (uint32_t)mEffectInterface);
6678 result.append(buffer);
6679
6680 result.append("\t\tDescriptor:\n");
6681 snprintf(buffer, SIZE, "\t\t- UUID: %08X-%04X-%04X-%04X-%02X%02X%02X%02X%02X%02X\n",
6682 mDescriptor.uuid.timeLow, mDescriptor.uuid.timeMid, mDescriptor.uuid.timeHiAndVersion,
6683 mDescriptor.uuid.clockSeq, mDescriptor.uuid.node[0], mDescriptor.uuid.node[1],mDescriptor.uuid.node[2],
6684 mDescriptor.uuid.node[3],mDescriptor.uuid.node[4],mDescriptor.uuid.node[5]);
6685 result.append(buffer);
6686 snprintf(buffer, SIZE, "\t\t- TYPE: %08X-%04X-%04X-%04X-%02X%02X%02X%02X%02X%02X\n",
6687 mDescriptor.type.timeLow, mDescriptor.type.timeMid, mDescriptor.type.timeHiAndVersion,
6688 mDescriptor.type.clockSeq, mDescriptor.type.node[0], mDescriptor.type.node[1],mDescriptor.type.node[2],
6689 mDescriptor.type.node[3],mDescriptor.type.node[4],mDescriptor.type.node[5]);
6690 result.append(buffer);
Eric Laurente1315cf2011-05-17 19:16:02 -07006691 snprintf(buffer, SIZE, "\t\t- apiVersion: %08X\n\t\t- flags: %08X\n",
Mathias Agopian65ab4712010-07-14 17:59:35 -07006692 mDescriptor.apiVersion,
6693 mDescriptor.flags);
6694 result.append(buffer);
6695 snprintf(buffer, SIZE, "\t\t- name: %s\n",
6696 mDescriptor.name);
6697 result.append(buffer);
6698 snprintf(buffer, SIZE, "\t\t- implementor: %s\n",
6699 mDescriptor.implementor);
6700 result.append(buffer);
6701
6702 result.append("\t\t- Input configuration:\n");
6703 result.append("\t\t\tBuffer Frames Smp rate Channels Format\n");
6704 snprintf(buffer, SIZE, "\t\t\t0x%08x %05d %05d %08x %d\n",
6705 (uint32_t)mConfig.inputCfg.buffer.raw,
6706 mConfig.inputCfg.buffer.frameCount,
6707 mConfig.inputCfg.samplingRate,
6708 mConfig.inputCfg.channels,
6709 mConfig.inputCfg.format);
6710 result.append(buffer);
6711
6712 result.append("\t\t- Output configuration:\n");
6713 result.append("\t\t\tBuffer Frames Smp rate Channels Format\n");
6714 snprintf(buffer, SIZE, "\t\t\t0x%08x %05d %05d %08x %d\n",
6715 (uint32_t)mConfig.outputCfg.buffer.raw,
6716 mConfig.outputCfg.buffer.frameCount,
6717 mConfig.outputCfg.samplingRate,
6718 mConfig.outputCfg.channels,
6719 mConfig.outputCfg.format);
6720 result.append(buffer);
6721
6722 snprintf(buffer, SIZE, "\t\t%d Clients:\n", mHandles.size());
6723 result.append(buffer);
6724 result.append("\t\t\tPid Priority Ctrl Locked client server\n");
6725 for (size_t i = 0; i < mHandles.size(); ++i) {
6726 sp<EffectHandle> handle = mHandles[i].promote();
6727 if (handle != 0) {
6728 handle->dump(buffer, SIZE);
6729 result.append(buffer);
6730 }
6731 }
6732
6733 result.append("\n");
6734
6735 write(fd, result.string(), result.length());
6736
6737 if (locked) {
6738 mLock.unlock();
6739 }
6740
6741 return NO_ERROR;
6742}
6743
6744// ----------------------------------------------------------------------------
6745// EffectHandle implementation
6746// ----------------------------------------------------------------------------
6747
6748#undef LOG_TAG
6749#define LOG_TAG "AudioFlinger::EffectHandle"
6750
6751AudioFlinger::EffectHandle::EffectHandle(const sp<EffectModule>& effect,
6752 const sp<AudioFlinger::Client>& client,
6753 const sp<IEffectClient>& effectClient,
6754 int32_t priority)
6755 : BnEffect(),
Marco Nelissen3a34bef2011-08-02 13:33:41 -07006756 mEffect(effect), mEffectClient(effectClient), mClient(client), mCblk(NULL),
Eric Laurent59255e42011-07-27 19:49:51 -07006757 mPriority(priority), mHasControl(false), mEnabled(false)
Mathias Agopian65ab4712010-07-14 17:59:35 -07006758{
6759 LOGV("constructor %p", this);
6760
Marco Nelissen3a34bef2011-08-02 13:33:41 -07006761 if (client == 0) {
6762 return;
6763 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07006764 int bufOffset = ((sizeof(effect_param_cblk_t) - 1) / sizeof(int) + 1) * sizeof(int);
6765 mCblkMemory = client->heap()->allocate(EFFECT_PARAM_BUFFER_SIZE + bufOffset);
6766 if (mCblkMemory != 0) {
6767 mCblk = static_cast<effect_param_cblk_t *>(mCblkMemory->pointer());
6768
6769 if (mCblk) {
6770 new(mCblk) effect_param_cblk_t();
6771 mBuffer = (uint8_t *)mCblk + bufOffset;
6772 }
6773 } else {
6774 LOGE("not enough memory for Effect size=%u", EFFECT_PARAM_BUFFER_SIZE + sizeof(effect_param_cblk_t));
6775 return;
6776 }
6777}
6778
6779AudioFlinger::EffectHandle::~EffectHandle()
6780{
6781 LOGV("Destructor %p", this);
Marco Nelissen3a34bef2011-08-02 13:33:41 -07006782 disconnect(false);
Eric Laurent59255e42011-07-27 19:49:51 -07006783 LOGV("Destructor DONE %p", this);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006784}
6785
6786status_t AudioFlinger::EffectHandle::enable()
6787{
Eric Laurent59255e42011-07-27 19:49:51 -07006788 LOGV("enable %p", this);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006789 if (!mHasControl) return INVALID_OPERATION;
6790 if (mEffect == 0) return DEAD_OBJECT;
6791
Eric Laurentdb7c0792011-08-10 10:37:50 -07006792 if (mEnabled) {
6793 return NO_ERROR;
6794 }
6795
Eric Laurent59255e42011-07-27 19:49:51 -07006796 mEnabled = true;
6797
6798 sp<ThreadBase> thread = mEffect->thread().promote();
6799 if (thread != 0) {
6800 thread->checkSuspendOnEffectEnabled(mEffect, true, mEffect->sessionId());
6801 }
6802
6803 // checkSuspendOnEffectEnabled() can suspend this same effect when enabled
6804 if (mEffect->suspended()) {
6805 return NO_ERROR;
6806 }
6807
Eric Laurentdb7c0792011-08-10 10:37:50 -07006808 status_t status = mEffect->setEnabled(true);
6809 if (status != NO_ERROR) {
6810 if (thread != 0) {
6811 thread->checkSuspendOnEffectEnabled(mEffect, false, mEffect->sessionId());
6812 }
6813 mEnabled = false;
6814 }
6815 return status;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006816}
6817
6818status_t AudioFlinger::EffectHandle::disable()
6819{
Eric Laurent59255e42011-07-27 19:49:51 -07006820 LOGV("disable %p", this);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006821 if (!mHasControl) return INVALID_OPERATION;
Eric Laurent59255e42011-07-27 19:49:51 -07006822 if (mEffect == 0) return DEAD_OBJECT;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006823
Eric Laurentdb7c0792011-08-10 10:37:50 -07006824 if (!mEnabled) {
6825 return NO_ERROR;
6826 }
Eric Laurent59255e42011-07-27 19:49:51 -07006827 mEnabled = false;
6828
6829 if (mEffect->suspended()) {
6830 return NO_ERROR;
6831 }
6832
6833 status_t status = mEffect->setEnabled(false);
6834
6835 sp<ThreadBase> thread = mEffect->thread().promote();
6836 if (thread != 0) {
6837 thread->checkSuspendOnEffectEnabled(mEffect, false, mEffect->sessionId());
6838 }
6839
6840 return status;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006841}
6842
6843void AudioFlinger::EffectHandle::disconnect()
6844{
Marco Nelissen3a34bef2011-08-02 13:33:41 -07006845 disconnect(true);
6846}
6847
6848void AudioFlinger::EffectHandle::disconnect(bool unpiniflast)
6849{
6850 LOGV("disconnect(%s)", unpiniflast ? "true" : "false");
Mathias Agopian65ab4712010-07-14 17:59:35 -07006851 if (mEffect == 0) {
6852 return;
6853 }
Marco Nelissen3a34bef2011-08-02 13:33:41 -07006854 mEffect->disconnect(this, unpiniflast);
Eric Laurent59255e42011-07-27 19:49:51 -07006855
Eric Laurenta85a74a2011-10-19 11:44:54 -07006856 if (mHasControl && mEnabled) {
Eric Laurentdb7c0792011-08-10 10:37:50 -07006857 sp<ThreadBase> thread = mEffect->thread().promote();
6858 if (thread != 0) {
6859 thread->checkSuspendOnEffectEnabled(mEffect, false, mEffect->sessionId());
6860 }
Eric Laurent59255e42011-07-27 19:49:51 -07006861 }
6862
Mathias Agopian65ab4712010-07-14 17:59:35 -07006863 // release sp on module => module destructor can be called now
6864 mEffect.clear();
Mathias Agopian65ab4712010-07-14 17:59:35 -07006865 if (mClient != 0) {
Marco Nelissen3a34bef2011-08-02 13:33:41 -07006866 if (mCblk) {
6867 mCblk->~effect_param_cblk_t(); // destroy our shared-structure.
6868 }
6869 mCblkMemory.clear(); // and free the shared memory
Mathias Agopian65ab4712010-07-14 17:59:35 -07006870 Mutex::Autolock _l(mClient->audioFlinger()->mLock);
6871 mClient.clear();
6872 }
6873}
6874
Eric Laurent25f43952010-07-28 05:40:18 -07006875status_t AudioFlinger::EffectHandle::command(uint32_t cmdCode,
6876 uint32_t cmdSize,
6877 void *pCmdData,
6878 uint32_t *replySize,
6879 void *pReplyData)
Mathias Agopian65ab4712010-07-14 17:59:35 -07006880{
Eric Laurent25f43952010-07-28 05:40:18 -07006881// LOGV("command(), cmdCode: %d, mHasControl: %d, mEffect: %p",
6882// cmdCode, mHasControl, (mEffect == 0) ? 0 : mEffect.get());
Mathias Agopian65ab4712010-07-14 17:59:35 -07006883
6884 // only get parameter command is permitted for applications not controlling the effect
6885 if (!mHasControl && cmdCode != EFFECT_CMD_GET_PARAM) {
6886 return INVALID_OPERATION;
6887 }
6888 if (mEffect == 0) return DEAD_OBJECT;
Marco Nelissen3a34bef2011-08-02 13:33:41 -07006889 if (mClient == 0) return INVALID_OPERATION;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006890
6891 // handle commands that are not forwarded transparently to effect engine
6892 if (cmdCode == EFFECT_CMD_SET_PARAM_COMMIT) {
6893 // No need to trylock() here as this function is executed in the binder thread serving a particular client process:
6894 // no risk to block the whole media server process or mixer threads is we are stuck here
6895 Mutex::Autolock _l(mCblk->lock);
6896 if (mCblk->clientIndex > EFFECT_PARAM_BUFFER_SIZE ||
6897 mCblk->serverIndex > EFFECT_PARAM_BUFFER_SIZE) {
6898 mCblk->serverIndex = 0;
6899 mCblk->clientIndex = 0;
6900 return BAD_VALUE;
6901 }
6902 status_t status = NO_ERROR;
6903 while (mCblk->serverIndex < mCblk->clientIndex) {
6904 int reply;
Eric Laurent25f43952010-07-28 05:40:18 -07006905 uint32_t rsize = sizeof(int);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006906 int *p = (int *)(mBuffer + mCblk->serverIndex);
6907 int size = *p++;
6908 if (((uint8_t *)p + size) > mBuffer + mCblk->clientIndex) {
6909 LOGW("command(): invalid parameter block size");
6910 break;
6911 }
6912 effect_param_t *param = (effect_param_t *)p;
6913 if (param->psize == 0 || param->vsize == 0) {
6914 LOGW("command(): null parameter or value size");
6915 mCblk->serverIndex += size;
6916 continue;
6917 }
Eric Laurent25f43952010-07-28 05:40:18 -07006918 uint32_t psize = sizeof(effect_param_t) +
6919 ((param->psize - 1) / sizeof(int) + 1) * sizeof(int) +
6920 param->vsize;
6921 status_t ret = mEffect->command(EFFECT_CMD_SET_PARAM,
6922 psize,
6923 p,
6924 &rsize,
6925 &reply);
Eric Laurentaeae3de2010-09-02 11:56:55 -07006926 // stop at first error encountered
6927 if (ret != NO_ERROR) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07006928 status = ret;
Eric Laurentaeae3de2010-09-02 11:56:55 -07006929 *(int *)pReplyData = reply;
6930 break;
6931 } else if (reply != NO_ERROR) {
6932 *(int *)pReplyData = reply;
6933 break;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006934 }
6935 mCblk->serverIndex += size;
6936 }
6937 mCblk->serverIndex = 0;
6938 mCblk->clientIndex = 0;
6939 return status;
6940 } else if (cmdCode == EFFECT_CMD_ENABLE) {
Eric Laurentaeae3de2010-09-02 11:56:55 -07006941 *(int *)pReplyData = NO_ERROR;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006942 return enable();
6943 } else if (cmdCode == EFFECT_CMD_DISABLE) {
Eric Laurentaeae3de2010-09-02 11:56:55 -07006944 *(int *)pReplyData = NO_ERROR;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006945 return disable();
6946 }
6947
6948 return mEffect->command(cmdCode, cmdSize, pCmdData, replySize, pReplyData);
6949}
6950
6951sp<IMemory> AudioFlinger::EffectHandle::getCblk() const {
6952 return mCblkMemory;
6953}
6954
Eric Laurent59255e42011-07-27 19:49:51 -07006955void AudioFlinger::EffectHandle::setControl(bool hasControl, bool signal, bool enabled)
Mathias Agopian65ab4712010-07-14 17:59:35 -07006956{
6957 LOGV("setControl %p control %d", this, hasControl);
6958
6959 mHasControl = hasControl;
Eric Laurent59255e42011-07-27 19:49:51 -07006960 mEnabled = enabled;
6961
Mathias Agopian65ab4712010-07-14 17:59:35 -07006962 if (signal && mEffectClient != 0) {
6963 mEffectClient->controlStatusChanged(hasControl);
6964 }
6965}
6966
Eric Laurent25f43952010-07-28 05:40:18 -07006967void AudioFlinger::EffectHandle::commandExecuted(uint32_t cmdCode,
6968 uint32_t cmdSize,
6969 void *pCmdData,
6970 uint32_t replySize,
6971 void *pReplyData)
Mathias Agopian65ab4712010-07-14 17:59:35 -07006972{
6973 if (mEffectClient != 0) {
6974 mEffectClient->commandExecuted(cmdCode, cmdSize, pCmdData, replySize, pReplyData);
6975 }
6976}
6977
6978
6979
6980void AudioFlinger::EffectHandle::setEnabled(bool enabled)
6981{
6982 if (mEffectClient != 0) {
6983 mEffectClient->enableStatusChanged(enabled);
6984 }
6985}
6986
6987status_t AudioFlinger::EffectHandle::onTransact(
6988 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
6989{
6990 return BnEffect::onTransact(code, data, reply, flags);
6991}
6992
6993
6994void AudioFlinger::EffectHandle::dump(char* buffer, size_t size)
6995{
Marco Nelissen3a34bef2011-08-02 13:33:41 -07006996 bool locked = mCblk ? tryLock(mCblk->lock) : false;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006997
6998 snprintf(buffer, size, "\t\t\t%05d %05d %01u %01u %05u %05u\n",
6999 (mClient == NULL) ? getpid() : mClient->pid(),
7000 mPriority,
7001 mHasControl,
7002 !locked,
Marco Nelissen3a34bef2011-08-02 13:33:41 -07007003 mCblk ? mCblk->clientIndex : 0,
7004 mCblk ? mCblk->serverIndex : 0
Mathias Agopian65ab4712010-07-14 17:59:35 -07007005 );
7006
7007 if (locked) {
7008 mCblk->lock.unlock();
7009 }
7010}
7011
7012#undef LOG_TAG
7013#define LOG_TAG "AudioFlinger::EffectChain"
7014
7015AudioFlinger::EffectChain::EffectChain(const wp<ThreadBase>& wThread,
7016 int sessionId)
Eric Laurentb469b942011-05-09 12:09:06 -07007017 : mThread(wThread), mSessionId(sessionId), mActiveTrackCnt(0), mTrackCnt(0),
7018 mOwnInBuffer(false), mVolumeCtrlIdx(-1), mLeftVolume(UINT_MAX), mRightVolume(UINT_MAX),
7019 mNewLeftVolume(UINT_MAX), mNewRightVolume(UINT_MAX)
Mathias Agopian65ab4712010-07-14 17:59:35 -07007020{
Dima Zavinfce7a472011-04-19 22:30:36 -07007021 mStrategy = AudioSystem::getStrategyForStream(AUDIO_STREAM_MUSIC);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007022}
7023
7024AudioFlinger::EffectChain::~EffectChain()
7025{
7026 if (mOwnInBuffer) {
7027 delete mInBuffer;
7028 }
7029
7030}
7031
Eric Laurent59255e42011-07-27 19:49:51 -07007032// getEffectFromDesc_l() must be called with ThreadBase::mLock held
Eric Laurentcab11242010-07-15 12:50:15 -07007033sp<AudioFlinger::EffectModule> AudioFlinger::EffectChain::getEffectFromDesc_l(effect_descriptor_t *descriptor)
Mathias Agopian65ab4712010-07-14 17:59:35 -07007034{
7035 sp<EffectModule> effect;
7036 size_t size = mEffects.size();
7037
7038 for (size_t i = 0; i < size; i++) {
7039 if (memcmp(&mEffects[i]->desc().uuid, &descriptor->uuid, sizeof(effect_uuid_t)) == 0) {
7040 effect = mEffects[i];
7041 break;
7042 }
7043 }
7044 return effect;
7045}
7046
Eric Laurent59255e42011-07-27 19:49:51 -07007047// getEffectFromId_l() must be called with ThreadBase::mLock held
Eric Laurentcab11242010-07-15 12:50:15 -07007048sp<AudioFlinger::EffectModule> AudioFlinger::EffectChain::getEffectFromId_l(int id)
Mathias Agopian65ab4712010-07-14 17:59:35 -07007049{
7050 sp<EffectModule> effect;
7051 size_t size = mEffects.size();
7052
7053 for (size_t i = 0; i < size; i++) {
Eric Laurentde070132010-07-13 04:45:46 -07007054 // by convention, return first effect if id provided is 0 (0 is never a valid id)
7055 if (id == 0 || mEffects[i]->id() == id) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07007056 effect = mEffects[i];
7057 break;
7058 }
7059 }
7060 return effect;
7061}
7062
Eric Laurent59255e42011-07-27 19:49:51 -07007063// getEffectFromType_l() must be called with ThreadBase::mLock held
7064sp<AudioFlinger::EffectModule> AudioFlinger::EffectChain::getEffectFromType_l(
7065 const effect_uuid_t *type)
7066{
7067 sp<EffectModule> effect;
7068 size_t size = mEffects.size();
7069
7070 for (size_t i = 0; i < size; i++) {
7071 if (memcmp(&mEffects[i]->desc().type, type, sizeof(effect_uuid_t)) == 0) {
7072 effect = mEffects[i];
7073 break;
7074 }
7075 }
7076 return effect;
7077}
7078
Mathias Agopian65ab4712010-07-14 17:59:35 -07007079// Must be called with EffectChain::mLock locked
7080void AudioFlinger::EffectChain::process_l()
7081{
Eric Laurentdac69112010-09-28 14:09:57 -07007082 sp<ThreadBase> thread = mThread.promote();
7083 if (thread == 0) {
7084 LOGW("process_l(): cannot promote mixer thread");
7085 return;
7086 }
Dima Zavinfce7a472011-04-19 22:30:36 -07007087 bool isGlobalSession = (mSessionId == AUDIO_SESSION_OUTPUT_MIX) ||
7088 (mSessionId == AUDIO_SESSION_OUTPUT_STAGE);
Eric Laurentdac69112010-09-28 14:09:57 -07007089 bool tracksOnSession = false;
7090 if (!isGlobalSession) {
Eric Laurentb469b942011-05-09 12:09:06 -07007091 tracksOnSession = (trackCnt() != 0);
7092 }
7093
7094 // if no track is active, input buffer must be cleared here as the mixer process
7095 // will not do it
7096 if (tracksOnSession &&
7097 activeTrackCnt() == 0) {
Eric Laurent7c7f10b2011-06-17 21:29:58 -07007098 size_t numSamples = thread->frameCount() * thread->channelCount();
Eric Laurentb469b942011-05-09 12:09:06 -07007099 memset(mInBuffer, 0, numSamples * sizeof(int16_t));
Eric Laurentdac69112010-09-28 14:09:57 -07007100 }
7101
Mathias Agopian65ab4712010-07-14 17:59:35 -07007102 size_t size = mEffects.size();
Eric Laurentdac69112010-09-28 14:09:57 -07007103 // do not process effect if no track is present in same audio session
7104 if (isGlobalSession || tracksOnSession) {
7105 for (size_t i = 0; i < size; i++) {
7106 mEffects[i]->process();
7107 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07007108 }
7109 for (size_t i = 0; i < size; i++) {
7110 mEffects[i]->updateState();
7111 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07007112}
7113
Eric Laurentcab11242010-07-15 12:50:15 -07007114// addEffect_l() must be called with PlaybackThread::mLock held
Eric Laurentde070132010-07-13 04:45:46 -07007115status_t AudioFlinger::EffectChain::addEffect_l(const sp<EffectModule>& effect)
Mathias Agopian65ab4712010-07-14 17:59:35 -07007116{
7117 effect_descriptor_t desc = effect->desc();
7118 uint32_t insertPref = desc.flags & EFFECT_FLAG_INSERT_MASK;
7119
7120 Mutex::Autolock _l(mLock);
Eric Laurentde070132010-07-13 04:45:46 -07007121 effect->setChain(this);
7122 sp<ThreadBase> thread = mThread.promote();
7123 if (thread == 0) {
7124 return NO_INIT;
7125 }
7126 effect->setThread(thread);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007127
7128 if ((desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
7129 // Auxiliary effects are inserted at the beginning of mEffects vector as
7130 // they are processed first and accumulated in chain input buffer
7131 mEffects.insertAt(effect, 0);
Eric Laurentde070132010-07-13 04:45:46 -07007132
Mathias Agopian65ab4712010-07-14 17:59:35 -07007133 // the input buffer for auxiliary effect contains mono samples in
7134 // 32 bit format. This is to avoid saturation in AudoMixer
7135 // accumulation stage. Saturation is done in EffectModule::process() before
7136 // calling the process in effect engine
7137 size_t numSamples = thread->frameCount();
7138 int32_t *buffer = new int32_t[numSamples];
7139 memset(buffer, 0, numSamples * sizeof(int32_t));
7140 effect->setInBuffer((int16_t *)buffer);
7141 // auxiliary effects output samples to chain input buffer for further processing
7142 // by insert effects
7143 effect->setOutBuffer(mInBuffer);
7144 } else {
7145 // Insert effects are inserted at the end of mEffects vector as they are processed
7146 // after track and auxiliary effects.
7147 // Insert effect order as a function of indicated preference:
7148 // if EFFECT_FLAG_INSERT_EXCLUSIVE, insert in first position or reject if
7149 // another effect is present
7150 // else if EFFECT_FLAG_INSERT_FIRST, insert in first position or after the
7151 // last effect claiming first position
7152 // else if EFFECT_FLAG_INSERT_LAST, insert in last position or before the
7153 // first effect claiming last position
7154 // else if EFFECT_FLAG_INSERT_ANY insert after first or before last
7155 // Reject insertion if an effect with EFFECT_FLAG_INSERT_EXCLUSIVE is
7156 // already present
7157
7158 int size = (int)mEffects.size();
7159 int idx_insert = size;
7160 int idx_insert_first = -1;
7161 int idx_insert_last = -1;
7162
7163 for (int i = 0; i < size; i++) {
7164 effect_descriptor_t d = mEffects[i]->desc();
7165 uint32_t iMode = d.flags & EFFECT_FLAG_TYPE_MASK;
7166 uint32_t iPref = d.flags & EFFECT_FLAG_INSERT_MASK;
7167 if (iMode == EFFECT_FLAG_TYPE_INSERT) {
7168 // check invalid effect chaining combinations
7169 if (insertPref == EFFECT_FLAG_INSERT_EXCLUSIVE ||
7170 iPref == EFFECT_FLAG_INSERT_EXCLUSIVE) {
Eric Laurentcab11242010-07-15 12:50:15 -07007171 LOGW("addEffect_l() could not insert effect %s: exclusive conflict with %s", desc.name, d.name);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007172 return INVALID_OPERATION;
7173 }
7174 // remember position of first insert effect and by default
7175 // select this as insert position for new effect
7176 if (idx_insert == size) {
7177 idx_insert = i;
7178 }
7179 // remember position of last insert effect claiming
7180 // first position
7181 if (iPref == EFFECT_FLAG_INSERT_FIRST) {
7182 idx_insert_first = i;
7183 }
7184 // remember position of first insert effect claiming
7185 // last position
7186 if (iPref == EFFECT_FLAG_INSERT_LAST &&
7187 idx_insert_last == -1) {
7188 idx_insert_last = i;
7189 }
7190 }
7191 }
7192
7193 // modify idx_insert from first position if needed
7194 if (insertPref == EFFECT_FLAG_INSERT_LAST) {
7195 if (idx_insert_last != -1) {
7196 idx_insert = idx_insert_last;
7197 } else {
7198 idx_insert = size;
7199 }
7200 } else {
7201 if (idx_insert_first != -1) {
7202 idx_insert = idx_insert_first + 1;
7203 }
7204 }
7205
7206 // always read samples from chain input buffer
7207 effect->setInBuffer(mInBuffer);
7208
7209 // if last effect in the chain, output samples to chain
7210 // output buffer, otherwise to chain input buffer
7211 if (idx_insert == size) {
7212 if (idx_insert != 0) {
7213 mEffects[idx_insert-1]->setOutBuffer(mInBuffer);
7214 mEffects[idx_insert-1]->configure();
7215 }
7216 effect->setOutBuffer(mOutBuffer);
7217 } else {
7218 effect->setOutBuffer(mInBuffer);
7219 }
7220 mEffects.insertAt(effect, idx_insert);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007221
Eric Laurentcab11242010-07-15 12:50:15 -07007222 LOGV("addEffect_l() effect %p, added in chain %p at rank %d", effect.get(), this, idx_insert);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007223 }
7224 effect->configure();
7225 return NO_ERROR;
7226}
7227
Eric Laurentcab11242010-07-15 12:50:15 -07007228// removeEffect_l() must be called with PlaybackThread::mLock held
7229size_t AudioFlinger::EffectChain::removeEffect_l(const sp<EffectModule>& effect)
Mathias Agopian65ab4712010-07-14 17:59:35 -07007230{
7231 Mutex::Autolock _l(mLock);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007232 int size = (int)mEffects.size();
7233 int i;
7234 uint32_t type = effect->desc().flags & EFFECT_FLAG_TYPE_MASK;
7235
7236 for (i = 0; i < size; i++) {
7237 if (effect == mEffects[i]) {
Eric Laurentec437d82011-07-26 20:54:46 -07007238 // calling stop here will remove pre-processing effect from the audio HAL.
7239 // This is safe as we hold the EffectChain mutex which guarantees that we are not in
7240 // the middle of a read from audio HAL
Eric Laurentec35a142011-10-05 17:42:25 -07007241 if (mEffects[i]->state() == EffectModule::ACTIVE ||
7242 mEffects[i]->state() == EffectModule::STOPPING) {
7243 mEffects[i]->stop();
7244 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07007245 if (type == EFFECT_FLAG_TYPE_AUXILIARY) {
7246 delete[] effect->inBuffer();
7247 } else {
7248 if (i == size - 1 && i != 0) {
7249 mEffects[i - 1]->setOutBuffer(mOutBuffer);
7250 mEffects[i - 1]->configure();
7251 }
7252 }
7253 mEffects.removeAt(i);
Eric Laurentcab11242010-07-15 12:50:15 -07007254 LOGV("removeEffect_l() effect %p, removed from chain %p at rank %d", effect.get(), this, i);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007255 break;
7256 }
7257 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07007258
7259 return mEffects.size();
7260}
7261
Eric Laurentcab11242010-07-15 12:50:15 -07007262// setDevice_l() must be called with PlaybackThread::mLock held
7263void AudioFlinger::EffectChain::setDevice_l(uint32_t device)
Mathias Agopian65ab4712010-07-14 17:59:35 -07007264{
7265 size_t size = mEffects.size();
7266 for (size_t i = 0; i < size; i++) {
7267 mEffects[i]->setDevice(device);
7268 }
7269}
7270
Eric Laurentcab11242010-07-15 12:50:15 -07007271// setMode_l() must be called with PlaybackThread::mLock held
7272void AudioFlinger::EffectChain::setMode_l(uint32_t mode)
Mathias Agopian65ab4712010-07-14 17:59:35 -07007273{
7274 size_t size = mEffects.size();
7275 for (size_t i = 0; i < size; i++) {
7276 mEffects[i]->setMode(mode);
7277 }
7278}
7279
Eric Laurentcab11242010-07-15 12:50:15 -07007280// setVolume_l() must be called with PlaybackThread::mLock held
7281bool AudioFlinger::EffectChain::setVolume_l(uint32_t *left, uint32_t *right)
Mathias Agopian65ab4712010-07-14 17:59:35 -07007282{
7283 uint32_t newLeft = *left;
7284 uint32_t newRight = *right;
7285 bool hasControl = false;
Eric Laurentcab11242010-07-15 12:50:15 -07007286 int ctrlIdx = -1;
7287 size_t size = mEffects.size();
Mathias Agopian65ab4712010-07-14 17:59:35 -07007288
Eric Laurentcab11242010-07-15 12:50:15 -07007289 // first update volume controller
7290 for (size_t i = size; i > 0; i--) {
Eric Laurent8f45bd72010-08-31 13:50:07 -07007291 if (mEffects[i - 1]->isProcessEnabled() &&
Eric Laurentcab11242010-07-15 12:50:15 -07007292 (mEffects[i - 1]->desc().flags & EFFECT_FLAG_VOLUME_MASK) == EFFECT_FLAG_VOLUME_CTRL) {
7293 ctrlIdx = i - 1;
Eric Laurentf997cab2010-07-19 06:24:46 -07007294 hasControl = true;
Eric Laurentcab11242010-07-15 12:50:15 -07007295 break;
7296 }
7297 }
7298
7299 if (ctrlIdx == mVolumeCtrlIdx && *left == mLeftVolume && *right == mRightVolume) {
Eric Laurentf997cab2010-07-19 06:24:46 -07007300 if (hasControl) {
7301 *left = mNewLeftVolume;
7302 *right = mNewRightVolume;
7303 }
7304 return hasControl;
Eric Laurentcab11242010-07-15 12:50:15 -07007305 }
7306
7307 mVolumeCtrlIdx = ctrlIdx;
Eric Laurentf997cab2010-07-19 06:24:46 -07007308 mLeftVolume = newLeft;
7309 mRightVolume = newRight;
Eric Laurentcab11242010-07-15 12:50:15 -07007310
7311 // second get volume update from volume controller
7312 if (ctrlIdx >= 0) {
7313 mEffects[ctrlIdx]->setVolume(&newLeft, &newRight, true);
Eric Laurentf997cab2010-07-19 06:24:46 -07007314 mNewLeftVolume = newLeft;
7315 mNewRightVolume = newRight;
Mathias Agopian65ab4712010-07-14 17:59:35 -07007316 }
7317 // then indicate volume to all other effects in chain.
7318 // Pass altered volume to effects before volume controller
7319 // and requested volume to effects after controller
7320 uint32_t lVol = newLeft;
7321 uint32_t rVol = newRight;
Eric Laurentcab11242010-07-15 12:50:15 -07007322
Mathias Agopian65ab4712010-07-14 17:59:35 -07007323 for (size_t i = 0; i < size; i++) {
Eric Laurentcab11242010-07-15 12:50:15 -07007324 if ((int)i == ctrlIdx) continue;
7325 // this also works for ctrlIdx == -1 when there is no volume controller
7326 if ((int)i > ctrlIdx) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07007327 lVol = *left;
7328 rVol = *right;
7329 }
7330 mEffects[i]->setVolume(&lVol, &rVol, false);
7331 }
7332 *left = newLeft;
7333 *right = newRight;
7334
7335 return hasControl;
7336}
7337
Mathias Agopian65ab4712010-07-14 17:59:35 -07007338status_t AudioFlinger::EffectChain::dump(int fd, const Vector<String16>& args)
7339{
7340 const size_t SIZE = 256;
7341 char buffer[SIZE];
7342 String8 result;
7343
7344 snprintf(buffer, SIZE, "Effects for session %d:\n", mSessionId);
7345 result.append(buffer);
7346
7347 bool locked = tryLock(mLock);
7348 // failed to lock - AudioFlinger is probably deadlocked
7349 if (!locked) {
7350 result.append("\tCould not lock mutex:\n");
7351 }
7352
Eric Laurentcab11242010-07-15 12:50:15 -07007353 result.append("\tNum fx In buffer Out buffer Active tracks:\n");
7354 snprintf(buffer, SIZE, "\t%02d 0x%08x 0x%08x %d\n",
Mathias Agopian65ab4712010-07-14 17:59:35 -07007355 mEffects.size(),
7356 (uint32_t)mInBuffer,
7357 (uint32_t)mOutBuffer,
Mathias Agopian65ab4712010-07-14 17:59:35 -07007358 mActiveTrackCnt);
7359 result.append(buffer);
7360 write(fd, result.string(), result.size());
7361
7362 for (size_t i = 0; i < mEffects.size(); ++i) {
7363 sp<EffectModule> effect = mEffects[i];
7364 if (effect != 0) {
7365 effect->dump(fd, args);
7366 }
7367 }
7368
7369 if (locked) {
7370 mLock.unlock();
7371 }
7372
7373 return NO_ERROR;
7374}
7375
Eric Laurent59255e42011-07-27 19:49:51 -07007376// must be called with ThreadBase::mLock held
7377void AudioFlinger::EffectChain::setEffectSuspended_l(
7378 const effect_uuid_t *type, bool suspend)
7379{
7380 sp<SuspendedEffectDesc> desc;
7381 // use effect type UUID timelow as key as there is no real risk of identical
7382 // timeLow fields among effect type UUIDs.
7383 int index = mSuspendedEffects.indexOfKey(type->timeLow);
7384 if (suspend) {
7385 if (index >= 0) {
7386 desc = mSuspendedEffects.valueAt(index);
7387 } else {
7388 desc = new SuspendedEffectDesc();
7389 memcpy(&desc->mType, type, sizeof(effect_uuid_t));
7390 mSuspendedEffects.add(type->timeLow, desc);
7391 LOGV("setEffectSuspended_l() add entry for %08x", type->timeLow);
7392 }
7393 if (desc->mRefCount++ == 0) {
7394 sp<EffectModule> effect = getEffectIfEnabled(type);
7395 if (effect != 0) {
7396 desc->mEffect = effect;
7397 effect->setSuspended(true);
7398 effect->setEnabled(false);
7399 }
7400 }
7401 } else {
7402 if (index < 0) {
7403 return;
7404 }
7405 desc = mSuspendedEffects.valueAt(index);
7406 if (desc->mRefCount <= 0) {
7407 LOGW("setEffectSuspended_l() restore refcount should not be 0 %d", desc->mRefCount);
7408 desc->mRefCount = 1;
7409 }
7410 if (--desc->mRefCount == 0) {
7411 LOGV("setEffectSuspended_l() remove entry for %08x", mSuspendedEffects.keyAt(index));
7412 if (desc->mEffect != 0) {
7413 sp<EffectModule> effect = desc->mEffect.promote();
7414 if (effect != 0) {
7415 effect->setSuspended(false);
7416 sp<EffectHandle> handle = effect->controlHandle();
7417 if (handle != 0) {
7418 effect->setEnabled(handle->enabled());
7419 }
7420 }
7421 desc->mEffect.clear();
7422 }
7423 mSuspendedEffects.removeItemsAt(index);
7424 }
7425 }
7426}
7427
7428// must be called with ThreadBase::mLock held
7429void AudioFlinger::EffectChain::setEffectSuspendedAll_l(bool suspend)
7430{
7431 sp<SuspendedEffectDesc> desc;
7432
7433 int index = mSuspendedEffects.indexOfKey((int)kKeyForSuspendAll);
7434 if (suspend) {
7435 if (index >= 0) {
7436 desc = mSuspendedEffects.valueAt(index);
7437 } else {
7438 desc = new SuspendedEffectDesc();
7439 mSuspendedEffects.add((int)kKeyForSuspendAll, desc);
7440 LOGV("setEffectSuspendedAll_l() add entry for 0");
7441 }
7442 if (desc->mRefCount++ == 0) {
7443 Vector< sp<EffectModule> > effects = getSuspendEligibleEffects();
7444 for (size_t i = 0; i < effects.size(); i++) {
7445 setEffectSuspended_l(&effects[i]->desc().type, true);
7446 }
7447 }
7448 } else {
7449 if (index < 0) {
7450 return;
7451 }
7452 desc = mSuspendedEffects.valueAt(index);
7453 if (desc->mRefCount <= 0) {
7454 LOGW("setEffectSuspendedAll_l() restore refcount should not be 0 %d", desc->mRefCount);
7455 desc->mRefCount = 1;
7456 }
7457 if (--desc->mRefCount == 0) {
7458 Vector<const effect_uuid_t *> types;
7459 for (size_t i = 0; i < mSuspendedEffects.size(); i++) {
7460 if (mSuspendedEffects.keyAt(i) == (int)kKeyForSuspendAll) {
7461 continue;
7462 }
7463 types.add(&mSuspendedEffects.valueAt(i)->mType);
7464 }
7465 for (size_t i = 0; i < types.size(); i++) {
7466 setEffectSuspended_l(types[i], false);
7467 }
7468 LOGV("setEffectSuspendedAll_l() remove entry for %08x", mSuspendedEffects.keyAt(index));
7469 mSuspendedEffects.removeItem((int)kKeyForSuspendAll);
7470 }
7471 }
7472}
7473
Eric Laurent6bffdb82011-09-23 08:40:41 -07007474
7475// The volume effect is used for automated tests only
7476#ifndef OPENSL_ES_H_
7477static const effect_uuid_t SL_IID_VOLUME_ = { 0x09e8ede0, 0xddde, 0x11db, 0xb4f6,
7478 { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } };
7479const effect_uuid_t * const SL_IID_VOLUME = &SL_IID_VOLUME_;
7480#endif //OPENSL_ES_H_
7481
Eric Laurentdb7c0792011-08-10 10:37:50 -07007482bool AudioFlinger::EffectChain::isEffectEligibleForSuspend(const effect_descriptor_t& desc)
7483{
7484 // auxiliary effects and visualizer are never suspended on output mix
7485 if ((mSessionId == AUDIO_SESSION_OUTPUT_MIX) &&
7486 (((desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) ||
Eric Laurent6bffdb82011-09-23 08:40:41 -07007487 (memcmp(&desc.type, SL_IID_VISUALIZATION, sizeof(effect_uuid_t)) == 0) ||
7488 (memcmp(&desc.type, SL_IID_VOLUME, sizeof(effect_uuid_t)) == 0))) {
Eric Laurentdb7c0792011-08-10 10:37:50 -07007489 return false;
7490 }
7491 return true;
7492}
7493
Eric Laurent59255e42011-07-27 19:49:51 -07007494Vector< sp<AudioFlinger::EffectModule> > AudioFlinger::EffectChain::getSuspendEligibleEffects()
7495{
7496 Vector< sp<EffectModule> > effects;
7497 for (size_t i = 0; i < mEffects.size(); i++) {
Eric Laurentdb7c0792011-08-10 10:37:50 -07007498 if (!isEffectEligibleForSuspend(mEffects[i]->desc())) {
Eric Laurent59255e42011-07-27 19:49:51 -07007499 continue;
7500 }
7501 effects.add(mEffects[i]);
7502 }
7503 return effects;
7504}
7505
7506sp<AudioFlinger::EffectModule> AudioFlinger::EffectChain::getEffectIfEnabled(
7507 const effect_uuid_t *type)
7508{
7509 sp<EffectModule> effect;
7510 effect = getEffectFromType_l(type);
7511 if (effect != 0 && !effect->isEnabled()) {
7512 effect.clear();
7513 }
7514 return effect;
7515}
7516
7517void AudioFlinger::EffectChain::checkSuspendOnEffectEnabled(const sp<EffectModule>& effect,
7518 bool enabled)
7519{
7520 int index = mSuspendedEffects.indexOfKey(effect->desc().type.timeLow);
7521 if (enabled) {
7522 if (index < 0) {
7523 // if the effect is not suspend check if all effects are suspended
7524 index = mSuspendedEffects.indexOfKey((int)kKeyForSuspendAll);
7525 if (index < 0) {
7526 return;
7527 }
Eric Laurentdb7c0792011-08-10 10:37:50 -07007528 if (!isEffectEligibleForSuspend(effect->desc())) {
7529 return;
7530 }
Eric Laurent59255e42011-07-27 19:49:51 -07007531 setEffectSuspended_l(&effect->desc().type, enabled);
7532 index = mSuspendedEffects.indexOfKey(effect->desc().type.timeLow);
Eric Laurentdb7c0792011-08-10 10:37:50 -07007533 if (index < 0) {
7534 LOGW("checkSuspendOnEffectEnabled() Fx should be suspended here!");
7535 return;
7536 }
Eric Laurent59255e42011-07-27 19:49:51 -07007537 }
7538 LOGV("checkSuspendOnEffectEnabled() enable suspending fx %08x",
7539 effect->desc().type.timeLow);
7540 sp<SuspendedEffectDesc> desc = mSuspendedEffects.valueAt(index);
7541 // if effect is requested to suspended but was not yet enabled, supend it now.
7542 if (desc->mEffect == 0) {
7543 desc->mEffect = effect;
7544 effect->setEnabled(false);
7545 effect->setSuspended(true);
7546 }
7547 } else {
7548 if (index < 0) {
7549 return;
7550 }
7551 LOGV("checkSuspendOnEffectEnabled() disable restoring fx %08x",
7552 effect->desc().type.timeLow);
7553 sp<SuspendedEffectDesc> desc = mSuspendedEffects.valueAt(index);
7554 desc->mEffect.clear();
7555 effect->setSuspended(false);
7556 }
7557}
7558
Mathias Agopian65ab4712010-07-14 17:59:35 -07007559#undef LOG_TAG
7560#define LOG_TAG "AudioFlinger"
7561
7562// ----------------------------------------------------------------------------
7563
7564status_t AudioFlinger::onTransact(
7565 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
7566{
7567 return BnAudioFlinger::onTransact(code, data, reply, flags);
7568}
7569
Mathias Agopian65ab4712010-07-14 17:59:35 -07007570}; // namespace android