hal: Fix AudioRecord and AudioTrack timestamps incorrect
Calculate the timestamps with platfrom and snd device delay.
Add delay for snd device from xml and add platform rendor delay
with snd device delay for capture and playback usecases.
Bug: 137325602
Test: manual test
Change-Id: I2a606018cb1fb6678459e3a407dcb02b7db1b074
Signed-off-by: Robert Lee <lerobert@google.com>
(cherry picked from commit 225f7d47ac137746f99b4a436dfc279dc7be7918)
Signed-off-by: Aniket Kumar Lata <alata@codeaurora.org>
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index 7a42c1b..b3bd5fb 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -4289,8 +4289,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
@@ -5242,7 +5244,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);
@@ -6176,7 +6180,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;
@@ -7073,7 +7080,10 @@
unsigned int avail;
if (pcm_get_htimestamp(in->pcm, &avail, ×tamp) == 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..8fb0ceb 100644
--- a/hal/msm8916/platform.c
+++ b/hal/msm8916/platform.c
@@ -5766,9 +5766,18 @@
return NULL;
}
+void platform_set_snd_device_delay(snd_device_t snd_device __unused, int delay_ms __unused)
+{
+}
+
+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(audio_usecase_t usecase)
+int64_t platform_render_latency(struct audio_device *adev __unused,
+ audio_usecase_t usecase)
{
switch (usecase) {
case USECASE_AUDIO_PLAYBACK_DEEP_BUFFER:
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index c90e68a..7367104 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -1519,6 +1519,8 @@
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)
@@ -2148,6 +2150,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;
@@ -8568,31 +8571,87 @@
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];
+}
+
/* 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 c8c1447..0934bb2 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);
@@ -419,4 +420,5 @@
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);
#endif // AUDIO_PLATFORM_API_H
diff --git a/hal/platform_info.c b/hal/platform_info.c
index 5e25533..40b22bc 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,7 @@
CUSTOM_MTMX_IN_PARAMS,
CUSTOM_MTMX_PARAM_IN_CH_INFO,
MMSECNS,
+ SND_DEV_DELAY,
} section_t;
typedef void (* section_process_fn)(const XML_Char **attr);
@@ -104,6 +105,7 @@
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 section_process_fn section_table[] = {
[ROOT] = process_root,
@@ -128,6 +130,7 @@
[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,
};
static section_t section;
@@ -701,6 +704,34 @@
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_config_params(const XML_Char **attr)
{
if (strcmp(attr[0], "key") != 0) {
@@ -1437,6 +1468,9 @@
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) {
section_process_fn fn = section_table[section];
fn(attr);
}