VirtualizationService manages multiple guest VMs, protected or otherwise,
running on an Android system, primarily by managing instances of crosvm.
VirtualizationService exposes an AIDL API, which system services or apps can
use to start, monitor, and stop VMs. To use
virtmgr directly or import javalib or rustlib which executes
a child process.
Access to a VM is tracked by the
IVirtualMachine object. As long as there's
at least one reference to
IVirtualMachine object then the VM continues to
run (unless it crashes or shuts down of its own accord). If all references to
IVirtualMachine object are dropped before the VM shuts down, then
VirtualizationService automatically shuts down the VM. This process implies
that if the client that started the VM is shut down by the low memory killer,
then the VM is also shut down, thus preventing resource leaks.
Each VM is managed by its own instance of crosvm, which
in turn manages on behalf of the client.
starts these crosvm child processes as required with allocated global resources
including the CID granted by
virtualizationservice, and passes them the file descriptors for the images the
VirtualizationService then monitors the child process for when they
die, so it can notify any remaining clients accordingly.
crosvm supports two different ways of booting a VM: either a kernel and initrd are provided or a bootloader is provided. In either case, an arbitrary number of disk images can also be provided, which might be either a raw image or a composite of several partitions. The various images are provided by the client as file descriptors.
VirtualizationService builds composite disk images on demand. This process is
necessary because the composite disk file refers internally to the various
partition image files composing the disk, which are passed by the client and
might not be directly accessible by crosvm. To get around this issue,
VirtualizationService ensures that the file descriptor numbers inherited by
crosvm are the same as the file descriptor numbers which
used in creating the composite images. The composite disk image uses filenames
in the form to
/proc/self/fd/N to represent each partition file.
For Microdroid pVMs, AVF includes a bootloader, which loads the kernel from a partition of a composite disk image, following the standard Android Verified Boot flow.
VM Sockets (vsock)
The primary interface for communication between pVMs is vsock, a standard
virtio socket interface. Each VM is identified by a 32-bit context identifier
(CID), which is analogous to an IP address, which
VirtualizationServiceInternal assigns to the VM when
creates the VM, and can expose services on whatever port numbers the VM chooses.
The CID is unique while the VM is running, but the CID value can be recycled
when the VM is terminated and all the
IVirtualMachine binder handles to the VM
have been dropped.
vm command is provided for debug purposes. This command lets a developer
start a VM from the shell, view its logs, and terminate the VM. With the
command or other interfaces provided by AVF, a VM can start in either
debuggable (FULL) or non-debuggable (NONE) mode. With debuggable VM, you can see
OS level logs, access the ADB shell, and capture crash-dump or app payload.
It's recommended to use a non-debuggable VM in production. For more on
the command line tool and other debug interfaces that AVF provides, see