OTA per dispositivi non A/B con partizioni dinamiche

Android 10 supporta le partizioni dinamiche, un sistema di partizionamento dello spazio utente che può creare, ridimensionare ed eliminare le partizioni durante gli aggiornamenti OTA (over-the-air).

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

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

Aggiornare i dispositivi di lancio

Questa sezione si applica ai dispositivi non A/B che vengono lanciati con il supporto delle partizioni dinamiche. Questi dispositivi eseguono l'upgrade da Android 10 a release successive.

Genera pacchetti di aggiornamento

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

Per generare gli aggiornamenti, nel modulo Python esteso, implementa FullOTA_GetBlockDifferences() e IncrementalOTA_GetBlockDifferences(). Queste due funzioni restituiscono un elenco di oggetti BlockDifference, ciascuno che descrive la patch di aggiornamento da applicare a 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 un aggiornamento:

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

Aggiorna flusso

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

  • unmap_partition(name)
    • Se la partizione è mappata, annulla la mappatura, altrimenti non fare nulla.
    • Restituisce la stringa t in caso di esito positivo o una stringa vuota in caso di esito negativo.
  • map_partition(name)
    • Mappa la partizione se non è già mappata.
    • Restituisce il percorso assoluto del dispositivo di blocco mappato in caso di esito positivo o una stringa vuota in caso di errore.
  • update_dynamic_partitions(op_list)
    • Applica l'elenco di operazioni specificato ai metadati delle partizioni dinamiche, se necessario annulla la mappatura delle partizioni.
    • Restituisce t in caso di esito positivo o una stringa vuota in caso di esito negativo.

L'argomento op_list per update_dynamic_partitions fa riferimento a un file nel pacchetto di aggiornamento. Ogni riga del file specifica un'operazione. Se un'operazione non va a buon fine, update_dynamic_partitions restituisce immediatamente una stringa vuota. Le operazioni sono:

  • resize partition-name size
    • Annulla la mappatura della partizione, quindi ridimensionala in size.
  • remove partition_name
    • Annullare la mappatura della partizione, quindi rimuoverla.
  • add partition-name group-name
    • Aggiungi una nuova partizione al gruppo specificato.
    • Interrompi se il gruppo non esiste o se la partizione esiste già.
  • move partition-name group-name
    • Sposta la partizione nel gruppo specificato.
    • Interrompi se il gruppo o la partizione non esistono.
  • add_group group-name maximum-size
    • Aggiungi un gruppo con il nome e le dimensioni massime specificati.
    • Interrompi se il gruppo esiste già.
    • Un valore maximum_size pari a 0 indica che non esistono limiti di dimensione per le partizioni nel gruppo. Sono necessari test aggiuntivi per verificare che le partizioni del gruppo non superino lo spazio disponibile sul dispositivo.
  • resize_group group-name maximum-size
    • Ridimensiona il gruppo alla dimensione massima specificata.
    • Interrompi se il gruppo non esiste.
    • Un valore maximum_size pari a 0 indica che non esistono limiti di dimensione per le partizioni nel gruppo. Sono necessari ulteriori test per garantire che le partizioni nel gruppo non superino lo spazio disponibile sul dispositivo.
  • remove_group group-name
    • Rimuovere un gruppo.
    • Interrompi se ci sono partizioni nel gruppo.
  • remove_all_groups
    • Annullare 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 le partizioni/elimina le partizioni/rimuovi le partizioni dal gruppo (in modo che ci sia spazio sufficiente per ridurre i gruppi)
  2. Riduci i gruppi (in modo che ci sia spazio sufficiente per espanderli)
  3. Espandere i gruppi (in modo da avere spazio sufficiente per espandere/aggiungere le partizioni)
  4. Far crescere le partizioni/aggiungere partizioni/spostare partizioni in un nuovo gruppo

In 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 completa

Gli aggiornamenti OTA completi utilizzano la seguente logica:

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

In 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