Android 10 wprowadza punkt kontrolny danych użytkownika (UDC), który umożliwia Androidowi przywrócenie poprzedniego stanu, gdy aktualizacja OTA Androida nie powiedzie się. Jeśli aktualizacja OTA Androida zakończy się niepowodzeniem, dzięki UDC urządzenie może bezpiecznie wrócić do poprzedniego stanu. Chociaż aktualizacje A/B rozwiązują ten problem w przypadku wczesnego uruchamiania, wycofanie nie jest obsługiwane, gdy modyfikowana jest partycja danych użytkownika (zamontowana na /data
).
UDC umożliwia urządzeniu przywrócenie partycji danych użytkownika nawet po jej zmodyfikowaniu. Funkcja UDC osiąga to dzięki możliwościom kontroli w systemie plików, alternatywnej implementacji w przypadku, gdy system plików nie obsługuje punktów kontrolnych, integracji z mechanizmem A/B w bootloaderze, a także obsłudze aktualizacji niebędących A/B i zapobiegania odzyskiwaniu kluczy.
Wpływ na użytkownika
Funkcja UDC poprawia jakość aktualizacji OTA dla użytkowników, ponieważ w przypadku niepowodzenia aktualizacji OTA mniej użytkowników traci swoje dane. Może to zmniejszyć liczbę połączeń z zespołem pomocy od użytkowników, którzy napotykają problemy podczas procesu aktualizacji. Jeśli jednak aktualizacja OTA się nie powiedzie, użytkownicy mogą zauważyć, że urządzenie kilka razy uruchamia się ponownie.
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 jądra Linux 4.20 i przenosi ją do wszystkich popularnych jąder obsługiwanych przez urządzenia z Androidem 10.
W innych systemach plików do obsługi punktów kontrolnych UDC używa urządzenia wirtualnego z programem mapowania urządzeń o nazwie dm_bow
. dm_bow
znajduje się między urządzeniem a systemem plików. Gdy partycja jest zamontowana, jest wydawane polecenie przycinania, które powoduje wydanie poleceń przycinania przez system plików we wszystkich wolnych blokach. dm_bow
przechwytuje te przycinania i używa ich do konfigurowania listy blokowania bezpłatnych. Odczyty i zapisy są następnie wysyłane do urządzenia bez zmian, ale zanim zostanie zezwolone na zapis, dane potrzebne do przywrócenia są kopiowane do wolnego bloku.
Proces punktu kontrolnego
Gdy partycja z flagą checkpoint=fs/block
jest zamontowana, Android wywołuje restoreCheckpoint
na dysku, aby umożliwić urządzeniu przywrócenie bieżącego punktu kontrolnego. init
wywołuje funkcję needsCheckpoint
, aby określić, czy urządzenie jest w stanie bootloadera A/B, czy też ma ustawioną liczbę prób aktualizacji. Jeśli jedno z tych ustawień ma wartość Prawda, Android wywołuje createCheckpoint
, aby dodać flagi montowania lub skompilować urządzenie dm_bow
.
Po zamontowaniu partycji wywoływany jest kod punktu kontrolnego, który służy do wydawania cięć.
Następnie proces uruchamiania trwa normalnie. W miejscu LOCKED_BOOT_COMPLETE
Android wywołuje funkcję commitCheckpoint
, aby zatwierdzić bieżący punkt kontrolny, a aktualizacja będzie kontynuowana w normalny sposób.
Zarządzanie kluczami Keymaster
Klucze Keymaster służą do szyfrowania urządzenia i do innych celów. Aby zarządzać tymi kluczami, Android opóźnia wywołania usuwania kluczy do momentu zatwierdzenia punktu kontrolnego.
Monitorowanie stanu
Demon zdrowia sprawdza, czy jest wystarczająco dużo miejsca na dysku na utworzenie punktu kontrolnego. Demon zdrowia znajduje się w cp_healthDaemon
w Checkpoint.cpp
.
Demon diagnostyki ma następujące zachowania, które można skonfigurować:
ro.sys.cp_msleeptime
: określa, jak często urządzenie ma sprawdzać wykorzystanie dysku.ro.sys.cp_min_free_bytes
: określa minimalną wartość wyszukiwaną przez demona zdrowia.ro.sys.cp_commit_on_full
: określa, czy demon zdrowia ma ponownie uruchomić urządzenie, czy zatwierdzić punkt kontrolny i kontynuować, gdy dysk jest pełny.
Interfejsy API punktów kontrolnych
Funkcja UDC używa interfejsów API punktów kontrolnych. Inne interfejsy API używane przez UDC znajdziesz w IVold.aidl
.
void startCheckpoint(int retry)
tworzy punkt kontrolny.
Framework wywołuje tę metodę, gdy jest gotowy do rozpoczęcia aktualizacji. Punkt kontrolny jest tworzony przed zamontowaniem w trybie R/W po restarcie takich zweryfikowanych systemów plików, jak userdata. Jeśli liczba ponownych prób jest dodatnia, interfejs API obsługuje ponawiane próby śledzenia, a aktualizator wywołuje needsRollback
, aby sprawdzić, czy wymagane jest wycofanie aktualizacji. Jeśli liczba prób jest równa -1
, interfejs API odwołuje się do decyzji ładowarki rozruchowej A/B.
Ta metoda nie jest wywoływana podczas zwykłej aktualizacji A/B.
void CommitChanges()
Zatwierdź zmiany.
Framework wywołuje tę metodę po ponownym uruchomieniu, gdy zmiany są gotowe do zatwierdzenia. Jest on wywoływany przed zapisaniem danych (takich jak zdjęcia, filmy, SMS-y, potwierdzenie odbioru serwera) w plikach danych użytkownika i przed wywołaniem funkcji BootComplete
.
Jeśli nie ma aktywnej aktualizacji z punktami kontrolnymi, ta metoda nie ma zastosowania.
abortChanges()
Wymusza ponowne uruchomienie i powraca do punktu kontrolnego. Odrzuca wszystkie zmiany danych użytkownika od pierwszego ponownego uruchomienia.
Platforma wywołuje tę metodę po ponownym uruchomieniu, ale przed commitChanges
.
Wartość retry_counter
maleje, gdy wywoływana jest ta metoda. Tworzone są wpisy w logu.
bool needsRollback()
Określa, czy wymagane jest wycofanie.
Na urządzeniach bez punktów kontrolnych zwraca false
. W przypadku urządzeń punktów kontrolnych zwraca wartość true
podczas rozruchu innego niż punkt kontrolny.
Wdrożenie UDC
Implementacja referencyjna
Przykład implementacji UDC znajdziesz w pliku dm-bow.c. Dodatkową dokumentację funkcji znajdziesz w pliku dm-bow.txt.
Konfiguracja
W pliku on fs
w pliku init.hardware.rc
sprawdź, czy masz:
mount_all /vendor/etc/fstab.${ro.boot.hardware.platform} --early
W pliku 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
sprawdź, czy /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 prób i kluczy niebootloadera. Skonfiguruj partycję metadanych i zamontuj ją wcześnie w /metadata
.
W pliku fstab.hardware
sprawdź, czy /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
Inicjalizowanie partycji przez wypełnienie jej 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ą formatu danych z F2FS, sprawdź, czy Twoja wersja tego systemu 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>
w pliku fstab dla urządzenia zamontowanego w miejscu /data
.
Systemy inne niż F2FS
W przypadku systemów innych niż F2FS należy włączyć opcję dm-bow
w konfiguracji jądra.
Dodaj flagę checkpoint=block
do sekcji <fs_mgr_flags>
w pliku fstab dla urządzenia zamontowanego w miejscu /data
.
Sprawdzanie dzienników
Wpisy w logu są generowane, gdy wywoływane są interfejsy API Checkpoint.
Weryfikacja
Aby przetestować implementację UDC, uruchom zestaw VtsKernelCheckpointTest
testów VTS.