blob: 3f01de9f57f984c16e90a91d17bc4b4eef6cc766 [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
Svet Ganov33761132021-05-13 22:51:08 +000038using content::AttributionSourceState;
Philip P. Moltmannbda45752020-07-17 16:41:18 -070039
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];
Svet Ganov33761132021-05-13 22:51:08 +0000126 AttributionSourceState attributionSource;
127 attributionSource.packageName = "android";
128 attributionSource.token = sp<BBinder>::make();
129 sp<AudioEffect> fx = new AudioEffect(attributionSource);
Mikhail Naganov69d41cc2020-07-31 17:36:08 -0700130 fx->set(NULL, &effect->mUuid, -1, 0, 0, audioSession, input);
Eric Laurent7de5ac12014-10-21 09:07:11 -0700131 status_t status = fx->initCheck();
132 if (status != NO_ERROR && status != ALREADY_EXISTS) {
133 ALOGW("addInputEffects(): failed to create Fx %s on source %d",
134 effect->mName, (int32_t)aliasSource);
135 // fx goes out of scope and strong ref on AudioEffect is released
136 continue;
137 }
138 for (size_t j = 0; j < effect->mParams.size(); j++) {
139 fx->setParameter(effect->mParams[j]);
140 }
141 ALOGV("addInputEffects(): added Fx %s on source: %d",
bryant_liuba2b4392014-06-11 16:49:30 +0800142 effect->mName, (int32_t)aliasSource);
Eric Laurentfb66dd92016-01-28 18:32:03 -0800143 sessionDesc->mEffects.add(fx);
bryant_liuba2b4392014-06-11 16:49:30 +0800144 }
Eric Laurentfb66dd92016-01-28 18:32:03 -0800145 sessionDesc->setProcessorEnabled(true);
Eric Laurentb6436272016-12-07 19:24:50 -0800146 IPCThreadState::self()->restoreCallingIdentity(token);
bryant_liuba2b4392014-06-11 16:49:30 +0800147 }
bryant_liuba2b4392014-06-11 16:49:30 +0800148 return status;
149}
150
151
Eric Laurentfb66dd92016-01-28 18:32:03 -0800152status_t AudioPolicyEffects::releaseInputEffects(audio_io_handle_t input,
153 audio_session_t audioSession)
bryant_liuba2b4392014-06-11 16:49:30 +0800154{
155 status_t status = NO_ERROR;
156
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700157 Mutex::Autolock _l(mLock);
Eric Laurentfb66dd92016-01-28 18:32:03 -0800158 ssize_t index = mInputSessions.indexOfKey(audioSession);
bryant_liuba2b4392014-06-11 16:49:30 +0800159 if (index < 0) {
160 return status;
161 }
Eric Laurentfb66dd92016-01-28 18:32:03 -0800162 EffectVector *sessionDesc = mInputSessions.valueAt(index);
163 sessionDesc->mRefCount--;
164 ALOGV("releaseInputEffects(): input: %d, refCount: %d", input, sessionDesc->mRefCount);
165 if (sessionDesc->mRefCount == 0) {
166 sessionDesc->setProcessorEnabled(false);
167 delete sessionDesc;
168 mInputSessions.removeItemsAt(index);
bryant_liu890a5632014-08-20 18:06:13 +0800169 ALOGV("releaseInputEffects(): all effects released");
170 }
bryant_liuba2b4392014-06-11 16:49:30 +0800171 return status;
172}
173
Eric Laurentfb66dd92016-01-28 18:32:03 -0800174status_t AudioPolicyEffects::queryDefaultInputEffects(audio_session_t audioSession,
bryant_liuba2b4392014-06-11 16:49:30 +0800175 effect_descriptor_t *descriptors,
176 uint32_t *count)
177{
178 status_t status = NO_ERROR;
179
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700180 Mutex::Autolock _l(mLock);
bryant_liuba2b4392014-06-11 16:49:30 +0800181 size_t index;
Eric Laurentfb66dd92016-01-28 18:32:03 -0800182 for (index = 0; index < mInputSessions.size(); index++) {
183 if (mInputSessions.valueAt(index)->mSessionId == audioSession) {
bryant_liuba2b4392014-06-11 16:49:30 +0800184 break;
185 }
186 }
Eric Laurentfb66dd92016-01-28 18:32:03 -0800187 if (index == mInputSessions.size()) {
bryant_liuba2b4392014-06-11 16:49:30 +0800188 *count = 0;
189 return BAD_VALUE;
190 }
Eric Laurentfb66dd92016-01-28 18:32:03 -0800191 Vector< sp<AudioEffect> > effects = mInputSessions.valueAt(index)->mEffects;
bryant_liuba2b4392014-06-11 16:49:30 +0800192
193 for (size_t i = 0; i < effects.size(); i++) {
194 effect_descriptor_t desc = effects[i]->descriptor();
195 if (i < *count) {
196 descriptors[i] = desc;
197 }
198 }
199 if (effects.size() > *count) {
200 status = NO_MEMORY;
201 }
202 *count = effects.size();
203 return status;
204}
205
206
Eric Laurentfb66dd92016-01-28 18:32:03 -0800207status_t AudioPolicyEffects::queryDefaultOutputSessionEffects(audio_session_t audioSession,
bryant_liuba2b4392014-06-11 16:49:30 +0800208 effect_descriptor_t *descriptors,
209 uint32_t *count)
210{
211 status_t status = NO_ERROR;
212
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700213 Mutex::Autolock _l(mLock);
bryant_liuba2b4392014-06-11 16:49:30 +0800214 size_t index;
215 for (index = 0; index < mOutputSessions.size(); index++) {
216 if (mOutputSessions.valueAt(index)->mSessionId == audioSession) {
217 break;
218 }
219 }
220 if (index == mOutputSessions.size()) {
221 *count = 0;
222 return BAD_VALUE;
223 }
224 Vector< sp<AudioEffect> > effects = mOutputSessions.valueAt(index)->mEffects;
225
226 for (size_t i = 0; i < effects.size(); i++) {
227 effect_descriptor_t desc = effects[i]->descriptor();
228 if (i < *count) {
229 descriptors[i] = desc;
230 }
231 }
232 if (effects.size() > *count) {
233 status = NO_MEMORY;
234 }
235 *count = effects.size();
236 return status;
237}
238
239
240status_t AudioPolicyEffects::addOutputSessionEffects(audio_io_handle_t output,
241 audio_stream_type_t stream,
Eric Laurentfb66dd92016-01-28 18:32:03 -0800242 audio_session_t audioSession)
bryant_liuba2b4392014-06-11 16:49:30 +0800243{
244 status_t status = NO_ERROR;
245
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700246 Mutex::Autolock _l(mLock);
bryant_liuba2b4392014-06-11 16:49:30 +0800247 // create audio processors according to stream
Eric Laurent223fd5c2014-11-11 13:43:36 -0800248 // FIXME: should we have specific post processing settings for internal streams?
249 // default to media for now.
250 if (stream >= AUDIO_STREAM_PUBLIC_CNT) {
251 stream = AUDIO_STREAM_MUSIC;
252 }
bryant_liuba2b4392014-06-11 16:49:30 +0800253 ssize_t index = mOutputStreams.indexOfKey(stream);
254 if (index < 0) {
255 ALOGV("addOutputSessionEffects(): no output processing needed for this stream");
256 return NO_ERROR;
257 }
258
259 ssize_t idx = mOutputSessions.indexOfKey(audioSession);
260 EffectVector *procDesc;
261 if (idx < 0) {
262 procDesc = new EffectVector(audioSession);
263 mOutputSessions.add(audioSession, procDesc);
264 } else {
bryant_liu890a5632014-08-20 18:06:13 +0800265 // EffectVector is existing and we just need to increase ref count
bryant_liuba2b4392014-06-11 16:49:30 +0800266 procDesc = mOutputSessions.valueAt(idx);
267 }
bryant_liu890a5632014-08-20 18:06:13 +0800268 procDesc->mRefCount++;
269
Eric Laurent7de5ac12014-10-21 09:07:11 -0700270 ALOGV("addOutputSessionEffects(): session: %d, refCount: %d",
271 audioSession, procDesc->mRefCount);
272 if (procDesc->mRefCount == 1) {
Eric Laurentb6436272016-12-07 19:24:50 -0800273 // make sure effects are associated to audio server even if we are executing a binder call
274 int64_t token = IPCThreadState::self()->clearCallingIdentity();
Eric Laurent7de5ac12014-10-21 09:07:11 -0700275 Vector <EffectDesc *> effects = mOutputStreams.valueAt(index)->mEffects;
276 for (size_t i = 0; i < effects.size(); i++) {
277 EffectDesc *effect = effects[i];
Svet Ganov33761132021-05-13 22:51:08 +0000278 AttributionSourceState attributionSource;
279 attributionSource.packageName = "android";
280 attributionSource.token = sp<BBinder>::make();
281 sp<AudioEffect> fx = new AudioEffect(attributionSource);
Mikhail Naganov69d41cc2020-07-31 17:36:08 -0700282 fx->set(NULL, &effect->mUuid, 0, 0, 0, audioSession, output);
Eric Laurent7de5ac12014-10-21 09:07:11 -0700283 status_t status = fx->initCheck();
284 if (status != NO_ERROR && status != ALREADY_EXISTS) {
285 ALOGE("addOutputSessionEffects(): failed to create Fx %s on session %d",
286 effect->mName, audioSession);
287 // fx goes out of scope and strong ref on AudioEffect is released
288 continue;
289 }
290 ALOGV("addOutputSessionEffects(): added Fx %s on session: %d for stream: %d",
291 effect->mName, audioSession, (int32_t)stream);
292 procDesc->mEffects.add(fx);
bryant_liuba2b4392014-06-11 16:49:30 +0800293 }
Eric Laurent7de5ac12014-10-21 09:07:11 -0700294
295 procDesc->setProcessorEnabled(true);
Eric Laurentb6436272016-12-07 19:24:50 -0800296 IPCThreadState::self()->restoreCallingIdentity(token);
bryant_liuba2b4392014-06-11 16:49:30 +0800297 }
bryant_liuba2b4392014-06-11 16:49:30 +0800298 return status;
299}
300
301status_t AudioPolicyEffects::releaseOutputSessionEffects(audio_io_handle_t output,
302 audio_stream_type_t stream,
Eric Laurentfb66dd92016-01-28 18:32:03 -0800303 audio_session_t audioSession)
bryant_liuba2b4392014-06-11 16:49:30 +0800304{
305 status_t status = NO_ERROR;
306 (void) output; // argument not used for now
307 (void) stream; // argument not used for now
308
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700309 Mutex::Autolock _l(mLock);
bryant_liuba2b4392014-06-11 16:49:30 +0800310 ssize_t index = mOutputSessions.indexOfKey(audioSession);
311 if (index < 0) {
312 ALOGV("releaseOutputSessionEffects: no output processing was attached to this stream");
313 return NO_ERROR;
314 }
315
316 EffectVector *procDesc = mOutputSessions.valueAt(index);
bryant_liu890a5632014-08-20 18:06:13 +0800317 procDesc->mRefCount--;
Eric Laurent7de5ac12014-10-21 09:07:11 -0700318 ALOGV("releaseOutputSessionEffects(): session: %d, refCount: %d",
319 audioSession, procDesc->mRefCount);
bryant_liu890a5632014-08-20 18:06:13 +0800320 if (procDesc->mRefCount == 0) {
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700321 procDesc->setProcessorEnabled(false);
bryant_liu890a5632014-08-20 18:06:13 +0800322 procDesc->mEffects.clear();
323 delete procDesc;
324 mOutputSessions.removeItemsAt(index);
325 ALOGV("releaseOutputSessionEffects(): output processing released from session: %d",
326 audioSession);
327 }
bryant_liuba2b4392014-06-11 16:49:30 +0800328 return status;
329}
330
Ari Hausman-Cohen24628312018-08-13 15:01:09 -0700331status_t AudioPolicyEffects::addSourceDefaultEffect(const effect_uuid_t *type,
332 const String16& opPackageName,
333 const effect_uuid_t *uuid,
334 int32_t priority,
335 audio_source_t source,
336 audio_unique_id_t* id)
337{
338 if (uuid == NULL || type == NULL) {
339 ALOGE("addSourceDefaultEffect(): Null uuid or type uuid pointer");
340 return BAD_VALUE;
341 }
342
Eric Laurentae4b6ec2019-01-15 18:34:38 -0800343 // HOTWORD, FM_TUNER and ECHO_REFERENCE are special case sources > MAX.
Ari Hausman-Cohen24628312018-08-13 15:01:09 -0700344 if (source < AUDIO_SOURCE_DEFAULT ||
345 (source > AUDIO_SOURCE_MAX &&
346 source != AUDIO_SOURCE_HOTWORD &&
Eric Laurentae4b6ec2019-01-15 18:34:38 -0800347 source != AUDIO_SOURCE_FM_TUNER &&
348 source != AUDIO_SOURCE_ECHO_REFERENCE)) {
Ari Hausman-Cohen24628312018-08-13 15:01:09 -0700349 ALOGE("addSourceDefaultEffect(): Unsupported source type %d", source);
350 return BAD_VALUE;
351 }
352
353 // Check that |uuid| or |type| corresponds to an effect on the system.
354 effect_descriptor_t descriptor = {};
355 status_t res = AudioEffect::getEffectDescriptor(
356 uuid, type, EFFECT_FLAG_TYPE_PRE_PROC, &descriptor);
357 if (res != OK) {
358 ALOGE("addSourceDefaultEffect(): Failed to find effect descriptor matching uuid/type.");
359 return res;
360 }
361
362 // Only pre-processing effects can be added dynamically as source defaults.
363 if ((descriptor.flags & EFFECT_FLAG_TYPE_MASK) != EFFECT_FLAG_TYPE_PRE_PROC) {
364 ALOGE("addSourceDefaultEffect(): Desired effect cannot be attached "
365 "as a source default effect.");
366 return BAD_VALUE;
367 }
368
369 Mutex::Autolock _l(mLock);
370
371 // Find the EffectDescVector for the given source type, or create a new one if necessary.
372 ssize_t index = mInputSources.indexOfKey(source);
373 EffectDescVector *desc = NULL;
374 if (index < 0) {
375 // No effects for this source type yet.
376 desc = new EffectDescVector();
377 mInputSources.add(source, desc);
378 } else {
379 desc = mInputSources.valueAt(index);
380 }
381
382 // Create a new effect and add it to the vector.
383 res = AudioEffect::newEffectUniqueId(id);
384 if (res != OK) {
385 ALOGE("addSourceDefaultEffect(): failed to get new unique id.");
386 return res;
387 }
388 EffectDesc *effect = new EffectDesc(
389 descriptor.name, *type, opPackageName, *uuid, priority, *id);
390 desc->mEffects.add(effect);
391 // TODO(b/71813697): Support setting params as well.
392
393 // TODO(b/71814300): Retroactively attach to any existing sources of the given type.
394 // This requires tracking the source type of each session id in addition to what is
395 // already being tracked.
396
397 return NO_ERROR;
398}
399
Ari Hausman-Cohen433722e2018-04-24 14:25:22 -0700400status_t AudioPolicyEffects::addStreamDefaultEffect(const effect_uuid_t *type,
401 const String16& opPackageName,
402 const effect_uuid_t *uuid,
403 int32_t priority,
404 audio_usage_t usage,
405 audio_unique_id_t* id)
406{
407 if (uuid == NULL || type == NULL) {
408 ALOGE("addStreamDefaultEffect(): Null uuid or type uuid pointer");
409 return BAD_VALUE;
410 }
François Gaffie58d4be52018-11-06 15:30:12 +0100411 audio_stream_type_t stream = AudioSystem::attributesToStreamType(attributes_initializer(usage));
Ari Hausman-Cohen433722e2018-04-24 14:25:22 -0700412
413 if (stream < AUDIO_STREAM_MIN || stream >= AUDIO_STREAM_PUBLIC_CNT) {
414 ALOGE("addStreamDefaultEffect(): Unsupported stream type %d", stream);
415 return BAD_VALUE;
416 }
417
418 // Check that |uuid| or |type| corresponds to an effect on the system.
419 effect_descriptor_t descriptor = {};
420 status_t res = AudioEffect::getEffectDescriptor(
421 uuid, type, EFFECT_FLAG_TYPE_INSERT, &descriptor);
422 if (res != OK) {
423 ALOGE("addStreamDefaultEffect(): Failed to find effect descriptor matching uuid/type.");
424 return res;
425 }
426
427 // Only insert effects can be added dynamically as stream defaults.
428 if ((descriptor.flags & EFFECT_FLAG_TYPE_MASK) != EFFECT_FLAG_TYPE_INSERT) {
429 ALOGE("addStreamDefaultEffect(): Desired effect cannot be attached "
430 "as a stream default effect.");
431 return BAD_VALUE;
432 }
433
434 Mutex::Autolock _l(mLock);
435
436 // Find the EffectDescVector for the given stream type, or create a new one if necessary.
437 ssize_t index = mOutputStreams.indexOfKey(stream);
438 EffectDescVector *desc = NULL;
439 if (index < 0) {
440 // No effects for this stream type yet.
441 desc = new EffectDescVector();
442 mOutputStreams.add(stream, desc);
443 } else {
444 desc = mOutputStreams.valueAt(index);
445 }
446
447 // Create a new effect and add it to the vector.
448 res = AudioEffect::newEffectUniqueId(id);
449 if (res != OK) {
450 ALOGE("addStreamDefaultEffect(): failed to get new unique id.");
451 return res;
452 }
453 EffectDesc *effect = new EffectDesc(
454 descriptor.name, *type, opPackageName, *uuid, priority, *id);
455 desc->mEffects.add(effect);
456 // TODO(b/71813697): Support setting params as well.
457
458 // TODO(b/71814300): Retroactively attach to any existing streams of the given type.
459 // This requires tracking the stream type of each session id in addition to what is
460 // already being tracked.
461
462 return NO_ERROR;
463}
464
Ari Hausman-Cohen24628312018-08-13 15:01:09 -0700465status_t AudioPolicyEffects::removeSourceDefaultEffect(audio_unique_id_t id)
466{
467 if (id == AUDIO_UNIQUE_ID_ALLOCATE) {
468 // ALLOCATE is not a unique identifier, but rather a reserved value indicating
469 // a real id has not been assigned. For default effects, this value is only used
470 // by system-owned defaults from the loaded config, which cannot be removed.
471 return BAD_VALUE;
472 }
473
474 Mutex::Autolock _l(mLock);
475
476 // Check each source type.
477 size_t numSources = mInputSources.size();
478 for (size_t i = 0; i < numSources; ++i) {
479 // Check each effect for each source.
480 EffectDescVector* descVector = mInputSources[i];
481 for (auto desc = descVector->mEffects.begin(); desc != descVector->mEffects.end(); ++desc) {
482 if ((*desc)->mId == id) {
483 // Found it!
484 // TODO(b/71814300): Remove from any sources the effect was attached to.
485 descVector->mEffects.erase(desc);
486 // Handles are unique; there can only be one match, so return early.
487 return NO_ERROR;
488 }
489 }
490 }
491
492 // Effect wasn't found, so it's been trivially removed successfully.
493 return NO_ERROR;
494}
495
Ari Hausman-Cohen433722e2018-04-24 14:25:22 -0700496status_t AudioPolicyEffects::removeStreamDefaultEffect(audio_unique_id_t id)
497{
498 if (id == AUDIO_UNIQUE_ID_ALLOCATE) {
499 // ALLOCATE is not a unique identifier, but rather a reserved value indicating
500 // a real id has not been assigned. For default effects, this value is only used
501 // by system-owned defaults from the loaded config, which cannot be removed.
502 return BAD_VALUE;
503 }
504
505 Mutex::Autolock _l(mLock);
506
507 // Check each stream type.
508 size_t numStreams = mOutputStreams.size();
509 for (size_t i = 0; i < numStreams; ++i) {
510 // Check each effect for each stream.
511 EffectDescVector* descVector = mOutputStreams[i];
512 for (auto desc = descVector->mEffects.begin(); desc != descVector->mEffects.end(); ++desc) {
513 if ((*desc)->mId == id) {
514 // Found it!
515 // TODO(b/71814300): Remove from any streams the effect was attached to.
516 descVector->mEffects.erase(desc);
517 // Handles are unique; there can only be one match, so return early.
518 return NO_ERROR;
519 }
520 }
521 }
522
523 // Effect wasn't found, so it's been trivially removed successfully.
524 return NO_ERROR;
525}
bryant_liuba2b4392014-06-11 16:49:30 +0800526
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700527void AudioPolicyEffects::EffectVector::setProcessorEnabled(bool enabled)
bryant_liuba2b4392014-06-11 16:49:30 +0800528{
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700529 for (size_t i = 0; i < mEffects.size(); i++) {
530 mEffects.itemAt(i)->setEnabled(enabled);
bryant_liuba2b4392014-06-11 16:49:30 +0800531 }
532}
533
534
535// ----------------------------------------------------------------------------
536// Audio processing configuration
537// ----------------------------------------------------------------------------
538
539/*static*/ const char * const AudioPolicyEffects::kInputSourceNames[AUDIO_SOURCE_CNT -1] = {
540 MIC_SRC_TAG,
541 VOICE_UL_SRC_TAG,
542 VOICE_DL_SRC_TAG,
543 VOICE_CALL_SRC_TAG,
544 CAMCORDER_SRC_TAG,
545 VOICE_REC_SRC_TAG,
rago8a397d52015-12-02 11:27:57 -0800546 VOICE_COMM_SRC_TAG,
Eric Laurentae4b6ec2019-01-15 18:34:38 -0800547 UNPROCESSED_SRC_TAG,
548 VOICE_PERFORMANCE_SRC_TAG
bryant_liuba2b4392014-06-11 16:49:30 +0800549};
550
551// returns the audio_source_t enum corresponding to the input source name or
552// AUDIO_SOURCE_CNT is no match found
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700553/*static*/ audio_source_t AudioPolicyEffects::inputSourceNameToEnum(const char *name)
bryant_liuba2b4392014-06-11 16:49:30 +0800554{
555 int i;
556 for (i = AUDIO_SOURCE_MIC; i < AUDIO_SOURCE_CNT; i++) {
557 if (strcmp(name, kInputSourceNames[i - AUDIO_SOURCE_MIC]) == 0) {
558 ALOGV("inputSourceNameToEnum found source %s %d", name, i);
559 break;
560 }
561 }
562 return (audio_source_t)i;
563}
564
Eric Laurent223fd5c2014-11-11 13:43:36 -0800565const char *AudioPolicyEffects::kStreamNames[AUDIO_STREAM_PUBLIC_CNT+1] = {
bryant_liuba2b4392014-06-11 16:49:30 +0800566 AUDIO_STREAM_DEFAULT_TAG,
567 AUDIO_STREAM_VOICE_CALL_TAG,
568 AUDIO_STREAM_SYSTEM_TAG,
569 AUDIO_STREAM_RING_TAG,
570 AUDIO_STREAM_MUSIC_TAG,
571 AUDIO_STREAM_ALARM_TAG,
572 AUDIO_STREAM_NOTIFICATION_TAG,
573 AUDIO_STREAM_BLUETOOTH_SCO_TAG,
574 AUDIO_STREAM_ENFORCED_AUDIBLE_TAG,
575 AUDIO_STREAM_DTMF_TAG,
Baekgyeong Kim3a26bb22019-10-30 20:29:41 +0900576 AUDIO_STREAM_TTS_TAG,
577 AUDIO_STREAM_ASSISTANT_TAG
bryant_liuba2b4392014-06-11 16:49:30 +0800578};
579
580// returns the audio_stream_t enum corresponding to the output stream name or
Eric Laurent223fd5c2014-11-11 13:43:36 -0800581// AUDIO_STREAM_PUBLIC_CNT is no match found
bryant_liuba2b4392014-06-11 16:49:30 +0800582audio_stream_type_t AudioPolicyEffects::streamNameToEnum(const char *name)
583{
584 int i;
Eric Laurent223fd5c2014-11-11 13:43:36 -0800585 for (i = AUDIO_STREAM_DEFAULT; i < AUDIO_STREAM_PUBLIC_CNT; i++) {
bryant_liuba2b4392014-06-11 16:49:30 +0800586 if (strcmp(name, kStreamNames[i - AUDIO_STREAM_DEFAULT]) == 0) {
587 ALOGV("streamNameToEnum found stream %s %d", name, i);
588 break;
589 }
590 }
591 return (audio_stream_type_t)i;
592}
593
594// ----------------------------------------------------------------------------
595// Audio Effect Config parser
596// ----------------------------------------------------------------------------
597
Eric Laurent138ed172016-02-10 10:40:44 -0800598size_t AudioPolicyEffects::growParamSize(char **param,
bryant_liuba2b4392014-06-11 16:49:30 +0800599 size_t size,
600 size_t *curSize,
601 size_t *totSize)
602{
603 // *curSize is at least sizeof(effect_param_t) + 2 * sizeof(int)
604 size_t pos = ((*curSize - 1 ) / size + 1) * size;
605
606 if (pos + size > *totSize) {
607 while (pos + size > *totSize) {
608 *totSize += ((*totSize + 7) / 8) * 4;
609 }
George Burgess IV31225682018-02-12 11:08:38 -0800610 char *newParam = (char *)realloc(*param, *totSize);
611 if (newParam == NULL) {
Eric Laurent138ed172016-02-10 10:40:44 -0800612 ALOGE("%s realloc error for size %zu", __func__, *totSize);
613 return 0;
614 }
George Burgess IV31225682018-02-12 11:08:38 -0800615 *param = newParam;
bryant_liuba2b4392014-06-11 16:49:30 +0800616 }
617 *curSize = pos + size;
618 return pos;
619}
620
Eric Laurent138ed172016-02-10 10:40:44 -0800621
bryant_liuba2b4392014-06-11 16:49:30 +0800622size_t AudioPolicyEffects::readParamValue(cnode *node,
Eric Laurent138ed172016-02-10 10:40:44 -0800623 char **param,
bryant_liuba2b4392014-06-11 16:49:30 +0800624 size_t *curSize,
625 size_t *totSize)
626{
Eric Laurent138ed172016-02-10 10:40:44 -0800627 size_t len = 0;
628 size_t pos;
629
bryant_liuba2b4392014-06-11 16:49:30 +0800630 if (strncmp(node->name, SHORT_TAG, sizeof(SHORT_TAG) + 1) == 0) {
Eric Laurent138ed172016-02-10 10:40:44 -0800631 pos = growParamSize(param, sizeof(short), curSize, totSize);
632 if (pos == 0) {
633 goto exit;
bryant_liuba2b4392014-06-11 16:49:30 +0800634 }
Eric Laurent138ed172016-02-10 10:40:44 -0800635 *(short *)(*param + pos) = (short)atoi(node->value);
636 ALOGV("readParamValue() reading short %d", *(short *)(*param + pos));
637 len = sizeof(short);
638 } else if (strncmp(node->name, INT_TAG, sizeof(INT_TAG) + 1) == 0) {
639 pos = growParamSize(param, sizeof(int), curSize, totSize);
640 if (pos == 0) {
641 goto exit;
642 }
643 *(int *)(*param + pos) = atoi(node->value);
644 ALOGV("readParamValue() reading int %d", *(int *)(*param + pos));
645 len = sizeof(int);
646 } else if (strncmp(node->name, FLOAT_TAG, sizeof(FLOAT_TAG) + 1) == 0) {
647 pos = growParamSize(param, sizeof(float), curSize, totSize);
648 if (pos == 0) {
649 goto exit;
650 }
651 *(float *)(*param + pos) = (float)atof(node->value);
652 ALOGV("readParamValue() reading float %f",*(float *)(*param + pos));
653 len = sizeof(float);
654 } else if (strncmp(node->name, BOOL_TAG, sizeof(BOOL_TAG) + 1) == 0) {
655 pos = growParamSize(param, sizeof(bool), curSize, totSize);
656 if (pos == 0) {
657 goto exit;
658 }
659 if (strncmp(node->value, "true", strlen("true") + 1) == 0) {
660 *(bool *)(*param + pos) = true;
661 } else {
662 *(bool *)(*param + pos) = false;
663 }
664 ALOGV("readParamValue() reading bool %s",
665 *(bool *)(*param + pos) ? "true" : "false");
666 len = sizeof(bool);
bryant_liuba2b4392014-06-11 16:49:30 +0800667 } else if (strncmp(node->name, STRING_TAG, sizeof(STRING_TAG) + 1) == 0) {
Eric Laurent138ed172016-02-10 10:40:44 -0800668 len = strnlen(node->value, EFFECT_STRING_LEN_MAX);
bryant_liuba2b4392014-06-11 16:49:30 +0800669 if (*curSize + len + 1 > *totSize) {
670 *totSize = *curSize + len + 1;
Chih-Hung Hsieh03077682018-08-30 14:11:00 -0700671 char *newParam = (char *)realloc(*param, *totSize);
672 if (newParam == NULL) {
Eric Laurent138ed172016-02-10 10:40:44 -0800673 len = 0;
674 ALOGE("%s realloc error for string len %zu", __func__, *totSize);
675 goto exit;
676 }
Chih-Hung Hsieh03077682018-08-30 14:11:00 -0700677 *param = newParam;
bryant_liuba2b4392014-06-11 16:49:30 +0800678 }
Eric Laurent138ed172016-02-10 10:40:44 -0800679 strncpy(*param + *curSize, node->value, len);
bryant_liuba2b4392014-06-11 16:49:30 +0800680 *curSize += len;
Eric Laurent138ed172016-02-10 10:40:44 -0800681 (*param)[*curSize] = '\0';
682 ALOGV("readParamValue() reading string %s", *param + *curSize - len);
683 } else {
684 ALOGW("readParamValue() unknown param type %s", node->name);
bryant_liuba2b4392014-06-11 16:49:30 +0800685 }
Eric Laurent138ed172016-02-10 10:40:44 -0800686exit:
687 return len;
bryant_liuba2b4392014-06-11 16:49:30 +0800688}
689
690effect_param_t *AudioPolicyEffects::loadEffectParameter(cnode *root)
691{
692 cnode *param;
693 cnode *value;
694 size_t curSize = sizeof(effect_param_t);
695 size_t totSize = sizeof(effect_param_t) + 2 * sizeof(int);
696 effect_param_t *fx_param = (effect_param_t *)malloc(totSize);
697
Eric Laurent138ed172016-02-10 10:40:44 -0800698 if (fx_param == NULL) {
699 ALOGE("%s malloc error for effect structure of size %zu",
700 __func__, totSize);
701 return NULL;
702 }
703
bryant_liuba2b4392014-06-11 16:49:30 +0800704 param = config_find(root, PARAM_TAG);
705 value = config_find(root, VALUE_TAG);
706 if (param == NULL && value == NULL) {
707 // try to parse simple parameter form {int int}
708 param = root->first_child;
709 if (param != NULL) {
710 // Note: that a pair of random strings is read as 0 0
711 int *ptr = (int *)fx_param->data;
Eric Laurent138ed172016-02-10 10:40:44 -0800712#if LOG_NDEBUG == 0
bryant_liuba2b4392014-06-11 16:49:30 +0800713 int *ptr2 = (int *)((char *)param + sizeof(effect_param_t));
Eric Laurent138ed172016-02-10 10:40:44 -0800714 ALOGV("loadEffectParameter() ptr %p ptr2 %p", ptr, ptr2);
715#endif
bryant_liuba2b4392014-06-11 16:49:30 +0800716 *ptr++ = atoi(param->name);
717 *ptr = atoi(param->value);
718 fx_param->psize = sizeof(int);
719 fx_param->vsize = sizeof(int);
720 return fx_param;
721 }
722 }
723 if (param == NULL || value == NULL) {
Eric Laurent138ed172016-02-10 10:40:44 -0800724 ALOGW("loadEffectParameter() invalid parameter description %s",
725 root->name);
bryant_liuba2b4392014-06-11 16:49:30 +0800726 goto error;
727 }
728
729 fx_param->psize = 0;
730 param = param->first_child;
731 while (param) {
732 ALOGV("loadEffectParameter() reading param of type %s", param->name);
Eric Laurent138ed172016-02-10 10:40:44 -0800733 size_t size =
734 readParamValue(param, (char **)&fx_param, &curSize, &totSize);
bryant_liuba2b4392014-06-11 16:49:30 +0800735 if (size == 0) {
736 goto error;
737 }
738 fx_param->psize += size;
739 param = param->next;
740 }
741
742 // align start of value field on 32 bit boundary
743 curSize = ((curSize - 1 ) / sizeof(int) + 1) * sizeof(int);
744
745 fx_param->vsize = 0;
746 value = value->first_child;
747 while (value) {
748 ALOGV("loadEffectParameter() reading value of type %s", value->name);
Eric Laurent138ed172016-02-10 10:40:44 -0800749 size_t size =
750 readParamValue(value, (char **)&fx_param, &curSize, &totSize);
bryant_liuba2b4392014-06-11 16:49:30 +0800751 if (size == 0) {
752 goto error;
753 }
754 fx_param->vsize += size;
755 value = value->next;
756 }
757
758 return fx_param;
759
760error:
Eric Laurent138ed172016-02-10 10:40:44 -0800761 free(fx_param);
bryant_liuba2b4392014-06-11 16:49:30 +0800762 return NULL;
763}
764
765void AudioPolicyEffects::loadEffectParameters(cnode *root, Vector <effect_param_t *>& params)
766{
767 cnode *node = root->first_child;
768 while (node) {
769 ALOGV("loadEffectParameters() loading param %s", node->name);
770 effect_param_t *param = loadEffectParameter(node);
Eric Laurent138ed172016-02-10 10:40:44 -0800771 if (param != NULL) {
772 params.add(param);
bryant_liuba2b4392014-06-11 16:49:30 +0800773 }
bryant_liuba2b4392014-06-11 16:49:30 +0800774 node = node->next;
775 }
776}
777
778
779AudioPolicyEffects::EffectDescVector *AudioPolicyEffects::loadEffectConfig(
780 cnode *root,
781 const Vector <EffectDesc *>& effects)
782{
783 cnode *node = root->first_child;
784 if (node == NULL) {
785 ALOGW("loadInputSource() empty element %s", root->name);
786 return NULL;
787 }
788 EffectDescVector *desc = new EffectDescVector();
789 while (node) {
790 size_t i;
Eric Laurent138ed172016-02-10 10:40:44 -0800791
bryant_liuba2b4392014-06-11 16:49:30 +0800792 for (i = 0; i < effects.size(); i++) {
793 if (strncmp(effects[i]->mName, node->name, EFFECT_STRING_LEN_MAX) == 0) {
794 ALOGV("loadEffectConfig() found effect %s in list", node->name);
795 break;
796 }
797 }
798 if (i == effects.size()) {
799 ALOGV("loadEffectConfig() effect %s not in list", node->name);
800 node = node->next;
801 continue;
802 }
803 EffectDesc *effect = new EffectDesc(*effects[i]); // deep copy
804 loadEffectParameters(node, effect->mParams);
805 ALOGV("loadEffectConfig() adding effect %s uuid %08x",
806 effect->mName, effect->mUuid.timeLow);
807 desc->mEffects.add(effect);
808 node = node->next;
809 }
810 if (desc->mEffects.size() == 0) {
811 ALOGW("loadEffectConfig() no valid effects found in config %s", root->name);
812 delete desc;
813 return NULL;
814 }
815 return desc;
816}
817
818status_t AudioPolicyEffects::loadInputEffectConfigurations(cnode *root,
819 const Vector <EffectDesc *>& effects)
820{
821 cnode *node = config_find(root, PREPROCESSING_TAG);
822 if (node == NULL) {
823 return -ENOENT;
824 }
825 node = node->first_child;
826 while (node) {
827 audio_source_t source = inputSourceNameToEnum(node->name);
828 if (source == AUDIO_SOURCE_CNT) {
829 ALOGW("loadInputSources() invalid input source %s", node->name);
830 node = node->next;
831 continue;
832 }
833 ALOGV("loadInputSources() loading input source %s", node->name);
834 EffectDescVector *desc = loadEffectConfig(node, effects);
835 if (desc == NULL) {
836 node = node->next;
837 continue;
838 }
839 mInputSources.add(source, desc);
840 node = node->next;
841 }
842 return NO_ERROR;
843}
844
845status_t AudioPolicyEffects::loadStreamEffectConfigurations(cnode *root,
846 const Vector <EffectDesc *>& effects)
847{
848 cnode *node = config_find(root, OUTPUT_SESSION_PROCESSING_TAG);
849 if (node == NULL) {
850 return -ENOENT;
851 }
852 node = node->first_child;
853 while (node) {
854 audio_stream_type_t stream = streamNameToEnum(node->name);
Eric Laurent223fd5c2014-11-11 13:43:36 -0800855 if (stream == AUDIO_STREAM_PUBLIC_CNT) {
bryant_liuba2b4392014-06-11 16:49:30 +0800856 ALOGW("loadStreamEffectConfigurations() invalid output stream %s", node->name);
857 node = node->next;
858 continue;
859 }
860 ALOGV("loadStreamEffectConfigurations() loading output stream %s", node->name);
861 EffectDescVector *desc = loadEffectConfig(node, effects);
862 if (desc == NULL) {
863 node = node->next;
864 continue;
865 }
866 mOutputStreams.add(stream, desc);
867 node = node->next;
868 }
869 return NO_ERROR;
870}
871
872AudioPolicyEffects::EffectDesc *AudioPolicyEffects::loadEffect(cnode *root)
873{
874 cnode *node = config_find(root, UUID_TAG);
875 if (node == NULL) {
876 return NULL;
877 }
878 effect_uuid_t uuid;
879 if (AudioEffect::stringToGuid(node->value, &uuid) != NO_ERROR) {
880 ALOGW("loadEffect() invalid uuid %s", node->value);
881 return NULL;
882 }
883 return new EffectDesc(root->name, uuid);
884}
885
886status_t AudioPolicyEffects::loadEffects(cnode *root, Vector <EffectDesc *>& effects)
887{
888 cnode *node = config_find(root, EFFECTS_TAG);
889 if (node == NULL) {
890 return -ENOENT;
891 }
892 node = node->first_child;
893 while (node) {
894 ALOGV("loadEffects() loading effect %s", node->name);
895 EffectDesc *effect = loadEffect(node);
896 if (effect == NULL) {
897 node = node->next;
898 continue;
899 }
900 effects.add(effect);
901 node = node->next;
902 }
903 return NO_ERROR;
904}
905
Kevin Rocard4fb615c2017-06-26 10:28:13 -0700906status_t AudioPolicyEffects::loadAudioEffectXmlConfig() {
907 auto result = effectsConfig::parse();
908 if (result.parsedConfig == nullptr) {
909 return -ENOENT;
910 }
911
912 auto loadProcessingChain = [](auto& processingChain, auto& streams) {
913 for (auto& stream : processingChain) {
914 auto effectDescs = std::make_unique<EffectDescVector>();
915 for (auto& effect : stream.effects) {
916 effectDescs->mEffects.add(
917 new EffectDesc{effect.get().name.c_str(), effect.get().uuid});
918 }
919 streams.add(stream.type, effectDescs.release());
920 }
921 };
François Gaffie06182982020-01-07 15:16:14 +0100922
923 auto loadDeviceProcessingChain = [](auto &processingChain, auto& devicesEffects) {
924 for (auto& deviceProcess : processingChain) {
925
926 auto effectDescs = std::make_unique<EffectDescVector>();
927 for (auto& effect : deviceProcess.effects) {
928 effectDescs->mEffects.add(
929 new EffectDesc{effect.get().name.c_str(), effect.get().uuid});
930 }
931 auto deviceEffects = std::make_unique<DeviceEffects>(
932 std::move(effectDescs), deviceProcess.type, deviceProcess.address);
933 devicesEffects.emplace(deviceProcess.address, std::move(deviceEffects));
934 }
935 };
936
Kevin Rocard4fb615c2017-06-26 10:28:13 -0700937 loadProcessingChain(result.parsedConfig->preprocess, mInputSources);
938 loadProcessingChain(result.parsedConfig->postprocess, mOutputStreams);
Mikhail Naganov12b716c2020-04-30 22:37:43 +0000939 {
940 Mutex::Autolock _l(mLock);
941 loadDeviceProcessingChain(result.parsedConfig->deviceprocess, mDeviceEffects);
942 }
Kevin Rocard4fb615c2017-06-26 10:28:13 -0700943 // Casting from ssize_t to status_t is probably safe, there should not be more than 2^31 errors
944 return result.nbSkippedElement;
945}
946
bryant_liuba2b4392014-06-11 16:49:30 +0800947status_t AudioPolicyEffects::loadAudioEffectConfig(const char *path)
948{
949 cnode *root;
950 char *data;
951
952 data = (char *)load_file(path, NULL);
953 if (data == NULL) {
954 return -ENODEV;
955 }
956 root = config_node("", "");
957 config_load(root, data);
958
959 Vector <EffectDesc *> effects;
960 loadEffects(root, effects);
961 loadInputEffectConfigurations(root, effects);
962 loadStreamEffectConfigurations(root, effects);
963
Eric Laurent182c2f52015-01-15 14:29:19 -0800964 for (size_t i = 0; i < effects.size(); i++) {
965 delete effects[i];
966 }
967
bryant_liuba2b4392014-06-11 16:49:30 +0800968 config_free(root);
969 free(root);
970 free(data);
971
972 return NO_ERROR;
973}
974
François Gaffie06182982020-01-07 15:16:14 +0100975void AudioPolicyEffects::initDefaultDeviceEffects()
976{
977 Mutex::Autolock _l(mLock);
978 for (const auto& deviceEffectsIter : mDeviceEffects) {
979 const auto& deviceEffects = deviceEffectsIter.second;
980 for (const auto& effectDesc : deviceEffects->mEffectDescriptors->mEffects) {
Svet Ganov33761132021-05-13 22:51:08 +0000981 AttributionSourceState attributionSource;
982 attributionSource.packageName = "android";
983 attributionSource.token = sp<BBinder>::make();
984 sp<AudioEffect> fx = new AudioEffect(attributionSource);
Mikhail Naganov69d41cc2020-07-31 17:36:08 -0700985 fx->set(EFFECT_UUID_NULL, &effectDesc->mUuid, 0, nullptr,
986 nullptr, AUDIO_SESSION_DEVICE, AUDIO_IO_HANDLE_NONE,
987 AudioDeviceTypeAddr{deviceEffects->getDeviceType(),
988 deviceEffects->getDeviceAddress()});
François Gaffie06182982020-01-07 15:16:14 +0100989 status_t status = fx->initCheck();
990 if (status != NO_ERROR && status != ALREADY_EXISTS) {
991 ALOGE("%s(): failed to create Fx %s on port type=%d address=%s", __func__,
992 effectDesc->mName, deviceEffects->getDeviceType(),
993 deviceEffects->getDeviceAddress().c_str());
994 // fx goes out of scope and strong ref on AudioEffect is released
995 continue;
996 }
997 fx->setEnabled(true);
998 ALOGV("%s(): create Fx %s added on port type=%d address=%s", __func__,
999 effectDesc->mName, deviceEffects->getDeviceType(),
1000 deviceEffects->getDeviceAddress().c_str());
Jintao Zhu230397e2021-03-07 14:15:10 +08001001 deviceEffects->mEffects.push_back(fx);
François Gaffie06182982020-01-07 15:16:14 +01001002 }
1003 }
1004}
bryant_liuba2b4392014-06-11 16:49:30 +08001005
Mikhail Naganov1b2a7942017-12-08 10:18:09 -08001006} // namespace android