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

Android 10 obsługuje partycje dynamiczne – system partycjonowania przestrzeni użytkownika, który umożliwia tworzenie, zmianę rozmiaru i niszczenie partycji podczas aktualizacji OTA.

Na tej stronie opisano, jak klienci OTA zmieniają rozmiar partycji dynamicznych podczas aktualizacji dla urządzeń innych niż A/B.

W przypadku urządzeń innych niż A/B aktualizacja OTA dla partycji dynamicznych jest stosowana przy użyciu updater znajdującego się w pakiecie aktualizacji.

Zaktualizuj urządzenia uruchamiające

Ta sekcja dotyczy urządzeń innych niż A/B, które uruchamiają się z obsługą partycji dynamicznych; te urządzenia uaktualniają się z Androida 10 do nowszych wersji.

Wygeneruj pakiety aktualizacji

Pakiety aktualizacji OTA są generowane przez skrypt ota_from_target_files , znajdujący się w build/make/tools/releasetools . Domyślnie skrypt generuje pakiet aktualizujący partycje system i vendor . Jeśli istnieją dodatkowe partycje dynamiczne, takie jak product , product_services lub odm , ich aktualizacje muszą zostać wygenerowane w kodzie specyficznym dla urządzenia .

Aby wygenerować aktualizacje, w rozszerzonym module Pythona zaimplementuj FullOTA_GetBlockDifferences() i IncrementalOTA_GetBlockDifferences() . Te dwie funkcje zwracają listę obiektów BlockDifference , z których każdy opisuje poprawkę aktualizacyjną, która zostanie zastosowana na partycji. Partycje zwracane przez te dwie funkcje nie powinny być modyfikowane ręcznie ani weryfikowane w innym miejscu, na przykład w *_InstallBegin() lub *_InstallEnd() .

Przykład generacji 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()]

Aktualizuj przepływ

Za kulisami do skryptu edify dodano następujące funkcje:

  • unmap_partition(name)
    • Usuń mapowanie partycji, jeśli jest zmapowana, w przeciwnym razie nie rób nic.
    • Zwraca ciąg t w przypadku powodzenia lub pusty ciąg w przypadku niepowodzenia.
  • map_partition(name)
    • Zamapuj partycję, jeśli nie została jeszcze zmapowana.
    • W przypadku powodzenia zwraca ścieżkę bezwzględną zmapowanego urządzenia blokowego lub pusty ciąg znaków w przypadku niepowodzenia.
  • update_dynamic_partitions(op_list)
    • Zastosuj podaną listę operacji na metadanych partycji dynamicznych, w razie potrzeby usuwając mapowanie partycji.
    • Zwróć t w przypadku powodzenia lub pusty ciąg w przypadku niepowodzenia.

Argument op_list parametru update_dynamic_partitions wskazuje plik w pakiecie aktualizacji. Każda linia w pliku określa operację. Jeśli jakakolwiek operacja nie powiedzie się, update_dynamic_partitions natychmiast zwraca pusty ciąg. Operacje to:

  • resize partition-name size
    • Usuń mapowanie partycji, a następnie zmień jej size na .
  • remove partition_name
    • Odmapuj partycję, a następnie ją usuń.
  • add partition-name group-name
    • Dodaj nową partycję do określonej grupy.
    • Przerwij, jeśli grupa nie istnieje lub jeśli partycja już istnieje.
  • move partition-name group-name
    • Przenieś partycję do określonej grupy.
    • Przerwij, jeśli grupa nie istnieje lub partycja nie istnieje.
  • add_group group-name maximum-size
    • Dodaj grupę o podanej nazwie i maksymalnym rozmiarze.
    • Przerwij, jeśli grupa już istnieje.
    • maximum_size wynoszący 0 oznacza, że ​​nie ma ograniczeń rozmiaru partycji w grupie. Wymagane są dodatkowe testy, aby upewnić się, że partycje w grupie nie przekraczają dostępnego miejsca na urządzeniu.
  • resize_group group-name maximum-size
    • Zmień rozmiar grupy do podanego maksymalnego rozmiaru.
    • Przerwij, jeśli grupa nie istnieje.
    • maximum_size wynoszący 0 oznacza, że ​​nie ma ograniczeń rozmiaru partycji w grupie. Wymagane są dodatkowe testy, aby upewnić się, że partycje w grupie nie przekraczają dostępnego miejsca na urządzeniu.
  • remove_group group-name
    • Usuń grupę.
    • Przerwij, jeśli w grupie znajdują się partycje.
  • remove_all_groups
    • Usuń mapowanie wszystkich partycji z narzędzia mapującego urządzenia.
    • Usuń wszystkie partycje i grupy.

Przyrostowa OTA

Przyrostowe aktualizacje OTA wykorzystują następującą logikę:

  1. Zmniejsz partycje/usuń partycje/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 powiększanie grup)
  3. Rozwijaj grupy (abyśmy mieli wystarczająco dużo miejsca na rozwój/dodawanie partycji)
  4. Zwiększ partycje/dodaj partycje/przenieś partycje do nowej grupy

Szczegółowo update-script jest generowany przy użyciu następującej 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 zgodnie z następującą logiką:

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 następującej logiki:

  1. Usuń wszystkie istniejące grupy i partycje
  2. Dodaj grupy
  3. Dodaj partycje

Szczegółowo update-script jest generowany przy użyciu następującej logiki:

update_dynamic_partitions(op_list)

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

Plik op_list dla update_dynamic_partitions jest generowany zgodnie z następującą logiką:

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