Utilisation du classeur IPC

Cette page décrit les modifications apportées au pilote du classeur dans Android 8, fournit des détails sur l'utilisation de l'IPC du classeur et répertorie la politique SELinux requise.

Modifications apportées au pilote de classeur

À partir d'Android 8, le framework Android et les HAL communiquent désormais entre eux à l'aide d'un classeur. Comme cette communication augmente considérablement le trafic du classeur, Android 8 inclut plusieurs améliorations conçues pour maintenir l'IPC du classeur rapide. SoC et fournisseurs OEM devraient fusionner directement des branches pertinentes de Android 4.4, Android 4.9 et supérieur du noyau / commun projet.

Domaines de liant multiples (contextes)

Common-4.4 et supérieur, y compris en amont

Pour diviser proprement le trafic de liant entre le cadre (dispositif indépendant) et fournisseur code (dispositif spécifique), Android 8 a introduit le concept d'un contexte de liant. Chaque contexte de classeur a son propre nœud de périphérique et son propre gestionnaire de contexte (service). Vous pouvez accéder au gestionnaire de contexte uniquement via le nœud de périphérique auquel il appartient et, lors du passage d'un nœud de classeur à travers un certain contexte, il n'est accessible à partir de ce même contexte que par un autre processus, isolant ainsi complètement les domaines les uns des autres. Pour plus de détails sur l' utilisation, voir vndbinder et vndservicemanager .

Scatter-rassembler

Common-4.4 et supérieur, y compris en amont

Dans les versions précédentes d'Android, chaque donnée d'un appel de classeur était copiée trois fois :

  • Une fois de sérialisation dans une Parcel dans le processus d' appel
  • Une fois dans le pilote du noyau pour copier le Parcel au processus cible
  • Une fois à désérialiser le Parcel dans le processus cible

Android 8 utilise la dispersion-optimisation se Parcel réunissent pour réduire le nombre de copies de 3 à 1. Au lieu des données sérialisation dans une Parcel d' abord, les données restent dans sa structure d' origine et la mise en page et la mémoire du conducteur des copies immédiatement au processus cible. Une fois que les données sont dans le processus cible, la structure et la disposition de la mémoire sont les mêmes et les données peuvent être lues sans nécessiter une autre copie.

Verrouillage à grain fin

Common-4.4 et supérieur, y compris en amont

Dans les versions précédentes d'Android, le pilote de classeur utilisait un verrou global pour se protéger contre l'accès simultané aux structures de données critiques. Bien qu'il y ait eu une contention minimale pour le verrou, le principal problème était que si un thread de faible priorité obtenait le verrou puis était préempté, cela pouvait sérieusement retarder les threads de priorité plus élevée devant obtenir le même verrou. Cela a provoqué des secousses sur la plate-forme.

Les premières tentatives pour résoudre ce problème impliquaient de désactiver la préemption tout en maintenant le verrou global. Cependant, il s'agissait plus d'un hack que d'une véritable solution et a finalement été rejeté par l'amont et rejeté. Les tentatives ultérieures se sont concentrées sur l'amélioration du verrouillage, dont une version fonctionne sur les appareils Pixel depuis janvier 2017. Bien que la majorité de ces modifications aient été rendues publiques, des améliorations substantielles ont été apportées aux versions suivantes.

Après avoir identifié de petits problèmes dans l'implémentation de verrouillage à grain fin, nous avons conçu une solution améliorée avec une architecture de verrouillage différente et soumis les modifications dans toutes les branches communes du noyau. Nous continuons à tester cette implémentation sur un grand nombre d'appareils différents ; comme nous ne connaissons aucun problème en suspens, il s'agit de l'implémentation recommandée pour les appareils livrés avec Android 8.

Héritage prioritaire en temps réel

Common-4.4 et common-4.9 (en amont bientôt disponible)

Le pilote de classeur a toujours pris en charge l'héritage de priorité agréable. Comme un nombre croissant de processus dans Android s'exécutent en priorité en temps réel, dans certains cas, il est désormais logique que si un thread en temps réel effectue un appel de classeur, le thread du processus qui gère cet appel s'exécute également en priorité en temps réel. . Pour prendre en charge ces cas d'utilisation, Android 8 implémente désormais l'héritage de priorité en temps réel dans le pilote de classeur.

En plus de l' héritage de priorité au niveau des transactions, l' héritage de priorité de noeud permet à un nœud (liant objet de service) pour spécifier une priorité minimale à laquelle des appels dans ce nœud doivent être exécutées. Les versions précédentes d'Android prenaient déjà en charge l'héritage de priorité de nœud avec des valeurs intéressantes, mais Android 8 ajoute la prise en charge de l'héritage de nœud des politiques de planification en temps réel.

Modifications de l'espace utilisateur

Android 8 inclut tous les changements nécessaires pour l' espace utilisateur avec le pilote de liant en cours dans le noyau commun à une exception près: La mise en œuvre originale de désactiver l' héritage de priorité temps réel pour /dev/binder utilisé un ioctl . Le développement ultérieur a basculé le contrôle de l'héritage des priorités sur une méthode plus fine qui est par mode de classeur (et non par contexte). Ainsi, l'ioctl est pas dans la branche commune Android et est plutôt soumis dans nos noyaux communs .

L'effet de ce changement est que l' héritage de priorité en temps réel est désactivé par défaut pour chaque nœud. L'équipe de performance Android a trouvé bénéfique pour l'héritage des priorités en temps réel pour tous les nœuds du hwbinder domaine. Pour atteindre ce même effet, cerise choisir ce changement dans l' espace utilisateur.

SHA pour les noyaux communs

Pour obtenir les modifications nécessaires au pilote du classeur, synchronisez-vous avec le SHA approprié :

  • Commun-3.18
    cc8b90c121de ANDROID : classeur : ne pas vérifier les autorisations prioritaires lors de la restauration.
  • Commun-4.4
    76b376eac7a2 ANDROID : classeur : ne pas vérifier les autorisations prioritaires lors de la restauration.
  • Commun-4,9
    ecd972d4f9b5 ANDROID : classeur : ne pas vérifier les autorisations prioritaires lors de la restauration.

Utilisation du liant IPC

Historiquement, les processus des fournisseurs ont utilisé la communication interprocessus de classeur (IPC) pour communiquer. Dans Android 8, le /dev/binder noeud de périphérique devient exclusif aux processus cadres, ce qui signifie des processus fournisseurs n'ont plus accès. Processus de fournisseurs peuvent accéder à /dev/hwbinder , mais ils doivent convertir leurs interfaces AIDL à l' utilisation HIDL. Pour les fournisseurs qui souhaitent continuer à utiliser les interfaces AIDL entre les processus des fournisseurs, Android prend en charge le classeur IPC comme décrit ci-dessous.

vndbinder

Applications 8 prend en charge un nouveau domaine de liaison à l' usage des services du fournisseur, accessible via /dev/vndbinder à la place de /dev/binder . Avec l'ajout de /dev/vndbinder , Android a maintenant les trois domaines CIB suivants:

Domaine IPC La description
/dev/binder IPC entre les processus framework/app avec les interfaces AIDL
/dev/hwbinder IPC entre processus framework/fournisseur avec interfaces HIDL
IPC entre processus fournisseurs avec interfaces HIDL
/dev/vndbinder IPC entre les processus fournisseur/fournisseur avec les interfaces AIDL

Pour /dev/vndbinder pour apparaître, assurer que l'article configuration du noyau CONFIG_ANDROID_BINDER_DEVICES est réglé sur "binder,hwbinder,vndbinder" (valeur par défaut dans les arbres du noyau commun d'Android).

Normalement, les processus de fournisseur ne pas ouvrir le pilote de liant directement et lien à la place contre la libbinder bibliothèque de l' espace utilisateur, qui ouvre le conducteur de liant. Ajout d' un procédé pour ::android::ProcessState() sélectionne le pilote de liant pour libbinder . Processus de fournisseurs doivent appeler cette méthode avant d' appeler en ProcessState, IPCThreadState ou avant de faire des appels de liant en général. Pour l' utiliser, placez l'appel suivant après la main() d'un processus de fournisseur (client et serveur):

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

vndservicemanager

Auparavant, les services liant ont été enregistrés auprès servicemanager , où ils pourraient être récupérés par d' autres processus. Dans Android 8, servicemanager est maintenant utilisé exclusivement par des processus cadres et applications et processus fournisseur ne peut plus y accéder.

Toutefois, les services de fournisseurs peuvent désormais utiliser vndservicemanager , une nouvelle instance de servicemanager que les utilisations /dev/vndbinder au lieu de /dev/binder et qui est construit à partir des mêmes sources que le cadre servicemanager . Processus de fournisseurs ne ont pas besoin d'apporter des modifications à parler à vndservicemanager ; lorsqu'un processus fournisseur ouvre / dev/vndbinder , de service vont lookups automatiquement vndservicemanager .

Le vndservicemanager binaire est inclus dans le makefile de l' appareil par défaut d'Android.

Politique SELinux

Les processus de fournisseur qui souhaitent utiliser la fonctionnalité de classeur pour communiquer entre eux ont besoin des éléments suivants :

  1. L' accès à /dev/vndbinder .
  2. Binder {transfer, call} crochets dans vndservicemanager .
  3. binder_call(A, B) pour chaque domaine fournisseur A qui veut appeler dans le domaine du fournisseur B sur l'interface de liaison du fournisseur.
  4. L' autorisation de {add, find} services vndservicemanager .

Pour répondre aux exigences 1 et 2, utilisez la vndbinder_use() macro:

vndbinder_use(some_vendor_process_domain);

Pour répondre à l' exigence 3, la binder_call(A, B) pour le fournisseur traite A et B qui ont besoin de parler sur liant peut rester en place et n'a pas besoin de changement de nom.

Pour répondre à l'exigence 4, vous devez apporter des modifications à la manière dont les noms de service, les étiquettes de service et les règles sont gérés.

Pour plus de détails sur SELinux, consultez Security-Enhanced Linux dans Android . Pour plus de détails sur SELinux dans Android 8.0, voir SELinux pour Android 8.0 .

Noms des services

Auparavant, les processus des fournisseurs de services noms enregistrés dans un service_contexts fichier et ajouté des règles correspondantes pour accéder à ce fichier. Exemple service_contexts fichier de 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

Dans Android 8, vndservicemanager charge les vndservice_contexts fichier au lieu. Services de fournisseurs émigrent vers vndservicemanager (et qui sont déjà dans le vieux service_contexts fichier) devraient être ajoutés au nouveau vndservice_contexts fichier.

Étiquettes de service

, Étiquettes de service précédemment tel que u:object_r:atfwd_service:s0 ont été définis dans un service.te fichier. Exemple:

type atfwd_service,      service_manager_type;

Dans Android 8, vous devez changer le type de vndservice_manager_type et déplacer la règle du vndservice.te fichier. Exemple:

type atfwd_service,      vndservice_manager_type;

Règles du gestionnaire de services

Accès Auparavant, les règles domaines accordé à ajouter ou trouver des services de servicemanager . Exemple:

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

Dans Android 8, ces règles peuvent rester en place et utiliser la même classe. Exemple:

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