Implementar o A/B virtual

Para implementar o A/B virtual em um novo dispositivo ou adaptar um dispositivo lançado, você precisa fazer mudanças no código específico do dispositivo.

Flags de build

Os dispositivos que usam A/B virtual precisam ser configurados como um dispositivo A/B e iniciar com partições dinâmicas.

Para dispositivos lançados com A/B virtual, defina a herança da configuração básica do dispositivo A/B virtual:

$(call inherit-product, \
    $(SRC_TARGET_DIR)/product/virtual_ab_ota.mk)

Os dispositivos lançados com A/B virtual precisam de apenas metade do tamanho da placa para BOARD_SUPER_PARTITION_SIZE porque os slots B não estão mais em super. Ou seja, BOARD_SUPER_PARTITION_SIZE precisa ser maior ou igual a sum(size of update groups) + overhead, que, por sua vez, precisa ser maior ou igual a sum(size of partitions) + overhead.

No Android 13 e versões mais recentes, para ativar snapshots compactados com o Virtual A/B, herde a seguinte configuração de base:

$(call inherit-product, $(SRC_TARGET_DIR)/product/generic_ramdisk.mk)
$(call inherit-product, \
    $(SRC_TARGET_DIR)/product/virtual_ab_ota/vabc_features.mk)

Isso permite snapshots do espaço do usuário com o Virtual A/B usando um método de compressão sem operação. Em seguida, configure o método de compactação para um dos métodos compatíveis, zstd e lz4. No Android 15, a compactação pode ser ainda mais personalizada para atender às necessidades do dispositivo. Para mais informações, consulte Ajuste fino da compactação.

PRODUCT_VIRTUAL_AB_COMPRESSION_METHOD := lz4
PRODUCT_VIRTUAL_AB_COMPRESSION_FACTOR := 65536

No Android 12, para ativar snapshots compactados com A/B virtual, herde a seguinte configuração de base:

$(call inherit-product, $(SRC_TARGET_DIR)/product/generic_ramdisk.mk)
$(call inherit-product, \
    $(SRC_TARGET_DIR)/product/virtual_ab_ota/compression.mk)

Compactação XOR

Em dispositivos que estão fazendo upgrade para o Android 13 e versões mais recentes, o recurso de compactação XOR não é ativado por padrão. Para ativar a compactação XOR, adicione o seguinte ao arquivo .mk do dispositivo.

PRODUCT_VENDOR_PROPERTIES += ro.virtual_ab.compression.xor.enabled=true

A compactação XOR é ativada por padrão para dispositivos que herdam de android_t_baseline.mk.

Mesclagem do espaço do usuário

Na versão moderna do A/B virtual (Android T e versões mais recentes), o processo de mesclagem de snapshots acontece totalmente no espaço do usuário. Essa mudança é possível graças ao snapuserd e ao dm-user. Os dispositivos lançados com o Android 13 e versões mais recentes têm a fusão do espaço do usuário ativada por padrão. Para dispositivos mais antigos que estão sendo atualizados, essa propriedade pode ser definida com o seguinte:

PRODUCT_VENDOR_PROPERTIES += ro.virtual_ab.userspace.snapshots.enabled=true

HAL de controle de inicialização

O HAL de controle de inicialização fornece uma interface para que os clientes OTA controlem os slots de inicialização. A A/B virtual requer um upgrade de versão secundária do HAL de controle de inicialização porque APIs adicionais são necessárias para garantir que o carregador de inicialização esteja protegido durante a atualização ou a redefinição de fábrica. Consulte IBootControl.hal e types.hal para conferir a versão mais recente da definição da HAL.

// hardware/interfaces/boot/1.1/types.hal
enum MergeStatus : uint8_t {
    NONE, UNKNOWN, SNAPSHOTTED, MERGING, CANCELLED };

// hardware/interfaces/boot/1.1/IBootControl.hal
package android.hardware.boot@1.1;
interface IBootControl extends @1.0::IBootControl {
    setSnapshotMergeStatus(MergeStatus status)
        generates (bool success);
    getSnapshotMergeStatus()
        generates (MergeStatus status);
}
// Recommended implementation

Return<bool> BootControl::setSnapshotMergeStatus(MergeStatus v) {
    // Write value to persistent storage
    // e.g. misc partition (using libbootloader_message)
    // bootloader rejects wipe when status is SNAPSHOTTED
    // or MERGING
}

Mudanças no fstab

A integridade da partição de metadados é essencial para o processo de inicialização, principalmente logo após a aplicação de uma atualização OTA. Portanto, a partição de metadados precisa ser verificada antes que o first_stage_init a monte. Para garantir que isso aconteça, adicione a flag check fs_mgr à entrada de /metadata. Confira um exemplo:

/dev/block/by-name/metadata /metadata ext4 noatime,nosuid,nodev,discard,sync wait,formattable,first_stage_mount,check

Requisitos do kernel

Para ativar a criação de snapshots, defina CONFIG_DM_SNAPSHOT como true.

Para dispositivos que usam F2FS, inclua o patch do kernel f2fs: export FS_NOCOW_FL flag to user para corrigir a fixação de arquivos. Inclua também o patch do kernel f2fs: support aligned pinned file.

O A/B virtual depende de recursos adicionados na versão 4.3 do kernel: o bit de status de overflow nos destinos snapshot e snapshot-merge. Todos os dispositivos lançados com o Android 9 e versões mais recentes já têm a versão 4.4 ou mais recente do kernel.

Para ativar snapshots compactados, a versão mínima compatível do kernel é a 4.19. Defina CONFIG_DM_USER=m ou CONFIG_DM_USER=y. Se estiver usando o primeiro (um módulo), ele precisa ser carregado no ramdisk da primeira etapa. Para isso, adicione a seguinte linha ao Makefile do dispositivo:

BOARD_GENERIC_RAMDISK_KERNEL_MODULES_LOAD := dm-user.ko

Mudanças nas ferramentas do fastboot

O Android 11 faz as seguintes mudanças no protocolo fastboot:

  • getvar snapshot-update-status: retorna o valor que a HAL de controle de inicialização comunicou ao carregador de inicialização:
    • Se o estado for MERGING, o carregador de inicialização vai retornar merging.
    • Se o estado for SNAPSHOTTED, o carregador de inicialização vai retornar snapshotted.
    • Caso contrário, o carregador de inicialização precisa retornar none.
  • snapshot-update merge: conclui uma operação de mesclagem, inicializando a recuperação/fastbootd, se necessário. Esse comando só é válido se snapshot-update-status for merging e só é compatível com o fastbootd.
  • snapshot-update cancel — Define o status de mesclagem da HAL de controle de inicialização como CANCELLED. Esse comando é inválido quando o dispositivo está bloqueado.
  • erase ou wipe: um erase ou wipe de metadata, userdata ou uma partição que contém o status de fusão para a HAL de controle de inicialização precisa verificar o status de fusão do snapshot. Se o status for MERGING ou SNAPSHOTTED, o dispositivo vai interromper a operação.
  • set_active: um comando set_active que muda o slot ativo precisa verificar o status de fusão do snapshot. Se o status for MERGING, o dispositivo vai interromper a operação. O slot pode ser alterado com segurança no estado SNAPSHOTTED.

Essas mudanças foram criadas para evitar que um dispositivo seja acidentalmente não inicializável, mas podem prejudicar ferramentas automatizadas. Quando os comandos são usados como um componente de atualização de todas as partições, como a execução de fastboot flashall, é recomendado usar o seguinte fluxo:

  1. Consulta getvar snapshot-update-status.
  2. Se merging ou snapshotted, emita snapshot-update cancel.
  3. Siga as etapas de atualização.

Reduzir os requisitos de armazenamento

Recomendamos que dispositivos que não têm armazenamento A/B completo alocado no super e esperam usar /data conforme necessário usem a ferramenta de mapeamento de blocos. A ferramenta de mapeamento de blocos mantém a alocação consistente entre builds, reduzindo gravações desnecessárias no snapshot. Isso está documentado em Redução do tamanho da OTA.

Algoritmos de compactação OTA

Os pacotes OTA podem ser ajustados para diferentes métricas de desempenho. O Android oferece vários métodos de compactação compatíveis (lz4, zstd e none) que têm compensações entre o tempo de instalação, o uso do espaço COW, o tempo de inicialização e o tempo de fusão de snapshots. A opção padrão ativada para a variável virtual de teste A/B com compactação é lz4 compression method.

Ajuste de detalhes da compressão

Os algoritmos de compactação podem ser ainda mais personalizados por dois métodos: nível de compactação (a quantidade de compactação alcançada às custas da velocidade) e fator de compactação (o tamanho máximo da janela compactável). O nível de compactação está disponível para alguns algoritmos, como zstd, e mudar o nível implica uma compensação entre velocidade e taxa de compactação. O fator de compactação descreve o tamanho máximo da janela de compactação usado durante a instalação OTA. O padrão é definido como 64k, mas pode ser substituído personalizando o parâmetro de build PRODUCT_VIRTUAL_AB_COMPRESSION_FACTOR. Fatores de compactação compatíveis: 4k, 8k, 16k, 32k, 64k, 128k e 256k.

PRODUCT_VIRTUAL_AB_COMPRESSION_FACTOR := 65536

OTA incremental no Pixel 8 Pro

Tempo de instalação sem a fase de pós-instalação Uso de espaço do COW Tempo de inicialização após OTA Tempo de mesclagem do snapshot
lz4 18 min 15s 2,5 GB 32,7 s 98,6 s
zstd 24 min 49s 2,05 GB 36,3 s 133,2 s
none 16 min 42s 4,76 GB 28,7 s 76,6 segundos

OTA completa no Pixel 8 Pro

Tempo de instalação sem a fase de pós-instalação Uso de espaço do COW Tempo de inicialização após OTA Tempo de mesclagem do snapshot
lz4 15 min 11s 4,16 GB 17,6 s 82,2 s
zstd 16 min 19s 3,46 GB 21 seg 106,3 s
none 13 min e 33 s 6,39 GB 18,5 s 92,5 s