目录
一. Android Camera Architecture整体架构
四. CameraProvider与CameraService、CameraHAL交互
五. CameraService调用CameraProvider
一. Android Camera Architecture整体架构
首先来看Camera Provider的位置:
Camera Provider正是包含v4l2 camera hal的核心模块,负责与虚拟Camera节点的交互。
对于各个模块关键作用如下:
- Camera Framework:以jar包形式运行在app进程中,实现了Camera Api v2标准接口,通过Camera AIDL跨进程接口将请求发送至Camera Service
- Camera Service:独立进程。通过HIDL跨进程接口将请求再次下发到Camera Provider
- Camera Provider:独立进程。内部加载了Camera HAL Module,该Module由OEM/ODM实现,遵循谷歌制定的标准Camera HAL3接口
- Camera Driver: LINUX为视频采集设备制定了标准的V4L2接口,并在内核中实现了其基础框架V4L2 Core,视频采集设备驱动厂商按照V4L2 Core的要求开发自己的驱动程序
一图胜千言,对照图走一遍流程自然全部理解。
二. Camera Provider注册时序图
三. Camera Provider初始化时序图:
在hw_get_module查找camera.xxx.so文件时,关键部分代码如下:
/*
* Check if a HAL with given name and subname exists, if so return 0, otherwise
* otherwise return negative. On success path will contain the path to the HAL.
*/
static int hw_module_exists(char *path, size_t path_len, const char *name,
const char *subname)
{
snprintf(path, path_len, "%s/%s.%s.so",
HAL_LIBRARY_PATH3, name, subname);
if (path_in_path(path, HAL_LIBRARY_PATH3) && access(path, R_OK) == 0)
return 0;
snprintf(path, path_len, "%s/%s.%s.so",
HAL_LIBRARY_PATH2, name, subname);
if (path_in_path(path, HAL_LIBRARY_PATH2) && access(path, R_OK) == 0)
return 0;
#ifndef __ANDROID_VNDK__
snprintf(path, path_len, "%s/%s.%s.so",
HAL_LIBRARY_PATH1, name, subname);
if (path_in_path(path, HAL_LIBRARY_PATH1) && access(path, R_OK) == 0)
return 0;
#endif
return -ENOENT;
}
path即为so文件路径,是通过三个字符串拼接而成。第一个字符串HAL_LIBRARY_PATH1/2/3即为时序图中列出的三个路径,第二个字符串name为传入的camera,第三个字符串需要注意,首先会先判断ro.hardware.camera是否为空,对于v4l2 camera hal而言,ro.hardware.camera=v4l2,因此第三个字符串为v4l2,最后找的so也就是camera.v4l2.so。如果ro.hardware.camera为空,则从系统中四个prop属性中获取,如下:
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]));
...
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);
/*
* 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.
*/
/* First try a property specific to the class and possibly instance */
// 此处为 ro.hardware.camera
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;
}
}
/* Loop through the configuration variants looking for a module */
for (i=0 ; i<HAL_VARIANT_KEYS_COUNT; i++) {
if (property_get(variant_keys[i], prop, NULL) == 0) {
continue;
}
if (hw_module_exists(path, sizeof(path), name, prop) == 0) {
goto found;
}
}
/* Nothing found, try the default */
if (hw_module_exists(path, sizeof(path), name, "default") == 0) {
goto found;
}
return -ENOENT;
found:
/* load the module, if this fails, we're doomed, and we should not try
* to load a different variant. */
return load(class_id, path, module);
}
使用adb shell getprop ro.hardware等共四个,可获取到对应值,高通芯片一般ro.hardware=qcom。
用dlopen查找存在对应名字的so,再用dlsym获取HAL_MODULE_INFO_SYM函数地址找到camera_module_t地址即为hal入口地好址,进而调用hal的各个接口。各个接口由OEM厂商进行具体实现,开发可在此基础上自行修改、新增,但修改的接口要符合Camera v2标准。
四. CameraProvider与CameraService、CameraHAL交互
1. 和CameraService进程通信
CameraProvider进程主要是使用了HIDL直通式的方式注册了ICameraProvider.hal中的服务端,这个是用来给CameraService进程来主动调用。
ICameraProvider.hal里面会有setCallback的函数主要是通过回调的形式让CameraService进程接收CameraProvider进程主动发送的消息。
2. 加载CameraHAL的so库
CameraProvider初始化时通过hw_module_get()加载对应的so库,获取到camera_module_t对象之后赋值给CameraModule,然后在CameraModule中通过camera_module_t获取摄像头的信息以及后续对摄像头进行操作。
五. CameraService调用CameraProvider
上面已经提到,系统启动时CameraProvider就已经注册,那么CameraService如何调用CameraProvider呢?
起点在/frameworks/av/camera/cameraserver/main_cameraserver.cpp
CameraService::instantiate();
这里需要注意CameraService继承自几个类:
class CameraService :
public BinderService<CameraService>,
public virtual ::android::hardware::BnCameraService,
public virtual IBinder::DeathRecipient,
public virtual CameraProviderManager::StatusListener
其中,BinderService实现了instantiate()方法。其中CameraService被强指针引用,首次被强指针引用会调到CameraService::onFirstRef()方法中,一路调到CameraProviderManager:
sp<provider::V2_4::ICameraProvider> interface;
interface = mServiceProxy->tryGetService(providerName);
...
providerInfo->initialize(interface, mDeviceState);
...
mProviders.push_back(providerInfo);
通过ProviderInfo来保存当前Camera Provider信息。
具体见以下博客:
Android Camera Provider and Service 启动流程_信田君9527的博客-CSDN博客_android.hardware.camera.provider