HAL module (libhardware)架构

硬件抽象层 (HAL)

HAL 可定义一个标准接口以供硬件供应商实现,这可让 Android 忽略较低级别的驱动程序实现。借助 HAL,您可以顺利实现相关功能,而不会影响或更改更高级别的系统。HAL 实现会被封装成模块,并由 Android 系统适时地加载。

HAL module (libhardware)架构

为了保证 HAL 具有可预测的结构,每个特定于硬件的 HAL 接口都要具有 hardware/libhardware/include/hardware/hardware.h 中定义的属性。这类接口可让 Android 系统以一致的方式加载 HAL 模块的正确版本。HAL 接口包含两个组件:模块和设备

HAL 模块

模块表示被封装且存储为共享库 (.so file) 的 HAL 实现。hardware/libhardware/include/hardware/hardware.h标头文件会定义一个表示模块的结构体 (hw_module_t),其中包含模块的版本、名称和作者等元数据。Android 会根据这些元数据来找到并正确加载 HAL 模块。

另外,hw_module_t 结构体还包含指向另一个结构体 hw_module_methods_t 的指针,后面这个结构体会包含一个指向相应模块的 open 函数的指针。此 open 函数用于与相关硬件(此 HAL 是其抽象形式)建立通信。每个特定于硬件的 HAL 通常都会使用附加信息为该特定硬件扩展通用的 hw_module_t 结构体。例如,在相机 HAL 中,camera_module_t 结构体会包含一个 hw_module_t 结构体以及其他特定于相机的函数指针:

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;

实现 HAL 并创建模块结构体时,您必须将其命名为 HAL_MODULE_INFO_SYM。以下是 Nexus 9 音频 HAL 的示例:

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,
    },
};

 

HAL 设备

设备是产品硬件的抽象表示。例如,一个音频模块可能包含主音频设备、USB 音频设备或蓝牙 A2DP 音频设备。

设备由 hw_device_t 结构体表示。与模块类似,每类设备都定义了一个通用 hw_device_t 的详细版本,其中包含指向硬件特定功能的函数指针。例如,audio_hw_device_t 结构体类型会包含指向音频设备操作的函数指针:

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;

 

 

Framework&applications

external libraries &runtime 

HAL(libhardware)

(sensor stub-stub-stub)

linux device driver

 

HAL module 架构主要分为如下3个结构体

1.struct hw_module_t;
2.struct hw_module_methods_t;
3.struct hw_device_t;

三者继承关系如下

private_module_t(-base:gralloc_module_t)

gralloc_module_t(-common:hw_module_t)

hw_module_t(-methods:hw_methods_t)

hw_module_methods_t(-open:gralloc_device_open)

3个抽象文件在hardware.c中描述。HAL模块源代码保存在hardware目录中。

(1)结构体struct hw_module_t在文件\hardware\libhardware\include\hardware/hardware.h中定义,具体代码如下:

typedef struct hw_module_t {
    /** tag must be initialized to HARDWARE_MODULE_TAG */
    uint32_t tag;

    uint16_t module_api_version;
#define version_major module_api_version  

  uint16_t hal_api_version;
#define version_minor hal_api_version

    /** Identifier of module */
    const char *id;

    /** Name of this module */
    const char *name;

    /** Author/owner/implementor of the module */
    const char *author;

    /** Modules methods */
    struct hw_module_methods_t* methods;

    /** module's dso */
    void* dso;

#ifdef __LP64__
    uint64_t reserved[32-7];
#else
    /** padding to 128 bytes, reserved for future use */
    uint32_t reserved[32-7];
#endif

} hw_module_t;
 

硬件抽象层的中每个模块必须自己定义一个硬件抽象层模块结构体。

(2)结构体struct hw_module_methods_t在文件\hardware\libhardware\include\hardware/hardware.h中定义,具体代码如下

typedef struct hw_module_methods_t {
    /** Open a specific device */
    int (*open)(const struct hw_module_t* module, const char* id,
            struct hw_device_t** device);

} hw_module_methods_t;
只有一个成员变量,它是一个函数指针,用来打开硬件抽象层模块中的硬件设备。module 表示要打开的硬件设备所在的模块,ID表示设备的ID ,device 是一个输出参数,描述一个已经打开的设备。由于一个硬件抽象层模块可能含有多个硬件设备,因为在调用结构体struct hw_module_methods_t的成员变量open,打开一个硬件设备时需要指定的ID

(3)结构体struct hw_device_t 在文件\hardware\libhardware\include\hardware/hardware.h中定义,具体代码如下

typedef struct hw_device_t {
    /** tag must be initialized to HARDWARE_DEVICE_TAG */
    uint32_t tag;

 uint32_t version;

    /** reference to the module this device belongs to */
    struct hw_module_t* module;

    /** padding reserved for future use */
#ifdef __LP64__
    uint64_t reserved[12];
#else
    uint32_t reserved[12];
#endif

    /** Close this device */
    int (*close)(struct hw_device_t* device);

} hw_device_t;