blob: fd82306e5af9964334e4bb4ae70c970ba9c32801 [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
Glenn Kastenec1d6b52011-12-12 09:04:45 -080066static const char kDeadlockedString[] = "AudioFlinger may be deadlocked\n";
67static const char kHardwareLockedString[] = "Hardware lock is taken\n";
Mathias Agopian65ab4712010-07-14 17:59:35 -070068
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;
Glenn Kasten7dede872011-12-13 11:04:14 -080083static const int kDumpLockSleepUs = 20000;
Mathias Agopian65ab4712010-07-14 17:59:35 -070084
Glenn Kasten7dede872011-12-13 11:04:14 -080085// don't warn about blocked writes or record buffer overflows more often than this
86static const nsecs_t kWarningThrottleNs = seconds(5);
Mathias Agopian65ab4712010-07-14 17:59:35 -070087
Eric Laurent7c7f10b2011-06-17 21:29:58 -070088// RecordThread loop sleep time upon application overrun or audio HAL read error
89static const int kRecordThreadSleepUs = 5000;
Mathias Agopian65ab4712010-07-14 17:59:35 -070090
Glenn Kasten7dede872011-12-13 11:04:14 -080091// maximum time to wait for setParameters to complete
92static const nsecs_t kSetParametersTimeoutNs = seconds(2);
Eric Laurent60cd0a02011-09-13 11:40:21 -070093
Eric Laurent7cafbb32011-11-22 18:50:29 -080094// minimum sleep time for the mixer thread loop when tracks are active but in underrun
95static const uint32_t kMinThreadSleepTimeUs = 5000;
96// maximum divider applied to the active sleep time in the mixer thread loop
97static const uint32_t kMaxThreadSleepTimeShift = 2;
98
99
Mathias Agopian65ab4712010-07-14 17:59:35 -0700100// ----------------------------------------------------------------------------
101
102static bool recordingAllowed() {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700103 if (getpid() == IPCThreadState::self()->getCallingPid()) return true;
104 bool ok = checkCallingPermission(String16("android.permission.RECORD_AUDIO"));
105 if (!ok) LOGE("Request requires android.permission.RECORD_AUDIO");
106 return ok;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700107}
108
109static bool settingsAllowed() {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700110 if (getpid() == IPCThreadState::self()->getCallingPid()) return true;
111 bool ok = checkCallingPermission(String16("android.permission.MODIFY_AUDIO_SETTINGS"));
112 if (!ok) LOGE("Request requires android.permission.MODIFY_AUDIO_SETTINGS");
113 return ok;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700114}
115
Gloria Wang9ee159b2011-02-24 14:51:45 -0800116// To collect the amplifier usage
117static void addBatteryData(uint32_t params) {
118 sp<IBinder> binder =
119 defaultServiceManager()->getService(String16("media.player"));
120 sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder);
121 if (service.get() == NULL) {
122 LOGW("Cannot connect to the MediaPlayerService for battery tracking");
123 return;
124 }
125
126 service->addBatteryData(params);
127}
128
Dima Zavin799a70e2011-04-18 16:57:27 -0700129static int load_audio_interface(const char *if_name, const hw_module_t **mod,
130 audio_hw_device_t **dev)
131{
132 int rc;
133
134 rc = hw_get_module_by_class(AUDIO_HARDWARE_MODULE_ID, if_name, mod);
135 if (rc)
136 goto out;
137
138 rc = audio_hw_device_open(*mod, dev);
139 LOGE_IF(rc, "couldn't open audio hw device in %s.%s (%s)",
140 AUDIO_HARDWARE_MODULE_ID, if_name, strerror(-rc));
141 if (rc)
142 goto out;
143
144 return 0;
145
146out:
147 *mod = NULL;
148 *dev = NULL;
149 return rc;
150}
151
Glenn Kastenec1d6b52011-12-12 09:04:45 -0800152static const char * const audio_interfaces[] = {
Dima Zavin799a70e2011-04-18 16:57:27 -0700153 "primary",
154 "a2dp",
155 "usb",
156};
157#define ARRAY_SIZE(x) (sizeof((x))/sizeof(((x)[0])))
158
Mathias Agopian65ab4712010-07-14 17:59:35 -0700159// ----------------------------------------------------------------------------
160
161AudioFlinger::AudioFlinger()
162 : BnAudioFlinger(),
Eric Laurent59bd0da2011-08-01 09:52:20 -0700163 mPrimaryHardwareDev(0), mMasterVolume(1.0f), mMasterMute(false), mNextUniqueId(1),
Eric Laurentbee53372011-08-29 12:42:48 -0700164 mBtNrecIsOff(false)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700165{
Dima Zavin5a61d2f2011-04-19 19:04:32 -0700166}
167
168void AudioFlinger::onFirstRef()
169{
Dima Zavin799a70e2011-04-18 16:57:27 -0700170 int rc = 0;
Dima Zavinfce7a472011-04-19 22:30:36 -0700171
Eric Laurent93575202011-01-18 18:39:02 -0800172 Mutex::Autolock _l(mLock);
173
Dima Zavin799a70e2011-04-18 16:57:27 -0700174 /* TODO: move all this work into an Init() function */
Mathias Agopian65ab4712010-07-14 17:59:35 -0700175 mHardwareStatus = AUDIO_HW_IDLE;
176
Dima Zavin799a70e2011-04-18 16:57:27 -0700177 for (size_t i = 0; i < ARRAY_SIZE(audio_interfaces); i++) {
178 const hw_module_t *mod;
179 audio_hw_device_t *dev;
Dima Zavinfce7a472011-04-19 22:30:36 -0700180
Dima Zavin799a70e2011-04-18 16:57:27 -0700181 rc = load_audio_interface(audio_interfaces[i], &mod, &dev);
182 if (rc)
183 continue;
184
185 LOGI("Loaded %s audio interface from %s (%s)", audio_interfaces[i],
186 mod->name, mod->id);
187 mAudioHwDevs.push(dev);
188
189 if (!mPrimaryHardwareDev) {
190 mPrimaryHardwareDev = dev;
191 LOGI("Using '%s' (%s.%s) as the primary audio interface",
Dima Zavin5a61d2f2011-04-19 19:04:32 -0700192 mod->name, mod->id, audio_interfaces[i]);
Dima Zavin799a70e2011-04-18 16:57:27 -0700193 }
194 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700195
196 mHardwareStatus = AUDIO_HW_INIT;
Dima Zavinfce7a472011-04-19 22:30:36 -0700197
Dima Zavin799a70e2011-04-18 16:57:27 -0700198 if (!mPrimaryHardwareDev || mAudioHwDevs.size() == 0) {
199 LOGE("Primary audio interface not found");
200 return;
201 }
202
203 for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
204 audio_hw_device_t *dev = mAudioHwDevs[i];
205
206 mHardwareStatus = AUDIO_HW_INIT;
207 rc = dev->init_check(dev);
208 if (rc == 0) {
209 AutoMutex lock(mHardwareLock);
210
211 mMode = AUDIO_MODE_NORMAL;
212 mHardwareStatus = AUDIO_HW_SET_MODE;
213 dev->set_mode(dev, mMode);
214 mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
215 dev->set_master_volume(dev, 1.0f);
216 mHardwareStatus = AUDIO_HW_IDLE;
217 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700218 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700219}
220
Dima Zavin5a61d2f2011-04-19 19:04:32 -0700221status_t AudioFlinger::initCheck() const
222{
223 Mutex::Autolock _l(mLock);
224 if (mPrimaryHardwareDev == NULL || mAudioHwDevs.size() == 0)
225 return NO_INIT;
226 return NO_ERROR;
227}
228
Mathias Agopian65ab4712010-07-14 17:59:35 -0700229AudioFlinger::~AudioFlinger()
230{
Dima Zavin799a70e2011-04-18 16:57:27 -0700231 int num_devs = mAudioHwDevs.size();
232
Mathias Agopian65ab4712010-07-14 17:59:35 -0700233 while (!mRecordThreads.isEmpty()) {
234 // closeInput() will remove first entry from mRecordThreads
235 closeInput(mRecordThreads.keyAt(0));
236 }
237 while (!mPlaybackThreads.isEmpty()) {
238 // closeOutput() will remove first entry from mPlaybackThreads
239 closeOutput(mPlaybackThreads.keyAt(0));
240 }
Dima Zavin799a70e2011-04-18 16:57:27 -0700241
242 for (int i = 0; i < num_devs; i++) {
243 audio_hw_device_t *dev = mAudioHwDevs[i];
244 audio_hw_device_close(dev);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700245 }
Dima Zavin799a70e2011-04-18 16:57:27 -0700246 mAudioHwDevs.clear();
Mathias Agopian65ab4712010-07-14 17:59:35 -0700247}
248
Dima Zavin799a70e2011-04-18 16:57:27 -0700249audio_hw_device_t* AudioFlinger::findSuitableHwDev_l(uint32_t devices)
250{
251 /* first matching HW device is returned */
252 for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
253 audio_hw_device_t *dev = mAudioHwDevs[i];
254 if ((dev->get_supported_devices(dev) & devices) == devices)
255 return dev;
256 }
257 return NULL;
258}
Mathias Agopian65ab4712010-07-14 17:59:35 -0700259
260status_t AudioFlinger::dumpClients(int fd, const Vector<String16>& args)
261{
262 const size_t SIZE = 256;
263 char buffer[SIZE];
264 String8 result;
265
266 result.append("Clients:\n");
267 for (size_t i = 0; i < mClients.size(); ++i) {
268 wp<Client> wClient = mClients.valueAt(i);
269 if (wClient != 0) {
270 sp<Client> client = wClient.promote();
271 if (client != 0) {
272 snprintf(buffer, SIZE, " pid: %d\n", client->pid());
273 result.append(buffer);
274 }
275 }
276 }
Marco Nelissen3a34bef2011-08-02 13:33:41 -0700277
278 result.append("Global session refs:\n");
279 result.append(" session pid cnt\n");
280 for (size_t i = 0; i < mAudioSessionRefs.size(); i++) {
281 AudioSessionRef *r = mAudioSessionRefs[i];
282 snprintf(buffer, SIZE, " %7d %3d %3d\n", r->sessionid, r->pid, r->cnt);
283 result.append(buffer);
284 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700285 write(fd, result.string(), result.size());
286 return NO_ERROR;
287}
288
289
290status_t AudioFlinger::dumpInternals(int fd, const Vector<String16>& args)
291{
292 const size_t SIZE = 256;
293 char buffer[SIZE];
294 String8 result;
295 int hardwareStatus = mHardwareStatus;
296
297 snprintf(buffer, SIZE, "Hardware status: %d\n", hardwareStatus);
298 result.append(buffer);
299 write(fd, result.string(), result.size());
300 return NO_ERROR;
301}
302
303status_t AudioFlinger::dumpPermissionDenial(int fd, const Vector<String16>& args)
304{
305 const size_t SIZE = 256;
306 char buffer[SIZE];
307 String8 result;
308 snprintf(buffer, SIZE, "Permission Denial: "
309 "can't dump AudioFlinger from pid=%d, uid=%d\n",
310 IPCThreadState::self()->getCallingPid(),
311 IPCThreadState::self()->getCallingUid());
312 result.append(buffer);
313 write(fd, result.string(), result.size());
314 return NO_ERROR;
315}
316
317static bool tryLock(Mutex& mutex)
318{
319 bool locked = false;
320 for (int i = 0; i < kDumpLockRetries; ++i) {
321 if (mutex.tryLock() == NO_ERROR) {
322 locked = true;
323 break;
324 }
Glenn Kasten7dede872011-12-13 11:04:14 -0800325 usleep(kDumpLockSleepUs);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700326 }
327 return locked;
328}
329
330status_t AudioFlinger::dump(int fd, const Vector<String16>& args)
331{
332 if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
333 dumpPermissionDenial(fd, args);
334 } else {
335 // get state of hardware lock
336 bool hardwareLocked = tryLock(mHardwareLock);
337 if (!hardwareLocked) {
338 String8 result(kHardwareLockedString);
339 write(fd, result.string(), result.size());
340 } else {
341 mHardwareLock.unlock();
342 }
343
344 bool locked = tryLock(mLock);
345
346 // failed to lock - AudioFlinger is probably deadlocked
347 if (!locked) {
348 String8 result(kDeadlockedString);
349 write(fd, result.string(), result.size());
350 }
351
352 dumpClients(fd, args);
353 dumpInternals(fd, args);
354
355 // dump playback threads
356 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
357 mPlaybackThreads.valueAt(i)->dump(fd, args);
358 }
359
360 // dump record threads
361 for (size_t i = 0; i < mRecordThreads.size(); i++) {
362 mRecordThreads.valueAt(i)->dump(fd, args);
363 }
364
Dima Zavin799a70e2011-04-18 16:57:27 -0700365 // dump all hardware devs
366 for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
367 audio_hw_device_t *dev = mAudioHwDevs[i];
368 dev->dump(dev, fd);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700369 }
370 if (locked) mLock.unlock();
371 }
372 return NO_ERROR;
373}
374
375
376// IAudioFlinger interface
377
378
379sp<IAudioTrack> AudioFlinger::createTrack(
380 pid_t pid,
381 int streamType,
382 uint32_t sampleRate,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -0700383 uint32_t format,
384 uint32_t channelMask,
Mathias Agopian65ab4712010-07-14 17:59:35 -0700385 int frameCount,
386 uint32_t flags,
387 const sp<IMemory>& sharedBuffer,
388 int output,
389 int *sessionId,
390 status_t *status)
391{
392 sp<PlaybackThread::Track> track;
393 sp<TrackHandle> trackHandle;
394 sp<Client> client;
395 wp<Client> wclient;
396 status_t lStatus;
397 int lSessionId;
398
Dima Zavinfce7a472011-04-19 22:30:36 -0700399 if (streamType >= AUDIO_STREAM_CNT) {
Glenn Kastend8796012011-10-28 10:31:42 -0700400 LOGE("createTrack() invalid stream type %d", streamType);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700401 lStatus = BAD_VALUE;
402 goto Exit;
403 }
404
405 {
406 Mutex::Autolock _l(mLock);
407 PlaybackThread *thread = checkPlaybackThread_l(output);
Eric Laurent39e94f82010-07-28 01:32:47 -0700408 PlaybackThread *effectThread = NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700409 if (thread == NULL) {
410 LOGE("unknown output thread");
411 lStatus = BAD_VALUE;
412 goto Exit;
413 }
414
415 wclient = mClients.valueFor(pid);
416
417 if (wclient != NULL) {
418 client = wclient.promote();
419 } else {
420 client = new Client(this, pid);
421 mClients.add(pid, client);
422 }
423
Steve Block3856b092011-10-20 11:56:00 +0100424 ALOGV("createTrack() sessionId: %d", (sessionId == NULL) ? -2 : *sessionId);
Dima Zavinfce7a472011-04-19 22:30:36 -0700425 if (sessionId != NULL && *sessionId != AUDIO_SESSION_OUTPUT_MIX) {
Eric Laurentde070132010-07-13 04:45:46 -0700426 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
Eric Laurent39e94f82010-07-28 01:32:47 -0700427 sp<PlaybackThread> t = mPlaybackThreads.valueAt(i);
428 if (mPlaybackThreads.keyAt(i) != output) {
429 // prevent same audio session on different output threads
430 uint32_t sessions = t->hasAudioSession(*sessionId);
431 if (sessions & PlaybackThread::TRACK_SESSION) {
Glenn Kastend8796012011-10-28 10:31:42 -0700432 LOGE("createTrack() session ID %d already in use", *sessionId);
Eric Laurent39e94f82010-07-28 01:32:47 -0700433 lStatus = BAD_VALUE;
434 goto Exit;
435 }
436 // check if an effect with same session ID is waiting for a track to be created
437 if (sessions & PlaybackThread::EFFECT_SESSION) {
438 effectThread = t.get();
439 }
Eric Laurentde070132010-07-13 04:45:46 -0700440 }
441 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700442 lSessionId = *sessionId;
443 } else {
Eric Laurentde070132010-07-13 04:45:46 -0700444 // if no audio session id is provided, create one here
Eric Laurent7c7f10b2011-06-17 21:29:58 -0700445 lSessionId = nextUniqueId();
Mathias Agopian65ab4712010-07-14 17:59:35 -0700446 if (sessionId != NULL) {
447 *sessionId = lSessionId;
448 }
449 }
Steve Block3856b092011-10-20 11:56:00 +0100450 ALOGV("createTrack() lSessionId: %d", lSessionId);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700451
452 track = thread->createTrack_l(client, streamType, sampleRate, format,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -0700453 channelMask, frameCount, sharedBuffer, lSessionId, &lStatus);
Eric Laurent39e94f82010-07-28 01:32:47 -0700454
455 // move effect chain to this output thread if an effect on same session was waiting
456 // for a track to be created
457 if (lStatus == NO_ERROR && effectThread != NULL) {
458 Mutex::Autolock _dl(thread->mLock);
459 Mutex::Autolock _sl(effectThread->mLock);
460 moveEffectChain_l(lSessionId, effectThread, thread, true);
461 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700462 }
463 if (lStatus == NO_ERROR) {
464 trackHandle = new TrackHandle(track);
465 } else {
466 // remove local strong reference to Client before deleting the Track so that the Client
467 // destructor is called by the TrackBase destructor with mLock held
468 client.clear();
469 track.clear();
470 }
471
472Exit:
473 if(status) {
474 *status = lStatus;
475 }
476 return trackHandle;
477}
478
479uint32_t AudioFlinger::sampleRate(int output) const
480{
481 Mutex::Autolock _l(mLock);
482 PlaybackThread *thread = checkPlaybackThread_l(output);
483 if (thread == NULL) {
484 LOGW("sampleRate() unknown thread %d", output);
485 return 0;
486 }
487 return thread->sampleRate();
488}
489
490int AudioFlinger::channelCount(int output) const
491{
492 Mutex::Autolock _l(mLock);
493 PlaybackThread *thread = checkPlaybackThread_l(output);
494 if (thread == NULL) {
495 LOGW("channelCount() unknown thread %d", output);
496 return 0;
497 }
498 return thread->channelCount();
499}
500
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -0700501uint32_t AudioFlinger::format(int output) const
Mathias Agopian65ab4712010-07-14 17:59:35 -0700502{
503 Mutex::Autolock _l(mLock);
504 PlaybackThread *thread = checkPlaybackThread_l(output);
505 if (thread == NULL) {
506 LOGW("format() unknown thread %d", output);
507 return 0;
508 }
509 return thread->format();
510}
511
512size_t AudioFlinger::frameCount(int output) const
513{
514 Mutex::Autolock _l(mLock);
515 PlaybackThread *thread = checkPlaybackThread_l(output);
516 if (thread == NULL) {
517 LOGW("frameCount() unknown thread %d", output);
518 return 0;
519 }
520 return thread->frameCount();
521}
522
523uint32_t AudioFlinger::latency(int output) const
524{
525 Mutex::Autolock _l(mLock);
526 PlaybackThread *thread = checkPlaybackThread_l(output);
527 if (thread == NULL) {
528 LOGW("latency() unknown thread %d", output);
529 return 0;
530 }
531 return thread->latency();
532}
533
534status_t AudioFlinger::setMasterVolume(float value)
535{
Eric Laurenta1884f92011-08-23 08:25:03 -0700536 status_t ret = initCheck();
537 if (ret != NO_ERROR) {
538 return ret;
539 }
540
Mathias Agopian65ab4712010-07-14 17:59:35 -0700541 // check calling permissions
542 if (!settingsAllowed()) {
543 return PERMISSION_DENIED;
544 }
545
546 // when hw supports master volume, don't scale in sw mixer
Eric Laurent93575202011-01-18 18:39:02 -0800547 { // scope for the lock
548 AutoMutex lock(mHardwareLock);
549 mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
Dima Zavin799a70e2011-04-18 16:57:27 -0700550 if (mPrimaryHardwareDev->set_master_volume(mPrimaryHardwareDev, value) == NO_ERROR) {
Eric Laurent93575202011-01-18 18:39:02 -0800551 value = 1.0f;
552 }
553 mHardwareStatus = AUDIO_HW_IDLE;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700554 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700555
Eric Laurent93575202011-01-18 18:39:02 -0800556 Mutex::Autolock _l(mLock);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700557 mMasterVolume = value;
558 for (uint32_t i = 0; i < mPlaybackThreads.size(); i++)
559 mPlaybackThreads.valueAt(i)->setMasterVolume(value);
560
561 return NO_ERROR;
562}
563
564status_t AudioFlinger::setMode(int mode)
565{
Eric Laurenta1884f92011-08-23 08:25:03 -0700566 status_t ret = initCheck();
567 if (ret != NO_ERROR) {
568 return ret;
569 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700570
571 // check calling permissions
572 if (!settingsAllowed()) {
573 return PERMISSION_DENIED;
574 }
Dima Zavinfce7a472011-04-19 22:30:36 -0700575 if ((mode < 0) || (mode >= AUDIO_MODE_CNT)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700576 LOGW("Illegal value: setMode(%d)", mode);
577 return BAD_VALUE;
578 }
579
580 { // scope for the lock
581 AutoMutex lock(mHardwareLock);
582 mHardwareStatus = AUDIO_HW_SET_MODE;
Dima Zavin799a70e2011-04-18 16:57:27 -0700583 ret = mPrimaryHardwareDev->set_mode(mPrimaryHardwareDev, mode);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700584 mHardwareStatus = AUDIO_HW_IDLE;
585 }
586
587 if (NO_ERROR == ret) {
588 Mutex::Autolock _l(mLock);
589 mMode = mode;
590 for (uint32_t i = 0; i < mPlaybackThreads.size(); i++)
591 mPlaybackThreads.valueAt(i)->setMode(mode);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700592 }
593
594 return ret;
595}
596
597status_t AudioFlinger::setMicMute(bool state)
598{
Eric Laurenta1884f92011-08-23 08:25:03 -0700599 status_t ret = initCheck();
600 if (ret != NO_ERROR) {
601 return ret;
602 }
603
Mathias Agopian65ab4712010-07-14 17:59:35 -0700604 // check calling permissions
605 if (!settingsAllowed()) {
606 return PERMISSION_DENIED;
607 }
608
609 AutoMutex lock(mHardwareLock);
610 mHardwareStatus = AUDIO_HW_SET_MIC_MUTE;
Eric Laurenta1884f92011-08-23 08:25:03 -0700611 ret = mPrimaryHardwareDev->set_mic_mute(mPrimaryHardwareDev, state);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700612 mHardwareStatus = AUDIO_HW_IDLE;
613 return ret;
614}
615
616bool AudioFlinger::getMicMute() const
617{
Eric Laurenta1884f92011-08-23 08:25:03 -0700618 status_t ret = initCheck();
619 if (ret != NO_ERROR) {
620 return false;
621 }
622
Dima Zavinfce7a472011-04-19 22:30:36 -0700623 bool state = AUDIO_MODE_INVALID;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700624 mHardwareStatus = AUDIO_HW_GET_MIC_MUTE;
Dima Zavin799a70e2011-04-18 16:57:27 -0700625 mPrimaryHardwareDev->get_mic_mute(mPrimaryHardwareDev, &state);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700626 mHardwareStatus = AUDIO_HW_IDLE;
627 return state;
628}
629
630status_t AudioFlinger::setMasterMute(bool muted)
631{
632 // check calling permissions
633 if (!settingsAllowed()) {
634 return PERMISSION_DENIED;
635 }
636
Eric Laurent93575202011-01-18 18:39:02 -0800637 Mutex::Autolock _l(mLock);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700638 mMasterMute = muted;
639 for (uint32_t i = 0; i < mPlaybackThreads.size(); i++)
640 mPlaybackThreads.valueAt(i)->setMasterMute(muted);
641
642 return NO_ERROR;
643}
644
645float AudioFlinger::masterVolume() const
646{
647 return mMasterVolume;
648}
649
650bool AudioFlinger::masterMute() const
651{
652 return mMasterMute;
653}
654
655status_t AudioFlinger::setStreamVolume(int stream, float value, int output)
656{
657 // check calling permissions
658 if (!settingsAllowed()) {
659 return PERMISSION_DENIED;
660 }
661
Dima Zavinfce7a472011-04-19 22:30:36 -0700662 if (stream < 0 || uint32_t(stream) >= AUDIO_STREAM_CNT) {
Glenn Kastend8796012011-10-28 10:31:42 -0700663 LOGE("setStreamVolume() invalid stream %d", stream);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700664 return BAD_VALUE;
665 }
666
667 AutoMutex lock(mLock);
668 PlaybackThread *thread = NULL;
669 if (output) {
670 thread = checkPlaybackThread_l(output);
671 if (thread == NULL) {
672 return BAD_VALUE;
673 }
674 }
675
676 mStreamTypes[stream].volume = value;
677
678 if (thread == NULL) {
679 for (uint32_t i = 0; i < mPlaybackThreads.size(); i++) {
680 mPlaybackThreads.valueAt(i)->setStreamVolume(stream, value);
681 }
682 } else {
683 thread->setStreamVolume(stream, value);
684 }
685
686 return NO_ERROR;
687}
688
689status_t AudioFlinger::setStreamMute(int stream, bool muted)
690{
691 // check calling permissions
692 if (!settingsAllowed()) {
693 return PERMISSION_DENIED;
694 }
695
Dima Zavinfce7a472011-04-19 22:30:36 -0700696 if (stream < 0 || uint32_t(stream) >= AUDIO_STREAM_CNT ||
697 uint32_t(stream) == AUDIO_STREAM_ENFORCED_AUDIBLE) {
Glenn Kastend8796012011-10-28 10:31:42 -0700698 LOGE("setStreamMute() invalid stream %d", stream);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700699 return BAD_VALUE;
700 }
701
Eric Laurent93575202011-01-18 18:39:02 -0800702 AutoMutex lock(mLock);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700703 mStreamTypes[stream].mute = muted;
704 for (uint32_t i = 0; i < mPlaybackThreads.size(); i++)
705 mPlaybackThreads.valueAt(i)->setStreamMute(stream, muted);
706
707 return NO_ERROR;
708}
709
710float AudioFlinger::streamVolume(int stream, int output) const
711{
Dima Zavinfce7a472011-04-19 22:30:36 -0700712 if (stream < 0 || uint32_t(stream) >= AUDIO_STREAM_CNT) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700713 return 0.0f;
714 }
715
716 AutoMutex lock(mLock);
717 float volume;
718 if (output) {
719 PlaybackThread *thread = checkPlaybackThread_l(output);
720 if (thread == NULL) {
721 return 0.0f;
722 }
723 volume = thread->streamVolume(stream);
724 } else {
725 volume = mStreamTypes[stream].volume;
726 }
727
728 return volume;
729}
730
731bool AudioFlinger::streamMute(int stream) const
732{
Dima Zavinfce7a472011-04-19 22:30:36 -0700733 if (stream < 0 || stream >= (int)AUDIO_STREAM_CNT) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700734 return true;
735 }
736
737 return mStreamTypes[stream].mute;
738}
739
Mathias Agopian65ab4712010-07-14 17:59:35 -0700740status_t AudioFlinger::setParameters(int ioHandle, const String8& keyValuePairs)
741{
742 status_t result;
743
Steve Block3856b092011-10-20 11:56:00 +0100744 ALOGV("setParameters(): io %d, keyvalue %s, tid %d, calling tid %d",
Mathias Agopian65ab4712010-07-14 17:59:35 -0700745 ioHandle, keyValuePairs.string(), gettid(), IPCThreadState::self()->getCallingPid());
746 // check calling permissions
747 if (!settingsAllowed()) {
748 return PERMISSION_DENIED;
749 }
750
Mathias Agopian65ab4712010-07-14 17:59:35 -0700751 // ioHandle == 0 means the parameters are global to the audio hardware interface
752 if (ioHandle == 0) {
753 AutoMutex lock(mHardwareLock);
754 mHardwareStatus = AUDIO_SET_PARAMETER;
Dima Zavin799a70e2011-04-18 16:57:27 -0700755 status_t final_result = NO_ERROR;
756 for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
757 audio_hw_device_t *dev = mAudioHwDevs[i];
758 result = dev->set_parameters(dev, keyValuePairs.string());
759 final_result = result ?: final_result;
760 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700761 mHardwareStatus = AUDIO_HW_IDLE;
Eric Laurent59bd0da2011-08-01 09:52:20 -0700762 // disable AEC and NS if the device is a BT SCO headset supporting those pre processings
763 AudioParameter param = AudioParameter(keyValuePairs);
764 String8 value;
765 if (param.get(String8(AUDIO_PARAMETER_KEY_BT_NREC), value) == NO_ERROR) {
766 Mutex::Autolock _l(mLock);
Eric Laurentbee53372011-08-29 12:42:48 -0700767 bool btNrecIsOff = (value == AUDIO_PARAMETER_VALUE_OFF);
768 if (mBtNrecIsOff != btNrecIsOff) {
Eric Laurent59bd0da2011-08-01 09:52:20 -0700769 for (size_t i = 0; i < mRecordThreads.size(); i++) {
770 sp<RecordThread> thread = mRecordThreads.valueAt(i);
771 RecordThread::RecordTrack *track = thread->track();
772 if (track != NULL) {
773 audio_devices_t device = (audio_devices_t)(
774 thread->device() & AUDIO_DEVICE_IN_ALL);
Eric Laurentbee53372011-08-29 12:42:48 -0700775 bool suspend = audio_is_bluetooth_sco_device(device) && btNrecIsOff;
Eric Laurent59bd0da2011-08-01 09:52:20 -0700776 thread->setEffectSuspended(FX_IID_AEC,
777 suspend,
778 track->sessionId());
779 thread->setEffectSuspended(FX_IID_NS,
780 suspend,
781 track->sessionId());
782 }
783 }
Eric Laurentbee53372011-08-29 12:42:48 -0700784 mBtNrecIsOff = btNrecIsOff;
Eric Laurent59bd0da2011-08-01 09:52:20 -0700785 }
786 }
Dima Zavin799a70e2011-04-18 16:57:27 -0700787 return final_result;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700788 }
789
790 // hold a strong ref on thread in case closeOutput() or closeInput() is called
791 // and the thread is exited once the lock is released
792 sp<ThreadBase> thread;
793 {
794 Mutex::Autolock _l(mLock);
795 thread = checkPlaybackThread_l(ioHandle);
796 if (thread == NULL) {
797 thread = checkRecordThread_l(ioHandle);
Eric Laurent7c7f10b2011-06-17 21:29:58 -0700798 } else if (thread.get() == primaryPlaybackThread_l()) {
799 // indicate output device change to all input threads for pre processing
800 AudioParameter param = AudioParameter(keyValuePairs);
801 int value;
802 if (param.getInt(String8(AudioParameter::keyRouting), value) == NO_ERROR) {
803 for (size_t i = 0; i < mRecordThreads.size(); i++) {
804 mRecordThreads.valueAt(i)->setParameters(keyValuePairs);
805 }
806 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700807 }
808 }
809 if (thread != NULL) {
810 result = thread->setParameters(keyValuePairs);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700811 return result;
812 }
813 return BAD_VALUE;
814}
815
816String8 AudioFlinger::getParameters(int ioHandle, const String8& keys)
817{
Steve Block3856b092011-10-20 11:56:00 +0100818// ALOGV("getParameters() io %d, keys %s, tid %d, calling tid %d",
Mathias Agopian65ab4712010-07-14 17:59:35 -0700819// ioHandle, keys.string(), gettid(), IPCThreadState::self()->getCallingPid());
820
821 if (ioHandle == 0) {
Dima Zavinfce7a472011-04-19 22:30:36 -0700822 String8 out_s8;
823
Dima Zavin799a70e2011-04-18 16:57:27 -0700824 for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
825 audio_hw_device_t *dev = mAudioHwDevs[i];
826 char *s = dev->get_parameters(dev, keys.string());
827 out_s8 += String8(s);
828 free(s);
829 }
Dima Zavinfce7a472011-04-19 22:30:36 -0700830 return out_s8;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700831 }
832
833 Mutex::Autolock _l(mLock);
834
835 PlaybackThread *playbackThread = checkPlaybackThread_l(ioHandle);
836 if (playbackThread != NULL) {
837 return playbackThread->getParameters(keys);
838 }
839 RecordThread *recordThread = checkRecordThread_l(ioHandle);
840 if (recordThread != NULL) {
841 return recordThread->getParameters(keys);
842 }
843 return String8("");
844}
845
846size_t AudioFlinger::getInputBufferSize(uint32_t sampleRate, int format, int channelCount)
847{
Eric Laurenta1884f92011-08-23 08:25:03 -0700848 status_t ret = initCheck();
849 if (ret != NO_ERROR) {
850 return 0;
851 }
852
Dima Zavin799a70e2011-04-18 16:57:27 -0700853 return mPrimaryHardwareDev->get_input_buffer_size(mPrimaryHardwareDev, sampleRate, format, channelCount);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700854}
855
856unsigned int AudioFlinger::getInputFramesLost(int ioHandle)
857{
858 if (ioHandle == 0) {
859 return 0;
860 }
861
862 Mutex::Autolock _l(mLock);
863
864 RecordThread *recordThread = checkRecordThread_l(ioHandle);
865 if (recordThread != NULL) {
866 return recordThread->getInputFramesLost();
867 }
868 return 0;
869}
870
871status_t AudioFlinger::setVoiceVolume(float value)
872{
Eric Laurenta1884f92011-08-23 08:25:03 -0700873 status_t ret = initCheck();
874 if (ret != NO_ERROR) {
875 return ret;
876 }
877
Mathias Agopian65ab4712010-07-14 17:59:35 -0700878 // check calling permissions
879 if (!settingsAllowed()) {
880 return PERMISSION_DENIED;
881 }
882
883 AutoMutex lock(mHardwareLock);
884 mHardwareStatus = AUDIO_SET_VOICE_VOLUME;
Eric Laurenta1884f92011-08-23 08:25:03 -0700885 ret = mPrimaryHardwareDev->set_voice_volume(mPrimaryHardwareDev, value);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700886 mHardwareStatus = AUDIO_HW_IDLE;
887
888 return ret;
889}
890
891status_t AudioFlinger::getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames, int output)
892{
893 status_t status;
894
895 Mutex::Autolock _l(mLock);
896
897 PlaybackThread *playbackThread = checkPlaybackThread_l(output);
898 if (playbackThread != NULL) {
899 return playbackThread->getRenderPosition(halFrames, dspFrames);
900 }
901
902 return BAD_VALUE;
903}
904
905void AudioFlinger::registerClient(const sp<IAudioFlingerClient>& client)
906{
907
908 Mutex::Autolock _l(mLock);
909
910 int pid = IPCThreadState::self()->getCallingPid();
911 if (mNotificationClients.indexOfKey(pid) < 0) {
912 sp<NotificationClient> notificationClient = new NotificationClient(this,
913 client,
914 pid);
Steve Block3856b092011-10-20 11:56:00 +0100915 ALOGV("registerClient() client %p, pid %d", notificationClient.get(), pid);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700916
917 mNotificationClients.add(pid, notificationClient);
918
919 sp<IBinder> binder = client->asBinder();
920 binder->linkToDeath(notificationClient);
921
922 // the config change is always sent from playback or record threads to avoid deadlock
923 // with AudioSystem::gLock
924 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
925 mPlaybackThreads.valueAt(i)->sendConfigEvent(AudioSystem::OUTPUT_OPENED);
926 }
927
928 for (size_t i = 0; i < mRecordThreads.size(); i++) {
929 mRecordThreads.valueAt(i)->sendConfigEvent(AudioSystem::INPUT_OPENED);
930 }
931 }
932}
933
934void AudioFlinger::removeNotificationClient(pid_t pid)
935{
936 Mutex::Autolock _l(mLock);
937
938 int index = mNotificationClients.indexOfKey(pid);
939 if (index >= 0) {
940 sp <NotificationClient> client = mNotificationClients.valueFor(pid);
Steve Block3856b092011-10-20 11:56:00 +0100941 ALOGV("removeNotificationClient() %p, pid %d", client.get(), pid);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700942 mNotificationClients.removeItem(pid);
943 }
Marco Nelissen3a34bef2011-08-02 13:33:41 -0700944
Steve Block3856b092011-10-20 11:56:00 +0100945 ALOGV("%d died, releasing its sessions", pid);
Marco Nelissen3a34bef2011-08-02 13:33:41 -0700946 int num = mAudioSessionRefs.size();
947 bool removed = false;
948 for (int i = 0; i< num; i++) {
949 AudioSessionRef *ref = mAudioSessionRefs.itemAt(i);
Steve Block3856b092011-10-20 11:56:00 +0100950 ALOGV(" pid %d @ %d", ref->pid, i);
Marco Nelissen3a34bef2011-08-02 13:33:41 -0700951 if (ref->pid == pid) {
Steve Block3856b092011-10-20 11:56:00 +0100952 ALOGV(" removing entry for pid %d session %d", pid, ref->sessionid);
Marco Nelissen3a34bef2011-08-02 13:33:41 -0700953 mAudioSessionRefs.removeAt(i);
954 delete ref;
955 removed = true;
956 i--;
957 num--;
958 }
959 }
960 if (removed) {
961 purgeStaleEffects_l();
962 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700963}
964
965// audioConfigChanged_l() must be called with AudioFlinger::mLock held
966void AudioFlinger::audioConfigChanged_l(int event, int ioHandle, void *param2)
967{
968 size_t size = mNotificationClients.size();
969 for (size_t i = 0; i < size; i++) {
970 mNotificationClients.valueAt(i)->client()->ioConfigChanged(event, ioHandle, param2);
971 }
972}
973
974// removeClient_l() must be called with AudioFlinger::mLock held
975void AudioFlinger::removeClient_l(pid_t pid)
976{
Steve Block3856b092011-10-20 11:56:00 +0100977 ALOGV("removeClient_l() pid %d, tid %d, calling tid %d", pid, gettid(), IPCThreadState::self()->getCallingPid());
Mathias Agopian65ab4712010-07-14 17:59:35 -0700978 mClients.removeItem(pid);
979}
980
981
982// ----------------------------------------------------------------------------
983
Eric Laurent7c7f10b2011-06-17 21:29:58 -0700984AudioFlinger::ThreadBase::ThreadBase(const sp<AudioFlinger>& audioFlinger, int id, uint32_t device)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700985 : Thread(false),
986 mAudioFlinger(audioFlinger), mSampleRate(0), mFrameCount(0), mChannelCount(0),
Eric Laurentfeb0db62011-07-22 09:04:31 -0700987 mFrameSize(1), mFormat(0), mStandby(false), mId(id), mExiting(false),
988 mDevice(device)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700989{
Eric Laurentfeb0db62011-07-22 09:04:31 -0700990 mDeathRecipient = new PMDeathRecipient(this);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700991}
992
993AudioFlinger::ThreadBase::~ThreadBase()
994{
995 mParamCond.broadcast();
Eric Laurentfeb0db62011-07-22 09:04:31 -0700996 // do not lock the mutex in destructor
997 releaseWakeLock_l();
Eric Laurent9d18ec52011-09-27 12:07:15 -0700998 if (mPowerManager != 0) {
999 sp<IBinder> binder = mPowerManager->asBinder();
1000 binder->unlinkToDeath(mDeathRecipient);
1001 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07001002}
1003
1004void AudioFlinger::ThreadBase::exit()
1005{
Glenn Kasten362c4e62011-12-14 10:28:06 -08001006 // keep a strong ref on ourself so that we won't get
Mathias Agopian65ab4712010-07-14 17:59:35 -07001007 // destroyed in the middle of requestExitAndWait()
1008 sp <ThreadBase> strongMe = this;
1009
Steve Block3856b092011-10-20 11:56:00 +01001010 ALOGV("ThreadBase::exit");
Mathias Agopian65ab4712010-07-14 17:59:35 -07001011 {
1012 AutoMutex lock(&mLock);
1013 mExiting = true;
1014 requestExit();
1015 mWaitWorkCV.signal();
1016 }
1017 requestExitAndWait();
1018}
1019
1020uint32_t AudioFlinger::ThreadBase::sampleRate() const
1021{
1022 return mSampleRate;
1023}
1024
1025int AudioFlinger::ThreadBase::channelCount() const
1026{
1027 return (int)mChannelCount;
1028}
1029
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07001030uint32_t AudioFlinger::ThreadBase::format() const
Mathias Agopian65ab4712010-07-14 17:59:35 -07001031{
1032 return mFormat;
1033}
1034
1035size_t AudioFlinger::ThreadBase::frameCount() const
1036{
1037 return mFrameCount;
1038}
1039
1040status_t AudioFlinger::ThreadBase::setParameters(const String8& keyValuePairs)
1041{
1042 status_t status;
1043
Steve Block3856b092011-10-20 11:56:00 +01001044 ALOGV("ThreadBase::setParameters() %s", keyValuePairs.string());
Mathias Agopian65ab4712010-07-14 17:59:35 -07001045 Mutex::Autolock _l(mLock);
1046
1047 mNewParameters.add(keyValuePairs);
1048 mWaitWorkCV.signal();
1049 // wait condition with timeout in case the thread loop has exited
1050 // before the request could be processed
Glenn Kasten7dede872011-12-13 11:04:14 -08001051 if (mParamCond.waitRelative(mLock, kSetParametersTimeoutNs) == NO_ERROR) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001052 status = mParamStatus;
1053 mWaitWorkCV.signal();
1054 } else {
1055 status = TIMED_OUT;
1056 }
1057 return status;
1058}
1059
1060void AudioFlinger::ThreadBase::sendConfigEvent(int event, int param)
1061{
1062 Mutex::Autolock _l(mLock);
1063 sendConfigEvent_l(event, param);
1064}
1065
1066// sendConfigEvent_l() must be called with ThreadBase::mLock held
1067void AudioFlinger::ThreadBase::sendConfigEvent_l(int event, int param)
1068{
1069 ConfigEvent *configEvent = new ConfigEvent();
1070 configEvent->mEvent = event;
1071 configEvent->mParam = param;
1072 mConfigEvents.add(configEvent);
Steve Block3856b092011-10-20 11:56:00 +01001073 ALOGV("sendConfigEvent() num events %d event %d, param %d", mConfigEvents.size(), event, param);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001074 mWaitWorkCV.signal();
1075}
1076
1077void AudioFlinger::ThreadBase::processConfigEvents()
1078{
1079 mLock.lock();
1080 while(!mConfigEvents.isEmpty()) {
Steve Block3856b092011-10-20 11:56:00 +01001081 ALOGV("processConfigEvents() remaining events %d", mConfigEvents.size());
Mathias Agopian65ab4712010-07-14 17:59:35 -07001082 ConfigEvent *configEvent = mConfigEvents[0];
1083 mConfigEvents.removeAt(0);
1084 // release mLock before locking AudioFlinger mLock: lock order is always
1085 // AudioFlinger then ThreadBase to avoid cross deadlock
1086 mLock.unlock();
1087 mAudioFlinger->mLock.lock();
1088 audioConfigChanged_l(configEvent->mEvent, configEvent->mParam);
1089 mAudioFlinger->mLock.unlock();
1090 delete configEvent;
1091 mLock.lock();
1092 }
1093 mLock.unlock();
1094}
1095
1096status_t AudioFlinger::ThreadBase::dumpBase(int fd, const Vector<String16>& args)
1097{
1098 const size_t SIZE = 256;
1099 char buffer[SIZE];
1100 String8 result;
1101
1102 bool locked = tryLock(mLock);
1103 if (!locked) {
1104 snprintf(buffer, SIZE, "thread %p maybe dead locked\n", this);
1105 write(fd, buffer, strlen(buffer));
1106 }
1107
1108 snprintf(buffer, SIZE, "standby: %d\n", mStandby);
1109 result.append(buffer);
1110 snprintf(buffer, SIZE, "Sample rate: %d\n", mSampleRate);
1111 result.append(buffer);
1112 snprintf(buffer, SIZE, "Frame count: %d\n", mFrameCount);
1113 result.append(buffer);
1114 snprintf(buffer, SIZE, "Channel Count: %d\n", mChannelCount);
1115 result.append(buffer);
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07001116 snprintf(buffer, SIZE, "Channel Mask: 0x%08x\n", mChannelMask);
1117 result.append(buffer);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001118 snprintf(buffer, SIZE, "Format: %d\n", mFormat);
1119 result.append(buffer);
1120 snprintf(buffer, SIZE, "Frame size: %d\n", mFrameSize);
1121 result.append(buffer);
1122
1123 snprintf(buffer, SIZE, "\nPending setParameters commands: \n");
1124 result.append(buffer);
1125 result.append(" Index Command");
1126 for (size_t i = 0; i < mNewParameters.size(); ++i) {
1127 snprintf(buffer, SIZE, "\n %02d ", i);
1128 result.append(buffer);
1129 result.append(mNewParameters[i]);
1130 }
1131
1132 snprintf(buffer, SIZE, "\n\nPending config events: \n");
1133 result.append(buffer);
1134 snprintf(buffer, SIZE, " Index event param\n");
1135 result.append(buffer);
1136 for (size_t i = 0; i < mConfigEvents.size(); i++) {
1137 snprintf(buffer, SIZE, " %02d %02d %d\n", i, mConfigEvents[i]->mEvent, mConfigEvents[i]->mParam);
1138 result.append(buffer);
1139 }
1140 result.append("\n");
1141
1142 write(fd, result.string(), result.size());
1143
1144 if (locked) {
1145 mLock.unlock();
1146 }
1147 return NO_ERROR;
1148}
1149
Eric Laurent1d2bff02011-07-24 17:49:51 -07001150status_t AudioFlinger::ThreadBase::dumpEffectChains(int fd, const Vector<String16>& args)
1151{
1152 const size_t SIZE = 256;
1153 char buffer[SIZE];
1154 String8 result;
1155
1156 snprintf(buffer, SIZE, "\n- %d Effect Chains:\n", mEffectChains.size());
1157 write(fd, buffer, strlen(buffer));
1158
1159 for (size_t i = 0; i < mEffectChains.size(); ++i) {
1160 sp<EffectChain> chain = mEffectChains[i];
1161 if (chain != 0) {
1162 chain->dump(fd, args);
1163 }
1164 }
1165 return NO_ERROR;
1166}
1167
Eric Laurentfeb0db62011-07-22 09:04:31 -07001168void AudioFlinger::ThreadBase::acquireWakeLock()
1169{
1170 Mutex::Autolock _l(mLock);
1171 acquireWakeLock_l();
1172}
1173
1174void AudioFlinger::ThreadBase::acquireWakeLock_l()
1175{
1176 if (mPowerManager == 0) {
1177 // use checkService() to avoid blocking if power service is not up yet
1178 sp<IBinder> binder =
1179 defaultServiceManager()->checkService(String16("power"));
1180 if (binder == 0) {
1181 LOGW("Thread %s cannot connect to the power manager service", mName);
1182 } else {
1183 mPowerManager = interface_cast<IPowerManager>(binder);
1184 binder->linkToDeath(mDeathRecipient);
1185 }
1186 }
1187 if (mPowerManager != 0) {
1188 sp<IBinder> binder = new BBinder();
1189 status_t status = mPowerManager->acquireWakeLock(POWERMANAGER_PARTIAL_WAKE_LOCK,
1190 binder,
1191 String16(mName));
1192 if (status == NO_ERROR) {
1193 mWakeLockToken = binder;
1194 }
Steve Block3856b092011-10-20 11:56:00 +01001195 ALOGV("acquireWakeLock_l() %s status %d", mName, status);
Eric Laurentfeb0db62011-07-22 09:04:31 -07001196 }
1197}
1198
1199void AudioFlinger::ThreadBase::releaseWakeLock()
1200{
1201 Mutex::Autolock _l(mLock);
Eric Laurent6dbe8832011-07-28 13:59:02 -07001202 releaseWakeLock_l();
Eric Laurentfeb0db62011-07-22 09:04:31 -07001203}
1204
1205void AudioFlinger::ThreadBase::releaseWakeLock_l()
1206{
1207 if (mWakeLockToken != 0) {
Steve Block3856b092011-10-20 11:56:00 +01001208 ALOGV("releaseWakeLock_l() %s", mName);
Eric Laurentfeb0db62011-07-22 09:04:31 -07001209 if (mPowerManager != 0) {
1210 mPowerManager->releaseWakeLock(mWakeLockToken, 0);
1211 }
1212 mWakeLockToken.clear();
1213 }
1214}
1215
1216void AudioFlinger::ThreadBase::clearPowerManager()
1217{
1218 Mutex::Autolock _l(mLock);
1219 releaseWakeLock_l();
1220 mPowerManager.clear();
1221}
1222
1223void AudioFlinger::ThreadBase::PMDeathRecipient::binderDied(const wp<IBinder>& who)
1224{
1225 sp<ThreadBase> thread = mThread.promote();
1226 if (thread != 0) {
1227 thread->clearPowerManager();
1228 }
1229 LOGW("power manager service died !!!");
1230}
Eric Laurent1d2bff02011-07-24 17:49:51 -07001231
Eric Laurent59255e42011-07-27 19:49:51 -07001232void AudioFlinger::ThreadBase::setEffectSuspended(
1233 const effect_uuid_t *type, bool suspend, int sessionId)
1234{
1235 Mutex::Autolock _l(mLock);
1236 setEffectSuspended_l(type, suspend, sessionId);
1237}
1238
1239void AudioFlinger::ThreadBase::setEffectSuspended_l(
1240 const effect_uuid_t *type, bool suspend, int sessionId)
1241{
1242 sp<EffectChain> chain;
1243 chain = getEffectChain_l(sessionId);
1244 if (chain != 0) {
1245 if (type != NULL) {
1246 chain->setEffectSuspended_l(type, suspend);
1247 } else {
1248 chain->setEffectSuspendedAll_l(suspend);
1249 }
1250 }
1251
1252 updateSuspendedSessions_l(type, suspend, sessionId);
1253}
1254
1255void AudioFlinger::ThreadBase::checkSuspendOnAddEffectChain_l(const sp<EffectChain>& chain)
1256{
1257 int index = mSuspendedSessions.indexOfKey(chain->sessionId());
1258 if (index < 0) {
1259 return;
1260 }
1261
1262 KeyedVector <int, sp<SuspendedSessionDesc> > sessionEffects =
1263 mSuspendedSessions.editValueAt(index);
1264
1265 for (size_t i = 0; i < sessionEffects.size(); i++) {
1266 sp <SuspendedSessionDesc> desc = sessionEffects.valueAt(i);
1267 for (int j = 0; j < desc->mRefCount; j++) {
1268 if (sessionEffects.keyAt(i) == EffectChain::kKeyForSuspendAll) {
1269 chain->setEffectSuspendedAll_l(true);
1270 } else {
Steve Block3856b092011-10-20 11:56:00 +01001271 ALOGV("checkSuspendOnAddEffectChain_l() suspending effects %08x",
Eric Laurent59255e42011-07-27 19:49:51 -07001272 desc->mType.timeLow);
1273 chain->setEffectSuspended_l(&desc->mType, true);
1274 }
1275 }
1276 }
1277}
1278
Eric Laurent59255e42011-07-27 19:49:51 -07001279void AudioFlinger::ThreadBase::updateSuspendedSessions_l(const effect_uuid_t *type,
1280 bool suspend,
1281 int sessionId)
1282{
1283 int index = mSuspendedSessions.indexOfKey(sessionId);
1284
1285 KeyedVector <int, sp<SuspendedSessionDesc> > sessionEffects;
1286
1287 if (suspend) {
1288 if (index >= 0) {
1289 sessionEffects = mSuspendedSessions.editValueAt(index);
1290 } else {
1291 mSuspendedSessions.add(sessionId, sessionEffects);
1292 }
1293 } else {
1294 if (index < 0) {
1295 return;
1296 }
1297 sessionEffects = mSuspendedSessions.editValueAt(index);
1298 }
1299
1300
1301 int key = EffectChain::kKeyForSuspendAll;
1302 if (type != NULL) {
1303 key = type->timeLow;
1304 }
1305 index = sessionEffects.indexOfKey(key);
1306
1307 sp <SuspendedSessionDesc> desc;
1308 if (suspend) {
1309 if (index >= 0) {
1310 desc = sessionEffects.valueAt(index);
1311 } else {
1312 desc = new SuspendedSessionDesc();
1313 if (type != NULL) {
1314 memcpy(&desc->mType, type, sizeof(effect_uuid_t));
1315 }
1316 sessionEffects.add(key, desc);
Steve Block3856b092011-10-20 11:56:00 +01001317 ALOGV("updateSuspendedSessions_l() suspend adding effect %08x", key);
Eric Laurent59255e42011-07-27 19:49:51 -07001318 }
1319 desc->mRefCount++;
1320 } else {
1321 if (index < 0) {
1322 return;
1323 }
1324 desc = sessionEffects.valueAt(index);
1325 if (--desc->mRefCount == 0) {
Steve Block3856b092011-10-20 11:56:00 +01001326 ALOGV("updateSuspendedSessions_l() restore removing effect %08x", key);
Eric Laurent59255e42011-07-27 19:49:51 -07001327 sessionEffects.removeItemsAt(index);
1328 if (sessionEffects.isEmpty()) {
Steve Block3856b092011-10-20 11:56:00 +01001329 ALOGV("updateSuspendedSessions_l() restore removing session %d",
Eric Laurent59255e42011-07-27 19:49:51 -07001330 sessionId);
1331 mSuspendedSessions.removeItem(sessionId);
1332 }
1333 }
1334 }
1335 if (!sessionEffects.isEmpty()) {
1336 mSuspendedSessions.replaceValueFor(sessionId, sessionEffects);
1337 }
1338}
1339
1340void AudioFlinger::ThreadBase::checkSuspendOnEffectEnabled(const sp<EffectModule>& effect,
1341 bool enabled,
1342 int sessionId)
1343{
1344 Mutex::Autolock _l(mLock);
Eric Laurenta85a74a2011-10-19 11:44:54 -07001345 checkSuspendOnEffectEnabled_l(effect, enabled, sessionId);
1346}
Eric Laurent59255e42011-07-27 19:49:51 -07001347
Eric Laurenta85a74a2011-10-19 11:44:54 -07001348void AudioFlinger::ThreadBase::checkSuspendOnEffectEnabled_l(const sp<EffectModule>& effect,
1349 bool enabled,
1350 int sessionId)
1351{
Eric Laurentdb7c0792011-08-10 10:37:50 -07001352 if (mType != RECORD) {
1353 // suspend all effects in AUDIO_SESSION_OUTPUT_MIX when enabling any effect on
1354 // another session. This gives the priority to well behaved effect control panels
1355 // and applications not using global effects.
1356 if (sessionId != AUDIO_SESSION_OUTPUT_MIX) {
1357 setEffectSuspended_l(NULL, enabled, AUDIO_SESSION_OUTPUT_MIX);
1358 }
1359 }
Eric Laurent59255e42011-07-27 19:49:51 -07001360
1361 sp<EffectChain> chain = getEffectChain_l(sessionId);
1362 if (chain != 0) {
1363 chain->checkSuspendOnEffectEnabled(effect, enabled);
1364 }
1365}
1366
Mathias Agopian65ab4712010-07-14 17:59:35 -07001367// ----------------------------------------------------------------------------
1368
Eric Laurent7c7f10b2011-06-17 21:29:58 -07001369AudioFlinger::PlaybackThread::PlaybackThread(const sp<AudioFlinger>& audioFlinger,
1370 AudioStreamOut* output,
1371 int id,
1372 uint32_t device)
1373 : ThreadBase(audioFlinger, id, device),
Mathias Agopian65ab4712010-07-14 17:59:35 -07001374 mMixBuffer(0), mSuspended(0), mBytesWritten(0), mOutput(output),
Eric Laurent7c7f10b2011-06-17 21:29:58 -07001375 mLastWriteTime(0), mNumWrites(0), mNumDelayedWrites(0), mInWrite(false)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001376{
Eric Laurentfeb0db62011-07-22 09:04:31 -07001377 snprintf(mName, kNameLength, "AudioOut_%d", id);
1378
Mathias Agopian65ab4712010-07-14 17:59:35 -07001379 readOutputParameters();
1380
1381 mMasterVolume = mAudioFlinger->masterVolume();
1382 mMasterMute = mAudioFlinger->masterMute();
1383
Dima Zavinfce7a472011-04-19 22:30:36 -07001384 for (int stream = 0; stream < AUDIO_STREAM_CNT; stream++) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001385 mStreamTypes[stream].volume = mAudioFlinger->streamVolumeInternal(stream);
1386 mStreamTypes[stream].mute = mAudioFlinger->streamMute(stream);
Eric Laurent9f6530f2011-08-30 10:18:54 -07001387 mStreamTypes[stream].valid = true;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001388 }
1389}
1390
1391AudioFlinger::PlaybackThread::~PlaybackThread()
1392{
1393 delete [] mMixBuffer;
1394}
1395
1396status_t AudioFlinger::PlaybackThread::dump(int fd, const Vector<String16>& args)
1397{
1398 dumpInternals(fd, args);
1399 dumpTracks(fd, args);
1400 dumpEffectChains(fd, args);
1401 return NO_ERROR;
1402}
1403
1404status_t AudioFlinger::PlaybackThread::dumpTracks(int fd, const Vector<String16>& args)
1405{
1406 const size_t SIZE = 256;
1407 char buffer[SIZE];
1408 String8 result;
1409
1410 snprintf(buffer, SIZE, "Output thread %p tracks\n", this);
1411 result.append(buffer);
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07001412 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 -07001413 for (size_t i = 0; i < mTracks.size(); ++i) {
1414 sp<Track> track = mTracks[i];
1415 if (track != 0) {
1416 track->dump(buffer, SIZE);
1417 result.append(buffer);
1418 }
1419 }
1420
1421 snprintf(buffer, SIZE, "Output thread %p active tracks\n", this);
1422 result.append(buffer);
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07001423 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 -07001424 for (size_t i = 0; i < mActiveTracks.size(); ++i) {
1425 wp<Track> wTrack = mActiveTracks[i];
1426 if (wTrack != 0) {
1427 sp<Track> track = wTrack.promote();
1428 if (track != 0) {
1429 track->dump(buffer, SIZE);
1430 result.append(buffer);
1431 }
1432 }
1433 }
1434 write(fd, result.string(), result.size());
1435 return NO_ERROR;
1436}
1437
Mathias Agopian65ab4712010-07-14 17:59:35 -07001438status_t AudioFlinger::PlaybackThread::dumpInternals(int fd, const Vector<String16>& args)
1439{
1440 const size_t SIZE = 256;
1441 char buffer[SIZE];
1442 String8 result;
1443
1444 snprintf(buffer, SIZE, "\nOutput thread %p internals\n", this);
1445 result.append(buffer);
1446 snprintf(buffer, SIZE, "last write occurred (msecs): %llu\n", ns2ms(systemTime() - mLastWriteTime));
1447 result.append(buffer);
1448 snprintf(buffer, SIZE, "total writes: %d\n", mNumWrites);
1449 result.append(buffer);
1450 snprintf(buffer, SIZE, "delayed writes: %d\n", mNumDelayedWrites);
1451 result.append(buffer);
1452 snprintf(buffer, SIZE, "blocked in write: %d\n", mInWrite);
1453 result.append(buffer);
1454 snprintf(buffer, SIZE, "suspend count: %d\n", mSuspended);
1455 result.append(buffer);
1456 snprintf(buffer, SIZE, "mix buffer : %p\n", mMixBuffer);
1457 result.append(buffer);
1458 write(fd, result.string(), result.size());
1459
1460 dumpBase(fd, args);
1461
1462 return NO_ERROR;
1463}
1464
1465// Thread virtuals
1466status_t AudioFlinger::PlaybackThread::readyToRun()
1467{
Eric Laurentb8ba0a92011-08-07 16:32:26 -07001468 status_t status = initCheck();
1469 if (status == NO_ERROR) {
1470 LOGI("AudioFlinger's thread %p ready to run", this);
1471 } else {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001472 LOGE("No working audio driver found.");
Mathias Agopian65ab4712010-07-14 17:59:35 -07001473 }
Eric Laurentb8ba0a92011-08-07 16:32:26 -07001474 return status;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001475}
1476
1477void AudioFlinger::PlaybackThread::onFirstRef()
1478{
Eric Laurentfeb0db62011-07-22 09:04:31 -07001479 run(mName, ANDROID_PRIORITY_URGENT_AUDIO);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001480}
1481
1482// PlaybackThread::createTrack_l() must be called with AudioFlinger::mLock held
1483sp<AudioFlinger::PlaybackThread::Track> AudioFlinger::PlaybackThread::createTrack_l(
1484 const sp<AudioFlinger::Client>& client,
1485 int streamType,
1486 uint32_t sampleRate,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07001487 uint32_t format,
1488 uint32_t channelMask,
Mathias Agopian65ab4712010-07-14 17:59:35 -07001489 int frameCount,
1490 const sp<IMemory>& sharedBuffer,
1491 int sessionId,
1492 status_t *status)
1493{
1494 sp<Track> track;
1495 status_t lStatus;
1496
1497 if (mType == DIRECT) {
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07001498 if ((format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM) {
1499 if (sampleRate != mSampleRate || format != mFormat || channelMask != mChannelMask) {
1500 LOGE("createTrack_l() Bad parameter: sampleRate %d format %d, channelMask 0x%08x \""
1501 "for output %p with format %d",
1502 sampleRate, format, channelMask, mOutput, mFormat);
1503 lStatus = BAD_VALUE;
1504 goto Exit;
1505 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07001506 }
1507 } else {
1508 // Resampler implementation limits input sampling rate to 2 x output sampling rate.
1509 if (sampleRate > mSampleRate*2) {
1510 LOGE("Sample rate out of range: %d mSampleRate %d", sampleRate, mSampleRate);
1511 lStatus = BAD_VALUE;
1512 goto Exit;
1513 }
1514 }
1515
Eric Laurent7c7f10b2011-06-17 21:29:58 -07001516 lStatus = initCheck();
1517 if (lStatus != NO_ERROR) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001518 LOGE("Audio driver not initialized.");
Mathias Agopian65ab4712010-07-14 17:59:35 -07001519 goto Exit;
1520 }
1521
1522 { // scope for mLock
1523 Mutex::Autolock _l(mLock);
Eric Laurentde070132010-07-13 04:45:46 -07001524
1525 // all tracks in same audio session must share the same routing strategy otherwise
1526 // conflicts will happen when tracks are moved from one output to another by audio policy
1527 // manager
1528 uint32_t strategy =
Dima Zavinfce7a472011-04-19 22:30:36 -07001529 AudioSystem::getStrategyForStream((audio_stream_type_t)streamType);
Eric Laurentde070132010-07-13 04:45:46 -07001530 for (size_t i = 0; i < mTracks.size(); ++i) {
1531 sp<Track> t = mTracks[i];
1532 if (t != 0) {
Glenn Kastend8796012011-10-28 10:31:42 -07001533 uint32_t actual = AudioSystem::getStrategyForStream((audio_stream_type_t)t->type());
1534 if (sessionId == t->sessionId() && strategy != actual) {
1535 LOGE("createTrack_l() mismatched strategy; expected %u but found %u",
1536 strategy, actual);
Eric Laurentde070132010-07-13 04:45:46 -07001537 lStatus = BAD_VALUE;
1538 goto Exit;
1539 }
1540 }
1541 }
1542
Mathias Agopian65ab4712010-07-14 17:59:35 -07001543 track = new Track(this, client, streamType, sampleRate, format,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07001544 channelMask, frameCount, sharedBuffer, sessionId);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001545 if (track->getCblk() == NULL || track->name() < 0) {
1546 lStatus = NO_MEMORY;
1547 goto Exit;
1548 }
1549 mTracks.add(track);
1550
1551 sp<EffectChain> chain = getEffectChain_l(sessionId);
1552 if (chain != 0) {
Steve Block3856b092011-10-20 11:56:00 +01001553 ALOGV("createTrack_l() setting main buffer %p", chain->inBuffer());
Mathias Agopian65ab4712010-07-14 17:59:35 -07001554 track->setMainBuffer(chain->inBuffer());
Dima Zavinfce7a472011-04-19 22:30:36 -07001555 chain->setStrategy(AudioSystem::getStrategyForStream((audio_stream_type_t)track->type()));
Eric Laurentb469b942011-05-09 12:09:06 -07001556 chain->incTrackCnt();
Mathias Agopian65ab4712010-07-14 17:59:35 -07001557 }
Eric Laurent9f6530f2011-08-30 10:18:54 -07001558
1559 // invalidate track immediately if the stream type was moved to another thread since
1560 // createTrack() was called by the client process.
1561 if (!mStreamTypes[streamType].valid) {
1562 LOGW("createTrack_l() on thread %p: invalidating track on stream %d",
1563 this, streamType);
1564 android_atomic_or(CBLK_INVALID_ON, &track->mCblk->flags);
1565 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07001566 }
1567 lStatus = NO_ERROR;
1568
1569Exit:
1570 if(status) {
1571 *status = lStatus;
1572 }
1573 return track;
1574}
1575
1576uint32_t AudioFlinger::PlaybackThread::latency() const
1577{
Eric Laurentb8ba0a92011-08-07 16:32:26 -07001578 Mutex::Autolock _l(mLock);
1579 if (initCheck() == NO_ERROR) {
Dima Zavin799a70e2011-04-18 16:57:27 -07001580 return mOutput->stream->get_latency(mOutput->stream);
Eric Laurentb8ba0a92011-08-07 16:32:26 -07001581 } else {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001582 return 0;
1583 }
1584}
1585
1586status_t AudioFlinger::PlaybackThread::setMasterVolume(float value)
1587{
Mathias Agopian65ab4712010-07-14 17:59:35 -07001588 mMasterVolume = value;
1589 return NO_ERROR;
1590}
1591
1592status_t AudioFlinger::PlaybackThread::setMasterMute(bool muted)
1593{
Mathias Agopian65ab4712010-07-14 17:59:35 -07001594 mMasterMute = muted;
1595 return NO_ERROR;
1596}
1597
1598float AudioFlinger::PlaybackThread::masterVolume() const
1599{
1600 return mMasterVolume;
1601}
1602
1603bool AudioFlinger::PlaybackThread::masterMute() const
1604{
1605 return mMasterMute;
1606}
1607
1608status_t AudioFlinger::PlaybackThread::setStreamVolume(int stream, float value)
1609{
Mathias Agopian65ab4712010-07-14 17:59:35 -07001610 mStreamTypes[stream].volume = value;
1611 return NO_ERROR;
1612}
1613
1614status_t AudioFlinger::PlaybackThread::setStreamMute(int stream, bool muted)
1615{
Mathias Agopian65ab4712010-07-14 17:59:35 -07001616 mStreamTypes[stream].mute = muted;
1617 return NO_ERROR;
1618}
1619
1620float AudioFlinger::PlaybackThread::streamVolume(int stream) const
1621{
1622 return mStreamTypes[stream].volume;
1623}
1624
1625bool AudioFlinger::PlaybackThread::streamMute(int stream) const
1626{
1627 return mStreamTypes[stream].mute;
1628}
1629
Mathias Agopian65ab4712010-07-14 17:59:35 -07001630// addTrack_l() must be called with ThreadBase::mLock held
1631status_t AudioFlinger::PlaybackThread::addTrack_l(const sp<Track>& track)
1632{
1633 status_t status = ALREADY_EXISTS;
1634
1635 // set retry count for buffer fill
1636 track->mRetryCount = kMaxTrackStartupRetries;
1637 if (mActiveTracks.indexOf(track) < 0) {
1638 // the track is newly added, make sure it fills up all its
1639 // buffers before playing. This is to ensure the client will
1640 // effectively get the latency it requested.
1641 track->mFillingUpStatus = Track::FS_FILLING;
1642 track->mResetDone = false;
1643 mActiveTracks.add(track);
1644 if (track->mainBuffer() != mMixBuffer) {
1645 sp<EffectChain> chain = getEffectChain_l(track->sessionId());
1646 if (chain != 0) {
Steve Block3856b092011-10-20 11:56:00 +01001647 ALOGV("addTrack_l() starting track on chain %p for session %d", chain.get(), track->sessionId());
Eric Laurentb469b942011-05-09 12:09:06 -07001648 chain->incActiveTrackCnt();
Mathias Agopian65ab4712010-07-14 17:59:35 -07001649 }
1650 }
1651
1652 status = NO_ERROR;
1653 }
1654
Steve Block3856b092011-10-20 11:56:00 +01001655 ALOGV("mWaitWorkCV.broadcast");
Mathias Agopian65ab4712010-07-14 17:59:35 -07001656 mWaitWorkCV.broadcast();
1657
1658 return status;
1659}
1660
1661// destroyTrack_l() must be called with ThreadBase::mLock held
1662void AudioFlinger::PlaybackThread::destroyTrack_l(const sp<Track>& track)
1663{
1664 track->mState = TrackBase::TERMINATED;
1665 if (mActiveTracks.indexOf(track) < 0) {
Eric Laurentb469b942011-05-09 12:09:06 -07001666 removeTrack_l(track);
1667 }
1668}
1669
1670void AudioFlinger::PlaybackThread::removeTrack_l(const sp<Track>& track)
1671{
1672 mTracks.remove(track);
1673 deleteTrackName_l(track->name());
1674 sp<EffectChain> chain = getEffectChain_l(track->sessionId());
1675 if (chain != 0) {
1676 chain->decTrackCnt();
Mathias Agopian65ab4712010-07-14 17:59:35 -07001677 }
1678}
1679
1680String8 AudioFlinger::PlaybackThread::getParameters(const String8& keys)
1681{
Eric Laurentb8ba0a92011-08-07 16:32:26 -07001682 String8 out_s8 = String8("");
Dima Zavinfce7a472011-04-19 22:30:36 -07001683 char *s;
1684
Eric Laurentb8ba0a92011-08-07 16:32:26 -07001685 Mutex::Autolock _l(mLock);
1686 if (initCheck() != NO_ERROR) {
1687 return out_s8;
1688 }
1689
Dima Zavin799a70e2011-04-18 16:57:27 -07001690 s = mOutput->stream->common.get_parameters(&mOutput->stream->common, keys.string());
Dima Zavinfce7a472011-04-19 22:30:36 -07001691 out_s8 = String8(s);
1692 free(s);
1693 return out_s8;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001694}
1695
Eric Laurentb8ba0a92011-08-07 16:32:26 -07001696// audioConfigChanged_l() must be called with AudioFlinger::mLock held
Mathias Agopian65ab4712010-07-14 17:59:35 -07001697void AudioFlinger::PlaybackThread::audioConfigChanged_l(int event, int param) {
1698 AudioSystem::OutputDescriptor desc;
1699 void *param2 = 0;
1700
Steve Block3856b092011-10-20 11:56:00 +01001701 ALOGV("PlaybackThread::audioConfigChanged_l, thread %p, event %d, param %d", this, event, param);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001702
1703 switch (event) {
1704 case AudioSystem::OUTPUT_OPENED:
1705 case AudioSystem::OUTPUT_CONFIG_CHANGED:
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07001706 desc.channels = mChannelMask;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001707 desc.samplingRate = mSampleRate;
1708 desc.format = mFormat;
1709 desc.frameCount = mFrameCount;
1710 desc.latency = latency();
1711 param2 = &desc;
1712 break;
1713
1714 case AudioSystem::STREAM_CONFIG_CHANGED:
1715 param2 = &param;
1716 case AudioSystem::OUTPUT_CLOSED:
1717 default:
1718 break;
1719 }
1720 mAudioFlinger->audioConfigChanged_l(event, mId, param2);
1721}
1722
1723void AudioFlinger::PlaybackThread::readOutputParameters()
1724{
Dima Zavin799a70e2011-04-18 16:57:27 -07001725 mSampleRate = mOutput->stream->common.get_sample_rate(&mOutput->stream->common);
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07001726 mChannelMask = mOutput->stream->common.get_channels(&mOutput->stream->common);
1727 mChannelCount = (uint16_t)popcount(mChannelMask);
Dima Zavin799a70e2011-04-18 16:57:27 -07001728 mFormat = mOutput->stream->common.get_format(&mOutput->stream->common);
1729 mFrameSize = (uint16_t)audio_stream_frame_size(&mOutput->stream->common);
1730 mFrameCount = mOutput->stream->common.get_buffer_size(&mOutput->stream->common) / mFrameSize;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001731
1732 // FIXME - Current mixer implementation only supports stereo output: Always
1733 // Allocate a stereo buffer even if HW output is mono.
1734 if (mMixBuffer != NULL) delete[] mMixBuffer;
1735 mMixBuffer = new int16_t[mFrameCount * 2];
1736 memset(mMixBuffer, 0, mFrameCount * 2 * sizeof(int16_t));
1737
Eric Laurentde070132010-07-13 04:45:46 -07001738 // force reconfiguration of effect chains and engines to take new buffer size and audio
1739 // parameters into account
1740 // Note that mLock is not held when readOutputParameters() is called from the constructor
1741 // but in this case nothing is done below as no audio sessions have effect yet so it doesn't
1742 // matter.
1743 // create a copy of mEffectChains as calling moveEffectChain_l() can reorder some effect chains
1744 Vector< sp<EffectChain> > effectChains = mEffectChains;
1745 for (size_t i = 0; i < effectChains.size(); i ++) {
Eric Laurent39e94f82010-07-28 01:32:47 -07001746 mAudioFlinger->moveEffectChain_l(effectChains[i]->sessionId(), this, this, false);
Eric Laurentde070132010-07-13 04:45:46 -07001747 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07001748}
1749
1750status_t AudioFlinger::PlaybackThread::getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames)
1751{
1752 if (halFrames == 0 || dspFrames == 0) {
1753 return BAD_VALUE;
1754 }
Eric Laurentb8ba0a92011-08-07 16:32:26 -07001755 Mutex::Autolock _l(mLock);
Eric Laurent7c7f10b2011-06-17 21:29:58 -07001756 if (initCheck() != NO_ERROR) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001757 return INVALID_OPERATION;
1758 }
Dima Zavin799a70e2011-04-18 16:57:27 -07001759 *halFrames = mBytesWritten / audio_stream_frame_size(&mOutput->stream->common);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001760
Dima Zavin799a70e2011-04-18 16:57:27 -07001761 return mOutput->stream->get_render_position(mOutput->stream, dspFrames);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001762}
1763
Eric Laurent39e94f82010-07-28 01:32:47 -07001764uint32_t AudioFlinger::PlaybackThread::hasAudioSession(int sessionId)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001765{
1766 Mutex::Autolock _l(mLock);
Eric Laurent39e94f82010-07-28 01:32:47 -07001767 uint32_t result = 0;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001768 if (getEffectChain_l(sessionId) != 0) {
Eric Laurent39e94f82010-07-28 01:32:47 -07001769 result = EFFECT_SESSION;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001770 }
1771
1772 for (size_t i = 0; i < mTracks.size(); ++i) {
1773 sp<Track> track = mTracks[i];
Eric Laurentde070132010-07-13 04:45:46 -07001774 if (sessionId == track->sessionId() &&
1775 !(track->mCblk->flags & CBLK_INVALID_MSK)) {
Eric Laurent39e94f82010-07-28 01:32:47 -07001776 result |= TRACK_SESSION;
1777 break;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001778 }
1779 }
1780
Eric Laurent39e94f82010-07-28 01:32:47 -07001781 return result;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001782}
1783
Eric Laurentde070132010-07-13 04:45:46 -07001784uint32_t AudioFlinger::PlaybackThread::getStrategyForSession_l(int sessionId)
1785{
Dima Zavinfce7a472011-04-19 22:30:36 -07001786 // session AUDIO_SESSION_OUTPUT_MIX is placed in same strategy as MUSIC stream so that
Eric Laurentde070132010-07-13 04:45:46 -07001787 // it is moved to correct output by audio policy manager when A2DP is connected or disconnected
Dima Zavinfce7a472011-04-19 22:30:36 -07001788 if (sessionId == AUDIO_SESSION_OUTPUT_MIX) {
1789 return AudioSystem::getStrategyForStream(AUDIO_STREAM_MUSIC);
Eric Laurentde070132010-07-13 04:45:46 -07001790 }
1791 for (size_t i = 0; i < mTracks.size(); i++) {
1792 sp<Track> track = mTracks[i];
1793 if (sessionId == track->sessionId() &&
1794 !(track->mCblk->flags & CBLK_INVALID_MSK)) {
Dima Zavinfce7a472011-04-19 22:30:36 -07001795 return AudioSystem::getStrategyForStream((audio_stream_type_t) track->type());
Eric Laurentde070132010-07-13 04:45:46 -07001796 }
1797 }
Dima Zavinfce7a472011-04-19 22:30:36 -07001798 return AudioSystem::getStrategyForStream(AUDIO_STREAM_MUSIC);
Eric Laurentde070132010-07-13 04:45:46 -07001799}
1800
Mathias Agopian65ab4712010-07-14 17:59:35 -07001801
Eric Laurentb8ba0a92011-08-07 16:32:26 -07001802AudioFlinger::AudioStreamOut* AudioFlinger::PlaybackThread::getOutput()
1803{
1804 Mutex::Autolock _l(mLock);
1805 return mOutput;
1806}
1807
1808AudioFlinger::AudioStreamOut* AudioFlinger::PlaybackThread::clearOutput()
1809{
1810 Mutex::Autolock _l(mLock);
1811 AudioStreamOut *output = mOutput;
1812 mOutput = NULL;
1813 return output;
1814}
1815
1816// this method must always be called either with ThreadBase mLock held or inside the thread loop
1817audio_stream_t* AudioFlinger::PlaybackThread::stream()
1818{
1819 if (mOutput == NULL) {
1820 return NULL;
1821 }
1822 return &mOutput->stream->common;
1823}
1824
Eric Laurent162b40b2011-12-05 09:47:19 -08001825uint32_t AudioFlinger::PlaybackThread::activeSleepTimeUs()
1826{
1827 // A2DP output latency is not due only to buffering capacity. It also reflects encoding,
1828 // decoding and transfer time. So sleeping for half of the latency would likely cause
1829 // underruns
1830 if (audio_is_a2dp_device((audio_devices_t)mDevice)) {
1831 return (uint32_t)((uint32_t)((mFrameCount * 1000) / mSampleRate) * 1000);
1832 } else {
1833 return (uint32_t)(mOutput->stream->get_latency(mOutput->stream) * 1000) / 2;
1834 }
1835}
1836
Mathias Agopian65ab4712010-07-14 17:59:35 -07001837// ----------------------------------------------------------------------------
1838
Dima Zavin799a70e2011-04-18 16:57:27 -07001839AudioFlinger::MixerThread::MixerThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id, uint32_t device)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001840 : PlaybackThread(audioFlinger, output, id, device),
1841 mAudioMixer(0)
1842{
Eric Laurent7c7f10b2011-06-17 21:29:58 -07001843 mType = ThreadBase::MIXER;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001844 mAudioMixer = new AudioMixer(mFrameCount, mSampleRate);
1845
1846 // FIXME - Current mixer implementation only supports stereo output
1847 if (mChannelCount == 1) {
1848 LOGE("Invalid audio hardware channel count");
1849 }
1850}
1851
1852AudioFlinger::MixerThread::~MixerThread()
1853{
1854 delete mAudioMixer;
1855}
1856
1857bool AudioFlinger::MixerThread::threadLoop()
1858{
1859 Vector< sp<Track> > tracksToRemove;
1860 uint32_t mixerStatus = MIXER_IDLE;
1861 nsecs_t standbyTime = systemTime();
1862 size_t mixBufferSize = mFrameCount * mFrameSize;
1863 // FIXME: Relaxed timing because of a certain device that can't meet latency
1864 // Should be reduced to 2x after the vendor fixes the driver issue
Eric Laurent5c4e8182011-10-18 15:42:27 -07001865 // increase threshold again due to low power audio mode. The way this warning threshold is
1866 // calculated and its usefulness should be reconsidered anyway.
1867 nsecs_t maxPeriod = seconds(mFrameCount) / mSampleRate * 15;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001868 nsecs_t lastWarning = 0;
1869 bool longStandbyExit = false;
1870 uint32_t activeSleepTime = activeSleepTimeUs();
1871 uint32_t idleSleepTime = idleSleepTimeUs();
1872 uint32_t sleepTime = idleSleepTime;
Eric Laurent7cafbb32011-11-22 18:50:29 -08001873 uint32_t sleepTimeShift = 0;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001874 Vector< sp<EffectChain> > effectChains;
Glenn Kasten4d8d0c32011-07-08 15:26:12 -07001875#ifdef DEBUG_CPU_USAGE
1876 ThreadCpuUsage cpu;
1877 const CentralTendencyStatistics& stats = cpu.statistics();
1878#endif
Mathias Agopian65ab4712010-07-14 17:59:35 -07001879
Eric Laurentfeb0db62011-07-22 09:04:31 -07001880 acquireWakeLock();
1881
Mathias Agopian65ab4712010-07-14 17:59:35 -07001882 while (!exitPending())
1883 {
Glenn Kasten4d8d0c32011-07-08 15:26:12 -07001884#ifdef DEBUG_CPU_USAGE
1885 cpu.sampleAndEnable();
1886 unsigned n = stats.n();
1887 // cpu.elapsed() is expensive, so don't call it every loop
1888 if ((n & 127) == 1) {
1889 long long elapsed = cpu.elapsed();
1890 if (elapsed >= DEBUG_CPU_USAGE * 1000000000LL) {
1891 double perLoop = elapsed / (double) n;
1892 double perLoop100 = perLoop * 0.01;
1893 double mean = stats.mean();
1894 double stddev = stats.stddev();
1895 double minimum = stats.minimum();
1896 double maximum = stats.maximum();
1897 cpu.resetStatistics();
1898 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",
1899 elapsed * .000000001, n, perLoop * .000001,
1900 mean * .001,
1901 stddev * .001,
1902 minimum * .001,
1903 maximum * .001,
1904 mean / perLoop100,
1905 stddev / perLoop100,
1906 minimum / perLoop100,
1907 maximum / perLoop100);
1908 }
1909 }
1910#endif
Mathias Agopian65ab4712010-07-14 17:59:35 -07001911 processConfigEvents();
1912
1913 mixerStatus = MIXER_IDLE;
1914 { // scope for mLock
1915
1916 Mutex::Autolock _l(mLock);
1917
1918 if (checkForNewParameters_l()) {
1919 mixBufferSize = mFrameCount * mFrameSize;
1920 // FIXME: Relaxed timing because of a certain device that can't meet latency
1921 // Should be reduced to 2x after the vendor fixes the driver issue
Eric Laurent5c4e8182011-10-18 15:42:27 -07001922 // increase threshold again due to low power audio mode. The way this warning
1923 // threshold is calculated and its usefulness should be reconsidered anyway.
1924 maxPeriod = seconds(mFrameCount) / mSampleRate * 15;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001925 activeSleepTime = activeSleepTimeUs();
1926 idleSleepTime = idleSleepTimeUs();
1927 }
1928
1929 const SortedVector< wp<Track> >& activeTracks = mActiveTracks;
1930
1931 // put audio hardware into standby after short delay
1932 if UNLIKELY((!activeTracks.size() && systemTime() > standbyTime) ||
1933 mSuspended) {
1934 if (!mStandby) {
Steve Block3856b092011-10-20 11:56:00 +01001935 ALOGV("Audio hardware entering standby, mixer %p, mSuspended %d\n", this, mSuspended);
Dima Zavin799a70e2011-04-18 16:57:27 -07001936 mOutput->stream->common.standby(&mOutput->stream->common);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001937 mStandby = true;
1938 mBytesWritten = 0;
1939 }
1940
1941 if (!activeTracks.size() && mConfigEvents.isEmpty()) {
1942 // we're about to wait, flush the binder command buffer
1943 IPCThreadState::self()->flushCommands();
1944
1945 if (exitPending()) break;
1946
Eric Laurentfeb0db62011-07-22 09:04:31 -07001947 releaseWakeLock_l();
Mathias Agopian65ab4712010-07-14 17:59:35 -07001948 // wait until we have something to do...
Steve Block3856b092011-10-20 11:56:00 +01001949 ALOGV("MixerThread %p TID %d going to sleep\n", this, gettid());
Mathias Agopian65ab4712010-07-14 17:59:35 -07001950 mWaitWorkCV.wait(mLock);
Steve Block3856b092011-10-20 11:56:00 +01001951 ALOGV("MixerThread %p TID %d waking up\n", this, gettid());
Eric Laurentfeb0db62011-07-22 09:04:31 -07001952 acquireWakeLock_l();
Mathias Agopian65ab4712010-07-14 17:59:35 -07001953
1954 if (mMasterMute == false) {
1955 char value[PROPERTY_VALUE_MAX];
1956 property_get("ro.audio.silent", value, "0");
1957 if (atoi(value)) {
1958 LOGD("Silence is golden");
1959 setMasterMute(true);
1960 }
1961 }
1962
1963 standbyTime = systemTime() + kStandbyTimeInNsecs;
1964 sleepTime = idleSleepTime;
Eric Laurent7cafbb32011-11-22 18:50:29 -08001965 sleepTimeShift = 0;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001966 continue;
1967 }
1968 }
1969
1970 mixerStatus = prepareTracks_l(activeTracks, &tracksToRemove);
1971
1972 // prevent any changes in effect chain list and in each effect chain
1973 // during mixing and effect process as the audio buffers could be deleted
1974 // or modified if an effect is created or deleted
Eric Laurentde070132010-07-13 04:45:46 -07001975 lockEffectChains_l(effectChains);
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -08001976 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07001977
1978 if (LIKELY(mixerStatus == MIXER_TRACKS_READY)) {
1979 // mix buffers...
1980 mAudioMixer->process();
1981 sleepTime = 0;
Eric Laurent7cafbb32011-11-22 18:50:29 -08001982 // increase sleep time progressively when application underrun condition clears
1983 if (sleepTimeShift > 0) {
1984 sleepTimeShift--;
1985 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07001986 standbyTime = systemTime() + kStandbyTimeInNsecs;
1987 //TODO: delay standby when effects have a tail
1988 } else {
1989 // If no tracks are ready, sleep once for the duration of an output
1990 // buffer size, then write 0s to the output
1991 if (sleepTime == 0) {
1992 if (mixerStatus == MIXER_TRACKS_ENABLED) {
Eric Laurent7cafbb32011-11-22 18:50:29 -08001993 sleepTime = activeSleepTime >> sleepTimeShift;
1994 if (sleepTime < kMinThreadSleepTimeUs) {
1995 sleepTime = kMinThreadSleepTimeUs;
1996 }
1997 // reduce sleep time in case of consecutive application underruns to avoid
1998 // starving the audio HAL. As activeSleepTimeUs() is larger than a buffer
1999 // duration we would end up writing less data than needed by the audio HAL if
2000 // the condition persists.
2001 if (sleepTimeShift < kMaxThreadSleepTimeShift) {
2002 sleepTimeShift++;
2003 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07002004 } else {
2005 sleepTime = idleSleepTime;
2006 }
2007 } else if (mBytesWritten != 0 ||
2008 (mixerStatus == MIXER_TRACKS_ENABLED && longStandbyExit)) {
2009 memset (mMixBuffer, 0, mixBufferSize);
2010 sleepTime = 0;
Steve Block3856b092011-10-20 11:56:00 +01002011 ALOGV_IF((mBytesWritten == 0 && (mixerStatus == MIXER_TRACKS_ENABLED && longStandbyExit)), "anticipated start");
Mathias Agopian65ab4712010-07-14 17:59:35 -07002012 }
2013 // TODO add standby time extension fct of effect tail
2014 }
2015
2016 if (mSuspended) {
Eric Laurent25cbe0e2010-08-18 18:13:17 -07002017 sleepTime = suspendSleepTimeUs();
Mathias Agopian65ab4712010-07-14 17:59:35 -07002018 }
2019 // sleepTime == 0 means we must write to audio hardware
2020 if (sleepTime == 0) {
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -08002021 for (size_t i = 0; i < effectChains.size(); i ++) {
2022 effectChains[i]->process_l();
2023 }
2024 // enable changes in effect chain
2025 unlockEffectChains(effectChains);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002026 mLastWriteTime = systemTime();
2027 mInWrite = true;
2028 mBytesWritten += mixBufferSize;
2029
Dima Zavin799a70e2011-04-18 16:57:27 -07002030 int bytesWritten = (int)mOutput->stream->write(mOutput->stream, mMixBuffer, mixBufferSize);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002031 if (bytesWritten < 0) mBytesWritten -= mixBufferSize;
2032 mNumWrites++;
2033 mInWrite = false;
2034 nsecs_t now = systemTime();
2035 nsecs_t delta = now - mLastWriteTime;
Eric Laurent5c4e8182011-10-18 15:42:27 -07002036 if (!mStandby && delta > maxPeriod) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07002037 mNumDelayedWrites++;
Glenn Kasten7dede872011-12-13 11:04:14 -08002038 if ((now - lastWarning) > kWarningThrottleNs) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07002039 LOGW("write blocked for %llu msecs, %d delayed writes, thread %p",
2040 ns2ms(delta), mNumDelayedWrites, this);
2041 lastWarning = now;
2042 }
2043 if (mStandby) {
2044 longStandbyExit = true;
2045 }
2046 }
2047 mStandby = false;
2048 } else {
2049 // enable changes in effect chain
Eric Laurentde070132010-07-13 04:45:46 -07002050 unlockEffectChains(effectChains);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002051 usleep(sleepTime);
2052 }
2053
2054 // finally let go of all our tracks, without the lock held
2055 // since we can't guarantee the destructors won't acquire that
2056 // same lock.
2057 tracksToRemove.clear();
2058
2059 // Effect chains will be actually deleted here if they were removed from
2060 // mEffectChains list during mixing or effects processing
2061 effectChains.clear();
2062 }
2063
2064 if (!mStandby) {
Dima Zavin799a70e2011-04-18 16:57:27 -07002065 mOutput->stream->common.standby(&mOutput->stream->common);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002066 }
2067
Eric Laurentfeb0db62011-07-22 09:04:31 -07002068 releaseWakeLock();
2069
Steve Block3856b092011-10-20 11:56:00 +01002070 ALOGV("MixerThread %p exiting", this);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002071 return false;
2072}
2073
2074// prepareTracks_l() must be called with ThreadBase::mLock held
2075uint32_t AudioFlinger::MixerThread::prepareTracks_l(const SortedVector< wp<Track> >& activeTracks, Vector< sp<Track> > *tracksToRemove)
2076{
2077
2078 uint32_t mixerStatus = MIXER_IDLE;
2079 // find out which tracks need to be processed
2080 size_t count = activeTracks.size();
2081 size_t mixedTracks = 0;
2082 size_t tracksWithEffect = 0;
2083
2084 float masterVolume = mMasterVolume;
2085 bool masterMute = mMasterMute;
2086
Eric Laurent571d49c2010-08-11 05:20:11 -07002087 if (masterMute) {
2088 masterVolume = 0;
2089 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07002090 // Delegate master volume control to effect in output mix effect chain if needed
Dima Zavinfce7a472011-04-19 22:30:36 -07002091 sp<EffectChain> chain = getEffectChain_l(AUDIO_SESSION_OUTPUT_MIX);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002092 if (chain != 0) {
Eric Laurent571d49c2010-08-11 05:20:11 -07002093 uint32_t v = (uint32_t)(masterVolume * (1 << 24));
Eric Laurentcab11242010-07-15 12:50:15 -07002094 chain->setVolume_l(&v, &v);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002095 masterVolume = (float)((v + (1 << 23)) >> 24);
2096 chain.clear();
2097 }
2098
2099 for (size_t i=0 ; i<count ; i++) {
2100 sp<Track> t = activeTracks[i].promote();
2101 if (t == 0) continue;
2102
2103 Track* const track = t.get();
2104 audio_track_cblk_t* cblk = track->cblk();
2105
2106 // The first time a track is added we wait
2107 // for all its buffers to be filled before processing it
2108 mAudioMixer->setActiveTrack(track->name());
Eric Laurenta47b69c2011-11-08 18:10:16 -08002109 // make sure that we have enough frames to mix one full buffer.
2110 // enforce this condition only once to enable draining the buffer in case the client
2111 // app does not call stop() and relies on underrun to stop:
2112 // hence the test on (track->mRetryCount >= kMaxTrackRetries) meaning the track was mixed
2113 // during last round
Eric Laurent3dbe3202011-11-03 12:16:05 -07002114 uint32_t minFrames = 1;
Eric Laurenta47b69c2011-11-08 18:10:16 -08002115 if (!track->isStopped() && !track->isPausing() &&
2116 (track->mRetryCount >= kMaxTrackRetries)) {
Eric Laurent3dbe3202011-11-03 12:16:05 -07002117 if (t->sampleRate() == (int)mSampleRate) {
2118 minFrames = mFrameCount;
2119 } else {
2120 minFrames = (mFrameCount * t->sampleRate()) / mSampleRate + 1;
2121 }
2122 }
2123 if ((cblk->framesReady() >= minFrames) && track->isReady() &&
Mathias Agopian65ab4712010-07-14 17:59:35 -07002124 !track->isPaused() && !track->isTerminated())
2125 {
Steve Block3856b092011-10-20 11:56:00 +01002126 //ALOGV("track %d u=%08x, s=%08x [OK] on thread %p", track->name(), cblk->user, cblk->server, this);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002127
2128 mixedTracks++;
2129
2130 // track->mainBuffer() != mMixBuffer means there is an effect chain
2131 // connected to the track
2132 chain.clear();
2133 if (track->mainBuffer() != mMixBuffer) {
2134 chain = getEffectChain_l(track->sessionId());
2135 // Delegate volume control to effect in track effect chain if needed
2136 if (chain != 0) {
2137 tracksWithEffect++;
2138 } else {
2139 LOGW("prepareTracks_l(): track %08x attached to effect but no chain found on session %d",
2140 track->name(), track->sessionId());
2141 }
2142 }
2143
2144
2145 int param = AudioMixer::VOLUME;
2146 if (track->mFillingUpStatus == Track::FS_FILLED) {
2147 // no ramp for the first volume setting
2148 track->mFillingUpStatus = Track::FS_ACTIVE;
2149 if (track->mState == TrackBase::RESUMING) {
2150 track->mState = TrackBase::ACTIVE;
2151 param = AudioMixer::RAMP_VOLUME;
2152 }
Eric Laurent243f5f92011-02-28 16:52:51 -08002153 mAudioMixer->setParameter(AudioMixer::RESAMPLE, AudioMixer::RESET, NULL);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002154 } else if (cblk->server != 0) {
2155 // If the track is stopped before the first frame was mixed,
2156 // do not apply ramp
2157 param = AudioMixer::RAMP_VOLUME;
2158 }
2159
2160 // compute volume for this track
Eric Laurente0aed6d2010-09-10 17:44:44 -07002161 uint32_t vl, vr, va;
Eric Laurent8569f0d2010-07-29 23:43:43 -07002162 if (track->isMuted() || track->isPausing() ||
Mathias Agopian65ab4712010-07-14 17:59:35 -07002163 mStreamTypes[track->type()].mute) {
Eric Laurente0aed6d2010-09-10 17:44:44 -07002164 vl = vr = va = 0;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002165 if (track->isPausing()) {
2166 track->setPaused();
2167 }
2168 } else {
Eric Laurente0aed6d2010-09-10 17:44:44 -07002169
Mathias Agopian65ab4712010-07-14 17:59:35 -07002170 // read original volumes with volume control
2171 float typeVolume = mStreamTypes[track->type()].volume;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002172 float v = masterVolume * typeVolume;
Eric Laurente0aed6d2010-09-10 17:44:44 -07002173 vl = (uint32_t)(v * cblk->volume[0]) << 12;
2174 vr = (uint32_t)(v * cblk->volume[1]) << 12;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002175
Eric Laurente0aed6d2010-09-10 17:44:44 -07002176 va = (uint32_t)(v * cblk->sendLevel);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002177 }
Eric Laurente0aed6d2010-09-10 17:44:44 -07002178 // Delegate volume control to effect in track effect chain if needed
2179 if (chain != 0 && chain->setVolume_l(&vl, &vr)) {
2180 // Do not ramp volume if volume is controlled by effect
2181 param = AudioMixer::VOLUME;
2182 track->mHasVolumeController = true;
2183 } else {
2184 // force no volume ramp when volume controller was just disabled or removed
2185 // from effect chain to avoid volume spike
2186 if (track->mHasVolumeController) {
2187 param = AudioMixer::VOLUME;
2188 }
2189 track->mHasVolumeController = false;
2190 }
2191
2192 // Convert volumes from 8.24 to 4.12 format
2193 int16_t left, right, aux;
2194 uint32_t v_clamped = (vl + (1 << 11)) >> 12;
2195 if (v_clamped > MAX_GAIN_INT) v_clamped = MAX_GAIN_INT;
2196 left = int16_t(v_clamped);
2197 v_clamped = (vr + (1 << 11)) >> 12;
2198 if (v_clamped > MAX_GAIN_INT) v_clamped = MAX_GAIN_INT;
2199 right = int16_t(v_clamped);
2200
2201 if (va > MAX_GAIN_INT) va = MAX_GAIN_INT;
2202 aux = int16_t(va);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002203
Mathias Agopian65ab4712010-07-14 17:59:35 -07002204 // XXX: these things DON'T need to be done each time
2205 mAudioMixer->setBufferProvider(track);
2206 mAudioMixer->enable(AudioMixer::MIXING);
2207
2208 mAudioMixer->setParameter(param, AudioMixer::VOLUME0, (void *)left);
2209 mAudioMixer->setParameter(param, AudioMixer::VOLUME1, (void *)right);
2210 mAudioMixer->setParameter(param, AudioMixer::AUXLEVEL, (void *)aux);
2211 mAudioMixer->setParameter(
2212 AudioMixer::TRACK,
2213 AudioMixer::FORMAT, (void *)track->format());
2214 mAudioMixer->setParameter(
2215 AudioMixer::TRACK,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07002216 AudioMixer::CHANNEL_MASK, (void *)track->channelMask());
Mathias Agopian65ab4712010-07-14 17:59:35 -07002217 mAudioMixer->setParameter(
2218 AudioMixer::RESAMPLE,
2219 AudioMixer::SAMPLE_RATE,
2220 (void *)(cblk->sampleRate));
2221 mAudioMixer->setParameter(
2222 AudioMixer::TRACK,
2223 AudioMixer::MAIN_BUFFER, (void *)track->mainBuffer());
2224 mAudioMixer->setParameter(
2225 AudioMixer::TRACK,
2226 AudioMixer::AUX_BUFFER, (void *)track->auxBuffer());
2227
2228 // reset retry count
2229 track->mRetryCount = kMaxTrackRetries;
2230 mixerStatus = MIXER_TRACKS_READY;
2231 } else {
Steve Block3856b092011-10-20 11:56:00 +01002232 //ALOGV("track %d u=%08x, s=%08x [NOT READY] on thread %p", track->name(), cblk->user, cblk->server, this);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002233 if (track->isStopped()) {
2234 track->reset();
2235 }
2236 if (track->isTerminated() || track->isStopped() || track->isPaused()) {
2237 // We have consumed all the buffers of this track.
2238 // Remove it from the list of active tracks.
2239 tracksToRemove->add(track);
2240 } else {
2241 // No buffers for this track. Give it a few chances to
2242 // fill a buffer, then remove it from active list.
2243 if (--(track->mRetryCount) <= 0) {
Steve Block3856b092011-10-20 11:56:00 +01002244 ALOGV("BUFFER TIMEOUT: remove(%d) from active list on thread %p", track->name(), this);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002245 tracksToRemove->add(track);
Eric Laurent44d98482010-09-30 16:12:31 -07002246 // indicate to client process that the track was disabled because of underrun
Eric Laurent38ccae22011-03-28 18:37:07 -07002247 android_atomic_or(CBLK_DISABLED_ON, &cblk->flags);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002248 } else if (mixerStatus != MIXER_TRACKS_READY) {
2249 mixerStatus = MIXER_TRACKS_ENABLED;
2250 }
2251 }
2252 mAudioMixer->disable(AudioMixer::MIXING);
2253 }
2254 }
2255
2256 // remove all the tracks that need to be...
2257 count = tracksToRemove->size();
2258 if (UNLIKELY(count)) {
2259 for (size_t i=0 ; i<count ; i++) {
2260 const sp<Track>& track = tracksToRemove->itemAt(i);
2261 mActiveTracks.remove(track);
2262 if (track->mainBuffer() != mMixBuffer) {
2263 chain = getEffectChain_l(track->sessionId());
2264 if (chain != 0) {
Steve Block3856b092011-10-20 11:56:00 +01002265 ALOGV("stopping track on chain %p for session Id: %d", chain.get(), track->sessionId());
Eric Laurentb469b942011-05-09 12:09:06 -07002266 chain->decActiveTrackCnt();
Mathias Agopian65ab4712010-07-14 17:59:35 -07002267 }
2268 }
2269 if (track->isTerminated()) {
Eric Laurentb469b942011-05-09 12:09:06 -07002270 removeTrack_l(track);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002271 }
2272 }
2273 }
2274
2275 // mix buffer must be cleared if all tracks are connected to an
2276 // effect chain as in this case the mixer will not write to
2277 // mix buffer and track effects will accumulate into it
2278 if (mixedTracks != 0 && mixedTracks == tracksWithEffect) {
2279 memset(mMixBuffer, 0, mFrameCount * mChannelCount * sizeof(int16_t));
2280 }
2281
2282 return mixerStatus;
2283}
2284
2285void AudioFlinger::MixerThread::invalidateTracks(int streamType)
2286{
Steve Block3856b092011-10-20 11:56:00 +01002287 ALOGV ("MixerThread::invalidateTracks() mixer %p, streamType %d, mTracks.size %d",
Eric Laurentde070132010-07-13 04:45:46 -07002288 this, streamType, mTracks.size());
Mathias Agopian65ab4712010-07-14 17:59:35 -07002289 Mutex::Autolock _l(mLock);
Eric Laurentde070132010-07-13 04:45:46 -07002290
Mathias Agopian65ab4712010-07-14 17:59:35 -07002291 size_t size = mTracks.size();
2292 for (size_t i = 0; i < size; i++) {
2293 sp<Track> t = mTracks[i];
2294 if (t->type() == streamType) {
Eric Laurent38ccae22011-03-28 18:37:07 -07002295 android_atomic_or(CBLK_INVALID_ON, &t->mCblk->flags);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002296 t->mCblk->cv.signal();
Mathias Agopian65ab4712010-07-14 17:59:35 -07002297 }
2298 }
2299}
2300
Eric Laurent9f6530f2011-08-30 10:18:54 -07002301void AudioFlinger::PlaybackThread::setStreamValid(int streamType, bool valid)
2302{
Steve Block3856b092011-10-20 11:56:00 +01002303 ALOGV ("PlaybackThread::setStreamValid() thread %p, streamType %d, valid %d",
Eric Laurent9f6530f2011-08-30 10:18:54 -07002304 this, streamType, valid);
2305 Mutex::Autolock _l(mLock);
2306
2307 mStreamTypes[streamType].valid = valid;
2308}
Mathias Agopian65ab4712010-07-14 17:59:35 -07002309
2310// getTrackName_l() must be called with ThreadBase::mLock held
2311int AudioFlinger::MixerThread::getTrackName_l()
2312{
2313 return mAudioMixer->getTrackName();
2314}
2315
2316// deleteTrackName_l() must be called with ThreadBase::mLock held
2317void AudioFlinger::MixerThread::deleteTrackName_l(int name)
2318{
Steve Block3856b092011-10-20 11:56:00 +01002319 ALOGV("remove track (%d) and delete from mixer", name);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002320 mAudioMixer->deleteTrackName(name);
2321}
2322
2323// checkForNewParameters_l() must be called with ThreadBase::mLock held
2324bool AudioFlinger::MixerThread::checkForNewParameters_l()
2325{
2326 bool reconfig = false;
2327
2328 while (!mNewParameters.isEmpty()) {
2329 status_t status = NO_ERROR;
2330 String8 keyValuePair = mNewParameters[0];
2331 AudioParameter param = AudioParameter(keyValuePair);
2332 int value;
2333
2334 if (param.getInt(String8(AudioParameter::keySamplingRate), value) == NO_ERROR) {
2335 reconfig = true;
2336 }
2337 if (param.getInt(String8(AudioParameter::keyFormat), value) == NO_ERROR) {
Dima Zavinfce7a472011-04-19 22:30:36 -07002338 if (value != AUDIO_FORMAT_PCM_16_BIT) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07002339 status = BAD_VALUE;
2340 } else {
2341 reconfig = true;
2342 }
2343 }
2344 if (param.getInt(String8(AudioParameter::keyChannels), value) == NO_ERROR) {
Dima Zavinfce7a472011-04-19 22:30:36 -07002345 if (value != AUDIO_CHANNEL_OUT_STEREO) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07002346 status = BAD_VALUE;
2347 } else {
2348 reconfig = true;
2349 }
2350 }
2351 if (param.getInt(String8(AudioParameter::keyFrameCount), value) == NO_ERROR) {
2352 // do not accept frame count changes if tracks are open as the track buffer
Glenn Kasten362c4e62011-12-14 10:28:06 -08002353 // size depends on frame count and correct behavior would not be guaranteed
Mathias Agopian65ab4712010-07-14 17:59:35 -07002354 // if frame count is changed after track creation
2355 if (!mTracks.isEmpty()) {
2356 status = INVALID_OPERATION;
2357 } else {
2358 reconfig = true;
2359 }
2360 }
2361 if (param.getInt(String8(AudioParameter::keyRouting), value) == NO_ERROR) {
Gloria Wang9ee159b2011-02-24 14:51:45 -08002362 // when changing the audio output device, call addBatteryData to notify
2363 // the change
Eric Laurentb469b942011-05-09 12:09:06 -07002364 if ((int)mDevice != value) {
Gloria Wang9ee159b2011-02-24 14:51:45 -08002365 uint32_t params = 0;
2366 // check whether speaker is on
Dima Zavinfce7a472011-04-19 22:30:36 -07002367 if (value & AUDIO_DEVICE_OUT_SPEAKER) {
Gloria Wang9ee159b2011-02-24 14:51:45 -08002368 params |= IMediaPlayerService::kBatteryDataSpeakerOn;
2369 }
2370
2371 int deviceWithoutSpeaker
Dima Zavinfce7a472011-04-19 22:30:36 -07002372 = AUDIO_DEVICE_OUT_ALL & ~AUDIO_DEVICE_OUT_SPEAKER;
Gloria Wang9ee159b2011-02-24 14:51:45 -08002373 // check if any other device (except speaker) is on
2374 if (value & deviceWithoutSpeaker ) {
2375 params |= IMediaPlayerService::kBatteryDataOtherAudioDeviceOn;
2376 }
2377
2378 if (params != 0) {
2379 addBatteryData(params);
2380 }
2381 }
2382
Mathias Agopian65ab4712010-07-14 17:59:35 -07002383 // forward device change to effects that have requested to be
2384 // aware of attached audio device.
2385 mDevice = (uint32_t)value;
2386 for (size_t i = 0; i < mEffectChains.size(); i++) {
Eric Laurentcab11242010-07-15 12:50:15 -07002387 mEffectChains[i]->setDevice_l(mDevice);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002388 }
2389 }
2390
2391 if (status == NO_ERROR) {
Dima Zavin799a70e2011-04-18 16:57:27 -07002392 status = mOutput->stream->common.set_parameters(&mOutput->stream->common,
Dima Zavinfce7a472011-04-19 22:30:36 -07002393 keyValuePair.string());
Mathias Agopian65ab4712010-07-14 17:59:35 -07002394 if (!mStandby && status == INVALID_OPERATION) {
Dima Zavin799a70e2011-04-18 16:57:27 -07002395 mOutput->stream->common.standby(&mOutput->stream->common);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002396 mStandby = true;
2397 mBytesWritten = 0;
Dima Zavin799a70e2011-04-18 16:57:27 -07002398 status = mOutput->stream->common.set_parameters(&mOutput->stream->common,
Dima Zavinfce7a472011-04-19 22:30:36 -07002399 keyValuePair.string());
Mathias Agopian65ab4712010-07-14 17:59:35 -07002400 }
2401 if (status == NO_ERROR && reconfig) {
2402 delete mAudioMixer;
2403 readOutputParameters();
2404 mAudioMixer = new AudioMixer(mFrameCount, mSampleRate);
2405 for (size_t i = 0; i < mTracks.size() ; i++) {
2406 int name = getTrackName_l();
2407 if (name < 0) break;
2408 mTracks[i]->mName = name;
2409 // limit track sample rate to 2 x new output sample rate
2410 if (mTracks[i]->mCblk->sampleRate > 2 * sampleRate()) {
2411 mTracks[i]->mCblk->sampleRate = 2 * sampleRate();
2412 }
2413 }
2414 sendConfigEvent_l(AudioSystem::OUTPUT_CONFIG_CHANGED);
2415 }
2416 }
2417
2418 mNewParameters.removeAt(0);
2419
2420 mParamStatus = status;
2421 mParamCond.signal();
Eric Laurent60cd0a02011-09-13 11:40:21 -07002422 // wait for condition with time out in case the thread calling ThreadBase::setParameters()
2423 // already timed out waiting for the status and will never signal the condition.
Glenn Kasten7dede872011-12-13 11:04:14 -08002424 mWaitWorkCV.waitRelative(mLock, kSetParametersTimeoutNs);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002425 }
2426 return reconfig;
2427}
2428
2429status_t AudioFlinger::MixerThread::dumpInternals(int fd, const Vector<String16>& args)
2430{
2431 const size_t SIZE = 256;
2432 char buffer[SIZE];
2433 String8 result;
2434
2435 PlaybackThread::dumpInternals(fd, args);
2436
2437 snprintf(buffer, SIZE, "AudioMixer tracks: %08x\n", mAudioMixer->trackNames());
2438 result.append(buffer);
2439 write(fd, result.string(), result.size());
2440 return NO_ERROR;
2441}
2442
Mathias Agopian65ab4712010-07-14 17:59:35 -07002443uint32_t AudioFlinger::MixerThread::idleSleepTimeUs()
2444{
Eric Laurent60e18242010-07-29 06:50:24 -07002445 return (uint32_t)(((mFrameCount * 1000) / mSampleRate) * 1000) / 2;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002446}
2447
Eric Laurent25cbe0e2010-08-18 18:13:17 -07002448uint32_t AudioFlinger::MixerThread::suspendSleepTimeUs()
2449{
2450 return (uint32_t)(((mFrameCount * 1000) / mSampleRate) * 1000);
2451}
2452
Mathias Agopian65ab4712010-07-14 17:59:35 -07002453// ----------------------------------------------------------------------------
Dima Zavin799a70e2011-04-18 16:57:27 -07002454AudioFlinger::DirectOutputThread::DirectOutputThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id, uint32_t device)
Mathias Agopian65ab4712010-07-14 17:59:35 -07002455 : PlaybackThread(audioFlinger, output, id, device)
2456{
Eric Laurent7c7f10b2011-06-17 21:29:58 -07002457 mType = ThreadBase::DIRECT;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002458}
2459
2460AudioFlinger::DirectOutputThread::~DirectOutputThread()
2461{
2462}
2463
2464
2465static inline int16_t clamp16(int32_t sample)
2466{
2467 if ((sample>>15) ^ (sample>>31))
2468 sample = 0x7FFF ^ (sample>>31);
2469 return sample;
2470}
2471
2472static inline
2473int32_t mul(int16_t in, int16_t v)
2474{
2475#if defined(__arm__) && !defined(__thumb__)
2476 int32_t out;
2477 asm( "smulbb %[out], %[in], %[v] \n"
2478 : [out]"=r"(out)
2479 : [in]"%r"(in), [v]"r"(v)
2480 : );
2481 return out;
2482#else
2483 return in * int32_t(v);
2484#endif
2485}
2486
2487void AudioFlinger::DirectOutputThread::applyVolume(uint16_t leftVol, uint16_t rightVol, bool ramp)
2488{
2489 // Do not apply volume on compressed audio
Dima Zavinfce7a472011-04-19 22:30:36 -07002490 if (!audio_is_linear_pcm(mFormat)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07002491 return;
2492 }
2493
2494 // convert to signed 16 bit before volume calculation
Dima Zavinfce7a472011-04-19 22:30:36 -07002495 if (mFormat == AUDIO_FORMAT_PCM_8_BIT) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07002496 size_t count = mFrameCount * mChannelCount;
2497 uint8_t *src = (uint8_t *)mMixBuffer + count-1;
2498 int16_t *dst = mMixBuffer + count-1;
2499 while(count--) {
2500 *dst-- = (int16_t)(*src--^0x80) << 8;
2501 }
2502 }
2503
2504 size_t frameCount = mFrameCount;
2505 int16_t *out = mMixBuffer;
2506 if (ramp) {
2507 if (mChannelCount == 1) {
2508 int32_t d = ((int32_t)leftVol - (int32_t)mLeftVolShort) << 16;
2509 int32_t vlInc = d / (int32_t)frameCount;
2510 int32_t vl = ((int32_t)mLeftVolShort << 16);
2511 do {
2512 out[0] = clamp16(mul(out[0], vl >> 16) >> 12);
2513 out++;
2514 vl += vlInc;
2515 } while (--frameCount);
2516
2517 } else {
2518 int32_t d = ((int32_t)leftVol - (int32_t)mLeftVolShort) << 16;
2519 int32_t vlInc = d / (int32_t)frameCount;
2520 d = ((int32_t)rightVol - (int32_t)mRightVolShort) << 16;
2521 int32_t vrInc = d / (int32_t)frameCount;
2522 int32_t vl = ((int32_t)mLeftVolShort << 16);
2523 int32_t vr = ((int32_t)mRightVolShort << 16);
2524 do {
2525 out[0] = clamp16(mul(out[0], vl >> 16) >> 12);
2526 out[1] = clamp16(mul(out[1], vr >> 16) >> 12);
2527 out += 2;
2528 vl += vlInc;
2529 vr += vrInc;
2530 } while (--frameCount);
2531 }
2532 } else {
2533 if (mChannelCount == 1) {
2534 do {
2535 out[0] = clamp16(mul(out[0], leftVol) >> 12);
2536 out++;
2537 } while (--frameCount);
2538 } else {
2539 do {
2540 out[0] = clamp16(mul(out[0], leftVol) >> 12);
2541 out[1] = clamp16(mul(out[1], rightVol) >> 12);
2542 out += 2;
2543 } while (--frameCount);
2544 }
2545 }
2546
2547 // convert back to unsigned 8 bit after volume calculation
Dima Zavinfce7a472011-04-19 22:30:36 -07002548 if (mFormat == AUDIO_FORMAT_PCM_8_BIT) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07002549 size_t count = mFrameCount * mChannelCount;
2550 int16_t *src = mMixBuffer;
2551 uint8_t *dst = (uint8_t *)mMixBuffer;
2552 while(count--) {
2553 *dst++ = (uint8_t)(((int32_t)*src++ + (1<<7)) >> 8)^0x80;
2554 }
2555 }
2556
2557 mLeftVolShort = leftVol;
2558 mRightVolShort = rightVol;
2559}
2560
2561bool AudioFlinger::DirectOutputThread::threadLoop()
2562{
2563 uint32_t mixerStatus = MIXER_IDLE;
2564 sp<Track> trackToRemove;
2565 sp<Track> activeTrack;
2566 nsecs_t standbyTime = systemTime();
2567 int8_t *curBuf;
2568 size_t mixBufferSize = mFrameCount*mFrameSize;
2569 uint32_t activeSleepTime = activeSleepTimeUs();
2570 uint32_t idleSleepTime = idleSleepTimeUs();
2571 uint32_t sleepTime = idleSleepTime;
2572 // use shorter standby delay as on normal output to release
2573 // hardware resources as soon as possible
2574 nsecs_t standbyDelay = microseconds(activeSleepTime*2);
2575
Eric Laurentfeb0db62011-07-22 09:04:31 -07002576 acquireWakeLock();
2577
Mathias Agopian65ab4712010-07-14 17:59:35 -07002578 while (!exitPending())
2579 {
2580 bool rampVolume;
2581 uint16_t leftVol;
2582 uint16_t rightVol;
2583 Vector< sp<EffectChain> > effectChains;
2584
2585 processConfigEvents();
2586
2587 mixerStatus = MIXER_IDLE;
2588
2589 { // scope for the mLock
2590
2591 Mutex::Autolock _l(mLock);
2592
2593 if (checkForNewParameters_l()) {
2594 mixBufferSize = mFrameCount*mFrameSize;
2595 activeSleepTime = activeSleepTimeUs();
2596 idleSleepTime = idleSleepTimeUs();
2597 standbyDelay = microseconds(activeSleepTime*2);
2598 }
2599
2600 // put audio hardware into standby after short delay
2601 if UNLIKELY((!mActiveTracks.size() && systemTime() > standbyTime) ||
2602 mSuspended) {
2603 // wait until we have something to do...
2604 if (!mStandby) {
Steve Block3856b092011-10-20 11:56:00 +01002605 ALOGV("Audio hardware entering standby, mixer %p\n", this);
Dima Zavin799a70e2011-04-18 16:57:27 -07002606 mOutput->stream->common.standby(&mOutput->stream->common);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002607 mStandby = true;
2608 mBytesWritten = 0;
2609 }
2610
2611 if (!mActiveTracks.size() && mConfigEvents.isEmpty()) {
2612 // we're about to wait, flush the binder command buffer
2613 IPCThreadState::self()->flushCommands();
2614
2615 if (exitPending()) break;
2616
Eric Laurentfeb0db62011-07-22 09:04:31 -07002617 releaseWakeLock_l();
Steve Block3856b092011-10-20 11:56:00 +01002618 ALOGV("DirectOutputThread %p TID %d going to sleep\n", this, gettid());
Mathias Agopian65ab4712010-07-14 17:59:35 -07002619 mWaitWorkCV.wait(mLock);
Steve Block3856b092011-10-20 11:56:00 +01002620 ALOGV("DirectOutputThread %p TID %d waking up in active mode\n", this, gettid());
Eric Laurentfeb0db62011-07-22 09:04:31 -07002621 acquireWakeLock_l();
Mathias Agopian65ab4712010-07-14 17:59:35 -07002622
2623 if (mMasterMute == false) {
2624 char value[PROPERTY_VALUE_MAX];
2625 property_get("ro.audio.silent", value, "0");
2626 if (atoi(value)) {
2627 LOGD("Silence is golden");
2628 setMasterMute(true);
2629 }
2630 }
2631
2632 standbyTime = systemTime() + standbyDelay;
2633 sleepTime = idleSleepTime;
2634 continue;
2635 }
2636 }
2637
2638 effectChains = mEffectChains;
2639
2640 // find out which tracks need to be processed
2641 if (mActiveTracks.size() != 0) {
2642 sp<Track> t = mActiveTracks[0].promote();
2643 if (t == 0) continue;
2644
2645 Track* const track = t.get();
2646 audio_track_cblk_t* cblk = track->cblk();
2647
2648 // The first time a track is added we wait
2649 // for all its buffers to be filled before processing it
Eric Laurentaf59ce22010-10-05 14:41:42 -07002650 if (cblk->framesReady() && track->isReady() &&
Mathias Agopian65ab4712010-07-14 17:59:35 -07002651 !track->isPaused() && !track->isTerminated())
2652 {
Steve Block3856b092011-10-20 11:56:00 +01002653 //ALOGV("track %d u=%08x, s=%08x [OK]", track->name(), cblk->user, cblk->server);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002654
2655 if (track->mFillingUpStatus == Track::FS_FILLED) {
2656 track->mFillingUpStatus = Track::FS_ACTIVE;
2657 mLeftVolFloat = mRightVolFloat = 0;
2658 mLeftVolShort = mRightVolShort = 0;
2659 if (track->mState == TrackBase::RESUMING) {
2660 track->mState = TrackBase::ACTIVE;
2661 rampVolume = true;
2662 }
2663 } else if (cblk->server != 0) {
2664 // If the track is stopped before the first frame was mixed,
2665 // do not apply ramp
2666 rampVolume = true;
2667 }
2668 // compute volume for this track
2669 float left, right;
2670 if (track->isMuted() || mMasterMute || track->isPausing() ||
2671 mStreamTypes[track->type()].mute) {
2672 left = right = 0;
2673 if (track->isPausing()) {
2674 track->setPaused();
2675 }
2676 } else {
2677 float typeVolume = mStreamTypes[track->type()].volume;
2678 float v = mMasterVolume * typeVolume;
2679 float v_clamped = v * cblk->volume[0];
2680 if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN;
2681 left = v_clamped/MAX_GAIN;
2682 v_clamped = v * cblk->volume[1];
2683 if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN;
2684 right = v_clamped/MAX_GAIN;
2685 }
2686
2687 if (left != mLeftVolFloat || right != mRightVolFloat) {
2688 mLeftVolFloat = left;
2689 mRightVolFloat = right;
2690
2691 // If audio HAL implements volume control,
2692 // force software volume to nominal value
Dima Zavin799a70e2011-04-18 16:57:27 -07002693 if (mOutput->stream->set_volume(mOutput->stream, left, right) == NO_ERROR) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07002694 left = 1.0f;
2695 right = 1.0f;
2696 }
2697
2698 // Convert volumes from float to 8.24
2699 uint32_t vl = (uint32_t)(left * (1 << 24));
2700 uint32_t vr = (uint32_t)(right * (1 << 24));
2701
2702 // Delegate volume control to effect in track effect chain if needed
2703 // only one effect chain can be present on DirectOutputThread, so if
2704 // there is one, the track is connected to it
2705 if (!effectChains.isEmpty()) {
Eric Laurente0aed6d2010-09-10 17:44:44 -07002706 // Do not ramp volume if volume is controlled by effect
Eric Laurentcab11242010-07-15 12:50:15 -07002707 if(effectChains[0]->setVolume_l(&vl, &vr)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07002708 rampVolume = false;
2709 }
2710 }
2711
2712 // Convert volumes from 8.24 to 4.12 format
2713 uint32_t v_clamped = (vl + (1 << 11)) >> 12;
2714 if (v_clamped > MAX_GAIN_INT) v_clamped = MAX_GAIN_INT;
2715 leftVol = (uint16_t)v_clamped;
2716 v_clamped = (vr + (1 << 11)) >> 12;
2717 if (v_clamped > MAX_GAIN_INT) v_clamped = MAX_GAIN_INT;
2718 rightVol = (uint16_t)v_clamped;
2719 } else {
2720 leftVol = mLeftVolShort;
2721 rightVol = mRightVolShort;
2722 rampVolume = false;
2723 }
2724
2725 // reset retry count
2726 track->mRetryCount = kMaxTrackRetriesDirect;
2727 activeTrack = t;
2728 mixerStatus = MIXER_TRACKS_READY;
2729 } else {
Steve Block3856b092011-10-20 11:56:00 +01002730 //ALOGV("track %d u=%08x, s=%08x [NOT READY]", track->name(), cblk->user, cblk->server);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002731 if (track->isStopped()) {
2732 track->reset();
2733 }
2734 if (track->isTerminated() || track->isStopped() || track->isPaused()) {
2735 // We have consumed all the buffers of this track.
2736 // Remove it from the list of active tracks.
2737 trackToRemove = track;
2738 } else {
2739 // No buffers for this track. Give it a few chances to
2740 // fill a buffer, then remove it from active list.
2741 if (--(track->mRetryCount) <= 0) {
Steve Block3856b092011-10-20 11:56:00 +01002742 ALOGV("BUFFER TIMEOUT: remove(%d) from active list", track->name());
Mathias Agopian65ab4712010-07-14 17:59:35 -07002743 trackToRemove = track;
2744 } else {
2745 mixerStatus = MIXER_TRACKS_ENABLED;
2746 }
2747 }
2748 }
2749 }
2750
2751 // remove all the tracks that need to be...
2752 if (UNLIKELY(trackToRemove != 0)) {
2753 mActiveTracks.remove(trackToRemove);
2754 if (!effectChains.isEmpty()) {
Steve Block3856b092011-10-20 11:56:00 +01002755 ALOGV("stopping track on chain %p for session Id: %d", effectChains[0].get(),
Eric Laurentde070132010-07-13 04:45:46 -07002756 trackToRemove->sessionId());
Eric Laurentb469b942011-05-09 12:09:06 -07002757 effectChains[0]->decActiveTrackCnt();
Mathias Agopian65ab4712010-07-14 17:59:35 -07002758 }
2759 if (trackToRemove->isTerminated()) {
Eric Laurentb469b942011-05-09 12:09:06 -07002760 removeTrack_l(trackToRemove);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002761 }
2762 }
2763
Eric Laurentde070132010-07-13 04:45:46 -07002764 lockEffectChains_l(effectChains);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002765 }
2766
2767 if (LIKELY(mixerStatus == MIXER_TRACKS_READY)) {
2768 AudioBufferProvider::Buffer buffer;
2769 size_t frameCount = mFrameCount;
2770 curBuf = (int8_t *)mMixBuffer;
2771 // output audio to hardware
2772 while (frameCount) {
2773 buffer.frameCount = frameCount;
2774 activeTrack->getNextBuffer(&buffer);
2775 if (UNLIKELY(buffer.raw == 0)) {
2776 memset(curBuf, 0, frameCount * mFrameSize);
2777 break;
2778 }
2779 memcpy(curBuf, buffer.raw, buffer.frameCount * mFrameSize);
2780 frameCount -= buffer.frameCount;
2781 curBuf += buffer.frameCount * mFrameSize;
2782 activeTrack->releaseBuffer(&buffer);
2783 }
2784 sleepTime = 0;
2785 standbyTime = systemTime() + standbyDelay;
2786 } else {
2787 if (sleepTime == 0) {
2788 if (mixerStatus == MIXER_TRACKS_ENABLED) {
2789 sleepTime = activeSleepTime;
2790 } else {
2791 sleepTime = idleSleepTime;
2792 }
Dima Zavinfce7a472011-04-19 22:30:36 -07002793 } else if (mBytesWritten != 0 && audio_is_linear_pcm(mFormat)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07002794 memset (mMixBuffer, 0, mFrameCount * mFrameSize);
2795 sleepTime = 0;
2796 }
2797 }
2798
2799 if (mSuspended) {
Eric Laurent25cbe0e2010-08-18 18:13:17 -07002800 sleepTime = suspendSleepTimeUs();
Mathias Agopian65ab4712010-07-14 17:59:35 -07002801 }
2802 // sleepTime == 0 means we must write to audio hardware
2803 if (sleepTime == 0) {
2804 if (mixerStatus == MIXER_TRACKS_READY) {
2805 applyVolume(leftVol, rightVol, rampVolume);
2806 }
2807 for (size_t i = 0; i < effectChains.size(); i ++) {
2808 effectChains[i]->process_l();
2809 }
Eric Laurentde070132010-07-13 04:45:46 -07002810 unlockEffectChains(effectChains);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002811
2812 mLastWriteTime = systemTime();
2813 mInWrite = true;
2814 mBytesWritten += mixBufferSize;
Dima Zavin799a70e2011-04-18 16:57:27 -07002815 int bytesWritten = (int)mOutput->stream->write(mOutput->stream, mMixBuffer, mixBufferSize);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002816 if (bytesWritten < 0) mBytesWritten -= mixBufferSize;
2817 mNumWrites++;
2818 mInWrite = false;
2819 mStandby = false;
2820 } else {
Eric Laurentde070132010-07-13 04:45:46 -07002821 unlockEffectChains(effectChains);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002822 usleep(sleepTime);
2823 }
2824
2825 // finally let go of removed track, without the lock held
2826 // since we can't guarantee the destructors won't acquire that
2827 // same lock.
2828 trackToRemove.clear();
2829 activeTrack.clear();
2830
2831 // Effect chains will be actually deleted here if they were removed from
2832 // mEffectChains list during mixing or effects processing
2833 effectChains.clear();
2834 }
2835
2836 if (!mStandby) {
Dima Zavin799a70e2011-04-18 16:57:27 -07002837 mOutput->stream->common.standby(&mOutput->stream->common);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002838 }
2839
Eric Laurentfeb0db62011-07-22 09:04:31 -07002840 releaseWakeLock();
2841
Steve Block3856b092011-10-20 11:56:00 +01002842 ALOGV("DirectOutputThread %p exiting", this);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002843 return false;
2844}
2845
2846// getTrackName_l() must be called with ThreadBase::mLock held
2847int AudioFlinger::DirectOutputThread::getTrackName_l()
2848{
2849 return 0;
2850}
2851
2852// deleteTrackName_l() must be called with ThreadBase::mLock held
2853void AudioFlinger::DirectOutputThread::deleteTrackName_l(int name)
2854{
2855}
2856
2857// checkForNewParameters_l() must be called with ThreadBase::mLock held
2858bool AudioFlinger::DirectOutputThread::checkForNewParameters_l()
2859{
2860 bool reconfig = false;
2861
2862 while (!mNewParameters.isEmpty()) {
2863 status_t status = NO_ERROR;
2864 String8 keyValuePair = mNewParameters[0];
2865 AudioParameter param = AudioParameter(keyValuePair);
2866 int value;
2867
2868 if (param.getInt(String8(AudioParameter::keyFrameCount), value) == NO_ERROR) {
2869 // do not accept frame count changes if tracks are open as the track buffer
2870 // size depends on frame count and correct behavior would not be garantied
2871 // if frame count is changed after track creation
2872 if (!mTracks.isEmpty()) {
2873 status = INVALID_OPERATION;
2874 } else {
2875 reconfig = true;
2876 }
2877 }
2878 if (status == NO_ERROR) {
Dima Zavin799a70e2011-04-18 16:57:27 -07002879 status = mOutput->stream->common.set_parameters(&mOutput->stream->common,
Dima Zavinfce7a472011-04-19 22:30:36 -07002880 keyValuePair.string());
Mathias Agopian65ab4712010-07-14 17:59:35 -07002881 if (!mStandby && status == INVALID_OPERATION) {
Dima Zavin799a70e2011-04-18 16:57:27 -07002882 mOutput->stream->common.standby(&mOutput->stream->common);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002883 mStandby = true;
2884 mBytesWritten = 0;
Dima Zavin799a70e2011-04-18 16:57:27 -07002885 status = mOutput->stream->common.set_parameters(&mOutput->stream->common,
Dima Zavinfce7a472011-04-19 22:30:36 -07002886 keyValuePair.string());
Mathias Agopian65ab4712010-07-14 17:59:35 -07002887 }
2888 if (status == NO_ERROR && reconfig) {
2889 readOutputParameters();
2890 sendConfigEvent_l(AudioSystem::OUTPUT_CONFIG_CHANGED);
2891 }
2892 }
2893
2894 mNewParameters.removeAt(0);
2895
2896 mParamStatus = status;
2897 mParamCond.signal();
Eric Laurent60cd0a02011-09-13 11:40:21 -07002898 // wait for condition with time out in case the thread calling ThreadBase::setParameters()
2899 // already timed out waiting for the status and will never signal the condition.
Glenn Kasten7dede872011-12-13 11:04:14 -08002900 mWaitWorkCV.waitRelative(mLock, kSetParametersTimeoutNs);
Mathias Agopian65ab4712010-07-14 17:59:35 -07002901 }
2902 return reconfig;
2903}
2904
2905uint32_t AudioFlinger::DirectOutputThread::activeSleepTimeUs()
2906{
2907 uint32_t time;
Dima Zavinfce7a472011-04-19 22:30:36 -07002908 if (audio_is_linear_pcm(mFormat)) {
Eric Laurent162b40b2011-12-05 09:47:19 -08002909 time = PlaybackThread::activeSleepTimeUs();
Mathias Agopian65ab4712010-07-14 17:59:35 -07002910 } else {
2911 time = 10000;
2912 }
2913 return time;
2914}
2915
2916uint32_t AudioFlinger::DirectOutputThread::idleSleepTimeUs()
2917{
2918 uint32_t time;
Dima Zavinfce7a472011-04-19 22:30:36 -07002919 if (audio_is_linear_pcm(mFormat)) {
Eric Laurent60e18242010-07-29 06:50:24 -07002920 time = (uint32_t)(((mFrameCount * 1000) / mSampleRate) * 1000) / 2;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002921 } else {
2922 time = 10000;
2923 }
2924 return time;
2925}
2926
Eric Laurent25cbe0e2010-08-18 18:13:17 -07002927uint32_t AudioFlinger::DirectOutputThread::suspendSleepTimeUs()
2928{
2929 uint32_t time;
Dima Zavinfce7a472011-04-19 22:30:36 -07002930 if (audio_is_linear_pcm(mFormat)) {
Eric Laurent25cbe0e2010-08-18 18:13:17 -07002931 time = (uint32_t)(((mFrameCount * 1000) / mSampleRate) * 1000);
2932 } else {
2933 time = 10000;
2934 }
2935 return time;
2936}
2937
2938
Mathias Agopian65ab4712010-07-14 17:59:35 -07002939// ----------------------------------------------------------------------------
2940
2941AudioFlinger::DuplicatingThread::DuplicatingThread(const sp<AudioFlinger>& audioFlinger, AudioFlinger::MixerThread* mainThread, int id)
2942 : MixerThread(audioFlinger, mainThread->getOutput(), id, mainThread->device()), mWaitTimeMs(UINT_MAX)
2943{
Eric Laurent7c7f10b2011-06-17 21:29:58 -07002944 mType = ThreadBase::DUPLICATING;
Mathias Agopian65ab4712010-07-14 17:59:35 -07002945 addOutputTrack(mainThread);
2946}
2947
2948AudioFlinger::DuplicatingThread::~DuplicatingThread()
2949{
2950 for (size_t i = 0; i < mOutputTracks.size(); i++) {
2951 mOutputTracks[i]->destroy();
2952 }
2953 mOutputTracks.clear();
2954}
2955
2956bool AudioFlinger::DuplicatingThread::threadLoop()
2957{
2958 Vector< sp<Track> > tracksToRemove;
2959 uint32_t mixerStatus = MIXER_IDLE;
2960 nsecs_t standbyTime = systemTime();
2961 size_t mixBufferSize = mFrameCount*mFrameSize;
2962 SortedVector< sp<OutputTrack> > outputTracks;
2963 uint32_t writeFrames = 0;
2964 uint32_t activeSleepTime = activeSleepTimeUs();
2965 uint32_t idleSleepTime = idleSleepTimeUs();
2966 uint32_t sleepTime = idleSleepTime;
2967 Vector< sp<EffectChain> > effectChains;
2968
Eric Laurentfeb0db62011-07-22 09:04:31 -07002969 acquireWakeLock();
2970
Mathias Agopian65ab4712010-07-14 17:59:35 -07002971 while (!exitPending())
2972 {
2973 processConfigEvents();
2974
2975 mixerStatus = MIXER_IDLE;
2976 { // scope for the mLock
2977
2978 Mutex::Autolock _l(mLock);
2979
2980 if (checkForNewParameters_l()) {
2981 mixBufferSize = mFrameCount*mFrameSize;
2982 updateWaitTime();
2983 activeSleepTime = activeSleepTimeUs();
2984 idleSleepTime = idleSleepTimeUs();
2985 }
2986
2987 const SortedVector< wp<Track> >& activeTracks = mActiveTracks;
2988
2989 for (size_t i = 0; i < mOutputTracks.size(); i++) {
2990 outputTracks.add(mOutputTracks[i]);
2991 }
2992
2993 // put audio hardware into standby after short delay
2994 if UNLIKELY((!activeTracks.size() && systemTime() > standbyTime) ||
2995 mSuspended) {
2996 if (!mStandby) {
2997 for (size_t i = 0; i < outputTracks.size(); i++) {
2998 outputTracks[i]->stop();
2999 }
3000 mStandby = true;
3001 mBytesWritten = 0;
3002 }
3003
3004 if (!activeTracks.size() && mConfigEvents.isEmpty()) {
3005 // we're about to wait, flush the binder command buffer
3006 IPCThreadState::self()->flushCommands();
3007 outputTracks.clear();
3008
3009 if (exitPending()) break;
3010
Eric Laurentfeb0db62011-07-22 09:04:31 -07003011 releaseWakeLock_l();
Steve Block3856b092011-10-20 11:56:00 +01003012 ALOGV("DuplicatingThread %p TID %d going to sleep\n", this, gettid());
Mathias Agopian65ab4712010-07-14 17:59:35 -07003013 mWaitWorkCV.wait(mLock);
Steve Block3856b092011-10-20 11:56:00 +01003014 ALOGV("DuplicatingThread %p TID %d waking up\n", this, gettid());
Eric Laurentfeb0db62011-07-22 09:04:31 -07003015 acquireWakeLock_l();
3016
Mathias Agopian65ab4712010-07-14 17:59:35 -07003017 if (mMasterMute == false) {
3018 char value[PROPERTY_VALUE_MAX];
3019 property_get("ro.audio.silent", value, "0");
3020 if (atoi(value)) {
3021 LOGD("Silence is golden");
3022 setMasterMute(true);
3023 }
3024 }
3025
3026 standbyTime = systemTime() + kStandbyTimeInNsecs;
3027 sleepTime = idleSleepTime;
3028 continue;
3029 }
3030 }
3031
3032 mixerStatus = prepareTracks_l(activeTracks, &tracksToRemove);
3033
3034 // prevent any changes in effect chain list and in each effect chain
3035 // during mixing and effect process as the audio buffers could be deleted
3036 // or modified if an effect is created or deleted
Eric Laurentde070132010-07-13 04:45:46 -07003037 lockEffectChains_l(effectChains);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003038 }
3039
3040 if (LIKELY(mixerStatus == MIXER_TRACKS_READY)) {
3041 // mix buffers...
3042 if (outputsReady(outputTracks)) {
3043 mAudioMixer->process();
3044 } else {
3045 memset(mMixBuffer, 0, mixBufferSize);
3046 }
3047 sleepTime = 0;
3048 writeFrames = mFrameCount;
3049 } else {
3050 if (sleepTime == 0) {
3051 if (mixerStatus == MIXER_TRACKS_ENABLED) {
3052 sleepTime = activeSleepTime;
3053 } else {
3054 sleepTime = idleSleepTime;
3055 }
3056 } else if (mBytesWritten != 0) {
3057 // flush remaining overflow buffers in output tracks
3058 for (size_t i = 0; i < outputTracks.size(); i++) {
3059 if (outputTracks[i]->isActive()) {
3060 sleepTime = 0;
3061 writeFrames = 0;
3062 memset(mMixBuffer, 0, mixBufferSize);
3063 break;
3064 }
3065 }
3066 }
3067 }
3068
3069 if (mSuspended) {
Eric Laurent25cbe0e2010-08-18 18:13:17 -07003070 sleepTime = suspendSleepTimeUs();
Mathias Agopian65ab4712010-07-14 17:59:35 -07003071 }
3072 // sleepTime == 0 means we must write to audio hardware
3073 if (sleepTime == 0) {
3074 for (size_t i = 0; i < effectChains.size(); i ++) {
3075 effectChains[i]->process_l();
3076 }
3077 // enable changes in effect chain
Eric Laurentde070132010-07-13 04:45:46 -07003078 unlockEffectChains(effectChains);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003079
3080 standbyTime = systemTime() + kStandbyTimeInNsecs;
3081 for (size_t i = 0; i < outputTracks.size(); i++) {
3082 outputTracks[i]->write(mMixBuffer, writeFrames);
3083 }
3084 mStandby = false;
3085 mBytesWritten += mixBufferSize;
3086 } else {
3087 // enable changes in effect chain
Eric Laurentde070132010-07-13 04:45:46 -07003088 unlockEffectChains(effectChains);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003089 usleep(sleepTime);
3090 }
3091
3092 // finally let go of all our tracks, without the lock held
3093 // since we can't guarantee the destructors won't acquire that
3094 // same lock.
3095 tracksToRemove.clear();
3096 outputTracks.clear();
3097
3098 // Effect chains will be actually deleted here if they were removed from
3099 // mEffectChains list during mixing or effects processing
3100 effectChains.clear();
3101 }
3102
Eric Laurentfeb0db62011-07-22 09:04:31 -07003103 releaseWakeLock();
3104
Mathias Agopian65ab4712010-07-14 17:59:35 -07003105 return false;
3106}
3107
3108void AudioFlinger::DuplicatingThread::addOutputTrack(MixerThread *thread)
3109{
3110 int frameCount = (3 * mFrameCount * mSampleRate) / thread->sampleRate();
3111 OutputTrack *outputTrack = new OutputTrack((ThreadBase *)thread,
3112 this,
3113 mSampleRate,
3114 mFormat,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07003115 mChannelMask,
Mathias Agopian65ab4712010-07-14 17:59:35 -07003116 frameCount);
3117 if (outputTrack->cblk() != NULL) {
Dima Zavinfce7a472011-04-19 22:30:36 -07003118 thread->setStreamVolume(AUDIO_STREAM_CNT, 1.0f);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003119 mOutputTracks.add(outputTrack);
Steve Block3856b092011-10-20 11:56:00 +01003120 ALOGV("addOutputTrack() track %p, on thread %p", outputTrack, thread);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003121 updateWaitTime();
3122 }
3123}
3124
3125void AudioFlinger::DuplicatingThread::removeOutputTrack(MixerThread *thread)
3126{
3127 Mutex::Autolock _l(mLock);
3128 for (size_t i = 0; i < mOutputTracks.size(); i++) {
3129 if (mOutputTracks[i]->thread() == (ThreadBase *)thread) {
3130 mOutputTracks[i]->destroy();
3131 mOutputTracks.removeAt(i);
3132 updateWaitTime();
3133 return;
3134 }
3135 }
Steve Block3856b092011-10-20 11:56:00 +01003136 ALOGV("removeOutputTrack(): unkonwn thread: %p", thread);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003137}
3138
3139void AudioFlinger::DuplicatingThread::updateWaitTime()
3140{
3141 mWaitTimeMs = UINT_MAX;
3142 for (size_t i = 0; i < mOutputTracks.size(); i++) {
3143 sp<ThreadBase> strong = mOutputTracks[i]->thread().promote();
3144 if (strong != NULL) {
3145 uint32_t waitTimeMs = (strong->frameCount() * 2 * 1000) / strong->sampleRate();
3146 if (waitTimeMs < mWaitTimeMs) {
3147 mWaitTimeMs = waitTimeMs;
3148 }
3149 }
3150 }
3151}
3152
3153
3154bool AudioFlinger::DuplicatingThread::outputsReady(SortedVector< sp<OutputTrack> > &outputTracks)
3155{
3156 for (size_t i = 0; i < outputTracks.size(); i++) {
3157 sp <ThreadBase> thread = outputTracks[i]->thread().promote();
3158 if (thread == 0) {
3159 LOGW("DuplicatingThread::outputsReady() could not promote thread on output track %p", outputTracks[i].get());
3160 return false;
3161 }
3162 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
3163 if (playbackThread->standby() && !playbackThread->isSuspended()) {
Steve Block3856b092011-10-20 11:56:00 +01003164 ALOGV("DuplicatingThread output track %p on thread %p Not Ready", outputTracks[i].get(), thread.get());
Mathias Agopian65ab4712010-07-14 17:59:35 -07003165 return false;
3166 }
3167 }
3168 return true;
3169}
3170
3171uint32_t AudioFlinger::DuplicatingThread::activeSleepTimeUs()
3172{
3173 return (mWaitTimeMs * 1000) / 2;
3174}
3175
3176// ----------------------------------------------------------------------------
3177
3178// TrackBase constructor must be called with AudioFlinger::mLock held
3179AudioFlinger::ThreadBase::TrackBase::TrackBase(
3180 const wp<ThreadBase>& thread,
3181 const sp<Client>& client,
3182 uint32_t sampleRate,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07003183 uint32_t format,
3184 uint32_t channelMask,
Mathias Agopian65ab4712010-07-14 17:59:35 -07003185 int frameCount,
3186 uint32_t flags,
3187 const sp<IMemory>& sharedBuffer,
3188 int sessionId)
3189 : RefBase(),
3190 mThread(thread),
3191 mClient(client),
3192 mCblk(0),
3193 mFrameCount(0),
3194 mState(IDLE),
3195 mClientTid(-1),
3196 mFormat(format),
3197 mFlags(flags & ~SYSTEM_FLAGS_MASK),
3198 mSessionId(sessionId)
3199{
Steve Block3856b092011-10-20 11:56:00 +01003200 ALOGV_IF(sharedBuffer != 0, "sharedBuffer: %p, size: %d", sharedBuffer->pointer(), sharedBuffer->size());
Mathias Agopian65ab4712010-07-14 17:59:35 -07003201
3202 // LOGD("Creating track with %d buffers @ %d bytes", bufferCount, bufferSize);
3203 size_t size = sizeof(audio_track_cblk_t);
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07003204 uint8_t channelCount = popcount(channelMask);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003205 size_t bufferSize = frameCount*channelCount*sizeof(int16_t);
3206 if (sharedBuffer == 0) {
3207 size += bufferSize;
3208 }
3209
3210 if (client != NULL) {
3211 mCblkMemory = client->heap()->allocate(size);
3212 if (mCblkMemory != 0) {
3213 mCblk = static_cast<audio_track_cblk_t *>(mCblkMemory->pointer());
3214 if (mCblk) { // construct the shared structure in-place.
3215 new(mCblk) audio_track_cblk_t();
3216 // clear all buffers
3217 mCblk->frameCount = frameCount;
3218 mCblk->sampleRate = sampleRate;
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07003219 mChannelCount = channelCount;
3220 mChannelMask = channelMask;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003221 if (sharedBuffer == 0) {
3222 mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t);
3223 memset(mBuffer, 0, frameCount*channelCount*sizeof(int16_t));
3224 // Force underrun condition to avoid false underrun callback until first data is
Eric Laurent44d98482010-09-30 16:12:31 -07003225 // written to buffer (other flags are cleared)
Mathias Agopian65ab4712010-07-14 17:59:35 -07003226 mCblk->flags = CBLK_UNDERRUN_ON;
3227 } else {
3228 mBuffer = sharedBuffer->pointer();
3229 }
3230 mBufferEnd = (uint8_t *)mBuffer + bufferSize;
3231 }
3232 } else {
3233 LOGE("not enough memory for AudioTrack size=%u", size);
3234 client->heap()->dump("AudioTrack");
3235 return;
3236 }
3237 } else {
3238 mCblk = (audio_track_cblk_t *)(new uint8_t[size]);
3239 if (mCblk) { // construct the shared structure in-place.
3240 new(mCblk) audio_track_cblk_t();
3241 // clear all buffers
3242 mCblk->frameCount = frameCount;
3243 mCblk->sampleRate = sampleRate;
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07003244 mChannelCount = channelCount;
3245 mChannelMask = channelMask;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003246 mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t);
3247 memset(mBuffer, 0, frameCount*channelCount*sizeof(int16_t));
3248 // Force underrun condition to avoid false underrun callback until first data is
Eric Laurent44d98482010-09-30 16:12:31 -07003249 // written to buffer (other flags are cleared)
Mathias Agopian65ab4712010-07-14 17:59:35 -07003250 mCblk->flags = CBLK_UNDERRUN_ON;
3251 mBufferEnd = (uint8_t *)mBuffer + bufferSize;
3252 }
3253 }
3254}
3255
3256AudioFlinger::ThreadBase::TrackBase::~TrackBase()
3257{
3258 if (mCblk) {
3259 mCblk->~audio_track_cblk_t(); // destroy our shared-structure.
3260 if (mClient == NULL) {
3261 delete mCblk;
3262 }
3263 }
3264 mCblkMemory.clear(); // and free the shared memory
3265 if (mClient != NULL) {
3266 Mutex::Autolock _l(mClient->audioFlinger()->mLock);
3267 mClient.clear();
3268 }
3269}
3270
3271void AudioFlinger::ThreadBase::TrackBase::releaseBuffer(AudioBufferProvider::Buffer* buffer)
3272{
3273 buffer->raw = 0;
3274 mFrameCount = buffer->frameCount;
3275 step();
3276 buffer->frameCount = 0;
3277}
3278
3279bool AudioFlinger::ThreadBase::TrackBase::step() {
3280 bool result;
3281 audio_track_cblk_t* cblk = this->cblk();
3282
3283 result = cblk->stepServer(mFrameCount);
3284 if (!result) {
Steve Block3856b092011-10-20 11:56:00 +01003285 ALOGV("stepServer failed acquiring cblk mutex");
Mathias Agopian65ab4712010-07-14 17:59:35 -07003286 mFlags |= STEPSERVER_FAILED;
3287 }
3288 return result;
3289}
3290
3291void AudioFlinger::ThreadBase::TrackBase::reset() {
3292 audio_track_cblk_t* cblk = this->cblk();
3293
3294 cblk->user = 0;
3295 cblk->server = 0;
3296 cblk->userBase = 0;
3297 cblk->serverBase = 0;
3298 mFlags &= (uint32_t)(~SYSTEM_FLAGS_MASK);
Steve Block3856b092011-10-20 11:56:00 +01003299 ALOGV("TrackBase::reset");
Mathias Agopian65ab4712010-07-14 17:59:35 -07003300}
3301
3302sp<IMemory> AudioFlinger::ThreadBase::TrackBase::getCblk() const
3303{
3304 return mCblkMemory;
3305}
3306
3307int AudioFlinger::ThreadBase::TrackBase::sampleRate() const {
3308 return (int)mCblk->sampleRate;
3309}
3310
3311int AudioFlinger::ThreadBase::TrackBase::channelCount() const {
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07003312 return (const int)mChannelCount;
3313}
3314
3315uint32_t AudioFlinger::ThreadBase::TrackBase::channelMask() const {
3316 return mChannelMask;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003317}
3318
3319void* AudioFlinger::ThreadBase::TrackBase::getBuffer(uint32_t offset, uint32_t frames) const {
3320 audio_track_cblk_t* cblk = this->cblk();
3321 int8_t *bufferStart = (int8_t *)mBuffer + (offset-cblk->serverBase)*cblk->frameSize;
3322 int8_t *bufferEnd = bufferStart + frames * cblk->frameSize;
3323
3324 // Check validity of returned pointer in case the track control block would have been corrupted.
3325 if (bufferStart < mBuffer || bufferStart > bufferEnd || bufferEnd > mBufferEnd ||
3326 ((unsigned long)bufferStart & (unsigned long)(cblk->frameSize - 1))) {
3327 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 -07003328 server %d, serverBase %d, user %d, userBase %d",
Mathias Agopian65ab4712010-07-14 17:59:35 -07003329 bufferStart, bufferEnd, mBuffer, mBufferEnd,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07003330 cblk->server, cblk->serverBase, cblk->user, cblk->userBase);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003331 return 0;
3332 }
3333
3334 return bufferStart;
3335}
3336
3337// ----------------------------------------------------------------------------
3338
3339// Track constructor must be called with AudioFlinger::mLock and ThreadBase::mLock held
3340AudioFlinger::PlaybackThread::Track::Track(
3341 const wp<ThreadBase>& thread,
3342 const sp<Client>& client,
3343 int streamType,
3344 uint32_t sampleRate,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07003345 uint32_t format,
3346 uint32_t channelMask,
Mathias Agopian65ab4712010-07-14 17:59:35 -07003347 int frameCount,
3348 const sp<IMemory>& sharedBuffer,
3349 int sessionId)
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07003350 : TrackBase(thread, client, sampleRate, format, channelMask, frameCount, 0, sharedBuffer, sessionId),
Eric Laurent8f45bd72010-08-31 13:50:07 -07003351 mMute(false), mSharedBuffer(sharedBuffer), mName(-1), mMainBuffer(NULL), mAuxBuffer(NULL),
3352 mAuxEffectId(0), mHasVolumeController(false)
Mathias Agopian65ab4712010-07-14 17:59:35 -07003353{
3354 if (mCblk != NULL) {
3355 sp<ThreadBase> baseThread = thread.promote();
3356 if (baseThread != 0) {
3357 PlaybackThread *playbackThread = (PlaybackThread *)baseThread.get();
3358 mName = playbackThread->getTrackName_l();
3359 mMainBuffer = playbackThread->mixBuffer();
3360 }
Steve Block3856b092011-10-20 11:56:00 +01003361 ALOGV("Track constructor name %d, calling thread %d", mName, IPCThreadState::self()->getCallingPid());
Mathias Agopian65ab4712010-07-14 17:59:35 -07003362 if (mName < 0) {
3363 LOGE("no more track names available");
3364 }
3365 mVolume[0] = 1.0f;
3366 mVolume[1] = 1.0f;
3367 mStreamType = streamType;
3368 // NOTE: audio_track_cblk_t::frameSize for 8 bit PCM data is based on a sample size of
3369 // 16 bit because data is converted to 16 bit before being stored in buffer by AudioTrack
Eric Laurentedc15ad2011-07-21 19:35:01 -07003370 mCblk->frameSize = audio_is_linear_pcm(format) ? mChannelCount * sizeof(int16_t) : sizeof(uint8_t);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003371 }
3372}
3373
3374AudioFlinger::PlaybackThread::Track::~Track()
3375{
Steve Block3856b092011-10-20 11:56:00 +01003376 ALOGV("PlaybackThread::Track destructor");
Mathias Agopian65ab4712010-07-14 17:59:35 -07003377 sp<ThreadBase> thread = mThread.promote();
3378 if (thread != 0) {
3379 Mutex::Autolock _l(thread->mLock);
3380 mState = TERMINATED;
3381 }
3382}
3383
3384void AudioFlinger::PlaybackThread::Track::destroy()
3385{
3386 // NOTE: destroyTrack_l() can remove a strong reference to this Track
3387 // by removing it from mTracks vector, so there is a risk that this Tracks's
3388 // desctructor is called. As the destructor needs to lock mLock,
3389 // we must acquire a strong reference on this Track before locking mLock
3390 // here so that the destructor is called only when exiting this function.
3391 // On the other hand, as long as Track::destroy() is only called by
3392 // TrackHandle destructor, the TrackHandle still holds a strong ref on
3393 // this Track with its member mTrack.
3394 sp<Track> keep(this);
3395 { // scope for mLock
3396 sp<ThreadBase> thread = mThread.promote();
3397 if (thread != 0) {
3398 if (!isOutputTrack()) {
3399 if (mState == ACTIVE || mState == RESUMING) {
Eric Laurentde070132010-07-13 04:45:46 -07003400 AudioSystem::stopOutput(thread->id(),
Dima Zavinfce7a472011-04-19 22:30:36 -07003401 (audio_stream_type_t)mStreamType,
Eric Laurentde070132010-07-13 04:45:46 -07003402 mSessionId);
Gloria Wang9ee159b2011-02-24 14:51:45 -08003403
3404 // to track the speaker usage
3405 addBatteryData(IMediaPlayerService::kBatteryDataAudioFlingerStop);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003406 }
3407 AudioSystem::releaseOutput(thread->id());
3408 }
3409 Mutex::Autolock _l(thread->mLock);
3410 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
3411 playbackThread->destroyTrack_l(this);
3412 }
3413 }
3414}
3415
3416void AudioFlinger::PlaybackThread::Track::dump(char* buffer, size_t size)
3417{
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07003418 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 -07003419 mName - AudioMixer::TRACK0,
3420 (mClient == NULL) ? getpid() : mClient->pid(),
3421 mStreamType,
3422 mFormat,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07003423 mChannelMask,
Mathias Agopian65ab4712010-07-14 17:59:35 -07003424 mSessionId,
3425 mFrameCount,
3426 mState,
3427 mMute,
3428 mFillingUpStatus,
3429 mCblk->sampleRate,
3430 mCblk->volume[0],
3431 mCblk->volume[1],
3432 mCblk->server,
3433 mCblk->user,
3434 (int)mMainBuffer,
3435 (int)mAuxBuffer);
3436}
3437
3438status_t AudioFlinger::PlaybackThread::Track::getNextBuffer(AudioBufferProvider::Buffer* buffer)
3439{
3440 audio_track_cblk_t* cblk = this->cblk();
3441 uint32_t framesReady;
3442 uint32_t framesReq = buffer->frameCount;
3443
3444 // Check if last stepServer failed, try to step now
3445 if (mFlags & TrackBase::STEPSERVER_FAILED) {
3446 if (!step()) goto getNextBuffer_exit;
Steve Block3856b092011-10-20 11:56:00 +01003447 ALOGV("stepServer recovered");
Mathias Agopian65ab4712010-07-14 17:59:35 -07003448 mFlags &= ~TrackBase::STEPSERVER_FAILED;
3449 }
3450
3451 framesReady = cblk->framesReady();
3452
3453 if (LIKELY(framesReady)) {
3454 uint32_t s = cblk->server;
3455 uint32_t bufferEnd = cblk->serverBase + cblk->frameCount;
3456
3457 bufferEnd = (cblk->loopEnd < bufferEnd) ? cblk->loopEnd : bufferEnd;
3458 if (framesReq > framesReady) {
3459 framesReq = framesReady;
3460 }
3461 if (s + framesReq > bufferEnd) {
3462 framesReq = bufferEnd - s;
3463 }
3464
3465 buffer->raw = getBuffer(s, framesReq);
3466 if (buffer->raw == 0) goto getNextBuffer_exit;
3467
3468 buffer->frameCount = framesReq;
3469 return NO_ERROR;
3470 }
3471
3472getNextBuffer_exit:
3473 buffer->raw = 0;
3474 buffer->frameCount = 0;
Steve Block3856b092011-10-20 11:56:00 +01003475 ALOGV("getNextBuffer() no more data for track %d on thread %p", mName, mThread.unsafe_get());
Mathias Agopian65ab4712010-07-14 17:59:35 -07003476 return NOT_ENOUGH_DATA;
3477}
3478
3479bool AudioFlinger::PlaybackThread::Track::isReady() const {
Eric Laurentaf59ce22010-10-05 14:41:42 -07003480 if (mFillingUpStatus != FS_FILLING || isStopped() || isPausing()) return true;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003481
3482 if (mCblk->framesReady() >= mCblk->frameCount ||
3483 (mCblk->flags & CBLK_FORCEREADY_MSK)) {
3484 mFillingUpStatus = FS_FILLED;
Eric Laurent38ccae22011-03-28 18:37:07 -07003485 android_atomic_and(~CBLK_FORCEREADY_MSK, &mCblk->flags);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003486 return true;
3487 }
3488 return false;
3489}
3490
3491status_t AudioFlinger::PlaybackThread::Track::start()
3492{
3493 status_t status = NO_ERROR;
Steve Block3856b092011-10-20 11:56:00 +01003494 ALOGV("start(%d), calling thread %d session %d",
Eric Laurentf997cab2010-07-19 06:24:46 -07003495 mName, IPCThreadState::self()->getCallingPid(), mSessionId);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003496 sp<ThreadBase> thread = mThread.promote();
3497 if (thread != 0) {
3498 Mutex::Autolock _l(thread->mLock);
3499 int state = mState;
3500 // here the track could be either new, or restarted
3501 // in both cases "unstop" the track
3502 if (mState == PAUSED) {
3503 mState = TrackBase::RESUMING;
Steve Block3856b092011-10-20 11:56:00 +01003504 ALOGV("PAUSED => RESUMING (%d) on thread %p", mName, this);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003505 } else {
3506 mState = TrackBase::ACTIVE;
Steve Block3856b092011-10-20 11:56:00 +01003507 ALOGV("? => ACTIVE (%d) on thread %p", mName, this);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003508 }
3509
3510 if (!isOutputTrack() && state != ACTIVE && state != RESUMING) {
3511 thread->mLock.unlock();
Eric Laurentde070132010-07-13 04:45:46 -07003512 status = AudioSystem::startOutput(thread->id(),
Dima Zavinfce7a472011-04-19 22:30:36 -07003513 (audio_stream_type_t)mStreamType,
Eric Laurentde070132010-07-13 04:45:46 -07003514 mSessionId);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003515 thread->mLock.lock();
Gloria Wang9ee159b2011-02-24 14:51:45 -08003516
3517 // to track the speaker usage
3518 if (status == NO_ERROR) {
3519 addBatteryData(IMediaPlayerService::kBatteryDataAudioFlingerStart);
3520 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07003521 }
3522 if (status == NO_ERROR) {
3523 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
3524 playbackThread->addTrack_l(this);
3525 } else {
3526 mState = state;
3527 }
3528 } else {
3529 status = BAD_VALUE;
3530 }
3531 return status;
3532}
3533
3534void AudioFlinger::PlaybackThread::Track::stop()
3535{
Steve Block3856b092011-10-20 11:56:00 +01003536 ALOGV("stop(%d), calling thread %d", mName, IPCThreadState::self()->getCallingPid());
Mathias Agopian65ab4712010-07-14 17:59:35 -07003537 sp<ThreadBase> thread = mThread.promote();
3538 if (thread != 0) {
3539 Mutex::Autolock _l(thread->mLock);
3540 int state = mState;
3541 if (mState > STOPPED) {
3542 mState = STOPPED;
3543 // If the track is not active (PAUSED and buffers full), flush buffers
3544 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
3545 if (playbackThread->mActiveTracks.indexOf(this) < 0) {
3546 reset();
3547 }
Steve Block3856b092011-10-20 11:56:00 +01003548 ALOGV("(> STOPPED) => STOPPED (%d) on thread %p", mName, playbackThread);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003549 }
3550 if (!isOutputTrack() && (state == ACTIVE || state == RESUMING)) {
3551 thread->mLock.unlock();
Eric Laurentde070132010-07-13 04:45:46 -07003552 AudioSystem::stopOutput(thread->id(),
Dima Zavinfce7a472011-04-19 22:30:36 -07003553 (audio_stream_type_t)mStreamType,
Eric Laurentde070132010-07-13 04:45:46 -07003554 mSessionId);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003555 thread->mLock.lock();
Gloria Wang9ee159b2011-02-24 14:51:45 -08003556
3557 // to track the speaker usage
3558 addBatteryData(IMediaPlayerService::kBatteryDataAudioFlingerStop);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003559 }
3560 }
3561}
3562
3563void AudioFlinger::PlaybackThread::Track::pause()
3564{
Steve Block3856b092011-10-20 11:56:00 +01003565 ALOGV("pause(%d), calling thread %d", mName, IPCThreadState::self()->getCallingPid());
Mathias Agopian65ab4712010-07-14 17:59:35 -07003566 sp<ThreadBase> thread = mThread.promote();
3567 if (thread != 0) {
3568 Mutex::Autolock _l(thread->mLock);
3569 if (mState == ACTIVE || mState == RESUMING) {
3570 mState = PAUSING;
Steve Block3856b092011-10-20 11:56:00 +01003571 ALOGV("ACTIVE/RESUMING => PAUSING (%d) on thread %p", mName, thread.get());
Mathias Agopian65ab4712010-07-14 17:59:35 -07003572 if (!isOutputTrack()) {
3573 thread->mLock.unlock();
Eric Laurentde070132010-07-13 04:45:46 -07003574 AudioSystem::stopOutput(thread->id(),
Dima Zavinfce7a472011-04-19 22:30:36 -07003575 (audio_stream_type_t)mStreamType,
Eric Laurentde070132010-07-13 04:45:46 -07003576 mSessionId);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003577 thread->mLock.lock();
Gloria Wang9ee159b2011-02-24 14:51:45 -08003578
3579 // to track the speaker usage
3580 addBatteryData(IMediaPlayerService::kBatteryDataAudioFlingerStop);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003581 }
3582 }
3583 }
3584}
3585
3586void AudioFlinger::PlaybackThread::Track::flush()
3587{
Steve Block3856b092011-10-20 11:56:00 +01003588 ALOGV("flush(%d)", mName);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003589 sp<ThreadBase> thread = mThread.promote();
3590 if (thread != 0) {
3591 Mutex::Autolock _l(thread->mLock);
3592 if (mState != STOPPED && mState != PAUSED && mState != PAUSING) {
3593 return;
3594 }
3595 // No point remaining in PAUSED state after a flush => go to
3596 // STOPPED state
3597 mState = STOPPED;
3598
Eric Laurent38ccae22011-03-28 18:37:07 -07003599 // do not reset the track if it is still in the process of being stopped or paused.
3600 // this will be done by prepareTracks_l() when the track is stopped.
3601 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
3602 if (playbackThread->mActiveTracks.indexOf(this) < 0) {
3603 reset();
3604 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07003605 }
3606}
3607
3608void AudioFlinger::PlaybackThread::Track::reset()
3609{
3610 // Do not reset twice to avoid discarding data written just after a flush and before
3611 // the audioflinger thread detects the track is stopped.
3612 if (!mResetDone) {
3613 TrackBase::reset();
3614 // Force underrun condition to avoid false underrun callback until first data is
3615 // written to buffer
Eric Laurent38ccae22011-03-28 18:37:07 -07003616 android_atomic_and(~CBLK_FORCEREADY_MSK, &mCblk->flags);
3617 android_atomic_or(CBLK_UNDERRUN_ON, &mCblk->flags);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003618 mFillingUpStatus = FS_FILLING;
3619 mResetDone = true;
3620 }
3621}
3622
3623void AudioFlinger::PlaybackThread::Track::mute(bool muted)
3624{
3625 mMute = muted;
3626}
3627
3628void AudioFlinger::PlaybackThread::Track::setVolume(float left, float right)
3629{
3630 mVolume[0] = left;
3631 mVolume[1] = right;
3632}
3633
3634status_t AudioFlinger::PlaybackThread::Track::attachAuxEffect(int EffectId)
3635{
3636 status_t status = DEAD_OBJECT;
3637 sp<ThreadBase> thread = mThread.promote();
3638 if (thread != 0) {
3639 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
3640 status = playbackThread->attachAuxEffect(this, EffectId);
3641 }
3642 return status;
3643}
3644
3645void AudioFlinger::PlaybackThread::Track::setAuxBuffer(int EffectId, int32_t *buffer)
3646{
3647 mAuxEffectId = EffectId;
3648 mAuxBuffer = buffer;
3649}
3650
3651// ----------------------------------------------------------------------------
3652
3653// RecordTrack constructor must be called with AudioFlinger::mLock held
3654AudioFlinger::RecordThread::RecordTrack::RecordTrack(
3655 const wp<ThreadBase>& thread,
3656 const sp<Client>& client,
3657 uint32_t sampleRate,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07003658 uint32_t format,
3659 uint32_t channelMask,
Mathias Agopian65ab4712010-07-14 17:59:35 -07003660 int frameCount,
3661 uint32_t flags,
3662 int sessionId)
3663 : TrackBase(thread, client, sampleRate, format,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07003664 channelMask, frameCount, flags, 0, sessionId),
Mathias Agopian65ab4712010-07-14 17:59:35 -07003665 mOverflow(false)
3666{
3667 if (mCblk != NULL) {
Steve Block3856b092011-10-20 11:56:00 +01003668 ALOGV("RecordTrack constructor, size %d", (int)mBufferEnd - (int)mBuffer);
Dima Zavinfce7a472011-04-19 22:30:36 -07003669 if (format == AUDIO_FORMAT_PCM_16_BIT) {
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07003670 mCblk->frameSize = mChannelCount * sizeof(int16_t);
Dima Zavinfce7a472011-04-19 22:30:36 -07003671 } else if (format == AUDIO_FORMAT_PCM_8_BIT) {
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07003672 mCblk->frameSize = mChannelCount * sizeof(int8_t);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003673 } else {
3674 mCblk->frameSize = sizeof(int8_t);
3675 }
3676 }
3677}
3678
3679AudioFlinger::RecordThread::RecordTrack::~RecordTrack()
3680{
3681 sp<ThreadBase> thread = mThread.promote();
3682 if (thread != 0) {
3683 AudioSystem::releaseInput(thread->id());
3684 }
3685}
3686
3687status_t AudioFlinger::RecordThread::RecordTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer)
3688{
3689 audio_track_cblk_t* cblk = this->cblk();
3690 uint32_t framesAvail;
3691 uint32_t framesReq = buffer->frameCount;
3692
3693 // Check if last stepServer failed, try to step now
3694 if (mFlags & TrackBase::STEPSERVER_FAILED) {
3695 if (!step()) goto getNextBuffer_exit;
Steve Block3856b092011-10-20 11:56:00 +01003696 ALOGV("stepServer recovered");
Mathias Agopian65ab4712010-07-14 17:59:35 -07003697 mFlags &= ~TrackBase::STEPSERVER_FAILED;
3698 }
3699
3700 framesAvail = cblk->framesAvailable_l();
3701
3702 if (LIKELY(framesAvail)) {
3703 uint32_t s = cblk->server;
3704 uint32_t bufferEnd = cblk->serverBase + cblk->frameCount;
3705
3706 if (framesReq > framesAvail) {
3707 framesReq = framesAvail;
3708 }
3709 if (s + framesReq > bufferEnd) {
3710 framesReq = bufferEnd - s;
3711 }
3712
3713 buffer->raw = getBuffer(s, framesReq);
3714 if (buffer->raw == 0) goto getNextBuffer_exit;
3715
3716 buffer->frameCount = framesReq;
3717 return NO_ERROR;
3718 }
3719
3720getNextBuffer_exit:
3721 buffer->raw = 0;
3722 buffer->frameCount = 0;
3723 return NOT_ENOUGH_DATA;
3724}
3725
3726status_t AudioFlinger::RecordThread::RecordTrack::start()
3727{
3728 sp<ThreadBase> thread = mThread.promote();
3729 if (thread != 0) {
3730 RecordThread *recordThread = (RecordThread *)thread.get();
3731 return recordThread->start(this);
3732 } else {
3733 return BAD_VALUE;
3734 }
3735}
3736
3737void AudioFlinger::RecordThread::RecordTrack::stop()
3738{
3739 sp<ThreadBase> thread = mThread.promote();
3740 if (thread != 0) {
3741 RecordThread *recordThread = (RecordThread *)thread.get();
3742 recordThread->stop(this);
Eric Laurent38ccae22011-03-28 18:37:07 -07003743 TrackBase::reset();
3744 // Force overerrun condition to avoid false overrun callback until first data is
3745 // read from buffer
3746 android_atomic_or(CBLK_UNDERRUN_ON, &mCblk->flags);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003747 }
3748}
3749
3750void AudioFlinger::RecordThread::RecordTrack::dump(char* buffer, size_t size)
3751{
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07003752 snprintf(buffer, size, " %05d %03u 0x%08x %05d %04u %01d %05u %08x %08x\n",
Mathias Agopian65ab4712010-07-14 17:59:35 -07003753 (mClient == NULL) ? getpid() : mClient->pid(),
3754 mFormat,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07003755 mChannelMask,
Mathias Agopian65ab4712010-07-14 17:59:35 -07003756 mSessionId,
3757 mFrameCount,
3758 mState,
3759 mCblk->sampleRate,
3760 mCblk->server,
3761 mCblk->user);
3762}
3763
3764
3765// ----------------------------------------------------------------------------
3766
3767AudioFlinger::PlaybackThread::OutputTrack::OutputTrack(
3768 const wp<ThreadBase>& thread,
3769 DuplicatingThread *sourceThread,
3770 uint32_t sampleRate,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07003771 uint32_t format,
3772 uint32_t channelMask,
Mathias Agopian65ab4712010-07-14 17:59:35 -07003773 int frameCount)
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07003774 : Track(thread, NULL, AUDIO_STREAM_CNT, sampleRate, format, channelMask, frameCount, NULL, 0),
Mathias Agopian65ab4712010-07-14 17:59:35 -07003775 mActive(false), mSourceThread(sourceThread)
3776{
3777
3778 PlaybackThread *playbackThread = (PlaybackThread *)thread.unsafe_get();
3779 if (mCblk != NULL) {
3780 mCblk->flags |= CBLK_DIRECTION_OUT;
3781 mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t);
3782 mCblk->volume[0] = mCblk->volume[1] = 0x1000;
3783 mOutBuffer.frameCount = 0;
3784 playbackThread->mTracks.add(this);
Steve Block3856b092011-10-20 11:56:00 +01003785 ALOGV("OutputTrack constructor mCblk %p, mBuffer %p, mCblk->buffers %p, " \
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07003786 "mCblk->frameCount %d, mCblk->sampleRate %d, mChannelMask 0x%08x mBufferEnd %p",
3787 mCblk, mBuffer, mCblk->buffers,
3788 mCblk->frameCount, mCblk->sampleRate, mChannelMask, mBufferEnd);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003789 } else {
3790 LOGW("Error creating output track on thread %p", playbackThread);
3791 }
3792}
3793
3794AudioFlinger::PlaybackThread::OutputTrack::~OutputTrack()
3795{
3796 clearBufferQueue();
3797}
3798
3799status_t AudioFlinger::PlaybackThread::OutputTrack::start()
3800{
3801 status_t status = Track::start();
3802 if (status != NO_ERROR) {
3803 return status;
3804 }
3805
3806 mActive = true;
3807 mRetryCount = 127;
3808 return status;
3809}
3810
3811void AudioFlinger::PlaybackThread::OutputTrack::stop()
3812{
3813 Track::stop();
3814 clearBufferQueue();
3815 mOutBuffer.frameCount = 0;
3816 mActive = false;
3817}
3818
3819bool AudioFlinger::PlaybackThread::OutputTrack::write(int16_t* data, uint32_t frames)
3820{
3821 Buffer *pInBuffer;
3822 Buffer inBuffer;
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07003823 uint32_t channelCount = mChannelCount;
Mathias Agopian65ab4712010-07-14 17:59:35 -07003824 bool outputBufferFull = false;
3825 inBuffer.frameCount = frames;
3826 inBuffer.i16 = data;
3827
3828 uint32_t waitTimeLeftMs = mSourceThread->waitTimeMs();
3829
3830 if (!mActive && frames != 0) {
3831 start();
3832 sp<ThreadBase> thread = mThread.promote();
3833 if (thread != 0) {
3834 MixerThread *mixerThread = (MixerThread *)thread.get();
3835 if (mCblk->frameCount > frames){
3836 if (mBufferQueue.size() < kMaxOverFlowBuffers) {
3837 uint32_t startFrames = (mCblk->frameCount - frames);
3838 pInBuffer = new Buffer;
3839 pInBuffer->mBuffer = new int16_t[startFrames * channelCount];
3840 pInBuffer->frameCount = startFrames;
3841 pInBuffer->i16 = pInBuffer->mBuffer;
3842 memset(pInBuffer->raw, 0, startFrames * channelCount * sizeof(int16_t));
3843 mBufferQueue.add(pInBuffer);
3844 } else {
3845 LOGW ("OutputTrack::write() %p no more buffers in queue", this);
3846 }
3847 }
3848 }
3849 }
3850
3851 while (waitTimeLeftMs) {
3852 // First write pending buffers, then new data
3853 if (mBufferQueue.size()) {
3854 pInBuffer = mBufferQueue.itemAt(0);
3855 } else {
3856 pInBuffer = &inBuffer;
3857 }
3858
3859 if (pInBuffer->frameCount == 0) {
3860 break;
3861 }
3862
3863 if (mOutBuffer.frameCount == 0) {
3864 mOutBuffer.frameCount = pInBuffer->frameCount;
3865 nsecs_t startTime = systemTime();
3866 if (obtainBuffer(&mOutBuffer, waitTimeLeftMs) == (status_t)AudioTrack::NO_MORE_BUFFERS) {
Steve Block3856b092011-10-20 11:56:00 +01003867 ALOGV ("OutputTrack::write() %p thread %p no more output buffers", this, mThread.unsafe_get());
Mathias Agopian65ab4712010-07-14 17:59:35 -07003868 outputBufferFull = true;
3869 break;
3870 }
3871 uint32_t waitTimeMs = (uint32_t)ns2ms(systemTime() - startTime);
3872 if (waitTimeLeftMs >= waitTimeMs) {
3873 waitTimeLeftMs -= waitTimeMs;
3874 } else {
3875 waitTimeLeftMs = 0;
3876 }
3877 }
3878
3879 uint32_t outFrames = pInBuffer->frameCount > mOutBuffer.frameCount ? mOutBuffer.frameCount : pInBuffer->frameCount;
3880 memcpy(mOutBuffer.raw, pInBuffer->raw, outFrames * channelCount * sizeof(int16_t));
3881 mCblk->stepUser(outFrames);
3882 pInBuffer->frameCount -= outFrames;
3883 pInBuffer->i16 += outFrames * channelCount;
3884 mOutBuffer.frameCount -= outFrames;
3885 mOutBuffer.i16 += outFrames * channelCount;
3886
3887 if (pInBuffer->frameCount == 0) {
3888 if (mBufferQueue.size()) {
3889 mBufferQueue.removeAt(0);
3890 delete [] pInBuffer->mBuffer;
3891 delete pInBuffer;
Steve Block3856b092011-10-20 11:56:00 +01003892 ALOGV("OutputTrack::write() %p thread %p released overflow buffer %d", this, mThread.unsafe_get(), mBufferQueue.size());
Mathias Agopian65ab4712010-07-14 17:59:35 -07003893 } else {
3894 break;
3895 }
3896 }
3897 }
3898
3899 // If we could not write all frames, allocate a buffer and queue it for next time.
3900 if (inBuffer.frameCount) {
3901 sp<ThreadBase> thread = mThread.promote();
3902 if (thread != 0 && !thread->standby()) {
3903 if (mBufferQueue.size() < kMaxOverFlowBuffers) {
3904 pInBuffer = new Buffer;
3905 pInBuffer->mBuffer = new int16_t[inBuffer.frameCount * channelCount];
3906 pInBuffer->frameCount = inBuffer.frameCount;
3907 pInBuffer->i16 = pInBuffer->mBuffer;
3908 memcpy(pInBuffer->raw, inBuffer.raw, inBuffer.frameCount * channelCount * sizeof(int16_t));
3909 mBufferQueue.add(pInBuffer);
Steve Block3856b092011-10-20 11:56:00 +01003910 ALOGV("OutputTrack::write() %p thread %p adding overflow buffer %d", this, mThread.unsafe_get(), mBufferQueue.size());
Mathias Agopian65ab4712010-07-14 17:59:35 -07003911 } else {
3912 LOGW("OutputTrack::write() %p thread %p no more overflow buffers", mThread.unsafe_get(), this);
3913 }
3914 }
3915 }
3916
3917 // Calling write() with a 0 length buffer, means that no more data will be written:
3918 // If no more buffers are pending, fill output track buffer to make sure it is started
3919 // by output mixer.
3920 if (frames == 0 && mBufferQueue.size() == 0) {
3921 if (mCblk->user < mCblk->frameCount) {
3922 frames = mCblk->frameCount - mCblk->user;
3923 pInBuffer = new Buffer;
3924 pInBuffer->mBuffer = new int16_t[frames * channelCount];
3925 pInBuffer->frameCount = frames;
3926 pInBuffer->i16 = pInBuffer->mBuffer;
3927 memset(pInBuffer->raw, 0, frames * channelCount * sizeof(int16_t));
3928 mBufferQueue.add(pInBuffer);
3929 } else if (mActive) {
3930 stop();
3931 }
3932 }
3933
3934 return outputBufferFull;
3935}
3936
3937status_t AudioFlinger::PlaybackThread::OutputTrack::obtainBuffer(AudioBufferProvider::Buffer* buffer, uint32_t waitTimeMs)
3938{
3939 int active;
3940 status_t result;
3941 audio_track_cblk_t* cblk = mCblk;
3942 uint32_t framesReq = buffer->frameCount;
3943
Steve Block3856b092011-10-20 11:56:00 +01003944// ALOGV("OutputTrack::obtainBuffer user %d, server %d", cblk->user, cblk->server);
Mathias Agopian65ab4712010-07-14 17:59:35 -07003945 buffer->frameCount = 0;
3946
3947 uint32_t framesAvail = cblk->framesAvailable();
3948
3949
3950 if (framesAvail == 0) {
3951 Mutex::Autolock _l(cblk->lock);
3952 goto start_loop_here;
3953 while (framesAvail == 0) {
3954 active = mActive;
3955 if (UNLIKELY(!active)) {
Steve Block3856b092011-10-20 11:56:00 +01003956 ALOGV("Not active and NO_MORE_BUFFERS");
Mathias Agopian65ab4712010-07-14 17:59:35 -07003957 return AudioTrack::NO_MORE_BUFFERS;
3958 }
3959 result = cblk->cv.waitRelative(cblk->lock, milliseconds(waitTimeMs));
3960 if (result != NO_ERROR) {
3961 return AudioTrack::NO_MORE_BUFFERS;
3962 }
3963 // read the server count again
3964 start_loop_here:
3965 framesAvail = cblk->framesAvailable_l();
3966 }
3967 }
3968
3969// if (framesAvail < framesReq) {
3970// return AudioTrack::NO_MORE_BUFFERS;
3971// }
3972
3973 if (framesReq > framesAvail) {
3974 framesReq = framesAvail;
3975 }
3976
3977 uint32_t u = cblk->user;
3978 uint32_t bufferEnd = cblk->userBase + cblk->frameCount;
3979
3980 if (u + framesReq > bufferEnd) {
3981 framesReq = bufferEnd - u;
3982 }
3983
3984 buffer->frameCount = framesReq;
3985 buffer->raw = (void *)cblk->buffer(u);
3986 return NO_ERROR;
3987}
3988
3989
3990void AudioFlinger::PlaybackThread::OutputTrack::clearBufferQueue()
3991{
3992 size_t size = mBufferQueue.size();
3993 Buffer *pBuffer;
3994
3995 for (size_t i = 0; i < size; i++) {
3996 pBuffer = mBufferQueue.itemAt(i);
3997 delete [] pBuffer->mBuffer;
3998 delete pBuffer;
3999 }
4000 mBufferQueue.clear();
4001}
4002
4003// ----------------------------------------------------------------------------
4004
4005AudioFlinger::Client::Client(const sp<AudioFlinger>& audioFlinger, pid_t pid)
4006 : RefBase(),
4007 mAudioFlinger(audioFlinger),
4008 mMemoryDealer(new MemoryDealer(1024*1024, "AudioFlinger::Client")),
4009 mPid(pid)
4010{
4011 // 1 MB of address space is good for 32 tracks, 8 buffers each, 4 KB/buffer
4012}
4013
4014// Client destructor must be called with AudioFlinger::mLock held
4015AudioFlinger::Client::~Client()
4016{
4017 mAudioFlinger->removeClient_l(mPid);
4018}
4019
4020const sp<MemoryDealer>& AudioFlinger::Client::heap() const
4021{
4022 return mMemoryDealer;
4023}
4024
4025// ----------------------------------------------------------------------------
4026
4027AudioFlinger::NotificationClient::NotificationClient(const sp<AudioFlinger>& audioFlinger,
4028 const sp<IAudioFlingerClient>& client,
4029 pid_t pid)
4030 : mAudioFlinger(audioFlinger), mPid(pid), mClient(client)
4031{
4032}
4033
4034AudioFlinger::NotificationClient::~NotificationClient()
4035{
4036 mClient.clear();
4037}
4038
4039void AudioFlinger::NotificationClient::binderDied(const wp<IBinder>& who)
4040{
4041 sp<NotificationClient> keep(this);
4042 {
4043 mAudioFlinger->removeNotificationClient(mPid);
4044 }
4045}
4046
4047// ----------------------------------------------------------------------------
4048
4049AudioFlinger::TrackHandle::TrackHandle(const sp<AudioFlinger::PlaybackThread::Track>& track)
4050 : BnAudioTrack(),
4051 mTrack(track)
4052{
4053}
4054
4055AudioFlinger::TrackHandle::~TrackHandle() {
4056 // just stop the track on deletion, associated resources
4057 // will be freed from the main thread once all pending buffers have
4058 // been played. Unless it's not in the active track list, in which
4059 // case we free everything now...
4060 mTrack->destroy();
4061}
4062
4063status_t AudioFlinger::TrackHandle::start() {
4064 return mTrack->start();
4065}
4066
4067void AudioFlinger::TrackHandle::stop() {
4068 mTrack->stop();
4069}
4070
4071void AudioFlinger::TrackHandle::flush() {
4072 mTrack->flush();
4073}
4074
4075void AudioFlinger::TrackHandle::mute(bool e) {
4076 mTrack->mute(e);
4077}
4078
4079void AudioFlinger::TrackHandle::pause() {
4080 mTrack->pause();
4081}
4082
4083void AudioFlinger::TrackHandle::setVolume(float left, float right) {
4084 mTrack->setVolume(left, right);
4085}
4086
4087sp<IMemory> AudioFlinger::TrackHandle::getCblk() const {
4088 return mTrack->getCblk();
4089}
4090
4091status_t AudioFlinger::TrackHandle::attachAuxEffect(int EffectId)
4092{
4093 return mTrack->attachAuxEffect(EffectId);
4094}
4095
4096status_t AudioFlinger::TrackHandle::onTransact(
4097 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
4098{
4099 return BnAudioTrack::onTransact(code, data, reply, flags);
4100}
4101
4102// ----------------------------------------------------------------------------
4103
4104sp<IAudioRecord> AudioFlinger::openRecord(
4105 pid_t pid,
4106 int input,
4107 uint32_t sampleRate,
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07004108 uint32_t format,
4109 uint32_t channelMask,
Mathias Agopian65ab4712010-07-14 17:59:35 -07004110 int frameCount,
4111 uint32_t flags,
4112 int *sessionId,
4113 status_t *status)
4114{
4115 sp<RecordThread::RecordTrack> recordTrack;
4116 sp<RecordHandle> recordHandle;
4117 sp<Client> client;
4118 wp<Client> wclient;
4119 status_t lStatus;
4120 RecordThread *thread;
4121 size_t inFrameCount;
4122 int lSessionId;
4123
4124 // check calling permissions
4125 if (!recordingAllowed()) {
4126 lStatus = PERMISSION_DENIED;
4127 goto Exit;
4128 }
4129
4130 // add client to list
4131 { // scope for mLock
4132 Mutex::Autolock _l(mLock);
4133 thread = checkRecordThread_l(input);
4134 if (thread == NULL) {
4135 lStatus = BAD_VALUE;
4136 goto Exit;
4137 }
4138
4139 wclient = mClients.valueFor(pid);
4140 if (wclient != NULL) {
4141 client = wclient.promote();
4142 } else {
4143 client = new Client(this, pid);
4144 mClients.add(pid, client);
4145 }
4146
4147 // If no audio session id is provided, create one here
Dima Zavinfce7a472011-04-19 22:30:36 -07004148 if (sessionId != NULL && *sessionId != AUDIO_SESSION_OUTPUT_MIX) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07004149 lSessionId = *sessionId;
4150 } else {
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004151 lSessionId = nextUniqueId();
Mathias Agopian65ab4712010-07-14 17:59:35 -07004152 if (sessionId != NULL) {
4153 *sessionId = lSessionId;
4154 }
4155 }
4156 // create new record track. The record track uses one track in mHardwareMixerThread by convention.
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004157 recordTrack = thread->createRecordTrack_l(client,
4158 sampleRate,
4159 format,
4160 channelMask,
4161 frameCount,
4162 flags,
4163 lSessionId,
4164 &lStatus);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004165 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004166 if (lStatus != NO_ERROR) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07004167 // remove local strong reference to Client before deleting the RecordTrack so that the Client
4168 // destructor is called by the TrackBase destructor with mLock held
4169 client.clear();
4170 recordTrack.clear();
Mathias Agopian65ab4712010-07-14 17:59:35 -07004171 goto Exit;
4172 }
4173
4174 // return to handle to client
4175 recordHandle = new RecordHandle(recordTrack);
4176 lStatus = NO_ERROR;
4177
4178Exit:
4179 if (status) {
4180 *status = lStatus;
4181 }
4182 return recordHandle;
4183}
4184
4185// ----------------------------------------------------------------------------
4186
4187AudioFlinger::RecordHandle::RecordHandle(const sp<AudioFlinger::RecordThread::RecordTrack>& recordTrack)
4188 : BnAudioRecord(),
4189 mRecordTrack(recordTrack)
4190{
4191}
4192
4193AudioFlinger::RecordHandle::~RecordHandle() {
4194 stop();
4195}
4196
4197status_t AudioFlinger::RecordHandle::start() {
Steve Block3856b092011-10-20 11:56:00 +01004198 ALOGV("RecordHandle::start()");
Mathias Agopian65ab4712010-07-14 17:59:35 -07004199 return mRecordTrack->start();
4200}
4201
4202void AudioFlinger::RecordHandle::stop() {
Steve Block3856b092011-10-20 11:56:00 +01004203 ALOGV("RecordHandle::stop()");
Mathias Agopian65ab4712010-07-14 17:59:35 -07004204 mRecordTrack->stop();
4205}
4206
4207sp<IMemory> AudioFlinger::RecordHandle::getCblk() const {
4208 return mRecordTrack->getCblk();
4209}
4210
4211status_t AudioFlinger::RecordHandle::onTransact(
4212 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
4213{
4214 return BnAudioRecord::onTransact(code, data, reply, flags);
4215}
4216
4217// ----------------------------------------------------------------------------
4218
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004219AudioFlinger::RecordThread::RecordThread(const sp<AudioFlinger>& audioFlinger,
4220 AudioStreamIn *input,
4221 uint32_t sampleRate,
4222 uint32_t channels,
4223 int id,
4224 uint32_t device) :
4225 ThreadBase(audioFlinger, id, device),
4226 mInput(input), mTrack(NULL), mResampler(0), mRsmpOutBuffer(0), mRsmpInBuffer(0)
Mathias Agopian65ab4712010-07-14 17:59:35 -07004227{
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004228 mType = ThreadBase::RECORD;
Eric Laurentfeb0db62011-07-22 09:04:31 -07004229
4230 snprintf(mName, kNameLength, "AudioIn_%d", id);
4231
Dima Zavinfce7a472011-04-19 22:30:36 -07004232 mReqChannelCount = popcount(channels);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004233 mReqSampleRate = sampleRate;
4234 readInputParameters();
4235}
4236
4237
4238AudioFlinger::RecordThread::~RecordThread()
4239{
4240 delete[] mRsmpInBuffer;
4241 if (mResampler != 0) {
4242 delete mResampler;
4243 delete[] mRsmpOutBuffer;
4244 }
4245}
4246
4247void AudioFlinger::RecordThread::onFirstRef()
4248{
Eric Laurentfeb0db62011-07-22 09:04:31 -07004249 run(mName, PRIORITY_URGENT_AUDIO);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004250}
4251
Eric Laurentb8ba0a92011-08-07 16:32:26 -07004252status_t AudioFlinger::RecordThread::readyToRun()
4253{
4254 status_t status = initCheck();
4255 LOGW_IF(status != NO_ERROR,"RecordThread %p could not initialize", this);
4256 return status;
4257}
4258
Mathias Agopian65ab4712010-07-14 17:59:35 -07004259bool AudioFlinger::RecordThread::threadLoop()
4260{
4261 AudioBufferProvider::Buffer buffer;
4262 sp<RecordTrack> activeTrack;
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004263 Vector< sp<EffectChain> > effectChains;
Mathias Agopian65ab4712010-07-14 17:59:35 -07004264
Eric Laurent44d98482010-09-30 16:12:31 -07004265 nsecs_t lastWarning = 0;
4266
Eric Laurentfeb0db62011-07-22 09:04:31 -07004267 acquireWakeLock();
4268
Mathias Agopian65ab4712010-07-14 17:59:35 -07004269 // start recording
4270 while (!exitPending()) {
4271
4272 processConfigEvents();
4273
4274 { // scope for mLock
4275 Mutex::Autolock _l(mLock);
4276 checkForNewParameters_l();
4277 if (mActiveTrack == 0 && mConfigEvents.isEmpty()) {
4278 if (!mStandby) {
Dima Zavin799a70e2011-04-18 16:57:27 -07004279 mInput->stream->common.standby(&mInput->stream->common);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004280 mStandby = true;
4281 }
4282
4283 if (exitPending()) break;
4284
Eric Laurentfeb0db62011-07-22 09:04:31 -07004285 releaseWakeLock_l();
Steve Block3856b092011-10-20 11:56:00 +01004286 ALOGV("RecordThread: loop stopping");
Mathias Agopian65ab4712010-07-14 17:59:35 -07004287 // go to sleep
4288 mWaitWorkCV.wait(mLock);
Steve Block3856b092011-10-20 11:56:00 +01004289 ALOGV("RecordThread: loop starting");
Eric Laurentfeb0db62011-07-22 09:04:31 -07004290 acquireWakeLock_l();
Mathias Agopian65ab4712010-07-14 17:59:35 -07004291 continue;
4292 }
4293 if (mActiveTrack != 0) {
4294 if (mActiveTrack->mState == TrackBase::PAUSING) {
4295 if (!mStandby) {
Dima Zavin799a70e2011-04-18 16:57:27 -07004296 mInput->stream->common.standby(&mInput->stream->common);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004297 mStandby = true;
4298 }
4299 mActiveTrack.clear();
4300 mStartStopCond.broadcast();
4301 } else if (mActiveTrack->mState == TrackBase::RESUMING) {
4302 if (mReqChannelCount != mActiveTrack->channelCount()) {
4303 mActiveTrack.clear();
4304 mStartStopCond.broadcast();
4305 } else if (mBytesRead != 0) {
4306 // record start succeeds only if first read from audio input
4307 // succeeds
4308 if (mBytesRead > 0) {
4309 mActiveTrack->mState = TrackBase::ACTIVE;
4310 } else {
4311 mActiveTrack.clear();
4312 }
4313 mStartStopCond.broadcast();
4314 }
4315 mStandby = false;
4316 }
4317 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004318 lockEffectChains_l(effectChains);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004319 }
4320
4321 if (mActiveTrack != 0) {
4322 if (mActiveTrack->mState != TrackBase::ACTIVE &&
4323 mActiveTrack->mState != TrackBase::RESUMING) {
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004324 unlockEffectChains(effectChains);
4325 usleep(kRecordThreadSleepUs);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004326 continue;
4327 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004328 for (size_t i = 0; i < effectChains.size(); i ++) {
4329 effectChains[i]->process_l();
4330 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004331
Mathias Agopian65ab4712010-07-14 17:59:35 -07004332 buffer.frameCount = mFrameCount;
4333 if (LIKELY(mActiveTrack->getNextBuffer(&buffer) == NO_ERROR)) {
4334 size_t framesOut = buffer.frameCount;
4335 if (mResampler == 0) {
4336 // no resampling
4337 while (framesOut) {
4338 size_t framesIn = mFrameCount - mRsmpInIndex;
4339 if (framesIn) {
4340 int8_t *src = (int8_t *)mRsmpInBuffer + mRsmpInIndex * mFrameSize;
4341 int8_t *dst = buffer.i8 + (buffer.frameCount - framesOut) * mActiveTrack->mCblk->frameSize;
4342 if (framesIn > framesOut)
4343 framesIn = framesOut;
4344 mRsmpInIndex += framesIn;
4345 framesOut -= framesIn;
4346 if ((int)mChannelCount == mReqChannelCount ||
Dima Zavinfce7a472011-04-19 22:30:36 -07004347 mFormat != AUDIO_FORMAT_PCM_16_BIT) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07004348 memcpy(dst, src, framesIn * mFrameSize);
4349 } else {
4350 int16_t *src16 = (int16_t *)src;
4351 int16_t *dst16 = (int16_t *)dst;
4352 if (mChannelCount == 1) {
4353 while (framesIn--) {
4354 *dst16++ = *src16;
4355 *dst16++ = *src16++;
4356 }
4357 } else {
4358 while (framesIn--) {
4359 *dst16++ = (int16_t)(((int32_t)*src16 + (int32_t)*(src16 + 1)) >> 1);
4360 src16 += 2;
4361 }
4362 }
4363 }
4364 }
4365 if (framesOut && mFrameCount == mRsmpInIndex) {
4366 if (framesOut == mFrameCount &&
Dima Zavinfce7a472011-04-19 22:30:36 -07004367 ((int)mChannelCount == mReqChannelCount || mFormat != AUDIO_FORMAT_PCM_16_BIT)) {
Dima Zavin799a70e2011-04-18 16:57:27 -07004368 mBytesRead = mInput->stream->read(mInput->stream, buffer.raw, mInputBytes);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004369 framesOut = 0;
4370 } else {
Dima Zavin799a70e2011-04-18 16:57:27 -07004371 mBytesRead = mInput->stream->read(mInput->stream, mRsmpInBuffer, mInputBytes);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004372 mRsmpInIndex = 0;
4373 }
4374 if (mBytesRead < 0) {
4375 LOGE("Error reading audio input");
4376 if (mActiveTrack->mState == TrackBase::ACTIVE) {
4377 // Force input into standby so that it tries to
4378 // recover at next read attempt
Dima Zavin799a70e2011-04-18 16:57:27 -07004379 mInput->stream->common.standby(&mInput->stream->common);
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004380 usleep(kRecordThreadSleepUs);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004381 }
4382 mRsmpInIndex = mFrameCount;
4383 framesOut = 0;
4384 buffer.frameCount = 0;
4385 }
4386 }
4387 }
4388 } else {
4389 // resampling
4390
4391 memset(mRsmpOutBuffer, 0, framesOut * 2 * sizeof(int32_t));
4392 // alter output frame count as if we were expecting stereo samples
4393 if (mChannelCount == 1 && mReqChannelCount == 1) {
4394 framesOut >>= 1;
4395 }
4396 mResampler->resample(mRsmpOutBuffer, framesOut, this);
4397 // ditherAndClamp() works as long as all buffers returned by mActiveTrack->getNextBuffer()
4398 // are 32 bit aligned which should be always true.
4399 if (mChannelCount == 2 && mReqChannelCount == 1) {
4400 AudioMixer::ditherAndClamp(mRsmpOutBuffer, mRsmpOutBuffer, framesOut);
4401 // the resampler always outputs stereo samples: do post stereo to mono conversion
4402 int16_t *src = (int16_t *)mRsmpOutBuffer;
4403 int16_t *dst = buffer.i16;
4404 while (framesOut--) {
4405 *dst++ = (int16_t)(((int32_t)*src + (int32_t)*(src + 1)) >> 1);
4406 src += 2;
4407 }
4408 } else {
4409 AudioMixer::ditherAndClamp((int32_t *)buffer.raw, mRsmpOutBuffer, framesOut);
4410 }
4411
4412 }
4413 mActiveTrack->releaseBuffer(&buffer);
4414 mActiveTrack->overflow();
4415 }
4416 // client isn't retrieving buffers fast enough
4417 else {
Eric Laurent44d98482010-09-30 16:12:31 -07004418 if (!mActiveTrack->setOverflow()) {
4419 nsecs_t now = systemTime();
Glenn Kasten7dede872011-12-13 11:04:14 -08004420 if ((now - lastWarning) > kWarningThrottleNs) {
Eric Laurent44d98482010-09-30 16:12:31 -07004421 LOGW("RecordThread: buffer overflow");
4422 lastWarning = now;
4423 }
4424 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07004425 // Release the processor for a while before asking for a new buffer.
4426 // This will give the application more chance to read from the buffer and
4427 // clear the overflow.
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004428 usleep(kRecordThreadSleepUs);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004429 }
4430 }
Eric Laurentec437d82011-07-26 20:54:46 -07004431 // enable changes in effect chain
4432 unlockEffectChains(effectChains);
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004433 effectChains.clear();
Mathias Agopian65ab4712010-07-14 17:59:35 -07004434 }
4435
4436 if (!mStandby) {
Dima Zavin799a70e2011-04-18 16:57:27 -07004437 mInput->stream->common.standby(&mInput->stream->common);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004438 }
4439 mActiveTrack.clear();
4440
4441 mStartStopCond.broadcast();
4442
Eric Laurentfeb0db62011-07-22 09:04:31 -07004443 releaseWakeLock();
4444
Steve Block3856b092011-10-20 11:56:00 +01004445 ALOGV("RecordThread %p exiting", this);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004446 return false;
4447}
4448
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004449
4450sp<AudioFlinger::RecordThread::RecordTrack> AudioFlinger::RecordThread::createRecordTrack_l(
4451 const sp<AudioFlinger::Client>& client,
4452 uint32_t sampleRate,
4453 int format,
4454 int channelMask,
4455 int frameCount,
4456 uint32_t flags,
4457 int sessionId,
4458 status_t *status)
4459{
4460 sp<RecordTrack> track;
4461 status_t lStatus;
4462
4463 lStatus = initCheck();
4464 if (lStatus != NO_ERROR) {
4465 LOGE("Audio driver not initialized.");
4466 goto Exit;
4467 }
4468
4469 { // scope for mLock
4470 Mutex::Autolock _l(mLock);
4471
4472 track = new RecordTrack(this, client, sampleRate,
4473 format, channelMask, frameCount, flags, sessionId);
4474
4475 if (track->getCblk() == NULL) {
4476 lStatus = NO_MEMORY;
4477 goto Exit;
4478 }
4479
4480 mTrack = track.get();
Eric Laurent59bd0da2011-08-01 09:52:20 -07004481 // disable AEC and NS if the device is a BT SCO headset supporting those pre processings
4482 bool suspend = audio_is_bluetooth_sco_device(
Eric Laurentbee53372011-08-29 12:42:48 -07004483 (audio_devices_t)(mDevice & AUDIO_DEVICE_IN_ALL)) && mAudioFlinger->btNrecIsOff();
Eric Laurent59bd0da2011-08-01 09:52:20 -07004484 setEffectSuspended_l(FX_IID_AEC, suspend, sessionId);
4485 setEffectSuspended_l(FX_IID_NS, suspend, sessionId);
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004486 }
4487 lStatus = NO_ERROR;
4488
4489Exit:
4490 if (status) {
4491 *status = lStatus;
4492 }
4493 return track;
4494}
4495
Mathias Agopian65ab4712010-07-14 17:59:35 -07004496status_t AudioFlinger::RecordThread::start(RecordThread::RecordTrack* recordTrack)
4497{
Steve Block3856b092011-10-20 11:56:00 +01004498 ALOGV("RecordThread::start");
Mathias Agopian65ab4712010-07-14 17:59:35 -07004499 sp <ThreadBase> strongMe = this;
4500 status_t status = NO_ERROR;
4501 {
4502 AutoMutex lock(&mLock);
4503 if (mActiveTrack != 0) {
4504 if (recordTrack != mActiveTrack.get()) {
4505 status = -EBUSY;
4506 } else if (mActiveTrack->mState == TrackBase::PAUSING) {
4507 mActiveTrack->mState = TrackBase::ACTIVE;
4508 }
4509 return status;
4510 }
4511
4512 recordTrack->mState = TrackBase::IDLE;
4513 mActiveTrack = recordTrack;
4514 mLock.unlock();
4515 status_t status = AudioSystem::startInput(mId);
4516 mLock.lock();
4517 if (status != NO_ERROR) {
4518 mActiveTrack.clear();
4519 return status;
4520 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07004521 mRsmpInIndex = mFrameCount;
4522 mBytesRead = 0;
Eric Laurent243f5f92011-02-28 16:52:51 -08004523 if (mResampler != NULL) {
4524 mResampler->reset();
4525 }
4526 mActiveTrack->mState = TrackBase::RESUMING;
Mathias Agopian65ab4712010-07-14 17:59:35 -07004527 // signal thread to start
Steve Block3856b092011-10-20 11:56:00 +01004528 ALOGV("Signal record thread");
Mathias Agopian65ab4712010-07-14 17:59:35 -07004529 mWaitWorkCV.signal();
4530 // do not wait for mStartStopCond if exiting
4531 if (mExiting) {
4532 mActiveTrack.clear();
4533 status = INVALID_OPERATION;
4534 goto startError;
4535 }
4536 mStartStopCond.wait(mLock);
4537 if (mActiveTrack == 0) {
Steve Block3856b092011-10-20 11:56:00 +01004538 ALOGV("Record failed to start");
Mathias Agopian65ab4712010-07-14 17:59:35 -07004539 status = BAD_VALUE;
4540 goto startError;
4541 }
Steve Block3856b092011-10-20 11:56:00 +01004542 ALOGV("Record started OK");
Mathias Agopian65ab4712010-07-14 17:59:35 -07004543 return status;
4544 }
4545startError:
4546 AudioSystem::stopInput(mId);
4547 return status;
4548}
4549
4550void AudioFlinger::RecordThread::stop(RecordThread::RecordTrack* recordTrack) {
Steve Block3856b092011-10-20 11:56:00 +01004551 ALOGV("RecordThread::stop");
Mathias Agopian65ab4712010-07-14 17:59:35 -07004552 sp <ThreadBase> strongMe = this;
4553 {
4554 AutoMutex lock(&mLock);
4555 if (mActiveTrack != 0 && recordTrack == mActiveTrack.get()) {
4556 mActiveTrack->mState = TrackBase::PAUSING;
4557 // do not wait for mStartStopCond if exiting
4558 if (mExiting) {
4559 return;
4560 }
4561 mStartStopCond.wait(mLock);
4562 // if we have been restarted, recordTrack == mActiveTrack.get() here
4563 if (mActiveTrack == 0 || recordTrack != mActiveTrack.get()) {
4564 mLock.unlock();
4565 AudioSystem::stopInput(mId);
4566 mLock.lock();
Steve Block3856b092011-10-20 11:56:00 +01004567 ALOGV("Record stopped OK");
Mathias Agopian65ab4712010-07-14 17:59:35 -07004568 }
4569 }
4570 }
4571}
4572
4573status_t AudioFlinger::RecordThread::dump(int fd, const Vector<String16>& args)
4574{
4575 const size_t SIZE = 256;
4576 char buffer[SIZE];
4577 String8 result;
4578 pid_t pid = 0;
4579
4580 snprintf(buffer, SIZE, "\nInput thread %p internals\n", this);
4581 result.append(buffer);
4582
4583 if (mActiveTrack != 0) {
4584 result.append("Active Track:\n");
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07004585 result.append(" Clien Fmt Chn mask Session Buf S SRate Serv User\n");
Mathias Agopian65ab4712010-07-14 17:59:35 -07004586 mActiveTrack->dump(buffer, SIZE);
4587 result.append(buffer);
4588
4589 snprintf(buffer, SIZE, "In index: %d\n", mRsmpInIndex);
4590 result.append(buffer);
4591 snprintf(buffer, SIZE, "In size: %d\n", mInputBytes);
4592 result.append(buffer);
4593 snprintf(buffer, SIZE, "Resampling: %d\n", (mResampler != 0));
4594 result.append(buffer);
4595 snprintf(buffer, SIZE, "Out channel count: %d\n", mReqChannelCount);
4596 result.append(buffer);
4597 snprintf(buffer, SIZE, "Out sample rate: %d\n", mReqSampleRate);
4598 result.append(buffer);
4599
4600
4601 } else {
4602 result.append("No record client\n");
4603 }
4604 write(fd, result.string(), result.size());
4605
4606 dumpBase(fd, args);
Eric Laurent1d2bff02011-07-24 17:49:51 -07004607 dumpEffectChains(fd, args);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004608
4609 return NO_ERROR;
4610}
4611
4612status_t AudioFlinger::RecordThread::getNextBuffer(AudioBufferProvider::Buffer* buffer)
4613{
4614 size_t framesReq = buffer->frameCount;
4615 size_t framesReady = mFrameCount - mRsmpInIndex;
4616 int channelCount;
4617
4618 if (framesReady == 0) {
Dima Zavin799a70e2011-04-18 16:57:27 -07004619 mBytesRead = mInput->stream->read(mInput->stream, mRsmpInBuffer, mInputBytes);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004620 if (mBytesRead < 0) {
4621 LOGE("RecordThread::getNextBuffer() Error reading audio input");
4622 if (mActiveTrack->mState == TrackBase::ACTIVE) {
4623 // Force input into standby so that it tries to
4624 // recover at next read attempt
Dima Zavin799a70e2011-04-18 16:57:27 -07004625 mInput->stream->common.standby(&mInput->stream->common);
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004626 usleep(kRecordThreadSleepUs);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004627 }
4628 buffer->raw = 0;
4629 buffer->frameCount = 0;
4630 return NOT_ENOUGH_DATA;
4631 }
4632 mRsmpInIndex = 0;
4633 framesReady = mFrameCount;
4634 }
4635
4636 if (framesReq > framesReady) {
4637 framesReq = framesReady;
4638 }
4639
4640 if (mChannelCount == 1 && mReqChannelCount == 2) {
4641 channelCount = 1;
4642 } else {
4643 channelCount = 2;
4644 }
4645 buffer->raw = mRsmpInBuffer + mRsmpInIndex * channelCount;
4646 buffer->frameCount = framesReq;
4647 return NO_ERROR;
4648}
4649
4650void AudioFlinger::RecordThread::releaseBuffer(AudioBufferProvider::Buffer* buffer)
4651{
4652 mRsmpInIndex += buffer->frameCount;
4653 buffer->frameCount = 0;
4654}
4655
4656bool AudioFlinger::RecordThread::checkForNewParameters_l()
4657{
4658 bool reconfig = false;
4659
4660 while (!mNewParameters.isEmpty()) {
4661 status_t status = NO_ERROR;
4662 String8 keyValuePair = mNewParameters[0];
4663 AudioParameter param = AudioParameter(keyValuePair);
4664 int value;
4665 int reqFormat = mFormat;
4666 int reqSamplingRate = mReqSampleRate;
4667 int reqChannelCount = mReqChannelCount;
4668
4669 if (param.getInt(String8(AudioParameter::keySamplingRate), value) == NO_ERROR) {
4670 reqSamplingRate = value;
4671 reconfig = true;
4672 }
4673 if (param.getInt(String8(AudioParameter::keyFormat), value) == NO_ERROR) {
4674 reqFormat = value;
4675 reconfig = true;
4676 }
4677 if (param.getInt(String8(AudioParameter::keyChannels), value) == NO_ERROR) {
Dima Zavinfce7a472011-04-19 22:30:36 -07004678 reqChannelCount = popcount(value);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004679 reconfig = true;
4680 }
4681 if (param.getInt(String8(AudioParameter::keyFrameCount), value) == NO_ERROR) {
4682 // do not accept frame count changes if tracks are open as the track buffer
4683 // size depends on frame count and correct behavior would not be garantied
4684 // if frame count is changed after track creation
4685 if (mActiveTrack != 0) {
4686 status = INVALID_OPERATION;
4687 } else {
4688 reconfig = true;
4689 }
4690 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004691 if (param.getInt(String8(AudioParameter::keyRouting), value) == NO_ERROR) {
4692 // forward device change to effects that have requested to be
4693 // aware of attached audio device.
4694 for (size_t i = 0; i < mEffectChains.size(); i++) {
4695 mEffectChains[i]->setDevice_l(value);
4696 }
4697 // store input device and output device but do not forward output device to audio HAL.
4698 // Note that status is ignored by the caller for output device
4699 // (see AudioFlinger::setParameters()
4700 if (value & AUDIO_DEVICE_OUT_ALL) {
4701 mDevice &= (uint32_t)~(value & AUDIO_DEVICE_OUT_ALL);
4702 status = BAD_VALUE;
4703 } else {
4704 mDevice &= (uint32_t)~(value & AUDIO_DEVICE_IN_ALL);
Eric Laurent59bd0da2011-08-01 09:52:20 -07004705 // disable AEC and NS if the device is a BT SCO headset supporting those pre processings
4706 if (mTrack != NULL) {
4707 bool suspend = audio_is_bluetooth_sco_device(
Eric Laurentbee53372011-08-29 12:42:48 -07004708 (audio_devices_t)value) && mAudioFlinger->btNrecIsOff();
Eric Laurent59bd0da2011-08-01 09:52:20 -07004709 setEffectSuspended_l(FX_IID_AEC, suspend, mTrack->sessionId());
4710 setEffectSuspended_l(FX_IID_NS, suspend, mTrack->sessionId());
4711 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004712 }
4713 mDevice |= (uint32_t)value;
4714 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07004715 if (status == NO_ERROR) {
Dima Zavin799a70e2011-04-18 16:57:27 -07004716 status = mInput->stream->common.set_parameters(&mInput->stream->common, keyValuePair.string());
Mathias Agopian65ab4712010-07-14 17:59:35 -07004717 if (status == INVALID_OPERATION) {
Dima Zavin799a70e2011-04-18 16:57:27 -07004718 mInput->stream->common.standby(&mInput->stream->common);
4719 status = mInput->stream->common.set_parameters(&mInput->stream->common, keyValuePair.string());
Mathias Agopian65ab4712010-07-14 17:59:35 -07004720 }
4721 if (reconfig) {
4722 if (status == BAD_VALUE &&
Dima Zavin799a70e2011-04-18 16:57:27 -07004723 reqFormat == mInput->stream->common.get_format(&mInput->stream->common) &&
Dima Zavinfce7a472011-04-19 22:30:36 -07004724 reqFormat == AUDIO_FORMAT_PCM_16_BIT &&
Dima Zavin799a70e2011-04-18 16:57:27 -07004725 ((int)mInput->stream->common.get_sample_rate(&mInput->stream->common) <= (2 * reqSamplingRate)) &&
4726 (popcount(mInput->stream->common.get_channels(&mInput->stream->common)) < 3) &&
Dima Zavinfce7a472011-04-19 22:30:36 -07004727 (reqChannelCount < 3)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07004728 status = NO_ERROR;
4729 }
4730 if (status == NO_ERROR) {
4731 readInputParameters();
4732 sendConfigEvent_l(AudioSystem::INPUT_CONFIG_CHANGED);
4733 }
4734 }
4735 }
4736
4737 mNewParameters.removeAt(0);
4738
4739 mParamStatus = status;
4740 mParamCond.signal();
Eric Laurent60cd0a02011-09-13 11:40:21 -07004741 // wait for condition with time out in case the thread calling ThreadBase::setParameters()
4742 // already timed out waiting for the status and will never signal the condition.
Glenn Kasten7dede872011-12-13 11:04:14 -08004743 mWaitWorkCV.waitRelative(mLock, kSetParametersTimeoutNs);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004744 }
4745 return reconfig;
4746}
4747
4748String8 AudioFlinger::RecordThread::getParameters(const String8& keys)
4749{
Dima Zavinfce7a472011-04-19 22:30:36 -07004750 char *s;
Eric Laurentb8ba0a92011-08-07 16:32:26 -07004751 String8 out_s8 = String8();
4752
4753 Mutex::Autolock _l(mLock);
4754 if (initCheck() != NO_ERROR) {
4755 return out_s8;
4756 }
Dima Zavinfce7a472011-04-19 22:30:36 -07004757
Dima Zavin799a70e2011-04-18 16:57:27 -07004758 s = mInput->stream->common.get_parameters(&mInput->stream->common, keys.string());
Dima Zavinfce7a472011-04-19 22:30:36 -07004759 out_s8 = String8(s);
4760 free(s);
4761 return out_s8;
Mathias Agopian65ab4712010-07-14 17:59:35 -07004762}
4763
4764void AudioFlinger::RecordThread::audioConfigChanged_l(int event, int param) {
4765 AudioSystem::OutputDescriptor desc;
4766 void *param2 = 0;
4767
4768 switch (event) {
4769 case AudioSystem::INPUT_OPENED:
4770 case AudioSystem::INPUT_CONFIG_CHANGED:
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07004771 desc.channels = mChannelMask;
Mathias Agopian65ab4712010-07-14 17:59:35 -07004772 desc.samplingRate = mSampleRate;
4773 desc.format = mFormat;
4774 desc.frameCount = mFrameCount;
4775 desc.latency = 0;
4776 param2 = &desc;
4777 break;
4778
4779 case AudioSystem::INPUT_CLOSED:
4780 default:
4781 break;
4782 }
4783 mAudioFlinger->audioConfigChanged_l(event, mId, param2);
4784}
4785
4786void AudioFlinger::RecordThread::readInputParameters()
4787{
4788 if (mRsmpInBuffer) delete mRsmpInBuffer;
4789 if (mRsmpOutBuffer) delete mRsmpOutBuffer;
4790 if (mResampler) delete mResampler;
4791 mResampler = 0;
4792
Dima Zavin799a70e2011-04-18 16:57:27 -07004793 mSampleRate = mInput->stream->common.get_sample_rate(&mInput->stream->common);
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -07004794 mChannelMask = mInput->stream->common.get_channels(&mInput->stream->common);
4795 mChannelCount = (uint16_t)popcount(mChannelMask);
Dima Zavin799a70e2011-04-18 16:57:27 -07004796 mFormat = mInput->stream->common.get_format(&mInput->stream->common);
4797 mFrameSize = (uint16_t)audio_stream_frame_size(&mInput->stream->common);
4798 mInputBytes = mInput->stream->common.get_buffer_size(&mInput->stream->common);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004799 mFrameCount = mInputBytes / mFrameSize;
4800 mRsmpInBuffer = new int16_t[mFrameCount * mChannelCount];
4801
4802 if (mSampleRate != mReqSampleRate && mChannelCount < 3 && mReqChannelCount < 3)
4803 {
4804 int channelCount;
4805 // optmization: if mono to mono, use the resampler in stereo to stereo mode to avoid
4806 // stereo to mono post process as the resampler always outputs stereo.
4807 if (mChannelCount == 1 && mReqChannelCount == 2) {
4808 channelCount = 1;
4809 } else {
4810 channelCount = 2;
4811 }
4812 mResampler = AudioResampler::create(16, channelCount, mReqSampleRate);
4813 mResampler->setSampleRate(mSampleRate);
4814 mResampler->setVolume(AudioMixer::UNITY_GAIN, AudioMixer::UNITY_GAIN);
4815 mRsmpOutBuffer = new int32_t[mFrameCount * 2];
4816
4817 // optmization: if mono to mono, alter input frame count as if we were inputing stereo samples
4818 if (mChannelCount == 1 && mReqChannelCount == 1) {
4819 mFrameCount >>= 1;
4820 }
4821
4822 }
4823 mRsmpInIndex = mFrameCount;
4824}
4825
4826unsigned int AudioFlinger::RecordThread::getInputFramesLost()
4827{
Eric Laurentb8ba0a92011-08-07 16:32:26 -07004828 Mutex::Autolock _l(mLock);
4829 if (initCheck() != NO_ERROR) {
4830 return 0;
4831 }
4832
Dima Zavin799a70e2011-04-18 16:57:27 -07004833 return mInput->stream->get_input_frames_lost(mInput->stream);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004834}
4835
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004836uint32_t AudioFlinger::RecordThread::hasAudioSession(int sessionId)
4837{
4838 Mutex::Autolock _l(mLock);
4839 uint32_t result = 0;
4840 if (getEffectChain_l(sessionId) != 0) {
4841 result = EFFECT_SESSION;
4842 }
4843
4844 if (mTrack != NULL && sessionId == mTrack->sessionId()) {
4845 result |= TRACK_SESSION;
4846 }
4847
4848 return result;
4849}
4850
Eric Laurent59bd0da2011-08-01 09:52:20 -07004851AudioFlinger::RecordThread::RecordTrack* AudioFlinger::RecordThread::track()
4852{
4853 Mutex::Autolock _l(mLock);
4854 return mTrack;
4855}
4856
Eric Laurentb8ba0a92011-08-07 16:32:26 -07004857AudioFlinger::AudioStreamIn* AudioFlinger::RecordThread::getInput()
4858{
4859 Mutex::Autolock _l(mLock);
4860 return mInput;
4861}
4862
4863AudioFlinger::AudioStreamIn* AudioFlinger::RecordThread::clearInput()
4864{
4865 Mutex::Autolock _l(mLock);
4866 AudioStreamIn *input = mInput;
4867 mInput = NULL;
4868 return input;
4869}
4870
4871// this method must always be called either with ThreadBase mLock held or inside the thread loop
4872audio_stream_t* AudioFlinger::RecordThread::stream()
4873{
4874 if (mInput == NULL) {
4875 return NULL;
4876 }
4877 return &mInput->stream->common;
4878}
4879
4880
Mathias Agopian65ab4712010-07-14 17:59:35 -07004881// ----------------------------------------------------------------------------
4882
4883int AudioFlinger::openOutput(uint32_t *pDevices,
4884 uint32_t *pSamplingRate,
4885 uint32_t *pFormat,
4886 uint32_t *pChannels,
4887 uint32_t *pLatencyMs,
4888 uint32_t flags)
4889{
4890 status_t status;
4891 PlaybackThread *thread = NULL;
4892 mHardwareStatus = AUDIO_HW_OUTPUT_OPEN;
4893 uint32_t samplingRate = pSamplingRate ? *pSamplingRate : 0;
4894 uint32_t format = pFormat ? *pFormat : 0;
4895 uint32_t channels = pChannels ? *pChannels : 0;
4896 uint32_t latency = pLatencyMs ? *pLatencyMs : 0;
Dima Zavin799a70e2011-04-18 16:57:27 -07004897 audio_stream_out_t *outStream;
4898 audio_hw_device_t *outHwDev;
Mathias Agopian65ab4712010-07-14 17:59:35 -07004899
Steve Block3856b092011-10-20 11:56:00 +01004900 ALOGV("openOutput(), Device %x, SamplingRate %d, Format %d, Channels %x, flags %x",
Mathias Agopian65ab4712010-07-14 17:59:35 -07004901 pDevices ? *pDevices : 0,
4902 samplingRate,
4903 format,
4904 channels,
4905 flags);
4906
4907 if (pDevices == NULL || *pDevices == 0) {
4908 return 0;
4909 }
Dima Zavin799a70e2011-04-18 16:57:27 -07004910
Mathias Agopian65ab4712010-07-14 17:59:35 -07004911 Mutex::Autolock _l(mLock);
4912
Dima Zavin799a70e2011-04-18 16:57:27 -07004913 outHwDev = findSuitableHwDev_l(*pDevices);
4914 if (outHwDev == NULL)
4915 return 0;
4916
4917 status = outHwDev->open_output_stream(outHwDev, *pDevices, (int *)&format,
4918 &channels, &samplingRate, &outStream);
Steve Block3856b092011-10-20 11:56:00 +01004919 ALOGV("openOutput() openOutputStream returned output %p, SamplingRate %d, Format %d, Channels %x, status %d",
Dima Zavin799a70e2011-04-18 16:57:27 -07004920 outStream,
Mathias Agopian65ab4712010-07-14 17:59:35 -07004921 samplingRate,
4922 format,
4923 channels,
4924 status);
4925
4926 mHardwareStatus = AUDIO_HW_IDLE;
Dima Zavin799a70e2011-04-18 16:57:27 -07004927 if (outStream != NULL) {
4928 AudioStreamOut *output = new AudioStreamOut(outHwDev, outStream);
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004929 int id = nextUniqueId();
Dima Zavin799a70e2011-04-18 16:57:27 -07004930
Dima Zavinfce7a472011-04-19 22:30:36 -07004931 if ((flags & AUDIO_POLICY_OUTPUT_FLAG_DIRECT) ||
4932 (format != AUDIO_FORMAT_PCM_16_BIT) ||
4933 (channels != AUDIO_CHANNEL_OUT_STEREO)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07004934 thread = new DirectOutputThread(this, output, id, *pDevices);
Steve Block3856b092011-10-20 11:56:00 +01004935 ALOGV("openOutput() created direct output: ID %d thread %p", id, thread);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004936 } else {
4937 thread = new MixerThread(this, output, id, *pDevices);
Steve Block3856b092011-10-20 11:56:00 +01004938 ALOGV("openOutput() created mixer output: ID %d thread %p", id, thread);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004939 }
4940 mPlaybackThreads.add(id, thread);
4941
4942 if (pSamplingRate) *pSamplingRate = samplingRate;
4943 if (pFormat) *pFormat = format;
4944 if (pChannels) *pChannels = channels;
4945 if (pLatencyMs) *pLatencyMs = thread->latency();
4946
4947 // notify client processes of the new output creation
4948 thread->audioConfigChanged_l(AudioSystem::OUTPUT_OPENED);
4949 return id;
4950 }
4951
4952 return 0;
4953}
4954
4955int AudioFlinger::openDuplicateOutput(int output1, int output2)
4956{
4957 Mutex::Autolock _l(mLock);
4958 MixerThread *thread1 = checkMixerThread_l(output1);
4959 MixerThread *thread2 = checkMixerThread_l(output2);
4960
4961 if (thread1 == NULL || thread2 == NULL) {
4962 LOGW("openDuplicateOutput() wrong output mixer type for output %d or %d", output1, output2);
4963 return 0;
4964 }
4965
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004966 int id = nextUniqueId();
Mathias Agopian65ab4712010-07-14 17:59:35 -07004967 DuplicatingThread *thread = new DuplicatingThread(this, thread1, id);
4968 thread->addOutputTrack(thread2);
4969 mPlaybackThreads.add(id, thread);
4970 // notify client processes of the new output creation
4971 thread->audioConfigChanged_l(AudioSystem::OUTPUT_OPENED);
4972 return id;
4973}
4974
4975status_t AudioFlinger::closeOutput(int output)
4976{
4977 // keep strong reference on the playback thread so that
4978 // it is not destroyed while exit() is executed
4979 sp <PlaybackThread> thread;
4980 {
4981 Mutex::Autolock _l(mLock);
4982 thread = checkPlaybackThread_l(output);
4983 if (thread == NULL) {
4984 return BAD_VALUE;
4985 }
4986
Steve Block3856b092011-10-20 11:56:00 +01004987 ALOGV("closeOutput() %d", output);
Mathias Agopian65ab4712010-07-14 17:59:35 -07004988
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004989 if (thread->type() == ThreadBase::MIXER) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07004990 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
Eric Laurent7c7f10b2011-06-17 21:29:58 -07004991 if (mPlaybackThreads.valueAt(i)->type() == ThreadBase::DUPLICATING) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07004992 DuplicatingThread *dupThread = (DuplicatingThread *)mPlaybackThreads.valueAt(i).get();
4993 dupThread->removeOutputTrack((MixerThread *)thread.get());
4994 }
4995 }
4996 }
4997 void *param2 = 0;
4998 audioConfigChanged_l(AudioSystem::OUTPUT_CLOSED, output, param2);
4999 mPlaybackThreads.removeItem(output);
5000 }
5001 thread->exit();
5002
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005003 if (thread->type() != ThreadBase::DUPLICATING) {
Eric Laurentb8ba0a92011-08-07 16:32:26 -07005004 AudioStreamOut *out = thread->clearOutput();
5005 // from now on thread->mOutput is NULL
Dima Zavin799a70e2011-04-18 16:57:27 -07005006 out->hwDev->close_output_stream(out->hwDev, out->stream);
5007 delete out;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005008 }
5009 return NO_ERROR;
5010}
5011
5012status_t AudioFlinger::suspendOutput(int output)
5013{
5014 Mutex::Autolock _l(mLock);
5015 PlaybackThread *thread = checkPlaybackThread_l(output);
5016
5017 if (thread == NULL) {
5018 return BAD_VALUE;
5019 }
5020
Steve Block3856b092011-10-20 11:56:00 +01005021 ALOGV("suspendOutput() %d", output);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005022 thread->suspend();
5023
5024 return NO_ERROR;
5025}
5026
5027status_t AudioFlinger::restoreOutput(int output)
5028{
5029 Mutex::Autolock _l(mLock);
5030 PlaybackThread *thread = checkPlaybackThread_l(output);
5031
5032 if (thread == NULL) {
5033 return BAD_VALUE;
5034 }
5035
Steve Block3856b092011-10-20 11:56:00 +01005036 ALOGV("restoreOutput() %d", output);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005037
5038 thread->restore();
5039
5040 return NO_ERROR;
5041}
5042
5043int AudioFlinger::openInput(uint32_t *pDevices,
5044 uint32_t *pSamplingRate,
5045 uint32_t *pFormat,
5046 uint32_t *pChannels,
5047 uint32_t acoustics)
5048{
5049 status_t status;
5050 RecordThread *thread = NULL;
5051 uint32_t samplingRate = pSamplingRate ? *pSamplingRate : 0;
5052 uint32_t format = pFormat ? *pFormat : 0;
5053 uint32_t channels = pChannels ? *pChannels : 0;
5054 uint32_t reqSamplingRate = samplingRate;
5055 uint32_t reqFormat = format;
5056 uint32_t reqChannels = channels;
Dima Zavin799a70e2011-04-18 16:57:27 -07005057 audio_stream_in_t *inStream;
5058 audio_hw_device_t *inHwDev;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005059
5060 if (pDevices == NULL || *pDevices == 0) {
5061 return 0;
5062 }
Dima Zavin799a70e2011-04-18 16:57:27 -07005063
Mathias Agopian65ab4712010-07-14 17:59:35 -07005064 Mutex::Autolock _l(mLock);
5065
Dima Zavin799a70e2011-04-18 16:57:27 -07005066 inHwDev = findSuitableHwDev_l(*pDevices);
5067 if (inHwDev == NULL)
5068 return 0;
5069
5070 status = inHwDev->open_input_stream(inHwDev, *pDevices, (int *)&format,
5071 &channels, &samplingRate,
Dima Zavinfce7a472011-04-19 22:30:36 -07005072 (audio_in_acoustics_t)acoustics,
Dima Zavin799a70e2011-04-18 16:57:27 -07005073 &inStream);
Steve Block3856b092011-10-20 11:56:00 +01005074 ALOGV("openInput() openInputStream returned input %p, SamplingRate %d, Format %d, Channels %x, acoustics %x, status %d",
Dima Zavin799a70e2011-04-18 16:57:27 -07005075 inStream,
Mathias Agopian65ab4712010-07-14 17:59:35 -07005076 samplingRate,
5077 format,
5078 channels,
5079 acoustics,
5080 status);
5081
5082 // If the input could not be opened with the requested parameters and we can handle the conversion internally,
5083 // try to open again with the proposed parameters. The AudioFlinger can resample the input and do mono to stereo
5084 // or stereo to mono conversions on 16 bit PCM inputs.
Dima Zavin799a70e2011-04-18 16:57:27 -07005085 if (inStream == NULL && status == BAD_VALUE &&
Dima Zavinfce7a472011-04-19 22:30:36 -07005086 reqFormat == format && format == AUDIO_FORMAT_PCM_16_BIT &&
Mathias Agopian65ab4712010-07-14 17:59:35 -07005087 (samplingRate <= 2 * reqSamplingRate) &&
Dima Zavinfce7a472011-04-19 22:30:36 -07005088 (popcount(channels) < 3) && (popcount(reqChannels) < 3)) {
Steve Block3856b092011-10-20 11:56:00 +01005089 ALOGV("openInput() reopening with proposed sampling rate and channels");
Dima Zavin799a70e2011-04-18 16:57:27 -07005090 status = inHwDev->open_input_stream(inHwDev, *pDevices, (int *)&format,
5091 &channels, &samplingRate,
Dima Zavinfce7a472011-04-19 22:30:36 -07005092 (audio_in_acoustics_t)acoustics,
Dima Zavin799a70e2011-04-18 16:57:27 -07005093 &inStream);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005094 }
5095
Dima Zavin799a70e2011-04-18 16:57:27 -07005096 if (inStream != NULL) {
5097 AudioStreamIn *input = new AudioStreamIn(inHwDev, inStream);
5098
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005099 int id = nextUniqueId();
5100 // Start record thread
5101 // RecorThread require both input and output device indication to forward to audio
5102 // pre processing modules
5103 uint32_t device = (*pDevices) | primaryOutputDevice_l();
5104 thread = new RecordThread(this,
5105 input,
5106 reqSamplingRate,
5107 reqChannels,
5108 id,
5109 device);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005110 mRecordThreads.add(id, thread);
Steve Block3856b092011-10-20 11:56:00 +01005111 ALOGV("openInput() created record thread: ID %d thread %p", id, thread);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005112 if (pSamplingRate) *pSamplingRate = reqSamplingRate;
5113 if (pFormat) *pFormat = format;
5114 if (pChannels) *pChannels = reqChannels;
5115
Dima Zavin799a70e2011-04-18 16:57:27 -07005116 input->stream->common.standby(&input->stream->common);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005117
5118 // notify client processes of the new input creation
5119 thread->audioConfigChanged_l(AudioSystem::INPUT_OPENED);
5120 return id;
5121 }
5122
5123 return 0;
5124}
5125
5126status_t AudioFlinger::closeInput(int input)
5127{
5128 // keep strong reference on the record thread so that
5129 // it is not destroyed while exit() is executed
5130 sp <RecordThread> thread;
5131 {
5132 Mutex::Autolock _l(mLock);
5133 thread = checkRecordThread_l(input);
5134 if (thread == NULL) {
5135 return BAD_VALUE;
5136 }
5137
Steve Block3856b092011-10-20 11:56:00 +01005138 ALOGV("closeInput() %d", input);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005139 void *param2 = 0;
5140 audioConfigChanged_l(AudioSystem::INPUT_CLOSED, input, param2);
5141 mRecordThreads.removeItem(input);
5142 }
5143 thread->exit();
5144
Eric Laurentb8ba0a92011-08-07 16:32:26 -07005145 AudioStreamIn *in = thread->clearInput();
5146 // from now on thread->mInput is NULL
Dima Zavin799a70e2011-04-18 16:57:27 -07005147 in->hwDev->close_input_stream(in->hwDev, in->stream);
5148 delete in;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005149
5150 return NO_ERROR;
5151}
5152
5153status_t AudioFlinger::setStreamOutput(uint32_t stream, int output)
5154{
5155 Mutex::Autolock _l(mLock);
5156 MixerThread *dstThread = checkMixerThread_l(output);
5157 if (dstThread == NULL) {
5158 LOGW("setStreamOutput() bad output id %d", output);
5159 return BAD_VALUE;
5160 }
5161
Steve Block3856b092011-10-20 11:56:00 +01005162 ALOGV("setStreamOutput() stream %d to output %d", stream, output);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005163 audioConfigChanged_l(AudioSystem::STREAM_CONFIG_CHANGED, output, &stream);
5164
Eric Laurent9f6530f2011-08-30 10:18:54 -07005165 dstThread->setStreamValid(stream, true);
5166
Mathias Agopian65ab4712010-07-14 17:59:35 -07005167 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
5168 PlaybackThread *thread = mPlaybackThreads.valueAt(i).get();
5169 if (thread != dstThread &&
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005170 thread->type() != ThreadBase::DIRECT) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07005171 MixerThread *srcThread = (MixerThread *)thread;
Eric Laurent9f6530f2011-08-30 10:18:54 -07005172 srcThread->setStreamValid(stream, false);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005173 srcThread->invalidateTracks(stream);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005174 }
Eric Laurentde070132010-07-13 04:45:46 -07005175 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07005176
5177 return NO_ERROR;
5178}
5179
5180
5181int AudioFlinger::newAudioSessionId()
5182{
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005183 return nextUniqueId();
Mathias Agopian65ab4712010-07-14 17:59:35 -07005184}
5185
Marco Nelissen3a34bef2011-08-02 13:33:41 -07005186void AudioFlinger::acquireAudioSessionId(int audioSession)
5187{
5188 Mutex::Autolock _l(mLock);
5189 int caller = IPCThreadState::self()->getCallingPid();
Steve Block3856b092011-10-20 11:56:00 +01005190 ALOGV("acquiring %d from %d", audioSession, caller);
Marco Nelissen3a34bef2011-08-02 13:33:41 -07005191 int num = mAudioSessionRefs.size();
5192 for (int i = 0; i< num; i++) {
5193 AudioSessionRef *ref = mAudioSessionRefs.editItemAt(i);
5194 if (ref->sessionid == audioSession && ref->pid == caller) {
5195 ref->cnt++;
Steve Block3856b092011-10-20 11:56:00 +01005196 ALOGV(" incremented refcount to %d", ref->cnt);
Marco Nelissen3a34bef2011-08-02 13:33:41 -07005197 return;
5198 }
5199 }
5200 AudioSessionRef *ref = new AudioSessionRef();
5201 ref->sessionid = audioSession;
5202 ref->pid = caller;
5203 ref->cnt = 1;
5204 mAudioSessionRefs.push(ref);
Steve Block3856b092011-10-20 11:56:00 +01005205 ALOGV(" added new entry for %d", ref->sessionid);
Marco Nelissen3a34bef2011-08-02 13:33:41 -07005206}
5207
5208void AudioFlinger::releaseAudioSessionId(int audioSession)
5209{
5210 Mutex::Autolock _l(mLock);
5211 int caller = IPCThreadState::self()->getCallingPid();
Steve Block3856b092011-10-20 11:56:00 +01005212 ALOGV("releasing %d from %d", audioSession, caller);
Marco Nelissen3a34bef2011-08-02 13:33:41 -07005213 int num = mAudioSessionRefs.size();
5214 for (int i = 0; i< num; i++) {
5215 AudioSessionRef *ref = mAudioSessionRefs.itemAt(i);
5216 if (ref->sessionid == audioSession && ref->pid == caller) {
5217 ref->cnt--;
Steve Block3856b092011-10-20 11:56:00 +01005218 ALOGV(" decremented refcount to %d", ref->cnt);
Marco Nelissen3a34bef2011-08-02 13:33:41 -07005219 if (ref->cnt == 0) {
5220 mAudioSessionRefs.removeAt(i);
5221 delete ref;
5222 purgeStaleEffects_l();
5223 }
5224 return;
5225 }
5226 }
5227 LOGW("session id %d not found for pid %d", audioSession, caller);
5228}
5229
5230void AudioFlinger::purgeStaleEffects_l() {
5231
Steve Block3856b092011-10-20 11:56:00 +01005232 ALOGV("purging stale effects");
Marco Nelissen3a34bef2011-08-02 13:33:41 -07005233
5234 Vector< sp<EffectChain> > chains;
5235
5236 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
5237 sp<PlaybackThread> t = mPlaybackThreads.valueAt(i);
5238 for (size_t j = 0; j < t->mEffectChains.size(); j++) {
5239 sp<EffectChain> ec = t->mEffectChains[j];
Marco Nelissen0270b182011-08-12 14:14:39 -07005240 if (ec->sessionId() > AUDIO_SESSION_OUTPUT_MIX) {
5241 chains.push(ec);
5242 }
Marco Nelissen3a34bef2011-08-02 13:33:41 -07005243 }
5244 }
5245 for (size_t i = 0; i < mRecordThreads.size(); i++) {
5246 sp<RecordThread> t = mRecordThreads.valueAt(i);
5247 for (size_t j = 0; j < t->mEffectChains.size(); j++) {
5248 sp<EffectChain> ec = t->mEffectChains[j];
5249 chains.push(ec);
5250 }
5251 }
5252
5253 for (size_t i = 0; i < chains.size(); i++) {
5254 sp<EffectChain> ec = chains[i];
5255 int sessionid = ec->sessionId();
5256 sp<ThreadBase> t = ec->mThread.promote();
5257 if (t == 0) {
5258 continue;
5259 }
5260 size_t numsessionrefs = mAudioSessionRefs.size();
5261 bool found = false;
5262 for (size_t k = 0; k < numsessionrefs; k++) {
5263 AudioSessionRef *ref = mAudioSessionRefs.itemAt(k);
5264 if (ref->sessionid == sessionid) {
Steve Block3856b092011-10-20 11:56:00 +01005265 ALOGV(" session %d still exists for %d with %d refs",
Marco Nelissen3a34bef2011-08-02 13:33:41 -07005266 sessionid, ref->pid, ref->cnt);
5267 found = true;
5268 break;
5269 }
5270 }
5271 if (!found) {
5272 // remove all effects from the chain
5273 while (ec->mEffects.size()) {
5274 sp<EffectModule> effect = ec->mEffects[0];
5275 effect->unPin();
5276 Mutex::Autolock _l (t->mLock);
5277 t->removeEffect_l(effect);
5278 for (size_t j = 0; j < effect->mHandles.size(); j++) {
5279 sp<EffectHandle> handle = effect->mHandles[j].promote();
5280 if (handle != 0) {
5281 handle->mEffect.clear();
Eric Laurenta85a74a2011-10-19 11:44:54 -07005282 if (handle->mHasControl && handle->mEnabled) {
5283 t->checkSuspendOnEffectEnabled_l(effect, false, effect->sessionId());
5284 }
Marco Nelissen3a34bef2011-08-02 13:33:41 -07005285 }
5286 }
5287 AudioSystem::unregisterEffect(effect->id());
5288 }
5289 }
5290 }
5291 return;
5292}
5293
Mathias Agopian65ab4712010-07-14 17:59:35 -07005294// checkPlaybackThread_l() must be called with AudioFlinger::mLock held
5295AudioFlinger::PlaybackThread *AudioFlinger::checkPlaybackThread_l(int output) const
5296{
5297 PlaybackThread *thread = NULL;
5298 if (mPlaybackThreads.indexOfKey(output) >= 0) {
5299 thread = (PlaybackThread *)mPlaybackThreads.valueFor(output).get();
5300 }
5301 return thread;
5302}
5303
5304// checkMixerThread_l() must be called with AudioFlinger::mLock held
5305AudioFlinger::MixerThread *AudioFlinger::checkMixerThread_l(int output) const
5306{
5307 PlaybackThread *thread = checkPlaybackThread_l(output);
5308 if (thread != NULL) {
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005309 if (thread->type() == ThreadBase::DIRECT) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07005310 thread = NULL;
5311 }
5312 }
5313 return (MixerThread *)thread;
5314}
5315
5316// checkRecordThread_l() must be called with AudioFlinger::mLock held
5317AudioFlinger::RecordThread *AudioFlinger::checkRecordThread_l(int input) const
5318{
5319 RecordThread *thread = NULL;
5320 if (mRecordThreads.indexOfKey(input) >= 0) {
5321 thread = (RecordThread *)mRecordThreads.valueFor(input).get();
5322 }
5323 return thread;
5324}
5325
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005326uint32_t AudioFlinger::nextUniqueId()
Mathias Agopian65ab4712010-07-14 17:59:35 -07005327{
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005328 return android_atomic_inc(&mNextUniqueId);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005329}
5330
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005331AudioFlinger::PlaybackThread *AudioFlinger::primaryPlaybackThread_l()
5332{
5333 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
5334 PlaybackThread *thread = mPlaybackThreads.valueAt(i).get();
Eric Laurentb8ba0a92011-08-07 16:32:26 -07005335 AudioStreamOut *output = thread->getOutput();
5336 if (output != NULL && output->hwDev == mPrimaryHardwareDev) {
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005337 return thread;
5338 }
5339 }
5340 return NULL;
5341}
5342
5343uint32_t AudioFlinger::primaryOutputDevice_l()
5344{
5345 PlaybackThread *thread = primaryPlaybackThread_l();
5346
5347 if (thread == NULL) {
5348 return 0;
5349 }
5350
5351 return thread->device();
5352}
5353
5354
Mathias Agopian65ab4712010-07-14 17:59:35 -07005355// ----------------------------------------------------------------------------
5356// Effect management
5357// ----------------------------------------------------------------------------
5358
5359
Mathias Agopian65ab4712010-07-14 17:59:35 -07005360status_t AudioFlinger::queryNumberEffects(uint32_t *numEffects)
5361{
5362 Mutex::Autolock _l(mLock);
5363 return EffectQueryNumberEffects(numEffects);
5364}
5365
5366status_t AudioFlinger::queryEffect(uint32_t index, effect_descriptor_t *descriptor)
5367{
5368 Mutex::Autolock _l(mLock);
5369 return EffectQueryEffect(index, descriptor);
5370}
5371
5372status_t AudioFlinger::getEffectDescriptor(effect_uuid_t *pUuid, effect_descriptor_t *descriptor)
5373{
5374 Mutex::Autolock _l(mLock);
5375 return EffectGetDescriptor(pUuid, descriptor);
5376}
5377
5378
Mathias Agopian65ab4712010-07-14 17:59:35 -07005379sp<IEffect> AudioFlinger::createEffect(pid_t pid,
5380 effect_descriptor_t *pDesc,
5381 const sp<IEffectClient>& effectClient,
5382 int32_t priority,
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005383 int io,
Mathias Agopian65ab4712010-07-14 17:59:35 -07005384 int sessionId,
5385 status_t *status,
5386 int *id,
5387 int *enabled)
5388{
5389 status_t lStatus = NO_ERROR;
5390 sp<EffectHandle> handle;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005391 effect_descriptor_t desc;
5392 sp<Client> client;
5393 wp<Client> wclient;
5394
Steve Block3856b092011-10-20 11:56:00 +01005395 ALOGV("createEffect pid %d, client %p, priority %d, sessionId %d, io %d",
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005396 pid, effectClient.get(), priority, sessionId, io);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005397
5398 if (pDesc == NULL) {
5399 lStatus = BAD_VALUE;
5400 goto Exit;
5401 }
5402
Eric Laurent84e9a102010-09-23 16:10:16 -07005403 // check audio settings permission for global effects
Dima Zavinfce7a472011-04-19 22:30:36 -07005404 if (sessionId == AUDIO_SESSION_OUTPUT_MIX && !settingsAllowed()) {
Eric Laurent84e9a102010-09-23 16:10:16 -07005405 lStatus = PERMISSION_DENIED;
5406 goto Exit;
5407 }
5408
Dima Zavinfce7a472011-04-19 22:30:36 -07005409 // Session AUDIO_SESSION_OUTPUT_STAGE is reserved for output stage effects
Eric Laurent84e9a102010-09-23 16:10:16 -07005410 // that can only be created by audio policy manager (running in same process)
Dima Zavinfce7a472011-04-19 22:30:36 -07005411 if (sessionId == AUDIO_SESSION_OUTPUT_STAGE && getpid() != pid) {
Eric Laurent84e9a102010-09-23 16:10:16 -07005412 lStatus = PERMISSION_DENIED;
5413 goto Exit;
5414 }
5415
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005416 if (io == 0) {
Dima Zavinfce7a472011-04-19 22:30:36 -07005417 if (sessionId == AUDIO_SESSION_OUTPUT_STAGE) {
Eric Laurent84e9a102010-09-23 16:10:16 -07005418 // output must be specified by AudioPolicyManager when using session
Dima Zavinfce7a472011-04-19 22:30:36 -07005419 // AUDIO_SESSION_OUTPUT_STAGE
Eric Laurent84e9a102010-09-23 16:10:16 -07005420 lStatus = BAD_VALUE;
5421 goto Exit;
Dima Zavinfce7a472011-04-19 22:30:36 -07005422 } else if (sessionId == AUDIO_SESSION_OUTPUT_MIX) {
Eric Laurent84e9a102010-09-23 16:10:16 -07005423 // if the output returned by getOutputForEffect() is removed before we lock the
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005424 // mutex below, the call to checkPlaybackThread_l(io) below will detect it
Eric Laurent84e9a102010-09-23 16:10:16 -07005425 // and we will exit safely
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005426 io = AudioSystem::getOutputForEffect(&desc);
Eric Laurent84e9a102010-09-23 16:10:16 -07005427 }
5428 }
5429
Mathias Agopian65ab4712010-07-14 17:59:35 -07005430 {
5431 Mutex::Autolock _l(mLock);
5432
Mathias Agopian65ab4712010-07-14 17:59:35 -07005433
5434 if (!EffectIsNullUuid(&pDesc->uuid)) {
5435 // if uuid is specified, request effect descriptor
5436 lStatus = EffectGetDescriptor(&pDesc->uuid, &desc);
5437 if (lStatus < 0) {
5438 LOGW("createEffect() error %d from EffectGetDescriptor", lStatus);
5439 goto Exit;
5440 }
5441 } else {
5442 // if uuid is not specified, look for an available implementation
5443 // of the required type in effect factory
5444 if (EffectIsNullUuid(&pDesc->type)) {
5445 LOGW("createEffect() no effect type");
5446 lStatus = BAD_VALUE;
5447 goto Exit;
5448 }
5449 uint32_t numEffects = 0;
5450 effect_descriptor_t d;
Marco Nelissen3a34bef2011-08-02 13:33:41 -07005451 d.flags = 0; // prevent compiler warning
Mathias Agopian65ab4712010-07-14 17:59:35 -07005452 bool found = false;
5453
5454 lStatus = EffectQueryNumberEffects(&numEffects);
5455 if (lStatus < 0) {
5456 LOGW("createEffect() error %d from EffectQueryNumberEffects", lStatus);
5457 goto Exit;
5458 }
5459 for (uint32_t i = 0; i < numEffects; i++) {
5460 lStatus = EffectQueryEffect(i, &desc);
5461 if (lStatus < 0) {
5462 LOGW("createEffect() error %d from EffectQueryEffect", lStatus);
5463 continue;
5464 }
5465 if (memcmp(&desc.type, &pDesc->type, sizeof(effect_uuid_t)) == 0) {
5466 // If matching type found save effect descriptor. If the session is
5467 // 0 and the effect is not auxiliary, continue enumeration in case
5468 // an auxiliary version of this effect type is available
5469 found = true;
5470 memcpy(&d, &desc, sizeof(effect_descriptor_t));
Dima Zavinfce7a472011-04-19 22:30:36 -07005471 if (sessionId != AUDIO_SESSION_OUTPUT_MIX ||
Mathias Agopian65ab4712010-07-14 17:59:35 -07005472 (desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
5473 break;
5474 }
5475 }
5476 }
5477 if (!found) {
5478 lStatus = BAD_VALUE;
5479 LOGW("createEffect() effect not found");
5480 goto Exit;
5481 }
5482 // For same effect type, chose auxiliary version over insert version if
5483 // connect to output mix (Compliance to OpenSL ES)
Dima Zavinfce7a472011-04-19 22:30:36 -07005484 if (sessionId == AUDIO_SESSION_OUTPUT_MIX &&
Mathias Agopian65ab4712010-07-14 17:59:35 -07005485 (d.flags & EFFECT_FLAG_TYPE_MASK) != EFFECT_FLAG_TYPE_AUXILIARY) {
5486 memcpy(&desc, &d, sizeof(effect_descriptor_t));
5487 }
5488 }
5489
5490 // Do not allow auxiliary effects on a session different from 0 (output mix)
Dima Zavinfce7a472011-04-19 22:30:36 -07005491 if (sessionId != AUDIO_SESSION_OUTPUT_MIX &&
Mathias Agopian65ab4712010-07-14 17:59:35 -07005492 (desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
5493 lStatus = INVALID_OPERATION;
5494 goto Exit;
5495 }
5496
Eric Laurent59255e42011-07-27 19:49:51 -07005497 // check recording permission for visualizer
5498 if ((memcmp(&desc.type, SL_IID_VISUALIZATION, sizeof(effect_uuid_t)) == 0) &&
5499 !recordingAllowed()) {
5500 lStatus = PERMISSION_DENIED;
5501 goto Exit;
5502 }
5503
Mathias Agopian65ab4712010-07-14 17:59:35 -07005504 // return effect descriptor
5505 memcpy(pDesc, &desc, sizeof(effect_descriptor_t));
5506
5507 // If output is not specified try to find a matching audio session ID in one of the
5508 // output threads.
Eric Laurent84e9a102010-09-23 16:10:16 -07005509 // If output is 0 here, sessionId is neither SESSION_OUTPUT_STAGE nor SESSION_OUTPUT_MIX
5510 // because of code checking output when entering the function.
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005511 // Note: io is never 0 when creating an effect on an input
5512 if (io == 0) {
Eric Laurent84e9a102010-09-23 16:10:16 -07005513 // look for the thread where the specified audio session is present
5514 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
5515 if (mPlaybackThreads.valueAt(i)->hasAudioSession(sessionId) != 0) {
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005516 io = mPlaybackThreads.keyAt(i);
Eric Laurent84e9a102010-09-23 16:10:16 -07005517 break;
Eric Laurent39e94f82010-07-28 01:32:47 -07005518 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07005519 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005520 if (io == 0) {
5521 for (size_t i = 0; i < mRecordThreads.size(); i++) {
5522 if (mRecordThreads.valueAt(i)->hasAudioSession(sessionId) != 0) {
5523 io = mRecordThreads.keyAt(i);
5524 break;
5525 }
5526 }
5527 }
Eric Laurent84e9a102010-09-23 16:10:16 -07005528 // If no output thread contains the requested session ID, default to
5529 // first output. The effect chain will be moved to the correct output
5530 // thread when a track with the same session ID is created
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005531 if (io == 0 && mPlaybackThreads.size()) {
5532 io = mPlaybackThreads.keyAt(0);
5533 }
Steve Block3856b092011-10-20 11:56:00 +01005534 ALOGV("createEffect() got io %d for effect %s", io, desc.name);
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005535 }
5536 ThreadBase *thread = checkRecordThread_l(io);
5537 if (thread == NULL) {
5538 thread = checkPlaybackThread_l(io);
5539 if (thread == NULL) {
5540 LOGE("createEffect() unknown output thread");
5541 lStatus = BAD_VALUE;
5542 goto Exit;
Eric Laurent84e9a102010-09-23 16:10:16 -07005543 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07005544 }
Eric Laurent84e9a102010-09-23 16:10:16 -07005545
Mathias Agopian65ab4712010-07-14 17:59:35 -07005546 wclient = mClients.valueFor(pid);
5547
5548 if (wclient != NULL) {
5549 client = wclient.promote();
5550 } else {
5551 client = new Client(this, pid);
5552 mClients.add(pid, client);
5553 }
5554
Marco Nelissen3a34bef2011-08-02 13:33:41 -07005555 // create effect on selected output thread
Eric Laurentde070132010-07-13 04:45:46 -07005556 handle = thread->createEffect_l(client, effectClient, priority, sessionId,
5557 &desc, enabled, &lStatus);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005558 if (handle != 0 && id != NULL) {
5559 *id = handle->id();
5560 }
5561 }
5562
5563Exit:
5564 if(status) {
5565 *status = lStatus;
5566 }
5567 return handle;
5568}
5569
Eric Laurent59255e42011-07-27 19:49:51 -07005570status_t AudioFlinger::moveEffects(int sessionId, int srcOutput, int dstOutput)
Eric Laurentde070132010-07-13 04:45:46 -07005571{
Steve Block3856b092011-10-20 11:56:00 +01005572 ALOGV("moveEffects() session %d, srcOutput %d, dstOutput %d",
Eric Laurent59255e42011-07-27 19:49:51 -07005573 sessionId, srcOutput, dstOutput);
Eric Laurentde070132010-07-13 04:45:46 -07005574 Mutex::Autolock _l(mLock);
5575 if (srcOutput == dstOutput) {
5576 LOGW("moveEffects() same dst and src outputs %d", dstOutput);
5577 return NO_ERROR;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005578 }
Eric Laurentde070132010-07-13 04:45:46 -07005579 PlaybackThread *srcThread = checkPlaybackThread_l(srcOutput);
5580 if (srcThread == NULL) {
5581 LOGW("moveEffects() bad srcOutput %d", srcOutput);
5582 return BAD_VALUE;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005583 }
Eric Laurentde070132010-07-13 04:45:46 -07005584 PlaybackThread *dstThread = checkPlaybackThread_l(dstOutput);
5585 if (dstThread == NULL) {
5586 LOGW("moveEffects() bad dstOutput %d", dstOutput);
5587 return BAD_VALUE;
5588 }
5589
5590 Mutex::Autolock _dl(dstThread->mLock);
5591 Mutex::Autolock _sl(srcThread->mLock);
Eric Laurent59255e42011-07-27 19:49:51 -07005592 moveEffectChain_l(sessionId, srcThread, dstThread, false);
Eric Laurentde070132010-07-13 04:45:46 -07005593
Mathias Agopian65ab4712010-07-14 17:59:35 -07005594 return NO_ERROR;
5595}
5596
Marco Nelissen3a34bef2011-08-02 13:33:41 -07005597// moveEffectChain_l must be called with both srcThread and dstThread mLocks held
Eric Laurent59255e42011-07-27 19:49:51 -07005598status_t AudioFlinger::moveEffectChain_l(int sessionId,
Eric Laurentde070132010-07-13 04:45:46 -07005599 AudioFlinger::PlaybackThread *srcThread,
Eric Laurent39e94f82010-07-28 01:32:47 -07005600 AudioFlinger::PlaybackThread *dstThread,
5601 bool reRegister)
Eric Laurentde070132010-07-13 04:45:46 -07005602{
Steve Block3856b092011-10-20 11:56:00 +01005603 ALOGV("moveEffectChain_l() session %d from thread %p to thread %p",
Eric Laurent59255e42011-07-27 19:49:51 -07005604 sessionId, srcThread, dstThread);
Eric Laurentde070132010-07-13 04:45:46 -07005605
Eric Laurent59255e42011-07-27 19:49:51 -07005606 sp<EffectChain> chain = srcThread->getEffectChain_l(sessionId);
Eric Laurentde070132010-07-13 04:45:46 -07005607 if (chain == 0) {
5608 LOGW("moveEffectChain_l() effect chain for session %d not on source thread %p",
Eric Laurent59255e42011-07-27 19:49:51 -07005609 sessionId, srcThread);
Eric Laurentde070132010-07-13 04:45:46 -07005610 return INVALID_OPERATION;
5611 }
5612
Eric Laurent39e94f82010-07-28 01:32:47 -07005613 // remove chain first. This is useful only if reconfiguring effect chain on same output thread,
Eric Laurentde070132010-07-13 04:45:46 -07005614 // so that a new chain is created with correct parameters when first effect is added. This is
Eric Laurentec35a142011-10-05 17:42:25 -07005615 // otherwise unnecessary as removeEffect_l() will remove the chain when last effect is
Eric Laurentde070132010-07-13 04:45:46 -07005616 // removed.
5617 srcThread->removeEffectChain_l(chain);
5618
5619 // transfer all effects one by one so that new effect chain is created on new thread with
5620 // correct buffer sizes and audio parameters and effect engines reconfigured accordingly
Eric Laurent39e94f82010-07-28 01:32:47 -07005621 int dstOutput = dstThread->id();
5622 sp<EffectChain> dstChain;
Marco Nelissen3a34bef2011-08-02 13:33:41 -07005623 uint32_t strategy = 0; // prevent compiler warning
Eric Laurentde070132010-07-13 04:45:46 -07005624 sp<EffectModule> effect = chain->getEffectFromId_l(0);
5625 while (effect != 0) {
5626 srcThread->removeEffect_l(effect);
5627 dstThread->addEffect_l(effect);
Eric Laurentec35a142011-10-05 17:42:25 -07005628 // removeEffect_l() has stopped the effect if it was active so it must be restarted
5629 if (effect->state() == EffectModule::ACTIVE ||
5630 effect->state() == EffectModule::STOPPING) {
5631 effect->start();
5632 }
Eric Laurent39e94f82010-07-28 01:32:47 -07005633 // if the move request is not received from audio policy manager, the effect must be
5634 // re-registered with the new strategy and output
5635 if (dstChain == 0) {
5636 dstChain = effect->chain().promote();
5637 if (dstChain == 0) {
5638 LOGW("moveEffectChain_l() cannot get chain from effect %p", effect.get());
5639 srcThread->addEffect_l(effect);
5640 return NO_INIT;
5641 }
5642 strategy = dstChain->strategy();
5643 }
5644 if (reRegister) {
5645 AudioSystem::unregisterEffect(effect->id());
5646 AudioSystem::registerEffect(&effect->desc(),
5647 dstOutput,
5648 strategy,
Eric Laurent59255e42011-07-27 19:49:51 -07005649 sessionId,
Eric Laurent39e94f82010-07-28 01:32:47 -07005650 effect->id());
5651 }
Eric Laurentde070132010-07-13 04:45:46 -07005652 effect = chain->getEffectFromId_l(0);
5653 }
5654
5655 return NO_ERROR;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005656}
5657
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005658
Mathias Agopian65ab4712010-07-14 17:59:35 -07005659// PlaybackThread::createEffect_l() must be called with AudioFlinger::mLock held
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005660sp<AudioFlinger::EffectHandle> AudioFlinger::ThreadBase::createEffect_l(
Mathias Agopian65ab4712010-07-14 17:59:35 -07005661 const sp<AudioFlinger::Client>& client,
5662 const sp<IEffectClient>& effectClient,
5663 int32_t priority,
5664 int sessionId,
5665 effect_descriptor_t *desc,
5666 int *enabled,
5667 status_t *status
5668 )
5669{
5670 sp<EffectModule> effect;
5671 sp<EffectHandle> handle;
5672 status_t lStatus;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005673 sp<EffectChain> chain;
Eric Laurentde070132010-07-13 04:45:46 -07005674 bool chainCreated = false;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005675 bool effectCreated = false;
5676 bool effectRegistered = false;
5677
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005678 lStatus = initCheck();
5679 if (lStatus != NO_ERROR) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07005680 LOGW("createEffect_l() Audio driver not initialized.");
Mathias Agopian65ab4712010-07-14 17:59:35 -07005681 goto Exit;
5682 }
5683
5684 // Do not allow effects with session ID 0 on direct output or duplicating threads
5685 // TODO: add rule for hw accelerated effects on direct outputs with non PCM format
Dima Zavinfce7a472011-04-19 22:30:36 -07005686 if (sessionId == AUDIO_SESSION_OUTPUT_MIX && mType != MIXER) {
Eric Laurentde070132010-07-13 04:45:46 -07005687 LOGW("createEffect_l() Cannot add auxiliary effect %s to session %d",
5688 desc->name, sessionId);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005689 lStatus = BAD_VALUE;
5690 goto Exit;
5691 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005692 // Only Pre processor effects are allowed on input threads and only on input threads
5693 if ((mType == RECORD &&
5694 (desc->flags & EFFECT_FLAG_TYPE_MASK) != EFFECT_FLAG_TYPE_PRE_PROC) ||
5695 (mType != RECORD &&
5696 (desc->flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC)) {
5697 LOGW("createEffect_l() effect %s (flags %08x) created on wrong thread type %d",
5698 desc->name, desc->flags, mType);
5699 lStatus = BAD_VALUE;
5700 goto Exit;
5701 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07005702
Steve Block3856b092011-10-20 11:56:00 +01005703 ALOGV("createEffect_l() thread %p effect %s on session %d", this, desc->name, sessionId);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005704
5705 { // scope for mLock
5706 Mutex::Autolock _l(mLock);
5707
5708 // check for existing effect chain with the requested audio session
5709 chain = getEffectChain_l(sessionId);
5710 if (chain == 0) {
5711 // create a new chain for this session
Steve Block3856b092011-10-20 11:56:00 +01005712 ALOGV("createEffect_l() new effect chain for session %d", sessionId);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005713 chain = new EffectChain(this, sessionId);
5714 addEffectChain_l(chain);
Eric Laurentde070132010-07-13 04:45:46 -07005715 chain->setStrategy(getStrategyForSession_l(sessionId));
5716 chainCreated = true;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005717 } else {
Eric Laurentcab11242010-07-15 12:50:15 -07005718 effect = chain->getEffectFromDesc_l(desc);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005719 }
5720
Steve Block3856b092011-10-20 11:56:00 +01005721 ALOGV("createEffect_l() got effect %p on chain %p", effect == 0 ? 0 : effect.get(), chain.get());
Mathias Agopian65ab4712010-07-14 17:59:35 -07005722
5723 if (effect == 0) {
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005724 int id = mAudioFlinger->nextUniqueId();
Mathias Agopian65ab4712010-07-14 17:59:35 -07005725 // Check CPU and memory usage
Eric Laurentde070132010-07-13 04:45:46 -07005726 lStatus = AudioSystem::registerEffect(desc, mId, chain->strategy(), sessionId, id);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005727 if (lStatus != NO_ERROR) {
5728 goto Exit;
5729 }
5730 effectRegistered = true;
5731 // create a new effect module if none present in the chain
Eric Laurentde070132010-07-13 04:45:46 -07005732 effect = new EffectModule(this, chain, desc, id, sessionId);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005733 lStatus = effect->status();
5734 if (lStatus != NO_ERROR) {
5735 goto Exit;
5736 }
Eric Laurentcab11242010-07-15 12:50:15 -07005737 lStatus = chain->addEffect_l(effect);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005738 if (lStatus != NO_ERROR) {
5739 goto Exit;
5740 }
5741 effectCreated = true;
5742
5743 effect->setDevice(mDevice);
5744 effect->setMode(mAudioFlinger->getMode());
5745 }
5746 // create effect handle and connect it to effect module
5747 handle = new EffectHandle(effect, client, effectClient, priority);
5748 lStatus = effect->addHandle(handle);
5749 if (enabled) {
5750 *enabled = (int)effect->isEnabled();
5751 }
5752 }
5753
5754Exit:
5755 if (lStatus != NO_ERROR && lStatus != ALREADY_EXISTS) {
Eric Laurentde070132010-07-13 04:45:46 -07005756 Mutex::Autolock _l(mLock);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005757 if (effectCreated) {
Eric Laurentde070132010-07-13 04:45:46 -07005758 chain->removeEffect_l(effect);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005759 }
5760 if (effectRegistered) {
Eric Laurentde070132010-07-13 04:45:46 -07005761 AudioSystem::unregisterEffect(effect->id());
5762 }
5763 if (chainCreated) {
5764 removeEffectChain_l(chain);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005765 }
5766 handle.clear();
5767 }
5768
5769 if(status) {
5770 *status = lStatus;
5771 }
5772 return handle;
5773}
5774
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005775sp<AudioFlinger::EffectModule> AudioFlinger::ThreadBase::getEffect_l(int sessionId, int effectId)
5776{
5777 sp<EffectModule> effect;
5778
5779 sp<EffectChain> chain = getEffectChain_l(sessionId);
5780 if (chain != 0) {
5781 effect = chain->getEffectFromId_l(effectId);
5782 }
5783 return effect;
5784}
5785
Eric Laurentde070132010-07-13 04:45:46 -07005786// PlaybackThread::addEffect_l() must be called with AudioFlinger::mLock and
5787// PlaybackThread::mLock held
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005788status_t AudioFlinger::ThreadBase::addEffect_l(const sp<EffectModule>& effect)
Eric Laurentde070132010-07-13 04:45:46 -07005789{
5790 // check for existing effect chain with the requested audio session
5791 int sessionId = effect->sessionId();
5792 sp<EffectChain> chain = getEffectChain_l(sessionId);
5793 bool chainCreated = false;
5794
5795 if (chain == 0) {
5796 // create a new chain for this session
Steve Block3856b092011-10-20 11:56:00 +01005797 ALOGV("addEffect_l() new effect chain for session %d", sessionId);
Eric Laurentde070132010-07-13 04:45:46 -07005798 chain = new EffectChain(this, sessionId);
5799 addEffectChain_l(chain);
5800 chain->setStrategy(getStrategyForSession_l(sessionId));
5801 chainCreated = true;
5802 }
Steve Block3856b092011-10-20 11:56:00 +01005803 ALOGV("addEffect_l() %p chain %p effect %p", this, chain.get(), effect.get());
Eric Laurentde070132010-07-13 04:45:46 -07005804
5805 if (chain->getEffectFromId_l(effect->id()) != 0) {
5806 LOGW("addEffect_l() %p effect %s already present in chain %p",
5807 this, effect->desc().name, chain.get());
5808 return BAD_VALUE;
5809 }
5810
5811 status_t status = chain->addEffect_l(effect);
5812 if (status != NO_ERROR) {
5813 if (chainCreated) {
5814 removeEffectChain_l(chain);
5815 }
5816 return status;
5817 }
5818
5819 effect->setDevice(mDevice);
5820 effect->setMode(mAudioFlinger->getMode());
5821 return NO_ERROR;
5822}
5823
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005824void AudioFlinger::ThreadBase::removeEffect_l(const sp<EffectModule>& effect) {
Eric Laurentde070132010-07-13 04:45:46 -07005825
Steve Block3856b092011-10-20 11:56:00 +01005826 ALOGV("removeEffect_l() %p effect %p", this, effect.get());
Mathias Agopian65ab4712010-07-14 17:59:35 -07005827 effect_descriptor_t desc = effect->desc();
Eric Laurentde070132010-07-13 04:45:46 -07005828 if ((desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
5829 detachAuxEffect_l(effect->id());
5830 }
5831
5832 sp<EffectChain> chain = effect->chain().promote();
5833 if (chain != 0) {
5834 // remove effect chain if removing last effect
5835 if (chain->removeEffect_l(effect) == 0) {
5836 removeEffectChain_l(chain);
5837 }
5838 } else {
5839 LOGW("removeEffect_l() %p cannot promote chain for effect %p", this, effect.get());
5840 }
5841}
5842
Eric Laurent7c7f10b2011-06-17 21:29:58 -07005843void AudioFlinger::ThreadBase::lockEffectChains_l(
5844 Vector<sp <AudioFlinger::EffectChain> >& effectChains)
5845{
5846 effectChains = mEffectChains;
5847 for (size_t i = 0; i < mEffectChains.size(); i++) {
5848 mEffectChains[i]->lock();
5849 }
5850}
5851
5852void AudioFlinger::ThreadBase::unlockEffectChains(
5853 Vector<sp <AudioFlinger::EffectChain> >& effectChains)
5854{
5855 for (size_t i = 0; i < effectChains.size(); i++) {
5856 effectChains[i]->unlock();
5857 }
5858}
5859
5860sp<AudioFlinger::EffectChain> AudioFlinger::ThreadBase::getEffectChain(int sessionId)
5861{
5862 Mutex::Autolock _l(mLock);
5863 return getEffectChain_l(sessionId);
5864}
5865
5866sp<AudioFlinger::EffectChain> AudioFlinger::ThreadBase::getEffectChain_l(int sessionId)
5867{
5868 sp<EffectChain> chain;
5869
5870 size_t size = mEffectChains.size();
5871 for (size_t i = 0; i < size; i++) {
5872 if (mEffectChains[i]->sessionId() == sessionId) {
5873 chain = mEffectChains[i];
5874 break;
5875 }
5876 }
5877 return chain;
5878}
5879
5880void AudioFlinger::ThreadBase::setMode(uint32_t mode)
5881{
5882 Mutex::Autolock _l(mLock);
5883 size_t size = mEffectChains.size();
5884 for (size_t i = 0; i < size; i++) {
5885 mEffectChains[i]->setMode_l(mode);
5886 }
5887}
5888
5889void AudioFlinger::ThreadBase::disconnectEffect(const sp<EffectModule>& effect,
Marco Nelissen3a34bef2011-08-02 13:33:41 -07005890 const wp<EffectHandle>& handle,
5891 bool unpiniflast) {
Eric Laurent59255e42011-07-27 19:49:51 -07005892
Mathias Agopian65ab4712010-07-14 17:59:35 -07005893 Mutex::Autolock _l(mLock);
Steve Block3856b092011-10-20 11:56:00 +01005894 ALOGV("disconnectEffect() %p effect %p", this, effect.get());
Mathias Agopian65ab4712010-07-14 17:59:35 -07005895 // delete the effect module if removing last handle on it
5896 if (effect->removeHandle(handle) == 0) {
Marco Nelissen3a34bef2011-08-02 13:33:41 -07005897 if (!effect->isPinned() || unpiniflast) {
5898 removeEffect_l(effect);
5899 AudioSystem::unregisterEffect(effect->id());
5900 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07005901 }
5902}
5903
5904status_t AudioFlinger::PlaybackThread::addEffectChain_l(const sp<EffectChain>& chain)
5905{
5906 int session = chain->sessionId();
5907 int16_t *buffer = mMixBuffer;
5908 bool ownsBuffer = false;
5909
Steve Block3856b092011-10-20 11:56:00 +01005910 ALOGV("addEffectChain_l() %p on thread %p for session %d", chain.get(), this, session);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005911 if (session > 0) {
5912 // Only one effect chain can be present in direct output thread and it uses
5913 // the mix buffer as input
5914 if (mType != DIRECT) {
5915 size_t numSamples = mFrameCount * mChannelCount;
5916 buffer = new int16_t[numSamples];
5917 memset(buffer, 0, numSamples * sizeof(int16_t));
Steve Block3856b092011-10-20 11:56:00 +01005918 ALOGV("addEffectChain_l() creating new input buffer %p session %d", buffer, session);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005919 ownsBuffer = true;
5920 }
5921
5922 // Attach all tracks with same session ID to this chain.
5923 for (size_t i = 0; i < mTracks.size(); ++i) {
5924 sp<Track> track = mTracks[i];
5925 if (session == track->sessionId()) {
Steve Block3856b092011-10-20 11:56:00 +01005926 ALOGV("addEffectChain_l() track->setMainBuffer track %p buffer %p", track.get(), buffer);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005927 track->setMainBuffer(buffer);
Eric Laurentb469b942011-05-09 12:09:06 -07005928 chain->incTrackCnt();
Mathias Agopian65ab4712010-07-14 17:59:35 -07005929 }
5930 }
5931
5932 // indicate all active tracks in the chain
5933 for (size_t i = 0 ; i < mActiveTracks.size() ; ++i) {
5934 sp<Track> track = mActiveTracks[i].promote();
5935 if (track == 0) continue;
5936 if (session == track->sessionId()) {
Steve Block3856b092011-10-20 11:56:00 +01005937 ALOGV("addEffectChain_l() activating track %p on session %d", track.get(), session);
Eric Laurentb469b942011-05-09 12:09:06 -07005938 chain->incActiveTrackCnt();
Mathias Agopian65ab4712010-07-14 17:59:35 -07005939 }
5940 }
5941 }
5942
5943 chain->setInBuffer(buffer, ownsBuffer);
5944 chain->setOutBuffer(mMixBuffer);
Dima Zavinfce7a472011-04-19 22:30:36 -07005945 // Effect chain for session AUDIO_SESSION_OUTPUT_STAGE is inserted at end of effect
Eric Laurentde070132010-07-13 04:45:46 -07005946 // chains list in order to be processed last as it contains output stage effects
Dima Zavinfce7a472011-04-19 22:30:36 -07005947 // Effect chain for session AUDIO_SESSION_OUTPUT_MIX is inserted before
5948 // session AUDIO_SESSION_OUTPUT_STAGE to be processed
Mathias Agopian65ab4712010-07-14 17:59:35 -07005949 // after track specific effects and before output stage
Dima Zavinfce7a472011-04-19 22:30:36 -07005950 // It is therefore mandatory that AUDIO_SESSION_OUTPUT_MIX == 0 and
5951 // that AUDIO_SESSION_OUTPUT_STAGE < AUDIO_SESSION_OUTPUT_MIX
Eric Laurentde070132010-07-13 04:45:46 -07005952 // Effect chain for other sessions are inserted at beginning of effect
5953 // chains list to be processed before output mix effects. Relative order between other
5954 // sessions is not important
Mathias Agopian65ab4712010-07-14 17:59:35 -07005955 size_t size = mEffectChains.size();
5956 size_t i = 0;
5957 for (i = 0; i < size; i++) {
5958 if (mEffectChains[i]->sessionId() < session) break;
5959 }
5960 mEffectChains.insertAt(chain, i);
Eric Laurent59255e42011-07-27 19:49:51 -07005961 checkSuspendOnAddEffectChain_l(chain);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005962
5963 return NO_ERROR;
5964}
5965
5966size_t AudioFlinger::PlaybackThread::removeEffectChain_l(const sp<EffectChain>& chain)
5967{
5968 int session = chain->sessionId();
5969
Steve Block3856b092011-10-20 11:56:00 +01005970 ALOGV("removeEffectChain_l() %p from thread %p for session %d", chain.get(), this, session);
Mathias Agopian65ab4712010-07-14 17:59:35 -07005971
5972 for (size_t i = 0; i < mEffectChains.size(); i++) {
5973 if (chain == mEffectChains[i]) {
5974 mEffectChains.removeAt(i);
Eric Laurentb469b942011-05-09 12:09:06 -07005975 // detach all active tracks from the chain
5976 for (size_t i = 0 ; i < mActiveTracks.size() ; ++i) {
5977 sp<Track> track = mActiveTracks[i].promote();
5978 if (track == 0) continue;
5979 if (session == track->sessionId()) {
Steve Block3856b092011-10-20 11:56:00 +01005980 ALOGV("removeEffectChain_l(): stopping track on chain %p for session Id: %d",
Eric Laurentb469b942011-05-09 12:09:06 -07005981 chain.get(), session);
5982 chain->decActiveTrackCnt();
5983 }
5984 }
5985
Mathias Agopian65ab4712010-07-14 17:59:35 -07005986 // detach all tracks with same session ID from this chain
5987 for (size_t i = 0; i < mTracks.size(); ++i) {
5988 sp<Track> track = mTracks[i];
5989 if (session == track->sessionId()) {
5990 track->setMainBuffer(mMixBuffer);
Eric Laurentb469b942011-05-09 12:09:06 -07005991 chain->decTrackCnt();
Mathias Agopian65ab4712010-07-14 17:59:35 -07005992 }
5993 }
Eric Laurentde070132010-07-13 04:45:46 -07005994 break;
Mathias Agopian65ab4712010-07-14 17:59:35 -07005995 }
5996 }
5997 return mEffectChains.size();
5998}
5999
Eric Laurentde070132010-07-13 04:45:46 -07006000status_t AudioFlinger::PlaybackThread::attachAuxEffect(
6001 const sp<AudioFlinger::PlaybackThread::Track> track, int EffectId)
Mathias Agopian65ab4712010-07-14 17:59:35 -07006002{
6003 Mutex::Autolock _l(mLock);
6004 return attachAuxEffect_l(track, EffectId);
6005}
6006
Eric Laurentde070132010-07-13 04:45:46 -07006007status_t AudioFlinger::PlaybackThread::attachAuxEffect_l(
6008 const sp<AudioFlinger::PlaybackThread::Track> track, int EffectId)
Mathias Agopian65ab4712010-07-14 17:59:35 -07006009{
6010 status_t status = NO_ERROR;
6011
6012 if (EffectId == 0) {
6013 track->setAuxBuffer(0, NULL);
6014 } else {
Dima Zavinfce7a472011-04-19 22:30:36 -07006015 // Auxiliary effects are always in audio session AUDIO_SESSION_OUTPUT_MIX
6016 sp<EffectModule> effect = getEffect_l(AUDIO_SESSION_OUTPUT_MIX, EffectId);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006017 if (effect != 0) {
6018 if ((effect->desc().flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
6019 track->setAuxBuffer(EffectId, (int32_t *)effect->inBuffer());
6020 } else {
6021 status = INVALID_OPERATION;
6022 }
6023 } else {
6024 status = BAD_VALUE;
6025 }
6026 }
6027 return status;
6028}
6029
6030void AudioFlinger::PlaybackThread::detachAuxEffect_l(int effectId)
6031{
6032 for (size_t i = 0; i < mTracks.size(); ++i) {
6033 sp<Track> track = mTracks[i];
6034 if (track->auxEffectId() == effectId) {
6035 attachAuxEffect_l(track, 0);
6036 }
6037 }
6038}
6039
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006040status_t AudioFlinger::RecordThread::addEffectChain_l(const sp<EffectChain>& chain)
6041{
6042 // only one chain per input thread
6043 if (mEffectChains.size() != 0) {
6044 return INVALID_OPERATION;
6045 }
Steve Block3856b092011-10-20 11:56:00 +01006046 ALOGV("addEffectChain_l() %p on thread %p", chain.get(), this);
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006047
6048 chain->setInBuffer(NULL);
6049 chain->setOutBuffer(NULL);
6050
Eric Laurent59255e42011-07-27 19:49:51 -07006051 checkSuspendOnAddEffectChain_l(chain);
6052
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006053 mEffectChains.add(chain);
6054
6055 return NO_ERROR;
6056}
6057
6058size_t AudioFlinger::RecordThread::removeEffectChain_l(const sp<EffectChain>& chain)
6059{
Steve Block3856b092011-10-20 11:56:00 +01006060 ALOGV("removeEffectChain_l() %p from thread %p", chain.get(), this);
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006061 LOGW_IF(mEffectChains.size() != 1,
6062 "removeEffectChain_l() %p invalid chain size %d on thread %p",
6063 chain.get(), mEffectChains.size(), this);
6064 if (mEffectChains.size() == 1) {
6065 mEffectChains.removeAt(0);
6066 }
6067 return 0;
6068}
6069
Mathias Agopian65ab4712010-07-14 17:59:35 -07006070// ----------------------------------------------------------------------------
6071// EffectModule implementation
6072// ----------------------------------------------------------------------------
6073
6074#undef LOG_TAG
6075#define LOG_TAG "AudioFlinger::EffectModule"
6076
6077AudioFlinger::EffectModule::EffectModule(const wp<ThreadBase>& wThread,
6078 const wp<AudioFlinger::EffectChain>& chain,
6079 effect_descriptor_t *desc,
6080 int id,
6081 int sessionId)
6082 : mThread(wThread), mChain(chain), mId(id), mSessionId(sessionId), mEffectInterface(NULL),
Eric Laurent59255e42011-07-27 19:49:51 -07006083 mStatus(NO_INIT), mState(IDLE), mSuspended(false)
Mathias Agopian65ab4712010-07-14 17:59:35 -07006084{
Steve Block3856b092011-10-20 11:56:00 +01006085 ALOGV("Constructor %p", this);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006086 int lStatus;
6087 sp<ThreadBase> thread = mThread.promote();
6088 if (thread == 0) {
6089 return;
6090 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07006091
6092 memcpy(&mDescriptor, desc, sizeof(effect_descriptor_t));
6093
6094 // create effect engine from effect factory
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006095 mStatus = EffectCreate(&desc->uuid, sessionId, thread->id(), &mEffectInterface);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006096
6097 if (mStatus != NO_ERROR) {
6098 return;
6099 }
6100 lStatus = init();
6101 if (lStatus < 0) {
6102 mStatus = lStatus;
6103 goto Error;
6104 }
6105
Marco Nelissen3a34bef2011-08-02 13:33:41 -07006106 if (mSessionId > AUDIO_SESSION_OUTPUT_MIX) {
6107 mPinned = true;
6108 }
Steve Block3856b092011-10-20 11:56:00 +01006109 ALOGV("Constructor success name %s, Interface %p", mDescriptor.name, mEffectInterface);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006110 return;
6111Error:
6112 EffectRelease(mEffectInterface);
6113 mEffectInterface = NULL;
Steve Block3856b092011-10-20 11:56:00 +01006114 ALOGV("Constructor Error %d", mStatus);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006115}
6116
6117AudioFlinger::EffectModule::~EffectModule()
6118{
Steve Block3856b092011-10-20 11:56:00 +01006119 ALOGV("Destructor %p", this);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006120 if (mEffectInterface != NULL) {
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006121 if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC ||
6122 (mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_POST_PROC) {
6123 sp<ThreadBase> thread = mThread.promote();
6124 if (thread != 0) {
Eric Laurentb8ba0a92011-08-07 16:32:26 -07006125 audio_stream_t *stream = thread->stream();
6126 if (stream != NULL) {
6127 stream->remove_audio_effect(stream, mEffectInterface);
6128 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006129 }
6130 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07006131 // release effect engine
6132 EffectRelease(mEffectInterface);
6133 }
6134}
6135
6136status_t AudioFlinger::EffectModule::addHandle(sp<EffectHandle>& handle)
6137{
6138 status_t status;
6139
6140 Mutex::Autolock _l(mLock);
6141 // First handle in mHandles has highest priority and controls the effect module
6142 int priority = handle->priority();
6143 size_t size = mHandles.size();
6144 sp<EffectHandle> h;
6145 size_t i;
6146 for (i = 0; i < size; i++) {
6147 h = mHandles[i].promote();
6148 if (h == 0) continue;
6149 if (h->priority() <= priority) break;
6150 }
6151 // if inserted in first place, move effect control from previous owner to this handle
6152 if (i == 0) {
Eric Laurent59255e42011-07-27 19:49:51 -07006153 bool enabled = false;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006154 if (h != 0) {
Eric Laurent59255e42011-07-27 19:49:51 -07006155 enabled = h->enabled();
6156 h->setControl(false/*hasControl*/, true /*signal*/, enabled /*enabled*/);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006157 }
Eric Laurent59255e42011-07-27 19:49:51 -07006158 handle->setControl(true /*hasControl*/, false /*signal*/, enabled /*enabled*/);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006159 status = NO_ERROR;
6160 } else {
6161 status = ALREADY_EXISTS;
6162 }
Steve Block3856b092011-10-20 11:56:00 +01006163 ALOGV("addHandle() %p added handle %p in position %d", this, handle.get(), i);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006164 mHandles.insertAt(handle, i);
6165 return status;
6166}
6167
6168size_t AudioFlinger::EffectModule::removeHandle(const wp<EffectHandle>& handle)
6169{
6170 Mutex::Autolock _l(mLock);
6171 size_t size = mHandles.size();
6172 size_t i;
6173 for (i = 0; i < size; i++) {
6174 if (mHandles[i] == handle) break;
6175 }
6176 if (i == size) {
6177 return size;
6178 }
Steve Block3856b092011-10-20 11:56:00 +01006179 ALOGV("removeHandle() %p removed handle %p in position %d", this, handle.unsafe_get(), i);
Eric Laurent59255e42011-07-27 19:49:51 -07006180
6181 bool enabled = false;
6182 EffectHandle *hdl = handle.unsafe_get();
6183 if (hdl) {
Steve Block3856b092011-10-20 11:56:00 +01006184 ALOGV("removeHandle() unsafe_get OK");
Eric Laurent59255e42011-07-27 19:49:51 -07006185 enabled = hdl->enabled();
6186 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07006187 mHandles.removeAt(i);
6188 size = mHandles.size();
6189 // if removed from first place, move effect control from this handle to next in line
6190 if (i == 0 && size != 0) {
6191 sp<EffectHandle> h = mHandles[0].promote();
6192 if (h != 0) {
Eric Laurent59255e42011-07-27 19:49:51 -07006193 h->setControl(true /*hasControl*/, true /*signal*/ , enabled /*enabled*/);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006194 }
6195 }
6196
Eric Laurentec437d82011-07-26 20:54:46 -07006197 // Prevent calls to process() and other functions on effect interface from now on.
6198 // The effect engine will be released by the destructor when the last strong reference on
6199 // this object is released which can happen after next process is called.
Marco Nelissen3a34bef2011-08-02 13:33:41 -07006200 if (size == 0 && !mPinned) {
Eric Laurentec437d82011-07-26 20:54:46 -07006201 mState = DESTROYED;
Eric Laurentdac69112010-09-28 14:09:57 -07006202 }
6203
Mathias Agopian65ab4712010-07-14 17:59:35 -07006204 return size;
6205}
6206
Eric Laurent59255e42011-07-27 19:49:51 -07006207sp<AudioFlinger::EffectHandle> AudioFlinger::EffectModule::controlHandle()
6208{
6209 Mutex::Autolock _l(mLock);
6210 sp<EffectHandle> handle;
6211 if (mHandles.size() != 0) {
6212 handle = mHandles[0].promote();
6213 }
6214 return handle;
6215}
6216
Marco Nelissen3a34bef2011-08-02 13:33:41 -07006217void AudioFlinger::EffectModule::disconnect(const wp<EffectHandle>& handle, bool unpiniflast)
Mathias Agopian65ab4712010-07-14 17:59:35 -07006218{
Steve Block3856b092011-10-20 11:56:00 +01006219 ALOGV("disconnect() %p handle %p ", this, handle.unsafe_get());
Mathias Agopian65ab4712010-07-14 17:59:35 -07006220 // keep a strong reference on this EffectModule to avoid calling the
6221 // destructor before we exit
6222 sp<EffectModule> keep(this);
6223 {
6224 sp<ThreadBase> thread = mThread.promote();
6225 if (thread != 0) {
Marco Nelissen3a34bef2011-08-02 13:33:41 -07006226 thread->disconnectEffect(keep, handle, unpiniflast);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006227 }
6228 }
6229}
6230
6231void AudioFlinger::EffectModule::updateState() {
6232 Mutex::Autolock _l(mLock);
6233
6234 switch (mState) {
6235 case RESTART:
6236 reset_l();
6237 // FALL THROUGH
6238
6239 case STARTING:
6240 // clear auxiliary effect input buffer for next accumulation
6241 if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
6242 memset(mConfig.inputCfg.buffer.raw,
6243 0,
6244 mConfig.inputCfg.buffer.frameCount*sizeof(int32_t));
6245 }
6246 start_l();
6247 mState = ACTIVE;
6248 break;
6249 case STOPPING:
6250 stop_l();
6251 mDisableWaitCnt = mMaxDisableWaitCnt;
6252 mState = STOPPED;
6253 break;
6254 case STOPPED:
6255 // mDisableWaitCnt is forced to 1 by process() when the engine indicates the end of the
6256 // turn off sequence.
6257 if (--mDisableWaitCnt == 0) {
6258 reset_l();
6259 mState = IDLE;
6260 }
6261 break;
Eric Laurentec437d82011-07-26 20:54:46 -07006262 default: //IDLE , ACTIVE, DESTROYED
Mathias Agopian65ab4712010-07-14 17:59:35 -07006263 break;
6264 }
6265}
6266
6267void AudioFlinger::EffectModule::process()
6268{
6269 Mutex::Autolock _l(mLock);
6270
Eric Laurentec437d82011-07-26 20:54:46 -07006271 if (mState == DESTROYED || mEffectInterface == NULL ||
Mathias Agopian65ab4712010-07-14 17:59:35 -07006272 mConfig.inputCfg.buffer.raw == NULL ||
6273 mConfig.outputCfg.buffer.raw == NULL) {
6274 return;
6275 }
6276
Eric Laurent8f45bd72010-08-31 13:50:07 -07006277 if (isProcessEnabled()) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07006278 // do 32 bit to 16 bit conversion for auxiliary effect input buffer
6279 if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
6280 AudioMixer::ditherAndClamp(mConfig.inputCfg.buffer.s32,
6281 mConfig.inputCfg.buffer.s32,
Eric Laurentde070132010-07-13 04:45:46 -07006282 mConfig.inputCfg.buffer.frameCount/2);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006283 }
6284
6285 // do the actual processing in the effect engine
6286 int ret = (*mEffectInterface)->process(mEffectInterface,
6287 &mConfig.inputCfg.buffer,
6288 &mConfig.outputCfg.buffer);
6289
6290 // force transition to IDLE state when engine is ready
6291 if (mState == STOPPED && ret == -ENODATA) {
6292 mDisableWaitCnt = 1;
6293 }
6294
6295 // clear auxiliary effect input buffer for next accumulation
6296 if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
Eric Laurent73337482011-01-19 18:36:13 -08006297 memset(mConfig.inputCfg.buffer.raw, 0,
6298 mConfig.inputCfg.buffer.frameCount*sizeof(int32_t));
Mathias Agopian65ab4712010-07-14 17:59:35 -07006299 }
6300 } else if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_INSERT &&
Eric Laurent73337482011-01-19 18:36:13 -08006301 mConfig.inputCfg.buffer.raw != mConfig.outputCfg.buffer.raw) {
6302 // If an insert effect is idle and input buffer is different from output buffer,
6303 // accumulate input onto output
Mathias Agopian65ab4712010-07-14 17:59:35 -07006304 sp<EffectChain> chain = mChain.promote();
Eric Laurentb469b942011-05-09 12:09:06 -07006305 if (chain != 0 && chain->activeTrackCnt() != 0) {
Eric Laurent73337482011-01-19 18:36:13 -08006306 size_t frameCnt = mConfig.inputCfg.buffer.frameCount * 2; //always stereo here
6307 int16_t *in = mConfig.inputCfg.buffer.s16;
6308 int16_t *out = mConfig.outputCfg.buffer.s16;
6309 for (size_t i = 0; i < frameCnt; i++) {
6310 out[i] = clamp16((int32_t)out[i] + (int32_t)in[i]);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006311 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07006312 }
6313 }
6314}
6315
6316void AudioFlinger::EffectModule::reset_l()
6317{
6318 if (mEffectInterface == NULL) {
6319 return;
6320 }
6321 (*mEffectInterface)->command(mEffectInterface, EFFECT_CMD_RESET, 0, NULL, 0, NULL);
6322}
6323
6324status_t AudioFlinger::EffectModule::configure()
6325{
6326 uint32_t channels;
6327 if (mEffectInterface == NULL) {
6328 return NO_INIT;
6329 }
6330
6331 sp<ThreadBase> thread = mThread.promote();
6332 if (thread == 0) {
6333 return DEAD_OBJECT;
6334 }
6335
6336 // TODO: handle configuration of effects replacing track process
6337 if (thread->channelCount() == 1) {
Eric Laurente1315cf2011-05-17 19:16:02 -07006338 channels = AUDIO_CHANNEL_OUT_MONO;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006339 } else {
Eric Laurente1315cf2011-05-17 19:16:02 -07006340 channels = AUDIO_CHANNEL_OUT_STEREO;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006341 }
6342
6343 if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
Eric Laurente1315cf2011-05-17 19:16:02 -07006344 mConfig.inputCfg.channels = AUDIO_CHANNEL_OUT_MONO;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006345 } else {
6346 mConfig.inputCfg.channels = channels;
6347 }
6348 mConfig.outputCfg.channels = channels;
Eric Laurente1315cf2011-05-17 19:16:02 -07006349 mConfig.inputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
6350 mConfig.outputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006351 mConfig.inputCfg.samplingRate = thread->sampleRate();
6352 mConfig.outputCfg.samplingRate = mConfig.inputCfg.samplingRate;
6353 mConfig.inputCfg.bufferProvider.cookie = NULL;
6354 mConfig.inputCfg.bufferProvider.getBuffer = NULL;
6355 mConfig.inputCfg.bufferProvider.releaseBuffer = NULL;
6356 mConfig.outputCfg.bufferProvider.cookie = NULL;
6357 mConfig.outputCfg.bufferProvider.getBuffer = NULL;
6358 mConfig.outputCfg.bufferProvider.releaseBuffer = NULL;
6359 mConfig.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ;
6360 // Insert effect:
Dima Zavinfce7a472011-04-19 22:30:36 -07006361 // - in session AUDIO_SESSION_OUTPUT_MIX or AUDIO_SESSION_OUTPUT_STAGE,
Eric Laurentde070132010-07-13 04:45:46 -07006362 // always overwrites output buffer: input buffer == output buffer
Mathias Agopian65ab4712010-07-14 17:59:35 -07006363 // - in other sessions:
6364 // last effect in the chain accumulates in output buffer: input buffer != output buffer
6365 // other effect: overwrites output buffer: input buffer == output buffer
6366 // Auxiliary effect:
6367 // accumulates in output buffer: input buffer != output buffer
6368 // Therefore: accumulate <=> input buffer != output buffer
6369 if (mConfig.inputCfg.buffer.raw != mConfig.outputCfg.buffer.raw) {
6370 mConfig.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_ACCUMULATE;
6371 } else {
6372 mConfig.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_WRITE;
6373 }
6374 mConfig.inputCfg.mask = EFFECT_CONFIG_ALL;
6375 mConfig.outputCfg.mask = EFFECT_CONFIG_ALL;
6376 mConfig.inputCfg.buffer.frameCount = thread->frameCount();
6377 mConfig.outputCfg.buffer.frameCount = mConfig.inputCfg.buffer.frameCount;
6378
Steve Block3856b092011-10-20 11:56:00 +01006379 ALOGV("configure() %p thread %p buffer %p framecount %d",
Eric Laurentde070132010-07-13 04:45:46 -07006380 this, thread.get(), mConfig.inputCfg.buffer.raw, mConfig.inputCfg.buffer.frameCount);
6381
Mathias Agopian65ab4712010-07-14 17:59:35 -07006382 status_t cmdStatus;
Eric Laurent25f43952010-07-28 05:40:18 -07006383 uint32_t size = sizeof(int);
6384 status_t status = (*mEffectInterface)->command(mEffectInterface,
6385 EFFECT_CMD_CONFIGURE,
6386 sizeof(effect_config_t),
6387 &mConfig,
6388 &size,
6389 &cmdStatus);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006390 if (status == 0) {
6391 status = cmdStatus;
6392 }
6393
6394 mMaxDisableWaitCnt = (MAX_DISABLE_TIME_MS * mConfig.outputCfg.samplingRate) /
6395 (1000 * mConfig.outputCfg.buffer.frameCount);
6396
6397 return status;
6398}
6399
6400status_t AudioFlinger::EffectModule::init()
6401{
6402 Mutex::Autolock _l(mLock);
6403 if (mEffectInterface == NULL) {
6404 return NO_INIT;
6405 }
6406 status_t cmdStatus;
Eric Laurent25f43952010-07-28 05:40:18 -07006407 uint32_t size = sizeof(status_t);
6408 status_t status = (*mEffectInterface)->command(mEffectInterface,
6409 EFFECT_CMD_INIT,
6410 0,
6411 NULL,
6412 &size,
6413 &cmdStatus);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006414 if (status == 0) {
6415 status = cmdStatus;
6416 }
6417 return status;
6418}
6419
Eric Laurentec35a142011-10-05 17:42:25 -07006420status_t AudioFlinger::EffectModule::start()
6421{
6422 Mutex::Autolock _l(mLock);
6423 return start_l();
6424}
6425
Mathias Agopian65ab4712010-07-14 17:59:35 -07006426status_t AudioFlinger::EffectModule::start_l()
6427{
6428 if (mEffectInterface == NULL) {
6429 return NO_INIT;
6430 }
6431 status_t cmdStatus;
Eric Laurent25f43952010-07-28 05:40:18 -07006432 uint32_t size = sizeof(status_t);
6433 status_t status = (*mEffectInterface)->command(mEffectInterface,
6434 EFFECT_CMD_ENABLE,
6435 0,
6436 NULL,
6437 &size,
6438 &cmdStatus);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006439 if (status == 0) {
6440 status = cmdStatus;
6441 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006442 if (status == 0 &&
6443 ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC ||
6444 (mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_POST_PROC)) {
6445 sp<ThreadBase> thread = mThread.promote();
6446 if (thread != 0) {
Eric Laurentb8ba0a92011-08-07 16:32:26 -07006447 audio_stream_t *stream = thread->stream();
6448 if (stream != NULL) {
6449 stream->add_audio_effect(stream, mEffectInterface);
6450 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006451 }
6452 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07006453 return status;
6454}
6455
Eric Laurentec437d82011-07-26 20:54:46 -07006456status_t AudioFlinger::EffectModule::stop()
6457{
6458 Mutex::Autolock _l(mLock);
6459 return stop_l();
6460}
6461
Mathias Agopian65ab4712010-07-14 17:59:35 -07006462status_t AudioFlinger::EffectModule::stop_l()
6463{
6464 if (mEffectInterface == NULL) {
6465 return NO_INIT;
6466 }
6467 status_t cmdStatus;
Eric Laurent25f43952010-07-28 05:40:18 -07006468 uint32_t size = sizeof(status_t);
6469 status_t status = (*mEffectInterface)->command(mEffectInterface,
6470 EFFECT_CMD_DISABLE,
6471 0,
6472 NULL,
6473 &size,
6474 &cmdStatus);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006475 if (status == 0) {
6476 status = cmdStatus;
6477 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006478 if (status == 0 &&
6479 ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC ||
6480 (mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_POST_PROC)) {
6481 sp<ThreadBase> thread = mThread.promote();
6482 if (thread != 0) {
Eric Laurentb8ba0a92011-08-07 16:32:26 -07006483 audio_stream_t *stream = thread->stream();
6484 if (stream != NULL) {
6485 stream->remove_audio_effect(stream, mEffectInterface);
6486 }
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006487 }
6488 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07006489 return status;
6490}
6491
Eric Laurent25f43952010-07-28 05:40:18 -07006492status_t AudioFlinger::EffectModule::command(uint32_t cmdCode,
6493 uint32_t cmdSize,
6494 void *pCmdData,
6495 uint32_t *replySize,
6496 void *pReplyData)
Mathias Agopian65ab4712010-07-14 17:59:35 -07006497{
6498 Mutex::Autolock _l(mLock);
Steve Block3856b092011-10-20 11:56:00 +01006499// ALOGV("command(), cmdCode: %d, mEffectInterface: %p", cmdCode, mEffectInterface);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006500
Eric Laurentec437d82011-07-26 20:54:46 -07006501 if (mState == DESTROYED || mEffectInterface == NULL) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07006502 return NO_INIT;
6503 }
Eric Laurent25f43952010-07-28 05:40:18 -07006504 status_t status = (*mEffectInterface)->command(mEffectInterface,
6505 cmdCode,
6506 cmdSize,
6507 pCmdData,
6508 replySize,
6509 pReplyData);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006510 if (cmdCode != EFFECT_CMD_GET_PARAM && status == NO_ERROR) {
Eric Laurent25f43952010-07-28 05:40:18 -07006511 uint32_t size = (replySize == NULL) ? 0 : *replySize;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006512 for (size_t i = 1; i < mHandles.size(); i++) {
6513 sp<EffectHandle> h = mHandles[i].promote();
6514 if (h != 0) {
6515 h->commandExecuted(cmdCode, cmdSize, pCmdData, size, pReplyData);
6516 }
6517 }
6518 }
6519 return status;
6520}
6521
6522status_t AudioFlinger::EffectModule::setEnabled(bool enabled)
6523{
Eric Laurentdb7c0792011-08-10 10:37:50 -07006524
Mathias Agopian65ab4712010-07-14 17:59:35 -07006525 Mutex::Autolock _l(mLock);
Steve Block3856b092011-10-20 11:56:00 +01006526 ALOGV("setEnabled %p enabled %d", this, enabled);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006527
6528 if (enabled != isEnabled()) {
Eric Laurentdb7c0792011-08-10 10:37:50 -07006529 status_t status = AudioSystem::setEffectEnabled(mId, enabled);
6530 if (enabled && status != NO_ERROR) {
6531 return status;
6532 }
6533
Mathias Agopian65ab4712010-07-14 17:59:35 -07006534 switch (mState) {
6535 // going from disabled to enabled
6536 case IDLE:
6537 mState = STARTING;
6538 break;
6539 case STOPPED:
6540 mState = RESTART;
6541 break;
6542 case STOPPING:
6543 mState = ACTIVE;
6544 break;
6545
6546 // going from enabled to disabled
6547 case RESTART:
Eric Laurent8f45bd72010-08-31 13:50:07 -07006548 mState = STOPPED;
6549 break;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006550 case STARTING:
6551 mState = IDLE;
6552 break;
6553 case ACTIVE:
6554 mState = STOPPING;
6555 break;
Eric Laurentec437d82011-07-26 20:54:46 -07006556 case DESTROYED:
6557 return NO_ERROR; // simply ignore as we are being destroyed
Mathias Agopian65ab4712010-07-14 17:59:35 -07006558 }
6559 for (size_t i = 1; i < mHandles.size(); i++) {
6560 sp<EffectHandle> h = mHandles[i].promote();
6561 if (h != 0) {
6562 h->setEnabled(enabled);
6563 }
6564 }
6565 }
6566 return NO_ERROR;
6567}
6568
6569bool AudioFlinger::EffectModule::isEnabled()
6570{
6571 switch (mState) {
6572 case RESTART:
6573 case STARTING:
6574 case ACTIVE:
6575 return true;
6576 case IDLE:
6577 case STOPPING:
6578 case STOPPED:
Eric Laurentec437d82011-07-26 20:54:46 -07006579 case DESTROYED:
Mathias Agopian65ab4712010-07-14 17:59:35 -07006580 default:
6581 return false;
6582 }
6583}
6584
Eric Laurent8f45bd72010-08-31 13:50:07 -07006585bool AudioFlinger::EffectModule::isProcessEnabled()
6586{
6587 switch (mState) {
6588 case RESTART:
6589 case ACTIVE:
6590 case STOPPING:
6591 case STOPPED:
6592 return true;
6593 case IDLE:
6594 case STARTING:
Eric Laurentec437d82011-07-26 20:54:46 -07006595 case DESTROYED:
Eric Laurent8f45bd72010-08-31 13:50:07 -07006596 default:
6597 return false;
6598 }
6599}
6600
Mathias Agopian65ab4712010-07-14 17:59:35 -07006601status_t AudioFlinger::EffectModule::setVolume(uint32_t *left, uint32_t *right, bool controller)
6602{
6603 Mutex::Autolock _l(mLock);
6604 status_t status = NO_ERROR;
6605
6606 // Send volume indication if EFFECT_FLAG_VOLUME_IND is set and read back altered volume
6607 // if controller flag is set (Note that controller == TRUE => EFFECT_FLAG_VOLUME_CTRL set)
Eric Laurent8f45bd72010-08-31 13:50:07 -07006608 if (isProcessEnabled() &&
Eric Laurentf997cab2010-07-19 06:24:46 -07006609 ((mDescriptor.flags & EFFECT_FLAG_VOLUME_MASK) == EFFECT_FLAG_VOLUME_CTRL ||
6610 (mDescriptor.flags & EFFECT_FLAG_VOLUME_MASK) == EFFECT_FLAG_VOLUME_IND)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07006611 status_t cmdStatus;
6612 uint32_t volume[2];
6613 uint32_t *pVolume = NULL;
Eric Laurent25f43952010-07-28 05:40:18 -07006614 uint32_t size = sizeof(volume);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006615 volume[0] = *left;
6616 volume[1] = *right;
6617 if (controller) {
6618 pVolume = volume;
6619 }
Eric Laurent25f43952010-07-28 05:40:18 -07006620 status = (*mEffectInterface)->command(mEffectInterface,
6621 EFFECT_CMD_SET_VOLUME,
6622 size,
6623 volume,
6624 &size,
6625 pVolume);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006626 if (controller && status == NO_ERROR && size == sizeof(volume)) {
6627 *left = volume[0];
6628 *right = volume[1];
6629 }
6630 }
6631 return status;
6632}
6633
6634status_t AudioFlinger::EffectModule::setDevice(uint32_t device)
6635{
6636 Mutex::Autolock _l(mLock);
6637 status_t status = NO_ERROR;
Eric Laurent7c7f10b2011-06-17 21:29:58 -07006638 if (device && (mDescriptor.flags & EFFECT_FLAG_DEVICE_MASK) == EFFECT_FLAG_DEVICE_IND) {
6639 // audio pre processing modules on RecordThread can receive both output and
6640 // input device indication in the same call
6641 uint32_t dev = device & AUDIO_DEVICE_OUT_ALL;
6642 if (dev) {
6643 status_t cmdStatus;
6644 uint32_t size = sizeof(status_t);
6645
6646 status = (*mEffectInterface)->command(mEffectInterface,
6647 EFFECT_CMD_SET_DEVICE,
6648 sizeof(uint32_t),
6649 &dev,
6650 &size,
6651 &cmdStatus);
6652 if (status == NO_ERROR) {
6653 status = cmdStatus;
6654 }
6655 }
6656 dev = device & AUDIO_DEVICE_IN_ALL;
6657 if (dev) {
6658 status_t cmdStatus;
6659 uint32_t size = sizeof(status_t);
6660
6661 status_t status2 = (*mEffectInterface)->command(mEffectInterface,
6662 EFFECT_CMD_SET_INPUT_DEVICE,
6663 sizeof(uint32_t),
6664 &dev,
6665 &size,
6666 &cmdStatus);
6667 if (status2 == NO_ERROR) {
6668 status2 = cmdStatus;
6669 }
6670 if (status == NO_ERROR) {
6671 status = status2;
6672 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07006673 }
6674 }
6675 return status;
6676}
6677
6678status_t AudioFlinger::EffectModule::setMode(uint32_t mode)
6679{
6680 Mutex::Autolock _l(mLock);
6681 status_t status = NO_ERROR;
6682 if ((mDescriptor.flags & EFFECT_FLAG_AUDIO_MODE_MASK) == EFFECT_FLAG_AUDIO_MODE_IND) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07006683 status_t cmdStatus;
Eric Laurent25f43952010-07-28 05:40:18 -07006684 uint32_t size = sizeof(status_t);
6685 status = (*mEffectInterface)->command(mEffectInterface,
6686 EFFECT_CMD_SET_AUDIO_MODE,
6687 sizeof(int),
Eric Laurente1315cf2011-05-17 19:16:02 -07006688 &mode,
Eric Laurent25f43952010-07-28 05:40:18 -07006689 &size,
6690 &cmdStatus);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006691 if (status == NO_ERROR) {
6692 status = cmdStatus;
6693 }
6694 }
6695 return status;
6696}
6697
Eric Laurent59255e42011-07-27 19:49:51 -07006698void AudioFlinger::EffectModule::setSuspended(bool suspended)
6699{
6700 Mutex::Autolock _l(mLock);
6701 mSuspended = suspended;
6702}
6703bool AudioFlinger::EffectModule::suspended()
6704{
6705 Mutex::Autolock _l(mLock);
6706 return mSuspended;
6707}
6708
Mathias Agopian65ab4712010-07-14 17:59:35 -07006709status_t AudioFlinger::EffectModule::dump(int fd, const Vector<String16>& args)
6710{
6711 const size_t SIZE = 256;
6712 char buffer[SIZE];
6713 String8 result;
6714
6715 snprintf(buffer, SIZE, "\tEffect ID %d:\n", mId);
6716 result.append(buffer);
6717
6718 bool locked = tryLock(mLock);
6719 // failed to lock - AudioFlinger is probably deadlocked
6720 if (!locked) {
6721 result.append("\t\tCould not lock Fx mutex:\n");
6722 }
6723
6724 result.append("\t\tSession Status State Engine:\n");
6725 snprintf(buffer, SIZE, "\t\t%05d %03d %03d 0x%08x\n",
6726 mSessionId, mStatus, mState, (uint32_t)mEffectInterface);
6727 result.append(buffer);
6728
6729 result.append("\t\tDescriptor:\n");
6730 snprintf(buffer, SIZE, "\t\t- UUID: %08X-%04X-%04X-%04X-%02X%02X%02X%02X%02X%02X\n",
6731 mDescriptor.uuid.timeLow, mDescriptor.uuid.timeMid, mDescriptor.uuid.timeHiAndVersion,
6732 mDescriptor.uuid.clockSeq, mDescriptor.uuid.node[0], mDescriptor.uuid.node[1],mDescriptor.uuid.node[2],
6733 mDescriptor.uuid.node[3],mDescriptor.uuid.node[4],mDescriptor.uuid.node[5]);
6734 result.append(buffer);
6735 snprintf(buffer, SIZE, "\t\t- TYPE: %08X-%04X-%04X-%04X-%02X%02X%02X%02X%02X%02X\n",
6736 mDescriptor.type.timeLow, mDescriptor.type.timeMid, mDescriptor.type.timeHiAndVersion,
6737 mDescriptor.type.clockSeq, mDescriptor.type.node[0], mDescriptor.type.node[1],mDescriptor.type.node[2],
6738 mDescriptor.type.node[3],mDescriptor.type.node[4],mDescriptor.type.node[5]);
6739 result.append(buffer);
Eric Laurente1315cf2011-05-17 19:16:02 -07006740 snprintf(buffer, SIZE, "\t\t- apiVersion: %08X\n\t\t- flags: %08X\n",
Mathias Agopian65ab4712010-07-14 17:59:35 -07006741 mDescriptor.apiVersion,
6742 mDescriptor.flags);
6743 result.append(buffer);
6744 snprintf(buffer, SIZE, "\t\t- name: %s\n",
6745 mDescriptor.name);
6746 result.append(buffer);
6747 snprintf(buffer, SIZE, "\t\t- implementor: %s\n",
6748 mDescriptor.implementor);
6749 result.append(buffer);
6750
6751 result.append("\t\t- Input configuration:\n");
6752 result.append("\t\t\tBuffer Frames Smp rate Channels Format\n");
6753 snprintf(buffer, SIZE, "\t\t\t0x%08x %05d %05d %08x %d\n",
6754 (uint32_t)mConfig.inputCfg.buffer.raw,
6755 mConfig.inputCfg.buffer.frameCount,
6756 mConfig.inputCfg.samplingRate,
6757 mConfig.inputCfg.channels,
6758 mConfig.inputCfg.format);
6759 result.append(buffer);
6760
6761 result.append("\t\t- Output configuration:\n");
6762 result.append("\t\t\tBuffer Frames Smp rate Channels Format\n");
6763 snprintf(buffer, SIZE, "\t\t\t0x%08x %05d %05d %08x %d\n",
6764 (uint32_t)mConfig.outputCfg.buffer.raw,
6765 mConfig.outputCfg.buffer.frameCount,
6766 mConfig.outputCfg.samplingRate,
6767 mConfig.outputCfg.channels,
6768 mConfig.outputCfg.format);
6769 result.append(buffer);
6770
6771 snprintf(buffer, SIZE, "\t\t%d Clients:\n", mHandles.size());
6772 result.append(buffer);
6773 result.append("\t\t\tPid Priority Ctrl Locked client server\n");
6774 for (size_t i = 0; i < mHandles.size(); ++i) {
6775 sp<EffectHandle> handle = mHandles[i].promote();
6776 if (handle != 0) {
6777 handle->dump(buffer, SIZE);
6778 result.append(buffer);
6779 }
6780 }
6781
6782 result.append("\n");
6783
6784 write(fd, result.string(), result.length());
6785
6786 if (locked) {
6787 mLock.unlock();
6788 }
6789
6790 return NO_ERROR;
6791}
6792
6793// ----------------------------------------------------------------------------
6794// EffectHandle implementation
6795// ----------------------------------------------------------------------------
6796
6797#undef LOG_TAG
6798#define LOG_TAG "AudioFlinger::EffectHandle"
6799
6800AudioFlinger::EffectHandle::EffectHandle(const sp<EffectModule>& effect,
6801 const sp<AudioFlinger::Client>& client,
6802 const sp<IEffectClient>& effectClient,
6803 int32_t priority)
6804 : BnEffect(),
Marco Nelissen3a34bef2011-08-02 13:33:41 -07006805 mEffect(effect), mEffectClient(effectClient), mClient(client), mCblk(NULL),
Eric Laurent59255e42011-07-27 19:49:51 -07006806 mPriority(priority), mHasControl(false), mEnabled(false)
Mathias Agopian65ab4712010-07-14 17:59:35 -07006807{
Steve Block3856b092011-10-20 11:56:00 +01006808 ALOGV("constructor %p", this);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006809
Marco Nelissen3a34bef2011-08-02 13:33:41 -07006810 if (client == 0) {
6811 return;
6812 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07006813 int bufOffset = ((sizeof(effect_param_cblk_t) - 1) / sizeof(int) + 1) * sizeof(int);
6814 mCblkMemory = client->heap()->allocate(EFFECT_PARAM_BUFFER_SIZE + bufOffset);
6815 if (mCblkMemory != 0) {
6816 mCblk = static_cast<effect_param_cblk_t *>(mCblkMemory->pointer());
6817
6818 if (mCblk) {
6819 new(mCblk) effect_param_cblk_t();
6820 mBuffer = (uint8_t *)mCblk + bufOffset;
6821 }
6822 } else {
6823 LOGE("not enough memory for Effect size=%u", EFFECT_PARAM_BUFFER_SIZE + sizeof(effect_param_cblk_t));
6824 return;
6825 }
6826}
6827
6828AudioFlinger::EffectHandle::~EffectHandle()
6829{
Steve Block3856b092011-10-20 11:56:00 +01006830 ALOGV("Destructor %p", this);
Marco Nelissen3a34bef2011-08-02 13:33:41 -07006831 disconnect(false);
Steve Block3856b092011-10-20 11:56:00 +01006832 ALOGV("Destructor DONE %p", this);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006833}
6834
6835status_t AudioFlinger::EffectHandle::enable()
6836{
Steve Block3856b092011-10-20 11:56:00 +01006837 ALOGV("enable %p", this);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006838 if (!mHasControl) return INVALID_OPERATION;
6839 if (mEffect == 0) return DEAD_OBJECT;
6840
Eric Laurentdb7c0792011-08-10 10:37:50 -07006841 if (mEnabled) {
6842 return NO_ERROR;
6843 }
6844
Eric Laurent59255e42011-07-27 19:49:51 -07006845 mEnabled = true;
6846
6847 sp<ThreadBase> thread = mEffect->thread().promote();
6848 if (thread != 0) {
6849 thread->checkSuspendOnEffectEnabled(mEffect, true, mEffect->sessionId());
6850 }
6851
6852 // checkSuspendOnEffectEnabled() can suspend this same effect when enabled
6853 if (mEffect->suspended()) {
6854 return NO_ERROR;
6855 }
6856
Eric Laurentdb7c0792011-08-10 10:37:50 -07006857 status_t status = mEffect->setEnabled(true);
6858 if (status != NO_ERROR) {
6859 if (thread != 0) {
6860 thread->checkSuspendOnEffectEnabled(mEffect, false, mEffect->sessionId());
6861 }
6862 mEnabled = false;
6863 }
6864 return status;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006865}
6866
6867status_t AudioFlinger::EffectHandle::disable()
6868{
Steve Block3856b092011-10-20 11:56:00 +01006869 ALOGV("disable %p", this);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006870 if (!mHasControl) return INVALID_OPERATION;
Eric Laurent59255e42011-07-27 19:49:51 -07006871 if (mEffect == 0) return DEAD_OBJECT;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006872
Eric Laurentdb7c0792011-08-10 10:37:50 -07006873 if (!mEnabled) {
6874 return NO_ERROR;
6875 }
Eric Laurent59255e42011-07-27 19:49:51 -07006876 mEnabled = false;
6877
6878 if (mEffect->suspended()) {
6879 return NO_ERROR;
6880 }
6881
6882 status_t status = mEffect->setEnabled(false);
6883
6884 sp<ThreadBase> thread = mEffect->thread().promote();
6885 if (thread != 0) {
6886 thread->checkSuspendOnEffectEnabled(mEffect, false, mEffect->sessionId());
6887 }
6888
6889 return status;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006890}
6891
6892void AudioFlinger::EffectHandle::disconnect()
6893{
Marco Nelissen3a34bef2011-08-02 13:33:41 -07006894 disconnect(true);
6895}
6896
6897void AudioFlinger::EffectHandle::disconnect(bool unpiniflast)
6898{
Steve Block3856b092011-10-20 11:56:00 +01006899 ALOGV("disconnect(%s)", unpiniflast ? "true" : "false");
Mathias Agopian65ab4712010-07-14 17:59:35 -07006900 if (mEffect == 0) {
6901 return;
6902 }
Marco Nelissen3a34bef2011-08-02 13:33:41 -07006903 mEffect->disconnect(this, unpiniflast);
Eric Laurent59255e42011-07-27 19:49:51 -07006904
Eric Laurenta85a74a2011-10-19 11:44:54 -07006905 if (mHasControl && mEnabled) {
Eric Laurentdb7c0792011-08-10 10:37:50 -07006906 sp<ThreadBase> thread = mEffect->thread().promote();
6907 if (thread != 0) {
6908 thread->checkSuspendOnEffectEnabled(mEffect, false, mEffect->sessionId());
6909 }
Eric Laurent59255e42011-07-27 19:49:51 -07006910 }
6911
Mathias Agopian65ab4712010-07-14 17:59:35 -07006912 // release sp on module => module destructor can be called now
6913 mEffect.clear();
Mathias Agopian65ab4712010-07-14 17:59:35 -07006914 if (mClient != 0) {
Marco Nelissen3a34bef2011-08-02 13:33:41 -07006915 if (mCblk) {
6916 mCblk->~effect_param_cblk_t(); // destroy our shared-structure.
6917 }
6918 mCblkMemory.clear(); // and free the shared memory
Mathias Agopian65ab4712010-07-14 17:59:35 -07006919 Mutex::Autolock _l(mClient->audioFlinger()->mLock);
6920 mClient.clear();
6921 }
6922}
6923
Eric Laurent25f43952010-07-28 05:40:18 -07006924status_t AudioFlinger::EffectHandle::command(uint32_t cmdCode,
6925 uint32_t cmdSize,
6926 void *pCmdData,
6927 uint32_t *replySize,
6928 void *pReplyData)
Mathias Agopian65ab4712010-07-14 17:59:35 -07006929{
Steve Block3856b092011-10-20 11:56:00 +01006930// ALOGV("command(), cmdCode: %d, mHasControl: %d, mEffect: %p",
Eric Laurent25f43952010-07-28 05:40:18 -07006931// cmdCode, mHasControl, (mEffect == 0) ? 0 : mEffect.get());
Mathias Agopian65ab4712010-07-14 17:59:35 -07006932
6933 // only get parameter command is permitted for applications not controlling the effect
6934 if (!mHasControl && cmdCode != EFFECT_CMD_GET_PARAM) {
6935 return INVALID_OPERATION;
6936 }
6937 if (mEffect == 0) return DEAD_OBJECT;
Marco Nelissen3a34bef2011-08-02 13:33:41 -07006938 if (mClient == 0) return INVALID_OPERATION;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006939
6940 // handle commands that are not forwarded transparently to effect engine
6941 if (cmdCode == EFFECT_CMD_SET_PARAM_COMMIT) {
6942 // No need to trylock() here as this function is executed in the binder thread serving a particular client process:
6943 // no risk to block the whole media server process or mixer threads is we are stuck here
6944 Mutex::Autolock _l(mCblk->lock);
6945 if (mCblk->clientIndex > EFFECT_PARAM_BUFFER_SIZE ||
6946 mCblk->serverIndex > EFFECT_PARAM_BUFFER_SIZE) {
6947 mCblk->serverIndex = 0;
6948 mCblk->clientIndex = 0;
6949 return BAD_VALUE;
6950 }
6951 status_t status = NO_ERROR;
6952 while (mCblk->serverIndex < mCblk->clientIndex) {
6953 int reply;
Eric Laurent25f43952010-07-28 05:40:18 -07006954 uint32_t rsize = sizeof(int);
Mathias Agopian65ab4712010-07-14 17:59:35 -07006955 int *p = (int *)(mBuffer + mCblk->serverIndex);
6956 int size = *p++;
6957 if (((uint8_t *)p + size) > mBuffer + mCblk->clientIndex) {
6958 LOGW("command(): invalid parameter block size");
6959 break;
6960 }
6961 effect_param_t *param = (effect_param_t *)p;
6962 if (param->psize == 0 || param->vsize == 0) {
6963 LOGW("command(): null parameter or value size");
6964 mCblk->serverIndex += size;
6965 continue;
6966 }
Eric Laurent25f43952010-07-28 05:40:18 -07006967 uint32_t psize = sizeof(effect_param_t) +
6968 ((param->psize - 1) / sizeof(int) + 1) * sizeof(int) +
6969 param->vsize;
6970 status_t ret = mEffect->command(EFFECT_CMD_SET_PARAM,
6971 psize,
6972 p,
6973 &rsize,
6974 &reply);
Eric Laurentaeae3de2010-09-02 11:56:55 -07006975 // stop at first error encountered
6976 if (ret != NO_ERROR) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07006977 status = ret;
Eric Laurentaeae3de2010-09-02 11:56:55 -07006978 *(int *)pReplyData = reply;
6979 break;
6980 } else if (reply != NO_ERROR) {
6981 *(int *)pReplyData = reply;
6982 break;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006983 }
6984 mCblk->serverIndex += size;
6985 }
6986 mCblk->serverIndex = 0;
6987 mCblk->clientIndex = 0;
6988 return status;
6989 } else if (cmdCode == EFFECT_CMD_ENABLE) {
Eric Laurentaeae3de2010-09-02 11:56:55 -07006990 *(int *)pReplyData = NO_ERROR;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006991 return enable();
6992 } else if (cmdCode == EFFECT_CMD_DISABLE) {
Eric Laurentaeae3de2010-09-02 11:56:55 -07006993 *(int *)pReplyData = NO_ERROR;
Mathias Agopian65ab4712010-07-14 17:59:35 -07006994 return disable();
6995 }
6996
6997 return mEffect->command(cmdCode, cmdSize, pCmdData, replySize, pReplyData);
6998}
6999
7000sp<IMemory> AudioFlinger::EffectHandle::getCblk() const {
7001 return mCblkMemory;
7002}
7003
Eric Laurent59255e42011-07-27 19:49:51 -07007004void AudioFlinger::EffectHandle::setControl(bool hasControl, bool signal, bool enabled)
Mathias Agopian65ab4712010-07-14 17:59:35 -07007005{
Steve Block3856b092011-10-20 11:56:00 +01007006 ALOGV("setControl %p control %d", this, hasControl);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007007
7008 mHasControl = hasControl;
Eric Laurent59255e42011-07-27 19:49:51 -07007009 mEnabled = enabled;
7010
Mathias Agopian65ab4712010-07-14 17:59:35 -07007011 if (signal && mEffectClient != 0) {
7012 mEffectClient->controlStatusChanged(hasControl);
7013 }
7014}
7015
Eric Laurent25f43952010-07-28 05:40:18 -07007016void AudioFlinger::EffectHandle::commandExecuted(uint32_t cmdCode,
7017 uint32_t cmdSize,
7018 void *pCmdData,
7019 uint32_t replySize,
7020 void *pReplyData)
Mathias Agopian65ab4712010-07-14 17:59:35 -07007021{
7022 if (mEffectClient != 0) {
7023 mEffectClient->commandExecuted(cmdCode, cmdSize, pCmdData, replySize, pReplyData);
7024 }
7025}
7026
7027
7028
7029void AudioFlinger::EffectHandle::setEnabled(bool enabled)
7030{
7031 if (mEffectClient != 0) {
7032 mEffectClient->enableStatusChanged(enabled);
7033 }
7034}
7035
7036status_t AudioFlinger::EffectHandle::onTransact(
7037 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
7038{
7039 return BnEffect::onTransact(code, data, reply, flags);
7040}
7041
7042
7043void AudioFlinger::EffectHandle::dump(char* buffer, size_t size)
7044{
Marco Nelissen3a34bef2011-08-02 13:33:41 -07007045 bool locked = mCblk ? tryLock(mCblk->lock) : false;
Mathias Agopian65ab4712010-07-14 17:59:35 -07007046
7047 snprintf(buffer, size, "\t\t\t%05d %05d %01u %01u %05u %05u\n",
7048 (mClient == NULL) ? getpid() : mClient->pid(),
7049 mPriority,
7050 mHasControl,
7051 !locked,
Marco Nelissen3a34bef2011-08-02 13:33:41 -07007052 mCblk ? mCblk->clientIndex : 0,
7053 mCblk ? mCblk->serverIndex : 0
Mathias Agopian65ab4712010-07-14 17:59:35 -07007054 );
7055
7056 if (locked) {
7057 mCblk->lock.unlock();
7058 }
7059}
7060
7061#undef LOG_TAG
7062#define LOG_TAG "AudioFlinger::EffectChain"
7063
7064AudioFlinger::EffectChain::EffectChain(const wp<ThreadBase>& wThread,
7065 int sessionId)
Eric Laurent544fe9b2011-11-11 15:42:52 -08007066 : mThread(wThread), mSessionId(sessionId), mActiveTrackCnt(0), mTrackCnt(0), mTailBufferCount(0),
Eric Laurentb469b942011-05-09 12:09:06 -07007067 mOwnInBuffer(false), mVolumeCtrlIdx(-1), mLeftVolume(UINT_MAX), mRightVolume(UINT_MAX),
7068 mNewLeftVolume(UINT_MAX), mNewRightVolume(UINT_MAX)
Mathias Agopian65ab4712010-07-14 17:59:35 -07007069{
Dima Zavinfce7a472011-04-19 22:30:36 -07007070 mStrategy = AudioSystem::getStrategyForStream(AUDIO_STREAM_MUSIC);
Eric Laurent544fe9b2011-11-11 15:42:52 -08007071 sp<ThreadBase> thread = mThread.promote();
7072 if (thread == 0) {
7073 return;
7074 }
7075 mMaxTailBuffers = ((kProcessTailDurationMs * thread->sampleRate()) / 1000) /
7076 thread->frameCount();
Mathias Agopian65ab4712010-07-14 17:59:35 -07007077}
7078
7079AudioFlinger::EffectChain::~EffectChain()
7080{
7081 if (mOwnInBuffer) {
7082 delete mInBuffer;
7083 }
7084
7085}
7086
Eric Laurent59255e42011-07-27 19:49:51 -07007087// getEffectFromDesc_l() must be called with ThreadBase::mLock held
Eric Laurentcab11242010-07-15 12:50:15 -07007088sp<AudioFlinger::EffectModule> AudioFlinger::EffectChain::getEffectFromDesc_l(effect_descriptor_t *descriptor)
Mathias Agopian65ab4712010-07-14 17:59:35 -07007089{
7090 sp<EffectModule> effect;
7091 size_t size = mEffects.size();
7092
7093 for (size_t i = 0; i < size; i++) {
7094 if (memcmp(&mEffects[i]->desc().uuid, &descriptor->uuid, sizeof(effect_uuid_t)) == 0) {
7095 effect = mEffects[i];
7096 break;
7097 }
7098 }
7099 return effect;
7100}
7101
Eric Laurent59255e42011-07-27 19:49:51 -07007102// getEffectFromId_l() must be called with ThreadBase::mLock held
Eric Laurentcab11242010-07-15 12:50:15 -07007103sp<AudioFlinger::EffectModule> AudioFlinger::EffectChain::getEffectFromId_l(int id)
Mathias Agopian65ab4712010-07-14 17:59:35 -07007104{
7105 sp<EffectModule> effect;
7106 size_t size = mEffects.size();
7107
7108 for (size_t i = 0; i < size; i++) {
Eric Laurentde070132010-07-13 04:45:46 -07007109 // by convention, return first effect if id provided is 0 (0 is never a valid id)
7110 if (id == 0 || mEffects[i]->id() == id) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07007111 effect = mEffects[i];
7112 break;
7113 }
7114 }
7115 return effect;
7116}
7117
Eric Laurent59255e42011-07-27 19:49:51 -07007118// getEffectFromType_l() must be called with ThreadBase::mLock held
7119sp<AudioFlinger::EffectModule> AudioFlinger::EffectChain::getEffectFromType_l(
7120 const effect_uuid_t *type)
7121{
7122 sp<EffectModule> effect;
7123 size_t size = mEffects.size();
7124
7125 for (size_t i = 0; i < size; i++) {
7126 if (memcmp(&mEffects[i]->desc().type, type, sizeof(effect_uuid_t)) == 0) {
7127 effect = mEffects[i];
7128 break;
7129 }
7130 }
7131 return effect;
7132}
7133
Mathias Agopian65ab4712010-07-14 17:59:35 -07007134// Must be called with EffectChain::mLock locked
7135void AudioFlinger::EffectChain::process_l()
7136{
Eric Laurentdac69112010-09-28 14:09:57 -07007137 sp<ThreadBase> thread = mThread.promote();
7138 if (thread == 0) {
7139 LOGW("process_l(): cannot promote mixer thread");
7140 return;
7141 }
Dima Zavinfce7a472011-04-19 22:30:36 -07007142 bool isGlobalSession = (mSessionId == AUDIO_SESSION_OUTPUT_MIX) ||
7143 (mSessionId == AUDIO_SESSION_OUTPUT_STAGE);
Eric Laurent544fe9b2011-11-11 15:42:52 -08007144 // always process effects unless no more tracks are on the session and the effect tail
7145 // has been rendered
7146 bool doProcess = true;
Eric Laurentdac69112010-09-28 14:09:57 -07007147 if (!isGlobalSession) {
Eric Laurent544fe9b2011-11-11 15:42:52 -08007148 bool tracksOnSession = (trackCnt() != 0);
Eric Laurentb469b942011-05-09 12:09:06 -07007149
Eric Laurent544fe9b2011-11-11 15:42:52 -08007150 if (!tracksOnSession && mTailBufferCount == 0) {
7151 doProcess = false;
7152 }
7153
7154 if (activeTrackCnt() == 0) {
7155 // if no track is active and the effect tail has not been rendered,
7156 // the input buffer must be cleared here as the mixer process will not do it
7157 if (tracksOnSession || mTailBufferCount > 0) {
7158 size_t numSamples = thread->frameCount() * thread->channelCount();
7159 memset(mInBuffer, 0, numSamples * sizeof(int16_t));
7160 if (mTailBufferCount > 0) {
7161 mTailBufferCount--;
7162 }
7163 }
7164 }
Eric Laurentdac69112010-09-28 14:09:57 -07007165 }
7166
Mathias Agopian65ab4712010-07-14 17:59:35 -07007167 size_t size = mEffects.size();
Eric Laurent544fe9b2011-11-11 15:42:52 -08007168 if (doProcess) {
Eric Laurentdac69112010-09-28 14:09:57 -07007169 for (size_t i = 0; i < size; i++) {
7170 mEffects[i]->process();
7171 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07007172 }
7173 for (size_t i = 0; i < size; i++) {
7174 mEffects[i]->updateState();
7175 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07007176}
7177
Eric Laurentcab11242010-07-15 12:50:15 -07007178// addEffect_l() must be called with PlaybackThread::mLock held
Eric Laurentde070132010-07-13 04:45:46 -07007179status_t AudioFlinger::EffectChain::addEffect_l(const sp<EffectModule>& effect)
Mathias Agopian65ab4712010-07-14 17:59:35 -07007180{
7181 effect_descriptor_t desc = effect->desc();
7182 uint32_t insertPref = desc.flags & EFFECT_FLAG_INSERT_MASK;
7183
7184 Mutex::Autolock _l(mLock);
Eric Laurentde070132010-07-13 04:45:46 -07007185 effect->setChain(this);
7186 sp<ThreadBase> thread = mThread.promote();
7187 if (thread == 0) {
7188 return NO_INIT;
7189 }
7190 effect->setThread(thread);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007191
7192 if ((desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
7193 // Auxiliary effects are inserted at the beginning of mEffects vector as
7194 // they are processed first and accumulated in chain input buffer
7195 mEffects.insertAt(effect, 0);
Eric Laurentde070132010-07-13 04:45:46 -07007196
Mathias Agopian65ab4712010-07-14 17:59:35 -07007197 // the input buffer for auxiliary effect contains mono samples in
7198 // 32 bit format. This is to avoid saturation in AudoMixer
7199 // accumulation stage. Saturation is done in EffectModule::process() before
7200 // calling the process in effect engine
7201 size_t numSamples = thread->frameCount();
7202 int32_t *buffer = new int32_t[numSamples];
7203 memset(buffer, 0, numSamples * sizeof(int32_t));
7204 effect->setInBuffer((int16_t *)buffer);
7205 // auxiliary effects output samples to chain input buffer for further processing
7206 // by insert effects
7207 effect->setOutBuffer(mInBuffer);
7208 } else {
7209 // Insert effects are inserted at the end of mEffects vector as they are processed
7210 // after track and auxiliary effects.
7211 // Insert effect order as a function of indicated preference:
7212 // if EFFECT_FLAG_INSERT_EXCLUSIVE, insert in first position or reject if
7213 // another effect is present
7214 // else if EFFECT_FLAG_INSERT_FIRST, insert in first position or after the
7215 // last effect claiming first position
7216 // else if EFFECT_FLAG_INSERT_LAST, insert in last position or before the
7217 // first effect claiming last position
7218 // else if EFFECT_FLAG_INSERT_ANY insert after first or before last
7219 // Reject insertion if an effect with EFFECT_FLAG_INSERT_EXCLUSIVE is
7220 // already present
7221
7222 int size = (int)mEffects.size();
7223 int idx_insert = size;
7224 int idx_insert_first = -1;
7225 int idx_insert_last = -1;
7226
7227 for (int i = 0; i < size; i++) {
7228 effect_descriptor_t d = mEffects[i]->desc();
7229 uint32_t iMode = d.flags & EFFECT_FLAG_TYPE_MASK;
7230 uint32_t iPref = d.flags & EFFECT_FLAG_INSERT_MASK;
7231 if (iMode == EFFECT_FLAG_TYPE_INSERT) {
7232 // check invalid effect chaining combinations
7233 if (insertPref == EFFECT_FLAG_INSERT_EXCLUSIVE ||
7234 iPref == EFFECT_FLAG_INSERT_EXCLUSIVE) {
Eric Laurentcab11242010-07-15 12:50:15 -07007235 LOGW("addEffect_l() could not insert effect %s: exclusive conflict with %s", desc.name, d.name);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007236 return INVALID_OPERATION;
7237 }
7238 // remember position of first insert effect and by default
7239 // select this as insert position for new effect
7240 if (idx_insert == size) {
7241 idx_insert = i;
7242 }
7243 // remember position of last insert effect claiming
7244 // first position
7245 if (iPref == EFFECT_FLAG_INSERT_FIRST) {
7246 idx_insert_first = i;
7247 }
7248 // remember position of first insert effect claiming
7249 // last position
7250 if (iPref == EFFECT_FLAG_INSERT_LAST &&
7251 idx_insert_last == -1) {
7252 idx_insert_last = i;
7253 }
7254 }
7255 }
7256
7257 // modify idx_insert from first position if needed
7258 if (insertPref == EFFECT_FLAG_INSERT_LAST) {
7259 if (idx_insert_last != -1) {
7260 idx_insert = idx_insert_last;
7261 } else {
7262 idx_insert = size;
7263 }
7264 } else {
7265 if (idx_insert_first != -1) {
7266 idx_insert = idx_insert_first + 1;
7267 }
7268 }
7269
7270 // always read samples from chain input buffer
7271 effect->setInBuffer(mInBuffer);
7272
7273 // if last effect in the chain, output samples to chain
7274 // output buffer, otherwise to chain input buffer
7275 if (idx_insert == size) {
7276 if (idx_insert != 0) {
7277 mEffects[idx_insert-1]->setOutBuffer(mInBuffer);
7278 mEffects[idx_insert-1]->configure();
7279 }
7280 effect->setOutBuffer(mOutBuffer);
7281 } else {
7282 effect->setOutBuffer(mInBuffer);
7283 }
7284 mEffects.insertAt(effect, idx_insert);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007285
Steve Block3856b092011-10-20 11:56:00 +01007286 ALOGV("addEffect_l() effect %p, added in chain %p at rank %d", effect.get(), this, idx_insert);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007287 }
7288 effect->configure();
7289 return NO_ERROR;
7290}
7291
Eric Laurentcab11242010-07-15 12:50:15 -07007292// removeEffect_l() must be called with PlaybackThread::mLock held
7293size_t AudioFlinger::EffectChain::removeEffect_l(const sp<EffectModule>& effect)
Mathias Agopian65ab4712010-07-14 17:59:35 -07007294{
7295 Mutex::Autolock _l(mLock);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007296 int size = (int)mEffects.size();
7297 int i;
7298 uint32_t type = effect->desc().flags & EFFECT_FLAG_TYPE_MASK;
7299
7300 for (i = 0; i < size; i++) {
7301 if (effect == mEffects[i]) {
Eric Laurentec437d82011-07-26 20:54:46 -07007302 // calling stop here will remove pre-processing effect from the audio HAL.
7303 // This is safe as we hold the EffectChain mutex which guarantees that we are not in
7304 // the middle of a read from audio HAL
Eric Laurentec35a142011-10-05 17:42:25 -07007305 if (mEffects[i]->state() == EffectModule::ACTIVE ||
7306 mEffects[i]->state() == EffectModule::STOPPING) {
7307 mEffects[i]->stop();
7308 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07007309 if (type == EFFECT_FLAG_TYPE_AUXILIARY) {
7310 delete[] effect->inBuffer();
7311 } else {
7312 if (i == size - 1 && i != 0) {
7313 mEffects[i - 1]->setOutBuffer(mOutBuffer);
7314 mEffects[i - 1]->configure();
7315 }
7316 }
7317 mEffects.removeAt(i);
Steve Block3856b092011-10-20 11:56:00 +01007318 ALOGV("removeEffect_l() effect %p, removed from chain %p at rank %d", effect.get(), this, i);
Mathias Agopian65ab4712010-07-14 17:59:35 -07007319 break;
7320 }
7321 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07007322
7323 return mEffects.size();
7324}
7325
Eric Laurentcab11242010-07-15 12:50:15 -07007326// setDevice_l() must be called with PlaybackThread::mLock held
7327void AudioFlinger::EffectChain::setDevice_l(uint32_t device)
Mathias Agopian65ab4712010-07-14 17:59:35 -07007328{
7329 size_t size = mEffects.size();
7330 for (size_t i = 0; i < size; i++) {
7331 mEffects[i]->setDevice(device);
7332 }
7333}
7334
Eric Laurentcab11242010-07-15 12:50:15 -07007335// setMode_l() must be called with PlaybackThread::mLock held
7336void AudioFlinger::EffectChain::setMode_l(uint32_t mode)
Mathias Agopian65ab4712010-07-14 17:59:35 -07007337{
7338 size_t size = mEffects.size();
7339 for (size_t i = 0; i < size; i++) {
7340 mEffects[i]->setMode(mode);
7341 }
7342}
7343
Eric Laurentcab11242010-07-15 12:50:15 -07007344// setVolume_l() must be called with PlaybackThread::mLock held
7345bool AudioFlinger::EffectChain::setVolume_l(uint32_t *left, uint32_t *right)
Mathias Agopian65ab4712010-07-14 17:59:35 -07007346{
7347 uint32_t newLeft = *left;
7348 uint32_t newRight = *right;
7349 bool hasControl = false;
Eric Laurentcab11242010-07-15 12:50:15 -07007350 int ctrlIdx = -1;
7351 size_t size = mEffects.size();
Mathias Agopian65ab4712010-07-14 17:59:35 -07007352
Eric Laurentcab11242010-07-15 12:50:15 -07007353 // first update volume controller
7354 for (size_t i = size; i > 0; i--) {
Eric Laurent8f45bd72010-08-31 13:50:07 -07007355 if (mEffects[i - 1]->isProcessEnabled() &&
Eric Laurentcab11242010-07-15 12:50:15 -07007356 (mEffects[i - 1]->desc().flags & EFFECT_FLAG_VOLUME_MASK) == EFFECT_FLAG_VOLUME_CTRL) {
7357 ctrlIdx = i - 1;
Eric Laurentf997cab2010-07-19 06:24:46 -07007358 hasControl = true;
Eric Laurentcab11242010-07-15 12:50:15 -07007359 break;
7360 }
7361 }
7362
7363 if (ctrlIdx == mVolumeCtrlIdx && *left == mLeftVolume && *right == mRightVolume) {
Eric Laurentf997cab2010-07-19 06:24:46 -07007364 if (hasControl) {
7365 *left = mNewLeftVolume;
7366 *right = mNewRightVolume;
7367 }
7368 return hasControl;
Eric Laurentcab11242010-07-15 12:50:15 -07007369 }
7370
7371 mVolumeCtrlIdx = ctrlIdx;
Eric Laurentf997cab2010-07-19 06:24:46 -07007372 mLeftVolume = newLeft;
7373 mRightVolume = newRight;
Eric Laurentcab11242010-07-15 12:50:15 -07007374
7375 // second get volume update from volume controller
7376 if (ctrlIdx >= 0) {
7377 mEffects[ctrlIdx]->setVolume(&newLeft, &newRight, true);
Eric Laurentf997cab2010-07-19 06:24:46 -07007378 mNewLeftVolume = newLeft;
7379 mNewRightVolume = newRight;
Mathias Agopian65ab4712010-07-14 17:59:35 -07007380 }
7381 // then indicate volume to all other effects in chain.
7382 // Pass altered volume to effects before volume controller
7383 // and requested volume to effects after controller
7384 uint32_t lVol = newLeft;
7385 uint32_t rVol = newRight;
Eric Laurentcab11242010-07-15 12:50:15 -07007386
Mathias Agopian65ab4712010-07-14 17:59:35 -07007387 for (size_t i = 0; i < size; i++) {
Eric Laurentcab11242010-07-15 12:50:15 -07007388 if ((int)i == ctrlIdx) continue;
7389 // this also works for ctrlIdx == -1 when there is no volume controller
7390 if ((int)i > ctrlIdx) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07007391 lVol = *left;
7392 rVol = *right;
7393 }
7394 mEffects[i]->setVolume(&lVol, &rVol, false);
7395 }
7396 *left = newLeft;
7397 *right = newRight;
7398
7399 return hasControl;
7400}
7401
Mathias Agopian65ab4712010-07-14 17:59:35 -07007402status_t AudioFlinger::EffectChain::dump(int fd, const Vector<String16>& args)
7403{
7404 const size_t SIZE = 256;
7405 char buffer[SIZE];
7406 String8 result;
7407
7408 snprintf(buffer, SIZE, "Effects for session %d:\n", mSessionId);
7409 result.append(buffer);
7410
7411 bool locked = tryLock(mLock);
7412 // failed to lock - AudioFlinger is probably deadlocked
7413 if (!locked) {
7414 result.append("\tCould not lock mutex:\n");
7415 }
7416
Eric Laurentcab11242010-07-15 12:50:15 -07007417 result.append("\tNum fx In buffer Out buffer Active tracks:\n");
7418 snprintf(buffer, SIZE, "\t%02d 0x%08x 0x%08x %d\n",
Mathias Agopian65ab4712010-07-14 17:59:35 -07007419 mEffects.size(),
7420 (uint32_t)mInBuffer,
7421 (uint32_t)mOutBuffer,
Mathias Agopian65ab4712010-07-14 17:59:35 -07007422 mActiveTrackCnt);
7423 result.append(buffer);
7424 write(fd, result.string(), result.size());
7425
7426 for (size_t i = 0; i < mEffects.size(); ++i) {
7427 sp<EffectModule> effect = mEffects[i];
7428 if (effect != 0) {
7429 effect->dump(fd, args);
7430 }
7431 }
7432
7433 if (locked) {
7434 mLock.unlock();
7435 }
7436
7437 return NO_ERROR;
7438}
7439
Eric Laurent59255e42011-07-27 19:49:51 -07007440// must be called with ThreadBase::mLock held
7441void AudioFlinger::EffectChain::setEffectSuspended_l(
7442 const effect_uuid_t *type, bool suspend)
7443{
7444 sp<SuspendedEffectDesc> desc;
7445 // use effect type UUID timelow as key as there is no real risk of identical
7446 // timeLow fields among effect type UUIDs.
7447 int index = mSuspendedEffects.indexOfKey(type->timeLow);
7448 if (suspend) {
7449 if (index >= 0) {
7450 desc = mSuspendedEffects.valueAt(index);
7451 } else {
7452 desc = new SuspendedEffectDesc();
7453 memcpy(&desc->mType, type, sizeof(effect_uuid_t));
7454 mSuspendedEffects.add(type->timeLow, desc);
Steve Block3856b092011-10-20 11:56:00 +01007455 ALOGV("setEffectSuspended_l() add entry for %08x", type->timeLow);
Eric Laurent59255e42011-07-27 19:49:51 -07007456 }
7457 if (desc->mRefCount++ == 0) {
7458 sp<EffectModule> effect = getEffectIfEnabled(type);
7459 if (effect != 0) {
7460 desc->mEffect = effect;
7461 effect->setSuspended(true);
7462 effect->setEnabled(false);
7463 }
7464 }
7465 } else {
7466 if (index < 0) {
7467 return;
7468 }
7469 desc = mSuspendedEffects.valueAt(index);
7470 if (desc->mRefCount <= 0) {
7471 LOGW("setEffectSuspended_l() restore refcount should not be 0 %d", desc->mRefCount);
7472 desc->mRefCount = 1;
7473 }
7474 if (--desc->mRefCount == 0) {
Steve Block3856b092011-10-20 11:56:00 +01007475 ALOGV("setEffectSuspended_l() remove entry for %08x", mSuspendedEffects.keyAt(index));
Eric Laurent59255e42011-07-27 19:49:51 -07007476 if (desc->mEffect != 0) {
7477 sp<EffectModule> effect = desc->mEffect.promote();
7478 if (effect != 0) {
7479 effect->setSuspended(false);
7480 sp<EffectHandle> handle = effect->controlHandle();
7481 if (handle != 0) {
7482 effect->setEnabled(handle->enabled());
7483 }
7484 }
7485 desc->mEffect.clear();
7486 }
7487 mSuspendedEffects.removeItemsAt(index);
7488 }
7489 }
7490}
7491
7492// must be called with ThreadBase::mLock held
7493void AudioFlinger::EffectChain::setEffectSuspendedAll_l(bool suspend)
7494{
7495 sp<SuspendedEffectDesc> desc;
7496
7497 int index = mSuspendedEffects.indexOfKey((int)kKeyForSuspendAll);
7498 if (suspend) {
7499 if (index >= 0) {
7500 desc = mSuspendedEffects.valueAt(index);
7501 } else {
7502 desc = new SuspendedEffectDesc();
7503 mSuspendedEffects.add((int)kKeyForSuspendAll, desc);
Steve Block3856b092011-10-20 11:56:00 +01007504 ALOGV("setEffectSuspendedAll_l() add entry for 0");
Eric Laurent59255e42011-07-27 19:49:51 -07007505 }
7506 if (desc->mRefCount++ == 0) {
7507 Vector< sp<EffectModule> > effects = getSuspendEligibleEffects();
7508 for (size_t i = 0; i < effects.size(); i++) {
7509 setEffectSuspended_l(&effects[i]->desc().type, true);
7510 }
7511 }
7512 } else {
7513 if (index < 0) {
7514 return;
7515 }
7516 desc = mSuspendedEffects.valueAt(index);
7517 if (desc->mRefCount <= 0) {
7518 LOGW("setEffectSuspendedAll_l() restore refcount should not be 0 %d", desc->mRefCount);
7519 desc->mRefCount = 1;
7520 }
7521 if (--desc->mRefCount == 0) {
7522 Vector<const effect_uuid_t *> types;
7523 for (size_t i = 0; i < mSuspendedEffects.size(); i++) {
7524 if (mSuspendedEffects.keyAt(i) == (int)kKeyForSuspendAll) {
7525 continue;
7526 }
7527 types.add(&mSuspendedEffects.valueAt(i)->mType);
7528 }
7529 for (size_t i = 0; i < types.size(); i++) {
7530 setEffectSuspended_l(types[i], false);
7531 }
Steve Block3856b092011-10-20 11:56:00 +01007532 ALOGV("setEffectSuspendedAll_l() remove entry for %08x", mSuspendedEffects.keyAt(index));
Eric Laurent59255e42011-07-27 19:49:51 -07007533 mSuspendedEffects.removeItem((int)kKeyForSuspendAll);
7534 }
7535 }
7536}
7537
Eric Laurent6bffdb82011-09-23 08:40:41 -07007538
7539// The volume effect is used for automated tests only
7540#ifndef OPENSL_ES_H_
7541static const effect_uuid_t SL_IID_VOLUME_ = { 0x09e8ede0, 0xddde, 0x11db, 0xb4f6,
7542 { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } };
7543const effect_uuid_t * const SL_IID_VOLUME = &SL_IID_VOLUME_;
7544#endif //OPENSL_ES_H_
7545
Eric Laurentdb7c0792011-08-10 10:37:50 -07007546bool AudioFlinger::EffectChain::isEffectEligibleForSuspend(const effect_descriptor_t& desc)
7547{
7548 // auxiliary effects and visualizer are never suspended on output mix
7549 if ((mSessionId == AUDIO_SESSION_OUTPUT_MIX) &&
7550 (((desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) ||
Eric Laurent6bffdb82011-09-23 08:40:41 -07007551 (memcmp(&desc.type, SL_IID_VISUALIZATION, sizeof(effect_uuid_t)) == 0) ||
7552 (memcmp(&desc.type, SL_IID_VOLUME, sizeof(effect_uuid_t)) == 0))) {
Eric Laurentdb7c0792011-08-10 10:37:50 -07007553 return false;
7554 }
7555 return true;
7556}
7557
Eric Laurent59255e42011-07-27 19:49:51 -07007558Vector< sp<AudioFlinger::EffectModule> > AudioFlinger::EffectChain::getSuspendEligibleEffects()
7559{
7560 Vector< sp<EffectModule> > effects;
7561 for (size_t i = 0; i < mEffects.size(); i++) {
Eric Laurentdb7c0792011-08-10 10:37:50 -07007562 if (!isEffectEligibleForSuspend(mEffects[i]->desc())) {
Eric Laurent59255e42011-07-27 19:49:51 -07007563 continue;
7564 }
7565 effects.add(mEffects[i]);
7566 }
7567 return effects;
7568}
7569
7570sp<AudioFlinger::EffectModule> AudioFlinger::EffectChain::getEffectIfEnabled(
7571 const effect_uuid_t *type)
7572{
7573 sp<EffectModule> effect;
7574 effect = getEffectFromType_l(type);
7575 if (effect != 0 && !effect->isEnabled()) {
7576 effect.clear();
7577 }
7578 return effect;
7579}
7580
7581void AudioFlinger::EffectChain::checkSuspendOnEffectEnabled(const sp<EffectModule>& effect,
7582 bool enabled)
7583{
7584 int index = mSuspendedEffects.indexOfKey(effect->desc().type.timeLow);
7585 if (enabled) {
7586 if (index < 0) {
7587 // if the effect is not suspend check if all effects are suspended
7588 index = mSuspendedEffects.indexOfKey((int)kKeyForSuspendAll);
7589 if (index < 0) {
7590 return;
7591 }
Eric Laurentdb7c0792011-08-10 10:37:50 -07007592 if (!isEffectEligibleForSuspend(effect->desc())) {
7593 return;
7594 }
Eric Laurent59255e42011-07-27 19:49:51 -07007595 setEffectSuspended_l(&effect->desc().type, enabled);
7596 index = mSuspendedEffects.indexOfKey(effect->desc().type.timeLow);
Eric Laurentdb7c0792011-08-10 10:37:50 -07007597 if (index < 0) {
7598 LOGW("checkSuspendOnEffectEnabled() Fx should be suspended here!");
7599 return;
7600 }
Eric Laurent59255e42011-07-27 19:49:51 -07007601 }
Steve Block3856b092011-10-20 11:56:00 +01007602 ALOGV("checkSuspendOnEffectEnabled() enable suspending fx %08x",
Eric Laurent59255e42011-07-27 19:49:51 -07007603 effect->desc().type.timeLow);
7604 sp<SuspendedEffectDesc> desc = mSuspendedEffects.valueAt(index);
7605 // if effect is requested to suspended but was not yet enabled, supend it now.
7606 if (desc->mEffect == 0) {
7607 desc->mEffect = effect;
7608 effect->setEnabled(false);
7609 effect->setSuspended(true);
7610 }
7611 } else {
7612 if (index < 0) {
7613 return;
7614 }
Steve Block3856b092011-10-20 11:56:00 +01007615 ALOGV("checkSuspendOnEffectEnabled() disable restoring fx %08x",
Eric Laurent59255e42011-07-27 19:49:51 -07007616 effect->desc().type.timeLow);
7617 sp<SuspendedEffectDesc> desc = mSuspendedEffects.valueAt(index);
7618 desc->mEffect.clear();
7619 effect->setSuspended(false);
7620 }
7621}
7622
Mathias Agopian65ab4712010-07-14 17:59:35 -07007623#undef LOG_TAG
7624#define LOG_TAG "AudioFlinger"
7625
7626// ----------------------------------------------------------------------------
7627
7628status_t AudioFlinger::onTransact(
7629 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
7630{
7631 return BnAudioFlinger::onTransact(code, data, reply, flags);
7632}
7633
Mathias Agopian65ab4712010-07-14 17:59:35 -07007634}; // namespace android