Bluetooth: Protect callbacks during shutdown

- Hold the mutex during callbacks
- Disable power mode before deleting hci_

Bug: 36084266
Test: Switch users repeatedly (toggles Bluetooth)
Change-Id: I7e4d405e9028c3363c112a8b09c03b8aea652b7a
This commit is contained in:
Myles Watson 2017-03-09 10:39:31 -08:00
parent 691a455b9f
commit 9ef1f71982
2 changed files with 12 additions and 13 deletions

View file

@ -159,19 +159,13 @@ void AsyncFdWatcher::ThreadRoutine() {
} }
// Invoke the data ready callbacks if appropriate. // Invoke the data ready callbacks if appropriate.
std::vector<decltype(watched_fds_)::value_type> saved_callbacks;
{ {
// Hold the mutex to make sure that the callbacks are still valid.
std::unique_lock<std::mutex> guard(internal_mutex_); std::unique_lock<std::mutex> guard(internal_mutex_);
for (auto& it : watched_fds_) { for (auto& it : watched_fds_) {
if (FD_ISSET(it.first, &read_fds)) { if (FD_ISSET(it.first, &read_fds)) {
saved_callbacks.push_back(it);
}
}
}
for (auto& it : saved_callbacks) {
if (it.second) {
it.second(it.first); it.second(it.first);
}
} }
} }
} }

View file

@ -268,6 +268,16 @@ bool VendorInterface::Open(InitializeCompleteCallback initialize_complete_cb,
} }
void VendorInterface::Close() { void VendorInterface::Close() {
// These callbacks may send HCI events (vendor-dependent), so make sure to
// StopWatching the file descriptor after this.
if (lib_interface_ != nullptr) {
bt_vendor_lpm_mode_t mode = BT_VND_LPM_DISABLE;
lib_interface_->op(BT_VND_OP_LPM_SET_MODE, &mode);
int power_state = BT_VND_PWR_OFF;
lib_interface_->op(BT_VND_OP_POWER_CTRL, &power_state);
}
fd_watcher_.StopWatchingFileDescriptors(); fd_watcher_.StopWatchingFileDescriptors();
if (hci_ != nullptr) { if (hci_ != nullptr) {
@ -276,12 +286,7 @@ void VendorInterface::Close() {
} }
if (lib_interface_ != nullptr) { if (lib_interface_ != nullptr) {
bt_vendor_lpm_mode_t mode = BT_VND_LPM_DISABLE;
lib_interface_->op(BT_VND_OP_LPM_SET_MODE, &mode);
lib_interface_->op(BT_VND_OP_USERIAL_CLOSE, nullptr); lib_interface_->op(BT_VND_OP_USERIAL_CLOSE, nullptr);
int power_state = BT_VND_PWR_OFF;
lib_interface_->op(BT_VND_OP_POWER_CTRL, &power_state);
} }
if (lib_handle_ != nullptr) { if (lib_handle_ != nullptr) {