OTA para dispositivos A/B sem partições dinâmicas

O Android 10 oferece suporte partições dinâmicas, uma técnica de particionamento que pode criar, redimensionar e destruir partições durante atualizações OTA.

Esta página descreve como os clientes OTA redimensionam partições dinâmicas durante uma atualização de dispositivos A/B lançados sem suporte a partições dinâmicas e como os clientes OTA são atualizados para o Android 10.

Contexto

Durante a atualização de um dispositivo A/B para oferecer suporte a partições dinâmicas, a A tabela de partições GUID (GPT) no dispositivo é preservada, por isso não há super partição no dispositivo. Os metadados são armazenados em system_a e system_b, mas pode ser pode ser personalizado mudando BOARD_SUPER_PARTITION_METADATA_DEVICE.

Em cada um dos dispositivos de bloco há dois slots de metadados. Só um do slot de metadados em cada dispositivo de blocos. Por exemplo, os metadados 0 em system_a e Metadados 1 às system_b correspondem às partições nos slots A e B, respectivamente. Em ambiente de execução, não importa qual slot esteja sendo atualizado.

Nesta página, os slots de metadados são chamados de Metadata S (origem) e Metadados T (destino). Da mesma forma, as partições são chamadas como system_s, vendor_t e assim por diante.

Para saber mais sobre as configurações do sistema de build, consulte Fazer upgrade de dispositivos.

Para mais informações sobre como as partições pertencem à política de atualização, grupos, consulte Quadro mudanças na configuração de novos dispositivos.

Um exemplo de metadados em um dispositivo é:

  • Dispositivo de bloqueio físico system_a
    • Metadados 0
      • Grupo foo_a
        • Partição lógica (dinâmica) system_a
        • Partição lógica (dinâmica) product_services_a
        • Outras partições atualizadas pelo Foo
      • Grupo bar_a
        • Partição lógica (dinâmica) vendor_a
        • Partição lógica (dinâmica) product_a
        • Outras partições atualizadas por Barra
    • Metadados 1 (não usado)
  • Dispositivo de bloqueio físico system_b
    • Metadados 0 (não usado)
    • Metadados 1
      • Grupo foo_b
        • Partição lógica (dinâmica) system_b
        • Partição lógica (dinâmica) product_services_b
        • Outras partições atualizadas pelo Foo
      • Barra do grupo_b
        • Partição lógica (dinâmica) vendor_b
        • Partição lógica (dinâmica) product_b
        • Outras partições atualizadas por Barra

Você pode usar a ferramenta lpdump em system/extras/partition_tools para despejar os metadados em seu dispositivo. Exemplo:

lpdump --slot 0 /dev/block/by-name/system_a
lpdump --slot 1 /dev/block/by-name/system_b

Retrofit para uma atualização

Em dispositivos com o Android 9 e versões anteriores, o cliente OTA no dispositivo não oferece suporte ao mapeamento de partições dinâmicas antes da atualização. Um um conjunto adicional de patches é criado para que o mapeamento possa ser aplicado diretamente às partições físicas atuais.

O OTA generator cria o arquivo super.img final que contém o conteúdo de todas as partições dinâmicas e divide a imagem em várias imagens correspondentes aos tamanhos dos dispositivos de bloco físico correspondente ao sistema, fornecedor e assim por diante. Essas imagens são chamadas super_system.img, super_vendor.img e assim por diante. O cliente OTA aplica essas imagens às partições físicas, em vez do que aplicar as imagens às partições lógicas (dinâmicas).

Como o cliente OTA não sabe mapear partições dinâmicas, todas as etapas pós-instalação são desativadas automaticamente para essas partições. quando o pacote de atualização for gerado. Consulte Como configurar a pós-instalação para mais detalhes.

O fluxo de atualização é o mesmo do Android 9.

Antes da atualização:

ro.boot.dynamic_partitions=
ro.boot.dynamic_partitions_retrofit=

Após a atualização:

ro.boot.dynamic_partitions=true
ro.boot.dynamic_partitions_retrofit=true

Futuras atualizações após a retrofit

Após a atualização da retrofit, o cliente OTA é atualizado para funcionar com partições dinâmicas. As extensões das partições de origem nunca abrangem nas partições físicas de destino.

Fluxo de atualização usando um pacote de atualização regular

  1. Inicialize os metadados da partição super.
    1. Construir novos metadados M de metadados S (metadados de origem). Por exemplo, se os metadados S usarem [system_s, vendor_s, product_s] como bloco dispositivos, os novos metadados M usam [system_t, vendor_t, product_t] como bloco dispositivos. Todos os grupos e partições são descartados em M.
    2. Adicione grupos de destino e partições de acordo com Campo dynamic_partition_metadata na atualização manifesto do aplicativo. O tamanho de cada partição pode ser encontrado em new_partition_info:
    3. Grave M em T de metadados.
    4. Mapear as partições adicionadas no mapeador do dispositivo como graváveis.
  2. Aplique a atualização nos dispositivos de transferência por blocos.
    1. Se necessário, mapeie as partições de origem no mapeador do dispositivo. como somente leitura. Isso é necessário para sideload porque partições de origem não são mapeadas antes da atualização.
    2. Aplique uma atualização completa ou delta a todos os dispositivos de transferência por blocos no na posição desejada.
    3. Ative as partições para executar o script pós-instalação e depois e desconectar as partições.
  3. Desfaça o mapeamento das partições de destino.

Atualizar o fluxo usando um pacote de atualização da Retrofit

Se o pacote de atualização da Retrofit for aplicado a um dispositivo que ativa partições dinâmicas, o cliente OTA aplica a divisão super.img diretamente em dispositivos em bloco. A atualização é semelhante a uma atualização de retrofit. Consulte Fazer o retroajuste de uma atualização para mais detalhes.

Por exemplo, suponha que:

  • O slot A é o ativo.
  • system_a contém os metadados ativos no slot 0.
  • system_a, vendor_a e product_a são usados como dispositivos de bloco.

Quando o cliente OTA recebe um pacote de atualização da Retrofit, ele se aplica super_system.img no system_b físico, super_vendor.img no vendor_b físico e super_product.img no product_b físico. O dispositivo de bloco físico system_b contém o metadados para mapear o system_b lógico, vendor_b e product_b no momento da inicialização.

Gerar pacotes de atualização

OTA incremental

Ao gerar OTAs incrementais para dispositivos de retrofit, as atualizações depender de o build de base definir ou não PRODUCT_USE_DYNAMIC_PARTITIONS e PRODUCT_RETROFIT_DYNAMIC_PARTITIONS.

  • Se o build de base não definir as variáveis, essa será uma atualização de retroajuste. O pacote de atualização contém a divisão super.img e desativa a etapa pós-instalação.
  • Se a compilação de base definir as variáveis, isso será o mesmo que uma atualização típica com partições dinâmicas. O pacote de atualização contém as imagens para partições lógicas (dinâmicas). A a etapa pós-instalação pode ser ativada.

OTA completo

Dois pacotes OTA completos são gerados para dispositivos de retrofit.

  • $(PRODUCT)-ota-retrofit-$(TAG).zip sempre contém dividir super.img e desativar a etapa pós-instalação para atualização de retroajuste.
    • Ele é gerado com um argumento adicional --retrofit_dynamic_partitions para o ota_from_target_files.
    • Ela pode ser aplicada a todos os builds.
  • $(PRODUCT)-ota-$(TAG).zip contém imagens lógicas para atualizações futuras.
    • Aplicar isto somente a builds com partições dinâmicas ativado. Confira abaixo os detalhes sobre como aplicar essa política.

Rejeitar atualizações que não são da Retrofit em builds antigos

Aplicar o pacote OTA completo normal somente aos builds com com partições dinâmicas ativadas. Se o servidor OTA estiver configurado incorretamente e envia esses pacotes para dispositivos com o Android 9 ou mais baixos, os dispositivos não inicializam. O cliente OTA no Android 9 e mais baixos não conseguem diferenciar um pacote OTA de retrofit e um pacote OTA completo normal, para que o cliente não rejeite o pacote completo.

Para evitar que o dispositivo aceite o pacote OTA completo, você pode exigem uma etapa pós-instalação para verificar o dispositivo configuração do Terraform. Exemplo:

device/device_name/dynamic_partitions/check_dynamic_partitions

#!/system/bin/sh
DP_PROPERTY_NAME="ro.boot.dynamic_partitions"
DP_RETROFIT_PROPERTY_NAME="ro.boot.dynamic_partitions_retrofit"

DP_PROPERTY=$(getprop ${DP_PROPERTY_NAME})
DP_RETROFIT_PROPERTY=$(getprop ${DP_RETROFIT_PROPERTY_NAME})

if [ "${DP_PROPERTY}" != "true" ] || [ "${DP_RETROFIT_PROPERTY}" != "true" ] ; then
    echo "Error: applied non-retrofit update on build without dynamic" \
         "partitions."
    echo "${DP_PROPERTY_NAME}=${DP_PROPERTY}"
    echo "${DP_RETROFIT_PROPERTY_NAME}=${DP_RETROFIT_PROPERTY}"
    exit 1
fi

device/device_name/dynamic_partitions/Android.mk

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE:= check_dynamic_partitions
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_CLASS := EXECUTABLES
LOCAL_SRC_FILES := check_dynamic_partitions
LOCAL_PRODUCT_MODULE := true
include $(BUILD_PREBUILT)

device/device_name/device.mk

PRODUCT_PACKAGES += check_dynamic_partitions

# OPTIONAL=false so that the error in check_dynamic_partitions will be
# propagated to OTA client.
AB_OTA_POSTINSTALL_CONFIG += \
    RUN_POSTINSTALL_product=true \
    POSTINSTALL_PATH_product=bin/check_dynamic_partitions \
    FILESYSTEM_TYPE_product=ext4 \
    POSTINSTALL_OPTIONAL_product=false \

Quando o pacote OTA normal é aplicado em um dispositivo sem recursos com partições ativadas, o cliente OTA é executado check_dynamic_partitions como uma etapa pós-instalação; e rejeita a atualização.