Five commits. The first two re-derive the API 37 failure; the last three close nine findings from the overnight review.
The correction
docs/api-37-emulator-crash.md claimed "Both swiftshader_indirect and host crash… the crash is in the gralloc mapper, below the renderer."The renderer decides whether API 37 boots, 7 runs for 7 — it boots iff the emulator log says something other than gles_mode_selected:host.
-gpu
image
boots?
host
37.0 rev6 and 37.1 rev8
no — 71 aborts, looping
swangle_indirect / angle_indirect
37.0
yes — 85 s, 1 abort
This is the exact inverse of API 33–36, where host works and SwiftShader segfaults the host. The harness now chooses per level (gpu_for_api).
Why the old claim looked right: the local swiftshader_indirect sample was void — every SwiftShader-GLES launch segfaults this host via the execheap bug, which was not understood when that file was written. So "both GPU modes" was one CI sample plus one local -gpu host sample. ANGLE had never been tried.
Mechanism: SystemUI nav-bar luma sampling → SF RegionSamplingThread locks a GraphicBuffer → Gralloc5 → GoldfishMapper::readFromHost asserts → init SIGKILLs zygote, restarting the framework mid-test.
CI should still stop at API 36 — CI runs swiftshader on a GPU-less runner, the working config needs SystemUI disabled, and 37 is permanently 47/49 (two CodecExceptions on c2.goldfish.h264.decoder; API 35 under the same renderer is green, so it is the image).
The negotiation claim now rests on the aborts under ANGLE, not on an SDK string search
Two false claims fell out of R4 rather than being renumbered: "47 of 49" is not a ratio when 2 of the 49 are skips (45+2+2), and "matches the Pixel baseline of 49/0/0/2 exactly"describes a run that never happened — the Pixel measured 40/0/0/2 at edd6385.
Validation
bash -n clean throughout. shellcheck is not installed here, so two stub harnesses were built instead: a lifecycle test (13 checks) that demonstrates the empty-pid kill really does hit the sender's process group and that the fix signals nothing; and a smoke test driving the real script end to end on the boot-failure path (22 checks). All pass. No emulator was booted and no sweep was run — every finding here was fixable by reading.
Held, not done
R32 (#41) is not PLAUSIBLE — it was reproduced.yes | sdkmanager under pipefail returns 141 even on success, so a successful install reports "FAILED". It should bite nearly every install, and this branch makes the install path the normal path. Untouched: fixing it means handling sdkmanager's licence prompt, which needs a machine with the image uninstalled to validate. Ticket relabelled CONFIRMED.
R19 (#28) — status_check.yml's API-37 comment is falsified by this branch. .github/ deliberately not opened.
The exit-code semantics were documented, not changed. Subtracting 37's contribution reverses a recorded decision — the repo owner's call.
Five commits. The first two re-derive the API 37 failure; the last three close nine findings from the overnight review.
## The correction
`docs/api-37-emulator-crash.md` claimed *"Both `swiftshader_indirect` and `host` crash… the crash is in the gralloc mapper, below the renderer."* **The renderer decides whether API 37 boots**, 7 runs for 7 — it boots iff the emulator log says something other than `gles_mode_selected:host`.
| `-gpu` | image | boots? |
|---|---|---|
| `host` | 37.0 rev6 **and** 37.1 rev8 | **no** — 71 aborts, looping |
| `swangle_indirect` / `angle_indirect` | 37.0 | **yes** — 85 s, 1 abort |
**This is the exact inverse of API 33–36**, where `host` works and SwiftShader segfaults the host. The harness now chooses per level (`gpu_for_api`).
**Why the old claim looked right:** the local `swiftshader_indirect` sample was *void* — every SwiftShader-GLES launch segfaults this host via the `execheap` bug, which was not understood when that file was written. So "both GPU modes" was one CI sample plus one local `-gpu host` sample. **ANGLE had never been tried.**
Mechanism: SystemUI nav-bar luma sampling → SF `RegionSamplingThread` locks a GraphicBuffer → Gralloc5 → `GoldfishMapper::readFromHost` asserts → **init SIGKILLs zygote**, restarting the framework mid-test.
**CI should still stop at API 36** — CI runs swiftshader on a GPU-less runner, the working config needs SystemUI disabled, and 37 is permanently 47/49 (two `CodecException`s on `c2.goldfish.h264.decoder`; API 35 under the same renderer is green, so it is the image).
## Review findings closed
| | |
|---|---|
| R17 #26 | `cleanup` now runs on EXIT/INT/TERM — an interrupted sweep no longer leaks the emulator, AVD and port |
| R31 #40 | `kill -9 "${EMU_PID:-0}"` **signalled the whole process group** when empty. Narrowed. |
| R33 #42 | `avd_config_path` searches every directory avdmanager honours; an unwritable `config.ini` fails the level instead of running at default RAM |
| R34 #43 | Deleted a property loop that never waited; named the service check as the real wait |
| R4 #13 · R20 #29 | Suite size is now **derived, not written down** — the total equals the checkout's `@Test` count, and a grep is given so a *mismatch* is the signal |
| R16 #25 | The default sweep is red **by design**; now documented, with the note printed only when 37.x is the sole red level |
| R27 #36 | "sole trigger" → "dominant trigger", residue named as undecided |
| R28 #37 | The negotiation claim now rests on the aborts under ANGLE, not on an SDK string search |
**Two false claims fell out of R4** rather than being renumbered: "47 of 49" is not a ratio when 2 of the 49 are skips (45+2+2), and *"matches the Pixel baseline of 49/0/0/2 exactly"* **describes a run that never happened** — the Pixel measured 40/0/0/2 at `edd6385`.
## Validation
`bash -n` clean throughout. **`shellcheck` is not installed here**, so two stub harnesses were built instead: a lifecycle test (13 checks) that *demonstrates* the empty-pid kill really does hit the sender's process group and that the fix signals nothing; and a smoke test driving the **real script** end to end on the boot-failure path (22 checks). All pass. **No emulator was booted and no sweep was run** — every finding here was fixable by reading.
## Held, not done
- **R32 (#41) is not PLAUSIBLE — it was reproduced.** `yes | sdkmanager` under `pipefail` returns 141 even on success, so a successful install reports "FAILED". It should bite nearly every install, and this branch makes the install path the normal path. Untouched: fixing it means handling sdkmanager's licence prompt, which needs a machine with the image uninstalled to validate. Ticket relabelled CONFIRMED.
- **R19 (#28)** — `status_check.yml`'s API-37 comment is falsified by this branch. `.github/` deliberately not opened.
- **The exit-code semantics** were documented, not changed. Subtracting 37's contribution reverses a recorded decision — the repo owner's call.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Five commits. The first two re-derive the API 37 failure; the last three close nine findings from the overnight review.
The correction
docs/api-37-emulator-crash.mdclaimed "Bothswiftshader_indirectandhostcrash… the crash is in the gralloc mapper, below the renderer." The renderer decides whether API 37 boots, 7 runs for 7 — it boots iff the emulator log says something other thangles_mode_selected:host.-gpuhostswangle_indirect/angle_indirectThis is the exact inverse of API 33–36, where
hostworks and SwiftShader segfaults the host. The harness now chooses per level (gpu_for_api).Why the old claim looked right: the local
swiftshader_indirectsample was void — every SwiftShader-GLES launch segfaults this host via theexecheapbug, which was not understood when that file was written. So "both GPU modes" was one CI sample plus one local-gpu hostsample. ANGLE had never been tried.Mechanism: SystemUI nav-bar luma sampling → SF
RegionSamplingThreadlocks a GraphicBuffer → Gralloc5 →GoldfishMapper::readFromHostasserts → init SIGKILLs zygote, restarting the framework mid-test.CI should still stop at API 36 — CI runs swiftshader on a GPU-less runner, the working config needs SystemUI disabled, and 37 is permanently 47/49 (two
CodecExceptions onc2.goldfish.h264.decoder; API 35 under the same renderer is green, so it is the image).Review findings closed
cleanupnow runs on EXIT/INT/TERM — an interrupted sweep no longer leaks the emulator, AVD and portkill -9 "${EMU_PID:-0}"signalled the whole process group when empty. Narrowed.avd_config_pathsearches every directory avdmanager honours; an unwritableconfig.inifails the level instead of running at default RAM@Testcount, and a grep is given so a mismatch is the signalTwo false claims fell out of R4 rather than being renumbered: "47 of 49" is not a ratio when 2 of the 49 are skips (45+2+2), and "matches the Pixel baseline of 49/0/0/2 exactly" describes a run that never happened — the Pixel measured 40/0/0/2 at
edd6385.Validation
bash -nclean throughout.shellcheckis not installed here, so two stub harnesses were built instead: a lifecycle test (13 checks) that demonstrates the empty-pid kill really does hit the sender's process group and that the fix signals nothing; and a smoke test driving the real script end to end on the boot-failure path (22 checks). All pass. No emulator was booted and no sweep was run — every finding here was fixable by reading.Held, not done
yes | sdkmanagerunderpipefailreturns 141 even on success, so a successful install reports "FAILED". It should bite nearly every install, and this branch makes the install path the normal path. Untouched: fixing it means handling sdkmanager's licence prompt, which needs a machine with the image uninstalled to validate. Ticket relabelled CONFIRMED.status_check.yml's API-37 comment is falsified by this branch..github/deliberately not opened.🤖 Generated with Claude Code