From 0d05883b7675bbb783297040291fff158cab1a83 Mon Sep 17 00:00:00 2001 From: Guogang Li Date: Wed, 11 Dec 2024 13:05:07 -0800 Subject: [PATCH] Internal refactor PiperOrigin-RevId: 705210963 --- .../windows/bluetooth_classic_medium.cc | 494 ++++++++++-------- .../windows/bluetooth_classic_medium.h | 25 +- 2 files changed, 297 insertions(+), 222 deletions(-) diff --git a/internal/platform/implementation/windows/bluetooth_classic_medium.cc b/internal/platform/implementation/windows/bluetooth_classic_medium.cc index 8fff2eb7..5b9434f5 100644 --- a/internal/platform/implementation/windows/bluetooth_classic_medium.cc +++ b/internal/platform/implementation/windows/bluetooth_classic_medium.cc @@ -16,25 +16,21 @@ #include -#include #include #include -#include -#include #include #include // NOLINT #include #include +#include "absl/synchronization/mutex.h" #include "internal/platform/cancellation_flag.h" #include "internal/platform/cancellation_flag_listener.h" -#include "internal/platform/exception.h" #include "internal/platform/feature_flags.h" #include "internal/platform/implementation/bluetooth_adapter.h" #include "internal/platform/implementation/bluetooth_classic.h" #include "internal/platform/implementation/windows/bluetooth_adapter.h" #include "internal/platform/implementation/windows/bluetooth_classic_device.h" -#include "internal/platform/implementation/windows/bluetooth_classic_server_socket.h" #include "internal/platform/implementation/windows/bluetooth_classic_socket.h" #include "internal/platform/implementation/windows/bluetooth_pairing.h" #include "internal/platform/implementation/windows/generated/winrt/Windows.Devices.Bluetooth.Rfcomm.h" @@ -119,57 +115,6 @@ BluetoothClassicMedium::BluetoothClassicMedium( BluetoothClassicMedium::~BluetoothClassicMedium() {} -void BluetoothClassicMedium::OnScanModeChanged( - BluetoothAdapter::ScanMode scan_mode) { - LOG(INFO) << __func__ << ": OnScanModeChanged is called with scanMode: " - << static_cast(scan_mode); - - if (scan_mode == scan_mode_) { - LOG(INFO) << __func__ << ": No change of scan mode."; - return; - } - - scan_mode_ = scan_mode; - bool radio_discoverable = - scan_mode_ == BluetoothAdapter::ScanMode::kConnectableDiscoverable; - - if (bluetooth_adapter_.GetName().size() > - kAndroidDiscoverableBluetoothNameMaxLength) { - // If the name longer than the android limitation, always set the value to - // false. - radio_discoverable = false; - } - - if (is_radio_discoverable_ == radio_discoverable) { - LOG(INFO) << __func__ << ": No change of radio discovery."; - return; - } - - if (rfcomm_provider_ == nullptr) { - LOG(WARNING) << __func__ << ": No advertising."; - return; - } - - try { - rfcomm_provider_.StopAdvertising(); - rfcomm_provider_.StartAdvertising( - raw_server_socket_->stream_socket_listener(), radio_discoverable); - is_radio_discoverable_ = radio_discoverable; - return; - } catch (std::exception exception) { - LOG(ERROR) << __func__ - << ": OnScanModeChanged exception: " << exception.what(); - return; - } catch (const winrt::hresult_error& ex) { - LOG(ERROR) << __func__ << ": OnScanModeChanged exception: " << ex.code() - << ": " << winrt::to_string(ex.message()); - return; - } catch (...) { - LOG(ERROR) << __func__ << ": Unknown exception."; - return; - } -} - bool BluetoothClassicMedium::StartDiscovery( BluetoothClassicMedium::DiscoveryCallback discovery_callback) { LOG(INFO) << "StartDiscovery is called."; @@ -197,53 +142,6 @@ bool BluetoothClassicMedium::StopDiscovery() { return result; } -void BluetoothClassicMedium::InitializeDeviceWatcher() { - try { - // create watcher - const winrt::param::iterable requested_properties = - winrt::single_threaded_vector( - {winrt::to_hstring("System.Devices.Aep.IsPresent"), - winrt::to_hstring("System.Devices.Aep.DeviceAddress")}); - - device_watcher_ = DeviceInformation::CreateWatcher( - kBluetoothSelector, // aqsFilter - requested_properties, // additionalProperties - DeviceInformationKind::AssociationEndpoint); // kind - - // An app must subscribe to all of the added, removed, and updated events - // to be notified when there are device additions, removals or updates. If - // an app handles only the added event, it will not receive an update if a - // device is added to the system after the initial device enumeration - // completes. register event handlers before starting the watcher - - // Event that is raised when a device is added to the collection enumerated - // by the DeviceWatcher. - // https://docs.microsoft.com/en-us/uwp/api/windows.devices.enumeration.devicewatcher.added?view=winrt-20348 - device_watcher_.Added({this, &BluetoothClassicMedium::DeviceWatcher_Added}); - - // Event that is raised when a device is updated in the collection of - // enumerated devices. - // https://docs.microsoft.com/en-us/uwp/api/windows.devices.enumeration.devicewatcher.updated?view=winrt-20348 - device_watcher_.Updated( - {this, &BluetoothClassicMedium::DeviceWatcher_Updated}); - - // Event that is raised when a device is removed from the collection of - // enumerated devices. - // https://docs.microsoft.com/en-us/uwp/api/windows.devices.enumeration.devicewatcher.removed?view=winrt-20348 - device_watcher_.Removed( - {this, &BluetoothClassicMedium::DeviceWatcher_Removed}); - } catch (std::exception exception) { - LOG(ERROR) << __func__ - << ": InitializeDeviceWatcher exception: " << exception.what(); - } catch (const winrt::hresult_error& ex) { - LOG(ERROR) << __func__ - << ": InitializeDeviceWatcher exception: " << ex.code() << ": " - << winrt::to_string(ex.message()); - } catch (...) { - LOG(ERROR) << __func__ << ": Unknown exception."; - } -} - std::unique_ptr BluetoothClassicMedium::ConnectToService( api::BluetoothDevice& remote_device, const std::string& service_uuid, CancellationFlag* cancellation_flag) { @@ -273,8 +171,8 @@ std::unique_ptr BluetoothClassicMedium::ConnectToService( return nullptr; } - auto remote_device_to_connect_ = dynamic_cast( - GetRemoteDevice(remote_device.GetMacAddress())); + BluetoothDevice* remote_device_to_connect_ = + GetRemoteDeviceInternal(remote_device.GetMacAddress()); if (remote_device_to_connect_ == nullptr || remote_device_to_connect_->GetId().empty()) { @@ -341,6 +239,55 @@ std::unique_ptr BluetoothClassicMedium::ConnectToService( } } +// https://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html#listenUsingInsecureRfcommWithServiceRecord +// +// service_uuid is the canonical textual representation +// (https://en.wikipedia.org/wiki/Universally_unique_identifier#Format) of a +// type 3 name-based +// (https://en.wikipedia.org/wiki/Universally_unique_identifier#Versions_3_and_5_(namespace_name-based)) +// UUID. +// +// Returns nullptr error. +std::unique_ptr +BluetoothClassicMedium::ListenForService(const std::string& service_name, + const std::string& service_uuid) { + LOG(INFO) << "ListenForService is called with service name: " << service_name + << "."; + if (service_uuid.empty()) { + LOG(ERROR) << __func__ << ": service_uuid was empty."; + return nullptr; + } + + if (service_name.empty()) { + LOG(ERROR) << __func__ << ": service_name was empty."; + return nullptr; + } + + service_name_ = service_name; + service_uuid_ = service_uuid; + + scan_mode_ = bluetooth_adapter_.GetScanMode(); + + LOG(INFO) << __func__ << ": scan_mode: " << static_cast(scan_mode_); + bool radio_discoverable = + scan_mode_ == BluetoothAdapter::ScanMode::kConnectableDiscoverable; + + bool result = StartAdvertising(radio_discoverable); + + if (!result) { + LOG(ERROR) << __func__ << ": Failed to start listening."; + return nullptr; + } + + return std::move(server_socket_); +} + +api::BluetoothDevice* BluetoothClassicMedium::GetRemoteDevice( + const std::string& mac_address) { + LOG(INFO) << "GetRemoteDevice is called with mac_address: " << mac_address; + return GetRemoteDeviceInternal(mac_address); +} + std::unique_ptr BluetoothClassicMedium::CreatePairing( api::BluetoothDevice& remote_device) { VLOG(1) << __func__ << ": Start to createPairing with device: " @@ -371,6 +318,104 @@ std::unique_ptr BluetoothClassicMedium::CreatePairing( return nullptr; } +void BluetoothClassicMedium::InitializeDeviceWatcher() { + try { + // create watcher + const winrt::param::iterable requested_properties = + winrt::single_threaded_vector( + {winrt::to_hstring("System.Devices.Aep.IsPresent"), + winrt::to_hstring("System.Devices.Aep.DeviceAddress")}); + + device_watcher_ = DeviceInformation::CreateWatcher( + kBluetoothSelector, // aqsFilter + requested_properties, // additionalProperties + DeviceInformationKind::AssociationEndpoint); // kind + + // An app must subscribe to all of the added, removed, and updated events + // to be notified when there are device additions, removals or updates. If + // an app handles only the added event, it will not receive an update if a + // device is added to the system after the initial device enumeration + // completes. register event handlers before starting the watcher + + // Event that is raised when a device is added to the collection enumerated + // by the DeviceWatcher. + // https://docs.microsoft.com/en-us/uwp/api/windows.devices.enumeration.devicewatcher.added?view=winrt-20348 + device_watcher_.Added({this, &BluetoothClassicMedium::DeviceWatcher_Added}); + + // Event that is raised when a device is updated in the collection of + // enumerated devices. + // https://docs.microsoft.com/en-us/uwp/api/windows.devices.enumeration.devicewatcher.updated?view=winrt-20348 + device_watcher_.Updated( + {this, &BluetoothClassicMedium::DeviceWatcher_Updated}); + + // Event that is raised when a device is removed from the collection of + // enumerated devices. + // https://docs.microsoft.com/en-us/uwp/api/windows.devices.enumeration.devicewatcher.removed?view=winrt-20348 + device_watcher_.Removed( + {this, &BluetoothClassicMedium::DeviceWatcher_Removed}); + } catch (std::exception exception) { + LOG(ERROR) << __func__ + << ": InitializeDeviceWatcher exception: " << exception.what(); + } catch (const winrt::hresult_error& ex) { + LOG(ERROR) << __func__ + << ": InitializeDeviceWatcher exception: " << ex.code() << ": " + << winrt::to_string(ex.message()); + } catch (...) { + LOG(ERROR) << __func__ << ": Unknown exception."; + } +} + +void BluetoothClassicMedium::OnScanModeChanged( + BluetoothAdapter::ScanMode scan_mode) { + LOG(INFO) << __func__ << ": OnScanModeChanged is called with scanMode: " + << static_cast(scan_mode); + + if (scan_mode == scan_mode_) { + LOG(INFO) << __func__ << ": No change of scan mode."; + return; + } + + scan_mode_ = scan_mode; + bool radio_discoverable = + scan_mode_ == BluetoothAdapter::ScanMode::kConnectableDiscoverable; + + if (bluetooth_adapter_.GetName().size() > + kAndroidDiscoverableBluetoothNameMaxLength) { + // If the name longer than the android limitation, always set the value to + // false. + radio_discoverable = false; + } + + if (is_radio_discoverable_ == radio_discoverable) { + LOG(INFO) << __func__ << ": No change of radio discovery."; + return; + } + + if (rfcomm_provider_ == nullptr) { + LOG(WARNING) << __func__ << ": No advertising."; + return; + } + + try { + rfcomm_provider_.StopAdvertising(); + rfcomm_provider_.StartAdvertising( + raw_server_socket_->stream_socket_listener(), radio_discoverable); + is_radio_discoverable_ = radio_discoverable; + return; + } catch (std::exception exception) { + LOG(ERROR) << __func__ + << ": OnScanModeChanged exception: " << exception.what(); + return; + } catch (const winrt::hresult_error& ex) { + LOG(ERROR) << __func__ << ": OnScanModeChanged exception: " << ex.code() + << ": " << winrt::to_string(ex.message()); + return; + } catch (...) { + LOG(ERROR) << __func__ << ": Unknown exception."; + return; + } +} + bool BluetoothClassicMedium::HaveAccess(winrt::hstring device_id) { if (device_id.empty()) { return false; @@ -438,72 +483,74 @@ bool BluetoothClassicMedium::CheckSdp(RfcommDeviceService requested_service) { } } -// https://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html#listenUsingInsecureRfcommWithServiceRecord -// -// service_uuid is the canonical textual representation -// (https://en.wikipedia.org/wiki/Universally_unique_identifier#Format) of a -// type 3 name-based -// (https://en.wikipedia.org/wiki/Universally_unique_identifier#Versions_3_and_5_(namespace_name-based)) -// UUID. -// -// Returns nullptr error. -std::unique_ptr -BluetoothClassicMedium::ListenForService(const std::string& service_name, - const std::string& service_uuid) { - LOG(INFO) << "ListenForService is called with service name: " << service_name - << "."; - if (service_uuid.empty()) { - LOG(ERROR) << __func__ << ": service_uuid was empty."; - return nullptr; +bool BluetoothClassicMedium::HasRemoteDevice(const std::string& mac_address) { + absl::MutexLock lock(&devices_map_mutex_); + if (IsWatcherStarted()) { + return mac_address_to_bluetooth_device_map_.contains(mac_address); + } else { + return cached_bluetooth_devices_map_.contains(mac_address); } - - if (service_name.empty()) { - LOG(ERROR) << __func__ << ": service_name was empty."; - return nullptr; - } - - service_name_ = service_name; - service_uuid_ = service_uuid; - - scan_mode_ = bluetooth_adapter_.GetScanMode(); - - LOG(INFO) << __func__ << ": scan_mode: " << static_cast(scan_mode_); - bool radio_discoverable = - scan_mode_ == BluetoothAdapter::ScanMode::kConnectableDiscoverable; - - bool result = StartAdvertising(radio_discoverable); - - if (!result) { - LOG(ERROR) << __func__ << ": Failed to start listening."; - return nullptr; - } - - return std::move(server_socket_); } -api::BluetoothDevice* BluetoothClassicMedium::GetRemoteDevice( +bool BluetoothClassicMedium::RemoveRemoteDevice( const std::string& mac_address) { + absl::MutexLock lock(&devices_map_mutex_); + auto it = mac_address_to_bluetooth_device_map_.find(mac_address); - - if (it == mac_address_to_bluetooth_device_map_.end()) { - LOG(WARNING) << __func__ << ": Bluetooth device " << mac_address - << " is not in list. create it"; - auto bluetooth_device = std::make_unique(mac_address); - - if (IsWatcherStarted()) { - mac_address_to_bluetooth_device_map_[mac_address] = - std::move(bluetooth_device); - return mac_address_to_bluetooth_device_map_[mac_address].get(); - } else { - cached_bluetooth_devices_map_[mac_address] = std::move(bluetooth_device); - return cached_bluetooth_devices_map_[mac_address].get(); - } + if (it != mac_address_to_bluetooth_device_map_.end()) { + auto node = mac_address_to_bluetooth_device_map_.extract(mac_address); + removed_bluetooth_devices_map_[mac_address] = std::move(node.mapped()); + return true; } - LOG(INFO) << __func__ << ": Bluetooth device " << mac_address - << " is in cache"; + return false; +} - return it->second.get(); +bool BluetoothClassicMedium::AssignRemoteDevice( + const std::string& mac_address, std::unique_ptr device) { + absl::MutexLock lock(&devices_map_mutex_); + auto result = mac_address_to_bluetooth_device_map_.insert_or_assign( + mac_address, std::move(device)); + return result.second; +} + +BluetoothDevice* BluetoothClassicMedium::GetRemoteDeviceInternal( + const std::string& mac_address) { + absl::MutexLock lock(&devices_map_mutex_); + if (IsWatcherStarted()) { + auto it = mac_address_to_bluetooth_device_map_.find(mac_address); + + if (it == mac_address_to_bluetooth_device_map_.end()) { + LOG(WARNING) << __func__ << ": Bluetooth device " << mac_address + << " is not in list. create it"; + auto bluetooth_device = std::make_unique(mac_address); + + mac_address_to_bluetooth_device_map_[mac_address] = + std::move(bluetooth_device); + auto result = mac_address_to_bluetooth_device_map_.insert_or_assign( + mac_address, std::move(bluetooth_device)); + + return result.first->second.get(); + } + + return it->second.get(); + + } else { + auto it = cached_bluetooth_devices_map_.find(mac_address); + + if (it == cached_bluetooth_devices_map_.end()) { + LOG(WARNING) << __func__ << ": Bluetooth device " << mac_address + << " is not in cache list. create it"; + auto bluetooth_device = std::make_unique(mac_address); + + auto result = cached_bluetooth_devices_map_.insert_or_assign( + mac_address, std::move(bluetooth_device)); + + return result.first->second.get(); + } + + return it->second.get(); + } } bool BluetoothClassicMedium::StartScanning() { @@ -514,16 +561,19 @@ bool BluetoothClassicMedium::StartScanning() { return false; } - mac_address_to_bluetooth_device_map_.clear(); - removed_bluetooth_devices_map_.clear(); - if (!cached_bluetooth_devices_map_.empty()) { - for (auto& [mac_address, bluetooth_device] : - cached_bluetooth_devices_map_) { - mac_address_to_bluetooth_device_map_[mac_address] = - std::move(bluetooth_device); - } + { + absl::MutexLock lock(&devices_map_mutex_); + mac_address_to_bluetooth_device_map_.clear(); + removed_bluetooth_devices_map_.clear(); + if (!cached_bluetooth_devices_map_.empty()) { + for (auto& [mac_address, bluetooth_device] : + cached_bluetooth_devices_map_) { + mac_address_to_bluetooth_device_map_[mac_address] = + std::move(bluetooth_device); + } - cached_bluetooth_devices_map_.clear(); + cached_bluetooth_devices_map_.clear(); + } } // The Start method can only be called when the DeviceWatcher is in the @@ -557,13 +607,16 @@ bool BluetoothClassicMedium::StopScanning() { winrt::fire_and_forget BluetoothClassicMedium::DeviceWatcher_Added( DeviceWatcher sender, DeviceInformation device_info) { LOG(INFO) << "Device added " << winrt::to_string(device_info.Id()); - IMapView properties = device_info.Properties(); - DumpDeviceInformation(properties); - if (!IsWatcherStarted()) { + LOG(WARNING) << __func__ << ": Ignore the Bluetooth device " + << winrt::to_string(device_info.Id()) + << " due to watcher not started."; return winrt::fire_and_forget(); } + IMapView properties = device_info.Properties(); + DumpDeviceInformation(properties); + // If device no item name, ignore it. if (!properties.HasKey(L"System.ItemNameDisplay")) { LOG(WARNING) << __func__ << ": Ignore the Bluetooth device " @@ -602,11 +655,7 @@ winrt::fire_and_forget BluetoothClassicMedium::DeviceWatcher_Added( std::string mac_address = uint64_to_mac_address_string(native_bluetooth_device.BluetoothAddress()); - // Create an iterator for the internal list - auto it = mac_address_to_bluetooth_device_map_.find(mac_address); - - // Add to our internal list if necessary - if (it != mac_address_to_bluetooth_device_map_.end()) { + if (HasRemoteDevice(mac_address)) { // We're already tracking this one LOG(WARNING) << __func__ << ": Bluetooth device " << mac_address << " is alreay added."; @@ -616,23 +665,35 @@ winrt::fire_and_forget BluetoothClassicMedium::DeviceWatcher_Added( auto bluetooth_device = std::make_unique(native_bluetooth_device); - mac_address_to_bluetooth_device_map_[mac_address] = - std::move(bluetooth_device); + AssignRemoteDevice(mac_address, std::move(bluetooth_device)); + + api::BluetoothDevice* device = GetRemoteDeviceInternal(mac_address); + if (device == nullptr) { + LOG(ERROR) << __func__ << ": Failed to get remote device."; + return winrt::fire_and_forget(); + } LOG(INFO) << __func__ << ": Notifying bluetooth device " << mac_address << " added"; if (discovery_callback_.device_discovered_cb != nullptr) { - discovery_callback_.device_discovered_cb( - *mac_address_to_bluetooth_device_map_[mac_address]); + discovery_callback_.device_discovered_cb(*device); } for (auto& observer : observers_.GetObservers()) { - observer->DeviceAdded(*mac_address_to_bluetooth_device_map_[mac_address]); + observer->DeviceAdded(*device); } return winrt::fire_and_forget(); } winrt::fire_and_forget BluetoothClassicMedium::DeviceWatcher_Updated( DeviceWatcher sender, DeviceInformationUpdate device_update_info) { + LOG(INFO) << "Device updated " << winrt::to_string(device_update_info.Id()); + if (!IsWatcherStarted()) { + LOG(WARNING) << __func__ << ": Ignore the Bluetooth device " + << winrt::to_string(device_update_info.Id()) + << " due to watcher not started."; + return winrt::fire_and_forget(); + } + auto native_bluetooth_device = ::winrt::Windows::Devices::Bluetooth::BluetoothDevice::FromIdAsync( device_update_info.Id()) @@ -640,43 +701,39 @@ winrt::fire_and_forget BluetoothClassicMedium::DeviceWatcher_Updated( std::string mac_address = uint64_to_mac_address_string(native_bluetooth_device.BluetoothAddress()); - auto it = mac_address_to_bluetooth_device_map_.find(mac_address); - - if (it == mac_address_to_bluetooth_device_map_.end()) { + if (!HasRemoteDevice(mac_address)) { LOG(WARNING) << __func__ << ": Bluetooth device " << mac_address << " is not in list."; return winrt::fire_and_forget(); } - LOG(INFO) << "Device updated name: " - << mac_address_to_bluetooth_device_map_[mac_address]->GetName() - << " (" << mac_address << ")"; + BluetoothDevice* device = GetRemoteDeviceInternal(mac_address); + if (device == nullptr) { + LOG(ERROR) << __func__ << ": Failed to get remote device."; + return winrt::fire_and_forget(); + } + + LOG(INFO) << "Device updated name: " << device->GetName() << " (" + << mac_address << ")"; IMapView properties = device_update_info.Properties(); DumpDeviceInformation(properties); - if (!IsWatcherStarted()) { - // Spurious call, watcher has stopped or wasn't started - return winrt::fire_and_forget(); - } - // https://learn.microsoft.com/en-us/windows/uwp/devices-sensors/device-information-properties#associationendpoint-properties if (properties.HasKey(L"System.ItemNameDisplay")) { // we need to really change the name of the bluetooth device std::string new_device_name = InspectableReader::ReadString( properties.Lookup(L"System.ItemNameDisplay")); - if (it->second->GetName() == new_device_name) { + if (device->GetName() == new_device_name) { LOG(INFO) << "Device name is same as old name, ignore the update."; } else { - it->second->SetName(new_device_name); + device->SetName(new_device_name); - LOG(INFO) << "Updated device name:" - << mac_address_to_bluetooth_device_map_[mac_address]->GetName(); + LOG(INFO) << "Updated device name:" << device->GetName(); if (discovery_callback_.device_name_changed_cb != nullptr) { - discovery_callback_.device_name_changed_cb( - *mac_address_to_bluetooth_device_map_[mac_address]); + discovery_callback_.device_name_changed_cb(*device); } } } @@ -689,9 +746,7 @@ winrt::fire_and_forget BluetoothClassicMedium::DeviceWatcher_Updated( << ": Notifying device paired changed: " << std::boolalpha << new_paired_status; for (auto& observer : observers_.GetObservers()) { - observer->DevicePairedChanged( - *mac_address_to_bluetooth_device_map_[mac_address], - new_paired_status); + observer->DevicePairedChanged(*device, new_paired_status); } } @@ -700,6 +755,14 @@ winrt::fire_and_forget BluetoothClassicMedium::DeviceWatcher_Updated( winrt::fire_and_forget BluetoothClassicMedium::DeviceWatcher_Removed( DeviceWatcher sender, DeviceInformationUpdate device_update_info) { + LOG(INFO) << "Device removed " << winrt::to_string(device_update_info.Id()); + if (!IsWatcherStarted()) { + LOG(WARNING) << __func__ << ": Ignore the Bluetooth device " + << winrt::to_string(device_update_info.Id()) + << " due to watcher not started."; + return winrt::fire_and_forget(); + } + auto native_bluetooth_device = ::winrt::Windows::Devices::Bluetooth::BluetoothDevice::FromIdAsync( device_update_info.Id()) @@ -712,34 +775,31 @@ winrt::fire_and_forget BluetoothClassicMedium::DeviceWatcher_Removed( std::string mac_address = uint64_to_mac_address_string(native_bluetooth_device.BluetoothAddress()); - auto it = mac_address_to_bluetooth_device_map_.find(mac_address); - if (it == mac_address_to_bluetooth_device_map_.end()) { + if (!HasRemoteDevice(mac_address)) { LOG(WARNING) << __func__ << ": Bluetooth device " << mac_address << " is not in list."; return winrt::fire_and_forget(); } - LOG(INFO) << "Device removed " - << mac_address_to_bluetooth_device_map_[mac_address]->GetName() - << " (" << mac_address << ")"; + api::BluetoothDevice* device = GetRemoteDeviceInternal(mac_address); - if (!IsWatcherStarted()) { + if (device == nullptr) { + LOG(ERROR) << __func__ << ": Failed to get remote device."; return winrt::fire_and_forget(); } - LOG(INFO) << __func__ << ": Notifying bluetooth device removed"; + LOG(INFO) << __func__ << ": Notifying bluetooth device (" << mac_address + << ") removed"; if (discovery_callback_.device_lost_cb != nullptr) { - discovery_callback_.device_lost_cb( - *mac_address_to_bluetooth_device_map_[mac_address]); + discovery_callback_.device_lost_cb(*device); } for (auto& observer : observers_.GetObservers()) { - observer->DeviceRemoved(*mac_address_to_bluetooth_device_map_[mac_address]); + observer->DeviceRemoved(*device); } - auto node = mac_address_to_bluetooth_device_map_.extract(mac_address); - removed_bluetooth_devices_map_[mac_address] = std::move(node.mapped()); + RemoveRemoteDevice(mac_address); return winrt::fire_and_forget(); } diff --git a/internal/platform/implementation/windows/bluetooth_classic_medium.h b/internal/platform/implementation/windows/bluetooth_classic_medium.h index f12ec2cd..54945425 100644 --- a/internal/platform/implementation/windows/bluetooth_classic_medium.h +++ b/internal/platform/implementation/windows/bluetooth_classic_medium.h @@ -15,12 +15,12 @@ #ifndef PLATFORM_IMPL_WINDOWS_BLUETOOTH_CLASSIC_MEDIUM_H_ #define PLATFORM_IMPL_WINDOWS_BLUETOOTH_CLASSIC_MEDIUM_H_ -#include -#include #include #include +#include "absl/base/thread_annotations.h" #include "absl/container/flat_hash_map.h" +#include "absl/synchronization/mutex.h" #include "internal/base/observer_list.h" #include "internal/platform/cancellation_flag.h" #include "internal/platform/implementation/bluetooth_adapter.h" @@ -141,6 +141,17 @@ class BluetoothClassicMedium : public api::BluetoothClassicMedium { // Check to see that the device actually handles the requested service bool CheckSdp(RfcommDeviceService requested_service); + // Methods to handle bluetooth devices + bool HasRemoteDevice(const std::string& mac_address) + ABSL_LOCKS_EXCLUDED(devices_map_mutex_); + bool RemoveRemoteDevice(const std::string& mac_address) + ABSL_LOCKS_EXCLUDED(devices_map_mutex_); + bool AssignRemoteDevice(const std::string& mac_address, + std::unique_ptr device) + ABSL_LOCKS_EXCLUDED(devices_map_mutex_); + BluetoothDevice* GetRemoteDeviceInternal(const std::string& mac_address) + ABSL_LOCKS_EXCLUDED(devices_map_mutex_); + BluetoothClassicMedium::DiscoveryCallback discovery_callback_; ::winrt::Windows::Devices::Enumeration::DeviceWatcher device_watcher_ = @@ -151,17 +162,21 @@ class BluetoothClassicMedium : public api::BluetoothClassicMedium { std::string service_name_; std::string service_uuid_; + absl::Mutex devices_map_mutex_; + // Map MAC address to bluetooth device. absl::flat_hash_map> - mac_address_to_bluetooth_device_map_; + mac_address_to_bluetooth_device_map_ ABSL_GUARDED_BY(devices_map_mutex_); // Track removed devices. absl::flat_hash_map> - removed_bluetooth_devices_map_; + removed_bluetooth_devices_map_ ABSL_GUARDED_BY(devices_map_mutex_); + ; // The caller may call to create Bluetooth device when scanning is off. absl::flat_hash_map> - cached_bluetooth_devices_map_; + cached_bluetooth_devices_map_ ABSL_GUARDED_BY(devices_map_mutex_); + ; BluetoothAdapter& bluetooth_adapter_;