Home | History | Annotate | Download | only in factory
      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