Usa IPC binder

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 upstream

Per 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 upstream

Nelle 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 upstream

Nelle 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 numero elevato di dispositivi diversi; in quanto 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:

  1. Accedi a /dev/vndbinder.
  2. Aggancia {transfer, call} raccoglitore in vndservicemanager.
  3. 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.
  4. Autorizzazione per {add, find} servizi in vndservicemanager.

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;