androidHAL教程(含实例)
Android Hal 分析
-------rockchip Andy
本⽂是基于android4.0.3.对应其他低版本的代码,可能有所差异,但基本⼤同⼩异。
1.产⽣HAL的原因
Android的HAL是为了保护⼀些硬件提供商的知识产权⽽提出的,是为了避开linux的GPL束缚。思路是把控制硬件的动作都放到了Android HAL中,⽽linux driver仅仅完成⼀些简单的数据交互作⽤,甚⾄把硬件寄存器空间直接映射到user space。⽽Android是基于Apache的license,因此硬件⼚商可以只提供⼆进制代码,所以说Android只是⼀个开放的平台,并不是⼀个开源的平台。也许也正是因为Android不遵从GPL,所以Greg Kroah-Hartman才在2.6.33内核将Andorid驱动从linux中删除。GPL和硬件⼚商⽬前还是有着⽆法弥合的裂痕。Android想要把这个问题处理好也是不容易的。
总结下来,Android HAL存在的原因主要有:
1. 并不是所有的硬件设备都有标准的linux kernel的接⼝
2. KERNEL DRIVER涉及到GPL的版权。某些设备制造商并不原因公开硬件驱动,所以才去⽤HAL⽅ 式绕过GPL。
3. 针对某些硬件,An有⼀些特殊的需求
现有HAL架构由Patrick Brady (Google) 在2008 Google I/O演讲中提出的,如下图:
2.源码⽬录介绍
/hardware/libhardware_legacy/ 旧的架构、采取链接库模块的⽅式
/hardware/libhardware 新架构、调整为 HAL stub。
/hardware/ril ⽆线电抽象层
⼀般除了它们3个都是硬件⼚商相关的hal⽬录。
2.1 libhardware⽬录的结构如下
/hardware/libhardware/hardware.c 编译成libhardware.s置于/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 ⽬录下定义了很多硬件模块
2.2 下⾯⼏个是各个⼚商平台相关的hal
/hardware/msm7k
/hardware/qcom
/hardware/ti
/device/Samsung
/device/moto
这些硬件模块都编译成so,⽬标位置为/system/lib/hw⽬录
3.HAL层的两种架构与两种访问⽅式
3.1 两种架构
位于libhardware_legacy⽬录下的“旧HAL架构”和位于libhardware⽬录下的“新HAL架构”。两种框架如下图所⽰:
libhardware_legacy 是将 *.so ⽂件当作shared library来使⽤,在runtime(JNI 部份)以 direct functio
n call 使⽤ HAL module。通过直接函数调⽤的⽅式,来操作驱动程序。当然,应⽤程序也可以不需要通过 JNI 的⽅式进⾏,直接加载 *.so
(dlopen)的做法调⽤*.so ⾥的符号(symbol)也是⼀种⽅式。总⽽⾔之是没有经过封装,上层可以直接操作硬件。
现在的libhardware 架构,就有stub的味道了。HAL stub 是⼀种代理⼈(proxy)的概念,stub 虽然仍是以 *.so的形式存在,但HAL已经将 *.so 隐藏起来了。Stub 向 HAL提供操作函数(operations),⽽ runtime 则是向 HAL 取得特定模块(stub)的operations,再 callback 这些操作函数。这种以 indirect function call 的架构,让HAL stub 变成是⼀种包含关系,即 HAL ⾥包含了许许多多的 stub(代理⼈)。Runtime 只要说明类型,即 module ID,就可以取得操作函数。对于⽬前的HAL,可以认为Android定义了HAL层结构框架,通过⼏个接⼝访问硬件从⽽统⼀了调⽤⽅式。
Android的HAL的实现需要通过JNI(Java Native Interface),JNI简单来说就是java程序可以调⽤C/C++写的动态链接库,这样的话,HAL可以使⽤C/C++语⾔编写,效率更⾼。
3.2 调⽤过程如下
3.3 两种访问⽅式
(1)Android的app可以直接通过service调⽤.so格式的jni
(2)经过Manager调⽤service
上⾯两种⽅法应该说是各有优缺点:
第⼀种⽅法简单⾼效,但不正规。
第⼆种⽅法实现起来⽐较复杂,但更符合⽬前的Android框架。第⼆种⽅法中,LegManager和LedService(java)在两个进程中,需要进程通讯。
android简单教程 在现在的android框架中,这两种⽅式都存在,⽐如对于lights,是直接透过LightsService调⽤JNI,⽽对于sensor,中间则是通过SensorsManager来调⽤JNI的。
4.通⽤硬件模块(libhardware.so)
⼀般来说HAL moudle需要涉及的是三个关键结构体:
struct hw_module_t;
struct hw_module_methods_t;
struct hw_device_t;
这三个结构体定义在hardware.h中。
路径为:/hardware/libhardware/include/hardware/hardware.h
头⽂件中主要定义了通⽤硬件模块结构体hw_module_t,声明了JNI调⽤的接⼝函数hw_get_module。hw_module_t定义如下:
1/**
2
3* Every hardware module must have a data structure named HAL_MODULE_INFO_SYM
4
5 * and the fields of this data structure must begin with hw_module_t
6
7 * followed by module specific information.
8
9*/
10 typedef struct hw_module_t {
11
12 /** tag must be initialized to HARDWARE_MODULE_TAG */
13 uint32_t tag;
14
15 /** major version number for the module */
16 uint16_t version_major;
17
18 /** minor version number of the module */
19 uint16_t version_minor;
20
21 /** Identifier of module */
22 const char *id;
23
24 /** Name of this module */
25 const char *name;
26
27 /** Author/owner/implementor of the module */
28 const char *author;
29
30 /** Modules methods */
31 struct hw_module_methods_t* ; //硬件模块的⽅法
32
33 /** module's dso */
34 void* dso;
35
36 /** padding to 128 bytes, reserved for future use */
37 uint32_t reserved[32-7];
38
39 } hw_module_t;
如注释所说,所有的hal模块都要有⼀个以命名的结构,⽽且这个结构要以hw_module_t为第⼀个成员,即要继承hw_module_t这个结构,⽐如lights,sensor:
1struct sensors_module_t {
2struct;
3int (*get_sensors_list)(struct sensors_module_t* module,
4struct sensor_t const** list);
5 };
6
7/*
8 * The lights Module
9*/
10struct light_module_t = {
11 .: {
12 tag: HARDWARE_MODULE_TAG,
13 version_major: 1,
14 version_minor: 0,
15 id: LIGHTS_HARDWARE_MODULE_ID,
16 name: "Lights module",
17 author: "Rockchip",
18 methods: &,
19 }
20 };
21
22const struct sensors_module_t = {
23 . = {
24 .tag = HARDWARE_MODULE_TAG,
25 .version_major = 1,
26 .version_minor = 0,
27 .id = SENSORS_HARDWARE_MODULE_ID,
28 .name = "Stingray SENSORS Module",
29 .author = "Motorola",
30 .methods = &,
31 },
32 .get_sensors_list = sensors__get_sensors_list
33
34 };
hw_module_t中⽐较重要的是硬件模块⽅法结构体hw_module_methods_t定义如下:
1 typedef struct hw_module_methods_t {
2
3 /** Open a specific device */
4
5 int (*open)(const struct hw_module_t* module, const char* id,
6
7 struct hw_device_t** device);
8
9 } hw_module_methods_t;
该⽅法在定义的时候被初始化。⽬前该结构中只定义了⼀个open⽅法,其中调⽤的设备结构体参数hw_device_t定义如下:
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论