VirtualizationService manages all guest VMs, protected
or otherwise, running on an Android system, primarily by managing instances of
VirtualizationService exposes an AIDL API, which system services
or apps can use to start, monitor, and stop VMs.
VirtualizationService exposes an AIDL API that clients can use to provide
images and start a VM. This description can either be a raw VM configuration
with file descriptors for the bootloader or kernel and various disk images to
include in the VM, or a Microdroid configuration where the client just provides
the payload and the VM is started with a standard Microdroid kernel and
VirtualizationService then returns an
object that represents the VM. The client that started the VM can choose to
share the Binder object with other processes, using the usual Binder mechanisms.
IVirtualMachine has AIDL methods to get information about the VM, such as
the CID, which can be used to communicate with it over vsock, and also allows
a callback to be registered to be called when the VM stops. In the case of
Microdroid VMs the
IVirtualMachine object can also be used to set up
Binder connections to the VM.
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.
VirtualizationService starts these
crosvm child processes as required, and passes them the file descriptors for
the images the VM needs.
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 VirtualizationService
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
assigns to the VM when the VM is created, 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
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. The
command also includes an option to list currently running VMs, including their
statuses and associated processes. This option is implemented
as an extra method on the
VirtualizationService AIDL API which, to avoid
abuse, can be only called by the shell user.
AVF also includes support for forwarding an
adb connection over vsock,
adb access to guest VMs. For example, for a Microdroid VM with
CID 10 running
adbd on port 5555, the developer can get a shell in
the Microdroid VM from their workstation with the following commands:
$ adb forward tcp:8000 vsock:10:5555 $ adb connect localhost:8000 $ adb -s localhost:8000 shell
adb connection over vsock is available only for VMs running in