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

Android 10 obsługuje partycje dynamiczne, czyli system partycjonowania w przestrzeni użytkownika, który umożliwia tworzenie, zmianę rozmiaru i usuwanie partycji podczas aktualizacji bezprzewodowych (OTA).

Na tej stronie opisujemy, jak klienci OTA zmieniają rozmiar partycji dynamicznych podczas aktualizacji urządzeń A/B, które zostały wprowadzone na rynek bez obsługi partycji dynamicznych, oraz jak klienci OTA przeprowadzają aktualizację do Androida 10.

Tło

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

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

Na tej stronie miejsca na metadane są nazywane metadanymi S (źródło) i metadanymi T (cel). Podobnie partycje są określane jako system_s, vendor_t, itd.

Więcej informacji o konfiguracjach systemu kompilacji znajdziesz w artykule Aktualizowanie urządzeń.

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

Przykład metadanych na urządzeniu:

  • Fizyczne urządzenie blokowe system_a
    • Metadane 0
      • Grupa foo_a
        • Logiczna (dynamiczna) partycja system_a
        • Logiczna (dynamiczna) partycja product_services_a
        • Inne partycje aktualizowane przez Foo
      • Grupa bar_a
        • Logiczna (dynamiczna) partycja vendor_a
        • Logiczna (dynamiczna) partycja product_a
        • Inne partycje aktualizowane przez Bar
    • Metadane 1 (nieużywane)
  • Fizyczne urządzenie blokowe system_b
    • Metadane 0 (nieużywane)
    • Metadane 1
      • Grupa foo_b
        • Logiczna (dynamiczna) partycja system_b
        • Logiczna (dynamiczna) partycja product_services_b
        • Inne partycje aktualizowane przez Foo
      • Grupa bar_b
        • Logiczna (dynamiczna) partycja vendor_b
        • Logiczna (dynamiczna) partycja product_b
        • Inne partycje aktualizowane przez Bar

Aby zrzucić metadane na urządzeniu, możesz użyć narzędzia lpdump w system/extras/partition_tools Przykład:

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

Dopasowywanie aktualizacji

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

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

Ponieważ klient OTA nie wie, jak mapować partycje dynamiczne, 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 dopasowaniu

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

Proces aktualizacji przy użyciu zwykłego pakietu aktualizacji

  1. Zainicjuj metadane partycji super
    1. Utwórz nowe metadane M na podstawie metadanych S (metadane źródłowe). Jeśli na przykład metadane S używają [system_s, vendor_s, product_s] jako urządzeń blokowych, nowe metadane M używają [system_t, vendor_t, product_t] jako urządzeń blokowych. Wszystkie grupy i partycje są odrzucane w M.
    2. Dodaj grupy i partycje docelowe zgodnie z polem dynamic_partition_metadata w manifeście aktualizacji. Rozmiar każdej partycji można znaleźć 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 blokowych.
    1. W razie potrzeby zmapuj partycje źródłowe w mapowaniu urządzeń jako tylko do odczytu. Jest to konieczne w przypadku wczytywania z boku, ponieważ partycje źródłowe nie są mapowane przed aktualizacją.
    2. Zastosuj pełną lub przyrostową aktualizację do wszystkich urządzeń blokowych w miejscu docelowym.
    3. Zamontuj partycje, aby uruchomić skrypt po instalacji, a następnie odmontuj partycje.
  3. Odmapuj partycje docelowe.

Proces aktualizacji przy użyciu pakietu aktualizacji dopasowującej

Jeśli pakiet aktualizacji dopasowującej zostanie zastosowany na urządzeniu, które już obsługuje partycje dynamiczne, klient OTA zastosuje podzielony super.img bezpośrednio na urządzeniach blokowych. Proces aktualizacji przepływu jest podobny do aktualizacji dopasowującej. Szczegółowe informacje znajdziesz w artykule Dopasowywanie aktualizacji.

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

  • Miejsce A jest miejscem aktywnym.
  • system_a zawiera aktywne metadane w miejscu 0.
  • system_a, vendor_a, i product_a są używane jako urządzenia blokowe.

Gdy klient OTA otrzyma pakiet aktualizacji dopasowującej, zastosuje super_system.img na fizycznym system_b, super_vendor.img na fizycznym vendor_b, i super_product.img na fizycznym product_b. Fizyczne urządzenie blokowe system_b zawiera prawidłowe metadane do mapowania logicznych system_b, vendor_b i product_b podczas uruchamiania.

Generowanie pakietów aktualizacji

Przyrostowa aktualizacja OTA

Podczas generowania przyrostowych aktualizacji OTA dla urządzeń dopasowujących aktualizacje zależą od tego, czy kompilacja podstawowa definiuje PRODUCT_USE_DYNAMIC_PARTITIONS i PRODUCT_RETROFIT_DYNAMIC_PARTITIONS.

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

Pełna aktualizacja OTA

Dla urządzeń dopasowujących generowane są 2 pełne pakiety OTA.

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

Odrzucanie aktualizacji niedopasowujących w starszych kompilacjach

Zastosuj zwykły pełny pakiet OTA tylko do kompilacji z partycjami dynamicznymi. Jeśli serwer OTA jest nieprawidłowo skonfigurowany i wysyła te pakiety na urządzenia z Androidem 9 lub starszym, urządzenia nie uruchomią się. Klient OTA w Androidzie 9 i starszym nie może odróżnić pakietu OTA dopasowującego od zwykłego pełnego pakietu OTA, więc klient nie odrzuci pełnego pakietu.

Aby uniemożliwić urządzeniu zaakceptowanie pełnego pakietu OTA, możesz wymagać wykonania kroku po instalacji, aby sprawdzić istniejącą konfigurację urządzenia. 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ę.