Test Results, Firebase Test Lab, and What's Next for Pockr
Part 6 of 6 — the final chapter of building Pockr, a single APK that runs Docker on non-rooted Android.
— v1.0.0 · ARM64 · 163 MB
Requires Android 9+ (API 28), ARM64 device. Enable "Install from unknown sources" before installing.
How We Test: Firebase Test Lab
Physical device testing on a Mac with an Android emulator is unreliable for this project — QEMU needs hardware virtualisation, and nested virtualisation in emulators doesn't work.
Instead, every build gets tested on Firebase Test Lab with a Robo test:
Setting
Value
Device
Pixel 2 (arm64)
Android version
11 (API 30)
Test type
Robo (automated UI crawler)
Timeout
600 seconds
Architecture
ARM64 (same as real phones)
The Robo crawler explores the UI systematically — tapping every button it finds, navigating every screen, filling forms. It's brutal but effective at finding race conditions and edge cases that manual testing misses.
Test History
Version
Result
What Changed
v11–v20
❌ Various crashes
ELF/linker issues, asset extraction bugs
v22
✅ Pass
VmManager as Application singleton — QEMU survives Activity relaunch
v23
✅ Pass
DNS fix ( use-vc+ 8.8.8.8 fallback) — Docker Hub reachable
v24
✅ Pass
Flutter ScaffoldMessengercontext fix
v25
✅ Pass
First container pull + run — busybox and nginx from Docker Hub (~78s)
v28
✅ Pass
Release APK + Pockr branding
v30
✅ Pass
Corrected APK filename in test script
v33
✅ Pass
Race condition fix in VmManager.getStatus()— no more restart loop
v34
❌ Fail
Double-start found — Robo tapped Start during starting→runningtransition, launching a second QEMU instance
v35
✅ Pass
Double-start guard in VmState.startVm()— confirmed no double-start, containers running
What a Passing Test Looks Like
From the v35 logcat (second boot — Docker image cache already warm):
CODE03:38:02 VmManager: Starting VM...
03:38:02 VmManager: Reusing existing user.qcow2 (Docker image cache preserved)
03:38:02 VmManager: VM process launched
... Alpine second boot: ~50 seconds ...
... API server comes up ...
03:38:53 VmApiClient: Container started: alpine_1772710722409 ✅
03:39:28 VmApiClient: Container started: test_1772710762640 ✅
From cold install (first boot, Docker + Python setup):
CODE03:35:33 VmManager: Starting VM...
03:35:33 VmManager: Extracted vm/base.qcow2 (fresh install)
03:35:33 VmManager: VM process launched
... Alpine first boot: ~2–5 minutes ...
... Docker installs, API server bootstraps ...
From cold install to running container: ~5 minutes.
Second boot (Docker image cache warm): ~50 seconds.
What Works Today
- ✅ Install APK → tap Start → QEMU boots Alpine Linux
- ✅ Docker pulls images from Docker Hub over SLIRP networking
- ✅
busybox,alpine,nginxconfirmed running on real hardware (ARM64, Android 11)
- ✅ Persistent overlay disk — pulled images survive VM restarts
- ✅ No root. No Termux. No PC required after install.
- ✅ Foreground service keeps VM alive when app is backgrounded
- ✅ Auto-start option to launch VM on app open
Current Limitations
Limitation
Notes
First boot ~5 min
Docker + Python bootstrap on Alpine; subsequent boots ~50s
ARM64 only
QEMU binary targets aarch64only (no ARM32/x86)
Storage driver: vfs
Less efficient than overlay2, but works without kernel modules
--network hostonly
No isolated container networks without bridge module
APK size ~163 MB
Includes full Alpine disk image + QEMU binary + 50 libraries
What's Next
- [ ] Stop container / view logs in app UI
- [ ] ARM32 device support
- [ ] Reduce first-boot time
- [ ] Custom container image support from UI
The Full Series
What is Pockr? Start here
1
Executing Binaries — The SELinux Problem
3
Docker Without Kernel Modules
5
Test Results and What's Next
SOCIAL SHARE CARD GENERATOR