Skip to content

scroll "bottom" fails deterministically on Pixel 9 Pro XL API 37 emulator: helper returns invalid gesture viewport #1332

Description

@thymikee

Summary

Surfaced while capturing device footage for a blog post. scroll "bottom" fails deterministically
(3/3) on the Pixel 9 Pro XL API 37 emulator (emulator-5556) with:

COMMAND_FAILED: Android helper returned an invalid gesture viewport

preceded by a helper warning:

android_touch_helper_viewport_session_fallback  reason: "unknown session command"

Non-scroll operations (open, get, is, press, back, record) all work normally on this
same emulator/session. This looks like the daemon's session-scoped viewport-detection path issuing
a command the on-device snapshot helper doesn't recognize, and the one-shot fallback that's
supposed to catch that failure also fails to produce a usable gesture viewport.

Repro

open com.android.settings --relaunch
scroll bottom

Result: COMMAND_FAILED: Android helper returned an invalid gesture viewport.

Reproduced on three separate daemon builds, ruling out a build-specific regression:

  • 3fed8acda
  • a84caa818 (current main HEAD at the time of testing)
  • d85165842

Environment: Pixel 9 Pro XL API 37 emulator (emulator-5556), on-device snapshot helper
agent-device-android-snapshot-helper-0.19.3.apk.

Root cause (read from source)

readAndroidTouchHelperViewport (src/platforms/android/touch-helper.ts:106-127) first tries a
session-scoped viewport command against the persistent helper:

const sessionHeaders = await runAndroidSnapshotHelperSessionTouchCommand({
  deviceKey: prepared.deviceKey,
  action: 'viewport',
  helper: touchSessionHelperIdentity(prepared.artifact),
  timeoutMs: HELPER_VIEWPORT_TIMEOUT_MS,
});
if (sessionHeaders) return readViewportResult(sessionHeaders);

On this emulator/helper combination that command throws, and the catch block logs the
android_touch_helper_viewport_session_fallback warning with the underlying error message as
reason — which is exactly "unknown session command", i.e. the persistent
UiAutomation-instrumentation session (Java: SnapshotInstrumentation, which emits "unknown session command" at
android/snapshot-helper/src/main/java/com/callstack/agentdevice/snapshothelper/SnapshotInstrumentation.java:201)
does not recognize whatever session command the daemon sent for action: 'viewport'.

The catch block then stops the session and falls back to a one-shot instrumentation run
(runOneShotTouchHelper with mode=viewport, same file, ~line 127-135). On this emulator that
fallback also fails to produce a usable viewport, and the caller surfaces the generic:

throw new AppError('COMMAND_FAILED', 'Android helper returned an invalid gesture viewport');

(src/platforms/android/gesture-viewport.ts:13, and the equivalent check in
src/platforms/android/touch-helper.ts:306), which is what scroll (and presumably other
gesture-planned commands that need a viewport) sees.

Since open/get/is/press/back/record don't go through this gesture-viewport resolution
path, they're unaffected — this narrows the bug to the viewport-detection session command
specifically, not the helper or session machinery broadly.

Note

The resulting divergence signature (when this is hit via the replay/differential machinery) has
the same shape as div_plain_1.json already used elsewhere in the wave-3 evidence set. This is
likely related to the existing gesture-viewport / Android-helper-scroll work (see the
android-helper-scroll-attrs-authoritative and android-automation-helper-consolidation lines of
work) — worth checking whether the persistent helper's session-command protocol (post the #1281
single-persistent-helper consolidation) has a gap for the viewport action specifically on this
API level/device combination.

Source leads

  • src/platforms/android/touch-helper.ts:
    • readAndroidTouchHelperViewport (~line 106) — session-scoped viewport attempt, catch +
      fallback-to-one-shot.
    • Line ~124: phase: 'android_touch_helper_viewport_session_fallback' diagnostic emission.
    • Line ~306: 'Android helper returned an invalid gesture viewport' (one-shot fallback also
      failing).
  • src/platforms/android/gesture-viewport.ts:13 — same error string, gesture-plan-level check.
  • android/snapshot-helper/src/main/java/com/callstack/agentdevice/snapshothelper/SnapshotInstrumentation.java:201
    "unknown session command" source of the fallback's reason.

Repro builds / environment

  • Builds tested: 3fed8acda, a84caa818 (main HEAD), d85165842 — all fail identically.
  • Emulator: Pixel 9 Pro XL API 37, emulator-5556.
  • Helper: agent-device-android-snapshot-helper-0.19.3.apk.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions