Punkt kontrolny danych użytkownika

Android 10 wprowadza punkt kontrolny danych użytkownika (UDC), który umożliwia przywrócenie poprzedniego stanu Androida w przypadku niepowodzenia aktualizacji Androida przez sieć (OTA). Dzięki UDC w przypadku nieudanej aktualizacji OTA Androida urządzenie może bezpiecznie wrócić do poprzedniego stanu. Chociaż aktualizacje A/B rozwiązują ten problem w przypadku wczesnego rozruchu, wycofanie zmian nie jest obsługiwane, gdy zmodyfikowana zostanie partycja danych użytkownika (zamontowana na /data).

UDC umożliwia przywrócenie partycji danych użytkownika nawet po jej zmodyfikowaniu. Funkcja UDC realizuje to za pomocą możliwości punktów kontrolnych w systemie plików, alternatywnej implementacji, gdy system plików nie obsługuje punktów kontrolnych, integracji z mechanizmem A/B bootloadera przy jednoczesnej obsłudze aktualizacji innych niż A/B oraz obsługi powiązania wersji klucza i zapobiegania wycofywaniu klucza.

Wpływ na użytkownika

Funkcja UDC poprawia komfort aktualizacji OTA, ponieważ w przypadku niepowodzenia aktualizacji OTA mniej użytkowników traci dane. Może to zmniejszyć liczbę połączeń z pomocą techniczną od użytkowników, którzy napotkali problemy podczas procesu aktualizacji. Jeśli jednak aktualizacja OTA się nie powiedzie, użytkownicy mogą zauważyć, że urządzenie uruchamia się ponownie kilka razy.

Jak to działa

Funkcja punktu kontrolnego w różnych systemach plików

W przypadku systemu plików F2FS UDC dodaje funkcję punktu kontrolnego do głównej wersji jądra Linuxa 4.20 i przenosi ją do wszystkich popularnych jąder obsługiwanych przez urządzenia z Androidem 10.

W przypadku innych systemów plików UDC używa wirtualnego urządzenia mapowania urządzeń o nazwie dm_bow do obsługi funkcji punktu kontrolnego. dm_bow znajduje się między urządzeniem a systemem plików. Gdy partycja jest montowana, wydawane jest polecenie TRIM, co powoduje, że system plików wydaje polecenia TRIM na wszystkich wolnych blokach. dm_bow przechwytuje te polecenia i używa ich do utworzenia listy wolnych bloków. Odczyty i zapisy są następnie wysyłane do urządzenia bez zmian, ale zanim zapis zostanie dozwolony, dane potrzebne do przywrócenia są zapisywane w wolnym bloku.

Proces punktu kontrolnego

Gdy zamontowana jest partycja z flagą checkpoint=fs/block, Android wywołuje restoreCheckpoint na dysku, aby umożliwić urządzeniu przywrócenie bieżącego punktu kontrolnego. init wywołuje funkcję init, aby sprawdzić, czy urządzenie jest w stanie A/B bootloadera lub czy ustawiono liczbę ponownych prób aktualizacji.needsCheckpoint Jeśli którykolwiek z tych warunków jest spełniony, Android wywołuje funkcję createCheckpoint, aby dodać flagi montowania lub utworzyć urządzenie dm_bow.

Po zamontowaniu partycji wywoływany jest kod punktu kontrolnego, aby wydać polecenia TRIM. Proces uruchamiania będzie przebiegać normalnie. W momencie LOCKED_BOOT_COMPLETE Android wywołuje commitCheckpoint, aby zatwierdzić bieżący punkt kontrolny, a aktualizacja jest kontynuowana w normalny sposób.

Zarządzanie kluczami KeyMint (wcześniej Keymaster)

Klucze KeyMint są używane do szyfrowania urządzenia lub w innych celach. Aby zarządzać tymi kluczami, Android opóźnia wywołania usuwania kluczy do momentu zatwierdzenia punktu kontrolnego.

Monitorowanie stanu zdrowia

Demon stanu sprawdza, czy jest wystarczająco dużo miejsca na dysku, aby utworzyć punkt kontrolny. Demon stanu znajduje się w regionie cp_healthDaemonCheckpoint.cpp.

Demon stanu ma te konfigurowalne zachowania:

  • ro.sys.cp_msleeptime: Określa, jak często urządzenie sprawdza wykorzystanie dysku.
  • ro.sys.cp_min_free_bytes: określa minimalną wartość, której szuka demon stanu urządzenia.
  • ro.sys.cp_commit_on_full: Określa, czy demon stanu urządzenia ponownie uruchamia urządzenie, czy zapisuje punkt kontrolny i kontynuuje działanie, gdy dysk jest pełny.

Interfejsy API punktów kontrolnych

Interfejsy API punktów kontrolnych są używane przez funkcję UDC. Informacje o innych interfejsach API używanych przez UDC znajdziesz w IVold.aidl.

void startCheckpoint(int retry)

Tworzy punkt kontrolny.

Platforma wywołuje tę metodę, gdy jest gotowa do rozpoczęcia aktualizacji. Punkt kontrolny jest tworzony przed zamontowaniem po ponownym uruchomieniu systemów plików z punktami kontrolnymi, takich jak userdata, w trybie odczytu i zapisu. Jeśli liczba ponownych prób jest dodatnia, interfejs API obsługuje ponowne próby śledzenia, a program aktualizujący wywołuje funkcję needsRollback, aby sprawdzić, czy wymagane jest wycofanie aktualizacji. Jeśli liczba ponownych prób wynosi -1, interfejs API przekazuje decyzję do programu rozruchowego A/B.

Ta metoda nie jest wywoływana podczas normalnej aktualizacji A/B.

void commitChanges()

Zatwierdza zmiany.

Platforma wywołuje tę metodę po ponownym uruchomieniu, gdy zmiany są gotowe do zatwierdzenia. Ta funkcja jest wywoływana przed zapisaniem danych (takich jak zdjęcia, filmy, SMS-y, potwierdzenie odbioru przez serwer) w danych użytkownika i przed BootComplete.

Jeśli nie ma aktywnej aktualizacji z punktem kontrolnym, ta metoda nie ma żadnego efektu.

abortChanges()

Wymusza ponowne uruchomienie i przywraca punkt kontrolny. Anuluje wszystkie zmiany w danych użytkownika od pierwszego ponownego uruchomienia.

Platforma wywołuje tę metodę po ponownym uruchomieniu, ale przed commitChanges. Gdy ta metoda jest wywoływana, wartość retry_counter maleje. Wpisy logu są generowane.

bool needsRollback()

Określa, czy wymagane jest wycofanie zmian.

Na urządzeniach bez punktu kontrolnego zwraca wartość false. Na urządzeniach z punktami kontrolnymi zwraca wartość true podczas uruchamiania bez punktu kontrolnego.

Wdrażanie UDC

Implementacja referencyjna

Przykład implementacji UDC znajdziesz w pliku dm-bow.c. Dodatkowe informacje o tej funkcji znajdziesz w pliku dm-bow.txt.

Konfiguracja

W sekcji on fs w pliku init.hardware.rc sprawdź, czy masz:

mount_all /vendor/etc/fstab.${ro.boot.hardware.platform} --early

W sekcji on late-fs w pliku init.hardware.rc sprawdź, czy masz:

mount_all /vendor/etc/fstab.${ro.boot.hardware.platform} --late

W pliku fstab.hardware upewnij się, że /data jest oznaczony tagiem latemount.

/dev/block/bootdevice/by-name/userdata              /data              f2fs
noatime,nosuid,nodev,discard,reserve_root=32768,resgid=1065,fsync_mode=nobarrier
latemount,wait,check,fileencryption=ice,keydirectory=/metadata/vold/metadata_encryption,quota,formattable,sysfs_path=/sys/devices/platform/soc/1d84000.ufshc,reservedsize=128M,checkpoint=fs

Dodawanie partycji metadanych

UDC wymaga partycji metadanych do przechowywania liczby ponownych prób bez bootloadera i kluczy. Skonfiguruj partycję metadanych i wcześniej zamontuj ją w /metadata.

W pliku fstab.hardware upewnij się, że /metadata jest oznaczony tagiem earlymount lub first_stage_mount.

/dev/block/by-name/metadata           /metadata           ext4
noatime,nosuid,nodev,discard,sync
wait,formattable,first_stage_mount

Zainicjuj partycję zerami.

Dodaj do pliku BoardConfig.mk te wiersze:

BOARD_USES_METADATA_PARTITION := true
BOARD_ROOT_EXTRA_FOLDERS := existing_folders metadata

Aktualizowanie systemów

Systemy F2FS

W przypadku systemów, które używają F2FS do formatowania danych, upewnij się, że Twoja wersja F2FS obsługuje punkty kontrolne. Więcej informacji znajdziesz w artykule Funkcja punktu kontrolnego w różnych systemach plików.

Dodaj flagę checkpoint=fs do sekcji <fs_mgr_flags> pliku fstab dla urządzenia zamontowanego w /data.

Systemy inne niż F2FS

W przypadku systemów innych niż F2FS funkcja dm-bow musi być włączona w konfiguracji jądra.

Dodaj flagę checkpoint=block do sekcji <fs_mgr_flags> pliku fstab dla urządzenia zamontowanego w /data.

Sprawdzanie logów

Wpisy logu są generowane, gdy wywoływane są interfejsy API punktu kontrolnego.

Weryfikacja

Aby przetestować implementację UDC, uruchom VtsKernelCheckpointTestzestaw testów VTS.