From 3c77c0dfa03495c3bb97e7bfd70763462651f970 Mon Sep 17 00:00:00 2001 From: hai007 Date: Fri, 11 Apr 2025 11:57:58 -0700 Subject: [PATCH] Stop BLE_V2 scan before upgrading to Wifi HotSpot to avoid interference PiperOrigin-RevId: 746541587 --- connections/implementation/bwu_manager.cc | 38 +++++++++++++++++++ connections/implementation/bwu_manager.h | 2 + .../flags/nearby_connections_feature_flags.h | 3 ++ connections/implementation/mediums/ble_v2.cc | 10 +++++ connections/implementation/mediums/ble_v2.h | 6 +++ internal/platform/ble_v2.cc | 14 +++++++ internal/platform/ble_v2.h | 6 +++ .../apple/Mediums/BLEv2/GNCBLEMedium.h | 25 ++++++++---- .../apple/Mediums/BLEv2/GNCBLEMedium.m | 10 +++++ .../implementation/apple/ble_medium.h | 10 +++++ .../implementation/apple/ble_medium.mm | 18 +++++++++ internal/platform/implementation/ble_v2.h | 4 ++ 12 files changed, 138 insertions(+), 8 deletions(-) diff --git a/connections/implementation/bwu_manager.cc b/connections/implementation/bwu_manager.cc index 56f2c11a..1aa881ef 100644 --- a/connections/implementation/bwu_manager.cc +++ b/connections/implementation/bwu_manager.cc @@ -23,6 +23,7 @@ #include "absl/container/flat_hash_map.h" #include "absl/functional/bind_front.h" +#include "absl/strings/str_cat.h" #include "absl/time/time.h" #include "connections/implementation/analytics/connection_attempt_metadata_params.h" #include "connections/implementation/bluetooth_bwu_handler.h" @@ -31,9 +32,11 @@ #include "connections/implementation/endpoint_channel.h" #include "connections/implementation/endpoint_channel_manager.h" #include "connections/implementation/endpoint_manager.h" +#include "connections/implementation/flags/nearby_connections_feature_flags.h" #include "connections/implementation/mediums/mediums.h" #include "connections/implementation/offline_frames.h" #include "connections/implementation/service_id_constants.h" +#include "internal/flags/nearby_flags.h" #ifdef NO_WEBRTC #include "connections/implementation/webrtc_bwu_handler_stub.h" #else @@ -897,6 +900,8 @@ BwuManager::ProcessBwuPathAvailableEventInternal( // Get service ID from the old channel. Don't keep the old channel's shared // pointer in scope longer than necessary. std::string service_id; + Medium old_medium = Medium::UNKNOWN_MEDIUM; + bool disable_ble_scanning = false; { std::shared_ptr old_channel = channel_manager_->GetChannelForEndpoint(endpoint_id); @@ -910,11 +915,44 @@ BwuManager::ProcessBwuPathAvailableEventInternal( Error(OperationResultCode::NEARBY_GENERIC_OLD_ENDPOINT_CHANNEL_NULL)}; } service_id = old_channel->GetServiceId(); + old_medium = old_channel->GetMedium(); + } + + bool enable_ble_v2 = NearbyFlags::GetInstance().GetBoolFlag( + config_package_nearby::nearby_connections_feature::kEnableBleV2); + if (NearbyFlags::GetInstance().GetBoolFlag( + config_package_nearby::nearby_connections_feature:: + kEnableStopBLEScanningOnWifiUpgrade)) { + if (client->GetLocalOsInfo().type() == + location::nearby::connections::OsInfo::APPLE && + old_medium == Medium::BLE && medium == Medium::WIFI_HOTSPOT) { + disable_ble_scanning = true; + if (enable_ble_v2) { + NEARBY_LOGS(INFO) + << "For Apple OS, if upgrade from BLE_V2 to WIFI_HOTSPOT, " + "we need to pause " + "BLE_V2 scanning because it can interfere with WIFI " + "Hotspot scanning and connection."; + ble_v2_medium_.PauseMediumScanning(); + } + } } ErrorOr> result = handler->CreateUpgradedEndpointChannel(client, service_id, endpoint_id, upgrade_path_info); + + if (NearbyFlags::GetInstance().GetBoolFlag( + config_package_nearby::nearby_connections_feature:: + kEnableStopBLEScanningOnWifiUpgrade)) { + if (disable_ble_scanning) { + if (enable_ble_v2) { + NEARBY_LOGS(INFO) << "Resume BLE_V2 scanning."; + ble_v2_medium_.ResumeMediumScanning(); + } + } + } + if (result.has_error() || !result.has_value()) { NEARBY_LOGS(ERROR) << "BwuManager failed to create an endpoint " "channel to endpoint" diff --git a/connections/implementation/bwu_manager.h b/connections/implementation/bwu_manager.h index 7c620951..722f6ced 100644 --- a/connections/implementation/bwu_manager.h +++ b/connections/implementation/bwu_manager.h @@ -28,6 +28,7 @@ #include "connections/implementation/endpoint_channel.h" #include "connections/implementation/endpoint_channel_manager.h" #include "connections/implementation/endpoint_manager.h" +#include "connections/implementation/mediums/ble_v2.h" #include "connections/implementation/mediums/mediums.h" #include "connections/medium_selector.h" #include "internal/platform/cancelable_alarm.h" @@ -226,6 +227,7 @@ class BwuManager : public EndpointManager::FrameProcessor { Mediums* mediums_; absl::flat_hash_map> handlers_; + BleV2& ble_v2_medium_{mediums_->GetBleV2()}; EndpointManager* endpoint_manager_; EndpointChannelManager* channel_manager_; diff --git a/connections/implementation/flags/nearby_connections_feature_flags.h b/connections/implementation/flags/nearby_connections_feature_flags.h index d68becf4..c56e55d0 100644 --- a/connections/implementation/flags/nearby_connections_feature_flags.h +++ b/connections/implementation/flags/nearby_connections_feature_flags.h @@ -89,6 +89,9 @@ constexpr auto kUseStableEndpointId = // When true, disable instant on lost on BLE without extended feature. constexpr auto kDisableInstantOnLostOnBleWithoutExtended = flags::Flag(kConfigPackage, "45687098", true); +// When true, stop BLE_V2 scanning when upgrading to WIFI Hotspot or WFD. +constexpr auto kEnableStopBLEScanningOnWifiUpgrade = + flags::Flag(kConfigPackage, "45687902", false); // When true, enable multiplexing in NC for AWDL. constexpr auto kEnableMultiplexAwdl = flags::Flag(kConfigPackage, "45690761", false); diff --git a/connections/implementation/mediums/ble_v2.cc b/connections/implementation/mediums/ble_v2.cc index 29074c1b..29334cde 100644 --- a/connections/implementation/mediums/ble_v2.cc +++ b/connections/implementation/mediums/ble_v2.cc @@ -564,6 +564,16 @@ bool BleV2::StopScanning(const std::string& service_id) { return medium_.StopScanning(); } +bool BleV2::PauseMediumScanning() { + MutexLock lock(&mutex_); + return medium_.PauseMediumScanning(); +} + +bool BleV2::ResumeMediumScanning() { + MutexLock lock(&mutex_); + return medium_.ResumeMediumScanning(); +} + bool BleV2::IsScanning(const std::string& service_id) const { MutexLock lock(&mutex_); diff --git a/connections/implementation/mediums/ble_v2.h b/connections/implementation/mediums/ble_v2.h index 2585f343..f22846a9 100644 --- a/connections/implementation/mediums/ble_v2.h +++ b/connections/implementation/mediums/ble_v2.h @@ -145,6 +145,12 @@ class BleV2 final { // Returns true, if the scanning was previously enabled, false otherwise. bool StopScanning(const std::string& service_id) ABSL_LOCKS_EXCLUDED(mutex_); + // Pauses BLE scanning at platform Medium level. + bool PauseMediumScanning(); + + // Resumes BLE scanning at platform Medium level. + bool ResumeMediumScanning(); + // Returns true if the scanning for service ID is enabled. bool IsScanning(const std::string& service_id) const ABSL_LOCKS_EXCLUDED(mutex_); diff --git a/internal/platform/ble_v2.cc b/internal/platform/ble_v2.cc index 856e09f8..d7a61775 100644 --- a/internal/platform/ble_v2.cc +++ b/internal/platform/ble_v2.cc @@ -147,6 +147,20 @@ bool BleV2Medium::StopScanning() { NEARBY_LOGS(INFO) << "Ble Scanning disabled: impl=" << GetImpl(); return impl_->StopScanning(); } +bool BleV2Medium::PauseMediumScanning() { + MutexLock lock(&mutex_); + if (!scanning_enabled_) { + return true; + } + NEARBY_LOGS(INFO) << "Pause Medium level BLE_V2 Scanning: impl=" + << GetImpl(); + return impl_->PauseMediumScanning(); +} + +bool BleV2Medium::ResumeMediumScanning() { + MutexLock lock(&mutex_); + return impl_->ResumeMediumScanning(); +} std::unique_ptr BleV2Medium::StartScanning(const Uuid& service_uuid, diff --git a/internal/platform/ble_v2.h b/internal/platform/ble_v2.h index 0fead541..01534672 100644 --- a/internal/platform/ble_v2.h +++ b/internal/platform/ble_v2.h @@ -496,6 +496,12 @@ class BleV2Medium final { // TODO(b/271305977) remove this function. bool StopScanning(); + // Pause BLE scanning at platform Medium level. + bool PauseMediumScanning(); + + // Resume BLE scanning at platform Medium level. + bool ResumeMediumScanning(); + std::unique_ptr StartScanning( const Uuid& service_uuid, api::ble_v2::TxPowerLevel tx_power_level, api::ble_v2::BleMedium::ScanningCallback callback); diff --git a/internal/platform/implementation/apple/Mediums/BLEv2/GNCBLEMedium.h b/internal/platform/implementation/apple/Mediums/BLEv2/GNCBLEMedium.h index 8094f07a..ac11a381 100644 --- a/internal/platform/implementation/apple/Mediums/BLEv2/GNCBLEMedium.h +++ b/internal/platform/implementation/apple/Mediums/BLEv2/GNCBLEMedium.h @@ -120,7 +120,7 @@ typedef void (^GNCOpenL2CAPServerCompletionHandler)(GNCBLEL2CAPServer *_Nullable * * @param serviceData A dictionary that contains service-specific advertisement data. * @param completionHandler Called on a private queue with @c nil if successfully started - * advertising or an error if one has occured. + * advertising or an error if one has occurred. */ - (void)startAdvertisingData:(NSDictionary *)serviceData completionHandler:(nullable GNCStartAdvertisingCompletionHandler)completionHandler; @@ -129,7 +129,7 @@ typedef void (^GNCOpenL2CAPServerCompletionHandler)(GNCBLEL2CAPServer *_Nullable * Stops advertising all service data. * * @param completionHandler Called on a private queue with @c nil if successfully stopped - * advertising or an error if one has occured. + * advertising or an error if one has occurred. */ - (void)stopAdvertisingWithCompletionHandler: (nullable GNCStopAdvertisingCompletionHandler)completionHandler; @@ -140,7 +140,7 @@ typedef void (^GNCOpenL2CAPServerCompletionHandler)(GNCBLEL2CAPServer *_Nullable * @param serviceUUID The service UUID to scan for. * @param advertisementFoundHandler Called on a private queue when a peripheral has been discovered. * @param completionHandler Called on a private queue with @c nil if successfully started scanning - * or an error if one has occured. + * or an error if one has occurred. */ - (void)startScanningForService:(CBUUID *)serviceUUID advertisementFoundHandler:(GNCAdvertisementFoundHandler)advertisementFoundHandler @@ -154,7 +154,7 @@ typedef void (^GNCOpenL2CAPServerCompletionHandler)(GNCBLEL2CAPServer *_Nullable * discovered. * @param advertisementFoundHandler Called on a private queue when a peripheral has been discovered. * @param completionHandler Called on a private queue with @c nil if successfully started scanning - * or an error if one has occured. + * or an error if one has occurred. */ - (void)startScanningForMultipleServices:(NSArray *)serviceUUIDs advertisementFoundHandler:(GNCAdvertisementFoundHandler)advertisementFoundHandler @@ -165,16 +165,25 @@ typedef void (^GNCOpenL2CAPServerCompletionHandler)(GNCBLEL2CAPServer *_Nullable * Stops scanning for peripherals. * * @param completionHandler Called on a private queue with @c nil if successfully stopped - * scanning or an error if one has occured. + * scanning or an error if one has occurred. */ - (void)stopScanningWithCompletionHandler: (nullable GNCStopScanningCompletionHandler)completionHandler; +/** + * Resumes scanning for peripherals. + * + * @param completionHandler Called on a private queue with @c nil if successfully resumed scanning + * or an error if one has occurred. + */ +- (void)resumeMediumScanning: + (nullable GNCStartScanningCompletionHandler)completionHandler; + /** * Starts a GATT server. * * @param completionHandler Called on a private queue with the GATT server if successfully started - * or an error if one has occured. + * or an error if one has occurred. */ - (void)startGATTServerWithCompletionHandler: (nullable GNCGATTServerCompletionHandler)completionHandler; @@ -185,7 +194,7 @@ typedef void (^GNCOpenL2CAPServerCompletionHandler)(GNCBLEL2CAPServer *_Nullable * @param remotePeripheral The peripheral to which the central is attempting to connect. * @param disconnectionHandler Called on a private queue when the peripheral has been disconnected. * @param completionHandler Called on a private queue with a GATT client if successfully connected - * or an error if one has occured. + * or an error if one has occurred. */ - (void)connectToGATTServerForPeripheral:(id)remotePeripheral disconnectionHandler:(nullable GNCGATTDisconnectionHandler)disconnectionHandler @@ -196,7 +205,7 @@ typedef void (^GNCOpenL2CAPServerCompletionHandler)(GNCBLEL2CAPServer *_Nullable * Opens a L2CAP server. * * @param completionHandler Called on a private queue with the L2CAP server if successfully started - * or an error if one has occured. + * or an error if one has occurred. * @param peripheralManager The peripheral manager instance. */ - (void)openL2CAPServerWithCompletionHandler:(GNCOpenL2CAPServerCompletionHandler)completionHandler diff --git a/internal/platform/implementation/apple/Mediums/BLEv2/GNCBLEMedium.m b/internal/platform/implementation/apple/Mediums/BLEv2/GNCBLEMedium.m index bf92971d..c60d0771 100644 --- a/internal/platform/implementation/apple/Mediums/BLEv2/GNCBLEMedium.m +++ b/internal/platform/implementation/apple/Mediums/BLEv2/GNCBLEMedium.m @@ -170,6 +170,16 @@ static GNCBLEL2CAPServer *_Nonnull CreateL2CapServer( }); } +- (void)resumeMediumScanning: + (nullable GNCStartScanningCompletionHandler)completionHandler { + dispatch_async(_queue, ^{ + [self internalStartScanningIfPoweredOn]; + if (completionHandler) { + completionHandler(nil); + } + }); +} + - (void)startGATTServerWithCompletionHandler: (nullable GNCGATTServerCompletionHandler)completionHandler { dispatch_async(_queue, ^{ diff --git a/internal/platform/implementation/apple/ble_medium.h b/internal/platform/implementation/apple/ble_medium.h index a8d5a611..c7a6c4f5 100644 --- a/internal/platform/implementation/apple/ble_medium.h +++ b/internal/platform/implementation/apple/ble_medium.h @@ -97,6 +97,16 @@ class BleMedium : public api::ble_v2::BleMedium { // Returns whether or not scanning was successfully stopped. bool StopScanning() override; + // Pauses BLE scanning at platform Medium level. + // + // Returns whether or not scanning was successfully paused. + bool PauseMediumScanning() override; + + // Resumes BLE scanning at platform Medium level. + // + // Returns whether or not scanning was successfully resumed. + bool ResumeMediumScanning() override; + // TODO(b/290385712): ServerGattConnectionCallback methods are not yet implemented. // // Starts a GATT server. Returns a nullptr upon error. diff --git a/internal/platform/implementation/apple/ble_medium.mm b/internal/platform/implementation/apple/ble_medium.mm index 5e154e52..2efefa21 100644 --- a/internal/platform/implementation/apple/ble_medium.mm +++ b/internal/platform/implementation/apple/ble_medium.mm @@ -266,6 +266,24 @@ bool BleMedium::StopScanning() { return blockError == nil; } +bool BleMedium::PauseMediumScanning() { + return StopScanning(); +} + +bool BleMedium::ResumeMediumScanning() { + dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); + __block NSError *blockError = nil; + [medium_ resumeMediumScanning:^(NSError *error) { + if (error != nil) { + GTMLoggerError(@"Failed to start scanning for multiple services: %@", error); + blockError = error; + } + dispatch_semaphore_signal(semaphore); + }]; + dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); + return blockError == nil; +} + // TODO(b/290385712): Add implementation that calls ServerGattConnectionCallback methods. std::unique_ptr BleMedium::StartGattServer( api::ble_v2::ServerGattConnectionCallback callback) { diff --git a/internal/platform/implementation/ble_v2.h b/internal/platform/implementation/ble_v2.h index fb6417f8..6ca3d9a7 100644 --- a/internal/platform/implementation/ble_v2.h +++ b/internal/platform/implementation/ble_v2.h @@ -512,6 +512,10 @@ class BleMedium { // Stops scanning. virtual bool StopScanning() = 0; + virtual bool PauseMediumScanning() { return true; } + + virtual bool ResumeMediumScanning() { return true; } + struct ScanningSession { absl::AnyInvocable stop_scanning; };