HAL heredadas

Un HAL define una interfaz estándar para que los proveedores de hardware la implementen, lo que permite que Android sea independiente de las implementaciones de controladores de nivel inferior. El uso de un HAL te permite implementar funcionalidades sin afectar ni modificar el sistema de nivel superior. En esta página, se describe la arquitectura anterior, que ya no se admite a partir de Android 8.0. Para Android 8.0 y versiones posteriores, consulta la descripción general de HAL.

Componentes de HAL

Figura 1: Componentes de HAL

Debes implementar el HAL (y el controlador) correspondiente para el hardware específico que proporciona tu producto. Por lo general, las implementaciones de HAL se compilan en módulos de bibliotecas compartidas (archivos .so), pero como Android no exige una interacción estándar entre una implementación de HAL y los controladores de dispositivos, puedes hacer lo que sea mejor para tu situación. Sin embargo, para permitir que el sistema Android interactúe correctamente con tu hardware, debes cumplir con el contrato definido en cada interfaz HAL específica del hardware.

Para garantizar que los HAL tengan una estructura predecible, cada interfaz de HAL específica del hardware tiene propiedades definidas en hardware/libhardware/include/hardware/hardware.h. Esta interfaz permite que el sistema Android cargue las versiones correctas de tus módulos HAL de forma coherente. Una interfaz de HAL consta de dos componentes: módulos y dispositivos.

Módulos de HAL

Un módulo representa tu implementación de HAL empaquetada, que se almacena como una biblioteca compartida (.so file). El archivo de encabezado hardware/libhardware/include/hardware/hardware.h define una estructura (hw_module_t) que representa un módulo y contiene metadatos, como la versión, el nombre y el autor del módulo. Android usa estos metadatos para encontrar y cargar el módulo HAL correctamente.

Además, la estructura hw_module_t contiene un puntero a otra estructura, hw_module_methods_t, que contiene un puntero a una función abierta para el módulo. Esta función abierta se usa para iniciar la comunicación con el hardware para el que el HAL funciona como una abstracción. Por lo general, cada HAL específico del hardware extiende la estructura genérica hw_module_t con información adicional para ese hardware específico. Por ejemplo, en la HAL de la cámara, la estructura camera_module_t contiene una estructura hw_module_t junto con otros punteros de función específicos de la cámara:

typedef struct camera_module {
    hw_module_t common;
    int (*get_number_of_cameras)(void);
    int (*get_camera_info)(int camera_id, struct camera_info *info);
} camera_module_t;

Cuando implementes un HAL y crees la estructura del módulo, debes nombrarlo HAL_MODULE_INFO_SYM. Ejemplo del HAL de audio del Nexus 9:

struct audio_module HAL_MODULE_INFO_SYM = {
    .common = {
        .tag = HARDWARE_MODULE_TAG,
        .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
        .hal_api_version = HARDWARE_HAL_API_VERSION,
        .id = AUDIO_HARDWARE_MODULE_ID,
        .name = "NVIDIA Tegra Audio HAL",
        .author = "The Android Open Source Project",
        .methods = &hal_module_methods,
    },
};

Dispositivos HAL

Un dispositivo abstrae el hardware de tu producto. Por ejemplo, un módulo de audio puede contener un dispositivo de audio principal, un dispositivo de audio USB o un dispositivo de audio A2DP Bluetooth.

La estructura hw_device_t representa un dispositivo. Al igual que un módulo, cada tipo de dispositivo define una versión detallada del hw_device_t genérico que contiene punteros de función para funciones específicas del hardware. Por ejemplo, el tipo de struct audio_hw_device_t contiene punteros de función a operaciones de dispositivos de audio:

struct audio_hw_device {
    struct hw_device_t common;

    /**
     * used by audio flinger to enumerate what devices are supported by
     * each audio_hw_device implementation.
     *
     * Return value is a bitmask of 1 or more values of audio_devices_t
     */
    uint32_t (*get_supported_devices)(const struct audio_hw_device *dev);
  ...
};
typedef struct audio_hw_device audio_hw_device_t;

Además de estas propiedades estándar, cada interfaz de HAL específica del hardware puede definir más de sus propias funciones y requisitos. Para obtener más información, consulta la documentación de referencia de HAL, así como las instrucciones individuales de cada HAL.

Cómo compilar módulos de HAL

Las implementaciones de HAL se compilan en archivos de módulos (.so) y Android las vincula de manera dinámica cuando corresponde. Para compilar tus módulos, crea archivos Android.mk para cada una de tus implementaciones de HAL y dirige a tus archivos de origen. En general, las bibliotecas compartidas deben tener un nombre con un formato específico para que se puedan encontrar y cargar correctamente. El esquema de nombres varía ligeramente de un módulo a otro, pero sigue el patrón general de <module_type>.<device_name>.

HAL heredado

El término HAL heredado se refiere de forma general a todos los HAL anteriores a Android 8.0 (que dejaron de estar disponibles en Android 8). La mayor parte de las interfaces del sistema Android (cámara, audio, sensores, etc.) se definen en "hardware/libhardware/include/hardware" y tienen un control de versiones aproximado y una ABI estable. Algunos subsistemas (incluidos Wi-Fi, la capa de interfaz de radio y Bluetooth) tienen otras interfaces no estandarizadas en "libhardware_legacy" o intercaladas en toda la base de código. Los HAL heredados nunca proporcionaron garantías de estabilidad sólidas.