blob: 42f789987927525f436df2833c6411c138710906 [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
Shunkai Yao8d6489a2023-04-18 23:14:25 +000044AudioPolicyEffects::AudioPolicyEffects(const sp<EffectsFactoryHalInterface>& effectsFactoryHal) {
45 // load xml config with effectsFactoryHal
46 status_t loadResult = loadAudioEffectConfig(effectsFactoryHal);
François Gaffie163ce832023-06-28 11:36:35 +020047 if (loadResult < 0) {
Shunkai Yaoeab8a7c2023-05-15 21:07:08 +000048 ALOGW("Failed to query effect configuration, fallback to load .conf");
49 // load automatic audio effect modules
50 if (access(AUDIO_EFFECT_VENDOR_CONFIG_FILE, R_OK) == 0) {
51 loadAudioEffectConfigLegacy(AUDIO_EFFECT_VENDOR_CONFIG_FILE);
52 } else if (access(AUDIO_EFFECT_DEFAULT_CONFIG_FILE, R_OK) == 0) {
53 loadAudioEffectConfigLegacy(AUDIO_EFFECT_DEFAULT_CONFIG_FILE);
54 }
Kevin Rocard4fb615c2017-06-26 10:28:13 -070055 } else if (loadResult > 0) {
56 ALOGE("Effect config is partially invalid, skipped %d elements", loadResult);
bryant_liuba2b4392014-06-11 16:49:30 +080057 }
58}
59
François Gaffie163ce832023-06-28 11:36:35 +020060void AudioPolicyEffects::setDefaultDeviceEffects() {
61 mDefaultDeviceEffectFuture = std::async(
62 std::launch::async, &AudioPolicyEffects::initDefaultDeviceEffects, this);
63}
64
bryant_liuba2b4392014-06-11 16:49:30 +080065AudioPolicyEffects::~AudioPolicyEffects()
66{
67 size_t i = 0;
68 // release audio input processing resources
69 for (i = 0; i < mInputSources.size(); i++) {
70 delete mInputSources.valueAt(i);
71 }
72 mInputSources.clear();
73
Eric Laurentfb66dd92016-01-28 18:32:03 -080074 for (i = 0; i < mInputSessions.size(); i++) {
75 mInputSessions.valueAt(i)->mEffects.clear();
76 delete mInputSessions.valueAt(i);
bryant_liuba2b4392014-06-11 16:49:30 +080077 }
Eric Laurentfb66dd92016-01-28 18:32:03 -080078 mInputSessions.clear();
bryant_liuba2b4392014-06-11 16:49:30 +080079
80 // release audio output processing resources
81 for (i = 0; i < mOutputStreams.size(); i++) {
82 delete mOutputStreams.valueAt(i);
83 }
84 mOutputStreams.clear();
85
86 for (i = 0; i < mOutputSessions.size(); i++) {
87 mOutputSessions.valueAt(i)->mEffects.clear();
88 delete mOutputSessions.valueAt(i);
89 }
90 mOutputSessions.clear();
91}
92
93
94status_t AudioPolicyEffects::addInputEffects(audio_io_handle_t input,
95 audio_source_t inputSource,
Eric Laurentfb66dd92016-01-28 18:32:03 -080096 audio_session_t audioSession)
bryant_liuba2b4392014-06-11 16:49:30 +080097{
98 status_t status = NO_ERROR;
99
100 // create audio pre processors according to input source
101 audio_source_t aliasSource = (inputSource == AUDIO_SOURCE_HOTWORD) ?
102 AUDIO_SOURCE_VOICE_RECOGNITION : inputSource;
103
Andy Hung79eacdb2023-11-30 19:34:24 -0800104 audio_utils::lock_guard _l(mMutex);
bryant_liuba2b4392014-06-11 16:49:30 +0800105 ssize_t index = mInputSources.indexOfKey(aliasSource);
106 if (index < 0) {
107 ALOGV("addInputEffects(): no processing needs to be attached to this source");
108 return status;
109 }
Eric Laurentfb66dd92016-01-28 18:32:03 -0800110 ssize_t idx = mInputSessions.indexOfKey(audioSession);
111 EffectVector *sessionDesc;
bryant_liuba2b4392014-06-11 16:49:30 +0800112 if (idx < 0) {
Eric Laurentfb66dd92016-01-28 18:32:03 -0800113 sessionDesc = new EffectVector(audioSession);
114 mInputSessions.add(audioSession, sessionDesc);
bryant_liuba2b4392014-06-11 16:49:30 +0800115 } else {
bryant_liu890a5632014-08-20 18:06:13 +0800116 // EffectVector is existing and we just need to increase ref count
Eric Laurentfb66dd92016-01-28 18:32:03 -0800117 sessionDesc = mInputSessions.valueAt(idx);
bryant_liuba2b4392014-06-11 16:49:30 +0800118 }
Eric Laurentfb66dd92016-01-28 18:32:03 -0800119 sessionDesc->mRefCount++;
bryant_liu890a5632014-08-20 18:06:13 +0800120
Eric Laurentfb66dd92016-01-28 18:32:03 -0800121 ALOGV("addInputEffects(): input: %d, refCount: %d", input, sessionDesc->mRefCount);
122 if (sessionDesc->mRefCount == 1) {
Eric Laurentb6436272016-12-07 19:24:50 -0800123 int64_t token = IPCThreadState::self()->clearCallingIdentity();
Eric Laurent7de5ac12014-10-21 09:07:11 -0700124 Vector <EffectDesc *> effects = mInputSources.valueAt(index)->mEffects;
125 for (size_t i = 0; i < effects.size(); i++) {
126 EffectDesc *effect = effects[i];
Svet Ganov3e5f14f2021-05-13 22:51:08 +0000127 AttributionSourceState attributionSource;
128 attributionSource.packageName = "android";
129 attributionSource.token = sp<BBinder>::make();
130 sp<AudioEffect> fx = new AudioEffect(attributionSource);
Atneya Nair884f7992022-05-17 19:22:42 -0400131 fx->set(nullptr /*type */, &effect->mUuid, -1 /* priority */, nullptr /* callback */,
132 audioSession, input);
Eric Laurent7de5ac12014-10-21 09:07:11 -0700133 status_t status = fx->initCheck();
134 if (status != NO_ERROR && status != ALREADY_EXISTS) {
135 ALOGW("addInputEffects(): failed to create Fx %s on source %d",
136 effect->mName, (int32_t)aliasSource);
137 // fx goes out of scope and strong ref on AudioEffect is released
138 continue;
139 }
140 for (size_t j = 0; j < effect->mParams.size(); j++) {
141 fx->setParameter(effect->mParams[j]);
142 }
143 ALOGV("addInputEffects(): added Fx %s on source: %d",
bryant_liuba2b4392014-06-11 16:49:30 +0800144 effect->mName, (int32_t)aliasSource);
Eric Laurentfb66dd92016-01-28 18:32:03 -0800145 sessionDesc->mEffects.add(fx);
bryant_liuba2b4392014-06-11 16:49:30 +0800146 }
Eric Laurentfb66dd92016-01-28 18:32:03 -0800147 sessionDesc->setProcessorEnabled(true);
Eric Laurentb6436272016-12-07 19:24:50 -0800148 IPCThreadState::self()->restoreCallingIdentity(token);
bryant_liuba2b4392014-06-11 16:49:30 +0800149 }
bryant_liuba2b4392014-06-11 16:49:30 +0800150 return status;
151}
152
153
Eric Laurentfb66dd92016-01-28 18:32:03 -0800154status_t AudioPolicyEffects::releaseInputEffects(audio_io_handle_t input,
155 audio_session_t audioSession)
bryant_liuba2b4392014-06-11 16:49:30 +0800156{
157 status_t status = NO_ERROR;
158
Andy Hung79eacdb2023-11-30 19:34:24 -0800159 audio_utils::lock_guard _l(mMutex);
Eric Laurentfb66dd92016-01-28 18:32:03 -0800160 ssize_t index = mInputSessions.indexOfKey(audioSession);
bryant_liuba2b4392014-06-11 16:49:30 +0800161 if (index < 0) {
162 return status;
163 }
Eric Laurentfb66dd92016-01-28 18:32:03 -0800164 EffectVector *sessionDesc = mInputSessions.valueAt(index);
165 sessionDesc->mRefCount--;
166 ALOGV("releaseInputEffects(): input: %d, refCount: %d", input, sessionDesc->mRefCount);
167 if (sessionDesc->mRefCount == 0) {
168 sessionDesc->setProcessorEnabled(false);
169 delete sessionDesc;
170 mInputSessions.removeItemsAt(index);
bryant_liu890a5632014-08-20 18:06:13 +0800171 ALOGV("releaseInputEffects(): all effects released");
172 }
bryant_liuba2b4392014-06-11 16:49:30 +0800173 return status;
174}
175
Eric Laurentfb66dd92016-01-28 18:32:03 -0800176status_t AudioPolicyEffects::queryDefaultInputEffects(audio_session_t audioSession,
bryant_liuba2b4392014-06-11 16:49:30 +0800177 effect_descriptor_t *descriptors,
178 uint32_t *count)
179{
180 status_t status = NO_ERROR;
181
Andy Hung79eacdb2023-11-30 19:34:24 -0800182 audio_utils::lock_guard _l(mMutex);
bryant_liuba2b4392014-06-11 16:49:30 +0800183 size_t index;
Eric Laurentfb66dd92016-01-28 18:32:03 -0800184 for (index = 0; index < mInputSessions.size(); index++) {
185 if (mInputSessions.valueAt(index)->mSessionId == audioSession) {
bryant_liuba2b4392014-06-11 16:49:30 +0800186 break;
187 }
188 }
Eric Laurentfb66dd92016-01-28 18:32:03 -0800189 if (index == mInputSessions.size()) {
bryant_liuba2b4392014-06-11 16:49:30 +0800190 *count = 0;
191 return BAD_VALUE;
192 }
Eric Laurentfb66dd92016-01-28 18:32:03 -0800193 Vector< sp<AudioEffect> > effects = mInputSessions.valueAt(index)->mEffects;
bryant_liuba2b4392014-06-11 16:49:30 +0800194
195 for (size_t i = 0; i < effects.size(); i++) {
196 effect_descriptor_t desc = effects[i]->descriptor();
197 if (i < *count) {
198 descriptors[i] = desc;
199 }
200 }
201 if (effects.size() > *count) {
202 status = NO_MEMORY;
203 }
204 *count = effects.size();
205 return status;
206}
207
208
Eric Laurentfb66dd92016-01-28 18:32:03 -0800209status_t AudioPolicyEffects::queryDefaultOutputSessionEffects(audio_session_t audioSession,
bryant_liuba2b4392014-06-11 16:49:30 +0800210 effect_descriptor_t *descriptors,
211 uint32_t *count)
212{
213 status_t status = NO_ERROR;
214
Andy Hung79eacdb2023-11-30 19:34:24 -0800215 audio_utils::lock_guard _l(mMutex);
bryant_liuba2b4392014-06-11 16:49:30 +0800216 size_t index;
217 for (index = 0; index < mOutputSessions.size(); index++) {
218 if (mOutputSessions.valueAt(index)->mSessionId == audioSession) {
219 break;
220 }
221 }
222 if (index == mOutputSessions.size()) {
223 *count = 0;
224 return BAD_VALUE;
225 }
226 Vector< sp<AudioEffect> > effects = mOutputSessions.valueAt(index)->mEffects;
227
228 for (size_t i = 0; i < effects.size(); i++) {
229 effect_descriptor_t desc = effects[i]->descriptor();
230 if (i < *count) {
231 descriptors[i] = desc;
232 }
233 }
234 if (effects.size() > *count) {
235 status = NO_MEMORY;
236 }
237 *count = effects.size();
238 return status;
239}
240
241
242status_t AudioPolicyEffects::addOutputSessionEffects(audio_io_handle_t output,
243 audio_stream_type_t stream,
Eric Laurentfb66dd92016-01-28 18:32:03 -0800244 audio_session_t audioSession)
bryant_liuba2b4392014-06-11 16:49:30 +0800245{
246 status_t status = NO_ERROR;
247
Andy Hung79eacdb2023-11-30 19:34:24 -0800248 audio_utils::lock_guard _l(mMutex);
bryant_liuba2b4392014-06-11 16:49:30 +0800249 // create audio processors according to stream
Eric Laurent223fd5c2014-11-11 13:43:36 -0800250 // FIXME: should we have specific post processing settings for internal streams?
251 // default to media for now.
252 if (stream >= AUDIO_STREAM_PUBLIC_CNT) {
253 stream = AUDIO_STREAM_MUSIC;
254 }
bryant_liuba2b4392014-06-11 16:49:30 +0800255 ssize_t index = mOutputStreams.indexOfKey(stream);
256 if (index < 0) {
257 ALOGV("addOutputSessionEffects(): no output processing needed for this stream");
258 return NO_ERROR;
259 }
260
261 ssize_t idx = mOutputSessions.indexOfKey(audioSession);
262 EffectVector *procDesc;
263 if (idx < 0) {
264 procDesc = new EffectVector(audioSession);
265 mOutputSessions.add(audioSession, procDesc);
266 } else {
bryant_liu890a5632014-08-20 18:06:13 +0800267 // EffectVector is existing and we just need to increase ref count
bryant_liuba2b4392014-06-11 16:49:30 +0800268 procDesc = mOutputSessions.valueAt(idx);
269 }
bryant_liu890a5632014-08-20 18:06:13 +0800270 procDesc->mRefCount++;
271
Eric Laurent7de5ac12014-10-21 09:07:11 -0700272 ALOGV("addOutputSessionEffects(): session: %d, refCount: %d",
273 audioSession, procDesc->mRefCount);
274 if (procDesc->mRefCount == 1) {
Eric Laurentb6436272016-12-07 19:24:50 -0800275 // make sure effects are associated to audio server even if we are executing a binder call
276 int64_t token = IPCThreadState::self()->clearCallingIdentity();
Eric Laurent7de5ac12014-10-21 09:07:11 -0700277 Vector <EffectDesc *> effects = mOutputStreams.valueAt(index)->mEffects;
278 for (size_t i = 0; i < effects.size(); i++) {
279 EffectDesc *effect = effects[i];
Svet Ganov3e5f14f2021-05-13 22:51:08 +0000280 AttributionSourceState attributionSource;
281 attributionSource.packageName = "android";
282 attributionSource.token = sp<BBinder>::make();
283 sp<AudioEffect> fx = new AudioEffect(attributionSource);
Atneya Nair884f7992022-05-17 19:22:42 -0400284 fx->set(nullptr /* type */, &effect->mUuid, 0 /* priority */, nullptr /* callback */,
285 audioSession, output);
Eric Laurent7de5ac12014-10-21 09:07:11 -0700286 status_t status = fx->initCheck();
287 if (status != NO_ERROR && status != ALREADY_EXISTS) {
288 ALOGE("addOutputSessionEffects(): failed to create Fx %s on session %d",
289 effect->mName, audioSession);
290 // fx goes out of scope and strong ref on AudioEffect is released
291 continue;
292 }
293 ALOGV("addOutputSessionEffects(): added Fx %s on session: %d for stream: %d",
294 effect->mName, audioSession, (int32_t)stream);
295 procDesc->mEffects.add(fx);
bryant_liuba2b4392014-06-11 16:49:30 +0800296 }
Eric Laurent7de5ac12014-10-21 09:07:11 -0700297
298 procDesc->setProcessorEnabled(true);
Eric Laurentb6436272016-12-07 19:24:50 -0800299 IPCThreadState::self()->restoreCallingIdentity(token);
bryant_liuba2b4392014-06-11 16:49:30 +0800300 }
bryant_liuba2b4392014-06-11 16:49:30 +0800301 return status;
302}
303
304status_t AudioPolicyEffects::releaseOutputSessionEffects(audio_io_handle_t output,
305 audio_stream_type_t stream,
Eric Laurentfb66dd92016-01-28 18:32:03 -0800306 audio_session_t audioSession)
bryant_liuba2b4392014-06-11 16:49:30 +0800307{
308 status_t status = NO_ERROR;
309 (void) output; // argument not used for now
310 (void) stream; // argument not used for now
311
Andy Hung79eacdb2023-11-30 19:34:24 -0800312 audio_utils::lock_guard _l(mMutex);
bryant_liuba2b4392014-06-11 16:49:30 +0800313 ssize_t index = mOutputSessions.indexOfKey(audioSession);
314 if (index < 0) {
315 ALOGV("releaseOutputSessionEffects: no output processing was attached to this stream");
316 return NO_ERROR;
317 }
318
319 EffectVector *procDesc = mOutputSessions.valueAt(index);
bryant_liu890a5632014-08-20 18:06:13 +0800320 procDesc->mRefCount--;
Eric Laurent7de5ac12014-10-21 09:07:11 -0700321 ALOGV("releaseOutputSessionEffects(): session: %d, refCount: %d",
322 audioSession, procDesc->mRefCount);
bryant_liu890a5632014-08-20 18:06:13 +0800323 if (procDesc->mRefCount == 0) {
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700324 procDesc->setProcessorEnabled(false);
bryant_liu890a5632014-08-20 18:06:13 +0800325 procDesc->mEffects.clear();
326 delete procDesc;
327 mOutputSessions.removeItemsAt(index);
328 ALOGV("releaseOutputSessionEffects(): output processing released from session: %d",
329 audioSession);
330 }
bryant_liuba2b4392014-06-11 16:49:30 +0800331 return status;
332}
333
Ari Hausman-Cohen24628312018-08-13 15:01:09 -0700334status_t AudioPolicyEffects::addSourceDefaultEffect(const effect_uuid_t *type,
335 const String16& opPackageName,
336 const effect_uuid_t *uuid,
337 int32_t priority,
338 audio_source_t source,
339 audio_unique_id_t* id)
340{
341 if (uuid == NULL || type == NULL) {
342 ALOGE("addSourceDefaultEffect(): Null uuid or type uuid pointer");
343 return BAD_VALUE;
344 }
345
Eric Laurentae4b6ec2019-01-15 18:34:38 -0800346 // HOTWORD, FM_TUNER and ECHO_REFERENCE are special case sources > MAX.
Ari Hausman-Cohen24628312018-08-13 15:01:09 -0700347 if (source < AUDIO_SOURCE_DEFAULT ||
348 (source > AUDIO_SOURCE_MAX &&
349 source != AUDIO_SOURCE_HOTWORD &&
Eric Laurentae4b6ec2019-01-15 18:34:38 -0800350 source != AUDIO_SOURCE_FM_TUNER &&
Carter Hsua3abb402021-10-26 11:11:20 +0800351 source != AUDIO_SOURCE_ECHO_REFERENCE &&
352 source != AUDIO_SOURCE_ULTRASOUND)) {
Ari Hausman-Cohen24628312018-08-13 15:01:09 -0700353 ALOGE("addSourceDefaultEffect(): Unsupported source type %d", source);
354 return BAD_VALUE;
355 }
356
357 // Check that |uuid| or |type| corresponds to an effect on the system.
358 effect_descriptor_t descriptor = {};
359 status_t res = AudioEffect::getEffectDescriptor(
360 uuid, type, EFFECT_FLAG_TYPE_PRE_PROC, &descriptor);
361 if (res != OK) {
362 ALOGE("addSourceDefaultEffect(): Failed to find effect descriptor matching uuid/type.");
363 return res;
364 }
365
366 // Only pre-processing effects can be added dynamically as source defaults.
367 if ((descriptor.flags & EFFECT_FLAG_TYPE_MASK) != EFFECT_FLAG_TYPE_PRE_PROC) {
368 ALOGE("addSourceDefaultEffect(): Desired effect cannot be attached "
369 "as a source default effect.");
370 return BAD_VALUE;
371 }
372
Andy Hung79eacdb2023-11-30 19:34:24 -0800373 audio_utils::lock_guard _l(mMutex);
Ari Hausman-Cohen24628312018-08-13 15:01:09 -0700374
375 // Find the EffectDescVector for the given source type, or create a new one if necessary.
376 ssize_t index = mInputSources.indexOfKey(source);
377 EffectDescVector *desc = NULL;
378 if (index < 0) {
379 // No effects for this source type yet.
380 desc = new EffectDescVector();
381 mInputSources.add(source, desc);
382 } else {
383 desc = mInputSources.valueAt(index);
384 }
385
386 // Create a new effect and add it to the vector.
387 res = AudioEffect::newEffectUniqueId(id);
388 if (res != OK) {
389 ALOGE("addSourceDefaultEffect(): failed to get new unique id.");
390 return res;
391 }
392 EffectDesc *effect = new EffectDesc(
Eric Laurent2685aa02022-02-01 14:26:38 +0100393 descriptor.name, descriptor.type, opPackageName, descriptor.uuid, priority, *id);
Ari Hausman-Cohen24628312018-08-13 15:01:09 -0700394 desc->mEffects.add(effect);
395 // TODO(b/71813697): Support setting params as well.
396
397 // TODO(b/71814300): Retroactively attach to any existing sources of the given type.
398 // This requires tracking the source type of each session id in addition to what is
399 // already being tracked.
400
401 return NO_ERROR;
402}
403
Ari Hausman-Cohen433722e2018-04-24 14:25:22 -0700404status_t AudioPolicyEffects::addStreamDefaultEffect(const effect_uuid_t *type,
405 const String16& opPackageName,
406 const effect_uuid_t *uuid,
407 int32_t priority,
408 audio_usage_t usage,
409 audio_unique_id_t* id)
410{
411 if (uuid == NULL || type == NULL) {
412 ALOGE("addStreamDefaultEffect(): Null uuid or type uuid pointer");
413 return BAD_VALUE;
414 }
François Gaffie58d4be52018-11-06 15:30:12 +0100415 audio_stream_type_t stream = AudioSystem::attributesToStreamType(attributes_initializer(usage));
Ari Hausman-Cohen433722e2018-04-24 14:25:22 -0700416
417 if (stream < AUDIO_STREAM_MIN || stream >= AUDIO_STREAM_PUBLIC_CNT) {
418 ALOGE("addStreamDefaultEffect(): Unsupported stream type %d", stream);
419 return BAD_VALUE;
420 }
421
422 // Check that |uuid| or |type| corresponds to an effect on the system.
423 effect_descriptor_t descriptor = {};
424 status_t res = AudioEffect::getEffectDescriptor(
425 uuid, type, EFFECT_FLAG_TYPE_INSERT, &descriptor);
426 if (res != OK) {
427 ALOGE("addStreamDefaultEffect(): Failed to find effect descriptor matching uuid/type.");
428 return res;
429 }
430
431 // Only insert effects can be added dynamically as stream defaults.
432 if ((descriptor.flags & EFFECT_FLAG_TYPE_MASK) != EFFECT_FLAG_TYPE_INSERT) {
433 ALOGE("addStreamDefaultEffect(): Desired effect cannot be attached "
434 "as a stream default effect.");
435 return BAD_VALUE;
436 }
437
Andy Hung79eacdb2023-11-30 19:34:24 -0800438 audio_utils::lock_guard _l(mMutex);
Ari Hausman-Cohen433722e2018-04-24 14:25:22 -0700439
440 // Find the EffectDescVector for the given stream type, or create a new one if necessary.
441 ssize_t index = mOutputStreams.indexOfKey(stream);
442 EffectDescVector *desc = NULL;
443 if (index < 0) {
444 // No effects for this stream type yet.
445 desc = new EffectDescVector();
446 mOutputStreams.add(stream, desc);
447 } else {
448 desc = mOutputStreams.valueAt(index);
449 }
450
451 // Create a new effect and add it to the vector.
452 res = AudioEffect::newEffectUniqueId(id);
453 if (res != OK) {
454 ALOGE("addStreamDefaultEffect(): failed to get new unique id.");
455 return res;
456 }
457 EffectDesc *effect = new EffectDesc(
Eric Laurent2685aa02022-02-01 14:26:38 +0100458 descriptor.name, descriptor.type, opPackageName, descriptor.uuid, priority, *id);
Ari Hausman-Cohen433722e2018-04-24 14:25:22 -0700459 desc->mEffects.add(effect);
460 // TODO(b/71813697): Support setting params as well.
461
462 // TODO(b/71814300): Retroactively attach to any existing streams of the given type.
463 // This requires tracking the stream type of each session id in addition to what is
464 // already being tracked.
465
466 return NO_ERROR;
467}
468
Ari Hausman-Cohen24628312018-08-13 15:01:09 -0700469status_t AudioPolicyEffects::removeSourceDefaultEffect(audio_unique_id_t id)
470{
471 if (id == AUDIO_UNIQUE_ID_ALLOCATE) {
472 // ALLOCATE is not a unique identifier, but rather a reserved value indicating
473 // a real id has not been assigned. For default effects, this value is only used
474 // by system-owned defaults from the loaded config, which cannot be removed.
475 return BAD_VALUE;
476 }
477
Andy Hung79eacdb2023-11-30 19:34:24 -0800478 audio_utils::lock_guard _l(mMutex);
Ari Hausman-Cohen24628312018-08-13 15:01:09 -0700479
480 // Check each source type.
481 size_t numSources = mInputSources.size();
482 for (size_t i = 0; i < numSources; ++i) {
483 // Check each effect for each source.
484 EffectDescVector* descVector = mInputSources[i];
485 for (auto desc = descVector->mEffects.begin(); desc != descVector->mEffects.end(); ++desc) {
486 if ((*desc)->mId == id) {
487 // Found it!
488 // TODO(b/71814300): Remove from any sources the effect was attached to.
489 descVector->mEffects.erase(desc);
490 // Handles are unique; there can only be one match, so return early.
491 return NO_ERROR;
492 }
493 }
494 }
495
496 // Effect wasn't found, so it's been trivially removed successfully.
497 return NO_ERROR;
498}
499
Ari Hausman-Cohen433722e2018-04-24 14:25:22 -0700500status_t AudioPolicyEffects::removeStreamDefaultEffect(audio_unique_id_t id)
501{
502 if (id == AUDIO_UNIQUE_ID_ALLOCATE) {
503 // ALLOCATE is not a unique identifier, but rather a reserved value indicating
504 // a real id has not been assigned. For default effects, this value is only used
505 // by system-owned defaults from the loaded config, which cannot be removed.
506 return BAD_VALUE;
507 }
508
Andy Hung79eacdb2023-11-30 19:34:24 -0800509 audio_utils::lock_guard _l(mMutex);
Ari Hausman-Cohen433722e2018-04-24 14:25:22 -0700510
511 // Check each stream type.
512 size_t numStreams = mOutputStreams.size();
513 for (size_t i = 0; i < numStreams; ++i) {
514 // Check each effect for each stream.
515 EffectDescVector* descVector = mOutputStreams[i];
516 for (auto desc = descVector->mEffects.begin(); desc != descVector->mEffects.end(); ++desc) {
517 if ((*desc)->mId == id) {
518 // Found it!
519 // TODO(b/71814300): Remove from any streams the effect was attached to.
520 descVector->mEffects.erase(desc);
521 // Handles are unique; there can only be one match, so return early.
522 return NO_ERROR;
523 }
524 }
525 }
526
527 // Effect wasn't found, so it's been trivially removed successfully.
528 return NO_ERROR;
529}
bryant_liuba2b4392014-06-11 16:49:30 +0800530
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700531void AudioPolicyEffects::EffectVector::setProcessorEnabled(bool enabled)
bryant_liuba2b4392014-06-11 16:49:30 +0800532{
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700533 for (size_t i = 0; i < mEffects.size(); i++) {
534 mEffects.itemAt(i)->setEnabled(enabled);
bryant_liuba2b4392014-06-11 16:49:30 +0800535 }
536}
537
538
539// ----------------------------------------------------------------------------
540// Audio processing configuration
541// ----------------------------------------------------------------------------
542
543/*static*/ const char * const AudioPolicyEffects::kInputSourceNames[AUDIO_SOURCE_CNT -1] = {
544 MIC_SRC_TAG,
545 VOICE_UL_SRC_TAG,
546 VOICE_DL_SRC_TAG,
547 VOICE_CALL_SRC_TAG,
548 CAMCORDER_SRC_TAG,
549 VOICE_REC_SRC_TAG,
rago8a397d52015-12-02 11:27:57 -0800550 VOICE_COMM_SRC_TAG,
Carter Hsua3abb402021-10-26 11:11:20 +0800551 REMOTE_SUBMIX_SRC_TAG,
Eric Laurentae4b6ec2019-01-15 18:34:38 -0800552 UNPROCESSED_SRC_TAG,
553 VOICE_PERFORMANCE_SRC_TAG
bryant_liuba2b4392014-06-11 16:49:30 +0800554};
555
556// returns the audio_source_t enum corresponding to the input source name or
557// AUDIO_SOURCE_CNT is no match found
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700558/*static*/ audio_source_t AudioPolicyEffects::inputSourceNameToEnum(const char *name)
bryant_liuba2b4392014-06-11 16:49:30 +0800559{
560 int i;
561 for (i = AUDIO_SOURCE_MIC; i < AUDIO_SOURCE_CNT; i++) {
562 if (strcmp(name, kInputSourceNames[i - AUDIO_SOURCE_MIC]) == 0) {
563 ALOGV("inputSourceNameToEnum found source %s %d", name, i);
564 break;
565 }
566 }
567 return (audio_source_t)i;
568}
569
Eric Laurent223fd5c2014-11-11 13:43:36 -0800570const char *AudioPolicyEffects::kStreamNames[AUDIO_STREAM_PUBLIC_CNT+1] = {
bryant_liuba2b4392014-06-11 16:49:30 +0800571 AUDIO_STREAM_DEFAULT_TAG,
572 AUDIO_STREAM_VOICE_CALL_TAG,
573 AUDIO_STREAM_SYSTEM_TAG,
574 AUDIO_STREAM_RING_TAG,
575 AUDIO_STREAM_MUSIC_TAG,
576 AUDIO_STREAM_ALARM_TAG,
577 AUDIO_STREAM_NOTIFICATION_TAG,
578 AUDIO_STREAM_BLUETOOTH_SCO_TAG,
579 AUDIO_STREAM_ENFORCED_AUDIBLE_TAG,
580 AUDIO_STREAM_DTMF_TAG,
Baekgyeong Kim3a26bb22019-10-30 20:29:41 +0900581 AUDIO_STREAM_TTS_TAG,
582 AUDIO_STREAM_ASSISTANT_TAG
bryant_liuba2b4392014-06-11 16:49:30 +0800583};
584
585// returns the audio_stream_t enum corresponding to the output stream name or
Eric Laurent223fd5c2014-11-11 13:43:36 -0800586// AUDIO_STREAM_PUBLIC_CNT is no match found
bryant_liuba2b4392014-06-11 16:49:30 +0800587audio_stream_type_t AudioPolicyEffects::streamNameToEnum(const char *name)
588{
589 int i;
Eric Laurent223fd5c2014-11-11 13:43:36 -0800590 for (i = AUDIO_STREAM_DEFAULT; i < AUDIO_STREAM_PUBLIC_CNT; i++) {
bryant_liuba2b4392014-06-11 16:49:30 +0800591 if (strcmp(name, kStreamNames[i - AUDIO_STREAM_DEFAULT]) == 0) {
592 ALOGV("streamNameToEnum found stream %s %d", name, i);
593 break;
594 }
595 }
596 return (audio_stream_type_t)i;
597}
598
599// ----------------------------------------------------------------------------
600// Audio Effect Config parser
601// ----------------------------------------------------------------------------
602
Eric Laurent138ed172016-02-10 10:40:44 -0800603size_t AudioPolicyEffects::growParamSize(char **param,
bryant_liuba2b4392014-06-11 16:49:30 +0800604 size_t size,
605 size_t *curSize,
606 size_t *totSize)
607{
608 // *curSize is at least sizeof(effect_param_t) + 2 * sizeof(int)
609 size_t pos = ((*curSize - 1 ) / size + 1) * size;
610
611 if (pos + size > *totSize) {
612 while (pos + size > *totSize) {
613 *totSize += ((*totSize + 7) / 8) * 4;
614 }
George Burgess IV31225682018-02-12 11:08:38 -0800615 char *newParam = (char *)realloc(*param, *totSize);
616 if (newParam == NULL) {
Eric Laurent138ed172016-02-10 10:40:44 -0800617 ALOGE("%s realloc error for size %zu", __func__, *totSize);
618 return 0;
619 }
George Burgess IV31225682018-02-12 11:08:38 -0800620 *param = newParam;
bryant_liuba2b4392014-06-11 16:49:30 +0800621 }
622 *curSize = pos + size;
623 return pos;
624}
625
Eric Laurent138ed172016-02-10 10:40:44 -0800626
bryant_liuba2b4392014-06-11 16:49:30 +0800627size_t AudioPolicyEffects::readParamValue(cnode *node,
Eric Laurent138ed172016-02-10 10:40:44 -0800628 char **param,
bryant_liuba2b4392014-06-11 16:49:30 +0800629 size_t *curSize,
630 size_t *totSize)
631{
Eric Laurent138ed172016-02-10 10:40:44 -0800632 size_t len = 0;
633 size_t pos;
634
bryant_liuba2b4392014-06-11 16:49:30 +0800635 if (strncmp(node->name, SHORT_TAG, sizeof(SHORT_TAG) + 1) == 0) {
Eric Laurent138ed172016-02-10 10:40:44 -0800636 pos = growParamSize(param, sizeof(short), curSize, totSize);
637 if (pos == 0) {
638 goto exit;
bryant_liuba2b4392014-06-11 16:49:30 +0800639 }
Eric Laurent138ed172016-02-10 10:40:44 -0800640 *(short *)(*param + pos) = (short)atoi(node->value);
641 ALOGV("readParamValue() reading short %d", *(short *)(*param + pos));
642 len = sizeof(short);
643 } else if (strncmp(node->name, INT_TAG, sizeof(INT_TAG) + 1) == 0) {
644 pos = growParamSize(param, sizeof(int), curSize, totSize);
645 if (pos == 0) {
646 goto exit;
647 }
648 *(int *)(*param + pos) = atoi(node->value);
649 ALOGV("readParamValue() reading int %d", *(int *)(*param + pos));
650 len = sizeof(int);
651 } else if (strncmp(node->name, FLOAT_TAG, sizeof(FLOAT_TAG) + 1) == 0) {
652 pos = growParamSize(param, sizeof(float), curSize, totSize);
653 if (pos == 0) {
654 goto exit;
655 }
656 *(float *)(*param + pos) = (float)atof(node->value);
657 ALOGV("readParamValue() reading float %f",*(float *)(*param + pos));
658 len = sizeof(float);
659 } else if (strncmp(node->name, BOOL_TAG, sizeof(BOOL_TAG) + 1) == 0) {
660 pos = growParamSize(param, sizeof(bool), curSize, totSize);
661 if (pos == 0) {
662 goto exit;
663 }
664 if (strncmp(node->value, "true", strlen("true") + 1) == 0) {
665 *(bool *)(*param + pos) = true;
666 } else {
667 *(bool *)(*param + pos) = false;
668 }
669 ALOGV("readParamValue() reading bool %s",
670 *(bool *)(*param + pos) ? "true" : "false");
671 len = sizeof(bool);
bryant_liuba2b4392014-06-11 16:49:30 +0800672 } else if (strncmp(node->name, STRING_TAG, sizeof(STRING_TAG) + 1) == 0) {
Eric Laurent138ed172016-02-10 10:40:44 -0800673 len = strnlen(node->value, EFFECT_STRING_LEN_MAX);
bryant_liuba2b4392014-06-11 16:49:30 +0800674 if (*curSize + len + 1 > *totSize) {
675 *totSize = *curSize + len + 1;
Chih-Hung Hsieh03077682018-08-30 14:11:00 -0700676 char *newParam = (char *)realloc(*param, *totSize);
677 if (newParam == NULL) {
Eric Laurent138ed172016-02-10 10:40:44 -0800678 len = 0;
679 ALOGE("%s realloc error for string len %zu", __func__, *totSize);
680 goto exit;
681 }
Chih-Hung Hsieh03077682018-08-30 14:11:00 -0700682 *param = newParam;
bryant_liuba2b4392014-06-11 16:49:30 +0800683 }
Eric Laurent138ed172016-02-10 10:40:44 -0800684 strncpy(*param + *curSize, node->value, len);
bryant_liuba2b4392014-06-11 16:49:30 +0800685 *curSize += len;
Eric Laurent138ed172016-02-10 10:40:44 -0800686 (*param)[*curSize] = '\0';
687 ALOGV("readParamValue() reading string %s", *param + *curSize - len);
688 } else {
689 ALOGW("readParamValue() unknown param type %s", node->name);
bryant_liuba2b4392014-06-11 16:49:30 +0800690 }
Eric Laurent138ed172016-02-10 10:40:44 -0800691exit:
692 return len;
bryant_liuba2b4392014-06-11 16:49:30 +0800693}
694
695effect_param_t *AudioPolicyEffects::loadEffectParameter(cnode *root)
696{
697 cnode *param;
698 cnode *value;
699 size_t curSize = sizeof(effect_param_t);
700 size_t totSize = sizeof(effect_param_t) + 2 * sizeof(int);
701 effect_param_t *fx_param = (effect_param_t *)malloc(totSize);
702
Eric Laurent138ed172016-02-10 10:40:44 -0800703 if (fx_param == NULL) {
704 ALOGE("%s malloc error for effect structure of size %zu",
705 __func__, totSize);
706 return NULL;
707 }
708
bryant_liuba2b4392014-06-11 16:49:30 +0800709 param = config_find(root, PARAM_TAG);
710 value = config_find(root, VALUE_TAG);
711 if (param == NULL && value == NULL) {
712 // try to parse simple parameter form {int int}
713 param = root->first_child;
714 if (param != NULL) {
715 // Note: that a pair of random strings is read as 0 0
716 int *ptr = (int *)fx_param->data;
Eric Laurent138ed172016-02-10 10:40:44 -0800717#if LOG_NDEBUG == 0
bryant_liuba2b4392014-06-11 16:49:30 +0800718 int *ptr2 = (int *)((char *)param + sizeof(effect_param_t));
Eric Laurent138ed172016-02-10 10:40:44 -0800719 ALOGV("loadEffectParameter() ptr %p ptr2 %p", ptr, ptr2);
720#endif
bryant_liuba2b4392014-06-11 16:49:30 +0800721 *ptr++ = atoi(param->name);
722 *ptr = atoi(param->value);
723 fx_param->psize = sizeof(int);
724 fx_param->vsize = sizeof(int);
725 return fx_param;
726 }
727 }
728 if (param == NULL || value == NULL) {
Eric Laurent138ed172016-02-10 10:40:44 -0800729 ALOGW("loadEffectParameter() invalid parameter description %s",
730 root->name);
bryant_liuba2b4392014-06-11 16:49:30 +0800731 goto error;
732 }
733
734 fx_param->psize = 0;
735 param = param->first_child;
736 while (param) {
737 ALOGV("loadEffectParameter() reading param of type %s", param->name);
Eric Laurent138ed172016-02-10 10:40:44 -0800738 size_t size =
739 readParamValue(param, (char **)&fx_param, &curSize, &totSize);
bryant_liuba2b4392014-06-11 16:49:30 +0800740 if (size == 0) {
741 goto error;
742 }
743 fx_param->psize += size;
744 param = param->next;
745 }
746
747 // align start of value field on 32 bit boundary
748 curSize = ((curSize - 1 ) / sizeof(int) + 1) * sizeof(int);
749
750 fx_param->vsize = 0;
751 value = value->first_child;
752 while (value) {
753 ALOGV("loadEffectParameter() reading value of type %s", value->name);
Eric Laurent138ed172016-02-10 10:40:44 -0800754 size_t size =
755 readParamValue(value, (char **)&fx_param, &curSize, &totSize);
bryant_liuba2b4392014-06-11 16:49:30 +0800756 if (size == 0) {
757 goto error;
758 }
759 fx_param->vsize += size;
760 value = value->next;
761 }
762
763 return fx_param;
764
765error:
Eric Laurent138ed172016-02-10 10:40:44 -0800766 free(fx_param);
bryant_liuba2b4392014-06-11 16:49:30 +0800767 return NULL;
768}
769
770void AudioPolicyEffects::loadEffectParameters(cnode *root, Vector <effect_param_t *>& params)
771{
772 cnode *node = root->first_child;
773 while (node) {
774 ALOGV("loadEffectParameters() loading param %s", node->name);
775 effect_param_t *param = loadEffectParameter(node);
Eric Laurent138ed172016-02-10 10:40:44 -0800776 if (param != NULL) {
777 params.add(param);
bryant_liuba2b4392014-06-11 16:49:30 +0800778 }
bryant_liuba2b4392014-06-11 16:49:30 +0800779 node = node->next;
780 }
781}
782
783
784AudioPolicyEffects::EffectDescVector *AudioPolicyEffects::loadEffectConfig(
785 cnode *root,
786 const Vector <EffectDesc *>& effects)
787{
788 cnode *node = root->first_child;
789 if (node == NULL) {
790 ALOGW("loadInputSource() empty element %s", root->name);
791 return NULL;
792 }
793 EffectDescVector *desc = new EffectDescVector();
794 while (node) {
795 size_t i;
Eric Laurent138ed172016-02-10 10:40:44 -0800796
bryant_liuba2b4392014-06-11 16:49:30 +0800797 for (i = 0; i < effects.size(); i++) {
798 if (strncmp(effects[i]->mName, node->name, EFFECT_STRING_LEN_MAX) == 0) {
799 ALOGV("loadEffectConfig() found effect %s in list", node->name);
800 break;
801 }
802 }
803 if (i == effects.size()) {
804 ALOGV("loadEffectConfig() effect %s not in list", node->name);
805 node = node->next;
806 continue;
807 }
808 EffectDesc *effect = new EffectDesc(*effects[i]); // deep copy
809 loadEffectParameters(node, effect->mParams);
810 ALOGV("loadEffectConfig() adding effect %s uuid %08x",
811 effect->mName, effect->mUuid.timeLow);
812 desc->mEffects.add(effect);
813 node = node->next;
814 }
815 if (desc->mEffects.size() == 0) {
816 ALOGW("loadEffectConfig() no valid effects found in config %s", root->name);
817 delete desc;
818 return NULL;
819 }
820 return desc;
821}
822
823status_t AudioPolicyEffects::loadInputEffectConfigurations(cnode *root,
824 const Vector <EffectDesc *>& effects)
825{
826 cnode *node = config_find(root, PREPROCESSING_TAG);
827 if (node == NULL) {
828 return -ENOENT;
829 }
830 node = node->first_child;
831 while (node) {
832 audio_source_t source = inputSourceNameToEnum(node->name);
833 if (source == AUDIO_SOURCE_CNT) {
834 ALOGW("loadInputSources() invalid input source %s", node->name);
835 node = node->next;
836 continue;
837 }
838 ALOGV("loadInputSources() loading input source %s", node->name);
839 EffectDescVector *desc = loadEffectConfig(node, effects);
840 if (desc == NULL) {
841 node = node->next;
842 continue;
843 }
844 mInputSources.add(source, desc);
845 node = node->next;
846 }
847 return NO_ERROR;
848}
849
850status_t AudioPolicyEffects::loadStreamEffectConfigurations(cnode *root,
851 const Vector <EffectDesc *>& effects)
852{
853 cnode *node = config_find(root, OUTPUT_SESSION_PROCESSING_TAG);
854 if (node == NULL) {
855 return -ENOENT;
856 }
857 node = node->first_child;
858 while (node) {
859 audio_stream_type_t stream = streamNameToEnum(node->name);
Eric Laurent223fd5c2014-11-11 13:43:36 -0800860 if (stream == AUDIO_STREAM_PUBLIC_CNT) {
bryant_liuba2b4392014-06-11 16:49:30 +0800861 ALOGW("loadStreamEffectConfigurations() invalid output stream %s", node->name);
862 node = node->next;
863 continue;
864 }
865 ALOGV("loadStreamEffectConfigurations() loading output stream %s", node->name);
866 EffectDescVector *desc = loadEffectConfig(node, effects);
867 if (desc == NULL) {
868 node = node->next;
869 continue;
870 }
871 mOutputStreams.add(stream, desc);
872 node = node->next;
873 }
874 return NO_ERROR;
875}
876
877AudioPolicyEffects::EffectDesc *AudioPolicyEffects::loadEffect(cnode *root)
878{
879 cnode *node = config_find(root, UUID_TAG);
880 if (node == NULL) {
881 return NULL;
882 }
883 effect_uuid_t uuid;
884 if (AudioEffect::stringToGuid(node->value, &uuid) != NO_ERROR) {
885 ALOGW("loadEffect() invalid uuid %s", node->value);
886 return NULL;
887 }
888 return new EffectDesc(root->name, uuid);
889}
890
891status_t AudioPolicyEffects::loadEffects(cnode *root, Vector <EffectDesc *>& effects)
892{
893 cnode *node = config_find(root, EFFECTS_TAG);
894 if (node == NULL) {
895 return -ENOENT;
896 }
897 node = node->first_child;
898 while (node) {
899 ALOGV("loadEffects() loading effect %s", node->name);
900 EffectDesc *effect = loadEffect(node);
901 if (effect == NULL) {
902 node = node->next;
903 continue;
904 }
905 effects.add(effect);
906 node = node->next;
907 }
908 return NO_ERROR;
909}
910
Shunkai Yao8d6489a2023-04-18 23:14:25 +0000911status_t AudioPolicyEffects::loadAudioEffectConfig(
912 const sp<EffectsFactoryHalInterface>& effectsFactoryHal) {
913 if (!effectsFactoryHal) {
914 ALOGE("%s Null EffectsFactoryHalInterface", __func__);
915 return UNEXPECTED_NULL;
916 }
917
918 const auto skippedElements = VALUE_OR_RETURN_STATUS(effectsFactoryHal->getSkippedElements());
919 const auto processings = effectsFactoryHal->getProcessings();
920 if (!processings) {
921 ALOGE("%s Null processings with %zu skipped elements", __func__, skippedElements);
922 return UNEXPECTED_NULL;
Kevin Rocard4fb615c2017-06-26 10:28:13 -0700923 }
924
925 auto loadProcessingChain = [](auto& processingChain, auto& streams) {
926 for (auto& stream : processingChain) {
927 auto effectDescs = std::make_unique<EffectDescVector>();
928 for (auto& effect : stream.effects) {
Shunkai Yao6c19bcf2023-05-08 20:40:06 +0000929 effectDescs->mEffects.add(new EffectDesc{effect->name.c_str(), effect->uuid});
Kevin Rocard4fb615c2017-06-26 10:28:13 -0700930 }
931 streams.add(stream.type, effectDescs.release());
932 }
933 };
François Gaffie06182982020-01-07 15:16:14 +0100934
Shunkai Yao8d6489a2023-04-18 23:14:25 +0000935 auto loadDeviceProcessingChain = [](auto& processingChain, auto& devicesEffects) {
François Gaffie06182982020-01-07 15:16:14 +0100936 for (auto& deviceProcess : processingChain) {
François Gaffie06182982020-01-07 15:16:14 +0100937 auto effectDescs = std::make_unique<EffectDescVector>();
938 for (auto& effect : deviceProcess.effects) {
Shunkai Yao6c19bcf2023-05-08 20:40:06 +0000939 effectDescs->mEffects.add(new EffectDesc{effect->name.c_str(), effect->uuid});
François Gaffie06182982020-01-07 15:16:14 +0100940 }
941 auto deviceEffects = std::make_unique<DeviceEffects>(
942 std::move(effectDescs), deviceProcess.type, deviceProcess.address);
943 devicesEffects.emplace(deviceProcess.address, std::move(deviceEffects));
944 }
945 };
946
Shunkai Yao8d6489a2023-04-18 23:14:25 +0000947 loadProcessingChain(processings->preprocess, mInputSources);
948 loadProcessingChain(processings->postprocess, mOutputStreams);
949
Mikhail Naganov12b716c2020-04-30 22:37:43 +0000950 {
Andy Hung79eacdb2023-11-30 19:34:24 -0800951 audio_utils::lock_guard _l(mMutex);
Shunkai Yao8d6489a2023-04-18 23:14:25 +0000952 loadDeviceProcessingChain(processings->deviceprocess, mDeviceEffects);
Mikhail Naganov12b716c2020-04-30 22:37:43 +0000953 }
Shunkai Yao8d6489a2023-04-18 23:14:25 +0000954
955 return skippedElements;
Kevin Rocard4fb615c2017-06-26 10:28:13 -0700956}
957
Shunkai Yaoeab8a7c2023-05-15 21:07:08 +0000958status_t AudioPolicyEffects::loadAudioEffectConfigLegacy(const char *path)
959{
960 cnode *root;
961 char *data;
962
963 data = (char *)load_file(path, NULL);
964 if (data == NULL) {
965 return -ENODEV;
966 }
967 root = config_node("", "");
968 config_load(root, data);
969
970 Vector <EffectDesc *> effects;
971 loadEffects(root, effects);
972 loadInputEffectConfigurations(root, effects);
973 loadStreamEffectConfigurations(root, effects);
974
975 for (size_t i = 0; i < effects.size(); i++) {
976 delete effects[i];
977 }
978
979 config_free(root);
980 free(root);
981 free(data);
982
983 return NO_ERROR;
984}
985
François Gaffie06182982020-01-07 15:16:14 +0100986void AudioPolicyEffects::initDefaultDeviceEffects()
987{
Andy Hung79eacdb2023-11-30 19:34:24 -0800988 audio_utils::lock_guard _l(mMutex);
François Gaffie06182982020-01-07 15:16:14 +0100989 for (const auto& deviceEffectsIter : mDeviceEffects) {
990 const auto& deviceEffects = deviceEffectsIter.second;
991 for (const auto& effectDesc : deviceEffects->mEffectDescriptors->mEffects) {
Svet Ganov3e5f14f2021-05-13 22:51:08 +0000992 AttributionSourceState attributionSource;
993 attributionSource.packageName = "android";
994 attributionSource.token = sp<BBinder>::make();
995 sp<AudioEffect> fx = new AudioEffect(attributionSource);
Atneya Nair884f7992022-05-17 19:22:42 -0400996 fx->set(EFFECT_UUID_NULL, &effectDesc->mUuid, 0 /* priority */, nullptr /* callback */,
997 AUDIO_SESSION_DEVICE, AUDIO_IO_HANDLE_NONE,
Mikhail Naganov69d41cc2020-07-31 17:36:08 -0700998 AudioDeviceTypeAddr{deviceEffects->getDeviceType(),
999 deviceEffects->getDeviceAddress()});
François Gaffie06182982020-01-07 15:16:14 +01001000 status_t status = fx->initCheck();
1001 if (status != NO_ERROR && status != ALREADY_EXISTS) {
1002 ALOGE("%s(): failed to create Fx %s on port type=%d address=%s", __func__,
1003 effectDesc->mName, deviceEffects->getDeviceType(),
1004 deviceEffects->getDeviceAddress().c_str());
1005 // fx goes out of scope and strong ref on AudioEffect is released
1006 continue;
1007 }
1008 fx->setEnabled(true);
1009 ALOGV("%s(): create Fx %s added on port type=%d address=%s", __func__,
1010 effectDesc->mName, deviceEffects->getDeviceType(),
1011 deviceEffects->getDeviceAddress().c_str());
Jintao Zhu230397e2021-03-07 14:15:10 +08001012 deviceEffects->mEffects.push_back(fx);
François Gaffie06182982020-01-07 15:16:14 +01001013 }
1014 }
1015}
bryant_liuba2b4392014-06-11 16:49:30 +08001016
Mikhail Naganov1b2a7942017-12-08 10:18:09 -08001017} // namespace android