# Bug report — Vega/Kepler automation-toolkit `/screenshot` (submission form)
##
Bug Description
## 1. Summary
The Kepler automation toolkit’s W3C `GET /session/:id/screenshot` endpoint (used via
`@amazon-devices/appium-kepler-driver`) returns an **empty payload**
(`HTTP 200, {“value”: null}`, 0 bytes) as soon as **DRM-protected VOD content**
starts playing in the app. It does **not** recover for the rest of the device’s
uptime — surviving app force-relaunch, Appium session recreation, and re-creating
the toolkit enable file. Only a **device reboot** restores screenshots. Pre-roll
ads still capture fine (a 4 MB screenshot is captured mid-ad in our logs); the
endpoint only breaks when the protected feature video begins. Impact: automated UI
screenshots are lost from the first protected playback onward, removing visual
evidence from test runs (functional/element-tree verification is unaffected).
**App Name:** My app
**App Link on Amazon Appstore:**
**Bug Severity** (select one):
- [ ] Impacts operation of app
- [x] **Other** — Defect in the SDK automation toolkit / Kepler driver
(\`/screenshot\`). Affects **\*\*automated UI testing\*\*** (screenshot capture), not
the app's runtime playback. \*(If your triage prefers it, this can also be
filed as "Blocks current development" — it blocks automated screenshot
evidence in our CI test suite.)\*
- [ ] Blocks current development
- [ ] Improvement suggestion
- [ ] Issue with documentation
- [ ] Other
### 2. Steps to Reproduce
1. Connect to the device via the Kepler driver (`appium-kepler-driver`,
`automationName: automation-toolkit/JSON-RPC`) and create an Appium session over
`vda://:5555`.
2. Call `GET /session/:id/screenshot` — confirm it returns a valid PNG (~2 MB at
1920×1080).
works.
3. In the app, open and play **DRM-protected VOD content** through to the main
feature (i.e. past any pre-roll ads — ads alone do **not** trigger the bug).
4. Call `GET /session/:id/screenshot` again while/after the protected content plays.
5. Observe the endpoint now returns an empty payload, and keeps doing so for every
subsequent call — even after the video stops, the app is force-killed
(`vlcm terminate-app --pkg-id --force`) and relaunched (`vmsgr send
orpheus://`), and the Appium session is recreated.
**Specific component / method triggering it:** the WebDriver/Appium
`GET /session/:id/screenshot` endpoint served by the on-device automation toolkit
(Kepler driver `KeplerDriver`). Not a React Native app-code call.
### 3. Observed Behavior
- Before any protected playback, `/screenshot` reliably returns full PNGs
(~2.0–2.5 MB; one 4 MB capture succeeded **while a pre-roll ad was on screen**).
- The instant the **ad ends and the DRM-protected feature video renders**, every
`/screenshot` call returns `HTTP 200` with `{“value”: null}` (0 bytes).
- The empty state **persists for the rest of device uptime**:
-
it remains empty after the video ends and normal UI is back on screen,
-
`vlcm terminate-app --force` + `vmsgr` relaunch of the app does not clear it,
-
recreating the Appium session does not clear it,
-
re-creating `/tmp/automation-toolkit.enable` does not clear it,
-
the on-device Wayland `screenshooter` fallback also cannot capture (it blocks
until timeout — 0 successful frames).
- A run started after a prior playback run is **blank from step 1** (see log B).
- **Only a reboot** (`vega exec vda reboot`) restores `/screenshot`.
### 4. Expected Behavior
`GET /session/:id/screenshot` should return a PNG of the current screen. For
DRM-protected/secure surfaces where the framebuffer legitimately cannot be read, it
should return a **black/placeholder frame** (or an explicit, distinct error) rather
than an empty `{“value”: null}`, and it should **recover automatically once the
protected content is no longer on screen** (after playback ends / app exit) without
requiring a device reboot.
### 4.a Possible Root Cause & Temporary Workaround
**Likely root cause (hypothesis):** during the protected feature, the compositor
(Weston) promotes the video to a **secure/protected hardware overlay plane**
(HDCP / Widevine-backed) that the toolkit’s frame grabber and the Wayland
`screenshooter` cannot read back, and the protected-plane / capture path is **not
torn down** when playback ends or the app exits — so it stays “unreadable” until
reboot. The ad-vs-feature split (ads capture fine, protected feature does not)
points at content protection rather than “any video”.
**Why we cannot work around it from automation:** the toolkit `mobile: shell` runs
as an unprivileged app sandbox (`uid=5000 app_user`); `systemctl is-system-running`
→ `offline` and `cat /proc/1/comm` → `Permission denied` (process enumeration
blocked), so it cannot restart the compositor or media/DRM services. See attached
`C_capability_probe_20260625.txt`.
**Temporary workaround in use:** detect the stuck state (a `/screenshot` that
returns empty after a previously-successful capture) and reboot the device between test sections, then
continue. Screenshots are sacrificed until the reboot; functional checks continue
via the element tree.
### 5. Logs or crash report
Not a crash — no crash log. Attached app/device logs (ANSI-stripped run logs +
capability probe):
- **`A_Run_20260625_172304_worked_then_broke.log`** — 15 successful captures
(incl. a 4 MB capture at `17:25:37` *during* the ad), then empty from `17:26:02`
when the protected feature starts; never recovers.
- **`B_Run_20260625_173026_blank_from_start.log`** — empty from step 1 despite a
fresh enable-file touch + app force-relaunch (`17:30:37–39`).
- **`C_capability_probe_20260625.txt`** — unprivileged-sandbox evidence (systemd
offline, `/proc` enumeration blocked) showing no soft reset is possible.
- `README.md` — maps the above to the exact lines to read.
*(All four are in the `bug_logs/` folder accompanying this report.)*
## 6. Environment
**SDK Version:** `0.22`
**App State:** Foreground (app is in the foreground, actively playing VOD).
Additional environment (for context):
- Device: Amazon Fire TV (Kepler / Vega), physical device (arm), VDA serial
`G071R20720350DT6`, connected `vda://192.168.x.xx:5555`.
- Appium driver: `@amazon-devices/appium-kepler-driver` **v3.30.0**
(`automationName: automation-toolkit/JSON-RPC`), Appium 2.x on the host.
- Host: Windows 11; test harness uses direct W3C REST calls to the driver.
- Screenshot when working: 1920×1080 PNG, ~2.0–2.5 MB.
- Session capabilities:
```json
{
"platformName": "Kepler",
"appium:automationName": "automation-toolkit/JSON-RPC",
"kepler:device": "vda://192.168.x.xx:5555",
"appium:appURL": "my app",
"appium:newCommandTimeout": 120
}
```
### 7. Example Code Snippet / Screenshots / Screengrabs
Not React Native app code — the trigger is the WebDriver screenshot call. Minimal
repro against a live session (any HTTP client):
```
# 1. works before protected playback → returns a base64 PNG in “value”
GET http://127.0.0.1:4723/session//screenshot
# 2. start DRM-protected VOD (past the ads), then call again:
GET http://127.0.0.1:4723/session//screenshot
# → HTTP 200 {“value”: null} (0 bytes) — and stays empty until reboot
```
Screenshots: cannot attach a “stuck” screenshot — the endpoint returns nothing.
The byte-count timeline in `A_…log` is the evidence (full PNG → null).
—
##
Playback Issues
This is screenshot-capture-during-playback, so the playback context matters:
- **Content:** DRM-protected VOD in RTL+ (RTLDE), title *"Bandit – Catch Him If You
Can"* (deeplink_id `1670749`), opened in-app by search/deeplink.
- **Pre-conditions:** RTL+ catalog is **geo-restricted to Germany**; guest (free)
user; pre-roll ads play before the feature.
- **Architecture:** arm (physical Fire TV device), not the x86 simulator.
Additional details:
**Q: media/content URL**
**Q: special headers required** — N/A (no manual headers; auth/DRM handled in-app).
Note: the bug is **not** about playback itself — VOD plays correctly; it is the
**`/screenshot` capture** that fails while/after protected content is on screen.
—
##
Additional Context
- The empty payload is `HTTP 200 {“value”: null}`, **not** an HTTP error — so it is
indistinguishable from “toolkit not enabled”, which initially sent us down the
wrong path (the `/tmp/automation-toolkit.enable` file). Log **B** rules the enable
file out (fresh touch + relaunch, still empty).
- We verified the reboot recovery path works via `vega exec vda reboot` +
`vega exec vda wait-for-device`.
- Open questions we’d appreciate answers to:
1. Is `/screenshot` empty because the feature moved to a secure/protected plane
(HDCP/Widevine) the grabber can't read?
2. Can the toolkit return a **black frame** (or an explicit error code) for
protected content instead of an empty \`value: null\`?
3. Why does it stay broken **after** playback ends and the app is killed, until
reboot — is the protected plane / decoder session not torn down?
4. Is there a supported **soft reset** (via VDA / a privileged `vega exec vda …`
command) to restore capture without a full reboot?
5. Is this expected on retail Fire TV, or specific to this build / dev unit?