From e5f097f9e1a198d285e19c8beecf5c7659f79c14 Mon Sep 17 00:00:00 2001 From: Swung0x48 Date: Sat, 3 Oct 2026 02:25:34 -0400 Subject: [PATCH] [Docs] (Anland): add a Chrome device-loss recovery test and the GPU-process launch mode. --- .../skills/anland-mobilegl-plasma/SKILL.md | 3 +- .../scripts/chrome-launch.sh | 13 +- .../scripts/chrome-recover.sh | 146 ++++++++++++++++++ 3 files changed, 157 insertions(+), 5 deletions(-) create mode 100644 .claude/skills/anland-mobilegl-plasma/scripts/chrome-recover.sh diff --git a/.claude/skills/anland-mobilegl-plasma/SKILL.md b/.claude/skills/anland-mobilegl-plasma/SKILL.md index d8e59ad9..552d7ff6 100644 --- a/.claude/skills/anland-mobilegl-plasma/SKILL.md +++ b/.claude/skills/anland-mobilegl-plasma/SKILL.md @@ -125,7 +125,8 @@ mgrun offscreen eglinfo -B ; mgrun offscreen glxinfo -B timeout 25 mgrun offscreen glmark2-es2-wayland -s 1280x720 --run-forever > /tmp/gm.out 2>&1 & sleep 8; grep -a "presented through" /tmp/mgl-run.client.log ``` -Chrome: `bash scripts/chrome-launch.sh [flags]` (log `/tmp/mgl-chrome-.client.log`, screenshot `ch-.png`). +Chrome: `bash scripts/chrome-launch.sh [flags]` (log `/tmp/mgl-chrome-.client.log`, screenshot `ch-.png`; `CHROME_GPU=process` runs the GPU in its own process, which needs the anland startup script that knows `MOBILEGL_CHROME_GPU`). +Device loss: `setprop debug.mobilegl.inject_device_lost_pid ` (as root) loses the server session of the client whose pid - as it sees itself in the container - is ``, once per value, on any backend and whether or not it presents; `debug.mobilegl.inject_device_lost_at N` instead loses whichever session makes the N-th device check (Espryt presents and read-backs only). `bash scripts/chrome-recover.sh [rounds]` checks that Chrome repaints after such a loss without a restart (battery-guarded, stops below 40%). Probes: `scripts/probes/texfmt.c` (texture formats keep alpha?), `dmahash.c` (hash a process's dma-bufs); build in the container, e.g. `gcc -O1 /root/texfmt.c -o /usr/local/bin/mgl-texfmt -lEGL`, run with `mgrun offscreen`. A result counts only if ALL hold: diff --git a/.claude/skills/anland-mobilegl-plasma/scripts/chrome-launch.sh b/.claude/skills/anland-mobilegl-plasma/scripts/chrome-launch.sh index 0be8d77b..5f2279b0 100644 --- a/.claude/skills/anland-mobilegl-plasma/scripts/chrome-launch.sh +++ b/.claude/skills/anland-mobilegl-plasma/scripts/chrome-launch.sh @@ -1,10 +1,14 @@ #!/usr/bin/env bash # chrome-launch.sh [extra chrome flags...] - (re)start Chrome inside the running Plasma session -# through mobilegl-startup.sh's `chrome` mode (ANGLE GLES over MobileGL EGL, in-process GPU), client -# log /tmp/mgl-chrome-.client.log, then print its "presented through" line and save a screenshot +# through mobilegl-startup.sh's `chrome` mode (ANGLE GLES over MobileGL EGL), client log +# /tmp/mgl-chrome-.client.log, then print its "presented through" line and save a screenshot # to $ANL_DIR/ch-.png. Kills the running chrome first (pkill -x, never -f). MobileGL is the # container's system-wide vendor (10_mobilegl.json + /etc/mobilegl/client.conf), so only the log is set here. -# Env: WAIT (s before checking, default 20), CHANNEL (ct.sh channel, default chrome). +# Env: WAIT (s before checking, default 20), CHANNEL (ct.sh channel, default chrome), +# CHROME_GPU (in-process, the default, or process: the GPU in its own process, which presents +# through GBM dma-bufs and is restarted by Chrome after a device loss - needs the startup +# script that knows MOBILEGL_CHROME_GPU; with process both the GPU process and the browser +# write the one client log, the GPU process last); CHROME_GPU_SANDBOX=on keeps its GPU sandbox. set -euo pipefail here=$(cd "$(dirname "$0")" && pwd) . "$here/env.sh" @@ -12,7 +16,8 @@ TAG=${1:?usage: chrome-launch.sh [chrome flags...]}; shift bash "$here/ct.sh" "${CHANNEL:-chrome}" < /tmp/chrome-$TAG-out.log 2>&1 &' +rm -f /tmp/mgl-chrome-$TAG.client.log /tmp/chrome-$TAG-out.log +sudo -u $MGL_DESKTOP_USER env XDG_RUNTIME_DIR=/run/user/\$U WAYLAND_DISPLAY=wayland-0 DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/\$U/bus MOBILEGL_LOG_FILE_PATH=/tmp/mgl-chrome-$TAG.log MOBILEGL_CHROME_GPU=${CHROME_GPU:-in-process} MOBILEGL_CHROME_GPU_SANDBOX=${CHROME_GPU_SANDBOX:-off} bash -c 'nohup /opt/mobilegl/bin/mobilegl-startup.sh chrome --restore-last-session $* > /tmp/chrome-$TAG-out.log 2>&1 &' sleep ${WAIT:-20} grep -ah 'presented through' /tmp/mgl-chrome-$TAG.client.log | head -3 IN diff --git a/.claude/skills/anland-mobilegl-plasma/scripts/chrome-recover.sh b/.claude/skills/anland-mobilegl-plasma/scripts/chrome-recover.sh new file mode 100644 index 00000000..a0cf7852 --- /dev/null +++ b/.claude/skills/anland-mobilegl-plasma/scripts/chrome-recover.sh @@ -0,0 +1,146 @@ +#!/usr/bin/env bash +# chrome-recover.sh [rounds] - does Chrome repaint after a GPU device loss, +# without a restart? Starts Chrome (chrome-launch.sh, CHROME_GPU=) on an animated WebGL page, +# then per round: screenshots (the page must animate), loses the session of Chrome's GPU client with +# the server's pid-targeted debug knob (debug.mobilegl.inject_device_lost_pid; the pid as Chrome sees +# itself in the container), waits, and screenshots again. A round PASSES when the server latched +# that pid's session, the browser process is the same one (no restart), a GPU client is drawing on a +# NEW server session, and the screen still animates. Stops early below MIN_BATTERY percent. +# +# in-process the GPU in the browser process (the startup script's default today): the target is +# the browser itself; recovery needs ANGLE to make a new native context. +# process the GPU in its own process (MOBILEGL_CHROME_GPU=process): the target is the GPU +# process; Chrome restarts it after the loss, so the next round's target is a new pid. +# +# Deploy first (same MobileGL commit on both sides; see SKILL.md): +# bash scripts/build-android.sh && bash scripts/cyc.sh pre # server -> APK, restarts the session +# bash scripts/xbuild.sh && bash scripts/xdeploy.sh # client -> container +# STARTUP=/producers/kde/Arch_v5/mobilegl-startup.sh bash scripts/chrome-recover.sh deploy-startup +# Env: ROUNDS (default 2), SETTLE (s after the loss, default 8), MIN_BATTERY (default 40), +# CHANNEL (ct.sh channel, default crec), TAG (log tag, default crec-). +set -euo pipefail +here=$(cd "$(dirname "$0")" && pwd) +. "$here/env.sh" +MODE=${1:?usage: chrome-recover.sh [rounds]} +ROUNDS=${2:-${ROUNDS:-2}} +SETTLE=${SETTLE:-8} +MIN_BATTERY=${MIN_BATTERY:-40} +CH=${CHANNEL:-crec} +TAG=${TAG:-crec-$MODE} +PAGE=/tmp/mgl-spin.html + +ct() { bash "$here/ct.sh" "$CH"; } + +battery() { adb_ shell dumpsys battery | tr -d '\r' | awk '/ level:/ {print $2}'; } +check_battery() { + local level; level=$(battery) + echo "battery: $level%" + if [ -n "$level" ] && [ "$level" -lt "$MIN_BATTERY" ]; then + echo "STOP: battery below $MIN_BATTERY%"; cleanup; exit 3 + fi +} +cleanup() { adb_ shell "su -c 'setprop debug.mobilegl.inject_device_lost_pid 0'" || true; } + +if [ "$MODE" = deploy-startup ]; then + # The anland startup script that knows MOBILEGL_CHROME_GPU, installed by rename (a running + # session keeps its open copy). + src=${STARTUP:?STARTUP=} + tr -d '\r' < "$src" > "$ANL_DIR/mobilegl-startup.sh" + adb_ push "$ANL_DIR/mobilegl-startup.sh" "$DEV_SHARE/mobilegl-startup.sh.new" >/dev/null + ct <<'IN' +install -m 755 /run/anland-mobilegl/mobilegl-startup.sh.new /opt/mobilegl/bin/mobilegl-startup.sh.new +mv -f /opt/mobilegl/bin/mobilegl-startup.sh.new /opt/mobilegl/bin/mobilegl-startup.sh +grep -c MOBILEGL_CHROME_GPU /opt/mobilegl/bin/mobilegl-startup.sh +IN + exit 0 +fi +case "$MODE" in in-process|process) ;; *) echo "mode must be in-process or process" >&2; exit 2;; esac +trap cleanup EXIT + +check_battery +adb_ shell "su -c 'sh $DEV_TOOLS/status.sh'" || true +cleanup + +# The page: WebGL clears that change colour every frame plus a moving block, so a frame that +# reaches the screen changes the screenshot. +ct < $PAGE <<'HTML' + + + +HTML +chmod 644 $PAGE +IN + +WAIT=${WAIT:-20} CHROME_GPU=$MODE CHANNEL=$CH bash "$here/chrome-launch.sh" "$TAG" --new-window "file://$PAGE" + +# The target pid inside the container: the browser (in-process) or the GPU process. +target_pid() { + ct <<'IN' | tr -d '\r' | tail -1 +for p in $(pgrep -x chrome); do + args=$(tr '\0' ' ' < /proc/$p/cmdline) + case "$args" in + *--type=gpu-process*) echo "gpu $p" ;; + *--type=*) ;; + *) echo "browser $p" ;; + esac +done | sort > /tmp/mgl-crec-pids +cat /tmp/mgl-crec-pids >&2 +echo "$(awk '/^browser/ {print $2; exit}' /tmp/mgl-crec-pids) $(awk '/^gpu/ {print $2; exit}' /tmp/mgl-crec-pids)" +IN +} + +pass=0 +for round in $(seq 1 "$ROUNDS"); do + echo "=== round $round/$ROUNDS ($MODE)" + check_battery + read -r browser gpu < <(target_pid) + if [ "$MODE" = process ]; then target=$gpu; else target=$browser; fi + echo "browser=$browser gpu=${gpu:-none} target=$target" + if [ -z "$target" ]; then echo "FAIL: no target process"; break; fi + bash "$here/shot.sh" "$TAG-r$round-pre" 2 1 + adb_ logcat -c + adb_ shell "su -c 'setprop debug.mobilegl.inject_device_lost_pid $target'" + sleep "$SETTLE" + adb_ shell "su -c 'setprop debug.mobilegl.inject_device_lost_pid 0'" + bash "$here/shot.sh" "$TAG-r$round-post" 3 1 | tee "$ANL_DIR/$TAG-r$round-post.md5" + latched=$(adb_ logcat -d | grep -c "injected:pid=$target" || true) + started=$(adb_ logcat -d | grep -c "session #[0-9]* started" || true) + adb_ logcat -d | grep -E "inject_device_lost_pid|SessionLatch|session #[0-9]+ (started|pid)" | cut -c1-220 | head -12 || true + read -r browser2 gpu2 < <(target_pid) + echo "after: browser=$browser2 gpu=${gpu2:-none}" + ct < $browser2): Chrome restarted"; verdict=FAIL; } + [ "$started" -ge 1 ] || { echo " - no new server session started after the loss"; verdict=FAIL; } + if [ "$MODE" = process ]; then + [ -n "$gpu2" ] && [ "$gpu2" != "$gpu" ] || { echo " - no new GPU process"; verdict=FAIL; } + fi + [ "$hashes" -ge 2 ] || { echo " - the screen does not change after the loss (frozen)"; verdict=FAIL; } + echo "round $round: $verdict" + [ "$verdict" = PASS ] && pass=$((pass + 1)) + [ "$verdict" = PASS ] || break +done +echo "=== $pass/$ROUNDS rounds passed ($MODE); screenshots in $ANL_DIR/$TAG-r*-*.png"