Verwenden von Binder IPC

Diese Seite beschreibt Änderungen am Binder-Treiber in Android 8, enthält Details zur Verwendung von Binder-IPC und listet die erforderliche SELinux-Richtlinie auf.

Änderungen am Bindertreiber

Ab Android 8 kommunizieren das Android-Framework und HALs jetzt über Binder miteinander. Da diese Kommunikation den Binder-Datenverkehr drastisch erhöht, enthält Android 8 mehrere Verbesserungen, die dafür sorgen, dass Binder-IPC schnell bleibt. SoC - Anbieter und OEMs direkt aus den entsprechenden Zweigen der Android-4.4, android-4,9 und höher der Zusammenführung sollte kernel / gemeinsamen Projekt.

Mehrere Binderdomänen (Kontexte)

Common-4.4 und höher, einschließlich Upstream

Um sauber Split der Bindemittel Verkehr zwischen Rahmen (geräteunabhängig) und Lieferanten (gerätespezifisch) Code, Android 8 führte das Konzept eines Bindemittels Kontextes. Jeder Binderkontext hat seinen eigenen Geräteknoten und seinen eigenen Kontext-(Dienst-)Manager. Sie können auf den Kontextmanager nur über den Geräteknoten zugreifen, zu dem er gehört, und wenn ein Binderknoten durch einen bestimmten Kontext geleitet wird, ist er nur von diesem Kontext aus durch einen anderen Prozess zugänglich, wodurch die Domänen vollständig voneinander isoliert sind. Einzelheiten zur Verwendung finden vndbinder und vndservicemanager .

Streuen sammeln

Common-4.4 und höher, einschließlich Upstream

In früheren Versionen von Android wurde jedes Datenelement in einem Binder-Aufruf dreimal kopiert:

  • Sobald sie in eine serialisiert Parcel in dem rufenden Prozess
  • Einmal in den Kernel - Treiber das kopieren Parcel an den Zielprozess
  • Sobald die unserialize Parcel in den Zielprozess

Android 8 verwendet Verstreutensammel Optimierung der Anzahl der Kopien von 3 bis 1. Statt Serialisieren von Daten in einem reduzieren Parcel ersten, bleiben die Daten in ihrer ursprünglichen Struktur und Speicherlayout und der Fahrer sofort kopiert sie in den Zielprozess. Nachdem sich die Daten im Zielprozess befinden, sind Struktur und Speicherlayout gleich und die Daten können ohne weitere Kopie gelesen werden.

Feinkörnige Verriegelung

Common-4.4 und höher, einschließlich Upstream

In früheren Android-Versionen verwendete der Binder-Treiber eine globale Sperre zum Schutz vor gleichzeitigem Zugriff auf kritische Datenstrukturen. Obwohl es nur minimale Konflikte um die Sperre gab, bestand das Hauptproblem darin, dass, wenn ein Thread mit niedriger Priorität die Sperre erhielt und dann vorzeitig aufgehoben wurde, dies Threads mit höherer Priorität, die dieselbe Sperre benötigen, erheblich verzögern konnte. Dies verursachte einen Ruck in der Plattform.

Anfängliche Versuche, dieses Problem zu lösen, beinhalteten das Deaktivieren der Vorbelegung, während die globale Sperre gehalten wurde. Dies war jedoch eher ein Hack als eine echte Lösung und wurde schließlich vom Upstream abgelehnt und verworfen. Nachfolgende Versuche konzentrierten sich darauf, die Sperrung feinkörniger zu gestalten, von denen eine Version seit Januar 2017 auf Pixel-Geräten ausgeführt wird. Während die meisten dieser Änderungen veröffentlicht wurden, wurden in nachfolgenden Versionen erhebliche Verbesserungen vorgenommen.

Nachdem wir kleine Probleme in der feingranularen Locking-Implementierung identifiziert hatten, haben wir eine verbesserte Lösung mit einer anderen Locking-Architektur entwickelt und die Änderungen in allen gängigen Kernel-Branches eingereicht. Wir testen diese Implementierung weiterhin auf einer großen Anzahl verschiedener Geräte; Da uns keine offenen Probleme bekannt sind, ist dies die empfohlene Implementierung für Geräte, die mit Android 8 ausgeliefert werden.

Prioritätsvererbung in Echtzeit

Common-4.4 und Common-4.9 (Upstream in Kürze)

Der Binder-Treiber hat die Vererbung von netten Prioritäten immer unterstützt. Da immer mehr Prozesse in Android mit Echtzeitpriorität ausgeführt werden, ist es in einigen Fällen jetzt sinnvoll, dass der Thread im Prozess, der diesen Aufruf verarbeitet, auch mit Echtzeitpriorität ausgeführt wird, wenn ein Echtzeit-Thread einen Binder-Aufruf durchführt. . Um diese Anwendungsfälle zu unterstützen, implementiert Android 8 jetzt die Prioritätsvererbung in Echtzeit im Binder-Treiber.

Neben der Transaktionsebene Prioritätsvererbung, Knotenpriorität Vererbung ermöglicht es einem Knoten (Bindemittel Dienstobjekt) eine minimale Priorität angeben , an denen Anrufe in diesem Knoten ausgeführt werden sollte. Frühere Versionen von Android unterstützten bereits die Vererbung der Knotenpriorität mit netten Werten, aber Android 8 bietet Unterstützung für die Knotenvererbung von Planungsrichtlinien in Echtzeit.

Userspace-Änderungen

Android 8 enthält alle User - Space zur Arbeit mit dem aktuellen Bindemitteltreiber im gemeinsamen Kern mit einer Ausnahme erforderlich ändert: Die ursprüngliche Implementierung zu deaktivieren Echtzeit - Prioritätsvererbung für /dev/binder verwendete einen ioctl . Die nachfolgende Entwicklung schaltete die Steuerung der Prioritätsvererbung auf eine feinkörnigere Methode um, die pro Bindermodus (und nicht pro Kontext) gilt. Somit ist die ioctl nicht im Android gemeinsamen Zweig und wird stattdessen in unserem gemeinsamen Kernel eingereicht .

Der Effekt dieser Änderung ist , dass Echtzeit - Prioritätsvererbung wird für jeden Knoten standardmäßig deaktiviert. Die Android - Performance - Team hat es sich vorteilhaft erwiesen , Vererbung Echtzeit - Priorität für alle Knoten in der ermöglichen hwbinder Domäne. Um das zu erreichen , dass gleiche Wirkung, Kirsch holt diese Änderung in User - Space.

SHAs für gängige Kernel

Um die erforderlichen Änderungen am Binder-Treiber zu erhalten, synchronisieren Sie mit dem entsprechenden SHA:

  • Allgemein-3,18
    cc8b90c121de ANDROID: Binder: Prio-Berechtigungen beim Wiederherstellen nicht überprüfen.
  • Allgemein-4.4
    76b376eac7a2 ANDROID: Binder: Prio-Berechtigungen beim Wiederherstellen nicht überprüfen.
  • Allgemein-4.9
    ecd972d4f9b5 ANDROID: Binder: Prio-Berechtigungen beim Wiederherstellen nicht überprüfen.

Verwendung von Binder IPC

In der Vergangenheit haben Anbieterprozesse zur Kommunikation die Binder-Interprozess-Kommunikation (IPC) verwendet. In Android 8, die /dev/binder Geräteknoten wird auf Rahmen Prozesse exklusiv, dh Anbieter Prozesse keinen Zugriff mehr darauf haben. Lieferantenprozesse zugreifen können /dev/hwbinder , sondern müssen ihre AIDL Schnittstellen zu verwenden HIDL konvertieren. Für Anbieter, die weiterhin AIDL-Schnittstellen zwischen Anbieterprozessen verwenden möchten, unterstützt Android Binder IPC wie unten beschrieben.

vndbinder

Android 8 unterstützt eine neue Bindemittel Domäne für die Verwendung durch Vendor Services zugegriffen mit /dev/vndbinder statt /dev/binder . Mit dem Zusatz von /dev/vndbinder , Android jetzt hat den folgenden drei IPC - Domains:

IPC-Domäne Beschreibung
/dev/binder IPC zwischen Framework-/App-Prozessen mit AIDL-Schnittstellen
/dev/hwbinder IPC zwischen Framework/Vendor-Prozessen mit HIDL-Schnittstellen
IPC zwischen Lieferantenprozessen mit HIDL-Schnittstellen
/dev/vndbinder IPC zwischen Lieferanten-/Lieferantenprozessen mit AIDL-Schnittstellen

Für /dev/vndbinder erscheinen, sicherzustellen , dass die Kernel - Konfigurationselement CONFIG_ANDROID_BINDER_DEVICES wird auf "binder,hwbinder,vndbinder" (dies ist die Standardeinstellung in Androids gemeinsamen Kernel Bäume ist).

Normalerweise Lieferantenprozesse öffnen Sie nicht das Bindemittel Treiber direkt und stattdessen verbinden gegen die libbinder Userspace - Bibliothek, die das Bindemittel Treiber öffnet. Hinzufügen eines Verfahrens zum ::android::ProcessState() wählt die Bindemitteltreiber für libbinder . Lieferantenprozesse sollten diese Methode aufrufen , bevor sie in Aufruf ProcessState, IPCThreadState , oder vor einem Bindemittel Anrufe im Allgemeinen machen. Gebrauch, setzen Sie den folgenden Aufruf nach dem main() von einem Lieferanten Prozess (Client und Server):

ProcessState::initWithDriver("/dev/vndbinder");

vndservicemanager

Bisher wurden Bindemittel Dienstleistungen mit registrierten servicemanager , wo sie von anderen Prozessen abgerufen werden konnte. In Android 8, servicemanager wird nun ausschließlich durch Rahmen und App - Prozesse und Lieferantenprozesse können nicht mehr darauf zugreifen, verwendet.

Allerdings kann Dienste - Anbieter nun nutzen vndservicemanager , eine neue Instanz des servicemanager dass Anwendungen /dev/vndbinder statt /dev/binder und die aus den gleichen Quellen wie Framework aufgebaut servicemanager . Lieferantenprozesse brauchen keine Änderungen zu reden machen vndservicemanager ; wenn ein Anbieter Prozess öffnet / dev/vndbinder , Service - Lookups gehen automatisch auf vndservicemanager .

Die vndservicemanager Binary finden Sie im Android-Standardgerät Makefiles enthalten.

SELinux-Richtlinie

Lieferantenprozesse, die Binder-Funktionalität verwenden möchten, um miteinander zu kommunizieren, benötigen Folgendes:

  1. Der Zugriff auf /dev/vndbinder .
  2. Binder {transfer, call} Haken in vndservicemanager .
  3. binder_call(A, B) für jeden Verkäufer - Domäne A, die in der Domäne B - Anbieter über den Anbieter Bindemittel Schnittstelle aufrufen möchte.
  4. Die Erlaubnis zum {add, find} Dienstleistungen in vndservicemanager .

Zur Erfüllung Anforderung 1 und 2, verwenden Sie die vndbinder_use() Makro:

vndbinder_use(some_vendor_process_domain);

Zur Erfüllung Anforderung 3, das binder_call(A, B) für die Lieferantenprozesse A und B , dass Notwendigkeit, über Bindemittel zu sprechen an ihrem Platz bleiben kann und nicht Umbenennung müssen.

Um Anforderung 4 zu erfüllen, müssen Sie Änderungen an der Handhabung von Dienstnamen, Dienstbezeichnungen und Regeln vornehmen.

Einzelheiten zu SELinux finden Sie Security-Enhanced Linux in Android . Einzelheiten zu SELinux in Android 8.0, siehe SELinux für Android 8.0 .

Dienstnamen

Zuvor Anbieter Prozesse registrierten Servicenamen in einer service_contexts Datei und entsprechende Regeln hinzugefügt für diese Datei zugreifen. Beispiel service_contexts Datei von 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 lädt die vndservice_contexts Datei statt. Vendor Services zu migrieren vndservicemanager (und die bereits in der alten service_contexts Datei) auf die neue hinzugefügt werden vndservice_contexts Datei.

Serviceetiketten

Zuvor Service Labels wie u:object_r:atfwd_service:s0 wurden in einer definierten service.te Datei. Beispiel:

type atfwd_service,      service_manager_type;

In Android 8, müssen Sie den Typ ändern vndservice_manager_type und die Regel zum bewegen vndservice.te Datei. Beispiel:

type atfwd_service,      vndservice_manager_type;

Servicemanager-Regeln

Zuvor Regeln Domains Zugang gewährt zu Dienstleistungen von hinzufügen oder finden servicemanager . Beispiel:

allow atfwd atfwd_service:service_manager find;
allow some_vendor_app atfwd_service:service_manager add;

In Android 8 können solche Regeln bestehen bleiben und dieselbe Klasse verwenden. Beispiel:

allow atfwd atfwd_service:service_manager find;
allow some_vendor_app atfwd_service:service_manager add;