blob: 8426a77b51263a99444bebd77868d31d7697af7e [file] [log] [blame]
bryant_liuba2b4392014-06-11 16:49:30 +08001/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "AudioPolicyEffects"
Eric Laurent897a4082014-07-11 16:51:53 -070018//#define LOG_NDEBUG 0
bryant_liuba2b4392014-06-11 16:49:30 +080019
20#include <stdlib.h>
21#include <stdio.h>
22#include <string.h>
Kevin Rocard4fb615c2017-06-26 10:28:13 -070023#include <memory>
bryant_liuba2b4392014-06-11 16:49:30 +080024#include <cutils/misc.h>
25#include <media/AudioEffect.h>
Kevin Rocard4fb615c2017-06-26 10:28:13 -070026#include <media/EffectsConfig.h>
Andy Hungab7ef302018-05-15 19:35:29 -070027#include <mediautils/ServiceUtilities.h>
bryant_liuba2b4392014-06-11 16:49:30 +080028#include <system/audio.h>
Mikhail Naganovc2f710f2016-10-17 18:05:36 -070029#include <system/audio_effects/audio_effects_conf.h>
bryant_liuba2b4392014-06-11 16:49:30 +080030#include <utils/Vector.h>
31#include <utils/SortedVector.h>
32#include <cutils/config_utils.h>
Eric Laurentb6436272016-12-07 19:24:50 -080033#include <binder/IPCThreadState.h>
bryant_liuba2b4392014-06-11 16:49:30 +080034#include "AudioPolicyEffects.h"
bryant_liuba2b4392014-06-11 16:49:30 +080035
36namespace android {
37
Philip P. Moltmannbda45752020-07-17 16:41:18 -070038using media::permission::Identity;
39
bryant_liuba2b4392014-06-11 16:49:30 +080040// ----------------------------------------------------------------------------
41// AudioPolicyEffects Implementation
42// ----------------------------------------------------------------------------
43
44AudioPolicyEffects::AudioPolicyEffects()
45{
Kevin Rocard4fb615c2017-06-26 10:28:13 -070046 status_t loadResult = loadAudioEffectXmlConfig();
François Gaffie06182982020-01-07 15:16:14 +010047 if (loadResult == NO_ERROR) {
48 mDefaultDeviceEffectFuture = std::async(
49 std::launch::async, &AudioPolicyEffects::initDefaultDeviceEffects, this);
50 } else if (loadResult < 0) {
Kevin Rocard4fb615c2017-06-26 10:28:13 -070051 ALOGW("Failed to load XML effect configuration, fallback to .conf");
52 // load automatic audio effect modules
53 if (access(AUDIO_EFFECT_VENDOR_CONFIG_FILE, R_OK) == 0) {
54 loadAudioEffectConfig(AUDIO_EFFECT_VENDOR_CONFIG_FILE);
55 } else if (access(AUDIO_EFFECT_DEFAULT_CONFIG_FILE, R_OK) == 0) {
56 loadAudioEffectConfig(AUDIO_EFFECT_DEFAULT_CONFIG_FILE);
57 }
58 } else if (loadResult > 0) {
59 ALOGE("Effect config is partially invalid, skipped %d elements", loadResult);
bryant_liuba2b4392014-06-11 16:49:30 +080060 }
61}
62
63
64AudioPolicyEffects::~AudioPolicyEffects()
65{
66 size_t i = 0;
67 // release audio input processing resources
68 for (i = 0; i < mInputSources.size(); i++) {
69 delete mInputSources.valueAt(i);
70 }
71 mInputSources.clear();
72
Eric Laurentfb66dd92016-01-28 18:32:03 -080073 for (i = 0; i < mInputSessions.size(); i++) {
74 mInputSessions.valueAt(i)->mEffects.clear();
75 delete mInputSessions.valueAt(i);
bryant_liuba2b4392014-06-11 16:49:30 +080076 }
Eric Laurentfb66dd92016-01-28 18:32:03 -080077 mInputSessions.clear();
bryant_liuba2b4392014-06-11 16:49:30 +080078
79 // release audio output processing resources
80 for (i = 0; i < mOutputStreams.size(); i++) {
81 delete mOutputStreams.valueAt(i);
82 }
83 mOutputStreams.clear();
84
85 for (i = 0; i < mOutputSessions.size(); i++) {
86 mOutputSessions.valueAt(i)->mEffects.clear();
87 delete mOutputSessions.valueAt(i);
88 }
89 mOutputSessions.clear();
90}
91
92
93status_t AudioPolicyEffects::addInputEffects(audio_io_handle_t input,
94 audio_source_t inputSource,
Eric Laurentfb66dd92016-01-28 18:32:03 -080095 audio_session_t audioSession)
bryant_liuba2b4392014-06-11 16:49:30 +080096{
97 status_t status = NO_ERROR;
98
99 // create audio pre processors according to input source
100 audio_source_t aliasSource = (inputSource == AUDIO_SOURCE_HOTWORD) ?
101 AUDIO_SOURCE_VOICE_RECOGNITION : inputSource;
102
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700103 Mutex::Autolock _l(mLock);
bryant_liuba2b4392014-06-11 16:49:30 +0800104 ssize_t index = mInputSources.indexOfKey(aliasSource);
105 if (index < 0) {
106 ALOGV("addInputEffects(): no processing needs to be attached to this source");
107 return status;
108 }
Eric Laurentfb66dd92016-01-28 18:32:03 -0800109 ssize_t idx = mInputSessions.indexOfKey(audioSession);
110 EffectVector *sessionDesc;
bryant_liuba2b4392014-06-11 16:49:30 +0800111 if (idx < 0) {
Eric Laurentfb66dd92016-01-28 18:32:03 -0800112 sessionDesc = new EffectVector(audioSession);
113 mInputSessions.add(audioSession, sessionDesc);
bryant_liuba2b4392014-06-11 16:49:30 +0800114 } else {
bryant_liu890a5632014-08-20 18:06:13 +0800115 // EffectVector is existing and we just need to increase ref count
Eric Laurentfb66dd92016-01-28 18:32:03 -0800116 sessionDesc = mInputSessions.valueAt(idx);
bryant_liuba2b4392014-06-11 16:49:30 +0800117 }
Eric Laurentfb66dd92016-01-28 18:32:03 -0800118 sessionDesc->mRefCount++;
bryant_liu890a5632014-08-20 18:06:13 +0800119
Eric Laurentfb66dd92016-01-28 18:32:03 -0800120 ALOGV("addInputEffects(): input: %d, refCount: %d", input, sessionDesc->mRefCount);
121 if (sessionDesc->mRefCount == 1) {
Eric Laurentb6436272016-12-07 19:24:50 -0800122 int64_t token = IPCThreadState::self()->clearCallingIdentity();
Eric Laurent7de5ac12014-10-21 09:07:11 -0700123 Vector <EffectDesc *> effects = mInputSources.valueAt(index)->mEffects;
124 for (size_t i = 0; i < effects.size(); i++) {
125 EffectDesc *effect = effects[i];
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700126 Identity identity;
127 identity.packageName = "android";
128 sp<AudioEffect> fx = new AudioEffect(identity);
Mikhail Naganov69d41cc2020-07-31 17:36:08 -0700129 fx->set(NULL, &effect->mUuid, -1, 0, 0, audioSession, input);
Eric Laurent7de5ac12014-10-21 09:07:11 -0700130 status_t status = fx->initCheck();
131 if (status != NO_ERROR && status != ALREADY_EXISTS) {
132 ALOGW("addInputEffects(): failed to create Fx %s on source %d",
133 effect->mName, (int32_t)aliasSource);
134 // fx goes out of scope and strong ref on AudioEffect is released
135 continue;
136 }
137 for (size_t j = 0; j < effect->mParams.size(); j++) {
138 fx->setParameter(effect->mParams[j]);
139 }
140 ALOGV("addInputEffects(): added Fx %s on source: %d",
bryant_liuba2b4392014-06-11 16:49:30 +0800141 effect->mName, (int32_t)aliasSource);
Eric Laurentfb66dd92016-01-28 18:32:03 -0800142 sessionDesc->mEffects.add(fx);
bryant_liuba2b4392014-06-11 16:49:30 +0800143 }
Eric Laurentfb66dd92016-01-28 18:32:03 -0800144 sessionDesc->setProcessorEnabled(true);
Eric Laurentb6436272016-12-07 19:24:50 -0800145 IPCThreadState::self()->restoreCallingIdentity(token);
bryant_liuba2b4392014-06-11 16:49:30 +0800146 }
bryant_liuba2b4392014-06-11 16:49:30 +0800147 return status;
148}
149
150
Eric Laurentfb66dd92016-01-28 18:32:03 -0800151status_t AudioPolicyEffects::releaseInputEffects(audio_io_handle_t input,
152 audio_session_t audioSession)
bryant_liuba2b4392014-06-11 16:49:30 +0800153{
154 status_t status = NO_ERROR;
155
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700156 Mutex::Autolock _l(mLock);
Eric Laurentfb66dd92016-01-28 18:32:03 -0800157 ssize_t index = mInputSessions.indexOfKey(audioSession);
bryant_liuba2b4392014-06-11 16:49:30 +0800158 if (index < 0) {
159 return status;
160 }
Eric Laurentfb66dd92016-01-28 18:32:03 -0800161 EffectVector *sessionDesc = mInputSessions.valueAt(index);
162 sessionDesc->mRefCount--;
163 ALOGV("releaseInputEffects(): input: %d, refCount: %d", input, sessionDesc->mRefCount);
164 if (sessionDesc->mRefCount == 0) {
165 sessionDesc->setProcessorEnabled(false);
166 delete sessionDesc;
167 mInputSessions.removeItemsAt(index);
bryant_liu890a5632014-08-20 18:06:13 +0800168 ALOGV("releaseInputEffects(): all effects released");
169 }
bryant_liuba2b4392014-06-11 16:49:30 +0800170 return status;
171}
172
Eric Laurentfb66dd92016-01-28 18:32:03 -0800173status_t AudioPolicyEffects::queryDefaultInputEffects(audio_session_t audioSession,
bryant_liuba2b4392014-06-11 16:49:30 +0800174 effect_descriptor_t *descriptors,
175 uint32_t *count)
176{
177 status_t status = NO_ERROR;
178
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700179 Mutex::Autolock _l(mLock);
bryant_liuba2b4392014-06-11 16:49:30 +0800180 size_t index;
Eric Laurentfb66dd92016-01-28 18:32:03 -0800181 for (index = 0; index < mInputSessions.size(); index++) {
182 if (mInputSessions.valueAt(index)->mSessionId == audioSession) {
bryant_liuba2b4392014-06-11 16:49:30 +0800183 break;
184 }
185 }
Eric Laurentfb66dd92016-01-28 18:32:03 -0800186 if (index == mInputSessions.size()) {
bryant_liuba2b4392014-06-11 16:49:30 +0800187 *count = 0;
188 return BAD_VALUE;
189 }
Eric Laurentfb66dd92016-01-28 18:32:03 -0800190 Vector< sp<AudioEffect> > effects = mInputSessions.valueAt(index)->mEffects;
bryant_liuba2b4392014-06-11 16:49:30 +0800191
192 for (size_t i = 0; i < effects.size(); i++) {
193 effect_descriptor_t desc = effects[i]->descriptor();
194 if (i < *count) {
195 descriptors[i] = desc;
196 }
197 }
198 if (effects.size() > *count) {
199 status = NO_MEMORY;
200 }
201 *count = effects.size();
202 return status;
203}
204
205
Eric Laurentfb66dd92016-01-28 18:32:03 -0800206status_t AudioPolicyEffects::queryDefaultOutputSessionEffects(audio_session_t audioSession,
bryant_liuba2b4392014-06-11 16:49:30 +0800207 effect_descriptor_t *descriptors,
208 uint32_t *count)
209{
210 status_t status = NO_ERROR;
211
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700212 Mutex::Autolock _l(mLock);
bryant_liuba2b4392014-06-11 16:49:30 +0800213 size_t index;
214 for (index = 0; index < mOutputSessions.size(); index++) {
215 if (mOutputSessions.valueAt(index)->mSessionId == audioSession) {
216 break;
217 }
218 }
219 if (index == mOutputSessions.size()) {
220 *count = 0;
221 return BAD_VALUE;
222 }
223 Vector< sp<AudioEffect> > effects = mOutputSessions.valueAt(index)->mEffects;
224
225 for (size_t i = 0; i < effects.size(); i++) {
226 effect_descriptor_t desc = effects[i]->descriptor();
227 if (i < *count) {
228 descriptors[i] = desc;
229 }
230 }
231 if (effects.size() > *count) {
232 status = NO_MEMORY;
233 }
234 *count = effects.size();
235 return status;
236}
237
238
239status_t AudioPolicyEffects::addOutputSessionEffects(audio_io_handle_t output,
240 audio_stream_type_t stream,
Eric Laurentfb66dd92016-01-28 18:32:03 -0800241 audio_session_t audioSession)
bryant_liuba2b4392014-06-11 16:49:30 +0800242{
243 status_t status = NO_ERROR;
244
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700245 Mutex::Autolock _l(mLock);
bryant_liuba2b4392014-06-11 16:49:30 +0800246 // create audio processors according to stream
Eric Laurent223fd5c2014-11-11 13:43:36 -0800247 // FIXME: should we have specific post processing settings for internal streams?
248 // default to media for now.
249 if (stream >= AUDIO_STREAM_PUBLIC_CNT) {
250 stream = AUDIO_STREAM_MUSIC;
251 }
bryant_liuba2b4392014-06-11 16:49:30 +0800252 ssize_t index = mOutputStreams.indexOfKey(stream);
253 if (index < 0) {
254 ALOGV("addOutputSessionEffects(): no output processing needed for this stream");
255 return NO_ERROR;
256 }
257
258 ssize_t idx = mOutputSessions.indexOfKey(audioSession);
259 EffectVector *procDesc;
260 if (idx < 0) {
261 procDesc = new EffectVector(audioSession);
262 mOutputSessions.add(audioSession, procDesc);
263 } else {
bryant_liu890a5632014-08-20 18:06:13 +0800264 // EffectVector is existing and we just need to increase ref count
bryant_liuba2b4392014-06-11 16:49:30 +0800265 procDesc = mOutputSessions.valueAt(idx);
266 }
bryant_liu890a5632014-08-20 18:06:13 +0800267 procDesc->mRefCount++;
268
Eric Laurent7de5ac12014-10-21 09:07:11 -0700269 ALOGV("addOutputSessionEffects(): session: %d, refCount: %d",
270 audioSession, procDesc->mRefCount);
271 if (procDesc->mRefCount == 1) {
Eric Laurentb6436272016-12-07 19:24:50 -0800272 // make sure effects are associated to audio server even if we are executing a binder call
273 int64_t token = IPCThreadState::self()->clearCallingIdentity();
Eric Laurent7de5ac12014-10-21 09:07:11 -0700274 Vector <EffectDesc *> effects = mOutputStreams.valueAt(index)->mEffects;
275 for (size_t i = 0; i < effects.size(); i++) {
276 EffectDesc *effect = effects[i];
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700277 Identity identity;
278 identity.packageName = "android";
279 sp<AudioEffect> fx = new AudioEffect(identity);
Mikhail Naganov69d41cc2020-07-31 17:36:08 -0700280 fx->set(NULL, &effect->mUuid, 0, 0, 0, audioSession, output);
Eric Laurent7de5ac12014-10-21 09:07:11 -0700281 status_t status = fx->initCheck();
282 if (status != NO_ERROR && status != ALREADY_EXISTS) {
283 ALOGE("addOutputSessionEffects(): failed to create Fx %s on session %d",
284 effect->mName, audioSession);
285 // fx goes out of scope and strong ref on AudioEffect is released
286 continue;
287 }
288 ALOGV("addOutputSessionEffects(): added Fx %s on session: %d for stream: %d",
289 effect->mName, audioSession, (int32_t)stream);
290 procDesc->mEffects.add(fx);
bryant_liuba2b4392014-06-11 16:49:30 +0800291 }
Eric Laurent7de5ac12014-10-21 09:07:11 -0700292
293 procDesc->setProcessorEnabled(true);
Eric Laurentb6436272016-12-07 19:24:50 -0800294 IPCThreadState::self()->restoreCallingIdentity(token);
bryant_liuba2b4392014-06-11 16:49:30 +0800295 }
bryant_liuba2b4392014-06-11 16:49:30 +0800296 return status;
297}
298
299status_t AudioPolicyEffects::releaseOutputSessionEffects(audio_io_handle_t output,
300 audio_stream_type_t stream,
Eric Laurentfb66dd92016-01-28 18:32:03 -0800301 audio_session_t audioSession)
bryant_liuba2b4392014-06-11 16:49:30 +0800302{
303 status_t status = NO_ERROR;
304 (void) output; // argument not used for now
305 (void) stream; // argument not used for now
306
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700307 Mutex::Autolock _l(mLock);
bryant_liuba2b4392014-06-11 16:49:30 +0800308 ssize_t index = mOutputSessions.indexOfKey(audioSession);
309 if (index < 0) {
310 ALOGV("releaseOutputSessionEffects: no output processing was attached to this stream");
311 return NO_ERROR;
312 }
313
314 EffectVector *procDesc = mOutputSessions.valueAt(index);
bryant_liu890a5632014-08-20 18:06:13 +0800315 procDesc->mRefCount--;
Eric Laurent7de5ac12014-10-21 09:07:11 -0700316 ALOGV("releaseOutputSessionEffects(): session: %d, refCount: %d",
317 audioSession, procDesc->mRefCount);
bryant_liu890a5632014-08-20 18:06:13 +0800318 if (procDesc->mRefCount == 0) {
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700319 procDesc->setProcessorEnabled(false);
bryant_liu890a5632014-08-20 18:06:13 +0800320 procDesc->mEffects.clear();
321 delete procDesc;
322 mOutputSessions.removeItemsAt(index);
323 ALOGV("releaseOutputSessionEffects(): output processing released from session: %d",
324 audioSession);
325 }
bryant_liuba2b4392014-06-11 16:49:30 +0800326 return status;
327}
328
Ari Hausman-Cohen24628312018-08-13 15:01:09 -0700329status_t AudioPolicyEffects::addSourceDefaultEffect(const effect_uuid_t *type,
330 const String16& opPackageName,
331 const effect_uuid_t *uuid,
332 int32_t priority,
333 audio_source_t source,
334 audio_unique_id_t* id)
335{
336 if (uuid == NULL || type == NULL) {
337 ALOGE("addSourceDefaultEffect(): Null uuid or type uuid pointer");
338 return BAD_VALUE;
339 }
340
Eric Laurentae4b6ec2019-01-15 18:34:38 -0800341 // HOTWORD, FM_TUNER and ECHO_REFERENCE are special case sources > MAX.
Ari Hausman-Cohen24628312018-08-13 15:01:09 -0700342 if (source < AUDIO_SOURCE_DEFAULT ||
343 (source > AUDIO_SOURCE_MAX &&
344 source != AUDIO_SOURCE_HOTWORD &&
Eric Laurentae4b6ec2019-01-15 18:34:38 -0800345 source != AUDIO_SOURCE_FM_TUNER &&
346 source != AUDIO_SOURCE_ECHO_REFERENCE)) {
Ari Hausman-Cohen24628312018-08-13 15:01:09 -0700347 ALOGE("addSourceDefaultEffect(): Unsupported source type %d", source);
348 return BAD_VALUE;
349 }
350
351 // Check that |uuid| or |type| corresponds to an effect on the system.
352 effect_descriptor_t descriptor = {};
353 status_t res = AudioEffect::getEffectDescriptor(
354 uuid, type, EFFECT_FLAG_TYPE_PRE_PROC, &descriptor);
355 if (res != OK) {
356 ALOGE("addSourceDefaultEffect(): Failed to find effect descriptor matching uuid/type.");
357 return res;
358 }
359
360 // Only pre-processing effects can be added dynamically as source defaults.
361 if ((descriptor.flags & EFFECT_FLAG_TYPE_MASK) != EFFECT_FLAG_TYPE_PRE_PROC) {
362 ALOGE("addSourceDefaultEffect(): Desired effect cannot be attached "
363 "as a source default effect.");
364 return BAD_VALUE;
365 }
366
367 Mutex::Autolock _l(mLock);
368
369 // Find the EffectDescVector for the given source type, or create a new one if necessary.
370 ssize_t index = mInputSources.indexOfKey(source);
371 EffectDescVector *desc = NULL;
372 if (index < 0) {
373 // No effects for this source type yet.
374 desc = new EffectDescVector();
375 mInputSources.add(source, desc);
376 } else {
377 desc = mInputSources.valueAt(index);
378 }
379
380 // Create a new effect and add it to the vector.
381 res = AudioEffect::newEffectUniqueId(id);
382 if (res != OK) {
383 ALOGE("addSourceDefaultEffect(): failed to get new unique id.");
384 return res;
385 }
386 EffectDesc *effect = new EffectDesc(
387 descriptor.name, *type, opPackageName, *uuid, priority, *id);
388 desc->mEffects.add(effect);
389 // TODO(b/71813697): Support setting params as well.
390
391 // TODO(b/71814300): Retroactively attach to any existing sources of the given type.
392 // This requires tracking the source type of each session id in addition to what is
393 // already being tracked.
394
395 return NO_ERROR;
396}
397
Ari Hausman-Cohen433722e2018-04-24 14:25:22 -0700398status_t AudioPolicyEffects::addStreamDefaultEffect(const effect_uuid_t *type,
399 const String16& opPackageName,
400 const effect_uuid_t *uuid,
401 int32_t priority,
402 audio_usage_t usage,
403 audio_unique_id_t* id)
404{
405 if (uuid == NULL || type == NULL) {
406 ALOGE("addStreamDefaultEffect(): Null uuid or type uuid pointer");
407 return BAD_VALUE;
408 }
François Gaffie58d4be52018-11-06 15:30:12 +0100409 audio_stream_type_t stream = AudioSystem::attributesToStreamType(attributes_initializer(usage));
Ari Hausman-Cohen433722e2018-04-24 14:25:22 -0700410
411 if (stream < AUDIO_STREAM_MIN || stream >= AUDIO_STREAM_PUBLIC_CNT) {
412 ALOGE("addStreamDefaultEffect(): Unsupported stream type %d", stream);
413 return BAD_VALUE;
414 }
415
416 // Check that |uuid| or |type| corresponds to an effect on the system.
417 effect_descriptor_t descriptor = {};
418 status_t res = AudioEffect::getEffectDescriptor(
419 uuid, type, EFFECT_FLAG_TYPE_INSERT, &descriptor);
420 if (res != OK) {
421 ALOGE("addStreamDefaultEffect(): Failed to find effect descriptor matching uuid/type.");
422 return res;
423 }
424
425 // Only insert effects can be added dynamically as stream defaults.
426 if ((descriptor.flags & EFFECT_FLAG_TYPE_MASK) != EFFECT_FLAG_TYPE_INSERT) {
427 ALOGE("addStreamDefaultEffect(): Desired effect cannot be attached "
428 "as a stream default effect.");
429 return BAD_VALUE;
430 }
431
432 Mutex::Autolock _l(mLock);
433
434 // Find the EffectDescVector for the given stream type, or create a new one if necessary.
435 ssize_t index = mOutputStreams.indexOfKey(stream);
436 EffectDescVector *desc = NULL;
437 if (index < 0) {
438 // No effects for this stream type yet.
439 desc = new EffectDescVector();
440 mOutputStreams.add(stream, desc);
441 } else {
442 desc = mOutputStreams.valueAt(index);
443 }
444
445 // Create a new effect and add it to the vector.
446 res = AudioEffect::newEffectUniqueId(id);
447 if (res != OK) {
448 ALOGE("addStreamDefaultEffect(): failed to get new unique id.");
449 return res;
450 }
451 EffectDesc *effect = new EffectDesc(
452 descriptor.name, *type, opPackageName, *uuid, priority, *id);
453 desc->mEffects.add(effect);
454 // TODO(b/71813697): Support setting params as well.
455
456 // TODO(b/71814300): Retroactively attach to any existing streams of the given type.
457 // This requires tracking the stream type of each session id in addition to what is
458 // already being tracked.
459
460 return NO_ERROR;
461}
462
Ari Hausman-Cohen24628312018-08-13 15:01:09 -0700463status_t AudioPolicyEffects::removeSourceDefaultEffect(audio_unique_id_t id)
464{
465 if (id == AUDIO_UNIQUE_ID_ALLOCATE) {
466 // ALLOCATE is not a unique identifier, but rather a reserved value indicating
467 // a real id has not been assigned. For default effects, this value is only used
468 // by system-owned defaults from the loaded config, which cannot be removed.
469 return BAD_VALUE;
470 }
471
472 Mutex::Autolock _l(mLock);
473
474 // Check each source type.
475 size_t numSources = mInputSources.size();
476 for (size_t i = 0; i < numSources; ++i) {
477 // Check each effect for each source.
478 EffectDescVector* descVector = mInputSources[i];
479 for (auto desc = descVector->mEffects.begin(); desc != descVector->mEffects.end(); ++desc) {
480 if ((*desc)->mId == id) {
481 // Found it!
482 // TODO(b/71814300): Remove from any sources the effect was attached to.
483 descVector->mEffects.erase(desc);
484 // Handles are unique; there can only be one match, so return early.
485 return NO_ERROR;
486 }
487 }
488 }
489
490 // Effect wasn't found, so it's been trivially removed successfully.
491 return NO_ERROR;
492}
493
Ari Hausman-Cohen433722e2018-04-24 14:25:22 -0700494status_t AudioPolicyEffects::removeStreamDefaultEffect(audio_unique_id_t id)
495{
496 if (id == AUDIO_UNIQUE_ID_ALLOCATE) {
497 // ALLOCATE is not a unique identifier, but rather a reserved value indicating
498 // a real id has not been assigned. For default effects, this value is only used
499 // by system-owned defaults from the loaded config, which cannot be removed.
500 return BAD_VALUE;
501 }
502
503 Mutex::Autolock _l(mLock);
504
505 // Check each stream type.
506 size_t numStreams = mOutputStreams.size();
507 for (size_t i = 0; i < numStreams; ++i) {
508 // Check each effect for each stream.
509 EffectDescVector* descVector = mOutputStreams[i];
510 for (auto desc = descVector->mEffects.begin(); desc != descVector->mEffects.end(); ++desc) {
511 if ((*desc)->mId == id) {
512 // Found it!
513 // TODO(b/71814300): Remove from any streams the effect was attached to.
514 descVector->mEffects.erase(desc);
515 // Handles are unique; there can only be one match, so return early.
516 return NO_ERROR;
517 }
518 }
519 }
520
521 // Effect wasn't found, so it's been trivially removed successfully.
522 return NO_ERROR;
523}
bryant_liuba2b4392014-06-11 16:49:30 +0800524
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700525void AudioPolicyEffects::EffectVector::setProcessorEnabled(bool enabled)
bryant_liuba2b4392014-06-11 16:49:30 +0800526{
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700527 for (size_t i = 0; i < mEffects.size(); i++) {
528 mEffects.itemAt(i)->setEnabled(enabled);
bryant_liuba2b4392014-06-11 16:49:30 +0800529 }
530}
531
532
533// ----------------------------------------------------------------------------
534// Audio processing configuration
535// ----------------------------------------------------------------------------
536
537/*static*/ const char * const AudioPolicyEffects::kInputSourceNames[AUDIO_SOURCE_CNT -1] = {
538 MIC_SRC_TAG,
539 VOICE_UL_SRC_TAG,
540 VOICE_DL_SRC_TAG,
541 VOICE_CALL_SRC_TAG,
542 CAMCORDER_SRC_TAG,
543 VOICE_REC_SRC_TAG,
rago8a397d52015-12-02 11:27:57 -0800544 VOICE_COMM_SRC_TAG,
Eric Laurentae4b6ec2019-01-15 18:34:38 -0800545 UNPROCESSED_SRC_TAG,
546 VOICE_PERFORMANCE_SRC_TAG
bryant_liuba2b4392014-06-11 16:49:30 +0800547};
548
549// returns the audio_source_t enum corresponding to the input source name or
550// AUDIO_SOURCE_CNT is no match found
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700551/*static*/ audio_source_t AudioPolicyEffects::inputSourceNameToEnum(const char *name)
bryant_liuba2b4392014-06-11 16:49:30 +0800552{
553 int i;
554 for (i = AUDIO_SOURCE_MIC; i < AUDIO_SOURCE_CNT; i++) {
555 if (strcmp(name, kInputSourceNames[i - AUDIO_SOURCE_MIC]) == 0) {
556 ALOGV("inputSourceNameToEnum found source %s %d", name, i);
557 break;
558 }
559 }
560 return (audio_source_t)i;
561}
562
Eric Laurent223fd5c2014-11-11 13:43:36 -0800563const char *AudioPolicyEffects::kStreamNames[AUDIO_STREAM_PUBLIC_CNT+1] = {
bryant_liuba2b4392014-06-11 16:49:30 +0800564 AUDIO_STREAM_DEFAULT_TAG,
565 AUDIO_STREAM_VOICE_CALL_TAG,
566 AUDIO_STREAM_SYSTEM_TAG,
567 AUDIO_STREAM_RING_TAG,
568 AUDIO_STREAM_MUSIC_TAG,
569 AUDIO_STREAM_ALARM_TAG,
570 AUDIO_STREAM_NOTIFICATION_TAG,
571 AUDIO_STREAM_BLUETOOTH_SCO_TAG,
572 AUDIO_STREAM_ENFORCED_AUDIBLE_TAG,
573 AUDIO_STREAM_DTMF_TAG,
Baekgyeong Kim3a26bb22019-10-30 20:29:41 +0900574 AUDIO_STREAM_TTS_TAG,
575 AUDIO_STREAM_ASSISTANT_TAG
bryant_liuba2b4392014-06-11 16:49:30 +0800576};
577
578// returns the audio_stream_t enum corresponding to the output stream name or
Eric Laurent223fd5c2014-11-11 13:43:36 -0800579// AUDIO_STREAM_PUBLIC_CNT is no match found
bryant_liuba2b4392014-06-11 16:49:30 +0800580audio_stream_type_t AudioPolicyEffects::streamNameToEnum(const char *name)
581{
582 int i;
Eric Laurent223fd5c2014-11-11 13:43:36 -0800583 for (i = AUDIO_STREAM_DEFAULT; i < AUDIO_STREAM_PUBLIC_CNT; i++) {
bryant_liuba2b4392014-06-11 16:49:30 +0800584 if (strcmp(name, kStreamNames[i - AUDIO_STREAM_DEFAULT]) == 0) {
585 ALOGV("streamNameToEnum found stream %s %d", name, i);
586 break;
587 }
588 }
589 return (audio_stream_type_t)i;
590}
591
592// ----------------------------------------------------------------------------
593// Audio Effect Config parser
594// ----------------------------------------------------------------------------
595
Eric Laurent138ed172016-02-10 10:40:44 -0800596size_t AudioPolicyEffects::growParamSize(char **param,
bryant_liuba2b4392014-06-11 16:49:30 +0800597 size_t size,
598 size_t *curSize,
599 size_t *totSize)
600{
601 // *curSize is at least sizeof(effect_param_t) + 2 * sizeof(int)
602 size_t pos = ((*curSize - 1 ) / size + 1) * size;
603
604 if (pos + size > *totSize) {
605 while (pos + size > *totSize) {
606 *totSize += ((*totSize + 7) / 8) * 4;
607 }
George Burgess IV31225682018-02-12 11:08:38 -0800608 char *newParam = (char *)realloc(*param, *totSize);
609 if (newParam == NULL) {
Eric Laurent138ed172016-02-10 10:40:44 -0800610 ALOGE("%s realloc error for size %zu", __func__, *totSize);
611 return 0;
612 }
George Burgess IV31225682018-02-12 11:08:38 -0800613 *param = newParam;
bryant_liuba2b4392014-06-11 16:49:30 +0800614 }
615 *curSize = pos + size;
616 return pos;
617}
618
Eric Laurent138ed172016-02-10 10:40:44 -0800619
bryant_liuba2b4392014-06-11 16:49:30 +0800620size_t AudioPolicyEffects::readParamValue(cnode *node,
Eric Laurent138ed172016-02-10 10:40:44 -0800621 char **param,
bryant_liuba2b4392014-06-11 16:49:30 +0800622 size_t *curSize,
623 size_t *totSize)
624{
Eric Laurent138ed172016-02-10 10:40:44 -0800625 size_t len = 0;
626 size_t pos;
627
bryant_liuba2b4392014-06-11 16:49:30 +0800628 if (strncmp(node->name, SHORT_TAG, sizeof(SHORT_TAG) + 1) == 0) {
Eric Laurent138ed172016-02-10 10:40:44 -0800629 pos = growParamSize(param, sizeof(short), curSize, totSize);
630 if (pos == 0) {
631 goto exit;
bryant_liuba2b4392014-06-11 16:49:30 +0800632 }
Eric Laurent138ed172016-02-10 10:40:44 -0800633 *(short *)(*param + pos) = (short)atoi(node->value);
634 ALOGV("readParamValue() reading short %d", *(short *)(*param + pos));
635 len = sizeof(short);
636 } else if (strncmp(node->name, INT_TAG, sizeof(INT_TAG) + 1) == 0) {
637 pos = growParamSize(param, sizeof(int), curSize, totSize);
638 if (pos == 0) {
639 goto exit;
640 }
641 *(int *)(*param + pos) = atoi(node->value);
642 ALOGV("readParamValue() reading int %d", *(int *)(*param + pos));
643 len = sizeof(int);
644 } else if (strncmp(node->name, FLOAT_TAG, sizeof(FLOAT_TAG) + 1) == 0) {
645 pos = growParamSize(param, sizeof(float), curSize, totSize);
646 if (pos == 0) {
647 goto exit;
648 }
649 *(float *)(*param + pos) = (float)atof(node->value);
650 ALOGV("readParamValue() reading float %f",*(float *)(*param + pos));
651 len = sizeof(float);
652 } else if (strncmp(node->name, BOOL_TAG, sizeof(BOOL_TAG) + 1) == 0) {
653 pos = growParamSize(param, sizeof(bool), curSize, totSize);
654 if (pos == 0) {
655 goto exit;
656 }
657 if (strncmp(node->value, "true", strlen("true") + 1) == 0) {
658 *(bool *)(*param + pos) = true;
659 } else {
660 *(bool *)(*param + pos) = false;
661 }
662 ALOGV("readParamValue() reading bool %s",
663 *(bool *)(*param + pos) ? "true" : "false");
664 len = sizeof(bool);
bryant_liuba2b4392014-06-11 16:49:30 +0800665 } else if (strncmp(node->name, STRING_TAG, sizeof(STRING_TAG) + 1) == 0) {
Eric Laurent138ed172016-02-10 10:40:44 -0800666 len = strnlen(node->value, EFFECT_STRING_LEN_MAX);
bryant_liuba2b4392014-06-11 16:49:30 +0800667 if (*curSize + len + 1 > *totSize) {
668 *totSize = *curSize + len + 1;
Chih-Hung Hsieh03077682018-08-30 14:11:00 -0700669 char *newParam = (char *)realloc(*param, *totSize);
670 if (newParam == NULL) {
Eric Laurent138ed172016-02-10 10:40:44 -0800671 len = 0;
672 ALOGE("%s realloc error for string len %zu", __func__, *totSize);
673 goto exit;
674 }
Chih-Hung Hsieh03077682018-08-30 14:11:00 -0700675 *param = newParam;
bryant_liuba2b4392014-06-11 16:49:30 +0800676 }
Eric Laurent138ed172016-02-10 10:40:44 -0800677 strncpy(*param + *curSize, node->value, len);
bryant_liuba2b4392014-06-11 16:49:30 +0800678 *curSize += len;
Eric Laurent138ed172016-02-10 10:40:44 -0800679 (*param)[*curSize] = '\0';
680 ALOGV("readParamValue() reading string %s", *param + *curSize - len);
681 } else {
682 ALOGW("readParamValue() unknown param type %s", node->name);
bryant_liuba2b4392014-06-11 16:49:30 +0800683 }
Eric Laurent138ed172016-02-10 10:40:44 -0800684exit:
685 return len;
bryant_liuba2b4392014-06-11 16:49:30 +0800686}
687
688effect_param_t *AudioPolicyEffects::loadEffectParameter(cnode *root)
689{
690 cnode *param;
691 cnode *value;
692 size_t curSize = sizeof(effect_param_t);
693 size_t totSize = sizeof(effect_param_t) + 2 * sizeof(int);
694 effect_param_t *fx_param = (effect_param_t *)malloc(totSize);
695
Eric Laurent138ed172016-02-10 10:40:44 -0800696 if (fx_param == NULL) {
697 ALOGE("%s malloc error for effect structure of size %zu",
698 __func__, totSize);
699 return NULL;
700 }
701
bryant_liuba2b4392014-06-11 16:49:30 +0800702 param = config_find(root, PARAM_TAG);
703 value = config_find(root, VALUE_TAG);
704 if (param == NULL && value == NULL) {
705 // try to parse simple parameter form {int int}
706 param = root->first_child;
707 if (param != NULL) {
708 // Note: that a pair of random strings is read as 0 0
709 int *ptr = (int *)fx_param->data;
Eric Laurent138ed172016-02-10 10:40:44 -0800710#if LOG_NDEBUG == 0
bryant_liuba2b4392014-06-11 16:49:30 +0800711 int *ptr2 = (int *)((char *)param + sizeof(effect_param_t));
Eric Laurent138ed172016-02-10 10:40:44 -0800712 ALOGV("loadEffectParameter() ptr %p ptr2 %p", ptr, ptr2);
713#endif
bryant_liuba2b4392014-06-11 16:49:30 +0800714 *ptr++ = atoi(param->name);
715 *ptr = atoi(param->value);
716 fx_param->psize = sizeof(int);
717 fx_param->vsize = sizeof(int);
718 return fx_param;
719 }
720 }
721 if (param == NULL || value == NULL) {
Eric Laurent138ed172016-02-10 10:40:44 -0800722 ALOGW("loadEffectParameter() invalid parameter description %s",
723 root->name);
bryant_liuba2b4392014-06-11 16:49:30 +0800724 goto error;
725 }
726
727 fx_param->psize = 0;
728 param = param->first_child;
729 while (param) {
730 ALOGV("loadEffectParameter() reading param of type %s", param->name);
Eric Laurent138ed172016-02-10 10:40:44 -0800731 size_t size =
732 readParamValue(param, (char **)&fx_param, &curSize, &totSize);
bryant_liuba2b4392014-06-11 16:49:30 +0800733 if (size == 0) {
734 goto error;
735 }
736 fx_param->psize += size;
737 param = param->next;
738 }
739
740 // align start of value field on 32 bit boundary
741 curSize = ((curSize - 1 ) / sizeof(int) + 1) * sizeof(int);
742
743 fx_param->vsize = 0;
744 value = value->first_child;
745 while (value) {
746 ALOGV("loadEffectParameter() reading value of type %s", value->name);
Eric Laurent138ed172016-02-10 10:40:44 -0800747 size_t size =
748 readParamValue(value, (char **)&fx_param, &curSize, &totSize);
bryant_liuba2b4392014-06-11 16:49:30 +0800749 if (size == 0) {
750 goto error;
751 }
752 fx_param->vsize += size;
753 value = value->next;
754 }
755
756 return fx_param;
757
758error:
Eric Laurent138ed172016-02-10 10:40:44 -0800759 free(fx_param);
bryant_liuba2b4392014-06-11 16:49:30 +0800760 return NULL;
761}
762
763void AudioPolicyEffects::loadEffectParameters(cnode *root, Vector <effect_param_t *>& params)
764{
765 cnode *node = root->first_child;
766 while (node) {
767 ALOGV("loadEffectParameters() loading param %s", node->name);
768 effect_param_t *param = loadEffectParameter(node);
Eric Laurent138ed172016-02-10 10:40:44 -0800769 if (param != NULL) {
770 params.add(param);
bryant_liuba2b4392014-06-11 16:49:30 +0800771 }
bryant_liuba2b4392014-06-11 16:49:30 +0800772 node = node->next;
773 }
774}
775
776
777AudioPolicyEffects::EffectDescVector *AudioPolicyEffects::loadEffectConfig(
778 cnode *root,
779 const Vector <EffectDesc *>& effects)
780{
781 cnode *node = root->first_child;
782 if (node == NULL) {
783 ALOGW("loadInputSource() empty element %s", root->name);
784 return NULL;
785 }
786 EffectDescVector *desc = new EffectDescVector();
787 while (node) {
788 size_t i;
Eric Laurent138ed172016-02-10 10:40:44 -0800789
bryant_liuba2b4392014-06-11 16:49:30 +0800790 for (i = 0; i < effects.size(); i++) {
791 if (strncmp(effects[i]->mName, node->name, EFFECT_STRING_LEN_MAX) == 0) {
792 ALOGV("loadEffectConfig() found effect %s in list", node->name);
793 break;
794 }
795 }
796 if (i == effects.size()) {
797 ALOGV("loadEffectConfig() effect %s not in list", node->name);
798 node = node->next;
799 continue;
800 }
801 EffectDesc *effect = new EffectDesc(*effects[i]); // deep copy
802 loadEffectParameters(node, effect->mParams);
803 ALOGV("loadEffectConfig() adding effect %s uuid %08x",
804 effect->mName, effect->mUuid.timeLow);
805 desc->mEffects.add(effect);
806 node = node->next;
807 }
808 if (desc->mEffects.size() == 0) {
809 ALOGW("loadEffectConfig() no valid effects found in config %s", root->name);
810 delete desc;
811 return NULL;
812 }
813 return desc;
814}
815
816status_t AudioPolicyEffects::loadInputEffectConfigurations(cnode *root,
817 const Vector <EffectDesc *>& effects)
818{
819 cnode *node = config_find(root, PREPROCESSING_TAG);
820 if (node == NULL) {
821 return -ENOENT;
822 }
823 node = node->first_child;
824 while (node) {
825 audio_source_t source = inputSourceNameToEnum(node->name);
826 if (source == AUDIO_SOURCE_CNT) {
827 ALOGW("loadInputSources() invalid input source %s", node->name);
828 node = node->next;
829 continue;
830 }
831 ALOGV("loadInputSources() loading input source %s", node->name);
832 EffectDescVector *desc = loadEffectConfig(node, effects);
833 if (desc == NULL) {
834 node = node->next;
835 continue;
836 }
837 mInputSources.add(source, desc);
838 node = node->next;
839 }
840 return NO_ERROR;
841}
842
843status_t AudioPolicyEffects::loadStreamEffectConfigurations(cnode *root,
844 const Vector <EffectDesc *>& effects)
845{
846 cnode *node = config_find(root, OUTPUT_SESSION_PROCESSING_TAG);
847 if (node == NULL) {
848 return -ENOENT;
849 }
850 node = node->first_child;
851 while (node) {
852 audio_stream_type_t stream = streamNameToEnum(node->name);
Eric Laurent223fd5c2014-11-11 13:43:36 -0800853 if (stream == AUDIO_STREAM_PUBLIC_CNT) {
bryant_liuba2b4392014-06-11 16:49:30 +0800854 ALOGW("loadStreamEffectConfigurations() invalid output stream %s", node->name);
855 node = node->next;
856 continue;
857 }
858 ALOGV("loadStreamEffectConfigurations() loading output stream %s", node->name);
859 EffectDescVector *desc = loadEffectConfig(node, effects);
860 if (desc == NULL) {
861 node = node->next;
862 continue;
863 }
864 mOutputStreams.add(stream, desc);
865 node = node->next;
866 }
867 return NO_ERROR;
868}
869
870AudioPolicyEffects::EffectDesc *AudioPolicyEffects::loadEffect(cnode *root)
871{
872 cnode *node = config_find(root, UUID_TAG);
873 if (node == NULL) {
874 return NULL;
875 }
876 effect_uuid_t uuid;
877 if (AudioEffect::stringToGuid(node->value, &uuid) != NO_ERROR) {
878 ALOGW("loadEffect() invalid uuid %s", node->value);
879 return NULL;
880 }
881 return new EffectDesc(root->name, uuid);
882}
883
884status_t AudioPolicyEffects::loadEffects(cnode *root, Vector <EffectDesc *>& effects)
885{
886 cnode *node = config_find(root, EFFECTS_TAG);
887 if (node == NULL) {
888 return -ENOENT;
889 }
890 node = node->first_child;
891 while (node) {
892 ALOGV("loadEffects() loading effect %s", node->name);
893 EffectDesc *effect = loadEffect(node);
894 if (effect == NULL) {
895 node = node->next;
896 continue;
897 }
898 effects.add(effect);
899 node = node->next;
900 }
901 return NO_ERROR;
902}
903
Kevin Rocard4fb615c2017-06-26 10:28:13 -0700904status_t AudioPolicyEffects::loadAudioEffectXmlConfig() {
905 auto result = effectsConfig::parse();
906 if (result.parsedConfig == nullptr) {
907 return -ENOENT;
908 }
909
910 auto loadProcessingChain = [](auto& processingChain, auto& streams) {
911 for (auto& stream : processingChain) {
912 auto effectDescs = std::make_unique<EffectDescVector>();
913 for (auto& effect : stream.effects) {
914 effectDescs->mEffects.add(
915 new EffectDesc{effect.get().name.c_str(), effect.get().uuid});
916 }
917 streams.add(stream.type, effectDescs.release());
918 }
919 };
François Gaffie06182982020-01-07 15:16:14 +0100920
921 auto loadDeviceProcessingChain = [](auto &processingChain, auto& devicesEffects) {
922 for (auto& deviceProcess : processingChain) {
923
924 auto effectDescs = std::make_unique<EffectDescVector>();
925 for (auto& effect : deviceProcess.effects) {
926 effectDescs->mEffects.add(
927 new EffectDesc{effect.get().name.c_str(), effect.get().uuid});
928 }
929 auto deviceEffects = std::make_unique<DeviceEffects>(
930 std::move(effectDescs), deviceProcess.type, deviceProcess.address);
931 devicesEffects.emplace(deviceProcess.address, std::move(deviceEffects));
932 }
933 };
934
Kevin Rocard4fb615c2017-06-26 10:28:13 -0700935 loadProcessingChain(result.parsedConfig->preprocess, mInputSources);
936 loadProcessingChain(result.parsedConfig->postprocess, mOutputStreams);
Mikhail Naganov12b716c2020-04-30 22:37:43 +0000937 {
938 Mutex::Autolock _l(mLock);
939 loadDeviceProcessingChain(result.parsedConfig->deviceprocess, mDeviceEffects);
940 }
Kevin Rocard4fb615c2017-06-26 10:28:13 -0700941 // Casting from ssize_t to status_t is probably safe, there should not be more than 2^31 errors
942 return result.nbSkippedElement;
943}
944
bryant_liuba2b4392014-06-11 16:49:30 +0800945status_t AudioPolicyEffects::loadAudioEffectConfig(const char *path)
946{
947 cnode *root;
948 char *data;
949
950 data = (char *)load_file(path, NULL);
951 if (data == NULL) {
952 return -ENODEV;
953 }
954 root = config_node("", "");
955 config_load(root, data);
956
957 Vector <EffectDesc *> effects;
958 loadEffects(root, effects);
959 loadInputEffectConfigurations(root, effects);
960 loadStreamEffectConfigurations(root, effects);
961
Eric Laurent182c2f52015-01-15 14:29:19 -0800962 for (size_t i = 0; i < effects.size(); i++) {
963 delete effects[i];
964 }
965
bryant_liuba2b4392014-06-11 16:49:30 +0800966 config_free(root);
967 free(root);
968 free(data);
969
970 return NO_ERROR;
971}
972
François Gaffie06182982020-01-07 15:16:14 +0100973void AudioPolicyEffects::initDefaultDeviceEffects()
974{
975 Mutex::Autolock _l(mLock);
976 for (const auto& deviceEffectsIter : mDeviceEffects) {
977 const auto& deviceEffects = deviceEffectsIter.second;
978 for (const auto& effectDesc : deviceEffects->mEffectDescriptors->mEffects) {
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700979 Identity identity;
980 identity.packageName = "android";
981 sp<AudioEffect> fx = new AudioEffect(identity);
Mikhail Naganov69d41cc2020-07-31 17:36:08 -0700982 fx->set(EFFECT_UUID_NULL, &effectDesc->mUuid, 0, nullptr,
983 nullptr, AUDIO_SESSION_DEVICE, AUDIO_IO_HANDLE_NONE,
984 AudioDeviceTypeAddr{deviceEffects->getDeviceType(),
985 deviceEffects->getDeviceAddress()});
François Gaffie06182982020-01-07 15:16:14 +0100986 status_t status = fx->initCheck();
987 if (status != NO_ERROR && status != ALREADY_EXISTS) {
988 ALOGE("%s(): failed to create Fx %s on port type=%d address=%s", __func__,
989 effectDesc->mName, deviceEffects->getDeviceType(),
990 deviceEffects->getDeviceAddress().c_str());
991 // fx goes out of scope and strong ref on AudioEffect is released
992 continue;
993 }
994 fx->setEnabled(true);
995 ALOGV("%s(): create Fx %s added on port type=%d address=%s", __func__,
996 effectDesc->mName, deviceEffects->getDeviceType(),
997 deviceEffects->getDeviceAddress().c_str());
Jintao Zhu230397e2021-03-07 14:15:10 +0800998 deviceEffects->mEffects.push_back(fx);
François Gaffie06182982020-01-07 15:16:14 +0100999 }
1000 }
1001}
bryant_liuba2b4392014-06-11 16:49:30 +08001002
Mikhail Naganov1b2a7942017-12-08 10:18:09 -08001003} // namespace android