Java HIDL

In Android 8.0, il sistema operativo Android è stato riprogettato per definire interfacce chiare tra la piattaforma Android indipendente dal dispositivo e quella specifica del fornitore e del dispositivo le API nel tuo codice. Android ha già definito molte interfacce di questo tipo sotto forma di HAL interfacce definite come intestazioni C in hardware/libhardware. HIDL ha sostituito queste interfacce HAL con interfacce stabili con controllo delle versioni, in Java (descritto di seguito) o sul lato client e lato server HIDL interfacce in C++.

Le interfacce HIDL sono progettate per essere utilizzate principalmente da codice nativo e come risultato HIDL è incentrato sulla generazione automatica di codice efficiente in C++. Tuttavia, Le interfacce HIDL devono inoltre essere disponibili per l'utilizzo direttamente da Java, poiché alcuni modelli sottosistemi (come la telefonia) hanno interfacce Java HIDL.

Le pagine di questa sezione descrivono il frontend Java per le interfacce HIDL, descrivere in dettaglio come creare, registrare e utilizzare i servizi e spiegare come gli HAL e HAL I client scritti in Java interagiscono con il sistema RPC HIDL.

Esempio di client

Questo è un esempio di client per un'interfaccia IFoo nel pacchetto android.hardware.foo@1.0 registrato come nome di servizio default e un servizio aggiuntivo con il nome del servizio personalizzato second_impl.

Aggiungi librerie

È necessario aggiungere dipendenze nella libreria stub HIDL corrispondente se vuoi usarlo. Di solito, si tratta di una libreria statica:

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

Se sai già che stai estraendo le dipendenze da queste librerie, puoi anche usare il collegamento condiviso:

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

Considerazioni aggiuntive per l'aggiunta di librerie in Android 10

Se hai un'app di sistema o di un fornitore che ha come target Android 10 o versioni successive: puoi includere le librerie in modo statico. Puoi anche utilizzare (solo) classi HIDL da JAR personalizzati installati sul dispositivo con API Java stabili rese disponibili utilizzando il meccanismo uses-library esistente per le app di sistema. La quest'ultimo consente di risparmiare spazio sul dispositivo. Per maggiori dettagli, consulta Implementazione della libreria SDK Java. Per per le app meno recenti, viene mantenuto il comportamento precedente.

A partire da Android 10, "shallow" di queste librerie . Sono inclusi il corso in questione, ma non nessuno delle classi dipendenti. Ad esempio, android.hardware.foo-V1.0-java-shallow include corsi nel file foo ma non include classi in android.hidl.base-V1.0-java, che contiene la classe base di tutti Interfacce HIDL. Se stai creando una libreria che contiene già i preferiti disponibili come dipendenza, puoi usare quanto segue:

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

Inoltre, le librerie di base e gestore HIDL non sono più disponibili all'avvio classpath per le app (in precedenza, a volte venivano utilizzate come API nascoste) classloader, delegato di Android). Sono stati invece spostati in un nuovo con jarjar e le app che ne usano (necessariamente priv app) devono avere copie separate. per i moduli sul classpath di avvio L'HIDL deve usare le varianti superficiali di queste librerie Java e aggiungere jarjar_rules: ":framework-jarjar-rules" al suo Android.bp per utilizzare la versione di queste librerie esistente nel classpath di avvio.

Modifica il tuo codice sorgente Java

Esiste una sola versione (@1.0) di questo servizio, quindi questo codice recupera solo quella versione. Consulta estensioni di interfaccia su come gestire più versioni diverse del servizio.

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

Fornire un servizio

Il codice framework in Java potrebbe dover gestire le interfacce per ricevere dagli HAL.

Per l'interfaccia IFooCallback nella versione 1.0 di android.hardware.foo, puoi implementare l'interfaccia utilizzando la seguente procedura:

  1. Definisci l'interfaccia in HIDL.
  2. Apri /tmp/android/hardware/foo/IFooCallback.java come riferimento.
  3. Crea un nuovo modulo per l'implementazione Java.
  4. Esaminare la classe astratta android.hardware.foo.V1_0.IFooCallback.Stub, quindi scrivi un nuovo corso per estenderlo e implementare i metodi astratti.

Visualizza i file generati automaticamente

Per visualizzare i file generati automaticamente, esegui:

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

Questi comandi generano la directory /tmp/android/hardware/foo/1.0. Per il file hardware/interfaces/foo/1.0/IFooCallback.hal, questo genera file /tmp/android/hardware/foo/1.0/IFooCallback.java, che incapsula l’interfaccia Java, il codice proxy e gli stub (sia stub sono conformi all'interfaccia).

-Lmakefile genera le regole che eseguono questo comando al momento della build e ti consentono di includere android.hardware.foo-V1.0-java e collega alla i file appropriati. Uno script che esegue questa operazione automaticamente per un progetto pieno di disponibili all'indirizzo hardware/interfaces/update-makefiles.sh. In questo esempio, i percorsi sono relativi; hardware/interfacce può essere una soluzione sotto la struttura del codice per consentirti di sviluppare un HAL prima la pubblicazione.

Esegui un servizio

L'HAL fornisce l'interfaccia IFoo, che deve rendere asincrono al framework tramite l'interfaccia IFooCallback. La L'interfaccia di IFooCallback non è registrata per nome come rilevabile servizio; invece, IFoo deve contenere un metodo come setFooCallback(IFooCallback x).

Per configurare IFooCallback dalla versione 1.0 di Pacchetto android.hardware.foo, aggiungi android.hardware.foo-V1.0-java a Android.mk. Il codice per eseguire il servizio è:

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

Estensioni interfaccia

Presumendo che un determinato servizio implementi l'interfaccia IFoo in tutte su un dispositivo specifico, è possibile che il servizio funzionalità aggiuntive implementate nell'estensione di interfaccia IBetterFoo, come segue:

interface IFoo {
   ...
};

interface IBetterFoo extends IFoo {
   ...
};

Il codice di chiamata che conosce l'interfaccia estesa può utilizzare il castFrom() metodo Java per trasmettere in sicurezza l'interfaccia di base all'account dell'interfaccia estesa:

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