This is the fix for StartDiscovery/Connect/Disconnect/StartDiscovery.

PiperOrigin-RevId: 424866263
This commit is contained in:
jfcarroll
2022-02-02 11:45:04 -08:00
committed by hai007
parent 5bc20e2ea4
commit 1e61c5fb23
3 changed files with 69 additions and 40 deletions
@@ -97,9 +97,13 @@ bool BluetoothClassicMedium::StopDiscovery() {
void BluetoothClassicMedium::InitializeDeviceWatcher() {
// create watcher
const winrt::param::iterable<winrt::hstring> RequestedProperties =
winrt::single_threaded_vector<winrt::hstring>(
{winrt::to_hstring("System.Devices.Aep.IsPresent")});
device_watcher_ = DeviceInformation::CreateWatcher(
BLUETOOTH_SELECTOR, // aqsFilter
nullptr, // additionalProperties
RequestedProperties, // additionalProperties
DeviceInformationKind::AssociationEndpoint); // kind
// An app must subscribe to all of the added, removed, and updated events to
@@ -177,8 +181,6 @@ std::unique_ptr<api::BluetoothSocket> BluetoothClassicMedium::ConnectToService(
return nullptr;
}
device_watcher_.Stop();
EnterCriticalSection(&critical_section_);
std::unique_ptr<BluetoothSocket> rfcommSocket =
@@ -190,7 +192,7 @@ std::unique_ptr<api::BluetoothSocket> BluetoothClassicMedium::ConnectToService(
try {
rfcommSocket->Connect(requestedService.ConnectionHostName(),
requestedService.ConnectionServiceName());
requestedService.ConnectionServiceName());
} catch (std::exception exception) {
// We will log and eat the exception since the caller
// expects nullptr if it fails
@@ -320,6 +322,8 @@ api::BluetoothDevice* BluetoothClassicMedium::GetRemoteDevice(
bool BluetoothClassicMedium::StartScanning() {
if (!IsWatcherStarted()) {
discovered_devices_by_id_.clear();
// The Start method can only be called when the DeviceWatcher is in the
// Created, Stopped or Aborted state.
auto status = device_watcher_.Status();
@@ -360,32 +364,37 @@ winrt::fire_and_forget BluetoothClassicMedium::DeviceWatcher_Added(
// Create an iterator for the internal list
std::map<winrt::hstring, std::unique_ptr<BluetoothDevice>>::const_iterator
it = devices_by_id_.find(deviceInfo.Id());
it = discovered_devices_by_id_.find(deviceInfo.Id());
// Add to our internal list if necessary
if (it == devices_by_id_.end()) {
// Create a bluetooth device out of this id
winrt::Windows::Devices::Bluetooth::BluetoothDevice::FromIdAsync(
deviceInfo.Id())
.Completed(
[this, deviceInfo, wbd = std::move(windowsBluetoothDevice)](
auto&& async,
winrt::Windows::Foundation::AsyncStatus status) {
EnterCriticalSection(&critical_section_);
std::unique_ptr<BluetoothDevice> bluetoothDevice =
std::make_unique<BluetoothDevice>(async.get());
devices_by_id_[deviceInfo.Id()] = std::move(bluetoothDevice);
if (discovery_callback_.device_discovered_cb != nullptr) {
discovery_callback_.device_discovered_cb(
*devices_by_id_[deviceInfo.Id()]);
}
LeaveCriticalSection(&critical_section_);
});
if (it != discovered_devices_by_id_.end()) {
// We're already tracking this one
return winrt::fire_and_forget();
}
// Create a bluetooth device out of this id
winrt::Windows::Devices::Bluetooth::BluetoothDevice::FromIdAsync(
deviceInfo.Id())
.Completed([this, deviceInfo](
winrt::Windows::Foundation::IAsyncOperation<
winrt::Windows::Devices::Bluetooth::BluetoothDevice>
bluetoothDevice,
winrt::Windows::Foundation::AsyncStatus status) {
EnterCriticalSection(&critical_section_);
std::unique_ptr<BluetoothDevice> bluetoothDeviceP =
std::make_unique<BluetoothDevice>(bluetoothDevice.get());
discovered_devices_by_id_[deviceInfo.Id()] =
std::move(bluetoothDeviceP);
if (discovery_callback_.device_discovered_cb != nullptr) {
discovery_callback_.device_discovered_cb(
*discovered_devices_by_id_[deviceInfo.Id()]);
}
LeaveCriticalSection(&critical_section_);
});
}
return winrt::fire_and_forget();
@@ -393,10 +402,30 @@ winrt::fire_and_forget BluetoothClassicMedium::DeviceWatcher_Added(
winrt::fire_and_forget BluetoothClassicMedium::DeviceWatcher_Updated(
DeviceWatcher sender, DeviceInformationUpdate deviceInfoUpdate) {
if (IsWatcherStarted()) {
// TODO(jfcarroll): Check for device name change
EnterCriticalSection(&critical_section_);
if (!IsWatcherStarted()) {
// Spurious call, watcher has stopped or wasn't started
LeaveCriticalSection(&critical_section_);
return winrt::fire_and_forget();
}
auto it = discovered_devices_by_id_.find(deviceInfoUpdate.Id());
if (it == discovered_devices_by_id_.end()) {
LeaveCriticalSection(&critical_section_);
// Not tracking this device
return winrt::fire_and_forget();
}
if (deviceInfoUpdate.Properties().HasKey(
winrt::to_hstring("System.ItemNameDisplay"))) {
discovery_callback_.device_name_changed_cb(
*discovered_devices_by_id_[deviceInfoUpdate.Id()]);
}
LeaveCriticalSection(&critical_section_);
return winrt::fire_and_forget();
}
@@ -404,14 +433,17 @@ winrt::fire_and_forget BluetoothClassicMedium::DeviceWatcher_Removed(
DeviceWatcher sender, DeviceInformationUpdate deviceInfo) {
EnterCriticalSection(&critical_section_);
if (IsWatcherStarted()) {
if (discovery_callback_.device_lost_cb != nullptr) {
discovery_callback_.device_lost_cb(*devices_by_id_[deviceInfo.Id()]);
}
devices_by_id_.erase(deviceInfo.Id());
if (!IsWatcherStarted()) {
return winrt::fire_and_forget();
}
if (discovery_callback_.device_lost_cb != nullptr) {
discovery_callback_.device_lost_cb(
*discovered_devices_by_id_[deviceInfo.Id()]);
}
discovered_devices_by_id_.erase(deviceInfo.Id());
LeaveCriticalSection(&critical_section_);
return winrt::fire_and_forget();
@@ -173,7 +173,8 @@ class BluetoothClassicMedium : public api::BluetoothClassicMedium {
// hstring is the only type of string winrt understands.
// https://docs.microsoft.com/en-us/uwp/cpp-ref-for-winrt/hstring
std::map<winrt::hstring, std::unique_ptr<BluetoothDevice>> devices_by_id_;
std::map<winrt::hstring, std::unique_ptr<BluetoothDevice>>
discovered_devices_by_id_;
// CRITICAL_SECTION is a lightweight synchronization mechanism
// https://docs.microsoft.com/en-us/windows/win32/sync/critical-section-objects
@@ -23,10 +23,6 @@ namespace windows {
BluetoothSocket::BluetoothSocket(StreamSocket streamSocket)
: windows_socket_(streamSocket) {
bluetooth_device_ = std::make_unique<BluetoothDevice>(
winrt::Windows::Devices::Bluetooth::BluetoothDevice::FromHostNameAsync(
windows_socket_.Information().RemoteHostName())
.get());
input_stream_ =
std::make_unique<BluetoothInputStream>(windows_socket_.InputStream());
output_stream_ =