Gestion des versions d'interface

HIDL nécessite que chaque interface écrite en HIDL possède une version gérée. Après une opération HAL l'interface est publiée, elle est bloquée et toute modification supplémentaire doit être apportée nouvelle version de cette interface. Bien qu'une interface publiée donnée ne puisse pas être modifié, il peut être étendu par une autre interface.

Structure du code HIDL

Le code HIDL est organisé en blocs définis par l'utilisateur types, interfaces et packages:

  • Types définis par l'utilisateur (UDT). HIDL permet d'accéder à un ensemble types de données primitifs qui peuvent être utilisés pour composer des types plus complexes via les structures, les unions et les énumérations. Les UDT sont transmises aux méthodes interfaces et peuvent être définies au niveau d'un package (commun à toutes interfaces) ou localement à une interface.
  • Interfaces : En tant que composant de base de HIDL, une interface se compose d'UDT et de déclarations de méthode. Les interfaces peuvent aussi hériter une autre interface.
  • Packages : Organise les interfaces HIDL associées et les données sur lesquels elles opèrent. Un package est identifié par un nom et une version et comprend les éléments suivants: <ph type="x-smartling-placeholder">
      </ph>
    • Fichier de définition du type de données appelé types.hal.
    • Aucune, une ou plusieurs interfaces, chacune dans son propre fichier .hal.

Le fichier de définition de type de données types.hal ne contient que des UDT les UDT au niveau du package sont conservés dans un seul fichier. Représentations dans la cible sont disponibles pour toutes les interfaces du package.

Philosophie de gestion des versions

Un package HIDL (tel que android.hardware.nfc), après avoir été publiée pour une version donnée (par exemple, 1.0) est immuable. cette ne peut pas être modifiée. Les modifications des interfaces du package ou de toute les modifications de ses UDT ne peuvent avoir lieu que dans un autre package.

Dans HIDL, la gestion des versions s'applique au niveau du package, pas au niveau de l'interface, et toutes les interfaces et tous les UDT d'un package partagent la même version. Colis d'après les versions sémantiques gestion des versions sans les composants de niveau de correctif et de métadonnées de compilation. Dans un package donné, une augmentation de version mineure implique la nouvelle version de le package est rétrocompatible avec l'ancien paquet et un système principal version signifie que la nouvelle version du package n'est pas rétrocompatible avec l'ancien package.

D'un point de vue conceptuel, un package peut être associé à un autre package de plusieurs manières:

  • Pas du tout.
  • Extensibilité rétrocompatible au niveau du package. Ce se produit pour les nouvelles versions supérieures d'une version mineure (révision par incréments suivante) d'un package ; le nouveau package a le même nom et la même version majeure que l'ancien, mais une version mineure supérieure. D'un point de vue fonctionnel, le nouveau package est un sur-ensemble de l'ancien "package", c'est-à-dire: <ph type="x-smartling-placeholder">
      </ph>
    • Les interfaces de niveau supérieur du package parent sont présentes dans le nouveau package, bien que les interfaces puissent avoir de nouvelles méthodes, de nouveaux UDT locaux d'interface (les l'extension au niveau de l'interface décrite ci-dessous) et de nouveaux modèles UDT dans types.hal
    • De nouvelles interfaces peuvent également être ajoutées au nouveau package.
    • Tous les types de données du package parent sont présents dans le nouveau package et peuvent être gérés par les méthodes (éventuellement réimplémentées) de l'ancien package.
    • De nouveaux types de données peuvent également être ajoutés pour être utilisés par l'une ou l'autre des nouvelles méthodes de mise à jour. via des interfaces existantes, ou par de nouvelles interfaces.
  • Extensibilité rétrocompatible au niveau de l'interface. Les nouvelles le package d'origine peut également étendre le package d'origine en se basant sur des des interfaces qui fournissent simplement des fonctionnalités supplémentaires, et non l’interface de base. À cette fin, il peut être souhaitable d'effectuer les opérations suivantes: <ph type="x-smartling-placeholder">
      </ph>
    • Les interfaces du nouveau package ont besoin de recourir aux types de données de l'ancien. d'un package.
    • Les interfaces du nouveau package peuvent étendre les interfaces d'un ou de plusieurs anciens packages packages.
  • Prolonger l'incompatibilité ascendante d'origine Il s'agit d'un de la mise à niveau vers la version majeure du package et il n'est pas nécessaire qu'il y ait de corrélation entre les deux. Si tel est le cas, il peut être exprimé à l'aide d'une combinaison de l'ancienne version du package et héritage d'un sous-ensemble de l'ancien package.

Structuration de l'interface

Pour une interface bien structurée, l'ajout de nouveaux types de fonctionnalités ne font pas partie de la conception d’origine devrait nécessiter une modification du HIDL de commande. À l'inverse, si vous pouvez ou prévoyez d'effectuer un changement des deux côtés L'interface qui introduit de nouvelles fonctionnalités sans modifier l'interface elle-même, alors l’interface n’est pas structurée.

Treble prend en charge les composants fournisseur et système compilés séparément dans lesquels le vendor.img sur un appareil et system.img peut être compilées séparément. Toutes les interactions entre vendor.img et Les system.img doivent être définies explicitement et minutieusement afin de pouvoir continuent à travailler pendant de nombreuses années. Cela inclut de nombreuses surfaces d'API, mais un surface est le mécanisme d'IPC utilisé par HIDL pour la communication inter-processus sur le Limite system.img/vendor.img.

Conditions requises

Toutes les données transmises via HIDL doivent être définies explicitement. Pour vous assurer qu'une et le client peut continuer à fonctionner ensemble, même lorsqu'il est compilé séparément ou développées indépendamment, les données doivent respecter les configuration requise:

  • Peut être décrit directement en HIDL (à l'aide d'énumérations structs, etc.) avec noms sémantiques et leur signification.
  • Peut être décrit par une norme publique telle que ISO/IEC 7816.
  • Peut être décrit par une norme matérielle ou une disposition physique du matériel.
  • Il peut s'agir de données opaques (telles que des clés publiques, des identifiants, etc.) si nécessaire.

Si des données opaques sont utilisées, elles ne doivent être lues que par un seul côté du HIDL de commande. Par exemple, si le code vendor.img donne à un composant sur le system.img un message de chaîne ou vec<uint8_t> données, ces données ne peuvent pas être analysées par la system.img elle-même. il peut ne seront renvoyés qu'à vendor.img pour interpréter. Quand en transmettant une valeur de vendor.img au code fournisseur sur system.img ou à un autre appareil, le format des données et la façon dont elles doit être décrite avec précision et fait toujours partie du de commande.

Consignes

Vous devez être en mesure d'écrire une implémentation ou un client d'une HAL en utilisant uniquement les fichiers .hal (vous n'avez pas besoin de consulter la source Android standards). Nous vous recommandons de spécifier le comportement exact requis. Les déclarations telles que tels que "une implémentation pourrait faire A ou B" encourager les implémentations à devenir en lien avec les clients avec lesquels ils sont développés.

Mise en page du code HIDL

HIDL inclut les packages de base et les packages fournisseurs.

Les interfaces HIDL principales sont celles spécifiées par Google. Les packages auxquels ils appartiennent commencent par android.hardware. et sont nommés par sous-système, potentiellement avec des niveaux imbriqués de nommage. Par exemple, le package NFC est nommé android.hardware.nfc et le package appareil photo est android.hardware.camera En général, un package de base porte le nom android.hardware.[name1].[name2].... Les packages HIDL ont une version en plus de leur nom. Par exemple, le package android.hardware.camera est peut-être en version 3.4. c'est important, car la version d'un package affecte son emplacement dans l'arborescence source.

Tous les packages de base sont placés sous hardware/interfaces/ dans du système de compilation. Le package android.hardware.[name1].[name2]... à la version $m.$n est sous hardware/interfaces/name1/name2/.../$m.$n/ ; package La version 3.4 de android.hardware.camera se trouve dans le répertoire hardware/interfaces/camera/3.4/. Un mappage codé en dur existe entre le préfixe de package android.hardware. et le chemin d'accès hardware/interfaces/

Les packages autres que les packages principaux sont ceux produits par le fournisseur SoC ou l'ODM. La pour les packages non principaux est vendor.$(VENDOR).hardware., où $(VENDOR)fait référence à un fournisseur de SoC ou à un OEM/ODM. Cela correspond au chemin vendor/$(VENDOR)/interfaces dans l'arborescence (ce mappage est également codées en dur).

Noms complets définis par l'utilisateur

Dans HIDL, chaque UDT a un nom complet composé du nom UDT, le nom du package dans lequel l'UDT est défini et la version du package. La un nom complet n'est utilisé que lorsque des instances du type sont déclarées et et non là où le type lui-même est défini. Par exemple, supposons que le package La version 1.0 de android.hardware.nfc, définit un struct nommée NfcData. Sur le site de la déclaration (que ce soit types.hal ou dans une déclaration d'interface), la déclaration indique simplement:

struct NfcData {
    vec<uint8_t> data;
};

Lors de la déclaration d'une instance de ce type (que ce soit dans une structure de données ou comme paramètre de méthode), utilisez le nom de type complet:

android.hardware.nfc@1.0::NfcData

La syntaxe générale est PACKAGE@VERSION::UDT, où:

  • PACKAGE est le nom d'un package HIDL, séparé par un point (par exemple, android.hardware.nfc).
  • VERSION est la version majeure.minor-version séparée par un point. format du package (par exemple, 1.0).
  • UDT est le nom d'un UDT HIDL, séparé par un point. Étant donné que HIDL prend en charge les UDT imbriquées, les interfaces HIDL peuvent contenir des UDT (un type de déclaration imbriquée), des points sont utilisés pour accéder aux noms.

Par exemple, si la déclaration imbriquée suivante a été définie dans le fichier commun fichier de types dans la version android.hardware.example du package 1.0:

// types.hal
package android.hardware.example@1.0;
struct Foo {
    struct Bar {
        // …
    };
    Bar cheers;
};

Le nom complet de Bar est android.hardware.example@1.0::Foo.Bar Si, en plus d’être dans du package ci-dessus, la déclaration imbriquée se trouvait dans une interface appelée IQuux:

// IQuux.hal
package android.hardware.example@1.0;
interface IQuux {
    struct Foo {
        struct Bar {
            // …
        };
        Bar cheers;
    };
    doSomething(Foo f) generates (Foo.Bar fb);
};

Le nom complet de Bar est android.hardware.example@1.0::IQuux.Foo.Bar

Dans les deux cas, Bar ne peut être désigné que par Bar dans le champ d'application de la déclaration de Foo. Sur le colis ou au niveau de l'interface, vous devez faire référence à Bar via Foo: Foo.Bar, comme dans la déclaration de la méthode doSomething ci-dessus. Vous pouvez également déclarer la méthode de manière plus détaillée comme suit:

// IQuux.hal
doSomething(android.hardware.example@1.0::IQuux.Foo f) generates (android.hardware.example@1.0::IQuux.Foo.Bar fb);

Valeurs d'énumération complètes

Si un UDT est de type enum, alors chaque valeur de ce type possède un nom complet qui commence par le nom complet du type d'énumération suivi du signe deux-points, puis du nom de la valeur d'énumération. Par exemple : suppose la version 1.0 du package android.hardware.nfc, définit un type d'énumération NfcStatus:

enum NfcStatus {
    STATUS_OK,
    STATUS_FAILED
};

Lorsque vous faites référence à STATUS_OK, le nom complet est le suivant:

android.hardware.nfc@1.0::NfcStatus:STATUS_OK

La syntaxe générale est PACKAGE@VERSION::UDT:VALUE, où:

  • PACKAGE@VERSION::UDT est le exactement le même nom complet pour le type d'énumération.
  • VALUE est le nom de la valeur.

Règles d'inférence automatique

Il n'est pas nécessaire de spécifier un nom UDT complet. Un nom UDT peut omettez en toute sécurité les éléments suivants:

  • Le package (par exemple, @1.0::IFoo.Type
  • Package et version (par exemple, IFoo.Type

HIDL tente de compléter le nom à l'aide de règles d'interférence automatique (règle inférieure le chiffre correspond au niveau de priorité le plus élevé).

Règle 1

Si aucun package et aucune version ne sont fournis, une tentative de recherche du nom local est effectuée. Exemple :

interface Nfc {
    typedef string NfcErrorMessage;
    send(NfcData d) generates (@1.0::NfcStatus s, NfcErrorMessage m);
};

NfcErrorMessage est recherché localement et typedef au-dessus de celui-ci est trouvé. NfcData est également recherché localement, mais comme c'est le cas non définies localement, les règles 2 et 3 sont utilisées. @1.0::NfcStatus fournit une version, la règle 1 ne s'applique donc pas.

Règle 2

Si la règle 1 échoue et qu'un composant du nom complet est manquant (package, version ou package et version), le composant est rempli automatiquement avec des informations du package actuel. Le compilateur HIDL recherche ensuite dans fichier actuel (et toutes les importations) pour trouver le nom complet saisi automatiquement. À l'aide de l'exemple ci-dessus, supposons que la déclaration ExtendedNfcData a été faite dans le même package (android.hardware.nfc) et (1.0) en tant que NfcData, comme suit:

struct ExtendedNfcData {
    NfcData base;
    // … additional members
};

Le compilateur HIDL renseigne le nom du package et le nom de la version à partir du le package actuel pour produire le nom UDT complet android.hardware.nfc@1.0::NfcData Comme le nom existe dans le le package actuel (en supposant qu'il est importé correctement), il est utilisé pour la déclaration.

Un nom du package actuel n'est importé que si l'un des éléments suivants est true:

  • Il est importé explicitement avec une instruction import.
  • Il est défini dans types.hal dans le package actuel.

La même procédure est suivie si NfcData a été qualifié uniquement par le numéro de version:

struct ExtendedNfcData {
    // autofill the current package name (android.hardware.nfc)
    @1.0::NfcData base;
    // … additional members
};

Règle 3

Si la règle 2 ne produit pas de correspondance (l'UDT n'est pas défini dans le code package), le compilateur HIDL recherche une correspondance dans tous les packages importés. À l'aide de l'exemple ci-dessus, supposons que ExtendedNfcData est déclaré dans la version 1.1 du package android.hardware.nfc, 1.1 importe 1.0 comme il se doit (voir Extensions au niveau du package), et la définition spécifie uniquement le nom UDT:

struct ExtendedNfcData {
    NfcData base;
    // … additional members
};

Le compilateur recherche n'importe quel UDT nommé NfcData et en trouve un dans android.hardware.nfc en version 1.0, ce qui entraîne une UDT complet de android.hardware.nfc@1.0::NfcData. Si plus plusieurs correspondances sont trouvées pour un UDT partiellement qualifié, le compilateur HIDL génère une erreur.

Exemple

À l'aide de la règle 2, un type importé défini dans le package actuel est privilégié un type importé d'un autre package:

// hardware/interfaces/foo/1.0/types.hal
package android.hardware.foo@1.0;
struct S {};

// hardware/interfaces/foo/1.0/IFooCallback.hal
package android.hardware.foo@1.0;
interface IFooCallback {};

// hardware/interfaces/bar/1.0/types.hal
package android.hardware.bar@1.0;
typedef string S;

// hardware/interfaces/bar/1.0/IFooCallback.hal
package android.hardware.bar@1.0;
interface IFooCallback {};

// hardware/interfaces/bar/1.0/IBar.hal
package android.hardware.bar@1.0;
import android.hardware.foo@1.0;
interface IBar {
    baz1(S s); // android.hardware.bar@1.0::S
    baz2(IFooCallback s); // android.hardware.foo@1.0::IFooCallback
};
  • S est interpolé en tant que android.hardware.bar@1.0::S, se trouve dans bar/1.0/types.hal (car types.hal est automatiquement importées).
  • IFooCallback est interpolé en tant que android.hardware.bar@1.0::IFooCallback à l'aide de la règle 2, est introuvable, car bar/1.0/IFooCallback.hal n'a pas été importé automatiquement (comme types.hal). Ainsi, la règle 3 le résout en android.hardware.foo@1.0::IFooCallback, qui est importé via import android.hardware.foo@1.0;).

types.hal

Chaque package HIDL contient un fichier types.hal contenant des UDT qui sont partagés entre toutes les interfaces participant à ce package. Types de HIDL sont toujours publiques ; qu'un UDT soit déclaré ou non types.hal ou dans une déclaration d'interface, ces types sont accessibles en dehors du champ d'application où ils sont définis. types.hal n'est pas destiné à décrire l'API publique d'un package, mais plutôt à héberger des UDT utilisé par toutes les interfaces du package. En raison de la nature du HIDL, tous les UDT font partie de l'interface.

types.hal se compose d'UDT et d'instructions import. Étant donné que types.hal est mis à la disposition de toutes les interfaces de (il s'agit d'une importation implicite), ces instructions import sont au niveau du package par définition. Les UDT dans types.hal peuvent également intégrer UDT et interfaces ainsi importés.

Par exemple, pour un IFoo.hal:

package android.hardware.foo@1.0;
// whole package import
import android.hardware.bar@1.0;
// types only import
import android.hardware.baz@1.0::types;
// partial imports
import android.hardware.qux@1.0::IQux.Quux;
// partial imports
import android.hardware.quuz@1.0::Quuz;

Les éléments suivants sont importés:

  • android.hidl.base@1.0::IBase (implicitement)
  • android.hardware.foo@1.0::types (implicitement)
  • Tous les éléments de android.hardware.bar@1.0 (y compris tous interfaces et ses types.hal)
  • types.hal de android.hardware.baz@1.0::types (les interfaces de android.hardware.baz@1.0 ne sont pas importées)
  • IQux.hal et types.hal de android.hardware.qux@1.0
  • Quuz à partir de android.hardware.quuz@1.0 (en supposant Quuz est défini dans types.hal, l'intégralité types.hal fichier est analysé, mais les types autres que Quuz ne sont pas importées).

Gestion des versions au niveau de l'interface

Chaque interface d'un package se trouve dans son propre fichier. Le package auquel appartient l'interface est déclarée en haut de l'interface à l'aide de la méthode package. Après la déclaration du package, zéro ou plus les importations au niveau de l'interface (partielles ou complètes) peuvent être répertoriées. Exemple :

package android.hardware.nfc@1.0;

Dans HIDL, les interfaces peuvent hériter d'autres interfaces à l'aide du extends mot clé. Pour qu'une interface étende une autre interface, doit y avoir accès via une instruction import. Le nom du l'interface étendue (l'interface de base) respecte les règles pour type-name d'éligibilité expliquée ci-dessus. Une interface ne peut hériter que d'une seule interface. HIDL n'est pas compatible avec l'héritage multiple.

Les exemples de gestion des versions "uprev" ci-dessous utilisent le package suivant:

// types.hal
package android.hardware.example@1.0
struct Foo {
    struct Bar {
        vec<uint32_t> val;
    };
};

// IQuux.hal
package android.hardware.example@1.0
interface IQuux {
    fromFooToBar(Foo f) generates (Foo.Bar b);
}

Règles d'augmentation

Pour définir un package package@major.minor : A ou l'ensemble de B doit être vraie:

Règle A "Est une version mineure de début" : toutes les versions mineures précédentes, package@major.0, package@major.1, etc. package@major.(minor-1) ne doit pas être défini.
OR
Règle B

Toutes les affirmations suivantes sont vraies:

  1. "La version mineure précédente est valide" : package@major.(minor-1) doivent être définis et suivre la même règle A (aucun des package@major.0 à package@major.(minor-2) ou règle B (s'il s'agit d'une augmentation de @major.(minor-2)) ;

    ET

  2. "Hériter d'au moins une interface portant le même nom" : il existe un l'interface package@major.minor::IFoo qui étend package@major.(minor-1)::IFoo (si le package précédent comporte une interface) ;

    ET

  3. "Aucune interface héritée portant un nom différent" : il ne doit pas exister package@major.minor::IBar qui s'étend package@major.(minor-1)::IBaz, où IBar et IBaz sont deux noms différents. S'il existe une interface avec même nom, package@major.minor::IBar doit étendre package@major.(minor-k)::IBar de sorte qu'il n'existe pas d'IBar avec plus petit.

En raison de la règle A:

  • Le package peut commencer par n'importe quel numéro de version mineure (par exemple, android.hardware.biometrics.fingerprint commence à @2.1).
  • L'exigence "android.hardware.foo@1.0 n'est pas définie" signifie le répertoire hardware/interfaces/foo/1.0 ne devrait même pas exister.

Cependant, la règle A n'affecte pas un package portant le même nom, mais ayant une paire valeur/clé une autre version majeure (par exemple, android.hardware.camera.device a à la fois @1.0 et @3.2 défini @3.2 n'a pas besoin d'interagir avec @1.0.) Par conséquent, @3.2::IExtFoo peut étendre @1.0::IFoo

Si le nom du package est différent, package@major.minor::IBar peut s'étendre à partir d'une interface avec un un autre nom (par exemple, android.hardware.bar@1.0::IBar peut étendre android.hardware.baz@2.2::IBaz). Si une interface ne dispose pas déclarer explicitement un super-type avec le mot clé extend, étend android.hidl.base@1.0::IBase (sauf IBase) lui-même).

Les sections B.2 et B.3 doivent être suivies en même temps. Par exemple, même si android.hardware.foo@1.1::IFoo extension android.hardware.foo@1.0::IFoo pour valider la règle B.2, si une android.hardware.foo@1.1::IExtBar extension android.hardware.foo@1.0::IBar, ce montant n'est toujours pas valide.

Interfaces Uprev

Pour augmenter la valeur de android.hardware.example@1.0 (défini ci-dessus) à @1.1:

// types.hal
package android.hardware.example@1.1;
import android.hardware.example@1.0;

// IQuux.hal
package android.hardware.example@1.1
interface IQuux extends @1.0::IQuux {
    fromBarToFoo(Foo.Bar b) generates (Foo f);
}

Il s'agit d'un import au niveau du package de la version 1.0 de android.hardware.example dans types.hal. Bien qu'il ne soit pas nouveau Les UDT sont ajoutées dans la version 1.1 du package. Les références aux UDT dans la version 1.0 sont encore nécessaires, d'où l'importation au niveau du package. dans le pays suivant : types.hal. (Le même effet aurait pu être obtenu avec une importation au niveau de l'interface dans IQuux.hal.)

Dans extends @1.0::IQuux, dans la déclaration de IQuux, nous avons spécifié la version de IQuux actuellement en cours héritée (la clarification est obligatoire, car IQuux est utilisé pour déclarer une interface et hériter d'une interface). Étant donné que les déclarations sont simplement les noms qui héritent de tous les attributs de package et de version sur le site du la liste doit être clarifiée dans le nom de l'interface de base ; nous aurait également pu utiliser l'UDT complet, mais cela aurait été redondants.

La nouvelle interface IQuux ne redéclare pas la méthode fromFooToBar() hérite de @1.0::IQuux ; il suffit affiche la nouvelle méthode et ajoute fromBarToFoo(). En HIDL, les valeurs héritées ne peuvent pas être déclarées à nouveau dans les interfaces enfants. Par conséquent, l'interface IQuux ne peut pas déclarer le fromFooToBar() explicitement.

Conventions Uprev

Il arrive que le nom de l'interface d'extension doive être renommé. Nous vous recommandons que les extensions, les structures et les unions d'énumération portent le même nom que ce qu'ils étendent ; sauf s'ils sont suffisamment différents pour justifier un nouveau nom. Exemples :

// in parent hal file
enum Brightness : uint32_t { NONE, WHITE };

// in child hal file extending the existing set with additional similar values
enum Brightness : @1.0::Brightness { AUTOMATIC };

// extending the existing set with values that require a new, more descriptive name:
enum Color : @1.0::Brightness { HW_GREEN, RAINBOW };

Si une méthode peut avoir un nouveau nom sémantique (par exemple, fooWithLocation), il est préférable d'utiliser cette option. Sinon, il doit s'agir nommé de la même manière que ce qu'il étend. Par exemple, la méthode foo_1_1 dans @1.1::IFoo peut remplacer la fonctionnalité de la méthode foo dans @1.0::IFoo, s'il n'y a pas de meilleure nom alternatif.

Gestion des versions au niveau du package

La gestion des versions HIDL s'effectue au niveau du package. après la publication d'un package, est immuable (son ensemble d'interfaces et d'UDT ne peut pas être modifié). Les packages peuvent se rapportent les uns aux autres de plusieurs manières, qui peuvent toutes s'exprimer via un combinaison de l'héritage au niveau de l'interface et de la création d'UDT par composition.

Cependant, un type de relation est strictement défini et doit être appliqué: Héritage rétrocompatible au niveau du package. Dans ce scénario, le Le package parent correspond au package hérité et Le package child est celui qui étend le parent. Au niveau du package Les règles d'héritage rétrocompatibles sont les suivantes:

  1. Toutes les interfaces de niveau supérieur du package parent sont héritées par les interfaces dans le package enfant.
  2. De nouvelles interfaces peuvent également être ajoutées au nouveau package (aucune restriction les relations avec d'autres interfaces dans d'autres packages).
  3. De nouveaux types de données peuvent également être ajoutés pour être utilisés par l'une ou l'autre des nouvelles méthodes de mise à jour. via des interfaces existantes, ou par de nouvelles interfaces.

Ces règles peuvent être implémentées à l'aide de l'héritage au niveau de l'interface HIDL et de l'UDT la composition, mais ils nécessitent des connaissances de niveau méta-niveau pour connaître ces relations constituent une extension de package rétrocompatible. Ces connaissances sont déduites comme suit:

Si un package répond à cette exigence, hidl-gen applique des règles de rétrocompatibilité.