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 não A/B.
Para 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 iniciados com suporte a partições dinâmicas; esses dispositivos são atualizados do Android 10 para versões superiores.
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 do system
e vendor
. Se houver partições dinâmicas adicionais, como product
, product_services
ou odm
, suas atualizações deverã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 ou 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()]
Fluxo de atualização
Nos bastidores, as seguintes funções são adicionadas ao script edify:
-
unmap_partition(name)
- Remova o mapeamento da partição se estiver mapeada, caso contrário não faça nada.
- Retorna a string
t
em caso de sucesso ou uma string vazia em caso de falha.
-
map_partition(name)
- Mapeie a partição se 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)
- Aplique a lista de operações fornecida nos metadados da partição dinâmica, desmapeando as partições, se necessário.
- Retorna
t
em 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 do arquivo especifica uma operação. Se alguma operação falhar, update_dynamic_partitions
retornará imediatamente uma string vazia. As operações são:
-
resize partition-name size
- Remova o mapeamento da partição e redimensione-a para size .
-
remove partition_name
- Remova o mapeamento da partição e remova-a.
-
add partition-name group-name
- Adicione uma nova partição ao grupo especificado.
- Aborte 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.
- Aborte se o grupo não existir ou a partição não existir.
-
add_group group-name maximum-size
- Adicione um grupo com o nome fornecido e tamanho máximo.
- Aborte se o grupo já existir.
- Um maximum_size igual a 0 significa que não há limites de tamanho nas partições do grupo. São necessários testes adicionais para garantir que as partições do 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 fornecido.
- Aborte se o grupo não existir.
- Um maximum_size igual a 0 significa que não há limites de tamanho nas partições do grupo. São necessários testes adicionais para garantir que as partições do grupo não excedam o espaço disponível no dispositivo.
-
remove_group group-name
- Remover um grupo.
- Aborte se houver partições no grupo.
-
remove_all_groups
- Remova o mapeamento de todas as partições do mapeador de dispositivos.
- Remova todas as partições e grupos.
OTA incremental
As atualizações incrementais OTA usam a seguinte lógica:
- Reduzir partições/excluir partições/mover partições para fora do grupo (para que haja espaço suficiente para reduzir grupos)
- Diminuir grupos (para que haja espaço suficiente para aumentar os grupos)
- Aumentar grupos (para que tenhamos espaço suficiente para aumentar/adicionar partições)
- Aumentar partições/adicionar partições/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 group
OTA completo
As atualizações completas do OTA usam a seguinte lógica:
- Exclua todos os grupos e partições existentes
- 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