O A/B virtual é o principal mecanismo de atualização do Android. Os builds A/B virtuais se baseiam nas atualizações A/B legadas (consulte Atualizações do sistema A/B) e não A/B, que foram descontinuados 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 na 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 compactar os snapshots e minimiza o uso do 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 incremental da OTA é reduzido em cerca de 55%.
O Android 12 oferece a opção de compactação A/B virtual para compactar partições com snapshots. O A/B virtual oferece o seguinte:
- As atualizações A/B virtuais são integradas (a atualização ocorre inteiramente em segundo plano enquanto o dispositivo está operacional), como atualizações A/B. As atualizações A/B virtuais minimizam o tempo em que um dispositivo fica off-line e inutilizável.
- As atualizações A/B virtuais podem ser revertidas. Se houver falha na inicialização do novo SO, os dispositivos serão revertidos automaticamente para a versão anterior.
- As atualizações A/B virtuais usam um espaço mínimo extra duplicando apenas as partições usadas pelo carregador de inicialização. Outras partições atualizáveis têm snapshots.
Contexto e terminologia
Esta seção define a terminologia e descreve a tecnologia que oferece suporte ao A/B virtual. Durante a instalação do OTA, 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. Após a reinicialização do dispositivo, os dados da partição dinâmica são mesclados novamente no dispositivo base por meio do uso do dm-user e dos daemons Snapuserd. Esse processo ocorre 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
partições dinâmicas, partições como
/system
são uma pilha de dispositivos em camadas:
- Na parte de baixo da pilha, há a partição super física (por exemplo,
/dev/block/by-name/super
). - No meio, há um dispositivo
dm-linear
, que especifica quais blocos na superpartilha formam a partição dinâmica especificada. 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, está um dispositivo
dm-verity
, criado para partições verificadas. Esse dispositivo verifica se os blocos no dispositivodm-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 a aparência da pilha abaixo do ponto de montagem /system
.
Figura 1. Empilhamento 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 de espaço do usuário para implementar um novo formato de snapshot.
Esses componentes ativam a compactação. As outras mudanças necessárias feitas para implementar os recursos de snapshots compactados são fornecidas nas próximas seções: Formato COW para snapshots compactados, dm-user e snapuserd.
Formato COW para snapshots compactados
No Android 12 e 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 contendo operações COW e novos dados do sistema operacional. Em comparação com o formato de snapshot do kernel, que permitia apenas operações de substituição, substitua o bloco X na imagem 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:
- Cópia: o bloco X no dispositivo de base precisa ser substituído pelo bloco Y no dispositivo base.
- Substituir: o bloco X no dispositivo base precisa ser substituído pelo conteúdo do bloco Y no snapshot. Cada um desses blocos é comprimido em gz.
- Zero: o bloco X no dispositivo base precisa ser substituído por todos os zeros.
- XOR: o dispositivo COW armazena bytes compactados XOR entre o bloco X e o bloco Y. Disponível no Android 13 e em versões mais recentes.
As atualizações OTA completas consistem apenas em operações de substituir e zero. As atualizações OTA incrementais também podem ter operações de cópia.
O layout de snapshot completo no disco tem esta aparência:
Figura 2. Formato de COW do Android no disco
dm-user
O módulo do kernel dm-user permite que 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 pesquisar 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 seja preenchido (para uma leitura) ou propagado (para uma gravação).
O módulo do kernel dm-user
oferece uma nova interface visível para o usuário
que não faz parte da base de código upstream kernel.org. Até que seja, 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 do espaço do usuário responsável por gravar e ler
os dispositivos COW do Android. Toda a E/S do snapshot precisa passar por esse serviço.
Durante a instalação do OTA, novos dados do sistema operacional são gravados no snapshot por
Snapuserd (com compactação). A análise dos metadados e a descompactação de novos
dados do bloco também são tratadas 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 os 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 A/B virtual, o esquema de armazenamento de compactação XOR usa menos espaço do que o esquema de armazenamento padrão, porque snapshots não armazenam 4.000 bytes 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 dados de bloco brutos. 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.
Mesclar snapshots
Em dispositivos lançados com o Android 13 e versões mais recentes, os
processos de mesclagem e de snapshot na compactação A/B virtual são realizados
pelo componente de espaço do usuário snapuserd
. Para dispositivos que fizerem upgrade para o Android
13 e versões mais recentes, esse recurso precisa estar ativado. Para
mais detalhes, consulte Mesclar o espaço do usuário.
Confira a seguir a descrição do processo de compactação A/B virtual:
- O framework monta a partição
/system
fora de um dispositivodm-verity
, que é empilhado sobre um dispositivodm-user
. Isso significa que todas as E/S do sistema de arquivos raiz são roteadas paradm-user
. dm-user
encaminha a E/S para o daemonsnapuserd
do espaço do usuário, que processa a solicitação de E/S.- Quando a operação de mesclagem é concluída, o framework reduz
dm-verity
em cima dedm-linear
(system_base
) e removedm-user
.
Figura 3. Processo de compactação do A/B virtual
O processo de mesclagem de snapshots pode ser interrompido. Se o dispositivo for reinicializado durante o processo de mesclagem, esse processo será retomado após a reinicialização.
Transições de inicialização
Ao inicializar com snapshots compactados, a inicialização da primeira fase precisa iniciar
snapuserd
para montar partições. Isso gera 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, o snapuserd
faz transições em conjunto com o init
, da seguinte maneira:
- O
init
de primeiro estágio inicia osnapuserd
no ramdisk e salva um descritor de arquivo aberto para ele em uma variável de ambiente. - A
init
do primeiro estágio alterna o sistema de arquivos raiz para a partição do sistema e, em seguida, executa a cópia do sistema deinit
. - A cópia do sistema de
init
lê a sepolicy combinada em uma string. Init
invocamlock()
em todas as páginas com suporte para ext4. Em seguida, ele desativa todas as tabelas de mapeamento de dispositivo para dispositivos de snapshot e interrompe osnapuserd
. Depois disso, fica proibido ler das partições, porque isso causa um deadlock.- Usando o descritor aberto para a cópia do ramdisk de
snapuserd
,init
reinicia o daemon com o contexto correto do selinux. As tabelas de mapeador de dispositivo para dispositivos de snapshot são reativadas. - O init invoca
munlockall()
. É seguro realizar a E/S novamente.
Uso do 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 OTA do Pixel.
Impacto do tamanho | não A/B | A/B | A/B virtual | A/B virtual (compactado) |
---|---|---|---|---|
Imagem original da fábrica | Super de 4,5 GB (imagem de 3,8 GB + 700 MB reservados)1 | 9 GB super (3,8 GB + 700 MB reservados, para dois slots) | 4,5 GB super (3,8 GB de imagem + 700 MB reservados) | 4,5 GB super (3,8 GB de imagem + 700 MB reservados) |
Outras partições estáticas | /cache | Nenhum | Nenhum | Nenhum |
Armazenamento adicional durante a OTA (espaço retornado após a aplicação do 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 (superior e dados) | 9GB (super) | 8,3 GB3 (super e dados) | 6,6 GB3 (super e dados) |
1 Indica o layout presumido com base no mapeamento de pixels.
2Assume que a nova imagem do sistema tem o mesmo tamanho que a original.
3 O 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 COW do kernel. Isso foi descontinuado porque o formato COW do kernel não oferece suporte à compressão.
A/B virtual do Android 12
No Android 12, há suporte à compactação 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 do dm-snapshot
.
Para implementar o A/B virtual ou usar recursos de snapshot compactado, consulte Como implementar o A/B virtual.