Android HAL

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)

  1. static void  
  2. acquireWakeLock(JNIEnv *env, jobject clazz, jint lock, jstring idObj)  
  3. {  
  4.     if (idObj == NULL) {  
  5.         throw_NullPointerException(env, "id is null");  
  6.         return ;  
  7.     }  
  8.   
  9.     const char *id = env->GetStringUTFChars(idObj, NULL);  
  10.   
  11.     acquire_wake_lock(lock, id);  
  12.   
  13.     env->ReleaseStringUTFChars(idObj, id);  
  14. }  

HAL層:Power.c(hardware\libhardware_legacy\power)
  1. int  
  2. acquire_wake_lock(int lock, const char* id)  
  3. {  
  4.     initialize_fds();  
  5.   
  6. //    LOGI("acquire_wake_lock lock=%d id='%s'\n", lock, id);   
  7.   
  8.     if (g_error) return g_error;  
  9.   
  10.     int fd;  
  11.   
  12.     if (lock == PARTIAL_WAKE_LOCK) {  
  13.         fd = g_fds[ACQUIRE_PARTIAL_WAKE_LOCK];  
  14.     }  
  15.     else {  
  16.         return EINVAL;  
  17.     }  
  18.   
  19.     return write(fd, id, strlen(id));  
  20. }  

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個結構體規定了統一接口

  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 hw_module_t {  
  7.     /** tag must be initialized to HARDWARE_MODULE_TAG */  
  8.     uint32_t tag;  
  9.   
  10.     /** major version number for the module */  
  11.     uint16_t version_major;  
  12.   
  13.     /** minor version number of the module */  
  14.     uint16_t version_minor;  
  15.   
  16.     /** Identifier of module */  
  17.     const char *id;  
  18.   
  19.     /** Name of this module */  
  20.     const char *name;  
  21.   
  22.     /** Author/owner/implementor of the module */  
  23.     const char *author;  
  24.   
  25.     /** Modules methods */  
  26.     struct hw_module_methods_t* methods;  
  27.   
  28.     /** module's dso */  
  29.     void* dso;  
  30.   
  31.     /** padding to 128 bytes, reserved for future use */  
  32.     uint32_t reserved[32-7];  
  33.   
  34. } hw_module_t;  

由註釋可知,每個HAL模塊都必須繼承這個結構體,繼承方式爲,定義一個結構體,其第一個元素爲hw_module_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.     /** tag must be initialized to HARDWARE_DEVICE_TAG */  
  7.     uint32_t tag;  
  8.   
  9.     /** version number for hw_device_t */  
  10.     uint32_t version;  
  11.   
  12.     /** reference to the module this device belongs to */  
  13.     struct hw_module_t* module;  
  14.   
  15.     /** padding reserved for future use */  
  16.     uint32_t reserved[12];  
  17.   
  18.     /** Close this device */  
  19.     int (*close)(struct hw_device_t* device);  
  20.   
  21. } 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)

  1. void DisplayHardware::init(uint32_t dpy)  
  2. {  
  3.     mNativeWindow = new FramebufferNativeWindow();  
  4.     framebuffer_device_t const * fbDev = mNativeWindow->getDevice();  
  5.     mDpiX = mNativeWindow->xdpi;  
  6.     mDpiY = mNativeWindow->ydpi;  
  7.     mRefreshRate = fbDev->fps;  
  8.   
  9.     mOverlayEngine = NULL;  
  10.     hw_module_t const* module;  
  11.     if (hw_get_module(OVERLAY_HARDWARE_MODULE_ID, &module) == 0) {  
  12.         overlay_control_open(module, &mOverlayEngine);  
  13.     }  
  14.     ....  
  15. }  

HAL層:Overlay.h(hardware\libhardware\include\hardware)

  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. struct overlay_module_t {  
  7.     struct hw_module_t common;  
  8. };  

  1. /** 
  2.  * Every device data structure must begin with hw_device_t 
  3.  * followed by module specific public methods and attributes. 
  4.  */  
  5.   
  6. struct overlay_control_device_t {  
  7.     struct hw_device_t common;  
  8.       
  9.     /* get static informations about the capabilities of the overlay engine */  
  10.     int (*get)(struct overlay_control_device_t *dev, int name);  
  11.   
  12.     /* creates an overlay matching the given parameters as closely as possible. 
  13.      * returns an error if no more overlays are available. The actual 
  14.      * size and format is returned in overlay_t. */  
  15.     overlay_t* (*createOverlay)(struct overlay_control_device_t *dev,  
  16.             uint32_t w, uint32_t h, int32_t format);  
  17.       
  18.     /* destroys an overlay. This call releases all 
  19.      * resources associated with overlay_t and make it invalid */  
  20.     void (*destroyOverlay)(struct overlay_control_device_t *dev,  
  21.             overlay_t* overlay);  
  22.   
  23.     /* set position and scaling of the given overlay as closely as possible. 
  24.      * if scaling cannot be performed, overlay must be centered. */  
  25.     int (*setPosition)(struct overlay_control_device_t *dev,  
  26.             overlay_t* overlay,   
  27.             int x, int y, uint32_t w, uint32_t h);  
  28.   
  29.     /* returns the actual position and size of the overlay */  
  30.     int (*getPosition)(struct overlay_control_device_t *dev,  
  31.             overlay_t* overlay,   
  32.             int* x, int* y, uint32_t* w, uint32_t* h);  
  33.   
  34.     /* sets configurable parameters for this overlay. returns an error if not 
  35.      * supported. */  
  36.     int (*setParameter)(struct overlay_control_device_t *dev,  
  37.             overlay_t* overlay, int param, int value);  
  38.   
  39.     int (*stage)(struct overlay_control_device_t *dev, overlay_t* overlay);  
  40.     int (*commit)(struct overlay_control_device_t *dev, overlay_t* overlay);  
  41. };  

Overlay.cpp (hardware\libhardware\modules\overlay)

  1. static int overlay_device_open(const struct hw_module_t* module, const char* name,  
  2.         struct hw_device_t** device);  
  3.   
  4. static struct hw_module_methods_t overlay_module_methods = {  
  5.     open: overlay_device_open  
  6. };  
  7.   
  8. struct overlay_module_t HAL_MODULE_INFO_SYM = {  
  9.     common: {  
  10.         tag: HARDWARE_MODULE_TAG,  
  11.         version_major: 1,  
  12.         version_minor: 0,  
  13.         id: OVERLAY_HARDWARE_MODULE_ID,  
  14.         name: "Sample Overlay module",  
  15.         author: "The Android Open Source Project",  
  16.         methods: &overlay_module_methods,  
  17.     }  
  18. };  

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.csdn.net/k229650014/article/details/5801397

http://my.unix-center.net/~Simon_fu/?p=630

發佈了9 篇原創文章 · 獲贊 6 · 訪問量 13萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章