码字不易,多谢支持
前文回顾
简单介绍Camx架构,接下来看下initialize流程
一、open&initialize 流程
1.1 原文解读
* 1. Framework calls camera_module_t->common.open(), which returns a
* hardware_device_t structure.
*
* 2. Framework inspects the hardware_device_t->version field, and instantiates
* the appropriate handler for that version of the camera hardware device. In
* case the version is CAMERA_DEVICE_API_VERSION_3_0, the device is cast to
* a camera3_device_t.
*
* 3. Framework calls camera3_device_t->ops->initialize() with the framework
* callback function pointers. This will only be called this one time after
* open(), before any other functions in the ops structure are called.1、打开相机:framework这块调用common结构体的方法,camera_module_t-> common.open(),在hw_module_methods_t这块的open你的方法来打开特定 Camera,返回一个的 hardware_device_t结构。
2、检查设备硬件版本,并为之实例化:framework检查hardware_device_t-> version字段,并为该版本的相机硬件设备实例化适当的处理程序。 如果版本为CAMERA_DEVICE_API_VERSION_3_0,则设备将投射到的camera3_device_t。
3、初始化:在open()之后,ops结构中的任何其他函数之前,只调用一次initialize。framework使用framework回调函数指针调用1camera3_device_t-> ops->camera3_device_ops的 initialize()。
1.2 官网文档
《80-pc212-1_a_chi_api_specifications_for_qualcomm_spectra_2xx_camera.pdf》简单介绍初始化驱动的过程
1.3 代码分析
Framework到HAL3的衔接在上一篇文章概述了 Framework和HAL3之间概述,还是简单顺一下framework这块的逻辑。
hardware/interfaces/camera/provider/2.4/default/CameraProvider_2_4.cpp 中 (1)创建 CameraProvider对象 (2)获取ExternalCameraProviderImpl_2_4实例
hardware/interfaces/camera/provider/2.4/default/ExternalCameraProviderImpl_2_4.cpp 中 (1)创建ExternalCameraDevice 对象
hardware/interfaces/camera/device/3.4/default/ExternalCameraDevice.cpp 中 (1)open
hardware/interfaces/camera/device/3.2/default/CameraDeviceSession.cpp 中 (1)initialize
代码分析这块直接从camxhal3entry.cpp 开始撸代码。
注意camxhal3entry.cpp这块和Framework的映射关系
1.3.1 open
vendor/qcom/proprietary/camx/src/core/hal/camxhal3entry.cpp
int open(
const struct hw_module_t* pHwModuleAPI,
const char* pCameraIdAPI,
struct hw_device_t** ppHwDeviceAPI)
{
/// @todo (CAMX-43) - Reload Jumptable from settings
JumpTableHAL3* pHAL3 = static_cast<JumpTableHAL3*>(g_dispatchHAL3.GetJumpTable());
return pHAL3->open(pHwModuleAPI, pCameraIdAPI, ppHwDeviceAPI);
}
(1)camxhal3entry.cpp这块 ops都是用JumpTable来获取到 camxhal3.cpp 中的JumpTableHAL3的跳转,open也不例外
vendor/qcom/proprietary/camx/src/core/hal/camxhal3.cpp
static int open(
const struct hw_module_t* pHwModuleAPI,
const char* pCameraIdAPI,
struct hw_device_t** ppHwDeviceAPI)
{
//省略一些断言判断
if ((NULL != pHwModuleAPI) &&
(NULL != pHwModuleAPI->id) &&
(NULL != pHwModuleAPI->name) &&
(NULL != pHwModuleAPI->author) &&
(NULL != pHwModuleAPI->methods) &&
(NULL != pCameraIdAPI) &&
('\0' != pCameraIdAPI[0]) &&
(NULL != ppHwDeviceAPI))
{
if (CamxResultSuccess == result)
{
// Framework camera ID should only be known to these static landing functions, and the remap function
logicalCameraId = GetCHIAppCallbacks()->chi_remap_camera_id(cameraId, IdRemapCamera);
// Reserve the Torch resource for camera.
// If torch already switched on, then turn it off and reserve for camera.
HAL3Module::GetInstance()->ReserveTorchForCamera(
GetCHIAppCallbacks()->chi_remap_camera_id(cameraId, IdRemapTorch), cameraId);
// Sample code to show how the VOID* can be used in ExtendOpen
ChiOverrideExtendOpen extend = { 0 };
ChiOverrideToken tokenList[NumExtendSettings] = { { 0 } };
extend.pTokens = tokenList;
GenerateExtendOpenData(NumExtendSettings, &extend);
// Reserve the camera to detect if it is already open or too many concurrent are open
CAMX_LOG_CONFIG(CamxLogGroupHAL, "HalOp: Begin OPEN, logicalCameraId: %d, cameraId: %d",
logicalCameraId, cameraId);
result = HAL3Module::GetInstance()->ProcessCameraOpen(logicalCameraId, &extend);
}
//省略一些modifySetting的操作
CAMX_LOG_CONFIG(CamxLogGroupHAL, "HalOp: End OPEN, logicalCameraId: %d, cameraId: %d",
logicalCameraId, cameraId);
}
return Utils::CamxResultToErrno(result);
}
(1)camxhal3.cpp 这块的open函数,重要的是 调用ProcessCameraOpen
(2)open函数之前 GetCHIAppCallbacks 会链接HAL3Module,后面的操作可以访问到HAL3Module的函数
vendor/qcom/proprietary/camx/src/core/hal/camxhal3module.cpp
CamxResult HAL3Module::ProcessCameraOpen(
UINT32 logicalCameraId,
VOID* pPriv)
{
CamxResult result = CamxResultSuccess;
//省略无效camera id、已经被使用camera id、CameraOpen个数大于最大值 判断
{
result = m_ChiAppCallbacks.chi_extend_open(logicalCameraId, pPriv);
if (CamxResultSuccess == result)
{
m_perCameraInfo[logicalCameraId].isCameraOpened = TRUE;
m_numCamerasOpened++;
CAMX_LOG_CONFIG(CamxLogGroupHAL, "number of Camera Opened %d", m_numCamerasOpened);
}
}
return result;
}
(1)camxhal3module.cpp这块的ProcessCameraOpen函数,重要的是 调用chi_extend_open
(2) m_ChiAppCallbacks 这块是由 HAL3Module函数中
CHIHALOverrideEntry funcCHIHALOverrideEntry =
reinterpret_cast<CHIHALOverrideEntry>(
CamX::OsUtils::LibGetAddr(m_hChiOverrideModuleHandle, "chi_hal_override_entry"));if (NULL != funcCHIHALOverrideEntry)
{
funcCHIHALOverrideEntry(&m_ChiAppCallbacks);
vendor/qcom/proprietary/chi-cdk/vendor/chioverride/default/chxextensioninterface.cpp
static CDKResult chi_extend_open(
uint32_t cameraId,
void* priv)
{
ExtensionModule* pExtensionModule = ExtensionModule::GetInstance();
return pExtensionModule->ExtendOpen(cameraId, priv);
}
(1)chxextensioninterface.cpp这块的chi_extend_open函数,重要的是 调用ExtendOpen
(2)是通过加头文件#include "chioverride.h" ,从camxhal3module.cpp 调到 chxextensioninterface.cpp
vendor/qcom/proprietary/chi-cdk/vendor/chioverride/default/chxextensionmodule.cpp
(1)配置参数,没有多少实际意义
CDKResult ExtensionModule::ExtendOpen(
uint32_t logicalCameraId,
VOID* pPriv)
{
// The ExtensionModule has been initialized, and if there is any work needed to be done during HAL open, this is where
// to add that code
// sample code...this uses the input to create a data structure used to hold configuration settings
ChiOverrideExtendOpen* pExtend = static_cast<ChiOverrideExtendOpen*>(pPriv);
UINT32 openCameraCost = m_singleISPResourceCost;
CDKResult result = CDKResultSuccess;
if ((NULL == m_pConfigSettings) || (pExtend->numTokens > MaxConfigSettings))
{
CHX_LOG_ERROR("ExtendOpen failed! m_pConfigSettings=%p, numTokens=%d MaxConfigSettings=%d",
m_pConfigSettings, pExtend->numTokens, MaxConfigSettings);
result = CDKResultEInvalidArg;
}
if (m_logicalCameraInfo[logicalCameraId].numPhysicalCameras > 1)
{
openCameraCost = m_singleISPResourceCost * 2; // dual/multi
}
if ((CDKResultSuccess == result) && (openCameraCost + CostOfAnyCurrentlyOpenLogicalCameras()) > m_totalResourceBudget)
{
CHX_LOG_ERROR("ExtendOpen failed! HW resource insufficient! openCameraCost=%d"
"CostOfAnyCurrentlyOpenLogicalCameras =%d, m_totalResourceBudget = %d",
openCameraCost, CostOfAnyCurrentlyOpenLogicalCameras(), m_totalResourceBudget);
result = CamxResultETooManyUsers; // over capacity
}
if (CDKResultSuccess == result)
{
if (NULL == m_pPerfLockManager[logicalCameraId])
{
m_pPerfLockManager[logicalCameraId] = PerfLockManager::Create();
if (NULL == m_pPerfLockManager[logicalCameraId])
{
CHX_LOG_ERROR("Failed to create perflock manager %d", logicalCameraId);
}
}
if (NULL != m_pPerfLockManager[logicalCameraId])
{
m_pPerfLockManager[logicalCameraId]->AcquirePerfLock(PERF_LOCK_OPEN_CAMERA, 1000);
}
MappingConfigSettings(pExtend->numTokens, static_cast<VOID*>(pExtend->pTokens));
// Update camera open and close status in static settings
for (UINT8 index = 0; index < m_logicalCameraInfo[logicalCameraId].numPhysicalCameras; index++)
{
UINT32 cameraId = m_logicalCameraInfo[logicalCameraId].ppDeviceInfo[index]->cameraId;
*m_pOverrideCameraOpen |= (1 << cameraId);
*m_pOverrideCameraClose &= ~(1 << cameraId);
}
CHX_LOG_INFO("Open Logical cameraId: %d numPhysicalCameras: %d"
"CameraOpen Mask = 0x%x CameraClose Mask 0x%x",
logicalCameraId, m_logicalCameraInfo[logicalCameraId].numPhysicalCameras,
*m_pOverrideCameraOpen, *m_pOverrideCameraClose);
m_TeardownInProgress = FALSE;
m_RecoveryInProgress = FALSE;
}
return result;
}
1.3.2 initialize
vendor/qcom/proprietary/camx/src/core/hal/camxhal3entry.cpp
int initialize(
const struct camera3_device* pCamera3DeviceAPI,
const camera3_callback_ops_t* pCamera3CbOpsAPI)
{
JumpTableHAL3* pHAL3 = static_cast<JumpTableHAL3*>(g_dispatchHAL3.GetJumpTable());
//省略一部分判断赋值的操作
return pHAL3->initialize(pCamera3DeviceAPI, pCamera3CbOpsAPI);
}
vendor/qcom/proprietary/camx/src/core/hal/camxhal3.cpp
static int initialize(
const struct camera3_device* pCamera3DeviceAPI,
const camera3_callback_ops_t* pCamera3CbOpsAPI)
{
CAMX_ENTRYEXIT_SCOPE(CamxLogGroupHAL, SCOPEEventHAL3Initialize);
CamxResult result = CamxResultSuccess;
CAMX_ASSERT(NULL != pCamera3DeviceAPI);
CAMX_ASSERT(NULL != pCamera3DeviceAPI->priv);
CAMX_LOG_INFO(CamxLogGroupHAL, "initialize(): %p, %p", pCamera3DeviceAPI, pCamera3CbOpsAPI);
if ((NULL != pCamera3DeviceAPI) &&
(NULL != pCamera3DeviceAPI->priv))
{
HALDevice* pHALDevice = GetHALDevice(pCamera3DeviceAPI);
pHALDevice->SetCallbackOps(pCamera3CbOpsAPI);
}
else
{
CAMX_LOG_ERROR(CamxLogGroupHAL, "Invalid argument(s) for initialize()");
// HAL interface requires -ENODEV (EFailed) if initialization fails for any reason, including invalid arguments.
result = CamxResultEFailed;
}
return Utils::CamxResultToErrno(result);
}
(1) GetHALDevice 获取当前HAL的device
(2) SetCallbackOps 设置回调
vendor/qcom/proprietary/camx/src/core/hal/camxhaldevice.cpp
CamxResult HALDevice::Initialize(
const HwModule* pHwModule,
UINT32 cameraId)
{
CamxResult result = CamxResultSuccess;
m_cameraId = cameraId;
if (CamxResultSuccess == result)
{
m_camera3Device.hwDevice.tag = HARDWARE_DEVICE_TAG; /// @todo (CAMX-351) Get from local macro
#if ((CAMX_ANDROID_API) && (CAMX_ANDROID_API >= 28)) // Android-P or better
m_camera3Device.hwDevice.version = CAMERA_DEVICE_API_VERSION_3_5;
#else
m_camera3Device.hwDevice.version = CAMERA_DEVICE_API_VERSION_3_3;
#endif // ((CAMX_ANDROID_API) && (CAMX_ANDROID_API >= 28))
m_camera3Device.hwDevice.close = reinterpret_cast<CloseFunc>(GetHwDeviceCloseFunc());
m_camera3Device.pDeviceOps = reinterpret_cast<Camera3DeviceOps*>(GetCamera3DeviceOps());
m_camera3Device.pPrivateData = this;
// NOWHINE CP036a: Need exception here
m_camera3Device.hwDevice.pModule = const_cast<HwModule*>(pHwModule);
m_HALCallbacks.process_capture_result = ProcessCaptureResult;
m_HALCallbacks.notify_result = Notify;
}
m_pHALSession = NULL;
Utils::Memset(m_flushRequest, 0, sizeof(m_flushRequest));
SIZE_T entryCapacity;
SIZE_T dataSize;
HAL3MetadataUtil::CalculateSizeAllMeta(&entryCapacity, &dataSize, TagSectionVisibleToFramework);
m_pResultMetadata = HAL3MetadataUtil::CreateMetadata(
entryCapacity,
dataSize);
for (UINT i = RequestTemplatePreview; i < RequestTemplateCount; i++)
{
if (NULL == m_pDefaultRequestMetadata[i])
{
ConstructDefaultRequestSettings(static_cast<Camera3RequestTemplate>(i));
}
}
const StaticSettings* pStaticSettings = HwEnvironment::GetInstance()->GetStaticSettings();
m_numPartialResult = pStaticSettings->numMetadataResults;
/* We will increment the Partial result count by 1 if CHI also has its own implementation */
if (CHIPartialDataSeparate == pStaticSettings->enableCHIPartialData)
{
m_numPartialResult++;
}
if (TRUE == pStaticSettings->enableThermalMitigation)
{
ThermalManager* pThermalManager = HAL3Module::GetInstance()->GetThermalManager();
if (NULL != pThermalManager)
{
CamxResult resultThermalReg = pThermalManager->RegisterHALDevice(this);
if (CamxResultEResource == resultThermalReg)
{
result = resultThermalReg;
}
// else Ignore result even if it fails. We don't want camera to fail due to any issues with initializing the
// thermal engine
}
}
return result;
}
(1)设置m_HALCallbacks( <--HAL callbacks provided to the CHI override)的 Resutl和 Notify的回调
(2)计算所有meta的size,生成metadata
(3)构建默认请求配置、获取静态配置
(4)注册HAL Device
二、LOG
01-24 13:29:53.274 779 779 I CamX : [CONFIG][HAL ] camxhal3.cpp:406 open() HalOp: Begin OPEN, logicalCameraId: 0, cameraId: 0
01-24 13:29:53.276 779 779 I CHIUSECASE: [INFO ] chxextensionmodule.cpp:553 ExtendOpen() Open Logical cameraId: 0 numPhysicalCameras: 1CameraOpen Mask = 0x1 CameraClose Mask 0x0
01-24 13:29:53.276 779 779 I CamX : [CONFIG][HAL ] camxhal3module.cpp:598 ProcessCameraOpen() number of Camera Opened 101-24 13:29:53.276 779 779 I CamX : [CONFIG][HAL ] camxhal3.cpp:466 open() HalOp: End OPEN, logicalCameraId: 0, cameraId: 0
三、常见问题
//TODO:回家吃饭,小伙子明天再搞