En Android 8.0, se 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 (descrito a continuación) o ser 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 estar disponibles para su uso directamente desde Java, ya que algunos subsistemas de Android (como Telefonía) tienen interfaces Java HIDL.
Las páginas de esta sección describen la interfaz de Java para las interfaces HIDL, detallan cómo crear, registrar y usar servicios, y explican cómo las HAL y los clientes HAL escritos en Java interactúan con el sistema HIDL RPC.
ser un 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ódigo auxiliar 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á generando 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 un sistema o una aplicación de proveedor que apunta a Android 10 o superior, puede incluir estas bibliotecas de forma estática. También puede usar (solo) clases HIDL de archivos JAR personalizados instalados en el dispositivo con API de Java estables disponibles mediante el mecanismo de uses-library
existente para aplicaciones del sistema. El último enfoque ahorra espacio en el dispositivo. Para obtener más detalles, consulte Implementación de la biblioteca SDK de Java . Para aplicaciones más antiguas, se conserva el comportamiento anterior.
A partir de Android 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 base y de administrador de HIDL ya no están disponibles en la ruta de clases de arranque para las aplicaciones (anteriormente, a veces se usaban como API oculta, debido al cargador de clases de delegado primero de Android). En su lugar, se han movido a un nuevo espacio de nombres con jarjar
y las aplicaciones que los usan (necesariamente aplicaciones privadas) deben tener sus propias copias separadas. Los módulos en el classpath de arranque que usan HIDL deben usar las variantes superficiales de estas bibliotecas de Java y agregar jarjar_rules: ":framework-jarjar-rules"
a su Android.bp
para usar la versión de estas bibliotecas que existe en el classpath de arranque.
Modificando su fuente Java
Solo hay una versión ( @1.0
) de este servicio, por lo que este código recupera solo 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(…);
Proporcionar un servicio
Es posible que el código del marco en Java necesite servir interfaces para recibir devoluciones de llamada asincrónicas de las HAL.
Para la interfaz IFooCallback
en la versión 1.0 del paquete android.hardware.foo
, puede implementar su interfaz en Java siguiendo los siguientes pasos:
- Defina su interfaz en HIDL.
- Abra
/tmp/android/hardware/foo/IFooCallback.java
como referencia. - Cree un nuevo módulo para su implementación de Java.
- Examine la clase abstracta
android.hardware.foo.V1_0.IFooCallback.Stub
, luego escriba una nueva clase para ampliarla e implementar los métodos abstractos.
Visualización de 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 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 con los archivos correspondientes. Puede encontrar un script que hace esto automáticamente para un proyecto lleno de interfaces en hardware/interfaces/update-makefiles.sh
. Las rutas en este ejemplo son relativas; hardware/interfaces puede ser un directorio temporal bajo 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 asincrónicas al marco a través de la interfaz IFooCallback
. La interfaz IFooCallback
no está registrada por nombre como un servicio detectable; 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 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
Suponiendo que un servicio dado implemente 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 la interfaz IBetterFoo
, de la siguiente manera:
interface IFoo { ... }; interface IBetterFoo extends IFoo { ... };
Llamar al código consciente de la interfaz extendida puede usar el método Java castFrom()
para convertir de manera 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. }