blob: d4035d6bf132935227e26428578d84eb70b73829 [file] [log] [blame]
Eric Laurentca7cc822012-11-19 14:55:58 -08001/*
2**
3** Copyright 2012, The Android Open Source Project
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9** http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
18
19#define LOG_TAG "AudioFlinger"
20//#define LOG_NDEBUG 0
21
Glenn Kasten153b9fe2013-07-15 11:23:36 -070022#include "Configuration.h"
Eric Laurentca7cc822012-11-19 14:55:58 -080023#include <utils/Log.h>
24#include <audio_effects/effect_visualizer.h>
25#include <audio_utils/primitives.h>
26#include <private/media/AudioEffectShared.h>
27#include <media/EffectsFactoryApi.h>
28
29#include "AudioFlinger.h"
Mikhail Naganov4a3d5c22016-08-15 13:47:42 -070030#include "EffectHalInterface.h"
Mikhail Naganov4a3d5c22016-08-15 13:47:42 -070031#include "EffectsFactoryHalInterface.h"
Eric Laurentca7cc822012-11-19 14:55:58 -080032#include "ServiceUtilities.h"
33
34// ----------------------------------------------------------------------------
35
36// Note: the following macro is used for extremely verbose logging message. In
37// order to run with ALOG_ASSERT turned on, we need to have LOG_NDEBUG set to
38// 0; but one side effect of this is to turn all LOGV's as well. Some messages
39// are so verbose that we want to suppress them even when we have ALOG_ASSERT
40// turned on. Do not uncomment the #def below unless you really know what you
41// are doing and want to see all of the extremely verbose messages.
42//#define VERY_VERY_VERBOSE_LOGGING
43#ifdef VERY_VERY_VERBOSE_LOGGING
44#define ALOGVV ALOGV
45#else
46#define ALOGVV(a...) do { } while(0)
47#endif
48
Ricardo Garcia726b6a72014-08-11 12:04:54 -070049#define min(a, b) ((a) < (b) ? (a) : (b))
50
Eric Laurentca7cc822012-11-19 14:55:58 -080051namespace android {
52
53// ----------------------------------------------------------------------------
54// EffectModule implementation
55// ----------------------------------------------------------------------------
56
57#undef LOG_TAG
58#define LOG_TAG "AudioFlinger::EffectModule"
59
60AudioFlinger::EffectModule::EffectModule(ThreadBase *thread,
61 const wp<AudioFlinger::EffectChain>& chain,
62 effect_descriptor_t *desc,
63 int id,
Glenn Kastend848eb42016-03-08 13:42:11 -080064 audio_session_t sessionId)
Eric Laurentca7cc822012-11-19 14:55:58 -080065 : mPinned(sessionId > AUDIO_SESSION_OUTPUT_MIX),
66 mThread(thread), mChain(chain), mId(id), mSessionId(sessionId),
67 mDescriptor(*desc),
68 // mConfig is set by configure() and not used before then
Eric Laurentca7cc822012-11-19 14:55:58 -080069 mStatus(NO_INIT), mState(IDLE),
70 // mMaxDisableWaitCnt is set by configure() and not used before then
71 // mDisableWaitCnt is set by process() and updateState() and not used before then
Eric Laurentaaa44472014-09-12 17:41:50 -070072 mSuspended(false),
73 mAudioFlinger(thread->mAudioFlinger)
Eric Laurentca7cc822012-11-19 14:55:58 -080074{
75 ALOGV("Constructor %p", this);
76 int lStatus;
77
78 // create effect engine from effect factory
Mikhail Naganov4a3d5c22016-08-15 13:47:42 -070079 mStatus = -ENODEV;
80 sp<AudioFlinger> audioFlinger = mAudioFlinger.promote();
Mikhail Naganov1dc98672016-08-18 17:50:29 -070081 if (audioFlinger != 0) {
Mikhail Naganov4a3d5c22016-08-15 13:47:42 -070082 sp<EffectsFactoryHalInterface> effectsFactory = audioFlinger->getEffectsFactory();
Mikhail Naganov1dc98672016-08-18 17:50:29 -070083 if (effectsFactory != 0) {
Mikhail Naganov4a3d5c22016-08-15 13:47:42 -070084 mStatus = effectsFactory->createEffect(
85 &desc->uuid, sessionId, thread->id(), &mEffectInterface);
86 }
87 }
Eric Laurentca7cc822012-11-19 14:55:58 -080088
89 if (mStatus != NO_ERROR) {
90 return;
91 }
92 lStatus = init();
93 if (lStatus < 0) {
94 mStatus = lStatus;
95 goto Error;
96 }
97
Mikhail Naganov4a3d5c22016-08-15 13:47:42 -070098 ALOGV("Constructor success name %s, Interface %p", mDescriptor.name, mEffectInterface.get());
Eric Laurentca7cc822012-11-19 14:55:58 -080099 return;
100Error:
Mikhail Naganov4a3d5c22016-08-15 13:47:42 -0700101 mEffectInterface.clear();
Eric Laurentca7cc822012-11-19 14:55:58 -0800102 ALOGV("Constructor Error %d", mStatus);
103}
104
105AudioFlinger::EffectModule::~EffectModule()
106{
107 ALOGV("Destructor %p", this);
Mikhail Naganov1dc98672016-08-18 17:50:29 -0700108 if (mEffectInterface != 0) {
Eric Laurentbfb1b832013-01-07 09:53:42 -0800109 remove_effect_from_hal_l();
Eric Laurentca7cc822012-11-19 14:55:58 -0800110 // release effect engine
Mikhail Naganov4a3d5c22016-08-15 13:47:42 -0700111 mEffectInterface.clear();
Eric Laurentca7cc822012-11-19 14:55:58 -0800112 }
113}
114
115status_t AudioFlinger::EffectModule::addHandle(EffectHandle *handle)
116{
117 status_t status;
118
119 Mutex::Autolock _l(mLock);
120 int priority = handle->priority();
121 size_t size = mHandles.size();
122 EffectHandle *controlHandle = NULL;
123 size_t i;
124 for (i = 0; i < size; i++) {
125 EffectHandle *h = mHandles[i];
126 if (h == NULL || h->destroyed_l()) {
127 continue;
128 }
129 // first non destroyed handle is considered in control
Glenn Kasten6e2ebe92013-08-13 09:14:51 -0700130 if (controlHandle == NULL) {
Eric Laurentca7cc822012-11-19 14:55:58 -0800131 controlHandle = h;
Glenn Kasten6e2ebe92013-08-13 09:14:51 -0700132 }
Eric Laurentca7cc822012-11-19 14:55:58 -0800133 if (h->priority() <= priority) {
134 break;
135 }
136 }
137 // if inserted in first place, move effect control from previous owner to this handle
138 if (i == 0) {
139 bool enabled = false;
140 if (controlHandle != NULL) {
141 enabled = controlHandle->enabled();
142 controlHandle->setControl(false/*hasControl*/, true /*signal*/, enabled /*enabled*/);
143 }
144 handle->setControl(true /*hasControl*/, false /*signal*/, enabled /*enabled*/);
145 status = NO_ERROR;
146 } else {
147 status = ALREADY_EXISTS;
148 }
Glenn Kastenc42e9b42016-03-21 11:35:03 -0700149 ALOGV("addHandle() %p added handle %p in position %zu", this, handle, i);
Eric Laurentca7cc822012-11-19 14:55:58 -0800150 mHandles.insertAt(handle, i);
151 return status;
152}
153
154size_t AudioFlinger::EffectModule::removeHandle(EffectHandle *handle)
155{
156 Mutex::Autolock _l(mLock);
157 size_t size = mHandles.size();
158 size_t i;
159 for (i = 0; i < size; i++) {
160 if (mHandles[i] == handle) {
161 break;
162 }
163 }
164 if (i == size) {
165 return size;
166 }
Glenn Kastenc42e9b42016-03-21 11:35:03 -0700167 ALOGV("removeHandle() %p removed handle %p in position %zu", this, handle, i);
Eric Laurentca7cc822012-11-19 14:55:58 -0800168
169 mHandles.removeAt(i);
170 // if removed from first place, move effect control from this handle to next in line
171 if (i == 0) {
172 EffectHandle *h = controlHandle_l();
173 if (h != NULL) {
174 h->setControl(true /*hasControl*/, true /*signal*/ , handle->enabled() /*enabled*/);
175 }
176 }
177
178 // Prevent calls to process() and other functions on effect interface from now on.
179 // The effect engine will be released by the destructor when the last strong reference on
180 // this object is released which can happen after next process is called.
181 if (mHandles.size() == 0 && !mPinned) {
182 mState = DESTROYED;
183 }
184
185 return mHandles.size();
186}
187
188// must be called with EffectModule::mLock held
189AudioFlinger::EffectHandle *AudioFlinger::EffectModule::controlHandle_l()
190{
191 // the first valid handle in the list has control over the module
192 for (size_t i = 0; i < mHandles.size(); i++) {
193 EffectHandle *h = mHandles[i];
194 if (h != NULL && !h->destroyed_l()) {
195 return h;
196 }
197 }
198
199 return NULL;
200}
201
202size_t AudioFlinger::EffectModule::disconnect(EffectHandle *handle, bool unpinIfLast)
203{
204 ALOGV("disconnect() %p handle %p", this, handle);
205 // keep a strong reference on this EffectModule to avoid calling the
206 // destructor before we exit
207 sp<EffectModule> keep(this);
208 {
Eric Laurentaaa44472014-09-12 17:41:50 -0700209 if (removeHandle(handle) == 0) {
210 if (!isPinned() || unpinIfLast) {
211 sp<ThreadBase> thread = mThread.promote();
212 if (thread != 0) {
213 Mutex::Autolock _l(thread->mLock);
214 thread->removeEffect_l(this);
215 }
216 sp<AudioFlinger> af = mAudioFlinger.promote();
217 if (af != 0) {
218 af->updateOrphanEffectChains(this);
219 }
220 AudioSystem::unregisterEffect(mId);
221 }
Eric Laurentca7cc822012-11-19 14:55:58 -0800222 }
223 }
224 return mHandles.size();
225}
226
Eric Laurentfa1e1232016-08-02 19:01:49 -0700227bool AudioFlinger::EffectModule::updateState() {
Eric Laurentca7cc822012-11-19 14:55:58 -0800228 Mutex::Autolock _l(mLock);
229
Eric Laurentfa1e1232016-08-02 19:01:49 -0700230 bool started = false;
Eric Laurentca7cc822012-11-19 14:55:58 -0800231 switch (mState) {
232 case RESTART:
233 reset_l();
234 // FALL THROUGH
235
236 case STARTING:
237 // clear auxiliary effect input buffer for next accumulation
238 if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
239 memset(mConfig.inputCfg.buffer.raw,
240 0,
241 mConfig.inputCfg.buffer.frameCount*sizeof(int32_t));
242 }
Eric Laurentd0ebb532013-04-02 16:41:41 -0700243 if (start_l() == NO_ERROR) {
244 mState = ACTIVE;
Eric Laurentfa1e1232016-08-02 19:01:49 -0700245 started = true;
Eric Laurentd0ebb532013-04-02 16:41:41 -0700246 } else {
247 mState = IDLE;
248 }
Eric Laurentca7cc822012-11-19 14:55:58 -0800249 break;
250 case STOPPING:
Eric Laurentd0ebb532013-04-02 16:41:41 -0700251 if (stop_l() == NO_ERROR) {
252 mDisableWaitCnt = mMaxDisableWaitCnt;
253 } else {
254 mDisableWaitCnt = 1; // will cause immediate transition to IDLE
255 }
Eric Laurentca7cc822012-11-19 14:55:58 -0800256 mState = STOPPED;
257 break;
258 case STOPPED:
259 // mDisableWaitCnt is forced to 1 by process() when the engine indicates the end of the
260 // turn off sequence.
261 if (--mDisableWaitCnt == 0) {
262 reset_l();
263 mState = IDLE;
264 }
265 break;
266 default: //IDLE , ACTIVE, DESTROYED
267 break;
268 }
Eric Laurentfa1e1232016-08-02 19:01:49 -0700269
270 return started;
Eric Laurentca7cc822012-11-19 14:55:58 -0800271}
272
273void AudioFlinger::EffectModule::process()
274{
275 Mutex::Autolock _l(mLock);
276
Mikhail Naganov1dc98672016-08-18 17:50:29 -0700277 if (mState == DESTROYED || mEffectInterface == 0 ||
Eric Laurentca7cc822012-11-19 14:55:58 -0800278 mConfig.inputCfg.buffer.raw == NULL ||
279 mConfig.outputCfg.buffer.raw == NULL) {
280 return;
281 }
282
283 if (isProcessEnabled()) {
284 // do 32 bit to 16 bit conversion for auxiliary effect input buffer
285 if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
286 ditherAndClamp(mConfig.inputCfg.buffer.s32,
287 mConfig.inputCfg.buffer.s32,
288 mConfig.inputCfg.buffer.frameCount/2);
289 }
Eric Laurent6dd0fd92016-09-15 12:44:53 -0700290 int ret;
291 if (isProcessImplemented()) {
292 // do the actual processing in the effect engine
Eric Laurentdb0fd692016-09-16 10:26:09 -0700293 ret = mEffectInterface->process(&mConfig.inputCfg.buffer, &mConfig.outputCfg.buffer);
Eric Laurent6dd0fd92016-09-15 12:44:53 -0700294 } else {
295 if (mConfig.inputCfg.buffer.raw != mConfig.outputCfg.buffer.raw) {
296 size_t frameCnt = mConfig.inputCfg.buffer.frameCount * FCC_2; //always stereo here
297 int16_t *in = mConfig.inputCfg.buffer.s16;
298 int16_t *out = mConfig.outputCfg.buffer.s16;
Eric Laurentca7cc822012-11-19 14:55:58 -0800299
Eric Laurent6dd0fd92016-09-15 12:44:53 -0700300 if (mConfig.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE) {
301 for (size_t i = 0; i < frameCnt; i++) {
302 out[i] = clamp16((int32_t)out[i] + (int32_t)in[i]);
303 }
304 } else {
305 memcpy(mConfig.outputCfg.buffer.raw, mConfig.inputCfg.buffer.raw,
306 frameCnt * sizeof(int16_t));
307 }
308 }
309 ret = -ENODATA;
310 }
Eric Laurentca7cc822012-11-19 14:55:58 -0800311 // force transition to IDLE state when engine is ready
312 if (mState == STOPPED && ret == -ENODATA) {
313 mDisableWaitCnt = 1;
314 }
315
316 // clear auxiliary effect input buffer for next accumulation
317 if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
318 memset(mConfig.inputCfg.buffer.raw, 0,
319 mConfig.inputCfg.buffer.frameCount*sizeof(int32_t));
320 }
321 } else if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_INSERT &&
322 mConfig.inputCfg.buffer.raw != mConfig.outputCfg.buffer.raw) {
323 // If an insert effect is idle and input buffer is different from output buffer,
324 // accumulate input onto output
325 sp<EffectChain> chain = mChain.promote();
326 if (chain != 0 && chain->activeTrackCnt() != 0) {
Eric Laurent6dd0fd92016-09-15 12:44:53 -0700327 size_t frameCnt = mConfig.inputCfg.buffer.frameCount * FCC_2; //always stereo here
Eric Laurentca7cc822012-11-19 14:55:58 -0800328 int16_t *in = mConfig.inputCfg.buffer.s16;
329 int16_t *out = mConfig.outputCfg.buffer.s16;
330 for (size_t i = 0; i < frameCnt; i++) {
331 out[i] = clamp16((int32_t)out[i] + (int32_t)in[i]);
332 }
333 }
334 }
335}
336
337void AudioFlinger::EffectModule::reset_l()
338{
Mikhail Naganov1dc98672016-08-18 17:50:29 -0700339 if (mStatus != NO_ERROR || mEffectInterface == 0) {
Eric Laurentca7cc822012-11-19 14:55:58 -0800340 return;
341 }
Mikhail Naganov4a3d5c22016-08-15 13:47:42 -0700342 mEffectInterface->command(EFFECT_CMD_RESET, 0, NULL, 0, NULL);
Eric Laurentca7cc822012-11-19 14:55:58 -0800343}
344
345status_t AudioFlinger::EffectModule::configure()
346{
Eric Laurentd0ebb532013-04-02 16:41:41 -0700347 status_t status;
348 sp<ThreadBase> thread;
349 uint32_t size;
350 audio_channel_mask_t channelMask;
351
Mikhail Naganov1dc98672016-08-18 17:50:29 -0700352 if (mEffectInterface == 0) {
Eric Laurentd0ebb532013-04-02 16:41:41 -0700353 status = NO_INIT;
354 goto exit;
Eric Laurentca7cc822012-11-19 14:55:58 -0800355 }
356
Eric Laurentd0ebb532013-04-02 16:41:41 -0700357 thread = mThread.promote();
Eric Laurentca7cc822012-11-19 14:55:58 -0800358 if (thread == 0) {
Eric Laurentd0ebb532013-04-02 16:41:41 -0700359 status = DEAD_OBJECT;
360 goto exit;
Eric Laurentca7cc822012-11-19 14:55:58 -0800361 }
362
363 // TODO: handle configuration of effects replacing track process
Eric Laurentd0ebb532013-04-02 16:41:41 -0700364 channelMask = thread->channelMask();
Ricardo Garciad11da702015-05-28 12:14:12 -0700365 mConfig.outputCfg.channels = channelMask;
Eric Laurentca7cc822012-11-19 14:55:58 -0800366
367 if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
368 mConfig.inputCfg.channels = AUDIO_CHANNEL_OUT_MONO;
369 } else {
370 mConfig.inputCfg.channels = channelMask;
Ricardo Garciad11da702015-05-28 12:14:12 -0700371 // TODO: Update this logic when multichannel effects are implemented.
372 // For offloaded tracks consider mono output as stereo for proper effect initialization
373 if (channelMask == AUDIO_CHANNEL_OUT_MONO) {
374 mConfig.inputCfg.channels = AUDIO_CHANNEL_OUT_STEREO;
375 mConfig.outputCfg.channels = AUDIO_CHANNEL_OUT_STEREO;
376 ALOGV("Overriding effect input and output as STEREO");
377 }
Eric Laurentca7cc822012-11-19 14:55:58 -0800378 }
Ricardo Garciad11da702015-05-28 12:14:12 -0700379
Eric Laurentca7cc822012-11-19 14:55:58 -0800380 mConfig.inputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
381 mConfig.outputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
382 mConfig.inputCfg.samplingRate = thread->sampleRate();
383 mConfig.outputCfg.samplingRate = mConfig.inputCfg.samplingRate;
384 mConfig.inputCfg.bufferProvider.cookie = NULL;
385 mConfig.inputCfg.bufferProvider.getBuffer = NULL;
386 mConfig.inputCfg.bufferProvider.releaseBuffer = NULL;
387 mConfig.outputCfg.bufferProvider.cookie = NULL;
388 mConfig.outputCfg.bufferProvider.getBuffer = NULL;
389 mConfig.outputCfg.bufferProvider.releaseBuffer = NULL;
390 mConfig.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ;
391 // Insert effect:
392 // - in session AUDIO_SESSION_OUTPUT_MIX or AUDIO_SESSION_OUTPUT_STAGE,
393 // always overwrites output buffer: input buffer == output buffer
394 // - in other sessions:
395 // last effect in the chain accumulates in output buffer: input buffer != output buffer
396 // other effect: overwrites output buffer: input buffer == output buffer
397 // Auxiliary effect:
398 // accumulates in output buffer: input buffer != output buffer
399 // Therefore: accumulate <=> input buffer != output buffer
400 if (mConfig.inputCfg.buffer.raw != mConfig.outputCfg.buffer.raw) {
401 mConfig.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_ACCUMULATE;
402 } else {
403 mConfig.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_WRITE;
404 }
405 mConfig.inputCfg.mask = EFFECT_CONFIG_ALL;
406 mConfig.outputCfg.mask = EFFECT_CONFIG_ALL;
407 mConfig.inputCfg.buffer.frameCount = thread->frameCount();
408 mConfig.outputCfg.buffer.frameCount = mConfig.inputCfg.buffer.frameCount;
409
Glenn Kastenc42e9b42016-03-21 11:35:03 -0700410 ALOGV("configure() %p thread %p buffer %p framecount %zu",
Eric Laurentca7cc822012-11-19 14:55:58 -0800411 this, thread.get(), mConfig.inputCfg.buffer.raw, mConfig.inputCfg.buffer.frameCount);
412
413 status_t cmdStatus;
Eric Laurentd0ebb532013-04-02 16:41:41 -0700414 size = sizeof(int);
Mikhail Naganov4a3d5c22016-08-15 13:47:42 -0700415 status = mEffectInterface->command(EFFECT_CMD_SET_CONFIG,
416 sizeof(effect_config_t),
417 &mConfig,
418 &size,
419 &cmdStatus);
Eric Laurentca7cc822012-11-19 14:55:58 -0800420 if (status == 0) {
421 status = cmdStatus;
422 }
423
424 if (status == 0 &&
425 (memcmp(&mDescriptor.type, SL_IID_VISUALIZATION, sizeof(effect_uuid_t)) == 0)) {
426 uint32_t buf32[sizeof(effect_param_t) / sizeof(uint32_t) + 2];
427 effect_param_t *p = (effect_param_t *)buf32;
428
429 p->psize = sizeof(uint32_t);
430 p->vsize = sizeof(uint32_t);
431 size = sizeof(int);
432 *(int32_t *)p->data = VISUALIZER_PARAM_LATENCY;
433
434 uint32_t latency = 0;
435 PlaybackThread *pbt = thread->mAudioFlinger->checkPlaybackThread_l(thread->mId);
436 if (pbt != NULL) {
437 latency = pbt->latency_l();
438 }
439
440 *((int32_t *)p->data + 1)= latency;
Mikhail Naganov4a3d5c22016-08-15 13:47:42 -0700441 mEffectInterface->command(EFFECT_CMD_SET_PARAM,
442 sizeof(effect_param_t) + 8,
443 &buf32,
444 &size,
445 &cmdStatus);
Eric Laurentca7cc822012-11-19 14:55:58 -0800446 }
447
448 mMaxDisableWaitCnt = (MAX_DISABLE_TIME_MS * mConfig.outputCfg.samplingRate) /
449 (1000 * mConfig.outputCfg.buffer.frameCount);
450
Eric Laurentd0ebb532013-04-02 16:41:41 -0700451exit:
452 mStatus = status;
Eric Laurentca7cc822012-11-19 14:55:58 -0800453 return status;
454}
455
456status_t AudioFlinger::EffectModule::init()
457{
458 Mutex::Autolock _l(mLock);
Mikhail Naganov1dc98672016-08-18 17:50:29 -0700459 if (mEffectInterface == 0) {
Eric Laurentca7cc822012-11-19 14:55:58 -0800460 return NO_INIT;
461 }
462 status_t cmdStatus;
463 uint32_t size = sizeof(status_t);
Mikhail Naganov4a3d5c22016-08-15 13:47:42 -0700464 status_t status = mEffectInterface->command(EFFECT_CMD_INIT,
465 0,
466 NULL,
467 &size,
468 &cmdStatus);
Eric Laurentca7cc822012-11-19 14:55:58 -0800469 if (status == 0) {
470 status = cmdStatus;
471 }
472 return status;
473}
474
Eric Laurent1b928682014-10-02 19:41:47 -0700475void AudioFlinger::EffectModule::addEffectToHal_l()
476{
477 if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC ||
478 (mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_POST_PROC) {
479 sp<ThreadBase> thread = mThread.promote();
480 if (thread != 0) {
Mikhail Naganov1dc98672016-08-18 17:50:29 -0700481 sp<StreamHalInterface> stream = thread->stream();
482 if (stream != 0) {
483 status_t result = stream->addEffect(mEffectInterface);
484 ALOGE_IF(result != OK, "Error when adding effect: %d", result);
Eric Laurent1b928682014-10-02 19:41:47 -0700485 }
486 }
487 }
488}
489
Eric Laurentfa1e1232016-08-02 19:01:49 -0700490// start() must be called with PlaybackThread::mLock or EffectChain::mLock held
Eric Laurentca7cc822012-11-19 14:55:58 -0800491status_t AudioFlinger::EffectModule::start()
492{
Eric Laurentfa1e1232016-08-02 19:01:49 -0700493 sp<EffectChain> chain;
494 status_t status;
495 {
496 Mutex::Autolock _l(mLock);
497 status = start_l();
498 if (status == NO_ERROR) {
499 chain = mChain.promote();
500 }
501 }
502 if (chain != 0) {
503 chain->resetVolume_l();
504 }
505 return status;
Eric Laurentca7cc822012-11-19 14:55:58 -0800506}
507
508status_t AudioFlinger::EffectModule::start_l()
509{
Mikhail Naganov1dc98672016-08-18 17:50:29 -0700510 if (mEffectInterface == 0) {
Eric Laurentca7cc822012-11-19 14:55:58 -0800511 return NO_INIT;
512 }
Eric Laurentd0ebb532013-04-02 16:41:41 -0700513 if (mStatus != NO_ERROR) {
514 return mStatus;
515 }
Eric Laurentca7cc822012-11-19 14:55:58 -0800516 status_t cmdStatus;
517 uint32_t size = sizeof(status_t);
Mikhail Naganov4a3d5c22016-08-15 13:47:42 -0700518 status_t status = mEffectInterface->command(EFFECT_CMD_ENABLE,
519 0,
520 NULL,
521 &size,
522 &cmdStatus);
Eric Laurentca7cc822012-11-19 14:55:58 -0800523 if (status == 0) {
524 status = cmdStatus;
525 }
Eric Laurentcb4b6e92014-10-01 14:26:10 -0700526 if (status == 0) {
Eric Laurent1b928682014-10-02 19:41:47 -0700527 addEffectToHal_l();
Eric Laurentca7cc822012-11-19 14:55:58 -0800528 }
529 return status;
530}
531
532status_t AudioFlinger::EffectModule::stop()
533{
534 Mutex::Autolock _l(mLock);
535 return stop_l();
536}
537
538status_t AudioFlinger::EffectModule::stop_l()
539{
Mikhail Naganov1dc98672016-08-18 17:50:29 -0700540 if (mEffectInterface == 0) {
Eric Laurentca7cc822012-11-19 14:55:58 -0800541 return NO_INIT;
542 }
Eric Laurentd0ebb532013-04-02 16:41:41 -0700543 if (mStatus != NO_ERROR) {
544 return mStatus;
545 }
Eric Laurentbfb1b832013-01-07 09:53:42 -0800546 status_t cmdStatus = NO_ERROR;
Eric Laurentca7cc822012-11-19 14:55:58 -0800547 uint32_t size = sizeof(status_t);
Mikhail Naganov4a3d5c22016-08-15 13:47:42 -0700548 status_t status = mEffectInterface->command(EFFECT_CMD_DISABLE,
549 0,
550 NULL,
551 &size,
552 &cmdStatus);
Eric Laurentbfb1b832013-01-07 09:53:42 -0800553 if (status == NO_ERROR) {
Eric Laurentca7cc822012-11-19 14:55:58 -0800554 status = cmdStatus;
555 }
Eric Laurentbfb1b832013-01-07 09:53:42 -0800556 if (status == NO_ERROR) {
557 status = remove_effect_from_hal_l();
558 }
559 return status;
560}
561
562status_t AudioFlinger::EffectModule::remove_effect_from_hal_l()
563{
564 if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC ||
565 (mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_POST_PROC) {
Eric Laurentca7cc822012-11-19 14:55:58 -0800566 sp<ThreadBase> thread = mThread.promote();
567 if (thread != 0) {
Mikhail Naganov1dc98672016-08-18 17:50:29 -0700568 sp<StreamHalInterface> stream = thread->stream();
569 if (stream != 0) {
570 status_t result = stream->removeEffect(mEffectInterface);
571 ALOGE_IF(result != OK, "Error when removing effect: %d", result);
Eric Laurentca7cc822012-11-19 14:55:58 -0800572 }
573 }
574 }
Eric Laurentbfb1b832013-01-07 09:53:42 -0800575 return NO_ERROR;
Eric Laurentca7cc822012-11-19 14:55:58 -0800576}
577
Andy Hunge4a1d912016-08-17 14:11:13 -0700578// round up delta valid if value and divisor are positive.
579template <typename T>
580static T roundUpDelta(const T &value, const T &divisor) {
581 T remainder = value % divisor;
582 return remainder == 0 ? 0 : divisor - remainder;
583}
584
Eric Laurentca7cc822012-11-19 14:55:58 -0800585status_t AudioFlinger::EffectModule::command(uint32_t cmdCode,
586 uint32_t cmdSize,
587 void *pCmdData,
588 uint32_t *replySize,
589 void *pReplyData)
590{
591 Mutex::Autolock _l(mLock);
Mikhail Naganov4a3d5c22016-08-15 13:47:42 -0700592 ALOGVV("command(), cmdCode: %d, mEffectInterface: %p", cmdCode, mEffectInterface.get());
Eric Laurentca7cc822012-11-19 14:55:58 -0800593
Mikhail Naganov1dc98672016-08-18 17:50:29 -0700594 if (mState == DESTROYED || mEffectInterface == 0) {
Eric Laurentca7cc822012-11-19 14:55:58 -0800595 return NO_INIT;
596 }
Eric Laurentd0ebb532013-04-02 16:41:41 -0700597 if (mStatus != NO_ERROR) {
598 return mStatus;
599 }
Andy Hung110bc952016-06-20 15:22:52 -0700600 if (cmdCode == EFFECT_CMD_GET_PARAM &&
601 (*replySize < sizeof(effect_param_t) ||
602 ((effect_param_t *)pCmdData)->psize > *replySize - sizeof(effect_param_t))) {
603 android_errorWriteLog(0x534e4554, "29251553");
604 return -EINVAL;
605 }
Andy Hunge4a1d912016-08-17 14:11:13 -0700606 if ((cmdCode == EFFECT_CMD_SET_PARAM
607 || cmdCode == EFFECT_CMD_SET_PARAM_DEFERRED) && // DEFERRED not generally used
608 (sizeof(effect_param_t) > cmdSize
609 || ((effect_param_t *)pCmdData)->psize > cmdSize
610 - sizeof(effect_param_t)
611 || ((effect_param_t *)pCmdData)->vsize > cmdSize
612 - sizeof(effect_param_t)
613 - ((effect_param_t *)pCmdData)->psize
614 || roundUpDelta(((effect_param_t *)pCmdData)->psize, (uint32_t)sizeof(int)) >
615 cmdSize
616 - sizeof(effect_param_t)
617 - ((effect_param_t *)pCmdData)->psize
618 - ((effect_param_t *)pCmdData)->vsize)) {
619 android_errorWriteLog(0x534e4554, "30204301");
620 return -EINVAL;
621 }
Mikhail Naganov4a3d5c22016-08-15 13:47:42 -0700622 status_t status = mEffectInterface->command(cmdCode,
623 cmdSize,
624 pCmdData,
625 replySize,
626 pReplyData);
Eric Laurentca7cc822012-11-19 14:55:58 -0800627 if (cmdCode != EFFECT_CMD_GET_PARAM && status == NO_ERROR) {
628 uint32_t size = (replySize == NULL) ? 0 : *replySize;
629 for (size_t i = 1; i < mHandles.size(); i++) {
630 EffectHandle *h = mHandles[i];
631 if (h != NULL && !h->destroyed_l()) {
632 h->commandExecuted(cmdCode, cmdSize, pCmdData, size, pReplyData);
633 }
634 }
635 }
636 return status;
637}
638
639status_t AudioFlinger::EffectModule::setEnabled(bool enabled)
640{
641 Mutex::Autolock _l(mLock);
642 return setEnabled_l(enabled);
643}
644
645// must be called with EffectModule::mLock held
646status_t AudioFlinger::EffectModule::setEnabled_l(bool enabled)
647{
648
649 ALOGV("setEnabled %p enabled %d", this, enabled);
650
651 if (enabled != isEnabled()) {
652 status_t status = AudioSystem::setEffectEnabled(mId, enabled);
653 if (enabled && status != NO_ERROR) {
654 return status;
655 }
656
657 switch (mState) {
658 // going from disabled to enabled
659 case IDLE:
660 mState = STARTING;
661 break;
662 case STOPPED:
663 mState = RESTART;
664 break;
665 case STOPPING:
666 mState = ACTIVE;
667 break;
668
669 // going from enabled to disabled
670 case RESTART:
671 mState = STOPPED;
672 break;
673 case STARTING:
674 mState = IDLE;
675 break;
676 case ACTIVE:
677 mState = STOPPING;
678 break;
679 case DESTROYED:
680 return NO_ERROR; // simply ignore as we are being destroyed
681 }
682 for (size_t i = 1; i < mHandles.size(); i++) {
683 EffectHandle *h = mHandles[i];
684 if (h != NULL && !h->destroyed_l()) {
685 h->setEnabled(enabled);
686 }
687 }
688 }
689 return NO_ERROR;
690}
691
692bool AudioFlinger::EffectModule::isEnabled() const
693{
694 switch (mState) {
695 case RESTART:
696 case STARTING:
697 case ACTIVE:
698 return true;
699 case IDLE:
700 case STOPPING:
701 case STOPPED:
702 case DESTROYED:
703 default:
704 return false;
705 }
706}
707
708bool AudioFlinger::EffectModule::isProcessEnabled() const
709{
Eric Laurentd0ebb532013-04-02 16:41:41 -0700710 if (mStatus != NO_ERROR) {
711 return false;
712 }
713
Eric Laurentca7cc822012-11-19 14:55:58 -0800714 switch (mState) {
715 case RESTART:
716 case ACTIVE:
717 case STOPPING:
718 case STOPPED:
719 return true;
720 case IDLE:
721 case STARTING:
722 case DESTROYED:
723 default:
724 return false;
725 }
726}
727
728status_t AudioFlinger::EffectModule::setVolume(uint32_t *left, uint32_t *right, bool controller)
729{
730 Mutex::Autolock _l(mLock);
Eric Laurentd0ebb532013-04-02 16:41:41 -0700731 if (mStatus != NO_ERROR) {
732 return mStatus;
733 }
Eric Laurentca7cc822012-11-19 14:55:58 -0800734 status_t status = NO_ERROR;
Eric Laurentca7cc822012-11-19 14:55:58 -0800735 // Send volume indication if EFFECT_FLAG_VOLUME_IND is set and read back altered volume
736 // if controller flag is set (Note that controller == TRUE => EFFECT_FLAG_VOLUME_CTRL set)
737 if (isProcessEnabled() &&
738 ((mDescriptor.flags & EFFECT_FLAG_VOLUME_MASK) == EFFECT_FLAG_VOLUME_CTRL ||
739 (mDescriptor.flags & EFFECT_FLAG_VOLUME_MASK) == EFFECT_FLAG_VOLUME_IND)) {
Eric Laurentca7cc822012-11-19 14:55:58 -0800740 uint32_t volume[2];
741 uint32_t *pVolume = NULL;
742 uint32_t size = sizeof(volume);
743 volume[0] = *left;
744 volume[1] = *right;
745 if (controller) {
746 pVolume = volume;
747 }
Mikhail Naganov4a3d5c22016-08-15 13:47:42 -0700748 status = mEffectInterface->command(EFFECT_CMD_SET_VOLUME,
749 size,
750 volume,
751 &size,
752 pVolume);
Eric Laurentca7cc822012-11-19 14:55:58 -0800753 if (controller && status == NO_ERROR && size == sizeof(volume)) {
754 *left = volume[0];
755 *right = volume[1];
756 }
757 }
758 return status;
759}
760
761status_t AudioFlinger::EffectModule::setDevice(audio_devices_t device)
762{
763 if (device == AUDIO_DEVICE_NONE) {
764 return NO_ERROR;
765 }
766
767 Mutex::Autolock _l(mLock);
Eric Laurentd0ebb532013-04-02 16:41:41 -0700768 if (mStatus != NO_ERROR) {
769 return mStatus;
770 }
Eric Laurentca7cc822012-11-19 14:55:58 -0800771 status_t status = NO_ERROR;
Eric Laurent7e1139c2013-06-06 18:29:01 -0700772 if ((mDescriptor.flags & EFFECT_FLAG_DEVICE_MASK) == EFFECT_FLAG_DEVICE_IND) {
Eric Laurentca7cc822012-11-19 14:55:58 -0800773 status_t cmdStatus;
774 uint32_t size = sizeof(status_t);
775 uint32_t cmd = audio_is_output_devices(device) ? EFFECT_CMD_SET_DEVICE :
776 EFFECT_CMD_SET_INPUT_DEVICE;
Mikhail Naganov4a3d5c22016-08-15 13:47:42 -0700777 status = mEffectInterface->command(cmd,
778 sizeof(uint32_t),
779 &device,
780 &size,
781 &cmdStatus);
Eric Laurentca7cc822012-11-19 14:55:58 -0800782 }
783 return status;
784}
785
786status_t AudioFlinger::EffectModule::setMode(audio_mode_t mode)
787{
788 Mutex::Autolock _l(mLock);
Eric Laurentd0ebb532013-04-02 16:41:41 -0700789 if (mStatus != NO_ERROR) {
790 return mStatus;
791 }
Eric Laurentca7cc822012-11-19 14:55:58 -0800792 status_t status = NO_ERROR;
793 if ((mDescriptor.flags & EFFECT_FLAG_AUDIO_MODE_MASK) == EFFECT_FLAG_AUDIO_MODE_IND) {
794 status_t cmdStatus;
795 uint32_t size = sizeof(status_t);
Mikhail Naganov4a3d5c22016-08-15 13:47:42 -0700796 status = mEffectInterface->command(EFFECT_CMD_SET_AUDIO_MODE,
797 sizeof(audio_mode_t),
798 &mode,
799 &size,
800 &cmdStatus);
Eric Laurentca7cc822012-11-19 14:55:58 -0800801 if (status == NO_ERROR) {
802 status = cmdStatus;
803 }
804 }
805 return status;
806}
807
808status_t AudioFlinger::EffectModule::setAudioSource(audio_source_t source)
809{
810 Mutex::Autolock _l(mLock);
Eric Laurentd0ebb532013-04-02 16:41:41 -0700811 if (mStatus != NO_ERROR) {
812 return mStatus;
813 }
Eric Laurentca7cc822012-11-19 14:55:58 -0800814 status_t status = NO_ERROR;
815 if ((mDescriptor.flags & EFFECT_FLAG_AUDIO_SOURCE_MASK) == EFFECT_FLAG_AUDIO_SOURCE_IND) {
816 uint32_t size = 0;
Mikhail Naganov4a3d5c22016-08-15 13:47:42 -0700817 status = mEffectInterface->command(EFFECT_CMD_SET_AUDIO_SOURCE,
818 sizeof(audio_source_t),
819 &source,
820 &size,
821 NULL);
Eric Laurentca7cc822012-11-19 14:55:58 -0800822 }
823 return status;
824}
825
826void AudioFlinger::EffectModule::setSuspended(bool suspended)
827{
828 Mutex::Autolock _l(mLock);
829 mSuspended = suspended;
830}
831
832bool AudioFlinger::EffectModule::suspended() const
833{
834 Mutex::Autolock _l(mLock);
835 return mSuspended;
836}
837
838bool AudioFlinger::EffectModule::purgeHandles()
839{
840 bool enabled = false;
841 Mutex::Autolock _l(mLock);
842 for (size_t i = 0; i < mHandles.size(); i++) {
843 EffectHandle *handle = mHandles[i];
844 if (handle != NULL && !handle->destroyed_l()) {
845 handle->effect().clear();
846 if (handle->hasControl()) {
847 enabled = handle->enabled();
848 }
849 }
850 }
851 return enabled;
852}
853
Eric Laurent5baf2af2013-09-12 17:37:00 -0700854status_t AudioFlinger::EffectModule::setOffloaded(bool offloaded, audio_io_handle_t io)
855{
856 Mutex::Autolock _l(mLock);
857 if (mStatus != NO_ERROR) {
858 return mStatus;
859 }
860 status_t status = NO_ERROR;
861 if ((mDescriptor.flags & EFFECT_FLAG_OFFLOAD_SUPPORTED) != 0) {
862 status_t cmdStatus;
863 uint32_t size = sizeof(status_t);
864 effect_offload_param_t cmd;
865
866 cmd.isOffload = offloaded;
867 cmd.ioHandle = io;
Mikhail Naganov4a3d5c22016-08-15 13:47:42 -0700868 status = mEffectInterface->command(EFFECT_CMD_OFFLOAD,
869 sizeof(effect_offload_param_t),
870 &cmd,
871 &size,
872 &cmdStatus);
Eric Laurent5baf2af2013-09-12 17:37:00 -0700873 if (status == NO_ERROR) {
874 status = cmdStatus;
875 }
876 mOffloaded = (status == NO_ERROR) ? offloaded : false;
877 } else {
878 if (offloaded) {
879 status = INVALID_OPERATION;
880 }
881 mOffloaded = false;
882 }
883 ALOGV("setOffloaded() offloaded %d io %d status %d", offloaded, io, status);
884 return status;
885}
886
887bool AudioFlinger::EffectModule::isOffloaded() const
888{
889 Mutex::Autolock _l(mLock);
890 return mOffloaded;
891}
892
Marco Nelissenb2208842014-02-07 14:00:50 -0800893String8 effectFlagsToString(uint32_t flags) {
894 String8 s;
895
896 s.append("conn. mode: ");
897 switch (flags & EFFECT_FLAG_TYPE_MASK) {
898 case EFFECT_FLAG_TYPE_INSERT: s.append("insert"); break;
899 case EFFECT_FLAG_TYPE_AUXILIARY: s.append("auxiliary"); break;
900 case EFFECT_FLAG_TYPE_REPLACE: s.append("replace"); break;
901 case EFFECT_FLAG_TYPE_PRE_PROC: s.append("preproc"); break;
902 case EFFECT_FLAG_TYPE_POST_PROC: s.append("postproc"); break;
903 default: s.append("unknown/reserved"); break;
904 }
905 s.append(", ");
906
907 s.append("insert pref: ");
908 switch (flags & EFFECT_FLAG_INSERT_MASK) {
909 case EFFECT_FLAG_INSERT_ANY: s.append("any"); break;
910 case EFFECT_FLAG_INSERT_FIRST: s.append("first"); break;
911 case EFFECT_FLAG_INSERT_LAST: s.append("last"); break;
912 case EFFECT_FLAG_INSERT_EXCLUSIVE: s.append("exclusive"); break;
913 default: s.append("unknown/reserved"); break;
914 }
915 s.append(", ");
916
917 s.append("volume mgmt: ");
918 switch (flags & EFFECT_FLAG_VOLUME_MASK) {
919 case EFFECT_FLAG_VOLUME_NONE: s.append("none"); break;
920 case EFFECT_FLAG_VOLUME_CTRL: s.append("implements control"); break;
921 case EFFECT_FLAG_VOLUME_IND: s.append("requires indication"); break;
922 default: s.append("unknown/reserved"); break;
923 }
924 s.append(", ");
925
926 uint32_t devind = flags & EFFECT_FLAG_DEVICE_MASK;
927 if (devind) {
928 s.append("device indication: ");
929 switch (devind) {
930 case EFFECT_FLAG_DEVICE_IND: s.append("requires updates"); break;
931 default: s.append("unknown/reserved"); break;
932 }
933 s.append(", ");
934 }
935
936 s.append("input mode: ");
937 switch (flags & EFFECT_FLAG_INPUT_MASK) {
938 case EFFECT_FLAG_INPUT_DIRECT: s.append("direct"); break;
939 case EFFECT_FLAG_INPUT_PROVIDER: s.append("provider"); break;
940 case EFFECT_FLAG_INPUT_BOTH: s.append("direct+provider"); break;
941 default: s.append("not set"); break;
942 }
943 s.append(", ");
944
945 s.append("output mode: ");
946 switch (flags & EFFECT_FLAG_OUTPUT_MASK) {
947 case EFFECT_FLAG_OUTPUT_DIRECT: s.append("direct"); break;
948 case EFFECT_FLAG_OUTPUT_PROVIDER: s.append("provider"); break;
949 case EFFECT_FLAG_OUTPUT_BOTH: s.append("direct+provider"); break;
950 default: s.append("not set"); break;
951 }
952 s.append(", ");
953
954 uint32_t accel = flags & EFFECT_FLAG_HW_ACC_MASK;
955 if (accel) {
956 s.append("hardware acceleration: ");
957 switch (accel) {
958 case EFFECT_FLAG_HW_ACC_SIMPLE: s.append("non-tunneled"); break;
959 case EFFECT_FLAG_HW_ACC_TUNNEL: s.append("tunneled"); break;
960 default: s.append("unknown/reserved"); break;
961 }
962 s.append(", ");
963 }
964
965 uint32_t modeind = flags & EFFECT_FLAG_AUDIO_MODE_MASK;
966 if (modeind) {
967 s.append("mode indication: ");
968 switch (modeind) {
969 case EFFECT_FLAG_AUDIO_MODE_IND: s.append("required"); break;
970 default: s.append("unknown/reserved"); break;
971 }
972 s.append(", ");
973 }
974
975 uint32_t srcind = flags & EFFECT_FLAG_AUDIO_SOURCE_MASK;
976 if (srcind) {
977 s.append("source indication: ");
978 switch (srcind) {
979 case EFFECT_FLAG_AUDIO_SOURCE_IND: s.append("required"); break;
980 default: s.append("unknown/reserved"); break;
981 }
982 s.append(", ");
983 }
984
985 if (flags & EFFECT_FLAG_OFFLOAD_MASK) {
986 s.append("offloadable, ");
987 }
988
989 int len = s.length();
990 if (s.length() > 2) {
Glenn Kasten57c4e6f2016-03-18 14:54:07 -0700991 (void) s.lockBuffer(len);
Marco Nelissenb2208842014-02-07 14:00:50 -0800992 s.unlockBuffer(len - 2);
993 }
994 return s;
995}
996
997
Glenn Kasten0f11b512014-01-31 16:18:54 -0800998void AudioFlinger::EffectModule::dump(int fd, const Vector<String16>& args __unused)
Eric Laurentca7cc822012-11-19 14:55:58 -0800999{
1000 const size_t SIZE = 256;
1001 char buffer[SIZE];
1002 String8 result;
1003
1004 snprintf(buffer, SIZE, "\tEffect ID %d:\n", mId);
1005 result.append(buffer);
1006
1007 bool locked = AudioFlinger::dumpTryLock(mLock);
1008 // failed to lock - AudioFlinger is probably deadlocked
1009 if (!locked) {
1010 result.append("\t\tCould not lock Fx mutex:\n");
1011 }
1012
1013 result.append("\t\tSession Status State Engine:\n");
Kévin PETIT377b2ec2014-02-03 12:35:36 +00001014 snprintf(buffer, SIZE, "\t\t%05d %03d %03d %p\n",
Mikhail Naganov4a3d5c22016-08-15 13:47:42 -07001015 mSessionId, mStatus, mState, mEffectInterface.get());
Eric Laurentca7cc822012-11-19 14:55:58 -08001016 result.append(buffer);
1017
1018 result.append("\t\tDescriptor:\n");
1019 snprintf(buffer, SIZE, "\t\t- UUID: %08X-%04X-%04X-%04X-%02X%02X%02X%02X%02X%02X\n",
1020 mDescriptor.uuid.timeLow, mDescriptor.uuid.timeMid, mDescriptor.uuid.timeHiAndVersion,
1021 mDescriptor.uuid.clockSeq, mDescriptor.uuid.node[0], mDescriptor.uuid.node[1],
1022 mDescriptor.uuid.node[2],
1023 mDescriptor.uuid.node[3],mDescriptor.uuid.node[4],mDescriptor.uuid.node[5]);
1024 result.append(buffer);
1025 snprintf(buffer, SIZE, "\t\t- TYPE: %08X-%04X-%04X-%04X-%02X%02X%02X%02X%02X%02X\n",
1026 mDescriptor.type.timeLow, mDescriptor.type.timeMid,
1027 mDescriptor.type.timeHiAndVersion,
1028 mDescriptor.type.clockSeq, mDescriptor.type.node[0], mDescriptor.type.node[1],
1029 mDescriptor.type.node[2],
1030 mDescriptor.type.node[3],mDescriptor.type.node[4],mDescriptor.type.node[5]);
1031 result.append(buffer);
Marco Nelissenb2208842014-02-07 14:00:50 -08001032 snprintf(buffer, SIZE, "\t\t- apiVersion: %08X\n\t\t- flags: %08X (%s)\n",
Eric Laurentca7cc822012-11-19 14:55:58 -08001033 mDescriptor.apiVersion,
Marco Nelissenb2208842014-02-07 14:00:50 -08001034 mDescriptor.flags,
1035 effectFlagsToString(mDescriptor.flags).string());
Eric Laurentca7cc822012-11-19 14:55:58 -08001036 result.append(buffer);
1037 snprintf(buffer, SIZE, "\t\t- name: %s\n",
1038 mDescriptor.name);
1039 result.append(buffer);
1040 snprintf(buffer, SIZE, "\t\t- implementor: %s\n",
1041 mDescriptor.implementor);
1042 result.append(buffer);
1043
1044 result.append("\t\t- Input configuration:\n");
Kévin PETIT377b2ec2014-02-03 12:35:36 +00001045 result.append("\t\t\tFrames Smp rate Channels Format Buffer\n");
Narayan Kamath1d6fa7a2014-02-11 13:47:53 +00001046 snprintf(buffer, SIZE, "\t\t\t%05zu %05d %08x %6d (%s) %p\n",
Eric Laurentca7cc822012-11-19 14:55:58 -08001047 mConfig.inputCfg.buffer.frameCount,
1048 mConfig.inputCfg.samplingRate,
1049 mConfig.inputCfg.channels,
Marco Nelissenb2208842014-02-07 14:00:50 -08001050 mConfig.inputCfg.format,
Narayan Kamath1d6fa7a2014-02-11 13:47:53 +00001051 formatToString((audio_format_t)mConfig.inputCfg.format),
Kévin PETIT377b2ec2014-02-03 12:35:36 +00001052 mConfig.inputCfg.buffer.raw);
Eric Laurentca7cc822012-11-19 14:55:58 -08001053 result.append(buffer);
1054
1055 result.append("\t\t- Output configuration:\n");
1056 result.append("\t\t\tBuffer Frames Smp rate Channels Format\n");
Narayan Kamath1d6fa7a2014-02-11 13:47:53 +00001057 snprintf(buffer, SIZE, "\t\t\t%p %05zu %05d %08x %d (%s)\n",
Kévin PETIT377b2ec2014-02-03 12:35:36 +00001058 mConfig.outputCfg.buffer.raw,
Eric Laurentca7cc822012-11-19 14:55:58 -08001059 mConfig.outputCfg.buffer.frameCount,
1060 mConfig.outputCfg.samplingRate,
1061 mConfig.outputCfg.channels,
Marco Nelissenb2208842014-02-07 14:00:50 -08001062 mConfig.outputCfg.format,
1063 formatToString((audio_format_t)mConfig.outputCfg.format));
Eric Laurentca7cc822012-11-19 14:55:58 -08001064 result.append(buffer);
1065
Kévin PETIT377b2ec2014-02-03 12:35:36 +00001066 snprintf(buffer, SIZE, "\t\t%zu Clients:\n", mHandles.size());
Eric Laurentca7cc822012-11-19 14:55:58 -08001067 result.append(buffer);
Marco Nelissenb2208842014-02-07 14:00:50 -08001068 result.append("\t\t\t Pid Priority Ctrl Locked client server\n");
Eric Laurentca7cc822012-11-19 14:55:58 -08001069 for (size_t i = 0; i < mHandles.size(); ++i) {
1070 EffectHandle *handle = mHandles[i];
1071 if (handle != NULL && !handle->destroyed_l()) {
Glenn Kasten01d3acb2014-02-06 08:24:07 -08001072 handle->dumpToBuffer(buffer, SIZE);
Eric Laurentca7cc822012-11-19 14:55:58 -08001073 result.append(buffer);
1074 }
1075 }
1076
Eric Laurentca7cc822012-11-19 14:55:58 -08001077 write(fd, result.string(), result.length());
1078
1079 if (locked) {
1080 mLock.unlock();
1081 }
1082}
1083
1084// ----------------------------------------------------------------------------
1085// EffectHandle implementation
1086// ----------------------------------------------------------------------------
1087
1088#undef LOG_TAG
1089#define LOG_TAG "AudioFlinger::EffectHandle"
1090
1091AudioFlinger::EffectHandle::EffectHandle(const sp<EffectModule>& effect,
1092 const sp<AudioFlinger::Client>& client,
1093 const sp<IEffectClient>& effectClient,
1094 int32_t priority)
1095 : BnEffect(),
1096 mEffect(effect), mEffectClient(effectClient), mClient(client), mCblk(NULL),
1097 mPriority(priority), mHasControl(false), mEnabled(false), mDestroyed(false)
1098{
1099 ALOGV("constructor %p", this);
1100
1101 if (client == 0) {
1102 return;
1103 }
1104 int bufOffset = ((sizeof(effect_param_cblk_t) - 1) / sizeof(int) + 1) * sizeof(int);
1105 mCblkMemory = client->heap()->allocate(EFFECT_PARAM_BUFFER_SIZE + bufOffset);
Glenn Kastene75da402013-11-20 13:54:52 -08001106 if (mCblkMemory == 0 ||
1107 (mCblk = static_cast<effect_param_cblk_t *>(mCblkMemory->pointer())) == NULL) {
Glenn Kastenc42e9b42016-03-21 11:35:03 -07001108 ALOGE("not enough memory for Effect size=%zu", EFFECT_PARAM_BUFFER_SIZE +
Eric Laurentca7cc822012-11-19 14:55:58 -08001109 sizeof(effect_param_cblk_t));
Glenn Kastene75da402013-11-20 13:54:52 -08001110 mCblkMemory.clear();
Eric Laurentca7cc822012-11-19 14:55:58 -08001111 return;
1112 }
Glenn Kastene75da402013-11-20 13:54:52 -08001113 new(mCblk) effect_param_cblk_t();
1114 mBuffer = (uint8_t *)mCblk + bufOffset;
Eric Laurentca7cc822012-11-19 14:55:58 -08001115}
1116
1117AudioFlinger::EffectHandle::~EffectHandle()
1118{
1119 ALOGV("Destructor %p", this);
1120
1121 if (mEffect == 0) {
1122 mDestroyed = true;
1123 return;
1124 }
1125 mEffect->lock();
1126 mDestroyed = true;
1127 mEffect->unlock();
1128 disconnect(false);
1129}
1130
Glenn Kastene75da402013-11-20 13:54:52 -08001131status_t AudioFlinger::EffectHandle::initCheck()
1132{
1133 return mClient == 0 || mCblkMemory != 0 ? OK : NO_MEMORY;
1134}
1135
Eric Laurentca7cc822012-11-19 14:55:58 -08001136status_t AudioFlinger::EffectHandle::enable()
1137{
1138 ALOGV("enable %p", this);
1139 if (!mHasControl) {
1140 return INVALID_OPERATION;
1141 }
1142 if (mEffect == 0) {
1143 return DEAD_OBJECT;
1144 }
1145
1146 if (mEnabled) {
1147 return NO_ERROR;
1148 }
1149
1150 mEnabled = true;
1151
1152 sp<ThreadBase> thread = mEffect->thread().promote();
1153 if (thread != 0) {
1154 thread->checkSuspendOnEffectEnabled(mEffect, true, mEffect->sessionId());
1155 }
1156
1157 // checkSuspendOnEffectEnabled() can suspend this same effect when enabled
1158 if (mEffect->suspended()) {
1159 return NO_ERROR;
1160 }
1161
1162 status_t status = mEffect->setEnabled(true);
1163 if (status != NO_ERROR) {
1164 if (thread != 0) {
1165 thread->checkSuspendOnEffectEnabled(mEffect, false, mEffect->sessionId());
1166 }
1167 mEnabled = false;
Eric Laurent813e2a72013-08-31 12:59:48 -07001168 } else {
Eric Laurent59fe0102013-09-27 18:48:26 -07001169 if (thread != 0) {
1170 if (thread->type() == ThreadBase::OFFLOAD) {
Eric Laurent813e2a72013-08-31 12:59:48 -07001171 PlaybackThread *t = (PlaybackThread *)thread.get();
Eric Laurent59fe0102013-09-27 18:48:26 -07001172 Mutex::Autolock _l(t->mLock);
1173 t->broadcast_l();
Eric Laurent813e2a72013-08-31 12:59:48 -07001174 }
Eric Laurent59fe0102013-09-27 18:48:26 -07001175 if (!mEffect->isOffloadable()) {
1176 if (thread->type() == ThreadBase::OFFLOAD) {
1177 PlaybackThread *t = (PlaybackThread *)thread.get();
1178 t->invalidateTracks(AUDIO_STREAM_MUSIC);
1179 }
1180 if (mEffect->sessionId() == AUDIO_SESSION_OUTPUT_MIX) {
1181 thread->mAudioFlinger->onNonOffloadableGlobalEffectEnable();
1182 }
Eric Laurent813e2a72013-08-31 12:59:48 -07001183 }
1184 }
Eric Laurentca7cc822012-11-19 14:55:58 -08001185 }
1186 return status;
1187}
1188
1189status_t AudioFlinger::EffectHandle::disable()
1190{
1191 ALOGV("disable %p", this);
1192 if (!mHasControl) {
1193 return INVALID_OPERATION;
1194 }
1195 if (mEffect == 0) {
1196 return DEAD_OBJECT;
1197 }
1198
1199 if (!mEnabled) {
1200 return NO_ERROR;
1201 }
1202 mEnabled = false;
1203
1204 if (mEffect->suspended()) {
1205 return NO_ERROR;
1206 }
1207
1208 status_t status = mEffect->setEnabled(false);
1209
1210 sp<ThreadBase> thread = mEffect->thread().promote();
1211 if (thread != 0) {
1212 thread->checkSuspendOnEffectEnabled(mEffect, false, mEffect->sessionId());
Eric Laurent59fe0102013-09-27 18:48:26 -07001213 if (thread->type() == ThreadBase::OFFLOAD) {
1214 PlaybackThread *t = (PlaybackThread *)thread.get();
1215 Mutex::Autolock _l(t->mLock);
1216 t->broadcast_l();
1217 }
Eric Laurentca7cc822012-11-19 14:55:58 -08001218 }
1219
1220 return status;
1221}
1222
1223void AudioFlinger::EffectHandle::disconnect()
1224{
1225 disconnect(true);
1226}
1227
1228void AudioFlinger::EffectHandle::disconnect(bool unpinIfLast)
1229{
1230 ALOGV("disconnect(%s)", unpinIfLast ? "true" : "false");
1231 if (mEffect == 0) {
1232 return;
1233 }
1234 // restore suspended effects if the disconnected handle was enabled and the last one.
1235 if ((mEffect->disconnect(this, unpinIfLast) == 0) && mEnabled) {
1236 sp<ThreadBase> thread = mEffect->thread().promote();
1237 if (thread != 0) {
1238 thread->checkSuspendOnEffectEnabled(mEffect, false, mEffect->sessionId());
1239 }
1240 }
1241
1242 // release sp on module => module destructor can be called now
1243 mEffect.clear();
1244 if (mClient != 0) {
1245 if (mCblk != NULL) {
1246 // unlike ~TrackBase(), mCblk is never a local new, so don't delete
1247 mCblk->~effect_param_cblk_t(); // destroy our shared-structure.
1248 }
1249 mCblkMemory.clear(); // free the shared memory before releasing the heap it belongs to
Eric Laurent021cf962014-05-13 10:18:14 -07001250 // Client destructor must run with AudioFlinger client mutex locked
1251 Mutex::Autolock _l(mClient->audioFlinger()->mClientLock);
Eric Laurentca7cc822012-11-19 14:55:58 -08001252 mClient.clear();
1253 }
1254}
1255
1256status_t AudioFlinger::EffectHandle::command(uint32_t cmdCode,
1257 uint32_t cmdSize,
1258 void *pCmdData,
1259 uint32_t *replySize,
1260 void *pReplyData)
1261{
1262 ALOGVV("command(), cmdCode: %d, mHasControl: %d, mEffect: %p",
1263 cmdCode, mHasControl, (mEffect == 0) ? 0 : mEffect.get());
1264
1265 // only get parameter command is permitted for applications not controlling the effect
1266 if (!mHasControl && cmdCode != EFFECT_CMD_GET_PARAM) {
1267 return INVALID_OPERATION;
1268 }
1269 if (mEffect == 0) {
1270 return DEAD_OBJECT;
1271 }
1272 if (mClient == 0) {
1273 return INVALID_OPERATION;
1274 }
1275
1276 // handle commands that are not forwarded transparently to effect engine
1277 if (cmdCode == EFFECT_CMD_SET_PARAM_COMMIT) {
1278 // No need to trylock() here as this function is executed in the binder thread serving a
1279 // particular client process: no risk to block the whole media server process or mixer
1280 // threads if we are stuck here
1281 Mutex::Autolock _l(mCblk->lock);
1282 if (mCblk->clientIndex > EFFECT_PARAM_BUFFER_SIZE ||
1283 mCblk->serverIndex > EFFECT_PARAM_BUFFER_SIZE) {
1284 mCblk->serverIndex = 0;
1285 mCblk->clientIndex = 0;
1286 return BAD_VALUE;
1287 }
1288 status_t status = NO_ERROR;
1289 while (mCblk->serverIndex < mCblk->clientIndex) {
1290 int reply;
1291 uint32_t rsize = sizeof(int);
1292 int *p = (int *)(mBuffer + mCblk->serverIndex);
1293 int size = *p++;
1294 if (((uint8_t *)p + size) > mBuffer + mCblk->clientIndex) {
1295 ALOGW("command(): invalid parameter block size");
1296 break;
1297 }
1298 effect_param_t *param = (effect_param_t *)p;
1299 if (param->psize == 0 || param->vsize == 0) {
1300 ALOGW("command(): null parameter or value size");
1301 mCblk->serverIndex += size;
1302 continue;
1303 }
1304 uint32_t psize = sizeof(effect_param_t) +
1305 ((param->psize - 1) / sizeof(int) + 1) * sizeof(int) +
1306 param->vsize;
1307 status_t ret = mEffect->command(EFFECT_CMD_SET_PARAM,
1308 psize,
1309 p,
1310 &rsize,
1311 &reply);
1312 // stop at first error encountered
1313 if (ret != NO_ERROR) {
1314 status = ret;
1315 *(int *)pReplyData = reply;
1316 break;
1317 } else if (reply != NO_ERROR) {
1318 *(int *)pReplyData = reply;
1319 break;
1320 }
1321 mCblk->serverIndex += size;
1322 }
1323 mCblk->serverIndex = 0;
1324 mCblk->clientIndex = 0;
1325 return status;
1326 } else if (cmdCode == EFFECT_CMD_ENABLE) {
1327 *(int *)pReplyData = NO_ERROR;
1328 return enable();
1329 } else if (cmdCode == EFFECT_CMD_DISABLE) {
1330 *(int *)pReplyData = NO_ERROR;
1331 return disable();
1332 }
1333
1334 return mEffect->command(cmdCode, cmdSize, pCmdData, replySize, pReplyData);
1335}
1336
1337void AudioFlinger::EffectHandle::setControl(bool hasControl, bool signal, bool enabled)
1338{
1339 ALOGV("setControl %p control %d", this, hasControl);
1340
1341 mHasControl = hasControl;
1342 mEnabled = enabled;
1343
1344 if (signal && mEffectClient != 0) {
1345 mEffectClient->controlStatusChanged(hasControl);
1346 }
1347}
1348
1349void AudioFlinger::EffectHandle::commandExecuted(uint32_t cmdCode,
1350 uint32_t cmdSize,
1351 void *pCmdData,
1352 uint32_t replySize,
1353 void *pReplyData)
1354{
1355 if (mEffectClient != 0) {
1356 mEffectClient->commandExecuted(cmdCode, cmdSize, pCmdData, replySize, pReplyData);
1357 }
1358}
1359
1360
1361
1362void AudioFlinger::EffectHandle::setEnabled(bool enabled)
1363{
1364 if (mEffectClient != 0) {
1365 mEffectClient->enableStatusChanged(enabled);
1366 }
1367}
1368
1369status_t AudioFlinger::EffectHandle::onTransact(
1370 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
1371{
1372 return BnEffect::onTransact(code, data, reply, flags);
1373}
1374
1375
Glenn Kasten01d3acb2014-02-06 08:24:07 -08001376void AudioFlinger::EffectHandle::dumpToBuffer(char* buffer, size_t size)
Eric Laurentca7cc822012-11-19 14:55:58 -08001377{
1378 bool locked = mCblk != NULL && AudioFlinger::dumpTryLock(mCblk->lock);
1379
Marco Nelissenb2208842014-02-07 14:00:50 -08001380 snprintf(buffer, size, "\t\t\t%5d %5d %3s %3s %5u %5u\n",
Eric Laurentca7cc822012-11-19 14:55:58 -08001381 (mClient == 0) ? getpid_cached : mClient->pid(),
1382 mPriority,
Marco Nelissenb2208842014-02-07 14:00:50 -08001383 mHasControl ? "yes" : "no",
1384 locked ? "yes" : "no",
Eric Laurentca7cc822012-11-19 14:55:58 -08001385 mCblk ? mCblk->clientIndex : 0,
1386 mCblk ? mCblk->serverIndex : 0
1387 );
1388
1389 if (locked) {
1390 mCblk->lock.unlock();
1391 }
1392}
1393
1394#undef LOG_TAG
1395#define LOG_TAG "AudioFlinger::EffectChain"
1396
1397AudioFlinger::EffectChain::EffectChain(ThreadBase *thread,
Glenn Kastend848eb42016-03-08 13:42:11 -08001398 audio_session_t sessionId)
Eric Laurentca7cc822012-11-19 14:55:58 -08001399 : mThread(thread), mSessionId(sessionId), mActiveTrackCnt(0), mTrackCnt(0), mTailBufferCount(0),
1400 mOwnInBuffer(false), mVolumeCtrlIdx(-1), mLeftVolume(UINT_MAX), mRightVolume(UINT_MAX),
Eric Laurentfa1e1232016-08-02 19:01:49 -07001401 mNewLeftVolume(UINT_MAX), mNewRightVolume(UINT_MAX)
Eric Laurentca7cc822012-11-19 14:55:58 -08001402{
1403 mStrategy = AudioSystem::getStrategyForStream(AUDIO_STREAM_MUSIC);
1404 if (thread == NULL) {
1405 return;
1406 }
1407 mMaxTailBuffers = ((kProcessTailDurationMs * thread->sampleRate()) / 1000) /
1408 thread->frameCount();
1409}
1410
1411AudioFlinger::EffectChain::~EffectChain()
1412{
1413 if (mOwnInBuffer) {
1414 delete mInBuffer;
1415 }
1416
1417}
1418
1419// getEffectFromDesc_l() must be called with ThreadBase::mLock held
1420sp<AudioFlinger::EffectModule> AudioFlinger::EffectChain::getEffectFromDesc_l(
1421 effect_descriptor_t *descriptor)
1422{
1423 size_t size = mEffects.size();
1424
1425 for (size_t i = 0; i < size; i++) {
1426 if (memcmp(&mEffects[i]->desc().uuid, &descriptor->uuid, sizeof(effect_uuid_t)) == 0) {
1427 return mEffects[i];
1428 }
1429 }
1430 return 0;
1431}
1432
1433// getEffectFromId_l() must be called with ThreadBase::mLock held
1434sp<AudioFlinger::EffectModule> AudioFlinger::EffectChain::getEffectFromId_l(int id)
1435{
1436 size_t size = mEffects.size();
1437
1438 for (size_t i = 0; i < size; i++) {
1439 // by convention, return first effect if id provided is 0 (0 is never a valid id)
1440 if (id == 0 || mEffects[i]->id() == id) {
1441 return mEffects[i];
1442 }
1443 }
1444 return 0;
1445}
1446
1447// getEffectFromType_l() must be called with ThreadBase::mLock held
1448sp<AudioFlinger::EffectModule> AudioFlinger::EffectChain::getEffectFromType_l(
1449 const effect_uuid_t *type)
1450{
1451 size_t size = mEffects.size();
1452
1453 for (size_t i = 0; i < size; i++) {
1454 if (memcmp(&mEffects[i]->desc().type, type, sizeof(effect_uuid_t)) == 0) {
1455 return mEffects[i];
1456 }
1457 }
1458 return 0;
1459}
1460
1461void AudioFlinger::EffectChain::clearInputBuffer()
1462{
1463 Mutex::Autolock _l(mLock);
1464 sp<ThreadBase> thread = mThread.promote();
1465 if (thread == 0) {
1466 ALOGW("clearInputBuffer(): cannot promote mixer thread");
1467 return;
1468 }
1469 clearInputBuffer_l(thread);
1470}
1471
1472// Must be called with EffectChain::mLock locked
Chih-Hung Hsieh36d0ca12016-08-09 14:31:32 -07001473void AudioFlinger::EffectChain::clearInputBuffer_l(const sp<ThreadBase>& thread)
Eric Laurentca7cc822012-11-19 14:55:58 -08001474{
Ricardo Garcia322bab22014-08-06 11:43:46 -07001475 // TODO: This will change in the future, depending on multichannel
1476 // and sample format changes for effects.
1477 // Currently effects processing is only available for stereo, AUDIO_FORMAT_PCM_16_BIT
1478 // (4 bytes frame size)
Ricardo Garcia726b6a72014-08-11 12:04:54 -07001479 const size_t frameSize =
1480 audio_bytes_per_sample(AUDIO_FORMAT_PCM_16_BIT) * min(FCC_2, thread->channelCount());
Ricardo Garcia322bab22014-08-06 11:43:46 -07001481 memset(mInBuffer, 0, thread->frameCount() * frameSize);
Eric Laurentca7cc822012-11-19 14:55:58 -08001482}
1483
1484// Must be called with EffectChain::mLock locked
1485void AudioFlinger::EffectChain::process_l()
1486{
1487 sp<ThreadBase> thread = mThread.promote();
1488 if (thread == 0) {
1489 ALOGW("process_l(): cannot promote mixer thread");
1490 return;
1491 }
1492 bool isGlobalSession = (mSessionId == AUDIO_SESSION_OUTPUT_MIX) ||
1493 (mSessionId == AUDIO_SESSION_OUTPUT_STAGE);
Jean-Michel Trivifed62922013-09-25 18:50:33 -07001494 // never process effects when:
1495 // - on an OFFLOAD thread
1496 // - no more tracks are on the session and the effect tail has been rendered
1497 bool doProcess = (thread->type() != ThreadBase::OFFLOAD);
Eric Laurentca7cc822012-11-19 14:55:58 -08001498 if (!isGlobalSession) {
1499 bool tracksOnSession = (trackCnt() != 0);
1500
1501 if (!tracksOnSession && mTailBufferCount == 0) {
1502 doProcess = false;
1503 }
1504
1505 if (activeTrackCnt() == 0) {
1506 // if no track is active and the effect tail has not been rendered,
1507 // the input buffer must be cleared here as the mixer process will not do it
1508 if (tracksOnSession || mTailBufferCount > 0) {
1509 clearInputBuffer_l(thread);
1510 if (mTailBufferCount > 0) {
1511 mTailBufferCount--;
1512 }
1513 }
1514 }
1515 }
1516
1517 size_t size = mEffects.size();
1518 if (doProcess) {
1519 for (size_t i = 0; i < size; i++) {
1520 mEffects[i]->process();
1521 }
1522 }
Eric Laurentfa1e1232016-08-02 19:01:49 -07001523 bool doResetVolume = false;
Eric Laurentca7cc822012-11-19 14:55:58 -08001524 for (size_t i = 0; i < size; i++) {
Eric Laurentfa1e1232016-08-02 19:01:49 -07001525 doResetVolume = mEffects[i]->updateState() || doResetVolume;
1526 }
1527 if (doResetVolume) {
1528 resetVolume_l();
Eric Laurentca7cc822012-11-19 14:55:58 -08001529 }
1530}
1531
1532// addEffect_l() must be called with PlaybackThread::mLock held
1533status_t AudioFlinger::EffectChain::addEffect_l(const sp<EffectModule>& effect)
1534{
1535 effect_descriptor_t desc = effect->desc();
1536 uint32_t insertPref = desc.flags & EFFECT_FLAG_INSERT_MASK;
1537
1538 Mutex::Autolock _l(mLock);
1539 effect->setChain(this);
1540 sp<ThreadBase> thread = mThread.promote();
1541 if (thread == 0) {
1542 return NO_INIT;
1543 }
1544 effect->setThread(thread);
1545
1546 if ((desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
1547 // Auxiliary effects are inserted at the beginning of mEffects vector as
1548 // they are processed first and accumulated in chain input buffer
1549 mEffects.insertAt(effect, 0);
1550
1551 // the input buffer for auxiliary effect contains mono samples in
1552 // 32 bit format. This is to avoid saturation in AudoMixer
1553 // accumulation stage. Saturation is done in EffectModule::process() before
1554 // calling the process in effect engine
1555 size_t numSamples = thread->frameCount();
1556 int32_t *buffer = new int32_t[numSamples];
1557 memset(buffer, 0, numSamples * sizeof(int32_t));
1558 effect->setInBuffer((int16_t *)buffer);
1559 // auxiliary effects output samples to chain input buffer for further processing
1560 // by insert effects
1561 effect->setOutBuffer(mInBuffer);
1562 } else {
1563 // Insert effects are inserted at the end of mEffects vector as they are processed
1564 // after track and auxiliary effects.
1565 // Insert effect order as a function of indicated preference:
1566 // if EFFECT_FLAG_INSERT_EXCLUSIVE, insert in first position or reject if
1567 // another effect is present
1568 // else if EFFECT_FLAG_INSERT_FIRST, insert in first position or after the
1569 // last effect claiming first position
1570 // else if EFFECT_FLAG_INSERT_LAST, insert in last position or before the
1571 // first effect claiming last position
1572 // else if EFFECT_FLAG_INSERT_ANY insert after first or before last
1573 // Reject insertion if an effect with EFFECT_FLAG_INSERT_EXCLUSIVE is
1574 // already present
1575
1576 size_t size = mEffects.size();
1577 size_t idx_insert = size;
1578 ssize_t idx_insert_first = -1;
1579 ssize_t idx_insert_last = -1;
1580
1581 for (size_t i = 0; i < size; i++) {
1582 effect_descriptor_t d = mEffects[i]->desc();
1583 uint32_t iMode = d.flags & EFFECT_FLAG_TYPE_MASK;
1584 uint32_t iPref = d.flags & EFFECT_FLAG_INSERT_MASK;
1585 if (iMode == EFFECT_FLAG_TYPE_INSERT) {
1586 // check invalid effect chaining combinations
1587 if (insertPref == EFFECT_FLAG_INSERT_EXCLUSIVE ||
1588 iPref == EFFECT_FLAG_INSERT_EXCLUSIVE) {
1589 ALOGW("addEffect_l() could not insert effect %s: exclusive conflict with %s",
1590 desc.name, d.name);
1591 return INVALID_OPERATION;
1592 }
1593 // remember position of first insert effect and by default
1594 // select this as insert position for new effect
1595 if (idx_insert == size) {
1596 idx_insert = i;
1597 }
1598 // remember position of last insert effect claiming
1599 // first position
1600 if (iPref == EFFECT_FLAG_INSERT_FIRST) {
1601 idx_insert_first = i;
1602 }
1603 // remember position of first insert effect claiming
1604 // last position
1605 if (iPref == EFFECT_FLAG_INSERT_LAST &&
1606 idx_insert_last == -1) {
1607 idx_insert_last = i;
1608 }
1609 }
1610 }
1611
1612 // modify idx_insert from first position if needed
1613 if (insertPref == EFFECT_FLAG_INSERT_LAST) {
1614 if (idx_insert_last != -1) {
1615 idx_insert = idx_insert_last;
1616 } else {
1617 idx_insert = size;
1618 }
1619 } else {
1620 if (idx_insert_first != -1) {
1621 idx_insert = idx_insert_first + 1;
1622 }
1623 }
1624
1625 // always read samples from chain input buffer
1626 effect->setInBuffer(mInBuffer);
1627
1628 // if last effect in the chain, output samples to chain
1629 // output buffer, otherwise to chain input buffer
1630 if (idx_insert == size) {
1631 if (idx_insert != 0) {
1632 mEffects[idx_insert-1]->setOutBuffer(mInBuffer);
1633 mEffects[idx_insert-1]->configure();
1634 }
1635 effect->setOutBuffer(mOutBuffer);
1636 } else {
1637 effect->setOutBuffer(mInBuffer);
1638 }
1639 mEffects.insertAt(effect, idx_insert);
1640
Glenn Kastenc42e9b42016-03-21 11:35:03 -07001641 ALOGV("addEffect_l() effect %p, added in chain %p at rank %zu", effect.get(), this,
Eric Laurentca7cc822012-11-19 14:55:58 -08001642 idx_insert);
1643 }
1644 effect->configure();
1645 return NO_ERROR;
1646}
1647
1648// removeEffect_l() must be called with PlaybackThread::mLock held
1649size_t AudioFlinger::EffectChain::removeEffect_l(const sp<EffectModule>& effect)
1650{
1651 Mutex::Autolock _l(mLock);
1652 size_t size = mEffects.size();
1653 uint32_t type = effect->desc().flags & EFFECT_FLAG_TYPE_MASK;
1654
1655 for (size_t i = 0; i < size; i++) {
1656 if (effect == mEffects[i]) {
1657 // calling stop here will remove pre-processing effect from the audio HAL.
1658 // This is safe as we hold the EffectChain mutex which guarantees that we are not in
1659 // the middle of a read from audio HAL
1660 if (mEffects[i]->state() == EffectModule::ACTIVE ||
1661 mEffects[i]->state() == EffectModule::STOPPING) {
1662 mEffects[i]->stop();
1663 }
1664 if (type == EFFECT_FLAG_TYPE_AUXILIARY) {
1665 delete[] effect->inBuffer();
1666 } else {
1667 if (i == size - 1 && i != 0) {
1668 mEffects[i - 1]->setOutBuffer(mOutBuffer);
1669 mEffects[i - 1]->configure();
1670 }
1671 }
1672 mEffects.removeAt(i);
Glenn Kastenc42e9b42016-03-21 11:35:03 -07001673 ALOGV("removeEffect_l() effect %p, removed from chain %p at rank %zu", effect.get(),
Eric Laurentca7cc822012-11-19 14:55:58 -08001674 this, i);
1675 break;
1676 }
1677 }
1678
1679 return mEffects.size();
1680}
1681
1682// setDevice_l() must be called with PlaybackThread::mLock held
1683void AudioFlinger::EffectChain::setDevice_l(audio_devices_t device)
1684{
1685 size_t size = mEffects.size();
1686 for (size_t i = 0; i < size; i++) {
1687 mEffects[i]->setDevice(device);
1688 }
1689}
1690
1691// setMode_l() must be called with PlaybackThread::mLock held
1692void AudioFlinger::EffectChain::setMode_l(audio_mode_t mode)
1693{
1694 size_t size = mEffects.size();
1695 for (size_t i = 0; i < size; i++) {
1696 mEffects[i]->setMode(mode);
1697 }
1698}
1699
1700// setAudioSource_l() must be called with PlaybackThread::mLock held
1701void AudioFlinger::EffectChain::setAudioSource_l(audio_source_t source)
1702{
1703 size_t size = mEffects.size();
1704 for (size_t i = 0; i < size; i++) {
1705 mEffects[i]->setAudioSource(source);
1706 }
1707}
1708
Eric Laurentfa1e1232016-08-02 19:01:49 -07001709// setVolume_l() must be called with PlaybackThread::mLock or EffectChain::mLock held
1710bool AudioFlinger::EffectChain::setVolume_l(uint32_t *left, uint32_t *right, bool force)
Eric Laurentca7cc822012-11-19 14:55:58 -08001711{
1712 uint32_t newLeft = *left;
1713 uint32_t newRight = *right;
1714 bool hasControl = false;
1715 int ctrlIdx = -1;
1716 size_t size = mEffects.size();
1717
1718 // first update volume controller
1719 for (size_t i = size; i > 0; i--) {
1720 if (mEffects[i - 1]->isProcessEnabled() &&
1721 (mEffects[i - 1]->desc().flags & EFFECT_FLAG_VOLUME_MASK) == EFFECT_FLAG_VOLUME_CTRL) {
1722 ctrlIdx = i - 1;
1723 hasControl = true;
1724 break;
1725 }
1726 }
1727
Eric Laurentfa1e1232016-08-02 19:01:49 -07001728 if (!force && ctrlIdx == mVolumeCtrlIdx &&
Eric Laurentcb4b6e92014-10-01 14:26:10 -07001729 *left == mLeftVolume && *right == mRightVolume) {
Eric Laurentca7cc822012-11-19 14:55:58 -08001730 if (hasControl) {
1731 *left = mNewLeftVolume;
1732 *right = mNewRightVolume;
1733 }
1734 return hasControl;
1735 }
1736
1737 mVolumeCtrlIdx = ctrlIdx;
1738 mLeftVolume = newLeft;
1739 mRightVolume = newRight;
1740
1741 // second get volume update from volume controller
1742 if (ctrlIdx >= 0) {
1743 mEffects[ctrlIdx]->setVolume(&newLeft, &newRight, true);
1744 mNewLeftVolume = newLeft;
1745 mNewRightVolume = newRight;
1746 }
1747 // then indicate volume to all other effects in chain.
1748 // Pass altered volume to effects before volume controller
1749 // and requested volume to effects after controller
1750 uint32_t lVol = newLeft;
1751 uint32_t rVol = newRight;
1752
1753 for (size_t i = 0; i < size; i++) {
1754 if ((int)i == ctrlIdx) {
1755 continue;
1756 }
1757 // this also works for ctrlIdx == -1 when there is no volume controller
1758 if ((int)i > ctrlIdx) {
1759 lVol = *left;
1760 rVol = *right;
1761 }
1762 mEffects[i]->setVolume(&lVol, &rVol, false);
1763 }
1764 *left = newLeft;
1765 *right = newRight;
1766
1767 return hasControl;
1768}
1769
Eric Laurentfa1e1232016-08-02 19:01:49 -07001770// resetVolume_l() must be called with PlaybackThread::mLock or EffectChain::mLock held
1771void AudioFlinger::EffectChain::resetVolume_l()
1772{
Eric Laurente7449bf2016-08-03 18:44:07 -07001773 if ((mLeftVolume != UINT_MAX) && (mRightVolume != UINT_MAX)) {
1774 uint32_t left = mLeftVolume;
1775 uint32_t right = mRightVolume;
1776 (void)setVolume_l(&left, &right, true);
1777 }
Eric Laurentfa1e1232016-08-02 19:01:49 -07001778}
1779
Eric Laurent1b928682014-10-02 19:41:47 -07001780void AudioFlinger::EffectChain::syncHalEffectsState()
1781{
1782 Mutex::Autolock _l(mLock);
1783 for (size_t i = 0; i < mEffects.size(); i++) {
1784 if (mEffects[i]->state() == EffectModule::ACTIVE ||
1785 mEffects[i]->state() == EffectModule::STOPPING) {
1786 mEffects[i]->addEffectToHal_l();
1787 }
1788 }
1789}
1790
Eric Laurentca7cc822012-11-19 14:55:58 -08001791void AudioFlinger::EffectChain::dump(int fd, const Vector<String16>& args)
1792{
1793 const size_t SIZE = 256;
1794 char buffer[SIZE];
1795 String8 result;
1796
Marco Nelissenb2208842014-02-07 14:00:50 -08001797 size_t numEffects = mEffects.size();
Glenn Kastenc42e9b42016-03-21 11:35:03 -07001798 snprintf(buffer, SIZE, " %zu effects for session %d\n", numEffects, mSessionId);
Eric Laurentca7cc822012-11-19 14:55:58 -08001799 result.append(buffer);
1800
Marco Nelissenb2208842014-02-07 14:00:50 -08001801 if (numEffects) {
1802 bool locked = AudioFlinger::dumpTryLock(mLock);
1803 // failed to lock - AudioFlinger is probably deadlocked
1804 if (!locked) {
1805 result.append("\tCould not lock mutex:\n");
Eric Laurentca7cc822012-11-19 14:55:58 -08001806 }
Eric Laurentca7cc822012-11-19 14:55:58 -08001807
Marco Nelissenb2208842014-02-07 14:00:50 -08001808 result.append("\tIn buffer Out buffer Active tracks:\n");
Narayan Kamath1d6fa7a2014-02-11 13:47:53 +00001809 snprintf(buffer, SIZE, "\t%p %p %d\n",
1810 mInBuffer,
1811 mOutBuffer,
Marco Nelissenb2208842014-02-07 14:00:50 -08001812 mActiveTrackCnt);
1813 result.append(buffer);
1814 write(fd, result.string(), result.size());
1815
1816 for (size_t i = 0; i < numEffects; ++i) {
1817 sp<EffectModule> effect = mEffects[i];
1818 if (effect != 0) {
1819 effect->dump(fd, args);
1820 }
1821 }
1822
1823 if (locked) {
1824 mLock.unlock();
1825 }
Eric Laurentca7cc822012-11-19 14:55:58 -08001826 }
1827}
1828
1829// must be called with ThreadBase::mLock held
1830void AudioFlinger::EffectChain::setEffectSuspended_l(
1831 const effect_uuid_t *type, bool suspend)
1832{
1833 sp<SuspendedEffectDesc> desc;
1834 // use effect type UUID timelow as key as there is no real risk of identical
1835 // timeLow fields among effect type UUIDs.
1836 ssize_t index = mSuspendedEffects.indexOfKey(type->timeLow);
1837 if (suspend) {
1838 if (index >= 0) {
1839 desc = mSuspendedEffects.valueAt(index);
1840 } else {
1841 desc = new SuspendedEffectDesc();
1842 desc->mType = *type;
1843 mSuspendedEffects.add(type->timeLow, desc);
1844 ALOGV("setEffectSuspended_l() add entry for %08x", type->timeLow);
1845 }
1846 if (desc->mRefCount++ == 0) {
1847 sp<EffectModule> effect = getEffectIfEnabled(type);
1848 if (effect != 0) {
1849 desc->mEffect = effect;
1850 effect->setSuspended(true);
1851 effect->setEnabled(false);
1852 }
1853 }
1854 } else {
1855 if (index < 0) {
1856 return;
1857 }
1858 desc = mSuspendedEffects.valueAt(index);
1859 if (desc->mRefCount <= 0) {
1860 ALOGW("setEffectSuspended_l() restore refcount should not be 0 %d", desc->mRefCount);
1861 desc->mRefCount = 1;
1862 }
1863 if (--desc->mRefCount == 0) {
1864 ALOGV("setEffectSuspended_l() remove entry for %08x", mSuspendedEffects.keyAt(index));
1865 if (desc->mEffect != 0) {
1866 sp<EffectModule> effect = desc->mEffect.promote();
1867 if (effect != 0) {
1868 effect->setSuspended(false);
1869 effect->lock();
1870 EffectHandle *handle = effect->controlHandle_l();
1871 if (handle != NULL && !handle->destroyed_l()) {
1872 effect->setEnabled_l(handle->enabled());
1873 }
1874 effect->unlock();
1875 }
1876 desc->mEffect.clear();
1877 }
1878 mSuspendedEffects.removeItemsAt(index);
1879 }
1880 }
1881}
1882
1883// must be called with ThreadBase::mLock held
1884void AudioFlinger::EffectChain::setEffectSuspendedAll_l(bool suspend)
1885{
1886 sp<SuspendedEffectDesc> desc;
1887
1888 ssize_t index = mSuspendedEffects.indexOfKey((int)kKeyForSuspendAll);
1889 if (suspend) {
1890 if (index >= 0) {
1891 desc = mSuspendedEffects.valueAt(index);
1892 } else {
1893 desc = new SuspendedEffectDesc();
1894 mSuspendedEffects.add((int)kKeyForSuspendAll, desc);
1895 ALOGV("setEffectSuspendedAll_l() add entry for 0");
1896 }
1897 if (desc->mRefCount++ == 0) {
1898 Vector< sp<EffectModule> > effects;
1899 getSuspendEligibleEffects(effects);
1900 for (size_t i = 0; i < effects.size(); i++) {
1901 setEffectSuspended_l(&effects[i]->desc().type, true);
1902 }
1903 }
1904 } else {
1905 if (index < 0) {
1906 return;
1907 }
1908 desc = mSuspendedEffects.valueAt(index);
1909 if (desc->mRefCount <= 0) {
1910 ALOGW("setEffectSuspendedAll_l() restore refcount should not be 0 %d", desc->mRefCount);
1911 desc->mRefCount = 1;
1912 }
1913 if (--desc->mRefCount == 0) {
1914 Vector<const effect_uuid_t *> types;
1915 for (size_t i = 0; i < mSuspendedEffects.size(); i++) {
1916 if (mSuspendedEffects.keyAt(i) == (int)kKeyForSuspendAll) {
1917 continue;
1918 }
1919 types.add(&mSuspendedEffects.valueAt(i)->mType);
1920 }
1921 for (size_t i = 0; i < types.size(); i++) {
1922 setEffectSuspended_l(types[i], false);
1923 }
1924 ALOGV("setEffectSuspendedAll_l() remove entry for %08x",
1925 mSuspendedEffects.keyAt(index));
1926 mSuspendedEffects.removeItem((int)kKeyForSuspendAll);
1927 }
1928 }
1929}
1930
1931
1932// The volume effect is used for automated tests only
1933#ifndef OPENSL_ES_H_
1934static const effect_uuid_t SL_IID_VOLUME_ = { 0x09e8ede0, 0xddde, 0x11db, 0xb4f6,
1935 { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } };
1936const effect_uuid_t * const SL_IID_VOLUME = &SL_IID_VOLUME_;
1937#endif //OPENSL_ES_H_
1938
1939bool AudioFlinger::EffectChain::isEffectEligibleForSuspend(const effect_descriptor_t& desc)
1940{
1941 // auxiliary effects and visualizer are never suspended on output mix
1942 if ((mSessionId == AUDIO_SESSION_OUTPUT_MIX) &&
1943 (((desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) ||
1944 (memcmp(&desc.type, SL_IID_VISUALIZATION, sizeof(effect_uuid_t)) == 0) ||
1945 (memcmp(&desc.type, SL_IID_VOLUME, sizeof(effect_uuid_t)) == 0))) {
1946 return false;
1947 }
1948 return true;
1949}
1950
1951void AudioFlinger::EffectChain::getSuspendEligibleEffects(
1952 Vector< sp<AudioFlinger::EffectModule> > &effects)
1953{
1954 effects.clear();
1955 for (size_t i = 0; i < mEffects.size(); i++) {
1956 if (isEffectEligibleForSuspend(mEffects[i]->desc())) {
1957 effects.add(mEffects[i]);
1958 }
1959 }
1960}
1961
1962sp<AudioFlinger::EffectModule> AudioFlinger::EffectChain::getEffectIfEnabled(
1963 const effect_uuid_t *type)
1964{
1965 sp<EffectModule> effect = getEffectFromType_l(type);
1966 return effect != 0 && effect->isEnabled() ? effect : 0;
1967}
1968
1969void AudioFlinger::EffectChain::checkSuspendOnEffectEnabled(const sp<EffectModule>& effect,
1970 bool enabled)
1971{
1972 ssize_t index = mSuspendedEffects.indexOfKey(effect->desc().type.timeLow);
1973 if (enabled) {
1974 if (index < 0) {
1975 // if the effect is not suspend check if all effects are suspended
1976 index = mSuspendedEffects.indexOfKey((int)kKeyForSuspendAll);
1977 if (index < 0) {
1978 return;
1979 }
1980 if (!isEffectEligibleForSuspend(effect->desc())) {
1981 return;
1982 }
1983 setEffectSuspended_l(&effect->desc().type, enabled);
1984 index = mSuspendedEffects.indexOfKey(effect->desc().type.timeLow);
1985 if (index < 0) {
1986 ALOGW("checkSuspendOnEffectEnabled() Fx should be suspended here!");
1987 return;
1988 }
1989 }
1990 ALOGV("checkSuspendOnEffectEnabled() enable suspending fx %08x",
1991 effect->desc().type.timeLow);
1992 sp<SuspendedEffectDesc> desc = mSuspendedEffects.valueAt(index);
1993 // if effect is requested to suspended but was not yet enabled, supend it now.
1994 if (desc->mEffect == 0) {
1995 desc->mEffect = effect;
1996 effect->setEnabled(false);
1997 effect->setSuspended(true);
1998 }
1999 } else {
2000 if (index < 0) {
2001 return;
2002 }
2003 ALOGV("checkSuspendOnEffectEnabled() disable restoring fx %08x",
2004 effect->desc().type.timeLow);
2005 sp<SuspendedEffectDesc> desc = mSuspendedEffects.valueAt(index);
2006 desc->mEffect.clear();
2007 effect->setSuspended(false);
2008 }
2009}
2010
Eric Laurent5baf2af2013-09-12 17:37:00 -07002011bool AudioFlinger::EffectChain::isNonOffloadableEnabled()
Eric Laurent813e2a72013-08-31 12:59:48 -07002012{
2013 Mutex::Autolock _l(mLock);
2014 size_t size = mEffects.size();
2015 for (size_t i = 0; i < size; i++) {
Eric Laurent5baf2af2013-09-12 17:37:00 -07002016 if (mEffects[i]->isEnabled() && !mEffects[i]->isOffloadable()) {
Eric Laurent813e2a72013-08-31 12:59:48 -07002017 return true;
2018 }
2019 }
2020 return false;
2021}
2022
Eric Laurentaaa44472014-09-12 17:41:50 -07002023void AudioFlinger::EffectChain::setThread(const sp<ThreadBase>& thread)
2024{
2025 Mutex::Autolock _l(mLock);
2026 mThread = thread;
2027 for (size_t i = 0; i < mEffects.size(); i++) {
2028 mEffects[i]->setThread(thread);
2029 }
2030}
2031
Eric Laurent4c415062016-06-17 16:14:16 -07002032bool AudioFlinger::EffectChain::hasSoftwareEffect() const
2033{
2034 Mutex::Autolock _l(mLock);
2035 for (size_t i = 0; i < mEffects.size(); i++) {
2036 if (mEffects[i]->isImplementationSoftware()) {
2037 return true;
2038 }
2039 }
2040 return false;
2041}
2042
2043// isCompatibleWithThread_l() must be called with thread->mLock held
2044bool AudioFlinger::EffectChain::isCompatibleWithThread_l(const sp<ThreadBase>& thread) const
2045{
2046 Mutex::Autolock _l(mLock);
2047 for (size_t i = 0; i < mEffects.size(); i++) {
2048 if (thread->checkEffectCompatibility_l(&(mEffects[i]->desc()), mSessionId) != NO_ERROR) {
2049 return false;
2050 }
2051 }
2052 return true;
2053}
2054
Glenn Kasten63238ef2015-03-02 15:50:29 -08002055} // namespace android