[automerger skipped] Merge "DO NOT MERGE - Merge pie-platform-release (PPRL.190105.001) into master" am: d895cc82f8 -s ours am: 050abd84e0 -s ours
am: 019506dd32 -s ours
am skip reason: subject contains skip directive

Change-Id: I4f05ea84f56a66c5033830ec6dd0d74b294df46e
diff --git a/hal/Android.mk b/hal/Android.mk
index 236ed11..7f93710 100644
--- a/hal/Android.mk
+++ b/hal/Android.mk
@@ -197,7 +197,6 @@
     LOCAL_SRC_FILES += audio_extn/sndmonitor.c
 endif
 
-
 ifeq ($(strip $(AUDIO_FEATURE_ENABLED_USB_SERVICE_INTERVAL)), true)
     LOCAL_CFLAGS += -DUSB_SERVICE_INTERVAL_ENABLED
 endif
@@ -215,6 +214,10 @@
     LOCAL_CFLAGS += -DBG_CODEC_CAL
 endif
 
+ifeq ($(strip $(AUDIO_FEATURE_ENABLED_DYNAMIC_ECNS)),true)
+    LOCAL_CFLAGS += -DDYNAMIC_ECNS_ENABLED
+endif
+
 LOCAL_SHARED_LIBRARIES += libbase libhidlbase libhwbinder libutils android.hardware.power@1.2 liblog
 
 LOCAL_SRC_FILES += audio_perf.cpp
diff --git a/hal/audio_extn/a2dp.c b/hal/audio_extn/a2dp.c
index 671fe59..7c2e4db 100644
--- a/hal/audio_extn/a2dp.c
+++ b/hal/audio_extn/a2dp.c
@@ -141,6 +141,7 @@
                                enc_codec_t *codec_type);
 typedef int (*audio_check_a2dp_ready_t)(void);
 typedef int (*audio_is_scrambling_enabled_t)(void);
+typedef uint16_t (*audio_get_a2dp_sink_latency_t)(void);
 
 enum A2DP_STATE {
     A2DP_STATE_CONNECTED,
@@ -221,6 +222,8 @@
     audio_check_a2dp_ready_t audio_check_a2dp_ready;
     /* Check if scrambling is enabled on BTSoC */
     audio_is_scrambling_enabled_t audio_is_scrambling_enabled;
+    /* Get sink latency from Bluetooth stack */
+    audio_get_a2dp_sink_latency_t audio_get_a2dp_sink_latency;
     /* Internal A2DP state identifier */
     enum A2DP_STATE bt_state;
     /* A2DP codec type configured */
@@ -713,6 +716,8 @@
                         dlsym(a2dp.bt_lib_handle,"audio_check_a2dp_ready");
             a2dp.audio_is_scrambling_enabled = (audio_is_scrambling_enabled_t)
                         dlsym(a2dp.bt_lib_handle,"audio_is_scrambling_enabled");
+            a2dp.audio_get_a2dp_sink_latency = (audio_get_a2dp_sink_latency_t)
+                        dlsym(a2dp.bt_lib_handle,"audio_get_a2dp_sink_latency");
         }
     }
 
@@ -1714,7 +1719,7 @@
 
 uint32_t audio_extn_a2dp_get_encoder_latency()
 {
-    uint32_t latency = 0;
+    uint32_t latency_ms = 0;
     int avsync_runtime_prop = 0;
     int sbc_offset = 0, aptx_offset = 0, aptxhd_offset = 0,
         aac_offset = 0, ldac_offset = 0;
@@ -1731,36 +1736,41 @@
         }
     }
 
+    uint32_t slatency_ms = 0;
+    if (a2dp.audio_get_a2dp_sink_latency && a2dp.bt_state != A2DP_STATE_DISCONNECTED) {
+        slatency_ms = a2dp.audio_get_a2dp_sink_latency();
+    }
+
     switch (a2dp.bt_encoder_format) {
         case ENC_CODEC_TYPE_SBC:
-            latency = (avsync_runtime_prop > 0) ? sbc_offset : ENCODER_LATENCY_SBC;
-            latency += DEFAULT_SINK_LATENCY_SBC;
+            latency_ms = (avsync_runtime_prop > 0) ? sbc_offset : ENCODER_LATENCY_SBC;
+            latency_ms += (slatency_ms == 0) ? DEFAULT_SINK_LATENCY_SBC : slatency_ms;
             break;
         case ENC_CODEC_TYPE_APTX:
-            latency = (avsync_runtime_prop > 0) ? aptx_offset : ENCODER_LATENCY_APTX;
-            latency += DEFAULT_SINK_LATENCY_APTX;
+            latency_ms = (avsync_runtime_prop > 0) ? aptx_offset : ENCODER_LATENCY_APTX;
+            latency_ms += (slatency_ms == 0) ? DEFAULT_SINK_LATENCY_APTX : slatency_ms;
             break;
         case ENC_CODEC_TYPE_APTX_HD:
-            latency = (avsync_runtime_prop > 0) ? aptxhd_offset : ENCODER_LATENCY_APTX_HD;
-            latency += DEFAULT_SINK_LATENCY_APTX_HD;
+            latency_ms = (avsync_runtime_prop > 0) ? aptxhd_offset : ENCODER_LATENCY_APTX_HD;
+            latency_ms += (slatency_ms == 0) ? DEFAULT_SINK_LATENCY_APTX_HD : slatency_ms;
             break;
         case ENC_CODEC_TYPE_AAC:
-            latency = (avsync_runtime_prop > 0) ? aac_offset : ENCODER_LATENCY_AAC;
-            latency += DEFAULT_SINK_LATENCY_AAC;
+            latency_ms = (avsync_runtime_prop > 0) ? aac_offset : ENCODER_LATENCY_AAC;
+            latency_ms += (slatency_ms == 0) ? DEFAULT_SINK_LATENCY_AAC : slatency_ms;
             break;
         case ENC_CODEC_TYPE_LDAC:
-            latency = (avsync_runtime_prop > 0) ? ldac_offset : ENCODER_LATENCY_LDAC;
-            latency += DEFAULT_SINK_LATENCY_LDAC;
+            latency_ms = (avsync_runtime_prop > 0) ? ldac_offset : ENCODER_LATENCY_LDAC;
+            latency_ms += (slatency_ms == 0) ? DEFAULT_SINK_LATENCY_LDAC : slatency_ms;
             break;
         case ENC_CODEC_TYPE_PCM:
-            latency = ENCODER_LATENCY_PCM;
-            latency += DEFAULT_SINK_LATENCY_PCM;
+            latency_ms = ENCODER_LATENCY_PCM;
+            latency_ms += DEFAULT_SINK_LATENCY_PCM;
             break;
         default:
-            latency = DEFAULT_ENCODER_LATENCY;
+            latency_ms = DEFAULT_ENCODER_LATENCY;
             break;
     }
-    return latency;
+    return latency_ms;
 }
 
 int audio_extn_a2dp_get_parameters(struct str_parms *query,
diff --git a/hal/audio_extn/maxxaudio.c b/hal/audio_extn/maxxaudio.c
index 2fd188d..69c4606 100644
--- a/hal/audio_extn/maxxaudio.c
+++ b/hal/audio_extn/maxxaudio.c
@@ -43,13 +43,15 @@
 
 #define MA_QDSP_PARAM_INIT      "maxxaudio_qdsp_initialize"
 #define MA_QDSP_PARAM_DEINIT    "maxxaudio_qdsp_uninitialize"
+#define MA_QDSP_IS_FEATURE_USED "maxxaudio_qdsp_is_feature_supported"
 #define MA_QDSP_SET_LR_SWAP     "maxxaudio_qdsp_set_lr_swap"
+#define MA_QDSP_SET_ORIENTATION "maxxaudio_qdsp_set_orientation"
 #define MA_QDSP_SET_MODE        "maxxaudio_qdsp_set_sound_mode"
 #define MA_QDSP_SET_VOL         "maxxaudio_qdsp_set_volume"
 #define MA_QDSP_SET_VOLT        "maxxaudio_qdsp_set_volume_table"
 #define MA_QDSP_SET_PARAM       "maxxaudio_qdsp_set_parameter"
 
-#define SUPPORT_DEV "Blackbird"
+#define SUPPORT_DEV "18d1:5033" // Blackbird usbid
 #define SUPPORTED_USB 0x01
 
 typedef unsigned int effective_scope_flag_t;
@@ -87,6 +89,8 @@
     MA_CMD_VOL,
     MA_CMD_SWAP_ENABLE,
     MA_CMD_SWAP_DISABLE,
+    MA_CMD_ROTATE_ENABLE,
+    MA_CMD_ROTATE_DISABLE,
     MA_CMD_SOFT_MUTE_ENABLE,
     MA_CMD_SOFT_MUTE_DISABLE,
 } ma_cmd_t;
@@ -120,9 +124,14 @@
 
 typedef bool (*ma_param_deinit_t)(ma_audio_cal_handle_t *);
 
+typedef bool (*ma_is_feature_used_t)(ma_audio_cal_handle_t, const char *);
+
 typedef bool (*ma_set_lr_swap_t)(ma_audio_cal_handle_t,
                                  const struct ma_audio_cal_settings *, bool);
 
+typedef bool (*ma_set_orientation_t)(ma_audio_cal_handle_t,
+                                     const struct ma_audio_cal_settings *, int);
+
 typedef bool (*ma_set_sound_mode_t)(ma_audio_cal_handle_t,
                                     const struct ma_audio_cal_settings *,
                                     unsigned int);
@@ -144,11 +153,16 @@
     pthread_mutex_t lock;
     ma_param_init_t          ma_param_init;
     ma_param_deinit_t        ma_param_deinit;
+    ma_is_feature_used_t     ma_is_feature_used;
     ma_set_lr_swap_t         ma_set_lr_swap;
+    ma_set_orientation_t     ma_set_orientation;
     ma_set_sound_mode_t      ma_set_sound_mode;
     ma_set_volume_t          ma_set_volume;
     ma_set_volume_table_t    ma_set_volume_table;
     ma_set_param_t           ma_set_param;
+    bool speaker_lr_swap;
+    bool orientation_used;
+    int dispaly_orientation;
 };
 
 ma_audio_cal_handle_t g_ma_audio_cal_handle = NULL;
@@ -171,6 +185,13 @@
                                    audio_cal_settings, swap);
 }
 
+static bool ma_set_orientation_l(
+    const struct ma_audio_cal_settings *audio_cal_settings, int orientation)
+{
+    return my_data->ma_set_orientation(g_ma_audio_cal_handle,
+                                   audio_cal_settings, orientation);
+}
+
 static bool ma_set_sound_mode_l(
     const struct ma_audio_cal_settings *audio_cal_settings, int sound_mode)
 {
@@ -211,8 +232,10 @@
          (usecase->id == USECASE_AUDIO_PLAYBACK_OFFLOAD)) &&
         /* support devices */
         ((usecase->devices & AUDIO_DEVICE_OUT_SPEAKER) ||
-         (usecase->devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE)))
-         /* TODO: enable A2DP/USB when it is ready */
+         (usecase->devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE) ||
+         (audio_is_usb_out_device(usecase->devices) &&
+          audio_extn_ma_supported_usb())))
+        /* TODO: enable A2DP when it is ready */
 
         return true;
 
@@ -281,11 +304,14 @@
                     break;
 
                 case MA_CMD_SWAP_ENABLE:
-                    ret = ma_set_lr_swap_l(&ma_cal, true);
-                    if (ret)
-                        ALOGV("ma_set_lr_swap_l enable returned with success.");
-                    else
-                        ALOGE("ma_set_lr_swap_l enable returned with error.");
+                    /* lr swap only enable for speaker path */
+                    if (ma_cal.common.device & AUDIO_DEVICE_OUT_SPEAKER) {
+                        ret = ma_set_lr_swap_l(&ma_cal, true);
+                        if (ret)
+                            ALOGV("ma_set_lr_swap_l enable returned with success.");
+                        else
+                            ALOGE("ma_set_lr_swap_l enable returned with error.");
+                    }
                     break;
 
                 case MA_CMD_SWAP_DISABLE:
@@ -296,6 +322,24 @@
                         ALOGE("ma_set_lr_swap_l disable returned with error.");
                     break;
 
+                case MA_CMD_ROTATE_ENABLE:
+                    if (ma_cal.common.device & AUDIO_DEVICE_OUT_SPEAKER) {
+                        ret = ma_set_orientation_l(&ma_cal, my_data->dispaly_orientation);
+                        if (ret)
+                            ALOGV("ma_set_orientation_l %d returned with success.", my_data->dispaly_orientation);
+                        else
+                            ALOGE("ma_set_orientation_l %d returned with error.", my_data->dispaly_orientation);
+                    }
+                    break;
+
+                case MA_CMD_ROTATE_DISABLE:
+                    ret = ma_set_orientation_l(&ma_cal, 0);
+                    if (ret)
+                        ALOGV("ma_set_orientation_l 0 returned with success.");
+                    else
+                        ALOGE("ma_set_orientation_l 0 returned with error.");
+                    break;
+
                 case MA_CMD_SOFT_MUTE_ENABLE:
                     if (usecase->id == USECASE_AUDIO_PLAYBACK_LOW_LATENCY) break;
 
@@ -351,20 +395,20 @@
 
 static void ma_set_swap_l(struct audio_device *adev, bool enable)
 {
-    // do platform LR swap if it enables on Waves effect
-    // but there is no Waves implementation
-    if (!my_data) {
-        platform_check_and_set_swap_lr_channels(adev, enable);
-        ALOGV("%s: maxxaudio isn't initialized.", __func__);
-        return;
-    }
-
     if (enable)
         check_and_send_all_audio_cal(adev, MA_CMD_SWAP_ENABLE);
     else
         check_and_send_all_audio_cal(adev, MA_CMD_SWAP_DISABLE);
 }
 
+static void ma_set_rotation_l(struct audio_device *adev, int orientation)
+{
+    if (orientation != 0)
+        check_and_send_all_audio_cal(adev, MA_CMD_ROTATE_ENABLE);
+    else
+        check_and_send_all_audio_cal(adev, MA_CMD_ROTATE_DISABLE);
+}
+
 static void ma_support_usb(bool enable, int card)
 {
     char path[128];
@@ -374,7 +418,7 @@
     char *idd;
 
     if (enable) {
-        ret = snprintf(path, sizeof(path), "/proc/asound/card%u/id", card);
+        ret = snprintf(path, sizeof(path), "/proc/asound/card%u/usbid", card);
         if (ret < 0) {
             ALOGE("%s: failed on snprintf (%d) to path %s\n",
                   __func__, ret, path);
@@ -394,10 +438,10 @@
         idd = strtok(id, "\n");
 
         if (find_sup_dev(idd)) {
-            ALOGV("%s: support device name is %s", __func__, id);
+            ALOGV("%s: support usbid is %s", __func__, id);
             g_supported_dev |= SUPPORTED_USB;
         } else
-            ALOGV("%s: device %s isn't found from %s", __func__, id, SUPPORT_DEV);
+            ALOGV("%s: usbid %s isn't found from %s", __func__, id, SUPPORT_DEV);
     } else {
         g_supported_dev &= ~SUPPORTED_USB;
     }
@@ -459,6 +503,18 @@
              goto error;
          }
 
+        my_data->ma_is_feature_used = (ma_is_feature_used_t)dlsym(my_data->waves_handle,
+                                    MA_QDSP_IS_FEATURE_USED);
+        if (!my_data->ma_is_feature_used) {
+            ALOGV("%s: dlsym error %s for ma_is_feature_used", __func__, dlerror());
+        }
+
+        my_data->ma_set_orientation = (ma_set_orientation_t)dlsym(my_data->waves_handle,
+                                        MA_QDSP_SET_ORIENTATION);
+        if (!my_data->ma_set_orientation) {
+            ALOGV("%s: dlsym error %s for ma_set_orientation", __func__, dlerror());
+        }
+
          my_data->ma_set_lr_swap = (ma_set_lr_swap_t)dlsym(my_data->waves_handle,
                                     MA_QDSP_SET_LR_SWAP);
          if (!my_data->ma_set_lr_swap) {
@@ -556,6 +612,14 @@
         ma_cur_state_table[i].active = false;
     }
 
+    my_data->speaker_lr_swap = false;
+    my_data->orientation_used = false;
+    my_data->dispaly_orientation = 0;
+
+    if (g_ma_audio_cal_handle && my_data->ma_is_feature_used) {
+        my_data->orientation_used = my_data->ma_is_feature_used(g_ma_audio_cal_handle, "SET_ORIENTATION");
+    }
+
     return;
 
 error:
@@ -657,6 +721,19 @@
     pthread_mutex_lock(&my_data->lock);
 
     if (is_active()) {
+
+        if (ma_cal.common.device & AUDIO_DEVICE_OUT_SPEAKER) {
+            if (my_data->orientation_used)
+                ma_set_rotation_l(usecase->stream.out->dev, my_data->dispaly_orientation);
+            else
+                ma_set_swap_l(usecase->stream.out->dev, my_data->speaker_lr_swap);
+        } else {
+            if (my_data->orientation_used)
+                ma_set_rotation_l(usecase->stream.out->dev, 0);
+            else
+                ma_set_swap_l(usecase->stream.out->dev, false);
+        }
+
         ALOGV("%s: send volume table === Start", __func__);
         for (i = 0; i < STREAM_MAX_TYPES; i++)
             ALOGV("%s: stream(%d) volume(%f) active(%s)", __func__, i,
@@ -686,16 +763,27 @@
     // do LR swap and usb recognition
     ret = str_parms_get_int(parms, "rotation", &val);
     if (ret >= 0) {
+        if (!my_data) {
+            ALOGV("%s: maxxaudio isn't initialized.", __func__);
+            return;
+        }
+
         switch (val) {
         case 270:
-            ma_set_swap_l(adev, true);
+            my_data->speaker_lr_swap = true;
             break;
         case 0:
         case 90:
         case 180:
-            ma_set_swap_l(adev, false);
+            my_data->speaker_lr_swap = false;
             break;
         }
+        my_data->dispaly_orientation = val;
+
+        if (my_data->orientation_used)
+            ma_set_rotation_l(adev, my_data->dispaly_orientation);
+        else
+            ma_set_swap_l(adev, my_data->speaker_lr_swap);
     }
 
     // check connect status
diff --git a/hal/audio_extn/sndmonitor.c b/hal/audio_extn/sndmonitor.c
index 2e8fd43..85a8c94 100644
--- a/hal/audio_extn/sndmonitor.c
+++ b/hal/audio_extn/sndmonitor.c
@@ -194,7 +194,8 @@
         if ((strncasecmp(card_id, "msm", 3) != 0) &&
             (strncasecmp(card_id, "sdm", 3) != 0) &&
             (strncasecmp(card_id, "sdc", 3) != 0) &&
-            (strncasecmp(card_id, "apq", 3) != 0)) {
+            (strncasecmp(card_id, "apq", 3) != 0) &&
+            (strncasecmp(card_id, "sm8150", 6) != 0)) {
             ALOGW("Skip over non-ADSP snd card %s", card_id);
             continue;
         }
diff --git a/hal/audio_extn/utils.c b/hal/audio_extn/utils.c
index 73de0ab..3a1877b 100644
--- a/hal/audio_extn/utils.c
+++ b/hal/audio_extn/utils.c
@@ -281,6 +281,10 @@
                                                    usecase->out_snd_device,
                                                    out->sample_rate,
                                                    sample_rate);
+    } else if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
+        audio_extn_a2dp_get_sample_rate(sample_rate);
+        ALOGI("%s: Using sample rate %d for A2DP CoPP", __func__,
+               *sample_rate);
     }
 
     app_type_cfg->mode = flags_to_mode(0 /*playback*/, out->flags);
@@ -577,7 +581,7 @@
         }
 
         /* Initialize snd card name specific ids and/or backends*/
-        if (snd_card_info_init(platform_info_file, my_data,
+        if (platform_info_init(platform_info_file, my_data, false,
                                &acdb_set_parameters) < 0) {
             ALOGE("Failed to find platform_info_file");
             goto cleanup;
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index f315b5e..00cf661 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -225,7 +225,7 @@
 #define AFE_PROXY_CHANNEL_COUNT 2
 #define AFE_PROXY_SAMPLING_RATE 48000
 
-#define AFE_PROXY_PLAYBACK_PERIOD_SIZE  768
+#define AFE_PROXY_PLAYBACK_PERIOD_SIZE  256
 #define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
 
 struct pcm_config pcm_config_afe_proxy_playback = {
@@ -239,7 +239,7 @@
     .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
 };
 
-#define AFE_PROXY_RECORD_PERIOD_SIZE  768
+#define AFE_PROXY_RECORD_PERIOD_SIZE  256
 #define AFE_PROXY_RECORD_PERIOD_COUNT 4
 
 struct pcm_config pcm_config_afe_proxy_record = {
@@ -615,7 +615,7 @@
                        struct audio_usecase *usecase)
 {
     snd_device_t snd_device;
-    char mixer_path[50];
+    char mixer_path[MIXER_PATH_MAX_LENGTH];
 
     if (usecase == NULL)
         return -EINVAL;
@@ -628,8 +628,13 @@
         snd_device = usecase->out_snd_device;
     audio_extn_utils_send_app_type_cfg(adev, usecase);
     audio_extn_utils_send_audio_calibration(adev, usecase);
-    strcpy(mixer_path, use_case_table[usecase->id]);
+
+    // we shouldn't truncate mixer_path
+    ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
+            >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
+    // this also appends to mixer_path
     platform_add_backend_name(adev->platform, mixer_path, snd_device);
+
     audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
     ALOGD("%s: usecase(%d) apply and update mixer path: %s", __func__,  usecase->id, mixer_path);
     audio_route_apply_and_update_path(adev->audio_route, mixer_path);
@@ -642,7 +647,7 @@
                         struct audio_usecase *usecase)
 {
     snd_device_t snd_device;
-    char mixer_path[50];
+    char mixer_path[MIXER_PATH_MAX_LENGTH];
 
     if (usecase == NULL)
         return -EINVAL;
@@ -652,9 +657,14 @@
         snd_device = usecase->in_snd_device;
     else
         snd_device = usecase->out_snd_device;
-    strcpy(mixer_path, use_case_table[usecase->id]);
+
+    // we shouldn't truncate mixer_path
+    ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
+            >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
+    // this also appends to mixer_path
     platform_add_backend_name(adev->platform, mixer_path, snd_device);
     ALOGD("%s: usecase(%d) reset and update mixer path: %s", __func__, usecase->id, mixer_path);
+
     audio_route_reset_and_update_path(adev->audio_route, mixer_path);
     audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
 
@@ -797,6 +807,147 @@
     return 0;
 }
 
+#ifdef DYNAMIC_ECNS_ENABLED
+static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
+                          struct stream_in *in,
+                          struct audio_effect_config effect_config,
+                          unsigned int param_value)
+{
+    char mixer_ctl_name[] = "Audio Effect";
+    long set_values[6];
+
+    struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
+    if (!ctl) {
+        ALOGE("%s: Could not get mixer ctl - %s",
+               __func__, mixer_ctl_name);
+        return -EINVAL;
+    }
+
+    set_values[0] = 1; //0:Rx 1:Tx
+    set_values[1] = in->app_type_cfg.app_type;
+    set_values[2] = (long)effect_config.module_id;
+    set_values[3] = (long)effect_config.instance_id;
+    set_values[4] = (long)effect_config.param_id;
+    set_values[5] = param_value;
+
+    mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
+
+    return 0;
+
+}
+
+static int update_effect_param_ecns(struct audio_usecase *usecase,
+                               unsigned int module_id, int effect_type,
+                               unsigned int *param_value)
+{
+    int ret = 0;
+    struct audio_effect_config other_effect_config;
+    struct stream_in *in = NULL;
+
+    if (!usecase)
+        return -EINVAL;
+
+    in = usecase->stream.in;
+
+    /* Get the effect config data of the other effect */
+    ret = platform_get_effect_config_data(usecase->in_snd_device,
+                                          &other_effect_config,
+                                          effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
+    if (ret < 0) {
+        ALOGE("%s Failed to get effect params %d", __func__, ret);
+        return ret;
+    }
+
+    if (module_id == other_effect_config.module_id) {
+            //Same module id for AEC/NS. Values need to be combined
+            if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
+                ((effect_type == EFFECT_NS) && (in->enable_aec)))
+                *param_value |= other_effect_config.param_value;
+    }
+
+    return ret;
+}
+
+static int enable_disable_effect(struct audio_device *adev, struct stream_in *in,
+                                   int effect_type, bool enable)
+{
+    struct audio_effect_config effect_config;
+    struct audio_usecase *usecase = NULL;
+    int ret = 0;
+    unsigned int param_value = 0;
+
+    if (!in) {
+        ALOGE("%s: Invalid input stream", __func__);
+        return -EINVAL;
+    }
+
+    ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
+
+    usecase = get_usecase_from_list(adev, in->usecase);
+
+    ret = platform_get_effect_config_data(usecase->in_snd_device,
+                                           &effect_config, effect_type);
+    if (ret < 0) {
+        ALOGE("%s Failed to get module id %d", __func__, ret);
+        return ret;
+    }
+    ALOGV("%s: module %d app_type %d usecase->id:%d usecase->in_snd_device:%d",
+           __func__, effect_config.module_id, in->app_type_cfg.app_type,
+          usecase->id, usecase->in_snd_device);
+
+    if (enable)
+        param_value = effect_config.param_value;
+
+    /*Special handling for AEC & NS effects Param values need to be
+      updated if module ids are same*/
+
+    if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
+        ret = update_effect_param_ecns(usecase, effect_config.module_id,
+                                       effect_type, &param_value);
+        if (ret < 0)
+            return ret;
+    }
+
+    ret = send_effect_enable_disable_mixer_ctl(adev, in,
+                                               effect_config, param_value);
+
+    return ret;
+}
+
+static int check_and_enable_effect(struct audio_device *adev)
+{
+    int ret = 0;
+
+    struct listnode *node;
+    struct stream_in *in = NULL;
+
+    list_for_each(node, &adev->usecase_list)
+    {
+        struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
+        if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL) {
+            in = usecase->stream.in;
+
+            if (in->standby)
+                continue;
+
+            if (in->enable_aec) {
+                ret = enable_disable_effect(adev, in, EFFECT_AEC, true);
+            }
+
+            if (in->enable_ns &&
+                in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
+                ret = enable_disable_effect(adev, in, EFFECT_NS, true);
+            }
+        }
+    }
+
+    return ret;
+}
+#else
+#define enable_disable_effect(w, x, y, z) -ENOSYS
+#define check_and_enable_effect(x) -ENOSYS
+#endif
+
 /*
   legend:
   uc - existing usecase
@@ -1022,6 +1173,10 @@
         if (usecase->type != PCM_PLAYBACK &&
                 usecase != uc_info &&
                 usecase->in_snd_device != snd_device &&
+                ((uc_info->type == VOICE_CALL &&
+                  usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL) ||
+                 platform_check_backends_match(snd_device,\
+                                              usecase->in_snd_device)) &&
                 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
             ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
                   __func__, use_case_table[usecase->id],
@@ -1134,8 +1289,14 @@
         // audio_channel_in_mask_from_count() does the right conversion to either positional or
         // indexed mask
         for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
-            supported_channel_masks[num_masks++] =
+            const audio_channel_mask_t mask =
                     audio_channel_in_mask_from_count(channel_count);
+            supported_channel_masks[num_masks++] = mask;
+            const audio_channel_mask_t index_mask =
+                    audio_channel_mask_for_index_assignment_from_count(channel_count);
+            if (mask != index_mask && num_masks < max_masks) { // ensure index mask added.
+                supported_channel_masks[num_masks++] = index_mask;
+            }
         }
     }
 #ifdef NDEBUG
@@ -1270,6 +1431,44 @@
     return false;
 }
 
+struct stream_in *adev_get_active_input(const struct audio_device *adev)
+{
+    struct listnode *node;
+    struct stream_in *last_active_in = NULL;
+
+    /* Get last added active input.
+     * TODO: We may use a priority mechanism to pick highest priority active source */
+    list_for_each(node, &adev->usecase_list)
+    {
+        struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
+        if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL) {
+            last_active_in =  usecase->stream.in;
+        }
+    }
+
+    return last_active_in;
+}
+
+struct stream_in *get_voice_communication_input(const struct audio_device *adev)
+{
+    struct listnode *node;
+
+    /* First check active inputs with voice communication source and then
+     * any input if audio mode is in communication */
+    list_for_each(node, &adev->usecase_list)
+    {
+        struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
+        if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL &&
+            usecase->stream.in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
+            return usecase->stream.in;
+        }
+    }
+    if (adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
+        return adev_get_active_input(adev);
+    }
+    return NULL;
+}
+
 int select_devices(struct audio_device *adev,
                    audio_usecase_t uc_id)
 {
@@ -1294,7 +1493,9 @@
         (usecase->type == PCM_HFP_CALL)) {
         out_snd_device = platform_get_output_snd_device(adev->platform,
                                                         usecase->stream.out->devices);
-        in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
+        in_snd_device = platform_get_input_snd_device(adev->platform,
+                                                      NULL,
+                                                      usecase->stream.out->devices);
         usecase->devices = usecase->stream.out->devices;
     } else {
         /*
@@ -1326,6 +1527,7 @@
             in_snd_device = SND_DEVICE_NONE;
             if (out_snd_device == SND_DEVICE_NONE) {
                 struct stream_out *voip_out = adev->primary_output;
+                struct stream_in *voip_in = get_voice_communication_input(adev);
 
                 out_snd_device = platform_get_output_snd_device(adev->platform,
                                             usecase->stream.out->devices);
@@ -1333,11 +1535,8 @@
                 if (voip_usecase)
                     voip_out = voip_usecase->stream.out;
 
-                if (usecase->stream.out == voip_out &&
-                        adev->active_input &&
-                        (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
-                            adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
-                    select_devices(adev, adev->active_input->usecase);
+                if (usecase->stream.out == voip_out && voip_in != NULL) {
+                    select_devices(adev, voip_in->usecase);
                 }
             }
         } else if (usecase->type == PCM_CAPTURE) {
@@ -1345,9 +1544,9 @@
             out_snd_device = SND_DEVICE_NONE;
             if (in_snd_device == SND_DEVICE_NONE) {
                 audio_devices_t out_device = AUDIO_DEVICE_NONE;
-                if (adev->active_input &&
-                        (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
-                            adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
+                struct stream_in *voip_in = get_voice_communication_input(adev);
+
+                if (voip_in != NULL) {
 
                     struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
                                                              USECASE_AUDIO_PLAYBACK_VOIP);
@@ -1361,7 +1560,9 @@
                         out_device = adev->primary_output->devices;
                     }
                 }
-                in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
+                in_snd_device = platform_get_input_snd_device(adev->platform,
+                                                              usecase->stream.in,
+                                                              out_device);
             }
         }
     }
@@ -1487,6 +1688,11 @@
 
     audio_extn_ma_set_device(usecase);
 
+    /* If input stream is already running the effect needs to be
+       applied on the new input device that's being enabled here.  */
+    if (in_snd_device != SND_DEVICE_NONE)
+        check_and_enable_effect(adev);
+
     /* Applicable only on the targets that has external modem.
      * Enable device command should be sent to modem only after
      * enabling voice call mixer controls
@@ -1518,17 +1724,6 @@
     ALOGV("%s: enter: usecase(%d: %s)", __func__,
           in->usecase, use_case_table[in->usecase]);
 
-    if (adev->active_input) {
-        if (adev->active_input->usecase == in->usecase) {
-            adev->active_input = NULL;
-        } else {
-            ALOGW("%s adev->active_input->usecase %s, v/s in->usecase %s",
-                __func__,
-                use_case_table[adev->active_input->usecase],
-                use_case_table[in->usecase]);
-        }
-    }
-
     uc_info = get_usecase_from_list(adev, in->usecase);
     if (uc_info == NULL) {
         ALOGE("%s: Could not find the usecase (%d) in the list",
@@ -1586,7 +1781,6 @@
         goto error_config;
     }
 
-    adev->active_input = in;
     uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
     uc_info->id = in->usecase;
     uc_info->type = PCM_CAPTURE;
@@ -1664,6 +1858,7 @@
         }
     }
     register_in_stream(in);
+    check_and_enable_effect(adev);
     audio_streaming_hint_end();
     audio_extn_perf_lock_release();
     ALOGV("%s: exit", __func__);
@@ -1676,7 +1871,6 @@
     audio_extn_perf_lock_release();
 
 error_config:
-    adev->active_input = NULL;
     ALOGW("%s: exit: status(%d)", __func__, ret);
     return ret;
 }
@@ -1727,15 +1921,15 @@
     struct stream_out *out = (struct stream_out *) context;
     struct listnode *item;
 
-    out->offload_state = OFFLOAD_STATE_IDLE;
-    out->playback_started = 0;
-
     setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
     set_sched_policy(0, SP_FOREGROUND);
     prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
 
     ALOGV("%s", __func__);
+
     lock_output_stream(out);
+    out->offload_state = OFFLOAD_STATE_IDLE;
+    out->playback_started = 0;
     for (;;) {
         struct offload_cmd *cmd = NULL;
         stream_callback_event_t event;
@@ -1994,6 +2188,9 @@
         audio_low_latency_hint_end();
     }
 
+    if (out->usecase == USECASE_INCALL_MUSIC_UPLINK)
+        voice_set_device_mute_flag(adev, false);
+
     /* 1. Get and set stream specific mixer controls */
     disable_audio_route(adev, uc_info);
 
@@ -2117,6 +2314,9 @@
 
     audio_extn_extspk_update(adev->extspk);
 
+    if (out->usecase == USECASE_INCALL_MUSIC_UPLINK)
+        voice_set_device_mute_flag(adev, true);
+
     ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
           __func__, adev->snd_card, out->pcm_device_id, out->config.format);
     if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
@@ -2546,10 +2746,13 @@
         // otherwise audio is no longer played on the new usb devices.
         // By forcing the stream in standby, the usb stack refcount drops to 0
         // and the driver is closed.
-        if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD && val == AUDIO_DEVICE_NONE &&
+        if (val == AUDIO_DEVICE_NONE &&
                 audio_is_usb_out_device(out->devices)) {
-            ALOGD("%s() putting the usb device in standby after disconnection", __func__);
-            out_standby_l(&out->stream.common);
+            if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
+                ALOGD("%s() putting the usb device in standby after disconnection", __func__);
+                out_standby_l(&out->stream.common);
+            }
+            val = AUDIO_DEVICE_OUT_SPEAKER;
         }
 
         pthread_mutex_lock(&adev->lock);
@@ -2712,7 +2915,7 @@
                                           struct str_parms *reply,
                                           audio_channel_mask_t *supported_channel_masks) {
     int ret = -1;
-    char value[256];
+    char value[ARRAY_SIZE(channels_name_to_enum_table) * 32 /* max channel name size */];
     bool first = true;
     size_t i, j;
 
@@ -3902,6 +4105,8 @@
     effect_descriptor_t desc;
 
     status = (*effect)->get_descriptor(effect, &desc);
+    ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
+
     if (status != 0)
         return status;
 
@@ -3926,14 +4131,18 @@
                     select_devices(adev, usecase->id);
             }
         }
-        if (!in->standby)
+        if (!in->standby
+            && enable_disable_effect(in->dev, in, EFFECT_AEC, enable) == -ENOSYS)
             select_devices(in->dev, in->usecase);
     }
     if (in->enable_ns != enable &&
             (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
         in->enable_ns = enable;
-        if (!in->standby)
-            select_devices(in->dev, in->usecase);
+        if (!in->standby) {
+            if (in->source != AUDIO_SOURCE_VOICE_COMMUNICATION
+                || enable_disable_effect(in->dev, in, EFFECT_NS, enable) == -ENOSYS)
+                select_devices(in->dev, in->usecase);
+        }
     }
     pthread_mutex_unlock(&in->dev->lock);
     pthread_mutex_unlock(&in->lock);
@@ -4153,6 +4362,21 @@
     return ret;
 }
 
+static int in_set_microphone_direction(const struct audio_stream_in *stream,
+                                           audio_microphone_direction_t dir) {
+    (void)stream;
+    (void)dir;
+    ALOGVV("%s", __func__);
+    return -ENOSYS;
+}
+
+static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
+    (void)stream;
+    (void)zoom;
+    ALOGVV("%s", __func__);
+    return -ENOSYS;
+}
+
 static int adev_open_output_stream(struct audio_hw_device *dev,
                                    audio_io_handle_t handle,
                                    audio_devices_t devices,
@@ -5030,7 +5254,10 @@
                                                             devices,
                                                             flags,
                                                             source);
-    ALOGV("%s: enter", __func__);
+    ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
+            " sample_rate %u, channel_mask %#x, format %#x",
+            __func__, flags, is_usb_dev, may_use_hifi_record,
+            config->sample_rate, config->channel_mask, config->format);
     *stream_in = NULL;
 
     if (is_usb_dev && !is_usb_ready(adev, false /* is_playback */)) {
@@ -5077,6 +5304,8 @@
     in->stream.get_input_frames_lost = in_get_input_frames_lost;
     in->stream.get_capture_position = in_get_capture_position;
     in->stream.get_active_microphones = in_get_active_microphones;
+    in->stream.set_microphone_direction = in_set_microphone_direction;
+    in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
 
     in->device = devices;
     in->source = source;
@@ -5085,7 +5314,7 @@
     in->capture_handle = handle;
     in->flags = flags;
 
-    ALOGV("%s: source = %d, config->channel_mask = %d", __func__, source, config->channel_mask);
+    ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
     if (source == AUDIO_SOURCE_VOICE_UPLINK ||
          source == AUDIO_SOURCE_VOICE_DOWNLINK) {
         /* Force channel config requested to mono if incall
@@ -5401,13 +5630,10 @@
             uc_info.id = audio_usecase;
             uc_info.type = usecase_type;
             if (dir) {
-                adev->active_input = &in;
                 memset(&in, 0, sizeof(in));
                 in.device = audio_device;
                 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
                 uc_info.stream.in = &in;
-            }  else {
-                adev->active_input = NULL;
             }
             memset(&out, 0, sizeof(out));
             out.devices = audio_device; /* only field needed in select_devices */
@@ -5441,7 +5667,6 @@
             list_remove(&uc_info.list);
         }
     }
-    adev->active_input = NULL; /* restore adev state */
     return 0;
 }
 
@@ -5646,7 +5871,6 @@
     /* Set the default route before the PCM stream is opened */
     pthread_mutex_lock(&adev->lock);
     adev->mode = AUDIO_MODE_NORMAL;
-    adev->active_input = NULL;
     adev->primary_output = NULL;
     adev->bluetooth_nrec = true;
     adev->acdb_settings = TTY_MODE_OFF;
diff --git a/hal/audio_hw.h b/hal/audio_hw.h
index 0b3b028..cc24c45 100644
--- a/hal/audio_hw.h
+++ b/hal/audio_hw.h
@@ -340,7 +340,6 @@
     pthread_mutex_t lock; /* see note below on mutex acquisition order */
     struct mixer *mixer;
     audio_mode_t mode;
-    struct stream_in *active_input;
     struct stream_out *primary_output;
     struct stream_out *voice_tx_output;
     struct stream_out *current_call_output;
@@ -357,6 +356,7 @@
     bool enable_voicerx;
     bool enable_hfp;
     bool mic_break_enabled;
+    bool use_voice_device_mute;
 
     int snd_card;
     void *platform;
diff --git a/hal/msm8916/platform.c b/hal/msm8916/platform.c
index 750d4e5..7d35ff5 100644
--- a/hal/msm8916/platform.c
+++ b/hal/msm8916/platform.c
@@ -81,6 +81,8 @@
 #define TOSTRING_(x) #x
 #define TOSTRING(x) TOSTRING_(x)
 
+#define GET_IN_DEVICE_INDEX(SND_DEVICE) ((SND_DEVICE) - (SND_DEVICE_IN_BEGIN))
+
 char cal_name_info[WCD9XXX_MAX_CAL][MAX_CAL_NAME] = {
         [WCD9XXX_MBHC_CAL] = "mbhc_cal",
 };
@@ -301,6 +303,34 @@
     [SND_DEVICE_IN_SPEAKER_QMIC_AEC_NS] = "quad-mic",
 };
 
+static struct audio_effect_config \
+               effect_config_table[GET_IN_DEVICE_INDEX(SND_DEVICE_MAX)][EFFECT_COUNT] = {
+    [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_SPEAKER_QMIC_AEC_NS)][EFFECT_AEC] = \
+                                      {TX_VOICE_FLUENCE_PROV2, 0x0, 0x10EAF, 0x01},
+    [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_SPEAKER_QMIC_AEC_NS)][EFFECT_NS] = \
+                                      {TX_VOICE_FLUENCE_PROV2,  0x0, 0x10EAF, 0x02},
+    [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS_BROADSIDE)][EFFECT_AEC] = \
+                                      {TX_VOICE_DM_FV5_BROADSIDE, 0x0, 0x10EAF, 0x01},
+    [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS_BROADSIDE)][EFFECT_NS] = \
+                                      {TX_VOICE_DM_FV5_BROADSIDE, 0x0, 0x10EAF, 0x02},
+    [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS)][EFFECT_AEC] = \
+                                      {TX_VOICE_FV5ECNS_DM, 0x0, 0x10EAF, 0x01},
+    [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS)][EFFECT_NS] = \
+                                      {TX_VOICE_FV5ECNS_DM, 0x0, 0x10EAF, 0x02},
+    [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_SPEAKER_MIC_AEC_NS)][EFFECT_AEC] = \
+                                      {TX_VOICE_FV5ECNS_SM, 0x0, 0x10EAF, 0x01},
+    [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_SPEAKER_MIC_AEC_NS)][EFFECT_NS] = \
+                                      {TX_VOICE_FV5ECNS_SM, 0x0, 0x10EAF, 0x02},
+    [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_HANDSET_DMIC_AEC_NS)][EFFECT_AEC] = \
+                                      {TX_VOICE_FV5ECNS_DM, 0x0, 0x10EAF, 0x01},
+    [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_HANDSET_DMIC_AEC_NS)][EFFECT_NS] = \
+                                      {TX_VOICE_FV5ECNS_DM, 0x0, 0x10EAF, 0x02},
+    [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_HANDSET_MIC_AEC_NS)][EFFECT_AEC] = \
+                                      {TX_VOICE_FV5ECNS_SM, 0x0, 0x10EAF, 0x01},
+    [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_HANDSET_MIC_AEC_NS)][EFFECT_NS] = \
+                                      {TX_VOICE_FV5ECNS_SM, 0x0, 0x10EAF, 0x02},
+};
+
 /* ACDB IDs (audio DSP path configuration IDs) for each sound device */
 static int acdb_device_table[SND_DEVICE_MAX] = {
     [SND_DEVICE_NONE] = -1,
@@ -1132,7 +1162,8 @@
     /* Initialize ACDB and PCM ID's */
     strlcpy(platform_info_path, PLATFORM_INFO_XML_PATH, MAX_MIXER_XML_PATH);
     resolve_config_file(platform_info_path);
-    platform_info_init(platform_info_path, my_data);
+    platform_info_init(platform_info_path, my_data,
+                       true, &platform_set_parameters);
 
     my_data->acdb_handle = dlopen(LIB_ACDB_LOADER, RTLD_NOW);
     if (my_data->acdb_handle == NULL) {
@@ -1415,6 +1446,35 @@
     return find_index(usecase_name_index, AUDIO_USECASE_MAX, usecase_name);
 }
 
+int platform_get_effect_config_data(snd_device_t snd_device,
+                                      struct audio_effect_config *effect_config,
+                                      effect_type_t effect_type)
+{
+    int ret = 0;
+
+    if ((snd_device < SND_DEVICE_IN_BEGIN) || (snd_device >= SND_DEVICE_MAX) ||
+        (effect_type <= EFFECT_NONE) || (effect_type >= EFFECT_COUNT)) {
+        ALOGE("%s: Invalid snd_device = %d or effect_type = %d",
+            __func__, snd_device, effect_type);
+        ret = -EINVAL;
+        goto done;
+    }
+
+    if (effect_config == NULL) {
+        ALOGE("%s: Invalid effect_config", __func__);
+        ret = -EINVAL;
+        goto done;
+    }
+
+    ALOGV("%s: snd_device = %d module_id = %d",
+          __func__, snd_device,
+          effect_config_table[GET_IN_DEVICE_INDEX(snd_device)][effect_type].module_id);
+    *effect_config = effect_config_table[GET_IN_DEVICE_INDEX(snd_device)][effect_type];
+
+done:
+    return ret;
+}
+
 void platform_add_operator_specific_device(snd_device_t snd_device,
                                            const char *operator,
                                            const char *mixer_path,
@@ -1498,6 +1558,27 @@
         }
     }
     return key;
+
+int platform_set_effect_config_data(snd_device_t snd_device,
+                                      struct audio_effect_config effect_config,
+                                      effect_type_t effect_type)
+{
+    int ret = 0;
+
+    if ((snd_device < SND_DEVICE_IN_BEGIN) || (snd_device >= SND_DEVICE_MAX) ||
+        (effect_type <= EFFECT_NONE) || (effect_type >= EFFECT_COUNT)) {
+        ALOGE("%s: Invalid snd_device = %d or effect_type = %d",
+            __func__, snd_device, effect_type);
+        ret = -EINVAL;
+        goto done;
+    }
+
+    ALOGV("%s 0x%x 0x%x 0x%x 0x%x", __func__, effect_config.module_id,
+           effect_config.instance_id, effect_config.param_id,
+           effect_config.param_value);
+    effect_config_table[GET_IN_DEVICE_INDEX(snd_device)][effect_type] = effect_config;
+done:
+    return ret;
 }
 
 int platform_get_default_app_type_v2(void *platform, usecase_type_t type, int *app_type)
@@ -1651,6 +1732,7 @@
     struct audio_device *adev = my_data->adev;
     struct mixer_ctl *ctl;
     const char *mixer_ctl_name = "Voice Rx Gain";
+    const char *mute_mixer_ctl_name = "Voice Rx Device Mute";
     int vol_index = 0, ret = 0;
     uint32_t set_values[ ] = {0,
                               ALL_SESSION_VSID,
@@ -1661,7 +1743,6 @@
     // But this values don't changed in kernel. So, below change is need.
     vol_index = (int)percent_to_index(volume, MIN_VOL_INDEX, my_data->max_vol_index);
     set_values[0] = vol_index;
-
     ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
     if (!ctl) {
         ALOGE("%s: Could not get ctl for mixer cmd - %s",
@@ -1671,6 +1752,23 @@
     ALOGV("Setting voice volume index: %d", set_values[0]);
     ret = mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
 
+    // Send mute command in case volume index is max since indexes are inverted
+    // for mixer controls.
+    if (vol_index == my_data->max_vol_index) {
+        set_values[0] = 1;
+    }
+    else {
+        set_values[0] = 0;
+    }
+
+    ctl = mixer_get_ctl_by_name(adev->mixer, mute_mixer_ctl_name);
+    if (!ctl) {
+        ALOGE("%s: Could not get ctl for mixer cmd - %s",
+              __func__, mute_mixer_ctl_name);
+        return -EINVAL;
+    }
+    ALOGV("%s: Setting RX Device Mute to: %d", __func__, set_values[0]);
+    mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
     return ret;
 }
 
@@ -1780,10 +1878,6 @@
     audio_mode_t mode = adev->mode;
     snd_device_t snd_device = SND_DEVICE_NONE;
 
-    audio_channel_mask_t channel_mask = (adev->active_input == NULL) ?
-                                AUDIO_CHANNEL_IN_MONO : adev->active_input->channel_mask;
-    int channel_count = popcount(channel_mask);
-
     ALOGV("%s: enter: output devices(%#x)", __func__, devices);
     if (devices == AUDIO_DEVICE_NONE ||
         devices & AUDIO_DEVICE_BIT_IN) {
@@ -1916,21 +2010,157 @@
     return snd_device;
 }
 
-snd_device_t platform_get_input_snd_device(void *platform, audio_devices_t out_device)
+#ifdef DYNAMIC_ECNS_ENABLED
+static snd_device_t get_snd_device_for_voice_comm(struct platform_data *my_data,
+                                                  struct stream_in *in __unused,
+                                                  audio_devices_t out_device,
+                                                  audio_devices_t in_device)
+{
+    struct audio_device *adev = my_data->adev;
+    snd_device_t snd_device = SND_DEVICE_NONE;
+
+    if (my_data->fluence_type != FLUENCE_NONE) {
+        switch(AUDIO_DEVICE_BIT_IN | in_device) {
+            case AUDIO_DEVICE_IN_BACK_MIC:
+                if (my_data->fluence_in_spkr_mode) {
+                    if (my_data->fluence_type & FLUENCE_QUAD_MIC) {
+                        snd_device = SND_DEVICE_IN_SPEAKER_QMIC_AEC_NS;
+                    } else if (my_data->fluence_type & FLUENCE_DUAL_MIC) {
+                        if (my_data->fluence_mode == FLUENCE_BROADSIDE)
+                            snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS_BROADSIDE;
+                        else
+                            snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS;
+                    }
+                    adev->acdb_settings |= DMIC_FLAG;
+                } else
+                    snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC_NS;
+                break;
+            case AUDIO_DEVICE_IN_BUILTIN_MIC:
+                if (my_data->fluence_type & FLUENCE_DUAL_MIC) {
+                    snd_device = SND_DEVICE_IN_HANDSET_DMIC_AEC_NS;
+                    adev->acdb_settings |= DMIC_FLAG;
+                } else
+                    snd_device = SND_DEVICE_IN_HANDSET_MIC_AEC_NS;
+                break;
+            default:
+                ALOGE("%s: Unsupported in_device %#x", __func__, in_device);
+                break;
+        }
+        platform_set_echo_reference(adev, true, out_device);
+    }
+
+    return snd_device;
+}
+#else
+static snd_device_t get_snd_device_for_voice_comm(struct platform_data *my_data,
+                                                  struct stream_in *in,
+                                                  audio_devices_t out_device,
+                                                  audio_devices_t in_device)
+{
+    struct audio_device *adev = my_data->adev;
+    snd_device_t snd_device = SND_DEVICE_NONE;
+
+    if (my_data->fluence_type != FLUENCE_NONE &&
+        in->enable_aec &&
+        in->enable_ns) {
+        if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
+            if (my_data->fluence_in_spkr_mode) {
+                if (my_data->fluence_type & FLUENCE_QUAD_MIC) {
+                    snd_device = SND_DEVICE_IN_SPEAKER_QMIC_AEC_NS;
+                } else if (my_data->fluence_type & FLUENCE_DUAL_MIC) {
+                    if (my_data->fluence_mode == FLUENCE_BROADSIDE)
+                        snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS_BROADSIDE;
+                    else
+                        snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS;
+                }
+                adev->acdb_settings |= DMIC_FLAG;
+            } else
+                snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC_NS;
+        } else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
+            if (my_data->fluence_type & FLUENCE_DUAL_MIC) {
+                snd_device = SND_DEVICE_IN_HANDSET_DMIC_AEC_NS;
+                adev->acdb_settings |= DMIC_FLAG;
+            } else
+                snd_device = SND_DEVICE_IN_HANDSET_MIC_AEC_NS;
+        } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
+            snd_device = SND_DEVICE_IN_HEADSET_MIC_FLUENCE;
+        }
+        platform_set_echo_reference(adev, true, out_device);
+    } else if (my_data->fluence_type != FLUENCE_NONE &&
+               in->enable_aec) {
+        if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
+            if (my_data->fluence_in_spkr_mode) {
+                if (my_data->fluence_type & FLUENCE_QUAD_MIC) {
+                    snd_device = SND_DEVICE_IN_SPEAKER_QMIC_AEC;
+                } else if (my_data->fluence_type & FLUENCE_DUAL_MIC) {
+                    if (my_data->fluence_mode == FLUENCE_BROADSIDE)
+                        snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC_BROADSIDE;
+                    else
+                        snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC;
+                }
+                adev->acdb_settings |= DMIC_FLAG;
+            } else
+                snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC;
+        } else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
+            if (my_data->fluence_type & FLUENCE_DUAL_MIC) {
+                snd_device = SND_DEVICE_IN_HANDSET_DMIC_AEC;
+                adev->acdb_settings |= DMIC_FLAG;
+            } else
+                snd_device = SND_DEVICE_IN_HANDSET_MIC_AEC;
+        } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
+            snd_device = SND_DEVICE_IN_HEADSET_MIC_FLUENCE;
+        }
+        platform_set_echo_reference(adev, true, out_device);
+    } else if (my_data->fluence_type != FLUENCE_NONE &&
+               in->enable_ns) {
+        if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
+            if (my_data->fluence_in_spkr_mode) {
+                if (my_data->fluence_type & FLUENCE_QUAD_MIC) {
+                    snd_device = SND_DEVICE_IN_SPEAKER_QMIC_NS;
+                } else if (my_data->fluence_type & FLUENCE_DUAL_MIC) {
+                    if (my_data->fluence_mode == FLUENCE_BROADSIDE)
+                        snd_device = SND_DEVICE_IN_SPEAKER_DMIC_NS_BROADSIDE;
+                    else
+                        snd_device = SND_DEVICE_IN_SPEAKER_DMIC_NS;
+                }
+                adev->acdb_settings |= DMIC_FLAG;
+            } else
+                snd_device = SND_DEVICE_IN_SPEAKER_MIC_NS;
+        } else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
+            if (my_data->fluence_type & FLUENCE_DUAL_MIC) {
+                snd_device = SND_DEVICE_IN_HANDSET_DMIC_NS;
+                adev->acdb_settings |= DMIC_FLAG;
+            } else
+                snd_device = SND_DEVICE_IN_HANDSET_MIC_NS;
+        } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
+            snd_device = SND_DEVICE_IN_HEADSET_MIC_FLUENCE;
+        }
+        platform_set_echo_reference(adev, false, out_device);
+    } else
+        platform_set_echo_reference(adev, false, out_device);
+
+    return snd_device;
+}
+#endif //DYNAMIC_ECNS_ENABLED
+
+snd_device_t platform_get_input_snd_device(void *platform,
+                                           struct stream_in *in,
+                                           audio_devices_t out_device)
 {
     struct platform_data *my_data = (struct platform_data *)platform;
     struct audio_device *adev = my_data->adev;
-    audio_source_t  source = (adev->active_input == NULL) ?
-                                AUDIO_SOURCE_DEFAULT : adev->active_input->source;
-
-    audio_mode_t    mode   = adev->mode;
-    audio_devices_t in_device = ((adev->active_input == NULL) ?
-                                    AUDIO_DEVICE_NONE : adev->active_input->device)
-                                & ~AUDIO_DEVICE_BIT_IN;
-    audio_channel_mask_t channel_mask = (adev->active_input == NULL) ?
-                                AUDIO_CHANNEL_IN_MONO : adev->active_input->channel_mask;
+    audio_mode_t mode = adev->mode;
     snd_device_t snd_device = SND_DEVICE_NONE;
-    int channel_count = popcount(channel_mask);
+
+    if (in == NULL) {
+        in = adev_get_active_input(adev);
+    }
+
+    audio_source_t source = (in == NULL) ? AUDIO_SOURCE_DEFAULT : in->source;
+    audio_devices_t in_device =
+        ((in == NULL) ? AUDIO_DEVICE_NONE : in->device) & ~AUDIO_DEVICE_BIT_IN;
+    audio_channel_mask_t channel_mask = (in == NULL) ? AUDIO_CHANNEL_IN_MONO : in->channel_mask;
+    int channel_count = audio_channel_count_from_in_mask(channel_mask);
 
     ALOGV("%s: enter: out_device(%#x) in_device(%#x)",
           __func__, out_device, in_device);
@@ -2025,7 +2255,7 @@
             if (channel_count == 2) {
                 snd_device = SND_DEVICE_IN_VOICE_REC_DMIC_STEREO;
                 adev->acdb_settings |= DMIC_FLAG;
-            } else if (adev->active_input->enable_ns)
+            } else if (in->enable_ns)
                 snd_device = SND_DEVICE_IN_VOICE_REC_MIC_NS;
             else if (my_data->fluence_type != FLUENCE_NONE &&
                      my_data->fluence_in_voice_rec) {
@@ -2039,85 +2269,10 @@
               (mode == AUDIO_MODE_IN_COMMUNICATION)) {
         if (out_device & AUDIO_DEVICE_OUT_SPEAKER)
             in_device = AUDIO_DEVICE_IN_BACK_MIC;
-        if (adev->active_input) {
-            if (my_data->fluence_type != FLUENCE_NONE &&
-                adev->active_input->enable_aec &&
-                adev->active_input->enable_ns) {
-                if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
-                    if (my_data->fluence_in_spkr_mode) {
-                        if (my_data->fluence_type & FLUENCE_QUAD_MIC) {
-                            snd_device = SND_DEVICE_IN_SPEAKER_QMIC_AEC_NS;
-                        } else if (my_data->fluence_type & FLUENCE_DUAL_MIC) {
-                            if (my_data->fluence_mode == FLUENCE_BROADSIDE)
-                                snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS_BROADSIDE;
-                            else
-                                snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS;
-                        }
-                        adev->acdb_settings |= DMIC_FLAG;
-                    } else
-                        snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC_NS;
-                } else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
-                    if (my_data->fluence_type & FLUENCE_DUAL_MIC) {
-                        snd_device = SND_DEVICE_IN_HANDSET_DMIC_AEC_NS;
-                        adev->acdb_settings |= DMIC_FLAG;
-                    } else
-                        snd_device = SND_DEVICE_IN_HANDSET_MIC_AEC_NS;
-                } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
-                    snd_device = SND_DEVICE_IN_HEADSET_MIC_FLUENCE;
-                }
-                platform_set_echo_reference(adev, true, out_device);
-            } else if (my_data->fluence_type != FLUENCE_NONE &&
-                       adev->active_input->enable_aec) {
-                if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
-                    if (my_data->fluence_in_spkr_mode) {
-                        if (my_data->fluence_type & FLUENCE_QUAD_MIC) {
-                            snd_device = SND_DEVICE_IN_SPEAKER_QMIC_AEC;
-                        } else if (my_data->fluence_type & FLUENCE_DUAL_MIC) {
-                            if (my_data->fluence_mode == FLUENCE_BROADSIDE)
-                                snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC_BROADSIDE;
-                            else
-                                snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC;
-                        }
-                        adev->acdb_settings |= DMIC_FLAG;
-                    } else
-                        snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC;
-                } else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
-                    if (my_data->fluence_type & FLUENCE_DUAL_MIC) {
-                        snd_device = SND_DEVICE_IN_HANDSET_DMIC_AEC;
-                        adev->acdb_settings |= DMIC_FLAG;
-                    } else
-                        snd_device = SND_DEVICE_IN_HANDSET_MIC_AEC;
-                } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
-                    snd_device = SND_DEVICE_IN_HEADSET_MIC_FLUENCE;
-                }
-                platform_set_echo_reference(adev, true, out_device);
-            } else if (my_data->fluence_type != FLUENCE_NONE &&
-                       adev->active_input->enable_ns) {
-                if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
-                    if (my_data->fluence_in_spkr_mode) {
-                        if (my_data->fluence_type & FLUENCE_QUAD_MIC) {
-                            snd_device = SND_DEVICE_IN_SPEAKER_QMIC_NS;
-                        } else if (my_data->fluence_type & FLUENCE_DUAL_MIC) {
-                            if (my_data->fluence_mode == FLUENCE_BROADSIDE)
-                                snd_device = SND_DEVICE_IN_SPEAKER_DMIC_NS_BROADSIDE;
-                            else
-                                snd_device = SND_DEVICE_IN_SPEAKER_DMIC_NS;
-                        }
-                        adev->acdb_settings |= DMIC_FLAG;
-                    } else
-                        snd_device = SND_DEVICE_IN_SPEAKER_MIC_NS;
-                } else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
-                    if (my_data->fluence_type & FLUENCE_DUAL_MIC) {
-                        snd_device = SND_DEVICE_IN_HANDSET_DMIC_NS;
-                        adev->acdb_settings |= DMIC_FLAG;
-                    } else
-                        snd_device = SND_DEVICE_IN_HANDSET_MIC_NS;
-                } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
-                    snd_device = SND_DEVICE_IN_HEADSET_MIC_FLUENCE;
-                }
-                platform_set_echo_reference(adev, false, out_device);
-            } else
-                platform_set_echo_reference(adev, false, out_device);
+
+        if (in) {
+            snd_device = get_snd_device_for_voice_comm(my_data, in, 
+                                                       out_device, in_device);
         }
     } else if (source == AUDIO_SOURCE_FM_TUNER) {
         snd_device = SND_DEVICE_IN_CAPTURE_FM;
diff --git a/hal/msm8916/platform.h b/hal/msm8916/platform.h
index 9913322..f3dbc3d 100644
--- a/hal/msm8916/platform.h
+++ b/hal/msm8916/platform.h
@@ -250,6 +250,11 @@
 
 #define AUDIO_MAKE_STRING_FROM_ENUM(X)   { #X, X }
 
+#define TX_VOICE_FLUENCE_PROV2 0x10F17
+#define TX_VOICE_DM_FV5_BROADSIDE 0x10F18
+#define TX_VOICE_FV5ECNS_SM 0x10F09
+#define TX_VOICE_FV5ECNS_DM 0x10F0A
+
 #define LIB_CSD_CLIENT "libcsd-client.so"
 /* CSD-CLIENT related functions */
 typedef int (*init_t)();
diff --git a/hal/msm8960/platform.c b/hal/msm8960/platform.c
index bd8c41c..be2b95e 100644
--- a/hal/msm8960/platform.c
+++ b/hal/msm8960/platform.c
@@ -729,21 +729,24 @@
     return snd_device;
 }
 
-snd_device_t platform_get_input_snd_device(void *platform, audio_devices_t out_device)
+snd_device_t platform_get_input_snd_device(void *platform,
+                                           struct stream_in *in,
+                                           audio_devices_t out_device)
 {
     struct platform_data *my_data = (struct platform_data *)platform;
     struct audio_device *adev = my_data->adev;
-    audio_source_t  source = (adev->active_input == NULL) ?
-                                AUDIO_SOURCE_DEFAULT : adev->active_input->source;
-
-    audio_mode_t    mode   = adev->mode;
-    audio_devices_t in_device = ((adev->active_input == NULL) ?
-                                    AUDIO_DEVICE_NONE : adev->active_input->device)
-                                & ~AUDIO_DEVICE_BIT_IN;
-    audio_channel_mask_t channel_mask = (adev->active_input == NULL) ?
-                                AUDIO_CHANNEL_IN_MONO : adev->active_input->channel_mask;
+    audio_mode_t mode = adev->mode;
     snd_device_t snd_device = SND_DEVICE_NONE;
 
+    if (in == NULL) {
+        in = adev_get_active_input(adev);
+    }
+
+    audio_source_t source = (in == NULL) ? AUDIO_SOURCE_DEFAULT : in->source;
+    audio_devices_t in_device =
+        ((in == NULL) ? AUDIO_DEVICE_NONE : in->device) & ~AUDIO_DEVICE_BIT_IN;
+    audio_channel_mask_t channel_mask = (in == NULL) ? AUDIO_CHANNEL_IN_MONO : in->channel_mask;
+
     ALOGV("%s: enter: out_device(%#x) in_device(%#x)",
           __func__, out_device, in_device);
     if ((out_device != AUDIO_DEVICE_NONE) && voice_is_in_call(adev)) {
@@ -827,8 +830,8 @@
             mode == AUDIO_MODE_IN_COMMUNICATION) {
         if (out_device & AUDIO_DEVICE_OUT_SPEAKER)
             in_device = AUDIO_DEVICE_IN_BACK_MIC;
-        if (adev->active_input) {
-            if (adev->active_input->enable_aec) {
+        if (in) {
+            if (in != NULL && in->enable_aec) {
                 if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
                     snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC;
                 } else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index 5a36f0c..f03356b 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -72,6 +72,8 @@
 #define TOSTRING_(x) #x
 #define TOSTRING(x) TOSTRING_(x)
 
+#define GET_IN_DEVICE_INDEX(SND_DEVICE) ((SND_DEVICE) - (SND_DEVICE_IN_BEGIN))
+
 struct audio_block_header
 {
     int reserved;
@@ -125,6 +127,10 @@
     uint32_t             sampling_rate;
     uint32_t             cal_type;
     uint32_t             module_id;
+#ifdef PLATFORM_SM8150
+    uint16_t             instance_id;
+    uint16_t             reserved;
+#endif
     uint32_t             param_id;
 } acdb_audio_cal_cfg_t;
 
@@ -364,6 +370,32 @@
     [SND_DEVICE_IN_CAMCORDER_SELFIE_LANDSCAPE] = "camcorder-mic",
     [SND_DEVICE_IN_CAMCORDER_SELFIE_INVERT_LANDSCAPE] = "camcorder-mic",
     [SND_DEVICE_IN_CAMCORDER_SELFIE_PORTRAIT] = "camcorder-mic",
+    [SND_DEVICE_IN_SPEAKER_QMIC_NS] = "quad-mic",
+    [SND_DEVICE_IN_SPEAKER_QMIC_AEC_NS] = "quad-mic",
+};
+
+static struct audio_effect_config \
+                  effect_config_table[GET_IN_DEVICE_INDEX(SND_DEVICE_MAX)][EFFECT_COUNT] = {
+    [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_SPEAKER_QMIC_AEC_NS)][EFFECT_AEC] = \
+                                      {TX_VOICE_FLUENCE_PROV2, 0x0, 0x10EAF, 0x01},
+    [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_SPEAKER_QMIC_AEC_NS)][EFFECT_NS] = \
+                                      {TX_VOICE_FLUENCE_PROV2,  0x0, 0x10EAF, 0x02},
+    [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS)][EFFECT_AEC] = \
+                                      {TX_VOICE_FV5ECNS_DM, 0x0, 0x10EAF, 0x01},
+    [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS)][EFFECT_NS] = \
+                                      {TX_VOICE_FV5ECNS_DM, 0x0, 0x10EAF, 0x02},
+    [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_SPEAKER_MIC_AEC_NS)][EFFECT_AEC] = \
+                                      {TX_VOICE_FV5ECNS_SM, 0x0, 0x10EAF, 0x01},
+    [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_SPEAKER_MIC_AEC_NS)][EFFECT_NS] = \
+                                      {TX_VOICE_FV5ECNS_SM, 0x0, 0x10EAF, 0x02},
+    [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_HANDSET_DMIC_AEC_NS)][EFFECT_AEC] = \
+                                      {TX_VOICE_FV5ECNS_DM, 0x0, 0x10EAF, 0x01},
+    [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_HANDSET_DMIC_AEC_NS)][EFFECT_NS] = \
+                                      {TX_VOICE_FV5ECNS_DM, 0x0, 0x10EAF, 0x02},
+    [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_HANDSET_MIC_AEC_NS)][EFFECT_AEC] = \
+                                      {TX_VOICE_FV5ECNS_SM, 0x0, 0x10EAF, 0x01},
+    [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_HANDSET_MIC_AEC_NS)][EFFECT_NS] = \
+                                      {TX_VOICE_FV5ECNS_SM, 0x0, 0x10EAF, 0x02},
 };
 
 /* ACDB IDs (audio DSP path configuration IDs) for each sound device */
@@ -487,6 +519,8 @@
     [SND_DEVICE_IN_CAMCORDER_SELFIE_LANDSCAPE] = 61,
     [SND_DEVICE_IN_CAMCORDER_SELFIE_INVERT_LANDSCAPE] = 61,
     [SND_DEVICE_IN_CAMCORDER_SELFIE_PORTRAIT] = 61,
+    [SND_DEVICE_IN_SPEAKER_QMIC_NS] = 129,
+    [SND_DEVICE_IN_SPEAKER_QMIC_AEC_NS] = 129,
 };
 
 // Platform specific backend bit width table
@@ -623,6 +657,8 @@
     {TO_NAME_INDEX(SND_DEVICE_IN_CAMCORDER_SELFIE_PORTRAIT)},
     /* For legacy xml file parsing */
     {TO_NAME_INDEX(SND_DEVICE_IN_CAMCORDER_MIC)},
+    {TO_NAME_INDEX(SND_DEVICE_IN_SPEAKER_QMIC_NS)},
+    {TO_NAME_INDEX(SND_DEVICE_IN_SPEAKER_QMIC_AEC_NS)},
 };
 
 static char * backend_tag_table[SND_DEVICE_MAX] = {0};
@@ -911,7 +947,9 @@
 
         if (cal.dev_id) {
             if (audio_is_input_device(cal.dev_id)) {
-                cal.snd_dev_id = platform_get_input_snd_device(platform, cal.dev_id);
+                // FIXME: why pass an input device whereas
+                // platform_get_input_snd_device() expects as an output device?
+                cal.snd_dev_id = platform_get_input_snd_device(platform, NULL, cal.dev_id);
             } else {
                 cal.snd_dev_id = platform_get_output_snd_device(platform, cal.dev_id);
             }
@@ -1336,6 +1374,8 @@
     hw_interface_table[SND_DEVICE_IN_SPEAKER_DMIC_STEREO] = strdup("SLIMBUS_0_TX");
     hw_interface_table[SND_DEVICE_IN_VOICE_DMIC] = strdup("SLIMBUS_0_TX");
     hw_interface_table[SND_DEVICE_IN_VOICE_DMIC_TMUS] = strdup("SLIMBUS_0_TX");
+    hw_interface_table[SND_DEVICE_IN_SPEAKER_QMIC_NS] = strdup("SLIMBUS_0_TX");
+    hw_interface_table[SND_DEVICE_IN_SPEAKER_QMIC_AEC_NS] = strdup("SLIMBUS_0_TX");
     hw_interface_table[SND_DEVICE_IN_VOICE_SPEAKER_MIC] = strdup("SLIMBUS_0_TX");
     hw_interface_table[SND_DEVICE_IN_VOICE_SPEAKER_DMIC] = strdup("SLIMBUS_0_TX");
     hw_interface_table[SND_DEVICE_IN_VOICE_SPEAKER_MIC_HFP] = strdup("SLIMBUS_0_TX");
@@ -1649,7 +1689,8 @@
 
     my_data->declared_mic_count = 0;
     /* Initialize platform specific ids and/or backends*/
-    platform_info_init(platform_info_file, my_data);
+    platform_info_init(platform_info_file, my_data,
+                       true, &platform_set_parameters);
 
     ALOGD("%s: Loading mixer file: %s", __func__, mixer_xml_file);
     adev->audio_route = audio_route_init(snd_card_num, mixer_xml_file);
@@ -2060,6 +2101,57 @@
     return find_index(usecase_name_index, AUDIO_USECASE_MAX, usecase_name);
 }
 
+int platform_get_effect_config_data(snd_device_t snd_device,
+                                      struct audio_effect_config *effect_config,
+                                      effect_type_t effect_type)
+{
+    int ret = 0;
+
+    if ((snd_device < SND_DEVICE_IN_BEGIN) || (snd_device >= SND_DEVICE_MAX) ||
+        (effect_type <= EFFECT_NONE) || (effect_type >= EFFECT_COUNT)) {
+        ALOGE("%s: Invalid snd_device = %d or effect_type = %d",
+            __func__, snd_device, effect_type);
+        ret = -EINVAL;
+        goto done;
+    }
+
+    if (effect_config == NULL) {
+        ALOGE("%s: Invalid effect_config", __func__);
+        ret = -EINVAL;
+        goto done;
+    }
+
+    ALOGV("%s: snd_device = %d module_id = %d",
+            __func__, snd_device, effect_config_table[GET_IN_DEVICE_INDEX(snd_device)][effect_type].module_id);
+    *effect_config = effect_config_table[GET_IN_DEVICE_INDEX(snd_device)][effect_type];
+
+done:
+    return ret;
+}
+
+int platform_set_effect_config_data(snd_device_t snd_device,
+                                      struct audio_effect_config effect_config,
+                                      effect_type_t effect_type)
+{
+    int ret = 0;
+
+    if ((snd_device < SND_DEVICE_IN_BEGIN) || (snd_device >= SND_DEVICE_MAX) ||
+        (effect_type <= EFFECT_NONE) || (effect_type >= EFFECT_COUNT)) {
+        ALOGE("%s: Invalid snd_device = %d or effect_type = %d",
+            __func__, snd_device, effect_type);
+        ret = -EINVAL;
+        goto done;
+    }
+
+    ALOGV("%s 0x%x 0x%x 0x%x 0x%x", __func__, effect_config.module_id,
+           effect_config.instance_id, effect_config.param_id,
+           effect_config.param_value);
+    effect_config_table[GET_IN_DEVICE_INDEX(snd_device)][effect_type] = effect_config;
+
+done:
+    return ret;
+}
+
 void platform_add_operator_specific_device(snd_device_t snd_device,
                                            const char *operator,
                                            const char *mixer_path,
@@ -2512,7 +2604,7 @@
               __func__, mixer_ctl_name);
         return -EINVAL;
     }
-    ALOGV("Setting voice mute state: %d", state);
+    ALOGV("%s: Setting voice mute state: %d", __func__, state);
     mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
 
     if (my_data->csd != NULL) {
@@ -2858,24 +2950,148 @@
     return snd_device;
 }
 
-snd_device_t platform_get_input_snd_device(void *platform, audio_devices_t out_device)
+#ifdef DYNAMIC_ECNS_ENABLED
+static snd_device_t get_snd_device_for_voice_comm(struct platform_data *my_data,
+                                                  struct stream_in *in __unused,
+                                                  audio_devices_t out_device,
+                                                  audio_devices_t in_device)
+{
+    struct audio_device *adev = my_data->adev;
+    snd_device_t snd_device = SND_DEVICE_NONE;
+
+    if (my_data->fluence_type != FLUENCE_DISABLE) {
+        switch(AUDIO_DEVICE_BIT_IN | in_device) {
+            case AUDIO_DEVICE_IN_BACK_MIC:
+                if (my_data->fluence_in_spkr_mode) {
+                    if ((my_data->fluence_type & FLUENCE_PRO_ENABLE) &&
+                        (my_data->source_mic_type & SOURCE_QUAD_MIC)) {
+                        snd_device = SND_DEVICE_IN_SPEAKER_QMIC_AEC_NS;
+                    } else if (((my_data->fluence_type & FLUENCE_PRO_ENABLE) ||
+                               (my_data->fluence_type & FLUENCE_ENABLE)) &&
+                               (my_data->source_mic_type & SOURCE_DUAL_MIC)) {
+                            snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS;
+                    }
+                    adev->acdb_settings |= DMIC_FLAG;
+                } else
+                    snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC_NS;
+                break;
+            case AUDIO_DEVICE_IN_BUILTIN_MIC:
+                if (((my_data->fluence_type & FLUENCE_PRO_ENABLE) ||
+                    (my_data->fluence_type & FLUENCE_ENABLE)) &&
+                    (my_data->source_mic_type & SOURCE_DUAL_MIC)) {
+                    snd_device = SND_DEVICE_IN_HANDSET_DMIC_AEC_NS;
+                    adev->acdb_settings |= DMIC_FLAG;
+                } else
+                    snd_device = SND_DEVICE_IN_HANDSET_MIC_AEC_NS;
+                break;
+            default:
+                ALOGE("%s: Unsupported in_device %#x", __func__, in_device);
+                break;
+        }
+        platform_set_echo_reference(adev, true, out_device);
+    }
+
+    return snd_device;
+}
+#else
+static snd_device_t get_snd_device_for_voice_comm(struct platform_data *my_data,
+                                                  struct stream_in *in,
+                                                  audio_devices_t out_device,
+                                                  audio_devices_t in_device)
+{
+    struct audio_device *adev = my_data->adev;
+    snd_device_t snd_device = SND_DEVICE_NONE;
+
+    if (in->enable_aec &&
+            in->enable_ns) {
+        if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
+            if (my_data->fluence_in_spkr_mode &&
+                    my_data->fluence_in_voice_comm &&
+                    (my_data->source_mic_type & SOURCE_DUAL_MIC)) {
+                snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS;
+            } else {
+                snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC_NS;
+            }
+        } else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
+            if (my_data->fluence_in_voice_comm &&
+                    (my_data->source_mic_type & SOURCE_DUAL_MIC)) {
+                snd_device = SND_DEVICE_IN_HANDSET_DMIC_AEC_NS;
+            } else {
+                snd_device = SND_DEVICE_IN_HANDSET_MIC_AEC_NS;
+            }
+        } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
+            snd_device = SND_DEVICE_IN_HEADSET_MIC_AEC;
+        } else if (audio_is_usb_in_device(in_device | AUDIO_DEVICE_BIT_IN)) {
+            snd_device = SND_DEVICE_IN_USB_HEADSET_MIC_AEC;
+        }
+        platform_set_echo_reference(adev, true, out_device);
+    } else if (in->enable_aec) {
+        if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
+            if (my_data->fluence_in_spkr_mode &&
+                    my_data->fluence_in_voice_comm &&
+                    (my_data->source_mic_type & SOURCE_DUAL_MIC)) {
+                snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC;
+            } else {
+                snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC;
+            }
+        } else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
+            if (my_data->fluence_in_voice_comm &&
+                    (my_data->source_mic_type & SOURCE_DUAL_MIC)) {
+                snd_device = SND_DEVICE_IN_HANDSET_DMIC_AEC;
+            } else {
+                snd_device = SND_DEVICE_IN_HANDSET_MIC_AEC;
+            }
+       } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
+           snd_device = SND_DEVICE_IN_HEADSET_MIC_AEC;
+       } else if (audio_is_usb_in_device(in_device | AUDIO_DEVICE_BIT_IN)) {
+           snd_device = SND_DEVICE_IN_USB_HEADSET_MIC_AEC;
+       }
+       platform_set_echo_reference(adev, true, out_device);
+    } else if (in->enable_ns) {
+        if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
+            if (my_data->fluence_in_spkr_mode &&
+                    my_data->fluence_in_voice_comm &&
+                    (my_data->source_mic_type & SOURCE_DUAL_MIC)) {
+                snd_device = SND_DEVICE_IN_SPEAKER_DMIC_NS;
+            } else {
+                snd_device = SND_DEVICE_IN_SPEAKER_MIC_NS;
+            }
+        } else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
+            if (my_data->fluence_in_voice_comm &&
+                    (my_data->source_mic_type & SOURCE_DUAL_MIC)) {
+                snd_device = SND_DEVICE_IN_HANDSET_DMIC_NS;
+            } else {
+                snd_device = SND_DEVICE_IN_HANDSET_MIC_NS;
+            }
+        }
+    }
+
+    return snd_device;
+}
+#endif //DYNAMIC_ECNS_ENABLED
+
+snd_device_t platform_get_input_snd_device(void *platform,
+                                           struct stream_in *in,
+                                           audio_devices_t out_device)
 {
     struct platform_data *my_data = (struct platform_data *)platform;
     struct audio_device *adev = my_data->adev;
-    audio_source_t  source = (adev->active_input == NULL) ?
-                                AUDIO_SOURCE_DEFAULT : adev->active_input->source;
-
-    audio_mode_t    mode   = adev->mode;
-    audio_devices_t in_device = ((adev->active_input == NULL) ?
-                                    AUDIO_DEVICE_NONE : adev->active_input->device)
-                                & ~AUDIO_DEVICE_BIT_IN;
-    audio_channel_mask_t channel_mask = (adev->active_input == NULL) ?
-                                AUDIO_CHANNEL_IN_MONO : adev->active_input->channel_mask;
+    audio_mode_t mode = adev->mode;
     snd_device_t snd_device = SND_DEVICE_NONE;
-    int channel_count = popcount(channel_mask);
+
+    if (in == NULL) {
+        in = adev_get_active_input(adev);
+    }
+
+    audio_source_t source = (in == NULL) ? AUDIO_SOURCE_DEFAULT : in->source;
+    audio_devices_t in_device =
+        ((in == NULL) ? AUDIO_DEVICE_NONE : in->device) & ~AUDIO_DEVICE_BIT_IN;
+    audio_channel_mask_t channel_mask = (in == NULL) ? AUDIO_CHANNEL_IN_MONO : in->channel_mask;
+    int channel_count = audio_channel_count_from_in_mask(channel_mask);
 
     ALOGV("%s: enter: out_device(%#x) in_device(%#x) channel_count (%d) channel_mask (0x%x)",
           __func__, out_device, in_device, channel_count, channel_mask);
+
     if ((out_device != AUDIO_DEVICE_NONE) && (voice_is_in_call(adev) ||
         audio_extn_hfp_is_active(adev))) {
         if (adev->voice.tty_mode != TTY_MODE_OFF) {
@@ -3004,20 +3220,20 @@
             if (my_data->fluence_in_voice_rec && channel_count == 1) {
                 if ((my_data->fluence_type == FLUENCE_PRO_ENABLE) &&
                     (my_data->source_mic_type & SOURCE_QUAD_MIC)) {
-                    if (adev->active_input->enable_aec)
+                    if (in->enable_aec)
                         snd_device = SND_DEVICE_IN_HANDSET_QMIC_AEC;
                     else
                         snd_device = SND_DEVICE_IN_HANDSET_QMIC;
                 } else if ((my_data->fluence_type == FLUENCE_PRO_ENABLE) &&
                     (my_data->source_mic_type & SOURCE_THREE_MIC)) {
-                    if (adev->active_input->enable_aec)
+                    if (in->enable_aec)
                         snd_device = SND_DEVICE_IN_HANDSET_TMIC_AEC;
                     else
                         snd_device = SND_DEVICE_IN_HANDSET_TMIC;
                 } else if (((my_data->fluence_type == FLUENCE_PRO_ENABLE) ||
                     (my_data->fluence_type == FLUENCE_ENABLE)) &&
                     (my_data->source_mic_type & SOURCE_DUAL_MIC)) {
-                    if (adev->active_input->enable_aec)
+                    if (in->enable_aec)
                         snd_device = SND_DEVICE_IN_HANDSET_DMIC_AEC;
                     else
                         snd_device = SND_DEVICE_IN_VOICE_REC_DMIC_FLUENCE;
@@ -3034,14 +3250,14 @@
                 snd_device = SND_DEVICE_IN_QUAD_MIC;
             }
             if (snd_device == SND_DEVICE_NONE) {
-                if (adev->active_input->enable_aec) {
-                    if (adev->active_input->enable_ns) {
+                if (in->enable_aec) {
+                    if (in->enable_ns) {
                         snd_device = SND_DEVICE_IN_VOICE_REC_MIC_AEC_NS;
                     } else {
                         snd_device = SND_DEVICE_IN_VOICE_REC_MIC_AEC;
                     }
                     platform_set_echo_reference(adev, true, out_device);
-                } else if (adev->active_input->enable_ns) {
+                } else if (in->enable_ns) {
                     snd_device = SND_DEVICE_IN_VOICE_REC_MIC_NS;
                 } else {
                     snd_device = SND_DEVICE_IN_VOICE_REC_MIC;
@@ -3080,70 +3296,9 @@
                 !audio_extn_usb_is_capture_supported())) {
             in_device = AUDIO_DEVICE_IN_BACK_MIC;
         }
-        if (adev->active_input) {
-            if (adev->active_input->enable_aec &&
-                    adev->active_input->enable_ns) {
-                if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
-                    if (my_data->fluence_in_spkr_mode &&
-                            my_data->fluence_in_voice_comm &&
-                            (my_data->source_mic_type & SOURCE_DUAL_MIC)) {
-                        snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS;
-                    } else {
-                        snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC_NS;
-                    }
-                } else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
-                    if (my_data->fluence_in_voice_comm &&
-                            (my_data->source_mic_type & SOURCE_DUAL_MIC)) {
-                        snd_device = SND_DEVICE_IN_HANDSET_DMIC_AEC_NS;
-                    } else {
-                        snd_device = SND_DEVICE_IN_HANDSET_MIC_AEC_NS;
-                    }
-                } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
-                    snd_device = SND_DEVICE_IN_HEADSET_MIC_AEC;
-                } else if (audio_is_usb_in_device(in_device | AUDIO_DEVICE_BIT_IN)) {
-                    snd_device = SND_DEVICE_IN_USB_HEADSET_MIC_AEC;
-                }
-                platform_set_echo_reference(adev, true, out_device);
-            } else if (adev->active_input->enable_aec) {
-                if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
-                    if (my_data->fluence_in_spkr_mode &&
-                            my_data->fluence_in_voice_comm &&
-                            (my_data->source_mic_type & SOURCE_DUAL_MIC)) {
-                        snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC;
-                    } else {
-                        snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC;
-                    }
-                } else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
-                    if (my_data->fluence_in_voice_comm &&
-                            (my_data->source_mic_type & SOURCE_DUAL_MIC)) {
-                        snd_device = SND_DEVICE_IN_HANDSET_DMIC_AEC;
-                    } else {
-                        snd_device = SND_DEVICE_IN_HANDSET_MIC_AEC;
-                    }
-               } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
-                   snd_device = SND_DEVICE_IN_HEADSET_MIC_AEC;
-               } else if (audio_is_usb_in_device(in_device | AUDIO_DEVICE_BIT_IN)) {
-                   snd_device = SND_DEVICE_IN_USB_HEADSET_MIC_AEC;
-               }
-               platform_set_echo_reference(adev, true, out_device);
-            } else if (adev->active_input->enable_ns) {
-                if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
-                    if (my_data->fluence_in_spkr_mode &&
-                            my_data->fluence_in_voice_comm &&
-                            (my_data->source_mic_type & SOURCE_DUAL_MIC)) {
-                        snd_device = SND_DEVICE_IN_SPEAKER_DMIC_NS;
-                    } else {
-                        snd_device = SND_DEVICE_IN_SPEAKER_MIC_NS;
-                    }
-                } else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
-                    if (my_data->fluence_in_voice_comm &&
-                            (my_data->source_mic_type & SOURCE_DUAL_MIC)) {
-                        snd_device = SND_DEVICE_IN_HANDSET_DMIC_NS;
-                    } else {
-                        snd_device = SND_DEVICE_IN_HANDSET_MIC_NS;
-                    }
-                }
-            }
+
+        if (in) {
+            snd_device = get_snd_device_for_voice_comm(my_data, in, out_device, in_device);
         }
     } else if (source == AUDIO_SOURCE_DEFAULT) {
         goto exit;
@@ -4743,7 +4898,7 @@
     size_t actual_mic_count = 0;
 
     snd_device_t active_input_snd_device =
-            platform_get_input_snd_device(platform, usecase->stream.in->device);
+            platform_get_input_snd_device(platform, usecase->stream.in, AUDIO_DEVICE_NONE);
     if (active_input_snd_device == SND_DEVICE_NONE) {
         ALOGI("%s: No active microphones found", __func__);
         goto end;
diff --git a/hal/msm8974/platform.h b/hal/msm8974/platform.h
index f6c5a58..a885f27 100644
--- a/hal/msm8974/platform.h
+++ b/hal/msm8974/platform.h
@@ -190,6 +190,8 @@
     SND_DEVICE_IN_CAMCORDER_SELFIE_LANDSCAPE,
     SND_DEVICE_IN_CAMCORDER_SELFIE_INVERT_LANDSCAPE,
     SND_DEVICE_IN_CAMCORDER_SELFIE_PORTRAIT,
+    SND_DEVICE_IN_SPEAKER_QMIC_NS,
+    SND_DEVICE_IN_SPEAKER_QMIC_AEC_NS,
     SND_DEVICE_IN_END,
 
     SND_DEVICE_MAX = SND_DEVICE_IN_END,
@@ -343,6 +345,11 @@
 #define HFP_ASM_RX_TX 24
 #endif
 
+#define TX_VOICE_FLUENCE_PROV2 0x10F17
+#define TX_VOICE_DM_FV5_BROADSIDE 0x10F18
+#define TX_VOICE_FV5ECNS_SM 0x10F09
+#define TX_VOICE_FV5ECNS_DM 0x10F0A
+
 #define LIB_CSD_CLIENT "libcsd-client.so"
 #define LIB_MDM_DETECT "libmdmdetect.so"
 
diff --git a/hal/platform_api.h b/hal/platform_api.h
index 1a7d2c3..5e5b662 100644
--- a/hal/platform_api.h
+++ b/hal/platform_api.h
@@ -27,6 +27,20 @@
 #define SAMPLE_RATE_11025 11025
 #define sample_rate_multiple(sr, base) ((sr % base)== 0?true:false)
 
+typedef enum {
+    EFFECT_NONE = 0,
+    EFFECT_AEC,
+    EFFECT_NS,
+    EFFECT_COUNT
+} effect_type_t;
+
+struct audio_effect_config {
+    uint32_t module_id;
+    uint32_t instance_id;
+    uint32_t param_id;
+    uint32_t param_value;
+};
+
 struct amp_db_and_gain_table {
     float amp;
     float db;
@@ -56,6 +70,12 @@
 int platform_get_snd_device_index(char *snd_device_index_name);
 int platform_set_snd_device_acdb_id(snd_device_t snd_device, unsigned int acdb_id);
 int platform_get_snd_device_acdb_id(snd_device_t snd_device);
+int platform_set_effect_config_data(snd_device_t snd_device,
+                                      struct audio_effect_config effect_config,
+                                      effect_type_t effect_type);
+int platform_get_effect_config_data(snd_device_t snd_device,
+                                      struct audio_effect_config *effect_config,
+                                      effect_type_t effect_type);
 int platform_send_audio_calibration(void *platform, snd_device_t snd_device);
 int platform_send_audio_calibration_v2(void *platform, struct audio_usecase *usecase,
                                        int app_type, int sample_rate);
@@ -82,7 +102,9 @@
 int platform_get_sample_rate(void *platform, uint32_t *rate);
 int platform_set_device_mute(void *platform, bool state, char *dir);
 snd_device_t platform_get_output_snd_device(void *platform, audio_devices_t devices);
-snd_device_t platform_get_input_snd_device(void *platform, audio_devices_t out_device);
+snd_device_t platform_get_input_snd_device(void *platform,
+                                           struct stream_in *in,
+                                           audio_devices_t out_device);
 int platform_set_hdmi_channels(void *platform, int channel_count);
 int platform_edid_get_max_channels(void *platform);
 void platform_add_operator_specific_device(snd_device_t snd_device,
@@ -117,11 +139,11 @@
 
 bool platform_sound_trigger_usecase_needs_event(audio_usecase_t uc_id);
 
-/* From platform_info.c */
-int platform_info_init(const char *filename, void *);
-
 typedef int (*set_parameters_fn)(void *platform, struct str_parms *parms);
-int snd_card_info_init(const char *filename, void *, set_parameters_fn);
+
+/* From platform_info.c */
+int platform_info_init(const char *filename, void *,
+                       bool do_full_parse, set_parameters_fn);
 
 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);
@@ -182,4 +204,8 @@
 int platform_get_usb_service_interval(void *platform,
                                       bool playback,
                                       unsigned long *service_interval);
+
+/* callback functions from platform to common audio HAL */
+struct stream_in *adev_get_active_input(const struct audio_device *adev);
+
 #endif // AUDIO_PLATFORM_API_H
diff --git a/hal/platform_info.c b/hal/platform_info.c
index f5fbe3f..233e120 100644
--- a/hal/platform_info.c
+++ b/hal/platform_info.c
@@ -25,10 +25,22 @@
 #include "platform_api.h"
 #include <platform.h>
 #include <math.h>
+#include <pthread.h>
+
+/*
+ * Mandatory microphone characteristics include: device_id, type, address, location, group,
+ * index_in_the_group, directionality, num_frequency_responses, frequencies and responses.
+ * MANDATORY_MICROPHONE_CHARACTERISTICS should be updated when mandatory microphone
+ * characteristics are changed.
+ */
+#define MANDATORY_MICROPHONE_CHARACTERISTICS (1 << 10) - 1
 
 typedef enum {
     ROOT,
     ACDB,
+    MODULE,
+    AEC,
+    NS,
     PCM_ID,
     BACKEND_NAME,
     CONFIG_PARAMS,
@@ -47,6 +59,9 @@
 typedef void (* section_process_fn)(const XML_Char **attr);
 
 static void process_acdb_id(const XML_Char **attr);
+static void process_audio_effect(const XML_Char **attr, effect_type_t effect_type);
+static void process_effect_aec(const XML_Char **attr);
+static void process_effect_ns(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_config_params(const XML_Char **attr);
@@ -62,6 +77,8 @@
 static section_process_fn section_table[] = {
     [ROOT] = process_root,
     [ACDB] = process_acdb_id,
+    [AEC] = process_effect_aec,
+    [NS] = process_effect_ns,
     [PCM_ID] = process_pcm_id,
     [BACKEND_NAME] = process_backend_name,
     [CONFIG_PARAMS] = process_config_params,
@@ -74,17 +91,19 @@
     [ACDB_METAINFO_KEY] = process_acdb_metainfo_key,
 };
 
-static set_parameters_fn set_parameters = &platform_set_parameters;
-
 static section_t section;
 
 struct platform_info {
+    pthread_mutex_t   lock;
     bool              do_full_parse;
     void             *platform;
     struct str_parms *kvpairs;
+    set_parameters_fn set_parameters;
 };
 
-static struct platform_info my_data = {true, NULL, NULL};
+static struct platform_info my_data = {PTHREAD_MUTEX_INITIALIZER,
+                                       true, NULL, NULL,
+                                       &platform_set_parameters};
 
 struct audio_string_to_enum {
     const char* name;
@@ -145,17 +164,6 @@
     AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_DEFAULT),
 };
 
-enum {
-    AUDIO_MICROPHONE_CHARACTERISTIC_NONE = 0u, // 0x0
-    AUDIO_MICROPHONE_CHARACTERISTIC_SENSITIVITY = 1u, // 0x1
-    AUDIO_MICROPHONE_CHARACTERISTIC_MAX_SPL = 2u, // 0x2
-    AUDIO_MICROPHONE_CHARACTERISTIC_MIN_SPL = 4u, // 0x4
-    AUDIO_MICROPHONE_CHARACTERISTIC_ORIENTATION = 8u, // 0x8
-    AUDIO_MICROPHONE_CHARACTERISTIC_GEOMETRIC_LOCATION = 16u, // 0x10
-    AUDIO_MICROPHONE_CHARACTERISTIC_ALL = 31u, /* ((((SENSITIVITY | MAX_SPL) | MIN_SPL)
-                                                  | ORIENTATION) | GEOMETRIC_LOCATION) */
-};
-
 static bool find_enum_by_string(const struct audio_string_to_enum * table, const char * name,
                                 int32_t len, unsigned int *value)
 {
@@ -185,6 +193,11 @@
  * ...
  * ...
  * </acdb_ids>
+ * <module_ids>
+ * <device name="???" module_id="???"/>
+ * ...
+ * ...
+ * </module_ids>
  * <backend_names>
  * <device name="???" backend="???"/>
  * ...
@@ -216,6 +229,77 @@
 {
 }
 
+static void process_audio_effect(const XML_Char **attr, effect_type_t effect_type)
+{
+    int index;
+    struct audio_effect_config effect_config;
+
+    if (strncmp(attr[0], "name", strlen("name")) != 0) {
+        ALOGE("%s: 'name' not found, no MODULE ID set!", __func__);
+        goto done;
+    }
+
+    index = platform_get_snd_device_index((char *)attr[1]);
+    if (index < 0) {
+        ALOGE("%s: Device %s in platform info xml not found, no MODULE ID set!",
+              __func__, attr[1]);
+        goto done;
+    }
+
+    if (strncmp(attr[2], "module_id", strlen("module_id")) != 0) {
+        ALOGE("%s: Device %s in platform info xml has no module_id, no MODULE ID set!",
+              __func__, attr[2]);
+        goto done;
+    }
+
+    if (strncmp(attr[4], "instance_id", strlen("instance_id")) != 0) {
+        ALOGE("%s: Device %s in platform info xml has no instance_id, no INSTANCE ID set!",
+              __func__, attr[4]);
+        goto done;
+    }
+
+    if (strncmp(attr[6], "param_id", strlen("param_id")) != 0) {
+        ALOGE("%s: Device %s in platform info xml has no param_id, no PARAM ID set!",
+              __func__, attr[6]);
+        goto done;
+    }
+
+    if (strncmp(attr[8], "param_value", strlen("param_value")) != 0) {
+        ALOGE("%s: Device %s in platform info xml has no param_value, no PARAM VALUE set!",
+              __func__, attr[8]);
+        goto done;
+    }
+
+    effect_config = (struct audio_effect_config){strtol((char *)attr[3], NULL, 0),
+                                                 strtol((char *)attr[5], NULL, 0),
+                                                 strtol((char *)attr[7], NULL, 0),
+                                                 strtol((char *)attr[9], NULL, 0)};
+
+
+    if (platform_set_effect_config_data(index, effect_config, effect_type) < 0) {
+        ALOGE("%s: Effect = %d Device %s, MODULE/INSTANCE/PARAM ID %u %u %u %u was not set!",
+              __func__, effect_type, attr[1], effect_config.module_id,
+              effect_config.instance_id, effect_config.param_id,
+              effect_config.param_value);
+        goto done;
+    }
+
+done:
+    return;
+}
+
+static void process_effect_aec(const XML_Char **attr)
+{
+    process_audio_effect(attr, EFFECT_AEC);
+    return;
+}
+
+static void process_effect_ns(const XML_Char **attr)
+{
+    process_audio_effect(attr, EFFECT_NS);
+    return;
+}
+
 /* mapping from usecase to pcm dev id */
 static void process_pcm_id(const XML_Char **attr)
 {
@@ -418,7 +502,7 @@
     }
 
     str_parms_add_str(my_data.kvpairs, (char*)attr[1], (char*)attr[3]);
-    set_parameters(my_data.platform, my_data.kvpairs);
+    my_data.set_parameters(my_data.platform, my_data.kvpairs);
 done:
     return;
 }
@@ -458,221 +542,165 @@
 
 static void process_microphone_characteristic(const XML_Char **attr) {
     struct audio_microphone_characteristic_t microphone;
-    uint32_t curIdx = 0;
+    uint32_t index = 0;
+    uint32_t found_mandatory_characteristics = 0;
+    uint32_t num_frequencies = 0;
+    uint32_t num_responses = 0;
+    microphone.sensitivity = AUDIO_MICROPHONE_SENSITIVITY_UNKNOWN;
+    microphone.max_spl = AUDIO_MICROPHONE_SPL_UNKNOWN;
+    microphone.min_spl = AUDIO_MICROPHONE_SPL_UNKNOWN;
+    microphone.orientation.x = 0.0f;
+    microphone.orientation.y = 0.0f;
+    microphone.orientation.z = 0.0f;
+    microphone.geometric_location.x = AUDIO_MICROPHONE_COORDINATE_UNKNOWN;
+    microphone.geometric_location.y = AUDIO_MICROPHONE_COORDINATE_UNKNOWN;
+    microphone.geometric_location.z = AUDIO_MICROPHONE_COORDINATE_UNKNOWN;
 
-    if (strcmp(attr[curIdx++], "valid_mask")) {
-        ALOGE("%s: valid_mask not found", __func__);
-        goto done;
-    }
-    uint32_t valid_mask = atoi(attr[curIdx++]);
-
-    if (strcmp(attr[curIdx++], "device_id")) {
-        ALOGE("%s: device_id not found", __func__);
-        goto done;
-    }
-    if (strlen(attr[curIdx]) > AUDIO_MICROPHONE_ID_MAX_LEN) {
-        ALOGE("%s: device_id %s is too long", __func__, attr[curIdx]);
-        goto done;
-    }
-    strcpy(microphone.device_id, attr[curIdx++]);
-
-    if (strcmp(attr[curIdx++], "type")) {
-        ALOGE("%s: device not found", __func__);
-        goto done;
-    }
-    if (!find_enum_by_string(device_in_types, (char*)attr[curIdx++],
-            ARRAY_SIZE(device_in_types), &microphone.device)) {
-        ALOGE("%s: type %s in %s not found!",
-              __func__, attr[--curIdx], PLATFORM_INFO_XML_PATH);
-        goto done;
-    }
-
-    if (strcmp(attr[curIdx++], "address")) {
-        ALOGE("%s: address not found", __func__);
-        goto done;
-    }
-    if (strlen(attr[curIdx]) > AUDIO_DEVICE_MAX_ADDRESS_LEN) {
-        ALOGE("%s, address %s is too long", __func__, attr[curIdx]);
-        goto done;
-    }
-    strcpy(microphone.address, attr[curIdx++]);
-    if (strlen(microphone.address) == 0) {
-        // If the address is empty, populate the address according to device type.
-        if (microphone.device == AUDIO_DEVICE_IN_BUILTIN_MIC) {
-            strcpy(microphone.address, AUDIO_BOTTOM_MICROPHONE_ADDRESS);
-        } else if (microphone.device == AUDIO_DEVICE_IN_BACK_MIC) {
-            strcpy(microphone.address, AUDIO_BACK_MICROPHONE_ADDRESS);
-        }
-    }
-
-    if (strcmp(attr[curIdx++], "location")) {
-        ALOGE("%s: location not found", __func__);
-        goto done;
-    }
-    if (!find_enum_by_string(mic_locations, (char*)attr[curIdx++],
-            AUDIO_MICROPHONE_LOCATION_CNT, &microphone.location)) {
-        ALOGE("%s: location %s in %s not found!",
-              __func__, attr[--curIdx], PLATFORM_INFO_XML_PATH);
-        goto done;
-    }
-
-    if (strcmp(attr[curIdx++], "group")) {
-        ALOGE("%s: group not found", __func__);
-        goto done;
-    }
-    microphone.group = atoi(attr[curIdx++]);
-
-    if (strcmp(attr[curIdx++], "index_in_the_group")) {
-        ALOGE("%s: index_in_the_group not found", __func__);
-        goto done;
-    }
-    microphone.index_in_the_group = atoi(attr[curIdx++]);
-
-    if (strcmp(attr[curIdx++], "directionality")) {
-        ALOGE("%s: directionality not found", __func__);
-        goto done;
-    }
-    if (!find_enum_by_string(mic_directionalities, (char*)attr[curIdx++],
-                AUDIO_MICROPHONE_DIRECTIONALITY_CNT, &microphone.directionality)) {
-        ALOGE("%s: directionality %s in %s not found!",
-              __func__, attr[--curIdx], PLATFORM_INFO_XML_PATH);
-        goto done;
-    }
-
-    if (strcmp(attr[curIdx++], "num_frequency_responses")) {
-        ALOGE("%s: num_frequency_responses not found", __func__);
-        goto done;
-    }
-    microphone.num_frequency_responses = atoi(attr[curIdx++]);
-    if (microphone.num_frequency_responses > AUDIO_MICROPHONE_MAX_FREQUENCY_RESPONSES) {
-        ALOGE("%s: num_frequency_responses is too large", __func__);
-        goto done;
-    }
-    if (microphone.num_frequency_responses > 0) {
-        if (strcmp(attr[curIdx++], "frequencies")) {
-            ALOGE("%s: frequencies not found", __func__);
-            goto done;
-        }
-        char *token = strtok((char *)attr[curIdx++], " ");
-        uint32_t num_frequencies = 0;
-        while (token) {
-            microphone.frequency_responses[0][num_frequencies++] = atof(token);
-            if (num_frequencies > AUDIO_MICROPHONE_MAX_FREQUENCY_RESPONSES) {
-                ALOGE("%s: num %u of frequency is too large", __func__, num_frequencies);
+    while (attr[index] != NULL) {
+        const char *attribute = attr[index++];
+        char value[strlen(attr[index]) + 1];
+        strcpy(value, attr[index++]);
+        if (strcmp(attribute, "device_id") == 0) {
+            if (strlen(value) > AUDIO_MICROPHONE_ID_MAX_LEN) {
+                ALOGE("%s: device_id %s is too long", __func__, value);
                 goto done;
             }
-            token = strtok(NULL, " ");
-        }
-
-        if (strcmp(attr[curIdx++], "responses")) {
-            ALOGE("%s: responses not found", __func__);
-            goto done;
-        }
-        token = strtok((char *)attr[curIdx++], " ");
-        uint32_t num_responses = 0;
-        while (token) {
-            microphone.frequency_responses[1][num_responses++] = atof(token);
-            if (num_responses > AUDIO_MICROPHONE_MAX_FREQUENCY_RESPONSES) {
-                ALOGE("%s: num %u of response is too large", __func__, num_responses);
+            strcpy(microphone.device_id, value);
+            found_mandatory_characteristics |= 1;
+        } else if (strcmp(attribute, "type") == 0) {
+            if (!find_enum_by_string(device_in_types, value,
+                    ARRAY_SIZE(device_in_types), &microphone.device)) {
+                ALOGE("%s: type %s in %s not found!",
+                        __func__, value, PLATFORM_INFO_XML_PATH);
                 goto done;
             }
-            token = strtok(NULL, " ");
-        }
-
-        if (num_frequencies != num_responses
-                || num_frequencies != microphone.num_frequency_responses) {
-            ALOGE("%s: num of frequency and response not match: %u, %u, %u",
-                  __func__, num_frequencies, num_responses, microphone.num_frequency_responses);
-            goto done;
-        }
-    }
-
-    if (valid_mask & AUDIO_MICROPHONE_CHARACTERISTIC_SENSITIVITY) {
-        if (strcmp(attr[curIdx++], "sensitivity")) {
-            ALOGE("%s: sensitivity not found", __func__);
-            goto done;
-        }
-        microphone.sensitivity = atof(attr[curIdx++]);
-    } else {
-        microphone.sensitivity = AUDIO_MICROPHONE_SENSITIVITY_UNKNOWN;
-    }
-
-    if (valid_mask & AUDIO_MICROPHONE_CHARACTERISTIC_MAX_SPL) {
-        if (strcmp(attr[curIdx++], "max_spl")) {
-            ALOGE("%s: max_spl not found", __func__);
-            goto done;
-        }
-        microphone.max_spl = atof(attr[curIdx++]);
-    } else {
-        microphone.max_spl = AUDIO_MICROPHONE_SPL_UNKNOWN;
-    }
-
-    if (valid_mask & AUDIO_MICROPHONE_CHARACTERISTIC_MIN_SPL) {
-        if (strcmp(attr[curIdx++], "min_spl")) {
-            ALOGE("%s: min_spl not found", __func__);
-            goto done;
-        }
-        microphone.min_spl = atof(attr[curIdx++]);
-    } else {
-        microphone.min_spl = AUDIO_MICROPHONE_SPL_UNKNOWN;
-    }
-
-    if (valid_mask & AUDIO_MICROPHONE_CHARACTERISTIC_ORIENTATION) {
-        if (strcmp(attr[curIdx++], "orientation")) {
-            ALOGE("%s: orientation not found", __func__);
-            goto done;
-        }
-        char *token = strtok((char *)attr[curIdx++], " ");
-        float orientation[3];
-        uint32_t idx = 0;
-        while (token) {
-            orientation[idx++] = atof(token);
-            if (idx > 3) {
+            found_mandatory_characteristics |= (1 << 1);
+        } else if (strcmp(attribute, "address") == 0) {
+            if (strlen(value) > AUDIO_DEVICE_MAX_ADDRESS_LEN) {
+                ALOGE("%s, address %s is too long", __func__, value);
+                goto done;
+            }
+            strcpy(microphone.address, value);
+            if (strlen(microphone.address) == 0) {
+                // If the address is empty, populate the address according to device type.
+                if (microphone.device == AUDIO_DEVICE_IN_BUILTIN_MIC) {
+                    strcpy(microphone.address, AUDIO_BOTTOM_MICROPHONE_ADDRESS);
+                } else if (microphone.device == AUDIO_DEVICE_IN_BACK_MIC) {
+                    strcpy(microphone.address, AUDIO_BACK_MICROPHONE_ADDRESS);
+                }
+            }
+            found_mandatory_characteristics |= (1 << 2);
+        } else if (strcmp(attribute, "location") == 0) {
+            if (!find_enum_by_string(mic_locations, value,
+                    AUDIO_MICROPHONE_LOCATION_CNT, &microphone.location)) {
+                ALOGE("%s: location %s in %s not found!",
+                        __func__, value, PLATFORM_INFO_XML_PATH);
+                goto done;
+            }
+            found_mandatory_characteristics |= (1 << 3);
+        } else if (strcmp(attribute, "group") == 0) {
+            microphone.group = atoi(value);
+            found_mandatory_characteristics |= (1 << 4);
+        } else if (strcmp(attribute, "index_in_the_group") == 0) {
+            microphone.index_in_the_group = atoi(value);
+            found_mandatory_characteristics |= (1 << 5);
+        } else if (strcmp(attribute, "directionality") == 0) {
+            if (!find_enum_by_string(mic_directionalities, value,
+                    AUDIO_MICROPHONE_DIRECTIONALITY_CNT, &microphone.directionality)) {
+                ALOGE("%s: directionality %s in %s not found!",
+                      __func__, attr[index], PLATFORM_INFO_XML_PATH);
+                goto done;
+            }
+            found_mandatory_characteristics |= (1 << 6);
+        } else if (strcmp(attribute, "num_frequency_responses") == 0) {
+            microphone.num_frequency_responses = atoi(value);
+            if (microphone.num_frequency_responses > AUDIO_MICROPHONE_MAX_FREQUENCY_RESPONSES) {
+                ALOGE("%s: num_frequency_responses is too large", __func__);
+                goto done;
+            }
+            found_mandatory_characteristics |= (1 << 7);
+        } else if (strcmp(attribute, "frequencies") == 0) {
+            char *token = strtok(value, " ");
+            while (token) {
+                microphone.frequency_responses[0][num_frequencies++] = atof(token);
+                if (num_frequencies > AUDIO_MICROPHONE_MAX_FREQUENCY_RESPONSES) {
+                    ALOGE("%s: num %u of frequency is too large", __func__, num_frequencies);
+                    goto done;
+                }
+                token = strtok(NULL, " ");
+            }
+            found_mandatory_characteristics |= (1 << 8);
+        } else if (strcmp(attribute, "responses") == 0) {
+            char *token = strtok(value, " ");
+            while (token) {
+                microphone.frequency_responses[1][num_responses++] = atof(token);
+                if (num_responses > AUDIO_MICROPHONE_MAX_FREQUENCY_RESPONSES) {
+                    ALOGE("%s: num %u of response is too large", __func__, num_responses);
+                    goto done;
+                }
+                token = strtok(NULL, " ");
+            }
+            found_mandatory_characteristics |= (1 << 9);
+        } else if (strcmp(attribute, "sensitivity") == 0) {
+            microphone.sensitivity = atof(value);
+        } else if (strcmp(attribute, "max_spl") == 0) {
+            microphone.max_spl = atof(value);
+        } else if (strcmp(attribute, "min_spl") == 0) {
+            microphone.min_spl = atof(value);
+        } else if (strcmp(attribute, "orientation") == 0) {
+            char *token = strtok(value, " ");
+            float orientation[3];
+            uint32_t idx = 0;
+            while (token) {
+                orientation[idx++] = atof(token);
+                if (idx > 3) {
+                    ALOGE("%s: orientation invalid", __func__);
+                    goto done;
+                }
+                token = strtok(NULL, " ");
+            }
+            if (idx != 3) {
                 ALOGE("%s: orientation invalid", __func__);
                 goto done;
             }
-            token = strtok(NULL, " ");
-        }
-        if (idx != 3) {
-            ALOGE("%s: orientation invalid", __func__);
-            goto done;
-        }
-        microphone.orientation.x = orientation[0];
-        microphone.orientation.y = orientation[1];
-        microphone.orientation.z = orientation[2];
-    } else {
-        microphone.orientation.x = 0.0f;
-        microphone.orientation.y = 0.0f;
-        microphone.orientation.z = 0.0f;
-    }
-
-    if (valid_mask & AUDIO_MICROPHONE_CHARACTERISTIC_GEOMETRIC_LOCATION) {
-        if (strcmp(attr[curIdx++], "geometric_location")) {
-            ALOGE("%s: geometric_location not found", __func__);
-            goto done;
-        }
-        char *token = strtok((char *)attr[curIdx++], " ");
-        float geometric_location[3];
-        uint32_t idx = 0;
-        while (token) {
-            geometric_location[idx++] = atof(token);
-            if (idx > 3) {
+            microphone.orientation.x = orientation[0];
+            microphone.orientation.y = orientation[1];
+            microphone.orientation.z = orientation[2];
+        } else if (strcmp(attribute, "geometric_location") == 0) {
+            char *token = strtok(value, " ");
+            float geometric_location[3];
+            uint32_t idx = 0;
+            while (token) {
+                geometric_location[idx++] = atof(token);
+                if (idx > 3) {
+                    ALOGE("%s: geometric_location invalid", __func__);
+                    goto done;
+                }
+                token = strtok(NULL, " ");
+            }
+            if (idx != 3) {
                 ALOGE("%s: geometric_location invalid", __func__);
                 goto done;
             }
-            token = strtok(NULL, " ");
+            microphone.geometric_location.x = geometric_location[0];
+            microphone.geometric_location.y = geometric_location[1];
+            microphone.geometric_location.z = geometric_location[2];
+        } else {
+            ALOGW("%s: unknown attribute of microphone characteristics: %s",
+                    __func__, attribute);
         }
-        if (idx != 3) {
-            ALOGE("%s: geometric_location invalid", __func__);
-            goto done;
-        }
-        microphone.geometric_location.x = geometric_location[0];
-        microphone.geometric_location.y = geometric_location[1];
-        microphone.geometric_location.z = geometric_location[2];
-    } else {
-        microphone.geometric_location.x = AUDIO_MICROPHONE_COORDINATE_UNKNOWN;
-        microphone.geometric_location.y = AUDIO_MICROPHONE_COORDINATE_UNKNOWN;
-        microphone.geometric_location.z = AUDIO_MICROPHONE_COORDINATE_UNKNOWN;
+    }
+
+    if (num_frequencies != num_responses
+            || num_frequencies != microphone.num_frequency_responses) {
+        ALOGE("%s: num of frequency and response not match: %u, %u, %u",
+              __func__, num_frequencies, num_responses, microphone.num_frequency_responses);
+        goto done;
+    }
+
+    if (found_mandatory_characteristics != MANDATORY_MICROPHONE_CHARACTERISTICS) {
+        ALOGE("%s: some of mandatory microphone characteriscts are missed: %u",
+                __func__, found_mandatory_characteristics);
     }
 
     platform_set_microphone_characteristic(my_data.platform, microphone);
@@ -773,6 +801,8 @@
     if (my_data.do_full_parse) {
         if (strcmp(tag_name, "acdb_ids") == 0) {
             section = ACDB;
+        } else if (strncmp(tag_name, "module_ids", strlen("module_ids")) == 0) {
+            section = MODULE;
         } else if (strcmp(tag_name, "pcm_ids") == 0) {
             section = PCM_ID;
         } else if (strcmp(tag_name, "backend_names") == 0) {
@@ -792,8 +822,9 @@
         } 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 != OPERATOR_SPECIFIC)) {
-                ALOGE("device tag only supported for acdb/backend names");
+            if ((section != ACDB) && (section != AEC) && (section != NS) &&
+                (section != BACKEND_NAME) && (section != OPERATOR_SPECIFIC)) {
+                ALOGE("device tag only supported for acdb/backend/aec/ns/operator_specific names");
                 return;
             }
 
@@ -870,6 +901,20 @@
             section_process_fn fn = section_table[MIC_INFO];
             fn(attr);
         }
+        else if (strncmp(tag_name, "aec", strlen("aec")) == 0) {
+            if (section != MODULE) {
+                ALOGE("aec tag only supported with MODULE section");
+                return;
+            }
+            section = AEC;
+        }
+        else if (strncmp(tag_name, "ns", strlen("ns")) == 0) {
+            if (section != MODULE) {
+                ALOGE("ns tag only supported with MODULE section");
+                return;
+            }
+            section = NS;
+        }
     } else {
         if(strcmp(tag_name, "config_params") == 0) {
             section = CONFIG_PARAMS;
@@ -891,6 +936,12 @@
 {
     if (strcmp(tag_name, "acdb_ids") == 0) {
         section = ROOT;
+    } else if (strncmp(tag_name, "module_ids", strlen("module_ids")) == 0) {
+        section = ROOT;
+    } else if (strncmp(tag_name, "aec", strlen("aec")) == 0) {
+        section = MODULE;
+    } else if (strncmp(tag_name, "ns", strlen("ns")) == 0) {
+        section = MODULE;
     } else if (strcmp(tag_name, "pcm_ids") == 0) {
         section = ROOT;
     } else if (strcmp(tag_name, "backend_names") == 0) {
@@ -916,14 +967,8 @@
     }
 }
 
-int snd_card_info_init(const char *filename, void *platform, set_parameters_fn fn)
-{
-    set_parameters = fn;
-    my_data.do_full_parse = false;
-    return platform_info_init(filename, platform);
-}
-
-int platform_info_init(const char *filename, void *platform)
+int platform_info_init(const char *filename, void *platform,
+                       bool do_full_parse, set_parameters_fn fn)
 {
     XML_Parser      parser;
     FILE            *file;
@@ -932,7 +977,6 @@
     void            *buf;
     static const uint32_t kBufSize = 1024;
     char   platform_info_file_name[MIXER_PATH_MAX_LENGTH]= {0};
-    section = ROOT;
 
     if (filename == NULL) {
         strlcpy(platform_info_file_name, PLATFORM_INFO_XML_PATH, MIXER_PATH_MAX_LENGTH);
@@ -958,8 +1002,12 @@
         goto err_close_file;
     }
 
+    pthread_mutex_lock(&my_data.lock);
+    section = ROOT;
+    my_data.do_full_parse = do_full_parse;
     my_data.platform = platform;
     my_data.kvpairs = str_parms_create();
+    my_data.set_parameters = fn;
 
     XML_SetElementHandler(parser, start_tag, end_tag);
 
@@ -990,10 +1038,12 @@
             break;
     }
 
-    set_parameters = &platform_set_parameters;
-    my_data.do_full_parse = true;
-
 err_free_parser:
+    if (my_data.kvpairs != NULL) {
+        str_parms_destroy(my_data.kvpairs);
+        my_data.kvpairs = NULL;
+    }
+    pthread_mutex_unlock(&my_data.lock);
     XML_ParserFree(parser);
 err_close_file:
     fclose(file);
diff --git a/hal/voice.c b/hal/voice.c
index 09cb926..708ce6c 100644
--- a/hal/voice.c
+++ b/hal/voice.c
@@ -171,6 +171,7 @@
     uc_info->devices = adev->current_call_output ->devices;
     uc_info->in_snd_device = SND_DEVICE_NONE;
     uc_info->out_snd_device = SND_DEVICE_NONE;
+    adev->use_voice_device_mute = false;
 
     list_add_tail(&adev->usecase_list, &uc_info->list);
 
@@ -357,11 +358,19 @@
 int voice_set_mic_mute(struct audio_device *adev, bool state)
 {
     int err = 0;
+    struct audio_usecase *usecase = NULL;
 
     adev->voice.mic_mute = state;
     if (adev->mode == AUDIO_MODE_IN_CALL ||
-        adev->mode == AUDIO_MODE_IN_COMMUNICATION)
-        err = platform_set_mic_mute(adev->platform, state);
+        adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
+        /* Use device mute if incall music delivery usecase is in progress */
+        if (adev->use_voice_device_mute)
+            err = platform_set_device_mute(adev->platform, state, "tx");
+        else
+            err = platform_set_mic_mute(adev->platform, state);
+        ALOGV("%s: voice mute status=%d, use_voice_device_mute_flag=%d",
+            __func__, state, adev->use_voice_device_mute);
+    }
 
     return err;
 }
@@ -371,6 +380,25 @@
     return adev->voice.mic_mute;
 }
 
+// Following function is called when incall music uplink usecase is
+// created or destroyed while mic is muted. If incall music uplink
+// usecase is active, apply voice device mute to mute only voice Tx
+// path and not the mixed voice Tx + inncall-music path. Revert to
+// voice stream mute once incall music uplink usecase is inactive
+void voice_set_device_mute_flag (struct audio_device *adev, bool state)
+{
+    if (adev->voice.mic_mute) {
+        if (state) {
+            platform_set_device_mute(adev->platform, true, "tx");
+            platform_set_mic_mute(adev->platform, false);
+        } else {
+            platform_set_mic_mute(adev->platform, true);
+            platform_set_device_mute(adev->platform, false, "tx");
+        }
+    }
+    adev->use_voice_device_mute = state;
+}
+
 int voice_set_volume(struct audio_device *adev, float volume)
 {
     int vol, err = 0;
@@ -517,6 +545,8 @@
     adev->voice.volume = 1.0f;
     adev->voice.mic_mute = false;
     adev->voice.in_call = false;
+    adev->use_voice_device_mute = 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 469a3b5..71e096b 100644
--- a/hal/voice.h
+++ b/hal/voice.h
@@ -95,4 +95,6 @@
                        snd_device_t out_snd_device,
                        bool enable);
 bool voice_is_call_state_active(struct audio_device *adev);
+void voice_set_device_mute_flag (struct audio_device *adev, bool state);
+
 #endif //VOICE_H