Repository navigation
fix(android): control emulators argent can't find over adb - #1397
blazejkustra wants to merge 3 commits into
Conversation
…ontroller An emulator started outside argent under another HOME (a CI runner, a service account) has no gRPC discovery file where argent looks, so every screenshot, tap and swipe failed with 'not found among running emulators'. Retry such emulators with the screen-sharing (android_device) controller, which only needs adb.
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews:
auto_review:
drafts: true
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
latekvo
left a comment
There was a problem hiding this comment.
[Diplomat, Opus 5.5]: Ran the PR on a real Pixel_6_API_34 emulator started under a separate HOME, comparing this PR with main and with a normally started emulator: screenshot, tap, swipe, pinch, two-finger gesture-custom, rotate, paste, keyboard, buttons, screen recording, stop-simulator-server respawn, and two tool-servers on one device. Ran the shipped Linux simulator-server in a container to check the discovery error paths. Also ran prettier, eslint, both tool-server typechecks and the full tool-server vitest suite (all green), checked that the new test fails on main, and mutation-tested the fallback guard. The core claim reproduces: on main, screenshot, tap and swipe fail on that emulator, and with this PR they work.
| `[sim ${device.id}] emulator not found through gRPC discovery; ` + | ||
| `falling back to the adb screen-sharing controller\n` | ||
| ); | ||
| return spawnSimulatorServerProcess(device.id, "android_device"); |
There was a problem hiding this comment.
[Diplomat, Opus 5.5]: Once an emulator falls back here, two-finger gestures report success but do nothing. Measured on a Pixel_6_API_34 started with HOME=<tmp> emulator -avd Pixel_6_API_34 -read-only -no-window, with Google Maps open:
gesture-pinch(centre 0.5,0.35, distance 0.1 -> 0.5) returnedpinched:true.gesture-customwithx2/y2returned 200.- Neither changed the zoom in 3 attempts. A single-finger pan on the same server works.
The same two calls on main, against a normally started emulator on the android controller, zoom in and out. The device keeps kind: "emulator", so nothing downstream knows it is now behind the phone controller. Before this change these calls failed with SIMULATOR_SERVER_READY_EXITED; now they report a gesture that never happened.
There was a problem hiding this comment.
Leaving open: making two-finger gestures work on the phone controller, or rejecting them for a fallen-back emulator (it keeps kind: "emulator"), is a design call for a human, not an unattended change.
| device.id, | ||
| subcommandForDevice(device) | ||
| ); | ||
| const { proc, apiUrl, streamUrl } = await spawnWithEmulatorFallback(device); |
There was a problem hiding this comment.
[Diplomat, Opus 5.5]: A tap that is the first call to reach a fallen-back emulator is reported as done but does not land. Each trial: Settings open, search bar frame from uiautomator dump [42,591][1038,728] on a 1080x2400 screen, then stop-simulator-server, then gesture-tap at (0.5, 0.2747), then the top activity after 2 s.
| Run | Tap result | Top activity |
|---|---|---|
| This PR, fallen-back emulator, tap as the first call | tapped:true (~1.1 s) |
.Settings in 3/3 |
This PR, same, one screenshot before the tap |
tapped:true |
SearchActivity in 3/3 |
| main, normal emulator, tap as the first call | tapped:true |
SearchActivity in 3/3 |
Every respawn of this service is exposed: first use, after stop-simulator-server, and after the registry's connection-refused recovery. Each one hands back a server whose first touch is silently dropped.
There was a problem hiding this comment.
Leaving open: the dropped first tap needs a warm-up or readiness fix verified on a real emulator, which I did not do unattended.
| `[sim ${device.id}] emulator not found through gRPC discovery; ` + | ||
| `falling back to the adb screen-sharing controller\n` | ||
| ); | ||
| return spawnSimulatorServerProcess(device.id, "android_device"); |
There was a problem hiding this comment.
[Diplomat, Opus 5.5]: Two tool-servers driving one fallen-back emulator evict each other. Each android_device start kills the screen-sharing agents already on the device, so the other server's simulator-server exits (status 143) and respawns on its next call, at 1.3-1.6 s per alternating call. The tap after such a respawn is the dropped first tap described on line 598. Two android servers on a normally started emulator coexist, with every frame fresh.
There was a problem hiding this comment.
Leaving open: two tool-servers evicting each other comes from the android_device controller killing existing agents; fixing that is simulator-server work or a product decision on whether to accept it for this fallback.
| `[sim ${device.id}] emulator not found through gRPC discovery; ` + | ||
| `falling back to the adb screen-sharing controller\n` | ||
| ); | ||
| return spawnSimulatorServerProcess(device.id, "android_device"); |
There was a problem hiding this comment.
[Diplomat, Opus 5.5]: The phone controller leaves state on the emulator that the emulator controller never touches:
- Each spawn adds an
adb reverseforscreen-sharing-agent-*that is never removed. There were 11 after one session of restarts. - The 9.5 MB agent stays in
/data/local/tmp/.studio. rotatesetsaccelerometer_rotation=0and leaves it there. On main's emulator path it stays1.
For an emulator someone else started, all of this persists after argent is gone.
There was a problem hiding this comment.
Leaving open: cleaning up the adb reverse, the pushed agent and accelerometer_rotation on an emulator argent did not start needs a decision on what argent should own and undo.
| `[sim ${device.id}] emulator not found through gRPC discovery; ` + | ||
| `falling back to the adb screen-sharing controller\n` | ||
| ); | ||
| return spawnSimulatorServerProcess(device.id, "android_device"); |
There was a problem hiding this comment.
[Diplomat, Opus 5.5]: Screenshots through the fallback come from a 920x2044 stream instead of the emulator's 1080x2400. A default-scale screenshot is 230x511 here and 270x600 on the gRPC path of the same AVD. So screenshot-diff reports dimension_mismatch when one side was captured on the normal path and the other through this fallback.
There was a problem hiding this comment.
Leaving open: the 920x2044 stream size comes from the phone controller; matching the gRPC path resolution (or documenting the mismatch) needs a human decision.
…ectory On Linux, a user with no avd/running directory gets 'Failed to find any running emulator' instead of 'not found among running emulators', so the fallback never triggered there. Match both, keep the emulator controller's error when the adb fallback fails too, and update the comments that said emulators always use the gRPC bridge.
Problem
An Android emulator started outside argent under a different home directory (for example by another tool or user account) could not be screenshotted, tapped or swiped: argent did not find it, and each of those calls failed.
Approach
argent now falls back to controlling such an emulator over adb, the way it already controls physical phones. That path does not need to find the emulator first, so it works.
Tests
HOME=<other dir> emulator -avd <avd> -read-only -no-window: on main,screenshot,gesture-tapandgesture-swipefailed (3 of 3); with this PR all three work (search opened, app drawer opened).buttonandkeyboardgo through adb and work on both builds.emulator -read-only -no-windowor token-less-grpc 8554launch already works on main, so it is unaffected.Screenshots
Before
android-emu-before.mp4
After
android-emu-after.mp4