• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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"
18 //#define LOG_NDEBUG 0
19 
20 #include <stdlib.h>
21 #include <stdio.h>
22 #include <string.h>
23 #include <memory>
24 #include <cutils/misc.h>
25 #include <media/AudioEffect.h>
26 #include <media/EffectsConfig.h>
27 #include <mediautils/ServiceUtilities.h>
28 #include <system/audio.h>
29 #include <system/audio_effects/audio_effects_conf.h>
30 #include <utils/Vector.h>
31 #include <utils/SortedVector.h>
32 #include <cutils/config_utils.h>
33 #include <binder/IPCThreadState.h>
34 #include "AudioPolicyEffects.h"
35 
36 namespace android {
37 
38 // ----------------------------------------------------------------------------
39 // AudioPolicyEffects Implementation
40 // ----------------------------------------------------------------------------
41 
AudioPolicyEffects()42 AudioPolicyEffects::AudioPolicyEffects()
43 {
44     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);
55     }
56 }
57 
58 
~AudioPolicyEffects()59 AudioPolicyEffects::~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 
68     for (i = 0; i < mInputSessions.size(); i++) {
69         mInputSessions.valueAt(i)->mEffects.clear();
70         delete mInputSessions.valueAt(i);
71     }
72     mInputSessions.clear();
73 
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 
addInputEffects(audio_io_handle_t input,audio_source_t inputSource,audio_session_t audioSession)88 status_t AudioPolicyEffects::addInputEffects(audio_io_handle_t input,
89                              audio_source_t inputSource,
90                              audio_session_t audioSession)
91 {
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 
98     Mutex::Autolock _l(mLock);
99     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     }
104     ssize_t idx = mInputSessions.indexOfKey(audioSession);
105     EffectVector *sessionDesc;
106     if (idx < 0) {
107         sessionDesc = new EffectVector(audioSession);
108         mInputSessions.add(audioSession, sessionDesc);
109     } else {
110         // EffectVector is existing and we just need to increase ref count
111         sessionDesc = mInputSessions.valueAt(idx);
112     }
113     sessionDesc->mRefCount++;
114 
115     ALOGV("addInputEffects(): input: %d, refCount: %d", input, sessionDesc->mRefCount);
116     if (sessionDesc->mRefCount == 1) {
117         int64_t token = IPCThreadState::self()->clearCallingIdentity();
118         Vector <EffectDesc *> effects = mInputSources.valueAt(index)->mEffects;
119         for (size_t i = 0; i < effects.size(); i++) {
120             EffectDesc *effect = effects[i];
121             sp<AudioEffect> fx = new AudioEffect(NULL, String16("android"), &effect->mUuid, -1, 0,
122                                                  0, audioSession, input);
123             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",
134                   effect->mName, (int32_t)aliasSource);
135             sessionDesc->mEffects.add(fx);
136         }
137         sessionDesc->setProcessorEnabled(true);
138         IPCThreadState::self()->restoreCallingIdentity(token);
139     }
140     return status;
141 }
142 
143 
releaseInputEffects(audio_io_handle_t input,audio_session_t audioSession)144 status_t AudioPolicyEffects::releaseInputEffects(audio_io_handle_t input,
145                                                  audio_session_t audioSession)
146 {
147     status_t status = NO_ERROR;
148 
149     Mutex::Autolock _l(mLock);
150     ssize_t index = mInputSessions.indexOfKey(audioSession);
151     if (index < 0) {
152         return status;
153     }
154     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);
161         ALOGV("releaseInputEffects(): all effects released");
162     }
163     return status;
164 }
165 
queryDefaultInputEffects(audio_session_t audioSession,effect_descriptor_t * descriptors,uint32_t * count)166 status_t AudioPolicyEffects::queryDefaultInputEffects(audio_session_t audioSession,
167                                                       effect_descriptor_t *descriptors,
168                                                       uint32_t *count)
169 {
170     status_t status = NO_ERROR;
171 
172     Mutex::Autolock _l(mLock);
173     size_t index;
174     for (index = 0; index < mInputSessions.size(); index++) {
175         if (mInputSessions.valueAt(index)->mSessionId == audioSession) {
176             break;
177         }
178     }
179     if (index == mInputSessions.size()) {
180         *count = 0;
181         return BAD_VALUE;
182     }
183     Vector< sp<AudioEffect> > effects = mInputSessions.valueAt(index)->mEffects;
184 
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 
queryDefaultOutputSessionEffects(audio_session_t audioSession,effect_descriptor_t * descriptors,uint32_t * count)199 status_t AudioPolicyEffects::queryDefaultOutputSessionEffects(audio_session_t audioSession,
200                          effect_descriptor_t *descriptors,
201                          uint32_t *count)
202 {
203     status_t status = NO_ERROR;
204 
205     Mutex::Autolock _l(mLock);
206     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 
addOutputSessionEffects(audio_io_handle_t output,audio_stream_type_t stream,audio_session_t audioSession)232 status_t AudioPolicyEffects::addOutputSessionEffects(audio_io_handle_t output,
233                          audio_stream_type_t stream,
234                          audio_session_t audioSession)
235 {
236     status_t status = NO_ERROR;
237 
238     Mutex::Autolock _l(mLock);
239     // create audio processors according to stream
240     // 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     }
245     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 {
257         // EffectVector is existing and we just need to increase ref count
258         procDesc = mOutputSessions.valueAt(idx);
259     }
260     procDesc->mRefCount++;
261 
262     ALOGV("addOutputSessionEffects(): session: %d, refCount: %d",
263           audioSession, procDesc->mRefCount);
264     if (procDesc->mRefCount == 1) {
265         // make sure effects are associated to audio server even if we are executing a binder call
266         int64_t token = IPCThreadState::self()->clearCallingIdentity();
267         Vector <EffectDesc *> effects = mOutputStreams.valueAt(index)->mEffects;
268         for (size_t i = 0; i < effects.size(); i++) {
269             EffectDesc *effect = effects[i];
270             sp<AudioEffect> fx = new AudioEffect(NULL, String16("android"), &effect->mUuid, 0, 0, 0,
271                                                  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);
282         }
283 
284         procDesc->setProcessorEnabled(true);
285         IPCThreadState::self()->restoreCallingIdentity(token);
286     }
287     return status;
288 }
289 
releaseOutputSessionEffects(audio_io_handle_t output,audio_stream_type_t stream,audio_session_t audioSession)290 status_t AudioPolicyEffects::releaseOutputSessionEffects(audio_io_handle_t output,
291                          audio_stream_type_t stream,
292                          audio_session_t audioSession)
293 {
294     status_t status = NO_ERROR;
295     (void) output; // argument not used for now
296     (void) stream; // argument not used for now
297 
298     Mutex::Autolock _l(mLock);
299     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);
306     procDesc->mRefCount--;
307     ALOGV("releaseOutputSessionEffects(): session: %d, refCount: %d",
308           audioSession, procDesc->mRefCount);
309     if (procDesc->mRefCount == 0) {
310         procDesc->setProcessorEnabled(false);
311         procDesc->mEffects.clear();
312         delete procDesc;
313         mOutputSessions.removeItemsAt(index);
314         ALOGV("releaseOutputSessionEffects(): output processing released from session: %d",
315               audioSession);
316     }
317     return status;
318 }
319 
addSourceDefaultEffect(const effect_uuid_t * type,const String16 & opPackageName,const effect_uuid_t * uuid,int32_t priority,audio_source_t source,audio_unique_id_t * id)320 status_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 
332     // HOTWORD, FM_TUNER and ECHO_REFERENCE are special case sources > MAX.
333     if (source < AUDIO_SOURCE_DEFAULT ||
334             (source > AUDIO_SOURCE_MAX &&
335              source != AUDIO_SOURCE_HOTWORD &&
336              source != AUDIO_SOURCE_FM_TUNER &&
337              source != AUDIO_SOURCE_ECHO_REFERENCE)) {
338         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 
addStreamDefaultEffect(const effect_uuid_t * type,const String16 & opPackageName,const effect_uuid_t * uuid,int32_t priority,audio_usage_t usage,audio_unique_id_t * id)389 status_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     }
400     audio_stream_type_t stream = AudioSystem::attributesToStreamType(attributes_initializer(usage));
401 
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 
removeSourceDefaultEffect(audio_unique_id_t id)454 status_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 
removeStreamDefaultEffect(audio_unique_id_t id)485 status_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 }
515 
setProcessorEnabled(bool enabled)516 void AudioPolicyEffects::EffectVector::setProcessorEnabled(bool enabled)
517 {
518     for (size_t i = 0; i < mEffects.size(); i++) {
519         mEffects.itemAt(i)->setEnabled(enabled);
520     }
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,
535     VOICE_COMM_SRC_TAG,
536     UNPROCESSED_SRC_TAG,
537     VOICE_PERFORMANCE_SRC_TAG
538 };
539 
540 // returns the audio_source_t enum corresponding to the input source name or
541 // AUDIO_SOURCE_CNT is no match found
inputSourceNameToEnum(const char * name)542 /*static*/ audio_source_t AudioPolicyEffects::inputSourceNameToEnum(const char *name)
543 {
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 
554 const char *AudioPolicyEffects::kStreamNames[AUDIO_STREAM_PUBLIC_CNT+1] = {
555     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,
565     AUDIO_STREAM_TTS_TAG
566 };
567 
568 // returns the audio_stream_t enum corresponding to the output stream name or
569 // AUDIO_STREAM_PUBLIC_CNT is no match found
streamNameToEnum(const char * name)570 audio_stream_type_t AudioPolicyEffects::streamNameToEnum(const char *name)
571 {
572     int i;
573     for (i = AUDIO_STREAM_DEFAULT; i < AUDIO_STREAM_PUBLIC_CNT; i++) {
574         if (strcmp(name, kStreamNames[i - AUDIO_STREAM_DEFAULT]) == 0) {
575             ALOGV("streamNameToEnum found stream %s %d", name, i);
576             break;
577         }
578     }
579     return (audio_stream_type_t)i;
580 }
581 
582 // ----------------------------------------------------------------------------
583 // Audio Effect Config parser
584 // ----------------------------------------------------------------------------
585 
growParamSize(char ** param,size_t size,size_t * curSize,size_t * totSize)586 size_t AudioPolicyEffects::growParamSize(char **param,
587                                          size_t size,
588                                          size_t *curSize,
589                                          size_t *totSize)
590 {
591     // *curSize is at least sizeof(effect_param_t) + 2 * sizeof(int)
592     size_t pos = ((*curSize - 1 ) / size + 1) * size;
593 
594     if (pos + size > *totSize) {
595         while (pos + size > *totSize) {
596             *totSize += ((*totSize + 7) / 8) * 4;
597         }
598         char *newParam = (char *)realloc(*param, *totSize);
599         if (newParam == NULL) {
600             ALOGE("%s realloc error for size %zu", __func__, *totSize);
601             return 0;
602         }
603         *param = newParam;
604     }
605     *curSize = pos + size;
606     return pos;
607 }
608 
609 
readParamValue(cnode * node,char ** param,size_t * curSize,size_t * totSize)610 size_t AudioPolicyEffects::readParamValue(cnode *node,
611                                           char **param,
612                                           size_t *curSize,
613                                           size_t *totSize)
614 {
615     size_t len = 0;
616     size_t pos;
617 
618     if (strncmp(node->name, SHORT_TAG, sizeof(SHORT_TAG) + 1) == 0) {
619         pos = growParamSize(param, sizeof(short), curSize, totSize);
620         if (pos == 0) {
621             goto exit;
622         }
623         *(short *)(*param + pos) = (short)atoi(node->value);
624         ALOGV("readParamValue() reading short %d", *(short *)(*param + pos));
625         len = sizeof(short);
626     } else if (strncmp(node->name, INT_TAG, sizeof(INT_TAG) + 1) == 0) {
627         pos = growParamSize(param, sizeof(int), curSize, totSize);
628         if (pos == 0) {
629             goto exit;
630         }
631         *(int *)(*param + pos) = atoi(node->value);
632         ALOGV("readParamValue() reading int %d", *(int *)(*param + pos));
633         len = sizeof(int);
634     } else if (strncmp(node->name, FLOAT_TAG, sizeof(FLOAT_TAG) + 1) == 0) {
635         pos = growParamSize(param, sizeof(float), curSize, totSize);
636         if (pos == 0) {
637             goto exit;
638         }
639         *(float *)(*param + pos) = (float)atof(node->value);
640         ALOGV("readParamValue() reading float %f",*(float *)(*param + pos));
641         len = sizeof(float);
642     } else if (strncmp(node->name, BOOL_TAG, sizeof(BOOL_TAG) + 1) == 0) {
643         pos = growParamSize(param, sizeof(bool), curSize, totSize);
644         if (pos == 0) {
645             goto exit;
646         }
647         if (strncmp(node->value, "true", strlen("true") + 1) == 0) {
648             *(bool *)(*param + pos) = true;
649         } else {
650             *(bool *)(*param + pos) = false;
651         }
652         ALOGV("readParamValue() reading bool %s",
653               *(bool *)(*param + pos) ? "true" : "false");
654         len = sizeof(bool);
655     } else if (strncmp(node->name, STRING_TAG, sizeof(STRING_TAG) + 1) == 0) {
656         len = strnlen(node->value, EFFECT_STRING_LEN_MAX);
657         if (*curSize + len + 1 > *totSize) {
658             *totSize = *curSize + len + 1;
659             char *newParam = (char *)realloc(*param, *totSize);
660             if (newParam == NULL) {
661                 len = 0;
662                 ALOGE("%s realloc error for string len %zu", __func__, *totSize);
663                 goto exit;
664             }
665             *param = newParam;
666         }
667         strncpy(*param + *curSize, node->value, len);
668         *curSize += len;
669         (*param)[*curSize] = '\0';
670         ALOGV("readParamValue() reading string %s", *param + *curSize - len);
671     } else {
672         ALOGW("readParamValue() unknown param type %s", node->name);
673     }
674 exit:
675     return len;
676 }
677 
loadEffectParameter(cnode * root)678 effect_param_t *AudioPolicyEffects::loadEffectParameter(cnode *root)
679 {
680     cnode *param;
681     cnode *value;
682     size_t curSize = sizeof(effect_param_t);
683     size_t totSize = sizeof(effect_param_t) + 2 * sizeof(int);
684     effect_param_t *fx_param = (effect_param_t *)malloc(totSize);
685 
686     if (fx_param == NULL) {
687         ALOGE("%s malloc error for effect structure of size %zu",
688               __func__, totSize);
689         return NULL;
690     }
691 
692     param = config_find(root, PARAM_TAG);
693     value = config_find(root, VALUE_TAG);
694     if (param == NULL && value == NULL) {
695         // try to parse simple parameter form {int int}
696         param = root->first_child;
697         if (param != NULL) {
698             // Note: that a pair of random strings is read as 0 0
699             int *ptr = (int *)fx_param->data;
700 #if LOG_NDEBUG == 0
701             int *ptr2 = (int *)((char *)param + sizeof(effect_param_t));
702             ALOGV("loadEffectParameter() ptr %p ptr2 %p", ptr, ptr2);
703 #endif
704             *ptr++ = atoi(param->name);
705             *ptr = atoi(param->value);
706             fx_param->psize = sizeof(int);
707             fx_param->vsize = sizeof(int);
708             return fx_param;
709         }
710     }
711     if (param == NULL || value == NULL) {
712         ALOGW("loadEffectParameter() invalid parameter description %s",
713               root->name);
714         goto error;
715     }
716 
717     fx_param->psize = 0;
718     param = param->first_child;
719     while (param) {
720         ALOGV("loadEffectParameter() reading param of type %s", param->name);
721         size_t size =
722                 readParamValue(param, (char **)&fx_param, &curSize, &totSize);
723         if (size == 0) {
724             goto error;
725         }
726         fx_param->psize += size;
727         param = param->next;
728     }
729 
730     // align start of value field on 32 bit boundary
731     curSize = ((curSize - 1 ) / sizeof(int) + 1) * sizeof(int);
732 
733     fx_param->vsize = 0;
734     value = value->first_child;
735     while (value) {
736         ALOGV("loadEffectParameter() reading value of type %s", value->name);
737         size_t size =
738                 readParamValue(value, (char **)&fx_param, &curSize, &totSize);
739         if (size == 0) {
740             goto error;
741         }
742         fx_param->vsize += size;
743         value = value->next;
744     }
745 
746     return fx_param;
747 
748 error:
749     free(fx_param);
750     return NULL;
751 }
752 
loadEffectParameters(cnode * root,Vector<effect_param_t * > & params)753 void AudioPolicyEffects::loadEffectParameters(cnode *root, Vector <effect_param_t *>& params)
754 {
755     cnode *node = root->first_child;
756     while (node) {
757         ALOGV("loadEffectParameters() loading param %s", node->name);
758         effect_param_t *param = loadEffectParameter(node);
759         if (param != NULL) {
760             params.add(param);
761         }
762         node = node->next;
763     }
764 }
765 
766 
loadEffectConfig(cnode * root,const Vector<EffectDesc * > & effects)767 AudioPolicyEffects::EffectDescVector *AudioPolicyEffects::loadEffectConfig(
768                                                             cnode *root,
769                                                             const Vector <EffectDesc *>& effects)
770 {
771     cnode *node = root->first_child;
772     if (node == NULL) {
773         ALOGW("loadInputSource() empty element %s", root->name);
774         return NULL;
775     }
776     EffectDescVector *desc = new EffectDescVector();
777     while (node) {
778         size_t i;
779 
780         for (i = 0; i < effects.size(); i++) {
781             if (strncmp(effects[i]->mName, node->name, EFFECT_STRING_LEN_MAX) == 0) {
782                 ALOGV("loadEffectConfig() found effect %s in list", node->name);
783                 break;
784             }
785         }
786         if (i == effects.size()) {
787             ALOGV("loadEffectConfig() effect %s not in list", node->name);
788             node = node->next;
789             continue;
790         }
791         EffectDesc *effect = new EffectDesc(*effects[i]);   // deep copy
792         loadEffectParameters(node, effect->mParams);
793         ALOGV("loadEffectConfig() adding effect %s uuid %08x",
794               effect->mName, effect->mUuid.timeLow);
795         desc->mEffects.add(effect);
796         node = node->next;
797     }
798     if (desc->mEffects.size() == 0) {
799         ALOGW("loadEffectConfig() no valid effects found in config %s", root->name);
800         delete desc;
801         return NULL;
802     }
803     return desc;
804 }
805 
loadInputEffectConfigurations(cnode * root,const Vector<EffectDesc * > & effects)806 status_t AudioPolicyEffects::loadInputEffectConfigurations(cnode *root,
807                                                            const Vector <EffectDesc *>& effects)
808 {
809     cnode *node = config_find(root, PREPROCESSING_TAG);
810     if (node == NULL) {
811         return -ENOENT;
812     }
813     node = node->first_child;
814     while (node) {
815         audio_source_t source = inputSourceNameToEnum(node->name);
816         if (source == AUDIO_SOURCE_CNT) {
817             ALOGW("loadInputSources() invalid input source %s", node->name);
818             node = node->next;
819             continue;
820         }
821         ALOGV("loadInputSources() loading input source %s", node->name);
822         EffectDescVector *desc = loadEffectConfig(node, effects);
823         if (desc == NULL) {
824             node = node->next;
825             continue;
826         }
827         mInputSources.add(source, desc);
828         node = node->next;
829     }
830     return NO_ERROR;
831 }
832 
loadStreamEffectConfigurations(cnode * root,const Vector<EffectDesc * > & effects)833 status_t AudioPolicyEffects::loadStreamEffectConfigurations(cnode *root,
834                                                             const Vector <EffectDesc *>& effects)
835 {
836     cnode *node = config_find(root, OUTPUT_SESSION_PROCESSING_TAG);
837     if (node == NULL) {
838         return -ENOENT;
839     }
840     node = node->first_child;
841     while (node) {
842         audio_stream_type_t stream = streamNameToEnum(node->name);
843         if (stream == AUDIO_STREAM_PUBLIC_CNT) {
844             ALOGW("loadStreamEffectConfigurations() invalid output stream %s", node->name);
845             node = node->next;
846             continue;
847         }
848         ALOGV("loadStreamEffectConfigurations() loading output stream %s", node->name);
849         EffectDescVector *desc = loadEffectConfig(node, effects);
850         if (desc == NULL) {
851             node = node->next;
852             continue;
853         }
854         mOutputStreams.add(stream, desc);
855         node = node->next;
856     }
857     return NO_ERROR;
858 }
859 
loadEffect(cnode * root)860 AudioPolicyEffects::EffectDesc *AudioPolicyEffects::loadEffect(cnode *root)
861 {
862     cnode *node = config_find(root, UUID_TAG);
863     if (node == NULL) {
864         return NULL;
865     }
866     effect_uuid_t uuid;
867     if (AudioEffect::stringToGuid(node->value, &uuid) != NO_ERROR) {
868         ALOGW("loadEffect() invalid uuid %s", node->value);
869         return NULL;
870     }
871     return new EffectDesc(root->name, uuid);
872 }
873 
loadEffects(cnode * root,Vector<EffectDesc * > & effects)874 status_t AudioPolicyEffects::loadEffects(cnode *root, Vector <EffectDesc *>& effects)
875 {
876     cnode *node = config_find(root, EFFECTS_TAG);
877     if (node == NULL) {
878         return -ENOENT;
879     }
880     node = node->first_child;
881     while (node) {
882         ALOGV("loadEffects() loading effect %s", node->name);
883         EffectDesc *effect = loadEffect(node);
884         if (effect == NULL) {
885             node = node->next;
886             continue;
887         }
888         effects.add(effect);
889         node = node->next;
890     }
891     return NO_ERROR;
892 }
893 
loadAudioEffectXmlConfig()894 status_t AudioPolicyEffects::loadAudioEffectXmlConfig() {
895     auto result = effectsConfig::parse();
896     if (result.parsedConfig == nullptr) {
897         return -ENOENT;
898     }
899 
900     auto loadProcessingChain = [](auto& processingChain, auto& streams) {
901         for (auto& stream : processingChain) {
902             auto effectDescs = std::make_unique<EffectDescVector>();
903             for (auto& effect : stream.effects) {
904                 effectDescs->mEffects.add(
905                         new EffectDesc{effect.get().name.c_str(), effect.get().uuid});
906             }
907             streams.add(stream.type, effectDescs.release());
908         }
909     };
910     loadProcessingChain(result.parsedConfig->preprocess, mInputSources);
911     loadProcessingChain(result.parsedConfig->postprocess, mOutputStreams);
912     // Casting from ssize_t to status_t is probably safe, there should not be more than 2^31 errors
913     return result.nbSkippedElement;
914 }
915 
loadAudioEffectConfig(const char * path)916 status_t AudioPolicyEffects::loadAudioEffectConfig(const char *path)
917 {
918     cnode *root;
919     char *data;
920 
921     data = (char *)load_file(path, NULL);
922     if (data == NULL) {
923         return -ENODEV;
924     }
925     root = config_node("", "");
926     config_load(root, data);
927 
928     Vector <EffectDesc *> effects;
929     loadEffects(root, effects);
930     loadInputEffectConfigurations(root, effects);
931     loadStreamEffectConfigurations(root, effects);
932 
933     for (size_t i = 0; i < effects.size(); i++) {
934         delete effects[i];
935     }
936 
937     config_free(root);
938     free(root);
939     free(data);
940 
941     return NO_ERROR;
942 }
943 
944 
945 } // namespace android
946