mirror of
https://github.com/kidfromjupiter/nearby.git
synced 2026-09-14 14:46:12 -04:00
Introduce factory patterns for BLE managers in BleMedium.
PiperOrigin-RevId: 897492346
This commit is contained in:
committed by
Copybara-Service
parent
ef166b6534
commit
26efd91ff4
@@ -47,11 +47,13 @@ namespace apple {
|
||||
|
||||
class BleMediumPeer {
|
||||
public:
|
||||
static void SetSocketCentralManager(BleMedium *ble_medium, GNSCentralManager *manager) {
|
||||
ble_medium->socketCentralManager_ = manager;
|
||||
static void SetPeripheralManagerFactory(BleMedium *ble_medium,
|
||||
BleMedium::PeripheralManagerFactory factory) {
|
||||
ble_medium->peripheral_manager_factory_ = std::move(factory);
|
||||
}
|
||||
static void SetSocketPeripheralManager(BleMedium *ble_medium, GNSPeripheralManager *manager) {
|
||||
ble_medium->socketPeripheralManager_ = manager;
|
||||
static void SetCentralManagerFactory(BleMedium *ble_medium,
|
||||
BleMedium::CentralManagerFactory factory) {
|
||||
ble_medium->central_manager_factory_ = std::move(factory);
|
||||
}
|
||||
static GNSPeripheralServiceManager *GetSocketPeripheralServiceManager(BleMedium *ble_medium) {
|
||||
return ble_medium->socketPeripheralServiceManager_;
|
||||
@@ -88,6 +90,28 @@ static const char *const kTestServiceID = "TestServiceID";
|
||||
[super tearDown];
|
||||
}
|
||||
|
||||
- (void)testOpenServerSocket_UsesFactoryForInitialization {
|
||||
__block BOOL factoryWasCalled = NO;
|
||||
id mockPeripheralManager = OCMClassMock([GNSPeripheralManager class]);
|
||||
OCMStub([mockPeripheralManager addPeripheralServiceManager:[OCMArg any]
|
||||
bleServiceAddedCompletion:[OCMArg any]])
|
||||
.andDo(^(GNSPeripheralManager *localSelf, GNSPeripheralServiceManager *manager,
|
||||
void (^completion)(NSError *error)) {
|
||||
completion(nil);
|
||||
});
|
||||
|
||||
nearby::apple::BleMediumPeer::SetPeripheralManagerFactory(_medium.get(), ^() {
|
||||
factoryWasCalled = YES;
|
||||
return mockPeripheralManager;
|
||||
});
|
||||
|
||||
// This call should trigger the factory inside BleMedium.
|
||||
auto server_socket = _medium->OpenServerSocket(kTestServiceID);
|
||||
|
||||
XCTAssertTrue(factoryWasCalled, @"BleMedium should have requested the manager from the factory.");
|
||||
XCTAssertNotEqual(server_socket.get(), nullptr);
|
||||
}
|
||||
|
||||
#pragma mark - Advertising Tests
|
||||
|
||||
- (void)testStartAdvertising_Success {
|
||||
@@ -431,7 +455,9 @@ static const char *const kTestServiceID = "TestServiceID";
|
||||
id mockCentralManager = OCMClassMock([GNSCentralManager class]);
|
||||
OCMStub([mockCentralManager retrieveCentralPeerWithIdentifier:fakePeripheral.identifier])
|
||||
.andReturn(nil);
|
||||
nearby::apple::BleMediumPeer::SetSocketCentralManager(_medium.get(), mockCentralManager);
|
||||
nearby::apple::BleMediumPeer::SetCentralManagerFactory(_medium.get(), ^(CBUUID *uuid) {
|
||||
return mockCentralManager;
|
||||
});
|
||||
|
||||
auto socket = _medium->Connect(kTestServiceID, nearby::api::ble::TxPowerLevel::kUltraLow,
|
||||
fakePeripheral.identifier.hash, nullptr);
|
||||
@@ -469,7 +495,9 @@ static const char *const kTestServiceID = "TestServiceID";
|
||||
id mockCentralManager = OCMClassMock([GNSCentralManager class]);
|
||||
OCMStub([mockCentralManager retrieveCentralPeerWithIdentifier:fakePeripheral.identifier])
|
||||
.andReturn(mockCentralPeerManager);
|
||||
nearby::apple::BleMediumPeer::SetSocketCentralManager(_medium.get(), mockCentralManager);
|
||||
nearby::apple::BleMediumPeer::SetCentralManagerFactory(_medium.get(), ^(CBUUID *uuid) {
|
||||
return mockCentralManager;
|
||||
});
|
||||
|
||||
auto socket = _medium->Connect(kTestServiceID, nearby::api::ble::TxPowerLevel::kUltraLow,
|
||||
fakePeripheral.identifier.hash, nullptr);
|
||||
@@ -490,7 +518,9 @@ static const char *const kTestServiceID = "TestServiceID";
|
||||
void (^completion)(NSError *error)) {
|
||||
completion(nil);
|
||||
});
|
||||
nearby::apple::BleMediumPeer::SetSocketPeripheralManager(_medium.get(), mockPeripheralManager);
|
||||
nearby::apple::BleMediumPeer::SetPeripheralManagerFactory(_medium.get(), ^() {
|
||||
return mockPeripheralManager;
|
||||
});
|
||||
|
||||
auto server_socket = _medium->OpenServerSocket(kTestServiceID);
|
||||
|
||||
@@ -512,7 +542,9 @@ static const char *const kTestServiceID = "TestServiceID";
|
||||
void (^completion)(NSError *error)) {
|
||||
completion(nil);
|
||||
});
|
||||
nearby::apple::BleMediumPeer::SetSocketPeripheralManager(_medium.get(), mockPeripheralManager);
|
||||
nearby::apple::BleMediumPeer::SetPeripheralManagerFactory(_medium.get(), ^() {
|
||||
return mockPeripheralManager;
|
||||
});
|
||||
|
||||
auto server_socket = _medium->OpenServerSocket(kTestServiceID);
|
||||
|
||||
@@ -534,7 +566,9 @@ static const char *const kTestServiceID = "TestServiceID";
|
||||
void (^completion)(NSError *error)) {
|
||||
completion(nil);
|
||||
});
|
||||
nearby::apple::BleMediumPeer::SetSocketPeripheralManager(_medium.get(), mockPeripheralManager);
|
||||
nearby::apple::BleMediumPeer::SetPeripheralManagerFactory(_medium.get(), ^() {
|
||||
return mockPeripheralManager;
|
||||
});
|
||||
|
||||
auto server_socket = _medium->OpenServerSocket(kTestServiceID);
|
||||
XCTAssertNotEqual(server_socket.get(), nullptr);
|
||||
@@ -570,9 +604,10 @@ static const char *const kTestServiceID = "TestServiceID";
|
||||
// Since we use dispatch_async internally for connection callback, give it a small amount of time
|
||||
// to process so we know it didn't crash.
|
||||
XCTestExpectation *expectation2 = [self expectationWithDescription:@"Wait for async execution"];
|
||||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
||||
[expectation2 fulfill];
|
||||
});
|
||||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)),
|
||||
dispatch_get_main_queue(), ^{
|
||||
[expectation2 fulfill];
|
||||
});
|
||||
[self waitForExpectations:@[ expectation2 ] timeout:1.0];
|
||||
}
|
||||
|
||||
@@ -584,7 +619,9 @@ static const char *const kTestServiceID = "TestServiceID";
|
||||
void (^completion)(NSError *error)) {
|
||||
completion([NSError errorWithDomain:@"test" code:0 userInfo:nil]);
|
||||
});
|
||||
nearby::apple::BleMediumPeer::SetSocketPeripheralManager(_medium.get(), mockPeripheralManager);
|
||||
nearby::apple::BleMediumPeer::SetPeripheralManagerFactory(_medium.get(), ^() {
|
||||
return mockPeripheralManager;
|
||||
});
|
||||
|
||||
auto server_socket = _medium->OpenServerSocket(kTestServiceID);
|
||||
|
||||
@@ -599,7 +636,9 @@ static const char *const kTestServiceID = "TestServiceID";
|
||||
void (^completion)(NSError *error)){
|
||||
// Do not call completion to simulate timeout.
|
||||
});
|
||||
nearby::apple::BleMediumPeer::SetSocketPeripheralManager(_medium.get(), mockPeripheralManager);
|
||||
nearby::apple::BleMediumPeer::SetPeripheralManagerFactory(_medium.get(), ^() {
|
||||
return mockPeripheralManager;
|
||||
});
|
||||
|
||||
auto server_socket = _medium->OpenServerSocket(kTestServiceID);
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@@ -50,6 +51,10 @@ class BleMedium : public api::ble::BleMedium {
|
||||
friend class BleMediumPeer;
|
||||
|
||||
public:
|
||||
// Define factory types for managers.
|
||||
using PeripheralManagerFactory = std::function<GNSPeripheralManager *()>;
|
||||
using CentralManagerFactory = std::function<GNSCentralManager *(CBUUID *)>;
|
||||
|
||||
BleMedium();
|
||||
// For testing only.
|
||||
explicit BleMedium(GNCBLEMedium *medium);
|
||||
@@ -217,6 +222,10 @@ class BleMedium : public api::ble::BleMedium {
|
||||
// The executor for handling callbacks.
|
||||
apple::SingleThreadExecutor callback_executor_;
|
||||
|
||||
// Factories for lazy initialization
|
||||
PeripheralManagerFactory peripheral_manager_factory_ = nullptr;
|
||||
CentralManagerFactory central_manager_factory_ = nullptr;
|
||||
|
||||
GNCBLEMedium *medium_;
|
||||
|
||||
PeripheralsMap peripherals_;
|
||||
|
||||
@@ -193,7 +193,11 @@ std::unique_ptr<api::ble::BleMedium::ScanningSession> BleMedium::StartScanning(
|
||||
peripherals_.Clear();
|
||||
ClearAdvertisementPacketsMap();
|
||||
|
||||
socketCentralManager_ = [[GNSCentralManager alloc] initWithSocketServiceUUID:serviceUUID];
|
||||
if (central_manager_factory_) {
|
||||
socketCentralManager_ = central_manager_factory_(serviceUUID);
|
||||
} else {
|
||||
socketCentralManager_ = [[GNSCentralManager alloc] initWithSocketServiceUUID:serviceUUID];
|
||||
}
|
||||
[socketCentralManager_ startNoScanModeWithAdvertisedServiceUUIDs:@[ serviceUUID ]];
|
||||
|
||||
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
|
||||
@@ -247,7 +251,11 @@ bool BleMedium::StartScanning(const Uuid &service_uuid, api::ble::TxPowerLevel t
|
||||
peripherals_.Clear();
|
||||
ClearAdvertisementPacketsMap();
|
||||
|
||||
socketCentralManager_ = [[GNSCentralManager alloc] initWithSocketServiceUUID:serviceUUID];
|
||||
if (central_manager_factory_) {
|
||||
socketCentralManager_ = central_manager_factory_(serviceUUID);
|
||||
} else {
|
||||
socketCentralManager_ = [[GNSCentralManager alloc] initWithSocketServiceUUID:serviceUUID];
|
||||
}
|
||||
[socketCentralManager_ startNoScanModeWithAdvertisedServiceUUIDs:@[ serviceUUID ]];
|
||||
|
||||
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
|
||||
@@ -294,7 +302,11 @@ bool BleMedium::StartMultipleServicesScanning(const std::vector<Uuid> &service_u
|
||||
peripherals_.Clear();
|
||||
ClearAdvertisementPacketsMap();
|
||||
|
||||
socketCentralManager_ = [[GNSCentralManager alloc] initWithSocketServiceUUID:serviceUUIDs[0]];
|
||||
if (central_manager_factory_) {
|
||||
socketCentralManager_ = central_manager_factory_(serviceUUIDs[0]);
|
||||
} else {
|
||||
socketCentralManager_ = [[GNSCentralManager alloc] initWithSocketServiceUUID:serviceUUIDs[0]];
|
||||
}
|
||||
[socketCentralManager_ startNoScanModeWithAdvertisedServiceUUIDs:@[ serviceUUIDs[0] ]];
|
||||
|
||||
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
|
||||
@@ -460,12 +472,12 @@ std::unique_ptr<api::ble::BleServerSocket> BleMedium::OpenServerSocketWithDeadlo
|
||||
auto server_socket = std::make_unique<BleServerSocket>();
|
||||
|
||||
if (socketPeripheralManager_ == nil) {
|
||||
socketPeripheralManager_ = [[GNSPeripheralManager alloc] initWithAdvertisedName:nil
|
||||
restoreIdentifier:nil];
|
||||
}
|
||||
if (socketPeripheralManager_ == nil) {
|
||||
GNCLoggerError(@"Failed to create peripheral manager.");
|
||||
return nullptr;
|
||||
if (peripheral_manager_factory_) {
|
||||
socketPeripheralManager_ = peripheral_manager_factory_();
|
||||
} else {
|
||||
socketPeripheralManager_ = [[GNSPeripheralManager alloc] initWithAdvertisedName:nil
|
||||
restoreIdentifier:nil];
|
||||
}
|
||||
}
|
||||
|
||||
// Fix for b/494335036 (Registry + Background Queue)
|
||||
@@ -543,12 +555,12 @@ std::unique_ptr<api::ble::BleServerSocket> BleMedium::OpenServerSocketLegacy(
|
||||
auto server_socket = std::make_unique<BleServerSocket>();
|
||||
|
||||
if (socketPeripheralManager_ == nil) {
|
||||
socketPeripheralManager_ = [[GNSPeripheralManager alloc] initWithAdvertisedName:nil
|
||||
restoreIdentifier:nil];
|
||||
}
|
||||
if (socketPeripheralManager_ == nil) {
|
||||
GNCLoggerError(@"Failed to create peripheral manager.");
|
||||
return nullptr;
|
||||
if (peripheral_manager_factory_) {
|
||||
socketPeripheralManager_ = peripheral_manager_factory_();
|
||||
} else {
|
||||
socketPeripheralManager_ = [[GNSPeripheralManager alloc] initWithAdvertisedName:nil
|
||||
restoreIdentifier:nil];
|
||||
}
|
||||
}
|
||||
|
||||
// Raw pointer for closure capture in the legacy path (risks use-after-free).
|
||||
|
||||
Reference in New Issue
Block a user