Android 10 wprowadza punkt kontrolny danych użytkownika (UDC), który umożliwia Androidowi powrót do poprzedniego stanu w przypadku nieudanej aktualizacji OTA. Dzięki UDC, jeśli aktualizacja OTA na Androidzie się nie powiedzie, urządzenie może bezpiecznie wycofać zmiany do poprzedniego stanu. Chociaż
aktualizacje A/B rozwiązują ten problem w przypadku wczesnego uruchamiania, przywracanie
nie jest obsługiwane, gdy zmodyfikowana zostanie partycja danych użytkownika (zamontowana w /data).
UDC umożliwia urządzeniu przywrócenie partycji danych użytkownika nawet po jej zmodyfikowaniu. Funkcja UDC realizuje to dzięki możliwościom punktów kontrolnych w systemie plików, alternatywnemu wdrożeniu, gdy system plików nie obsługuje punktów kontrolnych, integracji z mechanizmem A/B programu rozruchowego przy jednoczesnej obsłudze aktualizacji innych niż A/B oraz obsłudze powiązania wersji klucza i zapobiegania przywracaniu klucza.
Wpływ na użytkownika
Funkcja UDC poprawia komfort aktualizacji OTA, ponieważ mniej użytkowników traci dane w przypadku nieudanej aktualizacji OTA. Może to zmniejszyć liczbę zgłoszeń do pomocy od użytkowników, którzy napotykają problemy podczas procesu aktualizacji. Gdy 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 funkcja UDC dodaje funkcję punktu kontrolnego do upstreamowego 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 funkcja UDC używa wirtualnego urządzenia mapującego urządzenia 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, wydawane jest polecenie trim, które powoduje, że system plików wydaje polecenia trim na wszystkich wolnych blokach. dm_bow przechwytuje te polecenia trim 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 funkcję restoreCheckpoint na dysku, aby umożliwić urządzeniu przywrócenie bieżącego punktu kontrolnego. init wywołuje następnie funkcję needsCheckpoint, aby sprawdzić, czy urządzenie jest w stanie programu rozruchowego A/B, czy też ustawiło liczbę ponownych prób aktualizacji. 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 przebiega normalnie. W LOCKED_BOOT_COMPLETE Android wywołuje funkcję commitCheckpoint, aby zatwierdzić bieżący punkt kontrolny, a aktualizacja przebiega normalnie.
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
Demon stanu sprawdza, czy jest wystarczająco dużo miejsca na dysku, aby utworzyć punkt kontrolny. Demon stanu znajduje się w
cp_healthDaemon
w Checkpoint.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.ro.sys.cp_commit_on_full: określa, czy demon stanu ma ponownie uruchomić urządzenie, czy zatwierdzić punkt kontrolny i kontynuować, gdy dysk jest pełny.
Interfejsy API punktu kontrolnego
Interfejsy API punktu kontrolnego są używane przez funkcję UDC. Więcej informacji o innych interfejsach API używanych przez UDC znajdziesz w
IVold.aidl.
void startCheckpoint(int retry)
Tworzy punkt kontrolny.
Gdy platforma jest gotowa do rozpoczęcia aktualizacji, wywołuje tę metodę. Punkt kontrolny jest tworzony przed zamontowaniem systemów plików z punktami kontrolnymi, takich jak userdata, w trybie R/W po ponownym uruchomieniu. Jeśli liczba ponownych prób jest dodatnia, interfejs API obsługuje śledzenie ponownych prób, a aktualizator wywołuje funkcję needsRollback, aby sprawdzić, czy wymagane jest przywrócenie aktualizacji. Jeśli liczba ponownych prób wynosi -1, interfejs API odwołuje się do decyzji programu rozruchowego A/B.
Ta metoda nie jest wywoływana podczas normalnej aktualizacji A/B.
void commitChanges()
Zatwierdza zmiany.
Gdy zmiany są gotowe do zatwierdzenia, platforma wywołuje tę metodę po ponownym uruchomieniu. Jest ona wywoływana przed zapisaniem danych (takich jak zdjęcia, filmy, SMS-y, potwierdzenie otrzymania od serwera) w userdata 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. Porzuca wszystkie modyfikacje userdata od pierwszego ponownego uruchomienia.
Platforma wywołuje tę metodę po ponownym uruchomieniu, ale przed commitChanges.
Gdy ta metoda jest wywoływana, retry_counter jest zmniejszany. Generowane są wpisy logu.
bool needsRollback()
Określa, czy wymagane jest przywrócenie.
Na urządzeniach bez punktu kontrolnego zwraca wartość false. Na urządzeniach z punktem kontrolnym 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 w dm-bow.txt.
Konfiguracja
W pliku init.hardware.rc w sekcji on fs upewnij się, że masz:
mount_all /vendor/etc/fstab.${ro.boot.hardware.platform} --early
W pliku init.hardware.rc w sekcji on late-fs upewnij się, że masz:
mount_all /vendor/etc/fstab.${ro.boot.hardware.platform} --late
W pliku fstab.hardware upewnij się, że /data jest oznaczony jako 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 i kluczy innych niż program rozruchowy. Skonfiguruj partycję metadanych i zamontuj ją wcześnie w /metadata.
W pliku fstab.hardware upewnij się, że /metadata jest oznaczony jako 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 te wiersze do BoardConfig.mk:
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 sekcji Funkcja punktu kontrolnego w różnych systemach plików.
Dodaj flagę checkpoint=fs do sekcji <fs_mgr_flags> w fstab dla
urządzenia zamontowanego w /data.
Systemy inne niż F2FS
W przypadku systemów innych niż F2FS w konfiguracji jądra musi być włączona funkcja dm-bow.
Dodaj flagę checkpoint=block do sekcji <fs_mgr_flags> w fstab dla urządzenia zamontowanego w /data.
Sprawdzanie logów
Gdy wywoływane są interfejsy API punktu kontrolnego, generowane są wpisy logu.
Weryfikacja
Aby przetestować implementację UDC, uruchom zestaw testów VTS VtsKernelCheckpointTest.