Punkt kontrolny danych użytkownika

W Androidzie 10 wprowadzono punkt kontrolny danych użytkownika (UDC), który umożliwia przywrócenie poprzedniego stanu Androida w przypadku niepowodzenia aktualizacji bezprzewodowej (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 wycofaniu 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ą 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 zamontowana, wysyłane jest polecenie TRIM, co powoduje, że system plików wysyła polecenia TRIM do wszystkich wolnych bloków. dm_bow przechwytuje te przycięcia i używa ich do utworzenia listy bezpłatnych bloków. Operacje odczytu i zapisu są następnie wysyłane do urządzenia bez zmian, ale zanim będzie można zapisać dane, 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 funkcję 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 createCheckpoint, aby dodać flagi montowania lub utworzyć urządzenie dm_bow.

Po zamontowaniu partycji wywoływany jest kod punktu kontrolnego, aby wydać polecenia przycinania. 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 innych celów. 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:

Interfejsy API punktów kontrolnych

Interfejsy Checkpoint API są używane przez funkcję UDC. Informacje o innych interfejsach API używanych przez UDC znajdziesz w sekcji 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 systemu 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 aktualizator 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 testu 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 wywołaniem metody commitChanges. Gdy ta metoda jest wywoływana, wartość retry_counter maleje. Wpisy logu są generowane.

bool needsRollback()

Określa, czy wymagane jest wycofanie.

Na urządzeniach bez punktów kontrolnych 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 dm-bow.c. Dodatkową dokumentację dotyczącą tej funkcji znajdziesz 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ę samymi 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ą systemu F2FS do formatowania danych, upewnij się, że Twoja wersja systemu 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 należy włączyć dm-bow 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.