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

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

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


硬件抽象层接口方法


1hardware模块的方式

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

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

在使用硬件抽象层的过程中,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 print ?
  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. };

  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);

hw_get_module()函数的实现在hardware/libhardware/hardware.c文件中实现int hw_get_module(const char *id, const struct hw_module_t **module) {    int status;    int i;    const struct hw_module_t *hmi = NULL;    char prop[PATH_MAX];    char path[PATH_MAX];    /*     * Here we rely on the fact that calling dlopen multiple times on     * the same .so will simply increment a refcount (and not load     * a new copy of the library).     * We also assume that dlopen() is thread-safe.     */    /* Loop through the configuration variants looking for a module */    for (i=0 ; i<HAL_VARIANT_KEYS_COUNT+1 ; i++) {        if (i < HAL_VARIANT_KEYS_COUNT) {            if (property_get(variant_keys[i], prop, NULL) == 0) {                continue;            }            snprintf(path, sizeof(path), "%s/%s.%s.so",                    HAL_LIBRARY_PATH1, id, prop);//得到模块的名称            if (access(path, R_OK) == 0) break;            snprintf(path, sizeof(path), "%s/%s.%s.so",                     HAL_LIBRARY_PATH2, id, prop);            if (access(path, R_OK) == 0) break;        } else {            snprintf(path, sizeof(path), "%s/%s.default.so",//得到默认模块的名称                     HAL_LIBRARY_PATH1, id);            if (access(path, R_OK) == 0) break;//找到模块然后退出        }    }    status = -ENOENT;    if (i < HAL_VARIANT_KEYS_COUNT+1) {        /* load the module, if this fails, we're doomed, and we should not try         * to load a different variant. */        status = load(id, path, module);    }    return status;}hw_get_module()函数执行的是一个动态查找的过程,找到硬件动态库*.so打开,当没有动态库的时候,将打开默认的库文件*default.so在hw_get_module()函数中调用的load()函数,在hardware.c中其主要内容如下/** * Load the file defined by the variant and if successful * return the dlopen handle and the hmi. * @return 0 = success, !0 = failure. */static int load(const char *id,        const char *path,        const struct hw_module_t **pHmi){    int status;    void *handle;    struct hw_module_t *hmi;    /*     * load the symbols resolving undefined symbols before     * dlopen returns. Since RTLD_GLOBAL is not or'd in with     * RTLD_NOW the external symbols will not be global     */    handle = dlopen(path, RTLD_NOW);进行动态库的打开    if (handle == NULL) {        char const *err_str = dlerror();        LOGE("load: module=%s\n%s", path, err_str?err_str:"unknown");        status = -EINVAL;        goto done;    }    /* Get the address of the struct hal_module_info. */    const char *sym = HAL_MODULE_INFO_SYM_AS_STR;    hmi = (struct hw_module_t *)dlsym(handle, sym);    if (hmi == NULL) {        LOGE("load: couldn't find symbol %s", sym);        status = -EINVAL;        goto done;    }    /* Check that the id matches */    if (strcmp(id, hmi->id) != 0) {        LOGE("load: id=%s != hmi->id=%s", id, hmi->id);        status = -EINVAL;        goto done;    }    hmi->dso = handle;    /* success */    status = 0;    done:    if (status != 0) {        hmi = NULL;        if (handle != NULL) {            dlclose(handle);            handle = NULL;        }    } else {        LOGV("loaded HAL id=%s path=%s hmi=%p handle=%p",                id, path, *pHmi, handle);    }    *pHmi = hmi;    return status;}/********************************************************************/load()函数实际上执行了一个动态的打开dlopen和动态取出符号dlsym的过程,这个过程解除了在编译时的Android本地框架对特有硬件模块依赖硬件模块的调用方式如下/----------------------------------------------------------------------------------------------------/xxx_module_t*gModule;xxx_device_t*gDevice;{xxx_module_t const *module;err = hw_get_module(XXXX_HARDWARE_MODULE_ID, (const hw_moeule_t **)&module);gModule = (xxxx_module_t *)module;gModule->ModuleFunction();//调用模块中的函数gDevice->DeviceFunction();//调用设备中的函数}通常情况下,硬件模块调用者是Android中的本地框架层libhardware的接口头文件中,除了hardware.h之外,其他各个头文件是相互并列的,每一个文件表示了一种硬件抽象层lights.h背光和指示灯模块copybit.h位复制模块overlay.h叠加视频抽象层模块qemud.hQEMU的守护进程模块sensors.h传感器模块gralloc.h用于显示的模块gprs.hGPRS模块

2 直接接口方式

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

hardware/libhardware_legacy/include/hardware_legacy

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

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

3 C++的继承实现方式

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



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

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

更多相关文章

  1. React Native 中的 Android(安卓)原生模块
  2. Android入门教程(四)之------Android工程目录结构介绍
  3. Android(安卓)工程目录结构介绍
  4. Android(安卓)源代码结构
  5. Google Android应用开发04 Android应用程序结构
  6. android程序目录结构及分析
  7. Amazon 的平板能否威胁 Google
  8. Android——消息机制中的Message Pool是个什么鬼,Message Pool会
  9. 20172324 2017-2018《程序设计与数据结构》第十一周学习总结

随机推荐

  1. android
  2. Android中的数据传递之Parcelable接口
  3. Android(安卓)开发中使用 SQLite 数据库
  4. Android(安卓)开发一定要看的15个实战项
  5. Android(安卓)安全攻防(一):SEAndroid的编译
  6. Android文件操作中的openFileOutPut和ope
  7. 浅谈android的selector,背景选择器
  8. Android入门 — 模拟器的创建和运行
  9. [Android]仿Windows Phone的启动器,无广告
  10. Android消息推送实现