Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update to latest to enable compatibility with more recent devices #870

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
da9dae6
Adding my local changes. Delta installs, fixed logging and other stuff
davidrogers-unity Dec 2, 2020
5c6241b
We know that iOS 13.7+ require a secure connection
davidrogers-unity Dec 2, 2020
8f71fd5
Fixed iOS version check for requiring secure connection
AndreasReich Dec 4, 2020
552dbed
Documented now exposed deltaInstallApplicatoinWithPath
AndreasReich Dec 17, 2020
2f11fce
Expose configurable work queues on FBDeviceSet init
AndreasReich Dec 19, 2020
c8c16c8
Fixed use of FBApplicationLaunchMode for FBDevice
AndreasReich Dec 22, 2020
c208d8c
disabled debug symbol generation for release builds
AndreasReich Jan 5, 2021
2e58797
Fixed running apps being identified by non-unique application name
AndreasReich Jan 12, 2021
809c9f1
Fix application list filtering out processes that are applications bu…
AndreasReich Jan 27, 2021
1bc57bc
Fix bug that product version is not overwritten correctly on FBAM(Res…
AndreasReich Jan 28, 2021
de61162
Merge remote-tracking branch 'upstream/master' into update-idb
AndreasReich Aug 13, 2021
d54da90
removed spammy log message
AndreasReich Aug 13, 2021
0968de4
Merge pull request #1 from Unity-Technologies/update-idb
AndreasReich Aug 13, 2021
f095a40
Merge remote-tracking branch 'upstream/main' into update-idb
AndreasReich Nov 26, 2021
80e1d76
Fix missing NSNumber conversion
AndreasReich Nov 26, 2021
2442b6e
Merge pull request #2 from Unity-Technologies/update-idb
AndreasReich Nov 30, 2021
c1d754c
Fix always using iOS developer images
AndreasReich Dec 22, 2021
f02a51d
Merge pull request #4 from Unity-Technologies/fix-developer-images-al…
AndreasReich Dec 23, 2021
d441f6d
add invalidateHouseArrestAFCConnectionForBundleID as workaround for b…
AndreasReich Dec 22, 2021
57595df
Merge remote-tracking branch 'upstream/main' into update-to-latest
juho-gavert Jul 2, 2024
3e55180
missing FBDeviceApplicationCommands?
juho-gavert Jul 11, 2024
cc4d8ad
Merge pull request #5 from Unity-Technologies/afcconnection-invalidation
bitter Oct 1, 2024
f4845f1
Add missing InvalidateAFCHouseArrest method that was recently added t…
guillaumelevass Oct 1, 2024
91e7909
Update dylibs
guillaumelevass Oct 2, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions FBControlCore/Utility/FBDeveloperDiskImage.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,13 @@ NS_ASSUME_NONNULL_BEGIN
@param error an error out for any error that occurs.
@return the path of the disk image.
*/
+ (nullable instancetype)developerDiskImage:(NSOperatingSystemVersion)targetVersion logger:(nullable id<FBControlCoreLogger>)logger error:(NSError **)error;
+ (nullable instancetype)developerDiskImage:(NSOperatingSystemVersion)targetVersion logger:(nullable id<FBControlCoreLogger>)logger platformRootDirectory:(NSString*)platformRootDirectory error:(NSError **)error;

/**
Returns all of the Developer Disk Images that are available.
These Disk Images are found by inspecting the appropriate directories within the current installed Xcode.
*/
+ (NSArray<FBDeveloperDiskImage *> *)allDiskImages;
+ (NSArray<FBDeveloperDiskImage *> *)allDiskImages:(NSString*)platformRootDirectory;

#pragma mark Properties

Expand Down
9 changes: 5 additions & 4 deletions FBControlCore/Utility/FBDeveloperDiskImage.m
Original file line number Diff line number Diff line change
Expand Up @@ -60,18 +60,18 @@ + (nullable FBDeveloperDiskImage *)diskImageAtPath:(NSString *)path xcodeVersion

#pragma mark Initializers

+ (FBDeveloperDiskImage *)developerDiskImage:(NSOperatingSystemVersion)targetVersion logger:(id<FBControlCoreLogger>)logger error:(NSError **)error
+ (FBDeveloperDiskImage *)developerDiskImage:(NSOperatingSystemVersion)targetVersion logger:(id<FBControlCoreLogger>)logger platformRootDirectory:(NSString*)platformRootDirectory error:(NSError **)error
{
NSArray<FBDeveloperDiskImage *> *images = FBDeveloperDiskImage.allDiskImages;
NSArray<FBDeveloperDiskImage *> *images = [FBDeveloperDiskImage allDiskImages:platformRootDirectory];
return [self bestImageForImages:images targetVersion:targetVersion logger:logger error:error];
}

+ (NSArray<FBDeveloperDiskImage *> *)allDiskImages
+ (NSArray<FBDeveloperDiskImage *> *)allDiskImages:(NSString*)platformRootDirectory
{
static dispatch_once_t onceToken;
static NSArray<FBDeveloperDiskImage *> *images = nil;
dispatch_once(&onceToken, ^{
images = [self allDiskImagesFromSearchPath:[FBXcodeConfiguration.developerDirectory stringByAppendingPathComponent:@"Platforms/iPhoneOS.platform/DeviceSupport"] xcodeVersion:FBXcodeConfiguration.xcodeVersion logger:FBControlCoreGlobalConfiguration.defaultLogger];
images = [self allDiskImagesFromSearchPath:[platformRootDirectory stringByAppendingPathComponent:@"DeviceSupport"] xcodeVersion:FBXcodeConfiguration.xcodeVersion logger:FBControlCoreGlobalConfiguration.defaultLogger];
if ([[NSProcessInfo.processInfo.environment allKeys] containsObject:ExtraDeviceSupportDirEnv]) {
NSArray<FBDeveloperDiskImage *> *extraImages = [self allDiskImagesFromSearchPath:NSProcessInfo.processInfo.environment[ExtraDeviceSupportDirEnv] xcodeVersion:FBXcodeConfiguration.xcodeVersion logger:FBControlCoreGlobalConfiguration.defaultLogger];
images = [images arrayByAddingObjectsFromArray:extraImages];
Expand Down Expand Up @@ -107,6 +107,7 @@ - (instancetype)initWithDiskImagePath:(NSString *)diskImagePath signature:(NSDat

#pragma mark Public

// TODO: This only yields symbols for iOS, not tvOS or other.
+ (NSString *)pathForDeveloperSymbols:(NSString *)buildVersion logger:(id<FBControlCoreLogger>)logger error:(NSError **)error
{
NSArray<NSString *> *searchPaths = @[
Expand Down
16 changes: 16 additions & 0 deletions FBDeviceControl/Commands/FBDeviceApplicationCommands.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,22 @@ NS_ASSUME_NONNULL_BEGIN
An Implementation of FBApplicationCommands for Devices
*/
@interface FBDeviceApplicationCommands : NSObject <FBApplicationCommands>
/**
Instantiates the Commands instance.

@param target the target to use.
@return a new instance of the Command.
*/
+ (instancetype)commandsWithTarget:(FBDevice *)target;

/**
Installs application at given path on the host using a shadow dir on the host to only install changed files.

@param path the file path of the Application Bundle on the host.
@param shadowDir directory on the host that is used for the shadow copy.
@return A future that resolves when successful.
*/
- (FBFuture<NSNull *> *)deltaInstallApplicationWithPath:(NSString *)path andShadowDirectory:(NSString *)shadowDir;

@end

Expand Down
107 changes: 100 additions & 7 deletions FBDeviceControl/Commands/FBDeviceApplicationCommands.m
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,24 @@ - (instancetype)initWithDevice:(FBDevice *)device deltaUpdateDirectory:(NSURL *)
}];
}

- (FBFuture<NSNull *> *)deltaInstallApplicationWithPath:(NSString *)path andShadowDirectory:(NSString *)shadowDir
{
NSString *cacheDirectory = shadowDir;
if (cacheDirectory == nil) {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
cacheDirectory = [[paths objectAtIndex:0] stringByAppendingPathComponent:@"idb"];
}

// Ensure that the shadow directory exists as the Apple API will not create it.
NSError *error = nil;
[[NSFileManager defaultManager] createDirectoryAtPath:cacheDirectory withIntermediateDirectories:TRUE attributes:nil error:&error];

NSDictionary *options = @{@"PackageType" : @"Developer", @"ShadowParentKey" : [NSURL fileURLWithPath:cacheDirectory]};
NSURL *appURL = [NSURL fileURLWithPath:path isDirectory:YES];

return [self secureDeltaInstallApplication:appURL options:options];
}

- (FBFuture<id> *)uninstallApplicationWithBundleID:(NSString *)bundleID
{
// It may be better to investigate if FB_AMDeviceSecureUninstallApplication
Expand Down Expand Up @@ -293,7 +311,7 @@ - (instancetype)initWithDevice:(FBDevice *)device deltaUpdateDirectory:(NSURL *)
bundleNameToPID[bundleName] = pid;
}
return bundleNameToPID;
}];
}];
}

- (FBFuture<NSNumber *> *)processIDWithBundleID:(NSString *)bundleID
Expand Down Expand Up @@ -321,6 +339,26 @@ - (instancetype)initWithDevice:(FBDevice *)device deltaUpdateDirectory:(NSURL *)
}

- (FBFuture<id<FBLaunchedApplication>> *)launchApplication:(FBApplicationLaunchConfiguration *)configuration
{
if (configuration.launchMode == FBApplicationLaunchModeFailIfRunning) {
return [[self processIDWithBundleID:configuration.bundleID] onQueue:self.device.asyncQueue chain:^ (FBFuture<NSNumber *>* processIdQueryResult) {
if (processIdQueryResult.state == FBFutureStateDone) {
return [[FBDeviceControlError
describeFormat:@"Application %@ already running with pid %@", configuration.bundleID, processIdQueryResult.result]
failFuture];
} else if (processIdQueryResult.state == FBFutureStateFailed) {
return (FBFuture*)[self launchApplicationIgnoreCurrentState:configuration];
} else {
return (FBFuture*)processIdQueryResult;
}
}];
}
return [self launchApplicationIgnoreCurrentState:configuration];
}

#pragma mark Private

- (FBFuture<id<FBLaunchedApplication>> *)launchApplicationIgnoreCurrentState:(FBApplicationLaunchConfiguration *)configuration
{
if (self.device.osVersion.version.majorVersion >= 17) {
FBAppleDevicectlCommandExecutor *devicectl = [[FBAppleDevicectlCommandExecutor alloc] initWithDevice:self.device];
Expand Down Expand Up @@ -348,8 +386,6 @@ - (instancetype)initWithDevice:(FBDevice *)device deltaUpdateDirectory:(NSURL *)
}
}

#pragma mark Private

- (FBFuture<NSNull *> *)killApplicationWithProcessIdentifier:(pid_t)processIdentifier
{
return [[self
Expand All @@ -359,6 +395,62 @@ - (instancetype)initWithDevice:(FBDevice *)device deltaUpdateDirectory:(NSURL *)
}];
}

- (FBFuture<NSNull *> *)secureInstallApplicationBundle:(NSURL *)hostAppURL options:(NSDictionary<NSString *, id> *)options
{
return [[self.device
connectToDeviceWithPurpose:@"install"]
onQueue:self.device.workQueue pop:^ FBFuture<NSNull *> * (id<FBDeviceCommands> device) {
FBDeviceWorkflowStatistics *statistics = [[FBDeviceWorkflowStatistics alloc] initWithWorkflowType:@"Install" logger:device.logger];
[self.device.logger logFormat:@"Installing Application %@", hostAppURL];
int status = device.calls.SecureInstallApplicationBundle(
device.amDeviceRef,
(__bridge CFURLRef _Nonnull)(hostAppURL),
(__bridge CFDictionaryRef _Nonnull)(options),
(AMDeviceProgressCallback) WorkflowCallback,
(__bridge void *) (statistics)
);
if (status != 0) {
NSString *errorMessage = CFBridgingRelease(device.calls.CopyErrorText(status));
return [[FBDeviceControlError
describeFormat:@"Failed to install application %@ 0x%x (%@). %@", [hostAppURL lastPathComponent], status, errorMessage, statistics.summaryOfRecentEvents]
failFuture];
//return [[FBDeviceControlError
// describeFormat:@"Failed to install application %@ 0x%x (%@)", [hostAppURL lastPathComponent], status, errorMessage]
// failFuture];
}
[self.device.logger logFormat:@"Installed Application %@", hostAppURL];
return FBFuture.empty;
}];
}

- (FBFuture<NSNull *> *)secureDeltaInstallApplication:(NSURL *)appURL options:(NSDictionary *)options
{
return [[self.device
connectToDeviceWithPurpose:@"install"]
onQueue:self.device.workQueue pop:^ FBFuture<NSNull *> * (id<FBDeviceCommands> device) {
FBDeviceWorkflowStatistics *statistics = [[FBDeviceWorkflowStatistics alloc] initWithWorkflowType:@"Install" logger:device.logger];
[self.device.logger logFormat:@"Installing Application %@", appURL];
int status = device.calls.SecureInstallApplicationBundle(
device.amDeviceRef,
(__bridge CFURLRef _Nonnull)(appURL),
(__bridge CFDictionaryRef _Nonnull)(options),
(AMDeviceProgressCallback) WorkflowCallback,
(__bridge void *) (statistics)
);
if (status != 0) {
NSString *errorMessage = CFBridgingRelease(device.calls.CopyErrorText(status));
return [[FBDeviceControlError
describeFormat:@"Failed to install application %@ 0x%x (%@). %@", [appURL lastPathComponent], status, errorMessage, statistics.summaryOfRecentEvents]
failFuture];
//return [[FBDeviceControlError
// describeFormat:@"Failed to install application %@ 0x%x (%@)", [appURL lastPathComponent], status, errorMessage]
// failFuture];
}
[self.device.logger logFormat:@"Installed Application %@", appURL];
return FBFuture.empty;
}];
}

- (FBFuture<NSDictionary<NSString *, NSDictionary<NSString *, id> *> *> *)installedApplicationsData:(NSArray<NSString *> *)returnAttributes
{
return [[self.device
Expand Down Expand Up @@ -398,7 +490,7 @@ - (instancetype)initWithDevice:(FBDevice *)device deltaUpdateDirectory:(NSURL *)
}];
}

- (FBFuture<NSDictionary<NSString *, NSNumber *> *> *)pidToRunningProcessName
- (FBFuture<NSDictionary<NSNumber *, NSString *> *> *)pidToRunningProcessName
{
return [[self.device
startService:@"com.apple.os_trace_relay"]
Expand Down Expand Up @@ -428,15 +520,16 @@ - (instancetype)initWithDevice:(FBDevice *)device deltaUpdateDirectory:(NSURL *)
describeFormat:@"Request to PidList is not RequestSuccessful %@", error]
failFuture];
}
NSDictionary<NSNumber *, id> *payload = response[@"Payload"];
NSDictionary<NSString *, id> *payload = response[@"Payload"];
NSMutableDictionary<NSNumber *, NSString *> *pidToRunningProcessName = NSMutableDictionary.dictionary;
for (NSNumber *processIdentifer in payload.keyEnumerator) {
for (NSString *processIdentifer in payload.keyEnumerator) {
NSDictionary<NSString *, NSString *> *contents = payload[processIdentifer];
NSString *processName = contents[@"ProcessName"];
if (![processName isKindOfClass:NSString.class]) {
continue;
}
pidToRunningProcessName[processIdentifer] = processName;
NSNumber* processIdentiferNumber = [NSNumber numberWithInteger:[processIdentifer integerValue]];
pidToRunningProcessName[processIdentiferNumber] = processName;
}
return [FBFuture futureWithResult:pidToRunningProcessName];
}];
Expand Down
7 changes: 7 additions & 0 deletions FBDeviceControl/Commands/FBDeviceCommands.h
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,13 @@ extern FBDeviceActivationState FBDeviceActivationStateCoerceFromString(NSString
*/
- (FBFutureContext<FBAFCConnection *> *)houseArrestAFCConnectionForBundleID:(NSString *)bundleID afcCalls:(AFCCalls)afcCalls;

/**
Invalidates house arrest connection for a given bundle id.
Does nothing if no connection exists already.
This can be used whenever a cached connection returns previously encountered errors on subsequent operations
*/
- (void)invalidateHouseArrestAFCConnectionForBundleID:(NSString *)bundleID;

@end

NS_ASSUME_NONNULL_END
6 changes: 3 additions & 3 deletions FBDeviceControl/Commands/FBDeviceDeveloperDiskImageCommands.m
Original file line number Diff line number Diff line change
Expand Up @@ -90,14 +90,14 @@ - (instancetype)initWithDevice:(FBDevice *)device

- (NSArray<FBDeveloperDiskImage *> *)mountableDiskImages
{
return FBDeveloperDiskImage.allDiskImages;
return [FBDeveloperDiskImage allDiskImages: self.device.platformRootDirectory];
}

- (FBFuture<FBDeveloperDiskImage *> *)ensureDeveloperDiskImageIsMounted
{
NSError *error = nil;
NSOperatingSystemVersion targetVersion = [FBOSVersion operatingSystemVersionFromName:self.device.productVersion];
FBDeveloperDiskImage *diskImage = [FBDeveloperDiskImage developerDiskImage:targetVersion logger:self.device.logger error:&error];
FBDeveloperDiskImage *diskImage = [FBDeveloperDiskImage developerDiskImage:targetVersion logger:self.device.logger platformRootDirectory: self.device.platformRootDirectory error:&error];
if (!diskImage) {
return [FBFuture futureWithError:error];
}
Expand All @@ -112,7 +112,7 @@ - (instancetype)initWithDevice:(FBDevice *)device
return [[self
mountedImageEntries]
onQueue:self.device.asyncQueue map:^(NSArray<NSDictionary<NSString *,id> *> *mountEntries) {
NSArray<FBDeveloperDiskImage *> *images = FBDeveloperDiskImage.allDiskImages;
NSArray<FBDeveloperDiskImage *> *images = [FBDeveloperDiskImage allDiskImages: self.device.platformRootDirectory];
NSDictionary<NSData *, FBDeveloperDiskImage *> *imagesBySignature = [NSDictionary dictionaryWithObjects:images forKeys:[images valueForKey:@"signature"]];
NSMutableDictionary<NSDictionary<NSString *, id> *, FBDeveloperDiskImage *> *mountEntryToDiskImage = NSMutableDictionary.dictionary;
for (NSDictionary<NSString *, id> *mountEntry in mountEntries) {
Expand Down
2 changes: 2 additions & 0 deletions FBDeviceControl/Commands/FBDeviceLogCommands.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ NS_ASSUME_NONNULL_BEGIN
An implementation of Log Commands for Devices.
*/
@interface FBDeviceLogCommands : NSObject <FBLogCommands, FBiOSTargetCommand>
+ (instancetype)commandsWithTarget:(FBDevice *)target;
- (FBFuture<id<FBLogOperation>> *)tailLog:(NSArray<NSString *> *)arguments consumer:(id<FBDataConsumer>)consumer;

@end

Expand Down
4 changes: 4 additions & 0 deletions FBDeviceControl/FBDeviceControl.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,16 @@
#import <FBDeviceControl/FBAMDefines.h>
#import <FBDeviceControl/FBAMDevice+Private.h>
#import <FBDeviceControl/FBAMDevice.h>
#import <FBDeviceControl/FBAMDeviceManager.h>
#import <FBDeviceControl/FBAMRestorableDeviceManager.h>
#import <FBDeviceControl/FBDevice.h>
#import <FBDeviceControl/FBDeviceActivationCommands.h>
#import <FBDeviceControl/FBDeviceApplicationCommands.h>
#import <FBDeviceControl/FBDeviceCommands.h>
#import <FBDeviceControl/FBDeviceControlError.h>
#import <FBDeviceControl/FBDeviceControlFrameworkLoader.h>
#import <FBDeviceControl/FBDeviceFileCommands.h>
#import <FBDeviceControl/FBDeviceLogCommands.h>
#import <FBDeviceControl/FBDeviceDebugSymbolsCommands.h>
#import <FBDeviceControl/FBDevicePowerCommands.h>
#import <FBDeviceControl/FBDeviceRecoveryCommands.h>
Expand Down
5 changes: 5 additions & 0 deletions FBDeviceControl/Management/FBAMDServiceConnection.h
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,11 @@ NS_ASSUME_NONNULL_BEGIN
*/
@property (nonatomic, strong, nullable, readonly) id<FBControlCoreLogger> logger;

/**
The size of the read buffer. Public so specific services(such as syslog) can override the default.
*/
@property (nonatomic, assign) int readBufferSize;

@end

NS_ASSUME_NONNULL_END
2 changes: 2 additions & 0 deletions FBDeviceControl/Management/FBAMDServiceConnection.m
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,8 @@ - (instancetype)initWithName:(NSString *)name connection:(AMDServiceConnectionRe
_device = device;
_calls = calls;
_logger = logger;
// There's an upper limit on the number of bytes we can read at once
_readBufferSize = 1024 * 4;

return self;
}
Expand Down
7 changes: 7 additions & 0 deletions FBDeviceControl/Management/FBAMDevice.m
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,11 @@ - (FBDeviceActivationState)activationState
}];
}

- (void)invalidateHouseArrestAFCConnectionForBundleID:(NSString *)bundleID
{
[self.serviceManager invalidateHouseArrestAFCConnectionForBundleID:bundleID];
}

#pragma mark FBFutureContextManager Implementation

- (FBFuture<FBAMDevice *> *)prepare:(id<FBControlCoreLogger>)logger
Expand Down Expand Up @@ -277,6 +282,8 @@ + (NSString *)osVersionForDeviceClass:(NSString *)deviceClass productVersion:(NS
NSDictionary<NSString *, NSString *> *deviceClassOSPrefixMapping = @{
@"iPhone" : @"iOS",
@"iPad" : @"iOS",
@"iPod" : @"iOS",
@"AppleTV" : @"tvOS",
};
NSString *osPrefix = deviceClassOSPrefixMapping[deviceClass];
if (!osPrefix) {
Expand Down
8 changes: 8 additions & 0 deletions FBDeviceControl/Management/FBAMDeviceServiceManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,14 @@ NS_ASSUME_NONNULL_BEGIN
*/
- (FBFutureContextManager<FBAFCConnection *> *)houseArrestAFCConnectionForBundleID:(NSString *)bundleID afcCalls:(AFCCalls)afcCalls;


/**
Invalidates house arrest connection for a given bundle id.
Does nothing if no connection exists already.
This can be used whenever a cached connection returns previously encountered errors on subsequent operations
*/
- (void)invalidateHouseArrestAFCConnectionForBundleID:(NSString *)bundleID;

@end

NS_ASSUME_NONNULL_END
7 changes: 7 additions & 0 deletions FBDeviceControl/Management/FBAMDeviceServiceManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -131,4 +131,11 @@ - (instancetype)initWithAMDevice:(FBAMDevice *)device serviceTimeout:(nullable N
return manager;
}

- (void)invalidateHouseArrestAFCConnectionForBundleID:(NSString *)bundleID
{
[self.houseArrestManagers removeObjectForKey:bundleID];
[self.houseArrestDelegates removeObjectForKey:bundleID];
}


@end
Loading