Atualizações do sistema que não são A/B

As atualizações não AB são uma metodologia descontinuada de OTA usada por dispositivos Android mais antigos (Android 6 e anteriores). Esses dispositivos têm uma partição de recuperação dedicada que contém o software necessário para descompactar um pacote de atualização transferido por download e aplicar a atualização às outras partições.

Em dispositivos Android mais antigos sem partições A/B, o espaço de inicialização geralmente contém as seguintes partições:

inicialização
Contém o kernel do Linux e um sistema de arquivos raiz mínimo (carregado em um disco RAM). Ele monta o sistema e outras partições e inicia o ambiente de execução localizado na partição do sistema.
system
Contém aplicativos e bibliotecas do sistema que têm código-fonte disponível no Android Open Source Project (AOSP). Durante a operação normal, essa partição é montada como somente leitura. O conteúdo dela muda apenas durante uma atualização OTA.
fornecedor
Contém aplicativos e bibliotecas do sistema que não têm o código-fonte disponível no Android Open Source Project (AOSP). Durante a operação normal, essa partição é montada somente leitura. O conteúdo dela muda apenas durante uma atualização OTA.
userdata
Armazena os dados salvos por aplicativos instalados pelo usuário etc. Essa partição normalmente não é afetada pelo processo de atualização OTA.
cache
Área de retenção temporária usada por alguns aplicativos (o acesso a essa partição requer permissões especiais do app) e para o armazenamento de pacotes de atualização OTA transferidos por download. Outros programas usam esse espaço com a expectativa de que os arquivos possam desaparecer a qualquer momento. Algumas instalações de pacotes OTA podem resultar na eliminação completa dessa partição. O cache também contém os registros de atualização de uma atualização OTA.
recuperação
Contém um segundo sistema Linux completo, incluindo um kernel e o binário de recuperação especial que lê um pacote e usa o conteúdo dele para atualizar as outras partições.
Diversos
Pequena partição usada pela recuperação para armazenar algumas informações sobre o que está sendo feito caso o dispositivo seja reiniciado enquanto o pacote OTA está sendo aplicado.

Vida útil de uma atualização OTA

Uma atualização OTA típica contém as seguintes etapas:

  1. O dispositivo faz o check-in regular com os servidores OTA e é notificado sobre a disponibilidade de uma atualização, incluindo o URL do pacote de atualização e uma string de descrição para mostrar ao usuário.
  2. Faz a atualização de downloads para uma partição de dados ou de cache, e a assinatura criptográfica é verificada em relação aos certificados em /system/etc/security/otacerts.zip. O usuário é solicitado a instalar a atualização.
  3. O dispositivo é reinicializado no modo de recuperação, em que o kernel e o sistema na partição de recuperação são inicializados em vez do kernel na partição de inicialização.
  4. O binário de recuperação é iniciado pelo init. Ele encontra argumentos de linha de comando em /cache/recovery/command que apontam para o pacote transferido.
  5. A recuperação verifica a assinatura criptográfica do pacote em relação às chaves públicas em /res/keys (parte do disco RAM contido na partição de recuperação).
  6. Os dados são extraídos do pacote e usados para atualizar as partições de inicialização, do sistema e/ou do fornecedor, conforme necessário. Um dos novos arquivos deixados na partição do sistema contém o conteúdo da nova partição de recuperação.
  7. O dispositivo é reinicializado normalmente.
    1. A partição de inicialização atualizada é carregada, montada e começa a executar binários na partição do sistema atualizada.
    2. Como parte da inicialização normal, o sistema verifica o conteúdo da partição de recuperação em relação ao conteúdo desejado (que foi armazenado anteriormente como um arquivo em /system). Como eles são diferentes, a partição de recuperação é reescrita com o conteúdo desejado. (Em inicializações subsequentes, a partição de recuperação já contém o novo conteúdo, portanto, não é necessário refazer o flash.)

A atualização do sistema foi concluída. Os registros de atualização podem ser encontrados em /cache/recovery/last_log.#.

Atualizar pacotes

Um pacote de atualização é um arquivo .zip que contém o binário executável META-INF/com/google/android/update-binary. Depois de verificar a assinatura no pacote, o recovery extrai esse binário para /tmp e o executa, transmitindo os seguintes argumentos:

  • Atualize o número da versão da API binária. Se os argumentos transmitidos para a mudança de binário da atualização forem alterados, esse número vai aumentar.
  • Descritor de arquivos do canal de comando. O programa de atualização pode usar esse pipe para enviar comandos de volta ao binário de recuperação, principalmente para mudanças na interface, como indicar o progresso ao usuário.
  • Nome do arquivo .zip do pacote de atualização.

Um pacote de atualização pode usar qualquer binário vinculado estaticamente como o binário de atualização. As ferramentas de construção do pacote OTA usam o programa de atualização (bootable/recovery/updater), que oferece uma linguagem de script simples que pode realizar muitas tarefas de instalação. É possível substituir qualquer outro binário em execução no dispositivo.

Para saber mais sobre o binário do atualizador, a sintaxe do edify e as funções integradas, consulte Dentro dos pacotes OTA.

Migrar de versões anteriores

Ao migrar do Android 2.3/3.0/4.0, a principal mudança é a conversão de todas as funcionalidades específicas do dispositivo de um conjunto de funções C com nomes predefinidos para objetos C++. A tabela a seguir lista as funções antigas e os novos métodos que servem a uma finalidade equivalente:

Função C Método C++
device_recovery_start() Device::RecoveryStart()
device_toggle_display()
device_reboot_now()
RecoveryUI::CheckKey()
(também RecoveryUI::IsKeyPressed())
device_handle_key() Device::HandleMenuKey()
device_perform_action() Device::InvokeMenuItem()
device_wipe_data() Device::WipeData()
device_ui_init() ScreenRecoveryUI::Init()

A conversão de funções antigas em novos métodos precisa ser razoavelmente simples. Não se esqueça de adicionar a nova função make_device() para criar e retornar uma instância da nova subclasse de dispositivo.