blob: 1d931ffd95c01eba9d3c8a6097e9ddc0d8d6ff6e [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);
bryant_liuba2b4392014-06-11 16:49:30 +080080 ssize_t index = mInputSources.indexOfKey(aliasSource);
81 if (index < 0) {
82 ALOGV("addInputEffects(): no processing needs to be attached to this source");
83 return status;
84 }
Eric Laurentfb66dd92016-01-28 18:32:03 -080085 ssize_t idx = mInputSessions.indexOfKey(audioSession);
Andy Hungf42175b2023-12-19 19:03:19 -080086 std::shared_ptr<EffectVector> sessionDesc;
bryant_liuba2b4392014-06-11 16:49:30 +080087 if (idx < 0) {
Andy Hungf42175b2023-12-19 19:03:19 -080088 sessionDesc = std::make_shared<EffectVector>(audioSession);
Eric Laurentfb66dd92016-01-28 18:32:03 -080089 mInputSessions.add(audioSession, sessionDesc);
bryant_liuba2b4392014-06-11 16:49:30 +080090 } else {
bryant_liu890a5632014-08-20 18:06:13 +080091 // EffectVector is existing and we just need to increase ref count
Eric Laurentfb66dd92016-01-28 18:32:03 -080092 sessionDesc = mInputSessions.valueAt(idx);
bryant_liuba2b4392014-06-11 16:49:30 +080093 }
Eric Laurentfb66dd92016-01-28 18:32:03 -080094 sessionDesc->mRefCount++;
bryant_liu890a5632014-08-20 18:06:13 +080095
Eric Laurentfb66dd92016-01-28 18:32:03 -080096 ALOGV("addInputEffects(): input: %d, refCount: %d", input, sessionDesc->mRefCount);
97 if (sessionDesc->mRefCount == 1) {
Eric Laurentb6436272016-12-07 19:24:50 -080098 int64_t token = IPCThreadState::self()->clearCallingIdentity();
Andy Hungf42175b2023-12-19 19:03:19 -080099 const std::shared_ptr<EffectDescVector>& effects = mInputSources.valueAt(index);
100 for (const std::shared_ptr<EffectDesc>& effect : *effects) {
Svet Ganov3e5f14f2021-05-13 22:51:08 +0000101 AttributionSourceState attributionSource;
102 attributionSource.packageName = "android";
103 attributionSource.token = sp<BBinder>::make();
Andy Hungf42175b2023-12-19 19:03:19 -0800104 auto fx = sp<AudioEffect>::make(attributionSource);
Atneya Nair884f7992022-05-17 19:22:42 -0400105 fx->set(nullptr /*type */, &effect->mUuid, -1 /* priority */, nullptr /* callback */,
106 audioSession, input);
Eric Laurent7de5ac12014-10-21 09:07:11 -0700107 status_t status = fx->initCheck();
108 if (status != NO_ERROR && status != ALREADY_EXISTS) {
109 ALOGW("addInputEffects(): failed to create Fx %s on source %d",
Andy Hung7760a852023-12-19 17:27:52 -0800110 effect->mName.c_str(), (int32_t)aliasSource);
Eric Laurent7de5ac12014-10-21 09:07:11 -0700111 // fx goes out of scope and strong ref on AudioEffect is released
112 continue;
113 }
114 for (size_t j = 0; j < effect->mParams.size(); j++) {
Andy Hung7760a852023-12-19 17:27:52 -0800115 // const_cast here due to API.
116 fx->setParameter(const_cast<effect_param_t*>(effect->mParams[j].get()));
Eric Laurent7de5ac12014-10-21 09:07:11 -0700117 }
118 ALOGV("addInputEffects(): added Fx %s on source: %d",
Andy Hung7760a852023-12-19 17:27:52 -0800119 effect->mName.c_str(), (int32_t)aliasSource);
Andy Hungf42175b2023-12-19 19:03:19 -0800120 sessionDesc->mEffects.push_back(std::move(fx));
bryant_liuba2b4392014-06-11 16:49:30 +0800121 }
Eric Laurentfb66dd92016-01-28 18:32:03 -0800122 sessionDesc->setProcessorEnabled(true);
Eric Laurentb6436272016-12-07 19:24:50 -0800123 IPCThreadState::self()->restoreCallingIdentity(token);
bryant_liuba2b4392014-06-11 16:49:30 +0800124 }
bryant_liuba2b4392014-06-11 16:49:30 +0800125 return status;
126}
127
128
Eric Laurentfb66dd92016-01-28 18:32:03 -0800129status_t AudioPolicyEffects::releaseInputEffects(audio_io_handle_t input,
130 audio_session_t audioSession)
bryant_liuba2b4392014-06-11 16:49:30 +0800131{
132 status_t status = NO_ERROR;
133
Andy Hung79eacdb2023-11-30 19:34:24 -0800134 audio_utils::lock_guard _l(mMutex);
Eric Laurentfb66dd92016-01-28 18:32:03 -0800135 ssize_t index = mInputSessions.indexOfKey(audioSession);
bryant_liuba2b4392014-06-11 16:49:30 +0800136 if (index < 0) {
137 return status;
138 }
Andy Hungf42175b2023-12-19 19:03:19 -0800139 std::shared_ptr<EffectVector> sessionDesc = mInputSessions.valueAt(index);
Eric Laurentfb66dd92016-01-28 18:32:03 -0800140 sessionDesc->mRefCount--;
141 ALOGV("releaseInputEffects(): input: %d, refCount: %d", input, sessionDesc->mRefCount);
142 if (sessionDesc->mRefCount == 0) {
143 sessionDesc->setProcessorEnabled(false);
Eric Laurentfb66dd92016-01-28 18:32:03 -0800144 mInputSessions.removeItemsAt(index);
bryant_liu890a5632014-08-20 18:06:13 +0800145 ALOGV("releaseInputEffects(): all effects released");
146 }
bryant_liuba2b4392014-06-11 16:49:30 +0800147 return status;
148}
149
Eric Laurentfb66dd92016-01-28 18:32:03 -0800150status_t AudioPolicyEffects::queryDefaultInputEffects(audio_session_t audioSession,
bryant_liuba2b4392014-06-11 16:49:30 +0800151 effect_descriptor_t *descriptors,
152 uint32_t *count)
153{
154 status_t status = NO_ERROR;
155
Andy Hung79eacdb2023-11-30 19:34:24 -0800156 audio_utils::lock_guard _l(mMutex);
bryant_liuba2b4392014-06-11 16:49:30 +0800157 size_t index;
Eric Laurentfb66dd92016-01-28 18:32:03 -0800158 for (index = 0; index < mInputSessions.size(); index++) {
159 if (mInputSessions.valueAt(index)->mSessionId == audioSession) {
bryant_liuba2b4392014-06-11 16:49:30 +0800160 break;
161 }
162 }
Eric Laurentfb66dd92016-01-28 18:32:03 -0800163 if (index == mInputSessions.size()) {
bryant_liuba2b4392014-06-11 16:49:30 +0800164 *count = 0;
165 return BAD_VALUE;
166 }
Andy Hungf42175b2023-12-19 19:03:19 -0800167 const std::vector<sp<AudioEffect>>& effects = mInputSessions.valueAt(index)->mEffects;
bryant_liuba2b4392014-06-11 16:49:30 +0800168
169 for (size_t i = 0; i < effects.size(); i++) {
170 effect_descriptor_t desc = effects[i]->descriptor();
171 if (i < *count) {
172 descriptors[i] = desc;
173 }
174 }
175 if (effects.size() > *count) {
176 status = NO_MEMORY;
177 }
178 *count = effects.size();
179 return status;
180}
181
182
Eric Laurentfb66dd92016-01-28 18:32:03 -0800183status_t AudioPolicyEffects::queryDefaultOutputSessionEffects(audio_session_t audioSession,
bryant_liuba2b4392014-06-11 16:49:30 +0800184 effect_descriptor_t *descriptors,
185 uint32_t *count)
186{
187 status_t status = NO_ERROR;
188
Andy Hung79eacdb2023-11-30 19:34:24 -0800189 audio_utils::lock_guard _l(mMutex);
bryant_liuba2b4392014-06-11 16:49:30 +0800190 size_t index;
191 for (index = 0; index < mOutputSessions.size(); index++) {
192 if (mOutputSessions.valueAt(index)->mSessionId == audioSession) {
193 break;
194 }
195 }
196 if (index == mOutputSessions.size()) {
197 *count = 0;
198 return BAD_VALUE;
199 }
Andy Hungf42175b2023-12-19 19:03:19 -0800200 const std::vector<sp<AudioEffect>>& effects = mOutputSessions.valueAt(index)->mEffects;
bryant_liuba2b4392014-06-11 16:49:30 +0800201
202 for (size_t i = 0; i < effects.size(); i++) {
203 effect_descriptor_t desc = effects[i]->descriptor();
204 if (i < *count) {
205 descriptors[i] = desc;
206 }
207 }
208 if (effects.size() > *count) {
209 status = NO_MEMORY;
210 }
211 *count = effects.size();
212 return status;
213}
214
215
216status_t AudioPolicyEffects::addOutputSessionEffects(audio_io_handle_t output,
217 audio_stream_type_t stream,
Eric Laurentfb66dd92016-01-28 18:32:03 -0800218 audio_session_t audioSession)
bryant_liuba2b4392014-06-11 16:49:30 +0800219{
220 status_t status = NO_ERROR;
221
Andy Hung79eacdb2023-11-30 19:34:24 -0800222 audio_utils::lock_guard _l(mMutex);
bryant_liuba2b4392014-06-11 16:49:30 +0800223 // create audio processors according to stream
Eric Laurent223fd5c2014-11-11 13:43:36 -0800224 // FIXME: should we have specific post processing settings for internal streams?
225 // default to media for now.
226 if (stream >= AUDIO_STREAM_PUBLIC_CNT) {
227 stream = AUDIO_STREAM_MUSIC;
228 }
bryant_liuba2b4392014-06-11 16:49:30 +0800229 ssize_t index = mOutputStreams.indexOfKey(stream);
230 if (index < 0) {
231 ALOGV("addOutputSessionEffects(): no output processing needed for this stream");
232 return NO_ERROR;
233 }
234
235 ssize_t idx = mOutputSessions.indexOfKey(audioSession);
Andy Hungf42175b2023-12-19 19:03:19 -0800236 std::shared_ptr<EffectVector> procDesc;
bryant_liuba2b4392014-06-11 16:49:30 +0800237 if (idx < 0) {
Andy Hungf42175b2023-12-19 19:03:19 -0800238 procDesc = std::make_shared<EffectVector>(audioSession);
bryant_liuba2b4392014-06-11 16:49:30 +0800239 mOutputSessions.add(audioSession, procDesc);
240 } else {
bryant_liu890a5632014-08-20 18:06:13 +0800241 // EffectVector is existing and we just need to increase ref count
bryant_liuba2b4392014-06-11 16:49:30 +0800242 procDesc = mOutputSessions.valueAt(idx);
243 }
bryant_liu890a5632014-08-20 18:06:13 +0800244 procDesc->mRefCount++;
245
Eric Laurent7de5ac12014-10-21 09:07:11 -0700246 ALOGV("addOutputSessionEffects(): session: %d, refCount: %d",
247 audioSession, procDesc->mRefCount);
248 if (procDesc->mRefCount == 1) {
Eric Laurentb6436272016-12-07 19:24:50 -0800249 // make sure effects are associated to audio server even if we are executing a binder call
250 int64_t token = IPCThreadState::self()->clearCallingIdentity();
Andy Hungf42175b2023-12-19 19:03:19 -0800251 const std::shared_ptr<EffectDescVector>& effects = mOutputStreams.valueAt(index);
252 for (const std::shared_ptr<EffectDesc>& effect : *effects) {
Svet Ganov3e5f14f2021-05-13 22:51:08 +0000253 AttributionSourceState attributionSource;
254 attributionSource.packageName = "android";
255 attributionSource.token = sp<BBinder>::make();
Andy Hungf42175b2023-12-19 19:03:19 -0800256 auto fx = sp<AudioEffect>::make(attributionSource);
Atneya Nair884f7992022-05-17 19:22:42 -0400257 fx->set(nullptr /* type */, &effect->mUuid, 0 /* priority */, nullptr /* callback */,
258 audioSession, output);
Eric Laurent7de5ac12014-10-21 09:07:11 -0700259 status_t status = fx->initCheck();
260 if (status != NO_ERROR && status != ALREADY_EXISTS) {
261 ALOGE("addOutputSessionEffects(): failed to create Fx %s on session %d",
Andy Hung7760a852023-12-19 17:27:52 -0800262 effect->mName.c_str(), audioSession);
Eric Laurent7de5ac12014-10-21 09:07:11 -0700263 // fx goes out of scope and strong ref on AudioEffect is released
264 continue;
265 }
266 ALOGV("addOutputSessionEffects(): added Fx %s on session: %d for stream: %d",
Andy Hung7760a852023-12-19 17:27:52 -0800267 effect->mName.c_str(), audioSession, (int32_t)stream);
Andy Hungf42175b2023-12-19 19:03:19 -0800268 procDesc->mEffects.push_back(std::move(fx));
bryant_liuba2b4392014-06-11 16:49:30 +0800269 }
Eric Laurent7de5ac12014-10-21 09:07:11 -0700270
271 procDesc->setProcessorEnabled(true);
Eric Laurentb6436272016-12-07 19:24:50 -0800272 IPCThreadState::self()->restoreCallingIdentity(token);
bryant_liuba2b4392014-06-11 16:49:30 +0800273 }
bryant_liuba2b4392014-06-11 16:49:30 +0800274 return status;
275}
276
277status_t AudioPolicyEffects::releaseOutputSessionEffects(audio_io_handle_t output,
278 audio_stream_type_t stream,
Eric Laurentfb66dd92016-01-28 18:32:03 -0800279 audio_session_t audioSession)
bryant_liuba2b4392014-06-11 16:49:30 +0800280{
281 status_t status = NO_ERROR;
282 (void) output; // argument not used for now
283 (void) stream; // argument not used for now
284
Andy Hung79eacdb2023-11-30 19:34:24 -0800285 audio_utils::lock_guard _l(mMutex);
bryant_liuba2b4392014-06-11 16:49:30 +0800286 ssize_t index = mOutputSessions.indexOfKey(audioSession);
287 if (index < 0) {
288 ALOGV("releaseOutputSessionEffects: no output processing was attached to this stream");
289 return NO_ERROR;
290 }
291
Andy Hungf42175b2023-12-19 19:03:19 -0800292 std::shared_ptr<EffectVector> procDesc = mOutputSessions.valueAt(index);
bryant_liu890a5632014-08-20 18:06:13 +0800293 procDesc->mRefCount--;
Eric Laurent7de5ac12014-10-21 09:07:11 -0700294 ALOGV("releaseOutputSessionEffects(): session: %d, refCount: %d",
295 audioSession, procDesc->mRefCount);
bryant_liu890a5632014-08-20 18:06:13 +0800296 if (procDesc->mRefCount == 0) {
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700297 procDesc->setProcessorEnabled(false);
bryant_liu890a5632014-08-20 18:06:13 +0800298 procDesc->mEffects.clear();
bryant_liu890a5632014-08-20 18:06:13 +0800299 mOutputSessions.removeItemsAt(index);
300 ALOGV("releaseOutputSessionEffects(): output processing released from session: %d",
301 audioSession);
302 }
bryant_liuba2b4392014-06-11 16:49:30 +0800303 return status;
304}
305
Ari Hausman-Cohen24628312018-08-13 15:01:09 -0700306status_t AudioPolicyEffects::addSourceDefaultEffect(const effect_uuid_t *type,
307 const String16& opPackageName,
308 const effect_uuid_t *uuid,
309 int32_t priority,
310 audio_source_t source,
311 audio_unique_id_t* id)
312{
313 if (uuid == NULL || type == NULL) {
314 ALOGE("addSourceDefaultEffect(): Null uuid or type uuid pointer");
315 return BAD_VALUE;
316 }
317
Eric Laurentae4b6ec2019-01-15 18:34:38 -0800318 // HOTWORD, FM_TUNER and ECHO_REFERENCE are special case sources > MAX.
Ari Hausman-Cohen24628312018-08-13 15:01:09 -0700319 if (source < AUDIO_SOURCE_DEFAULT ||
320 (source > AUDIO_SOURCE_MAX &&
321 source != AUDIO_SOURCE_HOTWORD &&
Eric Laurentae4b6ec2019-01-15 18:34:38 -0800322 source != AUDIO_SOURCE_FM_TUNER &&
Carter Hsua3abb402021-10-26 11:11:20 +0800323 source != AUDIO_SOURCE_ECHO_REFERENCE &&
324 source != AUDIO_SOURCE_ULTRASOUND)) {
Ari Hausman-Cohen24628312018-08-13 15:01:09 -0700325 ALOGE("addSourceDefaultEffect(): Unsupported source type %d", source);
326 return BAD_VALUE;
327 }
328
329 // Check that |uuid| or |type| corresponds to an effect on the system.
330 effect_descriptor_t descriptor = {};
331 status_t res = AudioEffect::getEffectDescriptor(
332 uuid, type, EFFECT_FLAG_TYPE_PRE_PROC, &descriptor);
333 if (res != OK) {
334 ALOGE("addSourceDefaultEffect(): Failed to find effect descriptor matching uuid/type.");
335 return res;
336 }
337
338 // Only pre-processing effects can be added dynamically as source defaults.
339 if ((descriptor.flags & EFFECT_FLAG_TYPE_MASK) != EFFECT_FLAG_TYPE_PRE_PROC) {
340 ALOGE("addSourceDefaultEffect(): Desired effect cannot be attached "
341 "as a source default effect.");
342 return BAD_VALUE;
343 }
344
Andy Hung79eacdb2023-11-30 19:34:24 -0800345 audio_utils::lock_guard _l(mMutex);
Ari Hausman-Cohen24628312018-08-13 15:01:09 -0700346
347 // Find the EffectDescVector for the given source type, or create a new one if necessary.
348 ssize_t index = mInputSources.indexOfKey(source);
Andy Hungf42175b2023-12-19 19:03:19 -0800349 std::shared_ptr<EffectDescVector> desc;
Ari Hausman-Cohen24628312018-08-13 15:01:09 -0700350 if (index < 0) {
351 // No effects for this source type yet.
Andy Hungf42175b2023-12-19 19:03:19 -0800352 desc = std::make_shared<EffectDescVector>();
Ari Hausman-Cohen24628312018-08-13 15:01:09 -0700353 mInputSources.add(source, desc);
354 } else {
355 desc = mInputSources.valueAt(index);
356 }
357
358 // Create a new effect and add it to the vector.
359 res = AudioEffect::newEffectUniqueId(id);
360 if (res != OK) {
361 ALOGE("addSourceDefaultEffect(): failed to get new unique id.");
362 return res;
363 }
Andy Hungf42175b2023-12-19 19:03:19 -0800364 std::shared_ptr<EffectDesc> effect = std::make_shared<EffectDesc>(
Eric Laurent2685aa02022-02-01 14:26:38 +0100365 descriptor.name, descriptor.type, opPackageName, descriptor.uuid, priority, *id);
Andy Hungf42175b2023-12-19 19:03:19 -0800366 desc->push_back(std::move(effect));
Ari Hausman-Cohen24628312018-08-13 15:01:09 -0700367 // TODO(b/71813697): Support setting params as well.
368
369 // TODO(b/71814300): Retroactively attach to any existing sources of the given type.
370 // This requires tracking the source type of each session id in addition to what is
371 // already being tracked.
372
373 return NO_ERROR;
374}
375
Ari Hausman-Cohen433722e2018-04-24 14:25:22 -0700376status_t AudioPolicyEffects::addStreamDefaultEffect(const effect_uuid_t *type,
377 const String16& opPackageName,
378 const effect_uuid_t *uuid,
379 int32_t priority,
380 audio_usage_t usage,
381 audio_unique_id_t* id)
382{
383 if (uuid == NULL || type == NULL) {
384 ALOGE("addStreamDefaultEffect(): Null uuid or type uuid pointer");
385 return BAD_VALUE;
386 }
François Gaffie58d4be52018-11-06 15:30:12 +0100387 audio_stream_type_t stream = AudioSystem::attributesToStreamType(attributes_initializer(usage));
Ari Hausman-Cohen433722e2018-04-24 14:25:22 -0700388
389 if (stream < AUDIO_STREAM_MIN || stream >= AUDIO_STREAM_PUBLIC_CNT) {
390 ALOGE("addStreamDefaultEffect(): Unsupported stream type %d", stream);
391 return BAD_VALUE;
392 }
393
394 // Check that |uuid| or |type| corresponds to an effect on the system.
395 effect_descriptor_t descriptor = {};
396 status_t res = AudioEffect::getEffectDescriptor(
397 uuid, type, EFFECT_FLAG_TYPE_INSERT, &descriptor);
398 if (res != OK) {
399 ALOGE("addStreamDefaultEffect(): Failed to find effect descriptor matching uuid/type.");
400 return res;
401 }
402
403 // Only insert effects can be added dynamically as stream defaults.
404 if ((descriptor.flags & EFFECT_FLAG_TYPE_MASK) != EFFECT_FLAG_TYPE_INSERT) {
405 ALOGE("addStreamDefaultEffect(): Desired effect cannot be attached "
406 "as a stream default effect.");
407 return BAD_VALUE;
408 }
409
Andy Hung79eacdb2023-11-30 19:34:24 -0800410 audio_utils::lock_guard _l(mMutex);
Ari Hausman-Cohen433722e2018-04-24 14:25:22 -0700411
412 // Find the EffectDescVector for the given stream type, or create a new one if necessary.
413 ssize_t index = mOutputStreams.indexOfKey(stream);
Andy Hungf42175b2023-12-19 19:03:19 -0800414 std::shared_ptr<EffectDescVector> desc;
Ari Hausman-Cohen433722e2018-04-24 14:25:22 -0700415 if (index < 0) {
416 // No effects for this stream type yet.
Andy Hungf42175b2023-12-19 19:03:19 -0800417 desc = std::make_shared<EffectDescVector>();
Ari Hausman-Cohen433722e2018-04-24 14:25:22 -0700418 mOutputStreams.add(stream, desc);
419 } else {
420 desc = mOutputStreams.valueAt(index);
421 }
422
423 // Create a new effect and add it to the vector.
424 res = AudioEffect::newEffectUniqueId(id);
425 if (res != OK) {
426 ALOGE("addStreamDefaultEffect(): failed to get new unique id.");
427 return res;
428 }
Andy Hungf42175b2023-12-19 19:03:19 -0800429 std::shared_ptr<EffectDesc> effect = std::make_shared<EffectDesc>(
Eric Laurent2685aa02022-02-01 14:26:38 +0100430 descriptor.name, descriptor.type, opPackageName, descriptor.uuid, priority, *id);
Andy Hungf42175b2023-12-19 19:03:19 -0800431 desc->push_back(std::move(effect));
Ari Hausman-Cohen433722e2018-04-24 14:25:22 -0700432 // TODO(b/71813697): Support setting params as well.
433
434 // TODO(b/71814300): Retroactively attach to any existing streams of the given type.
435 // This requires tracking the stream type of each session id in addition to what is
436 // already being tracked.
437
438 return NO_ERROR;
439}
440
Ari Hausman-Cohen24628312018-08-13 15:01:09 -0700441status_t AudioPolicyEffects::removeSourceDefaultEffect(audio_unique_id_t id)
442{
443 if (id == AUDIO_UNIQUE_ID_ALLOCATE) {
444 // ALLOCATE is not a unique identifier, but rather a reserved value indicating
445 // a real id has not been assigned. For default effects, this value is only used
446 // by system-owned defaults from the loaded config, which cannot be removed.
447 return BAD_VALUE;
448 }
449
Andy Hung79eacdb2023-11-30 19:34:24 -0800450 audio_utils::lock_guard _l(mMutex);
Ari Hausman-Cohen24628312018-08-13 15:01:09 -0700451
452 // Check each source type.
453 size_t numSources = mInputSources.size();
454 for (size_t i = 0; i < numSources; ++i) {
455 // Check each effect for each source.
Andy Hungf42175b2023-12-19 19:03:19 -0800456 auto descVector = mInputSources[i];
457 for (auto desc = descVector->begin(); desc != descVector->end(); ++desc) {
Ari Hausman-Cohen24628312018-08-13 15:01:09 -0700458 if ((*desc)->mId == id) {
459 // Found it!
460 // TODO(b/71814300): Remove from any sources the effect was attached to.
Andy Hungf42175b2023-12-19 19:03:19 -0800461 descVector->erase(desc);
Ari Hausman-Cohen24628312018-08-13 15:01:09 -0700462 // Handles are unique; there can only be one match, so return early.
463 return NO_ERROR;
464 }
465 }
466 }
467
468 // Effect wasn't found, so it's been trivially removed successfully.
469 return NO_ERROR;
470}
471
Ari Hausman-Cohen433722e2018-04-24 14:25:22 -0700472status_t AudioPolicyEffects::removeStreamDefaultEffect(audio_unique_id_t id)
473{
474 if (id == AUDIO_UNIQUE_ID_ALLOCATE) {
475 // ALLOCATE is not a unique identifier, but rather a reserved value indicating
476 // a real id has not been assigned. For default effects, this value is only used
477 // by system-owned defaults from the loaded config, which cannot be removed.
478 return BAD_VALUE;
479 }
480
Andy Hung79eacdb2023-11-30 19:34:24 -0800481 audio_utils::lock_guard _l(mMutex);
Ari Hausman-Cohen433722e2018-04-24 14:25:22 -0700482
483 // Check each stream type.
484 size_t numStreams = mOutputStreams.size();
485 for (size_t i = 0; i < numStreams; ++i) {
486 // Check each effect for each stream.
Andy Hungf42175b2023-12-19 19:03:19 -0800487 auto descVector = mOutputStreams[i];
488 for (auto desc = descVector->begin(); desc != descVector->end(); ++desc) {
Ari Hausman-Cohen433722e2018-04-24 14:25:22 -0700489 if ((*desc)->mId == id) {
490 // Found it!
491 // TODO(b/71814300): Remove from any streams the effect was attached to.
Andy Hungf42175b2023-12-19 19:03:19 -0800492 descVector->erase(desc);
Ari Hausman-Cohen433722e2018-04-24 14:25:22 -0700493 // Handles are unique; there can only be one match, so return early.
494 return NO_ERROR;
495 }
496 }
497 }
498
499 // Effect wasn't found, so it's been trivially removed successfully.
500 return NO_ERROR;
501}
bryant_liuba2b4392014-06-11 16:49:30 +0800502
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700503void AudioPolicyEffects::EffectVector::setProcessorEnabled(bool enabled)
bryant_liuba2b4392014-06-11 16:49:30 +0800504{
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700505 for (size_t i = 0; i < mEffects.size(); i++) {
Andy Hungf42175b2023-12-19 19:03:19 -0800506 mEffects[i]->setEnabled(enabled);
bryant_liuba2b4392014-06-11 16:49:30 +0800507 }
508}
509
510
511// ----------------------------------------------------------------------------
512// Audio processing configuration
513// ----------------------------------------------------------------------------
514
Andy Hungd3595ed2023-12-19 15:34:46 -0800515// we keep to const char* instead of std::string_view as comparison is believed faster.
516constexpr const char* kInputSourceNames[AUDIO_SOURCE_CNT - 1] = {
bryant_liuba2b4392014-06-11 16:49:30 +0800517 MIC_SRC_TAG,
518 VOICE_UL_SRC_TAG,
519 VOICE_DL_SRC_TAG,
520 VOICE_CALL_SRC_TAG,
521 CAMCORDER_SRC_TAG,
522 VOICE_REC_SRC_TAG,
rago8a397d52015-12-02 11:27:57 -0800523 VOICE_COMM_SRC_TAG,
Carter Hsua3abb402021-10-26 11:11:20 +0800524 REMOTE_SUBMIX_SRC_TAG,
Eric Laurentae4b6ec2019-01-15 18:34:38 -0800525 UNPROCESSED_SRC_TAG,
526 VOICE_PERFORMANCE_SRC_TAG
bryant_liuba2b4392014-06-11 16:49:30 +0800527};
528
529// returns the audio_source_t enum corresponding to the input source name or
530// AUDIO_SOURCE_CNT is no match found
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700531/*static*/ audio_source_t AudioPolicyEffects::inputSourceNameToEnum(const char *name)
bryant_liuba2b4392014-06-11 16:49:30 +0800532{
533 int i;
534 for (i = AUDIO_SOURCE_MIC; i < AUDIO_SOURCE_CNT; i++) {
535 if (strcmp(name, kInputSourceNames[i - AUDIO_SOURCE_MIC]) == 0) {
536 ALOGV("inputSourceNameToEnum found source %s %d", name, i);
537 break;
538 }
539 }
540 return (audio_source_t)i;
541}
542
Andy Hungd3595ed2023-12-19 15:34:46 -0800543// +1 as enum starts from -1
544constexpr const char* kStreamNames[AUDIO_STREAM_PUBLIC_CNT + 1] = {
bryant_liuba2b4392014-06-11 16:49:30 +0800545 AUDIO_STREAM_DEFAULT_TAG,
546 AUDIO_STREAM_VOICE_CALL_TAG,
547 AUDIO_STREAM_SYSTEM_TAG,
548 AUDIO_STREAM_RING_TAG,
549 AUDIO_STREAM_MUSIC_TAG,
550 AUDIO_STREAM_ALARM_TAG,
551 AUDIO_STREAM_NOTIFICATION_TAG,
552 AUDIO_STREAM_BLUETOOTH_SCO_TAG,
553 AUDIO_STREAM_ENFORCED_AUDIBLE_TAG,
554 AUDIO_STREAM_DTMF_TAG,
Baekgyeong Kim3a26bb22019-10-30 20:29:41 +0900555 AUDIO_STREAM_TTS_TAG,
556 AUDIO_STREAM_ASSISTANT_TAG
bryant_liuba2b4392014-06-11 16:49:30 +0800557};
558
559// returns the audio_stream_t enum corresponding to the output stream name or
Eric Laurent223fd5c2014-11-11 13:43:36 -0800560// AUDIO_STREAM_PUBLIC_CNT is no match found
Andy Hungd3595ed2023-12-19 15:34:46 -0800561/* static */
bryant_liuba2b4392014-06-11 16:49:30 +0800562audio_stream_type_t AudioPolicyEffects::streamNameToEnum(const char *name)
563{
564 int i;
Eric Laurent223fd5c2014-11-11 13:43:36 -0800565 for (i = AUDIO_STREAM_DEFAULT; i < AUDIO_STREAM_PUBLIC_CNT; i++) {
bryant_liuba2b4392014-06-11 16:49:30 +0800566 if (strcmp(name, kStreamNames[i - AUDIO_STREAM_DEFAULT]) == 0) {
567 ALOGV("streamNameToEnum found stream %s %d", name, i);
568 break;
569 }
570 }
571 return (audio_stream_type_t)i;
572}
573
574// ----------------------------------------------------------------------------
575// Audio Effect Config parser
576// ----------------------------------------------------------------------------
577
Andy Hungd3595ed2023-12-19 15:34:46 -0800578/* static */
Eric Laurent138ed172016-02-10 10:40:44 -0800579size_t AudioPolicyEffects::growParamSize(char **param,
bryant_liuba2b4392014-06-11 16:49:30 +0800580 size_t size,
581 size_t *curSize,
582 size_t *totSize)
583{
584 // *curSize is at least sizeof(effect_param_t) + 2 * sizeof(int)
585 size_t pos = ((*curSize - 1 ) / size + 1) * size;
586
587 if (pos + size > *totSize) {
588 while (pos + size > *totSize) {
589 *totSize += ((*totSize + 7) / 8) * 4;
590 }
George Burgess IV31225682018-02-12 11:08:38 -0800591 char *newParam = (char *)realloc(*param, *totSize);
592 if (newParam == NULL) {
Eric Laurent138ed172016-02-10 10:40:44 -0800593 ALOGE("%s realloc error for size %zu", __func__, *totSize);
594 return 0;
595 }
George Burgess IV31225682018-02-12 11:08:38 -0800596 *param = newParam;
bryant_liuba2b4392014-06-11 16:49:30 +0800597 }
598 *curSize = pos + size;
599 return pos;
600}
601
Andy Hungd3595ed2023-12-19 15:34:46 -0800602/* static */
bryant_liuba2b4392014-06-11 16:49:30 +0800603size_t AudioPolicyEffects::readParamValue(cnode *node,
Eric Laurent138ed172016-02-10 10:40:44 -0800604 char **param,
bryant_liuba2b4392014-06-11 16:49:30 +0800605 size_t *curSize,
606 size_t *totSize)
607{
Eric Laurent138ed172016-02-10 10:40:44 -0800608 size_t len = 0;
609 size_t pos;
610
bryant_liuba2b4392014-06-11 16:49:30 +0800611 if (strncmp(node->name, SHORT_TAG, sizeof(SHORT_TAG) + 1) == 0) {
Eric Laurent138ed172016-02-10 10:40:44 -0800612 pos = growParamSize(param, sizeof(short), curSize, totSize);
613 if (pos == 0) {
614 goto exit;
bryant_liuba2b4392014-06-11 16:49:30 +0800615 }
Eric Laurent138ed172016-02-10 10:40:44 -0800616 *(short *)(*param + pos) = (short)atoi(node->value);
617 ALOGV("readParamValue() reading short %d", *(short *)(*param + pos));
618 len = sizeof(short);
619 } else if (strncmp(node->name, INT_TAG, sizeof(INT_TAG) + 1) == 0) {
620 pos = growParamSize(param, sizeof(int), curSize, totSize);
621 if (pos == 0) {
622 goto exit;
623 }
624 *(int *)(*param + pos) = atoi(node->value);
625 ALOGV("readParamValue() reading int %d", *(int *)(*param + pos));
626 len = sizeof(int);
627 } else if (strncmp(node->name, FLOAT_TAG, sizeof(FLOAT_TAG) + 1) == 0) {
628 pos = growParamSize(param, sizeof(float), curSize, totSize);
629 if (pos == 0) {
630 goto exit;
631 }
632 *(float *)(*param + pos) = (float)atof(node->value);
633 ALOGV("readParamValue() reading float %f",*(float *)(*param + pos));
634 len = sizeof(float);
635 } else if (strncmp(node->name, BOOL_TAG, sizeof(BOOL_TAG) + 1) == 0) {
636 pos = growParamSize(param, sizeof(bool), curSize, totSize);
637 if (pos == 0) {
638 goto exit;
639 }
640 if (strncmp(node->value, "true", strlen("true") + 1) == 0) {
641 *(bool *)(*param + pos) = true;
642 } else {
643 *(bool *)(*param + pos) = false;
644 }
645 ALOGV("readParamValue() reading bool %s",
646 *(bool *)(*param + pos) ? "true" : "false");
647 len = sizeof(bool);
bryant_liuba2b4392014-06-11 16:49:30 +0800648 } else if (strncmp(node->name, STRING_TAG, sizeof(STRING_TAG) + 1) == 0) {
Eric Laurent138ed172016-02-10 10:40:44 -0800649 len = strnlen(node->value, EFFECT_STRING_LEN_MAX);
bryant_liuba2b4392014-06-11 16:49:30 +0800650 if (*curSize + len + 1 > *totSize) {
651 *totSize = *curSize + len + 1;
Chih-Hung Hsieh03077682018-08-30 14:11:00 -0700652 char *newParam = (char *)realloc(*param, *totSize);
653 if (newParam == NULL) {
Eric Laurent138ed172016-02-10 10:40:44 -0800654 len = 0;
655 ALOGE("%s realloc error for string len %zu", __func__, *totSize);
656 goto exit;
657 }
Chih-Hung Hsieh03077682018-08-30 14:11:00 -0700658 *param = newParam;
bryant_liuba2b4392014-06-11 16:49:30 +0800659 }
Eric Laurent138ed172016-02-10 10:40:44 -0800660 strncpy(*param + *curSize, node->value, len);
bryant_liuba2b4392014-06-11 16:49:30 +0800661 *curSize += len;
Eric Laurent138ed172016-02-10 10:40:44 -0800662 (*param)[*curSize] = '\0';
663 ALOGV("readParamValue() reading string %s", *param + *curSize - len);
664 } else {
665 ALOGW("readParamValue() unknown param type %s", node->name);
bryant_liuba2b4392014-06-11 16:49:30 +0800666 }
Eric Laurent138ed172016-02-10 10:40:44 -0800667exit:
668 return len;
bryant_liuba2b4392014-06-11 16:49:30 +0800669}
670
Andy Hungd3595ed2023-12-19 15:34:46 -0800671/* static */
Andy Hung7760a852023-12-19 17:27:52 -0800672std::shared_ptr<const effect_param_t> AudioPolicyEffects::loadEffectParameter(cnode* root)
bryant_liuba2b4392014-06-11 16:49:30 +0800673{
674 cnode *param;
675 cnode *value;
676 size_t curSize = sizeof(effect_param_t);
677 size_t totSize = sizeof(effect_param_t) + 2 * sizeof(int);
678 effect_param_t *fx_param = (effect_param_t *)malloc(totSize);
679
Eric Laurent138ed172016-02-10 10:40:44 -0800680 if (fx_param == NULL) {
681 ALOGE("%s malloc error for effect structure of size %zu",
682 __func__, totSize);
683 return NULL;
684 }
685
bryant_liuba2b4392014-06-11 16:49:30 +0800686 param = config_find(root, PARAM_TAG);
687 value = config_find(root, VALUE_TAG);
688 if (param == NULL && value == NULL) {
689 // try to parse simple parameter form {int int}
690 param = root->first_child;
691 if (param != NULL) {
692 // Note: that a pair of random strings is read as 0 0
693 int *ptr = (int *)fx_param->data;
Eric Laurent138ed172016-02-10 10:40:44 -0800694#if LOG_NDEBUG == 0
bryant_liuba2b4392014-06-11 16:49:30 +0800695 int *ptr2 = (int *)((char *)param + sizeof(effect_param_t));
Eric Laurent138ed172016-02-10 10:40:44 -0800696 ALOGV("loadEffectParameter() ptr %p ptr2 %p", ptr, ptr2);
697#endif
bryant_liuba2b4392014-06-11 16:49:30 +0800698 *ptr++ = atoi(param->name);
699 *ptr = atoi(param->value);
700 fx_param->psize = sizeof(int);
701 fx_param->vsize = sizeof(int);
Andy Hung7760a852023-12-19 17:27:52 -0800702 return {fx_param, free};
bryant_liuba2b4392014-06-11 16:49:30 +0800703 }
704 }
705 if (param == NULL || value == NULL) {
Eric Laurent138ed172016-02-10 10:40:44 -0800706 ALOGW("loadEffectParameter() invalid parameter description %s",
707 root->name);
bryant_liuba2b4392014-06-11 16:49:30 +0800708 goto error;
709 }
710
711 fx_param->psize = 0;
712 param = param->first_child;
713 while (param) {
714 ALOGV("loadEffectParameter() reading param of type %s", param->name);
Eric Laurent138ed172016-02-10 10:40:44 -0800715 size_t size =
716 readParamValue(param, (char **)&fx_param, &curSize, &totSize);
bryant_liuba2b4392014-06-11 16:49:30 +0800717 if (size == 0) {
718 goto error;
719 }
720 fx_param->psize += size;
721 param = param->next;
722 }
723
724 // align start of value field on 32 bit boundary
725 curSize = ((curSize - 1 ) / sizeof(int) + 1) * sizeof(int);
726
727 fx_param->vsize = 0;
728 value = value->first_child;
729 while (value) {
730 ALOGV("loadEffectParameter() reading value of type %s", value->name);
Eric Laurent138ed172016-02-10 10:40:44 -0800731 size_t size =
732 readParamValue(value, (char **)&fx_param, &curSize, &totSize);
bryant_liuba2b4392014-06-11 16:49:30 +0800733 if (size == 0) {
734 goto error;
735 }
736 fx_param->vsize += size;
737 value = value->next;
738 }
739
Andy Hung7760a852023-12-19 17:27:52 -0800740 return {fx_param, free};
bryant_liuba2b4392014-06-11 16:49:30 +0800741
742error:
Eric Laurent138ed172016-02-10 10:40:44 -0800743 free(fx_param);
bryant_liuba2b4392014-06-11 16:49:30 +0800744 return NULL;
745}
746
Andy Hungd3595ed2023-12-19 15:34:46 -0800747/* static */
Andy Hung7760a852023-12-19 17:27:52 -0800748void AudioPolicyEffects::loadEffectParameters(
749 cnode* root, std::vector<std::shared_ptr<const effect_param_t>>& params)
bryant_liuba2b4392014-06-11 16:49:30 +0800750{
751 cnode *node = root->first_child;
752 while (node) {
753 ALOGV("loadEffectParameters() loading param %s", node->name);
Andy Hung7760a852023-12-19 17:27:52 -0800754 const auto param = loadEffectParameter(node);
755 if (param != nullptr) {
756 params.push_back(param);
bryant_liuba2b4392014-06-11 16:49:30 +0800757 }
bryant_liuba2b4392014-06-11 16:49:30 +0800758 node = node->next;
759 }
760}
761
Andy Hungd3595ed2023-12-19 15:34:46 -0800762/* static */
Andy Hungf42175b2023-12-19 19:03:19 -0800763std::shared_ptr<AudioPolicyEffects::EffectDescVector> AudioPolicyEffects::loadEffectConfig(
764 cnode* root, const EffectDescVector& effects)
bryant_liuba2b4392014-06-11 16:49:30 +0800765{
766 cnode *node = root->first_child;
767 if (node == NULL) {
768 ALOGW("loadInputSource() empty element %s", root->name);
769 return NULL;
770 }
Andy Hungf42175b2023-12-19 19:03:19 -0800771 auto desc = std::make_shared<EffectDescVector>();
bryant_liuba2b4392014-06-11 16:49:30 +0800772 while (node) {
773 size_t i;
Eric Laurent138ed172016-02-10 10:40:44 -0800774
bryant_liuba2b4392014-06-11 16:49:30 +0800775 for (i = 0; i < effects.size(); i++) {
Andy Hung7760a852023-12-19 17:27:52 -0800776 if (effects[i]->mName == node->name) {
bryant_liuba2b4392014-06-11 16:49:30 +0800777 ALOGV("loadEffectConfig() found effect %s in list", node->name);
778 break;
779 }
780 }
781 if (i == effects.size()) {
782 ALOGV("loadEffectConfig() effect %s not in list", node->name);
783 node = node->next;
784 continue;
785 }
Andy Hungf42175b2023-12-19 19:03:19 -0800786 auto effect = std::make_shared<EffectDesc>(*effects[i]); // deep copy
bryant_liuba2b4392014-06-11 16:49:30 +0800787 loadEffectParameters(node, effect->mParams);
788 ALOGV("loadEffectConfig() adding effect %s uuid %08x",
Andy Hung7760a852023-12-19 17:27:52 -0800789 effect->mName.c_str(), effect->mUuid.timeLow);
Andy Hungf42175b2023-12-19 19:03:19 -0800790 desc->push_back(std::move(effect));
bryant_liuba2b4392014-06-11 16:49:30 +0800791 node = node->next;
792 }
Andy Hungf42175b2023-12-19 19:03:19 -0800793 if (desc->empty()) {
bryant_liuba2b4392014-06-11 16:49:30 +0800794 ALOGW("loadEffectConfig() no valid effects found in config %s", root->name);
Andy Hungf42175b2023-12-19 19:03:19 -0800795 return nullptr;
bryant_liuba2b4392014-06-11 16:49:30 +0800796 }
797 return desc;
798}
799
Andy Hungd3595ed2023-12-19 15:34:46 -0800800status_t AudioPolicyEffects::loadInputEffectConfigurations_l(cnode* root,
Andy Hungf42175b2023-12-19 19:03:19 -0800801 const EffectDescVector& effects)
bryant_liuba2b4392014-06-11 16:49:30 +0800802{
803 cnode *node = config_find(root, PREPROCESSING_TAG);
804 if (node == NULL) {
805 return -ENOENT;
806 }
807 node = node->first_child;
808 while (node) {
809 audio_source_t source = inputSourceNameToEnum(node->name);
810 if (source == AUDIO_SOURCE_CNT) {
Andy Hungd3595ed2023-12-19 15:34:46 -0800811 ALOGW("%s() invalid input source %s", __func__, node->name);
bryant_liuba2b4392014-06-11 16:49:30 +0800812 node = node->next;
813 continue;
814 }
Andy Hungd3595ed2023-12-19 15:34:46 -0800815 ALOGV("%s() loading input source %s", __func__, node->name);
Andy Hungf42175b2023-12-19 19:03:19 -0800816 auto desc = loadEffectConfig(node, effects);
bryant_liuba2b4392014-06-11 16:49:30 +0800817 if (desc == NULL) {
818 node = node->next;
819 continue;
820 }
821 mInputSources.add(source, desc);
822 node = node->next;
823 }
824 return NO_ERROR;
825}
826
Andy Hungd3595ed2023-12-19 15:34:46 -0800827status_t AudioPolicyEffects::loadStreamEffectConfigurations_l(cnode* root,
Andy Hungf42175b2023-12-19 19:03:19 -0800828 const EffectDescVector& effects)
bryant_liuba2b4392014-06-11 16:49:30 +0800829{
830 cnode *node = config_find(root, OUTPUT_SESSION_PROCESSING_TAG);
831 if (node == NULL) {
832 return -ENOENT;
833 }
834 node = node->first_child;
835 while (node) {
836 audio_stream_type_t stream = streamNameToEnum(node->name);
Eric Laurent223fd5c2014-11-11 13:43:36 -0800837 if (stream == AUDIO_STREAM_PUBLIC_CNT) {
Andy Hungd3595ed2023-12-19 15:34:46 -0800838 ALOGW("%s() invalid output stream %s", __func__, node->name);
bryant_liuba2b4392014-06-11 16:49:30 +0800839 node = node->next;
840 continue;
841 }
Andy Hungd3595ed2023-12-19 15:34:46 -0800842 ALOGV("%s() loading output stream %s", __func__, node->name);
Andy Hungf42175b2023-12-19 19:03:19 -0800843 std::shared_ptr<EffectDescVector> desc = loadEffectConfig(node, effects);
bryant_liuba2b4392014-06-11 16:49:30 +0800844 if (desc == NULL) {
845 node = node->next;
846 continue;
847 }
848 mOutputStreams.add(stream, desc);
849 node = node->next;
850 }
851 return NO_ERROR;
852}
853
Andy Hungd3595ed2023-12-19 15:34:46 -0800854/* static */
Andy Hungf42175b2023-12-19 19:03:19 -0800855std::shared_ptr<AudioPolicyEffects::EffectDesc> AudioPolicyEffects::loadEffect(cnode* root)
bryant_liuba2b4392014-06-11 16:49:30 +0800856{
857 cnode *node = config_find(root, UUID_TAG);
858 if (node == NULL) {
859 return NULL;
860 }
861 effect_uuid_t uuid;
862 if (AudioEffect::stringToGuid(node->value, &uuid) != NO_ERROR) {
863 ALOGW("loadEffect() invalid uuid %s", node->value);
864 return NULL;
865 }
Andy Hungf42175b2023-12-19 19:03:19 -0800866 return std::make_shared<EffectDesc>(root->name, uuid);
bryant_liuba2b4392014-06-11 16:49:30 +0800867}
868
Andy Hungd3595ed2023-12-19 15:34:46 -0800869/* static */
Andy Hungf42175b2023-12-19 19:03:19 -0800870android::AudioPolicyEffects::EffectDescVector AudioPolicyEffects::loadEffects(cnode *root)
bryant_liuba2b4392014-06-11 16:49:30 +0800871{
Andy Hungf42175b2023-12-19 19:03:19 -0800872 EffectDescVector effects;
bryant_liuba2b4392014-06-11 16:49:30 +0800873 cnode *node = config_find(root, EFFECTS_TAG);
874 if (node == NULL) {
Andy Hungf42175b2023-12-19 19:03:19 -0800875 ALOGW("%s() Cannot find %s configuration", __func__, EFFECTS_TAG);
876 return effects;
bryant_liuba2b4392014-06-11 16:49:30 +0800877 }
878 node = node->first_child;
879 while (node) {
880 ALOGV("loadEffects() loading effect %s", node->name);
Andy Hungf42175b2023-12-19 19:03:19 -0800881 auto effect = loadEffect(node);
bryant_liuba2b4392014-06-11 16:49:30 +0800882 if (effect == NULL) {
883 node = node->next;
884 continue;
885 }
Andy Hungf42175b2023-12-19 19:03:19 -0800886 effects.push_back(std::move(effect));
bryant_liuba2b4392014-06-11 16:49:30 +0800887 node = node->next;
888 }
Andy Hungf42175b2023-12-19 19:03:19 -0800889 return effects;
bryant_liuba2b4392014-06-11 16:49:30 +0800890}
891
Andy Hungd3595ed2023-12-19 15:34:46 -0800892status_t AudioPolicyEffects::loadAudioEffectConfig_ll(
Shunkai Yao8d6489a2023-04-18 23:14:25 +0000893 const sp<EffectsFactoryHalInterface>& effectsFactoryHal) {
894 if (!effectsFactoryHal) {
895 ALOGE("%s Null EffectsFactoryHalInterface", __func__);
896 return UNEXPECTED_NULL;
897 }
898
899 const auto skippedElements = VALUE_OR_RETURN_STATUS(effectsFactoryHal->getSkippedElements());
900 const auto processings = effectsFactoryHal->getProcessings();
901 if (!processings) {
902 ALOGE("%s Null processings with %zu skipped elements", __func__, skippedElements);
903 return UNEXPECTED_NULL;
Kevin Rocard4fb615c2017-06-26 10:28:13 -0700904 }
905
906 auto loadProcessingChain = [](auto& processingChain, auto& streams) {
907 for (auto& stream : processingChain) {
Andy Hungf42175b2023-12-19 19:03:19 -0800908 auto effectDescs = std::make_shared<EffectDescVector>();
Kevin Rocard4fb615c2017-06-26 10:28:13 -0700909 for (auto& effect : stream.effects) {
Andy Hungf42175b2023-12-19 19:03:19 -0800910 effectDescs->push_back(
Andy Hungbb2f2bf2023-12-27 13:17:16 -0800911 std::make_shared<EffectDesc>(effect->name, effect->uuid));
Kevin Rocard4fb615c2017-06-26 10:28:13 -0700912 }
Andy Hungf42175b2023-12-19 19:03:19 -0800913 streams.add(stream.type, std::move(effectDescs));
Kevin Rocard4fb615c2017-06-26 10:28:13 -0700914 }
915 };
François Gaffie06182982020-01-07 15:16:14 +0100916
Shunkai Yao8d6489a2023-04-18 23:14:25 +0000917 auto loadDeviceProcessingChain = [](auto& processingChain, auto& devicesEffects) {
François Gaffie06182982020-01-07 15:16:14 +0100918 for (auto& deviceProcess : processingChain) {
François Gaffie06182982020-01-07 15:16:14 +0100919 auto effectDescs = std::make_unique<EffectDescVector>();
920 for (auto& effect : deviceProcess.effects) {
Andy Hungf42175b2023-12-19 19:03:19 -0800921 effectDescs->push_back(
Andy Hungbb2f2bf2023-12-27 13:17:16 -0800922 std::make_shared<EffectDesc>(effect->name, effect->uuid));
François Gaffie06182982020-01-07 15:16:14 +0100923 }
Andy Hungf42175b2023-12-19 19:03:19 -0800924 auto devEffects = std::make_unique<DeviceEffects>(
François Gaffie06182982020-01-07 15:16:14 +0100925 std::move(effectDescs), deviceProcess.type, deviceProcess.address);
Andy Hungf42175b2023-12-19 19:03:19 -0800926 devicesEffects.emplace(deviceProcess.address, std::move(devEffects));
François Gaffie06182982020-01-07 15:16:14 +0100927 }
928 };
929
Andy Hungd3595ed2023-12-19 15:34:46 -0800930 // access to mInputSources and mOutputStreams requires mMutex;
Shunkai Yao8d6489a2023-04-18 23:14:25 +0000931 loadProcessingChain(processings->preprocess, mInputSources);
932 loadProcessingChain(processings->postprocess, mOutputStreams);
933
Andy Hungd3595ed2023-12-19 15:34:46 -0800934 // access to mDeviceEffects requires mDeviceEffectsMutex
935 loadDeviceProcessingChain(processings->deviceprocess, mDeviceEffects);
Shunkai Yao8d6489a2023-04-18 23:14:25 +0000936
937 return skippedElements;
Kevin Rocard4fb615c2017-06-26 10:28:13 -0700938}
939
Andy Hungd3595ed2023-12-19 15:34:46 -0800940status_t AudioPolicyEffects::loadAudioEffectConfigLegacy_l(const char *path)
Shunkai Yaoeab8a7c2023-05-15 21:07:08 +0000941{
942 cnode *root;
943 char *data;
944
945 data = (char *)load_file(path, NULL);
946 if (data == NULL) {
947 return -ENODEV;
948 }
949 root = config_node("", "");
950 config_load(root, data);
951
Andy Hungf42175b2023-12-19 19:03:19 -0800952 const EffectDescVector effects = loadEffects(root);
Andy Hungd3595ed2023-12-19 15:34:46 -0800953
954 // requires mMutex
955 loadInputEffectConfigurations_l(root, effects);
956 loadStreamEffectConfigurations_l(root, effects);
Shunkai Yaoeab8a7c2023-05-15 21:07:08 +0000957 config_free(root);
958 free(root);
959 free(data);
960
961 return NO_ERROR;
962}
963
François Gaffie06182982020-01-07 15:16:14 +0100964void AudioPolicyEffects::initDefaultDeviceEffects()
965{
Andy Hungd3595ed2023-12-19 15:34:46 -0800966 std::lock_guard _l(mDeviceEffectsMutex);
François Gaffie06182982020-01-07 15:16:14 +0100967 for (const auto& deviceEffectsIter : mDeviceEffects) {
968 const auto& deviceEffects = deviceEffectsIter.second;
Andy Hungf42175b2023-12-19 19:03:19 -0800969 for (const auto& effectDesc : *deviceEffects->mEffectDescriptors) {
Svet Ganov3e5f14f2021-05-13 22:51:08 +0000970 AttributionSourceState attributionSource;
971 attributionSource.packageName = "android";
972 attributionSource.token = sp<BBinder>::make();
Andy Hungf42175b2023-12-19 19:03:19 -0800973 sp<AudioEffect> fx = sp<AudioEffect>::make(attributionSource);
Atneya Nair884f7992022-05-17 19:22:42 -0400974 fx->set(EFFECT_UUID_NULL, &effectDesc->mUuid, 0 /* priority */, nullptr /* callback */,
975 AUDIO_SESSION_DEVICE, AUDIO_IO_HANDLE_NONE,
Mikhail Naganov69d41cc2020-07-31 17:36:08 -0700976 AudioDeviceTypeAddr{deviceEffects->getDeviceType(),
977 deviceEffects->getDeviceAddress()});
François Gaffie06182982020-01-07 15:16:14 +0100978 status_t status = fx->initCheck();
979 if (status != NO_ERROR && status != ALREADY_EXISTS) {
980 ALOGE("%s(): failed to create Fx %s on port type=%d address=%s", __func__,
Andy Hung7760a852023-12-19 17:27:52 -0800981 effectDesc->mName.c_str(), deviceEffects->getDeviceType(),
François Gaffie06182982020-01-07 15:16:14 +0100982 deviceEffects->getDeviceAddress().c_str());
983 // fx goes out of scope and strong ref on AudioEffect is released
984 continue;
985 }
986 fx->setEnabled(true);
987 ALOGV("%s(): create Fx %s added on port type=%d address=%s", __func__,
Andy Hung7760a852023-12-19 17:27:52 -0800988 effectDesc->mName.c_str(), deviceEffects->getDeviceType(),
François Gaffie06182982020-01-07 15:16:14 +0100989 deviceEffects->getDeviceAddress().c_str());
Andy Hungf42175b2023-12-19 19:03:19 -0800990 deviceEffects->mEffects.push_back(std::move(fx));
François Gaffie06182982020-01-07 15:16:14 +0100991 }
992 }
993}
bryant_liuba2b4392014-06-11 16:49:30 +0800994
Mikhail Naganov1b2a7942017-12-08 10:18:09 -0800995} // namespace android