blob: 71edd572946dbcf697388d6f54e0d187db6c15c6 [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) {
Andy Hungd3595ed2023-12-19 15:34:46 -080045 // Note: clang thread-safety permits the ctor to call guarded _l methods without
46 // acquiring the associated mutex capability as standard practice is to assume
47 // single threaded construction and destruction.
48
Shunkai Yao8d6489a2023-04-18 23:14:25 +000049 // load xml config with effectsFactoryHal
Andy Hungd3595ed2023-12-19 15:34:46 -080050 status_t loadResult = loadAudioEffectConfig_ll(effectsFactoryHal);
François Gaffie163ce832023-06-28 11:36:35 +020051 if (loadResult < 0) {
Shunkai Yaoeab8a7c2023-05-15 21:07:08 +000052 ALOGW("Failed to query effect configuration, fallback to load .conf");
53 // load automatic audio effect modules
54 if (access(AUDIO_EFFECT_VENDOR_CONFIG_FILE, R_OK) == 0) {
Andy Hungd3595ed2023-12-19 15:34:46 -080055 loadAudioEffectConfigLegacy_l(AUDIO_EFFECT_VENDOR_CONFIG_FILE);
Shunkai Yaoeab8a7c2023-05-15 21:07:08 +000056 } else if (access(AUDIO_EFFECT_DEFAULT_CONFIG_FILE, R_OK) == 0) {
Andy Hungd3595ed2023-12-19 15:34:46 -080057 loadAudioEffectConfigLegacy_l(AUDIO_EFFECT_DEFAULT_CONFIG_FILE);
Shunkai Yaoeab8a7c2023-05-15 21:07:08 +000058 }
Kevin Rocard4fb615c2017-06-26 10:28:13 -070059 } else if (loadResult > 0) {
60 ALOGE("Effect config is partially invalid, skipped %d elements", loadResult);
bryant_liuba2b4392014-06-11 16:49:30 +080061 }
62}
63
François Gaffie163ce832023-06-28 11:36:35 +020064void AudioPolicyEffects::setDefaultDeviceEffects() {
65 mDefaultDeviceEffectFuture = std::async(
66 std::launch::async, &AudioPolicyEffects::initDefaultDeviceEffects, this);
67}
68
bryant_liuba2b4392014-06-11 16:49:30 +080069status_t AudioPolicyEffects::addInputEffects(audio_io_handle_t input,
70 audio_source_t inputSource,
Eric Laurentfb66dd92016-01-28 18:32:03 -080071 audio_session_t audioSession)
bryant_liuba2b4392014-06-11 16:49:30 +080072{
73 status_t status = NO_ERROR;
74
75 // create audio pre processors according to input source
76 audio_source_t aliasSource = (inputSource == AUDIO_SOURCE_HOTWORD) ?
77 AUDIO_SOURCE_VOICE_RECOGNITION : inputSource;
78
Andy Hung79eacdb2023-11-30 19:34:24 -080079 audio_utils::lock_guard _l(mMutex);
Andy Hung43119fb2023-12-26 19:26:35 -080080 auto sourceIt = mInputSources.find(aliasSource);
81 if (sourceIt == mInputSources.end()) {
bryant_liuba2b4392014-06-11 16:49:30 +080082 ALOGV("addInputEffects(): no processing needs to be attached to this source");
83 return status;
84 }
Andy Hung43119fb2023-12-26 19:26:35 -080085 std::shared_ptr<EffectVector>& sessionDesc = mInputSessions[audioSession];
86 if (sessionDesc == nullptr) {
Andy Hungf42175b2023-12-19 19:03:19 -080087 sessionDesc = std::make_shared<EffectVector>(audioSession);
bryant_liuba2b4392014-06-11 16:49:30 +080088 }
Eric Laurentfb66dd92016-01-28 18:32:03 -080089 sessionDesc->mRefCount++;
bryant_liu890a5632014-08-20 18:06:13 +080090
Eric Laurentfb66dd92016-01-28 18:32:03 -080091 ALOGV("addInputEffects(): input: %d, refCount: %d", input, sessionDesc->mRefCount);
92 if (sessionDesc->mRefCount == 1) {
Eric Laurentb6436272016-12-07 19:24:50 -080093 int64_t token = IPCThreadState::self()->clearCallingIdentity();
Andy Hung43119fb2023-12-26 19:26:35 -080094 const std::shared_ptr<EffectDescVector>& effects = sourceIt->second;
Andy Hungf42175b2023-12-19 19:03:19 -080095 for (const std::shared_ptr<EffectDesc>& effect : *effects) {
Svet Ganov3e5f14f2021-05-13 22:51:08 +000096 AttributionSourceState attributionSource;
97 attributionSource.packageName = "android";
98 attributionSource.token = sp<BBinder>::make();
Andy Hungf42175b2023-12-19 19:03:19 -080099 auto fx = sp<AudioEffect>::make(attributionSource);
Atneya Nair884f7992022-05-17 19:22:42 -0400100 fx->set(nullptr /*type */, &effect->mUuid, -1 /* priority */, nullptr /* callback */,
101 audioSession, input);
Eric Laurent7de5ac12014-10-21 09:07:11 -0700102 status_t status = fx->initCheck();
103 if (status != NO_ERROR && status != ALREADY_EXISTS) {
104 ALOGW("addInputEffects(): failed to create Fx %s on source %d",
Andy Hung7760a852023-12-19 17:27:52 -0800105 effect->mName.c_str(), (int32_t)aliasSource);
Eric Laurent7de5ac12014-10-21 09:07:11 -0700106 // fx goes out of scope and strong ref on AudioEffect is released
107 continue;
108 }
109 for (size_t j = 0; j < effect->mParams.size(); j++) {
Andy Hung7760a852023-12-19 17:27:52 -0800110 // const_cast here due to API.
111 fx->setParameter(const_cast<effect_param_t*>(effect->mParams[j].get()));
Eric Laurent7de5ac12014-10-21 09:07:11 -0700112 }
113 ALOGV("addInputEffects(): added Fx %s on source: %d",
Andy Hung7760a852023-12-19 17:27:52 -0800114 effect->mName.c_str(), (int32_t)aliasSource);
Andy Hungf42175b2023-12-19 19:03:19 -0800115 sessionDesc->mEffects.push_back(std::move(fx));
bryant_liuba2b4392014-06-11 16:49:30 +0800116 }
Eric Laurentfb66dd92016-01-28 18:32:03 -0800117 sessionDesc->setProcessorEnabled(true);
Eric Laurentb6436272016-12-07 19:24:50 -0800118 IPCThreadState::self()->restoreCallingIdentity(token);
bryant_liuba2b4392014-06-11 16:49:30 +0800119 }
bryant_liuba2b4392014-06-11 16:49:30 +0800120 return status;
121}
122
123
Eric Laurentfb66dd92016-01-28 18:32:03 -0800124status_t AudioPolicyEffects::releaseInputEffects(audio_io_handle_t input,
125 audio_session_t audioSession)
bryant_liuba2b4392014-06-11 16:49:30 +0800126{
127 status_t status = NO_ERROR;
128
Andy Hung79eacdb2023-11-30 19:34:24 -0800129 audio_utils::lock_guard _l(mMutex);
Andy Hung43119fb2023-12-26 19:26:35 -0800130 auto it = mInputSessions.find(audioSession);
131 if (it == mInputSessions.end()) {
bryant_liuba2b4392014-06-11 16:49:30 +0800132 return status;
133 }
Andy Hung43119fb2023-12-26 19:26:35 -0800134 std::shared_ptr<EffectVector> sessionDesc = it->second;
Eric Laurentfb66dd92016-01-28 18:32:03 -0800135 sessionDesc->mRefCount--;
136 ALOGV("releaseInputEffects(): input: %d, refCount: %d", input, sessionDesc->mRefCount);
137 if (sessionDesc->mRefCount == 0) {
138 sessionDesc->setProcessorEnabled(false);
Andy Hung43119fb2023-12-26 19:26:35 -0800139 mInputSessions.erase(it);
bryant_liu890a5632014-08-20 18:06:13 +0800140 ALOGV("releaseInputEffects(): all effects released");
141 }
bryant_liuba2b4392014-06-11 16:49:30 +0800142 return status;
143}
144
Eric Laurentfb66dd92016-01-28 18:32:03 -0800145status_t AudioPolicyEffects::queryDefaultInputEffects(audio_session_t audioSession,
bryant_liuba2b4392014-06-11 16:49:30 +0800146 effect_descriptor_t *descriptors,
147 uint32_t *count)
148{
149 status_t status = NO_ERROR;
150
Andy Hung79eacdb2023-11-30 19:34:24 -0800151 audio_utils::lock_guard _l(mMutex);
Andy Hung43119fb2023-12-26 19:26:35 -0800152 auto it = mInputSessions.find(audioSession);
153 if (it == mInputSessions.end()) {
bryant_liuba2b4392014-06-11 16:49:30 +0800154 *count = 0;
155 return BAD_VALUE;
156 }
Andy Hung43119fb2023-12-26 19:26:35 -0800157 const std::vector<sp<AudioEffect>>& effects = it->second->mEffects;
158 const size_t copysize = std::min(effects.size(), (size_t)*count);
159 for (size_t i = 0; i < copysize; i++) {
160 descriptors[i] = effects[i]->descriptor();
bryant_liuba2b4392014-06-11 16:49:30 +0800161 }
162 if (effects.size() > *count) {
163 status = NO_MEMORY;
164 }
165 *count = effects.size();
166 return status;
167}
168
169
Eric Laurentfb66dd92016-01-28 18:32:03 -0800170status_t AudioPolicyEffects::queryDefaultOutputSessionEffects(audio_session_t audioSession,
bryant_liuba2b4392014-06-11 16:49:30 +0800171 effect_descriptor_t *descriptors,
172 uint32_t *count)
173{
174 status_t status = NO_ERROR;
175
Andy Hung79eacdb2023-11-30 19:34:24 -0800176 audio_utils::lock_guard _l(mMutex);
Andy Hung43119fb2023-12-26 19:26:35 -0800177 auto it = mOutputSessions.find(audioSession);
178 if (it == mOutputSessions.end()) {
bryant_liuba2b4392014-06-11 16:49:30 +0800179 *count = 0;
180 return BAD_VALUE;
181 }
Andy Hung43119fb2023-12-26 19:26:35 -0800182 const std::vector<sp<AudioEffect>>& effects = it->second->mEffects;
183 const size_t copysize = std::min(effects.size(), (size_t)*count);
184 for (size_t i = 0; i < copysize; i++) {
185 descriptors[i] = effects[i]->descriptor();
bryant_liuba2b4392014-06-11 16:49:30 +0800186 }
187 if (effects.size() > *count) {
188 status = NO_MEMORY;
189 }
190 *count = effects.size();
191 return status;
192}
193
194
195status_t AudioPolicyEffects::addOutputSessionEffects(audio_io_handle_t output,
196 audio_stream_type_t stream,
Eric Laurentfb66dd92016-01-28 18:32:03 -0800197 audio_session_t audioSession)
bryant_liuba2b4392014-06-11 16:49:30 +0800198{
199 status_t status = NO_ERROR;
200
Andy Hung79eacdb2023-11-30 19:34:24 -0800201 audio_utils::lock_guard _l(mMutex);
bryant_liuba2b4392014-06-11 16:49:30 +0800202 // create audio processors according to stream
Eric Laurent223fd5c2014-11-11 13:43:36 -0800203 // FIXME: should we have specific post processing settings for internal streams?
204 // default to media for now.
205 if (stream >= AUDIO_STREAM_PUBLIC_CNT) {
206 stream = AUDIO_STREAM_MUSIC;
207 }
Andy Hung43119fb2023-12-26 19:26:35 -0800208 auto it = mOutputStreams.find(stream);
209 if (it == mOutputStreams.end()) {
bryant_liuba2b4392014-06-11 16:49:30 +0800210 ALOGV("addOutputSessionEffects(): no output processing needed for this stream");
211 return NO_ERROR;
212 }
213
Andy Hung43119fb2023-12-26 19:26:35 -0800214 std::shared_ptr<EffectVector>& procDesc = mOutputSessions[audioSession];
215 if (procDesc == nullptr) {
Andy Hungf42175b2023-12-19 19:03:19 -0800216 procDesc = std::make_shared<EffectVector>(audioSession);
bryant_liuba2b4392014-06-11 16:49:30 +0800217 }
bryant_liu890a5632014-08-20 18:06:13 +0800218 procDesc->mRefCount++;
219
Eric Laurent7de5ac12014-10-21 09:07:11 -0700220 ALOGV("addOutputSessionEffects(): session: %d, refCount: %d",
221 audioSession, procDesc->mRefCount);
222 if (procDesc->mRefCount == 1) {
Eric Laurentb6436272016-12-07 19:24:50 -0800223 // make sure effects are associated to audio server even if we are executing a binder call
224 int64_t token = IPCThreadState::self()->clearCallingIdentity();
Andy Hung43119fb2023-12-26 19:26:35 -0800225 const std::shared_ptr<EffectDescVector>& effects = it->second;
Andy Hungf42175b2023-12-19 19:03:19 -0800226 for (const std::shared_ptr<EffectDesc>& effect : *effects) {
Svet Ganov3e5f14f2021-05-13 22:51:08 +0000227 AttributionSourceState attributionSource;
228 attributionSource.packageName = "android";
229 attributionSource.token = sp<BBinder>::make();
Andy Hungf42175b2023-12-19 19:03:19 -0800230 auto fx = sp<AudioEffect>::make(attributionSource);
Atneya Nair884f7992022-05-17 19:22:42 -0400231 fx->set(nullptr /* type */, &effect->mUuid, 0 /* priority */, nullptr /* callback */,
232 audioSession, output);
Eric Laurent7de5ac12014-10-21 09:07:11 -0700233 status_t status = fx->initCheck();
234 if (status != NO_ERROR && status != ALREADY_EXISTS) {
235 ALOGE("addOutputSessionEffects(): failed to create Fx %s on session %d",
Andy Hung7760a852023-12-19 17:27:52 -0800236 effect->mName.c_str(), audioSession);
Eric Laurent7de5ac12014-10-21 09:07:11 -0700237 // fx goes out of scope and strong ref on AudioEffect is released
238 continue;
239 }
240 ALOGV("addOutputSessionEffects(): added Fx %s on session: %d for stream: %d",
Andy Hung7760a852023-12-19 17:27:52 -0800241 effect->mName.c_str(), audioSession, (int32_t)stream);
Andy Hungf42175b2023-12-19 19:03:19 -0800242 procDesc->mEffects.push_back(std::move(fx));
bryant_liuba2b4392014-06-11 16:49:30 +0800243 }
Eric Laurent7de5ac12014-10-21 09:07:11 -0700244
245 procDesc->setProcessorEnabled(true);
Eric Laurentb6436272016-12-07 19:24:50 -0800246 IPCThreadState::self()->restoreCallingIdentity(token);
bryant_liuba2b4392014-06-11 16:49:30 +0800247 }
bryant_liuba2b4392014-06-11 16:49:30 +0800248 return status;
249}
250
251status_t AudioPolicyEffects::releaseOutputSessionEffects(audio_io_handle_t output,
252 audio_stream_type_t stream,
Eric Laurentfb66dd92016-01-28 18:32:03 -0800253 audio_session_t audioSession)
bryant_liuba2b4392014-06-11 16:49:30 +0800254{
bryant_liuba2b4392014-06-11 16:49:30 +0800255 (void) output; // argument not used for now
256 (void) stream; // argument not used for now
257
Andy Hung79eacdb2023-11-30 19:34:24 -0800258 audio_utils::lock_guard _l(mMutex);
Andy Hung43119fb2023-12-26 19:26:35 -0800259 auto it = mOutputSessions.find(audioSession);
260 if (it == mOutputSessions.end()) {
bryant_liuba2b4392014-06-11 16:49:30 +0800261 ALOGV("releaseOutputSessionEffects: no output processing was attached to this stream");
262 return NO_ERROR;
263 }
264
Andy Hung43119fb2023-12-26 19:26:35 -0800265 std::shared_ptr<EffectVector> procDesc = it->second;
bryant_liu890a5632014-08-20 18:06:13 +0800266 procDesc->mRefCount--;
Eric Laurent7de5ac12014-10-21 09:07:11 -0700267 ALOGV("releaseOutputSessionEffects(): session: %d, refCount: %d",
268 audioSession, procDesc->mRefCount);
bryant_liu890a5632014-08-20 18:06:13 +0800269 if (procDesc->mRefCount == 0) {
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700270 procDesc->setProcessorEnabled(false);
bryant_liu890a5632014-08-20 18:06:13 +0800271 procDesc->mEffects.clear();
Andy Hung43119fb2023-12-26 19:26:35 -0800272 mOutputSessions.erase(it);
bryant_liu890a5632014-08-20 18:06:13 +0800273 ALOGV("releaseOutputSessionEffects(): output processing released from session: %d",
274 audioSession);
275 }
Andy Hung43119fb2023-12-26 19:26:35 -0800276 return NO_ERROR;
bryant_liuba2b4392014-06-11 16:49:30 +0800277}
278
Ari Hausman-Cohen24628312018-08-13 15:01:09 -0700279status_t AudioPolicyEffects::addSourceDefaultEffect(const effect_uuid_t *type,
280 const String16& opPackageName,
281 const effect_uuid_t *uuid,
282 int32_t priority,
283 audio_source_t source,
284 audio_unique_id_t* id)
285{
286 if (uuid == NULL || type == NULL) {
287 ALOGE("addSourceDefaultEffect(): Null uuid or type uuid pointer");
288 return BAD_VALUE;
289 }
290
Eric Laurentae4b6ec2019-01-15 18:34:38 -0800291 // HOTWORD, FM_TUNER and ECHO_REFERENCE are special case sources > MAX.
Ari Hausman-Cohen24628312018-08-13 15:01:09 -0700292 if (source < AUDIO_SOURCE_DEFAULT ||
293 (source > AUDIO_SOURCE_MAX &&
294 source != AUDIO_SOURCE_HOTWORD &&
Eric Laurentae4b6ec2019-01-15 18:34:38 -0800295 source != AUDIO_SOURCE_FM_TUNER &&
Carter Hsua3abb402021-10-26 11:11:20 +0800296 source != AUDIO_SOURCE_ECHO_REFERENCE &&
297 source != AUDIO_SOURCE_ULTRASOUND)) {
Ari Hausman-Cohen24628312018-08-13 15:01:09 -0700298 ALOGE("addSourceDefaultEffect(): Unsupported source type %d", source);
299 return BAD_VALUE;
300 }
301
302 // Check that |uuid| or |type| corresponds to an effect on the system.
303 effect_descriptor_t descriptor = {};
304 status_t res = AudioEffect::getEffectDescriptor(
305 uuid, type, EFFECT_FLAG_TYPE_PRE_PROC, &descriptor);
306 if (res != OK) {
307 ALOGE("addSourceDefaultEffect(): Failed to find effect descriptor matching uuid/type.");
308 return res;
309 }
310
311 // Only pre-processing effects can be added dynamically as source defaults.
312 if ((descriptor.flags & EFFECT_FLAG_TYPE_MASK) != EFFECT_FLAG_TYPE_PRE_PROC) {
313 ALOGE("addSourceDefaultEffect(): Desired effect cannot be attached "
314 "as a source default effect.");
315 return BAD_VALUE;
316 }
317
Andy Hung79eacdb2023-11-30 19:34:24 -0800318 audio_utils::lock_guard _l(mMutex);
Ari Hausman-Cohen24628312018-08-13 15:01:09 -0700319
320 // Find the EffectDescVector for the given source type, or create a new one if necessary.
Andy Hung43119fb2023-12-26 19:26:35 -0800321 std::shared_ptr<EffectDescVector>& desc = mInputSources[source];
322 if (desc == nullptr) {
Andy Hungf42175b2023-12-19 19:03:19 -0800323 desc = std::make_shared<EffectDescVector>();
Ari Hausman-Cohen24628312018-08-13 15:01:09 -0700324 }
325
326 // Create a new effect and add it to the vector.
327 res = AudioEffect::newEffectUniqueId(id);
328 if (res != OK) {
329 ALOGE("addSourceDefaultEffect(): failed to get new unique id.");
330 return res;
331 }
Andy Hungf42175b2023-12-19 19:03:19 -0800332 std::shared_ptr<EffectDesc> effect = std::make_shared<EffectDesc>(
Eric Laurent2685aa02022-02-01 14:26:38 +0100333 descriptor.name, descriptor.type, opPackageName, descriptor.uuid, priority, *id);
Andy Hungf42175b2023-12-19 19:03:19 -0800334 desc->push_back(std::move(effect));
Ari Hausman-Cohen24628312018-08-13 15:01:09 -0700335 // TODO(b/71813697): Support setting params as well.
336
337 // TODO(b/71814300): Retroactively attach to any existing sources of the given type.
338 // This requires tracking the source type of each session id in addition to what is
339 // already being tracked.
340
341 return NO_ERROR;
342}
343
Ari Hausman-Cohen433722e2018-04-24 14:25:22 -0700344status_t AudioPolicyEffects::addStreamDefaultEffect(const effect_uuid_t *type,
345 const String16& opPackageName,
346 const effect_uuid_t *uuid,
347 int32_t priority,
348 audio_usage_t usage,
349 audio_unique_id_t* id)
350{
351 if (uuid == NULL || type == NULL) {
352 ALOGE("addStreamDefaultEffect(): Null uuid or type uuid pointer");
353 return BAD_VALUE;
354 }
François Gaffie58d4be52018-11-06 15:30:12 +0100355 audio_stream_type_t stream = AudioSystem::attributesToStreamType(attributes_initializer(usage));
Ari Hausman-Cohen433722e2018-04-24 14:25:22 -0700356
357 if (stream < AUDIO_STREAM_MIN || stream >= AUDIO_STREAM_PUBLIC_CNT) {
358 ALOGE("addStreamDefaultEffect(): Unsupported stream type %d", stream);
359 return BAD_VALUE;
360 }
361
362 // Check that |uuid| or |type| corresponds to an effect on the system.
363 effect_descriptor_t descriptor = {};
364 status_t res = AudioEffect::getEffectDescriptor(
365 uuid, type, EFFECT_FLAG_TYPE_INSERT, &descriptor);
366 if (res != OK) {
367 ALOGE("addStreamDefaultEffect(): Failed to find effect descriptor matching uuid/type.");
368 return res;
369 }
370
371 // Only insert effects can be added dynamically as stream defaults.
372 if ((descriptor.flags & EFFECT_FLAG_TYPE_MASK) != EFFECT_FLAG_TYPE_INSERT) {
373 ALOGE("addStreamDefaultEffect(): Desired effect cannot be attached "
374 "as a stream default effect.");
375 return BAD_VALUE;
376 }
377
Andy Hung79eacdb2023-11-30 19:34:24 -0800378 audio_utils::lock_guard _l(mMutex);
Ari Hausman-Cohen433722e2018-04-24 14:25:22 -0700379
380 // Find the EffectDescVector for the given stream type, or create a new one if necessary.
Andy Hung43119fb2023-12-26 19:26:35 -0800381 std::shared_ptr<EffectDescVector>& desc = mOutputStreams[stream];
382 if (desc == nullptr) {
Ari Hausman-Cohen433722e2018-04-24 14:25:22 -0700383 // No effects for this stream type yet.
Andy Hungf42175b2023-12-19 19:03:19 -0800384 desc = std::make_shared<EffectDescVector>();
Ari Hausman-Cohen433722e2018-04-24 14:25:22 -0700385 }
386
387 // Create a new effect and add it to the vector.
388 res = AudioEffect::newEffectUniqueId(id);
389 if (res != OK) {
390 ALOGE("addStreamDefaultEffect(): failed to get new unique id.");
391 return res;
392 }
Andy Hungf42175b2023-12-19 19:03:19 -0800393 std::shared_ptr<EffectDesc> effect = std::make_shared<EffectDesc>(
Eric Laurent2685aa02022-02-01 14:26:38 +0100394 descriptor.name, descriptor.type, opPackageName, descriptor.uuid, priority, *id);
Andy Hungf42175b2023-12-19 19:03:19 -0800395 desc->push_back(std::move(effect));
Ari Hausman-Cohen433722e2018-04-24 14:25:22 -0700396 // TODO(b/71813697): Support setting params as well.
397
398 // TODO(b/71814300): Retroactively attach to any existing streams of the given type.
399 // This requires tracking the stream type of each session id in addition to what is
400 // already being tracked.
401
402 return NO_ERROR;
403}
404
Ari Hausman-Cohen24628312018-08-13 15:01:09 -0700405status_t AudioPolicyEffects::removeSourceDefaultEffect(audio_unique_id_t id)
406{
407 if (id == AUDIO_UNIQUE_ID_ALLOCATE) {
408 // ALLOCATE is not a unique identifier, but rather a reserved value indicating
409 // a real id has not been assigned. For default effects, this value is only used
410 // by system-owned defaults from the loaded config, which cannot be removed.
411 return BAD_VALUE;
412 }
413
Andy Hung79eacdb2023-11-30 19:34:24 -0800414 audio_utils::lock_guard _l(mMutex);
Ari Hausman-Cohen24628312018-08-13 15:01:09 -0700415
416 // Check each source type.
Andy Hung43119fb2023-12-26 19:26:35 -0800417 for (auto& [source, descVector] : mInputSources) {
Ari Hausman-Cohen24628312018-08-13 15:01:09 -0700418 // Check each effect for each source.
Andy Hungf42175b2023-12-19 19:03:19 -0800419 for (auto desc = descVector->begin(); desc != descVector->end(); ++desc) {
Ari Hausman-Cohen24628312018-08-13 15:01:09 -0700420 if ((*desc)->mId == id) {
421 // Found it!
422 // TODO(b/71814300): Remove from any sources the effect was attached to.
Andy Hungf42175b2023-12-19 19:03:19 -0800423 descVector->erase(desc);
Ari Hausman-Cohen24628312018-08-13 15:01:09 -0700424 // Handles are unique; there can only be one match, so return early.
425 return NO_ERROR;
426 }
427 }
428 }
429
430 // Effect wasn't found, so it's been trivially removed successfully.
431 return NO_ERROR;
432}
433
Ari Hausman-Cohen433722e2018-04-24 14:25:22 -0700434status_t AudioPolicyEffects::removeStreamDefaultEffect(audio_unique_id_t id)
435{
436 if (id == AUDIO_UNIQUE_ID_ALLOCATE) {
437 // ALLOCATE is not a unique identifier, but rather a reserved value indicating
438 // a real id has not been assigned. For default effects, this value is only used
439 // by system-owned defaults from the loaded config, which cannot be removed.
440 return BAD_VALUE;
441 }
442
Andy Hung79eacdb2023-11-30 19:34:24 -0800443 audio_utils::lock_guard _l(mMutex);
Ari Hausman-Cohen433722e2018-04-24 14:25:22 -0700444
445 // Check each stream type.
Andy Hung43119fb2023-12-26 19:26:35 -0800446 for (auto& [stream, descVector] : mOutputStreams) {
Ari Hausman-Cohen433722e2018-04-24 14:25:22 -0700447 // Check each effect for each stream.
Andy Hungf42175b2023-12-19 19:03:19 -0800448 for (auto desc = descVector->begin(); desc != descVector->end(); ++desc) {
Ari Hausman-Cohen433722e2018-04-24 14:25:22 -0700449 if ((*desc)->mId == id) {
450 // Found it!
451 // TODO(b/71814300): Remove from any streams the effect was attached to.
Andy Hungf42175b2023-12-19 19:03:19 -0800452 descVector->erase(desc);
Ari Hausman-Cohen433722e2018-04-24 14:25:22 -0700453 // Handles are unique; there can only be one match, so return early.
454 return NO_ERROR;
455 }
456 }
457 }
458
459 // Effect wasn't found, so it's been trivially removed successfully.
460 return NO_ERROR;
461}
bryant_liuba2b4392014-06-11 16:49:30 +0800462
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700463void AudioPolicyEffects::EffectVector::setProcessorEnabled(bool enabled)
bryant_liuba2b4392014-06-11 16:49:30 +0800464{
Andy Hung43119fb2023-12-26 19:26:35 -0800465 for (const auto& effect : mEffects) {
466 effect->setEnabled(enabled);
bryant_liuba2b4392014-06-11 16:49:30 +0800467 }
468}
469
470
471// ----------------------------------------------------------------------------
472// Audio processing configuration
473// ----------------------------------------------------------------------------
474
Andy Hungd3595ed2023-12-19 15:34:46 -0800475// we keep to const char* instead of std::string_view as comparison is believed faster.
476constexpr const char* kInputSourceNames[AUDIO_SOURCE_CNT - 1] = {
bryant_liuba2b4392014-06-11 16:49:30 +0800477 MIC_SRC_TAG,
478 VOICE_UL_SRC_TAG,
479 VOICE_DL_SRC_TAG,
480 VOICE_CALL_SRC_TAG,
481 CAMCORDER_SRC_TAG,
482 VOICE_REC_SRC_TAG,
rago8a397d52015-12-02 11:27:57 -0800483 VOICE_COMM_SRC_TAG,
Carter Hsua3abb402021-10-26 11:11:20 +0800484 REMOTE_SUBMIX_SRC_TAG,
Eric Laurentae4b6ec2019-01-15 18:34:38 -0800485 UNPROCESSED_SRC_TAG,
486 VOICE_PERFORMANCE_SRC_TAG
bryant_liuba2b4392014-06-11 16:49:30 +0800487};
488
489// returns the audio_source_t enum corresponding to the input source name or
490// AUDIO_SOURCE_CNT is no match found
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700491/*static*/ audio_source_t AudioPolicyEffects::inputSourceNameToEnum(const char *name)
bryant_liuba2b4392014-06-11 16:49:30 +0800492{
493 int i;
494 for (i = AUDIO_SOURCE_MIC; i < AUDIO_SOURCE_CNT; i++) {
495 if (strcmp(name, kInputSourceNames[i - AUDIO_SOURCE_MIC]) == 0) {
496 ALOGV("inputSourceNameToEnum found source %s %d", name, i);
497 break;
498 }
499 }
500 return (audio_source_t)i;
501}
502
Andy Hungd3595ed2023-12-19 15:34:46 -0800503// +1 as enum starts from -1
504constexpr const char* kStreamNames[AUDIO_STREAM_PUBLIC_CNT + 1] = {
bryant_liuba2b4392014-06-11 16:49:30 +0800505 AUDIO_STREAM_DEFAULT_TAG,
506 AUDIO_STREAM_VOICE_CALL_TAG,
507 AUDIO_STREAM_SYSTEM_TAG,
508 AUDIO_STREAM_RING_TAG,
509 AUDIO_STREAM_MUSIC_TAG,
510 AUDIO_STREAM_ALARM_TAG,
511 AUDIO_STREAM_NOTIFICATION_TAG,
512 AUDIO_STREAM_BLUETOOTH_SCO_TAG,
513 AUDIO_STREAM_ENFORCED_AUDIBLE_TAG,
514 AUDIO_STREAM_DTMF_TAG,
Baekgyeong Kim3a26bb22019-10-30 20:29:41 +0900515 AUDIO_STREAM_TTS_TAG,
516 AUDIO_STREAM_ASSISTANT_TAG
bryant_liuba2b4392014-06-11 16:49:30 +0800517};
518
519// returns the audio_stream_t enum corresponding to the output stream name or
Eric Laurent223fd5c2014-11-11 13:43:36 -0800520// AUDIO_STREAM_PUBLIC_CNT is no match found
Andy Hungd3595ed2023-12-19 15:34:46 -0800521/* static */
bryant_liuba2b4392014-06-11 16:49:30 +0800522audio_stream_type_t AudioPolicyEffects::streamNameToEnum(const char *name)
523{
524 int i;
Eric Laurent223fd5c2014-11-11 13:43:36 -0800525 for (i = AUDIO_STREAM_DEFAULT; i < AUDIO_STREAM_PUBLIC_CNT; i++) {
bryant_liuba2b4392014-06-11 16:49:30 +0800526 if (strcmp(name, kStreamNames[i - AUDIO_STREAM_DEFAULT]) == 0) {
527 ALOGV("streamNameToEnum found stream %s %d", name, i);
528 break;
529 }
530 }
531 return (audio_stream_type_t)i;
532}
533
534// ----------------------------------------------------------------------------
535// Audio Effect Config parser
536// ----------------------------------------------------------------------------
537
Andy Hungd3595ed2023-12-19 15:34:46 -0800538/* static */
Eric Laurent138ed172016-02-10 10:40:44 -0800539size_t AudioPolicyEffects::growParamSize(char **param,
bryant_liuba2b4392014-06-11 16:49:30 +0800540 size_t size,
541 size_t *curSize,
542 size_t *totSize)
543{
544 // *curSize is at least sizeof(effect_param_t) + 2 * sizeof(int)
545 size_t pos = ((*curSize - 1 ) / size + 1) * size;
546
547 if (pos + size > *totSize) {
548 while (pos + size > *totSize) {
549 *totSize += ((*totSize + 7) / 8) * 4;
550 }
George Burgess IV31225682018-02-12 11:08:38 -0800551 char *newParam = (char *)realloc(*param, *totSize);
552 if (newParam == NULL) {
Eric Laurent138ed172016-02-10 10:40:44 -0800553 ALOGE("%s realloc error for size %zu", __func__, *totSize);
554 return 0;
555 }
George Burgess IV31225682018-02-12 11:08:38 -0800556 *param = newParam;
bryant_liuba2b4392014-06-11 16:49:30 +0800557 }
558 *curSize = pos + size;
559 return pos;
560}
561
Andy Hungd3595ed2023-12-19 15:34:46 -0800562/* static */
bryant_liuba2b4392014-06-11 16:49:30 +0800563size_t AudioPolicyEffects::readParamValue(cnode *node,
Eric Laurent138ed172016-02-10 10:40:44 -0800564 char **param,
bryant_liuba2b4392014-06-11 16:49:30 +0800565 size_t *curSize,
566 size_t *totSize)
567{
Eric Laurent138ed172016-02-10 10:40:44 -0800568 size_t len = 0;
569 size_t pos;
570
bryant_liuba2b4392014-06-11 16:49:30 +0800571 if (strncmp(node->name, SHORT_TAG, sizeof(SHORT_TAG) + 1) == 0) {
Eric Laurent138ed172016-02-10 10:40:44 -0800572 pos = growParamSize(param, sizeof(short), curSize, totSize);
573 if (pos == 0) {
574 goto exit;
bryant_liuba2b4392014-06-11 16:49:30 +0800575 }
Eric Laurent138ed172016-02-10 10:40:44 -0800576 *(short *)(*param + pos) = (short)atoi(node->value);
577 ALOGV("readParamValue() reading short %d", *(short *)(*param + pos));
578 len = sizeof(short);
579 } else if (strncmp(node->name, INT_TAG, sizeof(INT_TAG) + 1) == 0) {
580 pos = growParamSize(param, sizeof(int), curSize, totSize);
581 if (pos == 0) {
582 goto exit;
583 }
584 *(int *)(*param + pos) = atoi(node->value);
585 ALOGV("readParamValue() reading int %d", *(int *)(*param + pos));
586 len = sizeof(int);
587 } else if (strncmp(node->name, FLOAT_TAG, sizeof(FLOAT_TAG) + 1) == 0) {
588 pos = growParamSize(param, sizeof(float), curSize, totSize);
589 if (pos == 0) {
590 goto exit;
591 }
592 *(float *)(*param + pos) = (float)atof(node->value);
593 ALOGV("readParamValue() reading float %f",*(float *)(*param + pos));
594 len = sizeof(float);
595 } else if (strncmp(node->name, BOOL_TAG, sizeof(BOOL_TAG) + 1) == 0) {
596 pos = growParamSize(param, sizeof(bool), curSize, totSize);
597 if (pos == 0) {
598 goto exit;
599 }
600 if (strncmp(node->value, "true", strlen("true") + 1) == 0) {
601 *(bool *)(*param + pos) = true;
602 } else {
603 *(bool *)(*param + pos) = false;
604 }
605 ALOGV("readParamValue() reading bool %s",
606 *(bool *)(*param + pos) ? "true" : "false");
607 len = sizeof(bool);
bryant_liuba2b4392014-06-11 16:49:30 +0800608 } else if (strncmp(node->name, STRING_TAG, sizeof(STRING_TAG) + 1) == 0) {
Eric Laurent138ed172016-02-10 10:40:44 -0800609 len = strnlen(node->value, EFFECT_STRING_LEN_MAX);
bryant_liuba2b4392014-06-11 16:49:30 +0800610 if (*curSize + len + 1 > *totSize) {
611 *totSize = *curSize + len + 1;
Chih-Hung Hsieh03077682018-08-30 14:11:00 -0700612 char *newParam = (char *)realloc(*param, *totSize);
613 if (newParam == NULL) {
Eric Laurent138ed172016-02-10 10:40:44 -0800614 len = 0;
615 ALOGE("%s realloc error for string len %zu", __func__, *totSize);
616 goto exit;
617 }
Chih-Hung Hsieh03077682018-08-30 14:11:00 -0700618 *param = newParam;
bryant_liuba2b4392014-06-11 16:49:30 +0800619 }
Eric Laurent138ed172016-02-10 10:40:44 -0800620 strncpy(*param + *curSize, node->value, len);
bryant_liuba2b4392014-06-11 16:49:30 +0800621 *curSize += len;
Eric Laurent138ed172016-02-10 10:40:44 -0800622 (*param)[*curSize] = '\0';
623 ALOGV("readParamValue() reading string %s", *param + *curSize - len);
624 } else {
625 ALOGW("readParamValue() unknown param type %s", node->name);
bryant_liuba2b4392014-06-11 16:49:30 +0800626 }
Eric Laurent138ed172016-02-10 10:40:44 -0800627exit:
628 return len;
bryant_liuba2b4392014-06-11 16:49:30 +0800629}
630
Andy Hungd3595ed2023-12-19 15:34:46 -0800631/* static */
Andy Hung7760a852023-12-19 17:27:52 -0800632std::shared_ptr<const effect_param_t> AudioPolicyEffects::loadEffectParameter(cnode* root)
bryant_liuba2b4392014-06-11 16:49:30 +0800633{
634 cnode *param;
635 cnode *value;
636 size_t curSize = sizeof(effect_param_t);
637 size_t totSize = sizeof(effect_param_t) + 2 * sizeof(int);
638 effect_param_t *fx_param = (effect_param_t *)malloc(totSize);
639
Eric Laurent138ed172016-02-10 10:40:44 -0800640 if (fx_param == NULL) {
641 ALOGE("%s malloc error for effect structure of size %zu",
642 __func__, totSize);
643 return NULL;
644 }
645
bryant_liuba2b4392014-06-11 16:49:30 +0800646 param = config_find(root, PARAM_TAG);
647 value = config_find(root, VALUE_TAG);
648 if (param == NULL && value == NULL) {
649 // try to parse simple parameter form {int int}
650 param = root->first_child;
651 if (param != NULL) {
652 // Note: that a pair of random strings is read as 0 0
653 int *ptr = (int *)fx_param->data;
Eric Laurent138ed172016-02-10 10:40:44 -0800654#if LOG_NDEBUG == 0
bryant_liuba2b4392014-06-11 16:49:30 +0800655 int *ptr2 = (int *)((char *)param + sizeof(effect_param_t));
Eric Laurent138ed172016-02-10 10:40:44 -0800656 ALOGV("loadEffectParameter() ptr %p ptr2 %p", ptr, ptr2);
657#endif
bryant_liuba2b4392014-06-11 16:49:30 +0800658 *ptr++ = atoi(param->name);
659 *ptr = atoi(param->value);
660 fx_param->psize = sizeof(int);
661 fx_param->vsize = sizeof(int);
Andy Hung7760a852023-12-19 17:27:52 -0800662 return {fx_param, free};
bryant_liuba2b4392014-06-11 16:49:30 +0800663 }
664 }
665 if (param == NULL || value == NULL) {
Eric Laurent138ed172016-02-10 10:40:44 -0800666 ALOGW("loadEffectParameter() invalid parameter description %s",
667 root->name);
bryant_liuba2b4392014-06-11 16:49:30 +0800668 goto error;
669 }
670
671 fx_param->psize = 0;
672 param = param->first_child;
673 while (param) {
674 ALOGV("loadEffectParameter() reading param of type %s", param->name);
Eric Laurent138ed172016-02-10 10:40:44 -0800675 size_t size =
676 readParamValue(param, (char **)&fx_param, &curSize, &totSize);
bryant_liuba2b4392014-06-11 16:49:30 +0800677 if (size == 0) {
678 goto error;
679 }
680 fx_param->psize += size;
681 param = param->next;
682 }
683
684 // align start of value field on 32 bit boundary
685 curSize = ((curSize - 1 ) / sizeof(int) + 1) * sizeof(int);
686
687 fx_param->vsize = 0;
688 value = value->first_child;
689 while (value) {
690 ALOGV("loadEffectParameter() reading value of type %s", value->name);
Eric Laurent138ed172016-02-10 10:40:44 -0800691 size_t size =
692 readParamValue(value, (char **)&fx_param, &curSize, &totSize);
bryant_liuba2b4392014-06-11 16:49:30 +0800693 if (size == 0) {
694 goto error;
695 }
696 fx_param->vsize += size;
697 value = value->next;
698 }
699
Andy Hung7760a852023-12-19 17:27:52 -0800700 return {fx_param, free};
bryant_liuba2b4392014-06-11 16:49:30 +0800701
702error:
Eric Laurent138ed172016-02-10 10:40:44 -0800703 free(fx_param);
bryant_liuba2b4392014-06-11 16:49:30 +0800704 return NULL;
705}
706
Andy Hungd3595ed2023-12-19 15:34:46 -0800707/* static */
Andy Hung7760a852023-12-19 17:27:52 -0800708void AudioPolicyEffects::loadEffectParameters(
709 cnode* root, std::vector<std::shared_ptr<const effect_param_t>>& params)
bryant_liuba2b4392014-06-11 16:49:30 +0800710{
711 cnode *node = root->first_child;
712 while (node) {
713 ALOGV("loadEffectParameters() loading param %s", node->name);
Andy Hung7760a852023-12-19 17:27:52 -0800714 const auto param = loadEffectParameter(node);
715 if (param != nullptr) {
716 params.push_back(param);
bryant_liuba2b4392014-06-11 16:49:30 +0800717 }
bryant_liuba2b4392014-06-11 16:49:30 +0800718 node = node->next;
719 }
720}
721
Andy Hungd3595ed2023-12-19 15:34:46 -0800722/* static */
Andy Hungf42175b2023-12-19 19:03:19 -0800723std::shared_ptr<AudioPolicyEffects::EffectDescVector> AudioPolicyEffects::loadEffectConfig(
724 cnode* root, const EffectDescVector& effects)
bryant_liuba2b4392014-06-11 16:49:30 +0800725{
726 cnode *node = root->first_child;
727 if (node == NULL) {
728 ALOGW("loadInputSource() empty element %s", root->name);
729 return NULL;
730 }
Andy Hungf42175b2023-12-19 19:03:19 -0800731 auto desc = std::make_shared<EffectDescVector>();
bryant_liuba2b4392014-06-11 16:49:30 +0800732 while (node) {
733 size_t i;
Eric Laurent138ed172016-02-10 10:40:44 -0800734
bryant_liuba2b4392014-06-11 16:49:30 +0800735 for (i = 0; i < effects.size(); i++) {
Andy Hung7760a852023-12-19 17:27:52 -0800736 if (effects[i]->mName == node->name) {
bryant_liuba2b4392014-06-11 16:49:30 +0800737 ALOGV("loadEffectConfig() found effect %s in list", node->name);
738 break;
739 }
740 }
741 if (i == effects.size()) {
742 ALOGV("loadEffectConfig() effect %s not in list", node->name);
743 node = node->next;
744 continue;
745 }
Andy Hungf42175b2023-12-19 19:03:19 -0800746 auto effect = std::make_shared<EffectDesc>(*effects[i]); // deep copy
bryant_liuba2b4392014-06-11 16:49:30 +0800747 loadEffectParameters(node, effect->mParams);
748 ALOGV("loadEffectConfig() adding effect %s uuid %08x",
Andy Hung7760a852023-12-19 17:27:52 -0800749 effect->mName.c_str(), effect->mUuid.timeLow);
Andy Hungf42175b2023-12-19 19:03:19 -0800750 desc->push_back(std::move(effect));
bryant_liuba2b4392014-06-11 16:49:30 +0800751 node = node->next;
752 }
Andy Hungf42175b2023-12-19 19:03:19 -0800753 if (desc->empty()) {
bryant_liuba2b4392014-06-11 16:49:30 +0800754 ALOGW("loadEffectConfig() no valid effects found in config %s", root->name);
Andy Hungf42175b2023-12-19 19:03:19 -0800755 return nullptr;
bryant_liuba2b4392014-06-11 16:49:30 +0800756 }
757 return desc;
758}
759
Andy Hungd3595ed2023-12-19 15:34:46 -0800760status_t AudioPolicyEffects::loadInputEffectConfigurations_l(cnode* root,
Andy Hungf42175b2023-12-19 19:03:19 -0800761 const EffectDescVector& effects)
bryant_liuba2b4392014-06-11 16:49:30 +0800762{
763 cnode *node = config_find(root, PREPROCESSING_TAG);
764 if (node == NULL) {
765 return -ENOENT;
766 }
767 node = node->first_child;
768 while (node) {
769 audio_source_t source = inputSourceNameToEnum(node->name);
770 if (source == AUDIO_SOURCE_CNT) {
Andy Hungd3595ed2023-12-19 15:34:46 -0800771 ALOGW("%s() invalid input source %s", __func__, node->name);
bryant_liuba2b4392014-06-11 16:49:30 +0800772 node = node->next;
773 continue;
774 }
Andy Hungd3595ed2023-12-19 15:34:46 -0800775 ALOGV("%s() loading input source %s", __func__, node->name);
Andy Hungf42175b2023-12-19 19:03:19 -0800776 auto desc = loadEffectConfig(node, effects);
bryant_liuba2b4392014-06-11 16:49:30 +0800777 if (desc == NULL) {
778 node = node->next;
779 continue;
780 }
Andy Hung43119fb2023-12-26 19:26:35 -0800781 mInputSources[source] = std::move(desc);
bryant_liuba2b4392014-06-11 16:49:30 +0800782 node = node->next;
783 }
784 return NO_ERROR;
785}
786
Andy Hungd3595ed2023-12-19 15:34:46 -0800787status_t AudioPolicyEffects::loadStreamEffectConfigurations_l(cnode* root,
Andy Hungf42175b2023-12-19 19:03:19 -0800788 const EffectDescVector& effects)
bryant_liuba2b4392014-06-11 16:49:30 +0800789{
790 cnode *node = config_find(root, OUTPUT_SESSION_PROCESSING_TAG);
791 if (node == NULL) {
792 return -ENOENT;
793 }
794 node = node->first_child;
795 while (node) {
796 audio_stream_type_t stream = streamNameToEnum(node->name);
Eric Laurent223fd5c2014-11-11 13:43:36 -0800797 if (stream == AUDIO_STREAM_PUBLIC_CNT) {
Andy Hungd3595ed2023-12-19 15:34:46 -0800798 ALOGW("%s() invalid output stream %s", __func__, node->name);
bryant_liuba2b4392014-06-11 16:49:30 +0800799 node = node->next;
800 continue;
801 }
Andy Hungd3595ed2023-12-19 15:34:46 -0800802 ALOGV("%s() loading output stream %s", __func__, node->name);
Andy Hungf42175b2023-12-19 19:03:19 -0800803 std::shared_ptr<EffectDescVector> desc = loadEffectConfig(node, effects);
bryant_liuba2b4392014-06-11 16:49:30 +0800804 if (desc == NULL) {
805 node = node->next;
806 continue;
807 }
Andy Hung43119fb2023-12-26 19:26:35 -0800808 mOutputStreams[stream] = std::move(desc);
bryant_liuba2b4392014-06-11 16:49:30 +0800809 node = node->next;
810 }
811 return NO_ERROR;
812}
813
Andy Hungd3595ed2023-12-19 15:34:46 -0800814/* static */
Andy Hungf42175b2023-12-19 19:03:19 -0800815std::shared_ptr<AudioPolicyEffects::EffectDesc> AudioPolicyEffects::loadEffect(cnode* root)
bryant_liuba2b4392014-06-11 16:49:30 +0800816{
817 cnode *node = config_find(root, UUID_TAG);
818 if (node == NULL) {
819 return NULL;
820 }
821 effect_uuid_t uuid;
822 if (AudioEffect::stringToGuid(node->value, &uuid) != NO_ERROR) {
823 ALOGW("loadEffect() invalid uuid %s", node->value);
824 return NULL;
825 }
Andy Hungf42175b2023-12-19 19:03:19 -0800826 return std::make_shared<EffectDesc>(root->name, uuid);
bryant_liuba2b4392014-06-11 16:49:30 +0800827}
828
Andy Hungd3595ed2023-12-19 15:34:46 -0800829/* static */
Andy Hungf42175b2023-12-19 19:03:19 -0800830android::AudioPolicyEffects::EffectDescVector AudioPolicyEffects::loadEffects(cnode *root)
bryant_liuba2b4392014-06-11 16:49:30 +0800831{
Andy Hungf42175b2023-12-19 19:03:19 -0800832 EffectDescVector effects;
bryant_liuba2b4392014-06-11 16:49:30 +0800833 cnode *node = config_find(root, EFFECTS_TAG);
834 if (node == NULL) {
Andy Hungf42175b2023-12-19 19:03:19 -0800835 ALOGW("%s() Cannot find %s configuration", __func__, EFFECTS_TAG);
836 return effects;
bryant_liuba2b4392014-06-11 16:49:30 +0800837 }
838 node = node->first_child;
839 while (node) {
840 ALOGV("loadEffects() loading effect %s", node->name);
Andy Hungf42175b2023-12-19 19:03:19 -0800841 auto effect = loadEffect(node);
bryant_liuba2b4392014-06-11 16:49:30 +0800842 if (effect == NULL) {
843 node = node->next;
844 continue;
845 }
Andy Hungf42175b2023-12-19 19:03:19 -0800846 effects.push_back(std::move(effect));
bryant_liuba2b4392014-06-11 16:49:30 +0800847 node = node->next;
848 }
Andy Hungf42175b2023-12-19 19:03:19 -0800849 return effects;
bryant_liuba2b4392014-06-11 16:49:30 +0800850}
851
Andy Hungd3595ed2023-12-19 15:34:46 -0800852status_t AudioPolicyEffects::loadAudioEffectConfig_ll(
Shunkai Yao8d6489a2023-04-18 23:14:25 +0000853 const sp<EffectsFactoryHalInterface>& effectsFactoryHal) {
854 if (!effectsFactoryHal) {
855 ALOGE("%s Null EffectsFactoryHalInterface", __func__);
856 return UNEXPECTED_NULL;
857 }
858
859 const auto skippedElements = VALUE_OR_RETURN_STATUS(effectsFactoryHal->getSkippedElements());
860 const auto processings = effectsFactoryHal->getProcessings();
861 if (!processings) {
862 ALOGE("%s Null processings with %zu skipped elements", __func__, skippedElements);
863 return UNEXPECTED_NULL;
Kevin Rocard4fb615c2017-06-26 10:28:13 -0700864 }
865
866 auto loadProcessingChain = [](auto& processingChain, auto& streams) {
867 for (auto& stream : processingChain) {
Andy Hungf42175b2023-12-19 19:03:19 -0800868 auto effectDescs = std::make_shared<EffectDescVector>();
Kevin Rocard4fb615c2017-06-26 10:28:13 -0700869 for (auto& effect : stream.effects) {
Andy Hungf42175b2023-12-19 19:03:19 -0800870 effectDescs->push_back(
Andy Hungbb2f2bf2023-12-27 13:17:16 -0800871 std::make_shared<EffectDesc>(effect->name, effect->uuid));
Kevin Rocard4fb615c2017-06-26 10:28:13 -0700872 }
Andy Hung43119fb2023-12-26 19:26:35 -0800873 streams[stream.type] = std::move(effectDescs);
Kevin Rocard4fb615c2017-06-26 10:28:13 -0700874 }
875 };
François Gaffie06182982020-01-07 15:16:14 +0100876
Shunkai Yao8d6489a2023-04-18 23:14:25 +0000877 auto loadDeviceProcessingChain = [](auto& processingChain, auto& devicesEffects) {
François Gaffie06182982020-01-07 15:16:14 +0100878 for (auto& deviceProcess : processingChain) {
François Gaffie06182982020-01-07 15:16:14 +0100879 auto effectDescs = std::make_unique<EffectDescVector>();
880 for (auto& effect : deviceProcess.effects) {
Andy Hungf42175b2023-12-19 19:03:19 -0800881 effectDescs->push_back(
Andy Hungbb2f2bf2023-12-27 13:17:16 -0800882 std::make_shared<EffectDesc>(effect->name, effect->uuid));
François Gaffie06182982020-01-07 15:16:14 +0100883 }
Andy Hungf42175b2023-12-19 19:03:19 -0800884 auto devEffects = std::make_unique<DeviceEffects>(
François Gaffie06182982020-01-07 15:16:14 +0100885 std::move(effectDescs), deviceProcess.type, deviceProcess.address);
Andy Hungf42175b2023-12-19 19:03:19 -0800886 devicesEffects.emplace(deviceProcess.address, std::move(devEffects));
François Gaffie06182982020-01-07 15:16:14 +0100887 }
888 };
889
Andy Hungd3595ed2023-12-19 15:34:46 -0800890 // access to mInputSources and mOutputStreams requires mMutex;
Shunkai Yao8d6489a2023-04-18 23:14:25 +0000891 loadProcessingChain(processings->preprocess, mInputSources);
892 loadProcessingChain(processings->postprocess, mOutputStreams);
893
Andy Hungd3595ed2023-12-19 15:34:46 -0800894 // access to mDeviceEffects requires mDeviceEffectsMutex
895 loadDeviceProcessingChain(processings->deviceprocess, mDeviceEffects);
Shunkai Yao8d6489a2023-04-18 23:14:25 +0000896
897 return skippedElements;
Kevin Rocard4fb615c2017-06-26 10:28:13 -0700898}
899
Andy Hungd3595ed2023-12-19 15:34:46 -0800900status_t AudioPolicyEffects::loadAudioEffectConfigLegacy_l(const char *path)
Shunkai Yaoeab8a7c2023-05-15 21:07:08 +0000901{
902 cnode *root;
903 char *data;
904
905 data = (char *)load_file(path, NULL);
906 if (data == NULL) {
907 return -ENODEV;
908 }
909 root = config_node("", "");
910 config_load(root, data);
911
Andy Hungf42175b2023-12-19 19:03:19 -0800912 const EffectDescVector effects = loadEffects(root);
Andy Hungd3595ed2023-12-19 15:34:46 -0800913
914 // requires mMutex
915 loadInputEffectConfigurations_l(root, effects);
916 loadStreamEffectConfigurations_l(root, effects);
Shunkai Yaoeab8a7c2023-05-15 21:07:08 +0000917 config_free(root);
918 free(root);
919 free(data);
920
921 return NO_ERROR;
922}
923
François Gaffie06182982020-01-07 15:16:14 +0100924void AudioPolicyEffects::initDefaultDeviceEffects()
925{
Andy Hungd3595ed2023-12-19 15:34:46 -0800926 std::lock_guard _l(mDeviceEffectsMutex);
François Gaffie06182982020-01-07 15:16:14 +0100927 for (const auto& deviceEffectsIter : mDeviceEffects) {
928 const auto& deviceEffects = deviceEffectsIter.second;
Andy Hungf42175b2023-12-19 19:03:19 -0800929 for (const auto& effectDesc : *deviceEffects->mEffectDescriptors) {
Svet Ganov3e5f14f2021-05-13 22:51:08 +0000930 AttributionSourceState attributionSource;
931 attributionSource.packageName = "android";
932 attributionSource.token = sp<BBinder>::make();
Andy Hungf42175b2023-12-19 19:03:19 -0800933 sp<AudioEffect> fx = sp<AudioEffect>::make(attributionSource);
Atneya Nair884f7992022-05-17 19:22:42 -0400934 fx->set(EFFECT_UUID_NULL, &effectDesc->mUuid, 0 /* priority */, nullptr /* callback */,
935 AUDIO_SESSION_DEVICE, AUDIO_IO_HANDLE_NONE,
Mikhail Naganov69d41cc2020-07-31 17:36:08 -0700936 AudioDeviceTypeAddr{deviceEffects->getDeviceType(),
937 deviceEffects->getDeviceAddress()});
François Gaffie06182982020-01-07 15:16:14 +0100938 status_t status = fx->initCheck();
939 if (status != NO_ERROR && status != ALREADY_EXISTS) {
940 ALOGE("%s(): failed to create Fx %s on port type=%d address=%s", __func__,
Andy Hung7760a852023-12-19 17:27:52 -0800941 effectDesc->mName.c_str(), deviceEffects->getDeviceType(),
François Gaffie06182982020-01-07 15:16:14 +0100942 deviceEffects->getDeviceAddress().c_str());
943 // fx goes out of scope and strong ref on AudioEffect is released
944 continue;
945 }
946 fx->setEnabled(true);
947 ALOGV("%s(): create Fx %s added on port type=%d address=%s", __func__,
Andy Hung7760a852023-12-19 17:27:52 -0800948 effectDesc->mName.c_str(), deviceEffects->getDeviceType(),
François Gaffie06182982020-01-07 15:16:14 +0100949 deviceEffects->getDeviceAddress().c_str());
Andy Hungf42175b2023-12-19 19:03:19 -0800950 deviceEffects->mEffects.push_back(std::move(fx));
François Gaffie06182982020-01-07 15:16:14 +0100951 }
952 }
953}
bryant_liuba2b4392014-06-11 16:49:30 +0800954
Mikhail Naganov1b2a7942017-12-08 10:18:09 -0800955} // namespace android