blob: d67ddb6d4567ed15c96700121b7d7bb22597e3c5 [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
bryant_liuba2b4392014-06-11 16:49:30 +080064status_t AudioPolicyEffects::addInputEffects(audio_io_handle_t input,
65 audio_source_t inputSource,
Eric Laurentfb66dd92016-01-28 18:32:03 -080066 audio_session_t audioSession)
bryant_liuba2b4392014-06-11 16:49:30 +080067{
68 status_t status = NO_ERROR;
69
70 // create audio pre processors according to input source
71 audio_source_t aliasSource = (inputSource == AUDIO_SOURCE_HOTWORD) ?
72 AUDIO_SOURCE_VOICE_RECOGNITION : inputSource;
73
Andy Hung79eacdb2023-11-30 19:34:24 -080074 audio_utils::lock_guard _l(mMutex);
Andy Hung43119fb2023-12-26 19:26:35 -080075 auto sourceIt = mInputSources.find(aliasSource);
76 if (sourceIt == mInputSources.end()) {
bryant_liuba2b4392014-06-11 16:49:30 +080077 ALOGV("addInputEffects(): no processing needs to be attached to this source");
78 return status;
79 }
Andy Hung43119fb2023-12-26 19:26:35 -080080 std::shared_ptr<EffectVector>& sessionDesc = mInputSessions[audioSession];
81 if (sessionDesc == nullptr) {
Andy Hungf42175b2023-12-19 19:03:19 -080082 sessionDesc = std::make_shared<EffectVector>(audioSession);
bryant_liuba2b4392014-06-11 16:49:30 +080083 }
Eric Laurentfb66dd92016-01-28 18:32:03 -080084 sessionDesc->mRefCount++;
bryant_liu890a5632014-08-20 18:06:13 +080085
Eric Laurentfb66dd92016-01-28 18:32:03 -080086 ALOGV("addInputEffects(): input: %d, refCount: %d", input, sessionDesc->mRefCount);
87 if (sessionDesc->mRefCount == 1) {
Eric Laurentb6436272016-12-07 19:24:50 -080088 int64_t token = IPCThreadState::self()->clearCallingIdentity();
Andy Hung43119fb2023-12-26 19:26:35 -080089 const std::shared_ptr<EffectDescVector>& effects = sourceIt->second;
Andy Hungf42175b2023-12-19 19:03:19 -080090 for (const std::shared_ptr<EffectDesc>& effect : *effects) {
Svet Ganov3e5f14f2021-05-13 22:51:08 +000091 AttributionSourceState attributionSource;
92 attributionSource.packageName = "android";
93 attributionSource.token = sp<BBinder>::make();
Andy Hungf42175b2023-12-19 19:03:19 -080094 auto fx = sp<AudioEffect>::make(attributionSource);
Atneya Nair884f7992022-05-17 19:22:42 -040095 fx->set(nullptr /*type */, &effect->mUuid, -1 /* priority */, nullptr /* callback */,
96 audioSession, input);
Eric Laurent7de5ac12014-10-21 09:07:11 -070097 status_t status = fx->initCheck();
98 if (status != NO_ERROR && status != ALREADY_EXISTS) {
99 ALOGW("addInputEffects(): failed to create Fx %s on source %d",
Andy Hung7760a852023-12-19 17:27:52 -0800100 effect->mName.c_str(), (int32_t)aliasSource);
Eric Laurent7de5ac12014-10-21 09:07:11 -0700101 // fx goes out of scope and strong ref on AudioEffect is released
102 continue;
103 }
104 for (size_t j = 0; j < effect->mParams.size(); j++) {
Andy Hung7760a852023-12-19 17:27:52 -0800105 // const_cast here due to API.
106 fx->setParameter(const_cast<effect_param_t*>(effect->mParams[j].get()));
Eric Laurent7de5ac12014-10-21 09:07:11 -0700107 }
108 ALOGV("addInputEffects(): added Fx %s on source: %d",
Andy Hung7760a852023-12-19 17:27:52 -0800109 effect->mName.c_str(), (int32_t)aliasSource);
Andy Hungf42175b2023-12-19 19:03:19 -0800110 sessionDesc->mEffects.push_back(std::move(fx));
bryant_liuba2b4392014-06-11 16:49:30 +0800111 }
Eric Laurentfb66dd92016-01-28 18:32:03 -0800112 sessionDesc->setProcessorEnabled(true);
Eric Laurentb6436272016-12-07 19:24:50 -0800113 IPCThreadState::self()->restoreCallingIdentity(token);
bryant_liuba2b4392014-06-11 16:49:30 +0800114 }
bryant_liuba2b4392014-06-11 16:49:30 +0800115 return status;
116}
117
118
Eric Laurentfb66dd92016-01-28 18:32:03 -0800119status_t AudioPolicyEffects::releaseInputEffects(audio_io_handle_t input,
120 audio_session_t audioSession)
bryant_liuba2b4392014-06-11 16:49:30 +0800121{
122 status_t status = NO_ERROR;
123
Andy Hung79eacdb2023-11-30 19:34:24 -0800124 audio_utils::lock_guard _l(mMutex);
Andy Hung43119fb2023-12-26 19:26:35 -0800125 auto it = mInputSessions.find(audioSession);
126 if (it == mInputSessions.end()) {
bryant_liuba2b4392014-06-11 16:49:30 +0800127 return status;
128 }
Andy Hung43119fb2023-12-26 19:26:35 -0800129 std::shared_ptr<EffectVector> sessionDesc = it->second;
Eric Laurentfb66dd92016-01-28 18:32:03 -0800130 sessionDesc->mRefCount--;
131 ALOGV("releaseInputEffects(): input: %d, refCount: %d", input, sessionDesc->mRefCount);
132 if (sessionDesc->mRefCount == 0) {
133 sessionDesc->setProcessorEnabled(false);
Andy Hung43119fb2023-12-26 19:26:35 -0800134 mInputSessions.erase(it);
bryant_liu890a5632014-08-20 18:06:13 +0800135 ALOGV("releaseInputEffects(): all effects released");
136 }
bryant_liuba2b4392014-06-11 16:49:30 +0800137 return status;
138}
139
Eric Laurentfb66dd92016-01-28 18:32:03 -0800140status_t AudioPolicyEffects::queryDefaultInputEffects(audio_session_t audioSession,
bryant_liuba2b4392014-06-11 16:49:30 +0800141 effect_descriptor_t *descriptors,
142 uint32_t *count)
143{
144 status_t status = NO_ERROR;
145
Andy Hung79eacdb2023-11-30 19:34:24 -0800146 audio_utils::lock_guard _l(mMutex);
Andy Hung43119fb2023-12-26 19:26:35 -0800147 auto it = mInputSessions.find(audioSession);
148 if (it == mInputSessions.end()) {
bryant_liuba2b4392014-06-11 16:49:30 +0800149 *count = 0;
150 return BAD_VALUE;
151 }
Andy Hung43119fb2023-12-26 19:26:35 -0800152 const std::vector<sp<AudioEffect>>& effects = it->second->mEffects;
153 const size_t copysize = std::min(effects.size(), (size_t)*count);
154 for (size_t i = 0; i < copysize; i++) {
155 descriptors[i] = effects[i]->descriptor();
bryant_liuba2b4392014-06-11 16:49:30 +0800156 }
157 if (effects.size() > *count) {
158 status = NO_MEMORY;
159 }
160 *count = effects.size();
161 return status;
162}
163
164
Eric Laurentfb66dd92016-01-28 18:32:03 -0800165status_t AudioPolicyEffects::queryDefaultOutputSessionEffects(audio_session_t audioSession,
bryant_liuba2b4392014-06-11 16:49:30 +0800166 effect_descriptor_t *descriptors,
167 uint32_t *count)
168{
169 status_t status = NO_ERROR;
170
Andy Hung79eacdb2023-11-30 19:34:24 -0800171 audio_utils::lock_guard _l(mMutex);
Andy Hung43119fb2023-12-26 19:26:35 -0800172 auto it = mOutputSessions.find(audioSession);
173 if (it == mOutputSessions.end()) {
bryant_liuba2b4392014-06-11 16:49:30 +0800174 *count = 0;
175 return BAD_VALUE;
176 }
Andy Hung43119fb2023-12-26 19:26:35 -0800177 const std::vector<sp<AudioEffect>>& effects = it->second->mEffects;
178 const size_t copysize = std::min(effects.size(), (size_t)*count);
179 for (size_t i = 0; i < copysize; i++) {
180 descriptors[i] = effects[i]->descriptor();
bryant_liuba2b4392014-06-11 16:49:30 +0800181 }
182 if (effects.size() > *count) {
183 status = NO_MEMORY;
184 }
185 *count = effects.size();
186 return status;
187}
188
189
190status_t AudioPolicyEffects::addOutputSessionEffects(audio_io_handle_t output,
191 audio_stream_type_t stream,
Eric Laurentfb66dd92016-01-28 18:32:03 -0800192 audio_session_t audioSession)
bryant_liuba2b4392014-06-11 16:49:30 +0800193{
194 status_t status = NO_ERROR;
195
Andy Hung79eacdb2023-11-30 19:34:24 -0800196 audio_utils::lock_guard _l(mMutex);
bryant_liuba2b4392014-06-11 16:49:30 +0800197 // create audio processors according to stream
Eric Laurent223fd5c2014-11-11 13:43:36 -0800198 // FIXME: should we have specific post processing settings for internal streams?
199 // default to media for now.
200 if (stream >= AUDIO_STREAM_PUBLIC_CNT) {
201 stream = AUDIO_STREAM_MUSIC;
202 }
Andy Hung43119fb2023-12-26 19:26:35 -0800203 auto it = mOutputStreams.find(stream);
204 if (it == mOutputStreams.end()) {
bryant_liuba2b4392014-06-11 16:49:30 +0800205 ALOGV("addOutputSessionEffects(): no output processing needed for this stream");
206 return NO_ERROR;
207 }
208
Andy Hung43119fb2023-12-26 19:26:35 -0800209 std::shared_ptr<EffectVector>& procDesc = mOutputSessions[audioSession];
210 if (procDesc == nullptr) {
Andy Hungf42175b2023-12-19 19:03:19 -0800211 procDesc = std::make_shared<EffectVector>(audioSession);
bryant_liuba2b4392014-06-11 16:49:30 +0800212 }
bryant_liu890a5632014-08-20 18:06:13 +0800213 procDesc->mRefCount++;
214
Eric Laurent7de5ac12014-10-21 09:07:11 -0700215 ALOGV("addOutputSessionEffects(): session: %d, refCount: %d",
216 audioSession, procDesc->mRefCount);
217 if (procDesc->mRefCount == 1) {
Eric Laurentb6436272016-12-07 19:24:50 -0800218 // make sure effects are associated to audio server even if we are executing a binder call
219 int64_t token = IPCThreadState::self()->clearCallingIdentity();
Andy Hung43119fb2023-12-26 19:26:35 -0800220 const std::shared_ptr<EffectDescVector>& effects = it->second;
Andy Hungf42175b2023-12-19 19:03:19 -0800221 for (const std::shared_ptr<EffectDesc>& effect : *effects) {
Svet Ganov3e5f14f2021-05-13 22:51:08 +0000222 AttributionSourceState attributionSource;
223 attributionSource.packageName = "android";
224 attributionSource.token = sp<BBinder>::make();
Andy Hungf42175b2023-12-19 19:03:19 -0800225 auto fx = sp<AudioEffect>::make(attributionSource);
Atneya Nair884f7992022-05-17 19:22:42 -0400226 fx->set(nullptr /* type */, &effect->mUuid, 0 /* priority */, nullptr /* callback */,
227 audioSession, output);
Eric Laurent7de5ac12014-10-21 09:07:11 -0700228 status_t status = fx->initCheck();
229 if (status != NO_ERROR && status != ALREADY_EXISTS) {
230 ALOGE("addOutputSessionEffects(): failed to create Fx %s on session %d",
Andy Hung7760a852023-12-19 17:27:52 -0800231 effect->mName.c_str(), audioSession);
Eric Laurent7de5ac12014-10-21 09:07:11 -0700232 // fx goes out of scope and strong ref on AudioEffect is released
233 continue;
234 }
235 ALOGV("addOutputSessionEffects(): added Fx %s on session: %d for stream: %d",
Andy Hung7760a852023-12-19 17:27:52 -0800236 effect->mName.c_str(), audioSession, (int32_t)stream);
Andy Hungf42175b2023-12-19 19:03:19 -0800237 procDesc->mEffects.push_back(std::move(fx));
bryant_liuba2b4392014-06-11 16:49:30 +0800238 }
Eric Laurent7de5ac12014-10-21 09:07:11 -0700239
240 procDesc->setProcessorEnabled(true);
Eric Laurentb6436272016-12-07 19:24:50 -0800241 IPCThreadState::self()->restoreCallingIdentity(token);
bryant_liuba2b4392014-06-11 16:49:30 +0800242 }
bryant_liuba2b4392014-06-11 16:49:30 +0800243 return status;
244}
245
246status_t AudioPolicyEffects::releaseOutputSessionEffects(audio_io_handle_t output,
247 audio_stream_type_t stream,
Eric Laurentfb66dd92016-01-28 18:32:03 -0800248 audio_session_t audioSession)
bryant_liuba2b4392014-06-11 16:49:30 +0800249{
bryant_liuba2b4392014-06-11 16:49:30 +0800250 (void) output; // argument not used for now
251 (void) stream; // argument not used for now
252
Andy Hung79eacdb2023-11-30 19:34:24 -0800253 audio_utils::lock_guard _l(mMutex);
Andy Hung43119fb2023-12-26 19:26:35 -0800254 auto it = mOutputSessions.find(audioSession);
255 if (it == mOutputSessions.end()) {
bryant_liuba2b4392014-06-11 16:49:30 +0800256 ALOGV("releaseOutputSessionEffects: no output processing was attached to this stream");
257 return NO_ERROR;
258 }
259
Andy Hung43119fb2023-12-26 19:26:35 -0800260 std::shared_ptr<EffectVector> procDesc = it->second;
bryant_liu890a5632014-08-20 18:06:13 +0800261 procDesc->mRefCount--;
Eric Laurent7de5ac12014-10-21 09:07:11 -0700262 ALOGV("releaseOutputSessionEffects(): session: %d, refCount: %d",
263 audioSession, procDesc->mRefCount);
bryant_liu890a5632014-08-20 18:06:13 +0800264 if (procDesc->mRefCount == 0) {
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700265 procDesc->setProcessorEnabled(false);
bryant_liu890a5632014-08-20 18:06:13 +0800266 procDesc->mEffects.clear();
Andy Hung43119fb2023-12-26 19:26:35 -0800267 mOutputSessions.erase(it);
bryant_liu890a5632014-08-20 18:06:13 +0800268 ALOGV("releaseOutputSessionEffects(): output processing released from session: %d",
269 audioSession);
270 }
Andy Hung43119fb2023-12-26 19:26:35 -0800271 return NO_ERROR;
bryant_liuba2b4392014-06-11 16:49:30 +0800272}
273
Ari Hausman-Cohen24628312018-08-13 15:01:09 -0700274status_t AudioPolicyEffects::addSourceDefaultEffect(const effect_uuid_t *type,
275 const String16& opPackageName,
276 const effect_uuid_t *uuid,
277 int32_t priority,
278 audio_source_t source,
279 audio_unique_id_t* id)
280{
281 if (uuid == NULL || type == NULL) {
282 ALOGE("addSourceDefaultEffect(): Null uuid or type uuid pointer");
283 return BAD_VALUE;
284 }
285
Eric Laurentae4b6ec2019-01-15 18:34:38 -0800286 // HOTWORD, FM_TUNER and ECHO_REFERENCE are special case sources > MAX.
Ari Hausman-Cohen24628312018-08-13 15:01:09 -0700287 if (source < AUDIO_SOURCE_DEFAULT ||
288 (source > AUDIO_SOURCE_MAX &&
289 source != AUDIO_SOURCE_HOTWORD &&
Eric Laurentae4b6ec2019-01-15 18:34:38 -0800290 source != AUDIO_SOURCE_FM_TUNER &&
Carter Hsua3abb402021-10-26 11:11:20 +0800291 source != AUDIO_SOURCE_ECHO_REFERENCE &&
292 source != AUDIO_SOURCE_ULTRASOUND)) {
Ari Hausman-Cohen24628312018-08-13 15:01:09 -0700293 ALOGE("addSourceDefaultEffect(): Unsupported source type %d", source);
294 return BAD_VALUE;
295 }
296
297 // Check that |uuid| or |type| corresponds to an effect on the system.
298 effect_descriptor_t descriptor = {};
299 status_t res = AudioEffect::getEffectDescriptor(
300 uuid, type, EFFECT_FLAG_TYPE_PRE_PROC, &descriptor);
301 if (res != OK) {
302 ALOGE("addSourceDefaultEffect(): Failed to find effect descriptor matching uuid/type.");
303 return res;
304 }
305
306 // Only pre-processing effects can be added dynamically as source defaults.
307 if ((descriptor.flags & EFFECT_FLAG_TYPE_MASK) != EFFECT_FLAG_TYPE_PRE_PROC) {
308 ALOGE("addSourceDefaultEffect(): Desired effect cannot be attached "
309 "as a source default effect.");
310 return BAD_VALUE;
311 }
312
Andy Hung79eacdb2023-11-30 19:34:24 -0800313 audio_utils::lock_guard _l(mMutex);
Ari Hausman-Cohen24628312018-08-13 15:01:09 -0700314
315 // Find the EffectDescVector for the given source type, or create a new one if necessary.
Andy Hung43119fb2023-12-26 19:26:35 -0800316 std::shared_ptr<EffectDescVector>& desc = mInputSources[source];
317 if (desc == nullptr) {
Andy Hungf42175b2023-12-19 19:03:19 -0800318 desc = std::make_shared<EffectDescVector>();
Ari Hausman-Cohen24628312018-08-13 15:01:09 -0700319 }
320
321 // Create a new effect and add it to the vector.
322 res = AudioEffect::newEffectUniqueId(id);
323 if (res != OK) {
324 ALOGE("addSourceDefaultEffect(): failed to get new unique id.");
325 return res;
326 }
Andy Hungf42175b2023-12-19 19:03:19 -0800327 std::shared_ptr<EffectDesc> effect = std::make_shared<EffectDesc>(
Eric Laurent2685aa02022-02-01 14:26:38 +0100328 descriptor.name, descriptor.type, opPackageName, descriptor.uuid, priority, *id);
Andy Hungf42175b2023-12-19 19:03:19 -0800329 desc->push_back(std::move(effect));
Ari Hausman-Cohen24628312018-08-13 15:01:09 -0700330 // TODO(b/71813697): Support setting params as well.
331
332 // TODO(b/71814300): Retroactively attach to any existing sources of the given type.
333 // This requires tracking the source type of each session id in addition to what is
334 // already being tracked.
335
336 return NO_ERROR;
337}
338
Ari Hausman-Cohen433722e2018-04-24 14:25:22 -0700339status_t AudioPolicyEffects::addStreamDefaultEffect(const effect_uuid_t *type,
340 const String16& opPackageName,
341 const effect_uuid_t *uuid,
342 int32_t priority,
343 audio_usage_t usage,
344 audio_unique_id_t* id)
345{
346 if (uuid == NULL || type == NULL) {
347 ALOGE("addStreamDefaultEffect(): Null uuid or type uuid pointer");
348 return BAD_VALUE;
349 }
François Gaffie58d4be52018-11-06 15:30:12 +0100350 audio_stream_type_t stream = AudioSystem::attributesToStreamType(attributes_initializer(usage));
Ari Hausman-Cohen433722e2018-04-24 14:25:22 -0700351
352 if (stream < AUDIO_STREAM_MIN || stream >= AUDIO_STREAM_PUBLIC_CNT) {
353 ALOGE("addStreamDefaultEffect(): Unsupported stream type %d", stream);
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_INSERT, &descriptor);
361 if (res != OK) {
362 ALOGE("addStreamDefaultEffect(): Failed to find effect descriptor matching uuid/type.");
363 return res;
364 }
365
366 // Only insert effects can be added dynamically as stream defaults.
367 if ((descriptor.flags & EFFECT_FLAG_TYPE_MASK) != EFFECT_FLAG_TYPE_INSERT) {
368 ALOGE("addStreamDefaultEffect(): Desired effect cannot be attached "
369 "as a stream default effect.");
370 return BAD_VALUE;
371 }
372
Andy Hung79eacdb2023-11-30 19:34:24 -0800373 audio_utils::lock_guard _l(mMutex);
Ari Hausman-Cohen433722e2018-04-24 14:25:22 -0700374
375 // Find the EffectDescVector for the given stream type, or create a new one if necessary.
Andy Hung43119fb2023-12-26 19:26:35 -0800376 std::shared_ptr<EffectDescVector>& desc = mOutputStreams[stream];
377 if (desc == nullptr) {
Ari Hausman-Cohen433722e2018-04-24 14:25:22 -0700378 // No effects for this stream type yet.
Andy Hungf42175b2023-12-19 19:03:19 -0800379 desc = std::make_shared<EffectDescVector>();
Ari Hausman-Cohen433722e2018-04-24 14:25:22 -0700380 }
381
382 // Create a new effect and add it to the vector.
383 res = AudioEffect::newEffectUniqueId(id);
384 if (res != OK) {
385 ALOGE("addStreamDefaultEffect(): failed to get new unique id.");
386 return res;
387 }
Andy Hungf42175b2023-12-19 19:03:19 -0800388 std::shared_ptr<EffectDesc> effect = std::make_shared<EffectDesc>(
Eric Laurent2685aa02022-02-01 14:26:38 +0100389 descriptor.name, descriptor.type, opPackageName, descriptor.uuid, priority, *id);
Andy Hungf42175b2023-12-19 19:03:19 -0800390 desc->push_back(std::move(effect));
Ari Hausman-Cohen433722e2018-04-24 14:25:22 -0700391 // TODO(b/71813697): Support setting params as well.
392
393 // TODO(b/71814300): Retroactively attach to any existing streams of the given type.
394 // This requires tracking the stream type of each session id in addition to what is
395 // already being tracked.
396
397 return NO_ERROR;
398}
399
Ari Hausman-Cohen24628312018-08-13 15:01:09 -0700400status_t AudioPolicyEffects::removeSourceDefaultEffect(audio_unique_id_t id)
401{
402 if (id == AUDIO_UNIQUE_ID_ALLOCATE) {
403 // ALLOCATE is not a unique identifier, but rather a reserved value indicating
404 // a real id has not been assigned. For default effects, this value is only used
405 // by system-owned defaults from the loaded config, which cannot be removed.
406 return BAD_VALUE;
407 }
408
Andy Hung79eacdb2023-11-30 19:34:24 -0800409 audio_utils::lock_guard _l(mMutex);
Ari Hausman-Cohen24628312018-08-13 15:01:09 -0700410
411 // Check each source type.
Andy Hung43119fb2023-12-26 19:26:35 -0800412 for (auto& [source, descVector] : mInputSources) {
Ari Hausman-Cohen24628312018-08-13 15:01:09 -0700413 // Check each effect for each source.
Andy Hungf42175b2023-12-19 19:03:19 -0800414 for (auto desc = descVector->begin(); desc != descVector->end(); ++desc) {
Ari Hausman-Cohen24628312018-08-13 15:01:09 -0700415 if ((*desc)->mId == id) {
416 // Found it!
417 // TODO(b/71814300): Remove from any sources the effect was attached to.
Andy Hungf42175b2023-12-19 19:03:19 -0800418 descVector->erase(desc);
Ari Hausman-Cohen24628312018-08-13 15:01:09 -0700419 // Handles are unique; there can only be one match, so return early.
420 return NO_ERROR;
421 }
422 }
423 }
424
425 // Effect wasn't found, so it's been trivially removed successfully.
426 return NO_ERROR;
427}
428
Ari Hausman-Cohen433722e2018-04-24 14:25:22 -0700429status_t AudioPolicyEffects::removeStreamDefaultEffect(audio_unique_id_t id)
430{
431 if (id == AUDIO_UNIQUE_ID_ALLOCATE) {
432 // ALLOCATE is not a unique identifier, but rather a reserved value indicating
433 // a real id has not been assigned. For default effects, this value is only used
434 // by system-owned defaults from the loaded config, which cannot be removed.
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 // Check each stream type.
Andy Hung43119fb2023-12-26 19:26:35 -0800441 for (auto& [stream, descVector] : mOutputStreams) {
Ari Hausman-Cohen433722e2018-04-24 14:25:22 -0700442 // Check each effect for each stream.
Andy Hungf42175b2023-12-19 19:03:19 -0800443 for (auto desc = descVector->begin(); desc != descVector->end(); ++desc) {
Ari Hausman-Cohen433722e2018-04-24 14:25:22 -0700444 if ((*desc)->mId == id) {
445 // Found it!
446 // TODO(b/71814300): Remove from any streams the effect was attached to.
Andy Hungf42175b2023-12-19 19:03:19 -0800447 descVector->erase(desc);
Ari Hausman-Cohen433722e2018-04-24 14:25:22 -0700448 // Handles are unique; there can only be one match, so return early.
449 return NO_ERROR;
450 }
451 }
452 }
453
454 // Effect wasn't found, so it's been trivially removed successfully.
455 return NO_ERROR;
456}
bryant_liuba2b4392014-06-11 16:49:30 +0800457
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700458void AudioPolicyEffects::EffectVector::setProcessorEnabled(bool enabled)
bryant_liuba2b4392014-06-11 16:49:30 +0800459{
Andy Hung43119fb2023-12-26 19:26:35 -0800460 for (const auto& effect : mEffects) {
461 effect->setEnabled(enabled);
bryant_liuba2b4392014-06-11 16:49:30 +0800462 }
463}
464
465
466// ----------------------------------------------------------------------------
467// Audio processing configuration
468// ----------------------------------------------------------------------------
469
Andy Hungd3595ed2023-12-19 15:34:46 -0800470// we keep to const char* instead of std::string_view as comparison is believed faster.
471constexpr const char* kInputSourceNames[AUDIO_SOURCE_CNT - 1] = {
bryant_liuba2b4392014-06-11 16:49:30 +0800472 MIC_SRC_TAG,
473 VOICE_UL_SRC_TAG,
474 VOICE_DL_SRC_TAG,
475 VOICE_CALL_SRC_TAG,
476 CAMCORDER_SRC_TAG,
477 VOICE_REC_SRC_TAG,
rago8a397d52015-12-02 11:27:57 -0800478 VOICE_COMM_SRC_TAG,
Carter Hsua3abb402021-10-26 11:11:20 +0800479 REMOTE_SUBMIX_SRC_TAG,
Eric Laurentae4b6ec2019-01-15 18:34:38 -0800480 UNPROCESSED_SRC_TAG,
481 VOICE_PERFORMANCE_SRC_TAG
bryant_liuba2b4392014-06-11 16:49:30 +0800482};
483
484// returns the audio_source_t enum corresponding to the input source name or
485// AUDIO_SOURCE_CNT is no match found
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700486/*static*/ audio_source_t AudioPolicyEffects::inputSourceNameToEnum(const char *name)
bryant_liuba2b4392014-06-11 16:49:30 +0800487{
488 int i;
489 for (i = AUDIO_SOURCE_MIC; i < AUDIO_SOURCE_CNT; i++) {
490 if (strcmp(name, kInputSourceNames[i - AUDIO_SOURCE_MIC]) == 0) {
491 ALOGV("inputSourceNameToEnum found source %s %d", name, i);
492 break;
493 }
494 }
495 return (audio_source_t)i;
496}
497
Andy Hungd3595ed2023-12-19 15:34:46 -0800498// +1 as enum starts from -1
499constexpr const char* kStreamNames[AUDIO_STREAM_PUBLIC_CNT + 1] = {
bryant_liuba2b4392014-06-11 16:49:30 +0800500 AUDIO_STREAM_DEFAULT_TAG,
501 AUDIO_STREAM_VOICE_CALL_TAG,
502 AUDIO_STREAM_SYSTEM_TAG,
503 AUDIO_STREAM_RING_TAG,
504 AUDIO_STREAM_MUSIC_TAG,
505 AUDIO_STREAM_ALARM_TAG,
506 AUDIO_STREAM_NOTIFICATION_TAG,
507 AUDIO_STREAM_BLUETOOTH_SCO_TAG,
508 AUDIO_STREAM_ENFORCED_AUDIBLE_TAG,
509 AUDIO_STREAM_DTMF_TAG,
Baekgyeong Kim3a26bb22019-10-30 20:29:41 +0900510 AUDIO_STREAM_TTS_TAG,
511 AUDIO_STREAM_ASSISTANT_TAG
bryant_liuba2b4392014-06-11 16:49:30 +0800512};
513
514// returns the audio_stream_t enum corresponding to the output stream name or
Eric Laurent223fd5c2014-11-11 13:43:36 -0800515// AUDIO_STREAM_PUBLIC_CNT is no match found
Andy Hungd3595ed2023-12-19 15:34:46 -0800516/* static */
bryant_liuba2b4392014-06-11 16:49:30 +0800517audio_stream_type_t AudioPolicyEffects::streamNameToEnum(const char *name)
518{
519 int i;
Eric Laurent223fd5c2014-11-11 13:43:36 -0800520 for (i = AUDIO_STREAM_DEFAULT; i < AUDIO_STREAM_PUBLIC_CNT; i++) {
bryant_liuba2b4392014-06-11 16:49:30 +0800521 if (strcmp(name, kStreamNames[i - AUDIO_STREAM_DEFAULT]) == 0) {
522 ALOGV("streamNameToEnum found stream %s %d", name, i);
523 break;
524 }
525 }
526 return (audio_stream_type_t)i;
527}
528
529// ----------------------------------------------------------------------------
530// Audio Effect Config parser
531// ----------------------------------------------------------------------------
532
Andy Hungd3595ed2023-12-19 15:34:46 -0800533/* static */
Eric Laurent138ed172016-02-10 10:40:44 -0800534size_t AudioPolicyEffects::growParamSize(char **param,
bryant_liuba2b4392014-06-11 16:49:30 +0800535 size_t size,
536 size_t *curSize,
537 size_t *totSize)
538{
539 // *curSize is at least sizeof(effect_param_t) + 2 * sizeof(int)
540 size_t pos = ((*curSize - 1 ) / size + 1) * size;
541
542 if (pos + size > *totSize) {
543 while (pos + size > *totSize) {
544 *totSize += ((*totSize + 7) / 8) * 4;
545 }
George Burgess IV31225682018-02-12 11:08:38 -0800546 char *newParam = (char *)realloc(*param, *totSize);
547 if (newParam == NULL) {
Eric Laurent138ed172016-02-10 10:40:44 -0800548 ALOGE("%s realloc error for size %zu", __func__, *totSize);
549 return 0;
550 }
George Burgess IV31225682018-02-12 11:08:38 -0800551 *param = newParam;
bryant_liuba2b4392014-06-11 16:49:30 +0800552 }
553 *curSize = pos + size;
554 return pos;
555}
556
Andy Hungd3595ed2023-12-19 15:34:46 -0800557/* static */
bryant_liuba2b4392014-06-11 16:49:30 +0800558size_t AudioPolicyEffects::readParamValue(cnode *node,
Eric Laurent138ed172016-02-10 10:40:44 -0800559 char **param,
bryant_liuba2b4392014-06-11 16:49:30 +0800560 size_t *curSize,
561 size_t *totSize)
562{
Eric Laurent138ed172016-02-10 10:40:44 -0800563 size_t len = 0;
564 size_t pos;
565
bryant_liuba2b4392014-06-11 16:49:30 +0800566 if (strncmp(node->name, SHORT_TAG, sizeof(SHORT_TAG) + 1) == 0) {
Eric Laurent138ed172016-02-10 10:40:44 -0800567 pos = growParamSize(param, sizeof(short), curSize, totSize);
568 if (pos == 0) {
569 goto exit;
bryant_liuba2b4392014-06-11 16:49:30 +0800570 }
Eric Laurent138ed172016-02-10 10:40:44 -0800571 *(short *)(*param + pos) = (short)atoi(node->value);
572 ALOGV("readParamValue() reading short %d", *(short *)(*param + pos));
573 len = sizeof(short);
574 } else if (strncmp(node->name, INT_TAG, sizeof(INT_TAG) + 1) == 0) {
575 pos = growParamSize(param, sizeof(int), curSize, totSize);
576 if (pos == 0) {
577 goto exit;
578 }
579 *(int *)(*param + pos) = atoi(node->value);
580 ALOGV("readParamValue() reading int %d", *(int *)(*param + pos));
581 len = sizeof(int);
582 } else if (strncmp(node->name, FLOAT_TAG, sizeof(FLOAT_TAG) + 1) == 0) {
583 pos = growParamSize(param, sizeof(float), curSize, totSize);
584 if (pos == 0) {
585 goto exit;
586 }
587 *(float *)(*param + pos) = (float)atof(node->value);
588 ALOGV("readParamValue() reading float %f",*(float *)(*param + pos));
589 len = sizeof(float);
590 } else if (strncmp(node->name, BOOL_TAG, sizeof(BOOL_TAG) + 1) == 0) {
591 pos = growParamSize(param, sizeof(bool), curSize, totSize);
592 if (pos == 0) {
593 goto exit;
594 }
595 if (strncmp(node->value, "true", strlen("true") + 1) == 0) {
596 *(bool *)(*param + pos) = true;
597 } else {
598 *(bool *)(*param + pos) = false;
599 }
600 ALOGV("readParamValue() reading bool %s",
601 *(bool *)(*param + pos) ? "true" : "false");
602 len = sizeof(bool);
bryant_liuba2b4392014-06-11 16:49:30 +0800603 } else if (strncmp(node->name, STRING_TAG, sizeof(STRING_TAG) + 1) == 0) {
Eric Laurent138ed172016-02-10 10:40:44 -0800604 len = strnlen(node->value, EFFECT_STRING_LEN_MAX);
bryant_liuba2b4392014-06-11 16:49:30 +0800605 if (*curSize + len + 1 > *totSize) {
606 *totSize = *curSize + len + 1;
Chih-Hung Hsieh03077682018-08-30 14:11:00 -0700607 char *newParam = (char *)realloc(*param, *totSize);
608 if (newParam == NULL) {
Eric Laurent138ed172016-02-10 10:40:44 -0800609 len = 0;
610 ALOGE("%s realloc error for string len %zu", __func__, *totSize);
611 goto exit;
612 }
Chih-Hung Hsieh03077682018-08-30 14:11:00 -0700613 *param = newParam;
bryant_liuba2b4392014-06-11 16:49:30 +0800614 }
Eric Laurent138ed172016-02-10 10:40:44 -0800615 strncpy(*param + *curSize, node->value, len);
bryant_liuba2b4392014-06-11 16:49:30 +0800616 *curSize += len;
Eric Laurent138ed172016-02-10 10:40:44 -0800617 (*param)[*curSize] = '\0';
618 ALOGV("readParamValue() reading string %s", *param + *curSize - len);
619 } else {
620 ALOGW("readParamValue() unknown param type %s", node->name);
bryant_liuba2b4392014-06-11 16:49:30 +0800621 }
Eric Laurent138ed172016-02-10 10:40:44 -0800622exit:
623 return len;
bryant_liuba2b4392014-06-11 16:49:30 +0800624}
625
Andy Hungd3595ed2023-12-19 15:34:46 -0800626/* static */
Andy Hung7760a852023-12-19 17:27:52 -0800627std::shared_ptr<const effect_param_t> AudioPolicyEffects::loadEffectParameter(cnode* root)
bryant_liuba2b4392014-06-11 16:49:30 +0800628{
629 cnode *param;
630 cnode *value;
631 size_t curSize = sizeof(effect_param_t);
632 size_t totSize = sizeof(effect_param_t) + 2 * sizeof(int);
633 effect_param_t *fx_param = (effect_param_t *)malloc(totSize);
634
Eric Laurent138ed172016-02-10 10:40:44 -0800635 if (fx_param == NULL) {
636 ALOGE("%s malloc error for effect structure of size %zu",
637 __func__, totSize);
638 return NULL;
639 }
640
bryant_liuba2b4392014-06-11 16:49:30 +0800641 param = config_find(root, PARAM_TAG);
642 value = config_find(root, VALUE_TAG);
643 if (param == NULL && value == NULL) {
644 // try to parse simple parameter form {int int}
645 param = root->first_child;
646 if (param != NULL) {
647 // Note: that a pair of random strings is read as 0 0
648 int *ptr = (int *)fx_param->data;
Eric Laurent138ed172016-02-10 10:40:44 -0800649#if LOG_NDEBUG == 0
bryant_liuba2b4392014-06-11 16:49:30 +0800650 int *ptr2 = (int *)((char *)param + sizeof(effect_param_t));
Eric Laurent138ed172016-02-10 10:40:44 -0800651 ALOGV("loadEffectParameter() ptr %p ptr2 %p", ptr, ptr2);
652#endif
bryant_liuba2b4392014-06-11 16:49:30 +0800653 *ptr++ = atoi(param->name);
654 *ptr = atoi(param->value);
655 fx_param->psize = sizeof(int);
656 fx_param->vsize = sizeof(int);
Andy Hung7760a852023-12-19 17:27:52 -0800657 return {fx_param, free};
bryant_liuba2b4392014-06-11 16:49:30 +0800658 }
659 }
660 if (param == NULL || value == NULL) {
Eric Laurent138ed172016-02-10 10:40:44 -0800661 ALOGW("loadEffectParameter() invalid parameter description %s",
662 root->name);
bryant_liuba2b4392014-06-11 16:49:30 +0800663 goto error;
664 }
665
666 fx_param->psize = 0;
667 param = param->first_child;
668 while (param) {
669 ALOGV("loadEffectParameter() reading param of type %s", param->name);
Eric Laurent138ed172016-02-10 10:40:44 -0800670 size_t size =
671 readParamValue(param, (char **)&fx_param, &curSize, &totSize);
bryant_liuba2b4392014-06-11 16:49:30 +0800672 if (size == 0) {
673 goto error;
674 }
675 fx_param->psize += size;
676 param = param->next;
677 }
678
679 // align start of value field on 32 bit boundary
680 curSize = ((curSize - 1 ) / sizeof(int) + 1) * sizeof(int);
681
682 fx_param->vsize = 0;
683 value = value->first_child;
684 while (value) {
685 ALOGV("loadEffectParameter() reading value of type %s", value->name);
Eric Laurent138ed172016-02-10 10:40:44 -0800686 size_t size =
687 readParamValue(value, (char **)&fx_param, &curSize, &totSize);
bryant_liuba2b4392014-06-11 16:49:30 +0800688 if (size == 0) {
689 goto error;
690 }
691 fx_param->vsize += size;
692 value = value->next;
693 }
694
Andy Hung7760a852023-12-19 17:27:52 -0800695 return {fx_param, free};
bryant_liuba2b4392014-06-11 16:49:30 +0800696
697error:
Eric Laurent138ed172016-02-10 10:40:44 -0800698 free(fx_param);
bryant_liuba2b4392014-06-11 16:49:30 +0800699 return NULL;
700}
701
Andy Hungd3595ed2023-12-19 15:34:46 -0800702/* static */
Andy Hung7760a852023-12-19 17:27:52 -0800703void AudioPolicyEffects::loadEffectParameters(
704 cnode* root, std::vector<std::shared_ptr<const effect_param_t>>& params)
bryant_liuba2b4392014-06-11 16:49:30 +0800705{
706 cnode *node = root->first_child;
707 while (node) {
708 ALOGV("loadEffectParameters() loading param %s", node->name);
Andy Hung7760a852023-12-19 17:27:52 -0800709 const auto param = loadEffectParameter(node);
710 if (param != nullptr) {
711 params.push_back(param);
bryant_liuba2b4392014-06-11 16:49:30 +0800712 }
bryant_liuba2b4392014-06-11 16:49:30 +0800713 node = node->next;
714 }
715}
716
Andy Hungd3595ed2023-12-19 15:34:46 -0800717/* static */
Andy Hungf42175b2023-12-19 19:03:19 -0800718std::shared_ptr<AudioPolicyEffects::EffectDescVector> AudioPolicyEffects::loadEffectConfig(
719 cnode* root, const EffectDescVector& effects)
bryant_liuba2b4392014-06-11 16:49:30 +0800720{
721 cnode *node = root->first_child;
722 if (node == NULL) {
723 ALOGW("loadInputSource() empty element %s", root->name);
724 return NULL;
725 }
Andy Hungf42175b2023-12-19 19:03:19 -0800726 auto desc = std::make_shared<EffectDescVector>();
bryant_liuba2b4392014-06-11 16:49:30 +0800727 while (node) {
728 size_t i;
Eric Laurent138ed172016-02-10 10:40:44 -0800729
bryant_liuba2b4392014-06-11 16:49:30 +0800730 for (i = 0; i < effects.size(); i++) {
Andy Hung7760a852023-12-19 17:27:52 -0800731 if (effects[i]->mName == node->name) {
bryant_liuba2b4392014-06-11 16:49:30 +0800732 ALOGV("loadEffectConfig() found effect %s in list", node->name);
733 break;
734 }
735 }
736 if (i == effects.size()) {
737 ALOGV("loadEffectConfig() effect %s not in list", node->name);
738 node = node->next;
739 continue;
740 }
Andy Hungf42175b2023-12-19 19:03:19 -0800741 auto effect = std::make_shared<EffectDesc>(*effects[i]); // deep copy
bryant_liuba2b4392014-06-11 16:49:30 +0800742 loadEffectParameters(node, effect->mParams);
743 ALOGV("loadEffectConfig() adding effect %s uuid %08x",
Andy Hung7760a852023-12-19 17:27:52 -0800744 effect->mName.c_str(), effect->mUuid.timeLow);
Andy Hungf42175b2023-12-19 19:03:19 -0800745 desc->push_back(std::move(effect));
bryant_liuba2b4392014-06-11 16:49:30 +0800746 node = node->next;
747 }
Andy Hungf42175b2023-12-19 19:03:19 -0800748 if (desc->empty()) {
bryant_liuba2b4392014-06-11 16:49:30 +0800749 ALOGW("loadEffectConfig() no valid effects found in config %s", root->name);
Andy Hungf42175b2023-12-19 19:03:19 -0800750 return nullptr;
bryant_liuba2b4392014-06-11 16:49:30 +0800751 }
752 return desc;
753}
754
Andy Hungd3595ed2023-12-19 15:34:46 -0800755status_t AudioPolicyEffects::loadInputEffectConfigurations_l(cnode* root,
Andy Hungf42175b2023-12-19 19:03:19 -0800756 const EffectDescVector& effects)
bryant_liuba2b4392014-06-11 16:49:30 +0800757{
758 cnode *node = config_find(root, PREPROCESSING_TAG);
759 if (node == NULL) {
760 return -ENOENT;
761 }
762 node = node->first_child;
763 while (node) {
764 audio_source_t source = inputSourceNameToEnum(node->name);
765 if (source == AUDIO_SOURCE_CNT) {
Andy Hungd3595ed2023-12-19 15:34:46 -0800766 ALOGW("%s() invalid input source %s", __func__, node->name);
bryant_liuba2b4392014-06-11 16:49:30 +0800767 node = node->next;
768 continue;
769 }
Andy Hungd3595ed2023-12-19 15:34:46 -0800770 ALOGV("%s() loading input source %s", __func__, node->name);
Andy Hungf42175b2023-12-19 19:03:19 -0800771 auto desc = loadEffectConfig(node, effects);
bryant_liuba2b4392014-06-11 16:49:30 +0800772 if (desc == NULL) {
773 node = node->next;
774 continue;
775 }
Andy Hung43119fb2023-12-26 19:26:35 -0800776 mInputSources[source] = std::move(desc);
bryant_liuba2b4392014-06-11 16:49:30 +0800777 node = node->next;
778 }
779 return NO_ERROR;
780}
781
Andy Hungd3595ed2023-12-19 15:34:46 -0800782status_t AudioPolicyEffects::loadStreamEffectConfigurations_l(cnode* root,
Andy Hungf42175b2023-12-19 19:03:19 -0800783 const EffectDescVector& effects)
bryant_liuba2b4392014-06-11 16:49:30 +0800784{
785 cnode *node = config_find(root, OUTPUT_SESSION_PROCESSING_TAG);
786 if (node == NULL) {
787 return -ENOENT;
788 }
789 node = node->first_child;
790 while (node) {
791 audio_stream_type_t stream = streamNameToEnum(node->name);
Eric Laurent223fd5c2014-11-11 13:43:36 -0800792 if (stream == AUDIO_STREAM_PUBLIC_CNT) {
Andy Hungd3595ed2023-12-19 15:34:46 -0800793 ALOGW("%s() invalid output stream %s", __func__, node->name);
bryant_liuba2b4392014-06-11 16:49:30 +0800794 node = node->next;
795 continue;
796 }
Andy Hungd3595ed2023-12-19 15:34:46 -0800797 ALOGV("%s() loading output stream %s", __func__, node->name);
Andy Hungf42175b2023-12-19 19:03:19 -0800798 std::shared_ptr<EffectDescVector> desc = loadEffectConfig(node, effects);
bryant_liuba2b4392014-06-11 16:49:30 +0800799 if (desc == NULL) {
800 node = node->next;
801 continue;
802 }
Andy Hung43119fb2023-12-26 19:26:35 -0800803 mOutputStreams[stream] = std::move(desc);
bryant_liuba2b4392014-06-11 16:49:30 +0800804 node = node->next;
805 }
806 return NO_ERROR;
807}
808
Andy Hungd3595ed2023-12-19 15:34:46 -0800809/* static */
Andy Hungf42175b2023-12-19 19:03:19 -0800810std::shared_ptr<AudioPolicyEffects::EffectDesc> AudioPolicyEffects::loadEffect(cnode* root)
bryant_liuba2b4392014-06-11 16:49:30 +0800811{
812 cnode *node = config_find(root, UUID_TAG);
813 if (node == NULL) {
814 return NULL;
815 }
816 effect_uuid_t uuid;
817 if (AudioEffect::stringToGuid(node->value, &uuid) != NO_ERROR) {
818 ALOGW("loadEffect() invalid uuid %s", node->value);
819 return NULL;
820 }
Andy Hungf42175b2023-12-19 19:03:19 -0800821 return std::make_shared<EffectDesc>(root->name, uuid);
bryant_liuba2b4392014-06-11 16:49:30 +0800822}
823
Andy Hungd3595ed2023-12-19 15:34:46 -0800824/* static */
Andy Hungf42175b2023-12-19 19:03:19 -0800825android::AudioPolicyEffects::EffectDescVector AudioPolicyEffects::loadEffects(cnode *root)
bryant_liuba2b4392014-06-11 16:49:30 +0800826{
Andy Hungf42175b2023-12-19 19:03:19 -0800827 EffectDescVector effects;
bryant_liuba2b4392014-06-11 16:49:30 +0800828 cnode *node = config_find(root, EFFECTS_TAG);
829 if (node == NULL) {
Andy Hungf42175b2023-12-19 19:03:19 -0800830 ALOGW("%s() Cannot find %s configuration", __func__, EFFECTS_TAG);
831 return effects;
bryant_liuba2b4392014-06-11 16:49:30 +0800832 }
833 node = node->first_child;
834 while (node) {
835 ALOGV("loadEffects() loading effect %s", node->name);
Andy Hungf42175b2023-12-19 19:03:19 -0800836 auto effect = loadEffect(node);
bryant_liuba2b4392014-06-11 16:49:30 +0800837 if (effect == NULL) {
838 node = node->next;
839 continue;
840 }
Andy Hungf42175b2023-12-19 19:03:19 -0800841 effects.push_back(std::move(effect));
bryant_liuba2b4392014-06-11 16:49:30 +0800842 node = node->next;
843 }
Andy Hungf42175b2023-12-19 19:03:19 -0800844 return effects;
bryant_liuba2b4392014-06-11 16:49:30 +0800845}
846
Andy Hungd3595ed2023-12-19 15:34:46 -0800847status_t AudioPolicyEffects::loadAudioEffectConfig_ll(
Shunkai Yao8d6489a2023-04-18 23:14:25 +0000848 const sp<EffectsFactoryHalInterface>& effectsFactoryHal) {
849 if (!effectsFactoryHal) {
850 ALOGE("%s Null EffectsFactoryHalInterface", __func__);
851 return UNEXPECTED_NULL;
852 }
853
854 const auto skippedElements = VALUE_OR_RETURN_STATUS(effectsFactoryHal->getSkippedElements());
855 const auto processings = effectsFactoryHal->getProcessings();
856 if (!processings) {
857 ALOGE("%s Null processings with %zu skipped elements", __func__, skippedElements);
858 return UNEXPECTED_NULL;
Kevin Rocard4fb615c2017-06-26 10:28:13 -0700859 }
860
861 auto loadProcessingChain = [](auto& processingChain, auto& streams) {
862 for (auto& stream : processingChain) {
Andy Hungf42175b2023-12-19 19:03:19 -0800863 auto effectDescs = std::make_shared<EffectDescVector>();
Kevin Rocard4fb615c2017-06-26 10:28:13 -0700864 for (auto& effect : stream.effects) {
Andy Hungf42175b2023-12-19 19:03:19 -0800865 effectDescs->push_back(
Andy Hungbb2f2bf2023-12-27 13:17:16 -0800866 std::make_shared<EffectDesc>(effect->name, effect->uuid));
Kevin Rocard4fb615c2017-06-26 10:28:13 -0700867 }
Andy Hung43119fb2023-12-26 19:26:35 -0800868 streams[stream.type] = std::move(effectDescs);
Kevin Rocard4fb615c2017-06-26 10:28:13 -0700869 }
870 };
François Gaffie06182982020-01-07 15:16:14 +0100871
Shunkai Yao8d6489a2023-04-18 23:14:25 +0000872 auto loadDeviceProcessingChain = [](auto& processingChain, auto& devicesEffects) {
François Gaffie06182982020-01-07 15:16:14 +0100873 for (auto& deviceProcess : processingChain) {
François Gaffie06182982020-01-07 15:16:14 +0100874 auto effectDescs = std::make_unique<EffectDescVector>();
875 for (auto& effect : deviceProcess.effects) {
Andy Hungf42175b2023-12-19 19:03:19 -0800876 effectDescs->push_back(
Andy Hungbb2f2bf2023-12-27 13:17:16 -0800877 std::make_shared<EffectDesc>(effect->name, effect->uuid));
François Gaffie06182982020-01-07 15:16:14 +0100878 }
Andy Hungf42175b2023-12-19 19:03:19 -0800879 auto devEffects = std::make_unique<DeviceEffects>(
François Gaffie06182982020-01-07 15:16:14 +0100880 std::move(effectDescs), deviceProcess.type, deviceProcess.address);
Andy Hungf42175b2023-12-19 19:03:19 -0800881 devicesEffects.emplace(deviceProcess.address, std::move(devEffects));
François Gaffie06182982020-01-07 15:16:14 +0100882 }
883 };
884
Andy Hungd3595ed2023-12-19 15:34:46 -0800885 // access to mInputSources and mOutputStreams requires mMutex;
Shunkai Yao8d6489a2023-04-18 23:14:25 +0000886 loadProcessingChain(processings->preprocess, mInputSources);
887 loadProcessingChain(processings->postprocess, mOutputStreams);
888
Andy Hungd3595ed2023-12-19 15:34:46 -0800889 // access to mDeviceEffects requires mDeviceEffectsMutex
890 loadDeviceProcessingChain(processings->deviceprocess, mDeviceEffects);
Shunkai Yao8d6489a2023-04-18 23:14:25 +0000891
892 return skippedElements;
Kevin Rocard4fb615c2017-06-26 10:28:13 -0700893}
894
Andy Hungd3595ed2023-12-19 15:34:46 -0800895status_t AudioPolicyEffects::loadAudioEffectConfigLegacy_l(const char *path)
Shunkai Yaoeab8a7c2023-05-15 21:07:08 +0000896{
897 cnode *root;
898 char *data;
899
900 data = (char *)load_file(path, NULL);
901 if (data == NULL) {
902 return -ENODEV;
903 }
904 root = config_node("", "");
905 config_load(root, data);
906
Andy Hungf42175b2023-12-19 19:03:19 -0800907 const EffectDescVector effects = loadEffects(root);
Andy Hungd3595ed2023-12-19 15:34:46 -0800908
909 // requires mMutex
910 loadInputEffectConfigurations_l(root, effects);
911 loadStreamEffectConfigurations_l(root, effects);
Shunkai Yaoeab8a7c2023-05-15 21:07:08 +0000912 config_free(root);
913 free(root);
914 free(data);
915
916 return NO_ERROR;
917}
918
François Gaffie06182982020-01-07 15:16:14 +0100919void AudioPolicyEffects::initDefaultDeviceEffects()
920{
Andy Hungd3595ed2023-12-19 15:34:46 -0800921 std::lock_guard _l(mDeviceEffectsMutex);
François Gaffie06182982020-01-07 15:16:14 +0100922 for (const auto& deviceEffectsIter : mDeviceEffects) {
923 const auto& deviceEffects = deviceEffectsIter.second;
Andy Hungf42175b2023-12-19 19:03:19 -0800924 for (const auto& effectDesc : *deviceEffects->mEffectDescriptors) {
Svet Ganov3e5f14f2021-05-13 22:51:08 +0000925 AttributionSourceState attributionSource;
926 attributionSource.packageName = "android";
927 attributionSource.token = sp<BBinder>::make();
Andy Hungf42175b2023-12-19 19:03:19 -0800928 sp<AudioEffect> fx = sp<AudioEffect>::make(attributionSource);
Atneya Nair884f7992022-05-17 19:22:42 -0400929 fx->set(EFFECT_UUID_NULL, &effectDesc->mUuid, 0 /* priority */, nullptr /* callback */,
930 AUDIO_SESSION_DEVICE, AUDIO_IO_HANDLE_NONE,
Mikhail Naganov69d41cc2020-07-31 17:36:08 -0700931 AudioDeviceTypeAddr{deviceEffects->getDeviceType(),
932 deviceEffects->getDeviceAddress()});
François Gaffie06182982020-01-07 15:16:14 +0100933 status_t status = fx->initCheck();
934 if (status != NO_ERROR && status != ALREADY_EXISTS) {
935 ALOGE("%s(): failed to create Fx %s on port type=%d address=%s", __func__,
Andy Hung7760a852023-12-19 17:27:52 -0800936 effectDesc->mName.c_str(), deviceEffects->getDeviceType(),
François Gaffie06182982020-01-07 15:16:14 +0100937 deviceEffects->getDeviceAddress().c_str());
938 // fx goes out of scope and strong ref on AudioEffect is released
939 continue;
940 }
941 fx->setEnabled(true);
942 ALOGV("%s(): create Fx %s added on port type=%d address=%s", __func__,
Andy Hung7760a852023-12-19 17:27:52 -0800943 effectDesc->mName.c_str(), deviceEffects->getDeviceType(),
François Gaffie06182982020-01-07 15:16:14 +0100944 deviceEffects->getDeviceAddress().c_str());
Andy Hungf42175b2023-12-19 19:03:19 -0800945 deviceEffects->mEffects.push_back(std::move(fx));
François Gaffie06182982020-01-07 15:16:14 +0100946 }
947 }
948}
bryant_liuba2b4392014-06-11 16:49:30 +0800949
Mikhail Naganov1b2a7942017-12-08 10:18:09 -0800950} // namespace android