Camera hal 之 CameraProvider_icameraprovider-程序员宅基地

技术标签: android  camera  

一、CameraProvider的作用

cameraProvider的主要作用就是向下调用CameraModule,通过CameraModule 来和 Camera driver 交流,向上通过binder会被framework java 层的CameraProviderManager调用,然后CameraProviderManager 最终会被CameraService 使用。
总体来说就是camera hal层的桥梁,承上启下。

二、CameraProvider的启动、初始化

1、启动进程 [email protected]_64
hardware/interfaces/camera/provider/2.4/default/[email protected]_64.rc

service vendor.camera-provider-2-4 /vendor/bin/hw/android.hardware.camera.provider@2.4-service_64
    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

bin文件 [email protected]_64 在hardware/interfaces/camera/provider/2.4/default/Android.bp中被编译出来会放在/vendor/bin/hw 目录下面

cc_binary {
    
    name: "[email protected]_64",
    defaults: ["hidl_defaults"],
    proprietary: true,
    relative_install_path: "hw",
    srcs: ["service.cpp"],
    compile_multilib: "64",
    init_rc: ["[email protected]_64.rc"],
    shared_libs: [
        "libhidlbase",
        "libhidltransport",
        "libbinder",
        "liblog",
        "libutils",
        "[email protected]",
        "[email protected]",
        "[email protected]",
        "[email protected]",
        "[email protected]",
        "[email protected]",
    ],
}

通过init进程来执行rc文件,最终会执行bin文件[email protected]_64,

2、注册[email protected]_64到BpHwServiceManager

hardware/interfaces/camera/provider/2.4/default/service.cpp

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

template<class Interface> 
__attribute__((warn_unused_result))
status_t defaultPassthroughServiceImplementation(std::string name,
                                            size_t maxThreads = 1) {
    
    configureRpcThreadpool(maxThreads, true);
    /*Interface是 *ICameraProvider , name 是 "legacy/0" */
    status_t result = registerPassthroughServiceImplementation<Interface>(name);

    if (result != OK) {
    
        return result;
    }

    joinRpcThreadpool();
    return UNKNOWN_ERROR;
}

template<class Interface>
__attribute__((warn_unused_result))
status_t registerPassthroughServiceImplementation(
        std::string name = "default") {
    
      /* 这里的Interface 就是ICameraProvider ,所以Interface::getService就是
     * 调用 ICameraProvider::getService()
     * getStub = ture 时,getservice 以 passthrough 模式打开 HAL 实现
     * 因此这个会获得CameraProvider实例化对象(不是binder代理)
    */
    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;
}

这里详细看一下ICameraProvider::getService(),在out/soong/.intermediates/./hardware/interfaces/camera/provider/2.4/[email protected]_genc++/gen/android/hardware/camera/provider/2.4/CameraProviderAll.cpp中

// static
::android::sp<ICameraProvider> ICameraProvider::getService(const std::string &serviceName, const bool getStub) {
    
    return ::android::hardware::details::getServiceInternal<BpHwCameraProvider>(serviceName, true, getStub);
}

getServiceInternal的实现在system/libhidl/transport/include/hidl/HidlTransportSupport.h中

template <typename BpType, typename IType = typename BpType::Pure,
          typename = std::enable_if_t<std::is_same<i_tag, typename IType::_hidl_tag>::value>,
          typename = std::enable_if_t<std::is_same<bphw_tag, typename BpType::_hidl_tag>::value>>
sp<IType> getServiceInternal(const std::string& instance, bool retry, bool getStub) {
    
    using ::android::hidl::base::V1_0::IBase;

    sp<IBase> base = getRawServiceInternal(IType::descriptor, instance, retry, getStub);

    if (base == nullptr) {
    
        return nullptr;
    }

    if (base->isRemote()) {
    
        // getRawServiceInternal guarantees we get the proper class
        return sp<IType>(new BpType(toBinder<IBase>(base)));
    }

    return IType::castFrom(base);
}

接着看system/libhidl/transport/ServiceManagement.cpp文件

sp<::android::hidl::base::V1_0::IBase> getRawServiceInternal(const std::string& descriptor,
                                                             const std::string& instance,
                                                             bool retry, bool getStub) {
    
    ...

	/* getStub 为 true,直通模式,将返回CameraProvider实例对象 */
	if (getStub || vintfPassthru || vintfLegacy) {
    
        /* 获取ServiceManager代理 */
        const sp<IServiceManager> pm = getPassthroughServiceManager();
        if (pm != nullptr) {
    
            /* 获取CameraProvider实例对象 */
            /* descriptor 是  ,instance 是 
            sp<IBase> base = pm->get(descriptor, instance).withDefault(nullptr);
            if (!getStub || trebleTestingOverride) {
                base = wrapPassthrough(base);
            }
            return base;
        }
    }

    return nullptr;
}

struct PassthroughServiceManager : IServiceManager1_1 {
    static void openLibs(
        const std::string& fqName,
        const std::function<bool /* continue */ (void* /* handle */, const std::string& /* lib */,
                                                 const std::string& /* sym */)>& eachLib) {
    
        //fqName looks like [email protected]::IFoo
        /* fqName = [email protected]::ICameraProvider */
        size_t idx = fqName.find("::");

        if (idx == std::string::npos ||
                idx + strlen("::") + 1 >= fqName.size()) {
    
            LOG(ERROR) << "Invalid interface name passthrough lookup: " << fqName;
            return;
        }

        std::string packageAndVersion = fqName.substr(0, idx);
        std::string ifaceName = fqName.substr(idx + strlen("::"));

        /* prefix = [email protected] */
        const std::string prefix = packageAndVersion + "-impl";
        /* sym = HIDL_FETCH_ICameraProvider */
        const std::string sym = "HIDL_FETCH_" + ifaceName;

        constexpr int dlMode = RTLD_LAZY;
        void* handle = nullptr;

        dlerror(); // clear

        static std::string halLibPathVndkSp = android::base::StringPrintf(
            HAL_LIBRARY_PATH_VNDK_SP_FOR_VERSION, details::getVndkVersionStr().c_str());
        std::vector<std::string> paths = {
    HAL_LIBRARY_PATH_ODM, HAL_LIBRARY_PATH_VENDOR,
                                          halLibPathVndkSp, HAL_LIBRARY_PATH_SYSTEM};

        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;

                /* 经过上面的一些添加转换,最终
                 * fullPath = /vendor/lib/hw/[email protected]
                 * */
                if (path == HAL_LIBRARY_PATH_SYSTEM) {
    
                    handle = dlopen(fullPath.c_str(), dlMode);
                } else {
    
                    handle = android_load_sphal_library(fullPath.c_str(), dlMode);
                }

                if (handle == nullptr) {
    
                    const char* error = dlerror();
                    LOG(ERROR) << "Failed to dlopen " << lib << ": "
                               << (error == nullptr ? "unknown error" : error);
                    continue;
                }

                /* Lambda表达式代入 */
                if (!eachLib(handle, lib, sym)) {
    
                    return;
                }
            }
        }
    }

    Return<sp<IBase>> get(const hidl_string& fqName,
                          const hidl_string& name) override {
    
        sp<IBase> ret = nullptr;

        /* [&] 此处为Lambda表达式,简单理解为函数指针即可,先执行 openLibs() */
        openLibs(fqName, [&](void* handle, const std::string &lib, const std::string &sym) {
    
            /* handle :dlopen() 的返回值
             * lib :[email protected]
             * sym :HIDL_FETCH_ICameraProvider
             */
            IBase* (*generator)(const char* name);
            /* 返回 HIDL_FETCH_ICameraProvider() 函数对应的函数地址 */
            *(void **)(&generator) = dlsym(handle, sym.c_str());
            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;
            }

            /* 执行 HIDL_FETCH_ICameraProvider() 函数,该函数返回CameraProvider实例对象保存在ret,
             * 所以get()函数将返回 ret 
             * */
            ret = (*generator)(name.c_str());

            if (ret == nullptr) {
    
                dlclose(handle);
                return true; // this module doesn't provide this instance name
            }

            // Actual fqname might be a subclass.
            // This assumption is tested in vts_treble_vintf_test
            using ::android::hardware::details::getDescriptor;
            std::string actualFqName = getDescriptor(ret.get());
            CHECK(actualFqName.size() > 0);
            registerReference(actualFqName, name);
            return false;
        });

        return ret;
    }
}

(*generator)(name.c_str()) 就是 HIDL_FETCH_ICameraProvider(“legacy/0”),
hardware/interfaces/camera/provider/2.4/default/CameraProvider.cpp

ICameraProvider* HIDL_FETCH_ICameraProvider(const char* name) {
    
    /* 传递进来的 name 为 legacy/0,而 kLegacyProviderName 定义为 legacy/0 */
    if (strcmp(name, kLegacyProviderName) == 0) {
    
        /* 创建CameraProvider对象,构造函数将会调用CameraProvider的initialize() 函数 */
        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;
    } else if (strcmp(name, kExternalProviderName) == 0) {
    
        ExternalCameraProvider* provider = new ExternalCameraProvider();
        return provider;
    }
    ALOGE("%s: unknown instance name: %s", __FUNCTION__, name);
    return nullptr;
}

bool CameraProvider::initialize() {
    
    camera_module_t *rawModule;
    /* 在通过 hw_get_module() 加载HAL层so:其实是通过获取各种android属性
     * (在设备端可以通过 getprop 命令查看当前设备支持的属性),
     * 得到HAL so的名称(*variant_keys[]),而后探测、加载该HAL so库,并通
     * 过 dlsym() 函数返回标识符为 HAL_MODULE_INFO_SYM_AS_STR 的HMI地址
     * (由于各个HAL层代码最终会通过 HAL_MODULE_INFO_SYM 修饰,编译器识别到
     * 该符号时将会将标示地址导出为HMI符号,从而在加载HAL so时可以获取)
     */
    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 对象 */
    /* CameraModule.cpp:android/hardware/interfaces/camera/common/1.0/default */
    mModule = new CameraModule(rawModule);
    /* mModule->init()主要完成以下操作:
     * 1. 当camera HAL的 module_api_version >= CAMERA_MODULE_API_VERSION_2_4,将调用HAL->init()
     * 2. 通过 HAL getNumberOfCameras() 获取设置camera数量,并将该参数设置为 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());

    ...

    mNumberOfLegacyCameras = mModule->getNumberOfCameras();
    for (int i = 0; i < mNumberOfLegacyCameras; i++) {
    
        struct camera_info info;
        /* 将获取camera信息并保存,其中将有HAL version 信息,应用
         * 层将会检查HAL层版本信息从而确认调用不同的API实现相机应用
         */
        auto rc = mModule->getCameraInfo(i, &info);
        if (rc != NO_ERROR) {
    
            ALOGE("%s: Camera info query failed!", __func__);
            mModule.clear();
            return true;
        }

        ...
    }

    return false; // mInitFailed
}

out/soong/.intermediates/./hardware/interfaces/camera/provider/2.4/[email protected]_genc++/gen/android/hardware/camera/provider/2.4/CameraProviderAll.cpp
这里的CameraProviderAll.cpp是IcameraProvider.hal经过脚本生成的

::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;
    }
     /*
     * 这里的sm实质是BpHwServiceManager,调用BpHwServiceManager::add来将cameraProvider注册到hwBinder			
     * 里面
     */
    ::android::hardware::Return<bool> ret = sm->add(serviceName.c_str(), this);
    return ret.isOk() && ret ? ::android::OK : ::android::UNKNOWN_ERROR;
}

这里顺便看一下,一个hal文件能生成多少东西
在这里插入图片描述

一个ICameraProvider对应的要生成 CameraProviderAll.cpp BpCameraProvider.cpp ICameraProvider.h BnCameraProvider.cpp iHwCameraProvider.h

参考下面的cameraProvider的启动时序图
在这里插入图片描述
在这里插入图片描述

参考文章:https://blog.csdn.net/weixin_41944449/article/details/99453461

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/lisiwei1994/article/details/119910660

智能推荐

解决win10/win8/8.1 64位操作系统MT65xx preloader线刷驱动无法安装_mt65驱动-程序员宅基地

文章浏览阅读1.3w次。转载自 http://www.miui.com/thread-2003672-1-1.html 当手机在刷错包或者误修改删除系统文件后会出现无法开机或者是移动定制(联通合约机)版想刷标准版,这时就会用到线刷,首先就是安装线刷驱动。 在XP和win7上线刷是比较方便的,用那个驱动自动安装版,直接就可以安装好,完成线刷。不过现在也有好多机友换成了win8/8.1系统,再使用这个_mt65驱动

SonarQube简介及客户端集成_sonar的客户端区别-程序员宅基地

文章浏览阅读1k次。SonarQube是一个代码质量管理平台,可以扫描监测代码并给出质量评价及修改建议,通过插件机制支持25+中开发语言,可以很容易与gradle\maven\jenkins等工具进行集成,是非常流行的代码质量管控平台。通CheckStyle、findbugs等工具定位不同,SonarQube定位于平台,有完善的管理机制及强大的管理页面,并通过插件支持checkstyle及findbugs等既有的流..._sonar的客户端区别

元学习系列(六):神经图灵机详细分析_神经图灵机方法改进-程序员宅基地

文章浏览阅读3.4k次,点赞2次,收藏27次。神经图灵机是LSTM、GRU的改进版本,本质上依然包含一个外部记忆结构、可对记忆进行读写操作,主要针对读写操作进行了改进,或者说提出了一种新的读写操作思路。神经图灵机之所以叫这个名字是因为它通过深度学习模型模拟了图灵机,但是我觉得如果先去介绍图灵机的概念,就会搞得很混乱,所以这里主要从神经图灵机改进了LSTM的哪些方面入手进行讲解,同时,由于模型的结构比较复杂,为了让思路更清晰,这次也会分开几..._神经图灵机方法改进

【机器学习】机器学习模型迭代方法(Python)-程序员宅基地

文章浏览阅读2.8k次。一、模型迭代方法机器学习模型在实际应用的场景,通常要根据新增的数据下进行模型的迭代,常见的模型迭代方法有以下几种:1、全量数据重新训练一个模型,直接合并历史训练数据与新增的数据,模型直接离线学习全量数据,学习得到一个全新的模型。优缺点:这也是实际最为常见的模型迭代方式,通常模型效果也是最好的,但这样模型迭代比较耗时,资源耗费比较多,实时性较差,特别是在大数据场景更为困难;2、模型融合的方法,将旧模..._模型迭代

base64图片打成Zip包上传,以及服务端解压的简单实现_base64可以装换zip吗-程序员宅基地

文章浏览阅读2.3k次。1、前言上传图片一般采用异步上传的方式,但是异步上传带来不好的地方,就如果图片有改变或者删除,图片服务器端就会造成浪费。所以有时候就会和参数同步提交。笔者喜欢base64图片一起上传,但是图片过多时就会出现数据丢失等异常。因为tomcat的post请求默认是2M的长度限制。2、解决办法有两种:① 修改tomcat的servel.xml的配置文件,设置 maxPostSize=..._base64可以装换zip吗

Opencv自然场景文本识别系统(源码&教程)_opencv自然场景实时识别文字-程序员宅基地

文章浏览阅读1k次,点赞17次,收藏22次。Opencv自然场景文本识别系统(源码&教程)_opencv自然场景实时识别文字

随便推点

ESXi 快速复制虚拟机脚本_exsi6.7快速克隆centos-程序员宅基地

文章浏览阅读1.3k次。拷贝虚拟机文件时间比较长,因为虚拟机 flat 文件很大,所以要等。脚本完成后,以复制虚拟机文件夹。将以下脚本内容写入文件。_exsi6.7快速克隆centos

好友推荐—基于关系的java和spark代码实现_本关任务:使用 spark core 知识完成 " 好友推荐 " 的程序。-程序员宅基地

文章浏览阅读2k次。本文主要实现基于二度好友的推荐。数学公式参考于:http://blog.csdn.net/qq_14950717/article/details/52197565测试数据为自己随手画的关系图把图片整理成文本信息如下:a b c d e f yb c a f gc a b dd c a e h q re f h d af e a b gg h f bh e g i di j m n ..._本关任务:使用 spark core 知识完成 " 好友推荐 " 的程序。

南京大学-高级程序设计复习总结_南京大学高级程序设计-程序员宅基地

文章浏览阅读367次。南京大学高级程序设计期末复习总结,c++面向对象编程_南京大学高级程序设计

4.朴素贝叶斯分类器实现-matlab_朴素贝叶斯 matlab训练和测试输出-程序员宅基地

文章浏览阅读3.1k次,点赞2次,收藏12次。实现朴素贝叶斯分类器,并且根据李航《统计机器学习》第四章提供的数据训练与测试,结果与书中一致分别实现了朴素贝叶斯以及带有laplace平滑的朴素贝叶斯%书中例题实现朴素贝叶斯%特征1的取值集合A1=[1;2;3];%特征2的取值集合A2=[4;5;6];%S M LAValues={A1;A2};%Y的取值集合YValue=[-1;1];%数据集和T=[ 1,4,-1;..._朴素贝叶斯 matlab训练和测试输出

Markdown 文本换行_markdowntext 换行-程序员宅基地

文章浏览阅读1.6k次。Markdown 文本换行_markdowntext 换行

错误:0xC0000022 在运行 Microsoft Windows 非核心版本的计算机上,运行”slui.exe 0x2a 0xC0000022″以显示错误文本_错误: 0xc0000022 在运行 microsoft windows 非核心版本的计算机上,运行-程序员宅基地

文章浏览阅读6.7w次,点赞2次,收藏37次。win10 2016长期服务版激活错误解决方法:打开“注册表编辑器”;(Windows + R然后输入Regedit)修改SkipRearm的值为1:(在HKEY_LOCAL_MACHINE–》SOFTWARE–》Microsoft–》Windows NT–》CurrentVersion–》SoftwareProtectionPlatform里面,将SkipRearm的值修改为1)重..._错误: 0xc0000022 在运行 microsoft windows 非核心版本的计算机上,运行“slui.ex