Anbieter APEX

Mit dem APEX-Dateiformat können Sie untergeordnete Android-Betriebssystemmodule verpacken und installieren. Sie ermöglicht unabhängige Erstellung und Installation von Komponenten wie nativen Diensten und Bibliotheken, HAL Implementierungen, Firmware, Konfigurationsdateien usw.

Anbieter-APEX werden vom Build-System automatisch im /vendor installiert und zur Laufzeit von apexd aktiviert werden, genau wie APEXes in anderen Partitionen.

Anwendungsfälle

Modularisierung von Anbieterbildern

APEX erleichtert die natürliche Bündelung und Modularisierung von Funktionen Implementierungen in Anbieter-Images.

Wenn Anbieter-Images als Kombination aus unabhängigen Anbietern erstellt werden APEX: Gerätehersteller können ganz einfach die gewünschten welche Implementierungen auf ihrem Gerät erwünscht sind. Hersteller können sogar eine neue Anbieter-APEX erstellen, wenn keine der bereitgestellten APEXes ihren Anforderungen entspricht oder sie eine brandneue benutzerdefinierte Hardware haben.

Beispielsweise kann ein OEM sein Gerät mit AOSP-WLAN zusammensetzen. APEX-Implementierung, SoC-Bluetooth-Implementierung APEX und ein benutzerdefinierter OEM Telefonieimplementierung APEX.

Eine Implementierung mit so vielen Abhängigkeiten zwischen die Komponenten eines Anbieters erfordern eine sorgfältige Koordination und Nachverfolgung. Wenn Sie alle Komponenten (einschließlich Konfigurationsdateien und zusätzlicher Bibliotheken) in APEX-Objekte mit klar definierten Schnittstellen an jeder Stelle der funktionsübergreifenden Kommunikation einbetten, werden die verschiedenen Komponenten austauschbar.

Entwickleriteration

Anbieter-APEX-Objekte helfen Entwicklern, beim Entwickeln von Anbietermodulen schneller zu iterieren, indem eine vollständige Funktionsimplementierung wie die WLAN-HAL in einem Anbieter-APEX-Objekt gebündelt wird. Entwickler können das Anbieter-APEX dann individuell erstellen und per Push zum Testen übertragen. anstatt das gesamte Anbieter-Image neu zu erstellen.

Dies vereinfacht und beschleunigt den Iterationszyklus für Entwickler, die hauptsächlich in einem bestimmten Funktionsbereich arbeiten und nur diesen Bereich iterieren möchten.

Durch die natürliche Bündelung eines Feature-Bereichs in einem APEX-Objekt wird auch der Prozess zum Erstellen, Pushen und Testen von Änderungen für diesen Feature-Bereich vereinfacht. Wenn Sie beispielsweise eine APEX-Anwendung neu installieren, werden automatisch alle Bibliotheken oder Konfigurationsdateien aktualisiert, die in der APEX-Anwendung enthalten sind.

Wenn Sie einen Funktionsbereich in einem APEX-Objekt bündeln, wird auch das Debuggen oder Zurücksetzen vereinfacht, wenn ein schlechtes Geräteverhalten festgestellt wird. Wenn die Telefonie in einem neuen Build beispielsweise schlecht funktioniert, können Entwickler versuchen, eine ältere APEX-Telefonieimplementierung auf einem Gerät zu installieren (ohne einen vollständigen Build zu flashen) und zu prüfen, ob das Problem dadurch behoben wird.

Beispielworkflow:

# Build the entire device and flash. OR, obtain an already-flashed device.
source build/envsetup.sh && lunch oem_device-userdebug
m
fastboot flashall -w

# Test the device.
... testing ...

# Check previous behavior using a vendor APEX from one week ago, downloaded from
# your continuous integration build.
... download command ...
adb install <path to downloaded APEX>
adb reboot
... testing ...

# Edit and rebuild just the APEX to change and test behavior.
... edit APEX source contents ...
m <apex module name>
adb install out/<path to built APEX>
adb reboot
... testing ...

Beispiele

Grundlegende Informationen

Informationen zu generischem APEX finden Sie auf der Hauptseite des APEX-Dateiformats Informationen, einschließlich Geräteanforderungen, Details zum Dateiformat und Installationsschritten.

Wenn Sie in Android.bp die Eigenschaft vendor: true festlegen, wird ein APEX-Modul zu einem Anbieter-APEX.

apex {
  ..
  vendor: true,
  ..
}

Binärdateien und gemeinsam genutzte Bibliotheken

Ein APEX-Bundle enthält transitive Abhängigkeiten in der APEX-Nutzlast, es sei denn, sie haben stabile Schnittstellen.

Zu den stabilen nativen Schnittstellen für APEX-Abhängigkeiten von Anbietern gehören cc_library mit stubs und LLNDK-Bibliotheken. Diese Abhängigkeiten sind von der Paketerstellung und Abhängigkeiten werden im APEX-Manifest aufgezeichnet. Das Manifest ist von linkerconfig verarbeitet, sodass die externen nativen Abhängigkeiten zur Laufzeit verfügbar.

Im folgenden Snippet enthält die APEX-Datei sowohl die Binärdatei (my_service) als auch die nicht stabilen Abhängigkeiten (*.so-Dateien).

apex {
  ..
  vendor: true,
  binaries: ["my_service"],
  ..
}

Im folgenden Snippet enthält das APEX die gemeinsam genutzte Bibliothek. my_standalone_libund alle zugehörigen instabilen Abhängigkeiten (wie oben beschrieben) werden erkannt.

apex {
  ..
  vendor: true,
  native_shared_libs: ["my_standalone_lib"],
  ..
}

APEX verkleinern

APEX kann größer werden, da es instabile Abhängigkeiten bündelt. Wir empfehlen, mit statischer Verknüpfung. Gängige Bibliotheken wie libc++.so und libbase.so können statisch mit HAL-Binärdateien verknüpft ist. Eine weitere Option ist die Abhängigkeit von einer anderen Komponente, um eine stabile Benutzeroberfläche bereitzustellen. Die Abhängigkeit wird nicht im APEX gebündelt.

HAL-Implementierungen

Um eine HAL-Implementierung zu definieren, stellen Sie die entsprechenden Binärdateien und Bibliotheken bereit in einem Anbieter-APEX so ähnlich wie in den folgenden Beispielen:

Um die HAL-Implementierung vollständig zu kapseln, sollte die APEX auch alle relevanten VINTF-Fragmente und Init-Scripts angeben.

VINTF-Fragmente

VINTF-Fragmente können von einem Anbieter-APEX bereitgestellt werden, wenn sich die Fragmente etc/vintf des APEX.

Verwende die Property prebuilts, um die VINTF-Fragmente in die APEX einzubetten.

apex {
  ..
  vendor: true,
  prebuilts: ["fragment.xml"],
  ..
}

prebuilt_etc {
  name: "fragment.xml",
  src: "fragment.xml",
  sub_dir: "vintf",
}

Abfrage-APIs

Wenn VINTF-Fragmente zu APEX hinzugefügt werden, verwende libbinder_ndk APIs, um die Zuordnungen von HAL-Schnittstellen und APEX-Namen abzurufen.

  • AServiceManager_isUpdatableViaApex("com.android.foo.IFoo/default") : true Wenn die HAL-Instanz in APEX definiert ist.
  • AServiceManager_getUpdatableApexName("com.android.foo.IFoo/default", ...) : ruft den APEX-Namen ab, der die HAL-Instanz definiert.
  • AServiceManager_openDeclaredPassthroughHal("mapper", "instance", ...): Mit dieser Option wird eine Passthrough-HAL geöffnet.

Init-Scripts

APEX-Dateien können auf zwei Arten Init-Scripts enthalten: (A) eine vorgefertigte Textdatei in der APEX-Nutzlast oder (B) ein reguläres Init-Script in /vendor/etc. Sie können sowohl für dasselbe APEX.

Init-Script in APEX:

prebuilt_etc {
  name: "myinit.rc",
  src: "myinit.rc"
}

apex {
  ..
  vendor: true,
  prebuilts: ["myinit.rc"],
  ..
}

Init-Scripts in Anbieter-APEXes können service-Definitionen und on <property or event>-Anweisungen enthalten.

Achten Sie darauf, dass eine service-Definition auf eine Binärdatei im selben APEX verweist. com.android.foo APEX kann beispielsweise einen Dienst mit dem Namen foo-service definieren.

on foo-service /apex/com.android.foo/bin/foo
  ...

Seien Sie vorsichtig bei der Verwendung von on-Anweisungen. Da Init-Scripts in APEX-Objekten nach der Aktivierung von APEX-Objekten geparst und ausgeführt werden, können einige Ereignisse oder Properties nicht verwendet werden. Verwende apex.all.ready=true, um Aktionen so früh wie möglich auszulösen. Bootstrap-APEXes können on init verwenden, aber nicht on early-init.

Firmware

Beispiel:

Befolgen Sie die folgenden Schritte, um die Firmware in einem Anbieter-APEX mit dem Modultyp prebuilt_firmware einzubetten.

prebuilt_firmware {
  name: "my.bin",
  src: "path_to_prebuilt_firmware",
  vendor: true,
}

apex {
  ..
  vendor: true,
  prebuilts: ["my.bin"],  // installed inside APEX as /etc/firmware/my.bin
  ..
}

prebuilt_firmware-Module werden im Verzeichnis <apex name>/etc/firmware der APEX installiert. ueventd scannt /apex/*/etc/firmware-Verzeichnisse, um Firmwaremodule zu finden.

Die file_contexts des APEX muss alle Firmware-Nutzlasteinträge korrekt labeln, damit diese Dateien zur Laufzeit von ueventd zugänglich sind. Normalerweise ist das Label vendor_file ausreichend. Beispiel:

(/.*)? u:object_r:vendor_file:s0

Kernelmodule

Betten Sie Kernelmodule wie im Folgenden beschrieben als vordefinierte Module in eine Anbieter-APEX ein.

prebuilt_etc {
  name: "my.ko",
  src: "my.ko",
  vendor: true,
  sub_dir: "modules"
}

apex {
  ..
  vendor: true,
  prebuilts: ["my.ko"],  // installed inside APEX as /etc/modules/my.ko
  ..
}

Die file_contexts des APEX sollte alle Kernel-Modul-Nutzlasteinträge korrekt kennzeichnen. Beispiel:

/etc/modules(/.*)? u:object_r:vendor_kernel_modules:s0

Kernelmodule müssen explizit installiert werden. Das folgende Beispiel für ein Init-Script in der Anbieterpartition zeigt die Installation über insmod:

my_init.rc:

on early-boot
  insmod /apex/myapex/etc/modules/my.ko
  ..

Laufzeit-Ressourcen-Overlays

Beispiel:

Mit der Property rros können Sie Laufzeitressourcen-Overlays in eine APEX-Anzeigenfläche eines Anbieters einbetten.

runtime_resource_overlay {
    name: "my_rro",
    soc_specific: true,
}


apex {
  ..
  vendor: true,
  rros: ["my_rro"],  // installed inside APEX as /overlay/my_rro.apk
  ..
}

Andere Konfigurationsdateien

Anbieter-APEXes unterstützen verschiedene andere Konfigurationsdateien, die sich in der Regel als Prebuilts in Anbieter-APEXes auf der Anbieterpartition befinden. Es werden ständig weitere hinzugefügt.

Beispiele:

APEX des Bootstrap-Anbieters

Einige HAL-Dienste wie keymint sollten verfügbar sein, bevor APEX-Dienste installiert werden. aktiviert. Diese HALs legen in der Regel early_hal in ihrer Dienstdefinition im Init-Script fest. Ein weiteres Beispiel ist die animation-Klasse, die in der Regel früher als das post-fs-data-Ereignis gestartet wird. Wenn ein solcher HAL-Dienst in einem Anbieter-APEX-Paket enthalten ist, muss der Apex "vendorBootstrap": true im APEX-Manifest sein, damit er früher aktiviert werden kann. Bootstrap-APEX-Dateien können nur am vordefinierten Speicherort wie /vendor/apex aktiviert, nicht vom /data/apex.

Systemeigenschaften

Das Framework liest die folgenden Systemeigenschaften, um Anbieter-APEXes zu unterstützen:

  • input_device.config_file.apex=<apex name> – wenn festgelegt, die Eingabe In den Konfigurationsdateien (*.idc, *.kl und *.kcm) wird gesucht. /etc/usr-Verzeichnis des APEX.
  • ro.vulkan.apex=<apex name> – wenn festgelegt, wird der Vulkan-Treiber aus dem APEX geladen. Da der Vulkan-Treiber von frühen HALs verwendet wird, müssen Sie APEX als Bootstrap APEX festlegen und diesen Linker-Namespace sichtbar konfigurieren.

Legen Sie die Systemeigenschaften in init-Skripts mithilfe von setprop fest. .

Zusätzliche Entwicklungsfunktionen

APEX-Auswahl beim Starten

Beispiel:

Entwickler können auch mehrere Versionen von Anbieter-APEX installieren, die den gleichen denselben APEX-Namen und -Schlüssel und wählen Sie aus, welche Version jeweils aktiviert wird mit persistenten Sysprops. Bei bestimmten Anwendungsfällen für Entwickler einfacher als die Installation einer neuen APEX-Kopie mit adb install.

Beispiele für Anwendungsfälle:

  • 3 Versionen des WLAN-HAL-Anbieters APEX installieren: QA-Teams können manuelle oder automatische Tests mit einer Version, führen Sie einen Neustart mit einer anderen Version durch und die Tests erneut ausführen und die Endergebnisse vergleichen.
  • Installieren Sie zwei Versionen des Kamera-HAL-Anbieters APEX, aktuell und experimentell:Dogfooder können die experimentelle Version ohne eine zusätzliche Datei herunterladen und installieren, damit sie einfach zurückwechseln können.

Beim Start sucht apexd nach Sysprops mit einem bestimmten Format, die richtige APEX-Version zu aktivieren.

Für den Attributschlüssel werden folgende Formate erwartet:

  • Bootconfig
    • Wird verwendet, um den Standardwert in BoardConfig.mk festzulegen.
    • androidboot.vendor.apex.<apex name>
  • Persistente Sysprop
    • Wird zum Ändern des Standardwerts auf einem bereits gestarteten Gerät verwendet.
    • Überschreibt den Wert „bootconfig“, falls vorhanden.
    • persist.vendor.apex.<apex name>

Der Wert der Eigenschaft sollte der Dateiname des APEX sein. Dieser sollte aktiviert.

// Default version.
apex {
  name: "com.oem.camera.hal.my_apex_default",
  vendor: true,
  ..
}

// Non-default version.
apex {
  name: "com.oem.camera.hal.my_apex_experimental",
  vendor: true,
  ..
}

Die Standardversion sollte auch mit bootconfig in BoardConfig.mk:

# Example for APEX "com.oem.camera.hal" with the default above:
BOARD_BOOTCONFIG += \
    androidboot.vendor.apex.com.oem.camera.hal=com.oem.camera.hal.my_apex_default

Ändern Sie nach dem Starten des Geräts die aktivierte Version, indem Sie das persistente Sysprop festlegen:

$ adb root;
$ adb shell setprop \
    persist.vendor.apex.com.oem.camera.hal \
    com.oem.camera.hal.my_apex_experimental;
$ adb reboot;

Wenn das Gerät die Aktualisierung von bootconfig nach dem Flashen unterstützt (z. B. über fastboot oem-Befehle), muss das Attribut „bootconfig“ für die Mehrfachinstallation Außerdem ändert APEX die beim Booten aktivierte Version.

Bei virtuellen Referenzgeräten auf Basis von Cuttlefish können Sie die Bootconfig-Eigenschaft direkt beim Starten mit dem Befehl --extra_bootconfig_args festlegen. Beispiel:

launch_cvd --noresume \
  --extra_bootconfig_args "androidboot.vendor.apex.com.oem.camera.hal:=com.oem.camera.hal.my_apex_experimental";