这个函数的主要功能是根据模块ID寻找硬件模块动态链接库德地址,然后调用load去打开动态链接库并从中获取硬件模块结构体地址。具体的源码如下:
代码@/hardware/libhardware/hardware.c
int hw_get_module(const char *id, const struct hw_module_t **module)
120 {
121 int status;
122 int i;
123 const struct hw_module_t *hmi = NULL;
124 char prop[PATH_MAX];
125 char path[PATH_MAX];
/* Loop through the configuration variants looking for a module */
135 for (i=0 ; i<HAL_VARIANT_KEYS_COUNT+1 ; i++) {
/*
*这个地方我们来看一下下面将要用到的一个数组variant_keys,因为HAL_VARIANT_KEYS_COUNT这个就是
*数组variant_keys的大小。
*
*44 static const char *variant_keys[] = {
* 45 "ro.hardware", /* This goes first so that it can pick up a different
* 46 file on the emulator. */
* 47 "ro.product.board",
* 48 "ro.board.platform",
* 49 "ro.arch"
* 50 };
*这里我们记住这个数组,下面我就将用到它。
*/
136 if (i < HAL_VARIANT_KEYS_COUNT) {
137 if (property_get(variant_keys[i], prop, NULL) == 0) {
138 continue;
139 }
/*
*这个地方prop得到的就似乎相应的权限,variant_keys[i]对应的如下:
*
*trout\msm7k\ARMV6就是这三个值,那个ro.hardware没有找到。这个地方我也是看注册的,没有弄懂
*知道的同学指教一些,谢谢。
*/
140 snprintf(path, sizeof(path), "%s/%s.%s.so",//把相应的路径及文件名保存到path中
141 HAL_LIBRARY_PATH, id, prop);
/*
*看到没有,这个地方其实就是把HAL_LIBRARY_PATH/id.***.so保存到path中,其中***就是上面我们所分析的variant_keys各个元素所对应的值。
*/
142 } else {
/*
*这个地方就体现了为什么我们上面for循环用的是HAL_VARIANT_KEYS_COUNT+1而不是*HAL_VARIANT_KEYS_COUNT。因为我们在最后还有加载一个default的属性。
*/
143 snprintf(path, sizeof(path), "%s/%s.default.so",
144 HAL_LIBRARY_PATH, id);
145 }
146 if (access(path, R_OK)) {
147 continue;
148 }
149 /* we found a library matching this id/variant */
150 break;
151 }
152
153 status = -ENOENT;
154 if (i < HAL_VARIANT_KEYS_COUNT+1) {
155 /* load the module, if this fails, we're doomed, and we should not try
156 * to load a different variant. */
157 status = load(id, path, module);//load相应库。并把它们的HMI保存到module中。//具体见西分析
158 }
159
return status;
161 }
代码@/hardware/libhardware/hardware.c
这个代码其实很简单。load相应库。并把它们的HMI保存到module中
0 static int load(const char *id,
61 const char *path,
62 const struct hw_module_t **pHmi)
63 {
64 int status;
65 void *handle;
66 struct hw_module_t *hmi;
handle = dlopen(path, RTLD_NOW);//打开相应的库
74 if (handle == NULL) {
75 char const *err_str = dlerror();
76 LOGE("load: module=%s\n%s", path, err_str?err_str:"unknown");
77 status = -EINVAL;
78 goto done;
79 }
82 const char *sym = HAL_MODULE_INFO_SYM_AS_STR;
83 hmi = (struct hw_module_t *)dlsym(handle, sym);//找到库中的HMI函数的地址(据snownight0102说,HMI不是一个函数,我还不是很清楚,等待解释)
84 if (hmi == NULL) {
85 LOGE("load: couldn't find symbol %s", sym);
86 status = -EINVAL;
87 goto done;
88 }
89
90 /* Check that the id matches */
91 if (strcmp(id, hmi->id) != 0) {//只是一个check
92 LOGE("load: id=%s != hmi->id=%s", id, hmi->id);
93 status = -EINVAL;
94 goto done;
95 }
96
97 hmi->dso = handle;
98
99 /* success */
100 status = 0;
done:
103 if (status != 0) {
104 hmi = NULL;
105 if (handle != NULL) {
106 dlclose(handle);
107 handle = NULL;
108 }
109 } else {
110 LOGV("loaded HAL id=%s path=%s hmi=%p handle=%p",
111 id, path, *pHmi, handle);
112 }
113
114 *pHmi = hmi;//把这个返回过去
115
116 return status;
117 }