Skip to content

Releases: ExTV/Podroid

AVF multi-core fix (test build)

01 Jun 20:54

Choose a tag to compare

Pre-release

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 any nr_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

29 May 16:34

Choose a tag to compare

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, and podroid-power stop|restart|status controls 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

26 May 19:49

Choose a tag to compare

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-notify posts an Android notification (with a title, priority, and --id to update one in place), and podroid-forward adds, 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

22 May 14:40

Choose a tag to compare

New

  • LXC distro containers: lxc-create -t download now works, so you can spin up Alpine, Ubuntu, Debian and other distributions as LXC containers alongside Podman and Docker (the download template and xz are 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

20 May 15:35

Choose a tag to compare

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

18 May 19:57

Choose a tag to compare

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_MACHINE

No 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 false

Or 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 false

Known 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

09 May 16:54

Choose a tag to compare

⚠️ First proper release build. Until 1.1.8, every shipped APK was a debug build with applicationId com.excp.podroid.debug and a -debug version suffix. 1.1.9 is a signed release build with applicationId com.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 by AudioTrack with 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-x11 OpenRC service. Stale /tmp/.X0-lock is 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.

⚠️ AMD64 inside ARM64 TCG is double emulation — fine for build tooling, painful for daemons.

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's iso10646-1 font), 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 openbox and start it once before launching the app, or use firefox --kiosk. There's no WM shipped by default (deliberate — keeps the rootfs small and lets you pick).
  • xterm defaults to 80×24 chars at a small font; launch with xterm -fa "DejaVu Sans Mono" -fs 16 -geometry 120x36 for 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

30 Apr 04:26

Choose a tag to compare

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 bare Pa;Pb;Pcq intro and the missing $ / - flush triggers).
  • iTerm2 (OSC 1337): imgcat and 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 and kitty +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' on is 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=truecolor is now exported from /etc/profile.d inside 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: + Add opens the system file chooser (SAF). Drop in any .ttf or .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 into coroutine-ucontext.c.
  • Orphan VM after uninstall / OOM kill: a tiny native launcher (libpodroid-launcher.so) now wraps QEMU and sets PR_SET_PDEATHSIG = SIGKILL before execv. 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-debug no longer compares as older than 1.1.x, so the in-app update banner stops nagging on every launch.
  • Cursor flicker on keyboard slide: removed a redundant forceUpdateSizeFromView call that was racing with tv.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 + updateSize on every recomposition.
  • dmesg cleanup: 9p msize lowered to virtio's actual cap (512000); deprecated kernel elevator= cmdline replaced with per-device sysfs writes in podroid-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 from MatanZ/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 hoisted RectF reduce wakeups and GC pressure on image-heavy frames.

Installation

Important: Delete any older Podroid app versions before installing.

  1. Uninstall the existing Podroid app completely
  2. Download and install the new APK
  3. You may need to allow installation from unknown sources

Note: This is a debug build as per project convention.

v1.1.7

29 Apr 02:56

Choose a tag to compare

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 hi works out of the box. The podroid-bootstrap service bind-mounts /var/lib/docker to raw ext4 on every boot, so Docker's per-container overlay2 mount 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 test works without any manual bridge or NAT setup. podroid-bootstrap pre-creates lxcbr0 (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.sh and lxc-checkconfig both 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.gz shipped: 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, and net.bridge.bridge-nf-call-ip6tables are now set in podroid-bootstrap alongside their IPv4 counterparts.

Fixes

  • Terminal regression: The hvc0 getty line in inittab was setting TERM=vt100 since the OpenRC migration, which broke 256-color rendering, italics, mouse tracking, and arrow-key handling in TUI apps. Restored to xterm-256color.

Installation

Important: Delete any older Podroid app versions before installing.

  1. Uninstall the existing Podroid app completely
  2. Download and install the new APK
  3. You may need to allow installation from unknown sources

Note: This is a debug build as per project convention.

v1.1.6

29 Apr 01:40

Choose a tag to compare

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 start works 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=y and CONFIG_SQUASHFS_XATTR=y are now forced built-in so file capabilities (security.capability xattrs) survive the overlay, which rootless Podman's newuidmap/newgidmap need.

Fixes

  • Issue #17: podman exec -it now works correctly both rootful and rootless. The root cause was setns(CLONE_NEWNS) resetting fs->root inside crun 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-ready service.

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 / podroid and the adduser -G wheel <name> workflow for creating regular users with doas / sudo access.

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.

  1. Uninstall the existing Podroid app completely
  2. Download and install the new APK
  3. You may need to allow installation from unknown sources

Note: This is a debug build as per project convention.