Skip to content

Commit bf2a4f1

Browse files
lawrencelomaxfacebook-github-bot
authored andcommitted
Permit discovery of booted but unpaired devices
Summary: There is a circumstance where we will ignore the `AMDevice` value for a booted device that is only ever then represented by an `AMRestorableDevice`. This occurs because "pairing" is always validated when obtaining `AMDevice` values. This is undesirable as it prevents us from being able to pull out values like the UDID for a device that we otherwise could do. Instead, it makes more sense to fetch the values here and to flag the device as unpaired. Starting pairing with a session is still preferred as this provides more values than just a simple "Connect" call so we attempt to do so if possible. Performing a session w/ pairing means that we obtain information such as the backup info, amongst others Because of the lack of pairing, operations later on will fail but in an informative way. There will be pairing failure messages in these eventualities which is vastly preferrable to the device "dissapearing" Reviewed By: abesto Differential Revision: D25494639 fbshipit-source-id: c21e20cc570170a889d45ef8dfde2edfd2757d35
1 parent be17e41 commit bf2a4f1

File tree

2 files changed

+118
-60
lines changed

2 files changed

+118
-60
lines changed

FBDeviceControl/Management/FBAMDeviceManager.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,10 @@ NS_ASSUME_NONNULL_BEGIN
3232
- (instancetype)initWithCalls:(AMDCalls)calls workQueue:(dispatch_queue_t)workQueue asyncQueue:(dispatch_queue_t)asyncQueue ecidFilter:(NSString *)ecidFilter logger:(id<FBControlCoreLogger>)logger;
3333

3434
/**
35-
Starts using the AMDeviceRef via Connections.
35+
Starts using the AMDeviceRef by doing the following:
36+
- Starts a Connection with the device
37+
- Performing and validating pairing.
38+
- Starts a session.
3639
3740
@param device the device to use.
3841
@param calls the calls to use.
@@ -44,6 +47,8 @@ NS_ASSUME_NONNULL_BEGIN
4447

4548
/**
4649
Stops using the AMDeviceRef connections.
50+
- Stops the session with the device.
51+
- Stops the connection with the device.
4752
4853
@param device the device to use.
4954
@param calls the calls to use.

FBDeviceControl/Management/FBAMDeviceManager.m

Lines changed: 112 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,12 @@
1616

1717
@interface FBAMDeviceManager ()
1818

19+
+ (BOOL)startConnectionToDevice:(AMDeviceRef)device calls:(AMDCalls)calls logger:(id<FBControlCoreLogger>)logger error:(NSError **)error;
20+
+ (BOOL)startSessionByPairingWithDevice:(AMDeviceRef)device calls:(AMDCalls)calls logger:(id<FBControlCoreLogger>)logger error:(NSError **)error;
21+
+ (BOOL)stopConnectionToDevice:(AMDeviceRef)device calls:(AMDCalls)calls logger:(id<FBControlCoreLogger>)logger error:(NSError **)error;
22+
+ (BOOL)stopSessionWithDevice:(AMDeviceRef)device calls:(AMDCalls)calls logger:(id<FBControlCoreLogger>)logger error:(NSError **)error;
23+
24+
1925
@property (nonatomic, strong, readonly) dispatch_queue_t workQueue;
2026
@property (nonatomic, strong, readonly) dispatch_queue_t asyncQueue;
2127
@property (nonatomic, assign, readonly) AMDCalls calls;
@@ -31,27 +37,42 @@ static BOOL FB_AMDeviceConnected(AMDeviceRef device, FBAMDeviceManager *manager)
3137
NSError *error = nil;
3238
id<FBControlCoreLogger> logger = manager.logger;
3339
AMDCalls calls = manager.calls;
34-
if (![FBAMDeviceManager startUsing:device calls:calls logger:logger error:&error]) {
35-
[logger.error logFormat:@"Cannot start session with device, ignoring device %@", error];
40+
41+
// Start with a basic connection. This should always succeed, even if the device is not paired.
42+
if (![FBAMDeviceManager startConnectionToDevice:device calls:calls logger:logger error:&error]) {
43+
[logger.error logFormat:@"Cannot connect to device, ignoring device %@", error];
3644
return NO;
3745
}
3846
NSString *uniqueChipID = [CFBridgingRelease(calls.CopyValue(device, NULL, (__bridge CFStringRef)(FBDeviceKeyUniqueChipID))) stringValue];
3947
if (!uniqueChipID) {
40-
[FBAMDeviceManager stopUsing:device calls:calls logger:logger error:nil];
48+
[FBAMDeviceManager stopConnectionToDevice:device calls:calls logger:logger error:nil];
4149
[logger.error logFormat:@"Ignoring device as cannot obtain ECID for it"];
4250
return NO;
4351
}
4452
if (manager.ecidFilter && ![uniqueChipID isEqualToString:manager.ecidFilter]) {
45-
[FBAMDeviceManager stopUsing:device calls:calls logger:logger error:nil];
53+
[FBAMDeviceManager stopConnectionToDevice:device calls:calls logger:logger error:nil];
4654
[logger.error logFormat:@"Ignoring device as ECID %@ does not match filter %@", uniqueChipID, manager.ecidFilter];
4755
return NO;
4856
}
49-
// Get the values from the default domain.
57+
58+
NSError *pairingError = nil;
59+
BOOL pairedWithSession = [FBAMDeviceManager startSessionByPairingWithDevice:device calls:calls logger:logger error:&pairingError];
60+
if (!pairedWithSession) {
61+
[logger logFormat:@"Device is not paired, degraded device information will be provied %@", pairingError];
62+
}
63+
64+
// Get the values from the default domain, this will obtain information regardless of whether pairing was successful or not.
5065
NSMutableDictionary<NSString *, id> *info = [CFBridgingRelease(calls.CopyValue(device, NULL, NULL)) mutableCopy];
51-
// Get values from mobile backup.
66+
// Get values from mobile backup, this will only return meaningful information if paired.
5267
NSDictionary<NSString *, id> * backupInfo = [CFBridgingRelease(calls.CopyValue(device, (__bridge CFStringRef)(MobileBackupDomain), NULL)) copy] ?: @{};
53-
// We're done with getting the device values.
54-
[FBAMDeviceManager stopUsing:device calls:calls logger:logger error:nil];
68+
69+
// Stop the session if one was created.
70+
if (pairedWithSession) {
71+
[FBAMDeviceManager stopSessionWithDevice:device calls:calls logger:logger error:nil];
72+
}
73+
// Always disconnect, regardless of whether there was a session or not.
74+
[FBAMDeviceManager stopConnectionToDevice:device calls:calls logger:logger error:nil];
75+
5576
if (!info) {
5677
[logger.error log:@"Ignoring device as no values were returned for it"];
5778
return NO;
@@ -119,66 +140,25 @@ - (instancetype)initWithCalls:(AMDCalls)calls workQueue:(dispatch_queue_t)workQu
119140

120141
+ (BOOL)startUsing:(AMDeviceRef)device calls:(AMDCalls)calls logger:(id<FBControlCoreLogger>)logger error:(NSError **)error
121142
{
122-
if (device == NULL) {
123-
return [[FBDeviceControlError
124-
describe:@"Cannot utilize a non existent AMDeviceRef"]
125-
failBool:error];
126-
}
127-
128-
[logger logFormat:@"Connecting to %@", device];
129-
int status = calls.Connect(device);
130-
if (status != 0) {
131-
NSString *errorDescription = CFBridgingRelease(calls.CopyErrorText(status));
132-
return [[FBDeviceControlError
133-
describeFormat:@"Failed to connect to %@. (%@)", device, errorDescription]
134-
failBool:error];
135-
}
136-
137-
[logger logFormat:@"Checking whether %@ is paired", device];
138-
if (!calls.IsPaired(device)) {
139-
[logger logFormat:@"%@ is not paired, attempting to pair", device];
140-
status = calls.Pair(device);
141-
if (status != 0) {
142-
NSString *errorDescription = CFBridgingRelease(calls.CopyErrorText(status));
143-
return [[FBDeviceControlError
144-
describeFormat:@"%@ is not paired with this host %@", device, errorDescription]
145-
failBool:error];
146-
}
147-
[logger logFormat:@"%@ succeeded pairing request", device];
148-
}
149-
150-
[logger logFormat:@"Validating Pairing to %@", device];
151-
status = calls.ValidatePairing(device);
152-
if (status != 0) {
153-
NSString *errorDescription = CFBridgingRelease(calls.CopyErrorText(status));
154-
return [[FBDeviceControlError
155-
describeFormat:@"Failed to validate pairing for %@. (%@)", device, errorDescription]
156-
failBool:error];
143+
// Connect first
144+
if (![self startConnectionToDevice:device calls:calls logger:logger error:error]) {
145+
return NO;
157146
}
158-
159-
[logger logFormat:@"Starting Session on %@", device];
160-
status = calls.StartSession(device);
161-
if (status != 0) {
162-
calls.Disconnect(device);
163-
NSString *errorDescription = CFBridgingRelease(calls.CopyErrorText(status));
164-
return [[FBDeviceControlError
165-
describeFormat:@"Failed to start session with device. (%@)", errorDescription]
166-
failBool:error];
147+
// Confirm pairing and start a session
148+
if (![self startSessionByPairingWithDevice:device calls:calls logger:logger error:error]) {
149+
return NO;
167150
}
168-
169151
[logger logFormat:@"%@ ready for use", device];
170152
return YES;
171153
}
172154

173155
+ (BOOL)stopUsing:(AMDeviceRef)device calls:(AMDCalls)calls logger:(id<FBControlCoreLogger>)logger error:(NSError **)error
174156
{
175-
[logger logFormat:@"Stopping Session on %@", device];
176-
calls.StopSession(device);
157+
// Stop the session first.
158+
[self stopSessionWithDevice:device calls:calls logger:logger error:nil];
177159

178-
[logger logFormat:@"Disconnecting from %@", device];
179-
calls.Disconnect(device);
180-
181-
[logger logFormat:@"Disconnected from %@", device];
160+
// Then the connection.
161+
[self stopConnectionToDevice:device calls:calls logger:logger error:nil];
182162

183163
return YES;
184164
}
@@ -268,4 +248,77 @@ - (NSString *)identifierForDevice:(AMDeviceRef)amDevice
268248
return nil;
269249
}
270250

251+
+ (BOOL)startConnectionToDevice:(AMDeviceRef)device calls:(AMDCalls)calls logger:(id<FBControlCoreLogger>)logger error:(NSError **)error
252+
{
253+
if (device == NULL) {
254+
return [[FBDeviceControlError
255+
describe:@"Cannot utilize a non existent AMDeviceRef"]
256+
failBool:error];
257+
}
258+
259+
[logger logFormat:@"Connecting to %@", device];
260+
int status = calls.Connect(device);
261+
if (status != 0) {
262+
NSString *errorDescription = CFBridgingRelease(calls.CopyErrorText(status));
263+
return [[FBDeviceControlError
264+
describeFormat:@"Failed to connect to %@. (%@)", device, errorDescription]
265+
failBool:error];
266+
}
267+
return YES;
268+
}
269+
270+
+ (BOOL)startSessionByPairingWithDevice:(AMDeviceRef)device calls:(AMDCalls)calls logger:(id<FBControlCoreLogger>)logger error:(NSError **)error
271+
{
272+
// Then confirm the pairing.
273+
[logger logFormat:@"Checking whether %@ is paired", device];
274+
if (!calls.IsPaired(device)) {
275+
[logger logFormat:@"%@ is not paired, attempting to pair", device];
276+
int status = calls.Pair(device);
277+
if (status != 0) {
278+
NSString *errorDescription = CFBridgingRelease(calls.CopyErrorText(status));
279+
return [[FBDeviceControlError
280+
describeFormat:@"%@ is not paired with this host %@", device, errorDescription]
281+
failBool:error];
282+
}
283+
[logger logFormat:@"%@ succeeded pairing request", device];
284+
}
285+
286+
[logger logFormat:@"Validating Pairing to %@", device];
287+
int status = calls.ValidatePairing(device);
288+
if (status != 0) {
289+
NSString *errorDescription = CFBridgingRelease(calls.CopyErrorText(status));
290+
return [[FBDeviceControlError
291+
describeFormat:@"Failed to validate pairing for %@. (%@)", device, errorDescription]
292+
failBool:error];
293+
}
294+
295+
// A session may also be required.
296+
[logger logFormat:@"Starting Session on %@", device];
297+
status = calls.StartSession(device);
298+
if (status != 0) {
299+
calls.Disconnect(device);
300+
NSString *errorDescription = CFBridgingRelease(calls.CopyErrorText(status));
301+
return [[FBDeviceControlError
302+
describeFormat:@"Failed to start session with device. (%@)", errorDescription]
303+
failBool:error];
304+
}
305+
306+
return YES;
307+
}
308+
309+
+ (BOOL)stopSessionWithDevice:(AMDeviceRef)device calls:(AMDCalls)calls logger:(id<FBControlCoreLogger>)logger error:(NSError **)error
310+
{
311+
[logger logFormat:@"Stopping Session on %@", device];
312+
calls.StopSession(device);
313+
return YES;
314+
}
315+
316+
+ (BOOL)stopConnectionToDevice:(AMDeviceRef)device calls:(AMDCalls)calls logger:(id<FBControlCoreLogger>)logger error:(NSError **)error
317+
{
318+
[logger logFormat:@"Disconnecting from %@", device];
319+
calls.Disconnect(device);
320+
[logger logFormat:@"Disconnected from %@", device];
321+
return YES;
322+
}
323+
271324
@end

0 commit comments

Comments
 (0)