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

Commit fc1705d9 authored by Pavlin Radoslavov's avatar Pavlin Radoslavov
Browse files

Gracefully handle A2DP hardware offload Audio HAL service death

Register for Audio HAL service death, and restart the Audio HAL session
if necessary.

Bug: 77926419
Test: Manual: stream Bluetooth audio and kill -9 the audioserver
Change-Id: I45e83aea0fb95301e6ceadee74661dd55f8c0f66
Merged-In: I45e83aea0fb95301e6ceadee74661dd55f8c0f66
(cherry picked from commit 5c80c8653a61780f8047413d5ad9f939a8a397f3)
parent 4401b5e5
Loading
Loading
Loading
Loading
+3 −0
Original line number Original line Diff line number Diff line
@@ -121,6 +121,7 @@ cc_test {
    header_libs: ["libbluetooth_headers"],
    header_libs: ["libbluetooth_headers"],
    shared_libs: [
    shared_libs: [
        "libaudioclient",
        "libaudioclient",
        "android.hardware.bluetooth.a2dp@1.0",
        "libhidlbase",
        "libhidlbase",
        "liblog",
        "liblog",
        "libprotobuf-cpp-lite",
        "libprotobuf-cpp-lite",
@@ -132,7 +133,9 @@ cc_test {
        "libbtcore",
        "libbtcore",
        "libbt-stack",
        "libbt-stack",
        "libbt-sbc-encoder",
        "libbt-sbc-encoder",
        "libbt-utils",
        "libFraunhoferAAC",
        "libFraunhoferAAC",
        "libg722codec",
        "libbtdevice",
        "libbtdevice",
        "libbt-hci",
        "libbt-hci",
        "libudrv-uipc",
        "libudrv-uipc",
+43 −0
Original line number Original line Diff line number Diff line
@@ -50,8 +50,10 @@ using android::hardware::bluetooth::a2dp::V1_0::ChannelMode;
using android::hardware::ProcessState;
using android::hardware::ProcessState;
using ::android::hardware::Return;
using ::android::hardware::Return;
using ::android::hardware::Void;
using ::android::hardware::Void;
using ::android::hardware::hidl_death_recipient;
using ::android::hardware::hidl_vec;
using ::android::hardware::hidl_vec;
using ::android::sp;
using ::android::sp;
using ::android::wp;
android::sp<IBluetoothAudioOffload> btAudio;
android::sp<IBluetoothAudioOffload> btAudio;


#define CASE_RETURN_STR(const) \
#define CASE_RETURN_STR(const) \
@@ -65,6 +67,7 @@ static void btif_a2dp_audio_send_start_req();
static void btif_a2dp_audio_send_suspend_req();
static void btif_a2dp_audio_send_suspend_req();
static void btif_a2dp_audio_interface_init();
static void btif_a2dp_audio_interface_init();
static void btif_a2dp_audio_interface_deinit();
static void btif_a2dp_audio_interface_deinit();
static void btif_a2dp_audio_interface_restart_session();
// Delay reporting
// Delay reporting
// static void btif_a2dp_audio_send_sink_latency();
// static void btif_a2dp_audio_send_sink_latency();


@@ -91,6 +94,20 @@ class BluetoothAudioHost : public IBluetoothAudioHost {
      }*/
      }*/
};
};


class BluetoothAudioDeathRecipient : public hidl_death_recipient {
 public:
  virtual void serviceDied(
      uint64_t /*cookie*/,
      const wp<::android::hidl::base::V1_0::IBase>& /*who*/) {
    LOG_ERROR(LOG_TAG, "%s", __func__);
    // Restart the session on the correct thread
    do_in_bta_thread(FROM_HERE,
                     base::Bind(&btif_a2dp_audio_interface_restart_session));
  }
};
sp<BluetoothAudioDeathRecipient> bluetoothAudioDeathRecipient =
    new BluetoothAudioDeathRecipient();

static Status mapToStatus(uint8_t resp) {
static Status mapToStatus(uint8_t resp) {
  switch (resp) {
  switch (resp) {
    case A2DP_CTRL_ACK_SUCCESS:
    case A2DP_CTRL_ACK_SUCCESS:
@@ -190,6 +207,12 @@ static void btif_a2dp_audio_interface_init() {
  btAudio = IBluetoothAudioOffload::getService();
  btAudio = IBluetoothAudioOffload::getService();
  CHECK(btAudio != nullptr);
  CHECK(btAudio != nullptr);


  auto death_link = btAudio->linkToDeath(bluetoothAudioDeathRecipient, 0);
  if (!death_link.isOk()) {
    LOG_ERROR(LOG_TAG, "%s: Cannot observe the Bluetooth Audio HAL's death",
              __func__);
  }

  LOG_DEBUG(
  LOG_DEBUG(
      LOG_TAG, "%s: IBluetoothAudioOffload::getService() returned %p (%s)",
      LOG_TAG, "%s: IBluetoothAudioOffload::getService() returned %p (%s)",
      __func__, btAudio.get(), (btAudio->isRemote() ? "remote" : "local"));
      __func__, btAudio.get(), (btAudio->isRemote() ? "remote" : "local"));
@@ -199,6 +222,14 @@ static void btif_a2dp_audio_interface_init() {


static void btif_a2dp_audio_interface_deinit() {
static void btif_a2dp_audio_interface_deinit() {
  LOG_INFO(LOG_TAG, "%s: start", __func__);
  LOG_INFO(LOG_TAG, "%s: start", __func__);
  if (btAudio != nullptr) {
    auto death_unlink = btAudio->unlinkToDeath(bluetoothAudioDeathRecipient);
    if (!death_unlink.isOk()) {
      LOG_ERROR(LOG_TAG,
                "%s: Error unlinking death observer from Bluetooth Audio HAL",
                __func__);
    }
  }
  btAudio = nullptr;
  btAudio = nullptr;
}
}


@@ -222,6 +253,18 @@ void btif_a2dp_audio_interface_end_session() {
  btif_a2dp_audio_interface_deinit();
  btif_a2dp_audio_interface_deinit();
}
}


// Conditionally restart the session only if it was started before
static void btif_a2dp_audio_interface_restart_session() {
  LOG_INFO(LOG_TAG, "%s", __func__);
  if (btAudio == nullptr) {
    LOG_INFO(LOG_TAG, "%s: nothing to restart - session was not started",
             __func__);
    return;
  }
  btAudio = nullptr;
  btif_a2dp_audio_interface_start_session();
}

void btif_a2dp_audio_on_started(tBTA_AV_STATUS status) {
void btif_a2dp_audio_on_started(tBTA_AV_STATUS status) {
  LOG_INFO(LOG_TAG, "%s: status = %d", __func__, status);
  LOG_INFO(LOG_TAG, "%s: status = %d", __func__, status);
  if (btAudio != nullptr) {
  if (btAudio != nullptr) {