Android 8 rediseña el SO Android para definir interfaces claras entre
plataforma de Android independiente del dispositivo y código específico para el dispositivo y el proveedor.
Android ya define muchas de esas interfaces en la forma de interfaces HAL,
definidos como encabezados de C en hardware/libhardware
. El HIDL los reemplaza
Interfaces de HAL con interfaces estables con control de versiones, que pueden ser de cliente
interfaces HIDL del servidor en C++ (como se describen a continuación)
Java.
En las páginas de esta sección, se describen las implementaciones de C++ de las interfaces HIDL.
incluidos los detalles sobre los archivos generados automáticamente a partir del .hal
de HIDL
archivos por el compilador hidl-gen
, la forma en que se empaquetan estos archivos y
cómo integrar esos archivos con el código de C++ que los usa.
Implementaciones de cliente y servidor
Las interfaces HIDL tienen implementaciones de cliente y servidor:
- Un cliente de una interfaz HIDL es el código que usa el a través de una llamada a los métodos en ella.
- Un servidor es una implementación de una interfaz HIDL que recibe llamadas de los clientes y devuelve resultados (si es necesario).
En la transición de HAL de libhardware
a HAL de HIDL, la HAL
se convierte en el servidor, y el proceso que llama a la HAL pasa a ser
al cliente. Las implementaciones predeterminadas pueden entregar contenido de transferencia y enlazado
y pueden cambiar con el tiempo:
Figura 1: Progreso del desarrollo de HAL heredadas.
Crea el cliente HAL
Para comenzar, incluye las bibliotecas HAL en el archivo makefile:
- Marca:
LOCAL_SHARED_LIBRARIES += android.hardware.nfc@1.0
- Soong:
shared_libs: [ …, android.hardware.nfc@1.0 ]
Luego, incluye los archivos de encabezado de la HAL:
#include <android/hardware/nfc/1.0/IFoo.h> … // in code: sp<IFoo> client = IFoo::getService(); client->doThing();
Cómo crear el servidor de HAL
Para crear la implementación de HAL, debes tener los archivos .hal
que representan tu HAL y ya generaron archivos makefile para tu HAL usando
-Lmakefile
o -Landroidbp
en hidl-gen
(./hardware/interfaces/update-makefiles.sh
hace esto para usuarios
HAL y es una buena referencia). Cuando se transfieren HALs desde
libhardware
, puedes realizar muchos de estos trabajos de manera sencilla con c2hal.
Si quieres crear los archivos necesarios para implementar la HAL, haz lo siguiente:
PACKAGE=android.hardware.nfc@1.0 LOC=hardware/interfaces/nfc/1.0/default/ m -j hidl-gen hidl-gen -o $LOC -Lc++-impl -randroid.hardware:hardware/interfaces \ -randroid.hidl:system/libhidl/transport $PACKAGE hidl-gen -o $LOC -Landroidbp-impl -randroid.hardware:hardware/interfaces \ -randroid.hidl:system/libhidl/transport $PACKAGE
Para que la HAL funcione en el modo de transferencia, debes tener
la función HIDL_FETCH_IModuleName
que reside en
/(system|vendor|...)/lib(64)?/hw/android.hardware.package@3.0-impl(OPTIONAL_IDENTIFIER).so
donde OPTIONAL_IDENTIFIER es una cadena que identifica la transferencia.
para implementarlos. Los requisitos del modo de transferencia se cumplen automáticamente
anteriores, que también crean el android.hardware.nfc@1.0-impl
pero se puede usar cualquier extensión. Por ejemplo:
android.hardware.nfc@1.0-impl-foo
usa -foo
para
diferenciarse del resto.
Si una HAL es una versión secundaria o una extensión de otra
HAL, se debe usar la HAL de base para asignar un nombre a este objeto binario. Por ejemplo:
Las implementaciones de android.hardware.graphics.mapper@2.1
deben
todavía estar en un objeto binario llamado
android.hardware.graphics.mapper@2.0-impl(OPTIONAL_IDENTIFIER)
Por lo general, la OPTIONAL_IDENTIFIER de aquí incluiría la HAL real
versión. Al nombrar el objeto binario de esta manera, los clientes 2.0 pueden recuperarlo directamente,
y los clientes 2.1 pueden mejorar la implementación.
A continuación, completa los stubs con funcionalidad y configura un daemon. Ejemplo Código daemon (compatible con transferencia):
#include <hidl/LegacySupport.h> int main(int /* argc */, char* /* argv */ []) { return defaultPassthroughServiceImplementation<INfc>("nfc"); }
defaultPassthroughServiceImplementation
llamada
dlopen()
para la biblioteca -impl
proporcionada y la proporciona como
un servicio vinculado. Ejemplo de código de daemon (para un servicio vinculado puro):
int main(int /* argc */, char* /* argv */ []) { // This function must be called before you join to ensure the proper // number of threads are created. The threadpool never exceeds // size one because of this call. ::android::hardware::configureRpcThreadpool(1 /*threads*/, true /*willJoin*/); sp<INfc> nfc = new Nfc(); const status_t status = nfc->registerAsService(); if (status != ::android::OK) { return 1; // or handle error } // Adds this thread to the threadpool, resulting in one total // thread in the threadpool. We could also do other things, but // would have to specify 'false' to willJoin in configureRpcThreadpool. ::android::hardware::joinRpcThreadpool(); return 1; // joinRpcThreadpool should never return }
Este daemon suele vivir en $PACKAGE + "-service-suffix"
(durante
por ejemplo, android.hardware.nfc@1.0-service
), pero podría estar en cualquier lugar.
La sepolicy para una configuración
de HAL es el atributo hal_<module>
(por ejemplo,
hal_nfc)
Este atributo debe aplicarse al daemon que ejecuta un
HAL específica (si el mismo proceso entrega varias HAL, varios atributos
se les puede aplicar).