转自: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;
}