mirror of
https://github.com/kidfromjupiter/nearby.git
synced 2026-09-14 14:46:12 -04:00
Add stop advertising and stop scanning BLE implementation for Apple platforms
PiperOrigin-RevId: 559838443
This commit is contained in:
committed by
Copybara-Service
parent
387393f1d6
commit
91fb4a9a3e
@@ -19,11 +19,39 @@
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
* A block to be invoked when a call to
|
||||
* @c createCharacteristicWithServiceID:characteristicUUID:permissions:properties:completionHandler:
|
||||
* has completed.
|
||||
*
|
||||
* @param characteristic The created characteristic, or @c nil if an error occurred.
|
||||
* @param error The cause of the failure, or @c nil if no error occurred.
|
||||
*/
|
||||
typedef void (^GNCCreateCharacteristicCompletionHandler)(
|
||||
GNCBLEGATTCharacteristic *_Nullable characteristic, NSError *_Nullable error);
|
||||
|
||||
/**
|
||||
* A block to be invoked when a call to @c updateCharacteristic:value:completionHandler: has
|
||||
* completed.
|
||||
*
|
||||
* @param error The cause of the failure, or @c nil if no error occurred.
|
||||
*/
|
||||
typedef void (^GNCUpdateCharacteristicCompletionHandler)(NSError *_Nullable error);
|
||||
|
||||
/**
|
||||
* A block to be invoked when a call to @c startAdvertisingData:completionHandler: has completed.
|
||||
*
|
||||
* @param error The cause of the failure, or @c nil if no error occurred.
|
||||
*/
|
||||
typedef void (^GNCStartAdvertisingCompletionHandler)(NSError *_Nullable error);
|
||||
|
||||
/**
|
||||
* A block to be invoked when a call to @c stopAdvertisingWithcompletionHandler: has completed.
|
||||
*
|
||||
* @param error The cause of the failure, or @c nil if no error occurred.
|
||||
*/
|
||||
typedef void (^GNCStopAdvertisingCompletionHandler)(NSError *_Nullable error);
|
||||
|
||||
/**
|
||||
* An object that manages and advertises GATT characteritics.
|
||||
*
|
||||
@@ -82,6 +110,15 @@ typedef void (^GNCStartAdvertisingCompletionHandler)(NSError *_Nullable error);
|
||||
- (void)startAdvertisingData:(NSDictionary<CBUUID *, NSData *> *)serviceData
|
||||
completionHandler:(nullable GNCStartAdvertisingCompletionHandler)completionHandler;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
- (void)stopAdvertisingWithCompletionHandler:
|
||||
(nullable GNCStopAdvertisingCompletionHandler)completionHandler;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
@@ -223,6 +223,17 @@ static char *const kGNCBLEGATTServerQueueLabel = "com.nearby.GNCBLEGATTServer";
|
||||
});
|
||||
}
|
||||
|
||||
- (void)stopAdvertisingWithCompletionHandler:
|
||||
(nullable GNCStopAdvertisingCompletionHandler)completionHandler {
|
||||
dispatch_async(_queue, ^{
|
||||
_advertisementData = nil;
|
||||
[_peripheralManager stopAdvertising];
|
||||
if (completionHandler) {
|
||||
completionHandler(nil);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#pragma mark - Internal
|
||||
|
||||
- (void)internalAddPendingServicesIfPoweredOn {
|
||||
|
||||
@@ -30,6 +30,13 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
*/
|
||||
typedef void (^GNCStartAdvertisingCompletionHandler)(NSError *_Nullable error);
|
||||
|
||||
/**
|
||||
* A block to be invoked when a call to @c stopAdvertisingWithcompletionHandler: has completed.
|
||||
*
|
||||
* @param error The cause of the failure, or @c nil if no error occurred.
|
||||
*/
|
||||
typedef void (^GNCStopAdvertisingCompletionHandler)(NSError *_Nullable error);
|
||||
|
||||
/**
|
||||
* A block to be invoked when a peripheral’s advertisement has been discovered.
|
||||
*
|
||||
@@ -50,6 +57,13 @@ typedef void (^GNCAdvertisementFoundHandler)(id<GNCPeripheral> peripheral,
|
||||
*/
|
||||
typedef void (^GNCStartScanningCompletionHandler)(NSError *_Nullable error);
|
||||
|
||||
/**
|
||||
* A block to be invoked when a call to @c stopScanningWithCompletionHandler: has completed.
|
||||
*
|
||||
* @param error The cause of the failure, or @c nil if no error occurred.
|
||||
*/
|
||||
typedef void (^GNCStopScanningCompletionHandler)(NSError *_Nullable error);
|
||||
|
||||
/**
|
||||
* A block to be invoked when a call to @c startGATTServerWithCompletionHandler: has completed.
|
||||
*
|
||||
@@ -100,6 +114,15 @@ typedef void (^GNCGATTConnectionCompletionHandler)(GNCBLEGATTClient *_Nullable c
|
||||
- (void)startAdvertisingData:(NSDictionary<CBUUID *, NSData *> *)serviceData
|
||||
completionHandler:(nullable GNCStartAdvertisingCompletionHandler)completionHandler;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
- (void)stopAdvertisingWithCompletionHandler:
|
||||
(nullable GNCStopAdvertisingCompletionHandler)completionHandler;
|
||||
|
||||
/**
|
||||
* Scans for peripherals that are advertising the specified service.
|
||||
*
|
||||
@@ -112,6 +135,15 @@ typedef void (^GNCGATTConnectionCompletionHandler)(GNCBLEGATTClient *_Nullable c
|
||||
advertisementFoundHandler:(GNCAdvertisementFoundHandler)advertisementFoundHandler
|
||||
completionHandler:(nullable GNCStartScanningCompletionHandler)completionHandler;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
- (void)stopScanningWithCompletionHandler:
|
||||
(nullable GNCStopScanningCompletionHandler)completionHandler;
|
||||
|
||||
/**
|
||||
* Starts a GATT server.
|
||||
*
|
||||
|
||||
@@ -101,6 +101,19 @@ static NSError *AlreadyScanningError() {
|
||||
});
|
||||
}
|
||||
|
||||
- (void)stopAdvertisingWithCompletionHandler:
|
||||
(nullable GNCStopAdvertisingCompletionHandler)completionHandler {
|
||||
dispatch_async(_queue, ^{
|
||||
if (!_server) {
|
||||
if (completionHandler) {
|
||||
completionHandler(nil);
|
||||
}
|
||||
return;
|
||||
}
|
||||
[_server stopAdvertisingWithCompletionHandler:completionHandler];
|
||||
});
|
||||
}
|
||||
|
||||
- (void)startScanningForService:(CBUUID *)serviceUUID
|
||||
advertisementFoundHandler:(GNCAdvertisementFoundHandler)advertisementFoundHandler
|
||||
completionHandler:(nullable GNCStartScanningCompletionHandler)completionHandler {
|
||||
@@ -122,6 +135,18 @@ static NSError *AlreadyScanningError() {
|
||||
});
|
||||
}
|
||||
|
||||
- (void)stopScanningWithCompletionHandler:
|
||||
(nullable GNCStopScanningCompletionHandler)completionHandler {
|
||||
dispatch_async(_queue, ^{
|
||||
_serviceUUID = nil;
|
||||
_advertisementFoundHandler = nil;
|
||||
[_centralManager stopScan];
|
||||
if (completionHandler) {
|
||||
completionHandler(nil);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
- (void)startGATTServerWithCompletionHandler:
|
||||
(nullable GNCGATTServerCompletionHandler)completionHandler {
|
||||
dispatch_async(_queue, ^{
|
||||
|
||||
@@ -614,4 +614,44 @@ static NSString *const kCharacteristicUUID2 = @"00000000-0000-3000-8000-00000000
|
||||
[self waitForExpectations:@[ expectation ] timeout:3];
|
||||
}
|
||||
|
||||
- (void)testStartStopStartAdvertising {
|
||||
GNCFakePeripheralManager *fakePeripheralManager = [[GNCFakePeripheralManager alloc] init];
|
||||
|
||||
GNCBLEGATTServer *gattServer =
|
||||
[[GNCBLEGATTServer alloc] initWithPeripheralManager:fakePeripheralManager];
|
||||
|
||||
[fakePeripheralManager simulatePeripheralManagerDidUpdateState:CBManagerStatePoweredOn];
|
||||
|
||||
XCTestExpectation *expectation =
|
||||
[[XCTestExpectation alloc] initWithDescription:@"Start advertising."];
|
||||
|
||||
[gattServer startAdvertisingData:@{[CBUUID UUIDWithString:@"FEF3"] : [NSData data]}
|
||||
completionHandler:^(NSError *error) {
|
||||
XCTAssertNil(error);
|
||||
XCTAssertTrue(fakePeripheralManager.isAdvertising);
|
||||
NSDictionary<NSString *, id> *data = fakePeripheralManager.advertisementData;
|
||||
XCTAssertEqualObjects(data[CBAdvertisementDataLocalNameKey], @"");
|
||||
XCTAssertEqualObjects(data[CBAdvertisementDataServiceUUIDsKey][0],
|
||||
[CBUUID UUIDWithString:@"FEF3"]);
|
||||
[gattServer stopAdvertisingWithCompletionHandler:^(NSError *error) {
|
||||
XCTAssertNil(error);
|
||||
XCTAssertFalse(fakePeripheralManager.isAdvertising);
|
||||
[gattServer
|
||||
startAdvertisingData:@{[CBUUID UUIDWithString:@"FEF4"] : [NSData data]}
|
||||
completionHandler:^(NSError *error) {
|
||||
XCTAssertNil(error);
|
||||
XCTAssertTrue(fakePeripheralManager.isAdvertising);
|
||||
NSDictionary<NSString *, id> *data =
|
||||
fakePeripheralManager.advertisementData;
|
||||
XCTAssertEqualObjects(data[CBAdvertisementDataLocalNameKey], @"");
|
||||
XCTAssertEqualObjects(data[CBAdvertisementDataServiceUUIDsKey][0],
|
||||
[CBUUID UUIDWithString:@"FEF4"]);
|
||||
[expectation fulfill];
|
||||
}];
|
||||
}];
|
||||
}];
|
||||
|
||||
[self waitForExpectations:@[ expectation ] timeout:3];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -106,6 +106,36 @@ static NSString *const kServiceUUID = @"0000FEF3-0000-1000-8000-00805F9B34FB";
|
||||
[self waitForExpectations:@[ expectation ] timeout:3];
|
||||
}
|
||||
|
||||
- (void)testStartStopStartScanning {
|
||||
GNCFakeCentralManager *fakeCentralManager = [[GNCFakeCentralManager alloc] init];
|
||||
GNCBLEMedium *medium = [[GNCBLEMedium alloc] initWithCentralManager:fakeCentralManager queue:nil];
|
||||
XCTestExpectation *expectation =
|
||||
[[XCTestExpectation alloc] initWithDescription:@"Start scanning."];
|
||||
|
||||
CBUUID *serviceUUID = [CBUUID UUIDWithString:kServiceUUID];
|
||||
|
||||
[medium startScanningForService:serviceUUID
|
||||
advertisementFoundHandler:^(id<GNCPeripheral> peripheral,
|
||||
NSDictionary<CBUUID *, NSData *> *data) {
|
||||
}
|
||||
completionHandler:^(NSError *error) {
|
||||
XCTAssertNil(error);
|
||||
[medium stopScanningWithCompletionHandler:^(NSError *error) {
|
||||
XCTAssertNil(error);
|
||||
[medium startScanningForService:serviceUUID
|
||||
advertisementFoundHandler:^(id<GNCPeripheral> peripheral,
|
||||
NSDictionary<CBUUID *, NSData *> *data) {
|
||||
}
|
||||
completionHandler:^(NSError *error) {
|
||||
XCTAssertNil(error);
|
||||
[expectation fulfill];
|
||||
}];
|
||||
}];
|
||||
}];
|
||||
|
||||
[self waitForExpectations:@[ expectation ] timeout:3];
|
||||
}
|
||||
|
||||
#pragma mark - Decode Advertisement Data
|
||||
|
||||
- (void)testDecodeAndroidStyleAdvertisementData {
|
||||
@@ -226,6 +256,22 @@ static NSString *const kServiceUUID = @"0000FEF3-0000-1000-8000-00805F9B34FB";
|
||||
[self waitForExpectations:@[ expectation ] timeout:3];
|
||||
}
|
||||
|
||||
- (void)testStopAdvertising {
|
||||
GNCFakeCentralManager *fakeCentralManager = [[GNCFakeCentralManager alloc] init];
|
||||
GNCBLEMedium *medium = [[GNCBLEMedium alloc] initWithCentralManager:fakeCentralManager queue:nil];
|
||||
XCTestExpectation *expectation =
|
||||
[[XCTestExpectation alloc] initWithDescription:@"Stop advertising."];
|
||||
|
||||
// Stop advertising is fully covered with @c GNCBLEGATTServer tests. We are only testing stopping
|
||||
// without having started which tests the code paths relevant to @c GNCBLEMedium.
|
||||
[medium stopAdvertisingWithCompletionHandler:^(NSError *error) {
|
||||
XCTAssertNil(error);
|
||||
[expectation fulfill];
|
||||
}];
|
||||
|
||||
[self waitForExpectations:@[ expectation ] timeout:3];
|
||||
}
|
||||
|
||||
#pragma mark - Connect
|
||||
|
||||
- (void)testSuccessfulConnect {
|
||||
|
||||
@@ -119,6 +119,7 @@
|
||||
}
|
||||
|
||||
- (void)stopAdvertising {
|
||||
_isAdvertising = false;
|
||||
}
|
||||
|
||||
#pragma mark - Testing Helpers
|
||||
|
||||
@@ -67,8 +67,6 @@ class BleMedium : public api::ble_v2::BleMedium {
|
||||
bool StartAdvertising(const api::ble_v2::BleAdvertisementData &advertising_data,
|
||||
api::ble_v2::AdvertiseParameters advertise_set_parameters) override;
|
||||
|
||||
// TODO(b/290385712): Not yet implemented.
|
||||
//
|
||||
// Stops advertising.
|
||||
//
|
||||
// Returns whether or not advertising was successfully stopped.
|
||||
@@ -92,8 +90,6 @@ class BleMedium : public api::ble_v2::BleMedium {
|
||||
bool StartScanning(const Uuid &service_uuid, api::ble_v2::TxPowerLevel tx_power_level,
|
||||
api::ble_v2::BleMedium::ScanCallback callback) override;
|
||||
|
||||
// TODO(b/290385712): Not yet implemented.
|
||||
//
|
||||
// Stops scanning.
|
||||
//
|
||||
// Returns whether or not scanning was successfully stopped.
|
||||
|
||||
@@ -87,8 +87,19 @@ bool BleMedium::StartAdvertising(const api::ble_v2::BleAdvertisementData &advert
|
||||
return blockError == nil;
|
||||
}
|
||||
|
||||
// TODO(b/290385712): Implement.
|
||||
bool BleMedium::StopAdvertising() { return false; }
|
||||
bool BleMedium::StopAdvertising() {
|
||||
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
|
||||
__block NSError *blockError = nil;
|
||||
[medium_ stopAdvertisingWithCompletionHandler:^(NSError *error) {
|
||||
if (error != nil) {
|
||||
GTMLoggerError(@"Failed to stop advertising: %@", error);
|
||||
}
|
||||
blockError = error;
|
||||
dispatch_semaphore_signal(semaphore);
|
||||
}];
|
||||
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
|
||||
return blockError == nil;
|
||||
}
|
||||
|
||||
// TODO(b/290385712): Implement.
|
||||
std::unique_ptr<api::ble_v2::BleMedium::ScanningSession> BleMedium::StartScanning(
|
||||
@@ -139,8 +150,19 @@ bool BleMedium::StartScanning(const Uuid &service_uuid, api::ble_v2::TxPowerLeve
|
||||
return blockError == nil;
|
||||
}
|
||||
|
||||
// TODO(b/290385712): Implement.
|
||||
bool BleMedium::StopScanning() { return false; }
|
||||
bool BleMedium::StopScanning() {
|
||||
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
|
||||
__block NSError *blockError = nil;
|
||||
[medium_ stopScanningWithCompletionHandler:^(NSError *error) {
|
||||
if (error != nil) {
|
||||
GTMLoggerError(@"Failed to stop scanning: %@", 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<api::ble_v2::GattServer> BleMedium::StartGattServer(
|
||||
|
||||
Reference in New Issue
Block a user