blob: 0b42c50c0eab253ed6382d8b36ac1ae8cda0c615 [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 +080069AudioPolicyEffects::~AudioPolicyEffects()
70{
71 size_t i = 0;
72 // release audio input processing resources
73 for (i = 0; i < mInputSources.size(); i++) {
74 delete mInputSources.valueAt(i);
75 }
76 mInputSources.clear();
77
Eric Laurentfb66dd92016-01-28 18:32:03 -080078 for (i = 0; i < mInputSessions.size(); i++) {
79 mInputSessions.valueAt(i)->mEffects.clear();
80 delete mInputSessions.valueAt(i);
bryant_liuba2b4392014-06-11 16:49:30 +080081 }
Eric Laurentfb66dd92016-01-28 18:32:03 -080082 mInputSessions.clear();
bryant_liuba2b4392014-06-11 16:49:30 +080083
84 // release audio output processing resources
85 for (i = 0; i < mOutputStreams.size(); i++) {
86 delete mOutputStreams.valueAt(i);
87 }
88 mOutputStreams.clear();
89
90 for (i = 0; i < mOutputSessions.size(); i++) {
91 mOutputSessions.valueAt(i)->mEffects.clear();
92 delete mOutputSessions.valueAt(i);
93 }
94 mOutputSessions.clear();
95}
96
97
98status_t AudioPolicyEffects::addInputEffects(audio_io_handle_t input,
99 audio_source_t inputSource,
Eric Laurentfb66dd92016-01-28 18:32:03 -0800100 audio_session_t audioSession)
bryant_liuba2b4392014-06-11 16:49:30 +0800101{
102 status_t status = NO_ERROR;
103
104 // create audio pre processors according to input source
105 audio_source_t aliasSource = (inputSource == AUDIO_SOURCE_HOTWORD) ?
106 AUDIO_SOURCE_VOICE_RECOGNITION : inputSource;
107
Andy Hung79eacdb2023-11-30 19:34:24 -0800108 audio_utils::lock_guard _l(mMutex);
bryant_liuba2b4392014-06-11 16:49:30 +0800109 ssize_t index = mInputSources.indexOfKey(aliasSource);
110 if (index < 0) {
111 ALOGV("addInputEffects(): no processing needs to be attached to this source");
112 return status;
113 }
Eric Laurentfb66dd92016-01-28 18:32:03 -0800114 ssize_t idx = mInputSessions.indexOfKey(audioSession);
115 EffectVector *sessionDesc;
bryant_liuba2b4392014-06-11 16:49:30 +0800116 if (idx < 0) {
Eric Laurentfb66dd92016-01-28 18:32:03 -0800117 sessionDesc = new EffectVector(audioSession);
118 mInputSessions.add(audioSession, sessionDesc);
bryant_liuba2b4392014-06-11 16:49:30 +0800119 } else {
bryant_liu890a5632014-08-20 18:06:13 +0800120 // EffectVector is existing and we just need to increase ref count
Eric Laurentfb66dd92016-01-28 18:32:03 -0800121 sessionDesc = mInputSessions.valueAt(idx);
bryant_liuba2b4392014-06-11 16:49:30 +0800122 }
Eric Laurentfb66dd92016-01-28 18:32:03 -0800123 sessionDesc->mRefCount++;
bryant_liu890a5632014-08-20 18:06:13 +0800124
Eric Laurentfb66dd92016-01-28 18:32:03 -0800125 ALOGV("addInputEffects(): input: %d, refCount: %d", input, sessionDesc->mRefCount);
126 if (sessionDesc->mRefCount == 1) {
Eric Laurentb6436272016-12-07 19:24:50 -0800127 int64_t token = IPCThreadState::self()->clearCallingIdentity();
Eric Laurent7de5ac12014-10-21 09:07:11 -0700128 Vector <EffectDesc *> effects = mInputSources.valueAt(index)->mEffects;
129 for (size_t i = 0; i < effects.size(); i++) {
130 EffectDesc *effect = effects[i];
Svet Ganov3e5f14f2021-05-13 22:51:08 +0000131 AttributionSourceState attributionSource;
132 attributionSource.packageName = "android";
133 attributionSource.token = sp<BBinder>::make();
134 sp<AudioEffect> fx = new AudioEffect(attributionSource);
Atneya Nair884f7992022-05-17 19:22:42 -0400135 fx->set(nullptr /*type */, &effect->mUuid, -1 /* priority */, nullptr /* callback */,
136 audioSession, input);
Eric Laurent7de5ac12014-10-21 09:07:11 -0700137 status_t status = fx->initCheck();
138 if (status != NO_ERROR && status != ALREADY_EXISTS) {
139 ALOGW("addInputEffects(): failed to create Fx %s on source %d",
140 effect->mName, (int32_t)aliasSource);
141 // fx goes out of scope and strong ref on AudioEffect is released
142 continue;
143 }
144 for (size_t j = 0; j < effect->mParams.size(); j++) {
145 fx->setParameter(effect->mParams[j]);
146 }
147 ALOGV("addInputEffects(): added Fx %s on source: %d",
bryant_liuba2b4392014-06-11 16:49:30 +0800148 effect->mName, (int32_t)aliasSource);
Eric Laurentfb66dd92016-01-28 18:32:03 -0800149 sessionDesc->mEffects.add(fx);
bryant_liuba2b4392014-06-11 16:49:30 +0800150 }
Eric Laurentfb66dd92016-01-28 18:32:03 -0800151 sessionDesc->setProcessorEnabled(true);
Eric Laurentb6436272016-12-07 19:24:50 -0800152 IPCThreadState::self()->restoreCallingIdentity(token);
bryant_liuba2b4392014-06-11 16:49:30 +0800153 }
bryant_liuba2b4392014-06-11 16:49:30 +0800154 return status;
155}
156
157
Eric Laurentfb66dd92016-01-28 18:32:03 -0800158status_t AudioPolicyEffects::releaseInputEffects(audio_io_handle_t input,
159 audio_session_t audioSession)
bryant_liuba2b4392014-06-11 16:49:30 +0800160{
161 status_t status = NO_ERROR;
162
Andy Hung79eacdb2023-11-30 19:34:24 -0800163 audio_utils::lock_guard _l(mMutex);
Eric Laurentfb66dd92016-01-28 18:32:03 -0800164 ssize_t index = mInputSessions.indexOfKey(audioSession);
bryant_liuba2b4392014-06-11 16:49:30 +0800165 if (index < 0) {
166 return status;
167 }
Eric Laurentfb66dd92016-01-28 18:32:03 -0800168 EffectVector *sessionDesc = mInputSessions.valueAt(index);
169 sessionDesc->mRefCount--;
170 ALOGV("releaseInputEffects(): input: %d, refCount: %d", input, sessionDesc->mRefCount);
171 if (sessionDesc->mRefCount == 0) {
172 sessionDesc->setProcessorEnabled(false);
173 delete sessionDesc;
174 mInputSessions.removeItemsAt(index);
bryant_liu890a5632014-08-20 18:06:13 +0800175 ALOGV("releaseInputEffects(): all effects released");
176 }
bryant_liuba2b4392014-06-11 16:49:30 +0800177 return status;
178}
179
Eric Laurentfb66dd92016-01-28 18:32:03 -0800180status_t AudioPolicyEffects::queryDefaultInputEffects(audio_session_t audioSession,
bryant_liuba2b4392014-06-11 16:49:30 +0800181 effect_descriptor_t *descriptors,
182 uint32_t *count)
183{
184 status_t status = NO_ERROR;
185
Andy Hung79eacdb2023-11-30 19:34:24 -0800186 audio_utils::lock_guard _l(mMutex);
bryant_liuba2b4392014-06-11 16:49:30 +0800187 size_t index;
Eric Laurentfb66dd92016-01-28 18:32:03 -0800188 for (index = 0; index < mInputSessions.size(); index++) {
189 if (mInputSessions.valueAt(index)->mSessionId == audioSession) {
bryant_liuba2b4392014-06-11 16:49:30 +0800190 break;
191 }
192 }
Eric Laurentfb66dd92016-01-28 18:32:03 -0800193 if (index == mInputSessions.size()) {
bryant_liuba2b4392014-06-11 16:49:30 +0800194 *count = 0;
195 return BAD_VALUE;
196 }
Eric Laurentfb66dd92016-01-28 18:32:03 -0800197 Vector< sp<AudioEffect> > effects = mInputSessions.valueAt(index)->mEffects;
bryant_liuba2b4392014-06-11 16:49:30 +0800198
199 for (size_t i = 0; i < effects.size(); i++) {
200 effect_descriptor_t desc = effects[i]->descriptor();
201 if (i < *count) {
202 descriptors[i] = desc;
203 }
204 }
205 if (effects.size() > *count) {
206 status = NO_MEMORY;
207 }
208 *count = effects.size();
209 return status;
210}
211
212
Eric Laurentfb66dd92016-01-28 18:32:03 -0800213status_t AudioPolicyEffects::queryDefaultOutputSessionEffects(audio_session_t audioSession,
bryant_liuba2b4392014-06-11 16:49:30 +0800214 effect_descriptor_t *descriptors,
215 uint32_t *count)
216{
217 status_t status = NO_ERROR;
218
Andy Hung79eacdb2023-11-30 19:34:24 -0800219 audio_utils::lock_guard _l(mMutex);
bryant_liuba2b4392014-06-11 16:49:30 +0800220 size_t index;
221 for (index = 0; index < mOutputSessions.size(); index++) {
222 if (mOutputSessions.valueAt(index)->mSessionId == audioSession) {
223 break;
224 }
225 }
226 if (index == mOutputSessions.size()) {
227 *count = 0;
228 return BAD_VALUE;
229 }
230 Vector< sp<AudioEffect> > effects = mOutputSessions.valueAt(index)->mEffects;
231
232 for (size_t i = 0; i < effects.size(); i++) {
233 effect_descriptor_t desc = effects[i]->descriptor();
234 if (i < *count) {
235 descriptors[i] = desc;
236 }
237 }
238 if (effects.size() > *count) {
239 status = NO_MEMORY;
240 }
241 *count = effects.size();
242 return status;
243}
244
245
246status_t AudioPolicyEffects::addOutputSessionEffects(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{
250 status_t status = NO_ERROR;
251
Andy Hung79eacdb2023-11-30 19:34:24 -0800252 audio_utils::lock_guard _l(mMutex);
bryant_liuba2b4392014-06-11 16:49:30 +0800253 // create audio processors according to stream
Eric Laurent223fd5c2014-11-11 13:43:36 -0800254 // FIXME: should we have specific post processing settings for internal streams?
255 // default to media for now.
256 if (stream >= AUDIO_STREAM_PUBLIC_CNT) {
257 stream = AUDIO_STREAM_MUSIC;
258 }
bryant_liuba2b4392014-06-11 16:49:30 +0800259 ssize_t index = mOutputStreams.indexOfKey(stream);
260 if (index < 0) {
261 ALOGV("addOutputSessionEffects(): no output processing needed for this stream");
262 return NO_ERROR;
263 }
264
265 ssize_t idx = mOutputSessions.indexOfKey(audioSession);
266 EffectVector *procDesc;
267 if (idx < 0) {
268 procDesc = new EffectVector(audioSession);
269 mOutputSessions.add(audioSession, procDesc);
270 } else {
bryant_liu890a5632014-08-20 18:06:13 +0800271 // EffectVector is existing and we just need to increase ref count
bryant_liuba2b4392014-06-11 16:49:30 +0800272 procDesc = mOutputSessions.valueAt(idx);
273 }
bryant_liu890a5632014-08-20 18:06:13 +0800274 procDesc->mRefCount++;
275
Eric Laurent7de5ac12014-10-21 09:07:11 -0700276 ALOGV("addOutputSessionEffects(): session: %d, refCount: %d",
277 audioSession, procDesc->mRefCount);
278 if (procDesc->mRefCount == 1) {
Eric Laurentb6436272016-12-07 19:24:50 -0800279 // make sure effects are associated to audio server even if we are executing a binder call
280 int64_t token = IPCThreadState::self()->clearCallingIdentity();
Eric Laurent7de5ac12014-10-21 09:07:11 -0700281 Vector <EffectDesc *> effects = mOutputStreams.valueAt(index)->mEffects;
282 for (size_t i = 0; i < effects.size(); i++) {
283 EffectDesc *effect = effects[i];
Svet Ganov3e5f14f2021-05-13 22:51:08 +0000284 AttributionSourceState attributionSource;
285 attributionSource.packageName = "android";
286 attributionSource.token = sp<BBinder>::make();
287 sp<AudioEffect> fx = new AudioEffect(attributionSource);
Atneya Nair884f7992022-05-17 19:22:42 -0400288 fx->set(nullptr /* type */, &effect->mUuid, 0 /* priority */, nullptr /* callback */,
289 audioSession, output);
Eric Laurent7de5ac12014-10-21 09:07:11 -0700290 status_t status = fx->initCheck();
291 if (status != NO_ERROR && status != ALREADY_EXISTS) {
292 ALOGE("addOutputSessionEffects(): failed to create Fx %s on session %d",
293 effect->mName, audioSession);
294 // fx goes out of scope and strong ref on AudioEffect is released
295 continue;
296 }
297 ALOGV("addOutputSessionEffects(): added Fx %s on session: %d for stream: %d",
298 effect->mName, audioSession, (int32_t)stream);
299 procDesc->mEffects.add(fx);
bryant_liuba2b4392014-06-11 16:49:30 +0800300 }
Eric Laurent7de5ac12014-10-21 09:07:11 -0700301
302 procDesc->setProcessorEnabled(true);
Eric Laurentb6436272016-12-07 19:24:50 -0800303 IPCThreadState::self()->restoreCallingIdentity(token);
bryant_liuba2b4392014-06-11 16:49:30 +0800304 }
bryant_liuba2b4392014-06-11 16:49:30 +0800305 return status;
306}
307
308status_t AudioPolicyEffects::releaseOutputSessionEffects(audio_io_handle_t output,
309 audio_stream_type_t stream,
Eric Laurentfb66dd92016-01-28 18:32:03 -0800310 audio_session_t audioSession)
bryant_liuba2b4392014-06-11 16:49:30 +0800311{
312 status_t status = NO_ERROR;
313 (void) output; // argument not used for now
314 (void) stream; // argument not used for now
315
Andy Hung79eacdb2023-11-30 19:34:24 -0800316 audio_utils::lock_guard _l(mMutex);
bryant_liuba2b4392014-06-11 16:49:30 +0800317 ssize_t index = mOutputSessions.indexOfKey(audioSession);
318 if (index < 0) {
319 ALOGV("releaseOutputSessionEffects: no output processing was attached to this stream");
320 return NO_ERROR;
321 }
322
323 EffectVector *procDesc = mOutputSessions.valueAt(index);
bryant_liu890a5632014-08-20 18:06:13 +0800324 procDesc->mRefCount--;
Eric Laurent7de5ac12014-10-21 09:07:11 -0700325 ALOGV("releaseOutputSessionEffects(): session: %d, refCount: %d",
326 audioSession, procDesc->mRefCount);
bryant_liu890a5632014-08-20 18:06:13 +0800327 if (procDesc->mRefCount == 0) {
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700328 procDesc->setProcessorEnabled(false);
bryant_liu890a5632014-08-20 18:06:13 +0800329 procDesc->mEffects.clear();
330 delete procDesc;
331 mOutputSessions.removeItemsAt(index);
332 ALOGV("releaseOutputSessionEffects(): output processing released from session: %d",
333 audioSession);
334 }
bryant_liuba2b4392014-06-11 16:49:30 +0800335 return status;
336}
337
Ari Hausman-Cohen24628312018-08-13 15:01:09 -0700338status_t AudioPolicyEffects::addSourceDefaultEffect(const effect_uuid_t *type,
339 const String16& opPackageName,
340 const effect_uuid_t *uuid,
341 int32_t priority,
342 audio_source_t source,
343 audio_unique_id_t* id)
344{
345 if (uuid == NULL || type == NULL) {
346 ALOGE("addSourceDefaultEffect(): Null uuid or type uuid pointer");
347 return BAD_VALUE;
348 }
349
Eric Laurentae4b6ec2019-01-15 18:34:38 -0800350 // HOTWORD, FM_TUNER and ECHO_REFERENCE are special case sources > MAX.
Ari Hausman-Cohen24628312018-08-13 15:01:09 -0700351 if (source < AUDIO_SOURCE_DEFAULT ||
352 (source > AUDIO_SOURCE_MAX &&
353 source != AUDIO_SOURCE_HOTWORD &&
Eric Laurentae4b6ec2019-01-15 18:34:38 -0800354 source != AUDIO_SOURCE_FM_TUNER &&
Carter Hsua3abb402021-10-26 11:11:20 +0800355 source != AUDIO_SOURCE_ECHO_REFERENCE &&
356 source != AUDIO_SOURCE_ULTRASOUND)) {
Ari Hausman-Cohen24628312018-08-13 15:01:09 -0700357 ALOGE("addSourceDefaultEffect(): Unsupported source type %d", source);
358 return BAD_VALUE;
359 }
360
361 // Check that |uuid| or |type| corresponds to an effect on the system.
362 effect_descriptor_t descriptor = {};
363 status_t res = AudioEffect::getEffectDescriptor(
364 uuid, type, EFFECT_FLAG_TYPE_PRE_PROC, &descriptor);
365 if (res != OK) {
366 ALOGE("addSourceDefaultEffect(): Failed to find effect descriptor matching uuid/type.");
367 return res;
368 }
369
370 // Only pre-processing effects can be added dynamically as source defaults.
371 if ((descriptor.flags & EFFECT_FLAG_TYPE_MASK) != EFFECT_FLAG_TYPE_PRE_PROC) {
372 ALOGE("addSourceDefaultEffect(): Desired effect cannot be attached "
373 "as a source default effect.");
374 return BAD_VALUE;
375 }
376
Andy Hung79eacdb2023-11-30 19:34:24 -0800377 audio_utils::lock_guard _l(mMutex);
Ari Hausman-Cohen24628312018-08-13 15:01:09 -0700378
379 // Find the EffectDescVector for the given source type, or create a new one if necessary.
380 ssize_t index = mInputSources.indexOfKey(source);
381 EffectDescVector *desc = NULL;
382 if (index < 0) {
383 // No effects for this source type yet.
384 desc = new EffectDescVector();
385 mInputSources.add(source, desc);
386 } else {
387 desc = mInputSources.valueAt(index);
388 }
389
390 // Create a new effect and add it to the vector.
391 res = AudioEffect::newEffectUniqueId(id);
392 if (res != OK) {
393 ALOGE("addSourceDefaultEffect(): failed to get new unique id.");
394 return res;
395 }
396 EffectDesc *effect = new EffectDesc(
Eric Laurent2685aa02022-02-01 14:26:38 +0100397 descriptor.name, descriptor.type, opPackageName, descriptor.uuid, priority, *id);
Ari Hausman-Cohen24628312018-08-13 15:01:09 -0700398 desc->mEffects.add(effect);
399 // TODO(b/71813697): Support setting params as well.
400
401 // TODO(b/71814300): Retroactively attach to any existing sources of the given type.
402 // This requires tracking the source type of each session id in addition to what is
403 // already being tracked.
404
405 return NO_ERROR;
406}
407
Ari Hausman-Cohen433722e2018-04-24 14:25:22 -0700408status_t AudioPolicyEffects::addStreamDefaultEffect(const effect_uuid_t *type,
409 const String16& opPackageName,
410 const effect_uuid_t *uuid,
411 int32_t priority,
412 audio_usage_t usage,
413 audio_unique_id_t* id)
414{
415 if (uuid == NULL || type == NULL) {
416 ALOGE("addStreamDefaultEffect(): Null uuid or type uuid pointer");
417 return BAD_VALUE;
418 }
François Gaffie58d4be52018-11-06 15:30:12 +0100419 audio_stream_type_t stream = AudioSystem::attributesToStreamType(attributes_initializer(usage));
Ari Hausman-Cohen433722e2018-04-24 14:25:22 -0700420
421 if (stream < AUDIO_STREAM_MIN || stream >= AUDIO_STREAM_PUBLIC_CNT) {
422 ALOGE("addStreamDefaultEffect(): Unsupported stream type %d", stream);
423 return BAD_VALUE;
424 }
425
426 // Check that |uuid| or |type| corresponds to an effect on the system.
427 effect_descriptor_t descriptor = {};
428 status_t res = AudioEffect::getEffectDescriptor(
429 uuid, type, EFFECT_FLAG_TYPE_INSERT, &descriptor);
430 if (res != OK) {
431 ALOGE("addStreamDefaultEffect(): Failed to find effect descriptor matching uuid/type.");
432 return res;
433 }
434
435 // Only insert effects can be added dynamically as stream defaults.
436 if ((descriptor.flags & EFFECT_FLAG_TYPE_MASK) != EFFECT_FLAG_TYPE_INSERT) {
437 ALOGE("addStreamDefaultEffect(): Desired effect cannot be attached "
438 "as a stream default effect.");
439 return BAD_VALUE;
440 }
441
Andy Hung79eacdb2023-11-30 19:34:24 -0800442 audio_utils::lock_guard _l(mMutex);
Ari Hausman-Cohen433722e2018-04-24 14:25:22 -0700443
444 // Find the EffectDescVector for the given stream type, or create a new one if necessary.
445 ssize_t index = mOutputStreams.indexOfKey(stream);
446 EffectDescVector *desc = NULL;
447 if (index < 0) {
448 // No effects for this stream type yet.
449 desc = new EffectDescVector();
450 mOutputStreams.add(stream, desc);
451 } else {
452 desc = mOutputStreams.valueAt(index);
453 }
454
455 // Create a new effect and add it to the vector.
456 res = AudioEffect::newEffectUniqueId(id);
457 if (res != OK) {
458 ALOGE("addStreamDefaultEffect(): failed to get new unique id.");
459 return res;
460 }
461 EffectDesc *effect = new EffectDesc(
Eric Laurent2685aa02022-02-01 14:26:38 +0100462 descriptor.name, descriptor.type, opPackageName, descriptor.uuid, priority, *id);
Ari Hausman-Cohen433722e2018-04-24 14:25:22 -0700463 desc->mEffects.add(effect);
464 // TODO(b/71813697): Support setting params as well.
465
466 // TODO(b/71814300): Retroactively attach to any existing streams of the given type.
467 // This requires tracking the stream type of each session id in addition to what is
468 // already being tracked.
469
470 return NO_ERROR;
471}
472
Ari Hausman-Cohen24628312018-08-13 15:01:09 -0700473status_t AudioPolicyEffects::removeSourceDefaultEffect(audio_unique_id_t id)
474{
475 if (id == AUDIO_UNIQUE_ID_ALLOCATE) {
476 // ALLOCATE is not a unique identifier, but rather a reserved value indicating
477 // a real id has not been assigned. For default effects, this value is only used
478 // by system-owned defaults from the loaded config, which cannot be removed.
479 return BAD_VALUE;
480 }
481
Andy Hung79eacdb2023-11-30 19:34:24 -0800482 audio_utils::lock_guard _l(mMutex);
Ari Hausman-Cohen24628312018-08-13 15:01:09 -0700483
484 // Check each source type.
485 size_t numSources = mInputSources.size();
486 for (size_t i = 0; i < numSources; ++i) {
487 // Check each effect for each source.
488 EffectDescVector* descVector = mInputSources[i];
489 for (auto desc = descVector->mEffects.begin(); desc != descVector->mEffects.end(); ++desc) {
490 if ((*desc)->mId == id) {
491 // Found it!
492 // TODO(b/71814300): Remove from any sources the effect was attached to.
493 descVector->mEffects.erase(desc);
494 // Handles are unique; there can only be one match, so return early.
495 return NO_ERROR;
496 }
497 }
498 }
499
500 // Effect wasn't found, so it's been trivially removed successfully.
501 return NO_ERROR;
502}
503
Ari Hausman-Cohen433722e2018-04-24 14:25:22 -0700504status_t AudioPolicyEffects::removeStreamDefaultEffect(audio_unique_id_t id)
505{
506 if (id == AUDIO_UNIQUE_ID_ALLOCATE) {
507 // ALLOCATE is not a unique identifier, but rather a reserved value indicating
508 // a real id has not been assigned. For default effects, this value is only used
509 // by system-owned defaults from the loaded config, which cannot be removed.
510 return BAD_VALUE;
511 }
512
Andy Hung79eacdb2023-11-30 19:34:24 -0800513 audio_utils::lock_guard _l(mMutex);
Ari Hausman-Cohen433722e2018-04-24 14:25:22 -0700514
515 // Check each stream type.
516 size_t numStreams = mOutputStreams.size();
517 for (size_t i = 0; i < numStreams; ++i) {
518 // Check each effect for each stream.
519 EffectDescVector* descVector = mOutputStreams[i];
520 for (auto desc = descVector->mEffects.begin(); desc != descVector->mEffects.end(); ++desc) {
521 if ((*desc)->mId == id) {
522 // Found it!
523 // TODO(b/71814300): Remove from any streams the effect was attached to.
524 descVector->mEffects.erase(desc);
525 // Handles are unique; there can only be one match, so return early.
526 return NO_ERROR;
527 }
528 }
529 }
530
531 // Effect wasn't found, so it's been trivially removed successfully.
532 return NO_ERROR;
533}
bryant_liuba2b4392014-06-11 16:49:30 +0800534
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700535void AudioPolicyEffects::EffectVector::setProcessorEnabled(bool enabled)
bryant_liuba2b4392014-06-11 16:49:30 +0800536{
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700537 for (size_t i = 0; i < mEffects.size(); i++) {
538 mEffects.itemAt(i)->setEnabled(enabled);
bryant_liuba2b4392014-06-11 16:49:30 +0800539 }
540}
541
542
543// ----------------------------------------------------------------------------
544// Audio processing configuration
545// ----------------------------------------------------------------------------
546
Andy Hungd3595ed2023-12-19 15:34:46 -0800547// we keep to const char* instead of std::string_view as comparison is believed faster.
548constexpr const char* kInputSourceNames[AUDIO_SOURCE_CNT - 1] = {
bryant_liuba2b4392014-06-11 16:49:30 +0800549 MIC_SRC_TAG,
550 VOICE_UL_SRC_TAG,
551 VOICE_DL_SRC_TAG,
552 VOICE_CALL_SRC_TAG,
553 CAMCORDER_SRC_TAG,
554 VOICE_REC_SRC_TAG,
rago8a397d52015-12-02 11:27:57 -0800555 VOICE_COMM_SRC_TAG,
Carter Hsua3abb402021-10-26 11:11:20 +0800556 REMOTE_SUBMIX_SRC_TAG,
Eric Laurentae4b6ec2019-01-15 18:34:38 -0800557 UNPROCESSED_SRC_TAG,
558 VOICE_PERFORMANCE_SRC_TAG
bryant_liuba2b4392014-06-11 16:49:30 +0800559};
560
561// returns the audio_source_t enum corresponding to the input source name or
562// AUDIO_SOURCE_CNT is no match found
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700563/*static*/ audio_source_t AudioPolicyEffects::inputSourceNameToEnum(const char *name)
bryant_liuba2b4392014-06-11 16:49:30 +0800564{
565 int i;
566 for (i = AUDIO_SOURCE_MIC; i < AUDIO_SOURCE_CNT; i++) {
567 if (strcmp(name, kInputSourceNames[i - AUDIO_SOURCE_MIC]) == 0) {
568 ALOGV("inputSourceNameToEnum found source %s %d", name, i);
569 break;
570 }
571 }
572 return (audio_source_t)i;
573}
574
Andy Hungd3595ed2023-12-19 15:34:46 -0800575// +1 as enum starts from -1
576constexpr const char* kStreamNames[AUDIO_STREAM_PUBLIC_CNT + 1] = {
bryant_liuba2b4392014-06-11 16:49:30 +0800577 AUDIO_STREAM_DEFAULT_TAG,
578 AUDIO_STREAM_VOICE_CALL_TAG,
579 AUDIO_STREAM_SYSTEM_TAG,
580 AUDIO_STREAM_RING_TAG,
581 AUDIO_STREAM_MUSIC_TAG,
582 AUDIO_STREAM_ALARM_TAG,
583 AUDIO_STREAM_NOTIFICATION_TAG,
584 AUDIO_STREAM_BLUETOOTH_SCO_TAG,
585 AUDIO_STREAM_ENFORCED_AUDIBLE_TAG,
586 AUDIO_STREAM_DTMF_TAG,
Baekgyeong Kim3a26bb22019-10-30 20:29:41 +0900587 AUDIO_STREAM_TTS_TAG,
588 AUDIO_STREAM_ASSISTANT_TAG
bryant_liuba2b4392014-06-11 16:49:30 +0800589};
590
591// returns the audio_stream_t enum corresponding to the output stream name or
Eric Laurent223fd5c2014-11-11 13:43:36 -0800592// AUDIO_STREAM_PUBLIC_CNT is no match found
Andy Hungd3595ed2023-12-19 15:34:46 -0800593/* static */
bryant_liuba2b4392014-06-11 16:49:30 +0800594audio_stream_type_t AudioPolicyEffects::streamNameToEnum(const char *name)
595{
596 int i;
Eric Laurent223fd5c2014-11-11 13:43:36 -0800597 for (i = AUDIO_STREAM_DEFAULT; i < AUDIO_STREAM_PUBLIC_CNT; i++) {
bryant_liuba2b4392014-06-11 16:49:30 +0800598 if (strcmp(name, kStreamNames[i - AUDIO_STREAM_DEFAULT]) == 0) {
599 ALOGV("streamNameToEnum found stream %s %d", name, i);
600 break;
601 }
602 }
603 return (audio_stream_type_t)i;
604}
605
606// ----------------------------------------------------------------------------
607// Audio Effect Config parser
608// ----------------------------------------------------------------------------
609
Andy Hungd3595ed2023-12-19 15:34:46 -0800610/* static */
Eric Laurent138ed172016-02-10 10:40:44 -0800611size_t AudioPolicyEffects::growParamSize(char **param,
bryant_liuba2b4392014-06-11 16:49:30 +0800612 size_t size,
613 size_t *curSize,
614 size_t *totSize)
615{
616 // *curSize is at least sizeof(effect_param_t) + 2 * sizeof(int)
617 size_t pos = ((*curSize - 1 ) / size + 1) * size;
618
619 if (pos + size > *totSize) {
620 while (pos + size > *totSize) {
621 *totSize += ((*totSize + 7) / 8) * 4;
622 }
George Burgess IV31225682018-02-12 11:08:38 -0800623 char *newParam = (char *)realloc(*param, *totSize);
624 if (newParam == NULL) {
Eric Laurent138ed172016-02-10 10:40:44 -0800625 ALOGE("%s realloc error for size %zu", __func__, *totSize);
626 return 0;
627 }
George Burgess IV31225682018-02-12 11:08:38 -0800628 *param = newParam;
bryant_liuba2b4392014-06-11 16:49:30 +0800629 }
630 *curSize = pos + size;
631 return pos;
632}
633
Andy Hungd3595ed2023-12-19 15:34:46 -0800634/* static */
bryant_liuba2b4392014-06-11 16:49:30 +0800635size_t AudioPolicyEffects::readParamValue(cnode *node,
Eric Laurent138ed172016-02-10 10:40:44 -0800636 char **param,
bryant_liuba2b4392014-06-11 16:49:30 +0800637 size_t *curSize,
638 size_t *totSize)
639{
Eric Laurent138ed172016-02-10 10:40:44 -0800640 size_t len = 0;
641 size_t pos;
642
bryant_liuba2b4392014-06-11 16:49:30 +0800643 if (strncmp(node->name, SHORT_TAG, sizeof(SHORT_TAG) + 1) == 0) {
Eric Laurent138ed172016-02-10 10:40:44 -0800644 pos = growParamSize(param, sizeof(short), curSize, totSize);
645 if (pos == 0) {
646 goto exit;
bryant_liuba2b4392014-06-11 16:49:30 +0800647 }
Eric Laurent138ed172016-02-10 10:40:44 -0800648 *(short *)(*param + pos) = (short)atoi(node->value);
649 ALOGV("readParamValue() reading short %d", *(short *)(*param + pos));
650 len = sizeof(short);
651 } else if (strncmp(node->name, INT_TAG, sizeof(INT_TAG) + 1) == 0) {
652 pos = growParamSize(param, sizeof(int), curSize, totSize);
653 if (pos == 0) {
654 goto exit;
655 }
656 *(int *)(*param + pos) = atoi(node->value);
657 ALOGV("readParamValue() reading int %d", *(int *)(*param + pos));
658 len = sizeof(int);
659 } else if (strncmp(node->name, FLOAT_TAG, sizeof(FLOAT_TAG) + 1) == 0) {
660 pos = growParamSize(param, sizeof(float), curSize, totSize);
661 if (pos == 0) {
662 goto exit;
663 }
664 *(float *)(*param + pos) = (float)atof(node->value);
665 ALOGV("readParamValue() reading float %f",*(float *)(*param + pos));
666 len = sizeof(float);
667 } else if (strncmp(node->name, BOOL_TAG, sizeof(BOOL_TAG) + 1) == 0) {
668 pos = growParamSize(param, sizeof(bool), curSize, totSize);
669 if (pos == 0) {
670 goto exit;
671 }
672 if (strncmp(node->value, "true", strlen("true") + 1) == 0) {
673 *(bool *)(*param + pos) = true;
674 } else {
675 *(bool *)(*param + pos) = false;
676 }
677 ALOGV("readParamValue() reading bool %s",
678 *(bool *)(*param + pos) ? "true" : "false");
679 len = sizeof(bool);
bryant_liuba2b4392014-06-11 16:49:30 +0800680 } else if (strncmp(node->name, STRING_TAG, sizeof(STRING_TAG) + 1) == 0) {
Eric Laurent138ed172016-02-10 10:40:44 -0800681 len = strnlen(node->value, EFFECT_STRING_LEN_MAX);
bryant_liuba2b4392014-06-11 16:49:30 +0800682 if (*curSize + len + 1 > *totSize) {
683 *totSize = *curSize + len + 1;
Chih-Hung Hsieh03077682018-08-30 14:11:00 -0700684 char *newParam = (char *)realloc(*param, *totSize);
685 if (newParam == NULL) {
Eric Laurent138ed172016-02-10 10:40:44 -0800686 len = 0;
687 ALOGE("%s realloc error for string len %zu", __func__, *totSize);
688 goto exit;
689 }
Chih-Hung Hsieh03077682018-08-30 14:11:00 -0700690 *param = newParam;
bryant_liuba2b4392014-06-11 16:49:30 +0800691 }
Eric Laurent138ed172016-02-10 10:40:44 -0800692 strncpy(*param + *curSize, node->value, len);
bryant_liuba2b4392014-06-11 16:49:30 +0800693 *curSize += len;
Eric Laurent138ed172016-02-10 10:40:44 -0800694 (*param)[*curSize] = '\0';
695 ALOGV("readParamValue() reading string %s", *param + *curSize - len);
696 } else {
697 ALOGW("readParamValue() unknown param type %s", node->name);
bryant_liuba2b4392014-06-11 16:49:30 +0800698 }
Eric Laurent138ed172016-02-10 10:40:44 -0800699exit:
700 return len;
bryant_liuba2b4392014-06-11 16:49:30 +0800701}
702
Andy Hungd3595ed2023-12-19 15:34:46 -0800703/* static */
bryant_liuba2b4392014-06-11 16:49:30 +0800704effect_param_t *AudioPolicyEffects::loadEffectParameter(cnode *root)
705{
706 cnode *param;
707 cnode *value;
708 size_t curSize = sizeof(effect_param_t);
709 size_t totSize = sizeof(effect_param_t) + 2 * sizeof(int);
710 effect_param_t *fx_param = (effect_param_t *)malloc(totSize);
711
Eric Laurent138ed172016-02-10 10:40:44 -0800712 if (fx_param == NULL) {
713 ALOGE("%s malloc error for effect structure of size %zu",
714 __func__, totSize);
715 return NULL;
716 }
717
bryant_liuba2b4392014-06-11 16:49:30 +0800718 param = config_find(root, PARAM_TAG);
719 value = config_find(root, VALUE_TAG);
720 if (param == NULL && value == NULL) {
721 // try to parse simple parameter form {int int}
722 param = root->first_child;
723 if (param != NULL) {
724 // Note: that a pair of random strings is read as 0 0
725 int *ptr = (int *)fx_param->data;
Eric Laurent138ed172016-02-10 10:40:44 -0800726#if LOG_NDEBUG == 0
bryant_liuba2b4392014-06-11 16:49:30 +0800727 int *ptr2 = (int *)((char *)param + sizeof(effect_param_t));
Eric Laurent138ed172016-02-10 10:40:44 -0800728 ALOGV("loadEffectParameter() ptr %p ptr2 %p", ptr, ptr2);
729#endif
bryant_liuba2b4392014-06-11 16:49:30 +0800730 *ptr++ = atoi(param->name);
731 *ptr = atoi(param->value);
732 fx_param->psize = sizeof(int);
733 fx_param->vsize = sizeof(int);
734 return fx_param;
735 }
736 }
737 if (param == NULL || value == NULL) {
Eric Laurent138ed172016-02-10 10:40:44 -0800738 ALOGW("loadEffectParameter() invalid parameter description %s",
739 root->name);
bryant_liuba2b4392014-06-11 16:49:30 +0800740 goto error;
741 }
742
743 fx_param->psize = 0;
744 param = param->first_child;
745 while (param) {
746 ALOGV("loadEffectParameter() reading param of type %s", param->name);
Eric Laurent138ed172016-02-10 10:40:44 -0800747 size_t size =
748 readParamValue(param, (char **)&fx_param, &curSize, &totSize);
bryant_liuba2b4392014-06-11 16:49:30 +0800749 if (size == 0) {
750 goto error;
751 }
752 fx_param->psize += size;
753 param = param->next;
754 }
755
756 // align start of value field on 32 bit boundary
757 curSize = ((curSize - 1 ) / sizeof(int) + 1) * sizeof(int);
758
759 fx_param->vsize = 0;
760 value = value->first_child;
761 while (value) {
762 ALOGV("loadEffectParameter() reading value of type %s", value->name);
Eric Laurent138ed172016-02-10 10:40:44 -0800763 size_t size =
764 readParamValue(value, (char **)&fx_param, &curSize, &totSize);
bryant_liuba2b4392014-06-11 16:49:30 +0800765 if (size == 0) {
766 goto error;
767 }
768 fx_param->vsize += size;
769 value = value->next;
770 }
771
772 return fx_param;
773
774error:
Eric Laurent138ed172016-02-10 10:40:44 -0800775 free(fx_param);
bryant_liuba2b4392014-06-11 16:49:30 +0800776 return NULL;
777}
778
Andy Hungd3595ed2023-12-19 15:34:46 -0800779/* static */
bryant_liuba2b4392014-06-11 16:49:30 +0800780void AudioPolicyEffects::loadEffectParameters(cnode *root, Vector <effect_param_t *>& params)
781{
782 cnode *node = root->first_child;
783 while (node) {
784 ALOGV("loadEffectParameters() loading param %s", node->name);
785 effect_param_t *param = loadEffectParameter(node);
Eric Laurent138ed172016-02-10 10:40:44 -0800786 if (param != NULL) {
787 params.add(param);
bryant_liuba2b4392014-06-11 16:49:30 +0800788 }
bryant_liuba2b4392014-06-11 16:49:30 +0800789 node = node->next;
790 }
791}
792
Andy Hungd3595ed2023-12-19 15:34:46 -0800793/* static */
bryant_liuba2b4392014-06-11 16:49:30 +0800794AudioPolicyEffects::EffectDescVector *AudioPolicyEffects::loadEffectConfig(
795 cnode *root,
796 const Vector <EffectDesc *>& effects)
797{
798 cnode *node = root->first_child;
799 if (node == NULL) {
800 ALOGW("loadInputSource() empty element %s", root->name);
801 return NULL;
802 }
803 EffectDescVector *desc = new EffectDescVector();
804 while (node) {
805 size_t i;
Eric Laurent138ed172016-02-10 10:40:44 -0800806
bryant_liuba2b4392014-06-11 16:49:30 +0800807 for (i = 0; i < effects.size(); i++) {
808 if (strncmp(effects[i]->mName, node->name, EFFECT_STRING_LEN_MAX) == 0) {
809 ALOGV("loadEffectConfig() found effect %s in list", node->name);
810 break;
811 }
812 }
813 if (i == effects.size()) {
814 ALOGV("loadEffectConfig() effect %s not in list", node->name);
815 node = node->next;
816 continue;
817 }
818 EffectDesc *effect = new EffectDesc(*effects[i]); // deep copy
819 loadEffectParameters(node, effect->mParams);
820 ALOGV("loadEffectConfig() adding effect %s uuid %08x",
821 effect->mName, effect->mUuid.timeLow);
822 desc->mEffects.add(effect);
823 node = node->next;
824 }
825 if (desc->mEffects.size() == 0) {
826 ALOGW("loadEffectConfig() no valid effects found in config %s", root->name);
827 delete desc;
828 return NULL;
829 }
830 return desc;
831}
832
Andy Hungd3595ed2023-12-19 15:34:46 -0800833status_t AudioPolicyEffects::loadInputEffectConfigurations_l(cnode* root,
bryant_liuba2b4392014-06-11 16:49:30 +0800834 const Vector <EffectDesc *>& effects)
835{
836 cnode *node = config_find(root, PREPROCESSING_TAG);
837 if (node == NULL) {
838 return -ENOENT;
839 }
840 node = node->first_child;
841 while (node) {
842 audio_source_t source = inputSourceNameToEnum(node->name);
843 if (source == AUDIO_SOURCE_CNT) {
Andy Hungd3595ed2023-12-19 15:34:46 -0800844 ALOGW("%s() invalid input source %s", __func__, node->name);
bryant_liuba2b4392014-06-11 16:49:30 +0800845 node = node->next;
846 continue;
847 }
Andy Hungd3595ed2023-12-19 15:34:46 -0800848 ALOGV("%s() loading input source %s", __func__, node->name);
bryant_liuba2b4392014-06-11 16:49:30 +0800849 EffectDescVector *desc = loadEffectConfig(node, effects);
850 if (desc == NULL) {
851 node = node->next;
852 continue;
853 }
854 mInputSources.add(source, desc);
855 node = node->next;
856 }
857 return NO_ERROR;
858}
859
Andy Hungd3595ed2023-12-19 15:34:46 -0800860status_t AudioPolicyEffects::loadStreamEffectConfigurations_l(cnode* root,
bryant_liuba2b4392014-06-11 16:49:30 +0800861 const Vector <EffectDesc *>& effects)
862{
863 cnode *node = config_find(root, OUTPUT_SESSION_PROCESSING_TAG);
864 if (node == NULL) {
865 return -ENOENT;
866 }
867 node = node->first_child;
868 while (node) {
869 audio_stream_type_t stream = streamNameToEnum(node->name);
Eric Laurent223fd5c2014-11-11 13:43:36 -0800870 if (stream == AUDIO_STREAM_PUBLIC_CNT) {
Andy Hungd3595ed2023-12-19 15:34:46 -0800871 ALOGW("%s() invalid output stream %s", __func__, node->name);
bryant_liuba2b4392014-06-11 16:49:30 +0800872 node = node->next;
873 continue;
874 }
Andy Hungd3595ed2023-12-19 15:34:46 -0800875 ALOGV("%s() loading output stream %s", __func__, node->name);
bryant_liuba2b4392014-06-11 16:49:30 +0800876 EffectDescVector *desc = loadEffectConfig(node, effects);
877 if (desc == NULL) {
878 node = node->next;
879 continue;
880 }
881 mOutputStreams.add(stream, desc);
882 node = node->next;
883 }
884 return NO_ERROR;
885}
886
Andy Hungd3595ed2023-12-19 15:34:46 -0800887/* static */
bryant_liuba2b4392014-06-11 16:49:30 +0800888AudioPolicyEffects::EffectDesc *AudioPolicyEffects::loadEffect(cnode *root)
889{
890 cnode *node = config_find(root, UUID_TAG);
891 if (node == NULL) {
892 return NULL;
893 }
894 effect_uuid_t uuid;
895 if (AudioEffect::stringToGuid(node->value, &uuid) != NO_ERROR) {
896 ALOGW("loadEffect() invalid uuid %s", node->value);
897 return NULL;
898 }
899 return new EffectDesc(root->name, uuid);
900}
901
Andy Hungd3595ed2023-12-19 15:34:46 -0800902/* static */
bryant_liuba2b4392014-06-11 16:49:30 +0800903status_t AudioPolicyEffects::loadEffects(cnode *root, Vector <EffectDesc *>& effects)
904{
905 cnode *node = config_find(root, EFFECTS_TAG);
906 if (node == NULL) {
907 return -ENOENT;
908 }
909 node = node->first_child;
910 while (node) {
911 ALOGV("loadEffects() loading effect %s", node->name);
912 EffectDesc *effect = loadEffect(node);
913 if (effect == NULL) {
914 node = node->next;
915 continue;
916 }
917 effects.add(effect);
918 node = node->next;
919 }
920 return NO_ERROR;
921}
922
Andy Hungd3595ed2023-12-19 15:34:46 -0800923status_t AudioPolicyEffects::loadAudioEffectConfig_ll(
Shunkai Yao8d6489a2023-04-18 23:14:25 +0000924 const sp<EffectsFactoryHalInterface>& effectsFactoryHal) {
925 if (!effectsFactoryHal) {
926 ALOGE("%s Null EffectsFactoryHalInterface", __func__);
927 return UNEXPECTED_NULL;
928 }
929
930 const auto skippedElements = VALUE_OR_RETURN_STATUS(effectsFactoryHal->getSkippedElements());
931 const auto processings = effectsFactoryHal->getProcessings();
932 if (!processings) {
933 ALOGE("%s Null processings with %zu skipped elements", __func__, skippedElements);
934 return UNEXPECTED_NULL;
Kevin Rocard4fb615c2017-06-26 10:28:13 -0700935 }
936
937 auto loadProcessingChain = [](auto& processingChain, auto& streams) {
938 for (auto& stream : processingChain) {
939 auto effectDescs = std::make_unique<EffectDescVector>();
940 for (auto& effect : stream.effects) {
Shunkai Yao6c19bcf2023-05-08 20:40:06 +0000941 effectDescs->mEffects.add(new EffectDesc{effect->name.c_str(), effect->uuid});
Kevin Rocard4fb615c2017-06-26 10:28:13 -0700942 }
943 streams.add(stream.type, effectDescs.release());
944 }
945 };
François Gaffie06182982020-01-07 15:16:14 +0100946
Shunkai Yao8d6489a2023-04-18 23:14:25 +0000947 auto loadDeviceProcessingChain = [](auto& processingChain, auto& devicesEffects) {
François Gaffie06182982020-01-07 15:16:14 +0100948 for (auto& deviceProcess : processingChain) {
François Gaffie06182982020-01-07 15:16:14 +0100949 auto effectDescs = std::make_unique<EffectDescVector>();
950 for (auto& effect : deviceProcess.effects) {
Shunkai Yao6c19bcf2023-05-08 20:40:06 +0000951 effectDescs->mEffects.add(new EffectDesc{effect->name.c_str(), effect->uuid});
François Gaffie06182982020-01-07 15:16:14 +0100952 }
953 auto deviceEffects = std::make_unique<DeviceEffects>(
954 std::move(effectDescs), deviceProcess.type, deviceProcess.address);
955 devicesEffects.emplace(deviceProcess.address, std::move(deviceEffects));
956 }
957 };
958
Andy Hungd3595ed2023-12-19 15:34:46 -0800959 // access to mInputSources and mOutputStreams requires mMutex;
Shunkai Yao8d6489a2023-04-18 23:14:25 +0000960 loadProcessingChain(processings->preprocess, mInputSources);
961 loadProcessingChain(processings->postprocess, mOutputStreams);
962
Andy Hungd3595ed2023-12-19 15:34:46 -0800963 // access to mDeviceEffects requires mDeviceEffectsMutex
964 loadDeviceProcessingChain(processings->deviceprocess, mDeviceEffects);
Shunkai Yao8d6489a2023-04-18 23:14:25 +0000965
966 return skippedElements;
Kevin Rocard4fb615c2017-06-26 10:28:13 -0700967}
968
Andy Hungd3595ed2023-12-19 15:34:46 -0800969status_t AudioPolicyEffects::loadAudioEffectConfigLegacy_l(const char *path)
Shunkai Yaoeab8a7c2023-05-15 21:07:08 +0000970{
971 cnode *root;
972 char *data;
973
974 data = (char *)load_file(path, NULL);
975 if (data == NULL) {
976 return -ENODEV;
977 }
978 root = config_node("", "");
979 config_load(root, data);
980
981 Vector <EffectDesc *> effects;
982 loadEffects(root, effects);
Andy Hungd3595ed2023-12-19 15:34:46 -0800983
984 // requires mMutex
985 loadInputEffectConfigurations_l(root, effects);
986 loadStreamEffectConfigurations_l(root, effects);
Shunkai Yaoeab8a7c2023-05-15 21:07:08 +0000987
988 for (size_t i = 0; i < effects.size(); i++) {
989 delete effects[i];
990 }
991
992 config_free(root);
993 free(root);
994 free(data);
995
996 return NO_ERROR;
997}
998
François Gaffie06182982020-01-07 15:16:14 +0100999void AudioPolicyEffects::initDefaultDeviceEffects()
1000{
Andy Hungd3595ed2023-12-19 15:34:46 -08001001 std::lock_guard _l(mDeviceEffectsMutex);
François Gaffie06182982020-01-07 15:16:14 +01001002 for (const auto& deviceEffectsIter : mDeviceEffects) {
1003 const auto& deviceEffects = deviceEffectsIter.second;
1004 for (const auto& effectDesc : deviceEffects->mEffectDescriptors->mEffects) {
Svet Ganov3e5f14f2021-05-13 22:51:08 +00001005 AttributionSourceState attributionSource;
1006 attributionSource.packageName = "android";
1007 attributionSource.token = sp<BBinder>::make();
1008 sp<AudioEffect> fx = new AudioEffect(attributionSource);
Atneya Nair884f7992022-05-17 19:22:42 -04001009 fx->set(EFFECT_UUID_NULL, &effectDesc->mUuid, 0 /* priority */, nullptr /* callback */,
1010 AUDIO_SESSION_DEVICE, AUDIO_IO_HANDLE_NONE,
Mikhail Naganov69d41cc2020-07-31 17:36:08 -07001011 AudioDeviceTypeAddr{deviceEffects->getDeviceType(),
1012 deviceEffects->getDeviceAddress()});
François Gaffie06182982020-01-07 15:16:14 +01001013 status_t status = fx->initCheck();
1014 if (status != NO_ERROR && status != ALREADY_EXISTS) {
1015 ALOGE("%s(): failed to create Fx %s on port type=%d address=%s", __func__,
1016 effectDesc->mName, deviceEffects->getDeviceType(),
1017 deviceEffects->getDeviceAddress().c_str());
1018 // fx goes out of scope and strong ref on AudioEffect is released
1019 continue;
1020 }
1021 fx->setEnabled(true);
1022 ALOGV("%s(): create Fx %s added on port type=%d address=%s", __func__,
1023 effectDesc->mName, deviceEffects->getDeviceType(),
1024 deviceEffects->getDeviceAddress().c_str());
Jintao Zhu230397e2021-03-07 14:15:10 +08001025 deviceEffects->mEffects.push_back(fx);
François Gaffie06182982020-01-07 15:16:14 +01001026 }
1027 }
1028}
bryant_liuba2b4392014-06-11 16:49:30 +08001029
Mikhail Naganov1b2a7942017-12-08 10:18:09 -08001030} // namespace android