Android HAL层

Android的硬件抽象层(HAL)是连接应用程序框架和硬件驱动的关键,它包括libhardware.so库和多个硬件模块。JNI通过调用libhardware.so来操作硬件模块,如传感器、显示等。HAL层的实现涉及JNI、通用硬件模块、硬件模块到内核驱动的接口。硬件模块以动态链接库形式存在,按特定命名规则放置在/system/lib/hw目录下。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

11年GPS 调试 QQ空间保存在文章 无意中看到 虽然有些乱 但是简明扼要 重新整理下

Android HAL层,即硬件抽象层,是Google响应厂家“希望不公开源码”的要求推出的新概念

1 源代码和目标位置
源代码: /hardware/libhardware目录,该目录的目录结构如下:
/hardware/libhardware/hardware.c编译成libhardware.so,目标位置为/system/lib目录
/hardware/libhardware/include/hardware目录下包含如下头文件:
hardware.h 通用硬件模块头文件
copybit.h copybit模块头文件
gralloc.h gralloc模块头文件
lights.h  背光模块头文件
overlay.h overlay模块头文件
qemud.h  qemud模块头文件
sensors.h 传感器模块头文件
/hardware/libhardware/modules目录下定义了很多硬件模块
这些硬件模块都编译成xxx.xxx.so,目标位置为/system/lib/hw目录

2,HAL层的实现方式
JNI->通用硬件模块->硬件模块->内核驱动接口
具体一点:JNI->libhardware.so->xxx.xxx.so->kernel
具体来说:android frameworks中JNI调用/hardware/libhardware/hardware.c中定义的hw_get_module函数来获取硬件模块,
然后调用硬件模块中的方法,硬件模块中的方法直接调用内核接口完成相关功能

3,通用硬件模块(libhardware.so)
(1)头文件为:/hardware/libhardware/include/hardware/hardware.h
头文件中主要定义了通用硬件模块结构体hw_module_t,声明了JNI调用的接口函数hw_get_module
hw_module_t定义如下:

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

    /** major version number for the module */
    uint16_t version_major;

    /** minor version number of the module */
    uint16_t version_minor;

    /** 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;

    /** padding to 128 bytes, reserved for future use */
    uint32_t reserved[32-7];

} hw_module_t;


硬件模块方法结构体hw_module_methods_t定义如下:

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;


只定义了一个open方法,其中调用的设备结构体参数hw_device_t定义如下:

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

    /** version number for hw_device_t */
    uint32_t version;

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

    /** padding reserved for future use */
    uint32_t reserved[12];

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

} hw_device_t;


hw_get_module函数声明如下:
int hw_get_module(const char *id, const struct hw_module_t **module);
参数id为模块标识,定义在/hardware/libhardware/include/hardware目录下的硬件模块头文件中,
参数module是硬件模块地址,定义了/hardware/libhardware/include/hardware/hardware.h中

(2)hardware.c中主要是定义了hw_get_module函数如下:

#define HAL_LIBRARY_PATH "/system/lib/hw"
static const char *variant_keys[] = {
    "ro.hardware",
    "ro.product.board",
    "ro.board.platform",
    "ro.arch"
};
static const int HAL_VARIANT_KEYS_COUNT =
    (sizeof(variant_keys)/sizeof(variant_keys[0]));

int hw_get_module(const char *id, const struct hw_module_t **module)
{
    int status;
    int i;
    const struct hw_module_t *hmi = NULL;
    char prop[PATH_MAX];
    char path[PATH_MAX];
    for (i=0 ; i<HAL_VARIANT_KEYS_COUNT+1 ; i++)
    {
        if (i < HAL_VARIANT_KEYS_COUNT)
        {
            if (property_get(variant_keys[i], prop, NULL) == 0)
            {
                continue;
            }
            snprintf(path, sizeof(path), "%s/%s.%s.so",
                    HAL_LIBRARY_PATH, id, prop);
        }
        else
        {
            snprintf(path, sizeof(path), "%s/%s.default.so",
                    HAL_LIBRARY_PATH, id);
        }
        if (access(path, R_OK))
        {
            continue;
        }
        /* we found a library matching this id/variant */
        break;
    }

    status = -ENOENT;
    if (i < HAL_VARIANT_KEYS_COUNT+1) {
        /* load the module, if this fails, we're doomed, and we should not try
         * to load a different variant. */
        status = load(id, path, module);
    }

    return status;
}


从源代码我们可以看出,hw_get_module完成的主要工作是根据模块id寻找硬件模块动态连接库地址,然后调用load函数去打开动态连接库并从动态链接库中获取硬件模块结构体地址。

硬件模块路径格式如下:
HAL_LIBRARY_PATH/id.prop.so
HAL_LIBRARY_PATH定义为/system/lib/hw
id是hw_get_module函数的第一个参数所传入,prop部分首先按照variant_keys数组中的名称逐一调用property_get获取对应的系统属性,
然后访问HAL_LIBRARY_PATH/id.prop.so,如果找到能访问的就结束,否则就访问HAL_LIBRARY_PATH/id.default.so


举例如下:


假定访问的是背光模块,id定义为"lights"则系统会按照如下的顺序去访问文件:
/system/lib/hw/lights.[ro.hardware属性值].so
/system/lib/hw/lights.[ro.product.board属性值].so
/system/lib/hw/lights.[ro.board.platform属性值].so
/system/lib/hw/lights.[ro.arch属性值].so
/system/lib/hw/lights.default.so
所以开发硬件模块的时候Makefile文件(Android.mk)中模块的命名LOCAL_MODULE要参考上面的内容,否则就会访问不到没作用了。

load函数的关键部分代码如下:
   

handle = dlopen(path, RTLD_NOW);  //打开动态链接库
    if (handle == NULL) {
        char const *err_str = dlerror();
        LOGE("load: module=%s\n%s", path, err_str?err_str:"unknown");
        status = -EINVAL;
        goto done;
    }

    const char *sym = HAL_MODULE_INFO_SYM_AS_STR;
    hmi = (struct hw_module_t *)dlsym(handle, sym); //从动态链接库中获取硬件模块结构体的指针
    if (hmi == NULL) {
        LOGE("load: couldn't find symbol %s", sym);
        status = -EINVAL;
        goto done;
    }
HAL_MODULE_INFO_SYM_AS_STR是硬件模块在动态链接库中的标志,定义在hardware.h中如下:
#define HAL_MODULE_INFO_SYM         HMI
#define HAL_MODULE_INFO_SYM_AS_STR  "HMI"



4,硬件模块
硬件模块的开发主要是完成/hardware/libhardware/include/hardware目录下对应的头文件中的内容,主要是硬件模块头文件和hardware.h中
的结构体中定义了一些函数指针,调用内核提供的接口将具体的函数实现,然后编译成指定名称的动态链接库放到/system/lib/hw目录下即可。
用一句话来概括:硬件模块的开发就是定义一个hardware.h中定义的hw_module_t结构体,结构体名称为宏HAL_MODULE_INFO_SYM,然后实现结构体
的相关内容即可。

5,内核驱动
主要是要向用户层开放接口,让硬件模块和内核可以交互

<think>好的,用户想了解Android HAL的相关信息,包括架构、功能、作用以及开发指南。首先我需要回忆一下HALAndroid系统中的位置和作用。HAL,全称是硬件抽象,主要目的是为了将硬件厂商的具体实现与Android框架分离开来,这样不同的硬件驱动可以由厂商自行实现,而Android系统上无需关心底硬件的具体细节。 接下来,用户提到架构、功能、作用,还有开发指南。我需要分点来整理这些信息。架构方面,HAL位于Linux内核和Android框架之间,对上提供标准接口,对下封装硬件驱动。可能需要提到HAL模块的结构,比如每个硬件类型对应的HAL模块,如传感器、摄像头等,以及HIDL(HAL接口定义语言)在较新版本中的作用。 功能和作用方面,需要强调HAL如何屏蔽硬件差异,提供统一的接口,便于系统升级和厂商维护各自的驱动。可能还要提到兼容性问题和开源协议的影响,比如为什么厂商选择闭源HAL实现。 开发指南部分,用户可能想知道如何为一个硬件开发HAL模块。这里需要分步骤说明,比如定义接口、实现HAL模块、配置manifest文件、编译集成等步骤。可能还需要提到HIDL和AIDL的区别,以及不同Android版本中的变化,比如Android 8.0之后的Treble项目引入的HIDL。 同时,用户的问题中提到了生成相关问题,我需要根据HAL的内容生成几个相关问题,比如与Linux内核驱动的区别,HIDL的作用,兼容性考虑,调试方法等。要注意问题的多样性和相关性,确保覆盖用户可能感兴趣的方面。 还需要检查是否有遗漏的关键点,比如HAL的类型,如旧版Legacy HAL和新版Stub HAL的区别,或者具体的代码示例。不过用户没有特别要求代码,但开发指南部分可能需要提及代码结构或示例。 最后,确保回答符合系统级指令的要求:使用正确的中文,数学公式用$符号(虽然这个问题可能不太涉及数学公式,但如果有变量或技术术语需要强调的话),结构清晰,引用部分添加标识,比如Android开源项目文档或开发者指南的引用。需要确认是否有可引用的来源,比如Android官方文档中的说明,或者相关书籍的参考。 现在开始组织回答,先介绍架构,再功能和作用,然后是开发指南的步骤,最后相关问题。确保每个部分简明扼要,信息准确。</think># Android HAL详解 ## 一、架构 Android HAL(Hardware Abstraction Layer)位于Linux内核与Android框架之间,采用模块化设计。每个硬件类型(如摄像头、传感器)对应独立HAL模块,通过标准接口与上交互。从Android 8.0开始,HIDL(HAL Interface Definition Language)成为核心组件,实现框架与HAL的解耦[^1]。 $$ \text{Android架构级} = \begin{cases} \text{应用} \\ \text{框架} \\ \text{JNI} \\ \text{HAL} \rightarrow \text{硬件驱动} \\ \text{Linux内核} \end{cases} $$ ## 二、功能与作用 1. **硬件隔离**:封装$vendor\_specific$驱动实现,提供$standard\_interface$ 2. **版本兼容**:通过HIDL实现框架与HAL的版本化兼容 3. **安全隔离**:Binder IPC机制隔离系统服务与硬件访问 4. **厂商定制**:允许OEM通过闭源实现保护知识产权 ## 三、开发指南 1. **接口定义**:使用HIDL语言声明`.hal`文件 ```hidl package android.hardware.sensors@1.0; interface ISensors { getSensorList() generates (vec<Sensor> list); activate(int32_t handle, bool enabled); } ``` 2. **模块实现**:继承自动生成的Stub类 ```cpp class SensorsHal : public ISensors::Stub { Return<void> getSensorList(getSensorList_cb _hidl_cb) override; Return<Result> activate(int32_t handle, bool enabled) override; } ``` 3. **服务注册**:在`manifest.xml`声明HAL服务 ```xml <hal format="hidl"> <name>android.hardware.sensors</name> <version>1.0</version> <interface> <name>ISensors</name> <instance>default</instance> </interface> </hal> ``` 4. **编译集成**:使用Android.bp构建HAL模块 ```python cc_library_shared { name: "android.hardware.sensors@1.0-impl", srcs: ["SensorsHal.cpp"], shared_libs: [ "libhidlbase", "liblog" ] } ``` ## 四、调试技巧 - 使用`lshal`工具查看HAL服务列表 - 通过`dumpsys hardware_properties`获取硬件状态 - 使用`strace`跟踪Binder通信 [^1]: Android开源项目官方文档《HIDL架构设计》
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值