blob: 9a281370a8cab6c3d3d51e4dc3426d4a9d1f0be3 [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>
23#include <cutils/misc.h>
24#include <media/AudioEffect.h>
25#include <system/audio.h>
26#include <hardware/audio_effect.h>
27#include <audio_effects/audio_effects_conf.h>
28#include <utils/Vector.h>
29#include <utils/SortedVector.h>
30#include <cutils/config_utils.h>
31#include "AudioPolicyEffects.h"
32#include "ServiceUtilities.h"
33
34namespace android {
35
36// ----------------------------------------------------------------------------
37// AudioPolicyEffects Implementation
38// ----------------------------------------------------------------------------
39
40AudioPolicyEffects::AudioPolicyEffects()
41{
42 // load automatic audio effect modules
43 if (access(AUDIO_EFFECT_VENDOR_CONFIG_FILE, R_OK) == 0) {
44 loadAudioEffectConfig(AUDIO_EFFECT_VENDOR_CONFIG_FILE);
45 } else if (access(AUDIO_EFFECT_DEFAULT_CONFIG_FILE, R_OK) == 0) {
46 loadAudioEffectConfig(AUDIO_EFFECT_DEFAULT_CONFIG_FILE);
47 }
48}
49
50
51AudioPolicyEffects::~AudioPolicyEffects()
52{
53 size_t i = 0;
54 // release audio input processing resources
55 for (i = 0; i < mInputSources.size(); i++) {
56 delete mInputSources.valueAt(i);
57 }
58 mInputSources.clear();
59
Eric Laurentfb66dd92016-01-28 18:32:03 -080060 for (i = 0; i < mInputSessions.size(); i++) {
61 mInputSessions.valueAt(i)->mEffects.clear();
62 delete mInputSessions.valueAt(i);
bryant_liuba2b4392014-06-11 16:49:30 +080063 }
Eric Laurentfb66dd92016-01-28 18:32:03 -080064 mInputSessions.clear();
bryant_liuba2b4392014-06-11 16:49:30 +080065
66 // release audio output processing resources
67 for (i = 0; i < mOutputStreams.size(); i++) {
68 delete mOutputStreams.valueAt(i);
69 }
70 mOutputStreams.clear();
71
72 for (i = 0; i < mOutputSessions.size(); i++) {
73 mOutputSessions.valueAt(i)->mEffects.clear();
74 delete mOutputSessions.valueAt(i);
75 }
76 mOutputSessions.clear();
77}
78
79
80status_t AudioPolicyEffects::addInputEffects(audio_io_handle_t input,
81 audio_source_t inputSource,
Eric Laurentfb66dd92016-01-28 18:32:03 -080082 audio_session_t audioSession)
bryant_liuba2b4392014-06-11 16:49:30 +080083{
84 status_t status = NO_ERROR;
85
86 // create audio pre processors according to input source
87 audio_source_t aliasSource = (inputSource == AUDIO_SOURCE_HOTWORD) ?
88 AUDIO_SOURCE_VOICE_RECOGNITION : inputSource;
89
Eric Laurent8b1e80b2014-10-07 09:08:47 -070090 Mutex::Autolock _l(mLock);
bryant_liuba2b4392014-06-11 16:49:30 +080091 ssize_t index = mInputSources.indexOfKey(aliasSource);
92 if (index < 0) {
93 ALOGV("addInputEffects(): no processing needs to be attached to this source");
94 return status;
95 }
Eric Laurentfb66dd92016-01-28 18:32:03 -080096 ssize_t idx = mInputSessions.indexOfKey(audioSession);
97 EffectVector *sessionDesc;
bryant_liuba2b4392014-06-11 16:49:30 +080098 if (idx < 0) {
Eric Laurentfb66dd92016-01-28 18:32:03 -080099 sessionDesc = new EffectVector(audioSession);
100 mInputSessions.add(audioSession, sessionDesc);
bryant_liuba2b4392014-06-11 16:49:30 +0800101 } else {
bryant_liu890a5632014-08-20 18:06:13 +0800102 // EffectVector is existing and we just need to increase ref count
Eric Laurentfb66dd92016-01-28 18:32:03 -0800103 sessionDesc = mInputSessions.valueAt(idx);
bryant_liuba2b4392014-06-11 16:49:30 +0800104 }
Eric Laurentfb66dd92016-01-28 18:32:03 -0800105 sessionDesc->mRefCount++;
bryant_liu890a5632014-08-20 18:06:13 +0800106
Eric Laurentfb66dd92016-01-28 18:32:03 -0800107 ALOGV("addInputEffects(): input: %d, refCount: %d", input, sessionDesc->mRefCount);
108 if (sessionDesc->mRefCount == 1) {
Eric Laurent7de5ac12014-10-21 09:07:11 -0700109 Vector <EffectDesc *> effects = mInputSources.valueAt(index)->mEffects;
110 for (size_t i = 0; i < effects.size(); i++) {
111 EffectDesc *effect = effects[i];
Svet Ganovbe71aa22015-04-28 12:06:02 -0700112 sp<AudioEffect> fx = new AudioEffect(NULL, String16("android"), &effect->mUuid, -1, 0,
113 0, audioSession, input);
Eric Laurent7de5ac12014-10-21 09:07:11 -0700114 status_t status = fx->initCheck();
115 if (status != NO_ERROR && status != ALREADY_EXISTS) {
116 ALOGW("addInputEffects(): failed to create Fx %s on source %d",
117 effect->mName, (int32_t)aliasSource);
118 // fx goes out of scope and strong ref on AudioEffect is released
119 continue;
120 }
121 for (size_t j = 0; j < effect->mParams.size(); j++) {
122 fx->setParameter(effect->mParams[j]);
123 }
124 ALOGV("addInputEffects(): added Fx %s on source: %d",
bryant_liuba2b4392014-06-11 16:49:30 +0800125 effect->mName, (int32_t)aliasSource);
Eric Laurentfb66dd92016-01-28 18:32:03 -0800126 sessionDesc->mEffects.add(fx);
bryant_liuba2b4392014-06-11 16:49:30 +0800127 }
Eric Laurentfb66dd92016-01-28 18:32:03 -0800128 sessionDesc->setProcessorEnabled(true);
bryant_liuba2b4392014-06-11 16:49:30 +0800129 }
bryant_liuba2b4392014-06-11 16:49:30 +0800130 return status;
131}
132
133
Eric Laurentfb66dd92016-01-28 18:32:03 -0800134status_t AudioPolicyEffects::releaseInputEffects(audio_io_handle_t input,
135 audio_session_t audioSession)
bryant_liuba2b4392014-06-11 16:49:30 +0800136{
137 status_t status = NO_ERROR;
138
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700139 Mutex::Autolock _l(mLock);
Eric Laurentfb66dd92016-01-28 18:32:03 -0800140 ssize_t index = mInputSessions.indexOfKey(audioSession);
bryant_liuba2b4392014-06-11 16:49:30 +0800141 if (index < 0) {
142 return status;
143 }
Eric Laurentfb66dd92016-01-28 18:32:03 -0800144 EffectVector *sessionDesc = mInputSessions.valueAt(index);
145 sessionDesc->mRefCount--;
146 ALOGV("releaseInputEffects(): input: %d, refCount: %d", input, sessionDesc->mRefCount);
147 if (sessionDesc->mRefCount == 0) {
148 sessionDesc->setProcessorEnabled(false);
149 delete sessionDesc;
150 mInputSessions.removeItemsAt(index);
bryant_liu890a5632014-08-20 18:06:13 +0800151 ALOGV("releaseInputEffects(): all effects released");
152 }
bryant_liuba2b4392014-06-11 16:49:30 +0800153 return status;
154}
155
Eric Laurentfb66dd92016-01-28 18:32:03 -0800156status_t AudioPolicyEffects::queryDefaultInputEffects(audio_session_t audioSession,
bryant_liuba2b4392014-06-11 16:49:30 +0800157 effect_descriptor_t *descriptors,
158 uint32_t *count)
159{
160 status_t status = NO_ERROR;
161
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700162 Mutex::Autolock _l(mLock);
bryant_liuba2b4392014-06-11 16:49:30 +0800163 size_t index;
Eric Laurentfb66dd92016-01-28 18:32:03 -0800164 for (index = 0; index < mInputSessions.size(); index++) {
165 if (mInputSessions.valueAt(index)->mSessionId == audioSession) {
bryant_liuba2b4392014-06-11 16:49:30 +0800166 break;
167 }
168 }
Eric Laurentfb66dd92016-01-28 18:32:03 -0800169 if (index == mInputSessions.size()) {
bryant_liuba2b4392014-06-11 16:49:30 +0800170 *count = 0;
171 return BAD_VALUE;
172 }
Eric Laurentfb66dd92016-01-28 18:32:03 -0800173 Vector< sp<AudioEffect> > effects = mInputSessions.valueAt(index)->mEffects;
bryant_liuba2b4392014-06-11 16:49:30 +0800174
175 for (size_t i = 0; i < effects.size(); i++) {
176 effect_descriptor_t desc = effects[i]->descriptor();
177 if (i < *count) {
178 descriptors[i] = desc;
179 }
180 }
181 if (effects.size() > *count) {
182 status = NO_MEMORY;
183 }
184 *count = effects.size();
185 return status;
186}
187
188
Eric Laurentfb66dd92016-01-28 18:32:03 -0800189status_t AudioPolicyEffects::queryDefaultOutputSessionEffects(audio_session_t audioSession,
bryant_liuba2b4392014-06-11 16:49:30 +0800190 effect_descriptor_t *descriptors,
191 uint32_t *count)
192{
193 status_t status = NO_ERROR;
194
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700195 Mutex::Autolock _l(mLock);
bryant_liuba2b4392014-06-11 16:49:30 +0800196 size_t index;
197 for (index = 0; index < mOutputSessions.size(); index++) {
198 if (mOutputSessions.valueAt(index)->mSessionId == audioSession) {
199 break;
200 }
201 }
202 if (index == mOutputSessions.size()) {
203 *count = 0;
204 return BAD_VALUE;
205 }
206 Vector< sp<AudioEffect> > effects = mOutputSessions.valueAt(index)->mEffects;
207
208 for (size_t i = 0; i < effects.size(); i++) {
209 effect_descriptor_t desc = effects[i]->descriptor();
210 if (i < *count) {
211 descriptors[i] = desc;
212 }
213 }
214 if (effects.size() > *count) {
215 status = NO_MEMORY;
216 }
217 *count = effects.size();
218 return status;
219}
220
221
222status_t AudioPolicyEffects::addOutputSessionEffects(audio_io_handle_t output,
223 audio_stream_type_t stream,
Eric Laurentfb66dd92016-01-28 18:32:03 -0800224 audio_session_t audioSession)
bryant_liuba2b4392014-06-11 16:49:30 +0800225{
226 status_t status = NO_ERROR;
227
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700228 Mutex::Autolock _l(mLock);
bryant_liuba2b4392014-06-11 16:49:30 +0800229 // create audio processors according to stream
Eric Laurent223fd5c2014-11-11 13:43:36 -0800230 // FIXME: should we have specific post processing settings for internal streams?
231 // default to media for now.
232 if (stream >= AUDIO_STREAM_PUBLIC_CNT) {
233 stream = AUDIO_STREAM_MUSIC;
234 }
bryant_liuba2b4392014-06-11 16:49:30 +0800235 ssize_t index = mOutputStreams.indexOfKey(stream);
236 if (index < 0) {
237 ALOGV("addOutputSessionEffects(): no output processing needed for this stream");
238 return NO_ERROR;
239 }
240
241 ssize_t idx = mOutputSessions.indexOfKey(audioSession);
242 EffectVector *procDesc;
243 if (idx < 0) {
244 procDesc = new EffectVector(audioSession);
245 mOutputSessions.add(audioSession, procDesc);
246 } else {
bryant_liu890a5632014-08-20 18:06:13 +0800247 // EffectVector is existing and we just need to increase ref count
bryant_liuba2b4392014-06-11 16:49:30 +0800248 procDesc = mOutputSessions.valueAt(idx);
249 }
bryant_liu890a5632014-08-20 18:06:13 +0800250 procDesc->mRefCount++;
251
Eric Laurent7de5ac12014-10-21 09:07:11 -0700252 ALOGV("addOutputSessionEffects(): session: %d, refCount: %d",
253 audioSession, procDesc->mRefCount);
254 if (procDesc->mRefCount == 1) {
255 Vector <EffectDesc *> effects = mOutputStreams.valueAt(index)->mEffects;
256 for (size_t i = 0; i < effects.size(); i++) {
257 EffectDesc *effect = effects[i];
Svet Ganovbe71aa22015-04-28 12:06:02 -0700258 sp<AudioEffect> fx = new AudioEffect(NULL, String16("android"), &effect->mUuid, 0, 0, 0,
Eric Laurent7de5ac12014-10-21 09:07:11 -0700259 audioSession, output);
260 status_t status = fx->initCheck();
261 if (status != NO_ERROR && status != ALREADY_EXISTS) {
262 ALOGE("addOutputSessionEffects(): failed to create Fx %s on session %d",
263 effect->mName, audioSession);
264 // fx goes out of scope and strong ref on AudioEffect is released
265 continue;
266 }
267 ALOGV("addOutputSessionEffects(): added Fx %s on session: %d for stream: %d",
268 effect->mName, audioSession, (int32_t)stream);
269 procDesc->mEffects.add(fx);
bryant_liuba2b4392014-06-11 16:49:30 +0800270 }
Eric Laurent7de5ac12014-10-21 09:07:11 -0700271
272 procDesc->setProcessorEnabled(true);
bryant_liuba2b4392014-06-11 16:49:30 +0800273 }
bryant_liuba2b4392014-06-11 16:49:30 +0800274 return status;
275}
276
277status_t AudioPolicyEffects::releaseOutputSessionEffects(audio_io_handle_t output,
278 audio_stream_type_t stream,
Eric Laurentfb66dd92016-01-28 18:32:03 -0800279 audio_session_t audioSession)
bryant_liuba2b4392014-06-11 16:49:30 +0800280{
281 status_t status = NO_ERROR;
282 (void) output; // argument not used for now
283 (void) stream; // argument not used for now
284
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700285 Mutex::Autolock _l(mLock);
bryant_liuba2b4392014-06-11 16:49:30 +0800286 ssize_t index = mOutputSessions.indexOfKey(audioSession);
287 if (index < 0) {
288 ALOGV("releaseOutputSessionEffects: no output processing was attached to this stream");
289 return NO_ERROR;
290 }
291
292 EffectVector *procDesc = mOutputSessions.valueAt(index);
bryant_liu890a5632014-08-20 18:06:13 +0800293 procDesc->mRefCount--;
Eric Laurent7de5ac12014-10-21 09:07:11 -0700294 ALOGV("releaseOutputSessionEffects(): session: %d, refCount: %d",
295 audioSession, procDesc->mRefCount);
bryant_liu890a5632014-08-20 18:06:13 +0800296 if (procDesc->mRefCount == 0) {
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700297 procDesc->setProcessorEnabled(false);
bryant_liu890a5632014-08-20 18:06:13 +0800298 procDesc->mEffects.clear();
299 delete procDesc;
300 mOutputSessions.removeItemsAt(index);
301 ALOGV("releaseOutputSessionEffects(): output processing released from session: %d",
302 audioSession);
303 }
bryant_liuba2b4392014-06-11 16:49:30 +0800304 return status;
305}
306
307
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700308void AudioPolicyEffects::EffectVector::setProcessorEnabled(bool enabled)
bryant_liuba2b4392014-06-11 16:49:30 +0800309{
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700310 for (size_t i = 0; i < mEffects.size(); i++) {
311 mEffects.itemAt(i)->setEnabled(enabled);
bryant_liuba2b4392014-06-11 16:49:30 +0800312 }
313}
314
315
316// ----------------------------------------------------------------------------
317// Audio processing configuration
318// ----------------------------------------------------------------------------
319
320/*static*/ const char * const AudioPolicyEffects::kInputSourceNames[AUDIO_SOURCE_CNT -1] = {
321 MIC_SRC_TAG,
322 VOICE_UL_SRC_TAG,
323 VOICE_DL_SRC_TAG,
324 VOICE_CALL_SRC_TAG,
325 CAMCORDER_SRC_TAG,
326 VOICE_REC_SRC_TAG,
rago8a397d52015-12-02 11:27:57 -0800327 VOICE_COMM_SRC_TAG,
328 UNPROCESSED_SRC_TAG
bryant_liuba2b4392014-06-11 16:49:30 +0800329};
330
331// returns the audio_source_t enum corresponding to the input source name or
332// AUDIO_SOURCE_CNT is no match found
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700333/*static*/ audio_source_t AudioPolicyEffects::inputSourceNameToEnum(const char *name)
bryant_liuba2b4392014-06-11 16:49:30 +0800334{
335 int i;
336 for (i = AUDIO_SOURCE_MIC; i < AUDIO_SOURCE_CNT; i++) {
337 if (strcmp(name, kInputSourceNames[i - AUDIO_SOURCE_MIC]) == 0) {
338 ALOGV("inputSourceNameToEnum found source %s %d", name, i);
339 break;
340 }
341 }
342 return (audio_source_t)i;
343}
344
Eric Laurent223fd5c2014-11-11 13:43:36 -0800345const char *AudioPolicyEffects::kStreamNames[AUDIO_STREAM_PUBLIC_CNT+1] = {
bryant_liuba2b4392014-06-11 16:49:30 +0800346 AUDIO_STREAM_DEFAULT_TAG,
347 AUDIO_STREAM_VOICE_CALL_TAG,
348 AUDIO_STREAM_SYSTEM_TAG,
349 AUDIO_STREAM_RING_TAG,
350 AUDIO_STREAM_MUSIC_TAG,
351 AUDIO_STREAM_ALARM_TAG,
352 AUDIO_STREAM_NOTIFICATION_TAG,
353 AUDIO_STREAM_BLUETOOTH_SCO_TAG,
354 AUDIO_STREAM_ENFORCED_AUDIBLE_TAG,
355 AUDIO_STREAM_DTMF_TAG,
356 AUDIO_STREAM_TTS_TAG
357};
358
359// returns the audio_stream_t enum corresponding to the output stream name or
Eric Laurent223fd5c2014-11-11 13:43:36 -0800360// AUDIO_STREAM_PUBLIC_CNT is no match found
bryant_liuba2b4392014-06-11 16:49:30 +0800361audio_stream_type_t AudioPolicyEffects::streamNameToEnum(const char *name)
362{
363 int i;
Eric Laurent223fd5c2014-11-11 13:43:36 -0800364 for (i = AUDIO_STREAM_DEFAULT; i < AUDIO_STREAM_PUBLIC_CNT; i++) {
bryant_liuba2b4392014-06-11 16:49:30 +0800365 if (strcmp(name, kStreamNames[i - AUDIO_STREAM_DEFAULT]) == 0) {
366 ALOGV("streamNameToEnum found stream %s %d", name, i);
367 break;
368 }
369 }
370 return (audio_stream_type_t)i;
371}
372
373// ----------------------------------------------------------------------------
374// Audio Effect Config parser
375// ----------------------------------------------------------------------------
376
Eric Laurent138ed172016-02-10 10:40:44 -0800377size_t AudioPolicyEffects::growParamSize(char **param,
bryant_liuba2b4392014-06-11 16:49:30 +0800378 size_t size,
379 size_t *curSize,
380 size_t *totSize)
381{
382 // *curSize is at least sizeof(effect_param_t) + 2 * sizeof(int)
383 size_t pos = ((*curSize - 1 ) / size + 1) * size;
384
385 if (pos + size > *totSize) {
386 while (pos + size > *totSize) {
387 *totSize += ((*totSize + 7) / 8) * 4;
388 }
Eric Laurent138ed172016-02-10 10:40:44 -0800389 *param = (char *)realloc(*param, *totSize);
390 if (*param == NULL) {
391 ALOGE("%s realloc error for size %zu", __func__, *totSize);
392 return 0;
393 }
bryant_liuba2b4392014-06-11 16:49:30 +0800394 }
395 *curSize = pos + size;
396 return pos;
397}
398
Eric Laurent138ed172016-02-10 10:40:44 -0800399
bryant_liuba2b4392014-06-11 16:49:30 +0800400size_t AudioPolicyEffects::readParamValue(cnode *node,
Eric Laurent138ed172016-02-10 10:40:44 -0800401 char **param,
bryant_liuba2b4392014-06-11 16:49:30 +0800402 size_t *curSize,
403 size_t *totSize)
404{
Eric Laurent138ed172016-02-10 10:40:44 -0800405 size_t len = 0;
406 size_t pos;
407
bryant_liuba2b4392014-06-11 16:49:30 +0800408 if (strncmp(node->name, SHORT_TAG, sizeof(SHORT_TAG) + 1) == 0) {
Eric Laurent138ed172016-02-10 10:40:44 -0800409 pos = growParamSize(param, sizeof(short), curSize, totSize);
410 if (pos == 0) {
411 goto exit;
bryant_liuba2b4392014-06-11 16:49:30 +0800412 }
Eric Laurent138ed172016-02-10 10:40:44 -0800413 *(short *)(*param + pos) = (short)atoi(node->value);
414 ALOGV("readParamValue() reading short %d", *(short *)(*param + pos));
415 len = sizeof(short);
416 } else if (strncmp(node->name, INT_TAG, sizeof(INT_TAG) + 1) == 0) {
417 pos = growParamSize(param, sizeof(int), curSize, totSize);
418 if (pos == 0) {
419 goto exit;
420 }
421 *(int *)(*param + pos) = atoi(node->value);
422 ALOGV("readParamValue() reading int %d", *(int *)(*param + pos));
423 len = sizeof(int);
424 } else if (strncmp(node->name, FLOAT_TAG, sizeof(FLOAT_TAG) + 1) == 0) {
425 pos = growParamSize(param, sizeof(float), curSize, totSize);
426 if (pos == 0) {
427 goto exit;
428 }
429 *(float *)(*param + pos) = (float)atof(node->value);
430 ALOGV("readParamValue() reading float %f",*(float *)(*param + pos));
431 len = sizeof(float);
432 } else if (strncmp(node->name, BOOL_TAG, sizeof(BOOL_TAG) + 1) == 0) {
433 pos = growParamSize(param, sizeof(bool), curSize, totSize);
434 if (pos == 0) {
435 goto exit;
436 }
437 if (strncmp(node->value, "true", strlen("true") + 1) == 0) {
438 *(bool *)(*param + pos) = true;
439 } else {
440 *(bool *)(*param + pos) = false;
441 }
442 ALOGV("readParamValue() reading bool %s",
443 *(bool *)(*param + pos) ? "true" : "false");
444 len = sizeof(bool);
bryant_liuba2b4392014-06-11 16:49:30 +0800445 } else if (strncmp(node->name, STRING_TAG, sizeof(STRING_TAG) + 1) == 0) {
Eric Laurent138ed172016-02-10 10:40:44 -0800446 len = strnlen(node->value, EFFECT_STRING_LEN_MAX);
bryant_liuba2b4392014-06-11 16:49:30 +0800447 if (*curSize + len + 1 > *totSize) {
448 *totSize = *curSize + len + 1;
Eric Laurent138ed172016-02-10 10:40:44 -0800449 *param = (char *)realloc(*param, *totSize);
450 if (*param == NULL) {
451 len = 0;
452 ALOGE("%s realloc error for string len %zu", __func__, *totSize);
453 goto exit;
454 }
bryant_liuba2b4392014-06-11 16:49:30 +0800455 }
Eric Laurent138ed172016-02-10 10:40:44 -0800456 strncpy(*param + *curSize, node->value, len);
bryant_liuba2b4392014-06-11 16:49:30 +0800457 *curSize += len;
Eric Laurent138ed172016-02-10 10:40:44 -0800458 (*param)[*curSize] = '\0';
459 ALOGV("readParamValue() reading string %s", *param + *curSize - len);
460 } else {
461 ALOGW("readParamValue() unknown param type %s", node->name);
bryant_liuba2b4392014-06-11 16:49:30 +0800462 }
Eric Laurent138ed172016-02-10 10:40:44 -0800463exit:
464 return len;
bryant_liuba2b4392014-06-11 16:49:30 +0800465}
466
467effect_param_t *AudioPolicyEffects::loadEffectParameter(cnode *root)
468{
469 cnode *param;
470 cnode *value;
471 size_t curSize = sizeof(effect_param_t);
472 size_t totSize = sizeof(effect_param_t) + 2 * sizeof(int);
473 effect_param_t *fx_param = (effect_param_t *)malloc(totSize);
474
Eric Laurent138ed172016-02-10 10:40:44 -0800475 if (fx_param == NULL) {
476 ALOGE("%s malloc error for effect structure of size %zu",
477 __func__, totSize);
478 return NULL;
479 }
480
bryant_liuba2b4392014-06-11 16:49:30 +0800481 param = config_find(root, PARAM_TAG);
482 value = config_find(root, VALUE_TAG);
483 if (param == NULL && value == NULL) {
484 // try to parse simple parameter form {int int}
485 param = root->first_child;
486 if (param != NULL) {
487 // Note: that a pair of random strings is read as 0 0
488 int *ptr = (int *)fx_param->data;
Eric Laurent138ed172016-02-10 10:40:44 -0800489#if LOG_NDEBUG == 0
bryant_liuba2b4392014-06-11 16:49:30 +0800490 int *ptr2 = (int *)((char *)param + sizeof(effect_param_t));
Eric Laurent138ed172016-02-10 10:40:44 -0800491 ALOGV("loadEffectParameter() ptr %p ptr2 %p", ptr, ptr2);
492#endif
bryant_liuba2b4392014-06-11 16:49:30 +0800493 *ptr++ = atoi(param->name);
494 *ptr = atoi(param->value);
495 fx_param->psize = sizeof(int);
496 fx_param->vsize = sizeof(int);
497 return fx_param;
498 }
499 }
500 if (param == NULL || value == NULL) {
Eric Laurent138ed172016-02-10 10:40:44 -0800501 ALOGW("loadEffectParameter() invalid parameter description %s",
502 root->name);
bryant_liuba2b4392014-06-11 16:49:30 +0800503 goto error;
504 }
505
506 fx_param->psize = 0;
507 param = param->first_child;
508 while (param) {
509 ALOGV("loadEffectParameter() reading param of type %s", param->name);
Eric Laurent138ed172016-02-10 10:40:44 -0800510 size_t size =
511 readParamValue(param, (char **)&fx_param, &curSize, &totSize);
bryant_liuba2b4392014-06-11 16:49:30 +0800512 if (size == 0) {
513 goto error;
514 }
515 fx_param->psize += size;
516 param = param->next;
517 }
518
519 // align start of value field on 32 bit boundary
520 curSize = ((curSize - 1 ) / sizeof(int) + 1) * sizeof(int);
521
522 fx_param->vsize = 0;
523 value = value->first_child;
524 while (value) {
525 ALOGV("loadEffectParameter() reading value of type %s", value->name);
Eric Laurent138ed172016-02-10 10:40:44 -0800526 size_t size =
527 readParamValue(value, (char **)&fx_param, &curSize, &totSize);
bryant_liuba2b4392014-06-11 16:49:30 +0800528 if (size == 0) {
529 goto error;
530 }
531 fx_param->vsize += size;
532 value = value->next;
533 }
534
535 return fx_param;
536
537error:
Eric Laurent138ed172016-02-10 10:40:44 -0800538 free(fx_param);
bryant_liuba2b4392014-06-11 16:49:30 +0800539 return NULL;
540}
541
542void AudioPolicyEffects::loadEffectParameters(cnode *root, Vector <effect_param_t *>& params)
543{
544 cnode *node = root->first_child;
545 while (node) {
546 ALOGV("loadEffectParameters() loading param %s", node->name);
547 effect_param_t *param = loadEffectParameter(node);
Eric Laurent138ed172016-02-10 10:40:44 -0800548 if (param != NULL) {
549 params.add(param);
bryant_liuba2b4392014-06-11 16:49:30 +0800550 }
bryant_liuba2b4392014-06-11 16:49:30 +0800551 node = node->next;
552 }
553}
554
555
556AudioPolicyEffects::EffectDescVector *AudioPolicyEffects::loadEffectConfig(
557 cnode *root,
558 const Vector <EffectDesc *>& effects)
559{
560 cnode *node = root->first_child;
561 if (node == NULL) {
562 ALOGW("loadInputSource() empty element %s", root->name);
563 return NULL;
564 }
565 EffectDescVector *desc = new EffectDescVector();
566 while (node) {
567 size_t i;
Eric Laurent138ed172016-02-10 10:40:44 -0800568
bryant_liuba2b4392014-06-11 16:49:30 +0800569 for (i = 0; i < effects.size(); i++) {
570 if (strncmp(effects[i]->mName, node->name, EFFECT_STRING_LEN_MAX) == 0) {
571 ALOGV("loadEffectConfig() found effect %s in list", node->name);
572 break;
573 }
574 }
575 if (i == effects.size()) {
576 ALOGV("loadEffectConfig() effect %s not in list", node->name);
577 node = node->next;
578 continue;
579 }
580 EffectDesc *effect = new EffectDesc(*effects[i]); // deep copy
581 loadEffectParameters(node, effect->mParams);
582 ALOGV("loadEffectConfig() adding effect %s uuid %08x",
583 effect->mName, effect->mUuid.timeLow);
584 desc->mEffects.add(effect);
585 node = node->next;
586 }
587 if (desc->mEffects.size() == 0) {
588 ALOGW("loadEffectConfig() no valid effects found in config %s", root->name);
589 delete desc;
590 return NULL;
591 }
592 return desc;
593}
594
595status_t AudioPolicyEffects::loadInputEffectConfigurations(cnode *root,
596 const Vector <EffectDesc *>& effects)
597{
598 cnode *node = config_find(root, PREPROCESSING_TAG);
599 if (node == NULL) {
600 return -ENOENT;
601 }
602 node = node->first_child;
603 while (node) {
604 audio_source_t source = inputSourceNameToEnum(node->name);
605 if (source == AUDIO_SOURCE_CNT) {
606 ALOGW("loadInputSources() invalid input source %s", node->name);
607 node = node->next;
608 continue;
609 }
610 ALOGV("loadInputSources() loading input source %s", node->name);
611 EffectDescVector *desc = loadEffectConfig(node, effects);
612 if (desc == NULL) {
613 node = node->next;
614 continue;
615 }
616 mInputSources.add(source, desc);
617 node = node->next;
618 }
619 return NO_ERROR;
620}
621
622status_t AudioPolicyEffects::loadStreamEffectConfigurations(cnode *root,
623 const Vector <EffectDesc *>& effects)
624{
625 cnode *node = config_find(root, OUTPUT_SESSION_PROCESSING_TAG);
626 if (node == NULL) {
627 return -ENOENT;
628 }
629 node = node->first_child;
630 while (node) {
631 audio_stream_type_t stream = streamNameToEnum(node->name);
Eric Laurent223fd5c2014-11-11 13:43:36 -0800632 if (stream == AUDIO_STREAM_PUBLIC_CNT) {
bryant_liuba2b4392014-06-11 16:49:30 +0800633 ALOGW("loadStreamEffectConfigurations() invalid output stream %s", node->name);
634 node = node->next;
635 continue;
636 }
637 ALOGV("loadStreamEffectConfigurations() loading output stream %s", node->name);
638 EffectDescVector *desc = loadEffectConfig(node, effects);
639 if (desc == NULL) {
640 node = node->next;
641 continue;
642 }
643 mOutputStreams.add(stream, desc);
644 node = node->next;
645 }
646 return NO_ERROR;
647}
648
649AudioPolicyEffects::EffectDesc *AudioPolicyEffects::loadEffect(cnode *root)
650{
651 cnode *node = config_find(root, UUID_TAG);
652 if (node == NULL) {
653 return NULL;
654 }
655 effect_uuid_t uuid;
656 if (AudioEffect::stringToGuid(node->value, &uuid) != NO_ERROR) {
657 ALOGW("loadEffect() invalid uuid %s", node->value);
658 return NULL;
659 }
660 return new EffectDesc(root->name, uuid);
661}
662
663status_t AudioPolicyEffects::loadEffects(cnode *root, Vector <EffectDesc *>& effects)
664{
665 cnode *node = config_find(root, EFFECTS_TAG);
666 if (node == NULL) {
667 return -ENOENT;
668 }
669 node = node->first_child;
670 while (node) {
671 ALOGV("loadEffects() loading effect %s", node->name);
672 EffectDesc *effect = loadEffect(node);
673 if (effect == NULL) {
674 node = node->next;
675 continue;
676 }
677 effects.add(effect);
678 node = node->next;
679 }
680 return NO_ERROR;
681}
682
683status_t AudioPolicyEffects::loadAudioEffectConfig(const char *path)
684{
685 cnode *root;
686 char *data;
687
688 data = (char *)load_file(path, NULL);
689 if (data == NULL) {
690 return -ENODEV;
691 }
692 root = config_node("", "");
693 config_load(root, data);
694
695 Vector <EffectDesc *> effects;
696 loadEffects(root, effects);
697 loadInputEffectConfigurations(root, effects);
698 loadStreamEffectConfigurations(root, effects);
699
Eric Laurent182c2f52015-01-15 14:29:19 -0800700 for (size_t i = 0; i < effects.size(); i++) {
701 delete effects[i];
702 }
703
bryant_liuba2b4392014-06-11 16:49:30 +0800704 config_free(root);
705 free(root);
706 free(data);
707
708 return NO_ERROR;
709}
710
711
712}; // namespace android