• MTK平台Metadata的加载(2)——Sensor和3A相关Static加载


    Camera static metadata 在 camerahalserver 进程启动时就会进行加载。

    (1)CameraService的启动

    camerahalserver: 透过 init service 启动。

    在这里插入图片描述
    (A)Android.mk文件

    ifneq ($(MYKCAM_USE_LEGACY_HAL_API),yes)
    #-----------------------------------------------------------
    ifeq ($(MTK_CAM_LAZY_HAL), yes)
    LOCAL_SRC_FILES += serviceLazy.cpp
    else
    LOCAL_SRC_FILES += service.cpp
    endif
    
    ifeq ($(MTK_CAM_LAZY_HAL), yes)
    LOCAL_INIT_RC := camerahalserverLazy.rc
    else ifneq ($(strip $(FPGA_EARLY_PORTING)), yes)
    LOCAL_INIT_RC := camerahalserver.rc
    endif
    
    LOCAL_MODULE := camerahalserver
    LOCAL_MODULE_RELATIVE_PATH := hw
    LOCAL_MODULE_OWNER := mtk
    LOCAL_PROPRIETARY_MODULE := true
    LOCAL_MULTILIB := first
    
    //...
    

    通过ProjectConfig.mk当中MTK_CAM_LAZY_HAL来加载不同的mode。

    (B)camerahalserver.rc

    service camerahalserver /vendor/bin/hw/camerahalserver
        class main
        user cameraserver
        group audio camera input drmrpc sdcard_rw system media graphics
        ioprio rt 4
        capabilities SYS_NICE
        task_profiles CameraServiceCapacity MaxPerformance
    

    (C)service.cpp

    在 camerahalserver 中注册相关的 HIDL service。

    using android::hardware::registerPassthroughServiceImplementation;
    
    auto err = registerPassthroughServiceImplementation<ICameraProvider>("internal/0" /*"internal" for binderized mode*/);
    auto err = registerPassthroughServiceImplementation<IAdvCamControl>("internal/0" /*"internal" for binderized mode*/);
     auto err = registerPassthroughServiceImplementation<ILomoEffect>("internal/0" /*"internal" for binderized mode*/);
    auto err = registerPassthroughServiceImplementation<ICCAPControl>("internal/0" /*"internal" for binderized mode*/);
    auto err = registerPassthroughServiceImplementation<IISPModule>("internal/0" /*"internal" for binderized mode*/);
    auto err = registerPassthroughServiceImplementation<IISPModule>("internal/0" /*"internal" for binderized mode*/);
    auto err = registerPassthroughServiceImplementation<IPostDevice>("internal/0" /*"internal" for binderized mode*/);
    auto err = registerPassthroughServiceImplementation<IFRHandler>("internal/0" /*"internal" for binderized mode*/);
    auto err = registerPassthroughServiceImplementation<IBGService>("internal/0" /*"internal" for binderized mode*/);
    

    通过registerPassthroughServiceImplementation调用到HIDL_FETCH_ICameraProvider函数,我们来看看HIDL_FETCH_ICameraProvider函数的具体实现。

    //vendor/mediatek/proprietary/hardware/mtkcam3/main/hal/devicemgr/depend/instance.cpp
    
    extern "C"
    ICameraProvider*
    createICameraProvider_V2_6(const char* providerName, NSCam::ICameraDeviceManager* manager);
    
    extern "C"
    ICameraProvider*
    HIDL_FETCH_ICameraProvider(const char* name)
    {
        //...
        
        return createICameraProvider_V2_6(name, getCameraDeviceManager());
    }
    
    //vendor/mediatek/proprietary/hardware/mtkcam3/main/hal/entry/hidl/provider/2.6/HidlCameraProvider.cpp
    
    extern "C"
    ICameraProvider*
    createICameraProvider_V2_6(const char* providerName, ICameraDeviceManager* manager)
    {
        MY_LOGI("+ %s", providerName);
        //
        if ( ! manager ) {
            MY_LOGE("bad camera device manager");
            return nullptr;
        }
        //
        auto provider = new HidlCameraProvider(providerName, manager);
        if ( ! provider ) {
            MY_LOGE("cannot allocate camera provider %s", providerName);
            return nullptr;
        }
        //
        if ( ! provider->initialize() ) {
            MY_LOGE("camera provider %s initialize failed", providerName);
            delete provider;
            provider = nullptr;
        }
        //
        MY_LOGI("- %s provider:%p manager:%p", providerName, provider, manager);
        return provider;
    }
    

    在 HIDL_FETCH_ICameraProvider() 中,调用careateICameraProvier_V2_6(name, getCameraDeviceManager())。

    //vendor/mediatek/proprietary/hardware/mtkcam3/main/hal/devicemgr/depend/instance.cpp
    
    extern "C"
    NSCam::ICameraDeviceManager*
    getCameraDeviceManager()
    {
        MY_LOGI("[hidldc] getCameraDeviceManager");
        static NSCam::CameraDeviceManagerImpl singleton(getProviderType().c_str());
        static bool init = singleton.initialize();
        if ( ! init ) {
            MY_LOGE("CameraDeviceManagerImpl::initialize fail %p", &singleton);
            return nullptr;
        }
        return &singleton;
    }
    

    在 getCameraDeviceManager 中创建 CameraDeviceManagerImpl 实例并 initialize()。

    最终会调用到 CameraDeviceManagerImpl 中的 onEnumerateDevicesLocked()。

    (D)CameraDeviceManagerImpl.cpp

    这里开始即进入Camera Hal的逻辑,我们在这里查看onEnumerateDevicesLocked()。

    //vendor/mediatek/proprietary/hardware/mtkcam3/main/hal/devicemgr/depend/CameraDeviceManagerImpl.cpp
    
    auto
    CameraDeviceManagerImpl::
    onEnumerateDevicesLocked() -> ::android::status_t
    {
        NSMetadataProviderManager::clear();
        mPhysEnumDeviceMap.clear();
    
        //IHalSensorList*const pHalSensorList = MAKE_HalSensorList();
        //size_t const sensorNum = pHalSensorList->searchSensors();
        ///
        IHalLogicalDeviceList* pHalDeviceList = MAKE_HalLogicalDeviceList();
        if(pHalDeviceList == nullptr) {
            MY_LOGE("Cannot get logical device list");
            return -ENODEV;
        }
    
    //(1)加载sensor & 3A相关的static metadata
        size_t const deviceNum = pHalDeviceList->searchDevices();
        CAM_ULOGMI("pHalDeviceList:%p searchDevices:%zu queryNumberOfDevices:%d", pHalDeviceList, deviceNum, pHalDeviceList->queryNumberOfDevices());
    
        mVirtEnumDeviceMap.setCapacity(deviceNum*2);
        uint32_t virtualInstanceId = 0;
        for (size_t instanceId = 0; instanceId < deviceNum; instanceId++)
        {
            virtualInstanceId = pHalDeviceList->getVirtualInstanceId(instanceId);
            bool isHidden = false;
            isHidden = pHalDeviceList->isCameraHidden(instanceId);
            
            //(2)加载其他的static metadata
            sp<IMetadataProvider> pMetadataProvider;
            pMetadataProvider = IMetadataProvider::create(instanceId);
            if(pMetadataProvider)
            {
                std::map<uint32_t, sp<IMetadataProvider>> physicalMetaProviders;
                NSMetadataProviderManager::add(instanceId, pMetadataProvider.get());
                MY_LOGD("[0x%02zx] vid: 0x%02" PRIu32 " isHidden:%d IMetadataProvider:%p sensor:%s",
                                instanceId,
                                virtualInstanceId,
                                isHidden,
                                pMetadataProvider.get(),
                                pHalDeviceList->queryDriverName(instanceId));
                //check if the virtual device backuped by multiple physical devices
                IMetadata::IEntry const& capbilities = pMetadataProvider->getMtkStaticCharacteristics().entryFor(MTK_REQUEST_AVAILABLE_CAPABILITIES);
    
                addVirtualDevicesLocked(instanceId, virtualInstanceId, isHidden, pMetadataProvider, physicalMetaProviders);
            }
            else
            {
                MY_LOGE("Create metadata provider failed, id %zu", instanceId);
            }
        }
    
    //...
    

    在 onEnumerateDevicesLocked()中首先会通过 pHalDeviceList->searchDevices()加载 sensor 与 3A 相关
    的 static metadata,然后再通过 IMetadataProvider::create(instatceId++)加载其他 static metadata。

    (2)searchSensor以及加载Metadata

    //vendor/mediatek/proprietary/hardware/mtkcam/utils/LogicalCam/HalLogicalDeviceList.cpp
    
    MUINT HalLogicalDeviceList::searchDevices()
    {
        if( mDeviceSensorMap.size() == 0 )
        {
            MY_LOGD("Create logical device map");
            createDeviceMap();
        }
        return mDeviceSensorMap.size();
    }
    
    
    MINT32 HalLogicalDeviceList::createDeviceMap()
    {
        SensorInfo_t vTempInfo;
        unsigned int i = 0;
    
        // firstly, we create a logical camera device per physical camera
        IHalSensorList* const pHalSensorList = MAKE_HalSensorList();
        if(CC_UNLIKELY(!pHalSensorList))
        {
            MY_LOGA("create pHalSensorList fail");
            return 1;
        }
        size_t const sensorNum = pHalSensorList->searchSensors();
        MY_LOGD("sensorNum : %zu", sensorNum);
        for(i = 0; i < sensorNum; i++)
        {
        	//...
        }
    }
    

    最终会调用到 HalSensorList.cpp 中的 searchSensors()开始加载 static metadata。

    备注:MT6771 平台及之后平台加载是是 common/v1_1下面的,可查看如下Android.mk确认。

    //vendor/mediatek/proprietary/hardware/mtkcam/drv/src/sensor/mtxxxx/Android.mk
    
    SENINF_COMMON_SRC = ../common/v1_1
    

    (A)HalSensorList::searchSensor()

    //vendor/mediatek/proprietary/hardware/mtkcam/drv/src/sensor/common/v1_1/HalSensorList.cpp
    
    MUINT
    HalSensorList::
    searchSensors()
    {
        Mutex::Autolock _l(mEnumSensorMutex);
    
        MY_LOGD("searchSensors");
    
        SeninfDrv *const pSeninfDrv = SeninfDrv::getInstance();
    
    	//(1)SeninfDrv的init
        if(!pSeninfDrv || pSeninfDrv->init() < 0) {
            MY_LOGE("pSeninfDrv->init() fail");
            return 0;
        }
    
    #ifdef MTK_CAM_MAX_NUMBER_OF_CAMERA
        MUINT max_index_of_camera = MTK_CAM_MAX_NUMBER_OF_CAMERA - 1;
    #else
        MUINT max_index_of_camera = IMGSENSOR_SENSOR_IDX_SUB;
    #endif
        MY_LOGD("impSearchSensor search to %d\n", max_index_of_camera);
        for (MUINT i = IMGSENSOR_SENSOR_IDX_MIN_NUM; i <= max_index_of_camera; i++) {
            ImgSensorDrv *pSensorDrv = ImgSensorDrv::getInstance((IMGSENSOR_SENSOR_IDX)i);
    
    		//(2)ImgSensorDrv的init
            if(!pSensorDrv || pSensorDrv->init((IMGSENSOR_SENSOR_IDX)i) != SENSOR_NO_ERROR)
                continue;
    
            //...
    
    		//(3)searchSensor动作
            if(pSensorDrv->searchSensor() == SENSOR_NO_ERROR) {
                //query sensorinfo
                querySensorInfo((IMGSENSOR_SENSOR_IDX)i);
                //fill in metadata
                buildSensorMetadata((IMGSENSOR_SENSOR_IDX)i);
                addAndInitSensorEnumInfo_Locked(
                    (IMGSENSOR_SENSOR_IDX)i,
                    mapToSensorType(pSensorDrv->getType()),
                    (char *)pSensorDrv->getName());
                
                //...
            }
    	}
    
        return  mEnumSensorList.size();
    }
    
    //vendor/mediatek/proprietary/hardware/mtkcam/drv/src/sensor/common/v1_1/HalSensorList.cpp
    
    HalSensorList::EnumInfo const*
    HalSensorList::
    addAndInitSensorEnumInfo_Locked(
        IMGSENSOR_SENSOR_IDX eSensorDev,
        MUINT eSensorType,
        char *szSensorDrvName
    )
    {
    	//返回的SensorList
        mEnumSensorList.push_back(EnumInfo());
    
        EnumInfo& rEnumInfo = mEnumSensorList.editTop();
    
       ///...
       
        std::string drvName(szSensorDrvName);
        std::transform(drvName.begin(), drvName.end(), drvName.begin(), ::toupper);
        rEnumInfo.setDeviceId(eSensorDev);
        rEnumInfo.setSensorType(eSensorType);
        rEnumInfo.setBackSide(bBackSide);
        std::stringstream sstream;
        sstream << "SENSOR_DRVNAME_" << drvName.c_str();
        rEnumInfo.setSensorDrvName(sstream.str());
    
        buildStaticInfo(rEnumInfo, rEnumInfo.mMetadata);
    
        return  &rEnumInfo;
    }
    

    最终会调用buildStaticInfo()从 camera metadata 配置文件加载 sensor 与 3A 相关的 static metadata 或者自动生成特定的 static metadata。

    (B)HalSensorList::buildStaticInfo()

    //vendor/mediatek/proprietary/hardware/mtkcam/drv/src/sensor/common/v1_1/HalSensorList.cpp
    
    MBOOL
    HalSensorList::buildStaticInfo(Info const& rInfo, IMetadata& rMetadata) const {
        const SensorStaticInfo *pSensorStaticInfo =
            &sensorStaticInfo[rInfo.getDeviceId()];
    
        MUINT8 u8Para = 0;
    
    #if MTKCAM_CUSTOM_METADATA_COMMON
        bool v1 = true;
        if (property_get_int32("vendor.debug.camera.static_meta.version", 1) != 0) {
        
        	//(1)通过impBuildStaticInfo_v1来加载metadata
            if (!impBuildStaticInfo_v1(rInfo, rMetadata)) {
                v1 = false;
                MY_LOGW("V1: Fail to build static info for %s index:%d type:%d",
                        rInfo.getSensorDrvName().c_str(), rInfo.getDeviceId(),
                        rInfo.getSensorType());
            } else {
                checkSensorData(rMetadata);
                updateAFData(rMetadata);
                goto lbLoadDone;
            }
        }
    #endif
    
    	//(2)通过impBuildStaticInfo来加载metadata
        if (!impBuildStaticInfo(rInfo, rMetadata))
        {
            MY_LOGE(
                "Fail to build static info for %s index:%d",
                rInfo.getSensorDrvName().c_str(), rInfo.getDeviceId()
            );
            //return  MFALSE;
        }
    
    lbLoadDone:
        // METEDATA Ref: system/media/camera/docs/docs.html
        // using full size
        {
    	
    		//(3)自动生成相应的Metadata
            IMetadata::IEntry entryA(MTK_SENSOR_INFO_ACTIVE_ARRAY_REGION);
            MRect region1(
            			MPoint(pSensorStaticInfo->SensorGrabStartX_CAP,pSensorStaticInfo->SensorGrabStartY_CAP),
                        MSize(pSensorStaticInfo->captureWidth,pSensorStaticInfo->captureHeight)
                        );
            entryA.push_back(region1, Type2Type<MRect>());
            if (rMetadata.update(MTK_SENSOR_INFO_ACTIVE_ARRAY_REGION, entryA) < 0)
              MY_LOGE("update Metadata SENSOR_INFO_ACTIVE_ARRAY_REGION failed");
        }
    	
    	//...
    
    	#if MTKCAM_CUSTOM_METADATA_COMMON
        if ( v1 )
        
        	//(4)通过impBuildStaticInfo_v1_overwrite来加载metadata
            impBuildStaticInfo_v1_overwrite(rInfo, rMetadata);
    	#endif
    
        rMetadata.sort();
    
        return  MTRUE;
    }
    

    我们首先看一下impBuildStaticInfo函数。

    (C)HalSensorList::impBuildStaticInfo()

    ImpBuidStaticInfo 会先从
    /vendor/mediatek/proprietary/custom/mtxxxx/hal/imgsensor_metadata/imxxxx_raw中加载对应类型的 metadata。

    如果这一类型从此目录下没有找到,那么就会到
    /vendor/mediatek/proprietary/ custom/mtxxxx/hal/imgsensor_metadata/common 目录下加载对应的类型。

    //vendor/mediatek/proprietary/hardware/mtkcam/drv/src/sensor/common/v1_1/HalSensorList.cpp
    
    static
    char const*const
    kStaticMetadataTypeNames[] = {
        "LENS",
        "SENSOR",
        "TUNING_3A",
        "FLASHLIGHT",
        "SCALER",
        "FEATURE",
        "CAMERA",
        "REQUEST",
        NULL
    };
    
    static MBOOL impBuildStaticInfo(
        Info const& rInfo,
        IMetadata& rMetadata) {
        std::stringstream sstream;
        for (unsigned int i = 0; NULL != kStaticMetadataTypeNames[i]; i++) {
            char const* const pTypeName = kStaticMetadataTypeNames[i];
    
        MBOOL status = MTRUE;
    
    	//DEVICE
    	sstream.str("");
        sstream << PREFIX_FUNCTION_STATIC_METADATA << "_DEVICE_" << pTypeName << "_"
                << rInfo.getSensorDrvName().c_str();
            std::string const s8Symbol_Sensor = sstream.str();
            status = impConstructStaticMetadata_by_SymbolName(s8Symbol_Sensor,
                                                            rInfo, rMetadata);
            if (MTRUE == status) {
                continue;
            }
    
            sstream.str("");
        sstream << PREFIX_FUNCTION_STATIC_METADATA << "_DEVICE_" << pTypeName << "_"
                << "COMMON";
            std::string const s8Symbol_Common = sstream.str();
            status = impConstructStaticMetadata_by_SymbolName(s8Symbol_Common,
                                                            rInfo, rMetadata);
            if (MTRUE == status) {
                continue;
            }
    
            MY_LOGE_IF(0, "Fail for both %s & %s", s8Symbol_Sensor.c_str(),
                        s8Symbol_Common.c_str());
        }
    
    	//PROJECT
        for (unsigned int i = 0; NULL != kStaticMetadataTypeNames[i]; i++) {
            char const* const pTypeName = kStaticMetadataTypeNames[i];
    	
    	
        return MTRUE;
    }
    

    对应的类型有:LENS、SENSOR、TUNING_3A、FLASHLIGHT、SCALER、FEATURE、CAMERA、REQUEST。

    上面部分使用类型等参数从 Camera metadata 配置文件中找到对应文件中的函数指针进行加载,这里以Lens为例:

     sstream << PREFIX_FUNCTION_STATIC_METADATA << "_DEVICE_" << pTypeName << "_" << rInfo.getSensorDrvName().c_str();
    
    • PREFIX_FUNCTION_STATIC_METADATA = STATIC_METADATA2_BEGIN
    • pTypeName = LENS
    • rInfo.getSensorDrvName().c_str() = sensorName

    上面字符串对应的函数指针就是STATIC_METADATA2_BEGIN(DEVICE, LENS, SENSOR_DRVNAM
    E_XXXX_MIPI_RAW),对应加载的配置文件就是函数所属文件:config_static_metadata.lens.xxxxmipira
    w.h。

    (D)加载的so和metadata文件

    HalSensorList.cpp 中加载的是 Sensor 与 3A 的 metadata。open 的是 libcam.halsensor.so
    这个动态库。而这个动态库保存的就是 Sensor 与 3A 相关的 metadata。

    static MBOOL impConstructStaticMetadata_by_SymbolName(
        std::string const& s8Symbol,
        Info const& rInfo,
        IMetadata& rMetadata) {
        typedef MBOOL (*PFN_T)(
            IMetadata & metadata,
            Info const& info);
    
        PFN_T pfn;
        MBOOL ret = MTRUE;
    
        std::stringstream sstream;
        sstream << "libcam.halsensor.so";
        std::string s8LibPath = sstream.str();
        void* handle = ::dlopen(s8LibPath.c_str(), RTLD_GLOBAL);
    
        if (!handle) {
            char const* err_str = ::dlerror();
            MY_LOGW("dlopen library=%s %s", s8LibPath.c_str(),
                    err_str ? err_str : "unknown");
            ret = MFALSE;
            goto lbExit;
        }
        pfn = (PFN_T)::dlsym(handle, s8Symbol.c_str());
        if (!pfn) {
            // MY_LOGW("%s not found", s8Symbol.c_str());
            ret = MFALSE;
            goto lbExit;
        }
    
        ret = pfn(rMetadata, rInfo);
        MY_LOGW_IF(!ret, "%s fail", s8Symbol.c_str());
    
    lbExit:
        if (handle) {
            ::dlclose(handle);
            handle = NULL;
        }
        return ret;
    }
    

    那么sensor 与 3A 相关的metadata是如何被加载到libcam.halsensor.so中的呢?

    如下是表示Android P 版 camera metadata 配置的文件夹。

    在这里插入图片描述

    文件中的命名有三种:

    • config_request_metadata_*.h
    • config_static_metadata_*.h
    • config_static_metadata.*.h

    libcam.halsensor.so 默认会加载 libcam.halsensor.custom 这个 static lib,
    而这个 static lib 加载的是"config_static_metadata.*.h"类型的文件。

    (E)Android.mk

    如下的Android.mk显示,libcam.halsensor.custom只加载"config_static_metadata.*.h"类型的文件。

    • config_static_metadata.lens.gc8034mipiraw.h
    • config_static_metadata.project.camera.gc8034mipiraw.h
    • config_static_metadata.project.flashlight.gc8034mipiraw.h
    • config_static_metadata.project.flashlight.gc8034mipiraw.h
    • config_static_metadata.tuning_3a.gc8034mipiraw.h
    //vendor/mediatek/proprietary/hardware/mtkcam/drv/src/sensor/mtxxxx/custom/Android.mk
    
    define my-all-config.sensor-metadata-under
    $(patsubst ./%,%, \
      $(shell find $(1)  -maxdepth 2 \( -name "config_static_metadata.*.h" \) -and -not -name ".*") \
     )
    endef
    
    LOCAL_MODULE := libcam.halsensor.custom
    LOCAL_PROPRIETARY_MODULE := true
    LOCAL_MODULE_CLASS := STATIC_LIBRARIES
    

    而"config_request_metadata_.h"与"config_static_metadata_.h"类型的文件则会被后面将要介绍的
    libmtkcam_metastore.so加载(其他的static metadata、RequsetTemplate)。

  • 相关阅读:
    解决OpenCV在Cmake时,因网络问题无法下载部分所需文件
    Golang编译生成可执行程序的三种方法
    共享办公室行业当前发展现状和未来发展前景
    C#中的数组探究与学习
    顺序表在线OJ题(详解+图解)
    Docker容器的创建、启动、和停止及删除
    用HTML+CSS做一个漂亮简单的轻量级图片相册博客网站(web前端期末大作业)
    typescript85-class组件类型
    Matlab数组操作教程
    如何避免邮件被识别为垃圾邮件
  • 原文地址:https://blog.csdn.net/dongxianfei/article/details/124300049