Fornitore APEX

Puoi utilizzare il formato file APEX per pacchettizzare e installare moduli del sistema operativo Android di livello inferiore. Consente la compilazione e l'installazione indipendenti di componenti come servizi e librerie native, implementazioni HAL, firmware, file di configurazione e così via.

I file APEX del fornitore vengono installati automaticamente dal sistema di compilazione nella partizione /vendor e attivati in fase di esecuzione da apexd, proprio come i file APEX in altre partizioni.

Casi d'uso

Modularizzazione delle immagini dei fornitori

Gli APEX facilitano il naturale raggruppamento e la modularizzazione delle caratteristiche le implementazioni delle immagini dei fornitori.

Quando le immagini del fornitore vengono create come combinazione di fornitori creati in modo indipendente APEX, i produttori di dispositivi possono selezionare e scegliere facilmente le implementazioni richieste dai fornitori sul loro dispositivo. I produttori possono anche creare una l'APEX del nuovo fornitore se nessuno degli APEX forniti soddisfa le sue esigenze o se hardware personalizzato completamente nuovo.

Ad esempio, un OEM potrebbe scegliere di comporre il proprio dispositivo con l'APEX di implementazione del Wi-Fi AOSP, l'APEX di implementazione del Bluetooth SoC e un APEX di implementazione della telefonia OEM personalizzato.

Senza APEX del fornitore, un'implementazione con così tante dipendenze tra i componenti del fornitore richiede un attento coordinamento e monitoraggio. Includendo tutti (inclusi file di configurazione e librerie aggiuntive) negli APEX con interfacce chiaramente definite in ogni punto di comunicazione tra funzionalità, i vari componenti diventano intercambiabili.

Iterazione dello sviluppatore

Gli APEX del fornitore aiutano gli sviluppatori a eseguire l'iterazione più velocemente durante lo sviluppo dei moduli del fornitore raggruppando un'intera implementazione della funzionalità, come l'HAL Wi-Fi, all'interno di un APEX del fornitore. Gli sviluppatori possono quindi creare ed eseguire il push dell'APEX del fornitore per testarlo delle modifiche, anziché ricreare l'intera immagine del fornitore.

In questo modo, il ciclo di iterazione degli sviluppatori viene semplificato e accelerato per gli sviluppatori che lavorano principalmente in un'area di funzionalità e vogliono eseguire l'iterazione solo su quella.

Anche il naturale raggruppamento di un'area di caratteristiche in un APEX semplifica il processo di creazione, push e test delle modifiche per quell'area delle caratteristiche. Ad esempio, la reinstallazione di un APEX aggiorna automaticamente eventuali file di configurazione o librerie inclusi nell'APEX.

Il raggruppamento di un'area di funzionalità in un APEX semplifica anche il debug o il ripristino quando viene osservato un comportamento anomalo del dispositivo. Ad esempio, se la telefonia non funziona correttamente in una nuova build, gli sviluppatori potrebbero provare a installare un APEX di implementazione della telefonia precedente su un dispositivo (senza dover eseguire il flashing di una build completa) e verificare se il comportamento corretto viene ripristinato.

Esempio di flusso di lavoro:

# 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 ...

Esempi

Nozioni di base

Consulta la pagina principale Formato file APEX per l'APEX generico informazioni, tra cui i requisiti dei dispositivi, i dettagli dei formati dei file e i passaggi per l'installazione.

In Android.bp, l'impostazione della proprietà vendor: true rende un modulo APEX un APEX del fornitore.

apex {
  ..
  vendor: true,
  ..
}

Binari e librerie condivise

Un APEX include dipendenze trasitive all'interno del payload APEX, a meno che non abbiano interfacce stabili.

Le interfacce native stabili per le dipendenze APEX del fornitore includono cc_library con stubs e LLNDK. Queste dipendenze sono escluse la pacchettizzazione e le dipendenze vengono registrate nel manifest APEX. Il file manifest è elaborati da linkerconfig in modo che le dipendenze native esterne disponibili in fase di runtime.

Nel seguente snippet, l'APEX contiene sia il file binario (my_service) che i relativi delle dipendenze non stabili (*.so file).

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

Nel seguente snippet, il file APEX contiene la libreria condivisamy_standalone_lib e le eventuali dipendenze non stabili (come descritto sopra).

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

Riduci APEX

APEX potrebbe aumentare di dimensioni perché raggruppa dipendenze non stabili. I nostri suggerimenti tramite link statici. Le librerie comuni come libc++.so e libbase.so possono essere collegate staticamente ai file binari HAL. Un'altra opzione è creare una dipendenza per fornire un'interfaccia stabile. La dipendenza non verrà inclusa in APEX.

Implementazioni HAL

Per definire un'implementazione HAL, fornisci i file binari e le librerie corrispondenti all'interno dell'APEX di un fornitore, come nei seguenti esempi:

Per incapsulare completamente l'implementazione HAL, l'APEX deve anche specificare qualsiasi frammenti VINTF e script di inizializzazione pertinenti.

Frammenti VINTF

I frammenti VINTF possono essere forniti dall'APEX di un fornitore quando i frammenti si trovano in etc/vintf dell'APEX.

Utilizza la proprietà prebuilts per incorporare i frammenti VINTF nell'APEX.

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

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

API di query

Quando i frammenti VINTF vengono aggiunti ad APEX, utilizza le API libbinder_ndk per ottenere le mappature delle interfacce HAL e dei nomi APEX.

  • AServiceManager_isUpdatableViaApex("com.android.foo.IFoo/default") : true se l'istanza HAL è definita in APEX.
  • AServiceManager_getUpdatableApexName("com.android.foo.IFoo/default", ...) : ottiene il nome APEX che definisce l'istanza HAL.
  • AServiceManager_openDeclaredPassthroughHal("mapper", "instance", ...): utilizza questa opzione per aprire un HAL passthrough.

Script di inizializzazione

Gli APEX possono includere script di inizializzazione in due modi: (A) un file di testo precompilato all'interno del payload APEX o (B) un normale script di inizializzazione in /vendor/etc. Puoi impostare entrambi per lo stesso APEX.

Script di inizializzazione in APEX:

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

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

Gli script di inizializzazione negli APEX del fornitore possono avere definizioni di service e on <property or event>.

Assicurati che una definizione service indichi un file binario nello stesso APEX. Ad esempio, com.android.foo APEX può definire un servizio denominato foo-service.

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

Fai attenzione quando usi istruzioni on. Poiché gli script di inizializzazione negli APEX vengono analizzati ed eseguiti dopo l'attivazione degli APEX, alcuni eventi o proprietà non possono essere utilizzate. Utilizza apex.all.ready=true per attivare le azioni il prima possibile. Gli APEX di bootstrap possono utilizzare on init, ma non on early-init.

Firmware

Esempio:

Incorpora il firmware nell'APEX di un fornitore con il tipo di modulo prebuilt_firmware, come .

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 moduli sono installati in <apex name>/etc/firmware dell'APEX. ueventd esegue la scansione delle directory /apex/*/etc/firmware per trovare i moduli del firmware.

Il file_contexts dell'APEX deve etichettare correttamente le eventuali voci del payload del firmware per garantire che questi file siano accessibili da ueventd in fase di esecuzione. In genere, l'etichetta vendor_file è sufficiente. Ad esempio:

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

Moduli del kernel

Incorpora i moduli del kernel in un APEX del fornitore come moduli predefiniti, come segue.

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

Il file_contexts dell'APEX deve etichettare qualsiasi voce di payload del modulo kernel correttamente. Ad esempio:

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

I moduli del kernel devono essere installati in modo esplicito. Lo script di inizializzazione dell'esempio seguente nella partizione del fornitore mostra l'installazione tramite insmod:

my_init.rc:

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

Overlay di risorse di runtime

Esempio:

Incorporano overlay di risorse di runtime nell'APEX di un fornitore utilizzando la proprietà rros.

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


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

Altri file di configurazione

Gli APEX del fornitore supportano vari altri file di configurazione che in genere si trovano sul la partizione è preconfigurata all'interno degli APEX del fornitore e se ne stanno aggiungendo altre.

Esempi:

APEX del fornitore di bootstrap

Alcuni servizi HAL come keymint dovrebbero essere disponibili prima che gli APEX siano è stata attivata. Questi HAL in genere impostano early_hal nella definizione del servizio nello script di inizializzazione. Un altro esempio è la classe animation, che di solito è iniziata prima dell'evento post-fs-data. Quando un servizio HAL precedente è impacchettato nell'APEX del fornitore, crea l'apex "vendorBootstrap": true nel suo manifest APEX in modo che possa essere attivato in precedenza. Tieni presente che gli APEX di bootstrap possono essere attivati solo dalla posizione predefinita, ad esempio /vendor/apex, non da /data/apex.

Proprietà di sistema

Queste sono le proprietà di sistema che il framework legge per supportare gli APEX del fornitore:

  • input_device.config_file.apex=<apex name>: se impostato, l'input di configurazione automatica (*.idc, *.kl e *.kcm) viene eseguita la ricerca da directory /etc/usr dell'APEX.
  • ro.vulkan.apex=<apex name>: se impostato, il driver Vulkan viene caricato da l'APEX. Poiché il driver Vulkan viene utilizzato dai primi HAL, imposta l'APEX Avvia APEX e configura lo spazio dei nomi del linker visibile.

Imposta le proprietà di sistema negli script di inizializzazione utilizzando il comando setprop.

Funzionalità di sviluppo aggiuntive

Selezione di APEX all'avvio

Esempio:

Gli sviluppatori possono anche installare più versioni degli APEX dei fornitori che condividono con lo stesso nome e la stessa chiave APEX, quindi scegli la versione da attivare durante ogni utilizzando sysprop permanenti. Per determinati casi d'uso degli sviluppatori, questa operazione potrebbe essere più semplice rispetto all'installazione di una nuova copia di APEX utilizzando adb install.

Esempi di casi d'uso:

  • Installa 3 versioni dell'APEX del fornitore HAL Wi-Fi: i team QA possono eseguire test manuali o automatici utilizzando una versione, quindi riavviare in un'altra versione e eseguire nuovamente i test, per poi confrontare i risultati finali.
  • Installa due versioni dell'APEX del fornitore HAL per la videocamera, attuale e sperimentale: i dogfood possono utilizzare la versione sperimentale senza scaricano e installano un file aggiuntivo in modo che possano tornare facilmente alla versione precedente.

Durante l'avvio, apexd cerca i sysprop che seguono un formato specifico per attivare la versione APEX corretta.

I formati previsti per la chiave della proprietà sono:

  • Bootconfig
    • Utilizzato per impostare il valore predefinito, in BoardConfig.mk.
    • androidboot.vendor.apex.<apex name>
  • sysprop permanente
    • Utilizzato per modificare il valore predefinito impostato su un dispositivo già avviato.
    • Sostituisce il valore bootconfig, se presente.
    • persist.vendor.apex.<apex name>

Il valore della proprietà deve essere il nome file dell'APEX, che deve essere è stata attivata.

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

La versione predefinita deve essere configurata anche utilizzando 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

Dopo l'avvio del dispositivo, modifica la versione attivata impostando la proprietà sysprop permanente:

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

Se il dispositivo supporta l'aggiornamento di bootconfig dopo il flashing (ad esempio tramite i comandi fastboot oem), la modifica della proprietà bootconfig per APEX installato su più dispositivi modifica anche la versione attivata all'avvio.

Per i dispositivi di riferimento virtuali basati su Cuttlefish, puoi utilizzare il comando --extra_bootconfig_args per impostare la proprietà bootconfig direttamente durante l'avvio. Ad esempio:

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