summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Jeremy Wu <jrwu@google.com> 2024-04-07 12:24:01 +0000
committer Jeremy Wu <jrwu@google.com> 2024-05-08 09:29:57 +0000
commit1e43219cd13a46c2f6636e6c9707cea1970a7038 (patch)
tree35ff03f010fbc3426404845ae3ebb1c02e943892
parentba2e67285bf8d6e30fc779ae82f4bca606241ca8 (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.cc5
-rw-r--r--system/btif/src/btif_a2dp_source.cc7
-rw-r--r--system/common/repeating_timer.cc11
-rw-r--r--system/common/repeating_timer.h9
-rw-r--r--system/common/time_util.cc12
-rw-r--r--system/common/time_util.h4
-rw-r--r--system/gd/Android.bp6
-rw-r--r--system/gd/hal/link_clocker.cc5
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);
}