blob: b111865a5285b09b295d6d67d4aba3d1c68ea612 [file] [log] [blame]
bryant_liuba2b4392014-06-11 16:49:30 +08001/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "AudioPolicyEffects"
Eric Laurent897a4082014-07-11 16:51:53 -070018//#define LOG_NDEBUG 0
bryant_liuba2b4392014-06-11 16:49:30 +080019
20#include <stdlib.h>
21#include <stdio.h>
22#include <string.h>
Kevin Rocard4fb615c2017-06-26 10:28:13 -070023#include <memory>
bryant_liuba2b4392014-06-11 16:49:30 +080024#include <cutils/misc.h>
25#include <media/AudioEffect.h>
Kevin Rocard4fb615c2017-06-26 10:28:13 -070026#include <media/EffectsConfig.h>
Andy Hungab7ef302018-05-15 19:35:29 -070027#include <mediautils/ServiceUtilities.h>
bryant_liuba2b4392014-06-11 16:49:30 +080028#include <system/audio.h>
Mikhail Naganovc2f710f2016-10-17 18:05:36 -070029#include <system/audio_effects/audio_effects_conf.h>
bryant_liuba2b4392014-06-11 16:49:30 +080030#include <utils/Vector.h>
31#include <utils/SortedVector.h>
32#include <cutils/config_utils.h>
Eric Laurentb6436272016-12-07 19:24:50 -080033#include <binder/IPCThreadState.h>
bryant_liuba2b4392014-06-11 16:49:30 +080034#include "AudioPolicyEffects.h"
bryant_liuba2b4392014-06-11 16:49:30 +080035
36namespace android {
37
Svet Ganov3e5f14f2021-05-13 22:51:08 +000038using content::AttributionSourceState;
Philip P. Moltmannbda45752020-07-17 16:41:18 -070039
bryant_liuba2b4392014-06-11 16:49:30 +080040// ----------------------------------------------------------------------------
41// AudioPolicyEffects Implementation
42// ----------------------------------------------------------------------------
43
Shunkai Yao8d6489a2023-04-18 23:14:25 +000044AudioPolicyEffects::AudioPolicyEffects(const sp<EffectsFactoryHalInterface>& effectsFactoryHal) {
45 // load xml config with effectsFactoryHal
46 status_t loadResult = loadAudioEffectConfig(effectsFactoryHal);
François Gaffie06182982020-01-07 15:16:14 +010047 if (loadResult == NO_ERROR) {
Shunkai Yao8d6489a2023-04-18 23:14:25 +000048 mDefaultDeviceEffectFuture =
49 std::async(std::launch::async, &AudioPolicyEffects::initDefaultDeviceEffects, this);
François Gaffie06182982020-01-07 15:16:14 +010050 } else if (loadResult < 0) {
Shunkai Yao8d6489a2023-04-18 23:14:25 +000051 ALOGW("Failed to query effect configuration, fallback to load .conf");
Kevin Rocard4fb615c2017-06-26 10:28:13 -070052 // load automatic audio effect modules
53 if (access(AUDIO_EFFECT_VENDOR_CONFIG_FILE, R_OK) == 0) {
Shunkai Yao8d6489a2023-04-18 23:14:25 +000054 loadAudioEffectConfigLegacy(AUDIO_EFFECT_VENDOR_CONFIG_FILE);
Kevin Rocard4fb615c2017-06-26 10:28:13 -070055 } else if (access(AUDIO_EFFECT_DEFAULT_CONFIG_FILE, R_OK) == 0) {
Shunkai Yao8d6489a2023-04-18 23:14:25 +000056 loadAudioEffectConfigLegacy(AUDIO_EFFECT_DEFAULT_CONFIG_FILE);
Kevin Rocard4fb615c2017-06-26 10:28:13 -070057 }
58 } else if (loadResult > 0) {
59 ALOGE("Effect config is partially invalid, skipped %d elements", loadResult);
bryant_liuba2b4392014-06-11 16:49:30 +080060 }
61}
62
bryant_liuba2b4392014-06-11 16:49:30 +080063AudioPolicyEffects::~AudioPolicyEffects()
64{
65 size_t i = 0;
66 // release audio input processing resources
67 for (i = 0; i < mInputSources.size(); i++) {
68 delete mInputSources.valueAt(i);
69 }
70 mInputSources.clear();
71
Eric Laurentfb66dd92016-01-28 18:32:03 -080072 for (i = 0; i < mInputSessions.size(); i++) {
73 mInputSessions.valueAt(i)->mEffects.clear();
74 delete mInputSessions.valueAt(i);
bryant_liuba2b4392014-06-11 16:49:30 +080075 }
Eric Laurentfb66dd92016-01-28 18:32:03 -080076 mInputSessions.clear();
bryant_liuba2b4392014-06-11 16:49:30 +080077
78 // release audio output processing resources
79 for (i = 0; i < mOutputStreams.size(); i++) {
80 delete mOutputStreams.valueAt(i);
81 }
82 mOutputStreams.clear();
83
84 for (i = 0; i < mOutputSessions.size(); i++) {
85 mOutputSessions.valueAt(i)->mEffects.clear();
86 delete mOutputSessions.valueAt(i);
87 }
88 mOutputSessions.clear();
89}
90
91
92status_t AudioPolicyEffects::addInputEffects(audio_io_handle_t input,
93 audio_source_t inputSource,
Eric Laurentfb66dd92016-01-28 18:32:03 -080094 audio_session_t audioSession)
bryant_liuba2b4392014-06-11 16:49:30 +080095{
96 status_t status = NO_ERROR;
97
98 // create audio pre processors according to input source
99 audio_source_t aliasSource = (inputSource == AUDIO_SOURCE_HOTWORD) ?
100 AUDIO_SOURCE_VOICE_RECOGNITION : inputSource;
101
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700102 Mutex::Autolock _l(mLock);
bryant_liuba2b4392014-06-11 16:49:30 +0800103 ssize_t index = mInputSources.indexOfKey(aliasSource);
104 if (index < 0) {
105 ALOGV("addInputEffects(): no processing needs to be attached to this source");
106 return status;
107 }
Eric Laurentfb66dd92016-01-28 18:32:03 -0800108 ssize_t idx = mInputSessions.indexOfKey(audioSession);
109 EffectVector *sessionDesc;
bryant_liuba2b4392014-06-11 16:49:30 +0800110 if (idx < 0) {
Eric Laurentfb66dd92016-01-28 18:32:03 -0800111 sessionDesc = new EffectVector(audioSession);
112 mInputSessions.add(audioSession, sessionDesc);
bryant_liuba2b4392014-06-11 16:49:30 +0800113 } else {
bryant_liu890a5632014-08-20 18:06:13 +0800114 // EffectVector is existing and we just need to increase ref count
Eric Laurentfb66dd92016-01-28 18:32:03 -0800115 sessionDesc = mInputSessions.valueAt(idx);
bryant_liuba2b4392014-06-11 16:49:30 +0800116 }
Eric Laurentfb66dd92016-01-28 18:32:03 -0800117 sessionDesc->mRefCount++;
bryant_liu890a5632014-08-20 18:06:13 +0800118
Eric Laurentfb66dd92016-01-28 18:32:03 -0800119 ALOGV("addInputEffects(): input: %d, refCount: %d", input, sessionDesc->mRefCount);
120 if (sessionDesc->mRefCount == 1) {
Eric Laurentb6436272016-12-07 19:24:50 -0800121 int64_t token = IPCThreadState::self()->clearCallingIdentity();
Eric Laurent7de5ac12014-10-21 09:07:11 -0700122 Vector <EffectDesc *> effects = mInputSources.valueAt(index)->mEffects;
123 for (size_t i = 0; i < effects.size(); i++) {
124 EffectDesc *effect = effects[i];
Svet Ganov3e5f14f2021-05-13 22:51:08 +0000125 AttributionSourceState attributionSource;
126 attributionSource.packageName = "android";
127 attributionSource.token = sp<BBinder>::make();
128 sp<AudioEffect> fx = new AudioEffect(attributionSource);
Atneya Nair884f7992022-05-17 19:22:42 -0400129 fx->set(nullptr /*type */, &effect->mUuid, -1 /* priority */, nullptr /* callback */,
130 audioSession, input);
Eric Laurent7de5ac12014-10-21 09:07:11 -0700131 status_t status = fx->initCheck();
132 if (status != NO_ERROR && status != ALREADY_EXISTS) {
133 ALOGW("addInputEffects(): failed to create Fx %s on source %d",
134 effect->mName, (int32_t)aliasSource);
135 // fx goes out of scope and strong ref on AudioEffect is released
136 continue;
137 }
138 for (size_t j = 0; j < effect->mParams.size(); j++) {
139 fx->setParameter(effect->mParams[j]);
140 }
141 ALOGV("addInputEffects(): added Fx %s on source: %d",
bryant_liuba2b4392014-06-11 16:49:30 +0800142 effect->mName, (int32_t)aliasSource);
Eric Laurentfb66dd92016-01-28 18:32:03 -0800143 sessionDesc->mEffects.add(fx);
bryant_liuba2b4392014-06-11 16:49:30 +0800144 }
Eric Laurentfb66dd92016-01-28 18:32:03 -0800145 sessionDesc->setProcessorEnabled(true);
Eric Laurentb6436272016-12-07 19:24:50 -0800146 IPCThreadState::self()->restoreCallingIdentity(token);
bryant_liuba2b4392014-06-11 16:49:30 +0800147 }
bryant_liuba2b4392014-06-11 16:49:30 +0800148 return status;
149}
150
151
Eric Laurentfb66dd92016-01-28 18:32:03 -0800152status_t AudioPolicyEffects::releaseInputEffects(audio_io_handle_t input,
153 audio_session_t audioSession)
bryant_liuba2b4392014-06-11 16:49:30 +0800154{
155 status_t status = NO_ERROR;
156
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700157 Mutex::Autolock _l(mLock);
Eric Laurentfb66dd92016-01-28 18:32:03 -0800158 ssize_t index = mInputSessions.indexOfKey(audioSession);
bryant_liuba2b4392014-06-11 16:49:30 +0800159 if (index < 0) {
160 return status;
161 }
Eric Laurentfb66dd92016-01-28 18:32:03 -0800162 EffectVector *sessionDesc = mInputSessions.valueAt(index);
163 sessionDesc->mRefCount--;
164 ALOGV("releaseInputEffects(): input: %d, refCount: %d", input, sessionDesc->mRefCount);
165 if (sessionDesc->mRefCount == 0) {
166 sessionDesc->setProcessorEnabled(false);
167 delete sessionDesc;
168 mInputSessions.removeItemsAt(index);
bryant_liu890a5632014-08-20 18:06:13 +0800169 ALOGV("releaseInputEffects(): all effects released");
170 }
bryant_liuba2b4392014-06-11 16:49:30 +0800171 return status;
172}
173
Eric Laurentfb66dd92016-01-28 18:32:03 -0800174status_t AudioPolicyEffects::queryDefaultInputEffects(audio_session_t audioSession,
bryant_liuba2b4392014-06-11 16:49:30 +0800175 effect_descriptor_t *descriptors,
176 uint32_t *count)
177{
178 status_t status = NO_ERROR;
179
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700180 Mutex::Autolock _l(mLock);
bryant_liuba2b4392014-06-11 16:49:30 +0800181 size_t index;
Eric Laurentfb66dd92016-01-28 18:32:03 -0800182 for (index = 0; index < mInputSessions.size(); index++) {
183 if (mInputSessions.valueAt(index)->mSessionId == audioSession) {
bryant_liuba2b4392014-06-11 16:49:30 +0800184 break;
185 }
186 }
Eric Laurentfb66dd92016-01-28 18:32:03 -0800187 if (index == mInputSessions.size()) {
bryant_liuba2b4392014-06-11 16:49:30 +0800188 *count = 0;
189 return BAD_VALUE;
190 }
Eric Laurentfb66dd92016-01-28 18:32:03 -0800191 Vector< sp<AudioEffect> > effects = mInputSessions.valueAt(index)->mEffects;
bryant_liuba2b4392014-06-11 16:49:30 +0800192
193 for (size_t i = 0; i < effects.size(); i++) {
194 effect_descriptor_t desc = effects[i]->descriptor();
195 if (i < *count) {
196 descriptors[i] = desc;
197 }
198 }
199 if (effects.size() > *count) {
200 status = NO_MEMORY;
201 }
202 *count = effects.size();
203 return status;
204}
205
206
Eric Laurentfb66dd92016-01-28 18:32:03 -0800207status_t AudioPolicyEffects::queryDefaultOutputSessionEffects(audio_session_t audioSession,
bryant_liuba2b4392014-06-11 16:49:30 +0800208 effect_descriptor_t *descriptors,
209 uint32_t *count)
210{
211 status_t status = NO_ERROR;
212
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700213 Mutex::Autolock _l(mLock);
bryant_liuba2b4392014-06-11 16:49:30 +0800214 size_t index;
215 for (index = 0; index < mOutputSessions.size(); index++) {
216 if (mOutputSessions.valueAt(index)->mSessionId == audioSession) {
217 break;
218 }
219 }
220 if (index == mOutputSessions.size()) {
221 *count = 0;
222 return BAD_VALUE;
223 }
224 Vector< sp<AudioEffect> > effects = mOutputSessions.valueAt(index)->mEffects;
225
226 for (size_t i = 0; i < effects.size(); i++) {
227 effect_descriptor_t desc = effects[i]->descriptor();
228 if (i < *count) {
229 descriptors[i] = desc;
230 }
231 }
232 if (effects.size() > *count) {
233 status = NO_MEMORY;
234 }
235 *count = effects.size();
236 return status;
237}
238
239
240status_t AudioPolicyEffects::addOutputSessionEffects(audio_io_handle_t output,
241 audio_stream_type_t stream,
Eric Laurentfb66dd92016-01-28 18:32:03 -0800242 audio_session_t audioSession)
bryant_liuba2b4392014-06-11 16:49:30 +0800243{
244 status_t status = NO_ERROR;
245
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700246 Mutex::Autolock _l(mLock);
bryant_liuba2b4392014-06-11 16:49:30 +0800247 // create audio processors according to stream
Eric Laurent223fd5c2014-11-11 13:43:36 -0800248 // FIXME: should we have specific post processing settings for internal streams?
249 // default to media for now.
250 if (stream >= AUDIO_STREAM_PUBLIC_CNT) {
251 stream = AUDIO_STREAM_MUSIC;
252 }
bryant_liuba2b4392014-06-11 16:49:30 +0800253 ssize_t index = mOutputStreams.indexOfKey(stream);
254 if (index < 0) {
255 ALOGV("addOutputSessionEffects(): no output processing needed for this stream");
256 return NO_ERROR;
257 }
258
259 ssize_t idx = mOutputSessions.indexOfKey(audioSession);
260 EffectVector *procDesc;
261 if (idx < 0) {
262 procDesc = new EffectVector(audioSession);
263 mOutputSessions.add(audioSession, procDesc);
264 } else {
bryant_liu890a5632014-08-20 18:06:13 +0800265 // EffectVector is existing and we just need to increase ref count
bryant_liuba2b4392014-06-11 16:49:30 +0800266 procDesc = mOutputSessions.valueAt(idx);
267 }
bryant_liu890a5632014-08-20 18:06:13 +0800268 procDesc->mRefCount++;
269
Eric Laurent7de5ac12014-10-21 09:07:11 -0700270 ALOGV("addOutputSessionEffects(): session: %d, refCount: %d",
271 audioSession, procDesc->mRefCount);
272 if (procDesc->mRefCount == 1) {
Eric Laurentb6436272016-12-07 19:24:50 -0800273 // make sure effects are associated to audio server even if we are executing a binder call
274 int64_t token = IPCThreadState::self()->clearCallingIdentity();
Eric Laurent7de5ac12014-10-21 09:07:11 -0700275 Vector <EffectDesc *> effects = mOutputStreams.valueAt(index)->mEffects;
276 for (size_t i = 0; i < effects.size(); i++) {
277 EffectDesc *effect = effects[i];
Svet Ganov3e5f14f2021-05-13 22:51:08 +0000278 AttributionSourceState attributionSource;
279 attributionSource.packageName = "android";
280 attributionSource.token = sp<BBinder>::make();
281 sp<AudioEffect> fx = new AudioEffect(attributionSource);
Atneya Nair884f7992022-05-17 19:22:42 -0400282 fx->set(nullptr /* type */, &effect->mUuid, 0 /* priority */, nullptr /* callback */,
283 audioSession, output);
Eric Laurent7de5ac12014-10-21 09:07:11 -0700284 status_t status = fx->initCheck();
285 if (status != NO_ERROR && status != ALREADY_EXISTS) {
286 ALOGE("addOutputSessionEffects(): failed to create Fx %s on session %d",
287 effect->mName, audioSession);
288 // fx goes out of scope and strong ref on AudioEffect is released
289 continue;
290 }
291 ALOGV("addOutputSessionEffects(): added Fx %s on session: %d for stream: %d",
292 effect->mName, audioSession, (int32_t)stream);
293 procDesc->mEffects.add(fx);
bryant_liuba2b4392014-06-11 16:49:30 +0800294 }
Eric Laurent7de5ac12014-10-21 09:07:11 -0700295
296 procDesc->setProcessorEnabled(true);
Eric Laurentb6436272016-12-07 19:24:50 -0800297 IPCThreadState::self()->restoreCallingIdentity(token);
bryant_liuba2b4392014-06-11 16:49:30 +0800298 }
bryant_liuba2b4392014-06-11 16:49:30 +0800299 return status;
300}
301
302status_t AudioPolicyEffects::releaseOutputSessionEffects(audio_io_handle_t output,
303 audio_stream_type_t stream,
Eric Laurentfb66dd92016-01-28 18:32:03 -0800304 audio_session_t audioSession)
bryant_liuba2b4392014-06-11 16:49:30 +0800305{
306 status_t status = NO_ERROR;
307 (void) output; // argument not used for now
308 (void) stream; // argument not used for now
309
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700310 Mutex::Autolock _l(mLock);
bryant_liuba2b4392014-06-11 16:49:30 +0800311 ssize_t index = mOutputSessions.indexOfKey(audioSession);
312 if (index < 0) {
313 ALOGV("releaseOutputSessionEffects: no output processing was attached to this stream");
314 return NO_ERROR;
315 }
316
317 EffectVector *procDesc = mOutputSessions.valueAt(index);
bryant_liu890a5632014-08-20 18:06:13 +0800318 procDesc->mRefCount--;
Eric Laurent7de5ac12014-10-21 09:07:11 -0700319 ALOGV("releaseOutputSessionEffects(): session: %d, refCount: %d",
320 audioSession, procDesc->mRefCount);
bryant_liu890a5632014-08-20 18:06:13 +0800321 if (procDesc->mRefCount == 0) {
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700322 procDesc->setProcessorEnabled(false);
bryant_liu890a5632014-08-20 18:06:13 +0800323 procDesc->mEffects.clear();
324 delete procDesc;
325 mOutputSessions.removeItemsAt(index);
326 ALOGV("releaseOutputSessionEffects(): output processing released from session: %d",
327 audioSession);
328 }
bryant_liuba2b4392014-06-11 16:49:30 +0800329 return status;
330}
331
Ari Hausman-Cohen24628312018-08-13 15:01:09 -0700332status_t AudioPolicyEffects::addSourceDefaultEffect(const effect_uuid_t *type,
333 const String16& opPackageName,
334 const effect_uuid_t *uuid,
335 int32_t priority,
336 audio_source_t source,
337 audio_unique_id_t* id)
338{
339 if (uuid == NULL || type == NULL) {
340 ALOGE("addSourceDefaultEffect(): Null uuid or type uuid pointer");
341 return BAD_VALUE;
342 }
343
Eric Laurentae4b6ec2019-01-15 18:34:38 -0800344 // HOTWORD, FM_TUNER and ECHO_REFERENCE are special case sources > MAX.
Ari Hausman-Cohen24628312018-08-13 15:01:09 -0700345 if (source < AUDIO_SOURCE_DEFAULT ||
346 (source > AUDIO_SOURCE_MAX &&
347 source != AUDIO_SOURCE_HOTWORD &&
Eric Laurentae4b6ec2019-01-15 18:34:38 -0800348 source != AUDIO_SOURCE_FM_TUNER &&
Carter Hsua3abb402021-10-26 11:11:20 +0800349 source != AUDIO_SOURCE_ECHO_REFERENCE &&
350 source != AUDIO_SOURCE_ULTRASOUND)) {
Ari Hausman-Cohen24628312018-08-13 15:01:09 -0700351 ALOGE("addSourceDefaultEffect(): Unsupported source type %d", source);
352 return BAD_VALUE;
353 }
354
355 // Check that |uuid| or |type| corresponds to an effect on the system.
356 effect_descriptor_t descriptor = {};
357 status_t res = AudioEffect::getEffectDescriptor(
358 uuid, type, EFFECT_FLAG_TYPE_PRE_PROC, &descriptor);
359 if (res != OK) {
360 ALOGE("addSourceDefaultEffect(): Failed to find effect descriptor matching uuid/type.");
361 return res;
362 }
363
364 // Only pre-processing effects can be added dynamically as source defaults.
365 if ((descriptor.flags & EFFECT_FLAG_TYPE_MASK) != EFFECT_FLAG_TYPE_PRE_PROC) {
366 ALOGE("addSourceDefaultEffect(): Desired effect cannot be attached "
367 "as a source default effect.");
368 return BAD_VALUE;
369 }
370
371 Mutex::Autolock _l(mLock);
372
373 // Find the EffectDescVector for the given source type, or create a new one if necessary.
374 ssize_t index = mInputSources.indexOfKey(source);
375 EffectDescVector *desc = NULL;
376 if (index < 0) {
377 // No effects for this source type yet.
378 desc = new EffectDescVector();
379 mInputSources.add(source, desc);
380 } else {
381 desc = mInputSources.valueAt(index);
382 }
383
384 // Create a new effect and add it to the vector.
385 res = AudioEffect::newEffectUniqueId(id);
386 if (res != OK) {
387 ALOGE("addSourceDefaultEffect(): failed to get new unique id.");
388 return res;
389 }
390 EffectDesc *effect = new EffectDesc(
Eric Laurent2685aa02022-02-01 14:26:38 +0100391 descriptor.name, descriptor.type, opPackageName, descriptor.uuid, priority, *id);
Ari Hausman-Cohen24628312018-08-13 15:01:09 -0700392 desc->mEffects.add(effect);
393 // TODO(b/71813697): Support setting params as well.
394
395 // TODO(b/71814300): Retroactively attach to any existing sources of the given type.
396 // This requires tracking the source type of each session id in addition to what is
397 // already being tracked.
398
399 return NO_ERROR;
400}
401
Ari Hausman-Cohen433722e2018-04-24 14:25:22 -0700402status_t AudioPolicyEffects::addStreamDefaultEffect(const effect_uuid_t *type,
403 const String16& opPackageName,
404 const effect_uuid_t *uuid,
405 int32_t priority,
406 audio_usage_t usage,
407 audio_unique_id_t* id)
408{
409 if (uuid == NULL || type == NULL) {
410 ALOGE("addStreamDefaultEffect(): Null uuid or type uuid pointer");
411 return BAD_VALUE;
412 }
François Gaffie58d4be52018-11-06 15:30:12 +0100413 audio_stream_type_t stream = AudioSystem::attributesToStreamType(attributes_initializer(usage));
Ari Hausman-Cohen433722e2018-04-24 14:25:22 -0700414
415 if (stream < AUDIO_STREAM_MIN || stream >= AUDIO_STREAM_PUBLIC_CNT) {
416 ALOGE("addStreamDefaultEffect(): Unsupported stream type %d", stream);
417 return BAD_VALUE;
418 }
419
420 // Check that |uuid| or |type| corresponds to an effect on the system.
421 effect_descriptor_t descriptor = {};
422 status_t res = AudioEffect::getEffectDescriptor(
423 uuid, type, EFFECT_FLAG_TYPE_INSERT, &descriptor);
424 if (res != OK) {
425 ALOGE("addStreamDefaultEffect(): Failed to find effect descriptor matching uuid/type.");
426 return res;
427 }
428
429 // Only insert effects can be added dynamically as stream defaults.
430 if ((descriptor.flags & EFFECT_FLAG_TYPE_MASK) != EFFECT_FLAG_TYPE_INSERT) {
431 ALOGE("addStreamDefaultEffect(): Desired effect cannot be attached "
432 "as a stream default effect.");
433 return BAD_VALUE;
434 }
435
436 Mutex::Autolock _l(mLock);
437
438 // Find the EffectDescVector for the given stream type, or create a new one if necessary.
439 ssize_t index = mOutputStreams.indexOfKey(stream);
440 EffectDescVector *desc = NULL;
441 if (index < 0) {
442 // No effects for this stream type yet.
443 desc = new EffectDescVector();
444 mOutputStreams.add(stream, desc);
445 } else {
446 desc = mOutputStreams.valueAt(index);
447 }
448
449 // Create a new effect and add it to the vector.
450 res = AudioEffect::newEffectUniqueId(id);
451 if (res != OK) {
452 ALOGE("addStreamDefaultEffect(): failed to get new unique id.");
453 return res;
454 }
455 EffectDesc *effect = new EffectDesc(
Eric Laurent2685aa02022-02-01 14:26:38 +0100456 descriptor.name, descriptor.type, opPackageName, descriptor.uuid, priority, *id);
Ari Hausman-Cohen433722e2018-04-24 14:25:22 -0700457 desc->mEffects.add(effect);
458 // TODO(b/71813697): Support setting params as well.
459
460 // TODO(b/71814300): Retroactively attach to any existing streams of the given type.
461 // This requires tracking the stream type of each session id in addition to what is
462 // already being tracked.
463
464 return NO_ERROR;
465}
466
Ari Hausman-Cohen24628312018-08-13 15:01:09 -0700467status_t AudioPolicyEffects::removeSourceDefaultEffect(audio_unique_id_t id)
468{
469 if (id == AUDIO_UNIQUE_ID_ALLOCATE) {
470 // ALLOCATE is not a unique identifier, but rather a reserved value indicating
471 // a real id has not been assigned. For default effects, this value is only used
472 // by system-owned defaults from the loaded config, which cannot be removed.
473 return BAD_VALUE;
474 }
475
476 Mutex::Autolock _l(mLock);
477
478 // Check each source type.
479 size_t numSources = mInputSources.size();
480 for (size_t i = 0; i < numSources; ++i) {
481 // Check each effect for each source.
482 EffectDescVector* descVector = mInputSources[i];
483 for (auto desc = descVector->mEffects.begin(); desc != descVector->mEffects.end(); ++desc) {
484 if ((*desc)->mId == id) {
485 // Found it!
486 // TODO(b/71814300): Remove from any sources the effect was attached to.
487 descVector->mEffects.erase(desc);
488 // Handles are unique; there can only be one match, so return early.
489 return NO_ERROR;
490 }
491 }
492 }
493
494 // Effect wasn't found, so it's been trivially removed successfully.
495 return NO_ERROR;
496}
497
Ari Hausman-Cohen433722e2018-04-24 14:25:22 -0700498status_t AudioPolicyEffects::removeStreamDefaultEffect(audio_unique_id_t id)
499{
500 if (id == AUDIO_UNIQUE_ID_ALLOCATE) {
501 // ALLOCATE is not a unique identifier, but rather a reserved value indicating
502 // a real id has not been assigned. For default effects, this value is only used
503 // by system-owned defaults from the loaded config, which cannot be removed.
504 return BAD_VALUE;
505 }
506
507 Mutex::Autolock _l(mLock);
508
509 // Check each stream type.
510 size_t numStreams = mOutputStreams.size();
511 for (size_t i = 0; i < numStreams; ++i) {
512 // Check each effect for each stream.
513 EffectDescVector* descVector = mOutputStreams[i];
514 for (auto desc = descVector->mEffects.begin(); desc != descVector->mEffects.end(); ++desc) {
515 if ((*desc)->mId == id) {
516 // Found it!
517 // TODO(b/71814300): Remove from any streams the effect was attached to.
518 descVector->mEffects.erase(desc);
519 // Handles are unique; there can only be one match, so return early.
520 return NO_ERROR;
521 }
522 }
523 }
524
525 // Effect wasn't found, so it's been trivially removed successfully.
526 return NO_ERROR;
527}
bryant_liuba2b4392014-06-11 16:49:30 +0800528
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700529void AudioPolicyEffects::EffectVector::setProcessorEnabled(bool enabled)
bryant_liuba2b4392014-06-11 16:49:30 +0800530{
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700531 for (size_t i = 0; i < mEffects.size(); i++) {
532 mEffects.itemAt(i)->setEnabled(enabled);
bryant_liuba2b4392014-06-11 16:49:30 +0800533 }
534}
535
536
537// ----------------------------------------------------------------------------
538// Audio processing configuration
539// ----------------------------------------------------------------------------
540
541/*static*/ const char * const AudioPolicyEffects::kInputSourceNames[AUDIO_SOURCE_CNT -1] = {
542 MIC_SRC_TAG,
543 VOICE_UL_SRC_TAG,
544 VOICE_DL_SRC_TAG,
545 VOICE_CALL_SRC_TAG,
546 CAMCORDER_SRC_TAG,
547 VOICE_REC_SRC_TAG,
rago8a397d52015-12-02 11:27:57 -0800548 VOICE_COMM_SRC_TAG,
Carter Hsua3abb402021-10-26 11:11:20 +0800549 REMOTE_SUBMIX_SRC_TAG,
Eric Laurentae4b6ec2019-01-15 18:34:38 -0800550 UNPROCESSED_SRC_TAG,
551 VOICE_PERFORMANCE_SRC_TAG
bryant_liuba2b4392014-06-11 16:49:30 +0800552};
553
554// returns the audio_source_t enum corresponding to the input source name or
555// AUDIO_SOURCE_CNT is no match found
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700556/*static*/ audio_source_t AudioPolicyEffects::inputSourceNameToEnum(const char *name)
bryant_liuba2b4392014-06-11 16:49:30 +0800557{
558 int i;
559 for (i = AUDIO_SOURCE_MIC; i < AUDIO_SOURCE_CNT; i++) {
560 if (strcmp(name, kInputSourceNames[i - AUDIO_SOURCE_MIC]) == 0) {
561 ALOGV("inputSourceNameToEnum found source %s %d", name, i);
562 break;
563 }
564 }
565 return (audio_source_t)i;
566}
567
Eric Laurent223fd5c2014-11-11 13:43:36 -0800568const char *AudioPolicyEffects::kStreamNames[AUDIO_STREAM_PUBLIC_CNT+1] = {
bryant_liuba2b4392014-06-11 16:49:30 +0800569 AUDIO_STREAM_DEFAULT_TAG,
570 AUDIO_STREAM_VOICE_CALL_TAG,
571 AUDIO_STREAM_SYSTEM_TAG,
572 AUDIO_STREAM_RING_TAG,
573 AUDIO_STREAM_MUSIC_TAG,
574 AUDIO_STREAM_ALARM_TAG,
575 AUDIO_STREAM_NOTIFICATION_TAG,
576 AUDIO_STREAM_BLUETOOTH_SCO_TAG,
577 AUDIO_STREAM_ENFORCED_AUDIBLE_TAG,
578 AUDIO_STREAM_DTMF_TAG,
Baekgyeong Kim3a26bb22019-10-30 20:29:41 +0900579 AUDIO_STREAM_TTS_TAG,
580 AUDIO_STREAM_ASSISTANT_TAG
bryant_liuba2b4392014-06-11 16:49:30 +0800581};
582
583// returns the audio_stream_t enum corresponding to the output stream name or
Eric Laurent223fd5c2014-11-11 13:43:36 -0800584// AUDIO_STREAM_PUBLIC_CNT is no match found
bryant_liuba2b4392014-06-11 16:49:30 +0800585audio_stream_type_t AudioPolicyEffects::streamNameToEnum(const char *name)
586{
587 int i;
Eric Laurent223fd5c2014-11-11 13:43:36 -0800588 for (i = AUDIO_STREAM_DEFAULT; i < AUDIO_STREAM_PUBLIC_CNT; i++) {
bryant_liuba2b4392014-06-11 16:49:30 +0800589 if (strcmp(name, kStreamNames[i - AUDIO_STREAM_DEFAULT]) == 0) {
590 ALOGV("streamNameToEnum found stream %s %d", name, i);
591 break;
592 }
593 }
594 return (audio_stream_type_t)i;
595}
596
597// ----------------------------------------------------------------------------
598// Audio Effect Config parser
599// ----------------------------------------------------------------------------
600
Eric Laurent138ed172016-02-10 10:40:44 -0800601size_t AudioPolicyEffects::growParamSize(char **param,
bryant_liuba2b4392014-06-11 16:49:30 +0800602 size_t size,
603 size_t *curSize,
604 size_t *totSize)
605{
606 // *curSize is at least sizeof(effect_param_t) + 2 * sizeof(int)
607 size_t pos = ((*curSize - 1 ) / size + 1) * size;
608
609 if (pos + size > *totSize) {
610 while (pos + size > *totSize) {
611 *totSize += ((*totSize + 7) / 8) * 4;
612 }
George Burgess IV31225682018-02-12 11:08:38 -0800613 char *newParam = (char *)realloc(*param, *totSize);
614 if (newParam == NULL) {
Eric Laurent138ed172016-02-10 10:40:44 -0800615 ALOGE("%s realloc error for size %zu", __func__, *totSize);
616 return 0;
617 }
George Burgess IV31225682018-02-12 11:08:38 -0800618 *param = newParam;
bryant_liuba2b4392014-06-11 16:49:30 +0800619 }
620 *curSize = pos + size;
621 return pos;
622}
623
Eric Laurent138ed172016-02-10 10:40:44 -0800624
bryant_liuba2b4392014-06-11 16:49:30 +0800625size_t AudioPolicyEffects::readParamValue(cnode *node,
Eric Laurent138ed172016-02-10 10:40:44 -0800626 char **param,
bryant_liuba2b4392014-06-11 16:49:30 +0800627 size_t *curSize,
628 size_t *totSize)
629{
Eric Laurent138ed172016-02-10 10:40:44 -0800630 size_t len = 0;
631 size_t pos;
632
bryant_liuba2b4392014-06-11 16:49:30 +0800633 if (strncmp(node->name, SHORT_TAG, sizeof(SHORT_TAG) + 1) == 0) {
Eric Laurent138ed172016-02-10 10:40:44 -0800634 pos = growParamSize(param, sizeof(short), curSize, totSize);
635 if (pos == 0) {
636 goto exit;
bryant_liuba2b4392014-06-11 16:49:30 +0800637 }
Eric Laurent138ed172016-02-10 10:40:44 -0800638 *(short *)(*param + pos) = (short)atoi(node->value);
639 ALOGV("readParamValue() reading short %d", *(short *)(*param + pos));
640 len = sizeof(short);
641 } else if (strncmp(node->name, INT_TAG, sizeof(INT_TAG) + 1) == 0) {
642 pos = growParamSize(param, sizeof(int), curSize, totSize);
643 if (pos == 0) {
644 goto exit;
645 }
646 *(int *)(*param + pos) = atoi(node->value);
647 ALOGV("readParamValue() reading int %d", *(int *)(*param + pos));
648 len = sizeof(int);
649 } else if (strncmp(node->name, FLOAT_TAG, sizeof(FLOAT_TAG) + 1) == 0) {
650 pos = growParamSize(param, sizeof(float), curSize, totSize);
651 if (pos == 0) {
652 goto exit;
653 }
654 *(float *)(*param + pos) = (float)atof(node->value);
655 ALOGV("readParamValue() reading float %f",*(float *)(*param + pos));
656 len = sizeof(float);
657 } else if (strncmp(node->name, BOOL_TAG, sizeof(BOOL_TAG) + 1) == 0) {
658 pos = growParamSize(param, sizeof(bool), curSize, totSize);
659 if (pos == 0) {
660 goto exit;
661 }
662 if (strncmp(node->value, "true", strlen("true") + 1) == 0) {
663 *(bool *)(*param + pos) = true;
664 } else {
665 *(bool *)(*param + pos) = false;
666 }
667 ALOGV("readParamValue() reading bool %s",
668 *(bool *)(*param + pos) ? "true" : "false");
669 len = sizeof(bool);
bryant_liuba2b4392014-06-11 16:49:30 +0800670 } else if (strncmp(node->name, STRING_TAG, sizeof(STRING_TAG) + 1) == 0) {
Eric Laurent138ed172016-02-10 10:40:44 -0800671 len = strnlen(node->value, EFFECT_STRING_LEN_MAX);
bryant_liuba2b4392014-06-11 16:49:30 +0800672 if (*curSize + len + 1 > *totSize) {
673 *totSize = *curSize + len + 1;
Chih-Hung Hsieh03077682018-08-30 14:11:00 -0700674 char *newParam = (char *)realloc(*param, *totSize);
675 if (newParam == NULL) {
Eric Laurent138ed172016-02-10 10:40:44 -0800676 len = 0;
677 ALOGE("%s realloc error for string len %zu", __func__, *totSize);
678 goto exit;
679 }
Chih-Hung Hsieh03077682018-08-30 14:11:00 -0700680 *param = newParam;
bryant_liuba2b4392014-06-11 16:49:30 +0800681 }
Eric Laurent138ed172016-02-10 10:40:44 -0800682 strncpy(*param + *curSize, node->value, len);
bryant_liuba2b4392014-06-11 16:49:30 +0800683 *curSize += len;
Eric Laurent138ed172016-02-10 10:40:44 -0800684 (*param)[*curSize] = '\0';
685 ALOGV("readParamValue() reading string %s", *param + *curSize - len);
686 } else {
687 ALOGW("readParamValue() unknown param type %s", node->name);
bryant_liuba2b4392014-06-11 16:49:30 +0800688 }
Eric Laurent138ed172016-02-10 10:40:44 -0800689exit:
690 return len;
bryant_liuba2b4392014-06-11 16:49:30 +0800691}
692
693effect_param_t *AudioPolicyEffects::loadEffectParameter(cnode *root)
694{
695 cnode *param;
696 cnode *value;
697 size_t curSize = sizeof(effect_param_t);
698 size_t totSize = sizeof(effect_param_t) + 2 * sizeof(int);
699 effect_param_t *fx_param = (effect_param_t *)malloc(totSize);
700
Eric Laurent138ed172016-02-10 10:40:44 -0800701 if (fx_param == NULL) {
702 ALOGE("%s malloc error for effect structure of size %zu",
703 __func__, totSize);
704 return NULL;
705 }
706
bryant_liuba2b4392014-06-11 16:49:30 +0800707 param = config_find(root, PARAM_TAG);
708 value = config_find(root, VALUE_TAG);
709 if (param == NULL && value == NULL) {
710 // try to parse simple parameter form {int int}
711 param = root->first_child;
712 if (param != NULL) {
713 // Note: that a pair of random strings is read as 0 0
714 int *ptr = (int *)fx_param->data;
Eric Laurent138ed172016-02-10 10:40:44 -0800715#if LOG_NDEBUG == 0
bryant_liuba2b4392014-06-11 16:49:30 +0800716 int *ptr2 = (int *)((char *)param + sizeof(effect_param_t));
Eric Laurent138ed172016-02-10 10:40:44 -0800717 ALOGV("loadEffectParameter() ptr %p ptr2 %p", ptr, ptr2);
718#endif
bryant_liuba2b4392014-06-11 16:49:30 +0800719 *ptr++ = atoi(param->name);
720 *ptr = atoi(param->value);
721 fx_param->psize = sizeof(int);
722 fx_param->vsize = sizeof(int);
723 return fx_param;
724 }
725 }
726 if (param == NULL || value == NULL) {
Eric Laurent138ed172016-02-10 10:40:44 -0800727 ALOGW("loadEffectParameter() invalid parameter description %s",
728 root->name);
bryant_liuba2b4392014-06-11 16:49:30 +0800729 goto error;
730 }
731
732 fx_param->psize = 0;
733 param = param->first_child;
734 while (param) {
735 ALOGV("loadEffectParameter() reading param of type %s", param->name);
Eric Laurent138ed172016-02-10 10:40:44 -0800736 size_t size =
737 readParamValue(param, (char **)&fx_param, &curSize, &totSize);
bryant_liuba2b4392014-06-11 16:49:30 +0800738 if (size == 0) {
739 goto error;
740 }
741 fx_param->psize += size;
742 param = param->next;
743 }
744
745 // align start of value field on 32 bit boundary
746 curSize = ((curSize - 1 ) / sizeof(int) + 1) * sizeof(int);
747
748 fx_param->vsize = 0;
749 value = value->first_child;
750 while (value) {
751 ALOGV("loadEffectParameter() reading value of type %s", value->name);
Eric Laurent138ed172016-02-10 10:40:44 -0800752 size_t size =
753 readParamValue(value, (char **)&fx_param, &curSize, &totSize);
bryant_liuba2b4392014-06-11 16:49:30 +0800754 if (size == 0) {
755 goto error;
756 }
757 fx_param->vsize += size;
758 value = value->next;
759 }
760
761 return fx_param;
762
763error:
Eric Laurent138ed172016-02-10 10:40:44 -0800764 free(fx_param);
bryant_liuba2b4392014-06-11 16:49:30 +0800765 return NULL;
766}
767
768void AudioPolicyEffects::loadEffectParameters(cnode *root, Vector <effect_param_t *>& params)
769{
770 cnode *node = root->first_child;
771 while (node) {
772 ALOGV("loadEffectParameters() loading param %s", node->name);
773 effect_param_t *param = loadEffectParameter(node);
Eric Laurent138ed172016-02-10 10:40:44 -0800774 if (param != NULL) {
775 params.add(param);
bryant_liuba2b4392014-06-11 16:49:30 +0800776 }
bryant_liuba2b4392014-06-11 16:49:30 +0800777 node = node->next;
778 }
779}
780
781
782AudioPolicyEffects::EffectDescVector *AudioPolicyEffects::loadEffectConfig(
783 cnode *root,
784 const Vector <EffectDesc *>& effects)
785{
786 cnode *node = root->first_child;
787 if (node == NULL) {
788 ALOGW("loadInputSource() empty element %s", root->name);
789 return NULL;
790 }
791 EffectDescVector *desc = new EffectDescVector();
792 while (node) {
793 size_t i;
Eric Laurent138ed172016-02-10 10:40:44 -0800794
bryant_liuba2b4392014-06-11 16:49:30 +0800795 for (i = 0; i < effects.size(); i++) {
796 if (strncmp(effects[i]->mName, node->name, EFFECT_STRING_LEN_MAX) == 0) {
797 ALOGV("loadEffectConfig() found effect %s in list", node->name);
798 break;
799 }
800 }
801 if (i == effects.size()) {
802 ALOGV("loadEffectConfig() effect %s not in list", node->name);
803 node = node->next;
804 continue;
805 }
806 EffectDesc *effect = new EffectDesc(*effects[i]); // deep copy
807 loadEffectParameters(node, effect->mParams);
808 ALOGV("loadEffectConfig() adding effect %s uuid %08x",
809 effect->mName, effect->mUuid.timeLow);
810 desc->mEffects.add(effect);
811 node = node->next;
812 }
813 if (desc->mEffects.size() == 0) {
814 ALOGW("loadEffectConfig() no valid effects found in config %s", root->name);
815 delete desc;
816 return NULL;
817 }
818 return desc;
819}
820
821status_t AudioPolicyEffects::loadInputEffectConfigurations(cnode *root,
822 const Vector <EffectDesc *>& effects)
823{
824 cnode *node = config_find(root, PREPROCESSING_TAG);
825 if (node == NULL) {
826 return -ENOENT;
827 }
828 node = node->first_child;
829 while (node) {
830 audio_source_t source = inputSourceNameToEnum(node->name);
831 if (source == AUDIO_SOURCE_CNT) {
832 ALOGW("loadInputSources() invalid input source %s", node->name);
833 node = node->next;
834 continue;
835 }
836 ALOGV("loadInputSources() loading input source %s", node->name);
837 EffectDescVector *desc = loadEffectConfig(node, effects);
838 if (desc == NULL) {
839 node = node->next;
840 continue;
841 }
842 mInputSources.add(source, desc);
843 node = node->next;
844 }
845 return NO_ERROR;
846}
847
848status_t AudioPolicyEffects::loadStreamEffectConfigurations(cnode *root,
849 const Vector <EffectDesc *>& effects)
850{
851 cnode *node = config_find(root, OUTPUT_SESSION_PROCESSING_TAG);
852 if (node == NULL) {
853 return -ENOENT;
854 }
855 node = node->first_child;
856 while (node) {
857 audio_stream_type_t stream = streamNameToEnum(node->name);
Eric Laurent223fd5c2014-11-11 13:43:36 -0800858 if (stream == AUDIO_STREAM_PUBLIC_CNT) {
bryant_liuba2b4392014-06-11 16:49:30 +0800859 ALOGW("loadStreamEffectConfigurations() invalid output stream %s", node->name);
860 node = node->next;
861 continue;
862 }
863 ALOGV("loadStreamEffectConfigurations() loading output stream %s", node->name);
864 EffectDescVector *desc = loadEffectConfig(node, effects);
865 if (desc == NULL) {
866 node = node->next;
867 continue;
868 }
869 mOutputStreams.add(stream, desc);
870 node = node->next;
871 }
872 return NO_ERROR;
873}
874
875AudioPolicyEffects::EffectDesc *AudioPolicyEffects::loadEffect(cnode *root)
876{
877 cnode *node = config_find(root, UUID_TAG);
878 if (node == NULL) {
879 return NULL;
880 }
881 effect_uuid_t uuid;
882 if (AudioEffect::stringToGuid(node->value, &uuid) != NO_ERROR) {
883 ALOGW("loadEffect() invalid uuid %s", node->value);
884 return NULL;
885 }
886 return new EffectDesc(root->name, uuid);
887}
888
889status_t AudioPolicyEffects::loadEffects(cnode *root, Vector <EffectDesc *>& effects)
890{
891 cnode *node = config_find(root, EFFECTS_TAG);
892 if (node == NULL) {
893 return -ENOENT;
894 }
895 node = node->first_child;
896 while (node) {
897 ALOGV("loadEffects() loading effect %s", node->name);
898 EffectDesc *effect = loadEffect(node);
899 if (effect == NULL) {
900 node = node->next;
901 continue;
902 }
903 effects.add(effect);
904 node = node->next;
905 }
906 return NO_ERROR;
907}
908
Shunkai Yao8d6489a2023-04-18 23:14:25 +0000909status_t AudioPolicyEffects::loadAudioEffectConfig(
910 const sp<EffectsFactoryHalInterface>& effectsFactoryHal) {
911 if (!effectsFactoryHal) {
912 ALOGE("%s Null EffectsFactoryHalInterface", __func__);
913 return UNEXPECTED_NULL;
914 }
915
916 const auto skippedElements = VALUE_OR_RETURN_STATUS(effectsFactoryHal->getSkippedElements());
917 const auto processings = effectsFactoryHal->getProcessings();
918 if (!processings) {
919 ALOGE("%s Null processings with %zu skipped elements", __func__, skippedElements);
920 return UNEXPECTED_NULL;
Kevin Rocard4fb615c2017-06-26 10:28:13 -0700921 }
922
923 auto loadProcessingChain = [](auto& processingChain, auto& streams) {
924 for (auto& stream : processingChain) {
925 auto effectDescs = std::make_unique<EffectDescVector>();
926 for (auto& effect : stream.effects) {
927 effectDescs->mEffects.add(
928 new EffectDesc{effect.get().name.c_str(), effect.get().uuid});
929 }
930 streams.add(stream.type, effectDescs.release());
931 }
932 };
François Gaffie06182982020-01-07 15:16:14 +0100933
Shunkai Yao8d6489a2023-04-18 23:14:25 +0000934 auto loadDeviceProcessingChain = [](auto& processingChain, auto& devicesEffects) {
François Gaffie06182982020-01-07 15:16:14 +0100935 for (auto& deviceProcess : processingChain) {
François Gaffie06182982020-01-07 15:16:14 +0100936 auto effectDescs = std::make_unique<EffectDescVector>();
937 for (auto& effect : deviceProcess.effects) {
938 effectDescs->mEffects.add(
939 new EffectDesc{effect.get().name.c_str(), effect.get().uuid});
940 }
941 auto deviceEffects = std::make_unique<DeviceEffects>(
942 std::move(effectDescs), deviceProcess.type, deviceProcess.address);
943 devicesEffects.emplace(deviceProcess.address, std::move(deviceEffects));
944 }
945 };
946
Shunkai Yao8d6489a2023-04-18 23:14:25 +0000947 loadProcessingChain(processings->preprocess, mInputSources);
948 loadProcessingChain(processings->postprocess, mOutputStreams);
949
Mikhail Naganov12b716c2020-04-30 22:37:43 +0000950 {
951 Mutex::Autolock _l(mLock);
Shunkai Yao8d6489a2023-04-18 23:14:25 +0000952 loadDeviceProcessingChain(processings->deviceprocess, mDeviceEffects);
Mikhail Naganov12b716c2020-04-30 22:37:43 +0000953 }
Shunkai Yao8d6489a2023-04-18 23:14:25 +0000954
955 return skippedElements;
Kevin Rocard4fb615c2017-06-26 10:28:13 -0700956}
957
Shunkai Yao8d6489a2023-04-18 23:14:25 +0000958status_t AudioPolicyEffects::loadAudioEffectConfigLegacy(const char *path)
bryant_liuba2b4392014-06-11 16:49:30 +0800959{
960 cnode *root;
961 char *data;
962
963 data = (char *)load_file(path, NULL);
964 if (data == NULL) {
965 return -ENODEV;
966 }
967 root = config_node("", "");
968 config_load(root, data);
969
970 Vector <EffectDesc *> effects;
971 loadEffects(root, effects);
972 loadInputEffectConfigurations(root, effects);
973 loadStreamEffectConfigurations(root, effects);
974
Eric Laurent182c2f52015-01-15 14:29:19 -0800975 for (size_t i = 0; i < effects.size(); i++) {
976 delete effects[i];
977 }
978
bryant_liuba2b4392014-06-11 16:49:30 +0800979 config_free(root);
980 free(root);
981 free(data);
982
983 return NO_ERROR;
984}
985
François Gaffie06182982020-01-07 15:16:14 +0100986void AudioPolicyEffects::initDefaultDeviceEffects()
987{
988 Mutex::Autolock _l(mLock);
989 for (const auto& deviceEffectsIter : mDeviceEffects) {
990 const auto& deviceEffects = deviceEffectsIter.second;
991 for (const auto& effectDesc : deviceEffects->mEffectDescriptors->mEffects) {
Svet Ganov3e5f14f2021-05-13 22:51:08 +0000992 AttributionSourceState attributionSource;
993 attributionSource.packageName = "android";
994 attributionSource.token = sp<BBinder>::make();
995 sp<AudioEffect> fx = new AudioEffect(attributionSource);
Atneya Nair884f7992022-05-17 19:22:42 -0400996 fx->set(EFFECT_UUID_NULL, &effectDesc->mUuid, 0 /* priority */, nullptr /* callback */,
997 AUDIO_SESSION_DEVICE, AUDIO_IO_HANDLE_NONE,
Mikhail Naganov69d41cc2020-07-31 17:36:08 -0700998 AudioDeviceTypeAddr{deviceEffects->getDeviceType(),
999 deviceEffects->getDeviceAddress()});
François Gaffie06182982020-01-07 15:16:14 +01001000 status_t status = fx->initCheck();
1001 if (status != NO_ERROR && status != ALREADY_EXISTS) {
1002 ALOGE("%s(): failed to create Fx %s on port type=%d address=%s", __func__,
1003 effectDesc->mName, deviceEffects->getDeviceType(),
1004 deviceEffects->getDeviceAddress().c_str());
1005 // fx goes out of scope and strong ref on AudioEffect is released
1006 continue;
1007 }
1008 fx->setEnabled(true);
1009 ALOGV("%s(): create Fx %s added on port type=%d address=%s", __func__,
1010 effectDesc->mName, deviceEffects->getDeviceType(),
1011 deviceEffects->getDeviceAddress().c_str());
Jintao Zhu230397e2021-03-07 14:15:10 +08001012 deviceEffects->mEffects.push_back(fx);
François Gaffie06182982020-01-07 15:16:14 +01001013 }
1014 }
1015}
bryant_liuba2b4392014-06-11 16:49:30 +08001016
Mikhail Naganov1b2a7942017-12-08 10:18:09 -08001017} // namespace android