HIDL Java

In Android 8.0 wurde die Architektur des Android-Betriebssystems umgestaltet, um klare Schnittstellen zu definieren. zwischen der geräteunabhängigen Android-Plattform und den geräte- und anbieterspezifischen Code. Android hat bereits viele dieser Schnittstellen in Form von HAL definiert. Schnittstellen, die in hardware/libhardware als C-Header definiert sind. HIDL diese HAL-Schnittstellen durch stabile, versionierte Schnittstellen ersetzt wurden, entweder in Java (siehe Beschreibung unten) oder clientseitiges und serverseitiges HIDL Schnittstellen in C++.

HIDL-Schnittstellen werden hauptsächlich aus nativem Code verwendet und Ergebnis-HIDL konzentriert sich auf die automatische Generierung von effizientem Code in C++. Sie können jedoch HIDL-Schnittstellen müssen auch für die direkte Verwendung in Java verfügbar sein, da einige Android- Subsysteme (z. B. Telefonie) verfügen über Java HIDL-Schnittstellen.

Die Seiten in diesem Abschnitt beschreiben das Java-Front-End für HIDL-Schnittstellen. Erläutern, wie Dienste erstellt, registriert und genutzt werden und wie HALs und HAL funktionieren In Java geschriebene Clients interagieren mit dem HIDL RPC-System.

Kundenbeispiel

Dies ist ein Beispiel eines Clients für die Schnittstelle IFoo im Paket android.hardware.foo@1.0, die als Dienstname registriert ist default und ein zusätzlicher Dienst mit dem benutzerdefinierten Dienstnamen second_impl.

Bibliotheken hinzufügen

Sie müssen Abhängigkeiten zur entsprechenden HIDL-Stub-Bibliothek hinzufügen, wenn die Sie verwenden möchten. Normalerweise ist dies eine statische Bibliothek:

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

Wenn Sie wissen, dass Sie bereits Abhängigkeiten von diesen Bibliotheken abrufen, kann auch eine freigegebene Verknüpfung verwenden:

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

Weitere Überlegungen zum Hinzufügen von Bibliotheken in Android 10

Wenn Sie eine System- oder Anbieter-App haben, die auf Android 10 oder höher ausgerichtet ist, können Sie diese Bibliotheken statisch einbinden. Sie können auch (nur) HIDL-Klassen verwenden aus benutzerdefinierten JARs, die auf dem Gerät mit stabilen Java-APIs installiert sind Dabei wird der vorhandene Mechanismus uses-library für System-Apps verwendet. Die spart Speicherplatz auf dem Gerät. Weitere Informationen finden Sie unter Java SDK-Bibliothek implementieren. Für älteren Apps verwendet, wird das alte Verhalten beibehalten.

Ab Android 10 „oberflächlich“ Versionen dieser Bibliotheken sind ebenfalls verfügbar. Dazu gehören der betreffende Kurs, aber keine der abhängigen Klassen gibt. Beispiel: android.hardware.foo-V1.0-java-shallow enthält Klassen in foo. -Paket enthält, jedoch keine Klassen in android.hidl.base-V1.0-java, die die Basisklasse aller HIDL-Schnittstellen Wenn Sie eine Bibliothek erstellen, die bereits die bevorzugte als Abhängigkeit zur Verfügung stehen, können Sie Folgendes verwenden:

// 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

HIDL-Basis- und Managerbibliotheken sind ebenfalls beim Booten nicht mehr verfügbar Klassenpfad für Apps (bisher wurden sie manchmal als verborgene API verwendet, Delegat-First-Classloader von Android). Stattdessen wurden sie in eine neue Namespace mit jarjar und Anwendungen, die diese verwenden (unbedingt priv Apps) müssen separate Kopien haben. Module im Boot-Klassenpfad mithilfe von HIDL muss die oberflächlichen Varianten dieser Java-Bibliotheken verwenden und jarjar_rules: ":framework-jarjar-rules" zu ihrem/seinem Android.bp, um die vorhandene Version dieser Bibliotheken zu verwenden im Boot-Klassenpfad.

Java-Quelle modifizieren

Es gibt nur eine Version (@1.0) dieses Dienstes, daher wird dieser Code ruft nur diese Version ab. Weitere Informationen finden Sie unter Erweiterungen für die Benutzeroberfläche .

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(…);

Dienst bereitstellen

Framework-Code in Java muss möglicherweise Schnittstellen bereitstellen, um asynchrone Rückrufen von HALs.

Für die IFooCallback-Schnittstelle in Version 1.0 des android.hardware.foo-Pakets enthält, können Sie Ihre Schnittstelle implementieren in Gehen Sie dazu so vor:

  1. Definieren Sie Ihre Schnittstelle in HIDL.
  2. /tmp/android/hardware/foo/IFooCallback.java öffnen als Referenz.
  3. Erstellen Sie ein neues Modul für Ihre Java-Implementierung.
  4. Die abstrakte Klasse untersuchen android.hardware.foo.V1_0.IFooCallback.Stub und anschließend einen neuen Kurs schreiben um sie zu erweitern und abstrakte Methoden zu implementieren.

Automatisch generierte Dateien ansehen

Führen Sie folgenden Befehl aus, um die automatisch generierten Dateien aufzurufen:

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

Mit diesen Befehlen wird das Verzeichnis /tmp/android/hardware/foo/1.0 Für die Datei hardware/interfaces/foo/1.0/IFooCallback.hal generiert die Datei /tmp/android/hardware/foo/1.0/IFooCallback.java, die kapselt die Java-Schnittstelle, den Proxy-Code und die Stubs (sowohl Proxy- -Stubs entsprechen der -Schnittstelle).

-Lmakefile generiert die Regeln, die diesen Befehl beim Build ausführen Zeit und ermöglichen es Ihnen, android.hardware.foo-V1.0-java und verknüpfen Sie sie mit dem die entsprechenden Dateien. Ein Skript, das dies für ein Projekt mit vielen finden Sie unter hardware/interfaces/update-makefiles.sh. Die Pfade in diesem Beispiel sind relativ. Hardware/Schnittstellen können temporäre unter Ihrem Code-Baum, damit Sie eine HAL vor der bei der Veröffentlichung.

Dienst ausführen

Der HAL stellt die IFoo-Schnittstelle bereit, die eine asynchrone Callbacks an das Framework über die IFooCallback-Schnittstelle. Die Die IFooCallback-Schnittstelle ist namentlich nicht als sichtbar registriert Service; Stattdessen muss IFoo eine Methode wie setFooCallback(IFooCallback x)

Zum Einrichten von IFooCallback aus Version 1.0 des android.hardware.foo Paket, hinzufügen android.hardware.foo-V1.0-java bis Android.mk. Der Code zum Ausführen des Dienstes ist:

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);

Erweiterungen der Benutzeroberfläche

Wenn ein bestimmter Dienst die IFoo-Schnittstelle für alle kann es passieren, dass der Dienst auf einem bestimmten Gerät zusätzliche Funktionen, die in der Erweiterung für die Benutzeroberfläche implementiert wurden IBetterFoo:

interface IFoo {
   ...
};

interface IBetterFoo extends IFoo {
   ...
};

Ein Aufrufcode, der die erweiterte Oberfläche berücksichtigt, kann die Funktion castFrom()-Java-Methode, um die Basisschnittstelle sicher in den erweiterte Oberfläche:

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.
}