Merge "audio-hal: use audio source to get delay latency"
diff --git a/hal/audio_extn/qaf.c b/hal/audio_extn/qaf.c
index 46e625d..2cff53e 100644
--- a/hal/audio_extn/qaf.c
+++ b/hal/audio_extn/qaf.c
@@ -952,10 +952,10 @@
 
         if (qaf_mod->stream_out[QAF_OUT_OFFLOAD])
             platform_latency =
-                platform_render_latency(qaf_mod->stream_out[QAF_OUT_OFFLOAD]->usecase);
+                platform_render_latency(qaf_mod->stream_out[QAF_OUT_OFFLOAD]);
         else
             platform_latency =
-                platform_render_latency(qaf_mod->stream_out[QAF_OUT_OFFLOAD_MCH]->usecase);
+                platform_render_latency(qaf_mod->stream_out[QAF_OUT_OFFLOAD_MCH]);
 
         dsp_latency = (platform_latency * sample_rate) / 1000000LL;
     } else if (qaf_mod->stream_out[QAF_OUT_TRANSCODE_PASSTHROUGH] != NULL) {
diff --git a/hal/audio_extn/soundtrigger.c b/hal/audio_extn/soundtrigger.c
index 4ef3581..4f86373 100644
--- a/hal/audio_extn/soundtrigger.c
+++ b/hal/audio_extn/soundtrigger.c
@@ -186,6 +186,8 @@
 #define SVA_PARAM_CHANNEL_INDEX "st_channel_index"
 #define MAX_STR_LENGTH_FFV_PARAMS 30
 #define MAX_FFV_SESSION_ID 100
+
+#define ST_DEVICE SND_DEVICE_IN_HANDSET_MIC
 /*
  * Current proprietary API version used by AHAL. Queried by STHAL
  * for compatibility check with AHAL
@@ -254,7 +256,8 @@
         break;
 
     case PCM_CAPTURE:
-        if (uc_info->id == USECASE_AUDIO_RECORD_VOIP)
+        if (uc_info->stream.in != NULL &&
+             uc_info->stream.in->source == AUDIO_SOURCE_VOICE_COMMUNICATION)
             usecase->type = USECASE_TYPE_VOIP_CALL;
         else
             usecase->type = USECASE_TYPE_PCM_CAPTURE;
@@ -474,14 +477,7 @@
 
 bool is_same_as_st_device(snd_device_t snd_device)
 {
-    if (snd_device == SND_DEVICE_IN_HANDSET_MIC_AEC ||
-        snd_device == SND_DEVICE_IN_HANDSET_MIC ||
-        snd_device == SND_DEVICE_IN_HANDSET_MIC_AEC_NS ||
-        snd_device == SND_DEVICE_IN_SPEAKER_MIC ||
-        snd_device == SND_DEVICE_IN_VOICE_SPEAKER_MIC ||
-        snd_device == SND_DEVICE_IN_SPEAKER_MIC_AEC ||
-        snd_device == SND_DEVICE_IN_SPEAKER_MIC_AEC_NS ||
-        snd_device == SND_DEVICE_IN_SPEAKER_MIC_NS) {
+    if (platform_check_all_backends_match(ST_DEVICE, snd_device)) {
         ALOGD("audio HAL using same device %d as ST", snd_device);
         return true;
     }
@@ -529,32 +525,52 @@
 {
     bool raise_event = false;
     int device_type = -1;
+    struct audio_event_info ev_info;
+
+    ev_info.u.usecase.type = -1;
 
     if (!st_dev)
        return;
 
+    list_init(&ev_info.device_info.devices);
+
     if (snd_device >= SND_DEVICE_OUT_BEGIN &&
         snd_device < SND_DEVICE_OUT_END)
         device_type = PCM_PLAYBACK;
     else if (snd_device >= SND_DEVICE_IN_BEGIN &&
-        snd_device < SND_DEVICE_IN_END)
+        snd_device < SND_DEVICE_IN_END) {
         device_type = PCM_CAPTURE;
-    else {
+        if (is_same_as_st_device(snd_device))
+            update_device_list(&ev_info.device_info.devices, ST_DEVICE_HANDSET_MIC, "", true);
+    } else {
         ALOGE("%s: invalid device 0x%x, for event %d",
                            __func__, snd_device, event);
         return;
     }
 
+    struct stream_in *active_input = adev_get_active_input(st_dev->adev);
+    audio_source_t  source = (active_input == NULL) ?
+                               AUDIO_SOURCE_DEFAULT : active_input->source;
+    if (st_dev->adev->mode == AUDIO_MODE_IN_CALL) {
+        ev_info.u.usecase.type = USECASE_TYPE_VOICE_CALL;
+    } else if ((st_dev->adev->mode == AUDIO_MODE_IN_COMMUNICATION ||
+                source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
+               active_input) {
+        ev_info.u.usecase.type  = USECASE_TYPE_VOIP_CALL;
+    } else if (device_type == PCM_CAPTURE) {
+        ev_info.u.usecase.type  = USECASE_TYPE_PCM_CAPTURE;
+    }
+
     raise_event = platform_sound_trigger_device_needs_event(snd_device);
     ALOGI("%s: device 0x%x of type %d for Event %d, with Raise=%d",
         __func__, snd_device, device_type, event, raise_event);
     if (raise_event && (device_type == PCM_CAPTURE)) {
         switch(event) {
         case ST_EVENT_SND_DEVICE_FREE:
-            st_dev->st_callback(AUDIO_EVENT_CAPTURE_DEVICE_INACTIVE, NULL);
+            st_dev->st_callback(AUDIO_EVENT_CAPTURE_DEVICE_INACTIVE, &ev_info);
             break;
         case ST_EVENT_SND_DEVICE_BUSY:
-            st_dev->st_callback(AUDIO_EVENT_CAPTURE_DEVICE_ACTIVE, NULL);
+            st_dev->st_callback(AUDIO_EVENT_CAPTURE_DEVICE_ACTIVE, &ev_info);
             break;
         default:
             ALOGW("%s:invalid event %d for device 0x%x",
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index 13910f6..48c4ad0 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -4297,8 +4297,10 @@
     /* This adjustment accounts for buffering after app processor.
      * It is based on estimated DSP latency per use case, rather than exact.
      */
-    int64_t platform_latency =  platform_render_latency(out->usecase) *
+    pthread_mutex_lock(&adev->lock);
+    int64_t platform_latency =  platform_render_latency(out->dev, out->usecase) *
                                 out->sample_rate / 1000000LL;
+    pthread_mutex_unlock(&adev->lock);
 
     pthread_mutex_lock(&out->position_query_lock);
     /* not querying actual state of buffering in kernel as it would involve an ioctl call
@@ -5250,7 +5252,9 @@
                          1000) / (out->config.rate);
         else
             period_ms = 0;
-        latency = period_ms + platform_render_latency(out->usecase)/1000;
+        pthread_mutex_lock(&adev->lock);
+        latency = period_ms + platform_render_latency(out->dev, out->usecase)/1000;
+        pthread_mutex_unlock(&adev->lock);
     } else {
         latency = (out->config.period_count * out->config.period_size * 1000) /
            (out->config.rate);
@@ -6184,7 +6188,10 @@
 
                 // This adjustment accounts for buffering after app processor.
                 // It is based on estimated DSP latency per use case, rather than exact.
-                frames_temp = platform_render_latency(out->usecase) * out->sample_rate / 1000000LL;
+                pthread_mutex_lock(&adev->lock);
+                frames_temp = platform_render_latency(out->dev, out->usecase) *
+                              out->sample_rate / 1000000LL;
+                pthread_mutex_unlock(&adev->lock);
                 if (signed_frames >= frames_temp)
                     signed_frames -= frames_temp;
 
@@ -7081,7 +7088,10 @@
         unsigned int avail;
         if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
             *frames = in->frames_read + avail;
-            *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
+            pthread_mutex_lock(&adev->lock);
+            *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec
+                    - platform_capture_latency(in->dev, in->usecase) * 1000LL;
+            pthread_mutex_unlock(&adev->lock);
             ret = 0;
         }
     }
diff --git a/hal/msm8916/platform.c b/hal/msm8916/platform.c
index b1ba217..73d8b74 100644
--- a/hal/msm8916/platform.c
+++ b/hal/msm8916/platform.c
@@ -1034,6 +1034,22 @@
 #define ULL_PLATFORM_DELAY (6*1000LL)
 #define MMAP_PLATFORM_DELAY (3*1000LL)
 
+static int audio_source_delay_ms[AUDIO_SOURCE_CNT] = {0};
+
+static struct name_to_index audio_source_index[AUDIO_SOURCE_CNT] = {
+    {TO_NAME_INDEX(AUDIO_SOURCE_DEFAULT)},
+    {TO_NAME_INDEX(AUDIO_SOURCE_MIC)},
+    {TO_NAME_INDEX(AUDIO_SOURCE_VOICE_UPLINK)},
+    {TO_NAME_INDEX(AUDIO_SOURCE_VOICE_DOWNLINK)},
+    {TO_NAME_INDEX(AUDIO_SOURCE_VOICE_CALL)},
+    {TO_NAME_INDEX(AUDIO_SOURCE_CAMCORDER)},
+    {TO_NAME_INDEX(AUDIO_SOURCE_VOICE_RECOGNITION)},
+    {TO_NAME_INDEX(AUDIO_SOURCE_VOICE_COMMUNICATION)},
+    {TO_NAME_INDEX(AUDIO_SOURCE_REMOTE_SUBMIX)},
+    {TO_NAME_INDEX(AUDIO_SOURCE_UNPROCESSED)},
+    {TO_NAME_INDEX(AUDIO_SOURCE_VOICE_PERFORMANCE)},
+};
+
 static const char *platform_get_mixer_control(struct mixer_ctl *);
 
 static void update_interface(const char *snd_card_name) {
@@ -3215,6 +3231,11 @@
     return find_index(usecase_name_index, AUDIO_USECASE_MAX, usecase_name);
 }
 
+int platform_get_audio_source_index(const char *audio_source_name)
+{
+    return find_index(audio_source_index, AUDIO_SOURCE_CNT, audio_source_name);
+}
+
 int platform_get_effect_config_data(snd_device_t snd_device,
                                       struct audio_effect_config *effect_config,
                                       effect_type_t effect_type)
@@ -5767,24 +5788,80 @@
 }
 
 
-/* Delay in Us, only to be used for PCM formats */
-int64_t platform_render_latency(audio_usecase_t usecase)
+void platform_set_snd_device_delay(snd_device_t snd_device __unused, int delay_ms __unused)
 {
+}
+
+void platform_set_audio_source_delay(audio_source_t audio_source, int delay_ms)
+{
+    if ((audio_source < AUDIO_SOURCE_DEFAULT) ||
+           (audio_source > AUDIO_SOURCE_MAX)) {
+        ALOGE("%s: Invalid audio_source = %d", __func__, audio_source);
+        return;
+    }
+
+    audio_source_delay_ms[audio_source] = delay_ms;
+}
+
+/* Delay in Us */
+int64_t platform_get_audio_source_delay(audio_source_t audio_source)
+{
+    if ((audio_source < AUDIO_SOURCE_DEFAULT) ||
+            (audio_source > AUDIO_SOURCE_MAX)) {
+        ALOGE("%s: Invalid audio_source = %d", __func__, audio_source);
+        return 0;
+    }
+
+    return 1000LL * audio_source_delay_ms[audio_source];
+}
+
+int64_t platform_capture_latency(struct audio_device *adev __unused,
+                                 audio_usecase_t usecase)
+{
+}
+
+/* Delay in Us, only to be used for PCM formats */
+int64_t platform_render_latency(struct audio_device *adev __unused,
+                                audio_usecase_t usecase)
+{
+    int64_t delay = 0LL;
+
     switch (usecase) {
         case USECASE_AUDIO_PLAYBACK_DEEP_BUFFER:
-            return DEEP_BUFFER_PLATFORM_DELAY;
+            delay = DEEP_BUFFER_PLATFORM_DELAY;
+            break;
         case USECASE_AUDIO_PLAYBACK_LOW_LATENCY:
-            return LOW_LATENCY_PLATFORM_DELAY;
+            delay = LOW_LATENCY_PLATFORM_DELAY;
+            break;
         case USECASE_AUDIO_PLAYBACK_OFFLOAD:
         case USECASE_AUDIO_PLAYBACK_OFFLOAD2:
-            return PCM_OFFLOAD_PLATFORM_DELAY;
+            delay = PCM_OFFLOAD_PLATFORM_DELAY;
+            break;
         case USECASE_AUDIO_PLAYBACK_ULL:
-            return ULL_PLATFORM_DELAY;
+            delay = ULL_PLATFORM_DELAY;
+            break;
         case USECASE_AUDIO_PLAYBACK_MMAP:
-            return MMAP_PLATFORM_DELAY;
+            delay = MMAP_PLATFORM_DELAY;
+            break;
         default:
-            return 0;
+            break;
     }
+
+    /* out->device could be used to add delay time if it's necessary */
+    return delay;
+}
+
+int64_t platform_capture_latency(struct stream_in *in)
+{
+    int64_t delay = 0LL;
+
+    if (!in)
+        return delay;
+
+    delay = platform_get_audio_source_delay(in->source);
+
+    /* in->device could be used to add delay time if it's necessary */
+    return delay;
 }
 
 int platform_update_usecase_from_source(int source, int usecase)
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index a8892f3..122e4fc 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -1520,12 +1520,30 @@
     sizeof(msm_device_to_be_id) / sizeof(msm_device_to_be_id[0]);
 #endif
 
+static int snd_device_delay_ms[SND_DEVICE_MAX] = {0};
+
 #define DEEP_BUFFER_PLATFORM_DELAY (29*1000LL)
 #define PCM_OFFLOAD_PLATFORM_DELAY (30*1000LL)
 #define LOW_LATENCY_PLATFORM_DELAY (13*1000LL)
 #define ULL_PLATFORM_DELAY         (3*1000LL)
 #define MMAP_PLATFORM_DELAY        (3*1000LL)
 
+static int audio_source_delay_ms[AUDIO_SOURCE_CNT] = {0};
+
+static struct name_to_index audio_source_index[AUDIO_SOURCE_CNT] = {
+    {TO_NAME_INDEX(AUDIO_SOURCE_DEFAULT)},
+    {TO_NAME_INDEX(AUDIO_SOURCE_MIC)},
+    {TO_NAME_INDEX(AUDIO_SOURCE_VOICE_UPLINK)},
+    {TO_NAME_INDEX(AUDIO_SOURCE_VOICE_DOWNLINK)},
+    {TO_NAME_INDEX(AUDIO_SOURCE_VOICE_CALL)},
+    {TO_NAME_INDEX(AUDIO_SOURCE_CAMCORDER)},
+    {TO_NAME_INDEX(AUDIO_SOURCE_VOICE_RECOGNITION)},
+    {TO_NAME_INDEX(AUDIO_SOURCE_VOICE_COMMUNICATION)},
+    {TO_NAME_INDEX(AUDIO_SOURCE_REMOTE_SUBMIX)},
+    {TO_NAME_INDEX(AUDIO_SOURCE_UNPROCESSED)},
+    {TO_NAME_INDEX(AUDIO_SOURCE_VOICE_PERFORMANCE)},
+};
+
 static bool is_usb_snd_dev(snd_device_t snd_device)
 {
     if (snd_device < SND_DEVICE_IN_BEGIN) {
@@ -2154,6 +2172,7 @@
         hw_interface_table[dev] = NULL;
         operator_specific_device_table[dev] = NULL;
         external_specific_device_table[dev] = NULL;
+        snd_device_delay_ms[dev] = 0;
     }
     for (dev = 0; dev < SND_DEVICE_MAX; dev++) {
         backend_bit_width_table[dev] = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
@@ -4647,6 +4666,11 @@
     return find_index(usecase_name_index, AUDIO_USECASE_MAX, usecase_name);
 }
 
+int platform_get_audio_source_index(const char *audio_source_name)
+{
+    return find_index(audio_source_index, AUDIO_SOURCE_CNT, audio_source_name);
+}
+
 void platform_add_operator_specific_device(snd_device_t snd_device,
                                            const char *operator,
                                            const char *mixer_path,
@@ -8602,31 +8626,110 @@
     return NULL;
 }
 
+void platform_set_snd_device_delay(snd_device_t snd_device, int delay_ms)
+{
+    if ((snd_device < SND_DEVICE_MIN) || (snd_device >= SND_DEVICE_MAX)) {
+        ALOGE("%s: Invalid snd_device = %d", __func__, snd_device);
+        return;
+    }
+
+    snd_device_delay_ms[snd_device] = delay_ms;
+}
+
+/* return delay in Us */
+int64_t platform_get_snd_device_delay(snd_device_t snd_device)
+{
+    if ((snd_device < SND_DEVICE_MIN) || (snd_device >= SND_DEVICE_MAX)) {
+        ALOGE("%s: Invalid snd_device = %d", __func__, snd_device);
+        return 0;
+    }
+    return 1000LL * (int64_t)snd_device_delay_ms[snd_device];
+}
+
+void platform_set_audio_source_delay(audio_source_t audio_source, int delay_ms)
+{
+    if ((audio_source < AUDIO_SOURCE_DEFAULT) ||
+           (audio_source > AUDIO_SOURCE_MAX)) {
+        ALOGE("%s: Invalid audio_source = %d", __func__, audio_source);
+        return;
+    }
+
+    audio_source_delay_ms[audio_source] = delay_ms;
+}
+
+/* Delay in Us */
+int64_t platform_get_audio_source_delay(audio_source_t audio_source)
+{
+    if ((audio_source < AUDIO_SOURCE_DEFAULT) ||
+            (audio_source > AUDIO_SOURCE_MAX)) {
+        ALOGE("%s: Invalid audio_source = %d", __func__, audio_source);
+        return 0;
+    }
+
+    return 1000LL * audio_source_delay_ms[audio_source];
+}
+
 /* Delay in Us */
 /* Delay in Us, only to be used for PCM formats */
-int64_t platform_render_latency(audio_usecase_t usecase)
+int64_t platform_render_latency(struct audio_device *adev, audio_usecase_t usecase)
 {
+    int64_t delay = 0LL;
+    struct audio_usecase *uc_info;
+
     switch (usecase) {
         case USECASE_AUDIO_PLAYBACK_DEEP_BUFFER:
         case USECASE_AUDIO_PLAYBACK_MEDIA:
         case USECASE_AUDIO_PLAYBACK_NAV_GUIDANCE:
         case USECASE_AUDIO_PLAYBACK_REAR_SEAT:
-            return DEEP_BUFFER_PLATFORM_DELAY;
+            delay = DEEP_BUFFER_PLATFORM_DELAY;
+            break;
         case USECASE_AUDIO_PLAYBACK_LOW_LATENCY:
         case USECASE_AUDIO_PLAYBACK_WITH_HAPTICS:
         case USECASE_AUDIO_PLAYBACK_SYS_NOTIFICATION:
         case USECASE_AUDIO_PLAYBACK_PHONE:
-            return LOW_LATENCY_PLATFORM_DELAY;
+            delay = LOW_LATENCY_PLATFORM_DELAY;
+            break;
         case USECASE_AUDIO_PLAYBACK_OFFLOAD:
         case USECASE_AUDIO_PLAYBACK_OFFLOAD2:
-             return PCM_OFFLOAD_PLATFORM_DELAY;
+            delay = PCM_OFFLOAD_PLATFORM_DELAY;
+            break;
         case USECASE_AUDIO_PLAYBACK_ULL:
-             return ULL_PLATFORM_DELAY;
+            delay = ULL_PLATFORM_DELAY;
+            break;
         case USECASE_AUDIO_PLAYBACK_MMAP:
-             return MMAP_PLATFORM_DELAY;
+            delay = MMAP_PLATFORM_DELAY;
+            break;
         default:
-            return 0;
+            break;
     }
+
+    uc_info = get_usecase_from_list(adev, usecase);
+
+    if (uc_info != NULL) {
+        if (uc_info->type == PCM_PLAYBACK)
+            delay += platform_get_snd_device_delay(uc_info->out_snd_device);
+        else
+            ALOGE("%s: Invalid uc_info->type %d", __func__, uc_info->type);
+    }
+
+    return delay;
+}
+
+int64_t platform_capture_latency(struct audio_device *adev, audio_usecase_t usecase)
+{
+    int64_t delay = 0LL;
+    struct audio_usecase *uc_info;
+
+    uc_info = get_usecase_from_list(adev, usecase);
+
+    if (uc_info != NULL) {
+        if (uc_info->type == PCM_CAPTURE)
+            delay += platform_get_snd_device_delay(uc_info->in_snd_device);
+        else
+            ALOGE("%s: Invalid uc_info->type %d", __func__, uc_info->type);
+    }
+
+    return delay;
 }
 
 int platform_update_usecase_from_source(int source, int usecase)
diff --git a/hal/platform_api.h b/hal/platform_api.h
index 05ddcb1..1da7198 100644
--- a/hal/platform_api.h
+++ b/hal/platform_api.h
@@ -236,7 +236,8 @@
 int platform_update_lch(void *platform, struct voice_session *session,
                         enum voice_lch_mode lch_mode);
 /* returns the latency for a usecase in Us */
-int64_t platform_render_latency(audio_usecase_t usecase);
+int64_t platform_render_latency(struct audio_device* adev, audio_usecase_t usecase);
+int64_t platform_capture_latency(struct audio_device* adev, audio_usecase_t usecase);
 int platform_update_usecase_from_source(int source, audio_usecase_t usecase);
 
 bool platform_listen_device_needs_event(snd_device_t snd_device);
@@ -314,6 +315,7 @@
                               int *num_devices,
                               snd_device_t *new_snd_devices);
 
+bool platform_check_all_backends_match(snd_device_t snd_device1, snd_device_t snd_device2);
 bool platform_check_backends_match(snd_device_t snd_device1, snd_device_t snd_device2);
 int platform_set_sidetone(struct audio_device *adev,
                           snd_device_t out_snd_device,
@@ -418,4 +420,9 @@
                                   int controller, int stream);
 int platform_get_display_port_ctl_index(int controller, int stream);
 bool platform_is_call_proxy_snd_device(snd_device_t snd_device);
+void platform_set_snd_device_delay(snd_device_t snd_device, int delay_ms);
+void platform_set_audio_source_delay(audio_source_t audio_source, int delay_ms);
+
+int platform_get_audio_source_index(const char *audio_source_name);
+
 #endif // AUDIO_PLATFORM_API_H
diff --git a/hal/platform_info.c b/hal/platform_info.c
index 5e25533..9b64c79 100644
--- a/hal/platform_info.c
+++ b/hal/platform_info.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2019, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2020, 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
@@ -77,6 +77,8 @@
     CUSTOM_MTMX_IN_PARAMS,
     CUSTOM_MTMX_PARAM_IN_CH_INFO,
     MMSECNS,
+    SND_DEV_DELAY,
+    AUDIO_SOURCE_DELAY,
 } section_t;
 
 typedef void (* section_process_fn)(const XML_Char **attr);
@@ -104,6 +106,8 @@
 static void process_custom_mtmx_in_params(const XML_Char **attr);
 static void process_custom_mtmx_param_in_ch_info(const XML_Char **attr);
 static void process_fluence_mmsecns(const XML_Char **attr);
+static void process_snd_device_delay(const XML_Char **attr);
+static void process_audio_source_delay(const XML_Char **attr);
 
 static section_process_fn section_table[] = {
     [ROOT] = process_root,
@@ -128,6 +132,8 @@
     [CUSTOM_MTMX_IN_PARAMS] = process_custom_mtmx_in_params,
     [CUSTOM_MTMX_PARAM_IN_CH_INFO] = process_custom_mtmx_param_in_ch_info,
     [MMSECNS] = process_fluence_mmsecns,
+    [SND_DEV_DELAY] = process_snd_device_delay,
+    [AUDIO_SOURCE_DELAY] = process_audio_source_delay,
 };
 
 static section_t section;
@@ -701,6 +707,60 @@
     return;
 }
 
+static void process_snd_device_delay(const XML_Char **attr)
+{
+    snd_device_t snd_device = SND_DEVICE_NONE;
+
+    if (strcmp(attr[0], "name") != 0) {
+        ALOGE("%s: 'name' not found", __func__);
+        goto done;
+    }
+
+    snd_device = platform_get_snd_device_index((char *)attr[1]);
+    if (snd_device < 0) {
+        ALOGE("%s: Device %s in %s not found, no ACDB ID set!",
+              __func__, (char *)attr[3], PLATFORM_INFO_XML_PATH);
+        goto done;
+    }
+
+    if (strcmp(attr[2], "delay") != 0) {
+        ALOGE("%s: 'delay' not found", __func__);
+        goto done;
+    }
+
+    platform_set_snd_device_delay(snd_device, atoi((char *)attr[3]));
+
+done:
+    return;
+}
+
+static void process_audio_source_delay(const XML_Char **attr)
+{
+    audio_source_t audio_source = -1;
+
+    if (strcmp(attr[0], "name") != 0) {
+        ALOGE("%s: 'name' not found", __func__);
+        goto done;
+    }
+    audio_source = platform_get_audio_source_index((const char *)attr[1]);
+
+    if (audio_source < 0) {
+        ALOGE("%s: audio_source %s is not defined",
+              __func__, (char *)attr[1]);
+        goto done;
+    }
+
+    if (strcmp(attr[2], "delay") != 0) {
+        ALOGE("%s: 'delay' not found", __func__);
+        goto done;
+    }
+
+    platform_set_audio_source_delay(audio_source, atoi((char *)attr[3]));
+
+done:
+    return;
+}
+
 static void process_config_params(const XML_Char **attr)
 {
     if (strcmp(attr[0], "key") != 0) {
@@ -1437,6 +1497,12 @@
                 return;
             }
             section = CUSTOM_MTMX_PARAM_IN_CH_INFO;
+        } else if (strcmp(tag_name, "snd_device_delay") == 0) {
+            section = SND_DEV_DELAY;
+        } else if (strcmp(tag_name, "device_delay") == 0) {
+        } else if (strcmp(tag_name, "audio_input_source_delay") == 0) {
+            section = AUDIO_SOURCE_DELAY;
+        } else if (strcmp(tag_name, "audio_source_delay") == 0) {
             section_process_fn fn = section_table[section];
             fn(attr);
         }