Android的Framework分析---4硬體抽象HAL

來源:互聯網
上載者:User

標籤:android   style   class   blog   c   code   

大家都知道android是基於linux的kernel上的。android可以 運行在intel,高通,nvidia等硬體平台。但是涉及到一些GPU,顯卡和一些裝置的驅動問題,因為這些驅動都不是開源的,google位了相容這些裝置廠商的驅動源碼,提出了硬體抽象層HAL的概念。HAL層對上為framework和native開發提供統一的API介面,為下層驅動的代碼提供統一的調用介面。本文主要講解HAL是如何?的。

1.HAL的資料結構

 HAL的通用寫法裡面有兩個重要的結構體:

1.1 hw_module_t 硬體模組結構體

typedef struct hw_module_t {    /** tag must be initialized to HARDWARE_MODULE_TAG */    uint32_t tag;      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 */    struct hw_module_methods_t* methods;    /** module's dso */    void* dso;    /** 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;
模組方法的結構體,open的函數指標,用於開啟一個硬體裝置hw_device_t。開發人員需要實現這個open函數。

1.2硬體裝置結構體

typedef struct hw_device_t {    /** tag must be initialized to HARDWARE_DEVICE_TAG */    uint32_t tag;    uint32_t version;    /** reference to the module this device belongs to */    struct hw_module_t* module;    /** padding reserved for future use */    uint32_t reserved[12];    /** Close this device */    int (*close)(struct hw_device_t* device);} hw_device_t;
表示一個硬體抽象裝置。這是通用的結構體,開發人員可以繼承這個結構體添加自己需要的介面。

1.3 擷取一個hw_model_t模組

HAL層提供一個方法使用者擷取一個model,進而同過open方法開啟裝置device

/** * 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);
定義一個全域變數

const struct hw_module_t   HAL_MODULE_INFO_SYM={ ...};

用於在hw_get_modules通過解析so時,得到該全域變數。

2.硬體模組庫的裝載於解析
裝載和解析有hw_get_module 完成,它會安按照一定的規則去尋找so庫,然後解析出全域變數名,得到硬體裝置的open函數,最後通過參數返回一個device的指標給調用者。

2.1搜尋so的規則;

 

/** Base path of the hal modules */#define HAL_LIBRARY_PATH1 "/system/lib/hw"#define HAL_LIBRARY_PATH2 "/vendor/lib/hw"/** * There are a set of variant filename for modules. The form of the filename * is "<MODULE_ID>.variant.so" so for the led module the Dream variants  * of base "ro.product.board", "ro.board.platform" and "ro.arch" would be: * * led.trout.so * led.msm7k.so * led.ARMV6.so * led.default.so */static const char *variant_keys[] = {    "ro.hardware",  /* This goes first so that it can pick up a different                       file on the emulator. */    "ro.product.board",    "ro.board.platform",    "ro.arch"};
搜尋規則就是按照上面的說明進行。

2.2函數載入解析的過程

(1)調用hw_get_module,通過傳給他一個module_id 字串例如“camera”等。調用hw_get_module_by_class(id, NULL, module);

 (2)搜尋對應的so並調用load去解析so

int hw_get_module_by_class(const char *class_id, const char *inst,                           const struct hw_module_t **module){    int status = -EINVAL;    int i = 0;    char prop[PATH_MAX] = {0};    char path[PATH_MAX] = {0};    char name[PATH_MAX] = {0};    if (inst)        snprintf(name, PATH_MAX, "%s.%s", class_id, inst);    else        strlcpy(name, class_id, PATH_MAX);    /*     * Here we rely on the fact that calling dlopen multiple times on     * the same .so will simply increment a refcount (and not load     * a new copy of the library).     * We also assume that dlopen() is thread-safe.     */    /* Loop through the configuration variants looking for a module */    for (i=0 ; i<HAL_VARIANT_KEYS_COUNT+1 ; i++) {        if (i < HAL_VARIANT_KEYS_COUNT) {            if (property_get(variant_keys[i], prop, NULL) == 0) {                continue;            }            snprintf(path, sizeof(path), "%s/%s.%s.so",                     HAL_LIBRARY_PATH2, name, prop);            if (access(path, R_OK) == 0) break;            snprintf(path, sizeof(path), "%s/%s.%s.so",                     HAL_LIBRARY_PATH1, name, prop);            if (access(path, R_OK) == 0) break;        } else {            snprintf(path, sizeof(path), "%s/%s.default.so",                     HAL_LIBRARY_PATH2, name);            if (access(path, R_OK) == 0) break;            snprintf(path, sizeof(path), "%s/%s.default.so",                     HAL_LIBRARY_PATH1, name);            if (access(path, R_OK) == 0) break;        }    }    status = -ENOENT;    if (i < HAL_VARIANT_KEYS_COUNT+1) {        /* load the module, if this fails, we're doomed, and we should not try         * to load a different variant. */        status = load(class_id, path, module);    }    return status;}
(3)load函數解析so,得到hw_module_t的hw_device_t的函數指標。

/** * Load the file defined by the variant and if successful * return the dlopen handle and the hmi. * @return 0 = success, !0 = failure. */static int load(const char *id,        const char *path,        const struct hw_module_t **pHmi){    int status = -EINVAL;    void *handle = NULL;    struct hw_module_t *hmi = NULL;    /*     * load the symbols resolving undefined symbols before     * dlopen returns. Since RTLD_GLOBAL is not or'd in with     * RTLD_NOW the external symbols will not be global     */    handle = dlopen(path, RTLD_NOW);    if (handle == NULL) {        char const *err_str = dlerror();        ALOGE("load: module=%s\n%s", path, err_str?err_str:"unknown");        status = -EINVAL;        goto done;    }    /* Get the address of the struct hal_module_info. */    const char *sym = HAL_MODULE_INFO_SYM_AS_STR;    hmi = (struct hw_module_t *)dlsym(handle, sym);    if (hmi == NULL) {        ALOGE("load: couldn't find symbol %s", sym);        status = -EINVAL;        goto done;    }    /* Check that the id matches */    if (strcmp(id, hmi->id) != 0) {        ALOGE("load: id=%s != hmi->id=%s", id, hmi->id);        status = -EINVAL;        goto done;    }    hmi->dso = handle;    /* success */    status = 0;    done:    if (status != 0) {        hmi = NULL;        if (handle != NULL) {            dlclose(handle);            handle = NULL;        }    } else {        ALOGV("loaded HAL id=%s path=%s hmi=%p handle=%p",                id, path, *pHmi, handle);    }    *pHmi = hmi;    return status;}


相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.