blob: a8f051107bb6aecee47a68d259251f78834e4865 [file] [log] [blame]
Eric Laurentca7cc822012-11-19 14:55:58 -08001/*
Alok Kediya601e9b52013-09-27 11:55:10 +05302** Copyright (c) 2013, The Linux Foundation. All rights reserved.
3** Not a Contribution.
Eric Laurentca7cc822012-11-19 14:55:58 -08004** Copyright 2012, The Android Open Source Project
5**
6** Licensed under the Apache License, Version 2.0 (the "License");
7** you may not use this file except in compliance with the License.
8** You may obtain a copy of the License at
9**
10** http://www.apache.org/licenses/LICENSE-2.0
11**
12** Unless required by applicable law or agreed to in writing, software
13** distributed under the License is distributed on an "AS IS" BASIS,
14** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15** See the License for the specific language governing permissions and
16** limitations under the License.
17*/
18
19
20#define LOG_TAG "AudioFlinger"
21//#define LOG_NDEBUG 0
22
Glenn Kasten153b9fe2013-07-15 11:23:36 -070023#include "Configuration.h"
Eric Laurentca7cc822012-11-19 14:55:58 -080024#include <utils/Log.h>
25#include <audio_effects/effect_visualizer.h>
26#include <audio_utils/primitives.h>
27#include <private/media/AudioEffectShared.h>
28#include <media/EffectsFactoryApi.h>
29
30#include "AudioFlinger.h"
31#include "ServiceUtilities.h"
32
Alok Kediya601e9b52013-09-27 11:55:10 +053033#ifdef SRS_PROCESSING
34#include "srs_processing.h"
35#include "postpro_patch_ics.h"
36#endif
37
Eric Laurentca7cc822012-11-19 14:55:58 -080038// ----------------------------------------------------------------------------
39
40// Note: the following macro is used for extremely verbose logging message. In
41// order to run with ALOG_ASSERT turned on, we need to have LOG_NDEBUG set to
42// 0; but one side effect of this is to turn all LOGV's as well. Some messages
43// are so verbose that we want to suppress them even when we have ALOG_ASSERT
44// turned on. Do not uncomment the #def below unless you really know what you
45// are doing and want to see all of the extremely verbose messages.
46//#define VERY_VERY_VERBOSE_LOGGING
47#ifdef VERY_VERY_VERBOSE_LOGGING
48#define ALOGVV ALOGV
49#else
50#define ALOGVV(a...) do { } while(0)
51#endif
52
53namespace android {
54
55// ----------------------------------------------------------------------------
56// EffectModule implementation
57// ----------------------------------------------------------------------------
58
59#undef LOG_TAG
60#define LOG_TAG "AudioFlinger::EffectModule"
61
62AudioFlinger::EffectModule::EffectModule(ThreadBase *thread,
63 const wp<AudioFlinger::EffectChain>& chain,
64 effect_descriptor_t *desc,
65 int id,
66 int sessionId)
67 : mPinned(sessionId > AUDIO_SESSION_OUTPUT_MIX),
68 mThread(thread), mChain(chain), mId(id), mSessionId(sessionId),
69 mDescriptor(*desc),
70 // mConfig is set by configure() and not used before then
71 mEffectInterface(NULL),
72 mStatus(NO_INIT), mState(IDLE),
73 // mMaxDisableWaitCnt is set by configure() and not used before then
74 // mDisableWaitCnt is set by process() and updateState() and not used before then
Ethan Chen8d420ed2013-11-14 00:40:54 -080075#ifdef QCOM_HARDWARE
Alok Kediya601e9b52013-09-27 11:55:10 +053076 mSuspended(false), mIsForLPA(false)
Ethan Chen8d420ed2013-11-14 00:40:54 -080077#else
78 mSuspended(false)
79#endif
Eric Laurentca7cc822012-11-19 14:55:58 -080080{
81 ALOGV("Constructor %p", this);
82 int lStatus;
83
84 // create effect engine from effect factory
85 mStatus = EffectCreate(&desc->uuid, sessionId, thread->id(), &mEffectInterface);
86
87 if (mStatus != NO_ERROR) {
88 return;
89 }
90 lStatus = init();
91 if (lStatus < 0) {
92 mStatus = lStatus;
93 goto Error;
94 }
95
96 ALOGV("Constructor success name %s, Interface %p", mDescriptor.name, mEffectInterface);
97 return;
98Error:
99 EffectRelease(mEffectInterface);
100 mEffectInterface = NULL;
101 ALOGV("Constructor Error %d", mStatus);
102}
103
104AudioFlinger::EffectModule::~EffectModule()
105{
106 ALOGV("Destructor %p", this);
107 if (mEffectInterface != NULL) {
Eric Laurentbfb1b832013-01-07 09:53:42 -0800108 remove_effect_from_hal_l();
Eric Laurentca7cc822012-11-19 14:55:58 -0800109 // release effect engine
110 EffectRelease(mEffectInterface);
111 }
112}
113
114status_t AudioFlinger::EffectModule::addHandle(EffectHandle *handle)
115{
116 status_t status;
117
118 Mutex::Autolock _l(mLock);
119 int priority = handle->priority();
120 size_t size = mHandles.size();
121 EffectHandle *controlHandle = NULL;
122 size_t i;
123 for (i = 0; i < size; i++) {
124 EffectHandle *h = mHandles[i];
125 if (h == NULL || h->destroyed_l()) {
126 continue;
127 }
128 // first non destroyed handle is considered in control
129 if (controlHandle == NULL)
130 controlHandle = h;
131 if (h->priority() <= priority) {
132 break;
133 }
134 }
135 // if inserted in first place, move effect control from previous owner to this handle
136 if (i == 0) {
137 bool enabled = false;
138 if (controlHandle != NULL) {
139 enabled = controlHandle->enabled();
140 controlHandle->setControl(false/*hasControl*/, true /*signal*/, enabled /*enabled*/);
141 }
142 handle->setControl(true /*hasControl*/, false /*signal*/, enabled /*enabled*/);
143 status = NO_ERROR;
144 } else {
145 status = ALREADY_EXISTS;
146 }
147 ALOGV("addHandle() %p added handle %p in position %d", this, handle, i);
148 mHandles.insertAt(handle, i);
149 return status;
150}
151
152size_t AudioFlinger::EffectModule::removeHandle(EffectHandle *handle)
153{
154 Mutex::Autolock _l(mLock);
155 size_t size = mHandles.size();
156 size_t i;
157 for (i = 0; i < size; i++) {
158 if (mHandles[i] == handle) {
159 break;
160 }
161 }
162 if (i == size) {
163 return size;
164 }
165 ALOGV("removeHandle() %p removed handle %p in position %d", this, handle, i);
166
167 mHandles.removeAt(i);
168 // if removed from first place, move effect control from this handle to next in line
169 if (i == 0) {
170 EffectHandle *h = controlHandle_l();
171 if (h != NULL) {
172 h->setControl(true /*hasControl*/, true /*signal*/ , handle->enabled() /*enabled*/);
173 }
174 }
175
176 // Prevent calls to process() and other functions on effect interface from now on.
177 // The effect engine will be released by the destructor when the last strong reference on
178 // this object is released which can happen after next process is called.
179 if (mHandles.size() == 0 && !mPinned) {
180 mState = DESTROYED;
181 }
182
183 return mHandles.size();
184}
185
186// must be called with EffectModule::mLock held
187AudioFlinger::EffectHandle *AudioFlinger::EffectModule::controlHandle_l()
188{
189 // the first valid handle in the list has control over the module
190 for (size_t i = 0; i < mHandles.size(); i++) {
191 EffectHandle *h = mHandles[i];
192 if (h != NULL && !h->destroyed_l()) {
193 return h;
194 }
195 }
196
197 return NULL;
198}
199
200size_t AudioFlinger::EffectModule::disconnect(EffectHandle *handle, bool unpinIfLast)
201{
202 ALOGV("disconnect() %p handle %p", this, handle);
203 // keep a strong reference on this EffectModule to avoid calling the
204 // destructor before we exit
205 sp<EffectModule> keep(this);
206 {
207 sp<ThreadBase> thread = mThread.promote();
208 if (thread != 0) {
209 thread->disconnectEffect(keep, handle, unpinIfLast);
210 }
211 }
212 return mHandles.size();
213}
214
215void AudioFlinger::EffectModule::updateState() {
216 Mutex::Autolock _l(mLock);
217
218 switch (mState) {
219 case RESTART:
220 reset_l();
221 // FALL THROUGH
222
223 case STARTING:
224 // clear auxiliary effect input buffer for next accumulation
225 if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
226 memset(mConfig.inputCfg.buffer.raw,
227 0,
228 mConfig.inputCfg.buffer.frameCount*sizeof(int32_t));
229 }
Eric Laurentd0ebb532013-04-02 16:41:41 -0700230 if (start_l() == NO_ERROR) {
231 mState = ACTIVE;
232 } else {
233 mState = IDLE;
234 }
Eric Laurentca7cc822012-11-19 14:55:58 -0800235 break;
236 case STOPPING:
Eric Laurentd0ebb532013-04-02 16:41:41 -0700237 if (stop_l() == NO_ERROR) {
238 mDisableWaitCnt = mMaxDisableWaitCnt;
239 } else {
240 mDisableWaitCnt = 1; // will cause immediate transition to IDLE
241 }
Eric Laurentca7cc822012-11-19 14:55:58 -0800242 mState = STOPPED;
243 break;
244 case STOPPED:
245 // mDisableWaitCnt is forced to 1 by process() when the engine indicates the end of the
246 // turn off sequence.
247 if (--mDisableWaitCnt == 0) {
248 reset_l();
249 mState = IDLE;
250 }
251 break;
252 default: //IDLE , ACTIVE, DESTROYED
253 break;
254 }
255}
256
257void AudioFlinger::EffectModule::process()
258{
259 Mutex::Autolock _l(mLock);
260
261 if (mState == DESTROYED || mEffectInterface == NULL ||
262 mConfig.inputCfg.buffer.raw == NULL ||
263 mConfig.outputCfg.buffer.raw == NULL) {
264 return;
265 }
266
267 if (isProcessEnabled()) {
268 // do 32 bit to 16 bit conversion for auxiliary effect input buffer
269 if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
270 ditherAndClamp(mConfig.inputCfg.buffer.s32,
271 mConfig.inputCfg.buffer.s32,
272 mConfig.inputCfg.buffer.frameCount/2);
273 }
274
275 // do the actual processing in the effect engine
276 int ret = (*mEffectInterface)->process(mEffectInterface,
277 &mConfig.inputCfg.buffer,
278 &mConfig.outputCfg.buffer);
279
280 // force transition to IDLE state when engine is ready
281 if (mState == STOPPED && ret == -ENODATA) {
282 mDisableWaitCnt = 1;
283 }
284
285 // clear auxiliary effect input buffer for next accumulation
286 if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
287 memset(mConfig.inputCfg.buffer.raw, 0,
288 mConfig.inputCfg.buffer.frameCount*sizeof(int32_t));
289 }
290 } else if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_INSERT &&
291 mConfig.inputCfg.buffer.raw != mConfig.outputCfg.buffer.raw) {
292 // If an insert effect is idle and input buffer is different from output buffer,
293 // accumulate input onto output
294 sp<EffectChain> chain = mChain.promote();
295 if (chain != 0 && chain->activeTrackCnt() != 0) {
296 size_t frameCnt = mConfig.inputCfg.buffer.frameCount * 2; //always stereo here
297 int16_t *in = mConfig.inputCfg.buffer.s16;
298 int16_t *out = mConfig.outputCfg.buffer.s16;
299 for (size_t i = 0; i < frameCnt; i++) {
300 out[i] = clamp16((int32_t)out[i] + (int32_t)in[i]);
301 }
302 }
303 }
304}
305
306void AudioFlinger::EffectModule::reset_l()
307{
Eric Laurentd0ebb532013-04-02 16:41:41 -0700308 if (mStatus != NO_ERROR || mEffectInterface == NULL) {
Eric Laurentca7cc822012-11-19 14:55:58 -0800309 return;
310 }
311 (*mEffectInterface)->command(mEffectInterface, EFFECT_CMD_RESET, 0, NULL, 0, NULL);
312}
313
Ethan Chen8d420ed2013-11-14 00:40:54 -0800314#ifdef QCOM_HARDWARE
Alok Kediya601e9b52013-09-27 11:55:10 +0530315status_t AudioFlinger::EffectModule::configure(bool isForLPA, int sampleRate, int channelCount, int frameCount)
Ethan Chen8d420ed2013-11-14 00:40:54 -0800316#else
317status_t AudioFlinger::EffectModule::configure()
318#endif
Eric Laurentca7cc822012-11-19 14:55:58 -0800319{
Eric Laurentd0ebb532013-04-02 16:41:41 -0700320 status_t status;
Alok Kediya601e9b52013-09-27 11:55:10 +0530321 status_t cmdStatus = 0;
Eric Laurentd0ebb532013-04-02 16:41:41 -0700322 sp<ThreadBase> thread;
323 uint32_t size;
324 audio_channel_mask_t channelMask;
Ethan Chen8d420ed2013-11-14 00:40:54 -0800325#ifdef QCOM_HARDWARE
Alok Kediya601e9b52013-09-27 11:55:10 +0530326 uint32_t channels;
Ethan Chen8d420ed2013-11-14 00:40:54 -0800327#endif
Eric Laurentd0ebb532013-04-02 16:41:41 -0700328
Eric Laurentca7cc822012-11-19 14:55:58 -0800329 if (mEffectInterface == NULL) {
Eric Laurentd0ebb532013-04-02 16:41:41 -0700330 status = NO_INIT;
331 goto exit;
Eric Laurentca7cc822012-11-19 14:55:58 -0800332 }
333
Eric Laurentd0ebb532013-04-02 16:41:41 -0700334 thread = mThread.promote();
Eric Laurentca7cc822012-11-19 14:55:58 -0800335 if (thread == 0) {
Eric Laurentd0ebb532013-04-02 16:41:41 -0700336 status = DEAD_OBJECT;
337 goto exit;
Eric Laurentca7cc822012-11-19 14:55:58 -0800338 }
339
340 // TODO: handle configuration of effects replacing track process
Eric Laurentd0ebb532013-04-02 16:41:41 -0700341 channelMask = thread->channelMask();
Ethan Chen8d420ed2013-11-14 00:40:54 -0800342#ifdef QCOM_HARDWARE
Alok Kediya601e9b52013-09-27 11:55:10 +0530343 if(popcount(channelMask) > 2) {
344 ALOGE("Error: Trying to apply effect on %d channel content",popcount(channelMask));
345 return INVALID_OPERATION;
346 }
347 mIsForLPA = isForLPA;
348 if(isForLPA) {
349 if (channelCount == 1) {
350 channels = AUDIO_CHANNEL_OUT_MONO;
351 } else {
352 channels = AUDIO_CHANNEL_OUT_STEREO;
353 }
354 } else {
355 if (thread->channelCount() == 1) {
356 channels = AUDIO_CHANNEL_OUT_MONO;
357 } else {
358 channels = AUDIO_CHANNEL_OUT_STEREO;
359 }
360 }
Ethan Chen8d420ed2013-11-14 00:40:54 -0800361#endif
Eric Laurentca7cc822012-11-19 14:55:58 -0800362
363 if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
364 mConfig.inputCfg.channels = AUDIO_CHANNEL_OUT_MONO;
365 } else {
366 mConfig.inputCfg.channels = channelMask;
367 }
368 mConfig.outputCfg.channels = channelMask;
369 mConfig.inputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
370 mConfig.outputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
Ethan Chen8d420ed2013-11-14 00:40:54 -0800371#ifdef QCOM_HARDWARE
Alok Kediya601e9b52013-09-27 11:55:10 +0530372 if(isForLPA){
373 mConfig.inputCfg.samplingRate = sampleRate;
374 } else {
Ethan Chen8d420ed2013-11-14 00:40:54 -0800375#endif
Alok Kediya601e9b52013-09-27 11:55:10 +0530376 mConfig.inputCfg.samplingRate = thread->sampleRate();
Ethan Chen8d420ed2013-11-14 00:40:54 -0800377#ifdef QCOM_HARDWARE
Alok Kediya601e9b52013-09-27 11:55:10 +0530378 }
Ethan Chen8d420ed2013-11-14 00:40:54 -0800379#endif
Eric Laurentca7cc822012-11-19 14:55:58 -0800380 mConfig.outputCfg.samplingRate = mConfig.inputCfg.samplingRate;
381 mConfig.inputCfg.bufferProvider.cookie = NULL;
382 mConfig.inputCfg.bufferProvider.getBuffer = NULL;
383 mConfig.inputCfg.bufferProvider.releaseBuffer = NULL;
384 mConfig.outputCfg.bufferProvider.cookie = NULL;
385 mConfig.outputCfg.bufferProvider.getBuffer = NULL;
386 mConfig.outputCfg.bufferProvider.releaseBuffer = NULL;
387 mConfig.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ;
388 // Insert effect:
389 // - in session AUDIO_SESSION_OUTPUT_MIX or AUDIO_SESSION_OUTPUT_STAGE,
390 // always overwrites output buffer: input buffer == output buffer
391 // - in other sessions:
392 // last effect in the chain accumulates in output buffer: input buffer != output buffer
393 // other effect: overwrites output buffer: input buffer == output buffer
394 // Auxiliary effect:
395 // accumulates in output buffer: input buffer != output buffer
396 // Therefore: accumulate <=> input buffer != output buffer
397 if (mConfig.inputCfg.buffer.raw != mConfig.outputCfg.buffer.raw) {
398 mConfig.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_ACCUMULATE;
399 } else {
400 mConfig.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_WRITE;
401 }
402 mConfig.inputCfg.mask = EFFECT_CONFIG_ALL;
403 mConfig.outputCfg.mask = EFFECT_CONFIG_ALL;
Ethan Chen8d420ed2013-11-14 00:40:54 -0800404#ifdef QCOM_HARDWARE
Alok Kediya601e9b52013-09-27 11:55:10 +0530405 if(isForLPA) {
406 mConfig.inputCfg.buffer.frameCount = frameCount;
407 } else {
Ethan Chen8d420ed2013-11-14 00:40:54 -0800408#endif
Alok Kediya601e9b52013-09-27 11:55:10 +0530409 mConfig.inputCfg.buffer.frameCount = thread->frameCount();
Ethan Chen8d420ed2013-11-14 00:40:54 -0800410#ifdef QCOM_HARDWARE
Alok Kediya601e9b52013-09-27 11:55:10 +0530411 }
Ethan Chen8d420ed2013-11-14 00:40:54 -0800412#endif
Eric Laurentca7cc822012-11-19 14:55:58 -0800413 mConfig.outputCfg.buffer.frameCount = mConfig.inputCfg.buffer.frameCount;
414
415 ALOGV("configure() %p thread %p buffer %p framecount %d",
416 this, thread.get(), mConfig.inputCfg.buffer.raw, mConfig.inputCfg.buffer.frameCount);
417
Eric Laurentd0ebb532013-04-02 16:41:41 -0700418 size = sizeof(int);
419 status = (*mEffectInterface)->command(mEffectInterface,
Eric Laurentca7cc822012-11-19 14:55:58 -0800420 EFFECT_CMD_SET_CONFIG,
421 sizeof(effect_config_t),
422 &mConfig,
423 &size,
424 &cmdStatus);
425 if (status == 0) {
426 status = cmdStatus;
427 }
428
429 if (status == 0 &&
430 (memcmp(&mDescriptor.type, SL_IID_VISUALIZATION, sizeof(effect_uuid_t)) == 0)) {
431 uint32_t buf32[sizeof(effect_param_t) / sizeof(uint32_t) + 2];
432 effect_param_t *p = (effect_param_t *)buf32;
433
434 p->psize = sizeof(uint32_t);
435 p->vsize = sizeof(uint32_t);
436 size = sizeof(int);
437 *(int32_t *)p->data = VISUALIZER_PARAM_LATENCY;
438
439 uint32_t latency = 0;
440 PlaybackThread *pbt = thread->mAudioFlinger->checkPlaybackThread_l(thread->mId);
441 if (pbt != NULL) {
442 latency = pbt->latency_l();
443 }
444
445 *((int32_t *)p->data + 1)= latency;
446 (*mEffectInterface)->command(mEffectInterface,
447 EFFECT_CMD_SET_PARAM,
448 sizeof(effect_param_t) + 8,
449 &buf32,
450 &size,
451 &cmdStatus);
452 }
453
454 mMaxDisableWaitCnt = (MAX_DISABLE_TIME_MS * mConfig.outputCfg.samplingRate) /
455 (1000 * mConfig.outputCfg.buffer.frameCount);
456
Eric Laurentd0ebb532013-04-02 16:41:41 -0700457exit:
458 mStatus = status;
Eric Laurentca7cc822012-11-19 14:55:58 -0800459 return status;
460}
461
462status_t AudioFlinger::EffectModule::init()
463{
464 Mutex::Autolock _l(mLock);
465 if (mEffectInterface == NULL) {
466 return NO_INIT;
467 }
Alok Kediya601e9b52013-09-27 11:55:10 +0530468 status_t cmdStatus = 0;
Eric Laurentca7cc822012-11-19 14:55:58 -0800469 uint32_t size = sizeof(status_t);
470 status_t status = (*mEffectInterface)->command(mEffectInterface,
471 EFFECT_CMD_INIT,
472 0,
473 NULL,
474 &size,
475 &cmdStatus);
476 if (status == 0) {
477 status = cmdStatus;
478 }
479 return status;
480}
481
482status_t AudioFlinger::EffectModule::start()
483{
484 Mutex::Autolock _l(mLock);
485 return start_l();
486}
487
488status_t AudioFlinger::EffectModule::start_l()
489{
490 if (mEffectInterface == NULL) {
491 return NO_INIT;
492 }
Eric Laurentd0ebb532013-04-02 16:41:41 -0700493 if (mStatus != NO_ERROR) {
494 return mStatus;
495 }
Alok Kediya601e9b52013-09-27 11:55:10 +0530496 status_t cmdStatus = 0;
Eric Laurentca7cc822012-11-19 14:55:58 -0800497 uint32_t size = sizeof(status_t);
498 status_t status = (*mEffectInterface)->command(mEffectInterface,
499 EFFECT_CMD_ENABLE,
500 0,
501 NULL,
502 &size,
503 &cmdStatus);
504 if (status == 0) {
505 status = cmdStatus;
506 }
507 if (status == 0 &&
508 ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC ||
509 (mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_POST_PROC)) {
510 sp<ThreadBase> thread = mThread.promote();
511 if (thread != 0) {
512 audio_stream_t *stream = thread->stream();
513 if (stream != NULL) {
514 stream->add_audio_effect(stream, mEffectInterface);
515 }
516 }
517 }
518 return status;
519}
520
521status_t AudioFlinger::EffectModule::stop()
522{
523 Mutex::Autolock _l(mLock);
524 return stop_l();
525}
526
527status_t AudioFlinger::EffectModule::stop_l()
528{
529 if (mEffectInterface == NULL) {
530 return NO_INIT;
531 }
Eric Laurentd0ebb532013-04-02 16:41:41 -0700532 if (mStatus != NO_ERROR) {
533 return mStatus;
534 }
Eric Laurentbfb1b832013-01-07 09:53:42 -0800535 status_t cmdStatus = NO_ERROR;
Eric Laurentca7cc822012-11-19 14:55:58 -0800536 uint32_t size = sizeof(status_t);
537 status_t status = (*mEffectInterface)->command(mEffectInterface,
538 EFFECT_CMD_DISABLE,
539 0,
540 NULL,
541 &size,
542 &cmdStatus);
Eric Laurentbfb1b832013-01-07 09:53:42 -0800543 if (status == NO_ERROR) {
Eric Laurentca7cc822012-11-19 14:55:58 -0800544 status = cmdStatus;
545 }
Eric Laurentbfb1b832013-01-07 09:53:42 -0800546 if (status == NO_ERROR) {
547 status = remove_effect_from_hal_l();
548 }
549 return status;
550}
551
552status_t AudioFlinger::EffectModule::remove_effect_from_hal_l()
553{
554 if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC ||
555 (mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_POST_PROC) {
Eric Laurentca7cc822012-11-19 14:55:58 -0800556 sp<ThreadBase> thread = mThread.promote();
557 if (thread != 0) {
558 audio_stream_t *stream = thread->stream();
559 if (stream != NULL) {
560 stream->remove_audio_effect(stream, mEffectInterface);
561 }
562 }
563 }
Eric Laurentbfb1b832013-01-07 09:53:42 -0800564 return NO_ERROR;
Eric Laurentca7cc822012-11-19 14:55:58 -0800565}
566
567status_t AudioFlinger::EffectModule::command(uint32_t cmdCode,
568 uint32_t cmdSize,
569 void *pCmdData,
570 uint32_t *replySize,
571 void *pReplyData)
572{
573 Mutex::Autolock _l(mLock);
574 ALOGVV("command(), cmdCode: %d, mEffectInterface: %p", cmdCode, mEffectInterface);
575
576 if (mState == DESTROYED || mEffectInterface == NULL) {
577 return NO_INIT;
578 }
Eric Laurentd0ebb532013-04-02 16:41:41 -0700579 if (mStatus != NO_ERROR) {
580 return mStatus;
581 }
Eric Laurentca7cc822012-11-19 14:55:58 -0800582 status_t status = (*mEffectInterface)->command(mEffectInterface,
583 cmdCode,
584 cmdSize,
585 pCmdData,
586 replySize,
587 pReplyData);
588 if (cmdCode != EFFECT_CMD_GET_PARAM && status == NO_ERROR) {
589 uint32_t size = (replySize == NULL) ? 0 : *replySize;
590 for (size_t i = 1; i < mHandles.size(); i++) {
591 EffectHandle *h = mHandles[i];
592 if (h != NULL && !h->destroyed_l()) {
593 h->commandExecuted(cmdCode, cmdSize, pCmdData, size, pReplyData);
594 }
595 }
596 }
597 return status;
598}
599
600status_t AudioFlinger::EffectModule::setEnabled(bool enabled)
601{
602 Mutex::Autolock _l(mLock);
603 return setEnabled_l(enabled);
604}
605
606// must be called with EffectModule::mLock held
607status_t AudioFlinger::EffectModule::setEnabled_l(bool enabled)
608{
Ethan Chen8d420ed2013-11-14 00:40:54 -0800609#ifdef QCOM_HARDWARE
Alok Kediya601e9b52013-09-27 11:55:10 +0530610 bool effectStateChanged = false;
Ethan Chen8d420ed2013-11-14 00:40:54 -0800611#endif
Eric Laurentca7cc822012-11-19 14:55:58 -0800612 ALOGV("setEnabled %p enabled %d", this, enabled);
613
614 if (enabled != isEnabled()) {
Ethan Chen8d420ed2013-11-14 00:40:54 -0800615#ifdef QCOM_HARDWARE
Alok Kediya601e9b52013-09-27 11:55:10 +0530616 effectStateChanged = true;
Ethan Chen8d420ed2013-11-14 00:40:54 -0800617#endif
Eric Laurentca7cc822012-11-19 14:55:58 -0800618 status_t status = AudioSystem::setEffectEnabled(mId, enabled);
619 if (enabled && status != NO_ERROR) {
620 return status;
621 }
622
623 switch (mState) {
624 // going from disabled to enabled
625 case IDLE:
626 mState = STARTING;
627 break;
628 case STOPPED:
629 mState = RESTART;
630 break;
631 case STOPPING:
632 mState = ACTIVE;
633 break;
634
635 // going from enabled to disabled
636 case RESTART:
637 mState = STOPPED;
638 break;
639 case STARTING:
640 mState = IDLE;
641 break;
642 case ACTIVE:
643 mState = STOPPING;
644 break;
645 case DESTROYED:
646 return NO_ERROR; // simply ignore as we are being destroyed
647 }
648 for (size_t i = 1; i < mHandles.size(); i++) {
649 EffectHandle *h = mHandles[i];
650 if (h != NULL && !h->destroyed_l()) {
651 h->setEnabled(enabled);
652 }
653 }
654 }
Ethan Chen8d420ed2013-11-14 00:40:54 -0800655#ifdef QCOM_HARDWARE
Alok Kediya601e9b52013-09-27 11:55:10 +0530656 /*
657 Send notification event to LPA Player when an effect for
658 LPA output is enabled or disabled.
659 */
660 sp<EffectChain> chain = mChain.promote();
661 if (effectStateChanged && chain->isForLPATrack()) {
662 sp<ThreadBase> thread = mThread.promote();
663 unlock();//Acquire locks in certain sequence to avoid deadlock
664 thread->effectConfigChanged();
665 lock();
666 }
Ethan Chen8d420ed2013-11-14 00:40:54 -0800667#endif
Eric Laurentca7cc822012-11-19 14:55:58 -0800668 return NO_ERROR;
669}
670
671bool AudioFlinger::EffectModule::isEnabled() const
672{
673 switch (mState) {
674 case RESTART:
675 case STARTING:
676 case ACTIVE:
677 return true;
678 case IDLE:
679 case STOPPING:
680 case STOPPED:
681 case DESTROYED:
682 default:
683 return false;
684 }
685}
686
687bool AudioFlinger::EffectModule::isProcessEnabled() const
688{
Eric Laurentd0ebb532013-04-02 16:41:41 -0700689 if (mStatus != NO_ERROR) {
690 return false;
691 }
692
Eric Laurentca7cc822012-11-19 14:55:58 -0800693 switch (mState) {
694 case RESTART:
695 case ACTIVE:
696 case STOPPING:
697 case STOPPED:
698 return true;
699 case IDLE:
700 case STARTING:
701 case DESTROYED:
702 default:
703 return false;
704 }
705}
706
707status_t AudioFlinger::EffectModule::setVolume(uint32_t *left, uint32_t *right, bool controller)
708{
709 Mutex::Autolock _l(mLock);
Eric Laurentd0ebb532013-04-02 16:41:41 -0700710 if (mStatus != NO_ERROR) {
711 return mStatus;
712 }
Eric Laurentca7cc822012-11-19 14:55:58 -0800713 status_t status = NO_ERROR;
Eric Laurentca7cc822012-11-19 14:55:58 -0800714 // Send volume indication if EFFECT_FLAG_VOLUME_IND is set and read back altered volume
715 // if controller flag is set (Note that controller == TRUE => EFFECT_FLAG_VOLUME_CTRL set)
716 if (isProcessEnabled() &&
717 ((mDescriptor.flags & EFFECT_FLAG_VOLUME_MASK) == EFFECT_FLAG_VOLUME_CTRL ||
718 (mDescriptor.flags & EFFECT_FLAG_VOLUME_MASK) == EFFECT_FLAG_VOLUME_IND)) {
Alok Kediya601e9b52013-09-27 11:55:10 +0530719 status_t cmdStatus = 0;
Eric Laurentca7cc822012-11-19 14:55:58 -0800720 uint32_t volume[2];
721 uint32_t *pVolume = NULL;
722 uint32_t size = sizeof(volume);
723 volume[0] = *left;
724 volume[1] = *right;
725 if (controller) {
726 pVolume = volume;
727 }
728 status = (*mEffectInterface)->command(mEffectInterface,
729 EFFECT_CMD_SET_VOLUME,
730 size,
731 volume,
732 &size,
733 pVolume);
734 if (controller && status == NO_ERROR && size == sizeof(volume)) {
735 *left = volume[0];
736 *right = volume[1];
737 }
738 }
739 return status;
740}
741
742status_t AudioFlinger::EffectModule::setDevice(audio_devices_t device)
743{
744 if (device == AUDIO_DEVICE_NONE) {
745 return NO_ERROR;
746 }
747
748 Mutex::Autolock _l(mLock);
Eric Laurentd0ebb532013-04-02 16:41:41 -0700749 if (mStatus != NO_ERROR) {
750 return mStatus;
751 }
Eric Laurentca7cc822012-11-19 14:55:58 -0800752 status_t status = NO_ERROR;
Eric Laurent7e1139c2013-06-06 18:29:01 -0700753 if ((mDescriptor.flags & EFFECT_FLAG_DEVICE_MASK) == EFFECT_FLAG_DEVICE_IND) {
Alok Kediya601e9b52013-09-27 11:55:10 +0530754 status_t cmdStatus = 0;
Eric Laurentca7cc822012-11-19 14:55:58 -0800755 uint32_t size = sizeof(status_t);
756 uint32_t cmd = audio_is_output_devices(device) ? EFFECT_CMD_SET_DEVICE :
757 EFFECT_CMD_SET_INPUT_DEVICE;
758 status = (*mEffectInterface)->command(mEffectInterface,
759 cmd,
760 sizeof(uint32_t),
761 &device,
762 &size,
763 &cmdStatus);
764 }
765 return status;
766}
767
768status_t AudioFlinger::EffectModule::setMode(audio_mode_t mode)
769{
770 Mutex::Autolock _l(mLock);
Eric Laurentd0ebb532013-04-02 16:41:41 -0700771 if (mStatus != NO_ERROR) {
772 return mStatus;
773 }
Eric Laurentca7cc822012-11-19 14:55:58 -0800774 status_t status = NO_ERROR;
775 if ((mDescriptor.flags & EFFECT_FLAG_AUDIO_MODE_MASK) == EFFECT_FLAG_AUDIO_MODE_IND) {
Alok Kediya601e9b52013-09-27 11:55:10 +0530776 status_t cmdStatus = 0;
Eric Laurentca7cc822012-11-19 14:55:58 -0800777 uint32_t size = sizeof(status_t);
778 status = (*mEffectInterface)->command(mEffectInterface,
779 EFFECT_CMD_SET_AUDIO_MODE,
780 sizeof(audio_mode_t),
781 &mode,
782 &size,
783 &cmdStatus);
784 if (status == NO_ERROR) {
785 status = cmdStatus;
786 }
787 }
788 return status;
789}
790
791status_t AudioFlinger::EffectModule::setAudioSource(audio_source_t source)
792{
793 Mutex::Autolock _l(mLock);
Eric Laurentd0ebb532013-04-02 16:41:41 -0700794 if (mStatus != NO_ERROR) {
795 return mStatus;
796 }
Eric Laurentca7cc822012-11-19 14:55:58 -0800797 status_t status = NO_ERROR;
798 if ((mDescriptor.flags & EFFECT_FLAG_AUDIO_SOURCE_MASK) == EFFECT_FLAG_AUDIO_SOURCE_IND) {
799 uint32_t size = 0;
800 status = (*mEffectInterface)->command(mEffectInterface,
801 EFFECT_CMD_SET_AUDIO_SOURCE,
802 sizeof(audio_source_t),
803 &source,
804 &size,
805 NULL);
806 }
807 return status;
808}
809
810void AudioFlinger::EffectModule::setSuspended(bool suspended)
811{
812 Mutex::Autolock _l(mLock);
813 mSuspended = suspended;
814}
815
816bool AudioFlinger::EffectModule::suspended() const
817{
818 Mutex::Autolock _l(mLock);
819 return mSuspended;
820}
821
822bool AudioFlinger::EffectModule::purgeHandles()
823{
824 bool enabled = false;
825 Mutex::Autolock _l(mLock);
826 for (size_t i = 0; i < mHandles.size(); i++) {
827 EffectHandle *handle = mHandles[i];
828 if (handle != NULL && !handle->destroyed_l()) {
829 handle->effect().clear();
830 if (handle->hasControl()) {
831 enabled = handle->enabled();
832 }
833 }
834 }
835 return enabled;
836}
837
Eric Laurent5baf2af2013-09-12 17:37:00 -0700838status_t AudioFlinger::EffectModule::setOffloaded(bool offloaded, audio_io_handle_t io)
839{
840 Mutex::Autolock _l(mLock);
841 if (mStatus != NO_ERROR) {
842 return mStatus;
843 }
844 status_t status = NO_ERROR;
845 if ((mDescriptor.flags & EFFECT_FLAG_OFFLOAD_SUPPORTED) != 0) {
846 status_t cmdStatus;
847 uint32_t size = sizeof(status_t);
848 effect_offload_param_t cmd;
849
850 cmd.isOffload = offloaded;
851 cmd.ioHandle = io;
852 status = (*mEffectInterface)->command(mEffectInterface,
853 EFFECT_CMD_OFFLOAD,
854 sizeof(effect_offload_param_t),
855 &cmd,
856 &size,
857 &cmdStatus);
858 if (status == NO_ERROR) {
859 status = cmdStatus;
860 }
861 mOffloaded = (status == NO_ERROR) ? offloaded : false;
862 } else {
863 if (offloaded) {
864 status = INVALID_OPERATION;
865 }
866 mOffloaded = false;
867 }
868 ALOGV("setOffloaded() offloaded %d io %d status %d", offloaded, io, status);
869 return status;
870}
871
872bool AudioFlinger::EffectModule::isOffloaded() const
873{
874 Mutex::Autolock _l(mLock);
875 return mOffloaded;
876}
877
Eric Laurentca7cc822012-11-19 14:55:58 -0800878void AudioFlinger::EffectModule::dump(int fd, const Vector<String16>& args)
879{
880 const size_t SIZE = 256;
881 char buffer[SIZE];
882 String8 result;
883
884 snprintf(buffer, SIZE, "\tEffect ID %d:\n", mId);
885 result.append(buffer);
886
887 bool locked = AudioFlinger::dumpTryLock(mLock);
888 // failed to lock - AudioFlinger is probably deadlocked
889 if (!locked) {
890 result.append("\t\tCould not lock Fx mutex:\n");
891 }
892
893 result.append("\t\tSession Status State Engine:\n");
894 snprintf(buffer, SIZE, "\t\t%05d %03d %03d 0x%08x\n",
895 mSessionId, mStatus, mState, (uint32_t)mEffectInterface);
896 result.append(buffer);
897
898 result.append("\t\tDescriptor:\n");
899 snprintf(buffer, SIZE, "\t\t- UUID: %08X-%04X-%04X-%04X-%02X%02X%02X%02X%02X%02X\n",
900 mDescriptor.uuid.timeLow, mDescriptor.uuid.timeMid, mDescriptor.uuid.timeHiAndVersion,
901 mDescriptor.uuid.clockSeq, mDescriptor.uuid.node[0], mDescriptor.uuid.node[1],
902 mDescriptor.uuid.node[2],
903 mDescriptor.uuid.node[3],mDescriptor.uuid.node[4],mDescriptor.uuid.node[5]);
904 result.append(buffer);
905 snprintf(buffer, SIZE, "\t\t- TYPE: %08X-%04X-%04X-%04X-%02X%02X%02X%02X%02X%02X\n",
906 mDescriptor.type.timeLow, mDescriptor.type.timeMid,
907 mDescriptor.type.timeHiAndVersion,
908 mDescriptor.type.clockSeq, mDescriptor.type.node[0], mDescriptor.type.node[1],
909 mDescriptor.type.node[2],
910 mDescriptor.type.node[3],mDescriptor.type.node[4],mDescriptor.type.node[5]);
911 result.append(buffer);
912 snprintf(buffer, SIZE, "\t\t- apiVersion: %08X\n\t\t- flags: %08X\n",
913 mDescriptor.apiVersion,
914 mDescriptor.flags);
915 result.append(buffer);
916 snprintf(buffer, SIZE, "\t\t- name: %s\n",
917 mDescriptor.name);
918 result.append(buffer);
919 snprintf(buffer, SIZE, "\t\t- implementor: %s\n",
920 mDescriptor.implementor);
921 result.append(buffer);
922
923 result.append("\t\t- Input configuration:\n");
924 result.append("\t\t\tBuffer Frames Smp rate Channels Format\n");
925 snprintf(buffer, SIZE, "\t\t\t0x%08x %05d %05d %08x %d\n",
926 (uint32_t)mConfig.inputCfg.buffer.raw,
927 mConfig.inputCfg.buffer.frameCount,
928 mConfig.inputCfg.samplingRate,
929 mConfig.inputCfg.channels,
930 mConfig.inputCfg.format);
931 result.append(buffer);
932
933 result.append("\t\t- Output configuration:\n");
934 result.append("\t\t\tBuffer Frames Smp rate Channels Format\n");
935 snprintf(buffer, SIZE, "\t\t\t0x%08x %05d %05d %08x %d\n",
936 (uint32_t)mConfig.outputCfg.buffer.raw,
937 mConfig.outputCfg.buffer.frameCount,
938 mConfig.outputCfg.samplingRate,
939 mConfig.outputCfg.channels,
940 mConfig.outputCfg.format);
941 result.append(buffer);
942
943 snprintf(buffer, SIZE, "\t\t%d Clients:\n", mHandles.size());
944 result.append(buffer);
945 result.append("\t\t\tPid Priority Ctrl Locked client server\n");
946 for (size_t i = 0; i < mHandles.size(); ++i) {
947 EffectHandle *handle = mHandles[i];
948 if (handle != NULL && !handle->destroyed_l()) {
949 handle->dump(buffer, SIZE);
950 result.append(buffer);
951 }
952 }
953
954 result.append("\n");
955
956 write(fd, result.string(), result.length());
957
958 if (locked) {
959 mLock.unlock();
960 }
961}
962
963// ----------------------------------------------------------------------------
964// EffectHandle implementation
965// ----------------------------------------------------------------------------
966
967#undef LOG_TAG
968#define LOG_TAG "AudioFlinger::EffectHandle"
969
970AudioFlinger::EffectHandle::EffectHandle(const sp<EffectModule>& effect,
971 const sp<AudioFlinger::Client>& client,
972 const sp<IEffectClient>& effectClient,
973 int32_t priority)
974 : BnEffect(),
975 mEffect(effect), mEffectClient(effectClient), mClient(client), mCblk(NULL),
976 mPriority(priority), mHasControl(false), mEnabled(false), mDestroyed(false)
977{
978 ALOGV("constructor %p", this);
979
980 if (client == 0) {
981 return;
982 }
983 int bufOffset = ((sizeof(effect_param_cblk_t) - 1) / sizeof(int) + 1) * sizeof(int);
984 mCblkMemory = client->heap()->allocate(EFFECT_PARAM_BUFFER_SIZE + bufOffset);
985 if (mCblkMemory != 0) {
986 mCblk = static_cast<effect_param_cblk_t *>(mCblkMemory->pointer());
987
988 if (mCblk != NULL) {
989 new(mCblk) effect_param_cblk_t();
990 mBuffer = (uint8_t *)mCblk + bufOffset;
991 }
992 } else {
993 ALOGE("not enough memory for Effect size=%u", EFFECT_PARAM_BUFFER_SIZE +
994 sizeof(effect_param_cblk_t));
995 return;
996 }
997}
998
999AudioFlinger::EffectHandle::~EffectHandle()
1000{
1001 ALOGV("Destructor %p", this);
1002
1003 if (mEffect == 0) {
1004 mDestroyed = true;
1005 return;
1006 }
1007 mEffect->lock();
1008 mDestroyed = true;
1009 mEffect->unlock();
1010 disconnect(false);
1011}
1012
1013status_t AudioFlinger::EffectHandle::enable()
1014{
1015 ALOGV("enable %p", this);
1016 if (!mHasControl) {
1017 return INVALID_OPERATION;
1018 }
1019 if (mEffect == 0) {
1020 return DEAD_OBJECT;
1021 }
1022
1023 if (mEnabled) {
1024 return NO_ERROR;
1025 }
1026
1027 mEnabled = true;
1028
1029 sp<ThreadBase> thread = mEffect->thread().promote();
1030 if (thread != 0) {
1031 thread->checkSuspendOnEffectEnabled(mEffect, true, mEffect->sessionId());
1032 }
1033
1034 // checkSuspendOnEffectEnabled() can suspend this same effect when enabled
1035 if (mEffect->suspended()) {
1036 return NO_ERROR;
1037 }
1038
1039 status_t status = mEffect->setEnabled(true);
1040 if (status != NO_ERROR) {
1041 if (thread != 0) {
1042 thread->checkSuspendOnEffectEnabled(mEffect, false, mEffect->sessionId());
1043 }
1044 mEnabled = false;
Eric Laurent813e2a72013-08-31 12:59:48 -07001045 } else {
Eric Laurent59fe0102013-09-27 18:48:26 -07001046 if (thread != 0) {
1047 if (thread->type() == ThreadBase::OFFLOAD) {
Eric Laurent813e2a72013-08-31 12:59:48 -07001048 PlaybackThread *t = (PlaybackThread *)thread.get();
Eric Laurent59fe0102013-09-27 18:48:26 -07001049 Mutex::Autolock _l(t->mLock);
1050 t->broadcast_l();
Eric Laurent813e2a72013-08-31 12:59:48 -07001051 }
Eric Laurent59fe0102013-09-27 18:48:26 -07001052 if (!mEffect->isOffloadable()) {
1053 if (thread->type() == ThreadBase::OFFLOAD) {
1054 PlaybackThread *t = (PlaybackThread *)thread.get();
1055 t->invalidateTracks(AUDIO_STREAM_MUSIC);
1056 }
1057 if (mEffect->sessionId() == AUDIO_SESSION_OUTPUT_MIX) {
1058 thread->mAudioFlinger->onNonOffloadableGlobalEffectEnable();
1059 }
Eric Laurent813e2a72013-08-31 12:59:48 -07001060 }
1061 }
Eric Laurentca7cc822012-11-19 14:55:58 -08001062 }
1063 return status;
1064}
1065
1066status_t AudioFlinger::EffectHandle::disable()
1067{
1068 ALOGV("disable %p", this);
1069 if (!mHasControl) {
1070 return INVALID_OPERATION;
1071 }
1072 if (mEffect == 0) {
1073 return DEAD_OBJECT;
1074 }
1075
1076 if (!mEnabled) {
1077 return NO_ERROR;
1078 }
1079 mEnabled = false;
1080
1081 if (mEffect->suspended()) {
1082 return NO_ERROR;
1083 }
1084
1085 status_t status = mEffect->setEnabled(false);
1086
1087 sp<ThreadBase> thread = mEffect->thread().promote();
1088 if (thread != 0) {
1089 thread->checkSuspendOnEffectEnabled(mEffect, false, mEffect->sessionId());
Eric Laurent59fe0102013-09-27 18:48:26 -07001090 if (thread->type() == ThreadBase::OFFLOAD) {
1091 PlaybackThread *t = (PlaybackThread *)thread.get();
1092 Mutex::Autolock _l(t->mLock);
1093 t->broadcast_l();
1094 }
Eric Laurentca7cc822012-11-19 14:55:58 -08001095 }
1096
1097 return status;
1098}
1099
1100void AudioFlinger::EffectHandle::disconnect()
1101{
1102 disconnect(true);
1103}
1104
1105void AudioFlinger::EffectHandle::disconnect(bool unpinIfLast)
1106{
1107 ALOGV("disconnect(%s)", unpinIfLast ? "true" : "false");
1108 if (mEffect == 0) {
1109 return;
1110 }
1111 // restore suspended effects if the disconnected handle was enabled and the last one.
1112 if ((mEffect->disconnect(this, unpinIfLast) == 0) && mEnabled) {
1113 sp<ThreadBase> thread = mEffect->thread().promote();
1114 if (thread != 0) {
1115 thread->checkSuspendOnEffectEnabled(mEffect, false, mEffect->sessionId());
1116 }
1117 }
1118
1119 // release sp on module => module destructor can be called now
1120 mEffect.clear();
1121 if (mClient != 0) {
1122 if (mCblk != NULL) {
1123 // unlike ~TrackBase(), mCblk is never a local new, so don't delete
1124 mCblk->~effect_param_cblk_t(); // destroy our shared-structure.
1125 }
1126 mCblkMemory.clear(); // free the shared memory before releasing the heap it belongs to
1127 // Client destructor must run with AudioFlinger mutex locked
1128 Mutex::Autolock _l(mClient->audioFlinger()->mLock);
1129 mClient.clear();
1130 }
1131}
1132
1133status_t AudioFlinger::EffectHandle::command(uint32_t cmdCode,
1134 uint32_t cmdSize,
1135 void *pCmdData,
1136 uint32_t *replySize,
1137 void *pReplyData)
1138{
1139 ALOGVV("command(), cmdCode: %d, mHasControl: %d, mEffect: %p",
1140 cmdCode, mHasControl, (mEffect == 0) ? 0 : mEffect.get());
1141
1142 // only get parameter command is permitted for applications not controlling the effect
1143 if (!mHasControl && cmdCode != EFFECT_CMD_GET_PARAM) {
1144 return INVALID_OPERATION;
1145 }
1146 if (mEffect == 0) {
1147 return DEAD_OBJECT;
1148 }
1149 if (mClient == 0) {
1150 return INVALID_OPERATION;
1151 }
1152
1153 // handle commands that are not forwarded transparently to effect engine
1154 if (cmdCode == EFFECT_CMD_SET_PARAM_COMMIT) {
1155 // No need to trylock() here as this function is executed in the binder thread serving a
1156 // particular client process: no risk to block the whole media server process or mixer
1157 // threads if we are stuck here
1158 Mutex::Autolock _l(mCblk->lock);
1159 if (mCblk->clientIndex > EFFECT_PARAM_BUFFER_SIZE ||
1160 mCblk->serverIndex > EFFECT_PARAM_BUFFER_SIZE) {
1161 mCblk->serverIndex = 0;
1162 mCblk->clientIndex = 0;
1163 return BAD_VALUE;
1164 }
1165 status_t status = NO_ERROR;
1166 while (mCblk->serverIndex < mCblk->clientIndex) {
1167 int reply;
1168 uint32_t rsize = sizeof(int);
1169 int *p = (int *)(mBuffer + mCblk->serverIndex);
1170 int size = *p++;
1171 if (((uint8_t *)p + size) > mBuffer + mCblk->clientIndex) {
1172 ALOGW("command(): invalid parameter block size");
1173 break;
1174 }
1175 effect_param_t *param = (effect_param_t *)p;
1176 if (param->psize == 0 || param->vsize == 0) {
1177 ALOGW("command(): null parameter or value size");
1178 mCblk->serverIndex += size;
1179 continue;
1180 }
1181 uint32_t psize = sizeof(effect_param_t) +
1182 ((param->psize - 1) / sizeof(int) + 1) * sizeof(int) +
1183 param->vsize;
1184 status_t ret = mEffect->command(EFFECT_CMD_SET_PARAM,
1185 psize,
1186 p,
1187 &rsize,
1188 &reply);
1189 // stop at first error encountered
1190 if (ret != NO_ERROR) {
1191 status = ret;
1192 *(int *)pReplyData = reply;
1193 break;
1194 } else if (reply != NO_ERROR) {
1195 *(int *)pReplyData = reply;
1196 break;
1197 }
1198 mCblk->serverIndex += size;
1199 }
1200 mCblk->serverIndex = 0;
1201 mCblk->clientIndex = 0;
1202 return status;
1203 } else if (cmdCode == EFFECT_CMD_ENABLE) {
1204 *(int *)pReplyData = NO_ERROR;
1205 return enable();
1206 } else if (cmdCode == EFFECT_CMD_DISABLE) {
1207 *(int *)pReplyData = NO_ERROR;
1208 return disable();
1209 }
1210
Ethan Chen8d420ed2013-11-14 00:40:54 -08001211#ifdef QCOM_HARDWARE
Alok Kediya601e9b52013-09-27 11:55:10 +05301212 if(mEffect->isOnLPA() &&
1213 ((cmdCode == EFFECT_CMD_SET_PARAM) || (cmdCode == EFFECT_CMD_SET_PARAM_DEFERRED) ||
1214 (cmdCode == EFFECT_CMD_SET_PARAM_COMMIT) || (cmdCode == EFFECT_CMD_SET_DEVICE) ||
1215 (cmdCode == EFFECT_CMD_SET_VOLUME) || (cmdCode == EFFECT_CMD_SET_AUDIO_MODE)) ) {
1216 // Notify Direct track for the change in Effect module
1217 // TODO: check if it is required to send mLPAHandle
1218 ALOGV("Notifying Direct Track for the change in effect config %d", cmdCode);
1219 mClient->audioFlinger()->audioConfigChanged_l(AudioSystem::EFFECT_CONFIG_CHANGED, 0, NULL);
1220 }
Ethan Chen8d420ed2013-11-14 00:40:54 -08001221#endif
Eric Laurentca7cc822012-11-19 14:55:58 -08001222 return mEffect->command(cmdCode, cmdSize, pCmdData, replySize, pReplyData);
1223}
1224
1225void AudioFlinger::EffectHandle::setControl(bool hasControl, bool signal, bool enabled)
1226{
1227 ALOGV("setControl %p control %d", this, hasControl);
1228
1229 mHasControl = hasControl;
1230 mEnabled = enabled;
1231
1232 if (signal && mEffectClient != 0) {
1233 mEffectClient->controlStatusChanged(hasControl);
1234 }
1235}
1236
1237void AudioFlinger::EffectHandle::commandExecuted(uint32_t cmdCode,
1238 uint32_t cmdSize,
1239 void *pCmdData,
1240 uint32_t replySize,
1241 void *pReplyData)
1242{
1243 if (mEffectClient != 0) {
1244 mEffectClient->commandExecuted(cmdCode, cmdSize, pCmdData, replySize, pReplyData);
1245 }
1246}
1247
1248
1249
1250void AudioFlinger::EffectHandle::setEnabled(bool enabled)
1251{
1252 if (mEffectClient != 0) {
1253 mEffectClient->enableStatusChanged(enabled);
1254 }
1255}
1256
1257status_t AudioFlinger::EffectHandle::onTransact(
1258 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
1259{
1260 return BnEffect::onTransact(code, data, reply, flags);
1261}
1262
1263
1264void AudioFlinger::EffectHandle::dump(char* buffer, size_t size)
1265{
1266 bool locked = mCblk != NULL && AudioFlinger::dumpTryLock(mCblk->lock);
1267
1268 snprintf(buffer, size, "\t\t\t%05d %05d %01u %01u %05u %05u\n",
1269 (mClient == 0) ? getpid_cached : mClient->pid(),
1270 mPriority,
1271 mHasControl,
1272 !locked,
1273 mCblk ? mCblk->clientIndex : 0,
1274 mCblk ? mCblk->serverIndex : 0
1275 );
1276
1277 if (locked) {
1278 mCblk->lock.unlock();
1279 }
1280}
1281
1282#undef LOG_TAG
1283#define LOG_TAG "AudioFlinger::EffectChain"
1284
1285AudioFlinger::EffectChain::EffectChain(ThreadBase *thread,
1286 int sessionId)
1287 : mThread(thread), mSessionId(sessionId), mActiveTrackCnt(0), mTrackCnt(0), mTailBufferCount(0),
1288 mOwnInBuffer(false), mVolumeCtrlIdx(-1), mLeftVolume(UINT_MAX), mRightVolume(UINT_MAX),
Ethan Chen8d420ed2013-11-14 00:40:54 -08001289#ifdef QCOM_HARDWARE
Alok Kediya601e9b52013-09-27 11:55:10 +05301290 mNewLeftVolume(UINT_MAX), mNewRightVolume(UINT_MAX), mIsForLPATrack(false)
Ethan Chen8d420ed2013-11-14 00:40:54 -08001291#else
1292 mNewLeftVolume(UINT_MAX), mNewRightVolume(UINT_MAX)
1293#endif
Eric Laurentca7cc822012-11-19 14:55:58 -08001294{
1295 mStrategy = AudioSystem::getStrategyForStream(AUDIO_STREAM_MUSIC);
1296 if (thread == NULL) {
1297 return;
1298 }
1299 mMaxTailBuffers = ((kProcessTailDurationMs * thread->sampleRate()) / 1000) /
1300 thread->frameCount();
1301}
1302
1303AudioFlinger::EffectChain::~EffectChain()
1304{
1305 if (mOwnInBuffer) {
1306 delete mInBuffer;
1307 }
1308
1309}
1310
1311// getEffectFromDesc_l() must be called with ThreadBase::mLock held
1312sp<AudioFlinger::EffectModule> AudioFlinger::EffectChain::getEffectFromDesc_l(
1313 effect_descriptor_t *descriptor)
1314{
1315 size_t size = mEffects.size();
1316
1317 for (size_t i = 0; i < size; i++) {
1318 if (memcmp(&mEffects[i]->desc().uuid, &descriptor->uuid, sizeof(effect_uuid_t)) == 0) {
1319 return mEffects[i];
1320 }
1321 }
1322 return 0;
1323}
1324
1325// getEffectFromId_l() must be called with ThreadBase::mLock held
1326sp<AudioFlinger::EffectModule> AudioFlinger::EffectChain::getEffectFromId_l(int id)
1327{
1328 size_t size = mEffects.size();
1329
1330 for (size_t i = 0; i < size; i++) {
1331 // by convention, return first effect if id provided is 0 (0 is never a valid id)
1332 if (id == 0 || mEffects[i]->id() == id) {
1333 return mEffects[i];
1334 }
1335 }
1336 return 0;
1337}
1338
Ethan Chen8d420ed2013-11-14 00:40:54 -08001339#ifdef QCOM_HARDWARE
Alok Kediya601e9b52013-09-27 11:55:10 +05301340sp<AudioFlinger::EffectModule> AudioFlinger::EffectChain::getEffectFromIndex_l(int idx)
1341{
1342 sp<EffectModule> effect = NULL;
1343 if(idx < 0 || idx >= mEffects.size()) {
1344 ALOGE("EffectChain::getEffectFromIndex_l: invalid index %d", idx);
1345 }
1346 if(mEffects.size() > 0){
1347 effect = mEffects[idx];
1348 }
1349 return effect;
1350}
Ethan Chen8d420ed2013-11-14 00:40:54 -08001351#endif
Alok Kediya601e9b52013-09-27 11:55:10 +05301352
Eric Laurentca7cc822012-11-19 14:55:58 -08001353// getEffectFromType_l() must be called with ThreadBase::mLock held
1354sp<AudioFlinger::EffectModule> AudioFlinger::EffectChain::getEffectFromType_l(
1355 const effect_uuid_t *type)
1356{
1357 size_t size = mEffects.size();
1358
1359 for (size_t i = 0; i < size; i++) {
1360 if (memcmp(&mEffects[i]->desc().type, type, sizeof(effect_uuid_t)) == 0) {
1361 return mEffects[i];
1362 }
1363 }
1364 return 0;
1365}
1366
1367void AudioFlinger::EffectChain::clearInputBuffer()
1368{
1369 Mutex::Autolock _l(mLock);
1370 sp<ThreadBase> thread = mThread.promote();
1371 if (thread == 0) {
1372 ALOGW("clearInputBuffer(): cannot promote mixer thread");
1373 return;
1374 }
1375 clearInputBuffer_l(thread);
1376}
1377
1378// Must be called with EffectChain::mLock locked
1379void AudioFlinger::EffectChain::clearInputBuffer_l(sp<ThreadBase> thread)
1380{
Eric Laurentbfb1b832013-01-07 09:53:42 -08001381 memset(mInBuffer, 0, thread->frameCount() * thread->frameSize());
Eric Laurentca7cc822012-11-19 14:55:58 -08001382}
1383
1384// Must be called with EffectChain::mLock locked
1385void AudioFlinger::EffectChain::process_l()
1386{
1387 sp<ThreadBase> thread = mThread.promote();
1388 if (thread == 0) {
1389 ALOGW("process_l(): cannot promote mixer thread");
1390 return;
1391 }
1392 bool isGlobalSession = (mSessionId == AUDIO_SESSION_OUTPUT_MIX) ||
1393 (mSessionId == AUDIO_SESSION_OUTPUT_STAGE);
Jean-Michel Trivifed62922013-09-25 18:50:33 -07001394 // never process effects when:
1395 // - on an OFFLOAD thread
1396 // - no more tracks are on the session and the effect tail has been rendered
1397 bool doProcess = (thread->type() != ThreadBase::OFFLOAD);
Eric Laurentca7cc822012-11-19 14:55:58 -08001398 if (!isGlobalSession) {
1399 bool tracksOnSession = (trackCnt() != 0);
1400
1401 if (!tracksOnSession && mTailBufferCount == 0) {
1402 doProcess = false;
1403 }
1404
1405 if (activeTrackCnt() == 0) {
1406 // if no track is active and the effect tail has not been rendered,
1407 // the input buffer must be cleared here as the mixer process will not do it
1408 if (tracksOnSession || mTailBufferCount > 0) {
1409 clearInputBuffer_l(thread);
1410 if (mTailBufferCount > 0) {
1411 mTailBufferCount--;
1412 }
1413 }
1414 }
1415 }
1416
1417 size_t size = mEffects.size();
Ethan Chen8d420ed2013-11-14 00:40:54 -08001418#ifdef QCOM_HARDWARE
Alok Kediya601e9b52013-09-27 11:55:10 +05301419 if (doProcess || isForLPATrack()) {
Ethan Chen8d420ed2013-11-14 00:40:54 -08001420#else
1421 if (doProcess) {
1422#endif
Eric Laurentca7cc822012-11-19 14:55:58 -08001423 for (size_t i = 0; i < size; i++) {
1424 mEffects[i]->process();
1425 }
1426 }
1427 for (size_t i = 0; i < size; i++) {
1428 mEffects[i]->updateState();
1429 }
1430}
1431
1432// addEffect_l() must be called with PlaybackThread::mLock held
1433status_t AudioFlinger::EffectChain::addEffect_l(const sp<EffectModule>& effect)
1434{
1435 effect_descriptor_t desc = effect->desc();
1436 uint32_t insertPref = desc.flags & EFFECT_FLAG_INSERT_MASK;
1437
1438 Mutex::Autolock _l(mLock);
1439 effect->setChain(this);
1440 sp<ThreadBase> thread = mThread.promote();
1441 if (thread == 0) {
1442 return NO_INIT;
1443 }
1444 effect->setThread(thread);
1445
1446 if ((desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
1447 // Auxiliary effects are inserted at the beginning of mEffects vector as
1448 // they are processed first and accumulated in chain input buffer
1449 mEffects.insertAt(effect, 0);
1450
1451 // the input buffer for auxiliary effect contains mono samples in
1452 // 32 bit format. This is to avoid saturation in AudoMixer
1453 // accumulation stage. Saturation is done in EffectModule::process() before
1454 // calling the process in effect engine
1455 size_t numSamples = thread->frameCount();
1456 int32_t *buffer = new int32_t[numSamples];
1457 memset(buffer, 0, numSamples * sizeof(int32_t));
1458 effect->setInBuffer((int16_t *)buffer);
1459 // auxiliary effects output samples to chain input buffer for further processing
1460 // by insert effects
1461 effect->setOutBuffer(mInBuffer);
1462 } else {
1463 // Insert effects are inserted at the end of mEffects vector as they are processed
1464 // after track and auxiliary effects.
1465 // Insert effect order as a function of indicated preference:
1466 // if EFFECT_FLAG_INSERT_EXCLUSIVE, insert in first position or reject if
1467 // another effect is present
1468 // else if EFFECT_FLAG_INSERT_FIRST, insert in first position or after the
1469 // last effect claiming first position
1470 // else if EFFECT_FLAG_INSERT_LAST, insert in last position or before the
1471 // first effect claiming last position
1472 // else if EFFECT_FLAG_INSERT_ANY insert after first or before last
1473 // Reject insertion if an effect with EFFECT_FLAG_INSERT_EXCLUSIVE is
1474 // already present
1475
1476 size_t size = mEffects.size();
1477 size_t idx_insert = size;
1478 ssize_t idx_insert_first = -1;
1479 ssize_t idx_insert_last = -1;
1480
1481 for (size_t i = 0; i < size; i++) {
1482 effect_descriptor_t d = mEffects[i]->desc();
1483 uint32_t iMode = d.flags & EFFECT_FLAG_TYPE_MASK;
1484 uint32_t iPref = d.flags & EFFECT_FLAG_INSERT_MASK;
1485 if (iMode == EFFECT_FLAG_TYPE_INSERT) {
1486 // check invalid effect chaining combinations
1487 if (insertPref == EFFECT_FLAG_INSERT_EXCLUSIVE ||
1488 iPref == EFFECT_FLAG_INSERT_EXCLUSIVE) {
1489 ALOGW("addEffect_l() could not insert effect %s: exclusive conflict with %s",
1490 desc.name, d.name);
1491 return INVALID_OPERATION;
1492 }
1493 // remember position of first insert effect and by default
1494 // select this as insert position for new effect
1495 if (idx_insert == size) {
1496 idx_insert = i;
1497 }
1498 // remember position of last insert effect claiming
1499 // first position
1500 if (iPref == EFFECT_FLAG_INSERT_FIRST) {
1501 idx_insert_first = i;
1502 }
1503 // remember position of first insert effect claiming
1504 // last position
1505 if (iPref == EFFECT_FLAG_INSERT_LAST &&
1506 idx_insert_last == -1) {
1507 idx_insert_last = i;
1508 }
1509 }
1510 }
1511
1512 // modify idx_insert from first position if needed
1513 if (insertPref == EFFECT_FLAG_INSERT_LAST) {
1514 if (idx_insert_last != -1) {
1515 idx_insert = idx_insert_last;
1516 } else {
1517 idx_insert = size;
1518 }
1519 } else {
1520 if (idx_insert_first != -1) {
1521 idx_insert = idx_insert_first + 1;
1522 }
1523 }
1524
1525 // always read samples from chain input buffer
1526 effect->setInBuffer(mInBuffer);
1527
1528 // if last effect in the chain, output samples to chain
1529 // output buffer, otherwise to chain input buffer
1530 if (idx_insert == size) {
1531 if (idx_insert != 0) {
1532 mEffects[idx_insert-1]->setOutBuffer(mInBuffer);
1533 mEffects[idx_insert-1]->configure();
1534 }
1535 effect->setOutBuffer(mOutBuffer);
1536 } else {
1537 effect->setOutBuffer(mInBuffer);
1538 }
1539 mEffects.insertAt(effect, idx_insert);
1540
1541 ALOGV("addEffect_l() effect %p, added in chain %p at rank %d", effect.get(), this,
1542 idx_insert);
1543 }
1544 effect->configure();
1545 return NO_ERROR;
1546}
1547
1548// removeEffect_l() must be called with PlaybackThread::mLock held
1549size_t AudioFlinger::EffectChain::removeEffect_l(const sp<EffectModule>& effect)
1550{
1551 Mutex::Autolock _l(mLock);
1552 size_t size = mEffects.size();
1553 uint32_t type = effect->desc().flags & EFFECT_FLAG_TYPE_MASK;
1554
1555 for (size_t i = 0; i < size; i++) {
1556 if (effect == mEffects[i]) {
1557 // calling stop here will remove pre-processing effect from the audio HAL.
1558 // This is safe as we hold the EffectChain mutex which guarantees that we are not in
1559 // the middle of a read from audio HAL
1560 if (mEffects[i]->state() == EffectModule::ACTIVE ||
1561 mEffects[i]->state() == EffectModule::STOPPING) {
1562 mEffects[i]->stop();
1563 }
1564 if (type == EFFECT_FLAG_TYPE_AUXILIARY) {
1565 delete[] effect->inBuffer();
1566 } else {
1567 if (i == size - 1 && i != 0) {
1568 mEffects[i - 1]->setOutBuffer(mOutBuffer);
1569 mEffects[i - 1]->configure();
1570 }
1571 }
1572 mEffects.removeAt(i);
1573 ALOGV("removeEffect_l() effect %p, removed from chain %p at rank %d", effect.get(),
1574 this, i);
1575 break;
1576 }
1577 }
1578
1579 return mEffects.size();
1580}
1581
1582// setDevice_l() must be called with PlaybackThread::mLock held
1583void AudioFlinger::EffectChain::setDevice_l(audio_devices_t device)
1584{
1585 size_t size = mEffects.size();
1586 for (size_t i = 0; i < size; i++) {
1587 mEffects[i]->setDevice(device);
1588 }
1589}
1590
1591// setMode_l() must be called with PlaybackThread::mLock held
1592void AudioFlinger::EffectChain::setMode_l(audio_mode_t mode)
1593{
1594 size_t size = mEffects.size();
1595 for (size_t i = 0; i < size; i++) {
1596 mEffects[i]->setMode(mode);
1597 }
1598}
1599
1600// setAudioSource_l() must be called with PlaybackThread::mLock held
1601void AudioFlinger::EffectChain::setAudioSource_l(audio_source_t source)
1602{
1603 size_t size = mEffects.size();
1604 for (size_t i = 0; i < size; i++) {
1605 mEffects[i]->setAudioSource(source);
1606 }
1607}
1608
1609// setVolume_l() must be called with PlaybackThread::mLock held
1610bool AudioFlinger::EffectChain::setVolume_l(uint32_t *left, uint32_t *right)
1611{
1612 uint32_t newLeft = *left;
1613 uint32_t newRight = *right;
1614 bool hasControl = false;
1615 int ctrlIdx = -1;
1616 size_t size = mEffects.size();
1617
1618 // first update volume controller
1619 for (size_t i = size; i > 0; i--) {
1620 if (mEffects[i - 1]->isProcessEnabled() &&
1621 (mEffects[i - 1]->desc().flags & EFFECT_FLAG_VOLUME_MASK) == EFFECT_FLAG_VOLUME_CTRL) {
1622 ctrlIdx = i - 1;
1623 hasControl = true;
1624 break;
1625 }
1626 }
1627
1628 if (ctrlIdx == mVolumeCtrlIdx && *left == mLeftVolume && *right == mRightVolume) {
1629 if (hasControl) {
1630 *left = mNewLeftVolume;
1631 *right = mNewRightVolume;
1632 }
1633 return hasControl;
1634 }
1635
1636 mVolumeCtrlIdx = ctrlIdx;
1637 mLeftVolume = newLeft;
1638 mRightVolume = newRight;
1639
1640 // second get volume update from volume controller
1641 if (ctrlIdx >= 0) {
1642 mEffects[ctrlIdx]->setVolume(&newLeft, &newRight, true);
1643 mNewLeftVolume = newLeft;
1644 mNewRightVolume = newRight;
1645 }
1646 // then indicate volume to all other effects in chain.
1647 // Pass altered volume to effects before volume controller
1648 // and requested volume to effects after controller
1649 uint32_t lVol = newLeft;
1650 uint32_t rVol = newRight;
1651
1652 for (size_t i = 0; i < size; i++) {
1653 if ((int)i == ctrlIdx) {
1654 continue;
1655 }
1656 // this also works for ctrlIdx == -1 when there is no volume controller
1657 if ((int)i > ctrlIdx) {
1658 lVol = *left;
1659 rVol = *right;
1660 }
1661 mEffects[i]->setVolume(&lVol, &rVol, false);
1662 }
1663 *left = newLeft;
1664 *right = newRight;
1665
1666 return hasControl;
1667}
1668
1669void AudioFlinger::EffectChain::dump(int fd, const Vector<String16>& args)
1670{
1671 const size_t SIZE = 256;
1672 char buffer[SIZE];
1673 String8 result;
1674
1675 snprintf(buffer, SIZE, "Effects for session %d:\n", mSessionId);
1676 result.append(buffer);
1677
1678 bool locked = AudioFlinger::dumpTryLock(mLock);
1679 // failed to lock - AudioFlinger is probably deadlocked
1680 if (!locked) {
1681 result.append("\tCould not lock mutex:\n");
1682 }
1683
1684 result.append("\tNum fx In buffer Out buffer Active tracks:\n");
1685 snprintf(buffer, SIZE, "\t%02d 0x%08x 0x%08x %d\n",
1686 mEffects.size(),
1687 (uint32_t)mInBuffer,
1688 (uint32_t)mOutBuffer,
1689 mActiveTrackCnt);
1690 result.append(buffer);
1691 write(fd, result.string(), result.size());
1692
1693 for (size_t i = 0; i < mEffects.size(); ++i) {
1694 sp<EffectModule> effect = mEffects[i];
1695 if (effect != 0) {
1696 effect->dump(fd, args);
1697 }
1698 }
1699
1700 if (locked) {
1701 mLock.unlock();
1702 }
1703}
1704
1705// must be called with ThreadBase::mLock held
1706void AudioFlinger::EffectChain::setEffectSuspended_l(
1707 const effect_uuid_t *type, bool suspend)
1708{
1709 sp<SuspendedEffectDesc> desc;
1710 // use effect type UUID timelow as key as there is no real risk of identical
1711 // timeLow fields among effect type UUIDs.
1712 ssize_t index = mSuspendedEffects.indexOfKey(type->timeLow);
1713 if (suspend) {
1714 if (index >= 0) {
1715 desc = mSuspendedEffects.valueAt(index);
1716 } else {
1717 desc = new SuspendedEffectDesc();
1718 desc->mType = *type;
1719 mSuspendedEffects.add(type->timeLow, desc);
1720 ALOGV("setEffectSuspended_l() add entry for %08x", type->timeLow);
1721 }
1722 if (desc->mRefCount++ == 0) {
1723 sp<EffectModule> effect = getEffectIfEnabled(type);
1724 if (effect != 0) {
1725 desc->mEffect = effect;
1726 effect->setSuspended(true);
1727 effect->setEnabled(false);
1728 }
1729 }
1730 } else {
1731 if (index < 0) {
1732 return;
1733 }
1734 desc = mSuspendedEffects.valueAt(index);
1735 if (desc->mRefCount <= 0) {
1736 ALOGW("setEffectSuspended_l() restore refcount should not be 0 %d", desc->mRefCount);
1737 desc->mRefCount = 1;
1738 }
1739 if (--desc->mRefCount == 0) {
1740 ALOGV("setEffectSuspended_l() remove entry for %08x", mSuspendedEffects.keyAt(index));
1741 if (desc->mEffect != 0) {
1742 sp<EffectModule> effect = desc->mEffect.promote();
1743 if (effect != 0) {
1744 effect->setSuspended(false);
1745 effect->lock();
1746 EffectHandle *handle = effect->controlHandle_l();
1747 if (handle != NULL && !handle->destroyed_l()) {
1748 effect->setEnabled_l(handle->enabled());
1749 }
1750 effect->unlock();
1751 }
1752 desc->mEffect.clear();
1753 }
1754 mSuspendedEffects.removeItemsAt(index);
1755 }
1756 }
1757}
1758
1759// must be called with ThreadBase::mLock held
1760void AudioFlinger::EffectChain::setEffectSuspendedAll_l(bool suspend)
1761{
1762 sp<SuspendedEffectDesc> desc;
1763
1764 ssize_t index = mSuspendedEffects.indexOfKey((int)kKeyForSuspendAll);
1765 if (suspend) {
1766 if (index >= 0) {
1767 desc = mSuspendedEffects.valueAt(index);
1768 } else {
1769 desc = new SuspendedEffectDesc();
1770 mSuspendedEffects.add((int)kKeyForSuspendAll, desc);
1771 ALOGV("setEffectSuspendedAll_l() add entry for 0");
1772 }
1773 if (desc->mRefCount++ == 0) {
1774 Vector< sp<EffectModule> > effects;
1775 getSuspendEligibleEffects(effects);
1776 for (size_t i = 0; i < effects.size(); i++) {
1777 setEffectSuspended_l(&effects[i]->desc().type, true);
1778 }
1779 }
1780 } else {
1781 if (index < 0) {
1782 return;
1783 }
1784 desc = mSuspendedEffects.valueAt(index);
1785 if (desc->mRefCount <= 0) {
1786 ALOGW("setEffectSuspendedAll_l() restore refcount should not be 0 %d", desc->mRefCount);
1787 desc->mRefCount = 1;
1788 }
1789 if (--desc->mRefCount == 0) {
1790 Vector<const effect_uuid_t *> types;
1791 for (size_t i = 0; i < mSuspendedEffects.size(); i++) {
1792 if (mSuspendedEffects.keyAt(i) == (int)kKeyForSuspendAll) {
1793 continue;
1794 }
1795 types.add(&mSuspendedEffects.valueAt(i)->mType);
1796 }
1797 for (size_t i = 0; i < types.size(); i++) {
1798 setEffectSuspended_l(types[i], false);
1799 }
1800 ALOGV("setEffectSuspendedAll_l() remove entry for %08x",
1801 mSuspendedEffects.keyAt(index));
1802 mSuspendedEffects.removeItem((int)kKeyForSuspendAll);
1803 }
1804 }
1805}
1806
1807
1808// The volume effect is used for automated tests only
1809#ifndef OPENSL_ES_H_
1810static const effect_uuid_t SL_IID_VOLUME_ = { 0x09e8ede0, 0xddde, 0x11db, 0xb4f6,
1811 { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } };
1812const effect_uuid_t * const SL_IID_VOLUME = &SL_IID_VOLUME_;
1813#endif //OPENSL_ES_H_
1814
1815bool AudioFlinger::EffectChain::isEffectEligibleForSuspend(const effect_descriptor_t& desc)
1816{
1817 // auxiliary effects and visualizer are never suspended on output mix
1818 if ((mSessionId == AUDIO_SESSION_OUTPUT_MIX) &&
1819 (((desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) ||
1820 (memcmp(&desc.type, SL_IID_VISUALIZATION, sizeof(effect_uuid_t)) == 0) ||
1821 (memcmp(&desc.type, SL_IID_VOLUME, sizeof(effect_uuid_t)) == 0))) {
1822 return false;
1823 }
1824 return true;
1825}
1826
1827void AudioFlinger::EffectChain::getSuspendEligibleEffects(
1828 Vector< sp<AudioFlinger::EffectModule> > &effects)
1829{
1830 effects.clear();
1831 for (size_t i = 0; i < mEffects.size(); i++) {
1832 if (isEffectEligibleForSuspend(mEffects[i]->desc())) {
1833 effects.add(mEffects[i]);
1834 }
1835 }
1836}
1837
1838sp<AudioFlinger::EffectModule> AudioFlinger::EffectChain::getEffectIfEnabled(
1839 const effect_uuid_t *type)
1840{
1841 sp<EffectModule> effect = getEffectFromType_l(type);
1842 return effect != 0 && effect->isEnabled() ? effect : 0;
1843}
1844
1845void AudioFlinger::EffectChain::checkSuspendOnEffectEnabled(const sp<EffectModule>& effect,
1846 bool enabled)
1847{
1848 ssize_t index = mSuspendedEffects.indexOfKey(effect->desc().type.timeLow);
1849 if (enabled) {
1850 if (index < 0) {
1851 // if the effect is not suspend check if all effects are suspended
1852 index = mSuspendedEffects.indexOfKey((int)kKeyForSuspendAll);
1853 if (index < 0) {
1854 return;
1855 }
1856 if (!isEffectEligibleForSuspend(effect->desc())) {
1857 return;
1858 }
1859 setEffectSuspended_l(&effect->desc().type, enabled);
1860 index = mSuspendedEffects.indexOfKey(effect->desc().type.timeLow);
1861 if (index < 0) {
1862 ALOGW("checkSuspendOnEffectEnabled() Fx should be suspended here!");
1863 return;
1864 }
1865 }
1866 ALOGV("checkSuspendOnEffectEnabled() enable suspending fx %08x",
1867 effect->desc().type.timeLow);
1868 sp<SuspendedEffectDesc> desc = mSuspendedEffects.valueAt(index);
1869 // if effect is requested to suspended but was not yet enabled, supend it now.
1870 if (desc->mEffect == 0) {
1871 desc->mEffect = effect;
1872 effect->setEnabled(false);
1873 effect->setSuspended(true);
1874 }
1875 } else {
1876 if (index < 0) {
1877 return;
1878 }
1879 ALOGV("checkSuspendOnEffectEnabled() disable restoring fx %08x",
1880 effect->desc().type.timeLow);
1881 sp<SuspendedEffectDesc> desc = mSuspendedEffects.valueAt(index);
1882 desc->mEffect.clear();
1883 effect->setSuspended(false);
1884 }
1885}
1886
Alok Kediya601e9b52013-09-27 11:55:10 +05301887
Eric Laurent5baf2af2013-09-12 17:37:00 -07001888bool AudioFlinger::EffectChain::isNonOffloadableEnabled()
Eric Laurent813e2a72013-08-31 12:59:48 -07001889{
1890 Mutex::Autolock _l(mLock);
1891 size_t size = mEffects.size();
1892 for (size_t i = 0; i < size; i++) {
Eric Laurent5baf2af2013-09-12 17:37:00 -07001893 if (mEffects[i]->isEnabled() && !mEffects[i]->isOffloadable()) {
Eric Laurent813e2a72013-08-31 12:59:48 -07001894 return true;
1895 }
1896 }
1897 return false;
1898}
1899
Ethan Chen8d420ed2013-11-14 00:40:54 -08001900#ifdef QCOM_HARDWARE
Alok Kediya601e9b52013-09-27 11:55:10 +05301901#define DEAFULT_FRAME_COUNT 1200
1902bool AudioFlinger::applyEffectsOn(void *token, int16_t *inBuffer,
1903 int16_t *outBuffer, int size, bool force)
1904{
1905 ALOGV("applyEffectsOn: inBuf %p outBuf %p size %d token %p", inBuffer, outBuffer, size, token);
1906 // This might be the first buffer to apply effects after effect config change
1907 // should not skip effects processing
1908 mIsEffectConfigChanged = false;
1909
1910 volatile size_t numEffects = 0;
1911#ifdef SRS_PROCESSING
1912 POSTPRO_PATCH_ICS_OUTPROC_DIRECT_SAMPLES(token, AUDIO_FORMAT_PCM_16_BIT, outBuffer, size, mLPASampleRate, mLPANumChannels);
1913#endif
1914
1915 if(mLPAEffectChain != NULL) {
1916 numEffects = mLPAEffectChain->getNumEffects();
1917 }
1918
1919 if( numEffects > 0) {
1920 size_t i = 0;
1921 int16_t *pIn = inBuffer;
1922 int16_t *pOut = outBuffer;
1923
1924 int frameCount = size / (sizeof(int16_t) * mLPANumChannels);
1925
1926 while(frameCount > 0) {
1927 if(mLPAEffectChain == NULL) {
1928 ALOGV("LPA Effect Chain is removed - No effects processing !!");
1929 numEffects = 0;
1930 break;
1931 }
1932 mLPAEffectChain->lock();
1933
1934 numEffects = mLPAEffectChain->getNumEffects();
1935 if(!numEffects) {
1936 ALOGV("applyEffectsOn: All the effects are removed - nothing to process");
1937 mLPAEffectChain->unlock();
1938 break;
1939 }
1940
1941 int outFrameCount = (frameCount > DEAFULT_FRAME_COUNT ? DEAFULT_FRAME_COUNT: frameCount);
1942 bool isEffectEnabled = false;
1943 for(i = 0; i < numEffects; i++) {
1944 // If effect configuration is changed while applying effects do not process further
1945 if(mIsEffectConfigChanged && !force) {
1946 mLPAEffectChain->unlock();
1947 ALOGV("applyEffectsOn: mIsEffectConfigChanged is set - no further processing %d",frameCount);
1948 return false;
1949 }
1950 sp<EffectModule> effect = mLPAEffectChain->getEffectFromIndex_l(i);
1951 if(effect == NULL) {
1952 ALOGE("getEffectFromIndex_l(%d) returned NULL ptr", i);
1953 mLPAEffectChain->unlock();
1954 return false;
1955 }
1956 if(i == 0) {
1957 // For the first set input and output buffers different
1958 isEffectEnabled = effect->isProcessEnabled();
1959 effect->setInBuffer(pIn);
1960 effect->setOutBuffer(pOut);
1961 } else {
1962 // For the remaining use previous effect's output buffer as input buffer
1963 effect->setInBuffer(pOut);
1964 effect->setOutBuffer(pOut);
1965 }
1966 // true indicates that it is being applied on LPA output
1967 effect->configure(true, mLPASampleRate, mLPANumChannels, outFrameCount);
1968 }
1969
1970 if(isEffectEnabled) {
1971 // Clear the output buffer
1972 memset(pOut, 0, (outFrameCount * mLPANumChannels * sizeof(int16_t)));
1973 } else {
1974 // Copy input buffer content to the output buffer
1975 memcpy(pOut, pIn, (outFrameCount * mLPANumChannels * sizeof(int16_t)));
1976 }
1977
1978 mLPAEffectChain->process_l();
1979
1980 mLPAEffectChain->unlock();
1981
1982 // Update input and output buffer pointers
1983 pIn += (outFrameCount * mLPANumChannels);
1984 pOut += (outFrameCount * mLPANumChannels);
1985 frameCount -= outFrameCount;
1986 }
1987 }
1988
1989 if (!numEffects && !force) {
1990 ALOGV("applyEffectsOn: There are no effects to be applied");
1991 if(inBuffer != outBuffer) {
1992 // No effect applied so just copy input buffer to output buffer
1993 memcpy(outBuffer, inBuffer, size);
1994 }
1995 }
1996 return true;
1997}
1998
1999void *AudioFlinger::DirectAudioTrack::EffectsThreadWrapper(void *me) {
2000 static_cast<DirectAudioTrack *>(me)->EffectsThreadEntry();
2001 return NULL;
2002}
2003
2004void AudioFlinger::DirectAudioTrack::EffectsThreadEntry() {
2005 while(1) {
2006 mEffectLock.lock();
2007 if (!mEffectConfigChanged && !mKillEffectsThread) {
2008 mEffectCv.wait(mEffectLock);
2009 }
2010 if(mKillEffectsThread) {
2011 mEffectLock.unlock();
2012 break;
2013 }
2014 if (mEffectConfigChanged) {
2015 mEffectConfigChanged = false;
2016 if (mFlag & AUDIO_OUTPUT_FLAG_LPA) {
2017 for ( List<BufferInfo>::iterator it = mEffectsPool.begin();
2018 it != mEffectsPool.end(); it++) {
2019 ALOGV("ete: calling applyEffectsOn buff %x",it->localBuf);
2020 bool isEffectsApplied = mAudioFlinger->applyEffectsOn(
2021 static_cast<void *>(this),
2022 (int16_t *)it->localBuf,
2023 (int16_t *)mEffectsThreadScratchBuffer,
2024 it->bytesToWrite,
2025 false);
2026 if (isEffectsApplied == true){
2027 ALOGV("ete:dsp updated for local buf %x",it->localBuf);
2028 memcpy(it->dspBuf, mEffectsThreadScratchBuffer, it->bytesToWrite);
2029 }
2030 else
2031 ALOGV("ete:dsp updated for local buf %x SKIPPED",it->localBuf);
2032
2033 if (mEffectConfigChanged) {
2034 ALOGE("ete:effects changed, abort effects application");
2035 break;
2036 }
2037 }
2038#ifdef SRS_PROCESSING
2039 } else if (mFlag & AUDIO_OUTPUT_FLAG_TUNNEL) {
2040 ALOGV("applying effects for TUNNEL");
2041 char buffer[2];
2042 //dummy buffer to ensure the SRS processing takes place
2043 // The API mandates Sample rate and channel mode. Hence
2044 // defaulted the sample rate channel mode to 48000 and 2 respectively
2045 POSTPRO_PATCH_ICS_OUTPROC_DIRECT_SAMPLES(static_cast<void *>(this),
2046 AUDIO_FORMAT_PCM_16_BIT,
2047 (int16_t*)buffer, 2, 48000, 2);
2048#endif
2049 }
2050 }
2051 mEffectLock.unlock();
2052 }
2053 ALOGV("Effects thread is dead");
2054 mEffectsThreadAlive = false;
2055}
2056
2057void AudioFlinger::DirectAudioTrack::requestAndWaitForEffectsThreadExit() {
2058 if (!mEffectsThreadAlive)
2059 return;
2060 mKillEffectsThread = true;
2061 mEffectCv.signal();
2062 pthread_join(mEffectsThread,NULL);
2063 ALOGV("effects thread killed");
2064}
2065
2066void AudioFlinger::DirectAudioTrack::createEffectThread() {
2067 //Create the effects thread
2068 pthread_attr_t attr;
2069 pthread_attr_init(&attr);
2070 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
2071 mEffectsThreadAlive = true;
2072 ALOGV("Creating Effects Thread");
2073 pthread_create(&mEffectsThread, &attr, EffectsThreadWrapper, this);
2074}
Ethan Chen8d420ed2013-11-14 00:40:54 -08002075#endif
Alok Kediya601e9b52013-09-27 11:55:10 +05302076
Eric Laurentca7cc822012-11-19 14:55:58 -08002077}; // namespace android