Visão geral A/B virtual

O Android tem dois mecanismos de atualização: atualizações A/B (contínuas) e atualizações não A/B. Para reduzir a complexidade do código e aprimorar o processo de atualização, no Android 11 os dois mecanismos são unificados por meio de A/B virtual para trazer atualizações perfeitas para todos os dispositivos com um custo de armazenamento minimizado. O Android 12 oferece a opção de compactação A/B virtual para compactar partições instantâneas. Tanto no Android 11 quanto no Android 12, o seguinte se aplica:

  • As atualizações A/B virtuais são perfeitas como as atualizações A/B. As atualizações A/B virtuais minimizam o tempo que um dispositivo fica offline e inutilizável.
  • As atualizações A/B virtuais podem ser revertidas . Se o novo sistema operacional falhar ao inicializar, os dispositivos reverterão 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 que são usadas pelo bootloader. Outras partições atualizáveis ​​são instantâneas .

Histórico e terminologia

Esta seção define a terminologia e descreve a tecnologia que suporta A/B virtual.

mapeador de dispositivos

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 inferior da pilha está a superpartição física (por exemplo, /dev/block/by-name/super ).
  • No meio está um dispositivo dm-linear , especificando quais blocos na superpartição formam a partição especificada. Isso 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.
  • No topo reside um dispositivo dm-verity , criado para partições verificadas. Este dispositivo verifica se os blocos no dispositivo dm-linear estão assinados corretamente. Ele aparece como /dev/block/mapper/system-verity e é a fonte do ponto de montagem /system .

A Figura 1 mostra a aparência da pilha sob o ponto de montagem /system .

Partition stacking underneath system

Figura 1. Empilhe sob o ponto de montagem /system

dm-instantâneo

O Virtual A/B depende do dm-snapshot , um módulo mapeador de dispositivos para captura instantânea do estado de um dispositivo de armazenamento. Ao usar dm-snapshot , há quatro dispositivos em jogo:

  • O dispositivo base é o dispositivo que é capturado. Nesta página, o dispositivo base é sempre uma partição dinâmica, como sistema ou fornecedor.
  • O dispositivo copy-on-write (COW), para registrar alterações no dispositivo base. Pode ser de qualquer tamanho, mas deve ser grande o suficiente para acomodar todas as alterações no dispositivo básico.
  • O dispositivo de instantâneo é criado usando o destino snapshot . As gravações no dispositivo de instantâneo são gravadas no dispositivo COW. As leituras do dispositivo de instantâneo são lidas do dispositivo base ou do dispositivo COW, dependendo se os dados acessados ​​foram alterados pelo instantâneo.
  • O dispositivo de origem é criado usando o destino snapshot-origin . Lê para o dispositivo de origem lido diretamente do dispositivo base. As gravações no dispositivo de origem gravam diretamente no dispositivo base, mas o backup dos dados originais é feito por meio da gravação no dispositivo COW.

Device mapping for dm-snapshot

Figura 2. Mapeamento de dispositivo para dm-snapshot

Instantâneos compactados

No Android 12 e superior, como os requisitos de espaço na partição /data podem ser altos, você pode habilitar instantâneos compactados em sua compilação para atender aos requisitos de espaço mais altos da partição /data .

Os instantâneos compactados A/B virtuais são criados com base nos seguintes componentes disponíveis no Android 12 e superior:

  • 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 de usuário para implementar um novo formato de instantâneo.

Esses componentes permitem a compactação. As outras alterações necessárias feitas para implementar os recursos de instantâneos compactados são fornecidas nas próximas seções: formato COW para instantâneos compactados , dm-user e Snapuserd .

Formato COW para instantâneos compactados

No Android 12 e superior, os instantâneos compactados usam um formato COW. Semelhante ao formato interno do kernel usado para instantâneos não compactados, o formato COW para instantâneos compactados tem seções alternadas de metadados e dados. Os metadados do formato original permitidos apenas para operações de substituição : Substitua o bloco X na imagem base pelo conteúdo do bloco Y no instantâneo. O formato COW de instantâneos compactados é mais expressivo e suporta as seguintes operações:

  • Copiar : O bloco X no dispositivo base deve ser substituído pelo bloco Y no dispositivo base.
  • Substituir : o bloco X no dispositivo base deve ser substituído pelo conteúdo do bloco Y no instantâneo. Cada um desses blocos é compactado em gz.
  • Zero : O bloco X no dispositivo base deve 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 superior.)

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

dm-user no Android 12

O módulo do kernel dm-user permite que userspace implemente dispositivos de bloco mapeadores de dispositivos. Uma entrada na tabela dm-user cria um dispositivo variado 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 o espaço do usuário preencher (para uma leitura) ou propagar (para uma gravação).

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

snapuserd

O componente snapuserd userspace para dm-user implementa a compressão Virtual A/B.

Na versão não compactada do Virtual A/B (no Android 11 e inferior ou no Android 12 sem a opção de instantâneo compactado), o dispositivo COW é um arquivo bruto. Quando a compactação está habilitada, o COW funciona como um dispositivo dm-user , que é conectado a uma instância do daemon snapuserd .

O kernel não usa o novo formato COW. Portanto, o componente snapuserd traduz solicitações entre o formato COW do Android e o formato interno do kernel:

Snapuserd component translating requests between Android COW format and kernel built-in format

Figura 3. Diagrama de fluxo do snapuserd como tradutor entre os formatos Android e Kernel COW

Essa conversão e descompactação nunca ocorre no disco. O componente snapuserd intercepta as leituras e gravações COW que ocorrem no kernel e as implementa usando o formato Android COW.

compressão XOR

Para dispositivos lançados com Android 13 e superior, o recurso de compactação XOR, ativado por padrão, permite que os instantâneos 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 os instantâneos não armazenam 4K bytes completos. Essa redução no tamanho do instantâneo é possível porque os dados XOR contêm muitos zeros e são mais fáceis de compactar do que os dados brutos do bloco. Em dispositivos Pixel, a compactação XOR reduz o tamanho do instantâneo em 25% a 40%.

Para dispositivos atualizados para Android 13 e superior, a compactação XOR deve estar ativada. Para obter detalhes, consulte compactação XOR .

Processos virtuais de compactação A/B

Esta seção fornece detalhes sobre o processo de compactação A/B virtual usado no Android 13 e no Android 12.

Lendo metadados (Android 12)

Os metadados são construídos por um daemon snapuserd . Os metadados são principalmente um mapeamento de dois IDs, de 8 bytes cada, que representam os setores a serem mesclados. Em dm-snapshot é chamado disk_exception .

struct disk_exception {
    uint64_t old_chunk;
    uint64_t new_chunk;
};

Uma exceção de disco é usada quando um bloco de dados antigo é substituído por um novo.

Um daemon snapuserd lê o arquivo COW interno por meio da biblioteca COW e constrói os metadados para cada uma das operações COW presentes no arquivo COW.

As leituras de metadados são iniciadas a partir do dm-snapshot no kernel quando o dispositivo dm- snapshot é criado.

A figura abaixo fornece um diagrama de sequência para o caminho IO para construção de metadados.

Sequence diagram, IO path for metadata construction

Figura 4. Fluxo de sequência para o caminho IO na construção de metadados

Mesclar (Android 12)

Após a conclusão do processo de inicialização, o mecanismo de atualização marca o slot como inicialização bem-sucedida e inicia a mesclagem alternando o destino dm-snapshot para o destino dm-snapshot-merge .

dm-snapshot percorre os metadados e inicia uma E/S de mesclagem para cada exceção de disco. Uma visão geral de alto nível do caminho de E/S de mesclagem é mostrada abaixo.

Merge IO path

Figura 5. Visão geral do caminho de E/S de mesclagem

Se o dispositivo for reinicializado durante o processo de mesclagem, a mesclagem será retomada na próxima reinicialização e a mesclagem será concluída.

Camadas do mapeador de dispositivos

Para dispositivos iniciados com Android 13 e superior, os processos de snapshot e mesclagem de snapshot na compactação A/B virtual são executados pelo componente snapuserd userspace. Para dispositivos atualizados para Android 13 e superior, esse recurso deve ser ativado. Para obter detalhes, consulte Fusão de espaço de usuário .

O seguinte descreve o processo de compactação A/B virtual:

  1. A estrutura monta a partição /system fora 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 roteia a E/S para o daemon snapuserd do espaço do usuário, que manipula a solicitação de E/S.
  3. Quando a operação de mesclagem é concluída, a estrutura colapsa dm-verity sobre dm-linear ( system_base ) e remove dm-user .

Processo de compressão A/B virtual

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

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

Iniciar transições

Ao inicializar com instantâneos compactados, o init de primeiro estágio deve iniciar snapuserd para montar as partições. Isso representa um problema: quando sepolicy é carregada e aplicada, snapuserd é colocado no contexto errado e suas solicitações de leitura falham, com negações do selinux.

Para resolver isso, snapuserd faz a transição em passo de bloqueio com init , como segue:

  1. init de primeiro estágio inicia snapuserd do ramdisk e salva um descritor de arquivo aberto nele em uma variável de ambiente.
  2. init de 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 a ext4. Em seguida, ele desativa todas as tabelas de mapeadores de dispositivos para dispositivos de instantâneo e interrompe snapuserd . Depois disso, é proibido ler as partições, pois isso causa um impasse.
  5. Usando o descritor aberto para a cópia do ramdisk do snapuserd , init reinicia o daemon com o contexto selinux correto. As tabelas do mapeador de dispositivos para dispositivos de instantâneo são reativadas.
  6. Init invoca munlockall() - é seguro executar IO novamente.

Uso do espaço

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

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

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

2 Assume que a nova imagem do sistema é do mesmo tamanho que a original.

3 O requisito de espaço é transitório até a reinicialização.

Para implementar o Virtual A/B ou para usar recursos de instantâneo compactado, consulte Implementando o Virtual A/B