1 HAL产生的原因
Android HAL(Hardware Abstraction Libraries)是处于user space的最下层,是Android定义的要求Linux内核空间来具体实现的驱动接口。根据Google的说法,使用user-space HAL的原因为:
1 Not all components have standardizedkernel driver interface
2 Kernel driver are GPL which exposes anyproprietary IP
3 Android has specific requirements forhardware drivers
但这其中最重要的原因为第二个,把控制硬件的动作都放到了user space中,在kernel driver里面只有最简单的读写寄存器的操作。Android user space的代码就可以不必受到GPL的束缚而封装成库,避免了暴露硬件厂商使用的硬件型号。
2 HAL的重要性
HAL的重要性主要表现在两个方面:
1 从学习的角度看,HAL通常是Linux内核开发者想学习整个Android系统架构时选择的突破口,这是由于HAL所处在整个系统架构的位置决定的;同样Android user-space的开发者,想要从APP和中间件进一步深入贯通到内核,HAL也是必经之路。如果把Kernel比作关内,Android user-space比作关外,HAL就是进出关的唯一通道,兵家必争之地。
2 从使用的频度来看,随着对SOC性能要求的进一步提高,越来越多的模块将使用硬件加速,甚至以前使用DSP来加速的一些模块,由于性能和功耗的要求,都改用硬件实现,特别是多媒体相关的领域,GPU也几乎成了最近2年出来的SOC的标配,Android也集成了方便使用硬件加速的标准OpenMAX, OpenGL等。
3 HAL的2种模式
3.1 直接调用(旧的模式)
1 源码路径:\hardware\libhardware_legacy
2 模式简介:libhardware_legacy是将 *.so 文件当作shared library来使用,JNI以 direct function call 使用 HAL module。通过直接函数调用的方式,来操作驱动程序。
3 实例:PowerManager
JNI层:android_os_Power.cpp(frameworks\base\core\jni)
- static void
- acquireWakeLock(JNIEnv *env, jobject clazz, jint lock, jstring idObj)
- {
- if (idObj == NULL) {
- throw_NullPointerException(env, "id is null");
- return ;
- }
- const char *id = env->GetStringUTFChars(idObj, NULL);
- acquire_wake_lock(lock, id);
- env->ReleaseStringUTFChars(idObj, id);
- }
HAL层:Power.c(hardware\libhardware_legacy\power)
- int
- acquire_wake_lock(int lock, const char* id)
- {
- initialize_fds();
- // LOGI("acquire_wake_lock lock=%d id='%s'\n", lock, id);
- if (g_error) return g_error;
- int fd;
- if (lock == PARTIAL_WAKE_LOCK) {
- fd = g_fds[ACQUIRE_PARTIAL_WAKE_LOCK];
- }
- else {
- return EINVAL;
- }
- return write(fd, id, strlen(id));
- }
3.2 通过回调函数调用并统一接口(新的模式)
1 源码路径:\hardware\libhardware
2 模式简介:hardware.c和hardware.h(hardware\libhardware\include\hardware)提供了使用这种模式的HAL的方式,并规定统一接口。上层通过hardware.c中的函数hw_get_module获取相应module的stub,然后通过stub来访问HAL。
3 接口源码hardware.c和hardware.h说明
(1)Hardware.h用2个结构体规定了统一接口
- /**
- * 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.
- */
- 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;
由注释可知,每个HAL模块都必须继承这个结构体,继承方式为,定义一个结构体,其第一个元素为hw_module_t,之后是表征自己模块独有的信息的变量。
- /**
- * Every device data structure must begin with hw_device_t
- * followed by module specific public methods and attributes.
- */
- typedef struct hw_device_t {
- /** tag must be initialized to HARDWARE_DEVICE_TAG */
- uint32_t tag;
- /** version number for hw_device_t */
- uint32_t version;
- /** reference to the module this device belongs to */
- struct hw_module_t* module;
- /** padding reserved for future use */
- uint32_t reserved[12];
- /** Close this device */
- int (*close)(struct hw_device_t* device);
- } hw_device_t;
由注释可知,每个HAL模块必须继承这个结构体,继承方式类似地,定义一个结构体,其第一个元素为hw_device_t,之后是自己模块独有的方法和属性。
(2)hardware.c使用hw_get_module函数,通过id查找并加载相应HAL模块,并获得相应模块的Stub。相关的解释见这篇文章http://my.unix-center.net/~Simon_fu/?p=630。
4 实例:overlay
Service层:DisplayHardware.cpp(frameworks\base\services\surfaceflinger\displayhardware)
- void DisplayHardware::init(uint32_t dpy)
- {
- mNativeWindow = new FramebufferNativeWindow();
- framebuffer_device_t const * fbDev = mNativeWindow->getDevice();
- mDpiX = mNativeWindow->xdpi;
- mDpiY = mNativeWindow->ydpi;
- mRefreshRate = fbDev->fps;
- mOverlayEngine = NULL;
- hw_module_t const* module;
- if (hw_get_module(OVERLAY_HARDWARE_MODULE_ID, &module) == 0) {
- overlay_control_open(module, &mOverlayEngine);
- }
- ....
- }
HAL层:Overlay.h(hardware\libhardware\include\hardware)
- /**
- * 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.
- */
- struct overlay_module_t {
- struct hw_module_t common;
- };
- /**
- * Every device data structure must begin with hw_device_t
- * followed by module specific public methods and attributes.
- */
- struct overlay_control_device_t {
- struct hw_device_t common;
- /* get static informations about the capabilities of the overlay engine */
- int (*get)(struct overlay_control_device_t *dev, int name);
- /* creates an overlay matching the given parameters as closely as possible.
- * returns an error if no more overlays are available. The actual
- * size and format is returned in overlay_t. */
- overlay_t* (*createOverlay)(struct overlay_control_device_t *dev,
- uint32_t w, uint32_t h, int32_t format);
- /* destroys an overlay. This call releases all
- * resources associated with overlay_t and make it invalid */
- void (*destroyOverlay)(struct overlay_control_device_t *dev,
- overlay_t* overlay);
- /* set position and scaling of the given overlay as closely as possible.
- * if scaling cannot be performed, overlay must be centered. */
- int (*setPosition)(struct overlay_control_device_t *dev,
- overlay_t* overlay,
- int x, int y, uint32_t w, uint32_t h);
- /* returns the actual position and size of the overlay */
- int (*getPosition)(struct overlay_control_device_t *dev,
- overlay_t* overlay,
- int* x, int* y, uint32_t* w, uint32_t* h);
- /* sets configurable parameters for this overlay. returns an error if not
- * supported. */
- int (*setParameter)(struct overlay_control_device_t *dev,
- overlay_t* overlay, int param, int value);
- int (*stage)(struct overlay_control_device_t *dev, overlay_t* overlay);
- int (*commit)(struct overlay_control_device_t *dev, overlay_t* overlay);
- };
Overlay.cpp (hardware\libhardware\modules\overlay)
- static int overlay_device_open(const struct hw_module_t* module, const char* name,
- struct hw_device_t** device);
- static struct hw_module_methods_t overlay_module_methods = {
- open: overlay_device_open
- };
- struct overlay_module_t HAL_MODULE_INFO_SYM = {
- common: {
- tag: HARDWARE_MODULE_TAG,
- version_major: 1,
- version_minor: 0,
- id: OVERLAY_HARDWARE_MODULE_ID,
- name: "Sample Overlay module",
- author: "The Android Open Source Project",
- methods: &overlay_module_methods,
- }
- };
4 后记
在理解HAL的时候,2种模式的区别万不可纠结于上层是用JNI调用,manager调用,还是用service调用,mokoid在这方面也许会造成一些误导。其关键为:旧的模式为直接调用,新的模式为通过hw_get_module获取到相应HAL模块的stub,以回调的方式进行调用。
5 Reference
http://android.tgbus.com/Android/tutorial/201104/350065.shtml
http://blog.youkuaiyun.com/k229650014/article/details/5801397