blob: 31d53119d3710329fb04cd0e3a4379581a8d0fae [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
jiabine70bc7f2020-06-30 22:07:55 -07001540status_t AudioFlinger::EffectModule::setHapticIntensity(int id, int intensity)
1541{
1542 if (mStatus != NO_ERROR) {
1543 return mStatus;
1544 }
1545 if (!isHapticGenerator()) {
1546 ALOGW("Should not set haptic intensity for effects that are not HapticGenerator");
1547 return INVALID_OPERATION;
1548 }
1549
1550 uint32_t buf32[sizeof(effect_param_t) / sizeof(uint32_t) + 3];
1551 effect_param_t *param = (effect_param_t*) buf32;
1552 param->psize = sizeof(int32_t);
1553 param->vsize = sizeof(int32_t) * 2;
1554 *(int32_t*)param->data = HG_PARAM_HAPTIC_INTENSITY;
1555 *((int32_t*)param->data + 1) = id;
1556 *((int32_t*)param->data + 2) = intensity;
1557 uint32_t size = sizeof(int32_t);
1558 status_t status = command(
1559 EFFECT_CMD_SET_PARAM, sizeof(effect_param_t) + param->psize + param->vsize,
1560 param, &size, &param->status);
1561 if (status == NO_ERROR) {
1562 status = param->status;
1563 }
1564 return status;
1565}
1566
Andy Hungbded9c82017-11-30 18:47:35 -08001567static std::string dumpInOutBuffer(bool isInput, const sp<EffectBufferHalInterface> &buffer) {
1568 std::stringstream ss;
1569
Ytai Ben-Tsvi3de1bbf2020-01-21 16:41:17 -08001570 if (buffer == nullptr) {
Andy Hungbded9c82017-11-30 18:47:35 -08001571 return "nullptr"; // make different than below
1572 } else if (buffer->externalData() != nullptr) {
1573 ss << (isInput ? buffer->externalData() : buffer->audioBuffer()->raw)
1574 << " -> "
1575 << (isInput ? buffer->audioBuffer()->raw : buffer->externalData());
1576 } else {
1577 ss << buffer->audioBuffer()->raw;
1578 }
1579 return ss.str();
1580}
Marco Nelissenb2208842014-02-07 14:00:50 -08001581
Eric Laurent41709552019-12-16 19:34:05 -08001582void AudioFlinger::EffectModule::dump(int fd, const Vector<String16>& args)
Eric Laurentca7cc822012-11-19 14:55:58 -08001583{
Eric Laurent41709552019-12-16 19:34:05 -08001584 EffectBase::dump(fd, args);
1585
Eric Laurentca7cc822012-11-19 14:55:58 -08001586 String8 result;
Eric Laurentca7cc822012-11-19 14:55:58 -08001587 bool locked = AudioFlinger::dumpTryLock(mLock);
Eric Laurentca7cc822012-11-19 14:55:58 -08001588
Eric Laurent41709552019-12-16 19:34:05 -08001589 result.append("\t\tStatus Engine:\n");
1590 result.appendFormat("\t\t%03d %p\n",
1591 mStatus, mEffectInterface.get());
Andy Hung9718d662017-12-22 17:57:39 -08001592
1593 result.appendFormat("\t\t- data: %s\n", mSupportsFloat ? "float" : "int16");
Eric Laurentca7cc822012-11-19 14:55:58 -08001594
1595 result.append("\t\t- Input configuration:\n");
Andy Hung9718d662017-12-22 17:57:39 -08001596 result.append("\t\t\tBuffer Frames Smp rate Channels Format\n");
1597 result.appendFormat("\t\t\t%p %05zu %05d %08x %6d (%s)\n",
1598 mConfig.inputCfg.buffer.raw,
Eric Laurentca7cc822012-11-19 14:55:58 -08001599 mConfig.inputCfg.buffer.frameCount,
1600 mConfig.inputCfg.samplingRate,
1601 mConfig.inputCfg.channels,
Marco Nelissenb2208842014-02-07 14:00:50 -08001602 mConfig.inputCfg.format,
Andy Hung9718d662017-12-22 17:57:39 -08001603 formatToString((audio_format_t)mConfig.inputCfg.format).c_str());
Eric Laurentca7cc822012-11-19 14:55:58 -08001604
1605 result.append("\t\t- Output configuration:\n");
1606 result.append("\t\t\tBuffer Frames Smp rate Channels Format\n");
Andy Hung9718d662017-12-22 17:57:39 -08001607 result.appendFormat("\t\t\t%p %05zu %05d %08x %6d (%s)\n",
Kévin PETIT377b2ec2014-02-03 12:35:36 +00001608 mConfig.outputCfg.buffer.raw,
Eric Laurentca7cc822012-11-19 14:55:58 -08001609 mConfig.outputCfg.buffer.frameCount,
1610 mConfig.outputCfg.samplingRate,
1611 mConfig.outputCfg.channels,
Marco Nelissenb2208842014-02-07 14:00:50 -08001612 mConfig.outputCfg.format,
Mikhail Naganov913d06c2016-11-01 12:49:22 -07001613 formatToString((audio_format_t)mConfig.outputCfg.format).c_str());
Eric Laurentca7cc822012-11-19 14:55:58 -08001614
rago94a1ee82017-07-21 15:11:02 -07001615#ifdef FLOAT_EFFECT_CHAIN
rago94a1ee82017-07-21 15:11:02 -07001616
Andy Hungbded9c82017-11-30 18:47:35 -08001617 result.appendFormat("\t\t- HAL buffers:\n"
1618 "\t\t\tIn(%s) InConversion(%s) Out(%s) OutConversion(%s)\n",
1619 dumpInOutBuffer(true /* isInput */, mInBuffer).c_str(),
1620 dumpInOutBuffer(true /* isInput */, mInConversionBuffer).c_str(),
1621 dumpInOutBuffer(false /* isInput */, mOutBuffer).c_str(),
1622 dumpInOutBuffer(false /* isInput */, mOutConversionBuffer).c_str());
rago94a1ee82017-07-21 15:11:02 -07001623#endif
1624
Eric Laurentca7cc822012-11-19 14:55:58 -08001625 write(fd, result.string(), result.length());
1626
Mikhail Naganov4d547672019-02-22 14:19:19 -08001627 if (mEffectInterface != 0) {
1628 dprintf(fd, "\tEffect ID %d HAL dump:\n", mId);
1629 (void)mEffectInterface->dump(fd);
1630 }
1631
Eric Laurentca7cc822012-11-19 14:55:58 -08001632 if (locked) {
1633 mLock.unlock();
1634 }
1635}
1636
1637// ----------------------------------------------------------------------------
1638// EffectHandle implementation
1639// ----------------------------------------------------------------------------
1640
1641#undef LOG_TAG
1642#define LOG_TAG "AudioFlinger::EffectHandle"
1643
Eric Laurent41709552019-12-16 19:34:05 -08001644AudioFlinger::EffectHandle::EffectHandle(const sp<EffectBase>& effect,
Eric Laurentca7cc822012-11-19 14:55:58 -08001645 const sp<AudioFlinger::Client>& client,
1646 const sp<IEffectClient>& effectClient,
1647 int32_t priority)
1648 : BnEffect(),
1649 mEffect(effect), mEffectClient(effectClient), mClient(client), mCblk(NULL),
Eric Laurent0d5a2ed2016-12-01 15:28:29 -08001650 mPriority(priority), mHasControl(false), mEnabled(false), mDisconnected(false)
Eric Laurentca7cc822012-11-19 14:55:58 -08001651{
Eric Laurentb82e6b72019-11-22 17:25:04 -08001652 ALOGV("constructor %p client %p", this, client.get());
Eric Laurentca7cc822012-11-19 14:55:58 -08001653
1654 if (client == 0) {
1655 return;
1656 }
1657 int bufOffset = ((sizeof(effect_param_cblk_t) - 1) / sizeof(int) + 1) * sizeof(int);
1658 mCblkMemory = client->heap()->allocate(EFFECT_PARAM_BUFFER_SIZE + bufOffset);
Glenn Kastene75da402013-11-20 13:54:52 -08001659 if (mCblkMemory == 0 ||
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -07001660 (mCblk = static_cast<effect_param_cblk_t *>(mCblkMemory->unsecurePointer())) == NULL) {
Glenn Kastenc42e9b42016-03-21 11:35:03 -07001661 ALOGE("not enough memory for Effect size=%zu", EFFECT_PARAM_BUFFER_SIZE +
Eric Laurentca7cc822012-11-19 14:55:58 -08001662 sizeof(effect_param_cblk_t));
Glenn Kastene75da402013-11-20 13:54:52 -08001663 mCblkMemory.clear();
Eric Laurentca7cc822012-11-19 14:55:58 -08001664 return;
1665 }
Glenn Kastene75da402013-11-20 13:54:52 -08001666 new(mCblk) effect_param_cblk_t();
1667 mBuffer = (uint8_t *)mCblk + bufOffset;
Eric Laurentca7cc822012-11-19 14:55:58 -08001668}
1669
1670AudioFlinger::EffectHandle::~EffectHandle()
1671{
1672 ALOGV("Destructor %p", this);
Eric Laurentca7cc822012-11-19 14:55:58 -08001673 disconnect(false);
1674}
1675
Glenn Kastene75da402013-11-20 13:54:52 -08001676status_t AudioFlinger::EffectHandle::initCheck()
1677{
1678 return mClient == 0 || mCblkMemory != 0 ? OK : NO_MEMORY;
1679}
1680
Eric Laurentca7cc822012-11-19 14:55:58 -08001681status_t AudioFlinger::EffectHandle::enable()
1682{
Eric Laurent0d5a2ed2016-12-01 15:28:29 -08001683 AutoMutex _l(mLock);
Eric Laurentca7cc822012-11-19 14:55:58 -08001684 ALOGV("enable %p", this);
Eric Laurent41709552019-12-16 19:34:05 -08001685 sp<EffectBase> effect = mEffect.promote();
Eric Laurent0d5a2ed2016-12-01 15:28:29 -08001686 if (effect == 0 || mDisconnected) {
1687 return DEAD_OBJECT;
1688 }
Eric Laurentca7cc822012-11-19 14:55:58 -08001689 if (!mHasControl) {
1690 return INVALID_OPERATION;
1691 }
Eric Laurentca7cc822012-11-19 14:55:58 -08001692
1693 if (mEnabled) {
1694 return NO_ERROR;
1695 }
1696
1697 mEnabled = true;
1698
Eric Laurent6c796322019-04-09 14:13:17 -07001699 status_t status = effect->updatePolicyState();
1700 if (status != NO_ERROR) {
1701 mEnabled = false;
1702 return status;
1703 }
1704
Eric Laurent6b446ce2019-12-13 10:56:31 -08001705 effect->checkSuspendOnEffectEnabled(true, false /*threadLocked*/);
Eric Laurentca7cc822012-11-19 14:55:58 -08001706
1707 // checkSuspendOnEffectEnabled() can suspend this same effect when enabled
Eric Laurent0d5a2ed2016-12-01 15:28:29 -08001708 if (effect->suspended()) {
Eric Laurentca7cc822012-11-19 14:55:58 -08001709 return NO_ERROR;
1710 }
1711
Eric Laurent6b446ce2019-12-13 10:56:31 -08001712 status = effect->setEnabled(true, true /*fromHandle*/);
Eric Laurentca7cc822012-11-19 14:55:58 -08001713 if (status != NO_ERROR) {
Eric Laurentca7cc822012-11-19 14:55:58 -08001714 mEnabled = false;
1715 }
1716 return status;
1717}
1718
1719status_t AudioFlinger::EffectHandle::disable()
1720{
1721 ALOGV("disable %p", this);
Eric Laurent0d5a2ed2016-12-01 15:28:29 -08001722 AutoMutex _l(mLock);
Eric Laurent41709552019-12-16 19:34:05 -08001723 sp<EffectBase> effect = mEffect.promote();
Eric Laurent0d5a2ed2016-12-01 15:28:29 -08001724 if (effect == 0 || mDisconnected) {
1725 return DEAD_OBJECT;
1726 }
Eric Laurentca7cc822012-11-19 14:55:58 -08001727 if (!mHasControl) {
1728 return INVALID_OPERATION;
1729 }
Eric Laurentca7cc822012-11-19 14:55:58 -08001730
1731 if (!mEnabled) {
1732 return NO_ERROR;
1733 }
1734 mEnabled = false;
1735
Eric Laurent6c796322019-04-09 14:13:17 -07001736 effect->updatePolicyState();
1737
Eric Laurent0d5a2ed2016-12-01 15:28:29 -08001738 if (effect->suspended()) {
Eric Laurentca7cc822012-11-19 14:55:58 -08001739 return NO_ERROR;
1740 }
1741
Eric Laurent6b446ce2019-12-13 10:56:31 -08001742 status_t status = effect->setEnabled(false, true /*fromHandle*/);
Eric Laurentca7cc822012-11-19 14:55:58 -08001743 return status;
1744}
1745
1746void AudioFlinger::EffectHandle::disconnect()
1747{
Eric Laurent0d5a2ed2016-12-01 15:28:29 -08001748 ALOGV("%s %p", __FUNCTION__, this);
Eric Laurentca7cc822012-11-19 14:55:58 -08001749 disconnect(true);
1750}
1751
1752void AudioFlinger::EffectHandle::disconnect(bool unpinIfLast)
1753{
Eric Laurent0d5a2ed2016-12-01 15:28:29 -08001754 AutoMutex _l(mLock);
1755 ALOGV("disconnect(%s) %p", unpinIfLast ? "true" : "false", this);
1756 if (mDisconnected) {
1757 if (unpinIfLast) {
1758 android_errorWriteLog(0x534e4554, "32707507");
1759 }
Eric Laurentca7cc822012-11-19 14:55:58 -08001760 return;
1761 }
Eric Laurent0d5a2ed2016-12-01 15:28:29 -08001762 mDisconnected = true;
Eric Laurent0d5a2ed2016-12-01 15:28:29 -08001763 {
Eric Laurent41709552019-12-16 19:34:05 -08001764 sp<EffectBase> effect = mEffect.promote();
Eric Laurent0d5a2ed2016-12-01 15:28:29 -08001765 if (effect != 0) {
Eric Laurent6b446ce2019-12-13 10:56:31 -08001766 if (effect->disconnectHandle(this, unpinIfLast) > 0) {
Eric Laurent6c796322019-04-09 14:13:17 -07001767 ALOGW("%s Effect handle %p disconnected after thread destruction",
1768 __func__, this);
1769 }
1770 effect->updatePolicyState();
Eric Laurentf10c7092016-12-06 17:09:56 -08001771 }
Eric Laurent0d5a2ed2016-12-01 15:28:29 -08001772 }
Eric Laurentca7cc822012-11-19 14:55:58 -08001773
Eric Laurentca7cc822012-11-19 14:55:58 -08001774 if (mClient != 0) {
1775 if (mCblk != NULL) {
1776 // unlike ~TrackBase(), mCblk is never a local new, so don't delete
1777 mCblk->~effect_param_cblk_t(); // destroy our shared-structure.
1778 }
1779 mCblkMemory.clear(); // free the shared memory before releasing the heap it belongs to
Eric Laurent021cf962014-05-13 10:18:14 -07001780 // Client destructor must run with AudioFlinger client mutex locked
1781 Mutex::Autolock _l(mClient->audioFlinger()->mClientLock);
Eric Laurentca7cc822012-11-19 14:55:58 -08001782 mClient.clear();
1783 }
1784}
1785
1786status_t AudioFlinger::EffectHandle::command(uint32_t cmdCode,
1787 uint32_t cmdSize,
1788 void *pCmdData,
1789 uint32_t *replySize,
1790 void *pReplyData)
1791{
1792 ALOGVV("command(), cmdCode: %d, mHasControl: %d, mEffect: %p",
Eric Laurent0d5a2ed2016-12-01 15:28:29 -08001793 cmdCode, mHasControl, mEffect.unsafe_get());
Eric Laurentca7cc822012-11-19 14:55:58 -08001794
Eric Laurentc7ab3092017-06-15 18:43:46 -07001795 // reject commands reserved for internal use by audio framework if coming from outside
1796 // of audioserver
1797 switch(cmdCode) {
1798 case EFFECT_CMD_ENABLE:
1799 case EFFECT_CMD_DISABLE:
1800 case EFFECT_CMD_SET_PARAM:
1801 case EFFECT_CMD_SET_PARAM_DEFERRED:
1802 case EFFECT_CMD_SET_PARAM_COMMIT:
1803 case EFFECT_CMD_GET_PARAM:
1804 break;
1805 default:
1806 if (cmdCode >= EFFECT_CMD_FIRST_PROPRIETARY) {
1807 break;
1808 }
1809 android_errorWriteLog(0x534e4554, "62019992");
1810 return BAD_VALUE;
1811 }
1812
Eric Laurent1ffc5852016-12-15 14:46:09 -08001813 if (cmdCode == EFFECT_CMD_ENABLE) {
1814 if (*replySize < sizeof(int)) {
1815 android_errorWriteLog(0x534e4554, "32095713");
1816 return BAD_VALUE;
1817 }
1818 *(int *)pReplyData = NO_ERROR;
1819 *replySize = sizeof(int);
1820 return enable();
1821 } else if (cmdCode == EFFECT_CMD_DISABLE) {
1822 if (*replySize < sizeof(int)) {
1823 android_errorWriteLog(0x534e4554, "32095713");
1824 return BAD_VALUE;
1825 }
1826 *(int *)pReplyData = NO_ERROR;
1827 *replySize = sizeof(int);
1828 return disable();
1829 }
1830
Eric Laurent0d5a2ed2016-12-01 15:28:29 -08001831 AutoMutex _l(mLock);
Eric Laurent41709552019-12-16 19:34:05 -08001832 sp<EffectBase> effect = mEffect.promote();
Eric Laurent0d5a2ed2016-12-01 15:28:29 -08001833 if (effect == 0 || mDisconnected) {
1834 return DEAD_OBJECT;
1835 }
Eric Laurentca7cc822012-11-19 14:55:58 -08001836 // only get parameter command is permitted for applications not controlling the effect
1837 if (!mHasControl && cmdCode != EFFECT_CMD_GET_PARAM) {
1838 return INVALID_OPERATION;
1839 }
Eric Laurentca7cc822012-11-19 14:55:58 -08001840
1841 // handle commands that are not forwarded transparently to effect engine
1842 if (cmdCode == EFFECT_CMD_SET_PARAM_COMMIT) {
Eric Laurentb82e6b72019-11-22 17:25:04 -08001843 if (mClient == 0) {
1844 return INVALID_OPERATION;
1845 }
1846
Eric Laurent1ffc5852016-12-15 14:46:09 -08001847 if (*replySize < sizeof(int)) {
1848 android_errorWriteLog(0x534e4554, "32095713");
1849 return BAD_VALUE;
1850 }
1851 *(int *)pReplyData = NO_ERROR;
1852 *replySize = sizeof(int);
1853
Eric Laurentca7cc822012-11-19 14:55:58 -08001854 // No need to trylock() here as this function is executed in the binder thread serving a
1855 // particular client process: no risk to block the whole media server process or mixer
1856 // threads if we are stuck here
1857 Mutex::Autolock _l(mCblk->lock);
Andy Hunga447a0f2016-11-15 17:19:58 -08001858 // keep local copy of index in case of client corruption b/32220769
1859 const uint32_t clientIndex = mCblk->clientIndex;
1860 const uint32_t serverIndex = mCblk->serverIndex;
1861 if (clientIndex > EFFECT_PARAM_BUFFER_SIZE ||
1862 serverIndex > EFFECT_PARAM_BUFFER_SIZE) {
Eric Laurentca7cc822012-11-19 14:55:58 -08001863 mCblk->serverIndex = 0;
1864 mCblk->clientIndex = 0;
1865 return BAD_VALUE;
1866 }
1867 status_t status = NO_ERROR;
Andy Hunga447a0f2016-11-15 17:19:58 -08001868 effect_param_t *param = NULL;
1869 for (uint32_t index = serverIndex; index < clientIndex;) {
1870 int *p = (int *)(mBuffer + index);
1871 const int size = *p++;
1872 if (size < 0
1873 || size > EFFECT_PARAM_BUFFER_SIZE
1874 || ((uint8_t *)p + size) > mBuffer + clientIndex) {
Eric Laurentca7cc822012-11-19 14:55:58 -08001875 ALOGW("command(): invalid parameter block size");
Andy Hunga447a0f2016-11-15 17:19:58 -08001876 status = BAD_VALUE;
Eric Laurentca7cc822012-11-19 14:55:58 -08001877 break;
1878 }
Andy Hunga447a0f2016-11-15 17:19:58 -08001879
1880 // copy to local memory in case of client corruption b/32220769
George Burgess IV80a22162020-01-05 20:06:15 -08001881 auto *newParam = (effect_param_t *)realloc(param, size);
1882 if (newParam == NULL) {
Andy Hunga447a0f2016-11-15 17:19:58 -08001883 ALOGW("command(): out of memory");
1884 status = NO_MEMORY;
1885 break;
Eric Laurentca7cc822012-11-19 14:55:58 -08001886 }
George Burgess IV80a22162020-01-05 20:06:15 -08001887 param = newParam;
Andy Hunga447a0f2016-11-15 17:19:58 -08001888 memcpy(param, p, size);
1889
1890 int reply = 0;
1891 uint32_t rsize = sizeof(reply);
Eric Laurent0d5a2ed2016-12-01 15:28:29 -08001892 status_t ret = effect->command(EFFECT_CMD_SET_PARAM,
Andy Hunga447a0f2016-11-15 17:19:58 -08001893 size,
1894 param,
Eric Laurentca7cc822012-11-19 14:55:58 -08001895 &rsize,
1896 &reply);
Andy Hunga447a0f2016-11-15 17:19:58 -08001897
1898 // verify shared memory: server index shouldn't change; client index can't go back.
1899 if (serverIndex != mCblk->serverIndex
1900 || clientIndex > mCblk->clientIndex) {
1901 android_errorWriteLog(0x534e4554, "32220769");
1902 status = BAD_VALUE;
1903 break;
1904 }
1905
Eric Laurentca7cc822012-11-19 14:55:58 -08001906 // stop at first error encountered
1907 if (ret != NO_ERROR) {
1908 status = ret;
1909 *(int *)pReplyData = reply;
1910 break;
1911 } else if (reply != NO_ERROR) {
1912 *(int *)pReplyData = reply;
1913 break;
1914 }
Andy Hunga447a0f2016-11-15 17:19:58 -08001915 index += size;
Eric Laurentca7cc822012-11-19 14:55:58 -08001916 }
Andy Hunga447a0f2016-11-15 17:19:58 -08001917 free(param);
Eric Laurentca7cc822012-11-19 14:55:58 -08001918 mCblk->serverIndex = 0;
1919 mCblk->clientIndex = 0;
1920 return status;
Eric Laurentca7cc822012-11-19 14:55:58 -08001921 }
1922
Eric Laurent0d5a2ed2016-12-01 15:28:29 -08001923 return effect->command(cmdCode, cmdSize, pCmdData, replySize, pReplyData);
Eric Laurentca7cc822012-11-19 14:55:58 -08001924}
1925
1926void AudioFlinger::EffectHandle::setControl(bool hasControl, bool signal, bool enabled)
1927{
1928 ALOGV("setControl %p control %d", this, hasControl);
1929
1930 mHasControl = hasControl;
1931 mEnabled = enabled;
1932
1933 if (signal && mEffectClient != 0) {
1934 mEffectClient->controlStatusChanged(hasControl);
1935 }
1936}
1937
1938void AudioFlinger::EffectHandle::commandExecuted(uint32_t cmdCode,
1939 uint32_t cmdSize,
1940 void *pCmdData,
1941 uint32_t replySize,
1942 void *pReplyData)
1943{
1944 if (mEffectClient != 0) {
1945 mEffectClient->commandExecuted(cmdCode, cmdSize, pCmdData, replySize, pReplyData);
1946 }
1947}
1948
1949
1950
1951void AudioFlinger::EffectHandle::setEnabled(bool enabled)
1952{
1953 if (mEffectClient != 0) {
1954 mEffectClient->enableStatusChanged(enabled);
1955 }
1956}
1957
1958status_t AudioFlinger::EffectHandle::onTransact(
1959 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
1960{
1961 return BnEffect::onTransact(code, data, reply, flags);
1962}
1963
1964
Glenn Kasten01d3acb2014-02-06 08:24:07 -08001965void AudioFlinger::EffectHandle::dumpToBuffer(char* buffer, size_t size)
Eric Laurentca7cc822012-11-19 14:55:58 -08001966{
1967 bool locked = mCblk != NULL && AudioFlinger::dumpTryLock(mCblk->lock);
1968
Marco Nelissenb2208842014-02-07 14:00:50 -08001969 snprintf(buffer, size, "\t\t\t%5d %5d %3s %3s %5u %5u\n",
Andy Hung4ef19fa2018-05-15 19:35:29 -07001970 (mClient == 0) ? getpid() : mClient->pid(),
Eric Laurentca7cc822012-11-19 14:55:58 -08001971 mPriority,
Marco Nelissenb2208842014-02-07 14:00:50 -08001972 mHasControl ? "yes" : "no",
1973 locked ? "yes" : "no",
Eric Laurentca7cc822012-11-19 14:55:58 -08001974 mCblk ? mCblk->clientIndex : 0,
1975 mCblk ? mCblk->serverIndex : 0
1976 );
1977
1978 if (locked) {
1979 mCblk->lock.unlock();
1980 }
1981}
1982
1983#undef LOG_TAG
1984#define LOG_TAG "AudioFlinger::EffectChain"
1985
Ytai Ben-Tsvi3de1bbf2020-01-21 16:41:17 -08001986AudioFlinger::EffectChain::EffectChain(const wp<ThreadBase>& thread,
1987 audio_session_t sessionId)
Eric Laurent6b446ce2019-12-13 10:56:31 -08001988 : mSessionId(sessionId), mActiveTrackCnt(0), mTrackCnt(0), mTailBufferCount(0),
Mikhail Naganov022b9952017-01-04 16:36:51 -08001989 mVolumeCtrlIdx(-1), mLeftVolume(UINT_MAX), mRightVolume(UINT_MAX),
Eric Laurent6b446ce2019-12-13 10:56:31 -08001990 mNewLeftVolume(UINT_MAX), mNewRightVolume(UINT_MAX),
Ytai Ben-Tsvi3de1bbf2020-01-21 16:41:17 -08001991 mEffectCallback(new EffectCallback(wp<EffectChain>(this), thread))
Eric Laurentca7cc822012-11-19 14:55:58 -08001992{
1993 mStrategy = AudioSystem::getStrategyForStream(AUDIO_STREAM_MUSIC);
Ytai Ben-Tsvi3de1bbf2020-01-21 16:41:17 -08001994 sp<ThreadBase> p = thread.promote();
1995 if (p == nullptr) {
Eric Laurentca7cc822012-11-19 14:55:58 -08001996 return;
1997 }
Ytai Ben-Tsvi3de1bbf2020-01-21 16:41:17 -08001998 mMaxTailBuffers = ((kProcessTailDurationMs * p->sampleRate()) / 1000) /
1999 p->frameCount();
Eric Laurentca7cc822012-11-19 14:55:58 -08002000}
2001
2002AudioFlinger::EffectChain::~EffectChain()
2003{
Eric Laurentca7cc822012-11-19 14:55:58 -08002004}
2005
2006// getEffectFromDesc_l() must be called with ThreadBase::mLock held
2007sp<AudioFlinger::EffectModule> AudioFlinger::EffectChain::getEffectFromDesc_l(
2008 effect_descriptor_t *descriptor)
2009{
2010 size_t size = mEffects.size();
2011
2012 for (size_t i = 0; i < size; i++) {
2013 if (memcmp(&mEffects[i]->desc().uuid, &descriptor->uuid, sizeof(effect_uuid_t)) == 0) {
2014 return mEffects[i];
2015 }
2016 }
2017 return 0;
2018}
2019
2020// getEffectFromId_l() must be called with ThreadBase::mLock held
2021sp<AudioFlinger::EffectModule> AudioFlinger::EffectChain::getEffectFromId_l(int id)
2022{
2023 size_t size = mEffects.size();
2024
2025 for (size_t i = 0; i < size; i++) {
2026 // by convention, return first effect if id provided is 0 (0 is never a valid id)
2027 if (id == 0 || mEffects[i]->id() == id) {
2028 return mEffects[i];
2029 }
2030 }
2031 return 0;
2032}
2033
2034// getEffectFromType_l() must be called with ThreadBase::mLock held
2035sp<AudioFlinger::EffectModule> AudioFlinger::EffectChain::getEffectFromType_l(
2036 const effect_uuid_t *type)
2037{
2038 size_t size = mEffects.size();
2039
2040 for (size_t i = 0; i < size; i++) {
2041 if (memcmp(&mEffects[i]->desc().type, type, sizeof(effect_uuid_t)) == 0) {
2042 return mEffects[i];
2043 }
2044 }
2045 return 0;
2046}
2047
Eric Laurent6c796322019-04-09 14:13:17 -07002048std::vector<int> AudioFlinger::EffectChain::getEffectIds()
2049{
2050 std::vector<int> ids;
2051 Mutex::Autolock _l(mLock);
2052 for (size_t i = 0; i < mEffects.size(); i++) {
2053 ids.push_back(mEffects[i]->id());
2054 }
2055 return ids;
2056}
2057
Eric Laurentca7cc822012-11-19 14:55:58 -08002058void AudioFlinger::EffectChain::clearInputBuffer()
2059{
2060 Mutex::Autolock _l(mLock);
Eric Laurent6b446ce2019-12-13 10:56:31 -08002061 clearInputBuffer_l();
Eric Laurentca7cc822012-11-19 14:55:58 -08002062}
2063
2064// Must be called with EffectChain::mLock locked
Eric Laurent6b446ce2019-12-13 10:56:31 -08002065void AudioFlinger::EffectChain::clearInputBuffer_l()
Eric Laurentca7cc822012-11-19 14:55:58 -08002066{
Eric Laurent6acd1d42017-01-04 14:23:29 -08002067 if (mInBuffer == NULL) {
2068 return;
2069 }
Ricardo Garcia726b6a72014-08-11 12:04:54 -07002070 const size_t frameSize =
Eric Laurent6b446ce2019-12-13 10:56:31 -08002071 audio_bytes_per_sample(EFFECT_BUFFER_FORMAT) * mEffectCallback->channelCount();
rago94a1ee82017-07-21 15:11:02 -07002072
Eric Laurent6b446ce2019-12-13 10:56:31 -08002073 memset(mInBuffer->audioBuffer()->raw, 0, mEffectCallback->frameCount() * frameSize);
Mikhail Naganov022b9952017-01-04 16:36:51 -08002074 mInBuffer->commit();
Eric Laurentca7cc822012-11-19 14:55:58 -08002075}
2076
2077// Must be called with EffectChain::mLock locked
2078void AudioFlinger::EffectChain::process_l()
2079{
Jean-Michel Trivifed62922013-09-25 18:50:33 -07002080 // never process effects when:
2081 // - on an OFFLOAD thread
2082 // - no more tracks are on the session and the effect tail has been rendered
Eric Laurent6b446ce2019-12-13 10:56:31 -08002083 bool doProcess = !mEffectCallback->isOffloadOrMmap();
Eric Laurent3f75a5b2019-11-12 15:55:51 -08002084 if (!audio_is_global_session(mSessionId)) {
Eric Laurentca7cc822012-11-19 14:55:58 -08002085 bool tracksOnSession = (trackCnt() != 0);
2086
2087 if (!tracksOnSession && mTailBufferCount == 0) {
2088 doProcess = false;
2089 }
2090
2091 if (activeTrackCnt() == 0) {
2092 // if no track is active and the effect tail has not been rendered,
2093 // the input buffer must be cleared here as the mixer process will not do it
2094 if (tracksOnSession || mTailBufferCount > 0) {
Eric Laurent6b446ce2019-12-13 10:56:31 -08002095 clearInputBuffer_l();
Eric Laurentca7cc822012-11-19 14:55:58 -08002096 if (mTailBufferCount > 0) {
2097 mTailBufferCount--;
2098 }
2099 }
2100 }
2101 }
2102
2103 size_t size = mEffects.size();
2104 if (doProcess) {
Mikhail Naganov022b9952017-01-04 16:36:51 -08002105 // Only the input and output buffers of the chain can be external,
2106 // and 'update' / 'commit' do nothing for allocated buffers, thus
2107 // it's not needed to consider any other buffers here.
2108 mInBuffer->update();
Mikhail Naganov06888802017-01-19 12:47:55 -08002109 if (mInBuffer->audioBuffer()->raw != mOutBuffer->audioBuffer()->raw) {
2110 mOutBuffer->update();
2111 }
Eric Laurentca7cc822012-11-19 14:55:58 -08002112 for (size_t i = 0; i < size; i++) {
2113 mEffects[i]->process();
2114 }
Mikhail Naganov06888802017-01-19 12:47:55 -08002115 mInBuffer->commit();
2116 if (mInBuffer->audioBuffer()->raw != mOutBuffer->audioBuffer()->raw) {
2117 mOutBuffer->commit();
2118 }
Eric Laurentca7cc822012-11-19 14:55:58 -08002119 }
Eric Laurentfa1e1232016-08-02 19:01:49 -07002120 bool doResetVolume = false;
Eric Laurentca7cc822012-11-19 14:55:58 -08002121 for (size_t i = 0; i < size; i++) {
Eric Laurentfa1e1232016-08-02 19:01:49 -07002122 doResetVolume = mEffects[i]->updateState() || doResetVolume;
2123 }
2124 if (doResetVolume) {
2125 resetVolume_l();
Eric Laurentca7cc822012-11-19 14:55:58 -08002126 }
2127}
2128
Eric Laurent0d5a2ed2016-12-01 15:28:29 -08002129// createEffect_l() must be called with ThreadBase::mLock held
2130status_t AudioFlinger::EffectChain::createEffect_l(sp<EffectModule>& effect,
Eric Laurent0d5a2ed2016-12-01 15:28:29 -08002131 effect_descriptor_t *desc,
2132 int id,
2133 audio_session_t sessionId,
2134 bool pinned)
2135{
2136 Mutex::Autolock _l(mLock);
Eric Laurentb82e6b72019-11-22 17:25:04 -08002137 effect = new EffectModule(mEffectCallback, desc, id, sessionId, pinned, AUDIO_PORT_HANDLE_NONE);
Eric Laurent0d5a2ed2016-12-01 15:28:29 -08002138 status_t lStatus = effect->status();
2139 if (lStatus == NO_ERROR) {
2140 lStatus = addEffect_ll(effect);
2141 }
2142 if (lStatus != NO_ERROR) {
2143 effect.clear();
2144 }
2145 return lStatus;
2146}
2147
2148// addEffect_l() must be called with ThreadBase::mLock held
Eric Laurentca7cc822012-11-19 14:55:58 -08002149status_t AudioFlinger::EffectChain::addEffect_l(const sp<EffectModule>& effect)
2150{
Eric Laurent0d5a2ed2016-12-01 15:28:29 -08002151 Mutex::Autolock _l(mLock);
2152 return addEffect_ll(effect);
2153}
2154// addEffect_l() must be called with ThreadBase::mLock and EffectChain::mLock held
2155status_t AudioFlinger::EffectChain::addEffect_ll(const sp<EffectModule>& effect)
2156{
Eric Laurentca7cc822012-11-19 14:55:58 -08002157 effect_descriptor_t desc = effect->desc();
2158 uint32_t insertPref = desc.flags & EFFECT_FLAG_INSERT_MASK;
2159
Eric Laurent6b446ce2019-12-13 10:56:31 -08002160 effect->setCallback(mEffectCallback);
Eric Laurentca7cc822012-11-19 14:55:58 -08002161
2162 if ((desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
2163 // Auxiliary effects are inserted at the beginning of mEffects vector as
2164 // they are processed first and accumulated in chain input buffer
2165 mEffects.insertAt(effect, 0);
2166
2167 // the input buffer for auxiliary effect contains mono samples in
2168 // 32 bit format. This is to avoid saturation in AudoMixer
2169 // accumulation stage. Saturation is done in EffectModule::process() before
2170 // calling the process in effect engine
Eric Laurent6b446ce2019-12-13 10:56:31 -08002171 size_t numSamples = mEffectCallback->frameCount();
Mikhail Naganov022b9952017-01-04 16:36:51 -08002172 sp<EffectBufferHalInterface> halBuffer;
rago94a1ee82017-07-21 15:11:02 -07002173#ifdef FLOAT_EFFECT_CHAIN
Eric Laurent6b446ce2019-12-13 10:56:31 -08002174 status_t result = mEffectCallback->allocateHalBuffer(
rago94a1ee82017-07-21 15:11:02 -07002175 numSamples * sizeof(float), &halBuffer);
2176#else
Eric Laurent6b446ce2019-12-13 10:56:31 -08002177 status_t result = mEffectCallback->allocateHalBuffer(
Mikhail Naganov022b9952017-01-04 16:36:51 -08002178 numSamples * sizeof(int32_t), &halBuffer);
rago94a1ee82017-07-21 15:11:02 -07002179#endif
Mikhail Naganov022b9952017-01-04 16:36:51 -08002180 if (result != OK) return result;
2181 effect->setInBuffer(halBuffer);
Eric Laurentca7cc822012-11-19 14:55:58 -08002182 // auxiliary effects output samples to chain input buffer for further processing
2183 // by insert effects
2184 effect->setOutBuffer(mInBuffer);
2185 } else {
2186 // Insert effects are inserted at the end of mEffects vector as they are processed
2187 // after track and auxiliary effects.
2188 // Insert effect order as a function of indicated preference:
2189 // if EFFECT_FLAG_INSERT_EXCLUSIVE, insert in first position or reject if
2190 // another effect is present
2191 // else if EFFECT_FLAG_INSERT_FIRST, insert in first position or after the
2192 // last effect claiming first position
2193 // else if EFFECT_FLAG_INSERT_LAST, insert in last position or before the
2194 // first effect claiming last position
2195 // else if EFFECT_FLAG_INSERT_ANY insert after first or before last
2196 // Reject insertion if an effect with EFFECT_FLAG_INSERT_EXCLUSIVE is
2197 // already present
2198
2199 size_t size = mEffects.size();
2200 size_t idx_insert = size;
2201 ssize_t idx_insert_first = -1;
2202 ssize_t idx_insert_last = -1;
2203
2204 for (size_t i = 0; i < size; i++) {
2205 effect_descriptor_t d = mEffects[i]->desc();
2206 uint32_t iMode = d.flags & EFFECT_FLAG_TYPE_MASK;
2207 uint32_t iPref = d.flags & EFFECT_FLAG_INSERT_MASK;
2208 if (iMode == EFFECT_FLAG_TYPE_INSERT) {
2209 // check invalid effect chaining combinations
2210 if (insertPref == EFFECT_FLAG_INSERT_EXCLUSIVE ||
2211 iPref == EFFECT_FLAG_INSERT_EXCLUSIVE) {
2212 ALOGW("addEffect_l() could not insert effect %s: exclusive conflict with %s",
2213 desc.name, d.name);
2214 return INVALID_OPERATION;
2215 }
2216 // remember position of first insert effect and by default
2217 // select this as insert position for new effect
2218 if (idx_insert == size) {
2219 idx_insert = i;
2220 }
2221 // remember position of last insert effect claiming
2222 // first position
2223 if (iPref == EFFECT_FLAG_INSERT_FIRST) {
2224 idx_insert_first = i;
2225 }
2226 // remember position of first insert effect claiming
2227 // last position
2228 if (iPref == EFFECT_FLAG_INSERT_LAST &&
2229 idx_insert_last == -1) {
2230 idx_insert_last = i;
2231 }
2232 }
2233 }
2234
2235 // modify idx_insert from first position if needed
2236 if (insertPref == EFFECT_FLAG_INSERT_LAST) {
2237 if (idx_insert_last != -1) {
2238 idx_insert = idx_insert_last;
2239 } else {
2240 idx_insert = size;
2241 }
2242 } else {
2243 if (idx_insert_first != -1) {
2244 idx_insert = idx_insert_first + 1;
2245 }
2246 }
2247
2248 // always read samples from chain input buffer
2249 effect->setInBuffer(mInBuffer);
2250
2251 // if last effect in the chain, output samples to chain
2252 // output buffer, otherwise to chain input buffer
2253 if (idx_insert == size) {
2254 if (idx_insert != 0) {
2255 mEffects[idx_insert-1]->setOutBuffer(mInBuffer);
2256 mEffects[idx_insert-1]->configure();
2257 }
2258 effect->setOutBuffer(mOutBuffer);
2259 } else {
2260 effect->setOutBuffer(mInBuffer);
2261 }
2262 mEffects.insertAt(effect, idx_insert);
2263
Glenn Kastenc42e9b42016-03-21 11:35:03 -07002264 ALOGV("addEffect_l() effect %p, added in chain %p at rank %zu", effect.get(), this,
Eric Laurentca7cc822012-11-19 14:55:58 -08002265 idx_insert);
2266 }
2267 effect->configure();
Eric Laurentd8365c52017-07-16 15:27:05 -07002268
Eric Laurentca7cc822012-11-19 14:55:58 -08002269 return NO_ERROR;
2270}
2271
Eric Laurent0d5a2ed2016-12-01 15:28:29 -08002272// removeEffect_l() must be called with ThreadBase::mLock held
2273size_t AudioFlinger::EffectChain::removeEffect_l(const sp<EffectModule>& effect,
2274 bool release)
Eric Laurentca7cc822012-11-19 14:55:58 -08002275{
2276 Mutex::Autolock _l(mLock);
2277 size_t size = mEffects.size();
2278 uint32_t type = effect->desc().flags & EFFECT_FLAG_TYPE_MASK;
2279
2280 for (size_t i = 0; i < size; i++) {
2281 if (effect == mEffects[i]) {
2282 // calling stop here will remove pre-processing effect from the audio HAL.
2283 // This is safe as we hold the EffectChain mutex which guarantees that we are not in
2284 // the middle of a read from audio HAL
2285 if (mEffects[i]->state() == EffectModule::ACTIVE ||
2286 mEffects[i]->state() == EffectModule::STOPPING) {
2287 mEffects[i]->stop();
2288 }
Eric Laurent0d5a2ed2016-12-01 15:28:29 -08002289 if (release) {
2290 mEffects[i]->release_l();
2291 }
2292
Mikhail Naganov022b9952017-01-04 16:36:51 -08002293 if (type != EFFECT_FLAG_TYPE_AUXILIARY) {
Eric Laurentca7cc822012-11-19 14:55:58 -08002294 if (i == size - 1 && i != 0) {
2295 mEffects[i - 1]->setOutBuffer(mOutBuffer);
2296 mEffects[i - 1]->configure();
2297 }
2298 }
2299 mEffects.removeAt(i);
Glenn Kastenc42e9b42016-03-21 11:35:03 -07002300 ALOGV("removeEffect_l() effect %p, removed from chain %p at rank %zu", effect.get(),
Eric Laurentca7cc822012-11-19 14:55:58 -08002301 this, i);
Eric Laurent0d5a2ed2016-12-01 15:28:29 -08002302
Eric Laurentca7cc822012-11-19 14:55:58 -08002303 break;
2304 }
2305 }
2306
2307 return mEffects.size();
2308}
2309
jiabin8f278ee2019-11-11 12:16:27 -08002310// setDevices_l() must be called with ThreadBase::mLock held
2311void AudioFlinger::EffectChain::setDevices_l(const AudioDeviceTypeAddrVector &devices)
Eric Laurentca7cc822012-11-19 14:55:58 -08002312{
2313 size_t size = mEffects.size();
2314 for (size_t i = 0; i < size; i++) {
jiabin8f278ee2019-11-11 12:16:27 -08002315 mEffects[i]->setDevices(devices);
2316 }
2317}
2318
2319// setInputDevice_l() must be called with ThreadBase::mLock held
2320void AudioFlinger::EffectChain::setInputDevice_l(const AudioDeviceTypeAddr &device)
2321{
2322 size_t size = mEffects.size();
2323 for (size_t i = 0; i < size; i++) {
2324 mEffects[i]->setInputDevice(device);
Eric Laurentca7cc822012-11-19 14:55:58 -08002325 }
2326}
2327
Eric Laurent0d5a2ed2016-12-01 15:28:29 -08002328// setMode_l() must be called with ThreadBase::mLock held
Eric Laurentca7cc822012-11-19 14:55:58 -08002329void AudioFlinger::EffectChain::setMode_l(audio_mode_t mode)
2330{
2331 size_t size = mEffects.size();
2332 for (size_t i = 0; i < size; i++) {
2333 mEffects[i]->setMode(mode);
2334 }
2335}
2336
Eric Laurent0d5a2ed2016-12-01 15:28:29 -08002337// setAudioSource_l() must be called with ThreadBase::mLock held
Eric Laurentca7cc822012-11-19 14:55:58 -08002338void AudioFlinger::EffectChain::setAudioSource_l(audio_source_t source)
2339{
2340 size_t size = mEffects.size();
2341 for (size_t i = 0; i < size; i++) {
2342 mEffects[i]->setAudioSource(source);
2343 }
2344}
2345
Zhou Songd505c642020-02-20 16:35:37 +08002346bool AudioFlinger::EffectChain::hasVolumeControlEnabled_l() const {
2347 for (const auto &effect : mEffects) {
2348 if (effect->isVolumeControlEnabled()) return true;
2349 }
2350 return false;
2351}
2352
Eric Laurent0d5a2ed2016-12-01 15:28:29 -08002353// setVolume_l() must be called with ThreadBase::mLock or EffectChain::mLock held
Eric Laurentfa1e1232016-08-02 19:01:49 -07002354bool AudioFlinger::EffectChain::setVolume_l(uint32_t *left, uint32_t *right, bool force)
Eric Laurentca7cc822012-11-19 14:55:58 -08002355{
2356 uint32_t newLeft = *left;
2357 uint32_t newRight = *right;
2358 bool hasControl = false;
2359 int ctrlIdx = -1;
2360 size_t size = mEffects.size();
2361
2362 // first update volume controller
2363 for (size_t i = size; i > 0; i--) {
Tomoharu Kasahara1990bd42014-12-12 14:04:11 +09002364 if (mEffects[i - 1]->isVolumeControlEnabled()) {
Eric Laurentca7cc822012-11-19 14:55:58 -08002365 ctrlIdx = i - 1;
2366 hasControl = true;
2367 break;
2368 }
2369 }
2370
Eric Laurentfa1e1232016-08-02 19:01:49 -07002371 if (!force && ctrlIdx == mVolumeCtrlIdx &&
Eric Laurentcb4b6e92014-10-01 14:26:10 -07002372 *left == mLeftVolume && *right == mRightVolume) {
Eric Laurentca7cc822012-11-19 14:55:58 -08002373 if (hasControl) {
2374 *left = mNewLeftVolume;
2375 *right = mNewRightVolume;
2376 }
2377 return hasControl;
2378 }
2379
2380 mVolumeCtrlIdx = ctrlIdx;
2381 mLeftVolume = newLeft;
2382 mRightVolume = newRight;
2383
2384 // second get volume update from volume controller
2385 if (ctrlIdx >= 0) {
2386 mEffects[ctrlIdx]->setVolume(&newLeft, &newRight, true);
2387 mNewLeftVolume = newLeft;
2388 mNewRightVolume = newRight;
2389 }
2390 // then indicate volume to all other effects in chain.
2391 // Pass altered volume to effects before volume controller
Jasmine Cha934ecfb2019-01-23 18:19:14 +08002392 // and requested volume to effects after controller or with volume monitor flag
Eric Laurentca7cc822012-11-19 14:55:58 -08002393 uint32_t lVol = newLeft;
2394 uint32_t rVol = newRight;
2395
2396 for (size_t i = 0; i < size; i++) {
2397 if ((int)i == ctrlIdx) {
2398 continue;
2399 }
2400 // this also works for ctrlIdx == -1 when there is no volume controller
2401 if ((int)i > ctrlIdx) {
2402 lVol = *left;
2403 rVol = *right;
2404 }
Jasmine Cha934ecfb2019-01-23 18:19:14 +08002405 // Pass requested volume directly if this is volume monitor module
2406 if (mEffects[i]->isVolumeMonitor()) {
2407 mEffects[i]->setVolume(left, right, false);
2408 } else {
2409 mEffects[i]->setVolume(&lVol, &rVol, false);
2410 }
Eric Laurentca7cc822012-11-19 14:55:58 -08002411 }
2412 *left = newLeft;
2413 *right = newRight;
2414
Tomoharu Kasahara1990bd42014-12-12 14:04:11 +09002415 setVolumeForOutput_l(*left, *right);
2416
Eric Laurentca7cc822012-11-19 14:55:58 -08002417 return hasControl;
2418}
2419
Eric Laurent0d5a2ed2016-12-01 15:28:29 -08002420// resetVolume_l() must be called with ThreadBase::mLock or EffectChain::mLock held
Eric Laurentfa1e1232016-08-02 19:01:49 -07002421void AudioFlinger::EffectChain::resetVolume_l()
2422{
Eric Laurente7449bf2016-08-03 18:44:07 -07002423 if ((mLeftVolume != UINT_MAX) && (mRightVolume != UINT_MAX)) {
2424 uint32_t left = mLeftVolume;
2425 uint32_t right = mRightVolume;
2426 (void)setVolume_l(&left, &right, true);
2427 }
Eric Laurentfa1e1232016-08-02 19:01:49 -07002428}
2429
jiabineb3bda02020-06-30 14:07:03 -07002430// containsHapticGeneratingEffect_l must be called with ThreadBase::mLock or EffectChain::mLock held
2431bool AudioFlinger::EffectChain::containsHapticGeneratingEffect_l()
2432{
2433 for (size_t i = 0; i < mEffects.size(); ++i) {
2434 if (mEffects[i]->isHapticGenerator()) {
2435 return true;
2436 }
2437 }
2438 return false;
2439}
2440
jiabine70bc7f2020-06-30 22:07:55 -07002441void AudioFlinger::EffectChain::setHapticIntensity_l(int id, int intensity)
2442{
2443 Mutex::Autolock _l(mLock);
2444 for (size_t i = 0; i < mEffects.size(); ++i) {
2445 mEffects[i]->setHapticIntensity(id, intensity);
2446 }
2447}
2448
Eric Laurent1b928682014-10-02 19:41:47 -07002449void AudioFlinger::EffectChain::syncHalEffectsState()
2450{
2451 Mutex::Autolock _l(mLock);
2452 for (size_t i = 0; i < mEffects.size(); i++) {
2453 if (mEffects[i]->state() == EffectModule::ACTIVE ||
2454 mEffects[i]->state() == EffectModule::STOPPING) {
2455 mEffects[i]->addEffectToHal_l();
2456 }
2457 }
2458}
2459
Eric Laurentca7cc822012-11-19 14:55:58 -08002460void AudioFlinger::EffectChain::dump(int fd, const Vector<String16>& args)
2461{
Eric Laurentca7cc822012-11-19 14:55:58 -08002462 String8 result;
2463
Mikhail Naganov19740ca2019-03-28 12:25:01 -07002464 const size_t numEffects = mEffects.size();
2465 result.appendFormat(" %zu effects for session %d\n", numEffects, mSessionId);
Eric Laurentca7cc822012-11-19 14:55:58 -08002466
Marco Nelissenb2208842014-02-07 14:00:50 -08002467 if (numEffects) {
2468 bool locked = AudioFlinger::dumpTryLock(mLock);
2469 // failed to lock - AudioFlinger is probably deadlocked
2470 if (!locked) {
2471 result.append("\tCould not lock mutex:\n");
Eric Laurentca7cc822012-11-19 14:55:58 -08002472 }
Eric Laurentca7cc822012-11-19 14:55:58 -08002473
Andy Hungbded9c82017-11-30 18:47:35 -08002474 const std::string inBufferStr = dumpInOutBuffer(true /* isInput */, mInBuffer);
2475 const std::string outBufferStr = dumpInOutBuffer(false /* isInput */, mOutBuffer);
2476 result.appendFormat("\t%-*s%-*s Active tracks:\n",
2477 (int)inBufferStr.size(), "In buffer ",
2478 (int)outBufferStr.size(), "Out buffer ");
2479 result.appendFormat("\t%s %s %d\n",
2480 inBufferStr.c_str(), outBufferStr.c_str(), mActiveTrackCnt);
Marco Nelissenb2208842014-02-07 14:00:50 -08002481 write(fd, result.string(), result.size());
2482
2483 for (size_t i = 0; i < numEffects; ++i) {
2484 sp<EffectModule> effect = mEffects[i];
2485 if (effect != 0) {
2486 effect->dump(fd, args);
2487 }
2488 }
2489
2490 if (locked) {
2491 mLock.unlock();
2492 }
Mikhail Naganov19740ca2019-03-28 12:25:01 -07002493 } else {
2494 write(fd, result.string(), result.size());
Eric Laurentca7cc822012-11-19 14:55:58 -08002495 }
2496}
2497
2498// must be called with ThreadBase::mLock held
2499void AudioFlinger::EffectChain::setEffectSuspended_l(
2500 const effect_uuid_t *type, bool suspend)
2501{
2502 sp<SuspendedEffectDesc> desc;
2503 // use effect type UUID timelow as key as there is no real risk of identical
2504 // timeLow fields among effect type UUIDs.
2505 ssize_t index = mSuspendedEffects.indexOfKey(type->timeLow);
2506 if (suspend) {
2507 if (index >= 0) {
2508 desc = mSuspendedEffects.valueAt(index);
2509 } else {
2510 desc = new SuspendedEffectDesc();
2511 desc->mType = *type;
2512 mSuspendedEffects.add(type->timeLow, desc);
2513 ALOGV("setEffectSuspended_l() add entry for %08x", type->timeLow);
2514 }
Eric Laurentd8365c52017-07-16 15:27:05 -07002515
Eric Laurentca7cc822012-11-19 14:55:58 -08002516 if (desc->mRefCount++ == 0) {
2517 sp<EffectModule> effect = getEffectIfEnabled(type);
2518 if (effect != 0) {
2519 desc->mEffect = effect;
2520 effect->setSuspended(true);
Eric Laurent6b446ce2019-12-13 10:56:31 -08002521 effect->setEnabled(false, false /*fromHandle*/);
Eric Laurentca7cc822012-11-19 14:55:58 -08002522 }
2523 }
2524 } else {
2525 if (index < 0) {
2526 return;
2527 }
2528 desc = mSuspendedEffects.valueAt(index);
2529 if (desc->mRefCount <= 0) {
2530 ALOGW("setEffectSuspended_l() restore refcount should not be 0 %d", desc->mRefCount);
Eric Laurentd8365c52017-07-16 15:27:05 -07002531 desc->mRefCount = 0;
2532 return;
Eric Laurentca7cc822012-11-19 14:55:58 -08002533 }
2534 if (--desc->mRefCount == 0) {
2535 ALOGV("setEffectSuspended_l() remove entry for %08x", mSuspendedEffects.keyAt(index));
2536 if (desc->mEffect != 0) {
2537 sp<EffectModule> effect = desc->mEffect.promote();
2538 if (effect != 0) {
2539 effect->setSuspended(false);
2540 effect->lock();
2541 EffectHandle *handle = effect->controlHandle_l();
Eric Laurent0d5a2ed2016-12-01 15:28:29 -08002542 if (handle != NULL && !handle->disconnected()) {
Eric Laurentca7cc822012-11-19 14:55:58 -08002543 effect->setEnabled_l(handle->enabled());
2544 }
2545 effect->unlock();
2546 }
2547 desc->mEffect.clear();
2548 }
2549 mSuspendedEffects.removeItemsAt(index);
2550 }
2551 }
2552}
2553
2554// must be called with ThreadBase::mLock held
2555void AudioFlinger::EffectChain::setEffectSuspendedAll_l(bool suspend)
2556{
2557 sp<SuspendedEffectDesc> desc;
2558
2559 ssize_t index = mSuspendedEffects.indexOfKey((int)kKeyForSuspendAll);
2560 if (suspend) {
2561 if (index >= 0) {
2562 desc = mSuspendedEffects.valueAt(index);
2563 } else {
2564 desc = new SuspendedEffectDesc();
2565 mSuspendedEffects.add((int)kKeyForSuspendAll, desc);
2566 ALOGV("setEffectSuspendedAll_l() add entry for 0");
2567 }
2568 if (desc->mRefCount++ == 0) {
2569 Vector< sp<EffectModule> > effects;
2570 getSuspendEligibleEffects(effects);
2571 for (size_t i = 0; i < effects.size(); i++) {
2572 setEffectSuspended_l(&effects[i]->desc().type, true);
2573 }
2574 }
2575 } else {
2576 if (index < 0) {
2577 return;
2578 }
2579 desc = mSuspendedEffects.valueAt(index);
2580 if (desc->mRefCount <= 0) {
2581 ALOGW("setEffectSuspendedAll_l() restore refcount should not be 0 %d", desc->mRefCount);
2582 desc->mRefCount = 1;
2583 }
2584 if (--desc->mRefCount == 0) {
2585 Vector<const effect_uuid_t *> types;
2586 for (size_t i = 0; i < mSuspendedEffects.size(); i++) {
2587 if (mSuspendedEffects.keyAt(i) == (int)kKeyForSuspendAll) {
2588 continue;
2589 }
2590 types.add(&mSuspendedEffects.valueAt(i)->mType);
2591 }
2592 for (size_t i = 0; i < types.size(); i++) {
2593 setEffectSuspended_l(types[i], false);
2594 }
2595 ALOGV("setEffectSuspendedAll_l() remove entry for %08x",
2596 mSuspendedEffects.keyAt(index));
2597 mSuspendedEffects.removeItem((int)kKeyForSuspendAll);
2598 }
2599 }
2600}
2601
2602
2603// The volume effect is used for automated tests only
2604#ifndef OPENSL_ES_H_
2605static const effect_uuid_t SL_IID_VOLUME_ = { 0x09e8ede0, 0xddde, 0x11db, 0xb4f6,
2606 { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } };
2607const effect_uuid_t * const SL_IID_VOLUME = &SL_IID_VOLUME_;
2608#endif //OPENSL_ES_H_
2609
Eric Laurentd8365c52017-07-16 15:27:05 -07002610/* static */
2611bool AudioFlinger::EffectChain::isEffectEligibleForBtNrecSuspend(const effect_uuid_t *type)
2612{
2613 // Only NS and AEC are suspended when BtNRec is off
2614 if ((memcmp(type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0) ||
2615 (memcmp(type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2616 return true;
2617 }
2618 return false;
2619}
2620
Eric Laurentca7cc822012-11-19 14:55:58 -08002621bool AudioFlinger::EffectChain::isEffectEligibleForSuspend(const effect_descriptor_t& desc)
2622{
2623 // auxiliary effects and visualizer are never suspended on output mix
2624 if ((mSessionId == AUDIO_SESSION_OUTPUT_MIX) &&
2625 (((desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) ||
2626 (memcmp(&desc.type, SL_IID_VISUALIZATION, sizeof(effect_uuid_t)) == 0) ||
Ricardo Garciac2a3a822019-07-17 14:29:12 -07002627 (memcmp(&desc.type, SL_IID_VOLUME, sizeof(effect_uuid_t)) == 0) ||
2628 (memcmp(&desc.type, SL_IID_DYNAMICSPROCESSING, sizeof(effect_uuid_t)) == 0))) {
Eric Laurentca7cc822012-11-19 14:55:58 -08002629 return false;
2630 }
2631 return true;
2632}
2633
2634void AudioFlinger::EffectChain::getSuspendEligibleEffects(
2635 Vector< sp<AudioFlinger::EffectModule> > &effects)
2636{
2637 effects.clear();
2638 for (size_t i = 0; i < mEffects.size(); i++) {
2639 if (isEffectEligibleForSuspend(mEffects[i]->desc())) {
2640 effects.add(mEffects[i]);
2641 }
2642 }
2643}
2644
2645sp<AudioFlinger::EffectModule> AudioFlinger::EffectChain::getEffectIfEnabled(
2646 const effect_uuid_t *type)
2647{
2648 sp<EffectModule> effect = getEffectFromType_l(type);
2649 return effect != 0 && effect->isEnabled() ? effect : 0;
2650}
2651
2652void AudioFlinger::EffectChain::checkSuspendOnEffectEnabled(const sp<EffectModule>& effect,
2653 bool enabled)
2654{
2655 ssize_t index = mSuspendedEffects.indexOfKey(effect->desc().type.timeLow);
2656 if (enabled) {
2657 if (index < 0) {
2658 // if the effect is not suspend check if all effects are suspended
2659 index = mSuspendedEffects.indexOfKey((int)kKeyForSuspendAll);
2660 if (index < 0) {
2661 return;
2662 }
2663 if (!isEffectEligibleForSuspend(effect->desc())) {
2664 return;
2665 }
2666 setEffectSuspended_l(&effect->desc().type, enabled);
2667 index = mSuspendedEffects.indexOfKey(effect->desc().type.timeLow);
2668 if (index < 0) {
2669 ALOGW("checkSuspendOnEffectEnabled() Fx should be suspended here!");
2670 return;
2671 }
2672 }
2673 ALOGV("checkSuspendOnEffectEnabled() enable suspending fx %08x",
2674 effect->desc().type.timeLow);
2675 sp<SuspendedEffectDesc> desc = mSuspendedEffects.valueAt(index);
Eric Laurentd8365c52017-07-16 15:27:05 -07002676 // if effect is requested to suspended but was not yet enabled, suspend it now.
Eric Laurentca7cc822012-11-19 14:55:58 -08002677 if (desc->mEffect == 0) {
2678 desc->mEffect = effect;
Eric Laurent6b446ce2019-12-13 10:56:31 -08002679 effect->setEnabled(false, false /*fromHandle*/);
Eric Laurentca7cc822012-11-19 14:55:58 -08002680 effect->setSuspended(true);
2681 }
2682 } else {
2683 if (index < 0) {
2684 return;
2685 }
2686 ALOGV("checkSuspendOnEffectEnabled() disable restoring fx %08x",
2687 effect->desc().type.timeLow);
2688 sp<SuspendedEffectDesc> desc = mSuspendedEffects.valueAt(index);
2689 desc->mEffect.clear();
2690 effect->setSuspended(false);
2691 }
2692}
2693
Eric Laurent5baf2af2013-09-12 17:37:00 -07002694bool AudioFlinger::EffectChain::isNonOffloadableEnabled()
Eric Laurent813e2a72013-08-31 12:59:48 -07002695{
2696 Mutex::Autolock _l(mLock);
Shingo Kitajima1f8df9a2018-05-29 11:35:06 +09002697 return isNonOffloadableEnabled_l();
2698}
2699
2700bool AudioFlinger::EffectChain::isNonOffloadableEnabled_l()
2701{
Eric Laurent813e2a72013-08-31 12:59:48 -07002702 size_t size = mEffects.size();
2703 for (size_t i = 0; i < size; i++) {
Eric Laurent5baf2af2013-09-12 17:37:00 -07002704 if (mEffects[i]->isEnabled() && !mEffects[i]->isOffloadable()) {
Eric Laurent813e2a72013-08-31 12:59:48 -07002705 return true;
2706 }
2707 }
2708 return false;
2709}
2710
Eric Laurentaaa44472014-09-12 17:41:50 -07002711void AudioFlinger::EffectChain::setThread(const sp<ThreadBase>& thread)
2712{
2713 Mutex::Autolock _l(mLock);
Ytai Ben-Tsvi3de1bbf2020-01-21 16:41:17 -08002714 mEffectCallback->setThread(thread);
Eric Laurentaaa44472014-09-12 17:41:50 -07002715}
2716
Andy Hungd3bb0ad2016-10-11 17:16:43 -07002717void AudioFlinger::EffectChain::checkOutputFlagCompatibility(audio_output_flags_t *flags) const
2718{
2719 if ((*flags & AUDIO_OUTPUT_FLAG_RAW) != 0 && !isRawCompatible()) {
2720 *flags = (audio_output_flags_t)(*flags & ~AUDIO_OUTPUT_FLAG_RAW);
2721 }
2722 if ((*flags & AUDIO_OUTPUT_FLAG_FAST) != 0 && !isFastCompatible()) {
2723 *flags = (audio_output_flags_t)(*flags & ~AUDIO_OUTPUT_FLAG_FAST);
2724 }
2725}
2726
2727void AudioFlinger::EffectChain::checkInputFlagCompatibility(audio_input_flags_t *flags) const
2728{
2729 if ((*flags & AUDIO_INPUT_FLAG_RAW) != 0 && !isRawCompatible()) {
2730 *flags = (audio_input_flags_t)(*flags & ~AUDIO_INPUT_FLAG_RAW);
2731 }
2732 if ((*flags & AUDIO_INPUT_FLAG_FAST) != 0 && !isFastCompatible()) {
2733 *flags = (audio_input_flags_t)(*flags & ~AUDIO_INPUT_FLAG_FAST);
2734 }
2735}
2736
2737bool AudioFlinger::EffectChain::isRawCompatible() const
Eric Laurent4c415062016-06-17 16:14:16 -07002738{
2739 Mutex::Autolock _l(mLock);
Andy Hungd3bb0ad2016-10-11 17:16:43 -07002740 for (const auto &effect : mEffects) {
2741 if (effect->isProcessImplemented()) {
2742 return false;
Eric Laurent4c415062016-06-17 16:14:16 -07002743 }
2744 }
Andy Hungd3bb0ad2016-10-11 17:16:43 -07002745 // Allow effects without processing.
2746 return true;
2747}
2748
2749bool AudioFlinger::EffectChain::isFastCompatible() const
2750{
2751 Mutex::Autolock _l(mLock);
2752 for (const auto &effect : mEffects) {
2753 if (effect->isProcessImplemented()
2754 && effect->isImplementationSoftware()) {
2755 return false;
2756 }
2757 }
2758 // Allow effects without processing or hw accelerated effects.
2759 return true;
Eric Laurent4c415062016-06-17 16:14:16 -07002760}
2761
2762// isCompatibleWithThread_l() must be called with thread->mLock held
2763bool AudioFlinger::EffectChain::isCompatibleWithThread_l(const sp<ThreadBase>& thread) const
2764{
2765 Mutex::Autolock _l(mLock);
2766 for (size_t i = 0; i < mEffects.size(); i++) {
2767 if (thread->checkEffectCompatibility_l(&(mEffects[i]->desc()), mSessionId) != NO_ERROR) {
2768 return false;
2769 }
2770 }
2771 return true;
2772}
2773
Eric Laurent6b446ce2019-12-13 10:56:31 -08002774// EffectCallbackInterface implementation
2775status_t AudioFlinger::EffectChain::EffectCallback::createEffectHal(
2776 const effect_uuid_t *pEffectUuid, int32_t sessionId, int32_t deviceId,
2777 sp<EffectHalInterface> *effect) {
2778 status_t status = NO_INIT;
2779 sp<AudioFlinger> af = mAudioFlinger.promote();
2780 if (af == nullptr) {
2781 return status;
2782 }
2783 sp<EffectsFactoryHalInterface> effectsFactory = af->getEffectsFactory();
2784 if (effectsFactory != 0) {
2785 status = effectsFactory->createEffect(pEffectUuid, sessionId, io(), deviceId, effect);
2786 }
2787 return status;
2788}
2789
2790bool AudioFlinger::EffectChain::EffectCallback::updateOrphanEffectChains(
Eric Laurent41709552019-12-16 19:34:05 -08002791 const sp<AudioFlinger::EffectBase>& effect) {
Eric Laurent6b446ce2019-12-13 10:56:31 -08002792 sp<AudioFlinger> af = mAudioFlinger.promote();
2793 if (af == nullptr) {
2794 return false;
2795 }
Eric Laurent41709552019-12-16 19:34:05 -08002796 // in EffectChain context, an EffectBase is always from an EffectModule so static cast is safe
2797 return af->updateOrphanEffectChains(effect->asEffectModule());
Eric Laurent6b446ce2019-12-13 10:56:31 -08002798}
2799
2800status_t AudioFlinger::EffectChain::EffectCallback::allocateHalBuffer(
2801 size_t size, sp<EffectBufferHalInterface>* buffer) {
2802 sp<AudioFlinger> af = mAudioFlinger.promote();
2803 LOG_ALWAYS_FATAL_IF(af == nullptr, "allocateHalBuffer() could not retrieved audio flinger");
2804 return af->mEffectsFactoryHal->allocateBuffer(size, buffer);
2805}
2806
2807status_t AudioFlinger::EffectChain::EffectCallback::addEffectToHal(
2808 sp<EffectHalInterface> effect) {
2809 status_t result = NO_INIT;
2810 sp<ThreadBase> t = mThread.promote();
2811 if (t == nullptr) {
2812 return result;
2813 }
2814 sp <StreamHalInterface> st = t->stream();
2815 if (st == nullptr) {
2816 return result;
2817 }
2818 result = st->addEffect(effect);
2819 ALOGE_IF(result != OK, "Error when adding effect: %d", result);
2820 return result;
2821}
2822
2823status_t AudioFlinger::EffectChain::EffectCallback::removeEffectFromHal(
2824 sp<EffectHalInterface> effect) {
2825 status_t result = NO_INIT;
2826 sp<ThreadBase> t = mThread.promote();
2827 if (t == nullptr) {
2828 return result;
2829 }
2830 sp <StreamHalInterface> st = t->stream();
2831 if (st == nullptr) {
2832 return result;
2833 }
2834 result = st->removeEffect(effect);
2835 ALOGE_IF(result != OK, "Error when removing effect: %d", result);
2836 return result;
2837}
2838
2839audio_io_handle_t AudioFlinger::EffectChain::EffectCallback::io() const {
2840 sp<ThreadBase> t = mThread.promote();
2841 if (t == nullptr) {
2842 return AUDIO_IO_HANDLE_NONE;
2843 }
2844 return t->id();
2845}
2846
2847bool AudioFlinger::EffectChain::EffectCallback::isOutput() const {
2848 sp<ThreadBase> t = mThread.promote();
2849 if (t == nullptr) {
2850 return true;
2851 }
2852 return t->isOutput();
2853}
2854
2855bool AudioFlinger::EffectChain::EffectCallback::isOffload() const {
2856 sp<ThreadBase> t = mThread.promote();
2857 if (t == nullptr) {
2858 return false;
2859 }
2860 return t->type() == ThreadBase::OFFLOAD;
2861}
2862
2863bool AudioFlinger::EffectChain::EffectCallback::isOffloadOrDirect() const {
2864 sp<ThreadBase> t = mThread.promote();
2865 if (t == nullptr) {
2866 return false;
2867 }
2868 return t->type() == ThreadBase::OFFLOAD || t->type() == ThreadBase::DIRECT;
2869}
2870
2871bool AudioFlinger::EffectChain::EffectCallback::isOffloadOrMmap() const {
2872 sp<ThreadBase> t = mThread.promote();
2873 if (t == nullptr) {
2874 return false;
2875 }
Andy Hungea840382020-05-05 21:50:17 -07002876 return t->isOffloadOrMmap();
Eric Laurent6b446ce2019-12-13 10:56:31 -08002877}
2878
2879uint32_t AudioFlinger::EffectChain::EffectCallback::sampleRate() const {
2880 sp<ThreadBase> t = mThread.promote();
2881 if (t == nullptr) {
2882 return 0;
2883 }
2884 return t->sampleRate();
2885}
2886
2887audio_channel_mask_t AudioFlinger::EffectChain::EffectCallback::channelMask() const {
2888 sp<ThreadBase> t = mThread.promote();
2889 if (t == nullptr) {
2890 return AUDIO_CHANNEL_NONE;
2891 }
2892 return t->channelMask();
2893}
2894
2895uint32_t AudioFlinger::EffectChain::EffectCallback::channelCount() const {
2896 sp<ThreadBase> t = mThread.promote();
2897 if (t == nullptr) {
2898 return 0;
2899 }
2900 return t->channelCount();
2901}
2902
jiabineb3bda02020-06-30 14:07:03 -07002903audio_channel_mask_t AudioFlinger::EffectChain::EffectCallback::hapticChannelMask() const {
2904 sp<ThreadBase> t = mThread.promote();
2905 if (t == nullptr) {
2906 return AUDIO_CHANNEL_NONE;
2907 }
2908 return t->hapticChannelMask();
2909}
2910
Eric Laurent6b446ce2019-12-13 10:56:31 -08002911size_t AudioFlinger::EffectChain::EffectCallback::frameCount() const {
2912 sp<ThreadBase> t = mThread.promote();
2913 if (t == nullptr) {
2914 return 0;
2915 }
2916 return t->frameCount();
2917}
2918
2919uint32_t AudioFlinger::EffectChain::EffectCallback::latency() const {
2920 sp<ThreadBase> t = mThread.promote();
2921 if (t == nullptr) {
2922 return 0;
2923 }
2924 return t->latency_l();
2925}
2926
2927void AudioFlinger::EffectChain::EffectCallback::setVolumeForOutput(float left, float right) const {
2928 sp<ThreadBase> t = mThread.promote();
2929 if (t == nullptr) {
2930 return;
2931 }
2932 t->setVolumeForOutput_l(left, right);
2933}
2934
2935void AudioFlinger::EffectChain::EffectCallback::checkSuspendOnEffectEnabled(
Eric Laurent41709552019-12-16 19:34:05 -08002936 const sp<EffectBase>& effect, bool enabled, bool threadLocked) {
Eric Laurent6b446ce2019-12-13 10:56:31 -08002937 sp<ThreadBase> t = mThread.promote();
2938 if (t == nullptr) {
2939 return;
2940 }
2941 t->checkSuspendOnEffectEnabled(enabled, effect->sessionId(), threadLocked);
2942
2943 sp<EffectChain> c = mChain.promote();
2944 if (c == nullptr) {
2945 return;
2946 }
Eric Laurent41709552019-12-16 19:34:05 -08002947 // in EffectChain context, an EffectBase is always from an EffectModule so static cast is safe
2948 c->checkSuspendOnEffectEnabled(effect->asEffectModule(), enabled);
Eric Laurent6b446ce2019-12-13 10:56:31 -08002949}
2950
Eric Laurent41709552019-12-16 19:34:05 -08002951void AudioFlinger::EffectChain::EffectCallback::onEffectEnable(const sp<EffectBase>& effect) {
Eric Laurent6b446ce2019-12-13 10:56:31 -08002952 sp<ThreadBase> t = mThread.promote();
2953 if (t == nullptr) {
2954 return;
2955 }
Eric Laurent41709552019-12-16 19:34:05 -08002956 // in EffectChain context, an EffectBase is always from an EffectModule so static cast is safe
2957 t->onEffectEnable(effect->asEffectModule());
Eric Laurent6b446ce2019-12-13 10:56:31 -08002958}
2959
Eric Laurent41709552019-12-16 19:34:05 -08002960void AudioFlinger::EffectChain::EffectCallback::onEffectDisable(const sp<EffectBase>& effect) {
Eric Laurent6b446ce2019-12-13 10:56:31 -08002961 checkSuspendOnEffectEnabled(effect, false, false /*threadLocked*/);
2962
2963 sp<ThreadBase> t = mThread.promote();
2964 if (t == nullptr) {
2965 return;
2966 }
2967 t->onEffectDisable();
2968}
2969
2970bool AudioFlinger::EffectChain::EffectCallback::disconnectEffectHandle(EffectHandle *handle,
2971 bool unpinIfLast) {
2972 sp<ThreadBase> t = mThread.promote();
2973 if (t == nullptr) {
2974 return false;
2975 }
2976 t->disconnectEffectHandle(handle, unpinIfLast);
2977 return true;
2978}
2979
2980void AudioFlinger::EffectChain::EffectCallback::resetVolume() {
2981 sp<EffectChain> c = mChain.promote();
2982 if (c == nullptr) {
2983 return;
2984 }
2985 c->resetVolume_l();
2986
2987}
2988
2989uint32_t AudioFlinger::EffectChain::EffectCallback::strategy() const {
2990 sp<EffectChain> c = mChain.promote();
2991 if (c == nullptr) {
2992 return PRODUCT_STRATEGY_NONE;
2993 }
2994 return c->strategy();
2995}
2996
2997int32_t AudioFlinger::EffectChain::EffectCallback::activeTrackCnt() const {
2998 sp<EffectChain> c = mChain.promote();
2999 if (c == nullptr) {
3000 return 0;
3001 }
3002 return c->activeTrackCnt();
3003}
3004
Eric Laurentb82e6b72019-11-22 17:25:04 -08003005
3006#undef LOG_TAG
3007#define LOG_TAG "AudioFlinger::DeviceEffectProxy"
3008
3009status_t AudioFlinger::DeviceEffectProxy::setEnabled(bool enabled, bool fromHandle)
3010{
3011 status_t status = EffectBase::setEnabled(enabled, fromHandle);
3012 Mutex::Autolock _l(mProxyLock);
3013 if (status == NO_ERROR) {
3014 for (auto& handle : mEffectHandles) {
3015 if (enabled) {
3016 status = handle.second->enable();
3017 } else {
3018 status = handle.second->disable();
3019 }
3020 }
3021 }
3022 ALOGV("%s enable %d status %d", __func__, enabled, status);
3023 return status;
3024}
3025
3026status_t AudioFlinger::DeviceEffectProxy::init(
3027 const std::map <audio_patch_handle_t, PatchPanel::Patch>& patches) {
3028//For all audio patches
3029//If src or sink device match
3030//If the effect is HW accelerated
3031// if no corresponding effect module
3032// Create EffectModule: mHalEffect
3033//Create and attach EffectHandle
3034//If the effect is not HW accelerated and the patch sink or src is a mixer port
3035// Create Effect on patch input or output thread on session -1
3036//Add EffectHandle to EffectHandle map of Effect Proxy:
3037 ALOGV("%s device type %d address %s", __func__, mDevice.mType, mDevice.getAddress());
3038 status_t status = NO_ERROR;
3039 for (auto &patch : patches) {
3040 status = onCreatePatch(patch.first, patch.second);
3041 ALOGV("%s onCreatePatch status %d", __func__, status);
3042 if (status == BAD_VALUE) {
3043 return status;
3044 }
3045 }
3046 return status;
3047}
3048
3049status_t AudioFlinger::DeviceEffectProxy::onCreatePatch(
3050 audio_patch_handle_t patchHandle, const AudioFlinger::PatchPanel::Patch& patch) {
3051 status_t status = NAME_NOT_FOUND;
3052 sp<EffectHandle> handle;
3053 // only consider source[0] as this is the only "true" source of a patch
3054 status = checkPort(patch, &patch.mAudioPatch.sources[0], &handle);
3055 ALOGV("%s source checkPort status %d", __func__, status);
3056 for (uint32_t i = 0; i < patch.mAudioPatch.num_sinks && status == NAME_NOT_FOUND; i++) {
3057 status = checkPort(patch, &patch.mAudioPatch.sinks[i], &handle);
3058 ALOGV("%s sink %d checkPort status %d", __func__, i, status);
3059 }
3060 if (status == NO_ERROR || status == ALREADY_EXISTS) {
3061 Mutex::Autolock _l(mProxyLock);
3062 mEffectHandles.emplace(patchHandle, handle);
3063 }
3064 ALOGW_IF(status == BAD_VALUE,
3065 "%s cannot attach effect %s on patch %d", __func__, mDescriptor.name, patchHandle);
3066
3067 return status;
3068}
3069
3070status_t AudioFlinger::DeviceEffectProxy::checkPort(const PatchPanel::Patch& patch,
3071 const struct audio_port_config *port, sp <EffectHandle> *handle) {
3072
3073 ALOGV("%s type %d device type %d address %s device ID %d patch.isSoftware() %d",
3074 __func__, port->type, port->ext.device.type,
3075 port->ext.device.address, port->id, patch.isSoftware());
3076 if (port->type != AUDIO_PORT_TYPE_DEVICE || port->ext.device.type != mDevice.mType
jiabin0a488932020-08-07 17:32:40 -07003077 || port->ext.device.address != mDevice.address()) {
Eric Laurentb82e6b72019-11-22 17:25:04 -08003078 return NAME_NOT_FOUND;
3079 }
3080 status_t status = NAME_NOT_FOUND;
3081
3082 if (mDescriptor.flags & EFFECT_FLAG_HW_ACC_TUNNEL) {
3083 Mutex::Autolock _l(mProxyLock);
3084 mDevicePort = *port;
3085 mHalEffect = new EffectModule(mMyCallback,
3086 const_cast<effect_descriptor_t *>(&mDescriptor),
3087 mMyCallback->newEffectId(), AUDIO_SESSION_DEVICE,
3088 false /* pinned */, port->id);
3089 if (audio_is_input_device(mDevice.mType)) {
3090 mHalEffect->setInputDevice(mDevice);
3091 } else {
3092 mHalEffect->setDevices({mDevice});
3093 }
3094 *handle = new EffectHandle(mHalEffect, nullptr, nullptr, 0 /*priority*/);
3095 status = (*handle)->initCheck();
3096 if (status == OK) {
3097 status = mHalEffect->addHandle((*handle).get());
3098 } else {
3099 mHalEffect.clear();
3100 mDevicePort.id = AUDIO_PORT_HANDLE_NONE;
3101 }
3102 } else if (patch.isSoftware() || patch.thread().promote() != nullptr) {
3103 sp <ThreadBase> thread;
3104 if (audio_port_config_has_input_direction(port)) {
3105 if (patch.isSoftware()) {
3106 thread = patch.mRecord.thread();
3107 } else {
3108 thread = patch.thread().promote();
3109 }
3110 } else {
3111 if (patch.isSoftware()) {
3112 thread = patch.mPlayback.thread();
3113 } else {
3114 thread = patch.thread().promote();
3115 }
3116 }
3117 int enabled;
3118 *handle = thread->createEffect_l(nullptr, nullptr, 0, AUDIO_SESSION_DEVICE,
3119 const_cast<effect_descriptor_t *>(&mDescriptor),
Eric Laurent2fe0acd2020-03-13 14:30:46 -07003120 &enabled, &status, false, false /*probe*/);
Eric Laurentb82e6b72019-11-22 17:25:04 -08003121 ALOGV("%s thread->createEffect_l status %d", __func__, status);
3122 } else {
3123 status = BAD_VALUE;
3124 }
3125 if (status == NO_ERROR || status == ALREADY_EXISTS) {
3126 if (isEnabled()) {
3127 (*handle)->enable();
3128 } else {
3129 (*handle)->disable();
3130 }
3131 }
3132 return status;
3133}
3134
3135void AudioFlinger::DeviceEffectProxy::onReleasePatch(audio_patch_handle_t patchHandle) {
3136 Mutex::Autolock _l(mProxyLock);
3137 mEffectHandles.erase(patchHandle);
3138}
3139
3140
3141size_t AudioFlinger::DeviceEffectProxy::removeEffect(const sp<EffectModule>& effect)
3142{
3143 Mutex::Autolock _l(mProxyLock);
3144 if (effect == mHalEffect) {
3145 mHalEffect.clear();
3146 mDevicePort.id = AUDIO_PORT_HANDLE_NONE;
3147 }
3148 return mHalEffect == nullptr ? 0 : 1;
3149}
3150
3151status_t AudioFlinger::DeviceEffectProxy::addEffectToHal(
3152 sp<EffectHalInterface> effect) {
3153 if (mHalEffect == nullptr) {
3154 return NO_INIT;
3155 }
3156 return mManagerCallback->addEffectToHal(
3157 mDevicePort.id, mDevicePort.ext.device.hw_module, effect);
3158}
3159
3160status_t AudioFlinger::DeviceEffectProxy::removeEffectFromHal(
3161 sp<EffectHalInterface> effect) {
3162 if (mHalEffect == nullptr) {
3163 return NO_INIT;
3164 }
3165 return mManagerCallback->removeEffectFromHal(
3166 mDevicePort.id, mDevicePort.ext.device.hw_module, effect);
3167}
3168
3169bool AudioFlinger::DeviceEffectProxy::isOutput() const {
3170 if (mDevicePort.id != AUDIO_PORT_HANDLE_NONE) {
3171 return mDevicePort.role == AUDIO_PORT_ROLE_SINK;
3172 }
3173 return true;
3174}
3175
3176uint32_t AudioFlinger::DeviceEffectProxy::sampleRate() const {
3177 if (mDevicePort.id != AUDIO_PORT_HANDLE_NONE &&
3178 (mDevicePort.config_mask & AUDIO_PORT_CONFIG_SAMPLE_RATE) != 0) {
3179 return mDevicePort.sample_rate;
3180 }
3181 return DEFAULT_OUTPUT_SAMPLE_RATE;
3182}
3183
3184audio_channel_mask_t AudioFlinger::DeviceEffectProxy::channelMask() const {
3185 if (mDevicePort.id != AUDIO_PORT_HANDLE_NONE &&
3186 (mDevicePort.config_mask & AUDIO_PORT_CONFIG_CHANNEL_MASK) != 0) {
3187 return mDevicePort.channel_mask;
3188 }
3189 return AUDIO_CHANNEL_OUT_STEREO;
3190}
3191
3192uint32_t AudioFlinger::DeviceEffectProxy::channelCount() const {
3193 if (isOutput()) {
3194 return audio_channel_count_from_out_mask(channelMask());
3195 }
3196 return audio_channel_count_from_in_mask(channelMask());
3197}
3198
3199void AudioFlinger::DeviceEffectProxy::dump(int fd, int spaces) {
3200 const Vector<String16> args;
3201 EffectBase::dump(fd, args);
3202
3203 const bool locked = dumpTryLock(mProxyLock);
3204 if (!locked) {
3205 String8 result("DeviceEffectProxy may be deadlocked\n");
3206 write(fd, result.string(), result.size());
3207 }
3208
3209 String8 outStr;
3210 if (mHalEffect != nullptr) {
3211 outStr.appendFormat("%*sHAL Effect Id: %d\n", spaces, "", mHalEffect->id());
3212 } else {
3213 outStr.appendFormat("%*sNO HAL Effect\n", spaces, "");
3214 }
3215 write(fd, outStr.string(), outStr.size());
3216 outStr.clear();
3217
3218 outStr.appendFormat("%*sSub Effects:\n", spaces, "");
3219 write(fd, outStr.string(), outStr.size());
3220 outStr.clear();
3221
3222 for (const auto& iter : mEffectHandles) {
3223 outStr.appendFormat("%*sEffect for patch handle %d:\n", spaces + 2, "", iter.first);
3224 write(fd, outStr.string(), outStr.size());
3225 outStr.clear();
3226 sp<EffectBase> effect = iter.second->effect().promote();
3227 if (effect != nullptr) {
3228 effect->dump(fd, args);
3229 }
3230 }
3231
3232 if (locked) {
3233 mLock.unlock();
3234 }
3235}
3236
3237#undef LOG_TAG
3238#define LOG_TAG "AudioFlinger::DeviceEffectProxy::ProxyCallback"
3239
3240int AudioFlinger::DeviceEffectProxy::ProxyCallback::newEffectId() {
3241 return mManagerCallback->newEffectId();
3242}
3243
3244
3245bool AudioFlinger::DeviceEffectProxy::ProxyCallback::disconnectEffectHandle(
3246 EffectHandle *handle, bool unpinIfLast) {
3247 sp<EffectBase> effectBase = handle->effect().promote();
3248 if (effectBase == nullptr) {
3249 return false;
3250 }
3251
3252 sp<EffectModule> effect = effectBase->asEffectModule();
3253 if (effect == nullptr) {
3254 return false;
3255 }
3256
3257 // restore suspended effects if the disconnected handle was enabled and the last one.
3258 bool remove = (effect->removeHandle(handle) == 0) && (!effect->isPinned() || unpinIfLast);
3259 if (remove) {
3260 sp<DeviceEffectProxy> proxy = mProxy.promote();
3261 if (proxy != nullptr) {
3262 proxy->removeEffect(effect);
3263 }
3264 if (handle->enabled()) {
3265 effectBase->checkSuspendOnEffectEnabled(false, false /*threadLocked*/);
3266 }
3267 }
3268 return true;
3269}
3270
3271status_t AudioFlinger::DeviceEffectProxy::ProxyCallback::createEffectHal(
3272 const effect_uuid_t *pEffectUuid, int32_t sessionId, int32_t deviceId,
3273 sp<EffectHalInterface> *effect) {
3274 return mManagerCallback->createEffectHal(pEffectUuid, sessionId, deviceId, effect);
3275}
3276
3277status_t AudioFlinger::DeviceEffectProxy::ProxyCallback::addEffectToHal(
3278 sp<EffectHalInterface> effect) {
3279 sp<DeviceEffectProxy> proxy = mProxy.promote();
3280 if (proxy == nullptr) {
3281 return NO_INIT;
3282 }
3283 return proxy->addEffectToHal(effect);
3284}
3285
3286status_t AudioFlinger::DeviceEffectProxy::ProxyCallback::removeEffectFromHal(
3287 sp<EffectHalInterface> effect) {
3288 sp<DeviceEffectProxy> proxy = mProxy.promote();
3289 if (proxy == nullptr) {
3290 return NO_INIT;
3291 }
3292 return proxy->addEffectToHal(effect);
3293}
3294
3295bool AudioFlinger::DeviceEffectProxy::ProxyCallback::isOutput() const {
3296 sp<DeviceEffectProxy> proxy = mProxy.promote();
3297 if (proxy == nullptr) {
3298 return true;
3299 }
3300 return proxy->isOutput();
3301}
3302
3303uint32_t AudioFlinger::DeviceEffectProxy::ProxyCallback::sampleRate() const {
3304 sp<DeviceEffectProxy> proxy = mProxy.promote();
3305 if (proxy == nullptr) {
3306 return DEFAULT_OUTPUT_SAMPLE_RATE;
3307 }
3308 return proxy->sampleRate();
3309}
3310
3311audio_channel_mask_t AudioFlinger::DeviceEffectProxy::ProxyCallback::channelMask() const {
3312 sp<DeviceEffectProxy> proxy = mProxy.promote();
3313 if (proxy == nullptr) {
3314 return AUDIO_CHANNEL_OUT_STEREO;
3315 }
3316 return proxy->channelMask();
3317}
3318
3319uint32_t AudioFlinger::DeviceEffectProxy::ProxyCallback::channelCount() const {
3320 sp<DeviceEffectProxy> proxy = mProxy.promote();
3321 if (proxy == nullptr) {
3322 return 2;
3323 }
3324 return proxy->channelCount();
3325}
3326
Glenn Kasten63238ef2015-03-02 15:50:29 -08003327} // namespace android