Promotion of av-userspace.lnx.2.0-00018.

CRs      Change ID                                   Subject
--------------------------------------------------------------------------------------------------------------
1019158   Ie40c286eb9988aeb5093f32c7f81cdb142e88eb6   hal: Add device sidetone support for USB audio ADSP solu
1032603   I476cc16e89438709bdd6ceea371eed6bdb7b62f4   audiopolicy: add log to print XML policy config flag
1015318   Iae65e00b0f4d2f74f303ef03610f8b3a098dc7aa   audio: config audio backend for HDMI playback
1019158   I95a9796d7cad71e09dedd2bcd451183cbd25ca71   hal: Add USB audio via ADSP support
1000024   Id0b67630077e06284b8a396be69ebe0c72747c90   audio : refactoring of compress passthrough changes.
1022145   I310a462ae8efe707658d941e88cb5ea59a9f8550   audio: Fix memory leak
1000024   I33bff4db9e03dbe417b93729d8c310ca4f1c7c53   audio:msmcobalt: Add Compress Passthrough support

Change-Id: I5d2bbf17af3823fd68cb21a13d1dc7bad4cdb482
CRs-Fixed: 1015318, 1000024, 1022145, 1032603, 1019158
diff --git a/configs/msm8996/audio_output_policy.conf b/configs/msm8996/audio_output_policy.conf
index 93cd0c2..0563503 100644
--- a/configs/msm8996/audio_output_policy.conf
+++ b/configs/msm8996/audio_output_policy.conf
@@ -46,11 +46,18 @@
     bit_width 24
     app_type 69940
   }
-  compress_passthrough {
+  compress_passthrough_16 {
     flags AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD|AUDIO_OUTPUT_FLAG_NON_BLOCKING|AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH
     formats AUDIO_FORMAT_AC3|AUDIO_FORMAT_E_AC3|AUDIO_FORMAT_E_AC3_JOC|AUDIO_FORMAT_DTS|AUDIO_FORMAT_DTS_HD
     sampling_rates 32000|44100|48000|88200|96000|176400|192000
-    bit_width 16|24
+    bit_width 16
+    app_type 69941
+  }
+  compress_passthrough_24 {
+    flags AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD|AUDIO_OUTPUT_FLAG_NON_BLOCKING|AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH
+    formats AUDIO_FORMAT_AC3|AUDIO_FORMAT_E_AC3|AUDIO_FORMAT_E_AC3_JOC|AUDIO_FORMAT_DTS|AUDIO_FORMAT_DTS_HD
+    sampling_rates 32000|44100|48000|88200|96000|176400|192000
+    bit_width 24
     app_type 69941
   }
   compress_offload_16 {
diff --git a/configs/msm8996/mixer_paths_tasha.xml b/configs/msm8996/mixer_paths_tasha.xml
index 360e80b..596b016 100644
--- a/configs/msm8996/mixer_paths_tasha.xml
+++ b/configs/msm8996/mixer_paths_tasha.xml
@@ -120,6 +120,7 @@
     <ctl name="HDMI Mixer MultiMedia4" value="0" />
     <ctl name="HDMI Mixer MultiMedia5" value="0" />
     <ctl name="HDMI Mixer MultiMedia7" value="0" />
+    <ctl name="HDMI Mixer MultiMedia9" value="0" />
     <ctl name="HDMI Mixer MultiMedia10" value="0" />
     <ctl name="HDMI Mixer MultiMedia11" value="0" />
     <ctl name="HDMI Mixer MultiMedia12" value="0" />
@@ -755,6 +756,10 @@
         <ctl name="HDMI Mixer MultiMedia4" value="1" />
     </path>
 
+    <path name="silence-playback hdmi">
+        <ctl name="HDMI Mixer MultiMedia9" value="1" />
+    </path>
+
     <path name="compress-offload-playback bt-sco">
         <ctl name="AUX_PCM_RX Audio Mixer MultiMedia4" value="1" />
     </path>
diff --git a/configs/msm8996/msm8996.mk b/configs/msm8996/msm8996.mk
index 2b70a81..d0ddf24 100644
--- a/configs/msm8996/msm8996.mk
+++ b/configs/msm8996/msm8996.mk
@@ -19,7 +19,8 @@
 AUDIO_FEATURE_ENABLED_FLUENCE := true
 AUDIO_FEATURE_ENABLED_HDMI_SPK := true
 AUDIO_FEATURE_ENABLED_HDMI_EDID := true
-AUDIO_FEATURE_ENABLED_HDMI_PASSTHROUGH := true
+#AUDIO_FEATURE_ENABLED_HDMI_PASSTHROUGH := true
+#AUDIO_FEATURE_ENABLED_KEEP_ALIVE := true
 AUDIO_FEATURE_ENABLED_HFP := true
 AUDIO_FEATURE_ENABLED_INCALL_MUSIC := false
 AUDIO_FEATURE_ENABLED_MULTI_VOICE_SESSIONS := true
@@ -45,8 +46,8 @@
 MM_AUDIO_ENABLED_SAFX := true
 TARGET_USES_QCOM_MM_AUDIO := true
 AUDIO_FEATURE_ENABLED_HW_ACCELERATED_EFFECTS := false
-DOLBY_DDP := true
 #AUDIO_FEATURE_ENABLED_DS2_DOLBY_DAP := true
+#DOLBY_DDP := true
 AUDIO_FEATURE_ENABLED_SOURCE_TRACKING := true
 AUDIO_FEATURE_ENABLED_AUDIOSPHERE := true
 ##AUDIO_FEATURE_FLAGS
diff --git a/configs/msmcobalt/audio_output_policy.conf b/configs/msmcobalt/audio_output_policy.conf
index 46fa191..67d79bf 100644
--- a/configs/msmcobalt/audio_output_policy.conf
+++ b/configs/msmcobalt/audio_output_policy.conf
@@ -46,6 +46,20 @@
     bit_width 24
     app_type 69940
   }
+  compress_passthrough_16 {
+    flags AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD|AUDIO_OUTPUT_FLAG_NON_BLOCKING|AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH
+    formats AUDIO_FORMAT_AC3|AUDIO_FORMAT_E_AC3|AUDIO_FORMAT_E_AC3_JOC|AUDIO_FORMAT_DTS|AUDIO_FORMAT_DTS_HD
+    sampling_rates 32000|44100|48000|88200|96000|176400|192000
+    bit_width 16
+    app_type 69941
+  }
+  compress_passthrough_24 {
+    flags AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD|AUDIO_OUTPUT_FLAG_NON_BLOCKING|AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH
+    formats AUDIO_FORMAT_AC3|AUDIO_FORMAT_E_AC3|AUDIO_FORMAT_E_AC3_JOC|AUDIO_FORMAT_DTS|AUDIO_FORMAT_DTS_HD
+    sampling_rates 32000|44100|48000|88200|96000|176400|192000
+    bit_width 24
+    app_type 69941
+  }
   compress_offload_16 {
     flags AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD|AUDIO_OUTPUT_FLAG_NON_BLOCKING
     formats AUDIO_FORMAT_MP3|AUDIO_FORMAT_PCM_16_BIT_OFFLOAD|AUDIO_FORMAT_PCM_24_BIT_OFFLOAD|AUDIO_FORMAT_FLAC|AUDIO_FORMAT_ALAC|AUDIO_FORMAT_APE|AUDIO_FORMAT_AAC_LC|AUDIO_FORMAT_AAC_HE_V1|AUDIO_FORMAT_AAC_HE_V2|AUDIO_FORMAT_WMA|AUDIO_FORMAT_WMA_PRO|AUDIO_FORMAT_VORBIS|AUDIO_FORMAT_AAC_ADTS_LC|AUDIO_FORMAT_AAC_ADTS_HE_V1|AUDIO_FORMAT_AAC_ADTS_HE_V2
diff --git a/configs/msmcobalt/audio_platform_info.xml b/configs/msmcobalt/audio_platform_info.xml
index fc86a53..ae252bc 100644
--- a/configs/msmcobalt/audio_platform_info.xml
+++ b/configs/msmcobalt/audio_platform_info.xml
@@ -69,6 +69,8 @@
         <!-- followed by perf lock options                             -->
         <param key="perf_lock_opts" value="4, 0x101, 0x704, 0x20F, 0x1E01"/>
         <param key="input_mic_max_count" value="4"/>
+        <!-- In the below value string, the value indicates sidetone gain in dB -->
+        <param key="usb_sidetone_gain" value="35"/>
     </config_params>
     <backend_names>
         <device name="SND_DEVICE_OUT_HEADPHONES" backend="headphones" interface="SLIMBUS_6_RX"/>
diff --git a/configs/msmcobalt/audio_policy.conf b/configs/msmcobalt/audio_policy.conf
index efd1ef3..08997e0 100644
--- a/configs/msmcobalt/audio_policy.conf
+++ b/configs/msmcobalt/audio_policy.conf
@@ -43,6 +43,13 @@
          devices AUDIO_DEVICE_OUT_SPEAKER|AUDIO_DEVICE_OUT_EARPIECE|AUDIO_DEVICE_OUT_WIRED_HEADSET|AUDIO_DEVICE_OUT_WIRED_HEADPHONE|AUDIO_DEVICE_OUT_LINE|AUDIO_DEVICE_OUT_ALL_SCO|AUDIO_DEVICE_OUT_AUX_DIGITAL|AUDIO_DEVICE_OUT_PROXY|AUDIO_DEVICE_OUT_FM
          flags AUDIO_OUTPUT_FLAG_DEEP_BUFFER
       }
+      compress_passthrough {
+        sampling_rates dynamic
+        channel_masks dynamic
+        formats dynamic
+        devices AUDIO_DEVICE_OUT_AUX_DIGITAL
+        flags AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD|AUDIO_OUTPUT_FLAG_NON_BLOCKING
+      }
       multichannel {
         sampling_rates 8000|11025|16000|22050|32000|44100|48000|64000|88200|96000|128000|176400|192000
         channel_masks dynamic
diff --git a/configs/msmcobalt/audio_policy_configuration.xml b/configs/msmcobalt/audio_policy_configuration.xml
index 56848ad..a3876ef 100644
--- a/configs/msmcobalt/audio_policy_configuration.xml
+++ b/configs/msmcobalt/audio_policy_configuration.xml
@@ -73,6 +73,11 @@
                     <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                              samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
                 </mixPort>
+                <mixPort name="compress_passthrough" role="source"
+                        flags="AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD|AUDIO_OUTPUT_FLAG_NON_BLOCKING">
+                    <profile name="" format="dynamic"
+                             samplingRates="dynamic" channelMasks="dynamic"/>
+                </mixPort>
                 <mixPort name="multichannel" role="source"
                         flags="AUDIO_OUTPUT_FLAG_DIRECT">
                     <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
@@ -266,7 +271,7 @@
                 <route type="mix" sink="Line"
                        sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload,voip_rx"/>
                 <route type="mix" sink="HDMI"
-                       sources="primary output,raw,deep_buffer,multichannel,direct_pcm,compressed_offload"/>
+                       sources="primary output,raw,deep_buffer,multichannel,direct_pcm,compressed_offload,compress_passthrough"/>
                 <route type="mix" sink="Proxy"
                        sources="primary output,raw,deep_buffer,multichannel,direct_pcm,compressed_offload"/>
                 <route type="mix" sink="FM"
diff --git a/configs/msmcobalt/mixer_paths_tasha.xml b/configs/msmcobalt/mixer_paths_tasha.xml
index f60a036..8d30f6b 100644
--- a/configs/msmcobalt/mixer_paths_tasha.xml
+++ b/configs/msmcobalt/mixer_paths_tasha.xml
@@ -131,6 +131,7 @@
     <ctl name="HDMI Mixer MultiMedia4" value="0" />
     <ctl name="HDMI Mixer MultiMedia5" value="0" />
     <ctl name="HDMI Mixer MultiMedia7" value="0" />
+    <ctl name="HDMI Mixer MultiMedia9" value="0" />
     <ctl name="HDMI Mixer MultiMedia10" value="0" />
     <ctl name="HDMI Mixer MultiMedia11" value="0" />
     <ctl name="HDMI Mixer MultiMedia12" value="0" />
@@ -481,7 +482,6 @@
 
     <!-- Incall Music -->
     <ctl name="Incall_Music Audio Mixer MultiMedia2" value="0" />
-    <ctl name="Incall_Music_2 Audio Mixer MultiMedia9" value="0" />
     <!-- Incall Music End -->
 
     <!-- compress-voip-call start -->
@@ -801,6 +801,10 @@
         <ctl name="HDMI Mixer MultiMedia4" value="1" />
     </path>
 
+    <path name="silence-playback hdmi">
+        <ctl name="HDMI Mixer MultiMedia9" value="1" />
+    </path>
+
     <path name="compress-offload-playback bt-sco">
         <ctl name="SLIMBUS_7_RX Audio Mixer MultiMedia4" value="1" />
     </path>
diff --git a/configs/msmcobalt/msmcobalt.mk b/configs/msmcobalt/msmcobalt.mk
index c6a7cc9..8244d6b 100644
--- a/configs/msmcobalt/msmcobalt.mk
+++ b/configs/msmcobalt/msmcobalt.mk
@@ -19,6 +19,10 @@
 AUDIO_FEATURE_ENABLED_FLUENCE := true
 AUDIO_FEATURE_ENABLED_HDMI_SPK := true
 AUDIO_FEATURE_ENABLED_HDMI_EDID := true
+#AUDIO_FEATURE_ENABLED_HDMI_PASSTHROUGH := true
+#AUDIO_FEATURE_ENABLED_KEEP_ALIVE := true
+#AUDIO_FEATURE_ENABLED_DS2_DOLBY_DAP := true
+#DOLBY_DDP := true
 AUDIO_FEATURE_ENABLED_HFP := true
 AUDIO_FEATURE_ENABLED_INCALL_MUSIC := false
 AUDIO_FEATURE_ENABLED_MULTI_VOICE_SESSIONS := true
diff --git a/hal/audio_extn/audio_extn.c b/hal/audio_extn/audio_extn.c
index 8b8632e..49e649c 100644
--- a/hal/audio_extn/audio_extn.c
+++ b/hal/audio_extn/audio_extn.c
@@ -677,11 +677,7 @@
     ret = str_parms_get_str(query, AUDIO_PARAMETER_CAN_OPEN_PROXY, value,
                             sizeof(value));
     if (ret >= 0) {
-        if (audio_extn_usb_is_proxy_inuse() ||
-            !adev->allow_afe_proxy_usage)
-            val = 0;
-        else
-            val = 1;
+        val = (adev->allow_afe_proxy_usage ? 1: 0);
         str_parms_add_int(reply, AUDIO_PARAMETER_CAN_OPEN_PROXY, val);
     }
     ALOGV("%s: called ... can_use_proxy %d", __func__, val);
diff --git a/hal/audio_extn/audio_extn.h b/hal/audio_extn/audio_extn.h
index 3ce83b1..090e6b0 100644
--- a/hal/audio_extn/audio_extn.h
+++ b/hal/audio_extn/audio_extn.h
@@ -151,24 +151,24 @@
 #endif
 
 #ifndef USB_HEADSET_ENABLED
-#define audio_extn_usb_init(adev)                        (0)
-#define audio_extn_usb_deinit()                          (0)
-#define audio_extn_usb_start_playback(adev)              (0)
-#define audio_extn_usb_stop_playback()                   (0)
-#define audio_extn_usb_start_capture(adev)               (0)
-#define audio_extn_usb_stop_capture()                    (0)
-#define audio_extn_usb_set_proxy_sound_card(sndcard_idx) (0)
-#define audio_extn_usb_is_proxy_inuse()                  (0)
+#define audio_extn_usb_init(adev)                                      (0)
+#define audio_extn_usb_deinit()                                        (0)
+#define audio_extn_usb_add_device(device, card)                        (0)
+#define audio_extn_usb_remove_device(device, card)                     (0)
+#define audio_extn_usb_is_config_supported(bit_width, sample_rate, ch) (0)
+#define audio_extn_usb_enable_sidetone(device, enable)                 (0)
+#define audio_extn_usb_set_sidetone_gain(parms, value, len)            (0)
 #else
-void initPlaybackVolume();
 void audio_extn_usb_init(void *adev);
 void audio_extn_usb_deinit();
-void audio_extn_usb_start_playback(void *adev);
-void audio_extn_usb_stop_playback();
-void audio_extn_usb_start_capture(void *adev);
-void audio_extn_usb_stop_capture();
-void audio_extn_usb_set_proxy_sound_card(uint32_t sndcard_idx);
-bool audio_extn_usb_is_proxy_inuse();
+void audio_extn_usb_add_device(audio_devices_t device, int card);
+void audio_extn_usb_remove_device(audio_devices_t device, int card);
+bool audio_extn_usb_is_config_supported(unsigned int *bit_width,
+                                        unsigned int *sample_rate,
+                                        unsigned int ch);
+int audio_extn_usb_enable_sidetone(int device, bool enable);
+int audio_extn_usb_set_sidetone_gain(struct str_parms *parms,
+                                     char *value, int len);
 #endif
 
 #ifndef SSR_ENABLED
@@ -354,7 +354,6 @@
                                     AUDIO_CHANNEL_OUT_FRONT_CENTER | AUDIO_CHANNEL_OUT_BACK_CENTER)
 #endif
 
-
 #if defined(DS1_DOLBY_DDP_ENABLED) || defined(DS1_DOLBY_DAP_ENABLED) || defined(DS2_DOLBY_DAP_ENABLED)
 void audio_extn_dolby_set_license(struct audio_device *adev);
 #else
@@ -389,13 +388,13 @@
 #endif
 
 #ifndef HDMI_PASSTHROUGH_ENABLED
-#define audio_extn_dolby_update_passt_stream_configuration(adev, out)      (0)
-#define audio_extn_dolby_is_passt_convert_supported(adev, out)             (0)
-#define audio_extn_dolby_is_passt_supported(adev, out)                     (0)
-#define audio_extn_dolby_is_passthrough_stream(out)                        (0)
-#define audio_extn_dolby_get_passt_buffer_size(info)                       (0)
-#define audio_extn_dolby_set_passt_volume(out, mute)                       (0)
-#define audio_extn_dolby_set_passt_latency(out, latency)                   (0)
+#define audio_extn_passthru_update_stream_configuration(adev, out)            (0)
+#define audio_extn_passthru_is_convert_supported(adev, out)                   (0)
+#define audio_extn_passthru_is_passt_supported(adev, out)                     (0)
+#define audio_extn_passthru_is_passthrough_stream(out)                        (0)
+#define audio_extn_passthru_get_buffer_size(info)                             (0)
+#define audio_extn_passthru_set_volume(out, mute)                             (0)
+#define audio_extn_passthru_set_latency(out, latency)                         (0)
 #define audio_extn_passthru_is_supported_format(f) (0)
 #define audio_extn_passthru_should_drop_data(o) (0)
 #define audio_extn_passthru_on_start(o) do {} while(0)
@@ -409,16 +408,16 @@
 
 #define AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH  0x1000
 #else
-bool audio_extn_dolby_is_passt_convert_supported(struct audio_device *adev,
+bool audio_extn_passthru_is_convert_supported(struct audio_device *adev,
                                                  struct stream_out *out);
-bool audio_extn_dolby_is_passt_supported(struct audio_device *adev,
+bool audio_extn_passthru_is_passt_supported(struct audio_device *adev,
                                          struct stream_out *out);
-void audio_extn_dolby_update_passt_stream_configuration(struct audio_device *adev,
+void audio_extn_passthru_update_stream_configuration(struct audio_device *adev,
                                                  struct stream_out *out);
-bool audio_extn_dolby_is_passthrough_stream(struct stream_out *out);
-int audio_extn_dolby_get_passt_buffer_size(audio_offload_info_t* info);
-int audio_extn_dolby_set_passt_volume(struct stream_out *out, int mute);
-int audio_extn_dolby_set_passt_latency(struct stream_out *out, int latency);
+bool audio_extn_passthru_is_passthrough_stream(struct stream_out *out);
+int audio_extn_passthru_get_buffer_size(audio_offload_info_t* info);
+int audio_extn_passthru_set_volume(struct stream_out *out, int mute);
+int audio_extn_passthru_set_latency(struct stream_out *out, int latency);
 bool audio_extn_passthru_is_supported_format(audio_format_t format);
 bool audio_extn_passthru_should_drop_data(struct stream_out * out);
 void audio_extn_passthru_on_start(struct stream_out *out);
@@ -430,7 +429,6 @@
 bool audio_extn_passthru_is_active();
 void audio_extn_passthru_init(struct audio_device *adev);
 bool audio_extn_passthru_should_standby(struct stream_out *out);
-
 #endif
 
 #ifndef HFP_ENABLED
diff --git a/hal/audio_extn/dolby.c b/hal/audio_extn/dolby.c
index ad8f8a4..f07c66a 100644
--- a/hal/audio_extn/dolby.c
+++ b/hal/audio_extn/dolby.c
@@ -357,45 +357,6 @@
 #endif /* DS1_DOLBY_DDP_ENABLED */
 
 #if defined(DS1_DOLBY_DDP_ENABLED) || defined(DS2_DOLBY_DAP_ENABLED)
-int audio_extn_dolby_get_snd_codec_id(struct audio_device *adev,
-                                      struct stream_out *out,
-                                      audio_format_t format)
-{
-    int id = 0;
-    /*
-     * Use wfd /hdmi sink channel cap for dolby params if device is wfd
-     * or hdmi. Otherwise use stereo configuration
-     */
-    int channel_cap = out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ?
-                      adev->cur_hdmi_channels :
-                      out->devices & AUDIO_DEVICE_OUT_PROXY ?
-                      adev->cur_wfd_channels : 2;
-
-    switch (format) {
-    case AUDIO_FORMAT_AC3:
-        id = SND_AUDIOCODEC_AC3;
-#ifdef DS1_DOLBY_DDP_ENABLED
-        send_ddp_endp_params_stream(out, out->devices,
-                            channel_cap, true /* set_cache */);
-#endif
-        audio_extn_dolby_set_dmid(adev);
-        break;
-    case AUDIO_FORMAT_E_AC3:
-    case AUDIO_FORMAT_E_AC3_JOC:
-        id = SND_AUDIOCODEC_EAC3;
-#ifdef DS1_DOLBY_DDP_ENABLED
-        send_ddp_endp_params_stream(out, out->devices,
-                            channel_cap, true /* set_cache */);
-#endif
-        audio_extn_dolby_set_dmid(adev);
-        break;
-    default:
-        ALOGE("%s: Unsupported audio format :%x", __func__, format);
-    }
-
-    return id;
-}
-
 bool audio_extn_is_dolby_format(audio_format_t format)
 {
     if (format == AUDIO_FORMAT_AC3 ||
@@ -407,121 +368,6 @@
 }
 #endif /* DS1_DOLBY_DDP_ENABLED || DS2_DOLBY_DAP_ENABLED */
 
-#ifdef HDMI_PASSTHROUGH_ENABLED
-bool audio_extn_dolby_is_passt_convert_supported(struct audio_device *adev,
-                                                 struct stream_out *out) {
-
-    bool convert = false;
-    switch (out->format) {
-    case AUDIO_FORMAT_E_AC3:
-    case AUDIO_FORMAT_E_AC3_JOC:
-        if (!platform_is_edid_supported_format(adev->platform,
-            AUDIO_FORMAT_E_AC3)) {
-            ALOGV("%s:PASSTHROUGH_CONVERT supported", __func__);
-            convert = true;
-        }
-        break;
-    default:
-        ALOGE("%s: PASSTHROUGH_CONVERT not supported for format 0x%x",
-              __func__, out->format);
-        break;
-    }
-    ALOGE("%s: convert %d", __func__, convert);
-    return convert;
-}
-
-bool audio_extn_dolby_is_passt_supported(struct audio_device *adev,
-                                         struct stream_out *out) {
-    bool passt = false;
-    switch (out->format) {
-    case AUDIO_FORMAT_E_AC3:
-        if (platform_is_edid_supported_format(adev->platform, out->format)) {
-            ALOGV("%s:PASSTHROUGH supported for format %x",
-                   __func__, out->format);
-            passt = true;
-        }
-        break;
-    case AUDIO_FORMAT_AC3:
-        if (platform_is_edid_supported_format(adev->platform, AUDIO_FORMAT_AC3)
-            || platform_is_edid_supported_format(adev->platform,
-            AUDIO_FORMAT_E_AC3)) {
-            ALOGV("%s:PASSTHROUGH supported for format %x",
-                   __func__, out->format);
-            passt = true;
-        }
-        break;
-    case AUDIO_FORMAT_E_AC3_JOC:
-         /* Check for DDP capability in edid for JOC contents.*/
-         if (platform_is_edid_supported_format(adev->platform,
-             AUDIO_FORMAT_E_AC3)) {
-             ALOGV("%s:PASSTHROUGH supported for format %x",
-                   __func__, out->format);
-             passt = true;
-         }
-    default:
-        ALOGV("%s:Passthrough not supported", __func__);
-    }
-    return passt;
-}
-
-void audio_extn_dolby_update_passt_stream_configuration(
-        struct audio_device *adev, struct stream_out *out) {
-    if (audio_extn_dolby_is_passt_supported(adev, out)) {
-        ALOGV("%s:PASSTHROUGH", __func__);
-        out->compr_config.codec->compr_passthr = PASSTHROUGH;
-    } else if (audio_extn_dolby_is_passt_convert_supported(adev, out)){
-        ALOGV("%s:PASSTHROUGH CONVERT", __func__);
-        out->compr_config.codec->compr_passthr = PASSTHROUGH_CONVERT;
-    } else {
-        ALOGV("%s:NO PASSTHROUGH", __func__);
-        out->compr_config.codec->compr_passthr = LEGACY_PCM;
-    }
-}
-
-bool audio_extn_dolby_is_passthrough_stream(struct stream_out *out) {
-
-    //check passthrough system property
-    if (!property_get_bool("audio.offload.passthrough", false)) {
-        return false;
-    }
-
-    //check supported device, currently only on HDMI.
-    if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
-        //passthrough flag
-        if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH)
-            return true;
-        //direct flag, check supported formats.
-        if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT) {
-            if (audio_extn_passthru_is_supported_format(out->format)) {
-                if (platform_is_edid_supported_format(out->dev->platform,
-                        out->format)) {
-                    return true;
-                } else if (audio_extn_is_dolby_format(out->format) &&
-                            platform_is_edid_supported_format(out->dev->platform,
-                                AUDIO_FORMAT_AC3)){
-                    //return true for EAC3/EAC3_JOC formats
-                    //if sink supports only AC3
-                    return true;
-                }
-            }
-        }
-    }
-
-    return false;
-}
-
-int audio_extn_dolby_get_passt_buffer_size(audio_offload_info_t* info) {
-    return platform_get_compress_passthrough_buffer_size(info);
-}
-
-int audio_extn_dolby_set_passt_volume(struct stream_out *out,  int mute) {
-    return platform_set_device_params(out, DEVICE_PARAM_MUTE_ID, mute);
-}
-
-int audio_extn_dolby_set_passt_latency(struct stream_out *out, int latency) {
-    return platform_set_device_params(out, DEVICE_PARAM_LATENCY_ID, latency);
-}
-#endif /* HDMI_PASSTHROUGH_ENABLED */
 
 #ifdef DS1_DOLBY_DAP_ENABLED
 void audio_extn_dolby_set_endpoint(struct audio_device *adev)
diff --git a/hal/audio_extn/keep_alive.c b/hal/audio_extn/keep_alive.c
index ab663ef..1a4f135 100644
--- a/hal/audio_extn/keep_alive.c
+++ b/hal/audio_extn/keep_alive.c
@@ -37,7 +37,7 @@
 #include <platform.h>
 
 #define SILENCE_MIXER_PATH "silence-playback hdmi"
-#define SILENCE_DEV_ID 5            /* index into machine driver */
+#define SILENCE_DEV_ID 32           /* index into machine driver */
 #define SILENCE_INTERVAL_US 2000000
 
 typedef enum {
@@ -147,22 +147,71 @@
 void audio_extn_keep_alive_start()
 {
     struct audio_device * adev = (struct audio_device *)ka.userdata;
-
-    if (ka.state == STATE_DEINIT)
-        return;
-
-    if (audio_extn_passthru_is_active())
-        return;
+    char mixer_ctl_name[MAX_LENGTH_MIXER_CONTROL_IN_INT];
+    int app_type_cfg[MAX_LENGTH_MIXER_CONTROL_IN_INT], len = 0, rc;
+    struct mixer_ctl *ctl;
+    int acdb_dev_id, snd_device;
+    int32_t sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
 
     pthread_mutex_lock(&ka.lock);
 
-    if (ka.state == STATE_ACTIVE)
+    if (ka.state == STATE_DEINIT) {
+        ALOGE(" %s : Invalid state ",__func__);
+        return;
+    }
+
+    if (audio_extn_passthru_is_active()) {
+        ALOGE(" %s : Pass through is already active", __func__);
+        return;
+    }
+
+    if (ka.state == STATE_ACTIVE) {
+        ALOGV(" %s : Keep alive state is already Active",__func__ );
         goto exit;
+    }
 
     ka.done = false;
-    //todo: platform_send_audio_calibration is replaced by audio_extn_utils_send_audio_calibration
-    //check why audio cal needs to be set
-    //platform_send_audio_calibration(adev->platform, SND_DEVICE_OUT_HDMI);
+
+    /*configure app type */
+    snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
+             "Audio Stream %d App Type Cfg",SILENCE_DEV_ID);
+
+    ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
+    if (!ctl) {
+        ALOGE("%s: Could not get ctl for mixer cmd - %s", __func__,
+              mixer_ctl_name);
+        rc = -EINVAL;
+        goto exit;
+    }
+
+    snd_device = SND_DEVICE_OUT_HDMI;
+    acdb_dev_id = platform_get_snd_device_acdb_id(snd_device);
+    if (acdb_dev_id < 0) {
+        ALOGE("%s: Couldn't get the acdb dev id", __func__);
+        rc = -EINVAL;
+        goto exit;
+    }
+
+    sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
+    app_type_cfg[len++] = platform_get_default_app_type(adev->platform);
+    app_type_cfg[len++] = acdb_dev_id;
+    app_type_cfg[len++] = sample_rate;
+
+    ALOGI("%s:%d PLAYBACK app_type %d, acdb_dev_id %d, sample_rate %d",
+          __func__, __LINE__,
+          platform_get_default_app_type(adev->platform),
+          acdb_dev_id, sample_rate);
+    mixer_ctl_set_array(ctl, app_type_cfg, len);
+
+    /*send calibration*/
+    struct audio_usecase *usecase = calloc(1, sizeof(struct audio_usecase));
+    usecase->type = PCM_PLAYBACK;
+    usecase->out_snd_device = SND_DEVICE_OUT_HDMI;
+
+    platform_send_audio_calibration(adev->platform, usecase,
+                platform_get_default_app_type(adev->platform), sample_rate);
+
+    /*apply audio route */
     audio_route_apply_and_update_path(adev->audio_route, SILENCE_MIXER_PATH);
 
     if (open_silence_stream() == 0) {
@@ -181,11 +230,11 @@
 {
     struct audio_device * adev = (struct audio_device *)ka.userdata;
 
+    pthread_mutex_lock(&ka.lock);
+
     if (ka.state == STATE_DEINIT)
         return;
 
-    pthread_mutex_lock(&ka.lock);
-
     if (ka.state == STATE_IDLE)
         goto exit;
 
@@ -211,7 +260,7 @@
     char value[32];
     int ret;
 
-    ret = str_parms_get_str(parms, "connect", value, sizeof(value));
+    ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
     if (ret >= 0) {
         int val = atoi(value);
         if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
@@ -237,12 +286,10 @@
 
 static void * keep_alive_loop(void * context __unused)
 {
-    struct audio_device *adev = (struct audio_device *)ka.userdata;
     struct keep_alive_cmd *cmd = NULL;
     struct listnode *item;
     uint8_t * silence = NULL;
-    int32_t bytes = 0, count = 0, i;
-    struct stream_out * p_out = NULL;
+    int32_t bytes = 0;
 
     while (true) {
         pthread_mutex_lock(&ka.lock);
diff --git a/hal/audio_extn/passthru.c b/hal/audio_extn/passthru.c
index d87303b..e6ac4dd 100644
--- a/hal/audio_extn/passthru.c
+++ b/hal/audio_extn/passthru.c
@@ -37,10 +37,14 @@
 #include "audio_extn.h"
 #include "platform_api.h"
 #include <platform.h>
+#include <cutils/properties.h>
+
+#include "sound/compress_params.h"
 
 static const audio_format_t audio_passthru_formats[] = {
     AUDIO_FORMAT_AC3,
     AUDIO_FORMAT_E_AC3,
+    AUDIO_FORMAT_E_AC3_JOC,
     AUDIO_FORMAT_DTS,
     AUDIO_FORMAT_DTS_HD
 };
@@ -63,9 +67,11 @@
 
     for (i = 0; i < num_passthru_formats; i++) {
         if (format == audio_passthru_formats[i]) {
+            ALOGD("%s : pass through format is true", __func__);
             return true;
         }
     }
+    ALOGD("%s : pass through format is false", __func__);
     return false;
 }
 
@@ -76,11 +82,6 @@
  */
 bool audio_extn_passthru_should_drop_data(struct stream_out * out)
 {
-    /* Make this product specific */
-    if (!(out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
-        ALOGI("drop data as end device 0x%x is unsupported", out->devices);
-        return true;
-    }
 
     if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
         if (android_atomic_acquire_load(&compress_passthru_active) > 0) {
@@ -158,8 +159,6 @@
 {
     if (android_atomic_acquire_load(&compress_passthru_active) == 0)
         return;
-
-    android_atomic_dec(&compress_passthru_active);
 }
 
 int audio_extn_passthru_set_parameters(struct audio_device *adev __unused,
@@ -183,3 +182,143 @@
 {
     return true;
 }
+
+bool audio_extn_passthru_is_convert_supported(struct audio_device *adev,
+                                                 struct stream_out *out)
+{
+
+    bool convert = false;
+    switch (out->format) {
+    case AUDIO_FORMAT_E_AC3:
+    case AUDIO_FORMAT_E_AC3_JOC:
+    case AUDIO_FORMAT_DTS_HD:
+        if (!platform_is_edid_supported_format(adev->platform,
+            out->format)) {
+            ALOGD("%s:PASSTHROUGH_CONVERT supported", __func__);
+            convert = true;
+        }
+        break;
+    default:
+        ALOGD("%s: PASSTHROUGH_CONVERT not supported for format 0x%x",
+              __func__, out->format);
+        break;
+    }
+    ALOGD("%s: convert %d", __func__, convert);
+    return convert;
+}
+
+bool audio_extn_passthru_is_passt_supported(struct audio_device *adev,
+                                         struct stream_out *out)
+{
+    bool passt = false;
+    switch (out->format) {
+    case AUDIO_FORMAT_E_AC3:
+        if (platform_is_edid_supported_format(adev->platform, out->format)) {
+            ALOGV("%s:PASSTHROUGH supported for format %x",
+                   __func__, out->format);
+            passt = true;
+        }
+        break;
+    case AUDIO_FORMAT_AC3:
+        if (platform_is_edid_supported_format(adev->platform, AUDIO_FORMAT_AC3)
+            || platform_is_edid_supported_format(adev->platform,
+            AUDIO_FORMAT_E_AC3)) {
+            ALOGV("%s:PASSTHROUGH supported for format %x",
+                   __func__, out->format);
+            passt = true;
+        }
+        break;
+    case AUDIO_FORMAT_E_AC3_JOC:
+         /* Check for DDP capability in edid for JOC contents.*/
+         if (platform_is_edid_supported_format(adev->platform,
+             AUDIO_FORMAT_E_AC3)) {
+             ALOGV("%s:PASSTHROUGH supported for format %x",
+                   __func__, out->format);
+             passt = true;
+         }
+         break;
+    case AUDIO_FORMAT_DTS:
+        if (platform_is_edid_supported_format(adev->platform, AUDIO_FORMAT_DTS)
+            || platform_is_edid_supported_format(adev->platform,
+            AUDIO_FORMAT_DTS_HD)) {
+            ALOGV("%s:PASSTHROUGH supported for format %x",
+                   __func__, out->format);
+            passt = true;
+        }
+        break;
+    case AUDIO_FORMAT_DTS_HD:
+        if (platform_is_edid_supported_format(adev->platform, out->format)) {
+            ALOGV("%s:PASSTHROUGH supported for format %x",
+                   __func__, out->format);
+            passt = true;
+        }
+        break;
+    default:
+        ALOGV("%s:Passthrough not supported", __func__);
+    }
+    return passt;
+}
+
+void audio_extn_passthru_update_stream_configuration(
+        struct audio_device *adev, struct stream_out *out)
+{
+    if (audio_extn_passthru_is_passt_supported(adev, out)) {
+        ALOGV("%s:PASSTHROUGH", __func__);
+        out->compr_config.codec->compr_passthr = PASSTHROUGH;
+    } else if (audio_extn_passthru_is_convert_supported(adev, out)){
+        ALOGV("%s:PASSTHROUGH CONVERT", __func__);
+        out->compr_config.codec->compr_passthr = PASSTHROUGH_CONVERT;
+    } else {
+        ALOGV("%s:NO PASSTHROUGH", __func__);
+        out->compr_config.codec->compr_passthr = LEGACY_PCM;
+    }
+}
+
+bool audio_extn_passthru_is_passthrough_stream(struct stream_out *out)
+{
+    //check passthrough system property
+    if (!property_get_bool("audio.offload.passthrough", false)) {
+        return false;
+    }
+
+    //check supported device, currently only on HDMI.
+    if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
+        //passthrough flag
+        if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH)
+            return true;
+        //direct flag, check supported formats.
+        if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT) {
+            if (audio_extn_passthru_is_supported_format(out->format)) {
+                if (platform_is_edid_supported_format(out->dev->platform,
+                        out->format)) {
+                    ALOGV("%s : return true",__func__);
+                    return true;
+                } else if (audio_extn_is_dolby_format(out->format) &&
+                            platform_is_edid_supported_format(out->dev->platform,
+                                AUDIO_FORMAT_AC3)){
+                    //return true for EAC3/EAC3_JOC formats
+                    //if sink supports only AC3
+                    ALOGV("%s : return true",__func__);
+                    return true;
+                }
+            }
+        }
+    }
+    ALOGV("%s : return false",__func__);
+    return false;
+}
+
+int audio_extn_passthru_get_buffer_size(audio_offload_info_t* info)
+{
+    return platform_get_compress_passthrough_buffer_size(info);
+}
+
+int audio_extn_passthru_set_volume(struct stream_out *out,  int mute)
+{
+    return platform_set_device_params(out, DEVICE_PARAM_MUTE_ID, mute);
+}
+
+int audio_extn_passthru_set_latency(struct stream_out *out, int latency)
+{
+    return platform_set_device_params(out, DEVICE_PARAM_LATENCY_ID, latency);
+}
diff --git a/hal/audio_extn/usb.c b/hal/audio_extn/usb.c
index 13e3138..da80422 100644
--- a/hal/audio_extn/usb.c
+++ b/hal/audio_extn/usb.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013, 2016, The Linux Foundation. All rights reserved.
  * Not a Contribution.
  *
  * Copyright (C) 2013 The Android Open Source Project
@@ -29,151 +29,296 @@
 #include <sys/ioctl.h>
 #include <fcntl.h>
 #include <sys/stat.h>
-
 #include <system/audio.h>
 #include <tinyalsa/asoundlib.h>
+#include <audio_hw.h>
+#include <cutils/properties.h>
+#include <ctype.h>
+#include <math.h>
 
 #ifdef USB_HEADSET_ENABLED
-#define USB_LOW_LATENCY_OUTPUT_PERIOD_SIZE   512
-#define USB_LOW_LATENCY_OUTPUT_PERIOD_COUNT  8
-#define USB_DEFAULT_OUTPUT_SAMPLING_RATE     48000
+#define USB_BUFF_SIZE           2048
+#define CHANNEL_NUMBER_STR      "Channels: "
+#define PLAYBACK_PROFILE_STR    "Playback:"
+#define CAPTURE_PROFILE_STR     "Capture:"
+#define USB_SIDETONE_GAIN_STR   "usb_sidetone_gain"
+#define ABS_SUB(A, B) (((A) > (B)) ? ((A) - (B)):((B) - (A)))
+#define SAMPLE_RATE_8000          8000
+#define SAMPLE_RATE_11025         11025
+// Supported sample rates for USB
+static uint32_t supported_sample_rates[] =
+    {44100, 48000, 64000, 88200, 96000, 176400, 192000};
 
-#define USB_PROXY_DEFAULT_SAMPLING_RATE      48000
-#define USB_PROXY_OPEN_RETRY_COUNT           100
-#define USB_PROXY_OPEN_WAIT_TIME             20
-#define USB_PROXY_PERIOD_SIZE                3072
-#define USB_PROXY_RATE_8000                  8000
-#define USB_PROXY_RATE_16000                 16000
-#define USB_PROXY_RATE_48000                 48000
-#define USB_PERIOD_SIZE                      2048
-#define USB_BUFF_SIZE                        2048
-#define AFE_PROXY_PERIOD_COUNT               32
-#define AFE_PROXY_PLAYBACK_DEVICE            8
-#define AFE_PROXY_CAPTURE_DEVICE             7
+#define  MAX_SAMPLE_RATE_SIZE  sizeof(supported_sample_rates)/sizeof(supported_sample_rates[0])
+
+enum usb_usecase_type{
+    USB_PLAYBACK = 0,
+    USB_CAPTURE,
+};
+
+enum {
+    USB_SIDETONE_ENABLE_INDEX = 0,
+    USB_SIDETONE_VOLUME_INDEX,
+    USB_SIDETONE_MAX_INDEX,
+};
+
+struct usb_device_config {
+    struct listnode list;
+    unsigned int bit_width;
+    unsigned int channels;
+    unsigned int rate_size;
+    unsigned int rates[MAX_SAMPLE_RATE_SIZE];
+};
+
+struct usb_card_config {
+    struct listnode list;
+    audio_devices_t usb_device_type;
+    int usb_card;
+    struct listnode usb_device_conf_list;
+    struct mixer *usb_snd_mixer;
+    int usb_sidetone_index[USB_SIDETONE_MAX_INDEX];
+    int usb_sidetone_vol_min;
+    int usb_sidetone_vol_max;
+};
 
 struct usb_module {
-    uint32_t usb_card;
-    uint32_t proxy_card;
-    uint32_t usb_device_id;
-    uint32_t proxy_device_id;
-
-    int32_t channels_playback;
-    int32_t sample_rate_playback;
-    int32_t channels_record;
-    int32_t sample_rate_record;
-
-    bool is_playback_running;
-    bool is_record_running;
-
-    pthread_t usb_playback_thr;
-    pthread_t usb_record_thr;
-    pthread_mutex_t usb_playback_lock;
-    pthread_mutex_t usb_record_lock;
-
-    struct pcm *proxy_pcm_playback_handle;
-    struct pcm *usb_pcm_playback_handle;
-    struct pcm *proxy_pcm_record_handle;
-    struct pcm *usb_pcm_record_handle;
+    struct listnode usb_card_conf_list;
     struct audio_device *adev;
+    int sidetone_gain;
 };
 
 static struct usb_module *usbmod = NULL;
-static pthread_once_t alloc_usbmod_once_ctl = PTHREAD_ONCE_INIT;
+static bool usb_audio_debug_enable = false;
+static int usb_sidetone_gain = 0;
 
-struct pcm_config pcm_config_usbmod = {
-    .channels = 2,
-    .rate = USB_DEFAULT_OUTPUT_SAMPLING_RATE,
-    .period_size = USB_LOW_LATENCY_OUTPUT_PERIOD_SIZE,
-    .period_count = USB_LOW_LATENCY_OUTPUT_PERIOD_COUNT,
-    .format = PCM_FORMAT_S16_LE,
-    .start_threshold = USB_LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
-    .stop_threshold = INT_MAX,
-    .avail_min = USB_LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
+static const char * const usb_sidetone_enable_str[] = {
+    "Sidetone Playback Switch",
+    "Mic Playback Switchs",
 };
 
-static void usb_alloc()
+static const char * const usb_sidetone_volume_str[] = {
+    "Sidetone Playback Volume",
+    "Mic Playback Volume",
+};
+
+static void usb_mixer_print_enum(struct mixer_ctl *ctl)
 {
-    usbmod = calloc(1, sizeof(struct usb_module));
-}
+    unsigned int num_enums;
+    unsigned int i;
+    const char *string;
 
-// Some USB audio accessories have a really low default volume set. Look for a suitable
-// volume control and set the volume to default volume level.
-static void initPlaybackVolume() {
-    ALOGD("initPlaybackVolume");
-    struct mixer *usbMixer = mixer_open(1);
+    num_enums = mixer_ctl_get_num_enums(ctl);
 
-    if (usbMixer) {
-         struct mixer_ctl *ctl = NULL;
-         unsigned int usbPlaybackVolume;
-         unsigned int i;
-         unsigned int num_ctls = mixer_get_num_ctls(usbMixer);
-
-         // Look for the first control named ".*Playback Volume" that isn't for a microphone
-         for (i = 0; i < num_ctls; i++) {
-             ctl = mixer_get_ctl(usbMixer, i);
-             if ((ctl) && (strstr((const char *)mixer_ctl_get_name(ctl), "Playback Volume") &&
-                 !strstr((const char *)mixer_ctl_get_name(ctl), "Mic"))) {
-                   break;
-             }
-         }
-         if (ctl != NULL) {
-            ALOGD("Found a volume control for USB: %s", mixer_ctl_get_name(ctl) );
-            usbPlaybackVolume = mixer_ctl_get_value(ctl, 0);
-            ALOGD("Value got from mixer_ctl_get is:%u", usbPlaybackVolume);
-            if (mixer_ctl_set_value(ctl,0,usbPlaybackVolume) < 0) {
-               ALOGE("Failed to set volume; default volume might be used");
-            }
-         } else {
-            ALOGE("No playback volume control found; default volume will be used");
-         }
-         mixer_close(usbMixer);
-    } else {
-         ALOGE("Failed to open mixer for card 1");
+    for (i = 0; i < num_enums; i++) {
+        string = mixer_ctl_get_enum_string(ctl, i);
+        ALOGI("\t%s%s", mixer_ctl_get_value(ctl, 0) == (int)i ? ">" : "", string);
     }
 }
 
-static int usb_get_numof_rates(char *rates_str)
+static void usb_soundcard_detail_control(struct mixer *mixer, const char *control)
 {
-    int i, size = 0;
+    struct mixer_ctl *ctl;
+    enum mixer_ctl_type type;
+    unsigned int num_values;
+    unsigned int i;
+    int min, max;
+
+    if (isdigit(control[0]))
+        ctl = mixer_get_ctl(mixer, atoi(control));
+    else
+        ctl = mixer_get_ctl_by_name(mixer, control);
+
+    if (!ctl) {
+        fprintf(stderr, "Invalid mixer control\n");
+        return;
+    }
+
+    type = mixer_ctl_get_type(ctl);
+    num_values = mixer_ctl_get_num_values(ctl);
+
+    ALOGI("%s:", mixer_ctl_get_name(ctl));
+
+    for (i = 0; i < num_values; i++) {
+        switch (type) {
+            case MIXER_CTL_TYPE_INT:
+                ALOGI(" %d", mixer_ctl_get_value(ctl, i));
+                break;
+            case MIXER_CTL_TYPE_BOOL:
+                ALOGI(" %s", mixer_ctl_get_value(ctl, i) ? "On" : "Off");
+                break;
+            case MIXER_CTL_TYPE_ENUM:
+                usb_mixer_print_enum(ctl);
+                break;
+            case MIXER_CTL_TYPE_BYTE:
+                ALOGI(" 0x%02x", mixer_ctl_get_value(ctl, i));
+                break;
+            default:
+                ALOGI(" unknown");
+                break;
+        }
+    }
+
+    if (type == MIXER_CTL_TYPE_INT) {
+        min = mixer_ctl_get_range_min(ctl);
+        max = mixer_ctl_get_range_max(ctl);
+        ALOGI(" (range %d->%d)", min, max);
+    }
+}
+
+static void usb_soundcard_list_controls(struct mixer *mixer)
+{
+    struct mixer_ctl *ctl;
+    const char *name, *type;
+    unsigned int num_ctls, num_values;
+    unsigned int i;
+
+    num_ctls = mixer_get_num_ctls(mixer);
+
+    ALOGI("Number of controls: %d\n", num_ctls);
+
+    ALOGI("ctl\ttype\tnum\t%-40s value\n", "name");
+    for (i = 0; i < num_ctls; i++) {
+        ctl = mixer_get_ctl(mixer, i);
+        if (ctl != NULL) {
+            name = mixer_ctl_get_name(ctl);
+            type = mixer_ctl_get_type_string(ctl);
+            num_values = mixer_ctl_get_num_values(ctl);
+            ALOGI("%d\t%s\t%d\t%-40s", i, type, num_values, name);
+            if (name != NULL)
+                usb_soundcard_detail_control(mixer, name);
+        }
+    }
+}
+
+static int usb_set_channel_mixer_ctl(int channel,
+                                     char *ch_mixer_ctl_name)
+{
+    struct mixer_ctl *ctl;
+
+    ctl = mixer_get_ctl_by_name(usbmod->adev->mixer, ch_mixer_ctl_name);
+    if (!ctl) {
+       ALOGE("%s: Could not get ctl for mixer cmd - %s",
+             __func__, ch_mixer_ctl_name);
+       return -EINVAL;
+    }
+    switch (channel) {
+       case 1:
+           mixer_ctl_set_enum_by_string(ctl, "One");
+           break;
+       case 2:
+           mixer_ctl_set_enum_by_string(ctl, "Two");
+           break;
+       default:
+           ALOGV("%s: channel(%d) not supported, set as default 2 channels",
+                 __func__, channel);
+           mixer_ctl_set_enum_by_string(ctl, "Two");
+           break;
+    }
+    return 0;
+}
+
+static int usb_set_dev_id_mixer_ctl(unsigned int usb_usecase_type, int card,
+                                    char *dev_mixer_ctl_name)
+{
+    struct mixer_ctl *ctl;
+    unsigned int dev_token;
+    unsigned int pcm_device_number = 0;
+
+    /*
+     * usb_dev_token_id is 32 bit number and is defined as below:
+     * usb_sound_card_idx(31:16) | usb PCM device ID(15:8) | usb_usecase_type(7:0)
+     */
+    dev_token = (card << 16 ) |
+                (pcm_device_number << 8) | (usb_usecase_type & 0xFF);
+
+    ctl = mixer_get_ctl_by_name(usbmod->adev->mixer, dev_mixer_ctl_name);
+    if (!ctl) {
+       ALOGE("%s: Could not get ctl for mixer cmd - %s",
+             __func__, dev_mixer_ctl_name);
+       return -EINVAL;
+    }
+    mixer_ctl_set_value(ctl, 0, dev_token);
+
+    return 0;
+}
+
+static int usb_get_sample_rates(char *rates_str,
+                                struct usb_device_config *config)
+{
+    uint32_t i;
     char *next_sr_string, *temp_ptr;
-    next_sr_string = strtok_r(rates_str, " ,", &temp_ptr);
+    uint32_t sr, min_sr, max_sr, sr_size = 0;
 
-    if (next_sr_string == NULL) {
-        ALOGE("%s: get_numof_rates: could not find rates string", __func__);
-        return 0;
-    }
-
-    for (i = 1; next_sr_string != NULL; i++) {
-        size ++;
+    /* Sample rate string can be in any of the folloing two bit_widthes:
+     * Rates: 8000 - 48000 (continuous)
+     * Rates: 8000, 44100, 48000
+     * Support both the bit_widths
+     */
+    ALOGV("%s: rates_str %s", __func__, rates_str);
+    if (strstr(rates_str, "continuous") != NULL) {
+        next_sr_string = strtok_r(rates_str, " ,", &temp_ptr);
+        if (next_sr_string == NULL) {
+            ALOGE("%s: could not find min rates string", __func__);
+            return -EINVAL;
+        }
+        min_sr = atoi(next_sr_string);
         next_sr_string = strtok_r(NULL, " ,.-", &temp_ptr);
+        if (next_sr_string == NULL) {
+            ALOGE("%s: could not find max rates string", __func__);
+            return -EINVAL;
+        }
+        max_sr = atoi(next_sr_string);
+
+        for (i = 0; i < MAX_SAMPLE_RATE_SIZE; i++)
+            if (supported_sample_rates[i] >= min_sr &&
+                supported_sample_rates[i] <= max_sr)
+                config->rates[sr_size++] = supported_sample_rates[i];
+    } else {
+        next_sr_string = strtok_r(rates_str, " ,", &temp_ptr);
+        if (next_sr_string == NULL) {
+            ALOGE("%s: get_numof_rates: could not find rates string", __func__);
+            return -EINVAL;
+        }
+        do {
+            sr = (uint32_t)atoi(next_sr_string);
+            for (i = 0; i < MAX_SAMPLE_RATE_SIZE; i++) {
+                if (supported_sample_rates[i] == sr) {
+                    ALOGI_IF(usb_audio_debug_enable,
+                        "%s: sr %d, supported_sample_rates[%d] %d -> matches!!",
+                        __func__, sr, i, supported_sample_rates[i]);
+                    config->rates[sr_size++] = supported_sample_rates[i];
+                }
+            }
+            next_sr_string = strtok_r(NULL, " ,.-", &temp_ptr);
+        } while (next_sr_string != NULL);
     }
-    return size;
+    config->rate_size = sr_size;
+    return 0;
 }
 
-static int usb_get_capability(char *type, int32_t *channels,
-                                    int32_t *sample_rate)
+static int usb_get_capability(int type,
+                              struct usb_card_config *usb_card_info,
+                              int card)
 {
-    ALOGD("%s: for %s", __func__, type);
-    long unsigned file_size;
-    FILE *fp;
-    char *buffer;
     int32_t err = 1;
     int32_t size = 0;
-    int32_t fd=-1, i, channels_playback;
-    char *str_start, *channel_start, *rates_str_start, *next_sr_str,
-         *next_sr_string, *temp_ptr;
-    struct stat st;
+    int32_t fd=-1;
+    int32_t altset_index = 1;
+    int32_t channels_no;
+    char *str_start, *channel_start, *bit_width_start, *rates_str_start,
+         *target;
     char *read_buf = NULL;
     char *rates_str = NULL;
-    char *rates_str_for_val = NULL;
-    int  *rates_supported = NULL;
-    char path[128];
+    char path[128], altset[9];
     int ret = 0;
+    char *bit_width_str = NULL;
+    struct usb_device_config * usb_device_info;
 
-    memset(&st, 0x0, sizeof(struct stat));
-    *sample_rate = 0;
+    ALOGV("%s: for %s", __func__, (type == USB_PLAYBACK) ?
+          PLAYBACK_PROFILE_STR : CAPTURE_PROFILE_STR);
+
     snprintf(path, sizeof(path), "/proc/asound/card%u/stream0",
-             usbmod->usb_card);
+             card);
 
     fd = open(path, O_RDONLY);
     if (fd <0) {
@@ -183,15 +328,6 @@
         goto done;
     }
 
-    if (fstat(fd, &st) < 0) {
-        ALOGE("%s: error failed to stat %s error %d\n",
-             __func__, path, errno);
-        ret = -EINVAL;
-        goto done;
-    }
-
-    file_size = st.st_size;
-
     read_buf = (char *)calloc(1, USB_BUFF_SIZE + 1);
 
     if (!read_buf) {
@@ -201,530 +337,707 @@
     }
 
     err = read(fd, read_buf, USB_BUFF_SIZE);
-    str_start = strstr(read_buf, type);
+    str_start = strstr(read_buf, ((type == USB_PLAYBACK) ?
+                       PLAYBACK_PROFILE_STR : CAPTURE_PROFILE_STR));
     if (str_start == NULL) {
         ALOGE("%s: error %s section not found in usb config file",
-               __func__, type);
+               __func__, ((type == USB_PLAYBACK) ?
+               PLAYBACK_PROFILE_STR : CAPTURE_PROFILE_STR));
         ret = -EINVAL;
         goto done;
     }
+    ALOGV("%s: usb_config = %s\n", __func__, str_start);
 
-    channel_start = strstr(str_start, "Channels:");
-    if (channel_start == NULL) {
-        ALOGE("%s: error could not find Channels information", __func__);
-        ret = -EINVAL;
-        goto done;
-    }
-
-    channel_start = strstr(channel_start, " ");
-    if (channel_start == NULL) {
-        ALOGE("%s: error channel section not found in usb config file",
-               __func__);
-        ret = -EINVAL;
-        goto done;
-    }
-
-    channels_playback = atoi(channel_start);
-    if (channels_playback == 1) {
-        *channels = 1;
-    } else {
-        *channels = 2;
-    }
-
-    ALOGD("%s: channels supported by device: %d", __func__, *channels);
-    rates_str_start = strstr(str_start, "Rates:");
-    if (rates_str_start == NULL) {
-        ALOGE("%s: error cant find rates information", __func__);
-        ret = -EINVAL;
-        goto done;
-    }
-
-    rates_str_start = strstr(rates_str_start, " ");
-    if (rates_str_start == NULL) {
-        ALOGE("%s: error channel section not found in usb config file",
-               __func__);
-        ret = -EINVAL;
-        goto done;
-    }
-
-    char *target = strchr(rates_str_start, '\n');
-    if (target == NULL) {
-        ALOGE("%s: error end of line not found", __func__);
-        ret = -EINVAL;
-        goto done;
-    }
-
-    size = target - rates_str_start;
-    if ((rates_str = (char *)malloc(size + 1)) == NULL) {
-        ALOGE("%s: error unable to allocate memory to hold sample rate strings",
-              __func__);
-        ret = -EINVAL;
-        goto done;
-    }
-
-    if ((rates_str_for_val = (char *)malloc(size + 1)) == NULL) {
-        ALOGE("%s: error unable to allocate memory to hold sample rate string",
-               __func__);
-        ret = -EINVAL;
-        goto done;
-    }
-
-    memcpy(rates_str, rates_str_start, size);
-    memcpy(rates_str_for_val, rates_str_start, size);
-    rates_str[size] = '\0';
-    rates_str_for_val[size] = '\0';
-
-    size = usb_get_numof_rates(rates_str);
-    if (!size) {
-        ALOGE("%s: error could not get rate size, returning", __func__);
-        ret = -EINVAL;
-        goto done;
-    }
-
-    rates_supported = (int *)malloc(sizeof(int) * size);
-
-    if (!rates_supported) {
-        ALOGE("couldn't allocate mem for rates_supported");
-        ret = -EINVAL;
-        goto done;
-    }
-
-    next_sr_string = strtok_r(rates_str_for_val, " ,", &temp_ptr);
-    if (next_sr_string == NULL) {
-        ALOGE("%s: error could not get first rate val", __func__);
-        ret = -EINVAL;
-        goto done;
-    }
-
-    rates_supported[0] = atoi(next_sr_string);
-    ALOGD("%s: rates_supported[0] for playback: %d",
-           __func__, rates_supported[0]);
-    for (i = 1; i<size; i++) {
-        next_sr_string = strtok_r(NULL, " ,.-", &temp_ptr);
-        if (next_sr_string == NULL) {
-            rates_supported[i] = -1; // fill in an invalid sr for the rest
+    while (str_start != NULL) {
+        sprintf(altset, "Altset %d", altset_index);
+        ALOGV("%s: altset_index %d\n", __func__, altset_index);
+        str_start = strstr(str_start, altset);
+        if (str_start == NULL) {
+            if (altset_index == 1) {
+                ALOGE("%s: error %s section not found in usb config file",
+                       __func__, (type == USB_PLAYBACK) ?
+                      PLAYBACK_PROFILE_STR : CAPTURE_PROFILE_STR);
+                ret = -EINVAL;
+            }
+            break;
+        }
+        usb_device_info = calloc(1, sizeof(struct usb_device_config));
+        if (usb_device_info == NULL) {
+            ALOGE("%s: error unable to allocate memory",
+                  __func__);
+            ret = -ENOMEM;
+            break;
+        }
+        altset_index++;
+        /* Bit bit_width parsing */
+        bit_width_start = strstr(str_start, "Format: ");
+        if (bit_width_start == NULL) {
+            ALOGI("%s: Could not find bit_width string", __func__);
+            free(usb_device_info);
             continue;
         }
-        rates_supported[i] = atoi(next_sr_string);
-        ALOGD("rates_supported[%d] for playback: %d",i, rates_supported[i]);
-    }
-
-    for (i = 0; i<size; i++) {
-        if ((rates_supported[i] > *sample_rate) &&
-            (rates_supported[i] <= 48000)) {
-            /* Sample Rate should be one of the proxy supported rates only
-               This is because proxy port is used to read from/write to DSP */
-            if ((rates_supported[i] == USB_PROXY_RATE_8000) ||
-                (rates_supported[i] == USB_PROXY_RATE_16000) ||
-                (rates_supported[i] == USB_PROXY_RATE_48000)) {
-                *sample_rate = rates_supported[i];
-            }
+        target = strchr(bit_width_start, '\n');
+        if (target == NULL) {
+            ALOGI("%s:end of line not found", __func__);
+            free(usb_device_info);
+            continue;
         }
+        size = target - bit_width_start;
+        if ((bit_width_str = (char *)malloc(size + 1)) == NULL) {
+            ALOGE("%s: unable to allocate memory to hold bit width strings",
+                  __func__);
+            ret = -EINVAL;
+            free(usb_device_info);
+            break;
+        }
+        memcpy(bit_width_str, bit_width_start, size);
+        bit_width_str[size] = '\0';
+        if (strstr(bit_width_str, "S16_LE"))
+            usb_device_info->bit_width = 16;
+        else if (strstr(bit_width_str, "S24_LE"))
+            usb_device_info->bit_width = 24;
+        else if (strstr(bit_width_str, "S24_3LE"))
+            usb_device_info->bit_width = 24;
+        else if (strstr(bit_width_str, "S32_LE"))
+            usb_device_info->bit_width = 32;
+
+        if (bit_width_str)
+            free(bit_width_str);
+
+        /* channels parsing */
+        channel_start = strstr(str_start, CHANNEL_NUMBER_STR);
+        if (channel_start == NULL) {
+            ALOGI("%s: could not find Channels string", __func__);
+            free(usb_device_info);
+            continue;
+        }
+        channels_no = atoi(channel_start + strlen(CHANNEL_NUMBER_STR));
+        usb_device_info->channels =  channels_no;
+
+        /* Sample rates parsing */
+        rates_str_start = strstr(str_start, "Rates: ");
+        if (rates_str_start == NULL) {
+            ALOGI("%s: cant find rates string", __func__);
+            free(usb_device_info);
+            continue;
+        }
+        target = strchr(rates_str_start, '\n');
+        if (target == NULL) {
+            ALOGI("%s: end of line not found", __func__);
+            free(usb_device_info);
+            continue;
+        }
+        size = target - rates_str_start;
+        if ((rates_str = (char *)malloc(size + 1)) == NULL) {
+            ALOGE("%s: unable to allocate memory to hold sample rate strings",
+                  __func__);
+            ret = -EINVAL;
+            free(usb_device_info);
+            break;
+        }
+        memcpy(rates_str, rates_str_start, size);
+        rates_str[size] = '\0';
+        ret = usb_get_sample_rates(rates_str, usb_device_info);
+        if (rates_str)
+            free(rates_str);
+        if (ret < 0) {
+            ALOGI("%s: error unable to get sample rate values",
+                  __func__);
+            free(usb_device_info);
+            continue;
+        }
+        /* Add to list if every field is valid */
+        list_add_tail(&usb_card_info->usb_device_conf_list,
+                      &usb_device_info->list);
     }
-    ALOGD("%s: sample_rate: %d", __func__, *sample_rate);
 
 done:
     if (fd >= 0) close(fd);
-    if (rates_str_for_val) free(rates_str_for_val);
-    if (rates_str) free(rates_str);
-    if (rates_supported) free(rates_supported);
     if (read_buf) free(read_buf);
     return ret;
 }
 
-static int32_t usb_playback_entry(void *adev)
+static int usb_get_device_pb_config(struct usb_card_config *usb_card_info,
+                                    int card)
 {
-    unsigned char usbbuf[USB_PROXY_PERIOD_SIZE] = {0};
-    int32_t ret, bytes, proxy_open_retry_count;
-
-    ALOGD("%s: entry", __func__);
-    /* update audio device pointer */
-    usbmod->adev = (struct audio_device*)adev;
-    proxy_open_retry_count = USB_PROXY_OPEN_RETRY_COUNT;
+    int ret;
+    struct listnode *node_d;
+    struct usb_device_config *dev_info;
 
     /* get capabilities */
-    pthread_mutex_lock(&usbmod->usb_playback_lock);
-    ret = usb_get_capability((char *)"Playback:",
-            &usbmod->channels_playback, &usbmod->sample_rate_playback);
-    if (ret) {
-        ALOGE("%s: could not get playback capabilities from usb device",
+    if ((ret = usb_get_capability(USB_PLAYBACK, usb_card_info, card))) {
+        ALOGE("%s: could not get Playback capabilities from usb device",
                __func__);
-        pthread_mutex_unlock(&usbmod->usb_playback_lock);
-        return -EINVAL;
+        goto exit;
     }
-    /* update config for usb
-       1 pcm frame(sample)= 4 bytes since two channels*/
-    pcm_config_usbmod.period_size = USB_PERIOD_SIZE/4;
-    pcm_config_usbmod.channels = usbmod->channels_playback;
-    pcm_config_usbmod.rate = usbmod->sample_rate_playback;
-    ALOGV("%s: usb device %u:period %u:channels %u:sample", __func__,
-          pcm_config_usbmod.period_size, pcm_config_usbmod.channels,
-          pcm_config_usbmod.rate);
-
-    usbmod->usb_pcm_playback_handle = pcm_open(usbmod->usb_card, \
-                                    usbmod->usb_device_id, PCM_OUT |
-                                    PCM_MMAP | PCM_NOIRQ , &pcm_config_usbmod);
-
-    if ((usbmod->usb_pcm_playback_handle \
-        && !pcm_is_ready(usbmod->usb_pcm_playback_handle))
-        || (!usbmod->is_playback_running)) {
-        ALOGE("%s: failed: %s", __func__,
-               pcm_get_error(usbmod->usb_pcm_playback_handle));
-        pcm_close(usbmod->usb_pcm_playback_handle);
-        usbmod->usb_pcm_playback_handle = NULL;
-        pthread_mutex_unlock(&usbmod->usb_playback_lock);
-        return -ENOMEM;
-    }
-    ALOGD("%s: USB configured for playback", __func__);
-
-    /* update config for proxy*/
-    pcm_config_usbmod.period_size = USB_PROXY_PERIOD_SIZE/3;
-    pcm_config_usbmod.rate = usbmod->sample_rate_playback;
-    pcm_config_usbmod.channels = usbmod->channels_playback;
-    pcm_config_usbmod.period_count = AFE_PROXY_PERIOD_COUNT;
-    usbmod->proxy_device_id = AFE_PROXY_PLAYBACK_DEVICE;
-    ALOGD("%s: proxy device %u:period %u:channels %u:sample", __func__,
-          pcm_config_usbmod.period_size, pcm_config_usbmod.channels,
-          pcm_config_usbmod.rate);
-
-    while(proxy_open_retry_count){
-        usbmod->proxy_pcm_playback_handle = pcm_open(usbmod->proxy_card,
-                                            usbmod->proxy_device_id, PCM_IN |
-                                     PCM_MMAP | PCM_NOIRQ, &pcm_config_usbmod);
-        if(usbmod->proxy_pcm_playback_handle
-            && !pcm_is_ready(usbmod->proxy_pcm_playback_handle)){
-                     pcm_close(usbmod->proxy_pcm_playback_handle);
-                     proxy_open_retry_count--;
-                     usleep(USB_PROXY_OPEN_WAIT_TIME * 1000);
-                     ALOGE("%s: pcm_open for proxy failed retrying = %d",
-                            __func__, proxy_open_retry_count);
-                }
-                else{
-                  break;
-                }
-    }
-
-    if ((usbmod->proxy_pcm_playback_handle
-        && !pcm_is_ready(usbmod->proxy_pcm_playback_handle))
-        || (!usbmod->is_playback_running)) {
-        ALOGE("%s: failed: %s", __func__,
-               pcm_get_error(usbmod->proxy_pcm_playback_handle));
-        pcm_close(usbmod->proxy_pcm_playback_handle);
-        usbmod->proxy_pcm_playback_handle = NULL;
-        pthread_mutex_unlock(&usbmod->usb_playback_lock);
-        return -ENOMEM;
-    }
-    ALOGD("%s: PROXY configured for playback", __func__);
-    pthread_mutex_unlock(&usbmod->usb_playback_lock);
-
-    ALOGD("Init USB volume");
-    initPlaybackVolume();
-    /* main loop to read from proxy and write to usb */
-    while (usbmod->is_playback_running) {
-        /* read data from proxy */
-        ret = pcm_mmap_read(usbmod->proxy_pcm_playback_handle,
-                                 (void *)usbbuf, USB_PROXY_PERIOD_SIZE);
-        /* Write to usb */
-        ret = pcm_mmap_write(usbmod->usb_pcm_playback_handle,
-                                (void *)usbbuf, USB_PROXY_PERIOD_SIZE);
-        if(!usbmod->is_playback_running)
+    /* Currently only use the first profile using to configure channel for simplification */
+    list_for_each(node_d, &usb_card_info->usb_device_conf_list) {
+        dev_info = node_to_item(node_d, struct usb_device_config, list);
+        if (dev_info != NULL) {
+            usb_set_channel_mixer_ctl(dev_info->channels, "USB_AUDIO_RX Channels");
             break;
-
-        memset(usbbuf, 0, USB_PROXY_PERIOD_SIZE);
-    } /* main loop end */
-
-    ALOGD("%s: exiting USB playback thread",__func__);
-    return 0;
-}
-
-static void* usb_playback_launcher(void *adev)
-{
-    int32_t ret;
-
-    usbmod->is_playback_running = true;
-    ret = usb_playback_entry(adev);
-
-    if (ret) {
-        ALOGE("%s: failed with err:%d", __func__, ret);
-        usbmod->is_playback_running = false;
+        }
     }
-    return NULL;
+    usb_set_dev_id_mixer_ctl(USB_PLAYBACK, card, "USB_AUDIO_RX dev_token");
+
+exit:
+
+    return ret;
 }
 
-static int32_t usb_record_entry(void *adev)
+static int usb_get_device_cap_config(struct usb_card_config *usb_card_info,
+                                      int card)
 {
-    unsigned char usbbuf[USB_PROXY_PERIOD_SIZE] = {0};
-    int32_t ret, bytes, proxy_open_retry_count;
-    ALOGD("%s: entry", __func__);
-
-    /* update audio device pointer */
-    usbmod->adev = (struct audio_device*)adev;
-    proxy_open_retry_count = USB_PROXY_OPEN_RETRY_COUNT;
+    int ret;
+    struct listnode *node_d;
+    struct usb_device_config *dev_info;
 
     /* get capabilities */
-    pthread_mutex_lock(&usbmod->usb_record_lock);
-    ret = usb_get_capability((char *)"Capture:",
-            &usbmod->channels_record, &usbmod->sample_rate_record);
-    if (ret) {
-        ALOGE("%s: could not get capture capabilities from usb device",
+    if ((ret = usb_get_capability(USB_CAPTURE, usb_card_info, card))) {
+        ALOGE("%s: could not get Playback capabilities from usb device",
                __func__);
-        pthread_mutex_unlock(&usbmod->usb_record_lock);
-        return -EINVAL;
+        goto exit;
     }
-    /* update config for usb
-       1 pcm frame(sample)= 4 bytes since two channels*/
-    pcm_config_usbmod.period_size = USB_PERIOD_SIZE/4;
-    pcm_config_usbmod.channels = usbmod->channels_record;
-    pcm_config_usbmod.rate = usbmod->sample_rate_record;
-    ALOGV("%s: usb device %u:period %u:channels %u:sample", __func__,
-          pcm_config_usbmod.period_size, pcm_config_usbmod.channels,
-          pcm_config_usbmod.rate);
-
-    usbmod->usb_pcm_record_handle = pcm_open(usbmod->usb_card, \
-                                    usbmod->usb_device_id, PCM_IN |
-                                    PCM_MMAP | PCM_NOIRQ , &pcm_config_usbmod);
-
-    if ((usbmod->usb_pcm_record_handle \
-        && !pcm_is_ready(usbmod->usb_pcm_record_handle))
-        || (!usbmod->is_record_running)) {
-        ALOGE("%s: failed: %s", __func__,
-               pcm_get_error(usbmod->usb_pcm_record_handle));
-        pcm_close(usbmod->usb_pcm_record_handle);
-        usbmod->usb_pcm_record_handle = NULL;
-        pthread_mutex_unlock(&usbmod->usb_record_lock);
-        return -ENOMEM;
-    }
-    ALOGD("%s: USB configured for capture", __func__);
-
-    /* update config for proxy*/
-    pcm_config_usbmod.period_size = USB_PROXY_PERIOD_SIZE/4;
-    pcm_config_usbmod.rate = usbmod->sample_rate_record;
-    pcm_config_usbmod.channels = usbmod->channels_record;
-    pcm_config_usbmod.period_count = AFE_PROXY_PERIOD_COUNT * 2;
-    usbmod->proxy_device_id = AFE_PROXY_CAPTURE_DEVICE;
-    ALOGV("%s: proxy device %u:period %u:channels %u:sample", __func__,
-          pcm_config_usbmod.period_size, pcm_config_usbmod.channels,
-          pcm_config_usbmod.rate);
-
-    while(proxy_open_retry_count){
-        usbmod->proxy_pcm_record_handle = pcm_open(usbmod->proxy_card,
-                                            usbmod->proxy_device_id, PCM_OUT |
-                                     PCM_MMAP | PCM_NOIRQ, &pcm_config_usbmod);
-        if(usbmod->proxy_pcm_record_handle
-            && !pcm_is_ready(usbmod->proxy_pcm_record_handle)){
-                     pcm_close(usbmod->proxy_pcm_record_handle);
-                     proxy_open_retry_count--;
-                     usleep(USB_PROXY_OPEN_WAIT_TIME * 1000);
-                     ALOGE("%s: pcm_open for proxy(recording) failed retrying = %d",
-                            __func__, proxy_open_retry_count);
-                }
-                else{
-                  break;
-                }
-    }
-    if ((usbmod->proxy_pcm_record_handle
-        && !pcm_is_ready(usbmod->proxy_pcm_record_handle))
-        || (!usbmod->is_record_running)) {
-        ALOGE("%s: failed: %s", __func__,
-               pcm_get_error(usbmod->proxy_pcm_record_handle));
-        pcm_close(usbmod->proxy_pcm_record_handle);
-        usbmod->proxy_pcm_record_handle = NULL;
-        pthread_mutex_unlock(&usbmod->usb_record_lock);
-        return -ENOMEM;
-    }
-    ALOGD("%s: PROXY configured for capture", __func__);
-    pthread_mutex_unlock(&usbmod->usb_record_lock);
-
-    /* main loop to read from usb and write to proxy */
-    while (usbmod->is_record_running) {
-        /* read data from usb */
-        ret = pcm_mmap_read(usbmod->usb_pcm_record_handle,
-                                 (void *)usbbuf, USB_PROXY_PERIOD_SIZE);
-        /* Write to proxy */
-        ret = pcm_mmap_write(usbmod->proxy_pcm_record_handle,
-                                (void *)usbbuf, USB_PROXY_PERIOD_SIZE);
-        if(!usbmod->is_record_running)
+    /* Currently only use the first profile using to configure channel for simplification */
+    list_for_each(node_d, &usb_card_info->usb_device_conf_list) {
+        dev_info = node_to_item(node_d, struct usb_device_config, list);
+        if (dev_info != NULL) {
+            usb_set_channel_mixer_ctl(dev_info->channels, "USB_AUDIO_TX Channels");
             break;
+        }
+    }
+    usb_set_dev_id_mixer_ctl(USB_CAPTURE, card, "USB_AUDIO_TX dev_token");
 
-        memset(usbbuf, 0, USB_PROXY_PERIOD_SIZE);
-    } /* main loop end */
-
-    ALOGD("%s: exiting USB capture thread",__func__);
-    return 0;
+exit:
+    return ret;
 }
 
-static void* usb_capture_launcher(void *adev)
+static void usb_get_sidetone_mixer(struct usb_card_config *usb_card_info)
 {
-    int32_t ret;
+    struct mixer_ctl *ctl;
+    unsigned int index;
 
-    usbmod->is_record_running = true;
-    ret = usb_record_entry(adev);
+    for (index = 0; index < USB_SIDETONE_MAX_INDEX; index++)
+        usb_card_info->usb_sidetone_index[index] = -1;
 
-    if (ret) {
-        ALOGE("%s: failed with err:%d", __func__, ret);
-        usbmod->is_record_running = false;
+    usb_card_info->usb_snd_mixer = mixer_open(usb_card_info->usb_card);
+    for (index = 0;
+         index < sizeof(usb_sidetone_enable_str)/sizeof(usb_sidetone_enable_str[0]);
+         index++) {
+        ctl = mixer_get_ctl_by_name(usb_card_info->usb_snd_mixer,
+                                    usb_sidetone_enable_str[index]);
+        if (ctl) {
+            usb_card_info->usb_sidetone_index[USB_SIDETONE_ENABLE_INDEX] = index;
+            /* Disable device sidetone by default */
+            mixer_ctl_set_value(ctl, 0, false);
+            break;
+        }
     }
-    return NULL;
+    for (index = 0;
+         index < sizeof(usb_sidetone_volume_str)/sizeof(usb_sidetone_volume_str[0]);
+         index++) {
+        ctl = mixer_get_ctl_by_name(usb_card_info->usb_snd_mixer,
+                                    usb_sidetone_volume_str[index]);
+        if (ctl) {
+            usb_card_info->usb_sidetone_index[USB_SIDETONE_VOLUME_INDEX] = index;
+            usb_card_info->usb_sidetone_vol_min = mixer_ctl_get_range_min(ctl);
+            usb_card_info->usb_sidetone_vol_max = mixer_ctl_get_range_max(ctl);
+            break;
+        }
+    }
+
+    if ((usb_card_info->usb_snd_mixer != NULL) && (usb_audio_debug_enable))
+        usb_soundcard_list_controls(usb_card_info->usb_snd_mixer);
+
+    return;
+}
+
+static bool usb_valid_device(int device)
+{
+    bool is_usb_device = false;
+    if ((device & AUDIO_DEVICE_OUT_USB_DEVICE) ||
+        (device & AUDIO_DEVICE_IN_USB_DEVICE))
+        is_usb_device = true;
+    return is_usb_device;
+}
+
+static void usb_print_active_device(void){
+    struct listnode *node_i, *node_j;
+    struct usb_device_config *dev_info;
+    struct usb_card_config *card_info;
+    unsigned int i;
+
+    ALOGI("%s", __func__);
+    list_for_each(node_i, &usbmod->usb_card_conf_list) {
+        card_info = node_to_item(node_i, struct usb_card_config, list);
+        ALOGI("%s: card_dev_type (0x%x), card_no(%d)",
+               __func__,  card_info->usb_device_type, card_info->usb_card);
+        list_for_each(node_j, &card_info->usb_device_conf_list) {
+            dev_info = node_to_item(node_j, struct usb_device_config, list);
+            ALOGI("%s: bit-width(%d) channel(%d)",
+                   __func__, dev_info->bit_width, dev_info->channels);
+            for (i =  0; i < dev_info->rate_size; i++)
+                ALOGI("%s: rate %d", __func__, dev_info->rates[i]);
+        }
+    }
+}
+
+static bool usb_get_best_match_for_bit_width(
+                            struct listnode *dev_list,
+                            unsigned int stream_bit_width,
+                            unsigned int *bit_width)
+{
+    struct listnode *node_i;
+    struct usb_device_config *dev_info;
+    unsigned int candidate = 0;
+
+    list_for_each(node_i, dev_list) {
+        dev_info = node_to_item(node_i, struct usb_device_config, list);
+        ALOGI_IF(usb_audio_debug_enable,
+                 "%s: USB bw(%d), stream bw(%d), candidate(%d)",
+                 __func__, dev_info->bit_width,
+                 stream_bit_width, candidate);
+        if (dev_info->bit_width == stream_bit_width) {
+            *bit_width = dev_info->bit_width;
+            ALOGV("%s: Found match bit-width (%d)",
+                  __func__, dev_info->bit_width);
+            goto exit;
+        } else if (candidate == 0) {
+                candidate = dev_info->bit_width;
+        }
+        /*
+        * If stream bit is 24, USB supports both 16 bit and 32 bit, then
+        *  higher bit width 32 is picked up instead of 16-bit
+        */
+        else if (ABS_SUB(stream_bit_width, dev_info->bit_width) <
+                 ABS_SUB(stream_bit_width, candidate)) {
+            candidate = dev_info->bit_width;
+        }
+        else if ((ABS_SUB(stream_bit_width, dev_info->bit_width) ==
+                  ABS_SUB(stream_bit_width, candidate)) &&
+                 (dev_info->bit_width > candidate)) {
+            candidate = dev_info->bit_width;
+        }
+    }
+    ALOGV("%s: No match found, use the best candidate bw(%d)",
+          __func__, candidate);
+    *bit_width = candidate;
+exit:
+    return true;
+}
+
+static bool usb_get_best_match_for_channels(
+                            struct listnode *dev_list,
+                            unsigned int bit_width,
+                            unsigned int stream_ch,
+                            unsigned int *ch)
+{
+    struct listnode *node_i;
+    struct usb_device_config *dev_info;
+    unsigned int candidate = 0;
+
+    list_for_each(node_i, dev_list) {
+        dev_info = node_to_item(node_i, struct usb_device_config, list);
+        ALOGI_IF(usb_audio_debug_enable,
+                 "%s: USB ch(%d)bw(%d), stream ch(%d)bw(%d), candidate(%d)",
+                 __func__, dev_info->channels, dev_info->bit_width,
+                 stream_ch, bit_width, candidate);
+        if (dev_info->bit_width != bit_width)
+            continue;
+        if (dev_info->channels== stream_ch) {
+            *ch = dev_info->channels;
+            ALOGV("%s: Found match channels (%d)",
+                  __func__, dev_info->channels);
+            goto exit;
+        } else if (candidate == 0)
+                candidate = dev_info->channels;
+            /*
+            * If stream channel is 4, USB supports both 3 and 5, then
+            *  higher channel 5 is picked up instead of 3
+            */
+        else if (ABS_SUB(stream_ch, dev_info->channels) <
+                 ABS_SUB(stream_ch, candidate)) {
+            candidate = dev_info->channels;
+        } else if ((ABS_SUB(stream_ch, dev_info->channels) ==
+                    ABS_SUB(stream_ch, candidate)) &&
+                   (dev_info->channels > candidate)) {
+            candidate = dev_info->channels;
+        }
+    }
+    ALOGV("%s: No match found, use the best candidate ch(%d)",
+          __func__, candidate);
+    *ch = candidate;
+exit:
+    return true;
+
+}
+
+static bool usb_sample_rate_multiple(
+                                     unsigned int stream_sample_rate,
+                                     unsigned int base)
+{
+    return (((stream_sample_rate / base) * base) == stream_sample_rate);
+}
+
+static bool usb_find_sample_rate_candidate(unsigned int base,
+                                           unsigned stream_rate,
+                                           unsigned int usb_rate,
+                                           unsigned int cur_candidate,
+                                           unsigned int *update_candidate)
+{
+    /* For sample rate, we should consider  fracational sample rate as high priority.
+    * For example, if the stream is 88.2kHz and USB device support both 44.1kH and
+    * 48kHz sample rate, we should pick 44.1kHz instead of 48kHz
+    */
+    if (!usb_sample_rate_multiple(cur_candidate, base) &&
+       usb_sample_rate_multiple(usb_rate, base)) {
+        *update_candidate = usb_rate;
+    } else if (usb_sample_rate_multiple(cur_candidate, base) &&
+               usb_sample_rate_multiple(usb_rate, base)) {
+        if (ABS_SUB(stream_rate, usb_rate) <
+            ABS_SUB(stream_rate, cur_candidate)) {
+            *update_candidate = usb_rate;
+        } else if ((ABS_SUB(stream_rate, usb_rate) ==
+                    ABS_SUB(stream_rate, cur_candidate)) &&
+                   (usb_rate > cur_candidate)) {
+            *update_candidate = usb_rate;
+        }
+    } else if (!usb_sample_rate_multiple(cur_candidate, base) &&
+               !usb_sample_rate_multiple(usb_rate, base)) {
+        if (ABS_SUB(stream_rate, usb_rate) <
+            ABS_SUB(stream_rate, cur_candidate)) {
+            *update_candidate = usb_rate;
+        } else if ((ABS_SUB(stream_rate, usb_rate) ==
+                    ABS_SUB(stream_rate, cur_candidate)) &&
+                   (usb_rate > cur_candidate)) {
+            *update_candidate = usb_rate;
+        }
+    }
+    return true;
+}
+
+static bool usb_get_best_match_for_sample_rate(
+                            struct listnode *dev_list,
+                            unsigned int bit_width,
+                            unsigned int ch,
+                            unsigned int stream_sample_rate,
+                            unsigned int *sr)
+{
+    struct listnode *node_i;
+    struct usb_device_config *dev_info;
+    unsigned int candidate = 48000;
+    unsigned int base = SAMPLE_RATE_8000;
+    bool multiple_8k = usb_sample_rate_multiple(stream_sample_rate, base);
+    unsigned int i;
+
+    ALOGV("%s: stm ch(%d)bw(%d)sr(%d), stream sample multiple of 8kHz(%d)",
+        __func__, ch, bit_width, stream_sample_rate, multiple_8k);
+
+    list_for_each(node_i, dev_list) {
+        dev_info = node_to_item(node_i, struct usb_device_config, list);
+        ALOGI_IF(usb_audio_debug_enable,
+                 "%s: USB ch(%d)bw(%d), stm ch(%d)bw(%d)sr(%d), candidate(%d)",
+                 __func__, dev_info->channels, dev_info->bit_width,
+                 ch, bit_width, stream_sample_rate, candidate);
+        if ((dev_info->bit_width != bit_width) && dev_info->channels != ch)
+            continue;
+
+        candidate = 0;
+        for (i = 0; i < dev_info->rate_size; i++) {
+            ALOGI_IF(usb_audio_debug_enable,
+                     "%s: USB ch(%d)bw(%d)sr(%d), stm ch(%d)bw(%d)sr(%d), candidate(%d)",
+                     __func__, dev_info->channels,
+                     dev_info->bit_width, dev_info->rates[i],
+                     ch, bit_width, stream_sample_rate, candidate);
+            if (stream_sample_rate == dev_info->rates[i]) {
+                *sr = dev_info->rates[i];
+                ALOGV("%s: Found match sample rate (%d)",
+                      __func__, dev_info->rates[i]);
+                goto exit;
+            } else if (candidate == 0) {
+                    candidate = dev_info->rates[i];
+                /*
+                * For sample rate, we should consider  fracational sample rate as high priority.
+                * For example, if the stream is 88.2kHz and USB device support both 44.1kH and
+                * 48kHz sample rate, we should pick 44.1kHz instead of 48kHz
+                */
+            } else if (multiple_8k) {
+                usb_find_sample_rate_candidate(SAMPLE_RATE_8000,
+                                               stream_sample_rate,
+                                               dev_info->rates[i],
+                                               candidate,
+                                               &candidate);
+            } else {
+                usb_find_sample_rate_candidate(SAMPLE_RATE_11025,
+                                               stream_sample_rate,
+                                               dev_info->rates[i],
+                                               candidate,
+                                               &candidate);
+            }
+        }
+    }
+    ALOGV("%s: No match found, use the best candidate sr(%d)",
+          __func__, candidate);
+    *sr = candidate;
+exit:
+    return true;
+}
+
+static bool usb_audio_backend_apply_policy(struct listnode *dev_list,
+                                           unsigned int *bit_width,
+                                           unsigned int *sample_rate,
+                                           unsigned int ch)
+{
+    unsigned int channel;
+    bool is_usb_supported = true;
+
+    ALOGV("%s: from stream: bit-width(%d) sample_rate(%d) channels (%d)",
+           __func__, *bit_width, *sample_rate, ch);
+    if (list_empty(dev_list)) {
+        *sample_rate = 48000;
+        *bit_width = 16;
+        channel = 2;
+        ALOGI("%s: list is empty,fall back to default setting", __func__);
+        goto exit;
+    }
+    usb_get_best_match_for_bit_width(dev_list, *bit_width, bit_width);
+    usb_get_best_match_for_channels(dev_list,
+                                    *bit_width,
+                                    ch,
+                                    &channel);
+    usb_get_best_match_for_sample_rate(dev_list,
+                                       *bit_width,
+                                       channel,
+                                       *sample_rate,
+                                       sample_rate);
+exit:
+    ALOGV("%s: Updated sample rate per profile: bit-width(%d) rate(%d) chs(%d)",
+           __func__, *bit_width, *sample_rate, channel);
+    usb_set_channel_mixer_ctl(channel, "USB_AUDIO_RX Channels");
+    return is_usb_supported;
+}
+
+static int usb_get_sidetone_gain(struct usb_card_config *card_info)
+{
+    int gain = card_info->usb_sidetone_vol_min + usbmod->sidetone_gain;
+    if (gain > card_info->usb_sidetone_vol_max)
+        gain = card_info->usb_sidetone_vol_max;
+    return gain;
+}
+
+void audio_extn_usb_set_sidetone_gain(struct str_parms *parms,
+                                char *value, int len)
+{
+    int err;
+
+    err = str_parms_get_str(parms, USB_SIDETONE_GAIN_STR,
+                            value, len);
+    if (err >= 0) {
+        usb_sidetone_gain = pow(10.0, (float)(atoi(value))/10.0);
+        ALOGV("%s: sidetone gain(%s) decimal %d",
+              __func__, value, usb_sidetone_gain);
+        str_parms_del(parms, USB_SIDETONE_GAIN_STR);
+    }
+    return;
+}
+
+int audio_extn_usb_enable_sidetone(int device, bool enable)
+{
+    int ret = -ENODEV;
+    struct listnode *node_i;
+    struct usb_card_config *card_info;
+    int i;
+    ALOGV("%s: card_dev_type (0x%x), sidetone enable(%d)",
+           __func__,  device, enable);
+
+    list_for_each(node_i, &usbmod->usb_card_conf_list) {
+        card_info = node_to_item(node_i, struct usb_card_config, list);
+        ALOGV("%s: card_dev_type (0x%x), card_no(%d)",
+               __func__,  card_info->usb_device_type, card_info->usb_card);
+        if (card_info->usb_device_type == AUDIO_DEVICE_OUT_USB_DEVICE) {
+            if ((i = card_info->usb_sidetone_index[USB_SIDETONE_ENABLE_INDEX]) != -1) {
+                struct mixer_ctl *ctl = mixer_get_ctl_by_name(
+                                card_info->usb_snd_mixer,
+                                usb_sidetone_enable_str[i]);
+                if (ctl)
+                    mixer_ctl_set_value(ctl, 0, enable);
+                else
+                    break;
+
+                if ((i = card_info->usb_sidetone_index[USB_SIDETONE_VOLUME_INDEX]) != -1) {
+                    ctl = mixer_get_ctl_by_name(
+                                card_info->usb_snd_mixer,
+                                usb_sidetone_volume_str[i]);
+                    if (ctl == NULL)
+                        ALOGV("%s: sidetone gain mixer command is not found",
+                               __func__);
+                    else if (enable)
+                        mixer_ctl_set_value(ctl, 0,
+                                            usb_get_sidetone_gain(card_info));
+                }
+                ret = 0;
+                break;
+            }
+        }
+    }
+    return ret;
+}
+
+bool audio_extn_usb_is_config_supported(unsigned int *bit_width,
+                                        unsigned int *sample_rate,
+                                        unsigned int ch)
+{
+    struct listnode *node_i;
+    struct usb_card_config *card_info;
+    bool is_usb_supported = false;
+
+    ALOGV("%s: from stream: bit-width(%d) sample_rate(%d) ch(%d)",
+           __func__, *bit_width, *sample_rate, ch);
+    list_for_each(node_i, &usbmod->usb_card_conf_list) {
+        card_info = node_to_item(node_i, struct usb_card_config, list);
+        ALOGI_IF(usb_audio_debug_enable,
+                 "%s: card_dev_type (0x%x), card_no(%d)",
+                 __func__,  card_info->usb_device_type, card_info->usb_card);
+        /* Currently only apply the first playback sound card configuration */
+        if (card_info->usb_device_type == AUDIO_DEVICE_OUT_USB_DEVICE) {
+            is_usb_supported = usb_audio_backend_apply_policy(
+                                           &card_info->usb_device_conf_list,
+                                           bit_width,
+                                           sample_rate,
+                                           ch);
+            break;
+        }
+    }
+    ALOGV("%s: updated: bit-width(%d) sample_rate(%d)",
+           __func__, *bit_width, *sample_rate);
+
+    return is_usb_supported;
+}
+
+void audio_extn_usb_add_device(audio_devices_t device, int card)
+{
+    struct usb_card_config *usb_card_info;
+    char check_debug_enable[PROPERTY_VALUE_MAX];
+
+    property_get("audio.usb.enable.debug", check_debug_enable, NULL);
+    if (atoi(check_debug_enable)) {
+        usb_audio_debug_enable = true;
+    }
+
+    ALOGI_IF(usb_audio_debug_enable,
+             "%s: parameters device(0x%x), card(%d)",
+             __func__, device, card);
+    if (usbmod == NULL) {
+        ALOGE("%s: USB device object is NULL", __func__);
+        goto exit;
+    }
+
+    if (!(usb_valid_device(device)) || (card < 0)) {
+        ALOGE("%s:device(0x%x), card(%d)",
+              __func__, device, card);
+        goto exit;
+    }
+
+    usb_card_info = calloc(1, sizeof(struct usb_card_config));
+    if (usb_card_info == NULL) {
+        ALOGE("%s: error unable to allocate memory",
+              __func__);
+        goto exit;
+    }
+    list_init(&usb_card_info->usb_device_conf_list);
+    if (device & AUDIO_DEVICE_OUT_USB_DEVICE) {
+        if (!usb_get_device_pb_config(usb_card_info, card)){
+            usb_card_info->usb_card = card;
+            usb_card_info->usb_device_type = AUDIO_DEVICE_OUT_USB_DEVICE;
+            usb_get_sidetone_mixer(usb_card_info);
+            list_add_tail(&usbmod->usb_card_conf_list, &usb_card_info->list);
+            goto exit;
+        }
+    } else if (device & AUDIO_DEVICE_IN_USB_DEVICE) {
+        if (!usb_get_device_cap_config(usb_card_info, card)) {
+            usb_card_info->usb_card = card;
+            usb_card_info->usb_device_type = AUDIO_DEVICE_IN_USB_DEVICE;
+            list_add_tail(&usbmod->usb_card_conf_list, &usb_card_info->list);
+            goto exit;
+        }
+    }
+    /* free memory in error case */
+    if (usb_card_info != NULL)
+        free(usb_card_info);
+exit:
+    if (usb_audio_debug_enable)
+        usb_print_active_device();
+    return;
+}
+
+void audio_extn_usb_remove_device(audio_devices_t device, int card)
+{
+    struct listnode *node_i, *temp_i;
+    struct listnode *node_j, *temp_j;
+    struct usb_device_config *dev_info;
+    struct usb_card_config *card_info;
+    unsigned int i;
+
+    ALOGV("%s: device(0x%x), card(%d)",
+           __func__, device, card);
+
+    if (usbmod == NULL) {
+        ALOGE("%s: USB device object is NULL", __func__);
+        goto exit;
+    }
+
+    if (!(usb_valid_device(device)) || (card < 0)) {
+        ALOGE("%s: Invalid parameters device(0x%x), card(%d)",
+              __func__, device, card);
+        goto exit;
+    }
+    list_for_each_safe(node_i, temp_i, &usbmod->usb_card_conf_list) {
+        card_info = node_to_item(node_i, struct usb_card_config, list);
+        ALOGV("%s: card_dev_type (0x%x), card_no(%d)",
+               __func__,  card_info->usb_device_type, card_info->usb_card);
+        if ((device == card_info->usb_device_type) && (card == card_info->usb_card)){
+            list_for_each_safe(node_j, temp_j, &card_info->usb_device_conf_list) {
+                dev_info = node_to_item(node_j, struct usb_device_config, list);
+                ALOGV("%s: bit-width(%d) channel(%d)",
+                       __func__, dev_info->bit_width, dev_info->channels);
+                for (i =  0; i < dev_info->rate_size; i++)
+                    ALOGV("%s: rate %d", __func__, dev_info->rates[i]);
+
+                list_remove(node_j);
+                free(node_to_item(node_j, struct usb_device_config, list));
+            }
+            list_remove(node_i);
+            free(node_to_item(node_i, struct usb_card_config, list));
+        }
+    }
+exit:
+    if (usb_audio_debug_enable)
+        usb_print_active_device();
+
+    return;
 }
 
 void audio_extn_usb_init(void *adev)
 {
-    pthread_once(&alloc_usbmod_once_ctl, usb_alloc);
-
-    usbmod->is_playback_running = false;
-    usbmod->is_record_running = false;
-
-    usbmod->usb_pcm_playback_handle = NULL;
-    usbmod->proxy_pcm_playback_handle = NULL;
-
-    usbmod->usb_pcm_record_handle = NULL;
-    usbmod->proxy_pcm_record_handle = NULL;
-
-    usbmod->usb_card = 1;
-    usbmod->usb_device_id = 0;
-    usbmod->proxy_card = 0;
-    usbmod->proxy_device_id = AFE_PROXY_PLAYBACK_DEVICE;
+    if (usbmod == NULL) {
+        usbmod = calloc(1, sizeof(struct usb_module));
+        if (usbmod == NULL) {
+            ALOGE("%s: error unable to allocate memory", __func__);
+            goto exit;
+        }
+    }
+    list_init(&usbmod->usb_card_conf_list);
     usbmod->adev = (struct audio_device*)adev;
-
-     pthread_mutex_init(&usbmod->usb_playback_lock,
-                        (const pthread_mutexattr_t *) NULL);
-     pthread_mutex_init(&usbmod->usb_record_lock,
-                        (const pthread_mutexattr_t *) NULL);
+    usbmod->sidetone_gain = usb_sidetone_gain;
+exit:
+    return;
 }
 
-void audio_extn_usb_deinit()
+void audio_extn_usb_deinit(void)
 {
     if (NULL != usbmod){
         free(usbmod);
         usbmod = NULL;
     }
 }
-
-void audio_extn_usb_set_proxy_sound_card(uint32_t sndcard_idx)
-{
-    /* Proxy port and USB headset are related to two different sound cards */
-    if (sndcard_idx == usbmod->usb_card) {
-        usbmod->usb_card = usbmod->proxy_card;
-    }
-
-    usbmod->proxy_card = sndcard_idx;
-}
-
-void audio_extn_usb_start_playback(void *adev)
-{
-    int32_t ret;
-
-    if (NULL == usbmod){
-        ALOGE("%s: USB device object is NULL", __func__);
-        return;
-    }
-
-    if (usbmod->is_playback_running){
-        ALOGE("%s: USB playback thread already running", __func__);
-        return;
-    }
-
-    ALOGD("%s: creating USB playback thread", __func__);
-    ret = pthread_create(&usbmod->usb_playback_thr, NULL,
-                         usb_playback_launcher, (void*)adev);
-    if (ret)
-        ALOGE("%s: failed to create USB playback thread with err:%d",
-              __func__, ret);
-}
-
-void audio_extn_usb_stop_playback()
-{
-    int32_t ret;
-    ALOGD("%s: entry", __func__);
-
-    usbmod->is_playback_running = false;
-    if (NULL != usbmod->proxy_pcm_playback_handle)
-        pcm_stop(usbmod->proxy_pcm_playback_handle);
-
-    if (NULL != usbmod->usb_pcm_playback_handle)
-        pcm_stop(usbmod->usb_pcm_playback_handle);
-
-    if(usbmod->usb_playback_thr) {
-        ret = pthread_join(usbmod->usb_playback_thr,NULL);
-        ALOGE("%s: return for pthread_join = %d", __func__, ret);
-        usbmod->usb_playback_thr = (pthread_t)NULL;
-    }
-
-    pthread_mutex_lock(&usbmod->usb_playback_lock);
-    if (NULL != usbmod->usb_pcm_playback_handle){
-        pcm_close(usbmod->usb_pcm_playback_handle);
-        usbmod->usb_pcm_playback_handle = NULL;
-    }
-
-    if (NULL != usbmod->proxy_pcm_playback_handle){
-        pcm_close(usbmod->proxy_pcm_playback_handle);
-        usbmod->proxy_pcm_playback_handle = NULL;
-    }
-    pthread_mutex_unlock(&usbmod->usb_playback_lock);
-
-    ALOGD("%s: exiting",__func__);
-}
-
-void audio_extn_usb_start_capture(void *adev)
-{
-    int32_t ret;
-
-    if (NULL == usbmod){
-        ALOGE("%s: USB device object is NULL", __func__);
-        return;
-    }
-
-    if (usbmod->is_record_running){
-        ALOGE("%s: USB capture thread already running", __func__);
-        return;
-    }
-
-    ALOGD("%s: creating USB capture thread", __func__);
-    ret = pthread_create(&usbmod->usb_record_thr, NULL,
-                         usb_capture_launcher, (void*)adev);
-    if (ret)
-        ALOGE("%s: failed to create USB capture thread with err:%d",
-              __func__, ret);
-}
-
-void audio_extn_usb_stop_capture()
-{
-    int32_t ret;
-    ALOGD("%s: entry", __func__);
-
-    usbmod->is_record_running = false;
-    if (NULL != usbmod->proxy_pcm_record_handle)
-        pcm_stop(usbmod->proxy_pcm_record_handle);
-
-    if (NULL != usbmod->usb_pcm_record_handle)
-        pcm_stop(usbmod->usb_pcm_record_handle);
-
-    if(usbmod->usb_record_thr) {
-        ret = pthread_join(usbmod->usb_record_thr,NULL);
-        ALOGE("%s: return for pthread_join = %d", __func__, ret);
-        usbmod->usb_record_thr = (pthread_t)NULL;
-    }
-
-    pthread_mutex_lock(&usbmod->usb_record_lock);
-    if (NULL != usbmod->usb_pcm_record_handle){
-        pcm_close(usbmod->usb_pcm_record_handle);
-        usbmod->usb_pcm_record_handle = NULL;
-    }
-
-    if (NULL != usbmod->proxy_pcm_record_handle){
-        pcm_close(usbmod->proxy_pcm_record_handle);
-        usbmod->proxy_pcm_record_handle = NULL;
-    }
-    pthread_mutex_unlock(&usbmod->usb_record_lock);
-
-    ALOGD("%s: exiting",__func__);
-}
-
-bool audio_extn_usb_is_proxy_inuse()
-{
-    if( usbmod->is_record_running || usbmod->is_playback_running)
-        return true;
-    else
-        return false;
-}
 #endif /*USB_HEADSET_ENABLED end*/
diff --git a/hal/audio_extn/utils.c b/hal/audio_extn/utils.c
index cd9ead7..cb646cf 100644
--- a/hal/audio_extn/utils.c
+++ b/hal/audio_extn/utils.c
@@ -107,8 +107,10 @@
     STRING_TO_ENUM(AUDIO_FORMAT_AMR_WB),
     STRING_TO_ENUM(AUDIO_FORMAT_AC3),
     STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
-#ifdef AUDIO_EXTN_FORMATS_ENABLED
     STRING_TO_ENUM(AUDIO_FORMAT_DTS),
+    STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
+#ifdef AUDIO_EXTN_FORMATS_ENABLED
+    STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
     STRING_TO_ENUM(AUDIO_FORMAT_WMA),
     STRING_TO_ENUM(AUDIO_FORMAT_WMA_PRO),
     STRING_TO_ENUM(AUDIO_FORMAT_AAC_ADIF),
@@ -639,20 +641,6 @@
                 sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
          }
 
-         app_type_cfg[len++] = usecase->stream.out->app_type_cfg.app_type;
-         app_type_cfg[len++] = acdb_dev_id;
-         if (((usecase->stream.out->format == AUDIO_FORMAT_E_AC3) ||
-             (usecase->stream.out->format == AUDIO_FORMAT_E_AC3_JOC)) &&
-             (usecase->stream.out->flags  & AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH))
-             app_type_cfg[len++] = sample_rate * 4;
-         else
-             app_type_cfg[len++] = sample_rate;
-
-         ALOGI("%s:%d PLAYBACK app_type %d, acdb_dev_id %d, sample_rate %d",
-               __func__, __LINE__,
-               platform_get_default_app_type(adev->platform),
-               acdb_dev_id, sample_rate);
-
         if ((24 == usecase->stream.out->bit_width) &&
             (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
             usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
@@ -667,7 +655,7 @@
         app_type_cfg[len++] = acdb_dev_id;
         if (((usecase->stream.out->format == AUDIO_FORMAT_E_AC3) ||
             (usecase->stream.out->format == AUDIO_FORMAT_E_AC3_JOC))
-            && audio_extn_dolby_is_passthrough_stream(usecase->stream.out)) {
+            && audio_extn_passthru_is_passthrough_stream(usecase->stream.out)) {
             app_type_cfg[len++] = sample_rate * 4;
         } else {
             app_type_cfg[len++] = sample_rate;
@@ -1009,7 +997,7 @@
     if (audio_extn_is_dolby_format(out->format) &&
         /*TODO:Extend code to support DTS passthrough*/
         /*set compressed channel status bits*/
-        audio_extn_dolby_is_passthrough_stream(out)){
+        audio_extn_passthru_is_passthrough_stream(out)){
         get_compressed_channel_status(buffer, bytes, channel_status, AUDIO_PARSER_CODEC_AC3);
     } else
 #endif
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index aabb656..d6e81b2 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -338,6 +338,10 @@
         format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
         format == AUDIO_FORMAT_PCM_8_24_BIT ||
         format == AUDIO_FORMAT_PCM_16_BIT ||
+        format == AUDIO_FORMAT_AC3 ||
+        format == AUDIO_FORMAT_E_AC3 ||
+        format == AUDIO_FORMAT_DTS ||
+        format == AUDIO_FORMAT_DTS_HD ||
         format == AUDIO_FORMAT_FLAC ||
         format == AUDIO_FORMAT_ALAC ||
         format == AUDIO_FORMAT_APE ||
@@ -384,6 +388,17 @@
     case AUDIO_FORMAT_WMA_PRO:
         id = SND_AUDIOCODEC_WMA_PRO;
         break;
+    case AUDIO_FORMAT_AC3:
+        id = SND_AUDIOCODEC_AC3;
+        break;
+    case AUDIO_FORMAT_E_AC3:
+    case AUDIO_FORMAT_E_AC3_JOC:
+        id = SND_AUDIOCODEC_EAC3;
+        break;
+    case AUDIO_FORMAT_DTS:
+    case AUDIO_FORMAT_DTS_HD:
+        id = SND_AUDIOCODEC_DTS;
+        break;
     default:
         ALOGE("%s: Unsupported audio format :%x", __func__, format);
     }
@@ -537,14 +552,7 @@
 
     if (audio_extn_spkr_prot_is_enabled())
          audio_extn_spkr_prot_calib_cancel(adev);
-    /* start usb playback thread */
-    if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
-       SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
-        audio_extn_usb_start_playback(adev);
 
-    /* start usb capture thread */
-    if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
-       audio_extn_usb_start_capture(adev);
 
     if (platform_can_enable_spkr_prot_on_device(snd_device) &&
          audio_extn_spkr_prot_is_enabled()) {
@@ -553,7 +561,7 @@
            return -EINVAL;
        }
        audio_extn_dev_arbi_acquire(snd_device);
-        if (audio_extn_spkr_prot_start_processing(snd_device)) {
+       if (audio_extn_spkr_prot_start_processing(snd_device)) {
             ALOGE("%s: spkr_start_processing failed", __func__);
             audio_extn_dev_arbi_release(snd_device);
             return -EINVAL;
@@ -621,15 +629,6 @@
 
     if (adev->snd_dev_ref_cnt[snd_device] == 0) {
         ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
-        /* exit usb play back thread */
-        if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
-           SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
-            audio_extn_usb_stop_playback();
-
-        /* exit usb capture thread */
-        if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
-            audio_extn_usb_stop_capture();
-
         if (platform_can_enable_spkr_prot_on_device(snd_device) &&
              audio_extn_spkr_prot_is_enabled()) {
             audio_extn_spkr_prot_stop_processing(snd_device);
@@ -872,9 +871,6 @@
         out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
         out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
         out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
-    case 2:
-        ALOGV("%s: HDMI supports 2 channels", __func__);
-        out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_STEREO;
         break;
     default:
         ALOGE("invalid/nonstandard channal count[%d]",channels);
@@ -1157,8 +1153,7 @@
 
     /* Enable new sound devices */
     if (out_snd_device != SND_DEVICE_NONE) {
-        if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
-            check_usecases_codec_backend(adev, usecase, out_snd_device);
+        check_usecases_codec_backend(adev, usecase, out_snd_device);
         enable_snd_device(adev, out_snd_device);
     }
 
@@ -1511,6 +1506,7 @@
 
         if (out->compr == NULL) {
             ALOGE("%s: Compress handle is NULL", __func__);
+            free(cmd);
             pthread_cond_signal(&out->cond);
             continue;
         }
@@ -1755,8 +1751,9 @@
     ALOGV("%s usecase %s out->format:%x out->bit_width:%d", __func__, use_case_table[out->usecase],out->format,out->bit_width);
 
     if (is_offload_usecase(out->usecase) &&
-        audio_extn_dolby_is_passthrough_stream(out)) {
+        audio_extn_passthru_is_passthrough_stream(out)) {
         enable_passthru = true;
+        ALOGV("%s : enable_passthru is set to true", __func__);
     }
 
     /* Check if change in HDMI channel config is allowed */
@@ -1770,7 +1767,7 @@
 
         if (enable_passthru) {
             audio_extn_passthru_on_start(out);
-            audio_extn_dolby_update_passt_stream_configuration(adev, out);
+            audio_extn_passthru_update_stream_configuration(adev, out);
         }
 
         /* For pass through case, the backend should be configured as stereo */
@@ -1805,7 +1802,7 @@
     }
 
     if (is_offload_usecase(out->usecase) &&
-        !(audio_extn_dolby_is_passthrough_stream(out))) {
+        !(audio_extn_passthru_is_passthrough_stream(out))) {
         if (adev->visualizer_stop_output != NULL)
             adev->visualizer_stop_output(out->handle, out->pcm_device_id);
 
@@ -1825,21 +1822,21 @@
     free(uc_info);
 
     if (is_offload_usecase(out->usecase) &&
-        (audio_extn_dolby_is_passthrough_stream(out))) {
+        (audio_extn_passthru_is_passthrough_stream(out))) {
         ALOGV("Disable passthrough , reset mixer to pcm");
         /* NO_PASSTHROUGH */
         out->compr_config.codec->compr_passthr = 0;
 
-        /* Must be called after removing the usecase from list */
-        if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
-                check_and_set_hdmi_config(adev, DEFAULT_HDMI_OUT_CHANNELS,
-                                          DEFAULT_HDMI_OUT_SAMPLE_RATE,
-                                          DEFAULT_HDMI_OUT_FORMAT,
-                                          false);
         audio_extn_passthru_on_stop(out);
         audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
     }
 
+    /* Must be called after removing the usecase from list */
+    if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
+        check_and_set_hdmi_config(adev, DEFAULT_HDMI_OUT_CHANNELS,
+                                  DEFAULT_HDMI_OUT_SAMPLE_RATE,
+                                  DEFAULT_HDMI_OUT_FORMAT,
+                                  false);
     ALOGV("%s: exit: status(%d)", __func__, ret);
     return ret;
 }
@@ -1980,7 +1977,7 @@
         if (audio_extn_is_dolby_format(out->format))
             audio_extn_dolby_send_ddp_endp_params(adev);
 #endif
-        if (!(audio_extn_dolby_is_passthrough_stream(out))) {
+        if (!(audio_extn_passthru_is_passthrough_stream(out))) {
             if (adev->visualizer_start_output != NULL)
                 adev->visualizer_start_output(out->handle, out->pcm_device_id);
             if (adev->offload_effects_start_output != NULL)
@@ -2264,7 +2261,7 @@
          */
         if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
                 (val == AUDIO_DEVICE_NONE) &&
-                !audio_extn_dolby_is_passthrough_stream(out) &&
+                !audio_extn_passthru_is_passthrough_stream(out) &&
                 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
             val = AUDIO_DEVICE_OUT_SPEAKER;
         }
@@ -2487,13 +2484,13 @@
         out->muted = (left == 0.0f);
         return 0;
     } else if (is_offload_usecase(out->usecase)) {
-        if (audio_extn_dolby_is_passthrough_stream(out)) {
+        if (audio_extn_passthru_is_passthrough_stream(out)) {
             /*
              * Set mute or umute on HDMI passthrough stream.
              * Only take left channel into account.
              * Mute is 0 and unmute 1
              */
-            audio_extn_dolby_set_passt_volume(out, (left == 0.0f));
+            audio_extn_passthru_set_volume(out, (left == 0.0f));
         } else {
             char mixer_ctl_name[128];
             struct audio_device *adev = out->dev;
@@ -2547,6 +2544,13 @@
         }
     }
 
+    if (audio_extn_passthru_should_drop_data(out)) {
+        ALOGD(" %s : Drop data as compress passthrough session is going on", __func__);
+        usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
+                        out_get_sample_rate(&out->stream.common));
+        goto exit;
+    }
+
     if (out->standby) {
         out->standby = false;
         pthread_mutex_lock(&adev->lock);
@@ -3395,7 +3399,7 @@
         }
 
         if (!is_supported_format(config->offload_info.format) &&
-                !audio_extn_is_dolby_format(config->offload_info.format)) {
+                !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
             ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
             ret = -EINVAL;
             goto error_open;
@@ -3449,21 +3453,19 @@
 
         out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
 
-        if (audio_extn_is_dolby_format(config->offload_info.format))
-            out->compr_config.codec->id =
-                audio_extn_dolby_get_snd_codec_id(adev, out,
-                                                  config->offload_info.format);
-        else
-            out->compr_config.codec->id =
-                get_snd_codec_id(config->offload_info.format);
+        out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
+        if (audio_extn_is_dolby_format(config->offload_info.format)) {
+            audio_extn_dolby_send_ddp_endp_params(adev);
+            audio_extn_dolby_set_dmid(adev);
+        }
 
         if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM) {
             out->compr_config.fragment_size =
                platform_get_pcm_offload_buffer_size(&config->offload_info);
             out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
-        } else if (audio_extn_dolby_is_passthrough_stream(out)) {
+        } else if (audio_extn_passthru_is_passthrough_stream(out)) {
             out->compr_config.fragment_size =
-               audio_extn_dolby_get_passt_buffer_size(&config->offload_info);
+               audio_extn_passthru_get_buffer_size(&config->offload_info);
             out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
         } else {
             out->compr_config.fragment_size =
@@ -3517,14 +3519,14 @@
          * AV playback
          * Direct PCM playback
          */
-        if (audio_extn_dolby_is_passthrough_stream(out) ||
+        if (audio_extn_passthru_is_passthrough_stream(out) ||
             config->offload_info.has_video ||
             out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
             check_and_set_gapless_mode(adev, false);
         } else
             check_and_set_gapless_mode(adev, true);
 
-        if (audio_extn_dolby_is_passthrough_stream(out)) {
+        if (audio_extn_passthru_is_passthrough_stream(out)) {
             out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
         }
     } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
@@ -3819,7 +3821,8 @@
         if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
             ALOGV("cache new edid");
             platform_cache_edid(adev->platform);
-        } else if (val & AUDIO_DEVICE_OUT_USB_DEVICE) {
+        } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
+                   (val & AUDIO_DEVICE_IN_USB_DEVICE)) {
             /*
              * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
              * Per AudioPolicyManager, USB device is higher priority than WFD.
@@ -3827,6 +3830,10 @@
              * If WFD use case occupies AFE proxy, it may result unintended behavior while
              * starting voice call on USB
              */
+            ret = str_parms_get_str(parms, "card", value, sizeof(value));
+            if (ret >= 0) {
+                audio_extn_usb_add_device(val, atoi(value));
+            }
             ALOGV("detected USB connect .. disable proxy");
             adev->allow_afe_proxy_usage = false;
         }
@@ -3837,8 +3844,13 @@
         val = atoi(value);
         if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
             ALOGV("invalidate cached edid");
-            platform_invalidate_edid(adev->platform);
-        } else if (val & AUDIO_DEVICE_OUT_USB_DEVICE) {
+            platform_invalidate_hdmi_config(adev->platform);
+        } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
+                   (val & AUDIO_DEVICE_IN_USB_DEVICE)) {
+            ret = str_parms_get_str(parms, "card", value, sizeof(value));
+            if (ret >= 0) {
+                audio_extn_usb_remove_device(val, atoi(value));
+            }
             ALOGV("detected USB disconnect .. enable proxy");
             adev->allow_afe_proxy_usage = true;
         }
diff --git a/hal/edid.c b/hal/edid.c
index 06e1e05..8f183d0 100644
--- a/hal/edid.c
+++ b/hal/edid.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014, 2016, The Linux Foundation. All rights reserved.
  * Not a Contribution.
  *
  * Copyright (C) 2014 The Android Open Source Project
@@ -685,3 +685,44 @@
     dump_edid_data(info);
     return true;
 }
+
+bool edid_is_supported_sr(edid_audio_info* info, int sr)
+{
+    int i = 0;
+    if (info != NULL && sr != 0) {
+        for (i = 0; i < info->audio_blocks && i < MAX_EDID_BLOCKS; i++) {
+            if (info->audio_blocks_array[i].sampling_freq == sr) {
+                ALOGV("%s: returns true for sample rate [%d]",
+                      __func__, sr);
+                return true;
+            }
+        }
+    }
+    ALOGV("%s: returns false for sample rate [%d]",
+           __func__, sr);
+    return false;
+}
+
+bool edid_is_supported_bps(edid_audio_info* info, int bps)
+{
+    int i = 0;
+
+    if (bps == 16) {
+        //16 bit bps is always supported
+        //some oem may not update 16bit support in their edid info
+        return true;
+    }
+
+    if (info != NULL && bps != 0) {
+        for (i = 0; i < info->audio_blocks && i < MAX_EDID_BLOCKS; i++) {
+            if (info->audio_blocks_array[i].bits_per_sample == bps) {
+                ALOGV("%s: returns true for bit width [%d]",
+                      __func__, bps);
+                return true;
+            }
+        }
+    }
+    ALOGV("%s: returns false for bit width [%d]",
+           __func__, bps);
+    return false;
+}
diff --git a/hal/edid.h b/hal/edid.h
index 0d7fbe6..387b17e 100644
--- a/hal/edid.h
+++ b/hal/edid.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014, 2016, 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
@@ -97,4 +97,8 @@
 #else
 bool edid_get_sink_caps(edid_audio_info* info, char *edid_data);
 #endif
+
+bool edid_is_supported_sr(edid_audio_info* info, int sr);
+bool edid_is_supported_bps(edid_audio_info* info, int bps);
+
 #endif /* EDID_H */
diff --git a/hal/msm8916/platform.c b/hal/msm8916/platform.c
index b39b668..2403c55 100644
--- a/hal/msm8916/platform.c
+++ b/hal/msm8916/platform.c
@@ -1837,8 +1837,6 @@
 
     /* init usb */
     audio_extn_usb_init(adev);
-    /* update sound cards appropriately */
-    audio_extn_usb_set_proxy_sound_card(adev->snd_card);
 
     /* Read one time ssr property */
     audio_extn_ssr_update_enabled();
@@ -1899,6 +1897,16 @@
             strdup("MI2S_TX SampleRate");
     }
 
+    my_data->current_backend_cfg[USB_AUDIO_RX_BACKEND].bitwidth_mixer_ctl =
+        strdup("USB_AUDIO_RX Format");
+    my_data->current_backend_cfg[USB_AUDIO_RX_BACKEND].samplerate_mixer_ctl =
+        strdup("USB_AUDIO_RX SampleRate");
+
+    my_data->current_backend_cfg[HDMI_RX_BACKEND].bitwidth_mixer_ctl =
+        strdup("HDMI_RX Bit Format");
+    my_data->current_backend_cfg[HDMI_RX_BACKEND].samplerate_mixer_ctl =
+        strdup("HDMI_RX SampleRate");
+
     ret = audio_extn_utils_get_codec_version(snd_card_name,
                                              my_data->adev->snd_card,
                                              my_data->codec_version);
@@ -2403,6 +2411,8 @@
                         port = HEADPHONE_BACKEND;
                 else if (strcmp(backend_tag_table[snd_device], "hdmi") == 0)
                         port = HDMI_RX_BACKEND;
+                else if (strcmp(backend_tag_table[snd_device], "usb-headphones") == 0)
+                        port = USB_AUDIO_RX_BACKEND;
         }
     } else {
         ALOGV("%s:napb: Invalid device - %d ", __func__, snd_device);
@@ -2763,6 +2773,12 @@
 
         new_snd_devices[1] = SND_DEVICE_OUT_HDMI;
         status = true;
+    } else if (snd_device == SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET &&
+               !platform_check_backends_match(SND_DEVICE_OUT_SPEAKER, SND_DEVICE_OUT_USB_HEADSET)) {
+        *num_devices = 2;
+        new_snd_devices[0] = SND_DEVICE_OUT_SPEAKER;
+        new_snd_devices[1] = SND_DEVICE_OUT_USB_HEADSET;
+        status = true;
     }
 
     ALOGD("%s: snd_device(%d) num devices(%d) new_snd_devices(%d)", __func__,
@@ -2832,6 +2848,9 @@
         } else if (devices == (AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET |
                                AUDIO_DEVICE_OUT_SPEAKER)) {
             snd_device = SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET;
+        } else if (devices == (AUDIO_DEVICE_OUT_USB_DEVICE |
+                               AUDIO_DEVICE_OUT_SPEAKER)) {
+            snd_device = SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET;
         } else {
             ALOGE("%s: Invalid combo device(%#x)", __func__, devices);
             goto exit;
@@ -2970,6 +2989,8 @@
         ALOGD("%s: setting USB hadset channel capability(2) for Proxy", __func__);
         audio_extn_set_afe_proxy_channel_mixer(adev, 2);
         snd_device = SND_DEVICE_OUT_USB_HEADSET;
+    } else if (devices & AUDIO_DEVICE_OUT_USB_DEVICE) {
+        snd_device = SND_DEVICE_OUT_USB_HEADSET;
     } else if (devices & AUDIO_DEVICE_OUT_FM_TX) {
         snd_device = SND_DEVICE_OUT_TRANSMISSION_FM;
     } else if (devices & AUDIO_DEVICE_OUT_EARPIECE) {
@@ -3329,6 +3350,8 @@
             snd_device = SND_DEVICE_IN_USB_HEADSET_MIC;
         } else if (in_device & AUDIO_DEVICE_IN_FM_TUNER) {
             snd_device = SND_DEVICE_IN_CAPTURE_FM;
+        } else if (in_device & AUDIO_DEVICE_IN_USB_DEVICE ) {
+            snd_device = SND_DEVICE_IN_USB_HEADSET_MIC;
         } else {
             ALOGE("%s: Unknown input device(s) %#x", __func__, in_device);
             ALOGW("%s: Using default handset-mic", __func__);
@@ -3364,6 +3387,8 @@
         } else if (out_device & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET ||
                    out_device & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET) {
             snd_device = SND_DEVICE_IN_USB_HEADSET_MIC;
+        } else if (out_device & AUDIO_DEVICE_OUT_USB_DEVICE) {
+            snd_device = SND_DEVICE_IN_USB_HEADSET_MIC;
         } else {
             ALOGE("%s: Unknown output device(s) %#x", __func__, out_device);
             ALOGW("%s: Using default handset-mic", __func__);
@@ -4021,6 +4046,8 @@
                 mixer_ctl_set_enum_by_string(ctl, "S24_3LE");
             else
                 mixer_ctl_set_enum_by_string(ctl, "S24_LE");
+        } else if (bit_width == 32) {
+            mixer_ctl_set_enum_by_string(ctl, "S24_LE");
         } else {
             mixer_ctl_set_enum_by_string(ctl, "S16_LE");
         }
@@ -4113,6 +4140,7 @@
     int backend_idx = DEFAULT_CODEC_BACKEND;
     struct platform_data *my_data = (struct platform_data *)adev->platform;
     int na_mode = platform_get_native_support();
+    edid_audio_info *edid_info = (edid_audio_info *)my_data->edid_info;
 
     backend_idx = platform_get_backend_index(snd_device);
 
@@ -4188,8 +4216,6 @@
         }
     }
 
-
-
     /*
      * hifi playback not supported on spkr devices, limit the Sample Rate
      * to 48 khz.
@@ -4221,6 +4247,19 @@
                sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
     }
 
+    if (backend_idx == HDMI_RX_BACKEND) {
+        //Check EDID info for supported samplerate
+        if (!edid_is_supported_sr(edid_info,sample_rate)) {
+            //reset to current sample rate
+            sample_rate = my_data->current_backend_cfg[backend_idx].sample_rate;
+        }
+        //Check EDID info for supported bit widhth
+        if (!edid_is_supported_bps(edid_info,bit_width)) {
+            //reset to current sample rate
+            bit_width = my_data->current_backend_cfg[backend_idx].bit_width;
+        }
+    }
+
     //check if mulitchannel clip needs to be down sampled to 48k
     property_get("audio.playback.mch.downsample",value,"");
     if (!strncmp("true", value, sizeof("true"))) {
@@ -4236,6 +4275,13 @@
          }
     }
 
+    if (backend_idx == USB_AUDIO_RX_BACKEND) {
+        unsigned int channels = audio_channel_count_from_out_mask(usecase->stream.out->channel_mask);
+        audio_extn_usb_is_config_supported(&bit_width, &sample_rate, channels);
+        ALOGV("%s: USB BE configured as bit_width(%d)sample_rate(%d)channels(%d)",
+                   __func__, bit_width, sample_rate, channels);
+    }
+
     ALOGI("%s:becf: afe: Codec selected backend: %d updated bit width: %d and sample rate: %d",
           __func__,
         backend_idx, bit_width, sample_rate);
@@ -4945,13 +4991,17 @@
     platform_get_edid_info(platform);
 }
 
-void platform_invalidate_edid(void * platform)
+void platform_invalidate_hdmi_config(void * platform)
 {
     struct platform_data *my_data = (struct platform_data *)platform;
     my_data->edid_valid = false;
     if (my_data->edid_info) {
         memset(my_data->edid_info, 0, sizeof(struct edid_audio_info));
     }
+
+    //reset HDMI_RX_BACKEND to default values
+    my_data->current_backend_cfg[HDMI_RX_BACKEND].sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
+    my_data->current_backend_cfg[HDMI_RX_BACKEND].bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
 }
 
 int platform_set_mixer_control(struct stream_out *out, const char * mixer_ctl_name,
@@ -5294,3 +5344,26 @@
              return snd_device;
     }
 }
+
+int platform_set_sidetone(struct audio_device *adev,
+                          snd_device_t out_snd_device,
+                          bool enable,
+                          char *str)
+{
+    int ret;
+    if (out_snd_device == SND_DEVICE_OUT_USB_HEADSET) {
+            ret = audio_extn_usb_enable_sidetone(out_snd_device, enable);
+            if (ret)
+                ALOGI("%s: usb device %d does not support device sidetone\n",
+                  __func__, out_snd_device);
+    } else {
+        ALOGV("%s: sidetone out device(%d) mixer cmd = %s\n",
+              __func__, out_snd_device, str);
+
+        if (enable)
+            audio_route_apply_and_update_path(adev->audio_route, str);
+        else
+            audio_route_reset_and_update_path(adev->audio_route, str);
+    }
+    return 0;
+}
diff --git a/hal/msm8916/platform.h b/hal/msm8916/platform.h
index aef905d..7ff9c46 100644
--- a/hal/msm8916/platform.h
+++ b/hal/msm8916/platform.h
@@ -211,6 +211,7 @@
     HEADPHONE_BACKEND,
     SLIMBUS_6_RX = HEADPHONE_BACKEND,
     HDMI_RX_BACKEND,
+    USB_AUDIO_RX_BACKEND,
     MAX_CODEC_BACKENDS
 };
 #define AUDIO_PARAMETER_KEY_NATIVE_AUDIO "audio.nat.codec.enabled"
diff --git a/hal/msm8960/platform.c b/hal/msm8960/platform.c
index 2c60f3b..2b6a1d7 100644
--- a/hal/msm8960/platform.c
+++ b/hal/msm8960/platform.c
@@ -1165,7 +1165,7 @@
 
 }
 
-void platform_invalidate_edid(void * platform __unused)
+void platform_invalidate_hdmi_config(void * platform __unused)
 {
 
 }
@@ -1234,3 +1234,26 @@
 {
     return true;
 }
+
+int platform_set_sidetone(struct audio_device *adev,
+                          snd_device_t out_snd_device,
+                          bool enable,
+                          char *str)
+{
+    int ret;
+    if (out_snd_device == SND_DEVICE_OUT_USB_HEADSET) {
+            ret = audio_extn_usb_enable_sidetone(out_snd_device, enable);
+            if (ret)
+                ALOGI("%s: usb device %d does not support device sidetone\n",
+                  __func__, out_snd_device);
+    } else {
+        ALOGV("%s: sidetone out device(%d) mixer cmd = %s\n",
+              __func__, out_snd_device, str);
+
+        if (enable)
+            audio_route_apply_and_update_path(adev->audio_route, str);
+        else
+            audio_route_reset_and_update_path(adev->audio_route, str);
+    }
+    return 0;
+}
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index 49e8b5e..cd63143 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -1642,6 +1642,9 @@
         platform_acdb_init(my_data);
     }
 
+    /* init keep-alive for compress passthru */
+    audio_extn_keep_alive_init(adev);
+
 acdb_init_fail:
 
     set_platform_defaults(my_data);
@@ -1675,8 +1678,6 @@
 
     /* init usb */
     audio_extn_usb_init(adev);
-    /* update sound cards appropriately */
-    audio_extn_usb_set_proxy_sound_card(adev->snd_card);
 
     /* init dap hal */
     audio_extn_dap_hal_init(adev->snd_card);
@@ -1737,6 +1738,15 @@
         strdup("SLIM_6_RX Format");
     my_data->current_backend_cfg[HEADPHONE_BACKEND].samplerate_mixer_ctl =
         strdup("SLIM_6_RX SampleRate");
+    my_data->current_backend_cfg[HDMI_RX_BACKEND].bitwidth_mixer_ctl =
+        strdup("HDMI_RX Bit Format");
+    my_data->current_backend_cfg[HDMI_RX_BACKEND].samplerate_mixer_ctl =
+        strdup("HDMI_RX SampleRate");
+
+    my_data->current_backend_cfg[USB_AUDIO_RX_BACKEND].bitwidth_mixer_ctl =
+        strdup("USB_AUDIO_RX Format");
+    my_data->current_backend_cfg[USB_AUDIO_RX_BACKEND].samplerate_mixer_ctl =
+        strdup("USB_AUDIO_RX SampleRate");
 
     my_data->edid_info = NULL;
     free(snd_card_name);
@@ -2213,6 +2223,8 @@
                         port = HEADPHONE_BACKEND;
                 else if (strcmp(backend_tag_table[snd_device], "hdmi") == 0)
                         port = HDMI_RX_BACKEND;
+                else if (strcmp(backend_tag_table[snd_device], "usb-headphones") == 0)
+                        port = USB_AUDIO_RX_BACKEND;
         }
     } else {
         ALOGV("%s:napb: Invalid device - %d ", __func__, snd_device);
@@ -2568,6 +2580,12 @@
         new_snd_devices[0] = SND_DEVICE_OUT_SPEAKER;
         new_snd_devices[1] = SND_DEVICE_OUT_HDMI;
         status = true;
+    } else if (snd_device == SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET &&
+               !platform_check_backends_match(SND_DEVICE_OUT_SPEAKER, SND_DEVICE_OUT_USB_HEADSET)) {
+        *num_devices = 2;
+        new_snd_devices[0] = SND_DEVICE_OUT_SPEAKER;
+        new_snd_devices[1] = SND_DEVICE_OUT_USB_HEADSET;
+        status = true;
     }
 
     ALOGD("%s: snd_device(%d) num devices(%d) new_snd_devices(%d)", __func__,
@@ -2625,6 +2643,9 @@
         } else if (devices == (AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET |
                                AUDIO_DEVICE_OUT_SPEAKER)) {
             snd_device = SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET;
+        } else if (devices == (AUDIO_DEVICE_OUT_USB_DEVICE |
+                               AUDIO_DEVICE_OUT_SPEAKER)) {
+            snd_device = SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET;
         } else {
             ALOGE("%s: Invalid combo device(%#x)", __func__, devices);
             goto exit;
@@ -2736,6 +2757,8 @@
         ALOGD("%s: setting USB hadset channel capability(2) for Proxy", __func__);
         audio_extn_set_afe_proxy_channel_mixer(adev, 2);
         snd_device = SND_DEVICE_OUT_USB_HEADSET;
+    } else if (devices & AUDIO_DEVICE_OUT_USB_DEVICE) {
+        snd_device = SND_DEVICE_OUT_USB_HEADSET;
     } else if (devices & AUDIO_DEVICE_OUT_FM_TX) {
         snd_device = SND_DEVICE_OUT_TRANSMISSION_FM;
     } else if (devices & AUDIO_DEVICE_OUT_EARPIECE) {
@@ -3070,6 +3093,8 @@
             snd_device = SND_DEVICE_IN_USB_HEADSET_MIC;
         } else if (in_device & AUDIO_DEVICE_IN_FM_TUNER) {
             snd_device = SND_DEVICE_IN_CAPTURE_FM;
+        } else if (in_device & AUDIO_DEVICE_IN_USB_DEVICE ) {
+            snd_device = SND_DEVICE_IN_USB_HEADSET_MIC;
         } else {
             ALOGE("%s: Unknown input device(s) %#x", __func__, in_device);
             ALOGW("%s: Using default handset-mic", __func__);
@@ -3113,6 +3138,8 @@
         } else if (out_device & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET ||
                    out_device & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET) {
             snd_device = SND_DEVICE_IN_USB_HEADSET_MIC;
+        } else if (out_device & AUDIO_DEVICE_OUT_USB_DEVICE) {
+            snd_device = SND_DEVICE_IN_USB_HEADSET_MIC;
         } else {
             ALOGE("%s: Unknown output device(s) %#x", __func__, out_device);
             ALOGW("%s: Using default handset-mic", __func__);
@@ -3547,6 +3574,7 @@
     set_audiocal(platform, parms, value, len);
     native_audio_set_params(platform, parms, value, len);
     audio_extn_spkr_prot_set_parameters(parms, value, len);
+    audio_extn_usb_set_sidetone_gain(parms, value, len);
     perf_lock_set_params(platform, parms, value, len);
 done:
     ALOGV("%s: exit with code(%d)", __func__, ret);
@@ -3997,6 +4025,8 @@
                  mixer_ctl_set_enum_by_string(ctl, "S24_3LE");
             else
                  mixer_ctl_set_enum_by_string(ctl, "S24_LE");
+        } else if (bit_width == 32) {
+            mixer_ctl_set_enum_by_string(ctl, "S24_LE");
         } else {
             mixer_ctl_set_enum_by_string(ctl, "S16_LE");
         }
@@ -4079,6 +4109,7 @@
     int backend_idx = DEFAULT_CODEC_BACKEND;
     struct platform_data *my_data = (struct platform_data *)adev->platform;
     int na_mode = platform_get_native_support();
+    edid_audio_info *edid_info = (edid_audio_info *)my_data->edid_info;
 
     backend_idx = platform_get_backend_index(snd_device);
 
@@ -4178,8 +4209,28 @@
               __func__);
     }
 
+    if (backend_idx == USB_AUDIO_RX_BACKEND) {
+        unsigned int channels = audio_channel_count_from_out_mask(usecase->stream.out->channel_mask);
+        audio_extn_usb_is_config_supported(&bit_width, &sample_rate, channels);
+        ALOGV("%s: USB BE configured as bit_width(%d)sample_rate(%d)channels(%d)",
+                   __func__, bit_width, sample_rate, channels);
+    }
+
+    if (backend_idx == HDMI_RX_BACKEND) {
+        //Check EDID info for supported samplerate
+        if (!edid_is_supported_sr(edid_info,sample_rate)) {
+            //reset to current sample rate
+            sample_rate = my_data->current_backend_cfg[backend_idx].sample_rate;
+        }
+        //Check EDID info for supported bit widhth
+        if (!edid_is_supported_bps(edid_info,bit_width)) {
+            //reset to current sample rate
+            bit_width = my_data->current_backend_cfg[backend_idx].bit_width;
+        }
+    }
     ALOGI("%s:becf: afe: Codec selected backend: %d updated bit width: %d and sample rate: %d",
           __func__, backend_idx , bit_width, sample_rate);
+
     // Force routing if the expected bitwdith or samplerate
     // is not same as current backend comfiguration
     if ((bit_width != my_data->current_backend_cfg[backend_idx].bit_width) ||
@@ -4884,13 +4935,18 @@
     platform_get_edid_info(platform);
 }
 
-void platform_invalidate_edid(void * platform)
+void platform_invalidate_hdmi_config(void * platform)
 {
+    //reset HDMI EDID info
     struct platform_data *my_data = (struct platform_data *)platform;
     my_data->edid_valid = false;
     if (my_data->edid_info) {
         memset(my_data->edid_info, 0, sizeof(struct edid_audio_info));
     }
+
+    //reset HDMI_RX_BACKEND to default values
+    my_data->current_backend_cfg[HDMI_RX_BACKEND].sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
+    my_data->current_backend_cfg[HDMI_RX_BACKEND].bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
 }
 
 int platform_set_mixer_control(struct stream_out *out, const char * mixer_ctl_name,
@@ -5134,4 +5190,25 @@
     return ret;
 }
 
+int platform_set_sidetone(struct audio_device *adev,
+                          snd_device_t out_snd_device,
+                          bool enable,
+                          char *str)
+{
+    int ret;
+    if (out_snd_device == SND_DEVICE_OUT_USB_HEADSET) {
+            ret = audio_extn_usb_enable_sidetone(out_snd_device, enable);
+            if (ret)
+                ALOGI("%s: usb device %d does not support device sidetone\n",
+                  __func__, out_snd_device);
+    } else {
+        ALOGV("%s: sidetone out device(%d) mixer cmd = %s\n",
+              __func__, out_snd_device, str);
 
+        if (enable)
+            audio_route_apply_and_update_path(adev->audio_route, str);
+        else
+            audio_route_reset_and_update_path(adev->audio_route, str);
+    }
+    return 0;
+}
diff --git a/hal/msm8974/platform.h b/hal/msm8974/platform.h
index 52f0bac..eb04109 100644
--- a/hal/msm8974/platform.h
+++ b/hal/msm8974/platform.h
@@ -201,6 +201,7 @@
     HEADPHONE_BACKEND,
     SLIMBUS_6_RX = HEADPHONE_BACKEND,
     HDMI_RX_BACKEND,
+    USB_AUDIO_RX_BACKEND,
     MAX_CODEC_BACKENDS
 };
 
diff --git a/hal/platform_api.h b/hal/platform_api.h
index cb177b6..fc1c440 100644
--- a/hal/platform_api.h
+++ b/hal/platform_api.h
@@ -130,7 +130,6 @@
 bool platform_is_edid_supported_format(void *platform, int format);
 bool platform_is_edid_supported_sample_rate(void *platform, int sample_rate);
 void platform_cache_edid(void * platform);
-void platform_invalidate_edid(void * platform);
 void platform_invalidate_hdmi_config(void * platform);
 int platform_set_hdmi_config(void *platform, uint32_t channel_count,
                              uint32_t sample_rate, bool enable_passthrough);
@@ -148,4 +147,8 @@
                                    snd_device_t *new_snd_devices);
 
 bool platform_check_backends_match(snd_device_t snd_device1, snd_device_t snd_device2);
+int platform_set_sidetone(struct audio_device *adev,
+                          snd_device_t out_snd_device,
+                          bool enable,
+                          char * str);
 #endif // AUDIO_PLATFORM_API_H
diff --git a/hal/voice.c b/hal/voice.c
index 5fef205..f86483e 100644
--- a/hal/voice.c
+++ b/hal/voice.c
@@ -72,6 +72,9 @@
         is_sidetone_dev = true;
         strlcpy(mixer_path, "sidetone-headphones", MIXER_PATH_MAX_LENGTH);
         break;
+    case SND_DEVICE_OUT_USB_HEADSET:
+        is_sidetone_dev = true;
+        break;
     default:
         is_sidetone_dev = false;
         break;
@@ -84,28 +87,11 @@
         snd_device_t out_snd_device, bool enable)
 {
     char mixer_path[MIXER_PATH_MAX_LENGTH];
-    bool is_sidetone_dev;
-
     ALOGD("%s: %s, out_snd_device: %d\n",
           __func__, (enable ? "enable" : "disable"),
           out_snd_device);
-
-    is_sidetone_dev = voice_is_sidetone_device(out_snd_device, mixer_path);
-
-    if (!is_sidetone_dev) {
-        ALOGD("%s: device %d does not support sidetone\n",
-              __func__, out_snd_device);
-        return;
-    }
-
-    ALOGD("%s: sidetone out device = %s\n",
-          __func__, mixer_path);
-
-    if (enable)
-        audio_route_apply_and_update_path(adev->audio_route, mixer_path);
-    else
-        audio_route_reset_and_update_path(adev->audio_route, mixer_path);
-
+    if (voice_is_sidetone_device(out_snd_device, mixer_path))
+        platform_set_sidetone(adev, out_snd_device, enable, mixer_path);
     return;
 }
 
diff --git a/policy_hal/Android.mk b/policy_hal/Android.mk
index 811c2c9..854eaee 100644
--- a/policy_hal/Android.mk
+++ b/policy_hal/Android.mk
@@ -65,6 +65,10 @@
 LOCAL_CFLAGS += -DFM_POWER_OPT
 endif
 
+ifeq ($(USE_XML_AUDIO_POLICY_CONF), 1)
+LOCAL_CFLAGS += -DUSE_XML_AUDIO_POLICY_CONF
+endif
+
 LOCAL_MODULE := libaudiopolicymanager
 
 include $(BUILD_SHARED_LIBRARY)
diff --git a/policy_hal/AudioPolicyManager.cpp b/policy_hal/AudioPolicyManager.cpp
index 4c15fda..a5e0978 100644
--- a/policy_hal/AudioPolicyManager.cpp
+++ b/policy_hal/AudioPolicyManager.cpp
@@ -2107,6 +2107,12 @@
       mFMIsActive(false)
 {
 
+#ifdef USE_XML_AUDIO_POLICY_CONF
+    ALOGD("USE_XML_AUDIO_POLICY_CONF is TRUE");
+#else
+    ALOGD("USE_XML_AUDIO_POLICY_CONF is FALSE");
+#endif
+
     //TODO: Check the new logic to parse policy conf and update the below code
     //      Need this when SSR encoding is enabled
     char ssr_enabled[PROPERTY_VALUE_MAX] = {0};