Android Camera原理之camera provider啟動
1.camera provider程序介紹:
cameraserver 736 1 274664 69564 binder_thread_read f3de10cc S [email protected]
其中的pid是736,說明camera provider程序啟動的時機比較早,而且許可權組是 cameraserver
手機上執行的[email protected]程序是支援camera執行的重要程序。
camera架構.jpg
上面這張圖比較清楚的表現了camera provider程序在camera架構中位置,作為承上啟下的部分,和cameraserver程序和底層的驅動互動,camera provider程序非常重要,camera HAL層幾乎全部執行在camera provider程序中完成。
[email protected]在手機啟動的時候就會啟動起來,下面整體分析一下[email protected]程序的啟動過程。
2.camera provider程序啟動流程:
首先看下camera provider所在原始碼中的位置:hardware/interfaces/camera/provider/
cameraprovider程式碼目錄.jpg
可以看出來在hardware/interfaces/camera/provider/2.4/default/ 下面有幾個rc檔案,Android初始化就是執行這些rc檔案,這裡執行的是
service vendor.camera-provider-2-4 /vendor/bin/hw/[email protected] class hal user cameraserver group audio camera input drmrpc ioprio rt 4 capabilities SYS_NICE writepid /dev/cpuset/camera-daemon/tasks /dev/stune/top-app/tasks
第一行就看到了啟動一個 /vendor/bin/hw/[email protected] 程序。
下面列出camera provider程序的啟動流程,大家可以先看一下。
camera provider程序啟動流程.jpg
service.cpp : hardware/interfaces/camera/provider/2.4/default/service.cpp
CameraProvider : hardware/interfaces/camera/provider/2.4/default/CameraProvider.cpp
hardware.c : hardware/libhardware/hardware.c
CameraModule : hardware/interfaces/camera/common/1.0/default/CameraModule.cpp
QCamera2Factory : hardware/qcom/camera/QCamera2Factory.cpp
QCameraFlash : hardware/qcom/camera/QCamera2/util/QCameraFlash.cpp
QCamera3HardwareInterface : hardware/qcom/camera/QCamera2/HAL3/QCamera3HWI.cpp
這兒值得講一講的就是native中的函式指標的問題,從camera interfaces中將函式指標對映到camera hal層中。
主要從CameraModule中呼叫到QCamera2Factory中。期間使用了camera_module_t這個結構體。可以看下 CameraModule::init函式。
int CameraModule::init() {
ATRACE_CALL();
int res = OK;
if (getModuleApiVersion() >= CAMERA_MODULE_API_VERSION_2_4 &&
mModule->init != NULL) {
ATRACE_BEGIN("camera_module->init");
res = mModule->init();
ATRACE_END();
}
mCameraInfoMap.setCapacity(getNumberOfCameras());
return res;
}
這兒呼叫的mModule->init(); 這個mModule就是camera_module_t結構體物件,這時候翻看一下《Android Camera原理之camera HAL底層資料結構與類總結》
typedef struct camera_module {
hw_module_t common;
int (*get_number_of_cameras)(void);
int (*get_camera_info)(int camera_id, struct camera_info *info);
int (*set_callbacks)(const camera_module_callbacks_t *callbacks);
void (*get_vendor_tag_ops)(vendor_tag_ops_t* ops);
int (*open_legacy)(const struct hw_module_t* module, const char* id,
uint32_t halVersion, struct hw_device_t** device);
int (*set_torch_mode)(const char* camera_id, bool enabled);
int (*init)();
void* reserved[5];
} camera_module_t;
結構體中有一些函式指標,我們現在需要搞清楚這些函式指標被對映到什麼地方了?
hardware中interface中提供了原生的對映方法,在hardware/libhardware/modules/camera/3_0/CameraHAL.cpp中。
camera_module_t HAL_MODULE_INFO_SYM __attribute__ ((visibility("default"))) = {
.common = {
.tag = HARDWARE_MODULE_TAG,
.module_api_version = CAMERA_MODULE_API_VERSION_2_2,
.hal_api_version = HARDWARE_HAL_API_VERSION,
.id = CAMERA_HARDWARE_MODULE_ID,
.name = "Default Camera HAL",
.author = "The Android Open Source Project",
.methods = &gCameraModuleMethods,
.dso = NULL,
.reserved = {0},
},
.get_number_of_cameras = get_number_of_cameras,
.get_camera_info = get_camera_info,
.set_callbacks = set_callbacks,
.get_vendor_tag_ops = get_vendor_tag_ops,
.open_legacy = NULL,
.set_torch_mode = NULL,
.init = NULL,
.reserved = {0},
};
這是通用的對映,我們手機的晶片會重新這個HAL層介面,例如使用高通晶片的話,會在hardware/qcom/camera/QCamera2/QCamera2Hal.cpp中重寫這個函式對映。
實際上可能不是這個路徑,根據你本地實際的hal層重新方法來查詢這些函式對映。
static hw_module_t camera_common = {
.tag = HARDWARE_MODULE_TAG,
.module_api_version = CAMERA_MODULE_API_VERSION_2_4,
.hal_api_version = HARDWARE_HAL_API_VERSION,
.id = CAMERA_HARDWARE_MODULE_ID,
.name = "QCamera Module",
.author = "Qualcomm Innovation Center Inc",
.methods = &qcamera::QCamera2Factory::mModuleMethods,
.dso = NULL,
.reserved = {0}
};
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 = NULL,
.set_torch_mode = qcamera::QCamera2Factory::set_torch_mode,
.init = NULL,
.reserved = {0}
};
明確這些函式對映之後,接下來可以直接呼叫到hal層了。再底層就是晶片中複寫的核心方法了,暫時不作深入介紹