HAL概述
以下是基於android4.0.3,對應其他低版本的代碼,可能有所差異,但基本大同小異。
Android的HAL是為了保護一些硬件提供商的知識產權而提出的,是為了避開linux的GPL束縛。
思路是把控制硬件的動作都放到了Android HAL中,而linux driver僅僅完成一些簡單的數據交互作用,甚至把硬件寄存器空間直接映射到user space。而Android是基於Aparch的license,因此硬件廠商可以只提供二進制代碼,所以說Android只是一個開放的平台,並不是一個開源的平台。
也正是因為Android不遵從GPL,所以Greg Kroah-Hartman才在2.6.33內核將Andorid驅動從linux中刪除。GPL和硬件廠商目前還是有着無法彌合的裂痕。Android想要把這個問題處理好也是不容易的。
總結下來,Android HAL存在的原因主要有:
- 並不是所有的硬件設備都有標准的linux kernel的接口
- KERNEL DRIVER涉及到GPL的版權。某些設備制造商並不原因公開硬件驅動,所以才去用HAL方 式繞過GPL。
- 針對某些硬件,An有一些特殊的需求
Android架構
源碼位置
/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
libhardware_legacy 是將 *.so 文件當作shared library來使用,在runtime(JNI 部份)以 direct function call 使用 HAL module。通過直接函數調用的方式,來操作驅動程序。
當然,應用程序也可以不需要通過 JNI 的方式進行,直接加載 *.so (dlopen)的做法調用*.so 里的符號(symbol)也是一種方式。
總而言之是沒有經過封裝,上層可以直接操作硬件。
libhardware
現在的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層結構框架,通過幾個接口訪問硬件從而統一了調用方式。
JNI
Android的HAL的實現需要通過JNI(Java Native Interface)。
JNI簡單來說就是java程序可以調用C/C++寫的動態鏈接庫,這樣的話,HAL可以使用C/C++語言編寫,效率更高。
JNI->通用硬件模塊->硬件模塊->內核驅動接口,具體一點:JNI->libhardware.so->xxx.xxx.so->kernel,具體來說:android frameworks中JNI調用hardware.c中定義的hw_get_module函數來獲取硬件模塊,然后調用硬件模塊中的方法,硬件模塊中的方法直接調用內核接口完成相關功能
訪問HAL方式
在Android下訪問HAL大致有以下兩種方式。
經過service調用
Android的app可以直接通過service調用.so格式的jni。
經過Manager調用service
上面兩種方法應該說是各有優缺點:
第一種方法簡單高效,但不正規。
第二種方法實現起來比較復雜,但更符合目前的Android框架。
第二種方法中,LedManager和LedService(java)在兩個進程中,需要通過進程通訊的方式來通訊。
在現在的android框架中,這兩種方式都存在,比如對於lights,是直接透過LightsService調用JNI,而對於sensor,中間則是通過SensorsManager來調用JNI的。
通用硬件模塊(libhardware.so)
一般來說HAL moudle需要涉及的是三個關鍵結構體:
struct hw_module_t; struct hw_module_methods_t; struct hw_device_t;
這三個結構體定義在hardware.h中(/hardware/libhardware/include/hardware/hardware.h)。
頭文件中主要定義了通用硬件模塊結構體hw_module_t,聲明了JNI調用的接口函數hw_get_module、hw_module_t。
定義如下:

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 7 typedef struct hw_module_t 8 { 9 10 /** tag must be initialized to HARDWARE_MODULE_TAG */ 11 uint32_t tag; 12 13 /** major version number for the module */ 14 uint16_t version_major; 15 16 /** minor version number of the module */ 17 uint16_t version_minor; 18 19 /** Identifier of module */ 20 const char *id; 21 22 /** Name of this module */ 23 const char *name; 24 25 /** Author/owner/implementor of the module */ 26 const char *author; 27 28 /** Modules methods */ 29 struct hw_module_methods_t* methods; //硬件模塊的方法 30 31 /** module's dso */ 32 void* dso; 33 34 35 /** padding to 128 bytes, reserved for future use */ 36 uint32_t reserved[32-7]; 37 38 } hw_module_t;
如注釋所說,所有的hal模塊都要有一個以HAL_MODULE_INFO_SYM命名的結構,而且這個結構要以hw_module_t開始,即要繼承hw_module_t這個結構。
比如lights,sensor:

1 struct sensors_module_t 2 { 3 struct hw_module_t common; 4 int (*get_sensors_list)(struct sensors_module_t* module, 5 struct sensor_t const** list); 6 }; 7 8 /* 9 * The lights Module 10 */ 11 struct light_module_t HAL_MODULE_INFO_SYM = { 12 common: { 13 tag: HARDWARE_MODULE_TAG, 14 version_major: 1, 15 version_minor: 0, 16 id: LIGHTS_HARDWARE_MODULE_ID, 17 name: "Lights module", 18 author: "Rockchip", 19 methods: &light_module_methods, 20 } 21 }; 22 23 const struct sensors_module_t HAL_MODULE_INFO_SYM = { 24 .common = { 25 .tag = HARDWARE_MODULE_TAG, 26 .version_major = 1, 27 .version_minor = 0, 28 .id = SENSORS_HARDWARE_MODULE_ID, 29 .name = "Stingray SENSORS Module", 30 .author = "Motorola", 31 .methods = &sensors_module_methods, 32 }, 33 .get_sensors_list = sensors__get_sensors_list 34 };
hw_module_t中比較重要的是硬件模塊方法結構體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;
該方法在定義HAL_MODULE_INFO_SYM的時候被初始化。目前該結構中只定義了一個open方法,其中調用的設備結構體參數hw_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 6 typedef struct hw_device_t 7 { 8 /** tag must be initialized to HARDWARE_DEVICE_TAG */ 9 uint32_t tag; 10 11 /** version number for hw_device_t */ 12 uint32_t version; 13 14 /** reference to the module this device belongs to */ 15 struct hw_module_t* module; 16 17 /** padding reserved for future use */ 18 uint32_t reserved[12]; 19 20 /** Close this device */ 21 int (*close)(struct hw_device_t* device); 22 } hw_device_t; 23 24 struct light_device_t 25 { 26 struct hw_device_t common; 27 int (*set_light)(struct light_device_t* dev, 28 struct light_state_t const* state); 29 }; 30 31 /** 32 * Every device data structure must begin with hw_device_t 33 * followed by module specific public methods and attributes. 34 */ 35 36 struct sensors_poll_device_t 37 { 38 struct hw_device_t common; 39 int (*activate)(struct sensors_poll_device_t *dev, 40 int handle, int enabled); 41 int (*setDelay)(struct sensors_poll_device_t *dev, 42 int handle, int64_t ns); 43 int (*poll)(struct sensors_poll_device_t *dev, 44 sensors_event_t* data, int count); 45 };
亦如注釋所說,每一個設備的數據結構都必須也以hw_device_t開始。
hw_get_module函數聲明如下:
int hw_get_module(const char *id, const struct hw_module_t **module);
參數id為模塊標識,定義在/hardware/libhardware/include/hardware錄下的硬件模塊頭文件中。
參數module是硬件模塊地址,定義在/hardware/libhardware/include/hardware/hardware.h中
調用關系