Este artículo detalla el proceso para crear un servicio HAL (Hardware Abstraction Layer) utilizando HIDL (Hardware Interface Definition Language) en Android, específicamente en el modo Binder (enlazado). Se implementará un servicio de ejemplo que ofrece operaciones aritméticas básicas.
Conceptos fundamentales
HIDL es el mecanismo de comunicación entre el Framework de Android y las capas HAL. En el modo Binder, el proceso HAL se ejecuta en un espacio de aislamiento separado del Framework, mejorando la estabilidad y seguridad del sistema.
Preparación del entorno
Se requiere una compilación del AOSP (Android Open Source Project) y la herramienta hidl-gen, la cual genera el código esqueleto a partir de las definiciones .hal.
Definición de la interfaz
Primero, se define el archivo de interfaz HIDL. En este ejemplo, la interfaz se llamará ICalculator y ofrecerá métodos para sumar, restar, multiplicar y dividir.
El archivo ICalculator.hal se ubicaría en un directorio como hardware/interfaces/calculator/1.0/. Su contenido sería:
package android.hardware.calculator@1.0;
interface ICalculator {
add(uint32_t num1, uint32_t num2) generates (uint32_t result);
subtract(uint32_t num1, uint32_t num2) generates (uint32_t result);
multiply(uint32_t num1, uint32_t num2) generates (uint32_t result);
divide(uint32_t num1, uint32_t num2) generates (uint32_t result);
};
Generación del esqueleto del código
Se ejecuta hidl-gen para generar los archivos de implementación C++ y los archivos de compilación Android.bp. Este paso crea un driectorio default con la implementación base del servicio.
Implementación del servicio HAL
Se modifica el archivo de cabecera generado (Calculator.h) y su archivo de implementación (Calculator.cpp) para proporcionar la lógica real de cada operación.
Un ejemplo de implementación para el método add podría ser:
Return<uint32_t> Calculator::add(uint32_t num1, uint32_t num2) {
uint32_t resultado = num1 + num2;
ALOGI("Operación suma: %u + %u = %u", num1, num2, resultado);
return resultado;
}
Configuración del servicio
Se crea un archivo de inicialización (.rc) para que el servicio HAL se inicie automáticamente con el sistema. Asimismo, se configura el archivo service.cpp principal que registrará el servicio.
// service.cpp
#define LOG_TAG "android.hardware.calculator@1.0-service"
#include <android/hardware/calculator/1.0/ICalculator.h>
#include <hidl/LegacySupport.h>
#include "Calculator.h"
using android::hardware::calculator::V1_0::ICalculator;
using android::hardware::calculator::V1_0::implementation::Calculator;
using android::hardware::defaultPassthroughServiceImplementation;
int main() {
return defaultPassthroughServiceImplementation<ICalculator>();
}
Compilación y despliegue
Se compila el módulo completo mediante el sistema de compilación de AOSP. Los artefactos generados son las bibliotecas compartidas (.so) y el ejecutable del servicio. Estos deben ser copiados a las rutas correspondientes en el dispositivo Android (/vendor/).
Finalmente, es necesario registrar el servicio en el manifiesto de compatibilidad (manifest.xml) del dispositivo para que sea visible para el Framework.
Prueba del servicio
Se puede crear un cliente de prueba sencillo para invocar los métodos del servicio HAL a través de la interfaz HIDL. El cliente obtiene una referencia al servicio usando ICalculator::getService() y ejecuta las operaciones.
// Ejemplo simplificado de cliente
#include <android/hardware/calculator/1.0/ICalculator.h>
using android::sp;
using android::hardware::calculator::V1_0::ICalculator;
int main() {
sp<ICalculator> calcService = ICalculator::getService();
if (calcService != nullptr) {
auto resSuma = calcService->add(10, 5);
ALOGI("Resultado de 10+5: %u", static_cast<uint32_t>(resSuma));
}
return 0;
}
Al ejecutar el cliente, se deben ver los mensajes de log correspondientes en el logcat, confirmando la comunicación exitosa entre el cliente y el servicio HAL a través del binder de HIDL.