• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 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 "EffectsFactory"
18 //#define LOG_NDEBUG 0
19 
20 #include "EffectsFactory.h"
21 #include <string.h>
22 #include <stdlib.h>
23 #include <dlfcn.h>
24 
25 #include <cutils/misc.h>
26 #include <cutils/config_utils.h>
27 #include <audio_effects/audio_effects_conf.h>
28 
29 static list_elem_t *gEffectList; // list of effect_entry_t: all currently created effects
30 static list_elem_t *gLibraryList; // list of lib_entry_t: all currently loaded libraries
31 // list of effect_descriptor and list of sub effects : all currently loaded
32 // It does not contain effects without sub effects.
33 static list_sub_elem_t *gSubEffectList;
34 static pthread_mutex_t gLibLock = PTHREAD_MUTEX_INITIALIZER; // controls access to gLibraryList
35 static uint32_t gNumEffects;         // total number number of effects
36 static list_elem_t *gCurLib;    // current library in enumeration process
37 static list_elem_t *gCurEffect; // current effect in enumeration process
38 static uint32_t gCurEffectIdx;       // current effect index in enumeration process
39 static lib_entry_t *gCachedLibrary;  // last library accessed by getLibrary()
40 
41 static int gInitDone; // true is global initialization has been preformed
42 static int gCanQueryEffect; // indicates that call to EffectQueryEffect() is valid, i.e. that the list of effects
43                           // was not modified since last call to EffectQueryNumberEffects()
44 
45 
46 /////////////////////////////////////////////////
47 //      Local functions prototypes
48 /////////////////////////////////////////////////
49 
50 static int init();
51 static int loadEffectConfigFile(const char *path);
52 static int loadLibraries(cnode *root);
53 static int loadLibrary(cnode *root, const char *name);
54 static int loadEffects(cnode *root);
55 static int loadEffect(cnode *node);
56 // To get and add the effect pointed by the passed node to the gSubEffectList
57 static int addSubEffect(cnode *root);
58 static lib_entry_t *getLibrary(const char *path);
59 static void resetEffectEnumeration();
60 static uint32_t updateNumEffects();
61 static int findEffect(const effect_uuid_t *type,
62                const effect_uuid_t *uuid,
63                lib_entry_t **lib,
64                effect_descriptor_t **desc);
65 // To search a subeffect in the gSubEffectList
66 int findSubEffect(const effect_uuid_t *uuid,
67                lib_entry_t **lib,
68                effect_descriptor_t **desc);
69 static void dumpEffectDescriptor(effect_descriptor_t *desc, char *str, size_t len);
70 static int stringToUuid(const char *str, effect_uuid_t *uuid);
71 static int uuidToString(const effect_uuid_t *uuid, char *str, size_t maxLen);
72 
73 /////////////////////////////////////////////////
74 //      Effect Control Interface functions
75 /////////////////////////////////////////////////
76 
Effect_Process(effect_handle_t self,audio_buffer_t * inBuffer,audio_buffer_t * outBuffer)77 int Effect_Process(effect_handle_t self, audio_buffer_t *inBuffer, audio_buffer_t *outBuffer)
78 {
79     int ret = init();
80     if (ret < 0) {
81         return ret;
82     }
83     effect_entry_t *fx = (effect_entry_t *)self;
84     pthread_mutex_lock(&gLibLock);
85     if (fx->lib == NULL) {
86         pthread_mutex_unlock(&gLibLock);
87         return -EPIPE;
88     }
89     pthread_mutex_lock(&fx->lib->lock);
90     pthread_mutex_unlock(&gLibLock);
91 
92     ret = (*fx->subItfe)->process(fx->subItfe, inBuffer, outBuffer);
93     pthread_mutex_unlock(&fx->lib->lock);
94     return ret;
95 }
96 
Effect_Command(effect_handle_t self,uint32_t cmdCode,uint32_t cmdSize,void * pCmdData,uint32_t * replySize,void * pReplyData)97 int Effect_Command(effect_handle_t self,
98                    uint32_t cmdCode,
99                    uint32_t cmdSize,
100                    void *pCmdData,
101                    uint32_t *replySize,
102                    void *pReplyData)
103 {
104     int ret = init();
105     if (ret < 0) {
106         return ret;
107     }
108     effect_entry_t *fx = (effect_entry_t *)self;
109     pthread_mutex_lock(&gLibLock);
110     if (fx->lib == NULL) {
111         pthread_mutex_unlock(&gLibLock);
112         return -EPIPE;
113     }
114     pthread_mutex_lock(&fx->lib->lock);
115     pthread_mutex_unlock(&gLibLock);
116 
117     ret = (*fx->subItfe)->command(fx->subItfe, cmdCode, cmdSize, pCmdData, replySize, pReplyData);
118     pthread_mutex_unlock(&fx->lib->lock);
119     return ret;
120 }
121 
Effect_GetDescriptor(effect_handle_t self,effect_descriptor_t * desc)122 int Effect_GetDescriptor(effect_handle_t self,
123                          effect_descriptor_t *desc)
124 {
125     int ret = init();
126     if (ret < 0) {
127         return ret;
128     }
129     effect_entry_t *fx = (effect_entry_t *)self;
130     pthread_mutex_lock(&gLibLock);
131     if (fx->lib == NULL) {
132         pthread_mutex_unlock(&gLibLock);
133         return -EPIPE;
134     }
135     pthread_mutex_lock(&fx->lib->lock);
136     pthread_mutex_unlock(&gLibLock);
137 
138     ret = (*fx->subItfe)->get_descriptor(fx->subItfe, desc);
139     pthread_mutex_unlock(&fx->lib->lock);
140     return ret;
141 }
142 
Effect_ProcessReverse(effect_handle_t self,audio_buffer_t * inBuffer,audio_buffer_t * outBuffer)143 int Effect_ProcessReverse(effect_handle_t self, audio_buffer_t *inBuffer, audio_buffer_t *outBuffer)
144 {
145     int ret = init();
146     if (ret < 0) {
147         return ret;
148     }
149     effect_entry_t *fx = (effect_entry_t *)self;
150     pthread_mutex_lock(&gLibLock);
151     if (fx->lib == NULL) {
152         pthread_mutex_unlock(&gLibLock);
153         return -EPIPE;
154     }
155     pthread_mutex_lock(&fx->lib->lock);
156     pthread_mutex_unlock(&gLibLock);
157 
158     if ((*fx->subItfe)->process_reverse != NULL) {
159         ret = (*fx->subItfe)->process_reverse(fx->subItfe, inBuffer, outBuffer);
160     } else {
161         ret = -ENOSYS;
162     }
163     pthread_mutex_unlock(&fx->lib->lock);
164     return ret;
165 }
166 
167 
168 const struct effect_interface_s gInterface = {
169         Effect_Process,
170         Effect_Command,
171         Effect_GetDescriptor,
172         NULL
173 };
174 
175 const struct effect_interface_s gInterfaceWithReverse = {
176         Effect_Process,
177         Effect_Command,
178         Effect_GetDescriptor,
179         Effect_ProcessReverse
180 };
181 
182 /////////////////////////////////////////////////
183 //      Effect Factory Interface functions
184 /////////////////////////////////////////////////
185 
EffectQueryNumberEffects(uint32_t * pNumEffects)186 int EffectQueryNumberEffects(uint32_t *pNumEffects)
187 {
188     int ret = init();
189     if (ret < 0) {
190         return ret;
191     }
192     if (pNumEffects == NULL) {
193         return -EINVAL;
194     }
195 
196     pthread_mutex_lock(&gLibLock);
197     *pNumEffects = gNumEffects;
198     gCanQueryEffect = 1;
199     pthread_mutex_unlock(&gLibLock);
200     ALOGV("EffectQueryNumberEffects(): %d", *pNumEffects);
201     return ret;
202 }
203 
EffectQueryEffect(uint32_t index,effect_descriptor_t * pDescriptor)204 int EffectQueryEffect(uint32_t index, effect_descriptor_t *pDescriptor)
205 {
206     int ret = init();
207     if (ret < 0) {
208         return ret;
209     }
210     if (pDescriptor == NULL ||
211         index >= gNumEffects) {
212         return -EINVAL;
213     }
214     if (gCanQueryEffect == 0) {
215         return -ENOSYS;
216     }
217 
218     pthread_mutex_lock(&gLibLock);
219     ret = -ENOENT;
220     if (index < gCurEffectIdx) {
221         resetEffectEnumeration();
222     }
223     while (gCurLib) {
224         if (gCurEffect) {
225             if (index == gCurEffectIdx) {
226                 *pDescriptor = *(effect_descriptor_t *)gCurEffect->object;
227                 ret = 0;
228                 break;
229             } else {
230                 gCurEffect = gCurEffect->next;
231                 gCurEffectIdx++;
232             }
233         } else {
234             gCurLib = gCurLib->next;
235             gCurEffect = ((lib_entry_t *)gCurLib->object)->effects;
236         }
237     }
238 
239 #if (LOG_NDEBUG == 0)
240     char str[256];
241     dumpEffectDescriptor(pDescriptor, str, 256);
242     ALOGV("EffectQueryEffect() desc:%s", str);
243 #endif
244     pthread_mutex_unlock(&gLibLock);
245     return ret;
246 }
247 
EffectGetDescriptor(const effect_uuid_t * uuid,effect_descriptor_t * pDescriptor)248 int EffectGetDescriptor(const effect_uuid_t *uuid, effect_descriptor_t *pDescriptor)
249 {
250     lib_entry_t *l = NULL;
251     effect_descriptor_t *d = NULL;
252 
253     int ret = init();
254     if (ret < 0) {
255         return ret;
256     }
257     if (pDescriptor == NULL || uuid == NULL) {
258         return -EINVAL;
259     }
260     pthread_mutex_lock(&gLibLock);
261     ret = findEffect(NULL, uuid, &l, &d);
262     if (ret == 0) {
263         *pDescriptor = *d;
264     }
265     pthread_mutex_unlock(&gLibLock);
266     return ret;
267 }
268 
EffectCreate(const effect_uuid_t * uuid,int32_t sessionId,int32_t ioId,effect_handle_t * pHandle)269 int EffectCreate(const effect_uuid_t *uuid, int32_t sessionId, int32_t ioId, effect_handle_t *pHandle)
270 {
271     list_elem_t *e = gLibraryList;
272     lib_entry_t *l = NULL;
273     effect_descriptor_t *d = NULL;
274     effect_handle_t itfe;
275     effect_entry_t *fx;
276     int found = 0;
277     int ret;
278 
279     if (uuid == NULL || pHandle == NULL) {
280         return -EINVAL;
281     }
282 
283     ALOGV("EffectCreate() UUID: %08X-%04X-%04X-%04X-%02X%02X%02X%02X%02X%02X\n",
284             uuid->timeLow, uuid->timeMid, uuid->timeHiAndVersion,
285             uuid->clockSeq, uuid->node[0], uuid->node[1],uuid->node[2],
286             uuid->node[3],uuid->node[4],uuid->node[5]);
287 
288     ret = init();
289 
290     if (ret < 0) {
291         ALOGW("EffectCreate() init error: %d", ret);
292         return ret;
293     }
294 
295     pthread_mutex_lock(&gLibLock);
296 
297     ret = findEffect(NULL, uuid, &l, &d);
298     if (ret < 0){
299         // Sub effects are not associated with the library->effects,
300         // so, findEffect will fail. Search for the effect in gSubEffectList.
301         ret = findSubEffect(uuid, &l, &d);
302         if (ret < 0 ) {
303             goto exit;
304         }
305     }
306 
307     // create effect in library
308     ret = l->desc->create_effect(uuid, sessionId, ioId, &itfe);
309     if (ret != 0) {
310         ALOGW("EffectCreate() library %s: could not create fx %s, error %d", l->name, d->name, ret);
311         goto exit;
312     }
313 
314     // add entry to effect list
315     fx = (effect_entry_t *)malloc(sizeof(effect_entry_t));
316     fx->subItfe = itfe;
317     if ((*itfe)->process_reverse != NULL) {
318         fx->itfe = (struct effect_interface_s *)&gInterfaceWithReverse;
319         ALOGV("EffectCreate() gInterfaceWithReverse");
320     }   else {
321         fx->itfe = (struct effect_interface_s *)&gInterface;
322         ALOGV("EffectCreate() gInterface");
323     }
324     fx->lib = l;
325 
326     e = (list_elem_t *)malloc(sizeof(list_elem_t));
327     e->object = fx;
328     e->next = gEffectList;
329     gEffectList = e;
330 
331     *pHandle = (effect_handle_t)fx;
332 
333     ALOGV("EffectCreate() created entry %p with sub itfe %p in library %s", *pHandle, itfe, l->name);
334 
335 exit:
336     pthread_mutex_unlock(&gLibLock);
337     return ret;
338 }
339 
EffectRelease(effect_handle_t handle)340 int EffectRelease(effect_handle_t handle)
341 {
342     effect_entry_t *fx;
343     list_elem_t *e1;
344     list_elem_t *e2;
345 
346     int ret = init();
347     if (ret < 0) {
348         return ret;
349     }
350 
351     // remove effect from effect list
352     pthread_mutex_lock(&gLibLock);
353     e1 = gEffectList;
354     e2 = NULL;
355     while (e1) {
356         if (e1->object == handle) {
357             if (e2) {
358                 e2->next = e1->next;
359             } else {
360                 gEffectList = e1->next;
361             }
362             fx = (effect_entry_t *)e1->object;
363             free(e1);
364             break;
365         }
366         e2 = e1;
367         e1 = e1->next;
368     }
369     if (e1 == NULL) {
370         ret = -ENOENT;
371         goto exit;
372     }
373 
374     // release effect in library
375     if (fx->lib == NULL) {
376         ALOGW("EffectRelease() fx %p library already unloaded", handle);
377     } else {
378         pthread_mutex_lock(&fx->lib->lock);
379         fx->lib->desc->release_effect(fx->subItfe);
380         pthread_mutex_unlock(&fx->lib->lock);
381     }
382     free(fx);
383 
384 exit:
385     pthread_mutex_unlock(&gLibLock);
386     return ret;
387 }
388 
EffectIsNullUuid(const effect_uuid_t * uuid)389 int EffectIsNullUuid(const effect_uuid_t *uuid)
390 {
391     if (memcmp(uuid, EFFECT_UUID_NULL, sizeof(effect_uuid_t))) {
392         return 0;
393     }
394     return 1;
395 }
396 
397 // Function to get the sub effect descriptors of the effect whose uuid
398 // is pointed by the first argument. It searches the gSubEffectList for the
399 // matching uuid and then copies the corresponding sub effect descriptors
400 // to the inout param
EffectGetSubEffects(const effect_uuid_t * uuid,sub_effect_entry_t ** pSube,size_t size)401 int EffectGetSubEffects(const effect_uuid_t *uuid, sub_effect_entry_t **pSube,
402                         size_t size)
403 {
404    ALOGV("EffectGetSubEffects() UUID: %08X-%04X-%04X-%04X-%02X%02X%02X%02X%02X"
405           "%02X\n",uuid->timeLow, uuid->timeMid, uuid->timeHiAndVersion,
406           uuid->clockSeq, uuid->node[0], uuid->node[1],uuid->node[2],
407           uuid->node[3],uuid->node[4],uuid->node[5]);
408 
409    // Check if the size of the desc buffer is large enough for 2 subeffects
410    if ((uuid == NULL) || (pSube == NULL) || (size < 2)) {
411        ALOGW("NULL pointer or insufficient memory. Cannot query subeffects");
412        return -EINVAL;
413    }
414    int ret = init();
415    if (ret < 0)
416       return ret;
417    list_sub_elem_t *e = gSubEffectList;
418    sub_effect_entry_t *subeffect;
419    effect_descriptor_t *d;
420    int count = 0;
421    while (e != NULL) {
422        d = (effect_descriptor_t*)e->object;
423        if (memcmp(uuid, &d->uuid, sizeof(effect_uuid_t)) == 0) {
424            ALOGV("EffectGetSubEffects: effect found in the list");
425            list_elem_t *subefx = e->sub_elem;
426            while (subefx != NULL) {
427                subeffect = (sub_effect_entry_t*)subefx->object;
428                pSube[count++] = subeffect;
429                subefx = subefx->next;
430            }
431            ALOGV("EffectGetSubEffects end - copied the sub effect structures");
432            return count;
433        }
434        e = e->next;
435    }
436    return -ENOENT;
437 }
438 /////////////////////////////////////////////////
439 //      Local functions
440 /////////////////////////////////////////////////
441 
init()442 int init() {
443     int hdl;
444 
445     if (gInitDone) {
446         return 0;
447     }
448 
449     pthread_mutex_init(&gLibLock, NULL);
450 
451     if (access(AUDIO_EFFECT_VENDOR_CONFIG_FILE, R_OK) == 0) {
452         loadEffectConfigFile(AUDIO_EFFECT_VENDOR_CONFIG_FILE);
453     } else if (access(AUDIO_EFFECT_DEFAULT_CONFIG_FILE, R_OK) == 0) {
454         loadEffectConfigFile(AUDIO_EFFECT_DEFAULT_CONFIG_FILE);
455     }
456 
457     updateNumEffects();
458     gInitDone = 1;
459     ALOGV("init() done");
460     return 0;
461 }
462 
loadEffectConfigFile(const char * path)463 int loadEffectConfigFile(const char *path)
464 {
465     cnode *root;
466     char *data;
467 
468     data = load_file(path, NULL);
469     if (data == NULL) {
470         return -ENODEV;
471     }
472     root = config_node("", "");
473     config_load(root, data);
474     loadLibraries(root);
475     loadEffects(root);
476     config_free(root);
477     free(root);
478     free(data);
479 
480     return 0;
481 }
482 
loadLibraries(cnode * root)483 int loadLibraries(cnode *root)
484 {
485     cnode *node;
486 
487     node = config_find(root, LIBRARIES_TAG);
488     if (node == NULL) {
489         return -ENOENT;
490     }
491     node = node->first_child;
492     while (node) {
493         loadLibrary(node, node->name);
494         node = node->next;
495     }
496     return 0;
497 }
498 
loadLibrary(cnode * root,const char * name)499 int loadLibrary(cnode *root, const char *name)
500 {
501     cnode *node;
502     void *hdl;
503     audio_effect_library_t *desc;
504     list_elem_t *e;
505     lib_entry_t *l;
506 
507     node = config_find(root, PATH_TAG);
508     if (node == NULL) {
509         return -EINVAL;
510     }
511 
512     hdl = dlopen(node->value, RTLD_NOW);
513     if (hdl == NULL) {
514         ALOGW("loadLibrary() failed to open %s", node->value);
515         goto error;
516     }
517 
518     desc = (audio_effect_library_t *)dlsym(hdl, AUDIO_EFFECT_LIBRARY_INFO_SYM_AS_STR);
519     if (desc == NULL) {
520         ALOGW("loadLibrary() could not find symbol %s", AUDIO_EFFECT_LIBRARY_INFO_SYM_AS_STR);
521         goto error;
522     }
523 
524     if (AUDIO_EFFECT_LIBRARY_TAG != desc->tag) {
525         ALOGW("getLibrary() bad tag %08x in lib info struct", desc->tag);
526         goto error;
527     }
528 
529     if (EFFECT_API_VERSION_MAJOR(desc->version) !=
530             EFFECT_API_VERSION_MAJOR(EFFECT_LIBRARY_API_VERSION)) {
531         ALOGW("loadLibrary() bad lib version %08x", desc->version);
532         goto error;
533     }
534 
535     // add entry for library in gLibraryList
536     l = malloc(sizeof(lib_entry_t));
537     l->name = strndup(name, PATH_MAX);
538     l->path = strndup(node->value, PATH_MAX);
539     l->handle = hdl;
540     l->desc = desc;
541     l->effects = NULL;
542     pthread_mutex_init(&l->lock, NULL);
543 
544     e = malloc(sizeof(list_elem_t));
545     e->object = l;
546     pthread_mutex_lock(&gLibLock);
547     e->next = gLibraryList;
548     gLibraryList = e;
549     pthread_mutex_unlock(&gLibLock);
550     ALOGV("getLibrary() linked library %p for path %s", l, node->value);
551 
552     return 0;
553 
554 error:
555     if (hdl != NULL) {
556         dlclose(hdl);
557     }
558     return -EINVAL;
559 }
560 
561 // This will find the library and UUID tags of the sub effect pointed by the
562 // node, gets the effect descriptor and lib_entry_t and adds the subeffect -
563 // sub_entry_t to the gSubEffectList
addSubEffect(cnode * root)564 int addSubEffect(cnode *root)
565 {
566     ALOGV("addSubEffect");
567     cnode *node;
568     effect_uuid_t uuid;
569     effect_descriptor_t *d;
570     lib_entry_t *l;
571     list_elem_t *e;
572     node = config_find(root, LIBRARY_TAG);
573     if (node == NULL) {
574         return -EINVAL;
575     }
576     l = getLibrary(node->value);
577     if (l == NULL) {
578         ALOGW("addSubEffect() could not get library %s", node->value);
579         return -EINVAL;
580     }
581     node = config_find(root, UUID_TAG);
582     if (node == NULL) {
583         return -EINVAL;
584     }
585     if (stringToUuid(node->value, &uuid) != 0) {
586         ALOGW("addSubEffect() invalid uuid %s", node->value);
587         return -EINVAL;
588     }
589     d = malloc(sizeof(effect_descriptor_t));
590     if (l->desc->get_descriptor(&uuid, d) != 0) {
591         char s[40];
592         uuidToString(&uuid, s, 40);
593         ALOGW("Error querying effect %s on lib %s", s, l->name);
594         free(d);
595         return -EINVAL;
596     }
597 #if (LOG_NDEBUG==0)
598     char s[256];
599     dumpEffectDescriptor(d, s, 256);
600     ALOGV("addSubEffect() read descriptor %p:%s",d, s);
601 #endif
602     if (EFFECT_API_VERSION_MAJOR(d->apiVersion) !=
603             EFFECT_API_VERSION_MAJOR(EFFECT_CONTROL_API_VERSION)) {
604         ALOGW("Bad API version %08x on lib %s", d->apiVersion, l->name);
605         free(d);
606         return -EINVAL;
607     }
608     sub_effect_entry_t *sub_effect = malloc(sizeof(sub_effect_entry_t));
609     sub_effect->object = d;
610     // lib_entry_t is stored since the sub effects are not linked to the library
611     sub_effect->lib = l;
612     e = malloc(sizeof(list_elem_t));
613     e->object = sub_effect;
614     e->next = gSubEffectList->sub_elem;
615     gSubEffectList->sub_elem = e;
616     ALOGV("addSubEffect end");
617     return 0;
618 }
619 
loadEffects(cnode * root)620 int loadEffects(cnode *root)
621 {
622     cnode *node;
623 
624     node = config_find(root, EFFECTS_TAG);
625     if (node == NULL) {
626         return -ENOENT;
627     }
628     node = node->first_child;
629     while (node) {
630         loadEffect(node);
631         node = node->next;
632     }
633     return 0;
634 }
635 
loadEffect(cnode * root)636 int loadEffect(cnode *root)
637 {
638     cnode *node;
639     effect_uuid_t uuid;
640     lib_entry_t *l;
641     effect_descriptor_t *d;
642     list_elem_t *e;
643 
644     node = config_find(root, LIBRARY_TAG);
645     if (node == NULL) {
646         return -EINVAL;
647     }
648 
649     l = getLibrary(node->value);
650     if (l == NULL) {
651         ALOGW("loadEffect() could not get library %s", node->value);
652         return -EINVAL;
653     }
654 
655     node = config_find(root, UUID_TAG);
656     if (node == NULL) {
657         return -EINVAL;
658     }
659     if (stringToUuid(node->value, &uuid) != 0) {
660         ALOGW("loadEffect() invalid uuid %s", node->value);
661         return -EINVAL;
662     }
663 
664     d = malloc(sizeof(effect_descriptor_t));
665     if (l->desc->get_descriptor(&uuid, d) != 0) {
666         char s[40];
667         uuidToString(&uuid, s, 40);
668         ALOGW("Error querying effect %s on lib %s", s, l->name);
669         free(d);
670         return -EINVAL;
671     }
672 #if (LOG_NDEBUG==0)
673     char s[256];
674     dumpEffectDescriptor(d, s, 256);
675     ALOGV("loadEffect() read descriptor %p:%s",d, s);
676 #endif
677     if (EFFECT_API_VERSION_MAJOR(d->apiVersion) !=
678             EFFECT_API_VERSION_MAJOR(EFFECT_CONTROL_API_VERSION)) {
679         ALOGW("Bad API version %08x on lib %s", d->apiVersion, l->name);
680         free(d);
681         return -EINVAL;
682     }
683     e = malloc(sizeof(list_elem_t));
684     e->object = d;
685     e->next = l->effects;
686     l->effects = e;
687 
688     // After the UUID node in the config_tree, if node->next is valid,
689     // that would be sub effect node.
690     // Find the sub effects and add them to the gSubEffectList
691     node = node->next;
692     int count = 2;
693     bool hwSubefx = false, swSubefx = false;
694     list_sub_elem_t *sube = NULL;
695     if (node != NULL) {
696         ALOGV("Adding the effect to gEffectSubList as there are sub effects");
697         sube = malloc(sizeof(list_sub_elem_t));
698         sube->object = d;
699         sube->sub_elem = NULL;
700         sube->next = gSubEffectList;
701         gSubEffectList = sube;
702     }
703     while (node != NULL && count) {
704        if (addSubEffect(node)) {
705            ALOGW("loadEffect() could not add subEffect %s", node->value);
706            // Change the gSubEffectList to point to older list;
707            gSubEffectList = sube->next;
708            free(sube->sub_elem);// Free an already added sub effect
709            sube->sub_elem = NULL;
710            free(sube);
711            return -ENOENT;
712        }
713        sub_effect_entry_t *subEntry = (sub_effect_entry_t*)gSubEffectList->sub_elem->object;
714        effect_descriptor_t *subEffectDesc = (effect_descriptor_t*)(subEntry->object);
715        // Since we return a dummy descriptor for the proxy during
716        // get_descriptor call,we replace it with the correspoding
717        // sw effect descriptor, but with Proxy UUID
718        // check for Sw desc
719         if (!((subEffectDesc->flags & EFFECT_FLAG_HW_ACC_MASK) ==
720                                            EFFECT_FLAG_HW_ACC_TUNNEL)) {
721              swSubefx = true;
722              *d = *subEffectDesc;
723              d->uuid = uuid;
724              ALOGV("loadEffect() Changed the Proxy desc");
725        } else
726            hwSubefx = true;
727        count--;
728        node = node->next;
729     }
730     // 1 HW and 1 SW sub effect found. Set the offload flag in the Proxy desc
731     if (hwSubefx && swSubefx) {
732         d->flags |= EFFECT_FLAG_OFFLOAD_SUPPORTED;
733     }
734     return 0;
735 }
736 
737 // Searches the sub effect matching to the specified uuid
738 // in the gSubEffectList. It gets the lib_entry_t for
739 // the matched sub_effect . Used in EffectCreate of sub effects
findSubEffect(const effect_uuid_t * uuid,lib_entry_t ** lib,effect_descriptor_t ** desc)740 int findSubEffect(const effect_uuid_t *uuid,
741                lib_entry_t **lib,
742                effect_descriptor_t **desc)
743 {
744     list_sub_elem_t *e = gSubEffectList;
745     list_elem_t *subefx;
746     sub_effect_entry_t *effect;
747     lib_entry_t *l = NULL;
748     effect_descriptor_t *d = NULL;
749     int found = 0;
750     int ret = 0;
751 
752     if (uuid == NULL)
753         return -EINVAL;
754 
755     while (e != NULL && !found) {
756         subefx = (list_elem_t*)(e->sub_elem);
757         while (subefx != NULL) {
758             effect = (sub_effect_entry_t*)subefx->object;
759             l = (lib_entry_t *)effect->lib;
760             d = (effect_descriptor_t *)effect->object;
761             if (memcmp(&d->uuid, uuid, sizeof(effect_uuid_t)) == 0) {
762                 ALOGV("uuid matched");
763                 found = 1;
764                 break;
765             }
766             subefx = subefx->next;
767         }
768         e = e->next;
769     }
770     if (!found) {
771         ALOGV("findSubEffect() effect not found");
772         ret = -ENOENT;
773     } else {
774         ALOGV("findSubEffect() found effect: %s in lib %s", d->name, l->name);
775         *lib = l;
776         if (desc != NULL) {
777             *desc = d;
778         }
779     }
780     return ret;
781 }
782 
getLibrary(const char * name)783 lib_entry_t *getLibrary(const char *name)
784 {
785     list_elem_t *e;
786 
787     if (gCachedLibrary &&
788             !strncmp(gCachedLibrary->name, name, PATH_MAX)) {
789         return gCachedLibrary;
790     }
791 
792     e = gLibraryList;
793     while (e) {
794         lib_entry_t *l = (lib_entry_t *)e->object;
795         if (!strcmp(l->name, name)) {
796             gCachedLibrary = l;
797             return l;
798         }
799         e = e->next;
800     }
801 
802     return NULL;
803 }
804 
805 
resetEffectEnumeration()806 void resetEffectEnumeration()
807 {
808     gCurLib = gLibraryList;
809     gCurEffect = NULL;
810     if (gCurLib) {
811         gCurEffect = ((lib_entry_t *)gCurLib->object)->effects;
812     }
813     gCurEffectIdx = 0;
814 }
815 
updateNumEffects()816 uint32_t updateNumEffects() {
817     list_elem_t *e;
818     uint32_t cnt = 0;
819 
820     resetEffectEnumeration();
821 
822     e = gLibraryList;
823     while (e) {
824         lib_entry_t *l = (lib_entry_t *)e->object;
825         list_elem_t *efx = l->effects;
826         while (efx) {
827             cnt++;
828             efx = efx->next;
829         }
830         e = e->next;
831     }
832     gNumEffects = cnt;
833     gCanQueryEffect = 0;
834     return cnt;
835 }
836 
findEffect(const effect_uuid_t * type,const effect_uuid_t * uuid,lib_entry_t ** lib,effect_descriptor_t ** desc)837 int findEffect(const effect_uuid_t *type,
838                const effect_uuid_t *uuid,
839                lib_entry_t **lib,
840                effect_descriptor_t **desc)
841 {
842     list_elem_t *e = gLibraryList;
843     lib_entry_t *l = NULL;
844     effect_descriptor_t *d = NULL;
845     int found = 0;
846     int ret = 0;
847 
848     while (e && !found) {
849         l = (lib_entry_t *)e->object;
850         list_elem_t *efx = l->effects;
851         while (efx) {
852             d = (effect_descriptor_t *)efx->object;
853             if (type != NULL && memcmp(&d->type, type, sizeof(effect_uuid_t)) == 0) {
854                 found = 1;
855                 break;
856             }
857             if (uuid != NULL && memcmp(&d->uuid, uuid, sizeof(effect_uuid_t)) == 0) {
858                 found = 1;
859                 break;
860             }
861             efx = efx->next;
862         }
863         e = e->next;
864     }
865     if (!found) {
866         ALOGV("findEffect() effect not found");
867         ret = -ENOENT;
868     } else {
869         ALOGV("findEffect() found effect: %s in lib %s", d->name, l->name);
870         *lib = l;
871         if (desc) {
872             *desc = d;
873         }
874     }
875 
876     return ret;
877 }
878 
dumpEffectDescriptor(effect_descriptor_t * desc,char * str,size_t len)879 void dumpEffectDescriptor(effect_descriptor_t *desc, char *str, size_t len) {
880     char s[256];
881 
882     snprintf(str, len, "\nEffect Descriptor %p:\n", desc);
883     strncat(str, "- TYPE: ", len);
884     uuidToString(&desc->uuid, s, 256);
885     snprintf(str, len, "- UUID: %s\n", s);
886     uuidToString(&desc->type, s, 256);
887     snprintf(str, len, "- TYPE: %s\n", s);
888     sprintf(s, "- apiVersion: %08X\n- flags: %08X\n",
889             desc->apiVersion, desc->flags);
890     strncat(str, s, len);
891     sprintf(s, "- name: %s\n", desc->name);
892     strncat(str, s, len);
893     sprintf(s, "- implementor: %s\n", desc->implementor);
894     strncat(str, s, len);
895 }
896 
stringToUuid(const char * str,effect_uuid_t * uuid)897 int stringToUuid(const char *str, effect_uuid_t *uuid)
898 {
899     int tmp[10];
900 
901     if (sscanf(str, "%08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x",
902             tmp, tmp+1, tmp+2, tmp+3, tmp+4, tmp+5, tmp+6, tmp+7, tmp+8, tmp+9) < 10) {
903         return -EINVAL;
904     }
905     uuid->timeLow = (uint32_t)tmp[0];
906     uuid->timeMid = (uint16_t)tmp[1];
907     uuid->timeHiAndVersion = (uint16_t)tmp[2];
908     uuid->clockSeq = (uint16_t)tmp[3];
909     uuid->node[0] = (uint8_t)tmp[4];
910     uuid->node[1] = (uint8_t)tmp[5];
911     uuid->node[2] = (uint8_t)tmp[6];
912     uuid->node[3] = (uint8_t)tmp[7];
913     uuid->node[4] = (uint8_t)tmp[8];
914     uuid->node[5] = (uint8_t)tmp[9];
915 
916     return 0;
917 }
918 
uuidToString(const effect_uuid_t * uuid,char * str,size_t maxLen)919 int uuidToString(const effect_uuid_t *uuid, char *str, size_t maxLen)
920 {
921 
922     snprintf(str, maxLen, "%08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x",
923             uuid->timeLow,
924             uuid->timeMid,
925             uuid->timeHiAndVersion,
926             uuid->clockSeq,
927             uuid->node[0],
928             uuid->node[1],
929             uuid->node[2],
930             uuid->node[3],
931             uuid->node[4],
932             uuid->node[5]);
933 
934     return 0;
935 }
936 
937