The script's set -euo pipefail made it die without any visible error in two places: an empty /tmp/jtube-adbkeys/ failed the glob cat (the error itself was discarded, so the output just stopped mid-script — this hits any host after a reboot), and the boot-wait loop was killed on its first iteration because adb exits non-zero while the device is still booting. Both were swallowing the whole && chain (adb connect, scrcpy), making it look like the emulator was broken when it was fine or about to be. The stale bridge-emulator.sh duplicate (different port, broken vendor keys path) is removed in the same spirit — keeping it invites running the wrong script. Docs updated to match the one script.
3.4 KiB
3.4 KiB
Agent container ↔ host emulator setup
How the testing loop between the JTube TV agent container and the host emulator works, and what needs to exist again after a rebuild.
Topology
- Emulator: runs on the host (
/opt/android-sdk, launched byscripts/start-emulator.sh). Headless is the default; setJTUBE_EMU_MODE=windowedif you want the Qt window (e.g. for desktop interaction testing). View it via scrcpy either way. - Only the host can start the emulator (by design — no SSH from the
container to the host, no SDK/KVM inside the container). If the agent
finds no emulator, it should tell the user to run
./scripts/start-emulator.shon the host rather than try to work around it. Reachability check:adb connect rutherford:5556thenadb -s rutherford:5556 shell getprop sys.boot_completed→1. - Agent container: image
agent-container:latest, container name patternac-<project>-<hash>, launched with--network host— it shares the host's network namespace. This is load-bearing: see below.
Why host networking makes adb trivial
With --network host, the container's localhost is the host's localhost.
So inside the container:
adb connect 127.0.0.1:5556→ hits the host's socat bridge → emulator adbd.- The adb server running on 127.0.0.1:5037 is also shared with the host, so the container inherits whatever authorization the host adb server has. No separate RSA handshake is needed. (Caveat: whoever's adb server grabs port 5037 first owns it; all clients share it.)
What must be (re)installed after a container rebuild
android-toolsin the container (providesadb; installed into the running container withsudo pacman -S --noconfirm android-tools, but that is ephemeral). To make rebuilds self-sufficient, bake it into theagent-containerimage at build time.- Nothing else is needed for adb: key handling is inherited from the
shared host adb server (see above). If the container is ever switched to
bridge networking, use
adb connect rutherford:5556— remote keys are handled by the emulator'sADB_VENDOR_KEYS(next section).
Emulator-side facts (host)
- Ports: console
5600, adbd5601(-port 5600⇒ console+1), LAN bridgesocat TCP-LISTEN:5556 → 127.0.0.1:5601(0.0.0.0, so remote machines canadb connect rutherford:5556). - Remote key whitelisting: the TV system image is a user build — adb
push/shellwrites to/data/misc/adb/adb_keysare blocked. The script therefore builds/tmp/jtube-adbkeys-combined(host key + every/tmp/jtube-adbkeys/*.pub) and launches the emulator withADB_VENDOR_KEYSpointing at it. To trust a new client: put its~/.android/adbkey.pubinto/tmp/jtube-adbkeys/before launching. - Logs:
/tmp/jtube-emu.log(QEMU),/tmp/jtube-socat.log(bridge),/tmp/jtube-adbkeys-combined(rebuilt each launch). - Viewing:
scrcpy -s emulator-5600on the host, or from any LAN machine:adb connect rutherford:5556 && scrcpy -s 127.0.0.1:5556.
Known quirks
- Emulator Qt toolbar (back/home buttons) is a detached XWayland window that misbehaves on Hyprland — drive the emulator via scrcpy or adb instead.
- The TV image is a user build: no
adb root. - Under the Android TV AVD, keyboard input in the Qt window works, but the
reliable inputs are scrcpy (
b= back,h= home) oradb shell input keyevent.