Google is committed to advancing racial equity for Black communities. See how.
Se usó la API de Cloud Translation para traducir esta página.
Switch to English

HIDL Java

Android 8.0 rediseñó el sistema operativo Android para definir interfaces claras entre la plataforma Android independiente del dispositivo y el código específico del dispositivo y del proveedor. Android ya definió muchas de estas interfaces en forma de interfaces HAL, definidas como encabezados C en hardware/libhardware . HIDL reemplazó estas interfaces HAL con interfaces versionadas estables, que pueden estar en Java (descritas a continuación) o como interfaces HIDL del lado del cliente y del servidor en C ++ .

Las interfaces HIDL están diseñadas para usarse principalmente a partir de código nativo y, como resultado, HIDL se centra en la generación automática de código eficiente en C ++. Sin embargo, las interfaces HIDL también deben poder usarse directamente desde Java, ya que algunos subsistemas de Android (como telefonía) probablemente tendrán interfaces Java HIDL.

Las páginas de esta sección describen la interfaz de Java para interfaces HIDL, detallan cómo crear, registrar y usar servicios, y explican cómo interactúan los clientes HAL y HAL escritos en Java con el sistema HIDL RPC.

Ser cliente

Este es un ejemplo de un cliente para una interfaz IFoo en el paquete android.hardware.foo@1.0 que está registrado como nombre de servicio default y un servicio adicional con el nombre de servicio personalizado second_impl .

Agregar bibliotecas

Debe agregar dependencias en la biblioteca de códigos auxiliares HIDL correspondiente si desea usarla. Por lo general, esta es una biblioteca estática:

// 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 sabe que ya está incorporando dependencias en estas bibliotecas, también puede usar el enlace compartido:

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

Consideraciones adicionales para agregar bibliotecas en Android 10

Si tiene una aplicación de sistema / proveedor destinada a Android 10 y superior, debe incluir estáticamente estas bibliotecas. Para las aplicaciones más antiguas, se conserva el comportamiento anterior. Alternativamente, es posible usar solo clases HIDL de JAR personalizados instalados en el dispositivo con API de Java estables disponibles mediante el mecanismo de uses-library existente para aplicaciones del sistema. Para ahorrar espacio en un dispositivo, este es el enfoque recomendado. Para obtener más detalles, consulte Implementación de la biblioteca SDK de Java .

A partir de la 10, también están disponibles versiones "superficiales" de estas bibliotecas. Estos incluyen la clase en cuestión, pero no incluyen ninguna de las clases dependientes. Por ejemplo, android.hardware.foo-V1.0-java-shallow incluye clases en el paquete foo, pero no incluye clases en android.hidl.base-V1.0-java , que contiene la clase base de todos los HIDL interfaces. Si está creando una biblioteca que ya tiene las clases base de la interfaz preferida disponibles como dependencia, puede usar lo siguiente:

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

Las bibliotecas de administración y base de HIDL tampoco están disponibles en la ruta de clases de arranque. En cambio, se han movido a un nuevo espacio de nombres con jarjar . Los módulos en la ruta de clases de arranque que usan HIDL deben usar las variantes superficiales de esas bibliotecas, así como agregar jarjar_rules: ":framework-jarjar-rules" a su Android.bp para evitar el código duplicado y que las aplicaciones del sistema / proveedor usen API ocultas .

Modificar su fuente de Java

Solo hay una versión ( @1.0 ) de este servicio, por lo que este código solo recupera esa versión. Consulte las extensiones de interfaz para saber cómo manejar varias versiones diferentes del servicio.

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

Brindar un servicio

Es posible que el código de marco en Java deba servir interfaces para recibir devoluciones de llamada asincrónicas de HAL.

Para la interfaz IFooCallback en la versión 1.0 del paquete android.hardware.foo , puede implementar su interfaz en Java siguiendo estos pasos:

  1. Defina su interfaz en HIDL.
  2. Abra /tmp/android/hardware/foo/IFooCallback.java como referencia.
  3. Cree un nuevo módulo para su implementación de Java.
  4. Examine la clase abstracta android.hardware.foo.V1_0.IFooCallback.Stub , luego escriba una nueva clase para extenderla e implementar los métodos abstractos.

Ver archivos generados automáticamente

Para ver los archivos generados automáticamente, ejecute:

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

Estos comandos generan el directorio /tmp/android/hardware/foo/1.0 . Para el archivo hardware/interfaces/foo/1.0/IFooCallback.hal , esto genera el archivo /tmp/android/hardware/foo/1.0/IFooCallback.java , que encapsula la interfaz Java, el código proxy y los stubs (ambos proxy y los stubs se ajustan a la interfaz).

-Lmakefile genera las reglas que ejecutan este comando en el momento de la compilación y le permiten incluir android.hardware.foo-V1.0-java y vincularlo a los archivos apropiados. Un script que hace esto automáticamente para un proyecto lleno de interfaces se puede encontrar en hardware/interfaces/update-makefiles.sh . Las rutas de este ejemplo son relativas; hardware / interfaces puede ser un directorio temporal debajo de su árbol de código para permitirle desarrollar un HAL antes de publicarlo.

Ejecutando un servicio

HAL proporciona la interfaz IFoo , que debe realizar devoluciones de llamada asíncronas al marco a través de la interfaz IFooCallback . La interfaz IFooCallback no está registrada por su nombre como un servicio IFooCallback ; en su lugar, IFoo debe contener un método como setFooCallback(IFooCallback x) .

Para configurar IFooCallback desde la versión 1.0 del paquete android.hardware.foo , agregue android.hardware.foo-V1.0-java a Android.mk . El código para ejecutar el servicio es:

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

Extensiones de interfaz

Suponiendo que un servicio determinado implementa la interfaz IFoo en todos los dispositivos, es posible que en un dispositivo en particular el servicio proporcione capacidades adicionales implementadas en la extensión de interfaz IBetterFoo , como se indica a continuación:

interface IFoo {
   ...
};

interface IBetterFoo extends IFoo {
   ...
};

El código de llamada consciente de la interfaz extendida puede usar el método de Java castFrom() de forma segura la interfaz base a la interfaz extendida:

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