Visão geral do A/B virtual

O A/B virtual é o principal mecanismo de atualização do Android. O A/B virtual é baseado em atualizações A/B legadas (consulte Atualizações A/B do sistema) e não A/B, que foi descontinuado no 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 snapshots e minimiza o uso do espaço em disco. Em uma atualização total, o tamanho do snapshot é reduzido em cerca de 45% com a compactação, e o tamanho do snapshot incremental da atualização por OTA é reduzido em cerca de 55%.

O Android 12 oferece a opção de compactação A/B virtual para compactar partições de snapshots. 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 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 o novo SO não inicializar, os dispositivos vão voltar 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 são criadas.

Contexto e terminologia

Esta seção define a terminologia e descreve a tecnologia que oferece suporte ao 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 de partição dinâmica são mesclados de volta ao dispositivo base pelo uso de dm-user e do daemon 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. Ela 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.

Partição empilhada abaixo do
sistema

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 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 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 o OTA e possui buffers distintos com 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:

  • Copiar: o bloco X no dispositivo base precisa ser substituído pelo bloco Y.
  • Replace: 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 completo do snapshot no disco tem esta aparência:

formato de vaca

Figura 2. Formato COW do Android no disco

dm-user

O módulo do kernel dm-user permite que userspace implemente dispositivos de bloco de 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 seja preenchido (para leitura) ou propagado (para gravação).

O módulo do kernel dm-user fornece uma nova interface visível para o usuário que não faz parte da base de código upstream kernel.org. Até que isso aconteça, 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. Todas as E/S para o snapshot precisam passar por esse serviço. Durante a instalação OTA, os novos dados do sistema operacional são gravados no snapshot pelo snapuserd (com compactação). A análise dos metadados e a descompactação de novos dados de bloco também são processadas 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 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 4K de 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 estão sendo atualizados 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 uma descrição do processo de compactação A/B virtual:

  1. O framework monta a partição /system de um dispositivo dm-verity, que é empilhado em cima de um dispositivo dm-user. Isso significa que todas as E/S do sistema de arquivos raiz são roteadas para dm-user.
  2. 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 reduz 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 do A/B virtual

O processo de mesclagem de snapshots pode ser interrompido. Se o dispositivo for reinicializado durante o processo de mesclagem, ele 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 esse problema, as transições snapuserd são sincronizadas com init, da seguinte maneira:

  1. O init de primeira fase inicia o snapuserd no ramdisk e salva um descritor de arquivo aberto para ele em uma variável de ambiente.
  2. 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 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 para ext4. Em seguida, ele desativa todas as tabelas de mapeamento de dispositivo para dispositivos de snapshot e interrompe snapuserd. Depois disso, fica 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 correto do selinux. As tabelas do Device-mapper para dispositivos de snapshot são reativadas.
  6. 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 extra 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)

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, a compactação tem suporte no formato COW específico do Android. Essa versão do A/B virtual exigia uma tradução da COW específica 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 snapshots compactados, consulte Como implementar o A/B virtual.