虚拟摄像头之四: 谁在调用 v4l2_camera_HAL 摄像头驱动

前言

本篇是虚拟摄像头重构过程的系列文章,本篇博文谨分析二方面内容:
(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: "[email protected]",
    defaults: ["hidl_defaults"],
    proprietary: true,
    relative_install_path: "hw",
    srcs: ["service.cpp"],
    compile_multilib: "32",
    init_rc: ["[email protected]"],
    shared_libs: [
        "libhidlbase",
        "libhidltransport",
        "libbinder",
        "liblog",
        "libutils",
        "[email protected]",
        "[email protected]",
        "[email protected]",
        "[email protected]",
        "[email protected]",
    ],
}

服务启动配置内容:
@hardware/interfaces/camera/2.4/default/[email protected]

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 "[email protected]"

#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("[email protected]::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("[email protected]", "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 [email protected]::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("[email protected]::ICameraProvider");
        std::string packageAndVersion = fqName.substr(0, idx);       

        //> 获取 [email protected]::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;
                }
            }
        }
    }

此处打开[email protected]库,并同时打开与之相关的库,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版本就是与该摄像头属性对应了。

猜你喜欢

转载自blog.csdn.net/weixin_38387929/article/details/126164189