OTA pour les appareils non A/B avec partitions dynamiques

Android 10 est compatible avec les partitions dynamiques, un système de partitionnement de l'espace utilisateur qui peut créer, redimensionner et détruire des partitions lors des mises à jour OTA (Over-the-Air).

Cette page explique comment les clients OTA redimensionnent les partitions dynamiques lors d'une mise à jour pour les appareils autres que A/B.

Pour les appareils autres qu'A/B, la mise à jour OTA pour les partitions dynamiques est appliquée à l'aide de updater dans le package de mise à jour.

Modifier les appareils de lancement

Cette section concerne les appareils non A/B qui sont compatibles avec les partitions dynamiques et qui sont mis à niveau depuis Android 10 vers une version ultérieure.

Générer des packages de mise à jour

Les packages de mise à jour OTA sont générés par le script ota_from_target_files, situé sous build/make/tools/releasetools. Par défaut, le script génère un package qui met à jour les partitions system et vendor. S'il existe des partitions dynamiques supplémentaires, telles que product, product_services ou odm, leurs mises à jour doivent être générées dans le code spécifique à l'appareil.

Pour générer des mises à jour, dans le module Python étendu, implémentez FullOTA_GetBlockDifferences() et IncrementalOTA_GetBlockDifferences(). Ces deux fonctions renvoient une liste d'objets BlockDifference, chacun décrivant le correctif de mise à jour qui serait appliqué à une partition. Les partitions renvoyées par ces deux fonctions ne doivent pas être modifiées manuellement ni validées ailleurs, par exemple dans *_InstallBegin() ou *_InstallEnd().

Exemple de génération de mises à jour:

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

Mettre à jour le flux

En coulisses, les fonctions suivantes sont ajoutées au script edify:

  • unmap_partition(name)
    • Désassociez la partition si elle est mappée, sinon ne faites rien.
    • Renvoie la chaîne t en cas de réussite ou une chaîne vide en cas d'échec.
  • map_partition(name)
    • Mappez la partition si elle n'est pas déjà mappée.
    • Renvoie le chemin d'accès absolu de l'appareil de bloc mappé en cas de réussite, ou une chaîne vide en cas d'échec.
  • update_dynamic_partitions(op_list)
    • Appliquez la liste d'opérations donnée aux métadonnées de partition dynamique, en désassociant les partitions si nécessaire.
    • Renvoyez t en cas de réussite ou une chaîne vide en cas d'échec.

L'argument op_list de update_dynamic_partitions pointe vers un fichier du package de mise à jour. Chaque ligne du fichier spécifie une opération. Si une opération échoue, update_dynamic_partitions renvoie immédiatement une chaîne vide. Les opérations sont les suivantes:

  • resize partition-name size
    • Désassociez la partition, puis redimensionnez-la en size.
  • remove partition_name
    • Désassociez la partition, puis supprimez-la.
  • add partition-name group-name
    • Ajoutez une partition au groupe spécifié.
    • Arrêtez l'opération si le groupe n'existe pas ou si la partition existe déjà.
  • move partition-name group-name
    • Déplacez la partition vers le groupe spécifié.
    • Arrêtez l'opération si le groupe ou la partition n'existent pas.
  • add_group group-name maximum-size
    • Ajoutez un groupe avec le nom et la taille maximale donnés.
    • Arrêtez l'opération si le groupe existe déjà.
    • Une valeur maximum_size de 0 signifie qu'il n'y a pas de limite de taille sur les partitions du groupe. Des tests supplémentaires sont requis pour vous assurer que les partitions du groupe ne dépassent pas l'espace disponible sur l'appareil.
  • resize_group group-name maximum-size
    • Redimensionnez le groupe à la taille maximale donnée.
    • Annulez si le groupe n'existe pas.
    • Une valeur maximum_size de 0 signifie qu'il n'y a aucune limite de taille pour les partitions du groupe. Des tests supplémentaires sont nécessaires pour s'assurer que les partitions du groupe ne dépassent pas l'espace disponible sur l'appareil.
  • remove_group group-name
    • supprimer un groupe ;
    • Annulez si le groupe contient des partitions.
  • remove_all_groups
    • Annulez le mappage de toutes les partitions dans le mappeur d'appareils.
    • Supprimez toutes les partitions et tous les groupes.

OTA incrémental

Les mises à jour OTA incrémentielles utilisent la logique suivante:

  1. Réduire les partitions/supprimer des partitions/déplacer des partitions hors du groupe (pour qu'il y ait suffisamment d'espace pour réduire les groupes)
  2. Réduire les groupes (pour qu'il y ait suffisamment d'espace pour les développer)
  3. Étendre les groupes (afin que nous ayons suffisamment d'espace pour étendre/ajouter des partitions)
  4. Augmenter la taille des partitions/Ajouter des partitions/Déplacer des partitions vers un nouveau groupe

Plus précisément, update-script est généré avec la logique suivante:

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

Le fichier op_list pour update_dynamic_partitions est généré avec cette logique:

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 complète

Les mises à jour OTA complètes utilisent la logique suivante:

  1. Supprimer tous les groupes et partitions existants
  2. Ajouter des groupes
  3. Ajouter des partitions

Plus précisément, update-script est généré avec la logique suivante:

update_dynamic_partitions(op_list)

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

Le fichier op_list pour update_dynamic_partitions est généré avec cette logique:

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