First submission of audio effect library from NXP software.

This CL contains the first open sourceable version of the audio effect library from NXP software.
The effects implemented are:
- Bass boost
- Virtualizer (stereo widening)
- Equalizer
- Spectrum analyzer

Source file for the effect engines are located under libeffects/lvm/lib
The wrapper implementing the interface with the audio effect framework in under libeffects/lvm/wrapper

The code of other effect libraries has also been reorganized fo clarity:
- the effect factory is now under libeffects/factory
- the test equalizer and reverb effects are under libeffect/testlibs
- the visualizer is under libeffects/virtualizer

Change-Id: I8d91e2181f81b89f8fc0c1e1e6bf552c5809b2eb
diff --git a/media/libeffects/factory/Android.mk b/media/libeffects/factory/Android.mk
new file mode 100644
index 0000000..20f58e5
--- /dev/null
+++ b/media/libeffects/factory/Android.mk
@@ -0,0 +1,25 @@
+LOCAL_PATH:= $(call my-dir)
+
+# Effect factory library
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+	EffectsFactory.c
+
+LOCAL_SHARED_LIBRARIES := \
+	libcutils
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)
+LOCAL_MODULE:= libeffects
+
+ifeq ($(TARGET_OS)-$(TARGET_SIMULATOR),linux-true)
+LOCAL_LDLIBS += -ldl
+endif
+
+ifneq ($(TARGET_SIMULATOR),true)
+LOCAL_SHARED_LIBRARIES += libdl
+endif
+
+LOCAL_C_INCLUDES := \
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libeffects/factory/EffectsFactory.c b/media/libeffects/factory/EffectsFactory.c
new file mode 100644
index 0000000..edd6184
--- /dev/null
+++ b/media/libeffects/factory/EffectsFactory.c
@@ -0,0 +1,642 @@
+/*
+ * Copyright (C) 2010 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 "EffectsFactory"
+//#define LOG_NDEBUG 0
+
+#include "EffectsFactory.h"
+#include <string.h>
+#include <stdlib.h>
+#include <dlfcn.h>
+
+
+static list_elem_t *gEffectList; // list of effect_entry_t: all currently created effects
+static list_elem_t *gLibraryList; // list of lib_entry_t: all currently loaded libraries
+static pthread_mutex_t gLibLock = PTHREAD_MUTEX_INITIALIZER; // controls access to gLibraryList
+static uint32_t gNumEffects;         // total number number of effects
+static list_elem_t *gCurLib;    // current library in enumeration process
+static list_elem_t *gCurEffect; // current effect in enumeration process
+static uint32_t gCurEffectIdx;       // current effect index in enumeration process
+
+static const char * const gEffectLibPath = "/system/lib/soundfx"; // path to built-in effect libraries
+static int gInitDone; // true is global initialization has been preformed
+static int gNextLibId; // used by loadLibrary() to allocate unique library handles
+static int gCanQueryEffect; // indicates that call to EffectQueryEffect() is valid, i.e. that the list of effects
+                          // was not modified since last call to EffectQueryNumberEffects()
+
+/////////////////////////////////////////////////
+//      Local functions prototypes
+/////////////////////////////////////////////////
+
+static int init();
+static int loadLibrary(const char *libPath, int *handle);
+static int unloadLibrary(int handle);
+static void resetEffectEnumeration();
+static uint32_t updateNumEffects();
+static int findEffect(effect_uuid_t *uuid, lib_entry_t **lib, effect_descriptor_t **desc);
+static void dumpEffectDescriptor(effect_descriptor_t *desc, char *str, size_t len);
+
+/////////////////////////////////////////////////
+//      Effect Control Interface functions
+/////////////////////////////////////////////////
+
+int Effect_Process(effect_interface_t self, audio_buffer_t *inBuffer, audio_buffer_t *outBuffer)
+{
+    int ret = init();
+    if (ret < 0) {
+        return ret;
+    }
+    effect_entry_t *fx = (effect_entry_t *)self;
+    pthread_mutex_lock(&gLibLock);
+    if (fx->lib == NULL) {
+        pthread_mutex_unlock(&gLibLock);
+        return -EPIPE;
+    }
+    pthread_mutex_lock(&fx->lib->lock);
+    pthread_mutex_unlock(&gLibLock);
+
+    ret = (*fx->subItfe)->process(fx->subItfe, inBuffer, outBuffer);
+    pthread_mutex_unlock(&fx->lib->lock);
+    return ret;
+}
+
+int Effect_Command(effect_interface_t self, int cmdCode, int cmdSize, void *pCmdData, int *replySize, void *pReplyData)
+{
+    int ret = init();
+    if (ret < 0) {
+        return ret;
+    }
+    effect_entry_t *fx = (effect_entry_t *)self;
+    pthread_mutex_lock(&gLibLock);
+    if (fx->lib == NULL) {
+        pthread_mutex_unlock(&gLibLock);
+        return -EPIPE;
+    }
+    pthread_mutex_lock(&fx->lib->lock);
+    pthread_mutex_unlock(&gLibLock);
+
+    ret = (*fx->subItfe)->command(fx->subItfe, cmdCode, cmdSize, pCmdData, replySize, pReplyData);
+    pthread_mutex_unlock(&fx->lib->lock);
+    return ret;
+}
+
+const struct effect_interface_s gInterface = {
+        Effect_Process,
+        Effect_Command
+};
+
+/////////////////////////////////////////////////
+//      Effect Factory Interface functions
+/////////////////////////////////////////////////
+
+int EffectQueryNumberEffects(uint32_t *pNumEffects)
+{
+    int ret = init();
+    if (ret < 0) {
+        return ret;
+    }
+    if (pNumEffects == NULL) {
+        return -EINVAL;
+    }
+
+    pthread_mutex_lock(&gLibLock);
+    *pNumEffects = gNumEffects;
+    gCanQueryEffect = 1;
+    pthread_mutex_unlock(&gLibLock);
+    LOGV("EffectQueryNumberEffects(): %d", *pNumEffects);
+    return ret;
+}
+
+int EffectQueryEffect(uint32_t index, effect_descriptor_t *pDescriptor)
+{
+    int ret = init();
+    if (ret < 0) {
+        return ret;
+    }
+    if (pDescriptor == NULL ||
+        index >= gNumEffects) {
+        return -EINVAL;
+    }
+    if (gCanQueryEffect == 0) {
+        return -ENOSYS;
+    }
+
+    pthread_mutex_lock(&gLibLock);
+    ret = -ENOENT;
+    if (index < gCurEffectIdx) {
+        resetEffectEnumeration();
+    }
+    while (gCurLib) {
+        if (gCurEffect) {
+            if (index == gCurEffectIdx) {
+                memcpy(pDescriptor, gCurEffect->object, sizeof(effect_descriptor_t));
+                ret = 0;
+                break;
+            } else {
+                gCurEffect = gCurEffect->next;
+                gCurEffectIdx++;
+            }
+        } else {
+            gCurLib = gCurLib->next;
+            gCurEffect = ((lib_entry_t *)gCurLib->object)->effects;
+        }
+    }
+
+#if (LOG_NDEBUG == 0)
+    char str[256];
+    dumpEffectDescriptor(pDescriptor, str, 256);
+    LOGV("EffectQueryEffect() desc:%s", str);
+#endif
+    pthread_mutex_unlock(&gLibLock);
+    return ret;
+}
+
+int EffectGetDescriptor(effect_uuid_t *uuid, effect_descriptor_t *pDescriptor)
+{
+    lib_entry_t *l = NULL;
+    effect_descriptor_t *d = NULL;
+
+    int ret = init();
+    if (ret < 0) {
+        return ret;
+    }
+    if (pDescriptor == NULL || uuid == NULL) {
+        return -EINVAL;
+    }
+    pthread_mutex_lock(&gLibLock);
+    ret = findEffect(uuid, &l, &d);
+    if (ret == 0) {
+        memcpy(pDescriptor, d, sizeof(effect_descriptor_t));
+    }
+    pthread_mutex_unlock(&gLibLock);
+    return ret;
+}
+
+int EffectCreate(effect_uuid_t *uuid, int32_t sessionId, int32_t ioId, effect_interface_t *pInterface)
+{
+    list_elem_t *e = gLibraryList;
+    lib_entry_t *l = NULL;
+    effect_descriptor_t *d = NULL;
+    effect_interface_t itfe;
+    effect_entry_t *fx;
+    int found = 0;
+    int ret;
+
+    if (uuid == NULL || pInterface == NULL) {
+        return -EINVAL;
+    }
+
+    LOGV("EffectCreate() UUID: %08X-%04X-%04X-%04X-%02X%02X%02X%02X%02X%02X\n",
+            uuid->timeLow, uuid->timeMid, uuid->timeHiAndVersion,
+            uuid->clockSeq, uuid->node[0], uuid->node[1],uuid->node[2],
+            uuid->node[3],uuid->node[4],uuid->node[5]);
+
+    ret = init();
+
+    if (ret < 0) {
+        LOGW("EffectCreate() init error: %d", ret);
+        return ret;
+    }
+
+    pthread_mutex_lock(&gLibLock);
+
+    ret = findEffect(uuid, &l, &d);
+    if (ret < 0){
+        goto exit;
+    }
+
+    // create effect in library
+    ret = l->createFx(uuid, sessionId, ioId, &itfe);
+    if (ret != 0) {
+        LOGW("EffectCreate() library %s: could not create fx %s, error %d", l->path, d->name, ret);
+        goto exit;
+    }
+
+    // add entry to effect list
+    fx = (effect_entry_t *)malloc(sizeof(effect_entry_t));
+    fx->subItfe = itfe;
+    fx->itfe = (struct effect_interface_s *)&gInterface;
+    fx->lib = l;
+
+    e = (list_elem_t *)malloc(sizeof(list_elem_t));
+    e->object = fx;
+    e->next = gEffectList;
+    gEffectList = e;
+
+    *pInterface = (effect_interface_t)fx;
+
+    LOGV("EffectCreate() created entry %p with sub itfe %p in library %s", *pInterface, itfe, l->path);
+
+exit:
+    pthread_mutex_unlock(&gLibLock);
+    return ret;
+}
+
+int EffectRelease(effect_interface_t interface)
+{
+    effect_entry_t *fx;
+    list_elem_t *e1;
+    list_elem_t *e2;
+
+    int ret = init();
+    if (ret < 0) {
+        return ret;
+    }
+
+    // remove effect from effect list
+    pthread_mutex_lock(&gLibLock);
+    e1 = gEffectList;
+    e2 = NULL;
+    while (e1) {
+        if (e1->object == interface) {
+            if (e2) {
+                e2->next = e1->next;
+            } else {
+                gEffectList = e1->next;
+            }
+            fx = (effect_entry_t *)e1->object;
+            free(e1);
+            break;
+        }
+        e2 = e1;
+        e1 = e1->next;
+    }
+    if (e1 == NULL) {
+        ret = -ENOENT;
+        goto exit;
+    }
+
+    // release effect in library
+    if (fx->lib == NULL) {
+        LOGW("EffectRelease() fx %p library already unloaded", interface);
+    } else {
+        pthread_mutex_lock(&fx->lib->lock);
+        fx->lib->releaseFx(fx->subItfe);
+        pthread_mutex_unlock(&fx->lib->lock);
+    }
+    free(fx);
+
+exit:
+    pthread_mutex_unlock(&gLibLock);
+    return ret;
+}
+
+int EffectLoadLibrary(const char *libPath, int *handle)
+{
+    int ret = init();
+    if (ret < 0) {
+        return ret;
+    }
+    if (libPath == NULL) {
+        return -EINVAL;
+    }
+
+    ret = loadLibrary(libPath, handle);
+    updateNumEffects();
+    return ret;
+}
+
+int EffectUnloadLibrary(int handle)
+{
+    int ret = init();
+    if (ret < 0) {
+        return ret;
+    }
+
+    ret = unloadLibrary(handle);
+    updateNumEffects();
+    return ret;
+}
+
+int EffectIsNullUuid(effect_uuid_t *uuid)
+{
+    if (memcmp(uuid, EFFECT_UUID_NULL, sizeof(effect_uuid_t))) {
+        return 0;
+    }
+    return 1;
+}
+
+/////////////////////////////////////////////////
+//      Local functions
+/////////////////////////////////////////////////
+
+int init() {
+    struct dirent *ent;
+    DIR *dir = NULL;
+    char libpath[PATH_MAX];
+    int hdl;
+
+    if (gInitDone) {
+        return 0;
+    }
+
+    pthread_mutex_init(&gLibLock, NULL);
+
+    // load built-in libraries
+    dir = opendir(gEffectLibPath);
+    if (dir == NULL) {
+        return -ENODEV;
+    }
+    while ((ent = readdir(dir)) != NULL) {
+        LOGV("init() reading file %s", ent->d_name);
+        if ((strlen(ent->d_name) < 3) ||
+            strncmp(ent->d_name, "lib", 3) != 0 ||
+            strncmp(ent->d_name + strlen(ent->d_name) - 3, ".so", 3) != 0) {
+            continue;
+        }
+        strcpy(libpath, gEffectLibPath);
+        strcat(libpath, "/");
+        strcat(libpath, ent->d_name);
+        if (loadLibrary(libpath, &hdl) < 0) {
+            LOGW("init() failed to load library %s",libpath);
+        }
+    }
+    closedir(dir);
+    updateNumEffects();
+    gInitDone = 1;
+    LOGV("init() done");
+    return 0;
+}
+
+
+int loadLibrary(const char *libPath, int *handle)
+{
+    void *hdl;
+    effect_QueryNumberEffects_t queryNumFx;
+    effect_QueryEffect_t queryFx;
+    effect_CreateEffect_t createFx;
+    effect_ReleaseEffect_t releaseFx;
+    uint32_t numFx;
+    uint32_t fx;
+    int ret;
+    list_elem_t *e, *descHead = NULL;
+    lib_entry_t *l;
+
+    if (handle == NULL) {
+        return -EINVAL;
+    }
+
+    *handle = 0;
+
+    hdl = dlopen(libPath, RTLD_NOW);
+    if (hdl == 0) {
+        LOGW("could open lib %s", libPath);
+        return -ENODEV;
+    }
+
+    // Check functions availability
+    queryNumFx = (effect_QueryNumberEffects_t)dlsym(hdl, "EffectQueryNumberEffects");
+    if (queryNumFx == NULL) {
+        LOGW("could not get EffectQueryNumberEffects from lib %s", libPath);
+        ret = -ENODEV;
+        goto error;
+    }
+    queryFx = (effect_QueryEffect_t)dlsym(hdl, "EffectQueryEffect");
+    if (queryFx == NULL) {
+        LOGW("could not get EffectQueryEffect from lib %s", libPath);
+        ret = -ENODEV;
+        goto error;
+    }
+    createFx = (effect_CreateEffect_t)dlsym(hdl, "EffectCreate");
+    if (createFx == NULL) {
+        LOGW("could not get EffectCreate from lib %s", libPath);
+        ret = -ENODEV;
+        goto error;
+    }
+    releaseFx = (effect_ReleaseEffect_t)dlsym(hdl, "EffectRelease");
+    if (releaseFx == NULL) {
+        LOGW("could not get EffectRelease from lib %s", libPath);
+        ret = -ENODEV;
+        goto error;
+    }
+
+    // load effect descriptors
+    ret = queryNumFx(&numFx);
+    if (ret) {
+        goto error;
+    }
+
+    for (fx = 0; fx < numFx; fx++) {
+        effect_descriptor_t *d = malloc(sizeof(effect_descriptor_t));
+        if (d == NULL) {
+            ret = -ENOMEM;
+            goto error;
+        }
+        ret = queryFx(fx, d);
+        if (ret == 0) {
+#if (LOG_NDEBUG==0)
+            char s[256];
+            dumpEffectDescriptor(d, s, 256);
+            LOGV("loadLibrary() read descriptor %p:%s",d, s);
+#endif
+            if (d->apiVersion != EFFECT_API_VERSION) {
+                LOGW("Bad API version %04x on lib %s", d->apiVersion, libPath);
+                free(d);
+                continue;
+            }
+            e = malloc(sizeof(list_elem_t));
+            if (e == NULL) {
+                free(d);
+                ret = -ENOMEM;
+                goto error;
+            }
+            e->object = d;
+            e->next = descHead;
+            descHead = e;
+        } else {
+            LOGW("Error querying effect # %d on lib %s", fx, libPath);
+        }
+    }
+
+    pthread_mutex_lock(&gLibLock);
+
+    // add entry for library in gLibraryList
+    l = malloc(sizeof(lib_entry_t));
+    l->id = ++gNextLibId;
+    l->handle = hdl;
+    strncpy(l->path, libPath, PATH_MAX);
+    l->createFx = createFx;
+    l->releaseFx = releaseFx;
+    l->effects = descHead;
+    pthread_mutex_init(&l->lock, NULL);
+
+    e = malloc(sizeof(list_elem_t));
+    e->next = gLibraryList;
+    e->object = l;
+    gLibraryList = e;
+    pthread_mutex_unlock(&gLibLock);
+    LOGV("loadLibrary() linked library %p", l);
+
+    *handle = l->id;
+
+    return 0;
+
+error:
+    LOGW("loadLibrary() error: %d on lib: %s", ret, libPath);
+    while (descHead) {
+        free(descHead->object);
+        e = descHead->next;
+        free(descHead);
+        descHead = e;;
+    }
+    dlclose(hdl);
+    return ret;
+}
+
+int unloadLibrary(int handle)
+{
+    void *hdl;
+    int ret;
+    list_elem_t *el1, *el2;
+    lib_entry_t *l;
+    effect_entry_t *fx;
+
+    pthread_mutex_lock(&gLibLock);
+    el1 = gLibraryList;
+    el2 = NULL;
+    while (el1) {
+        l = (lib_entry_t *)el1->object;
+        if (handle == l->id) {
+            if (el2) {
+                el2->next = el1->next;
+            } else {
+                gLibraryList = el1->next;
+            }
+            free(el1);
+            break;
+        }
+        el2 = el1;
+        el1 = el1->next;
+    }
+    pthread_mutex_unlock(&gLibLock);
+    if (el1 == NULL) {
+        return -ENOENT;
+    }
+
+    // clear effect descriptor list
+    el1 = l->effects;
+    while (el1) {
+        free(el1->object);
+        el2 = el1->next;
+        free(el1);
+        el1 = el2;
+    }
+
+    // disable all effects from this library
+    pthread_mutex_lock(&l->lock);
+
+    el1 = gEffectList;
+    while (el1) {
+        fx = (effect_entry_t *)el1->object;
+        if (fx->lib == l) {
+            fx->lib = NULL;
+        }
+        el1 = el1->next;
+    }
+    pthread_mutex_unlock(&l->lock);
+
+    dlclose(l->handle);
+    free(l);
+    return 0;
+}
+
+void resetEffectEnumeration()
+{
+    gCurLib = gLibraryList;
+    gCurEffect = NULL;
+    if (gCurLib) {
+        gCurEffect = ((lib_entry_t *)gCurLib->object)->effects;
+    }
+    gCurEffectIdx = 0;
+}
+
+uint32_t updateNumEffects() {
+    list_elem_t *e;
+    uint32_t cnt = 0;
+
+    resetEffectEnumeration();
+
+    e = gLibraryList;
+    while (e) {
+        lib_entry_t *l = (lib_entry_t *)e->object;
+        list_elem_t *efx = l->effects;
+        while (efx) {
+            cnt++;
+            efx = efx->next;
+        }
+        e = e->next;
+    }
+    gNumEffects = cnt;
+    gCanQueryEffect = 0;
+    return cnt;
+}
+
+int findEffect(effect_uuid_t *uuid, lib_entry_t **lib, effect_descriptor_t **desc)
+{
+    list_elem_t *e = gLibraryList;
+    lib_entry_t *l = NULL;
+    effect_descriptor_t *d = NULL;
+    int found = 0;
+    int ret = 0;
+
+    while (e && !found) {
+        l = (lib_entry_t *)e->object;
+        list_elem_t *efx = l->effects;
+        while (efx) {
+            d = (effect_descriptor_t *)efx->object;
+            if (memcmp(&d->uuid, uuid, sizeof(effect_uuid_t)) == 0) {
+                found = 1;
+                break;
+            }
+            efx = efx->next;
+        }
+        e = e->next;
+    }
+    if (!found) {
+        LOGV("findEffect() effect not found");
+        ret = -ENOENT;
+    } else {
+        LOGV("findEffect() found effect: %s in lib %s", d->name, l->path);
+        *lib = l;
+        *desc = d;
+    }
+
+    return ret;
+}
+
+void dumpEffectDescriptor(effect_descriptor_t *desc, char *str, size_t len) {
+    char s[256];
+
+    snprintf(str, len, "\nEffect Descriptor %p:\n", desc);
+    sprintf(s, "- UUID: %08X-%04X-%04X-%04X-%02X%02X%02X%02X%02X%02X\n",
+            desc->uuid.timeLow, desc->uuid.timeMid, desc->uuid.timeHiAndVersion,
+            desc->uuid.clockSeq, desc->uuid.node[0], desc->uuid.node[1],desc->uuid.node[2],
+            desc->uuid.node[3],desc->uuid.node[4],desc->uuid.node[5]);
+    strncat(str, s, len);
+    sprintf(s, "- TYPE: %08X-%04X-%04X-%04X-%02X%02X%02X%02X%02X%02X\n",
+                desc->type.timeLow, desc->type.timeMid, desc->type.timeHiAndVersion,
+                desc->type.clockSeq, desc->type.node[0], desc->type.node[1],desc->type.node[2],
+                desc->type.node[3],desc->type.node[4],desc->type.node[5]);
+    strncat(str, s, len);
+    sprintf(s, "- apiVersion: %04X\n- flags: %08X\n",
+            desc->apiVersion, desc->flags);
+    strncat(str, s, len);
+    sprintf(s, "- name: %s\n", desc->name);
+    strncat(str, s, len);
+    sprintf(s, "- implementor: %s\n", desc->implementor);
+    strncat(str, s, len);
+}
+
diff --git a/media/libeffects/factory/EffectsFactory.h b/media/libeffects/factory/EffectsFactory.h
new file mode 100644
index 0000000..8f543ca
--- /dev/null
+++ b/media/libeffects/factory/EffectsFactory.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2010 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_EFFECTSFACTORY_H_
+#define ANDROID_EFFECTSFACTORY_H_
+
+#include <cutils/log.h>
+#include <pthread.h>
+#include <dirent.h>
+#include <media/EffectsFactoryApi.h>
+
+
+#if __cplusplus
+extern "C" {
+#endif
+
+typedef struct list_elem_s {
+    void *object;
+    struct list_elem_s *next;
+} list_elem_t;
+
+typedef struct lib_entry_s {
+    char path[PATH_MAX];
+    void *handle;
+    int id;
+    effect_CreateEffect_t createFx;
+    effect_ReleaseEffect_t releaseFx;
+    list_elem_t *effects; //list of effect_descriptor_t
+    pthread_mutex_t lock;
+} lib_entry_t;
+
+typedef struct effect_entry_s {
+    struct effect_interface_s *itfe;
+    effect_interface_t subItfe;
+    lib_entry_t *lib;
+} effect_entry_t;
+
+#if __cplusplus
+}  // extern "C"
+#endif
+
+
+#endif /*ANDROID_EFFECTSFACTORY_H_*/