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() { void BluetoothClassicMedium::InitializeDeviceWatcher() {
// create watcher // 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( device_watcher_ = DeviceInformation::CreateWatcher(
BLUETOOTH_SELECTOR, // aqsFilter BLUETOOTH_SELECTOR, // aqsFilter
nullptr, // additionalProperties RequestedProperties, // additionalProperties
DeviceInformationKind::AssociationEndpoint); // kind DeviceInformationKind::AssociationEndpoint); // kind
// An app must subscribe to all of the added, removed, and updated events to // 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; return nullptr;
} }
device_watcher_.Stop();
EnterCriticalSection(&critical_section_); EnterCriticalSection(&critical_section_);
std::unique_ptr<BluetoothSocket> rfcommSocket = std::unique_ptr<BluetoothSocket> rfcommSocket =
@@ -190,7 +192,7 @@ std::unique_ptr<api::BluetoothSocket> BluetoothClassicMedium::ConnectToService(
try { try {
rfcommSocket->Connect(requestedService.ConnectionHostName(), rfcommSocket->Connect(requestedService.ConnectionHostName(),
requestedService.ConnectionServiceName()); requestedService.ConnectionServiceName());
} catch (std::exception exception) { } catch (std::exception exception) {
// We will log and eat the exception since the caller // We will log and eat the exception since the caller
// expects nullptr if it fails // expects nullptr if it fails
@@ -320,6 +322,8 @@ api::BluetoothDevice* BluetoothClassicMedium::GetRemoteDevice(
bool BluetoothClassicMedium::StartScanning() { bool BluetoothClassicMedium::StartScanning() {
if (!IsWatcherStarted()) { if (!IsWatcherStarted()) {
discovered_devices_by_id_.clear();
// The Start method can only be called when the DeviceWatcher is in the // The Start method can only be called when the DeviceWatcher is in the
// Created, Stopped or Aborted state. // Created, Stopped or Aborted state.
auto status = device_watcher_.Status(); auto status = device_watcher_.Status();
@@ -360,32 +364,37 @@ winrt::fire_and_forget BluetoothClassicMedium::DeviceWatcher_Added(
// Create an iterator for the internal list // Create an iterator for the internal list
std::map<winrt::hstring, std::unique_ptr<BluetoothDevice>>::const_iterator 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 // Add to our internal list if necessary
if (it == devices_by_id_.end()) { if (it != discovered_devices_by_id_.end()) {
// Create a bluetooth device out of this id // We're already tracking this one
winrt::Windows::Devices::Bluetooth::BluetoothDevice::FromIdAsync( return winrt::fire_and_forget();
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_);
});
} }
// 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(); return winrt::fire_and_forget();
@@ -393,10 +402,30 @@ winrt::fire_and_forget BluetoothClassicMedium::DeviceWatcher_Added(
winrt::fire_and_forget BluetoothClassicMedium::DeviceWatcher_Updated( winrt::fire_and_forget BluetoothClassicMedium::DeviceWatcher_Updated(
DeviceWatcher sender, DeviceInformationUpdate deviceInfoUpdate) { DeviceWatcher sender, DeviceInformationUpdate deviceInfoUpdate) {
if (IsWatcherStarted()) { EnterCriticalSection(&critical_section_);
// TODO(jfcarroll): Check for device name change
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(); return winrt::fire_and_forget();
} }
@@ -404,14 +433,17 @@ winrt::fire_and_forget BluetoothClassicMedium::DeviceWatcher_Removed(
DeviceWatcher sender, DeviceInformationUpdate deviceInfo) { DeviceWatcher sender, DeviceInformationUpdate deviceInfo) {
EnterCriticalSection(&critical_section_); EnterCriticalSection(&critical_section_);
if (IsWatcherStarted()) { if (!IsWatcherStarted()) {
if (discovery_callback_.device_lost_cb != nullptr) { return winrt::fire_and_forget();
discovery_callback_.device_lost_cb(*devices_by_id_[deviceInfo.Id()]);
}
devices_by_id_.erase(deviceInfo.Id());
} }
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_); LeaveCriticalSection(&critical_section_);
return winrt::fire_and_forget(); return winrt::fire_and_forget();
@@ -173,7 +173,8 @@ class BluetoothClassicMedium : public api::BluetoothClassicMedium {
// hstring is the only type of string winrt understands. // hstring is the only type of string winrt understands.
// https://docs.microsoft.com/en-us/uwp/cpp-ref-for-winrt/hstring // 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 // CRITICAL_SECTION is a lightweight synchronization mechanism
// https://docs.microsoft.com/en-us/windows/win32/sync/critical-section-objects // https://docs.microsoft.com/en-us/windows/win32/sync/critical-section-objects
@@ -23,10 +23,6 @@ namespace windows {
BluetoothSocket::BluetoothSocket(StreamSocket streamSocket) BluetoothSocket::BluetoothSocket(StreamSocket streamSocket)
: windows_socket_(streamSocket) { : windows_socket_(streamSocket) {
bluetooth_device_ = std::make_unique<BluetoothDevice>(
winrt::Windows::Devices::Bluetooth::BluetoothDevice::FromHostNameAsync(
windows_socket_.Information().RemoteHostName())
.get());
input_stream_ = input_stream_ =
std::make_unique<BluetoothInputStream>(windows_socket_.InputStream()); std::make_unique<BluetoothInputStream>(windows_socket_.InputStream());
output_stream_ = output_stream_ =