Format pliku APEX

Format kontenera Android Pony EXpress (APEX) został wprowadzony na Androida. 10 i jest używany podczas instalacji w systemach niższego poziomu. modułów. Ten format ułatwia aktualizację komponentów systemu, które nie pasują do siebie do standardowego modelu aplikacji na Androida. Niektóre przykładowe komponenty są natywne usługi i biblioteki, warstwy abstrakcji sprzętu (HAL), czas działania (ART) i biblioteki klas.

Termin „APEX” może też odnosić się do pliku APEX.

Tło

Android obsługuje aktualizacje modułów, które pasują do standardowej aplikacji. (np. usługi czy aktywności) za pomocą aplikacji instalatora pakietów (np. aplikacji Sklep Google Play) przy użyciu podobnego modelu w przypadku komponentów systemu operacyjnego niższego poziomu ma następujące wady:

  • Modułów opartych na pliku APK nie można używać na wczesnym etapie sekwencji rozruchu. Przesyłka Menedżer to główne repozytorium informacji o aplikacjach. rozpoczyna się w menedżerze aktywności, który jest gotowy na późniejszym etapie i procedurę uruchamiania.
  • Format APK (zwłaszcza plik manifestu) jest przeznaczony dla aplikacji na Androida i moduły systemowe nie zawsze są dobrze dopasowane.

Projektowanie

W tej sekcji znajdziesz ogólny opis formatu pliku APEX oraz Menedżer APEX – usługa zarządzająca plikami APEX.

Więcej informacji na temat tego, dlaczego wybrany został ten sposób wyświetlania w przypadku APEX, znajdziesz w Alternatywy brane pod uwagę przy rozwijaniu APEX.

Format APEX

Jest to format pliku APEX.

Format pliku APEX

Rysunek 1. Format pliku APEX

Najwyższego poziomu plik APEX to plik ZIP, w którym przechowywane są pliki. nieskompresowany i znajdujący się na granicach 4 KB.

Plik APEX zawiera te 4 pliki:

  • apex_manifest.json
  • AndroidManifest.xml
  • apex_payload.img
  • apex_pubkey

Plik apex_manifest.json zawiera nazwę i wersję pakietu, które identyfikować pliki APEX. To jest ApexManifest bufor protokołu w formacie JSON.

Plik AndroidManifest.xml zezwala pliku APEX na korzystanie z narzędzi związanych z pakietem APK taką jak ADB, PackageManager oraz aplikacje instalatora pakietów (takie jak Sklep Play). Na przykład plik APEX może korzystać z dotychczasowego narzędzia, takiego jak aapt skontrolowanie podstawowych metadanych z pliku. Plik zawiera nazwę pakietu i w informacjach o wersji. Te informacje są zwykle dostępne również w apex_manifest.json

Aby uzyskać nowy kod, zalecana cena apex_manifest.json to więcej niż AndroidManifest.xml które obsługują APEX. AndroidManifest.xml może zawierać dodatkowe informacji na temat kierowania, które mogą być wykorzystywane przez istniejące narzędzia do publikowania aplikacji.

apex_payload.img to obraz systemu plików ext4 korzystający z dm-verity. Obraz jest podłączana w czasie działania za pomocą urządzenia w pętli. Drzewo haszu i Bloki metadanych tworzy się za pomocą biblioteki libavb. Ładunek systemu plików nie jest przeanalizowany (ponieważ obraz powinien być możliwy do zamontowania). Zwykłe pliki są zawarte w pliku apex_payload.img.

apex_pubkey to klucz publiczny używany do podpisywania obrazu systemu plików. W czasie działania ten klucz gwarantuje, że pobrany APEX jest podpisany tym samym elementem który podpisuje ten sam wskaźnik APEX we wbudowanych partycjach.

Wytyczne dotyczące nazewnictwa APEX

Aby zapobiec konfliktom z nazwami nowych APEX w miarę rozwoju platformy, użyj tych wytycznych dotyczących nazewnictwa:

  • com.android.*
    • Rezerwowany dla AOSP APEX. Nie jest unikalne dla żadnej firmy ani na żadnym urządzeniu.
  • com.<companyname>.*
    • Zarezerwowane dla firmy. może być używany przez wiele urządzeń z tego kraju, firmy.
  • com.<companyname>.<devicename>.*
    • Zarezerwowana dla punktów APEX, które są unikalne dla określonego urządzenia (lub podzbioru urządzeń).

Menedżer APEX

Menedżer APEX (apexd) to samodzielny proces natywny odpowiedzialny za: weryfikacji, instalowania i odinstalowywania plików APEX. Proces ten rozpoczyna się, jest gotowa na wczesnym etapie sekwencji uruchamiania. Pliki APEX są zazwyczaj instalowane fabrycznie urządzenia w grupie /system/apex. Menedżer APEX domyślnie używa tych w przypadku braku aktualizacji.

W sekwencji aktualizacji punktu APEX jest używany parametr Klasa PackageManager i występuje jak niżej.

  1. Plik APEX jest pobierany przez aplikację instalatora pakietów, ADB lub inne źródła.
  2. Menedżer pakietów rozpocznie procedurę instalacji. Gdy zauważyłem, że jest to APEX, menedżer pakietów przekazuje kontrolę do APEX .
  3. Menedżer APEX weryfikuje plik APEX.
  4. Jeśli plik APEX jest zweryfikowany, wewnętrzna baza danych menedżera APEX to jest zaktualizowany, tak aby odzwierciedlało, że plik APEX jest aktywowany przy następnym uruchomieniu.
  5. Żądanie instalacji otrzymuje komunikat po pomyślnym pakiecie weryfikacji.
  6. Aby kontynuować instalację, należy ponownie uruchomić system.
  7. Przy następnym uruchomieniu menedżer APEX uruchamia się, odczytuje wewnętrzną bazę danych i wykona następujące elementy dla każdego wymienionego pliku APEX:

    1. Sprawdza plik APEX.
    2. Tworzy urządzenie pętli z pliku APEX.
    3. Tworzy urządzenie blokowe twórcy mapowania urządzeń na urządzeniu zapętlającym.
    4. Mocuje blokowe urządzenie mapera urządzeń w unikalnej ścieżce (na przykład /apex/name@ver).

Po podłączeniu wszystkich plików APEX wymienionych w wewnętrznej bazie danych interfejs APEX udostępnia usługę powiązania, która pozwala na wykonywanie zapytań dotyczących innych komponentów systemu o zainstalowanych plikach APEX. Na przykład drugi system może wysyłać zapytania o listę plików APEX zainstalowanych na urządzeniu lub wysyłać zapytania do dokładną ścieżkę, do której jest podłączony określony punkt APEX, tak by można było uzyskać dostęp do plików.

Pliki APEX to pliki APK

Pliki APEX są prawidłowymi plikami APK, ponieważ są to podpisane archiwa ZIP (z zastosowaniem schematu podpisu APK) zawierający plik AndroidManifest.xml. Dzięki temu APEX z plikami do korzystania z infrastruktury plików APK, np. instalatorem pakietów narzędzia do podpisywania i menedżera pakietów.

Plik AndroidManifest.xml w pliku APEX jest ograniczony i składa się z elementów pakiet name, versionCode i opcjonalnie targetSdkVersion, minSdkVersion, i maxSdkVersion w przypadku szczegółowego kierowania. Dzięki tej informacji APEX za pomocą istniejących kanałów, takich jak aplikacje instalacyjne pakietów ADB.

Obsługiwane typy plików

Format APEX obsługuje następujące typy plików:

  • Natywne udostępniane biblioteki
  • Natywne pliki wykonywalne
  • Pliki JAR
  • Pliki danych
  • Pliki konfiguracyjne

Nie oznacza to, że APEX może aktualizować wszystkie te typy plików. Określa, czy plik że można aktualizować typ w zależności od platformy i tego, jak stabilne są definicje i interfejsy dla różnych typów plików.

Opcje podpisywania

Pliki APEX są logowane na 2 sposoby. Po pierwsze, apex_payload.img (a konkretnie plik deskryptor vbmeta dołączony do pliku apex_payload.img) jest podpisany kluczem. Następnie cały APEX jest podpisany za pomocą Schemat podpisu pliku APK w wersji 3 Używane są 2 różne klucze w tym procesie.

Po stronie urządzenia klucz publiczny odpowiadający kluczowi prywatnemu służącemu do podpisywania. deskryptor vbmeta jest zainstalowany. Menedżer APEX używa klucza publicznego do weryfikować punkty dostępu APEX, które mają zostać zainstalowane. Każdy APEX musi być podpisany za pomocą różnych kluczy i jest egzekwowane zarówno w czasie kompilacji, jak i w czasie działania.

APEX we wbudowanych partycjach

Pliki APEX mogą znajdować się we wbudowanych partycjach, np. /system. partycja jest już ponad dm-verity, więc pliki APEX są podłączane bezpośrednio nad urządzeniem typu loopback.

Jeśli we wbudowanej partycji znajduje się APEX, można go zaktualizować przez dostarcza pakiet APEX o tej samej nazwie pakietu i większej lub równej do kodu wersji. Nowy raport APEX jest przechowywany w /data i – podobnie jak w przypadku plików APK – Nowo zainstalowana wersja zastępuje wersję już istniejącą partycji danych. W przeciwieństwie do plików APK nowo zainstalowana wersja APEX jest dostępna aktywowany po ponownym uruchomieniu.

Wymagania jądra systemu

Aby obsługiwać moduły APEX mainline na urządzeniu z Androidem, wymagane są funkcje jądra: sterownik pętli zwrotnej i dm-verity. Zapętlanie sterownik podłącza obraz systemu plików w module APEX, a dm-verity weryfikuje z modułu APEX.

Wydajność sterownika pętli i dm-weryfikacji ma duże znaczenie dla osiągnięcia dobrą wydajność systemu w przypadku modułów APEX.

Obsługiwane wersje jądra

Moduły APEX mainline są obsługiwane na urządzeniach z jądrem w wersji 4.4 lub wyższe. nowych urządzeniach z Androidem 10 lub nowszym; musi używać jądra w wersji 4.9 lub nowszej do obsługi modułów APEX.

Wymagane poprawki jądra systemu

Wymagane poprawki jądra obsługujących moduły APEX znajdują się w Popularne drzewo Androida. Aby pobrać poprawki do obsługi APEX, użyj najnowszej wersji systemu Android.

Jądro w wersji 4.4

Ta wersja jest obsługiwana tylko na urządzeniach, które zostały uaktualnione z Androida 9 do Androida 10 i chcesz obsługiwać moduły APEX. Aby uzyskać poprawek, scalanie w dół z gałęzi android-4.4 jest silnie zalecane. Oto lista wymaganych pojedynczych poprawek dla jądra w wersji 4.4.

  • UPSTREAM: pętla: dodaj ioctl, by zmienić rozmiar bloku logicznego (4,4)
  • BACKPORT: block/loop: ustaw hw_sectors (4,4)
  • UPSTREAM: pętla: dodaj LOOP_SET_BLOCK_SIZE w zgodnym ioctl (4,4)
  • ANDROID: mnt: Napraw next_descendent (4,4)
  • ANDROID: mnt: remount powinna rozpowszechnić się wśród niewolników (4,4)
  • ANDROID: mnt: poprawnie przeprowadź ponowną instalację (4,4)
  • Przywróć „ANDROID: dm verity: dodaj minimalny rozmiar pobierania z wyprzedzeniem” (4,4)
  • UPSTREAM: pętla: upuszczanie pamięci podręcznych w przypadku zmiany przesunięcia lub rozmiaru block_size (4,4)

Jądro w wersjach 4.9/4.14/4.19

Aby uzyskać wymagane poprawki do jądra w wersji 4.9/4.14/4.19, scal z gałąź android-common.

Wymagane opcje konfiguracji jądra

Na liście poniżej znajdziesz podstawowe wymagania konfiguracyjne w przypadku Moduły APEX wprowadzone w Androidzie 10. Elementy oznaczone gwiazdką (*) są dotychczasowe wymagania Androida w wersji 9 i starszych.

(*) CONFIG_AIO=Y # AIO support (for direct I/O on loop devices)
CONFIG_BLK_DEV_LOOP=Y # for loop device support
CONFIG_BLK_DEV_LOOP_MIN_COUNT=16 # pre-create 16 loop devices
(*) CONFIG_CRYPTO_SHA1=Y # SHA1 hash for DM-verity
(*) CONFIG_CRYPTO_SHA256=Y # SHA256 hash for DM-verity
CONFIG_DM_VERITY=Y # DM-verity support

Wymagania dotyczące parametrów wiersza poleceń jądra

Aby obsługiwać APEX, upewnij się, że parametry wiersza poleceń jądra spełniają te wymagania wymagania:

  • Pole loop.max_loop NIE może być ustawione
  • Wartość loop.max_part musi być mniejsza niż 8

Zyskaj APEX

Z tej sekcji dowiesz się, jak utworzyć APEX za pomocą systemu kompilacji Androida. Poniżej znajdziesz przykład użycia funkcji Android.bp w przypadku obszaru APEX o nazwie apex.test.

apex {
    name: "apex.test",
    manifest: "apex_manifest.json",
    file_contexts: "file_contexts",
    // libc.so and libcutils.so are included in the apex
    native_shared_libs: ["libc", "libcutils"],
    binaries: ["vold"],
    java_libs: ["core-all"],
    prebuilts: ["my_prebuilt"],
    compile_multilib: "both",
    key: "apex.test.key",
    certificate: "platform",
}

Przykład strony apex_manifest.json:

{
  "name": "com.android.example.apex",
  "version": 1
}

Przykład strony file_contexts:

(/.*)?           u:object_r:system_file:s0
/sub(/.*)?       u:object_r:sub_file:s0
/sub/file3       u:object_r:file3_file:s0

Typy i lokalizacje plików w APEX

Typ pliku Lokalizacja w APEX
Biblioteki udostępnione /lib i /lib64 (/lib/arm dla przetłumaczona ramię w x86)
Pliki wykonywalne /bin
Biblioteki Java /javalib
Gotowe /etc

Zależności pośrednie

Pliki APEX automatycznie uwzględniają przechodnie zależności natywnych współdzielonych bibliotek lub wykonywalne. Jeśli na przykład libFoo zależy od libBar, te 2 lib to: jest uwzględniane, gdy we właściwości native_shared_libs występuje tylko wartość libFoo.

Obsługa kilku interfejsów ABI

Zainstaluj właściwość native_shared_libs zarówno dla zasobu głównego, jak i dodatkowego interfejsów binarnych aplikacji (ABI) urządzenia. Jeśli segment APEX jest kierowany na urządzenia z pojedynczym interfejsem ABI (czyli tylko 32- lub 64-bitowym) tylko biblioteki z zainstalowany jest odpowiedni interfejs ABI.

Zainstaluj właściwość binaries tylko dla głównego interfejsu ABI urządzenia jako opisane poniżej:

  • Jeśli urządzenie jest tylko 32-bitowe, Zainstalowano.
  • Jeśli urządzenie ma tylko wersję 64-bitową, Zainstalowano.

Aby zapewnić szczegółową kontrolę nad interfejsami ABI bibliotek natywnych i plikami binarnymi, użyj multilib.[first|lib32|lib64|prefer32|both].[native_shared_libs|binaries] usług.

  • first: pasuje do głównego interfejsu ABI urządzenia. Jest to ustawienie domyślne dla pliki binarne.
  • lib32: pasuje do 32-bitowego interfejsu ABI urządzenia, jeśli jest obsługiwany.
  • lib64: pasuje do 64-bitowego interfejsu ABI urządzenia (obsługiwane).
  • prefer32: pasuje do 32-bitowego interfejsu ABI urządzenia, jeśli jest obsługiwany. Jeśli 32-bitowy ABI nie jest obsługiwany; pasuje do 64-bitowego interfejsu ABI.
  • both: pasuje do obu interfejsów ABI. Jest to ustawienie domyślne dla native_shared_libraries

Właściwości java, libraries i prebuilts są niezależne od interfejsu ABI.

Ten przykład dotyczy urządzenia, które obsługuje tryb 32/64 i nie preferuje formatu 32:

apex {
    // other properties are omitted
    native_shared_libs: ["libFoo"], // installed for 32 and 64
    binaries: ["exec1"], // installed for 64, but not for 32
    multilib: {
        first: {
            native_shared_libs: ["libBar"], // installed for 64, but not for 32
            binaries: ["exec2"], // same as binaries without multilib.first
        },
        both: {
            native_shared_libs: ["libBaz"], // same as native_shared_libs without multilib
            binaries: ["exec3"], // installed for 32 and 64
        },
        prefer32: {
            native_shared_libs: ["libX"], // installed for 32, but not for 64
        },
        lib64: {
            native_shared_libs: ["libY"], // installed for 64, but not for 32
        },
    },
}

podpisywanie vbmeta

Podpisz każdy APEX innymi kluczami. Gdy wymagany jest nowy klucz, utwórz i utworzyć moduł apex_key. Używaj właściwości key do: podpisz APEX za pomocą tego klucza. Klucz publiczny jest automatycznie dodawany do APEX o nazwie avb_pubkey.

# create an rsa key pair
openssl genrsa -out foo.pem 4096

# extract the public key from the key pair
avbtool extract_public_key --key foo.pem --output foo.avbpubkey

# in Android.bp
apex_key {
    name: "apex.test.key",
    public_key: "foo.avbpubkey",
    private_key: "foo.pem",
}

W powyższym przykładzie nazwa klucza publicznego (foo) staje się identyfikatorem klucza . Identyfikator klucza używanego do podpisania raportu APEX jest zapisywany w APEX. W czasie działania apexd weryfikuje APEX za pomocą klucza publicznego z tym samym identyfikatorem na urządzeniu.

Podpisywanie APEX

Podpisuj APEX w taki sam sposób, w jaki podpisujesz pliki APK. Dwukrotnie podpisz APEX. raz dla minisystemie plików (apex_payload.img plik) i jeden raz dla całego pliku.

Aby podpisać APEX na poziomie pliku, ustaw właściwość certificate w jednym ze te 3 sposoby:

  • Nie ustawiono: jeśli nie jest ustawiona żadna wartość, punkt APEX jest podpisany za pomocą certyfikatu znajdującego się o PRODUCT_DEFAULT_DEV_CERTIFICATE. Jeśli nie zostanie ustawiona żadna flaga, domyślna ścieżka do build/target/product/security/testkey.
  • <name>: APEX jest podpisany certyfikatem <name> w tym samym katalogu jako PRODUCT_DEFAULT_DEV_CERTIFICATE.
  • :<name>: APEX jest podpisany certyfikatem zdefiniowanym przez Moduł utworu o nazwie <name>. Moduł certyfikatu można zdefiniować jako co dalej.
.
android_app_certificate {
    name: "my_key_name",
    certificate: "dir/cert",
    // this will use dir/cert.x509.pem (the cert) and dir/cert.pk8 (the private key)
}

Zainstaluj APEX

Aby zainstalować APEX, użyj ADB.

adb install apex_file_name
adb reboot

Jeśli supportsRebootlessUpdate ma wartość true w tabeli apex_manifest.json, a parametry obecnie zainstalowany APEX nie jest używany (na przykład zawarte w nim usługi mają został zatrzymany), nowy APEX można zainstalować bez ponownego uruchamiania, --force-non-staged.

adb install --force-non-staged apex_file_name

Wykorzystaj APEX

Po ponownym uruchomieniu interfejs APEX jest podłączony w: /apex/<apex_name>@<version> katalogu. Jednocześnie można podłączyć wiele wersji tego samego punktu APEX. Spośród ścieżek podłączenia ta, która odpowiada najnowszej wersji, to powiązane konto użytkownika o /apex/<apex_name>.

Klienci mogą używać ścieżki podłączonej do powiązania do odczytu i wykonywania plików z APEX.

Wskaźniki APEX są zwykle używane w ten sposób:

  1. OEM lub ODM wstępnie wczytuje APEX poniżej /system/apex, gdy urządzenie wysłano.
  2. Dostęp do plików w APEX uzyskuje się przez ścieżkę /apex/<apex_name>/.
  3. Jeśli w /data/apex jest zainstalowana zaktualizowana wersja raportu APEX, ścieżka wskazuje nowy punkt APEX po ponownym uruchomieniu.

Aktualizowanie usługi przy użyciu numeru APEX

Aby zaktualizować usługę przy użyciu punktu dostępu APEX:

  1. Oznacz usługę na partycji systemowej jako możliwą do aktualizacji. Dodaj opcję updatable do definicji usługi.

    /system/etc/init/myservice.rc:
    
    service myservice /system/bin/myservice
        class core
        user system
        ...
        updatable
    
  2. Utwórz nowy plik .rc dla zaktualizowanej usługi. Użyj opcji override , aby ponownie zdefiniować istniejącą usługę.

    /apex/my.apex/etc/init.rc:
    
    service myservice /apex/my.apex/bin/myservice
        class core
        user system
        ...
        override
    

Definicje usług można zdefiniować tylko w pliku .rc APEX. Działanie nie są obsługiwane w krajach/regionach docelowych.

Jeśli usługa oznaczona jako dostępna do aktualizacji uruchomi się przed aktywacją punktów APEX, makro rozpoczęcie jest opóźnione do czasu zakończenia aktywacji punktów APEX.

Skonfiguruj system do obsługi aktualizacji APEX

Ustaw właściwość systemową na true, aby obsługiwać aktualizacje plików APEX.

<device.mk>:

PRODUCT_PROPERTY_OVERRIDES += ro.apex.updatable=true

BoardConfig.mk:
TARGET_FLATTEN_APEX := false

lub po prostu

<device.mk>:

$(call inherit-product, $(SRC_TARGET_DIR)/product/updatable_apex.mk)

Spłaszczony APEX

W przypadku starszych urządzeń zaktualizowanie starych danych jest czasem niemożliwe lub niemożliwe ją jądro, aby w pełni obsługiwać APEX. Na przykład jądro zostało stworzone bez narzędzia CONFIG_BLK_DEV_LOOP=Y, co jest niezbędne do podłączenia systemu plików wewnątrz obszaru APEX.

Spłaszczony APEX to specjalnie utworzony APEX, który można aktywować na urządzeniach do starszego jądra systemu. Pliki w rozdzielonym APEX są instalowane bezpośrednio w katalogu na wbudowanej partycji. Na przykład lib/libFoo.so w rozdzielonym punkcie APEX Aplikacja my.apex została zainstalowana w: /system/apex/my.apex/lib/libFoo.so.

Aktywowanie płaskiego punktu APEX nie obejmuje urządzenia z pętlą. Całość katalog /system/apex/my.apex jest bezpośrednio połączony z serwerem /apex/name@ver.

Spłaszczonych punktów APEX nie można aktualizować, pobierając zaktualizowane wersje punktów APEX z sieci, ponieważ nie można ich rozdzielić. Rozdzielone punkty APEX można aktualizować tylko za pomocą zwykłego OTA.

Spłaszczony APEX to konfiguracja domyślna. Oznacza to, że wszystkie Punkty APEX są domyślnie rozdzielane, chyba że osobno skonfigurujesz urządzenie aby tworzyć niespłaszczone APEX na potrzeby ich aktualizacji (jak wyjaśniliśmy powyżej).

Łączenie w urządzeniu spłaszczonych i niespłaszczonych węzłów APEX NIE JEST obsługiwane. Punkty APEX w urządzeniu muszą być albo niespłaszczone, albo w całości spłaszczone. Jest to szczególnie ważne w przypadku dostawy wstępnie podpisanych baz APEX takich jak Mainline. APEX, które nie są wstępnie podpisane (czyli utworzone na podstawie źródła) powinny być też niespłaszczone i podpisane odpowiednimi kluczami. urządzenie powinno dziedziczyć ustawienie updatable_apex.mk, zgodnie z opisem w sekcji Aktualizowanie usługi za pomocą punktu APEX.

Skompresowane APEX

Android 12 i nowsze używają kompresji APEX do zmniejszanie wpływu aktualizacji APEX na miejsce na dane. Po zaktualizowaniu do Rozszerzenie APEX jest zainstalowane, ale jego wstępnie zainstalowana wersja nie jest już używana, nadal zajmuje taką samą ilość miejsca. Zajmowane miejsce pozostaje niedostępne.

Kompresja APEX minimalizuje wpływ na pamięć masową dzięki zastosowaniu mocno skompresowanego zestawu plików APEX na partycjach tylko do odczytu (takich jak partycja /system). Android, w wersji 12 i nowszych używają algorytmu kompresji ZIP DEFLATE.

Kompresja nie zapewnia optymalizacji:

  • Wczytywanie APEX, które muszą być zamontowane bardzo na wczesnym etapie uruchamiania kolejne wartości.

  • Nieaktualizowane węzły APEX. Kompresja jest korzystna tylko wtedy, gdy zainstalowana jest zaktualizowana wersja APEX na partycji /data. Pełna lista aktualnych APEX jest dostępna na Elementy systemu modułowego stronę.

  • Dynamic shared libs APEX. Ponieważ apexd zawsze aktywuje obie wersje takich aplikacji APEX (wstępnie zainstalowanych i uaktualnionych), kompresowanie ich nie przynosi efektu.

Skompresowany format pliku APEX

Jest to format skompresowanego pliku APEX.

Schemat przedstawiający format skompresowanego pliku APEX

Rysunek 2. Skompresowany format pliku APEX

Na najwyższym poziomie skompresowany plik APEX to plik ZIP zawierający plik apex w formie z niedoprecyzowanym poziomem kompresji 9 oraz innymi plikami i nieskompresowane.

Cztery pliki składają się na plik APEX:

  • original_apex: obniżona cena z poziomem kompresji 9 To jest oryginalny, nieskompresowany plik APEX.
  • apex_manifest.pb: tylko zapisane
  • AndroidManifest.xml: tylko zapisane
  • apex_pubkey: tylko zapisane

Pliki apex_manifest.pb, AndroidManifest.xml i apex_pubkey są kopii odpowiednich plików w usłudze original_apex.

Utwórz skompresowany APEX

Skompresowany APEX można utworzyć za pomocą narzędzia apex_compression_tool.py znajdującego się na stronie system/apex/tools

W systemie kompilacji dostępnych jest kilka parametrów związanych z kompresją APEX.

W Android.bp o tym, czy plik APEX można skompresować, steruje klucz Właściwość compressible:

apex {
    name: "apex.test",
    manifest: "apex_manifest.json",
    file_contexts: "file_contexts",
    compressible: true,
}

Flaga produktu PRODUCT_COMPRESSED_APEX określa, czy obraz systemu został utworzony ze źródła musi zawierać skompresowane pliki APEX.

W przypadku eksperymentów lokalnych możesz wymusić kompresję przez kompresję punktów APEX przez ustawienie OVERRIDE_PRODUCT_COMPRESSED_APEX= do true.

Skompresowane pliki APEX wygenerowane przez system kompilacji mają rozszerzenie .capex. Rozszerzenie ułatwia rozróżnienie między skompresowanymi i nieskompresowanymi. różnych wersji pliku APEX.

Obsługiwane algorytmy kompresji

Android 12 obsługuje tylko kompresję deflate-zip.

Aktywowanie skompresowanego pliku APEX podczas uruchamiania

Zanim będzie można aktywować skompresowany plik APEX, zawarty w nim plik original_apex zdekompresowany do katalogu /data/apex/decompressed. W wyniku zdekompresowany plik APEX jest na stałe połączony z katalogiem /data/apex/active.

Poniższy przykład ilustruje proces opisany powyżej.

Traktuj /system/apex/com.android.foo.capex jako skompresowany obszar APEX aktywowano z kodem wersji 37.

  1. Plik original_apex w lokalizacji /system/apex/com.android.foo.capex to zdekompresowano do formatu /data/apex/decompressed/com.android.foo@37.apex.
  2. restorecon /data/apex/decompressed/com.android.foo@37.apex wykonuje się, aby Sprawdź, czy ma prawidłową etykietę SELinux.
  3. Weryfikacja jest przeprowadzana /data/apex/decompressed/com.android.foo@37.apex, aby upewnić się, że są prawidłowe: apexd sprawdza klucz publiczny w pakiecie /data/apex/decompressed/com.android.foo@37.apex, aby sprawdzić, czy jest równa do aplikacji w pakiecie /system/apex/com.android.foo.capex.
  4. Plik /data/apex/decompressed/com.android.foo@37.apex jest na stałe połączony z: w katalogu /data/apex/active/com.android.foo@37.apex.
  5. Zwykła logika aktywacji nieskompresowanych plików APEX jest wykonywana /data/apex/active/com.android.foo@37.apex

Interakcja z internetem OTA

Skompresowane pliki APEX mają wpływ na przesyłanie OTA i jego zastosowanie. Od aktualizacja OTA może zawierać skompresowany plik APEX w wersji wyższego poziomu. niż aktywna na urządzeniu, musi być zarezerwowana pewna ilość wolnego miejsca przed ponownym uruchomieniem urządzenia w celu zastosowania aktualizacji OTA.

Aby obsługiwać system OTA, apexd udostępnia 2 interfejsy API powiązań:

  • calculateSizeForCompressedApex – oblicza rozmiar wymagany do dekompresji APEX w pakiecie OTA. Może to służyć do sprawdzania, czy urządzenie musi wystarczyć miejsca na pobranie aktualizacji OTA.
  • reserveSpaceForCompressedApex – rezerwuje miejsce na dysku do wykorzystania w przyszłości. przez apexd, by zdekompresować skompresowane pliki APEX w pakiecie OTA.

W przypadku aktualizacji A/B OTA apexd podejmuje próbę dekompresji w interfejsie w ramach procedury OTA po instalacji. Jeśli dekompresja się nie powiedzie, apexd wykonuje dekompresję podczas uruchamiania, aby zastosować OTA. .

Alternatywy brane pod uwagę przy rozwijaniu APEX

Oto kilka opcji, które AOSP brał pod uwagę przy projektowaniu pliku APEX oraz powody ich uwzględnienia lub wykluczenia.

Zwykłe systemy zarządzania pakietami

Dystrybucje Linuksa mają systemy zarządzania pakietami, takie jak dpkg i rpm, które mają moc, i wytrzymałość. Nie byli to jednak również dla APEX, ponieważ nie są w stanie chronić przesyłek instalacji. Weryfikacja jest przeprowadzana tylko podczas instalowania pakietów. Hakerzy mogą niezauważyć naruszenia integralności zainstalowanych pakietów. To jest w przypadku Androida – wszystkie komponenty systemu były przechowywane w trybie tylko do odczytu systemów plików, których integralność jest chroniona dm-verity podczas każdego wejścia/wyjścia. Dowolne ingerowanie w elementy systemu musi być zabronione lub wykrywalne, urządzenie może odmówić uruchomienia w przypadku przejęcia.

dm-crypt dla integralności

Pliki w kontenerze APEX pochodzą z wbudowanych partycji (na przykład /system partycji) chronionej przez dm-verity, gdzie każda modyfikacja pliki są zabronione nawet po podłączeniu partycji. Aby udostępnić poziom bezpieczeństwa plików, wszystkie pliki w raporcie APEX są przechowywane w formie pliku obraz systemu sparowany z drzewem skrótu i deskryptorem vbmeta. Bez dm-verity, punkt APEX w partycji /data jest podatny na niezamierzone modyfikacje wprowadzone po sprawdzeniu i zainstalowaniu.

W rzeczywistości partycja /data jest również chroniona przez warstwy szyfrowania, takie jak dm-crypt. Chociaż zapewnia to pewien poziom ochrony przed nieuprawnionymi modyfikacjami, że ich głównym celem jest prywatność, a nie uczciwość. Gdy atakujący uzyska dostęp do /data, nie ma dodatkowej ochrony, a to znowu jest w porównaniu z każdym komponentem systemu, który jest w partycji /system. Drzewo skrótu w pliku APEX w połączeniu z dm-verity daje taki sam efekt. poziom ochrony treści.

Przekieruj ścieżki z /system do /apex

Pliki komponentów systemowych spakowane w APEX są dostępne za pomocą nowych ścieżek, takich jak /apex/<name>/lib/libfoo.so Kiedy pliki należały do folderu /system partycji, były dostępne poprzez ścieżki takie jak /system/lib/libfoo.so. O klienta pliku APEX (innych plików APEX lub platformy) musi używać nowego ścieżek konwersji. W wyniku zmiany ścieżki może być konieczna aktualizacja istniejącego kodu.

Chociaż jednym ze sposobów uniknięcia zmiany ścieżki jest nałożenie zawartości pliku pliku APEX na partycję /system, ale zespół Androida zdecydował się nie nakładać na partycji /system, bo może to wpłynąć na wydajność, liczba nałożonych plików (może nawet nakładać się jeden po drugim); wzrosła.

Inną możliwością było przejęcie funkcji dostępu do plików, takich jak open, stat czy readlink, dzięki czemu ścieżki zaczynające się od /system były przekierowywane do odpowiednich ścieżek w /apex. Zespół Androida odrzucił tę opcję bo nie można zmienić wszystkich funkcji, które akceptują ścieżki. Na przykład niektóre aplikacje statycznie łączą się z Bionic, który implementuje te funkcje. W takich przypadkach aplikacje nie są przekierowywane.