O Android 10 oferece suporte a partições dinâmicas, um sistema de particionamento no espaço do usuário 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 para dispositivos A/B lançados sem suporte a partições dinâmicas e como os clientes OTA fazem upgrade para o Android 10.
Contexto
Durante uma atualização de um dispositivo A/B para oferecer suporte a partições dinâmicas, a tabela de partições GUID (GPT) no dispositivo é preservada. Portanto, não há uma partição super
no dispositivo. Os metadados são armazenados em system_a
e system_b
, mas isso pode ser personalizado mudando BOARD_SUPER_PARTITION_METADATA_DEVICE
.
Em cada dispositivo de bloco, há dois slots de metadados. Apenas um slot de metadados em cada dispositivo de bloco é usado. Por exemplo, o metadado 0 em system_a
e o metadado 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 mais informações sobre configurações do sistema de build, consulte Fazer upgrade de dispositivos.
Para mais informações sobre como as partições pertencem a grupos de atualização, consulte Mudanças na configuração da placa para novos dispositivos.
Um exemplo de metadados em um dispositivo é:
- Dispositivo de bloco 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 por Foo
- Partição lógica (dinâmica)
- Grupo
bar_a
- Partição lógica (dinâmica)
vendor_a
- Partição lógica (dinâmica)
product_a
- Outras partições atualizadas pelo Bar
- Partição lógica (dinâmica)
- Grupo
- Metadados 1 (não usado)
- Metadados 0
- Dispositivo de bloco 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 por Foo
- Partição lógica (dinâmica)
- Grupo bar_b
- Partição lógica (dinâmica)
vendor_b
- Partição lógica (dinâmica)
product_b
- Outras partições atualizadas pelo Bar
- Partição lógica (dinâmica)
- Grupo foo_b
Use a ferramenta lpdump
em
system/extras/partition_tools
para despejar os metadados no
dispositivo. Exemplo:
lpdump --slot 0 /dev/block/by-name/system_a
lpdump --slot 1 /dev/block/by-name/system_b
Adaptar uma atualização
Em dispositivos com Android 9 e versões anteriores, o cliente OTA no dispositivo não é compatível com o 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 atuais.
O gerador de OTA 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 que correspondem aos tamanhos dos dispositivos de bloco físico
correspondentes ao sistema, ao fornecedor e assim por diante. Essas imagens são chamadas de
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 desativadas automaticamente para essas partições quando o pacote de atualização é gerado. Consulte Como configurar após a 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
Atualizações futuras após a adaptação
Após a atualização do retrofit, o cliente OTA é atualizado para funcionar com partições dinâmicas. Os intervalos das partições de origem nunca abrangem partições físicas de destino.
Fluxo de atualização usando um pacote de atualização regular
- Inicialize os metadados de partição
super
.-
Construa novos metadados M com base nos metadados S (origem).
Por exemplo, se os metadados S usarem [
system_s
,vendor_s
,product_s
] como dispositivos de bloco, 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 no M. -
Adicione grupos e partições de destino de acordo com o
campo
dynamic_partition_metadata
no manifesto de atualização. O tamanho de cada partição pode ser encontrado emnew_partition_info
. - Escreva M para Metadata T.
- Mapeie as partições adicionadas no mapeador de dispositivos como graváveis.
-
Construa novos metadados M com base nos metadados S (origem).
Por exemplo, se os metadados S usarem [
- Aplique a atualização nos dispositivos bloqueados.
- 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.
- Aplique uma atualização completa ou delta a todos os dispositivos de bloco no slot de destino.
- Monte as partições para executar o script pós-instalação e desmonte-as.
- Remova o mapeamento das partições de destino.
Fluxo de atualização usando um pacote de atualização do Retrofit
Se o pacote de atualização de adaptação for aplicado em um dispositivo que já
permite partições dinâmicas, o cliente OTA vai aplicar o arquivo
super.img
dividido diretamente em dispositivos de bloco. O fluxo de atualização é semelhante a uma atualização de adaptação. Consulte
Adaptar uma atualização
para mais detalhes.
Por exemplo, suponha que:
- O slot A é o slot ativo.
-
system_a
contém os metadados ativos no slot 0. -
system_a
,vendor_a
eproduct_a
são usados como dispositivos de bloqueio.
Quando o cliente OTA recebe um pacote de atualização de adaptação, ele aplica
super_system.img
em system_b
físico,
super_vendor.img
em vendor_b
físico e
super_product.img
em product_b
físico.
O dispositivo de bloco físico system_b
contém os metadados corretos para mapear os system_b
, vendor_b
e product_b
lógicos na inicialização.
Gerar pacotes de atualização
OTA incremental
Ao gerar OTAs incrementais para dispositivos adaptados, as atualizações
dependem de a build de base definir
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 adaptação. O pacote de atualização contém o arquivo
super.img
dividido e desativa a etapa pós-instalação. - Se o build 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 etapa pós-instalação pode ser ativada.
OTA completa
Dois pacotes OTA completos são gerados para dispositivos adaptados.
-
$(PRODUCT)-ota-retrofit-$(TAG).zip
sempre contém a divisãosuper.img
e desativa a etapa pós-instalação para atualização de adaptação.-
Ele é gerado com um argumento adicional
--retrofit_dynamic_partitions
para o scriptota_from_target_files
. - Ele pode ser aplicado a todas as criações.
-
Ele é gerado com um argumento adicional
-
$(PRODUCT)-ota-$(TAG).zip
contém imagens lógicas para atualizações futuras.- Aplique isso somente a builds com partições dinâmicas ativadas. Confira abaixo os detalhes sobre como fazer isso.
Rejeitar atualização sem adaptação em builds antigos
Aplique o pacote OTA completo regular apenas a builds com partições dinâmicas ativadas. Se o servidor OTA estiver configurado de maneira incorreta e enviar esses pacotes para dispositivos com o Android 9 ou versões anteriores, os dispositivos não vão inicializar. O cliente OTA no Android 9 e versões anteriores não consegue diferenciar um pacote OTA adaptado de um pacote OTA completo normal. Por isso, o cliente não rejeita 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 atual do dispositivo. 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 ativadas, o cliente OTA executa
check_dynamic_partitions
como uma etapa pós-instalação e
rejeita a atualização.