Android HAL模塊實現

1. HAL介紹

Android的HAL(Hardware Abstract Layer硬件抽象層)是爲了保護一些硬件提供商的知識產權而提出的,是爲了避開linux的GPL束縛。思路是把控制硬件的動做都放到了Android HAL中,而linux driver僅僅完成一些簡單的數據交互做用,甚至把硬件寄存器空間直接映射到user space。而Android是基於Aparch的license,所以硬件廠商能夠只提供二進制代碼,因此說Android只是一個開放的平臺,並非一個開源的平臺。 html

總結下來,Android HAL存在的緣由主要有: java

  1. 並非全部的硬件設備都有標準的linux kernel的接口
  2. KERNEL DRIVER涉及到GPL的版權。某些設備製造商並不緣由公開硬件驅動,因此纔去用HAL方式繞過GPL。
  3. 針對某些硬件,Android有一些特殊的需求。
  4. 不一樣的平臺廠商可在遵循HAL調用接口的前提下實現本身的HAL,不會影響到上層的調用者,這樣下降了模塊間的耦合度,可讓平臺開發者只關心HAL自己的實現便可。

下圖是HAL在android系統中所處的位置: node

android HAL

從這張圖中能夠看出,HAL把內核和framework隔離開來,使上層的開發能夠不依賴內核與驅動的實現。在android源碼中,HAL大體位於下面幾個位置: linux

  1. libhardware_legacy/ - 舊的架構、採起連接庫模塊的模式進行。
  2. libhardware/ - 新架構、調整爲 HAL stub 的概念。
  3. ril/ - Radio Interface Layer。
  4. msm7k  QUAL平臺相關。

主要包含如下一些模塊:Gps、Vibrator、Wifi、Copybit、Audio、Camera、Lights、Ril、Gralloc等。 android

2. HAL的兩種實現方式

下圖分別爲舊的HAL實現與新的HAL實現框圖: c++

HAL legacy

HAL

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和重入問題。 安全

3. HAL模塊的結構與編寫方法

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;

4. 硬件模塊庫的使用

硬件模塊庫的裝載與解析由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++的方式實現,不一樣硬件廠家的實現方式可能不一樣,但相同的是都必須實現這兩個結構。

5. 總結

  1. HAL經過hw_get_module來獲取hw_module_t結構。
  2. HAL經過hw_module_t->methods->open獲取hw_device_t指針,並在在open中初始化hw_device_t中的結構,包括函數指針(close操做)等。
  3. 兩個重要結構:

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)技術大牛作朋友,在線交流編程經驗,獲取編程基礎知識,解決編程問題。程序員互動聯盟,開發人員本身的家。

【Windows編程】系列第四篇:使用Unicode編程

相關文章
相關標籤/搜索