HAL概述

  以下是基于android4.0.3,对应其他低版本的代码,可能有所差异,但基本大同小异。

Android的HAL是为了保护一些硬件提供商的知识产权而提出的,是为了避开linux的GPL束缚。

  思路是把控制硬件的动作都放到了Android HAL中,而linux driver仅仅完成一些简单的数据交互作用,甚至把硬件寄存器空间直接映射到user space。而Android是基于Aparch的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有一些特殊的需求

Android架构

源码位置

/hardware/libhardware_legacy/   - 旧的架构、采取链接库模块的方式

/hardware/libhardware      新架构、调整为 HAL stub 目录的结构如下:

/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 目录下定义了很多硬件模块

/hardware/msm7k

/hardware/qcom

/hardware/ti

/device/Samsung

/device/moto 各个厂商平台相关的hal

  这些硬件模块都编译成xxx.xxx.so,目标位置为/system/lib/hw目录。

HAL层的实现方式

  目前HAL存在两种构架,位于libhardware_legacy目录下的“旧HAL架构”和位于libhardware目录下的“新HAL架构”。

  两种框架如下图所示:

libhardware_legacy

  libhardware_legacy 是将 *.so 文件当作shared library来使用,在runtime(JNI 部份)以 direct function call 使用 HAL module。通过直接函数调用的方式,来操作驱动程序。

  当然,应用程序也可以不需要通过 JNI 的方式进行,直接加载 *.so (dlopen)的做法调用*.so 里的符号(symbol)也是一种方式。

  总而言之是没有经过封装,上层可以直接操作硬件。

libhardware

  现在的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层结构框架,通过几个接口访问硬件从而统一了调用方式。

JNI

  Android的HAL的实现需要通过JNI(Java Native Interface)。

  JNI简单来说就是java程序可以调用C/C++写的动态链接库,这样的话,HAL可以使用C/C++语言编写,效率更高。

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

访问HAL方式

  在Android下访问HAL大致有以下两种方式。

经过service调用

  Android的app可以直接通过service调用.so格式的jni。

经过Manager调用service

  上面两种方法应该说是各有优缺点:

  第一种方法简单高效,但不正规。

  第二种方法实现起来比较复杂,但更符合目前的Android框架。

  第二种方法中,LedManager和LedService(java)在两个进程中,需要通过进程通讯的方式来通讯。

  在现在的android框架中,这两种方式都存在,比如对于lights,是直接透过LightsService调用JNI,而对于sensor,中间则是通过SensorsManager来调用JNI的。

通用硬件模块(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 * Every hardware module must have a data structure named HAL_MODULE_INFO_SYM 3  * and the fields of this data structure must begin with hw_module_t 4  * followed by module specific information. 5  */ 6  7 typedef struct hw_module_t  8 { 9 10 /** tag must be initialized to HARDWARE_MODULE_TAG */11 uint32_t tag;12 13 /** major version number for the module */14 uint16_t version_major;15 16 /** minor version number of the module */17 uint16_t version_minor; 18 19 /** Identifier of module */20 const char *id;21 22 /** Name of this module */23 const char *name;24 25 /** Author/owner/implementor of the module */26 const char *author;27 28 /** Modules methods */29 struct hw_module_methods_t* methods; //硬件模块的方法30 31 /** module's dso */32 void* dso;33  34 35 /** padding to 128 bytes, reserved for future use */36 uint32_t reserved[32-7];37 38 } hw_module_t;
View Code

  如注释所说,所有的hal模块都要有一个以HAL_MODULE_INFO_SYM命名的结构,而且这个结构要以hw_module_t开始,即要继承hw_module_t这个结构。

  比如lights,sensor:

 1 struct sensors_module_t  2 { 3  struct hw_module_t common; 4 int (*get_sensors_list)(struct sensors_module_t* module, 5             struct sensor_t const** list); 6 }; 7  8 /* 9  * The lights Module10  */11 struct light_module_t HAL_MODULE_INFO_SYM = {12     common: {13         tag: HARDWARE_MODULE_TAG,14         version_major: 1,15         version_minor: 0,16         id: LIGHTS_HARDWARE_MODULE_ID,17         name: "Lights module",18         author: "Rockchip",19         methods: &light_module_methods,20     }21 };22 23 const struct sensors_module_t HAL_MODULE_INFO_SYM = {24     .common = {25         .tag = HARDWARE_MODULE_TAG,26         .version_major = 1,27         .version_minor = 0,28         .id = SENSORS_HARDWARE_MODULE_ID,29         .name = "Stingray SENSORS Module",30         .author = "Motorola",31         .methods = &sensors_module_methods,32     },33     .get_sensors_list = sensors__get_sensors_list34 };
View Code

  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;

  该方法在定义HAL_MODULE_INFO_SYM的时候被初始化。目前该结构中只定义了一个open方法,其中调用的设备结构体参数hw_device_t定义如下:

 1  /** 2  * Every device data structure must begin with hw_device_t 3  * followed by module specific public methods and attributes. 4  */ 5  6 typedef struct hw_device_t 7 { 8     /** tag must be initialized to HARDWARE_DEVICE_TAG */ 9     uint32_t tag;10 11     /** version number for hw_device_t */12     uint32_t version;13 14     /** reference to the module this device belongs to */15     struct hw_module_t* module;16 17     /** padding reserved for future use */18     uint32_t reserved[12]; 19 20     /** Close this device */21     int (*close)(struct hw_device_t* device);22 } hw_device_t;23 24 struct light_device_t 25 {26     struct hw_device_t common;27     int (*set_light)(struct light_device_t* dev,28             struct light_state_t const* state);29 };30 31 /**32  * Every device data structure must begin with hw_device_t33  * followed by module specific public methods and attributes.34  */35 36 struct sensors_poll_device_t 37 {38     struct hw_device_t common;39     int (*activate)(struct sensors_poll_device_t *dev,40             int handle, int enabled);41     int (*setDelay)(struct sensors_poll_device_t *dev,42             int handle, int64_t ns);43     int (*poll)(struct sensors_poll_device_t *dev,44             sensors_event_t* data, int count);45 };
View Code

  亦如注释所说,每一个设备的数据结构都必须也以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中

调用关系

  

更多相关文章

  1. Android(安卓)Wifi模块分析(三)
  2. Android中dispatchDraw分析
  3. Android四大基本组件介绍与生命周期
  4. Android(安卓)Service AIDL
  5. Android调用天气预报的WebService简单例子
  6. android打电话发短信
  7. android 拨打紧急号码,通话时开启免提功能实现
  8. Android调用.NET Webservice报org.ksoap2.serialization.SoapPri
  9. Android架构分析之使用自定义硬件抽象层(HAL)模块

随机推荐

  1. js bridge 实现原理
  2. Shell脚本中的while getopts用法小结
  3. 全文检索技术ElasticSearch使用
  4. 【js效果】倒计时
  5. 【DB笔试面试672】在Oracle中,errorstack
  6. 【DB笔试面试660】在Oracle中,在编译存储
  7. Nodejs 开发CLI必备基础依赖库
  8. CXF实现WebService入门
  9. JS 中的 Reflect 和 Proxy
  10. Rxjs给应用带来的优势