Interfaces et packages

HIDL est construit autour des interfaces, un type abstrait utilisé dans les domaines orientés objet pour définir des comportements. Chaque interface fait partie d'un package.

Packages

Les noms de packages peuvent avoir des sous-niveaux tels que package.subpackage. La Le répertoire racine des packages HIDL publiés est hardware/interfaces ou vendor/vendorName (par exemple, vendor/google pour Pixel appareils). Le nom du package forme un ou plusieurs sous-répertoires sous la racine directory; tous les fichiers qui définissent un package se trouvent dans le même répertoire. Par exemple : package android.hardware.example.extension.light@2.0 est introuvable moins de hardware/interfaces/example/extension/light/2.0.

Le tableau suivant répertorie les préfixes et les emplacements des packages:

Préfixe du package Position Types d'interface
android.hardware.* hardware/interfaces/* HAL
android.frameworks.* frameworks/hardware/interfaces/* cadres/ associés
android.system.* system/hardware/interfaces/* au système/
android.hidl.* system/libhidl/transport/* core

Le répertoire du package contient des fichiers portant l'extension .hal. Toutes les doit contenir une instruction package nommant le package et version dont fait partie le fichier. Le fichier types.hal, s'il est présent, non pas définir une interface, mais plutôt des types de données accessibles à tous dans le package.

Définition de l'interface

Hormis types.hal, tous les autres fichiers .hal définissent une interface. Une interface est généralement définie comme suit:

interface IBar extends IFoo { // IFoo is another interface
    // embedded types
    struct MyStruct {/*...*/};

    // interface methods
    create(int32_t id) generates (MyStruct s);
    close();
};

Une interface sans déclaration extends explicite implicitement s'étend à partir de android.hidl.base@1.0::IBase (comme java.lang.Object en Java.) L'interface IBase, implicitement importé, déclare plusieurs méthodes réservées qui ne doivent pas et ne peuvent pas être soit redéclarée dans des interfaces définies par l'utilisateur, soit utilisée autrement. Ces méthodes incluent:

  • ping
  • interfaceChain
  • interfaceDescriptor
  • notifySyspropsChanged
  • linkToDeath
  • unlinkToDeath
  • setHALInstrumentation
  • getDebugInfo
  • debug
  • getHashChain

Processus d'importation

L'instruction import est un mécanisme HIDL permettant d'accéder au package interfaces et types dans un autre package. Une instruction import s'applique à deux entités:

  • L'entité d'importation, qui peut être un package ou une de commande
  • Entité importée, qui peut être un package ou une de commande

L'entité d'importation est déterminée par l'emplacement import. Lorsque l'instruction se trouve dans le types.hal : les éléments importés sont visibles par l'ensemble du package. il s'agit d'une importation au niveau du package. Lorsque l'instruction se trouve à l'intérieur d'un fichier d'interface, l'entité d'importation est l'interface elle-même. ceci est un au niveau de l'interface.

L'entité importée est déterminée par la valeur située après import mot clé. La valeur ne doit pas nécessairement être un nom complet. si un composant est omis, il est automatiquement rempli avec les informations du package actuel. Pour les valeurs complètes, les cas d'importation suivants sont acceptés:

  • Importations de packages entiers. Si la valeur est un nom de package et un (syntaxe décrite ci-dessous), l'intégralité du package est importée dans la importation de l'entité.
  • Importations partielles : Si la valeur est: <ph type="x-smartling-placeholder">
      </ph>
    • Une interface, le types.hal du package et cette interface sont importées dans l'entité d'importation.
    • Un UDT défini dans types.hal, seul cet UDT est importé dans L'entité à l'origine de l'importation (les autres types dans types.hal ne sont pas importés).
  • Importations de types uniquement. Si la valeur utilise la syntaxe d'une l'importation partielle décrite ci-dessus, mais avec le mot clé types à la place d'un nom d'interface, seuls les UDT dans types.hal de l'instance package sont importés.

L'entité importée a accès à une combinaison des éléments suivants:

  • Les UDT communs du package importé définis dans types.hal
  • Les interfaces du package importé (pour une importation de package entier) ou les paramètres (pour une importation partielle) dans le but de les appeler, de transmettre et/ou en hérite.

L'instruction d'importation utilise la syntaxe du nom de type complet pour fournir le Nom et version du package ou de l'interface en cours d'importation:

import android.hardware.nfc@1.0;            // import a whole package
import android.hardware.example@1.0::IQuux; // import an interface and types.hal
import android.hardware.example@1.0::types; // import just types.hal

Héritage de l'interface

Une interface peut être une extension d'une interface définie précédemment. Il existe trois types d'extensions:

  • Interface peut ajouter des fonctionnalités à une autre, en incorporant son API ne sont pas modifiées.
  • Le package peut ajouter des fonctionnalités à un autre en incorporant son API ne sont pas modifiées.
  • L'interface peut importer des types à partir d'un package ou d'une interface spécifique.

Une interface ne peut étendre qu'une seule autre interface (sans héritage multiple). Chaque interface d'un package ayant un numéro de version mineure non nulle doit étendre une dans la version précédente du package. Par exemple, si une interface IBar de la version 4.0 du package derivative est basé sur (étend) une interface IFoo dans la version 1.2 du package original, et la version 1.3 du package original est créé, IBar version 4.1 ne peut pas étendre la version 1.3 de IFoo À la place, la version 4.1 de IBar doit étendre La version 4.0 de IBar, qui est liée à la version 1.2 de IFoo. La version 5.0 de IBar pourrait étendre la version 1.3 de IFoo, si comme vous le souhaitez.

Les extensions d'interface n'impliquent pas de dépendance à une bibliothèque ni d'inclusion entre HAL. dans le code généré : ils importent simplement la structure des données et leur méthode au niveau du HIDL. Chaque méthode d'une HAL doit être implémentée CARL.

Extensions de fournisseur

Dans certains cas, les extensions de fournisseur sont implémentées en tant que sous-classes du qui représente l'interface principale qu'ils étendent. Le même objet est enregistré sous le nom et la version HAL de base, et sous le sous-réseau (vendor) Nom et version HAL.

Gestion des versions

Les packages ont des versions gérées et les interfaces possèdent la version de leur package. Les versions sont exprimées sous la forme de deux entiers : major.minor.

  • Les versions majeures ne sont pas rétrocompatibles. Incrémentation le numéro de version majeure réinitialise le numéro de version mineure à 0.
  • Les versions mineures sont rétrocompatibles. En augmentant la valeur indique que la version la plus récente est entièrement rétrocompatible avec le version précédente. Vous pouvez ajouter de nouvelles structures et méthodes de données, mais aucune structure existante les structures de données ou les signatures de méthode peuvent être modifiées.

Plusieurs versions majeures ou mineures d'une HAL peuvent être présentes sur un appareil. simultanément. Cependant, une version mineure est préférable à une version majeure. car le code client qui fonctionne avec l'interface d'une version mineure précédente fonctionne également avec les versions ultérieures mineures de cette même interface. Pour plus pour en savoir plus sur la gestion des versions et les extensions de fournisseur, consultez Gestion des versions HIDL.

Résumé de la mise en page de l'interface

Cette section résume comment gérer un package d'interface HIDL (tel que hardware/interfaces) et regroupe les informations présentées tout au long de la section HIDL. Avant de lire cet article, assurez-vous de bien connaître la gestion des versions HIDL, le hachage avec hidl-gen, les détails de l'utilisation avec HIDL en général et définitions suivantes:

Terme Définition
interface binaire d'application (ABI) Interface de programmation d'application et liaisons binaires requises.
nom complet (fqName) Nom permettant de distinguer un type d'hidl. Exemple: android.hardware.foo@1.0::IFoo
colis Package contenant une interface et des types HIDL. Exemple: android.hardware.foo@1.0
racine du package Package racine contenant les interfaces HIDL. Exemple: interface HIDL android.hardware se trouve dans la racine du package android.hardware.foo@1.0
chemin d'accès racine du package Emplacement dans l'arborescence source Android où est mappée la racine d'un package.

Pour obtenir plus de définitions, consultez HIDL Terminologie.

Chaque fichier peut être trouvé à partir du mappage de la racine du package et son nom complet ;

Les racines du package sont spécifiées sur hidl-gen en tant qu'argument -r android.hardware:hardware/interfaces Par exemple, si le le package est vendor.awesome.foo@1.0::IFoo et hidl-gen est envoyée le -r vendor.awesome:some/device/independent/path/interfaces, le fichier d'interface doit se trouver dans $ANDROID_BUILD_TOP/some/device/independent/path/interfaces/foo/1.0/IFoo.hal

En pratique, il est recommandé pour un fournisseur ou un OEM nommé awesome. de placer leurs interfaces standards dans vendor.awesome. Après un colis chemin d'accès a été sélectionné, il ne doit pas être modifié, car il est intégré à l'ABI de l'interface.

Le mappage du chemin d'accès au package doit être unique

Par exemple, si vous avez -rsome.package:$PATH_A et -rsome.package:$PATH_B, $PATH_A doit être égal à $PATH_B pour un répertoire d'interface cohérent (cela rend également interfaces de gestion des versions plus facilement).

La racine du package doit comporter un fichier de gestion des versions

Si vous créez un chemin d'accès au package tel que -r vendor.awesome:vendor/awesome/interfaces, vous devez également créer le fichier $ANDROID_BUILD_TOP/vendor/awesome/interfaces/current.txt, qui doit contenir les hachages des interfaces créées à l'aide de l'option -Lhash dans hidl-gen (ce sujet est abordé en détail dans Hachage avec hidl-gen).

Les interfaces sont indépendantes de l'appareil zones géographiques

En pratique, nous vous recommandons de partager les interfaces entre les branches. Ce permet de réutiliser le code le plus souvent possible et de le tester au maximum sur différentes appareils et cas d'utilisation.