Create and Register a 'IndigoHIDRegistrationPort' Port

This commit is contained in:
lawrencelomax 2016-01-29 16:12:49 +00:00
Родитель 993298f3c4
Коммит 5851401093
3 изменённых файлов: 50 добавлений и 8 удалений

Просмотреть файл

@ -28,11 +28,12 @@
Creates and returns a new FBSimulatorDirectLaunch object for the provided SimDeviceFramebufferService.
@param framebufferService the SimDeviceFramebufferService to connect to.
@param hidPort the Mach Port for the 'IndigoHIDRegistrationPort'.
@param launchConfiguration the launch configuration to create the service for.
@param simulator the Simulator to which the Framebuffer belongs.
@return a new FBSimulatorDirectLaunch instance. Must not be nil.
*/
+ (instancetype)withFramebufferService:(SimDeviceFramebufferService *)framebufferService configuration:(FBSimulatorLaunchConfiguration *)launchConfiguration simulator:(FBSimulator *)simulator;
+ (instancetype)withFramebufferService:(SimDeviceFramebufferService *)framebufferService hidPort:(mach_port_t)hidPort configuration:(FBSimulatorLaunchConfiguration *)launchConfiguration simulator:(FBSimulator *)simulator;
/**
Starts listening for Framebuffer events on a background queue.

Просмотреть файл

@ -10,9 +10,10 @@
#import "FBSimulatorFramebuffer.h"
#import <AppKit/AppKit.h>
#import <SimulatorKit/SimDeviceFramebufferBackingStore.h>
#import <SimulatorKit/SimDeviceFramebufferService.h>
#import <mach/exc.h>
#import <mach/mig.h>
#import "FBFramebufferCompositeDelegate.h"
#import "FBFramebufferCounter.h"
@ -42,6 +43,8 @@ static const NSInteger FBFramebufferLogFrameFrequency = 100;
@interface FBSimulatorFramebuffer () <FBFramebufferDelegate>
@property (nonatomic, strong, readonly) SimDeviceFramebufferService *framebufferService;
@property (nonatomic, assign, readonly) mach_port_t hidPort;
@property (nonatomic, strong, readonly) FBFramebufferCounter *counter;
@property (nonatomic, strong, readonly) id<FBSimulatorEventSink> eventSink;
@ -57,7 +60,7 @@ static const NSInteger FBFramebufferLogFrameFrequency = 100;
#pragma mark Initializers
+ (instancetype)withFramebufferService:(SimDeviceFramebufferService *)framebufferService configuration:(FBSimulatorLaunchConfiguration *)launchConfiguration simulator:(FBSimulator *)simulator {
+ (instancetype)withFramebufferService:(SimDeviceFramebufferService *)framebufferService hidPort:(mach_port_t)hidPort configuration:(FBSimulatorLaunchConfiguration *)launchConfiguration simulator:(FBSimulator *)simulator {
NSMutableArray *sinks = [NSMutableArray array];
BOOL useWindow = (launchConfiguration.options & FBSimulatorLaunchOptionsShowDebugWindow) == FBSimulatorLaunchOptionsShowDebugWindow;
if (useWindow) {
@ -75,12 +78,13 @@ static const NSInteger FBFramebufferLogFrameFrequency = 100;
[sinks addObject:[FBFramebufferImage withWritableLog:simulator.logs.screenshot eventSink:simulator.eventSink]];
id<FBFramebufferDelegate> delegate = [FBFramebufferCompositeDelegate withDelegates:[sinks copy]];
return [[self alloc] initWithFramebufferService:framebufferService counter:counter eventSink:simulator.eventSink delegate:delegate];
return [[self alloc] initWithFramebufferService:framebufferService hidPort:hidPort counter:counter eventSink:simulator.eventSink delegate:delegate];
}
- (instancetype)initWithFramebufferService:(SimDeviceFramebufferService *)framebufferService counter:(FBFramebufferCounter *)counter eventSink:(id<FBSimulatorEventSink>)eventSink delegate:(id<FBFramebufferDelegate>)delegate
- (instancetype)initWithFramebufferService:(SimDeviceFramebufferService *)framebufferService hidPort:(mach_port_t)hidPort counter:(FBFramebufferCounter *)counter eventSink:(id<FBSimulatorEventSink>)eventSink delegate:(id<FBFramebufferDelegate>)delegate
{
NSParameterAssert(framebufferService);
NSParameterAssert(hidPort > 0);
self = [super init];
if (!self) {
@ -88,6 +92,7 @@ static const NSInteger FBFramebufferLogFrameFrequency = 100;
}
_framebufferService = framebufferService;
_hidPort = hidPort;
_counter = counter;
_eventSink = eventSink;
_delegate = delegate;
@ -185,6 +190,8 @@ static const NSInteger FBFramebufferLogFrameFrequency = 100;
[self.framebufferService unregisterClient:self];
[self.framebufferService suspend];
mach_port_destroy(mach_task_self(), self.hidPort);
[self.delegate framebufferDidBecomeInvalid:self error:error];
[self.eventSink framebufferDidTerminate:self expected:(error != nil)];
}

Просмотреть файл

@ -10,8 +10,9 @@
#import "FBSimulatorInteraction+Lifecycle.h"
#import <CoreSimulator/SimDevice.h>
#import <SimulatorKit/SimDeviceFramebufferService.h>
#import <mach/exc.h>
#import <mach/mig.h>
#import "FBCollectionDescriptions.h"
#import "FBInteraction+Private.h"
@ -145,6 +146,10 @@
+ (BOOL)launchSimulatorDirectly:(FBSimulator *)simulator configuration:(FBSimulatorLaunchConfiguration *)configuration error:(NSError **)error
{
// If you're curious about where the knowledege for these parts of the CoreSimulator.framework comes from, take a look at:
// $DEVELOPER_DIR/Platforms/iPhoneSimulator.platform/Developer/Library/CoreSimulator/Profiles/Runtimes/iOS [VERSION].simruntime/Contents/Resources/profile.plist
// as well as the dissasembly for CoreSimulator.framework, SimulatorKit.Framework & the Simulator.app Executable.
// Creating the Framebuffer with the 'mainScreen' constructor will return a 'PurpleFBServer' and attach it to the '_registeredServices' ivar.
// This is the Framebuffer for the Simulator's main screen, which is distinct from 'PurpleFBTVOut' and 'Stark' Framebuffers for External Displays and CarPlay.
NSError *innerError = nil;
@ -156,6 +161,35 @@
failBool:error];
}
// As above with the 'PurpleFBServer', a 'IndigoHIDRegistrationPort' is needed in order for the synthesis of touch events to work appropriately.
// If this is not set you will see the following logger message in the System log upon booting the simulator
// 'backboardd[10667]: BKHID: Unable to open Indigo HID system'
// The dissasembly for backboardd shows that this will happen when the call to 'IndigoHIDSystemSpawnLoopback' fails.
// Simulator.app creates a Mach Port for the 'IndigoHIDRegistrationPort' and therefore succeeds in the above call.
// As with 'PurpleFBServer' this can be registered with 'register-head-services'
// The first step is to create the mach port
mach_port_t hidPort = 0;
mach_port_t machTask = mach_task_self();
kern_return_t result = mach_port_allocate(machTask, MACH_PORT_RIGHT_RECEIVE, &hidPort);
if (result != KERN_SUCCESS) {
return [[FBSimulatorError
describeFormat:@"Failed to create a Mach Port for IndigoHIDRegistrationPort with code %d", result]
failBool:error];
}
result = mach_port_insert_right(machTask, hidPort, hidPort, MACH_MSG_TYPE_MAKE_SEND);
if (result != KERN_SUCCESS) {
return [[FBSimulatorError
describeFormat:@"Failed to 'insert_right' the mach port with code %d", result]
failBool:error];
}
// Then register it as the 'IndigoHIDRegistrationPort'
if (![simulator.device registerPort:hidPort service:@"IndigoHIDRegistrationPort" error:&innerError]) {
return [[[FBSimulatorError
describeFormat:@"Failed to register %d as the IndigoHIDRegistrationPort", hidPort]
causedBy:innerError]
failBool:error];
}
// The 'register-head-services' option will attach the existing 'frameBufferService' when the Simulator is booted.
// Simulator.app behaves similarly, except we can't peek at the Framebuffer as it is in a protected process since Xcode 7.
// Prior to Xcode 6 it was possible to shim into the Simulator process but codesigning now prevents this https://gist.github.com/lawrencelomax/27bdc4e8a433a601008f
@ -176,7 +210,7 @@
// Create and start the consumer of the Framebuffer Service.
// The launch configuration will define the way that the Framebuffer is consumed.
// Then the simulator's event sink should be notified with the created framebuffer object.
FBSimulatorFramebuffer *framebuffer = [FBSimulatorFramebuffer withFramebufferService:framebufferService configuration:configuration simulator:simulator];
FBSimulatorFramebuffer *framebuffer = [FBSimulatorFramebuffer withFramebufferService:framebufferService hidPort:hidPort configuration:configuration simulator:simulator];
[framebuffer startListeningInBackground];
[simulator.eventSink framebufferDidStart:framebuffer];
@ -184,7 +218,7 @@
if (![self launchdSimWithAllRequiredProcessesForSimulator:simulator error:&innerError]) {
return [FBSimulatorError failBoolWithError:innerError errorOut:error];
}
return YES;
}