En Android 8.0, el sistema operativo Android se rediseñó para definir interfaces claras entre la plataforma Android independiente del dispositivo y el código específico del dispositivo y del proveedor. Android ya definido muchos tales interfaces en forma de interfaces de HAL, definidos como cabeceras de C en hardware/libhardware
. HIDL sustituye estas interfaces HAL con estables, interfaces versionados, que puede ser ya sea en Java (descrito a continuación) o ser interfaces de HIDL cliente-y del lado 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 interfaces HIDL, detallan cómo crear, registrar y utilizar 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á registrada como nombre de servicio default
y un servicio adicional con el nombre del servicio de encargo 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 un sistema o una aplicación de proveedor orientada a Android 10 o superior, puede incluir estáticamente estas bibliotecas. También puede utilizar (sólo) HIDL clases de los frascos personalizados instalados en el dispositivo con estables Java API facilitará a través del existentes uses-library
mecanismo para aplicaciones del sistema. El último enfoque ahorra espacio en el dispositivo. Para más detalles, véase Ejecución de Java SDK Biblioteca . Para las 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 del paquete foo, pero no incluye clases en android.hidl.base-V1.0-java
, que contiene la clase base de todos 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 tampoco 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 delegado primero de Android). En cambio, han sido trasladados a un nuevo espacio de nombres con jarjar
, y las aplicaciones que utilizan estas aplicaciones (necesariamente priv) deben tener sus propias copias separadas. Módulos en la ruta de clases de arranque usando HIDL debe utilizar la poca profundidad de las variantes de estas bibliotecas Java y añadir jarjar_rules: ":framework-jarjar-rules"
a su Android.bp
utilizar la versión de estas bibliotecas que existen en la ruta de clase de arranque.
Modificar su fuente de Java
Sólo hay una versión ( @1.0
) de este servicio, por lo que este código recupera esta versión la única. Ver extensiones de interfaz de cómo manejar múltiples 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 el IFooCallback
interfaz en la versión 1.0 de la android.hardware.foo
paquete, se puede implementar la interfaz en Java usando los siguientes pasos:
- Defina su interfaz en HIDL.
- Abrir
/tmp/android/hardware/foo/IFooCallback.java
como referencia. - Cree un nuevo módulo para su implementación de Java.
- Examinar la clase abstracta
android.hardware.foo.V1_0.IFooCallback.Stub
, a continuación, escribir una nueva clase de extenderla y poner en práctica 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 talones (tanto de proxy y los stubs se ajustan a la interfaz).
-Lmakefile
genera las reglas que ejecuta este comando en tiempo de compilación y le permiten incluir android.hardware.foo-V1.0-java
y el enlace con los archivos apropiados. Un script que hace esto automáticamente para un proyecto completo 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
El HAL proporciona la IFoo
interfaz, que debe realizar devoluciones de llamada asincrónicas con el marco sobre el IFooCallback
interfaz. El IFooCallback
interfaz no se ha registrado por su nombre como un servicio detectable; en cambio, IFoo
debe contener un método tal como setFooCallback(IFooCallback x)
.
Para configurar IFooCallback
de la versión 1.0 del android.hardware.foo
paquete, añadir 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 un determinado implementos de servicio la IFoo
interfaz en todos los dispositivos, es posible que en un dispositivo particular el servicio podría proporcionar capacidades adicionales implementadas en la ampliación de la interfaz IBetterFoo
, como sigue:
interface IFoo { ... }; interface IBetterFoo extends IFoo { ... };
Código de llamada al tanto de la interfaz extendida puede utilizar el castFrom()
método Java para emitir de forma segura el 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. }