As you may have known, we recently managed to bring multitask to LiveContainer. This originally came from FrontBoardAppLauncher which was reverse engineered of various Apple apps: ClarityBoard, SpringBoard, Xcode PreviewShell, etc. A quick recap of how we worked on it:
- I began reverse engineering said apps to study how to use various Private API of
FrontBoard
,RunningBoardServices
andUIKit
, resulted in MySystemShell and FrontBoardAppLauncher - I found app could spawn multiple processes thanks to the writeup of NSExtension
- We found we could extend memory limit by setting a hidden
NSExtensionPointIdentifier
However, as more and more people get to try it, we were reported that physical keyboard input wouldn't work. (LiveContainer/LiveContainer#524)
If anyone could figure it out, we will forever owe you.
After a couple of weeks, we have found the solution. Initially, I found that SpringBoardTS running in LiveContainer multitask mode would still have keyboard input, so I began digging in.
Soon, I found a workaround: fake it as _UIRootWindow
@implementation UIWindow(LiveContainerHooks)
- (BOOL)isKindOfClass:(Class)aClass {
return aClass == _UIRootWindow.class || [super isKindOfClass:aClass];
}
@end
However, we began observing some issues, such as app stops playing audio in the background. So I dig deeper by putting a breakpoint to see where it is called
frame #1: UIKitCore`-[_UIVisibilityPropagationInteraction _visibilityLock_didMoveToWindow:] + 828
frame #2: UIKitCore`-[_UIVisibilityPropagationInteraction _didMoveFromWindow:toWindow:] + 48
frame #3: UIKitCore`-[UIView(Internal) _didMoveFromWindow:toWindow:] + 1664
frame #4: UIKitCore`__45-[UIView(Hierarchy) _postMovedFromSuperview:]_block_invoke + 124
frame #5: UIKitCore`-[UIView _postMovedFromSuperview:] + 492
frame #6: UIKitCore`-[UIView(Internal) _addSubview:positioned:relativeTo:] + 2208
From there, I began decompiling the relevant method
- (BOOL)_visibilityLock_didMoveToWindow:(UIWindow *)window {
//...
if ([window isKindOfClass:[_UIRootWindow class]]) {
_visibilityLock_windowEnvironment = [NSString stringWithFormat:@"UIRootWindow:%p", window];
} else if ([window isKindOfClass:[_UIHostedWindow class]] ||
[window isKindOfClass:[UIRemoteKeyboardWindow class]] ||
[window isKindOfClass:[_UITextEffectsWindowHosted class]] ||
[window _isRemoteInputHostWindow]) {
// _visibilityLock_windowEnvironment = [NSString stringWithFormat:@"UIHostedWindow:%x", [window _contextId]];
_visibilityLock_windowEnvironment = _UISVisibilityEnvironmentForUIHostedWindowContextID([window _contextId]);
} else {
id scene = [window _fbsScene];
if (scene) {
FBSSceneIdentityToken *identityToken = [scene identityToken];
NSString *tokenString = [identityToken stringRepresentation];
// _visibilityLock_windowEnvironment = [NSString stringWithFormat:@"UIScene:%@", tokenString];
_visibilityLock_windowEnvironment = _UISVisibilityEnvironmentForSceneIdentityTokenString(tokenString);
} else {
_visibilityLock_windowEnvironment = nil;
}
}
//...
}
As you see, if UIWindow
is not a special kind of window (ie _UIRootWindow
), it will set _visibilityLock_windowEnvironment
to UIScene:
, which allows SpringBoard's visibility graph to find it. Otherwise, SpringBoard fails to find it and hand focus over to the requesting process.
The visibility propagation stuff is vaguely documented in BrowserEngineKit. I have not looked into it yet, but it seems disabling it is the quickest way to fix the issue for now.
@implementation UIScenePresentationContext(LiveContainerHooks)
- (BOOL)_isVisibilityPropagationEnabled {
return NO;
}
@end
Turns out it would still cause side effects, so we had to enable it back. Meanwhile HugeBlack pointed out _UISVisibilityEnvironmentForSceneIdentityTokenString
is called from 2 places:
- Returning different string here fixed the issue and side effects
* frame #0: 0x00000001947a5288 UIKitServices`_UISVisibilityEnvironmentForSceneIdentityTokenString
frame #1: 0x00000001880db938 UIKitCore`-[_UIScenePresentationView initWithPresenter:] + 276
frame #2: 0x000000018745d850 UIKitCore`-[_UIScenePresenter presentationView] + 88
frame #3: 0x00000001880dee28 UIKitCore`-[_UIScenePresenterOwner _setActivePrioritizedPresenter:] + 104
frame #4: 0x000000018745e1fc UIKitCore`-[_UIScenePresenterOwner _updateActivePrioritizedPresenterIfNecessary] + 68
frame #5: 0x00000001880de7e4 UIKitCore`-[_UIScenePresenterOwner _activatePresenter:] + 132
frame #6: 0x000000018745e194 UIKitCore`-[_UIScenePresenter activate] + 56
- Returning different string here broke audio background playback
* frame #0: 0x00000001947a5288 UIKitServices`_UISVisibilityEnvironmentForSceneIdentityTokenString
frame #1: 0x0000000188ab30f8 UIKitCore`-[_UIVisibilityPropagationInteraction _visibilityLock_didMoveToWindow:] + 1180
frame #2: 0x0000000188ab343c UIKitCore`-[_UIVisibilityPropagationInteraction _didMoveFromWindow:toWindow:] + 48
I looked into -[_UIScenePresentationView initWithPresenter:]
and saw that the value is then passed to +[RBSTarget targetWithPid:environmentIdentifier:]
, so I hooked it and everything is fixed.
@implementation RBSTarget(hook)
+ (instancetype)hook_targetWithPid:(pid_t)pid environmentIdentifier:(NSString *)environmentIdentifier {
if([environmentIdentifier containsString:@"LiveProcess"]) {
environmentIdentifier = [NSString stringWithFormat:@"LiveProcess:%d", pid];
}
return [self hook_targetWithPid:pid environmentIdentifier:environmentIdentifier];
}
@end
I began researching on it and found some potential APIs:
-[_UIKeyboardArbiter updateInterestedBundleIDs]:
-[_UIKeyboardArbiterClientHandle focusApplicationWithProcessIdentifier:context:stealingKeyboard:onCompletion:]
Sadly, @hugeBlack has no prior experience in playing with private API or tweaking iOS, so I tried to do research myself most of the time, which was quite difficult. I've attached to SpringBoard and tried to set random breakpoints:
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 5.497
* frame #0: 0x00000001b7f6f3dc KeyboardArbiter`-[_UIKeyboardArbiter keyboardFocusDidChangeWithoutAdvisorInputToPid:sceneIdentity:]
frame #1: 0x000000023feb5a88 SpringBoard`__76-[SBKeyboardFocusCoordinator keyboardFocusCoalitionDidUpdateEnforcedPolicy:]_block_invoke + 80
frame #2: 0x000000023feb5170 SpringBoard`-[SBKeyboardFocusCoordinator _talkToKeyboardArbiterAdvisor:] + 68
frame #3: 0x000000023feb586c SpringBoard`-[SBKeyboardFocusCoordinator keyboardFocusCoalitionDidUpdateEnforcedPolicy:] + 276
frame #4: 0x000000023f76cfcc SpringBoard`-[SBSingleMemberKeyboardFocusCoalition _arbitrateForReason:] + 692
frame #5: 0x000000023f76cc2c SpringBoard`-[SBSingleMemberKeyboardFocusCoalition setNeedsArbitrationForReason:] + 80
frame #6: 0x000000023fde8d20 SpringBoard`__69-[SBKeyboardFocusCoalition suppressKeyboardFocusEvaluationForReason:]_block_invoke + 208
frame #7: 0x0000000183bc6fcc BaseBoard`-[_BSCompoundAssertionAcquisitionReference invalidate] + 620
frame #8: 0x000000023feb2e8c SpringBoard`__71-[SBKeyboardFocusCoordinator suppressKeyboardFocusEvaluationForReason:]_block_invoke + 124
frame #9: 0x0000000183bc6fcc BaseBoard`-[_BSCompoundAssertionAcquisitionReference invalidate] + 620
frame #10: 0x00000001cdacc21c SpringBoard`-[SBKeyboardFocusCoordinatorAccessibility _accessibilitySwitchNativeFocusedApplicationWithPID:identifier:] + 572
frame #11: 0x00000001cdad46b0 SpringBoard`-[SpringBoardAccessibility _accessibilitySwitchNativeFocusedApplicationWithPID:identifier:] + 136
* thread #23, queue = 'com.apple.UIKit.keyboard-arbiter', stop reason = breakpoint 3.1
* frame #0: 0x000000023feb61cc SpringBoard`-[SBKeyboardFocusCoordinator keyboardArbiterAdvisor:request:sceneFocusChange:]
frame #1: 0x00000001b7f70418 KeyboardArbiter`-[_UIKeyboardArbiter reevaluateFocusedSceneIdentityForKeyboardFocusStealingKeyboardOnSuccess:] + 1552
frame #2: 0x00000001b7f6dddc KeyboardArbiter`-[_UIKeyboardArbiter handlerRequestedFocus:shouldStealKeyboard:] + 1632
frame #3: 0x00000001b7f69bc0 KeyboardArbiter`-[_UIKeyboardArbiter newClientConnected:withExpectedState:onConnected:] + 720
frame #4: 0x00000001b7f72828 KeyboardArbiter`-[_UIKeyboardArbiterClientHandle startArbitrationWithExpectedState:focusContext:hostingPIDs:usingFence:withSuppression:onConnected:] + 800
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 4.2
* frame #0: 0x00000001856c4d78 UIKitCore`-[UIKeyboardArbiterManager userSelectedProcessIdentifier:withSceneIdentity:onCompletion:]
frame #1: 0x000000023feb2b7c SpringBoard`-[SBKeyboardFocusCoordinator userFocusRequestForScene:reason:completion:] + 512
Then I checked logs for a sec, and soon I found something
2025-05-27 14:32:28.173440+0700 0x8867d8 Default 0x0 48988 0 SpringBoard: (SpringBoard) [com.apple.SpringBoard:KeyboardFocus] [coordinator] buffer all events for reason: background keyboard arbiter request <145>- begin
2025-05-27 14:32:28.177596+0700 0x86d5d7 Default 0x0 48988 0 SpringBoard: (SpringBoard) [com.apple.SpringBoard:KeyboardFocus] [coordinator] handling new keyboard arbiter request pid: 54855 sceneIdentity: 54788:com.apple.frontboard.workspace-service.fallback/FBSceneManager:sceneID%3ALiveContainerAppProcess-660EC880-7738-453D-B7D6-AFAA54EB8F14
2025-05-27 14:32:28.177617+0700 0x86d5d7 Default 0x0 48988 0 SpringBoard: (SpringBoard) [com.apple.SpringBoard:KeyboardFocus] arbiter: arbiter requested pid 54855 / 54788:com.apple.frontboard.workspace-service.fallback/FBSceneManager:sceneID%3ALiveContainerAppProcess-660EC880-7738-453D-B7D6-AFAA54EB8F14
2025-05-27 14:32:28.177638+0700 0x86d5d7 Default 0x0 48988 0 SpringBoard: (SpringBoard) [com.apple.SpringBoard:KeyboardFocus] [coordinator] using arbiter suggested pid 54855 + scene: 54788:com.apple.frontboard.workspace-service.fallback/FBSceneManager:sceneID%3ALiveContainerAppProcess-660EC880-7738-453D-B7D6-AFAA54EB8F14
2025-05-27 14:32:28.177695+0700 0x86d5d7 Default 0x0 48988 0 SpringBoard: (SpringBoard) [com.apple.SpringBoard:KeyboardFocus] Searching the visibility graph for hosting information for 54788:com.apple.frontboard.workspace-service.fallback/FBSceneManager:sceneID%3ALiveContainerAppProcess-660EC880-7738-453D-B7D6-AFAA54EB8F14
2025-05-27 14:32:28.181053+0700 0x86d5d7 Default 0x0 48988 0 SpringBoard: (SpringBoard) [com.apple.SpringBoard:KeyboardFocus] Visibility graph search found root scene com.apple.frontboard.systemappservices/FBSceneManager:com.apple.springboard and ultimate host <com.apple.frontboard.systemappservices/FBSceneManager:sceneID%3Acom.kdt.LiveMultitask-0205CFD8-338E-4D44-9DCD-541C5887BEC9 pid:54788>
2025-05-27 14:32:28.181112+0700 0x86d5d7 Default 0x0 48988 0 SpringBoard: (SpringBoard) [com.apple.SpringBoard:KeyboardFocus] [coordinator] S33KR3T target <54788:com.apple.frontboard.workspace-service.fallback/FBSceneManager:sceneID%3ALiveContainerAppProcess-660EC880-7738-453D-B7D6-AFAA54EB8F14 pid:54855> has an ultimate host <com.apple.frontboard.systemappservices/FBSceneManager:sceneID%3Acom.kdt.LiveMultitask-0205CFD8-338E-4D44-9DCD-541C5887BEC9 pid:54788>
2025-05-27 14:32:28.181138+0700 0x86d5d7 Default 0x0 48988 0 SpringBoard: (SpringBoard) [com.apple.SpringBoard:KeyboardFocus] [coordinator] informing scene controller 'com.apple.springboard' of focusTarget: <com.apple.frontboard.systemappservices/FBSceneManager:sceneID%3Acom.kdt.LiveMultitask-0205CFD8-338E-4D44-9DCD-541C5887BEC9 pid:54788>
2025-05-27 14:32:28.181254+0700 0x86d5d7 Default 0x0 48988 0 SpringBoard: (SpringBoard) [com.apple.SpringBoard:KeyboardFocus] [embedded coalition] _abritrateForReason: <keyboardArbiterSuggestion> - new policy is unchanged
2025-05-27 14:32:28.181286+0700 0x86d5d7 Default 0x0 48988 0 SpringBoard: (SpringBoard) [com.apple.SpringBoard:KeyboardFocus] [coordinator] keyboard arbiter suggested <pid: 54855; sceneIdentity: 54788:com.apple.frontboard.workspace-service.fallback/FBSceneManager:sceneID%3ALiveContainerAppProcess-660EC880-7738-453D-B7D6-AFAA54EB8F14> and we replied <com.apple.frontboard.systemappservices/FBSceneManager:sceneID%3Acom.kdt.LiveMultitask-0205CFD8-338E-4D44-9DCD-541C5887BEC9 pid:54788>
2025-05-27 14:32:28.181315+0700 0x86d5d7 Default 0x0 48988 0 SpringBoard: (SpringBoard) [com.apple.SpringBoard:KeyboardFocus] [coordinator] buffer all events for reason: background keyboard arbiter request <145> - end
Apparently, the process itself tried to acquire focus, but SpringBoard added some checks and it failed so it set focus back to the host app. Do note that this is only introduced in iOS 17 or so, so I had to rely on iOS simulator
* thread #1, queue = 'com.apple.main-thread', stop reason = step out
* frame #0: 0x000000023feb426c SpringBoard`-[SBKeyboardFocusCoordinator _sbWindowSceneHostingFBSSceneIdentityToken:ultimateHostTarget:] + 376:
"Searching the visibility graph for hosting information for %{public}@"
prints "Visibility graph search found root scene %{public}@ and ultimate host %{public}@"
frame #1: 0x000000023feb3f0c SpringBoard`-[SBKeyboardFocusCoordinator _sceneControllerHostingSceneIdentityToken:ultimateHostTarget:] + 296:
???
frame #2: 0x000000023feb66c0 SpringBoard`-[SBKeyboardFocusCoordinator _handleFocusSceneChange:fromArbiter:request:] + 536:
prints "[coordinator] keyboard arbiter suggested %{public}@ and we replied %{public}@"
frame #3: 0x000000023feb6410 SpringBoard`__78-[SBKeyboardFocusCoordinator keyboardArbiterAdvisor:request:sceneFocusChange:]_block_invoke + 52
I checked the log when it hosts other apps, and it goes like:
2025-05-27 16:07:51.698154+0700 0x8909b7 Default 0x0 56871 0 SpringBoard: (SpringBoard) [com.apple.SpringBoard:KeyboardFocus] [com.apple.springboard] coalition says I have focus; enforcing policy: {
keyboardFocusTarget: <com.apple.frontboard.systemappservices/FBSceneManager:sceneID%3Acom.apple.mobilesafari-CBDE3A51-92E9-42AA-9658-446A0DBD773F pid:58400>;
selectionPolicy: KeyboardArbiter;
shouldSuppressRemoteDeferring: 0;
}
* thread #1, queue = 'com.apple.main-thread', stop reason = step out
frame #0: 0x000000023fbdb8e4 SpringBoard`-[SBKeyboardFocusSceneProvider sceneForIdentityTokenStringRepresentation:] + 40
SpringBoard`-[SBKeyboardFocusSceneProvider sceneForIdentityTokenStringRepresentation:]:
-> 0x23fbdb8e4 <+40>: bl 0x23ff44eb8 ; symbol stub for: objc_claimAutoreleasedReturnValue
0x23fbdb8e8 <+44>: mov x21, x0
0x23fbdb8ec <+48>: mov x2, x19
0x23fbdb8f0 <+52>: bl 0x2403af8e0 ; objc_msgSend$sceneFromIdentityTokenStringRepresentation:
Target 0: (SpringBoard) stopped.
(lldb) po $x0
<FBSceneWorkspace: 0x6000029092d0; FBSceneManager; scenes: 8> {
scenes = {
I initially thought LiveProcess’s FBScene is not in SpringBoard’s FBSceneWorkspace, so it cannot find it and hand focus over it. How to add it now?
I then asked @hugeBlack and @34306 to try messing with keyboard focus in Swift Playgrounds:
- one reported it is possible to acquire keyboard focus once, if you tap outside, you can't type in it anymore.
- another reported the first time keyboard wouldn't focus, but by unfocusing and focusing on it again, it is possible to type. Then I grabbed the log and found another path of it acquiring focus:
default 21:16:21.994955+0700 SpringBoard Visibility graph search found root scene (null) and ultimate host <none>
error 21:16:21.995114+0700 SpringBoard Couldn't find the SB window scene hosting scene identity token: com.apple.preview-shell.system-services/FBSceneManager:UV-InjectedScene-(1138)-1-PreviewScene-7436
error 21:16:21.995295+0700 SpringBoard [coordinator] could not find (null)
default 21:16:21.995342+0700 SpringBoard [coordinator] informing scene controller 'com.apple.springboard' of focusTarget: <com.apple.preview-shell.system-services/FBSceneManager:UV-InjectedScene-(1138)-1-PreviewScene-7436 pid:1226>
So, it looks like apps spawned by Swift Playgrounds use its own system service called com.apple.preview-shell.system-services
hosted in PreviewShell
. I haven't looked into it yet. But is that the root cause?
As I began digging further, I found that Xcode's SwiftUI preview was also using PreviewShell
, so I took it and wasted a day trying to figure out how to acquire focus without success.
-[SBKeyboardFocusCoordinator _sbWindowSceneHostingFBSSceneIdentityToken:ultimateHostTarget:]
-[SBKeyboardFocusVisibilityGraphNavigator _ancestorPathForTargetEnvironment:orTargetPid:withinEndowmentTree:root:visitedLinks:]
(lldb) po $x2
<FBSSceneIdentityToken:0x6000017796c0 2113:com.apple.frontboard.workspace-service.fallback/FBSceneManager:sceneID%3ALiveProcess-EBEE1DD0-051E-4DBC-A21A-E8CEEF3174E7>
(lldb) fin
Process 1890 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = step out
...
(lldb) po *(id*)0x000000016f6f4778
<com.apple.frontboard.systemappservices/FBSceneManager:sceneID%3Acom.kdt.LiveMultitask-AEABB952-B236-4A71-A29D-B5C83CE9E59F pid:2113>
It then recursively calls:
(lldb) fin
Process 8424 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = step out
frame #0: 0x000000023f9e54d8 SpringBoard`-[SBKeyboardFocusVisibilityGraphNavigator _ancestorPathForTargetEnvironment:orTargetPid:withinEndowmentTree:root:visitedLinks:] + 404
(lldb) po $x0
<__NSArray0 0x1e7212908>(
)
(lldb) fin
Process 8424 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = step out
frame #0: 0x000000023f9e54d8 SpringBoard`-[SBKeyboardFocusVisibilityGraphNavigator _ancestorPathForTargetEnvironment:orTargetPid:withinEndowmentTree:root:visitedLinks:] + 404
(lldb) po $x0
<__NSSingleObjectArrayI 0x60000002d300>(
<RBSEndowmentLink| namespace:com.apple.frontboard.visibility srcEnv:8424/UIScene:com.apple.frontboard.systemappservices/FBSceneManager:com.apple.springboard targEnv:9455/UIScene:com.apple.frontboard.systemappservices/FBSceneManager:sceneID%3Acom.kdt.LiveMultitask-AEABB952-B236-4A71-A29D-B5C83CE9E59F>
(lldb) fin
Process 8424 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = step out
frame #0: 0x000000023f9e54d8 SpringBoard`-[SBKeyboardFocusVisibilityGraphNavigator _ancestorPathForTargetEnvironment:orTargetPid:withinEndowmentTree:root:visitedLinks:] + 404
(lldb) po $x0
<__NSArrayI_Transfer 0x6000004e3040>(
<RBSEndowmentLink| namespace:com.apple.frontboard.visibility srcEnv:8424/UIRootWindow:0x10680ce50 targEnv:8424/UIScene:com.apple.frontboard.systemappservices/FBSceneManager:com.apple.springboard>,
<RBSEndowmentLink| namespace:com.apple.frontboard.visibility srcEnv:8424/UIScene:com.apple.frontboard.systemappservices/FBSceneManager:com.apple.springboard targEnv:9455/UIScene:com.apple.frontboard.systemappservices/FBSceneManager:sceneID%3Acom.kdt.LiveMultitask-AEABB952-B236-4A71-A29D-B5C83CE9E59F>
(lldb) fin
Process 8424 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = step out
frame #0: 0x000000023feee848 SpringBoard`-[SBKeyboardFocusVisibilityGraphNavigator _reverseEnumerateChainContainingSceneIdentityToken:orSceneFromProcessID:block:] + 360
(lldb) po $x0
<__NSArrayI_Transfer 0x6000005402c0>(
<RBSEndowmentLink| namespace:com.apple.frontboard.visibility srcEnv:8424/*** RBS Endowment Root Environment *** targEnv:8424/UIRootWindow:0x10680ce50>,
<RBSEndowmentLink| namespace:com.apple.frontboard.visibility srcEnv:8424/UIRootWindow:0x10680ce50 targEnv:8424/UIScene:com.apple.frontboard.systemappservices/FBSceneManager:com.apple.springboard>,
<RBSEndowmentLink| namespace:com.apple.frontboard.visibility srcEnv:8424/UIScene:com.apple.frontboard.systemappservices/FBSceneManager:com.apple.springboard targEnv:9455/UIScene:com.apple.frontboard.systemappservices/FBSceneManager:sceneID%3Acom.kdt.LiveMultitask-AEABB952-B236-4A71-A29D-B5C83CE9E59F>
(lldb) fin
Process 8424 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = step out
frame #0: 0x000000023feb426c SpringBoard`-[SBKeyboardFocusCoordinator _sbWindowSceneHostingFBSSceneIdentityToken:ultimateHostTarget:] + 376
(lldb) po $x0
<FBSSceneIdentityToken:0x600001774380 9455:com.apple.frontboard.workspace-service.fallback/FBSceneManager:sceneID%3ALiveProcess-6A089B2B-5BDD-4771-AD42-C28C5A809C7A>
Endowment trace from host process:
* thread #17, queue = 'com.apple.root.user-initiated-qos', stop reason = breakpoint 1.109
* frame #0: 0x0000000183b75abc RunningBoardServices`RBSEndowmentEncode
frame #1: 0x0000000183b8347c RunningBoardServices`-[RBSHereditaryGrant _initWithNamespace:sourceEnvironment:endowment:attributes:] + 200
frame #2: 0x0000000183b835f4 RunningBoardServices`+[RBSHereditaryGrant grantWithNamespace:sourceEnvironment:attributes:] + 80
frame #3: 0x000000018601debc UIKitCore`__58-[_UIVisibilityPropagationInteraction _enqueuedUpdateBody]_block_invoke + 104
frame #4: 0x00000001876bcfc8 BoardServices`+[BSServiceConnectionEndpointInjector injectorWithConfigurator:] + 240
frame #5: 0x000000018601dde0 UIKitCore`__79-[_UIVisibilityPropagationInteraction _visibilityLock_enqueueUpdateIfNecessary]_block_invoke + 304
frame #0: 0x000000023feee6e0 SpringBoard`-[SBKeyboardFocusVisibilityGraphNavigator _reverseEnumerateChainContainingSceneIdentityToken:orSceneFromProcessID:block:]
SpringBoard`-[SBKeyboardFocusVisibilityGraphNavigator _reverseEnumerateChainContainingSceneIdentityToken:orSceneFromProcessID:block:]:
-> 0x23feee6e0 <+0>: stp x28, x27, [sp, #-0x60]!
0x23feee6e4 <+4>: stp x26, x25, [sp, #0x10]
0x23feee6e8 <+8>: stp x24, x23, [sp, #0x20]
0x23feee6ec <+12>: stp x22, x21, [sp, #0x30]
(lldb) po $x1
<FBSSceneIdentityToken:0x60000182b300 com.apple.preview-shell.system-services/FBSceneManager:SimDisplayScene-133-hosted-PreviewScene-986>
frame #0: 0x000000023f9e5344 SpringBoard`-[SBKeyboardFocusVisibilityGraphNavigator _ancestorPathForTargetEnvironment:orTargetPid:withinEndowmentTree:root:visitedLinks:]
(lldb) p (id)$x1
(__NSCFString *) 0x0000600002c6b700 @"UIScene:com.apple.preview-shell.system-services/FBSceneManager:SimDisplayScene-133-hosted-PreviewScene-986"
(lldb) po (id)$x2
nil
(lldb) po (id)$x3
<RBSEndowmentTree| namespace:com.apple.frontboard.visibility>
(lldb) po (id)$x4
<RBSEndowmentLink| namespace:com.apple.frontboard.visibility srcEnv:2569/*** RBS Endowment Root Environment *** targEnv:2569/UIRootWindow:0x102f24380>
(lldb) po (id)$x5
{(
)}
It then recursively calls:
* frame #0: 0x000000023f9e5344 SpringBoard`-[SBKeyboardFocusVisibilityGraphNavigator _ancestorPathForTargetEnvironment:orTargetPid:withinEndowmentTree:root:visitedLinks:]
frame #1: 0x000000023f9e54d8 SpringBoard`-[SBKeyboardFocusVisibilityGraphNavigator _ancestorPathForTargetEnvironment:orTargetPid:withinEndowmentTree:root:visitedLinks:] + 404
frame #2: 0x000000023f9e54d8 SpringBoard`-[SBKeyboardFocusVisibilityGraphNavigator _ancestorPathForTargetEnvironment:orTargetPid:withinEndowmentTree:root:visitedLinks:] + 404
frame #3: 0x000000023feee848 SpringBoard`-[SBKeyboardFocusVisibilityGraphNavigator _reverseEnumerateChainContainingSceneIdentityToken:orSceneFromProcessID:block:] + 360
(lldb) po (id)$x4
<RBSEndowmentLink| namespace:com.apple.frontboard.visibility srcEnv:2569/UIScene:com.apple.preview-shell.system-services/FBSceneManager:SimDisplayScene-133-hosted targEnv:3002/UIScene:com.apple.preview-shell.system-services/FBSceneManager:SimDisplayScene-133-hosted-PreviewScene-986>
(lldb) fin
...
(lldb) reg r x0
x0 = 0x00000001e7212908 CoreFoundation`__NSArray0__struct
(lldb) fin
...
(lldb) po $x0
<__NSSingleObjectArrayI 0x60000001d8c0>(
<RBSEndowmentLink| namespace:com.apple.frontboard.visibility srcEnv:2569/UIRootWindow:0x102f24380 targEnv:2569/UIScene:com.apple.preview-shell.system-services/FBSceneManager:SimDisplayScene-133-hosted>
)
(lldb) fin
...
(lldb) po $x0
<__NSArrayI_Transfer 0x6000004ec960>(
<RBSEndowmentLink| namespace:com.apple.frontboard.visibility srcEnv:2569/*** RBS Endowment Root Environment *** targEnv:2569/UIRootWindow:0x102f24380>,
<RBSEndowmentLink| namespace:com.apple.frontboard.visibility srcEnv:2569/UIRootWindow:0x102f24380 targEnv:2569/UIScene:com.apple.preview-shell.system-services/FBSceneManager:SimDisplayScene-133-hosted>
)
(lldb) fin
(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 3.1
* frame #0: 0x000000023feb4418 SpringBoard`__92-[SBKeyboardFocusCoordinator _sbWindowSceneHostingFBSSceneIdentityToken:ultimateHostTarget:]_block_invoke
...
(lldb) po $x1
com.apple.preview-shell.system-services/FBSceneManager:SimDisplayScene-133-hosted
Endowment trace from host process:
* thread #7, queue = 'com.apple.root.default-qos.cooperative', stop reason = breakpoint 2.76
frame #0: 0x0000000183b764fc RunningBoardServices`+[RBSEndowmentGrant grantWithNamespace:endowment:]
RunningBoardServices`+[RBSEndowmentGrant grantWithNamespace:endowment:]:
-> 0x183b764fc <+0>: stp x22, x21, [sp, #-0x30]!
0x183b76500 <+4>: stp x20, x19, [sp, #0x10]
0x183b76504 <+8>: stp x29, x30, [sp, #0x20]
0x183b76508 <+12>: add x29, sp, #0x20
Target 0: (PreviewShell) stopped.
(lldb) bt
* thread #7, queue = 'com.apple.root.default-qos.cooperative', stop reason = breakpoint 2.76
* frame #0: 0x0000000183b764fc RunningBoardServices`+[RBSEndowmentGrant grantWithNamespace:endowment:]
frame #1: 0x00000001876bd184 BoardServices`+[BSServiceConnectionEndpointInjector injectorWithConfigurator:] + 684
frame #2: 0x0000000234f5418c PreviewShellKit`___lldb_unnamed_symbol3593 + 1096
frame #3: 0x000000024a30e988 libswift_Concurrency.dylib`swift::runJobInEstablishedExecutorContext(swift::Job*) + 132
frame #4: 0x000000024a30fc28 libswift_Concurrency.dylib`swift_job_runImpl(swift::Job*, swift::SerialExecutorRef) + 156
frame #5: 0x000000018018f9cc libdispatch.dylib`_dispatch_root_queue_drain + 336
frame #6: 0x00000001801903b4 libdispatch.dylib`_dispatch_worker_thread2 + 232
frame #7: 0x00000001000bab90 libsystem_pthread.dylib`_pthread_wqthread + 228
(lldb) po $x2
com.apple.boardservices.endpoint-injection
(lldb) po $x3
{
e = "<NSXPCListenerEndpoint: 0x60000027dda0>";
s = "com.apple.uv.agent-jit-bootstrap-service";
t = "com.apple.preview-shell.system-services";
}