前言
本篇是虚拟摄像头重构过程的系列文章,本篇博文谨分析二方面内容:
(1). 谁在调用 v4l2_camera_HAL 摄像头驱动
(2). 如何管理多版本 camera_hal 摄像头设备
CameraProvider
CameraProvider是Camera的Hal层程序的调用者,android为实现内核与驱动分离、可单独升级android内核,所引入分层方法。
CameraProvider模块作为Camera设备提供者的角色、以Servcie形式、开机就与系统一起启动。我们向看看他的Android.bp文件,
@hardware/interfaces/camera/provider/2.4/default/Android.bp
cc_binary {
name: "android.hardware.camera.provider@2.4-service",
defaults: ["hidl_defaults"],
proprietary: true,
relative_install_path: "hw",
srcs: ["service.cpp"],
compile_multilib: "32",
init_rc: ["android.hardware.camera.provider@2.4-service.rc"],
shared_libs: [
"libhidlbase",
"libhidltransport",
"libbinder",
"liblog",
"libutils",
"android.hardware.camera.device@1.0",
"android.hardware.camera.device@3.2",
"android.hardware.camera.device@3.3",
"android.hardware.camera.provider@2.4",
"android.hardware.camera.common@1.0",
],
}
服务启动配置内容:
@hardware/interfaces/camera/2.4/default/android.hardware.camera.provider@2.4-service.rc
service camera-provider-2-4 /vendor/bin/hw/android.hardware.camera.provider@2.4-service
class hal
user cameraserver
group audio camera input drmrpc
ioprio rt 4
capabilities SYS_NICE
writepid /dev/cpuset/camera-daemon/tasks /dev/stune/top-app/tasks
服务名称camera-provider-2-4。服务主函数入口内容如下:
@hardware/interfaces/camera/2.4/default/service.cpp
#define LOG_TAG "android.hardware.camera.provider@2.4-service"
#include <android/hardware/camera/provider/2.4/ICameraProvider.h>
#include <hidl/LegacySupport.h>
#include <binder/ProcessState.h>
using android::hardware::camera::provider::V2_4::ICameraProvider;
using android::hardware::defaultPassthroughServiceImplementation;
int main()
{
ALOGI("Camera provider Service is starting.");
// The camera HAL may communicate to other vendor components via
// /dev/vndbinder
android::ProcessState::initWithDriver("/dev/vndbinder");
return defaultPassthroughServiceImplementation<ICameraProvider>("legacy/0", /*maxThreads*/ 6);
}
@system/libhidl/transport/include/hidl/LegacySupport.h
/**
* Creates default passthrough service implementation. This method never returns.
*
* Return value is exit status.
*/
template<class Interface>
__attribute__((warn_unused_result))
status_t defaultPassthroughServiceImplementation(std::string name,
size_t maxThreads = 1) {
configureRpcThreadpool(maxThreads, true);
status_t result = registerPassthroughServiceImplementation<Interface>(name);
if (result != OK) {
return result;
}
joinRpcThreadpool();
return 0;
}
/**
* Registers passthrough service implementation.
*/
template<class Interface>
__attribute__((warn_unused_result))
status_t registerPassthroughServiceImplementation(
std::string name = "default") {
sp<Interface> service = Interface::getService(name, true /* getStub */);
if (service == nullptr) {
ALOGE("Could not get passthrough implementation for %s/%s.",
Interface::descriptor, name.c_str());
return EXIT_FAILURE;
}
LOG_FATAL_IF(service->isRemote(), "Implementation of %s/%s is remote!",
Interface::descriptor, name.c_str());
status_t status = service->registerAsService(name);
if (status == OK) {
ALOGI("Registration complete for %s/%s.",
Interface::descriptor, name.c_str());
} else {
ALOGE("Could not register service %s/%s (%d).",
Interface::descriptor, name.c_str(), status);
}
return status;
}
上面程序调用 sp service = Interface::getService(name, true /* getStub */); 的内容具体是谁呢?这里面涉及android的HIDL
自动生成代码部分内容,HIDL部分内容不是本文研究对象。我把android编译自动生成的文件内容贴出来,供我们分析使用;
在service.cpp文件包含的
#include <android/hardware/camera/provider/2.4/ICameraProvider.h> 头文件是 ICameraProvider.hal 文件生成的头文件,而源码
CameraProviderAll.cpp 也是根据ICameraProvider.hal 文件生成的;在笔者android source 工程中路径:
out/soong/.intermediates/hardware/interfaces/camera/provider/2.4/android.ha
rdware.camera.provider@2.4_genc++/gen/android/hardware/camera/provider/2.4/CameraProviderAll.cpp
out/soong/.intermediates/hardware/interfaces/camera/provider/2.4/android.ha
rdware.camera.provider@2.4_genc++_headers/gen/android/hardware/camera/provider/2.4/ICameraProvider.h
ICameraProvider.h中与getService相关内容如下:
static ::android::sp<ICameraProvider> getService(const char serviceName[], bool getStub=false)
{
std::string str(serviceName ? serviceName : "");
return getService(str, getStub);
}
ICameraProviderAll.cpp中与getService相关内容如下:
//> ICameraProvider::descriptor 字符串内容
const char* ICameraProvider::descriptor("android.hardware.camera.provider@2.4::ICameraProvider");
//> getService实现
static
::android::sp<ICameraProvider> ICameraProvider::getService(const std::string &serviceName, const bool getStub) {
using ::android::hardware::defaultServiceManager;
using ::android::hardware::details::waitForHwService;
using ::android::hardware::getPassthroughServiceManager;
using ::android::hardware::Return;
using ::android::sp;
using Transport = ::android::hidl::manager::V1_0::IServiceManager::Transport;
sp<ICameraProvider> iface = nullptr;
const sp<::android::hidl::manager::V1_0::IServiceManager> sm = defaultServiceManager();
if (sm == nullptr) {
ALOGE("getService: defaultServiceManager() is null");
return nullptr;
}
Return<Transport> transportRet = sm->getTransport(ICameraProvider::descriptor, serviceName);
if (!transportRet.isOk()) {
ALOGE("getService: defaultServiceManager()->getTransport returns %s", transportRet.description().c_str());
return nullptr;
}
Transport transport = transportRet;
const bool vintfHwbinder = (transport == Transport::HWBINDER);
const bool vintfPassthru = (transport == Transport::PASSTHROUGH);
#ifdef __ANDROID_TREBLE__
#ifdef __ANDROID_DEBUGGABLE__
const char* env = std::getenv("TREBLE_TESTING_OVERRIDE");
const bool trebleTestingOverride = env && !strcmp(env, "true");
const bool vintfLegacy = (transport == Transport::EMPTY) && trebleTestingOverride;
#else // __ANDROID_TREBLE__ but not __ANDROID_DEBUGGABLE__
const bool trebleTestingOverride = false;
const bool vintfLegacy = false;
#endif // __ANDROID_DEBUGGABLE__
#else // not __ANDROID_TREBLE__
const char* env = std::getenv("TREBLE_TESTING_OVERRIDE");
const bool trebleTestingOverride = env && !strcmp(env, "true");
const bool vintfLegacy = (transport == Transport::EMPTY);
#endif // __ANDROID_TREBLE__
for (int tries = 0; !getStub && (vintfHwbinder || (vintfLegacy && tries == 0)); tries++) {
if (tries > 1) {
ALOGI("getService: Will do try %d for %s/%s in 1s...", tries, ICameraProvider::descriptor, serviceName.c_str());
sleep(1);
}
if (vintfHwbinder && tries > 0) {
waitForHwService(ICameraProvider::descriptor, serviceName);
}
Return<sp<::android::hidl::base::V1_0::IBase>> ret =
sm->get(ICameraProvider::descriptor, serviceName);
if (!ret.isOk()) {
ALOGE("ICameraProvider: defaultServiceManager()->get returns %s", ret.description().c_str());
break;
}
sp<::android::hidl::base::V1_0::IBase> base = ret;
if (base == nullptr) {
if (tries > 0) {
ALOGW("ICameraProvider: found null hwbinder interface");
}continue;
}
Return<sp<ICameraProvider>> castRet = ICameraProvider::castFrom(base, true /* emitError */);
if (!castRet.isOk()) {
if (castRet.isDeadObject()) {
ALOGW("ICameraProvider: found dead hwbinder service");
continue;
} else {
ALOGW("ICameraProvider: cannot call into hwbinder service: %s; No permission? Check for selinux denials.", castRet.description().c_str());
break;
}
}
iface = castRet;
if (iface == nullptr) {
ALOGW("ICameraProvider: received incompatible service; bug in hwservicemanager?");
break;
}
return iface;
}
if (getStub || vintfPassthru || vintfLegacy) {
const sp<::android::hidl::manager::V1_0::IServiceManager> pm = getPassthroughServiceManager();
if (pm != nullptr) {
Return<sp<::android::hidl::base::V1_0::IBase>> ret =
pm->get(ICameraProvider::descriptor, serviceName);
if (ret.isOk()) {
sp<::android::hidl::base::V1_0::IBase> baseInterface = ret;
if (baseInterface != nullptr) {
iface = ICameraProvider::castFrom(baseInterface);
if (!getStub || trebleTestingOverride) {
iface = new BsCameraProvider(iface);
}
}
}
}
}
return iface;
}
//> 注册服务
::android::status_t ICameraProvider::registerAsService(const std::string &serviceName) {
::android::hardware::details::onRegistration("android.hardware.camera.provider@2.4", "ICameraProvider", serviceName);
const ::android::sp<::android::hidl::manager::V1_0::IServiceManager> sm
= ::android::hardware::defaultServiceManager();
if (sm == nullptr) {
return ::android::INVALID_OPERATION;
}
::android::hardware::Return<bool> ret = sm->add(serviceName.c_str(), this);
return ret.isOk() && ret ? ::android::OK : ::android::UNKNOWN_ERROR;
}
@system/libhidl/transport/ServiceManagement.cpp
sp<IServiceManager1_0> getPassthroughServiceManager() {
return getPassthroughServiceManager1_1();
}
sp<IServiceManager1_1> getPassthroughServiceManager1_1() {
static sp<PassthroughServiceManager> manager(new PassthroughServiceManager());
return manager;
}
调用 getPassthroughServiceManager() 后、 程序中 pm->get() 源码内容如下:
Return<sp<IBase>> get(const hidl_string& fqName,
const hidl_string& name) override {
sp<IBase> ret = nullptr;
/* 此处为Lambda表达式,简单理解为函数指针即可,先执行 openLibs() 其中第一个参数就是fqName。
* 第二个参数是回调函数,
*/
openLibs(fqName, [&](void* handle, const std::string &lib, const std::string &sym) {
//> 回调函数的内部逻辑
IBase* (*generator)(const char* name); //> 声明一个函数
*(void **)(&generator) = dlsym(handle, sym.c_str()); //> sym = "HIDL_FETCH_ICameraProvider"
if(!generator) {
const char* error = dlerror();
LOG(ERROR) << "Passthrough lookup opened " << lib
<< " but could not find symbol " << sym << ": "
<< (error == nullptr ? "unknown error" : error);
dlclose(handle);
return true;
}
ret = (*generator)(name.c_str()); //> 运行函数 ICameraProvider* HIDL_FETCH_ICameraProvider(const char* name)
//> 其中ret为ICameraProvider对象
if (ret == nullptr) {
dlclose(handle);
return true; // this module doesn't provide this instance name
}
registerReference(fqName, name); //> 服务端注册,暂时不做分析
return false;
});
return ret;
}
该函数中使用 openLibs() 函数内容如下:
@system/libhidl/transport/ServiceManagement.cpp
static void openLibs(const std::string& fqName,
std::function<bool /* continue */(void* /* handle */,
const std::string& /* lib */, const std::string& /* sym */)> eachLib) {
//fqName looks like android.hardware.foo@1.0::IFoo
size_t idx = fqName.find("::");
if (idx == std::string::npos ||
idx + strlen("::") + 1 >= fqName.size()) {
LOG(ERROR) << "Invalid interface name passthrough lookup: " << fqName;
return;
}
//> 入口fqName参数为ICameraProvider::descriptor("android.hardware.camera.provider@2.4::ICameraProvider");
std::string packageAndVersion = fqName.substr(0, idx);
//> 获取 android.hardware.camera.provider@2.4::ICameraProvider 中,获取最后一个::后面内容 "ICameraProvider"
std::string ifaceName = fqName.substr(idx + strlen("::"));
const std::string prefix = packageAndVersion + "-impl";
//> 字符 sym 拼接后的内容为 "HIDL_FETCH_ICameraProvider"
const std::string sym = "HIDL_FETCH_" + ifaceName;
const int dlMode = RTLD_LAZY;
void *handle = nullptr;
dlerror(); // clear
std::vector<std::string> paths = {HAL_LIBRARY_PATH_ODM, HAL_LIBRARY_PATH_VENDOR,
HAL_LIBRARY_PATH_VNDK_SP, HAL_LIBRARY_PATH_SYSTEM};
#ifdef LIBHIDL_TARGET_DEBUGGABLE
const char* env = std::getenv("TREBLE_TESTING_OVERRIDE");
const bool trebleTestingOverride = env && !strcmp(env, "true");
if (trebleTestingOverride) {
const char* vtsRootPath = std::getenv("VTS_ROOT_PATH");
if (vtsRootPath && strlen(vtsRootPath) > 0) {
const std::string halLibraryPathVtsOverride =
std::string(vtsRootPath) + HAL_LIBRARY_PATH_SYSTEM;
paths.push_back(halLibraryPathVtsOverride);
}
}
#endif
for (const std::string& path : paths) { //>
std::vector<std::string> libs = search(path, prefix, ".so");
for (const std::string &lib : libs) {
const std::string fullPath = path + lib;
if (path != HAL_LIBRARY_PATH_SYSTEM) {
handle = android_load_sphal_library(fullPath.c_str(), dlMode);
} else {
handle = dlopen(fullPath.c_str(), dlMode);
}
if (handle == nullptr) {
const char* error = dlerror();
LOG(ERROR) << "Failed to dlopen " << lib << ": "
<< (error == nullptr ? "unknown error" : error);
continue;
}
if (!eachLib(handle, lib, sym)) {
return;
}
}
}
}
此处打开android.hardware.camera.provider@2.4-impl.so库,并同时打开与之相关的库,dlsym调用的是 “HIDL_FETCH_ICameraProvider()” 函数,也由此构建了
CameraProvider对象;
源码路径 @hardware/interfaces/camera/2.3/default/CameraProvider.cpp
ICameraProvider* HIDL_FETCH_ICameraProvider(const char* name) {
if (strcmp(name, kLegacyProviderName) != 0) {
return nullptr;
}
CameraProvider* provider = new CameraProvider();
if (provider == nullptr) {
ALOGE("%s: cannot allocate camera provider!", __FUNCTION__);
return nullptr;
}
if (provider->isInitFailed()) {
ALOGE("%s: camera provider init failed!", __FUNCTION__);
delete provider;
return nullptr;
}
return provider;
}
CameraProvider::CameraProvider() :
camera_module_callbacks_t({sCameraDeviceStatusChange,
sTorchModeStatusChange}) {
mInitFailed = initialize();
}
CameraProvider类构建函数中、调用 initialize() 方法;由此方法开启了对 v4l2_camera_HAL 驱动程序调用过程。
我们先总结一下:
(1). 通过上面分析,ICameraProvider.hal文件中定义的接口类,由CameraProvider继承并实现,在 camera-provider-2-4 启动的时候被实例化;
(2). 在 getStub = true 获取服务时、选定 PassthroughServiceManager 模式,执行 get(fqName, name) 函数;
(3). get() 函数打开与ICameraProvider相关库,并执行 “HIDL_FETCH_ICameraProvider()” 函数;
(4). 至此成功构建 ICameraProvider 对象。
此部分有些麻烦事情就是 HIDL 硬件描述语言文件、google妈妈把该生的源码自动给生产了=;梳理源码时有点费周折了。
至此阶段回答第一个问题,由 ICameraProvider 服务调用 v4l2_camera_HAL 驱动程序。
v4l2_camera_HAL 调用过程
有了前面铺垫、直接上源码:
@hardware/interfaces/camera/2.3/default/CameraProvider.cpp
bool CameraProvider::initialize() {
camera_module_t *rawModule;
//> 此 CAMERA_HARDWARE_MODULE_ID 就是 v4l2_camera_hal 中的 ID
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;
}
// rawModule 将指向 HAL 中的 camera_module_t 类型结构体
// 此时,CameraProvider 与 camera HAL 绑定成功,可以通过CameraProvider操作camera HAL
// 创建了一个CameraModule.cpp:android/hardware/interfaces/camera/common/1.0/default对象
// 并将该对象赋值给全局变量mModule保存起来(这里provider调用mModule对象然后调用到CameraModule
// 内部的camera_module_t来操作cameraHAL)
mModule = new CameraModule(rawModule); //> 构建 CameraModule()
// init()里面会调用 cameraHAL的init()函数,然后会获取camera number 并存放在CameraModule中的mCameraInfoMap 里
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
// 这里是设置camera_module_callbacks_t的回调,会在当前对象接收这些回调传递的数据
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.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++) { //> 此处可添加多个摄像头
struct camera_info info;
auto rc = mModule->getCameraInfo(i, &info);
if (rc != NO_ERROR) {
ALOGE("%s: Camera info query failed!", __func__);
mModule.clear();
return true;
}
if (checkCameraVersion(i, info) != 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;
mCameraIds.add(cameraIdStr);
// initialize mCameraDeviceNames and mOpenLegacySupported
mOpenLegacySupported[cameraIdStr] = false;
int deviceVersion = mModule->getDeviceVersion(i);
mCameraDeviceNames.add(
std::make_pair(cameraIdStr,
getHidlDeviceName(cameraIdStr, deviceVersion)));
if (deviceVersion >= CAMERA_DEVICE_API_VERSION_3_2 &&
mModule->isOpenLegacyDefined()) {
// try open_legacy to see if it actually works
struct hw_device_t* halDev = nullptr;
int ret = mModule->openLegacy(cameraId, CAMERA_DEVICE_API_VERSION_1_0, &halDev);
if (ret == 0) {
mOpenLegacySupported[cameraIdStr] = true;
halDev->close(halDev);
mCameraDeviceNames.add(
std::make_pair(cameraIdStr,
getHidlDeviceName(cameraIdStr, CAMERA_DEVICE_API_VERSION_1_0)));
} else if (ret == -EBUSY || ret == -EUSERS) {
// Looks like this provider instance is not initialized during
// system startup and there are other camera users already.
// Not a good sign but not fatal.
ALOGW("%s: open_legacy try failed!", __FUNCTION__);
}
}
}
return false; // mInitFailed
}
通过上面代码,我们梳理出 CameraProvider 程序调用 v4l2_camera_HAL层驱动程序,并且每个摄像头可以是不同版本HAL驱动程序,回答第二个问题了。
具体是如何切换呢?在构建摄像头对象时、就对应上HAL驱动版本,用户直接面向摄像头操作时,用的hal版本就是与该摄像头属性对应了。