Merge "hal: Fix incorrect wsa count update during platform_init"
diff --git a/configs/msm8909/msm8909.mk b/configs/msm8909/msm8909.mk
index 9a32dee..f9ce14c 100755
--- a/configs/msm8909/msm8909.mk
+++ b/configs/msm8909/msm8909.mk
@@ -135,6 +135,10 @@
 PRODUCT_PROPERTY_OVERRIDES += \
 vendor.audio.dolby.ds2.enabled=true
 
+#Disable split a2dp
+PRODUCT_PROPERTY_OVERRIDES += \
+persist.vendor.bt.enable.splita2dp=false
+
 PRODUCT_PACKAGES += \
     android.hardware.audio@2.0-service \
     android.hardware.audio@2.0-impl \
diff --git a/configs/msm8937/msm8937.mk b/configs/msm8937/msm8937.mk
index 6200705..0cf380c 100644
--- a/configs/msm8937/msm8937.mk
+++ b/configs/msm8937/msm8937.mk
@@ -228,6 +228,10 @@
 PRODUCT_PROPERTY_OVERRIDES += \
 ro.af.client_heap_size_kbyte=7168
 
+#Disable split a2dp
+PRODUCT_PROPERTY_OVERRIDES += \
+persist.vendor.bt.enable.splita2dp=false
+
 # for HIDL related packages
 PRODUCT_PACKAGES += \
     android.hardware.audio@2.0-service \
diff --git a/configs/msm8953/msm8953.mk b/configs/msm8953/msm8953.mk
index 068317d..83baae5 100644
--- a/configs/msm8953/msm8953.mk
+++ b/configs/msm8953/msm8953.mk
@@ -227,6 +227,10 @@
 PRODUCT_PROPERTY_OVERRIDES += \
 ro.af.client_heap_size_kbyte=7168
 
+#Disable split a2dp
+PRODUCT_PROPERTY_OVERRIDES += \
+persist.vendor.bt.enable.splita2dp=false
+
 # for HIDL related packages
 PRODUCT_PACKAGES += \
     android.hardware.audio@2.0-service \
diff --git a/hal/Makefile.am b/hal/Makefile.am
index 95224d0..46882f1 100644
--- a/hal/Makefile.am
+++ b/hal/Makefile.am
@@ -4,6 +4,7 @@
         -I $(top_srcdir)/hal \
         -I $(top_srcdir)/hal/audio_extn \
         -I $(top_srcdir)/hal/voice_extn \
+        -I $(PKG_CONFIG_SYSROOT_DIR)/usr/include/audio-kernel \
         -I $(top_srcdir)/hal/${TARGET_PLATFORM}
 
 c_sources = audio_hw.c \
diff --git a/hal/audio_extn/usb.c b/hal/audio_extn/usb.c
index af8cc89..8766c0e 100644
--- a/hal/audio_extn/usb.c
+++ b/hal/audio_extn/usb.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2016-2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013, 2016-2018 The Linux Foundation. All rights reserved.
  * Not a Contribution.
  *
  * Copyright (C) 2013 The Android Open Source Project
@@ -51,6 +51,7 @@
 #define ABS_SUB(A, B) (((A) > (B)) ? ((A) - (B)):((B) - (A)))
 #define SAMPLE_RATE_8000          8000
 #define SAMPLE_RATE_11025         11025
+#define SAMPLE_RATE_192000        192000
 // Supported sample rates for USB
 static uint32_t supported_sample_rates[] =
     {384000, 352800, 192000, 176400, 96000, 88200, 64000, 48000, 44100, 32000, 22050, 16000, 11025, 8000};
@@ -280,6 +281,10 @@
         for (i = 0; i < MAX_SAMPLE_RATE_SIZE; i++) {
             if (supported_sample_rates[i] >= min_sr &&
                 supported_sample_rates[i] <= max_sr) {
+                // FIXME: we don't support >192KHz in recording path for now
+                if ((supported_sample_rates[i] > SAMPLE_RATE_192000) &&
+                        (type == USB_CAPTURE))
+                    continue;
                 config->rates[sr_size++] = supported_sample_rates[i];
                 supported_sample_rates_mask[type] |= (1<<i);
                 ALOGI_IF(usb_audio_debug_enable,
@@ -290,6 +295,12 @@
     } else {
         do {
             sr = (uint32_t)atoi(next_sr_string);
+            // FIXME: we don't support >192KHz in recording path for now
+            if ((sr > SAMPLE_RATE_192000) && (type == USB_CAPTURE)) {
+                next_sr_string = strtok_r(NULL, " ,.-", &temp_ptr);
+                continue;
+            }
+
             for (i = 0; i < MAX_SAMPLE_RATE_SIZE; i++) {
                 if (supported_sample_rates[i] == sr) {
                     ALOGI_IF(usb_audio_debug_enable,
diff --git a/hal/audio_extn/utils.c b/hal/audio_extn/utils.c
index e03fdc8..d4c6351 100644
--- a/hal/audio_extn/utils.c
+++ b/hal/audio_extn/utils.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
  * Not a Contribution.
  *
  * Copyright (C) 2014 The Android Open Source Project
@@ -869,6 +869,25 @@
     }
 }
 
+void audio_extn_btsco_get_sample_rate(int snd_device, int *sample_rate)
+{
+    switch (snd_device) {
+    case SND_DEVICE_OUT_BT_SCO:
+    case SND_DEVICE_IN_BT_SCO_MIC:
+    case SND_DEVICE_IN_BT_SCO_MIC_NREC:
+        *sample_rate = 8000;
+        break;
+    case SND_DEVICE_OUT_BT_SCO_WB:
+    case SND_DEVICE_IN_BT_SCO_MIC_WB:
+    case SND_DEVICE_IN_BT_SCO_MIC_WB_NREC:
+        *sample_rate = 16000;
+        break;
+    default:
+        ALOGD("%s:Not a BT SCO device, need not update sampling rate\n", __func__);
+        break;
+    }
+}
+
 static int send_app_type_cfg_for_device(struct audio_device *adev,
                                         struct audio_usecase *usecase,
                                         int split_snd_device)
@@ -935,8 +954,13 @@
         goto exit_send_app_type_cfg;
     }
     snd_device = platform_get_spkr_prot_snd_device(snd_device);
-
-    acdb_dev_id = platform_get_snd_device_acdb_id(snd_device);
+    if (voice_is_in_call_rec_stream(usecase->stream.in) && usecase->type == PCM_CAPTURE) {
+        snd_device_t voice_device = voice_get_incall_rec_snd_device(usecase->in_snd_device);
+        acdb_dev_id = platform_get_snd_device_acdb_id(voice_device);
+        ALOGV("acdb id for voice call use case %d", acdb_dev_id);
+    } else {
+        acdb_dev_id = platform_get_snd_device_acdb_id(snd_device);
+    }
     if (acdb_dev_id <= 0) {
         ALOGE("%s: Couldn't get the acdb dev id", __func__);
         rc = -EINVAL;
@@ -992,6 +1016,7 @@
                    ALOGI("%s using %d sample rate rate for A2DP CoPP",
                         __func__, usecase->stream.out->app_type_cfg.sample_rate);
         }
+        audio_extn_btsco_get_sample_rate(snd_device, &usecase->stream.out->app_type_cfg.sample_rate);
         sample_rate = usecase->stream.out->app_type_cfg.sample_rate;
 
         /* Interactive streams are supported with only direct app type id.
@@ -1034,6 +1059,11 @@
         app_type_cfg[len++] = acdb_dev_id;
         if (usecase->id == USECASE_AUDIO_RECORD_VOIP)
             usecase->stream.in->app_type_cfg.sample_rate = usecase->stream.in->sample_rate;
+        if (voice_is_in_call_rec_stream(usecase->stream.in)) {
+            audio_extn_btsco_get_sample_rate(usecase->in_snd_device, &usecase->stream.in->app_type_cfg.sample_rate);
+        } else {
+            audio_extn_btsco_get_sample_rate(snd_device, &usecase->stream.in->app_type_cfg.sample_rate);
+        }
         sample_rate = usecase->stream.in->app_type_cfg.sample_rate;
         app_type_cfg[len++] = sample_rate;
         if (snd_device_be_idx > 0)
@@ -1067,6 +1097,7 @@
 {
     int i, num_devices = 0;
     snd_device_t new_snd_devices[SND_DEVICE_OUT_END] = {0};
+    snd_device_t in_snd_device = usecase->in_snd_device;
     int rc = 0;
 
     switch (usecase->type) {
@@ -1085,11 +1116,14 @@
     case PCM_CAPTURE:
         ALOGD("%s: usecase->in_snd_device %s",
               __func__, platform_get_snd_device_name(usecase->in_snd_device));
+        if (voice_is_in_call_rec_stream(usecase->stream.in)) {
+            in_snd_device = voice_get_incall_rec_backend_device(usecase->stream.in);
+        }
         /* check for in combo device */
         if (platform_split_snd_device(adev->platform,
-                                      usecase->in_snd_device,
+                                      in_snd_device,
                                       &num_devices, new_snd_devices)) {
-            new_snd_devices[0] = usecase->in_snd_device;
+            new_snd_devices[0] = in_snd_device;
             num_devices = 1;
         }
         break;
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index 9ebe142..c7186d9 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -90,6 +90,7 @@
 #define DIRECT_PCM_NUM_FRAGMENTS 2
 #define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
 #define VOIP_PLAYBACK_VOLUME_MAX 0x2000
+#define PCM_PLAYBACK_VOLUME_MAX 0x2000
 #define DSD_VOLUME_MIN_DB (-110)
 
 #define PROXY_OPEN_RETRY_COUNT           100
@@ -443,6 +444,7 @@
 static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore);
 static int out_set_compr_volume(struct audio_stream_out *stream, float left, float right);
 static int out_set_voip_volume(struct audio_stream_out *stream, float left, float right);
+static int out_set_pcm_volume(struct audio_stream_out *stream, float left, float right);
 
 static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
                                int flags __unused)
@@ -1423,6 +1425,11 @@
                                                                         usecase->out_snd_device,
                                                                         platform_get_input_snd_device(adev->platform, uc_info->devices));
                     enable_audio_route(adev, usecase);
+                    if (usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
+                        out_set_voip_volume(&usecase->stream.out->stream,
+                                            usecase->stream.out->volume_l,
+                                            usecase->stream.out->volume_r);
+                    }
                     if (usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
                         struct str_parms *parms = str_parms_create_str("fm_restore_volume=1");
                         if (parms)
@@ -3094,6 +3101,8 @@
         // apply volume for voip playback after path is set up
         if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
             out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
+        else if ((out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY || out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER))
+            out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
     } else {
         platform_set_stream_channel_map(adev->platform, out->channel_mask,
                    out->pcm_device_id, &out->channel_map_param.channel_map[0]);
@@ -4150,6 +4159,33 @@
     return 0;
 }
 
+static int out_set_pcm_volume(struct audio_stream_out *stream, float left,
+                              float right)
+{
+    struct stream_out *out = (struct stream_out *)stream;
+    /* Volume control for pcm playback */
+    if (left != right) {
+        return -EINVAL;
+    } else {
+        char mixer_ctl_name [128];
+        struct audio_device *adev = out->dev;
+        struct mixer_ctl *ctl;
+        int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
+        snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Volume", pcm_device_id);
+        ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
+        if (!ctl) {
+            ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
+            return -EINVAL;
+        }
+        int volume = (int) (left * PCM_PLAYBACK_VOLUME_MAX);
+        mixer_ctl_set_value(ctl, 0, volume);
+
+        ALOGV("%s : Pcm set volume value %d", __func__, volume);
+
+        return 0;
+    }
+}
+
 static int out_set_volume(struct audio_stream_out *stream, float left,
                           float right)
 {
@@ -4199,6 +4235,13 @@
         out->volume_l = left;
         out->volume_r = right;
         return ret;
+    } else {
+        /* Volume control for pcm playback */
+        if (!out->standby)
+            ret = out_set_pcm_volume(stream, left, right);
+        out->volume_l = left;
+        out->volume_r = right;
+        return ret;
     }
 
     return -ENOSYS;
@@ -4651,43 +4694,27 @@
         clock_gettime(CLOCK_MONOTONIC, timestamp);
     } else {
         if (out->pcm) {
-            int64_t signed_frames = -1;
-            // XXX it might be better to identify these
-            // as realtime usecases?
-            if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP ||
-                out->usecase == USECASE_AUDIO_PLAYBACK_ULL) {
-                unsigned int hw_ptr;
-                if (pcm_mmap_get_hw_ptr(out->pcm, &hw_ptr, timestamp) == 0) {
-                    signed_frames = hw_ptr;
-                }
-                ALOGV("%s frames %lld", __func__, (long long)signed_frames);
-            } else {
-                unsigned int avail;
-                if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
-                    size_t kernel_buffer_size =
-                            out->config.period_size * out->config.period_count;
-                     signed_frames =
-                            out->written - kernel_buffer_size + avail;
-                }
-            }
-
-            // This adjustment accounts for buffering after app processor.
-            // It is based on estimated DSP latency per use case, rather than exact.
-            signed_frames -=
-                    (platform_render_latency(out->usecase) *
-                     out->sample_rate / 1000000LL);
-
-            // Adjustment accounts for A2dp encoder latency with non offload usecases
-            // Note: Encoder latency is returned in ms, while platform_render_latency in us.
-            if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
+            unsigned int avail;
+            if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
+                size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
+                int64_t signed_frames = out->written - kernel_buffer_size + avail;
+                // This adjustment accounts for buffering after app processor.
+                // It is based on estimated DSP latency per use case, rather than exact.
                 signed_frames -=
-                        (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
-            }
+                        (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
 
-            // It would be unusual for this value to be negative, but check just in case ...
-            if (signed_frames >= 0) {
-                *frames = signed_frames;
-                ret = 0;
+                // Adjustment accounts for A2dp encoder latency with non offload usecases
+                // Note: Encoder latency is returned in ms, while platform_render_latency in us.
+                if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
+                    signed_frames -=
+                            (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
+                }
+
+                // It would be unusual for this value to be negative, but check just in case ...
+                if (signed_frames >= 0) {
+                    *frames = signed_frames;
+                    ret = 0;
+                }
             }
         } else if (out->card_status == CARD_STATUS_OFFLINE) {
             *frames = out->written;
diff --git a/hal/msm8916/platform.c b/hal/msm8916/platform.c
index b0c24ac..2e824b0 100644
--- a/hal/msm8916/platform.c
+++ b/hal/msm8916/platform.c
@@ -555,6 +555,9 @@
     [SND_DEVICE_IN_EC_REF_LOOPBACK_MONO] = "ec-ref-loopback-mono",
     [SND_DEVICE_IN_EC_REF_LOOPBACK_STEREO] = "ec-ref-loopback-stereo",
     [SND_DEVICE_IN_HANDSET_GENERIC_QMIC] = "quad-mic",
+    [SND_DEVICE_IN_INCALL_REC_RX] = "incall-rec-rx",
+    [SND_DEVICE_IN_INCALL_REC_TX] = "incall-rec-tx",
+    [SND_DEVICE_IN_INCALL_REC_RX_TX] = "incall-rec-rx-tx",
 };
 
 // Platform specific backend bit width table
@@ -868,6 +871,9 @@
     {TO_NAME_INDEX(SND_DEVICE_IN_EC_REF_LOOPBACK_MONO)},
     {TO_NAME_INDEX(SND_DEVICE_IN_EC_REF_LOOPBACK_STEREO)},
     {TO_NAME_INDEX(SND_DEVICE_IN_HANDSET_GENERIC_QMIC)},
+    {TO_NAME_INDEX(SND_DEVICE_IN_INCALL_REC_RX)},
+    {TO_NAME_INDEX(SND_DEVICE_IN_INCALL_REC_TX)},
+    {TO_NAME_INDEX(SND_DEVICE_IN_INCALL_REC_RX_TX)},
 };
 
 static char * backend_tag_table[SND_DEVICE_MAX] = {0};
@@ -1682,6 +1688,8 @@
     hw_interface_table[SND_DEVICE_IN_UNPROCESSED_QUAD_MIC] = strdup("SLIMBUS_0_TX");
     hw_interface_table[SND_DEVICE_IN_UNPROCESSED_HEADSET_MIC] = strdup("SLIMBUS_0_TX");
     hw_interface_table[SND_DEVICE_IN_HANDSET_GENERIC_QMIC] = strdup("SLIMBUS_0_TX");
+    hw_interface_table[SND_DEVICE_IN_INCALL_REC_RX] = strdup("INCALL_RECORD_RX");
+    hw_interface_table[SND_DEVICE_IN_INCALL_REC_TX] = strdup("INCALL_RECORD_TX");
 
     my_data->max_mic_count = PLATFORM_DEFAULT_MIC_COUNT;
     /*remove ALAC & APE from DSP decoder list based on software decoder availability*/
@@ -3795,6 +3803,11 @@
         new_snd_devices[0] = SND_DEVICE_OUT_SPEAKER;
         new_snd_devices[1] = SND_DEVICE_OUT_BT_A2DP;
         ret = 0;
+    } else if (SND_DEVICE_IN_INCALL_REC_RX_TX == snd_device) {
+        *num_devices = 2;
+        new_snd_devices[0] = SND_DEVICE_IN_INCALL_REC_RX;
+        new_snd_devices[1] = SND_DEVICE_IN_INCALL_REC_TX;
+        ret = 0;
     }
 
     ALOGD("%s: snd_device(%d) num devices(%d) new_snd_devices(%d)", __func__,
diff --git a/hal/msm8916/platform.h b/hal/msm8916/platform.h
index aeefcc2..c610e4c 100644
--- a/hal/msm8916/platform.h
+++ b/hal/msm8916/platform.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
  * Not a Contribution.
  *
  * Copyright (C) 2013 The Android Open Source Project
@@ -229,6 +229,9 @@
     SND_DEVICE_IN_EC_REF_LOOPBACK_MONO,
     SND_DEVICE_IN_EC_REF_LOOPBACK_STEREO,
     SND_DEVICE_IN_HANDSET_GENERIC_QMIC,
+    SND_DEVICE_IN_INCALL_REC_RX,
+    SND_DEVICE_IN_INCALL_REC_TX,
+    SND_DEVICE_IN_INCALL_REC_RX_TX,
     SND_DEVICE_IN_END,
 
     SND_DEVICE_MAX = SND_DEVICE_IN_END,
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index 475e438..e370641 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -539,6 +539,9 @@
     [SND_DEVICE_IN_UNPROCESSED_QUAD_MIC] = "unprocessed-quad-mic",
     [SND_DEVICE_IN_UNPROCESSED_HEADSET_MIC] = "unprocessed-headset-mic",
     [SND_DEVICE_IN_HANDSET_GENERIC_QMIC] = "quad-mic",
+    [SND_DEVICE_IN_INCALL_REC_RX] = "incall-rec-rx",
+    [SND_DEVICE_IN_INCALL_REC_TX] = "incall-rec-tx",
+    [SND_DEVICE_IN_INCALL_REC_RX_TX] = "incall-rec-rx-tx",
 };
 
 // Platform specific backend bit width table
@@ -849,6 +852,9 @@
     {TO_NAME_INDEX(SND_DEVICE_IN_UNPROCESSED_QUAD_MIC)},
     {TO_NAME_INDEX(SND_DEVICE_IN_UNPROCESSED_HEADSET_MIC)},
     {TO_NAME_INDEX(SND_DEVICE_IN_HANDSET_GENERIC_QMIC)},
+    {TO_NAME_INDEX(SND_DEVICE_IN_INCALL_REC_RX)},
+    {TO_NAME_INDEX(SND_DEVICE_IN_INCALL_REC_TX)},
+    {TO_NAME_INDEX(SND_DEVICE_IN_INCALL_REC_RX_TX)},
 };
 
 static char * backend_tag_table[SND_DEVICE_MAX] = {0};
@@ -1539,6 +1545,8 @@
     hw_interface_table[SND_DEVICE_IN_UNPROCESSED_QUAD_MIC] = strdup("SLIMBUS_0_TX");
     hw_interface_table[SND_DEVICE_IN_UNPROCESSED_HEADSET_MIC] = strdup("SLIMBUS_0_TX");
     hw_interface_table[SND_DEVICE_IN_HANDSET_GENERIC_QMIC] = strdup("SLIMBUS_0_TX");
+    hw_interface_table[SND_DEVICE_IN_INCALL_REC_RX] = strdup("INCALL_RECORD_RX");
+    hw_interface_table[SND_DEVICE_IN_INCALL_REC_TX] = strdup("INCALL_RECORD_TX");
 
     my_data->max_mic_count = PLATFORM_DEFAULT_MIC_COUNT;
 
@@ -3604,6 +3612,11 @@
         new_snd_devices[0] = SND_DEVICE_OUT_SPEAKER;
         new_snd_devices[1] = SND_DEVICE_OUT_BT_A2DP;
         ret = 0;
+    } else if (SND_DEVICE_IN_INCALL_REC_RX_TX == snd_device) {
+        *num_devices = 2;
+        new_snd_devices[0] = SND_DEVICE_IN_INCALL_REC_RX;
+        new_snd_devices[1] = SND_DEVICE_IN_INCALL_REC_TX;
+        ret = 0;
     }
 
     ALOGD("%s: snd_device(%d) num devices(%d) new_snd_devices(%d)", __func__,
diff --git a/hal/msm8974/platform.h b/hal/msm8974/platform.h
index 8151ea6..04f25de 100644
--- a/hal/msm8974/platform.h
+++ b/hal/msm8974/platform.h
@@ -234,6 +234,9 @@
     SND_DEVICE_IN_EC_REF_LOOPBACK_MONO,
     SND_DEVICE_IN_EC_REF_LOOPBACK_STEREO,
     SND_DEVICE_IN_HANDSET_GENERIC_QMIC,
+    SND_DEVICE_IN_INCALL_REC_RX,
+    SND_DEVICE_IN_INCALL_REC_TX,
+    SND_DEVICE_IN_INCALL_REC_RX_TX,
     SND_DEVICE_IN_END,
 
     SND_DEVICE_MAX = SND_DEVICE_IN_END,
diff --git a/hal/voice.c b/hal/voice.c
index f9e3562..0a48a05 100644
--- a/hal/voice.c
+++ b/hal/voice.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
  * Not a contribution.
  *
  * Copyright (C) 2013 The Android Open Source Project
@@ -436,6 +436,27 @@
     return ret;
 }
 
+snd_device_t voice_get_incall_rec_backend_device(struct stream_in *in)
+{
+   snd_device_t incall_record_device = {0};
+
+   switch(in->source) {
+    case AUDIO_SOURCE_VOICE_UPLINK:
+        incall_record_device = SND_DEVICE_IN_INCALL_REC_TX;
+        break;
+    case AUDIO_SOURCE_VOICE_DOWNLINK:
+         incall_record_device = SND_DEVICE_IN_INCALL_REC_RX;
+         break;
+    case AUDIO_SOURCE_VOICE_CALL:
+         incall_record_device = SND_DEVICE_IN_INCALL_REC_RX_TX;
+         break;
+    default:
+        ALOGI("Invalid source %d", in->source);
+    }
+
+   return incall_record_device;
+}
+
 snd_device_t voice_get_incall_rec_snd_device(snd_device_t in_snd_device)
 {
     snd_device_t incall_record_device = in_snd_device;
diff --git a/hal/voice.h b/hal/voice.h
index 3ae42a8..ca46e24 100644
--- a/hal/voice.h
+++ b/hal/voice.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2016,2018, The Linux Foundation. All rights reserved.
  * Not a contribution.
  *
  * Copyright (C) 2013 The Android Open Source Project
@@ -101,4 +101,5 @@
                                       snd_device_t out_snd_device,
                                       bool enable);
 bool voice_is_call_state_active(struct audio_device *adev);
+snd_device_t voice_get_incall_rec_backend_device(struct stream_in *in);
 #endif //VOICE_H
diff --git a/mm-audio/aenc-aac/qdsp6/Makefile.am b/mm-audio/aenc-aac/qdsp6/Makefile.am
index 08c9bee..67f0bf1 100644
--- a/mm-audio/aenc-aac/qdsp6/Makefile.am
+++ b/mm-audio/aenc-aac/qdsp6/Makefile.am
@@ -17,6 +17,7 @@
 AM_CPPFLAGS += -DNDEBUG
 AM_CPPFLAGS += -Iinc
 AM_CPPFLAGS += -I ${WORKSPACE}/hardware/qcom/media/mm-core/inc/
+AM_CPPFLAGS += -I $(PKG_CONFIG_SYSROOT_DIR)/usr/include/audio-kernel
 
 c_sources =src/omx_aac_aenc.cpp
 c_sources +=src/aenc_svr.c
diff --git a/mm-audio/aenc-amrnb/qdsp6/Makefile.am b/mm-audio/aenc-amrnb/qdsp6/Makefile.am
index 8becd07..1b7ed7c 100644
--- a/mm-audio/aenc-amrnb/qdsp6/Makefile.am
+++ b/mm-audio/aenc-amrnb/qdsp6/Makefile.am
@@ -17,6 +17,7 @@
 AM_CPPFLAGS += -DFEATURE_NATIVELINUX -Dstrlcpy=g_strlcpy
 AM_CPPFLAGS += -DFEATURE_DSM_DUP_ITEMS
 AM_CPPFLAGS += -I ${WORKSPACE}/hardware/qcom/media/mm-core/inc/
+AM_CPPFLAGS += -I $(PKG_CONFIG_SYSROOT_DIR)/usr/include/audio-kernel
 
 AM_CPPFLAGS += -g
 AM_CPPFLAGS += -DNDEBUG
diff --git a/mm-audio/aenc-g711/qdsp6/Makefile.am b/mm-audio/aenc-g711/qdsp6/Makefile.am
index 02b0d57..9f42449 100644
--- a/mm-audio/aenc-g711/qdsp6/Makefile.am
+++ b/mm-audio/aenc-g711/qdsp6/Makefile.am
@@ -11,6 +11,7 @@
             -DNDEBUG \
             -DAUDIOV2 \
             -I inc \
+            -I $(PKG_CONFIG_SYSROOT_DIR)/usr/include/audio-kernel \
             -I ${WORKSPACE}/hardware/qcom/media/mm-core/inc/
 
 C_SOURCES = src/aenc_svr.c \
diff --git a/post_proc/Makefile.am b/post_proc/Makefile.am
index e161f8d..54602a2 100644
--- a/post_proc/Makefile.am
+++ b/post_proc/Makefile.am
@@ -1,4 +1,5 @@
 AM_CFLAGS = -I ${WORKSPACE}/external/tinyalsa/include \
+            -I $(PKG_CONFIG_SYSROOT_DIR)/usr/include/audio-kernel \
             -I ${WORKSPACE}/system/media/audio_effects/include
 
 c_sources = bundle.c \
diff --git a/qahw_api/test/qahw_multi_record_test.c b/qahw_api/test/qahw_multi_record_test.c
index 2e0a396..e00ef7b 100644
--- a/qahw_api/test/qahw_multi_record_test.c
+++ b/qahw_api/test/qahw_multi_record_test.c
@@ -75,6 +75,8 @@
     double record_length;
     char profile[50];
     char kvpairs[256];
+    bool timestamp_mode;
+    char timestamp_file_in[256];
 };
 
 struct timed_params {
@@ -261,6 +263,7 @@
   char file_name[256] = "/data/rec";
   int data_sz = 0, name_len = strlen(file_name);
   qahw_in_buffer_t in_buf;
+  static int64_t timestamp = 1;
 
   struct audio_config_params* params = (struct audio_config_params*) thread_param;
   qahw_module_handle_t *qahw_mod_handle = params->qahw_mod_handle;
@@ -358,6 +361,17 @@
       test_end();
       pthread_exit(0);
   }
+
+  FILE *fd_in_ts;
+  if (*(params->timestamp_file_in))
+      fd_in_ts = fopen(params->timestamp_file_in, "w+");
+      if (fd_in_ts == NULL) {
+          fprintf(log_file, "playback timestamps file open failed \n");
+          if (log_file != stdout)
+              fprintf(stdout, "playback timestamps file open failed \n");
+          test_end();
+          pthread_exit(0);
+      }
   int bps = 16;
 
   switch(params->config.format) {
@@ -411,8 +425,12 @@
 
       in_buf.buffer = buffer;
       in_buf.bytes = buffer_size;
+      if (params->timestamp_mode)
+          in_buf.timestamp = &timestamp;
       bytes_read = qahw_in_read(in_handle, &in_buf);
 
+      if (params->timestamp_mode)
+          fprintf(fd_in_ts, "timestamp:%lu\n", timestamp);
       if (kpi_mode) {
           if (count == 0) {
               ret = clock_gettime(CLOCK_REALTIME, &tsColdF);
@@ -437,6 +455,7 @@
       }
       data_sz += buffer_size;
   }
+  fclose(fd_in_ts);
   /*Stopping sourcetracking thread*/
   sourcetrack_done = 1;
 
@@ -548,6 +567,7 @@
     thread_param->source = 1;
     thread_param->record_length = 8 /*sec*/;
     thread_param->record_delay = 0 /*sec*/;
+    thread_param->timestamp_mode = false;
 
     thread_param->handle = 0x99A - rec_session;
 }
@@ -568,6 +588,7 @@
     printf(" -D --recording-delay <in seconds>         - Delay in seconds after which recording should be started\n\n");
     printf(" -l  --log-file <FILEPATH>                 - File path for debug msg, to print\n");
     printf("                                             on console use stdout or 1 \n\n");
+    printf(" -m --timestamp-mode <FILEPATH>            - Use this flag to support timestamp-mode and timestamp file path for debug msg\n");
     printf(" -K  --kpi-mode                            - Use this flag to measure latency KPIs for this recording\n\n");
     printf(" -i  --interactive-mode                    - Use this flag if prefer configuring streams using interactive mode\n");
     printf("                                             All other flags passed would be ignore if this flag is used\n\n");
@@ -586,6 +607,8 @@
     printf(" hal_rec_test -F 1 --kpi-mode -> start a recording with low latency input flag and calculate latency KPIs\n\n");
     printf(" hal_rec_test -c 1 -r 16000 -t 30 -k ffvOn=true;ffv_ec_ref_ch_cnt=2 -> Enable FFV with stereo ec ref\n");
     printf("                                               For mono channel 16kHz rate for 30seconds\n\n");
+    printf(" hal_rec_test -d 2 -f 1 -r 44100 -c 2 -t 8 -D 2 -m <FILEPATH> -F 2147483648 --> enable timestamp mode and\n");
+    printf("                                           print timestamp debug msg in specified FILEPATH\n");
 }
 
 static void qti_audio_server_death_notify_cb(void *ctxt __unused) {
@@ -622,6 +645,7 @@
         {"recording-time",  required_argument,    0, 't'},
         {"recording-delay", required_argument,    0, 'D'},
         {"log-file",        required_argument,    0, 'l'},
+        {"timestamp-file",  required_argument,    0, 'm'},
         {"kpi-mode",        no_argument,          0, 'K'},
         {"interactive",     no_argument,          0, 'i'},
         {"source-tracking", no_argument,          0, 'S'},
@@ -634,7 +658,7 @@
     int option_index = 0;
     while ((opt = getopt_long(argc,
                               argv,
-                              "-d:f:F:r:c:s:p:t:D:l:k:KiSh",
+                              "-d:f:F:r:c:s:p:t:D:l:m:k:KiSh",
                               long_options,
                               &option_index)) != -1) {
             switch (opt) {
@@ -668,6 +692,10 @@
             case 'l':
                 snprintf(log_filename, sizeof(log_filename), "%s", optarg);
                 break;
+            case 'm':
+                params[0].timestamp_mode = true;
+                snprintf(params[0].timestamp_file_in, sizeof(params[0].timestamp_file_in), "%s", optarg);
+                break;
             case 'K':
                 kpi_mode = true;
                 break;