O Google tem o compromisso de promover a igualdade racial para as comunidades negras. Saiba como.

Implementando atualizações A / B

OEMs e SoC vendedores que querem implementar actualizações do sistema A / B devem garantir que seus implementos bootloader do boot_control HAL e passa os parâmetros corretos para o kernel.

Implementando o HAL de controle de inicialização

A gestores de arranque / B-capaz de implementar o boot_control HAL em hardware/libhardware/include/hardware/boot_control.h . Você pode testar as implementações usando o system/extras/bootctl utilidade e system/extras/tests/bootloader/ .

Você também deve implementar a máquina de estado mostrada abaixo:

Máquina de estado Figura 1. Bootloader

Configurando o kernel

Para implementar atualizações do sistema A / B:

  1. Escolha a seguinte série de patch do kernel (se necessário):
  2. Certifique-se de argumentos de linha de comando do kernel conter os seguintes argumentos extras:
    skip_initramfs rootwait ro init=/init root="/dev/dm-0 dm=system none ro,0 1 android-verity <public-key-id> <path-to-system-partition>"
    ... onde o <public-key-id> valor é o ID da chave pública utilizada para verificar a assinatura de tabela de verdade (para detalhes, ver dm-verdade ) .
  3. Adicione o certificado .X509 contendo a chave pública ao chaveiro do sistema:
    1. Copie o certificado .X509 formatado no .der formato para a raiz do kernel diretório. Se o certificado .X509 é formatado como uma .pem arquivo, use o seguinte openssl comando converter de .pem para .der formato:
      openssl x509 -in <x509-pem-certificate> -outform der -out <x509-der-certificate>
    2. Construir o zImage para incluir o certificado como parte do conjunto de chaves do sistema. Para verificar, verificar o procfs entrada (requer KEYS_CONFIG_DEBUG_PROC_KEYS a ser ativado):
      angler:/# cat /proc/keys
      
      1c8a217e I------     1 perm 1f010000     0     0 asymmetri
      Android: 7e4333f9bba00adfe0ede979e28ed1920492b40f: X509.RSA 0492b40f []
      2d454e3e I------     1 perm 1f030000     0     0 keyring
      .system_keyring: 1/4
      inclusão bem-sucedida do certificado .X509 indica a presença da chave pública no chaveiro do sistema (destaque denota o ID de chave pública).
    3. Substitua o espaço com # e passá-lo como <public-key-id> na linha de comando do kernel. Por exemplo, passar Android:#7e4333f9bba00adfe0ede979e28ed1920492b40f no lugar de <public-key-id> .

Configurando variáveis ​​de construção

Os carregadores de inicialização com capacidade A / B devem atender aos seguintes critérios de variável de compilação:

Deve definir para alvo A / B
  • AB_OTA_UPDATER := true
  • AB_OTA_PARTITIONS := \
    boot \
    system \
    vendor
    e outras partições actualizados através update_engine (rádio, bootloader, etc.)
  • PRODUCT_PACKAGES += \
    update_engine \
    update_verifier
Por exemplo, referem-se a /device/google/marlin/+/android-7.1.0_r1/device-common.mk . Opcionalmente, é possível realizar a pós-instalação (mas pré-reinicialização) dex2oat passo descrito na Compilação .
Fortemente recomendado para alvo A / B
  • Definir TARGET_NO_RECOVERY := true
  • Definir BOARD_USES_RECOVERY_AS_BOOT := true
  • Não defina BOARD_RECOVERYIMAGE_PARTITION_SIZE
Não é possível definir para alvo A / B
  • BOARD_CACHEIMAGE_PARTITION_SIZE
  • BOARD_CACHEIMAGE_FILE_SYSTEM_TYPE
Opcional para compilações de depuração PRODUCT_PACKAGES_DEBUG += update_engine_client

Configurando partições (slots)

Os dispositivos A / B não precisam de uma partição de recuperação ou partição de cache porque o Android não usa mais essas partições. A partição de dados agora é usada para o pacote OTA baixado e o código da imagem de recuperação está na partição de inicialização. Todas as partições que são A / B-ED deve ser chamado como se segue (ranhuras são sempre nomeados a , b , etc): boot_a , boot_b , system_a , system_b , vendor_a , vendor_b .

Cache

Para atualizações não A / B, a partição de cache foi usada para armazenar pacotes OTA baixados e para esconder blocos temporariamente durante a aplicação de atualizações. Nunca houve uma boa maneira de dimensionar a partição do cache: o tamanho necessário dependia de quais atualizações você desejava aplicar. O pior caso seria uma partição de cache tão grande quanto a imagem do sistema. Com as atualizações A / B, não há necessidade de esconder blocos (porque você está sempre gravando em uma partição que não é usada atualmente) e com o streaming A / B não há necessidade de baixar o pacote OTA inteiro antes de aplicá-lo.

Recuperação

O disco de recuperação RAM agora está contido no boot.img arquivo. Quando entrar em recuperação, o bootloader não pode colocar o skip_initramfs opção na linha de comando do kernel.

Para atualizações não A / B, a partição de recuperação contém o código usado para aplicar as atualizações. A updates / B são aplicados por update_engine correndo na imagem do sistema bota regular. Ainda há um modo de recuperação usado para implementar a redefinição dos dados de fábrica e o sideload de pacotes de atualização (de onde veio o nome "recuperação"). O código e os dados para o modo de recuperação são armazenados na partição de inicialização normal em um ramdisk; para inicializar na imagem do sistema, o carregador de inicialização diz ao kernel para pular o ramdisk (caso contrário, o dispositivo inicializa no modo de recuperação. O modo de recuperação é pequeno (e grande parte dele já estava na partição de inicialização), então a partição de inicialização não aumenta no tamanho.

Fstab

O slotselect argumento deve estar na linha para as partições A / B-ed. Por exemplo:

<path-to-block-device>/vendor  /vendor  ext4  ro
wait,verify=<path-to-block-device>/metadata,slotselect

Nenhuma partição deve ser nomeado vendor . Em vez disso, partição vendor_a ou vendor_b será seleccionado e montado no /vendor ponto de montagem.

Argumentos de slot de kernel

O sufixo ranhura atual deve ser passada através de um nó de árvore de dispositivo específico (DT) ( /firmware/android/slot_suffix ) ou através do androidboot.slot_suffix linha de comando do kernel ou argumento bootconfig.

Por padrão, o fastboot atualiza o slot atual em um dispositivo A / B. Se o pacote de atualização também contém imagens para o outro slot não atual, o fastboot atualiza essas imagens também. As opções disponíveis incluem:

  • --slot SLOT . Substitua o comportamento padrão e solicite que o fastboot atualize o slot que é passado como um argumento.
  • --set-active [ SLOT ] . Defina o slot como ativo. Se nenhum argumento opcional for especificado, o slot atual será definido como ativo.
  • fastboot --help . Obtenha detalhes sobre os comandos.

Se o fastboot implementos bootloader, ele deve suportar o comando set_active <slot> que define o atual ranhura ativa para o slot dada (isto também deve limpar o sinalizador não arranca para esse slot e repor a contagem de repetição para valores padrão). O bootloader também deve suportar as seguintes variáveis:

  • has-slot:<partition-base-name-without-suffix> . Retorna “sim” se a partição fornecida suportar slots, “não” caso contrário.
  • current-slot . Retorna o sufixo do slot que será inicializado a partir do próximo.
  • slot-count . Retorna um número inteiro que representa o número de slots disponíveis. Atualmente, dois slots são suportados de modo que este valor é 2 .
  • slot-successful:<slot-suffix> . Retorna "sim" se o slot fornecido foi marcado como inicializando com sucesso, "não" caso contrário.
  • slot-unbootable:<slot-suffix> . Retorna “sim” se o slot fornecido está marcado como não inicializável, “não” caso contrário.
  • slot-retry-count . Número de novas tentativas restantes para tentar inicializar o slot fornecido.

Para ver todas as variáveis, executar fastboot getvar all .

Gerando pacotes OTA

As ferramentas de pacote OTA seguir os mesmos comandos que os comandos para os dispositivos não-A / B. O target_files.zip arquivo deve ser gerado, definindo as variáveis de compilação para o destino A / B. As ferramentas de pacote OTA identificam e geram pacotes automaticamente no formato do atualizador A / B.

Exemplos:

  • Para gerar um OTA completa:
    ./build/make/tools/releasetools/ota_from_target_files \
        dist_output/tardis-target_files.zip \
        ota_update.zip
    
  • Para gerar um incremental OTA:
    ./build/make/tools/releasetools/ota_from_target_files \
        -i PREVIOUS-tardis-target_files.zip \
        dist_output/tardis-target_files.zip \
        incremental_ota_update.zip
    

Configurando partições

O update_engine pode actualizar qualquer par de partições A / B definidos no mesmo disco. Um par de divisórias tem um prefixo comum (tal como system ou boot ) e o sufixo por slot (tais como _a ). A lista de partições para o qual o gerador de carga define uma atualização está configurado pelos AB_OTA_PARTITIONS tornar variável.

Por exemplo, se um par de partições bootloader_a e booloader_b estão incluídas ( _a e _b são os sufixos caça-níqueis), você pode atualizar essas partições, especificando o seguinte na configuração do produto ou placa:

AB_OTA_PARTITIONS := \
  boot \
  system \
  bootloader

Todas as partições atualizados pelo update_engine não deve ser modificado pelo resto do sistema. Durante as atualizações incrementais ou delta, os dados binários a partir da entrada de corrente é usado para gerar os dados no novo slot. Qualquer modificação pode fazer com que os novos dados do slot falhem na verificação durante o processo de atualização e, portanto, falhem na atualização.

Configurando a pós-instalação

Você pode configurar a etapa de pós-instalação de maneira diferente para cada partição atualizada usando um conjunto de pares de chave-valor. Para executar um programa localizado na /system/usr/bin/postinst em uma nova imagem, especificar o caminho relativo à raiz do sistema de arquivos na partição do sistema.

Por exemplo, usr/bin/postinst é system/usr/bin/postinst (se não utilizar um disco de RAM). Além disso, especificar o tipo de sistema de arquivos para passar para a mount(2) chamada de sistema. Adicione o seguinte para o produto ou dispositivo .mk arquivos (se aplicável):

AB_OTA_POSTINSTALL_CONFIG += \
  RUN_POSTINSTALL_system=true \
  POSTINSTALL_PATH_system=usr/bin/postinst \
  FILESYSTEM_TYPE_system=ext4

Compilando

Por razões de segurança, system_server não pode usar just-in-time (JIT) compilação. Isto significa que você deve compilar antes do tempo arquivos odex para system_server e suas dependências, no mínimo; qualquer outra coisa é opcional.

Para compilar aplicativos em segundo plano, você deve adicionar o seguinte à configuração do dispositivo do produto (no device.mk do produto):

  1. Inclua os componentes nativos na construção para garantir que o script de compilação e os binários sejam compilados e incluídos na imagem do sistema.
      # A/B OTA dexopt package
      PRODUCT_PACKAGES += otapreopt_script
    
  2. Conecte o script de compilação para update_engine de tal forma que é executado como um pós-instalação passo.
      # A/B OTA dexopt update_engine hookup
      AB_OTA_POSTINSTALL_CONFIG += \
        RUN_POSTINSTALL_system=true \
        POSTINSTALL_PATH_system=system/bin/otapreopt_script \
        FILESYSTEM_TYPE_system=ext4 \
        POSTINSTALL_OPTIONAL_system=true
    

Para obter ajuda para instalar os arquivos preopted na partição do sistema não utilizados segundo, referem-se a primeira instalação de inicialização de arquivos DEX_PREOPT .