Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 11cb8753 authored by Shunkai Yao's avatar Shunkai Yao Committed by Automerger Merge Worker
Browse files

Merge changes I415a7be5,Id3ec0934 into udc-dev am: 1dbbf67c

parents 8e3c78c4 1dbbf67c
Loading
Loading
Loading
Loading
+7 −6
Original line number Original line Diff line number Diff line
@@ -49,26 +49,27 @@ struct Library {
    std::string name;
    std::string name;
    std::string path;
    std::string path;
};
};
using Libraries = std::vector<Library>;
using Libraries = std::vector<std::shared_ptr<const Library>>;


struct EffectImpl {
struct EffectImpl {
    Library* library; //< Only valid as long as the associated library vector is unmodified
    //< Only valid as long as the associated library vector is unmodified
    std::shared_ptr<const Library> library;
    effect_uuid_t uuid;
    effect_uuid_t uuid;
};
};


struct Effect : public EffectImpl {
struct Effect : public EffectImpl {
    std::string name;
    std::string name;
    bool isProxy;
    bool isProxy;
    EffectImpl libSw; //< Only valid if isProxy
    std::shared_ptr<EffectImpl> libSw; //< Only valid if isProxy
    EffectImpl libHw; //< Only valid if isProxy
    std::shared_ptr<EffectImpl> libHw; //< Only valid if isProxy
};
};


using Effects = std::vector<Effect>;
using Effects = std::vector<std::shared_ptr<const Effect>>;


template <class Type>
template <class Type>
struct Stream {
struct Stream {
    Type type;
    Type type;
    std::vector<std::reference_wrapper<Effect>> effects;
    Effects effects;
};
};
using OutputStream = Stream<audio_stream_type_t>;
using OutputStream = Stream<audio_stream_type_t>;
using InputStream = Stream<audio_source_t>;
using InputStream = Stream<audio_source_t>;
+19 −10
Original line number Original line Diff line number Diff line
@@ -19,6 +19,7 @@
#include <algorithm>
#include <algorithm>
#include <cstdint>
#include <cstdint>
#include <functional>
#include <functional>
#include <memory>
#include <string>
#include <string>
#include <unistd.h>
#include <unistd.h>


@@ -149,7 +150,10 @@ bool parseLibrary(const XMLElement& xmlLibrary, Libraries* libraries) {
        ALOGE("library must have a name and a path: %s", dump(xmlLibrary));
        ALOGE("library must have a name and a path: %s", dump(xmlLibrary));
        return false;
        return false;
    }
    }
    libraries->push_back({name, path});

    // need this temp variable because `struct Library` doesn't have a constructor
    Library lib({.name = name, .path = path});
    libraries->push_back(std::make_shared<const Library>(lib));
    return true;
    return true;
}
}


@@ -157,10 +161,10 @@ bool parseLibrary(const XMLElement& xmlLibrary, Libraries* libraries) {
 * @return nullptr if not found, the element address if found.
 * @return nullptr if not found, the element address if found.
 */
 */
template <class T>
template <class T>
T* findByName(const char* name, std::vector<T>& collection) {
T findByName(const char* name, std::vector<T>& collection) {
    auto it = find_if(begin(collection), end(collection),
    auto it = find_if(begin(collection), end(collection),
                         [name] (auto& item) { return item.name == name; });
                      [name](auto& item) { return item && item->name == name; });
    return it != end(collection) ? &*it : nullptr;
    return it != end(collection) ? *it : nullptr;
}
}


/** Parse an effect from an xml element describing it.
/** Parse an effect from an xml element describing it.
@@ -187,7 +191,7 @@ bool parseEffect(const XMLElement& xmlEffect, Libraries& libraries, Effects* eff
        }
        }


        // Convert library name to a pointer to the previously loaded library
        // Convert library name to a pointer to the previously loaded library
        auto* library = findByName(libraryName, libraries);
        auto library = findByName(libraryName, libraries);
        if (library == nullptr) {
        if (library == nullptr) {
            ALOGE("Could not find library referenced in: %s", dump(xmlImpl));
            ALOGE("Could not find library referenced in: %s", dump(xmlImpl));
            return false;
            return false;
@@ -211,20 +215,25 @@ bool parseEffect(const XMLElement& xmlEffect, Libraries& libraries, Effects* eff
        effect.isProxy = true;
        effect.isProxy = true;


        // Function to parse libhw and libsw
        // Function to parse libhw and libsw
        auto parseProxy = [&xmlEffect, &parseImpl](const char* tag, EffectImpl& proxyLib) {
        auto parseProxy = [&xmlEffect, &parseImpl](const char* tag,
                                                   const std::shared_ptr<EffectImpl>& proxyLib) {
            auto* xmlProxyLib = xmlEffect.FirstChildElement(tag);
            auto* xmlProxyLib = xmlEffect.FirstChildElement(tag);
            if (xmlProxyLib == nullptr) {
            if (xmlProxyLib == nullptr) {
                ALOGE("effectProxy must contain a <%s>: %s", tag, dump(xmlEffect));
                ALOGE("effectProxy must contain a <%s>: %s", tag, dump(xmlEffect));
                return false;
                return false;
            }
            }
            return parseImpl(*xmlProxyLib, proxyLib);
            return parseImpl(*xmlProxyLib, *proxyLib);
        };
        };
        effect.libSw = std::make_shared<EffectImpl>();
        effect.libHw = std::make_shared<EffectImpl>();
        if (!parseProxy("libhw", effect.libHw) || !parseProxy("libsw", effect.libSw)) {
        if (!parseProxy("libhw", effect.libHw) || !parseProxy("libsw", effect.libSw)) {
            effect.libSw.reset();
            effect.libHw.reset();
            return false;
            return false;
        }
        }
    }
    }


    effects->push_back(std::move(effect));
    effects->push_back(std::make_shared<const Effect>(effect));
    return true;
    return true;
}
}


@@ -250,12 +259,12 @@ bool parseStream(const XMLElement& xmlStream, Effects& effects, std::vector<Stre
            ALOGE("<stream|device>/apply must have reference an effect: %s", dump(xmlApply));
            ALOGE("<stream|device>/apply must have reference an effect: %s", dump(xmlApply));
            return false;
            return false;
        }
        }
        auto* effect = findByName(effectName, effects);
        auto effect = findByName(effectName, effects);
        if (effect == nullptr) {
        if (effect == nullptr) {
            ALOGE("Could not find effect referenced in: %s", dump(xmlApply));
            ALOGE("Could not find effect referenced in: %s", dump(xmlApply));
            return false;
            return false;
        }
        }
        stream.effects.emplace_back(*effect);
        stream.effects.emplace_back(effect);
    }
    }
    streams->push_back(std::move(stream));
    streams->push_back(std::move(stream));
    return true;
    return true;
+0 −1
Original line number Original line Diff line number Diff line
@@ -21,7 +21,6 @@ cc_library_shared {
    vendor: true,
    vendor: true,
    srcs: [
    srcs: [
         "EffectsFactory.c",
         "EffectsFactory.c",
         "EffectsConfigLoader.c",
         "EffectsFactoryState.c",
         "EffectsFactoryState.c",
         "EffectsXmlConfigLoader.cpp",
         "EffectsXmlConfigLoader.cpp",
    ],
    ],
+0 −439
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#define LOG_TAG "EffectsFactoryConfigLoader"
//#define LOG_NDEBUG 0

#include <dlfcn.h>
#include <stdlib.h>
#include <unistd.h>

#include <cutils/config_utils.h>
#include <cutils/misc.h>
#include <log/log.h>

#include <system/audio_effects/audio_effects_conf.h>

#include "EffectsConfigLoader.h"
#include "EffectsFactoryState.h"

/////////////////////////////////////////////////
//      Local functions prototypes
/////////////////////////////////////////////////

static int loadEffectConfigFile(const char *path);
static int loadLibraries(cnode *root);
static int loadLibrary(cnode *root, const char *name);
static int loadEffects(cnode *root);
static int loadEffect(cnode *node);
// To get and add the effect pointed by the passed node to the gSubEffectList
static int addSubEffect(cnode *root);
static lib_entry_t *getLibrary(const char *path);

static lib_entry_t *gCachedLibrary;  // last library accessed by getLibrary()

int EffectLoadEffectConfig()
{
    if (access(AUDIO_EFFECT_VENDOR_CONFIG_FILE, R_OK) == 0) {
        return loadEffectConfigFile(AUDIO_EFFECT_VENDOR_CONFIG_FILE);
    } else if (access(AUDIO_EFFECT_DEFAULT_CONFIG_FILE, R_OK) == 0) {
        return loadEffectConfigFile(AUDIO_EFFECT_DEFAULT_CONFIG_FILE);
    }
    return 0;
}

int loadEffectConfigFile(const char *path)
{
    cnode *root;
    char *data;

    data = load_file(path, NULL);
    if (data == NULL) {
        return -ENODEV;
    }
    root = config_node("", "");
    config_load(root, data);
    loadLibraries(root);
    loadEffects(root);
    config_free(root);
    free(root);
    free(data);

    return 0;
}

int loadLibraries(cnode *root)
{
    cnode *node;

    node = config_find(root, LIBRARIES_TAG);
    if (node == NULL) {
        return -ENOENT;
    }
    node = node->first_child;
    while (node) {
        loadLibrary(node, node->name);
        node = node->next;
    }
    return 0;
}

#ifdef __LP64__
// audio_effects.conf always specifies 32 bit lib path: convert to 64 bit path if needed
static const char *kLibraryPathRoot[] =
        {"/odm/lib64/soundfx", "/vendor/lib64/soundfx", "/system/lib64/soundfx"};
#else
static const char *kLibraryPathRoot[] =
        {"/odm/lib/soundfx", "/vendor/lib/soundfx", "/system/lib/soundfx"};
#endif

static const int kLibraryPathRootSize =
        (sizeof(kLibraryPathRoot) / sizeof(kLibraryPathRoot[0]));

// Checks if the library path passed as lib_path_in can be opened and if not
// tries in standard effect library directories with just the library name and returns correct path
// in lib_path_out
int checkLibraryPath(const char *lib_path_in, char *lib_path_out) {
    char *str;
    const char *lib_name;
    size_t len;

    if (lib_path_in == NULL || lib_path_out == NULL) {
        return -EINVAL;
    }

    strlcpy(lib_path_out, lib_path_in, PATH_MAX);

    // Try exact path first
    str = strstr(lib_path_out, "/lib/soundfx/");
    if (str == NULL) {
        return -EINVAL;
    }

    // Extract library name from input path
    len = str - lib_path_out;
    lib_name = lib_path_in + len + strlen("/lib/soundfx/");

    // Then try with library name and standard path names in order of preference
    for (int i = 0; i < kLibraryPathRootSize; i++) {
        char path[PATH_MAX];

        snprintf(path,
                 PATH_MAX,
                 "%s/%s",
                 kLibraryPathRoot[i],
                 lib_name);
        if (F_OK == access(path, 0)) {
            strcpy(lib_path_out, path);
            ALOGW_IF(strncmp(lib_path_out, lib_path_in, PATH_MAX) != 0,
                "checkLibraryPath() corrected library path %s to %s", lib_path_in, lib_path_out);
            return 0;
        }
    }
    return -EINVAL;
}



int loadLibrary(cnode *root, const char *name)
{
    cnode *node;
    void *hdl = NULL;
    audio_effect_library_t *desc;
    list_elem_t *e;
    lib_entry_t *l;
    char path[PATH_MAX];

    node = config_find(root, PATH_TAG);
    if (node == NULL) {
        return -EINVAL;
    }

    if (checkLibraryPath((const char *)node->value, path) != 0) {
        ALOGW("loadLibrary() could not find library %s", path);
        goto error;
    }

    hdl = dlopen(path, RTLD_NOW);
    if (hdl == NULL) {
        ALOGW("loadLibrary() failed to open %s", path);
        goto error;
    }

    desc = (audio_effect_library_t *)dlsym(hdl, AUDIO_EFFECT_LIBRARY_INFO_SYM_AS_STR);
    if (desc == NULL) {
        ALOGW("loadLibrary() could not find symbol %s", AUDIO_EFFECT_LIBRARY_INFO_SYM_AS_STR);
        goto error;
    }

    if (AUDIO_EFFECT_LIBRARY_TAG != desc->tag) {
        ALOGW("getLibrary() bad tag %08x in lib info struct", desc->tag);
        goto error;
    }

    if (EFFECT_API_VERSION_MAJOR(desc->version) !=
            EFFECT_API_VERSION_MAJOR(EFFECT_LIBRARY_API_VERSION)) {
        ALOGW("loadLibrary() bad lib version %08x", desc->version);
        goto error;
    }

    // add entry for library in gLibraryList
    l = malloc(sizeof(lib_entry_t));
    l->name = strndup(name, PATH_MAX);
    l->path = strndup(path, PATH_MAX);
    l->handle = hdl;
    l->desc = desc;
    l->effects = NULL;
    pthread_mutex_init(&l->lock, NULL);

    e = malloc(sizeof(list_elem_t));
    e->object = l;
    pthread_mutex_lock(&gLibLock);
    e->next = gLibraryList;
    gLibraryList = e;
    pthread_mutex_unlock(&gLibLock);
    ALOGV("getLibrary() linked library %p for path %s", l, path);

    return 0;

error:
    if (hdl != NULL) {
        dlclose(hdl);
    }
    //add entry for library errors in gLibraryFailedList
    lib_failed_entry_t *fl = malloc(sizeof(lib_failed_entry_t));
    fl->name = strndup(name, PATH_MAX);
    fl->path = strndup(path, PATH_MAX);

    list_elem_t *fe = malloc(sizeof(list_elem_t));
    fe->object = fl;
    fe->next = gLibraryFailedList;
    gLibraryFailedList = fe;
    ALOGV("getLibrary() linked error in library %p for path %s", fl, path);

    return -EINVAL;
}

// This will find the library and UUID tags of the sub effect pointed by the
// node, gets the effect descriptor and lib_entry_t and adds the subeffect -
// sub_entry_t to the gSubEffectList
int addSubEffect(cnode *root)
{
    ALOGV("addSubEffect");
    cnode *node;
    effect_uuid_t uuid;
    effect_descriptor_t *d;
    lib_entry_t *l;
    list_elem_t *e;
    node = config_find(root, LIBRARY_TAG);
    if (node == NULL) {
        return -EINVAL;
    }
    l = getLibrary(node->value);
    if (l == NULL) {
        ALOGW("addSubEffect() could not get library %s", node->value);
        return -EINVAL;
    }
    node = config_find(root, UUID_TAG);
    if (node == NULL) {
        return -EINVAL;
    }
    if (stringToUuid(node->value, &uuid) != 0) {
        ALOGW("addSubEffect() invalid uuid %s", node->value);
        return -EINVAL;
    }
    d = malloc(sizeof(effect_descriptor_t));
    if (l->desc->get_descriptor(&uuid, d) != 0) {
        char s[40];
        uuidToString(&uuid, s, 40);
        ALOGW("Error querying effect %s on lib %s", s, l->name);
        free(d);
        return -EINVAL;
    }
#if (LOG_NDEBUG==0)
    char s[512];
    dumpEffectDescriptor(d, s, sizeof(s), 0 /* indent */);
    ALOGV("addSubEffect() read descriptor %p:%s",d, s);
#endif
    if (EFFECT_API_VERSION_MAJOR(d->apiVersion) !=
            EFFECT_API_VERSION_MAJOR(EFFECT_CONTROL_API_VERSION)) {
        ALOGW("Bad API version %08x on lib %s", d->apiVersion, l->name);
        free(d);
        return -EINVAL;
    }
    sub_effect_entry_t *sub_effect = malloc(sizeof(sub_effect_entry_t));
    sub_effect->object = d;
    // lib_entry_t is stored since the sub effects are not linked to the library
    sub_effect->lib = l;
    e = malloc(sizeof(list_elem_t));
    e->object = sub_effect;
    e->next = gSubEffectList->sub_elem;
    gSubEffectList->sub_elem = e;
    ALOGV("addSubEffect end");
    return 0;
}

int loadEffects(cnode *root)
{
    cnode *node;

    node = config_find(root, EFFECTS_TAG);
    if (node == NULL) {
        return -ENOENT;
    }
    node = node->first_child;
    while (node) {
        loadEffect(node);
        node = node->next;
    }
    return 0;
}

int loadEffect(cnode *root)
{
    cnode *node;
    effect_uuid_t uuid;
    lib_entry_t *l;
    effect_descriptor_t *d;
    list_elem_t *e;

    node = config_find(root, LIBRARY_TAG);
    if (node == NULL) {
        return -EINVAL;
    }

    l = getLibrary(node->value);
    if (l == NULL) {
        ALOGW("loadEffect() could not get library %s", node->value);
        return -EINVAL;
    }

    node = config_find(root, UUID_TAG);
    if (node == NULL) {
        return -EINVAL;
    }
    if (stringToUuid(node->value, &uuid) != 0) {
        ALOGW("loadEffect() invalid uuid %s", node->value);
        return -EINVAL;
    }
    lib_entry_t *tmp;
    bool skip = false;
    if (findEffect(NULL, &uuid, &tmp, NULL) == 0) {
        ALOGW("skipping duplicate uuid %s %s", node->value,
                node->next ? "and its sub-effects" : "");
        skip = true;
    }

    d = malloc(sizeof(effect_descriptor_t));
    if (l->desc->get_descriptor(&uuid, d) != 0) {
        char s[40];
        uuidToString(&uuid, s, 40);
        ALOGW("Error querying effect %s on lib %s", s, l->name);
        free(d);
        return -EINVAL;
    }
#if (LOG_NDEBUG==0)
    char s[512];
    dumpEffectDescriptor(d, s, sizeof(s), 0 /* indent */);
    ALOGV("loadEffect() read descriptor %p:%s",d, s);
#endif
    if (EFFECT_API_VERSION_MAJOR(d->apiVersion) !=
            EFFECT_API_VERSION_MAJOR(EFFECT_CONTROL_API_VERSION)) {
        ALOGW("Bad API version %08x on lib %s", d->apiVersion, l->name);
        free(d);
        return -EINVAL;
    }
    e = malloc(sizeof(list_elem_t));
    e->object = d;
    if (skip) {
        e->next = gSkippedEffects;
        gSkippedEffects = e;
        return -EINVAL;
    } else {
        e->next = l->effects;
        l->effects = e;
    }

    // After the UUID node in the config_tree, if node->next is valid,
    // that would be sub effect node.
    // Find the sub effects and add them to the gSubEffectList
    node = node->next;
    int count = 2;
    bool hwSubefx = false, swSubefx = false;
    list_sub_elem_t *sube = NULL;
    if (node != NULL) {
        ALOGV("Adding the effect to gEffectSubList as there are sub effects");
        sube = malloc(sizeof(list_sub_elem_t));
        sube->object = d;
        sube->sub_elem = NULL;
        sube->next = gSubEffectList;
        gSubEffectList = sube;
    }
    while (node != NULL && count) {
       if (addSubEffect(node)) {
           ALOGW("loadEffect() could not add subEffect %s", node->value);
           // Change the gSubEffectList to point to older list;
           gSubEffectList = sube->next;
           free(sube->sub_elem);// Free an already added sub effect
           sube->sub_elem = NULL;
           free(sube);
           return -ENOENT;
       }
       sub_effect_entry_t *subEntry = (sub_effect_entry_t*)gSubEffectList->sub_elem->object;
       effect_descriptor_t *subEffectDesc = (effect_descriptor_t*)(subEntry->object);
       // Since we return a stub descriptor for the proxy during
       // get_descriptor call,we replace it with the correspoding
       // sw effect descriptor, but with Proxy UUID
       // check for Sw desc
        if (!((subEffectDesc->flags & EFFECT_FLAG_HW_ACC_MASK) ==
                                           EFFECT_FLAG_HW_ACC_TUNNEL)) {
             swSubefx = true;
             *d = *subEffectDesc;
             d->uuid = uuid;
             ALOGV("loadEffect() Changed the Proxy desc");
       } else
           hwSubefx = true;
       count--;
       node = node->next;
    }
    // 1 HW and 1 SW sub effect found. Set the offload flag in the Proxy desc
    if (hwSubefx && swSubefx) {
        d->flags |= EFFECT_FLAG_OFFLOAD_SUPPORTED;
    }
    return 0;
}

lib_entry_t *getLibrary(const char *name)
{
    list_elem_t *e;

    if (gCachedLibrary &&
            !strncmp(gCachedLibrary->name, name, PATH_MAX)) {
        return gCachedLibrary;
    }

    e = gLibraryList;
    while (e) {
        lib_entry_t *l = (lib_entry_t *)e->object;
        if (!strcmp(l->name, name)) {
            gCachedLibrary = l;
            return l;
        }
        e = e->next;
    }

    return NULL;
}
+0 −38
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef ANDROID_EFFECTSCONFIGLOADER_H
#define ANDROID_EFFECTSCONFIGLOADER_H

#include <cutils/compiler.h>
#include "EffectsFactoryState.h"

#ifdef  __cplusplus
extern "C" {
#endif


/** Parses the platform effect configuration
 * and stores its content in the global EffectFactoryState. */
ANDROID_API
int EffectLoadEffectConfig();


#ifdef  __cplusplus
} // extern "C"
#endif

#endif  // ANDROID_EFFECTSCONFIGLOADER_H
Loading