Releases: ExTV/Podroid
AVF multi-core fix (test build)
AVF test build for the multi-vCPU boot reboot on Tensor devices (Pixel 8 / 8a / 8 Pro and the Pixel 9 family). This is a prerelease for affected testers, not a general update, and the in-app updater will not offer it.
What changed since the diagnostic build
AVF now starts with the cores you set and, if the VM resets during early boot (the multi-core crash), it automatically retries with fewer cores and remembers the count that boots on your device. No setting to change and no kernel cmdline to paste: it self-corrects on the first run and boots straight away after that. The manual single-core option stays as a backstop.
For affected testers
- Installs in place over 1.2.4 or the previous debug build (same signing key). Your settings and VM data are preserved.
- Clear any kernel cmdline you added earlier: Settings -> Advanced -> "Kernel extra cmdline" should be back to its default (
loglevel=1 quiet). Remove anynr_cpus=...you pasted in during testing. - Set Backend to AVF and CPU cores above 1, then start the VM.
- Expected: it may reset once or twice while it finds the highest core count your device can boot, then it should reach the terminal. Later starts go straight there.
- Please report whether it reaches the terminal and how many cores it settled on. Export diagnostic shows it on the backend line as
vCPUs=N.
If you want the full early-boot kernel log captured, turn on verbose logging in Settings before starting.
If multi-core still will not boot, single core (CPU cores = 1) remains a reliable fallback, as does the QEMU backend.
v1.2.4
New
- Seamless updates: the Linux system inside the VM now upgrades across app versions with no reset and no data loss. Your installed packages, files, and containers carry over when you update Podroid.
- Server mode: a one-tap full-screen black overlay that keeps the VM running headless with the screen dimmed and burn-in protected; hold to exit. Drive it from the shell with
podroid-server on|off|status. - New in-guest commands:
podroid-open <url>opens a link on Android, andpodroid-power stop|restart|statuscontrols the VM from inside the shell. - UDP port forwarding now works on the AVF backend, matching QEMU (
podroid-forward add <host> <guest> udp). - When an AVF guest fails to boot, Podroid now shows what to do next (try a single core, switch to QEMU, or retry) instead of a blank failure, and captures early-boot kernel output to help diagnose it.
- A Documentation link in Settings -> About opens the online guide.
Fixes
- On devices whose virtualization build lacks the custom-VM API, Podroid now falls back to the QEMU backend automatically instead of failing to start.
- Broad reliability hardening across the AVF backend, the guest-to-Android bridge, and server mode.
Known limitation
- With an external mouse, right-click still exits fullscreen in the X11 viewer instead of reaching the desktop. Two-finger right-click via touch works. A fix is planned.
v1.2.3
New
- USB device passthrough: plug a real USB device (Wi-Fi adapter, storage, serial adapter, audio interface) into the running VM straight from Android, with no root. Turn it on in Settings or at first-run setup; it adds a USB controller at boot, so set it while the VM is stopped (QEMU backend).
- Talk back to Android from inside the VM:
podroid-notifyposts an Android notification (with a title, priority, and--idto update one in place), andpodroid-forwardadds, lists, and removes port-forward rules without leaving the shell. Both work on the QEMU and AVF backends. - The interface is now available in 中文 (Chinese) alongside English, selectable in Settings or following your device language.
- Updated to the Linux 7.0.10 kernel.
Fixes
- Interrupting a VM control action (for example, stopping the VM while a port-forward change is still in flight) no longer surfaces a spurious failure; the operation now unwinds cleanly.
Known limitation
- With an external mouse, right-click still exits fullscreen in the X11 viewer instead of reaching the desktop. Two-finger right-click via touch works. A fix is planned.
Thanks
- @9hm2 for the USB device passthrough feature (#32).
- @guoai2015 for the Chinese translation and in-app language switching (#35).
v1.2.2
New
- LXC distro containers:
lxc-create -t downloadnow works, so you can spin up Alpine, Ubuntu, Debian and other distributions as LXC containers alongside Podman and Docker (the download template andxzare now bundled). - Online documentation site, linked from the README.
Fixes
- Stopping or restarting the VM no longer risks losing recent work. The persistent disk is now flushed durably on shutdown, and the pKVM/AVF backend syncs the guest before stopping, instead of potentially discarding the last writes.
- The VM now reaches "Running" the moment it is actually ready, instead of waiting a fixed ~60 seconds. The terminal and SSH attach at the real boot time. Most noticeable on the QEMU backend.
- Fixed an intermittent "QEMU crashed" that could kill a healthy VM shortly after the app was sent to the background.
- The terminal no longer opens to a blank screen after boot. The login prompt now appears on its own, without needing a keypress.
- X11 viewer stability: hardened the remote-framebuffer decoding and audio handling, and held mouse buttons are now released when you leave the viewer.
- pKVM/AVF backend: protected-only devices are reported as "using QEMU" rather than shown as a failure, the guest boot log is captured in full, and a dropped control channel is detected and recovered.
- Broad reliability hardening across VM start, stop and restart, network interface selection, the terminal bridge, the port-forward agent, settings reads, and the update check.
Known limitation
- With an external mouse, right-click still exits fullscreen in the X11 viewer instead of reaching the desktop. Two-finger right-click via touch works. A fix is planned.
v1.2.1
New
- Configurable X11 viewer: a live-resizable desktop (match your screen, or 720p-1440p / custom presets), direct-touch and trackpad pointer modes with adjustable sensitivity and scroll, fullscreen, and rotation lock.
- External keyboard and mouse in the X11 viewer: physical keyboard with Ctrl/Alt/Shift combinations, and mouse-wheel scrolling.
- AVF (pKVM) backend on supported Pixel devices for near-native speed, selected from the device's hypervisor capabilities with automatic QEMU fallback.
- Verbose AVF logging that captures the guest console and decoded VM lifecycle codes for bug reports.
Fixes
- Resolved the AVF "setProtectedVm must be called explicitly" startup crash by selecting the VM mode from device capabilities.
- The AVF guest console is now captured in the diagnostic log; it was previously empty, which hid boot failures.
- The X11 viewer no longer disconnects on heavier desktops and apps.
Known limitation
- With an external mouse, right-click exits fullscreen instead of reaching the desktop. Two-finger right-click via touch works. A fix is planned.
v1.2.0
New UI
Every screen restyled into one design system — dark dashboard, lime accent, Inter for chrome + JetBrains Mono for tech values. Home now shows live uptime, network and last-session details. Settings re-sectioned with proper buttons for destructive actions. Refreshed setup wizard. New Quick Settings drawer in the terminal that closes on any interaction.
Hardware acceleration on Pixel 8 / 9 / 10
Podroid now runs the VM on pKVM (your phone's real hardware virtualization) instead of software emulation. The VM boots in a few seconds and feels near-native. Auto-detected — falls back to QEMU on any device that doesn't support it.
One-time setup. From a PC with adb:
adb shell pm grant com.excp.podroid android.permission.MANAGE_VIRTUAL_MACHINE
adb shell pm grant com.excp.podroid android.permission.USE_CUSTOM_VIRTUAL_MACHINENo PC? Install Shizuku, start it, then run the same two commands in its rish shell.
Backend lock (Auto / pKVM / QEMU) lives in Settings → Advanced. Switching applies on the next VM start — no app restart.
LAN-reachable port forwarding
Forward rules now bind on your phone's actual LAN IP, not just 127.0.0.1. From your laptop on the same WiFi:
ssh root@<phone-ip> -p 9922
curl http://<phone-ip>:8080
Adding / removing rules takes effect within a second — no VM restart. The X11 and audio viewers also come up on the LAN.
Terminal auto-resize
btop, htop, vim, less etc. now resize live as you rotate the phone or slide the keyboard — on both backends.
Snappier terminal & faster guest CPU
~50 ms off every keystroke. Keyboard slide → prompt redraw ~145 ms (was ~350). TUI streams render at ~30 fps (was ~15). Faster guest CPU under load. storage.img shrinks back on fstrim instead of growing forever.
Audio fixes
- Clicking noise in Firefox / video playback is gone
- Firefox + other apps actually reach the audio sink now (was silently broken)
X11 viewer no longer crashes mid-session
Used to disconnect when the VM sent a clipboard sync. Fixed — full sessions stay up.
More headroom
Swap inside the VM is now ~1.5× RAM (was half). Firefox + a full desktop in a 2 GB VM stays smooth. If memory does run out, the browser dies — not your SSH or X11.
Cleaner Settings
- New AVF (pKVM) diagnostic dialog
- Phone IP no longer shows the cellular CLAT internal address — always the LAN IP
- Downloads sharing toggle greys out (with explanation) on AVF where it's not supported
⚠️ Heads-up: Android phantom-process killer
Android 12+ kills background native processes. If your VM dies on app-switch, run once:
adb shell "device_config put activity_manager max_phantom_processes 2147483647"
adb shell settings put global settings_enable_monitor_phantom_procs falseOr via root:
su -c /system/bin/device_config put activity_manager max_phantom_processes 2147483647
su -c setprop persist.sys.fflag.override.settings_enable_monitor_phantom_procs falseKnown limitations
- Downloads folder sharing isn't available on pKVM — it's a system-app-only API on shipping Pixel firmware. Works on QEMU.
- Default VM RAM is still 512 MB — bump to 2 GB in Settings for desktop / browser workloads.
- Android 8 still unsupported (NDK / glib blocker).
v1.1.9
⚠️ First proper release build. Until 1.1.8, every shipped APK was a debug build with applicationIdcom.excp.podroid.debugand a-debugversion suffix. 1.1.9 is a signedreleasebuild with applicationIdcom.excp.podroid. Android treats those as two different apps — to upgrade you must uninstall the old debug build first (your VM storage is in app-private storage and will be wiped). Back up anything important from inside the VM before upgrading.
The headline: in-app X11 viewer with audio
A new monitor icon next to the gear in the terminal top bar opens a full-screen X11 view backed by an always-on Xvnc server inside the VM. Anything you apk add and launch from a shell renders on your phone, with sound piped through the speaker. No setup, no DISPLAY= prefix, no environment dance.
# inside the app's terminal:
apk add xeyes
xeyes
# ...tap the monitor icon. xeyes follows your finger.What's in there:
- Hand-rolled Kotlin RFB 3.8 client (~600 LOC, Raw + CopyRect encodings) — no third-party VNC library
- Audio: 44.1 kHz stereo PCM streamed over PulseAudio's
module-simple-protocol-tcp, decoded byAudioTrackwith auto-reconnect - 1280×720 fixed framebuffer — aspect-preserving letterbox into the phone screen, pinned to the top so the soft keyboard never overlaps the content
- Soft keyboard (top-right icon): printable chars via IME diff, plus Backspace, Enter, Tab, Esc, arrows
- Extra-keys row matching the terminal: ESC, TAB, sticky-one-shot CTRL/ALT, arrows (hold-to-repeat), HOME/END, PGUP/PGDN, F1–F12 — and it slides above the IME when the keyboard opens
- Always-on at boot via the new
podroid-x11OpenRC service. Stale/tmp/.X0-lockis auto-cleaned every start, so a hard VM kill never blocks the next launch. - GPL-2 compatible end-to-end (TigerVNC, PulseAudio); no Termux-X11 dependency
Three container runtimes, ready to go
The Alpine rootfs now ships with all three pre-installed and Docker auto-starting at boot:
| Runtime | Version | State |
|---|---|---|
| Docker | 29.1.3 | Auto-starts via OpenRC, in-kernel overlay, cgroup v2 |
| Podman | 5.7.0 | rootless-friendly with crun + native overlay |
| LXC | 6.0.5 | lxcbr0 bridge up, busybox template tested end-to-end |
Plus gcompat is built in so glibc-linked binaries (e.g. some prebuilt CLI tools) run on the musl rootfs, and gzip ships so lxc-checkconfig reads /proc/config.gz cleanly.
Kernel 7.0.5 + AMD64 container support (closes #27)
CONFIG_BINFMT_MISC=y is now baked in. tonistiigi/binfmt --install amd64 works, letting you run x86_64 container images under double TCG emulation. The build verifier enforces it so it can't silently regress.
QEMU 11.0.0 stable
Bumped from 11.0.0-rc2 to the GA release. The settings screen now shows 11.0.0 instead of the rc label.
Polish
- Setup wizard advertises 2 cores (matches the actual default; was stale at 1)
- About screen drops the misleading "Container runtime: Podman + crun" row — we ship three runtimes now
- X11 fonts shipped:
font-misc-misc(fixes xterm'siso10646-1font),font-cursor-misc,ttf-dejavu
Cost of all this
Idle, no X11 viewer connected:
| Resource | Δ vs 1.1.8 |
|---|---|
| APK size | +~90 MB (TigerVNC + PulseAudio + X11 fonts + Docker + LXC + binfmt support) |
| VM RAM | +~63 MB always-on (Xvnc 47 + pulseaudio 4 + helpers 12) |
| VM CPU idle | unchanged (~0%) |
| Boot time | +1–2 s |
| Network / container performance | zero impact |
| Storage on the host overlay | unchanged (services are stateless) |
Known limitations
- Apps without a window manager open at their default size — install
openboxand start it once before launching the app, or usefirefox --kiosk. There's no WM shipped by default (deliberate — keeps the rootfs small and lets you pick). xtermdefaults to 80×24 chars at a small font; launch withxterm -fa "DejaVu Sans Mono" -fs 16 -geometry 120x36for a comfortable size.- AMD64 container emulation via binfmt is slow (see above).
- The X11 framebuffer is fixed at 1280×720 in landscape orientation. Rotate the phone to landscape for a full-screen experience.
Thanks
To @wguanwei for #27 which prompted the BINFMT_MISC kernel work.
v1.1.8
What's New in v1.1.8
This release ships a fully-featured in-app terminal — inline images, modern escape-sequence support, ligatures, and a top-sheet Quick Settings panel with custom font and theme import — and resolves two long-standing stability bugs (Pixel 10 SIGILL, orphan VM after uninstall).
Terminal — image protocols
- Sixel:
chafa,lsix,img2sixel, lazygit thumbnails, and any tool that emits DCS-Sixel now render inline. Fixed two parser bugs in the upstream fork along the way (the barePa;Pb;Pcqintro and the missing$/-flush triggers). - iTerm2 (OSC 1337):
imgcatand friends just work. - Kitty graphics protocol (
a=T,f=100,t=d,m=0/1,c=,r=): multi-chunk PNG support, used by yazi/lf preview panes andkitty +kitten icat.
Terminal — modern features
- DECSET 2026 synchronized output: the emulator advertises and honors atomic-frame mode, so btop / nvim / lazygit no longer flicker during partial redraws.
- OSC 8 hyperlinks: tap-to-open URLs from
git,gh,lazygit, etc. - HarfBuzz ligatures:
'liga' on, 'calt' onis enabled on the Paint, so JetBrains Mono / FiraCode / Cascadia render===,=>,!=,->as fused glyphs. - XTVERSION (
CSI > 0 q): emulator answers\eP>|Podroid <ver>\e\so Neovim ≥0.10 and other modern apps detect the terminal correctly. COLORTERM=truecoloris now exported from/etc/profile.dinside the VM, so apps detect 24-bit color support without manual configuration.
Quick Settings — minimal top-sheet rewrite
- Drops down from the header in one tap, height-capped so the extra-keys row stays visible in landscape.
- Three-column grid per section: 4 visible swatches + More (full picker with search) + + Add (import).
- Continuous font-size slider, compact toggles for haptics and extra keys.
- Custom fonts:
+ Addopens the system file chooser (SAF). Drop in any.ttfor.otf; long-press a custom font to remove. No file-manager permission gymnastics required. - Custom themes: paste a terminalcolors.com URL and the app fetches the Alacritty TOML, parses it, and adds it to the picker.
Fixes
- Pixel 10 SIGILL on launch: QEMU's coroutine layer used Bionic's
sigsetjmp/siglongjmp, which fail PAC AUTH on ARMv9.2 (Tensor G6) when Downloads sharing is enabled. Replaced with a PAC-free aarch64 asm shim (libqemujmp.a) linked intocoroutine-ucontext.c. - Orphan VM after uninstall / OOM kill: a tiny native launcher (
libpodroid-launcher.so) now wraps QEMU and setsPR_SET_PDEATHSIG = SIGKILLbeforeexecv. The VM dies with the app instead of reparenting to PID 1 and continuing to consume RAM until reboot. Verified on Android 12 (rooted) and Android 16 (unrooted). - Update prompt regression:
1.1.x-debugno longer compares as older than1.1.x, so the in-app update banner stops nagging on every launch. - Cursor flicker on keyboard slide: removed a redundant
forceUpdateSizeFromViewcall that was racing withtv.updateSize()and triggering two SIGWINCH resizes per keyboard animation. - Cursor flicker on extra-keys toggle: cached the last applied font size so flipping CTRL/ALT no longer re-pushes
setTextSize+updateSizeon every recomposition. - dmesg cleanup: 9p
msizelowered to virtio's actual cap (512000); deprecated kernelelevator=cmdline replaced with per-device sysfs writes inpodroid-bootstrap.
Performance (TCG, no KVM)
-cpu max,sve=off: SVE's variable-length vector instructions are expensive to translate and effectively unused by Node, Podman, and most container workloads. Dropping them speeds general guest workloads.tb-size=512: bigger translation-block cache helps JIT-heavy guests like V8/Node.
Internals
- The terminal layer now lives as two local Gradle subprojects (
terminal-emulator,terminal-view) vendored fromMatanZ/termux-app:sixel4, instead of a JitPack AAR. We can patch the parser in-tree. - 64 KB PTY buffers, deduplicated
MSG_NEW_INPUT, and a hoistedRectFreduce wakeups and GC pressure on image-heavy frames.
Installation
Important: Delete any older Podroid app versions before installing.
- Uninstall the existing Podroid app completely
- Download and install the new APK
- You may need to allow installation from unknown sources
Note: This is a debug build as per project convention.
v1.1.7
What's New in v1.1.7
This release makes Docker and LXC work zero-config alongside Podman, fills out the kernel feature matrix so every container engine's audit script reports clean, and fixes a terminal regression introduced during the 1.1.6 OpenRC migration.
Container engines
- Zero-config Docker:
apk add docker; rc-service docker start; docker run --rm alpine echo hiworks out of the box. Thepodroid-bootstrapservice bind-mounts/var/lib/dockerto raw ext4 on every boot, so Docker's per-containeroverlay2mount no longer hits Linux's overlay-on-overlay rejection. Native kernel overlay driver, not the slower FUSE fallback. - Zero-config LXC:
apk add lxc lxc-templates; lxc-create -t busybox -n test; lxc-start -n testworks without any manual bridge or NAT setup.podroid-bootstrappre-createslxcbr0(10.0.3.1/24) and adds the matching MASQUERADE rule for outbound traffic. - Podman continues to work as before with
fuse-overlayfs.
Kernel
- Complete container feature matrix: ~30 additional Kconfig options forced built-in. Docker's
check-config.shandlxc-checkconfigboth report zero fixable complaints. New: BTRFS, IPVS family, VXLAN, IPVLAN, MACVLAN, IPsec (XFRM/INET_ESP), CFS bandwidth, raw iptables (v4 and v6), block-device throttling, FTP/TFTP NAT helpers, SCTP, nftables FIB family, BPF match, AppArmor LSM stub, and crypto AEAD/GCM/GHASH/SEQIV. /proc/config.gzshipped:CONFIG_IKCONFIG=y+CONFIG_IKCONFIG_PROC=y. Diagnostic tools that read the running kernel config now work without manual workarounds.- IPv6 forwarding sysctls:
net.ipv6.conf.all.forwarding,net.ipv6.conf.default.forwarding, andnet.bridge.bridge-nf-call-ip6tablesare now set inpodroid-bootstrapalongside their IPv4 counterparts.
Fixes
- Terminal regression: The hvc0 getty line in
inittabwas settingTERM=vt100since the OpenRC migration, which broke 256-color rendering, italics, mouse tracking, and arrow-key handling in TUI apps. Restored toxterm-256color.
Installation
Important: Delete any older Podroid app versions before installing.
- Uninstall the existing Podroid app completely
- Download and install the new APK
- You may need to allow installation from unknown sources
Note: This is a debug build as per project convention.
v1.1.6
What's New in v1.1.6
This release migrates the VM to a real Alpine Linux root running OpenRC as PID 1, fixes a long-standing rootless-Podman bug, and adds adaptive UI layouts for landscape phones and tablets.
Architecture
- OpenRC as PID 1: The VM now boots a standard Alpine 3.23 squashfs with OpenRC running real services.
apk add docker; rc-update add docker; rc-service docker startworks out of the box and persists across reboots in the writable overlay. - switch_root replaces chroot: The init pipeline mounts an ext4-over-squashfs overlay and
switch_roots into the new system instead of the old chroot pivot. This reorganizes the kernel mount tree itself, so namespace operations land on a clean/. - Dual-image boot: The squashfs ships as a second virtio-blk drive (
/dev/vdb, read-only, gzip-compressed) on top of the writable ext4 overlay (/dev/vda). - Kernel additions:
CONFIG_EXT4_FS_SECURITY=yandCONFIG_SQUASHFS_XATTR=yare now forced built-in so file capabilities (security.capabilityxattrs) survive the overlay, which rootless Podman'snewuidmap/newgidmapneed.
Fixes
- Issue #17:
podman exec -itnow works correctly both rootful and rootless. The root cause wassetns(CLONE_NEWNS)resettingfs->rootinsidecrun exec, which made the exec'd process see raw kernel paths. - Storage slider: Replaced with a chip selector. The slider's float-truncation snapped 8 GB silently to 7 GB.
- Boot stage detection: Stages now flow correctly from the new OpenRC
podroid-readyservice.
Terminal & UI
- Adaptive layouts: Setup, Home, Settings, and Terminal screens now use a two-column layout on landscape phones and tablets so action buttons no longer overflow below the fold or under the keyboard.
- Quick Settings redesign: Inline chip rows for font size, color theme, and font family replace the old nested dialogs. Horizontal edge fades show when more options exist past the visible row, and a left-edge vertical scrollbar indicates more options below the fold.
- Material 3 polish: Settings screen reorganized into uppercase-headered cards (VM Resources, Storage, Network, Appearance, Diagnostics, About) with chip-row selectors throughout.
- Default credentials: Login banner now shows
root / podroidand theadduser -G wheel <name>workflow for creating regular users withdoas/sudoaccess.
Container runtime
The VM now ships with the full rootless OCI stack pre-configured: Podman, crun, fuse-overlayfs, slirp4netns, aardvark-dns, netavark, iptables, ip6tables, nftables, bridge-utils, shadow-uidmap, doas, sudo, and Dropbear SSH.
Installation
Important: Delete any older Podroid app versions before installing.
- Uninstall the existing Podroid app completely
- Download and install the new APK
- You may need to allow installation from unknown sources
Note: This is a debug build as per project convention.