前面分析了android HAL層是如何搜索硬件模塊的動態共享庫的,其實就是在"system/lib/hw/"或者"/vendor/lib/hw/"這兩個路徑下找到共享庫modueid.variant.so後,經過調用load函數加載庫。android
下面咱們進入load函數,看看具體是如何實現加載共享庫的。架構
如下爲load函數定義,一樣在/hardware/libhardware/hardware.c中實現的。函數
/** * 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) {//傳入硬件模塊id和庫所在路徑,獲取到硬件模塊結構體 int status; void *handle; struct hw_module_t *hmi; /* * 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(); LOGE("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) { LOGE("load: couldn't find symbol %s", sym); status = -EINVAL; goto done; } /* Check that the id matches */ if (strcmp(id, hmi->id) != 0) {//匹配解析出硬件模塊的id和傳入咱們實際想要獲得的模塊id是否一致 LOGE("load: id=%s != hmi->id=%s", id, hmi->id); status = -EINVAL; goto done; } hmi->dso = handle; //將打開庫獲得句柄傳給硬件模塊的dso /* success */ status = 0; done: if (status != 0) { hmi = NULL; if (handle != NULL) { dlclose(handle); handle = NULL; } } else { LOGV("loaded HAL id=%s path=%s hmi=%p handle=%p", id, path, *pHmi, handle); } *pHmi = hmi;//將獲得的module的結果經過第三個參數傳給hw_module_t return status; }
能夠看到load函數傳入的幾個參數,第一個參數就是須要加載的硬件模塊對應動態庫的硬件模塊的id,spa
第二個參數就是動態庫存放的路徑,就是在hw_get_module函數前部分搜索庫獲得的path,指針
第三個參數就是咱們須要獲得的硬件模塊結構體,經過它傳給hw_get_module,hw_get_module函數在經過參數傳給jni。code
第19行,首先調用dlopen打開共享庫,該函數經過傳入的庫的路徑找到庫,而且打開它,傳回一個操做句柄handle,而後再調用dlsym函數解析這個打開的庫,下面第29行,獲得庫中包含的硬件模塊結構體,並將它返回回來。因此硬件廠商或者硬件移植者都必須根據hal的這個架構去實現填充這個和本身硬件相關的硬件模塊結構體hw_module_t,供使用。blog
經過dlsym解析以後就獲得了hw_module_t,隨後第37行,將從庫中解析獲得的結構體中的id和傳入的id作比較,看是否一致。get
若是一致則證實就是獲得正確的硬件模塊了。it
最後第60行,將hw_module_t結構體指針傳給第三個參數,傳給hw_get_module函數。class
到此,hw_get_module函數就獲得了硬件模塊結構體hw_module_t.
有了hw_module_t,那麼經過其內部的method open就能打開硬件模塊對應的設備了,經過結構體中的一些方法就能操做硬件設備了。