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 contínuas para todos os dispositivos com um custo minimizado de armazenamento. O Android 12 oferece a opção de compactação A/B virtual para compactar partições com snapshots. Tanto no Android 11 quanto no Android 12, aplica-se o seguinte:

  • 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 off-line e inutilizável.
  • As atualizações A/B virtuais podem ser revertidas . Se o novo sistema operacional não 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 usadas pelo gerenciador de inicialização. Outras partições atualizáveis ​​são capturadas .

Antecedentes 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 frequentemente 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 fornecida. 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 origem do ponto de montagem /system .

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

Partition stacking underneath system

Figura 1. Pilha sob o ponto de montagem /system

instantâneo dm

Virtual A/B depende de dm-snapshot , um módulo mapeador de dispositivos para capturar instantâneos do estado de um dispositivo de armazenamento. Ao usar dm-snapshot , existem quatro dispositivos em jogo:

  • O dispositivo base é o dispositivo do qual é feito o snapshot. 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 base.
  • O dispositivo de snapshot é criado usando o destino snapshot . As gravações no dispositivo de instantâneo são gravadas no dispositivo COW. Lê o dispositivo de instantâneo lido 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 são gravadas 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 dispositivos para dm-snapshot

Instantâneos compactados

No Android 12 e versões posteriores, como os requisitos de espaço na partição /data podem ser altos, você pode ativar snapshots compactados em seu build para atender aos requisitos de espaço mais elevados da partição /data .

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

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

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 versões posteriores, os snapshots compactados usam o formato COW. Semelhante ao formato integrado do kernel usado para instantâneos não compactados, o formato COW para instantâneos compactados possui seções alternadas de metadados e dados. Os metadados do formato original permitem apenas 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:

  • Cópia : 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 com gz.
  • Zero : O bloco X no dispositivo base deve ser substituído por 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 .

usuário dm no Android 12

O módulo do kernel dm-user permite que userspace implemente dispositivos de bloco mapeadores de dispositivos. Uma entrada da 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 o espaço do usuário preencher (para leitura) ou propagar (para 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 upstream do kernel.org. Até que isso aconteça, o Google reserva-se o direito de modificar a interface dm-user no Android.

snapuserd

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

Na versão descompactada 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 está 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 Android COW e o formato integrado 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

Esta traduçã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, 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 Virtual A/B, 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 bytes completos de 4K. 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 de bloco brutos. 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 Compressã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. No 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

Mesclando (Android 12)

Assim que o processo de inicialização for concluído, 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 mesclagem IO 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 mesclagem de E/S

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 de mapeador de dispositivos

Para dispositivos lançados com Android 13 e versões posteriores, os processos de snapshot e mesclagem de snapshot na compactação Virtual A/B são executados pelo componente snapuserd userspace. Para dispositivos atualizados para Android 13 e superior, esse recurso deve estar ativado. Para obter detalhes, consulte Mesclagem do espaço do usuário .

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

  1. A estrutura monta a partição /system de um dispositivo dm-verity , que é empilhado sobre um dispositivo dm-user . Isso significa que toda E/S do sistema de arquivos raiz é roteada para dm-user .
  2. dm-user roteia a E/S para o daemon snapuserd do espaço do usuário, que lida com a solicitação de E/S.
  3. Quando a operação de mesclagem for concluída, a estrutura recolherá dm-verity sobre dm-linear ( system_base ) e removerá dm-user .

Processo de compactaçã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.

Transições de inicialização

Ao inicializar com snapshots compactados, o init de primeiro estágio deve iniciar snapuserd para montar 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 transições em lock-step com init , como segue:

  1. init de primeiro estágio inicia snapuserd a partir do ramdisk e salva um descritor de arquivo aberto 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 do init lê a sepolicy combinada em uma string.
  4. Init invoca mlock() em todas as páginas suportadas por ext4. Em seguida, ele desativa todas as tabelas do mapeador de dispositivos para dispositivos de instantâneo e interrompe snapuserd . Depois disso é proibido ler partições, pois isso causa deadlock.
  5. Usando o descritor aberto para a cópia do disco ram do snapuserd , init reinicia o daemon com o contexto selinux correto. As tabelas do mapeador de dispositivos para dispositivos de snapshot são reativadas.
  6. Init invoca munlockall() - é seguro executar IO novamente.

Uso de espaço

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

Impacto do tamanho não-A/B A/B A/B virtuais A/B virtual (compactado)
Imagem original de fábrica Super 4,5 GB (imagem de 3,8 G + 700 MB reservados) 1 9GB super (3,8G + 700M reservados, para dois slots) Super 4,5 GB (imagem de 3,8 G + 700 MB reservados) Super 4,5 GB (imagem de 3,8 G + 700 MB reservados)
Outras partições estáticas /cache Nenhum Nenhum Nenhum
Armazenamento adicional durante o OTA (espaço retornado 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) 9 GB (super) 8,3 GB 3 (super e dados) 6,6 GB 3 (super e dados)

1 Indica layout assumido com base no mapeamento de pixels.

2 Pressupõe que a nova imagem do sistema tenha o mesmo tamanho da original.

3 A necessidade de espaço é transitória até a reinicialização.

Para implementar Virtual A/B ou usar recursos de snapshot compactado, consulte Implementando Virtual A/B