Implementar A/B virtual

Para implementar A/B virtual em um novo dispositivo ou para atualizar um dispositivo iniciado, você deve fazer alterações no código específico do dispositivo.

Construir bandeiras

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

Para dispositivos iniciados com A/B virtual, defina-os para herdar a configuração básica do dispositivo A/B virtual:

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

Os dispositivos iniciados com A/B virtual precisam apenas da 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 deve ser maior ou igual a sum(size of update groups) + overhead , que, por sua vez, deve ser maior ou igual a sum(size of partitions) + overhead .

Para Android 13 e superior, para habilitar snapshots compactados com Virtual A/B, herde a seguinte configuração básica:

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

Isso permite instantâneos do espaço do usuário com Virtual A/B ao usar um método de compactação não operacional. Você pode então configurar o método de compactação para um dos métodos suportados, gz e brotli .

PRODUCT_VIRTUAL_AB_COMPRESSION_METHOD := gz

Para o Android 12, para habilitar snapshots compactados com Virtual A/B, herde a seguinte configuração básica:

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

compressão XOR

Para dispositivos atualizados para Android 13 e superior, 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 é habilitada por padrão para dispositivos que herdam de android_t_baseline.mk .

Fusão do espaço do usuário

Para dispositivos atualizados para o Android 13 e superior, o processo de mesclagem do espaço do usuário, conforme descrito em Camadas do mapeador de dispositivos, não é ativado por padrão. Para habilitar a mesclagem do espaço do usuário, adicione a seguinte linha ao arquivo .mk do dispositivo:

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

A mesclagem do espaço do usuário é habilitada por padrão em dispositivos iniciados com 13 e superior.

Controle de inicialização HAL

O HAL de controle de inicialização fornece uma interface para clientes OTA controlarem os slots de inicialização. O Virtual A/B requer uma atualização 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 o flashing/redefinição de fábrica. Consulte IBootControl.hal e types.hal para obter a versão mais recente da definição 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, especialmente logo após a aplicação de uma atualização OTA. Portanto, a partição de metadados deve ser verificada antes de first_stage_init montá-la. Para garantir que isso aconteça, adicione o sinalizador check fs_mgr à entrada para /metadata . O seguinte fornece 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 captura instantânea, defina CONFIG_DM_SNAPSHOT como true .

Para dispositivos que usam F2FS, inclua o f2fs: export FS_NOCOW_FL flag to user kernel patch to fix file pinning. Inclua o f2fs: suporte ao patch de kernel de arquivo fixado alinhado também.

O Virtual A/B conta com recursos adicionados na versão 4.3 do kernel: o bit de status de estouro no snapshot e os destinos snapshot-merge . Todos os dispositivos iniciados com Android 9 e posterior já devem ter a versão do kernel 4.4 ou posterior.

Para habilitar instantâneos compactados, a versão mínima do kernel compatível é 4.19. Defina CONFIG_DM_USER=m ou CONFIG_DM_USER=y . Se estiver usando o primeiro (um módulo), o módulo deve ser carregado no ramdisk de primeiro estágio. Isso pode ser feito adicionando a seguinte linha ao Makefile do dispositivo:

BOARD_GENERIC_RAMDISK_KERNEL_MODULES_LOAD := dm-user.ko

Retrofit em dispositivos atualizando para o Android 11

Ao atualizar para o Android 11, os dispositivos iniciados com partições dinâmicas podem, opcionalmente, atualizar o A/B virtual. O processo de atualização é basicamente o mesmo para dispositivos iniciados com A/B virtual, com algumas pequenas diferenças:

  • Localização dos arquivos COW — Para dispositivos de inicialização, o cliente OTA usa todo o espaço vazio disponível na superpartição antes de usar o espaço em /data . Para dispositivos de atualização, sempre há espaço suficiente na super partição para que o arquivo COW nunca seja criado em /data .

  • Sinalizadores de recursos de tempo de construção — Para dispositivos que adaptam o A/B virtual, PRODUCT_VIRTUAL_AB_OTA e PRODUCT_VIRTUAL_AB_OTA_RETROFIT são definidos como true , conforme mostrado abaixo:

    (call inherit-product, \
        (SRC_TARGET_DIR)/product/virtual_ab_ota_retrofit.mk)
    
  • Super tamanho da partição — Os dispositivos iniciados com A/B virtual podem cortar BOARD_SUPER_PARTITION_SIZE pela metade porque os slots B não estão na super partição. Os dispositivos que adaptam o A/B virtual mantêm o antigo tamanho da superpartição, então BOARD_SUPER_PARTITION_SIZE é maior ou igual a 2 * sum(size of update groups) + overhead , que por sua vez é maior ou igual a 2 * sum(size of partitions) + despesas gerais .

Alterações do carregador de inicialização

Durante a etapa de mesclagem de uma atualização, /data contém a única instância inteira do sistema operacional Android. Após o início da migração, o system nativo, vendor e as partições product ficam incompletos até que a cópia seja concluída. Se o dispositivo for redefinido para as configurações de fábrica durante esse processo, seja por recuperação ou por meio da caixa de diálogo Configurações do sistema, o dispositivo não poderá ser inicializado.

Antes de apagar /data , conclua a mesclagem em recuperação ou reversão, dependendo do estado do dispositivo:

  • Se a nova compilação inicializou com êxito antes, conclua a migração.
  • Caso contrário, reverta para o slot antigo:
    • Para partições dinâmicas, reverta para o estado anterior.
    • Para partições estáticas, defina o slot ativo para o slot antigo.

Tanto o bootloader quanto fastbootd podem apagar a partição /data se o dispositivo estiver desbloqueado. Embora fastbootd possa forçar a conclusão da migração, o bootloader não pode. O bootloader não sabe se uma mesclagem está ou não em andamento ou quais blocos em /data constituem as partições do sistema operacional. Os dispositivos devem impedir que o usuário torne o dispositivo inoperável (bricking) inadvertidamente, fazendo o seguinte:

  1. Implemente o HAL de controle de inicialização para que o carregador de inicialização possa ler o valor definido pelo método setSnapshotMergeStatus() .
  2. Se o status de mesclagem for MERGING , ou se o status de mesclagem for SNAPSHOTTED e o slot tiver mudado para o slot recém-atualizado, as solicitações para limpar userdata , metadata ou a partição que armazena o status de mesclagem devem ser rejeitadas no bootloader.
  3. Implemente o comando fastboot snapshot-update cancel para que os usuários possam sinalizar ao bootloader que desejam ignorar esse mecanismo de proteção.
  4. Modifique ferramentas ou scripts de flash personalizados para fastboot snapshot-update cancel ao atualizar todo o dispositivo. Isso é seguro para emitir porque o flash de todo o dispositivo remove o OTA. As ferramentas podem detectar esse comando em tempo de execução implementando fastboot getvar snapshot-update-status . Este comando ajuda a diferenciar as condições de erro.

Exemplo

struct VirtualAbState {
    uint8_t StructVersion;
    uint8_t MergeStatus;
    uint8_t SourceSlot;
};

bool ShouldPreventUserdataWipe() {
    VirtualAbState state;
    if (!ReadVirtualAbState(&state)) ...
    return state.MergeStatus == MergeStatus::MERGING ||
           (state.MergeStatus == MergeStatus::SNAPSHOTTED &&
            state.SourceSlot != CurrentSlot()));
}

Mudanças nas ferramentas de inicialização rápida

O Android 11 faz as seguintes alterações no protocolo fastboot:

  • getvar snapshot-update-status — Retorna o valor que o controle de boot HAL comunicou ao bootloader:
    • Se o estado for MERGING , o bootloader deve retornar merging .
    • Se o estado for SNAPSHOTTED , o bootloader deve retornar snapshotted .
    • Caso contrário, o bootloader deve retornar none .
  • snapshot-update merge — Conclui uma operação de mesclagem, inicializando em recovery/fastbootd, se necessário. Este comando é válido somente se snapshot-update-status for merging e só é suportado em fastbootd.
  • snapshot-update cancel — Define o status de mesclagem do HAL de controle de inicialização para CANCELLED . Este 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 mesclagem para o HAL de controle de inicialização deve verificar o status de mesclagem do instantâneo. Se o status for MERGING ou SNAPSHOTTED , o dispositivo deve abortar a operação.
  • set_active — Um comando set_active que altera o slot ativo deve verificar o status de mesclagem do instantâneo. Se o status for MERGING , o dispositivo deve abortar a operação. O slot pode ser alterado com segurança no estado SNAPSHOTTED .

Essas alterações são projetadas para evitar que um dispositivo não inicialize acidentalmente, mas podem ser prejudiciais para ferramentas automatizadas. Quando os comandos são usados ​​como um componente de atualização de todas as partições, como executar fastboot flashall , é recomendável usar o seguinte fluxo:

  1. Consulta getvar snapshot-update-status .
  2. Se merging ou snapshotted , emita snapshot-update cancel .
  3. Prossiga com as etapas intermitentes.

Reduza os requisitos de armazenamento

Os dispositivos que não têm armazenamento A/B completo alocado em super e esperam usar /data conforme necessário, são altamente recomendados para usar a ferramenta de mapeamento de blocos. A ferramenta de mapeamento de blocos mantém a alocação de blocos consistente entre as compilações, reduzindo gravações desnecessárias no instantâneo. Isso está documentado em Redução do tamanho do OTA .

Métodos de compressão OTA

Os pacotes Ota podem ser ajustados para diferentes métricas de desempenho. Atualmente, o Android fornece alguns métodos de compactação suportados ( gz , lz4 e none ) que têm compensações entre tempo de instalação, uso de espaço COW, tempo de inicialização e tempo de mesclagem de instantâneo. A opção padrão habilitada para ab virtual com compactação é o gz compression method . (Observação: o desempenho relativo entre os métodos de compactação varia dependendo da velocidade da CPU e da taxa de transferência de armazenamento, que pode mudar dependendo do dispositivo. Todos os pacotes OTA gerados abaixo estão com o PostInstall desativado, o que diminuirá um pouco o tempo de inicialização. O tamanho total da partição dinâmica de um ota completo sem compactação é de 4,81 GB ).

OTA incremental no Pixel 6 Pro

Tempo de instalação sem fase de pós-instalação Uso do espaço COW Tempo de inicialização pós-OTA Tempo de mesclagem do instantâneo
gz 24 minutos 1,18 GB 40,2 seg 45,5 segundos
lz4 13 minutos 1,49 GB 37,4 seg 37,1 seg
nenhum 13 minutos 2,90 GB 37,6 seg 40,7 seg

OTA completo no Pixel 6 Pro

Tempo de instalação sem fase de pós-instalação Uso do Espaço COW Tempo de inicialização pós-OTA Tempo de mesclagem do instantâneo
gz 23 minutos 2,79 GB 24,9 seg 41,7 seg
lz4 12 minutos 3,46 GB 20,0 seg 25,3 seg
nenhum 10 minutos 4,85 GB 20,6 seg 29,8 seg