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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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