blob: c7a60c2e7fdfb0b592fb5bf818817853a3835a7d [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 Ganov3e5f14f2021-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 Ganov3e5f14f2021-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);
Atneya Nair884f7992022-05-17 19:22:42 -0400130 fx->set(nullptr /*type */, &effect->mUuid, -1 /* priority */, nullptr /* callback */,
131 audioSession, input);
Eric Laurent7de5ac12014-10-21 09:07:11 -0700132 status_t status = fx->initCheck();
133 if (status != NO_ERROR && status != ALREADY_EXISTS) {
134 ALOGW("addInputEffects(): failed to create Fx %s on source %d",
135 effect->mName, (int32_t)aliasSource);
136 // fx goes out of scope and strong ref on AudioEffect is released
137 continue;
138 }
139 for (size_t j = 0; j < effect->mParams.size(); j++) {
140 fx->setParameter(effect->mParams[j]);
141 }
142 ALOGV("addInputEffects(): added Fx %s on source: %d",
bryant_liuba2b4392014-06-11 16:49:30 +0800143 effect->mName, (int32_t)aliasSource);
Eric Laurentfb66dd92016-01-28 18:32:03 -0800144 sessionDesc->mEffects.add(fx);
bryant_liuba2b4392014-06-11 16:49:30 +0800145 }
Eric Laurentfb66dd92016-01-28 18:32:03 -0800146 sessionDesc->setProcessorEnabled(true);
Eric Laurentb6436272016-12-07 19:24:50 -0800147 IPCThreadState::self()->restoreCallingIdentity(token);
bryant_liuba2b4392014-06-11 16:49:30 +0800148 }
bryant_liuba2b4392014-06-11 16:49:30 +0800149 return status;
150}
151
152
Eric Laurentfb66dd92016-01-28 18:32:03 -0800153status_t AudioPolicyEffects::releaseInputEffects(audio_io_handle_t input,
154 audio_session_t audioSession)
bryant_liuba2b4392014-06-11 16:49:30 +0800155{
156 status_t status = NO_ERROR;
157
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700158 Mutex::Autolock _l(mLock);
Eric Laurentfb66dd92016-01-28 18:32:03 -0800159 ssize_t index = mInputSessions.indexOfKey(audioSession);
bryant_liuba2b4392014-06-11 16:49:30 +0800160 if (index < 0) {
161 return status;
162 }
Eric Laurentfb66dd92016-01-28 18:32:03 -0800163 EffectVector *sessionDesc = mInputSessions.valueAt(index);
164 sessionDesc->mRefCount--;
165 ALOGV("releaseInputEffects(): input: %d, refCount: %d", input, sessionDesc->mRefCount);
166 if (sessionDesc->mRefCount == 0) {
167 sessionDesc->setProcessorEnabled(false);
168 delete sessionDesc;
169 mInputSessions.removeItemsAt(index);
bryant_liu890a5632014-08-20 18:06:13 +0800170 ALOGV("releaseInputEffects(): all effects released");
171 }
bryant_liuba2b4392014-06-11 16:49:30 +0800172 return status;
173}
174
Eric Laurentfb66dd92016-01-28 18:32:03 -0800175status_t AudioPolicyEffects::queryDefaultInputEffects(audio_session_t audioSession,
bryant_liuba2b4392014-06-11 16:49:30 +0800176 effect_descriptor_t *descriptors,
177 uint32_t *count)
178{
179 status_t status = NO_ERROR;
180
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700181 Mutex::Autolock _l(mLock);
bryant_liuba2b4392014-06-11 16:49:30 +0800182 size_t index;
Eric Laurentfb66dd92016-01-28 18:32:03 -0800183 for (index = 0; index < mInputSessions.size(); index++) {
184 if (mInputSessions.valueAt(index)->mSessionId == audioSession) {
bryant_liuba2b4392014-06-11 16:49:30 +0800185 break;
186 }
187 }
Eric Laurentfb66dd92016-01-28 18:32:03 -0800188 if (index == mInputSessions.size()) {
bryant_liuba2b4392014-06-11 16:49:30 +0800189 *count = 0;
190 return BAD_VALUE;
191 }
Eric Laurentfb66dd92016-01-28 18:32:03 -0800192 Vector< sp<AudioEffect> > effects = mInputSessions.valueAt(index)->mEffects;
bryant_liuba2b4392014-06-11 16:49:30 +0800193
194 for (size_t i = 0; i < effects.size(); i++) {
195 effect_descriptor_t desc = effects[i]->descriptor();
196 if (i < *count) {
197 descriptors[i] = desc;
198 }
199 }
200 if (effects.size() > *count) {
201 status = NO_MEMORY;
202 }
203 *count = effects.size();
204 return status;
205}
206
207
Eric Laurentfb66dd92016-01-28 18:32:03 -0800208status_t AudioPolicyEffects::queryDefaultOutputSessionEffects(audio_session_t audioSession,
bryant_liuba2b4392014-06-11 16:49:30 +0800209 effect_descriptor_t *descriptors,
210 uint32_t *count)
211{
212 status_t status = NO_ERROR;
213
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700214 Mutex::Autolock _l(mLock);
bryant_liuba2b4392014-06-11 16:49:30 +0800215 size_t index;
216 for (index = 0; index < mOutputSessions.size(); index++) {
217 if (mOutputSessions.valueAt(index)->mSessionId == audioSession) {
218 break;
219 }
220 }
221 if (index == mOutputSessions.size()) {
222 *count = 0;
223 return BAD_VALUE;
224 }
225 Vector< sp<AudioEffect> > effects = mOutputSessions.valueAt(index)->mEffects;
226
227 for (size_t i = 0; i < effects.size(); i++) {
228 effect_descriptor_t desc = effects[i]->descriptor();
229 if (i < *count) {
230 descriptors[i] = desc;
231 }
232 }
233 if (effects.size() > *count) {
234 status = NO_MEMORY;
235 }
236 *count = effects.size();
237 return status;
238}
239
240
241status_t AudioPolicyEffects::addOutputSessionEffects(audio_io_handle_t output,
242 audio_stream_type_t stream,
Eric Laurentfb66dd92016-01-28 18:32:03 -0800243 audio_session_t audioSession)
bryant_liuba2b4392014-06-11 16:49:30 +0800244{
245 status_t status = NO_ERROR;
246
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700247 Mutex::Autolock _l(mLock);
bryant_liuba2b4392014-06-11 16:49:30 +0800248 // create audio processors according to stream
Eric Laurent223fd5c2014-11-11 13:43:36 -0800249 // FIXME: should we have specific post processing settings for internal streams?
250 // default to media for now.
251 if (stream >= AUDIO_STREAM_PUBLIC_CNT) {
252 stream = AUDIO_STREAM_MUSIC;
253 }
bryant_liuba2b4392014-06-11 16:49:30 +0800254 ssize_t index = mOutputStreams.indexOfKey(stream);
255 if (index < 0) {
256 ALOGV("addOutputSessionEffects(): no output processing needed for this stream");
257 return NO_ERROR;
258 }
259
260 ssize_t idx = mOutputSessions.indexOfKey(audioSession);
261 EffectVector *procDesc;
262 if (idx < 0) {
263 procDesc = new EffectVector(audioSession);
264 mOutputSessions.add(audioSession, procDesc);
265 } else {
bryant_liu890a5632014-08-20 18:06:13 +0800266 // EffectVector is existing and we just need to increase ref count
bryant_liuba2b4392014-06-11 16:49:30 +0800267 procDesc = mOutputSessions.valueAt(idx);
268 }
bryant_liu890a5632014-08-20 18:06:13 +0800269 procDesc->mRefCount++;
270
Eric Laurent7de5ac12014-10-21 09:07:11 -0700271 ALOGV("addOutputSessionEffects(): session: %d, refCount: %d",
272 audioSession, procDesc->mRefCount);
273 if (procDesc->mRefCount == 1) {
Eric Laurentb6436272016-12-07 19:24:50 -0800274 // make sure effects are associated to audio server even if we are executing a binder call
275 int64_t token = IPCThreadState::self()->clearCallingIdentity();
Eric Laurent7de5ac12014-10-21 09:07:11 -0700276 Vector <EffectDesc *> effects = mOutputStreams.valueAt(index)->mEffects;
277 for (size_t i = 0; i < effects.size(); i++) {
278 EffectDesc *effect = effects[i];
Svet Ganov3e5f14f2021-05-13 22:51:08 +0000279 AttributionSourceState attributionSource;
280 attributionSource.packageName = "android";
281 attributionSource.token = sp<BBinder>::make();
282 sp<AudioEffect> fx = new AudioEffect(attributionSource);
Atneya Nair884f7992022-05-17 19:22:42 -0400283 fx->set(nullptr /* type */, &effect->mUuid, 0 /* priority */, nullptr /* callback */,
284 audioSession, output);
Eric Laurent7de5ac12014-10-21 09:07:11 -0700285 status_t status = fx->initCheck();
286 if (status != NO_ERROR && status != ALREADY_EXISTS) {
287 ALOGE("addOutputSessionEffects(): failed to create Fx %s on session %d",
288 effect->mName, audioSession);
289 // fx goes out of scope and strong ref on AudioEffect is released
290 continue;
291 }
292 ALOGV("addOutputSessionEffects(): added Fx %s on session: %d for stream: %d",
293 effect->mName, audioSession, (int32_t)stream);
294 procDesc->mEffects.add(fx);
bryant_liuba2b4392014-06-11 16:49:30 +0800295 }
Eric Laurent7de5ac12014-10-21 09:07:11 -0700296
297 procDesc->setProcessorEnabled(true);
Eric Laurentb6436272016-12-07 19:24:50 -0800298 IPCThreadState::self()->restoreCallingIdentity(token);
bryant_liuba2b4392014-06-11 16:49:30 +0800299 }
bryant_liuba2b4392014-06-11 16:49:30 +0800300 return status;
301}
302
303status_t AudioPolicyEffects::releaseOutputSessionEffects(audio_io_handle_t output,
304 audio_stream_type_t stream,
Eric Laurentfb66dd92016-01-28 18:32:03 -0800305 audio_session_t audioSession)
bryant_liuba2b4392014-06-11 16:49:30 +0800306{
307 status_t status = NO_ERROR;
308 (void) output; // argument not used for now
309 (void) stream; // argument not used for now
310
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700311 Mutex::Autolock _l(mLock);
bryant_liuba2b4392014-06-11 16:49:30 +0800312 ssize_t index = mOutputSessions.indexOfKey(audioSession);
313 if (index < 0) {
314 ALOGV("releaseOutputSessionEffects: no output processing was attached to this stream");
315 return NO_ERROR;
316 }
317
318 EffectVector *procDesc = mOutputSessions.valueAt(index);
bryant_liu890a5632014-08-20 18:06:13 +0800319 procDesc->mRefCount--;
Eric Laurent7de5ac12014-10-21 09:07:11 -0700320 ALOGV("releaseOutputSessionEffects(): session: %d, refCount: %d",
321 audioSession, procDesc->mRefCount);
bryant_liu890a5632014-08-20 18:06:13 +0800322 if (procDesc->mRefCount == 0) {
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700323 procDesc->setProcessorEnabled(false);
bryant_liu890a5632014-08-20 18:06:13 +0800324 procDesc->mEffects.clear();
325 delete procDesc;
326 mOutputSessions.removeItemsAt(index);
327 ALOGV("releaseOutputSessionEffects(): output processing released from session: %d",
328 audioSession);
329 }
bryant_liuba2b4392014-06-11 16:49:30 +0800330 return status;
331}
332
Ari Hausman-Cohen24628312018-08-13 15:01:09 -0700333status_t AudioPolicyEffects::addSourceDefaultEffect(const effect_uuid_t *type,
334 const String16& opPackageName,
335 const effect_uuid_t *uuid,
336 int32_t priority,
337 audio_source_t source,
338 audio_unique_id_t* id)
339{
340 if (uuid == NULL || type == NULL) {
341 ALOGE("addSourceDefaultEffect(): Null uuid or type uuid pointer");
342 return BAD_VALUE;
343 }
344
Eric Laurentae4b6ec2019-01-15 18:34:38 -0800345 // HOTWORD, FM_TUNER and ECHO_REFERENCE are special case sources > MAX.
Ari Hausman-Cohen24628312018-08-13 15:01:09 -0700346 if (source < AUDIO_SOURCE_DEFAULT ||
347 (source > AUDIO_SOURCE_MAX &&
348 source != AUDIO_SOURCE_HOTWORD &&
Eric Laurentae4b6ec2019-01-15 18:34:38 -0800349 source != AUDIO_SOURCE_FM_TUNER &&
Carter Hsua3abb402021-10-26 11:11:20 +0800350 source != AUDIO_SOURCE_ECHO_REFERENCE &&
351 source != AUDIO_SOURCE_ULTRASOUND)) {
Ari Hausman-Cohen24628312018-08-13 15:01:09 -0700352 ALOGE("addSourceDefaultEffect(): Unsupported source type %d", source);
353 return BAD_VALUE;
354 }
355
356 // Check that |uuid| or |type| corresponds to an effect on the system.
357 effect_descriptor_t descriptor = {};
358 status_t res = AudioEffect::getEffectDescriptor(
359 uuid, type, EFFECT_FLAG_TYPE_PRE_PROC, &descriptor);
360 if (res != OK) {
361 ALOGE("addSourceDefaultEffect(): Failed to find effect descriptor matching uuid/type.");
362 return res;
363 }
364
365 // Only pre-processing effects can be added dynamically as source defaults.
366 if ((descriptor.flags & EFFECT_FLAG_TYPE_MASK) != EFFECT_FLAG_TYPE_PRE_PROC) {
367 ALOGE("addSourceDefaultEffect(): Desired effect cannot be attached "
368 "as a source default effect.");
369 return BAD_VALUE;
370 }
371
372 Mutex::Autolock _l(mLock);
373
374 // Find the EffectDescVector for the given source type, or create a new one if necessary.
375 ssize_t index = mInputSources.indexOfKey(source);
376 EffectDescVector *desc = NULL;
377 if (index < 0) {
378 // No effects for this source type yet.
379 desc = new EffectDescVector();
380 mInputSources.add(source, desc);
381 } else {
382 desc = mInputSources.valueAt(index);
383 }
384
385 // Create a new effect and add it to the vector.
386 res = AudioEffect::newEffectUniqueId(id);
387 if (res != OK) {
388 ALOGE("addSourceDefaultEffect(): failed to get new unique id.");
389 return res;
390 }
391 EffectDesc *effect = new EffectDesc(
Eric Laurent2685aa02022-02-01 14:26:38 +0100392 descriptor.name, descriptor.type, opPackageName, descriptor.uuid, priority, *id);
Ari Hausman-Cohen24628312018-08-13 15:01:09 -0700393 desc->mEffects.add(effect);
394 // TODO(b/71813697): Support setting params as well.
395
396 // TODO(b/71814300): Retroactively attach to any existing sources of the given type.
397 // This requires tracking the source type of each session id in addition to what is
398 // already being tracked.
399
400 return NO_ERROR;
401}
402
Ari Hausman-Cohen433722e2018-04-24 14:25:22 -0700403status_t AudioPolicyEffects::addStreamDefaultEffect(const effect_uuid_t *type,
404 const String16& opPackageName,
405 const effect_uuid_t *uuid,
406 int32_t priority,
407 audio_usage_t usage,
408 audio_unique_id_t* id)
409{
410 if (uuid == NULL || type == NULL) {
411 ALOGE("addStreamDefaultEffect(): Null uuid or type uuid pointer");
412 return BAD_VALUE;
413 }
François Gaffie58d4be52018-11-06 15:30:12 +0100414 audio_stream_type_t stream = AudioSystem::attributesToStreamType(attributes_initializer(usage));
Ari Hausman-Cohen433722e2018-04-24 14:25:22 -0700415
416 if (stream < AUDIO_STREAM_MIN || stream >= AUDIO_STREAM_PUBLIC_CNT) {
417 ALOGE("addStreamDefaultEffect(): Unsupported stream type %d", stream);
418 return BAD_VALUE;
419 }
420
421 // Check that |uuid| or |type| corresponds to an effect on the system.
422 effect_descriptor_t descriptor = {};
423 status_t res = AudioEffect::getEffectDescriptor(
424 uuid, type, EFFECT_FLAG_TYPE_INSERT, &descriptor);
425 if (res != OK) {
426 ALOGE("addStreamDefaultEffect(): Failed to find effect descriptor matching uuid/type.");
427 return res;
428 }
429
430 // Only insert effects can be added dynamically as stream defaults.
431 if ((descriptor.flags & EFFECT_FLAG_TYPE_MASK) != EFFECT_FLAG_TYPE_INSERT) {
432 ALOGE("addStreamDefaultEffect(): Desired effect cannot be attached "
433 "as a stream default effect.");
434 return BAD_VALUE;
435 }
436
437 Mutex::Autolock _l(mLock);
438
439 // Find the EffectDescVector for the given stream type, or create a new one if necessary.
440 ssize_t index = mOutputStreams.indexOfKey(stream);
441 EffectDescVector *desc = NULL;
442 if (index < 0) {
443 // No effects for this stream type yet.
444 desc = new EffectDescVector();
445 mOutputStreams.add(stream, desc);
446 } else {
447 desc = mOutputStreams.valueAt(index);
448 }
449
450 // Create a new effect and add it to the vector.
451 res = AudioEffect::newEffectUniqueId(id);
452 if (res != OK) {
453 ALOGE("addStreamDefaultEffect(): failed to get new unique id.");
454 return res;
455 }
456 EffectDesc *effect = new EffectDesc(
Eric Laurent2685aa02022-02-01 14:26:38 +0100457 descriptor.name, descriptor.type, opPackageName, descriptor.uuid, priority, *id);
Ari Hausman-Cohen433722e2018-04-24 14:25:22 -0700458 desc->mEffects.add(effect);
459 // TODO(b/71813697): Support setting params as well.
460
461 // TODO(b/71814300): Retroactively attach to any existing streams of the given type.
462 // This requires tracking the stream type of each session id in addition to what is
463 // already being tracked.
464
465 return NO_ERROR;
466}
467
Ari Hausman-Cohen24628312018-08-13 15:01:09 -0700468status_t AudioPolicyEffects::removeSourceDefaultEffect(audio_unique_id_t id)
469{
470 if (id == AUDIO_UNIQUE_ID_ALLOCATE) {
471 // ALLOCATE is not a unique identifier, but rather a reserved value indicating
472 // a real id has not been assigned. For default effects, this value is only used
473 // by system-owned defaults from the loaded config, which cannot be removed.
474 return BAD_VALUE;
475 }
476
477 Mutex::Autolock _l(mLock);
478
479 // Check each source type.
480 size_t numSources = mInputSources.size();
481 for (size_t i = 0; i < numSources; ++i) {
482 // Check each effect for each source.
483 EffectDescVector* descVector = mInputSources[i];
484 for (auto desc = descVector->mEffects.begin(); desc != descVector->mEffects.end(); ++desc) {
485 if ((*desc)->mId == id) {
486 // Found it!
487 // TODO(b/71814300): Remove from any sources the effect was attached to.
488 descVector->mEffects.erase(desc);
489 // Handles are unique; there can only be one match, so return early.
490 return NO_ERROR;
491 }
492 }
493 }
494
495 // Effect wasn't found, so it's been trivially removed successfully.
496 return NO_ERROR;
497}
498
Ari Hausman-Cohen433722e2018-04-24 14:25:22 -0700499status_t AudioPolicyEffects::removeStreamDefaultEffect(audio_unique_id_t id)
500{
501 if (id == AUDIO_UNIQUE_ID_ALLOCATE) {
502 // ALLOCATE is not a unique identifier, but rather a reserved value indicating
503 // a real id has not been assigned. For default effects, this value is only used
504 // by system-owned defaults from the loaded config, which cannot be removed.
505 return BAD_VALUE;
506 }
507
508 Mutex::Autolock _l(mLock);
509
510 // Check each stream type.
511 size_t numStreams = mOutputStreams.size();
512 for (size_t i = 0; i < numStreams; ++i) {
513 // Check each effect for each stream.
514 EffectDescVector* descVector = mOutputStreams[i];
515 for (auto desc = descVector->mEffects.begin(); desc != descVector->mEffects.end(); ++desc) {
516 if ((*desc)->mId == id) {
517 // Found it!
518 // TODO(b/71814300): Remove from any streams the effect was attached to.
519 descVector->mEffects.erase(desc);
520 // Handles are unique; there can only be one match, so return early.
521 return NO_ERROR;
522 }
523 }
524 }
525
526 // Effect wasn't found, so it's been trivially removed successfully.
527 return NO_ERROR;
528}
bryant_liuba2b4392014-06-11 16:49:30 +0800529
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700530void AudioPolicyEffects::EffectVector::setProcessorEnabled(bool enabled)
bryant_liuba2b4392014-06-11 16:49:30 +0800531{
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700532 for (size_t i = 0; i < mEffects.size(); i++) {
533 mEffects.itemAt(i)->setEnabled(enabled);
bryant_liuba2b4392014-06-11 16:49:30 +0800534 }
535}
536
537
538// ----------------------------------------------------------------------------
539// Audio processing configuration
540// ----------------------------------------------------------------------------
541
542/*static*/ const char * const AudioPolicyEffects::kInputSourceNames[AUDIO_SOURCE_CNT -1] = {
543 MIC_SRC_TAG,
544 VOICE_UL_SRC_TAG,
545 VOICE_DL_SRC_TAG,
546 VOICE_CALL_SRC_TAG,
547 CAMCORDER_SRC_TAG,
548 VOICE_REC_SRC_TAG,
rago8a397d52015-12-02 11:27:57 -0800549 VOICE_COMM_SRC_TAG,
Carter Hsua3abb402021-10-26 11:11:20 +0800550 REMOTE_SUBMIX_SRC_TAG,
Eric Laurentae4b6ec2019-01-15 18:34:38 -0800551 UNPROCESSED_SRC_TAG,
552 VOICE_PERFORMANCE_SRC_TAG
bryant_liuba2b4392014-06-11 16:49:30 +0800553};
554
555// returns the audio_source_t enum corresponding to the input source name or
556// AUDIO_SOURCE_CNT is no match found
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700557/*static*/ audio_source_t AudioPolicyEffects::inputSourceNameToEnum(const char *name)
bryant_liuba2b4392014-06-11 16:49:30 +0800558{
559 int i;
560 for (i = AUDIO_SOURCE_MIC; i < AUDIO_SOURCE_CNT; i++) {
561 if (strcmp(name, kInputSourceNames[i - AUDIO_SOURCE_MIC]) == 0) {
562 ALOGV("inputSourceNameToEnum found source %s %d", name, i);
563 break;
564 }
565 }
566 return (audio_source_t)i;
567}
568
Eric Laurent223fd5c2014-11-11 13:43:36 -0800569const char *AudioPolicyEffects::kStreamNames[AUDIO_STREAM_PUBLIC_CNT+1] = {
bryant_liuba2b4392014-06-11 16:49:30 +0800570 AUDIO_STREAM_DEFAULT_TAG,
571 AUDIO_STREAM_VOICE_CALL_TAG,
572 AUDIO_STREAM_SYSTEM_TAG,
573 AUDIO_STREAM_RING_TAG,
574 AUDIO_STREAM_MUSIC_TAG,
575 AUDIO_STREAM_ALARM_TAG,
576 AUDIO_STREAM_NOTIFICATION_TAG,
577 AUDIO_STREAM_BLUETOOTH_SCO_TAG,
578 AUDIO_STREAM_ENFORCED_AUDIBLE_TAG,
579 AUDIO_STREAM_DTMF_TAG,
Baekgyeong Kim3a26bb22019-10-30 20:29:41 +0900580 AUDIO_STREAM_TTS_TAG,
581 AUDIO_STREAM_ASSISTANT_TAG
bryant_liuba2b4392014-06-11 16:49:30 +0800582};
583
584// returns the audio_stream_t enum corresponding to the output stream name or
Eric Laurent223fd5c2014-11-11 13:43:36 -0800585// AUDIO_STREAM_PUBLIC_CNT is no match found
bryant_liuba2b4392014-06-11 16:49:30 +0800586audio_stream_type_t AudioPolicyEffects::streamNameToEnum(const char *name)
587{
588 int i;
Eric Laurent223fd5c2014-11-11 13:43:36 -0800589 for (i = AUDIO_STREAM_DEFAULT; i < AUDIO_STREAM_PUBLIC_CNT; i++) {
bryant_liuba2b4392014-06-11 16:49:30 +0800590 if (strcmp(name, kStreamNames[i - AUDIO_STREAM_DEFAULT]) == 0) {
591 ALOGV("streamNameToEnum found stream %s %d", name, i);
592 break;
593 }
594 }
595 return (audio_stream_type_t)i;
596}
597
598// ----------------------------------------------------------------------------
599// Audio Effect Config parser
600// ----------------------------------------------------------------------------
601
Eric Laurent138ed172016-02-10 10:40:44 -0800602size_t AudioPolicyEffects::growParamSize(char **param,
bryant_liuba2b4392014-06-11 16:49:30 +0800603 size_t size,
604 size_t *curSize,
605 size_t *totSize)
606{
607 // *curSize is at least sizeof(effect_param_t) + 2 * sizeof(int)
608 size_t pos = ((*curSize - 1 ) / size + 1) * size;
609
610 if (pos + size > *totSize) {
611 while (pos + size > *totSize) {
612 *totSize += ((*totSize + 7) / 8) * 4;
613 }
George Burgess IV31225682018-02-12 11:08:38 -0800614 char *newParam = (char *)realloc(*param, *totSize);
615 if (newParam == NULL) {
Eric Laurent138ed172016-02-10 10:40:44 -0800616 ALOGE("%s realloc error for size %zu", __func__, *totSize);
617 return 0;
618 }
George Burgess IV31225682018-02-12 11:08:38 -0800619 *param = newParam;
bryant_liuba2b4392014-06-11 16:49:30 +0800620 }
621 *curSize = pos + size;
622 return pos;
623}
624
Eric Laurent138ed172016-02-10 10:40:44 -0800625
bryant_liuba2b4392014-06-11 16:49:30 +0800626size_t AudioPolicyEffects::readParamValue(cnode *node,
Eric Laurent138ed172016-02-10 10:40:44 -0800627 char **param,
bryant_liuba2b4392014-06-11 16:49:30 +0800628 size_t *curSize,
629 size_t *totSize)
630{
Eric Laurent138ed172016-02-10 10:40:44 -0800631 size_t len = 0;
632 size_t pos;
633
bryant_liuba2b4392014-06-11 16:49:30 +0800634 if (strncmp(node->name, SHORT_TAG, sizeof(SHORT_TAG) + 1) == 0) {
Eric Laurent138ed172016-02-10 10:40:44 -0800635 pos = growParamSize(param, sizeof(short), curSize, totSize);
636 if (pos == 0) {
637 goto exit;
bryant_liuba2b4392014-06-11 16:49:30 +0800638 }
Eric Laurent138ed172016-02-10 10:40:44 -0800639 *(short *)(*param + pos) = (short)atoi(node->value);
640 ALOGV("readParamValue() reading short %d", *(short *)(*param + pos));
641 len = sizeof(short);
642 } else if (strncmp(node->name, INT_TAG, sizeof(INT_TAG) + 1) == 0) {
643 pos = growParamSize(param, sizeof(int), curSize, totSize);
644 if (pos == 0) {
645 goto exit;
646 }
647 *(int *)(*param + pos) = atoi(node->value);
648 ALOGV("readParamValue() reading int %d", *(int *)(*param + pos));
649 len = sizeof(int);
650 } else if (strncmp(node->name, FLOAT_TAG, sizeof(FLOAT_TAG) + 1) == 0) {
651 pos = growParamSize(param, sizeof(float), curSize, totSize);
652 if (pos == 0) {
653 goto exit;
654 }
655 *(float *)(*param + pos) = (float)atof(node->value);
656 ALOGV("readParamValue() reading float %f",*(float *)(*param + pos));
657 len = sizeof(float);
658 } else if (strncmp(node->name, BOOL_TAG, sizeof(BOOL_TAG) + 1) == 0) {
659 pos = growParamSize(param, sizeof(bool), curSize, totSize);
660 if (pos == 0) {
661 goto exit;
662 }
663 if (strncmp(node->value, "true", strlen("true") + 1) == 0) {
664 *(bool *)(*param + pos) = true;
665 } else {
666 *(bool *)(*param + pos) = false;
667 }
668 ALOGV("readParamValue() reading bool %s",
669 *(bool *)(*param + pos) ? "true" : "false");
670 len = sizeof(bool);
bryant_liuba2b4392014-06-11 16:49:30 +0800671 } else if (strncmp(node->name, STRING_TAG, sizeof(STRING_TAG) + 1) == 0) {
Eric Laurent138ed172016-02-10 10:40:44 -0800672 len = strnlen(node->value, EFFECT_STRING_LEN_MAX);
bryant_liuba2b4392014-06-11 16:49:30 +0800673 if (*curSize + len + 1 > *totSize) {
674 *totSize = *curSize + len + 1;
Chih-Hung Hsieh03077682018-08-30 14:11:00 -0700675 char *newParam = (char *)realloc(*param, *totSize);
676 if (newParam == NULL) {
Eric Laurent138ed172016-02-10 10:40:44 -0800677 len = 0;
678 ALOGE("%s realloc error for string len %zu", __func__, *totSize);
679 goto exit;
680 }
Chih-Hung Hsieh03077682018-08-30 14:11:00 -0700681 *param = newParam;
bryant_liuba2b4392014-06-11 16:49:30 +0800682 }
Eric Laurent138ed172016-02-10 10:40:44 -0800683 strncpy(*param + *curSize, node->value, len);
bryant_liuba2b4392014-06-11 16:49:30 +0800684 *curSize += len;
Eric Laurent138ed172016-02-10 10:40:44 -0800685 (*param)[*curSize] = '\0';
686 ALOGV("readParamValue() reading string %s", *param + *curSize - len);
687 } else {
688 ALOGW("readParamValue() unknown param type %s", node->name);
bryant_liuba2b4392014-06-11 16:49:30 +0800689 }
Eric Laurent138ed172016-02-10 10:40:44 -0800690exit:
691 return len;
bryant_liuba2b4392014-06-11 16:49:30 +0800692}
693
694effect_param_t *AudioPolicyEffects::loadEffectParameter(cnode *root)
695{
696 cnode *param;
697 cnode *value;
698 size_t curSize = sizeof(effect_param_t);
699 size_t totSize = sizeof(effect_param_t) + 2 * sizeof(int);
700 effect_param_t *fx_param = (effect_param_t *)malloc(totSize);
701
Eric Laurent138ed172016-02-10 10:40:44 -0800702 if (fx_param == NULL) {
703 ALOGE("%s malloc error for effect structure of size %zu",
704 __func__, totSize);
705 return NULL;
706 }
707
bryant_liuba2b4392014-06-11 16:49:30 +0800708 param = config_find(root, PARAM_TAG);
709 value = config_find(root, VALUE_TAG);
710 if (param == NULL && value == NULL) {
711 // try to parse simple parameter form {int int}
712 param = root->first_child;
713 if (param != NULL) {
714 // Note: that a pair of random strings is read as 0 0
715 int *ptr = (int *)fx_param->data;
Eric Laurent138ed172016-02-10 10:40:44 -0800716#if LOG_NDEBUG == 0
bryant_liuba2b4392014-06-11 16:49:30 +0800717 int *ptr2 = (int *)((char *)param + sizeof(effect_param_t));
Eric Laurent138ed172016-02-10 10:40:44 -0800718 ALOGV("loadEffectParameter() ptr %p ptr2 %p", ptr, ptr2);
719#endif
bryant_liuba2b4392014-06-11 16:49:30 +0800720 *ptr++ = atoi(param->name);
721 *ptr = atoi(param->value);
722 fx_param->psize = sizeof(int);
723 fx_param->vsize = sizeof(int);
724 return fx_param;
725 }
726 }
727 if (param == NULL || value == NULL) {
Eric Laurent138ed172016-02-10 10:40:44 -0800728 ALOGW("loadEffectParameter() invalid parameter description %s",
729 root->name);
bryant_liuba2b4392014-06-11 16:49:30 +0800730 goto error;
731 }
732
733 fx_param->psize = 0;
734 param = param->first_child;
735 while (param) {
736 ALOGV("loadEffectParameter() reading param of type %s", param->name);
Eric Laurent138ed172016-02-10 10:40:44 -0800737 size_t size =
738 readParamValue(param, (char **)&fx_param, &curSize, &totSize);
bryant_liuba2b4392014-06-11 16:49:30 +0800739 if (size == 0) {
740 goto error;
741 }
742 fx_param->psize += size;
743 param = param->next;
744 }
745
746 // align start of value field on 32 bit boundary
747 curSize = ((curSize - 1 ) / sizeof(int) + 1) * sizeof(int);
748
749 fx_param->vsize = 0;
750 value = value->first_child;
751 while (value) {
752 ALOGV("loadEffectParameter() reading value of type %s", value->name);
Eric Laurent138ed172016-02-10 10:40:44 -0800753 size_t size =
754 readParamValue(value, (char **)&fx_param, &curSize, &totSize);
bryant_liuba2b4392014-06-11 16:49:30 +0800755 if (size == 0) {
756 goto error;
757 }
758 fx_param->vsize += size;
759 value = value->next;
760 }
761
762 return fx_param;
763
764error:
Eric Laurent138ed172016-02-10 10:40:44 -0800765 free(fx_param);
bryant_liuba2b4392014-06-11 16:49:30 +0800766 return NULL;
767}
768
769void AudioPolicyEffects::loadEffectParameters(cnode *root, Vector <effect_param_t *>& params)
770{
771 cnode *node = root->first_child;
772 while (node) {
773 ALOGV("loadEffectParameters() loading param %s", node->name);
774 effect_param_t *param = loadEffectParameter(node);
Eric Laurent138ed172016-02-10 10:40:44 -0800775 if (param != NULL) {
776 params.add(param);
bryant_liuba2b4392014-06-11 16:49:30 +0800777 }
bryant_liuba2b4392014-06-11 16:49:30 +0800778 node = node->next;
779 }
780}
781
782
783AudioPolicyEffects::EffectDescVector *AudioPolicyEffects::loadEffectConfig(
784 cnode *root,
785 const Vector <EffectDesc *>& effects)
786{
787 cnode *node = root->first_child;
788 if (node == NULL) {
789 ALOGW("loadInputSource() empty element %s", root->name);
790 return NULL;
791 }
792 EffectDescVector *desc = new EffectDescVector();
793 while (node) {
794 size_t i;
Eric Laurent138ed172016-02-10 10:40:44 -0800795
bryant_liuba2b4392014-06-11 16:49:30 +0800796 for (i = 0; i < effects.size(); i++) {
797 if (strncmp(effects[i]->mName, node->name, EFFECT_STRING_LEN_MAX) == 0) {
798 ALOGV("loadEffectConfig() found effect %s in list", node->name);
799 break;
800 }
801 }
802 if (i == effects.size()) {
803 ALOGV("loadEffectConfig() effect %s not in list", node->name);
804 node = node->next;
805 continue;
806 }
807 EffectDesc *effect = new EffectDesc(*effects[i]); // deep copy
808 loadEffectParameters(node, effect->mParams);
809 ALOGV("loadEffectConfig() adding effect %s uuid %08x",
810 effect->mName, effect->mUuid.timeLow);
811 desc->mEffects.add(effect);
812 node = node->next;
813 }
814 if (desc->mEffects.size() == 0) {
815 ALOGW("loadEffectConfig() no valid effects found in config %s", root->name);
816 delete desc;
817 return NULL;
818 }
819 return desc;
820}
821
822status_t AudioPolicyEffects::loadInputEffectConfigurations(cnode *root,
823 const Vector <EffectDesc *>& effects)
824{
825 cnode *node = config_find(root, PREPROCESSING_TAG);
826 if (node == NULL) {
827 return -ENOENT;
828 }
829 node = node->first_child;
830 while (node) {
831 audio_source_t source = inputSourceNameToEnum(node->name);
832 if (source == AUDIO_SOURCE_CNT) {
833 ALOGW("loadInputSources() invalid input source %s", node->name);
834 node = node->next;
835 continue;
836 }
837 ALOGV("loadInputSources() loading input source %s", node->name);
838 EffectDescVector *desc = loadEffectConfig(node, effects);
839 if (desc == NULL) {
840 node = node->next;
841 continue;
842 }
843 mInputSources.add(source, desc);
844 node = node->next;
845 }
846 return NO_ERROR;
847}
848
849status_t AudioPolicyEffects::loadStreamEffectConfigurations(cnode *root,
850 const Vector <EffectDesc *>& effects)
851{
852 cnode *node = config_find(root, OUTPUT_SESSION_PROCESSING_TAG);
853 if (node == NULL) {
854 return -ENOENT;
855 }
856 node = node->first_child;
857 while (node) {
858 audio_stream_type_t stream = streamNameToEnum(node->name);
Eric Laurent223fd5c2014-11-11 13:43:36 -0800859 if (stream == AUDIO_STREAM_PUBLIC_CNT) {
bryant_liuba2b4392014-06-11 16:49:30 +0800860 ALOGW("loadStreamEffectConfigurations() invalid output stream %s", node->name);
861 node = node->next;
862 continue;
863 }
864 ALOGV("loadStreamEffectConfigurations() loading output stream %s", node->name);
865 EffectDescVector *desc = loadEffectConfig(node, effects);
866 if (desc == NULL) {
867 node = node->next;
868 continue;
869 }
870 mOutputStreams.add(stream, desc);
871 node = node->next;
872 }
873 return NO_ERROR;
874}
875
876AudioPolicyEffects::EffectDesc *AudioPolicyEffects::loadEffect(cnode *root)
877{
878 cnode *node = config_find(root, UUID_TAG);
879 if (node == NULL) {
880 return NULL;
881 }
882 effect_uuid_t uuid;
883 if (AudioEffect::stringToGuid(node->value, &uuid) != NO_ERROR) {
884 ALOGW("loadEffect() invalid uuid %s", node->value);
885 return NULL;
886 }
887 return new EffectDesc(root->name, uuid);
888}
889
890status_t AudioPolicyEffects::loadEffects(cnode *root, Vector <EffectDesc *>& effects)
891{
892 cnode *node = config_find(root, EFFECTS_TAG);
893 if (node == NULL) {
894 return -ENOENT;
895 }
896 node = node->first_child;
897 while (node) {
898 ALOGV("loadEffects() loading effect %s", node->name);
899 EffectDesc *effect = loadEffect(node);
900 if (effect == NULL) {
901 node = node->next;
902 continue;
903 }
904 effects.add(effect);
905 node = node->next;
906 }
907 return NO_ERROR;
908}
909
Kevin Rocard4fb615c2017-06-26 10:28:13 -0700910status_t AudioPolicyEffects::loadAudioEffectXmlConfig() {
911 auto result = effectsConfig::parse();
912 if (result.parsedConfig == nullptr) {
913 return -ENOENT;
914 }
915
916 auto loadProcessingChain = [](auto& processingChain, auto& streams) {
917 for (auto& stream : processingChain) {
918 auto effectDescs = std::make_unique<EffectDescVector>();
919 for (auto& effect : stream.effects) {
920 effectDescs->mEffects.add(
921 new EffectDesc{effect.get().name.c_str(), effect.get().uuid});
922 }
923 streams.add(stream.type, effectDescs.release());
924 }
925 };
François Gaffie06182982020-01-07 15:16:14 +0100926
927 auto loadDeviceProcessingChain = [](auto &processingChain, auto& devicesEffects) {
928 for (auto& deviceProcess : processingChain) {
929
930 auto effectDescs = std::make_unique<EffectDescVector>();
931 for (auto& effect : deviceProcess.effects) {
932 effectDescs->mEffects.add(
933 new EffectDesc{effect.get().name.c_str(), effect.get().uuid});
934 }
935 auto deviceEffects = std::make_unique<DeviceEffects>(
936 std::move(effectDescs), deviceProcess.type, deviceProcess.address);
937 devicesEffects.emplace(deviceProcess.address, std::move(deviceEffects));
938 }
939 };
940
Kevin Rocard4fb615c2017-06-26 10:28:13 -0700941 loadProcessingChain(result.parsedConfig->preprocess, mInputSources);
942 loadProcessingChain(result.parsedConfig->postprocess, mOutputStreams);
Mikhail Naganov12b716c2020-04-30 22:37:43 +0000943 {
944 Mutex::Autolock _l(mLock);
945 loadDeviceProcessingChain(result.parsedConfig->deviceprocess, mDeviceEffects);
946 }
Kevin Rocard4fb615c2017-06-26 10:28:13 -0700947 // Casting from ssize_t to status_t is probably safe, there should not be more than 2^31 errors
948 return result.nbSkippedElement;
949}
950
bryant_liuba2b4392014-06-11 16:49:30 +0800951status_t AudioPolicyEffects::loadAudioEffectConfig(const char *path)
952{
953 cnode *root;
954 char *data;
955
956 data = (char *)load_file(path, NULL);
957 if (data == NULL) {
958 return -ENODEV;
959 }
960 root = config_node("", "");
961 config_load(root, data);
962
963 Vector <EffectDesc *> effects;
964 loadEffects(root, effects);
965 loadInputEffectConfigurations(root, effects);
966 loadStreamEffectConfigurations(root, effects);
967
Eric Laurent182c2f52015-01-15 14:29:19 -0800968 for (size_t i = 0; i < effects.size(); i++) {
969 delete effects[i];
970 }
971
bryant_liuba2b4392014-06-11 16:49:30 +0800972 config_free(root);
973 free(root);
974 free(data);
975
976 return NO_ERROR;
977}
978
François Gaffie06182982020-01-07 15:16:14 +0100979void AudioPolicyEffects::initDefaultDeviceEffects()
980{
981 Mutex::Autolock _l(mLock);
982 for (const auto& deviceEffectsIter : mDeviceEffects) {
983 const auto& deviceEffects = deviceEffectsIter.second;
984 for (const auto& effectDesc : deviceEffects->mEffectDescriptors->mEffects) {
Svet Ganov3e5f14f2021-05-13 22:51:08 +0000985 AttributionSourceState attributionSource;
986 attributionSource.packageName = "android";
987 attributionSource.token = sp<BBinder>::make();
988 sp<AudioEffect> fx = new AudioEffect(attributionSource);
Atneya Nair884f7992022-05-17 19:22:42 -0400989 fx->set(EFFECT_UUID_NULL, &effectDesc->mUuid, 0 /* priority */, nullptr /* callback */,
990 AUDIO_SESSION_DEVICE, AUDIO_IO_HANDLE_NONE,
Mikhail Naganov69d41cc2020-07-31 17:36:08 -0700991 AudioDeviceTypeAddr{deviceEffects->getDeviceType(),
992 deviceEffects->getDeviceAddress()});
François Gaffie06182982020-01-07 15:16:14 +0100993 status_t status = fx->initCheck();
994 if (status != NO_ERROR && status != ALREADY_EXISTS) {
995 ALOGE("%s(): failed to create Fx %s on port type=%d address=%s", __func__,
996 effectDesc->mName, deviceEffects->getDeviceType(),
997 deviceEffects->getDeviceAddress().c_str());
998 // fx goes out of scope and strong ref on AudioEffect is released
999 continue;
1000 }
1001 fx->setEnabled(true);
1002 ALOGV("%s(): create Fx %s added on port type=%d address=%s", __func__,
1003 effectDesc->mName, deviceEffects->getDeviceType(),
1004 deviceEffects->getDeviceAddress().c_str());
Jintao Zhu230397e2021-03-07 14:15:10 +08001005 deviceEffects->mEffects.push_back(fx);
François Gaffie06182982020-01-07 15:16:14 +01001006 }
1007 }
1008}
bryant_liuba2b4392014-06-11 16:49:30 +08001009
Mikhail Naganov1b2a7942017-12-08 10:18:09 -08001010} // namespace android