編輯:關於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; }
說到handler大家都很熟悉,自己也用了很久,再此總結一下 從handler的源碼角度看看handler是如何執行的。涉及到的內容:Loop Message Messa
service servicemanager /system/bin/servicemanager class core user system
之前一直是做.NET開發的,最近需要弄一個新聞app,能力有限,只能借助HTML5 WebAPP+android studio來完成這項工作。 android studi
本文實例講述了Android開發中include控件用法。分享給大家供大家參考,具體如下:我們知道,基於Android系統的應用程序的開發,界面設計是非常重要的,它關系著