hal: remote merge from master to LA.BR.1 branch

- Merge commit 'b87c2eeacfec214f198169319b11e4aca8ab8e87'

Conflicts:
	hal/Android.mk
	hal/audio_extn/audio_extn.c
	hal/audio_extn/audio_extn.h
	hal/audio_extn/dolby.c
	hal/audio_hw.c
	hal/msm8916/hw_info.c
	hal/msm8916/platform.c
	hal/msm8916/platform.h
	hal/msm8974/platform.c
	hal/platform_api.h
	policy_hal/AudioPolicyManager.cpp

Change-Id: Ic9e8a18a5d82719b02038999c92c9991f843981b
diff --git a/hal/audio_extn/audio_defs.h b/hal/audio_extn/audio_defs.h
index 335a629..96b0a8b 100644
--- a/hal/audio_extn/audio_defs.h
+++ b/hal/audio_extn/audio_defs.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2015, 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
@@ -48,6 +48,30 @@
 #define AUDIO_OFFLOAD_CODEC_FLAC_MIN_FRAME_SIZE "music_offload_flac_min_frame_size"
 #define AUDIO_OFFLOAD_CODEC_FLAC_MAX_FRAME_SIZE "music_offload_flac_max_frame_size"
 
+#define AUDIO_OFFLOAD_CODEC_ALAC_FRAME_LENGTH "music_offload_alac_frame_length"
+#define AUDIO_OFFLOAD_CODEC_ALAC_COMPATIBLE_VERSION "music_offload_alac_compatible_version"
+#define AUDIO_OFFLOAD_CODEC_ALAC_BIT_DEPTH "music_offload_alac_bit_depth"
+#define AUDIO_OFFLOAD_CODEC_ALAC_PB "music_offload_alac_pb"
+#define AUDIO_OFFLOAD_CODEC_ALAC_MB "music_offload_alac_mb"
+#define AUDIO_OFFLOAD_CODEC_ALAC_KB "music_offload_alac_kb"
+#define AUDIO_OFFLOAD_CODEC_ALAC_NUM_CHANNELS "music_offload_alac_num_channels"
+#define AUDIO_OFFLOAD_CODEC_ALAC_MAX_RUN "music_offload_alac_max_run"
+#define AUDIO_OFFLOAD_CODEC_ALAC_MAX_FRAME_BYTES "music_offload_alac_max_frame_bytes"
+#define AUDIO_OFFLOAD_CODEC_ALAC_AVG_BIT_RATE "music_offload_alac_avg_bit_rate"
+#define AUDIO_OFFLOAD_CODEC_ALAC_SAMPLING_RATE "music_offload_alac_sampling_rate"
+#define AUDIO_OFFLOAD_CODEC_ALAC_CHANNEL_LAYOUT_TAG "music_offload_alac_channel_layout_tag"
+
+#define AUDIO_OFFLOAD_CODEC_APE_COMPATIBLE_VERSION "music_offload_ape_compatible_version"
+#define AUDIO_OFFLOAD_CODEC_APE_COMPRESSION_LEVEL "music_offload_ape_compression_level"
+#define AUDIO_OFFLOAD_CODEC_APE_FORMAT_FLAGS "music_offload_ape_format_flags"
+#define AUDIO_OFFLOAD_CODEC_APE_BLOCKS_PER_FRAME "music_offload_ape_blocks_per_frame"
+#define AUDIO_OFFLOAD_CODEC_APE_FINAL_FRAME_BLOCKS "music_offload_ape_final_frame_blocks"
+#define AUDIO_OFFLOAD_CODEC_APE_TOTAL_FRAMES "music_offload_ape_total_frames"
+#define AUDIO_OFFLOAD_CODEC_APE_BITS_PER_SAMPLE "music_offload_ape_bits_per_sample"
+#define AUDIO_OFFLOAD_CODEC_APE_NUM_CHANNELS "music_offload_ape_num_channels"
+#define AUDIO_OFFLOAD_CODEC_APE_SAMPLE_RATE "music_offload_ape_sample_rate"
+#define AUDIO_OFFLOAD_CODEC_APE_SEEK_TABLE_PRESENT "music_offload_seek_table_present"
+
 /* Query handle fm parameter*/
 #define AUDIO_PARAMETER_KEY_HANDLE_FM "handle_fm"
 
diff --git a/hal/audio_extn/audio_extn.c b/hal/audio_extn/audio_extn.c
index cae961d..ca5fd59 100644
--- a/hal/audio_extn/audio_extn.c
+++ b/hal/audio_extn/audio_extn.c
@@ -15,6 +15,24 @@
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
+ *
+ * This file was modified by DTS, Inc. The portions of the
+ * code modified by DTS, Inc are copyrighted and
+ * licensed separately, as follows:
+ *
+ * (C) 2014 DTS, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
  */
 
 #define LOG_TAG "audio_hw_extn"
@@ -31,6 +49,9 @@
 #include "audio_extn.h"
 #include "platform.h"
 #include "platform_api.h"
+#include "edid.h"
+
+#include "sound/compress_params.h"
 
 #define MAX_SLEEP_RETRY 100
 #define WIFI_INIT_WAIT_SLEEP 50
@@ -40,6 +61,7 @@
     bool aanc_enabled;
     bool custom_stereo_enabled;
     uint32_t proxy_channel_num;
+    bool hpx_enabled;
 };
 
 static struct audio_extn_module aextnmod = {
@@ -47,6 +69,7 @@
     .aanc_enabled = 0,
     .custom_stereo_enabled = 0,
     .proxy_channel_num = 2,
+    .hpx_enabled = 0,
 };
 
 #define AUDIO_PARAMETER_KEY_ANC        "anc_enabled"
@@ -55,6 +78,9 @@
 #define AUDIO_PARAMETER_CUSTOM_STEREO  "stereo_as_dual_mono"
 /* Query offload playback instances count */
 #define AUDIO_PARAMETER_OFFLOAD_NUM_ACTIVE "offload_num_active"
+#define AUDIO_PARAMETER_HPX            "HPX"
+#define AUDIO_PARAMETER_KEY_ASPHERE_ENABLE   "asphere_enable"
+#define AUDIO_PARAMETER_KEY_ASPHERE_STRENGTH "asphere_strength"
 
 #ifndef FM_ENABLED
 #define audio_extn_fm_set_parameters(adev, parms) (0)
@@ -69,6 +95,17 @@
                                            struct str_parms *parms);
 #endif
 
+#ifndef SOURCE_TRACKING_ENABLED
+#define audio_extn_source_track_set_parameters(adev, parms) (0)
+#define audio_extn_source_track_get_parameters(adev, query, reply) (0)
+#else
+void audio_extn_source_track_set_parameters(struct audio_device *adev,
+                                            struct str_parms *parms);
+void audio_extn_source_track_get_parameters(struct audio_device *adev,
+                                            struct str_parms *query,
+                                            struct str_parms *reply);
+#endif
+
 #ifndef CUSTOM_STEREO_ENABLED
 #define audio_extn_customstereo_set_parameters(adev, parms)         (0)
 #else
@@ -108,6 +145,76 @@
 }
 #endif /* CUSTOM_STEREO_ENABLED */
 
+#ifndef DTS_EAGLE
+#define audio_extn_hpx_set_parameters(adev, parms)         (0)
+#define audio_extn_hpx_get_parameters(query, reply)  (0)
+#define audio_extn_check_and_set_dts_hpx_state(adev)       (0)
+#else
+void audio_extn_hpx_set_parameters(struct audio_device *adev,
+                                   struct str_parms *parms)
+{
+    int ret = 0;
+    char value[32]={0};
+    char prop[PROPERTY_VALUE_MAX] = "false";
+    bool hpx_state = false;
+    const char *mixer_ctl_name = "Set HPX OnOff";
+    struct mixer_ctl *ctl = NULL;
+    ALOGV("%s", __func__);
+
+    property_get("use.dts_eagle", prop, "0");
+    if (strncmp("true", prop, sizeof("true")))
+        return;
+
+    ret = str_parms_get_str(parms, AUDIO_PARAMETER_HPX, value,
+                            sizeof(value));
+    if (ret >= 0) {
+        if (!strncmp("ON", value, sizeof("ON")))
+            hpx_state = true;
+
+        if (hpx_state == aextnmod.hpx_enabled)
+            return;
+
+        aextnmod.hpx_enabled = hpx_state;
+        /* set HPX state on stream pp */
+        if (adev->offload_effects_set_hpx_state != NULL)
+            adev->offload_effects_set_hpx_state(hpx_state);
+
+        /* set HPX state on device pp */
+        ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
+        if (ctl)
+            mixer_ctl_set_value(ctl, 0, aextnmod.hpx_enabled);
+    }
+}
+
+static int audio_extn_hpx_get_parameters(struct str_parms *query,
+                                       struct str_parms *reply)
+{
+    int ret;
+    char value[32]={0};
+
+    ALOGV("%s: hpx %d", __func__, aextnmod.hpx_enabled);
+    ret = str_parms_get_str(query, AUDIO_PARAMETER_HPX, value,
+                            sizeof(value));
+    if (ret >= 0) {
+        if (aextnmod.hpx_enabled)
+            str_parms_add_str(reply, AUDIO_PARAMETER_HPX, "ON");
+        else
+            str_parms_add_str(reply, AUDIO_PARAMETER_HPX, "OFF");
+    }
+    return ret;
+}
+
+void audio_extn_check_and_set_dts_hpx_state(const struct audio_device *adev)
+{
+    char prop[PROPERTY_VALUE_MAX];
+    property_get("use.dts_eagle", prop, "0");
+    if (strncmp("true", prop, sizeof("true")))
+        return;
+    if (adev->offload_effects_set_hpx_state)
+        adev->offload_effects_set_hpx_state(aextnmod.hpx_enabled);
+}
+#endif
+
 #ifndef ANC_HEADSET_ENABLED
 #define audio_extn_set_anc_parameters(adev, parms)       (0)
 #else
@@ -236,35 +343,11 @@
 #define audio_extn_set_afe_proxy_parameters(adev, parms)  (0)
 #define audio_extn_get_afe_proxy_parameters(query, reply) (0)
 #else
-/* Front left channel. */
-#define PCM_CHANNEL_FL    1
-
-/* Front right channel. */
-#define PCM_CHANNEL_FR    2
-
-/* Front center channel. */
-#define PCM_CHANNEL_FC    3
-
-/* Left surround channel.*/
-#define PCM_CHANNEL_LS   4
-
-/* Right surround channel.*/
-#define PCM_CHANNEL_RS   5
-
-/* Low frequency effect channel. */
-#define PCM_CHANNEL_LFE  6
-
-/* Left back channel; Rear left channel. */
-#define PCM_CHANNEL_LB   8
-
-/* Right back channel; Rear right channel. */
-#define PCM_CHANNEL_RB   9
-
 static int32_t afe_proxy_set_channel_mapping(struct audio_device *adev,
                                                      int channel_count)
 {
     struct mixer_ctl *ctl;
-    const char *mixer_ctl_name = "Playback Channel Map";
+    const char *mixer_ctl_name = "Playback Device Channel Map";
     int set_values[8] = {0};
     int ret;
     ALOGV("%s channel_count:%d",__func__, channel_count);
@@ -451,6 +534,103 @@
     return ret;
 }
 
+#ifndef AUDIOSPHERE_ENABLED
+#define audio_extn_asphere_set_parameters(adev, parms)  (0)
+#define audio_extn_asphere_get_parameters(adev, query, reply) (0)
+#else
+int32_t audio_extn_asphere_set_parameters(const struct audio_device *adev,
+                                     struct str_parms *parms)
+{
+    int ret = 0, val[2];
+    char value[32] = {0};
+    int set_enable, set_strength;
+    int enable = -1, strength = -1;
+    struct mixer_ctl *ctl = NULL;
+    const char *mixer_ctl_name = "MSM ASphere Set Param";
+    char propValue[PROPERTY_VALUE_MAX] = {0};
+    bool asphere_prop_enabled = false;
+
+    if (property_get("audio.pp.asphere.enabled", propValue, "false")) {
+        if (!strncmp("true", propValue, 4))
+            asphere_prop_enabled = true;
+    }
+
+    if (!asphere_prop_enabled) {
+        ALOGV("%s: property not set!!! not doing anything", __func__);
+        return ret;
+    }
+
+    set_enable = str_parms_get_str(parms,
+                            AUDIO_PARAMETER_KEY_ASPHERE_ENABLE,
+                            value, sizeof(value));
+    if (set_enable > 0)
+        enable = atoi(value);
+
+    set_strength = str_parms_get_str(parms,
+                            AUDIO_PARAMETER_KEY_ASPHERE_STRENGTH,
+                            value, sizeof(value));
+    if (set_strength > 0)
+        strength = atoi(value);
+
+    if (set_enable >= 0 || set_strength >= 0) {
+        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);
+            return -EINVAL;
+        }
+        ALOGD("%s: set ctl \"%s:%d,%d\"",
+              __func__, mixer_ctl_name, enable, strength);
+        val[0] = enable;
+        val[1] = strength;
+        ret = mixer_ctl_set_array(ctl, val, sizeof(val)/sizeof(val[0]));
+        if (ret)
+            ALOGE("%s: set ctl failed!!!\"%s:%d,%d\"",
+                  __func__, mixer_ctl_name, enable, strength);
+    }
+    ALOGV("%s: exit ret %d", __func__, ret);
+    return ret;
+}
+
+int32_t audio_extn_asphere_get_parameters(const struct audio_device *adev,
+                                          struct str_parms *query,
+                                          struct str_parms *reply)
+{
+    int ret = 0, val[2] = {-1, -1};
+    char value[32] = {0};
+    int get_enable, get_strength;
+    struct mixer_ctl *ctl = NULL;
+    const char *mixer_ctl_name = "MSM ASphere Set Param";
+
+    get_enable = str_parms_get_str(query,
+                                   AUDIO_PARAMETER_KEY_ASPHERE_ENABLE,
+                                   value, sizeof(value));
+    get_strength = str_parms_get_str(query,
+                                     AUDIO_PARAMETER_KEY_ASPHERE_STRENGTH,
+                                     value, sizeof(value));
+    if (get_enable > 0 || get_strength > 0) {
+        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);
+            return -EINVAL;
+        }
+        ret = mixer_ctl_get_array(ctl, val, sizeof(val)/sizeof(val[0]));
+        if (ret)
+            ALOGE("%s: got ctl failed!!! \"%s:%d,%d\"",
+                   __func__, mixer_ctl_name, val[0], val[1]);
+        if (get_enable > 0)
+            str_parms_add_int(reply,
+                              AUDIO_PARAMETER_KEY_ASPHERE_ENABLE, val[0]);
+        if (get_strength > 0)
+            str_parms_add_int(reply,
+                              AUDIO_PARAMETER_KEY_ASPHERE_STRENGTH, val[1]);
+    }
+    ALOGV("%s: exit ret %d", __func__, ret);
+    return ret;
+}
+#endif
+
 void audio_extn_set_parameters(struct audio_device *adev,
                                struct str_parms *parms)
 {
@@ -461,10 +641,14 @@
    audio_extn_sound_trigger_set_parameters(adev, parms);
    audio_extn_listen_set_parameters(adev, parms);
    audio_extn_hfp_set_parameters(adev, parms);
+   audio_extn_dts_eagle_set_parameters(adev, parms);
    audio_extn_ddp_set_parameters(adev, parms);
    audio_extn_ds2_set_parameters(adev, parms);
    audio_extn_customstereo_set_parameters(adev, parms);
+   audio_extn_hpx_set_parameters(adev, parms);
    audio_extn_pm_set_parameters(parms);
+   audio_extn_source_track_set_parameters(adev, parms);
+   audio_extn_asphere_set_parameters(adev, parms);
 }
 
 void audio_extn_get_parameters(const struct audio_device *adev,
@@ -475,12 +659,250 @@
     audio_extn_get_afe_proxy_parameters(query, reply);
     audio_extn_get_fluence_parameters(adev, query, reply);
     get_active_offload_usecases(adev, query, reply);
+    audio_extn_dts_eagle_get_parameters(adev, query, reply);
+    audio_extn_hpx_get_parameters(query, reply);
+    audio_extn_source_track_get_parameters(adev, query, reply);
+    audio_extn_asphere_get_parameters(adev, query, reply);
 
     kv_pairs = str_parms_to_str(reply);
     ALOGD_IF(kv_pairs != NULL, "%s: returns %s", __func__, kv_pairs);
     free(kv_pairs);
 }
 
+#ifndef COMPRESS_METADATA_NEEDED
+#define audio_extn_parse_compress_metadata(out, parms) (0)
+#else
+int audio_extn_parse_compress_metadata(struct stream_out *out,
+                                       struct str_parms *parms)
+{
+    int ret = 0;
+    char value[32];
+
+    if (out->format == AUDIO_FORMAT_FLAC) {
+        ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MIN_BLK_SIZE, value, sizeof(value));
+        if (ret >= 0) {
+            out->gapless_mdata.min_blk_size =
+            out->compr_config.codec->options.flac_dec.min_blk_size = atoi(value);
+            out->send_new_metadata = 1;
+        }
+        ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MAX_BLK_SIZE, value, sizeof(value));
+        if (ret >= 0) {
+            out->gapless_mdata.max_blk_size =
+            out->compr_config.codec->options.flac_dec.max_blk_size = atoi(value);
+            out->send_new_metadata = 1;
+        }
+        ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MIN_FRAME_SIZE, value, sizeof(value));
+        if (ret >= 0) {
+            out->compr_config.codec->options.flac_dec.min_frame_size = atoi(value);
+            out->send_new_metadata = 1;
+        }
+        ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MAX_FRAME_SIZE, value, sizeof(value));
+        if (ret >= 0) {
+            out->compr_config.codec->options.flac_dec.max_frame_size = atoi(value);
+            out->send_new_metadata = 1;
+        }
+        ALOGV("FLAC metadata: min_blk_size %d, max_blk_size %d min_frame_size %d max_frame_size %d",
+              out->compr_config.codec->options.flac_dec.min_blk_size,
+              out->compr_config.codec->options.flac_dec.max_blk_size,
+              out->compr_config.codec->options.flac_dec.min_frame_size,
+              out->compr_config.codec->options.flac_dec.max_frame_size);
+    }
+
+    else if (out->format == AUDIO_FORMAT_ALAC) {
+        ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_ALAC_FRAME_LENGTH, value, sizeof(value));
+        if (ret >= 0) {
+            out->compr_config.codec->options.alac.frame_length = atoi(value);
+            out->send_new_metadata = 1;
+        }
+        ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_ALAC_COMPATIBLE_VERSION, value, sizeof(value));
+        if (ret >= 0) {
+            out->compr_config.codec->options.alac.compatible_version = atoi(value);
+            out->send_new_metadata = 1;
+        }
+        ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_ALAC_BIT_DEPTH, value, sizeof(value));
+        if (ret >= 0) {
+            out->compr_config.codec->options.alac.bit_depth = atoi(value);
+            out->send_new_metadata = 1;
+        }
+        ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_ALAC_PB, value, sizeof(value));
+        if (ret >= 0) {
+            out->compr_config.codec->options.alac.pb = atoi(value);
+            out->send_new_metadata = 1;
+        }
+        ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_ALAC_MB, value, sizeof(value));
+        if (ret >= 0) {
+            out->compr_config.codec->options.alac.mb = atoi(value);
+            out->send_new_metadata = 1;
+        }
+
+        ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_ALAC_KB, value, sizeof(value));
+        if (ret >= 0) {
+            out->compr_config.codec->options.alac.kb = atoi(value);
+            out->send_new_metadata = 1;
+        }
+        ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_ALAC_NUM_CHANNELS, value, sizeof(value));
+        if (ret >= 0) {
+            out->compr_config.codec->options.alac.num_channels = atoi(value);
+            out->send_new_metadata = 1;
+        }
+        ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_ALAC_MAX_RUN, value, sizeof(value));
+        if (ret >= 0) {
+            out->compr_config.codec->options.alac.max_run = atoi(value);
+            out->send_new_metadata = 1;
+        }
+        ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_ALAC_MAX_FRAME_BYTES, value, sizeof(value));
+        if (ret >= 0) {
+            out->compr_config.codec->options.alac.max_frame_bytes = atoi(value);
+            out->send_new_metadata = 1;
+        }
+        ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_ALAC_AVG_BIT_RATE, value, sizeof(value));
+        if (ret >= 0) {
+            out->compr_config.codec->options.alac.avg_bit_rate = atoi(value);
+            out->send_new_metadata = 1;
+        }
+        ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_ALAC_SAMPLING_RATE, value, sizeof(value));
+        if (ret >= 0) {
+            out->compr_config.codec->options.alac.sample_rate = atoi(value);
+            out->send_new_metadata = 1;
+        }
+        ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_ALAC_CHANNEL_LAYOUT_TAG, value, sizeof(value));
+        if (ret >= 0) {
+            out->compr_config.codec->options.alac.channel_layout_tag = atoi(value);
+            out->send_new_metadata = 1;
+        }
+        ALOGV("ALAC CSD values: frameLength %d bitDepth %d numChannels %d"
+                " maxFrameBytes %d, avgBitRate %d, sampleRate %d",
+                out->compr_config.codec->options.alac.frame_length,
+                out->compr_config.codec->options.alac.bit_depth,
+                out->compr_config.codec->options.alac.num_channels,
+                out->compr_config.codec->options.alac.max_frame_bytes,
+                out->compr_config.codec->options.alac.avg_bit_rate,
+                out->compr_config.codec->options.alac.sample_rate);
+    }
+
+    else if (out->format == AUDIO_FORMAT_APE) {
+        ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_APE_COMPATIBLE_VERSION, value, sizeof(value));
+        if (ret >= 0) {
+            out->compr_config.codec->options.ape.compatible_version = atoi(value);
+            out->send_new_metadata = 1;
+        }
+        ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_APE_COMPRESSION_LEVEL, value, sizeof(value));
+        if (ret >= 0) {
+            out->compr_config.codec->options.ape.compression_level = atoi(value);
+            out->send_new_metadata = 1;
+        }
+        ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_APE_FORMAT_FLAGS, value, sizeof(value));
+        if (ret >= 0) {
+            out->compr_config.codec->options.ape.format_flags = atoi(value);
+            out->send_new_metadata = 1;
+        }
+        ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_APE_BLOCKS_PER_FRAME, value, sizeof(value));
+        if (ret >= 0) {
+            out->compr_config.codec->options.ape.blocks_per_frame = atoi(value);
+            out->send_new_metadata = 1;
+        }
+        ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_APE_FINAL_FRAME_BLOCKS, value, sizeof(value));
+        if (ret >= 0) {
+            out->compr_config.codec->options.ape.final_frame_blocks = atoi(value);
+            out->send_new_metadata = 1;
+        }
+        ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_APE_TOTAL_FRAMES, value, sizeof(value));
+        if (ret >= 0) {
+            out->compr_config.codec->options.ape.total_frames = atoi(value);
+            out->send_new_metadata = 1;
+        }
+        ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_APE_BITS_PER_SAMPLE, value, sizeof(value));
+        if (ret >= 0) {
+            out->compr_config.codec->options.ape.bits_per_sample = atoi(value);
+            out->send_new_metadata = 1;
+        }
+        ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_APE_NUM_CHANNELS, value, sizeof(value));
+        if (ret >= 0) {
+            out->compr_config.codec->options.ape.num_channels = atoi(value);
+            out->send_new_metadata = 1;
+        }
+        ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_APE_SAMPLE_RATE, value, sizeof(value));
+        if (ret >= 0) {
+            out->compr_config.codec->options.ape.sample_rate = atoi(value);
+            out->send_new_metadata = 1;
+        }
+        ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_APE_SEEK_TABLE_PRESENT, value, sizeof(value));
+        if (ret >= 0) {
+            out->compr_config.codec->options.ape.seek_table_present = atoi(value);
+            out->send_new_metadata = 1;
+        }
+        ALOGV("APE CSD values: compatibleVersion %d compressionLevel %d"
+                " formatFlags %d blocksPerFrame %d finalFrameBlocks %d"
+                " totalFrames %d bitsPerSample %d numChannels %d"
+                " sampleRate %d seekTablePresent %d",
+                out->compr_config.codec->options.ape.compatible_version,
+                out->compr_config.codec->options.ape.compression_level,
+                out->compr_config.codec->options.ape.format_flags,
+                out->compr_config.codec->options.ape.blocks_per_frame,
+                out->compr_config.codec->options.ape.final_frame_blocks,
+                out->compr_config.codec->options.ape.total_frames,
+                out->compr_config.codec->options.ape.bits_per_sample,
+                out->compr_config.codec->options.ape.num_channels,
+                out->compr_config.codec->options.ape.sample_rate,
+                out->compr_config.codec->options.ape.seek_table_present);
+    }
+
+    else if (out->format == AUDIO_FORMAT_VORBIS) {
+        // transcoded bitstream mode
+        out->compr_config.codec->options.vorbis_dec.bit_stream_fmt = 1;
+        out->send_new_metadata = 1;
+    }
+
+    else if (out->format == AUDIO_FORMAT_WMA || out->format == AUDIO_FORMAT_WMA_PRO) {
+        ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_FORMAT_TAG, value, sizeof(value));
+        if (ret >= 0) {
+            out->compr_config.codec->format = atoi(value);
+            out->send_new_metadata = 1;
+        }
+        ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_BLOCK_ALIGN, value, sizeof(value));
+        if (ret >= 0) {
+            out->compr_config.codec->options.wma.super_block_align = atoi(value);
+            out->send_new_metadata = 1;
+        }
+        ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_BIT_PER_SAMPLE, value, sizeof(value));
+        if (ret >= 0) {
+            out->compr_config.codec->options.wma.bits_per_sample = atoi(value);
+            out->send_new_metadata = 1;
+        }
+        ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_CHANNEL_MASK, value, sizeof(value));
+        if (ret >= 0) {
+            out->compr_config.codec->options.wma.channelmask = atoi(value);
+            out->send_new_metadata = 1;
+        }
+        ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_ENCODE_OPTION, value, sizeof(value));
+        if (ret >= 0) {
+            out->compr_config.codec->options.wma.encodeopt = atoi(value);
+            out->send_new_metadata = 1;
+        }
+        ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_ENCODE_OPTION1, value, sizeof(value));
+        if (ret >= 0) {
+            out->compr_config.codec->options.wma.encodeopt1 = atoi(value);
+            out->send_new_metadata = 1;
+        }
+        ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_ENCODE_OPTION2, value, sizeof(value));
+        if (ret >= 0) {
+            out->compr_config.codec->options.wma.encodeopt2 = atoi(value);
+            out->send_new_metadata = 1;
+        }
+        ALOGV("WMA params: fmt %x, balgn %x, sr %d, chmsk %x, encop %x, op1 %x, op2 %x",
+                out->compr_config.codec->format,
+                out->compr_config.codec->options.wma.super_block_align,
+                out->compr_config.codec->options.wma.bits_per_sample,
+                out->compr_config.codec->options.wma.channelmask,
+                out->compr_config.codec->options.wma.encodeopt,
+                out->compr_config.codec->options.wma.encodeopt1,
+                out->compr_config.codec->options.wma.encodeopt2);
+    }
+
+    return ret;
+}
+#endif
+
 #ifdef AUXPCM_BT_ENABLED
 int32_t audio_extn_read_xml(struct audio_device *adev, uint32_t mixer_card,
                             const char* mixer_xml_path,
diff --git a/hal/audio_extn/audio_extn.h b/hal/audio_extn/audio_extn.h
index 6baa37f..98b2672 100644
--- a/hal/audio_extn/audio_extn.h
+++ b/hal/audio_extn/audio_extn.h
@@ -15,6 +15,24 @@
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
+ *
+ * This file was modified by DTS, Inc. The portions of the
+ * code modified by DTS, Inc are copyrighted and
+ * licensed separately, as follows:
+ *
+ * (C) 2014 DTS, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
  */
 
 #ifndef AUDIO_EXTN_H
@@ -51,15 +69,34 @@
 #define AUDIO_DEVICE_IN_FM_RX_A2DP (AUDIO_DEVICE_BIT_IN | 0x10000)
 #endif
 
-#ifndef QTI_FLAC_DECODER
-#define AUDIO_FORMAT_FLAC 0x19000000UL
-#define AUDIO_OFFLOAD_CODEC_FLAC_MIN_BLK_SIZE "music_offload_flac_min_blk_size"
-#define AUDIO_OFFLOAD_CODEC_FLAC_MAX_BLK_SIZE "music_offload_flac_max_blk_size"
-#define AUDIO_OFFLOAD_CODEC_FLAC_MIN_FRAME_SIZE "music_offload_flac_min_frame_size"
-#define AUDIO_OFFLOAD_CODEC_FLAC_MAX_FRAME_SIZE "music_offload_flac_max_frame_size"
-#define PCM_OUTPUT_BIT_WIDTH (CODEC_BACKEND_DEFAULT_BIT_WIDTH)
+#ifndef FLAC_OFFLOAD_ENABLED
+#define AUDIO_FORMAT_FLAC 0x1D000000UL
+#endif
+
+#ifndef WMA_OFFLOAD_ENABLED
+#define AUDIO_FORMAT_WMA 0x13000000UL
+#define AUDIO_FORMAT_WMAPRO 0x14000000UL
+#endif
+
+#ifndef ALAC_OFFLOAD_ENABLED
+#define AUDIO_FORMAT_ALAC 0x1F000000UL
+#endif
+
+#ifndef APE_OFFLOAD_ENABLED
+#define AUDIO_FORMAT_APE 0x20000000UL
+#endif
+
+#ifndef COMPRESS_METADATA_NEEDED
+#define audio_extn_parse_compress_metadata(out, parms) (0)
 #else
+int audio_extn_parse_compress_metadata(struct stream_out *out,
+                                       struct str_parms *parms);
+#endif
+
+#ifdef PCM_OFFLOAD_ENABLED_24
 #define PCM_OUTPUT_BIT_WIDTH (config->offload_info.bit_width)
+#else
+#define PCM_OUTPUT_BIT_WIDTH (CODEC_BACKEND_DEFAULT_BIT_WIDTH)
 #endif
 
 #define MAX_LENGTH_MIXER_CONTROL_IN_INT                  (128)
@@ -251,6 +288,28 @@
 void audio_extn_compr_cap_deinit();
 #endif
 
+#ifndef DTS_EAGLE
+#define audio_extn_dts_eagle_set_parameters(adev, parms)     (0)
+#define audio_extn_dts_eagle_get_parameters(adev, query, reply) (0)
+#define audio_extn_dts_eagle_fade(adev, fade_in, out) (0)
+#define audio_extn_dts_create_state_notifier_node(stream_out) (0)
+#define audio_extn_dts_notify_playback_state(stream_out, has_video, sample_rate, \
+                                    channels, is_playing) (0)
+#define audio_extn_dts_remove_state_notifier_node(stream_out) (0)
+#define audio_extn_check_and_set_dts_hpx_state(adev)       (0)
+#else
+void audio_extn_dts_eagle_set_parameters(struct audio_device *adev,
+                                         struct str_parms *parms);
+int audio_extn_dts_eagle_get_parameters(const struct audio_device *adev,
+                  struct str_parms *query, struct str_parms *reply);
+int audio_extn_dts_eagle_fade(const struct audio_device *adev, bool fade_in, const struct stream_out *out);
+void audio_extn_dts_create_state_notifier_node(int stream_out);
+void audio_extn_dts_notify_playback_state(int stream_out, int has_video, int sample_rate,
+                                  int channels, int is_playing);
+void audio_extn_dts_remove_state_notifier_node(int stream_out);
+void audio_extn_check_and_set_dts_hpx_state(const struct audio_device *adev);
+#endif
+
 #if defined(DS1_DOLBY_DDP_ENABLED) || defined(DS1_DOLBY_DAP_ENABLED)
 void audio_extn_dolby_set_dmid(struct audio_device *adev);
 #else
@@ -288,6 +347,34 @@
 void audio_extn_ddp_set_parameters(struct audio_device *adev,
                                    struct str_parms *parms);
 void audio_extn_dolby_send_ddp_endp_params(struct audio_device *adev);
+
+#endif
+
+#ifndef HDMI_PASSTHROUGH_ENABLED
+#define audio_extn_dolby_update_passt_formats(adev, out)                   (0)
+#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(flags)                      (0)
+#define audio_extn_dolby_set_hdmi_config(adev, 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)
+#else
+int audio_extn_dolby_update_passt_formats(struct audio_device *adev,
+                                          struct stream_out *out);
+bool audio_extn_dolby_is_passt_convert_supported(struct audio_device *adev,
+                                                 struct stream_out *out);
+bool audio_extn_dolby_is_passt_supported(struct audio_device *adev,
+                                         struct stream_out *out);
+void audio_extn_dolby_update_passt_stream_configuration(struct audio_device *adev,
+                                                 struct stream_out *out);
+bool audio_extn_dolby_is_passthrough_stream(int flags);
+int audio_extn_dolby_set_hdmi_config(struct audio_device *adev,
+                                     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);
 #endif
 
 #ifndef HFP_ENABLED
@@ -373,11 +460,14 @@
 typedef enum {
     DAP_STATE_ON = 0,
     DAP_STATE_BYPASS,
-};
+} dap_state;
 #ifndef AUDIO_FORMAT_E_AC3_JOC
 #define AUDIO_FORMAT_E_AC3_JOC  0x19000000UL
 #endif
 
+int b64decode(char *inp, int ilen, uint8_t* outp);
+int b64encode(uint8_t *inp, int ilen, char* outp);
+
 #ifndef KPI_OPTIMIZE_ENABLED
 #define audio_extn_perf_lock_init() (0)
 #define audio_extn_perf_lock_acquire() (0)
diff --git a/hal/audio_extn/dev_arbi.c b/hal/audio_extn/dev_arbi.c
index d3c01c5..d7ab5ff 100644
--- a/hal/audio_extn/dev_arbi.c
+++ b/hal/audio_extn/dev_arbi.c
@@ -128,7 +128,13 @@
 {
     static snd_aud_dev_mapping_t snd_aud_dev_map[] = {
         {SND_DEVICE_OUT_HANDSET, AUDIO_DEVICE_OUT_EARPIECE},
-        {SND_DEVICE_OUT_VOICE_HANDSET, AUDIO_DEVICE_OUT_EARPIECE}
+        {SND_DEVICE_OUT_VOICE_HANDSET, AUDIO_DEVICE_OUT_EARPIECE},
+        {SND_DEVICE_OUT_SPEAKER, AUDIO_DEVICE_OUT_SPEAKER},
+        {SND_DEVICE_OUT_VOICE_SPEAKER, AUDIO_DEVICE_OUT_SPEAKER},
+        {SND_DEVICE_OUT_HEADPHONES, AUDIO_DEVICE_OUT_WIRED_HEADPHONE},
+        {SND_DEVICE_OUT_VOICE_HEADPHONES, AUDIO_DEVICE_OUT_WIRED_HEADPHONE},
+        {SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES,
+            AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_WIRED_HEADPHONE}
     };
 
     audio_devices_t aud_device = AUDIO_DEVICE_NONE;
diff --git a/hal/audio_extn/dolby.c b/hal/audio_extn/dolby.c
index 6e0b0ee..92ef4ac 100644
--- a/hal/audio_extn/dolby.c
+++ b/hal/audio_extn/dolby.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011-2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2015, The Linux Foundation. All rights reserved.
  * Not a Contribution.
  *
  * Copyright (C) 2010 The Android Open Source Project
@@ -18,9 +18,8 @@
  */
 
 #define LOG_TAG "audio_hw_dolby"
-#define LOG_NDEBUG 0
-#define LOG_NDDEBUG 0
-
+//#define LOG_NDEBUG 0
+//#define LOG_NDDEBUG 0
 #include <errno.h>
 #include <cutils/properties.h>
 #include <stdlib.h>
@@ -408,6 +407,118 @@
 }
 #endif /* DS1_DOLBY_DDP_ENABLED || DS2_DOLBY_DAP_ENABLED */
 
+#ifdef HDMI_PASSTHROUGH_ENABLED
+int audio_extn_dolby_update_passt_formats(struct audio_device *adev,
+                                          struct stream_out *out) {
+    int32_t i = 0, ret = -ENOSYS;
+
+    if (platform_is_edid_supported_format(adev->platform, AUDIO_FORMAT_AC3) ||
+        platform_is_edid_supported_format(adev->platform, AUDIO_FORMAT_E_AC3)) {
+        out->supported_formats[i++] = AUDIO_FORMAT_AC3;
+        out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
+        /* Reciever must support JOC and advertise, otherwise JOC is treated as DDP */
+        out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
+        ret = 0;
+    }
+    ALOGV("%s: ret = %d", __func__, ret);
+    return ret;
+}
+
+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(int flags) {
+
+    if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH)
+        return true;
+    return false;
+}
+
+int audio_extn_dolby_set_hdmi_config(struct audio_device *adev,
+                                                    struct stream_out *out) {
+    return platform_set_hdmi_config(out);
+}
+
+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)
 {
@@ -464,7 +575,7 @@
         return;
 
     property_get("dmid",c_dmid,"0");
-    i_dmid = atoi(c_dmid);
+    i_dmid = atoll(c_dmid);
 
     ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
     if (!ctl) {
@@ -653,7 +764,7 @@
     i_key = 0;
 #endif
     property_get("dmid",c_dmid,"0");
-    i_dmid = atoi(c_dmid);
+    i_dmid = atoll(c_dmid);
     ALOGV("%s Setting DS1 License, key:0x%x dmid %d",__func__, i_key,i_dmid);
     dolby_license.dmid = i_dmid;
     dolby_license.license_key = i_key;
diff --git a/hal/audio_extn/dts_eagle.c b/hal/audio_extn/dts_eagle.c
new file mode 100644
index 0000000..52d7abb
--- /dev/null
+++ b/hal/audio_extn/dts_eagle.c
@@ -0,0 +1,501 @@
+/*
+ *  (C) 2014 DTS, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "audio_hw_dts_eagle"
+/*#define LOG_NDEBUG 0*/
+
+#include <errno.h>
+#include <math.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <cutils/log.h>
+#include <cutils/properties.h>
+#include <cutils/str_parms.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sound/asound.h>
+#include <sound/audio_effects.h>
+#include <sound/devdep_params.h>
+#include "audio_hw.h"
+#include "platform.h"
+#include "platform_api.h"
+
+#ifdef DTS_EAGLE
+
+#define AUDIO_PARAMETER_KEY_DTS_EAGLE   "DTS_EAGLE"
+#define STATE_NOTIFY_FILE               "/data/misc/dts/stream"
+#define FADE_NOTIFY_FILE                "/data/misc/dts/fade"
+#define DTS_EAGLE_KEY                   "DTS_EAGLE"
+#define DEVICE_NODE                     "/dev/snd/hwC0D3"
+#define MAX_LENGTH_OF_INTEGER_IN_STRING 13
+#define PARAM_GET_MAX_SIZE              512
+
+struct dts_eagle_param_desc_alsa {
+    int alsa_effect_ID;
+    struct dts_eagle_param_desc d;
+};
+
+static struct dts_eagle_param_desc_alsa *fade_in_data = NULL;
+static struct dts_eagle_param_desc_alsa *fade_out_data = NULL;
+static int32_t mDevices = 0;
+static int32_t mCurrDevice = 0;
+static const char* DTS_EAGLE_STR = DTS_EAGLE_KEY;
+
+static int do_DTS_Eagle_params_stream(struct stream_out *out, struct dts_eagle_param_desc_alsa *t, bool get) {
+    char mixer_string[128];
+    char mixer_str_query[128];
+    struct mixer_ctl *ctl;
+    struct mixer_ctl *query_ctl;
+    int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
+
+    ALOGV("DTS_EAGLE_HAL (%s): enter", __func__);
+    snprintf(mixer_string, sizeof(mixer_string), "%s %d", "Audio Effects Config", pcm_device_id);
+    ctl = mixer_get_ctl_by_name(out->dev->mixer, mixer_string);
+    if (!ctl) {
+        ALOGE("DTS_EAGLE_HAL (%s): failed to open mixer %s", __func__, mixer_string);
+    } else if (t) {
+        int size = t->d.size + sizeof(struct dts_eagle_param_desc_alsa);
+        ALOGD("DTS_EAGLE_HAL (%s): opened mixer %s", __func__, mixer_string);
+        if (get) {
+            ALOGD("DTS_EAGLE_HAL (%s): get request", __func__);
+            snprintf(mixer_str_query, sizeof(mixer_str_query), "%s %d", "Query Audio Effect Param", pcm_device_id);
+            query_ctl = mixer_get_ctl_by_name(out->dev->mixer, mixer_str_query);
+            if (!query_ctl) {
+                ALOGE("DTS_EAGLE_HAL (%s): failed to open mixer %s", __func__, mixer_str_query);
+                return -EINVAL;
+            }
+            mixer_ctl_set_array(query_ctl, t, size);
+            return mixer_ctl_get_array(ctl, t, size);
+        }
+        ALOGD("DTS_EAGLE_HAL (%s): set request", __func__);
+        return mixer_ctl_set_array(ctl, t, size);
+    } else {
+        ALOGD("DTS_EAGLE_HAL (%s): parameter data NULL", __func__);
+    }
+    return -EINVAL;
+}
+
+static int do_DTS_Eagle_params(const struct audio_device *adev, struct dts_eagle_param_desc_alsa *t, bool get, const struct stream_out *out) {
+    struct listnode *node;
+    struct audio_usecase *usecase;
+    int ret = 0, sent = 0, tret = 0;
+
+    ALOGV("DTS_EAGLE_HAL (%s): enter", __func__);
+
+    if (out) {
+        /* if valid out stream is given, then send params to this stream only */
+        tret = do_DTS_Eagle_params_stream(out, t, get);
+        if (tret < 0)
+            ret = tret;
+        else
+            sent = 1;
+    } else {
+        list_for_each(node, &adev->usecase_list) {
+            usecase = node_to_item(node, struct audio_usecase, list);
+            /* set/get eagle params for offload usecases only */
+            if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
+                tret = do_DTS_Eagle_params_stream(usecase->stream.out, t, get);
+                if (tret < 0)
+                    ret = tret;
+                else
+                    sent = 1;
+            }
+        }
+    }
+
+    if (!sent) {
+        int fd = open(DEVICE_NODE, O_RDWR);
+
+        if (get) {
+            ALOGD("DTS_EAGLE_HAL (%s): no stream opened, attempting to retrieve directly from cache", __func__);
+            t->d.device &= ~DTS_EAGLE_FLAG_ALSA_GET;
+        } else {
+            ALOGD("DTS_EAGLE_HAL (%s): no stream opened, attempting to send directly to cache", __func__);
+            t->d.device |= DTS_EAGLE_FLAG_IOCTL_JUSTSETCACHE;
+        }
+
+        if (fd > 0) {
+            int cmd = get ? DTS_EAGLE_IOCTL_GET_PARAM : DTS_EAGLE_IOCTL_SET_PARAM;
+            if (ioctl(fd, cmd, &t->d) < 0) {
+                ALOGE("DTS_EAGLE_HAL (%s): error sending/getting param\n", __func__);
+                ret = -EINVAL;
+            } else {
+                ALOGD("DTS_EAGLE_HAL (%s): sent/retrieved param\n", __func__);
+            }
+            close(fd);
+        } else {
+            ALOGE("DTS_EAGLE_HAL (%s): couldn't open device %s\n", __func__, DEVICE_NODE);
+            ret = -EINVAL;
+        }
+    }
+    return ret;
+}
+
+static void fade_node(bool need_data) {
+    char prop[PROPERTY_VALUE_MAX];
+    property_get("use.dts_eagle", prop, "0");
+    if (strncmp("true", prop, sizeof("true")))
+        return;
+    int fd, n = 0;
+    if ((fd = open(FADE_NOTIFY_FILE, O_TRUNC|O_WRONLY)) < 0) {
+        ALOGV("No fade node, create one");
+        fd = creat(FADE_NOTIFY_FILE, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
+        if (fd < 0) {
+            ALOGE("DTS_EAGLE_HAL (%s): Creating fade notifier node failed", __func__);
+            return;
+        }
+        chmod(FADE_NOTIFY_FILE, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH);
+    }
+    char *str = need_data ? "need" : "have";
+    n = write(fd, str, strlen(str));
+    close(fd);
+    if (n > 0)
+        ALOGI("DTS_EAGLE_HAL (%s): fade notifier node set to \"%s\", %i bytes written", __func__, str, n);
+    else
+        ALOGE("DTS_EAGLE_HAL (%s): error writing to fade notifier node", __func__);
+}
+
+int audio_extn_dts_eagle_fade(const struct audio_device *adev, bool fade_in, const struct stream_out *out) {
+    char prop[PROPERTY_VALUE_MAX];
+
+    ALOGV("DTS_EAGLE_HAL (%s): enter with fade %s requested", __func__, fade_in ? "in" : "out");
+
+    property_get("use.dts_eagle", prop, "0");
+    if (strncmp("true", prop, sizeof("true")))
+        return 0;
+
+    if (!fade_in_data || !fade_out_data)
+        fade_node(true);
+
+    if (fade_in) {
+        if (fade_in_data)
+            return do_DTS_Eagle_params(adev, fade_in_data, false, out);
+    } else {
+        if (fade_out_data)
+            return do_DTS_Eagle_params(adev, fade_out_data, false, out);
+    }
+    return 0;
+}
+
+void audio_extn_dts_eagle_set_parameters(struct audio_device *adev, struct str_parms *parms) {
+    int ret, val;
+    char value[32] = { 0 }, prop[PROPERTY_VALUE_MAX];
+
+    ALOGV("DTS_EAGLE_HAL (%s): enter", __func__);
+
+    property_get("use.dts_eagle", prop, "0");
+    if (strncmp("true", prop, sizeof("true")))
+        return;
+
+    memset(value, 0, sizeof(value));
+    ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_DTS_EAGLE, value, sizeof(value));
+    if (ret >= 0) {
+        int *data = NULL, id, size, offset, count, dev, dts_found = 0, fade_in = 0;
+        struct dts_eagle_param_desc_alsa *t2 = NULL, **t = &t2;
+
+        ret = str_parms_get_str(parms, "fade", value, sizeof(value));
+        if (ret >= 0) {
+            fade_in = atoi(value);
+            if (fade_in > 0) {
+                t = (fade_in == 1) ? &fade_in_data : &fade_out_data;
+            }
+        }
+
+        ret = str_parms_get_str(parms, "count", value, sizeof(value));
+        if (ret >= 0) {
+            count = atoi(value);
+            if (count > 1) {
+                int tmp_size = count * 32;
+                char *tmp = malloc(tmp_size+1);
+                data = malloc(sizeof(int) * count);
+                ALOGV("DTS_EAGLE_HAL (%s): multi count param detected, count: %d", __func__, count);
+                if (data && tmp) {
+                    ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_DTS_EAGLE, tmp, tmp_size);
+                    if (ret >= 0) {
+                        int idx = 0, tidx, tcnt = 0;
+                        dts_found = 1;
+                        do {
+                            sscanf(&tmp[idx], "%i", &data[tcnt]);
+                            tidx = strcspn(&tmp[idx], ",");
+                            if (idx + tidx >= ret && tcnt < count-1) {
+                                ALOGE("DTS_EAGLE_HAL (%s): malformed multi value string.", __func__);
+                                dts_found = 0;
+                                break;
+                            }
+                            ALOGD("DTS_EAGLE_HAL (%s): %i:%i (next %s)", __func__, tcnt, data[tcnt], &tmp[idx+tidx]);
+                            idx += tidx + 1;
+                            tidx = 0;
+                            tcnt++;
+                        } while (tcnt < count);
+                    }
+                } else {
+                    ALOGE("DTS_EAGLE_HAL (%s): mem alloc for multi count param parse failed.", __func__);
+                }
+                free(tmp);
+            }
+        }
+
+        if (!dts_found) {
+            data = malloc(sizeof(int));
+            if (data) {
+                ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_DTS_EAGLE, value, sizeof(value));
+                if (ret >= 0) {
+                    *data = atoi(value);
+                    dts_found = 1;
+                    count = 1;
+                } else {
+                    ALOGE("DTS_EAGLE_HAL (%s): malformed value string.", __func__);
+                }
+            } else {
+                ALOGE("DTS_EAGLE_HAL (%s): mem alloc for param parse failed.", __func__);
+            }
+        }
+
+        if (dts_found) {
+            dts_found = 0;
+            ret = str_parms_get_str(parms, "id", value, sizeof(value));
+            if (ret >= 0) {
+                if (sscanf(value, "%x", &id) == 1) {
+                    ret = str_parms_get_str(parms, "size", value, sizeof(value));
+                    if (ret >= 0) {
+                        size = atoi(value);
+                        ret = str_parms_get_str(parms, "offset", value, sizeof(value));
+                        if (ret >= 0) {
+                            offset = atoi(value);
+                            ret = str_parms_get_str(parms, "device", value, sizeof(value));
+                            if (ret >= 0) {
+                                dev = atoi(value);
+                                dts_found = 1;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        if (dts_found && count > 1 && size != (int)(count * sizeof(int))) {
+            ALOGE("DTS_EAGLE_HAL (%s): size/count mismatch (size = %i bytes, count = %i integers / %u bytes).", __func__, size, count, count*sizeof(int));
+        } else if (dts_found) {
+            ALOGI("DTS_EAGLE_HAL (%s): param detected: %s", __func__, str_parms_to_str(parms));
+            if (!(*t))
+                *t = (struct dts_eagle_param_desc_alsa*)malloc(sizeof(struct dts_eagle_param_desc_alsa) + size);
+            if (*t) {
+                (*t)->alsa_effect_ID = DTS_EAGLE_MODULE;
+                (*t)->d.id = id;
+                (*t)->d.size = size;
+                (*t)->d.offset = offset;
+                (*t)->d.device = dev;
+                memcpy((void*)((char*)*t + sizeof(struct dts_eagle_param_desc_alsa)), data, size);
+                ALOGD("DTS_EAGLE_HAL (%s): id: 0x%X, size: %d, offset: %d, device: %d", __func__,
+                       (*t)->d.id, (*t)->d.size, (*t)->d.offset, (*t)->d.device);
+                if (!fade_in) {
+                    ret = do_DTS_Eagle_params(adev, *t, false, NULL);
+                    if (ret < 0)
+                        ALOGE("DTS_EAGLE_HAL (%s): failed setting params in kernel with error %i", __func__, ret);
+                }
+                free(t2);
+            } else {
+                ALOGE("DTS_EAGLE_HAL (%s): mem alloc for dsp structure failed.", __func__);
+            }
+        } else {
+            ALOGE("DTS_EAGLE_HAL (%s): param detected but failed parse: %s", __func__, str_parms_to_str(parms));
+        }
+        free(data);
+
+        if (fade_in > 0 && fade_in_data && fade_out_data)
+            fade_node(false);
+    }
+    ALOGV("DTS_EAGLE_HAL (%s): exit", __func__);
+}
+
+int audio_extn_dts_eagle_get_parameters(const struct audio_device *adev,
+                  struct str_parms *query, struct str_parms *reply) {
+    int ret, val;
+    char value[32] = { 0 }, prop[PROPERTY_VALUE_MAX];
+    char params[PARAM_GET_MAX_SIZE];
+
+    ALOGV("DTS_EAGLE_HAL (%s): enter", __func__);
+
+    property_get("use.dts_eagle", prop, "0");
+    if (strncmp("true", prop, sizeof("true")))
+        return 0;
+
+    ret = str_parms_get_str(query, AUDIO_PARAMETER_KEY_DTS_EAGLE, value, sizeof(value));
+    if (ret >= 0) {
+        int *data = NULL, id = 0, size = 0, offset = 0,
+            count = 1, dev = 0, idx = 0, dts_found = 0, i = 0;
+        const size_t chars_4_int = 16;
+        ret = str_parms_get_str(query, "count", value, sizeof(value));
+        if (ret >= 0) {
+            count = atoi(value);
+            if (count > 1) {
+                ALOGV("DTS_EAGLE_HAL (%s): multi count param detected, count: %d", __func__, count);
+            } else {
+                count = 1;
+            }
+        }
+
+        ret = str_parms_get_str(query, "id", value, sizeof(value));
+        if (ret >= 0) {
+            if (sscanf(value, "%x", &id) == 1) {
+                ret = str_parms_get_str(query, "size", value, sizeof(value));
+                if (ret >= 0) {
+                    size = atoi(value);
+                    ret = str_parms_get_str(query, "offset", value, sizeof(value));
+                    if (ret >= 0) {
+                        offset = atoi(value);
+                        ret = str_parms_get_str(query, "device", value, sizeof(value));
+                        if (ret >= 0) {
+                            dev = atoi(value);
+                            dts_found = 1;
+                        }
+                    }
+                }
+            }
+        }
+
+        if (dts_found) {
+            ALOGI("DTS_EAGLE_HAL (%s): param (get) detected: %s", __func__, str_parms_to_str(query));
+            struct dts_eagle_param_desc_alsa *t = (struct dts_eagle_param_desc_alsa *)params;
+            if (t) {
+                char buf[chars_4_int*count];
+                t->alsa_effect_ID = DTS_EAGLE_MODULE;
+                t->d.id = id;
+                t->d.size = size;
+                t->d.offset = offset;
+                t->d.device = dev;
+                ALOGV("DTS_EAGLE_HAL (%s): id (get): 0x%X, size: %d, offset: %d, device: %d", __func__,
+                       t->d.id, t->d.size, t->d.offset, t->d.device & 0x7FFFFFFF);
+                if ((sizeof(struct dts_eagle_param_desc_alsa) + size) > PARAM_GET_MAX_SIZE) {
+                    ALOGE("%s: requested data too large", __func__);
+                    return -1;
+                }
+                ret = do_DTS_Eagle_params(adev, t, true, NULL);
+                if (ret >= 0) {
+                    data = (int*)(params + sizeof(struct dts_eagle_param_desc_alsa));
+                    for (i = 0; i < count; i++)
+                        idx += snprintf(&buf[idx], chars_4_int, "%i,", data[i]);
+                    buf[idx > 0 ? idx-1 : 0] = 0;
+                    ALOGD("DTS_EAGLE_HAL (%s): get result: %s", __func__, buf);
+                    str_parms_add_int(reply, "size", size);
+                    str_parms_add_str(reply, AUDIO_PARAMETER_KEY_DTS_EAGLE, buf);
+                    str_parms_add_int(reply, "count", count);
+                    snprintf(value, sizeof(value), "0x%x", id);
+                    str_parms_add_str(reply, "id", value);
+                    str_parms_add_int(reply, "device", dev);
+                    str_parms_add_int(reply, "offset", offset);
+                    ALOGV("DTS_EAGLE_HAL (%s): reply: %s", __func__, str_parms_to_str(reply));
+                } else {
+                    ALOGE("DTS_EAGLE_HAL (%s): failed getting params from kernel with error %i", __func__, ret);
+                    return -1;
+                }
+            } else {
+                ALOGE("DTS_EAGLE_HAL (%s): mem alloc for (get) dsp structure failed.", __func__);
+                return -1;
+            }
+        } else {
+            ALOGE("DTS_EAGLE_HAL (%s): param (get) detected but failed parse: %s", __func__, str_parms_to_str(query));
+            return -1;
+        }
+    }
+
+    ALOGV("DTS_EAGLE_HAL (%s): exit", __func__);
+    return 0;
+}
+
+void audio_extn_dts_create_state_notifier_node(int stream_out)
+{
+    char prop[PROPERTY_VALUE_MAX];
+    char path[PATH_MAX];
+    char value[MAX_LENGTH_OF_INTEGER_IN_STRING];
+    int fd;
+    property_get("use.dts_eagle", prop, "0");
+    if ((!strncmp("true", prop, sizeof("true")) || atoi(prop))) {
+        ALOGV("DTS_EAGLE_NODE_STREAM (%s): create_state_notifier_node - stream_out: %d", __func__, stream_out);
+        strlcpy(path, STATE_NOTIFY_FILE, sizeof(path));
+        snprintf(value, sizeof(value), "%d", stream_out);
+        strlcat(path, value, sizeof(path));
+
+        if ((fd=open(path, O_RDONLY)) < 0) {
+            ALOGV("DTS_EAGLE_NODE_STREAM (%s): no file exists", __func__);
+        } else {
+            ALOGV("DTS_EAGLE_NODE_STREAM (%s): a file with the same name exists, removing it before creating it", __func__);
+            close(fd);
+            remove(path);
+        }
+        if ((fd=creat(path, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) < 0) {
+            ALOGE("DTS_EAGLE_NODE_STREAM (%s): opening state notifier node failed returned", __func__);
+            return;
+        }
+        chmod(path, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH);
+        ALOGV("DTS_EAGLE_NODE_STREAM (%s): opening state notifier node successful", __func__);
+        close(fd);
+        if (!fade_in_data || !fade_out_data)
+            fade_node(true);
+    }
+}
+
+void audio_extn_dts_notify_playback_state(int stream_out, int has_video, int sample_rate,
+                           int channels, int is_playing) {
+    char prop[PROPERTY_VALUE_MAX];
+    char path[PATH_MAX];
+    char value[MAX_LENGTH_OF_INTEGER_IN_STRING];
+    char buf[1024];
+    int fd;
+    property_get("use.dts_eagle", prop, "0");
+    if ((!strncmp("true", prop, sizeof("true")) || atoi(prop))) {
+        ALOGV("DTS_EAGLE_NODE_STREAM (%s): notify_playback_state - is_playing: %d", __func__, is_playing);
+        strlcpy(path, STATE_NOTIFY_FILE, sizeof(path));
+        snprintf(value, sizeof(value), "%d", stream_out);
+        strlcat(path, value, sizeof(path));
+        if ((fd=open(path, O_TRUNC|O_WRONLY)) < 0) {
+            ALOGE("DTS_EAGLE_NODE_STREAM (%s): open state notifier node failed", __func__);
+        } else {
+            snprintf(buf, sizeof(buf), "has_video=%d;sample_rate=%d;channel_mode=%d;playback_state=%d",
+                     has_video, sample_rate, channels, is_playing);
+            int n = write(fd, buf, strlen(buf));
+            if (n > 0)
+                ALOGV("DTS_EAGLE_NODE_STREAM (%s): write to state notifier node successful, bytes written: %d", __func__, n);
+            else
+                ALOGE("DTS_EAGLE_NODE_STREAM (%s): write state notifier node failed", __func__);
+            close(fd);
+        }
+    }
+}
+
+void audio_extn_dts_remove_state_notifier_node(int stream_out)
+{
+    char prop[PROPERTY_VALUE_MAX];
+    char path[PATH_MAX];
+    char value[MAX_LENGTH_OF_INTEGER_IN_STRING];
+    int fd;
+    property_get("use.dts_eagle", prop, "0");
+    if ((!strncmp("true", prop, sizeof("true")) || atoi(prop)) && (stream_out)) {
+        ALOGV("DTS_EAGLE_NODE_STREAM (%s): remove_state_notifier_node: stream_out - %d", __func__, stream_out);
+        strlcpy(path, STATE_NOTIFY_FILE, sizeof(path));
+        snprintf(value, sizeof(value), "%d", stream_out);
+        strlcat(path, value, sizeof(path));
+        if ((fd=open(path, O_RDONLY)) < 0) {
+            ALOGV("DTS_EAGLE_NODE_STREAM (%s): open state notifier node failed", __func__);
+        } else {
+            ALOGV("DTS_EAGLE_NODE_STREAM (%s): open state notifier node successful, removing the file", __func__);
+            close(fd);
+            remove(path);
+        }
+    }
+}
+
+#endif /* DTS_EAGLE end */
diff --git a/hal/audio_extn/soundtrigger.c b/hal/audio_extn/soundtrigger.c
index 5f4c6ba..9051334 100644
--- a/hal/audio_extn/soundtrigger.c
+++ b/hal/audio_extn/soundtrigger.c
@@ -165,6 +165,7 @@
             in->config = st_ses_info->st_ses.config;
             in->channel_mask = audio_channel_in_mask_from_count(in->config.channels);
             in->is_st_session = true;
+            in->is_st_session_active = true;
             ALOGD("%s: capture_handle %d is sound trigger", __func__, in->capture_handle);
             break;
         }
diff --git a/hal/audio_extn/source_track.c b/hal/audio_extn/source_track.c
new file mode 100644
index 0000000..316e52d
--- /dev/null
+++ b/hal/audio_extn/source_track.c
@@ -0,0 +1,640 @@
+/*
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above
+ *     copyright notice, this list of conditions and the following
+ *     disclaimer in the documentation and/or other materials provided
+ *     with the distribution.
+ *   * Neither the name of The Linux Foundation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#define LOG_TAG "source_track"
+/*#define LOG_NDEBUG 0*/
+#define LOG_NDDEBUG 0
+
+#include <errno.h>
+#include <math.h>
+#include <cutils/log.h>
+
+#include "audio_hw.h"
+#include "platform.h"
+#include "platform_api.h"
+#include "voice_extn.h"
+#include <stdlib.h>
+#include <cutils/str_parms.h>
+
+#ifdef SOURCE_TRACKING_ENABLED
+/* Audio Paramater Key to identify the list of start angles.
+ * Starting angle (in degrees) defines the boundary starting angle for each sector.
+ */
+#define AUDIO_PARAMETER_KEY_SOUND_FOCUS_START_ANGLES        "SoundFocus.start_angles"
+/* Audio Paramater Key to identify the list of enable flags corresponding to each sector.
+ */
+#define AUDIO_PARAMETER_KEY_SOUND_FOCUS_ENABLE_SECTORS      "SoundFocus.enable_sectors"
+/* Audio Paramater Key to identify the gain step value to be applied to all enabled sectors.
+ */
+#define AUDIO_PARAMETER_KEY_SOUND_FOCUS_GAIN_STEP           "SoundFocus.gain_step"
+/* Audio Paramater Key to identify the list of voice activity detector outputs corresponding
+ * to each sector.
+ */
+#define AUDIO_PARAMETER_KEY_SOURCE_TRACK_VAD                "SourceTrack.vad"
+/* Audio Paramater Key to identify the direction (in degrees) of arrival for desired talker
+ * (dominant source of speech).
+ */
+#define AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_SPEECH         "SourceTrack.doa_speech"
+/* Audio Paramater Key to identify the list of directions (in degrees) of arrival for
+ * interferers (interfering noise sources).
+ */
+#define AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_NOISE          "SourceTrack.doa_noise"
+/* Audio Paramater Key to identify the list of sound strength indicators at each degree
+ * of the horizontal plane referred to by a full circle (360 degrees).
+ */
+#define AUDIO_PARAMETER_KEY_SOURCE_TRACK_POLAR_ACTIVITY     "SourceTrack.polar_activity"
+
+#define BITMASK_AUDIO_PARAMETER_KEY_SOUND_FOCUS_START_ANGLES        0x1
+#define BITMASK_AUDIO_PARAMETER_KEY_SOUND_FOCUS_ENABLE_SECTORS      0x2
+#define BITMASK_AUDIO_PARAMETER_KEY_SOUND_FOCUS_GAIN_STEP           0x4
+#define BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_VAD                0x8
+#define BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_SPEECH         0x10
+#define BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_NOISE          0x20
+#define BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_POLAR_ACTIVITY     0x40
+
+#define BITMASK_AUDIO_PARAMETER_KEYS_SOUND_FOCUS \
+     (BITMASK_AUDIO_PARAMETER_KEY_SOUND_FOCUS_START_ANGLES |\
+      BITMASK_AUDIO_PARAMETER_KEY_SOUND_FOCUS_ENABLE_SECTORS |\
+      BITMASK_AUDIO_PARAMETER_KEY_SOUND_FOCUS_GAIN_STEP)
+
+#define BITMASK_AUDIO_PARAMETER_KEYS_SOURCE_TRACKING \
+     (BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_VAD |\
+      BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_SPEECH |\
+      BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_NOISE |\
+      BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_POLAR_ACTIVITY)
+
+#define MAX_SECTORS                                         8
+#define MAX_STR_SIZE                                       2048
+
+struct audio_device_to_audio_interface audio_device_to_interface_table[];
+int audio_device_to_interface_table_len;
+
+struct sound_focus_param {
+    uint16_t start_angle[MAX_SECTORS];
+    uint8_t enable[MAX_SECTORS];
+    uint16_t gain_step;
+};
+
+struct source_tracking_param {
+    uint8_t vad[MAX_SECTORS];
+    uint16_t doa_speech;
+    uint16_t doa_noise[3];
+    uint8_t polar_activity[360];
+};
+
+static int add_audio_intf_name_to_mixer_ctl(audio_devices_t device, char *mixer_ctl_name,
+                                struct audio_device_to_audio_interface *table, int len)
+{
+    int ret = 0;
+    int i;
+
+    if (table == NULL) {
+        ALOGE("%s: table is NULL", __func__);
+
+        ret = -EINVAL;
+        goto done;
+    }
+
+    if (mixer_ctl_name == NULL) {
+        ret = -EINVAL;
+        goto done;
+    }
+
+    for (i=0; i < len; i++) {
+        if (device == table[i].device) {
+             strlcat(mixer_ctl_name, " ", MIXER_PATH_MAX_LENGTH);
+             strlcat(mixer_ctl_name, table[i].interface_name, MIXER_PATH_MAX_LENGTH);
+             break;
+        }
+    }
+
+    if (i == len) {
+        ALOGE("%s: Audio Device not found in the table", __func__);
+
+        ret = -EINVAL;
+    }
+done:
+    return ret;
+}
+
+static bool is_stt_supported_snd_device(snd_device_t snd_device)
+{
+    bool ret = false;
+
+    switch (snd_device) {
+    case SND_DEVICE_IN_HANDSET_DMIC:
+    case SND_DEVICE_IN_HANDSET_DMIC_AEC:
+    case SND_DEVICE_IN_HANDSET_DMIC_NS:
+    case SND_DEVICE_IN_HANDSET_DMIC_AEC_NS:
+    case SND_DEVICE_IN_HANDSET_STEREO_DMIC:
+    case SND_DEVICE_IN_HANDSET_QMIC:
+    case SND_DEVICE_IN_VOICE_DMIC:
+    case SND_DEVICE_IN_VOICE_REC_DMIC_FLUENCE:
+    case SND_DEVICE_IN_HEADSET_MIC_FLUENCE:
+    case SND_DEVICE_IN_SPEAKER_DMIC:
+    case SND_DEVICE_IN_SPEAKER_DMIC_AEC:
+    case SND_DEVICE_IN_SPEAKER_DMIC_NS:
+    case SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS:
+    case SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS_BROADSIDE:
+    case SND_DEVICE_IN_SPEAKER_DMIC_AEC_BROADSIDE:
+    case SND_DEVICE_IN_SPEAKER_DMIC_NS_BROADSIDE:
+    case SND_DEVICE_IN_SPEAKER_QMIC_AEC:
+    case SND_DEVICE_IN_SPEAKER_QMIC_NS:
+    case SND_DEVICE_IN_SPEAKER_QMIC_AEC_NS:
+    case SND_DEVICE_IN_VOICE_SPEAKER_DMIC:
+    case SND_DEVICE_IN_VOICE_SPEAKER_DMIC_BROADSIDE:
+    case SND_DEVICE_IN_VOICE_SPEAKER_QMIC:
+        ret = true;
+        break;
+    default:
+        break;
+    }
+
+    return ret;
+}
+
+audio_devices_t get_input_audio_device(audio_devices_t device)
+{
+    audio_devices_t in_device = device;
+
+    switch (device) {
+    case AUDIO_DEVICE_OUT_EARPIECE:
+    case AUDIO_DEVICE_OUT_WIRED_HEADPHONE:
+        in_device = AUDIO_DEVICE_IN_BUILTIN_MIC;
+        break;
+    case AUDIO_DEVICE_OUT_SPEAKER:
+        in_device = AUDIO_DEVICE_IN_BACK_MIC;
+        break;
+    case AUDIO_DEVICE_OUT_WIRED_HEADSET:
+        in_device = AUDIO_DEVICE_IN_WIRED_HEADSET;
+        break;
+    case AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET:
+        in_device = AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET;
+        break;
+    default:
+        break;
+    }
+
+    return in_device;
+}
+
+static int derive_mixer_ctl_from_usecase_intf(struct audio_device *adev,
+                                              char *mixer_ctl_name) {
+    struct audio_usecase *usecase = NULL;
+    audio_devices_t in_device;
+    int ret = 0;
+
+    if (mixer_ctl_name == NULL) {
+        ALOGE("%s: mixer_ctl_name is NULL", __func__);
+
+        ret = -EINVAL;
+        goto done;
+    }
+
+    if (voice_is_in_call(adev)) {
+        strlcat(mixer_ctl_name, " ", MIXER_PATH_MAX_LENGTH);
+        strlcat(mixer_ctl_name, "Voice Tx", MIXER_PATH_MAX_LENGTH);
+        usecase = get_usecase_from_list(adev,
+                                        get_usecase_id_from_usecase_type(adev, VOICE_CALL));
+    } else if (voice_extn_compress_voip_is_active(adev)) {
+        strlcat(mixer_ctl_name, " ", MIXER_PATH_MAX_LENGTH);
+        strlcat(mixer_ctl_name, "Voice Tx", MIXER_PATH_MAX_LENGTH);
+        usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
+    } else {
+        strlcat(mixer_ctl_name, " ", MIXER_PATH_MAX_LENGTH);
+        strlcat(mixer_ctl_name, "Audio Tx", MIXER_PATH_MAX_LENGTH);
+        usecase = get_usecase_from_list(adev, get_usecase_id_from_usecase_type(adev, PCM_CAPTURE));
+    }
+
+    if (usecase && (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
+        if (is_stt_supported_snd_device(usecase->in_snd_device)) {
+             in_device = get_input_audio_device(usecase->devices);
+             ret = add_audio_intf_name_to_mixer_ctl(in_device, mixer_ctl_name,
+                audio_device_to_interface_table, audio_device_to_interface_table_len);
+        } else {
+            ALOGE("%s: Sound Focus/Source Tracking not supported on the input sound device (%s)",
+                    __func__, platform_get_snd_device_name(usecase->in_snd_device));
+
+            ret = -EINVAL;
+        }
+    } else {
+        ALOGE("%s: No use case is active which supports Sound Focus/Source Tracking",
+               __func__);
+
+        ret = -EINVAL;
+    }
+
+done:
+    return ret;
+}
+
+static int parse_soundfocus_sourcetracking_keys(struct str_parms *parms)
+{
+    char *str;
+    char *value = NULL;
+    int val, len;
+    int ret = 0, err;
+    char *kv_pairs = str_parms_to_str(parms);
+
+    ALOGV_IF(kv_pairs != NULL, "%s: enter: %s", __func__, kv_pairs);
+
+    len = strlen(kv_pairs);
+    value = (char*)calloc(len, sizeof(char));
+    if(value == NULL) {
+        ret = -ENOMEM;
+        ALOGE("%s: failed to allocate memory", __func__);
+
+        goto done;
+    }
+
+    err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_SOUND_FOCUS_START_ANGLES,
+                            value, len);
+    if (err >= 0) {
+        str_parms_del(parms, AUDIO_PARAMETER_KEY_SOUND_FOCUS_START_ANGLES);
+        ret = ret | BITMASK_AUDIO_PARAMETER_KEY_SOUND_FOCUS_START_ANGLES;
+    }
+
+    err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_SOUND_FOCUS_ENABLE_SECTORS,
+                            value, len);
+    if (err >= 0) {
+        str_parms_del(parms, AUDIO_PARAMETER_KEY_SOUND_FOCUS_ENABLE_SECTORS);
+        ret = ret | BITMASK_AUDIO_PARAMETER_KEY_SOUND_FOCUS_ENABLE_SECTORS;
+    }
+
+    err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_SOUND_FOCUS_GAIN_STEP,
+                            value, len);
+    if (err >= 0) {
+        str_parms_del(parms, AUDIO_PARAMETER_KEY_SOUND_FOCUS_GAIN_STEP);
+        ret = ret | BITMASK_AUDIO_PARAMETER_KEY_SOUND_FOCUS_GAIN_STEP;
+    }
+
+    err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_SOURCE_TRACK_VAD,
+                            value, len);
+    if (err >= 0) {
+        str_parms_del(parms, AUDIO_PARAMETER_KEY_SOURCE_TRACK_VAD);
+        ret = ret | BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_VAD;
+    }
+
+    err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_SPEECH,
+                            value, len);
+    if (err >= 0) {
+        str_parms_del(parms, AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_SPEECH);
+        ret = ret | BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_SPEECH;
+    }
+
+    err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_NOISE,
+                            value, len);
+    if (err >= 0) {
+        str_parms_del(parms, AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_NOISE);
+        ret = ret | BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_NOISE;
+    }
+
+    err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_SOURCE_TRACK_POLAR_ACTIVITY,
+                            value, len);
+    if (err >= 0) {
+        str_parms_del(parms, AUDIO_PARAMETER_KEY_SOURCE_TRACK_POLAR_ACTIVITY);
+        ret = ret | BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_POLAR_ACTIVITY;
+    }
+
+done:
+    free(kv_pairs);
+    if(value != NULL)
+        free(value);
+    ALOGV("%s: returning bitmask = %d", __func__, ret);
+
+    return ret;
+}
+
+static int get_soundfocus_sourcetracking_data(struct audio_device *adev,
+                                        const int bitmask,
+                                        struct sound_focus_param *sound_focus_data,
+                                        struct source_tracking_param *source_tracking_data)
+{
+    struct mixer_ctl *ctl;
+    char sound_focus_mixer_ctl_name[MIXER_PATH_MAX_LENGTH] = "Sound Focus";
+    char source_tracking_mixer_ctl_name[MIXER_PATH_MAX_LENGTH] = "Source Tracking";
+    int ret = -EINVAL;
+    int i, count;
+
+    if (bitmask & BITMASK_AUDIO_PARAMETER_KEYS_SOUND_FOCUS) {
+        /* Derive the mixer control name based on the use case and the audio interface
+         * for the corresponding audio device
+         */
+        ret = derive_mixer_ctl_from_usecase_intf(adev, sound_focus_mixer_ctl_name);
+        if (ret != 0) {
+            ALOGE("%s: Could not get Sound Focus Params", __func__);
+
+            goto done;
+        } else {
+            ALOGV("%s: Mixer Ctl name: %s", __func__, sound_focus_mixer_ctl_name);
+        }
+
+        ctl = mixer_get_ctl_by_name(adev->mixer, sound_focus_mixer_ctl_name);
+        if (!ctl) {
+            ALOGE("%s: Could not get ctl for mixer cmd - %s",
+                  __func__, sound_focus_mixer_ctl_name);
+
+            ret = -EINVAL;
+            goto done;
+        } else {
+            ALOGV("%s: Getting Sound Focus Params", __func__);
+
+            mixer_ctl_update(ctl);
+            count = mixer_ctl_get_num_values(ctl);
+            if (count != sizeof(struct sound_focus_param)) {
+                ALOGE("%s: mixer_ctl_get_num_values() invalid sound focus data size", __func__);
+
+                ret = -EINVAL;
+                goto done;
+            }
+
+            ret = mixer_ctl_get_array(ctl, (void *)sound_focus_data, count);
+            if (ret != 0) {
+                ALOGE("%s: mixer_ctl_get_array() failed to get Sound Focus Params", __func__);
+
+                ret = -EINVAL;
+                goto done;
+            }
+        }
+    }
+
+    if (bitmask & BITMASK_AUDIO_PARAMETER_KEYS_SOURCE_TRACKING) {
+        /* Derive the mixer control name based on the use case and the audio interface
+         * for the corresponding audio device
+         */
+        ret = derive_mixer_ctl_from_usecase_intf(adev, source_tracking_mixer_ctl_name);
+        if (ret != 0) {
+            ALOGE("%s: Could not get Source Tracking Params", __func__);
+
+            goto done;
+        } else {
+            ALOGV("%s: Mixer Ctl name: %s", __func__, source_tracking_mixer_ctl_name);
+        }
+
+        ctl = mixer_get_ctl_by_name(adev->mixer, source_tracking_mixer_ctl_name);
+        if (!ctl) {
+            ALOGE("%s: Could not get ctl for mixer cmd - %s",
+                  __func__, source_tracking_mixer_ctl_name);
+
+            ret = -EINVAL;
+            goto done;
+        } else {
+            ALOGV("%s: Getting Source Tracking Params", __func__);
+
+            mixer_ctl_update(ctl);
+            count = mixer_ctl_get_num_values(ctl);
+            if (count != sizeof(struct source_tracking_param)) {
+                ALOGE("%s: mixer_ctl_get_num_values() invalid source tracking data size", __func__);
+
+                ret = -EINVAL;
+                goto done;
+            }
+
+            ret = mixer_ctl_get_array(ctl, (void *)source_tracking_data, count);
+            if (ret != 0) {
+                ALOGE("%s: mixer_ctl_get_array() failed to get Source Tracking Params", __func__);
+
+                ret = -EINVAL;
+                goto done;
+            }
+        }
+    }
+
+done:
+    return ret;
+}
+
+static void send_soundfocus_sourcetracking_params(struct str_parms *reply,
+                                                const int bitmask,
+                                                const struct sound_focus_param sound_focus_data,
+                                                const struct source_tracking_param source_tracking_data)
+{
+    int i = 0, len = 0;
+    char value[MAX_STR_SIZE] = "";
+
+    if (bitmask & BITMASK_AUDIO_PARAMETER_KEY_SOUND_FOCUS_START_ANGLES) {
+        for (i = 0; i < MAX_SECTORS; i++) {
+            if ((i >=4) && (sound_focus_data.start_angle[i] == 0xFFFF))
+                continue;
+            if (i)
+                snprintf(value + strlen(value), MAX_STR_SIZE, ",");
+            snprintf(value + strlen(value), MAX_STR_SIZE, "%d", sound_focus_data.start_angle[i]);
+        }
+        str_parms_add_str(reply, AUDIO_PARAMETER_KEY_SOUND_FOCUS_START_ANGLES, value);
+    }
+
+    strlcpy(value, "", sizeof(""));
+    if (bitmask & BITMASK_AUDIO_PARAMETER_KEY_SOUND_FOCUS_ENABLE_SECTORS) {
+        for (i = 0; i < MAX_SECTORS; i++) {
+            if ((i >=4) && (sound_focus_data.enable[i] == 0xFF))
+                continue;
+            if (i)
+                snprintf(value + strlen(value), MAX_STR_SIZE, ",");
+            snprintf(value + strlen(value), MAX_STR_SIZE, "%d", sound_focus_data.enable[i]);
+        }
+        str_parms_add_str(reply, AUDIO_PARAMETER_KEY_SOUND_FOCUS_ENABLE_SECTORS, value);
+    }
+
+    if (bitmask & BITMASK_AUDIO_PARAMETER_KEY_SOUND_FOCUS_GAIN_STEP)
+        str_parms_add_int(reply, AUDIO_PARAMETER_KEY_SOUND_FOCUS_GAIN_STEP, sound_focus_data.gain_step);
+
+    strlcpy(value, "", sizeof(""));
+    if (bitmask & BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_VAD) {
+        for (i = 0; i < MAX_SECTORS; i++) {
+            if ((i >=4) && (source_tracking_data.vad[i] == 0xFF))
+                continue;
+            if (i)
+                snprintf(value + strlen(value), MAX_STR_SIZE, ",");
+            snprintf(value + strlen(value), MAX_STR_SIZE, "%d", source_tracking_data.vad[i]);
+        }
+        str_parms_add_str(reply, AUDIO_PARAMETER_KEY_SOURCE_TRACK_VAD, value);
+    }
+
+    if (bitmask & BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_SPEECH)
+        str_parms_add_int(reply, AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_SPEECH, source_tracking_data.doa_speech);
+
+    strlcpy(value, "", sizeof(""));
+    if (bitmask & BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_NOISE) {
+        snprintf(value, MAX_STR_SIZE,
+                     "%d,%d,%d", source_tracking_data.doa_noise[0], source_tracking_data.doa_noise[1], source_tracking_data.doa_noise[2]);
+        str_parms_add_str(reply, AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_NOISE, value);
+    }
+
+    strlcpy(value, "", sizeof(""));
+    if (bitmask & BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_POLAR_ACTIVITY) {
+        for (i = 0; i < 360; i++) {
+            if (i)
+                snprintf(value + strlen(value), MAX_STR_SIZE, ",");
+            snprintf(value + strlen(value), MAX_STR_SIZE, "%d", source_tracking_data.polar_activity[i]);
+        }
+        str_parms_add_str(reply, AUDIO_PARAMETER_KEY_SOURCE_TRACK_POLAR_ACTIVITY, value);
+    }
+}
+
+void audio_extn_source_track_get_parameters(struct audio_device *adev,
+                                            struct str_parms *query,
+                                            struct str_parms *reply)
+{
+    int bitmask = 0, ret = 0;
+    struct sound_focus_param sound_focus_data;
+    struct source_tracking_param source_tracking_data;
+
+    memset(&sound_focus_data, 0xFF, sizeof(struct sound_focus_param));
+    memset(&source_tracking_data, 0xFF, sizeof(struct source_tracking_param));
+
+    // Parse the input parameters string for Source Tracking keys
+    bitmask = parse_soundfocus_sourcetracking_keys(query);
+    if (bitmask) {
+        // Get the parameter values from the backend
+        ret = get_soundfocus_sourcetracking_data(adev, bitmask, &sound_focus_data, &source_tracking_data);
+        if (ret == 0) {
+            // Construct the return string with key, value pairs
+            send_soundfocus_sourcetracking_params(reply, bitmask, sound_focus_data, source_tracking_data);
+        }
+    }
+}
+
+void audio_extn_source_track_set_parameters(struct audio_device *adev,
+                                            struct str_parms *parms)
+{
+    int len, ret, count;;
+    struct mixer_ctl *ctl;
+    char sound_focus_mixer_ctl_name[MIXER_PATH_MAX_LENGTH] = "Sound Focus";
+    char *value = NULL;
+    char *kv_pairs = str_parms_to_str(parms);
+
+    len = strlen(kv_pairs);
+    value = (char*)calloc(len, sizeof(char));
+    if(value == NULL) {
+        ret = -ENOMEM;
+        ALOGE("%s: failed to allocate memory", __func__);
+
+        goto done;
+    }
+
+    // Parse the input parameter string for Source Tracking key, value pairs
+    ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_SOUND_FOCUS_START_ANGLES,
+                            value, len);
+    if (ret >= 0) {
+        char *saveptr, *tok;
+        int i = 0, val;
+        struct sound_focus_param sound_focus_param;
+
+        memset(&sound_focus_param, 0xFF, sizeof(struct sound_focus_param));
+
+        str_parms_del(parms, AUDIO_PARAMETER_KEY_SOUND_FOCUS_START_ANGLES);
+        tok = strtok_r(value, ",", &saveptr);
+        while ((i < MAX_SECTORS) && (tok != NULL)) {
+            if (sscanf(tok, "%d", &val) == 1) {
+                sound_focus_param.start_angle[i++] = (uint16_t)val;
+            }
+            tok = strtok_r(NULL, ",", &saveptr);
+        }
+
+        ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_SOUND_FOCUS_ENABLE_SECTORS,
+                                value, len);
+        if (ret >= 0) {
+            str_parms_del(parms, AUDIO_PARAMETER_KEY_SOUND_FOCUS_ENABLE_SECTORS);
+            tok = strtok_r(value, ",", &saveptr);
+            i = 0;
+            while ((i < MAX_SECTORS) && (tok != NULL)) {
+                if (sscanf(tok, "%d", &val) == 1) {
+                    sound_focus_param.enable[i++] = (uint8_t)val;
+                }
+                tok = strtok_r(NULL, ",", &saveptr);
+            }
+        } else {
+            ALOGE("%s: SoundFocus.enable_sectors key not found", __func__);
+
+            goto done;
+        }
+
+        ret = str_parms_get_int(parms, AUDIO_PARAMETER_KEY_SOUND_FOCUS_GAIN_STEP, &val);
+        if (ret >= 0) {
+            str_parms_del(parms, AUDIO_PARAMETER_KEY_SOUND_FOCUS_GAIN_STEP);
+            sound_focus_param.gain_step = (uint16_t)val;
+        } else {
+            ALOGE("%s: SoundFocus.gain_step key not found", __func__);
+
+            goto done;
+        }
+
+        /* Derive the mixer control name based on the use case and the audio h/w
+         * interface name for the corresponding audio device
+         */
+        ret = derive_mixer_ctl_from_usecase_intf(adev, sound_focus_mixer_ctl_name);
+        if (ret != 0) {
+            ALOGE("%s: Could not set Sound Focus Params", __func__);
+
+            goto done;
+        } else {
+            ALOGV("%s: Mixer Ctl name: %s", __func__, sound_focus_mixer_ctl_name);
+        }
+
+        ctl = mixer_get_ctl_by_name(adev->mixer, sound_focus_mixer_ctl_name);
+        if (!ctl) {
+            ALOGE("%s: Could not get ctl for mixer cmd - %s",
+                  __func__, sound_focus_mixer_ctl_name);
+
+            goto done;
+        } else {
+            ALOGV("%s: Setting Sound Focus Params", __func__);
+
+            for (i = 0; i < MAX_SECTORS;i++) {
+                ALOGV("%s: start_angles[%d] = %d", __func__, i, sound_focus_param.start_angle[i]);
+            }
+            for (i = 0; i < MAX_SECTORS;i++) {
+                ALOGV("%s: enable_sectors[%d] = %d", __func__, i, sound_focus_param.enable[i]);
+            }
+            ALOGV("%s: gain_step = %d", __func__, sound_focus_param.gain_step);
+
+            mixer_ctl_update(ctl);
+            count = mixer_ctl_get_num_values(ctl);
+            if (count != sizeof(struct sound_focus_param)) {
+                ALOGE("%s: mixer_ctl_get_num_values() invalid data size", __func__);
+
+                goto done;
+            }
+
+            // Set the parameters on the mixer control derived above
+            ret = mixer_ctl_set_array(ctl, (void *)&sound_focus_param, count);
+            if (ret != 0) {
+                ALOGE("%s: mixer_ctl_set_array() failed to set Sound Focus Params", __func__);
+
+                goto done;
+            }
+       }
+    }
+
+done:
+    free(kv_pairs);
+    if(value != NULL)
+        free(value);
+    return;
+}
+#endif /* SOURCE_TRACKING_ENABLED end */
diff --git a/hal/audio_extn/spkr_protection.c b/hal/audio_extn/spkr_protection.c
index a350198..312be97 100644
--- a/hal/audio_extn/spkr_protection.c
+++ b/hal/audio_extn/spkr_protection.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013 - 2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013 - 2015, 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
@@ -141,7 +141,7 @@
        handle.spkr_in_use = true;
     else {
        handle.spkr_in_use = false;
-       clock_gettime(CLOCK_MONOTONIC, &handle.spkr_last_time_used);
+       clock_gettime(CLOCK_BOOTTIME, &handle.spkr_last_time_used);
    }
 }
 
@@ -181,7 +181,7 @@
         *sec = 0;
          return true;
      } else {
-         clock_gettime(CLOCK_MONOTONIC, &temp);
+         clock_gettime(CLOCK_BOOTTIME, &temp);
          *sec = temp.tv_sec - handle.spkr_last_time_used.tv_sec;
          return false;
      }
@@ -475,9 +475,15 @@
             pcm_close(handle.pcm_tx);
         handle.pcm_tx = NULL;
         /* Clear TX calibration to handset mic */
-        platform_send_audio_calibration(adev->platform,
-        SND_DEVICE_IN_HANDSET_MIC,
-        platform_get_default_app_type(adev->platform), 8000);
+        if (disable_tx) {
+            uc_info_tx->id = USECASE_AUDIO_RECORD;
+            uc_info_tx->type = PCM_CAPTURE;
+            uc_info_tx->in_snd_device = SND_DEVICE_IN_HANDSET_MIC;
+            uc_info_tx->out_snd_device = SND_DEVICE_NONE;
+            platform_send_audio_calibration(adev->platform,
+              uc_info_tx,
+              platform_get_default_app_type(adev->platform), 8000);
+        }
         if (!status.status) {
             protCfg.mode = MSM_SPKR_PROT_CALIBRATED;
             protCfg.r0[SP_V2_SPKR_1] = status.r0[SP_V2_SPKR_1];
@@ -810,6 +816,7 @@
     struct audio_usecase *uc_info_tx;
     struct audio_device *adev = handle.adev_handle;
     int32_t pcm_dev_tx_id = -1, ret = 0;
+    bool disable_tx = false;
 
     ALOGV("%s: Entry", __func__);
     /* cancel speaker calibration */
@@ -836,6 +843,7 @@
         uc_info_tx->out_snd_device = SND_DEVICE_NONE;
         handle.pcm_tx = NULL;
         list_add_tail(&adev->usecase_list, &uc_info_tx->list);
+        disable_tx = true;
         enable_snd_device(adev, SND_DEVICE_IN_CAPTURE_VI_FEEDBACK);
         enable_audio_route(adev, uc_info_tx);
 
@@ -862,14 +870,24 @@
 
 exit:
    /* Clear VI feedback cal and replace with handset MIC  */
-   platform_send_audio_calibration(adev->platform,
-        SND_DEVICE_IN_HANDSET_MIC,
-        platform_get_default_app_type(adev->platform), 8000);
-    if (ret) {
+    if (disable_tx) {
+        uc_info_tx->id = USECASE_AUDIO_RECORD;
+        uc_info_tx->type = PCM_CAPTURE;
+        uc_info_tx->in_snd_device = SND_DEVICE_IN_HANDSET_MIC;
+        uc_info_tx->out_snd_device = SND_DEVICE_NONE;
+        platform_send_audio_calibration(adev->platform,
+          uc_info_tx,
+          platform_get_default_app_type(adev->platform), 8000);
+     }
+     if (ret) {
         if (handle.pcm_tx)
             pcm_close(handle.pcm_tx);
         handle.pcm_tx = NULL;
         list_remove(&uc_info_tx->list);
+        uc_info_tx->id = USECASE_AUDIO_SPKR_CALIB_TX;
+        uc_info_tx->type = PCM_CAPTURE;
+        uc_info_tx->in_snd_device = SND_DEVICE_IN_CAPTURE_VI_FEEDBACK;
+        uc_info_tx->out_snd_device = SND_DEVICE_NONE;
         disable_snd_device(adev, SND_DEVICE_IN_CAPTURE_VI_FEEDBACK);
         disable_audio_route(adev, uc_info_tx);
         free(uc_info_tx);
diff --git a/hal/audio_extn/usb.c b/hal/audio_extn/usb.c
index a4ea134..13e3138 100644
--- a/hal/audio_extn/usb.c
+++ b/hal/audio_extn/usb.c
@@ -111,8 +111,8 @@
          // 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 (strstr((const char *)mixer_ctl_get_name(ctl), "Playback Volume") &&
-                 !strstr((const char *)mixer_ctl_get_name(ctl), "Mic")) {
+             if ((ctl) && (strstr((const char *)mixer_ctl_get_name(ctl), "Playback Volume") &&
+                 !strstr((const char *)mixer_ctl_get_name(ctl), "Mic"))) {
                    break;
              }
          }
diff --git a/hal/audio_extn/utils.c b/hal/audio_extn/utils.c
index 273a194..82b596f 100644
--- a/hal/audio_extn/utils.c
+++ b/hal/audio_extn/utils.c
@@ -33,6 +33,7 @@
 #include "platform.h"
 #include "platform_api.h"
 #include "audio_extn.h"
+#include "voice.h"
 
 #define AUDIO_OUTPUT_POLICY_VENDOR_CONFIG_FILE "/vendor/etc/audio_output_policy.conf"
 
@@ -48,6 +49,9 @@
 #define STRING_TO_ENUM(string) { #string, string }
 #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
 
+#define BASE_TABLE_SIZE 64
+#define MAX_BASEINDEX_LEN 256
+
 struct string_to_enum {
     const char *name;
     uint32_t value;
@@ -60,12 +64,14 @@
     STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_DEEP_BUFFER),
     STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD),
     STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_NON_BLOCKING),
+    STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_HW_AV_SYNC),
 #ifdef INCALL_MUSIC_ENABLED
     STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_INCALL_MUSIC),
 #endif
 #ifdef COMPRESS_VOIP_ENABLED
     STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_VOIP_RX),
 #endif
+    STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH),
 };
 
 const struct string_to_enum s_format_name_to_enum_table[] = {
@@ -94,9 +100,24 @@
     STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT_OFFLOAD),
     STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_OFFLOAD),
     STRING_TO_ENUM(AUDIO_FORMAT_FLAC),
+    STRING_TO_ENUM(AUDIO_FORMAT_ALAC),
+    STRING_TO_ENUM(AUDIO_FORMAT_APE),
+    STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
+    STRING_TO_ENUM(AUDIO_FORMAT_AAC_LC),
+    STRING_TO_ENUM(AUDIO_FORMAT_AAC_HE_V1),
+    STRING_TO_ENUM(AUDIO_FORMAT_AAC_HE_V2),
 #endif
 };
 
+static char bTable[BASE_TABLE_SIZE] = {
+            'A','B','C','D','E','F','G','H','I','J','K','L',
+            'M','N','O','P','Q','R','S','T','U','V','W','X',
+            'Y','Z','a','b','c','d','e','f','g','h','i','j',
+            'k','l','m','n','o','p','q','r','s','t','u','v',
+            'w','x','y','z','0','1','2','3','4','5','6','7',
+            '8','9','+','/'
+};
+
 static uint32_t string_to_enum(const struct string_to_enum *table, size_t size,
                                const char *name)
 {
@@ -394,6 +415,7 @@
         ss_info = node_to_item(node_i, struct stream_sample_rate, list);
         if ((sample_rate <= ss_info->sample_rate) &&
             (bit_width == so_info->app_type_cfg.bit_width)) {
+
             app_type_cfg->app_type = so_info->app_type_cfg.app_type;
             app_type_cfg->sample_rate = ss_info->sample_rate;
             app_type_cfg->bit_width = so_info->app_type_cfg.bit_width;
@@ -439,6 +461,9 @@
 
     if ((24 == bit_width) &&
         (devices & AUDIO_DEVICE_OUT_SPEAKER)) {
+        int32_t bw = platform_get_snd_device_bit_width(SND_DEVICE_OUT_SPEAKER);
+        if (-ENOSYS != bw)
+            bit_width = (uint32_t)bw;
         sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
         ALOGI("%s Allowing 24-bit playback on speaker ONLY at default sampling rate", __func__);
     }
@@ -495,8 +520,8 @@
     if ((usecase->id != USECASE_AUDIO_PLAYBACK_DEEP_BUFFER) &&
         (usecase->id != USECASE_AUDIO_PLAYBACK_LOW_LATENCY) &&
         (usecase->id != USECASE_AUDIO_PLAYBACK_MULTI_CH) &&
-        (usecase->id != USECASE_AUDIO_PLAYBACK_OFFLOAD)) {
-        ALOGV("%s: a playback path where app type cfg is not required", __func__);
+        (!is_offload_usecase(usecase->id))) {
+        ALOGV("%s: a playback path where app type cfg is not required %d", __func__, usecase->id);
         rc = 0;
         goto exit_send_app_type_cfg;
     }
@@ -535,8 +560,12 @@
 
     app_type_cfg[len++] = out->app_type_cfg.app_type;
     app_type_cfg[len++] = acdb_dev_id;
-    app_type_cfg[len++] = sample_rate;
-
+    if (((out->format == AUDIO_FORMAT_E_AC3) ||
+        (out->format == AUDIO_FORMAT_E_AC3_JOC)) &&
+        (out->flags  & AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH))
+        app_type_cfg[len++] = sample_rate * 4;
+    else
+        app_type_cfg[len++] = sample_rate;
     mixer_ctl_set_array(ctl, app_type_cfg, len);
     ALOGI("%s app_type %d, acdb_dev_id %d, sample_rate %d",
            __func__, out->app_type_cfg.app_type, acdb_dev_id, sample_rate);
@@ -567,3 +596,145 @@
     }
 }
 
+// Base64 Encode and Decode
+// Not all features supported. This must be used only with following conditions.
+// Decode Modes: Support with and without padding
+//         CRLF not handling. So no CRLF in string to decode.
+// Encode Modes: Supports only padding
+int b64decode(char *inp, int ilen, uint8_t* outp)
+{
+    int i, j, k, ii, num;
+    int rem, pcnt;
+    uint32_t res=0;
+    uint8_t getIndex[MAX_BASEINDEX_LEN];
+    uint8_t tmp, cflag;
+
+    if(inp == NULL || outp == NULL || ilen <= 0) {
+        ALOGE("[%s] received NULL pointer or zero length",__func__);
+        return -1;
+    }
+
+    memset(getIndex, MAX_BASEINDEX_LEN-1, sizeof(getIndex));
+    for(i=0;i<BASE_TABLE_SIZE;i++) {
+        getIndex[(uint8_t)bTable[i]] = (uint8_t)i;
+    }
+    getIndex[(uint8_t)'=']=0;
+
+    j=0;k=0;
+    num = ilen/4;
+    rem = ilen%4;
+    if(rem==0)
+        num = num-1;
+    cflag=0;
+    for(i=0; i<num; i++) {
+        res=0;
+        for(ii=0;ii<4;ii++) {
+            res = res << 6;
+            tmp = getIndex[(uint8_t)inp[j++]];
+            res = res | tmp;
+            cflag = cflag | tmp;
+        }
+        outp[k++] = (res >> 16)&0xFF;
+        outp[k++] = (res >> 8)&0xFF;
+        outp[k++] = res & 0xFF;
+    }
+
+    // Handle last bytes special
+    pcnt=0;
+    if(rem == 0) {
+        //With padding or full data
+        res = 0;
+        for(ii=0;ii<4;ii++) {
+            if(inp[j] == '=')
+                pcnt++;
+            res = res << 6;
+            tmp = getIndex[(uint8_t)inp[j++]];
+            res = res | tmp;
+            cflag = cflag | tmp;
+        }
+        outp[k++] = res >> 16;
+        if(pcnt == 2)
+            goto done;
+        outp[k++] = (res>>8)&0xFF;
+        if(pcnt == 1)
+            goto done;
+        outp[k++] = res&0xFF;
+    } else {
+        //without padding
+        res = 0;
+        for(i=0;i<rem;i++) {
+            res = res << 6;
+            tmp = getIndex[(uint8_t)inp[j++]];
+            res = res | tmp;
+            cflag = cflag | tmp;
+        }
+        for(i=rem;i<4;i++) {
+            res = res << 6;
+            pcnt++;
+        }
+        outp[k++] = res >> 16;
+        if(pcnt == 2)
+            goto done;
+        outp[k++] = (res>>8)&0xFF;
+        if(pcnt == 1)
+            goto done;
+        outp[k++] = res&0xFF;
+    }
+done:
+    if(cflag == 0xFF) {
+        ALOGE("[%s] base64 decode failed. Invalid character found %s",
+            __func__, inp);
+        return 0;
+    }
+    return k;
+}
+
+int b64encode(uint8_t *inp, int ilen, char* outp)
+{
+    int i,j,k, num;
+    int rem=0;
+    uint32_t res=0;
+
+    if(inp == NULL || outp == NULL || ilen<=0) {
+        ALOGE("[%s] received NULL pointer or zero input length",__func__);
+        return -1;
+    }
+
+    num = ilen/3;
+    rem = ilen%3;
+    j=0;k=0;
+    for(i=0; i<num; i++) {
+        //prepare index
+        res = inp[j++]<<16;
+        res = res | inp[j++]<<8;
+        res = res | inp[j++];
+        //get output map from index
+        outp[k++] = (char) bTable[(res>>18)&0x3F];
+        outp[k++] = (char) bTable[(res>>12)&0x3F];
+        outp[k++] = (char) bTable[(res>>6)&0x3F];
+        outp[k++] = (char) bTable[res&0x3F];
+    }
+
+    switch(rem) {
+        case 1:
+            res = inp[j++]<<16;
+            outp[k++] = (char) bTable[res>>18];
+            outp[k++] = (char) bTable[(res>>12)&0x3F];
+            //outp[k++] = '=';
+            //outp[k++] = '=';
+            break;
+        case 2:
+            res = inp[j++]<<16;
+            res = res | inp[j++]<<8;
+            outp[k++] = (char) bTable[res>>18];
+            outp[k++] = (char) bTable[(res>>12)&0x3F];
+            outp[k++] = (char) bTable[(res>>6)&0x3F];
+            //outp[k++] = '=';
+            break;
+        default:
+            break;
+    }
+done:
+    outp[k] = '\0';
+    return k;
+}