Merge "hal: remove libmdmdetect library dependency"
diff --git a/hal/audio_extn/spkr_protection.c b/hal/audio_extn/spkr_protection.c
index 7ab65c6..951dadc 100644
--- a/hal/audio_extn/spkr_protection.c
+++ b/hal/audio_extn/spkr_protection.c
@@ -668,6 +668,15 @@
         handle.thermal_handle = NULL;
         handle.spkr_prot_enable = false;
     }
+
+    if (handle.spkr_prot_enable) {
+        char platform[PROPERTY_VALUE_MAX];
+        property_get("ro.board.platform", platform, "");
+        if (!strncmp("apq8084", platform, sizeof("apq8084"))) {
+            platform_set_snd_device_backend(SND_DEVICE_OUT_VOICE_SPEAKER,
+                                            "speaker-protected");
+        }
+    }
 }
 
 int audio_extn_spkr_prot_get_acdb_id(snd_device_t snd_device)
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index 87ea0d3..c394391 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -670,26 +670,26 @@
          * usecase. This is to avoid switching devices for voice call when
          * check_usecases_codec_backend() is called below.
          */
-        if (voice_is_in_call(adev)) {
+        if (adev->voice.in_call && adev->mode == AUDIO_MODE_IN_CALL) {
             vc_usecase = get_usecase_from_list(adev,
                                                get_voice_usecase_id_from_list(adev));
-            if ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
-                (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL)) {
+            if ((vc_usecase) && ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
+                (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
                 in_snd_device = vc_usecase->in_snd_device;
                 out_snd_device = vc_usecase->out_snd_device;
             }
         } else if (voice_extn_compress_voip_is_active(adev)) {
             voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
-            if ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
+            if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
                 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
-                 (voip_usecase->stream.out != adev->primary_output)) {
+                 (voip_usecase->stream.out != adev->primary_output))) {
                     in_snd_device = voip_usecase->in_snd_device;
                     out_snd_device = voip_usecase->out_snd_device;
             }
         } else if (audio_extn_hfp_is_active(adev)) {
             hfp_ucid = audio_extn_hfp_get_usecase();
             hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
-            if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
+            if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
                    in_snd_device = hfp_usecase->in_snd_device;
                    out_snd_device = hfp_usecase->out_snd_device;
             }
@@ -1628,17 +1628,18 @@
                 select_devices(adev, out->usecase);
 
             if ((adev->mode == AUDIO_MODE_IN_CALL) &&
-                    !voice_is_in_call(adev) &&
-                    (out == adev->primary_output)) {
+                !adev->voice.in_call &&
+                (out == adev->primary_output)) {
                 ret = voice_start_call(adev);
-            } else if (voice_is_in_call(adev) &&
-                            (out == adev->primary_output)) {
+            } else if ((adev->mode == AUDIO_MODE_IN_CALL) &&
+                       adev->voice.in_call &&
+                       (out == adev->primary_output)) {
                 voice_update_devices_for_all_voice_usecases(adev);
             }
         }
 
         if ((adev->mode == AUDIO_MODE_NORMAL) &&
-                voice_is_in_call(adev) &&
+                adev->voice.in_call &&
                 (out == adev->primary_output)) {
             ret = voice_stop_call(adev);
         }
diff --git a/hal/msm8916/platform.c b/hal/msm8916/platform.c
index e2ed4d9..6cf0f65 100644
--- a/hal/msm8916/platform.c
+++ b/hal/msm8916/platform.c
@@ -2079,3 +2079,21 @@
 bool platform_check_and_set_codec_backend_cfg(struct audio_device* adev, struct audio_usecase *usecase) {
     return false;
 }
+
+int platform_get_usecase_index(const char * usecase __unused)
+{
+    return -ENOSYS;
+}
+
+int platform_set_usecase_pcm_id(audio_usecase_t usecase __unused, int32_t type __unused,
+                                int32_t pcm_id __unused)
+{
+    return -ENOSYS;
+}
+
+int platform_set_snd_device_backend(snd_device_t snd_device __unused,
+                                    const char * backend __unused)
+{
+    return -ENOSYS;
+}
+
diff --git a/hal/msm8960/platform.c b/hal/msm8960/platform.c
index 2400cd8..d83a93f 100644
--- a/hal/msm8960/platform.c
+++ b/hal/msm8960/platform.c
@@ -959,3 +959,19 @@
     return false;
 }
 
+int platform_get_usecase_index(const char * usecase __unused)
+{
+    return -ENOSYS;
+}
+
+int platform_set_usecase_pcm_id(audio_usecase_t usecase __unused, int32_t type __unused,
+                                int32_t pcm_id __unused)
+{
+    return -ENOSYS;
+}
+
+int platform_set_snd_device_backend(snd_device_t snd_device __unused,
+                                    const char * backend __unused)
+{
+    return -ENOSYS;
+}
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index d8c1fd2..298089e 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -142,7 +142,7 @@
     struct csd_data *csd;
 };
 
-static const int pcm_device_table[AUDIO_USECASE_MAX][2] = {
+static int pcm_device_table[AUDIO_USECASE_MAX][2] = {
     [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {DEEP_BUFFER_PCM_DEVICE,
                                             DEEP_BUFFER_PCM_DEVICE},
     [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {LOWLATENCY_PCM_DEVICE,
@@ -372,7 +372,7 @@
     [SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS_BROADSIDE] = 120,
 };
 
-struct snd_device_index {
+struct name_to_index {
     char name[100];
     unsigned int index;
 };
@@ -380,7 +380,7 @@
 #define TO_NAME_INDEX(X)   #X, X
 
 /* Used to get index from parsed sting */
-struct snd_device_index snd_device_name_index[SND_DEVICE_MAX] = {
+static struct name_to_index snd_device_name_index[SND_DEVICE_MAX] = {
     {TO_NAME_INDEX(SND_DEVICE_OUT_HANDSET)},
     {TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER)},
     {TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_EXTERNAL_1)},
@@ -460,6 +460,26 @@
     {TO_NAME_INDEX(SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS_BROADSIDE)},
 };
 
+static char * backend_table[SND_DEVICE_MAX] = {0};
+
+static struct name_to_index usecase_name_index[AUDIO_USECASE_MAX] = {
+    {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_DEEP_BUFFER)},
+    {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_LOW_LATENCY)},
+    {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_MULTI_CH)},
+    {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_OFFLOAD)},
+    {TO_NAME_INDEX(USECASE_AUDIO_RECORD)},
+    {TO_NAME_INDEX(USECASE_AUDIO_RECORD_LOW_LATENCY)},
+    {TO_NAME_INDEX(USECASE_VOICE_CALL)},
+    {TO_NAME_INDEX(USECASE_VOICE2_CALL)},
+    {TO_NAME_INDEX(USECASE_VOLTE_CALL)},
+    {TO_NAME_INDEX(USECASE_QCHAT_CALL)},
+    {TO_NAME_INDEX(USECASE_VOWLAN_CALL)},
+    {TO_NAME_INDEX(USECASE_INCALL_REC_UPLINK)},
+    {TO_NAME_INDEX(USECASE_INCALL_REC_DOWNLINK)},
+    {TO_NAME_INDEX(USECASE_INCALL_REC_UPLINK_AND_DOWNLINK)},
+    {TO_NAME_INDEX(USECASE_AUDIO_HFP_SCO)},
+};
+
 #define DEEP_BUFFER_PLATFORM_DELAY (29*1000LL)
 #define LOW_LATENCY_PLATFORM_DELAY (13*1000LL)
 
@@ -642,6 +662,30 @@
     return plat_data->is_i2s_ext_modem;
 }
 
+static void set_platform_defaults(struct platform_data * my_data)
+{
+    int32_t dev;
+    for (dev = 0; dev < SND_DEVICE_MAX; dev++) {
+        backend_table[dev] = NULL;
+    }
+
+    // TBD - do these go to the platform-info.xml file.
+    // will help in avoiding strdups here
+    backend_table[SND_DEVICE_IN_BT_SCO_MIC] = strdup("bt-sco");
+    backend_table[SND_DEVICE_IN_BT_SCO_MIC_WB] = strdup("bt-sco-wb");
+    backend_table[SND_DEVICE_OUT_BT_SCO] = strdup("bt-sco");
+    backend_table[SND_DEVICE_OUT_BT_SCO_WB] = strdup("bt-sco-wb");
+    backend_table[SND_DEVICE_OUT_HDMI] = strdup("hdmi");
+    backend_table[SND_DEVICE_OUT_SPEAKER_AND_HDMI] = strdup("speaker-and-hdmi");
+    backend_table[SND_DEVICE_OUT_AFE_PROXY] = strdup("afe-proxy");
+    backend_table[SND_DEVICE_OUT_USB_HEADSET] = strdup("usb-headphones");
+    backend_table[SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET] =
+        strdup("speaker-and-usb-headphones");
+    backend_table[SND_DEVICE_IN_USB_HEADSET_MIC] = strdup("usb-headset-mic");
+    backend_table[SND_DEVICE_IN_CAPTURE_FM] = strdup("capture-fm");
+    backend_table[SND_DEVICE_OUT_TRANSMISSION_FM] = strdup("transmission-fm");
+}
+
 void *platform_init(struct audio_device *adev)
 {
     char platform[PROPERTY_VALUE_MAX];
@@ -804,6 +848,8 @@
             my_data->acdb_init(snd_card_name);
     }
 
+    set_platform_defaults(my_data);
+
     /* Initialize ACDB ID's */
     if (my_data->is_i2s_ext_modem)
         platform_info_init(PLATFORM_INFO_XML_PATH_I2S);
@@ -844,6 +890,14 @@
     hw_info_deinit(my_data->hw_info);
     close_csd_client(my_data->csd);
 
+    int32_t dev;
+    for (dev = 0; dev < SND_DEVICE_MAX; dev++) {
+        if (backend_table[dev]) {
+            free(backend_table[dev]);
+            backend_table[dev]= NULL;
+        }
+    }
+
     free(platform);
     /* deinit usb */
     audio_extn_usb_deinit();
@@ -875,37 +929,16 @@
 
 void platform_add_backend_name(char *mixer_path, snd_device_t snd_device)
 {
-    if (snd_device == SND_DEVICE_IN_BT_SCO_MIC)
-        strlcat(mixer_path, " bt-sco", MIXER_PATH_MAX_LENGTH);
-    else if (snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB)
-        strlcat(mixer_path, " bt-sco-wb", MIXER_PATH_MAX_LENGTH);
-    else if(snd_device == SND_DEVICE_OUT_BT_SCO)
-        strlcat(mixer_path, " bt-sco", MIXER_PATH_MAX_LENGTH);
-    else if(snd_device == SND_DEVICE_OUT_BT_SCO_WB)
-        strlcat(mixer_path, " bt-sco-wb", MIXER_PATH_MAX_LENGTH);
-    else if (snd_device == SND_DEVICE_OUT_HDMI)
-        strlcat(mixer_path, " hdmi", MIXER_PATH_MAX_LENGTH);
-    else if (snd_device == SND_DEVICE_OUT_SPEAKER_AND_HDMI)
-        strcat(mixer_path, " speaker-and-hdmi");
-    else if (snd_device == SND_DEVICE_OUT_AFE_PROXY)
-        strlcat(mixer_path, " afe-proxy", MIXER_PATH_MAX_LENGTH);
-    else if (snd_device == SND_DEVICE_OUT_USB_HEADSET)
-        strlcat(mixer_path, " usb-headphones", MIXER_PATH_MAX_LENGTH);
-    else if (snd_device == SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET)
-        strlcat(mixer_path, " speaker-and-usb-headphones",
-                MIXER_PATH_MAX_LENGTH);
-    else if (snd_device == SND_DEVICE_IN_USB_HEADSET_MIC)
-        strlcat(mixer_path, " usb-headset-mic", MIXER_PATH_MAX_LENGTH);
-    else if (snd_device == SND_DEVICE_IN_CAPTURE_FM)
-        strlcat(mixer_path, " capture-fm", MIXER_PATH_MAX_LENGTH);
-    else if (snd_device == SND_DEVICE_OUT_TRANSMISSION_FM)
-        strlcat(mixer_path, " transmission-fm", MIXER_PATH_MAX_LENGTH);
-    else if (snd_device == SND_DEVICE_OUT_VOICE_SPEAKER &&
-             audio_extn_spkr_prot_is_enabled() ) {
-        char platform[PROPERTY_VALUE_MAX];
-        property_get("ro.board.platform", platform, "");
-        if (!strncmp("apq8084", platform, sizeof("apq8084")))
-            strlcat(mixer_path, " speaker-protected", MIXER_PATH_MAX_LENGTH);
+    if ((snd_device < SND_DEVICE_MIN) || (snd_device >= SND_DEVICE_MAX)) {
+        ALOGE("%s: Invalid snd_device = %d", __func__, snd_device);
+        return;
+    }
+
+    const char * suffix = backend_table[snd_device];
+
+    if (suffix != NULL) {
+        strlcat(mixer_path, " ", MIXER_PATH_MAX_LENGTH);
+        strlcat(mixer_path, suffix, MIXER_PATH_MAX_LENGTH);
     }
 }
 
@@ -919,25 +952,36 @@
     return device_id;
 }
 
-int platform_get_snd_device_index(char *snd_device_index_name)
+static int find_index(struct name_to_index * table, int32_t len, const char * name)
 {
     int ret = 0;
-    int i;
+    int32_t i;
 
-    if (snd_device_index_name == NULL) {
-        ALOGE("%s: snd_device_index_name is NULL", __func__);
+    if (table == NULL) {
+        ALOGE("%s: table is NULL", __func__);
         ret = -ENODEV;
         goto done;
     }
 
-    for (i=0; i < SND_DEVICE_MAX; i++) {
-        if(strcmp(snd_device_name_index[i].name, snd_device_index_name) == 0) {
-            ret = snd_device_name_index[i].index;
+    if (name == NULL) {
+        ALOGE("null key");
+        ret = -ENODEV;
+        goto done;
+    }
+
+    for (i=0; i < len; i++) {
+        const char* tn = table[i].name;
+        int32_t len = strlen(tn);
+        if (strncmp(tn, name, len) == 0) {
+            if (strlen(name) != len) {
+                continue; // substring
+            }
+            ret = table[i].index;
             goto done;
         }
     }
-    ALOGE("%s: Could not find index for snd_device_index_name = %s",
-            __func__, snd_device_index_name);
+    ALOGE("%s: Could not find index for name = %s",
+            __func__, name);
     ret = -ENODEV;
 done:
     return ret;
@@ -1000,6 +1044,16 @@
     return ret;
 }
 
+int platform_get_snd_device_index(char *device_name)
+{
+    return find_index(snd_device_name_index, SND_DEVICE_MAX, device_name);
+}
+
+int platform_get_usecase_index(const char *usecase_name)
+{
+    return find_index(usecase_name_index, AUDIO_USECASE_MAX, usecase_name);
+}
+
 int platform_set_snd_device_acdb_id(snd_device_t snd_device, unsigned int acdb_id)
 {
     int ret = 0;
@@ -1041,7 +1095,7 @@
     struct platform_data *my_data = (struct platform_data *)platform;
     int acdb_dev_id, acdb_dev_type;
 
-    acdb_dev_id = acdb_device_table[snd_device];
+    acdb_dev_id = acdb_device_table[audio_extn_get_spkr_prot_snd_device(snd_device)];
     if (acdb_dev_id < 0) {
         ALOGE("%s: Could not find acdb id for device(%d)",
               __func__, snd_device);
@@ -2399,3 +2453,40 @@
 
     return false;
 }
+
+int platform_set_snd_device_backend(snd_device_t device, const char *backend)
+{
+    int ret = 0;
+
+    if ((device < SND_DEVICE_MIN) || (device >= SND_DEVICE_MAX)) {
+        ALOGE("%s: Invalid snd_device = %d",
+            __func__, device);
+        ret = -EINVAL;
+        goto done;
+    }
+
+    if (backend_table[device]) {
+        free(backend_table[device]);
+    }
+    backend_table[device] = strdup(backend);
+done:
+    return ret;
+}
+
+int platform_set_usecase_pcm_id(audio_usecase_t usecase, int32_t type, int32_t pcm_id)
+{
+    int ret = 0;
+    if ((usecase <= USECASE_INVALID) || (usecase >= AUDIO_USECASE_MAX)) {
+        ALOGE("%s: invalid usecase case idx %d", __func__, usecase);
+        ret = -EINVAL;
+        goto done;
+    }
+
+    if ((type != 0) && (type != 1)) {
+        ALOGE("%s: invalid usecase type", __func__);
+        ret = -EINVAL;
+    }
+    pcm_device_table[usecase][type] = pcm_id;
+done:
+    return ret;
+}
diff --git a/hal/platform_api.h b/hal/platform_api.h
index e09b070..85b3c4f 100644
--- a/hal/platform_api.h
+++ b/hal/platform_api.h
@@ -76,6 +76,8 @@
 bool platform_listen_device_needs_event(snd_device_t snd_device);
 bool platform_listen_usecase_needs_event(audio_usecase_t uc_id);
 
+int platform_set_snd_device_backend(snd_device_t snd_device, const char * backend);
+
 /* From platform_info_parser.c */
 int platform_info_init(const char *filename);
 
@@ -85,4 +87,7 @@
 
 bool platform_check_and_set_codec_backend_cfg(struct audio_device* adev, struct audio_usecase *usecase);
 bool platform_check_24_bit_support();
+int platform_get_usecase_index(const char * usecase);
+int platform_set_usecase_pcm_id(audio_usecase_t usecase, int32_t type, int32_t pcm_id);
+
 #endif // AUDIO_PLATFORM_API_H
diff --git a/hal/platform_info.c b/hal/platform_info.c
index 85a05eb..615b9f3 100644
--- a/hal/platform_info.c
+++ b/hal/platform_info.c
@@ -40,7 +40,137 @@
 
 #define BUF_SIZE                    1024
 
-static void process_device(const XML_Char **attr)
+typedef enum {
+    ROOT,
+    ACDB,
+    PCM_ID,
+    BACKEND_NAME,
+} section_t;
+
+typedef void (* section_process_fn)(const XML_Char **attr);
+
+static void process_acdb_id(const XML_Char **attr);
+static void process_pcm_id(const XML_Char **attr);
+static void process_backend_name(const XML_Char **attr);
+static void process_root(const XML_Char **attr);
+
+static section_process_fn section_table[] = {
+    [ROOT] = process_root,
+    [ACDB] = process_acdb_id,
+    [PCM_ID] = process_pcm_id,
+    [BACKEND_NAME] = process_backend_name,
+};
+
+static section_t section;
+
+/*
+ * <audio_platform_info>
+ * <acdb_ids>
+ * <device name="???" acdb_id="???"/>
+ * ...
+ * ...
+ * </acdb_ids>
+ * <backend_names>
+ * <device name="???" backend="???"/>
+ * ...
+ * ...
+ * </backend_names>
+ * <pcm_ids>
+ * <usecase name="???" type="in/out" id="???"/>
+ * ...
+ * ...
+ * </pcm_ids>
+ * </audio_platform_info>
+ */
+
+static void process_root(const XML_Char **attr __unused)
+{
+}
+
+/* mapping from usecase to pcm dev id */
+static void process_pcm_id(const XML_Char **attr)
+{
+    int index;
+
+    if (strcmp(attr[0], "name") != 0) {
+        ALOGE("%s: 'name' not found, no ACDB ID set!", __func__);
+        goto done;
+    }
+
+    index = platform_get_usecase_index((char *)attr[1]);
+    if (index < 0) {
+        ALOGE("%s: usecase %s not found!",
+              __func__, attr[1]);
+        goto done;
+    }
+
+    if (strcmp(attr[2], "type") != 0) {
+        ALOGE("%s: usecase type not mentioned", __func__);
+        goto done;
+    }
+
+    int type = -1;
+
+    if (!strcasecmp((char *)attr[3], "in")) {
+        type = 1;
+    } else if (!strcasecmp((char *)attr[3], "out")) {
+        type = 0;
+    } else {
+        ALOGE("%s: type must be IN or OUT", __func__);
+        goto done;
+    }
+
+    if (strcmp(attr[4], "id") != 0) {
+        ALOGE("%s: usecase id not mentioned", __func__);
+        goto done;
+    }
+
+    int id = atoi((char *)attr[5]);
+
+    if (platform_set_usecase_pcm_id(index, type, id) < 0) {
+        ALOGE("%s: usecase %s type %d id %d was not set!",
+              __func__, attr[1], type, id);
+        goto done;
+    }
+
+done:
+    return;
+}
+
+/* backend to be used for a device */
+static void process_backend_name(const XML_Char **attr)
+{
+    int index;
+
+    if (strcmp(attr[0], "name") != 0) {
+        ALOGE("%s: 'name' not found, no ACDB ID set!", __func__);
+        goto done;
+    }
+
+    index = platform_get_snd_device_index((char *)attr[1]);
+    if (index < 0) {
+        ALOGE("%s: Device %s not found, no ACDB ID set!",
+              __func__, attr[1]);
+        goto done;
+    }
+
+    if (strcmp(attr[2], "backend") != 0) {
+        ALOGE("%s: Device %s has no backend set!",
+              __func__, attr[1]);
+        goto done;
+    }
+
+    if (platform_set_snd_device_backend(index, attr[3]) < 0) {
+        ALOGE("%s: Device %s backend %s was not set!",
+              __func__, attr[1], attr[3]);
+        goto done;
+    }
+
+done:
+    return;
+}
+
+static void process_acdb_id(const XML_Char **attr)
 {
     int index;
 
@@ -62,8 +192,8 @@
         goto done;
     }
 
-    if(platform_set_snd_device_acdb_id(index, atoi((char *)attr[3])) < 0) {
-        ALOGE("%s: Device %s in platform info xml ACDB ID %d was not set!",
+    if (platform_set_snd_device_acdb_id(index, atoi((char *)attr[3])) < 0) {
+        ALOGE("%s: Device %s, ACDB ID %d was not set!",
               __func__, attr[1], atoi((char *)attr[3]));
         goto done;
     }
@@ -72,22 +202,50 @@
     return;
 }
 
-static void start_tag(void *userdata, const XML_Char *tag_name,
+static void start_tag(void *userdata __unused, const XML_Char *tag_name,
                       const XML_Char **attr)
 {
     const XML_Char              *attr_name = NULL;
     const XML_Char              *attr_value = NULL;
     unsigned int                i;
 
-    if (strcmp(tag_name, "device") == 0)
-        process_device(attr);
+    if (strcmp(tag_name, "acdb_ids") == 0) {
+        section = ACDB;
+    } else if (strcmp(tag_name, "pcm_ids") == 0) {
+        section = PCM_ID;
+    } else if (strcmp(tag_name, "backend_names") == 0) {
+        section = BACKEND_NAME;
+    } else if (strcmp(tag_name, "device") == 0) {
+        if ((section != ACDB) && (section != BACKEND_NAME)) {
+            ALOGE("device tag only supported for acdb/backend names");
+            return;
+        }
+
+        /* call into process function for the current section */
+        section_process_fn fn = section_table[section];
+        fn(attr);
+    } else if (strcmp(tag_name, "usecase") == 0) {
+        if (section != PCM_ID) {
+            ALOGE("usecase tag only supported with PCM_ID section");
+            return;
+        }
+
+        section_process_fn fn = section_table[PCM_ID];
+        fn(attr);
+    }
 
     return;
 }
 
-static void end_tag(void *userdata, const XML_Char *tag_name)
+static void end_tag(void *userdata __unused, const XML_Char *tag_name)
 {
-
+    if (strcmp(tag_name, "acdb_ids") == 0) {
+        section = ROOT;
+    } else if (strcmp(tag_name, "pcm_ids") == 0) {
+        section = ROOT;
+    } else if (strcmp(tag_name, "backend_names") == 0) {
+        section = ROOT;
+    }
 }
 
 int platform_info_init(const char *filename)
@@ -99,6 +257,8 @@
     void            *buf;
 
     file = fopen(filename, "r");
+    section = ROOT;
+
     if (!file) {
         ALOGD("%s: Failed to open %s, using defaults.",
             __func__, filename);
diff --git a/hal/voice.c b/hal/voice.c
index aa8c29a..33e0d2c 100644
--- a/hal/voice.c
+++ b/hal/voice.c
@@ -192,26 +192,27 @@
     }
 
     session->state.current = CALL_ACTIVE;
-    return 0;
+    goto done;
 
 error_start_voice:
     stop_call(adev, usecase_id);
 
+done:
     ALOGD("%s: exit: status(%d)", __func__, ret);
     return ret;
 }
 
-bool voice_is_in_call(struct audio_device *adev)
+bool voice_is_call_state_active(struct audio_device *adev)
 {
-    bool in_call = false;
+    bool call_state = false;
     int ret = 0;
 
-    ret = voice_extn_is_in_call(adev, &in_call);
+    ret = voice_extn_is_call_state_active(adev, &call_state);
     if (ret == -ENOSYS) {
-        in_call = (adev->voice.session[VOICE_SESS_IDX].state.current == CALL_ACTIVE) ? true : false;
+        call_state = (adev->voice.session[VOICE_SESS_IDX].state.current == CALL_ACTIVE) ? true : false;
     }
 
-    return in_call;
+    return call_state;
 }
 
 bool voice_is_in_call_rec_stream(struct stream_in *in)
@@ -247,7 +248,7 @@
     int usecase_id;
     int rec_mode = INCALL_REC_NONE;
 
-    if (voice_is_in_call(adev)) {
+    if (voice_is_call_state_active(adev)) {
         switch (in->source) {
         case AUDIO_SOURCE_VOICE_UPLINK:
             if (audio_extn_compr_cap_enabled() &&
@@ -373,6 +374,7 @@
     if (ret == -ENOSYS) {
         ret = start_call(adev, USECASE_VOICE_CALL);
     }
+    adev->voice.in_call = true;
 
     return ret;
 }
@@ -381,6 +383,7 @@
 {
     int ret = 0;
 
+    adev->voice.in_call = false;
     ret = voice_extn_stop_call(adev);
     if (ret == -ENOSYS) {
         ret = stop_call(adev, USECASE_VOICE_CALL);
@@ -434,7 +437,7 @@
         if (tty_mode != adev->voice.tty_mode) {
             adev->voice.tty_mode = tty_mode;
             adev->acdb_settings = (adev->acdb_settings & TTY_MODE_CLEAR) | tty_mode;
-            if (voice_is_in_call(adev))
+            if (voice_is_call_state_active(adev))
                voice_update_devices_for_all_voice_usecases(adev);
         }
     }
@@ -463,7 +466,7 @@
     adev->voice.tty_mode = TTY_MODE_OFF;
     adev->voice.volume = 1.0f;
     adev->voice.mic_mute = false;
-    adev->voice.voice_device_set = false;
+    adev->voice.in_call = false;
     for (i = 0; i < MAX_VOICE_SESSIONS; i++) {
         adev->voice.session[i].pcm_rx = NULL;
         adev->voice.session[i].pcm_tx = NULL;
diff --git a/hal/voice.h b/hal/voice.h
index 4df2d6a..5d1ae40 100644
--- a/hal/voice.h
+++ b/hal/voice.h
@@ -60,8 +60,8 @@
     int tty_mode;
     bool mic_mute;
     float volume;
-    bool voice_device_set;
     bool is_in_call;
+    bool in_call;
 };
 
 enum {
@@ -77,8 +77,8 @@
 void voice_get_parameters(struct audio_device *adev, struct str_parms *query,
                           struct str_parms *reply);
 void voice_init(struct audio_device *adev);
-bool voice_is_in_call(struct audio_device *adev);
 bool voice_is_in_call_rec_stream(struct stream_in *in);
+bool voice_is_call_state_active(struct audio_device *adev);
 int voice_set_mic_mute(struct audio_device *dev, bool state);
 bool voice_get_mic_mute(struct audio_device *dev);
 int voice_set_volume(struct audio_device *adev, float volume);
diff --git a/hal/voice_extn/compress_voip.c b/hal/voice_extn/compress_voip.c
index e709505..46aab7d 100644
--- a/hal/voice_extn/compress_voip.c
+++ b/hal/voice_extn/compress_voip.c
@@ -580,8 +580,14 @@
     ret = voip_start_call(adev, &out->config);
     out->pcm = voip_data.pcm_rx;
     uc_info = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
-    uc_info->stream.out = out;
-    uc_info->devices = out->devices;
+    if (uc_info) {
+        uc_info->stream.out = out;
+        uc_info->devices = out->devices;
+    } else {
+        ret = -EINVAL;
+        ALOGE("%s: exit(%d): failed to get use case info", __func__, ret);
+        goto error;
+    }
 
 error:
     ALOGV("%s: exit: status(%d)", __func__, ret);
diff --git a/hal/voice_extn/voice_extn.c b/hal/voice_extn/voice_extn.c
index b73eb31..89abc3a 100644
--- a/hal/voice_extn/voice_extn.c
+++ b/hal/voice_extn/voice_extn.c
@@ -73,7 +73,7 @@
 
 extern int start_call(struct audio_device *adev, audio_usecase_t usecase_id);
 extern int stop_call(struct audio_device *adev, audio_usecase_t usecase_id);
-int voice_extn_is_in_call(struct audio_device *adev, bool *in_call);
+int voice_extn_is_call_state_active(struct audio_device *adev, bool *is_call_active);
 
 static bool is_valid_call_state(int call_state)
 {
@@ -153,7 +153,6 @@
     struct voice_session *session = NULL;
     int fd = 0;
     int ret = 0;
-    bool is_in_call = false;
 
     ALOGD("%s: enter:", __func__);
 
@@ -213,10 +212,6 @@
                     ALOGE("%s: voice_end_call() failed for usecase: %d\n",
                           __func__, usecase_id);
                 } else {
-                    voice_extn_is_in_call(adev, &is_in_call);
-                    if (!is_in_call) {
-                        adev->voice.voice_device_set = false;
-                    }
                     session->state.current = session->state.new;
                 }
                 break;
@@ -288,8 +283,7 @@
 {
     struct voice_session *session = NULL;
     int i = 0;
-    bool is_in_call;
-    int no_of_calls_active = 0;
+    bool is_call_active;
 
     for (i = 0; i < MAX_VOICE_SESSIONS; i++) {
         if (vsid == adev->voice.session[i].vsid) {
@@ -298,21 +292,16 @@
         }
     }
 
-    for (i = 0; i < MAX_VOICE_SESSIONS; i++) {
-        if (CALL_INACTIVE != adev->voice.session[i].state.current)
-            no_of_calls_active++;
-    }
-
     if (session) {
         session->state.new = call_state;
-        voice_extn_is_in_call(adev, &is_in_call);
-        ALOGD("%s is_in_call:%d voice_device_set:%d, mode:%d\n",
-              __func__, is_in_call, adev->voice.voice_device_set, adev->mode);
+        voice_extn_is_call_state_active(adev, &is_call_active);
+        ALOGD("%s is_call_active:%d in_call:%d, mode:%d\n",
+              __func__, is_call_active, adev->voice.in_call, adev->mode);
         /* Dont start voice call before device routing for voice usescases has
          * occured, otherwise voice calls will be started unintendedly on
          * speaker.
          */
-        if (is_in_call || adev->voice.voice_device_set) {
+        if (is_call_active || adev->voice.in_call) {
             /* Device routing is not triggered for voice calls on the subsequent
              * subs, Hence update the call states if voice call is already
              * active on other sub.
@@ -334,16 +323,16 @@
     return 0;
 }
 
-int voice_extn_is_in_call(struct audio_device *adev, bool *in_call)
+int voice_extn_is_call_state_active(struct audio_device *adev, bool *is_call_active)
 {
     struct voice_session *session = NULL;
     int i = 0;
-    *in_call = false;
+    *is_call_active = false;
 
     for (i = 0; i < MAX_VOICE_SESSIONS; i++) {
         session = &adev->voice.session[i];
         if(session->state.current != CALL_INACTIVE){
-            *in_call = true;
+            *is_call_active = true;
             break;
         }
     }
@@ -415,7 +404,6 @@
      * udpated.
      */
     ALOGV("%s: enter:", __func__);
-    adev->voice.voice_device_set = true;
     return update_calls(adev);
 }
 
@@ -462,6 +450,7 @@
         err = str_parms_get_int(parms, AUDIO_PARAMETER_KEY_CALL_STATE, &value);
         if (err >= 0) {
             call_state = value;
+            str_parms_del(parms, AUDIO_PARAMETER_KEY_CALL_STATE);
         } else {
             ALOGE("%s: call_state key not found", __func__);
             ret = -EINVAL;
diff --git a/hal/voice_extn/voice_extn.h b/hal/voice_extn/voice_extn.h
index 4a9c610..73da18a 100644
--- a/hal/voice_extn/voice_extn.h
+++ b/hal/voice_extn/voice_extn.h
@@ -32,8 +32,9 @@
 void voice_extn_get_parameters(const struct audio_device *adev,
                                struct str_parms *query,
                                struct str_parms *reply);
-int voice_extn_is_in_call(struct audio_device *adev, bool *in_call);
 int voice_extn_is_in_call_rec_stream(struct stream_in *in, bool *in_call_rec);
+int voice_extn_is_call_state_active(struct audio_device *adev,
+                                    bool *is_call_active);
 int voice_extn_get_active_session_id(struct audio_device *adev,
                                      uint32_t *session_id);
 void voice_extn_in_get_parameters(struct stream_in *in,
@@ -76,7 +77,8 @@
 {
 }
 
-static int voice_extn_is_in_call(struct audio_device *adev, bool *in_call)
+static int voice_extn_is_call_state_active(struct audio_device *adev,
+                                           bool *is_call_active)
 {
     return -ENOSYS;
 }