Android HAL层分析

Android的HAL是为了保护一些硬件提供商的知识产权而提出的,是为了避开Linux的GPL束缚。思路是把控制硬件的动作都放到了Android HAL中,而linux driver仅仅完成一些简单的数据交互作用,甚至把硬件寄存器空间直接映射到user space。而Android是基于Aparch的license,因此硬件厂商可以只提供二进制代码,所以说Android只是一个开放的平台,并不是一个开源的平台。

Android的硬件抽象层,简单来说,就是对Linux内核驱动程序的封装,向上提供接口,屏蔽低层的实现细节。也就是说,把对硬件的支持分成了两层,一层放在用户空间(User Space),一层放在内核空间(Kernel Space),其中,硬件抽象层运行在用户空间,而Linux内核驱动程序运行在内核空间。为什么要这样安排呢?把硬件抽象层和内核驱动整合在一起放在内核空间不可行吗?从技术实现的角度来看,是可以的,然而从商业的角度来看,把对硬件的支持逻辑都放在内核空间,可能会损害厂家的利益。我们知道,Linux内核源代码版权遵循GNU License,而Android源代码版权遵循Apache License,前者在发布产品时,必须公布源代码,而后者无须发布源代码。如果把对硬件支持的所有代码都放在Linux驱动层,那就意味着发布时要公开驱动程序的源代码,而公开源代码就意味着把硬件的相关参数和实现都公开了,在手机市场竞争激烈的今天,这对厂家来说,损害是非常大的。因此,Android才会想到把对硬件的支持分成硬件抽象层和内核驱动层,内核驱动层只提供简单的访问硬件逻辑,例如读写硬件寄存器的通道,至于从硬件中读到了什么值或者写了什么值到硬件中的逻辑,都放在硬件抽象层中去了,这样就可以把商业秘密隐藏起来了。也正是由于这个分层的原因,Android被踢出了Linux内核主线代码树中。大家想想,Android放在内核空间的驱动程序对硬件的支持是不完整的,把Linux内核移植到别的机器上去时,由于缺乏硬件抽象层的支持,硬件就完全不能用了,这也是为什么说Android是开放系统而不是开源系统的原因。

     撇开这些争论,学习Android硬件抽象层,对理解整个Android整个系统,都是极其有用的,因为它从下到上涉及到了Android系统的硬件驱动层、硬件抽象层、运行时库和应用程序框架层等等,下面这个图阐述了硬件抽象层在Android系统中的位置,以及它和其它层的关系:


     在学习Android硬件抽象层的过程中,我们将会学习如何在内核空间编写硬件驱动程序、如何在硬件抽象层中添加接口支持访问硬件、如何在系统启动时提供硬件访问服务以及 如何编写JNI使得可以通过Java接口来访问硬件,而作为中间的一个小插曲,我们还将学习一下如何在Android系统中添加一个C可执行程序来访问硬件驱动程序。



一、代码文件介绍

/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 是将 *.so 文件当作shared library来使用,在runtime(JNI 部份)以 direct function call 使用 HAL module。通过直接函数调用的方式,来操作驱动程序。当然,应用程序也可以不需要通过 JNI 的方式进行,直接加载 *.so (dlopen)的做法调用*.so 里的符号(symbol)也是一种方式。总而言之是没有经过封装,上层可以直接操作硬件。

    现在的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层结构框架,通过几个接口访问硬件从而统一了调用方式。

Android的HAL的实现需要通过JNI(JavaNative Interface),JNI简单来说就是Java程序可以调用C/C++写的动态链接库,这样的话,HAL可以使用C/C++语言编写,效率更高。JNI->通用硬件模块->硬件模块->内核驱动接口,具体一点:JNI->libhardware.so->xxx.xxx.so->kernel,具体来说:android frameworks中JNI调用hardware.c中定义的hw_get_module函数来获取硬件模块,然后调用硬件模块中的方法,硬件模块中的方法直接调用内核接口完成相关功能

在Android下访问HAL大致有以下两种方式:

   (1)Android的app可以直接通过service调用.so格式的jni

(2)经过Manager调用service

上面两种方法应该说是各有优缺点,第一种方法简单高效,但不正规。第二种方法实现起来比较复杂,但更符合目前的Android框架。第二种方法中,LegManager和LedService(java)在两个进程中,需要通过进程通讯的方式来通讯。

在现在的android框架中,这两种方式都存在,比如对于lights,是直接透过LightsService调用JNI,而对于sensor,中间则是通过SensorsManager

来调用JNI的。


三、源码分析

最近在看SurfaceFlinger,我们就以这个为切入点,我们来看下面这段代码,通过hw_get_module函数通过HAL层获取到module,然后通过gralloc_open函数通过module来获取device。

  1. GraphicBufferAllocator::GraphicBufferAllocator()  
  2.     : mAllocDev(0)  
  3. {  
  4.     hw_module_t const* module;  
  5.     int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);  
  6.     if (err == 0) {  
  7.         gralloc_open(module, &mAllocDev);  
  8.     }  
  9. }  

3.1 hw_get_modeule

我们先来看hardware/libhardware/hardware.c中的hw_get_module函数,调用了hw_get_module_by_class函数。

  1. int hw_get_module(const char *id, const struct hw_module_t **module)  
  2. {  
  3.     return hw_get_module_by_class(id, NULL, module);  
  4. }  

我们配合上面的例子来分析hw_get_module函数,在GraphicBufferAllocator构造函数中,调用的hw_get_module函数,参数GRALLOC_HARDWARE_MODULE_ID我们看看是什么值

在hardware/libhardware/include/hardware/gralloc.h中定义了该宏

  1. #define GRALLOC_HARDWARE_MODULE_ID "gralloc"  

再来看下hw_get_module_by_class函数

  1. int hw_get_module_by_class(const char *class_id, const char *inst,  
  2.                            const struct hw_module_t **module)  
  3. {  
  4.     int i = 0;  
  5.     char prop[PATH_MAX] = {0};  
  6.     char path[PATH_MAX] = {0};  
  7.     char name[PATH_MAX] = {0};  
  8.     char prop_name[PATH_MAX] = {0};  
  9.   
  10.   
  11.     if (inst)  
  12.         snprintf(name, PATH_MAX, "%s.%s", class_id, inst);  
  13.     else  
  14.         strlcpy(name, class_id, PATH_MAX);//这个时候name就是gralloc  
  15.   
  16.     snprintf(prop_name, sizeof(prop_name), "ro.hardware.%s", name);//先获取ro.hardware.gralloc这个属性值  
  17.     if (property_get(prop_name, prop, NULL) > 0) {  
  18.         if (hw_module_exists(path, sizeof(path), name, prop) == 0) {//如果有这个值组成的动态库有,直接返回  
  19.             goto found;  
  20.         }  
  21.     }  
  22.   
  23.     /* Loop through the configuration variants looking for a module */  
  24.     for (i=0 ; i<HAL_VARIANT_KEYS_COUNT; i++) {//从variant_keys数组中获取其属性值,然后看能否找到其动态库  
  25.         if (property_get(variant_keys[i], prop, NULL) == 0) {  
  26.             continue;  
  27.         }  
  28.         if (hw_module_exists(path, sizeof(path), name, prop) == 0) {  
  29.             goto found;  
  30.         }  
  31.     }  
  32.   
  33.     /* Nothing found, try the default */  
  34.     if (hw_module_exists(path, sizeof(path), name, "default") == 0) {//最后还没找到直接用default传入  
  35.         goto found;  
  36.     }  
  37.   
  38.     return -ENOENT;  
  39.   
  40. found:  
  41.     /* load the module, if this fails, we're doomed, and we should not try 
  42.      * to load a different variant. */  
  43.     return load(class_id, path, module);  
  44. }  

我们再来看看hw_module_exists函数,用来看动态库是否存在,其中用到了HAL_LIBRARY_PATH1和HAL_LIBRARY_PATH1两个宏。然后将传进来的参数组合起来加上后缀名so,看看是否存在这样的so动态库。

  1. static int hw_module_exists(char *path, size_t path_len, const char *name,  
  2.                             const char *subname)  
  3. {  
  4.     snprintf(path, path_len, "%s/%s.%s.so",  
  5.              HAL_LIBRARY_PATH2, name, subname);  
  6.     if (access(path, R_OK) == 0)  
  7.         return 0;  
  8.   
  9.     snprintf(path, path_len, "%s/%s.%s.so",  
  10.              HAL_LIBRARY_PATH1, name, subname);  
  11.     if (access(path, R_OK) == 0)  
  12.         return 0;  
  13.   
  14.     return -ENOENT;  
  15. }  

下面我们看下两个宏

  1. #if defined(__LP64__)  
  2. #define HAL_LIBRARY_PATH1 "/system/lib64/hw"  
  3. #define HAL_LIBRARY_PATH2 "/vendor/lib64/hw"  
  4. #else  
  5. #define HAL_LIBRARY_PATH1 "/system/lib/hw"  
  6. #define HAL_LIBRARY_PATH2 "/vendor/lib/hw"  
  7. #endif  

我们再来看variant_keys数组中,用来获取属性的值,这个属性值是一个中间值。比如上面的例子应该是这样的"gralloc.属性值.so"

  1. static const char *variant_keys[] = {  
  2.     "ro.hardware",  /* This goes first so that it can pick up a different 
  3.                        file on the emulator. */  
  4.     "ro.product.board",  
  5.     "ro.board.platform",  
  6.     "ro.arch"  
  7. };  

最后如果还没找到,我们就用default,比如"gralloc.default.so"


最后找到了我们用load来加载,返回一个hw_modult_t类型的module

  1. static int load(const char *id,  
  2.         const char *path,  
  3.         const struct hw_module_t **pHmi)  
  4. {  
  5.     int status = -EINVAL;  
  6.     void *handle = NULL;  
  7.     struct hw_module_t *hmi = NULL;  
  8.   
  9.     /* 
  10.      * load the symbols resolving undefined symbols before 
  11.      * dlopen returns. Since RTLD_GLOBAL is not or'd in with 
  12.      * RTLD_NOW the external symbols will not be global 
  13.      */  
  14.     handle = dlopen(path, RTLD_NOW);  
  15.     if (handle == NULL) {  
  16.         char const *err_str = dlerror();  
  17.         ALOGE("load: module=%s\n%s", path, err_str?err_str:"unknown");  
  18.         status = -EINVAL;  
  19.         goto done;  
  20.     }  
  21.   
  22.     /* Get the address of the struct hal_module_info. */  
  23.     const char *sym = HAL_MODULE_INFO_SYM_AS_STR;  
  24.     hmi = (struct hw_module_t *)dlsym(handle, sym);  
  25.     if (hmi == NULL) {  
  26.         ALOGE("load: couldn't find symbol %s", sym);  
  27.         status = -EINVAL;  
  28.         goto done;  
  29.     }  
  30.   
  31.     /* Check that the id matches */  
  32.     if (strcmp(id, hmi->id) != 0) {  
  33.         ALOGE("load: id=%s != hmi->id=%s", id, hmi->id);  
  34.         status = -EINVAL;  
  35.         goto done;  
  36.     }  
  37.   
  38.     hmi->dso = handle;  
  39.   
  40.     /* success */  
  41.     status = 0;  
  42.   
  43.     done:  
  44.     if (status != 0) {  
  45.         hmi = NULL;  
  46.         if (handle != NULL) {  
  47.             dlclose(handle);  
  48.             handle = NULL;  
  49.         }  
  50.     } else {  
  51.         ALOGV("loaded HAL id=%s path=%s hmi=%p handle=%p",  
  52.                 id, path, *pHmi, handle);  
  53.     }  
  54.   
  55.     *pHmi = hmi;  
  56.   
  57.     return status;  
  58. }  

3.2 gralloc模块hal层实现

我们先来看看gralloc_module_t 这个结构体,先看下英文解释。每个硬件模块必须有一个数据结构name是HAL_MODULE_INFO_SYM,而且其中必须有一个成员变量是hw_modult_t类型的,而且必须是第一位。下面这个定义也是在gralloc.h中

  1. /** 
  2.  * Every hardware module must have a data structure named HAL_MODULE_INFO_SYM 
  3.  * and the fields of this data structure must begin with hw_module_t 
  4.  * followed by module specific information. 
  5.  */  
  6. typedef struct gralloc_module_t {  
  7.     struct hw_module_t common;  
  8.   
  9.     int (*unregisterBuffer)(struct gralloc_module_t const* module,  
  10.             buffer_handle_t handle);  
  11.   
  12.     int (*lock)(struct gralloc_module_t const* module,  
  13.             buffer_handle_t handle, int usage,  
  14.             int l, int t, int w, int h,  
  15.             void** vaddr);  
  16.   
  17.     int (*unlock)(struct gralloc_module_t const* module,  
  18.             buffer_handle_t handle);  
  19.   
  20.   
  21.     /* reserved for future use */  
  22.     int (*perform)(struct gralloc_module_t const* module,  
  23.             int operation, ... );  
  24.   
  25.     int (*lock_ycbcr)(struct gralloc_module_t const* module,  
  26.             buffer_handle_t handle, int usage,  
  27.             int l, int t, int w, int h,  
  28.             struct android_ycbcr *ycbcr);  
  29.   
  30.     int (*lockAsync)(struct gralloc_module_t const* module,  
  31.             buffer_handle_t handle, int usage,  
  32.             int l, int t, int w, int h,  
  33.             void** vaddr, int fenceFd);  
  34.   
  35.     int (*unlockAsync)(struct gralloc_module_t const* module,  
  36.             buffer_handle_t handle, int* fenceFd);  
  37.   
  38.     int (*lockAsync_ycbcr)(struct gralloc_module_t const* module,  
  39.             buffer_handle_t handle, int usage,  
  40.             int l, int t, int w, int h,  
  41.             struct android_ycbcr *ycbcr, int fenceFd);  
  42.   
  43.     /* reserved for future use */  
  44.     void* reserved_proc[3];  
  45. } gralloc_module_t;  

我们再来看下hw_modult_t类型,这个定义在hardware.h中

  1. typedef struct hw_module_t {  
  2.     /** tag must be initialized to HARDWARE_MODULE_TAG */  
  3.     uint32_t tag;  
  4.   
  5.     uint16_t module_api_version;  
  6. #define version_major module_api_version  
  7.   
  8. #define version_minor hal_api_version  
  9.   
  10.     /** Identifier of module */  
  11.     const char *id;  
  12.   
  13.     /** Name of this module */  
  14.     const char *name;  
  15.   
  16.     /** Author/owner/implementor of the module */  
  17.     const char *author;  
  18.   
  19.     /** Modules methods */  
  20.     struct hw_module_methods_t* methods;  
  21.   
  22.     /** module's dso */  
  23.     void* dso;  
  24.   
  25. #ifdef __LP64__  
  26.     uint64_t reserved[32-7];  
  27. #else  
  28.     /** padding to 128 bytes, reserved for future use */  
  29.     uint32_t reserved[32-7];  
  30. #endif  
  31.   
  32. } hw_module_t;  

上面其中有一个methods变量类型是hw_module_methods_t我们来看下。每个模块要实现这个结构体中的open函数,最终返回hw_device_t类型的device

  1. typedef struct hw_module_methods_t {  
  2.     /** Open a specific device */  
  3.     int (*open)(const struct hw_module_t* module, const char* id,  
  4.             struct hw_device_t** device);  
  5.   
  6. } hw_module_methods_t;  

我们再看gralloc模块的实现文件gralloc_modulc.cpp

  1. private_module_t:: ()  
  2. {  
  3. #define INIT_ZERO(obj) (memset(&(obj),0,sizeof((obj))))  
  4.   
  5.     base.common.tag = HARDWARE_MODULE_TAG;  
  6.     base.common.version_major = 1;  
  7.     base.common.version_minor = 0;  
  8.     base.common.id = GRALLOC_HARDWARE_MODULE_ID;  
  9.     base.common.name = "Graphics Memory Allocator Module";  
  10.     base.common.author = ".......";  
  11.     base.common.methods = &gralloc_module_methods;//这个方法是关键  
  12.     base.common.dso = NULL;  
  13.     INIT_ZERO(base.common.reserved);  
  14.   
  15.     base.registerBuffer = gralloc_register_buffer;  
  16.     base.unregisterBuffer = gralloc_unregister_buffer;  
  17.     base.lock = gralloc_lock;  
  18.     base.unlock = gralloc_unlock;  
  19.     base.perform = NULL;  
  20.     INIT_ZERO(base.reserved_proc);  
  21.   
  22.     framebuffer = NULL;  
  23.     flags = 0;  
  24.     numBuffers = 0;  
  25.     bufferMask = 0;  
  26.     pthread_mutex_init(&(lock), NULL);  
  27.     refcount = 0;  
  28.     currentBuffer = NULL;  
  29.     INIT_ZERO(info);  
  30.     INIT_ZERO(finfo);  
  31.     xdpi = 0.0f;  
  32.     ydpi = 0.0f;  
  33.     fps = 0.0f;  
  34.     swapInterval = 1;  
  35.   
  36.     initialize_blk_conf();  
  37.   
  38.     ion_client = -1;  
  39. #undef INIT_ZERO  
  40. };  
  41.   
  42. /* 
  43.  * HAL_MODULE_INFO_SYM will be initialized using the default constructor 
  44.  * implemented above 
  45.  */  
  46. struct private_module_t HAL_MODULE_INFO_SYM;//HAL_MODULE_INFO_SYM变量  

上面实现HAL_MODULE_INFO_SYM的类型是private_modult_t,是在hardware/libhardware/modules/gralloc/gralloc_priv.h中的

  1. struct private_module_t {  
  2.     gralloc_module_t base;  
  3.   
  4.     private_handle_t* framebuffer;  
  5.     uint32_t flags;  
  6.     uint32_t numBuffers;  
  7.     uint32_t bufferMask;  
  8.     pthread_mutex_t lock;  
  9.     buffer_handle_t currentBuffer;  
  10.     int pmem_master;  
  11.     void* pmem_master_base;  
  12.   
  13.     struct fb_var_screeninfo info;  
  14.     struct fb_fix_screeninfo finfo;  
  15.     float xdpi;  
  16.     float ydpi;  
  17.     float fps;  
  18. };  

我们再来看下gralloc_module_methods变量实现了open函数。

  1. static struct hw_module_methods_t gralloc_module_methods =  
  2. {  
  3.     open: gralloc_device_open  
  4. };  


然后我们再来看上面,获取了module后,又调用了gralloc_open函数

  1. GraphicBufferAllocator::GraphicBufferAllocator()  
  2.     : mAllocDev(0)  
  3. {  
  4.     hw_module_t const* module;  
  5.     int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);  
  6.     if (err == 0) {  
  7.         gralloc_open(module, &mAllocDev);  
  8.     }  
  9. }  

gralloc_open函数在gralloc.h中,这里调用模块methods中的open方法,前面说过最后会调用gralloc_device_open函数

  1. static inline int gralloc_open(const struct hw_module_t* module,   
  2.         struct alloc_device_t** device) {  
  3.     return module->methods->open(module,   
  4.             GRALLOC_HARDWARE_GPU0, (struct hw_device_t**)device);  
  5. }  

gralloc_device_open函数如下,因为我们传入的是GRALLOC_HARDWARE_GPU0,因此最后调用alloc_device_open函数来返回device。

  1. static int gralloc_device_open(const hw_module_t* module, const char* name, hw_device_t** device)  
  2. {  
  3.     int status = -EINVAL;  
  4.   
  5.     if (!strncmp(name, GRALLOC_HARDWARE_GPU0, MALI_GRALLOC_HARDWARE_MAX_STR_LEN))  
  6.     {  
  7.         status = alloc_device_open(module, name, device);  
  8.     }  
  9.     else if (!strncmp(name, GRALLOC_HARDWARE_FB0, MALI_GRALLOC_HARDWARE_MAX_STR_LEN))  
  10.     {  
  11.         status = framebuffer_device_open(module, name, device);  
  12.     }  
  13.   
  14.     return status;  
  15. }  

我们先来看看这个函数,在alloc_device.cpp中,这里新建了一个alloc_device_t,然后将其common变量赋给了device,因为common变量是alloc_device_t中的第一个变量,它的地址也就是alloc_device_t的地址。

  1. int alloc_device_open(hw_module_t const* module, const char* name, hw_device_t** device)  
  2. {  
  3.     alloc_device_t *dev;  
  4.   
  5.     dev = new alloc_device_t;  
  6.     if (NULL == dev)  
  7.     {  
  8.         return -1;  
  9.     }  
  10.   
  11. #if USE_VIVANTE_2D == 1  
  12.     if (has2Ddev == -1)  
  13.     {  
  14.         struct stat buf;  
  15.         if (stat("/dev/graphics/galcore_smmu", &buf) == 0)  
  16.         {  
  17.             ALOGI("%s: galcore and smmu both exist!", __FUNCTION__);  
  18.             has2Ddev = 1;  
  19.             SMMUEnable = 1;  
  20.         }  
  21.         else if (stat("/dev/graphics/galcore", &buf) == 0)  
  22.         {  
  23.             ALOGI("%s: only galcore exist!", __FUNCTION__);  
  24.             has2Ddev = 1;  
  25.             SMMUEnable = 0;  
  26.         }  
  27.         else  
  28.         {  
  29.             ALOGI("%s: check galcore failed", __FUNCTION__);  
  30.             has2Ddev = 0;  
  31.             SMMUEnable = 0;  
  32.         }  
  33.     }  
  34. #endif  
  35.   
  36.     /* initialize our state here */  
  37.     memset(dev, 0, sizeof(*dev));  
  38.   
  39.     /* initialize the procs */  
  40.     dev->common.tag = HARDWARE_DEVICE_TAG;  
  41.     dev->common.version = 0;  
  42.     dev->common.module = const_cast<hw_module_t*>(module);  
  43.     dev->common.close = alloc_backend_close;  
  44.     dev->alloc = alloc_device_alloc;  
  45.     dev->free = alloc_device_free;  
  46.   
  47.     if (0 != alloc_backend_open(dev)) {  
  48.         delete dev;  
  49.         return -1;  
  50.     }  
  51.   
  52.     *device = &dev->common;//common变量是第一个把 它的地址也就是alloc_device_t的地址  
  53.   
  54.     return 0;  
  55. }  

我们来看下alloc_device_t结构体在gralloc.h中,其第一个变量是hw_device_t

  1. typedef struct alloc_device_t {  
  2.     struct hw_device_t common;  
  3.       
  4.     int (*alloc)(struct alloc_device_t* dev,  
  5.             int w, int h, int format, int usage,  
  6.             buffer_handle_t* handle, int* stride);  
  7.   
  8.     int (*free)(struct alloc_device_t* dev,  
  9.             buffer_handle_t handle);  
  10.   
  11.     void (*dump)(struct alloc_device_t *dev, char *buff, int buff_len);  
  12.   
  13.     void* reserved_proc[7];  
  14. } alloc_device_t;  

我们再来看看hw_device_t结构体,在hardware.h文件中,我们看起英文注释,hw_device_t必须在上面alloc_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. typedef struct hw_device_t {  
  6.     uint32_t tag;  
  7.   
  8.     uint32_t version;  
  9.   
  10.     /** reference to the module this device belongs to */  
  11.     struct hw_module_t* module;  
  12.   
  13.     /** padding reserved for future use */  
  14. #ifdef __LP64__  
  15.     uint64_t reserved[12];  
  16. #else  
  17.     uint32_t reserved[12];  
  18. #endif  
  19.   
  20.     /** Close this device */  
  21.     int (*close)(struct hw_device_t* device);  
  22.   
  23. } hw_device_t;  
上面获取到的device是mAllocDev,类型是alloc_device_t。最后可以直接使用mAllocDev来调用比如alloc等函数。
  1. GraphicBufferAllocator::GraphicBufferAllocator()  
  2.     : mAllocDev(0)  
  3. {  
  4.     hw_module_t const* module;  
  5.     int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);  
  6.     if (err == 0) {  
  7.         gralloc_open(module, &mAllocDev);  
  8.     }  
  9. }  

四、注意

这里有几点注意点,我们来看下

4.1 JNI层方法调用

我们有几点要注意,一是上层代码可以如下。


  1. GraphicBufferAllocator::GraphicBufferAllocator()  
  2.     : mAllocDev(0)  
  3. {  
  4.     hw_module_t const* module;  
  5.     int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);  
  6.     if (err == 0) {  
  7.         gralloc_open(module, &mAllocDev);  
  8.     }  
  9. }  

也可以这样,这样都是可以的。


  1. GraphicBufferAllocator::GraphicBufferAllocator()  
  2.     : mAllocDev(0)  
  3. {  
  4.     private_module_t const* module;  
  5.     int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);  
  6.     if (err == 0) {  
  7.         gralloc_open(module->base->common, &mAllocDev);  
  8.     }  
  9. }  

为什么呢?因为,不管你中间有数据结构,但是因为都在第一个变量,其指针地址都是一致的。到时候想用什么类型。只要指针类型转化下就可以了。还可以这样,都是没有问题的。


  1. GraphicBufferAllocator::GraphicBufferAllocator()  
  2.     : mAllocDev(0)  
  3. {  
  4.     gralloc_module_t const* module;  
  5.     int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);  
  6.     if (err == 0) {  
  7.         gralloc_open(module->common, &mAllocDev);  
  8.     }  
  9. }  

4.2 Android.mk文件

Android.mk我们要注意什么呢?下面是上面gralloc模块的Android.mk文件。首先我们编译的是动态库这个没有问题,其次我们目录前面我们分析过,名字在vendor/lib/hw或者system/lib/hw下。最后我们的模块名字,要和前面分析的几个属性名字要符合


  1. ......  
  2. LOCAL_MODULE_RELATIVE_PATH := hw  
  3. ......  
  4. LOCAL_MODULE := gralloc.$(TARGET_BOARD_PLATFORM)  
  5. ......  
  6. include $(BUILD_SHARED_LIBRARY)  
这里我们用的属性名字是ro.board.platform

  1. static const char *variant_keys[] = {  
  2.     "ro.hardware",   
  3.     "ro.product.board",  
  4.     "ro.board.platform",  
  5.     "ro.arch"  
  6. };  


这里我们是系统模块,那比如我们自己写个hal层模块,应该用什么呢?模块名后面有default,就是上面分析的如果都找不到会用default。PATH这里没有使用相对路径,直接用的绝对路径,一个意思。

  1. LOCAL_PATH := $(call my-dir)    
  2. include $(CLEAR_VARS)    
  3.    
  4. LOCAL_MODULE_TAGS :optional    
  5.    
  6. LOCAL_PRELINK_MODULE :false    
  7.    
  8. LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw    
  9.     
  10. LOCAL_SHARED_LIBRARIES :liblog    
  11.   
  12. LOCAL_SRC_FILES :hello.c    
  13.    
  14. LOCAL_MODULE :hello.default    
  15.     
  16. include $(BUILD_SHARED_LIBRARY)    

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值