Merge " Audio: Revert hal changes to block pcm_close during SSR"
diff --git a/Android.mk b/Android.mk
index c63df05..094165e 100644
--- a/Android.mk
+++ b/Android.mk
@@ -1,4 +1,4 @@
-ifneq ($(filter mpq8092 msm8960 msm8226 msm8x26 msm8610 msm8974 msm8x74 apq8084 msm8916,$(TARGET_BOARD_PLATFORM)),)
+ifneq ($(filter mpq8092 msm8960 msm8226 msm8x26 msm8610 msm8974 msm8x74 apq8084 msm8916 msm8994,$(TARGET_BOARD_PLATFORM)),)
 
 MY_LOCAL_PATH := $(call my-dir)
 
diff --git a/hal/Android.mk b/hal/Android.mk
index 0ec3e3d..6239c01 100644
--- a/hal/Android.mk
+++ b/hal/Android.mk
@@ -8,7 +8,7 @@
 
 AUDIO_PLATFORM := $(TARGET_BOARD_PLATFORM)
 
-ifneq ($(filter msm8974 msm8226 msm8610 apq8084,$(TARGET_BOARD_PLATFORM)),)
+ifneq ($(filter msm8974 msm8226 msm8610 apq8084 msm8994,$(TARGET_BOARD_PLATFORM)),)
   # B-family platform uses msm8974 code base
   AUDIO_PLATFORM = msm8974
   MULTIPLE_HW_VARIANTS_ENABLED := true
@@ -21,6 +21,9 @@
 ifneq ($(filter apq8084,$(TARGET_BOARD_PLATFORM)),)
   LOCAL_CFLAGS := -DPLATFORM_APQ8084
 endif
+ifneq ($(filter msm8994,$(TARGET_BOARD_PLATFORM)),)
+  LOCAL_CFLAGS := -DPLATFORM_MSM8994
+endif
 endif
 
 ifneq ($(filter msm8916,$(TARGET_BOARD_PLATFORM)),)
@@ -35,7 +38,8 @@
 	platform_info.c \
 	$(AUDIO_PLATFORM)/platform.c
 
-LOCAL_SRC_FILES += audio_extn/audio_extn.c
+LOCAL_SRC_FILES += audio_extn/audio_extn.c \
+                   audio_extn/utils.c
 
 ifneq ($(strip $(AUDIO_FEATURE_DISABLED_PCM_OFFLOAD)),true)
     LOCAL_CFLAGS += -DPCM_OFFLOAD_ENABLED
@@ -75,6 +79,7 @@
     LOCAL_CFLAGS += -DSSR_ENABLED
     LOCAL_SRC_FILES += audio_extn/ssr.c
     LOCAL_C_INCLUDES += $(TARGET_OUT_HEADERS)/mm-audio/surround_sound/
+    LOCAL_C_INCLUDES += $(TARGET_OUT_HEADERS)/common/inc/
 endif
 
 ifneq ($(strip $(AUDIO_FEATURE_DISABLED_MULTI_VOICE_SESSIONS)),true)
@@ -91,6 +96,11 @@
     LOCAL_CFLAGS += -DCOMPRESS_VOIP_ENABLED
     LOCAL_SRC_FILES += voice_extn/compress_voip.c
 endif
+
+endif
+
+ifneq ($(strip $(AUDIO_FEATURE_DISABLED_FORMATS)),true)
+LOCAL_CFLAGS += -DFORMATS_ENABLED
 endif
 
 ifneq ($(strip, $(AUDIO_FEATURE_DISABLED_SPKR_PROTECTION)),true)
diff --git a/hal/audio_extn/audio_extn.h b/hal/audio_extn/audio_extn.h
index a17f011..ac8896e 100644
--- a/hal/audio_extn/audio_extn.h
+++ b/hal/audio_extn/audio_extn.h
@@ -61,6 +61,8 @@
 #endif
 
 
+#define MAX_LENGTH_MIXER_CONTROL_IN_INT                  (128)
+
 void audio_extn_set_parameters(struct audio_device *adev,
                                struct str_parms *parms);
 
@@ -182,11 +184,15 @@
 #define audio_extn_spkr_prot_start_processing(snd_device)    (-EINVAL)
 #define audio_extn_spkr_prot_stop_processing()     (0)
 #define audio_extn_spkr_prot_is_enabled() (false)
+#define audio_extn_spkr_prot_get_acdb_id(snd_device)         (-EINVAL)
+#define audio_extn_get_spkr_prot_snd_device(snd_device) (SND_DEVICE_OUT_SPEAKER)
 #else
 void audio_extn_spkr_prot_init(void *adev);
 int audio_extn_spkr_prot_start_processing(snd_device_t snd_device);
 void audio_extn_spkr_prot_stop_processing();
 bool audio_extn_spkr_prot_is_enabled();
+int audio_extn_spkr_prot_get_acdb_id(snd_device_t snd_device);
+int audio_extn_get_spkr_prot_snd_device(snd_device_t snd_device);
 #endif
 
 #ifndef COMPRESS_CAPTURE_ENABLED
@@ -246,4 +252,20 @@
 audio_usecase_t audio_extn_hfp_get_usecase();
 #endif
 
+void audio_extn_utils_update_streams_output_cfg_list(void *platform,
+                                  struct mixer *mixer,
+                                  struct listnode *streams_output_cfg_list);
+void audio_extn_utils_dump_streams_output_cfg_list(
+                                  struct listnode *streams_output_cfg_list);
+void audio_extn_utils_release_streams_output_cfg_list(
+                                  struct listnode *streams_output_cfg_list);
+void audio_extn_utils_update_stream_app_type_cfg(void *platform,
+                                  struct listnode *streams_output_cfg_list,
+                                  audio_output_flags_t flags,
+                                  audio_format_t format,
+                                  struct stream_app_type_cfg *app_type_cfg);
+int audio_extn_utils_send_app_type_cfg(struct audio_usecase *usecase);
+void audio_extn_utils_send_audio_calibration(struct audio_device *adev,
+                                             struct audio_usecase *usecase);
+
 #endif /* AUDIO_EXTN_H */
diff --git a/hal/audio_extn/spkr_protection.c b/hal/audio_extn/spkr_protection.c
index ce673ea..cd2a94e 100644
--- a/hal/audio_extn/spkr_protection.c
+++ b/hal/audio_extn/spkr_protection.c
@@ -44,7 +44,7 @@
 #include <math.h>
 #include <cutils/properties.h>
 #include "audio_extn.h"
-#include <linux/msm_audio_acdb.h>
+#include <linux/msm_audio_calibration.h>
 
 #ifdef SPKR_PROT_ENABLED
 
@@ -187,11 +187,87 @@
 }
 
 
+static int get_spkr_prot_cal(int cal_fd,
+				struct audio_cal_info_msm_spk_prot_status *status)
+{
+    int ret = 0;
+    struct audio_cal_fb_spk_prot_status    cal_data;
+
+    if (cal_fd < 0) {
+        ALOGE("%s: Error: cal_fd = %d", __func__, cal_fd);
+        ret = -EINVAL;
+        goto done;
+    }
+
+    if (status == NULL) {
+        ALOGE("%s: Error: status NULL", __func__);
+        ret = -EINVAL;
+        goto done;
+    }
+
+    cal_data.hdr.data_size = sizeof(cal_data);
+    cal_data.hdr.version = VERSION_0_0;
+    cal_data.hdr.cal_type = AFE_FB_SPKR_PROT_CAL_TYPE;
+    cal_data.hdr.cal_type_size = sizeof(cal_data.cal_type);
+    cal_data.cal_type.cal_hdr.version = VERSION_0_0;
+    cal_data.cal_type.cal_data.mem_handle = -1;
+
+    if (ioctl(cal_fd, AUDIO_GET_CALIBRATION, &cal_data)) {
+        ALOGE("%s: Error: AUDIO_GET_CALIBRATION failed!",
+            __func__);
+        ret = -ENODEV;
+        goto done;
+    }
+
+    status->r0 = cal_data.cal_type.cal_info.r0;
+    status->status = cal_data.cal_type.cal_info.status;
+done:
+    return ret;
+}
+
+static int set_spkr_prot_cal(int cal_fd,
+				struct audio_cal_info_spk_prot_cfg *protCfg)
+{
+    int ret = 0;
+    struct audio_cal_fb_spk_prot_cfg    cal_data;
+
+    if (cal_fd < 0) {
+        ALOGE("%s: Error: cal_fd = %d", __func__, cal_fd);
+        ret = -EINVAL;
+        goto done;
+    }
+
+    if (protCfg == NULL) {
+        ALOGE("%s: Error: status NULL", __func__);
+        ret = -EINVAL;
+        goto done;
+    }
+
+    cal_data.hdr.data_size = sizeof(cal_data);
+    cal_data.hdr.version = VERSION_0_0;
+    cal_data.hdr.cal_type = AFE_FB_SPKR_PROT_CAL_TYPE;
+    cal_data.hdr.cal_type_size = sizeof(cal_data.cal_type);
+    cal_data.cal_type.cal_hdr.version = VERSION_0_0;
+    cal_data.cal_type.cal_info.r0 = protCfg->r0;
+    cal_data.cal_type.cal_info.t0 = protCfg->t0;
+    cal_data.cal_type.cal_info.mode = protCfg->mode;
+    cal_data.cal_type.cal_data.mem_handle = -1;
+
+    if (ioctl(cal_fd, AUDIO_SET_CALIBRATION, &cal_data)) {
+        ALOGE("%s: Error: AUDIO_SET_CALIBRATION failed!",
+            __func__);
+        ret = -ENODEV;
+        goto done;
+    }
+done:
+    return ret;
+}
+
 static int spkr_calibrate(int t0)
 {
     struct audio_device *adev = handle.adev_handle;
-    struct msm_spk_prot_cfg protCfg;
-    struct msm_spk_prot_status status;
+    struct audio_cal_info_spk_prot_cfg protCfg;
+    struct audio_cal_info_msm_spk_prot_status status;
     bool cleanup = false, disable_rx = false, disable_tx = false;
     int acdb_fd = -1;
     struct audio_usecase *uc_info_rx = NULL, *uc_info_tx = NULL;
@@ -206,14 +282,14 @@
         ALOGD("%s: Usecase present retry speaker protection", __func__);
         return -EAGAIN;
     }
-    acdb_fd = open("/dev/msm_acdb",O_RDWR | O_NONBLOCK);
+    acdb_fd = open("/dev/msm_audio_cal",O_RDWR | O_NONBLOCK);
     if (acdb_fd < 0) {
         ALOGE("%s: spkr_prot_thread open msm_acdb failed", __func__);
         return -ENODEV;
     } else {
         protCfg.mode = MSM_SPKR_PROT_CALIBRATION_IN_PROGRESS;
         protCfg.t0 = t0;
-        if (ioctl(acdb_fd, AUDIO_SET_SPEAKER_PROT, &protCfg)) {
+        if (set_spkr_prot_cal(acdb_fd, &protCfg)) {
             ALOGE("%s: spkr_prot_thread set failed AUDIO_SET_SPEAKER_PROT",
             __func__);
             status.status = -ENODEV;
@@ -301,7 +377,7 @@
     }
     if (acdb_fd > 0) {
         status.status = -EINVAL;
-        while (!ioctl(acdb_fd, AUDIO_GET_SPEAKER_PROT,&status)) {
+        while (!get_spkr_prot_cal(acdb_fd, &status)) {
             /*sleep for 200 ms to check for status check*/
             if (!status.status) {
                 ALOGD("%s: spkr_prot_thread calib Success R0 %d",
@@ -348,14 +424,14 @@
         if (!status.status) {
             protCfg.mode = MSM_SPKR_PROT_CALIBRATED;
             protCfg.r0 = status.r0;
-            if (ioctl(acdb_fd, AUDIO_SET_SPEAKER_PROT, &protCfg))
+            if (set_spkr_prot_cal(acdb_fd, &protCfg))
                 ALOGE("%s: spkr_prot_thread disable calib mode", __func__);
             else
                 handle.spkr_prot_mode = MSM_SPKR_PROT_CALIBRATED;
         } else {
             protCfg.mode = MSM_SPKR_PROT_NOT_CALIBRATED;
             handle.spkr_prot_mode = MSM_SPKR_PROT_NOT_CALIBRATED;
-            if (ioctl(acdb_fd, AUDIO_SET_SPEAKER_PROT, &protCfg))
+            if (set_spkr_prot_cal(acdb_fd, &protCfg))
                 ALOGE("%s: spkr_prot_thread disable calib mode failed", __func__);
         }
         if (acdb_fd > 0)
@@ -377,18 +453,18 @@
     unsigned long sec = 0;
     int t0;
     bool goahead = false;
-    struct msm_spk_prot_cfg protCfg;
+    struct audio_cal_info_spk_prot_cfg protCfg;
     FILE *fp;
     int acdb_fd;
     struct audio_device *adev = handle.adev_handle;
 
     handle.speaker_prot_threadid = pthread_self();
     ALOGD("spkr_prot_thread enable prot Entry");
-    acdb_fd = open("/dev/msm_acdb",O_RDWR | O_NONBLOCK);
+    acdb_fd = open("/dev/msm_audio_cal",O_RDWR | O_NONBLOCK);
     if (acdb_fd > 0) {
         /*Set processing mode with t0/r0*/
         protCfg.mode = MSM_SPKR_PROT_NOT_CALIBRATED;
-        if (ioctl(acdb_fd, AUDIO_SET_SPEAKER_PROT, &protCfg)) {
+        if (set_spkr_prot_cal(acdb_fd, &protCfg)) {
             ALOGE("%s: spkr_prot_thread enable prot failed", __func__);
             handle.spkr_prot_mode = MSM_SPKR_PROT_DISABLED;
             close(acdb_fd);
@@ -419,7 +495,7 @@
             && protCfg.r0 < MAX_RESISTANCE_SPKR_Q24) {
             ALOGD("%s: Spkr calibrated", __func__);
             protCfg.mode = MSM_SPKR_PROT_CALIBRATED;
-            if (ioctl(acdb_fd, AUDIO_SET_SPEAKER_PROT, &protCfg)) {
+            if (set_spkr_prot_cal(acdb_fd, &protCfg)) {
                 ALOGE("%s: enable prot failed", __func__);
                 handle.spkr_prot_mode = MSM_SPKR_PROT_DISABLED;
             } else
@@ -577,6 +653,25 @@
     }
 }
 
+int audio_extn_spkr_prot_get_acdb_id(snd_device_t snd_device)
+{
+    int acdb_id;
+
+    acdb_id = (snd_device == SND_DEVICE_OUT_SPEAKER) ?
+              platform_get_snd_device_acdb_id(SND_DEVICE_OUT_SPEAKER_PROTECTED) :
+              -EINVAL;
+
+    return acdb_id;
+}
+
+int audio_extn_get_spkr_prot_snd_device(snd_device_t snd_device)
+{
+    if ((snd_device == SND_DEVICE_OUT_SPEAKER) && handle.spkr_prot_enable)
+        return SND_DEVICE_OUT_SPEAKER_PROTECTED;
+    else
+        return snd_device;
+}
+
 int audio_extn_spkr_prot_start_processing(snd_device_t snd_device)
 {
     struct audio_usecase uc_info_tx;
@@ -591,11 +686,6 @@
     }
     spkr_prot_calib_cancel(adev);
     spkr_prot_set_spkrstatus(true);
-    if (platform_send_audio_calibration(adev->platform,
-        SND_DEVICE_OUT_SPEAKER_PROTECTED) < 0) {
-        adev->snd_dev_ref_cnt[snd_device]--;
-        return -EINVAL;
-    }
     ALOGV("%s: snd_device(%d: %s)", __func__, snd_device,
          platform_get_snd_device_name(SND_DEVICE_OUT_SPEAKER_PROTECTED));
     audio_route_apply_and_update_path(adev->audio_route,
@@ -637,7 +727,8 @@
 exit:
    /* Clear VI feedback cal and replace with handset MIC  */
    platform_send_audio_calibration(adev->platform,
-        SND_DEVICE_IN_HANDSET_MIC);
+        SND_DEVICE_IN_HANDSET_MIC,
+        platform_get_default_app_type(adev->platform), 8000);
     if (ret) {
         if (handle.pcm_tx)
             pcm_close(handle.pcm_tx);
diff --git a/hal/audio_extn/utils.c b/hal/audio_extn/utils.c
new file mode 100644
index 0000000..6bb1b1b
--- /dev/null
+++ b/hal/audio_extn/utils.c
@@ -0,0 +1,469 @@
+/*
+ * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ *
+ * Copyright (C) 2014 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 "audio_hw_utils"
+/* #define LOG_NDEBUG 0 */
+
+#include <errno.h>
+#include <cutils/properties.h>
+#include <cutils/config_utils.h>
+#include <stdlib.h>
+#include <dlfcn.h>
+#include <cutils/str_parms.h>
+#include <cutils/log.h>
+#include <cutils/misc.h>
+
+#include "audio_hw.h"
+#include "platform.h"
+#include "platform_api.h"
+#include "audio_extn.h"
+
+#define AUDIO_OUTPUT_POLICY_VENDOR_CONFIG_FILE "/vendor/etc/audio_output_policy.conf"
+
+#define OUTPUTS_TAG "outputs"
+
+#define DYNAMIC_VALUE_TAG "dynamic"
+#define FLAGS_TAG "flags"
+#define FORMATS_TAG "formats"
+#define SAMPLING_RATES_TAG "sampling_rates"
+#define BIT_WIDTH_TAG "bit_width"
+#define APP_TYPE_TAG "app_type"
+
+#define STRING_TO_ENUM(string) { #string, string }
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
+
+struct string_to_enum {
+    const char *name;
+    uint32_t value;
+};
+
+const struct string_to_enum s_flag_name_to_enum_table[] = {
+    STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_DIRECT),
+    STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_PRIMARY),
+    STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_FAST),
+    STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_DEEP_BUFFER),
+    STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD),
+    STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_NON_BLOCKING),
+#ifdef INCALL_MUSIC_ENABLED
+    STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_INCALL_MUSIC),
+#endif
+#ifdef COMPRESS_VOIP_ENABLED
+    STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_VOIP_RX),
+#endif
+};
+
+const struct string_to_enum s_format_name_to_enum_table[] = {
+    STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
+    STRING_TO_ENUM(AUDIO_FORMAT_PCM_8_BIT),
+    STRING_TO_ENUM(AUDIO_FORMAT_MP3),
+    STRING_TO_ENUM(AUDIO_FORMAT_AAC),
+    STRING_TO_ENUM(AUDIO_FORMAT_VORBIS),
+#ifdef FORMATS_ENABLED
+    STRING_TO_ENUM(AUDIO_FORMAT_AC3),
+    STRING_TO_ENUM(AUDIO_FORMAT_EAC3),
+    STRING_TO_ENUM(AUDIO_FORMAT_DTS),
+    STRING_TO_ENUM(AUDIO_FORMAT_DTS_LBR),
+    STRING_TO_ENUM(AUDIO_FORMAT_WMA),
+    STRING_TO_ENUM(AUDIO_FORMAT_WMA_PRO),
+    STRING_TO_ENUM(AUDIO_FORMAT_AAC_ADIF),
+    STRING_TO_ENUM(AUDIO_FORMAT_AMR_NB),
+    STRING_TO_ENUM(AUDIO_FORMAT_AMR_WB),
+    STRING_TO_ENUM(AUDIO_FORMAT_AMR_WB_PLUS),
+    STRING_TO_ENUM(AUDIO_FORMAT_EVRC),
+    STRING_TO_ENUM(AUDIO_FORMAT_EVRCB),
+    STRING_TO_ENUM(AUDIO_FORMAT_EVRCWB),
+    STRING_TO_ENUM(AUDIO_FORMAT_QCELP),
+    STRING_TO_ENUM(AUDIO_FORMAT_MP2),
+    STRING_TO_ENUM(AUDIO_FORMAT_EVRCNW),
+    STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT_OFFLOAD),
+    STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_OFFLOAD),
+#endif
+};
+
+static uint32_t string_to_enum(const struct string_to_enum *table, size_t size,
+                               const char *name)
+{
+    size_t i;
+    for (i = 0; i < size; i++) {
+        if (strcmp(table[i].name, name) == 0) {
+            ALOGV("%s found %s", __func__, table[i].name);
+            return table[i].value;
+        }
+    }
+    return 0;
+}
+
+static audio_output_flags_t parse_flag_names(char *name)
+{
+    uint32_t flag = 0;
+    char *flag_name = strtok(name, "|");
+    while (flag_name != NULL) {
+        if (strlen(flag_name) != 0) {
+            flag |= string_to_enum(s_flag_name_to_enum_table,
+                               ARRAY_SIZE(s_flag_name_to_enum_table),
+                               flag_name);
+        }
+        flag_name = strtok(NULL, "|");
+    }
+
+    ALOGV("parse_flag_names: flag - %d", flag);
+    return (audio_output_flags_t)flag;
+}
+
+static void parse_format_names(char *name, struct streams_output_cfg *so_info)
+{
+    struct stream_format *sf_info = NULL;
+    char *str = strtok(name, "|");
+
+    if (str != NULL && strcmp(str, DYNAMIC_VALUE_TAG) == 0)
+        return;
+
+    list_init(&so_info->format_list);
+    while (str != NULL) {
+        audio_format_t format = (audio_format_t)string_to_enum(s_format_name_to_enum_table,
+                                              ARRAY_SIZE(s_format_name_to_enum_table), str);
+        ALOGV("%s: format - %d", __func__, format);
+        if (format != 0) {
+            sf_info = (struct stream_format *)calloc(1, sizeof(struct stream_format));
+            sf_info->format = format;
+            list_add_tail(&so_info->format_list, &sf_info->list);
+        }
+        str = strtok(NULL, "|");
+    }
+}
+
+static int parse_sample_rate_names(char *name)
+{
+    int sample_rate = 48000;
+    char *str = strtok(name, "|");
+
+    if (str != NULL && strcmp(str, DYNAMIC_VALUE_TAG))
+        sample_rate = (int)strtol(str, (char **)NULL, 10);
+
+    ALOGV("%s: sample_rate - %d", __func__, sample_rate);
+    return sample_rate;
+}
+
+static int parse_bit_width_names(char *name)
+{
+    int bit_width = 16;
+    char *str = strtok(name, "|");
+
+    if (str != NULL && strcmp(str, DYNAMIC_VALUE_TAG))
+        bit_width = (int)strtol(str, (char **)NULL, 10);
+
+    ALOGV("%s: bit_width - %d", __func__, bit_width);
+    return bit_width;
+}
+
+static int parse_app_type_names(void *platform, char *name)
+{
+    int app_type = platform_get_default_app_type(platform);
+    char *str = strtok(name, "|");
+
+    if (str != NULL && strcmp(str, DYNAMIC_VALUE_TAG))
+        app_type = (int)strtol(str, (char **)NULL, 10);
+
+    ALOGV("%s: app_type - %d", __func__, app_type);
+    return app_type;
+}
+
+static void update_streams_output_cfg_list(cnode *root, void *platform,
+                                           struct listnode *streams_output_cfg_list)
+{
+    cnode *node = root->first_child;
+    struct streams_output_cfg *so_info;
+
+    ALOGV("%s", __func__);
+    so_info = (struct streams_output_cfg *)calloc(1, sizeof(struct streams_output_cfg));
+    while (node) {
+        if (strcmp(node->name, FLAGS_TAG) == 0) {
+            so_info->flags = parse_flag_names((char *)node->value);
+        } else if (strcmp(node->name, FORMATS_TAG) == 0) {
+            parse_format_names((char *)node->value, so_info);
+        } else if (strcmp(node->name, SAMPLING_RATES_TAG) == 0) {
+            so_info->app_type_cfg.sample_rate = parse_sample_rate_names((char *)node->value);
+        } else if (strcmp(node->name, BIT_WIDTH_TAG) == 0) {
+            so_info->app_type_cfg.bit_width = parse_bit_width_names((char *)node->value);
+        } else if (strcmp(node->name, APP_TYPE_TAG) == 0) {
+            so_info->app_type_cfg.app_type = parse_app_type_names(platform, (char *)node->value);
+        }
+        node = node->next;
+    }
+    list_add_tail(streams_output_cfg_list, &so_info->list);
+}
+
+static void load_output(cnode *root, void *platform,
+                        struct listnode *streams_output_cfg_list)
+{
+    cnode *node = config_find(root, OUTPUTS_TAG);
+    if (node == NULL) {
+        ALOGE("%s: could not load output, node is NULL", __func__);
+        return;
+    }
+
+    node = node->first_child;
+    while (node) {
+        ALOGV("%s: loading output %s", __func__, node->name);
+        update_streams_output_cfg_list(node, platform, streams_output_cfg_list);
+        node = node->next;
+    }
+}
+
+static void send_app_type_cfg(void *platform, struct mixer *mixer,
+                              struct listnode *streams_output_cfg_list)
+{
+    int app_type_cfg[MAX_LENGTH_MIXER_CONTROL_IN_INT] = {-1};
+    int length = 0, i, num_app_types = 0;
+    struct listnode *node;
+    bool update;
+    struct mixer_ctl *ctl = NULL;
+    const char *mixer_ctl_name = "App Type Config";
+    struct streams_output_cfg *so_info;
+
+    if (!mixer) {
+        ALOGE("%s: mixer is null",__func__);
+        return;
+    }
+    ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
+    if (!ctl) {
+        ALOGE("%s: Could not get ctl for mixer cmd - %s",__func__, mixer_ctl_name);
+        return;
+    }
+    if (streams_output_cfg_list == NULL) {
+        app_type_cfg[length++] = 1;
+        app_type_cfg[length++] = platform_get_default_app_type(platform);
+        app_type_cfg[length++] = 48000;
+        app_type_cfg[length++] = 16;
+        mixer_ctl_set_array(ctl, app_type_cfg, length);
+        return;
+    }
+
+    app_type_cfg[length++] = num_app_types;
+    list_for_each(node, streams_output_cfg_list) {
+        so_info = node_to_item(node, struct streams_output_cfg, list);
+        update = true;
+        for (i=0; i<length; i=i+3) {
+            if (app_type_cfg[i+1] == -1)
+                break;
+            else if (app_type_cfg[i+1] == so_info->app_type_cfg.app_type) {
+                update = false;
+                break;
+            }
+        }
+        if (update && ((length + 3) <= MAX_LENGTH_MIXER_CONTROL_IN_INT)) {
+            num_app_types += 1 ;
+            app_type_cfg[length++] = so_info->app_type_cfg.app_type;
+            app_type_cfg[length++] = so_info->app_type_cfg.sample_rate;
+            app_type_cfg[length++] = so_info->app_type_cfg.bit_width;
+        }
+    }
+    ALOGV("%s: num_app_types: %d", __func__, num_app_types);
+    if (num_app_types) {
+        app_type_cfg[0] = num_app_types;
+        mixer_ctl_set_array(ctl, app_type_cfg, length);
+    }
+}
+
+void audio_extn_utils_update_streams_output_cfg_list(void *platform,
+                                       struct mixer *mixer,
+                                       struct listnode *streams_output_cfg_list)
+{
+    cnode *root;
+    char *data;
+
+    ALOGV("%s", __func__);
+    list_init(streams_output_cfg_list);
+    data = (char *)load_file(AUDIO_OUTPUT_POLICY_VENDOR_CONFIG_FILE, NULL);
+    if (data == NULL) {
+        send_app_type_cfg(platform, mixer, NULL);
+        ALOGE("%s: could not load output policy config file", __func__);
+        return;
+    }
+
+    root = config_node("", "");
+    config_load(root, data);
+    load_output(root, platform, streams_output_cfg_list);
+
+    send_app_type_cfg(platform, mixer, streams_output_cfg_list);
+}
+
+void audio_extn_utils_dump_streams_output_cfg_list(
+                                       struct listnode *streams_output_cfg_list)
+{
+    int i=0;
+    struct listnode *node_i, *node_j;
+    struct streams_output_cfg *so_info;
+    struct stream_format *sf_info;
+    ALOGV("%s", __func__);
+    list_for_each(node_i, streams_output_cfg_list) {
+        so_info = node_to_item(node_i, struct streams_output_cfg, list);
+        ALOGV("%d: flags-%d, output_sample_rate-%d, output_bit_width-%d, app_type-%d",
+               i++, so_info->flags, so_info->app_type_cfg.sample_rate,
+               so_info->app_type_cfg.bit_width, so_info->app_type_cfg.app_type);
+        list_for_each(node_j, &so_info->format_list) {
+            sf_info = node_to_item(node_j, struct stream_format, list);
+            ALOGV("format-%x", sf_info->format);
+        }
+    }
+}
+
+void audio_extn_utils_release_streams_output_cfg_list(
+                                       struct listnode *streams_output_cfg_list)
+{
+    struct listnode *node_i, *node_j;
+    struct streams_output_cfg *so_info;
+    struct stream_format *sf_info;
+
+    ALOGV("%s", __func__);
+    while (!list_empty(streams_output_cfg_list)) {
+        node_i = list_head(streams_output_cfg_list);
+        so_info = node_to_item(node_i, struct streams_output_cfg, list);
+        while (!list_empty(&so_info->format_list)) {
+            node_j = list_head(&so_info->format_list);
+            list_remove(node_j);
+            free(node_to_item(node_j, struct stream_format, list));
+        }
+        list_remove(node_i);
+        free(node_to_item(node_i, struct streams_output_cfg, list));
+    }
+}
+
+void audio_extn_utils_update_stream_app_type_cfg(void *platform,
+                                  struct listnode *streams_output_cfg_list,
+                                  audio_output_flags_t flags,
+                                  audio_format_t format,
+                                  struct stream_app_type_cfg *app_type_cfg)
+{
+    struct listnode *node_i, *node_j;
+    struct streams_output_cfg *so_info;
+    struct stream_format *sf_info;
+
+    ALOGV("%s: flags: %x, format: %x", __func__, flags, format);
+    list_for_each(node_i, streams_output_cfg_list) {
+        so_info = node_to_item(node_i, struct streams_output_cfg, list);
+        if (so_info->flags == flags) {
+            list_for_each(node_j, &so_info->format_list) {
+                sf_info = node_to_item(node_j, struct stream_format, list);
+                if (sf_info->format == format) {
+                    ALOGV("App type: %d", so_info->app_type_cfg.app_type);
+                    app_type_cfg->app_type = so_info->app_type_cfg.app_type;
+                    app_type_cfg->sample_rate = so_info->app_type_cfg.sample_rate;
+                    app_type_cfg->bit_width = so_info->app_type_cfg.bit_width;
+                    return;
+                }
+            }
+        }
+    }
+    list_for_each(node_i, streams_output_cfg_list) {
+        so_info = node_to_item(node_i, struct streams_output_cfg, list);
+        if (so_info->flags == AUDIO_OUTPUT_FLAG_PRIMARY) {
+            ALOGV("Compatible output profile not found.");
+            ALOGV("App type default to primary output: %d", so_info->app_type_cfg.app_type);
+            app_type_cfg->app_type = so_info->app_type_cfg.app_type;
+            app_type_cfg->sample_rate = so_info->app_type_cfg.sample_rate;
+            app_type_cfg->bit_width = so_info->app_type_cfg.bit_width;
+            return;
+        }
+    }
+    ALOGW("%s: App type could not be selected. Falling back to default", __func__);
+    app_type_cfg->app_type = platform_get_default_app_type(platform);
+    app_type_cfg->sample_rate = 48000;
+    app_type_cfg->bit_width = 16;
+}
+
+int audio_extn_utils_send_app_type_cfg(struct audio_usecase *usecase)
+{
+    char mixer_ctl_name[MAX_LENGTH_MIXER_CONTROL_IN_INT];
+    int app_type_cfg[MAX_LENGTH_MIXER_CONTROL_IN_INT], len = 0, rc;
+    struct stream_out *out = usecase->stream.out;
+    struct audio_device *adev = out->dev;
+    struct mixer_ctl *ctl;
+    int pcm_device_id, acdb_dev_id, snd_device = usecase->out_snd_device;
+
+    ALOGV("%s", __func__);
+
+    if (usecase->type != PCM_PLAYBACK) {
+        ALOGV("%s: not a playback path, no need to cfg app type", __func__);
+        rc = 0;
+        goto exit_send_app_type_cfg;
+    }
+    if ((usecase->id != USECASE_AUDIO_PLAYBACK_DEEP_BUFFER) &&
+        (usecase->id != USECASE_AUDIO_PLAYBACK_LOW_LATENCY) &&
+        (usecase->id != USECASE_AUDIO_PLAYBACK_MULTI_CH) &&
+        (usecase->id != USECASE_AUDIO_PLAYBACK_OFFLOAD)) {
+        ALOGV("%s: a playback path where app type cfg is not required", __func__);
+        rc = 0;
+        goto exit_send_app_type_cfg;
+    }
+
+    snd_device = usecase->out_snd_device;
+
+    pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
+
+    snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
+             "Audio Stream %d App Type Cfg", pcm_device_id);
+
+    ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
+    if (!ctl) {
+        ALOGE("%s: Could not get ctl for mixer cmd - %s", __func__,
+              mixer_ctl_name);
+        rc = -EINVAL;
+        goto exit_send_app_type_cfg;
+    }
+    snd_device = (snd_device == SND_DEVICE_OUT_SPEAKER) ?
+                 audio_extn_get_spkr_prot_snd_device(snd_device) : snd_device;
+    acdb_dev_id = platform_get_snd_device_acdb_id(snd_device);
+    if (acdb_dev_id < 0) {
+        ALOGE("%s: Couldn't get the acdb dev id", __func__);
+        rc = -EINVAL;
+        goto exit_send_app_type_cfg;
+    }
+    app_type_cfg[len++] = out->app_type_cfg.app_type;
+    app_type_cfg[len++] = acdb_dev_id;
+
+    mixer_ctl_set_array(ctl, app_type_cfg, len);
+
+    rc = 0;
+exit_send_app_type_cfg:
+    return rc;
+}
+
+void audio_extn_utils_send_audio_calibration(struct audio_device *adev,
+                                             struct audio_usecase *usecase)
+{
+    int type = usecase->type;
+
+    if (type == PCM_PLAYBACK) {
+        struct stream_out *out = usecase->stream.out;
+        int snd_device = usecase->out_snd_device;
+        snd_device = (snd_device == SND_DEVICE_OUT_SPEAKER) ?
+                     audio_extn_get_spkr_prot_snd_device(snd_device) : snd_device;
+        platform_send_audio_calibration(adev->platform, usecase->out_snd_device,
+                                        out->app_type_cfg.app_type,
+                                        out->app_type_cfg.sample_rate);
+    }
+    if ((type == PCM_HFP_CALL) || (type == PCM_CAPTURE)) {
+        /* when app type is default. the sample rate is not used to send cal */
+        platform_send_audio_calibration(adev->platform, usecase->in_snd_device,
+                                        platform_get_default_app_type(adev->platform),
+                                        48000);
+    }
+}
+
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index 5d12dce..b54261e 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -257,6 +257,8 @@
     audio_extn_dolby_set_dmid(adev);
     audio_extn_dolby_set_endpoint(adev);
 #endif
+    audio_extn_utils_send_audio_calibration(adev, usecase);
+    audio_extn_utils_send_app_type_cfg(usecase);
     strcpy(mixer_path, use_case_table[usecase->id]);
     platform_add_backend_name(mixer_path, snd_device);
     ALOGV("%s: apply mixer and update path: %s", __func__, mixer_path);
@@ -322,6 +324,10 @@
     if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
         snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
         audio_extn_spkr_prot_is_enabled()) {
+       if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) {
+           adev->snd_dev_ref_cnt[snd_device]--;
+           return -EINVAL;
+       }
         if (audio_extn_spkr_prot_start_processing(snd_device)) {
             ALOGE("%s: spkr_start_processing failed", __func__);
             return -EINVAL;
@@ -333,7 +339,7 @@
             and audio, notify listen hal before audio calibration is sent */
         audio_extn_listen_update_status(snd_device,
                        LISTEN_EVENT_SND_DEVICE_BUSY);
-        if (platform_send_audio_calibration(adev->platform, snd_device) < 0) {
+        if (platform_get_snd_device_acdb_id(snd_device) < 0) {
             adev->snd_dev_ref_cnt[snd_device]--;
             audio_extn_listen_update_status(snd_device,
                            LISTEN_EVENT_SND_DEVICE_FREE);
@@ -1535,8 +1541,7 @@
                     !voice_is_in_call(adev) &&
                     (out == adev->primary_output)) {
                 ret = voice_start_call(adev);
-            } else if ((adev->mode == AUDIO_MODE_IN_CALL) &&
-                            voice_is_in_call(adev) &&
+            } else if (voice_is_in_call(adev) &&
                             (out == adev->primary_output)) {
                 voice_update_devices_for_all_voice_usecases(adev);
             }
@@ -2200,6 +2205,7 @@
     struct audio_device *adev = (struct audio_device *)dev;
     struct stream_out *out;
     int i, ret = 0;
+    audio_format_t format;
 
     *stream_out = NULL;
     out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
@@ -2222,7 +2228,7 @@
     out->flags = flags;
     out->devices = devices;
     out->dev = adev;
-    out->format = config->format;
+    format = out->format = config->format;
     out->sample_rate = config->sample_rate;
     out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
     out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
@@ -2288,7 +2294,7 @@
             out->channel_mask = config->channel_mask;
             config->offload_info.channel_mask = config->channel_mask;
         }
-        out->format = config->offload_info.format;
+        format = out->format = config->offload_info.format;
         out->sample_rate = config->offload_info.sample_rate;
 
         out->stream.set_callback = out_set_callback;
@@ -2348,16 +2354,21 @@
             goto error_open;
         }
     } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
+        format = AUDIO_FORMAT_PCM_16_BIT;
         out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
         out->config = pcm_config_low_latency;
         out->sample_rate = out->config.rate;
     } else {
         /* primary path is the default path selected if no other outputs are available/suitable */
+        format = AUDIO_FORMAT_PCM_16_BIT;
         out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
         out->config = pcm_config_deep_buffer;
         out->sample_rate = out->config.rate;
     }
 
+    audio_extn_utils_update_stream_app_type_cfg(adev->platform,
+                                                &adev->streams_output_cfg_list,
+                                                flags, format, &out->app_type_cfg);
     if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
         (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
         /* Ensure the default output is not selected twice */
@@ -2770,6 +2781,7 @@
 
     if ((--audio_device_ref_count) == 0) {
         audio_extn_listen_deinit(adev);
+        audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
         audio_route_free(adev->audio_route);
         free(adev->snd_dev_ref_cnt);
         platform_deinit(adev->platform);
@@ -2889,6 +2901,9 @@
 
     *device = &adev->device.common;
 
+    audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
+                                                    &adev->streams_output_cfg_list);
+
     audio_device_ref_count++;
     pthread_mutex_unlock(&adev_init_lock);
 
diff --git a/hal/audio_hw.h b/hal/audio_hw.h
index a602e56..1b2606c 100644
--- a/hal/audio_hw.h
+++ b/hal/audio_hw.h
@@ -146,6 +146,12 @@
     int data[];
 };
 
+struct stream_app_type_cfg {
+    int sample_rate;
+    int bit_width;
+    int app_type;
+};
+
 struct stream_out {
     struct audio_stream_out stream;
     pthread_mutex_t lock; /* see note below on mutex acquisition order */
@@ -167,6 +173,7 @@
     bool muted;
     uint64_t written; /* total frames written, not cleared when entering standby */
     audio_io_handle_t handle;
+    struct stream_app_type_cfg app_type_cfg;
 
     int non_blocking;
     int playback_started;
@@ -230,6 +237,18 @@
     int state;
 };
 
+struct stream_format {
+    struct listnode list;
+    audio_format_t format;
+};
+
+struct streams_output_cfg {
+    struct listnode list;
+    audio_output_flags_t flags;
+    struct listnode format_list;
+    struct stream_app_type_cfg app_type_cfg;
+};
+
 struct audio_device {
     struct audio_hw_device device;
     pthread_mutex_t lock; /* see note below on mutex acquisition order */
@@ -242,6 +261,7 @@
     bool screen_off;
     int *snd_dev_ref_cnt;
     struct listnode usecase_list;
+    struct listnode streams_output_cfg_list;
     struct audio_route *audio_route;
     int acdb_settings;
     bool speaker_lr_swap;
diff --git a/hal/msm8916/hw_info.c b/hal/msm8916/hw_info.c
index 4f35ffc..9ea86ad 100644
--- a/hal/msm8916/hw_info.c
+++ b/hal/msm8916/hw_info.c
@@ -149,8 +149,32 @@
         hw_info->snd_devices = NULL;
         hw_info->num_snd_devices = 0;
         strlcpy(hw_info->dev_extn, "", sizeof(hw_info->dev_extn));
+    } else if (!strcmp(snd_card_name, "msm8939-snd-card")) {
+        strlcpy(hw_info->type, "", sizeof(hw_info->type));
+        strlcpy(hw_info->name, "msm8939", sizeof(hw_info->name));
+        hw_info->snd_devices = NULL;
+        hw_info->num_snd_devices = 0;
+        strlcpy(hw_info->dev_extn, "", sizeof(hw_info->dev_extn));
+    } else if (!strcmp(snd_card_name, "msm8939-snd-card-mtp")) {
+        strlcpy(hw_info->type, "", sizeof(hw_info->type));
+        strlcpy(hw_info->name, "msm8939", sizeof(hw_info->name));
+        hw_info->snd_devices = NULL;
+        hw_info->num_snd_devices = 0;
+        strlcpy(hw_info->dev_extn, "", sizeof(hw_info->dev_extn));
+    } else if (!strcmp(snd_card_name, "msm8939-skuh-snd-card")) {
+        strlcpy(hw_info->type, "skuh", sizeof(hw_info->type));
+        strlcpy(hw_info->name, "msm8939", sizeof(hw_info->name));
+        hw_info->snd_devices = NULL;
+        hw_info->num_snd_devices = 0;
+        strlcpy(hw_info->dev_extn, "", sizeof(hw_info->dev_extn));
+    } else if (!strcmp(snd_card_name, "msm8939-skui-snd-card")) {
+        strlcpy(hw_info->type, "skui", sizeof(hw_info->type));
+        strlcpy(hw_info->name, "msm8939", sizeof(hw_info->name));
+        hw_info->snd_devices = NULL;
+        hw_info->num_snd_devices = 0;
+        strlcpy(hw_info->dev_extn, "", sizeof(hw_info->dev_extn));
     } else {
-        ALOGW("%s: Not an  8x16 device", __func__);
+        ALOGW("%s: Not an  8x16/8939 device", __func__);
     }
 }
 
@@ -160,7 +184,7 @@
 
     hw_info = malloc(sizeof(struct hardware_info));
 
-    if(strstr(snd_card_name, "msm8x16")) {
+    if(strstr(snd_card_name, "msm8x16") || strstr(snd_card_name, "msm8939")) {
         ALOGV("8x16 - variant soundcard");
         update_hardware_info_8x16(hw_info, snd_card_name);
     } else {
diff --git a/hal/msm8916/platform.c b/hal/msm8916/platform.c
index c71706c..d92f707 100644
--- a/hal/msm8916/platform.c
+++ b/hal/msm8916/platform.c
@@ -70,6 +70,9 @@
 /* EDID format ID for LPCM audio */
 #define EDID_FORMAT_LPCM    1
 
+/* fallback app type if the default app type from acdb loader fails */
+#define DEFAULT_APP_TYPE  0x11130
+
 /* Retry for delay in FW loading*/
 #define RETRY_NUMBER 20
 #define RETRY_US 500000
@@ -97,9 +100,10 @@
 /* Audio calibration related functions */
 typedef void (*acdb_deallocate_t)();
 typedef int  (*acdb_init_t)(char *);
-typedef void (*acdb_send_audio_cal_t)(int, int);
+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);
+typedef int  (*acdb_get_default_app_type_t)(void);
 
 struct platform_data {
     struct audio_device *adev;
@@ -119,6 +123,7 @@
     acdb_send_audio_cal_t      acdb_send_audio_cal;
     acdb_send_voice_cal_t      acdb_send_voice_cal;
     acdb_reload_vocvoltable_t  acdb_reload_vocvoltable;
+    acdb_get_default_app_type_t acdb_get_default_app_type;
 
     void *hw_info;
     struct csd_data *csd;
@@ -412,6 +417,10 @@
                  sizeof("msm8x16-skui-snd-card"))) {
         strlcpy(mixer_xml_path, MIXER_XML_PATH_QRD_SKUI,
                 sizeof(MIXER_XML_PATH_QRD_SKUI));
+    } if (!strncmp(snd_card_name, "msm8939-snd-card-mtp",
+                 sizeof("msm8939-snd-card-mtp"))) {
+        strlcpy(mixer_xml_path, MIXER_XML_PATH,
+                sizeof(MIXER_XML_PATH));
     } else {
         strlcpy(mixer_xml_path, MIXER_XML_PATH,
                 sizeof(MIXER_XML_PATH));
@@ -680,7 +689,7 @@
                   __func__, LIB_ACDB_LOADER);
 
         my_data->acdb_send_audio_cal = (acdb_send_audio_cal_t)dlsym(my_data->acdb_handle,
-                                                    "acdb_loader_send_audio_cal");
+                                                    "acdb_loader_send_audio_cal_v2");
         if (!my_data->acdb_send_audio_cal)
             ALOGE("%s: Could not find the symbol acdb_send_audio_cal from %s",
                   __func__, LIB_ACDB_LOADER);
@@ -697,6 +706,13 @@
             ALOGE("%s: Could not find the symbol acdb_loader_reload_vocvoltable from %s",
                   __func__, LIB_ACDB_LOADER);
 
+        my_data->acdb_get_default_app_type = (acdb_get_default_app_type_t)dlsym(
+                                                    my_data->acdb_handle,
+                                                    "acdb_loader_get_default_app_type");
+        if (!my_data->acdb_get_default_app_type)
+            ALOGE("%s: Could not find the symbol acdb_get_default_app_type from %s",
+                  __func__, LIB_ACDB_LOADER);
+
         my_data->acdb_init = (acdb_init_t)dlsym(my_data->acdb_handle,
                                                     "acdb_loader_init_v2");
         if (my_data->acdb_init == NULL)
@@ -894,7 +910,27 @@
     return ret;
 }
 
-int platform_send_audio_calibration(void *platform, snd_device_t snd_device)
+int platform_get_default_app_type(void *platform)
+{
+    struct platform_data *my_data = (struct platform_data *)platform;
+
+    if (my_data->acdb_get_default_app_type)
+        return my_data->acdb_get_default_app_type();
+    else
+        return DEFAULT_APP_TYPE;
+}
+
+int platform_get_snd_device_acdb_id(snd_device_t snd_device)
+{
+    if ((snd_device < SND_DEVICE_MIN) || (snd_device >= SND_DEVICE_MAX)) {
+        ALOGE("%s: Invalid snd_device = %d", __func__, snd_device);
+        return -EINVAL;
+    }
+    return acdb_device_table[snd_device];
+}
+
+int platform_send_audio_calibration(void *platform, snd_device_t snd_device,
+                                    int app_type, int sample_rate)
 {
     struct platform_data *my_data = (struct platform_data *)platform;
     int acdb_dev_id, acdb_dev_type;
@@ -906,14 +942,15 @@
         return -EINVAL;
     }
     if (my_data->acdb_send_audio_cal) {
-        ("%s: sending audio calibration for snd_device(%d) acdb_id(%d)",
+        ALOGV("%s: sending audio calibration for snd_device(%d) acdb_id(%d)",
               __func__, snd_device, acdb_dev_id);
         if (snd_device >= SND_DEVICE_OUT_BEGIN &&
                 snd_device < SND_DEVICE_OUT_END)
             acdb_dev_type = ACDB_DEV_TYPE_OUT;
         else
             acdb_dev_type = ACDB_DEV_TYPE_IN;
-        my_data->acdb_send_audio_cal(acdb_dev_id, acdb_dev_type);
+        my_data->acdb_send_audio_cal(acdb_dev_id, acdb_dev_type, app_type,
+                                     sample_rate);
     }
     return 0;
 }
diff --git a/hal/msm8974/hw_info.c b/hal/msm8974/hw_info.c
index f43a3b0..85a9771 100644
--- a/hal/msm8974/hw_info.c
+++ b/hal/msm8974/hw_info.c
@@ -83,6 +83,31 @@
     SND_DEVICE_IN_SPEAKER_STEREO_DMIC,
 };
 
+static const snd_device_t tomtom_msm8994_CDP_variant_devices[] = {
+    SND_DEVICE_IN_HANDSET_MIC,
+};
+
+static const snd_device_t tomtom_liquid_variant_devices[] = {
+    SND_DEVICE_OUT_SPEAKER,
+    SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES,
+    SND_DEVICE_OUT_SPEAKER_AND_ANC_HEADSET,
+    SND_DEVICE_IN_SPEAKER_MIC,
+    SND_DEVICE_IN_HEADSET_MIC,
+    SND_DEVICE_IN_VOICE_DMIC,
+    SND_DEVICE_IN_VOICE_SPEAKER_DMIC,
+    SND_DEVICE_IN_VOICE_REC_DMIC_STEREO,
+    SND_DEVICE_IN_VOICE_REC_DMIC_FLUENCE,
+    SND_DEVICE_IN_QUAD_MIC,
+    SND_DEVICE_IN_HANDSET_STEREO_DMIC,
+    SND_DEVICE_IN_SPEAKER_STEREO_DMIC,
+};
+
+static const snd_device_t tomtom_stp_variant_devices[] = {
+    SND_DEVICE_OUT_SPEAKER,
+    SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES,
+    SND_DEVICE_OUT_SPEAKER_AND_ANC_HEADSET,
+};
+
 static const snd_device_t taiko_DB_variant_devices[] = {
     SND_DEVICE_OUT_SPEAKER,
     SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES,
@@ -173,6 +198,37 @@
     }
 }
 
+static void  update_hardware_info_8994(struct hardware_info *hw_info, const char *snd_card_name)
+{
+    if (!strcmp(snd_card_name, "msm8994-tomtom-mtp-snd-card")) {
+        strlcpy(hw_info->type, " mtp", sizeof(hw_info->type));
+        strlcpy(hw_info->name, "msm8994", sizeof(hw_info->name));
+        hw_info->snd_devices = NULL;
+        hw_info->num_snd_devices = 0;
+        strlcpy(hw_info->dev_extn, "", sizeof(hw_info->dev_extn));
+    } else if (!strcmp(snd_card_name, "msm8994-tomtom-cdp-snd-card ")) {
+        strlcpy(hw_info->type, " cdp", sizeof(hw_info->type));
+        strlcpy(hw_info->name, "msm8994", sizeof(hw_info->name));
+        hw_info->snd_devices = (snd_device_t *)tomtom_msm8994_CDP_variant_devices;
+        hw_info->num_snd_devices = ARRAY_SIZE(tomtom_msm8994_CDP_variant_devices);
+        strlcpy(hw_info->dev_extn, "-cdp", sizeof(hw_info->dev_extn));
+    } else if (!strcmp(snd_card_name, "msm8994-tomtom-stp-snd-card ")) {
+        strlcpy(hw_info->type, " stp", sizeof(hw_info->type));
+        strlcpy(hw_info->name, "msm8994", sizeof(hw_info->name));
+        hw_info->snd_devices = (snd_device_t *)tomtom_stp_variant_devices;
+        hw_info->num_snd_devices = ARRAY_SIZE(tomtom_stp_variant_devices);
+        strlcpy(hw_info->dev_extn, "-stp", sizeof(hw_info->dev_extn));
+    } else if (!strcmp(snd_card_name, "msm8994-tomtom-liquid-snd-card ")) {
+        strlcpy(hw_info->type, " liquid", sizeof(hw_info->type));
+        strlcpy(hw_info->name, "msm8994", sizeof(hw_info->name));
+        hw_info->snd_devices = (snd_device_t *)tomtom_liquid_variant_devices;
+        hw_info->num_snd_devices = ARRAY_SIZE(tomtom_liquid_variant_devices);
+        strlcpy(hw_info->dev_extn, "-liquid", sizeof(hw_info->dev_extn));
+    } else {
+        ALOGW("%s: Not an 8994 device", __func__);
+    }
+}
+
 static void  update_hardware_info_8974(struct hardware_info *hw_info, const char *snd_card_name)
 {
     if (!strcmp(snd_card_name, "msm8974-taiko-mtp-snd-card")) {
@@ -273,6 +329,9 @@
     hw_info = malloc(sizeof(struct hardware_info));
     hw_info->snd_devices = NULL;
     hw_info->num_snd_devices = 0;
+    strlcpy(hw_info->dev_extn, "", sizeof(hw_info->dev_extn));
+    strlcpy(hw_info->type, "", sizeof(hw_info->type));
+    strlcpy(hw_info->name, "", sizeof(hw_info->name));
 
     if(strstr(snd_card_name, "msm8974") ||
               strstr(snd_card_name, "apq8074")) {
@@ -287,6 +346,9 @@
     } else if(strstr(snd_card_name, "apq8084")) {
         ALOGV("8084 - variant soundcard");
         update_hardware_info_8084(hw_info, snd_card_name);
+    } else if(strstr(snd_card_name, "msm8994")) {
+        ALOGV("8994 - variant soundcard");
+        update_hardware_info_8994(hw_info, snd_card_name);
     } else {
         ALOGE("%s: Unsupported target %s:",__func__, snd_card_name);
         free(hw_info);
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index ecb8b50..82bafe5 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -74,6 +74,9 @@
 /* EDID format ID for LPCM audio */
 #define EDID_FORMAT_LPCM    1
 
+/* fallback app type if the default app type from acdb loader fails */
+#define DEFAULT_APP_TYPE  0x11130
+
 /* Retry for delay in FW loading*/
 #define RETRY_NUMBER 10
 #define RETRY_US 500000
@@ -101,9 +104,10 @@
 /* Audio calibration related functions */
 typedef void (*acdb_deallocate_t)();
 typedef int  (*acdb_init_t)(char *);
-typedef void (*acdb_send_audio_cal_t)(int, int);
+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);
+typedef int  (*acdb_get_default_app_type_t)(void);
 
 struct platform_data {
     struct audio_device *adev;
@@ -125,6 +129,7 @@
     acdb_send_audio_cal_t      acdb_send_audio_cal;
     acdb_send_voice_cal_t      acdb_send_voice_cal;
     acdb_reload_vocvoltable_t  acdb_reload_vocvoltable;
+    acdb_get_default_app_type_t acdb_get_default_app_type;
 
     void *hw_info;
     struct csd_data *csd;
@@ -743,7 +748,7 @@
                   __func__, LIB_ACDB_LOADER);
 
         my_data->acdb_send_audio_cal = (acdb_send_audio_cal_t)dlsym(my_data->acdb_handle,
-                                                    "acdb_loader_send_audio_cal");
+                                                    "acdb_loader_send_audio_cal_v2");
         if (!my_data->acdb_send_audio_cal)
             ALOGE("%s: Could not find the symbol acdb_send_audio_cal from %s",
                   __func__, LIB_ACDB_LOADER);
@@ -760,6 +765,13 @@
             ALOGE("%s: Could not find the symbol acdb_loader_reload_vocvoltable from %s",
                   __func__, LIB_ACDB_LOADER);
 
+        my_data->acdb_get_default_app_type = (acdb_get_default_app_type_t)dlsym(
+                                                    my_data->acdb_handle,
+                                                    "acdb_loader_get_default_app_type");
+        if (!my_data->acdb_get_default_app_type)
+            ALOGE("%s: Could not find the symbol acdb_get_default_app_type from %s",
+                  __func__, LIB_ACDB_LOADER);
+
         my_data->acdb_init = (acdb_init_t)dlsym(my_data->acdb_handle,
                                                     "acdb_loader_init_v2");
         if (my_data->acdb_init == NULL)
@@ -970,7 +982,27 @@
     return ret;
 }
 
-int platform_send_audio_calibration(void *platform, snd_device_t snd_device)
+int platform_get_default_app_type(void *platform)
+{
+    struct platform_data *my_data = (struct platform_data *)platform;
+
+    if (my_data->acdb_get_default_app_type)
+        return my_data->acdb_get_default_app_type();
+    else
+        return DEFAULT_APP_TYPE;
+}
+
+int platform_get_snd_device_acdb_id(snd_device_t snd_device)
+{
+    if ((snd_device < SND_DEVICE_MIN) || (snd_device >= SND_DEVICE_MAX)) {
+        ALOGE("%s: Invalid snd_device = %d", __func__, snd_device);
+        return -EINVAL;
+    }
+    return acdb_device_table[snd_device];
+}
+
+int platform_send_audio_calibration(void *platform, snd_device_t snd_device,
+                                    int app_type, int sample_rate)
 {
     struct platform_data *my_data = (struct platform_data *)platform;
     int acdb_dev_id, acdb_dev_type;
@@ -982,14 +1014,15 @@
         return -EINVAL;
     }
     if (my_data->acdb_send_audio_cal) {
-        ("%s: sending audio calibration for snd_device(%d) acdb_id(%d)",
+        ALOGV("%s: sending audio calibration for snd_device(%d) acdb_id(%d)",
               __func__, snd_device, acdb_dev_id);
         if (snd_device >= SND_DEVICE_OUT_BEGIN &&
                 snd_device < SND_DEVICE_OUT_END)
             acdb_dev_type = ACDB_DEV_TYPE_OUT;
         else
             acdb_dev_type = ACDB_DEV_TYPE_IN;
-        my_data->acdb_send_audio_cal(acdb_dev_id, acdb_dev_type);
+        my_data->acdb_send_audio_cal(acdb_dev_id, acdb_dev_type, app_type,
+                                     sample_rate);
     }
     return 0;
 }
diff --git a/hal/msm8974/platform.h b/hal/msm8974/platform.h
index ba89c1b..d7d1944 100644
--- a/hal/msm8974/platform.h
+++ b/hal/msm8974/platform.h
@@ -243,12 +243,18 @@
 #define VOLTE_CALL_PCM_DEVICE 15
 #define QCHAT_CALL_PCM_DEVICE 14
 #define VOWLAN_CALL_PCM_DEVICE -1
+#elif PLATFORM_MSM8994
+#define VOICE_CALL_PCM_DEVICE 2
+#define VOICE2_CALL_PCM_DEVICE 22
+#define VOLTE_CALL_PCM_DEVICE 14
+#define QCHAT_CALL_PCM_DEVICE 20
+#define VOWLAN_CALL_PCM_DEVICE 36
 #else
 #define VOICE_CALL_PCM_DEVICE 2
 #define VOICE2_CALL_PCM_DEVICE 22
 #define VOLTE_CALL_PCM_DEVICE 14
 #define QCHAT_CALL_PCM_DEVICE 20
-#define VOWLAN_CALL_PCM_DEVICE -1
+#define VOWLAN_CALL_PCM_DEVICE 36
 #endif
 
 #ifdef PLATFORM_MSM8x26
diff --git a/hal/platform_api.h b/hal/platform_api.h
index bf6bdcb..1e97adf 100644
--- a/hal/platform_api.h
+++ b/hal/platform_api.h
@@ -31,7 +31,10 @@
 int platform_set_fluence_type(void *platform, char *value);
 int platform_get_fluence_type(void *platform, char *value, uint32_t len);
 int platform_set_snd_device_acdb_id(snd_device_t snd_device, unsigned int acdb_id);
-int platform_send_audio_calibration(void *platform, snd_device_t snd_device);
+int platform_get_snd_device_acdb_id(snd_device_t snd_device);
+int platform_send_audio_calibration(void *platform, snd_device_t snd_device,
+                                    int app_type, int sample_rate);
+int platform_get_default_app_type(void *platform);
 int platform_switch_voice_call_device_pre(void *platform);
 int platform_switch_voice_call_enable_device_config(void *platform,
                                                     snd_device_t out_snd_device,
diff --git a/policy_hal/AudioPolicyManager.cpp b/policy_hal/AudioPolicyManager.cpp
index b679fdb..a8cbcda 100644
--- a/policy_hal/AudioPolicyManager.cpp
+++ b/policy_hal/AudioPolicyManager.cpp
@@ -1558,8 +1558,8 @@
                                                   0 /* ignored */);
        }
     }
-    mPrevPhoneState = oldState;
 #endif
+    mPrevPhoneState = oldState;
 
     int delayMs = 0;
     if (isStateInCall(state)) {
@@ -1609,6 +1609,12 @@
     ALOGD(" End of setPhoneState ... mPhoneState: %d ",mPhoneState);
 }
 
+bool AudioPolicyManager::isStateInCall(int state)
+{
+    return ((state == AudioSystem::MODE_IN_CALL) || (state == AudioSystem::MODE_IN_COMMUNICATION) ||
+       ((state == AudioSystem::MODE_RINGTONE) && (mPrevPhoneState == AudioSystem::MODE_IN_CALL)));
+}
+
 extern "C" AudioPolicyInterface* createAudioPolicyManager(AudioPolicyClientInterface *clientInterface)
 {
     return new AudioPolicyManager(clientInterface);
diff --git a/policy_hal/AudioPolicyManager.h b/policy_hal/AudioPolicyManager.h
index dce5bad..ab57768 100644
--- a/policy_hal/AudioPolicyManager.h
+++ b/policy_hal/AudioPolicyManager.h
@@ -61,6 +61,9 @@
         virtual bool isOffloadSupported(const audio_offload_info_t& offloadInfo);
 
         virtual void setPhoneState(int state);
+
+        // true if given state represents a device in a telephony or VoIP call
+        virtual bool isStateInCall(int state);
 protected:
         // return the strategy corresponding to a given stream type
         static routing_strategy getStrategy(AudioSystem::stream_type stream);
diff --git a/post_proc/bundle.c b/post_proc/bundle.c
index b11a700..a0d9fcb 100644
--- a/post_proc/bundle.c
+++ b/post_proc/bundle.c
@@ -201,6 +201,11 @@
 
     output_context_t *out_ctxt = (output_context_t *)
                                  malloc(sizeof(output_context_t));
+    if (!out_ctxt) {
+        ALOGE("%s fail to allocate for output context", __func__);
+        ret = -ENOMEM;
+        goto exit;
+    }
     out_ctxt->handle = output;
     out_ctxt->pcm_device_id = pcm_id;
 
@@ -334,6 +339,9 @@
         sizeof(effect_uuid_t)) == 0) {
         equalizer_context_t *eq_ctxt = (equalizer_context_t *)
                                        calloc(1, sizeof(equalizer_context_t));
+        if (eq_ctxt == NULL) {
+            return -ENOMEM;
+        }
         context = (effect_context_t *)eq_ctxt;
         context->ops.init = equalizer_init;
         context->ops.reset = equalizer_reset;
@@ -351,6 +359,9 @@
                sizeof(effect_uuid_t)) == 0) {
         bassboost_context_t *bass_ctxt = (bassboost_context_t *)
                                          calloc(1, sizeof(bassboost_context_t));
+        if (bass_ctxt == NULL) {
+            return -ENOMEM;
+        }
         context = (effect_context_t *)bass_ctxt;
         context->ops.init = bassboost_init;
         context->ops.reset = bassboost_reset;
@@ -368,6 +379,9 @@
                sizeof(effect_uuid_t)) == 0) {
         virtualizer_context_t *virt_ctxt = (virtualizer_context_t *)
                                            calloc(1, sizeof(virtualizer_context_t));
+        if (virt_ctxt == NULL) {
+            return -ENOMEM;
+        }
         context = (effect_context_t *)virt_ctxt;
         context->ops.init = virtualizer_init;
         context->ops.reset = virtualizer_reset;
@@ -391,6 +405,9 @@
                 sizeof(effect_uuid_t)) == 0)) {
         reverb_context_t *reverb_ctxt = (reverb_context_t *)
                                         calloc(1, sizeof(reverb_context_t));
+        if (reverb_ctxt == NULL) {
+            return -ENOMEM;
+        }
         context = (effect_context_t *)reverb_ctxt;
         context->ops.init = reverb_init;
         context->ops.reset = reverb_reset;
diff --git a/post_proc/effect_api.c b/post_proc/effect_api.c
index bad6ee1..971b67f 100644
--- a/post_proc/effect_api.c
+++ b/post_proc/effect_api.c
@@ -318,7 +318,8 @@
     uint32_t i;
 
     ALOGV("%s: flags 0x%x", __func__, param_send_flags);
-    if (eq.config.preset_id < -1 ) {
+    if ((eq.config.preset_id < -1) ||
+            ((param_send_flags & OFFLOAD_SEND_EQ_PRESET) && (eq.config.preset_id == -1))) {
         ALOGV("No Valid preset to set");
         return 0;
     }
diff --git a/visualizer/offload_visualizer.c b/visualizer/offload_visualizer.c
index 95b4687..94c44a5 100644
--- a/visualizer/offload_visualizer.c
+++ b/visualizer/offload_visualizer.c
@@ -431,6 +431,11 @@
     }
 
     output_context_t *out_ctxt = (output_context_t *)malloc(sizeof(output_context_t));
+    if (out_ctxt == NULL) {
+        ALOGE("%s fail to allocate memory", __func__);
+        ret = -ENOMEM;
+        goto exit;
+    }
     out_ctxt->handle = output;
     list_init(&out_ctxt->effects_list);
 
@@ -927,6 +932,10 @@
     if (memcmp(uuid, &visualizer_descriptor.uuid, sizeof(effect_uuid_t)) == 0) {
         visualizer_context_t *visu_ctxt = (visualizer_context_t *)calloc(1,
                                                                      sizeof(visualizer_context_t));
+        if (visu_ctxt == NULL) {
+            ALOGE("%s fail to allocate memory", __func__);
+            return -ENOMEM;
+        }
         context = (effect_context_t *)visu_ctxt;
         context->ops.init = visualizer_init;
         context->ops.reset = visualizer_reset;
diff --git a/voice_processing/voice_processing.c b/voice_processing/voice_processing.c
index b8b1e1b..1d18a3d 100644
--- a/voice_processing/voice_processing.c
+++ b/voice_processing/voice_processing.c
@@ -408,6 +408,10 @@
     }
 
     session = (struct session_s *)calloc(1, sizeof(struct session_s));
+    if (session == NULL) {
+        ALOGE("get_session() fail to allocate memory");
+        return NULL;
+    }
     session_init(session);
     session->id = sessionId;
     session->io = ioId;
@@ -682,6 +686,10 @@
         return -EINVAL;
     }
     id = uuid_to_id(&desc->type);
+    if (id >= NUM_ID) {
+        ALOGW("lib_create: fx not found type: %08x", desc->type.timeLow);
+        return -EINVAL;
+    }
 
     session = get_session(id, sessionId, ioId);