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 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 no ponto de montagem /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.
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:
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.
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.
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:
- A estrutura monta a partição
/system
de um dispositivodm-verity
, que é empilhado sobre um dispositivodm-user
. Isso significa que toda E/S do sistema de arquivos raiz é roteada paradm-user
. -
dm-user
roteia a E/S para o daemonsnapuserd
do espaço do usuário, que lida com a solicitação de E/S. - Quando a operação de mesclagem for concluída, a estrutura recolherá
dm-verity
sobredm-linear
(system_base
) e removerádm-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.
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:
-
init
de primeiro estágio iniciasnapuserd
a partir do ramdisk e salva um descritor de arquivo aberto 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 do
init
lê a sepolicy combinada em uma string. -
Init
invocamlock()
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 interrompesnapuserd
. Depois disso é proibido ler partições, pois isso causa deadlock. - 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. - 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