hw_get_module是jni层获取HAL层module的接口函数,原型为:int hw_get_module(const char *id, const struct hw_module_t **module)
这个id是hal层注册时加入的,例如sensor的hal的定义
struct sensors_module_t HAL_MODULE_INFO_SYM = {
.common = {
.tag = HARDWARE_MODULE_TAG,
.version_major = 1,
.version_minor = 0,
.id = SENSORS_HARDWARE_MODULE_ID,
.name = "MTK SENSORS Module",
.author = "The Android Open Source Project",
.methods = &sensors_module_methods,
},
.get_sensors_list = sensors__get_sensors_list,
};
#define SENSORS_HARDWARE_MODULE_ID "sensors"
hw_module_t是硬件模块结构,是HAL层的灵魂
下面来看hw_get_module是怎么去抓相应的HAL层硬件模块的
for (i=0 ; i
if (i < HAL_VARIANT_KEYS_COUNT) {
if (property_get(variant_keys[i], prop, NULL) == 0) {
continue;
}
/*获取ro.hardware/ro.product.board/ro.board.platform/ro.arch等key的值*/
snprintf(path, sizeof(path), "%s/%s.%s.so",
HAL_LIBRARY_PATH2, name, prop)
;
/*这个name是之前传进来的id,在我们这里就是"sensor",prop为之前抓取到的key信息,这里为mt6575*/
if (access(path, R_OK) == 0) break;
/*下面的这几个函数在给定的几个目录中搜索我们要加载的库sensors.mt6575.so*/
snprintf(path, sizeof(path), "%s/%s.%s.so",
HAL_LIBRARY_PATH1, name, prop);
if (access(path, R_OK) == 0) break;
snprintf(path, sizeof(path), "%s/%s.%s.so",
HAL_LIBRARY_PATH3, name, prop);
if (access(path, R_OK) == 0) break;
} else {
/*如果上面没有收到,则用默认库*/
snprintf(path, sizeof(path), "%s/%s.default.so",
HAL_LIBRARY_PATH1, name);
if (access(path, R_OK) == 0) break;
snprintf(path, sizeof(path), "%s/%s.default.so",
HAL_LIBRARY_PATH3, 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);
}
找到这次需要加载的库后,即调用load函数
static int load(const char *id,
const char *path,
const struct hw_module_t **pHmi)
{
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"*/
hmi = (struct hw_module_t *)dlsym(handle, sym);
/*获取hw_module_t 结构体*/
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) {
/*对比hw_module_t结构体总的id和我们传进来的id是否一致,不一致的话直接退出*/
LOGE("load: id=%s != hmi->id=%s", id, hmi->id);
status = -EINVAL;
goto done;
}
hmi->dso = handle;
/* success */
status = 0;
*pHmi = hmi;/*返回结果*/
return status;
}
通过readelf x.so来看看这个库的地址布局
Symbol table '.dynsym' contains 40 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 00000000 0 NOTYPE LOCAL DEFAULT UND
1: 000021d8 340 OBJECT GLOBAL DEFAULT 15 sSensorList
2: 00000000 0 FUNC GLOBAL DEFAULT UND __aeabi_unwind_cpp_pr0
3: 00000000 0 FUNC GLOBAL DEFAULT UND __android_log_print
4: 00000000 0 FUNC GLOBAL DEFAULT UND ioctl
5: 00000000 0 FUNC GLOBAL DEFAULT UND __aeabi_ldivmod
6: 00000000 0 FUNC GLOBAL DEFAULT UND __errno
7: 00000000 0 FUNC GLOBAL DEFAULT UND __aeabi_unwind_cpp_pr1
8: 00000000 0 FUNC GLOBAL DEFAULT UND malloc
9: 00000000 0 FUNC GLOBAL DEFAULT UND memset
10: 00000000 0 FUNC GLOBAL DEFAULT UND opendir
11: 00000000 0 FUNC GLOBAL DEFAULT UND strcpy
12: 00000000 0 FUNC GLOBAL DEFAULT UND strlen
13: 00000000 0 FUNC GLOBAL DEFAULT UND open
14: 00000000 0 FUNC GLOBAL DEFAULT UND strcmp
15: 00000000 0 FUNC GLOBAL DEFAULT UND close
16: 00000000 0 FUNC GLOBAL DEFAULT UND readdir
17: 00000000 0 FUNC GLOBAL DEFAULT UND closedir
18: 00000000 0 FUNC GLOBAL DEFAULT UND strerror
19: 00000000 0 FUNC GLOBAL DEFAULT UND __stack_chk_fail
20: 00000000 0 OBJECT GLOBAL DEFAULT UND __stack_chk_guard
21: 00000000 0 FUNC GLOBAL DEFAULT UND free
22: 00000000 0 FUNC GLOBAL DEFAULT UND memcpy
23: 00000000 0 FUNC GLOBAL DEFAULT UND read
24: 00002150 132 OBJECT GLOBAL DEFAULT 15 HMI
25: 00000000 0 FUNC GLOBAL DEFAULT UND __cxa_finalize
26: 00002330 0 NOTYPE GLOBAL DEFAULT 16 __dso_handle
27: 00002000 0 NOTYPE GLOBAL DEFAULT 11 __INIT_ARRAY__
28: 00002008 0 NOTYPE GLOBAL DEFAULT 12 __FINI_ARRAY__
29: 000013d0 0 NOTYPE GLOBAL DEFAULT ABS __exidx_end
30: 00001388 0 NOTYPE GLOBAL DEFAULT ABS __exidx_start
31: 00002150 0 NOTYPE GLOBAL DEFAULT 15 __data_start
32: 0000232c 0 NOTYPE GLOBAL DEFAULT ABS _edata
33: 0000232c 0 NOTYPE GLOBAL DEFAULT ABS __bss_start
34: 0000232c 0 NOTYPE GLOBAL DEFAULT ABS __bss_start__
35: 00002340 0 NOTYPE GLOBAL DEFAULT ABS _bss_end__
36: 00002340 0 NOTYPE GLOBAL DEFAULT ABS __bss_end__
37: 00002340 0 NOTYPE GLOBAL DEFAULT ABS __end__
38: 00002340 0 NOTYPE GLOBAL DEFAULT ABS _end
39: 00080000 0 NOTYPE GLOBAL DEFAULT ABS _stack
上面的"HMI"段就是我们之前定义的,即是hw_module_t结构体,每个hw_module_t的定义中名字都叫HAL_MODULE_INFO_SYM
实际上他还是由宏定义为"HMI"的
所以综上,可以得出,一个HAL模块也有一个入口地址,就是我们这里的hw_module_t结构体,通过它就可以把我们定义的接口给上层使用