Aktualizacje OTA dla urządzeń innych niż A/B z partycjami dynamicznymi

Android 10 obsługuje partycje dynamiczne, czyli system partycjonowania przestrzeni użytkownika, który może tworzyć, zmieniać rozmiar i usuwać partycje podczas aktualizacji bezprzewodowych (OTA).

Na tej stronie dowiesz się, jak klienty OTA zmieniają rozmiar partycji dynamicznych podczas aktualizacji na urządzeniach innych niż A/B.

W przypadku urządzeń innych niż A/B aktualizacja OTA dla partycji dynamicznych jest stosowana za pomocą updater w pakiecie aktualizacji.

Zaktualizuj urządzenia uruchamiające

Ta sekcja dotyczy urządzeń innych niż A/B, które są uruchamiane z obsługą partycji dynamicznych. Urządzenia te są uaktualniane z Androida 10 do wyższych wersji.

Generowanie pakietów aktualizacji

Pakiety aktualizacji OTA są generowane przez skrypt ota_from_target_files, który znajduje się w sekcji build/make/tools/releasetools. Domyślnie skrypt generuje pakiet, który aktualizuje partycje system i vendor. Jeśli istnieją dodatkowe partycje dynamiczne, takie jak product, product_services lub odm, ich aktualizacje muszą być generowane w kodzie dla konkretnego urządzenia.

Aby generować aktualizacje, w rozszerzonym module Pythona zaimplementuj funkcje FullOTA_GetBlockDifferences() i IncrementalOTA_GetBlockDifferences(). Te dwie funkcje zwracają listę obiektów BlockDifference, z których każda opisuje poprawkę aktualizacji, która zostałaby zastosowana na partycji. Partycji zwracanych przez te dwie funkcje nie należy modyfikować ręcznie ani weryfikować w innym miejscu, na przykład w funkcji *_InstallBegin() lub *_InstallEnd().

Przykład generowania aktualizacji:

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

Aktualizowanie przepływu

W skrypcie edify dodawane są te funkcje:

  • unmap_partition(name)
    • Usuń mapowanie partycji, jeśli jest zamapowana. W przeciwnym razie nie rób nic.
    • Zwraca ciąg znaków t w przypadku powodzenia lub pusty ciąg znaków w przypadku niepowodzenia.
  • map_partition(name)
    • Zmapuj partycję, jeśli jeszcze nie jest zamapowana.
    • W przypadku powodzenia zwraca ścieżkę bezwzględną zmapowanego urządzenia blokującego, a w przypadku niepowodzenia – pusty ciąg znaków.
  • update_dynamic_partitions(op_list)
    • Zastosuj podaną listę operacji do metadanych partycji dynamicznej, w razie potrzeby usuwając partycje.
    • Zwrot t w przypadku powodzenia lub pusty ciąg znaków w przypadku niepowodzenia.

Argument op_list w funkcji update_dynamic_partitions wskazuje plik w pakiecie aktualizacji. Każdy wiersz w pliku określa operację. Jeśli jakakolwiek operacja zakończy się niepowodzeniem, funkcja update_dynamic_partitions natychmiast zwróci pusty ciąg. Operacje to:

  • resize partition-name size
    • Odmapuj partycję, a następnie zmień jej rozmiar na size.
  • remove partition_name
    • Usuń mapowanie partycji, a następnie ją usuń.
  • add partition-name group-name
    • Dodaj nową partycję do określonej grupy.
    • Anuluj, jeśli grupa nie istnieje lub partycja już istnieje.
  • move partition-name group-name
    • Przenieś partycję do określonej grupy.
    • Anuluj, jeśli grupa lub partycja nie istnieje.
  • add_group group-name maximum-size
    • Dodaj grupę z podaną nazwą i maksymalną wielkością.
    • Anuluj, jeśli grupa już istnieje.
    • Wartość maximum_size 0 oznacza, że nie ma limitów rozmiaru dla partycji w grupie. Konieczne są dodatkowe testy, aby mieć pewność, że partycje w grupie nie przekraczają dostępnej przestrzeni na urządzeniu.
  • resize_group group-name maximum-size
    • Zmień rozmiar grupy do podanego maksymalnego rozmiaru.
    • Przerwij, jeśli grupa nie istnieje.
    • Wartość maximum_size 0 oznacza, że nie ma limitów rozmiaru dla partycji w grupie. Wymagane są dodatkowe testy, aby mieć pewność, że partycje w grupie nie przekraczają limitu dostępnego miejsca na urządzeniu.
  • remove_group group-name
    • usunąć grupę.
    • Anuluj, jeśli w grupie są partycje.
  • remove_all_groups
    • Odmapuj wszystkie partycje z mapera urządzenia.
    • Usuń wszystkie partycje i grupy.

Przyrostowa OTA

Incremental OTA updates use the following logic:

  1. Zmniejsz partycje, usuń partycje lub przenieś partycje poza grupę (aby było wystarczająco dużo miejsca na zmniejszenie grup).
  2. Zmniejsz grupy (aby było wystarczająco dużo miejsca na ich powiększenie).
  3. rozwijaj grupy (aby mieć wystarczającą ilość miejsca do powiększania/dodawania partycji)
  4. Powiększ partycje/dodaj partycje/przenieś partycje do nowej grupy

Szczegółowo update-script jest generowany według tej logiki:

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

Plik op_list dla update_dynamic_partitions jest generowany w ten sposób:

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

Pełna OTA

Pełne aktualizacje OTA korzystają z tej logiki:

  1. usunąć wszystkie istniejące grupy i partycje.
  2. Dodaj grupy
  3. Dodawanie partycji

Szczegóły dotyczące update-script są generowane zgodnie z tą logiką:

update_dynamic_partitions(op_list)

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

Plik op_list dla update_dynamic_partitions jest generowany według tej logiki:

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