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

O Android 10 oferece suporte a partições dinâmicas , um sistema de particionamento de espaço do usuário que pode criar, redimensionar e destruir partições durante atualizações over-the-air (OTA).

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

Fundo

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

Em cada um dos dispositivos de bloco, existem dois slots de metadados. Apenas um slot de metadados em cada dispositivo de bloco é usado. Por exemplo, os metadados 0 em system_a e os metadados 1 em system_b correspondem a partições nos slots A e B, respectivamente. Em tempo de execução, não importa qual slot está sendo atualizado.

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

Para obter mais informações sobre configurações do sistema de compilação , consulte Atualizando dispositivos .

Para obter mais informações sobre como as partições pertencem a grupos de atualização , consulte Alterações na configuração da placa para novos dispositivos.

Um exemplo de metadados em um dispositivo é:

  • system_a de dispositivo de bloco físico_a
    • Metadados 0
      • Grupo foo_a
        • system_a de partição lógica (dinâmica)_a
        • Partição lógica (dinâmica) product_services_a
        • Outras partições atualizadas por Foo
      • Grupo bar_a
        • vendor_a de partição lógica (dinâmica)_a
        • product_a de partição lógica (dinâmica)_a
        • Outras partições atualizadas pelo Bar
    • Metadados 1 (não usado)
  • system_b de dispositivo de bloco físico_b
    • Metadados 0 (não usado)
    • Metadados 1
      • Grupo foo_b
        • system_b de partição lógica (dinâmica)_b
        • Partição lógica (dinâmica) product_services_b
        • Outras partições atualizadas por Foo
      • Barra de grupo_b
        • vendor_b de partição lógica (dinâmica)_b
        • product_b de partição lógica (dinâmica)_b
        • Outras partições atualizadas pelo Bar

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

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

Retrofit uma atualização

Em dispositivos com 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 conjunto adicional de patches é criado para que o mapeamento possa ser aplicado diretamente às partições físicas existentes.

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

Como o cliente OTA não sabe como mapear partições dinâmicas, todas as etapas pós-instalação são desabilitadas automaticamente para essas partições quando o pacote de atualização é gerado. Consulte Configurando a pós-instalação para obter 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

Atualizações futuras após retrofit

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

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

  1. Inicialize os metadados super .
    1. Construa novos metadados M a partir de Metadados S (metadados de origem). Por exemplo, se os metadados S usarem [ system_s , vendor_s , product_s ] como dispositivos de bloco, então os novos metadados M usarão [ system_t , vendor_t , product_t ] como dispositivos de bloco. Todos os grupos e partições são descartados em M.
    2. Adicione grupos de destino e partições de acordo com o campo dynamic_partition_metadata no manifesto de atualização. O tamanho de cada partição pode ser encontrado em new_partition_info .
    3. Escreva M nos metadados T.
    4. Mapeie as partições adicionadas no mapeador de dispositivos como graváveis.
  2. Aplique a atualização nos dispositivos de bloco.
    1. Se necessário, mapeie as partições de origem no mapeador de dispositivos como somente leitura. Isso é necessário para o sideload porque as 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 bloco no slot de destino.
    3. Monte as partições para executar o script pós-instalação e desmonte as partições.
  3. Remova o mapeamento das partições de destino.

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

Se o pacote de atualização de retroajuste for aplicado em um dispositivo que já permite partições dinâmicas, o cliente OTA aplica o arquivo super.img dividido diretamente em dispositivos de bloco. O fluxo de atualização é semelhante a uma atualização de retrofit. Consulte Retrofit de uma atualização para obter detalhes.

Por exemplo, suponha o seguinte:

  • O slot A é o slot 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 de retroajuste, ele aplica super_system.img no físico system_b , super_vendor.img no físico vendor_b e super_product.img no físico product_b . O dispositivo de bloco físico system_b contém os metadados corretos para mapear os sistemas lógicos system_b , vendor_b e product_b no momento da inicialização.

Gerar pacotes de atualização

OTA incremental

Ao gerar OTAs incrementais para dispositivos de retroajuste, as atualizações dependem de a construção base definir ou não PRODUCT_USE_DYNAMIC_PARTITIONS e PRODUCT_RETROFIT_DYNAMIC_PARTITIONS .

  • Se a construção base não definir as variáveis, esta é uma atualização de retrofit. O pacote de atualização contém o arquivo super.img dividido e desativa a etapa pós-instalação.
  • Se a construção 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 etapa de pós-instalação pode ser habilitada.

OTA completo

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

  • $(PRODUCT)-ota-retrofit-$(TAG).zip sempre contém super.img dividido e desativa a etapa pós-instalação para atualização de atualização.
    • É gerado com um argumento adicional --retrofit_dynamic_partitions para o script ota_from_target_files .
    • Pode ser aplicado a todas as construções.
  • $(PRODUCT)-ota-$(TAG).zip contém imagens lógicas para atualizações futuras.
    • Aplique isto apenas a compilações com partições dinâmicas habilitadas. Veja detalhes abaixo sobre como fazer cumprir isso.

Rejeitar atualização não retrofit em compilações antigas

Aplique o pacote OTA completo regular apenas a compilações com partições dinâmicas habilitadas. Se o servidor OTA estiver configurado incorretamente e enviar esses pacotes para dispositivos que executam o Android 9 ou inferior, os dispositivos não conseguirão inicializar. O cliente OTA no Android 9 e versões anteriores não consegue distinguir entre um pacote OTA atualizado e um pacote OTA completo normal, portanto, o cliente não rejeitará o pacote completo.

Para evitar que o dispositivo aceite o pacote OTA completo, você pode exigir uma etapa pós-instalação para verificar a configuração existente do dispositivo. Por 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 regular é aplicado em um dispositivo sem partições dinâmicas habilitadas, o cliente OTA executa check_dynamic_partitions como uma etapa pós-instalação e rejeita a atualização.