Java HIDL

Dans Android 8.0, l'architecture du système d'exploitation Android a été repensée afin de définir des interfaces claires. entre la plate-forme Android indépendante de l'appareil et la plate-forme spécifique à l'appareil et au fournisseur. du code source. Android a déjà défini de nombreuses interfaces de ce type sous la forme de HAL. interfaces, définies comme des en-têtes C dans hardware/libhardware. HIDL remplacé ces interfaces HAL par des interfaces stables avec gestion des versions, qui peuvent soit en Java (décrit ci-dessous), soit en mode HIDL côté client et côté serveur. interfaces en C++.

Les interfaces HIDL sont destinées à être utilisées principalement à partir du code natif et en tant que HIDL résultat est axé sur la génération automatique d’un code efficace en C++. Toutefois, Les interfaces HIDL doivent également être disponibles pour une utilisation directement à partir de Java, car certaines Les sous-systèmes (tels que la téléphonie) ont des interfaces Java HIDL.

Les pages de cette section décrivent l'interface Java pour les interfaces HIDL, détailler comment créer, enregistrer et utiliser les services, et expliquer comment les HAL et HAL les clients écrits en Java interagissent avec le système HIDL RPC.

Exemple de client

Voici un exemple de client pour une interface IFoo dans un package android.hardware.foo@1.0 enregistré en tant que nom de service default et un service supplémentaire avec le nom de service personnalisé second_impl

Ajouter des bibliothèques

Vous devez ajouter des dépendances à la bibliothèque bouchon HIDL correspondante si que vous souhaitez l'utiliser. Il s'agit généralement d'une bibliothèque statique:

// in Android.bp
static_libs: [ "android.hardware.foo-V1.0-java", ],
// in Android.mk
LOCAL_STATIC_JAVA_LIBRARIES += android.hardware.foo-V1.0-java

Si vous savez que vous extrayez déjà des dépendances sur ces bibliothèques, vous peuvent également utiliser le lien partagé:

// in Android.bp
libs: [ "android.hardware.foo-V1.0-java", ],
// in Android.mk
LOCAL_JAVA_LIBRARIES += android.hardware.foo-V1.0-java

Éléments supplémentaires à prendre en compte pour ajouter des bibliothèques sous Android 10

Si vous disposez d'une application système ou d'un fournisseur qui cible Android 10 ou une version ultérieure, vous pouvez inclure ces bibliothèques de manière statique. Vous pouvez également utiliser des classes HIDL (uniquement) à partir de fichiers JAR personnalisés installés sur l'appareil, avec des API Java stables mises à disposition à l'aide du mécanisme uses-library existant pour les applications système. La la deuxième méthode permet d'économiser de l'espace sur l'appareil. Pour en savoir plus, consultez Implémenter la bibliothèque du SDK Java. Pour applications plus anciennes, l'ancien comportement est conservé.

À partir d'Android 10, version superficielle versions de ces bibliothèques sont également à disposition. Il s'agit du cours en question, mais pas des classes dépendantes. Par exemple, android.hardware.foo-V1.0-java-shallow inclut des classes dans l'élément "foo" mais n'inclut pas les classes android.hidl.base-V1.0-java, qui contient la classe de base de toutes Interfaces HIDL Si vous créez une bibliothèque qui dispose déjà de base de l'interface disponibles en tant que dépendances, vous pouvez utiliser le code suivant:

// in Android.bp
static_libs: [ "android.hardware.foo-V1.0-java-shallow", ],
// in Android.mk
LOCAL_STATIC_JAVA_LIBRARIES += android.hardware.foo-V1.0-java-shallow

Les bibliothèques de base et de gestionnaires HIDL ne sont également plus disponibles au démarrage classpath pour les applications (auparavant, elles étaient parfois utilisées en tant qu'API cachées en raison de le ClassLoader d'Android utilisé comme délégué). Au lieu de cela, ils ont été déplacés vers un nouveau avec jarjar, et les applications qui les utilisent (nécessairement les privilèges applications) doivent disposer de leurs propres copies. modules sur le classpath de démarrage à l'aide de HIDL doit utiliser les variantes superficielles de ces bibliothèques Java et ajouter jarjar_rules: ":framework-jarjar-rules" à leur Android.bp pour utiliser la version de ces bibliothèques existante dans le classpath de démarrage.

Modifier votre source Java

Il n'existe qu'une seule version (@1.0) de ce service. Ce code ne récupère que cette version. Voir extensions d'interface sur la façon de gérer plusieurs versions différentes du service.

import android.hardware.foo.V1_0.IFoo;
...
// retry to wait until the service starts up if it is in the manifest
IFoo server = IFoo.getService(true /* retry */); // throws NoSuchElementException if not available
IFoo anotherServer = IFoo.getService("second_impl", true /* retry */);
server.doSomething(…);

Fournir un service

Le code du framework en Java peut avoir besoin de diffuser des interfaces pour recevoir des des rappels HAL.

Pour l'interface IFooCallback de la version 1.0 de android.hardware.foo, vous pouvez implémenter votre interface dans Java, procédez comme suit:

  1. Définissez votre interface dans HIDL.
  2. Ouvrir /tmp/android/hardware/foo/IFooCallback.java en tant que référence.
  3. Créez un module pour votre implémentation Java.
  4. Examiner la classe abstraite android.hardware.foo.V1_0.IFooCallback.Stub, puis écrire une nouvelle classe pour l'étendre et implémenter les méthodes abstraites.

Afficher les fichiers générés automatiquement

Pour afficher les fichiers générés automatiquement, exécutez la commande suivante:

hidl-gen -o /tmp -Ljava \
  -randroid.hardware:hardware/interfaces \
  -randroid.hidl:system/libhidl/transport android.hardware.foo@1.0

Ces commandes génèrent le répertoire /tmp/android/hardware/foo/1.0 Pour le fichier hardware/interfaces/foo/1.0/IFooCallback.hal, cela génère fichier /tmp/android/hardware/foo/1.0/IFooCallback.java, qui encapsule l'interface Java, le code proxy et les bouchons (proxy et bouchons sont conformes à l'interface).

-Lmakefile génère les règles qui exécutent cette commande lors de la compilation et vous permettre d'inclure android.hardware.foo-V1.0-java et associez-le à la les fichiers appropriés. Un script qui le fait automatiquement pour un projet rempli de interfaces sont accessibles à l'adresse hardware/interfaces/update-makefiles.sh. Dans cet exemple, les chemins d'accès sont relatifs ; du matériel/des interfaces peut être dans votre arborescence de code pour vous permettre de développer une HAL avant de les publier.

Exécuter un service

Le HAL fournit l'interface IFoo, qui doit effectuer des appels asynchrones des rappels au framework sur l'interface IFooCallback. La L'interface IFooCallback n'est pas enregistrée par son nom comme visible service; Au lieu de cela, IFoo doit contenir une méthode telle que setFooCallback(IFooCallback x)

Pour configurer IFooCallback à partir de la version 1.0 de Package android.hardware.foo, ajouter De android.hardware.foo-V1.0-java à Android.mk. Le code pour exécuter le service:

import android.hardware.foo.V1_0.IFoo;
import android.hardware.foo.V1_0.IFooCallback.Stub;
....
class FooCallback extends IFooCallback.Stub {
    // implement methods
}
....
// Get the service from which you will be receiving callbacks.
// This also starts the threadpool for your callback service.
IFoo server = IFoo.getService(true /* retry */); // throws NoSuchElementException if not available
....
// This must be a persistent instance variable, not local,
//   to avoid premature garbage collection.
FooCallback mFooCallback = new FooCallback();
....
// Do this once to create the callback service and tell the "foo-bar" service
server.setFooCallback(mFooCallback);

Extensions d'interface

En supposant qu'un service donné implémente l'interface IFoo sur toutes il est possible que sur un appareil particulier, le service fournisse des fonctionnalités supplémentaires implémentées dans l'extension d'interface IBetterFoo, comme suit:

interface IFoo {
   ...
};

interface IBetterFoo extends IFoo {
   ...
};

Appeler le code de l'interface étendue peut utiliser la méthode castFrom() Méthode Java pour caster en toute sécurité l'interface de base vers la interface étendue:

IFoo baseService = IFoo.getService(true /* retry */); // throws NoSuchElementException if not available
IBetterFoo extendedService = IBetterFoo.castFrom(baseService);
if (extendedService != null) {
  // The service implements the extended interface.
} else {
  // The service implements only the base interface.
}