OTA para dispositivos que no sean A/B con particiones dinámicas

Android 10 admite particiones dinámicas , un sistema de partición del espacio de usuario que puede crear, cambiar el tamaño y destruir particiones durante las actualizaciones inalámbricas (OTA).

Esta página describe cómo los clientes OTA cambian el tamaño de las particiones dinámicas durante una actualización para dispositivos que no son A/B.

Para dispositivos que no son A/B, la actualización OTA para particiones dinámicas se aplica utilizando el updater dentro del paquete de actualización.

Actualizar dispositivos de lanzamiento

Esta sección se aplica a dispositivos que no son A/B y que se inician con soporte para particiones dinámicas; Estos dispositivos se actualizan desde Android 10 a versiones superiores.

Generar paquetes de actualización

Los paquetes de actualización OTA se generan mediante el script ota_from_target_files , ubicado en build/make/tools/releasetools . De forma predeterminada, el script genera un paquete que actualiza el system y las particiones vendor . Si hay particiones dinámicas adicionales, como product , product_services u odm , sus actualizaciones deben generarse en código específico del dispositivo .

Para generar actualizaciones, en el módulo extendido de Python, implemente FullOTA_GetBlockDifferences() e IncrementalOTA_GetBlockDifferences() . Estas dos funciones devuelven una lista de objetos BlockDifference , cada uno de los cuales describe el parche de actualización que se aplicaría en una partición. Las particiones devueltas por estas dos funciones no deben modificarse manualmente ni verificarse en otro lugar, por ejemplo en *_InstallBegin() o *_InstallEnd() .

Ejemplo de generación de actualizaciones:

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

Flujo de actualización

Detrás de escena, se agregan las siguientes funciones al script de edificar:

  • unmap_partition(name)
    • Desasignar la partición si está asignada; de lo contrario, no haga nada.
    • Devuelve la cadena t en caso de éxito, o una cadena vacía en caso de error.
  • map_partition(name)
    • Asigne la partición si aún no está asignada.
    • Devuelve la ruta absoluta del dispositivo de bloque asignado en caso de éxito, o una cadena vacía en caso de error.
  • update_dynamic_partitions(op_list)
    • Aplique la lista de operaciones proporcionada en los metadatos de la partición dinámica, desasignando las particiones si es necesario.
    • Devuelve t en caso de éxito, o una cadena vacía en caso de error.

El argumento op_list para update_dynamic_partitions apunta a un archivo en el paquete de actualización. Cada línea del archivo especifica una operación. Si alguna operación falla, update_dynamic_partitions devuelve inmediatamente una cadena vacía. Las operaciones son:

  • resize partition-name size
    • Desasignar la partición y luego cambiar su size .
  • remove partition_name
    • Desasignar la partición y luego eliminarla.
  • add partition-name group-name
    • Agregue una nueva partición al grupo especificado.
    • Cancele si el grupo no existe o si la partición ya existe.
  • move partition-name group-name
    • Mueva la partición al grupo especificado.
    • Cancele si el grupo no existe o la partición no existe.
  • add_group group-name maximum-size
    • Agregue un grupo con el nombre de pila y el tamaño máximo.
    • Cancelar si el grupo ya existe.
    • Un maximum_size de 0 significa que no hay límites de tamaño en las particiones del grupo. Se requieren pruebas adicionales para garantizar que las particiones del grupo no excedan el espacio disponible en el dispositivo.
  • resize_group group-name maximum-size
    • Cambie el tamaño del grupo al tamaño máximo dado.
    • Cancelar si el grupo no existe.
    • Un maximum_size de 0 significa que no hay límites de tamaño en las particiones del grupo. Se requieren pruebas adicionales para garantizar que las particiones del grupo no excedan el espacio disponible en el dispositivo.
  • remove_group group-name
    • Eliminar un grupo.
    • Cancele si hay particiones en el grupo.
  • remove_all_groups
    • Desasignar todas las particiones del asignador de dispositivos.
    • Elimine todas las particiones y grupos.

OTA incremental

Las actualizaciones OTA incrementales utilizan la siguiente lógica:

  1. Reducir particiones/eliminar particiones/sacar particiones del grupo (para que haya suficiente espacio para reducir los grupos)
  2. Reducir grupos (para que haya suficiente espacio para hacer crecer grupos)
  3. Crecer grupos (para que tengamos suficiente espacio para crecer/agregar particiones)
  4. Hacer crecer particiones/agregar particiones/mover particiones a un nuevo grupo

En detalle, update-script se genera con 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), …)

El archivo op_list para update_dynamic_partitions se genera con 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 completa

Las actualizaciones OTA completas utilizan la siguiente lógica:

  1. Eliminar todos los grupos y particiones existentes
  2. Agregar grupos
  3. Agregar particiones

En detalle, update-script se genera con esta lógica:

update_dynamic_partitions(op_list)

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

El archivo op_list para update_dynamic_partitions se genera con esta lógica:

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