一、HAL调用方式或流程(以gralloc为例):
hw_module_t const* module;
alloc_device_t* grDev;
hw_get_module(GRALLOC_HARDWARE_MODULE_ID,&module);获取hw_module_t结构
gralloc_open(module, &grDev); //调用相应的open接口,在这个接口里会对gralloc设备结构grDev初始化,以 后就可以使用其中的方法
如grDev->alloc(******);
再看一下gralloc.h提供的信息(与gralloc相关):
1、首先是扩展的hw_module_t结构:
typedef struct gralloc_module_t { struct hw_module_t common; /* * (*registerBuffer)() must be called before a buffer_handle_t that has not * been created with (*alloc_device_t::alloc)() can be used. * * This is intended to be used with buffer_handle_t's that have been * received in this process through IPC. * * This function checks that the handle is indeed a valid one and prepares * it for use with (*lock)() and (*unlock)(). * * It is not necessary to call (*registerBuffer)() on a handle created * with (*alloc_device_t::alloc)(). * * returns an error if this buffer_handle_t is not valid. */ int (*registerBuffer)(struct gralloc_module_t const* module, buffer_handle_t handle); /* * (*unregisterBuffer)() is called once this handle is no longer needed in * this process. After this call, it is an error to call (*lock)(), * (*unlock)(), or (*registerBuffer)(). * * This function doesn't close or free the handle itself; this is done * by other means, usually through libcutils's native_handle_close() and * native_handle_free(). * * It is an error to call (*unregisterBuffer)() on a buffer that wasn't * explicitly registered first. */ int (*unregisterBuffer)(struct gralloc_module_t const* module, buffer_handle_t handle); /* * The (*lock)() method is called before a buffer is accessed for the * specified usage. This call may block, for instance if the h/w needs * to finish rendering or if CPU caches need to be synchronized. * * The caller promises to modify only pixels in the area specified * by (l,t,w,h). * * The content of the buffer outside of the specified area is NOT modified * by this call. * * If usage specifies GRALLOC_USAGE_SW_*, vaddr is filled with the address * of the buffer in virtual memory. * * THREADING CONSIDERATIONS: * * It is legal for several different threads to lock a buffer from * read access, none of the threads are blocked. * * However, locking a buffer simultaneously for write or read/write is * undefined, but: * - shall not result in termination of the process * - shall not block the caller * It is acceptable to return an error or to leave the buffer's content * into an indeterminate state. * * If the buffer was created with a usage mask incompatible with the * requested usage flags here, -EINVAL is returned. * */ int (*lock)(struct gralloc_module_t const* module, buffer_handle_t handle, int usage, int l, int t, int w, int h, void** vaddr); /* * The (*unlock)() method must be called after all changes to the buffer * are completed. */ int (*unlock)(struct gralloc_module_t const* module, buffer_handle_t handle); /* reserved for future use */ int (*perform)(struct gralloc_module_t const* module, int operation, ... ); /* reserved for future use */ void* reserved_proc[7]; } gralloc_module_t; 2、然后是扩展的hw_device_t结构: typedef struct alloc_device_t { struct hw_device_t common; /* * (*alloc)() Allocates a buffer in graphic memory with the requested * parameters and returns a buffer_handle_t and the stride in pixels to * allow the implementation to satisfy hardware constraints on the width * of a pixmap (eg: it may have to be multiple of 8 pixels). * The CALLER TAKES OWNERSHIP of the buffer_handle_t. * * Returns 0 on success or -errno on error. */ int (*alloc)(struct alloc_device_t* dev, int w, int h, int format, int usage, buffer_handle_t* handle, int* stride); /* * (*free)() Frees a previously allocated buffer. * Behavior is undefined if the buffer is still mapped in any process, * but shall not result in termination of the program or security breaches * (allowing a process to get access to another process' buffers). * THIS FUNCTION TAKES OWNERSHIP of the buffer_handle_t which becomes * invalid after the call. * * Returns 0 on success or -errno on error. */ int (*free)(struct alloc_device_t* dev, buffer_handle_t handle); } alloc_device_t;
3、最后是两个方法:
static inline int gralloc_open(const struct hw_module_t* module, struct alloc_device_t** device) { return module->methods->open(module, GRALLOC_HARDWARE_GPU0, (struct hw_device_t**)device); } static inline int gralloc_close(struct alloc_device_t* device) { return device->common.close(&device->common); }
这里直接调用modules里面的open方法,该open指针是在hw_get_module时候赋值的。
所有模块的实现基本都是这样,一个扩展的hw_module_t结构,一个扩展的hw_device_t结构,hw_module_t结构的赋值是通过hw_get_module然后传相应的module ID,如GRALLOC_HARDWARE_MODULE_ID,获取相应ID hw_module_t结构的首地址;而hw_device_t结构是通过相应的Open方法,如这里的gralloc_open,通过这个接口,就获得了操作这个设备的方法了。
二、HAL相关实现
首先看一下hw_module_t结构:typedef struct hw_module_t { /** tag must be initialized to HARDWARE_MODULE_TAG */ uint32_t tag; /** major version number for the module */ uint16_t version_major; /** minor version number of the module */ uint16_t version_minor; /** Identifier of module */ const char *id; /** Name of this module */ const char *name; /** Author/owner/implementor of the module */ const char *author; /** Modules methods */ struct hw_module_methods_t* methods; /** module's dso */ void* dso; /** padding to 128 bytes, reserved for future use */ uint32_t reserved[32-7]; } hw_module_t;
比较重要的是id和methods,id用来区分各个模块,而hw_module_methods_t我们可以看到其定义是:
typedef struct hw_module_methods_t { /** Open a specific device */ int (*open)(const struct hw_module_t* module, const char* id, struct hw_device_t** device); } hw_module_methods_t;
一个open方法,指向了打开这个模块的Open方法
我们看一下gralloc模块相关结构的关系图:1、 先看一下private_module_t(hw_module_t)结构的赋值
struct private_module_t HAL_MODULE_INFO_SYM = { base: { common: { tag: HARDWARE_MODULE_TAG, version_major: 1, version_minor: 0, id: GRALLOC_HARDWARE_MODULE_ID, name: "Graphics Memory Allocator Module", author: "The Android Open Source Project", methods: &gralloc_module_methods }, registerBuffer: gralloc_register_buffer, unregisterBuffer: gralloc_unregister_buffer, lock: gralloc_lock, unlock: gralloc_unlock, }, framebuffer: 0, flags: 0, numBuffers: 0, bufferMask: 0, lock: PTHREAD_MUTEX_INITIALIZER, currentBuffer: 0, pmem_master: -1, pmem_master_base: 0 };
这里id赋值为GRALLOC_HARDWARE_MODULE_ID,methods赋值为gralloc_module_methods
看一下gralloc_module_methods
gralloc_module_t扩展了hw_module_t,增加4个方法,这四个方法可以在调用open之前调用。
static struct hw_module_methods_t gralloc_module_methods = { open: gralloc_device_open };
int gralloc_device_open(const hw_module_t* module, const char* name, hw_device_t** device) { int status = -EINVAL; if (!strcmp(name, GRALLOC_HARDWARE_GPU0)) { gralloc_context_t *dev; dev = (gralloc_context_t*)malloc(sizeof(*dev)); /* initialize our state here */ memset(dev, 0, sizeof(*dev)); /* initialize the procs */ dev->device.common.tag = HARDWARE_DEVICE_TAG; dev->device.common.version = 0; dev->device.common.module = const_cast<hw_module_t*>(module); dev->device.common.close = gralloc_close; dev->device.alloc = gralloc_alloc; dev->device.free = gralloc_free; *device = &dev->device.common; status = 0; } else { status = fb_device_open(module, name, device); } return status; }
可以看到,这里把module和device关联起来了
dev->device.common.module =const_cast<hw_module_t*>(module);
并对gralloc设备提供的两个方法进行赋值
dev->device.alloc = gralloc_alloc;
dev->device.free = gralloc_free;
这样,我们就可以调用gralloc提供的另外两个方法了。