An Android Terminal That Survives Screen-Off: Inside Zorv AI's proot Sandbox
Android's process-killing behavior makes long-running terminal sessions fragile. This architecture shows how to keep a shell alive across screen-off and app-switch events on Android 14+ using `specialUse` foreground services — a pattern any app that needs persistent background compute can adopt.
The Zorv AI app ships a complete terminal emulator built around proot and an Ubuntu 24.04 ARM64 rootfs, giving any Android device a real Linux toolchain — Python, apt, bash — without requiring root access. A PTY pseudo-terminal implementation over `/dev/ptmx` with `fork/exec` handles interactive shell sessions, while a `specialUse` foreground service pins the shell process so it survives screen-off, app switches, and even device reboots via a boot-completed receiver.
Twelve standardized ACI capabilities expose the terminal to external apps through AIDL, HTTP, and MCP, alongside four standard Android IPC channels: ContentProvider, Deep Link, Intent, and BroadcastReceiver. A 15-second patrol loop inside the keep-alive service detects dead sessions and rebuilds them automatically.
The rootfs downloads from Ubuntu mirrors as an ~80MB compressed tarball and unpacks to about 300MB under the app's private files directory. A bootstrap script can layer Node.js, Python, Rust, Go, Java, or OpenSSH runtimes on top, shared across all terminal sessions.
The `specialUse` foreground service type is the correct escape hatch for Android 14+ apps that need persistent background processes but don't fit `dataSync`, `mediaPlayback`, or `location` categories — and Google Play will inspect the required `<property>` justification.
Forking the shell child process inside the foreground service process, rather than in the UI process, is the architectural decision that makes keep-alive work: the service's elevated priority extends to its child processes automatically.
The 15-second patrol-and-rebuild loop is a pragmatic self-healing pattern for long-lived background sessions on a platform that offers no guaranteed process persistence.
Exposing terminal capabilities through both a structured ACI protocol and raw Android IPC channels (ContentProvider, Deep Link, Intent, BroadcastReceiver) covers the spectrum from programmatic integration to simple URL-based invocation.
Bundling proot as a `.so` inside the app's native library directory avoids external binary dependencies and keeps the sandbox self-contained within the APK.