Skip to content

Commit

Permalink
Fix crashes. App scenes are rendering on the Carplay scene
Browse files Browse the repository at this point in the history
  • Loading branch information
EthanArbuckle committed Mar 31, 2024
1 parent 908b750 commit 37b32b5
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 5 deletions.
21 changes: 18 additions & 3 deletions src/CRCarplayWindow.mm
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,14 @@ - (void)setupLiveAppView
id mainScreenIdentity = objcInvoke(displaySceneManager, @"displayIdentity");
assertGotExpectedObject(mainScreenIdentity, @"FBSDisplayIdentity");

id sceneIdentity = objcInvoke_2(displaySceneManager, @"_sceneIdentityForApplication:createPrimaryIfRequired:", self.application, 1);
id sceneIdentity = nil;
if ([displaySceneManager respondsToSelector:NSSelectorFromString(@"_sceneIdentityForApplication:createPrimaryIfRequired:")]) {
sceneIdentity = objcInvoke_2(displaySceneManager, @"_sceneIdentityForApplication:createPrimaryIfRequired:", self.application, 1);
}
else if ([displaySceneManager respondsToSelector:NSSelectorFromString(@"_sceneIdentityForApplication:createPrimaryIfRequired:sceneSessionRole:")]) {
sceneIdentity = objcInvoke_3(displaySceneManager, @"_sceneIdentityForApplication:createPrimaryIfRequired:sceneSessionRole:", self.application, 1, @"UIWindowSceneSessionRoleApplication");
}

assertGotExpectedObject(sceneIdentity, @"FBSSceneIdentity");

id sceneHandleRequest = objcInvoke_3(objc_getClass("SBApplicationSceneHandleRequest"), @"defaultRequestForApplication:sceneIdentity:displayIdentity:", self.application, sceneIdentity, mainScreenIdentity);
Expand Down Expand Up @@ -349,7 +356,14 @@ - (void)setupLiveAppView

// Create a scene monitor to watch for the app process dying. The carplay window will dismiss itself.
// todo: this returns nil if the app process isn't running..
NSString *sceneID = objcInvoke_1(sceneLayoutManager, @"primarySceneIdentifierForBundleIdentifier:", appIdentifier);
NSString *sceneID = nil;
if ([sceneLayoutManager respondsToSelector:NSSelectorFromString(@"primarySceneIdentifierForBundleIdentifier:")]) {
sceneID = objcInvoke_1(sceneLayoutManager, @"primarySceneIdentifierForBundleIdentifier:", appIdentifier);
}
else if ([sceneLayoutManager respondsToSelector:NSSelectorFromString(@"primarySceneIdentifierForBundleIdentifier:sceneSessionRole:")]) {
sceneID = objcInvoke_2(sceneLayoutManager, @"primarySceneIdentifierForBundleIdentifier:sceneSessionRole:", appIdentifier, @"UIWindowSceneSessionRoleApplication");
}

self.sceneMonitor = objcInvoke_1([objc_getClass("FBSceneMonitor") alloc], @"initWithSceneID:", sceneID);
objcInvoke_1(self.sceneMonitor, @"setDelegate:", self);
}
Expand Down Expand Up @@ -463,7 +477,7 @@ - (void)dismiss
id sceneSettings = objcInvoke(appScene, @"mutableSettings");
objcInvoke_1(sceneSettings, @"setBackgrounded:", 1);
objcInvoke_1(sceneSettings, @"setForeground:", 0);
((void (*)(id, SEL, id, id, void *))objc_msgSend)(appScene, NSSelectorFromString(@"updateSettings:withTransitionContext:completion:"), sceneSettings, nil, 0);
// ((void (*)(id, SEL, id, id))objc_msgSend)(appScene, NSSelectorFromString(@"updateSettings:withTransitionContext:"), sceneSettings, nil);
}
}

Expand Down Expand Up @@ -568,6 +582,7 @@ - (void)resizeAppViewForOrientation:(int)desiredOrientation fullscreen:(BOOL)ful
xOrigin = (carplayDisplaySize.width / 2) - (scaledDisplayWidth / 2);
}

NSLog(@"Scaling app view to %.2fx%.2f (target size: %.2fx%.2f)", widthScale, heightScale, carplayDisplaySize.width, carplayDisplaySize.height);
[hostingContentView setTransform:CGAffineTransformMakeScale(widthScale, heightScale)];
[[self.appViewController view] setFrame:CGRectMake(xOrigin, [[self.appViewController view] frame].origin.y, carplayDisplaySize.width, carplayDisplaySize.height)];

Expand Down
2 changes: 1 addition & 1 deletion src/hooks/CarPlay.xm
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ Include all User applications on the CarPlay dashboard
id appState = objcInvoke(appProxy, @"appState");
if (objcInvokeT(appState, @"isValid", int) == 1)
{
objcInvoke_2(allAppsLibrary, @"addApplicationProxy:withOverrideURL:", appProxy, 0);
// objcInvoke_2(allAppsLibrary, @"addApplicationProxy:withOverrideURL:", appProxy, 0);
}
}

Expand Down
11 changes: 10 additions & 1 deletion src/hooks/SpringBoard.xm
Original file line number Diff line number Diff line change
Expand Up @@ -183,8 +183,9 @@ happen while the device is in a faceup/facedown orientation.
Called when something is trying to change a scene's settings (including sending it to background/foreground).
Use this to prevent the App from going to sleep when other applications are launched on the main screen.
*/
- (void)updateSettings:(id)arg1 withTransitionContext:(id)arg2 completion:(void *)arg3
- (void)_updateSettings:(id)arg1 withTransitionContext:(id)arg2 completion:(void *)arg3
{
LOG_LIFECYCLE_EVENT;
id sceneClient = objcInvoke(self, @"client");
if ([sceneClient respondsToSelector:NSSelectorFromString(@"process")])
{
Expand All @@ -202,6 +203,14 @@ Use this to prevent the App from going to sleep when other applications are laun
%orig;
}

/*
The scene's client getter method was removed in iOS 15 but the ivar is still accessible
*/
%new
- (id)client {
return getIvar(self, @"_client");
}

%end

%hook SBMainSwitcherViewController
Expand Down

0 comments on commit 37b32b5

Please sign in to comment.