- 前言
- 代码流程分析
- 总结
前言
接上一篇Android R camera Hal启动(上)接着写,把谷歌的代码都分析完成,高通/MTK的代码就不贴了。
代码流程分析
上一篇说到getProviderImpl函数。实例化了CameraProvider对象,先看CameraProvider的构造函数。
templatestruct CameraProvider : public ICameraProvider { CameraProvider() : impl() {} ... }
调用了impl也就是LegacyCameraProviderImpl_2_4的构造。
LegacyCameraProviderImpl_2_4::LegacyCameraProviderImpl_2_4() :
camera_module_callbacks_t({sCameraDeviceStatusChange,
sTorchModeStatusChange}) {
mInitFailed = initialize();
}
camera_module_callbacks_t是HAL的回调函数,用于通知FW相机状态更新。直接看构造函数调用camera_module_callbacks_t比较奇怪,先看下LegacyCameraProviderImpl_2_4的类的申明和sCameraDeviceStatusChange/sTorchModeStatusChange两个函数的定义就能明白了。
struct LegacyCameraProviderImpl_2_4 : public camera_module_callbacks_t {
...
static void sCameraDeviceStatusChange(
const struct camera_module_callbacks* callbacks,
int camera_id,
int new_status);
static void sTorchModeStatusChange(
const struct camera_module_callbacks* callbacks,
const char* camera_id,
int new_status);
...
}
LegacyCameraProviderImpl_2_4是继承了camera_module_callbacks_t,所以类构造的同时使用sCameraDeviceStatusChange/sTorchModeStatusChange初始化了camera_module_callbacks_t中的camera_device_status_change/torch_mode_status_change函数指针。
camera_module_callbacks_t结构定义如下:
typedef struct camera_module_callbacks {
void (*camera_device_status_change)(const struct camera_module_callbacks*,
int camera_id,
int new_status);
void (*torch_mode_status_change)(const struct camera_module_callbacks*,
const char* camera_id,
int new_status);
} camera_module_callbacks_t;
再继续往下看,调用mInitFailed = initialize();看下initialize的实现:
bool LegacyCameraProviderImpl_2_4::initialize() {
camera_module_t *rawModule;
int err = hw_get_module(CAMERA_HARDWARE_MODULE_ID,
(const hw_module_t **)&rawModule);
if (err < 0) {
ALOGE("Could not load camera HAL module: %d (%s)", err, strerror(-err));
return true;
}
mModule = new CameraModule(rawModule);
err = mModule->init();
if (err != OK) {
ALOGE("Could not initialize camera HAL module: %d (%s)", err, strerror(-err));
mModule.clear();
return true;
}
ALOGI("Loaded "%s" camera module", mModule->getModuleName());
// Setup vendor tags here so HAL can setup vendor keys in camera characteristics
VendorTagDescriptor::clearGlobalVendorTagDescriptor();
if (!setUpVendorTags()) {
ALOGE("%s: Vendor tag setup failed, will not be available.", __FUNCTION__);
}
// Setup callback now because we are going to try openLegacy next
err = mModule->setCallbacks(this);
if (err != OK) {
ALOGE("Could not set camera module callback: %d (%s)", err, strerror(-err));
mModule.clear();
return true;
}
mPreferredHal3MinorVersion =
property_get_int32("ro.vendor.camera.wrapper.hal3TrebleMinorVersion", 3);
ALOGV("Preferred HAL 3 minor version is %d", mPreferredHal3MinorVersion);
switch(mPreferredHal3MinorVersion) {
case 2:
case 3:
// OK
break;
default:
ALOGW("Unknown minor camera device HAL version %d in property "
"'camera.wrapper.hal3TrebleMinorVersion', defaulting to 3",
mPreferredHal3MinorVersion);
mPreferredHal3MinorVersion = 3;
}
mNumberOfLegacyCameras = mModule->getNumberOfCameras();
for (int i = 0; i < mNumberOfLegacyCameras; i++) {
uint32_t device_version;
auto rc = mModule->getCameraDeviceVersion(i, &device_version);
if (rc != NO_ERROR) {
ALOGE("%s: Camera device version query failed!", __func__);
mModule.clear();
return true;
}
if (checkCameraVersion(i, device_version) != OK) {
ALOGE("%s: Camera version check failed!", __func__);
mModule.clear();
return true;
}
char cameraId[kMaxCameraIdLen];
snprintf(cameraId, sizeof(cameraId), "%d", i);
std::string cameraIdStr(cameraId);
mCameraStatusMap[cameraIdStr] = CAMERA_DEVICE_STATUS_PRESENT;
addDeviceNames(i);
}
return false; // mInitFailed
}
先看hw_get_module函数:hardware/libhardware/hardware.c
int hw_get_module(const char *id, const struct hw_module_t **module)
{
return hw_get_module_by_class(id, NULL, module);
}
int hw_get_module_by_class(const char *class_id, const char *inst,
const struct hw_module_t **module)
{
int i = 0;
char prop[PATH_MAX] = {0};
char path[PATH_MAX] = {0};
char name[PATH_MAX] = {0};
char prop_name[PATH_MAX] = {0};
if (inst)
snprintf(name, PATH_MAX, "%s.%s", class_id, inst);
else
strlcpy(name, class_id, PATH_MAX);
snprintf(prop_name, sizeof(prop_name), "ro.hardware.%s", name);
if (property_get(prop_name, prop, NULL) > 0) {
if (hw_module_exists(path, sizeof(path), name, prop) == 0) {
goto found;
}
}
for (i=0 ; i
hw_get_module会调用hw_get_module_by_class去找到实现HAL的so,class_id的值就是camera。先根据ro.hardware.camera的prop来找,这是没有的,然后就是根据variant_keys的数组查找对应的prop。
static const char *variant_keys[] = {
"ro.hardware",
"ro.product.board",
"ro.board.platform",
"ro.arch"
};
高通的平台ro.hardware的值是qcom,因为这个数组中的prop的值get出来之后能找到对应的so,所以就会调用hw_module_exists拼接这个so的完整路径,如果找不到的话就会调用hw_module_exists拼接camera.default.so的全路径,camera.default.so的源码在hardware/libhardware/modules/camera/3_0目录下,平台方会自己实现camera.xxx.so,所以这里可以看成谷歌写的一个demo,如果自己想写一个camera HAL的话,可以参考着写。
再继续看hw_get_module_by_class,通过hw_module_exists拿到全路径之后,继续调用load。
static int load(const char *id,
const char *path,
const struct hw_module_t **pHmi)
{
int status = -EINVAL;
void *handle = NULL;
struct hw_module_t *hmi = NULL;
#ifdef __ANDROID_VNDK__
const bool try_system = false;
#else
const bool try_system = true;
#endif
if (try_system &&
strncmp(path, HAL_LIBRARY_PATH1, strlen(HAL_LIBRARY_PATH1)) == 0) {
handle = dlopen(path, RTLD_NOW);
} else {
#if defined(__ANDROID_RECOVERY__)
handle = dlopen(path, RTLD_NOW);
#else
handle = android_load_sphal_library(path, RTLD_NOW);
#endif
}
if (handle == NULL) {
char const *err_str = dlerror();
ALOGE("load: module=%sn%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);
if (hmi == NULL) {
ALOGE("load: couldn't find symbol %s", sym);
status = -EINVAL;
goto done;
}
if (strcmp(id, hmi->id) != 0) {
ALOGE("load: id=%s != hmi->id=%s", id, hmi->id);
status = -EINVAL;
goto done;
}
hmi->dso = handle;
status = 0;
done:
if (status != 0) {
hmi = NULL;
if (handle != NULL) {
dlclose(handle);
handle = NULL;
}
} else {
ALOGV("loaded HAL id=%s path=%s hmi=%p handle=%p",
id, path, hmi, handle);
}
*pHmi = hmi;
return status;
}
load函数会根据上面传过来的地址通过dlopen打开camera.xxxx.so,这里打开的就是/vendor/lib64/hw/camera.qcom.so。然后再通过HAL_MODULE_INFO_SYM_AS_STR找到对应的符号链接。
#define HAL_MODULE_INFO_SYM_AS_STR "HMI"
这里为什么要用HMI,自行谷歌搜索,我一开始看到这里也很懵。谷歌搜完了只知道反正就是这么定的,想要用dlsym找到对应的符号,必须要这么写:
camera_module_t HAL_MODULE_INFO_SYM __attribute__ ((visibility("default")))
再用readelf -s camera.xxxx.so可以看到符号表里面有HMI。下面是我拿手机看的符号表:
0000000000802718 344 OBJECT GLOBAL DEFAULT 23 HMI
既然一定要有camera_module_t HAL_MODULE_INFO_SYM,那就到平台的代码里面找一下。
果然,在平台的代码里面找到了camera_module_t HAL_MODULE_INFO_SYM对应的实现。
到这里就明白了,谷歌只是注册了一个hidl服务,怎么就能调用到平台的代码完成初始化了。
再往下就是平台的具体实现,代码就不贴了,继续回头看bool LegacyCameraProviderImpl_2_4::initialize()函数。
接下来就是初始化module:
mModule = new CameraModule(rawModule);
hardware/interfaces/camera/provider/2.4/default/LegacyCameraProviderImpl_2_4.h中定义了:
using ::android::hardware::camera::common::V1_0::helper::CameraModule;
还是和前面一样,先看一下如何使用这个CameraModule的,先看一下hardware/interfaces/camera/common/1.0/default/Android.bp
cc_library_static {
name: "android.hardware.camera.common@1.0-helper",
vendor_available: true,
defaults: ["hidl_defaults"],
srcs: [
"CameraModule.cpp",
"Camerametadata.cpp",
"CameraParameters.cpp",
"VendorTagDescriptor.cpp",
"Handleimporter.cpp",
"Exif.cpp",
],
cflags: [
"-Werror",
"-Wextra",
"-Wall",
],
shared_libs: [
"liblog",
"libgralloctypes",
"libhardware",
"libcamera_metadata",
"android.hardware.graphics.mapper@2.0",
"android.hardware.graphics.mapper@3.0",
"android.hardware.graphics.mapper@4.0",
"libexif",
],
include_dirs: ["system/media/private/camera/include"],
export_include_dirs: ["include"],
}
cc_library_static说明这是一个静态库,应该直接就link到android.hardware.camera.provider@2.4-impl.so里面了。找了个手机看来一下,果然搜不到这个库,再看一下android.hardware.camera.provider@2.4-impl的编译文件。
cc_library_shared {
name: "android.hardware.camera.provider@2.4-impl",
...
static_libs: [
"android.hardware.camera.common@1.0-helper",
],
...
}
再看CameraModule的构造:
CameraModule::CameraModule(camera_module_t *module) : mNumberOfCameras(0) {
if (module == NULL) {
ALOGE("%s: camera hardware module must not be null", __FUNCTION__);
assert(0);
}
mModule = module;
}
因为CameraModule就是相机HAL的一个封装,所以初始化就是要保存camera_module_t到mModule。再继续看initialize函数。调用了err = mModule->init();这个实际上就是camera_module_t的init,平台的代码中实现了init,谷歌原生代码并没有实现这部分。再往下就没有什么特殊的代码就是一些初始化,获取属性,最终将camera状态设置成CAMERA_DEVICE_STATUS_PRESENT。initialize函数初始化完成,返回值是false。。。最终这个值给到mInitFailed。
这里的代码看完,再回到hardware/interfaces/camera/provider/2.4/default/CameraProvider_2_4.cpp中,provider初始化完成,调用provider->isInitFailed()检查是不是init成功。
总结
到这里就全部结束了,上面的流程是按照看代码的过程写的,有点乱,好多细节也没有说,不过也算是梳理了整个代码流程。最主要是说明HAL进程如何加载平台so并且关联到平台代码的。



