最近开始看Android的HAL开发方面的东东,发现现在国内研究这个的并不多,来自台湾的Jollen可能是走在Android HAL研究的最前沿,这也和他以前专注做嵌入式linux(openmoko)的工作经历有关,毕竟Android的application开发是基于Java的,而之前Jollen做的更多的还是C/C++开发,因此选择从HAL作为进入Android的shortcut还是很明智的,我以前也主要是做linux kernel以及基于C/C++的app开发,现在转作Android,发现它的HAL比较有意思,也是可以研究的一个很好的方向。

由于自己并没有参加Jollen的HAL整合培训,不过手头有这个培训的材料,以及从http://code.google.com/p/mokoid/下载了mokoid 工程的代码,花了一段时间研究了Android的HAL,也有一些心得,下面总结一下:

首先,Android的HAL是为了一些硬件提供商提出的“保护proprietary”的驱动程序而产生的东东,简而言之,就是为了避开linux kernel的GPL license的束缚。Android把控制硬件的动作都放到了user space中,而再kernel driver里面只有最简单的读写寄存器的操作,而完全去掉了各种功能性的操作(比如控制逻辑等),这些能够体现硬件特性的操作都放到了Android的HAL层,而Android是基于Aparch的license,因此硬件厂商可以只提供二进制代码,所以说Android只是一个开放的平台,并不是一个开源的平台。

然后,Android的HAL的实现需要通过JNI(Java Native Interface),JNI简单来说就是java程序可以调用C/C++写的动态链接库,这样的话,HAL可以使用C/C++语言编写,效率更高。而Android的app可以直接调用.so,也可以通过app->app_manager->service(java)->service(jni)->HAL来调用。第二种方法看上去很复杂,但是更加符合android的框架结构。我这里也着重介绍第二种方法。基本的框架如下所示:

Mokiod工程代码树如下所示:

        
  1. .
  2. |--apps -- 测试应用程序
  3. ||--LedClient-- 直接调用service控制硬件
  4. |||--AndroidManifest.xml
  5. ||`--src
  6. ||`--com
  7. ||`--mokoid
  8. ||`--LedClient
  9. ||`--LedClient.java
  10. |`--LedTest-- 通过manager来控制硬件
  11. ||--AndroidManifest.xml
  12. |`--src
  13. |`--com
  14. |`--mokoid
  15. |`--LedTest
  16. ||--LedSystemServer.java
  17. |`--LedTest.java
  18. |--frameworks-- 框架代码
  19. |`--base
  20. ||--core
  21. ||`--java
  22. ||`--mokoid
  23. ||`--hardware
  24. |||--ILedService.aidl-- Android Interface Definition Language 代码,提供LedService的接口
  25. ||`--LedManager.java-- LedManager实现代码
  26. |`--service
  27. ||--com.mokoid.server.xml
  28. ||--java
  29. ||`--com
  30. ||`--mokoid
  31. ||`--server
  32. ||`--LedService.java-- LedService的java实现代码
  33. |`--jni
  34. |`--com_mokoid_server_LedService.cpp-- LedService的jni实现代码
  35. |--hardware
  36. `--modules
  37. |--include
  38. |`--mokoid
  39. |`--led.h
  40. `--led
  41. `--led.c-- led实际控制硬件的代码

介绍Android的HAL的时候,我打算从底层往上层介绍。

1. Kernel Driver

这里的kernel driver相对于linux真正的driver形式上是一样的,也提供open,read,write,ioctl,mmap等接口,但是,一般来说,只通过这些代码,你并不能了解到硬件的特性,比如write接口,就可以只作成往寄存器写操作,至于如何写,为什么要写,这些工作都会再HAL层进行,而一般用户是看不到这些代码的。这也是为什么linux mainstream把android的kernel踢出去的原因,因为这些driver根本无法用在其他的linux平台上。

2. HAL层

这一层就位于kernel之上的user space了,一般来说这里需要涉及的是两个结构体:hw_module_t和hw_device_t, 第一个结构体是当这个hardware stub被load的时候(hw_get_module())提供的初始化操作,比如提供stub的open(module->methods->open())操作,而第二个结构体是提供该硬件stub具有的操作硬件的接口,再jollen的mokoid工程里,主要提供打开和关闭led的操作,相关的代码如下:

led.h

        
  1. structled_module_t{
  2. structhw_module_tcommon;
  3. };
  4. structled_control_device_t{
  5. structhw_device_tcommon;
  6. /*attributes*/
  7. intfd;
  8. /*supportingcontrolAPIsgohere*/
  9. /*打开led操作*/
  10. int(*set_on)(structled_control_device_t*dev,int32_tled);
  11. /*关闭led操作*/
  12. int(*set_off)(structled_control_device_t*dev,int32_tled);
  13. };

led.c

        
  1. /*打开led操作*/
  2. intled_on(structled_control_device_t*dev,int32_tled)
  3. {
  4. LOGI("LEDStub:set%don.",led);
  5. return0;
  6. }
  7. /*关闭led操作*/
  8. intled_off(structled_control_device_t*dev,int32_tled)
  9. {
  10. LOGI("LEDStub:set%doff.",led);
  11. return0;
  12. }
  13. /*打开led硬件时候的操作*/
  14. staticintled_device_open(conststructhw_module_t*module,constchar*name,
  15. structhw_device_t**device)
  16. {
  17. structled_control_device_t*dev;
  18. dev=(structled_control_device_t*)malloc(sizeof(*dev));
  19. memset(dev,0,sizeof(*dev));
  20. ...
  21. /*提供给service可用的硬件操作接口*/
  22. dev->set_on=led_on;
  23. dev->set_off=led_off;
  24. *device=&dev->common;
  25. success:
  26. return0;
  27. }
  28. staticstructhw_module_methods_tled_module_methods={
  29. open:led_device_open
  30. };
  31. conststructled_module_tHAL_MODULE_INFO_SYM={
  32. common:{
  33. tag:HARDWARE_MODULE_TAG,
  34. version_major:1,
  35. version_minor:0,
  36. id:LED_HARDWARE_MODULE_ID,
  37. name:"SampleLEDStub",
  38. author:"TheMokoidOpenSourceProject",
  39. methods:&led_module_methods,
  40. }
  41. /*supportingAPIsgohere*/
  42. };

以上代码最后会被编译成动态链接库,比如libled.so放到/system/libs/hw/, 当service调用hw_get_module(hardware/libhardware/hardware.c)时候,会在/system/libs/hw/里面寻找对应的动态链接库,然后提供给service对应的操作接口。

更多相关文章

  1. 升级代码的大概设计
  2. Android下使用TinyXml读取xml配置文件(Cocos2d-x游戏开发)
  3. Android(安卓)Launcher抽屉类SlidingDrawer的使用
  4. Android异步机制一:使用Thread+Handler实现非UI线程更新UI界面
  5. 《第一行代码--Android》读书笔记之多线程与服务
  6. Android中JNI编程的那些事儿 【转】
  7. Android平台开发-Android(安卓)HAL develop-Android(安卓)HAL开
  8. Android代码混淆指南
  9. Android(安卓)JNI

随机推荐

  1. Android(安卓)—— 自定义View的实现方法
  2. 大家看一下,我对Android的Activity的深入
  3. Android(安卓)百度地图 SDK v3.4.0 定位
  4. Android音频开发(四)——ffmpeg的编译
  5. 调用Android常用应用的接口
  6. 浅入浅出 Android(安卓)安全(六)Android(安
  7. Android(安卓)Shape(背景渐变颜色)
  8. Android(安卓)7.0新特性——依然范特西
  9. Android集成百度定位以及导航详解
  10. 深入Android(安卓)【三】 —— 组件入门