Revert "Deprecate support for legacy effect config file audio_effects.conf"

This reverts commit c11621e64e3a009fe88a8a3ba1dffab5d9828601.

Reason for revert: The legacy effect config parsing logic will be kept in the framework for now, but we will add metrics to track any possible partner usage of the config file.

Change-Id: I873e2e18924688df52c9ed761950f132d16dcc29
diff --git a/media/libeffects/factory/Android.bp b/media/libeffects/factory/Android.bp
index f56abbd..d94093e 100644
--- a/media/libeffects/factory/Android.bp
+++ b/media/libeffects/factory/Android.bp
@@ -21,6 +21,7 @@
     vendor: true,
     srcs: [
          "EffectsFactory.c",
+         "EffectsConfigLoader.c",
          "EffectsFactoryState.c",
          "EffectsXmlConfigLoader.cpp",
     ],
diff --git a/media/libeffects/factory/EffectsConfigLoader.c b/media/libeffects/factory/EffectsConfigLoader.c
new file mode 100644
index 0000000..e23530e
--- /dev/null
+++ b/media/libeffects/factory/EffectsConfigLoader.c
@@ -0,0 +1,439 @@
+/*
+ * 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;
+}
diff --git a/media/libeffects/factory/EffectsConfigLoader.h b/media/libeffects/factory/EffectsConfigLoader.h
new file mode 100644
index 0000000..3f82609
--- /dev/null
+++ b/media/libeffects/factory/EffectsConfigLoader.h
@@ -0,0 +1,38 @@
+/*
+ * 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
diff --git a/media/libeffects/factory/EffectsFactory.c b/media/libeffects/factory/EffectsFactory.c
index 38ba4b0..dcdf634 100644
--- a/media/libeffects/factory/EffectsFactory.c
+++ b/media/libeffects/factory/EffectsFactory.c
@@ -26,6 +26,7 @@
 
 #include <media/EffectsFactoryApi.h>
 
+#include "EffectsConfigLoader.h"
 #include "EffectsFactoryState.h"
 #include "EffectsXmlConfigLoader.h"
 
@@ -463,7 +464,8 @@
     } else {
         gConfigNbElemSkipped = EffectLoadXmlEffectConfig(NULL);
         if (gConfigNbElemSkipped < 0) {
-            ALOGE("Failed to load XML effect configuration with status %zd", gConfigNbElemSkipped);
+            ALOGW("Failed to load XML effect configuration, fallback to .conf");
+            EffectLoadEffectConfig();
         } else if (gConfigNbElemSkipped > 0) {
             ALOGE("Effect config is partially invalid, skipped %zd elements", gConfigNbElemSkipped);
         }
diff --git a/media/libeffects/factory/EffectsXmlConfigLoader.cpp b/media/libeffects/factory/EffectsXmlConfigLoader.cpp
index 10fda70..30a9007 100644
--- a/media/libeffects/factory/EffectsXmlConfigLoader.cpp
+++ b/media/libeffects/factory/EffectsXmlConfigLoader.cpp
@@ -26,6 +26,7 @@
 
 #include <media/EffectsConfig.h>
 
+#include "EffectsConfigLoader.h"
 #include "EffectsFactoryState.h"
 #include "EffectsXmlConfigLoader.h"
 
diff --git a/media/libeffects/factory/test/DumpConfig.cpp b/media/libeffects/factory/test/DumpConfig.cpp
index 1fecf06..0a156b4 100644
--- a/media/libeffects/factory/test/DumpConfig.cpp
+++ b/media/libeffects/factory/test/DumpConfig.cpp
@@ -16,31 +16,48 @@
 
 #include <media/EffectsFactoryApi.h>
 #include <unistd.h>
-
 #include "EffectsXmlConfigLoader.h"
+#include "EffectsConfigLoader.h"
 
 int main(int argc, char* argv[]) {
-    char* path = nullptr;
-    if ((argc == 2 || argc == 3) && strcmp(argv[1], "--xml") == 0) {
+    const char* path = nullptr;
+    bool legacyFormat;
+
+    if (argc == 2 && strcmp(argv[1], "--legacy") == 0) {
+        legacyFormat = true;
+        fprintf(stderr, "Dumping legacy effect config file\n");
+    } else if ((argc == 2 || argc == 3) && strcmp(argv[1], "--xml") == 0) {
+        legacyFormat = false;
         if (argc == 3) {
-            path = argv[2];
             fprintf(stderr, "Dumping XML effect config file: %s\n", path);
         } else {
             fprintf(stderr, "Dumping default XML effect config file.\n");
         }
     } else {
-        fprintf(stderr, "Invalid arguments.\nUsage: %s [--xml [FILE]]\n", argv[0]);
+        fprintf(stderr, "Invalid arguments.\n"
+                        "Usage: %s [--legacy|--xml [FILE]]\n", argv[0]);
         return 1;
     }
 
-    ssize_t ret = EffectLoadXmlEffectConfig(path);
-    if (ret < 0) {
-        fprintf(stderr, "loadXmlEffectConfig failed, see logcat for detail.\n");
-        return 2;
+    if (!legacyFormat) {
+        ssize_t ret = EffectLoadXmlEffectConfig(path);
+        if (ret < 0) {
+            fprintf(stderr, "loadXmlEffectConfig failed, see logcat for detail.\n");
+            return 2;
+        }
+        if (ret > 0) {
+            fprintf(stderr, "Partially failed to load config. Skipped %zu elements, "
+                    "see logcat for detail.\n", (size_t)ret);
+        }
     }
-    if (ret > 0) {
-        fprintf(stderr, "Partially failed to load config. Skipped %zu elements, "
-                "see logcat for detail.\n", (size_t)ret);
+
+    if (legacyFormat) {
+        auto ret = EffectLoadEffectConfig();
+        if (ret < 0) {
+            fprintf(stderr, "loadEffectConfig failed, see logcat for detail.\n");
+            return 3;
+        }
+        fprintf(stderr, "legacy loadEffectConfig has probably succeed, see logcat to make sure.\n");
     }
 
     if (EffectDumpEffects(STDOUT_FILENO) != 0) {
diff --git a/services/audiopolicy/service/AudioPolicyEffects.cpp b/services/audiopolicy/service/AudioPolicyEffects.cpp
index 4ea3751..b111865 100644
--- a/services/audiopolicy/service/AudioPolicyEffects.cpp
+++ b/services/audiopolicy/service/AudioPolicyEffects.cpp
@@ -48,7 +48,13 @@
         mDefaultDeviceEffectFuture =
                 std::async(std::launch::async, &AudioPolicyEffects::initDefaultDeviceEffects, this);
     } else if (loadResult < 0) {
-        ALOGE("Failed to query effect configuration with status %d", loadResult);
+        ALOGW("Failed to query effect configuration, fallback to load .conf");
+        // load automatic audio effect modules
+        if (access(AUDIO_EFFECT_VENDOR_CONFIG_FILE, R_OK) == 0) {
+            loadAudioEffectConfigLegacy(AUDIO_EFFECT_VENDOR_CONFIG_FILE);
+        } else if (access(AUDIO_EFFECT_DEFAULT_CONFIG_FILE, R_OK) == 0) {
+            loadAudioEffectConfigLegacy(AUDIO_EFFECT_DEFAULT_CONFIG_FILE);
+        }
     } else if (loadResult > 0) {
         ALOGE("Effect config is partially invalid, skipped %d elements", loadResult);
     }
@@ -949,6 +955,34 @@
     return skippedElements;
 }
 
+status_t AudioPolicyEffects::loadAudioEffectConfigLegacy(const char *path)
+{
+    cnode *root;
+    char *data;
+
+    data = (char *)load_file(path, NULL);
+    if (data == NULL) {
+        return -ENODEV;
+    }
+    root = config_node("", "");
+    config_load(root, data);
+
+    Vector <EffectDesc *> effects;
+    loadEffects(root, effects);
+    loadInputEffectConfigurations(root, effects);
+    loadStreamEffectConfigurations(root, effects);
+
+    for (size_t i = 0; i < effects.size(); i++) {
+        delete effects[i];
+    }
+
+    config_free(root);
+    free(root);
+    free(data);
+
+    return NO_ERROR;
+}
+
 void AudioPolicyEffects::initDefaultDeviceEffects()
 {
     Mutex::Autolock _l(mLock);
diff --git a/services/audiopolicy/service/AudioPolicyEffects.h b/services/audiopolicy/service/AudioPolicyEffects.h
index 80b0f91..9f65a96 100644
--- a/services/audiopolicy/service/AudioPolicyEffects.h
+++ b/services/audiopolicy/service/AudioPolicyEffects.h
@@ -39,7 +39,12 @@
  *
  * This class manages all effects attached to input and output streams in AudioPolicyService.
  * The effect configurations can be queried in several ways:
- * With HIDL HAL, the configuration file `audio_effects.xml` will be loaded by libAudioHal.
+ *
+ * With HIDL HAL, the configuration file `audio_effects.xml` will be loaded by libAudioHal. If this
+ * file does not exist, AudioPolicyEffects class will fallback to load configuration from
+ * `/vendor/etc/audio_effects.conf` (AUDIO_EFFECT_VENDOR_CONFIG_FILE). If this file also does not
+ * exist, the configuration will be loaded from the file `/system/etc/audio_effects.conf`.
+ *
  * With AIDL HAL, the configuration will be queried with the method `IFactory::queryProcessing()`.
  */
 class AudioPolicyEffects : public RefBase
@@ -47,7 +52,7 @@
 
 public:
 
-    // The constructor will parse audio_effects.xml
+    // The constructor will parse audio_effects.conf
     // First it will look whether vendor specific file exists,
     // otherwise it will parse the system default file.
     explicit AudioPolicyEffects(const sp<EffectsFactoryHalInterface>& effectsFactoryHal);
@@ -116,7 +121,7 @@
     void initDefaultDeviceEffects();
 
     // class to store the description of an effects and its parameters
-    // as defined in audio_effects.xml
+    // as defined in audio_effects.conf
     class EffectDesc {
     public:
         EffectDesc(const char *name,
@@ -230,7 +235,8 @@
     static const char *kStreamNames[AUDIO_STREAM_PUBLIC_CNT+1]; //+1 required as streams start from -1
     audio_stream_type_t streamNameToEnum(const char *name);
 
-    // Parse audio_effects.xml
+    // Parse audio_effects.conf
+    status_t loadAudioEffectConfigLegacy(const char *path);
     status_t loadAudioEffectConfig(const sp<EffectsFactoryHalInterface>& effectsFactoryHal);
 
     // Load all effects descriptors in configuration file
diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index 6cac9f9..4710a8a 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -1072,7 +1072,7 @@
     Mutex mNotificationClientsLock;
     DefaultKeyedVector<int64_t, sp<NotificationClient>> mNotificationClients
         GUARDED_BY(mNotificationClientsLock);
-    // Manage all effects configured in audio_effects.xml
+    // Manage all effects configured in audio_effects.conf
     // never hold AudioPolicyService::mLock when calling AudioPolicyEffects methods as
     // those can call back into AudioPolicyService methods and try to acquire the mutex
     sp<AudioPolicyEffects> mAudioPolicyEffects GUARDED_BY(mLock);