Repository navigation
fix(mobilerun): bound the state snapshot so a stuck app can't hang it - #43
Merged
Merged
Conversation
GET /mobilerun/state took one snapshot through XCTest, which waits up to its 60s accessibility timeout per request and retries on top. On an iPhone X / iOS 16 TikTok never finished snapshotting, so each state request held the runner for minutes and every request queued behind it, Home Screen included, timed out in mobilerun-ios and the CLI (DROID-305). Snapshots are now requested directly, without XCTest's resolution retries, under a temporary accessibility timeout: 10s for the full tree, then 5s for a shallow one (15 levels, 20 children per element). If neither finishes, the state still names the foreground app, which is known without a snapshot, with the app root alone as the tree. 'truncated' says when the tree is incomplete. The request now always answers 200, so a failed snapshot can't read as a missing route either. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…er's screen
On a device the runner app has no launch screen, so iOS runs it in the
letterboxed compatibility mode: its UIScreen bounds and nativeBounds both
describe a 320x480 screen. The root-only state for an app that could not
be snapshotted came out 480x480 on an iPhone XR (414x896). SpringBoard's
frame from a depth-1 snapshot (2s limit) gives the real screen, and it
answers while the app is stuck.
Verified on an iPhone XR (iOS 18.7.7): right after a cold start TikTok
stops answering accessibility requests ("Error getting main window
kAXErrorIPCTimeout"). /mobilerun/state now answers in 15.1s with
packageName com.zhiliaoapp.musically and an 896x896 root.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Timo972
marked this pull request as ready for review
October 22, 2026 06:57
niko-droidrun
approved these changes
Oct 23, 2026
Timo972
added a commit
that referenced
this pull request
Oct 23, 2026
Resolve the conflict with #43 (bounded state snapshot): the focused node is picked from the snapshot master now passes into fb_mobilerunA11yStateWithSnapshot:scale:truncated:, and the tree keeps master's SpringBoard-sized fallback root when no snapshot could be taken. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes DROID-305 (droidrun/mobilerun#484):
mobilerun device ui --ioshangs on an iPhone X / iOS 16.7 with TikTok, and on the Home Screen after that.Cause
GET /mobilerun/statetook its snapshot through XCTest (snapshotWithError:). XCTest waits up to its 60s accessibility timeout per request and retries on top of that ("Find the Application … (retry N)"). The reporter's debug log shows WDA silent for 61s on a single TikTok snapshot request.WDA handles one request at a time, so every later request queued behind the stuck snapshot. That includes requests made after going back to the Home Screen. mobilerun-ios hit its 60s deadline (and its recovery probe did too), and the CLI timed out after 30s on each of its 7 attempts.
Change
FBXCAXClientProxy), without XCTest's resolution retries, under a temporary accessibility timeout.phone_state.packageName). The app is detected without a snapshot, and the app root alone serves as the tree. Released mobilerun-ios rejects anulltree and drops a mostly off-screen childless root, so the root spans a square covering the screen in either orientation.truncatedfield. Released mobilerun-ios ignores it.Verification
truncated: trueand the rightpackageName.testSnapshotTimeoutDoesNotOutliveTheSnapshot): fails with the restore disabled (a later snapshot gave up after 1.01s), passes with it in place.UnitTests256/256 (1 skipped).FBMobilerunA11yIntegrationTestsandFBMobilerunActionsIntegrationTests7/7. tvOS lib builds.accessibilityDeadlinetest.Real device: iPhone XR, iOS 18.7.7, TikTok 45.7
Installed through
mobilerun-ios setup --reinstall --wda-unsigned-url …(ASC signing), the same path users take.Reproduced the hang on iOS 18. Right after a cold start, TikTok stops answering accessibility requests ("Error getting main window kAXErrorIPCTimeout") for minutes.
With this PR:
GET /mobilerun/stateanswers in 15.1s every time. The full snapshot gives up at 10s, the shallow one at 5s, and the answer is root-only withpackageName: com.zhiliaoapp.musicallyandtruncated: true./state_fullit takes 15.1–18.8s. The extra time is spent in the portal, not in WDA.mobilerun device ui --ios(mobilerun 0.6.20) with TikTok in front and stuck: returns in 16.5s with TikTok's package name and no retries.truncated: false. Same speed as the old runner (0.31–0.75s).Bug found on the device and fixed in f7e4623: the root-only fallback was sized from the runner's
UIScreen, which on a device is the letterboxed 320×480 compatibility screen, so it came out 480×480.nativeBoundsis scaled the same way. It now uses SpringBoard's frame (depth-1 snapshot, 2s limit), which gives 896×896 on the XR. The simulator can't show this, because the runner isn't letterboxed there.Still unverified: iOS 16 (the reporter's iPhone X). If
_setAXTimeoutfails there, WDA logs it and falls back to the old, unbounded behavior. A preview build goes to the reporter.Follow-ups (other repos)
truncated.ReadTimeout.🤖 Generated with Claude Code