码字不易,多谢支持
MTK Camera Open/Close流程
十分感谢
Camera(6) MTK camera启动流程介绍https://blog.csdn.net/karaskass/article/details/106261187
MTK Camera 从底层到应用层一网打尽
《Android Q 之MTK代码分析(一)--Camera Hal3 Service》
《Android Q 之MTK代码分析(二)--Camera Hal3 Search Sensor》
《Android Q 之MTK代码分析(三)--Camera Hal3 Open/Close》
《Android Q 之MTK代码分析(四)--Camera Hal3 configure_Streams》
《Android Q 之MTK代码分析(五)--Camera Hal3 process_capture_request》
《Android Q 之MTK代码分析(六)--Camera Hal3 process_capture_result》
备忘:
文末支持一波,感谢鞠躬
0、前文回顾
前文已经简单说明CameraHalService服务、Serarch Sensor的过程。
接下来分析下Hal层的camera Open/Close流程。
1、CameraService
frameworks/av/services/camera/libcameraservice/CameraService.cpp
08-26 11:30:28.450083 4144 4144 I CameraService: CameraService started (pid=4144)
08-26 11:30:28.450097 4144 4144 I CameraService: CameraService process starting/*这里打印的“开始延迟”是对HAL从开始运行所需时间的估计进程创建,将自己注册为HAL。实际的启动时间可能更长
因为进程可能还没有加入线程池,所以它可能还没有准备好加入处理事务*/
08-26 11:30:28.460310 4144 4144 I HidlServiceManagement: Registered android.frameworks.cameraservice.service@2.1::ICameraService/default (start delay of 129ms)
2、CameraHalService
vendor/mediatek/proprietary/hardware/mtkcam3/main/hal/service/service.cpp
08-26 11:30:28.462538 4145 4145 I camerahalserver: Camera HAL Server is starting..., ADV_CAM_SUPPORT(0)
3、Serarch sensor
08-26 11:30:28.684843 4145 4145 I mtkcam-devicemgr: [initialize] +
08-26 11:30:28.685697 4145 4145 D MtkCam/Util/LogicalDevice: (4145)[searchDevices] Create logical device map
08-26 11:30:28.686332 4145 4145 D MtkCam/HalSensorList: [searchSensors] searchSensors
// set mclk
08-26 11:30:28.687258 4145 4145 D SeninfDrvImp: [setMclk][setMclk]pcEn(1), clkPol(0), mMclkUser[0](1), TimestampClk(0), freq(24), mclkIdx 0
08-26 11:30:28.687995 4145 4145 D MtkCam/HalSensorList: [enumerateSensor_Locked] impSearchSensor search to 4
08-26 11:30:28.688013 4145 4145 D ImgSensorDrv: [searchSensor]SENSOR search start
08-26 11:30:28.740489 4145 4145 D ImgSensorDrv: [searchSensor]set sensor driver id =1
08-26 11:30:28.740519 4145 4145 D ImgSensorDrv: [searchSensor]sensorIdx 0 found <0x560d45/ov13b10_qtech_mipi_raw/SENSOR_DRVNAME_OV13B10_QTECH_MIPI_RAW>
08-26 11:30:28.740564 4145 4145 D ImgSensorDrv: [getInfo2]prv w=0x838,h=0x618
08-26 11:30:28.740572 4145 4145 D ImgSensorDrv: [getInfo2]cap w=0x1070,h=0xc30
08-26 11:30:28.740581 4145 4145 D ImgSensorDrv: [getInfo2]vd w=0x1070,h=0xc30
08-26 11:30:28.740590 4145 4145 D ImgSensorDrv: [getInfo2]pre GrapX=0x0,GrapY=0x008-26 11:30:28.740605 4145 4145 D MtkCam/HalSensorList: [getRawInfo] SensorOutputDataFormat: 0, ImageSensor Type: 0
// build sensor meta
08-26 11:30:28.740656 4145 4145 D MtkCam/HalSensorList: [buildSensorMetadata] impBuildSensorInfo start!
08-26 11:30:28.740757 4145 4145 D MtkCam/HalSensorList: [buildSensorMetadata] impBuildSensorInfo end!08-26 11:30:28.751473 4145 4145 I MtkCam/HalSensorList: [impBuildStaticInfo_v1] <load custom folder>
08-26 11:30:28.751473 4145 4145 I MtkCam/HalSensorList: STATIC_COMMON: [CAMERA]:1; [CONTROL_AE]:1; [CONTROL_AF]:1; [CONTROL_AWB]:1; [TUNING]:1; [FLASHLIGHT]:1; [SENSOR]:2; [LENS]:0;
08-26 11:30:28.751473 4145 4145 I MtkCam/HalSensorList: STATIC_PLATFORM: [MODULE]:8; [LENS]:8;
08-26 11:30:28.751473 4145 4145 I MtkCam/HalSensorList: STATIC_PROJECT: [MODULE]:0; [LENS]:0;08-26 11:30:28.758605 4145 4145 D MtkCam/HalSensorList: [updateAFData] MTK_LENS_INFO_MINIMUM_FOCUS_DISTANCE: 20.000000, add AF modes & regions
08-26 11:30:28.758626 4145 4145 D MtkCam/HalSensorList: [buildStaticInfo] MTK_SENSOR_INFO_ACTIVE_ARRAY_REGION(0, 0, 4208, 3120)
08-26 11:30:28.758638 4145 4145 D MtkCam/HalSensorList: [buildStaticInfo] MTK_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE(0, 0, 4208, 3120)08-26 11:30:28.760406 4145 4145 I MtkCam/HalSensorList: [impBuildStaticInfo_v1_overwrite] <load custom folder - overwrite>
08-26 11:30:28.760406 4145 4145 I MtkCam/HalSensorList: STATIC_PLATFORM: [MOD_OVERWRITE]:8;
08-26 11:30:28.760406 4145 4145 I MtkCam/HalSensorList: STATIC_PROJECT: [MOD_OVERWRITE]:0;/*这块会search 到5次sensor*/
08-26 11:30:29.077172 4145 4145 D MtkCam/Util/LogicalDevice: (4145)[createDeviceMap] sensorNum : 5
08-26 11:30:33.480615 4145 4145 I mtkcam-devicemgr: [initialize] -
其实在search sensor之后open之前还有一个CameraProviderManager initial的操作
08-26 11:30:33.486717 4144 4147 I CameraProviderManager: Connecting to new camera provider: internal/0, isRemote? 1
08-26 11:30:33.487572 4145 4165 W mtkcam-camprovider: [notifyDeviceStateChange] Not implement
08-26 11:30:33.490413 4145 4164 W mtkcam-camprovider: [getConcurrentStreamingCameraIds] Not implement, return OK
08-26 11:30:33.490669 4144 4147 I CameraProviderManager: Enumerating new camera device: device@3.6/internal/0
08-26 11:30:33.491152 4145 4164 D mtkcam-dev3: 0[CameraDevice3Impl::getResourceCost] Camera Device 0: resourceCost 100, conflict to [device@3.6/internal/5]
08-26 11:30:33.494548 4144 4147 I CameraProviderManager: Camera provider internal/0 ready with 6 camera devices强力建议熟读Camera3.h Startup and general expected operation sequence
https://www.androidos.net.cn/android/10.0.0_r6/xref/hardware/libhardware/include/hardware/camera3.h
1、camera 架构分析
Camera的框架分为Kernel部分和hal部分,其中kernel部分主要有两块:
image sensor driver,负责具体型号的sensor的id检测,上电,以及在preview、capture、初始化、3A等等功能设定时的寄存器配置;
isp driver,通过DMA将sensor数据流上传;
HAL层部分主要有三部分组成:
imageio,主要负责数据buffer上传的pipe;
drv,包含imgsensor和isp的hal层控制;
feature io,包含各种3A等性能配置;
2、camera open 流程
2.1原文阅读
* 1. Framework calls camera_module_t->common.open(), which returns a
* hardware_device_t structure.
简单翻译-->
framework调用camera_module这块的common方法,camera_module_t-> common.open(),在结构体hw_module_methods_t这块的open你的方法来打开特定 Camera,返回一个结构体的 hardware_device_t结构
2.2 结构体
打开指定的Camera
camera_module{
hw_module_t{
.open = open_dev
}
}
这个结构体里面有一个函数指针,什么地方明确了函数指针的指向了?
在 hardware/libhardware/modules/camera/3_0/CameraHAL.cpp中的167行明确了函数指针指向。指向其中的open_dev函数
2.3代码分析
1、MTK Open Camera 框图
2、frameworks/av/services/camera/libcameraservice/common/CameraProviderManager.cpp
framework层 CameraProviderManager 调用ICameraDevice提供的API->Open() ,对应图中1.open()
status_t CameraProviderManager::openSession(const std::string &id,
const sp<device::V1_0::ICameraDeviceCallback>& callback,
/*out*/
sp<device::V1_0::ICameraDevice> *session) {std::lock_guard<std::mutex> lock(mInterfaceMutex);
auto deviceInfo = findDeviceInfoLocked(id,
/*minVersion*/ {1,0}, /*maxVersion*/ {2,0});
if (deviceInfo == nullptr) return NAME_NOT_FOUND;auto *deviceInfo1 = static_cast<ProviderInfo::DeviceInfo1*>(deviceInfo);
const sp<provider::V2_4::ICameraProvider> provider =
deviceInfo->mParentProvider->startProviderInterface();
if (provider == nullptr) {
return DEAD_OBJECT;
}
saveRef(DeviceMode::CAMERA, id, provider);auto interface = deviceInfo1->startDeviceInterface<
CameraProviderManager::ProviderInfo::DeviceInfo1::InterfaceT>();
if (interface == nullptr) {
return DEAD_OBJECT;
}
hardware::Return<Status> status = interface->open(callback);
if (!status.isOk()) {
removeRef(DeviceMode::CAMERA, id);
ALOGE("%s: Transaction error opening a session for camera device %s: %s",
__FUNCTION__, id.c_str(), status.description().c_str());
return DEAD_OBJECT;
}
if (status == Status::OK) {
*session = interface;
}
return mapToStatusT(status);
}
3、vendor/mediatek/proprietary/hardware/mtkcam3/main/hal/device/3.x/device/CameraDevice3Impl.cpp
Return<void>
CameraDevice3Impl::
open(const ::android::sp<V3_2::ICameraDeviceCallback>& callback, open_cb _hidl_cb)
{
int systraceLevel = ::property_get_int32("vendor.debug.mtkcam.systrace.level", MTKCAM_SYSTRACE_LEVEL_DEFAULT);
MY_LOGI("open camera3 device (%s) systraceLevel(%d) instanceId(%d) vid(%d)",
mStaticDeviceInfo->mInstanceName.c_str(),
systraceLevel,
mStaticDeviceInfo->mInstanceId,
mStaticDeviceInfo->mVirtualInstanceId);
::android::status_t status = mSession->open(V3_5::ICameraDeviceCallback::castFrom(callback));
if ( ::android::OK != status ) {
_hidl_cb(mapToHidlCameraStatus(status), nullptr);
}
else {
_hidl_cb(mapToHidlCameraStatus(status), mSession);
}return Void();
}
vendor/mediatek/proprietary/hardware/mtkcam3/main/hal/device/3.x/device/CameraDevice3SessionImpl.cpp
对应图上2.1 startOpenDevice()
open camera之前,CameraDevice 需要通过startOpenDevice()注册到CameraDeviceManager,后者会对CameraDevice检测是否有重新open的动作
auto
ThisNamespace::
open(
const ::android::sp<V3_5::ICameraDeviceCallback>& callback
) -> ::android::status_t
{
CAM_ULOG_APILIFE_GUARD(MOD_CAMERA_DEVICE);
::android::Mutex::Autolock _lOpsLock(mOpsLock);
MY_LOGI("+");//unlink to death notification for existed device callback
if ( mCameraDeviceCallback != nullptr ) {
mCameraDeviceCallback->unlinkToDeath(this);
mCameraDeviceCallback = nullptr;
::memset(&mLinkToDeathDebugInfo, 0, sizeof(mLinkToDeathDebugInfo));
}//link to death notification for device callback
if ( callback != nullptr ) {
hardware::Return<bool> linked = callback->linkToDeath(this, (uint64_t)this);
if (!linked.isOk()) {
MY_LOGE("Transaction error in linking to mCameraDeviceCallback death: %s", linked.description().c_str());
} else if (!linked) {
MY_LOGW("Unable to link to mCameraDeviceCallback death notifications");
}
callback->getDebugInfo([this](const auto& info){
mLinkToDeathDebugInfo = info;
});
MY_LOGD("Link death to ICameraDeviceCallback %s", toString(mLinkToDeathDebugInfo).c_str());
}if(mpCpuCtrl)
{
MY_LOGD("Enter CPU performance mode, time: %d sec", mCpuPerfTime);
mpCpuCtrl->cpuPerformanceMode(mCpuPerfTime);
}
mpCpuPrefIdleCtrl->enablePreferIdle();
mDisplayIdleDelayUtil.enable();::android::status_t status = OK;
String8 const stateTag("-> open");
mStateLog.add(stateTag + " +");do {
if (callback == nullptr) {
MY_LOGE("cannot open camera. callback is null!");
status = BAD_VALUE;
break;
}auto pDeviceManager = mStaticInfo.mDeviceManager;
auto const& instanceName = mStaticInfo.mStaticDeviceInfo->mInstanceName;status = pDeviceManager->startOpenDevice(instanceName);
if ( OK != status ) {
pDeviceManager->updatePowerOnDone();
break;
}do {
//------------------------------------------------------------------
mCommandHandler = new CommandHandler(getInstanceId());
if ( mCommandHandler == nullptr ) {
MY_LOGE("Bad mCommandHandler");
status = NO_INIT;
break;
}
else {
const std::string threadName{std::to_string(getInstanceId())+":dev3-cmd"};
status = mCommandHandler->run(threadName.c_str());
if ( OK != status ) {
MY_LOGE("Fail to run the thread %s - status:%d(%s)", threadName.c_str(), status, ::strerror(-status));
mCommandHandler = nullptr;
status = NO_INIT;
break;
}
}
//------------------------------------------------------------------
int err = NO_INIT;
status = tryRunCommandLocked(getWaitCommandTimeout(), "onOpenLocked", [&, this](){
err = onOpenLocked(callback);
});
if ( status == OK ) {
status = err;
}
} while (0);pDeviceManager->updatePowerOnDone();
if ( OK != status ) {
pDeviceManager->finishOpenDevice(instanceName, true/*cancel*/);
break;
}status = pDeviceManager->finishOpenDevice(instanceName, false/*cancel*/);
if ( OK != status ) {
break;
}} while (0);
mStateLog.add(stateTag + " - " + (0==status ? "OK" : ::strerror(-status)));
return status;
}
4、vendor/mediatek/proprietary/hardware/mtkcam3/main/hal/devicemgr/CameraDeviceManagerBase.cpp
对应图上2.1.1 attach the device to open map //这块代码追下去就是
2.1.2 lock & turn off torch when 1st camera opened
auto
CameraDeviceManagerBase::
startOpenDevice(
const std::string& deviceName
) -> ::android::status_t
{
status_t status = OK;
waitForPreviousPowerOnDone();
::android::sp<IVirtualDevice> pVirtualDevice = nullptr;
//
{
RWLock::AutoRLock _l(mDataRWLock);
status = getVirtualDeviceLocked(deviceName, nullptr, &pVirtualDevice);
if ( OK != status ) {
return status;
}
}
//
//CAM_TRACE_ASYNC_BEGIN
MyTraceAsyncBegin _lAsyncTrace(
String8::format("%s:" LOG_TAG ":OpenDevice", pVirtualDevice->getInstanceName()),
pVirtualDevice->getInstanceId(), status);
CAM_TRACE_NAME(LOG_TAG ":startOpenDevice");
//
// save the caller's information, which will be validated in future.
status = mActiveOperation.lock(pVirtualDevice, ActiveOperation::OPEN);
if ( OK != status ) {
return status;
}
//
do {
RWLock::AutoWLock _l(mDataRWLock);
//
size_t const nOriginalOpenNum = mOpenDeviceMap.size();
//
MY_LOGD(
"+ %s mActiveOperationCommandList.size:%zu mOpenDeviceMap.size:%zu mPhysEnumDeviceMap.size:%zu mVirtEnumDeviceMap.size:%zu",
pVirtualDevice->getInstanceName(), mActiveOperationCommandList.size(),
mOpenDeviceMap.size(), mPhysEnumDeviceMap.size(), mVirtEnumDeviceMap.size());
//
// [1] check to see whether it's ready to open.
status = validateOpenLocked(pVirtualDevice);
if ( OK != status ) {
break;
}
//
// [2] attach opened device
status = attachOpenDeviceLocked(pVirtualDevice);
if ( OK != status ) {
break;
}
//
// [3] lock & turn off torch when first camera opened
// Note: torch must be turned off before opening camera...
if ( nOriginalOpenNum == 0 && mOpenDeviceMap.size() != 0 ) {
for (size_t i = 0; i < mVirtEnumDeviceMap.size(); i++) {
auto const& pInfo = mVirtEnumDeviceMap.valueAt(i);
if( pInfo->mVirtDevice->getFacing() == pVirtualDevice->getFacing() )
{
::android::sp<ICommand> pCommand = new SetTorchModeStatusCommand(
this, pInfo->mVirtDevice, ETorchModeStatus::NOT_AVAILABLE);
if ( OK == pCommand->doExecute() ) {
mActiveOperationCommandList.push_back(pCommand);
}
}
}
}
} while (0);
//
if ( OK != status ) {
// get locked only when this function returns OK.
mActiveOperation.unlock(pVirtualDevice, ActiveOperation::OPEN);
MY_LOGE("%s status:%s(%d)", pVirtualDevice->getInstanceName(), ::strerror(-status), -status);
}
//
return status;
}
5、vendor/mediatek/proprietary/hardware/mtkcam3/main/hal/device/3.x/device/CameraDevice3SessionImpl.cpp
对应图上2.2 onOpenLocked
创建IAppStreamManager 对象,
open pPipelineModel实例
auto
ThisNamespace::
onOpenLocked(
const ::android::sp<V3_4::ICameraDeviceCallback>& callback
) -> ::android::status_t
{
mLogLevel = getCameraDevice3DebugLogLevel();mCameraDeviceCallback = callback;
//--------------------------------------------------------------------------
{
Mutex::Autolock _l(mAppStreamManagerLock);if ( mAppStreamManager != nullptr ) {
MY_LOGE("mAppStreamManager:%p != 0 while opening", mAppStreamManager.get());
mAppStreamManager->destroy();
mAppStreamManager = nullptr;
}
mAppStreamManager = IAppStreamManager::create(
IAppStreamManager::CreationInfo{
.mInstanceId = getInstanceId(),
.mCameraDeviceCallback = callback,
.mMetadataProvider = mStaticInfo.mMetadataProvider,
.mPhysicalMetadataProviders = mStaticInfo.mPhysicalMetadataProviders,
.mMetadataConverter = mStaticInfo.mMetadataConverter,
.mErrorPrinter = std::static_pointer_cast<android::Printer>(mAppStreamManagerErrorState),
.mWarningPrinter = std::static_pointer_cast<android::Printer>(mAppStreamManagerWarningState),
.mDebugPrinter = std::static_pointer_cast<android::Printer>(mAppStreamManagerDebugState),
}
);
if ( mAppStreamManager == nullptr ) {
MY_LOGE("IAppStreamManager::create");
return NO_INIT;
}
}
//--------------------------------------------------------------------------
{
Mutex::Autolock _l(mPipelineModelLock);
auto pPipelineModelMgr = IPipelineModelManager::get();
if ( CC_UNLIKELY(pPipelineModelMgr == nullptr) ) {
MY_LOGE("IPipelineModelManager::get() is null object!");
return NO_INIT;
}
//
auto pPipelineModel = pPipelineModelMgr->getPipelineModel( getInstanceId() );
if ( CC_UNLIKELY(pPipelineModel == nullptr) ) {
MY_LOGE("IPipelineModelManager::getPipelineModel(%d) is null object!", getInstanceId());
return NO_INIT;
}
//
::android::status_t err = OK;
err = pPipelineModel->open(getInstanceName().c_str(), this);
if ( CC_UNLIKELY(OK != err) ) {
MY_LOGE( "fail to IPipelinemodel->open() status:%d(%s)", -err, ::strerror(-err) );
return NO_INIT;
}
mPipelineModel = pPipelineModel;
mConfigTimestamp = (uint64_t)::systemTime();
MY_LOGD("timestamp(%" PRIu64 ")", mConfigTimestamp);
}
//--------------------------------------------------------------------------
return OK;
}
6、vendor/mediatek/proprietary/hardware/mtkcam3/main/hal/devicemgr/CameraDeviceManagerBase.cpp
对应 图上 2.3.1
reset 所有东西
有任何改变通知CameraService,在其中改变状态
auto
CameraDeviceManagerBase::
finishOpenDevice(
const std::string& deviceName,
bool cancel
) -> ::android::status_t
{
status_t status = OK;
::android::sp<IVirtualDevice> pVirtualDevice = nullptr;
//
{
RWLock::AutoRLock _l(mDataRWLock);
status = getVirtualDeviceLocked(deviceName, nullptr, &pVirtualDevice);
if ( OK != status ) {
return status;
}
}
//
{
CAM_TRACE_NAME(LOG_TAG ":finishOpenDevice");bool needToFlushTorchCallback = ( ! cancel );
//
// check to see whether this is called by the same device and operation.
status = mActiveOperation.validate(pVirtualDevice, ActiveOperation::OPEN);
if ( OK != status ) {
return status;
}
//
{
RWLock::AutoWLock _l(mDataRWLock);
//
// restore all states when the operation is cancelled.
if ( cancel ) {
// detach opened device
updatePowerOnDone();
detachOpenDeviceLocked(pVirtualDevice);
// undo commands
for (auto const& pCommand : mActiveOperationCommandList) {
pCommand->undoExecute();
}
}// reset everything
mActiveOperationCommandList.clear();
}
//
if ( OK == status ) {
// unlock only for the right owner.
mActiveOperation.unlock(pVirtualDevice, ActiveOperation::OPEN);
}
//
// flush torch callback
if ( needToFlushTorchCallback ) {
flushTorchModeStatusChangeCallback();
}
}
//
if ( OK == status ) {
CAM_TRACE_ASYNC_END(
String8::format("%s:" LOG_TAG ":OpenDevice", pVirtualDevice->getInstanceName()).string(),
pVirtualDevice->getInstanceId());
}
return status;
}
vendor/mediatek/proprietary/hardware/mtkcam3/main/hal/devicemgr/provider/2.4/CameraProviderImpl.cpp
void
CameraProviderImpl::
onTorchModeStatusChange(char const* deviceName, uint32_t new_status)
{
::android::sp<ICameraProviderCallback> callback;
{
Mutex::Autolock _l(mProviderCallbackLock);
callback = mProviderCallback;
}if ( callback == 0 ) {
MY_LOGW("bad mProviderCallback - %s new_status:%u", deviceName, new_status);
return;
}TorchModeStatus const status = (TorchModeStatus) new_status;
auto ret = callback->torchModeStatusChange(deviceName, status);
if (!ret.isOk()) {
MY_LOGE("Transaction error in ICameraProviderCallback::torchModeStatusChange: %s", ret.description().c_str());
}
MY_LOGI("%s TorchModeStatus:%u", deviceName, status);
}
图略
3、camera close 流程
* 12. Alternatively, the framework may call camera3_device_t->common->close()
* to end the camera session. This may be called at any time when no other
* calls from the framework are active, although the call may block until all
* in-flight captures have completed (all results returned, all buffers
* filled). After the close call returns, no more calls to the
* camera3_callback_ops_t functions are allowed from the HAL. Once the
* close() call is underway, the framework may not call any other HAL device
* functions.
*
* 13. In case of an error or other asynchronous event, the HAL must call
* camera3_callback_ops_t->notify() with the appropriate error/event
* message. After returning from a fatal device-wide error notification, the
* HAL should act as if close() had been called on it. However, the HAL must
* either cancel or complete all outstanding captures before calling
* notify(), so that once notify() is called with a fatal error, the
* framework will not receive further callbacks from the device. Methods
* besides close() should return -ENODEV or NULL after the notify() method
* returns from a fatal error message.
图略
close是open的逆序操作,一笔而过
4、log
//open camera
08-26 11:30:38.443727 4145 4145 I mtkcam-dev3: 0[CameraDevice3Impl::open] open camera3 device (device@3.6/internal/0) systraceLevel(1) instanceId(0) vid(0)
mtkcam-dev3: [0-session::open] +
08-26 11:30:38.444652 4145 4145 D mtkcam-dev3: [0-session::open] Link death to ICameraDeviceCallback {.pid = 4144, .ptr = 4098102640, .arch = IS_32BIT}
08-26 11:30:38.448418 4145 4145 D mtkcam-devicemgr: [startOpenDevice] + device@3.6/internal/0 mActiveOperationCommandList.size:0 mOpenDeviceMap.size:0 mPhysEnumDeviceMap.size:5 mVirtEnumDeviceMap.size:608-26 11:30:38.448529 4145 4145 I mtkcam-devicemgr: [attachOpenDeviceLocked] device: device@3.6/internal/0 openTimestamp:08-26 11:30:38.448
5、参考文档
1、https://blog.csdn.net/karaskass/article/details/106261187
6、恰饭
如果您觉得有用,感谢老铁请支持一波