Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android的Framework分析---4硬件抽象HAL

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

編輯:關於Android編程

大家都知道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 ".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(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;
}


  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved