Merge "hal: Read hotword data from sound trigger hal"
diff --git a/hal/audio_extn/spkr_protection.c b/hal/audio_extn/spkr_protection.c
index e5201cc..391a501 100644
--- a/hal/audio_extn/spkr_protection.c
+++ b/hal/audio_extn/spkr_protection.c
@@ -214,7 +214,7 @@
             snprintf(name, MAX_PATH, TZ_TYPE, tzn);
             ALOGD("Opening %s\n", name);
             read_line_from_file(name, buf, sizeof(buf));
-            buf[strlen(sensor_name)] = '\0';
+            buf[strlen(buf)] = '\0';
             if (!strcmp(buf, sensor_name)) {
                 found = 1;
                 break;
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index 297d671..ae4de62 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -626,7 +626,7 @@
                 (usecase->out_snd_device != snd_device || force_routing)  &&
                 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
                 usecase_backend_idx == backend_idx) {
-            ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..", __func__,
+            ALOGD("%s: Usecase (%s) is active on (%s) - disabling ..", __func__,
                   use_case_table[usecase->id],
                   platform_get_snd_device_name(usecase->out_snd_device));
             disable_audio_route(adev, usecase);
@@ -870,7 +870,6 @@
                                             usecase->stream.out);
                 if (usecase->stream.out == adev->primary_output &&
                         adev->active_input &&
-                        adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
                         out_snd_device != usecase->out_snd_device) {
                     select_devices(adev, adev->active_input->usecase);
                 }
diff --git a/hal/msm8916/platform.c b/hal/msm8916/platform.c
index e6503dd..e2a9648 100644
--- a/hal/msm8916/platform.c
+++ b/hal/msm8916/platform.c
@@ -38,7 +38,7 @@
 #include "sound/msmcal-hwdep.h"
 #include <dirent.h>
 #define SOUND_TRIGGER_DEVICE_HANDSET_MONO_LOW_POWER_ACDB_ID (100)
-
+#define MAX_MIXER_XML_PATH  100
 #define MIXER_XML_PATH "/system/etc/mixer_paths.xml"
 #define MIXER_XML_PATH_MTP "/system/etc/mixer_paths_mtp.xml"
 #define MIXER_XML_PATH_SBC "/system/etc/mixer_paths_sbc.xml"
@@ -58,6 +58,7 @@
 #define MIXER_XML_PATH_WCD9306 "/system/etc/mixer_paths_wcd9306.xml"
 #define MIXER_XML_PATH_WCD9330 "/system/etc/mixer_paths_wcd9330.xml"
 #define MIXER_XML_PATH_WCD9335 "/system/etc/mixer_paths_wcd9335.xml"
+#define MIXER_XML_PATH_WCD9326 "/system/etc/mixer_paths_wcd9326.xml"
 #define MIXER_XML_PATH_SKUN "/system/etc/mixer_paths_qrd_skun.xml"
 #define PLATFORM_INFO_XML_PATH      "/system/etc/audio_platform_info.xml"
 #define PLATFORM_INFO_XML_PATH_EXTCODEC  "/system/etc/audio_platform_info_extcodec.xml"
@@ -136,7 +137,6 @@
 char cal_name_info[WCD9XXX_MAX_CAL][MAX_CAL_NAME] = {
         [WCD9XXX_ANC_CAL] = "anc_cal",
         [WCD9XXX_MBHC_CAL] = "mbhc_cal",
-        [WCD9XXX_MAD_CAL] = "mad_cal",
 };
 
 #define AUDIO_PARAMETER_KEY_REC_PLAY_CONC "rec_play_conc_on"
@@ -746,6 +746,8 @@
                   sizeof("msm8952-tomtom-snd-card")) ||
          !strncmp(snd_card_name, "msm8976-tasha-snd-card",
                   sizeof("msm8976-tasha-snd-card")) ||
+         !strncmp(snd_card_name, "msm8976-tashalite-snd-card",
+                  sizeof("msm8976-tashalite-snd-card")) ||
          !strncmp(snd_card_name, "msm8976-tasha-skun-snd-card",
                   sizeof("msm8976-tasha-skun-snd-card")))
      {
@@ -851,6 +853,14 @@
         msm_be_id_array_len  =
             sizeof(msm_device_to_be_id_external_codec) / sizeof(msm_device_to_be_id_external_codec[0]);
 
+    } else if (!strncmp(snd_card_name, "msm8976-tashalite-snd-card",
+                 sizeof("msm8976-tashalite-snd-card"))) {
+        strlcpy(mixer_xml_path, MIXER_XML_PATH_WCD9326,
+               MAX_MIXER_XML_PATH);
+        msm_device_to_be_id = msm_device_to_be_id_external_codec;
+        msm_be_id_array_len  =
+            sizeof(msm_device_to_be_id_external_codec) / sizeof(msm_device_to_be_id_external_codec[0]);
+
     } else if (!strncmp(snd_card_name, "msm8976-tasha-skun-snd-card",
                 sizeof("msm8976-tasha-skun-snd-card"))) {
         strlcpy(mixer_xml_path, MIXER_XML_PATH_SKUN,
@@ -1188,8 +1198,6 @@
         struct wcdcal_ioctl_buffer codec_buffer;
         struct param_data calib;
 
-        if (!strcmp(cal_name_info[type], "mad_cal"))
-            calib.acdb_id = SOUND_TRIGGER_DEVICE_HANDSET_MONO_LOW_POWER_ACDB_ID;
         calib.get_size = 1;
         ret = acdb_loader_get_calibration(cal_name_info[type], sizeof(struct param_data),
                                                                  &calib);
@@ -1286,7 +1294,7 @@
     struct platform_data *my_data = NULL;
     int retry_num = 0, snd_card_num = 0, key = 0;
     const char *snd_card_name;
-    char mixer_xml_path[100],ffspEnable[PROPERTY_VALUE_MAX];
+    char mixer_xml_path[MAX_MIXER_XML_PATH],ffspEnable[PROPERTY_VALUE_MAX];
     char *cvd_version = NULL;
     const char *mixer_ctl_name = "Set HPX ActiveBe";
     struct mixer_ctl *ctl = NULL;
@@ -1802,7 +1810,7 @@
 {
     if ((snd_device < SND_DEVICE_MIN) || (snd_device >= SND_DEVICE_MAX)) {
         ALOGE("%s: Invalid snd_device = %d", __func__, snd_device);
-        return DEFAULT_OUTPUT_SAMPLING_RATE;
+        return CODEC_BACKEND_DEFAULT_BIT_WIDTH;
     }
     return backend_bit_width_table[snd_device];
 }
@@ -1811,7 +1819,7 @@
 {
     na_props.platform_na_prop_enabled = na_props.ui_na_prop_enabled
         = codec_support;
-    ALOGV("%s: na_props.platform_na_prop_enabled: %d", __func__,
+    ALOGD("%s: na_props.platform_na_prop_enabled: %d", __func__,
            na_props.platform_na_prop_enabled);
     return 0;
 }
@@ -1862,10 +1870,15 @@
                              value, len);
     if (ret >= 0) {
         if (na_props.platform_na_prop_enabled) {
-            if (!strncmp("true", value, sizeof("true")))
+            if (!strncmp("true", value, sizeof("true"))) {
                 na_props.ui_na_prop_enabled = true;
-            else
+                ALOGD("%s: native audio feature enabled from UI",__func__);
+            }
+            else {
                 na_props.ui_na_prop_enabled = false;
+                ALOGD("%s: native audio feature disabled from UI",__func__);
+
+            }
 
             str_parms_del(parms, AUDIO_PARAMETER_KEY_NATIVE_AUDIO);
 
@@ -1878,14 +1891,15 @@
                     (usecase->stream.out->devices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
                     usecase->stream.out->devices & AUDIO_DEVICE_OUT_WIRED_HEADSET) &&
                     OUTPUT_SAMPLING_RATE_44100 == usecase->stream.out->sample_rate) {
-                         select_devices(platform->adev, usecase->id);
-                         ALOGV("%s: triggering dynamic device switch for usecase: "
-                               "%d, device: %d", __func__, usecase->id,
+                         ALOGD("%s: triggering dynamic device switch for usecase(%d: %s)"
+                               " stream(%p), device(%d)", __func__, usecase->id,
+                               use_case_table[usecase->id], usecase->stream,
                                usecase->stream.out->devices);
+                         select_devices(platform->adev, usecase->id);
                  }
             }
         } else {
-              ALOGV("%s: native audio not supported: %d", __func__,
+              ALOGD("%s: native audio not supported: %d", __func__,
                      na_props.platform_na_prop_enabled);
         }
     }
@@ -3564,6 +3578,8 @@
         sizeof("msm8952-tomtom-snd-card")) ||
         !strncmp(snd_card_name, "msm8976-tasha-snd-card",
         sizeof("msm8976-tasha-snd-card")) ||
+        !strncmp(snd_card_name, "msm8976-tashalite-snd-card",
+        sizeof("msm8976-tashalite-snd-card")) ||
         !strncmp(snd_card_name, "msm8976-tasha-skun-snd-card",
         sizeof("msm8976-tasha-skun-snd-card")))
     {
@@ -3768,6 +3784,16 @@
             sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
         }
     }
+
+    /*
+     * Sample rate greater than 48K is only supported by external codecs on
+     * specific devices e.g. Headphones, reset the sample rate to
+     * default value if not external codec.
+     */
+    if (!is_external_codec)
+        sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
+
+
     ALOGI("%s Codec selected backend: %d updated bit width: %d and sample rate: %d",
                __func__, backend_idx, bit_width, sample_rate);
     // Force routing if the expected bitwdith or samplerate
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index 5b339a7..019a889 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -129,7 +129,6 @@
 char cal_name_info[WCD9XXX_MAX_CAL][MAX_CAL_NAME] = {
         [WCD9XXX_ANC_CAL] = "anc_cal",
         [WCD9XXX_MBHC_CAL] = "mbhc_cal",
-        [WCD9XXX_MAD_CAL] = "mad_cal",
 };
 
 enum {
@@ -982,8 +981,6 @@
         struct wcdcal_ioctl_buffer codec_buffer;
         struct param_data calib;
 
-        if (!strcmp(cal_name_info[type], "mad_cal"))
-            calib.acdb_id = SOUND_TRIGGER_DEVICE_HANDSET_MONO_LOW_POWER_ACDB_ID;
         calib.get_size = 1;
         ret = acdb_loader_get_calibration(cal_name_info[type], sizeof(struct param_data),
                                                                  &calib);
@@ -1634,7 +1631,7 @@
 {
     na_props.platform_na_prop_enabled = na_props.ui_na_prop_enabled
         = codec_support;
-    ALOGV("%s: na_props.platform_na_prop_enabled: %d", __func__,
+    ALOGD("%s: na_props.platform_na_prop_enabled: %d", __func__,
            na_props.platform_na_prop_enabled);
     return 0;
 }
@@ -1685,10 +1682,15 @@
                              value, len);
     if (ret >= 0) {
         if (na_props.platform_na_prop_enabled) {
-            if (!strncmp("true", value, sizeof("true")))
+            if (!strncmp("true", value, sizeof("true"))) {
                 na_props.ui_na_prop_enabled = true;
-            else
+                ALOGD("%s: native audio feature enabled from UI",__func__);
+            }
+            else {
                 na_props.ui_na_prop_enabled = false;
+                ALOGD("%s: native audio feature disabled from UI",__func__);
+
+            }
 
             str_parms_del(parms, AUDIO_PARAMETER_KEY_NATIVE_AUDIO);
 
@@ -1703,14 +1705,15 @@
                     (usecase->stream.out->devices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
                     usecase->stream.out->devices & AUDIO_DEVICE_OUT_WIRED_HEADSET) &&
                     OUTPUT_SAMPLING_RATE_44100 == usecase->stream.out->sample_rate) {
-                         select_devices(platform->adev, usecase->id);
-                         ALOGV("%s: triggering dynamic device switch for usecase: "
-                               "%d, device: %d", __func__, usecase->id,
+                         ALOGD("%s: triggering dynamic device switch for usecase(%d: %s)"
+                               " stream(%p), device(%d)", __func__, usecase->id,
+                               use_case_table[usecase->id], usecase->stream,
                                usecase->stream.out->devices);
+                         select_devices(platform->adev, usecase->id);
                  }
             }
         } else {
-              ALOGV("%s: native audio not supported: %d", __func__,
+              ALOGD("%s: native audio not supported: %d", __func__,
                      na_props.platform_na_prop_enabled);
         }
     }
diff --git a/mm-audio/aenc-aac/qdsp6/src/omx_aac_aenc.cpp b/mm-audio/aenc-aac/qdsp6/src/omx_aac_aenc.cpp
index 4cfee1b..6154e0c 100644
--- a/mm-audio/aenc-aac/qdsp6/src/omx_aac_aenc.cpp
+++ b/mm-audio/aenc-aac/qdsp6/src/omx_aac_aenc.cpp
@@ -4070,6 +4070,8 @@
     //The total length of the data to be transcoded
     srcStart = buffer->pBuffer;
     OMX_U8 *data = NULL;
+    ssize_t bytes = 0;
+
     PrintFrameHdr(OMX_COMPONENT_GENERATE_ETB,buffer);
     memset(&meta_in,0,sizeof(meta_in));
     if ( search_input_bufhdr(buffer) == false )
@@ -4104,7 +4106,22 @@
     }
 
     memcpy(&data[sizeof(META_IN)],buffer->pBuffer,buffer->nFilledLen);
-    write(m_drv_fd, data, buffer->nFilledLen+sizeof(META_IN));
+    bytes = write(m_drv_fd, data, buffer->nFilledLen+sizeof(META_IN));
+    if (bytes <= 0) {
+        frame_done_cb((OMX_BUFFERHEADERTYPE *)buffer);
+
+        if (errno == ENETRESET)
+        {
+            ALOGE("In SSR, return error to close the session");
+            m_cb.EventHandler(&m_cmp,
+                  m_app_data,
+                  OMX_EventError,
+                  OMX_ErrorHardware,
+                  0, NULL );
+        }
+        return OMX_ErrorNone;
+    }
+
     pthread_mutex_lock(&m_state_lock);
     get_state(&m_cmp, &state);
     pthread_mutex_unlock(&m_state_lock);
diff --git a/mm-audio/aenc-evrc/qdsp6/src/omx_evrc_aenc.cpp b/mm-audio/aenc-evrc/qdsp6/src/omx_evrc_aenc.cpp
index 8200365..af9f785 100644
--- a/mm-audio/aenc-evrc/qdsp6/src/omx_evrc_aenc.cpp
+++ b/mm-audio/aenc-evrc/qdsp6/src/omx_evrc_aenc.cpp
@@ -3974,6 +3974,8 @@
     //The total length of the data to be transcoded
     srcStart = buffer->pBuffer;
     OMX_U8 *data = NULL;
+    ssize_t bytes = 0;
+
     PrintFrameHdr(OMX_COMPONENT_GENERATE_ETB,buffer);
     memset(&meta_in,0,sizeof(meta_in));
     if ( search_input_bufhdr(buffer) == false )
@@ -4003,7 +4005,21 @@
     }
 
     memcpy(&data[sizeof(META_IN)],buffer->pBuffer,buffer->nFilledLen);
-    write(m_drv_fd, data, buffer->nFilledLen+sizeof(META_IN));
+    bytes = write(m_drv_fd, data, buffer->nFilledLen+sizeof(META_IN));
+    if (bytes <= 0) {
+        frame_done_cb((OMX_BUFFERHEADERTYPE *)buffer);
+
+        if (errno == ENETRESET)
+        {
+            ALOGE("In SSR, return error to close the session");
+            m_cb.EventHandler(&m_cmp,
+                  m_app_data,
+                  OMX_EventError,
+                  OMX_ErrorHardware,
+                  0, NULL );
+        }
+        return OMX_ErrorNone;
+    }
 
     pthread_mutex_lock(&m_state_lock);
     get_state(&m_cmp, &state);
@@ -4045,11 +4061,21 @@
                          buffer->nAllocLen,buffer->pBuffer,
                          nReadbytes,nNumOutputBuf);
       if (nReadbytes <= 0) {
-                  buffer->nFilledLen = 0;
+            buffer->nFilledLen = 0;
             buffer->nOffset = 0;
-                buffer->nTimeStamp = nTimestamp;
-             frame_done_cb((OMX_BUFFERHEADERTYPE *)buffer);
-                  return OMX_ErrorNone;
+            buffer->nTimeStamp = nTimestamp;
+            frame_done_cb((OMX_BUFFERHEADERTYPE *)buffer);
+
+            if (errno == ENETRESET)
+            {
+                ALOGE("In SSR, return error to close the session");
+                m_cb.EventHandler(&m_cmp,
+                   m_app_data,
+                   OMX_EventError,
+                   OMX_ErrorHardware,
+                   0, NULL );
+            }
+            return OMX_ErrorNone;
       } else
               DEBUG_PRINT("Read bytes %d\n",nReadbytes);
       // Buffer from Driver will have
diff --git a/mm-audio/aenc-qcelp13/qdsp6/src/omx_qcelp13_aenc.cpp b/mm-audio/aenc-qcelp13/qdsp6/src/omx_qcelp13_aenc.cpp
index 399b8cf..d25eb7f 100644
--- a/mm-audio/aenc-qcelp13/qdsp6/src/omx_qcelp13_aenc.cpp
+++ b/mm-audio/aenc-qcelp13/qdsp6/src/omx_qcelp13_aenc.cpp
@@ -3972,6 +3972,8 @@
     //The total length of the data to be transcoded
     srcStart = buffer->pBuffer;
     OMX_U8 *data = NULL;
+    ssize_t bytes = 0;
+
     PrintFrameHdr(OMX_COMPONENT_GENERATE_ETB,buffer);
     memset(&meta_in,0,sizeof(meta_in));
     if ( search_input_bufhdr(buffer) == false )
@@ -4001,7 +4003,21 @@
     }
 
     memcpy(&data[sizeof(META_IN)],buffer->pBuffer,buffer->nFilledLen);
-    write(m_drv_fd, data, buffer->nFilledLen+sizeof(META_IN));
+    bytes = write(m_drv_fd, data, buffer->nFilledLen+sizeof(META_IN));
+    if (bytes <= 0) {
+        frame_done_cb((OMX_BUFFERHEADERTYPE *)buffer);
+
+        if (errno == ENETRESET)
+        {
+            ALOGE("In SSR, return error to close the session");
+            m_cb.EventHandler(&m_cmp,
+                  m_app_data,
+                  OMX_EventError,
+                  OMX_ErrorHardware,
+                  0, NULL );
+        }
+        return OMX_ErrorNone;
+    }
 
     pthread_mutex_lock(&m_state_lock);
     get_state(&m_cmp, &state);
@@ -4043,11 +4059,21 @@
                          buffer->nAllocLen,buffer->pBuffer,
                          nReadbytes,nNumOutputBuf);
       if (nReadbytes <= 0) {
-                  buffer->nFilledLen = 0;
+            buffer->nFilledLen = 0;
             buffer->nOffset = 0;
-                buffer->nTimeStamp = nTimestamp;
-             frame_done_cb((OMX_BUFFERHEADERTYPE *)buffer);
-                  return OMX_ErrorNone;
+            buffer->nTimeStamp = nTimestamp;
+            frame_done_cb((OMX_BUFFERHEADERTYPE *)buffer);
+
+            if (errno == ENETRESET)
+            {
+                ALOGE("In SSR, return error to close the session");
+                m_cb.EventHandler(&m_cmp,
+                   m_app_data,
+                   OMX_EventError,
+                   OMX_ErrorHardware,
+                   0, NULL );
+            }
+            return OMX_ErrorNone;
       } else
               DEBUG_PRINT("Read bytes %d\n",nReadbytes);
 
diff --git a/post_proc/EffectsHwAcc.cpp b/post_proc/EffectsHwAcc.cpp
index 0e4c55a..e11cfc7 100644
--- a/post_proc/EffectsHwAcc.cpp
+++ b/post_proc/EffectsHwAcc.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-15, 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
@@ -72,7 +72,7 @@
     size_t reqOutputFrameCount = pBuffer->frameCount;
     int ret = 0;
 
-    if (mTrackBufferProvider != NULL) {
+    if (mTrackInputBufferProvider != NULL) {
         while (1) {
             reqInputFrameCount = ((reqOutputFrameCount *
                                    mEffectsConfig.inputCfg.samplingRate)/
@@ -89,7 +89,7 @@
                      popcount(mEffectsConfig.inputCfg.channels);
             while (frameCount) {
                 pBuffer->frameCount = frameCount;
-                ret = mTrackBufferProvider->getNextBuffer(pBuffer, pts);
+                ret = mTrackInputBufferProvider->getNextBuffer(pBuffer, pts);
                 if (ret == OK) {
                     int bytesInBuffer = pBuffer->frameCount *
                                         FRAME_SIZE(mEffectsConfig.inputCfg.format) *
@@ -98,7 +98,7 @@
                     frameCount -= pBuffer->frameCount;
                     mInputBufferFrameCountOffset += pBuffer->frameCount;
                     offset += bytesInBuffer;
-                    mTrackBufferProvider->releaseBuffer(pBuffer);
+                    mTrackInputBufferProvider->releaseBuffer(pBuffer);
                 } else
                     break;
             }
@@ -133,7 +133,7 @@
                                           AudioBufferProvider::Buffer *pBuffer)
 {
     ALOGV("EffBufferProvider::releaseBuffer()");
-    if (this->mTrackBufferProvider != NULL) {
+    if (this->mTrackInputBufferProvider != NULL) {
         pBuffer->frameCount = 0;
         pBuffer->raw = NULL;
     } else {
@@ -189,7 +189,8 @@
     mEnabled = false;
 }
 
-status_t EffectsHwAcc::prepareEffects(AudioBufferProvider **bufferProvider,
+status_t EffectsHwAcc::prepareEffects(AudioBufferProvider **inputBufferProvider,
+                                      AudioBufferProvider **bufferProvider,
                                       int sessionId,
                                       audio_channel_mask_t channelMask,
                                       int frameCount)
@@ -316,10 +317,11 @@
         goto noEffectsForActiveTrack;
     }
     // initialization successful:
-    // - keep track of the real buffer provider in case it was set before
+    // - keep backup of track's buffer provider
     pHwAccbp->mTrackBufferProvider = *bufferProvider;
-    // - we'll use the hw acc effect integrated inside this
-    //    track's buffer provider, and we'll use it as the track's buffer provider
+    pHwAccbp->mTrackInputBufferProvider = *inputBufferProvider;
+    // - we'll use the hw acc effect integrated inside this track's buffer provider,
+    //   and we'll use it as the track's buffer provider
     mBufferProvider = pHwAccbp;
     *bufferProvider = pHwAccbp;
 
@@ -332,14 +334,14 @@
     return NO_INIT;
 }
 
-void EffectsHwAcc::setBufferProvider(AudioBufferProvider **bufferProvider,
+void EffectsHwAcc::setBufferProvider(AudioBufferProvider **trackInputBufferProvider,
                                      AudioBufferProvider **trackBufferProvider)
 {
     ALOGV("setBufferProvider");
     if (mBufferProvider &&
-        (mBufferProvider->mTrackBufferProvider != *bufferProvider)) {
+        (mBufferProvider->mTrackInputBufferProvider != *trackInputBufferProvider)) {
         *trackBufferProvider = mBufferProvider;
-        mBufferProvider->mTrackBufferProvider = *bufferProvider;
+        mBufferProvider->mTrackInputBufferProvider = *trackInputBufferProvider;
     }
 }
 
diff --git a/post_proc/EffectsHwAcc.h b/post_proc/EffectsHwAcc.h
index 6420a9b..0452f57 100644
--- a/post_proc/EffectsHwAcc.h
+++ b/post_proc/EffectsHwAcc.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-15, 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
@@ -43,10 +43,11 @@
 
     virtual void setSampleRate(uint32_t inpSR, uint32_t outSR);
     virtual void unprepareEffects(AudioBufferProvider **trackBufferProvider);
-    virtual status_t prepareEffects(AudioBufferProvider **trackBufferProvider,
+    virtual status_t prepareEffects(AudioBufferProvider **trackInputBufferProvider,
+                            AudioBufferProvider **trackBufferProvider,
                             int sessionId, audio_channel_mask_t channelMask,
                             int frameCount);
-    virtual void setBufferProvider(AudioBufferProvider **bufferProvider,
+    virtual void setBufferProvider(AudioBufferProvider **trackInputbufferProvider,
                            AudioBufferProvider **trackBufferProvider);
 #ifdef HW_ACC_HPX
     virtual void updateHPXState(uint32_t state);
@@ -62,6 +63,7 @@
         virtual status_t getNextBuffer(Buffer* buffer, int64_t pts);
         virtual void releaseBuffer(Buffer* buffer);
 
+        AudioBufferProvider* mTrackInputBufferProvider;
         AudioBufferProvider* mTrackBufferProvider;
         effect_handle_t    mEffectsHandle;
         effect_config_t    mEffectsConfig;
diff --git a/post_proc/reverb.c b/post_proc/reverb.c
index b256e53..450ce81 100644
--- a/post_proc/reverb.c
+++ b/post_proc/reverb.c
@@ -281,17 +281,19 @@
     context->next_preset = preset;
     offload_reverb_set_preset(&(context->offload_reverb), preset);
 
-    enable = (preset == REVERB_PRESET_NONE) ? false: true;
-    offload_reverb_set_enable_flag(&(context->offload_reverb), enable);
+    if (context->enabled_by_client) {
+        enable = (preset == REVERB_PRESET_NONE) ? false: true;
+        offload_reverb_set_enable_flag(&(context->offload_reverb), enable);
 
-    if (context->ctl)
-        offload_reverb_send_params(context->ctl, &context->offload_reverb,
+        if (context->ctl)
+            offload_reverb_send_params(context->ctl, &context->offload_reverb,
                                    OFFLOAD_SEND_REVERB_ENABLE_FLAG |
                                    OFFLOAD_SEND_REVERB_PRESET);
-    if (context->hw_acc_fd > 0)
-        hw_acc_reverb_send_params(context->hw_acc_fd, &context->offload_reverb,
+        if (context->hw_acc_fd > 0)
+            hw_acc_reverb_send_params(context->hw_acc_fd, &context->offload_reverb,
                                   OFFLOAD_SEND_REVERB_ENABLE_FLAG |
                                   OFFLOAD_SEND_REVERB_PRESET);
+    }
 }
 
 void reverb_set_all_properties(reverb_context_t *context,
@@ -600,6 +602,7 @@
     set_config(context, &context->config);
 
     reverb_ctxt->hw_acc_fd = -1;
+    reverb_ctxt->enabled_by_client = false;
     memset(&(reverb_ctxt->reverb_settings), 0, sizeof(reverb_settings_t));
     memset(&(reverb_ctxt->offload_reverb), 0, sizeof(struct reverb_params));
 
@@ -615,6 +618,16 @@
     reverb_context_t *reverb_ctxt = (reverb_context_t *)context;
 
     ALOGV("%s: ctxt %p", __func__, reverb_ctxt);
+    reverb_ctxt->enabled_by_client = true;
+
+    /* REVERB_PRESET_NONE is equivalent to disabled state,
+     * But support for this state is not provided in DSP.
+     * Hence, do not set enable flag, if in peset mode with preset "NONE".
+     * Effect would be enabled when valid preset is set.
+     */
+    if ((reverb_ctxt->preset == true) &&
+        (reverb_ctxt->next_preset == REVERB_PRESET_NONE))
+        return 0;
 
     if (!offload_reverb_get_enable_flag(&(reverb_ctxt->offload_reverb)))
         offload_reverb_set_enable_flag(&(reverb_ctxt->offload_reverb), true);
@@ -626,6 +639,7 @@
     reverb_context_t *reverb_ctxt = (reverb_context_t *)context;
 
     ALOGV("%s: ctxt %p", __func__, reverb_ctxt);
+    reverb_ctxt->enabled_by_client = false;
     if (offload_reverb_get_enable_flag(&(reverb_ctxt->offload_reverb))) {
         offload_reverb_set_enable_flag(&(reverb_ctxt->offload_reverb), false);
         if (reverb_ctxt->ctl)
diff --git a/post_proc/reverb.h b/post_proc/reverb.h
index 991151e..1a5ca0d 100644
--- a/post_proc/reverb.h
+++ b/post_proc/reverb.h
@@ -48,6 +48,7 @@
     // Offload vars
     struct mixer_ctl *ctl;
     int hw_acc_fd;
+    bool enabled_by_client;
     bool auxiliary;
     bool preset;
     uint16_t cur_preset;
diff --git a/post_proc/virtualizer.c b/post_proc/virtualizer.c
index 2748568..3874f0b 100644
--- a/post_proc/virtualizer.c
+++ b/post_proc/virtualizer.c
@@ -56,6 +56,15 @@
     ALOGV("%s: ctxt %p, strength: %d", __func__, context, strength);
     context->strength = strength;
 
+    /*
+     *  Zero strength is not equivalent to disable state as down mix
+     *  is still happening for multichannel inputs.
+     *  For better user experience, explicitly disable virtualizer module
+     *  when strength is 0.
+     */
+    offload_virtualizer_set_enable_flag(&(context->offload_virt),
+                                        ((strength > 0) && !(context->temp_disabled)) ?
+                                        true : false);
     offload_virtualizer_set_strength(&(context->offload_virt), strength);
     if (context->ctl)
         offload_virtualizer_send_params(context->ctl, &context->offload_virt,