APEX-Dateiformat

Das Containerformat Android Pony EXpress (APEX) wurde in Android eingeführt. 10 und wird während des Installationsvorgangs für untergeordnete Systeme verwendet, Module. Dieses Format ermöglicht die Aktualisierung von Systemkomponenten, die nicht Standard-Android-Anwendungsmodell integriert. Einige Beispielkomponenten sind nativ Dienste und Bibliotheken, Hardwareabstraktionsebenen (HALs), Laufzeit (ART) und Klassenbibliotheken.

Der Begriff „APEX“ auf eine APEX-Datei verweisen.

Hintergrund

Android unterstützt zwar Updates von Modulen, die in die Standard-App passen, (z. B. Dienstleistungen, Aktivitäten) über Paketinstallations-Apps (z. B. Google Play Store App). Dabei wird ein ähnliches Modell für untergeordnete Betriebssystemkomponenten verwendet. hat folgende Nachteile:

  • APK-basierte Module können nicht zu Beginn der Bootsequenz verwendet werden. Das Paket Manager ist das zentrale Repository für Informationen über Apps und kann nur die im Aktivitätsmanager gestartet werden, der in einer späteren Phase während des Bootvorgangs.
  • Das APK-Format, insbesondere das Manifest, ist für Android-Apps und Systemmodule nicht immer geeignet sind.

Design

In diesem Abschnitt werden das übergeordnete Design des APEX-Dateiformats und die APEX Manager, ein Dienst zum Verwalten von APEX-Dateien.

Weitere Informationen darüber, warum dieses Design für APEX ausgewählt wurde, finden Sie unter Alternativen bei der Entwicklung von APEX.

APEX-Format

Dies ist das Format einer APEX-Datei.

APEX-Dateiformat

Abbildung 1: APEX-Dateiformat

Auf der obersten Ebene ist eine APEX-Datei eine ZIP-Datei, in der Dateien gespeichert sind. unkomprimiert und an 4 KB-Grenzen platziert.

Die vier Dateien in einer APEX-Datei sind:

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

Die Datei apex_manifest.json enthält den Paketnamen und die Version. identifizieren Sie eine APEX-Datei. Dies ist ein ApexManifest Protokollpuffer im JSON-Format.

Mit der Datei AndroidManifest.xml kann die APEX-Datei APK-bezogene Tools und wie ADB, PackageManager und Paketinstallations-Apps (z. B. Play Store. Für die APEX-Datei kann beispielsweise ein vorhandenes Tool wie aapt verwendet werden um grundlegende Metadaten aus der Datei zu prüfen. Die Datei enthält den Paketnamen und Versionsinformationen. Diese Informationen sind in der Regel auch in apex_manifest.json

Für neuen Code und mehr als AndroidManifest.xml wird apex_manifest.json empfohlen, die mit APEX arbeiten. AndroidManifest.xml enthält möglicherweise weitere Targeting-Informationen, die von den vorhandenen App-Publishing-Tools verwendet werden können.

apex_payload.img ist ein ext4-Dateisystem-Image, das von dm-verity unterstützt wird. Das Bild wird zur Laufzeit über ein Loopback-Gerät bereitgestellt. Insbesondere sind der Hash-Baum und die Metadatenblock werden mit der libavb-Bibliothek erstellt. Die Nutzlast des Dateisystems nicht geparst wird (da das Image vorhanden sein sollte). Normale Dateien sind in der Datei apex_payload.img enthalten.

apex_pubkey ist der öffentliche Schlüssel, mit dem das Dateisystem-Image signiert wird. Während der Laufzeit Mit diesem Schlüssel wird sichergestellt, dass das heruntergeladene APEX mit derselben Entität signiert ist das dasselbe APEX in den integrierten Partitionen signiert.

APEX-Benennungsrichtlinien

Um Namenskonflikte zwischen neuen APEXes im Laufe der Weiterentwicklung der Plattform zu vermeiden, Beachten Sie die folgenden Benennungsrichtlinien:

  • com.android.*
    • Reserviert für AOSP APEXes. Sie ist für kein Unternehmen oder Gerät einzigartig.
  • com.<companyname>.*
    • Für ein Unternehmen reserviert. Möglicherweise von mehreren Geräten verwendet Unternehmen.
  • com.<companyname>.<devicename>.*
    • Reserviert für APEXes, die für ein bestimmtes Gerät (oder eine Untergruppe von Geräten) eindeutig sind.

APEX-Manager

Der APEX-Manager (oder apexd) ist ein eigenständiger nativer Prozess, der für Überprüfen, Installieren und Deinstallieren von APEX-Dateien. Dieser Prozess wird gestartet und zu Beginn der Startsequenz bereit sind. APEX-Dateien sind normalerweise auf das Gerät unter /system/apex. Der APEX-Manager verwendet diese Pakete, wenn keine Updates verfügbar sind.

Für die Aktualisierungssequenz eines APEX wird die Methode PackageManager-Klasse und sieht wie folgt aus.

  1. Eine APEX-Datei wird über eine Paketinstallations-App, ADB oder andere Quelle.
  2. Der Paketmanager startet den Installationsvorgang. Wenn ich erkannt habe, Wenn die Datei ein APEX ist, überträgt der Paketmanager die Kontrolle an das APEX. Manager.
  3. Der APEX-Manager überprüft die APEX-Datei.
  4. Wenn die APEX-Datei verifiziert wurde, ist die interne Datenbank des APEX-Managers aktualisiert, um anzugeben, dass die APEX-Datei beim nächsten Start aktiviert wird.
  5. Der Installationsanforderer erhält nach erfolgreichem Paket eine Nachricht an alle Überprüfung.
  6. Um die Installation fortzusetzen, muss das System neu gestartet werden.
  7. Beim nächsten Start startet der APEX-Manager, liest die interne Datenbank Folgendes für jede aufgeführte APEX-Datei:

    1. Überprüft die APEX-Datei.
    2. Erstellt ein Loopback-Gerät aus der APEX-Datei.
    3. Erstellt ein Device Mapper-Blockgerät über dem Loopback-Gerät.
    4. Stellt das Device Mapper-Blockgerät auf einem eindeutigen Pfad bereit (z. B. /apex/name@ver.

Wenn alle in der internen Datenbank aufgeführten APEX-Dateien bereitgestellt sind, Manager stellt einen Binder-Dienst für andere Systemkomponenten bereit, die abgefragt werden sollen. Informationen zu den installierten APEX-Dateien. Das andere System Komponenten die Liste der auf dem Gerät installierten APEX-Dateien abfragen oder die den genauen Pfad, unter dem ein bestimmtes APEX bereitgestellt wird, damit auf die Dateien zugegriffen werden kann.

APEX-Dateien sind APK-Dateien

APEX-Dateien sind gültige APK-Dateien, da es sich um signierte ZIP-Archive mit der Methode APK-Signaturschema), das eine AndroidManifest.xml-Datei enthält. Dies ermöglicht APEX Dateien zur Nutzung der Infrastruktur für APK-Dateien, z. B. eine App zur Paketinstallation, das Signaturdienstprogramm und den Paketmanager.

Die AndroidManifest.xml-Datei in einer APEX-Datei ist minimal und besteht aus dem Paket name, versionCode und optional targetSdkVersion, minSdkVersion, und maxSdkVersion für ein differenziertes Targeting. Durch diese Informationen kann APEX Dateien, die über vorhandene Kanäle wie Paketinstallations-Apps und ADB

Unterstützte Dateitypen

Das APEX-Format unterstützt folgende Dateitypen:

  • Native freigegebene Bibliotheken
  • Native ausführbare Dateien
  • JAR-Dateien
  • Datendateien
  • Konfigurationsdateien

Das bedeutet nicht, dass APEX alle diese Dateitypen aktualisieren kann. ob eine Datei hängt von der Plattform und davon ab, wie stabil die Definitionen die Schnittstellen für die Dateitypen sind.

Signaturoptionen

APEX-Dateien werden auf zwei Arten signiert. Erstens, die apex_payload.img (insbesondere der an die Datei apex_payload.img angehängte Vbmeta-Deskriptor-Deskriptor mit einem Schlüssel signiert ist. Dann wird das gesamte APEX mit dem APK-Signaturschema v3. Es werden zwei verschiedene Schlüssel verwendet in diesem Prozess.

Auf der Geräteseite ein öffentlicher Schlüssel, der dem privaten Schlüssel zum Signieren entspricht der vbmeta-Deskriptor installiert ist. Der APEX-Manager verwendet den öffentlichen Schlüssel, um Überprüfen Sie die APEX, die zur Installation angefordert werden. Jedes APEX muss signiert sein mit verschiedene Schlüssel und wird sowohl zur Build-Zeit als auch zur Laufzeit erzwungen.

APEX in integrierten Partitionen

APEX-Dateien können sich in integrierten Partitionen wie /system befinden. Die Die Partition befindet sich bereits über dm-verity, sodass die APEX-Dateien direkt bereitgestellt werden. über das Loopback-Gerät.

Wenn eine APEX in einer integrierten Partition vorhanden ist, kann APEX mit Sie stellen ein APEX-Paket mit demselben Paketnamen und einem Wert größer oder gleich auf den Versionscode. Das neue APEX wird in /data gespeichert. Ähnlich wie bei APKs ist das Eine neu installierte Version verdeckt die Version, die bereits in der integrierten Version vorhanden ist. -Partition an. Im Gegensatz zu APKs ist die neu installierte Version von APEX jedoch nur nach dem Neustart aktiviert werden.

Kernel-Anforderungen

Zur Unterstützung von APEX-Mainline-Modulen auf einem Android-Gerät werden die folgenden Linux- erforderlich: der Loopback-Treiber und dm-verity. Der Loopback Der Treiber stellt das Dateisystem-Image in einem APEX-Modul bereit und dm-verity verifiziert APEX-Modul.

Die Leistung des Loopback-Treibers und des dm-verity ist wichtig, um mit APEX-Modulen gute Systemleistung erzielen.

Unterstützte Kernel-Versionen

APEX-Mainline-Module werden auf Geräten mit Kernel-Versionen 4.4 oder höher liegen. Neue Geräte, die mit Android 10 oder höher auf den Markt gebracht werden muss zur Unterstützung von APEX-Modulen die Kernel-Version 4.9 oder höher verwenden.

Erforderliche Kernel-Patches

Die erforderlichen Kernel-Patches zur Unterstützung von APEX-Modulen sind im Android Common Tree. Damit die Patches APEX unterstützen, müssen Sie die neueste Version verwenden der Android Common Tree.

Kernel-Version 4.4

Diese Version wird nur für Geräte unterstützt, die von Android 9 auf aktualisiert wurden Android 10 verwenden und APEX-Module unterstützen möchten. Um die erforderliche Patches, wird eine Down-Zusammenführung vom android-4.4-Zweig dringend durchgeführt. wird empfohlen. Im Folgenden finden Sie eine Liste der erforderlichen einzelnen Patches: für Kernel-Version 4.4.

  • UPSTREAM: Schleife: ioctl zum Ändern der logischen Blockgröße hinzufügen (4,4)
  • BACKPORT: block/loop: set hw_sectors (4,4)
  • UPSTREAM: Schleife: LOOP_SET_BLOCK_SIZE in kompatibler ioctl hinzufügen (4,4)
  • ANDROID: mnt: Problem mit next_descendent beheben (4,4)
  • ANDROID: mnt: Erneute Bereitstellung sollte an Sklaven von Sklaven weitergegeben werden. (4,4)
  • ANDROID: mnt: Erneut bereitstellen (4,4)
  • "ANDROID: dm verity: Mindest-Prefetch-Größe hinzufügen" wiederherstellen (4,4)
  • UPSTREAM: Schleife: Caches werden gelöscht, wenn Offset oder block_size geändert werden (4,4)

Kernel-Versionen 4.9/4.14/4.19

Um die erforderlichen Patches für die Kernel-Versionen 4.9/4.14/4.19 zu erhalten, führen Sie Zweig android-common.

Erforderliche Kernel-Konfigurationsoptionen

In der folgenden Liste sind die grundlegenden Konfigurationsanforderungen für den Support aufgeführt. APEX-Module, die mit Android 10 eingeführt wurden. Die Elemente mit einem Sternchen (*) bestehende Anforderungen von Android 9 und niedriger.

(*) 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

Anforderungen an Kernel-Befehlszeilenparameter

Zur Unterstützung von APEX müssen die Kernel-Befehlszeilenparameter die folgenden Anforderungen erfüllen Anforderungen:

  • loop.max_loop darf NICHT festgelegt werden
  • loop.max_part muss <= 8 sein

APEX erstellen

In diesem Abschnitt wird beschrieben, wie Sie ein APEX mit dem Android-Build-System erstellen. Das folgende Beispiel zeigt Android.bp für ein APEX mit dem Namen 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",
}

Beispiel für apex_manifest.json:

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

Beispiel für file_contexts:

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

Dateitypen und Speicherorte in APEX

Dateityp Speicherort in APEX
Geteilte Fotogalerien /lib und /lib64 (/lib/arm für übersetzter Arm in x86)
Ausführbare Dateien /bin
Java-Bibliotheken /javalib
Vorgefertigt /etc

Transitive Abhängigkeiten

APEX-Dateien enthalten automatisch transitive Abhängigkeiten nativer freigegebener Bibliotheken oder ausführbare Dateien. Wenn libFoo beispielsweise von libBar abhängt, sind die beiden Bibliotheken enthalten, wenn in der Property native_shared_libs nur libFoo aufgeführt ist.

Mehrere ABIs verarbeiten

Installieren Sie das Attribut native_shared_libs sowohl für die primäre als auch für die sekundäre Instanz. Binäre Anwendungsschnittstellen (Application Binary Interface, ABI) des Geräts Wenn ein APEX auf Geräte ausgerichtet ist mit einer einzigen ABI (d. h. nur 32-Bit oder 64-Bit) haben, werden nur Bibliotheken mit der entsprechende ABI installiert.

Installiere das Attribut „binaries“ nur für die primäre ABI des Geräts als wie unten beschrieben:

  • Wenn das Gerät nur ein 32-Bit-Gerät hat, ist nur die 32-Bit-Variante des Binärprogramms installiert haben.
  • Wenn das Gerät nur eine 64-Bit-Version hat, ist nur die 64-Bit-Variante des Binärprogramms installiert haben.

Um die ABIs der nativen Bibliotheken und Binärdateien genau zu steuern, verwenden Sie die multilib.[first|lib32|lib64|prefer32|both].[native_shared_libs|binaries] Eigenschaften.

  • first: entspricht der primären ABI des Geräts. Dies ist die Standardeinstellung für Binärdateien.
  • lib32: entspricht der 32-Bit-ABI des Geräts, falls unterstützt.
  • lib64: Entspricht der unterstützten 64-Bit-ABI des Geräts.
  • prefer32: entspricht der 32-Bit-ABI des Geräts, falls unterstützt. Wenn die 32-Bit-ABI wird nicht unterstützt, stimmt aber mit 64-Bit-ABI überein.
  • both: Stimmt mit beiden ABIs überein. Dies ist die Standardeinstellung für native_shared_libraries

Die Attribute java, libraries und prebuilts sind ABI-unabhängig.

Dieses Beispiel ist für ein Gerät, das 32/64 unterstützt, aber nicht 32 bevorzugt:

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
        },
    },
}

VBmeta-Signatur

Signieren Sie jedes APEX mit verschiedenen Schlüsseln. Wenn ein neuer Schlüssel erforderlich ist, erstellen Sie einen ein öffentliches/privates Schlüsselpaar und erstellen ein apex_key-Modul. Mit dem Attribut key können Sie signieren Sie das APEX mit dem Schlüssel. Der öffentliche Schlüssel ist automatisch im APEX mit dem Namen 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",
}

Im obigen Beispiel wird der Name des öffentlichen Schlüssels (foo) zur ID des . Die ID des Schlüssels, mit dem ein APEX signiert wird, wird im APEX geschrieben. Während der Laufzeit apexd verifiziert APEX mithilfe eines öffentlichen Schlüssels mit derselben ID auf dem Gerät.

APEX-Signatur

Signieren Sie APEX-Dateien auf die gleiche Weise wie APKs. Signieren Sie APEXes zweimal. einmal für die Mini-Dateisystem (apex_payload.img-Datei) und einmal für die gesamte Datei.

Um ein APEX auf Dateiebene zu signieren, legen Sie das Attribut certificate in einer der auf diese drei Arten:

  • Nicht festgelegt: Wenn kein Wert festgelegt ist, wird das APEX mit dem Zertifikat signiert, das sich um PRODUCT_DEFAULT_DEV_CERTIFICATE. Wenn kein Flag festgelegt ist, werden die Standardeinstellungen des Pfads verwendet. an build/target/product/security/testkey.
  • <name>: Das APEX ist mit dem Zertifikat <name> im selben als PRODUCT_DEFAULT_DEV_CERTIFICATE.
  • :<name>: Das APEX ist mit dem Zertifikat signiert, das vom Songmodul mit dem Namen <name>. Das Zertifikatsmodul kann definiert werden als folgt.
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)
}

APEX installieren

Verwenden Sie ADB, um ein APEX zu installieren.

adb install apex_file_name
adb reboot

Wenn supportsRebootlessUpdate in apex_manifest.json auf true gesetzt ist und der das aktuell installierte APEX nicht verwendet wird (z. B. Dienste mit angehalten wurde, kann ein neues APEX ohne Neustart mit der --force-non-staged.

adb install --force-non-staged apex_file_name

APEX verwenden

Nach dem Neustart wird das APEX unter /apex/<apex_name>@<version> bereitgestellt. -Verzeichnis. Es können mehrere Versionen desselben APEX-Pakets gleichzeitig bereitgestellt werden. Unter den Bereitstellungspfaden ist derjenige, der der neuesten Version entspricht, unter /apex/<apex_name> durch Binde bereitgestellt.

Clients können den durch Bindung bereitgestellten Pfad verwenden, um Dateien aus APEX zu lesen oder auszuführen.

APTEX werden in der Regel so verwendet:

  1. Ein OEM oder ODM lädt ein APEX unter /system/apex vorab, wenn das Gerät versendet.
  2. Auf Dateien im APEX wird über den Pfad /apex/<apex_name>/ zugegriffen.
  3. Wenn eine aktualisierte Version von APEX in /data/apex installiert wird, ist der Pfad verweist nach dem Neustart auf das neue APEX.

Dienst mit einem APEX aktualisieren

So aktualisieren Sie einen Dienst mit einem APEX:

  1. Markieren Sie den Dienst in der Systempartition als aktualisierbar. Option hinzufügen updatable für die Dienstdefinition.

    /system/etc/init/myservice.rc:
    
    service myservice /system/bin/myservice
        class core
        user system
        ...
        updatable
    
  2. Erstellen Sie eine neue .rc-Datei für den aktualisierten Dienst. Option override verwenden um den bestehenden Dienst neu zu definieren.

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

Dienstdefinitionen können nur in der .rc-Datei eines APEX-Codes definiert werden. Aktion Trigger werden in APEX nicht unterstützt.

Wenn ein als aktualisierbar gekennzeichneter Dienst startet, bevor die APEXes aktiviert werden, wird der Start verzögert sich, bis die Aktivierung des APEXes abgeschlossen ist.

System zur Unterstützung von APEX-Updates konfigurieren

Legen Sie das folgende Systemattribut auf true fest, um APEX-Dateiaktualisierungen zu unterstützen.

<device.mk>:

PRODUCT_PROPERTY_OVERRIDES += ro.apex.updatable=true

BoardConfig.mk:
TARGET_FLATTEN_APEX := false

oder einfach

<device.mk>:

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

APEX (Flattened APEX)

Bei älteren Geräten ist es manchmal unmöglich oder gar nicht möglich, das alte um APEX vollständig zu unterstützen. Vielleicht wurde der Kernel ohne CONFIG_BLK_DEV_LOOP=Y, was für die Bereitstellung des Dateisystems in einem APEX erstellt.

Flattened APEX ist ein speziell entwickeltes APEX, das auf Geräten mit einem Legacy-Kernel. Dateien in einem vereinfachten APEX werden direkt in einem Verzeichnis installiert der integrierten Partition ein. Beispiel: lib/libFoo.so in einem vereinfachten APEX my.apex ist auf /system/apex/my.apex/lib/libFoo.so installiert.

Beim Aktivieren eines Flattened APEX wird das Loop Device nicht verwendet. Das gesamte Das Verzeichnis /system/apex/my.apex wird direkt durch Bindung an /apex/name@ver bereitgestellt.

Aufgeschlüsselte APEX-Dateien können nicht durch Herunterladen aktualisierter Versionen aktualisiert werden der APEX aus dem Netzwerk, da die heruntergeladenen APEXes nicht vereinfacht werden können. Flattened APEXes können nur über ein reguläres OTA-Update aktualisiert werden.

Das vereinfachte APEX ist die Standardkonfiguration. Das bedeutet, dass alle APEX-Dateien werden standardmäßig vereinfacht, es sei denn, Sie konfigurieren Ihr Gerät explizit nicht vereinfachte APEX, um APEX-Updates zu unterstützen (wie oben erläutert).

Das Vermischen von vereinfachten und nicht vereinfachten APEXes in einem Gerät unterstützt. APEX in einem Gerät müssen entweder alle nicht oder nur reduziert sein. Dies ist besonders wichtig, wenn vorsignierte APEX-Dateien für wie Mainline. Nicht vorsignierte APEX-Dateien, d. h., die aus der Quelle) sollten außerdem nicht vereinfacht und mit richtigen Schlüsseln signiert sein. Die Gerät sollte die Einstellungen von updatable_apex.mk übernehmen, wie unter Dienst mit einem APEX aktualisieren

Komprimierte APEX-Dateien

Android 12 und höher bieten die APEX-Komprimierung für weniger Speicherauswirkungen aktualisierbarer APEX-Pakete. Nach der Aktualisierung eines APEX ist installiert, obwohl die vorinstallierte Version nicht mehr verwendet wird, immer noch den gleichen Speicherplatz einnimmt. Dieser belegte Bereich ist weiterhin nicht verfügbar.

Die APEX-Komprimierung minimiert diese Speicherbelastung durch die Verwendung eines stark komprimierten Satzes. von APEX-Dateien auf schreibgeschützten Partitionen (z. B. der Partition /system). Android-Geräte ab Version 12 verwenden einen DEFLATE-Komprimierungsalgorithmus für die ZIP-Datei.

Die Komprimierung bietet keine Optimierung für Folgendes:

  • APEX-Dateien bootstrappen, die sehr früh im Boot bereitgestellt werden müssen Sequenz hinzufügen.

  • Nicht aktualisierbare APEXe. Die Komprimierung ist nur sinnvoll, wenn eine aktualisierte APEX-Version installiert ist. für die Partition /data. Eine vollständige Liste der aktualisierbaren APEXe findest du auf der Modulare Systemkomponenten Seite.

  • Dynamic Shared Libs APEXes. Da apexd immer beide Versionen von Solche APEX-Dateien (vorinstalliert und aktualisiert) bieten keinen Mehrwert, wenn sie komprimiert werden.

Komprimiertes APEX-Dateiformat

Dies ist das Format einer komprimierten APEX-Datei.

Das Diagramm zeigt das Format einer komprimierten APEX-Datei.

Abbildung 2: Komprimiertes APEX-Dateiformat

Auf der obersten Ebene ist eine komprimierte APEX-Datei eine ZIP-Datei, die Apex-Datei in degradierter Form mit der Komprimierungsstufe 9 und mit anderen Dateien unkomprimiert gespeichert.

Eine APEX-Datei besteht aus vier Dateien:

  • original_apex: entleert mit Komprimierungsstufe 9 Dies ist die unkomprimierte APEX-Datei.
  • apex_manifest.pb: nur gespeichert
  • AndroidManifest.xml: nur gespeichert
  • apex_pubkey: nur gespeichert

Die Dateien apex_manifest.pb, AndroidManifest.xml und apex_pubkey sind Kopien der entsprechenden Dateien in original_apex.

Komprimiertes APEX erstellen

Komprimiertes APEX kann mit dem apex_compression_tool.py-Tool unter system/apex/tools

Im Build-System sind mehrere Parameter im Zusammenhang mit der APEX-Komprimierung verfügbar.

In Android.bp wird festgelegt, ob eine APEX-Datei komprimierbar ist compressible-Property:

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

Ein PRODUCT_COMPRESSED_APEX-Produkt-Flag steuert, ob ein System-Image erstellt wird, aus der Quelle muss komprimierte APEX-Dateien enthalten.

Für lokale Tests können Sie erzwingen, dass ein Build APEXes komprimiert, indem Sie Folgendes festlegen: OVERRIDE_PRODUCT_COMPRESSED_APEX= in true.

Komprimierte APEX-Dateien, die vom Build-System generiert wurden, haben die Erweiterung .capex. Die Erweiterung erleichtert die Unterscheidung zwischen komprimiert und unkomprimiert. Versionen einer APEX-Datei.

Unterstützte Komprimierungsalgorithmen

Android 12 unterstützt nur die deflate-zip-Komprimierung.

Komprimierte APEX-Datei beim Start aktivieren

Bevor ein komprimiertes APEX aktiviert werden kann, muss die darin enthaltene original_apex-Datei im Verzeichnis /data/apex/decompressed dekomprimiert. Das Ergebnis Die dekomprimierte APEX-Datei ist hart mit dem Verzeichnis /data/apex/active verknüpft.

Betrachten Sie das folgende Beispiel zur Verdeutlichung des oben beschriebenen Prozesses.

/system/apex/com.android.foo.capex kann als komprimierte APEX-Datei betrachtet werden, aktiviert mit dem Versionscode 37.

  1. Die Datei original_apex in /system/apex/com.android.foo.capex ist in /data/apex/decompressed/com.android.foo@37.apex dekomprimiert.
  2. restorecon /data/apex/decompressed/com.android.foo@37.apex wird ausgeführt, um Überprüfen Sie, ob sie über ein korrektes SELinux-Label verfügt.
  3. Überprüfungen werden durchgeführt am /data/apex/decompressed/com.android.foo@37.apex, um die Gültigkeit sicherzustellen: apexd prüft den öffentlichen Schlüssel, der im Bundle enthalten ist /data/apex/decompressed/com.android.foo@37.apex, um zu prüfen, ob sie identisch sind mit dem Paket in /system/apex/com.android.foo.capex.
  4. Die Datei /data/apex/decompressed/com.android.foo@37.apex ist hartverknüpft mit das Verzeichnis /data/apex/active/com.android.foo@37.apex.
  5. Die reguläre Aktivierungslogik für unkomprimierte APEX-Dateien wird am /data/apex/active/com.android.foo@37.apex

Interaktion mit Onlinereisebüro

Komprimierte APEX-Dateien wirken sich auf die OTA-Bereitstellung und -Anwendung aus. Seit Ein OTA-Update kann eine komprimierte APEX-Datei mit einer höheren Versionsstufe enthalten. als auf einem Gerät aktiv ist, muss eine bestimmte Menge freier Speicherplatz reserviert werden. bevor ein Gerät neu gestartet wird, um ein OTA-Update anzuwenden.

Zur Unterstützung des OTA-Systems stellt apexd diese beiden Binder-APIs zur Verfügung:

  • calculateSizeForCompressedApex: Berechnet die für die Dekomprimierung erforderliche Größe APEX-Dateien in einem OTA-Paket. Damit kann überprüft werden, ob ein Gerät bevor ein OTA-Update heruntergeladen wird.
  • reserveSpaceForCompressedApex – reserviert Speicherplatz auf dem Laufwerk für die zukünftige Verwendung von apexd zur Dekomprimierung komprimierter APEX-Dateien im OTA-Paket.

Bei einem A/B-OTA-Update versucht apexd, die Dekomprimierung in der im Hintergrund der OTA-Routine nach der Installation. Wenn die Dekomprimierung fehlschlägt, apexd führt beim Start eine Dekomprimierung durch, bei der das OTA-Update angewendet wird aktualisieren.

Bei der Entwicklung von APEX berücksichtigte Alternativen

Hier sind einige Optionen, die AOSP beim Entwerfen der APEX-Datei berücksichtigt hat. und warum sie ein- oder ausgeschlossen wurden.

Reguläre Paketverwaltungssysteme

Linux-Distributionen haben Paketverwaltungssysteme wie dpkg und rpm, die leistungsstark, ausgereift und robust sind. Sie waren jedoch nicht für APEX eingeführt, da das Unternehmen die Pakete nach der Installation. Die Überprüfung wird nur durchgeführt, wenn Pakete installiert werden. Angreifer können unbemerkt die Integrität der installierten Pakete beschädigen. Dies ist Regression für Android, bei der alle Systemkomponenten schreibgeschützt gespeichert wurden. Dateisysteme, deren Integrität für jede E/A durch dm-verity geschützt wird. Beliebig Die Manipulation von Systemkomponenten muss entweder verboten oder erkennbar sein, dass das Gerät den Start verweigern kann, wenn es manipuliert wurde.

dm-crypt für Integrität

Die Dateien in einem APEX-Container stammen aus integrierten Partitionen (z. B. der /system), die durch dm-verity geschützt sind, wobei jede Änderung an Die Dateien sind auch nach der Bereitstellung der Partitionen nicht zulässig. Um die Alle Dateien in einem APEX werden in einer Datei gespeichert, System-Image, das mit einem Hash-Baum und einem vbmeta-Deskriptor gekoppelt ist. Ohne dm-verity ist, ist ein APEX in der Partition /data anfällig für unbeabsichtigte Änderungen vorgenommen werden, die nach der Überprüfung und Installation vorgenommen wurden.

Tatsächlich ist die Partition /data auch durch Verschlüsselungsebenen wie dm-Crypt. Dies bietet zwar einen gewissen Schutz vor Manipulationen, Hauptzweck ist der Datenschutz, nicht die Integrität. Wenn sich ein Angreifer Zugriff auf das /data-Partition können Sie keinen weiteren Schutz mehr gewähren. im Vergleich zu jeder Systemkomponente in der Partition /system. Der Hash-Baum in einer APEX-Datei bietet zusammen mit dm-verity dieselben um die Inhalte zu schützen.

Pfade von /system nach /apex weiterleiten

In einem APEX verpackte Systemkomponentendateien sind über neue Pfade wie /apex/<name>/lib/libfoo.so Wann die Dateien Teil des /system waren waren sie über Pfade wie /system/lib/libfoo.so zugänglich. A Client einer APEX-Datei (andere APEX-Dateien oder der Plattform) muss das neue Pfade. Aufgrund der Pfadänderung müssen Sie möglicherweise vorhandenen Code aktualisieren.

Eine Möglichkeit, die Pfadänderung zu vermeiden, besteht darin, den Dateiinhalt APEX-Datei in die Partition /system geschrieben, hat das Android-Team beschlossen, in der Partition /system, da dies die Leistung beeinträchtigen könnte, da Anzahl der eingeblendeten Dateien (möglicherweise sogar übereinander gestapelt) gestiegen.

Eine weitere Option bestand darin, Dateizugriffsfunktionen wie open, stat und readlink gesetzt, sodass Pfade, die mit /system beginnen, an ihre entsprechende Pfade unter /apex. Das Android-Team hat diese Option verworfen da es nicht möglich ist, alle Funktionen zu ändern, die Pfade akzeptieren. Einige Apps verknüpfen beispielsweise Bionic, das die Funktionen implementiert, statisch. In solchen Fällen werden diese Apps nicht weitergeleitet.