audio: Add support for multiple metainfo keys update

Add changes to read acdb metainfo key and module name from platform
info xml. Changes to add acdb key values to a list and query key value
based on module name.

CRs-Fixed: 1081424
Change-Id: Ia287a27c86f63fea16cdb35d553de6e2e853b4e9
diff --git a/hal/audio_extn/audio_extn.c b/hal/audio_extn/audio_extn.c
index d2e5434..fe6c9a4 100644
--- a/hal/audio_extn/audio_extn.c
+++ b/hal/audio_extn/audio_extn.c
@@ -762,7 +762,7 @@
     return ret;
 }
 
-void audio_extn_init(void)
+void audio_extn_init(struct audio_device *adev)
 {
     aextnmod.anc_enabled = 0;
     aextnmod.aanc_enabled = 0;
@@ -771,6 +771,8 @@
     aextnmod.hpx_enabled = 0;
     aextnmod.vbat_enabled = 0;
     aextnmod.hifi_audio_enabled = 0;
+
+    audio_extn_dolby_set_license(adev);
 }
 
 void audio_extn_set_parameters(struct audio_device *adev,
diff --git a/hal/audio_extn/audio_extn.h b/hal/audio_extn/audio_extn.h
index 9a2f825..6eb3f76 100644
--- a/hal/audio_extn/audio_extn.h
+++ b/hal/audio_extn/audio_extn.h
@@ -531,7 +531,7 @@
 void audio_extn_pm_unvote(void);
 #endif
 
-void audio_extn_init(void);
+void audio_extn_init(struct audio_device *adev);
 void audio_extn_utils_update_streams_cfg_lists(void *platform,
                                   struct mixer *mixer,
                                   struct listnode *streams_output_cfg_list,
diff --git a/hal/audio_extn/dolby.c b/hal/audio_extn/dolby.c
index b958bf6..fee0543 100644
--- a/hal/audio_extn/dolby.c
+++ b/hal/audio_extn/dolby.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011-2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
  * Not a Contribution.
  *
  * Copyright (C) 2010 The Android Open Source Project
@@ -445,7 +445,6 @@
 void audio_extn_dolby_set_license(struct audio_device *adev)
 {
     int ret, key=0;
-    char value[128] = {0};
     struct mixer_ctl *ctl;
     const char *mixer_ctl_name = "DS1 License";
 
@@ -456,9 +455,8 @@
         return;
     }
 
-    property_get("audio.ds1.metainfo.key",value,"0");
 #ifdef DOLBY_ACDB_LICENSE
-    key = atoi(value);
+    key = platform_get_meta_info_key_from_list(adev->platform, "dolby");
 #else
     key = 0;
 #endif
@@ -598,14 +596,12 @@
 void audio_extn_dolby_set_license(struct audio_device *adev __unused)
 {
     int i_key=0;
-    char c_key[128] = {0};
     char c_dmid[128] = {0};
     int i_dmid;
     struct dolby_param_license dolby_license;
 
 #ifdef DOLBY_ACDB_LICENSE
-    property_get("audio.ds1.metainfo.key",c_key,"0");
-    i_key = atoi(c_key);
+    i_key = platform_get_meta_info_key_from_list(adev->platform, "dolby");
 #else
     /* As ACDB based license mechanism is disabled, force set the license key to 0*/
     i_key = 0;
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index 71c05df..d7b5f3a 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -5069,7 +5069,7 @@
                                                         "visualizer_hal_stop_output");
         }
     }
-    audio_extn_init();
+    audio_extn_init(adev);
     audio_extn_listen_init(adev, adev->snd_card);
     audio_extn_sound_trigger_init(adev);
     audio_extn_gef_init(adev);
diff --git a/hal/msm8916/platform.c b/hal/msm8916/platform.c
index d9c7642..d4f9710 100644
--- a/hal/msm8916/platform.c
+++ b/hal/msm8916/platform.c
@@ -38,6 +38,8 @@
 #include "sound/msmcal-hwdep.h"
 #include <dirent.h>
 #include <linux/msm_audio.h>
+#include "linux/msm_audio_calibration.h"
+
 #define SOUND_TRIGGER_DEVICE_HANDSET_MONO_LOW_POWER_ACDB_ID (100)
 #define MAX_MIXER_XML_PATH  100
 #define MIXER_XML_PATH_QRD_SKUH "/system/etc/mixer_paths_qrd_skuh.xml"
@@ -212,6 +214,7 @@
 /* Audio calibration related functions */
 typedef void (*acdb_deallocate_t)();
 typedef int  (*acdb_init_t)(const char *, char *, int);
+typedef int  (*acdb_init_v3_t)(const char *, char *, struct listnode *);
 typedef void (*acdb_send_audio_cal_t)(int, int, int , int);
 typedef void (*acdb_send_voice_cal_t)(int, int);
 typedef int (*acdb_reload_vocvoltable_t)(int);
@@ -224,6 +227,7 @@
 typedef int (*acdb_set_codec_data_t) (void *, char *);
 typedef int (*acdb_reload_t) (char *, char *, char *, int);
 typedef int (*acdb_send_gain_dep_cal_t)(int, int, int, int, int);
+typedef int (*acdb_reload_v2_t) (char *, char *, char *, struct listnode *);
 
 typedef struct codec_backend_cfg {
     uint32_t sample_rate;
@@ -237,6 +241,12 @@
 static native_audio_prop na_props = {0, 0, 0};
 static bool supports_true_32_bit = false;
 
+struct meta_key_list {
+    struct listnode list;
+    struct audio_cal_info_metainfo cal_info;
+    char name[ACDB_METAINFO_KEY_MODULE_NAME_LEN];
+};
+
 struct platform_data {
     struct audio_device *adev;
     bool fluence_in_spkr_mode;
@@ -263,6 +273,7 @@
     void                       *acdb_handle;
     int                        voice_feature_set;
     acdb_init_t                acdb_init;
+    acdb_init_v3_t             acdb_init_v3;
     acdb_deallocate_t          acdb_deallocate;
     acdb_send_audio_cal_t      acdb_send_audio_cal;
     acdb_set_audio_cal_t       acdb_set_audio_cal;
@@ -273,6 +284,7 @@
     acdb_send_common_top_t     acdb_send_common_top;
     acdb_set_codec_data_t      acdb_set_codec_data;
     acdb_reload_t              acdb_reload;
+    acdb_reload_v2_t           acdb_reload_v2;
 #ifdef RECORD_PLAY_CONCURRENCY
     bool rec_play_conc_set;
 #endif
@@ -288,11 +300,11 @@
     int hw_dep_fd;
     char cvd_version[MAX_CVD_VERSION_STRING_SIZE];
     char snd_card_name[MAX_SND_CARD_STRING_SIZE];
-    int metainfo_key;
     int source_mic_type;
     int max_mic_count;
     bool is_dsd_supported;
     bool is_asrc_supported;
+    struct listnode acdb_meta_key_list;
 };
 
 static bool is_external_codec = false;
@@ -1631,10 +1643,12 @@
 {
     struct platform_data *my_data = (struct platform_data *)platform;
     char *cvd_version = NULL;
-    int key = 0;
     const char *snd_card_name, *acdb_snd_card_name;
-    int result;
-    char value[PROPERTY_VALUE_MAX];
+    int result = -1;
+    struct listnode *node;
+    struct meta_key_list *key_info;
+    int key = 0;
+
     cvd_version = calloc(1, MAX_CVD_VERSION_STRING_SIZE);
     if (!cvd_version) {
         ALOGE("Failed to allocate cvd version");
@@ -1643,19 +1657,23 @@
         get_cvd_version(cvd_version, my_data->adev);
     }
 
-    property_get("audio.ds1.metainfo.key",value,"0");
-    key = atoi(value);
     snd_card_name = mixer_get_name(my_data->adev->mixer);
     acdb_snd_card_name = get_snd_card_name_for_acdb_loader(snd_card_name);
 
-    result = my_data->acdb_init(acdb_snd_card_name, cvd_version, key);
-
+    if (my_data->acdb_init_v3) {
+        result = my_data->acdb_init_v3(acdb_snd_card_name, cvd_version,
+                                           &my_data->acdb_meta_key_list);
+    } else if (my_data->acdb_init) {
+        node = list_head(&my_data->acdb_meta_key_list);
+        key_info = node_to_item(node, struct meta_key_list, list);
+        key = key_info->cal_info.nKey;
+        result = my_data->acdb_init(acdb_snd_card_name, cvd_version, key);
+    }
     /* Save these variables in platform_data. These will be used
        while reloading ACDB files during run time. */
     strlcpy(my_data->cvd_version, cvd_version, MAX_CVD_VERSION_STRING_SIZE);
     strlcpy(my_data->snd_card_name, acdb_snd_card_name,
                                                MAX_SND_CARD_STRING_SIZE);
-    my_data->metainfo_key = key;
 
     if (cvd_version)
         free(cvd_version);
@@ -1940,6 +1958,16 @@
     if (ret || is_external_codec)
         my_data->hifi_audio = true;
 
+    list_init(&my_data->acdb_meta_key_list);
+
+    set_platform_defaults(my_data);
+
+    /* Initialize ACDB and PCM ID's */
+    if (is_external_codec)
+        platform_info_init(PLATFORM_INFO_XML_PATH_EXTCODEC, my_data);
+    else
+        platform_info_init(PLATFORM_INFO_XML_PATH, my_data);
+
     my_data->voice_feature_set = VOICE_FEATURE_SET_DEFAULT;
     my_data->acdb_handle = dlopen(LIB_ACDB_LOADER, RTLD_NOW);
     if (my_data->acdb_handle == NULL) {
@@ -2009,6 +2037,12 @@
             ALOGV("%s: Could not find the symbol acdb_loader_send_gain_dep_cal from %s",
                   __func__, LIB_ACDB_LOADER);
 
+        my_data->acdb_init_v3 = (acdb_init_v3_t)dlsym(my_data->acdb_handle,
+                                                    "acdb_loader_init_v3");
+        if (my_data->acdb_init_v3 == NULL) {
+            ALOGE("%s: dlsym error %s for acdb_loader_init_v3", __func__, dlerror());
+        }
+
         my_data->acdb_init = (acdb_init_t)dlsym(my_data->acdb_handle,
                                                     "acdb_loader_init_v2");
         if (my_data->acdb_init == NULL) {
@@ -2016,12 +2050,19 @@
             goto acdb_init_fail;
         }
 
+        my_data->acdb_reload_v2 = (acdb_reload_v2_t)dlsym(my_data->acdb_handle,
+                                                    "acdb_loader_reload_acdb_files_v2");
+        if (my_data->acdb_reload_v2 == NULL) {
+            ALOGE("%s: dlsym error %s for acdb_loader_reload_acdb_files_v2", __func__, dlerror());
+        }
+
         my_data->acdb_reload = (acdb_reload_t)dlsym(my_data->acdb_handle,
                                                     "acdb_loader_reload_acdb_files");
         if (my_data->acdb_reload == NULL) {
             ALOGE("%s: dlsym error %s for acdb_loader_reload_acdb_files", __func__, dlerror());
             goto acdb_init_fail;
         }
+
         platform_acdb_init(my_data);
     }
     audio_extn_pm_vote();
@@ -2035,14 +2076,6 @@
 
 acdb_init_fail:
 
-    set_platform_defaults(my_data);
-
-    /* Initialize ACDB and PCM ID's */
-    if (is_external_codec)
-        platform_info_init(PLATFORM_INFO_XML_PATH_EXTCODEC, my_data);
-    else
-        platform_info_init(PLATFORM_INFO_XML_PATH, my_data);
-
     if (audio_extn_can_use_ras()) {
         if (property_get_bool("persist.speaker.prot.enable", false)) {
             platform_set_snd_device_acdb_id(SND_DEVICE_OUT_SPEAKER_PROTECTED,
@@ -2075,8 +2108,6 @@
     /* init dap hal */
     audio_extn_dap_hal_init(adev->snd_card);
 
-    audio_extn_dolby_set_license(adev);
-
     /* init audio device arbitration */
     audio_extn_dev_arbi_init();
 
@@ -2497,6 +2528,45 @@
     return ret;
 }
 
+int platform_set_acdb_metainfo_key(void *platform, char *name, int key)
+{
+    struct meta_key_list *key_info;
+    struct platform_data *pdata = (struct platform_data *)platform;
+
+    key_info = (struct meta_key_list *)calloc(1, sizeof(struct meta_key_list));
+    if (!key_info) {
+        ALOGE("%s: Could not allocate memory for key %d", __func__, key);
+        return -ENOMEM;
+    }
+
+    key_info->cal_info.nKey = key;
+    strlcpy(key_info->name, name, sizeof(key_info->name));
+    list_add_tail(&pdata->acdb_meta_key_list, &key_info->list);
+    ALOGD("%s: successfully added module %s and key %d to the list", __func__,
+               key_info->name, key_info->cal_info.nKey);
+    return 0;
+}
+
+int platform_get_meta_info_key_from_list(void *platform, char *mod_name)
+{
+    struct listnode *node;
+    struct meta_key_list *key_info;
+    struct platform_data *pdata = (struct platform_data *)platform;
+    int key = 0;
+
+    ALOGV("%s: for module %s", __func__, mod_name);
+
+    list_for_each(node, &pdata->acdb_meta_key_list) {
+        key_info = node_to_item(node, struct meta_key_list, list);
+        if (strcmp(key_info->name, mod_name) == 0) {
+            key = key_info->cal_info.nKey;
+            ALOGD("%s: Found key %d for module %s", __func__, key, mod_name);
+            break;
+        }
+    }
+    return key;
+}
+
 int platform_get_default_app_type(void *platform)
 {
     struct platform_data *my_data = (struct platform_data *)platform;
@@ -4032,6 +4102,9 @@
     int len;
     int ret = 0, err;
     char *kv_pairs = NULL;
+    struct listnode *node;
+    struct meta_key_list *key_info;
+    int key = 0;
 
     kv_pairs = str_parms_to_str(parms);
     if(!kv_pairs)
@@ -4093,9 +4166,16 @@
     if (err >= 0) {
         str_parms_del(parms, AUDIO_PARAMETER_KEY_RELOAD_ACDB);
 
-        my_data->acdb_reload(value, my_data->snd_card_name,
-                              my_data->cvd_version, my_data->metainfo_key);
-
+        if (my_data->acdb_reload_v2) {
+            my_data->acdb_reload_v2(value, my_data->snd_card_name,
+                                  my_data->cvd_version, &my_data->acdb_meta_key_list);
+        } else if (my_data->acdb_reload) {
+            node = list_head(&my_data->acdb_meta_key_list);
+            key_info = node_to_item(node, struct meta_key_list, list);
+            key = key_info->cal_info.nKey;
+            my_data->acdb_reload(value, my_data->snd_card_name,
+                                  my_data->cvd_version, key);
+        }
     }
 
     if (hw_info_is_stereo_spkr(my_data->hw_info)) {
diff --git a/hal/msm8960/platform.c b/hal/msm8960/platform.c
index 31d86f4..0835329 100644
--- a/hal/msm8960/platform.c
+++ b/hal/msm8960/platform.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
  * Not a contribution.
  *
  * Copyright (C) 2013 The Android Open Source Project
@@ -1350,3 +1350,15 @@
 {
     return 0;
 }
+
+int platform_get_meta_info_key_from_list(void *platform __unused,
+                                         char *mod_name __unused)
+{
+    return 0;
+}
+
+int platform_set_acdb_metainfo_key(void *platform __unused, char *name __unused,
+                                   int key __unused)
+{
+    return 0;
+}
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index 74c429b..a73f13e 100755
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -190,6 +190,7 @@
 /* Audio calibration related functions */
 typedef void (*acdb_deallocate_t)();
 typedef int  (*acdb_init_t)(const char *, char *, int);
+typedef int  (*acdb_init_v3_t)(const char *, char *, struct listnode *);
 typedef void (*acdb_send_audio_cal_t)(int, int, int , int);
 typedef void (*acdb_send_voice_cal_t)(int, int);
 typedef int (*acdb_reload_vocvoltable_t)(int);
@@ -201,6 +202,7 @@
 typedef int (*acdb_send_common_top_t) (void);
 typedef int (*acdb_set_codec_data_t) (void *, char *);
 typedef int (*acdb_reload_t) (char *, char *, char *, int);
+typedef int (*acdb_reload_v2_t) (char *, char *, char *, struct listnode *);
 
 typedef struct codec_backend_cfg {
     uint32_t sample_rate;
@@ -215,6 +217,12 @@
 static bool supports_true_32_bit = false;
 typedef int (*acdb_send_gain_dep_cal_t)(int, int, int, int, int);
 
+struct meta_key_list {
+    struct listnode list;
+    struct audio_cal_info_metainfo cal_info;
+    char name[ACDB_METAINFO_KEY_MODULE_NAME_LEN];
+};
+
 struct platform_data {
     struct audio_device *adev;
     bool fluence_in_spkr_mode;
@@ -240,6 +248,7 @@
     void                       *acdb_handle;
     int                        voice_feature_set;
     acdb_init_t                acdb_init;
+    acdb_init_v3_t             acdb_init_v3;
     acdb_deallocate_t          acdb_deallocate;
     acdb_send_audio_cal_t      acdb_send_audio_cal;
     acdb_set_audio_cal_t       acdb_set_audio_cal;
@@ -250,6 +259,7 @@
     acdb_send_common_top_t     acdb_send_common_top;
     acdb_set_codec_data_t      acdb_set_codec_data;
     acdb_reload_t              acdb_reload;
+    acdb_reload_v2_t           acdb_reload_v2;
     void *hw_info;
     acdb_send_gain_dep_cal_t   acdb_send_gain_dep_cal;
     struct csd_data *csd;
@@ -262,11 +272,11 @@
     int hw_dep_fd;
     char cvd_version[MAX_CVD_VERSION_STRING_SIZE];
     char snd_card_name[MAX_SND_CARD_STRING_SIZE];
-    int metainfo_key;
     int source_mic_type;
     int max_mic_count;
     bool is_dsd_supported;
     bool is_asrc_supported;
+    struct listnode acdb_meta_key_list;
 };
 
 static int pcm_device_table[AUDIO_USECASE_MAX][2] = {
@@ -1419,10 +1429,12 @@
 {
     struct platform_data *my_data = (struct platform_data *)platform;
     char *cvd_version = NULL;
-    int key = 0;
     const char *snd_card_name;
-    int result;
-    char value[PROPERTY_VALUE_MAX];
+    int result = -1;
+    struct listnode *node;
+    struct meta_key_list *key_info;
+    int key = 0;
+
     cvd_version = calloc(1, MAX_CVD_VERSION_STRING_SIZE);
     if (!cvd_version) {
         ALOGE("Failed to allocate cvd version");
@@ -1431,17 +1443,22 @@
         get_cvd_version(cvd_version, my_data->adev);
     }
 
-    property_get("audio.ds1.metainfo.key",value,"0");
-    key = atoi(value);
     snd_card_name = mixer_get_name(my_data->adev->mixer);
-    result = my_data->acdb_init(snd_card_name, cvd_version, key);
+    if (my_data->acdb_init_v3) {
+        result = my_data->acdb_init_v3(snd_card_name, cvd_version,
+                                           &my_data->acdb_meta_key_list);
+    } else if (my_data->acdb_init) {
+        node = list_head(&my_data->acdb_meta_key_list);
+        key_info = node_to_item(node, struct meta_key_list, list);
+        key = key_info->cal_info.nKey;
+        result = my_data->acdb_init(snd_card_name, cvd_version, key);
+    }
 
     /* Save these variables in platform_data. These will be used
        while reloading ACDB files during run time. */
     strlcpy(my_data->cvd_version, cvd_version, MAX_CVD_VERSION_STRING_SIZE);
     strlcpy(my_data->snd_card_name, snd_card_name,
                                                MAX_SND_CARD_STRING_SIZE);
-    my_data->metainfo_key = key;
 
     if (cvd_version)
         free(cvd_version);
@@ -1671,6 +1688,16 @@
     if (ret)
         my_data->is_vbat_speaker = true;
 
+    list_init(&my_data->acdb_meta_key_list);
+
+    set_platform_defaults(my_data);
+
+    /* Initialize ACDB ID's */
+    if (my_data->is_i2s_ext_modem)
+        platform_info_init(PLATFORM_INFO_XML_PATH_I2S, my_data);
+    else
+        platform_info_init(PLATFORM_INFO_XML_PATH, my_data);
+
     my_data->voice_feature_set = VOICE_FEATURE_SET_DEFAULT;
     my_data->acdb_handle = dlopen(LIB_ACDB_LOADER, RTLD_NOW);
     if (my_data->acdb_handle == NULL) {
@@ -1741,13 +1768,25 @@
                   __func__, LIB_ACDB_LOADER);
 
 
+        my_data->acdb_init_v3 = (acdb_init_v3_t)dlsym(my_data->acdb_handle,
+                                                     "acdb_loader_init_v3");
+        if (my_data->acdb_init_v3 == NULL) {
+            ALOGE("%s: dlsym error %s for acdb_loader_init_v3", __func__, dlerror());
+        }
+
         my_data->acdb_init = (acdb_init_t)dlsym(my_data->acdb_handle,
-                                                    "acdb_loader_init_v2");
+                                                     "acdb_loader_init_v3");
         if (my_data->acdb_init == NULL) {
-            ALOGE("%s: dlsym error %s for acdb_loader_init_v2", __func__, dlerror());
+            ALOGE("%s: dlsym error %s for acdb_loader_init_v3", __func__, dlerror());
             goto acdb_init_fail;
         }
 
+        my_data->acdb_reload_v2 = (acdb_reload_v2_t)dlsym(my_data->acdb_handle,
+                                                    "acdb_loader_reload_acdb_files_v2");
+        if (my_data->acdb_reload_v2 == NULL) {
+            ALOGE("%s: dlsym error %s for acdb_loader_reload_acdb_files_v2", __func__, dlerror());
+        }
+
         my_data->acdb_reload = (acdb_reload_t)dlsym(my_data->acdb_handle,
                                                     "acdb_loader_reload_acdb_files");
         if (my_data->acdb_reload == NULL) {
@@ -1762,13 +1801,6 @@
 
 acdb_init_fail:
 
-    set_platform_defaults(my_data);
-
-    /* Initialize ACDB ID's */
-    if (my_data->is_i2s_ext_modem)
-        platform_info_init(PLATFORM_INFO_XML_PATH_I2S, my_data);
-    else
-        platform_info_init(PLATFORM_INFO_XML_PATH, my_data);
 
     if (audio_extn_can_use_ras()) {
         if (property_get_bool("persist.speaker.prot.enable", false)) {
@@ -1815,7 +1847,6 @@
     audio_extn_ssr_update_enabled();
     audio_extn_spkr_prot_init(adev);
 
-    audio_extn_dolby_set_license(adev);
 
     /* init audio device arbitration */
     audio_extn_dev_arbi_init();
@@ -2194,6 +2225,46 @@
     return ret;
 }
 
+int platform_set_acdb_metainfo_key(void *platform, char *name, int key)
+{
+    struct meta_key_list *key_info;
+    struct platform_data *pdata = (struct platform_data *)platform;
+
+    key_info = (struct meta_key_list *)calloc(1, sizeof(struct meta_key_list));
+    if (!key_info) {
+        ALOGE("%s: Could not allocate memory for key %d", __func__, key);
+        return -ENOMEM;
+    }
+
+    key_info->cal_info.nKey = key;
+    strlcpy(key_info->name, name, sizeof(key_info->name));
+    list_add_tail(&pdata->acdb_meta_key_list, &key_info->list);
+
+    ALOGD("%s: successfully added module %s and key %d to the list", __func__,
+               key_info->name, key_info->cal_info.nKey);
+    return 0;
+}
+
+int platform_get_meta_info_key_from_list(void *platform, char *mod_name)
+{
+    struct listnode *node;
+    struct meta_key_list *key_info;
+    struct platform_data *pdata = (struct platform_data *)platform;
+    int key = 0;
+
+    ALOGV("%s: for module %s", __func__, mod_name);
+
+    list_for_each(node, &pdata->acdb_meta_key_list) {
+        key_info = node_to_item(node, struct meta_key_list, list);
+        if (strcmp(key_info->name, mod_name) == 0) {
+            key = key_info->cal_info.nKey;
+            ALOGD("%s: Found key %d for module %s", __func__, key, mod_name);
+            break;
+        }
+    }
+    return key;
+}
+
 int platform_get_default_app_type(void *platform)
 {
     struct platform_data *my_data = (struct platform_data *)platform;
@@ -3866,6 +3937,9 @@
     int len;
     int ret = 0, err;
     char *kv_pairs = str_parms_to_str(parms);
+    struct listnode *node;
+    struct meta_key_list *key_info;
+    int key = 0;
 
     if(kv_pairs == NULL) {
         ret = -ENOMEM;
@@ -3935,9 +4009,16 @@
     if (err >= 0) {
         str_parms_del(parms, AUDIO_PARAMETER_KEY_RELOAD_ACDB);
 
-        my_data->acdb_reload(value, my_data->snd_card_name,
-                              my_data->cvd_version, my_data->metainfo_key);
-
+        if (my_data->acdb_reload_v2) {
+            my_data->acdb_reload_v2(value, my_data->snd_card_name,
+                                  my_data->cvd_version, &my_data->acdb_meta_key_list);
+        } else if (my_data->acdb_reload) {
+            node = list_head(&my_data->acdb_meta_key_list);
+            key_info = node_to_item(node, struct meta_key_list, list);
+            key = key_info->cal_info.nKey;
+            my_data->acdb_reload(value, my_data->snd_card_name,
+                                  my_data->cvd_version, key);
+        }
     }
 
     if (hw_info_is_stereo_spkr(my_data->hw_info)) {
diff --git a/hal/platform_api.h b/hal/platform_api.h
index e274e48..82bef97 100644
--- a/hal/platform_api.h
+++ b/hal/platform_api.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
  * Not a contribution.
  *
  * Copyright (C) 2013 The Android Open Source Project
@@ -31,6 +31,7 @@
 #define SAMPLE_RATE_11025 11025
 #define sample_rate_multiple(sr, base) ((sr % base)== 0?true:false)
 #define MAX_VOLUME_CAL_STEPS 15
+#define ACDB_METAINFO_KEY_MODULE_NAME_LEN 100
 
 struct amp_db_and_gain_table {
     float amp;
@@ -82,6 +83,8 @@
 int platform_get_snd_device_acdb_id(snd_device_t snd_device);
 int platform_set_snd_device_bit_width(snd_device_t snd_device, unsigned int bit_width);
 int platform_get_snd_device_bit_width(snd_device_t snd_device);
+int platform_set_acdb_metainfo_key(void *platform, char *name, int key);
+int platform_get_meta_info_key_from_list(void *platform, char *mod_name);
 int platform_set_native_support(int na_mode);
 int platform_get_native_support();
 int platform_send_audio_calibration(void *platform, struct audio_usecase *usecase,
diff --git a/hal/platform_info.c b/hal/platform_info.c
index 8e12dd6..a63b215 100644
--- a/hal/platform_info.c
+++ b/hal/platform_info.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -51,6 +51,7 @@
     INTERFACE_NAME,
     CONFIG_PARAMS,
     GAIN_LEVEL_MAPPING,
+    ACDB_METAINFO_KEY,
 } section_t;
 
 typedef void (* section_process_fn)(const XML_Char **attr);
@@ -63,6 +64,7 @@
 static void process_config_params(const XML_Char **attr);
 static void process_root(const XML_Char **attr);
 static void process_gain_db_to_level_map(const XML_Char **attr);
+static void process_acdb_metainfo_key(const XML_Char **attr);
 
 static section_process_fn section_table[] = {
     [ROOT] = process_root,
@@ -73,6 +75,7 @@
     [INTERFACE_NAME] = process_interface_name,
     [CONFIG_PARAMS] = process_config_params,
     [GAIN_LEVEL_MAPPING] = process_gain_db_to_level_map,
+    [ACDB_METAINFO_KEY] = process_acdb_metainfo_key,
 };
 
 static section_t section;
@@ -350,6 +353,29 @@
     return;
 }
 
+/* process acdb meta info key value */
+static void process_acdb_metainfo_key(const XML_Char **attr)
+{
+    if (strcmp(attr[0], "name") != 0) {
+        ALOGE("%s: 'name' not found", __func__);
+        goto done;
+    }
+
+    if (strcmp(attr[2], "value") != 0) {
+        ALOGE("%s: 'value' not found", __func__);
+        goto done;
+    }
+
+    int key = atoi((char *)attr[3]);
+    if (platform_set_acdb_metainfo_key(my_data.platform, (char*)attr[1], key) < 0) {
+        ALOGE("%s: key %d was not set!", __func__, key);
+        goto done;
+    }
+
+done:
+    return;
+}
+
 static void start_tag(void *userdata __unused, const XML_Char *tag_name,
                       const XML_Char **attr)
 {
@@ -367,6 +393,8 @@
         section = INTERFACE_NAME;
     } else if (strcmp(tag_name, "gain_db_to_level_mapping") == 0) {
         section = GAIN_LEVEL_MAPPING;
+    } else if(strcmp(tag_name, "acdb_metainfo_key") == 0) {
+        section = ACDB_METAINFO_KEY;
     } else if (strcmp(tag_name, "device") == 0) {
         if ((section != ACDB) && (section != BACKEND_NAME) && (section != BITWIDTH) &&
             (section != INTERFACE_NAME)) {
@@ -394,7 +422,7 @@
         section_process_fn fn = section_table[PCM_ID];
         fn(attr);
     } else if (strcmp(tag_name, "param") == 0) {
-        if (section != CONFIG_PARAMS) {
+        if ((section != CONFIG_PARAMS) && (section != ACDB_METAINFO_KEY)) {
             ALOGE("param tag only supported with CONFIG_PARAMS section");
             return;
         }
@@ -423,6 +451,8 @@
         section = ROOT;
     } else if (strcmp(tag_name, "gain_db_to_level_mapping") == 0) {
         section = ROOT;
+    } else if (strcmp(tag_name, "acdb_metainfo_key") == 0) {
+        section = ROOT;
     }
 }