Google 致力于为黑人社区推动种族平等。查看具体举措
Diese Seite wurde von der Cloud Translation API übersetzt.
Switch to English

HIDL Java

Android 8.0 hat das Android-Betriebssystem neu strukturiert, um klare Schnittstellen zwischen der geräteunabhängigen Android-Plattform und geräte- und herstellerspezifischem Code zu definieren. Android hat bereits viele solcher Schnittstellen in Form von HAL-Schnittstellen definiert, die in hardware/libhardware als C-Header hardware/libhardware . HIDL ersetzte diese HAL-Schnittstellen durch stabile, versionierte Schnittstellen, die in Java (unten beschrieben) oder als clientseitige und serverseitige HIDL-Schnittstellen in C ++ verwendet werden können .

HIDL-Schnittstellen sollen hauptsächlich aus nativem Code verwendet werden. Daher konzentriert sich HIDL auf die automatische Generierung von effizientem Code in C ++. HIDL-Schnittstellen müssen jedoch auch direkt von Java aus verwendet werden können, da einige Android-Subsysteme (z. B. Telefonie) höchstwahrscheinlich über Java-HIDL-Schnittstellen verfügen.

Auf den Seiten in diesem Abschnitt wird das Java-Frontend für HIDL-Schnittstellen beschrieben, das Erstellen, Registrieren und Verwenden von Diensten beschrieben und die Interaktion von in Java geschriebenen HALs und HAL-Clients mit dem HIDL-RPC-System erläutert.

Kunde sein

Dies ist ein Beispiel für einen Client für eine Schnittstelle IFoo im Paket android.hardware.foo@1.0 , die als default und ein zusätzlicher Dienst mit dem benutzerdefinierten second_impl .

Bibliotheken hinzufügen

Sie müssen Abhängigkeiten von der entsprechenden HIDL-Stub-Bibliothek hinzufügen, wenn Sie 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, können Sie auch eine gemeinsame 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

Zusätzliche Überlegungen zum Hinzufügen von Bibliotheken in Android 10

Wenn Sie eine System- / Anbieter-App für Android 10 und höher haben, müssen Sie diese Bibliotheken statisch einschließen. Bei älteren Apps bleibt das alte Verhalten erhalten. Alternativ können nur HIDL-Klassen aus benutzerdefinierten JARs verwendet werden, die auf dem Gerät installiert sind, wobei stabile Java-APIs verwendet werden, die mithilfe des vorhandenen uses-library für System-Apps verfügbar gemacht werden. Dies ist der empfohlene Ansatz, um Platz auf einem Gerät zu sparen. Weitere Informationen finden Sie unter Implementieren der Java SDK-Bibliothek .

Ab 10 sind auch "flache" Versionen dieser Bibliotheken verfügbar. Dazu gehört die betreffende Klasse, jedoch keine der abhängigen Klassen. Zum Beispiel enthält android.hardware.foo-V1.0-java-shallow Klassen im foo-Paket, jedoch keine Klassen in android.hidl.base-V1.0-java , das die Basisklasse aller HIDL enthält Schnittstellen. Wenn Sie eine Bibliothek erstellen, für die bereits die Basisklassen der bevorzugten Schnittstelle als Abhängigkeit verfügbar sind, 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 Manager-Bibliotheken sind im Boot-Klassenpfad ebenfalls nicht mehr verfügbar. Stattdessen wurden sie mit jarjar in einen neuen Namespace jarjar . Module im Boot-Klassenpfad, die HIDL verwenden, müssen die flachen Varianten dieser Bibliotheken verwenden und jarjar_rules: ":framework-jarjar-rules" zu ihrer Android.bp , um doppelten Code zu vermeiden und System- / Hersteller-Apps versteckte APIs verwenden zu lassen .

Ändern Ihrer Java-Quelle

Es gibt nur eine Version ( @1.0 ) dieses Dienstes, daher ruft dieser Code nur diese Version ab. Informationen zum Umgang mit mehreren verschiedenen Versionen des Dienstes finden Sie unter Schnittstellenerweiterungen .

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

Bereitstellung eines Dienstes

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

Für die IFooCallback Schnittstelle in Version 1.0 des Pakets android.hardware.foo können Sie Ihre Schnittstelle mithilfe der folgenden Schritte in Java implementieren:

  1. Definieren Sie Ihre Schnittstelle in HIDL.
  2. Öffnen Sie /tmp/android/hardware/foo/IFooCallback.java als Referenz.
  3. Erstellen Sie ein neues Modul für Ihre Java-Implementierung.
  4. Untersuchen Sie die abstrakte Klasse android.hardware.foo.V1_0.IFooCallback.Stub , schreiben Sie eine neue Klasse, um sie zu erweitern und die abstrakten Methoden zu implementieren.

Automatisch generierte Dateien anzeigen

Führen Sie Folgendes aus, um die automatisch generierten Dateien anzuzeigen:

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

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

-Lmakefile generiert die Regeln, die diesen Befehl zum Zeitpunkt der Erstellung ausführen, und ermöglicht es Ihnen, android.hardware.foo-V1.0-java und mit den entsprechenden Dateien zu verknüpfen. Ein Skript, das dies automatisch für ein Projekt voller hardware/interfaces/update-makefiles.sh , finden Sie unter hardware/interfaces/update-makefiles.sh . Die Pfade in diesem Beispiel sind relativ. Hardware / Schnittstellen können ein temporäres Verzeichnis unter Ihrem Codebaum sein, damit Sie eine HAL entwickeln können, bevor Sie sie veröffentlichen.

Ausführen eines Dienstes

Die HAL stellt die IFoo Schnittstelle bereit, die über die IFooCallback Schnittstelle asynchrone Rückrufe an das Framework IFooCallback . Die IFooCallback Schnittstelle ist nicht namentlich als IFooCallback Dienst registriert. IFoo muss IFoo eine Methode wie setFooCallback(IFooCallback x) .

android.hardware.foo Sie android.hardware.foo-V1.0-java hinzu, um IFooCallback ab Version 1.0 des Pakets android.hardware.foo-V1.0-java Android.mk . Der Code zum Ausführen des Dienstes lautet:

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 you will be receiving callbacks from.
// 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);

Schnittstellenerweiterungen

Angenommen, ein bestimmter Dienst implementiert die IFoo Schnittstelle auf allen Geräten, ist es möglich, dass der Dienst auf einem bestimmten Gerät zusätzliche Funktionen bereitstellt, die in der Schnittstellenerweiterung IBetterFoo wie folgt IBetterFoo sind:

interface IFoo {
   ...
};

interface IBetterFoo extends IFoo {
   ...
};

Das Aufrufen von Code, der die erweiterte Schnittstelle kennt, kann die Java-Methode castFrom() verwenden, um die Basisschnittstelle sicher in die erweiterte Schnittstelle castFrom() :

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