原文网址:http://www.cnblogs.com/lcw/p/3335505.html

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。

  定义如下:

 

  如注释所说,所有的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 Module
10 */
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_list
34 };

  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_t
33 * 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 };

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

调用关系

  

QQ联系方式:lcw@v.gg
邮箱:wwwlllll@126.com
本文申明:本文版权归作者和博客园共有,欢迎转载,转载请注明出处.

【转】【Android】HAL分析的更多相关文章

  1. Android Hal 分析

    本文是基于android4.0.3.对应其他低版本的代码,可能有所差异,但基本大同小异. Android的HAL是为了保护一些硬件提供商的知识产权而提出的,是为了避开linux的GPL束缚.思路是把控 ...

  2. android HAL 教程(含实例)

    http://www.cnblogs.com/armlinux/archive/2012/01/14/2396768.html Android Hal 分析                       ...

  3. Android架构分析之使用自定义硬件抽象层(HAL)模块

    作者:刘昊昱 博客:http://blog.csdn.net/liuhaoyutz Android版本:2.3.7_r1 Linux内核版本:android-goldfish-2.6.29 在上一篇博 ...

  4. Android Hal层简要分析

    Android Hal层简要分析 Android Hal层(即 Hardware Abstraction Layer)是Google开发的Android系统里上层应用对底层硬件操作屏蔽的一个软件层次, ...

  5. 【Android】HAL分析

    HAL概述 以下是基于android4.0.3,对应其他低版本的代码,可能有所差异,但基本大同小异. Android的HAL是为了保护一些硬件提供商的知识产权而提出的,是为了避开linux的GPL束缚 ...

  6. 【转】Android HAL实例解析

    原文网址:http://www.embedu.org/Column/Column339.htm 作者:刘老师,华清远见嵌入式学院讲师. 一.概述 本文希望通过分析台湾的Jollen的mokoid 工程 ...

  7. Android HAL实例解析

    一.概述 本文希望通过分析台湾的Jollen的mokoid 工程代码,和在s5pc100平台上实现过程种遇到的问题,解析Andorid HAL的开发方法. 二.HAL介绍 现有HAL架构由Patric ...

  8. Android多线程分析之五:使用AsyncTask异步下载图像

    Android多线程分析之五:使用AsyncTask异步下载图像 罗朝辉 (http://www.cnblogs.com/kesalin) CC 许可,转载请注明出处 在本系列文章的第一篇<An ...

  9. Android多线程分析之四:MessageQueue的实现

    Android多线程分析之四:MessageQueue的实现 罗朝辉 (http://www.cnblogs.com/kesalin/) CC 许可,转载请注明出处 在前面两篇文章<Androi ...

随机推荐

  1. jQuery 弹出div层

    目的:使用jQuery弹出一个div窗口:这种效果经常应用于页面内容的展示,登录效果的实现.其实,实现这种效果有好多种方式: 效果如下: 代码如下: <html> <head> ...

  2. Raid1源代码分析--读流程(重新整理)

    五.Raid1读流程分析 两个月前,刚刚接触raid1,就阅读了raid1读流程的代码,那个时候写了一篇博客.现在回过头看看,那篇的错误很多,并且很多地方没有表述清楚.所以还是决定重新写一篇以更正之前 ...

  3. <php>json小结

    1.页面中如果即用到jquery包,又用到js文件,要先写jquery包,再加载js文件 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Tr ...

  4. ubuntu14.04 + cocos2d-x-2.2.6 + eclipse发布android + Qt Creator4

    先把需要的东西准备好,打开控制台,执行以下语句: sudo apt--jdk lib32z1 lib32ncurses5 lib32bz2- 接下来,准备好cocos2d-x-2.2.6和 andro ...

  5. Node.js 之 express 入门 ejs include公共部分

    1. 直接进入express安装 因为之前有一篇文章我已经讲过怎么安装node了 而网上的教程也是非常多.所有直接进入到express.教程简陋 由于我比较笨 所有只要写到我自己明白就行. 这里有个教 ...

  6. WebApi2官网学习记录---Html Form Data

    HTML Forms概述 <form action="api/values" method="post"> 默认的method是GET,如果使用GE ...

  7. FineUI表单验证

    自动编码文本 默认情况下,Label的EncodeText属性为true,会对文本中的HTML进行编码.当然我们也可以设置EncodeText=false,从而将HTML片段赋值给Text属性,请看这 ...

  8. 《第一行代码》学习笔记4-活动Activity(2)

    1.Toast是Android系统中一种好的提醒方式,程序中使用它将一些短小的信 息通知给用户,信息会在不久自动消失,不占用任何屏幕空间. 2.定义一个弹出Toast的出发点,界面有按钮,就让点击按钮 ...

  9. C/C++中的switch使用

    代码: #include <iostream> #include <string> #include <cstdio> using namespace std; i ...

  10. log4j配置文件及nutch中的日志配置

    使用slf4j作为日志系统时,由于slf4j只是一个接口,它需要一个具体实现来执行. 具体参考http://blog.csdn.net/jediael_lu/article/details/43854 ...