一、HAL架构

HAL(硬件抽象层,Hardware Abstraction Layer)是为了保护一些硬件提供商的知识产权而提出的,是为了避免Linux的GPL束缚。把控制硬件的动作都放到了HAL中。


新架构、调整为 HAL stub 的观念 主要包含以下一些模块:Gps、Vibrator、Wifi、Copybit、Audio、Camera、Lights、Ril、Overlay等。
HAL架构是当前Android源码中使用的思路,每一个硬件模块称为一个stub(代理人),并且借尸so的形式编译,所有的stub都要通过libhardware.so(由hardware.c)才能找到每一个stub,才能回调每一个stub中硬件抽象接口,当然stub在编写时需要按照HAL_MODULE_INFO_SYM的格式来写,通过libhardware.so找到stub时,就会将该stub加载到内存,返回该stub的模块指针。优点:采用HAL module和HAL stub结合形式,HAL stub不是共享库,上层只拥有访问stub的函数指针,并不需要stub,Runtime只需要根据module ID并通过HAL module提供的统一接口就能取得stub的操作函数,只会被映射到一个进程,不会浪费空间。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XymXBbdA-1635519984284)(https://i.imgur.com/qrtgvMc.jpg)]

二、编写一款支持HAL的Linux的驱动程序步骤

第1步:编写Linux驱动

为Linux驱动添加HAL, 尽量保护敏感数据,代码尽量简洁,将业务逻辑放到HAL Library中。

第2步:编写HAL Library

HAL Library就是普通的Linux Library(*.so)文件,这类库文件有一个接口,通过HAL_MODULE_INFO_SYM变量实现。Service Library就是通过这个接口定义的ID来找到HAL Library的。

第3步:编写Service Library

新HAL架构要求我们必须编写。Service Library可以是Linux Library,也可以是JNI Library。还应该编写一个用JAVA写的服务管理类(ServiceManager).
ServiceManager会调用Service Library,而APK会调用ServiceManager来访问Service Library。

三、编写Linux驱动

以LED驱动为例
在之前实现的Linux驱动的基础上进行修改。去掉所有的与寄存器读写有关的代码,只保留创建设备文件及与寄存器交互的代码(只是简单的读写寄存器操作,不进行GPXDAT的具体操作)。
此环节实现在设备文件的read和write中读写指定的寄存器

编写HAL模块

struct led_module_t{
	struct hw_module_t hw_module;//HAL规定不能直接使用此结构,必须在外面套上一层。
};

struct led_control_device_t{
	struct hw_device_t hw_device;
	int (*set_off)(...);
	int(*set_on)(...);
};
#define LED_HARDWARE_MODULE_ID "led_hal"

第1步:定义结构体和宏

这两个结构体的第1个变量的数据类型必须是hw_module_thw_device_t,另外还需要为HAL模块定义一个ID。还有描述模块入口函数的hw_module_methods_t。首先使用的是hw_module_t,然后通过hw_module_methods_t找到.open函数,并且调用该函数,open函数相当于HAL模块的入口

第2步:编写HAL的open函数

  1. 初始化hw_device_t结构体。设置硬件操作函数(set_on和set_off)
  2. 打开设备文件
  3. 初始化寄存器

第3步:定义hw_module_methods_t结构体变量

指定open入口函数

第4步:定义HAL_MODULE_INFO_SYM变量

所有的HAL模块都必须有一个HAL_MODULE_INFO_SYM变量,一般为hw_module_t的或者其子结构体,会初始化此结构体,其中id和methods最重要,id表示HAL模块在Android系统中的标识。

第5步:编写HAL模块的close函数

HAL模块被卸载后会调用close函数

第6步:编写控制LED的函数

编写调用HAL模块的Service

编写调用Service的JAVA库 ##

将Service程序库封装在JAR文件中。