【高通SDM660平台】Camera Init 初始化流程
一、Camera 系统架构二、Camera Init 初始化流程2.1 CameraService 启动2.2 CameraService::instantiate()2.3 CameraService.cpp2.4 CameraService::CameraService()2.5 CameraService::onFirstRef()2.6 获取Camera数量 mModule->getNumberOfCameras()2.7 hardware层调用 get_num_of_cameras()2.8 Camera Init 初始化流程总结 三、hw_get_module()3.1 camera.sdm660.so《【高通SDM660平台】(1) — Camera 驱动 Bringup Guide》
《【高通SDM660平台】(2) — Camera Kernel 驱动层代码逻辑分析》
《【高通SDM660平台】(3) — Camera V4L2 驱动层分析 》
《【高通SDM660平台】(4) — Camera Init 初始化流程 》
《【高通SDM660平台】(5) — Camera Open 流程》
《【高通SDM660平台】(6) — Camera getParameters 及 setParameters 流程》
《【高通SDM660平台】(7) — Camera onPreview 代码流程》
《【高通SDM660平台】(8) — Camera MetaData介绍》
《【高通SDM660平台 Android 10.0】(9) — Qcom Camera Daemon 代码分析》
《【高通SDM660平台 Android 10.0】(10) — Camera Sensor lib 与 Kernel Camera Probe 代码分析》
《【高通SDM660平台】Camera Capture 流程》
《【高通SDM660平台】Camera mm-qcamera-app 代码分析》
Open Camera是Preview、TakePicture、Record的基础,Open Camera会初始化很多对象,
而Preview、TakePicture、Record等操作是围绕着这些对象进行操作的,所以这里用Open Camera来理清各个对象间的交互关系
一、Camera 系统架构
看到一张好图,自:《sdm660–opencamera流程详细分析》
Camera模块的系统架构分为四层,从上到下分别是
Package 文件夹下的 Java 层
Framework 文件夹下的 Framework 层
Framework层下细分为:Java Framework、JNI Framework、Hardware Interface Framework 。
Hardware 文件夹下的 Hal 层
HAL 层下又细分为 Hardware Interface 与 mm-camera 层
ADIL 是 JNI Framework 层 与 Hardware Interface Framework 层 交互的接口,即 CameraClient 进程 与 CameraService 进程的交互。
HIDL 是发生在 Framework 层 与 HAL层交互的接口。
Kernel 文件夹下的 Driver 层
接下来,我们进代码分析下 Camera Init 初始化流程
二、Camera Init 初始化流程
2.1 CameraService 启动
CameraService 是一个可执行程序放在/system/bin/cameraserver
,开机时通过init.rc 文件自启动。
@ frameworks/av/camera/cameraserver/cameraserver.rc
service cameraserver /system/bin/cameraserver
class main
user cameraserver
group audio camera input drmrpc
ioprio rt 4
writepid /dev/cpuset/camera-daemon/tasks /dev/stune/foreground/tasks
12345678
cameraserver 可执行程序代码如下:
@ frameworks/av/camera/cameraserver/main_cameraserver.cpp
#define LOG_TAG “cameraserver”
//#define LOG_NDEBUG 0
#include “CameraService.h”
using namespace android;
int main(int argc __unused, charargv __unused)
{
signal(SIGPIPE, SIG_IGN);
sp<span class="token operator"><</span>ProcessState<span class="token operator">></span> <span class="token function">proc</span><span class="token punctuation">(</span>ProcessState<span class="token punctuation">:</span><span class="token punctuation">:</span><span class="token function">self</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>sp<span class="token operator"><</span>IServiceManager<span class="token operator">></span> sm <span class="token operator">=</span> <span class="token function">defaultServiceManager</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token function">ALOGI</span><span class="token punctuation">(</span><span class="token string">"ServiceManager: %p"</span><span class="token punctuation">,</span> sm<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>CameraService<span class="token punctuation">:</span><span class="token punctuation">:</span><span class="token function">instantiate</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>ProcessState<span class="token punctuation">:</span><span class="token punctuation">:</span><span class="token function">self</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">startThreadPool</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>IPCThreadState<span class="token punctuation">:</span><span class="token punctuation">:</span><span class="token function">self</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">disableBackgroundScheduling</span><span class="token punctuation">(</span>true<span class="token punctuation">)</span><span class="token punctuation">;</span>IPCThreadState<span class="token punctuation">:</span><span class="token punctuation">:</span><span class="token function">self</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">joinThreadPool</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
}
12345678910111213141516171819
2.2 CameraService::instantiate()
@ frameworks/native/include/binder/BinderService.h
public:
static status_t publish(bool allowIsolated = false) {
sp<IServiceManager> sm(defaultServiceManager());
return sm->addService( String16(SERVICE::getServiceName()), new SERVICE(), allowIsolated);
}
static void instantiate() {publish(); }
12345678
这段代码的意思是,向ServiceManager
添加 name 为"media.camera"
的service 。
String16(SERVICE::getServiceName())=============>// Implementation of BinderService<T>static char const* getServiceName() {return "media.camera"; }
new SERVICE()
=>
相当于调用 new CameraService()
12345678
2.3 CameraService.cpp
由于是还 强指针的引用类型,代码new CameraService()
,
在调用CameraService::CameraService()
同时还会调用void CameraService::onFirstRef()
2.4 CameraService::CameraService()
主要工作如下:
定义全局 CameraService 指针对象 gCameraService初始化变量mNumberOfCameras = 0
、mNumberOfNormalCameras = 0
、mModule = NULL
将当前对象保存在 全局 CameraService 指针 gCameraService 中
@ frameworks/av/services/camera/libcameraservice/CameraService.cpp
static CameraService *gCameraService; // 1. 定义全局 CameraService 指针对象
CameraService::CameraService() :
mEventLog(DEFAULT_EVENT_LOG_LENGTH),
mNumberOfCameras(0), mNumberOfNormalCameras(0),
mSoundRef(0), mModule(nullptr) {
ALOGI(“CameraService started (pid=%d)”, getpid());
gCameraService = this; // 2. 将当前对象保存在 全局 CameraService 指针中
this<span class="token operator">-></span>camera_device_status_change <span class="token operator">=</span> android<span class="token punctuation">:</span><span class="token punctuation">:</span>camera_device_status_change<span class="token punctuation">;</span>this<span class="token operator">-></span>torch_mode_status_change <span class="token operator">=</span> android<span class="token punctuation">:</span><span class="token punctuation">:</span>torch_mode_status_change<span class="token punctuation">;</span>mServiceLockWrapper <span class="token operator">=</span> std<span class="token punctuation">:</span><span class="token punctuation">:</span>make_shared<span class="token operator"><</span>WaitableMutexWrapper<span class="token operator">></span><span class="token punctuation">(</span><span class="token operator">&</span>mServiceLock<span class="token punctuation">)</span><span class="token punctuation">;</span>
}
12345678910111213141516
2.5 CameraService::onFirstRef()
主要工作如下:
加载 hal 层 camera module,保存在rawModule
中 ,module定义在hardware/libhardware/include/hardware/camera_common.h
初始化CameraModule
对像,将camera_module_t *rawModule
保存在mModule
中调用 Camera HAL module 的init
方法,调用mModule->get_number_of_cameras()
,用来设置mCameraInfoMap
vector 的容量打印hardware camera module
的 name ,hal 层代码定义在hardware/qcom/camera/QCamera2/QCamera2Hal.cpp
获取 camera 个数,保存在CameraService
的私有变量mNumberOfCameras
及mNumberOfNormalCameras
中初始化CameraFlashlight
模块,根据 camera number 初始化mHasFlashlightMap
vector 数组变量调用mModule->getCameraInfo()返回hal 层mHalDescriptors 的信息,保存在 info 中通过 BpCameraServiceProxy 远程调用 BnCameraService 的 pingForUserUpdate() 函数
@ frameworks/av/services/camera/libcameraservice/CameraService.cppvoid CameraService::onFirstRef(){ALOGI("CameraService process starting");BnCameraService::onFirstRef();
<span class="token comment">// 1. 加载 hal 层 camera module,保存在 rawModule 中</span><span class="token comment">// #define CAMERA_HARDWARE_MODULE_ID "camera"</span><span class="token comment">// module定义在 hardware/libhardware/include/hardware/camera_common.h </span>camera_module_t <span class="token operator">*</span>rawModule<span class="token punctuation">;</span> <span class="token keyword">int</span> err <span class="token operator">=</span> <span class="token function">hw_get_module</span><span class="token punctuation">(</span>CAMERA_HARDWARE_MODULE_ID<span class="token punctuation">,</span><span class="token punctuation">(</span><span class="token keyword">const</span> hw_module_t <span class="token operator">*</span><span class="token operator">*</span><span class="token punctuation">)</span><span class="token operator">&</span>rawModule<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">// 2. 初始化 CameraModule 对像,将 camera_module_t *rawModule 保存在 mModule 中</span>mModule <span class="token operator">=</span> new <span class="token function">CameraModule</span><span class="token punctuation">(</span>rawModule<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">// 3. 调用 Camera HAL module 的 init 方法</span><span class="token comment">// 从 hardware/libhardware/include/hardware/camera_common.h 中得知 </span><span class="token comment">// #define CAMERA_MODULE_API_VERSION_CURRENT CAMERA_MODULE_API_VERSION_2_4</span><span class="token comment">// 因此,hal 层代码位于 hardware/qcom/camera/QCamera2/QCamera2Hal.cpp</span>err <span class="token operator">=</span> mModule<span class="token operator">-></span><span class="token function">init</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">></span><span class="token operator">+</span>@ frameworks<span class="token operator">/</span>frameworks<span class="token operator">-</span>new<span class="token operator">/</span>av<span class="token operator">/</span>services<span class="token operator">/</span>camera<span class="token operator">/</span>libcameraservice<span class="token operator">/</span>common<span class="token operator">/</span>CameraModule<span class="token punctuation">.</span>cpp<span class="token operator">+</span><span class="token keyword">int</span> CameraModule<span class="token punctuation">:</span><span class="token punctuation">:</span><span class="token function">init</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token operator">+</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">getModuleApiVersion</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">>=</span> CAMERA_MODULE_API_VERSION_2_4 <span class="token operator">&&</span> mModule<span class="token operator">-></span>init <span class="token operator">!=</span> <span class="token constant">NULL</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token operator">+</span> <span class="token function">ATRACE_BEGIN</span><span class="token punctuation">(</span><span class="token string">"camera_module->init"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token operator">+</span> res <span class="token operator">=</span> mModule<span class="token operator">-></span><span class="token function">init</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 从 QCamera2Hal.cpp 中得知,init = NULL</span><span class="token operator">+</span> <span class="token punctuation">}</span><span class="token operator">+</span> mCameraInfoMap<span class="token punctuation">.</span><span class="token function">setCapacity</span><span class="token punctuation">(</span><span class="token function">getNumberOfCameras</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">// 设置CameraInfoMap vector的大小</span><span class="token operator">+</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">></span><span class="token operator">+</span>numCameras <span class="token operator">=</span> mModule<span class="token operator">-></span><span class="token function">get_number_of_cameras</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token operator">+</span> <span class="token keyword">return</span> res<span class="token punctuation">;</span><span class="token operator">+</span><span class="token punctuation">}</span><span class="token operator"><=</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">=</span><span class="token comment">// 4. 打印 hardware camera module 的name ,定义在 hardware/qcom/camera/QCamera2/QCamera2Hal.cpp</span><span class="token function">ALOGI</span><span class="token punctuation">(</span><span class="token string">"Loaded \"%s\" camera module"</span><span class="token punctuation">,</span> mModule<span class="token operator">-></span><span class="token function">getModuleName</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// "QCamera Module"</span><span class="token comment">// 5. 获取 camera 个数,保存在CameraService 的私有变量 mNumberOfCameras 及 mNumberOfNormalCameras 中</span>mNumberOfCameras <span class="token operator">=</span> mModule<span class="token operator">-></span><span class="token function">getNumberOfCameras</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>mNumberOfNormalCameras <span class="token operator">=</span> mNumberOfCameras<span class="token punctuation">;</span><span class="token comment">// 6. 初始化 CameraFlashlight 模块,根据 camera number 初始化 mHasFlashlightMap vector 数组变量</span>mFlashlight <span class="token operator">=</span> new <span class="token function">CameraFlashlight</span><span class="token punctuation">(</span><span class="token operator">*</span>mModule<span class="token punctuation">,</span> <span class="token operator">*</span>this<span class="token punctuation">)</span><span class="token punctuation">;</span>status_t res <span class="token operator">=</span> mFlashlight<span class="token operator">-></span><span class="token function">findFlashUnits</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">// 7. 调用mModule->getCameraInfo()</span><span class="token keyword">int</span> latestStrangeCameraId <span class="token operator">=</span> INT_MAX<span class="token punctuation">;</span><span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">int</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator"><</span> mNumberOfCameras<span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>String8 cameraId <span class="token operator">=</span> String8<span class="token punctuation">:</span><span class="token punctuation">:</span><span class="token function">format</span><span class="token punctuation">(</span><span class="token string">"%d"</span><span class="token punctuation">,</span> i<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">// Get camera info</span><span class="token keyword">struct</span> camera_info info<span class="token punctuation">;</span>bool haveInfo <span class="token operator">=</span> true<span class="token punctuation">;</span>status_t rc <span class="token operator">=</span> mModule<span class="token operator">-></span><span class="token function">getCameraInfo</span><span class="token punctuation">(</span>i<span class="token punctuation">,</span> <span class="token operator">&</span>info<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 8. 返回 hardware 层 mHalDescriptors 的信息,保存在 info 中</span><span class="token comment">// Defaults to use for cost and conflicting devices</span><span class="token keyword">int</span> cost <span class="token operator">=</span> <span class="token number">100</span><span class="token punctuation">;</span><span class="token keyword">char</span><span class="token operator">*</span><span class="token operator">*</span> conflicting_devices <span class="token operator">=</span> nullptr<span class="token punctuation">;</span>size_t conflicting_devices_length <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span><span class="token comment">// If using post-2.4 module version, query the cost + conflicting devices from the HAL</span><span class="token keyword">if</span> <span class="token punctuation">(</span>mModule<span class="token operator">-></span><span class="token function">getModuleApiVersion</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">>=</span> CAMERA_MODULE_API_VERSION_2_4 <span class="token operator">&&</span> haveInfo<span class="token punctuation">)</span> <span class="token punctuation">{</span>cost <span class="token operator">=</span> info<span class="token punctuation">.</span>resource_cost<span class="token punctuation">;</span>conflicting_devices <span class="token operator">=</span> info<span class="token punctuation">.</span>conflicting_devices<span class="token punctuation">;</span>conflicting_devices_length <span class="token operator">=</span> info<span class="token punctuation">.</span>conflicting_devices_length<span class="token punctuation">;</span><span class="token punctuation">}</span>std<span class="token punctuation">:</span><span class="token punctuation">:</span>set<span class="token operator"><</span>String8<span class="token operator">></span> conflicting<span class="token punctuation">;</span><span class="token keyword">for</span> <span class="token punctuation">(</span>size_t i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator"><</span> conflicting_devices_length<span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>conflicting<span class="token punctuation">.</span><span class="token function">emplace</span><span class="token punctuation">(</span><span class="token function">String8</span><span class="token punctuation">(</span>conflicting_devices<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">}</span><span class="token comment">// Initialize state for each camera device</span><span class="token punctuation">{</span>Mutex<span class="token punctuation">:</span><span class="token punctuation">:</span>Autolock <span class="token function">lock</span><span class="token punctuation">(</span>mCameraStatesLock<span class="token punctuation">)</span><span class="token punctuation">;</span>mCameraStates<span class="token punctuation">.</span><span class="token function">emplace</span><span class="token punctuation">(</span>cameraId<span class="token punctuation">,</span> std<span class="token punctuation">:</span><span class="token punctuation">:</span>make_shared<span class="token operator"><</span>CameraState<span class="token operator">></span><span class="token punctuation">(</span>cameraId<span class="token punctuation">,</span> cost<span class="token punctuation">,</span> conflicting<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">}</span><span class="token keyword">if</span> <span class="token punctuation">(</span>mFlashlight<span class="token operator">-></span><span class="token function">hasFlashUnit</span><span class="token punctuation">(</span>cameraId<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>mTorchStatusMap<span class="token punctuation">.</span><span class="token function">add</span><span class="token punctuation">(</span>cameraId<span class="token punctuation">,</span> ICameraServiceListener<span class="token punctuation">:</span><span class="token punctuation">:</span>TORCH_STATUS_AVAILABLE_OFF<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token keyword">if</span> <span class="token punctuation">(</span>mModule<span class="token operator">-></span><span class="token function">getModuleApiVersion</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">>=</span> CAMERA_MODULE_API_VERSION_2_1<span class="token punctuation">)</span> <span class="token punctuation">{</span>mModule<span class="token operator">-></span><span class="token function">setCallbacks</span><span class="token punctuation">(</span>this<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">}</span><span class="token comment">// 9. 通过 BpCameraServiceProxy 远程调用 BnCameraService 的 pingForUserUpdate() 函数</span><span class="token comment">// 远程函数位于 IMPLEMENT_META_INTERFACE(CameraServiceProxy, "android.hardware.ICameraServiceProxy");</span>CameraService<span class="token punctuation">:</span><span class="token punctuation">:</span><span class="token function">pingCameraServiceProxy</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
}
123456789101112131415161718192223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
2.6 获取Camera数量 mModule->getNumberOfCameras()
进入hardware 层代码中:
@ hardware/qcom/camera/QCamera2/QCamera2Hal.cpp
camera_module_t HAL_MODULE_INFO_SYM = {
.common = camera_common,
.get_number_of_cameras = qcamera::QCamera2Factory::get_number_of_cameras,
.get_camera_info = qcamera::QCamera2Factory::get_camera_info,
.set_callbacks = qcamera::QCamera2Factory::set_callbacks,
.get_vendor_tag_ops = qcamera::QCamera3VendorTags::get_vendor_tag_ops,
.open_legacy = qcamera::QCamera2Factory::open_legacy,
.set_torch_mode = qcamera::QCamera2Factory::set_torch_mode,
.init = NULL,
.reserved = {0}
};
12345678910111213
首先初始化gQCamera2Factory
对像,接着判断当前camera hal 层走 HAL1 还是 HAL3,调用对应的接口。
camera 个数是直接返回的变量mNumOfCameras_expose
,
而mNumOfCameras_expose
变量是在gQCamera2Factory()
中赋值的。
接着,通过判定是否支持 双摄,来调用不同的getNumberOfCameras()
函数
@ hardware/qcom/camera/QCamera2/QCamera2Factory.cpp
int QCamera2Factory::get_number_of_cameras()
{
int numCameras = 0;
if (!gQCamera2Factory) {
gQCamera2Factory = new QCamera2Factory();
}
#ifdef QCAMERA_HAL1_SUPPORT
if(gQCameraMuxer)
numCameras = gQCameraMuxer->get_number_of_cameras();
else
#endif
numCameras = gQCamera2Factory->getNumberOfCameras();
===> return mNumOfCameras_expose;
<span class="token function">LOGH</span><span class="token punctuation">(</span><span class="token string">"num of cameras: %d"</span><span class="token punctuation">,</span> numCameras<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token keyword">return</span> numCameras<span class="token punctuation">;</span>
}
12345678910111213141516171819
接下来进入函数QCamera2Factory()
看下:
打开/dev/mediax
节点 获取camera 的个数,保存在g_cam_ctrl.num_cam
返回g_cam_ctrl.num_cam_to_expose = g_cam_ctrl.num_cam - is_secure;
,此处我们没有 secure ,所就它就是camera 个数判断当前Camera系统 是否支待 HAL3,且如果没有定义QCAMERA_HAL1_SUPPORT
,则默认支持 HAL3判断当前Camera系统是否支持双摄,如果是走HAL3 ,即未定义QCAMERA_HAL1_SUPPORT
,默认不支待双摄判断当前Camera系统中所有camera是否走的是HAL3, YUV sensor是只能走HAL1 了更新 mHalDescriptors 中每个camear id 所对应的 HAL API VERSION
QCamera2Factory::QCamera2Factory(){mHalDescriptors = NULL;mCallbacks = NULL;mNumOfCameras = get_num_of_cameras();// 1. 打开/dev/mediax 节点 获取camera 的个数,保存在g_cam_ctrl.num_cammNumOfCameras_expose = get_num_of_cameras_to_expose(); // 2. 返回 g_cam_ctrl.num_cam_to_expose = g_cam_ctrl.num_cam - is_secure; ,此处我们没有 secure ,所就它就是camera 个数int bDualCamera = 0;char propDefault[PROPERTY_VALUE_MAX];char prop[PROPERTY_VALUE_MAX];// 3. 判断当前Camera系统 是否支待 HAL3,且如果没有定义QCAMERA_HAL1_SUPPORT ,则默认支持 HAL3property_get("persist.camera.HAL3.enabled", prop, "0");int isHAL3Enabled = atoi(prop);#ifndef QCAMERA_HAL1_SUPPORTisHAL3Enabled = 1;#endif
<span class="token comment">// 4. 判断当前Camera系统是否支持双摄,如果是走HAL3 ,即未定义QCAMERA_HAL1_SUPPORT ,默认不支待双摄</span><span class="token comment">// Signifies whether system has to enable dual camera mode</span><span class="token function">snprintf</span><span class="token punctuation">(</span>propDefault<span class="token punctuation">,</span> PROPERTY_VALUE_MAX<span class="token punctuation">,</span> <span class="token string">"%d"</span><span class="token punctuation">,</span> <span class="token function">isDualCamAvailable</span><span class="token punctuation">(</span>isHAL3Enabled<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token function">property_get</span><span class="token punctuation">(</span><span class="token string">"persist.camera.dual.camera"</span><span class="token punctuation">,</span> prop<span class="token punctuation">,</span> <span class="token string">"0"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>bDualCamera <span class="token operator">=</span> <span class="token function">atoi</span><span class="token punctuation">(</span>prop<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token function">LOGH</span><span class="token punctuation">(</span><span class="token string">"dualCamera:%d "</span><span class="token punctuation">,</span> bDualCamera<span class="token punctuation">)</span><span class="token punctuation">;</span>
#ifndef QCAMERA_HAL1_SUPPORT
bDualCamera = 0;
#endif
<span class="token keyword">if</span><span class="token punctuation">(</span>bDualCamera<span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token function">LOGI</span><span class="token punctuation">(</span><span class="token string">"Enabling QCamera Muxer"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
#ifdef QCAMERA_HAL1_SUPPORT
if (!gQCameraMuxer) {
QCameraMuxer::getCameraMuxer(&gQCameraMuxer, mNumOfCameras);
if (!gQCameraMuxer) {
LOGE(“Error !! Failed to get QCameraMuxer”);
}
}
#endif
}
#ifdef QCAMERA_HAL1_SUPPORT
if (!gQCameraMuxer && (mNumOfCameras > 0) &&(mNumOfCameras <= MM_CAMERA_MAX_NUM_SENSORS)) {
#else
if ((mNumOfCameras > 0) &&(mNumOfCameras <= MM_CAMERA_MAX_NUM_SENSORS)) {
#endif
mHalDescriptors = new hal_desc[mNumOfCameras];
if ( NULL != mHalDescriptors) {
uint32_t cameraId = 0;
<span class="token comment">// 5. 判断当前Camera系统中所有camera是否走的是HAL3, YUV sensor是只能走HAL1 了</span><span class="token comment">// 6. 更新 mHalDescriptors 中每个camear id 所对应的 HAL API VERSION</span><span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">int</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator"><</span> mNumOfCameras <span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">,</span> cameraId<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>mHalDescriptors<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">.</span>cameraId <span class="token operator">=</span> cameraId<span class="token punctuation">;</span><span class="token comment">// Set Device version to 3.x when both HAL3 is enabled & its BAYER sensor</span><span class="token keyword">if</span> <span class="token punctuation">(</span>isHAL3Enabled <span class="token operator">&&</span> <span class="token operator">!</span><span class="token punctuation">(</span><span class="token function">is_yuv_sensor</span><span class="token punctuation">(</span>cameraId<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>mHalDescriptors<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">.</span>device_version <span class="token operator">=</span> CAMERA_DEVICE_API_VERSION_3_0<span class="token punctuation">;</span><span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>mHalDescriptors<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">.</span>device_version <span class="token operator">=</span> CAMERA_DEVICE_API_VERSION_1_0<span class="token punctuation">;</span><span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token punctuation">}</span>
}
12345678910111213141516171819222324252627282930313233343536373839404142434445464748495051525354555657585960
2.7 hardware层调用 get_num_of_cameras()
打开/dev/media0 -->(msm_config)msm_sensor_init
/dev/media1 ---->(msm_camera)v4l2
调用MEDIA_IOC_DEVICE_INFO
获取设备信息如果判断不是msm_config
则直接continue
寻找entity.id = 2
的所有subdev
,且type=MEDIA_ENT_T_V4L2_SUBDEV , group_id=14 , name = "msm_sensor_init"
找开/dev/media0 /dev/media1 ...
,开始查找camear 个数,保存在g_cam_ctrl.num_cam
中如果判断不是msm_config
则直接continue
遍历 V4L2 下camear 的个数获取所有信息,保存在g_cam_ctrl
中hardware/qcom/camera/QCamera2/stack/mm-camera-interface/src/mm_camera_interface.c
uint8_t get_num_of_cameras()
{
struct media_device_info mdev_info;
int num_media_devices = 0;
int8_t num_cameras = 0;
char subdev_name[32];
char prop[PROPERTY_VALUE_MAX];
LOGD(“E”);
memset <span class="token punctuation">(</span><span class="token operator">&</span>g_cam_ctrl<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> <span class="token keyword">sizeof</span> <span class="token punctuation">(</span>g_cam_ctrl<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token keyword">while</span> <span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>uint32_t num_entities <span class="token operator">=</span> <span class="token number">1U</span><span class="token punctuation">;</span><span class="token keyword">char</span> dev_name<span class="token punctuation">[</span><span class="token number">32</span><span class="token punctuation">]</span><span class="token punctuation">;</span><span class="token comment">// 1. 打开 /dev/media0 -->(msm_config)msm_sensor_init/dev/media1 ---->(msm_camera)v4l2</span><span class="token function">snprintf</span><span class="token punctuation">(</span>dev_name<span class="token punctuation">,</span> <span class="token keyword">sizeof</span><span class="token punctuation">(</span>dev_name<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string">"/dev/media%d"</span><span class="token punctuation">,</span> num_media_devices<span class="token punctuation">)</span><span class="token punctuation">;</span>dev_fd <span class="token operator">=</span> <span class="token function">open</span><span class="token punctuation">(</span>dev_name<span class="token punctuation">,</span> O_RDWR <span class="token operator">|</span> O_NONBLOCK<span class="token punctuation">)</span><span class="token punctuation">;</span>num_media_devices<span class="token operator">++</span><span class="token punctuation">;</span><span class="token comment">// 2. 调用 MEDIA_IOC_DEVICE_INFO 获取设备信息</span>rc <span class="token operator">=</span> <span class="token function">ioctl</span><span class="token punctuation">(</span>dev_fd<span class="token punctuation">,</span> MEDIA_IOC_DEVICE_INFO<span class="token punctuation">,</span> <span class="token operator">&</span>mdev_info<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">=</span><span class="token operator">></span><span class="token operator">+</span><span class="token comment">// kernel/msm-4.4/drivers/media/media-device.c</span><span class="token operator">+</span><span class="token keyword">static</span> <span class="token keyword">long</span> <span class="token function">media_device_ioctl</span><span class="token punctuation">(</span><span class="token keyword">struct</span> file <span class="token operator">*</span>filp<span class="token punctuation">,</span> <span class="token keyword">unsigned</span> <span class="token keyword">int</span> cmd<span class="token punctuation">,</span> <span class="token keyword">unsigned</span> <span class="token keyword">long</span> arg<span class="token punctuation">)</span><span class="token punctuation">{</span><span class="token operator">+</span><span class="token keyword">switch</span> <span class="token punctuation">(</span>cmd<span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token operator">+</span><span class="token keyword">case</span> MEDIA_IOC_DEVICE_INFO<span class="token punctuation">:</span><span class="token operator">+</span>ret <span class="token operator">=</span> <span class="token function">media_device_get_info</span><span class="token punctuation">(</span>dev<span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token keyword">struct</span> media_device_info __user <span class="token operator">*</span><span class="token punctuation">)</span>arg<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token operator">+</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">></span><span class="token operator">+</span><span class="token operator">-</span><span class="token function">strlcpy</span><span class="token punctuation">(</span>info<span class="token punctuation">.</span>driver<span class="token punctuation">,</span> dev<span class="token operator">-></span>dev<span class="token operator">-></span>driver<span class="token operator">-></span>name<span class="token punctuation">,</span> <span class="token keyword">sizeof</span><span class="token punctuation">(</span>info<span class="token punctuation">.</span>driver<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token operator">+</span><span class="token operator">-</span><span class="token function">strlcpy</span><span class="token punctuation">(</span>info<span class="token punctuation">.</span>model<span class="token punctuation">,</span> dev<span class="token operator">-></span>model<span class="token punctuation">,</span> <span class="token keyword">sizeof</span><span class="token punctuation">(</span>info<span class="token punctuation">.</span>model<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token operator">+</span><span class="token operator">-</span><span class="token function">strlcpy</span><span class="token punctuation">(</span>info<span class="token punctuation">.</span>serial<span class="token punctuation">,</span> dev<span class="token operator">-></span>serial<span class="token punctuation">,</span> <span class="token keyword">sizeof</span><span class="token punctuation">(</span>info<span class="token punctuation">.</span>serial<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token operator">+</span><span class="token operator">-</span><span class="token function">strlcpy</span><span class="token punctuation">(</span>info<span class="token punctuation">.</span>bus_info<span class="token punctuation">,</span> dev<span class="token operator">-></span>bus_info<span class="token punctuation">,</span> <span class="token keyword">sizeof</span><span class="token punctuation">(</span>info<span class="token punctuation">.</span>bus_info<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token operator">+</span><span class="token operator">-</span><span class="token operator">+</span><span class="token operator">-</span>info<span class="token punctuation">.</span>media_version <span class="token operator">=</span> MEDIA_API_VERSION<span class="token punctuation">;</span><span class="token operator">+</span><span class="token operator">-</span>info<span class="token punctuation">.</span>hw_revision <span class="token operator">=</span> dev<span class="token operator">-></span>hw_revision<span class="token punctuation">;</span><span class="token operator">+</span><span class="token operator">-</span>info<span class="token punctuation">.</span>driver_version <span class="token operator">=</span> dev<span class="token operator">-></span>driver_version<span class="token punctuation">;</span><span class="token operator">+</span><span class="token operator">-</span><span class="token function">copy_to_user</span><span class="token punctuation">(</span>__info<span class="token punctuation">,</span> <span class="token operator">&</span>info<span class="token punctuation">,</span> <span class="token keyword">sizeof</span><span class="token punctuation">(</span><span class="token operator">*</span>__info<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token operator">+</span><span class="token operator"><=</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">=</span><span class="token operator">+</span><span class="token keyword">break</span><span class="token punctuation">;</span><span class="token operator">+</span><span class="token operator">+</span><span class="token keyword">case</span> MEDIA_IOC_ENUM_ENTITIES<span class="token punctuation">:</span><span class="token operator">+</span>ret <span class="token operator">=</span> <span class="token function">media_device_enum_entities</span><span class="token punctuation">(</span>dev<span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token keyword">struct</span> media_entity_desc __user <span class="token operator">*</span><span class="token punctuation">)</span>arg<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token operator">+</span><span class="token keyword">break</span><span class="token punctuation">;</span><span class="token operator">+</span><span class="token punctuation">}</span><span class="token operator"><=</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token comment">// 3. 如果判断不是 msm_config 则直接continue </span><span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">strncmp</span><span class="token punctuation">(</span>mdev_info<span class="token punctuation">.</span>model<span class="token punctuation">,</span> MSM_CONFIGURATION_NAME<span class="token punctuation">,</span> <span class="token keyword">sizeof</span><span class="token punctuation">(</span>mdev_info<span class="token punctuation">.</span>model<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator">!=</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token function">close</span><span class="token punctuation">(</span>dev_fd<span class="token punctuation">)</span><span class="token punctuation">;</span>dev_fd <span class="token operator">=</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">;</span><span class="token keyword">continue</span><span class="token punctuation">;</span><span class="token punctuation">}</span><span class="token keyword">while</span> <span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token keyword">struct</span> media_entity_desc entity<span class="token punctuation">;</span><span class="token function">memset</span><span class="token punctuation">(</span><span class="token operator">&</span>entity<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> <span class="token keyword">sizeof</span><span class="token punctuation">(</span>entity<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>entity<span class="token punctuation">.</span>id <span class="token operator">=</span> num_entities<span class="token operator">++</span><span class="token punctuation">;</span><span class="token comment">// 2</span><span class="token function">LOGD</span><span class="token punctuation">(</span><span class="token string">"entity id %d"</span><span class="token punctuation">,</span> entity<span class="token punctuation">.</span>id<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">// 4. 寻找 entity.id = 2 的所有subdev ,且 type=MEDIA_ENT_T_V4L2_SUBDEV , group_id=14 , name = "msm_sensor_init"</span>rc <span class="token operator">=</span> <span class="token function">ioctl</span><span class="token punctuation">(</span>dev_fd<span class="token punctuation">,</span> MEDIA_IOC_ENUM_ENTITIES<span class="token punctuation">,</span> <span class="token operator">&</span>entity<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">=</span><span class="token operator">></span><span class="token operator">+</span> <span class="token function">media_device_enum_entities</span><span class="token punctuation">(</span>dev<span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token keyword">struct</span> media_entity_desc __user <span class="token operator">*</span><span class="token punctuation">)</span>arg<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token operator">+</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">-></span><span class="token operator">+</span>pvdev<span class="token operator">-></span>vdev<span class="token operator">-></span>entity<span class="token punctuation">.</span>type <span class="token operator">=</span> MEDIA_ENT_T_DEVNODE_V4L<span class="token punctuation">;</span> <span class="token comment">// V4L</span><span class="token operator">+</span>pvdev<span class="token operator">-></span>vdev<span class="token operator">-></span>entity<span class="token punctuation">.</span>group_id <span class="token operator">=</span> QCAMERA_VNODE_GROUP_ID<span class="token punctuation">;</span> <span class="token comment">// #define QCAMERA_VNODE_GROUP_ID 2</span><span class="token operator">+</span><span class="token operator"><</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">-</span><span class="token operator"><=</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token function">LOGD</span><span class="token punctuation">(</span><span class="token string">"entity name %s type %d group id %d"</span><span class="token punctuation">,</span> entity<span class="token punctuation">.</span>name<span class="token punctuation">,</span> entity<span class="token punctuation">.</span>type<span class="token punctuation">,</span> entity<span class="token punctuation">.</span>group_id<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token keyword">if</span> <span class="token punctuation">(</span>entity<span class="token punctuation">.</span>type <span class="token operator">==</span> MEDIA_ENT_T_V4L2_SUBDEV <span class="token operator">&&</span> entity<span class="token punctuation">.</span>group_id <span class="token operator">==</span> MSM_CAMERA_SUBDEV_SENSOR_INIT<span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token function">snprintf</span><span class="token punctuation">(</span>subdev_name<span class="token punctuation">,</span> <span class="token keyword">sizeof</span><span class="token punctuation">(</span>dev_name<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string">"/dev/%s"</span><span class="token punctuation">,</span> entity<span class="token punctuation">.</span>name<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token keyword">break</span><span class="token punctuation">;</span><span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token function">close</span><span class="token punctuation">(</span>dev_fd<span class="token punctuation">)</span><span class="token punctuation">;</span>dev_fd <span class="token operator">=</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">;</span><span class="token punctuation">}</span>num_media_devices <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span><span class="token keyword">while</span> <span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>uint32_t num_entities <span class="token operator">=</span> <span class="token number">1U</span><span class="token punctuation">;</span><span class="token keyword">char</span> dev_name<span class="token punctuation">[</span><span class="token number">32</span><span class="token punctuation">]</span><span class="token punctuation">;</span><span class="token comment">// 5. 找开 /dev/media0 /dev/media1 ... ,开始查找camear 个数</span><span class="token function">snprintf</span><span class="token punctuation">(</span>dev_name<span class="token punctuation">,</span> <span class="token keyword">sizeof</span><span class="token punctuation">(</span>dev_name<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string">"/dev/media%d"</span><span class="token punctuation">,</span> num_media_devices<span class="token punctuation">)</span><span class="token punctuation">;</span>dev_fd <span class="token operator">=</span> <span class="token function">open</span><span class="token punctuation">(</span>dev_name<span class="token punctuation">,</span> O_RDWR <span class="token operator">|</span> O_NONBLOCK<span class="token punctuation">)</span><span class="token punctuation">;</span>num_media_devices<span class="token operator">++</span><span class="token punctuation">;</span><span class="token function">memset</span><span class="token punctuation">(</span><span class="token operator">&</span>mdev_info<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> <span class="token keyword">sizeof</span><span class="token punctuation">(</span>mdev_info<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>rc <span class="token operator">=</span> <span class="token function">ioctl</span><span class="token punctuation">(</span>dev_fd<span class="token punctuation">,</span> MEDIA_IOC_DEVICE_INFO<span class="token punctuation">,</span> <span class="token operator">&</span>mdev_info<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">// 6. 如果判断不是 `msm_camera` 则直接`continue` </span><span class="token keyword">if</span><span class="token punctuation">(</span><span class="token function">strncmp</span><span class="token punctuation">(</span>mdev_info<span class="token punctuation">.</span>model<span class="token punctuation">,</span> MSM_CAMERA_NAME<span class="token punctuation">,</span> <span class="token keyword">sizeof</span><span class="token punctuation">(</span>mdev_info<span class="token punctuation">.</span>model<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator">!=</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token function">close</span><span class="token punctuation">(</span>dev_fd<span class="token punctuation">)</span><span class="token punctuation">;</span>dev_fd <span class="token operator">=</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">;</span><span class="token keyword">continue</span><span class="token punctuation">;</span><span class="token punctuation">}</span><span class="token keyword">while</span> <span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token keyword">struct</span> media_entity_desc entity<span class="token punctuation">;</span><span class="token function">memset</span><span class="token punctuation">(</span><span class="token operator">&</span>entity<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> <span class="token keyword">sizeof</span><span class="token punctuation">(</span>entity<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>entity<span class="token punctuation">.</span>id <span class="token operator">=</span> num_entities<span class="token operator">++</span><span class="token punctuation">;</span>rc <span class="token operator">=</span> <span class="token function">ioctl</span><span class="token punctuation">(</span>dev_fd<span class="token punctuation">,</span> MEDIA_IOC_ENUM_ENTITIES<span class="token punctuation">,</span> <span class="token operator">&</span>entity<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">// 7. 遍历 V4L2 下camear 的个数</span><span class="token keyword">if</span><span class="token punctuation">(</span>entity<span class="token punctuation">.</span>type <span class="token operator">==</span> MEDIA_ENT_T_DEVNODE_V4L <span class="token operator">&&</span> entity<span class="token punctuation">.</span>group_id <span class="token operator">==</span> QCAMERA_VNODE_GROUP_ID<span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token function">strlcpy</span><span class="token punctuation">(</span>g_cam_ctrl<span class="token punctuation">.</span>video_dev_name<span class="token punctuation">[</span>num_cameras<span class="token punctuation">]</span><span class="token punctuation">,</span> entity<span class="token punctuation">.</span>name<span class="token punctuation">,</span> <span class="token keyword">sizeof</span><span class="token punctuation">(</span>entity<span class="token punctuation">.</span>name<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token function">LOGI</span><span class="token punctuation">(</span><span class="token string">"dev_info[id=%d,name='%s']\n"</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token keyword">int</span><span class="token punctuation">)</span>num_cameras<span class="token punctuation">,</span> g_cam_ctrl<span class="token punctuation">.</span>video_dev_name<span class="token punctuation">[</span>num_cameras<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>num_cameras<span class="token operator">++</span><span class="token punctuation">;</span><span class="token keyword">break</span><span class="token punctuation">;</span><span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token function">close</span><span class="token punctuation">(</span>dev_fd<span class="token punctuation">)</span><span class="token punctuation">;</span>dev_fd <span class="token operator">=</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">;</span><span class="token keyword">if</span> <span class="token punctuation">(</span>num_cameras <span class="token operator">>=</span> MM_CAMERA_MAX_NUM_SENSORS<span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token function">LOGW</span><span class="token punctuation">(</span><span class="token string">"Maximum number of camera reached %d"</span><span class="token punctuation">,</span> num_cameras<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token keyword">break</span><span class="token punctuation">;</span><span class="token punctuation">}</span><span class="token punctuation">}</span>g_cam_ctrl<span class="token punctuation">.</span>num_cam <span class="token operator">=</span> num_cameras<span class="token punctuation">;</span><span class="token comment">// 8. 获取所有信息,保存在 g_cam_ctrl 中</span><span class="token function">get_sensor_info</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">// 9. 重新整理 g_cam_ctrl 中的camear 顺序,确保 后摄inx 比前摄大</span><span class="token comment">/* Order of the camera exposed is0 - Back Main Camera1 - Front Main Camera++ - Back Aux Camera++ - Front Aux Camera++ - Back Main + Back Aux camera++ - Front Main + Front Aux camera++ - Secure Camera*/</span><span class="token function">sort_camera_info</span><span class="token punctuation">(</span>g_cam_ctrl<span class="token punctuation">.</span>num_cam<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">/* unlock the mutex */</span><span class="token function">LOGI</span><span class="token punctuation">(</span><span class="token string">"num_cameras=%d\n"</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token keyword">int</span><span class="token punctuation">)</span>g_cam_ctrl<span class="token punctuation">.</span>num_cam<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token keyword">return</span><span class="token punctuation">(</span>uint8_t<span class="token punctuation">)</span>g_cam_ctrl<span class="token punctuation">.</span>num_cam<span class="token punctuation">;</span>
}
1234567891011121314151617181922232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811911122123124125126127128129130131132133134135136137138139140141142143
2.8 Camera Init 初始化流程总结
在Init 整个过程中,主要做了如下事情:
定义全局 CameraService 指针对象 gCameraService。加载 hal 层 camera module,保存在rawModule
中 ,module定义在hardware/libhardware/include/hardware/camera_common.h
。调用Camera hardware module 的mModule->get_number_of_cameras()
,获得Camera Number。调用 MEDIA_IOC_DEVICE_INFO 获取驱动层 Camera V4L2 的所有设备信息。同时初始化 hardware 层的 mHalDescriptors 数组,更新每个Camera 使用的 camera hal1 还是 hal3。
三、hw_get_module()
在前面代码中,主要是通过hw_get_module(CAMERA_HARDWARE_MODULE_ID,(const hw_module_t **)&rawModule)
来获取到驱动层的相关接口。
接下来,我们来看下hw_get_module
具体做了什么操作:
@ hardware/libhardware/hardware.c
int hw_get_module(const charid, const struct hw_module_t *module)
{
return hw_get_module_by_class(id, NULL, module);
}
123456
由此可知,CameraService.cpp
中调用hw_get_module
,传递的参数为CAMERA_HARDWARE_MODULE_ID
和&rawModule
#define CAMERA_HARDWARE_MODULE_ID "camera"
进入hw_get_module_by_class()
分析下:
id = "camera"
、inst = NULL
、module = &rawModule
拼凑出 PATH_MAX = "camera"
@ hardware/libhardware/hardware.c
int hw_get_module_by_class(const charclass_id, const char inst, const struct hw_module_tmodule)
{
int i = 0;
char prop[PATH_MAX] = {0};
char path[PATH_MAX] = {0};
char name[PATH_MAX] = {0};
char prop_name[PATH_MAX] = {0};
<span class="token comment">// 1. 拼凑出 PATH_MAX = "camera"</span><span class="token keyword">if</span> <span class="token punctuation">(</span>inst<span class="token punctuation">)</span><span class="token function">snprintf</span><span class="token punctuation">(</span>name<span class="token punctuation">,</span> PATH_MAX<span class="token punctuation">,</span> <span class="token string">"%s.%s"</span><span class="token punctuation">,</span> class_id<span class="token punctuation">,</span> inst<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token keyword">else</span><span class="token function">strlcpy</span><span class="token punctuation">(</span>name<span class="token punctuation">,</span> class_id<span class="token punctuation">,</span> PATH_MAX<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">// 2. 拼凑出 prop_name = "ro.hardware.camera"</span><span class="token comment">/* First try a property specific to the class and possibly instance */</span><span class="token function">snprintf</span><span class="token punctuation">(</span>prop_name<span class="token punctuation">,</span> <span class="token keyword">sizeof</span><span class="token punctuation">(</span>prop_name<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string">"ro.hardware.%s"</span><span class="token punctuation">,</span> name<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">property_get</span><span class="token punctuation">(</span>prop_name<span class="token punctuation">,</span> prop<span class="token punctuation">,</span> <span class="token constant">NULL</span><span class="token punctuation">)</span> <span class="token operator">></span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">hw_module_exists</span><span class="token punctuation">(</span>path<span class="token punctuation">,</span> <span class="token keyword">sizeof</span><span class="token punctuation">(</span>path<span class="token punctuation">)</span><span class="token punctuation">,</span> name<span class="token punctuation">,</span> prop<span class="token punctuation">)</span> <span class="token operator">==</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token keyword">goto</span> found<span class="token punctuation">;</span><span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token comment">/* Loop through the configuration variants looking for a module */</span><span class="token keyword">for</span> <span class="token punctuation">(</span>i<span class="token operator">=</span><span class="token number">0</span> <span class="token punctuation">;</span> i<span class="token operator"><</span>HAL_VARIANT_KEYS_COUNT<span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">property_get</span><span class="token punctuation">(</span>variant_keys<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">,</span> prop<span class="token punctuation">,</span> <span class="token constant">NULL</span><span class="token punctuation">)</span> <span class="token operator">==</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token keyword">continue</span><span class="token punctuation">;</span><span class="token punctuation">}</span><span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">hw_module_exists</span><span class="token punctuation">(</span>path<span class="token punctuation">,</span> <span class="token keyword">sizeof</span><span class="token punctuation">(</span>path<span class="token punctuation">)</span><span class="token punctuation">,</span> name<span class="token punctuation">,</span> prop<span class="token punctuation">)</span> <span class="token operator">==</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token keyword">goto</span> found<span class="token punctuation">;</span><span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token comment">/* Nothing found, try the default */</span><span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">hw_module_exists</span><span class="token punctuation">(</span>path<span class="token punctuation">,</span> <span class="token keyword">sizeof</span><span class="token punctuation">(</span>path<span class="token punctuation">)</span><span class="token punctuation">,</span> name<span class="token punctuation">,</span> <span class="token string">"default"</span><span class="token punctuation">)</span> <span class="token operator">==</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token keyword">goto</span> found<span class="token punctuation">;</span><span class="token punctuation">}</span><span class="token keyword">return</span> <span class="token operator">-</span>ENOENT<span class="token punctuation">;</span>
found:
/* load the module, if this fails, we’re doomed, and we should not try
* to load a different variant. */
return load(class_id, path, module);
}
1234567891011121314151617181922232425262728293031323334353637383940414243
可以看出,在hardware.c 中,在如下三个目录依次查找 ”camera.sdm660.so“ ,找到 后,
接下来load 库文件
// @ hardware/libhardware/hardware.c#define HAL_LIBRARY_PATH1 "/system/lib64/hw"#define HAL_LIBRARY_PATH2 "/vendor/lib64/hw"#define HAL_LIBRARY_PATH3 "/odm/lib64/hw"
/*
Check if a HAL with given name and subname exists, if so return 0, otherwise
otherwise return negative. On success path will contain the path to the HAL.
/
static int hw_module_exists(charpath, size_t path_len, const charname, const char subname)
{
snprintf(path, path_len, “%s/%s.%s.so”, HAL_LIBRARY_PATH3, name, subname);
if (access(path, R_OK) == 0)
return 0;
snprintf(path, path_len, “%s/%s.%s.so”, HAL_LIBRARY_PATH2, name, subname);
if (access(path, R_OK) == 0)
return 0;
snprintf(path, path_len, “%s/%s.%s.so”, HAL_LIBRARY_PATH1, name, subname);
if (access(path, R_OK) == 0)
return 0;
return -ENOENT;
}
123456789101112131415161718192223242526
3.1 camera.sdm660.so
camera.sdm660.so
文件代码位于hardware/qcom/camera/QCamera2/
# Enable SDLLVM compiler option for build flavour >= N flavourPLATFORM_SDK_NPDK = 24
LOCAL_COPY_HEADERS_TO := qcom/camera
LOCAL_COPY_HEADERS := QCameraFormat.h
LOCAL_SRC_FILES :=
util/QCameraBufferMaps.cpp
util/QCameraCmdThread.cpp
util/QCameraFlash.cpp
util/QCameraPerf.cpp
util/QCameraQueue.cpp
util/QCameraCommon.cpp
util/QCameraTrace.cpp
util/camscope_packet_type.cpp
QCamera2Hal.cpp
QCamera2Factory.cpp
#HAL 3.0 source
LOCAL_SRC_FILES +=
HAL3/QCamera3HWI.cpp
HAL3/QCamera3Mem.cpp
HAL3/QCamera3Stream.cpp
HAL3/QCamera3Channel.cpp
HAL3/QCamera3VendorTags.cpp
HAL3/QCamera3PostProc.cpp
HAL3/QCamera3CropRegionMapper.cpp
HAL3/QCamera3StreamMem.cpp
LOCAL_CFLAGS := -Wall -Wextra -Werror
#HAL 1.0 source
ifeq ($(TARGET_SUPPORT_HAL1),false)
LOCAL_CFLAGS += -DQCAMERA_HAL3_SUPPORT
else
LOCAL_CFLAGS += -DQCAMERA_HAL1_SUPPORT
LOCAL_SRC_FILES +=
HAL/QCamera2HWI.cpp
HAL/QCameraMuxer.cpp
HAL/QCameraMem.cpp
HAL/QCameraStateMachine.cpp
util/QCameraDisplay.cpp
HAL/QCameraChannel.cpp
HAL/QCameraStream.cpp
HAL/QCameraPostProc.cpp
HAL/QCamera2HWICallbacks.cpp
HAL/QCameraParameters.cpp
HAL/QCameraParametersIntf.cpp
HAL/QCameraThermalAdapter.cpp
util/QCameraFOVControl.cpp
util/QCameraHALPP.cpp
util/QCameraDualFOVPP.cpp
util/QCameraExtZoomTranslator.cpp
util/QCameraPprocManager.cpp
util/QCameraBokeh.cpp
util/QCameraClearSight.cpp
endif
LOCAL_MODULE_RELATIVE_PATH := hw
LOCAL_MODULE := camera.$(TARGET_BOARD_PLATFORM)
LOCAL_MODULE_TAGS := optional
LOCAL_32_BIT_ONLY := $(BOARD_QTI_CAMERA_32BIT_ONLY)
include $(BUILD_SHARED_LIBRARY)
123456789101112131415161718192223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
参考:
《sdm660–opencamera流程详细分析》
《Android camera fw学习(二)-open camera操作过程&准备工作分析》
《高通平台Camera框架部分浅谈–Camera C/S 的init流程》
《Android6.0 camera初始化及预览流程》
</div><link href="/release/phoenix/mdeditor/markdown_views-60ecaf1f42.css" rel="stylesheet"></div>