转自:http://hi.baidu.com/xdyang1986/blog/item/1681d3d4ef4a63d251da4bd5.html
这个函数的主要功能是根据模块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中
static int load(const char *id, const char *path, const struct hw_module_t **pHmi) { int status; void *handle; struct hw_module_t *hmi; 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; }
const char *sym = HAL_MODULE_INFO_SYM_AS_STR; hmi = (struct hw_module_t *)dlsym(handle, sym);//找到库中的HMI函数的地址(据snownight0102说,HMI不是一个函数,我还不是很清楚,等待解释) 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) {//只是一个check LOGE("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 { LOGV("loaded HAL id=%s path=%s hmi=%p handle=%p", id, path, *pHmi, handle); } *pHmi = hmi;//把这个返回过去 return status; }
以上为转载
以下为hardware/libhardware/hardware.c
/* * Copyright (C) 2008 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include <hardware/hardware.h> #include <cutils/properties.h> #include <dlfcn.h> #include <string.h> #include <pthread.h> #include <errno.h> #include <limits.h> #define LOG_TAG "HAL" #include <utils/Log.h> /** Base path of the hal modules */ #define HAL_LIBRARY_PATH "/system/lib/hw" /** * There are a set of variant filename for modules. The form of the filename * is "<MODULE_ID>.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" }; static const int HAL_VARIANT_KEYS_COUNT = (sizeof(variant_keys)/sizeof(variant_keys[0])); /** * 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; 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) { LOGE("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 { LOGV("loaded HAL id=%s path=%s hmi=%p handle=%p", id, path, *pHmi, handle); } *pHmi = hmi; return status; } int hw_get_module(const char *id, const struct hw_module_t **module) { int status; int i; const struct hw_module_t *hmi = NULL; char prop[PATH_MAX]; char path[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<HAL_VARIANT_KEYS_COUNT+1 ; i++) { if (i < HAL_VARIANT_KEYS_COUNT) { if (property_get(variant_keys[i], prop, NULL) == 0) { continue; } snprintf(path, sizeof(path), "%s/%s.%s.so", HAL_LIBRARY_PATH, id, prop); } else { snprintf(path, sizeof(path), "%s/%s.default.so", HAL_LIBRARY_PATH, id); } if (access(path, R_OK)) { continue; } /* we found a library matching this id/variant */ 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(id, path, module); } return status; }