Google is committed to advancing racial equity for Black communities. See how.
Cette page a été traduite par l'API Cloud Translation.
Switch to English

HIDL

Le langage de définition d'interface HAL ou HIDL (prononcé "hide-l") est un langage de description d'interface (IDL) pour spécifier l'interface entre un HAL et ses utilisateurs. Il permet de spécifier des types et des appels de méthode, collectés dans des interfaces et des packages. Plus largement, HIDL est un système de communication entre des bases de code qui peuvent être compilées indépendamment.

HIDL est destiné à être utilisé pour la communication inter-processus (IPC). La communication entre les processus est appelée mise en liasse . Pour les bibliothèques qui doivent être liées à un processus, un mode passthrough est également disponible (non pris en charge en Java).

HIDL spécifie des structures de données et des signatures de méthode, organisées en interfaces (similaires à une classe) qui sont collectées dans des packages. La syntaxe de HIDL semblera familière aux programmeurs C ++ et Java, mais avec un ensemble différent de mots-clés. HIDL utilise également des annotations de style Java.

Conception HIDL

L'objectif de HIDL est que le cadre peut être remplacé sans avoir à reconstruire les HAL. Les HAL seront construits par des fournisseurs ou des fabricants de SOC et placés dans une partition /vendor sur le périphérique, permettant au framework, dans sa propre partition, d'être remplacé par un OTA sans recompiler les HAL.

La conception HIDL équilibre les préoccupations suivantes:

  • Interopérabilité . Créez des interfaces interopérables de manière fiable entre les processus qui peuvent être compilées avec diverses architectures, chaînes d'outils et configurations de construction. Les interfaces HIDL sont versionnées et ne peuvent pas être modifiées après leur publication.
  • Efficacité . HIDL essaie de minimiser le nombre d'opérations de copie. Les données définies par HIDL sont fournies au code C ++ dans des structures de données de mise en page standard C ++ qui peuvent être utilisées sans décompression. HIDL fournit également des interfaces de mémoire partagée et, comme les RPC sont intrinsèquement quelque peu lents, HIDL prend en charge deux façons de transférer des données sans utiliser d'appel RPC: la mémoire partagée et une file d'attente de messages rapides (FMQ).
  • Intuitif . HIDL évite les problèmes épineux de propriété de la mémoire en utilisant uniquement in paramètres pour RPC (voir Android Interface Definition Language (AIDL) ); les valeurs qui ne peuvent pas être renvoyées efficacement à partir des méthodes sont renvoyées via des fonctions de rappel. Ni la transmission de données dans HIDL pour le transfert ni la réception de données de HIDL ne modifie la propriété des données - la propriété reste toujours avec la fonction appelante. Les données doivent persister uniquement pendant la durée de la fonction appelée et peuvent être détruites immédiatement après le retour de la fonction appelée.

Utilisation du mode passthrough

Pour mettre à jour les appareils exécutant des versions antérieures d'Android vers Android O, vous pouvez encapsuler les HAL conventionnels (et hérités) dans une nouvelle interface HIDL qui sert le HAL en modes binderized et de même processus (passthrough). Ce wrapping est transparent pour le framework HAL et Android.

Le mode Passthrough est disponible uniquement pour les clients et implémentations C ++. Les appareils exécutant des versions antérieures d'Android n'ont pas de HAL écrits en Java, de sorte que les HAL Java sont intrinsèquement liés.

Lorsqu'un fichier .hal est compilé, hidl-gen produit un fichier d'en-tête de BsFoo.h supplémentaire BsFoo.h en plus des en-têtes utilisés pour la communication du classeur; cet en-tête définit les fonctions à dlopen . Comme les HAL relais s'exécutent dans le même processus dans lequel ils sont appelés, dans la plupart des cas, les méthodes relais sont appelées par appel direct de fonction (même thread). oneway méthodes fonctionnent dans leur propre fil car ils ne sont pas destinés à attendre la couche d' abstraction pour les traiter (ce qui signifie une HAL que les utilisations oneway méthodes en mode passthrough doivent être thread-safe).

Étant donné un IFoo.hal , BsFoo.h encapsule les méthodes générées par HIDL pour fournir des fonctionnalités supplémentaires (telles que l'exécution de transactions oneway dans un autre thread). Ce fichier est similaire à BpFoo.h , cependant au lieu de passer des appels IPC à l'aide de binder, les fonctions souhaitées sont directement appelées. Les futures implémentations de HAL peuvent fournir plusieurs implémentations, telles que FooFast HAL et FooAccurate HAL. Dans de tels cas, un fichier pour chaque implémentation supplémentaire serait créé (par exemple, PTFooFast.cpp et PTFooAccurate.cpp ).

Liaison des HAL passifs

Vous pouvez binderize les implémentations HAL qui prennent en charge le mode passthrough. Étant donné une interface HAL abcd@MN::IFoo , deux packages sont créés:

  • abcd@MN::IFoo-impl . Contient l'implémentation de HAL et expose la fonction IFoo* HIDL_FETCH_IFoo(const char* name) . Sur les appareils hérités, ce package est dlopen et l'implémentation est instanciée à l'aide de HIDL_FETCH_IFoo . Vous pouvez générer le code de base en utilisant hidl-gen et -Lc++-impl -Landroidbp-impl et -Landroidbp-impl .
  • abcd@MN::IFoo-service . Ouvre le HAL passthrough et s'enregistre en tant que service lié, permettant à la même implémentation HAL d'être utilisée à la fois comme passthrough et lié.

Étant donné le type IFoo , vous pouvez appeler sp<IFoo> IFoo::getService(string name, bool getStub) pour accéder à une instance de IFoo . Si getStub est true, getService tente d'ouvrir le HAL uniquement en mode passthrough. Si getStub est faux, getService tente de trouver un service en liasse; si cela échoue, il essaie alors de trouver le service de relais. Le paramètre getStub ne doit jamais être utilisé sauf dans defaultPassthroughServiceImplementation . (Les appareils lancés avec Android O sont des appareils entièrement liés, l'ouverture d'un service en mode relais est donc interdite.)

Grammaire HIDL

De par sa conception, le langage HIDL est similaire à C (mais n'utilise pas le préprocesseur C). Toute ponctuation non décrite ci-dessous (hormis l'utilisation évidente de = et | ) fait partie de la grammaire.

Remarque: pour plus de détails sur le style de code HIDL, consultez le Guide des styles de code.

  • /** */ indique un commentaire de documentation. Celles-ci ne peuvent être appliquées qu'aux déclarations de type, de méthode, de champ et de valeur d'énumération.
  • /* */ indique un commentaire multiligne.
  • // indique un commentaire à la fin de la ligne. Mis à part // , les retours à la ligne sont identiques à tous les autres espaces.
  • Dans l'exemple de grammaire ci-dessous, le texte de // à la fin de la ligne ne fait pas partie de la grammaire mais est plutôt un commentaire sur la grammaire.
  • [empty] signifie que le terme peut être vide.
  • ? après un littéral ou un terme signifie qu'il est facultatif.
  • ... indique une séquence contenant zéro ou plusieurs éléments avec une ponctuation de séparation comme indiqué. Il n'y a pas d'arguments variadiques dans HIDL.
  • Les virgules séparent les éléments de séquence.
  • Des points-virgules terminent chaque élément, y compris le dernier élément.
  • UPPERCASE est un non-terminal.
  • italics est une famille de jetons telle qu'un integer ou un identifier (règles d'analyse standard C).
  • constexpr est une expression constante de style C (telle que 1 + 1 et 1L << 3 ).
  • import_name est un nom de package ou d'interface, qualifié comme décrit dans Gestion des versions HIDL .
  • Les words minuscules sont des jetons littéraux.

Exemple:

ROOT =
    PACKAGE IMPORTS PREAMBLE { ITEM ITEM ... }  // not for types.hal
  | PACKAGE IMPORTS ITEM ITEM...  // only for types.hal; no method definitions

ITEM =
    ANNOTATIONS? oneway? identifier(FIELD, FIELD ...) GENERATES?;
  |  safe_union identifier { UFIELD; UFIELD; ...};
  |  struct identifier { SFIELD; SFIELD; ...};  // Note - no forward declarations
  |  union identifier { UFIELD; UFIELD; ...};
  |  enum identifier: TYPE { ENUM_ENTRY, ENUM_ENTRY ... }; // TYPE = enum or scalar
  |  typedef TYPE identifier;

VERSION = integer.integer;

PACKAGE = package android.hardware.identifier[.identifier[...]]@VERSION;

PREAMBLE = interface identifier EXTENDS

EXTENDS = <empty> | extends import_name  // must be interface, not package

GENERATES = generates (FIELD, FIELD ...)

// allows the Binder interface to be used as a type
// (similar to typedef'ing the final identifier)
IMPORTS =
   [empty]
  |  IMPORTS import import_name;

TYPE =
  uint8_t | int8_t | uint16_t | int16_t | uint32_t | int32_t | uint64_t | int64_t |
 float | double | bool | string
|  identifier  // must be defined as a typedef, struct, union, enum or import
               // including those defined later in the file
|  memory
|  pointer
|  vec<TYPE>
|  bitfield<TYPE>  // TYPE is user-defined enum
|  fmq_sync<TYPE>
|  fmq_unsync<TYPE>
|  TYPE[SIZE]

FIELD =
   TYPE identifier

UFIELD =
   TYPE identifier
  |  safe_union identifier { FIELD; FIELD; ...} identifier;
  |  struct identifier { FIELD; FIELD; ...} identifier;
  |  union identifier { FIELD; FIELD; ...} identifier;

SFIELD =
   TYPE identifier
  |  safe_union identifier { FIELD; FIELD; ...};
  |  struct identifier { FIELD; FIELD; ...};
  |  union identifier { FIELD; FIELD; ...};
  |  safe_union identifier { FIELD; FIELD; ...} identifier;
  |  struct identifier { FIELD; FIELD; ...} identifier;
  |  union identifier { FIELD; FIELD; ...} identifier;

SIZE =  // Must be greater than zero
     constexpr

ANNOTATIONS =
     [empty]
  |  ANNOTATIONS ANNOTATION

ANNOTATION =
  |  @identifier
  |  @identifier(VALUE)
  |  @identifier(ANNO_ENTRY, ANNO_ENTRY  ...)

ANNO_ENTRY =
     identifier=VALUE

VALUE =
     "any text including \" and other escapes"
  |  constexpr
  |  {VALUE, VALUE ...}  // only in annotations

ENUM_ENTRY =
     identifier
  |  identifier = constexpr

Terminologie

Cette section utilise les termes suivants liés à HIDL:

lié Indique que HIDL est utilisé pour les appels de procédure distante entre les processus, implémenté via un mécanisme de type Binder. Voir aussi passthrough .
rappel, asynchrone Interface servie par un utilisateur HAL, transmise à la HAL (via une méthode HIDL), et appelée par la HAL pour renvoyer des données à tout moment.
rappel, synchrone Renvoie les données de l'implémentation de la méthode HIDL d'un serveur au client. Inutilisé pour les méthodes qui renvoient void ou une seule valeur primitive.
client Processus qui appelle les méthodes d'une interface particulière. Un processus HAL ou cadre peut être un client d'une interface et un serveur d'une autre. Voir aussi passthrough .
étend Indique une interface qui ajoute des méthodes et / ou des types à une autre interface. Une interface ne peut étendre qu'une seule autre interface. Peut être utilisé pour un incrément de version mineure dans le même nom de package ou pour un nouveau package (par exemple une extension de fournisseur) pour construire sur un package plus ancien.
génère Indique une méthode d'interface qui renvoie des valeurs au client. Pour renvoyer une valeur non primitive, ou plusieurs valeurs, une fonction de rappel synchrone est générée.
interface Collection de méthodes et types. Traduit en classe en C ++ ou Java. Toutes les méthodes d'une interface sont appelées dans le même sens: un processus client invoque des méthodes implémentées par un processus serveur.
une manière Lorsqu'elle est appliquée à une méthode HIDL, indique que la méthode ne renvoie aucune valeur et ne se bloque pas.
paquet Collection d'interfaces et de types de données partageant une version.
traverser Mode de HIDL dans lequel le serveur est une bibliothèque partagée, dlopen par le client. En mode passthrough, le client et le serveur sont le même processus mais des bases de code séparées. Utilisé uniquement pour importer des bases de code héritées dans le modèle HIDL. Voir aussi Binderized .
serveur Processus qui implémente les méthodes d'une interface. Voir aussi passthrough .
transport Infrastructure HIDL qui déplace les données entre le serveur et le client.
version Version d'un package. Se compose de deux entiers, majeur et mineur. Les incréments de version mineure peuvent ajouter (mais pas changer) des types et des méthodes.