Dynamiczne aktualizacje systemu (DSU) umożliwiają tworzenie obrazu systemu Android użytkownicy mogą pobierać z internetu i próbować bez ryzyka uszkodzenia urządzenia. do bieżącego obrazu systemu. Z tego dokumentu dowiesz się, jak obsługiwać DSU.
Wymagania jądra systemu
Zobacz Implementowanie partycji dynamicznych pod kątem wymagań jądra systemu operacyjnego.
Dodatkowo DSU korzysta z funkcji jądra systemu „device-mapper-verity” (dm-verity) aby zweryfikować obraz systemu Android. Musisz więc włączyć to jądro Konfiguracje:
CONFIG_DM_VERITY=y
CONFIG_DM_VERITY_FEC=y
Wymagania dotyczące partycji
Począwszy od Androida 11, DSU wymaga /data
do używania systemu plików F2FS lub ext4. F2FS zapewnia lepszą wydajność
jest zalecane, ale różnica powinna być nieistotna.
Oto kilka przykładów czasu trwania dynamicznej aktualizacji systemu na Pixelu urządzenie:
- Korzystanie z F2FS:
- 109s, użytkownik 8G, system 867M, typ systemu plików: F2FS: szyfrowanie=aes-256-xts:aes-256-cts
- 104 s, użytkownik 8 G, system 867 M, typ systemu plików: F2FS: encryption=ice
- Użycie ext4:
- 135s, użytkownik 8G, system 867M, typ systemu plików: ext4: szyfrowanie=aes-256-xts:aes-256-cts
Jeśli na Twojej platformie potrzeba więcej czasu, sprawdź, czy uchwyt flaga zawiera dowolną flagę powodującą zapis „sync”, ale można też podać wartość „async” bezpośrednio, by zwiększyć skuteczność.
Partycja metadata
(co najmniej 16 MB) jest wymagana do przechowywania danych związanych
do zainstalowanych obrazów. Należy ją zamontować podczas pierwszego etapu podłączania.
Partycja userdata
musi używać systemu plików F2FS lub ext4. Jeśli używasz F2FS, uwzględnij wszystkie poprawki związane z F2FS dostępne w ogólnym jądrze Androida.
DSU został opracowany i przetestowany z jądrem/common 4.9. Zalecane jest użycie jądro w wersji 4.9 lub nowszej.
Zachowanie interfejsu HAL dostawcy
Weaver HAL
HAL Weaver zapewnia stałą liczbę przedziałów do przechowywania kluczy użytkownika. Agencja DSU zużywa 2 dodatkowe przedziały na klucze. Jeśli OEM ma interfejs weaver HAL, musi mieć wystarczającą liczbę slotów na ogólny obraz systemu (GSI) i obraz hosta.
HAL bramkarz
HAL bramki musi:
obsługuje duże wartości USER_ID
, ponieważ GSI kompensuje identyfikatory UID do HAL o
+1000000.
Weryfikacja podczas uruchamiania
Jeśli chcesz mieć możliwość uruchamiania obrazów GSI dla programistów
w stanie ZABLOKOWANE bez wyłączania
weryfikacja podczas uruchamiania, dołącz klucze GSI dewelopera, dodając następujący wiersz:
do pliku device/<device_name>/device.mk
:
$(call inherit-product, $(SRC_TARGET_DIR)/product/developer_gsi_keys.mk)
Ochrona przed przywróceniem
Jeśli używasz DSU, pobrany obraz systemu Android musi być nowszy niż
bieżącego obrazu systemu na urządzeniu. Polega to na porównaniu poziomów poprawek zabezpieczeń w weryfikacji podczas uruchamiania Androida (AVB)(descriptor właściwości AVB) obu obrazów systemu: Prop: com.android.build.system.security_patch ->
'2019-04-05'
.
W przypadku urządzeń, które nie korzystają z AVB, podaj poziom aktualizacji zabezpieczeń bieżącego systemu
za pomocą polecenia cmdline jądra lub polecenia rozruchowego przy użyciu programu rozruchowego:
androidboot.system.security_patch=2019-04-05
Wymagania sprzętowe
Gdy uruchomisz instancję DSU, przydzielone zostaną 2 pliki tymczasowe:
- Partycja logiczna do przechowywania
GSI.img
(1~1,5 G) - pusty 8-gigabajtowy
/data
jako piaskownica do uruchamiania GSI;
Przed uruchomieniem DSU zalecamy zarezerwowanie co najmniej 10 GB wolnego miejsca instancji. DSU obsługuje też alokację z karty SD. Gdy karta SD jest obecna, ma najwyższy priorytet przy przydzielaniu. Obsługa karty SD jest kluczowe w przypadku urządzeń o mniejszej mocy, które mogą mieć za mało pamięci wewnętrznej. Jeśli masz kartę SD, upewnij się, że nie jest wykorzystywana. DSU nie obsługuje przyjętych kart SD.
Dostępne frontendy
Możesz uruchomić DSU za pomocą adb
, aplikacji OEM lub narzędzia ładującego DSU jednym kliknięciem (w
w Androidzie 11 lub nowszym).
Uruchamianie DSU za pomocą adb
Aby uruchomić DSU za pomocą narzędzia adb, wpisz te polecenia:
$ simg2img out/target/product/.../system.img system.raw
$ gzip -c system.raw > system.raw.gz
$ adb push system.raw.gz /storage/emulated/0/Download
$ adb shell am start-activity \
-n com.android.dynsystem/com.android.dynsystem.VerificationActivity \
-a android.os.image.action.START_INSTALL \
-d file:///storage/emulated/0/Download/system.raw.gz \
--el KEY_SYSTEM_SIZE $(du -b system.raw|cut -f1) \
--el KEY_USERDATA_SIZE 8589934592
Uruchamianie DSU za pomocą aplikacji
Głównym punktem wejścia do DSU jest android.os.image.DynamicSystemClient.java
Interfejs API:
public class DynamicSystemClient {
...
...
/**
* Start installing DynamicSystem from URL with default userdata size.
*
* @param systemUrl A network URL or a file URL to system image.
* @param systemSize size of system image.
*/
public void start(String systemUrl, long systemSize) {
start(systemUrl, systemSize, DEFAULT_USERDATA_SIZE);
}
Musisz spakować tę aplikację lub wstępnie zainstalować ją na urządzeniu. Ponieważ
DynamicSystemClient
to systemowy interfejs API, nie można utworzyć aplikacji za pomocą zwykłego interfejsu API
SDK API i nie możesz go opublikować w Google Play. Cel tej aplikacji:
- Pobieranie listy obrazów i odpowiadających im adresów URL za pomocą schematu określonego przez dostawcę.
- Dopasuj obrazy na liście do urządzenia i pokaż użytkownikowi kompatybilne obrazy.
Wywołaj
DynamicSystemClient.start
w ten sposób:DynamicSystemClient aot = new DynamicSystemClient(...) aot.start( ...URL of the selected image..., ...uncompressed size of the selected image...);
Adres URL wskazuje skompresowany, nierozdzielony plik obrazu systemowego, za pomocą tych poleceń:
$ simg2img ${OUT}/system.img ${OUT}/system.raw
$ gzip ${OUT}/system.raw
$ ls ${OUT}/system.raw.gz
Nazwa pliku powinna mieć ten format:
<android version>.<lunch name>.<user defined title>.raw.gz
Przykłady:
o.aosp_taimen-userdebug.2018dev.raw.gz
p.aosp_taimen-userdebug.2018dev.raw.gz
Moduł ładujący DSU 1 kliknięciem
Android 11 wprowadza ładowarkę DSU jednym kliknięciem, która jest interfejsem w ustawieniach dewelopera.
Rysunek 1. Uruchamianie programu ładującego DSU
Gdy deweloper kliknie przycisk Moduł ładujący DS, pobierze wstępnie skonfigurowany z internetowego deskryptora JSON DSU oraz wyświetla wszystkie odpowiednie obrazy w pływającego menu. Wybierz obraz, aby rozpocząć instalację DSU i postępować pokazuje się na pasku powiadomień.
Rysunek 2. Postęp instalacji obrazu DSU
Domyślnie ładownik DSU wczytuje opis JSON zawierający obrazy GSI. W tych sekcjach dowiesz się, jak tworzyć i ładować pakiety DSU podpisane przez OEM je z programu ładującego DSU.
Flaga funkcji
Funkcja DSU jest obsługiwana przez flagę funkcji settings_dynamic_android
. Przed
przy użyciu DSU, sprawdź, czy jest włączona odpowiednia flaga funkcji.
Rysunek 3. Włączanie flagi funkcji
Interfejs flagi funkcji może być niedostępny na urządzeniu z wersją użytkową. W takim przypadku użyj polecenia adb
:
$ adb shell setprop persist.sys.fflag.override.settings_dynamic_system 1
Obrazy systemu hosta dostawcy w GCE (opcjonalnie)
Jednym z możliwych miejsc przechowywania obrazów systemu jest zasobnik Google Compute Engine (GCE). Administrator wersji korzysta z konsoli miejsca na dane GCP, aby dodawać, usuwać i zmieniać opublikowany obraz systemu.
Obrazy muszą być dostępne publicznie, jak tutaj:
Rysunek 4. Dostęp publiczny w GCE
Procedura udostępniania elementów jest dostępna w dokumentacji Google Cloud.
Wielopartycjonalna jednostka DSU w pliku ZIP
Począwszy od Androida 11, DSU może mieć więcej niż 1 partycję. Na przykład może zawierać znak product.img
, a dodatkowo
system.img
Po uruchomieniu urządzenia pierwszy etap init
wykrywa
zainstalowano partycje DSU i tymczasowo zastępuje partycję na urządzeniu, gdy
czy zainstalowana aplikacja DSU jest włączona. Pakiet DSU może zawierać partycję, która nie ma odpowiadającej partycji na urządzeniu.
Rysunek 5. Proces DSU z wieloma partycjami
DSU podpisane przez OEM
Aby upewnić się, że wszystkie obrazy uruchomione na urządzeniu są autoryzowane przez urządzenie producenta, wszystkie obrazy w pakiecie DSU muszą być podpisane. Załóżmy, że mamy pakiet DSU zawierający 2 obrazy partycji:
dsu.zip {
- system.img
- product.img
}
Zarówno system.img
, jak i product.img
muszą być podpisane kluczem OEM
do pliku ZIP. Zazwyczaj stosuje się metody asymetryczne
(np. RSA), gdzie tajny klucz jest używany do podpisywania pakietu, a klucz
jest używany do jego weryfikacji. Ramdysk pierwszego etapu musi zawierać klucz publiczny do parowania, na przykład /avb/*.avbpubkey
. Jeśli urządzenie już zastosowało AVB,
wystarczy istniejąca procedura podpisywania. W kolejnych sekcjach przedstawiono proces podpisywania oraz wyróżniono miejsce docelowe klucza publicznego AVB, który służy do weryfikacji obrazów w pakiecie DSU.
Deskryptor JSON DSU
Deskryptor JSON DSU opisuje pakiety DSU. Obsługuje 2 elementy podstawowe.
Po pierwsze: element include
zawiera dodatkowe deskryptory lub przekierowania JSON
program ładujący DSU w nowe miejsce. Na przykład:
{
"include": ["https://.../gsi-release/gsi-src.json"]
}
Po drugie: podstawowy image
służy do opisywania udostępnionych pakietów DSU. Wewnątrz
do obiektu graficznego jest kilka atrybutów:
Atrybuty
name
idetails
to ciągi tekstowe, które są wyświetlane w okno, które użytkownik może wybrać.Atrybuty
cpu_api
,vndk
ios_version
są używane do sprawdzania zgodności, co jest opisane w następnej sekcji.Opcjonalny atrybut
pubkey
opisuje publiczne który będzie parowany z tajnym kluczem używanym do podpisywania pakietu DSU. Gdy go podasz, usługa DSU może sprawdzić, czy urządzenie ma klucz użyte do zweryfikowania pakietu DSU. Zapobiega to instalacji niezidentyfikowanego pakietu DSU, na przykład zainstalowania pakietu DSU podpisanego przez OEM-A na urządzeniu wyprodukowanym przez OEM-B.Opcjonalny atrybut
tos
wskazuje plik tekstowy, który opisuje warunki korzystania z usługi dla odpowiedniego pakietu DSU. Gdy deweloper wybiera pakiet DSU z określonym atrybutem warunków korzystania z usługi, otwiera się okno dialogowe widoczne na Rys. 6, z prośbą o zaakceptowanie warunków usługi przed zainstalowaniem pakietu DSU.Rysunek 6. Okno z Warunkami korzystania z usługi
Oto deskryptor JSON DSU dla GSI:
{
"images":[
{
"name":"GSI+GMS x86",
"os_version":"10",
"cpu_abi": "x86",
"details":"exp-QP1A.190711.020.C4-5928301",
"vndk":[
27,
28,
29
],
"pubkey":"",
"tos": "https://dl.google.com/developers/android/gsi/gsi-tos.txt",
"uri":"https://.../gsi/gsi_gms_x86-exp-QP1A.190711.020.C4-5928301.zip"
},
{
"name":"GSI+GMS ARM64",
"os_version":"10",
"cpu_abi": "arm64-v8a",
"details":"exp-QP1A.190711.020.C4-5928301",
"vndk":[
27,
28,
29
],
"pubkey":"",
"tos": "https://dl.google.com/developers/android/gsi/gsi-tos.txt",
"uri":"https://.../gsi/gsi_gms_arm64-exp-QP1A.190711.020.C4-5928301.zip"
},
{
"name":"GSI ARM64",
"os_version":"10",
"cpu_abi": "arm64-v8a",
"details":"exp-QP1A.190711.020.C4-5928301",
"vndk":[
27,
28,
29
],
"pubkey":"",
"uri":"https://.../gsi/aosp_arm64-exp-QP1A.190711.020.C4-5928301.zip"
},
{
"name":"GSI x86_64",
"os_version":"10",
"cpu_abi": "x86_64",
"details":"exp-QP1A.190711.020.C4-5928301",
"vndk":[
27,
28,
29
],
"pubkey":"",
"uri":"https://.../gsi/aosp_x86_64-exp-QP1A.190711.020.C4-5928301.zip"
}
]
}
Zarządzanie zgodnością
Do określenia zgodności pakietu DSU używa się kilku atrybutów oraz na urządzeniu lokalnym:
cpu_api
to ciąg tekstowy opisujący architekturę urządzenia. Ten atrybut jest wymagany i jest porównywany z właściwością systemowąro.product.cpu.abi
. Ich wartości muszą być identyczne.os_version
to opcjonalna liczba całkowita, która określa wersję Androida. Dla: na przykład w przypadku Androida 10os_version
to10
, a dla Androida 11,os_version
to11
. Gdy to został określony, musi on być równy lub większy niżro.system.build.version.release
właściwość systemową. To sprawdzanie służy do zapobiegania uruchamianiu obrazu GSI Androida 10 na urządzeniu sprzedawcy z Androidem 11, które obecnie nie jest obsługiwane. Rozruchowy obraz GSI Androida 11 jest dozwolony na urządzeniu z Androidem 10.vndk
to opcjonalna tablica, która określa wszystkie zestawy VNDK zawarte w pakietu DSU. Gdy jest podany, moduł wczytujący DSU sprawdza, czy numer wyodrębnione z właściwości systemowejro.vndk.version
.
Unieważnianie kluczy DSU ze względów bezpieczeństwa
W bardzo rzadkich przypadkach, gdy klucz RSA używany do podpisywania obrazów DSU zostanie skompromitowany, należy jak najszybciej zaktualizować dysk RAM, aby usunąć skompromitowany klucz. Oprócz aktualizacji partycji rozruchowej możesz zablokować klucze zagrożone za pomocą listy wycofania kluczy DSU (lista kluczy na czarnej liście) z adresu URL HTTPS.
Lista kluczy odwołania DSU zawiera listę odwoływanych kluczy publicznych AVB. Podczas instalacji DSU klucze publiczne w obrazach DSU są weryfikowane za pomocą listy odwołanych certyfikatów. Jeśli okaże się, że zawierają one unieważnione zdjęcia publiczne spowoduje to zatrzymanie procesu instalacji DSU.
Aby zapewnić bezpieczeństwo, adres URL listy kluczy musi być adresem URL protokołu HTTPS. Jest on określony w ciągu zasobu:
frameworks/base/packages/DynamicSystemInstallationService/res/values/strings.xml@key_revocation_list_url
Wartość ciągu to
https://dl.google.com/developers/android/gsi/gsi-keyblacklist.json
, czyli
listę unieważnień dla kluczy GSI udostępnionych przez Google. Ten ciąg znaków zasobu można nakładać i dostosowywać, aby producenci OEM, którzy korzystają z funkcji DSU, mogli udostępniać i utrzymywać własną listę kluczy zakazanych. Dzięki temu producent OEM może blokować niektóre klucze publiczne bez aktualizowania obrazu dysku RAM urządzenia.
Format listy odwołań:
{
"entries":[
{
"public_key":"bf14e439d1acf231095c4109f94f00fc473148e6",
"status":"REVOKED",
"reason":"Key revocation test key"
},
{
"public_key":"d199b2f29f3dc224cca778a7544ea89470cbef46",
"status":"REVOKED",
"reason":"Key revocation test key"
}
]
}
public_key
to skrót SHA-1 unieważnionego klucza w opisanym formacie podczas generowania klucza publikacyjnego AVB .status
wskazuje stan odwołania klucza. Obecnie jedyną obsługiwaną wartością jestREVOKED
.reason
to opcjonalny ciąg znaków opisujący przyczynę unieważnienia.
Procedury DSU
W tej sekcji opisujemy, jak wykonać różne procedury konfiguracji DSU.
Generowanie nowej pary kluczy
Użyj polecenia openssl
, aby wygenerować parę kluczy (prywatny/publiczny) RSA w .pem
format (np. rozmiar 2048-bitowy):
$ openssl genrsa -out oem_cert_pri.pem 2048
$ openssl rsa -in oem_cert_pri.pem -pubout -out oem_cert_pub.pem
Klucz prywatny może być niedostępny i przechowywany tylko w sprzętowym module zabezpieczeń (HSM). W takim przypadku po wygenerowaniu klucza może być dostępny certyfikat klucza publicznego X.509. Patrz Dodawanie klucza publicznego parowania do pliku ramdisk. , aby uzyskać instrukcje generowania klucza publicznego AVB z certyfikatu x509.
Aby przekonwertować certyfikat x509 na format PEM:
$ openssl x509 -pubkey -noout -in oem_cert_pub.x509.pem > oem_cert_pub.pem
Pomiń ten krok, jeśli certyfikat jest już plikiem PEM.
Dodaj klucz publiczny parowania do dysku ramdy
Aby zweryfikować podpisany pakiet DSU, musisz umieścić oem_cert.avbpubkey
w folderze /avb/*.avbpubkey
. Najpierw przekonwertuj klucz publiczny w formacie PEM na publiczny AVB
format klucza:
$ avbtool extract_public_key --key oem_cert_pub.pem --output oem_cert.avbpubkey
Następnie dołącz klucz publiczny do dysku RAM pierwszego etapu, wykonując czynności opisane poniżej.
Dodaj gotowy moduł, aby skopiować
avbpubkey
. Na przykład dodajdevice/<company>/<board>/oem_cert.avbpubkey
idevice/<company>/<board>/avb/Android.mk
z takimi treściami:include $(CLEAR_VARS) LOCAL_MODULE := oem_cert.avbpubkey LOCAL_MODULE_CLASS := ETC LOCAL_SRC_FILES := $(LOCAL_MODULE) ifeq ($(BOARD_USES_RECOVERY_AS_BOOT),true) LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/first_stage_ramdisk/avb else LOCAL_MODULE_PATH := $(TARGET_RAMDISK_OUT)/avb endif include $(BUILD_PREBUILT)
Ustaw zależność celu droidcore od dodanego
oem_cert.avbpubkey
:droidcore: oem_cert.avbpubkey
Generowanie atrybutu pubkey AVB w deskryptorze JSON
oem_cert.avbpubkey
ma format binarny klucza publicznego AVB. Użyj funkcji SHA-1, aby uczynić go czytelnym przed umieszczeniem w deskryptorze JSON:
$ sha1sum oem_cert.avbpubkey | cut -f1 -d ' '
3e62f2be9d9d813ef5........866ac72a51fd20
To będzie zawartość atrybutu pubkey
deskryptora JSON.
"images":[
{
...
"pubkey":"3e62f2be9d9d813ef5........866ac72a51fd20",
...
},
Podpisz pakiet DSU
Aby podpisać pakiet DSU, użyj jednej z tych metod:
Metoda 1. Użyj artefaktu utworzonego przez pierwotny proces podpisywania AVB, aby utworzyć pakiet DSU. Alternatywnym podejściem jest wyodrębnienie już podpisanych obrazów z opakowania wersji i użycie wyodrębnionych obrazów do bezpośredniego utworzenia pliku ZIP.
Metoda 2. Aby podpisać partycje DSU, użyj tych poleceń, jeśli prywatny jest dostępny. Każdy identyfikator
img
w pakiecie DSU (pliku ZIP) jest podpisany oddzielnie:$ key_len=$(openssl rsa -in oem_cert_pri.pem -text | grep Private-Key | sed -e 's/.*(\(.*\) bit.*/\1/') $ for partition in system product; do avbtool add_hashtree_footer \ --image ${OUT}/${partition}.img \ --partition_name ${partition} \ --algorithm SHA256_RSA${key_len} \ --key oem_cert_pri.pem done
Więcej informacji o dodawaniu add_hashtree_footer
za pomocą avbtool
znajdziesz w artykule Używanie narzędzia avbtool.
Weryfikacja pakietu DSU lokalnie
Zalecamy zweryfikowanie wszystkich lokalnych obrazów za pomocą parowania klucza publicznego za pomocą tych poleceń:
for partition in system product; do
avbtool verify_image --image ${OUT}/${partition}.img --key oem_cert_pub.pem
done
Oczekiwany wynik:
Verifying image dsu/system.img using key at oem_cert_pub.pem
vbmeta: Successfully verified footer and SHA256_RSA2048 vbmeta struct in dsu/system.img
: Successfully verified sha1 hashtree of dsu/system.img for image of 898494464 bytes
Verifying image dsu/product.img using key at oem_cert_pub.pem
vbmeta: Successfully verified footer and SHA256_RSA2048 vbmeta struct in dsu/product.img
: Successfully verified sha1 hashtree of dsu/product.img for image of 905830400 bytes
Tworzenie pakietu DSU
Ten przykład tworzy pakiet DSU zawierający system.img
i
product.img
:
dsu.zip {
- system.img
- product.img
}
Po podpisaniu obu obrazów użyj tego polecenia, aby utworzyć plik ZIP:
$ mkdir -p dsu
$ cp ${OUT}/system.img dsu
$ cp ${OUT}/product.img dsu
$ cd dsu && zip ../dsu.zip *.img && cd -
Dostosowywanie usługi DSU jednym kliknięciem
Domyślnie moduł ładujący DSU wskazuje metadane obrazów GSI, które są
https://...google.com/.../gsi-src.json
Producenci OEM mogą zastąpić tę listę, definiując właściwość persist.sys.fflag.override.settings_dynamic_system.list
, która wskazuje na ich własny opis JSON. Na przykład OEM może
podaj metadane JSON, które zawierają GSI, a także zastrzeżone obrazy OEM, jak na przykład:
{
"include": ["https://dl.google.com/.../gsi-src.JSON"]
"images":[
{
"name":"OEM image",
"os_version":"10",
"cpu_abi": "arm64-v8a",
"details":"...",
"vndk":[
27,
28,
29
],
"spl":"...",
"pubkey":"",
"uri":"https://.../....zip"
},
}
Producent OEM może połączyć opublikowane metadane DSU, jak pokazano na rysunku 7.
Rysunek 7. Łańcuch opublikowanych metadanych DSU