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//从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(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)    

更多相关文章

  1. 理解Android回调函数
  2. Android(安卓)build system ---转
  3. Android应用程序消息处理机制(Looper、Handler)分析
  4. Activity启动流程详解
  5. Android输入法框架系统(下)
  6. Android(安卓)ClassLoader
  7. Android核心模块及相关技术(自IT168)
  8. Android学习笔记
  9. Android的电源管理

随机推荐

  1. java 自定义注解(翻译)
  2. 【Android习惯】文件、方法、变量命名规
  3. Android 2.2中的APK安装参数installLocat
  4. 搞不懂为什么开发人员爱iOS恨Android?
  5. Android IPC(跨进程通信)之AIDL
  6. 第一行代码Android(一)
  7. android中listview的样式设置
  8. Android Q (Android 10.0)
  9. android 动画系列 - 目录
  10. [Android中级]使用Commons-net-ftp来实现