blob: 919a90d74474ed9a58f41ba6c037586b744b38df [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>
Ari Hausman-Cohen433722e2018-04-24 14:25:22 -070026#include <media/AudioPolicyHelper.h>
Kevin Rocard4fb615c2017-06-26 10:28:13 -070027#include <media/EffectsConfig.h>
Andy Hungab7ef302018-05-15 19:35:29 -070028#include <mediautils/ServiceUtilities.h>
bryant_liuba2b4392014-06-11 16:49:30 +080029#include <system/audio.h>
Mikhail Naganovc2f710f2016-10-17 18:05:36 -070030#include <system/audio_effects/audio_effects_conf.h>
bryant_liuba2b4392014-06-11 16:49:30 +080031#include <utils/Vector.h>
32#include <utils/SortedVector.h>
33#include <cutils/config_utils.h>
Eric Laurentb6436272016-12-07 19:24:50 -080034#include <binder/IPCThreadState.h>
bryant_liuba2b4392014-06-11 16:49:30 +080035#include "AudioPolicyEffects.h"
bryant_liuba2b4392014-06-11 16:49:30 +080036
37namespace android {
38
39// ----------------------------------------------------------------------------
40// AudioPolicyEffects Implementation
41// ----------------------------------------------------------------------------
42
43AudioPolicyEffects::AudioPolicyEffects()
44{
Kevin Rocard4fb615c2017-06-26 10:28:13 -070045 status_t loadResult = loadAudioEffectXmlConfig();
46 if (loadResult < 0) {
47 ALOGW("Failed to load XML effect configuration, fallback to .conf");
48 // load automatic audio effect modules
49 if (access(AUDIO_EFFECT_VENDOR_CONFIG_FILE, R_OK) == 0) {
50 loadAudioEffectConfig(AUDIO_EFFECT_VENDOR_CONFIG_FILE);
51 } else if (access(AUDIO_EFFECT_DEFAULT_CONFIG_FILE, R_OK) == 0) {
52 loadAudioEffectConfig(AUDIO_EFFECT_DEFAULT_CONFIG_FILE);
53 }
54 } else if (loadResult > 0) {
55 ALOGE("Effect config is partially invalid, skipped %d elements", loadResult);
bryant_liuba2b4392014-06-11 16:49:30 +080056 }
57}
58
59
60AudioPolicyEffects::~AudioPolicyEffects()
61{
62 size_t i = 0;
63 // release audio input processing resources
64 for (i = 0; i < mInputSources.size(); i++) {
65 delete mInputSources.valueAt(i);
66 }
67 mInputSources.clear();
68
Eric Laurentfb66dd92016-01-28 18:32:03 -080069 for (i = 0; i < mInputSessions.size(); i++) {
70 mInputSessions.valueAt(i)->mEffects.clear();
71 delete mInputSessions.valueAt(i);
bryant_liuba2b4392014-06-11 16:49:30 +080072 }
Eric Laurentfb66dd92016-01-28 18:32:03 -080073 mInputSessions.clear();
bryant_liuba2b4392014-06-11 16:49:30 +080074
75 // release audio output processing resources
76 for (i = 0; i < mOutputStreams.size(); i++) {
77 delete mOutputStreams.valueAt(i);
78 }
79 mOutputStreams.clear();
80
81 for (i = 0; i < mOutputSessions.size(); i++) {
82 mOutputSessions.valueAt(i)->mEffects.clear();
83 delete mOutputSessions.valueAt(i);
84 }
85 mOutputSessions.clear();
86}
87
88
89status_t AudioPolicyEffects::addInputEffects(audio_io_handle_t input,
90 audio_source_t inputSource,
Eric Laurentfb66dd92016-01-28 18:32:03 -080091 audio_session_t audioSession)
bryant_liuba2b4392014-06-11 16:49:30 +080092{
93 status_t status = NO_ERROR;
94
95 // create audio pre processors according to input source
96 audio_source_t aliasSource = (inputSource == AUDIO_SOURCE_HOTWORD) ?
97 AUDIO_SOURCE_VOICE_RECOGNITION : inputSource;
98
Eric Laurent8b1e80b2014-10-07 09:08:47 -070099 Mutex::Autolock _l(mLock);
bryant_liuba2b4392014-06-11 16:49:30 +0800100 ssize_t index = mInputSources.indexOfKey(aliasSource);
101 if (index < 0) {
102 ALOGV("addInputEffects(): no processing needs to be attached to this source");
103 return status;
104 }
Eric Laurentfb66dd92016-01-28 18:32:03 -0800105 ssize_t idx = mInputSessions.indexOfKey(audioSession);
106 EffectVector *sessionDesc;
bryant_liuba2b4392014-06-11 16:49:30 +0800107 if (idx < 0) {
Eric Laurentfb66dd92016-01-28 18:32:03 -0800108 sessionDesc = new EffectVector(audioSession);
109 mInputSessions.add(audioSession, sessionDesc);
bryant_liuba2b4392014-06-11 16:49:30 +0800110 } else {
bryant_liu890a5632014-08-20 18:06:13 +0800111 // EffectVector is existing and we just need to increase ref count
Eric Laurentfb66dd92016-01-28 18:32:03 -0800112 sessionDesc = mInputSessions.valueAt(idx);
bryant_liuba2b4392014-06-11 16:49:30 +0800113 }
Eric Laurentfb66dd92016-01-28 18:32:03 -0800114 sessionDesc->mRefCount++;
bryant_liu890a5632014-08-20 18:06:13 +0800115
Eric Laurentfb66dd92016-01-28 18:32:03 -0800116 ALOGV("addInputEffects(): input: %d, refCount: %d", input, sessionDesc->mRefCount);
117 if (sessionDesc->mRefCount == 1) {
Eric Laurentb6436272016-12-07 19:24:50 -0800118 int64_t token = IPCThreadState::self()->clearCallingIdentity();
Eric Laurent7de5ac12014-10-21 09:07:11 -0700119 Vector <EffectDesc *> effects = mInputSources.valueAt(index)->mEffects;
120 for (size_t i = 0; i < effects.size(); i++) {
121 EffectDesc *effect = effects[i];
Svet Ganovbe71aa22015-04-28 12:06:02 -0700122 sp<AudioEffect> fx = new AudioEffect(NULL, String16("android"), &effect->mUuid, -1, 0,
123 0, audioSession, input);
Eric Laurent7de5ac12014-10-21 09:07:11 -0700124 status_t status = fx->initCheck();
125 if (status != NO_ERROR && status != ALREADY_EXISTS) {
126 ALOGW("addInputEffects(): failed to create Fx %s on source %d",
127 effect->mName, (int32_t)aliasSource);
128 // fx goes out of scope and strong ref on AudioEffect is released
129 continue;
130 }
131 for (size_t j = 0; j < effect->mParams.size(); j++) {
132 fx->setParameter(effect->mParams[j]);
133 }
134 ALOGV("addInputEffects(): added Fx %s on source: %d",
bryant_liuba2b4392014-06-11 16:49:30 +0800135 effect->mName, (int32_t)aliasSource);
Eric Laurentfb66dd92016-01-28 18:32:03 -0800136 sessionDesc->mEffects.add(fx);
bryant_liuba2b4392014-06-11 16:49:30 +0800137 }
Eric Laurentfb66dd92016-01-28 18:32:03 -0800138 sessionDesc->setProcessorEnabled(true);
Eric Laurentb6436272016-12-07 19:24:50 -0800139 IPCThreadState::self()->restoreCallingIdentity(token);
bryant_liuba2b4392014-06-11 16:49:30 +0800140 }
bryant_liuba2b4392014-06-11 16:49:30 +0800141 return status;
142}
143
144
Eric Laurentfb66dd92016-01-28 18:32:03 -0800145status_t AudioPolicyEffects::releaseInputEffects(audio_io_handle_t input,
146 audio_session_t audioSession)
bryant_liuba2b4392014-06-11 16:49:30 +0800147{
148 status_t status = NO_ERROR;
149
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700150 Mutex::Autolock _l(mLock);
Eric Laurentfb66dd92016-01-28 18:32:03 -0800151 ssize_t index = mInputSessions.indexOfKey(audioSession);
bryant_liuba2b4392014-06-11 16:49:30 +0800152 if (index < 0) {
153 return status;
154 }
Eric Laurentfb66dd92016-01-28 18:32:03 -0800155 EffectVector *sessionDesc = mInputSessions.valueAt(index);
156 sessionDesc->mRefCount--;
157 ALOGV("releaseInputEffects(): input: %d, refCount: %d", input, sessionDesc->mRefCount);
158 if (sessionDesc->mRefCount == 0) {
159 sessionDesc->setProcessorEnabled(false);
160 delete sessionDesc;
161 mInputSessions.removeItemsAt(index);
bryant_liu890a5632014-08-20 18:06:13 +0800162 ALOGV("releaseInputEffects(): all effects released");
163 }
bryant_liuba2b4392014-06-11 16:49:30 +0800164 return status;
165}
166
Eric Laurentfb66dd92016-01-28 18:32:03 -0800167status_t AudioPolicyEffects::queryDefaultInputEffects(audio_session_t audioSession,
bryant_liuba2b4392014-06-11 16:49:30 +0800168 effect_descriptor_t *descriptors,
169 uint32_t *count)
170{
171 status_t status = NO_ERROR;
172
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700173 Mutex::Autolock _l(mLock);
bryant_liuba2b4392014-06-11 16:49:30 +0800174 size_t index;
Eric Laurentfb66dd92016-01-28 18:32:03 -0800175 for (index = 0; index < mInputSessions.size(); index++) {
176 if (mInputSessions.valueAt(index)->mSessionId == audioSession) {
bryant_liuba2b4392014-06-11 16:49:30 +0800177 break;
178 }
179 }
Eric Laurentfb66dd92016-01-28 18:32:03 -0800180 if (index == mInputSessions.size()) {
bryant_liuba2b4392014-06-11 16:49:30 +0800181 *count = 0;
182 return BAD_VALUE;
183 }
Eric Laurentfb66dd92016-01-28 18:32:03 -0800184 Vector< sp<AudioEffect> > effects = mInputSessions.valueAt(index)->mEffects;
bryant_liuba2b4392014-06-11 16:49:30 +0800185
186 for (size_t i = 0; i < effects.size(); i++) {
187 effect_descriptor_t desc = effects[i]->descriptor();
188 if (i < *count) {
189 descriptors[i] = desc;
190 }
191 }
192 if (effects.size() > *count) {
193 status = NO_MEMORY;
194 }
195 *count = effects.size();
196 return status;
197}
198
199
Eric Laurentfb66dd92016-01-28 18:32:03 -0800200status_t AudioPolicyEffects::queryDefaultOutputSessionEffects(audio_session_t audioSession,
bryant_liuba2b4392014-06-11 16:49:30 +0800201 effect_descriptor_t *descriptors,
202 uint32_t *count)
203{
204 status_t status = NO_ERROR;
205
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700206 Mutex::Autolock _l(mLock);
bryant_liuba2b4392014-06-11 16:49:30 +0800207 size_t index;
208 for (index = 0; index < mOutputSessions.size(); index++) {
209 if (mOutputSessions.valueAt(index)->mSessionId == audioSession) {
210 break;
211 }
212 }
213 if (index == mOutputSessions.size()) {
214 *count = 0;
215 return BAD_VALUE;
216 }
217 Vector< sp<AudioEffect> > effects = mOutputSessions.valueAt(index)->mEffects;
218
219 for (size_t i = 0; i < effects.size(); i++) {
220 effect_descriptor_t desc = effects[i]->descriptor();
221 if (i < *count) {
222 descriptors[i] = desc;
223 }
224 }
225 if (effects.size() > *count) {
226 status = NO_MEMORY;
227 }
228 *count = effects.size();
229 return status;
230}
231
232
233status_t AudioPolicyEffects::addOutputSessionEffects(audio_io_handle_t output,
234 audio_stream_type_t stream,
Eric Laurentfb66dd92016-01-28 18:32:03 -0800235 audio_session_t audioSession)
bryant_liuba2b4392014-06-11 16:49:30 +0800236{
237 status_t status = NO_ERROR;
238
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700239 Mutex::Autolock _l(mLock);
bryant_liuba2b4392014-06-11 16:49:30 +0800240 // create audio processors according to stream
Eric Laurent223fd5c2014-11-11 13:43:36 -0800241 // FIXME: should we have specific post processing settings for internal streams?
242 // default to media for now.
243 if (stream >= AUDIO_STREAM_PUBLIC_CNT) {
244 stream = AUDIO_STREAM_MUSIC;
245 }
bryant_liuba2b4392014-06-11 16:49:30 +0800246 ssize_t index = mOutputStreams.indexOfKey(stream);
247 if (index < 0) {
248 ALOGV("addOutputSessionEffects(): no output processing needed for this stream");
249 return NO_ERROR;
250 }
251
252 ssize_t idx = mOutputSessions.indexOfKey(audioSession);
253 EffectVector *procDesc;
254 if (idx < 0) {
255 procDesc = new EffectVector(audioSession);
256 mOutputSessions.add(audioSession, procDesc);
257 } else {
bryant_liu890a5632014-08-20 18:06:13 +0800258 // EffectVector is existing and we just need to increase ref count
bryant_liuba2b4392014-06-11 16:49:30 +0800259 procDesc = mOutputSessions.valueAt(idx);
260 }
bryant_liu890a5632014-08-20 18:06:13 +0800261 procDesc->mRefCount++;
262
Eric Laurent7de5ac12014-10-21 09:07:11 -0700263 ALOGV("addOutputSessionEffects(): session: %d, refCount: %d",
264 audioSession, procDesc->mRefCount);
265 if (procDesc->mRefCount == 1) {
Eric Laurentb6436272016-12-07 19:24:50 -0800266 // make sure effects are associated to audio server even if we are executing a binder call
267 int64_t token = IPCThreadState::self()->clearCallingIdentity();
Eric Laurent7de5ac12014-10-21 09:07:11 -0700268 Vector <EffectDesc *> effects = mOutputStreams.valueAt(index)->mEffects;
269 for (size_t i = 0; i < effects.size(); i++) {
270 EffectDesc *effect = effects[i];
Svet Ganovbe71aa22015-04-28 12:06:02 -0700271 sp<AudioEffect> fx = new AudioEffect(NULL, String16("android"), &effect->mUuid, 0, 0, 0,
Eric Laurent7de5ac12014-10-21 09:07:11 -0700272 audioSession, output);
273 status_t status = fx->initCheck();
274 if (status != NO_ERROR && status != ALREADY_EXISTS) {
275 ALOGE("addOutputSessionEffects(): failed to create Fx %s on session %d",
276 effect->mName, audioSession);
277 // fx goes out of scope and strong ref on AudioEffect is released
278 continue;
279 }
280 ALOGV("addOutputSessionEffects(): added Fx %s on session: %d for stream: %d",
281 effect->mName, audioSession, (int32_t)stream);
282 procDesc->mEffects.add(fx);
bryant_liuba2b4392014-06-11 16:49:30 +0800283 }
Eric Laurent7de5ac12014-10-21 09:07:11 -0700284
285 procDesc->setProcessorEnabled(true);
Eric Laurentb6436272016-12-07 19:24:50 -0800286 IPCThreadState::self()->restoreCallingIdentity(token);
bryant_liuba2b4392014-06-11 16:49:30 +0800287 }
bryant_liuba2b4392014-06-11 16:49:30 +0800288 return status;
289}
290
291status_t AudioPolicyEffects::releaseOutputSessionEffects(audio_io_handle_t output,
292 audio_stream_type_t stream,
Eric Laurentfb66dd92016-01-28 18:32:03 -0800293 audio_session_t audioSession)
bryant_liuba2b4392014-06-11 16:49:30 +0800294{
295 status_t status = NO_ERROR;
296 (void) output; // argument not used for now
297 (void) stream; // argument not used for now
298
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700299 Mutex::Autolock _l(mLock);
bryant_liuba2b4392014-06-11 16:49:30 +0800300 ssize_t index = mOutputSessions.indexOfKey(audioSession);
301 if (index < 0) {
302 ALOGV("releaseOutputSessionEffects: no output processing was attached to this stream");
303 return NO_ERROR;
304 }
305
306 EffectVector *procDesc = mOutputSessions.valueAt(index);
bryant_liu890a5632014-08-20 18:06:13 +0800307 procDesc->mRefCount--;
Eric Laurent7de5ac12014-10-21 09:07:11 -0700308 ALOGV("releaseOutputSessionEffects(): session: %d, refCount: %d",
309 audioSession, procDesc->mRefCount);
bryant_liu890a5632014-08-20 18:06:13 +0800310 if (procDesc->mRefCount == 0) {
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700311 procDesc->setProcessorEnabled(false);
bryant_liu890a5632014-08-20 18:06:13 +0800312 procDesc->mEffects.clear();
313 delete procDesc;
314 mOutputSessions.removeItemsAt(index);
315 ALOGV("releaseOutputSessionEffects(): output processing released from session: %d",
316 audioSession);
317 }
bryant_liuba2b4392014-06-11 16:49:30 +0800318 return status;
319}
320
Ari Hausman-Cohen24628312018-08-13 15:01:09 -0700321status_t AudioPolicyEffects::addSourceDefaultEffect(const effect_uuid_t *type,
322 const String16& opPackageName,
323 const effect_uuid_t *uuid,
324 int32_t priority,
325 audio_source_t source,
326 audio_unique_id_t* id)
327{
328 if (uuid == NULL || type == NULL) {
329 ALOGE("addSourceDefaultEffect(): Null uuid or type uuid pointer");
330 return BAD_VALUE;
331 }
332
Eric Laurentae4b6ec2019-01-15 18:34:38 -0800333 // HOTWORD, FM_TUNER and ECHO_REFERENCE are special case sources > MAX.
Ari Hausman-Cohen24628312018-08-13 15:01:09 -0700334 if (source < AUDIO_SOURCE_DEFAULT ||
335 (source > AUDIO_SOURCE_MAX &&
336 source != AUDIO_SOURCE_HOTWORD &&
Eric Laurentae4b6ec2019-01-15 18:34:38 -0800337 source != AUDIO_SOURCE_FM_TUNER &&
338 source != AUDIO_SOURCE_ECHO_REFERENCE)) {
Ari Hausman-Cohen24628312018-08-13 15:01:09 -0700339 ALOGE("addSourceDefaultEffect(): Unsupported source type %d", source);
340 return BAD_VALUE;
341 }
342
343 // Check that |uuid| or |type| corresponds to an effect on the system.
344 effect_descriptor_t descriptor = {};
345 status_t res = AudioEffect::getEffectDescriptor(
346 uuid, type, EFFECT_FLAG_TYPE_PRE_PROC, &descriptor);
347 if (res != OK) {
348 ALOGE("addSourceDefaultEffect(): Failed to find effect descriptor matching uuid/type.");
349 return res;
350 }
351
352 // Only pre-processing effects can be added dynamically as source defaults.
353 if ((descriptor.flags & EFFECT_FLAG_TYPE_MASK) != EFFECT_FLAG_TYPE_PRE_PROC) {
354 ALOGE("addSourceDefaultEffect(): Desired effect cannot be attached "
355 "as a source default effect.");
356 return BAD_VALUE;
357 }
358
359 Mutex::Autolock _l(mLock);
360
361 // Find the EffectDescVector for the given source type, or create a new one if necessary.
362 ssize_t index = mInputSources.indexOfKey(source);
363 EffectDescVector *desc = NULL;
364 if (index < 0) {
365 // No effects for this source type yet.
366 desc = new EffectDescVector();
367 mInputSources.add(source, desc);
368 } else {
369 desc = mInputSources.valueAt(index);
370 }
371
372 // Create a new effect and add it to the vector.
373 res = AudioEffect::newEffectUniqueId(id);
374 if (res != OK) {
375 ALOGE("addSourceDefaultEffect(): failed to get new unique id.");
376 return res;
377 }
378 EffectDesc *effect = new EffectDesc(
379 descriptor.name, *type, opPackageName, *uuid, priority, *id);
380 desc->mEffects.add(effect);
381 // TODO(b/71813697): Support setting params as well.
382
383 // TODO(b/71814300): Retroactively attach to any existing sources of the given type.
384 // This requires tracking the source type of each session id in addition to what is
385 // already being tracked.
386
387 return NO_ERROR;
388}
389
Ari Hausman-Cohen433722e2018-04-24 14:25:22 -0700390status_t AudioPolicyEffects::addStreamDefaultEffect(const effect_uuid_t *type,
391 const String16& opPackageName,
392 const effect_uuid_t *uuid,
393 int32_t priority,
394 audio_usage_t usage,
395 audio_unique_id_t* id)
396{
397 if (uuid == NULL || type == NULL) {
398 ALOGE("addStreamDefaultEffect(): Null uuid or type uuid pointer");
399 return BAD_VALUE;
400 }
401
402 audio_stream_type_t stream = audio_usage_to_stream_type(usage);
403
404 if (stream < AUDIO_STREAM_MIN || stream >= AUDIO_STREAM_PUBLIC_CNT) {
405 ALOGE("addStreamDefaultEffect(): Unsupported stream type %d", stream);
406 return BAD_VALUE;
407 }
408
409 // Check that |uuid| or |type| corresponds to an effect on the system.
410 effect_descriptor_t descriptor = {};
411 status_t res = AudioEffect::getEffectDescriptor(
412 uuid, type, EFFECT_FLAG_TYPE_INSERT, &descriptor);
413 if (res != OK) {
414 ALOGE("addStreamDefaultEffect(): Failed to find effect descriptor matching uuid/type.");
415 return res;
416 }
417
418 // Only insert effects can be added dynamically as stream defaults.
419 if ((descriptor.flags & EFFECT_FLAG_TYPE_MASK) != EFFECT_FLAG_TYPE_INSERT) {
420 ALOGE("addStreamDefaultEffect(): Desired effect cannot be attached "
421 "as a stream default effect.");
422 return BAD_VALUE;
423 }
424
425 Mutex::Autolock _l(mLock);
426
427 // Find the EffectDescVector for the given stream type, or create a new one if necessary.
428 ssize_t index = mOutputStreams.indexOfKey(stream);
429 EffectDescVector *desc = NULL;
430 if (index < 0) {
431 // No effects for this stream type yet.
432 desc = new EffectDescVector();
433 mOutputStreams.add(stream, desc);
434 } else {
435 desc = mOutputStreams.valueAt(index);
436 }
437
438 // Create a new effect and add it to the vector.
439 res = AudioEffect::newEffectUniqueId(id);
440 if (res != OK) {
441 ALOGE("addStreamDefaultEffect(): failed to get new unique id.");
442 return res;
443 }
444 EffectDesc *effect = new EffectDesc(
445 descriptor.name, *type, opPackageName, *uuid, priority, *id);
446 desc->mEffects.add(effect);
447 // TODO(b/71813697): Support setting params as well.
448
449 // TODO(b/71814300): Retroactively attach to any existing streams of the given type.
450 // This requires tracking the stream type of each session id in addition to what is
451 // already being tracked.
452
453 return NO_ERROR;
454}
455
Ari Hausman-Cohen24628312018-08-13 15:01:09 -0700456status_t AudioPolicyEffects::removeSourceDefaultEffect(audio_unique_id_t id)
457{
458 if (id == AUDIO_UNIQUE_ID_ALLOCATE) {
459 // ALLOCATE is not a unique identifier, but rather a reserved value indicating
460 // a real id has not been assigned. For default effects, this value is only used
461 // by system-owned defaults from the loaded config, which cannot be removed.
462 return BAD_VALUE;
463 }
464
465 Mutex::Autolock _l(mLock);
466
467 // Check each source type.
468 size_t numSources = mInputSources.size();
469 for (size_t i = 0; i < numSources; ++i) {
470 // Check each effect for each source.
471 EffectDescVector* descVector = mInputSources[i];
472 for (auto desc = descVector->mEffects.begin(); desc != descVector->mEffects.end(); ++desc) {
473 if ((*desc)->mId == id) {
474 // Found it!
475 // TODO(b/71814300): Remove from any sources the effect was attached to.
476 descVector->mEffects.erase(desc);
477 // Handles are unique; there can only be one match, so return early.
478 return NO_ERROR;
479 }
480 }
481 }
482
483 // Effect wasn't found, so it's been trivially removed successfully.
484 return NO_ERROR;
485}
486
Ari Hausman-Cohen433722e2018-04-24 14:25:22 -0700487status_t AudioPolicyEffects::removeStreamDefaultEffect(audio_unique_id_t id)
488{
489 if (id == AUDIO_UNIQUE_ID_ALLOCATE) {
490 // ALLOCATE is not a unique identifier, but rather a reserved value indicating
491 // a real id has not been assigned. For default effects, this value is only used
492 // by system-owned defaults from the loaded config, which cannot be removed.
493 return BAD_VALUE;
494 }
495
496 Mutex::Autolock _l(mLock);
497
498 // Check each stream type.
499 size_t numStreams = mOutputStreams.size();
500 for (size_t i = 0; i < numStreams; ++i) {
501 // Check each effect for each stream.
502 EffectDescVector* descVector = mOutputStreams[i];
503 for (auto desc = descVector->mEffects.begin(); desc != descVector->mEffects.end(); ++desc) {
504 if ((*desc)->mId == id) {
505 // Found it!
506 // TODO(b/71814300): Remove from any streams the effect was attached to.
507 descVector->mEffects.erase(desc);
508 // Handles are unique; there can only be one match, so return early.
509 return NO_ERROR;
510 }
511 }
512 }
513
514 // Effect wasn't found, so it's been trivially removed successfully.
515 return NO_ERROR;
516}
bryant_liuba2b4392014-06-11 16:49:30 +0800517
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700518void AudioPolicyEffects::EffectVector::setProcessorEnabled(bool enabled)
bryant_liuba2b4392014-06-11 16:49:30 +0800519{
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700520 for (size_t i = 0; i < mEffects.size(); i++) {
521 mEffects.itemAt(i)->setEnabled(enabled);
bryant_liuba2b4392014-06-11 16:49:30 +0800522 }
523}
524
525
526// ----------------------------------------------------------------------------
527// Audio processing configuration
528// ----------------------------------------------------------------------------
529
530/*static*/ const char * const AudioPolicyEffects::kInputSourceNames[AUDIO_SOURCE_CNT -1] = {
531 MIC_SRC_TAG,
532 VOICE_UL_SRC_TAG,
533 VOICE_DL_SRC_TAG,
534 VOICE_CALL_SRC_TAG,
535 CAMCORDER_SRC_TAG,
536 VOICE_REC_SRC_TAG,
rago8a397d52015-12-02 11:27:57 -0800537 VOICE_COMM_SRC_TAG,
Eric Laurentae4b6ec2019-01-15 18:34:38 -0800538 UNPROCESSED_SRC_TAG,
539 VOICE_PERFORMANCE_SRC_TAG
bryant_liuba2b4392014-06-11 16:49:30 +0800540};
541
542// returns the audio_source_t enum corresponding to the input source name or
543// AUDIO_SOURCE_CNT is no match found
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700544/*static*/ audio_source_t AudioPolicyEffects::inputSourceNameToEnum(const char *name)
bryant_liuba2b4392014-06-11 16:49:30 +0800545{
546 int i;
547 for (i = AUDIO_SOURCE_MIC; i < AUDIO_SOURCE_CNT; i++) {
548 if (strcmp(name, kInputSourceNames[i - AUDIO_SOURCE_MIC]) == 0) {
549 ALOGV("inputSourceNameToEnum found source %s %d", name, i);
550 break;
551 }
552 }
553 return (audio_source_t)i;
554}
555
Eric Laurent223fd5c2014-11-11 13:43:36 -0800556const char *AudioPolicyEffects::kStreamNames[AUDIO_STREAM_PUBLIC_CNT+1] = {
bryant_liuba2b4392014-06-11 16:49:30 +0800557 AUDIO_STREAM_DEFAULT_TAG,
558 AUDIO_STREAM_VOICE_CALL_TAG,
559 AUDIO_STREAM_SYSTEM_TAG,
560 AUDIO_STREAM_RING_TAG,
561 AUDIO_STREAM_MUSIC_TAG,
562 AUDIO_STREAM_ALARM_TAG,
563 AUDIO_STREAM_NOTIFICATION_TAG,
564 AUDIO_STREAM_BLUETOOTH_SCO_TAG,
565 AUDIO_STREAM_ENFORCED_AUDIBLE_TAG,
566 AUDIO_STREAM_DTMF_TAG,
567 AUDIO_STREAM_TTS_TAG
568};
569
570// returns the audio_stream_t enum corresponding to the output stream name or
Eric Laurent223fd5c2014-11-11 13:43:36 -0800571// AUDIO_STREAM_PUBLIC_CNT is no match found
bryant_liuba2b4392014-06-11 16:49:30 +0800572audio_stream_type_t AudioPolicyEffects::streamNameToEnum(const char *name)
573{
574 int i;
Eric Laurent223fd5c2014-11-11 13:43:36 -0800575 for (i = AUDIO_STREAM_DEFAULT; i < AUDIO_STREAM_PUBLIC_CNT; i++) {
bryant_liuba2b4392014-06-11 16:49:30 +0800576 if (strcmp(name, kStreamNames[i - AUDIO_STREAM_DEFAULT]) == 0) {
577 ALOGV("streamNameToEnum found stream %s %d", name, i);
578 break;
579 }
580 }
581 return (audio_stream_type_t)i;
582}
583
584// ----------------------------------------------------------------------------
585// Audio Effect Config parser
586// ----------------------------------------------------------------------------
587
Eric Laurent138ed172016-02-10 10:40:44 -0800588size_t AudioPolicyEffects::growParamSize(char **param,
bryant_liuba2b4392014-06-11 16:49:30 +0800589 size_t size,
590 size_t *curSize,
591 size_t *totSize)
592{
593 // *curSize is at least sizeof(effect_param_t) + 2 * sizeof(int)
594 size_t pos = ((*curSize - 1 ) / size + 1) * size;
595
596 if (pos + size > *totSize) {
597 while (pos + size > *totSize) {
598 *totSize += ((*totSize + 7) / 8) * 4;
599 }
George Burgess IV31225682018-02-12 11:08:38 -0800600 char *newParam = (char *)realloc(*param, *totSize);
601 if (newParam == NULL) {
Eric Laurent138ed172016-02-10 10:40:44 -0800602 ALOGE("%s realloc error for size %zu", __func__, *totSize);
603 return 0;
604 }
George Burgess IV31225682018-02-12 11:08:38 -0800605 *param = newParam;
bryant_liuba2b4392014-06-11 16:49:30 +0800606 }
607 *curSize = pos + size;
608 return pos;
609}
610
Eric Laurent138ed172016-02-10 10:40:44 -0800611
bryant_liuba2b4392014-06-11 16:49:30 +0800612size_t AudioPolicyEffects::readParamValue(cnode *node,
Eric Laurent138ed172016-02-10 10:40:44 -0800613 char **param,
bryant_liuba2b4392014-06-11 16:49:30 +0800614 size_t *curSize,
615 size_t *totSize)
616{
Eric Laurent138ed172016-02-10 10:40:44 -0800617 size_t len = 0;
618 size_t pos;
619
bryant_liuba2b4392014-06-11 16:49:30 +0800620 if (strncmp(node->name, SHORT_TAG, sizeof(SHORT_TAG) + 1) == 0) {
Eric Laurent138ed172016-02-10 10:40:44 -0800621 pos = growParamSize(param, sizeof(short), curSize, totSize);
622 if (pos == 0) {
623 goto exit;
bryant_liuba2b4392014-06-11 16:49:30 +0800624 }
Eric Laurent138ed172016-02-10 10:40:44 -0800625 *(short *)(*param + pos) = (short)atoi(node->value);
626 ALOGV("readParamValue() reading short %d", *(short *)(*param + pos));
627 len = sizeof(short);
628 } else if (strncmp(node->name, INT_TAG, sizeof(INT_TAG) + 1) == 0) {
629 pos = growParamSize(param, sizeof(int), curSize, totSize);
630 if (pos == 0) {
631 goto exit;
632 }
633 *(int *)(*param + pos) = atoi(node->value);
634 ALOGV("readParamValue() reading int %d", *(int *)(*param + pos));
635 len = sizeof(int);
636 } else if (strncmp(node->name, FLOAT_TAG, sizeof(FLOAT_TAG) + 1) == 0) {
637 pos = growParamSize(param, sizeof(float), curSize, totSize);
638 if (pos == 0) {
639 goto exit;
640 }
641 *(float *)(*param + pos) = (float)atof(node->value);
642 ALOGV("readParamValue() reading float %f",*(float *)(*param + pos));
643 len = sizeof(float);
644 } else if (strncmp(node->name, BOOL_TAG, sizeof(BOOL_TAG) + 1) == 0) {
645 pos = growParamSize(param, sizeof(bool), curSize, totSize);
646 if (pos == 0) {
647 goto exit;
648 }
649 if (strncmp(node->value, "true", strlen("true") + 1) == 0) {
650 *(bool *)(*param + pos) = true;
651 } else {
652 *(bool *)(*param + pos) = false;
653 }
654 ALOGV("readParamValue() reading bool %s",
655 *(bool *)(*param + pos) ? "true" : "false");
656 len = sizeof(bool);
bryant_liuba2b4392014-06-11 16:49:30 +0800657 } else if (strncmp(node->name, STRING_TAG, sizeof(STRING_TAG) + 1) == 0) {
Eric Laurent138ed172016-02-10 10:40:44 -0800658 len = strnlen(node->value, EFFECT_STRING_LEN_MAX);
bryant_liuba2b4392014-06-11 16:49:30 +0800659 if (*curSize + len + 1 > *totSize) {
660 *totSize = *curSize + len + 1;
Chih-Hung Hsieh03077682018-08-30 14:11:00 -0700661 char *newParam = (char *)realloc(*param, *totSize);
662 if (newParam == NULL) {
Eric Laurent138ed172016-02-10 10:40:44 -0800663 len = 0;
664 ALOGE("%s realloc error for string len %zu", __func__, *totSize);
665 goto exit;
666 }
Chih-Hung Hsieh03077682018-08-30 14:11:00 -0700667 *param = newParam;
bryant_liuba2b4392014-06-11 16:49:30 +0800668 }
Eric Laurent138ed172016-02-10 10:40:44 -0800669 strncpy(*param + *curSize, node->value, len);
bryant_liuba2b4392014-06-11 16:49:30 +0800670 *curSize += len;
Eric Laurent138ed172016-02-10 10:40:44 -0800671 (*param)[*curSize] = '\0';
672 ALOGV("readParamValue() reading string %s", *param + *curSize - len);
673 } else {
674 ALOGW("readParamValue() unknown param type %s", node->name);
bryant_liuba2b4392014-06-11 16:49:30 +0800675 }
Eric Laurent138ed172016-02-10 10:40:44 -0800676exit:
677 return len;
bryant_liuba2b4392014-06-11 16:49:30 +0800678}
679
680effect_param_t *AudioPolicyEffects::loadEffectParameter(cnode *root)
681{
682 cnode *param;
683 cnode *value;
684 size_t curSize = sizeof(effect_param_t);
685 size_t totSize = sizeof(effect_param_t) + 2 * sizeof(int);
686 effect_param_t *fx_param = (effect_param_t *)malloc(totSize);
687
Eric Laurent138ed172016-02-10 10:40:44 -0800688 if (fx_param == NULL) {
689 ALOGE("%s malloc error for effect structure of size %zu",
690 __func__, totSize);
691 return NULL;
692 }
693
bryant_liuba2b4392014-06-11 16:49:30 +0800694 param = config_find(root, PARAM_TAG);
695 value = config_find(root, VALUE_TAG);
696 if (param == NULL && value == NULL) {
697 // try to parse simple parameter form {int int}
698 param = root->first_child;
699 if (param != NULL) {
700 // Note: that a pair of random strings is read as 0 0
701 int *ptr = (int *)fx_param->data;
Eric Laurent138ed172016-02-10 10:40:44 -0800702#if LOG_NDEBUG == 0
bryant_liuba2b4392014-06-11 16:49:30 +0800703 int *ptr2 = (int *)((char *)param + sizeof(effect_param_t));
Eric Laurent138ed172016-02-10 10:40:44 -0800704 ALOGV("loadEffectParameter() ptr %p ptr2 %p", ptr, ptr2);
705#endif
bryant_liuba2b4392014-06-11 16:49:30 +0800706 *ptr++ = atoi(param->name);
707 *ptr = atoi(param->value);
708 fx_param->psize = sizeof(int);
709 fx_param->vsize = sizeof(int);
710 return fx_param;
711 }
712 }
713 if (param == NULL || value == NULL) {
Eric Laurent138ed172016-02-10 10:40:44 -0800714 ALOGW("loadEffectParameter() invalid parameter description %s",
715 root->name);
bryant_liuba2b4392014-06-11 16:49:30 +0800716 goto error;
717 }
718
719 fx_param->psize = 0;
720 param = param->first_child;
721 while (param) {
722 ALOGV("loadEffectParameter() reading param of type %s", param->name);
Eric Laurent138ed172016-02-10 10:40:44 -0800723 size_t size =
724 readParamValue(param, (char **)&fx_param, &curSize, &totSize);
bryant_liuba2b4392014-06-11 16:49:30 +0800725 if (size == 0) {
726 goto error;
727 }
728 fx_param->psize += size;
729 param = param->next;
730 }
731
732 // align start of value field on 32 bit boundary
733 curSize = ((curSize - 1 ) / sizeof(int) + 1) * sizeof(int);
734
735 fx_param->vsize = 0;
736 value = value->first_child;
737 while (value) {
738 ALOGV("loadEffectParameter() reading value of type %s", value->name);
Eric Laurent138ed172016-02-10 10:40:44 -0800739 size_t size =
740 readParamValue(value, (char **)&fx_param, &curSize, &totSize);
bryant_liuba2b4392014-06-11 16:49:30 +0800741 if (size == 0) {
742 goto error;
743 }
744 fx_param->vsize += size;
745 value = value->next;
746 }
747
748 return fx_param;
749
750error:
Eric Laurent138ed172016-02-10 10:40:44 -0800751 free(fx_param);
bryant_liuba2b4392014-06-11 16:49:30 +0800752 return NULL;
753}
754
755void AudioPolicyEffects::loadEffectParameters(cnode *root, Vector <effect_param_t *>& params)
756{
757 cnode *node = root->first_child;
758 while (node) {
759 ALOGV("loadEffectParameters() loading param %s", node->name);
760 effect_param_t *param = loadEffectParameter(node);
Eric Laurent138ed172016-02-10 10:40:44 -0800761 if (param != NULL) {
762 params.add(param);
bryant_liuba2b4392014-06-11 16:49:30 +0800763 }
bryant_liuba2b4392014-06-11 16:49:30 +0800764 node = node->next;
765 }
766}
767
768
769AudioPolicyEffects::EffectDescVector *AudioPolicyEffects::loadEffectConfig(
770 cnode *root,
771 const Vector <EffectDesc *>& effects)
772{
773 cnode *node = root->first_child;
774 if (node == NULL) {
775 ALOGW("loadInputSource() empty element %s", root->name);
776 return NULL;
777 }
778 EffectDescVector *desc = new EffectDescVector();
779 while (node) {
780 size_t i;
Eric Laurent138ed172016-02-10 10:40:44 -0800781
bryant_liuba2b4392014-06-11 16:49:30 +0800782 for (i = 0; i < effects.size(); i++) {
783 if (strncmp(effects[i]->mName, node->name, EFFECT_STRING_LEN_MAX) == 0) {
784 ALOGV("loadEffectConfig() found effect %s in list", node->name);
785 break;
786 }
787 }
788 if (i == effects.size()) {
789 ALOGV("loadEffectConfig() effect %s not in list", node->name);
790 node = node->next;
791 continue;
792 }
793 EffectDesc *effect = new EffectDesc(*effects[i]); // deep copy
794 loadEffectParameters(node, effect->mParams);
795 ALOGV("loadEffectConfig() adding effect %s uuid %08x",
796 effect->mName, effect->mUuid.timeLow);
797 desc->mEffects.add(effect);
798 node = node->next;
799 }
800 if (desc->mEffects.size() == 0) {
801 ALOGW("loadEffectConfig() no valid effects found in config %s", root->name);
802 delete desc;
803 return NULL;
804 }
805 return desc;
806}
807
808status_t AudioPolicyEffects::loadInputEffectConfigurations(cnode *root,
809 const Vector <EffectDesc *>& effects)
810{
811 cnode *node = config_find(root, PREPROCESSING_TAG);
812 if (node == NULL) {
813 return -ENOENT;
814 }
815 node = node->first_child;
816 while (node) {
817 audio_source_t source = inputSourceNameToEnum(node->name);
818 if (source == AUDIO_SOURCE_CNT) {
819 ALOGW("loadInputSources() invalid input source %s", node->name);
820 node = node->next;
821 continue;
822 }
823 ALOGV("loadInputSources() loading input source %s", node->name);
824 EffectDescVector *desc = loadEffectConfig(node, effects);
825 if (desc == NULL) {
826 node = node->next;
827 continue;
828 }
829 mInputSources.add(source, desc);
830 node = node->next;
831 }
832 return NO_ERROR;
833}
834
835status_t AudioPolicyEffects::loadStreamEffectConfigurations(cnode *root,
836 const Vector <EffectDesc *>& effects)
837{
838 cnode *node = config_find(root, OUTPUT_SESSION_PROCESSING_TAG);
839 if (node == NULL) {
840 return -ENOENT;
841 }
842 node = node->first_child;
843 while (node) {
844 audio_stream_type_t stream = streamNameToEnum(node->name);
Eric Laurent223fd5c2014-11-11 13:43:36 -0800845 if (stream == AUDIO_STREAM_PUBLIC_CNT) {
bryant_liuba2b4392014-06-11 16:49:30 +0800846 ALOGW("loadStreamEffectConfigurations() invalid output stream %s", node->name);
847 node = node->next;
848 continue;
849 }
850 ALOGV("loadStreamEffectConfigurations() loading output stream %s", node->name);
851 EffectDescVector *desc = loadEffectConfig(node, effects);
852 if (desc == NULL) {
853 node = node->next;
854 continue;
855 }
856 mOutputStreams.add(stream, desc);
857 node = node->next;
858 }
859 return NO_ERROR;
860}
861
862AudioPolicyEffects::EffectDesc *AudioPolicyEffects::loadEffect(cnode *root)
863{
864 cnode *node = config_find(root, UUID_TAG);
865 if (node == NULL) {
866 return NULL;
867 }
868 effect_uuid_t uuid;
869 if (AudioEffect::stringToGuid(node->value, &uuid) != NO_ERROR) {
870 ALOGW("loadEffect() invalid uuid %s", node->value);
871 return NULL;
872 }
873 return new EffectDesc(root->name, uuid);
874}
875
876status_t AudioPolicyEffects::loadEffects(cnode *root, Vector <EffectDesc *>& effects)
877{
878 cnode *node = config_find(root, EFFECTS_TAG);
879 if (node == NULL) {
880 return -ENOENT;
881 }
882 node = node->first_child;
883 while (node) {
884 ALOGV("loadEffects() loading effect %s", node->name);
885 EffectDesc *effect = loadEffect(node);
886 if (effect == NULL) {
887 node = node->next;
888 continue;
889 }
890 effects.add(effect);
891 node = node->next;
892 }
893 return NO_ERROR;
894}
895
Kevin Rocard4fb615c2017-06-26 10:28:13 -0700896status_t AudioPolicyEffects::loadAudioEffectXmlConfig() {
897 auto result = effectsConfig::parse();
898 if (result.parsedConfig == nullptr) {
899 return -ENOENT;
900 }
901
902 auto loadProcessingChain = [](auto& processingChain, auto& streams) {
903 for (auto& stream : processingChain) {
904 auto effectDescs = std::make_unique<EffectDescVector>();
905 for (auto& effect : stream.effects) {
906 effectDescs->mEffects.add(
907 new EffectDesc{effect.get().name.c_str(), effect.get().uuid});
908 }
909 streams.add(stream.type, effectDescs.release());
910 }
911 };
912 loadProcessingChain(result.parsedConfig->preprocess, mInputSources);
913 loadProcessingChain(result.parsedConfig->postprocess, mOutputStreams);
914 // Casting from ssize_t to status_t is probably safe, there should not be more than 2^31 errors
915 return result.nbSkippedElement;
916}
917
bryant_liuba2b4392014-06-11 16:49:30 +0800918status_t AudioPolicyEffects::loadAudioEffectConfig(const char *path)
919{
920 cnode *root;
921 char *data;
922
923 data = (char *)load_file(path, NULL);
924 if (data == NULL) {
925 return -ENODEV;
926 }
927 root = config_node("", "");
928 config_load(root, data);
929
930 Vector <EffectDesc *> effects;
931 loadEffects(root, effects);
932 loadInputEffectConfigurations(root, effects);
933 loadStreamEffectConfigurations(root, effects);
934
Eric Laurent182c2f52015-01-15 14:29:19 -0800935 for (size_t i = 0; i < effects.size(); i++) {
936 delete effects[i];
937 }
938
bryant_liuba2b4392014-06-11 16:49:30 +0800939 config_free(root);
940 free(root);
941 free(data);
942
943 return NO_ERROR;
944}
945
946
Mikhail Naganov1b2a7942017-12-08 10:18:09 -0800947} // namespace android