Java de HIDL

En Android 8.0, el SO Android se rediseñó para definir interfaces claras. entre la plataforma de Android independiente del dispositivo y ofertas específicas de dispositivos y proveedores código. Android ya definió muchas de esas interfaces en forma de HAL. definidas como encabezados de C en hardware/libhardware. HIDL reemplazaron estas interfaces de HAL por interfaces estables con control de versiones, que pueden estar en Java (como se describe a continuación) o ser HIDL del cliente y del servidor interfaces en C++.

Las interfaces HIDL están diseñadas para usarse principalmente a partir de código nativo y como HIDL de resultado se enfoca en la generación automática de código eficiente en C++. Sin embargo, Las interfaces HIDL también deben estar disponibles para usarse directamente desde Java, ya que algunos dispositivos subsistemas (como Telefonía) tienen interfaces HIDL de Java.

En las páginas de esta sección, se describe el frontend de Java para las interfaces HIDL, se detalla cómo crear, registrar y usar servicios, y se explica cómo las HAL y las HAL los clientes escritos en Java interactúan con el sistema de RPC HIDL.

Ejemplo de cliente

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

Cómo agregar bibliotecas

Debes agregar dependencias en la biblioteca de stub HIDL correspondiente si quieres usarlo. Por lo general, 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 sabes que ya estás extrayendo dependencias en estas bibliotecas, también pueden usar la vinculación compartida:

// 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 tienes una app del sistema o de un proveedor orientada a Android 10 o versiones posteriores, haz lo siguiente: puedes incluirlas de forma estática. También puedes usar (solo) clases HIDL a partir de archivos JAR personalizados instalados en el dispositivo con APIs de Java estables disponibles con el mecanismo uses-library existente para apps del sistema El este último enfoque ahorra espacio en el dispositivo. Para obtener más detalles, consulta Cómo implementar la biblioteca del SDK de Java. Para en las apps más antiguas, se conserva el comportamiento anterior.

A partir de Android 10, la versión "superficial" de estas bibliotecas también están disponibles. Incluyen la clase en cuestión, pero no incluyen de las clases dependientes. Por ejemplo: android.hardware.foo-V1.0-java-shallow incluye clases en el archivo foo. paquete, pero no incluye clases en android.hidl.base-V1.0-java, que contiene la clase base de todas Interfaces de HIDL Si estás creando una biblioteca que ya tiene la biblioteca disponibles como dependencia, puedes 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 administrador y base de HIDL tampoco están disponibles en el arranque de clase para las apps (antes, a veces se usaban como API oculta, debido a cargador de clases primero delegado de Android). sino que se trasladaron a un nuevo espacio de nombres con jarjar y las apps que las usan (necesariamente, priv apps) deben tener sus propias copias independientes. módulos en la ruta de clase de inicio con HIDL debe usar las variantes superficiales de estas bibliotecas Java y agregar jarjar_rules: ":framework-jarjar-rules" a su Android.bp para usar la versión existente de estas bibliotecas en la ruta de clase de inicio.

Modifica tu código fuente de Java

Solo hay una versión (@1.0) de este servicio, por lo que este código recupera solo esa versión. Consulta extensiones de interfaz sobre 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(…);

Proporcionar un servicio

Es posible que el código del framework en Java deba entregar interfaces para recibir de las HALs.

En el caso de la interfaz IFooCallback de la versión 1.0 de la android.hardware.foo, puedes implementar la interfaz en Java con los siguientes pasos:

  1. Define tu interfaz en HIDL.
  2. Abrir /tmp/android/hardware/foo/IFooCallback.java como referencia.
  3. Crea un módulo nuevo para tu implementación de Java.
  4. Examina la clase abstracta android.hardware.foo.V1_0.IFooCallback.Stub y, luego, escribe una clase nueva para extenderlo e implementar los métodos abstractos.

Cómo ver archivos generados automáticamente

Para ver los archivos generados automáticamente, ejecuta lo siguiente:

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, genera la archivo /tmp/android/hardware/foo/1.0/IFooCallback.java, que encapsula la interfaz de Java, el código del proxy y los stubs (proxy y los stubs cumplen con la interfaz).

-Lmakefile genera las reglas que ejecutan este comando en la compilación. tiempo y te permitirá incluir android.hardware.foo-V1.0-java y vincúlalo con el los archivos correspondientes. Una secuencia de comandos que hace esto automáticamente para un proyecto lleno estas interfaces en hardware/interfaces/update-makefiles.sh. En este ejemplo, las rutas de acceso son relativas; las interfaces o el hardware pueden ser bajo tu árbol de código para poder desarrollar una HAL antes de publicarlo.

Ejecuta un servicio

La HAL proporciona la interfaz IFoo, que debe hacer que la arquitectura devoluciones de llamadas al framework a través de la interfaz IFooCallback. El La interfaz IFooCallback no está registrada por nombre como detectable servicio; en su lugar, IFoo debe contener un método como setFooCallback(IFooCallback x)

Para configurar IFooCallback desde la versión 1.0 de la Paquete android.hardware.foo, agregar 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 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);

Extensiones de interfaz

Si suponemos que un servicio determinado implementa la interfaz IFoo en todos es posible que, en un dispositivo en particular, el servicio proporcione capacidades adicionales implementadas en la extensión de la interfaz IBetterFoo de la siguiente manera:

interface IFoo {
   ...
};

interface IBetterFoo extends IFoo {
   ...
};

Llamar a un reconocimiento de código de la interfaz extendida puede usar el castFrom() para convertir de manera segura la interfaz base al 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.
}