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

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

En esta página, se 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.

En el caso de los dispositivos que no son A/B, la actualización inalámbrica para particiones dinámicas se aplica con updater dentro del paquete de actualización.

Actualizar dispositivos de lanzamiento

Esta sección se aplica a dispositivos que no son A/B que se inician con compatibilidad con particiones dinámicas. Estos dispositivos se actualizan de Android 10 a versiones posteriores.

Genera paquetes de actualización

La secuencia de comandos ota_from_target_files, que se encuentra en build/make/tools/releasetools, genera los paquetes de actualización OTA. De forma predeterminada, la secuencia de comandos genera un paquete que actualiza las particiones system y vendor. Si hay particiones dinámicas adicionales, como product, product_services o odm, sus actualizaciones deben generarse en el código específico del dispositivo.

Para generar actualizaciones, en el módulo de Python extendido, implementa FullOTA_GetBlockDifferences() y IncrementalOTA_GetBlockDifferences(). Estas dos funciones muestran 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 que muestran estas dos funciones no se deben modificar manualmente ni verificar en ningún otro lugar, por ejemplo, en *_InstallBegin() o *_InstallEnd().

Ejemplo de generación de actualización:

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

Actualiza el flujo

En segundo plano, se agregan las siguientes funciones a la secuencia de comandos de edify:

  • unmap_partition(name)
    • Si la partición está asignada, anula la asignación. De lo contrario, no hagas nada.
    • Muestra la string t si la operación es exitosa o una string vacía si se produce un error.
  • map_partition(name)
    • Asigna la partición si aún no lo hiciste.
    • Muestra la ruta de acceso absoluta del dispositivo de almacenamiento en bloque asignado si se realiza correctamente o una cadena vacía si se produce un error.
  • update_dynamic_partitions(op_list)
    • Aplica la lista de operaciones proporcionada a los metadatos de particiones dinámicas y, si es necesario, anula la asignación de particiones.
    • Muestra t en caso de éxito o una string 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 falla alguna operación, update_dynamic_partitions muestra de inmediato una cadena vacía. Las operaciones son las siguientes:

  • resize partition-name size
    • Desvincula la partición y, luego, cámbiale el tamaño a size.
  • remove partition_name
    • Desvincula la partición y, luego, quítala.
  • add partition-name group-name
    • Agrega una partición nueva al grupo especificado.
    • Aborta si el grupo no existe o si la partición ya existe.
  • move partition-name group-name
    • Mueve la partición al grupo especificado.
    • Aborta si el grupo o la partición no existen.
  • add_group group-name maximum-size
    • Agrega un grupo con el nombre y el tamaño máximo especificados.
    • Aborta 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
    • Cambia el tamaño del grupo al tamaño máximo determinado.
    • Aborta 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 asegurarnos de que las particiones del grupo no superen el espacio disponible en el dispositivo.
  • remove_group group-name
    • Quitar un grupo
    • Aborta si hay particiones en el grupo.
  • remove_all_groups
    • Desvincula todas las particiones del asignador de dispositivos.
    • Quita todas las particiones y los grupos.

OTA incremental

Las actualizaciones OTA incrementales usan la siguiente lógica:

  1. Reducir particiones/borrar particiones/mover particiones fuera del grupo (de modo que haya suficiente espacio para reducir los grupos)
  2. Reducir los grupos (para que haya suficiente espacio para aumentarlos)
  3. Expandir grupos (para que tengamos suficiente espacio para expandir o agregar particiones)
  4. Aumentar particiones, agregar particiones o mover particiones a un grupo nuevo

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 usan la siguiente lógica:

  1. Borra 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