Under the hood
How it works
What happens when you run sarab start, from namespaces to windows, told for people who use Sarab rather than work on it.
Sarab boots an Android image that is not modified at all, LineageOS 20 (Android 13, x86_64) as the Waydroid project publishes it, and rebuilds only the part that runs on your machine, in Rust. That part does three jobs: it gives Android a place to run without root, it connects Android to your desktop, and it puts Android to sleep when you are not using it.
Your desktop session · your user
sarab-hostd · outside Android, answers it over binder
display relay, clipboard, notifications, launcher entries, dark mode
A cgroup of its own · frozen when idle
sarab-ns · user, pid, net, mount, cgroup, IPC and UTS namespaces
Android 13 · init is pid 1, its root is your user
A place to run, without root
Android expects to be the whole machine: to be root, to own /dev, to mount things, to start hundreds of processes under dozens of user ids. Sarab gives it all of that inside Linux namespaces, which an ordinary user may create.
When you run sarab start:
- A cgroup of its own. Sarab asks systemd for a scope under your user, so Android’s processes can be counted, frozen and measured as one group.
- Namespaces.
sarab-nscreates a user namespace and maps Android’s user ids onto the sub-ids your user owns in/etc/subuid: Android’s root becomes you, and its system and app users become your sub-ids. Inside that it creates pid, network, mount, cgroup, IPC and UTS namespaces. - A private
/dev, with binder. Android’s processes talk to each other through binder.sarab-nsmounts a binderfs of Android’s own; the kernel allows that inside an unprivileged user namespace, which is what makes a rootless Android possible at all. - The image as the root. It switches the root directory to the extracted Android image, lays Sarab’s few overlay files on top, and starts Android’s
initas process 1. - Networking.
pastajoins Android’s network namespace as your user and gives it an Ethernet interface. Android’s own Ethernet service picks it up, gets an address by DHCP and reaches the internet, with DNS forwarded to your host’s resolver. No bridge, no root. - Boot. Android boots in about a second and a half.
sarab startreturns once it is up.
Sarab also keeps Android’s view small: it starts with an environment of its own rather than your session’s, cannot create further user namespaces, and sees only the Android image, its data, a read-only /usr, and two sockets of your session: the display and your Pulse audio server. Security has the full account.
Connected to your desktop
Android’s framework, as built for this image, expects a few services on the host side. sarab-hostd provides them over binder, from outside the namespace:
- Windows. Android’s display composer draws each app as a Wayland window. Its connection goes through
sarab-hostd, which passes every message on to your compositor and adds one thing: a fixed size for each app window, taken from the composer’s own drawing size. A window of fixed size is one that Hyprland and sway float by themselves. - Clipboard. Android asks the host for the desktop’s clipboard, and hands over its own.
- Notifications. Android posts notifications to the host, and
sarab-hostdshows them through your notification daemon, relaying button presses back. - Launcher entries. Android tells the host when apps come and go;
sarab-hostdwrites a desktop entry, with the icon it extracts from the app’s APK. - Dark mode.
sarab-hostdfollows the colour scheme your desktop portal publishes and sets Android’s night mode to match.
sarab-hostd answers only callers running as Android’s system user. If it stops, Android’s windows go with it, so Sarab stops Android too, and the systemd unit starts both again.
Asleep when idle
Android’s composer keeps count of the windows it has open. When the count stays at zero for a minute, Sarab freezes the whole cgroup: every Android process stops where it is, with no CPU time and no wakeups. Opening an app, or any sarab command that talks to Android, thaws it, which takes about 13 ms. After ten minutes frozen, Sarab asks the kernel to push Android’s memory out to swap or zram, when there is any, down to about 172 MB of physical memory.
Trimmed for a desktop
On the first boot of Android’s data, Sarab applies a desktop policy: it switches off the parts of Android a desktop has no use for, such as telephony, the setup wizard, Android Auto and Google’s search app, and replaces Launcher3 with a home activity of 8.5 KB that never draws anything. That keeps Android’s memory down, and sarab policy revert undoes it.
Going deeper
If you want every technical decision and the reasons for it, the repository’s architecture overview has them, and SECURITY.md has the full security model. The source code is on GitHub.