Merge "hal: bug fixes for PCM offload"
diff --git a/hal/Android.mk b/hal/Android.mk
index 1e0e52b..0ed8b44 100644
--- a/hal/Android.mk
+++ b/hal/Android.mk
@@ -125,6 +125,11 @@
     LOCAL_SRC_FILES += audio_extn/compress_capture.c
 endif
 
+ifeq ($(strip $(AUDIO_FEATURE_ENABLED_DTS_EAGLE)),true)
+    LOCAL_CFLAGS += -DDTS_EAGLE
+    LOCAL_SRC_FILES += audio_extn/dts_eagle.c
+endif
+
 ifeq ($(strip $(DOLBY_DDP)),true)
     LOCAL_CFLAGS += -DDS1_DOLBY_DDP_ENABLED
     LOCAL_SRC_FILES += audio_extn/dolby.c
diff --git a/hal/audio_extn/AudioUtil.c b/hal/audio_extn/AudioUtil.c
new file mode 100644
index 0000000..45bf55f
--- /dev/null
+++ b/hal/audio_extn/AudioUtil.c
@@ -0,0 +1,130 @@
+/*Copyright (C) 2014 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+* 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 "AudioUtil"
+//#define LOG_NDEBUG 0
+#include <utils/Log.h>
+#include <stdlib.h>
+
+#include <cutils/properties.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sound/devdep_params.h>
+#include <sound/asound.h>
+#include "AudioUtil.h"
+
+#define ROUTE_PATH    "/data/data/dts/route"
+#define DEVICE_NODE   "/dev/snd/hwC0D3"
+
+static int32_t mDevices = 0;
+static int32_t mCurrDevice = 0;
+
+void create_route_node(void)
+{
+    char prop[PROPERTY_VALUE_MAX] = "true";
+    int fd;
+    property_get("use.dts_eagle", prop, "0");
+    if (!strncmp("true", prop, sizeof("true")) || atoi(prop)) {
+        ALOGV("create_route_node");
+        if ((fd=open(ROUTE_PATH, O_RDONLY)) < 0) {
+            ALOGV("No File exisit");
+        } else {
+            ALOGV("A file with the same name exist. Remove it before creating it");
+            close(fd);
+            remove(ROUTE_PATH);
+        }
+        if ((fd=creat(ROUTE_PATH, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) < 0) {
+            ALOGE("opening route node failed returned");
+            return;
+        }
+        chmod(ROUTE_PATH, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH);
+        ALOGV("opening route  node successful");
+        close(fd);
+    }
+}
+
+void notify_route_node(int active_device, int devices)
+{
+    char prop[PROPERTY_VALUE_MAX] = "true";
+    char buf[1024];
+    int fd;
+    if ((mCurrDevice == active_device) &&
+        (mDevices == devices)) {
+        ALOGV("nothing to update to route node");
+        return;
+    }
+    mDevices = devices;
+    mCurrDevice = active_device;
+    property_get("use.dts_eagle", prop, "0");
+    if (!strncmp("true", prop, sizeof("true")) || atoi(prop)) {
+        ALOGV("notify active device : %d all_devices : %d", active_device, devices);
+        if ((fd=open(ROUTE_PATH, O_TRUNC|O_WRONLY)) < 0) {
+            ALOGV("Write device to route node failed");
+        } else {
+            ALOGV("Write device to route node successful");
+            snprintf(buf, sizeof(buf), "device=%d;all_devices=%d", active_device, devices);
+            int n = write(fd, buf, strlen(buf));
+            ALOGV("number of bytes written: %d", n);
+            close(fd);
+        }
+        int eaglefd = open(DEVICE_NODE, O_RDWR);
+        int32_t params[2] = {active_device, 1 /*is primary device*/};
+        if (eaglefd > 0) {
+            if(ioctl(eaglefd, DTS_EAGLE_IOCTL_SET_ACTIVE_DEVICE, &params) < 0) {
+                ALOGE("DTS_EAGLE (%s): error sending primary device\n", __func__);
+            }
+            ALOGD("DTS_EAGLE (%s): sent primary device\n", __func__);
+            close(eaglefd);
+        } else {
+            ALOGE("DTS_EAGLE (%s): error opening eagle\n", __func__);
+        }
+    }
+}
+
+void remove_route_node(void)
+{
+    char prop[PROPERTY_VALUE_MAX] = "true";
+    int fd;
+    property_get("use.dts_eagle", prop, "0");
+    if (!strncmp("true", prop, sizeof("true")) || atoi(prop)) {
+        ALOGV("remove_route_node");
+        if ((fd=open(ROUTE_PATH, O_RDONLY)) < 0) {
+            ALOGV("open route  node failed");
+        } else {
+            ALOGV("open route node successful");
+            ALOGV("Remove the file");
+            close(fd);
+            remove(ROUTE_PATH);
+        }
+    }
+}
diff --git a/hal/audio_extn/AudioUtil.h b/hal/audio_extn/AudioUtil.h
new file mode 100644
index 0000000..02789cc
--- /dev/null
+++ b/hal/audio_extn/AudioUtil.h
@@ -0,0 +1,46 @@
+/*Copyright (C) 2014 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+* 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_UTIL_H_
+#define AUDIO_UTIL_H_
+
+#ifndef DTS_EAGLE
+#define create_route_node() (0)
+#define notify_route_node(active_device, devices) (0)
+#define remove_route_node() (0)
+#else
+void create_route_node(void);
+void notify_route_node(int active_device, int devices);
+void remove_route_node(void);
+#endif
+
+#endif  //AUDIO_UTIL_H_
diff --git a/hal/audio_extn/audio_extn.c b/hal/audio_extn/audio_extn.c
index 8c52eaa..e6964fc 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"
@@ -40,6 +58,7 @@
     bool aanc_enabled;
     bool custom_stereo_enabled;
     uint32_t proxy_channel_num;
+    bool hpx_enabled;
 };
 
 static struct audio_extn_module aextnmod = {
@@ -47,6 +66,7 @@
     .aanc_enabled = 0,
     .custom_stereo_enabled = 0,
     .proxy_channel_num = 2,
+    .hpx_enabled = 0,
 };
 
 #define AUDIO_PARAMETER_KEY_ANC        "anc_enabled"
@@ -55,6 +75,7 @@
 #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"
 
 #ifndef FM_ENABLED
 #define audio_extn_fm_set_parameters(adev, parms) (0)
@@ -108,6 +129,57 @@
 }
 #endif /* CUSTOM_STEREO_ENABLED */
 
+#ifndef DTS_EAGLE
+#define audio_extn_hpx_set_parameters(adev, parms)         (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);
+    }
+}
+
+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
@@ -437,9 +509,11 @@
    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);
 }
 
 void audio_extn_get_parameters(const struct audio_device *adev,
@@ -450,6 +524,7 @@
     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);
 
     kv_pairs = str_parms_to_str(reply);
     ALOGD_IF(kv_pairs != NULL, "%s: returns %s", __func__, kv_pairs);
diff --git a/hal/audio_extn/audio_extn.h b/hal/audio_extn/audio_extn.h
index 84192c7..556ebcf 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
@@ -251,6 +269,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) (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);
+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
diff --git a/hal/audio_extn/dts_eagle.c b/hal/audio_extn/dts_eagle.c
new file mode 100644
index 0000000..b4bbb9f
--- /dev/null
+++ b/hal/audio_extn/dts_eagle.c
@@ -0,0 +1,486 @@
+/*
+ *  (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/data/dts/stream"
+#define FADE_NOTIFY_FILE                "/data/data/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) {
+    struct listnode *node;
+    struct audio_usecase *usecase;
+    int ret = 0, sent = 0;
+
+    ALOGV("DTS_EAGLE_HAL (%s): enter", __func__);
+
+    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)) {
+            int 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) {
+    int fd = creat(FADE_NOTIFY_FILE, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH), n = 0;
+    char *str = need_data ? "need" : "have";
+    if (fd < 0) {
+        ALOGE("DTS_EAGLE_HAL (%s): opening fade notifier node failed", __func__);
+        return;
+    }
+    chmod(FADE_NOTIFY_FILE, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH);
+    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) {
+    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);
+    } else {
+        if (fade_out_data)
+            return do_DTS_Eagle_params(adev, fade_out_data, false);
+    }
+    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);
+                    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);
+                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_hw.c b/hal/audio_hw.c
index 2299b02..26088eb 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.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_primary"
@@ -1196,6 +1214,8 @@
                 ALOGE("%s: Next track returned error %d",__func__, ret);
             send_callback = true;
             event = STREAM_CBK_EVENT_DRAIN_READY;
+            /* Resend the metadata for next iteration */
+            out->send_new_metadata = 1;
             break;
         case OFFLOAD_CMD_DRAIN:
             ALOGD("copl(%p):calling compress_drain", out);
@@ -1212,6 +1232,7 @@
         out->offload_thread_blocked = false;
         pthread_cond_signal(&out->cond);
         if (send_callback) {
+            ALOGVV("%s: sending offload_callback event %d", __func__, event);
             out->offload_callback(event, NULL, out->offload_cookie);
         }
         free(cmd);
@@ -1362,6 +1383,9 @@
         !(audio_extn_dolby_is_passthrough_stream(out->flags))) {
         if (adev->visualizer_stop_output != NULL)
             adev->visualizer_stop_output(out->handle, out->pcm_device_id);
+
+        audio_extn_dts_remove_state_notifier_node(out->usecase);
+
         if (adev->offload_effects_stop_output != NULL)
             adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
     }
@@ -1514,6 +1538,11 @@
         if (out->offload_callback)
             compress_nonblock(out->compr, out->non_blocking);
 
+        audio_extn_dts_create_state_notifier_node(out->usecase);
+        audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
+                                             popcount(out->channel_mask),
+                                             out->playback_started);
+
 #ifdef DS1_DOLBY_DDP_ENABLED
         if (audio_extn_is_dolby_format(out->format))
             audio_extn_dolby_send_ddp_endp_params(adev);
@@ -1523,6 +1552,7 @@
                 adev->visualizer_start_output(out->handle, out->pcm_device_id);
             if (adev->offload_effects_start_output != NULL)
                 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
+            audio_extn_check_and_set_dts_hpx_state(adev);
         }
     }
     ALOGV("%s: exit", __func__);
@@ -1860,6 +1890,12 @@
     if (is_offload_usecase(out->usecase)) {
         pthread_mutex_lock(&out->lock);
         parse_compress_metadata(out, parms);
+
+        audio_extn_dts_create_state_notifier_node(out->usecase);
+        audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
+                                                 popcount(out->channel_mask),
+                                                 out->playback_started);
+
         pthread_mutex_unlock(&out->lock);
     }
 
@@ -2070,6 +2106,10 @@
             compress_start(out->compr);
             out->playback_started = 1;
             out->offload_state = OFFLOAD_STATE_PLAYING;
+
+            audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
+                                                     popcount(out->channel_mask),
+                                                     out->playback_started);
         }
         pthread_mutex_unlock(&out->lock);
         return ret;
@@ -2238,6 +2278,11 @@
                 status = compress_pause(out->compr);
 
             out->offload_state = OFFLOAD_STATE_PAUSED;
+
+            audio_extn_dts_eagle_fade(adev, false);
+            audio_extn_dts_notify_playback_state(out->usecase, 0,
+                                                 out->sample_rate, popcount(out->channel_mask),
+                                                 0);
         }
         pthread_mutex_unlock(&out->lock);
     }
@@ -2261,6 +2306,10 @@
                 status = compress_resume(out->compr);
 
             out->offload_state = OFFLOAD_STATE_PLAYING;
+
+            audio_extn_dts_eagle_fade(adev, true);
+            audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
+                                                     popcount(out->channel_mask), 1);
         }
         pthread_mutex_unlock(&out->lock);
     }
@@ -2530,7 +2579,8 @@
      * Instead of writing zeroes here, we could trust the hardware
      * to always provide zeroes when muted.
      */
-    if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in))
+    if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
+            in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
         memset(buffer, 0, bytes);
 
 exit:
@@ -2802,13 +2852,14 @@
         out->offload_state = OFFLOAD_STATE_IDLE;
         out->playback_started = 0;
 
+        audio_extn_dts_create_state_notifier_node(out->usecase);
+
         create_offload_callback_thread(out);
         ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
                 __func__, config->offload_info.version,
                 config->offload_info.bit_rate);
         //Decide if we need to use gapless mode by default
         check_and_set_gapless_mode(adev);
-
     } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
         ret = voice_check_and_set_incall_music_usecase(adev, out);
         if (ret != 0) {
@@ -2916,6 +2967,11 @@
     *stream_out = &out->stream;
     ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
         use_case_table[out->usecase]);
+
+    if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
+        audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
+                                             popcount(out->channel_mask), out->playback_started);
+
     ALOGV("%s: exit", __func__);
     return 0;
 
@@ -2946,6 +3002,7 @@
         out_standby(&stream->common);
 
     if (is_offload_usecase(out->usecase)) {
+        audio_extn_dts_remove_state_notifier_node(out->usecase);
         destroy_offload_callback_thread(out);
         free_offload_usecase(adev, out->usecase);
         if (out->compr_config.codec != NULL)
@@ -3558,6 +3615,9 @@
             adev->offload_effects_stop_output =
                         (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
                                          "offload_effects_bundle_hal_stop_output");
+            adev->offload_effects_set_hpx_state =
+                        (int (*)(bool))dlsym(adev->offload_effects_lib,
+                                         "offload_effects_bundle_set_hpx_state");
         }
     }
 
diff --git a/hal/audio_hw.h b/hal/audio_hw.h
index 818389a..ba24b6b 100644
--- a/hal/audio_hw.h
+++ b/hal/audio_hw.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 QCOM_AUDIO_HW_H
@@ -300,6 +318,7 @@
     int (*offload_effects_stop_output)(audio_io_handle_t, int);
 
     struct sound_card_status snd_card_status;
+    int (*offload_effects_set_hpx_state)(bool);
 };
 
 int select_devices(struct audio_device *adev,
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index 7f54a78..1c19a61 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -3164,10 +3164,12 @@
         case 1:
             /* AUDIO_CHANNEL_OUT_MONO */
             channel_map[0] = PCM_CHANNEL_FC;
+            break;
         case 2:
             /* AUDIO_CHANNEL_OUT_STEREO */
             channel_map[0] = PCM_CHANNEL_FL;
             channel_map[1] = PCM_CHANNEL_FR;
+            break;
         case 3:
             /* AUDIO_CHANNEL_OUT_2POINT1 */
             channel_map[0] = PCM_CHANNEL_FL;
@@ -3222,6 +3224,7 @@
             channel_map[4] = PCM_CHANNEL_LB;
             channel_map[5] = PCM_CHANNEL_RB;
             channel_map[6] = PCM_CHANNEL_CS;
+            break;
         case 8:
             /* AUDIO_CHANNEL_OUT_7POINT1 */
             channel_map[0] = PCM_CHANNEL_FL;
diff --git a/post_proc/Android.mk b/post_proc/Android.mk
index 6ed1416..720d3dd 100644
--- a/post_proc/Android.mk
+++ b/post_proc/Android.mk
@@ -13,10 +13,15 @@
 	bass_boost.c \
 	virtualizer.c \
 	reverb.c \
-	effect_api.c
+	effect_api.c \
+	effect_util.c
 
 LOCAL_CFLAGS+= -O2 -fvisibility=hidden
 
+ifneq ($(strip $(AUDIO_FEATURE_DISABLED_DTS_EAGLE)),true)
+    LOCAL_CFLAGS += -DDTS_EAGLE
+endif
+
 LOCAL_SHARED_LIBRARIES := \
 	libcutils \
 	liblog \
diff --git a/post_proc/bundle.c b/post_proc/bundle.c
index 0db2e37..a0a6765 100644
--- a/post_proc/bundle.c
+++ b/post_proc/bundle.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 "offload_effect_bundle"
@@ -32,6 +50,10 @@
 #include "virtualizer.h"
 #include "reverb.h"
 
+#ifdef DTS_EAGLE
+#include "effect_util.h"
+#endif
+
 enum {
     EFFECT_STATE_UNINITIALIZED,
     EFFECT_STATE_INITIALIZED,
@@ -190,6 +212,10 @@
 
     ALOGV("%s output %d pcm_id %d", __func__, output, pcm_id);
 
+#ifdef DTS_EAGLE
+    create_effect_state_node(pcm_id);
+#endif
+
     if (lib_init() != 0)
         return init_status;
 
@@ -285,6 +311,10 @@
 
     list_remove(&out_ctxt->outputs_list_node);
 
+#ifdef DTS_EAGLE
+    remove_effect_state_node(pcm_id);
+#endif
+
     free(out_ctxt);
 
 exit:
diff --git a/post_proc/effect_api.c b/post_proc/effect_api.c
index 971b67f..327ddb9 100644
--- a/post_proc/effect_api.c
+++ b/post_proc/effect_api.c
@@ -25,6 +25,24 @@
  * 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.
+ *
+ * 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 "offload_effect_api"
@@ -40,9 +58,13 @@
 #include <cutils/log.h>
 #include <tinyalsa/asoundlib.h>
 #include <sound/audio_effects.h>
-
+#include <sound/devdep_params.h>
 #include "effect_api.h"
 
+#ifdef DTS_EAGLE
+#include "effect_util.h"
+#endif
+
 #define ARRAY_SIZE(array) (sizeof array / sizeof array[0])
 
 #define OFFLOAD_PRESET_START_OFFSET_FOR_OPENSL 19
@@ -114,6 +136,10 @@
 {
     ALOGVV("%s: enable=%d", __func__, (int)enable);
     bassboost->enable_flag = enable;
+
+#ifdef DTS_EAGLE
+    update_effects_node(PCM_DEV_ID, EFFECT_TYPE_BB, EFFECT_ENABLE_PARAM, enable, EFFECT_NO_OP, EFFECT_NO_OP, EFFECT_NO_OP);
+#endif
 }
 
 int offload_bassboost_get_enable_flag(struct bass_boost_params *bassboost)
@@ -127,6 +153,10 @@
 {
     ALOGVV("%s: strength %d", __func__, strength);
     bassboost->strength = strength;
+
+#ifdef DTS_EAGLE
+    update_effects_node(PCM_DEV_ID, EFFECT_TYPE_BB, EFFECT_SET_PARAM, EFFECT_NO_OP, strength, EFFECT_NO_OP, EFFECT_NO_OP);
+#endif
 }
 
 void offload_bassboost_set_mode(struct bass_boost_params *bassboost,
@@ -190,6 +220,10 @@
 {
     ALOGVV("%s: enable=%d", __func__, (int)enable);
     virtualizer->enable_flag = enable;
+
+#ifdef DTS_EAGLE
+    update_effects_node(PCM_DEV_ID, EFFECT_TYPE_VIRT, EFFECT_ENABLE_PARAM, enable, EFFECT_NO_OP, EFFECT_NO_OP, EFFECT_NO_OP);
+#endif
 }
 
 int offload_virtualizer_get_enable_flag(struct virtualizer_params *virtualizer)
@@ -203,6 +237,10 @@
 {
     ALOGVV("%s: strength %d", __func__, strength);
     virtualizer->strength = strength;
+
+#ifdef DTS_EAGLE
+    update_effects_node(PCM_DEV_ID, EFFECT_TYPE_VIRT, EFFECT_SET_PARAM, EFFECT_NO_OP, strength, EFFECT_NO_OP, EFFECT_NO_OP);
+#endif
 }
 
 void offload_virtualizer_set_out_type(struct virtualizer_params *virtualizer,
@@ -279,6 +317,10 @@
 {
     ALOGVV("%s: enable=%d", __func__, (int)enable);
     eq->enable_flag = enable;
+
+#ifdef DTS_EAGLE
+    update_effects_node(PCM_DEV_ID, EFFECT_TYPE_EQ, EFFECT_ENABLE_PARAM, enable, EFFECT_NO_OP, EFFECT_NO_OP, EFFECT_NO_OP);
+#endif
 }
 
 int offload_eq_get_enable_flag(struct eq_params *eq)
@@ -308,6 +350,10 @@
         eq->per_band_cfg[i].gain_millibels = band_gain_list[i] * 100;
         eq->per_band_cfg[i].quality_factor = Q8_UNITY;
     }
+
+#ifdef DTS_EAGLE
+        update_effects_node(PCM_DEV_ID, EFFECT_TYPE_EQ, EFFECT_SET_PARAM, EFFECT_NO_OP, EFFECT_NO_OP, i, band_gain_list[i] * 100);
+#endif
 }
 
 int offload_eq_send_params(struct mixer_ctl *ctl, struct eq_params eq,
diff --git a/post_proc/effect_util.c b/post_proc/effect_util.c
new file mode 100644
index 0000000..cda89bc
--- /dev/null
+++ b/post_proc/effect_util.c
@@ -0,0 +1,210 @@
+/*
+ *  (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.
+ */
+
+#include <utils/Log.h>
+#include <stdlib.h>
+#include "effect_util.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+#define LOG_TAG "effect_util"
+
+/*#define LOG_NDEBUG 0*/
+
+enum {
+    EQUALIZER,
+    VIRTUALIZER,
+    BASSBOOST,
+};
+
+static const char *paramList[10] = {
+                              "eq_enable",
+                              "virt_enable",
+                              "bb_enable",
+                              "eq_param_level0",
+                              "eq_param_level1",
+                              "eq_param_level2",
+                              "eq_param_level3",
+                              "eq_param_level4",
+                              "virt_param_strength",
+                              "bassboost_param_strength"
+};
+
+#define EFFECT_FILE "/data/data/dts/effect"
+#define MAX_LENGTH_OF_INTEGER_IN_STRING 13
+
+#ifdef DTS_EAGLE
+void create_effect_state_node(int device_id)
+{
+    char prop[PROPERTY_VALUE_MAX];
+    int fd;
+    char buf[1024];
+    char path[PATH_MAX];
+    char value[MAX_LENGTH_OF_INTEGER_IN_STRING];
+
+    property_get("use.dts_eagle", prop, "0");
+    if (!strncmp("true", prop, sizeof("true")) || atoi(prop)) {
+        ALOGV("create_effect_node for - device_id: %d", device_id);
+        strlcpy(path, EFFECT_FILE, sizeof(path));
+        snprintf(value, sizeof(value), "%d", device_id);
+        strlcat(path, value, sizeof(path));
+        if ((fd=open(path, O_RDONLY)) < 0) {
+            ALOGV("No File exist");
+        } else {
+            ALOGV("A file with the same name exist. So, not creating again");
+            return;
+        }
+        if ((fd=creat(path, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) < 0) {
+            ALOGE("opening effect state node failed returned");
+            return;
+        }
+        chmod(path, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH);
+        snprintf(buf, sizeof(buf), "eq_enable=%d;virt_enable=%d;bb_enable=%d;eq_param_level0=%d;eq_param_level1=%d;eq_param_level2=%d;eq_param_level3=%d;eq_param_level4=%d;virt_param_strength=%d;bassboost_param_strength=%d", 0,0,0,0,0,0,0,0,0,0);
+        int n = write(fd, buf, strlen(buf));
+        ALOGV("number of bytes written: %d", n);
+        close(fd);
+    }
+}
+
+void update_effects_node(int device_id, int effect_type, int enable_or_set, int enable_disable, int strength, int eq_band, int eq_level)
+{
+    char prop[PROPERTY_VALUE_MAX];
+    char buf[1024];
+    int fd = 0;
+    int paramValue = 0;
+    char path[PATH_MAX];
+    char value[MAX_LENGTH_OF_INTEGER_IN_STRING];
+    char parameterValue[MAX_LENGTH_OF_INTEGER_IN_STRING];
+    int keyParamIndex = -1; //index in the paramlist array which has to be updated
+    char *s1, *s2;
+    char resultBuf[1024];
+    int index1 = -1;
+  //ALOGV("value of device_id and effect_type is %d and %d", device_id, effect_type);
+    property_get("use.dts_eagle", prop, "0");
+    if (!strncmp("true", prop, sizeof("true")) || atoi(prop)) {
+        strlcpy(path, EFFECT_FILE, sizeof(path));
+        snprintf(value, sizeof(value), "%d", device_id);
+        strlcat(path, value, sizeof(path));
+        switch (effect_type)
+        {
+        case EQUALIZER:
+            if (enable_or_set) {
+                keyParamIndex = 0;
+                paramValue = enable_disable;
+        } else {
+            switch (eq_band) {
+            case 0:
+                keyParamIndex = 3;
+                break;
+            case 1:
+                keyParamIndex = 4;
+                break;
+            case 2:
+                keyParamIndex = 5;
+                break;
+            case 3:
+                keyParamIndex = 6;
+                break;
+            case 4:
+                keyParamIndex = 7;
+                break;
+            default:
+                break;
+            }
+            paramValue = eq_level;
+        }
+        break;
+        case VIRTUALIZER:
+            if(enable_or_set) {
+                keyParamIndex = 1;
+                paramValue = enable_disable;
+            } else {
+                 keyParamIndex = 8;
+                 paramValue = strength;
+            }
+            break;
+        case BASSBOOST:
+            if (enable_or_set) {
+                keyParamIndex = 2;
+                paramValue = enable_disable;
+            } else {
+                keyParamIndex = 9;
+                paramValue = strength;
+            }
+            break;
+         default:
+            break;
+        }
+        if(keyParamIndex !=-1) {
+            FILE *fp;
+            fp = fopen(path,"r");
+            if (fp != NULL) {
+                memset(buf, 0, 1024);
+                memset(resultBuf, 0, 1024);
+                if (fgets(buf, 1024, fp) != NULL) {
+                    s1 = strstr(buf, paramList[keyParamIndex]);
+                    s2 = strstr(s1,";");
+                    index1 = s1 - buf;
+                    strncpy(resultBuf, buf, index1);
+                    strncat(resultBuf, paramList[keyParamIndex], sizeof(resultBuf)-strlen(resultBuf)-1);
+                    strncat(resultBuf, "=", sizeof(resultBuf)-strlen(resultBuf)-1);
+                    snprintf(parameterValue, sizeof(parameterValue), "%d", paramValue);
+                    strncat(resultBuf, parameterValue, sizeof(resultBuf)-strlen(resultBuf)-1);
+                    if (s2)
+                        strncat(resultBuf, s2, sizeof(resultBuf)-strlen(resultBuf)-1);
+                    fclose(fp);
+                    if ((fd=open(path, O_TRUNC|O_WRONLY)) < 0) {
+                       ALOGV("opening file for writing failed");
+                       return;
+                    }
+                    int n = write(fd, resultBuf, strlen(resultBuf));
+                    close(fd);
+                    ALOGV("number of bytes written: %d", n);
+                } else {
+                    ALOGV("file could not be read");
+                    fclose(fp);
+                }
+            } else
+                ALOGV("file could not be opened");
+        }
+    }
+}
+
+void remove_effect_state_node(int device_id)
+{
+    char prop[PROPERTY_VALUE_MAX];
+    int fd;
+    char path[PATH_MAX];
+    char value[MAX_LENGTH_OF_INTEGER_IN_STRING];
+
+    property_get("use.dts_eagle", prop, "0");
+    if (!strncmp("true", prop, sizeof("true")) || atoi(prop)) {
+        ALOGV("remove_state_notifier_node: device_id - %d", device_id);
+        strlcpy(path, EFFECT_FILE, sizeof(path));
+        snprintf(value, sizeof(value), "%d", device_id);
+        strlcat(path, value, sizeof(path));
+        if ((fd=open(path, O_RDONLY)) < 0) {
+            ALOGV("open effect state node failed");
+        } else {
+            ALOGV("open effect state node successful");
+            ALOGV("Remove the file");
+            close(fd);
+            remove(path);
+        }
+    }
+}
+#endif
diff --git a/post_proc/effect_util.h b/post_proc/effect_util.h
new file mode 100644
index 0000000..38bd9bd
--- /dev/null
+++ b/post_proc/effect_util.h
@@ -0,0 +1,47 @@
+/*
+ *  (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 EFFECT_UTIL_H_
+#define EFFECT_UTIL_H_
+
+#ifdef DTS_EAGLE
+
+#include <cutils/properties.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+enum {
+    EFFECT_TYPE_EQ = 0,
+    EFFECT_TYPE_VIRT,
+    EFFECT_TYPE_BB,
+};
+
+enum {
+    EFFECT_SET_PARAM = 0,
+    EFFECT_ENABLE_PARAM,
+};
+
+
+#define EFFECT_NO_OP 0
+#define PCM_DEV_ID 9
+
+void create_effect_state_node(int device_id);
+void update_effects_node(int device_id, int effect_type, int enable_or_set, int enable_disable, int strength, int band, int level);
+void remove_effect_state_node(int device_id);
+
+#endif /*DTS_EAGLE*/
+
+#endif /*EFFECT_UTIL_H_*/