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 dispositivodm-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
.
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.
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:
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.
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.
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:
- A estrutura monta a partição
/system
fora de um dispositivodm-verity
, que é empilhado em cima de um dispositivodm-user
. Isso significa que todas as E/S do sistema de arquivos raiz são roteadas paradm-user
. -
dm-user
roteia a E/S para o daemonsnapuserd
do espaço do usuário, que manipula a solicitação de E/S. - Quando a operação de mesclagem é concluída, a estrutura colapsa
dm-verity
sobredm-linear
(system_base
) e removedm-user
.
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:
-
init
de primeiro estágio iniciasnapuserd
do ramdisk e salva um descritor de arquivo aberto nele em uma variável de ambiente. -
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 deinit
. - A cópia do sistema de
init
lê a sepolicy combinada em uma string. -
Init
invocamlock()
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 interrompesnapuserd
. Depois disso, é proibido ler as partições, pois isso causa um impasse. - 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. - 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