From ee262121c3c4829de2b6df640083578ada3d008f Mon Sep 17 00:00:00 2001 From: Guogang Li Date: Tue, 6 Jun 2023 19:05:50 -0700 Subject: [PATCH] Added timeout to discover GATT and BT service PiperOrigin-RevId: 538352588 --- .../implementation/windows/ble_gatt_client.cc | 32 +++++++++-- .../windows/bluetooth_classic_device.cc | 55 ++++++++++--------- 2 files changed, 55 insertions(+), 32 deletions(-) diff --git a/internal/platform/implementation/windows/ble_gatt_client.cc b/internal/platform/implementation/windows/ble_gatt_client.cc index 0ba470ff..c75600fb 100644 --- a/internal/platform/implementation/windows/ble_gatt_client.cc +++ b/internal/platform/implementation/windows/ble_gatt_client.cc @@ -41,6 +41,7 @@ #include "winrt/Windows.Devices.Bluetooth.GenericAttributeProfile.h" #include "winrt/Windows.Devices.Bluetooth.h" #include "winrt/Windows.Foundation.Collections.h" +#include "winrt/Windows.Foundation.h" #include "winrt/Windows.Storage.Streams.h" namespace nearby { @@ -69,6 +70,7 @@ using ::winrt::Windows::Devices::Bluetooth::GenericAttributeProfile:: GattValueChangedEventArgs; using ::winrt::Windows::Devices::Bluetooth::GenericAttributeProfile:: GattWriteOption; +using ::winrt::Windows::Foundation::TimeSpan; using ::winrt::Windows::Foundation::Collections::IVectorView; using ::winrt::Windows::Storage::Streams::Buffer; using ::winrt::Windows::Storage::Streams::DataReader; @@ -77,6 +79,8 @@ using Property = api::ble_v2::GattCharacteristic::Property; using Permission = api::ble_v2::GattCharacteristic::Permission; using WriteType = api::ble_v2::GattClient::WriteType; +constexpr int kGattTimeoutInSeconds = 5; + std::string GattCommunicationStatusToString(GattCommunicationStatus status) { switch (status) { case GattCommunicationStatus::Success: @@ -121,8 +125,26 @@ bool BleGattClient::DiscoverServiceAndCharacteristics( } // Gets the GATT services on the BLE device. - gatt_devices_services_result_ = - ble_device_.GetGattServicesAsync(BluetoothCacheMode::Uncached).get(); + auto get_gatt_services_async = + ble_device_.GetGattServicesAsync(BluetoothCacheMode::Cached); + + switch (get_gatt_services_async.wait_for( + TimeSpan(std::chrono::seconds(kGattTimeoutInSeconds)))) { + case winrt::Windows::Foundation::AsyncStatus::Completed: + gatt_devices_services_result_ = get_gatt_services_async.GetResults(); + break; + case winrt::Windows::Foundation::AsyncStatus::Started: + NEARBY_LOGS(ERROR) << __func__ + << ": Failed to get GATT services due to timeout."; + get_gatt_services_async.Cancel(); + return false; + default: + NEARBY_LOGS(ERROR) + << __func__ + << ": Failed to get GATT services due to unknown reasons."; + return false; + } + if (gatt_devices_services_result_.Status() != GattCommunicationStatus::Success) { NEARBY_LOGS(ERROR) << __func__ @@ -475,9 +497,9 @@ bool BleGattClient::SetCharacteristicSubscription( return false; } } else if (native_characteristic_map_[characteristic].notification_token) { - gatt_characteristic->ValueChanged(std::exchange( - native_characteristic_map_[characteristic].notification_token, {})); - } + gatt_characteristic->ValueChanged(std::exchange( + native_characteristic_map_[characteristic].notification_token, {})); + } NEARBY_LOGS(ERROR) << __func__ << ": Successfully set Characteristic Subscription."; return true; diff --git a/internal/platform/implementation/windows/bluetooth_classic_device.cc b/internal/platform/implementation/windows/bluetooth_classic_device.cc index a2e3a4e8..707ebd62 100644 --- a/internal/platform/implementation/windows/bluetooth_classic_device.cc +++ b/internal/platform/implementation/windows/bluetooth_classic_device.cc @@ -29,9 +29,15 @@ #include "internal/platform/implementation/windows/generated/winrt/base.h" #include "internal/platform/implementation/windows/utils.h" #include "internal/platform/logging.h" +#include "winrt/Windows.Foundation.h" namespace nearby { namespace windows { +namespace { +constexpr int kBluetoothTimeoutInSeconds = 10; + +using ::winrt::Windows::Foundation::TimeSpan; +} // namespace BluetoothDevice::~BluetoothDevice() {} @@ -70,35 +76,30 @@ RfcommDeviceService BluetoothDevice::GetRfcommServiceForIdAsync( NEARBY_LOGS(INFO) << __func__ << ": Get RF services for service id:" << winrt::to_string(serviceId.AsString()); - // Check cache first - RfcommDeviceServicesResult rfcomm_device_services = - windows_bluetooth_device_ - .GetRfcommServicesForIdAsync(serviceId, BluetoothCacheMode::Cached) - .get(); - if (rfcomm_device_services != nullptr && - rfcomm_device_services.Services().Size() > 0) { - NEARBY_LOGS(INFO) << __func__ << ": Get " - << rfcomm_device_services.Services().Size() - << " services from cache."; - // found the matched service. - for (auto rfcomm_device_service : rfcomm_device_services.Services()) { - if (rfcomm_device_service.Device() != nullptr && - winrt::to_string(rfcomm_device_service.Device().DeviceId()) == - id_) { - NEARBY_LOGS(INFO) << __func__ << ": Found service from cache."; - return rfcomm_device_service; - } - } + RfcommDeviceServicesResult rfcomm_device_services = nullptr; + // Try to get service from un cached mode. + auto rfcomm_device_services_async = + windows_bluetooth_device_.GetRfcommServicesForIdAsync( + serviceId, BluetoothCacheMode::Uncached); + + switch (rfcomm_device_services_async.wait_for( + TimeSpan(std::chrono::seconds(kBluetoothTimeoutInSeconds)))) { + case winrt::Windows::Foundation::AsyncStatus::Completed: + rfcomm_device_services = rfcomm_device_services_async.GetResults(); + break; + case winrt::Windows::Foundation::AsyncStatus::Started: + NEARBY_LOGS(ERROR) + << __func__ + << ": Failed to get RfcommDeviceService due to timeout."; + rfcomm_device_services_async.Cancel(); + return nullptr; + default: + NEARBY_LOGS(ERROR) + << __func__ + << ": Failed to get RfcommDeviceService due to unknown reasons."; + return nullptr; } - NEARBY_LOGS(INFO) << __func__ - << ": Try to found service with no-cache mode."; - - // Try to get service from un cached mode. - rfcomm_device_services = windows_bluetooth_device_ - .GetRfcommServicesForIdAsync( - serviceId, BluetoothCacheMode::Uncached) - .get(); if (rfcomm_device_services != nullptr && rfcomm_device_services.Services().Size() > 0) { NEARBY_LOGS(INFO) << __func__ << ": Get "