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

Commit e0ca935c authored by Ugo Yu's avatar Ugo Yu
Browse files

Add timer to detect HwBinder thread stuck

Abort Bluetooth process when the HwBinder thread takes
too long to finish its tasks. The timer is on both audio
HAL and hci HAL since they are sharing the same HwBinder
thread.

Bug: 144592765
Test: Manual
Change-Id: I8bb84cd460ecebda47c49bb3299c93e7f0f2d4ef
parent 7d6b5ace
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -51,6 +51,7 @@ cc_test {
    static_libs: [
        "libbt-audio-hal-interface",
        "libbt-common",
        "libbt-stack",
    ],
    cflags: [
        "-DBUILDCFG",
+16 −0
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@
#include <hidl/ServiceManagement.h>
#include <future>

#include "btu.h"
#include "osi/include/log.h"

namespace bluetooth {
@@ -74,6 +75,8 @@ class BluetoothAudioPortImpl : public IBluetoothAudioPort {
      : sink_(sink), provider_(provider){};

  Return<void> startStream() override {
    main_thread_hwbinder_timer_start(
        FROM_HERE_WITH_EXPLICIT_FUNCTION(__func__));
    BluetoothAudioCtrlAck ack = sink_->StartRequest();
    if (ack != BluetoothAudioCtrlAck::PENDING) {
      auto hidl_retval =
@@ -82,10 +85,13 @@ class BluetoothAudioPortImpl : public IBluetoothAudioPort {
        LOG(ERROR) << __func__ << ": BluetoothAudioHal failure: " << hidl_retval.description();
      }
    }
    main_thread_hwbinder_timer_stop();
    return Void();
  }

  Return<void> suspendStream() override {
    main_thread_hwbinder_timer_start(
        FROM_HERE_WITH_EXPLICIT_FUNCTION(__func__));
    BluetoothAudioCtrlAck ack = sink_->SuspendRequest();
    if (ack != BluetoothAudioCtrlAck::PENDING) {
      auto hidl_retval =
@@ -94,16 +100,22 @@ class BluetoothAudioPortImpl : public IBluetoothAudioPort {
        LOG(ERROR) << __func__ << ": BluetoothAudioHal failure: " << hidl_retval.description();
      }
    }
    main_thread_hwbinder_timer_stop();
    return Void();
  }

  Return<void> stopStream() override {
    main_thread_hwbinder_timer_start(
        FROM_HERE_WITH_EXPLICIT_FUNCTION(__func__));
    sink_->StopRequest();
    main_thread_hwbinder_timer_stop();
    return Void();
  }

  Return<void> getPresentationPosition(
      getPresentationPosition_cb _hidl_cb) override {
    main_thread_hwbinder_timer_start(
        FROM_HERE_WITH_EXPLICIT_FUNCTION(__func__));
    uint64_t remote_delay_report_ns;
    uint64_t total_bytes_read;
    timespec data_position;
@@ -126,10 +138,13 @@ class BluetoothAudioPortImpl : public IBluetoothAudioPort {
                     : BluetoothAudioStatus::FAILURE),
             remote_delay_report_ns, total_bytes_read,
             transmittedOctetsTimeStamp);
    main_thread_hwbinder_timer_stop();
    return Void();
  }

  Return<void> updateMetadata(const SourceMetadata& sourceMetadata) override {
    main_thread_hwbinder_timer_start(
        FROM_HERE_WITH_EXPLICIT_FUNCTION(__func__));
    LOG(INFO) << __func__ << ": " << sourceMetadata.tracks.size()
              << " track(s)";
    // refer to StreamOut.impl.h within Audio HAL (AUDIO_HAL_VERSION_5_0)
@@ -146,6 +161,7 @@ class BluetoothAudioPortImpl : public IBluetoothAudioPort {
    const source_metadata_t source_metadata = {
        .track_count = metadata_vec.size(), .tracks = metadata_vec.data()};
    sink_->MetadataChanged(source_metadata);
    main_thread_hwbinder_timer_stop();
    return Void();
  }

+15 −0
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@

#include <base/location.h>
#include <base/logging.h>
#include "btu.h"
#include "buffer_allocator.h"
#include "osi/include/log.h"

@@ -88,32 +89,46 @@ class BluetoothHciCallbacks : public V1_1::IBluetoothHciCallbacks {
  }

  Return<void> initializationComplete(Status status) override {
    // Do not fire the hwbinder timer here because the main thread is blocked
    // before the initialization is completed.
    CHECK(status == Status::SUCCESS);
    initialization_complete();
    return Void();
  }

  Return<void> hciEventReceived(const hidl_vec<uint8_t>& event) override {
    main_thread_hwbinder_timer_start(
        FROM_HERE_WITH_EXPLICIT_FUNCTION(__func__));
    BT_HDR* packet = WrapPacketAndCopy(MSG_HC_TO_STACK_HCI_EVT, event);
    hci_event_received(FROM_HERE, packet);
    main_thread_hwbinder_timer_stop();
    return Void();
  }

  Return<void> aclDataReceived(const hidl_vec<uint8_t>& data) override {
    main_thread_hwbinder_timer_start(
        FROM_HERE_WITH_EXPLICIT_FUNCTION(__func__));
    BT_HDR* packet = WrapPacketAndCopy(MSG_HC_TO_STACK_HCI_ACL, data);
    acl_event_received(packet);
    main_thread_hwbinder_timer_stop();
    return Void();
  }

  Return<void> scoDataReceived(const hidl_vec<uint8_t>& data) override {
    main_thread_hwbinder_timer_start(
        FROM_HERE_WITH_EXPLICIT_FUNCTION(__func__));
    BT_HDR* packet = WrapPacketAndCopy(MSG_HC_TO_STACK_HCI_SCO, data);
    sco_data_received(packet);
    main_thread_hwbinder_timer_stop();
    return Void();
  }

  Return<void> isoDataReceived(const hidl_vec<uint8_t>& data) override {
    main_thread_hwbinder_timer_start(
        FROM_HERE_WITH_EXPLICIT_FUNCTION(__func__));
    BT_HDR* packet = WrapPacketAndCopy(MSG_HC_TO_STACK_HCI_ISO, data);
    iso_data_received(packet);
    main_thread_hwbinder_timer_stop();
    return Void();
  }

+30 −0
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@
#include "bte.h"
#include "btif/include/btif_common.h"
#include "common/message_loop_thread.h"
#include "common/once_timer.h"
#include "osi/include/osi.h"
#include "stack/btm/btm_int.h"
#include "stack/include/btu.h"
@@ -38,12 +39,18 @@
#include <base/run_loop.h>
#include <base/threading/thread.h>

#ifndef HWBINDER_TIMEOUT_MS
#define HWBINDER_TIMEOUT_MS 500
#endif

using bluetooth::common::MessageLoopThread;
using bluetooth::common::OnceTimer;

/* Define BTU storage area */
uint8_t btu_trace_level = HCI_INITIAL_TRACE_LEVEL;

static MessageLoopThread main_thread("bt_main_thread");
static OnceTimer hwbinder_timer;

void btu_hci_msg_process(BT_HDR* p_msg) {
  /* Determine the input message type. */
@@ -97,6 +104,29 @@ bt_status_t do_in_main_thread(const base::Location& from_here,
  return BT_STATUS_SUCCESS;
}

void hwbinder_timeout(const base::Location& from_here) {
  LOG(FATAL) << "HwBinder thread timeout at " << from_here.ToString();
}

void main_thread_hwbinder_timer_start(const base::Location& from_here) {
  if (hwbinder_timer.IsScheduled()) {
    LOG(FATAL) << __func__ << ": hwbinder_timer is already scheduled!";
  }
  if (!hwbinder_timer.Schedule(
          main_thread.GetWeakPtr(), from_here,
          base::Bind(&hwbinder_timeout, from_here),
          base::TimeDelta::FromMilliseconds(HWBINDER_TIMEOUT_MS))) {
    LOG(FATAL) << __func__ << ": failed from " << from_here.ToString();
  }
}

void main_thread_hwbinder_timer_stop() {
  if (!hwbinder_timer.IsScheduled()) {
    LOG(FATAL) << __func__ << ": hwbinder_timer is not scheduled!";
  }
  hwbinder_timer.CancelAndWait();
}

void btu_task_start_up(UNUSED_ATTR void* context) {
  LOG(INFO) << "Bluetooth chip preload is complete";

+2 −0
Original line number Diff line number Diff line
@@ -62,6 +62,8 @@ bluetooth::common::MessageLoopThread* get_main_thread();
base::MessageLoop* get_main_message_loop();
bt_status_t do_in_main_thread(const base::Location& from_here,
                              base::OnceClosure task);
void main_thread_hwbinder_timer_start(const base::Location& from_here);
void main_thread_hwbinder_timer_stop();

void BTU_StartUp(void);
void BTU_ShutDown(void);