Skip to content

fix: clean up Android snapshot helper sessions#862

Merged
thymikee merged 1 commit into
mainfrom
fix/android-snapshot-helper-lifecycle
Jun 24, 2026
Merged

fix: clean up Android snapshot helper sessions#862
thymikee merged 1 commit into
mainfrom
fix/android-snapshot-helper-lifecycle

Conversation

@thymikee

Copy link
Copy Markdown
Member

Summary

Fixes Android snapshot-helper ownership so standalone snapshot commands stop the persistent helper session after capture, releasing Android's single UiAutomation connection for uiautomator, Espresso, Appium, and other consumers.

App-backed daemon sessions still opt into persistent helper reuse, and close/teardown now stops the Android snapshot helper alongside other session-owned resources.

Closes #851

Touched files: 7.

Validation

Focused unit coverage passed for Android snapshot helper cleanup/reuse and session close teardown: pnpm exec vitest run src/platforms/android/__tests__/snapshot.test.ts src/platforms/android/__tests__/snapshot-helper-session.test.ts src/daemon/handlers/__tests__/session-close-shutdown.test.ts.

Static/build checks passed via direct installed binaries because the pnpm script wrapper hung or failed registry signature verification in this environment: oxlint . --deny-warnings, tsc -p tsconfig.json, rslib build, and node --test test/integration/smoke-*.test.ts.

Live Android emulator verification passed on emulator-5554: after node bin/agent-device.mjs --state-dir /private/tmp/agent-device-851-state snapshot --platform android --serial emulator-5554, adb shell ps -A | rg "snapshothelper|uiautomator|am instrument" returned no helper/instrumentation process, and adb shell uiautomator dump /data/local/tmp/agent-device-851.xml wrote the XML file successfully. No related #850 PR was found to sequence against.

@github-actions

github-actions Bot commented Jun 24, 2026

Copy link
Copy Markdown

Size Report

Metric Base Current Diff
JS raw 1.3 MB 1.3 MB -4.3 kB
JS gzip 430.3 kB 429.5 kB -791 B
npm tarball 566.5 kB 565.8 kB -777 B
npm unpacked 1.9 MB 1.9 MB -4.3 kB

Startup median (7 runs, lower is better):

Scenario Base Current Diff
CLI --version 26.4 ms 25.9 ms -0.5 ms
CLI --help 45.4 ms 45.5 ms +0.0 ms

Top changed chunks:

Chunk Raw diff Gzip diff
dist/src/find.js +8.8 kB +3.5 kB
dist/src/selector-runtime.js -2.5 kB -757 B
dist/src/2948.js -2.9 kB -458 B
dist/src/9722.js +334 B +106 B
dist/src/7394.js +177 B +52 B

@thymikee

Copy link
Copy Markdown
Member Author

Review: clean up Android snapshot helper sessions

Solid, well-scoped, and well-tested. I verified the lifecycle concerns and they hold up:

  • stopAndroidSnapshotHelperSession early-returns when no session exists, so the new finally double-stopping after the catch path (recoverAndroidHelperCaptureFailure already stops) is a harmless no-op.
  • The deleted local getAndroidSnapshotHelperDeviceKey has no other references; the replacement getAndroidSnapshotHelperSessionDeviceKey produces the identical ${platform}:${id} key.
  • The finally is correctly gated by commandScopedHelperSession, so daemon-session reuse is preserved.

Minor follow-ups (non-blocking):

  1. appBundleId → scope is an implicit proxy. In src/core/interactors/android.ts you map options?.appBundleId ? 'daemon-session' : 'command'. Correct in practice (daemon sessions set appBundleId after open; one-off CLI snapshots don't), but the coupling is non-obvious — a one-line comment ("presence of appBundleId ⇒ app-backed daemon session ⇒ reuse the persistent helper") would save the next reader. Also worth a quick check that no standalone snapshot path can carry an appBundleId and thereby keep a session alive (the finally is the safety net either way).

  2. Teardown is unconditional for Android sessionsstopSessionAndroidSnapshotHelper calls through even when no helper ran. Fine given idempotency; just confirming that's intended.

  3. Coordinate with fix: recover Android snapshots from system-only helper output #861 — it rewrites the same captureAndroidUiHierarchyWithHelper region and will conflict. This one should merge first.

LGTM once the above are acknowledged.

🤖 Automated review via Claude Code

@thymikee thymikee force-pushed the fix/android-snapshot-helper-lifecycle branch from feb6ed3 to fee6b76 Compare June 24, 2026 16:11
@thymikee

Copy link
Copy Markdown
Member Author

Addressed the actionable follow-up: added a comment at the Android interactor scope decision explaining why app-backed daemon sessions use persistent helper reuse while standalone snapshots release the helper after capture.

Also confirming the other notes:

Re-ran: oxfmt --write src/core/interactors/android.ts, oxlint src/core/interactors/android.ts --deny-warnings, tsc -p tsconfig.json.

@thymikee thymikee merged commit 5be101c into main Jun 24, 2026
20 checks passed
@thymikee thymikee deleted the fix/android-snapshot-helper-lifecycle branch June 24, 2026 17:29
@github-actions

Copy link
Copy Markdown
PR Preview Action v1.8.1
Preview removed because the pull request was closed.
2026-06-24 17:29 UTC

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Snapshot leaves the snapshot-helper instrumentation running, squatting the single UiAutomation connection

1 participant