blob: 60caa31be46ca036424a9ca4f51ca5996567c140 [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
38// ----------------------------------------------------------------------------
39// AudioPolicyEffects Implementation
40// ----------------------------------------------------------------------------
41
42AudioPolicyEffects::AudioPolicyEffects()
43{
Kevin Rocard4fb615c2017-06-26 10:28:13 -070044 status_t loadResult = loadAudioEffectXmlConfig();
45 if (loadResult < 0) {
46 ALOGW("Failed to load XML effect configuration, fallback to .conf");
47 // load automatic audio effect modules
48 if (access(AUDIO_EFFECT_VENDOR_CONFIG_FILE, R_OK) == 0) {
49 loadAudioEffectConfig(AUDIO_EFFECT_VENDOR_CONFIG_FILE);
50 } else if (access(AUDIO_EFFECT_DEFAULT_CONFIG_FILE, R_OK) == 0) {
51 loadAudioEffectConfig(AUDIO_EFFECT_DEFAULT_CONFIG_FILE);
52 }
53 } else if (loadResult > 0) {
54 ALOGE("Effect config is partially invalid, skipped %d elements", loadResult);
bryant_liuba2b4392014-06-11 16:49:30 +080055 }
56}
57
58
59AudioPolicyEffects::~AudioPolicyEffects()
60{
61 size_t i = 0;
62 // release audio input processing resources
63 for (i = 0; i < mInputSources.size(); i++) {
64 delete mInputSources.valueAt(i);
65 }
66 mInputSources.clear();
67
Eric Laurentfb66dd92016-01-28 18:32:03 -080068 for (i = 0; i < mInputSessions.size(); i++) {
69 mInputSessions.valueAt(i)->mEffects.clear();
70 delete mInputSessions.valueAt(i);
bryant_liuba2b4392014-06-11 16:49:30 +080071 }
Eric Laurentfb66dd92016-01-28 18:32:03 -080072 mInputSessions.clear();
bryant_liuba2b4392014-06-11 16:49:30 +080073
74 // release audio output processing resources
75 for (i = 0; i < mOutputStreams.size(); i++) {
76 delete mOutputStreams.valueAt(i);
77 }
78 mOutputStreams.clear();
79
80 for (i = 0; i < mOutputSessions.size(); i++) {
81 mOutputSessions.valueAt(i)->mEffects.clear();
82 delete mOutputSessions.valueAt(i);
83 }
84 mOutputSessions.clear();
85}
86
87
88status_t AudioPolicyEffects::addInputEffects(audio_io_handle_t input,
89 audio_source_t inputSource,
Eric Laurentfb66dd92016-01-28 18:32:03 -080090 audio_session_t audioSession)
bryant_liuba2b4392014-06-11 16:49:30 +080091{
92 status_t status = NO_ERROR;
93
94 // create audio pre processors according to input source
95 audio_source_t aliasSource = (inputSource == AUDIO_SOURCE_HOTWORD) ?
96 AUDIO_SOURCE_VOICE_RECOGNITION : inputSource;
97
Eric Laurent8b1e80b2014-10-07 09:08:47 -070098 Mutex::Autolock _l(mLock);
bryant_liuba2b4392014-06-11 16:49:30 +080099 ssize_t index = mInputSources.indexOfKey(aliasSource);
100 if (index < 0) {
101 ALOGV("addInputEffects(): no processing needs to be attached to this source");
102 return status;
103 }
Eric Laurentfb66dd92016-01-28 18:32:03 -0800104 ssize_t idx = mInputSessions.indexOfKey(audioSession);
105 EffectVector *sessionDesc;
bryant_liuba2b4392014-06-11 16:49:30 +0800106 if (idx < 0) {
Eric Laurentfb66dd92016-01-28 18:32:03 -0800107 sessionDesc = new EffectVector(audioSession);
108 mInputSessions.add(audioSession, sessionDesc);
bryant_liuba2b4392014-06-11 16:49:30 +0800109 } else {
bryant_liu890a5632014-08-20 18:06:13 +0800110 // EffectVector is existing and we just need to increase ref count
Eric Laurentfb66dd92016-01-28 18:32:03 -0800111 sessionDesc = mInputSessions.valueAt(idx);
bryant_liuba2b4392014-06-11 16:49:30 +0800112 }
Eric Laurentfb66dd92016-01-28 18:32:03 -0800113 sessionDesc->mRefCount++;
bryant_liu890a5632014-08-20 18:06:13 +0800114
Eric Laurentfb66dd92016-01-28 18:32:03 -0800115 ALOGV("addInputEffects(): input: %d, refCount: %d", input, sessionDesc->mRefCount);
116 if (sessionDesc->mRefCount == 1) {
Eric Laurentb6436272016-12-07 19:24:50 -0800117 int64_t token = IPCThreadState::self()->clearCallingIdentity();
Eric Laurent7de5ac12014-10-21 09:07:11 -0700118 Vector <EffectDesc *> effects = mInputSources.valueAt(index)->mEffects;
119 for (size_t i = 0; i < effects.size(); i++) {
120 EffectDesc *effect = effects[i];
Svet Ganovbe71aa22015-04-28 12:06:02 -0700121 sp<AudioEffect> fx = new AudioEffect(NULL, String16("android"), &effect->mUuid, -1, 0,
122 0, audioSession, input);
Eric Laurent7de5ac12014-10-21 09:07:11 -0700123 status_t status = fx->initCheck();
124 if (status != NO_ERROR && status != ALREADY_EXISTS) {
125 ALOGW("addInputEffects(): failed to create Fx %s on source %d",
126 effect->mName, (int32_t)aliasSource);
127 // fx goes out of scope and strong ref on AudioEffect is released
128 continue;
129 }
130 for (size_t j = 0; j < effect->mParams.size(); j++) {
131 fx->setParameter(effect->mParams[j]);
132 }
133 ALOGV("addInputEffects(): added Fx %s on source: %d",
bryant_liuba2b4392014-06-11 16:49:30 +0800134 effect->mName, (int32_t)aliasSource);
Eric Laurentfb66dd92016-01-28 18:32:03 -0800135 sessionDesc->mEffects.add(fx);
bryant_liuba2b4392014-06-11 16:49:30 +0800136 }
Eric Laurentfb66dd92016-01-28 18:32:03 -0800137 sessionDesc->setProcessorEnabled(true);
Eric Laurentb6436272016-12-07 19:24:50 -0800138 IPCThreadState::self()->restoreCallingIdentity(token);
bryant_liuba2b4392014-06-11 16:49:30 +0800139 }
bryant_liuba2b4392014-06-11 16:49:30 +0800140 return status;
141}
142
143
Eric Laurentfb66dd92016-01-28 18:32:03 -0800144status_t AudioPolicyEffects::releaseInputEffects(audio_io_handle_t input,
145 audio_session_t audioSession)
bryant_liuba2b4392014-06-11 16:49:30 +0800146{
147 status_t status = NO_ERROR;
148
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700149 Mutex::Autolock _l(mLock);
Eric Laurentfb66dd92016-01-28 18:32:03 -0800150 ssize_t index = mInputSessions.indexOfKey(audioSession);
bryant_liuba2b4392014-06-11 16:49:30 +0800151 if (index < 0) {
152 return status;
153 }
Eric Laurentfb66dd92016-01-28 18:32:03 -0800154 EffectVector *sessionDesc = mInputSessions.valueAt(index);
155 sessionDesc->mRefCount--;
156 ALOGV("releaseInputEffects(): input: %d, refCount: %d", input, sessionDesc->mRefCount);
157 if (sessionDesc->mRefCount == 0) {
158 sessionDesc->setProcessorEnabled(false);
159 delete sessionDesc;
160 mInputSessions.removeItemsAt(index);
bryant_liu890a5632014-08-20 18:06:13 +0800161 ALOGV("releaseInputEffects(): all effects released");
162 }
bryant_liuba2b4392014-06-11 16:49:30 +0800163 return status;
164}
165
Eric Laurentfb66dd92016-01-28 18:32:03 -0800166status_t AudioPolicyEffects::queryDefaultInputEffects(audio_session_t audioSession,
bryant_liuba2b4392014-06-11 16:49:30 +0800167 effect_descriptor_t *descriptors,
168 uint32_t *count)
169{
170 status_t status = NO_ERROR;
171
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700172 Mutex::Autolock _l(mLock);
bryant_liuba2b4392014-06-11 16:49:30 +0800173 size_t index;
Eric Laurentfb66dd92016-01-28 18:32:03 -0800174 for (index = 0; index < mInputSessions.size(); index++) {
175 if (mInputSessions.valueAt(index)->mSessionId == audioSession) {
bryant_liuba2b4392014-06-11 16:49:30 +0800176 break;
177 }
178 }
Eric Laurentfb66dd92016-01-28 18:32:03 -0800179 if (index == mInputSessions.size()) {
bryant_liuba2b4392014-06-11 16:49:30 +0800180 *count = 0;
181 return BAD_VALUE;
182 }
Eric Laurentfb66dd92016-01-28 18:32:03 -0800183 Vector< sp<AudioEffect> > effects = mInputSessions.valueAt(index)->mEffects;
bryant_liuba2b4392014-06-11 16:49:30 +0800184
185 for (size_t i = 0; i < effects.size(); i++) {
186 effect_descriptor_t desc = effects[i]->descriptor();
187 if (i < *count) {
188 descriptors[i] = desc;
189 }
190 }
191 if (effects.size() > *count) {
192 status = NO_MEMORY;
193 }
194 *count = effects.size();
195 return status;
196}
197
198
Eric Laurentfb66dd92016-01-28 18:32:03 -0800199status_t AudioPolicyEffects::queryDefaultOutputSessionEffects(audio_session_t audioSession,
bryant_liuba2b4392014-06-11 16:49:30 +0800200 effect_descriptor_t *descriptors,
201 uint32_t *count)
202{
203 status_t status = NO_ERROR;
204
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700205 Mutex::Autolock _l(mLock);
bryant_liuba2b4392014-06-11 16:49:30 +0800206 size_t index;
207 for (index = 0; index < mOutputSessions.size(); index++) {
208 if (mOutputSessions.valueAt(index)->mSessionId == audioSession) {
209 break;
210 }
211 }
212 if (index == mOutputSessions.size()) {
213 *count = 0;
214 return BAD_VALUE;
215 }
216 Vector< sp<AudioEffect> > effects = mOutputSessions.valueAt(index)->mEffects;
217
218 for (size_t i = 0; i < effects.size(); i++) {
219 effect_descriptor_t desc = effects[i]->descriptor();
220 if (i < *count) {
221 descriptors[i] = desc;
222 }
223 }
224 if (effects.size() > *count) {
225 status = NO_MEMORY;
226 }
227 *count = effects.size();
228 return status;
229}
230
231
232status_t AudioPolicyEffects::addOutputSessionEffects(audio_io_handle_t output,
233 audio_stream_type_t stream,
Eric Laurentfb66dd92016-01-28 18:32:03 -0800234 audio_session_t audioSession)
bryant_liuba2b4392014-06-11 16:49:30 +0800235{
236 status_t status = NO_ERROR;
237
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700238 Mutex::Autolock _l(mLock);
bryant_liuba2b4392014-06-11 16:49:30 +0800239 // create audio processors according to stream
Eric Laurent223fd5c2014-11-11 13:43:36 -0800240 // FIXME: should we have specific post processing settings for internal streams?
241 // default to media for now.
242 if (stream >= AUDIO_STREAM_PUBLIC_CNT) {
243 stream = AUDIO_STREAM_MUSIC;
244 }
bryant_liuba2b4392014-06-11 16:49:30 +0800245 ssize_t index = mOutputStreams.indexOfKey(stream);
246 if (index < 0) {
247 ALOGV("addOutputSessionEffects(): no output processing needed for this stream");
248 return NO_ERROR;
249 }
250
251 ssize_t idx = mOutputSessions.indexOfKey(audioSession);
252 EffectVector *procDesc;
253 if (idx < 0) {
254 procDesc = new EffectVector(audioSession);
255 mOutputSessions.add(audioSession, procDesc);
256 } else {
bryant_liu890a5632014-08-20 18:06:13 +0800257 // EffectVector is existing and we just need to increase ref count
bryant_liuba2b4392014-06-11 16:49:30 +0800258 procDesc = mOutputSessions.valueAt(idx);
259 }
bryant_liu890a5632014-08-20 18:06:13 +0800260 procDesc->mRefCount++;
261
Eric Laurent7de5ac12014-10-21 09:07:11 -0700262 ALOGV("addOutputSessionEffects(): session: %d, refCount: %d",
263 audioSession, procDesc->mRefCount);
264 if (procDesc->mRefCount == 1) {
Eric Laurentb6436272016-12-07 19:24:50 -0800265 // make sure effects are associated to audio server even if we are executing a binder call
266 int64_t token = IPCThreadState::self()->clearCallingIdentity();
Eric Laurent7de5ac12014-10-21 09:07:11 -0700267 Vector <EffectDesc *> effects = mOutputStreams.valueAt(index)->mEffects;
268 for (size_t i = 0; i < effects.size(); i++) {
269 EffectDesc *effect = effects[i];
Svet Ganovbe71aa22015-04-28 12:06:02 -0700270 sp<AudioEffect> fx = new AudioEffect(NULL, String16("android"), &effect->mUuid, 0, 0, 0,
Eric Laurent7de5ac12014-10-21 09:07:11 -0700271 audioSession, output);
272 status_t status = fx->initCheck();
273 if (status != NO_ERROR && status != ALREADY_EXISTS) {
274 ALOGE("addOutputSessionEffects(): failed to create Fx %s on session %d",
275 effect->mName, audioSession);
276 // fx goes out of scope and strong ref on AudioEffect is released
277 continue;
278 }
279 ALOGV("addOutputSessionEffects(): added Fx %s on session: %d for stream: %d",
280 effect->mName, audioSession, (int32_t)stream);
281 procDesc->mEffects.add(fx);
bryant_liuba2b4392014-06-11 16:49:30 +0800282 }
Eric Laurent7de5ac12014-10-21 09:07:11 -0700283
284 procDesc->setProcessorEnabled(true);
Eric Laurentb6436272016-12-07 19:24:50 -0800285 IPCThreadState::self()->restoreCallingIdentity(token);
bryant_liuba2b4392014-06-11 16:49:30 +0800286 }
bryant_liuba2b4392014-06-11 16:49:30 +0800287 return status;
288}
289
290status_t AudioPolicyEffects::releaseOutputSessionEffects(audio_io_handle_t output,
291 audio_stream_type_t stream,
Eric Laurentfb66dd92016-01-28 18:32:03 -0800292 audio_session_t audioSession)
bryant_liuba2b4392014-06-11 16:49:30 +0800293{
294 status_t status = NO_ERROR;
295 (void) output; // argument not used for now
296 (void) stream; // argument not used for now
297
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700298 Mutex::Autolock _l(mLock);
bryant_liuba2b4392014-06-11 16:49:30 +0800299 ssize_t index = mOutputSessions.indexOfKey(audioSession);
300 if (index < 0) {
301 ALOGV("releaseOutputSessionEffects: no output processing was attached to this stream");
302 return NO_ERROR;
303 }
304
305 EffectVector *procDesc = mOutputSessions.valueAt(index);
bryant_liu890a5632014-08-20 18:06:13 +0800306 procDesc->mRefCount--;
Eric Laurent7de5ac12014-10-21 09:07:11 -0700307 ALOGV("releaseOutputSessionEffects(): session: %d, refCount: %d",
308 audioSession, procDesc->mRefCount);
bryant_liu890a5632014-08-20 18:06:13 +0800309 if (procDesc->mRefCount == 0) {
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700310 procDesc->setProcessorEnabled(false);
bryant_liu890a5632014-08-20 18:06:13 +0800311 procDesc->mEffects.clear();
312 delete procDesc;
313 mOutputSessions.removeItemsAt(index);
314 ALOGV("releaseOutputSessionEffects(): output processing released from session: %d",
315 audioSession);
316 }
bryant_liuba2b4392014-06-11 16:49:30 +0800317 return status;
318}
319
Ari Hausman-Cohen24628312018-08-13 15:01:09 -0700320status_t AudioPolicyEffects::addSourceDefaultEffect(const effect_uuid_t *type,
321 const String16& opPackageName,
322 const effect_uuid_t *uuid,
323 int32_t priority,
324 audio_source_t source,
325 audio_unique_id_t* id)
326{
327 if (uuid == NULL || type == NULL) {
328 ALOGE("addSourceDefaultEffect(): Null uuid or type uuid pointer");
329 return BAD_VALUE;
330 }
331
Eric Laurentae4b6ec2019-01-15 18:34:38 -0800332 // HOTWORD, FM_TUNER and ECHO_REFERENCE are special case sources > MAX.
Ari Hausman-Cohen24628312018-08-13 15:01:09 -0700333 if (source < AUDIO_SOURCE_DEFAULT ||
334 (source > AUDIO_SOURCE_MAX &&
335 source != AUDIO_SOURCE_HOTWORD &&
Eric Laurentae4b6ec2019-01-15 18:34:38 -0800336 source != AUDIO_SOURCE_FM_TUNER &&
337 source != AUDIO_SOURCE_ECHO_REFERENCE)) {
Ari Hausman-Cohen24628312018-08-13 15:01:09 -0700338 ALOGE("addSourceDefaultEffect(): Unsupported source type %d", source);
339 return BAD_VALUE;
340 }
341
342 // Check that |uuid| or |type| corresponds to an effect on the system.
343 effect_descriptor_t descriptor = {};
344 status_t res = AudioEffect::getEffectDescriptor(
345 uuid, type, EFFECT_FLAG_TYPE_PRE_PROC, &descriptor);
346 if (res != OK) {
347 ALOGE("addSourceDefaultEffect(): Failed to find effect descriptor matching uuid/type.");
348 return res;
349 }
350
351 // Only pre-processing effects can be added dynamically as source defaults.
352 if ((descriptor.flags & EFFECT_FLAG_TYPE_MASK) != EFFECT_FLAG_TYPE_PRE_PROC) {
353 ALOGE("addSourceDefaultEffect(): Desired effect cannot be attached "
354 "as a source default effect.");
355 return BAD_VALUE;
356 }
357
358 Mutex::Autolock _l(mLock);
359
360 // Find the EffectDescVector for the given source type, or create a new one if necessary.
361 ssize_t index = mInputSources.indexOfKey(source);
362 EffectDescVector *desc = NULL;
363 if (index < 0) {
364 // No effects for this source type yet.
365 desc = new EffectDescVector();
366 mInputSources.add(source, desc);
367 } else {
368 desc = mInputSources.valueAt(index);
369 }
370
371 // Create a new effect and add it to the vector.
372 res = AudioEffect::newEffectUniqueId(id);
373 if (res != OK) {
374 ALOGE("addSourceDefaultEffect(): failed to get new unique id.");
375 return res;
376 }
377 EffectDesc *effect = new EffectDesc(
378 descriptor.name, *type, opPackageName, *uuid, priority, *id);
379 desc->mEffects.add(effect);
380 // TODO(b/71813697): Support setting params as well.
381
382 // TODO(b/71814300): Retroactively attach to any existing sources of the given type.
383 // This requires tracking the source type of each session id in addition to what is
384 // already being tracked.
385
386 return NO_ERROR;
387}
388
Ari Hausman-Cohen433722e2018-04-24 14:25:22 -0700389status_t AudioPolicyEffects::addStreamDefaultEffect(const effect_uuid_t *type,
390 const String16& opPackageName,
391 const effect_uuid_t *uuid,
392 int32_t priority,
393 audio_usage_t usage,
394 audio_unique_id_t* id)
395{
396 if (uuid == NULL || type == NULL) {
397 ALOGE("addStreamDefaultEffect(): Null uuid or type uuid pointer");
398 return BAD_VALUE;
399 }
François Gaffie58d4be52018-11-06 15:30:12 +0100400 audio_stream_type_t stream = AudioSystem::attributesToStreamType(attributes_initializer(usage));
Ari Hausman-Cohen433722e2018-04-24 14:25:22 -0700401
402 if (stream < AUDIO_STREAM_MIN || stream >= AUDIO_STREAM_PUBLIC_CNT) {
403 ALOGE("addStreamDefaultEffect(): Unsupported stream type %d", stream);
404 return BAD_VALUE;
405 }
406
407 // Check that |uuid| or |type| corresponds to an effect on the system.
408 effect_descriptor_t descriptor = {};
409 status_t res = AudioEffect::getEffectDescriptor(
410 uuid, type, EFFECT_FLAG_TYPE_INSERT, &descriptor);
411 if (res != OK) {
412 ALOGE("addStreamDefaultEffect(): Failed to find effect descriptor matching uuid/type.");
413 return res;
414 }
415
416 // Only insert effects can be added dynamically as stream defaults.
417 if ((descriptor.flags & EFFECT_FLAG_TYPE_MASK) != EFFECT_FLAG_TYPE_INSERT) {
418 ALOGE("addStreamDefaultEffect(): Desired effect cannot be attached "
419 "as a stream default effect.");
420 return BAD_VALUE;
421 }
422
423 Mutex::Autolock _l(mLock);
424
425 // Find the EffectDescVector for the given stream type, or create a new one if necessary.
426 ssize_t index = mOutputStreams.indexOfKey(stream);
427 EffectDescVector *desc = NULL;
428 if (index < 0) {
429 // No effects for this stream type yet.
430 desc = new EffectDescVector();
431 mOutputStreams.add(stream, desc);
432 } else {
433 desc = mOutputStreams.valueAt(index);
434 }
435
436 // Create a new effect and add it to the vector.
437 res = AudioEffect::newEffectUniqueId(id);
438 if (res != OK) {
439 ALOGE("addStreamDefaultEffect(): failed to get new unique id.");
440 return res;
441 }
442 EffectDesc *effect = new EffectDesc(
443 descriptor.name, *type, opPackageName, *uuid, priority, *id);
444 desc->mEffects.add(effect);
445 // TODO(b/71813697): Support setting params as well.
446
447 // TODO(b/71814300): Retroactively attach to any existing streams of the given type.
448 // This requires tracking the stream type of each session id in addition to what is
449 // already being tracked.
450
451 return NO_ERROR;
452}
453
Ari Hausman-Cohen24628312018-08-13 15:01:09 -0700454status_t AudioPolicyEffects::removeSourceDefaultEffect(audio_unique_id_t id)
455{
456 if (id == AUDIO_UNIQUE_ID_ALLOCATE) {
457 // ALLOCATE is not a unique identifier, but rather a reserved value indicating
458 // a real id has not been assigned. For default effects, this value is only used
459 // by system-owned defaults from the loaded config, which cannot be removed.
460 return BAD_VALUE;
461 }
462
463 Mutex::Autolock _l(mLock);
464
465 // Check each source type.
466 size_t numSources = mInputSources.size();
467 for (size_t i = 0; i < numSources; ++i) {
468 // Check each effect for each source.
469 EffectDescVector* descVector = mInputSources[i];
470 for (auto desc = descVector->mEffects.begin(); desc != descVector->mEffects.end(); ++desc) {
471 if ((*desc)->mId == id) {
472 // Found it!
473 // TODO(b/71814300): Remove from any sources the effect was attached to.
474 descVector->mEffects.erase(desc);
475 // Handles are unique; there can only be one match, so return early.
476 return NO_ERROR;
477 }
478 }
479 }
480
481 // Effect wasn't found, so it's been trivially removed successfully.
482 return NO_ERROR;
483}
484
Ari Hausman-Cohen433722e2018-04-24 14:25:22 -0700485status_t AudioPolicyEffects::removeStreamDefaultEffect(audio_unique_id_t id)
486{
487 if (id == AUDIO_UNIQUE_ID_ALLOCATE) {
488 // ALLOCATE is not a unique identifier, but rather a reserved value indicating
489 // a real id has not been assigned. For default effects, this value is only used
490 // by system-owned defaults from the loaded config, which cannot be removed.
491 return BAD_VALUE;
492 }
493
494 Mutex::Autolock _l(mLock);
495
496 // Check each stream type.
497 size_t numStreams = mOutputStreams.size();
498 for (size_t i = 0; i < numStreams; ++i) {
499 // Check each effect for each stream.
500 EffectDescVector* descVector = mOutputStreams[i];
501 for (auto desc = descVector->mEffects.begin(); desc != descVector->mEffects.end(); ++desc) {
502 if ((*desc)->mId == id) {
503 // Found it!
504 // TODO(b/71814300): Remove from any streams the effect was attached to.
505 descVector->mEffects.erase(desc);
506 // Handles are unique; there can only be one match, so return early.
507 return NO_ERROR;
508 }
509 }
510 }
511
512 // Effect wasn't found, so it's been trivially removed successfully.
513 return NO_ERROR;
514}
bryant_liuba2b4392014-06-11 16:49:30 +0800515
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700516void AudioPolicyEffects::EffectVector::setProcessorEnabled(bool enabled)
bryant_liuba2b4392014-06-11 16:49:30 +0800517{
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700518 for (size_t i = 0; i < mEffects.size(); i++) {
519 mEffects.itemAt(i)->setEnabled(enabled);
bryant_liuba2b4392014-06-11 16:49:30 +0800520 }
521}
522
523
524// ----------------------------------------------------------------------------
525// Audio processing configuration
526// ----------------------------------------------------------------------------
527
528/*static*/ const char * const AudioPolicyEffects::kInputSourceNames[AUDIO_SOURCE_CNT -1] = {
529 MIC_SRC_TAG,
530 VOICE_UL_SRC_TAG,
531 VOICE_DL_SRC_TAG,
532 VOICE_CALL_SRC_TAG,
533 CAMCORDER_SRC_TAG,
534 VOICE_REC_SRC_TAG,
rago8a397d52015-12-02 11:27:57 -0800535 VOICE_COMM_SRC_TAG,
Eric Laurentae4b6ec2019-01-15 18:34:38 -0800536 UNPROCESSED_SRC_TAG,
537 VOICE_PERFORMANCE_SRC_TAG
bryant_liuba2b4392014-06-11 16:49:30 +0800538};
539
540// returns the audio_source_t enum corresponding to the input source name or
541// AUDIO_SOURCE_CNT is no match found
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700542/*static*/ audio_source_t AudioPolicyEffects::inputSourceNameToEnum(const char *name)
bryant_liuba2b4392014-06-11 16:49:30 +0800543{
544 int i;
545 for (i = AUDIO_SOURCE_MIC; i < AUDIO_SOURCE_CNT; i++) {
546 if (strcmp(name, kInputSourceNames[i - AUDIO_SOURCE_MIC]) == 0) {
547 ALOGV("inputSourceNameToEnum found source %s %d", name, i);
548 break;
549 }
550 }
551 return (audio_source_t)i;
552}
553
Eric Laurent223fd5c2014-11-11 13:43:36 -0800554const char *AudioPolicyEffects::kStreamNames[AUDIO_STREAM_PUBLIC_CNT+1] = {
bryant_liuba2b4392014-06-11 16:49:30 +0800555 AUDIO_STREAM_DEFAULT_TAG,
556 AUDIO_STREAM_VOICE_CALL_TAG,
557 AUDIO_STREAM_SYSTEM_TAG,
558 AUDIO_STREAM_RING_TAG,
559 AUDIO_STREAM_MUSIC_TAG,
560 AUDIO_STREAM_ALARM_TAG,
561 AUDIO_STREAM_NOTIFICATION_TAG,
562 AUDIO_STREAM_BLUETOOTH_SCO_TAG,
563 AUDIO_STREAM_ENFORCED_AUDIBLE_TAG,
564 AUDIO_STREAM_DTMF_TAG,
Baekgyeong Kim3a26bb22019-10-30 20:29:41 +0900565 AUDIO_STREAM_TTS_TAG,
566 AUDIO_STREAM_ASSISTANT_TAG
bryant_liuba2b4392014-06-11 16:49:30 +0800567};
568
569// returns the audio_stream_t enum corresponding to the output stream name or
Eric Laurent223fd5c2014-11-11 13:43:36 -0800570// AUDIO_STREAM_PUBLIC_CNT is no match found
bryant_liuba2b4392014-06-11 16:49:30 +0800571audio_stream_type_t AudioPolicyEffects::streamNameToEnum(const char *name)
572{
573 int i;
Eric Laurent223fd5c2014-11-11 13:43:36 -0800574 for (i = AUDIO_STREAM_DEFAULT; i < AUDIO_STREAM_PUBLIC_CNT; i++) {
bryant_liuba2b4392014-06-11 16:49:30 +0800575 if (strcmp(name, kStreamNames[i - AUDIO_STREAM_DEFAULT]) == 0) {
576 ALOGV("streamNameToEnum found stream %s %d", name, i);
577 break;
578 }
579 }
580 return (audio_stream_type_t)i;
581}
582
583// ----------------------------------------------------------------------------
584// Audio Effect Config parser
585// ----------------------------------------------------------------------------
586
Eric Laurent138ed172016-02-10 10:40:44 -0800587size_t AudioPolicyEffects::growParamSize(char **param,
bryant_liuba2b4392014-06-11 16:49:30 +0800588 size_t size,
589 size_t *curSize,
590 size_t *totSize)
591{
592 // *curSize is at least sizeof(effect_param_t) + 2 * sizeof(int)
593 size_t pos = ((*curSize - 1 ) / size + 1) * size;
594
595 if (pos + size > *totSize) {
596 while (pos + size > *totSize) {
597 *totSize += ((*totSize + 7) / 8) * 4;
598 }
George Burgess IV31225682018-02-12 11:08:38 -0800599 char *newParam = (char *)realloc(*param, *totSize);
600 if (newParam == NULL) {
Eric Laurent138ed172016-02-10 10:40:44 -0800601 ALOGE("%s realloc error for size %zu", __func__, *totSize);
602 return 0;
603 }
George Burgess IV31225682018-02-12 11:08:38 -0800604 *param = newParam;
bryant_liuba2b4392014-06-11 16:49:30 +0800605 }
606 *curSize = pos + size;
607 return pos;
608}
609
Eric Laurent138ed172016-02-10 10:40:44 -0800610
bryant_liuba2b4392014-06-11 16:49:30 +0800611size_t AudioPolicyEffects::readParamValue(cnode *node,
Eric Laurent138ed172016-02-10 10:40:44 -0800612 char **param,
bryant_liuba2b4392014-06-11 16:49:30 +0800613 size_t *curSize,
614 size_t *totSize)
615{
Eric Laurent138ed172016-02-10 10:40:44 -0800616 size_t len = 0;
617 size_t pos;
618
bryant_liuba2b4392014-06-11 16:49:30 +0800619 if (strncmp(node->name, SHORT_TAG, sizeof(SHORT_TAG) + 1) == 0) {
Eric Laurent138ed172016-02-10 10:40:44 -0800620 pos = growParamSize(param, sizeof(short), curSize, totSize);
621 if (pos == 0) {
622 goto exit;
bryant_liuba2b4392014-06-11 16:49:30 +0800623 }
Eric Laurent138ed172016-02-10 10:40:44 -0800624 *(short *)(*param + pos) = (short)atoi(node->value);
625 ALOGV("readParamValue() reading short %d", *(short *)(*param + pos));
626 len = sizeof(short);
627 } else if (strncmp(node->name, INT_TAG, sizeof(INT_TAG) + 1) == 0) {
628 pos = growParamSize(param, sizeof(int), curSize, totSize);
629 if (pos == 0) {
630 goto exit;
631 }
632 *(int *)(*param + pos) = atoi(node->value);
633 ALOGV("readParamValue() reading int %d", *(int *)(*param + pos));
634 len = sizeof(int);
635 } else if (strncmp(node->name, FLOAT_TAG, sizeof(FLOAT_TAG) + 1) == 0) {
636 pos = growParamSize(param, sizeof(float), curSize, totSize);
637 if (pos == 0) {
638 goto exit;
639 }
640 *(float *)(*param + pos) = (float)atof(node->value);
641 ALOGV("readParamValue() reading float %f",*(float *)(*param + pos));
642 len = sizeof(float);
643 } else if (strncmp(node->name, BOOL_TAG, sizeof(BOOL_TAG) + 1) == 0) {
644 pos = growParamSize(param, sizeof(bool), curSize, totSize);
645 if (pos == 0) {
646 goto exit;
647 }
648 if (strncmp(node->value, "true", strlen("true") + 1) == 0) {
649 *(bool *)(*param + pos) = true;
650 } else {
651 *(bool *)(*param + pos) = false;
652 }
653 ALOGV("readParamValue() reading bool %s",
654 *(bool *)(*param + pos) ? "true" : "false");
655 len = sizeof(bool);
bryant_liuba2b4392014-06-11 16:49:30 +0800656 } else if (strncmp(node->name, STRING_TAG, sizeof(STRING_TAG) + 1) == 0) {
Eric Laurent138ed172016-02-10 10:40:44 -0800657 len = strnlen(node->value, EFFECT_STRING_LEN_MAX);
bryant_liuba2b4392014-06-11 16:49:30 +0800658 if (*curSize + len + 1 > *totSize) {
659 *totSize = *curSize + len + 1;
Chih-Hung Hsieh03077682018-08-30 14:11:00 -0700660 char *newParam = (char *)realloc(*param, *totSize);
661 if (newParam == NULL) {
Eric Laurent138ed172016-02-10 10:40:44 -0800662 len = 0;
663 ALOGE("%s realloc error for string len %zu", __func__, *totSize);
664 goto exit;
665 }
Chih-Hung Hsieh03077682018-08-30 14:11:00 -0700666 *param = newParam;
bryant_liuba2b4392014-06-11 16:49:30 +0800667 }
Eric Laurent138ed172016-02-10 10:40:44 -0800668 strncpy(*param + *curSize, node->value, len);
bryant_liuba2b4392014-06-11 16:49:30 +0800669 *curSize += len;
Eric Laurent138ed172016-02-10 10:40:44 -0800670 (*param)[*curSize] = '\0';
671 ALOGV("readParamValue() reading string %s", *param + *curSize - len);
672 } else {
673 ALOGW("readParamValue() unknown param type %s", node->name);
bryant_liuba2b4392014-06-11 16:49:30 +0800674 }
Eric Laurent138ed172016-02-10 10:40:44 -0800675exit:
676 return len;
bryant_liuba2b4392014-06-11 16:49:30 +0800677}
678
679effect_param_t *AudioPolicyEffects::loadEffectParameter(cnode *root)
680{
681 cnode *param;
682 cnode *value;
683 size_t curSize = sizeof(effect_param_t);
684 size_t totSize = sizeof(effect_param_t) + 2 * sizeof(int);
685 effect_param_t *fx_param = (effect_param_t *)malloc(totSize);
686
Eric Laurent138ed172016-02-10 10:40:44 -0800687 if (fx_param == NULL) {
688 ALOGE("%s malloc error for effect structure of size %zu",
689 __func__, totSize);
690 return NULL;
691 }
692
bryant_liuba2b4392014-06-11 16:49:30 +0800693 param = config_find(root, PARAM_TAG);
694 value = config_find(root, VALUE_TAG);
695 if (param == NULL && value == NULL) {
696 // try to parse simple parameter form {int int}
697 param = root->first_child;
698 if (param != NULL) {
699 // Note: that a pair of random strings is read as 0 0
700 int *ptr = (int *)fx_param->data;
Eric Laurent138ed172016-02-10 10:40:44 -0800701#if LOG_NDEBUG == 0
bryant_liuba2b4392014-06-11 16:49:30 +0800702 int *ptr2 = (int *)((char *)param + sizeof(effect_param_t));
Eric Laurent138ed172016-02-10 10:40:44 -0800703 ALOGV("loadEffectParameter() ptr %p ptr2 %p", ptr, ptr2);
704#endif
bryant_liuba2b4392014-06-11 16:49:30 +0800705 *ptr++ = atoi(param->name);
706 *ptr = atoi(param->value);
707 fx_param->psize = sizeof(int);
708 fx_param->vsize = sizeof(int);
709 return fx_param;
710 }
711 }
712 if (param == NULL || value == NULL) {
Eric Laurent138ed172016-02-10 10:40:44 -0800713 ALOGW("loadEffectParameter() invalid parameter description %s",
714 root->name);
bryant_liuba2b4392014-06-11 16:49:30 +0800715 goto error;
716 }
717
718 fx_param->psize = 0;
719 param = param->first_child;
720 while (param) {
721 ALOGV("loadEffectParameter() reading param of type %s", param->name);
Eric Laurent138ed172016-02-10 10:40:44 -0800722 size_t size =
723 readParamValue(param, (char **)&fx_param, &curSize, &totSize);
bryant_liuba2b4392014-06-11 16:49:30 +0800724 if (size == 0) {
725 goto error;
726 }
727 fx_param->psize += size;
728 param = param->next;
729 }
730
731 // align start of value field on 32 bit boundary
732 curSize = ((curSize - 1 ) / sizeof(int) + 1) * sizeof(int);
733
734 fx_param->vsize = 0;
735 value = value->first_child;
736 while (value) {
737 ALOGV("loadEffectParameter() reading value of type %s", value->name);
Eric Laurent138ed172016-02-10 10:40:44 -0800738 size_t size =
739 readParamValue(value, (char **)&fx_param, &curSize, &totSize);
bryant_liuba2b4392014-06-11 16:49:30 +0800740 if (size == 0) {
741 goto error;
742 }
743 fx_param->vsize += size;
744 value = value->next;
745 }
746
747 return fx_param;
748
749error:
Eric Laurent138ed172016-02-10 10:40:44 -0800750 free(fx_param);
bryant_liuba2b4392014-06-11 16:49:30 +0800751 return NULL;
752}
753
754void AudioPolicyEffects::loadEffectParameters(cnode *root, Vector <effect_param_t *>& params)
755{
756 cnode *node = root->first_child;
757 while (node) {
758 ALOGV("loadEffectParameters() loading param %s", node->name);
759 effect_param_t *param = loadEffectParameter(node);
Eric Laurent138ed172016-02-10 10:40:44 -0800760 if (param != NULL) {
761 params.add(param);
bryant_liuba2b4392014-06-11 16:49:30 +0800762 }
bryant_liuba2b4392014-06-11 16:49:30 +0800763 node = node->next;
764 }
765}
766
767
768AudioPolicyEffects::EffectDescVector *AudioPolicyEffects::loadEffectConfig(
769 cnode *root,
770 const Vector <EffectDesc *>& effects)
771{
772 cnode *node = root->first_child;
773 if (node == NULL) {
774 ALOGW("loadInputSource() empty element %s", root->name);
775 return NULL;
776 }
777 EffectDescVector *desc = new EffectDescVector();
778 while (node) {
779 size_t i;
Eric Laurent138ed172016-02-10 10:40:44 -0800780
bryant_liuba2b4392014-06-11 16:49:30 +0800781 for (i = 0; i < effects.size(); i++) {
782 if (strncmp(effects[i]->mName, node->name, EFFECT_STRING_LEN_MAX) == 0) {
783 ALOGV("loadEffectConfig() found effect %s in list", node->name);
784 break;
785 }
786 }
787 if (i == effects.size()) {
788 ALOGV("loadEffectConfig() effect %s not in list", node->name);
789 node = node->next;
790 continue;
791 }
792 EffectDesc *effect = new EffectDesc(*effects[i]); // deep copy
793 loadEffectParameters(node, effect->mParams);
794 ALOGV("loadEffectConfig() adding effect %s uuid %08x",
795 effect->mName, effect->mUuid.timeLow);
796 desc->mEffects.add(effect);
797 node = node->next;
798 }
799 if (desc->mEffects.size() == 0) {
800 ALOGW("loadEffectConfig() no valid effects found in config %s", root->name);
801 delete desc;
802 return NULL;
803 }
804 return desc;
805}
806
807status_t AudioPolicyEffects::loadInputEffectConfigurations(cnode *root,
808 const Vector <EffectDesc *>& effects)
809{
810 cnode *node = config_find(root, PREPROCESSING_TAG);
811 if (node == NULL) {
812 return -ENOENT;
813 }
814 node = node->first_child;
815 while (node) {
816 audio_source_t source = inputSourceNameToEnum(node->name);
817 if (source == AUDIO_SOURCE_CNT) {
818 ALOGW("loadInputSources() invalid input source %s", node->name);
819 node = node->next;
820 continue;
821 }
822 ALOGV("loadInputSources() loading input source %s", node->name);
823 EffectDescVector *desc = loadEffectConfig(node, effects);
824 if (desc == NULL) {
825 node = node->next;
826 continue;
827 }
828 mInputSources.add(source, desc);
829 node = node->next;
830 }
831 return NO_ERROR;
832}
833
834status_t AudioPolicyEffects::loadStreamEffectConfigurations(cnode *root,
835 const Vector <EffectDesc *>& effects)
836{
837 cnode *node = config_find(root, OUTPUT_SESSION_PROCESSING_TAG);
838 if (node == NULL) {
839 return -ENOENT;
840 }
841 node = node->first_child;
842 while (node) {
843 audio_stream_type_t stream = streamNameToEnum(node->name);
Eric Laurent223fd5c2014-11-11 13:43:36 -0800844 if (stream == AUDIO_STREAM_PUBLIC_CNT) {
bryant_liuba2b4392014-06-11 16:49:30 +0800845 ALOGW("loadStreamEffectConfigurations() invalid output stream %s", node->name);
846 node = node->next;
847 continue;
848 }
849 ALOGV("loadStreamEffectConfigurations() loading output stream %s", node->name);
850 EffectDescVector *desc = loadEffectConfig(node, effects);
851 if (desc == NULL) {
852 node = node->next;
853 continue;
854 }
855 mOutputStreams.add(stream, desc);
856 node = node->next;
857 }
858 return NO_ERROR;
859}
860
861AudioPolicyEffects::EffectDesc *AudioPolicyEffects::loadEffect(cnode *root)
862{
863 cnode *node = config_find(root, UUID_TAG);
864 if (node == NULL) {
865 return NULL;
866 }
867 effect_uuid_t uuid;
868 if (AudioEffect::stringToGuid(node->value, &uuid) != NO_ERROR) {
869 ALOGW("loadEffect() invalid uuid %s", node->value);
870 return NULL;
871 }
872 return new EffectDesc(root->name, uuid);
873}
874
875status_t AudioPolicyEffects::loadEffects(cnode *root, Vector <EffectDesc *>& effects)
876{
877 cnode *node = config_find(root, EFFECTS_TAG);
878 if (node == NULL) {
879 return -ENOENT;
880 }
881 node = node->first_child;
882 while (node) {
883 ALOGV("loadEffects() loading effect %s", node->name);
884 EffectDesc *effect = loadEffect(node);
885 if (effect == NULL) {
886 node = node->next;
887 continue;
888 }
889 effects.add(effect);
890 node = node->next;
891 }
892 return NO_ERROR;
893}
894
Kevin Rocard4fb615c2017-06-26 10:28:13 -0700895status_t AudioPolicyEffects::loadAudioEffectXmlConfig() {
896 auto result = effectsConfig::parse();
897 if (result.parsedConfig == nullptr) {
898 return -ENOENT;
899 }
900
901 auto loadProcessingChain = [](auto& processingChain, auto& streams) {
902 for (auto& stream : processingChain) {
903 auto effectDescs = std::make_unique<EffectDescVector>();
904 for (auto& effect : stream.effects) {
905 effectDescs->mEffects.add(
906 new EffectDesc{effect.get().name.c_str(), effect.get().uuid});
907 }
908 streams.add(stream.type, effectDescs.release());
909 }
910 };
911 loadProcessingChain(result.parsedConfig->preprocess, mInputSources);
912 loadProcessingChain(result.parsedConfig->postprocess, mOutputStreams);
913 // Casting from ssize_t to status_t is probably safe, there should not be more than 2^31 errors
914 return result.nbSkippedElement;
915}
916
bryant_liuba2b4392014-06-11 16:49:30 +0800917status_t AudioPolicyEffects::loadAudioEffectConfig(const char *path)
918{
919 cnode *root;
920 char *data;
921
922 data = (char *)load_file(path, NULL);
923 if (data == NULL) {
924 return -ENODEV;
925 }
926 root = config_node("", "");
927 config_load(root, data);
928
929 Vector <EffectDesc *> effects;
930 loadEffects(root, effects);
931 loadInputEffectConfigurations(root, effects);
932 loadStreamEffectConfigurations(root, effects);
933
Eric Laurent182c2f52015-01-15 14:29:19 -0800934 for (size_t i = 0; i < effects.size(); i++) {
935 delete effects[i];
936 }
937
bryant_liuba2b4392014-06-11 16:49:30 +0800938 config_free(root);
939 free(root);
940 free(data);
941
942 return NO_ERROR;
943}
944
945
Mikhail Naganov1b2a7942017-12-08 10:18:09 -0800946} // namespace android