Actualización inalámbrica para dispositivos que no son A/B con particiones dinámicas

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

En esta página, se describe cómo los clientes de 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 OTA para las particiones dinámicas se aplica con updater dentro del paquete de actualización.

Actualiza los dispositivos de lanzamiento

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

Genera paquetes de actualización

Los paquetes de actualización OTA se generan con la secuencia de comandos ota_from_target_files, que se encuentra en build/make/tools/releasetools. 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 se deben generar en 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 devuelven una lista de objetos BlockDifference, en la que cada uno describe el parche de actualización que se aplicaría en una partición. Las particiones que devuelven estas dos funciones no se deben modificar manualmente ni verificar en 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()]

Flujo de actualización

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

  • unmap_partition(name)
    • Desasigna la partición si está asignada; de lo contrario, no hagas nada.
    • Devuelve la cadena t si la operación se realiza correctamente o una cadena vacía si falla.
  • map_partition(name)
    • Asigna la partición si aún no se asignó.
    • Devuelve la ruta de acceso absoluta del dispositivo de bloqueo asignado si la operación se realiza correctamente o una cadena vacía si falla.
  • update_dynamic_partitions(op_list)
    • Aplica la lista de operaciones determinada en los metadatos de la partición dinámica y desasigna las particiones si es necesario.
    • Devuelve t si la operación se realiza correctamente o una cadena vacía si falla.

El argumento op_list de 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
    • Desasigna la partición y, luego, cambia su tamaño a size.
  • remove partition_name
    • Desasigna la partición y, luego, quítala.
  • add partition-name group-name
    • Agrega una partición nueva al grupo especificado.
    • Anula la operación si el grupo no existe o si la partición ya existe.
  • move partition-name group-name
    • Mueve la partición al grupo especificado.
    • Se anula si no existe el grupo o la partición.
  • add_group group-name maximum-size
    • Agrega un grupo con el nombre y el tamaño máximo determinados.
    • Se anula si el grupo ya existe.
    • Un valor de 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.
    • Se anula si el grupo no existe.
    • Un valor de 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
    • Quita un grupo.
    • Se anula si hay particiones en el grupo.
  • remove_all_groups
    • Desasigna 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 o borrar particiones, o moverlas fuera del grupo (para que haya suficiente espacio para reducir los grupos)
  2. Reducir los grupos (para que haya suficiente espacio para que crezcan)
  3. Expandir grupos (para tener suficiente espacio para expandir o agregar particiones)
  4. Expandir, agregar 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 las particiones existentes
  2. Agregar grupos
  3. Cómo 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