Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1e43219c authored by Jeremy Wu's avatar Jeremy Wu
Browse files

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
parent ba2e6728
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -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();
  }
+1 −6
Original line number Diff line number Diff line
@@ -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);

+5 −6
Original line number Diff line number Diff line
@@ -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()) {
+7 −2
Original line number Diff line number Diff line
@@ -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);
+10 −2
Original line number Diff line number Diff line
@@ -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() {
Loading