Android系統HAL基本概念


1、前言

Android系統硬件抽象層(Hardware Abstraction Layer),簡寫為HAL,是連接Android Framework與Linux內核設備驅動的重要橋梁。HAL存在的意義有以下兩個方面:

(1)HAL層屏蔽掉不同硬件設備的差異,為Android提供了統一的設備訪問接口。不同的硬件廠商遵循HAL標准來實現自己的硬件控制邏輯,開發者不必關心硬件設備的差異,只需按照HAL提供的標准接口對硬件進行訪問即可。

(2)HAL層幫助硬件廠商隱藏了設備的核心細節,HAL層位於用戶空間,遵循Apache協議,允許硬件廠商不公開源碼,將設備相關的實現放在HAL層中實現,並以共享庫(.so)的形式進行提供。

下面的圖描述了HAL層在Android系統中的位置:

使用HAL這種設計模式,使得上層服務與底層硬件之間的耦合度降低。

 

2、Stub HAL

Android系統中HAL具有兩種實現方式:Legacy以及Stub HAL,初期使用的是Legacy HAL的方式,該方式為標准的Linux共享庫,其它應用程序直接調用HAL層共享庫導出的函數。Google后來提出了Stub HAL的方式,仍然以共享庫(.so)的形式提供,它把所有供外部訪問的的方法(函數)的入口指針保存在統一的數據結構,其它程序需要訪問HAL中方法時,需要先獲得Stub,然后通過具體的函數指針去讀寫底層設備。

 

3、HAL標准接口的定義

Android已經為常用的硬件設備定義了標准的HAL接口,這些組件有以下:

當我們需要為這些設備編寫HAL層代碼時,必須嚴格按照Google定義的標准接口去實現,否則將導致設備無法在Android Framework下正常工作。

關於HAL的源碼在Android源碼樹的hardware目錄,其中關於Stub方式的HAL實現在libhardware目錄下:

# 常用設備HAL標准接口的頭文件
AOSP/hardware/libhardware/include/hardware

# 常用設備HAL標准接口實現
AOSP/hardware/libhardware/modules/

在目錄AOSP/hardware/libhardware/include/hardware中包含了一個hardware.h的接口頭文件,里面具有比較重要的結構體、變量和函數指針,在開發自己設備的HAL文件時,需要嵌入這些結構體,也就是繼承它們的特性,接下來對這些標准接口做介紹。

首先是struct hw_module_t結構體,定義如下:

typedef struct hw_module_t {
    uint32_t tag;
    uint16_t module_api_version;
    uint16_t hal_api_version;
    const char *id;
    const char *name;
    const char *author;
    struct hw_module_methods_t* module;
    void* dso;
    uint32_t reserved[32-7];
} hw_module_t;

成員簡單介紹:

tag:該值為module的tag,必須定義為HARDWARE_MODULE_TAG;

module_api_version:模塊中API函數接口的版本號;

hal_api_version:HAL模塊接口的API版本號;

id:硬件的id號,唯一標識模塊;

name:該模塊的名稱;

author:模塊的作者;

module:指向封裝有open函數指針的結構體,用於模塊打開。

對於struct hw_module_t結構體的理解為,每個硬件通過hw_module_t結構體來描述,我們可以"繼承"這個結構體,拓展自己的屬性,但是需要注意的是,宿主結構的第一個成員必須是struct hw_module_t類型,硬件對象必須定義一個固定的名字:HMI(Hardware Module Information),每個硬件對象里面都包含了module指針,對應得結構體里面封裝了open函數指針,用於打開硬件,並會返回硬件的操作方式。

接下來是struct hw_module_methods_t結構體的定義,如下所示:

typedef struct hw_module_methods_t {
    int (*open)(const struct hw_module_t* module, const char* id,
            struct hw_device_t** device);

} hw_module_methods_t;

該結構體里面封裝了一個open函數指針,該函數用於實現打開一個特定的設備,打開的設備通過device二級指針進行返回。

另外一個重要的結構體為struct hw_device_t,該定義如下:

typedef struct hw_device_t {
    uint32_t tag;
    uint32_t version;
    struct hw_module_t* module;
    uint32_t reserved[12];
    int (*close)(struct hw_device_t* device);
} hw_device_t;

成員簡單介紹:

tag:設備的tag,必須定義為HARDWARE_DEVICE_TAG;

version:設備操作方式的版本號;

module:hw_module_t結構體指針,指向設備所屬的硬件模塊,設備操作接口與硬件模塊的聯系;

close:函數指針,關閉該硬件設備的方法。

對於struct hw_device_t結構體的理解為,硬件設備的操作方法,通過struct module_methods_t結構內的open函數指針將返回hw_device_t結構體指針,從而獲得了該硬件設備的操作方法,我們也可以"繼承"該結構體,拓展實際硬件設備的操作方式,但是需要注意的是,在宿主結構中,第一個成員必須是struct hw_device_t類型。

在上面介紹的三個結構之間是緊密聯系的,每個硬件模塊都由一個struct hw_module_t結構體進行描述,當用戶拿到了這個硬件模塊,調用其封裝的open函數,便返回了硬件設備的操作方法接口,從而便可以調用相關接口對硬件設備進行讀寫了。

在HAL標准中還有兩個比較重要的宏定義和一個函數,如下:

/**
 * Name of the hal_module_info
 */
#define HAL_MODULE_INFO_SYM         HMI

/**
 * Name of the hal_module_info as a string
 */
#define HAL_MODULE_INFO_SYM_AS_STR  "HMI"

/**
 * Get the module info associated with a module by id.
 *
 * @return: 0 == success, <0 == error and *module == NULL
 */
int hw_get_module(const char *id, const struct hw_module_t **module);

在上面的代碼中,HAL_MODULE_INFO_SYM為硬件模塊固定的變量名,另外一個宏只是字符串的顯示,當用戶調用hw_get_module()函數時,將硬件的id名進行傳入,那么函數將會從當前系統中注冊的硬件模塊里查找對應的硬件模塊,並通過module二級指針進行返回。

 

4、小結

本篇文章對Android系統中HAL的基本概念做簡單介紹,另外,對HAL提供的接口進行了簡單的描述。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM