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)
diff --git a/btif/Android.bp b/btif/Android.bp
index f9177a7..4b2dc30 100644
--- a/btif/Android.bp
+++ b/btif/Android.bp
@@ -121,6 +121,7 @@
header_libs: ["libbluetooth_headers"],
shared_libs: [
"libaudioclient",
+ "android.hardware.bluetooth.a2dp@1.0",
"libhidlbase",
"liblog",
"libprotobuf-cpp-lite",
@@ -132,7 +133,9 @@
"libbtcore",
"libbt-stack",
"libbt-sbc-encoder",
+ "libbt-utils",
"libFraunhoferAAC",
+ "libg722codec",
"libbtdevice",
"libbt-hci",
"libudrv-uipc",
diff --git a/btif/src/btif_a2dp_audio_interface.cc b/btif/src/btif_a2dp_audio_interface.cc
index 56adb9b..b74dca7 100644
--- a/btif/src/btif_a2dp_audio_interface.cc
+++ b/btif/src/btif_a2dp_audio_interface.cc
@@ -50,8 +50,10 @@
using android::hardware::ProcessState;
using ::android::hardware::Return;
using ::android::hardware::Void;
+using ::android::hardware::hidl_death_recipient;
using ::android::hardware::hidl_vec;
using ::android::sp;
+using ::android::wp;
android::sp<IBluetoothAudioOffload> btAudio;
#define CASE_RETURN_STR(const) \
@@ -65,6 +67,7 @@
static void btif_a2dp_audio_send_suspend_req();
static void btif_a2dp_audio_interface_init();
static void btif_a2dp_audio_interface_deinit();
+static void btif_a2dp_audio_interface_restart_session();
// Delay reporting
// static void btif_a2dp_audio_send_sink_latency();
@@ -91,6 +94,20 @@
}*/
};
+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) {
switch (resp) {
case A2DP_CTRL_ACK_SUCCESS:
@@ -190,6 +207,12 @@
btAudio = IBluetoothAudioOffload::getService();
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_TAG, "%s: IBluetoothAudioOffload::getService() returned %p (%s)",
__func__, btAudio.get(), (btAudio->isRemote() ? "remote" : "local"));
@@ -199,6 +222,14 @@
static void btif_a2dp_audio_interface_deinit() {
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;
}
@@ -222,6 +253,18 @@
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) {
LOG_INFO(LOG_TAG, "%s: status = %d", __func__, status);
if (btAudio != nullptr) {