Home | History | Annotate | Download | only in factory
      1 /*
      2  * Copyright (C) 2017 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 "EffectsFactoryConfigLoader"
     18 //#define LOG_NDEBUG 0
     19 
     20 #include <dlfcn.h>
     21 #include <stdlib.h>
     22 #include <unistd.h>
     23 
     24 #include <cutils/config_utils.h>
     25 #include <cutils/misc.h>
     26 #include <log/log.h>
     27 
     28 #include <system/audio_effects/audio_effects_conf.h>
     29 
     30 #include "EffectsConfigLoader.h"
     31 #include "EffectsFactoryState.h"
     32 
     33 /////////////////////////////////////////////////
     34 //      Local functions prototypes
     35 /////////////////////////////////////////////////
     36 
     37 static int loadEffectConfigFile(const char *path);
     38 static int loadLibraries(cnode *root);
     39 static int loadLibrary(cnode *root, const char *name);
     40 static int loadEffects(cnode *root);
     41 static int loadEffect(cnode *node);
     42 // To get and add the effect pointed by the passed node to the gSubEffectList
     43 static int addSubEffect(cnode *root);
     44 static lib_entry_t *getLibrary(const char *path);
     45 
     46 static lib_entry_t *gCachedLibrary;  // last library accessed by getLibrary()
     47 
     48 int EffectLoadEffectConfig()
     49 {
     50     if (access(AUDIO_EFFECT_VENDOR_CONFIG_FILE, R_OK) == 0) {
     51         return loadEffectConfigFile(AUDIO_EFFECT_VENDOR_CONFIG_FILE);
     52     } else if (access(AUDIO_EFFECT_DEFAULT_CONFIG_FILE, R_OK) == 0) {
     53         return loadEffectConfigFile(AUDIO_EFFECT_DEFAULT_CONFIG_FILE);
     54     }
     55     return 0;
     56 }
     57 
     58 int loadEffectConfigFile(const char *path)
     59 {
     60     cnode *root;
     61     char *data;
     62 
     63     data = load_file(path, NULL);
     64     if (data == NULL) {
     65         return -ENODEV;
     66     }
     67     root = config_node("", "");
     68     config_load(root, data);
     69     loadLibraries(root);
     70     loadEffects(root);
     71     config_free(root);
     72     free(root);
     73     free(data);
     74 
     75     return 0;
     76 }
     77 
     78 int loadLibraries(cnode *root)
     79 {
     80     cnode *node;
     81 
     82     node = config_find(root, LIBRARIES_TAG);
     83     if (node == NULL) {
     84         return -ENOENT;
     85     }
     86     node = node->first_child;
     87     while (node) {
     88         loadLibrary(node, node->name);
     89         node = node->next;
     90     }
     91     return 0;
     92 }
     93 
     94 #ifdef __LP64__
     95 // audio_effects.conf always specifies 32 bit lib path: convert to 64 bit path if needed
     96 static const char *kLibraryPathRoot[] =
     97         {"/odm/lib64/soundfx", "/vendor/lib64/soundfx", "/system/lib64/soundfx"};
     98 #else
     99 static const char *kLibraryPathRoot[] =
    100         {"/odm/lib/soundfx", "/vendor/lib/soundfx", "/system/lib/soundfx"};
    101 #endif
    102 
    103 static const int kLibraryPathRootSize =
    104         (sizeof(kLibraryPathRoot) / sizeof(kLibraryPathRoot[0]));
    105 
    106 // Checks if the library path passed as lib_path_in can be opened and if not
    107 // tries in standard effect library directories with just the library name and returns correct path
    108 // in lib_path_out
    109 int checkLibraryPath(const char *lib_path_in, char *lib_path_out) {
    110     char *str;
    111     const char *lib_name;
    112     size_t len;
    113 
    114     if (lib_path_in == NULL || lib_path_out == NULL) {
    115         return -EINVAL;
    116     }
    117 
    118     strlcpy(lib_path_out, lib_path_in, PATH_MAX);
    119 
    120     // Try exact path first
    121     str = strstr(lib_path_out, "/lib/soundfx/");
    122     if (str == NULL) {
    123         return -EINVAL;
    124     }
    125 
    126     // Extract library name from input path
    127     len = str - lib_path_out;
    128     lib_name = lib_path_in + len + strlen("/lib/soundfx/");
    129 
    130     // Then try with library name and standard path names in order of preference
    131     for (int i = 0; i < kLibraryPathRootSize; i++) {
    132         char path[PATH_MAX];
    133 
    134         snprintf(path,
    135                  PATH_MAX,
    136                  "%s/%s",
    137                  kLibraryPathRoot[i],
    138                  lib_name);
    139         if (F_OK == access(path, 0)) {
    140             strcpy(lib_path_out, path);
    141             ALOGW_IF(strncmp(lib_path_out, lib_path_in, PATH_MAX) != 0,
    142                 "checkLibraryPath() corrected library path %s to %s", lib_path_in, lib_path_out);
    143             return 0;
    144         }
    145     }
    146     return -EINVAL;
    147 }
    148 
    149 
    150 
    151 int loadLibrary(cnode *root, const char *name)
    152 {
    153     cnode *node;
    154     void *hdl = NULL;
    155     audio_effect_library_t *desc;
    156     list_elem_t *e;
    157     lib_entry_t *l;
    158     char path[PATH_MAX];
    159 
    160     node = config_find(root, PATH_TAG);
    161     if (node == NULL) {
    162         return -EINVAL;
    163     }
    164 
    165     if (checkLibraryPath((const char *)node->value, path) != 0) {
    166         ALOGW("loadLibrary() could not find library %s", path);
    167         goto error;
    168     }
    169 
    170     hdl = dlopen(path, RTLD_NOW);
    171     if (hdl == NULL) {
    172         ALOGW("loadLibrary() failed to open %s", path);
    173         goto error;
    174     }
    175 
    176     desc = (audio_effect_library_t *)dlsym(hdl, AUDIO_EFFECT_LIBRARY_INFO_SYM_AS_STR);
    177     if (desc == NULL) {
    178         ALOGW("loadLibrary() could not find symbol %s", AUDIO_EFFECT_LIBRARY_INFO_SYM_AS_STR);
    179         goto error;
    180     }
    181 
    182     if (AUDIO_EFFECT_LIBRARY_TAG != desc->tag) {
    183         ALOGW("getLibrary() bad tag %08x in lib info struct", desc->tag);
    184         goto error;
    185     }
    186 
    187     if (EFFECT_API_VERSION_MAJOR(desc->version) !=
    188             EFFECT_API_VERSION_MAJOR(EFFECT_LIBRARY_API_VERSION)) {
    189         ALOGW("loadLibrary() bad lib version %08x", desc->version);
    190         goto error;
    191     }
    192 
    193     // add entry for library in gLibraryList
    194     l = malloc(sizeof(lib_entry_t));
    195     l->name = strndup(name, PATH_MAX);
    196     l->path = strndup(path, PATH_MAX);
    197     l->handle = hdl;
    198     l->desc = desc;
    199     l->effects = NULL;
    200     pthread_mutex_init(&l->lock, NULL);
    201 
    202     e = malloc(sizeof(list_elem_t));
    203     e->object = l;
    204     pthread_mutex_lock(&gLibLock);
    205     e->next = gLibraryList;
    206     gLibraryList = e;
    207     pthread_mutex_unlock(&gLibLock);
    208     ALOGV("getLibrary() linked library %p for path %s", l, path);
    209 
    210     return 0;
    211 
    212 error:
    213     if (hdl != NULL) {
    214         dlclose(hdl);
    215     }
    216     //add entry for library errors in gLibraryFailedList
    217     lib_failed_entry_t *fl = malloc(sizeof(lib_failed_entry_t));
    218     fl->name = strndup(name, PATH_MAX);
    219     fl->path = strndup(path, PATH_MAX);
    220 
    221     list_elem_t *fe = malloc(sizeof(list_elem_t));
    222     fe->object = fl;
    223     fe->next = gLibraryFailedList;
    224     gLibraryFailedList = fe;
    225     ALOGV("getLibrary() linked error in library %p for path %s", fl, path);
    226 
    227     return -EINVAL;
    228 }
    229 
    230 // This will find the library and UUID tags of the sub effect pointed by the
    231 // node, gets the effect descriptor and lib_entry_t and adds the subeffect -
    232 // sub_entry_t to the gSubEffectList
    233 int addSubEffect(cnode *root)
    234 {
    235     ALOGV("addSubEffect");
    236     cnode *node;
    237     effect_uuid_t uuid;
    238     effect_descriptor_t *d;
    239     lib_entry_t *l;
    240     list_elem_t *e;
    241     node = config_find(root, LIBRARY_TAG);
    242     if (node == NULL) {
    243         return -EINVAL;
    244     }
    245     l = getLibrary(node->value);
    246     if (l == NULL) {
    247         ALOGW("addSubEffect() could not get library %s", node->value);
    248         return -EINVAL;
    249     }
    250     node = config_find(root, UUID_TAG);
    251     if (node == NULL) {
    252         return -EINVAL;
    253     }
    254     if (stringToUuid(node->value, &uuid) != 0) {
    255         ALOGW("addSubEffect() invalid uuid %s", node->value);
    256         return -EINVAL;
    257     }
    258     d = malloc(sizeof(effect_descriptor_t));
    259     if (l->desc->get_descriptor(&uuid, d) != 0) {
    260         char s[40];
    261         uuidToString(&uuid, s, 40);
    262         ALOGW("Error querying effect %s on lib %s", s, l->name);
    263         free(d);
    264         return -EINVAL;
    265     }
    266 #if (LOG_NDEBUG==0)
    267     char s[512];
    268     dumpEffectDescriptor(d, s, sizeof(s), 0 /* indent */);
    269     ALOGV("addSubEffect() read descriptor %p:%s",d, s);
    270 #endif
    271     if (EFFECT_API_VERSION_MAJOR(d->apiVersion) !=
    272             EFFECT_API_VERSION_MAJOR(EFFECT_CONTROL_API_VERSION)) {
    273         ALOGW("Bad API version %08x on lib %s", d->apiVersion, l->name);
    274         free(d);
    275         return -EINVAL;
    276     }
    277     sub_effect_entry_t *sub_effect = malloc(sizeof(sub_effect_entry_t));
    278     sub_effect->object = d;
    279     // lib_entry_t is stored since the sub effects are not linked to the library
    280     sub_effect->lib = l;
    281     e = malloc(sizeof(list_elem_t));
    282     e->object = sub_effect;
    283     e->next = gSubEffectList->sub_elem;
    284     gSubEffectList->sub_elem = e;
    285     ALOGV("addSubEffect end");
    286     return 0;
    287 }
    288 
    289 int loadEffects(cnode *root)
    290 {
    291     cnode *node;
    292 
    293     node = config_find(root, EFFECTS_TAG);
    294     if (node == NULL) {
    295         return -ENOENT;
    296     }
    297     node = node->first_child;
    298     while (node) {
    299         loadEffect(node);
    300         node = node->next;
    301     }
    302     return 0;
    303 }
    304 
    305 int loadEffect(cnode *root)
    306 {
    307     cnode *node;
    308     effect_uuid_t uuid;
    309     lib_entry_t *l;
    310     effect_descriptor_t *d;
    311     list_elem_t *e;
    312 
    313     node = config_find(root, LIBRARY_TAG);
    314     if (node == NULL) {
    315         return -EINVAL;
    316     }
    317 
    318     l = getLibrary(node->value);
    319     if (l == NULL) {
    320         ALOGW("loadEffect() could not get library %s", node->value);
    321         return -EINVAL;
    322     }
    323 
    324     node = config_find(root, UUID_TAG);
    325     if (node == NULL) {
    326         return -EINVAL;
    327     }
    328     if (stringToUuid(node->value, &uuid) != 0) {
    329         ALOGW("loadEffect() invalid uuid %s", node->value);
    330         return -EINVAL;
    331     }
    332     lib_entry_t *tmp;
    333     bool skip = false;
    334     if (findEffect(NULL, &uuid, &tmp, NULL) == 0) {
    335         ALOGW("skipping duplicate uuid %s %s", node->value,
    336                 node->next ? "and its sub-effects" : "");
    337         skip = true;
    338     }
    339 
    340     d = malloc(sizeof(effect_descriptor_t));
    341     if (l->desc->get_descriptor(&uuid, d) != 0) {
    342         char s[40];
    343         uuidToString(&uuid, s, 40);
    344         ALOGW("Error querying effect %s on lib %s", s, l->name);
    345         free(d);
    346         return -EINVAL;
    347     }
    348 #if (LOG_NDEBUG==0)
    349     char s[512];
    350     dumpEffectDescriptor(d, s, sizeof(s), 0 /* indent */);
    351     ALOGV("loadEffect() read descriptor %p:%s",d, s);
    352 #endif
    353     if (EFFECT_API_VERSION_MAJOR(d->apiVersion) !=
    354             EFFECT_API_VERSION_MAJOR(EFFECT_CONTROL_API_VERSION)) {
    355         ALOGW("Bad API version %08x on lib %s", d->apiVersion, l->name);
    356         free(d);
    357         return -EINVAL;
    358     }
    359     e = malloc(sizeof(list_elem_t));
    360     e->object = d;
    361     if (skip) {
    362         e->next = gSkippedEffects;
    363         gSkippedEffects = e;
    364         return -EINVAL;
    365     } else {
    366         e->next = l->effects;
    367         l->effects = e;
    368     }
    369 
    370     // After the UUID node in the config_tree, if node->next is valid,
    371     // that would be sub effect node.
    372     // Find the sub effects and add them to the gSubEffectList
    373     node = node->next;
    374     int count = 2;
    375     bool hwSubefx = false, swSubefx = false;
    376     list_sub_elem_t *sube = NULL;
    377     if (node != NULL) {
    378         ALOGV("Adding the effect to gEffectSubList as there are sub effects");
    379         sube = malloc(sizeof(list_sub_elem_t));
    380         sube->object = d;
    381         sube->sub_elem = NULL;
    382         sube->next = gSubEffectList;
    383         gSubEffectList = sube;
    384     }
    385     while (node != NULL && count) {
    386        if (addSubEffect(node)) {
    387            ALOGW("loadEffect() could not add subEffect %s", node->value);
    388            // Change the gSubEffectList to point to older list;
    389            gSubEffectList = sube->next;
    390            free(sube->sub_elem);// Free an already added sub effect
    391            sube->sub_elem = NULL;
    392            free(sube);
    393            return -ENOENT;
    394        }
    395        sub_effect_entry_t *subEntry = (sub_effect_entry_t*)gSubEffectList->sub_elem->object;
    396        effect_descriptor_t *subEffectDesc = (effect_descriptor_t*)(subEntry->object);
    397        // Since we return a dummy descriptor for the proxy during
    398        // get_descriptor call,we replace it with the correspoding
    399        // sw effect descriptor, but with Proxy UUID
    400        // check for Sw desc
    401         if (!((subEffectDesc->flags & EFFECT_FLAG_HW_ACC_MASK) ==
    402                                            EFFECT_FLAG_HW_ACC_TUNNEL)) {
    403              swSubefx = true;
    404              *d = *subEffectDesc;
    405              d->uuid = uuid;
    406              ALOGV("loadEffect() Changed the Proxy desc");
    407        } else
    408            hwSubefx = true;
    409        count--;
    410        node = node->next;
    411     }
    412     // 1 HW and 1 SW sub effect found. Set the offload flag in the Proxy desc
    413     if (hwSubefx && swSubefx) {
    414         d->flags |= EFFECT_FLAG_OFFLOAD_SUPPORTED;
    415     }
    416     return 0;
    417 }
    418 
    419 lib_entry_t *getLibrary(const char *name)
    420 {
    421     list_elem_t *e;
    422 
    423     if (gCachedLibrary &&
    424             !strncmp(gCachedLibrary->name, name, PATH_MAX)) {
    425         return gCachedLibrary;
    426     }
    427 
    428     e = gLibraryList;
    429     while (e) {
    430         lib_entry_t *l = (lib_entry_t *)e->object;
    431         if (!strcmp(l->name, name)) {
    432             gCachedLibrary = l;
    433             return l;
    434         }
    435         e = e->next;
    436     }
    437 
    438     return NULL;
    439 }
    440