diff --git a/internal/platform/implementation/apple/Mediums/BLEv2/GNCBLEMedium.h b/internal/platform/implementation/apple/Mediums/BLEv2/GNCBLEMedium.h index b95790a9..65a8e633 100644 --- a/internal/platform/implementation/apple/Mediums/BLEv2/GNCBLEMedium.h +++ b/internal/platform/implementation/apple/Mediums/BLEv2/GNCBLEMedium.h @@ -238,6 +238,11 @@ typedef void (^GNCGATTConnectionCompletionHandler)(GNCBLEGATTClient *_Nullable c peripheral:(id)remotePeripheral completionHandler:(nullable GNCOpenL2CAPStreamCompletionHandler)completionHandler; +/** + * Stops all BLE operations. + */ +- (void)stop; + @end NS_ASSUME_NONNULL_END diff --git a/internal/platform/implementation/apple/Mediums/BLEv2/GNCBLEMedium.m b/internal/platform/implementation/apple/Mediums/BLEv2/GNCBLEMedium.m index 283620d2..0e14d94b 100644 --- a/internal/platform/implementation/apple/Mediums/BLEv2/GNCBLEMedium.m +++ b/internal/platform/implementation/apple/Mediums/BLEv2/GNCBLEMedium.m @@ -34,6 +34,7 @@ NS_ASSUME_NONNULL_BEGIN static char *const kBLEMediumQueueLabel = "com.nearby.GNCBLEMedium"; // TODO: b/762454867 - Make this a flag. static const NSTimeInterval kPeripheralConnectTimeout = 10.0; // 10 seconds timeout +static const NSTimeInterval kStopTimeout = 5.0; static NSError *AlreadyScanningError() { return [NSError errorWithDomain:GNCBLEErrorDomain code:GNCBLEErrorAlreadyScanning userInfo:nil]; @@ -122,8 +123,17 @@ static GNCBLEL2CAPServer *_Nonnull CreateL2CapServer( return self; } -- (void)dealloc { - [self cancelConnectionTimeout]; +- (void)stop { + dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); + dispatch_async(_queue, ^{ + [self cancelConnectionTimeout]; + dispatch_semaphore_signal(semaphore); + }); + dispatch_time_t timeout = + dispatch_time(DISPATCH_TIME_NOW, kStopTimeout * NSEC_PER_SEC); // 5 seconds timeout + if (dispatch_semaphore_wait(semaphore, timeout) != 0) { + GNCLoggerError(@"GNCBLEMedium stop timeout."); + } } - (BOOL)supportsExtendedAdvertisements { diff --git a/internal/platform/implementation/apple/Tests/GNCPlatformTest.mm b/internal/platform/implementation/apple/Tests/GNCPlatformTest.mm index 322d0725..72467db7 100644 --- a/internal/platform/implementation/apple/Tests/GNCPlatformTest.mm +++ b/internal/platform/implementation/apple/Tests/GNCPlatformTest.mm @@ -80,4 +80,10 @@ void GNCEnsureFileAtPath(std::string path) { XCTAssertEqualObjects(@(actual.c_str()), expected); } +- (void)testCreateBleV2Medium { + auto bluetooth_adapter = nearby::api::ImplementationPlatform::CreateBluetoothAdapter(); + auto ble_medium = nearby::api::ImplementationPlatform::CreateBleV2Medium(*bluetooth_adapter); + XCTAssertNotEqual(ble_medium.get(), nullptr); +} + @end diff --git a/internal/platform/implementation/apple/ble_medium.h b/internal/platform/implementation/apple/ble_medium.h index 6520221e..bc86ebcd 100644 --- a/internal/platform/implementation/apple/ble_medium.h +++ b/internal/platform/implementation/apple/ble_medium.h @@ -47,7 +47,7 @@ namespace apple { class BleMedium : public api::ble_v2::BleMedium { public: BleMedium(); - ~BleMedium() override = default; + ~BleMedium() override; // Async interface for StartAdvertising. // diff --git a/internal/platform/implementation/apple/ble_medium.mm b/internal/platform/implementation/apple/ble_medium.mm index 96071ed8..1c9277b2 100644 --- a/internal/platform/implementation/apple/ble_medium.mm +++ b/internal/platform/implementation/apple/ble_medium.mm @@ -82,6 +82,9 @@ NSString *ConvertDataToHexString(NSData *data) { BleMedium::BleMedium() : medium_([[GNCBLEMedium alloc] init]) {} +// ble_medium.mm +BleMedium::~BleMedium() { [medium_ stop]; } + std::unique_ptr BleMedium::StartAdvertising( const api::ble_v2::BleAdvertisementData &advertising_data, api::ble_v2::AdvertiseParameters advertise_set_parameters,