现在的位置: 首页 > 综合 > 正文

android HAL介绍

2018年04月04日 ⁄ 综合 ⁄ 共 11382字 ⁄ 字号 评论关闭

目录(?)[+]

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

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

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


硬件抽象层接口方法


1 hardware模块的方式

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

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

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

led.h中定义的id

#define LED_HARDWARE_MODULE_ID "led"

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

hardware/libhardware/include/hardware/hardware.h

/**

 * 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.

 */


[csharp] view
plain
copy

  1. 结构体一 struct hw_module_t 结构体用于定义硬件模块的格式  
  2. typedef struct hw_module_t {  
  3.     uint32_t tag;    /** tag must be initialized to HARDWARE_MODULE_TAG */  
  4.     uint16_t version_major; /** 主版本号 */  
  5.     uint16_t version_minor;/** 次版本号*/  
  6.     const char *id;   /*模块标识*/  
  7.     const char *name;//模块的名称   
  8.     const char *author;//模块的作者   
  9.     struct hw_module_methods_t* methods;   /** 模块方法*/  
  10.     void* dso;  /** 模块的 dso */  
  11.     uint32_t reserved[32-7];    /** 填充字节,为以后使用*/  
  12. } hw_module_t;  
  13. /********************************************************************/  
  14. 在led.h里定义  
  15. struct led_module_t {  
  16.    struct hw_module_t common;  
  17. };  
  18. /* 
  19. *struch hw_module_t结构体定义了一个硬件模块的信息,在各个具体硬件模块中,需要以这个结构体为第一个成员,即表示继承了这个结构体。 
  20. */  
  21. 在led.cpp里定义  
  22. extern "C" const struct led_module_t HAL_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: "Sample LED Stub",  
  29.         author: "The Forlinx Open Source Project",  
  30.         methods: &led_module_methods,  
  31.     }  
  32. };  
  33. 结构体二 struct hw_module_methods_t 是一个表示模块方法的结构体。  
  34. hardware/libhardware/include/hardware/hardware.h中定义  
  35.   
  36. typedef struct hw_module_methods_t {  
  37.     /** 打开设备的方法 */  
  38.     int (*open)(const struct hw_module_t* module, const char* id,  
  39.             struct hw_device_t** device);  
  40. } hw_module_methods_t;  
  41.   
  42. struct hw_module_methods_t结构体只包含了一个打开模块的函数指针,这个结构体也作为struct hw_module_t结构体的一个成员  
  43. /**************************************************************************/  
  44. static struct hw_module_methods_t led_module_methods = {  
  45.     open: led_device_open  
  46. };  
  47.   
  48. 结构体三 struct hw_device_t 表示一个硬件设备  
  49. hardware/libhardware/include/hardware/hardware.h中定义  
  50.   
  51.   
  52. typedef struct hw_device_t {  
  53.     uint32_t tag;  /** tag must be initialized to HARDWARE_DEVICE_TAG */  
  54.     uint32_t version;//hw_device_t的版本号   
  55.     struct hw_module_t* module;//引用这个设备属于的硬件模块   
  56.     uint32_t reserved[12];//填充保留字节   
  57.     int (*close)(struct hw_device_t* device);//关闭设备   
  58. } hw_device_t;  
  59.   
  60. struct hw_device_t 也是需要被具体实现的结构体包含使用,一个硬件模块可以包含多个硬件设备  
  61. /*****************************************************************************/  
  62. led.h  
  63. struct led_control_device_t {  
  64.    struct hw_device_t common;  
  65.    int fd;  
  66.   
  67.    /* supporting control APIs go here */  
  68.    int (*set_on)(struct led_control_device_t *dev, int32_t led);  
  69.    int (*set_off)(struct led_control_device_t *dev, int32_t led);  
  70. };  
[csharp] view
plain
copy

  1. <span style="font-size:12px;">结构体一 struct hw_module_t 结构体用于定义硬件模块的格式  
  2. typedef struct hw_module_t {  
  3.     uint32_t tag;    /** tag must be initialized to HARDWARE_MODULE_TAG */  
  4.     uint16_t version_major; /** 主版本号 */  
  5.     uint16_t version_minor;/** 次版本号*/  
  6.     const char *id;   /*模块标识*/  
  7.     const char *name;//模块的名称  
  8.     const char *author;//模块的作者  
  9.     struct hw_module_methods_t* methods;   /** 模块方法*/  
  10.     void* dso;  /** 模块的 dso */  
  11.     uint32_t reserved[32-7];    /** 填充字节,为以后使用*/  
  12. } hw_module_t;  
  13. /********************************************************************/  
  14. 在led.h里定义  
  15. struct led_module_t {  
  16.    struct hw_module_t common;  
  17. };  
  18. /* 
  19. *struch hw_module_t结构体定义了一个硬件模块的信息,在各个具体硬件模块中,需要以这个结构体为第一个成员,即表示继承了这个结构体。 
  20. */  
  21. 在led.cpp里定义  
  22. extern "C" const struct led_module_t HAL_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: "Sample LED Stub",  
  29.         author: "The Forlinx Open Source Project",  
  30.         methods: &led_module_methods,  
  31.     }  
  32. };  
  33. 结构体二 struct hw_module_methods_t 是一个表示模块方法的结构体。  
  34. hardware/libhardware/include/hardware/hardware.h中定义  
  35.   
  36. typedef struct hw_module_methods_t {  
  37.     /** 打开设备的方法 */  
  38.     int (*open)(const struct hw_module_t* module, const char* id,  
  39.             struct hw_device_t** device);  
  40. } hw_module_methods_t;  
  41.   
  42. struct hw_module_methods_t结构体只包含了一个打开模块的函数指针,这个结构体也作为struct hw_module_t结构体的一个成员  
  43. /**************************************************************************/  
  44. static struct hw_module_methods_t led_module_methods = {  
  45.     open: led_device_open  
  46. };  
  47.   
  48. 结构体三 struct hw_device_t 表示一个硬件设备  
  49. hardware/libhardware/include/hardware/hardware.h中定义  
  50.   
  51.   
  52. typedef struct hw_device_t {  
  53.     uint32_t tag;  /** tag must be initialized to HARDWARE_DEVICE_TAG */  
  54.     uint32_t version;//hw_device_t的版本号  
  55.     struct hw_module_t* module;//引用这个设备属于的硬件模块  
  56.     uint32_t reserved[12];//填充保留字节  
  57.     int (*close)(struct hw_device_t* device);//关闭设备  
  58. } hw_device_t;  
  59.   
  60. struct hw_device_t 也是需要被具体实现的结构体包含使用,一个硬件模块可以包含多个硬件设备  
  61. /*****************************************************************************/  
  62. led.h  
  63. struct led_control_device_t {  
  64.    struct hw_device_t common;  
  65.    int fd;  
  66.   
  67.    /* supporting control APIs go here */  
  68.    int (*set_on)(struct led_control_device_t *dev, int32_t led);  
  69.    int (*set_off)(struct led_control_device_t *dev, int32_t led);  
  70. };  
  71. </span>  

  1. 硬件的具体调用流程如下  
  2. 1)通过id得到硬件模块  
  3. #define LED_HARDWARE_MODULE_ID "led"   
  4. 2)从硬件模块中得到hw_module_methods_t,打开得到硬件设备hw_device_t  
  5.  open: led_device_open  
  6.   
  7. static int led_device_open(const struct hw_module_t* module, const char* name,  
  8.         struct hw_device_t** device)   
  9. {  
  10.     //打开后得到设备硬件dev   
  11.     struct led_control_device_t *dev;  
  12.     dev = (struct led_control_device_t *)malloc(sizeof(*dev));  
  13.     memset(dev, 0, sizeof(*dev));  
  14.   
  15.     dev->common.tag =  HARDWARE_DEVICE_TAG;  
  16.     dev->common.version = 0;//hw_module_t的版本号   
  17.     dev->common.module = (struct hw_module_t*)module;  
  18.     dev->common.close = led_device_close;  
  19.   
  20.   
  21. /********调用hw_device_t中的各个方法****************/  
  22.     dev->set_on = led_on;  
  23.     dev->set_off = led_off;  
  24. *device = &dev->common;//引用这个设备属于的硬件模块   
  25. g_fd = open("/dev/leds0", 0);
  26. if (g_fd < 0) 
  27. g_fd = open("/dev/leds", 0);
  28. if(g_fd<0) 
  29. LOGI("LED Stub: open /dev/leds fail."); 
  30. }else { 
  31. LOGI("LED Stub: open /dev/leds success ."); 
  32. }return 0;
  33. }
  34. 3)调用hw_device_t中的各个方法
  35. 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. <span style="font-size:12px;">hw_get_module()函数的实现在hardware/libhardware/hardware.c文件中实现  
  2. int hw_get_module(const char *id, const struct hw_module_t **module)   
  3. {  
  4.     int status;  
  5.     int i;  
  6.     const struct hw_module_t *hmi = NULL;  
  7.     char prop[PATH_MAX];  
  8.     char path[PATH_MAX];  
  9.   
  10.     /* 
  11.      * Here we rely on the fact that calling dlopen multiple times on 
  12.      * the same .so will simply increment a refcount (and not load 
  13.      * a new copy of the library). 
  14.      * We also assume that dlopen() is thread-safe. 
  15.      */  
  16.   
  17.     /* Loop through the configuration variants looking for a module */  
  18.     for (i=0 ; i<HAL_VARIANT_KEYS_COUNT+1 ; i++) {  
  19.         if (i < HAL_VARIANT_KEYS_COUNT) {  
  20.             if (property_get(variant_keys[i], prop, NULL) == 0) {  
  21.                 continue;  
  22.             }  
  23.             snprintf(path, sizeof(path), "%s/%s.%s.so",  
  24.                     HAL_LIBRARY_PATH1, id, prop);//得到模块的名称  
  25.             if (access(path, R_OK) == 0) break;  
  26.   
  27.             snprintf(path, sizeof(path), "%s/%s.%s.so",  
  28.                      HAL_LIBRARY_PATH2, id, prop);  
  29.             if (access(path, R_OK) == 0) break;  
  30.         } else {  
  31.             snprintf(path, sizeof(path), "%s/%s.default.so",//得到默认模块的名称  
  32.                      HAL_LIBRARY_PATH1, id);  
  33.             if (access(path, R_OK) == 0) break;//找到模块然后退出  
  34.         }  
  35.     }  
  36.   
  37.     status = -ENOENT;  
  38.     if (i < HAL_VARIANT_KEYS_COUNT+1) {  
  39.         /* load the module, if this fails, we're doomed, and we should not try 
  40.          * to load a different variant. */  
  41.         status = load(id, path, module);  
  42.     }  
  43.   
  44.     return status;  
  45. }  
  46.   
  47. hw_get_module()函数执行的是一个动态查找的过程,找到硬件动态库*.so打开,当没有动态库的时候,将打开默认的库文件*default.so  
  48. 在hw_get_module()函数中调用的load()函数,在hardware.c中其主要内容如下  
  49. /** 
  50.  * Load the file defined by the variant and if successful 
  51.  * return the dlopen handle and the hmi. 
  52.  * @return 0 = success, !0 = failure. 
  53.  */  
  54. static int load(const char *id,  
  55.         const char *path,  
  56.         const struct hw_module_t **pHmi)  
  57. {  
  58.     int status;  
  59.     void *handle;  
  60.     struct hw_module_t *hmi;  
  61.   
  62.     /* 
  63.      * load the symbols resolving undefined symbols before 
  64.      * dlopen returns. Since RTLD_GLOBAL is not or'd in with 
  65.      * RTLD_NOW the external symbols will not be global 
  66.      */  
  67.     handle = dlopen(path, RTLD_NOW);进行动态库的打开  
  68.     if (handle == NULL) {  
  69.         char const *err_str = dlerror();  
  70.         LOGE("load: module=%s\n%s", path, err_str?err_str:"unknown");  
  71.         status = -EINVAL;  
  72.         goto done;  
  73.     }  
  74.   
  75.     /* Get the address of the struct hal_module_info. */  
  76.     const char *sym = HAL_MODULE_INFO_SYM_AS_STR;  
  77.     hmi = (struct hw_module_t *)dlsym(handle, sym);  
  78.     if (hmi == NULL) {  
  79.         LOGE("load: couldn't find symbol %s", sym);  
  80.         status = -EINVAL;  
  81.         goto done;  
  82.     }  
  83.   
  84.     /* Check that the id matches */  
  85.     if (strcmp(id, hmi->id) != 0) {  
  86.         LOGE("load: id=%s != hmi->id=%s", id, hmi->id);  
  87.         status = -EINVAL;  
  88.         goto done;  
  89.     }  
  90.   
  91.     hmi->dso = handle;  
  92.   
  93.     /* success */  
  94.     status = 0;  
  95.   
  96.     done:  
  97.     if (status != 0) {  
  98.         hmi = NULL;  
  99.         if (handle != NULL) {  
  100.             dlclose(handle);  
  101.             handle = NULL;  
  102.         }  
  103.     } else {  
  104.         LOGV("loaded HAL id=%s path=%s hmi=%p handle=%p",  
  105.                 id, path, *pHmi, handle);  
  106.     }  
  107.   
  108.     *pHmi = hmi;  
  109.   
  110.     return status;  
  111. }  
  112. /********************************************************************/  
  113. load()函数实际上执行了一个动态的打开dlopen和动态取出符号dlsym的过程,这个过程解除了在编译时的Android本地框架对特有硬件模块依赖  
  114. 硬件模块的调用方式如下  
  115. /----------------------------------------------------------------------------------------------------/  
  116. xxx_module_t    *gModule;  
  117. xxx_device_t        *gDevice;  
  118. {  
  119.     xxx_module_t const *module;  
  120.     err = hw_get_module(XXXX_HARDWARE_MODULE_ID, (const hw_moeule_t **)&module);  
  121.     gModule = (xxxx_module_t *)module;  
  122.   
  123. gModule->ModuleFunction();//调用模块中的函数  
  124. gDevice->DeviceFunction();//调用设备中的函数  
  125. }  
  126. 通常情况下,硬件模块调用者是Android中的本地框架层  
  127. libhardware的接口头文件中,除了hardware.h之外,其他各个头文件是相互并列的,每一个文件表示了一种硬件抽象层  
  128. lights.h    背光和指示灯模块  
  129. copybit.h       位复制模块  
  130. overlay.h           叠加视频抽象层模块  
  131. qemud.h         QEMU的守护进程模块  
  132. sensors.h           传感器模块  
  133. gralloc.h           用于显示的模块  
  134. gprs.h          GPRS模块</span>  

直接接口方式

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

hardware/libhardware_legacy/include/hardware_legacy

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

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

3 C++的继承实现方式

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



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

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

抱歉!评论已关闭.