Visão geral do A/B virtual

O A/B virtual é o principal mecanismo de atualização do Android. O A/B virtual se baseia em atualizações A/B legadas (consulte Atualizações do sistema A/B) e não A/B, que foi descontinuado na versão 15 para reduzir a sobrecarga de espaço das atualizações.

O A/B virtual não tem um slot extra para partições dinâmicas. Consulte partições dinâmicas. Em vez disso, o delta é gravado em um snapshot e, em seguida, mesclado à partição de base após a confirmação de uma inicialização bem-sucedida. O A/B virtual usa um formato de snapshot específico do Android. Consulte Formato COW para snapshots compactados, que permite a compactação de snapshots e minimiza o uso de espaço em disco. Em uma OTA completa, o tamanho do snapshot é reduzido em cerca de 45% com a compactação, e o tamanho do snapshot da OTA incremental é reduzido em cerca de 55%.

O Android 12 oferece a opção de compactação A/B virtual para compactar snapshots de partições. O A/B virtual oferece o seguinte:

  • As atualizações A/B virtuais são ininterruptas (a atualização acontece totalmente em segundo plano enquanto o dispositivo está operacional), assim como as atualizações A/B. As atualizações do A/B virtual minimizam o tempo em que um dispositivo fica off-line e inutilizável.
  • As atualizações A/B virtuais podem ser revertidas. Se o novo SO não for inicializado, os dispositivos vão reverter automaticamente para a versão anterior.
  • As atualizações A/B virtuais usam um mínimo de espaço extra duplicando apenas as partições usadas pelo carregador de inicialização. Outras partições atualizáveis são instantâneas.

Contexto e terminologia

Esta seção define a terminologia e descreve a tecnologia que oferece suporte ao teste A/B virtual. Durante a instalação OTA, os novos dados do sistema operacional são gravados no novo slot para partições físicas ou em um dispositivo COW específico do Android. Depois que o dispositivo é reinicializado, os dados da partição dinâmica são mesclados novamente no dispositivo base usando o dm-user e o daemon snapuserd. Esse processo acontece inteiramente no espaço do usuário.

Device-mapper

O device-mapper é uma camada de bloco virtual do Linux usada com frequência no Android. Com as partições dinâmicas, partições como /system são uma pilha de dispositivos em camadas:

  • Na parte de baixo da pilha está a partição física super (por exemplo, /dev/block/by-name/super).
  • No meio, há um dispositivo dm-linear, especificando quais blocos na superpartição formam a partição dinâmica. Ele aparece como /dev/block/mapper/system_[a|b] em um dispositivo A/B ou /dev/block/mapper/system em um dispositivo não A/B.
  • Na parte de cima, há um dispositivo dm-verity, criado para partições verificadas. Esse dispositivo verifica se os blocos no dispositivo dm-linear estão assinados corretamente. Ele aparece como /dev/block/mapper/system-verity e é a origem do ponto de montagem /system.

A Figura 1 mostra como é a pilha no ponto de montagem /system.

Empilhamento de partições abaixo do sistema

Figura 1. Pilha no ponto de montagem /system

Snapshots compactados

No Android 12 e versões mais recentes, como os requisitos de espaço na partição /data podem ser altos, é possível ativar snapshots compactados no build para atender aos requisitos de espaço mais altos da partição /data.

Os snapshots compactados A/B virtuais são criados com base nos seguintes componentes disponíveis no Android 12 e versões mais recentes:

  • dm-user, um módulo do kernel semelhante ao FUSE que permite que o espaço do usuário implemente dispositivos de bloco.
  • snapuserd, um daemon do espaço do usuário para implementar um novo formato de snapshot.

Esses componentes ativam a compactação. As outras mudanças necessárias para implementar os recursos de snapshots compactados são apresentadas nas próximas seções: Formato COW para snapshots compactados, dm-user e snapuserd.

Formato COW para snapshots compactados

No Android 12 e em versões mais recentes, os snapshots compactados usam um formato COW específico do Android. O formato COW contém metadados sobre a OTA e tem buffers distintos com operações COW e novos dados do sistema operacional. Em comparação com o formato de snapshot do kernel, que só permitia operações de substituição (substituir o bloco X na imagem de base pelo conteúdo do bloco Y no snapshot), o formato COW de snapshots compactados do Android é mais expressivo e oferece suporte às seguintes operações:

  • Copiar: o bloco X no dispositivo base precisa ser substituído pelo bloco Y no dispositivo base.
  • Substituir: o bloco X no dispositivo de base precisa ser substituído pelo conteúdo do bloco Y no snapshot. Cada um desses blocos é compactado com gz.
  • Zero: o bloco X no dispositivo base precisa ser substituído por todos os zeros.
  • XOR: o dispositivo COW armazena bytes compactados por XOR entre o bloco X e o bloco Y. (Disponível no Android 13 e versões mais recentes.)

As atualizações OTA completas consistem apenas em operações de substituição e zero. As atualizações OTA incrementais também podem ter operações de cópia.

O layout completo do snapshot no disco é assim:

formato de vaca

Figura 2. Formato COW do Android no disco

dm-user

O módulo do kernel dm-user permite que o userspace implemente dispositivos de bloco device-mapper. Uma entrada de tabela dm-user cria um dispositivo diverso em /dev/dm-user/<control-name>. Um processo userspace pode consultar o dispositivo para receber solicitações de leitura e gravação do kernel. Cada solicitação tem um buffer associado para que o espaço do usuário preencha (para uma leitura) ou propague (para uma gravação).

O módulo do kernel dm-user oferece uma nova interface visível para o usuário do kernel que não faz parte da base de código upstream do kernel.org. Até lá, o Google se reserva o direito de modificar a interface dm-user no Android.

snapuserd

O componente de espaço do usuário snapuserd para dm-user implementa a compactação A/B virtual. O snapuserd é um daemon de espaço do usuário responsável por gravar e ler os dispositivos COW do Android. Toda E/S para o snapshot precisa passar por esse serviço. Durante a instalação OTA, novos dados do sistema operacional são gravados no snapshot pelo snapuserd (com compactação). O parsing dos metadados e a descompactação dos novos dados de bloco também são processados aqui.

Compactação XOR

Para dispositivos lançados com o Android 13 e versões mais recentes, o recurso de compactação XOR, que é ativado por padrão, permite que snapshots do espaço do usuário armazenem bytes compactados XOR entre blocos antigos e novos. Quando apenas alguns bytes em um bloco são alterados em uma atualização do Virtual A/B, o esquema de armazenamento de compressão XOR usa menos espaço do que o esquema de armazenamento padrão porque os snapshots não armazenam bytes de 4K completos. Essa redução no tamanho do snapshot é possível porque os dados XOR contêm muitos zeros e são mais fáceis de compactar do que os dados brutos de blocos. Em dispositivos Pixel, a compactação XOR reduz o tamanho do snapshot em 25% a 40%.

Para dispositivos que estão fazendo upgrade para o Android 13 e versões mais recentes, a compactação XOR precisa estar ativada. Para mais detalhes, consulte Compactação XOR.

Fusão de snapshots

Em dispositivos lançados com o Android 13 e versões mais recentes, os processos de snapshot e mesclagem de snapshot na compactação A/B virtual são realizados pelo componente de espaço do usuário snapuserd. Para dispositivos que estão sendo atualizados para o Android 13 e versões mais recentes, esse recurso precisa ser ativado. Para detalhes, consulte Mesclagem do espaço do usuário.

A seguir, descrevemos o processo de compactação A/B virtual:

  1. O framework monta a partição /system em um dispositivo dm-verity, que é empilhado em cima de um dispositivo dm-user. Isso significa que todas as operações de E/S do sistema de arquivos raiz são encaminhadas para dm-user.
  2. O dm-user encaminha a E/S para o daemon snapuserd do espaço do usuário, que processa a solicitação de E/S.
  3. Quando a operação de mesclagem é concluída, o framework recolhe dm-verity em cima de dm-linear (system_base) e remove dm-user.

Processo de compactação A/B virtual

Figura 3. Processo de compactação A/B virtual

O processo de mesclagem de snapshots pode ser interrompido. Se o dispositivo for reinicializado durante o processo de fusão, ele será retomado após a reinicialização.

Transições de inicialização

Ao inicializar com snapshots compactados, o init da primeira etapa precisa iniciar snapuserd para montar partições. Isso causa um problema: quando o sepolicy é carregado e aplicado, o snapuserd é colocado no contexto errado, e as solicitações de leitura falham, com negações do SELinux.

Para resolver isso, as transições de snapuserd ocorrem em sincronia com init, da seguinte maneira:

  1. O init de primeira etapa inicia o snapuserd do ramdisk e salva um descritor de arquivo aberto nele em uma variável de ambiente.
  2. O init da primeira etapa muda o sistema de arquivos raiz para a partição do sistema e executa a cópia do sistema de init.
  3. A cópia do sistema de init lê a sepolicy combinada em uma string.
  4. Init invoca mlock() em todas as páginas com suporte a ext4. Em seguida, ele desativa todas as tabelas de mapeamento de dispositivos para dispositivos de snapshot e interrompe o snapuserd. Depois disso, é proibido ler das partições, porque isso causa um deadlock.
  5. Usando o descritor aberto para a cópia do ramdisk de snapuserd, init reinicia o daemon com o contexto selinux correto. As tabelas de mapeamento de dispositivos para dispositivos de snapshot são reativadas.
  6. Init invoca munlockall(). É seguro realizar E/S novamente.

Uso de espaço

A tabela a seguir mostra uma comparação do uso de espaço para diferentes mecanismos de OTA usando o SO e os tamanhos de OTA do Pixel.

Impacto do tamanho não A/B A/B A/B virtual A/B virtual (compactado)
Imagem original da fábrica 4,5 GB super (imagem de 3,8 G + 700 M reservados)1 9 GB super (3,8 G + 700 M reservados, para dois slots) 4,5 GB super (imagem de 3,8 G + 700 M reservados) 4,5 GB super (imagem de 3,8 G + 700 M reservados)
Outras partições estáticas /cache Nenhum Nenhum Nenhum
Armazenamento adicional durante a OTA (espaço retornado após a aplicação da OTA) 1,4 GB em /data 0 3,8 GB2 em /data 2,1 GB2 em /data
Armazenamento total necessário para aplicar a OTA 5,9 GB3 (super e dados) 9GB (super) 8,3 GB3 (super e dados) 6,6 GB3 (super e dados)

1Indica o layout presumido com base no mapeamento de pixels.

2: presume que a nova imagem do sistema tem o mesmo tamanho da original.

3O requisito de espaço é temporário até a reinicialização.

A/B virtual do Android 11

O Android 11 do Virtual A/B gravou na partição dinâmica usando o formato Kernel COW. Ele foi descontinuado porque o formato COW do kernel não é compatível com compactação.

A/B virtual do Android 12

No Android 12, a compactação é compatível na forma de um formato COW específico do Android. Essa versão do A/B virtual exigia uma tradução do COW específico do Android para o formato COW do kernel. Eventualmente, isso foi substituído no Android 13, que removeu a dependência do formato COW do kernel e também de dm-snapshot.

Para implementar o A/B virtual ou usar recursos de snapshot compactado, consulte Como implementar o A/B virtual.