diff options
author | 2024-04-07 12:24:01 +0000 | |
---|---|---|
committer | 2024-05-08 09:29:57 +0000 | |
commit | 1e43219cd13a46c2f6636e6c9707cea1970a7038 (patch) | |
tree | 35ff03f010fbc3426404845ae3ebb1c02e943892 | |
parent | ba2e67285bf8d6e30fc779ae82f4bca606241ca8 (diff) |
Floss: address clock drift in asrc
Since ISO packets are sent out at fixed intervals, the |RepeatingTimer|
utility determines an important time domain.
By default, it uses NTP-adjusted clocks, the difference between the
timestamps of which is compatible with
|CLOCK_REALTIME/MONOTONIC/BOOTTIME| and such, aligning with Android's
audio server.
However, CrAS uses |CLOCK_MONOTONIC_RAW|, which is another time domain,
unaffected by NTP, and this can cause xruns when the clock drift
accumulates, which does relatively quickly.
This CL adds a parameter to |RepeatingTimer| to allow scheduling based
on |CLOCK_MONOTONIC_RAW|, where despite each |DelayedCallback| can still
drift (since libchrome schedulers use NTP-adjusted clocks), in the long
run they are aligned.
Bug: 333334341
Test: m Bluetooth
Flag: EXEMPT floss only changes
Change-Id: Ie90952138d53a67171f526db55edd604306a96f6
-rw-r--r-- | system/bta/le_audio/audio_hal_client/audio_source_hal_client.cc | 5 | ||||
-rw-r--r-- | system/btif/src/btif_a2dp_source.cc | 7 | ||||
-rw-r--r-- | system/common/repeating_timer.cc | 11 | ||||
-rw-r--r-- | system/common/repeating_timer.h | 9 | ||||
-rw-r--r-- | system/common/time_util.cc | 12 | ||||
-rw-r--r-- | system/common/time_util.h | 4 | ||||
-rw-r--r-- | system/gd/Android.bp | 6 | ||||
-rw-r--r-- | system/gd/hal/link_clocker.cc | 5 |
8 files changed, 40 insertions, 19 deletions
diff --git a/system/bta/le_audio/audio_hal_client/audio_source_hal_client.cc b/system/bta/le_audio/audio_hal_client/audio_source_hal_client.cc index 2a0768c5c9..6470edb6dd 100644 --- a/system/bta/le_audio/audio_hal_client/audio_source_hal_client.cc +++ b/system/bta/le_audio/audio_hal_client/audio_source_hal_client.cc @@ -74,7 +74,10 @@ class SourceImpl : public LeAudioSourceAudioHalClient { // Internal functionality SourceImpl(bool is_broadcaster) : le_audio_sink_hal_state_(HAL_UNINITIALIZED), - is_broadcaster_(is_broadcaster){}; + audio_timer_( + /* clock_tick_us= */ bluetooth::common:: + time_get_audio_server_tick_us), + is_broadcaster_(is_broadcaster) {} ~SourceImpl() override { if (le_audio_sink_hal_state_ != HAL_UNINITIALIZED) Release(); } diff --git a/system/btif/src/btif_a2dp_source.cc b/system/btif/src/btif_a2dp_source.cc index a68af1d75e..ae955655f2 100644 --- a/system/btif/src/btif_a2dp_source.cc +++ b/system/btif/src/btif_a2dp_source.cc @@ -898,13 +898,8 @@ 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(); - uint64_t stats_timestamp_us = timestamp_us; -#else - uint64_t timestamp_us = bluetooth::common::time_get_os_monotonic_raw_us(); + uint64_t timestamp_us = bluetooth::common::time_get_audio_server_tick_us(); uint64_t stats_timestamp_us = bluetooth::common::time_get_os_boottime_us(); -#endif log_tstamps_us("A2DP Source tx scheduling timer", timestamp_us); diff --git a/system/common/repeating_timer.cc b/system/common/repeating_timer.cc index 841343989f..f0a75ea69a 100644 --- a/system/common/repeating_timer.cc +++ b/system/common/repeating_timer.cc @@ -20,7 +20,6 @@ #include <bluetooth/log.h> #include "message_loop_thread.h" -#include "time_util.h" namespace bluetooth { @@ -47,7 +46,7 @@ bool RepeatingTimer::SchedulePeriodic( return false; } - uint64_t time_now_us = time_get_os_boottime_us(); + uint64_t time_now_us = clock_tick_us_(); uint64_t time_next_task_us = time_now_us + period.count(); std::lock_guard<std::recursive_mutex> api_lock(api_mutex_); if (thread == nullptr) { @@ -61,7 +60,7 @@ bool RepeatingTimer::SchedulePeriodic( base::Bind(&RepeatingTimer::RunTask, base::Unretained(this))); message_loop_thread_ = thread; period_ = period; - uint64_t time_until_next_us = time_next_task_us - time_get_os_boottime_us(); + uint64_t time_until_next_us = time_next_task_us - clock_tick_us_(); if (!thread->DoInThreadDelayed( from_here, task_wrapper_.callback(), std::chrono::microseconds(time_until_next_us))) { @@ -139,7 +138,7 @@ void RepeatingTimer::RunTask() { int64_t period_us = period_.count(); expected_time_next_task_us_ += period_us; - uint64_t time_now_us = time_get_os_boottime_us(); + uint64_t time_now_us = clock_tick_us_(); int64_t remaining_time_us = expected_time_next_task_us_ - time_now_us; if (remaining_time_us < 0) { // if remaining_time_us is negative, schedule the task to the nearest @@ -150,9 +149,9 @@ void RepeatingTimer::RunTask() { FROM_HERE, task_wrapper_.callback(), std::chrono::microseconds(remaining_time_us)); - uint64_t time_before_task_us = time_get_os_boottime_us(); + uint64_t time_before_task_us = clock_tick_us_(); task_.Run(); - uint64_t time_after_task_us = time_get_os_boottime_us(); + uint64_t time_after_task_us = clock_tick_us_(); auto task_time_us = static_cast<int64_t>(time_after_task_us - time_before_task_us); if (task_time_us > period_.count()) { diff --git a/system/common/repeating_timer.h b/system/common/repeating_timer.h index 6398af224b..7f004c31fc 100644 --- a/system/common/repeating_timer.h +++ b/system/common/repeating_timer.h @@ -23,6 +23,8 @@ #include <chrono> #include <future> +#include "time_util.h" + namespace bluetooth { namespace common { @@ -38,7 +40,9 @@ class MessageLoopThread; */ class RepeatingTimer final { public: - RepeatingTimer() : expected_time_next_task_us_(0) {} + RepeatingTimer(uint64_t (*clock_tick_us)(void) = + bluetooth::common::time_get_os_boottime_us) + : expected_time_next_task_us_(0), clock_tick_us_(clock_tick_us) {} RepeatingTimer(const RepeatingTimer&) = delete; RepeatingTimer& operator=(const RepeatingTimer&) = delete; @@ -83,7 +87,8 @@ class RepeatingTimer final { base::CancelableClosure task_wrapper_; base::RepeatingClosure task_; std::chrono::microseconds period_; - uint64_t expected_time_next_task_us_; // Using clock boot time in time_util.h + uint64_t expected_time_next_task_us_; + uint64_t (*clock_tick_us_)(void); mutable std::recursive_mutex api_mutex_; void CancelHelper(std::promise<void> promise); void CancelClosure(std::promise<void> promise); diff --git a/system/common/time_util.cc b/system/common/time_util.cc index d77c17c0c8..6799270ddf 100644 --- a/system/common/time_util.cc +++ b/system/common/time_util.cc @@ -16,15 +16,23 @@ * ******************************************************************************/ +#include "common/time_util.h" + #include <sys/time.h> #include <time.h> -#include "common/time_util.h" - namespace bluetooth { namespace common { +uint64_t time_get_audio_server_tick_us() { +#ifndef TARGET_FLOSS + return time_get_os_boottime_us(); +#else + return time_get_os_monotonic_raw_us(); +#endif +} + uint64_t time_get_os_boottime_ms() { return time_get_os_boottime_us() / 1000; } uint64_t time_get_os_boottime_us() { diff --git a/system/common/time_util.h b/system/common/time_util.h index 16808135c3..200c2bbd95 100644 --- a/system/common/time_util.h +++ b/system/common/time_util.h @@ -24,6 +24,10 @@ namespace bluetooth { namespace common { +// Get the time aligned to the clock domain of the audio server, in +// microseconds. +uint64_t time_get_audio_server_tick_us(); + // Get the OS boot time in milliseconds. uint64_t time_get_os_boottime_ms(); diff --git a/system/gd/Android.bp b/system/gd/Android.bp index 7fa3a5c1fe..6dee9b3f10 100644 --- a/system/gd/Android.bp +++ b/system/gd/Android.bp @@ -175,6 +175,7 @@ cc_defaults { "libbluetooth_crypto_toolbox", "libbluetooth_log", "libbluetooth_rust_interop", + "libbt-common", "libbt-platform-protos-lite", "libbt_shim_bridge", "libbt_shim_ffi", @@ -241,6 +242,7 @@ cc_library { ], static_libs: [ "libbluetooth-types", + "libbt-common", "libchrome", "libosi", ], @@ -262,6 +264,7 @@ cc_library { ], static_libs: [ "libbluetooth-types", + "libbt-common", "libchrome", "libosi", ], @@ -316,6 +319,7 @@ cc_binary { "libbluetooth_ras_pdl", "libbluetooth_rust_interop", "libbluetooth_smp_pdl", + "libbt-common", "libbt_shim_bridge", "libbt_shim_ffi", "libchrome", @@ -484,6 +488,7 @@ cc_test { "libbluetooth_ras_pdl", "libbluetooth_rust_interop", "libbluetooth_smp_pdl", + "libbt-common", "libbt-platform-protos-lite", "libbt_shim_bridge", "libbt_shim_ffi", @@ -632,6 +637,7 @@ cc_defaults { "libbluetooth_gd_fuzzing", "libbluetooth_log", "libbluetooth_rust_interop", + "libbt-common", "libbt_shim_bridge", "libbt_shim_ffi", "libchrome", diff --git a/system/gd/hal/link_clocker.cc b/system/gd/hal/link_clocker.cc index 830c90a4ab..a077f126f2 100644 --- a/system/gd/hal/link_clocker.cc +++ b/system/gd/hal/link_clocker.cc @@ -20,6 +20,8 @@ #include <algorithm> +#include "common/time_util.h" + namespace bluetooth::hal { static class : public ReadClockHandler { @@ -87,8 +89,7 @@ void LinkClocker::OnHciEvent(const HciPacket& packet) { // getting the local timestamp from the bound gd HCI event callback // adds jitter. - auto timestamp = std::chrono::system_clock::now().time_since_epoch(); - unsigned timestamp_us = std::chrono::duration_cast<std::chrono::microseconds>(timestamp).count(); + unsigned timestamp_us = bluetooth::common::time_get_audio_server_tick_us(); (*g_read_clock_handler).OnEvent(timestamp_us, bt_clock << 4); } |