一. Android Hal3回顧
HAL層操作簡單總結(jié):
1.Framework層發(fā)送捕獲數(shù)據(jù)的異步請求。
2.HAL層設(shè)備必須按照次序處理請求。對于每個請求,HAL層需要輸出元數(shù)據(jù)和一個或者多個圖像數(shù)據(jù)。
3.對于請求和結(jié)果都需要遵循先進先出的原則;這個數(shù)據(jù)流將被后續(xù)的請求所參考。
4,對于同一個請求献雅,所有輸出數(shù)據(jù)的時間戳必須相同,以便framework層同步輸出數(shù)據(jù)塌计,如果需要的話挺身。
5.在請求和結(jié)果數(shù)據(jù)總,所有捕獲數(shù)據(jù)的配置和狀態(tài)(除了3A處理)锌仅,都需要封裝起來瞒渠。
二. Qcom Hal3 CamX架構(gòu)
Qcom作為平臺廠商會根據(jù)谷歌定義的HAL3接口來實現(xiàn)自己的Camera HAL3,新的主流的Qcom Camera HAL3 架構(gòu)就是CamX了.
Camx的詳細(xì)過程可參考高通文檔:
80-pc212-1_d_qualcomm_spectra_isp_camera_chi_api_reference.pdf
最主要還是要看code,手機廠商對該層代碼有自己的改動,可能差別還是有的,具體項目大體框架一致但細(xì)節(jié)有區(qū)別,差異和機型的高通基線也保持一致.
2.1 CamX架構(gòu)總體結(jié)構(gòu)
簡單總結(jié)下:
- Camx的架構(gòu)入口為Camx包中的camxhal3entry.cpp,Camx中是高通平臺Camx架構(gòu)的核心跳轉(zhuǎn)及處理業(yè)務(wù)的代碼,一般手機廠商不會去更改,代碼目錄在vendor/qcom/proprietary/camx/下,編譯結(jié)果是camera.qcom.so
- Camx通過chxentensionInterface調(diào)用到chi-cdk 包下的代碼,這里面一般是手機廠商自己定制功能的地方,代碼目錄在vendor/qcom/proprietary/chi-cdk/,編譯結(jié)果是com.qti.chi.override.so
- 從這張圖中大概知道一個request來業(yè)務(wù)流程交給camx處理,但會經(jīng)過chi-cdk進行request定制化重新打包再交給camx實際去執(zhí)行或和kernel driver層進行交互,camx部分代碼即核心流程管控的代碼,而chi-cdk正是手機廠商想要實現(xiàn)自己定制化功能的代碼地方.
2.2 CamX架構(gòu)中重要的數(shù)據(jù)結(jié)構(gòu)及關(guān)系
缺一張圖
Usecase /Session/ Feature /pipeline/ Node
- Chi對Camx的操作良蒸,需要通過 ExtensionModule 進行操作,因此伍玖,camx對外提供的接口擴展需要通過ExtensionModule進行嫩痰,里面一個重要的變量就是g_chiContextOps。
- Camx對Chi的操作窍箍,是通過HAL3Module接口的m_ChiAppCallbacks進行的串纺,因此chi里面釋放的接口,都會在m_ChiAppCallbacks里面體現(xiàn)
- Usecase:基本上與App上的各種模式有一定的對應(yīng)關(guān)系椰棘,包括PreviewZSL,VideoLiveShot, SAT(Multicamera), RTB(Reatime Bokeh)纺棺,QCFA, Dual, superslowmotionfrc.., 一個usecase包含了realtime和snapshot的session邪狞, 需要包含所有的在這個usecase的所有feature的pipeline列表
- Feature: 在Usecase下打開某個功能設(shè)計的一種架構(gòu)祷蝌,通常情況下一個Usecase可以啟用各種不同的feature,feture包含了usecase里面的部分pipeline, 一般都是snapshot的才會包含feature進行處理帆卓,因此巨朦,usecase與feautre的界限并不明顯。
- Session: 包含了ChxSession剑令,ChiSession和CamxSession糊啡。Chxsession是對chi接口里面對CamxSession的封裝,Usecase里面創(chuàng)建的Session都是要創(chuàng)建這一個吁津。ChiSession是camx里面的一個部分棚蓄,是對camxSession的繼承和透傳。
- pipeline-包含單個經(jīng)過驗證的topology的可重用容器碍脏。驅(qū)動程序通過pipeline來了解所使用的引擎以及數(shù)據(jù)處理的流程梭依。
- Node—camera pipeline 內(nèi)的邏輯功能塊,在單個引擎上執(zhí)行典尾。node鏈接在一起構(gòu)成一個topology睛挚。在CHI API的初始版本中,ISP外部的所有節(jié)點都是通過CPU代碼調(diào)用的急黎,調(diào)的是native API。
不同機型,產(chǎn)品性能及定位不同,即使基線一樣usecase等也有可能不一樣,高通這么做給了手機廠商極大的自定義空間,舉個某機型例子,UseCase可以場景復(fù)用,對應(yīng)的pipeline也可以不用或復(fù)用.
2.3 CamX操作過程
基本操作,截圖自高通文檔:
詳細(xì)過程:
2.3.1 Open Camera
在這里插入圖片描述
2.3.2 ConfigureStream
2.3.3 Request & Result
request:
result:
一旦底層有事件上傳就會走到SyncManagerPollMethod中:
file: vendor/qcom/proprietary/camx/src/csl/hw/camxsyncmanager.cpp
--> VOID* SyncManager::SyncManagerPollMethod(VOID* pPollData)
|--> rc = poll(fds, 2, -1) //監(jiān)聽的syncFd有事件上傳
| |--> VOID* pData[] = {pEv, NULL}; //這里的pEv是包含回調(diào)方法的侧到,根據(jù)setRepeatingRequest中的分析勃教,這里的回調(diào)就是Node::CSLFenceCallback
| |--> ioctl(pCtrl->syncFd, VIDIOC_DQEVENT, pEv); //取出事件
| |--> result = pCtrl->pThreadManager->PostJob(pCtrl->hJob, SyncManager::StoppedCbDispatchJob, pData, FALSE, FALSE); //這里就會調(diào)到之前注冊的線程并回調(diào)SyncManager::CbDispatchJob方法
file: vendor/qcom/proprietary/camx/src/csl/hw/camxsyncmanager.cpp
| |--> VOID* SyncManager::CbDispatchJob(VOID* pData)
| | |--> Utils::Memcpy(&ev, reinterpret_cast<struct v4l2_event*> (pData), sizeof(ev));
| | |--> pPayloadData = CAM_SYNC_GET_PAYLOAD_PTR(ev, uint64_t);
| | |--> reinterpret_cast<CSLFenceHandler>(pPayloadData[0]))(reinterpret_cast<VOID* >(pPayloadData[1]), pEvHeader->sync_obj, fenceResult); //回調(diào)Node::CSLFenceCallback
file: vendor/qcom/proprietary/camx/src/core/camxnode.cpp
| | |--> VOID Node::CSLFenceCallback(...)
| | | |--> result = pNode->GetThreadManager()->PostJob(pNode->GetJobFamilyHandle(), NULL, &pData[0], FALSE, FALSE) //將工作放到JobFamilyHandle線程去做,回調(diào)Node::NodeThreadJobFamilyCb方法
| | | | |--> VOID* Node::NodeThreadJobFamilyCb(...) //因為是另一個線程處理,所以這個以縮進代表異步關(guān)系
| | | | | |--> FenceCallbackData* pFenceCallbackData = static_cast<FenceCallbackData*>(pCbData);
| | | | | |--> NodeFenceHandlerData* pNodeFenceHandlerData = static_cast<NodeFenceHandlerData*>(pFenceCallbackData->pNodePrivateData);
| | | | | |--> pFenceCallbackData->pNode->ProcessFenceCallback(pNodeFenceHandlerData);
| | | | | | |--> OutputPort* pOutputPort = pFenceHandlerData->pOutputPort;
| | | | | | |--> UINT64 requestId = pFenceHandlerData->requestId;
| | | | | | |--> UINT requestIdIndex = requestId % MaxRequestQueueDepth;
| | | | | | |--> m_pPipeline->NonSinkPortFenceSignaled(&pFenceHandlerData->hFence, pFenceHandlerData->requestId); //如果是no sink port
file: vendor/qcom/proprietary/camx/src/core/camxpipeline.cpp
| | | | | | |--> VOID Pipeline::NonSinkPortFenceSignaled(...)
| | | | | | | |--> m_pDeferredRequestQueue->FenceSignaledCallback(phFence, requestId);
file: vendor/qcom/proprietary/camx/src/core/camxdeferredrequestqueue.cpp
| | | | | | | |--> VOID DeferredRequestQueue::FenceSignaledCallback(...)
| | | | | | | | |--> UpdateDependency(PropertyIDInvalid, phFence, NULL, requestId, 0, TRUE);
| | | | | | | | |--> DispatchReadyNodes();
| | | | | | | | | |--> CamxResult result = m_pThreadManager->PostJob(m_hDeferredWorker, NULL, &pData[0], FALSE, FALSE); //針對所有ready Nodes 循環(huán)處理,m_hDefferredWorker 對應(yīng)的回調(diào)是DeferredWorkerWrapper
| | | | | | | | | | |--> VOID* DeferredRequestQueue::DeferredWorkerWrapper(VOID* pData) //異步調(diào)用,以縮進表示
| | | | | | | | | | | |--> Dependency* pDependency = reinterpret_cast<Dependency*>(pData);
| | | | | | | | | | | |--> DeferredRequestQueue* pDeferredQueue = pDependency->pInstance;
| | | | | | | | | | | |--> result = pDeferredQueue->DeferredWorkerCore(pDependency);
| | | | | | | | | | | | |--> pNode->ProcessRequest(&processRequest, pDependency->requestId)
file: vendor/qcom/proprietary/camx/src/core/camxnode.cpp
| | | | | | | | | | | | |--> CamxResult Node::ProcessRequest(NodeProcessRequestData* pNodeRequestData, UINT64 requestId)
| | | | | | | | | | | | | |--> result = ExecuteProcessRequest(&executeProcessData); //這里暫時以ipe node為例進行分析
file: vendor/qcom/proprietary/camx/src/hwl/ipe/camxipenode.cpp
| | | | | | | | | | | | | |--> CamxResult IPENode::ExecuteProcessRequest(ExecuteProcessRequestData* pExecuteProcessRequestData)
| | | | | | | | | | | | | | |--> GetHwContext()->Submit(GetCSLSession(), m_hDevice, pIQPacket); //發(fā)送設(shè)置命令
file: vendor/qcom/proprietary/camx/src/core/camxhwcontext.cpp
| | | | | | | | | | | | | | |--> CamxResult HwContext::Submit(CSLHandle hCSLSession, CSLDeviceHandle hDevice, Packet* pPacket)
| | | | | | | | | | | | | | | |--> result = CSLSubmit(hCSLSession, hDevice, pPacket->GetMemHandle(), pPacket->GetOffset());
file: vendor/qcom/proprietary/camx/src/csl/camxcsl.cpp
| | | | | | | | | | | | | | | |--> CamxResult CSLSubmit(...)
| | | | | | | | | | | | | | | | |--> return pJumpTable->CSLSubmit(hCSL, hDevice, hPacket, offset); //跳轉(zhuǎn)方法見func_list_camx_chi ⑤ ,接下來我就不分析了
| | | | | | |--> m_pPipeline->SinkPortFenceSignaled(pOutputPort->sinkTargetStreamId, ...) //如果是sink port
file: vendor/qcom/proprietary/camx/src/core/camxpipeline.cpp
| | | | | | |--> VOID Pipeline::SinkPortFenceSignaled(...)
| | | | | | | |--> ResultsData resultsData = {};
| | | | | | | |--> resultsData.pPrivData = pPerRequestInfo->request.pPrivData;
| | | | | | | |--> resultsData.type = CbType::Buffer;
| | | | | | | |--> m_pSession->NotifyResult(&resultsData);
file: vendor/qcom/proprietary/camx/src/core/camxsession.cpp
| | | | | | | |--> VOID Session::NotifyResult(ResultsData* pResultsData)
| | | | | | | | |--> switch (pResultsData->type)
| | | | | | | | |--> case CbType::Buffer:
| | | | | | | | |--> HandleBufferCb(&pResultsData->cbPayload.buffer, pResultsData->pipelineIndex, pResultsData->pPrivData);
| | | | | | | | | |--> InjectResult(ResultType::BufferOK, &outBuffer, pPayload->sequenceId, pPrivData, pipelineIndex);
| | | | | | | | | | |--> result = m_pThreadManager->PostJob(m_hJobFamilyHandle, NULL, &pData[0], FALSE, FALSE); //這里的線程cb是CHISession::ThreadJobCallback,為什么呢匠抗?
file: vendor/qcom/proprietary/camx/src/core/chi/camxchisession.cpp
| | | | | | | | | | |--> VOID* CHISession::ThreadJobCallback(VOID* pData)
| | | | | | | | | | | |--> result = pSession->ThreadJobExecute();
| | | | | | | | | | | | |--> result = ProcessResults();
file: vendor/qcom/proprietary/camx/src/core/camxsession.cpp
| | | | | | | | | | | | |--> CamxResult Session::ProcessResults()
| | | | | | | | | | | | | |--> LightweightDoublyLinkedListNode* pNode = m_resultHolderList.Head();
| | | | | | | | | | | | | |--> bufferReady = ProcessResultBuffers(pResultHolder, metadataReady, &numResults); //針對每一個node都調(diào)用這個方法故源,感覺這里就是全部node處理buffer的一個過程,后期需要確認(rèn)下
| | | | | | | | | | | | | |--> pNode = m_resultHolderList.NextNode(pNode); //取出下一個node進行操作
| | | | | | | | | | | | | |--> DispatchResults(&m_pCaptureResult[0], numResults); //發(fā)送results
| | | | | | | | | | | | | | |--> m_chiCallBacks.ChiProcessCaptureResult(&pCaptureResults[index], m_pPrivateCbData); //這里的m_chiCallBacks的介紹見func_list_camx_chi ⑦
file: vendor/qcom/proprietary/chi-cdk/vendor/chioverride/default/chxadvancedcamerausecase.h
| | | | | | | | | | | | | | |--> static VOID ProcessResultCb(...)
| | | | | | | | | | | | | | | |--> static_cast<AdvancedCameraUsecase*>(pCbData->pUsecase)->ProcessResult(pResult, pPrivateCallbackData);
file: vendor/qcom/proprietary/chi-cdk/vendor/chioverride/default/chxadvancedcamerausecase.cpp
| | | | | | | | | | | | | | | |--> VOID AdvancedCameraUsecase::ProcessResult(...)
| | | | | | | | | | | | | | | | |--> pFeature->ProcessResult(pResult, pPrivateCallbackData); //如果是AdvancedFeatureEnabled,這里我們考慮的是預(yù)覽汞贸,所以不是這分支
| | | | | | | | | | | | | | | | |--> CameraUsecaseBase::SessionCbCaptureResult(pResult, pPrivateCallbackData);
| | | | | | | | | | | | | | | | | |--> pCameraUsecase->SessionProcessResult(pCaptureResult, pSessionPrivateData);
| | | | | | | | | | | | | | | | | | |--> camera3_capture_result_t* pUsecaseResult = GetCaptureResult(resultFrameIndex);
| | | | | | | | | | | | | | | | | | |--> ChxUtils::PopulateChiToHALStreamBuffer(&pResult->pOutputBuffers[i], pResultBuffer);
| | | | | | | | | | | | | | | | | | |--> ProcessAndReturnFinishedResults();
| | | | | | | | | | | | | | | | | | | |--> Usecase::ReturnFrameworkResult(&result, m_cameraId);
file: vendor/qcom/proprietary/chi-cdk/vendor/chioverride/default/chxusecase.cpp
| | | | | | | | | | | | | | | | | | | |--> VOID Usecase::ReturnFrameworkResult(...)
| | | | | | | | | | | | | | | | | | | | |--> ExtensionModule::GetInstance()->ReturnFrameworkResult(pResult, cameraID);
file: vendor/qcom/proprietary/chi-cdk/vendor/chioverride/default/chxextensionmodule.cpp
| | | | | | | | | | | | | | | | | | | | |--> VOID ExtensionModule::ReturnFrameworkResult(const camera3_capture_result_t* pResult, UINT32 cameraID)
| | | | | | | | | | | | | | | | | | | | | |--> m_pHALOps->process_capture_result(m_logicalCameraInfo[cameraID].m_pCamera3Device, pResult); //這里就將result給到上面了
2.3.4 Flush
三.Qcom Hal3 Camx 重點
下面是具體項目上的工作者需要知道的camera相關(guān)的點,具體細(xì)節(jié)不贅述,這里記錄下,方便記憶.
3.1 定制化
定制pipeline要走那些算法及節(jié)點配置在xml中,類似魚如下路徑
vendor/qcom/proprietary/chi-cdk/vendor/topology/qcom/sdm845/sdm845_usecase.xml
源碼下可能因為共線有多個,要看清楚makefile中指定的是哪個.
bypass 是高通做的一套框架绳军,目的在于減少不必要的拷貝印机。
3.2 性能perflock
高通的perflock調(diào)試,需要掌握,可以通過抓取systrace來看cpu相關(guān)的變化,也可以通過讀取
/sys/devices/system/cpu/下的信息來調(diào)查cpu變化情況.
3.3 常見的node及作用
Node | 作用 | |
---|---|---|
BPS | Bayer Processing Segment,Bayer處理階段门驾。僅做snapshot的噪點降低和Bayer處理射赛,不良像素、PDAF奶是、LSC校正楣责,綠色不平衡校正,黑色級別聂沙,通道增益秆麸,demosaic,Down scaler及汉,HDR的合并與記錄沮趣,Bayer混合降噪等 | |
IFE | Image front-end engine,圖像前端引擎坷随。僅做video/preview的Bayer處理房铭,做些顏色校正,Down scaler甸箱,demosaic育叁,統(tǒng)計3A數(shù)據(jù)等 | |
IPE | Image-processing engine,圖像處理引擎芍殖。由NPS豪嗽、PPS兩部分組成,主要做些硬件降噪(MFNR豌骏、MFSR)龟梦、調(diào)整大小、噪聲處理窃躲、顏色處理(色差校正计贰、色度抑制)、細(xì)節(jié)增強(膚色增強) | |
JPEG | 打包jpeg | |
STATS | for 3A,ISP硬件給出的3A數(shù)據(jù)蒂窒,用于后面的3A算法 |
還有其他 縮略詞
IS 圖像穩(wěn)定 (Image Stabilization)
RDI 原始數(shù)據(jù)轉(zhuǎn)儲接口 (Raw Dump Interface)
RoI AF 感興趣區(qū)域 (AF Region of Interest)
SNoC 系統(tǒng) NoC (System NoC)
SOF:start of frame
ANR:application not response
MCC: mutil camera control
LPM: low power manager(低功耗下運行)
CTS/ITS :Android Camera Image Test Suite (ITS) is part of Android Compatibility Test Suite (CTS)
Android相機圖像測試套件(ITS)是Android兼容性測試套件(CTS)的一部分
驗證程序躁倒,包括驗證圖像內(nèi)容的測試。
從CTS 7.0_r8開始洒琢,CTS Verifier通過一體式攝像機ITS支持ITS測試自動化秧秉。
繼續(xù)支持手動測試,以確保涵蓋所有Android設(shè)備尺寸衰抑。
HAF:混合自動變焦
CRM: camera request manager
Sensor CRA(主光線角)
從鏡頭的傳感器一側(cè)象迎,可以聚焦到像素上的光線的最大角度被定義為一個參數(shù),稱為主光角(CRA)呛踊。對于主光角的一般性定義是:此角度處的像素響應(yīng)降低為零度角像素響應(yīng)(此時砾淌,此像素是垂直于光線的)的80%
https://blog.csdn.net/weixin_39839293/article/details/82118991
lens CRA與sensor 不配會使sensor 的pixel 出現(xiàn)在光檢測區(qū)域周圍啦撮,使pixel 曝光不足,亮度不夠汪厨,會使整個畫面造成亮度不均勻的情況赃春。還有可能造成chroma shading 或局部色偏。局部色偏比較嚴(yán)重骄崩,無法用算法補償
Sensor HDR:
sensor在一幅圖像里能夠同時體現(xiàn)高光和陰影部分內(nèi)容的能力
lens fov:視場角
視場角與焦距的關(guān)系:一般情況下聘鳞,視場角越大,焦距就越短
IFE :Image Front End要拂, Bayer processing for video/preview only抠璃, HDR/De-mosic, color correction 脱惰,scaler搏嗡,也可以直接輸出Raw到RDI
RDI : Raw Dump Interface,直接從IFE吐出來用于capture的
STATS:for 3A,ISP硬件給出的3A數(shù)據(jù)拉一,用于后面的3A算法
PDPC:PhaseDetection Pixel Correction采盒,相位檢測像素校正
ASD: Auto scene detection,自動場景檢測
CSIC:Camera serial interface decoder,攝像機串行接口解碼器
CAMIF: Ideal Raw的第一個dump點
FD: Face-based,基于人臉蔚润,也就是人臉識別
ICA:圖像校正和調(diào)整 是一個硬件單元磅氨,主要用于由鏡頭和運動引起的幾何扭曲
LENR:低/中頻增強和降噪
TMC:色調(diào)映射控制
CSID:攝像機串行接口解碼器模塊
IFE:圖像前端
IFE_Lite:?
BPS:Bayer處理段
IPE:圖像處理引擎
VPU:視頻處理單元
DPU:顯示處理單元
BPC:壞像素校正
BCC:壞群集校正
ABF:自適應(yīng)拜耳濾波器
GIC:綠色不平衡校正
GTM:全局色調(diào)映射
HNR:混合降噪
ANR:先進的降噪功能
TF:時間過濾器
MFNR:多幀降噪
LTM:局部色調(diào)映射
CS:色度抑制
ASF:自適應(yīng)空間濾波器
Upscaler:升頻器
GRA:Grain Adder(紋理增加器嫡纠?)烦租??
CPAS:相機外圍設(shè)備和支持
CAMIF:攝像頭接口除盏?叉橱??它是VFE(video front-end)硬件的第一部分者蠕,主要任務(wù)是同步sensor發(fā)送數(shù)據(jù)過程中涉及到的行窃祝、場同步信號。另外它還具有圖像提取和圖像鏡像能力踱侣,CAMIF hardware使外部camera sensor能夠通過一些簡單的外部協(xié)議鏈接到用戶單元粪小。為camera提供了數(shù)據(jù)和時鐘接口,但并沒有提供控制接口抡句,最具代表行的是用I2C做配置和狀態(tài)接口探膊。當(dāng)然,也可以是其他的一次控制信號做一些靜態(tài)控制玉转。例如:睡眠喚醒模式控制。
NPS:噪聲處理部分
PPS:后處理部分
MCTF:運動補償時間濾波
CAC殴蹄、CCM究抓、GLUT猾担、2D LUT(二維查找表?)刺下、CV(顏色轉(zhuǎn)換)绑嘹、CC(顏色校正)、SCE(膚色增強)橘茉、MCE(記憶色彩增強):工腋??畅卓?
SIMO:單輸入多輸出
Pedestal Correction:基座校正
Down Scaler:降低規(guī)模(尺寸)
Chroma Enhancement:色度增強
Chroma Suppression:色度抑制
PDAF:相位檢測自動對焦
LSC:鏡頭陰影校正
PNR:峰值降噪
ADRC:自動動態(tài)范圍壓縮
Backlit scene:背光場景
Garage scene:車庫場景
HNR:降低亮度噪聲擅腰,但保持紋理細(xì)節(jié)
LDC:鏡頭畸變校正
EIS:電子穩(wěn)像
Multi pass spatial noise filtering:多通空間噪聲濾波
LNR:鏡頭降噪
Invert gamma:反轉(zhuǎn)伽瑪
hue, saturation, lightness:色調(diào),飽和度翁潘,亮度
Upscaler:升頻器
ACE:高級色度增強
CPP:相機后處理器(相當(dāng)于新版的BPS趁冈、IPE)
BSP
board support package,板級支持安裝包拜马?
也就是“做出支持安裝包渗勘,來實現(xiàn)手機上各個硬件的基本功能”。
CCT:correlated color temperature俩莽,相關(guān)色溫旺坠,具體不詳;
chi-cdk:
Camera Hardward Interface扮超,相機硬件接口取刃;
Camera Development Kit,相機開發(fā)包瞒津;
HFR:High Frame Rate, min HFR=90, means>=90時蝉衣,需要enable HFR高幀率惭婿,目前最高960侥锦,但是是利用插值算法計算得出的,非實際960
3.4 日志資料
Camx日志由屬性控制,具體也是一套規(guī)則,
首先獲取權(quán)限:
adb root && adb remount
如果remount報錯:failed: Read-only file system
則執(zhí)行adb disable-verity && adb reboot 解決中狂,然后重新
adb root && adb remount
Camera user mode driver (UMD) ——相機用戶模式驅(qū)動
UMD的顯示格式
CamX: [<Verbosity Level>][<Group>] <File>:<Line Number> <Function Name> <Message>
例如:CamX : [ INFO][HAL ] camxhal3.cpp:1086 process_capture_request() frame_number 140
這里將log分為不同的level屁柏,不同的level下面有不同的group
如何打開指定level的指定group的log啦膜?其各level和group見相應(yīng)的camxtypes.h
如何打開指定level? level直接通過Name設(shè)定;
group通過二進制的每一位來確定淌喻,每個group對應(yīng)一個bit,置1表示打開
例如:logVerboseMask=0xFFFFFFFF //打開所有g(shù)roup的verbose級別的log
logWarningMask=0x82 //Warning級別打開第1個位和第6位表示的group僧家,其實是Sensor和HAL的group
平常測試開的log:
如何實際進行打開log
在手機中的: /vendor/etc/camera/camxoverridesettings.txt
例如:adb shell "echo logInfoMask=0xFFFFFFFF>> /vendor/etc/camera/camxoverridesettings.txt"
chi log:
例如:CHX_LOG_ERROR(fmt, args);
adb shell "echo overrideLogLevels=0x1f >> /vendor/etc/camera/camxoverridesettings.txt"
或:adb shell setprop vendor.debug.camera.overrideLogLevels 0x1F (camxsettings.xml中定義裸删,不同的代碼可能有區(qū)別)
平常開的log:
adb shell "echo logInfoMask=0x50080 >> /vendor/etc/camera/camxoverridesettings.txt" hal/core/chi
adb shell setprop persist.vendor.camera.logVerboseMask 0xFFFFFFFF
adb shell setprop persist.vendor.camera.logEntryExitMask 0xFFFFFFFF
adb shell setprop persist.vendor.camera.logInfoMask 0xFFFFFFFF
adb shell setprop persist.vendor.camera.logWarningMask 0xFFFFFFFF
adb shell setprop persist.vendor.camera.logConfigMask 0xFFFFFFFF
adb shell setprop persist.vendor.camera.systemLogEnable TRUE
adb shell setprop persist.vendor.camera.logLogDRQMask 0xFFFFFFFF
camx log:
adb shell "echo overrideLogLevels=0xF >> /vendor/etc/camera/camxoverridesettings.txt"
adb shell "echo logVerboseMask=0x1000 >> /vendor/etc/camera/camxoverridesettings.txt"
adb shell "echo logInfoMask=0xFFFFFFFF >> /vendor/etc/camera/camxoverridesettings.txt"