Utiliser l'IPC de liaison

Cette page décrit les modifications apportées au pilote de liaison dans Android 8, fournit des détails sur l'utilisation de l'IPC de liaison et la liste des règles SELinux requises.

Modifications apportées au pilote de liaison

À partir d'Android 8, le framework Android et les HAL communiquent à l'aide de la liaison. Alors que cette communication augmente considérablement le lien trafic, Android 8 inclut plusieurs améliorations conçues pour conserver l'IPC de liaison rapidement. Les fournisseurs de SoC et les OEM doivent fusionner directement avec les branches concernées de android-4.4, android-4.9 et versions ultérieures kernel/common.

Plusieurs domaines de liaison (contextes)

Common 4.4 et versions ultérieures, y compris en amont

Répartir correctement le trafic de liaison entre le framework (indépendant de l'appareil) et code (spécifique à l'appareil), Android 8 a introduit le concept de liaison le contexte. Chaque contexte de liaison possède son propre nœud d'appareil et son propre contexte (service). Vous ne pouvez accéder au gestionnaire de contexte que via l'appareil auquel il appartient et, lors de la transmission d'un nœud de liaison via un certain contexte, elles ne sont accessibles à partir de ce même contexte que par un autre processus. isolant complètement les domaines les uns des autres. Pour en savoir plus sur l'utilisation, consultez vndbinder et vndservicemanager.

Collectionneur de nuage de points

Common 4.4 et versions ultérieures, y compris en amont

Dans les versions précédentes d'Android, chaque élément de données d'un appel de liaison était copié trois fois:

  • Une fois pour la sérialiser Parcel pendant le processus d'appel.
  • Une fois dans le pilote du noyau pour copier Parcel sur la cible processus
  • Une fois pour désérialiser le Parcel dans le processus cible

Android 8 utilise recueil-de-diffusion optimisation pour faire passer le nombre de copies de 3 à 1. Au lieu de si vous sérialisez d'abord les données dans un Parcel, les données restent dans leur état d'origine et la structure de la mémoire. Le pilote les copie immédiatement processus. Une fois les données dans le processus cible, la structure et la mémoire la mise en page est la même et les données peuvent être lues sans nécessiter de copie supplémentaire.

Verrouillage ultraprécis

Common 4.4 et versions ultérieures, y compris en amont

Dans les versions précédentes d'Android, le pilote de liaison utilisait un verrouillage global pour protéger contre les accès simultanés à des structures de données critiques. Bien qu'il y ait un minimum le principal problème était que, si un thread à faible priorité obtenait la serrure avant d'être préemptée, elle pouvait sérieusement retarder threads prioritaires qui doivent obtenir le même verrouillage. Cela a causé des à-coups dans Google Cloud.

Les premières tentatives de résolution de ce problème impliquaient de désactiver la préemption pendant en maintenant le verrou mondial. Cependant, il s'agissait plus d'un piratage qu'une véritable solution, et a finalement été rejetée en amont, puis rejetée. Tentatives suivantes mais nous nous sommes attachés à rendre le verrouillage plus précis, sur les appareils Pixel depuis janvier 2017. Même si la majorité de ces changements rendues publiques, des améliorations importantes ont été apportées dans les versions ultérieures.

Après avoir identifié les petits problèmes dans l'implémentation ultraprécise du verrouillage, conçu une solution améliorée avec une architecture de verrouillage différente, les modifications dans toutes les branches de noyau courantes. Nous poursuivons les tests sur un grand nombre d'appareils différents ; car nous n'avons pas connaissance problèmes non résolus, il s'agit de la mise en œuvre recommandée pour les appareils livrés avec Android 8.

Héritage des priorités en temps réel

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

Le pilote de liaison a toujours pris en charge l'héritage de priorité agréable. En tant que de plus en plus de processus dans Android s'exécutent de façon prioritaire en temps réel, dans certains il est désormais logique que si un thread en temps réel effectue un appel de liaison, dans le processus qui gère cet appel s'exécute également avec une priorité en temps réel. À prennent 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 liaison.

Outre l'héritage de priorité au niveau des transactions, la priorité des nœuds héritage permet à un nœud (objet de service de liaison) de spécifier une valeur minimale à laquelle les appels vers ce nœud doivent être exécutés. Versions précédentes de Android prenait déjà en charge l'héritage de la priorité des nœuds avec des valeurs intéressantes, mais Android 8 prend en charge l'héritage des nœuds des règles de planification en temps réel.

Modifications de l'espace utilisateur

Android 8 inclut toutes les modifications de l'espace utilisateur requises pour fonctionner avec la version actuelle le pilote de liaison dans le noyau commun, à une exception près: le pilote d'origine pour désactiver l'héritage de priorité en temps réel /dev/binder a utilisé un ioctl. Le développement suivant a modifié le contrôle de priorité l'héritage à une méthode plus précise par mode de liaison (et non par le contexte actuel). Ainsi, ioctl ne figure pas dans la branche commune d'Android, mais est plutôt soumis dans nos noyaux communs.

L'effet de cette modification est que l'héritage de priorité en temps réel est désactivé par pour chaque nœud. L'équipe Android chargée des performances l'a trouvé utile d'activer l'héritage de priorité en temps réel pour tous les nœuds dans le hwbinder. Pour obtenir le même effet, choisissez ce changement dans l'espace utilisateur.

SHA pour les noyaux courants

Pour obtenir les modifications nécessaires apportées au pilote de liaison, synchronisez avec le SHA approprié:

  • Commun-3,18
    cc8b90c121de ANDROID: binder: ne cochez pas les autorisations prioritaires lors de la restauration.
  • Commun-4,4
    76b376eac7a2 ANDROID: binder: ne cochez pas les autorisations prioritaires lors de la restauration.
  • Commun-4,9
    ecd972d4f9b5 ANDROID: binder: ne cochez pas les autorisations prioritaires lors de la restauration.

Utiliser l'IPC de liaison

Auparavant, les processus des fournisseurs utilisaient la communication inter-processus de liaison (IPC) de communiquer. Sous Android 8, le nœud d'appareil /dev/binder devient exclusif aux processus du framework, ce qui signifie que les processus des fournisseurs ne y avoir accès. Les processus du fournisseur peuvent accéder à /dev/hwbinder, mais doivent convertir leurs interfaces AIDL pour utiliser HIDL. Pour les fournisseurs qui souhaitent continuer à l'aide d'interfaces AIDL entre les processus des fournisseurs, Android prend en charge l'IPC de liaison en tant que décrites ci-dessous. Dans Android 10, la version stable d'AIDL autorise tous pour utiliser /dev/binder tout en résolvant la stabilité garantit que les problèmes HIDL et /dev/hwbinder sont résolus. Pour savoir comment utiliser la version stable AIDL, voir AIDL pour les HAL

Vndbinder

Android 8 prend en charge un nouveau domaine de liaison destiné aux services des fournisseurs, accessible avec /dev/vndbinder au lieu de /dev/binder. Avec l'attribut ajout de /dev/vndbinder, Android dispose désormais des trois Domaines d'IPC:

Domaine IPC Description
/dev/binder IPC entre les processus du framework/de l'application avec des interfaces AIDL
/dev/hwbinder IPC entre les processus du framework/fournisseur avec des interfaces HIDL
IPC entre les processus des fournisseurs avec des interfaces HIDL
/dev/vndbinder IPC entre les processus fournisseur/fournisseur avec des interfaces AIDL

Pour que /dev/vndbinder s'affiche, assurez-vous que la configuration du noyau l'élément CONFIG_ANDROID_BINDER_DEVICES est défini sur "binder,hwbinder,vndbinder" (il s'agit du paramètre par défaut les arbres à noyau courants).

Normalement, les processus des fournisseurs n'ouvrent pas directement le pilote de liaison et au lieu vers la bibliothèque d'espace utilisateur libbinder, qui ouvre le pilote de liaison. Ajouter une méthode pour ::android::ProcessState() sélectionne le pilote de liaison pour libbinder. Les processus fournisseurs doivent appeler cette méthode avant d'appeler ProcessState,. IPCThreadState, ou avant d'effectuer des appels de liaison en général. À utilisez, passez l'appel suivant après l'main() d'un processus fournisseur (client et serveur):

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

vndservicemanager

Auparavant, les services de liaison étaient enregistrés avec servicemanager, où elles pourraient être récupérées par d'autres processus. Sous Android 8, servicemanager est désormais utilisé exclusivement par le framework et l'application processus et ceux des fournisseurs ne peuvent plus y accéder.

Toutefois, les services des fournisseurs peuvent désormais utiliser vndservicemanager, une nouvelle Une instance de servicemanager qui utilise /dev/vndbinder au lieu de /dev/binder et qui est créé à partir des mêmes sources que servicemanager. Les processus des fournisseurs n'ont pas besoin de faire modifications pour communiquer avec vndservicemanager ; lorsqu'un processus fournisseur s'ouvre /dev/vndbinder, les recherches de services renvoient automatiquement vers vndservicemanager

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

Règles SELinux

Les processus du fournisseur qui souhaitent utiliser la fonctionnalité de liaison pour communiquer avec ont besoin des éléments suivants:

  1. Accès à /dev/vndbinder.
  2. La liaison {transfer, call} s'accroche à vndservicemanager
  3. binder_call(A, B) pour tout domaine de fournisseur A souhaitant appeler dans le domaine du fournisseur B via l'interface de liaison du fournisseur.
  4. Autorisation pour {add, find} services dans vndservicemanager

Pour répondre aux exigences 1 et 2, utilisez l'vndbinder_use(). :

vndbinder_use(some_vendor_process_domain);

Pour répondre à l'exigence 3, le binder_call(A, B) du fournisseur les processus A et B qui ont besoin de parler par-dessus le binder peuvent rester en place et n'a pas à renommer.

Pour répondre à l'exigence 4, vous devez modifier la façon dont les noms des services, les étiquettes de service et les règles.

Pour plus d'informations sur SELinux, consultez le document Security-Enhanced Linux sur Android Pour plus d'informations sur SELinux dans Android 8.0, consultez SELinux pour Android 8.0.

Noms des services

Auparavant, le fournisseur traite les noms de services enregistrés service_contexts et ajouté les règles d'accès correspondantes ce fichier. Exemple de fichier service_contexts 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

Sous Android 8, vndservicemanager charge vndservice_contexts. Services des fournisseurs migrant vers vndservicemanager (et qui figurent déjà dans l'ancienne version service_contexts) doit être ajouté au nouveau vndservice_contexts.

Étiquettes de service

Auparavant, les étiquettes de service telles que u:object_r:atfwd_service:s0 ont été définies dans un fichier service.te. Exemple :

type atfwd_service,      service_manager_type;

Sous Android 8, vous devez remplacer le type par vndservice_manager_type, puis déplacez la règle vers vndservice.te. Exemple :

type atfwd_service,      vndservice_manager_type;

règles Servicemanager

Auparavant, les règles accordaient aux domaines un accès permettant d'ajouter ou de rechercher des services 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;