中調用hw_get_module
void CameraService::onFirstRef()
{
BnCameraService::onFirstRef();
if (hw_get_module(CAMERA_HARDWARE_MODULE_ID,
(const hw_module_t **)&mModule) < 0) {
LOGE("Could not load camera HAL module");
mNumberOfCameras = 0;
}
else {
mNumberOfCameras = mModule->get_number_of_cameras();
if (mNumberOfCameras > MAX_CAMERAS) {
LOGE("Number of cameras(%d) > MAX_CAMERAS(%d).",
mNumberOfCameras, MAX_CAMERAS);
mNumberOfCameras = MAX_CAMERAS;
}
for (int i = 0; i < mNumberOfCameras; i++) {
setCameraFree(i);
}
}
}
看一下hw_get_module是怎麼回事
int hw_get_module(const char *id, const struct hw_module_t **module)
{
return hw_get_module_by_class(id, NULL, module);
}
他只是一個封裝實際調用了[email protected] (hardware\libhardware)
好在不長,看看吧
int hw_get_module_by_class(const char *class_id, const char *inst,
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];//在下面起了重要
char name[PATH_MAX];//作用
if (inst)
snprintf(name, PATH_MAX, "%s.%s", class_id, inst);
else
strlcpy(name, class_id, 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)
//在這裏將prop的路徑得到,分別從
"ro.hardware[qcom]"
"ro.product.board"[7x27],
"ro.board.platform"[msm7627a],
"ro.arch",
"ro.hw_platform"[QRD_SKU3-1100]
這幾個屬性文件中獲得硬件的信息
有些硬件信息的字符串會出現在編譯後生成的.so名字中
{
continue;
}
snprintf(path, sizeof(path), "%s/%s.%s.so",
HAL_LIBRARY_PATH2, name, prop);
if (access(path, R_OK) == 0) break;
snprintf(path, sizeof(path), "%s/%s.%s.so",
HAL_LIBRARY_PATH1, name, prop);//走這裏,在這裏得到/system/lib/hw/camera.msm7627a.so
這樣一個路徑,這個庫裏有QualcommCamera.cpp,這是
camera模塊HAL代碼開始的地方
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;
}
}
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);//這裏關鍵,函數的三個參數可以串聯成一句話:
到path(/system/lib/hw/camera.msm7627a.so)這個路徑下找到一個id(camera)匹配的module
}
return status;
}
再來看看load這個函數@hardware.c (hardware\libhardware)
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;
}
在打開的.so(camera.msm7627a.so)中查找HMI符號的地址,並保存在hmi中。至此,.so中的hw_module_t已經被成功獲取,從而可以根
據它獲取別的相關接口。
1)HAL通過hw_get_module函數獲取hw_module_t
2)HAL通過hw_module_t->methods->open獲取hw_device_t指針,並在此open函數中初始化hw_device_t的包裝結構中的
函數及hw_device_t中的close函數,如gralloc_device_open。
3)三個重要的數據結構:
a) struct hw_device_t: 表示硬件設備,存儲了各種硬件設備的公共屬性和方法
b)struct hw_module_t: 可用hw_get_module進行加載的module
c)struct hw_module_methods_t: 用於定義操作設備的方法,其中只定義了一個打開設備的方法open.