summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Jeremy Wu <jrwu@google.com> 2022-09-13 09:29:14 +0000
committer Jeremy Wu <jrwu@google.com> 2022-09-15 06:54:17 +0000
commit9bca81c8b9ede39e721dbf2cab4f58b0176f38ab (patch)
tree8dfe6de5f19b471e65867c033b18bd582f08bd4b
parentde31b5a2b4dae9973e9946470f02fec9d6a64545 (diff)
Floss: use CLOCK_MONOTONIC_RAW in A2DP encoding for TARGET_FLOSS
Floss uses CLOCK_MONOTONIC and CLOCK_BOOTTIME for various timestamp and timediff calculation. This causes glitches when the audio stack calculates timestamp and schedules with CLOCK_MONOTONIC_RAW. In this CL, we swap out the clock used in scheduling A2DP packet encoding to use CLOCK_MONOTONIC_RAW when the build is targeted to Floss. Note that we intentionally leave the timestamps in metrics/stats untouched since they have different purposes (e.g., allowing to match with other timestamps across applications). Bug: 241816575 Tag: #floss Test: Build and verify A2DP doesn't glitch Change-Id: I275208e33285282911c49caa599cbb14a810bfa9
-rw-r--r--system/btif/src/btif_a2dp_source.cc11
-rw-r--r--system/common/time_util.cc9
-rw-r--r--system/common/time_util.h2
-rw-r--r--system/common/time_util_unittest.cc46
-rw-r--r--system/test/mock/mock_common_time_util.cc4
5 files changed, 67 insertions, 5 deletions
diff --git a/system/btif/src/btif_a2dp_source.cc b/system/btif/src/btif_a2dp_source.cc
index f13abac71a..55f46dd31c 100644
--- a/system/btif/src/btif_a2dp_source.cc
+++ b/system/btif/src/btif_a2dp_source.cc
@@ -895,8 +895,15 @@ static void btif_a2dp_source_audio_tx_stop_event(void) {
static void btif_a2dp_source_audio_handle_timer(void) {
if (btif_av_is_a2dp_offload_running()) return;
+#ifndef TARGET_FLOSS
uint64_t timestamp_us = bluetooth::common::time_get_os_boottime_us();
- log_tstamps_us("A2DP Source tx timer", timestamp_us);
+ uint64_t stats_timestamp_us = timestamp_us;
+#else
+ uint64_t timestamp_us = bluetooth::common::time_get_os_monotonic_raw_us();
+ uint64_t stats_timestamp_us = bluetooth::common::time_get_os_boottime_us();
+#endif
+
+ log_tstamps_us("A2DP Source tx scheduling timer", timestamp_us);
if (!btif_a2dp_source_cb.media_alarm.IsScheduled()) {
LOG_ERROR("%s: ERROR Media task Scheduled after Suspend", __func__);
@@ -916,7 +923,7 @@ static void btif_a2dp_source_audio_handle_timer(void) {
btif_a2dp_source_cb.encoder_interface->send_frames(timestamp_us);
bta_av_ci_src_data_ready(BTA_AV_CHNL_AUDIO);
update_scheduling_stats(&btif_a2dp_source_cb.stats.tx_queue_enqueue_stats,
- timestamp_us,
+ stats_timestamp_us,
btif_a2dp_source_cb.encoder_interval_ms * 1000);
}
diff --git a/system/common/time_util.cc b/system/common/time_util.cc
index 273be181d0..d77c17c0c8 100644
--- a/system/common/time_util.cc
+++ b/system/common/time_util.cc
@@ -42,6 +42,13 @@ uint64_t time_gettimeofday_us() {
static_cast<uint64_t>(tv.tv_usec);
}
+uint64_t time_get_os_monotonic_raw_us() {
+ struct timespec ts_now = {};
+ clock_gettime(CLOCK_MONOTONIC_RAW, &ts_now);
+
+ return ((uint64_t)ts_now.tv_sec * 1000000L) +
+ ((uint64_t)ts_now.tv_nsec / 1000);
+}
} // namespace common
-} // namespace bluetooth \ No newline at end of file
+} // namespace bluetooth
diff --git a/system/common/time_util.h b/system/common/time_util.h
index 70a64d2cba..16808135c3 100644
--- a/system/common/time_util.h
+++ b/system/common/time_util.h
@@ -33,6 +33,8 @@ uint64_t time_get_os_boottime_us();
// Get the current wall clock time in microseconds.
uint64_t time_gettimeofday_us();
+// Get the OS monotonic raw time in microseconds.
+uint64_t time_get_os_monotonic_raw_us();
} // namespace common
} // namespace bluetooth
diff --git a/system/common/time_util_unittest.cc b/system/common/time_util_unittest.cc
index 77e205d3a6..eb21aee5ad 100644
--- a/system/common/time_util_unittest.cc
+++ b/system/common/time_util_unittest.cc
@@ -42,8 +42,17 @@ TEST(TimeTest, test_time_get_os_boottime_us_not_zero) {
}
//
+// Test that the return value of
+// bluetooth::common::time_get_os_monotonic_raw_us() is not zero.
+//
+TEST(TimeTest, test_time_get_os_monotonic_raw_us_not_zero) {
+ uint64_t t1 = bluetooth::common::time_get_os_monotonic_raw_us();
+ ASSERT_GT(t1, uint64_t(0));
+}
+
+//
// Test that the return value of bluetooth::common::time_get_os_boottime_ms()
-// is monotonically increasing within reasonable boundries.
+// is monotonically increasing within reasonable boundaries.
//
TEST(TimeTest, test_time_get_os_boottime_ms_increases_upper_bound) {
uint64_t t1 = bluetooth::common::time_get_os_boottime_ms();
@@ -53,7 +62,7 @@ TEST(TimeTest, test_time_get_os_boottime_ms_increases_upper_bound) {
//
// Test that the return value of bluetooth::common::time_get_os_boottime_us()
-// is monotonically increasing within reasonable boundries.
+// is monotonically increasing within reasonable boundaries.
//
TEST(TimeTest, test_time_get_os_boottime_us_increases_upper_bound) {
uint64_t t1 = bluetooth::common::time_get_os_boottime_us();
@@ -62,6 +71,17 @@ TEST(TimeTest, test_time_get_os_boottime_us_increases_upper_bound) {
}
//
+// Test that the return value of
+// bluetooth::common::time_get_os_monotonic_raw_us() is monotonically increasing
+// within reasonable boundaries.
+//
+TEST(TimeTest, test_time_get_os_monotonic_raw_time_us_increases_upper_bound) {
+ uint64_t t1 = bluetooth::common::time_get_os_monotonic_raw_us();
+ uint64_t t2 = bluetooth::common::time_get_os_monotonic_raw_us();
+ ASSERT_TRUE((t2 - t1) < TEST_TIME_DELTA_UPPER_BOUND_MS * 1000);
+}
+
+//
// Test that the return value of bluetooth::common::time_get_os_boottime_ms()
// is increasing.
//
@@ -105,6 +125,28 @@ TEST(TimeTest, test_time_get_os_boottime_us_increases_lower_bound) {
}
//
+// Test that the return value of
+// bluetooth::common::time_get_os_monotonic_raw_us() is increasing.
+//
+TEST(TimeTest, test_time_get_os_monotonic_raw_us_increases_lower_bound) {
+ static const uint64_t TEST_TIME_SLEEP_US = 100 * 1000;
+ struct timespec delay = {};
+
+ delay.tv_sec = TEST_TIME_SLEEP_US / (1000 * 1000);
+ delay.tv_nsec = 1000 * (TEST_TIME_SLEEP_US % (1000 * 1000));
+
+ // Take two timestamps with sleep in-between
+ uint64_t t1 = bluetooth::common::time_get_os_monotonic_raw_us();
+ int err = nanosleep(&delay, &delay);
+ uint64_t t2 = bluetooth::common::time_get_os_monotonic_raw_us();
+
+ ASSERT_EQ(err, 0);
+ ASSERT_GT(t2, t1);
+ ASSERT_TRUE((t2 - t1) >= TEST_TIME_SLEEP_US);
+ ASSERT_TRUE((t2 - t1) < TEST_TIME_DELTA_UPPER_BOUND_MS * 1000);
+}
+
+//
// Test that the return value of bluetooth::common::time_gettimeofday_us() is
// not zero.
//
diff --git a/system/test/mock/mock_common_time_util.cc b/system/test/mock/mock_common_time_util.cc
index e29368e8bb..7a9c4d6a13 100644
--- a/system/test/mock/mock_common_time_util.cc
+++ b/system/test/mock/mock_common_time_util.cc
@@ -47,6 +47,10 @@ uint64_t time_gettimeofday_us() {
mock_function_count_map[__func__]++;
return 0;
}
+uint64_t time_get_os_monotonic_raw_us() {
+ mock_function_count_map[__func__]++;
+ return 0;
+}
} // namespace common
} // namespace bluetooth