Implementar atualizações OTA

Para implementar as atualizações OTA, o carregador de inicialização precisa ter acesso a um disco RAM de recuperação durante a inicialização. Se o dispositivo usar uma imagem de recuperação não modificada do AOSP, o carregador de inicialização vai ler os primeiros 32 bytes na partição misc. Se os dados corresponderem a boot-recovery, o carregador de inicialização será inicializado na imagem recovery. Esse método permite que qualquer trabalho de recuperação pendente (por exemplo, aplicar uma atualização OTA ou remover dados) continue a ser concluído.

Para detalhes sobre o conteúdo de um bloco em flash usado para comunicações por recuperação e pelo carregador de inicialização, consulte bootable/recovery/bootloader_message/bootloader_message.h.

Dispositivos com atualizações A/B

Para oferecer suporte a atualizações OTA em dispositivos que usam atualizações A/B, verifique se o carregador de inicialização do dispositivo atende aos critérios a seguir.

Critérios gerais

  • Todas as partições atualizadas por OTA precisam ser atualizáveis enquanto o sistema principal é inicializado, e não atualizada na recuperação.

  • Para inicializar a partição system, o carregador de inicialização transmite o seguinte valor na linha de comando do kernel: ro root=/dev/[node] rootwait init=/init.

  • É responsabilidade do framework do Android chamar markBootSuccessful na HAL. O carregador de inicialização nunca deve marcar uma partição como inicializada com êxito.

Suporte para HAL de controle de inicialização

O carregador de inicialização precisa ser compatível com a HAL boot_control, conforme definido em hardware/libhardware/include/hardware/boot_control.h. O atualizador consulta a HAL de controle de inicialização, atualiza o slot de inicialização que não está em uso, altera o slot ativo usando a HAL e reinicializa no sistema operacional atualizado. Para ver mais detalhes, consulte Como implementar a HAL de controle de inicialização.

Suporte para slots

O carregador de inicialização precisa ser compatível com funcionalidades relacionadas a partições e slots, incluindo:

  • Os nomes de partição precisam incluir um sufixo que identifique quais partições pertencem a um determinado slot no carregador de inicialização. Para cada partição, há uma variável correspondente has-slot:partition base name com um valor de yes. Os slots são nomeados alfabeticamente como a, b, c etc. e correspondem às partições com o sufixo _a, _b, _c etc. O carregador de inicialização precisa informar ao sistema operacional qual slot foi inicializado usando a propriedade de linha de comando androidboot.slot_suffix. Essa propriedade é definida pelo bootconfig para dispositivos iniciados com o Android 12 ou versões mais recentes.

  • O valor slot-retry-count é redefinido para um valor positivo (geralmente 3), pelo controle de inicialização HAL com o callback setActiveBootSlot ou o comando fastboot set_active. Ao modificar uma partição que faz parte de um slot, o carregador de inicialização limpa a "inicialização com sucesso" e redefine a contagem de novas tentativas do slot.

O carregador de inicialização também precisa determinar qual slot carregar. A figura mostra um exemplo de processo de decisão.

Fluxo de alocação do carregador de inicialização
Figura 1. Fluxo de alocação do carregador de inicialização
  1. Determine qual slot tentar. Não tente carregar um slot marcado como slot-unbootable. Esse slot precisa ser consistente com os valores retornados pelo fastboot e é chamado de slot atual.

  2. Se o slot atual não estiver marcado como slot-successful e tiver um slot-retry-count = 0, marque-o como slot-unbootable. Em seguida, selecione um slot diferente que não esteja marcado como unbootable e marcado como slot-successful. Esse slot agora é o selecionado. Se nenhum slot atual estiver disponível, inicialize para recuperação ou exiba uma mensagem de erro significativa para o usuário.

  3. Selecione o boot.img apropriado e inclua o caminho para corrigir a partição do sistema na linha de comando do kernel.

  4. Preencha o parâmetro slot_suffix da linha de comando do kernel.

  5. Inicialização. Se não estiver marcado como slot-successful, diminua slot-retry-count.

O utilitário fastboot determina qual partição atualizar ao executar qualquer comando de atualização. Por exemplo, executar o comando fastboot flash system system.img primeiro consulta a variável current-slot e depois concatena o resultado ao sistema para gerar o nome da partição que precisa ser atualizada (system_a, system_b etc.).

Ao configurar o slot atual usando o comando set_active do fastboot ou o comando setActiveBootSlot da HAL de controle de inicialização, o carregador de inicialização precisa atualizar o slot atual, limpar slot-unbootable e slot-successful e redefinir a contagem de novas tentativas. Essa é a única maneira de limpar slot-unbootable.

Dispositivos sem atualizações A/B

Para oferecer suporte a atualizações OTA em dispositivos que não usam atualizações A/B (consulte Dispositivos não atualizáveis A/B), verifique se o carregador de inicialização do dispositivo atende aos critérios a seguir.

  • A partição recovery precisa conter uma imagem capaz de ler uma imagem do sistema de alguma partição compatível (cache, userdata) e gravá-la na partição system.

  • O carregador de inicialização precisa ser compatível com a inicialização no modo de recuperação.

  • Se houver suporte para atualizações de imagem de rádio, a partição recovery também precisará atualizar o rádio. Isso pode ser feito de duas maneiras:

    • O carregador de inicialização atualiza o rádio. Nesse caso, é possível reiniciar a partir da partição de recuperação de volta para o carregador de inicialização para concluir a atualização.

    • A imagem de recuperação faz o rádio piscar.Essa funcionalidade pode ser fornecida como uma biblioteca binária ou um utilitário.