VirtualizationService

O VirtualizationService gerencia várias VMs convidadas, protegidas ou não, executadas em um sistema Android, principalmente gerenciando instâncias do crosvm. O VirtualizationService expõe uma API AIDL, que serviços ou apps do sistema podem usar para iniciar, monitorar e interromper VMs. Para usar VirtualizationService, execute virtmgr diretamente ou importe javalib ou rustlib, que executa virtmgr como um processo filho.

Ciclo de vida da VM

O acesso a uma VM é rastreado pelo objeto IVirtualMachine. Enquanto houver pelo menos uma referência ao objeto IVirtualMachine, a VM vai continuar em execução, a menos que falhe ou seja encerrada por conta própria. Se todas as referências ao objeto IVirtualMachine forem descartadas antes do encerramento da VM, o VirtualizationService vai encerrar a VM automaticamente. Esse processo implica que, se o cliente que iniciou a VM for encerrado pelo eliminador de memória insuficiente, a VM também será encerrada, evitando vazamentos de recursos.

Cada VM é gerenciada pela própria instância do crosvm, que VirtualizationService gerencia em nome do cliente. O VirtualizationService em virtmgr inicia esses processos filhos do crosvm conforme necessário com recursos globais alocados incluindo o CID concedido por VirtualizationServiceInternal em virtualizationservice e transmite a eles os descritores de arquivo das imagens que a VM precisa. Em seguida, VirtualizationService monitora o processo filho para saber quando ele é encerrado e notificar os clientes restantes.

Pacotes de VM

O crosvm oferece duas maneiras diferentes de inicializar uma VM: com um kernel e um initrd ou com um carregador de inicialização. Em qualquer caso, um número arbitrário de imagens de disco também pode ser fornecido, que pode ser uma imagem bruta ou um composto de várias partições. As várias imagens são fornecidas pelo cliente como descritores de arquivo.

O VirtualizationService cria imagens de disco compostas sob demanda. Esse processo é necessário porque o arquivo de disco composto se refere internamente aos vários arquivos de imagem de partição que compõem o disco, que são transmitidos pelo cliente e podem não ser acessíveis diretamente pelo crosvm. Para contornar esse problema, o VirtualizationService garante que os números de descritores de arquivo herdados pelo crosvm sejam os mesmos usados pelo VirtualizationService na criação das imagens compostas. A imagem de disco composta usa nomes de arquivo no formato /proc/self/fd/N para representar cada arquivo de partição.

Para pVMs do Microdroid, o AVF inclui um carregador de inicialização, que carrega o kernel de uma partição de uma imagem de disco composto, seguindo o fluxo padrão de inicialização verificada do Android.

Sockets de VM (vsock)

A interface principal para comunicação entre pVMs é vsock, uma interface de soquete virtio padrão. Cada VM é identificada por um identificador de contexto de 32 bits (CID), que é análogo a um endereço IP, que VirtualizationServiceInternal atribui à VM quando VirtualizationService cria a VM, e pode expor serviços em qualquer número de porta escolhido pela VM. O CID é exclusivo enquanto a VM está em execução, mas o valor pode ser reciclado quando a VM é encerrada e todos os identificadores de vinculação IVirtualMachine para a VM são descartados.

Interface de depuração

O comando vm é fornecido para fins de depuração. Esse comando permite que um desenvolvedor inicie uma VM no shell, veja os registros dela e encerre a VM. Com o comando vm ou outras interfaces fornecidas pelo AVF, uma VM pode ser iniciada no modo depurável (FULL) ou não depurável (NONE). Com uma VM depurável, é possível ver registros no nível do SO, acessar o shell ADB e capturar um despejo de falha ou a carga útil do app. Recomendamos usar uma VM não depurável em produção. Para mais informações sobre a ferramenta de linha de comando e outras interfaces de depuração fornecidas pelo AVF, consulte debug/README.md.