hal: Fix AudioRecord and AudioTrack timestamps incorrect

Add delay  from xml, add platform capture delay
with audio source for AudioRecord, and add more delay in
platform_render_latency for playback usecases.

Bug: 137600762
Test: Manual test with Clarity test apk
Change-Id: I95088fc1826cbb0ecaf2409d6e184dbaaaae7c12
Signed-off-by: millerliang <millerliang@google.com>
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index 1e3bb91..035b14e 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -3286,7 +3286,7 @@
         // return a smaller number
         period_ms = (out->af_period_multiplier * out->config.period_size *
                      1000) / (out->config.rate);
-        hw_delay = platform_render_latency(out->usecase)/1000;
+        hw_delay = platform_render_latency(out)/1000;
         return period_ms + hw_delay;
     }
 
@@ -3770,7 +3770,7 @@
                 // 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);
+                    (platform_render_latency(out) * 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.
@@ -4490,7 +4490,8 @@
         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;
+            *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec
+                    - platform_capture_latency(in) * 1000LL;
             ret = 0;
         }
     }
diff --git a/hal/msm8916/platform.c b/hal/msm8916/platform.c
index 8600b7d..1a62ac3 100644
--- a/hal/msm8916/platform.c
+++ b/hal/msm8916/platform.c
@@ -554,6 +554,24 @@
 #define DEEP_BUFFER_PLATFORM_DELAY (29*1000LL)
 #define LOW_LATENCY_PLATFORM_DELAY (13*1000LL)
 
+static int audio_usecase_delay_ms[AUDIO_USECASE_MAX] = {0};
+
+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 void query_platform(const char *snd_card_name,
                                       char *mixer_xml_path)
 {
@@ -1453,6 +1471,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)
@@ -2559,17 +2582,85 @@
     return ret;
 }
 
-/* Delay in Us */
-int64_t platform_render_latency(audio_usecase_t usecase)
+void platform_set_audio_source_delay(audio_source_t audio_source, int delay_ms)
 {
-    switch (usecase) {
-        case USECASE_AUDIO_PLAYBACK_DEEP_BUFFER:
-            return DEEP_BUFFER_PLATFORM_DELAY;
-        case USECASE_AUDIO_PLAYBACK_LOW_LATENCY:
-            return LOW_LATENCY_PLATFORM_DELAY;
-        default:
-            return 0;
+    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];
+}
+
+void platform_set_audio_usecase_delay(audio_usecase_t usecase, int delay_ms)
+{
+    if ((usecase <= USECASE_INVALID) || (usecase >= AUDIO_USECASE_MAX)) {
+        ALOGE("%s: invalid usecase case idx %d", __func__, usecase);
+        return;
+    }
+
+    audio_usecase_delay_ms[usecase] = delay_ms;
+}
+
+/* Delay in Us */
+int64_t platform_get_audio_usecase_delay(audio_usecase_t usecase)
+{
+    if ((usecase <= USECASE_INVALID) || (usecase >= AUDIO_USECASE_MAX)) {
+        ALOGE("%s: invalid usecase case idx %d", __func__, usecase);
+        return 0;
+    }
+
+    return 1000LL *  audio_usecase_delay_ms[usecase] ;
+}
+
+/* Delay in Us */
+int64_t platform_render_latency(struct stream_out *out)
+{
+    int64_t delay = 0LL;
+
+    if (!out)
+        return delay;
+
+    switch (out->usecase) {
+        case USECASE_AUDIO_PLAYBACK_DEEP_BUFFER:
+            delay = DEEP_BUFFER_PLATFORM_DELAY;
+            break;
+        case USECASE_AUDIO_PLAYBACK_LOW_LATENCY:
+            delay = LOW_LATENCY_PLATFORM_DELAY;
+            break;
+        default:
+            break;
+    }
+
+/* out->usecase could be used to add delay time if it's necessary */
+    delay += platform_get_audio_usecase_delay(out->usecase);
+    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_set_snd_device_backend(snd_device_t device, const char *backend, const char * hw_interface)
diff --git a/hal/msm8960/platform.c b/hal/msm8960/platform.c
index ae65ef2..6cc5411 100644
--- a/hal/msm8960/platform.c
+++ b/hal/msm8960/platform.c
@@ -226,6 +226,24 @@
 #define DEEP_BUFFER_PLATFORM_DELAY (29*1000LL)
 #define LOW_LATENCY_PLATFORM_DELAY (13*1000LL)
 
+static int audio_usecase_delay_ms[AUDIO_USECASE_MAX] = {0};
+
+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 pthread_once_t check_op_once_ctl = PTHREAD_ONCE_INIT;
 static bool is_tmus = false;
 
@@ -1026,17 +1044,85 @@
     return -ENOSYS;
 }
 
-/* Delay in Us */
-int64_t platform_render_latency(audio_usecase_t usecase)
+void platform_set_audio_source_delay(audio_source_t audio_source, int delay_ms)
 {
-    switch (usecase) {
-        case USECASE_AUDIO_PLAYBACK_DEEP_BUFFER:
-            return DEEP_BUFFER_PLATFORM_DELAY;
-        case USECASE_AUDIO_PLAYBACK_LOW_LATENCY:
-            return LOW_LATENCY_PLATFORM_DELAY;
-        default:
-            return 0;
+    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];
+}
+
+void platform_set_audio_usecase_delay(audio_usecase_t usecase, int delay_ms)
+{
+    if ((usecase <= USECASE_INVALID) || (usecase >= AUDIO_USECASE_MAX)) {
+        ALOGE("%s: invalid usecase case idx %d", __func__, usecase);
+        return;
+    }
+
+    audio_usecase_delay_ms[usecase] = delay_ms;
+}
+
+/* Delay in Us */
+int64_t platform_get_audio_usecase_delay(audio_usecase_t usecase)
+{
+    if ((usecase <= USECASE_INVALID) || (usecase >= AUDIO_USECASE_MAX)) {
+        ALOGE("%s: invalid usecase case idx %d", __func__, usecase);
+        return 0;
+    }
+
+    return 1000LL *  audio_usecase_delay_ms[usecase] ;
+}
+
+/* Delay in Us */
+int64_t platform_render_latency(struct stream_out *out)
+{
+    int64_t delay = 0LL;
+
+    if (!out)
+        return delay;
+
+    switch (out->usecase) {
+        case USECASE_AUDIO_PLAYBACK_DEEP_BUFFER:
+            delay = DEEP_BUFFER_PLATFORM_DELAY;
+            break;
+        case USECASE_AUDIO_PLAYBACK_LOW_LATENCY:
+            delay = LOW_LATENCY_PLATFORM_DELAY;
+            break;
+        default:
+            break;
+    }
+
+/* out->usecase could be used to add delay time if it's necessary */
+    delay += platform_get_audio_usecase_delay(out->usecase);
+    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_switch_voice_call_enable_device_config(void *platform __unused,
@@ -1063,6 +1149,11 @@
     return -ENOSYS;
 }
 
+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_set_usecase_pcm_id(audio_usecase_t usecase __unused, int32_t type __unused,
                                 int32_t pcm_id __unused)
 {
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index d8ec06a..8fa9826 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -741,6 +741,24 @@
 #define ULL_PLATFORM_DELAY         (3*1000LL)
 #define MMAP_PLATFORM_DELAY        (3*1000LL)
 
+static int audio_usecase_delay_ms[AUDIO_USECASE_MAX] = {0};
+
+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 pthread_once_t check_op_once_ctl = PTHREAD_ONCE_INIT;
 static bool is_tmus = false;
 
@@ -2254,6 +2272,11 @@
     return ret;
 }
 
+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,
@@ -3828,22 +3851,92 @@
     return ret;
 }
 
-/* Delay in Us */
-int64_t platform_render_latency(audio_usecase_t usecase)
+void platform_set_audio_source_delay(audio_source_t audio_source, int delay_ms)
 {
-    switch (usecase) {
+    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];
+}
+
+void platform_set_audio_usecase_delay(audio_usecase_t usecase, int delay_ms)
+{
+    if ((usecase <= USECASE_INVALID) || (usecase >= AUDIO_USECASE_MAX)) {
+        ALOGE("%s: invalid usecase case idx %d", __func__, usecase);
+        return;
+    }
+
+    audio_usecase_delay_ms[usecase] = delay_ms;
+}
+
+/* Delay in Us */
+int64_t platform_get_audio_usecase_delay(audio_usecase_t usecase)
+{
+    if ((usecase <= USECASE_INVALID) || (usecase >= AUDIO_USECASE_MAX)) {
+        ALOGE("%s: invalid usecase case idx %d", __func__, usecase);
+        return 0;
+    }
+
+    return 1000LL *  audio_usecase_delay_ms[usecase] ;
+}
+
+/* Delay in Us */
+int64_t platform_render_latency(struct stream_out *out)
+{
+    int64_t delay = 0LL;
+
+    if (!out)
+        return delay;
+
+    switch (out->usecase) {
         case USECASE_AUDIO_PLAYBACK_DEEP_BUFFER:
-            return DEEP_BUFFER_PLATFORM_DELAY;
+            delay = DEEP_BUFFER_PLATFORM_DELAY;
+            break;
         case USECASE_AUDIO_PLAYBACK_LOW_LATENCY:
         case USECASE_AUDIO_PLAYBACK_WITH_HAPTICS:
-            return LOW_LATENCY_PLATFORM_DELAY;
+            delay = LOW_LATENCY_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->usecase could be used to add delay time if it's necessary */
+    delay += platform_get_audio_usecase_delay(out->usecase);
+    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_set_snd_device_backend(snd_device_t device, const char *backend_tag,
diff --git a/hal/platform_api.h b/hal/platform_api.h
index 1d46c31..008e9a6 100644
--- a/hal/platform_api.h
+++ b/hal/platform_api.h
@@ -127,7 +127,8 @@
                                     int table_size);
 
 /* returns the latency for a usecase in Us */
-int64_t platform_render_latency(audio_usecase_t usecase);
+int64_t platform_render_latency(struct stream_out *out);
+int64_t platform_capture_latency(struct stream_in *in);
 
 int platform_set_incall_recording_session_id(void *platform,
                                              uint32_t session_id, int rec_mode);
@@ -209,6 +210,12 @@
                                       unsigned long *service_interval);
 int platform_get_haptics_pcm_device_id();
 
+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);
+
+void platform_set_audio_usecase_delay(audio_usecase_t usecase, int delay_ms);
+
 /* callback functions from platform to common audio HAL */
 struct stream_in *adev_get_active_input(const struct audio_device *adev);
 
diff --git a/hal/platform_info.c b/hal/platform_info.c
index 5159d6d..fd8f745 100644
--- a/hal/platform_info.c
+++ b/hal/platform_info.c
@@ -55,6 +55,8 @@
     MIC_INFO,
     ACDB_METAINFO_KEY,
     EXTERNAL_DEVICE_SPECIFIC,
+    AUDIO_SOURCE_DELAY,
+    AUDIO_OUTPUT_USECASE_DELAY,
 } section_t;
 
 typedef void (* section_process_fn)(const XML_Char **attr);
@@ -75,6 +77,8 @@
 static void process_mic_info(const XML_Char **attr);
 static void process_acdb_metainfo_key(const XML_Char **attr);
 static void process_external_dev(const XML_Char **attr);
+static void process_audio_source_delay(const XML_Char **attr);
+static void process_audio_usecase_delay(const XML_Char **attr);
 
 static section_process_fn section_table[] = {
     [ROOT] = process_root,
@@ -92,6 +96,8 @@
     [MIC_INFO] = process_mic_info,
     [ACDB_METAINFO_KEY] = process_acdb_metainfo_key,
     [EXTERNAL_DEVICE_SPECIFIC] = process_external_dev,
+    [AUDIO_SOURCE_DELAY] = process_audio_source_delay,
+    [AUDIO_OUTPUT_USECASE_DELAY] = process_audio_usecase_delay,
 };
 
 static section_t section;
@@ -523,6 +529,61 @@
     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_audio_usecase_delay(const XML_Char **attr)
+{
+    int index;
+
+    if (strcmp(attr[0], "name") != 0) {
+        ALOGE("%s: 'name' not found", __func__);
+        goto done;
+    }
+
+    index = platform_get_usecase_index((char *)attr[1]);
+    if (index < 0) {
+        ALOGE("%s: usecase %s in %s not found!",
+              __func__, attr[1], PLATFORM_INFO_XML_PATH);
+        goto done;
+    }
+
+    if (strcmp(attr[2], "delay") != 0) {
+        ALOGE("%s: 'delay' not found", __func__);
+        goto done;
+    }
+
+    platform_set_audio_usecase_delay(index, atoi((char *)attr[3]));
+
+done:
+    return;
+}
+
 /* platform specific configuration key-value pairs */
 static void process_config_params(const XML_Char **attr)
 {
@@ -954,6 +1015,16 @@
                 return;
             }
             section = NS;
+        } 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);
+        } else if (strcmp(tag_name, "audio_output_usecase_delay") == 0) {
+            section = AUDIO_OUTPUT_USECASE_DELAY;
+        } else if (strcmp(tag_name, "audio_usecase_delay") == 0) {
+            section_process_fn fn = section_table[section];
+            fn(attr);
         }
     } else {
         if(strcmp(tag_name, "config_params") == 0) {