Binder-IPC verwenden

Auf dieser Seite werden die Änderungen am Binder-Treiber in Android 8 beschrieben, Details zur Verwendung von Binder IPC und listet die erforderlichen SELinux-Richtlinien auf.

Änderungen am Binder-Treiber

Ab Android 8 kommunizieren das Android-Framework und die HALs jetzt mit miteinander unter Verwendung von Binder. Da durch diese Kommunikation die Bindung enthält Android 8 mehrere Verbesserungen, die das Binder-IPC aufrecht erhalten sollen. schnell. SoC-Anbieter und OEMs sollten direkt aus den relevanten Android-4.4, Android-4.9 und höher der kernel/common-Projekt zugeordnet.

Mehrere Binder-Domains (Kontexte)

Common 4.4 und höher, einschließlich Upstream

Um den Binder-Traffic zwischen Framework (geräteunabhängig) und Anbietercode (gerätespezifischer) wurde mit Android 8 das Konzept eines Bindeunternehmens eingeführt. Kontext. Jeder Binder-Kontext hat seinen eigenen Geräteknoten und seinen eigenen Kontext (Dienst-)Manager. Du kannst nur über das Gerät auf den Kontextmanager zugreifen Knoten, zu dem er gehört, und wenn ein Binder-Knoten über einen bestimmten Kontext ist, ist sie aus diesem Kontext nur über einen anderen Prozess zugänglich. um die Domains vollständig voneinander zu isolieren. Einzelheiten zur Verwendung finden Sie unter vndbinder und vndservicemanager.

Streudiagramm

Common 4.4 und höher, einschließlich Upstream

In früheren Android-Versionen wurden alle Daten in einem Binder-Aufruf kopiert. dreimal:

  • Sobald es in eine Parcel im Anrufprozess
  • Kopieren Sie im Kernel-Treiber das Parcel in das Ziel, Prozess
  • Einmal, um Parcel im Zielprozess neu zu konfigurieren

Android 8 nutzt Streudiagramm , um die Anzahl der Kopien von 3 auf 1 zu reduzieren. Anstelle von Wenn Daten zuerst in einem Parcel serialisiert werden, bleiben die Daten in ihrem ursprünglichen Zustand. und der Treiber kopiert sie sofort in die Ziel- . Sobald sich die Daten im Zielprozess befinden, ist das gleiche Layout und die Daten können ohne weitere Kopie gelesen werden.

Detailliertes Sperren

Common 4.4 und höher, einschließlich Upstream

In früheren Android-Releases verwendete der Binder-Treiber eine globale Sperre, um gleichzeitigen Zugriff auf kritische Datenstrukturen. Obwohl es nur minimale Konflikt um die Sperre, bestand das Hauptproblem darin, das Schloss überbrachte und dann wieder aufgehoben wurde, Threads mit höherer Priorität, die dieselbe Sperre benötigen. Dies führte zu einer Verzögerung im Plattform.

Die ersten Versuche zur Lösung dieses Problems bestand darin, das vorzeitige Beenden zu deaktivieren, während mit der globalen Sperre. Dabei handelte es sich jedoch eher um einen Hack als um eine echte Lösung, und schließlich von vorgelagerten Kanälen abgelehnt und verworfen. Nachfolgende Versuche konzentrierter sich darauf, die Sperre differenzierter zu gestalten. Diese Version wurde bereits auf Pixel-Geräten seit Januar 2017. Während die meisten dieser Änderungen veröffentlicht wurden, wurden in den nachfolgenden Versionen wesentliche Verbesserungen vorgenommen.

Nachdem wir kleine Probleme bei der detaillierten Sperrimplementierung identifiziert haben, eine verbesserte Lösung mit einer anderen Sperrarchitektur entwickelt und Änderungen in allen gängigen Kernel-Zweigen. Wir testen dies weiter Implementierung auf einer großen Anzahl verschiedener Geräte, da wir uns keinerlei immer noch behobene Probleme behoben haben, ist dies die empfohlene Implementierung für den Versand von Geräten mit Android 8.

Prioritätsübernahme in Echtzeit

Common-4.4 und Common-4.9 (Upstream demnächst verfügbar)

Der Binder-Treiber hat schon immer eine positive Prioritätsübernahme unterstützt. Als zunehmende Anzahl von Prozessen in Android mit Echtzeitpriorität, in einigen jetzt ist es sinnvoll, dass bei einem Echtzeit-Thread ein Binder-Aufruf erfolgt, Thread in dem Prozess, der diesen Aufruf verarbeitet, auch mit Echtzeitpriorität ausgeführt wird. Bis diese Anwendungsfälle unterstützen, implementiert Android 8 jetzt die Prioritätsübernahme in Echtzeit. im Binder-Treiber ein.

Zusätzlich zur Prioritätsübernahme auf Transaktionsebene wird die Knotenpriorität Übernahme ermöglicht einem Knoten (Binder-Dienstobjekt) die Angabe eines Minimums Priorität, mit der Aufrufe an diesen Knoten ausgeführt werden sollen. Vorherige Versionen von Android unterstützt bereits die Übernahme der Knotenpriorität mit schönen Werten, aber Android 8 unterstützt die Knotenübernahme von Richtlinien für die Echtzeitplanung.

Änderungen im Userspace

Android 8 umfasst alle Änderungen am Nutzerbereich, die für die aktuelle binder-Treiber im gemeinsamen Kernel mit einer Ausnahme: -Implementierung zum Deaktivieren der Echtzeit-Prioritätsübernahme für /dev/binder hat einen ioctl angeben. Bei späteren Entwicklungen wurde die Prioritätssteuerung geändert. Übernahme in eine detailliertere Methode, die pro Bindermodus (und nicht pro Kontext). Daher ist „ioctl“ nicht im gemeinsamen Branch von Android enthalten, sondern ist stattdessen in unseren gemeinsamen Kerneln gesendet.

Durch diese Änderung wird die Prioritätsübernahme in Echtzeit durch Standardeinstellung für jeden Knoten. Das Android Performance-Team hat es gefunden eine Echtzeit-Prioritätsübernahme für alle Knoten im hwbinder-Domain. Um diesen Effekt zu erzielen, dieser Änderung im Userspace.

SHAs für gängige Kernel

Um die erforderlichen Änderungen am Binder-Treiber zu erhalten, führen Sie eine Synchronisierung mit dem entsprechenden SHA-Wert durch:

  • Common-3,18
    cc8b90c121de ANDROID: binder: prio-Berechtigungen bei Wiederherstellung nicht überprüfen.
  • Common-4,4
    76b376eac7a2 ANDROID: binder: prio-Berechtigungen bei Wiederherstellung nicht überprüfen.
  • Common-4,9
    ecd972d4f9b5 ANDROID: binder: „prio-Berechtigungen“ bei der Wiederherstellung nicht prüfen.

Mit Binder IPC arbeiten

In der Vergangenheit wurde bei den Prozessen von Zulieferunternehmen Binder-Interprozesskommunikation eingesetzt (IPC) verwendet. In Android 8 hat der Geräteknoten /dev/binder wird ausschließlich in Framework-Prozessen eingebunden, was bedeutet, dass Zulieferunternehmen keine darauf zugreifen können. Anbieterprozesse können auf /dev/hwbinder zugreifen, aber müssen ihre AIDL-Schnittstellen zur Verwendung von HIDL konvertieren. Für Anbieter, die mit der mit AIDL-Schnittstellen zwischen Anbieterprozessen unterstützt Android Binder IPC als beschrieben. Unter Android 10 ermöglicht die stabile AIDL alle Prozesse, um /dev/binder zu verwenden und gleichzeitig Stabilität zu gewährleisten sorgt dafür, dass HIDL und /dev/hwbinder gelöst werden. So verwendest du die stabile Version AIDL, siehe AIDL für HALs

vndbinder

Android 8 unterstützt eine neue Binder-Domain, auf die Anbieterdienste zugreifen können mit /dev/vndbinder statt /dev/binder. Mit der /dev/vndbinder hinzugefügt wurde, hat Android jetzt die folgenden drei IPC-Domains:

IPC-Domain Beschreibung
/dev/binder IPC zwischen Framework-/App-Prozessen mit AIDL-Schnittstellen
/dev/hwbinder IPC zwischen Framework-/Anbieterprozessen mit HIDL-Schnittstellen
IPC zwischen Anbieterprozessen mit HIDL-Schnittstellen
/dev/vndbinder IPC zwischen Anbieter-/Anbieterprozessen mit AIDL Interfaces

Prüfen Sie die Kernel-Konfiguration, damit /dev/vndbinder angezeigt wird Element CONFIG_ANDROID_BINDER_DEVICES ist festgelegt auf "binder,hwbinder,vndbinder" (Dies ist die Standardeinstellung im gewöhnliche Kernbäume).

Normalerweise öffnen die Prozesse des Zulieferunternehmens den Binder-Treiber nicht direkt, sondern für die Userspace-Bibliothek „libbinder“, die die binder-Treiber. Methode für ::android::ProcessState() hinzufügen wählt den Binder-Treiber für libbinder aus. Die Prozesse von Zulieferunternehmen sollten Rufen Sie diese Methode auf, bevor Sie ProcessState, aufrufen. IPCThreadState oder vor allgemeinen Binder-Aufrufen. Bis verwenden: Platzieren Sie den folgenden Aufruf nach dem main() eines Anbieterprozesses. (Client und Server):

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

vndservicemanager

Zuvor waren Binder-Dienste bei servicemanager registriert. wo sie von anderen Prozessen abgerufen werden können. In Android 8 servicemanager wird jetzt ausschließlich vom Framework und der App verwendet nicht mehr auf sie zugreifen.

Anbieterdienste können jetzt jedoch vndservicemanager verwenden, eine neue Instanz von servicemanager, die /dev/vndbinder verwendet anstelle von /dev/binder, und die aus denselben Quellen wie Framework servicemanager. Die Prozesse von Zulieferunternehmen müssen für die Kommunikation mit vndservicemanager ändern; wenn ein Prozess des Zulieferunternehmens /dev/vndbinder, Dienstsuchen werden automatisch an vndservicemanager

Das Binärprogramm vndservicemanager ist in der Standardeinstellung von Android enthalten Makefiles auf dem Gerät.

SELinux-Richtlinie

Anbieterprozesse, die über die Binder-Funktion kommunizieren möchten miteinander kommunizieren müssen:

  1. Zugriff auf /dev/vndbinder.
  2. Ordner "{transfer, call}" wird angehakt in vndservicemanager.
  3. binder_call(A, B) für jede Anbieterdomain A, die einen Aufruf an über die Anbieter-Binder-Schnittstelle in die Domain B des Anbieters ein.
  4. Berechtigung: {add, find} Dienste in vndservicemanager.

Verwenden Sie die vndbinder_use(), um die Anforderungen 1 und 2 zu erfüllen. Makro:

vndbinder_use(some_vendor_process_domain);

Um Anforderung 3 zu erfüllen, muss die binder_call(A, B) für den Anbieter festgelegt werden. die Prozesse A und B, die über Binder kommunizieren müssen, an Ort und Stelle bleiben können müssen umbenannt werden.

Um Anforderung 4 zu erfüllen, müssen Sie Änderungen an Dienstnamen, Dienst-Labels und -Regeln verarbeitet werden.

Details zu SELinux finden Sie unter Verstärkte Sicherheit Linux für Android Details zu SELinux unter Android 8.0 finden Sie unter SELinux für Android 8.0.

Dienstnamen

Zuvor verarbeitete der Anbieter registrierte Dienstnamen in einem service_contexts Datei und entsprechende Regeln für den Zugriff hinzugefügt für diese Datei. Beispieldatei service_contexts aus 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 lädt vndservicemanager vndservice_contexts-Datei. Anbieterdienste werden migriert auf vndservicemanager (und die sich bereits in der alten service_contexts-Datei) sollte dem neuen vndservice_contexts-Datei.

Dienstlabels

Bisher wurden Dienstlabels wie u:object_r:atfwd_service:s0 in einer service.te-Datei definiert wurden. Beispiel:

type atfwd_service,      service_manager_type;

In Android 8 müssen Sie den Typ in vndservice_manager_type und verschieben Sie die Regel in den vndservice.te-Datei. Beispiel:

type atfwd_service,      vndservice_manager_type;

Service Manager-Regeln

Bisher haben Regeln Domains Zugriff gewährt, um Dienste hinzuzufügen oder zu suchen 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;