【Android】HAL分析
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存在的原因主要有:
- 并不是所有的硬件设备都有标准的linux kernel的接口
- KERNEL DRIVER涉及到GPL的版权。某些设备制造商并不原因公开硬件驱动,所以才去用HAL方 式绕过GPL。
- 针对某些硬件,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。
定义如下:
/**
* Every hardware module must have a data structure named HAL_MODULE_INFO_SYM
* and the fields of this data structure must begin with hw_module_t
* followed by module specific information.
*/ 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[-]; } hw_module_t;
如注释所说,所有的hal模块都要有一个以HAL_MODULE_INFO_SYM命名的结构,而且这个结构要以hw_module_t开始,即要继承hw_module_t这个结构。
比如lights,sensor:
struct sensors_module_t
{
struct hw_module_t common;
int (*get_sensors_list)(struct sensors_module_t* module,
struct sensor_t const** list);
}; /*
* The lights Module
*/
struct light_module_t HAL_MODULE_INFO_SYM = {
common: {
tag: HARDWARE_MODULE_TAG,
version_major: ,
version_minor: ,
id: LIGHTS_HARDWARE_MODULE_ID,
name: "Lights module",
author: "Rockchip",
methods: &light_module_methods,
}
}; const struct sensors_module_t HAL_MODULE_INFO_SYM = {
.common = {
.tag = HARDWARE_MODULE_TAG,
.version_major = ,
.version_minor = ,
.id = SENSORS_HARDWARE_MODULE_ID,
.name = "Stingray SENSORS Module",
.author = "Motorola",
.methods = &sensors_module_methods,
},
.get_sensors_list = sensors__get_sensors_list
};
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定义如下:
/**
* Every device data structure must begin with hw_device_t
* followed by module specific public methods and attributes.
*/ 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[]; /** Close this device */
int (*close)(struct hw_device_t* device);
} hw_device_t; struct light_device_t
{
struct hw_device_t common;
int (*set_light)(struct light_device_t* dev,
struct light_state_t const* state);
}; /**
* Every device data structure must begin with hw_device_t
* followed by module specific public methods and attributes.
*/ struct sensors_poll_device_t
{
struct hw_device_t common;
int (*activate)(struct sensors_poll_device_t *dev,
int handle, int enabled);
int (*setDelay)(struct sensors_poll_device_t *dev,
int handle, int64_t ns);
int (*poll)(struct sensors_poll_device_t *dev,
sensors_event_t* data, int count);
};
亦如注释所说,每一个设备的数据结构都必须也以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中
调用关系
【Android】HAL分析的更多相关文章
- Android Hal 分析
本文是基于android4.0.3.对应其他低版本的代码,可能有所差异,但基本大同小异. Android的HAL是为了保护一些硬件提供商的知识产权而提出的,是为了避开linux的GPL束缚.思路是把控 ...
- android HAL 教程(含实例)
http://www.cnblogs.com/armlinux/archive/2012/01/14/2396768.html Android Hal 分析 ...
- Android架构分析之使用自定义硬件抽象层(HAL)模块
作者:刘昊昱 博客:http://blog.csdn.net/liuhaoyutz Android版本:2.3.7_r1 Linux内核版本:android-goldfish-2.6.29 在上一篇博 ...
- Android Hal层简要分析
Android Hal层简要分析 Android Hal层(即 Hardware Abstraction Layer)是Google开发的Android系统里上层应用对底层硬件操作屏蔽的一个软件层次, ...
- 【转】【Android】HAL分析
原文网址:http://www.cnblogs.com/lcw/p/3335505.html HAL概述 以下是基于android4.0.3,对应其他低版本的代码,可能有所差异,但基本大同小异. An ...
- 【转】Android HAL实例解析
原文网址:http://www.embedu.org/Column/Column339.htm 作者:刘老师,华清远见嵌入式学院讲师. 一.概述 本文希望通过分析台湾的Jollen的mokoid 工程 ...
- Android HAL实例解析
一.概述 本文希望通过分析台湾的Jollen的mokoid 工程代码,和在s5pc100平台上实现过程种遇到的问题,解析Andorid HAL的开发方法. 二.HAL介绍 现有HAL架构由Patric ...
- Android多线程分析之五:使用AsyncTask异步下载图像
Android多线程分析之五:使用AsyncTask异步下载图像 罗朝辉 (http://www.cnblogs.com/kesalin) CC 许可,转载请注明出处 在本系列文章的第一篇<An ...
- Android多线程分析之四:MessageQueue的实现
Android多线程分析之四:MessageQueue的实现 罗朝辉 (http://www.cnblogs.com/kesalin/) CC 许可,转载请注明出处 在前面两篇文章<Androi ...
随机推荐
- FTP命令字和响应码解释
FTP命令: 命令 描述 ABOR 中断数据连接程序 ACCT <account> 系统特权帐号 ALLO <bytes> 为服务器上的文件存储器分配字节 APPE &l ...
- (原)luarocks install 提示 failed fetching manifest
转载请注明出处: http://www.cnblogs.com/darkknightzh/p/6400169.html 参考网址: https://github.com/torch/torch7/is ...
- iOS presentedViewController和presentingViewController的区别
当我们用present进行界面跳转时,会涉及到一个传向关系. 比如:A -> B 界面A跳转界面B A.presentedViewControlle = B B.presentingVie ...
- 进阶之路(基础篇) - 020 放弃Arduino IDE,拥抱Sublime Text 3
本帖转载:Arduino讨论区相信大家对Arduino IDE的不能输入中文,排版不方便,没有行号,界面难看......深恶痛绝.我也是.经过vs2012,eclipse等IDE的试用,配置麻烦,ID ...
- Python之包管理工具
安装Python包的过程中,经常涉及到distutils.setuptools.distribute.setup.py.easy_install.easy_install和pip等等. distuil ...
- Sqlserver大数据量分区表创建
/* 逆向删除对象 DROP PARTITION SCHEME [PS_BasicPolicy2014]; DROP PARTITION FUNCTION [PF_BasicPolicy2014]; ...
- Win10下Clion配置opencv3
本人不想在爱机装一个vs2013或者vs2015这种庞然大物,可是手头要弄一个基于windows的opencv项目,就只好装了个Clion,期间踩了不少坑,记录一下. 参考网址:http://www. ...
- nginx无法启动异常
Nginx安装过程中可能会报如下错误: /usr/local/nginx/sbin/nginx -t /usr/local/nginx/sbin/nginx: error while loading ...
- Android 获取自带浏览器上网记录
先是搜索了一下,在manifest里添加 <uses-permission android:name="com.android.browser.permission.READ_HIST ...
- [转]Java的文件读写操作
file(内存)----输入流---->[程序]----输出流---->file(内存) 当我们读写文本文件的时候,采用Reader是非常方便的,比如FileReader,InputStr ...