In questa pagina vengono descritte le modifiche al driver binder in Android 8, fornisce i dettagli sull'utilizzo dell'IPC binder ed elenca i criteri SELinux richiesti.
Modifiche al driver binder
A partire da Android 8, il framework Android e gli HAL ora comunicano utilizzando binder. Poiché questa comunicazione aumenta drasticamente la capacità di legatura traffico, Android 8 include diversi miglioramenti progettati per mantenere gli IPC di binder rapidamente. I fornitori di SoC e gli OEM devono fondersi direttamente dalle filiali pertinenti di android-4.4, android-4.9 e versioni successive di kernel/common.
Più domini binder (contesti)
Common-4.4 e versioni successive, incluso upstreamPer suddividere in modo chiaro il traffico binder tra framework (indipendente dal dispositivo) e del fornitore (specifico del dispositivo), Android 8 ha introdotto il concetto di raccoglitore contesto. Ogni contesto binder ha il proprio nodo dispositivo e il proprio contesto (servizio). Puoi accedere a Gestore contesto solo tramite il dispositivo nodo a cui appartiene e, quando passa un nodo binder attraverso un contesto, è accessibile dallo stesso contesto solo da un altro processo, isolando completamente i domini l'uno dall'altro. Per maggiori dettagli sull'utilizzo, vedi vndbinder e vndservicemanager.
Raccoglitore a dispersione
Common-4.4 e versioni successive, incluso upstreamNelle versioni precedenti di Android, ogni dato contenuto in una chiamata a Binder veniva copiato tre volte:
- Poi serializzarlo in un
Parcel
nel processo di chiamata - Una volta nel driver del kernel per copiare
Parcel
nella destinazione di elaborazione - Dopo aver annullato la serializzazione di
Parcel
nel processo di destinazione
Android 8 utilizza
dispersione
ottimizzazione per ridurre il numero di copie da 3 a 1. Invece di
serializzare prima i dati in un Parcel
, i dati rimangono nella versione originale
struttura e layout della memoria e il driver la copia immediatamente
e il processo di sviluppo. Quando i dati sono nel processo di destinazione, la struttura e la memoria
è lo stesso e i dati possono essere letti senza bisogno di un'altra copia.
Blocco granulare
Common-4.4 e versioni successive, incluso upstreamNelle versioni precedenti di Android, il driver di binder utilizzava un blocco globale contro l'accesso simultaneo a strutture di dati critiche. Anche se la quantità minima il blocco, il problema principale era che se un thread a bassa priorità il blocco è stato prerilasciato, si potrebbe ritardare i thread a priorità più alta che devono ottenere lo stesso blocco. Questo causava un blocco completamente gestita.
I primi tentativi per risolvere il problema hanno comportato la disattivazione della prerilascio mentre che tiene il blocco globale. Tuttavia, si trattava più di una compromissione che di una vera soluzione, e alla fine è stato rifiutato dall'upstream ed eliminato. Tentativi successivi sul rendere più granulare il blocco, una versione della quale è in esecuzione sui dispositivi Pixel da gennaio 2017. Sebbene la maggior parte di queste modifiche sia resi pubblici, nelle versioni successive sono stati apportati miglioramenti sostanziali.
Dopo aver identificato i piccoli problemi nell'implementazione di blocco granulare, Hanno ideato una soluzione migliore con un'architettura di blocco diversa e hanno inviato le modifiche in tutti i rami del kernel comuni. Continuiamo a testarlo l'implementazione su un gran numero di dispositivi diversi; perché non siamo a conoscenza di problemi in sospeso, questa è l'implementazione consigliata per la spedizione dei dispositivi con Android 8.
Eredità delle priorità in tempo reale
Common-4.4 e common-4.9 (upstream disponibile a breve)Il driver binder ha sempre supportato una buona ereditarietà prioritaria. Come il numero crescente di processi in Android viene eseguito con priorità in tempo reale, in alcune casi ora ha senso che se un thread in tempo reale effettua una chiamata a raccoglitore, il thread nel processo che gestisce la chiamata viene eseguito con priorità in tempo reale. A supporta questi casi d'uso, Android 8 ora implementa l'ereditarietà della priorità in tempo reale nel driver raccoglitore.
Oltre all'ereditarietà della priorità a livello di transazione, la priorità dei nodi l'ereditarietà consente a un nodo (oggetto di servizio binder) di specificare la priorità con cui devono essere eseguite le chiamate al nodo. Versioni precedenti di Android supportava già l'ereditarietà della priorità dei nodi con valori validi, ma Android 8 aggiunge il supporto per l'ereditarietà dei nodi di pianificazione in tempo reale.
Modifiche dello spazio utente
Android 8 include tutte le modifiche allo spazio utente necessarie per funzionare con l'attuale
binder nel kernel comune, con un'eccezione: l'originale
per disabilitare l'ereditarietà in tempo reale per
/dev/binder
ha usato un
ioctl, Lo sviluppo successivo ha cambiato il controllo della priorità
l'ereditarietà a un metodo più granulare in base alla modalità binder (e non
contesto). Pertanto, ioctl non si trova nel ramo comune di Android, ma
inviate nei nostri kernel comuni.
L'effetto di questa modifica è che l'ereditarietà in tempo reale è disabilitata
predefinito per ogni nodo. Il team responsabile delle prestazioni di Android l'ha trovato
è utile abilitare l'ereditarietà della priorità in tempo reale per tutti i nodi
Dominio hwbinder
. Per ottenere lo stesso effetto,
questa modifica nello spazio utente.
SHA per kernel comuni
Per ottenere le modifiche necessarie al driver di binder, esegui la sincronizzazione con l'SHA appropriata:
- Comune-3,18
cc8b90c121de ANDROID: binder: non controllare le autorizzazioni principali sul ripristino. - Comune-4,4
76b376eac7a2 ANDROID: binder: non controllare le autorizzazioni prioritarie sul ripristino. - Comune-4,9
ecd972d4f9b5 ANDROID: binder: non controllare le autorizzazioni prio sul ripristino.
Utilizzo dell'IPC di binder
Storicamente, i processi dei fornitori hanno utilizzato una comunicazione tra processi di binder
(IPC) per comunicare. In Android 8, il nodo dispositivo /dev/binder
diventa esclusivo per i processi framework, il che significa che i processi dei fornitori
vi abbiano accesso. I processi del fornitore possono accedere a /dev/hwbinder
, ma
devono convertire le interfacce AIDL per utilizzare l'HIDL. Per i fornitori che vogliono continuare
usando interfacce AIDL tra i processi dei fornitori, Android supporta
descritti di seguito. In Android 10, lo standard AIDL stabile consente
per utilizzare /dev/binder
e risolvere al contempo la stabilità
garantisce la risoluzione di HIDL e /dev/hwbinder
. Per informazioni su come utilizzare il canale stabile
AIDL, vedi
AIDL per HAL.
Vndbinder
Android 8 supporta un nuovo dominio binder per l'utilizzo da parte dei servizi dei fornitori, a cui accede
utilizzando /dev/vndbinder
anziché /dev/binder
. Con
aggiunta di /dev/vndbinder
, Android ora ha le seguenti tre
Domini IPC:
Dominio IPC | Descrizione |
---|---|
/dev/binder |
IPC tra framework/processi dell'app con interfacce AIDL |
/dev/hwbinder |
IPC tra framework/processi del fornitore con interfacce HIDL
IPC tra i processi del fornitore con le interfacce HIDL |
/dev/vndbinder |
IPC tra i processi di fornitore/fornitore con interfacce AIDL |
Affinché venga visualizzato /dev/vndbinder
, assicurati che la configurazione del kernel
l'elemento CONFIG_ANDROID_BINDER_DEVICES
è impostato su
"binder,hwbinder,vndbinder"
(impostazione predefinita nei
alberi di kernel comuni).
Normalmente, i processi del fornitore non aprono direttamente il driver binder, ma
rispetto alla libreria dello spazio utente libbinder
, che apre
raccoglitore di documenti. Aggiunta di un metodo per ::android::ProcessState()
in corso...
seleziona il driver binder per libbinder
. I processi del fornitore
chiama questo metodo prima di chiamare ProcessState,
IPCThreadState
o prima di effettuare chiamate a binder in generale. A
usa, effettua la seguente chiamata dopo il main()
di un processo del fornitore
(client e server):
ProcessState::initWithDriver("/dev/vndbinder");
serviziovndservicemanager
In precedenza, i servizi per la rilegatura erano registrati con servicemanager
,
dove potrebbero essere recuperati
da altri processi. In Android 8,
servicemanager
viene ora utilizzato esclusivamente per framework e app
da parte dei processi e dei fornitori non
potranno più accedervi.
Tuttavia, i servizi dei fornitori ora possono utilizzare vndservicemanager
, una nuova
istanza di servicemanager
che utilizza /dev/vndbinder
anziché /dev/binder
e che è stato creato dalle stesse origini di
il framework servicemanager
. I processi del fornitore non devono
modifiche per comunicare con vndservicemanager
; quando un processo del fornitore si apre
/dev/vndbinder
, le ricerche dei servizi passano automaticamente a
vndservicemanager
.
Il programma binario vndservicemanager
è incluso nell'impostazione predefinita di Android
i file creati dai dispositivi.
Criterio SELinux
Processi del fornitore che vogliono utilizzare la funzionalità di binder per comunicare con occorre quanto segue:
- Accedi a
/dev/vndbinder
. - Aggancia
{transfer, call}
raccoglitore invndservicemanager
. binder_call(A, B)
per qualsiasi dominio del fornitore A che vuole chiamare nel dominio del fornitore B tramite l'interfaccia del raccoglitore dei fornitori.- Autorizzazione per
{add, find}
servizi invndservicemanager
.
Per soddisfare i requisiti 1 e 2, utilizza vndbinder_use()
:
vndbinder_use(some_vendor_process_domain);
Per soddisfare il requisito 3, il binder_call(A, B)
per il fornitore
i processi A e B che devono analizzare il binder possono rimanere fermi e
devono essere rinominati.
Per soddisfare il requisito 4, devi modificare il modo in cui nomi dei servizi, vengono gestite le etichette di servizio e le regole.
Per maggiori dettagli su SELinux, consulta Security-Enhanced Linux su Android. Per maggiori dettagli su SELinux in Android 8.0, vedi SELinux per Android 8,0.
Nomi dei servizi
In precedenza, il fornitore elabora i nomi dei servizi registrati
service_contexts
file e regole corrispondenti aggiunte per l'accesso
quel file. File service_contexts
di esempio da
device/google/marlin/sepolicy
:
AtCmdFwd u:object_r:atfwd_service:s0 cneservice u:object_r:cne_service:s0 qti.ims.connectionmanagerservice u:object_r:imscm_service:s0 rcs u:object_r:radio_service:s0 uce u:object_r:uce_service:s0 vendor.qcom.PeripheralManager u:object_r:per_mgr_service:s0
In Android 8, vndservicemanager
carica
vndservice_contexts
. Migrazione di servizi dei fornitori a
vndservicemanager
(e che sono già nel vecchio
service_contexts
file) deve essere aggiunto al nuovo
vndservice_contexts
file.
Etichette servizio
In precedenza, etichette di servizio come u:object_r:atfwd_service:s0
sono state definite in un file service.te
. Esempio:
type atfwd_service, service_manager_type;
In Android 8, devi modificare il tipo in
vndservice_manager_type
e sposta la regola in
vndservice.te
file. Esempio:
type atfwd_service, vndservice_manager_type;
regole servicemanager
In precedenza, le regole concedevano ai domini l'accesso per aggiungere o trovare servizi
servicemanager
. Esempio:
allow atfwd atfwd_service:service_manager find; allow some_vendor_app atfwd_service:service_manager add;
In Android 8, queste regole possono rimanere attive e utilizzare la stessa classe. Esempio:
allow atfwd atfwd_service:service_manager find; allow some_vendor_app atfwd_service:service_manager add;