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)。