Android的HAL(Hardware Abstract Layer硬件抽象層)是爲了保護一些硬件提供商的知識產權而提出的,是爲了避開linux的GPL束縛。思路是把控制硬件的動做都放到了Android HAL中,而linux driver僅僅完成一些簡單的數據交互做用,甚至把硬件寄存器空間直接映射到user space。而Android是基於Aparch的license,所以硬件廠商能夠只提供二進制代碼,因此說Android只是一個開放的平臺,並非一個開源的平臺。 html
總結下來,Android HAL存在的緣由主要有: java
下圖是HAL在android系統中所處的位置: node
從這張圖中能夠看出,HAL把內核和framework隔離開來,使上層的開發能夠不依賴內核與驅動的實現。在android源碼中,HAL大體位於下面幾個位置: linux
主要包含如下一些模塊:Gps、Vibrator、Wifi、Copybit、Audio、Camera、Lights、Ril、Gralloc等。 android
下圖分別爲舊的HAL實現與新的HAL實現框圖: c++
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層結構框架,經過幾個接口訪問硬件從而統一了調用方式。 編程
由上可大體看出這兩種實現方式的優劣: api
HAL_legacy方式的HAL是一個模塊,採用共享庫形式,在編譯時會調用到。因爲採用function call形式調用,所以可被多個進程使用,但會被mapping到多個進程空間中,形成浪費,同時須要考慮代碼可否安全重入的問題(thread safe)。而新式的HAL採用HAL module和HAL stub結合形式,HAL stub不是一個share library,編譯時上層只擁有訪問HAL stub的函數指針,並不須要HAL stub。上層經過HAL module提供的統一接口獲取並操做HAL stub,so文件只會被mapping到一個進程,也不存在重複mapping和重入問題。 安全
HAL模塊主要有二個結構:
struct hw_module_t-表明抽象硬件模塊,包含硬件模塊的一些基本信息,例如版本號,開發者等,還有一個成員函數結構體。
struct hw_module_methods_t ,裏面只有一個用於打開抽象硬件設備hw_device_t的open函數指針。
struct hw_device_t-表明抽象硬件設備,裏面包含了版本號,一個關閉硬件的close函數指針,以及一個指向hw_module_t的結構的指針。
這兩個結構的定義在hardware/libhardware/include/hardware/hardware.h裏面,在實現本身的hw module與hw device結構時,第一個成員變量必須是這兩個結構,以達到相似C++中的繼承的目的。
這兩個結構的定義以下所示:
typedef struct hw_module_t { /** tag must be initialized to HARDWARE_MODULE_TAG */ uint32_t tag; /** * The API version of the implemented module. The module owner is * responsible for updating the version when a module interface has * changed. * * The derived modules such as gralloc and audio own and manage this field. * The module user must interpret the version field to decide whether or * not to inter-operate with the supplied module implementation. * For example, SurfaceFlinger is responsible for making sure that * it knows how to manage different versions of the gralloc-module API, * and AudioFlinger must know how to do the same for audio-module API. * * The module API version should include a major and a minor component. * For example, version 1.0 could be represented as 0x0100. This format * implies that versions 0x0100-0x01ff are all API-compatible. * * In the future, libhardware will expose a hw_get_module_version() * (or equivalent) function that will take minimum/maximum supported * versions as arguments and would be able to reject modules with * versions outside of the supplied range. */ uint16_t module_api_version; #define version_major module_api_version /** * version_major/version_minor defines are supplied here for temporary * source code compatibility. They will be removed in the next version. * ALL clients must convert to the new version format. */ /** * The API version of the HAL module interface. This is meant to * version the hw_module_t, hw_module_methods_t, and hw_device_t * structures and definitions. * * The HAL interface owns this field. Module users/implementations * must NOT rely on this value for version information. * * Presently, 0 is the only valid value. */ uint16_t hal_api_version; #define version_minor hal_api_version /** Identifier of module */ const char *id; /** Name of this module */ const char *name; /** Author/owner/implementor of the module */ const char *author; /** Modules methods */ <strong> struct hw_module_methods_t* methods;</strong> /** module's dso */ <strong> void* dso;</strong> /** padding to 128 bytes, reserved for future use */ uint32_t reserved[32-7]; } hw_module_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; /** * 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 of the module-specific device API. This value is used by * the derived-module user to manage different device implementations. * * The module user is responsible for checking the module_api_version * and device version fields to ensure that the user is capable of * communicating with the specific module implementation. * * One module can support multiple devices with different versions. This * can be useful when a device interface changes in an incompatible way * but it is still necessary to support older implementations at the same * time. One such example is the Camera 2.0 API. * * This field is interpreted by the module user and is ignored by the * HAL interface itself. */ uint32_t version; /** reference to the module this device belongs to */ <strong>struct hw_module_t* module;</strong> /** padding reserved for future use */ uint32_t reserved[12]; /** Close this device */ <strong>int (*close)(struct hw_device_t* device);</strong> } hw_device_t;
硬件模塊庫的裝載與解析由hardware.c中的hw_get_module函數完成,它先按照必定的規則選擇而後加載硬件模塊庫,而後由HAL_MODULE_INFO_SYM解析出庫中的全局變量名,獲得硬件模塊庫指針(hw_module_t結構),而後返回給調用者。
下面以camera爲例子來講明如何使用HAL層。
在系統啓動建立CameraService對象時,其函數onFirstRef被調用,在它裏面,經過hw_get_module(CAMERA_HARDWARE_MODULE_ID, (const hw_module_t**)&mModule)函數獲取camera的抽象硬件模塊camera_module,其過程如上所說,經過Camera的HAL動態庫而後解析HAL_MODULE_INFO_SYM符號獲得全局變量,而後經過獲取到的抽象硬件模塊結構獲取系統擁有的Camera數量等。具體代碼參見CameraService.cpp。
其中camera_module即camera HAL的抽象硬件模塊,其定義以下(camera_common.h):
typedef struct camera_module { hw_module_t common; /** * get_number_of_cameras: * * Returns the number of camera devices accessible through the camera * module. The camera devices are numbered 0 through N-1, where N is the * value returned by this call. The name of the camera device for open() is * simply the number converted to a string. That is, "0" for camera ID 0, * "1" for camera ID 1. * * The value here must be static, and cannot change after the first call to * this method */ int (*get_number_of_cameras)(void); /** * get_camera_info: * * Return the static camera information for a given camera device. This * information may not change for a camera device. * */ int (*get_camera_info)(int camera_id, struct camera_info *info); /** * set_callbacks: * * Provide callback function pointers to the HAL module to inform framework * of asynchronous camera module events. The framework will call this * function once after initial camera HAL module load, after the * get_number_of_cameras() method is called for the first time, and before * any other calls to the module. * * Version information (based on camera_module_t.common.module_api_version): * * CAMERA_MODULE_API_VERSION_1_0, CAMERA_MODULE_API_VERSION_2_0: * * Not provided by HAL module. Framework may not call this function. * * CAMERA_MODULE_API_VERSION_2_1: * * Valid to be called by the framework. * */ int (*set_callbacks)(const camera_module_callbacks_t *callbacks); /** * get_vendor_tag_ops: * * Get methods to query for vendor extension metadata tag information. The * HAL should fill in all the vendor tag operation methods, or leave ops * unchanged if no vendor tags are defined. * * Version information (based on camera_module_t.common.module_api_version): * * CAMERA_MODULE_API_VERSION_1_x/2_0/2_1: * Not provided by HAL module. Framework may not call this function. * * CAMERA_MODULE_API_VERSION_2_2: * Valid to be called by the framework. */ void (*get_vendor_tag_ops)(vendor_tag_ops_t* ops); /* reserved for future use */ void* reserved[8]; } camera_module_t;
由其定義看到,其第一個成員爲hw_module_t common,即上面說的本身的硬件抽象模塊必須包含hw_module結構,達到「繼承」的目的。另外定義了幾個本身的成員變量,好比獲取camera個數,及camera信息等。使用hw_get_module獲取到的camera_module_t變量位於平臺的camera HAL實現庫中,不一樣的廠家可能文件名字有所不一樣,可是確定會實現下面相似的結構(CameraHAL.cpp)。
camera_module_t HAL_MODULE_INFO_SYM __attribute__ ((visibility("default"))) = { common : { tag : HARDWARE_MODULE_TAG, module_api_version : CAMERA_MODULE_API_VERSION_2_0, hal_api_version : HARDWARE_HAL_API_VERSION, id : CAMERA_HARDWARE_MODULE_ID, name : "Default Camera HAL", author : "The Android Open Source Project", methods : &gCameraModuleMethods, dso : NULL, reserved : {0}, }, get_number_of_cameras : get_number_of_cameras, get_camera_info : get_camera_info, set_callbacks : set_callbacks };
有了Camera的HAL層的硬件抽象模塊camera_module,就能夠經過camera_module獲取到硬件抽象設備camera_device_t,不過它封裝在CameraHardwareInterface中,在鏈接一個camera時(CameraService的connect函數,最後調到CameraClient::initialize),將先建立CameraHardwareInterface對象,而後在其初始化函數中獲得camera_device_t:int rc = module->methods->open(module, mName.string(), (hw_device_t **)&mDevice);這個open函數就是gCameraModuleMethods裏面的open函數,其實現以下所示:
int Camera::open(const hw_module_t *module, hw_device_t **device) { ALOGI("%s:%d: Opening camera device", __func__, mId); CAMTRACE_CALL(); pthread_mutex_lock(&mMutex); if (mBusy) { pthread_mutex_unlock(&mMutex); ALOGE("%s:%d: Error! Camera device already opened", __func__, mId); return -EBUSY; } // TODO: open camera dev nodes, etc mBusy = true; mDevice.common.module = const_cast<hw_module_t*>(module); *device = &mDevice.common; pthread_mutex_unlock(&mMutex); return 0; }
這裏面就返回了camera_device_t,而此結構的初始化在構造函數中:
</pre> <pre>Camera::Camera(int id) : mId(id), mStaticInfo(NULL), mBusy(false), mCallbackOps(NULL), mStreams(NULL), mNumStreams(0), mSettings(NULL) { pthread_mutex_init(&mMutex, NULL); pthread_mutex_init(&mStaticInfoMutex, NULL); memset(&mDevice, 0, sizeof(mDevice)); mDevice.common.tag = HARDWARE_DEVICE_TAG; mDevice.common.version = CAMERA_DEVICE_API_VERSION_3_0; mDevice.common.close = close_device; mDevice.ops = const_cast<camera3_device_ops_t*>(&sOps); mDevice.priv = this; }
至此,CameraService就獲得了Camera的HAL層的硬件抽象模塊camera_module_t和抽象設備camera_device_t。有了這兩個結構,上層就可使用camera的功能了。以上代碼基於android4.4/hardware/libhardware/modules/camera,使用的是c++的方式實現,不一樣硬件廠家的實現方式可能不一樣,但相同的是都必須實現這兩個結構。
hw_module_t:硬件抽象模塊,能夠用hw_get_module獲取到。其中又包含了一個hw_module_methods_t結構,其中定義了打開設備open方法。
hw_device_t:硬件抽象設備,主要定義了硬件相關的一些函數,參數等。此結構經過hw_module_methods_t裏面定義的open函數獲取。
以上大體就是android hal模塊的內容,下一篇會以android的一個重要的HAL模塊gralloc來看看其具體的實現。
關注微信公衆平臺:程序員互動聯盟(coder_online),你能夠第一時間獲取原創技術文章,和(java/C/C++/Android/Windows/Linux)技術大牛作朋友,在線交流編程經驗,獲取編程基礎知識,解決編程問題。程序員互動聯盟,開發人員本身的家。