Merge "  hal: msm8974: Fix echo reference port for msm8x10"
diff --git a/hal/Android.mk b/hal/Android.mk
index 87ebeea..bc17a57 100644
--- a/hal/Android.mk
+++ b/hal/Android.mk
@@ -37,6 +37,10 @@
 
 LOCAL_SRC_FILES += audio_extn/audio_extn.c
 
+ifneq ($(strip $(AUDIO_FEATURE_DISABLED_PCM_OFFLOAD)),true)
+    LOCAL_CFLAGS += -DPCM_OFFLOAD_ENABLED
+endif
+
 ifneq ($(strip $(AUDIO_FEATURE_DISABLED_ANC_HEADSET)),true)
     LOCAL_CFLAGS += -DANC_HEADSET_ENABLED
 endif
diff --git a/hal/audio_extn/audio_extn.h b/hal/audio_extn/audio_extn.h
index 7feeb42..80bc434 100644
--- a/hal/audio_extn/audio_extn.h
+++ b/hal/audio_extn/audio_extn.h
@@ -22,6 +22,45 @@
 
 #include <cutils/str_parms.h>
 
+#ifndef PCM_OFFLOAD_ENABLED
+#define AUDIO_FORMAT_PCM_OFFLOAD 0x17000000UL
+#define AUDIO_FORMAT_PCM_16_BIT_OFFLOAD (AUDIO_FORMAT_PCM_OFFLOAD | AUDIO_FORMAT_PCM_SUB_16_BIT)
+#define AUDIO_FORMAT_PCM_24_BIT_OFFLOAD (AUDIO_FORMAT_PCM_OFFLOAD | AUDIO_FORMAT_PCM_SUB_8_24_BIT)
+#define AUDIO_OFFLOAD_CODEC_FORMAT  "music_offload_codec_format"
+static inline bool audio_is_offload_pcm(audio_format_t format) {
+    return ((format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM_OFFLOAD);
+}
+#endif
+
+#ifndef AFE_PROXY_ENABLED
+#define AUDIO_DEVICE_OUT_PROXY 0x40000
+#endif
+
+#ifndef COMPRESS_VOIP_ENABLED
+#define AUDIO_OUTPUT_FLAG_VOIP_RX 0x4000
+#endif
+
+#ifndef INCALL_MUSIC_ENABLED
+#define AUDIO_OUTPUT_FLAG_INCALL_MUSIC 0x8000
+#endif
+
+#ifndef FLUENCE_ENABLED
+#define AUDIO_PARAMETER_KEY_FLUENCE "fluence"
+#define AUDIO_PARAMETER_VALUE_QUADMIC "quadmic"
+#define AUDIO_PARAMETER_VALUE_DUALMIC "dualmic"
+#define AUDIO_PARAMETER_KEY_NO_FLUENCE "none"
+#endif
+
+#ifndef FM_ENABLED
+#define AUDIO_DEVICE_OUT_FM 0x80000
+#define AUDIO_DEVICE_OUT_FM_TX 0x100000
+#define AUDIO_SOURCE_FM_RX 9
+#define AUDIO_SOURCE_FM_RX_A2DP 10
+#define AUDIO_DEVICE_IN_FM_RX (AUDIO_DEVICE_BIT_IN | 0x8000)
+#define AUDIO_DEVICE_IN_FM_RX_A2DP AUDIO_DEVICE_BIT_IN | 0x10000
+#endif
+
+
 void audio_extn_set_parameters(struct audio_device *adev,
                                struct str_parms *parms);
 
diff --git a/hal/audio_extn/fm.c b/hal/audio_extn/fm.c
index a4157f8..35b20b8 100644
--- a/hal/audio_extn/fm.c
+++ b/hal/audio_extn/fm.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
  * Not a Contribution.
  *
  * Copyright (C) 2013 The Android Open Source Project
@@ -64,7 +64,7 @@
 {
     int32_t vol, ret = 0;
     struct mixer_ctl *ctl;
-    const char *mixer_ctl_name = "Internal FM RX Volume";
+    const char *mixer_ctl_name = FM_RX_VOLUME;
 
     ALOGV("%s: entry", __func__);
     ALOGD("%s: (%f)\n", __func__, value);
@@ -92,7 +92,6 @@
         return -EINVAL;
     }
     mixer_ctl_set_value(ctl, 0, vol);
-
     ALOGV("%s: exit", __func__);
     return ret;
 }
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index 9f76d31..2f67784 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -300,10 +300,12 @@
      * control in use-case does not work because rate update takes place after
      * AFE port open due to the limitation of mixer control order execution.
      */
-    if (snd_device == SND_DEVICE_OUT_BT_SCO) {
+    if ((snd_device == SND_DEVICE_OUT_BT_SCO) ||
+        (snd_device == SND_DEVICE_IN_BT_SCO_MIC)) {
         audio_route_apply_path(adev->audio_route, BT_SCO_SAMPLE_RATE);
         audio_route_update_mixer(adev->audio_route);
-    } else if (snd_device == SND_DEVICE_OUT_BT_SCO_WB) {
+    } else if ((snd_device == SND_DEVICE_OUT_BT_SCO_WB) ||
+               (snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB)) {
         audio_route_apply_path(adev->audio_route, BT_SCO_WB_SAMPLE_RATE);
         audio_route_update_mixer(adev->audio_route);
     }
@@ -437,23 +439,22 @@
         /* Make sure all the streams are de-routed before disabling the device */
         audio_route_update_mixer(adev->audio_route);
 
+        /* Make sure the previous devices to be disabled first and then enable the
+           selected devices */
         list_for_each(node, &adev->usecase_list) {
             usecase = node_to_item(node, struct audio_usecase, list);
             if (switch_device[usecase->id]) {
-                disable_snd_device(adev, usecase->out_snd_device, false);
+                disable_snd_device(adev, usecase->out_snd_device, true);
             }
         }
 
         list_for_each(node, &adev->usecase_list) {
             usecase = node_to_item(node, struct audio_usecase, list);
             if (switch_device[usecase->id]) {
-                enable_snd_device(adev, snd_device, false);
+                enable_snd_device(adev, snd_device, true);
             }
         }
 
-        /* Make sure new snd device is enabled before re-routing the streams */
-        audio_route_update_mixer(adev->audio_route);
-
         /* Re-route all the usecases on the shared backend other than the
            specified usecase to new snd devices */
         list_for_each(node, &adev->usecase_list) {
@@ -507,23 +508,22 @@
         /* Make sure all the streams are de-routed before disabling the device */
         audio_route_update_mixer(adev->audio_route);
 
+        /* Make sure the previous devices to be disabled first and then enable the
+           selected devices */
         list_for_each(node, &adev->usecase_list) {
             usecase = node_to_item(node, struct audio_usecase, list);
             if (switch_device[usecase->id]) {
-                disable_snd_device(adev, usecase->in_snd_device, false);
+                disable_snd_device(adev, usecase->in_snd_device, true);
             }
         }
 
         list_for_each(node, &adev->usecase_list) {
             usecase = node_to_item(node, struct audio_usecase, list);
             if (switch_device[usecase->id]) {
-                enable_snd_device(adev, snd_device, false);
+                enable_snd_device(adev, snd_device, true);
             }
         }
 
-        /* Make sure new snd device is enabled before re-routing the streams */
-        audio_route_update_mixer(adev->audio_route);
-
         /* Re-route all the usecases on the shared backend other than the
            specified usecase to new snd devices */
         list_for_each(node, &adev->usecase_list) {
@@ -637,7 +637,8 @@
             }
         } else if (voice_extn_compress_voip_is_active(adev)) {
             voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
-            if (voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
+            if ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
+                (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
                     in_snd_device = voip_usecase->in_snd_device;
                     out_snd_device = voip_usecase->out_snd_device;
             }
@@ -698,12 +699,12 @@
     /* Disable current sound devices */
     if (usecase->out_snd_device != SND_DEVICE_NONE) {
         disable_audio_route(adev, usecase, true);
-        disable_snd_device(adev, usecase->out_snd_device, false);
+        disable_snd_device(adev, usecase->out_snd_device, true);
     }
 
     if (usecase->in_snd_device != SND_DEVICE_NONE) {
         disable_audio_route(adev, usecase, true);
-        disable_snd_device(adev, usecase->in_snd_device, false);
+        disable_snd_device(adev, usecase->in_snd_device, true);
     }
 
     /* Applicable only on the targets that has external modem.
@@ -1424,13 +1425,14 @@
         pthread_mutex_lock(&adev->lock);
 
         /*
-         * When HDMI cable is unplugged the music playback is paused and
-         * the policy manager sends routing=0. But the audioflinger
-         * continues to write data until standby time (3sec).
-         * As the HDMI core is turned off, the write gets blocked.
+         * When HDMI cable is unplugged/usb hs is disconnected the
+         * music playback is paused and the policy manager sends routing=0
+         * But the audioflingercontinues to write data until standby time
+         * (3sec). As the HDMI core is turned off, the write gets blocked.
          * Avoid this by routing audio to speaker until standby.
          */
-        if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
+        if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
+                out->devices == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET) &&
                 val == AUDIO_DEVICE_NONE) {
             val = AUDIO_DEVICE_OUT_SPEAKER;
         }
@@ -2255,7 +2257,8 @@
 
     /* Check if this usecase is already existing */
     pthread_mutex_lock(&adev->lock);
-    if (get_usecase_from_list(adev, out->usecase) != NULL) {
+    if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
+        (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
         ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
         pthread_mutex_unlock(&adev->lock);
         ret = -EEXIST;
diff --git a/hal/msm8916/hw_info.c b/hal/msm8916/hw_info.c
index 7b955ba..661a0d0 100644
--- a/hal/msm8916/hw_info.c
+++ b/hal/msm8916/hw_info.c
@@ -137,6 +137,12 @@
         hw_info->snd_devices = NULL;
         hw_info->num_snd_devices = 0;
         strlcpy(hw_info->dev_extn, "", sizeof(hw_info->dev_extn));
+    } else if (!strcmp(snd_card_name, "msm8x16-skui-snd-card")) {
+        strlcpy(hw_info->type, "skui", sizeof(hw_info->type));
+        strlcpy(hw_info->name, "msm8x16", sizeof(hw_info->name));
+        hw_info->snd_devices = NULL;
+        hw_info->num_snd_devices = 0;
+        strlcpy(hw_info->dev_extn, "", sizeof(hw_info->dev_extn));
     } else {
         ALOGW("%s: Not an  8x16 device", __func__);
     }
diff --git a/hal/msm8916/platform.h b/hal/msm8916/platform.h
index f081912..f12697c 100644
--- a/hal/msm8916/platform.h
+++ b/hal/msm8916/platform.h
@@ -178,6 +178,8 @@
 #define PLAYBACK_OFFLOAD_DEVICE 9
 #define COMPRESS_VOIP_CALL_PCM_DEVICE 3
 
+/* Define macro for Internal FM volume mixer */
+#define FM_RX_VOLUME "Internal FM RX Volume"
 
 #define LOWLATENCY_PCM_DEVICE 12
 #define EC_REF_RX "I2S_RX"
diff --git a/hal/msm8960/platform.h b/hal/msm8960/platform.h
index e38d801..e326785 100644
--- a/hal/msm8960/platform.h
+++ b/hal/msm8960/platform.h
@@ -118,4 +118,7 @@
 #define AUDIO_CAPTURE_PERIOD_DURATION_MSEC 20
 #define AUDIO_CAPTURE_PERIOD_COUNT 2
 
+/* Define macro for Internal FM volume mixer */
+#define FM_RX_VOLUME "Internal FM RX Volume"
+
 #endif // QCOM_AUDIO_PLATFORM_H
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index a303a30..5315e78 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -1433,6 +1433,7 @@
             }
         } else if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
             snd_device = SND_DEVICE_IN_VOICE_HEADSET_MIC;
+            set_echo_reference(adev->mixer, EC_REF_RX);
         } else if (out_device & AUDIO_DEVICE_OUT_ALL_SCO) {
             if (my_data->btsco_sample_rate == SAMPLE_RATE_16KHZ)
                 snd_device = SND_DEVICE_IN_BT_SCO_MIC_WB;
@@ -1454,6 +1455,7 @@
                 }
             } else {
                 snd_device = SND_DEVICE_IN_VOICE_SPEAKER_MIC;
+                set_echo_reference(adev->mixer, EC_REF_RX);
             }
         }
     } else if (source == AUDIO_SOURCE_CAMCORDER) {
diff --git a/hal/msm8974/platform.h b/hal/msm8974/platform.h
index d0b6418..f86faf6 100644
--- a/hal/msm8974/platform.h
+++ b/hal/msm8974/platform.h
@@ -221,7 +221,7 @@
 #define VOICE_CALL_PCM_DEVICE 20
 #define VOICE2_CALL_PCM_DEVICE 25
 #define VOLTE_CALL_PCM_DEVICE 21
-#define QCHAT_CALL_PCM_DEVICE 06
+#define QCHAT_CALL_PCM_DEVICE 33
 #define VOWLAN_CALL_PCM_DEVICE -1
 #elif PLATFORM_MSM8610
 #define VOICE_CALL_PCM_DEVICE 2
@@ -245,6 +245,12 @@
 #define HFP_ASM_RX_TX 24
 #endif
 
+#ifdef PLATFORM_APQ8084
+#define FM_RX_VOLUME "Quat MI2S FM RX Volume"
+#else
+#define FM_RX_VOLUME "Internal FM RX Volume"
+#endif
+
 #define LIB_CSD_CLIENT "libcsd-client.so"
 /* CSD-CLIENT related functions */
 typedef int (*init_t)(bool);
diff --git a/hal/voice_extn/voice_extn.c b/hal/voice_extn/voice_extn.c
index f6083f3..5dbd7b9 100644
--- a/hal/voice_extn/voice_extn.c
+++ b/hal/voice_extn/voice_extn.c
@@ -570,6 +570,7 @@
     voice_extn_compress_voip_in_get_parameters(in, query, reply);
 }
 
+#ifdef INCALL_MUSIC_ENABLED
 int voice_extn_check_and_set_incall_music_usecase(struct audio_device *adev,
                                                   struct stream_out *out)
 {
@@ -591,4 +592,5 @@
 
     return 0;
 }
+#endif
 
diff --git a/policy_hal/Android.mk b/policy_hal/Android.mk
index 4f3a737..517f207 100644
--- a/policy_hal/Android.mk
+++ b/policy_hal/Android.mk
@@ -1,4 +1,4 @@
-ifeq ($(strip $(BOARD_USES_ALSA_AUDIO)),true)
+ifneq ($(strip $(BOARD_USES_AOSP_AUDIO_POLICY_MANAGER)),true)
 
 LOCAL_PATH := $(call my-dir)
 include $(CLEAR_VARS)
diff --git a/policy_hal/AudioPolicyManager.cpp b/policy_hal/AudioPolicyManager.cpp
index a6f0b0b..03f6c41 100644
--- a/policy_hal/AudioPolicyManager.cpp
+++ b/policy_hal/AudioPolicyManager.cpp
@@ -595,7 +595,63 @@
         return 0;
     }
 
+#ifdef VOICE_CONCURRENCY
 
+    char propValue[PROPERTY_VALUE_MAX];
+    bool prop_rec_enabled=false, prop_voip_enabled = false;
+
+    if(property_get("voice.record.conc.disabled", propValue, NULL)) {
+        prop_rec_enabled = atoi(propValue) || !strncmp("true", propValue, 4);
+    }
+
+    if(property_get("voice.voip.conc.disabled", propValue, NULL)) {
+        prop_voip_enabled = atoi(propValue) || !strncmp("true", propValue, 4);
+    }
+
+    if (prop_rec_enabled) {
+         //check if voice call is active  / running in background
+         //some of VoIP apps(like SIP2SIP call) supports resume of VoIP call when call in progress
+         //Need to block input request
+        if((AudioSystem::MODE_IN_CALL == mPhoneState) ||
+           ((AudioSystem::MODE_IN_CALL == mPrevPhoneState) &&
+             (AudioSystem::MODE_IN_COMMUNICATION == mPhoneState)))
+        {
+            switch(inputSource) {
+                case AUDIO_SOURCE_VOICE_UPLINK:
+                case AUDIO_SOURCE_VOICE_DOWNLINK:
+                case AUDIO_SOURCE_VOICE_CALL:
+                    ALOGD("Creating input during incall mode for inputSource: %d ",inputSource);
+                break;
+
+                 case AUDIO_SOURCE_VOICE_COMMUNICATION:
+                    if(prop_voip_enabled) {
+                        ALOGD("BLOCKING VoIP request during incall mode for inputSource: %d ",inputSource);
+                        return 0;
+                    }
+                break;
+
+               default:
+                   ALOGD("BLOCKING input during incall mode for inputSource: %d ",inputSource);
+               return 0;
+            }
+        }
+    }//check for VoIP flag
+    else if(prop_voip_enabled) {
+         //check if voice call is active  / running in background
+         //some of VoIP apps(like SIP2SIP call) supports resume of VoIP call when call in progress
+         //Need to block input request
+        if((AudioSystem::MODE_IN_CALL == mPhoneState) ||
+           ((AudioSystem::MODE_IN_CALL == mPrevPhoneState) &&
+             (AudioSystem::MODE_IN_COMMUNICATION == mPhoneState)))
+        {
+            if(inputSource == AUDIO_SOURCE_VOICE_COMMUNICATION) {
+                ALOGD("BLOCKING VoIP request during incall mode for inputSource: %d ",inputSource);
+                return 0;
+            }
+        }
+    }
+
+#endif
     IOProfile *profile = getInputProfile(device,
                                          samplingRate,
                                          format,
@@ -1076,19 +1132,11 @@
     if (stream == AudioSystem::VOICE_CALL ||
         stream == AudioSystem::BLUETOOTH_SCO) {
         float voiceVolume;
-
-        voiceVolume = (float)index/(float)mStreams[stream].mIndexMax;
-
-        // Force voice volume to max when Vgs is set for bluetooth SCO as volume is managed by the headset
-        if (stream == AudioSystem::BLUETOOTH_SCO) {
-            String8 key ("bt_headset_vgs");
-            mpClientInterface->getParameters(output,key);
-            AudioParameter result(mpClientInterface->getParameters(0,key));
-            int value;
-            if (result.getInt(String8("isVGS"),value) == NO_ERROR) {
-                ALOGV("Use BT-SCO Voice Volume");
-                voiceVolume = 1.0;
-            }
+        // Force voice volume to max for bluetooth SCO as volume is managed by the headset
+        if (stream == AudioSystem::VOICE_CALL) {
+            voiceVolume = (float)index/(float)mStreams[stream].mIndexMax;
+        } else {
+            voiceVolume = 1.0;
         }
 
         if (voiceVolume != mLastVoiceVolume && output == mPrimaryOutput) {
@@ -1148,13 +1196,49 @@
     IOProfile *profile = NULL;
 
 #ifdef VOICE_CONCURRENCY
-    if (isInCall()) {
-        ALOGV(" IN call mode adding ULL flags .. flags: %x ", flags );
-        //For voip paths
-        if(flags & AudioSystem::OUTPUT_FLAG_DIRECT)
-            flags = AudioSystem::OUTPUT_FLAG_DIRECT;
-        else //route every thing else to ULL path
-            flags = (AudioSystem::output_flags)AUDIO_OUTPUT_FLAG_FAST;
+    char propValue[PROPERTY_VALUE_MAX];
+    bool prop_play_enabled=false, prop_voip_enabled = false;
+
+    if(property_get("voice.playback.conc.disabled", propValue, NULL)) {
+       prop_play_enabled = atoi(propValue) || !strncmp("true", propValue, 4);
+    }
+
+    if(property_get("voice.voip.conc.disabled", propValue, NULL)) {
+       prop_voip_enabled = atoi(propValue) || !strncmp("true", propValue, 4);
+    }
+
+    if (prop_play_enabled) {
+        //check if voice call is active  / running in background
+        if((AudioSystem::MODE_IN_CALL == mPhoneState) ||
+             ((AudioSystem::MODE_IN_CALL == mPrevPhoneState)
+                && (AudioSystem::MODE_IN_COMMUNICATION == mPhoneState)))
+        {
+            if(AUDIO_OUTPUT_FLAG_VOIP_RX  & flags) {
+                if(prop_voip_enabled) {
+                    ALOGD(" IN call mode returing no output .. for VoIP usecase flags: %x ", flags );
+                   // flags = (AudioSystem::output_flags)AUDIO_OUTPUT_FLAG_FAST;
+                   return 0;
+                }
+            }
+            else {
+                ALOGD(" IN call mode adding ULL flags .. flags: %x ", flags );
+                flags = (AudioSystem::output_flags)AUDIO_OUTPUT_FLAG_FAST;
+            }
+        }
+    } else if (prop_voip_enabled) {
+        //check if voice call is active  / running in background
+        //some of VoIP apps(like SIP2SIP call) supports resume of VoIP call when call in progress
+        //return only ULL ouput
+        if((AudioSystem::MODE_IN_CALL == mPhoneState) ||
+             ((AudioSystem::MODE_IN_CALL == mPrevPhoneState)
+                && (AudioSystem::MODE_IN_COMMUNICATION == mPhoneState)))
+        {
+            if(AUDIO_OUTPUT_FLAG_VOIP_RX  & flags) {
+                ALOGD(" IN call mode returing no output .. for VoIP usecase flags: %x ", flags );
+               // flags = (AudioSystem::output_flags)AUDIO_OUTPUT_FLAG_FAST;
+               return 0;
+            }
+        }
     }
 #endif
 
@@ -1337,11 +1421,18 @@
      offloadInfo.has_video);
 
 #ifdef VOICE_CONCURRENCY
-    if(isInCall())
-    {
-        ALOGD("\n  blocking  compress offload on call mode\n");
-        return false;
+    char concpropValue[PROPERTY_VALUE_MAX];
+    if(property_get("voice.playback.conc.disabled", concpropValue, NULL)) {
+         bool propenabled = atoi(concpropValue) || !strncmp("true", concpropValue, 4);
+         if (propenabled) {
+            if(isInCall())
+            {
+                ALOGD("\n  blocking  compress offload on call mode\n");
+                return false;
+            }
+         }
     }
+
 #endif
     // Check if stream type is music, then only allow offload as of now.
     if (offloadInfo.stream_type != AUDIO_STREAM_MUSIC)
@@ -1449,7 +1540,7 @@
 void AudioPolicyManager::setPhoneState(int state)
 
 {
-    ALOGV("setPhoneState() state %d", state);
+    ALOGD("setPhoneState() state %d", state);
     audio_devices_t newDevice = AUDIO_DEVICE_NONE;
     if (state < 0 || state >= AudioSystem::NUM_MODES) {
         ALOGW("setPhoneState() invalid state %d", state);
@@ -1514,6 +1605,117 @@
     if (isStateInCall(oldState) && newDevice == AUDIO_DEVICE_NONE) {
         newDevice = hwOutputDesc->device();
     }
+#ifdef VOICE_CONCURRENCY
+    char propValue[PROPERTY_VALUE_MAX];
+    bool prop_playback_enabled = false, prop_rec_enabled=false, prop_voip_enabled = false;
+
+    if(property_get("voice.playback.conc.disabled", propValue, NULL)) {
+        prop_playback_enabled = atoi(propValue) || !strncmp("true", propValue, 4);
+    }
+
+    if(property_get("voice.record.conc.disabled", propValue, NULL)) {
+        prop_rec_enabled = atoi(propValue) || !strncmp("true", propValue, 4);
+    }
+
+    if(property_get("voice.voip.conc.disabled", propValue, NULL)) {
+        prop_voip_enabled = atoi(propValue) || !strncmp("true", propValue, 4);
+    }
+
+    if((AudioSystem::MODE_IN_CALL != oldState) && (AudioSystem::MODE_IN_CALL == state)) {
+        ALOGD("Entering to call mode oldState :: %d state::%d ",oldState, state);
+
+        if(prop_playback_enabled) {
+            //Call invalidate to reset all opened non ULL audio tracks
+            // Move tracks associated to this strategy from previous output to new output
+            for (int i = AudioSystem::SYSTEM; i < (int)AudioSystem::NUM_STREAM_TYPES; i++) {
+                ALOGV(" Invalidate on call mode for stream :: %d ", i);
+                //FIXME see fixme on name change
+                mpClientInterface->setStreamOutput((AudioSystem::stream_type)i,
+                                                  0 /* ignored */);
+            }
+        }
+
+        if(prop_rec_enabled) {
+            //Close all active inputs
+            audio_io_handle_t activeInput = getActiveInput();
+            if (activeInput != 0) {
+               AudioInputDescriptor *activeDesc = mInputs.valueFor(activeInput);
+               switch(activeDesc->mInputSource) {
+                   case AUDIO_SOURCE_VOICE_UPLINK:
+                   case AUDIO_SOURCE_VOICE_DOWNLINK:
+                   case AUDIO_SOURCE_VOICE_CALL:
+                       ALOGD("FOUND active input during call active: %d",activeDesc->mInputSource);
+                   break;
+
+                   case  AUDIO_SOURCE_VOICE_COMMUNICATION:
+                        if(prop_voip_enabled) {
+                            ALOGD("CLOSING VoIP input source on call setup :%d ",activeDesc->mInputSource);
+                            stopInput(activeInput);
+                            releaseInput(activeInput);
+                        }
+                   break;
+
+                   default:
+                       ALOGD("CLOSING input on call setup  for inputSource: %d",activeDesc->mInputSource);
+                       stopInput(activeInput);
+                       releaseInput(activeInput);
+                   break;
+               }
+           }
+        } else if(prop_voip_enabled) {
+            audio_io_handle_t activeInput = getActiveInput();
+            if (activeInput != 0) {
+               AudioInputDescriptor *activeDesc = mInputs.valueFor(activeInput);
+                if(AUDIO_SOURCE_VOICE_COMMUNICATION == activeDesc->mInputSource) {
+                    ALOGD("CLOSING VoIP on call setup : %d",activeDesc->mInputSource);
+                    stopInput(activeInput);
+                    releaseInput(activeInput);
+                }
+            }
+        }
+
+        //suspend  PCM (deep-buffer) output & close  compress & direct tracks
+        for (size_t i = 0; i < mOutputs.size(); i++) {
+            AudioOutputDescriptor *outputDesc = mOutputs.valueAt(i);
+            if (((!outputDesc->isDuplicated() &&outputDesc->mProfile->mFlags & AUDIO_OUTPUT_FLAG_PRIMARY))
+                        && prop_playback_enabled) {
+                ALOGD(" calling suspendOutput on call mdoe for primary output");
+                mpClientInterface->suspendOutput(mOutputs.keyAt(i));
+            } //Close compress all sessions
+            else if ((outputDesc->mProfile->mFlags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
+                            &&  prop_playback_enabled) {
+                ALOGD(" calling closeOutput on call mdoe for COMPRESS output");
+                closeOutput(mOutputs.keyAt(i));
+            }
+            else if ((outputDesc->mProfile->mFlags & AUDIO_OUTPUT_FLAG_VOIP_RX)
+                            && prop_voip_enabled) {
+                ALOGD(" calling closeOutput on call mdoe for DIRECT  output");
+                closeOutput(mOutputs.keyAt(i));
+            }
+        }
+   }
+
+   if((AudioSystem::MODE_IN_CALL == oldState) && (AudioSystem::MODE_IN_CALL != state)
+             && prop_playback_enabled) {
+        ALOGD("EXITING from call mode oldState :: %d state::%d \n",oldState, state);
+        //restore PCM (deep-buffer) output after call termination
+        for (size_t i = 0; i < mOutputs.size(); i++) {
+            AudioOutputDescriptor *outputDesc = mOutputs.valueAt(i);
+            if (!outputDesc->isDuplicated() &&outputDesc->mProfile->mFlags & AUDIO_OUTPUT_FLAG_PRIMARY) {
+                ALOGD("calling restoreOutput after call mode for primary output");
+                mpClientInterface->restoreOutput(mOutputs.keyAt(i));
+            }
+       }
+       //call invalidate tracks so that any open streams can fall back to deep buffer/compress path from ULL
+       for (int i = AudioSystem::SYSTEM; i < (int)AudioSystem::NUM_STREAM_TYPES; i++) {
+           ALOGD("Invalidate on call mode for stream :: %d ", i);
+           //FIXME see fixme on name change
+           mpClientInterface->setStreamOutput((AudioSystem::stream_type)i,
+                                                  0 /* ignored */);
+       }
+    }
+    mPrevPhoneState = oldState;
+#endif
 
     int delayMs = 0;
     if (isStateInCall(state)) {
@@ -1560,21 +1762,7 @@
     } else {
         mLimitRingtoneVolume = false;
     }
-
-#ifdef VOICE_CONCURRENCY
-    //Call invalidate to reset all opened non ULL audio tracks
-    if(isInCall())
-    {
-        // Move tracks associated to this strategy from previous output to new output
-        for (int i = AudioSystem::SYSTEM; i < (int)AudioSystem::NUM_STREAM_TYPES; i++) {
-                ALOGV("\n Invalidate on call mode for stream :: %d  \n", i);
-                //FIXME see fixme on name change
-                mpClientInterface->setStreamOutput((AudioSystem::stream_type)i,
-                                                  0 /* ignored */);
-        }
-    }
-#endif
-
+    ALOGD(" End of setPhoneState ... mPhoneState: %d ",mPhoneState);
 }
 
 extern "C" AudioPolicyInterface* createAudioPolicyManager(AudioPolicyClientInterface *clientInterface)
diff --git a/policy_hal/AudioPolicyManager.h b/policy_hal/AudioPolicyManager.h
index ca7031d..f2488b2 100644
--- a/policy_hal/AudioPolicyManager.h
+++ b/policy_hal/AudioPolicyManager.h
@@ -106,8 +106,12 @@
         //parameter indicates if HDMI plug in/out detected
         bool mHdmiAudioEvent;
 
+
 private:
         void handleNotificationRoutingForStream(AudioSystem::stream_type stream);
 
+        // Used for voip + voice concurrency usecase
+        int mPrevPhoneState;
+
 };
 };
diff --git a/post_proc/Android.mk b/post_proc/Android.mk
index 2cb910c..c50b7d0 100644
--- a/post_proc/Android.mk
+++ b/post_proc/Android.mk
@@ -3,6 +3,10 @@
 
 include $(CLEAR_VARS)
 
+ifneq ($(strip $(AUDIO_FEATURE_DISABLED_PROXY_DEVICE)),true)
+    LOCAL_CFLAGS += -DAFE_PROXY_ENABLED
+endif
+
 LOCAL_SRC_FILES:= \
 	bundle.c \
 	equalizer.c \
diff --git a/post_proc/bass_boost.c b/post_proc/bass_boost.c
index 657195d..341f145 100644
--- a/post_proc/bass_boost.c
+++ b/post_proc/bass_boost.c
@@ -100,12 +100,12 @@
 
     switch (param) {
     case BASSBOOST_PARAM_STRENGTH_SUPPORTED:
-	ALOGV("%s: BASSBOOST_PARAM_STRENGTH_SUPPORTED", __func__);
+        ALOGV("%s: BASSBOOST_PARAM_STRENGTH_SUPPORTED", __func__);
         *(uint32_t *)value = 1;
         break;
 
     case BASSBOOST_PARAM_STRENGTH:
-	ALOGV("%s: BASSBOOST_PARAM_STRENGTH", __func__);
+        ALOGV("%s: BASSBOOST_PARAM_STRENGTH", __func__);
         *(int16_t *)value = bassboost_get_strength(bass_ctxt);
         break;
 
@@ -133,7 +133,7 @@
 
     switch (param) {
     case BASSBOOST_PARAM_STRENGTH:
-	ALOGV("%s BASSBOOST_PARAM_STRENGTH", __func__);
+        ALOGV("%s BASSBOOST_PARAM_STRENGTH", __func__);
         strength = (uint32_t)(*(int16_t *)value);
         bassboost_set_strength(bass_ctxt, strength);
         break;
@@ -154,7 +154,9 @@
     if((device == AUDIO_DEVICE_OUT_SPEAKER) ||
        (device == AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT) ||
        (device == AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER) ||
+#ifdef AFE_PROXY_ENABLED
        (device == AUDIO_DEVICE_OUT_PROXY) ||
+#endif
        (device == AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
        (device == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET)) {
         if (offload_bassboost_get_enable_flag(&(bass_ctxt->offload_bass))) {
diff --git a/post_proc/virtualizer.c b/post_proc/virtualizer.c
index 54bca07..205b250 100644
--- a/post_proc/virtualizer.c
+++ b/post_proc/virtualizer.c
@@ -100,12 +100,12 @@
 
     switch (param) {
     case VIRTUALIZER_PARAM_STRENGTH_SUPPORTED:
-	ALOGV("%s: VIRTUALIZER_PARAM_STRENGTH_SUPPORTED", __func__);
+        ALOGV("%s: VIRTUALIZER_PARAM_STRENGTH_SUPPORTED", __func__);
         *(uint32_t *)value = 1;
         break;
 
     case VIRTUALIZER_PARAM_STRENGTH:
-	ALOGV("%s: VIRTUALIZER_PARAM_STRENGTH", __func__);
+        ALOGV("%s: VIRTUALIZER_PARAM_STRENGTH", __func__);
         *(int16_t *)value = virtualizer_get_strength(virt_ctxt);
         break;
 
@@ -133,7 +133,7 @@
 
     switch (param) {
     case VIRTUALIZER_PARAM_STRENGTH:
-	ALOGV("%s VIRTUALIZER_PARAM_STRENGTH", __func__);
+        ALOGV("%s VIRTUALIZER_PARAM_STRENGTH", __func__);
         strength = (uint32_t)(*(int16_t *)value);
         virtualizer_set_strength(virt_ctxt, strength);
         break;
@@ -154,7 +154,9 @@
     if((device == AUDIO_DEVICE_OUT_SPEAKER) ||
        (device == AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT) ||
        (device == AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER) ||
+#ifdef AFE_PROXY_ENABLED
        (device == AUDIO_DEVICE_OUT_PROXY) ||
+#endif
        (device == AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
        (device == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET)) {
         if (offload_virtualizer_get_enable_flag(&(virt_ctxt->offload_virt))) {