Merge "configs:  enable 3D Audio on msmnile/sdm710"
diff --git a/configs/apq8098_latv/apq8098_latv.mk b/configs/apq8098_latv/apq8098_latv.mk
index 088f3ed..582cd5c 100644
--- a/configs/apq8098_latv/apq8098_latv.mk
+++ b/configs/apq8098_latv/apq8098_latv.mk
@@ -253,10 +253,6 @@
 PRODUCT_PROPERTY_OVERRIDES += \
 vendor.audio.hw.aac.encoder=true
 
-#Disable FM a2dp concurrency
-PRODUCT_PROPERTY_OVERRIDES += \
-vendor.fm.a2dp.conc.disabled=true
-
 #audio becoming noisy intent broadcast delay
 PRODUCT_PROPERTY_OVERRIDES += \
 vendor.audio.noisy.broadcast.delay=600
diff --git a/configs/msm8998/msm8998.mk b/configs/msm8998/msm8998.mk
index d91fa57..368a7ec 100644
--- a/configs/msm8998/msm8998.mk
+++ b/configs/msm8998/msm8998.mk
@@ -212,10 +212,6 @@
 PRODUCT_PROPERTY_OVERRIDES += \
 vendor.audio.hw.aac.encoder=true
 
-#Disable FM a2dp concurrency
-PRODUCT_PROPERTY_OVERRIDES += \
-vendor.fm.a2dp.conc.disabled=true
-
 #audio becoming noisy intent broadcast delay
 PRODUCT_PROPERTY_OVERRIDES += \
 vendor.audio.noisy.broadcast.delay=600
diff --git a/configs/msmnile/mixer_paths_tavil.xml b/configs/msmnile/mixer_paths_tavil.xml
old mode 100755
new mode 100644
index 2e0f9c5..dc4f0b4
--- a/configs/msmnile/mixer_paths_tavil.xml
+++ b/configs/msmnile/mixer_paths_tavil.xml
@@ -1937,6 +1937,14 @@
         <ctl name="SLIM0_RX_VI_FB_RCH_MUX" value="SLIM4_TX" />
     </path>
 
+    <path name="speaker-protected-qrd">
+        <ctl name="AIF4_VI Mixer SPKR_VI_2" value="1" />
+        <ctl name="SLIM_4_TX Format" value="PACKED_16B" />
+        <path name="speaker-qrd" />
+        <ctl name="VI_FEED_TX Channels" value="One" />
+        <ctl name="SLIM0_RX_VI_FB_LCH_MUX" value="SLIM4_TX" />
+    </path>
+
     <path name="voice-speaker-protected">
         <ctl name="AIF4_VI Mixer SPKR_VI_1" value="1" />
         <ctl name="SLIM_4_TX Format" value="PACKED_16B" />
@@ -1945,6 +1953,10 @@
         <ctl name="SLIM0_RX_VI_FB_LCH_MUX" value="SLIM4_TX" />
     </path>
 
+    <path name="voice-speaker-protected-qrd">
+        <path name="speaker-protected-qrd" />
+    </path>
+
     <path name="voice-speaker-stereo-protected">
         <path name="speaker-protected" />
     </path>
diff --git a/configs/msmnile/msmnile.mk b/configs/msmnile/msmnile.mk
index aaa18f7..14a8128 100644
--- a/configs/msmnile/msmnile.mk
+++ b/configs/msmnile/msmnile.mk
@@ -67,6 +67,7 @@
 AUDIO_FEATURE_ENABLED_DLKM := true
 AUDIO_FEATURE_ENABLED_USB_BURST_MODE := true
 AUDIO_FEATURE_ENABLED_SVA_MULTI_STAGE := true
+AUDIO_FEATURE_ENABLED_BATTERY_LISTENER := true
 ##AUDIO_FEATURE_FLAGS
 
 ifneq ($(strip $(TARGET_USES_QSSI)), true)
@@ -200,10 +201,6 @@
 PRODUCT_PROPERTY_OVERRIDES += \
 vendor.audio.hw.aac.encoder=true
 
-#Disable FM a2dp concurrency
-PRODUCT_PROPERTY_OVERRIDES += \
-vendor.fm.a2dp.conc.disabled=true
-
 #audio becoming noisy intent broadcast delay
 PRODUCT_PROPERTY_OVERRIDES += \
 vendor.audio.noisy.broadcast.delay=600
diff --git a/configs/msmnile/sound_trigger_mixer_paths_wcd9340.xml b/configs/msmnile/sound_trigger_mixer_paths_wcd9340.xml
index 55dd42f..1e3d4e7 100644
--- a/configs/msmnile/sound_trigger_mixer_paths_wcd9340.xml
+++ b/configs/msmnile/sound_trigger_mixer_paths_wcd9340.xml
@@ -348,4 +348,11 @@
         <ctl name="EC Reference SampleRate" value="48000"/>
     </path>
 
+    <path name="echo-reference a2dp">
+        <ctl name="AUDIO_REF_EC_UL1 MUX" value="SLIM_7_RX"/>
+        <ctl name="EC Reference Channels" value="Two"/>
+        <ctl name="EC Reference Bit Format" value="S16_LE"/>
+        <ctl name="EC Reference SampleRate" value="48000"/>
+    </path>
+
 </mixer>
diff --git a/configs/msmnile/sound_trigger_platform_info.xml b/configs/msmnile/sound_trigger_platform_info.xml
index 27a6c04..34c3401 100644
--- a/configs/msmnile/sound_trigger_platform_info.xml
+++ b/configs/msmnile/sound_trigger_platform_info.xml
@@ -42,6 +42,7 @@
         <param support_device_switch="false" />
         <!-- Transition will only occur if execution_type="DYNAMIC" -->
         <param transit_to_adsp_on_playback="false" />
+        <param transit_to_adsp_on_battery_charging="false" />
         <!-- Below backend params must match with port used in mixer path file -->
         <!-- param used to configure backend sample rate, format and channels -->
         <param backend_port_name="SLIM_0_TX" />
diff --git a/configs/msmnile_au/msmnile_au.mk b/configs/msmnile_au/msmnile_au.mk
index 111cbd2..933ba80 100644
--- a/configs/msmnile_au/msmnile_au.mk
+++ b/configs/msmnile_au/msmnile_au.mk
@@ -194,10 +194,6 @@
 PRODUCT_PROPERTY_OVERRIDES += \
 vendor.audio.hw.aac.encoder=true
 
-#Disable FM a2dp concurrency
-PRODUCT_PROPERTY_OVERRIDES += \
-vendor.fm.a2dp.conc.disabled=true
-
 #audio becoming noisy intent broadcast delay
 PRODUCT_PROPERTY_OVERRIDES += \
 vendor.audio.noisy.broadcast.delay=600
diff --git a/configs/msmsteppe/msmsteppe.mk b/configs/msmsteppe/msmsteppe.mk
index 4fa0eb7..4c482b9 100644
--- a/configs/msmsteppe/msmsteppe.mk
+++ b/configs/msmsteppe/msmsteppe.mk
@@ -191,10 +191,6 @@
 PRODUCT_PROPERTY_OVERRIDES += \
 vendor.audio.hw.aac.encoder=true
 
-#Disable FM a2dp concurrency
-PRODUCT_PROPERTY_OVERRIDES += \
-vendor.fm.a2dp.conc.disabled=true
-
 #audio becoming noisy intent broadcast delay
 PRODUCT_PROPERTY_OVERRIDES += \
 vendor.audio.noisy.broadcast.delay=600
diff --git a/configs/sdm660/sdm660.mk b/configs/sdm660/sdm660.mk
index 555340a..e961a0e 100644
--- a/configs/sdm660/sdm660.mk
+++ b/configs/sdm660/sdm660.mk
@@ -220,10 +220,6 @@
 PRODUCT_PROPERTY_OVERRIDES += \
 vendor.audio.hw.aac.encoder=true
 
-#Disable FM a2dp concurrency
-PRODUCT_PROPERTY_OVERRIDES += \
-vendor.fm.a2dp.conc.disabled=true
-
 #audio becoming noisy intent broadcast delay
 PRODUCT_PROPERTY_OVERRIDES += \
 vendor.audio.noisy.broadcast.delay=600
diff --git a/configs/sdm710/sdm710.mk b/configs/sdm710/sdm710.mk
index 4116232..dc21eb4 100644
--- a/configs/sdm710/sdm710.mk
+++ b/configs/sdm710/sdm710.mk
@@ -69,6 +69,7 @@
 AUDIO_FEATURE_ENABLED_RAS := true
 AUDIO_FEATURE_ENABLED_SND_MONITOR := true
 AUDIO_FEATURE_ENABLED_DLKM := true
+AUDIO_FEATURE_ENABLED_SVA_MULTI_STAGE := true
 ##AUDIO_FEATURE_FLAGS
 
 ifneq ($(strip $(TARGET_USES_QSSI)), true)
@@ -241,10 +242,6 @@
 PRODUCT_PROPERTY_OVERRIDES += \
 vendor.audio.hw.aac.encoder=true
 
-#Disable FM a2dp concurrency
-PRODUCT_PROPERTY_OVERRIDES += \
-vendor.fm.a2dp.conc.disabled=true
-
 #audio becoming noisy intent broadcast delay
 PRODUCT_PROPERTY_OVERRIDES += \
 vendor.audio.noisy.broadcast.delay=600
@@ -266,4 +263,4 @@
     android.hardware.audio@2.0-service \
     android.hardware.audio@2.0-impl \
     android.hardware.audio.effect@2.0-impl \
-    android.hardware.soundtrigger@2.0-impl
+    android.hardware.soundtrigger@2.1-impl
diff --git a/configs/sdm710/sound_trigger_platform_info.xml b/configs/sdm710/sound_trigger_platform_info.xml
index cb39f39..b37753e 100644
--- a/configs/sdm710/sound_trigger_platform_info.xml
+++ b/configs/sdm710/sound_trigger_platform_info.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="ISO-8859-1"?>
-<!--- Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.       -->
+<!--- Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.       -->
 <!---                                                                           -->
 <!--- Redistribution and use in source and binary forms, with or without        -->
 <!--- modification, are permitted provided that the following conditions are    -->
@@ -78,6 +78,23 @@
         <!-- wdsp_fluence_type: fluence disabled: "NONE" -->
         <!-- fluence enabled: "FLUENCE_DMIC", "FLUENCE_TMIC", "FLUENCE_QMIC" -->
         <param wdsp_fluence_type="NONE" />
+        <arm_ss_usecase>
+            <!-- Options are "KEYWORD_DETECTION", "USER_VERIFICATION", "CUSTOM_DETECTION"  -->
+            <param sm_detection_type= "KEYWORD_DETECTION" />
+            <param sm_id="0x2" />
+            <param module_lib="libcapiv2svacnn.so"/>
+            <param sample_rate="16000"/>
+            <param bit_wdith="16"/>
+            <param channel_count="1"/>
+        </arm_ss_usecase>
+        <arm_ss_usecase>
+            <param sm_detection_type= "USER_VERIFICATION" />
+            <param sm_id="0x4" />
+            <param module_lib="libcapiv2vop.so"/>
+            <param sample_rate="16000"/>
+            <param bit_wdith="16"/>
+            <param channel_count="1"/>
+        </arm_ss_usecase>
         <gcs_usecase>
             <param uid="0x1" />
             <!-- module_id, instance_id, param_id -->
diff --git a/configs/sdm845/sdm845.mk b/configs/sdm845/sdm845.mk
index bcfe3af..7650379 100644
--- a/configs/sdm845/sdm845.mk
+++ b/configs/sdm845/sdm845.mk
@@ -207,10 +207,6 @@
 PRODUCT_PROPERTY_OVERRIDES += \
 vendor.audio.hw.aac.encoder=true
 
-#Disable FM a2dp concurrency
-PRODUCT_PROPERTY_OVERRIDES += \
-vendor.fm.a2dp.conc.disabled=true
-
 #audio becoming noisy intent broadcast delay
 PRODUCT_PROPERTY_OVERRIDES += \
 vendor.audio.noisy.broadcast.delay=600
diff --git a/hal/Android.mk b/hal/Android.mk
index fb03343..94c21bd 100644
--- a/hal/Android.mk
+++ b/hal/Android.mk
@@ -405,6 +405,15 @@
     LOCAL_CFLAGS += -DUSB_BURST_MODE_ENABLED
 endif
 
+ifeq ($(strip $(AUDIO_FEATURE_ENABLED_BATTERY_LISTENER)), true)
+    LOCAL_CFLAGS += -DBATTERY_LISTENER_ENABLED
+    LOCAL_SRC_FILES += audio_extn/battery_listener.cpp
+    LOCAL_SHARED_LIBRARIES += android.hardware.health@1.0 android.hardware.health@2.0 \
+                              libhidltransport libbase libhidlbase libhwbinder \
+                              libutils android.hardware.power@1.2
+    LOCAL_STATIC_LIBRARIES := libhealthhalutils
+endif
+
 LOCAL_CFLAGS += -Wall -Werror
 
 LOCAL_COPY_HEADERS_TO   := mm-audio
diff --git a/hal/audio_extn/a2dp.c b/hal/audio_extn/a2dp.c
index d228123..0d0a48b 100644
--- a/hal/audio_extn/a2dp.c
+++ b/hal/audio_extn/a2dp.c
@@ -55,6 +55,7 @@
 #define ENC_MEDIA_FMT_AAC                                  0x00010DA6
 #define ENC_MEDIA_FMT_APTX                                 0x000131ff
 #define ENC_MEDIA_FMT_APTX_HD                              0x00013200
+#define ENC_MEDIA_FMT_APTX_AD                              0x00013204
 #define ENC_MEDIA_FMT_SBC                                  0x00010BF2
 #define ENC_MEDIA_FMT_CELT                                 0x00013221
 #define ENC_MEDIA_FMT_LDAC                                 0x00013224
@@ -112,6 +113,10 @@
 // Instance identifier for A2DP
 #define MAX_INSTANCE_ID                (UINT32_MAX / 2)
 
+#define SAMPLING_RATE_48K               48000
+#define SAMPLING_RATE_441K              44100
+#define CH_STEREO                       2
+#define CH_MONO                         1
 /*
  * Below enum values are extended from audio_base.h to
  * to keep encoder codec type local to bthost_ipc
@@ -129,8 +134,33 @@
 #endif
     ENC_CODEC_TYPE_LDAC = AUDIO_FORMAT_LDAC, // 0x23000000UL
     ENC_CODEC_TYPE_CELT = 603979776u, // 0x24000000UL
+    ENC_CODEC_TYPE_APTX_AD = 620756992u, // 0x25000000UL
 }enc_codec_t;
 
+/*
+ * enums which describes the APTX Adaptive
+ * channel mode, these values are used by encoder
+ */
+ typedef enum {
+    APTX_AD_CHANNEL_UNCHANGED = -1,
+    APTX_AD_CHANNEL_JOINT_STEREO = 0, // default
+    APTX_AD_CHANNEL_MONO = 1,
+    APTX_AD_CHANNEL_DUAL_MONO = 2,
+    APTX_AD_CHANNEL_STEREO_TWS = 4,
+    APTX_AD_CHANNEL_EARBUD = 8,
+} enc_aptx_ad_channel_mode;
+
+/*
+ * enums which describes the APTX Adaptive
+ * sampling frequency, these values are used
+ * by encoder
+ */
+typedef enum {
+    APTX_AD_SR_UNCHANGED = 0x0,
+    APTX_AD_48 = 0x1,  // 48 KHz default
+    APTX_AD_44_1 = 0x2, // 44.1kHz
+} enc_aptx_ad_s_rate;
+
 typedef int (*audio_stream_open_t)(void);
 typedef int (*audio_stream_close_t)(void);
 typedef int (*audio_start_stream_t)(void);
@@ -215,6 +245,7 @@
     bool is_a2dp_offload_supported;
     bool is_handoff_in_progress;
     bool is_aptx_dual_mono_supported;
+    bool is_aptx_adaptive;
     /* Adaptive bitrate config for A2DP codecs */
     struct a2dp_abr_config abr_config;
 };
@@ -373,6 +404,27 @@
     struct aptx_v2_enc_cfg_ext_t aptx_v2_cfg;
 } __attribute__ ((packed));
 
+/* APTX AD structure */
+struct aptx_ad_enc_cfg_ext_t
+{
+    uint32_t  sampling_freq;
+    uint32_t  mtu;
+    uint32_t  channel_mode;
+    uint32_t  min_sink_modeA;
+    uint32_t  max_sink_modeA;
+    uint32_t  min_sink_modeB;
+    uint32_t  max_sink_modeB;
+    uint32_t  min_sink_modeC;
+    uint32_t  max_sink_modeC;
+} __attribute__ ((packed));
+
+struct aptx_ad_enc_cfg_t
+{
+    struct custom_enc_cfg_t  custom_cfg;
+    struct aptx_ad_enc_cfg_ext_t aptx_ad_cfg;
+    struct abr_enc_cfg_t abr_cfg;
+} __attribute__ ((packed));
+
 struct ldac_specific_enc_cfg_t
 {
     uint32_t      bit_rate;
@@ -421,6 +473,22 @@
 } audio_aptx_default_config;
 
 typedef struct {
+    uint8_t  sampling_rate;
+    uint8_t  channel_mode;
+    uint16_t mtu;
+    uint8_t  min_sink_modeA;
+    uint8_t  max_sink_modeA;
+    uint8_t  min_sink_modeB;
+    uint8_t  max_sink_modeB;
+    uint8_t  min_sink_modeC;
+    uint8_t  max_sink_modeC;
+    uint8_t  TTP_modeA_low;
+    uint8_t  TTP_modeA_high;
+    uint8_t  TTP_modeB_low;
+    uint8_t  TTP_modeB_high;
+} audio_aptx_ad_config;
+
+typedef struct {
     uint16_t sampling_rate;
     uint8_t  channels;
     uint32_t bitrate;
@@ -430,6 +498,7 @@
 typedef union {
     audio_aptx_default_config *default_cfg;
     audio_aptx_dual_mono_config *dual_mono_cfg;
+    audio_aptx_ad_config *ad_cfg;
 } audio_aptx_encoder_config;
 
 /* Information about BT AAC encoder configuration
@@ -509,6 +578,9 @@
             ALOGD("%s: ldac offload supported\n",__func__);
             a2dp.is_a2dp_offload_supported = true;
             break;
+        } else if( strcmp(tok, "aptxadaptive") == 0) {
+            ALOGD("%s: aptx adaptive offload supported\n",__func__);
+            a2dp.is_a2dp_offload_supported = true;
         }
         tok = strtok_r(NULL, "-", &saveptr);
     };
@@ -1021,6 +1093,73 @@
 }
 
 #ifndef LINUX_ENABLED
+static int update_aptx_ad_dsp_config(struct aptx_ad_enc_cfg_t *aptx_dsp_cfg,
+                                     audio_aptx_encoder_config *aptx_bt_cfg)
+{
+    int ret = 0;
+
+    if(aptx_dsp_cfg == NULL || aptx_bt_cfg == NULL) {
+        ALOGE("Invalid param, aptx_dsp_cfg %p aptx_bt_cfg %p",
+              aptx_dsp_cfg, aptx_bt_cfg);
+        return -EINVAL;
+    }
+
+    memset(aptx_dsp_cfg, 0x0, sizeof(struct aptx_ad_enc_cfg_t));
+    aptx_dsp_cfg->custom_cfg.enc_format = ENC_MEDIA_FMT_APTX_AD;
+
+
+    aptx_dsp_cfg->aptx_ad_cfg.sampling_freq = aptx_bt_cfg->ad_cfg->sampling_rate;
+    aptx_dsp_cfg->aptx_ad_cfg.mtu = aptx_bt_cfg->ad_cfg->mtu;
+    aptx_dsp_cfg->aptx_ad_cfg.channel_mode = aptx_bt_cfg->ad_cfg->channel_mode;
+    aptx_dsp_cfg->aptx_ad_cfg.min_sink_modeA = aptx_bt_cfg->ad_cfg->min_sink_modeA;
+    aptx_dsp_cfg->aptx_ad_cfg.max_sink_modeA = aptx_bt_cfg->ad_cfg->max_sink_modeA;
+    aptx_dsp_cfg->aptx_ad_cfg.min_sink_modeB = aptx_bt_cfg->ad_cfg->min_sink_modeB;
+    aptx_dsp_cfg->aptx_ad_cfg.max_sink_modeB = aptx_bt_cfg->ad_cfg->max_sink_modeB;
+    aptx_dsp_cfg->aptx_ad_cfg.min_sink_modeC = aptx_bt_cfg->ad_cfg->min_sink_modeC;
+    aptx_dsp_cfg->aptx_ad_cfg.max_sink_modeC = aptx_bt_cfg->ad_cfg->max_sink_modeC;
+    aptx_dsp_cfg->abr_cfg.imc_info.direction = IMC_RECEIVE;
+    aptx_dsp_cfg->abr_cfg.imc_info.enable = IMC_ENABLE;
+    aptx_dsp_cfg->abr_cfg.imc_info.purpose = IMC_PURPOSE_ID_BT_INFO;
+    aptx_dsp_cfg->abr_cfg.imc_info.comm_instance = a2dp.abr_config.imc_instance;
+
+
+    switch(aptx_dsp_cfg->aptx_ad_cfg.channel_mode) {
+        case APTX_AD_CHANNEL_UNCHANGED:
+        case APTX_AD_CHANNEL_JOINT_STEREO:
+        case APTX_AD_CHANNEL_DUAL_MONO:
+        case APTX_AD_CHANNEL_STEREO_TWS:
+        case APTX_AD_CHANNEL_EARBUD:
+        default:
+             a2dp.enc_channels = CH_STEREO;
+             aptx_dsp_cfg->custom_cfg.num_channels = CH_STEREO;
+             aptx_dsp_cfg->custom_cfg.channel_mapping[0] = PCM_CHANNEL_L;
+             aptx_dsp_cfg->custom_cfg.channel_mapping[1] = PCM_CHANNEL_R;
+             break;
+        case APTX_AD_CHANNEL_MONO:
+             a2dp.enc_channels = CH_MONO;
+             aptx_dsp_cfg->custom_cfg.num_channels = CH_MONO;
+             aptx_dsp_cfg->custom_cfg.channel_mapping[0] = PCM_CHANNEL_C;
+            break;
+    }
+    switch(aptx_dsp_cfg->aptx_ad_cfg.sampling_freq) {
+        case APTX_AD_SR_UNCHANGED:
+        case APTX_AD_48:
+        default:
+            a2dp.enc_sampling_rate = SAMPLING_RATE_48K;
+            aptx_dsp_cfg->custom_cfg.sample_rate = SAMPLING_RATE_48K;
+            break;
+        case APTX_AD_44_1:
+            a2dp.enc_sampling_rate = SAMPLING_RATE_441K;
+            aptx_dsp_cfg->custom_cfg.sample_rate = SAMPLING_RATE_441K;
+        break;
+    }
+    ALOGV("Successfully updated APTX AD enc format with \
+               samplingrate: %d channels:%d",
+               aptx_dsp_cfg->custom_cfg.sample_rate,
+               aptx_dsp_cfg->custom_cfg.num_channels);
+
+    return ret;
+}
 static int update_aptx_dsp_config_v2(struct aptx_enc_cfg_t *aptx_dsp_cfg,
                                      audio_aptx_encoder_config *aptx_bt_cfg)
 {
@@ -1118,8 +1257,13 @@
 
 #ifndef LINUX_ENABLED
     struct aptx_enc_cfg_t aptx_dsp_cfg;
-    mixer_size = sizeof(struct aptx_enc_cfg_t);
-    sample_rate_backup = aptx_bt_cfg->default_cfg->sampling_rate;
+    struct aptx_ad_enc_cfg_t aptx_ad_dsp_cfg;
+    if(a2dp.is_aptx_adaptive)
+       mixer_size = sizeof(struct aptx_ad_enc_cfg_t);
+    else {
+        mixer_size = sizeof(struct aptx_enc_cfg_t);
+        sample_rate_backup = aptx_bt_cfg->default_cfg->sampling_rate;
+    }
 #else
     struct custom_enc_cfg_t aptx_dsp_cfg;
     mixer_size = sizeof(struct custom_enc_cfg_t);
@@ -1134,7 +1278,11 @@
     }
 
 #ifndef LINUX_ENABLED
-    ret = update_aptx_dsp_config_v2(&aptx_dsp_cfg, aptx_bt_cfg);
+    if(a2dp.is_aptx_adaptive) {
+        ret = update_aptx_ad_dsp_config(&aptx_ad_dsp_cfg, aptx_bt_cfg);
+        sample_rate_backup = aptx_ad_dsp_cfg.custom_cfg.sample_rate;
+    } else
+        ret = update_aptx_dsp_config_v2(&aptx_dsp_cfg, aptx_bt_cfg);
 #else
     ret = update_aptx_dsp_config_v1(&aptx_dsp_cfg, aptx_bt_cfg);
 #endif
@@ -1143,7 +1291,11 @@
         is_configured = false;
         goto fail;
     }
-    ret = mixer_ctl_set_array(ctl_enc_data, (void *)&aptx_dsp_cfg,
+    if(a2dp.is_aptx_adaptive)
+        ret = mixer_ctl_set_array(ctl_enc_data, (void *)&aptx_ad_dsp_cfg,
+                             mixer_size);
+    else
+        ret = mixer_ctl_set_array(ctl_enc_data, (void *)&aptx_dsp_cfg,
                               mixer_size);
     if (ret != 0) {
         ALOGE("%s: Failed to set APTX encoder config", __func__);
@@ -1157,7 +1309,10 @@
         is_configured = false;
         goto fail;
     } else {
-        ret = mixer_ctl_set_enum_by_string(ctrl_bit_format, "S16_LE");
+        if (a2dp.is_aptx_adaptive)
+            ret = mixer_ctl_set_enum_by_string(ctrl_bit_format, "S24_LE");
+        else
+            ret = mixer_ctl_set_enum_by_string(ctrl_bit_format, "S16_LE");
         if (ret != 0) {
             ALOGE("%s: Failed to set bit format to encoder", __func__);
             is_configured = false;
@@ -1165,7 +1320,10 @@
         }
     }
     is_configured = true;
-    a2dp.bt_encoder_format = ENC_CODEC_TYPE_APTX;
+    if (a2dp.is_aptx_adaptive)
+        a2dp.bt_encoder_format = ENC_CODEC_TYPE_APTX_AD;
+    else
+        a2dp.bt_encoder_format = ENC_CODEC_TYPE_APTX;
 fail:
     /*restore sample rate */
     if(!is_configured)
@@ -1465,6 +1623,7 @@
 
     // ABR disabled by default for all codecs
     a2dp.abr_config.is_abr_enabled = false;
+    a2dp.is_aptx_adaptive = false;
 
     switch(codec_type) {
         case ENC_CODEC_TYPE_SBC:
@@ -1519,6 +1678,18 @@
                 (configure_ldac_enc_format((audio_ldac_encoder_config *)codec_info) &&
                  configure_a2dp_decoder_format(ENC_CODEC_TYPE_LDAC));
             break;
+         case ENC_CODEC_TYPE_APTX_AD:
+             ALOGD(" Received APTX AD encoder supported BT device");
+             if (!instance_id || instance_id > MAX_INSTANCE_ID)
+                 instance_id = MAX_INSTANCE_ID;
+              a2dp.abr_config.imc_instance = instance_id--;
+              a2dp.abr_config.is_abr_enabled = true; // for APTX Adaptive ABR is Always on
+              a2dp.is_aptx_adaptive = true;
+              aptx_encoder_cfg.ad_cfg = (audio_aptx_ad_config *)codec_info;
+              is_configured =
+                (configure_aptx_enc_format(&aptx_encoder_cfg) &&
+                 configure_a2dp_decoder_format(ENC_MEDIA_FMT_APTX_AD));
+            break;
         default:
             ALOGD(" Received Unsupported encoder formar");
             is_configured = false;
@@ -1819,6 +1990,7 @@
   a2dp.is_a2dp_offload_supported = false;
   a2dp.is_handoff_in_progress = false;
   a2dp.is_aptx_dual_mono_supported = false;
+  a2dp.is_aptx_adaptive = false;
   a2dp.abr_config.is_abr_enabled = false;
   a2dp.abr_config.abr_started = false;
   a2dp.abr_config.imc_instance = 0;
diff --git a/hal/audio_extn/audio_extn.h b/hal/audio_extn/audio_extn.h
index e7d2386..7231955 100644
--- a/hal/audio_extn/audio_extn.h
+++ b/hal/audio_extn/audio_extn.h
@@ -41,6 +41,7 @@
 #include <cutils/str_parms.h>
 #include "adsp_hdlr.h"
 #include "ip_hdlr_intf.h"
+#include "battery_listener.h"
 
 #ifndef AFE_PROXY_ENABLED
 #define AUDIO_DEVICE_OUT_PROXY 0x40000
@@ -156,10 +157,13 @@
 #define audio_extn_get_anc_enabled()                     (0)
 #define audio_extn_should_use_fb_anc()                   (0)
 #define audio_extn_should_use_handset_anc(in_channels)   (0)
+#define audio_extn_set_aanc_noise_level(adev, parms)     (0)
 #else
 bool audio_extn_get_anc_enabled(void);
 bool audio_extn_should_use_fb_anc(void);
 bool audio_extn_should_use_handset_anc(int in_channels);
+void audio_extn_set_aanc_noise_level(struct audio_device *adev,
+                                     struct str_parms *parms);
 #endif
 
 #ifndef VBAT_MONITOR_ENABLED
@@ -378,6 +382,7 @@
 #define audio_extn_sound_trigger_deinit(adev)                          (0)
 #define audio_extn_sound_trigger_update_device_status(snd_dev, event)  (0)
 #define audio_extn_sound_trigger_update_stream_status(uc_info, event)  (0)
+#define audio_extn_sound_trigger_update_battery_status(charging)       (0)
 #define audio_extn_sound_trigger_set_parameters(adev, parms)           (0)
 #define audio_extn_sound_trigger_get_parameters(adev, query, reply)    (0)
 #define audio_extn_sound_trigger_check_and_get_session(in)             (0)
@@ -399,6 +404,7 @@
                                      st_event_type_t event);
 void audio_extn_sound_trigger_update_stream_status(struct audio_usecase *uc_info,
                                      st_event_type_t event);
+void audio_extn_sound_trigger_update_battery_status(bool charging);
 void audio_extn_sound_trigger_set_parameters(struct audio_device *adev,
                                              struct str_parms *parms);
 void audio_extn_sound_trigger_check_and_get_session(struct stream_in *in);
diff --git a/hal/audio_extn/battery_listener.cpp b/hal/audio_extn/battery_listener.cpp
new file mode 100644
index 0000000..582e9e6
--- /dev/null
+++ b/hal/audio_extn/battery_listener.cpp
@@ -0,0 +1,247 @@
+/*
+* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+*     * Redistributions of source code must retain the above copyright
+*       notice, this list of conditions and the following disclaimer.
+*     * Redistributions in binary form must reproduce the above
+*       copyright notice, this list of conditions and the following
+*       disclaimer in the documentation and/or other materials provided
+*       with the distribution.
+*     * Neither the name of The Linux Foundation nor the names of its
+*       contributors may be used to endorse or promote products derived
+*       from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+#define LOG_TAG "audio_hw::BatteryListener"
+#include <log/log.h>
+#include <android/hidl/manager/1.0/IServiceManager.h>
+#include <android/hardware/health/2.0/IHealth.h>
+#include <healthhalutils/HealthHalUtils.h>
+#include <hidl/HidlTransportSupport.h>
+#include <thread>
+#include "battery_listener.h"
+
+using android::hardware::interfacesEqual;
+using android::hardware::Return;
+using android::hardware::Void;
+using android::hardware::health::V1_0::BatteryStatus;
+using android::hardware::health::V1_0::toString;
+using android::hardware::health::V2_0::get_health_service;
+using android::hardware::health::V2_0::HealthInfo;
+using android::hardware::health::V2_0::IHealth;
+using android::hardware::health::V2_0::Result;
+using android::hidl::manager::V1_0::IServiceManager;
+using namespace std::literals::chrono_literals;
+
+namespace android {
+
+#define GET_HEALTH_SVC_RETRY_CNT 5
+#define GET_HEALTH_SVC_WAIT_TIME_MS 500
+
+struct BatteryListenerImpl : public hardware::health::V2_0::IHealthInfoCallback,
+                             public hardware::hidl_death_recipient {
+    typedef std::function<void(bool)> cb_fn_t;
+    BatteryListenerImpl(cb_fn_t cb);
+    virtual ~BatteryListenerImpl ();
+    virtual hardware::Return<void> healthInfoChanged(
+        const hardware::health::V2_0::HealthInfo& info);
+    virtual void serviceDied(uint64_t cookie,
+                             const wp<hidl::base::V1_0::IBase>& who);
+    bool isCharging() {
+        std::lock_guard<std::mutex> _l(mLock);
+        return statusToBool(mStatus);
+    }
+  private:
+    sp<hardware::health::V2_0::IHealth> mHealth;
+    status_t init();
+    BatteryStatus mStatus;
+    cb_fn_t mCb;
+    std::mutex mLock;
+    std::condition_variable mCond;
+    std::unique_ptr<std::thread> mThread;
+    bool mDone;
+    bool statusToBool(const BatteryStatus &s) const {
+        return (s == BatteryStatus::CHARGING) ||
+               (s ==  BatteryStatus::FULL);
+    }
+};
+
+status_t BatteryListenerImpl::init()
+{
+    int tries = 0;
+
+    if (mHealth != NULL)
+        return INVALID_OPERATION;
+
+    do {
+        mHealth = get_health_service();
+        if (mHealth != NULL)
+            break;
+        usleep(GET_HEALTH_SVC_WAIT_TIME_MS * 1000);
+        tries++;
+    } while(tries < GET_HEALTH_SVC_RETRY_CNT);
+
+    if (mHealth == NULL) {
+        ALOGE("no health service found, retries %d", tries);
+        return NO_INIT;
+    } else {
+        ALOGI("Get health service in %d tries", tries);
+    }
+    mStatus = BatteryStatus::UNKNOWN;
+    auto ret = mHealth->getChargeStatus([&](Result r, BatteryStatus status) {
+        if (r != Result::SUCCESS) {
+            ALOGE("batterylistener: cannot get battery status");
+            return;
+        }
+        mStatus = status;
+    });
+    if (!ret.isOk())
+        ALOGE("batterylistener: get charge status transaction error");
+
+    if (mStatus == BatteryStatus::UNKNOWN)
+        ALOGW("batterylistener: init: invalid battery status");
+    mDone = false;
+    mThread = std::make_unique<std::thread>([this]() {
+            std::unique_lock<std::mutex> l(mLock);
+            BatteryStatus local_status = mStatus;
+            while (!mDone) {
+                if (local_status == mStatus) {
+                    mCond.wait(l);
+                    continue;
+                }
+                local_status = mStatus;
+                switch (local_status) {
+                    // NOT_CHARGING is a special event that indicates, a battery is connected,
+                    // but not charging. This is seen for approx a second
+                    // after charger is plugged in. A charging event is eventually received.
+                    // We must try to avoid an unnecessary cb to HAL
+                    // only to call it again shortly.
+                    // An option to deal with this transient event would be to ignore this.
+                    // Or process this event with a slight delay (i.e cancel this event
+                    // if a different event comes in within a timeout
+                    case BatteryStatus::NOT_CHARGING : {
+                        auto mStatusnot_ncharging =
+                                [this, local_status]() { return mStatus != local_status; };
+                        mCond.wait_for(l, 3s, mStatusnot_ncharging);
+                        if (mStatusnot_ncharging()) // i.e event changed
+                            break;
+                    }
+                    default:
+                        bool c = statusToBool(local_status);
+                        ALOGI("healthInfo cb thread: cb %s", c ? "CHARGING" : "NOT CHARGING");
+                        l.unlock();
+                        mCb(c);
+                        l.lock();
+                        break;
+                }
+            }
+        });
+    mHealth->registerCallback(this);
+    mHealth->linkToDeath(this, 0 /* cookie */);
+    return NO_ERROR;
+}
+
+BatteryListenerImpl::BatteryListenerImpl(cb_fn_t cb) :
+        mCb(cb)
+{
+    init();
+}
+
+BatteryListenerImpl::~BatteryListenerImpl()
+{
+    {
+        std::lock_guard<std::mutex> _l(mLock);
+        if (mHealth != NULL)
+            mHealth->unlinkToDeath(this);
+    }
+    mDone = true;
+    mThread->join();
+}
+
+void BatteryListenerImpl::serviceDied(uint64_t cookie __unused,
+                                     const wp<hidl::base::V1_0::IBase>& who)
+{
+    {
+        std::lock_guard<std::mutex> _l(mLock);
+        if (mHealth == NULL || !interfacesEqual(mHealth, who.promote())) {
+            ALOGE("health not initialized or unknown interface died");
+            return;
+        }
+        ALOGI("health service died, reinit");
+        mDone = true;
+    }
+    mThread->join();
+    std::lock_guard<std::mutex> _l(mLock);
+    init();
+}
+
+// this callback seems to be a SYNC callback and so
+// waits for return before next event is issued.
+// therefore we need not have a queue to process
+// NOT_CHARGING and CHARGING concurrencies.
+// Replace single var by a list if this assumption is broken
+Return<void> BatteryListenerImpl::healthInfoChanged(
+        const hardware::health::V2_0::HealthInfo& info)
+{
+    ALOGV("healthInfoChanged: %d", info.legacy.batteryStatus);
+    std::unique_lock<std::mutex> l(mLock);
+    if (info.legacy.batteryStatus != mStatus) {
+        mStatus = info.legacy.batteryStatus;
+        mCond.notify_one();
+    }
+    return Void();
+}
+
+static sp<BatteryListenerImpl> batteryListener;
+status_t batteryPropertiesListenerInit(BatteryListenerImpl::cb_fn_t cb)
+{
+    batteryListener = new BatteryListenerImpl(cb);
+    return NO_ERROR;
+}
+
+status_t batteryPropertiesListenerDeinit()
+{
+    batteryListener.clear();
+    return OK;
+}
+
+bool batteryPropertiesListenerIsCharging()
+{
+    return batteryListener->isCharging();
+}
+
+} // namespace android
+
+extern "C" {
+void audio_extn_battery_properties_listener_init(battery_status_change_fn_t fn)
+{
+    android::batteryPropertiesListenerInit([=](bool charging) {
+                                               fn(charging);
+                                          });
+}
+
+void audio_extn_battery_properties_listener_deinit()
+{
+    android::batteryPropertiesListenerDeinit();
+}
+
+bool audio_extn_battery_properties_is_charging()
+{
+    return android::batteryPropertiesListenerIsCharging();
+}
+
+} // extern C
diff --git a/hal/audio_extn/battery_listener.h b/hal/audio_extn/battery_listener.h
new file mode 100644
index 0000000..2fcd010
--- /dev/null
+++ b/hal/audio_extn/battery_listener.h
@@ -0,0 +1,44 @@
+/*
+* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+*     * Redistributions of source code must retain the above copyright
+*       notice, this list of conditions and the following disclaimer.
+*     * Redistributions in binary form must reproduce the above
+*       copyright notice, this list of conditions and the following
+*       disclaimer in the documentation and/or other materials provided
+*       with the distribution.
+*     * Neither the name of The Linux Foundation nor the names of its
+*       contributors may be used to endorse or promote products derived
+*       from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifdef BATTERY_LISTENER_ENABLED
+#ifdef __cplusplus
+extern "C" {
+#endif
+typedef void (* battery_status_change_fn_t)(bool);
+void audio_extn_battery_properties_listener_init(battery_status_change_fn_t fn);
+void audio_extn_battery_properties_listener_deinit();
+bool audio_extn_battery_properties_is_charging();
+#ifdef __cplusplus
+}
+#endif
+#else
+#define audio_extn_battery_properties_listener_init(fn) do { } while(0)
+#define audio_extn_battery_properties_listener_deinit() do { } while(0)
+#define audio_extn_battery_properties_is_charging() (false)
+#endif
diff --git a/hal/audio_extn/soundtrigger.c b/hal/audio_extn/soundtrigger.c
index 0fa30d0..b2e1bef 100644
--- a/hal/audio_extn/soundtrigger.c
+++ b/hal/audio_extn/soundtrigger.c
@@ -80,6 +80,7 @@
     AUDIO_EVENT_SVA_EXEC_MODE_STATUS,
     AUDIO_EVENT_CAPTURE_STREAM_INACTIVE,
     AUDIO_EVENT_CAPTURE_STREAM_ACTIVE,
+    AUDIO_EVENT_BATTERY_STATUS_CHANGED,
 } audio_event_type_t;
 
 typedef enum {
@@ -500,12 +501,16 @@
         __func__, uc_info->id, uc_info->type, event, raise_event);
     if (raise_event) {
         if (uc_info->type == PCM_PLAYBACK) {
+            if (uc_info->stream.out)
+                ev_info.device_info.device = uc_info->stream.out->devices;
+            else
+                ev_info.device_info.device = AUDIO_DEVICE_OUT_SPEAKER;
             switch(event) {
             case ST_EVENT_STREAM_FREE:
-                st_dev->st_callback(AUDIO_EVENT_PLAYBACK_STREAM_INACTIVE, NULL);
+                st_dev->st_callback(AUDIO_EVENT_PLAYBACK_STREAM_INACTIVE, &ev_info);
                 break;
             case ST_EVENT_STREAM_BUSY:
-                st_dev->st_callback(AUDIO_EVENT_PLAYBACK_STREAM_ACTIVE, NULL);
+                st_dev->st_callback(AUDIO_EVENT_PLAYBACK_STREAM_ACTIVE, &ev_info);
                 break;
             default:
                 ALOGW("%s:invalid event %d, for usecase %d",
@@ -525,6 +530,18 @@
     }
 }
 
+void audio_extn_sound_trigger_update_battery_status(bool charging)
+{
+    struct audio_event_info ev_info;
+
+    if (!st_dev || st_dev->sthal_prop_api_version < STHAL_PROP_API_VERSION_1_0)
+        return;
+
+    ev_info.u.value = charging;
+    st_dev->st_callback(AUDIO_EVENT_BATTERY_STATUS_CHANGED, &ev_info);
+}
+
+
 void audio_extn_sound_trigger_set_parameters(struct audio_device *adev __unused,
                                struct str_parms *params)
 {
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index 34a9937..fa36879 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -7390,6 +7390,15 @@
     return ret;
 }
 
+void adev_on_battery_status_changed(bool charging)
+{
+    pthread_mutex_lock(&adev->lock);
+    ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
+    adev->is_charging = charging;
+    audio_extn_sound_trigger_update_battery_status(charging);
+    pthread_mutex_unlock(&adev->lock);
+}
+
 static int adev_open(const hw_module_t *module, const char *name,
                      hw_device_t **device)
 {
@@ -7635,8 +7644,16 @@
     pthread_mutex_lock(&adev->lock);
     audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
     adev->card_status = CARD_STATUS_ONLINE;
-    pthread_mutex_unlock(&adev->lock);
+    audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
+    /*
+     * if the battery state callback happens before charging can be queried,
+     * it will be guarded with the adev->lock held in the cb function and so
+     * the callback value will reflect the latest state
+     */
+    adev->is_charging = audio_extn_battery_properties_is_charging();
     audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
+    audio_extn_sound_trigger_update_battery_status(adev->is_charging);
+    pthread_mutex_unlock(&adev->lock);
     /* Allocate memory for Device config params */
     adev->device_cfg_params = (struct audio_device_config_param*)
                                   calloc(platform_get_max_codec_backend(),
diff --git a/hal/audio_hw.h b/hal/audio_hw.h
index 497b5c8..c29f7b8 100755
--- a/hal/audio_hw.h
+++ b/hal/audio_hw.h
@@ -486,6 +486,7 @@
     unsigned int cur_wfd_channels;
     bool bt_wb_speech_enabled;
     bool allow_afe_proxy_usage;
+    bool is_charging; // from battery listener
 
     int snd_card;
     card_status_t card_status;
diff --git a/hal/msm8916/platform.c b/hal/msm8916/platform.c
index 41d6e6b..6e0a75a 100644
--- a/hal/msm8916/platform.c
+++ b/hal/msm8916/platform.c
@@ -233,6 +233,11 @@
 static int max_be_dai_names = 0;
 static const struct be_dai_name_struct *be_dai_name_table;
 
+struct snd_device_to_mic_map {
+    struct mic_info microphones[AUDIO_MICROPHONE_MAX_COUNT];
+    size_t mic_count;
+};
+
 struct platform_data {
     struct audio_device *adev;
     bool fluence_in_spkr_mode;
@@ -298,6 +303,9 @@
     struct listnode acdb_meta_key_list;
     bool use_generic_handset;
     struct acdb_init_data_v4 acdb_init_data;
+    uint32_t declared_mic_count;
+    struct audio_microphone_characteristic_t microphones[AUDIO_MICROPHONE_MAX_COUNT];
+    struct snd_device_to_mic_map mic_map[SND_DEVICE_MAX];
 };
 
 static bool is_external_codec = false;
@@ -935,6 +943,8 @@
     {TO_NAME_INDEX(USECASE_AUDIO_RECORD_AFE_PROXY)},
     {TO_NAME_INDEX(USECASE_AUDIO_EC_REF_LOOPBACK)},
     {TO_NAME_INDEX(USECASE_AUDIO_A2DP_ABR_FEEDBACK)},
+    {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_VOIP)},
+    {TO_NAME_INDEX(USECASE_AUDIO_RECORD_VOIP)},
 };
 
 #define NO_COLS 2
@@ -2073,6 +2083,8 @@
         if(snd_card_name) {
             if ((!strncmp(snd_card_name, "msm8953-snd-card-mtp",
                     sizeof("msm8953-snd-card-mtp")) ||
+                (!strncmp(snd_card_name, "msm8953-sku4-snd-card",
+                    sizeof("msm8953-sku4-snd-card"))) ||
                 (!strncmp(snd_card_name, "msm8952-skum-snd-card",
                     sizeof("msm8952-skum-snd-card"))))) {
                 *is_wsa_combo_supported = true;
@@ -2280,6 +2292,7 @@
     my_data->hw_dep_fd = -1;
     my_data->mono_speaker = SPKR_1;
     my_data->voice_speaker_stereo = false;
+    my_data->declared_mic_count = 0;
 
     be_dai_name_table = NULL;
 
@@ -5735,7 +5748,7 @@
                         rate_str = "KHZ_8";
                         break;
                 case 11025:
-                        rate_str = "HZ_11P025";
+                        rate_str = "KHZ_11P025";
                         break;
                 case 16000:
                         rate_str = "KHZ_16";
@@ -7433,6 +7446,7 @@
         (!strcmp(snd_card_name, "msm8976-skun-snd-card")) ||
         (!strcmp(snd_card_name, "msm8953-snd-card-mtp")) ||
         (!strcmp(snd_card_name, "msm8953-sku4-snd-card")) ||
+        (!strcmp(snd_card_name, "sdm439-sku1-snd-card")) ||
         (!strcmp(snd_card_name, "sdm439-snd-card-mtp")))
         return 1;
     else
@@ -8117,25 +8131,103 @@
     return id_string;
 }
 
-bool platform_set_microphone_characteristic(void *platform __unused,
-                                            struct audio_microphone_characteristic_t mic __unused) {
-    return -ENOSYS;
+bool platform_set_microphone_characteristic(void *platform,
+                                            struct audio_microphone_characteristic_t mic) {
+    struct platform_data *my_data = (struct platform_data *)platform;
+    if (my_data->declared_mic_count >= AUDIO_MICROPHONE_MAX_COUNT) {
+        ALOGE("mic number is more than maximum number");
+        return false;
+    }
+    for (size_t ch = 0; ch < AUDIO_CHANNEL_COUNT_MAX; ch++) {
+        mic.channel_mapping[ch] = AUDIO_MICROPHONE_CHANNEL_MAPPING_UNUSED;
+    }
+    my_data->microphones[my_data->declared_mic_count++] = mic;
+    return true;
 }
 
-int platform_get_microphones(void *platform __unused,
-                             struct audio_microphone_characteristic_t *mic_array __unused,
-                             size_t *mic_count __unused) {
-    return -ENOSYS;
+int platform_get_microphones(void *platform,
+                             struct audio_microphone_characteristic_t *mic_array,
+                             size_t *mic_count) {
+    struct platform_data *my_data = (struct platform_data *)platform;
+    if (mic_count == NULL)
+        return -EINVAL;
+    if (mic_array == NULL)
+        return -EINVAL;
+
+    if (*mic_count == 0) {
+        *mic_count = my_data->declared_mic_count;
+        return 0;
+    }
+
+    size_t max_mic_count = *mic_count;
+    size_t actual_mic_count = 0;
+    for (size_t i = 0; i < max_mic_count && i < my_data->declared_mic_count; i++) {
+        mic_array[i] = my_data->microphones[i];
+        actual_mic_count++;
+    }
+    *mic_count = actual_mic_count;
+    ALOGV("%s: returning number of mics %d", __func__, (int)*mic_count);
+    return 0;
 }
 
-bool platform_set_microphone_map(void *platform __unused, snd_device_t in_snd_device __unused,
-                                 const struct mic_info *info __unused) {
-    return false;
+bool platform_set_microphone_map(void *platform, snd_device_t in_snd_device,
+                                 const struct mic_info *info) {
+    struct platform_data *my_data = (struct platform_data *)platform;
+    if (in_snd_device < SND_DEVICE_IN_BEGIN || in_snd_device >= SND_DEVICE_IN_END) {
+        ALOGE("%s: Sound device not valid", __func__);
+        return false;
+    }
+    size_t m_count = my_data->mic_map[in_snd_device].mic_count++;
+    if (m_count >= AUDIO_MICROPHONE_MAX_COUNT) {
+        ALOGE("%s: Microphone count is greater than max allowed value", __func__);
+        my_data->mic_map[in_snd_device].mic_count--;
+        return false;
+    }
+    my_data->mic_map[in_snd_device].microphones[m_count] = *info;
+    return true;
 }
 
-int platform_get_active_microphones(void *platform __unused, unsigned int channels __unused,
-                                    audio_usecase_t usecase __unused,
-                                    struct audio_microphone_characteristic_t *mic_array __unused,
-                                    size_t *mic_count __unused) {
-    return -ENOSYS;
+int platform_get_active_microphones(void *platform, unsigned int channels,
+                                    audio_usecase_t uc_id,
+                                    struct audio_microphone_characteristic_t *mic_array,
+                                    size_t *mic_count) {
+    struct platform_data *my_data = (struct platform_data *)platform;
+    struct audio_usecase *usecase = get_usecase_from_list(my_data->adev, uc_id);
+    if (mic_count == NULL || mic_array == NULL || usecase == NULL) {
+        return -EINVAL;
+    }
+    size_t max_mic_count = my_data->declared_mic_count;
+    size_t actual_mic_count = 0;
+
+    snd_device_t active_input_snd_device =
+            platform_get_input_snd_device(platform, usecase->stream.in->device);
+    if (active_input_snd_device == SND_DEVICE_NONE) {
+        ALOGI("%s: No active microphones found", __func__);
+        goto end;
+    }
+
+    size_t  active_mic_count = my_data->mic_map[active_input_snd_device].mic_count;
+    struct mic_info *m_info = my_data->mic_map[active_input_snd_device].microphones;
+
+    for (size_t i = 0; i < active_mic_count; i++) {
+        unsigned int channels_for_active_mic = channels;
+        if (channels_for_active_mic > m_info[i].channel_count) {
+            channels_for_active_mic = m_info[i].channel_count;
+        }
+        for (size_t j = 0; j < max_mic_count; j++) {
+            if (strcmp(my_data->microphones[j].device_id,
+                       m_info[i].device_id) == 0) {
+                mic_array[actual_mic_count] = my_data->microphones[j];
+                for (size_t ch = 0; ch < channels_for_active_mic; ch++) {
+                     mic_array[actual_mic_count].channel_mapping[ch] =
+                             m_info[i].channel_mapping[ch];
+                }
+                actual_mic_count++;
+                break;
+            }
+        }
+    }
+end:
+    *mic_count = actual_mic_count;
+    return 0;
 }
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index 92f92aa..aeab831 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -920,6 +920,8 @@
     {TO_NAME_INDEX(USECASE_AUDIO_RECORD_AFE_PROXY)},
     {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_SILENCE)},
     {TO_NAME_INDEX(USECASE_AUDIO_A2DP_ABR_FEEDBACK)},
+    {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_VOIP)},
+    {TO_NAME_INDEX(USECASE_AUDIO_RECORD_VOIP)},
 };
 
 #define NO_COLS 2
@@ -5712,7 +5714,7 @@
                         rate_str = "KHZ_8";
                         break;
                 case 11025:
-                        rate_str = "HZ_11P025";
+                        rate_str = "KHZ_11P025";
                         break;
                 case 16000:
                         rate_str = "KHZ_16";
diff --git a/hal/platform_info.c b/hal/platform_info.c
index d27d689..dca577b 100644
--- a/hal/platform_info.c
+++ b/hal/platform_info.c
@@ -569,7 +569,7 @@
         ALOGE("%s: device_id %s is too long", __func__, attr[curIdx]);
         goto done;
     }
-    strcpy(microphone.device_id, attr[curIdx++]);
+    strlcpy(microphone.device_id, attr[curIdx++], sizeof(microphone.device_id));
 
     if (strcmp(attr[curIdx++], "type")) {
         ALOGE("%s: device not found", __func__);
@@ -590,13 +590,13 @@
         ALOGE("%s, address %s is too long", __func__, attr[curIdx]);
         goto done;
     }
-    strcpy(microphone.address, attr[curIdx++]);
+    strlcpy(microphone.address, attr[curIdx++], sizeof(microphone.address));
     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);
+            strlcpy(microphone.address, AUDIO_BOTTOM_MICROPHONE_ADDRESS, sizeof(microphone.address));
         } else if (microphone.device == AUDIO_DEVICE_IN_BACK_MIC) {
-            strcpy(microphone.address, AUDIO_BACK_MICROPHONE_ADDRESS);
+            strlcpy(microphone.address, AUDIO_BACK_MICROPHONE_ADDRESS, sizeof(microphone.address));
         }
     }
 
@@ -648,7 +648,8 @@
             ALOGE("%s: frequencies not found", __func__);
             goto done;
         }
-        char *token = strtok((char *)attr[curIdx++], " ");
+        char *context = NULL;
+        char *token = strtok_r((char *)attr[curIdx++], " ", &context);
         uint32_t num_frequencies = 0;
         while (token) {
             microphone.frequency_responses[0][num_frequencies++] = atof(token);
@@ -656,14 +657,14 @@
                 ALOGE("%s: num %u of frequency is too large", __func__, num_frequencies);
                 goto done;
             }
-            token = strtok(NULL, " ");
+            token = strtok_r(NULL, " ", &context);
         }
 
         if (strcmp(attr[curIdx++], "responses")) {
             ALOGE("%s: responses not found", __func__);
             goto done;
         }
-        token = strtok((char *)attr[curIdx++], " ");
+        token = strtok_r((char *)attr[curIdx++], " ", &context);
         uint32_t num_responses = 0;
         while (token) {
             microphone.frequency_responses[1][num_responses++] = atof(token);
@@ -671,7 +672,7 @@
                 ALOGE("%s: num %u of response is too large", __func__, num_responses);
                 goto done;
             }
-            token = strtok(NULL, " ");
+            token = strtok_r(NULL, " ", &context);
         }
 
         if (num_frequencies != num_responses
@@ -717,7 +718,8 @@
             ALOGE("%s: orientation not found", __func__);
             goto done;
         }
-        char *token = strtok((char *)attr[curIdx++], " ");
+        char *context = NULL;
+        char *token = strtok_r((char *)attr[curIdx++], " ", &context);
         float orientation[3];
         uint32_t idx = 0;
         while (token) {
@@ -726,7 +728,7 @@
                 ALOGE("%s: orientation invalid", __func__);
                 goto done;
             }
-            token = strtok(NULL, " ");
+            token = strtok_r(NULL, " ", &context);
         }
         if (idx != 3) {
             ALOGE("%s: orientation invalid", __func__);
@@ -746,7 +748,8 @@
             ALOGE("%s: geometric_location not found", __func__);
             goto done;
         }
-        char *token = strtok((char *)attr[curIdx++], " ");
+        char *context = NULL;
+        char *token = strtok_r((char *)attr[curIdx++], " ", &context);
         float geometric_location[3];
         uint32_t idx = 0;
         while (token) {
@@ -755,7 +758,7 @@
                 ALOGE("%s: geometric_location invalid", __func__);
                 goto done;
             }
-            token = strtok(NULL, " ");
+            token = strtok_r(NULL, " ", &context);
         }
         if (idx != 3) {
             ALOGE("%s: geometric_location invalid", __func__);
@@ -813,7 +816,8 @@
         ALOGE("%s: channel_mapping not found", __func__);
         goto on_error;
     }
-    const char *token = strtok((char *)attr[curIdx++], " ");
+    char *context = NULL;
+    const char *token = strtok_r((char *)attr[curIdx++], " ", &context);
     uint32_t idx = 0;
     while (token) {
         if (!find_enum_by_string(mic_channel_mapping, token,
@@ -823,7 +827,7 @@
                       __func__, attr[--curIdx], PLATFORM_INFO_XML_PATH);
             goto on_error;
         }
-        token = strtok(NULL, " ");
+        token = strtok_r(NULL, " ", &context);
     }
     microphone.channel_count = idx;