OTA per dispositivi non A/B con partizioni dinamiche

Android 10 supporta le partizioni dinamiche , un sistema di partizionamento dello spazio utente in grado di creare, ridimensionare e distruggere le partizioni durante gli aggiornamenti over-the-air (OTA).

Questa pagina descrive come i client OTA ridimensionano le partizioni dinamiche durante un aggiornamento per dispositivi non A/B.

Per i dispositivi non A/B, l'aggiornamento OTA per le partizioni dinamiche viene applicato utilizzando il updater all'interno del pacchetto di aggiornamento.

Aggiorna i dispositivi di lancio

Questa sezione si applica ai dispositivi non A/B che vengono avviati con il supporto delle partizioni dinamiche; questi dispositivi si aggiornano da Android 10 a versioni successive.

Genera pacchetti di aggiornamento

I pacchetti di aggiornamento OTA vengono generati dallo script ota_from_target_files , situato in build/make/tools/releasetools . Per impostazione predefinita, lo script genera un pacchetto che aggiorna il system e le partizioni vendor . Se sono presenti partizioni dinamiche aggiuntive, come product , product_services o odm , i relativi aggiornamenti devono essere generati nel codice specifico del dispositivo .

Per generare aggiornamenti, nel modulo Python esteso, implementare FullOTA_GetBlockDifferences() e IncrementalOTA_GetBlockDifferences() . Queste due funzioni restituiscono un elenco di oggetti BlockDifference , ciascuno dei quali descrive la patch di aggiornamento che verrebbe applicata su una partizione. Le partizioni restituite da queste due funzioni non devono essere modificate manualmente o verificate altrove, ad esempio in *_InstallBegin() o *_InstallEnd() .

Esempio di generazione di aggiornamenti:

# 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()]

Flusso di aggiornamento

Dietro le quinte, allo script edify vengono aggiunte le seguenti funzioni:

  • unmap_partition(name)
    • Annulla la mappatura della partizione se mappata, altrimenti non fare nulla.
    • Restituisce la stringa t in caso di successo o una stringa vuota in caso di fallimento.
  • map_partition(name)
    • Mappare la partizione se non è già mappata.
    • Restituisce il percorso assoluto del dispositivo a blocchi mappato in caso di successo o una stringa vuota in caso di fallimento.
  • update_dynamic_partitions(op_list)
    • Applicare l'elenco di operazioni fornito sui metadati della partizione dinamica, annullando la mappatura delle partizioni se necessario.
    • Restituisce t in caso di successo o una stringa vuota in caso di fallimento.

L'argomento op_list di update_dynamic_partitions punta a un file nel pacchetto di aggiornamento. Ogni riga nel file specifica un'operazione. Se un'operazione fallisce, update_dynamic_partitions restituisce immediatamente una stringa vuota. Le operazioni sono:

  • resize partition-name size
    • Annulla la mappatura della partizione, quindi ridimensionala alla size .
  • remove partition_name
    • Annulla la mappatura della partizione, quindi rimuovila.
  • add partition-name group-name
    • Aggiungi una nuova partizione al gruppo specificato.
    • Interrompe se il gruppo non esiste o se la partizione esiste già.
  • move partition-name group-name
    • Sposta la partizione nel gruppo specificato.
    • Interrompe se il gruppo non esiste o la partizione non esiste.
  • add_group group-name maximum-size
    • Aggiungi un gruppo con il nome specificato e la dimensione massima.
    • Interrompere se il gruppo esiste già.
    • Una maximum_size pari a 0 significa che non ci sono limiti di dimensione sulle partizioni nel gruppo. Sono necessari test aggiuntivi per garantire che le partizioni nel gruppo non superino lo spazio disponibile sul dispositivo.
  • resize_group group-name maximum-size
    • Ridimensiona il gruppo alla dimensione massima specificata.
    • Interrompere se il gruppo non esiste.
    • Una maximum_size pari a 0 significa che non ci sono limiti di dimensione sulle partizioni nel gruppo. Sono necessari test aggiuntivi per garantire che le partizioni nel gruppo non superino lo spazio disponibile sul dispositivo.
  • remove_group group-name
    • Rimuovere un gruppo.
    • Interrompe se sono presenti partizioni nel gruppo.
  • remove_all_groups
    • Annulla la mappatura di tutte le partizioni dal mappatore del dispositivo.
    • Rimuovi tutte le partizioni e i gruppi.

OTA incrementale

Gli aggiornamenti OTA incrementali utilizzano la seguente logica:

  1. Riduci partizioni/elimina partizioni/sposta partizioni fuori gruppo (in modo che ci sia spazio sufficiente per ridurre i gruppi)
  2. Riduci i gruppi (in modo che ci sia spazio sufficiente per far crescere i gruppi)
  3. Aumenta i gruppi (in modo da avere abbastanza spazio per espandere/aggiungere partizioni)
  4. Aumenta le partizioni/aggiungi partizioni/sposta le partizioni in un nuovo gruppo

Nel dettaglio, update-script viene generato con questa logica:

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), …)

Il file op_list per update_dynamic_partitions viene generato con questa logica:

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

Gli aggiornamenti OTA completi utilizzano la seguente logica:

  1. Elimina tutti i gruppi e le partizioni esistenti
  2. Aggiungi gruppi
  3. Aggiungi partizioni

Nel dettaglio, update-script viene generato con questa logica:

update_dynamic_partitions(op_list)

for each adding partition:
    block_image_update(map_partition(name), …)

Il file op_list per update_dynamic_partitions viene generato con questa logica:

remove_all_groups
for each adding group:
    add_group
for each adding partition:
    add
for each adding partition:
    resize