OTA para dispositivos no 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 mediante el updater dentro del paquete de actualización.

Actualizar dispositivos de lanzamiento

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

Generar paquetes de actualización

Los paquetes de actualización OTA son generados por el script ota_from_target_files , ubicado en build/make/tools/releasetools . De forma predeterminada, el script genera un paquete que actualiza las particiones del system y 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 Python extendido, 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 una 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

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

  • 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 mapeado en caso de éxito o una cadena vacía en caso de falla.
  • update_dynamic_partitions(op_list)
    • Aplique la lista de operaciones dada en metadatos de partición dinámica, desasignando 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
    • Quite el mapa de la partición, luego cambie su tamaño a size .
  • remove partition_name
    • Desasignar la partición y luego eliminarla.
  • add partition-name group-name
    • Agregue una nueva partición al grupo especificado.
    • Abortar si el grupo no existe o si la partición ya existe.
  • move partition-name group-name
    • Mueva la partición al grupo especificado.
    • Abortar si el grupo no existe o la partición no existe.
  • add_group group-name maximum-size
    • Agregue un grupo con el nombre dado y el tamaño máximo.
    • Abortar 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.
    • Abortar 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.
    • Abortar si hay particiones en el grupo.
  • remove_all_groups
    • Desasignar todas las particiones del mapeador de dispositivos.
    • Elimina todas las particiones y grupos.

OTA incrementales

Las actualizaciones incrementales de OTA utilizan la siguiente lógica:

  1. Reducir particiones/eliminar particiones/mover particiones fuera del grupo (para que haya suficiente espacio para reducir grupos)
  2. Reducir grupos (para que haya suficiente espacio para hacer crecer los grupos)
  3. Hacer crecer grupos (para que tengamos suficiente espacio para hacer crecer/agregar particiones)
  4. Aumentar 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 completo

Las actualizaciones completas de OTA 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