Aktualizacja OTA na urządzeniach z testami A/B bez partycji dynamicznych

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 opisujemy, jak klienci OTA zmieniają rozmiar partycji dynamicznych podczas aktualizacji na urządzeniach A/B, które zostały wprowadzone na rynek bez obsługi partycji dynamicznych, oraz jak klienci OTA przeprowadzają uaktualnienie do Androida 10.

Tło

Podczas aktualizacji urządzenia A/B w celu obsługi partycji dynamicznych tabela partycji GUID (GPT) na urządzeniu jest zachowywana, więc na urządzeniu nie ma partycji super. Metadane są przechowywane w lokalizacjach system_asystem_b, ale można to dostosować, zmieniając wartość BOARD_SUPER_PARTITION_METADATA_DEVICE.

Na każdym urządzeniu blokowym znajdują się 2 miejsca na metadane. W każdym urządzeniu blokowym używane jest tylko 1 miejsce na metadane. Na przykład metadane 0 w system_a i metadane 1 w system_b odpowiadają odpowiednio partycjom w gniazdach A i B. W czasie działania nie ma znaczenia, które miejsce na reklamę jest aktualizowane.

Na tej stronie gniazda metadanych są nazywane Metadata S (źródło) i Metadata T (miejsce docelowe). Podobnie partycje są oznaczane jako system_s, vendor_t itd.

Więcej informacji o konfiguracjach systemu kompilacji znajdziesz w sekcji Uaktualnianie urządzeń.

Więcej informacji o tym, do jakich grup aktualizacji należą partycje, znajdziesz w sekcji Zmiany w konfiguracji płyty w przypadku nowych urządzeń.

Przykład metadanych na urządzeniu:

  • Fizyczne urządzenie blokowesystem_a
    • Metadane 0
      • Grupa foo_a
        • Partycja logiczna (dynamiczna)system_a
        • Partycja logiczna (dynamiczna) product_services_a
        • Inne partycje zaktualizowane przez Foo
      • Grupa bar_a
        • Partycja logiczna (dynamiczna)vendor_a
        • Partycja logiczna (dynamiczna) product_a
        • Inne partycje zaktualizowane przez Bar
    • Metadane 1 (nieużywane)
  • Fizyczne urządzenie blokowesystem_b
    • Metadane 0 (nieużywane)
    • Metadane 1
      • Grupa foo_b
        • Partycja logiczna (dynamiczna) system_b
        • Partycja logiczna (dynamiczna) product_services_b
        • Inne partycje zaktualizowane przez Foo
      • Group bar_b
        • Partycja logiczna (dynamiczna) vendor_b
        • Partycja logiczna (dynamiczna) product_b
        • Inne partycje zaktualizowane przez Bar

Możesz użyć narzędzia lpdump w sekcji system/extras/partition_tools, aby zrzucić metadane na urządzenie. Na przykład:

lpdump --slot 0 /dev/block/by-name/system_a
lpdump --slot 1 /dev/block/by-name/system_b

Dostosowywanie aktualizacji

Na urządzeniach z Androidem 9 i starszym klient OTA nie obsługuje mapowania dynamicznych partycji przed aktualizacją. Tworzony jest dodatkowy zestaw poprawek, dzięki czemu mapowanie można zastosować bezpośrednio do istniejących partycji fizycznych.

Generator OTA tworzy ostateczny plik super.img, który zawiera zawartość wszystkich partycji dynamicznych, a następnie dzieli obraz na kilka obrazów o rozmiarach odpowiadających rozmiarom fizycznych urządzeń blokowych odpowiadających systemowi, dostawcy itp. Obrazy te noszą nazwy super_system.img, super_vendor.img itd. Klient OTA stosuje te obrazy do partycji fizycznych, a nie do partycji logicznych (dynamicznych).

Klient OTA nie wie, jak mapować partycje dynamiczne, więc wszystkie kroki po instalacji są automatycznie wyłączane w przypadku tych partycji podczas generowania pakietu aktualizacji. Więcej informacji znajdziesz w artykule Konfigurowanie po instalacji.

Proces aktualizacji jest taki sam jak w Androidzie 9.

Przed aktualizacją:

ro.boot.dynamic_partitions=
ro.boot.dynamic_partitions_retrofit=

Po aktualizacji:

ro.boot.dynamic_partitions=true
ro.boot.dynamic_partitions_retrofit=true

Przyszłe aktualizacje po modernizacji

Po aktualizacji modernizacyjnej klient OTA jest aktualizowany, aby działać z partycjami dynamicznymi. Zakresy partycji źródłowych nigdy nie obejmują docelowych partycji fizycznych.

Aktualizowanie przepływu za pomocą zwykłego pakietu aktualizacji

  1. Zainicjuj metadane partycji super.
    1. Utwórz nowe metadane M na podstawie metadanych S (metadanych źródłowych). Jeśli na przykład metadane S używają [system_s, vendor_s, product_s] jako urządzeń blokowych, to nowe metadane M używają [system_t, vendor_t, product_t] jako urządzeń blokowych. W przypadku M wszystkie grupy i partycje są odrzucane.
    2. Dodaj grupy docelowe i podziały zgodnie z polem dynamic_partition_metadata w pliku manifestu aktualizacji. Rozmiar każdej partycji znajdziesz w new_partition_info.
    3. Zapisz M w metadanych T.
    4. Zmapuj dodane partycje w mapowaniu urządzeń jako zapisywalne.
  2. Zastosuj aktualizację na urządzeniach blokujących.
    1. W razie potrzeby zmapuj partycje źródłowe na mapowaniu urządzenia jako tylko do odczytu. Jest to konieczne w przypadku wczytywania z zewnątrz, ponieważ partycje źródłowe nie są mapowane przed aktualizacją.
    2. Zastosuj pełną lub przyrostową aktualizację do wszystkich urządzeń blokowych w docelowym slocie.
    3. Zamontuj partycje, aby uruchomić skrypt poinstalacyjny, a następnie odmontuj partycje.
  3. Odłącz partycje docelowe.

Aktualizowanie przepływu za pomocą pakietu aktualizacji wstecznej

Jeśli pakiet aktualizacji zostanie zastosowany na urządzeniu, które już obsługuje partycje dynamiczne, klient OTA zastosuje plik super.img na urządzeniach blokowych bezpośrednio. Proces aktualizacji jest podobny do aktualizacji modernizacyjnej. Więcej informacji znajdziesz w artykule Dostosowywanie aktualizacji.

Załóżmy na przykład, że:

  • Slot A jest aktywny.
  • system_a zawiera aktywne metadane w slocie 0.
  • system_a, vendor_aproduct_a są używane jako urządzenia blokujące.

Gdy klient OTA otrzyma pakiet aktualizacji, zastosuje super_system.img na urządzeniu system_b, super_vendor.img na urządzeniu vendor_bsuper_product.img na urządzeniu product_b. Fizyczne urządzenie blokowe system_b zawiera prawidłowe metadane, które umożliwiają zmapowanie logicznych urządzeń system_b, vendor_bproduct_b podczas uruchamiania.

Generowanie pakietów aktualizacji

Przyrostowa OTA

Podczas generowania przyrostowych aktualizacji OTA dla urządzeń modernizowanych aktualizacje zależą od tego, czy kompilacja podstawowa definiuje PRODUCT_USE_DYNAMIC_PARTITIONSPRODUCT_RETROFIT_DYNAMIC_PARTITIONS.

  • Jeśli kompilacja podstawowa nie definiuje zmiennych, jest to aktualizacja dopasowująca. Pakiet aktualizacji zawiera podzielony plik super.img i wyłącza krok po instalacji.
  • Jeśli kompilacja podstawowa definiuje zmienne, jest to takie samo jak typowa aktualizacja z partycjami dynamicznymi. Pakiet aktualizacji zawiera obrazy partycji logicznych (dynamicznych). Można włączyć etap po instalacji.

Pełna aktualizacja OTA

W przypadku urządzeń modernizowanych generowane są 2 pełne pakiety OTA.

  • $(PRODUCT)-ota-retrofit-$(TAG).zip zawsze zawiera podzielony super.img i wyłącza krok po instalacji w przypadku aktualizacji.
    • Jest on generowany z dodatkowym argumentem --retrofit_dynamic_partitions do skryptu ota_from_target_files.
    • Można ją zastosować do wszystkich wersji.
  • $(PRODUCT)-ota-$(TAG).zip zawiera logiczne obrazy na potrzeby przyszłych aktualizacji.
    • Stosuj to tylko w przypadku kompilacji z włączonymi partycjami dynamicznymi. Szczegółowe informacje o egzekwowaniu tych zasad znajdziesz poniżej.

Odrzucanie aktualizacji bez dopasowania w przypadku starszych kompilacji

Zastosuj zwykły pełny pakiet OTA tylko w przypadku kompilacji z włączonymi partycjami dynamicznymi. Jeśli serwer OTA jest nieprawidłowo skonfigurowany i przesyła te pakiety na urządzenia z Androidem 9 lub starszym, urządzenia nie uruchomią się. Klient OTA na Androidzie 9 i starszych wersjach nie potrafi odróżnić pakietu OTA z modernizacją od zwykłego pełnego pakietu OTA, więc nie odrzuci pełnego pakietu.

Aby uniemożliwić urządzeniu zaakceptowanie pełnego pakietu OTA, możesz wymagać wykonania po instalacji czynności sprawdzającej istniejącą konfigurację urządzenia. Na przykład:

device/device_name/dynamic_partitions/check_dynamic_partitions

#!/system/bin/sh
DP_PROPERTY_NAME="ro.boot.dynamic_partitions"
DP_RETROFIT_PROPERTY_NAME="ro.boot.dynamic_partitions_retrofit"

DP_PROPERTY=$(getprop ${DP_PROPERTY_NAME})
DP_RETROFIT_PROPERTY=$(getprop ${DP_RETROFIT_PROPERTY_NAME})

if [ "${DP_PROPERTY}" != "true" ] || [ "${DP_RETROFIT_PROPERTY}" != "true" ] ; then
    echo "Error: applied non-retrofit update on build without dynamic" \
         "partitions."
    echo "${DP_PROPERTY_NAME}=${DP_PROPERTY}"
    echo "${DP_RETROFIT_PROPERTY_NAME}=${DP_RETROFIT_PROPERTY}"
    exit 1
fi

device/device_name/dynamic_partitions/Android.mk

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE:= check_dynamic_partitions
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_CLASS := EXECUTABLES
LOCAL_SRC_FILES := check_dynamic_partitions
LOCAL_PRODUCT_MODULE := true
include $(BUILD_PREBUILT)

device/device_name/device.mk

PRODUCT_PACKAGES += check_dynamic_partitions

# OPTIONAL=false so that the error in check_dynamic_partitions will be
# propagated to OTA client.
AB_OTA_POSTINSTALL_CONFIG += \
    RUN_POSTINSTALL_product=true \
    POSTINSTALL_PATH_product=bin/check_dynamic_partitions \
    FILESYSTEM_TYPE_product=ext4 \
    POSTINSTALL_OPTIONAL_product=false \

Gdy zwykły pakiet OTA zostanie zastosowany na urządzeniu bez włączonych partycji dynamicznych, klient OTA uruchomi check_dynamic_partitions jako krok po instalacji i odrzuci aktualizację.