blob: c192b858794943c81f5dbb150cce3e0e460b5cec [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
rago94a1ee82017-07-21 15:11:02 -070022#include <algorithm>
23
Glenn Kasten153b9fe2013-07-15 11:23:36 -070024#include "Configuration.h"
Eric Laurentca7cc822012-11-19 14:55:58 -080025#include <utils/Log.h>
Eric Laurentd8365c52017-07-16 15:27:05 -070026#include <system/audio_effects/effect_aec.h>
Ricardo Garciac2a3a822019-07-17 14:29:12 -070027#include <system/audio_effects/effect_dynamicsprocessing.h>
jiabineb3bda02020-06-30 14:07:03 -070028#include <system/audio_effects/effect_hapticgenerator.h>
Eric Laurentd8365c52017-07-16 15:27:05 -070029#include <system/audio_effects/effect_ns.h>
30#include <system/audio_effects/effect_visualizer.h>
Andy Hung9aad48c2017-11-29 10:29:19 -080031#include <audio_utils/channels.h>
Eric Laurentca7cc822012-11-19 14:55:58 -080032#include <audio_utils/primitives.h>
Mikhail Naganovf698ff22020-03-31 10:07:29 -070033#include <media/AudioCommonTypes.h>
jiabin8f278ee2019-11-11 12:16:27 -080034#include <media/AudioContainers.h>
Mikhail Naganov424c4f52017-07-19 17:54:29 -070035#include <media/AudioEffect.h>
jiabin8f278ee2019-11-11 12:16:27 -080036#include <media/AudioDeviceTypeAddr.h>
Mikhail Naganova0c91332016-09-19 10:01:12 -070037#include <media/audiohal/EffectHalInterface.h>
38#include <media/audiohal/EffectsFactoryHalInterface.h>
Andy Hungab7ef302018-05-15 19:35:29 -070039#include <mediautils/ServiceUtilities.h>
Eric Laurentca7cc822012-11-19 14:55:58 -080040
41#include "AudioFlinger.h"
Eric Laurentca7cc822012-11-19 14:55:58 -080042
43// ----------------------------------------------------------------------------
44
45// Note: the following macro is used for extremely verbose logging message. In
46// order to run with ALOG_ASSERT turned on, we need to have LOG_NDEBUG set to
47// 0; but one side effect of this is to turn all LOGV's as well. Some messages
48// are so verbose that we want to suppress them even when we have ALOG_ASSERT
49// turned on. Do not uncomment the #def below unless you really know what you
50// are doing and want to see all of the extremely verbose messages.
51//#define VERY_VERY_VERBOSE_LOGGING
52#ifdef VERY_VERY_VERBOSE_LOGGING
53#define ALOGVV ALOGV
54#else
55#define ALOGVV(a...) do { } while(0)
56#endif
57
Yuuki Yokoyamae17f8312017-05-26 19:06:33 +090058#define DEFAULT_OUTPUT_SAMPLE_RATE 48000
59
Eric Laurentca7cc822012-11-19 14:55:58 -080060namespace android {
61
62// ----------------------------------------------------------------------------
Eric Laurent41709552019-12-16 19:34:05 -080063// EffectBase implementation
Eric Laurentca7cc822012-11-19 14:55:58 -080064// ----------------------------------------------------------------------------
65
66#undef LOG_TAG
Eric Laurent41709552019-12-16 19:34:05 -080067#define LOG_TAG "AudioFlinger::EffectBase"
Eric Laurentca7cc822012-11-19 14:55:58 -080068
Eric Laurent41709552019-12-16 19:34:05 -080069AudioFlinger::EffectBase::EffectBase(const sp<AudioFlinger::EffectCallbackInterface>& callback,
Eric Laurentca7cc822012-11-19 14:55:58 -080070 effect_descriptor_t *desc,
71 int id,
Eric Laurent0d5a2ed2016-12-01 15:28:29 -080072 audio_session_t sessionId,
73 bool pinned)
74 : mPinned(pinned),
Eric Laurent6b446ce2019-12-13 10:56:31 -080075 mCallback(callback), mId(id), mSessionId(sessionId),
Eric Laurent41709552019-12-16 19:34:05 -080076 mDescriptor(*desc)
Eric Laurentca7cc822012-11-19 14:55:58 -080077{
Eric Laurentca7cc822012-11-19 14:55:58 -080078}
79
Eric Laurent41709552019-12-16 19:34:05 -080080// must be called with EffectModule::mLock held
81status_t AudioFlinger::EffectBase::setEnabled_l(bool enabled)
Eric Laurentca7cc822012-11-19 14:55:58 -080082{
Eric Laurent0d5a2ed2016-12-01 15:28:29 -080083
Eric Laurent41709552019-12-16 19:34:05 -080084 ALOGV("setEnabled %p enabled %d", this, enabled);
85
86 if (enabled != isEnabled()) {
87 switch (mState) {
88 // going from disabled to enabled
89 case IDLE:
90 mState = STARTING;
91 break;
92 case STOPPED:
93 mState = RESTART;
94 break;
95 case STOPPING:
96 mState = ACTIVE;
97 break;
98
99 // going from enabled to disabled
100 case RESTART:
101 mState = STOPPED;
102 break;
103 case STARTING:
104 mState = IDLE;
105 break;
106 case ACTIVE:
107 mState = STOPPING;
108 break;
109 case DESTROYED:
110 return NO_ERROR; // simply ignore as we are being destroyed
111 }
112 for (size_t i = 1; i < mHandles.size(); i++) {
113 EffectHandle *h = mHandles[i];
114 if (h != NULL && !h->disconnected()) {
115 h->setEnabled(enabled);
116 }
117 }
118 }
119 return NO_ERROR;
Eric Laurentca7cc822012-11-19 14:55:58 -0800120}
121
Eric Laurent41709552019-12-16 19:34:05 -0800122status_t AudioFlinger::EffectBase::setEnabled(bool enabled, bool fromHandle)
123{
124 status_t status;
125 {
126 Mutex::Autolock _l(mLock);
127 status = setEnabled_l(enabled);
128 }
129 if (fromHandle) {
130 if (enabled) {
131 if (status != NO_ERROR) {
132 mCallback->checkSuspendOnEffectEnabled(this, false, false /*threadLocked*/);
133 } else {
134 mCallback->onEffectEnable(this);
135 }
136 } else {
137 mCallback->onEffectDisable(this);
138 }
139 }
140 return status;
141}
142
143bool AudioFlinger::EffectBase::isEnabled() const
144{
145 switch (mState) {
146 case RESTART:
147 case STARTING:
148 case ACTIVE:
149 return true;
150 case IDLE:
151 case STOPPING:
152 case STOPPED:
153 case DESTROYED:
154 default:
155 return false;
156 }
157}
158
159void AudioFlinger::EffectBase::setSuspended(bool suspended)
160{
161 Mutex::Autolock _l(mLock);
162 mSuspended = suspended;
163}
164
165bool AudioFlinger::EffectBase::suspended() const
166{
167 Mutex::Autolock _l(mLock);
168 return mSuspended;
169}
170
171status_t AudioFlinger::EffectBase::addHandle(EffectHandle *handle)
Eric Laurentca7cc822012-11-19 14:55:58 -0800172{
173 status_t status;
174
175 Mutex::Autolock _l(mLock);
176 int priority = handle->priority();
177 size_t size = mHandles.size();
178 EffectHandle *controlHandle = NULL;
179 size_t i;
180 for (i = 0; i < size; i++) {
181 EffectHandle *h = mHandles[i];
Eric Laurent0d5a2ed2016-12-01 15:28:29 -0800182 if (h == NULL || h->disconnected()) {
Eric Laurentca7cc822012-11-19 14:55:58 -0800183 continue;
184 }
185 // first non destroyed handle is considered in control
Glenn Kasten6e2ebe92013-08-13 09:14:51 -0700186 if (controlHandle == NULL) {
Eric Laurentca7cc822012-11-19 14:55:58 -0800187 controlHandle = h;
Glenn Kasten6e2ebe92013-08-13 09:14:51 -0700188 }
Eric Laurentca7cc822012-11-19 14:55:58 -0800189 if (h->priority() <= priority) {
190 break;
191 }
192 }
193 // if inserted in first place, move effect control from previous owner to this handle
194 if (i == 0) {
195 bool enabled = false;
196 if (controlHandle != NULL) {
197 enabled = controlHandle->enabled();
198 controlHandle->setControl(false/*hasControl*/, true /*signal*/, enabled /*enabled*/);
199 }
200 handle->setControl(true /*hasControl*/, false /*signal*/, enabled /*enabled*/);
201 status = NO_ERROR;
202 } else {
203 status = ALREADY_EXISTS;
204 }
Glenn Kastenc42e9b42016-03-21 11:35:03 -0700205 ALOGV("addHandle() %p added handle %p in position %zu", this, handle, i);
Eric Laurentca7cc822012-11-19 14:55:58 -0800206 mHandles.insertAt(handle, i);
207 return status;
208}
209
Eric Laurent41709552019-12-16 19:34:05 -0800210status_t AudioFlinger::EffectBase::updatePolicyState()
Eric Laurent6c796322019-04-09 14:13:17 -0700211{
212 status_t status = NO_ERROR;
213 bool doRegister = false;
214 bool registered = false;
215 bool doEnable = false;
216 bool enabled = false;
Mikhail Naganov379d6872020-03-26 13:04:11 -0700217 audio_io_handle_t io = AUDIO_IO_HANDLE_NONE;
Mikhail Naganovf698ff22020-03-31 10:07:29 -0700218 uint32_t strategy = PRODUCT_STRATEGY_NONE;
Eric Laurent6c796322019-04-09 14:13:17 -0700219
220 {
221 Mutex::Autolock _l(mLock);
222 // register effect when first handle is attached and unregister when last handle is removed
223 if (mPolicyRegistered != mHandles.size() > 0) {
224 doRegister = true;
225 mPolicyRegistered = mHandles.size() > 0;
226 if (mPolicyRegistered) {
Eric Laurent6b446ce2019-12-13 10:56:31 -0800227 io = mCallback->io();
228 strategy = mCallback->strategy();
Eric Laurent6c796322019-04-09 14:13:17 -0700229 }
230 }
231 // enable effect when registered according to enable state requested by controlling handle
232 if (mHandles.size() > 0) {
233 EffectHandle *handle = controlHandle_l();
234 if (handle != nullptr && mPolicyEnabled != handle->enabled()) {
235 doEnable = true;
236 mPolicyEnabled = handle->enabled();
237 }
238 }
239 registered = mPolicyRegistered;
240 enabled = mPolicyEnabled;
241 mPolicyLock.lock();
242 }
243 ALOGV("%s name %s id %d session %d doRegister %d registered %d doEnable %d enabled %d",
244 __func__, mDescriptor.name, mId, mSessionId, doRegister, registered, doEnable, enabled);
245 if (doRegister) {
246 if (registered) {
247 status = AudioSystem::registerEffect(
248 &mDescriptor,
249 io,
250 strategy,
251 mSessionId,
252 mId);
253 } else {
254 status = AudioSystem::unregisterEffect(mId);
255 }
256 }
257 if (registered && doEnable) {
258 status = AudioSystem::setEffectEnabled(mId, enabled);
259 }
260 mPolicyLock.unlock();
261
262 return status;
263}
264
265
Eric Laurent41709552019-12-16 19:34:05 -0800266ssize_t AudioFlinger::EffectBase::removeHandle(EffectHandle *handle)
Eric Laurentca7cc822012-11-19 14:55:58 -0800267{
268 Mutex::Autolock _l(mLock);
Eric Laurent0d5a2ed2016-12-01 15:28:29 -0800269 return removeHandle_l(handle);
270}
271
Eric Laurent41709552019-12-16 19:34:05 -0800272ssize_t AudioFlinger::EffectBase::removeHandle_l(EffectHandle *handle)
Eric Laurent0d5a2ed2016-12-01 15:28:29 -0800273{
Eric Laurentca7cc822012-11-19 14:55:58 -0800274 size_t size = mHandles.size();
275 size_t i;
276 for (i = 0; i < size; i++) {
277 if (mHandles[i] == handle) {
278 break;
279 }
280 }
281 if (i == size) {
Eric Laurent0d5a2ed2016-12-01 15:28:29 -0800282 ALOGW("%s %p handle not found %p", __FUNCTION__, this, handle);
283 return BAD_VALUE;
Eric Laurentca7cc822012-11-19 14:55:58 -0800284 }
Eric Laurent0d5a2ed2016-12-01 15:28:29 -0800285 ALOGV("removeHandle_l() %p removed handle %p in position %zu", this, handle, i);
Eric Laurentca7cc822012-11-19 14:55:58 -0800286
287 mHandles.removeAt(i);
288 // if removed from first place, move effect control from this handle to next in line
289 if (i == 0) {
290 EffectHandle *h = controlHandle_l();
291 if (h != NULL) {
292 h->setControl(true /*hasControl*/, true /*signal*/ , handle->enabled() /*enabled*/);
293 }
294 }
295
Eric Laurentca7cc822012-11-19 14:55:58 -0800296 if (mHandles.size() == 0 && !mPinned) {
297 mState = DESTROYED;
298 }
299
300 return mHandles.size();
301}
302
303// must be called with EffectModule::mLock held
Eric Laurent41709552019-12-16 19:34:05 -0800304AudioFlinger::EffectHandle *AudioFlinger::EffectBase::controlHandle_l()
Eric Laurentca7cc822012-11-19 14:55:58 -0800305{
306 // the first valid handle in the list has control over the module
307 for (size_t i = 0; i < mHandles.size(); i++) {
308 EffectHandle *h = mHandles[i];
Eric Laurent0d5a2ed2016-12-01 15:28:29 -0800309 if (h != NULL && !h->disconnected()) {
Eric Laurentca7cc822012-11-19 14:55:58 -0800310 return h;
311 }
312 }
313
314 return NULL;
315}
316
Eric Laurentf10c7092016-12-06 17:09:56 -0800317// unsafe method called when the effect parent thread has been destroyed
Eric Laurent41709552019-12-16 19:34:05 -0800318ssize_t AudioFlinger::EffectBase::disconnectHandle(EffectHandle *handle, bool unpinIfLast)
Eric Laurentf10c7092016-12-06 17:09:56 -0800319{
320 ALOGV("disconnect() %p handle %p", this, handle);
Eric Laurent6b446ce2019-12-13 10:56:31 -0800321 if (mCallback->disconnectEffectHandle(handle, unpinIfLast)) {
322 return mHandles.size();
323 }
324
Eric Laurentf10c7092016-12-06 17:09:56 -0800325 Mutex::Autolock _l(mLock);
326 ssize_t numHandles = removeHandle_l(handle);
327 if ((numHandles == 0) && (!mPinned || unpinIfLast)) {
Eric Laurent6b446ce2019-12-13 10:56:31 -0800328 mLock.unlock();
329 mCallback->updateOrphanEffectChains(this);
330 mLock.lock();
Eric Laurentf10c7092016-12-06 17:09:56 -0800331 }
332 return numHandles;
333}
334
Eric Laurent41709552019-12-16 19:34:05 -0800335bool AudioFlinger::EffectBase::purgeHandles()
336{
337 bool enabled = false;
338 Mutex::Autolock _l(mLock);
339 EffectHandle *handle = controlHandle_l();
340 if (handle != NULL) {
341 enabled = handle->enabled();
342 }
343 mHandles.clear();
344 return enabled;
345}
346
347void AudioFlinger::EffectBase::checkSuspendOnEffectEnabled(bool enabled, bool threadLocked) {
348 mCallback->checkSuspendOnEffectEnabled(this, enabled, threadLocked);
349}
350
351static String8 effectFlagsToString(uint32_t flags) {
352 String8 s;
353
354 s.append("conn. mode: ");
355 switch (flags & EFFECT_FLAG_TYPE_MASK) {
356 case EFFECT_FLAG_TYPE_INSERT: s.append("insert"); break;
357 case EFFECT_FLAG_TYPE_AUXILIARY: s.append("auxiliary"); break;
358 case EFFECT_FLAG_TYPE_REPLACE: s.append("replace"); break;
359 case EFFECT_FLAG_TYPE_PRE_PROC: s.append("preproc"); break;
360 case EFFECT_FLAG_TYPE_POST_PROC: s.append("postproc"); break;
361 default: s.append("unknown/reserved"); break;
362 }
363 s.append(", ");
364
365 s.append("insert pref: ");
366 switch (flags & EFFECT_FLAG_INSERT_MASK) {
367 case EFFECT_FLAG_INSERT_ANY: s.append("any"); break;
368 case EFFECT_FLAG_INSERT_FIRST: s.append("first"); break;
369 case EFFECT_FLAG_INSERT_LAST: s.append("last"); break;
370 case EFFECT_FLAG_INSERT_EXCLUSIVE: s.append("exclusive"); break;
371 default: s.append("unknown/reserved"); break;
372 }
373 s.append(", ");
374
375 s.append("volume mgmt: ");
376 switch (flags & EFFECT_FLAG_VOLUME_MASK) {
377 case EFFECT_FLAG_VOLUME_NONE: s.append("none"); break;
378 case EFFECT_FLAG_VOLUME_CTRL: s.append("implements control"); break;
379 case EFFECT_FLAG_VOLUME_IND: s.append("requires indication"); break;
380 case EFFECT_FLAG_VOLUME_MONITOR: s.append("monitors volume"); break;
381 default: s.append("unknown/reserved"); break;
382 }
383 s.append(", ");
384
385 uint32_t devind = flags & EFFECT_FLAG_DEVICE_MASK;
386 if (devind) {
387 s.append("device indication: ");
388 switch (devind) {
389 case EFFECT_FLAG_DEVICE_IND: s.append("requires updates"); break;
390 default: s.append("unknown/reserved"); break;
391 }
392 s.append(", ");
393 }
394
395 s.append("input mode: ");
396 switch (flags & EFFECT_FLAG_INPUT_MASK) {
397 case EFFECT_FLAG_INPUT_DIRECT: s.append("direct"); break;
398 case EFFECT_FLAG_INPUT_PROVIDER: s.append("provider"); break;
399 case EFFECT_FLAG_INPUT_BOTH: s.append("direct+provider"); break;
400 default: s.append("not set"); break;
401 }
402 s.append(", ");
403
404 s.append("output mode: ");
405 switch (flags & EFFECT_FLAG_OUTPUT_MASK) {
406 case EFFECT_FLAG_OUTPUT_DIRECT: s.append("direct"); break;
407 case EFFECT_FLAG_OUTPUT_PROVIDER: s.append("provider"); break;
408 case EFFECT_FLAG_OUTPUT_BOTH: s.append("direct+provider"); break;
409 default: s.append("not set"); break;
410 }
411 s.append(", ");
412
413 uint32_t accel = flags & EFFECT_FLAG_HW_ACC_MASK;
414 if (accel) {
415 s.append("hardware acceleration: ");
416 switch (accel) {
417 case EFFECT_FLAG_HW_ACC_SIMPLE: s.append("non-tunneled"); break;
418 case EFFECT_FLAG_HW_ACC_TUNNEL: s.append("tunneled"); break;
419 default: s.append("unknown/reserved"); break;
420 }
421 s.append(", ");
422 }
423
424 uint32_t modeind = flags & EFFECT_FLAG_AUDIO_MODE_MASK;
425 if (modeind) {
426 s.append("mode indication: ");
427 switch (modeind) {
428 case EFFECT_FLAG_AUDIO_MODE_IND: s.append("required"); break;
429 default: s.append("unknown/reserved"); break;
430 }
431 s.append(", ");
432 }
433
434 uint32_t srcind = flags & EFFECT_FLAG_AUDIO_SOURCE_MASK;
435 if (srcind) {
436 s.append("source indication: ");
437 switch (srcind) {
438 case EFFECT_FLAG_AUDIO_SOURCE_IND: s.append("required"); break;
439 default: s.append("unknown/reserved"); break;
440 }
441 s.append(", ");
442 }
443
444 if (flags & EFFECT_FLAG_OFFLOAD_MASK) {
445 s.append("offloadable, ");
446 }
447
448 int len = s.length();
449 if (s.length() > 2) {
450 (void) s.lockBuffer(len);
451 s.unlockBuffer(len - 2);
452 }
453 return s;
454}
455
456void AudioFlinger::EffectBase::dump(int fd, const Vector<String16>& args __unused)
457{
458 String8 result;
459
460 result.appendFormat("\tEffect ID %d:\n", mId);
461
462 bool locked = AudioFlinger::dumpTryLock(mLock);
463 // failed to lock - AudioFlinger is probably deadlocked
464 if (!locked) {
465 result.append("\t\tCould not lock Fx mutex:\n");
466 }
467
468 result.append("\t\tSession State Registered Enabled Suspended:\n");
469 result.appendFormat("\t\t%05d %03d %s %s %s\n",
470 mSessionId, mState, mPolicyRegistered ? "y" : "n",
471 mPolicyEnabled ? "y" : "n", mSuspended ? "y" : "n");
472
473 result.append("\t\tDescriptor:\n");
474 char uuidStr[64];
475 AudioEffect::guidToString(&mDescriptor.uuid, uuidStr, sizeof(uuidStr));
476 result.appendFormat("\t\t- UUID: %s\n", uuidStr);
477 AudioEffect::guidToString(&mDescriptor.type, uuidStr, sizeof(uuidStr));
478 result.appendFormat("\t\t- TYPE: %s\n", uuidStr);
479 result.appendFormat("\t\t- apiVersion: %08X\n\t\t- flags: %08X (%s)\n",
480 mDescriptor.apiVersion,
481 mDescriptor.flags,
482 effectFlagsToString(mDescriptor.flags).string());
483 result.appendFormat("\t\t- name: %s\n",
484 mDescriptor.name);
485
486 result.appendFormat("\t\t- implementor: %s\n",
487 mDescriptor.implementor);
488
489 result.appendFormat("\t\t%zu Clients:\n", mHandles.size());
490 result.append("\t\t\t Pid Priority Ctrl Locked client server\n");
491 char buffer[256];
492 for (size_t i = 0; i < mHandles.size(); ++i) {
493 EffectHandle *handle = mHandles[i];
494 if (handle != NULL && !handle->disconnected()) {
495 handle->dumpToBuffer(buffer, sizeof(buffer));
496 result.append(buffer);
497 }
498 }
499 if (locked) {
500 mLock.unlock();
501 }
502
503 write(fd, result.string(), result.length());
504}
505
506// ----------------------------------------------------------------------------
507// EffectModule implementation
508// ----------------------------------------------------------------------------
509
510#undef LOG_TAG
511#define LOG_TAG "AudioFlinger::EffectModule"
512
513AudioFlinger::EffectModule::EffectModule(const sp<AudioFlinger::EffectCallbackInterface>& callback,
514 effect_descriptor_t *desc,
515 int id,
516 audio_session_t sessionId,
Eric Laurentb82e6b72019-11-22 17:25:04 -0800517 bool pinned,
518 audio_port_handle_t deviceId)
Eric Laurent41709552019-12-16 19:34:05 -0800519 : EffectBase(callback, desc, id, sessionId, pinned),
520 // clear mConfig to ensure consistent initial value of buffer framecount
521 // in case buffers are associated by setInBuffer() or setOutBuffer()
522 // prior to configure().
523 mConfig{{}, {}},
524 mStatus(NO_INIT),
525 mMaxDisableWaitCnt(1), // set by configure(), should be >= 1
526 mDisableWaitCnt(0), // set by process() and updateState()
527 mOffloaded(false)
528#ifdef FLOAT_EFFECT_CHAIN
529 , mSupportsFloat(false)
530#endif
531{
532 ALOGV("Constructor %p pinned %d", this, pinned);
533 int lStatus;
534
535 // create effect engine from effect factory
536 mStatus = callback->createEffectHal(
Eric Laurentb82e6b72019-11-22 17:25:04 -0800537 &desc->uuid, sessionId, deviceId, &mEffectInterface);
Eric Laurent41709552019-12-16 19:34:05 -0800538 if (mStatus != NO_ERROR) {
539 return;
540 }
541 lStatus = init();
542 if (lStatus < 0) {
543 mStatus = lStatus;
544 goto Error;
545 }
546
547 setOffloaded(callback->isOffload(), callback->io());
548 ALOGV("Constructor success name %s, Interface %p", mDescriptor.name, mEffectInterface.get());
549
550 return;
551Error:
552 mEffectInterface.clear();
553 ALOGV("Constructor Error %d", mStatus);
554}
555
556AudioFlinger::EffectModule::~EffectModule()
557{
558 ALOGV("Destructor %p", this);
559 if (mEffectInterface != 0) {
560 char uuidStr[64];
561 AudioEffect::guidToString(&mDescriptor.uuid, uuidStr, sizeof(uuidStr));
562 ALOGW("EffectModule %p destructor called with unreleased interface, effect %s",
563 this, uuidStr);
564 release_l();
565 }
566
567}
568
569ssize_t AudioFlinger::EffectModule::removeHandle_l(EffectHandle *handle)
570{
571 ssize_t status = EffectBase::removeHandle_l(handle);
572
573 // Prevent calls to process() and other functions on effect interface from now on.
574 // The effect engine will be released by the destructor when the last strong reference on
575 // this object is released which can happen after next process is called.
576 if (status == 0 && !mPinned) {
577 mEffectInterface->close();
578 }
579
580 return status;
581}
582
Eric Laurentfa1e1232016-08-02 19:01:49 -0700583bool AudioFlinger::EffectModule::updateState() {
Eric Laurentca7cc822012-11-19 14:55:58 -0800584 Mutex::Autolock _l(mLock);
585
Eric Laurentfa1e1232016-08-02 19:01:49 -0700586 bool started = false;
Eric Laurentca7cc822012-11-19 14:55:58 -0800587 switch (mState) {
588 case RESTART:
589 reset_l();
Chih-Hung Hsieh2b487032018-09-13 14:16:02 -0700590 FALLTHROUGH_INTENDED;
Eric Laurentca7cc822012-11-19 14:55:58 -0800591
592 case STARTING:
593 // clear auxiliary effect input buffer for next accumulation
594 if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
595 memset(mConfig.inputCfg.buffer.raw,
596 0,
597 mConfig.inputCfg.buffer.frameCount*sizeof(int32_t));
598 }
Eric Laurentd0ebb532013-04-02 16:41:41 -0700599 if (start_l() == NO_ERROR) {
600 mState = ACTIVE;
Eric Laurentfa1e1232016-08-02 19:01:49 -0700601 started = true;
Eric Laurentd0ebb532013-04-02 16:41:41 -0700602 } else {
603 mState = IDLE;
604 }
Eric Laurentca7cc822012-11-19 14:55:58 -0800605 break;
606 case STOPPING:
Tomoharu Kasahara1990bd42014-12-12 14:04:11 +0900607 // volume control for offload and direct threads must take effect immediately.
608 if (stop_l() == NO_ERROR
609 && !(isVolumeControl() && isOffloadedOrDirect())) {
Eric Laurentd0ebb532013-04-02 16:41:41 -0700610 mDisableWaitCnt = mMaxDisableWaitCnt;
611 } else {
612 mDisableWaitCnt = 1; // will cause immediate transition to IDLE
613 }
Eric Laurentca7cc822012-11-19 14:55:58 -0800614 mState = STOPPED;
615 break;
616 case STOPPED:
617 // mDisableWaitCnt is forced to 1 by process() when the engine indicates the end of the
618 // turn off sequence.
619 if (--mDisableWaitCnt == 0) {
620 reset_l();
621 mState = IDLE;
622 }
623 break;
624 default: //IDLE , ACTIVE, DESTROYED
625 break;
626 }
Eric Laurentfa1e1232016-08-02 19:01:49 -0700627
628 return started;
Eric Laurentca7cc822012-11-19 14:55:58 -0800629}
630
631void AudioFlinger::EffectModule::process()
632{
633 Mutex::Autolock _l(mLock);
634
Mikhail Naganov022b9952017-01-04 16:36:51 -0800635 if (mState == DESTROYED || mEffectInterface == 0 || mInBuffer == 0 || mOutBuffer == 0) {
Eric Laurentca7cc822012-11-19 14:55:58 -0800636 return;
637 }
638
rago94a1ee82017-07-21 15:11:02 -0700639 const uint32_t inChannelCount =
640 audio_channel_count_from_out_mask(mConfig.inputCfg.channels);
641 const uint32_t outChannelCount =
642 audio_channel_count_from_out_mask(mConfig.outputCfg.channels);
643 const bool auxType =
644 (mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY;
645
Andy Hungfa69ca32017-11-30 10:07:53 -0800646 // safeInputOutputSampleCount is 0 if the channel count between input and output
647 // buffers do not match. This prevents automatic accumulation or copying between the
648 // input and output effect buffers without an intermediary effect process.
649 // TODO: consider implementing channel conversion.
650 const size_t safeInputOutputSampleCount =
Andy Hungdd2e7a82018-10-31 14:19:13 -0700651 mInChannelCountRequested != mOutChannelCountRequested ? 0
652 : mOutChannelCountRequested * std::min(
Andy Hungfa69ca32017-11-30 10:07:53 -0800653 mConfig.inputCfg.buffer.frameCount,
654 mConfig.outputCfg.buffer.frameCount);
655 const auto accumulateInputToOutput = [this, safeInputOutputSampleCount]() {
656#ifdef FLOAT_EFFECT_CHAIN
657 accumulate_float(
658 mConfig.outputCfg.buffer.f32,
659 mConfig.inputCfg.buffer.f32,
660 safeInputOutputSampleCount);
661#else
662 accumulate_i16(
663 mConfig.outputCfg.buffer.s16,
664 mConfig.inputCfg.buffer.s16,
665 safeInputOutputSampleCount);
666#endif
667 };
668 const auto copyInputToOutput = [this, safeInputOutputSampleCount]() {
669#ifdef FLOAT_EFFECT_CHAIN
670 memcpy(
671 mConfig.outputCfg.buffer.f32,
672 mConfig.inputCfg.buffer.f32,
673 safeInputOutputSampleCount * sizeof(*mConfig.outputCfg.buffer.f32));
674
675#else
676 memcpy(
677 mConfig.outputCfg.buffer.s16,
678 mConfig.inputCfg.buffer.s16,
679 safeInputOutputSampleCount * sizeof(*mConfig.outputCfg.buffer.s16));
680#endif
681 };
682
Eric Laurentca7cc822012-11-19 14:55:58 -0800683 if (isProcessEnabled()) {
Eric Laurent6dd0fd92016-09-15 12:44:53 -0700684 int ret;
685 if (isProcessImplemented()) {
rago94a1ee82017-07-21 15:11:02 -0700686 if (auxType) {
687 // We overwrite the aux input buffer here and clear after processing.
Andy Hung9aad48c2017-11-29 10:29:19 -0800688 // aux input is always mono.
rago94a1ee82017-07-21 15:11:02 -0700689#ifdef FLOAT_EFFECT_CHAIN
690 if (mSupportsFloat) {
Andy Hung116a4982017-11-30 10:15:08 -0800691#ifndef FLOAT_AUX
rago94a1ee82017-07-21 15:11:02 -0700692 // Do in-place float conversion for auxiliary effect input buffer.
693 static_assert(sizeof(float) <= sizeof(int32_t),
694 "in-place conversion requires sizeof(float) <= sizeof(int32_t)");
695
Andy Hungfa69ca32017-11-30 10:07:53 -0800696 memcpy_to_float_from_q4_27(
697 mConfig.inputCfg.buffer.f32,
698 mConfig.inputCfg.buffer.s32,
699 mConfig.inputCfg.buffer.frameCount);
Andy Hung116a4982017-11-30 10:15:08 -0800700#endif // !FLOAT_AUX
Andy Hungfa69ca32017-11-30 10:07:53 -0800701 } else
Andy Hung116a4982017-11-30 10:15:08 -0800702#endif // FLOAT_EFFECT_CHAIN
Andy Hungfa69ca32017-11-30 10:07:53 -0800703 {
Andy Hung116a4982017-11-30 10:15:08 -0800704#ifdef FLOAT_AUX
705 memcpy_to_i16_from_float(
706 mConfig.inputCfg.buffer.s16,
707 mConfig.inputCfg.buffer.f32,
708 mConfig.inputCfg.buffer.frameCount);
709#else
Andy Hungfa69ca32017-11-30 10:07:53 -0800710 memcpy_to_i16_from_q4_27(
711 mConfig.inputCfg.buffer.s16,
rago94a1ee82017-07-21 15:11:02 -0700712 mConfig.inputCfg.buffer.s32,
Andy Hung5effdf62017-11-27 13:51:40 -0800713 mConfig.inputCfg.buffer.frameCount);
Andy Hung116a4982017-11-30 10:15:08 -0800714#endif
rago94a1ee82017-07-21 15:11:02 -0700715 }
rago94a1ee82017-07-21 15:11:02 -0700716 }
717#ifdef FLOAT_EFFECT_CHAIN
Andy Hung9aad48c2017-11-29 10:29:19 -0800718 sp<EffectBufferHalInterface> inBuffer = mInBuffer;
719 sp<EffectBufferHalInterface> outBuffer = mOutBuffer;
720
721 if (!auxType && mInChannelCountRequested != inChannelCount) {
722 adjust_channels(
723 inBuffer->audioBuffer()->f32, mInChannelCountRequested,
724 mInConversionBuffer->audioBuffer()->f32, inChannelCount,
725 sizeof(float),
726 sizeof(float)
727 * mInChannelCountRequested * mConfig.inputCfg.buffer.frameCount);
728 inBuffer = mInConversionBuffer;
729 }
730 if (mConfig.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE
731 && mOutChannelCountRequested != outChannelCount) {
732 adjust_selected_channels(
733 outBuffer->audioBuffer()->f32, mOutChannelCountRequested,
734 mOutConversionBuffer->audioBuffer()->f32, outChannelCount,
735 sizeof(float),
736 sizeof(float)
737 * mOutChannelCountRequested * mConfig.outputCfg.buffer.frameCount);
738 outBuffer = mOutConversionBuffer;
739 }
Andy Hungfa69ca32017-11-30 10:07:53 -0800740 if (!mSupportsFloat) { // convert input to int16_t as effect doesn't support float.
741 if (!auxType) {
Ytai Ben-Tsvi3de1bbf2020-01-21 16:41:17 -0800742 if (mInConversionBuffer == nullptr) {
Andy Hungfa69ca32017-11-30 10:07:53 -0800743 ALOGW("%s: mInConversionBuffer is null, bypassing", __func__);
744 goto data_bypass;
rago94a1ee82017-07-21 15:11:02 -0700745 }
Andy Hungfa69ca32017-11-30 10:07:53 -0800746 memcpy_to_i16_from_float(
747 mInConversionBuffer->audioBuffer()->s16,
Andy Hung9aad48c2017-11-29 10:29:19 -0800748 inBuffer->audioBuffer()->f32,
Andy Hungfa69ca32017-11-30 10:07:53 -0800749 inChannelCount * mConfig.inputCfg.buffer.frameCount);
Andy Hung9aad48c2017-11-29 10:29:19 -0800750 inBuffer = mInConversionBuffer;
rago94a1ee82017-07-21 15:11:02 -0700751 }
Andy Hungfa69ca32017-11-30 10:07:53 -0800752 if (mConfig.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE) {
Ytai Ben-Tsvi3de1bbf2020-01-21 16:41:17 -0800753 if (mOutConversionBuffer == nullptr) {
Andy Hungfa69ca32017-11-30 10:07:53 -0800754 ALOGW("%s: mOutConversionBuffer is null, bypassing", __func__);
755 goto data_bypass;
756 }
757 memcpy_to_i16_from_float(
758 mOutConversionBuffer->audioBuffer()->s16,
Andy Hung9aad48c2017-11-29 10:29:19 -0800759 outBuffer->audioBuffer()->f32,
Andy Hungfa69ca32017-11-30 10:07:53 -0800760 outChannelCount * mConfig.outputCfg.buffer.frameCount);
Andy Hung9aad48c2017-11-29 10:29:19 -0800761 outBuffer = mOutConversionBuffer;
rago94a1ee82017-07-21 15:11:02 -0700762 }
763 }
Andy Hungfa69ca32017-11-30 10:07:53 -0800764#endif
Mikhail Naganov022b9952017-01-04 16:36:51 -0800765 ret = mEffectInterface->process();
Andy Hungfa69ca32017-11-30 10:07:53 -0800766#ifdef FLOAT_EFFECT_CHAIN
767 if (!mSupportsFloat) { // convert output int16_t back to float.
Andy Hung9aad48c2017-11-29 10:29:19 -0800768 sp<EffectBufferHalInterface> target =
769 mOutChannelCountRequested != outChannelCount
770 ? mOutConversionBuffer : mOutBuffer;
771
Andy Hungfa69ca32017-11-30 10:07:53 -0800772 memcpy_to_float_from_i16(
Andy Hung9aad48c2017-11-29 10:29:19 -0800773 target->audioBuffer()->f32,
Andy Hungfa69ca32017-11-30 10:07:53 -0800774 mOutConversionBuffer->audioBuffer()->s16,
775 outChannelCount * mConfig.outputCfg.buffer.frameCount);
776 }
Andy Hung9aad48c2017-11-29 10:29:19 -0800777 if (mOutChannelCountRequested != outChannelCount) {
778 adjust_selected_channels(mOutConversionBuffer->audioBuffer()->f32, outChannelCount,
779 mOutBuffer->audioBuffer()->f32, mOutChannelCountRequested,
780 sizeof(float),
781 sizeof(float) * outChannelCount * mConfig.outputCfg.buffer.frameCount);
782 }
rago94a1ee82017-07-21 15:11:02 -0700783#endif
Eric Laurent6dd0fd92016-09-15 12:44:53 -0700784 } else {
rago94a1ee82017-07-21 15:11:02 -0700785#ifdef FLOAT_EFFECT_CHAIN
786 data_bypass:
787#endif
788 if (!auxType /* aux effects do not require data bypass */
Andy Hungfa69ca32017-11-30 10:07:53 -0800789 && mConfig.inputCfg.buffer.raw != mConfig.outputCfg.buffer.raw) {
Eric Laurent6dd0fd92016-09-15 12:44:53 -0700790 if (mConfig.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE) {
Andy Hungfa69ca32017-11-30 10:07:53 -0800791 accumulateInputToOutput();
Eric Laurent6dd0fd92016-09-15 12:44:53 -0700792 } else {
Andy Hungfa69ca32017-11-30 10:07:53 -0800793 copyInputToOutput();
Eric Laurent6dd0fd92016-09-15 12:44:53 -0700794 }
795 }
796 ret = -ENODATA;
797 }
Andy Hungfa69ca32017-11-30 10:07:53 -0800798
Eric Laurentca7cc822012-11-19 14:55:58 -0800799 // force transition to IDLE state when engine is ready
800 if (mState == STOPPED && ret == -ENODATA) {
801 mDisableWaitCnt = 1;
802 }
803
804 // clear auxiliary effect input buffer for next accumulation
rago94a1ee82017-07-21 15:11:02 -0700805 if (auxType) {
Andy Hung116a4982017-11-30 10:15:08 -0800806#ifdef FLOAT_AUX
807 const size_t size =
808 mConfig.inputCfg.buffer.frameCount * inChannelCount * sizeof(float);
809#else
rago94a1ee82017-07-21 15:11:02 -0700810 const size_t size =
811 mConfig.inputCfg.buffer.frameCount * inChannelCount * sizeof(int32_t);
Andy Hung116a4982017-11-30 10:15:08 -0800812#endif
rago94a1ee82017-07-21 15:11:02 -0700813 memset(mConfig.inputCfg.buffer.raw, 0, size);
Eric Laurentca7cc822012-11-19 14:55:58 -0800814 }
815 } else if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_INSERT &&
rago94a1ee82017-07-21 15:11:02 -0700816 // mInBuffer->audioBuffer()->raw != mOutBuffer->audioBuffer()->raw
Eric Laurentca7cc822012-11-19 14:55:58 -0800817 mConfig.inputCfg.buffer.raw != mConfig.outputCfg.buffer.raw) {
818 // If an insert effect is idle and input buffer is different from output buffer,
819 // accumulate input onto output
Eric Laurent6b446ce2019-12-13 10:56:31 -0800820 if (mCallback->activeTrackCnt() != 0) {
Andy Hunge8ac1b22018-10-31 14:22:35 -0700821 // similar handling with data_bypass above.
822 if (mConfig.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE) {
823 accumulateInputToOutput();
824 } else { // EFFECT_BUFFER_ACCESS_WRITE
825 copyInputToOutput();
826 }
Eric Laurentca7cc822012-11-19 14:55:58 -0800827 }
828 }
829}
830
831void AudioFlinger::EffectModule::reset_l()
832{
Mikhail Naganov1dc98672016-08-18 17:50:29 -0700833 if (mStatus != NO_ERROR || mEffectInterface == 0) {
Eric Laurentca7cc822012-11-19 14:55:58 -0800834 return;
835 }
Mikhail Naganov4a3d5c22016-08-15 13:47:42 -0700836 mEffectInterface->command(EFFECT_CMD_RESET, 0, NULL, 0, NULL);
Eric Laurentca7cc822012-11-19 14:55:58 -0800837}
838
839status_t AudioFlinger::EffectModule::configure()
840{
rago94a1ee82017-07-21 15:11:02 -0700841 ALOGVV("configure() started");
Eric Laurentd0ebb532013-04-02 16:41:41 -0700842 status_t status;
Eric Laurentd0ebb532013-04-02 16:41:41 -0700843 uint32_t size;
844 audio_channel_mask_t channelMask;
845
Mikhail Naganov1dc98672016-08-18 17:50:29 -0700846 if (mEffectInterface == 0) {
Eric Laurentd0ebb532013-04-02 16:41:41 -0700847 status = NO_INIT;
848 goto exit;
Eric Laurentca7cc822012-11-19 14:55:58 -0800849 }
850
Eric Laurentca7cc822012-11-19 14:55:58 -0800851 // TODO: handle configuration of effects replacing track process
Andy Hung9aad48c2017-11-29 10:29:19 -0800852 // TODO: handle configuration of input (record) SW effects above the HAL,
853 // similar to output EFFECT_FLAG_TYPE_INSERT/REPLACE,
854 // in which case input channel masks should be used here.
Eric Laurent6b446ce2019-12-13 10:56:31 -0800855 channelMask = mCallback->channelMask();
Andy Hung9aad48c2017-11-29 10:29:19 -0800856 mConfig.inputCfg.channels = channelMask;
Ricardo Garciad11da702015-05-28 12:14:12 -0700857 mConfig.outputCfg.channels = channelMask;
Eric Laurentca7cc822012-11-19 14:55:58 -0800858
859 if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
Andy Hung9aad48c2017-11-29 10:29:19 -0800860 if (mConfig.inputCfg.channels != AUDIO_CHANNEL_OUT_MONO) {
861 mConfig.inputCfg.channels = AUDIO_CHANNEL_OUT_MONO;
862 ALOGV("Overriding auxiliary effect input channels %#x as MONO",
863 mConfig.inputCfg.channels);
864 }
865#ifndef MULTICHANNEL_EFFECT_CHAIN
866 if (mConfig.outputCfg.channels != AUDIO_CHANNEL_OUT_STEREO) {
867 mConfig.outputCfg.channels = AUDIO_CHANNEL_OUT_STEREO;
868 ALOGV("Overriding auxiliary effect output channels %#x as STEREO",
869 mConfig.outputCfg.channels);
870 }
871#endif
Eric Laurentca7cc822012-11-19 14:55:58 -0800872 } else {
Andy Hung9aad48c2017-11-29 10:29:19 -0800873#ifndef MULTICHANNEL_EFFECT_CHAIN
Ricardo Garciad11da702015-05-28 12:14:12 -0700874 // TODO: Update this logic when multichannel effects are implemented.
875 // For offloaded tracks consider mono output as stereo for proper effect initialization
876 if (channelMask == AUDIO_CHANNEL_OUT_MONO) {
877 mConfig.inputCfg.channels = AUDIO_CHANNEL_OUT_STEREO;
878 mConfig.outputCfg.channels = AUDIO_CHANNEL_OUT_STEREO;
879 ALOGV("Overriding effect input and output as STEREO");
880 }
Andy Hung9aad48c2017-11-29 10:29:19 -0800881#endif
Eric Laurentca7cc822012-11-19 14:55:58 -0800882 }
jiabineb3bda02020-06-30 14:07:03 -0700883 if (isHapticGenerator()) {
884 audio_channel_mask_t hapticChannelMask = mCallback->hapticChannelMask();
885 mConfig.inputCfg.channels |= hapticChannelMask;
886 mConfig.outputCfg.channels |= hapticChannelMask;
887 }
Andy Hung9aad48c2017-11-29 10:29:19 -0800888 mInChannelCountRequested =
889 audio_channel_count_from_out_mask(mConfig.inputCfg.channels);
890 mOutChannelCountRequested =
891 audio_channel_count_from_out_mask(mConfig.outputCfg.channels);
Ricardo Garciad11da702015-05-28 12:14:12 -0700892
rago94a1ee82017-07-21 15:11:02 -0700893 mConfig.inputCfg.format = EFFECT_BUFFER_FORMAT;
894 mConfig.outputCfg.format = EFFECT_BUFFER_FORMAT;
Yuuki Yokoyamae17f8312017-05-26 19:06:33 +0900895
896 // Don't use sample rate for thread if effect isn't offloadable.
Daniel Bonnevier6bc62092019-12-06 09:14:56 +0100897 if (mCallback->isOffloadOrDirect() && !isOffloaded()) {
Yuuki Yokoyamae17f8312017-05-26 19:06:33 +0900898 mConfig.inputCfg.samplingRate = DEFAULT_OUTPUT_SAMPLE_RATE;
899 ALOGV("Overriding effect input as 48kHz");
900 } else {
Eric Laurent6b446ce2019-12-13 10:56:31 -0800901 mConfig.inputCfg.samplingRate = mCallback->sampleRate();
Yuuki Yokoyamae17f8312017-05-26 19:06:33 +0900902 }
Eric Laurentca7cc822012-11-19 14:55:58 -0800903 mConfig.outputCfg.samplingRate = mConfig.inputCfg.samplingRate;
904 mConfig.inputCfg.bufferProvider.cookie = NULL;
905 mConfig.inputCfg.bufferProvider.getBuffer = NULL;
906 mConfig.inputCfg.bufferProvider.releaseBuffer = NULL;
907 mConfig.outputCfg.bufferProvider.cookie = NULL;
908 mConfig.outputCfg.bufferProvider.getBuffer = NULL;
909 mConfig.outputCfg.bufferProvider.releaseBuffer = NULL;
910 mConfig.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ;
911 // Insert effect:
Eric Laurent3f75a5b2019-11-12 15:55:51 -0800912 // - in global sessions (e.g AUDIO_SESSION_OUTPUT_MIX),
Eric Laurentca7cc822012-11-19 14:55:58 -0800913 // always overwrites output buffer: input buffer == output buffer
914 // - in other sessions:
915 // last effect in the chain accumulates in output buffer: input buffer != output buffer
916 // other effect: overwrites output buffer: input buffer == output buffer
917 // Auxiliary effect:
918 // accumulates in output buffer: input buffer != output buffer
919 // Therefore: accumulate <=> input buffer != output buffer
920 if (mConfig.inputCfg.buffer.raw != mConfig.outputCfg.buffer.raw) {
921 mConfig.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_ACCUMULATE;
922 } else {
923 mConfig.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_WRITE;
924 }
925 mConfig.inputCfg.mask = EFFECT_CONFIG_ALL;
926 mConfig.outputCfg.mask = EFFECT_CONFIG_ALL;
Eric Laurent6b446ce2019-12-13 10:56:31 -0800927 mConfig.inputCfg.buffer.frameCount = mCallback->frameCount();
Eric Laurentca7cc822012-11-19 14:55:58 -0800928 mConfig.outputCfg.buffer.frameCount = mConfig.inputCfg.buffer.frameCount;
929
Eric Laurent6b446ce2019-12-13 10:56:31 -0800930 ALOGV("configure() %p chain %p buffer %p framecount %zu",
Ytai Ben-Tsvi3de1bbf2020-01-21 16:41:17 -0800931 this, mCallback->chain().promote().get(),
932 mConfig.inputCfg.buffer.raw, mConfig.inputCfg.buffer.frameCount);
Eric Laurentca7cc822012-11-19 14:55:58 -0800933
934 status_t cmdStatus;
Eric Laurentd0ebb532013-04-02 16:41:41 -0700935 size = sizeof(int);
Mikhail Naganov4a3d5c22016-08-15 13:47:42 -0700936 status = mEffectInterface->command(EFFECT_CMD_SET_CONFIG,
Andy Hung9aad48c2017-11-29 10:29:19 -0800937 sizeof(mConfig),
Mikhail Naganov4a3d5c22016-08-15 13:47:42 -0700938 &mConfig,
939 &size,
940 &cmdStatus);
rago94a1ee82017-07-21 15:11:02 -0700941 if (status == NO_ERROR) {
Eric Laurentca7cc822012-11-19 14:55:58 -0800942 status = cmdStatus;
943 }
Andy Hung9aad48c2017-11-29 10:29:19 -0800944
945#ifdef MULTICHANNEL_EFFECT_CHAIN
946 if (status != NO_ERROR &&
Eric Laurent6b446ce2019-12-13 10:56:31 -0800947 mCallback->isOutput() &&
Andy Hung9aad48c2017-11-29 10:29:19 -0800948 (mConfig.inputCfg.channels != AUDIO_CHANNEL_OUT_STEREO
949 || mConfig.outputCfg.channels != AUDIO_CHANNEL_OUT_STEREO)) {
950 // Older effects may require exact STEREO position mask.
Andy Hung01b32722018-05-18 13:52:02 -0700951 if (mConfig.inputCfg.channels != AUDIO_CHANNEL_OUT_STEREO
952 && (mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) != EFFECT_FLAG_TYPE_AUXILIARY) {
Andy Hung9aad48c2017-11-29 10:29:19 -0800953 ALOGV("Overriding effect input channels %#x as STEREO", mConfig.inputCfg.channels);
954 mConfig.inputCfg.channels = AUDIO_CHANNEL_OUT_STEREO;
955 }
956 if (mConfig.outputCfg.channels != AUDIO_CHANNEL_OUT_STEREO) {
957 ALOGV("Overriding effect output channels %#x as STEREO", mConfig.outputCfg.channels);
958 mConfig.outputCfg.channels = AUDIO_CHANNEL_OUT_STEREO;
959 }
960 size = sizeof(int);
rago94a1ee82017-07-21 15:11:02 -0700961 status = mEffectInterface->command(EFFECT_CMD_SET_CONFIG,
Andy Hung9aad48c2017-11-29 10:29:19 -0800962 sizeof(mConfig),
rago94a1ee82017-07-21 15:11:02 -0700963 &mConfig,
964 &size,
965 &cmdStatus);
966 if (status == NO_ERROR) {
967 status = cmdStatus;
Andy Hung9aad48c2017-11-29 10:29:19 -0800968 }
969 }
970#endif
971
972#ifdef FLOAT_EFFECT_CHAIN
973 if (status == NO_ERROR) {
974 mSupportsFloat = true;
975 }
976
977 if (status != NO_ERROR) {
978 ALOGV("EFFECT_CMD_SET_CONFIG failed with float format, retry with int16_t.");
979 mConfig.inputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
980 mConfig.outputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
981 size = sizeof(int);
982 status = mEffectInterface->command(EFFECT_CMD_SET_CONFIG,
983 sizeof(mConfig),
984 &mConfig,
985 &size,
986 &cmdStatus);
987 if (status == NO_ERROR) {
988 status = cmdStatus;
989 }
990 if (status == NO_ERROR) {
rago94a1ee82017-07-21 15:11:02 -0700991 mSupportsFloat = false;
992 ALOGVV("config worked with 16 bit");
993 } else {
994 ALOGE("%s failed %d with int16_t (as well as float)", __func__, status);
Eric Laurentca7cc822012-11-19 14:55:58 -0800995 }
rago94a1ee82017-07-21 15:11:02 -0700996 }
997#endif
Eric Laurentca7cc822012-11-19 14:55:58 -0800998
rago94a1ee82017-07-21 15:11:02 -0700999 if (status == NO_ERROR) {
1000 // Establish Buffer strategy
1001 setInBuffer(mInBuffer);
1002 setOutBuffer(mOutBuffer);
1003
1004 // Update visualizer latency
1005 if (memcmp(&mDescriptor.type, SL_IID_VISUALIZATION, sizeof(effect_uuid_t)) == 0) {
1006 uint32_t buf32[sizeof(effect_param_t) / sizeof(uint32_t) + 2];
1007 effect_param_t *p = (effect_param_t *)buf32;
1008
1009 p->psize = sizeof(uint32_t);
1010 p->vsize = sizeof(uint32_t);
1011 size = sizeof(int);
1012 *(int32_t *)p->data = VISUALIZER_PARAM_LATENCY;
1013
Eric Laurent6b446ce2019-12-13 10:56:31 -08001014 uint32_t latency = mCallback->latency();
rago94a1ee82017-07-21 15:11:02 -07001015
1016 *((int32_t *)p->data + 1)= latency;
1017 mEffectInterface->command(EFFECT_CMD_SET_PARAM,
1018 sizeof(effect_param_t) + 8,
1019 &buf32,
1020 &size,
1021 &cmdStatus);
1022 }
Eric Laurentca7cc822012-11-19 14:55:58 -08001023 }
1024
Andy Hung05083ac2017-12-14 15:00:28 -08001025 // mConfig.outputCfg.buffer.frameCount cannot be zero.
1026 mMaxDisableWaitCnt = (uint32_t)std::max(
1027 (uint64_t)1, // mMaxDisableWaitCnt must be greater than zero.
1028 (uint64_t)MAX_DISABLE_TIME_MS * mConfig.outputCfg.samplingRate
1029 / ((uint64_t)1000 * mConfig.outputCfg.buffer.frameCount));
Eric Laurentca7cc822012-11-19 14:55:58 -08001030
Eric Laurentd0ebb532013-04-02 16:41:41 -07001031exit:
Andy Hung6f88dc42017-12-13 16:19:39 -08001032 // TODO: consider clearing mConfig on error.
Eric Laurentd0ebb532013-04-02 16:41:41 -07001033 mStatus = status;
rago94a1ee82017-07-21 15:11:02 -07001034 ALOGVV("configure ended");
Eric Laurentca7cc822012-11-19 14:55:58 -08001035 return status;
1036}
1037
1038status_t AudioFlinger::EffectModule::init()
1039{
1040 Mutex::Autolock _l(mLock);
Mikhail Naganov1dc98672016-08-18 17:50:29 -07001041 if (mEffectInterface == 0) {
Eric Laurentca7cc822012-11-19 14:55:58 -08001042 return NO_INIT;
1043 }
1044 status_t cmdStatus;
1045 uint32_t size = sizeof(status_t);
Mikhail Naganov4a3d5c22016-08-15 13:47:42 -07001046 status_t status = mEffectInterface->command(EFFECT_CMD_INIT,
1047 0,
1048 NULL,
1049 &size,
1050 &cmdStatus);
Eric Laurentca7cc822012-11-19 14:55:58 -08001051 if (status == 0) {
1052 status = cmdStatus;
1053 }
1054 return status;
1055}
1056
Eric Laurent1b928682014-10-02 19:41:47 -07001057void AudioFlinger::EffectModule::addEffectToHal_l()
1058{
1059 if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC ||
1060 (mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_POST_PROC) {
Eric Laurent6b446ce2019-12-13 10:56:31 -08001061 (void)mCallback->addEffectToHal(mEffectInterface);
Eric Laurent1b928682014-10-02 19:41:47 -07001062 }
1063}
1064
Eric Laurentfa1e1232016-08-02 19:01:49 -07001065// start() must be called with PlaybackThread::mLock or EffectChain::mLock held
Eric Laurentca7cc822012-11-19 14:55:58 -08001066status_t AudioFlinger::EffectModule::start()
1067{
Eric Laurentfa1e1232016-08-02 19:01:49 -07001068 status_t status;
1069 {
1070 Mutex::Autolock _l(mLock);
1071 status = start_l();
Eric Laurentfa1e1232016-08-02 19:01:49 -07001072 }
Eric Laurent6b446ce2019-12-13 10:56:31 -08001073 if (status == NO_ERROR) {
1074 mCallback->resetVolume();
Eric Laurentfa1e1232016-08-02 19:01:49 -07001075 }
1076 return status;
Eric Laurentca7cc822012-11-19 14:55:58 -08001077}
1078
1079status_t AudioFlinger::EffectModule::start_l()
1080{
Mikhail Naganov1dc98672016-08-18 17:50:29 -07001081 if (mEffectInterface == 0) {
Eric Laurentca7cc822012-11-19 14:55:58 -08001082 return NO_INIT;
1083 }
Eric Laurentd0ebb532013-04-02 16:41:41 -07001084 if (mStatus != NO_ERROR) {
1085 return mStatus;
1086 }
Eric Laurentca7cc822012-11-19 14:55:58 -08001087 status_t cmdStatus;
1088 uint32_t size = sizeof(status_t);
Mikhail Naganov4a3d5c22016-08-15 13:47:42 -07001089 status_t status = mEffectInterface->command(EFFECT_CMD_ENABLE,
1090 0,
1091 NULL,
1092 &size,
1093 &cmdStatus);
Eric Laurentca7cc822012-11-19 14:55:58 -08001094 if (status == 0) {
1095 status = cmdStatus;
1096 }
Eric Laurentcb4b6e92014-10-01 14:26:10 -07001097 if (status == 0) {
Eric Laurent1b928682014-10-02 19:41:47 -07001098 addEffectToHal_l();
Eric Laurentca7cc822012-11-19 14:55:58 -08001099 }
1100 return status;
1101}
1102
1103status_t AudioFlinger::EffectModule::stop()
1104{
1105 Mutex::Autolock _l(mLock);
1106 return stop_l();
1107}
1108
1109status_t AudioFlinger::EffectModule::stop_l()
1110{
Mikhail Naganov1dc98672016-08-18 17:50:29 -07001111 if (mEffectInterface == 0) {
Eric Laurentca7cc822012-11-19 14:55:58 -08001112 return NO_INIT;
1113 }
Eric Laurentd0ebb532013-04-02 16:41:41 -07001114 if (mStatus != NO_ERROR) {
1115 return mStatus;
1116 }
Eric Laurentbfb1b832013-01-07 09:53:42 -08001117 status_t cmdStatus = NO_ERROR;
Eric Laurentca7cc822012-11-19 14:55:58 -08001118 uint32_t size = sizeof(status_t);
Tomoharu Kasahara1990bd42014-12-12 14:04:11 +09001119
1120 if (isVolumeControl() && isOffloadedOrDirect()) {
Tomoharu Kasahara1990bd42014-12-12 14:04:11 +09001121 // We have the EffectChain and EffectModule lock, permit a reentrant call to setVolume:
1122 // resetVolume_l --> setVolume_l --> EffectModule::setVolume
1123 mSetVolumeReentrantTid = gettid();
Eric Laurent6b446ce2019-12-13 10:56:31 -08001124 mCallback->resetVolume();
Tomoharu Kasahara1990bd42014-12-12 14:04:11 +09001125 mSetVolumeReentrantTid = INVALID_PID;
1126 }
1127
Mikhail Naganov4a3d5c22016-08-15 13:47:42 -07001128 status_t status = mEffectInterface->command(EFFECT_CMD_DISABLE,
1129 0,
1130 NULL,
1131 &size,
1132 &cmdStatus);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001133 if (status == NO_ERROR) {
Eric Laurentca7cc822012-11-19 14:55:58 -08001134 status = cmdStatus;
1135 }
Eric Laurentbfb1b832013-01-07 09:53:42 -08001136 if (status == NO_ERROR) {
Eric Laurent6b446ce2019-12-13 10:56:31 -08001137 status = removeEffectFromHal_l();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001138 }
1139 return status;
1140}
1141
Eric Laurent0d5a2ed2016-12-01 15:28:29 -08001142// must be called with EffectChain::mLock held
1143void AudioFlinger::EffectModule::release_l()
1144{
1145 if (mEffectInterface != 0) {
Eric Laurent6b446ce2019-12-13 10:56:31 -08001146 removeEffectFromHal_l();
Eric Laurent0d5a2ed2016-12-01 15:28:29 -08001147 // release effect engine
Mikhail Naganov022b9952017-01-04 16:36:51 -08001148 mEffectInterface->close();
Eric Laurent0d5a2ed2016-12-01 15:28:29 -08001149 mEffectInterface.clear();
1150 }
1151}
1152
Eric Laurent6b446ce2019-12-13 10:56:31 -08001153status_t AudioFlinger::EffectModule::removeEffectFromHal_l()
Eric Laurentbfb1b832013-01-07 09:53:42 -08001154{
1155 if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC ||
1156 (mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_POST_PROC) {
Eric Laurent6b446ce2019-12-13 10:56:31 -08001157 mCallback->removeEffectFromHal(mEffectInterface);
Eric Laurentca7cc822012-11-19 14:55:58 -08001158 }
Eric Laurentbfb1b832013-01-07 09:53:42 -08001159 return NO_ERROR;
Eric Laurentca7cc822012-11-19 14:55:58 -08001160}
1161
Andy Hunge4a1d912016-08-17 14:11:13 -07001162// round up delta valid if value and divisor are positive.
1163template <typename T>
1164static T roundUpDelta(const T &value, const T &divisor) {
1165 T remainder = value % divisor;
1166 return remainder == 0 ? 0 : divisor - remainder;
1167}
1168
Eric Laurentca7cc822012-11-19 14:55:58 -08001169status_t AudioFlinger::EffectModule::command(uint32_t cmdCode,
1170 uint32_t cmdSize,
1171 void *pCmdData,
1172 uint32_t *replySize,
1173 void *pReplyData)
1174{
1175 Mutex::Autolock _l(mLock);
Mikhail Naganov4a3d5c22016-08-15 13:47:42 -07001176 ALOGVV("command(), cmdCode: %d, mEffectInterface: %p", cmdCode, mEffectInterface.get());
Eric Laurentca7cc822012-11-19 14:55:58 -08001177
Mikhail Naganov1dc98672016-08-18 17:50:29 -07001178 if (mState == DESTROYED || mEffectInterface == 0) {
Eric Laurentca7cc822012-11-19 14:55:58 -08001179 return NO_INIT;
1180 }
Eric Laurentd0ebb532013-04-02 16:41:41 -07001181 if (mStatus != NO_ERROR) {
1182 return mStatus;
1183 }
Andy Hung110bc952016-06-20 15:22:52 -07001184 if (cmdCode == EFFECT_CMD_GET_PARAM &&
Andy Hung6660f122016-11-04 19:40:53 -07001185 (sizeof(effect_param_t) > cmdSize ||
1186 ((effect_param_t *)pCmdData)->psize > cmdSize
1187 - sizeof(effect_param_t))) {
1188 android_errorWriteLog(0x534e4554, "32438594");
Andy Hungb3456642016-11-28 13:50:21 -08001189 android_errorWriteLog(0x534e4554, "33003822");
1190 return -EINVAL;
1191 }
1192 if (cmdCode == EFFECT_CMD_GET_PARAM &&
1193 (*replySize < sizeof(effect_param_t) ||
1194 ((effect_param_t *)pCmdData)->psize > *replySize - sizeof(effect_param_t))) {
1195 android_errorWriteLog(0x534e4554, "29251553");
Andy Hung6660f122016-11-04 19:40:53 -07001196 return -EINVAL;
1197 }
ragoe2759072016-11-22 18:02:48 -08001198 if (cmdCode == EFFECT_CMD_GET_PARAM &&
1199 (sizeof(effect_param_t) > *replySize
1200 || ((effect_param_t *)pCmdData)->psize > *replySize
1201 - sizeof(effect_param_t)
1202 || ((effect_param_t *)pCmdData)->vsize > *replySize
1203 - sizeof(effect_param_t)
1204 - ((effect_param_t *)pCmdData)->psize
1205 || roundUpDelta(((effect_param_t *)pCmdData)->psize, (uint32_t)sizeof(int)) >
1206 *replySize
1207 - sizeof(effect_param_t)
1208 - ((effect_param_t *)pCmdData)->psize
1209 - ((effect_param_t *)pCmdData)->vsize)) {
1210 ALOGV("\tLVM_ERROR : EFFECT_CMD_GET_PARAM: reply size inconsistent");
1211 android_errorWriteLog(0x534e4554, "32705438");
1212 return -EINVAL;
1213 }
Andy Hunge4a1d912016-08-17 14:11:13 -07001214 if ((cmdCode == EFFECT_CMD_SET_PARAM
1215 || cmdCode == EFFECT_CMD_SET_PARAM_DEFERRED) && // DEFERRED not generally used
1216 (sizeof(effect_param_t) > cmdSize
1217 || ((effect_param_t *)pCmdData)->psize > cmdSize
1218 - sizeof(effect_param_t)
1219 || ((effect_param_t *)pCmdData)->vsize > cmdSize
1220 - sizeof(effect_param_t)
1221 - ((effect_param_t *)pCmdData)->psize
1222 || roundUpDelta(((effect_param_t *)pCmdData)->psize, (uint32_t)sizeof(int)) >
1223 cmdSize
1224 - sizeof(effect_param_t)
1225 - ((effect_param_t *)pCmdData)->psize
1226 - ((effect_param_t *)pCmdData)->vsize)) {
1227 android_errorWriteLog(0x534e4554, "30204301");
1228 return -EINVAL;
1229 }
Mikhail Naganov4a3d5c22016-08-15 13:47:42 -07001230 status_t status = mEffectInterface->command(cmdCode,
1231 cmdSize,
1232 pCmdData,
1233 replySize,
1234 pReplyData);
Eric Laurentca7cc822012-11-19 14:55:58 -08001235 if (cmdCode != EFFECT_CMD_GET_PARAM && status == NO_ERROR) {
1236 uint32_t size = (replySize == NULL) ? 0 : *replySize;
1237 for (size_t i = 1; i < mHandles.size(); i++) {
1238 EffectHandle *h = mHandles[i];
Eric Laurent0d5a2ed2016-12-01 15:28:29 -08001239 if (h != NULL && !h->disconnected()) {
Eric Laurentca7cc822012-11-19 14:55:58 -08001240 h->commandExecuted(cmdCode, cmdSize, pCmdData, size, pReplyData);
1241 }
1242 }
1243 }
1244 return status;
1245}
1246
Eric Laurentca7cc822012-11-19 14:55:58 -08001247bool AudioFlinger::EffectModule::isProcessEnabled() const
1248{
Eric Laurentd0ebb532013-04-02 16:41:41 -07001249 if (mStatus != NO_ERROR) {
1250 return false;
1251 }
1252
Eric Laurentca7cc822012-11-19 14:55:58 -08001253 switch (mState) {
1254 case RESTART:
1255 case ACTIVE:
1256 case STOPPING:
1257 case STOPPED:
1258 return true;
1259 case IDLE:
1260 case STARTING:
1261 case DESTROYED:
1262 default:
1263 return false;
1264 }
1265}
1266
Tomoharu Kasahara1990bd42014-12-12 14:04:11 +09001267bool AudioFlinger::EffectModule::isOffloadedOrDirect() const
1268{
Eric Laurent6b446ce2019-12-13 10:56:31 -08001269 return mCallback->isOffloadOrDirect();
Tomoharu Kasahara1990bd42014-12-12 14:04:11 +09001270}
1271
1272bool AudioFlinger::EffectModule::isVolumeControlEnabled() const
1273{
1274 return (isVolumeControl() && (isOffloadedOrDirect() ? isEnabled() : isProcessEnabled()));
1275}
1276
Mikhail Naganov022b9952017-01-04 16:36:51 -08001277void AudioFlinger::EffectModule::setInBuffer(const sp<EffectBufferHalInterface>& buffer) {
rago94a1ee82017-07-21 15:11:02 -07001278 ALOGVV("setInBuffer %p",(&buffer));
Andy Hung6f88dc42017-12-13 16:19:39 -08001279
1280 // mConfig.inputCfg.buffer.frameCount may be zero if configure() is not called yet.
Mikhail Naganov022b9952017-01-04 16:36:51 -08001281 if (buffer != 0) {
1282 mConfig.inputCfg.buffer.raw = buffer->audioBuffer()->raw;
1283 buffer->setFrameCount(mConfig.inputCfg.buffer.frameCount);
1284 } else {
1285 mConfig.inputCfg.buffer.raw = NULL;
1286 }
1287 mInBuffer = buffer;
Andy Hungc15aaee2017-11-27 17:02:40 -08001288 mEffectInterface->setInBuffer(buffer);
rago94a1ee82017-07-21 15:11:02 -07001289
1290#ifdef FLOAT_EFFECT_CHAIN
Andy Hungbded9c82017-11-30 18:47:35 -08001291 // aux effects do in place conversion to float - we don't allocate mInConversionBuffer.
rago94a1ee82017-07-21 15:11:02 -07001292 // Theoretically insert effects can also do in-place conversions (destroying
1293 // the original buffer) when the output buffer is identical to the input buffer,
1294 // but we don't optimize for it here.
1295 const bool auxType = (mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY;
Andy Hung9aad48c2017-11-29 10:29:19 -08001296 const uint32_t inChannelCount =
1297 audio_channel_count_from_out_mask(mConfig.inputCfg.channels);
1298 const bool formatMismatch = !mSupportsFloat || mInChannelCountRequested != inChannelCount;
Ytai Ben-Tsvi3de1bbf2020-01-21 16:41:17 -08001299 if (!auxType && formatMismatch && mInBuffer != nullptr) {
rago94a1ee82017-07-21 15:11:02 -07001300 // we need to translate - create hidl shared buffer and intercept
1301 const size_t inFrameCount = mConfig.inputCfg.buffer.frameCount;
Andy Hung9aad48c2017-11-29 10:29:19 -08001302 // Use FCC_2 in case mInChannelCountRequested is mono and the effect is stereo.
1303 const uint32_t inChannels = std::max((uint32_t)FCC_2, mInChannelCountRequested);
1304 const size_t size = inChannels * inFrameCount * std::max(sizeof(int16_t), sizeof(float));
rago94a1ee82017-07-21 15:11:02 -07001305
1306 ALOGV("%s: setInBuffer updating for inChannels:%d inFrameCount:%zu total size:%zu",
1307 __func__, inChannels, inFrameCount, size);
1308
Ytai Ben-Tsvi3de1bbf2020-01-21 16:41:17 -08001309 if (size > 0 && (mInConversionBuffer == nullptr
Andy Hungbded9c82017-11-30 18:47:35 -08001310 || size > mInConversionBuffer->getSize())) {
1311 mInConversionBuffer.clear();
1312 ALOGV("%s: allocating mInConversionBuffer %zu", __func__, size);
Eric Laurent6b446ce2019-12-13 10:56:31 -08001313 (void)mCallback->allocateHalBuffer(size, &mInConversionBuffer);
rago94a1ee82017-07-21 15:11:02 -07001314 }
Ytai Ben-Tsvi3de1bbf2020-01-21 16:41:17 -08001315 if (mInConversionBuffer != nullptr) {
Andy Hungbded9c82017-11-30 18:47:35 -08001316 mInConversionBuffer->setFrameCount(inFrameCount);
1317 mEffectInterface->setInBuffer(mInConversionBuffer);
rago94a1ee82017-07-21 15:11:02 -07001318 } else if (size > 0) {
Andy Hungbded9c82017-11-30 18:47:35 -08001319 ALOGE("%s cannot create mInConversionBuffer", __func__);
rago94a1ee82017-07-21 15:11:02 -07001320 }
1321 }
1322#endif
Mikhail Naganov022b9952017-01-04 16:36:51 -08001323}
1324
1325void AudioFlinger::EffectModule::setOutBuffer(const sp<EffectBufferHalInterface>& buffer) {
rago94a1ee82017-07-21 15:11:02 -07001326 ALOGVV("setOutBuffer %p",(&buffer));
Andy Hung6f88dc42017-12-13 16:19:39 -08001327
1328 // mConfig.outputCfg.buffer.frameCount may be zero if configure() is not called yet.
Mikhail Naganov022b9952017-01-04 16:36:51 -08001329 if (buffer != 0) {
1330 mConfig.outputCfg.buffer.raw = buffer->audioBuffer()->raw;
1331 buffer->setFrameCount(mConfig.outputCfg.buffer.frameCount);
1332 } else {
1333 mConfig.outputCfg.buffer.raw = NULL;
1334 }
1335 mOutBuffer = buffer;
Andy Hungc15aaee2017-11-27 17:02:40 -08001336 mEffectInterface->setOutBuffer(buffer);
rago94a1ee82017-07-21 15:11:02 -07001337
1338#ifdef FLOAT_EFFECT_CHAIN
Andy Hungbded9c82017-11-30 18:47:35 -08001339 // Note: Any effect that does not accumulate does not need mOutConversionBuffer and
rago94a1ee82017-07-21 15:11:02 -07001340 // can do in-place conversion from int16_t to float. We don't optimize here.
Andy Hung9aad48c2017-11-29 10:29:19 -08001341 const uint32_t outChannelCount =
1342 audio_channel_count_from_out_mask(mConfig.outputCfg.channels);
1343 const bool formatMismatch = !mSupportsFloat || mOutChannelCountRequested != outChannelCount;
Ytai Ben-Tsvi3de1bbf2020-01-21 16:41:17 -08001344 if (formatMismatch && mOutBuffer != nullptr) {
rago94a1ee82017-07-21 15:11:02 -07001345 const size_t outFrameCount = mConfig.outputCfg.buffer.frameCount;
Andy Hung9aad48c2017-11-29 10:29:19 -08001346 // Use FCC_2 in case mOutChannelCountRequested is mono and the effect is stereo.
1347 const uint32_t outChannels = std::max((uint32_t)FCC_2, mOutChannelCountRequested);
1348 const size_t size = outChannels * outFrameCount * std::max(sizeof(int16_t), sizeof(float));
rago94a1ee82017-07-21 15:11:02 -07001349
1350 ALOGV("%s: setOutBuffer updating for outChannels:%d outFrameCount:%zu total size:%zu",
1351 __func__, outChannels, outFrameCount, size);
1352
Ytai Ben-Tsvi3de1bbf2020-01-21 16:41:17 -08001353 if (size > 0 && (mOutConversionBuffer == nullptr
Andy Hungbded9c82017-11-30 18:47:35 -08001354 || size > mOutConversionBuffer->getSize())) {
1355 mOutConversionBuffer.clear();
1356 ALOGV("%s: allocating mOutConversionBuffer %zu", __func__, size);
Eric Laurent6b446ce2019-12-13 10:56:31 -08001357 (void)mCallback->allocateHalBuffer(size, &mOutConversionBuffer);
rago94a1ee82017-07-21 15:11:02 -07001358 }
Ytai Ben-Tsvi3de1bbf2020-01-21 16:41:17 -08001359 if (mOutConversionBuffer != nullptr) {
Andy Hungbded9c82017-11-30 18:47:35 -08001360 mOutConversionBuffer->setFrameCount(outFrameCount);
1361 mEffectInterface->setOutBuffer(mOutConversionBuffer);
rago94a1ee82017-07-21 15:11:02 -07001362 } else if (size > 0) {
Andy Hungbded9c82017-11-30 18:47:35 -08001363 ALOGE("%s cannot create mOutConversionBuffer", __func__);
rago94a1ee82017-07-21 15:11:02 -07001364 }
1365 }
1366#endif
Mikhail Naganov022b9952017-01-04 16:36:51 -08001367}
1368
Eric Laurentca7cc822012-11-19 14:55:58 -08001369status_t AudioFlinger::EffectModule::setVolume(uint32_t *left, uint32_t *right, bool controller)
1370{
Tomoharu Kasahara1990bd42014-12-12 14:04:11 +09001371 AutoLockReentrant _l(mLock, mSetVolumeReentrantTid);
Eric Laurentd0ebb532013-04-02 16:41:41 -07001372 if (mStatus != NO_ERROR) {
1373 return mStatus;
1374 }
Eric Laurentca7cc822012-11-19 14:55:58 -08001375 status_t status = NO_ERROR;
Eric Laurentca7cc822012-11-19 14:55:58 -08001376 // Send volume indication if EFFECT_FLAG_VOLUME_IND is set and read back altered volume
1377 // if controller flag is set (Note that controller == TRUE => EFFECT_FLAG_VOLUME_CTRL set)
1378 if (isProcessEnabled() &&
1379 ((mDescriptor.flags & EFFECT_FLAG_VOLUME_MASK) == EFFECT_FLAG_VOLUME_CTRL ||
Jasmine Cha934ecfb2019-01-23 18:19:14 +08001380 (mDescriptor.flags & EFFECT_FLAG_VOLUME_MASK) == EFFECT_FLAG_VOLUME_IND ||
1381 (mDescriptor.flags & EFFECT_FLAG_VOLUME_MASK) == EFFECT_FLAG_VOLUME_MONITOR)) {
Eric Laurentca7cc822012-11-19 14:55:58 -08001382 uint32_t volume[2];
1383 uint32_t *pVolume = NULL;
1384 uint32_t size = sizeof(volume);
1385 volume[0] = *left;
1386 volume[1] = *right;
1387 if (controller) {
1388 pVolume = volume;
1389 }
Mikhail Naganov4a3d5c22016-08-15 13:47:42 -07001390 status = mEffectInterface->command(EFFECT_CMD_SET_VOLUME,
1391 size,
1392 volume,
1393 &size,
1394 pVolume);
Eric Laurentca7cc822012-11-19 14:55:58 -08001395 if (controller && status == NO_ERROR && size == sizeof(volume)) {
1396 *left = volume[0];
1397 *right = volume[1];
1398 }
1399 }
1400 return status;
1401}
1402
Tomoharu Kasahara1990bd42014-12-12 14:04:11 +09001403void AudioFlinger::EffectChain::setVolumeForOutput_l(uint32_t left, uint32_t right)
1404{
Zhou Songd505c642020-02-20 16:35:37 +08001405 // for offload or direct thread, if the effect chain has non-offloadable
1406 // effect and any effect module within the chain has volume control, then
1407 // volume control is delegated to effect, otherwise, set volume to hal.
1408 if (mEffectCallback->isOffloadOrDirect() &&
1409 !(isNonOffloadableEnabled_l() && hasVolumeControlEnabled_l())) {
Tomoharu Kasahara1990bd42014-12-12 14:04:11 +09001410 float vol_l = (float)left / (1 << 24);
1411 float vol_r = (float)right / (1 << 24);
Eric Laurent6b446ce2019-12-13 10:56:31 -08001412 mEffectCallback->setVolumeForOutput(vol_l, vol_r);
Tomoharu Kasahara1990bd42014-12-12 14:04:11 +09001413 }
1414}
1415
jiabin8f278ee2019-11-11 12:16:27 -08001416status_t AudioFlinger::EffectModule::sendSetAudioDevicesCommand(
1417 const AudioDeviceTypeAddrVector &devices, uint32_t cmdCode)
Eric Laurentca7cc822012-11-19 14:55:58 -08001418{
jiabin8f278ee2019-11-11 12:16:27 -08001419 audio_devices_t deviceType = deviceTypesToBitMask(getAudioDeviceTypes(devices));
1420 if (deviceType == AUDIO_DEVICE_NONE) {
Eric Laurentca7cc822012-11-19 14:55:58 -08001421 return NO_ERROR;
1422 }
1423
1424 Mutex::Autolock _l(mLock);
Eric Laurentd0ebb532013-04-02 16:41:41 -07001425 if (mStatus != NO_ERROR) {
1426 return mStatus;
1427 }
Eric Laurentca7cc822012-11-19 14:55:58 -08001428 status_t status = NO_ERROR;
Eric Laurent7e1139c2013-06-06 18:29:01 -07001429 if ((mDescriptor.flags & EFFECT_FLAG_DEVICE_MASK) == EFFECT_FLAG_DEVICE_IND) {
Eric Laurentca7cc822012-11-19 14:55:58 -08001430 status_t cmdStatus;
1431 uint32_t size = sizeof(status_t);
jiabin8f278ee2019-11-11 12:16:27 -08001432 // FIXME: use audio device types and addresses when the hal interface is ready.
1433 status = mEffectInterface->command(cmdCode,
Mikhail Naganov4a3d5c22016-08-15 13:47:42 -07001434 sizeof(uint32_t),
jiabin8f278ee2019-11-11 12:16:27 -08001435 &deviceType,
Mikhail Naganov4a3d5c22016-08-15 13:47:42 -07001436 &size,
1437 &cmdStatus);
Eric Laurentca7cc822012-11-19 14:55:58 -08001438 }
1439 return status;
1440}
1441
jiabin8f278ee2019-11-11 12:16:27 -08001442status_t AudioFlinger::EffectModule::setDevices(const AudioDeviceTypeAddrVector &devices)
1443{
1444 return sendSetAudioDevicesCommand(devices, EFFECT_CMD_SET_DEVICE);
1445}
1446
1447status_t AudioFlinger::EffectModule::setInputDevice(const AudioDeviceTypeAddr &device)
1448{
1449 return sendSetAudioDevicesCommand({device}, EFFECT_CMD_SET_INPUT_DEVICE);
1450}
1451
Eric Laurentca7cc822012-11-19 14:55:58 -08001452status_t AudioFlinger::EffectModule::setMode(audio_mode_t mode)
1453{
1454 Mutex::Autolock _l(mLock);
Eric Laurentd0ebb532013-04-02 16:41:41 -07001455 if (mStatus != NO_ERROR) {
1456 return mStatus;
1457 }
Eric Laurentca7cc822012-11-19 14:55:58 -08001458 status_t status = NO_ERROR;
1459 if ((mDescriptor.flags & EFFECT_FLAG_AUDIO_MODE_MASK) == EFFECT_FLAG_AUDIO_MODE_IND) {
1460 status_t cmdStatus;
1461 uint32_t size = sizeof(status_t);
Mikhail Naganov4a3d5c22016-08-15 13:47:42 -07001462 status = mEffectInterface->command(EFFECT_CMD_SET_AUDIO_MODE,
1463 sizeof(audio_mode_t),
1464 &mode,
1465 &size,
1466 &cmdStatus);
Eric Laurentca7cc822012-11-19 14:55:58 -08001467 if (status == NO_ERROR) {
1468 status = cmdStatus;
1469 }
1470 }
1471 return status;
1472}
1473
1474status_t AudioFlinger::EffectModule::setAudioSource(audio_source_t source)
1475{
1476 Mutex::Autolock _l(mLock);
Eric Laurentd0ebb532013-04-02 16:41:41 -07001477 if (mStatus != NO_ERROR) {
1478 return mStatus;
1479 }
Eric Laurentca7cc822012-11-19 14:55:58 -08001480 status_t status = NO_ERROR;
1481 if ((mDescriptor.flags & EFFECT_FLAG_AUDIO_SOURCE_MASK) == EFFECT_FLAG_AUDIO_SOURCE_IND) {
1482 uint32_t size = 0;
Mikhail Naganov4a3d5c22016-08-15 13:47:42 -07001483 status = mEffectInterface->command(EFFECT_CMD_SET_AUDIO_SOURCE,
1484 sizeof(audio_source_t),
1485 &source,
1486 &size,
1487 NULL);
Eric Laurentca7cc822012-11-19 14:55:58 -08001488 }
1489 return status;
1490}
1491
Eric Laurent5baf2af2013-09-12 17:37:00 -07001492status_t AudioFlinger::EffectModule::setOffloaded(bool offloaded, audio_io_handle_t io)
1493{
1494 Mutex::Autolock _l(mLock);
1495 if (mStatus != NO_ERROR) {
1496 return mStatus;
1497 }
1498 status_t status = NO_ERROR;
1499 if ((mDescriptor.flags & EFFECT_FLAG_OFFLOAD_SUPPORTED) != 0) {
1500 status_t cmdStatus;
1501 uint32_t size = sizeof(status_t);
1502 effect_offload_param_t cmd;
1503
1504 cmd.isOffload = offloaded;
1505 cmd.ioHandle = io;
Mikhail Naganov4a3d5c22016-08-15 13:47:42 -07001506 status = mEffectInterface->command(EFFECT_CMD_OFFLOAD,
1507 sizeof(effect_offload_param_t),
1508 &cmd,
1509 &size,
1510 &cmdStatus);
Eric Laurent5baf2af2013-09-12 17:37:00 -07001511 if (status == NO_ERROR) {
1512 status = cmdStatus;
1513 }
1514 mOffloaded = (status == NO_ERROR) ? offloaded : false;
1515 } else {
1516 if (offloaded) {
1517 status = INVALID_OPERATION;
1518 }
1519 mOffloaded = false;
1520 }
1521 ALOGV("setOffloaded() offloaded %d io %d status %d", offloaded, io, status);
1522 return status;
1523}
1524
1525bool AudioFlinger::EffectModule::isOffloaded() const
1526{
1527 Mutex::Autolock _l(mLock);
1528 return mOffloaded;
1529}
1530
jiabineb3bda02020-06-30 14:07:03 -07001531/*static*/
1532bool AudioFlinger::EffectModule::isHapticGenerator(const effect_uuid_t *type) {
1533 return memcmp(type, FX_IID_HAPTICGENERATOR, sizeof(effect_uuid_t)) == 0;
1534}
1535
1536bool AudioFlinger::EffectModule::isHapticGenerator() const {
1537 return isHapticGenerator(&mDescriptor.type);
1538}
1539
Andy Hungbded9c82017-11-30 18:47:35 -08001540static std::string dumpInOutBuffer(bool isInput, const sp<EffectBufferHalInterface> &buffer) {
1541 std::stringstream ss;
1542
Ytai Ben-Tsvi3de1bbf2020-01-21 16:41:17 -08001543 if (buffer == nullptr) {
Andy Hungbded9c82017-11-30 18:47:35 -08001544 return "nullptr"; // make different than below
1545 } else if (buffer->externalData() != nullptr) {
1546 ss << (isInput ? buffer->externalData() : buffer->audioBuffer()->raw)
1547 << " -> "
1548 << (isInput ? buffer->audioBuffer()->raw : buffer->externalData());
1549 } else {
1550 ss << buffer->audioBuffer()->raw;
1551 }
1552 return ss.str();
1553}
Marco Nelissenb2208842014-02-07 14:00:50 -08001554
Eric Laurent41709552019-12-16 19:34:05 -08001555void AudioFlinger::EffectModule::dump(int fd, const Vector<String16>& args)
Eric Laurentca7cc822012-11-19 14:55:58 -08001556{
Eric Laurent41709552019-12-16 19:34:05 -08001557 EffectBase::dump(fd, args);
1558
Eric Laurentca7cc822012-11-19 14:55:58 -08001559 String8 result;
Eric Laurentca7cc822012-11-19 14:55:58 -08001560 bool locked = AudioFlinger::dumpTryLock(mLock);
Eric Laurentca7cc822012-11-19 14:55:58 -08001561
Eric Laurent41709552019-12-16 19:34:05 -08001562 result.append("\t\tStatus Engine:\n");
1563 result.appendFormat("\t\t%03d %p\n",
1564 mStatus, mEffectInterface.get());
Andy Hung9718d662017-12-22 17:57:39 -08001565
1566 result.appendFormat("\t\t- data: %s\n", mSupportsFloat ? "float" : "int16");
Eric Laurentca7cc822012-11-19 14:55:58 -08001567
1568 result.append("\t\t- Input configuration:\n");
Andy Hung9718d662017-12-22 17:57:39 -08001569 result.append("\t\t\tBuffer Frames Smp rate Channels Format\n");
1570 result.appendFormat("\t\t\t%p %05zu %05d %08x %6d (%s)\n",
1571 mConfig.inputCfg.buffer.raw,
Eric Laurentca7cc822012-11-19 14:55:58 -08001572 mConfig.inputCfg.buffer.frameCount,
1573 mConfig.inputCfg.samplingRate,
1574 mConfig.inputCfg.channels,
Marco Nelissenb2208842014-02-07 14:00:50 -08001575 mConfig.inputCfg.format,
Andy Hung9718d662017-12-22 17:57:39 -08001576 formatToString((audio_format_t)mConfig.inputCfg.format).c_str());
Eric Laurentca7cc822012-11-19 14:55:58 -08001577
1578 result.append("\t\t- Output configuration:\n");
1579 result.append("\t\t\tBuffer Frames Smp rate Channels Format\n");
Andy Hung9718d662017-12-22 17:57:39 -08001580 result.appendFormat("\t\t\t%p %05zu %05d %08x %6d (%s)\n",
Kévin PETIT377b2ec2014-02-03 12:35:36 +00001581 mConfig.outputCfg.buffer.raw,
Eric Laurentca7cc822012-11-19 14:55:58 -08001582 mConfig.outputCfg.buffer.frameCount,
1583 mConfig.outputCfg.samplingRate,
1584 mConfig.outputCfg.channels,
Marco Nelissenb2208842014-02-07 14:00:50 -08001585 mConfig.outputCfg.format,
Mikhail Naganov913d06c2016-11-01 12:49:22 -07001586 formatToString((audio_format_t)mConfig.outputCfg.format).c_str());
Eric Laurentca7cc822012-11-19 14:55:58 -08001587
rago94a1ee82017-07-21 15:11:02 -07001588#ifdef FLOAT_EFFECT_CHAIN
rago94a1ee82017-07-21 15:11:02 -07001589
Andy Hungbded9c82017-11-30 18:47:35 -08001590 result.appendFormat("\t\t- HAL buffers:\n"
1591 "\t\t\tIn(%s) InConversion(%s) Out(%s) OutConversion(%s)\n",
1592 dumpInOutBuffer(true /* isInput */, mInBuffer).c_str(),
1593 dumpInOutBuffer(true /* isInput */, mInConversionBuffer).c_str(),
1594 dumpInOutBuffer(false /* isInput */, mOutBuffer).c_str(),
1595 dumpInOutBuffer(false /* isInput */, mOutConversionBuffer).c_str());
rago94a1ee82017-07-21 15:11:02 -07001596#endif
1597
Eric Laurentca7cc822012-11-19 14:55:58 -08001598 write(fd, result.string(), result.length());
1599
Mikhail Naganov4d547672019-02-22 14:19:19 -08001600 if (mEffectInterface != 0) {
1601 dprintf(fd, "\tEffect ID %d HAL dump:\n", mId);
1602 (void)mEffectInterface->dump(fd);
1603 }
1604
Eric Laurentca7cc822012-11-19 14:55:58 -08001605 if (locked) {
1606 mLock.unlock();
1607 }
1608}
1609
1610// ----------------------------------------------------------------------------
1611// EffectHandle implementation
1612// ----------------------------------------------------------------------------
1613
1614#undef LOG_TAG
1615#define LOG_TAG "AudioFlinger::EffectHandle"
1616
Eric Laurent41709552019-12-16 19:34:05 -08001617AudioFlinger::EffectHandle::EffectHandle(const sp<EffectBase>& effect,
Eric Laurentca7cc822012-11-19 14:55:58 -08001618 const sp<AudioFlinger::Client>& client,
1619 const sp<IEffectClient>& effectClient,
1620 int32_t priority)
1621 : BnEffect(),
1622 mEffect(effect), mEffectClient(effectClient), mClient(client), mCblk(NULL),
Eric Laurent0d5a2ed2016-12-01 15:28:29 -08001623 mPriority(priority), mHasControl(false), mEnabled(false), mDisconnected(false)
Eric Laurentca7cc822012-11-19 14:55:58 -08001624{
Eric Laurentb82e6b72019-11-22 17:25:04 -08001625 ALOGV("constructor %p client %p", this, client.get());
Eric Laurentca7cc822012-11-19 14:55:58 -08001626
1627 if (client == 0) {
1628 return;
1629 }
1630 int bufOffset = ((sizeof(effect_param_cblk_t) - 1) / sizeof(int) + 1) * sizeof(int);
1631 mCblkMemory = client->heap()->allocate(EFFECT_PARAM_BUFFER_SIZE + bufOffset);
Glenn Kastene75da402013-11-20 13:54:52 -08001632 if (mCblkMemory == 0 ||
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -07001633 (mCblk = static_cast<effect_param_cblk_t *>(mCblkMemory->unsecurePointer())) == NULL) {
Glenn Kastenc42e9b42016-03-21 11:35:03 -07001634 ALOGE("not enough memory for Effect size=%zu", EFFECT_PARAM_BUFFER_SIZE +
Eric Laurentca7cc822012-11-19 14:55:58 -08001635 sizeof(effect_param_cblk_t));
Glenn Kastene75da402013-11-20 13:54:52 -08001636 mCblkMemory.clear();
Eric Laurentca7cc822012-11-19 14:55:58 -08001637 return;
1638 }
Glenn Kastene75da402013-11-20 13:54:52 -08001639 new(mCblk) effect_param_cblk_t();
1640 mBuffer = (uint8_t *)mCblk + bufOffset;
Eric Laurentca7cc822012-11-19 14:55:58 -08001641}
1642
1643AudioFlinger::EffectHandle::~EffectHandle()
1644{
1645 ALOGV("Destructor %p", this);
Eric Laurentca7cc822012-11-19 14:55:58 -08001646 disconnect(false);
1647}
1648
Glenn Kastene75da402013-11-20 13:54:52 -08001649status_t AudioFlinger::EffectHandle::initCheck()
1650{
1651 return mClient == 0 || mCblkMemory != 0 ? OK : NO_MEMORY;
1652}
1653
Eric Laurentca7cc822012-11-19 14:55:58 -08001654status_t AudioFlinger::EffectHandle::enable()
1655{
Eric Laurent0d5a2ed2016-12-01 15:28:29 -08001656 AutoMutex _l(mLock);
Eric Laurentca7cc822012-11-19 14:55:58 -08001657 ALOGV("enable %p", this);
Eric Laurent41709552019-12-16 19:34:05 -08001658 sp<EffectBase> effect = mEffect.promote();
Eric Laurent0d5a2ed2016-12-01 15:28:29 -08001659 if (effect == 0 || mDisconnected) {
1660 return DEAD_OBJECT;
1661 }
Eric Laurentca7cc822012-11-19 14:55:58 -08001662 if (!mHasControl) {
1663 return INVALID_OPERATION;
1664 }
Eric Laurentca7cc822012-11-19 14:55:58 -08001665
1666 if (mEnabled) {
1667 return NO_ERROR;
1668 }
1669
1670 mEnabled = true;
1671
Eric Laurent6c796322019-04-09 14:13:17 -07001672 status_t status = effect->updatePolicyState();
1673 if (status != NO_ERROR) {
1674 mEnabled = false;
1675 return status;
1676 }
1677
Eric Laurent6b446ce2019-12-13 10:56:31 -08001678 effect->checkSuspendOnEffectEnabled(true, false /*threadLocked*/);
Eric Laurentca7cc822012-11-19 14:55:58 -08001679
1680 // checkSuspendOnEffectEnabled() can suspend this same effect when enabled
Eric Laurent0d5a2ed2016-12-01 15:28:29 -08001681 if (effect->suspended()) {
Eric Laurentca7cc822012-11-19 14:55:58 -08001682 return NO_ERROR;
1683 }
1684
Eric Laurent6b446ce2019-12-13 10:56:31 -08001685 status = effect->setEnabled(true, true /*fromHandle*/);
Eric Laurentca7cc822012-11-19 14:55:58 -08001686 if (status != NO_ERROR) {
Eric Laurentca7cc822012-11-19 14:55:58 -08001687 mEnabled = false;
1688 }
1689 return status;
1690}
1691
1692status_t AudioFlinger::EffectHandle::disable()
1693{
1694 ALOGV("disable %p", this);
Eric Laurent0d5a2ed2016-12-01 15:28:29 -08001695 AutoMutex _l(mLock);
Eric Laurent41709552019-12-16 19:34:05 -08001696 sp<EffectBase> effect = mEffect.promote();
Eric Laurent0d5a2ed2016-12-01 15:28:29 -08001697 if (effect == 0 || mDisconnected) {
1698 return DEAD_OBJECT;
1699 }
Eric Laurentca7cc822012-11-19 14:55:58 -08001700 if (!mHasControl) {
1701 return INVALID_OPERATION;
1702 }
Eric Laurentca7cc822012-11-19 14:55:58 -08001703
1704 if (!mEnabled) {
1705 return NO_ERROR;
1706 }
1707 mEnabled = false;
1708
Eric Laurent6c796322019-04-09 14:13:17 -07001709 effect->updatePolicyState();
1710
Eric Laurent0d5a2ed2016-12-01 15:28:29 -08001711 if (effect->suspended()) {
Eric Laurentca7cc822012-11-19 14:55:58 -08001712 return NO_ERROR;
1713 }
1714
Eric Laurent6b446ce2019-12-13 10:56:31 -08001715 status_t status = effect->setEnabled(false, true /*fromHandle*/);
Eric Laurentca7cc822012-11-19 14:55:58 -08001716 return status;
1717}
1718
1719void AudioFlinger::EffectHandle::disconnect()
1720{
Eric Laurent0d5a2ed2016-12-01 15:28:29 -08001721 ALOGV("%s %p", __FUNCTION__, this);
Eric Laurentca7cc822012-11-19 14:55:58 -08001722 disconnect(true);
1723}
1724
1725void AudioFlinger::EffectHandle::disconnect(bool unpinIfLast)
1726{
Eric Laurent0d5a2ed2016-12-01 15:28:29 -08001727 AutoMutex _l(mLock);
1728 ALOGV("disconnect(%s) %p", unpinIfLast ? "true" : "false", this);
1729 if (mDisconnected) {
1730 if (unpinIfLast) {
1731 android_errorWriteLog(0x534e4554, "32707507");
1732 }
Eric Laurentca7cc822012-11-19 14:55:58 -08001733 return;
1734 }
Eric Laurent0d5a2ed2016-12-01 15:28:29 -08001735 mDisconnected = true;
Eric Laurent0d5a2ed2016-12-01 15:28:29 -08001736 {
Eric Laurent41709552019-12-16 19:34:05 -08001737 sp<EffectBase> effect = mEffect.promote();
Eric Laurent0d5a2ed2016-12-01 15:28:29 -08001738 if (effect != 0) {
Eric Laurent6b446ce2019-12-13 10:56:31 -08001739 if (effect->disconnectHandle(this, unpinIfLast) > 0) {
Eric Laurent6c796322019-04-09 14:13:17 -07001740 ALOGW("%s Effect handle %p disconnected after thread destruction",
1741 __func__, this);
1742 }
1743 effect->updatePolicyState();
Eric Laurentf10c7092016-12-06 17:09:56 -08001744 }
Eric Laurent0d5a2ed2016-12-01 15:28:29 -08001745 }
Eric Laurentca7cc822012-11-19 14:55:58 -08001746
Eric Laurentca7cc822012-11-19 14:55:58 -08001747 if (mClient != 0) {
1748 if (mCblk != NULL) {
1749 // unlike ~TrackBase(), mCblk is never a local new, so don't delete
1750 mCblk->~effect_param_cblk_t(); // destroy our shared-structure.
1751 }
1752 mCblkMemory.clear(); // free the shared memory before releasing the heap it belongs to
Eric Laurent021cf962014-05-13 10:18:14 -07001753 // Client destructor must run with AudioFlinger client mutex locked
1754 Mutex::Autolock _l(mClient->audioFlinger()->mClientLock);
Eric Laurentca7cc822012-11-19 14:55:58 -08001755 mClient.clear();
1756 }
1757}
1758
1759status_t AudioFlinger::EffectHandle::command(uint32_t cmdCode,
1760 uint32_t cmdSize,
1761 void *pCmdData,
1762 uint32_t *replySize,
1763 void *pReplyData)
1764{
1765 ALOGVV("command(), cmdCode: %d, mHasControl: %d, mEffect: %p",
Eric Laurent0d5a2ed2016-12-01 15:28:29 -08001766 cmdCode, mHasControl, mEffect.unsafe_get());
Eric Laurentca7cc822012-11-19 14:55:58 -08001767
Eric Laurentc7ab3092017-06-15 18:43:46 -07001768 // reject commands reserved for internal use by audio framework if coming from outside
1769 // of audioserver
1770 switch(cmdCode) {
1771 case EFFECT_CMD_ENABLE:
1772 case EFFECT_CMD_DISABLE:
1773 case EFFECT_CMD_SET_PARAM:
1774 case EFFECT_CMD_SET_PARAM_DEFERRED:
1775 case EFFECT_CMD_SET_PARAM_COMMIT:
1776 case EFFECT_CMD_GET_PARAM:
1777 break;
1778 default:
1779 if (cmdCode >= EFFECT_CMD_FIRST_PROPRIETARY) {
1780 break;
1781 }
1782 android_errorWriteLog(0x534e4554, "62019992");
1783 return BAD_VALUE;
1784 }
1785
Eric Laurent1ffc5852016-12-15 14:46:09 -08001786 if (cmdCode == EFFECT_CMD_ENABLE) {
1787 if (*replySize < sizeof(int)) {
1788 android_errorWriteLog(0x534e4554, "32095713");
1789 return BAD_VALUE;
1790 }
1791 *(int *)pReplyData = NO_ERROR;
1792 *replySize = sizeof(int);
1793 return enable();
1794 } else if (cmdCode == EFFECT_CMD_DISABLE) {
1795 if (*replySize < sizeof(int)) {
1796 android_errorWriteLog(0x534e4554, "32095713");
1797 return BAD_VALUE;
1798 }
1799 *(int *)pReplyData = NO_ERROR;
1800 *replySize = sizeof(int);
1801 return disable();
1802 }
1803
Eric Laurent0d5a2ed2016-12-01 15:28:29 -08001804 AutoMutex _l(mLock);
Eric Laurent41709552019-12-16 19:34:05 -08001805 sp<EffectBase> effect = mEffect.promote();
Eric Laurent0d5a2ed2016-12-01 15:28:29 -08001806 if (effect == 0 || mDisconnected) {
1807 return DEAD_OBJECT;
1808 }
Eric Laurentca7cc822012-11-19 14:55:58 -08001809 // only get parameter command is permitted for applications not controlling the effect
1810 if (!mHasControl && cmdCode != EFFECT_CMD_GET_PARAM) {
1811 return INVALID_OPERATION;
1812 }
Eric Laurentca7cc822012-11-19 14:55:58 -08001813
1814 // handle commands that are not forwarded transparently to effect engine
1815 if (cmdCode == EFFECT_CMD_SET_PARAM_COMMIT) {
Eric Laurentb82e6b72019-11-22 17:25:04 -08001816 if (mClient == 0) {
1817 return INVALID_OPERATION;
1818 }
1819
Eric Laurent1ffc5852016-12-15 14:46:09 -08001820 if (*replySize < sizeof(int)) {
1821 android_errorWriteLog(0x534e4554, "32095713");
1822 return BAD_VALUE;
1823 }
1824 *(int *)pReplyData = NO_ERROR;
1825 *replySize = sizeof(int);
1826
Eric Laurentca7cc822012-11-19 14:55:58 -08001827 // No need to trylock() here as this function is executed in the binder thread serving a
1828 // particular client process: no risk to block the whole media server process or mixer
1829 // threads if we are stuck here
1830 Mutex::Autolock _l(mCblk->lock);
Andy Hunga447a0f2016-11-15 17:19:58 -08001831 // keep local copy of index in case of client corruption b/32220769
1832 const uint32_t clientIndex = mCblk->clientIndex;
1833 const uint32_t serverIndex = mCblk->serverIndex;
1834 if (clientIndex > EFFECT_PARAM_BUFFER_SIZE ||
1835 serverIndex > EFFECT_PARAM_BUFFER_SIZE) {
Eric Laurentca7cc822012-11-19 14:55:58 -08001836 mCblk->serverIndex = 0;
1837 mCblk->clientIndex = 0;
1838 return BAD_VALUE;
1839 }
1840 status_t status = NO_ERROR;
Andy Hunga447a0f2016-11-15 17:19:58 -08001841 effect_param_t *param = NULL;
1842 for (uint32_t index = serverIndex; index < clientIndex;) {
1843 int *p = (int *)(mBuffer + index);
1844 const int size = *p++;
1845 if (size < 0
1846 || size > EFFECT_PARAM_BUFFER_SIZE
1847 || ((uint8_t *)p + size) > mBuffer + clientIndex) {
Eric Laurentca7cc822012-11-19 14:55:58 -08001848 ALOGW("command(): invalid parameter block size");
Andy Hunga447a0f2016-11-15 17:19:58 -08001849 status = BAD_VALUE;
Eric Laurentca7cc822012-11-19 14:55:58 -08001850 break;
1851 }
Andy Hunga447a0f2016-11-15 17:19:58 -08001852
1853 // copy to local memory in case of client corruption b/32220769
George Burgess IV80a22162020-01-05 20:06:15 -08001854 auto *newParam = (effect_param_t *)realloc(param, size);
1855 if (newParam == NULL) {
Andy Hunga447a0f2016-11-15 17:19:58 -08001856 ALOGW("command(): out of memory");
1857 status = NO_MEMORY;
1858 break;
Eric Laurentca7cc822012-11-19 14:55:58 -08001859 }
George Burgess IV80a22162020-01-05 20:06:15 -08001860 param = newParam;
Andy Hunga447a0f2016-11-15 17:19:58 -08001861 memcpy(param, p, size);
1862
1863 int reply = 0;
1864 uint32_t rsize = sizeof(reply);
Eric Laurent0d5a2ed2016-12-01 15:28:29 -08001865 status_t ret = effect->command(EFFECT_CMD_SET_PARAM,
Andy Hunga447a0f2016-11-15 17:19:58 -08001866 size,
1867 param,
Eric Laurentca7cc822012-11-19 14:55:58 -08001868 &rsize,
1869 &reply);
Andy Hunga447a0f2016-11-15 17:19:58 -08001870
1871 // verify shared memory: server index shouldn't change; client index can't go back.
1872 if (serverIndex != mCblk->serverIndex
1873 || clientIndex > mCblk->clientIndex) {
1874 android_errorWriteLog(0x534e4554, "32220769");
1875 status = BAD_VALUE;
1876 break;
1877 }
1878
Eric Laurentca7cc822012-11-19 14:55:58 -08001879 // stop at first error encountered
1880 if (ret != NO_ERROR) {
1881 status = ret;
1882 *(int *)pReplyData = reply;
1883 break;
1884 } else if (reply != NO_ERROR) {
1885 *(int *)pReplyData = reply;
1886 break;
1887 }
Andy Hunga447a0f2016-11-15 17:19:58 -08001888 index += size;
Eric Laurentca7cc822012-11-19 14:55:58 -08001889 }
Andy Hunga447a0f2016-11-15 17:19:58 -08001890 free(param);
Eric Laurentca7cc822012-11-19 14:55:58 -08001891 mCblk->serverIndex = 0;
1892 mCblk->clientIndex = 0;
1893 return status;
Eric Laurentca7cc822012-11-19 14:55:58 -08001894 }
1895
Eric Laurent0d5a2ed2016-12-01 15:28:29 -08001896 return effect->command(cmdCode, cmdSize, pCmdData, replySize, pReplyData);
Eric Laurentca7cc822012-11-19 14:55:58 -08001897}
1898
1899void AudioFlinger::EffectHandle::setControl(bool hasControl, bool signal, bool enabled)
1900{
1901 ALOGV("setControl %p control %d", this, hasControl);
1902
1903 mHasControl = hasControl;
1904 mEnabled = enabled;
1905
1906 if (signal && mEffectClient != 0) {
1907 mEffectClient->controlStatusChanged(hasControl);
1908 }
1909}
1910
1911void AudioFlinger::EffectHandle::commandExecuted(uint32_t cmdCode,
1912 uint32_t cmdSize,
1913 void *pCmdData,
1914 uint32_t replySize,
1915 void *pReplyData)
1916{
1917 if (mEffectClient != 0) {
1918 mEffectClient->commandExecuted(cmdCode, cmdSize, pCmdData, replySize, pReplyData);
1919 }
1920}
1921
1922
1923
1924void AudioFlinger::EffectHandle::setEnabled(bool enabled)
1925{
1926 if (mEffectClient != 0) {
1927 mEffectClient->enableStatusChanged(enabled);
1928 }
1929}
1930
1931status_t AudioFlinger::EffectHandle::onTransact(
1932 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
1933{
1934 return BnEffect::onTransact(code, data, reply, flags);
1935}
1936
1937
Glenn Kasten01d3acb2014-02-06 08:24:07 -08001938void AudioFlinger::EffectHandle::dumpToBuffer(char* buffer, size_t size)
Eric Laurentca7cc822012-11-19 14:55:58 -08001939{
1940 bool locked = mCblk != NULL && AudioFlinger::dumpTryLock(mCblk->lock);
1941
Marco Nelissenb2208842014-02-07 14:00:50 -08001942 snprintf(buffer, size, "\t\t\t%5d %5d %3s %3s %5u %5u\n",
Andy Hung4ef19fa2018-05-15 19:35:29 -07001943 (mClient == 0) ? getpid() : mClient->pid(),
Eric Laurentca7cc822012-11-19 14:55:58 -08001944 mPriority,
Marco Nelissenb2208842014-02-07 14:00:50 -08001945 mHasControl ? "yes" : "no",
1946 locked ? "yes" : "no",
Eric Laurentca7cc822012-11-19 14:55:58 -08001947 mCblk ? mCblk->clientIndex : 0,
1948 mCblk ? mCblk->serverIndex : 0
1949 );
1950
1951 if (locked) {
1952 mCblk->lock.unlock();
1953 }
1954}
1955
1956#undef LOG_TAG
1957#define LOG_TAG "AudioFlinger::EffectChain"
1958
Ytai Ben-Tsvi3de1bbf2020-01-21 16:41:17 -08001959AudioFlinger::EffectChain::EffectChain(const wp<ThreadBase>& thread,
1960 audio_session_t sessionId)
Eric Laurent6b446ce2019-12-13 10:56:31 -08001961 : mSessionId(sessionId), mActiveTrackCnt(0), mTrackCnt(0), mTailBufferCount(0),
Mikhail Naganov022b9952017-01-04 16:36:51 -08001962 mVolumeCtrlIdx(-1), mLeftVolume(UINT_MAX), mRightVolume(UINT_MAX),
Eric Laurent6b446ce2019-12-13 10:56:31 -08001963 mNewLeftVolume(UINT_MAX), mNewRightVolume(UINT_MAX),
Ytai Ben-Tsvi3de1bbf2020-01-21 16:41:17 -08001964 mEffectCallback(new EffectCallback(wp<EffectChain>(this), thread))
Eric Laurentca7cc822012-11-19 14:55:58 -08001965{
1966 mStrategy = AudioSystem::getStrategyForStream(AUDIO_STREAM_MUSIC);
Ytai Ben-Tsvi3de1bbf2020-01-21 16:41:17 -08001967 sp<ThreadBase> p = thread.promote();
1968 if (p == nullptr) {
Eric Laurentca7cc822012-11-19 14:55:58 -08001969 return;
1970 }
Ytai Ben-Tsvi3de1bbf2020-01-21 16:41:17 -08001971 mMaxTailBuffers = ((kProcessTailDurationMs * p->sampleRate()) / 1000) /
1972 p->frameCount();
Eric Laurentca7cc822012-11-19 14:55:58 -08001973}
1974
1975AudioFlinger::EffectChain::~EffectChain()
1976{
Eric Laurentca7cc822012-11-19 14:55:58 -08001977}
1978
1979// getEffectFromDesc_l() must be called with ThreadBase::mLock held
1980sp<AudioFlinger::EffectModule> AudioFlinger::EffectChain::getEffectFromDesc_l(
1981 effect_descriptor_t *descriptor)
1982{
1983 size_t size = mEffects.size();
1984
1985 for (size_t i = 0; i < size; i++) {
1986 if (memcmp(&mEffects[i]->desc().uuid, &descriptor->uuid, sizeof(effect_uuid_t)) == 0) {
1987 return mEffects[i];
1988 }
1989 }
1990 return 0;
1991}
1992
1993// getEffectFromId_l() must be called with ThreadBase::mLock held
1994sp<AudioFlinger::EffectModule> AudioFlinger::EffectChain::getEffectFromId_l(int id)
1995{
1996 size_t size = mEffects.size();
1997
1998 for (size_t i = 0; i < size; i++) {
1999 // by convention, return first effect if id provided is 0 (0 is never a valid id)
2000 if (id == 0 || mEffects[i]->id() == id) {
2001 return mEffects[i];
2002 }
2003 }
2004 return 0;
2005}
2006
2007// getEffectFromType_l() must be called with ThreadBase::mLock held
2008sp<AudioFlinger::EffectModule> AudioFlinger::EffectChain::getEffectFromType_l(
2009 const effect_uuid_t *type)
2010{
2011 size_t size = mEffects.size();
2012
2013 for (size_t i = 0; i < size; i++) {
2014 if (memcmp(&mEffects[i]->desc().type, type, sizeof(effect_uuid_t)) == 0) {
2015 return mEffects[i];
2016 }
2017 }
2018 return 0;
2019}
2020
Eric Laurent6c796322019-04-09 14:13:17 -07002021std::vector<int> AudioFlinger::EffectChain::getEffectIds()
2022{
2023 std::vector<int> ids;
2024 Mutex::Autolock _l(mLock);
2025 for (size_t i = 0; i < mEffects.size(); i++) {
2026 ids.push_back(mEffects[i]->id());
2027 }
2028 return ids;
2029}
2030
Eric Laurentca7cc822012-11-19 14:55:58 -08002031void AudioFlinger::EffectChain::clearInputBuffer()
2032{
2033 Mutex::Autolock _l(mLock);
Eric Laurent6b446ce2019-12-13 10:56:31 -08002034 clearInputBuffer_l();
Eric Laurentca7cc822012-11-19 14:55:58 -08002035}
2036
2037// Must be called with EffectChain::mLock locked
Eric Laurent6b446ce2019-12-13 10:56:31 -08002038void AudioFlinger::EffectChain::clearInputBuffer_l()
Eric Laurentca7cc822012-11-19 14:55:58 -08002039{
Eric Laurent6acd1d42017-01-04 14:23:29 -08002040 if (mInBuffer == NULL) {
2041 return;
2042 }
Ricardo Garcia726b6a72014-08-11 12:04:54 -07002043 const size_t frameSize =
Eric Laurent6b446ce2019-12-13 10:56:31 -08002044 audio_bytes_per_sample(EFFECT_BUFFER_FORMAT) * mEffectCallback->channelCount();
rago94a1ee82017-07-21 15:11:02 -07002045
Eric Laurent6b446ce2019-12-13 10:56:31 -08002046 memset(mInBuffer->audioBuffer()->raw, 0, mEffectCallback->frameCount() * frameSize);
Mikhail Naganov022b9952017-01-04 16:36:51 -08002047 mInBuffer->commit();
Eric Laurentca7cc822012-11-19 14:55:58 -08002048}
2049
2050// Must be called with EffectChain::mLock locked
2051void AudioFlinger::EffectChain::process_l()
2052{
Jean-Michel Trivifed62922013-09-25 18:50:33 -07002053 // never process effects when:
2054 // - on an OFFLOAD thread
2055 // - no more tracks are on the session and the effect tail has been rendered
Eric Laurent6b446ce2019-12-13 10:56:31 -08002056 bool doProcess = !mEffectCallback->isOffloadOrMmap();
Eric Laurent3f75a5b2019-11-12 15:55:51 -08002057 if (!audio_is_global_session(mSessionId)) {
Eric Laurentca7cc822012-11-19 14:55:58 -08002058 bool tracksOnSession = (trackCnt() != 0);
2059
2060 if (!tracksOnSession && mTailBufferCount == 0) {
2061 doProcess = false;
2062 }
2063
2064 if (activeTrackCnt() == 0) {
2065 // if no track is active and the effect tail has not been rendered,
2066 // the input buffer must be cleared here as the mixer process will not do it
2067 if (tracksOnSession || mTailBufferCount > 0) {
Eric Laurent6b446ce2019-12-13 10:56:31 -08002068 clearInputBuffer_l();
Eric Laurentca7cc822012-11-19 14:55:58 -08002069 if (mTailBufferCount > 0) {
2070 mTailBufferCount--;
2071 }
2072 }
2073 }
2074 }
2075
2076 size_t size = mEffects.size();
2077 if (doProcess) {
Mikhail Naganov022b9952017-01-04 16:36:51 -08002078 // Only the input and output buffers of the chain can be external,
2079 // and 'update' / 'commit' do nothing for allocated buffers, thus
2080 // it's not needed to consider any other buffers here.
2081 mInBuffer->update();
Mikhail Naganov06888802017-01-19 12:47:55 -08002082 if (mInBuffer->audioBuffer()->raw != mOutBuffer->audioBuffer()->raw) {
2083 mOutBuffer->update();
2084 }
Eric Laurentca7cc822012-11-19 14:55:58 -08002085 for (size_t i = 0; i < size; i++) {
2086 mEffects[i]->process();
2087 }
Mikhail Naganov06888802017-01-19 12:47:55 -08002088 mInBuffer->commit();
2089 if (mInBuffer->audioBuffer()->raw != mOutBuffer->audioBuffer()->raw) {
2090 mOutBuffer->commit();
2091 }
Eric Laurentca7cc822012-11-19 14:55:58 -08002092 }
Eric Laurentfa1e1232016-08-02 19:01:49 -07002093 bool doResetVolume = false;
Eric Laurentca7cc822012-11-19 14:55:58 -08002094 for (size_t i = 0; i < size; i++) {
Eric Laurentfa1e1232016-08-02 19:01:49 -07002095 doResetVolume = mEffects[i]->updateState() || doResetVolume;
2096 }
2097 if (doResetVolume) {
2098 resetVolume_l();
Eric Laurentca7cc822012-11-19 14:55:58 -08002099 }
2100}
2101
Eric Laurent0d5a2ed2016-12-01 15:28:29 -08002102// createEffect_l() must be called with ThreadBase::mLock held
2103status_t AudioFlinger::EffectChain::createEffect_l(sp<EffectModule>& effect,
Eric Laurent0d5a2ed2016-12-01 15:28:29 -08002104 effect_descriptor_t *desc,
2105 int id,
2106 audio_session_t sessionId,
2107 bool pinned)
2108{
2109 Mutex::Autolock _l(mLock);
Eric Laurentb82e6b72019-11-22 17:25:04 -08002110 effect = new EffectModule(mEffectCallback, desc, id, sessionId, pinned, AUDIO_PORT_HANDLE_NONE);
Eric Laurent0d5a2ed2016-12-01 15:28:29 -08002111 status_t lStatus = effect->status();
2112 if (lStatus == NO_ERROR) {
2113 lStatus = addEffect_ll(effect);
2114 }
2115 if (lStatus != NO_ERROR) {
2116 effect.clear();
2117 }
2118 return lStatus;
2119}
2120
2121// addEffect_l() must be called with ThreadBase::mLock held
Eric Laurentca7cc822012-11-19 14:55:58 -08002122status_t AudioFlinger::EffectChain::addEffect_l(const sp<EffectModule>& effect)
2123{
Eric Laurent0d5a2ed2016-12-01 15:28:29 -08002124 Mutex::Autolock _l(mLock);
2125 return addEffect_ll(effect);
2126}
2127// addEffect_l() must be called with ThreadBase::mLock and EffectChain::mLock held
2128status_t AudioFlinger::EffectChain::addEffect_ll(const sp<EffectModule>& effect)
2129{
Eric Laurentca7cc822012-11-19 14:55:58 -08002130 effect_descriptor_t desc = effect->desc();
2131 uint32_t insertPref = desc.flags & EFFECT_FLAG_INSERT_MASK;
2132
Eric Laurent6b446ce2019-12-13 10:56:31 -08002133 effect->setCallback(mEffectCallback);
Eric Laurentca7cc822012-11-19 14:55:58 -08002134
2135 if ((desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
2136 // Auxiliary effects are inserted at the beginning of mEffects vector as
2137 // they are processed first and accumulated in chain input buffer
2138 mEffects.insertAt(effect, 0);
2139
2140 // the input buffer for auxiliary effect contains mono samples in
2141 // 32 bit format. This is to avoid saturation in AudoMixer
2142 // accumulation stage. Saturation is done in EffectModule::process() before
2143 // calling the process in effect engine
Eric Laurent6b446ce2019-12-13 10:56:31 -08002144 size_t numSamples = mEffectCallback->frameCount();
Mikhail Naganov022b9952017-01-04 16:36:51 -08002145 sp<EffectBufferHalInterface> halBuffer;
rago94a1ee82017-07-21 15:11:02 -07002146#ifdef FLOAT_EFFECT_CHAIN
Eric Laurent6b446ce2019-12-13 10:56:31 -08002147 status_t result = mEffectCallback->allocateHalBuffer(
rago94a1ee82017-07-21 15:11:02 -07002148 numSamples * sizeof(float), &halBuffer);
2149#else
Eric Laurent6b446ce2019-12-13 10:56:31 -08002150 status_t result = mEffectCallback->allocateHalBuffer(
Mikhail Naganov022b9952017-01-04 16:36:51 -08002151 numSamples * sizeof(int32_t), &halBuffer);
rago94a1ee82017-07-21 15:11:02 -07002152#endif
Mikhail Naganov022b9952017-01-04 16:36:51 -08002153 if (result != OK) return result;
2154 effect->setInBuffer(halBuffer);
Eric Laurentca7cc822012-11-19 14:55:58 -08002155 // auxiliary effects output samples to chain input buffer for further processing
2156 // by insert effects
2157 effect->setOutBuffer(mInBuffer);
2158 } else {
2159 // Insert effects are inserted at the end of mEffects vector as they are processed
2160 // after track and auxiliary effects.
2161 // Insert effect order as a function of indicated preference:
2162 // if EFFECT_FLAG_INSERT_EXCLUSIVE, insert in first position or reject if
2163 // another effect is present
2164 // else if EFFECT_FLAG_INSERT_FIRST, insert in first position or after the
2165 // last effect claiming first position
2166 // else if EFFECT_FLAG_INSERT_LAST, insert in last position or before the
2167 // first effect claiming last position
2168 // else if EFFECT_FLAG_INSERT_ANY insert after first or before last
2169 // Reject insertion if an effect with EFFECT_FLAG_INSERT_EXCLUSIVE is
2170 // already present
2171
2172 size_t size = mEffects.size();
2173 size_t idx_insert = size;
2174 ssize_t idx_insert_first = -1;
2175 ssize_t idx_insert_last = -1;
2176
2177 for (size_t i = 0; i < size; i++) {
2178 effect_descriptor_t d = mEffects[i]->desc();
2179 uint32_t iMode = d.flags & EFFECT_FLAG_TYPE_MASK;
2180 uint32_t iPref = d.flags & EFFECT_FLAG_INSERT_MASK;
2181 if (iMode == EFFECT_FLAG_TYPE_INSERT) {
2182 // check invalid effect chaining combinations
2183 if (insertPref == EFFECT_FLAG_INSERT_EXCLUSIVE ||
2184 iPref == EFFECT_FLAG_INSERT_EXCLUSIVE) {
2185 ALOGW("addEffect_l() could not insert effect %s: exclusive conflict with %s",
2186 desc.name, d.name);
2187 return INVALID_OPERATION;
2188 }
2189 // remember position of first insert effect and by default
2190 // select this as insert position for new effect
2191 if (idx_insert == size) {
2192 idx_insert = i;
2193 }
2194 // remember position of last insert effect claiming
2195 // first position
2196 if (iPref == EFFECT_FLAG_INSERT_FIRST) {
2197 idx_insert_first = i;
2198 }
2199 // remember position of first insert effect claiming
2200 // last position
2201 if (iPref == EFFECT_FLAG_INSERT_LAST &&
2202 idx_insert_last == -1) {
2203 idx_insert_last = i;
2204 }
2205 }
2206 }
2207
2208 // modify idx_insert from first position if needed
2209 if (insertPref == EFFECT_FLAG_INSERT_LAST) {
2210 if (idx_insert_last != -1) {
2211 idx_insert = idx_insert_last;
2212 } else {
2213 idx_insert = size;
2214 }
2215 } else {
2216 if (idx_insert_first != -1) {
2217 idx_insert = idx_insert_first + 1;
2218 }
2219 }
2220
2221 // always read samples from chain input buffer
2222 effect->setInBuffer(mInBuffer);
2223
2224 // if last effect in the chain, output samples to chain
2225 // output buffer, otherwise to chain input buffer
2226 if (idx_insert == size) {
2227 if (idx_insert != 0) {
2228 mEffects[idx_insert-1]->setOutBuffer(mInBuffer);
2229 mEffects[idx_insert-1]->configure();
2230 }
2231 effect->setOutBuffer(mOutBuffer);
2232 } else {
2233 effect->setOutBuffer(mInBuffer);
2234 }
2235 mEffects.insertAt(effect, idx_insert);
2236
Glenn Kastenc42e9b42016-03-21 11:35:03 -07002237 ALOGV("addEffect_l() effect %p, added in chain %p at rank %zu", effect.get(), this,
Eric Laurentca7cc822012-11-19 14:55:58 -08002238 idx_insert);
2239 }
2240 effect->configure();
Eric Laurentd8365c52017-07-16 15:27:05 -07002241
Eric Laurentca7cc822012-11-19 14:55:58 -08002242 return NO_ERROR;
2243}
2244
Eric Laurent0d5a2ed2016-12-01 15:28:29 -08002245// removeEffect_l() must be called with ThreadBase::mLock held
2246size_t AudioFlinger::EffectChain::removeEffect_l(const sp<EffectModule>& effect,
2247 bool release)
Eric Laurentca7cc822012-11-19 14:55:58 -08002248{
2249 Mutex::Autolock _l(mLock);
2250 size_t size = mEffects.size();
2251 uint32_t type = effect->desc().flags & EFFECT_FLAG_TYPE_MASK;
2252
2253 for (size_t i = 0; i < size; i++) {
2254 if (effect == mEffects[i]) {
2255 // calling stop here will remove pre-processing effect from the audio HAL.
2256 // This is safe as we hold the EffectChain mutex which guarantees that we are not in
2257 // the middle of a read from audio HAL
2258 if (mEffects[i]->state() == EffectModule::ACTIVE ||
2259 mEffects[i]->state() == EffectModule::STOPPING) {
2260 mEffects[i]->stop();
2261 }
Eric Laurent0d5a2ed2016-12-01 15:28:29 -08002262 if (release) {
2263 mEffects[i]->release_l();
2264 }
2265
Mikhail Naganov022b9952017-01-04 16:36:51 -08002266 if (type != EFFECT_FLAG_TYPE_AUXILIARY) {
Eric Laurentca7cc822012-11-19 14:55:58 -08002267 if (i == size - 1 && i != 0) {
2268 mEffects[i - 1]->setOutBuffer(mOutBuffer);
2269 mEffects[i - 1]->configure();
2270 }
2271 }
2272 mEffects.removeAt(i);
Glenn Kastenc42e9b42016-03-21 11:35:03 -07002273 ALOGV("removeEffect_l() effect %p, removed from chain %p at rank %zu", effect.get(),
Eric Laurentca7cc822012-11-19 14:55:58 -08002274 this, i);
Eric Laurent0d5a2ed2016-12-01 15:28:29 -08002275
Eric Laurentca7cc822012-11-19 14:55:58 -08002276 break;
2277 }
2278 }
2279
2280 return mEffects.size();
2281}
2282
jiabin8f278ee2019-11-11 12:16:27 -08002283// setDevices_l() must be called with ThreadBase::mLock held
2284void AudioFlinger::EffectChain::setDevices_l(const AudioDeviceTypeAddrVector &devices)
Eric Laurentca7cc822012-11-19 14:55:58 -08002285{
2286 size_t size = mEffects.size();
2287 for (size_t i = 0; i < size; i++) {
jiabin8f278ee2019-11-11 12:16:27 -08002288 mEffects[i]->setDevices(devices);
2289 }
2290}
2291
2292// setInputDevice_l() must be called with ThreadBase::mLock held
2293void AudioFlinger::EffectChain::setInputDevice_l(const AudioDeviceTypeAddr &device)
2294{
2295 size_t size = mEffects.size();
2296 for (size_t i = 0; i < size; i++) {
2297 mEffects[i]->setInputDevice(device);
Eric Laurentca7cc822012-11-19 14:55:58 -08002298 }
2299}
2300
Eric Laurent0d5a2ed2016-12-01 15:28:29 -08002301// setMode_l() must be called with ThreadBase::mLock held
Eric Laurentca7cc822012-11-19 14:55:58 -08002302void AudioFlinger::EffectChain::setMode_l(audio_mode_t mode)
2303{
2304 size_t size = mEffects.size();
2305 for (size_t i = 0; i < size; i++) {
2306 mEffects[i]->setMode(mode);
2307 }
2308}
2309
Eric Laurent0d5a2ed2016-12-01 15:28:29 -08002310// setAudioSource_l() must be called with ThreadBase::mLock held
Eric Laurentca7cc822012-11-19 14:55:58 -08002311void AudioFlinger::EffectChain::setAudioSource_l(audio_source_t source)
2312{
2313 size_t size = mEffects.size();
2314 for (size_t i = 0; i < size; i++) {
2315 mEffects[i]->setAudioSource(source);
2316 }
2317}
2318
Zhou Songd505c642020-02-20 16:35:37 +08002319bool AudioFlinger::EffectChain::hasVolumeControlEnabled_l() const {
2320 for (const auto &effect : mEffects) {
2321 if (effect->isVolumeControlEnabled()) return true;
2322 }
2323 return false;
2324}
2325
Eric Laurent0d5a2ed2016-12-01 15:28:29 -08002326// setVolume_l() must be called with ThreadBase::mLock or EffectChain::mLock held
Eric Laurentfa1e1232016-08-02 19:01:49 -07002327bool AudioFlinger::EffectChain::setVolume_l(uint32_t *left, uint32_t *right, bool force)
Eric Laurentca7cc822012-11-19 14:55:58 -08002328{
2329 uint32_t newLeft = *left;
2330 uint32_t newRight = *right;
2331 bool hasControl = false;
2332 int ctrlIdx = -1;
2333 size_t size = mEffects.size();
2334
2335 // first update volume controller
2336 for (size_t i = size; i > 0; i--) {
Tomoharu Kasahara1990bd42014-12-12 14:04:11 +09002337 if (mEffects[i - 1]->isVolumeControlEnabled()) {
Eric Laurentca7cc822012-11-19 14:55:58 -08002338 ctrlIdx = i - 1;
2339 hasControl = true;
2340 break;
2341 }
2342 }
2343
Eric Laurentfa1e1232016-08-02 19:01:49 -07002344 if (!force && ctrlIdx == mVolumeCtrlIdx &&
Eric Laurentcb4b6e92014-10-01 14:26:10 -07002345 *left == mLeftVolume && *right == mRightVolume) {
Eric Laurentca7cc822012-11-19 14:55:58 -08002346 if (hasControl) {
2347 *left = mNewLeftVolume;
2348 *right = mNewRightVolume;
2349 }
2350 return hasControl;
2351 }
2352
2353 mVolumeCtrlIdx = ctrlIdx;
2354 mLeftVolume = newLeft;
2355 mRightVolume = newRight;
2356
2357 // second get volume update from volume controller
2358 if (ctrlIdx >= 0) {
2359 mEffects[ctrlIdx]->setVolume(&newLeft, &newRight, true);
2360 mNewLeftVolume = newLeft;
2361 mNewRightVolume = newRight;
2362 }
2363 // then indicate volume to all other effects in chain.
2364 // Pass altered volume to effects before volume controller
Jasmine Cha934ecfb2019-01-23 18:19:14 +08002365 // and requested volume to effects after controller or with volume monitor flag
Eric Laurentca7cc822012-11-19 14:55:58 -08002366 uint32_t lVol = newLeft;
2367 uint32_t rVol = newRight;
2368
2369 for (size_t i = 0; i < size; i++) {
2370 if ((int)i == ctrlIdx) {
2371 continue;
2372 }
2373 // this also works for ctrlIdx == -1 when there is no volume controller
2374 if ((int)i > ctrlIdx) {
2375 lVol = *left;
2376 rVol = *right;
2377 }
Jasmine Cha934ecfb2019-01-23 18:19:14 +08002378 // Pass requested volume directly if this is volume monitor module
2379 if (mEffects[i]->isVolumeMonitor()) {
2380 mEffects[i]->setVolume(left, right, false);
2381 } else {
2382 mEffects[i]->setVolume(&lVol, &rVol, false);
2383 }
Eric Laurentca7cc822012-11-19 14:55:58 -08002384 }
2385 *left = newLeft;
2386 *right = newRight;
2387
Tomoharu Kasahara1990bd42014-12-12 14:04:11 +09002388 setVolumeForOutput_l(*left, *right);
2389
Eric Laurentca7cc822012-11-19 14:55:58 -08002390 return hasControl;
2391}
2392
Eric Laurent0d5a2ed2016-12-01 15:28:29 -08002393// resetVolume_l() must be called with ThreadBase::mLock or EffectChain::mLock held
Eric Laurentfa1e1232016-08-02 19:01:49 -07002394void AudioFlinger::EffectChain::resetVolume_l()
2395{
Eric Laurente7449bf2016-08-03 18:44:07 -07002396 if ((mLeftVolume != UINT_MAX) && (mRightVolume != UINT_MAX)) {
2397 uint32_t left = mLeftVolume;
2398 uint32_t right = mRightVolume;
2399 (void)setVolume_l(&left, &right, true);
2400 }
Eric Laurentfa1e1232016-08-02 19:01:49 -07002401}
2402
jiabineb3bda02020-06-30 14:07:03 -07002403// containsHapticGeneratingEffect_l must be called with ThreadBase::mLock or EffectChain::mLock held
2404bool AudioFlinger::EffectChain::containsHapticGeneratingEffect_l()
2405{
2406 for (size_t i = 0; i < mEffects.size(); ++i) {
2407 if (mEffects[i]->isHapticGenerator()) {
2408 return true;
2409 }
2410 }
2411 return false;
2412}
2413
Eric Laurent1b928682014-10-02 19:41:47 -07002414void AudioFlinger::EffectChain::syncHalEffectsState()
2415{
2416 Mutex::Autolock _l(mLock);
2417 for (size_t i = 0; i < mEffects.size(); i++) {
2418 if (mEffects[i]->state() == EffectModule::ACTIVE ||
2419 mEffects[i]->state() == EffectModule::STOPPING) {
2420 mEffects[i]->addEffectToHal_l();
2421 }
2422 }
2423}
2424
Eric Laurentca7cc822012-11-19 14:55:58 -08002425void AudioFlinger::EffectChain::dump(int fd, const Vector<String16>& args)
2426{
Eric Laurentca7cc822012-11-19 14:55:58 -08002427 String8 result;
2428
Mikhail Naganov19740ca2019-03-28 12:25:01 -07002429 const size_t numEffects = mEffects.size();
2430 result.appendFormat(" %zu effects for session %d\n", numEffects, mSessionId);
Eric Laurentca7cc822012-11-19 14:55:58 -08002431
Marco Nelissenb2208842014-02-07 14:00:50 -08002432 if (numEffects) {
2433 bool locked = AudioFlinger::dumpTryLock(mLock);
2434 // failed to lock - AudioFlinger is probably deadlocked
2435 if (!locked) {
2436 result.append("\tCould not lock mutex:\n");
Eric Laurentca7cc822012-11-19 14:55:58 -08002437 }
Eric Laurentca7cc822012-11-19 14:55:58 -08002438
Andy Hungbded9c82017-11-30 18:47:35 -08002439 const std::string inBufferStr = dumpInOutBuffer(true /* isInput */, mInBuffer);
2440 const std::string outBufferStr = dumpInOutBuffer(false /* isInput */, mOutBuffer);
2441 result.appendFormat("\t%-*s%-*s Active tracks:\n",
2442 (int)inBufferStr.size(), "In buffer ",
2443 (int)outBufferStr.size(), "Out buffer ");
2444 result.appendFormat("\t%s %s %d\n",
2445 inBufferStr.c_str(), outBufferStr.c_str(), mActiveTrackCnt);
Marco Nelissenb2208842014-02-07 14:00:50 -08002446 write(fd, result.string(), result.size());
2447
2448 for (size_t i = 0; i < numEffects; ++i) {
2449 sp<EffectModule> effect = mEffects[i];
2450 if (effect != 0) {
2451 effect->dump(fd, args);
2452 }
2453 }
2454
2455 if (locked) {
2456 mLock.unlock();
2457 }
Mikhail Naganov19740ca2019-03-28 12:25:01 -07002458 } else {
2459 write(fd, result.string(), result.size());
Eric Laurentca7cc822012-11-19 14:55:58 -08002460 }
2461}
2462
2463// must be called with ThreadBase::mLock held
2464void AudioFlinger::EffectChain::setEffectSuspended_l(
2465 const effect_uuid_t *type, bool suspend)
2466{
2467 sp<SuspendedEffectDesc> desc;
2468 // use effect type UUID timelow as key as there is no real risk of identical
2469 // timeLow fields among effect type UUIDs.
2470 ssize_t index = mSuspendedEffects.indexOfKey(type->timeLow);
2471 if (suspend) {
2472 if (index >= 0) {
2473 desc = mSuspendedEffects.valueAt(index);
2474 } else {
2475 desc = new SuspendedEffectDesc();
2476 desc->mType = *type;
2477 mSuspendedEffects.add(type->timeLow, desc);
2478 ALOGV("setEffectSuspended_l() add entry for %08x", type->timeLow);
2479 }
Eric Laurentd8365c52017-07-16 15:27:05 -07002480
Eric Laurentca7cc822012-11-19 14:55:58 -08002481 if (desc->mRefCount++ == 0) {
2482 sp<EffectModule> effect = getEffectIfEnabled(type);
2483 if (effect != 0) {
2484 desc->mEffect = effect;
2485 effect->setSuspended(true);
Eric Laurent6b446ce2019-12-13 10:56:31 -08002486 effect->setEnabled(false, false /*fromHandle*/);
Eric Laurentca7cc822012-11-19 14:55:58 -08002487 }
2488 }
2489 } else {
2490 if (index < 0) {
2491 return;
2492 }
2493 desc = mSuspendedEffects.valueAt(index);
2494 if (desc->mRefCount <= 0) {
2495 ALOGW("setEffectSuspended_l() restore refcount should not be 0 %d", desc->mRefCount);
Eric Laurentd8365c52017-07-16 15:27:05 -07002496 desc->mRefCount = 0;
2497 return;
Eric Laurentca7cc822012-11-19 14:55:58 -08002498 }
2499 if (--desc->mRefCount == 0) {
2500 ALOGV("setEffectSuspended_l() remove entry for %08x", mSuspendedEffects.keyAt(index));
2501 if (desc->mEffect != 0) {
2502 sp<EffectModule> effect = desc->mEffect.promote();
2503 if (effect != 0) {
2504 effect->setSuspended(false);
2505 effect->lock();
2506 EffectHandle *handle = effect->controlHandle_l();
Eric Laurent0d5a2ed2016-12-01 15:28:29 -08002507 if (handle != NULL && !handle->disconnected()) {
Eric Laurentca7cc822012-11-19 14:55:58 -08002508 effect->setEnabled_l(handle->enabled());
2509 }
2510 effect->unlock();
2511 }
2512 desc->mEffect.clear();
2513 }
2514 mSuspendedEffects.removeItemsAt(index);
2515 }
2516 }
2517}
2518
2519// must be called with ThreadBase::mLock held
2520void AudioFlinger::EffectChain::setEffectSuspendedAll_l(bool suspend)
2521{
2522 sp<SuspendedEffectDesc> desc;
2523
2524 ssize_t index = mSuspendedEffects.indexOfKey((int)kKeyForSuspendAll);
2525 if (suspend) {
2526 if (index >= 0) {
2527 desc = mSuspendedEffects.valueAt(index);
2528 } else {
2529 desc = new SuspendedEffectDesc();
2530 mSuspendedEffects.add((int)kKeyForSuspendAll, desc);
2531 ALOGV("setEffectSuspendedAll_l() add entry for 0");
2532 }
2533 if (desc->mRefCount++ == 0) {
2534 Vector< sp<EffectModule> > effects;
2535 getSuspendEligibleEffects(effects);
2536 for (size_t i = 0; i < effects.size(); i++) {
2537 setEffectSuspended_l(&effects[i]->desc().type, true);
2538 }
2539 }
2540 } else {
2541 if (index < 0) {
2542 return;
2543 }
2544 desc = mSuspendedEffects.valueAt(index);
2545 if (desc->mRefCount <= 0) {
2546 ALOGW("setEffectSuspendedAll_l() restore refcount should not be 0 %d", desc->mRefCount);
2547 desc->mRefCount = 1;
2548 }
2549 if (--desc->mRefCount == 0) {
2550 Vector<const effect_uuid_t *> types;
2551 for (size_t i = 0; i < mSuspendedEffects.size(); i++) {
2552 if (mSuspendedEffects.keyAt(i) == (int)kKeyForSuspendAll) {
2553 continue;
2554 }
2555 types.add(&mSuspendedEffects.valueAt(i)->mType);
2556 }
2557 for (size_t i = 0; i < types.size(); i++) {
2558 setEffectSuspended_l(types[i], false);
2559 }
2560 ALOGV("setEffectSuspendedAll_l() remove entry for %08x",
2561 mSuspendedEffects.keyAt(index));
2562 mSuspendedEffects.removeItem((int)kKeyForSuspendAll);
2563 }
2564 }
2565}
2566
2567
2568// The volume effect is used for automated tests only
2569#ifndef OPENSL_ES_H_
2570static const effect_uuid_t SL_IID_VOLUME_ = { 0x09e8ede0, 0xddde, 0x11db, 0xb4f6,
2571 { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } };
2572const effect_uuid_t * const SL_IID_VOLUME = &SL_IID_VOLUME_;
2573#endif //OPENSL_ES_H_
2574
Eric Laurentd8365c52017-07-16 15:27:05 -07002575/* static */
2576bool AudioFlinger::EffectChain::isEffectEligibleForBtNrecSuspend(const effect_uuid_t *type)
2577{
2578 // Only NS and AEC are suspended when BtNRec is off
2579 if ((memcmp(type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0) ||
2580 (memcmp(type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2581 return true;
2582 }
2583 return false;
2584}
2585
Eric Laurentca7cc822012-11-19 14:55:58 -08002586bool AudioFlinger::EffectChain::isEffectEligibleForSuspend(const effect_descriptor_t& desc)
2587{
2588 // auxiliary effects and visualizer are never suspended on output mix
2589 if ((mSessionId == AUDIO_SESSION_OUTPUT_MIX) &&
2590 (((desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) ||
2591 (memcmp(&desc.type, SL_IID_VISUALIZATION, sizeof(effect_uuid_t)) == 0) ||
Ricardo Garciac2a3a822019-07-17 14:29:12 -07002592 (memcmp(&desc.type, SL_IID_VOLUME, sizeof(effect_uuid_t)) == 0) ||
2593 (memcmp(&desc.type, SL_IID_DYNAMICSPROCESSING, sizeof(effect_uuid_t)) == 0))) {
Eric Laurentca7cc822012-11-19 14:55:58 -08002594 return false;
2595 }
2596 return true;
2597}
2598
2599void AudioFlinger::EffectChain::getSuspendEligibleEffects(
2600 Vector< sp<AudioFlinger::EffectModule> > &effects)
2601{
2602 effects.clear();
2603 for (size_t i = 0; i < mEffects.size(); i++) {
2604 if (isEffectEligibleForSuspend(mEffects[i]->desc())) {
2605 effects.add(mEffects[i]);
2606 }
2607 }
2608}
2609
2610sp<AudioFlinger::EffectModule> AudioFlinger::EffectChain::getEffectIfEnabled(
2611 const effect_uuid_t *type)
2612{
2613 sp<EffectModule> effect = getEffectFromType_l(type);
2614 return effect != 0 && effect->isEnabled() ? effect : 0;
2615}
2616
2617void AudioFlinger::EffectChain::checkSuspendOnEffectEnabled(const sp<EffectModule>& effect,
2618 bool enabled)
2619{
2620 ssize_t index = mSuspendedEffects.indexOfKey(effect->desc().type.timeLow);
2621 if (enabled) {
2622 if (index < 0) {
2623 // if the effect is not suspend check if all effects are suspended
2624 index = mSuspendedEffects.indexOfKey((int)kKeyForSuspendAll);
2625 if (index < 0) {
2626 return;
2627 }
2628 if (!isEffectEligibleForSuspend(effect->desc())) {
2629 return;
2630 }
2631 setEffectSuspended_l(&effect->desc().type, enabled);
2632 index = mSuspendedEffects.indexOfKey(effect->desc().type.timeLow);
2633 if (index < 0) {
2634 ALOGW("checkSuspendOnEffectEnabled() Fx should be suspended here!");
2635 return;
2636 }
2637 }
2638 ALOGV("checkSuspendOnEffectEnabled() enable suspending fx %08x",
2639 effect->desc().type.timeLow);
2640 sp<SuspendedEffectDesc> desc = mSuspendedEffects.valueAt(index);
Eric Laurentd8365c52017-07-16 15:27:05 -07002641 // if effect is requested to suspended but was not yet enabled, suspend it now.
Eric Laurentca7cc822012-11-19 14:55:58 -08002642 if (desc->mEffect == 0) {
2643 desc->mEffect = effect;
Eric Laurent6b446ce2019-12-13 10:56:31 -08002644 effect->setEnabled(false, false /*fromHandle*/);
Eric Laurentca7cc822012-11-19 14:55:58 -08002645 effect->setSuspended(true);
2646 }
2647 } else {
2648 if (index < 0) {
2649 return;
2650 }
2651 ALOGV("checkSuspendOnEffectEnabled() disable restoring fx %08x",
2652 effect->desc().type.timeLow);
2653 sp<SuspendedEffectDesc> desc = mSuspendedEffects.valueAt(index);
2654 desc->mEffect.clear();
2655 effect->setSuspended(false);
2656 }
2657}
2658
Eric Laurent5baf2af2013-09-12 17:37:00 -07002659bool AudioFlinger::EffectChain::isNonOffloadableEnabled()
Eric Laurent813e2a72013-08-31 12:59:48 -07002660{
2661 Mutex::Autolock _l(mLock);
Shingo Kitajima1f8df9a2018-05-29 11:35:06 +09002662 return isNonOffloadableEnabled_l();
2663}
2664
2665bool AudioFlinger::EffectChain::isNonOffloadableEnabled_l()
2666{
Eric Laurent813e2a72013-08-31 12:59:48 -07002667 size_t size = mEffects.size();
2668 for (size_t i = 0; i < size; i++) {
Eric Laurent5baf2af2013-09-12 17:37:00 -07002669 if (mEffects[i]->isEnabled() && !mEffects[i]->isOffloadable()) {
Eric Laurent813e2a72013-08-31 12:59:48 -07002670 return true;
2671 }
2672 }
2673 return false;
2674}
2675
Eric Laurentaaa44472014-09-12 17:41:50 -07002676void AudioFlinger::EffectChain::setThread(const sp<ThreadBase>& thread)
2677{
2678 Mutex::Autolock _l(mLock);
Ytai Ben-Tsvi3de1bbf2020-01-21 16:41:17 -08002679 mEffectCallback->setThread(thread);
Eric Laurentaaa44472014-09-12 17:41:50 -07002680}
2681
Andy Hungd3bb0ad2016-10-11 17:16:43 -07002682void AudioFlinger::EffectChain::checkOutputFlagCompatibility(audio_output_flags_t *flags) const
2683{
2684 if ((*flags & AUDIO_OUTPUT_FLAG_RAW) != 0 && !isRawCompatible()) {
2685 *flags = (audio_output_flags_t)(*flags & ~AUDIO_OUTPUT_FLAG_RAW);
2686 }
2687 if ((*flags & AUDIO_OUTPUT_FLAG_FAST) != 0 && !isFastCompatible()) {
2688 *flags = (audio_output_flags_t)(*flags & ~AUDIO_OUTPUT_FLAG_FAST);
2689 }
2690}
2691
2692void AudioFlinger::EffectChain::checkInputFlagCompatibility(audio_input_flags_t *flags) const
2693{
2694 if ((*flags & AUDIO_INPUT_FLAG_RAW) != 0 && !isRawCompatible()) {
2695 *flags = (audio_input_flags_t)(*flags & ~AUDIO_INPUT_FLAG_RAW);
2696 }
2697 if ((*flags & AUDIO_INPUT_FLAG_FAST) != 0 && !isFastCompatible()) {
2698 *flags = (audio_input_flags_t)(*flags & ~AUDIO_INPUT_FLAG_FAST);
2699 }
2700}
2701
2702bool AudioFlinger::EffectChain::isRawCompatible() const
Eric Laurent4c415062016-06-17 16:14:16 -07002703{
2704 Mutex::Autolock _l(mLock);
Andy Hungd3bb0ad2016-10-11 17:16:43 -07002705 for (const auto &effect : mEffects) {
2706 if (effect->isProcessImplemented()) {
2707 return false;
Eric Laurent4c415062016-06-17 16:14:16 -07002708 }
2709 }
Andy Hungd3bb0ad2016-10-11 17:16:43 -07002710 // Allow effects without processing.
2711 return true;
2712}
2713
2714bool AudioFlinger::EffectChain::isFastCompatible() const
2715{
2716 Mutex::Autolock _l(mLock);
2717 for (const auto &effect : mEffects) {
2718 if (effect->isProcessImplemented()
2719 && effect->isImplementationSoftware()) {
2720 return false;
2721 }
2722 }
2723 // Allow effects without processing or hw accelerated effects.
2724 return true;
Eric Laurent4c415062016-06-17 16:14:16 -07002725}
2726
2727// isCompatibleWithThread_l() must be called with thread->mLock held
2728bool AudioFlinger::EffectChain::isCompatibleWithThread_l(const sp<ThreadBase>& thread) const
2729{
2730 Mutex::Autolock _l(mLock);
2731 for (size_t i = 0; i < mEffects.size(); i++) {
2732 if (thread->checkEffectCompatibility_l(&(mEffects[i]->desc()), mSessionId) != NO_ERROR) {
2733 return false;
2734 }
2735 }
2736 return true;
2737}
2738
Eric Laurent6b446ce2019-12-13 10:56:31 -08002739// EffectCallbackInterface implementation
2740status_t AudioFlinger::EffectChain::EffectCallback::createEffectHal(
2741 const effect_uuid_t *pEffectUuid, int32_t sessionId, int32_t deviceId,
2742 sp<EffectHalInterface> *effect) {
2743 status_t status = NO_INIT;
2744 sp<AudioFlinger> af = mAudioFlinger.promote();
2745 if (af == nullptr) {
2746 return status;
2747 }
2748 sp<EffectsFactoryHalInterface> effectsFactory = af->getEffectsFactory();
2749 if (effectsFactory != 0) {
2750 status = effectsFactory->createEffect(pEffectUuid, sessionId, io(), deviceId, effect);
2751 }
2752 return status;
2753}
2754
2755bool AudioFlinger::EffectChain::EffectCallback::updateOrphanEffectChains(
Eric Laurent41709552019-12-16 19:34:05 -08002756 const sp<AudioFlinger::EffectBase>& effect) {
Eric Laurent6b446ce2019-12-13 10:56:31 -08002757 sp<AudioFlinger> af = mAudioFlinger.promote();
2758 if (af == nullptr) {
2759 return false;
2760 }
Eric Laurent41709552019-12-16 19:34:05 -08002761 // in EffectChain context, an EffectBase is always from an EffectModule so static cast is safe
2762 return af->updateOrphanEffectChains(effect->asEffectModule());
Eric Laurent6b446ce2019-12-13 10:56:31 -08002763}
2764
2765status_t AudioFlinger::EffectChain::EffectCallback::allocateHalBuffer(
2766 size_t size, sp<EffectBufferHalInterface>* buffer) {
2767 sp<AudioFlinger> af = mAudioFlinger.promote();
2768 LOG_ALWAYS_FATAL_IF(af == nullptr, "allocateHalBuffer() could not retrieved audio flinger");
2769 return af->mEffectsFactoryHal->allocateBuffer(size, buffer);
2770}
2771
2772status_t AudioFlinger::EffectChain::EffectCallback::addEffectToHal(
2773 sp<EffectHalInterface> effect) {
2774 status_t result = NO_INIT;
2775 sp<ThreadBase> t = mThread.promote();
2776 if (t == nullptr) {
2777 return result;
2778 }
2779 sp <StreamHalInterface> st = t->stream();
2780 if (st == nullptr) {
2781 return result;
2782 }
2783 result = st->addEffect(effect);
2784 ALOGE_IF(result != OK, "Error when adding effect: %d", result);
2785 return result;
2786}
2787
2788status_t AudioFlinger::EffectChain::EffectCallback::removeEffectFromHal(
2789 sp<EffectHalInterface> effect) {
2790 status_t result = NO_INIT;
2791 sp<ThreadBase> t = mThread.promote();
2792 if (t == nullptr) {
2793 return result;
2794 }
2795 sp <StreamHalInterface> st = t->stream();
2796 if (st == nullptr) {
2797 return result;
2798 }
2799 result = st->removeEffect(effect);
2800 ALOGE_IF(result != OK, "Error when removing effect: %d", result);
2801 return result;
2802}
2803
2804audio_io_handle_t AudioFlinger::EffectChain::EffectCallback::io() const {
2805 sp<ThreadBase> t = mThread.promote();
2806 if (t == nullptr) {
2807 return AUDIO_IO_HANDLE_NONE;
2808 }
2809 return t->id();
2810}
2811
2812bool AudioFlinger::EffectChain::EffectCallback::isOutput() const {
2813 sp<ThreadBase> t = mThread.promote();
2814 if (t == nullptr) {
2815 return true;
2816 }
2817 return t->isOutput();
2818}
2819
2820bool AudioFlinger::EffectChain::EffectCallback::isOffload() const {
2821 sp<ThreadBase> t = mThread.promote();
2822 if (t == nullptr) {
2823 return false;
2824 }
2825 return t->type() == ThreadBase::OFFLOAD;
2826}
2827
2828bool AudioFlinger::EffectChain::EffectCallback::isOffloadOrDirect() const {
2829 sp<ThreadBase> t = mThread.promote();
2830 if (t == nullptr) {
2831 return false;
2832 }
2833 return t->type() == ThreadBase::OFFLOAD || t->type() == ThreadBase::DIRECT;
2834}
2835
2836bool AudioFlinger::EffectChain::EffectCallback::isOffloadOrMmap() const {
2837 sp<ThreadBase> t = mThread.promote();
2838 if (t == nullptr) {
2839 return false;
2840 }
Andy Hungea840382020-05-05 21:50:17 -07002841 return t->isOffloadOrMmap();
Eric Laurent6b446ce2019-12-13 10:56:31 -08002842}
2843
2844uint32_t AudioFlinger::EffectChain::EffectCallback::sampleRate() const {
2845 sp<ThreadBase> t = mThread.promote();
2846 if (t == nullptr) {
2847 return 0;
2848 }
2849 return t->sampleRate();
2850}
2851
2852audio_channel_mask_t AudioFlinger::EffectChain::EffectCallback::channelMask() const {
2853 sp<ThreadBase> t = mThread.promote();
2854 if (t == nullptr) {
2855 return AUDIO_CHANNEL_NONE;
2856 }
2857 return t->channelMask();
2858}
2859
2860uint32_t AudioFlinger::EffectChain::EffectCallback::channelCount() const {
2861 sp<ThreadBase> t = mThread.promote();
2862 if (t == nullptr) {
2863 return 0;
2864 }
2865 return t->channelCount();
2866}
2867
jiabineb3bda02020-06-30 14:07:03 -07002868audio_channel_mask_t AudioFlinger::EffectChain::EffectCallback::hapticChannelMask() const {
2869 sp<ThreadBase> t = mThread.promote();
2870 if (t == nullptr) {
2871 return AUDIO_CHANNEL_NONE;
2872 }
2873 return t->hapticChannelMask();
2874}
2875
Eric Laurent6b446ce2019-12-13 10:56:31 -08002876size_t AudioFlinger::EffectChain::EffectCallback::frameCount() const {
2877 sp<ThreadBase> t = mThread.promote();
2878 if (t == nullptr) {
2879 return 0;
2880 }
2881 return t->frameCount();
2882}
2883
2884uint32_t AudioFlinger::EffectChain::EffectCallback::latency() const {
2885 sp<ThreadBase> t = mThread.promote();
2886 if (t == nullptr) {
2887 return 0;
2888 }
2889 return t->latency_l();
2890}
2891
2892void AudioFlinger::EffectChain::EffectCallback::setVolumeForOutput(float left, float right) const {
2893 sp<ThreadBase> t = mThread.promote();
2894 if (t == nullptr) {
2895 return;
2896 }
2897 t->setVolumeForOutput_l(left, right);
2898}
2899
2900void AudioFlinger::EffectChain::EffectCallback::checkSuspendOnEffectEnabled(
Eric Laurent41709552019-12-16 19:34:05 -08002901 const sp<EffectBase>& effect, bool enabled, bool threadLocked) {
Eric Laurent6b446ce2019-12-13 10:56:31 -08002902 sp<ThreadBase> t = mThread.promote();
2903 if (t == nullptr) {
2904 return;
2905 }
2906 t->checkSuspendOnEffectEnabled(enabled, effect->sessionId(), threadLocked);
2907
2908 sp<EffectChain> c = mChain.promote();
2909 if (c == nullptr) {
2910 return;
2911 }
Eric Laurent41709552019-12-16 19:34:05 -08002912 // in EffectChain context, an EffectBase is always from an EffectModule so static cast is safe
2913 c->checkSuspendOnEffectEnabled(effect->asEffectModule(), enabled);
Eric Laurent6b446ce2019-12-13 10:56:31 -08002914}
2915
Eric Laurent41709552019-12-16 19:34:05 -08002916void AudioFlinger::EffectChain::EffectCallback::onEffectEnable(const sp<EffectBase>& effect) {
Eric Laurent6b446ce2019-12-13 10:56:31 -08002917 sp<ThreadBase> t = mThread.promote();
2918 if (t == nullptr) {
2919 return;
2920 }
Eric Laurent41709552019-12-16 19:34:05 -08002921 // in EffectChain context, an EffectBase is always from an EffectModule so static cast is safe
2922 t->onEffectEnable(effect->asEffectModule());
Eric Laurent6b446ce2019-12-13 10:56:31 -08002923}
2924
Eric Laurent41709552019-12-16 19:34:05 -08002925void AudioFlinger::EffectChain::EffectCallback::onEffectDisable(const sp<EffectBase>& effect) {
Eric Laurent6b446ce2019-12-13 10:56:31 -08002926 checkSuspendOnEffectEnabled(effect, false, false /*threadLocked*/);
2927
2928 sp<ThreadBase> t = mThread.promote();
2929 if (t == nullptr) {
2930 return;
2931 }
2932 t->onEffectDisable();
2933}
2934
2935bool AudioFlinger::EffectChain::EffectCallback::disconnectEffectHandle(EffectHandle *handle,
2936 bool unpinIfLast) {
2937 sp<ThreadBase> t = mThread.promote();
2938 if (t == nullptr) {
2939 return false;
2940 }
2941 t->disconnectEffectHandle(handle, unpinIfLast);
2942 return true;
2943}
2944
2945void AudioFlinger::EffectChain::EffectCallback::resetVolume() {
2946 sp<EffectChain> c = mChain.promote();
2947 if (c == nullptr) {
2948 return;
2949 }
2950 c->resetVolume_l();
2951
2952}
2953
2954uint32_t AudioFlinger::EffectChain::EffectCallback::strategy() const {
2955 sp<EffectChain> c = mChain.promote();
2956 if (c == nullptr) {
2957 return PRODUCT_STRATEGY_NONE;
2958 }
2959 return c->strategy();
2960}
2961
2962int32_t AudioFlinger::EffectChain::EffectCallback::activeTrackCnt() const {
2963 sp<EffectChain> c = mChain.promote();
2964 if (c == nullptr) {
2965 return 0;
2966 }
2967 return c->activeTrackCnt();
2968}
2969
Eric Laurentb82e6b72019-11-22 17:25:04 -08002970
2971#undef LOG_TAG
2972#define LOG_TAG "AudioFlinger::DeviceEffectProxy"
2973
2974status_t AudioFlinger::DeviceEffectProxy::setEnabled(bool enabled, bool fromHandle)
2975{
2976 status_t status = EffectBase::setEnabled(enabled, fromHandle);
2977 Mutex::Autolock _l(mProxyLock);
2978 if (status == NO_ERROR) {
2979 for (auto& handle : mEffectHandles) {
2980 if (enabled) {
2981 status = handle.second->enable();
2982 } else {
2983 status = handle.second->disable();
2984 }
2985 }
2986 }
2987 ALOGV("%s enable %d status %d", __func__, enabled, status);
2988 return status;
2989}
2990
2991status_t AudioFlinger::DeviceEffectProxy::init(
2992 const std::map <audio_patch_handle_t, PatchPanel::Patch>& patches) {
2993//For all audio patches
2994//If src or sink device match
2995//If the effect is HW accelerated
2996// if no corresponding effect module
2997// Create EffectModule: mHalEffect
2998//Create and attach EffectHandle
2999//If the effect is not HW accelerated and the patch sink or src is a mixer port
3000// Create Effect on patch input or output thread on session -1
3001//Add EffectHandle to EffectHandle map of Effect Proxy:
3002 ALOGV("%s device type %d address %s", __func__, mDevice.mType, mDevice.getAddress());
3003 status_t status = NO_ERROR;
3004 for (auto &patch : patches) {
3005 status = onCreatePatch(patch.first, patch.second);
3006 ALOGV("%s onCreatePatch status %d", __func__, status);
3007 if (status == BAD_VALUE) {
3008 return status;
3009 }
3010 }
3011 return status;
3012}
3013
3014status_t AudioFlinger::DeviceEffectProxy::onCreatePatch(
3015 audio_patch_handle_t patchHandle, const AudioFlinger::PatchPanel::Patch& patch) {
3016 status_t status = NAME_NOT_FOUND;
3017 sp<EffectHandle> handle;
3018 // only consider source[0] as this is the only "true" source of a patch
3019 status = checkPort(patch, &patch.mAudioPatch.sources[0], &handle);
3020 ALOGV("%s source checkPort status %d", __func__, status);
3021 for (uint32_t i = 0; i < patch.mAudioPatch.num_sinks && status == NAME_NOT_FOUND; i++) {
3022 status = checkPort(patch, &patch.mAudioPatch.sinks[i], &handle);
3023 ALOGV("%s sink %d checkPort status %d", __func__, i, status);
3024 }
3025 if (status == NO_ERROR || status == ALREADY_EXISTS) {
3026 Mutex::Autolock _l(mProxyLock);
3027 mEffectHandles.emplace(patchHandle, handle);
3028 }
3029 ALOGW_IF(status == BAD_VALUE,
3030 "%s cannot attach effect %s on patch %d", __func__, mDescriptor.name, patchHandle);
3031
3032 return status;
3033}
3034
3035status_t AudioFlinger::DeviceEffectProxy::checkPort(const PatchPanel::Patch& patch,
3036 const struct audio_port_config *port, sp <EffectHandle> *handle) {
3037
3038 ALOGV("%s type %d device type %d address %s device ID %d patch.isSoftware() %d",
3039 __func__, port->type, port->ext.device.type,
3040 port->ext.device.address, port->id, patch.isSoftware());
3041 if (port->type != AUDIO_PORT_TYPE_DEVICE || port->ext.device.type != mDevice.mType
3042 || port->ext.device.address != mDevice.mAddress) {
3043 return NAME_NOT_FOUND;
3044 }
3045 status_t status = NAME_NOT_FOUND;
3046
3047 if (mDescriptor.flags & EFFECT_FLAG_HW_ACC_TUNNEL) {
3048 Mutex::Autolock _l(mProxyLock);
3049 mDevicePort = *port;
3050 mHalEffect = new EffectModule(mMyCallback,
3051 const_cast<effect_descriptor_t *>(&mDescriptor),
3052 mMyCallback->newEffectId(), AUDIO_SESSION_DEVICE,
3053 false /* pinned */, port->id);
3054 if (audio_is_input_device(mDevice.mType)) {
3055 mHalEffect->setInputDevice(mDevice);
3056 } else {
3057 mHalEffect->setDevices({mDevice});
3058 }
3059 *handle = new EffectHandle(mHalEffect, nullptr, nullptr, 0 /*priority*/);
3060 status = (*handle)->initCheck();
3061 if (status == OK) {
3062 status = mHalEffect->addHandle((*handle).get());
3063 } else {
3064 mHalEffect.clear();
3065 mDevicePort.id = AUDIO_PORT_HANDLE_NONE;
3066 }
3067 } else if (patch.isSoftware() || patch.thread().promote() != nullptr) {
3068 sp <ThreadBase> thread;
3069 if (audio_port_config_has_input_direction(port)) {
3070 if (patch.isSoftware()) {
3071 thread = patch.mRecord.thread();
3072 } else {
3073 thread = patch.thread().promote();
3074 }
3075 } else {
3076 if (patch.isSoftware()) {
3077 thread = patch.mPlayback.thread();
3078 } else {
3079 thread = patch.thread().promote();
3080 }
3081 }
3082 int enabled;
3083 *handle = thread->createEffect_l(nullptr, nullptr, 0, AUDIO_SESSION_DEVICE,
3084 const_cast<effect_descriptor_t *>(&mDescriptor),
Eric Laurent2fe0acd2020-03-13 14:30:46 -07003085 &enabled, &status, false, false /*probe*/);
Eric Laurentb82e6b72019-11-22 17:25:04 -08003086 ALOGV("%s thread->createEffect_l status %d", __func__, status);
3087 } else {
3088 status = BAD_VALUE;
3089 }
3090 if (status == NO_ERROR || status == ALREADY_EXISTS) {
3091 if (isEnabled()) {
3092 (*handle)->enable();
3093 } else {
3094 (*handle)->disable();
3095 }
3096 }
3097 return status;
3098}
3099
3100void AudioFlinger::DeviceEffectProxy::onReleasePatch(audio_patch_handle_t patchHandle) {
3101 Mutex::Autolock _l(mProxyLock);
3102 mEffectHandles.erase(patchHandle);
3103}
3104
3105
3106size_t AudioFlinger::DeviceEffectProxy::removeEffect(const sp<EffectModule>& effect)
3107{
3108 Mutex::Autolock _l(mProxyLock);
3109 if (effect == mHalEffect) {
3110 mHalEffect.clear();
3111 mDevicePort.id = AUDIO_PORT_HANDLE_NONE;
3112 }
3113 return mHalEffect == nullptr ? 0 : 1;
3114}
3115
3116status_t AudioFlinger::DeviceEffectProxy::addEffectToHal(
3117 sp<EffectHalInterface> effect) {
3118 if (mHalEffect == nullptr) {
3119 return NO_INIT;
3120 }
3121 return mManagerCallback->addEffectToHal(
3122 mDevicePort.id, mDevicePort.ext.device.hw_module, effect);
3123}
3124
3125status_t AudioFlinger::DeviceEffectProxy::removeEffectFromHal(
3126 sp<EffectHalInterface> effect) {
3127 if (mHalEffect == nullptr) {
3128 return NO_INIT;
3129 }
3130 return mManagerCallback->removeEffectFromHal(
3131 mDevicePort.id, mDevicePort.ext.device.hw_module, effect);
3132}
3133
3134bool AudioFlinger::DeviceEffectProxy::isOutput() const {
3135 if (mDevicePort.id != AUDIO_PORT_HANDLE_NONE) {
3136 return mDevicePort.role == AUDIO_PORT_ROLE_SINK;
3137 }
3138 return true;
3139}
3140
3141uint32_t AudioFlinger::DeviceEffectProxy::sampleRate() const {
3142 if (mDevicePort.id != AUDIO_PORT_HANDLE_NONE &&
3143 (mDevicePort.config_mask & AUDIO_PORT_CONFIG_SAMPLE_RATE) != 0) {
3144 return mDevicePort.sample_rate;
3145 }
3146 return DEFAULT_OUTPUT_SAMPLE_RATE;
3147}
3148
3149audio_channel_mask_t AudioFlinger::DeviceEffectProxy::channelMask() const {
3150 if (mDevicePort.id != AUDIO_PORT_HANDLE_NONE &&
3151 (mDevicePort.config_mask & AUDIO_PORT_CONFIG_CHANNEL_MASK) != 0) {
3152 return mDevicePort.channel_mask;
3153 }
3154 return AUDIO_CHANNEL_OUT_STEREO;
3155}
3156
3157uint32_t AudioFlinger::DeviceEffectProxy::channelCount() const {
3158 if (isOutput()) {
3159 return audio_channel_count_from_out_mask(channelMask());
3160 }
3161 return audio_channel_count_from_in_mask(channelMask());
3162}
3163
3164void AudioFlinger::DeviceEffectProxy::dump(int fd, int spaces) {
3165 const Vector<String16> args;
3166 EffectBase::dump(fd, args);
3167
3168 const bool locked = dumpTryLock(mProxyLock);
3169 if (!locked) {
3170 String8 result("DeviceEffectProxy may be deadlocked\n");
3171 write(fd, result.string(), result.size());
3172 }
3173
3174 String8 outStr;
3175 if (mHalEffect != nullptr) {
3176 outStr.appendFormat("%*sHAL Effect Id: %d\n", spaces, "", mHalEffect->id());
3177 } else {
3178 outStr.appendFormat("%*sNO HAL Effect\n", spaces, "");
3179 }
3180 write(fd, outStr.string(), outStr.size());
3181 outStr.clear();
3182
3183 outStr.appendFormat("%*sSub Effects:\n", spaces, "");
3184 write(fd, outStr.string(), outStr.size());
3185 outStr.clear();
3186
3187 for (const auto& iter : mEffectHandles) {
3188 outStr.appendFormat("%*sEffect for patch handle %d:\n", spaces + 2, "", iter.first);
3189 write(fd, outStr.string(), outStr.size());
3190 outStr.clear();
3191 sp<EffectBase> effect = iter.second->effect().promote();
3192 if (effect != nullptr) {
3193 effect->dump(fd, args);
3194 }
3195 }
3196
3197 if (locked) {
3198 mLock.unlock();
3199 }
3200}
3201
3202#undef LOG_TAG
3203#define LOG_TAG "AudioFlinger::DeviceEffectProxy::ProxyCallback"
3204
3205int AudioFlinger::DeviceEffectProxy::ProxyCallback::newEffectId() {
3206 return mManagerCallback->newEffectId();
3207}
3208
3209
3210bool AudioFlinger::DeviceEffectProxy::ProxyCallback::disconnectEffectHandle(
3211 EffectHandle *handle, bool unpinIfLast) {
3212 sp<EffectBase> effectBase = handle->effect().promote();
3213 if (effectBase == nullptr) {
3214 return false;
3215 }
3216
3217 sp<EffectModule> effect = effectBase->asEffectModule();
3218 if (effect == nullptr) {
3219 return false;
3220 }
3221
3222 // restore suspended effects if the disconnected handle was enabled and the last one.
3223 bool remove = (effect->removeHandle(handle) == 0) && (!effect->isPinned() || unpinIfLast);
3224 if (remove) {
3225 sp<DeviceEffectProxy> proxy = mProxy.promote();
3226 if (proxy != nullptr) {
3227 proxy->removeEffect(effect);
3228 }
3229 if (handle->enabled()) {
3230 effectBase->checkSuspendOnEffectEnabled(false, false /*threadLocked*/);
3231 }
3232 }
3233 return true;
3234}
3235
3236status_t AudioFlinger::DeviceEffectProxy::ProxyCallback::createEffectHal(
3237 const effect_uuid_t *pEffectUuid, int32_t sessionId, int32_t deviceId,
3238 sp<EffectHalInterface> *effect) {
3239 return mManagerCallback->createEffectHal(pEffectUuid, sessionId, deviceId, effect);
3240}
3241
3242status_t AudioFlinger::DeviceEffectProxy::ProxyCallback::addEffectToHal(
3243 sp<EffectHalInterface> effect) {
3244 sp<DeviceEffectProxy> proxy = mProxy.promote();
3245 if (proxy == nullptr) {
3246 return NO_INIT;
3247 }
3248 return proxy->addEffectToHal(effect);
3249}
3250
3251status_t AudioFlinger::DeviceEffectProxy::ProxyCallback::removeEffectFromHal(
3252 sp<EffectHalInterface> effect) {
3253 sp<DeviceEffectProxy> proxy = mProxy.promote();
3254 if (proxy == nullptr) {
3255 return NO_INIT;
3256 }
3257 return proxy->addEffectToHal(effect);
3258}
3259
3260bool AudioFlinger::DeviceEffectProxy::ProxyCallback::isOutput() const {
3261 sp<DeviceEffectProxy> proxy = mProxy.promote();
3262 if (proxy == nullptr) {
3263 return true;
3264 }
3265 return proxy->isOutput();
3266}
3267
3268uint32_t AudioFlinger::DeviceEffectProxy::ProxyCallback::sampleRate() const {
3269 sp<DeviceEffectProxy> proxy = mProxy.promote();
3270 if (proxy == nullptr) {
3271 return DEFAULT_OUTPUT_SAMPLE_RATE;
3272 }
3273 return proxy->sampleRate();
3274}
3275
3276audio_channel_mask_t AudioFlinger::DeviceEffectProxy::ProxyCallback::channelMask() const {
3277 sp<DeviceEffectProxy> proxy = mProxy.promote();
3278 if (proxy == nullptr) {
3279 return AUDIO_CHANNEL_OUT_STEREO;
3280 }
3281 return proxy->channelMask();
3282}
3283
3284uint32_t AudioFlinger::DeviceEffectProxy::ProxyCallback::channelCount() const {
3285 sp<DeviceEffectProxy> proxy = mProxy.promote();
3286 if (proxy == nullptr) {
3287 return 2;
3288 }
3289 return proxy->channelCount();
3290}
3291
Glenn Kasten63238ef2015-03-02 15:50:29 -08003292} // namespace android