RenderScript è un framework per l'esecuzione di attività ad alta intensità di calcolo su Android ad alte prestazioni. È progettata per l'utilizzo con il calcolo parallelo dei dati, anche se i carichi di lavoro seriali possono trarre vantaggio. Il runtime di RenderScript esegue in parallelo il lavoro sui processori disponibili su un dispositivo, ad esempio CPU e GPU multi-core, consentendo agli sviluppatori di concentrarsi sull'espressione degli algoritmi anziché sulla pianificazione del lavoro. RenderScript è particolarmente utile per le app che eseguono l'elaborazione delle immagini, la fotografia computazionale o la visione artificiale.
I dispositivi con Android 8.0 e versioni successive utilizzano il seguente framework RenderScript e gli HAL del fornitore:
Figura 1. Codice del fornitore che rimanda alle librerie interne.
Le differenze rispetto a RenderScript in Android 7.x e versioni precedenti includono:
- Due istanze di librerie interne di RenderScript in un processo. Un set è per il percorso di riserva della CPU e parte direttamente da
/system/lib
; l'altro set è per il percorso della GPU e parte da/system/lib/vndk-sp
. - Le librerie interne di RSA in
/system/lib
sono create come parte della piattaforma e vengono aggiornate all'upgrade disystem.img
. Tuttavia, le librerie in/system/lib/vndk-sp
vengono compilate per il fornitore e non vengono aggiornate quando viene eseguito l'upgrade disystem.img
(sebbene possano essere aggiornate per una correzione di sicurezza, il loro ABI rimane invariato). - Il codice del fornitore (HAL RS, driver RS e
bcc plugin
) è collegato alle librerie interne di RenderScript situate in/system/lib/vndk-sp
. Non possono eseguire il collegamento alle librerie in/system/lib
perché le librerie in quella directory sono compilate per la piattaforma e potrebbero non essere compatibili con il codice del fornitore (ad es. i simboli potrebbero essere rimossi). In questo modo, un aggiornamento OTA solo del framework sarebbe impossibile.
Design
Le sezioni seguenti descrivono nel dettaglio la progettazione di RenderScript in Android 8.0 e versioni successive.
Librerie RenderScript disponibili per i fornitori
Questa sezione elenca le librerie RenderScript (note come Vendor NDK per HAL nello stesso processo o VNDK-SP) disponibili per il codice del fornitore e a cui è possibile eseguire il collegamento. Descrive inoltre librerie aggiuntive non correlate a RenderScript, ma fornite anche al codice del fornitore.
Sebbene il seguente elenco di librerie possa variare da una release di Android all'altra,
è immutabile per una release Android specifica. Per un elenco aggiornato delle
librerie disponibili, consulta /system/etc/ld.config.txt
.
Librerie RenderScript | Libre non di rendering |
---|---|
|
|
Configurazione dello spazio dei nomi del linker
La limitazione del collegamento che impedisce l'utilizzo delle librerie non presenti in VNDK-SP da parte del codice del fornitore viene applicata in fase di esecuzione utilizzando lo spazio dei nomi del linker. Per maggiori dettagli, consulta la presentazione VNDK Design.
Su un dispositivo con Android 8.0 e versioni successive, tutti gli HAL dello stesso processo (SP-HAL)
tranne RenderScript vengono caricati all'interno dello spazio dei nomi del linker
sphal
. RenderScript viene caricato nello spazio dei nomi rs
specifico di RenderScript, una posizione che consente un'applicazione leggermente meno rigorosa delle librerie RenderScript. Poiché l'implementazione RS deve caricare il bitcode compilato, /data/*/*.so
viene aggiunto al percorso dello spazio dei nomi rs
(altri SP-HAL non possono caricare librerie dalla partizione dati).
Inoltre, lo spazio dei nomi rs
consente più librerie rispetto a quelle fornite da altri spazi dei nomi. libmediandk.so
e libft2.so
sono esposti allo spazio dei nomi rs
perché
libRS_internal.so
ha una dipendenza interna da queste librerie.
Figura 2. Configurazione dello spazio dei nomi per il linker.
Carica i driver
Percorso di riserva della CPU
A seconda dell'esistenza del bit RS_CONTEXT_LOW_LATENCY
durante la creazione di un contesto RS, viene selezionato il percorso della CPU o della GPU. Quando viene selezionato il percorso della CPU, libRS_internal.so
(l'implementazione principale del framework RS) viene dlopen
direttamente dal namespace del linker predefinito in cui è fornita la versione della piattaforma delle librerie RS.
L'implementazione RS HAL del fornitore non viene utilizzata quando si utilizza il percorso di fallback della CPU e viene creato un oggetto RsContext
con mVendorDriverName
nullo. libRSDriver.so
è (per impostazione predefinita) dlopen
ed e il driver lib viene caricato dallo spazio dei nomi default
perché il chiamante (libRS_internal.so
) viene caricato anche nello spazio dei nomi default
.
Figura 3. Percorso di riserva della CPU.
Percorso GPU
Per il percorso della GPU, libRS_internal.so
viene caricato in modo diverso.
Innanzitutto, libRS.so
utilizza
android.hardware.renderscript@1.0.so
(e il relativo
libhidltransport.so
) per caricare
android.hardware.renderscript@1.0-impl.so
(un'implementazione del fornitore
dell'HAL RS) in uno spazio dei nomi del linker diverso chiamato
sphal
. L'HAL RSdlopen
libRS_internal.so
in un altro
spazio dei nomi del linker chiamato rs
.
I fornitori possono fornire il proprio driver RS impostando il flag di compilazione
OVERRIDE_RS_DRIVER
, incorporato nell'implementazione
HAL RS
(hardware/interfaces/renderscript/1.0/default/Context.cpp
). Il nome di questo
driver viene quindi dlopen
per il contesto RS per il percorso GPU.
La creazione dell'oggetto RsContext
è delegata all'implementazione RS HAL. L'HAL richiama il framework RS utilizzando
la funzione rsContextCreateVendor()
con il nome del driver da usare come argomento. Il framework RS carica quindi il driver specificato quando RsContext
viene inizializzato. In questo caso, la libreria del driver viene caricata nello spazio dei nomi rs
perché l'oggetto RsContext
viene creato all'interno dello spazio dei nomi rs
e /vendor/lib
si trova nel percorso di ricerca dello spazio dei nomi.
Figura 4. Percorso di riserva della GPU.
Durante la transizione dallo spazio dei nomi default
allo spazio dei nomi sphal
, libhidltransport.so
utilizza la funzione android_load_sphal_library()
per ordinare esplicitamente al linker dinamico di caricare la libreria -impl.so
dallo spazio dei nomi sphal
.
Quando si passa dallo spazio dei nomi sphal
allo spazio dei nomi rs
, il caricamento viene eseguito indirettamente dalla seguente riga in /system/etc/ld.config.txt
:
namespace.sphal.link.rs.shared_libs = libRS_internal.so
Questa riga specifica che il linker dinamico deve caricare libRS_internal.so
dallo spazio dei nomi rs
quando la libreria non può essere trovata/caricata dallo spazio dei nomi sphal
(il che accade sempre perché lo spazio dei nomi sphal
non esegue ricerche in /system/lib/vndk-sp
, dove risiede libRS_internal.so
). Con questa configurazione, una semplice chiamata dlopen()
a
libRS_internal.so
è sufficiente per eseguire la transizione dello spazio dei nomi.
Carica il plug-in Ccn
bcc plugin
è una libreria fornita dal fornitore caricata nel compilatore bcc
. Poiché bcc
è un processo di sistema nella directory /system/bin
, la raccolta bcc plugin
può essere considerata un HAL SP (ovvero un HAL del fornitore che può essere caricato direttamente nel processo di sistema senza essere associato). In qualità di SP-HAL, la
libreria bcc-plugin
:
- Non è possibile eseguire il collegamento a librerie solo per framework come
libLLVM.so
. - Può eseguire il collegamento solo alle librerie VNDK-SP disponibili per il fornitore.
Questa limitazione viene applicata caricando bcc plugin
nello spazio dei nomi sphal
utilizzando la funzione android_sphal_load_library()
. Nelle versioni precedenti di Android, il nome del plug-in veniva specificato utilizzando l'opzione -load
e la libreria veniva caricata utilizzando il semplice dlopen()
da libLLVM.so
. In Android 8.0 e versioni successive, questo valore è specificato nell'opzione -plugin
e la libreria viene caricata direttamente da -plugin
.bcc
Questa opzione abilita un percorso non specifico di Android al progetto LLVM open source.
Figura 5. Caricamento del plug-in bcc, Android 7.x e versioni precedenti.
Figura 6. Caricamento del plug-in bcc, Android 8.0 e versioni successive.
Percorsi di ricerca per ld.mc
Durante l'esecuzione di ld.mc
, alcune librerie di runtime RS vengono fornite come input
per il linker. Il bitcode RS dell'app è collegato alle librerie di runtime
e quando il bitcode convertito viene caricato in un processo dell'app, le librerie di runtime
vengono nuovamente collegate dinamicamente dal bitcode convertito.
Le librerie di runtime includono:
libcompiler_rt.so
libm.so
libc.so
- Driver RS (
libRSDriver.so
oOVERRIDE_RS_DRIVER
)
Quando carichi il bitcode compilato nel processo dell'app, fornisci la stessa identica libreria utilizzata da ld.mc
. In caso contrario, il bitcode compilato potrebbe non trovare un simbolo disponibile quando è stato collegato.
A tale scopo, il framework RS utilizza percorsi di ricerca diversi per le librerie di runtime durante l'esecuzione di ld.mc
, a seconda che il framework RS stesso sia caricato da /system/lib
o da /system/lib/vndk-sp
.
Questo può essere determinato leggendo l'indirizzo di un simbolo arbitrario di una libreria del framework RS
e utilizzando dladdr()
per ottenere il percorso del file mappato all'indirizzo.
Criterio SELinux
A seguito delle modifiche ai criteri SELinux in Android 8.0 e versioni successive, devi seguire regole specifiche (applicate tramite neverallows
) quando etichetti file aggiuntivi nella partizione vendor
:
vendor_file
deve essere l'etichetta predefinita per tutti i file dellavendor
partizione. Il criterio della piattaforma lo richiede per accedere alle implementazioni HAL passthrough.- Tutti i nuovi
exec_types
aggiunti nella partizionevendor
tramite SEPolicy del fornitore devono avere l'attributovendor_file_type
. Questa impostazione viene applicata tramiteneverallows
. - Per evitare conflitti con i futuri aggiornamenti della piattaforma/del framework, evita di etichettare
file diversi da
exec_types
nella partizionevendor
. - Tutte le dipendenze della libreria per gli HAL dello stesso processo identificati da AOSP devono essere contrassegnate come
same_process_hal_file
.
Per informazioni dettagliate sui criteri SELinux, consulta Security-Enhanced Linux in Android.
Compatibilità ABI per il codice bit
Se non vengono aggiunte nuove API, ovvero non viene eseguito l'upgrade della versione HAL, i framework RS continueranno a utilizzare il driver GPU esistente (HAL 1.0).
Per modifiche minori all'HAL (HAL 1.1) che non influiscono sul codice bit, i framework dovrebbero eseguire il fallback alla CPU per queste API appena aggiunte e continuare a utilizzare il driver GPU (HAL 1.0) altrove.
Per modifiche importanti all'HAL (HAL 2.0) che interessano la compilazione/il collegamento del codice bit, i framework RS devono scegliere di non caricare i driver GPU forniti dal fornitore e utilizzare invece il percorso CPU o Vulkan per l'accelerazione.
Il consumo del codice bit RenderScript avviene in tre fasi:
Palcoscenico | Dettagli |
---|---|
Compila |
|
Link |
|
Carica |
|
Oltre all'HAL, anche le API di runtime e i simboli esportati sono interfacce. Nessuna delle due interfacce è cambiata da Android 7.0 (API 24) e non sono previsti piani immediati per modificarle in Android 8.0 e versioni successive. Tuttavia, se l'interfaccia cambia, aumenta anche la versione HAL.
Implementazioni dei fornitori
Android 8.0 e versioni successive richiedono alcune modifiche al driver GPU per il suo corretto funzionamento.
Moduli del driver
- I moduli del driver non devono dipendere da librerie di sistema non presenti nell'elenco.
- Il driver deve fornire il proprio
android.hardware.renderscript@1.0-impl_{NAME}
o dichiarare l'implementazione predefinitaandroid.hardware.renderscript@1.0-impl
come dipendenza. - L'implementazione della CPU
libRSDriver.so
è un buon esempio di come rimuovere le dipendenze non VNDK-SP.
Compilatore di bitcode
Puoi compilare il codice bit RenderScript per il driver del fornitore in due modi:
- Richiama il compilatore RenderScript specifico del fornitore in
/vendor/bin/
(metodo preferito di compilazione della GPU). Come per gli altri moduli del driver, il codice binario del compilatore del fornitore non può dipendere da librerie di sistema non presenti nell'elenco delle librerie RenderScript disponibili per i fornitori. - Richiama il Ccn del sistema:
/system/bin/bcc
con unbcc plugin
fornito dal fornitore; questo plug-in non può dipendere da alcuna libreria di sistema che non è nell'elenco delle librerie di RenderScript disponibili per i fornitori.
Se il fornitore bcc plugin
deve interferire con la compilazione della CPU
e la sua dipendenza da libLLVM.so
non può essere facilmente
rimossa, il fornitore deve copiare bcc
(e tutte le dipendenze non LL-NDK, tra cui libLLVM.so
, libbcc.so
) nella
partizione /vendor
.
Inoltre, i fornitori devono apportare le seguenti modifiche:
Figura 7. Modifiche al driver del fornitore.
- Copia
libclcore.bc
nella partizione/vendor
. In questo modo,libclcore.bc
,libLLVM.so
elibbcc.so
sono sincronizzati. - Modifica il percorso del file eseguibile
bcc
impostandoRsdCpuScriptImpl::BCC_EXE_PATH
dall'implementazione dell'HAL RS.
Criterio SELinux
Il criterio SELinux influisce sia sul driver sia sugli eseguibili del compilatore. Tutti
i moduli del driver devono essere etichettati come same_process_hal_file
nel
file_contexts
del dispositivo. Ad esempio:
/vendor/lib(64)?/libRSDriver_EXAMPLE\.so u:object_r:same_process_hal_file:s0
L'eseguibile del compilatore deve essere richiamabile da un processo dell'app, così come la copia del fornitore di bcc (/vendor/bin/bcc
). Ad esempio:
device/vendor_foo/device_bar/sepolicy/file_contexts: /vendor/bin/bcc u:object_r:same_process_hal_file:s0
Dispositivi legacy
I dispositivi legacy sono quelli che soddisfano le seguenti condizioni:
- PRODUCT_SHIPPING_API_LEVEL è inferiore a 26.
- PRODUCT_FULL_TREBLE_OVERRIDE non è definito.
Per i dispositivi precedenti, le limitazioni non vengono applicate durante l'upgrade ad Android 8.0 e versioni successive, il che significa che i driver possono continuare a collegarsi alle librerie in /system/lib[64]
. Tuttavia, a causa della modifica dell'architettura
relativa a OVERRIDE_RS_DRIVER
,
android.hardware.renderscript@1.0-impl
deve essere installato nella
partizione /vendor
; in caso contrario, il fallback del runtime di RenderScript
viene forzato sul percorso della CPU.
Per informazioni sul motivo del ritiro di Renderscript, consulta il blog Android for Developers: Android GPU Compute Going Forward. Le informazioni sulle risorse per questo ritiro includono quanto segue:
- Eseguire la migrazione da Renderscript
- Esempio di RenderScriptMigration
- File README del toolkit di sostituzione degli elementi intrinseci
- Sostituzione di IntrinsicsToolkit.kt