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