docs: Agent container emulator workflow

Document how the host emulator is driven over adb from the agent
container: the start script now boots headless by default and trusts
remote adb keys via ADB_VENDOR_KEYS at launch, since the TV system
image is a user build that blocks pushing keys to adb_keys after boot.
AGENTS.md points to the new doc and fixes the stale SDK path.
This commit is contained in:
Jeena 2026-10-12 09:42:08 +00:00
parent ed65b77e90
commit 40a9d1e2c6
3 changed files with 93 additions and 25 deletions

View file

@ -1,9 +1,8 @@
#!/usr/bin/env bash
#
# start-emulator.sh — boot the JTube TV test emulator on the HOST (not inside the
# agent container), with GPU acceleration and a window. Use this when the app should
# be tested over scrcpy (ATD/system quirks make scrcpy fail against headless
# in-container emulators) or when you simply want to watch it.
# agent container), with GPU acceleration, headless by default (drive it via
# adb/scrcpy). JTUBE_EMU_MODE=windowed shows the Qt window.
#
# Boots on console :5600 (adbd :5601); the agent container bridges
# rutherford:5556 -> 127.0.0.1:5601 with socat, so after this script the emulator is
@ -54,22 +53,41 @@ for pid in $(ps aux | awk '/[q]emu-system-x86_64/ {print $2}' 2>/dev/null); do
done
sleep 1
ACCEL=()
MODE="${JTUBE_EMU_MODE:-headless}" # headless (default) | windowed
WINDOWED=1
if [ -n "${WAYLAND_DISPLAY:-}${DISPLAY:-}" ]; then
echo "desktop session detected — emulator window + GPU host"
ACCEL=()
if [ "$MODE" = windowed ]; then
if [ -n "${WAYLAND_DISPLAY:-}${DISPLAY:-}" ]; then
echo "windowed (JTUBE_EMU_MODE=windowed) — emulator window + GPU host"
else
echo "JTUBE_EMU_MODE=windowed but no display detected — falling back to headless"
WINDOWED=0
ACCEL+=(-no-window)
fi
else
WINDOWED=0
ACCEL+=(-no-window)
echo "headless (no display) — running without a window, swiftshader rendering"
echo "headless (default; JTUBE_EMU_MODE=windowed for a window) — no emulator window"
fi
if [ -e /dev/kvm ]; then
[ $WINDOWED -eq 1 ] && ACCEL+=(-accel kvm)
ACCEL+=(-accel on)
echo "/dev/kvm found — hardware acceleration on"
fi
# --- build combined adb vendor-keys file ------------------------------------
# The TV system image is a user build: adb push to /data/misc/adb/adb_keys is
# blocked, so remote keys are trusted via ADB_VENDOR_KEYS at launch instead.
# Drop extra public keys into /tmp/jtube-adbkeys/ (one per file), e.g. from the
# agent container: docker exec <ctr> sh -c 'cat ~/.android/adbkey.pub' > /tmp/jtube-adbkeys/agent-container.pub
VKEYS=/tmp/jtube-adbkeys-combined
{
cat "$HOME/.android/adbkey.pub"
cat /tmp/jtube-adbkeys/*.pub 2>/dev/null
} > "$VKEYS"
chmod 600 "$VKEYS"
echo "Booting AVD '$AVD' …"
setsid nohup "$EMU" -avd "$AVD" -port "$PORT" -gpu host "${ACCEL[@]:-}" \
ADB_VENDOR_KEYS="$VKEYS" setsid nohup "$EMU" -avd "$AVD" -port "$PORT" -gpu host "${ACCEL[@]:-}" \
-no-snapshot > /tmp/jtube-emu.log 2>&1 < /dev/null &
echo "emulator PID $! — log: /tmp/jtube-emu.log"
@ -79,21 +97,6 @@ for i in $(seq 1 90); do
sleep 5
done
# --- authorize remote adb clients headlessly ---------------------------------
# The host console transport is always trusted; use it to whitelist client keys
# so `adb connect rutherford:5556` from other machines works without a popup.
# Drop extra public keys into /tmp/jtube-adbkeys/ (one per file), e.g. from
# Chester: cat ~/.android/adbkey.pub > /tmp/jtube-adbkeys/chester.pub
"$ADB" -s "emulator-$PORT" root > /dev/null 2>&1 || true
for key_file in "$HOME/.android/adbkey.pub" /tmp/jtube-adbkeys/*.pub; do
[ -f "$key_file" ] || continue
"$ADB" -s "emulator-$PORT" push "$key_file" "/data/misc/adb/adb_keys" > /dev/null 2>&1 || \
"$ADB" -s "emulator-$PORT" shell "cat > /data/misc/adb/adb_keys" < "$key_file" || {
echo "could not whitelist $key_file";
}
done
"$ADB" -s "emulator-$PORT" shell "setprop service.adb.tcp.port 5601; stop adbd; start adbd" > /dev/null 2>&1 || true
# --- the bridge: advertise adbd on the LAN as :5556 ---------------------------
if ! ss -tln 2>/dev/null | grep -q ":5556"; then
if command -v socat > /dev/null; then