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 não A/B.
Em dispositivos não A/B, a atualização OTA para partições dinâmicas é aplicada
usando o updater dentro do pacote de atualização.
Atualizar dispositivos de lançamento
Esta seção se aplica a dispositivos não A/B que são lançados com suporte a partições dinâmicas e que são atualizados do Android 10 para versões mais recentes.
Gerar pacotes de atualização
Os pacotes de atualização OTA são gerados pelo script
ota_from_target_files, localizado em
build/make/tools/releasetools. Por padrão, o script
gera um pacote que atualiza as partições system e
vendor. Se houver outras partições dinâmicas, como product, product_services ou odm, as atualizações delas precisarão ser geradas em código específico do dispositivo.
Para gerar atualizações, no módulo Python estendido, implemente
FullOTA_GetBlockDifferences() e
IncrementalOTA_GetBlockDifferences(). Essas duas funções retornam uma lista de objetos BlockDifference, cada um descrevendo o patch de atualização que seria aplicado em uma partição. As partições retornadas por essas duas funções não devem ser modificadas manualmente nem verificadas em outro lugar, por exemplo, em *_InstallBegin() ou *_InstallEnd().
Exemplo de geração de atualização:
# device/yoyodyne/tardis/releasetools.py import os from common import BlockDifference, EmptyImage, GetUserImage # The joined list of user image partitions of source and target builds. # - Items should be added to the list if new dynamic partitions are added. # - Items should not be removed from the list even if dynamic partitions are # deleted. When generating an incremental OTA package, this script needs to # know that an image is present in source build but not in target build. USERIMAGE_PARTITIONS = [ "product", "odm", ] def GetUserImages(input_tmp, input_zip): return {partition: GetUserImage(partition, input_tmp, input_zip) for partition in USERIMAGE_PARTITIONS if os.path.exists(os.path.join(input_tmp, "IMAGES", partition + ".img"))} def FullOTA_GetBlockDifferences(info): images = GetUserImages(info.input_tmp, info.input_zip) return [BlockDifference(partition, image) for partition, image in images.items()] def IncrementalOTA_GetBlockDifferences(info): source_images = GetUserImages(info.source_tmp, info.source_zip) target_images = GetUserImages(info.target_tmp, info.target_zip) # Use EmptyImage() as a placeholder for partitions that will be deleted. for partition in source_images: target_images.setdefault(partition, EmptyImage()) # Use source_images.get() because new partitions are not in source_images. return [BlockDifference(partition, target_image, source_images.get(partition)) for partition, target_image in target_images.items()]
Atualizar fluxo
Nos bastidores, as seguintes funções são adicionadas ao script edify:
unmap_partition(name)- Desvincule a partição se ela estiver vinculada. Caso contrário, não faça nada.
- Retorne a string
tem caso de sucesso ou uma string vazia em caso de falha.
map_partition(name)- Mapeie a partição, se ela ainda não estiver mapeada.
- Retorna o caminho absoluto do dispositivo de bloco mapeado em caso de sucesso ou uma string vazia em caso de falha.
update_dynamic_partitions(op_list)- Aplica a lista de operações especificada aos metadados de partição dinâmica, removendo o mapeamento das partições, se necessário.
-
Retorne
tem caso de sucesso ou uma string vazia em caso de falha.
O argumento op_list para
update_dynamic_partitions aponta para um arquivo no
pacote de atualização. Cada linha no arquivo especifica uma operação. Se alguma operação falhar, update_dynamic_partitions vai retornar imediatamente uma string vazia. As operações são:
resize partition-name size- Desvincule a partição e redimensione-a para size.
remove partition_name- Desvincule e remova a partição.
add partition-name group-name- Adiciona uma nova partição ao grupo especificado.
- Abortar se o grupo não existir ou se a partição já existir.
move partition-name group-name- Mova a partição para o grupo especificado.
- Interrompa se o grupo ou a partição não existir.
-
add_group group-name maximum-size- Adiciona um grupo com o nome e o tamanho máximo especificados.
- Interrompe se o grupo já existir.
- Um maximum_size de 0 significa que não há limites de tamanho para partições no grupo. É necessário fazer mais testes para garantir que as partições no grupo não excedam o espaço disponível no dispositivo.
-
resize_group group-name maximum-size- Redimensione o grupo para o tamanho máximo especificado.
- Abortar se o grupo não existir.
- Um maximum_size de 0 significa que não há limites de tamanho para partições no grupo. É necessário fazer mais testes para garantir que as partições no grupo não excedam o espaço disponível no dispositivo.
remove_group group-name- Remover um grupo.
- Interrompa se houver partições no grupo.
remove_all_groups- Desvincule todas as partições do mapeador de dispositivos.
- Remova todas as partições e grupos.
OTA incremental
As atualizações OTA incrementais usam a seguinte lógica:
- Reduzir/excluir/mover partições para fora do grupo (para que haja espaço suficiente para reduzir os grupos)
- Reduza os grupos para que haja espaço suficiente para eles crescerem.
- Aumentar os grupos para que tenhamos espaço suficiente para aumentar/adicionar partições.
- Aumentar/adicionar/mover partições para um novo grupo
Em detalhes, update-script é gerado com esta lógica:
for each shrinking partition:
block_image_update(map_partition(name), …)
update_dynamic_partitions(op_list)
for each growing / adding partition:
block_image_update(map_partition(name), …)
O arquivo op_list para
update_dynamic_partitions é gerado com esta
lógica:
for each deleting partition:
remove
for each partition that changes groups:
move to "default"
for each shrinking partition:
resize
for each shrinking / removing group:
resize_group / remove_group
for each growing / adding group:
resize_group / add_group
for each adding partition:
add
for each growing / adding partition:
resize
for each partition that changes groups:
move to target groupOTA completa
As atualizações OTA completas usam a seguinte lógica:
- Excluir todos os grupos e partições atuais
- Adicionar grupos
- Adicionar partições
Em detalhes, update-script é gerado com esta lógica:
update_dynamic_partitions(op_list)
for each adding partition:
block_image_update(map_partition(name), …)
O arquivo op_list para
update_dynamic_partitions é gerado com esta
lógica:
remove_all_groups
for each adding group:
add_group
for each adding partition:
add
for each adding partition:
resize