DO NOT MERGE: Use a weak pointer to deliver updates to AVRCP devices.
If a device disconnects right before a update message gets queued, the
device becomes null and there is a crash when the callback for the
update executes on the disconnected device. This patch switches the
device reference from being Unretained to using a weak pointer so that
the callback just doesn't execute if the device is disconnected.
Bug: 120431125
Bug: 120445479
Test: Use the same test as b/120477414 as that bug causes a disconnect
at the same time as a media update.
Change-Id: I1dcc08e5c9866106e7ec0dad52505e34b42da600
diff --git a/system/btif/avrcp/avrcp_service.cc b/system/btif/avrcp/avrcp_service.cc
index 8c22365..5a058f4 100644
--- a/system/btif/avrcp/avrcp_service.cc
+++ b/system/btif/avrcp/avrcp_service.cc
@@ -346,10 +346,11 @@
// This function may be called on any thread, we need to make sure that the
// device update happens on the main thread.
- for (auto device : instance_->connection_handler_->GetListOfDevices()) {
- do_in_bta_thread(FROM_HERE, base::Bind(&Device::SendMediaUpdate,
- base::Unretained(device.get()),
- track_changed, play_state, queue));
+ for (const auto& device :
+ instance_->connection_handler_->GetListOfDevices()) {
+ do_in_bta_thread(FROM_HERE,
+ base::Bind(&Device::SendMediaUpdate, device.get()->Get(),
+ track_changed, play_state, queue));
}
}
@@ -361,11 +362,11 @@
<< " uids=" << uids;
// Ensure that the update is posted to the correct thread
- for (auto device : instance_->connection_handler_->GetListOfDevices()) {
- do_in_bta_thread(
- FROM_HERE,
- base::Bind(&Device::SendFolderUpdate, base::Unretained(device.get()),
- available_players, addressed_players, uids));
+ for (const auto& device :
+ instance_->connection_handler_->GetListOfDevices()) {
+ do_in_bta_thread(FROM_HERE,
+ base::Bind(&Device::SendFolderUpdate, device.get()->Get(),
+ available_players, addressed_players, uids));
}
}
diff --git a/system/profile/avrcp/device.cc b/system/profile/avrcp/device.cc
index 9b25fac..7f8ecae 100644
--- a/system/profile/avrcp/device.cc
+++ b/system/profile/avrcp/device.cc
@@ -52,6 +52,8 @@
volume_interface_ = volume_interface;
}
+base::WeakPtr<Device> Device::Get() { return weak_ptr_factory_.GetWeakPtr(); }
+
bool Device::IsActive() const {
return address_ == a2dp_interface_->active_peer();
}
diff --git a/system/profile/avrcp/device.h b/system/profile/avrcp/device.h
index 5ef886d..b1f3420 100644
--- a/system/profile/avrcp/device.h
+++ b/system/profile/avrcp/device.h
@@ -55,6 +55,12 @@
uint16_t ctrl_mtu, uint16_t browse_mtu);
virtual ~Device() = default;
+ /**
+ * Gets a weak pointer to this device that is invalidated when the device is
+ * disconnected.
+ */
+ base::WeakPtr<Device> Get();
+
const RawAddress& GetAddress() const { return address_; };
/**