目录(?)[+]

硬件抽象层是位于用户空间的Android系统和位于内核空间的Linux驱动程序中间的一个层次

android HAL介绍_第1张图片

Android系统实际关心的只是硬件抽像层,并不关心驱动程序,将Android系统的部分功能和Linux中的驱动程序隔

离,Android不依赖于Linux的驱动程序。


硬件抽象层接口方法


1hardware模块的方式

Androidlibhardware库提供一种不依赖编译时绑定,可以动态加载硬件抽象层

硬件模块方法的硬件抽象层架构

android HAL介绍_第2张图片

在使用硬件抽象层的过程中,Android系统的框架层将调用libhardware的接口,根据每一个模块的id,将在指定路径动态打开dlopen各个模块,然后找到符号dlsym,调用硬件模块中的各个接口。

led.h中定义的id

#defineLED_HARDWARE_MODULE_ID"led"

Libhardware的接口在以下目录中定义

hardware/libhardware/include/hardware/hardware.h

/**

*Everyhardwaremodulemusthaveadatastructurenamed HAL_MODULE_INFO_SYM

*andthefieldsofthisdatastructuremustbeginwithhw_module_t

*followedbymodulespecificinformation.

*/


[csharp] view plain copy
  1. 结构体一structhw_module_t结构体用于定义硬件模块的格式
  2. typedefstructhw_module_t{
  3. uint32_ttag;/**tagmustbeinitializedtoHARDWARE_MODULE_TAG*/
  4. uint16_tversion_major;/**主版本号*/
  5. uint16_tversion_minor;/**次版本号*/
  6. constchar*id;/*模块标识*/
  7. constchar*name;//模块的名称
  8. constchar*author;//模块的作者
  9. structhw_module_methods_t*methods;/**模块方法*/
  10. void*dso;/**模块的dso*/
  11. uint32_treserved[32-7];/**填充字节,为以后使用*/
  12. }hw_module_t;
  13. /********************************************************************/
  14. 在led.h里定义
  15. structled_module_t{
  16. structhw_module_tcommon;
  17. };
  18. /*
  19. *struchhw_module_t结构体定义了一个硬件模块的信息,在各个具体硬件模块中,需要以这个结构体为第一个成员,即表示继承了这个结构体。
  20. */
  21. 在led.cpp里定义
  22. extern"C"conststructled_module_tHAL_MODULE_INFO_SYM={
  23. common:{
  24. tag:HARDWARE_MODULE_TAG,
  25. version_major:1,
  26. version_minor:0,
  27. id:LED_HARDWARE_MODULE_ID,
  28. name:"SampleLEDStub",
  29. author:"TheForlinxOpenSourceProject",
  30. methods:&led_module_methods,
  31. }
  32. };
  33. 结构体二structhw_module_methods_t是一个表示模块方法的结构体。
  34. hardware/libhardware/include/hardware/hardware.h中定义
  35. typedefstructhw_module_methods_t{
  36. /**打开设备的方法*/
  37. int(*open)(conststructhw_module_t*module,constchar*id,
  38. structhw_device_t**device);
  39. }hw_module_methods_t;
  40. structhw_module_methods_t结构体只包含了一个打开模块的函数指针,这个结构体也作为structhw_module_t结构体的一个成员
  41. /**************************************************************************/
  42. staticstructhw_module_methods_tled_module_methods={
  43. open:led_device_open
  44. };
  45. 结构体三structhw_device_t表示一个硬件设备
  46. hardware/libhardware/include/hardware/hardware.h中定义
  47. typedefstructhw_device_t{
  48. uint32_ttag;/**tagmustbeinitializedtoHARDWARE_DEVICE_TAG*/
  49. uint32_tversion;//hw_device_t的版本号
  50. structhw_module_t*module;//引用这个设备属于的硬件模块
  51. uint32_treserved[12];//填充保留字节
  52. int(*close)(structhw_device_t*device);//关闭设备
  53. }hw_device_t;
  54. structhw_device_t也是需要被具体实现的结构体包含使用,一个硬件模块可以包含多个硬件设备
  55. /*****************************************************************************/
  56. led.h
  57. structled_control_device_t{
  58. structhw_device_tcommon;
  59. intfd;
  60. /*supportingcontrolAPIsgohere*/
  61. int(*set_on)(structled_control_device_t*dev,int32_tled);
  62. int(*set_off)(structled_control_device_t*dev,int32_tled);
  63. };
[csharp] view plain copy
  1. <spanstyle="font-size:12px;">结构体一structhw_module_t结构体用于定义硬件模块的格式
  2. typedefstructhw_module_t{
  3. uint32_ttag;/**tagmustbeinitializedtoHARDWARE_MODULE_TAG*/
  4. uint16_tversion_major;/**主版本号*/
  5. uint16_tversion_minor;/**次版本号*/
  6. constchar*id;/*模块标识*/
  7. constchar*name;//模块的名称
  8. constchar*author;//模块的作者
  9. structhw_module_methods_t*methods;/**模块方法*/
  10. void*dso;/**模块的dso*/
  11. uint32_treserved[32-7];/**填充字节,为以后使用*/
  12. }hw_module_t;
  13. /********************************************************************/
  14. 在led.h里定义
  15. structled_module_t{
  16. structhw_module_tcommon;
  17. };
  18. /*
  19. *struchhw_module_t结构体定义了一个硬件模块的信息,在各个具体硬件模块中,需要以这个结构体为第一个成员,即表示继承了这个结构体。
  20. */
  21. 在led.cpp里定义
  22. extern"C"conststructled_module_tHAL_MODULE_INFO_SYM={
  23. common:{
  24. tag:HARDWARE_MODULE_TAG,
  25. version_major:1,
  26. version_minor:0,
  27. id:LED_HARDWARE_MODULE_ID,
  28. name:"SampleLEDStub",
  29. author:"TheForlinxOpenSourceProject",
  30. methods:&led_module_methods,
  31. }
  32. };
  33. 结构体二structhw_module_methods_t是一个表示模块方法的结构体。
  34. hardware/libhardware/include/hardware/hardware.h中定义
  35. typedefstructhw_module_methods_t{
  36. /**打开设备的方法*/
  37. int(*open)(conststructhw_module_t*module,constchar*id,
  38. structhw_device_t**device);
  39. }hw_module_methods_t;
  40. structhw_module_methods_t结构体只包含了一个打开模块的函数指针,这个结构体也作为structhw_module_t结构体的一个成员
  41. /**************************************************************************/
  42. staticstructhw_module_methods_tled_module_methods={
  43. open:led_device_open
  44. };
  45. 结构体三structhw_device_t表示一个硬件设备
  46. hardware/libhardware/include/hardware/hardware.h中定义
  47. typedefstructhw_device_t{
  48. uint32_ttag;/**tagmustbeinitializedtoHARDWARE_DEVICE_TAG*/
  49. uint32_tversion;//hw_device_t的版本号
  50. structhw_module_t*module;//引用这个设备属于的硬件模块
  51. uint32_treserved[12];//填充保留字节
  52. int(*close)(structhw_device_t*device);//关闭设备
  53. }hw_device_t;
  54. structhw_device_t也是需要被具体实现的结构体包含使用,一个硬件模块可以包含多个硬件设备
  55. /*****************************************************************************/
  56. led.h
  57. structled_control_device_t{
  58. structhw_device_tcommon;
  59. intfd;
  60. /*supportingcontrolAPIsgohere*/
  61. int(*set_on)(structled_control_device_t*dev,int32_tled);
  62. int(*set_off)(structled_control_device_t*dev,int32_tled);
  63. };
  64. </span>

  1. 硬件的具体调用流程如下
  2. 1)通过id得到硬件模块
  3. #defineLED_HARDWARE_MODULE_ID"led"
  4. 2)从硬件模块中得到hw_module_methods_t,打开得到硬件设备hw_device_t
  5. open:led_device_open
  6. staticintled_device_open(conststructhw_module_t*module,constchar*name,
  7. structhw_device_t**device)
  8. {
  9. //打开后得到设备硬件dev
  10. structled_control_device_t*dev;
  11. dev=(structled_control_device_t*)malloc(sizeof(*dev));
  12. memset(dev,0,sizeof(*dev));
  13. dev->common.tag=HARDWARE_DEVICE_TAG;
  14. dev->common.version=0;//hw_module_t的版本号
  15. dev->common.module=(structhw_module_t*)module;
  16. dev->common.close=led_device_close;
  17. /********调用hw_device_t中的各个方法****************/
  18. dev->set_on=led_on;
  19. dev->set_off=led_off;
  20. *device=&dev->common;//引用这个设备属于的硬件模块
  21. g_fd=open("/dev/leds0",0);
  22. if(g_fd<0)
  23. {
  24. g_fd=open("/dev/leds",0);
  25. }
  26. if(g_fd<0)
  27. {
  28. LOGI("LEDStub:open/dev/ledsfail.");
  29. }else{
  30. LOGI("LEDStub:open/dev/ledssuccess.");
  31. }return0;
  32. }
  33. 3)调用hw_device_t中的各个方法
  34. 4)通过hw_device_t的close关闭设备

在以上流程中还需要libhardware提供一个得到模块的函数,hw_get_module 在hardware.h中定义

/**

* Get the module info associated with a module by id.

* @return: 0 == success, <0 == error and *pHmi == NULL

*/

int hw_get_module(const char *id, const struct hw_module_t **module);

[csharp] view plain copy
  1. <spanstyle="font-size:12px;">hw_get_module()函数的实现在hardware/libhardware/hardware.c文件中实现
  2. inthw_get_module(constchar*id,conststructhw_module_t**module)
  3. {
  4. intstatus;
  5. inti;
  6. conststructhw_module_t*hmi=NULL;
  7. charprop[PATH_MAX];
  8. charpath[PATH_MAX];
  9. /*
  10. *Herewerelyonthefactthatcallingdlopenmultipletimeson
  11. *thesame.sowillsimplyincrementarefcount(andnotload
  12. *anewcopyofthelibrary).
  13. *Wealsoassumethatdlopen()isthread-safe.
  14. */
  15. /*Loopthroughtheconfigurationvariantslookingforamodule*/
  16. for(i=0;i<HAL_VARIANT_KEYS_COUNT+1;i++){
  17. if(i<HAL_VARIANT_KEYS_COUNT){
  18. if(property_get(variant_keys[i],prop,NULL)==0){
  19. continue;
  20. }
  21. snprintf(path,sizeof(path),"%s/%s.%s.so",
  22. HAL_LIBRARY_PATH1,id,prop);//得到模块的名称
  23. if(access(path,R_OK)==0)break;
  24. snprintf(path,sizeof(path),"%s/%s.%s.so",
  25. HAL_LIBRARY_PATH2,id,prop);
  26. if(access(path,R_OK)==0)break;
  27. }else{
  28. snprintf(path,sizeof(path),"%s/%s.default.so",//得到默认模块的名称
  29. HAL_LIBRARY_PATH1,id);
  30. if(access(path,R_OK)==0)break;//找到模块然后退出
  31. }
  32. }
  33. status=-ENOENT;
  34. if(i<HAL_VARIANT_KEYS_COUNT+1){
  35. /*loadthemodule,ifthisfails,we'redoomed,andweshouldnottry
  36. *toloadadifferentvariant.*/
  37. status=load(id,path,module);
  38. }
  39. returnstatus;
  40. }
  41. hw_get_module()函数执行的是一个动态查找的过程,找到硬件动态库*.so打开,当没有动态库的时候,将打开默认的库文件*default.so
  42. 在hw_get_module()函数中调用的load()函数,在hardware.c中其主要内容如下
  43. /**
  44. *Loadthefiledefinedbythevariantandifsuccessful
  45. *returnthedlopenhandleandthehmi.
  46. *@return0=success,!0=failure.
  47. */
  48. staticintload(constchar*id,
  49. constchar*path,
  50. conststructhw_module_t**pHmi)
  51. {
  52. intstatus;
  53. void*handle;
  54. structhw_module_t*hmi;
  55. /*
  56. *loadthesymbolsresolvingundefinedsymbolsbefore
  57. *dlopenreturns.SinceRTLD_GLOBALisnotor'dinwith
  58. *RTLD_NOWtheexternalsymbolswillnotbeglobal
  59. */
  60. handle=dlopen(path,RTLD_NOW);进行动态库的打开
  61. if(handle==NULL){
  62. charconst*err_str=dlerror();
  63. LOGE("load:module=%s\n%s",path,err_str?err_str:"unknown");
  64. status=-EINVAL;
  65. gotodone;
  66. }
  67. /*Gettheaddressofthestructhal_module_info.*/
  68. constchar*sym=HAL_MODULE_INFO_SYM_AS_STR;
  69. hmi=(structhw_module_t*)dlsym(handle,sym);
  70. if(hmi==NULL){
  71. LOGE("load:couldn'tfindsymbol%s",sym);
  72. status=-EINVAL;
  73. gotodone;
  74. }
  75. /*Checkthattheidmatches*/
  76. if(strcmp(id,hmi->id)!=0){
  77. LOGE("load:id=%s!=hmi->id=%s",id,hmi->id);
  78. status=-EINVAL;
  79. gotodone;
  80. }
  81. hmi->dso=handle;
  82. /*success*/
  83. status=0;
  84. done:
  85. if(status!=0){
  86. hmi=NULL;
  87. if(handle!=NULL){
  88. dlclose(handle);
  89. handle=NULL;
  90. }
  91. }else{
  92. LOGV("loadedHALid=%spath=%shmi=%phandle=%p",
  93. id,path,*pHmi,handle);
  94. }
  95. *pHmi=hmi;
  96. returnstatus;
  97. }
  98. /********************************************************************/
  99. load()函数实际上执行了一个动态的打开dlopen和动态取出符号dlsym的过程,这个过程解除了在编译时的Android本地框架对特有硬件模块依赖
  100. 硬件模块的调用方式如下
  101. /----------------------------------------------------------------------------------------------------/
  102. xxx_module_t*gModule;
  103. xxx_device_t*gDevice;
  104. {
  105. xxx_module_tconst*module;
  106. err=hw_get_module(XXXX_HARDWARE_MODULE_ID,(consthw_moeule_t**)&module);
  107. gModule=(xxxx_module_t*)module;
  108. gModule->ModuleFunction();//调用模块中的函数
  109. gDevice->DeviceFunction();//调用设备中的函数
  110. }
  111. 通常情况下,硬件模块调用者是Android中的本地框架层
  112. libhardware的接口头文件中,除了hardware.h之外,其他各个头文件是相互并列的,每一个文件表示了一种硬件抽象层
  113. lights.h背光和指示灯模块
  114. copybit.h位复制模块
  115. overlay.h叠加视频抽象层模块
  116. qemud.hQEMU的守护进程模块
  117. sensors.h传感器模块
  118. gralloc.h用于显示的模块
  119. gprs.hGPRS模块</span>

2直接接口方式

hardware_legacy库中提供了一些各自独立的接口,由用户实现后形成库,被直接连接到系统中,这是实现硬件抽象层最直接的方式。

hardware/libhardware_legacy/include/hardware_legacy

hardware_legacy库中包含了几个C接口的文件,power,wifi,vibrator,在开发一个新的硬件系统时,可以根据需要去实现这几个库,也可以使用系统默认的实现方式。

这种做法实际上并没有完全将硬件抽象层和Android的本地框架分开,其好处是接口的定义和实现比较简单

3 C++的继承实现方式

使用C++类的继承方式实现硬件抽象层


android HAL介绍_第3张图片

在这种实现方式中,具体的硬件抽象层通常要求被编译成为指定的名称的动态库,由本地框架库连接它,通用的实现被编译成静态库*.a,本地框架库连接这些静态库的时候,其实就是包含了它们在其中。使用特定硬件抽象层还是通用的硬件抽象层,通常需要根据宏来指定

CameraAudio系统使用的是C++类的继承方式。

更多相关文章

  1. android的四层体系结构,基于mvc三层结构浅析
  2. Android是什么 之三手机之硬件形态
  3. Android架构分析之LOG模块
  4. Android Camera源码函数结构
  5. Android应用程序结构介绍
  6. Android WiFi 架构总览(模块及接口)
  7. Android系统结构

随机推荐

  1. stream audio on android 音频流 android
  2. Android布局学习之――按钮居中
  3. Modern Cross Platform Development
  4. 现在的行情很不好?顺便求职
  5. Android Fragment 问题汇总
  6. Android studio :适配器控件
  7. Android(安卓)Jetpack架构组件(二)带你了解
  8. Android 判断应用是否安装
  9. android 简单拨号器 代码
  10. android 弹出框无边款