参考链接:https://liuhongwei.blog.csdn.net/article/details/108684612
CameraService 的起点需要从 init.rc 说起。解析 init.rc 脚本是在 init.cpp 入口方法 main 中开始解析的。mediaserver 服务进程随即就会启动。
frameworks/av/media/mediaserver/mediaserver.rc
service media /system/bin/mediaserver
class main
user media
group audio camera inet net_bt net_bt_admin net_bw_acct drmrpc mediadrm
ioprio rt 4
writepid /dev/cpuset/foreground/tasks /dev/stune/foreground/tasks
经过分析可知,mediaserver 执行程序位于 main_mediaserver.cpp 中。调用 CameraService 类 instantiate() 启动了相机服务。
using namespace android;
int main(int argc __unused, char **argv __unused)
{
signal(SIGPIPE, SIG_IGN);
sp<ProcessState> proc(ProcessState::self());
sp<IServiceManager> sm(defaultServiceManager());
ALOGI("ServiceManager: %p", sm.get());
AIcu_initializeIcuOrDie();
MediaPlayerService::instantiate();
ResourceManagerService::instantiate();
registerExtensions();
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
}
再来看一下对应的 mk 文件,果然编译为 EXECUTABLE 类型。BUILD_EXECUTABLE 会生成可执行二进制文件到 /system/bin/ 下。
cc_binary {
name: "mediaserver",
srcs: ["main_mediaserver.cpp"],
shared_libs: [
"libresourcemanagerservice",
"liblog",
"libmediaplayerservice",
"libutils",
"libbinder",
"libandroidicu",
"[email protected]",
],
static_libs: [
"libregistermsext",
],
include_dirs: [
"frameworks/av/media/libmediaplayerservice",
"frameworks/av/services/mediaresourcemanager",
],
// back to 32-bit, b/126502613
compile_multilib: "32",
init_rc: ["mediaserver.rc"],
cflags: [
"-Werror",
"-Wall",
],
vintf_fragments: ["manifest_media_c2_software.xml"],
}
CameraService 类 instantiate() 实际继承自 BinderService。instantiate() 方法内部调用了 publish() 方法。这里将 CameraService 服务注册到了“总管” ServiceManager 中。对应的查询名称是通过 CameraService::getServiceName() 方法获取的,这个方法返回了 “media.camera”。我们从 Java 层查询的服务正是 Native 注册的相机服务。
// ---------------------------------------------------------------------------
namespace android {
template<typename SERVICE>
class BinderService
{
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(); }
......
};
}; // namespace android
// ---------------------------------------------------------------------------
再看 CameraService 类定义,就不难理解上面描述的内容了,BinderService 是一个模板类。这里其 SERVICE 对应的就是 CameraService。
class CameraService :
public BinderService<CameraService>,
public BnCameraService,
public IBinder::DeathRecipient,
public camera_module_callbacks_t
{
friend class BinderService<CameraService>;
public:
......
// Implementation of BinderService
static char const* getServiceName() { return "media.camera"; }
......
}
CameraService 构造函数中没干什么大事,初始化了一些成员变量。
static CameraService *gCameraService;
CameraService::CameraService() : mEventLog(DEFAULT_EVENT_LOG_LENGTH), mAllowedUsers(),
mSoundRef(0), mModule(0), mFlashlight(0) {
ALOGI("CameraService started (pid=%d)", getpid());
gCameraService = this;
this->camera_device_status_change = android::camera_device_status_change;
this->torch_mode_status_change = android::torch_mode_status_change;
mServiceLockWrapper = std::make_shared<WaitableMutexWrapper>(&mServiceLock);
}
onFirstRef() 属于其父类 RefBase,该函数在强引用 sp 新增引用计数时调用。延迟加载相机 HAL 模块。
1.加载相机 HAL 模块
2.初始化相机 HAL 模块
3.获取 camera 个数
4.查找闪光灯
5.初始化每个相机设备的状态
6.将 CameraService 注册到 CameraDeviceFactory
7.ping CameraServiceProxy
frameworks/av/services/camera/libcameraservice/CameraService.cpp
void CameraService::onFirstRef()
{
BnCameraService::onFirstRef();
// 如果服务正在重启,则更新电池寿命跟踪
BatteryNotifier& notifier(BatteryNotifier::getInstance());
notifier.noteResetCamera();
notifier.noteResetFlashlight();
// 加载相机 HAL 模块
camera_module_t *rawModule;
int err = hw_get_module(CAMERA_HARDWARE_MODULE_ID,
(const hw_module_t **)&rawModule);
if (err < 0) {
ALOGE("Could not load camera HAL module: %d (%s)", err, strerror(-err));
logServiceError("Could not load camera HAL module", err);
mNumberOfCameras = 0;
return;
}
// 初始化相机 HAL 模块
mModule = new CameraModule(rawModule);
err = mModule->init();
if (err != OK) {
ALOGE("Could not initialize camera HAL module: %d (%s)", err,
strerror(-err));
logServiceError("Could not initialize camera HAL module", err);
mNumberOfCameras = 0;
delete mModule;
mModule = nullptr;
return;
}
ALOGI("Loaded \"%s\" camera module", mModule->getModuleName());
// 获取 camera 个数
mNumberOfCameras = mModule->getNumberOfCameras();
mNumberOfNormalCameras = mNumberOfCameras;
// 在我们第一次调用 get_camera_info 之前设置供应商标签,
// 因为 HAL 可能需要在 get_camera_info 中设置静态供应商密钥
VendorTagDescriptor::clearGlobalVendorTagDescriptor();
if (mModule->getModuleApiVersion() >= CAMERA_MODULE_API_VERSION_2_2) {
setUpVendorTags();
}
mFlashlight = new CameraFlashlight(*mModule, *this);
// 查找闪光灯
status_t res = mFlashlight->findFlashUnits();
if (res) {
// impossible because we haven't open any camera devices.
ALOGE("Failed to find flash units.");
}
int latestStrangeCameraId = INT_MAX;
for (int i = 0; i < mNumberOfCameras; i++) {
String8 cameraId = String8::format("%d", i);
// 获取相机信息,填充 camera_info
struct camera_info info;
bool haveInfo = true;
status_t rc = mModule->getCameraInfo(i, &info);
if (rc != NO_ERROR) {
ALOGE("%s: Received error loading camera info for device %d, cost and"
" conflicting devices fields set to defaults for this device.",
__FUNCTION__, i);
haveInfo = false;
}
// 检查向后兼容性支持
if (haveInfo) {
if (checkCameraCapabilities(i, info, &latestStrangeCameraId) != OK) {
delete mModule;
mModule = nullptr;
return;
}
}
// Defaults to use for cost and conflicting devices
int cost = 100;
char** conflicting_devices = nullptr;
size_t conflicting_devices_length = 0;
// If using post-2.4 module version, query the cost + conflicting devices from the HAL
if (mModule->getModuleApiVersion() >= CAMERA_MODULE_API_VERSION_2_4 && haveInfo) {
cost = info.resource_cost;
conflicting_devices = info.conflicting_devices;
conflicting_devices_length = info.conflicting_devices_length;
}
std::set<String8> conflicting;
for (size_t i = 0; i < conflicting_devices_length; i++) {
conflicting.emplace(String8(conflicting_devices[i]));
}
// 初始化每个相机设备的状态
{
Mutex::Autolock lock(mCameraStatesLock);
mCameraStates.emplace(cameraId, std::make_shared<CameraState>(cameraId, cost,
conflicting));
}
if (mFlashlight->hasFlashUnit(cameraId)) {
mTorchStatusMap.add(cameraId,
ICameraServiceListener::TORCH_STATUS_AVAILABLE_OFF);
}
}
if (mModule->getModuleApiVersion() >= CAMERA_MODULE_API_VERSION_2_1) {
mModule->setCallbacks(this);
}
// 将 CameraService 注册到 CameraDeviceFactory
CameraDeviceFactory::registerService(this);
// ping CameraServiceProxy
CameraService::pingCameraServiceProxy();
}
先来了解一下 camera_module_t,注释的非常详细。
typedef struct camera_module {
/**
* 摄像头模块的常用方法。 *必须*是 camera_module 的第一个成员
*/
hw_module_t common;
/**
* 返回通过相机模块可访问的相机设备的数量。
* 摄像机设备的编号从 0 到 N-1,其中 N 是这个调用返回的值。
* open() 的相机设备名称只是转换成字符串的数字。
*/
int (*get_number_of_cameras)(void);
/**
* 返回给定相机设备的静态相机信息。
*/
int (*get_camera_info)(int camera_id, struct camera_info *info);
/**
* 提供指向 HAL 模块的回调函数指针,以通知框架异步相机模块事件。
*/
int (*set_callbacks)(const camera_module_callbacks_t *callbacks);
/**
* 获取查询供应商扩展元数据标签信息的方法。
* HAL 应该填写所有供应商标签操作方法,
* 或者如果未定义供应商标签,则保持 ops 不变。
*
* 这里使用的 vendor_tag_ops 结构定义在:
* system/media/camera/include/system/vendor_tags.h
*/
void (*get_vendor_tag_ops)(vendor_tag_ops_t* ops);
/**
* 如果此摄像机 HAL 模块支持多个设备 HAL API 版本,则打开特定的旧摄像机 HAL 设备。
* 例如,如果相机模块同时支持 CAMERA_DEVICE_API_VERSION_1_0 和 CAMERA_DEVICE_API_VERSION_3_2 设备 API,
* 则框架可以调用此函数以将相机设备作为 CAMERA_DEVICE_API_VERSION_1_0 设备打开。
*/
int (*open_legacy)(const struct hw_module_t* module, const char* id,
uint32_t halVersion, struct hw_device_t** device);
/**
* 打开或关闭与给定相机 ID 相关联的闪光灯的手电筒模式。
* 如果操作成功,则 HAL 必须通过使用新状态调用 camera_module_callbacks.torch_mode_status_change() 来通知框架闪光灯状态。
*
*/
int (*set_torch_mode)(const char* camera_id, bool enabled);
/**
* 在成功调用相机 HAL 库之后,相机服务将在调用任何其他方法之前调用此方法。
* 如果不需要初始化,则 HAL 模块可以将其保留为 NULL。
*
*/
int (*init)();
/* 留作将来使用 */
void* reserved[5];
} camera_module_t;
加载相机 HAL 模块调用了标准方法 hw_get_module(…),入参是 CAMERA_HARDWARE_MODULE_ID,代表相机 HAL 模块 ID。这样就能获取到 hw_module_t 结构,由于 hw_module_t 是 camera_module_t 第一个成员,变相的我们就得到了 camera_module_t 结构。接着是初始化相机 HAL 模块的过程。首先将 camera_module_t 作为入参封装为 CameraModule,接着调用 CameraModule 类 init() 方法进行初始化。
为什么需要 CameraModule?从这个类的注释我们得到了答案。
CameraModule 是 HAL 相机模块的包装器类。此类包装从 HAL 返回的 camera_module_t,以提供包装的 get_camera_info 实现,CameraService 会生成一些在较旧的 HAL 上以较新的 HAL 版本定义的照相机特性的键。
CameraModule 类 init() 方法最终会调用 camera_module_t 结构中的 init() 方法进行初始化。
CameraModule::CameraModule(camera_module_t *module) {
if (module == NULL) {
ALOGE("%s: camera hardware module must not be null", __FUNCTION__);
assert(0);
}
mModule = module;
}
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;
}
获取摄像头个数,实际上也是调用 CameraModule 类 getNumberOfCameras() 方法。不出意外调用 HAL camera_module_t 结构体中的 get_number_of_cameras() 方法实现。
int CameraModule::getNumberOfCameras() {
int numCameras;
ATRACE_BEGIN("camera_module->get_number_of_cameras");
numCameras = mModule->get_number_of_cameras();
ATRACE_END();
return numCameras;
}
再来看查找闪光灯的实现。主要是调用 CameraFlashlight 类 findFlashUnits() 查找闪光灯。 CameraFlashlight 类的主要作用是给相机服务提供控制闪光灯的一个接口。
获取相机个数
创建 ModuleFlashControl 对象
调用 ModuleFlashControl 类 hasFlashUnit(…) 方法检查闪光灯组件是否存在
将 Camera 对应的闪光灯组件是否存在一起添加到 HasFlashlightMap 中
CameraFlashlight::CameraFlashlight(CameraModule& cameraModule,
const camera_module_callbacks_t& callbacks) :
mCameraModule(&cameraModule),
mCallbacks(&callbacks),
mFlashlightMapInitialized(false) {
}
status_t CameraFlashlight::findFlashUnits() {
Mutex::Autolock l(mLock);
status_t res;
// 1.获取相机个数
int32_t numCameras = mCameraModule->getNumberOfCameras();
mHasFlashlightMap.clear();
mFlashlightMapInitialized = false;
for (int32_t i = 0; i < numCameras; i++) {
bool hasFlash = false;
String8 id = String8::format("%d", i);
// 2.创建 ModuleFlashControl 对象
res = createFlashlightControl(id);
if (res) {
ALOGE("%s: failed to create flash control for %s", __FUNCTION__,
id.string());
} else {
res = mFlashControl->hasFlashUnit(id, &hasFlash);
if (res == -EUSERS || res == -EBUSY) {
ALOGE("%s: failed to check if camera %s has a flash unit. Some "
"camera devices may be opened", __FUNCTION__,
id.string());
return res;
} else if (res) {
ALOGE("%s: failed to check if camera %s has a flash unit. %s"
" (%d)", __FUNCTION__, id.string(), strerror(-res),
res);
}
mFlashControl.clear();
}
// 3.添加到 HasFlashlightMap 中
mHasFlashlightMap.add(id, hasFlash);
}
mFlashlightMapInitialized = true;
return OK;
}
createFlashlightControl(…) 方法中主要创建了 ModuleFlashControl 对象。
status_t CameraFlashlight::createFlashlightControl(const String8& cameraId) {
ALOGV("%s: creating a flash light control for camera %s", __FUNCTION__,
cameraId.string());
if (mFlashControl != NULL) {
return INVALID_OPERATION;
}
status_t res = OK;
if (mCameraModule->getModuleApiVersion() >= CAMERA_MODULE_API_VERSION_2_4) {
mFlashControl = new ModuleFlashControl(*mCameraModule, *mCallbacks);
if (mFlashControl == NULL) {
ALOGV("%s: cannot create flash control for module api v2.4+",
__FUNCTION__);
return NO_MEMORY;
}
} else {
......
}
return OK;
}
获取 camera_info
从 CameraMetadata 中查找是否存在闪光灯组件
status_t ModuleFlashControl::hasFlashUnit(const String8& cameraId, bool *hasFlash) {
if (!hasFlash) {
return BAD_VALUE;
}
*hasFlash = false;
Mutex::Autolock l(mLock);
camera_info info;
status_t res = mCameraModule->getCameraInfo(atoi(cameraId.string()),
&info);
if (res != 0) {
return res;
}
CameraMetadata metadata;
metadata = info.static_camera_characteristics;
camera_metadata_entry flashAvailable =
metadata.find(ANDROID_FLASH_INFO_AVAILABLE);
if (flashAvailable.count == 1 && flashAvailable.data.u8[0] == 1) {
*hasFlash = true;
}
return OK;
}
现在是时候分析获取相机信息了,实际为填充 camera_info 结构。主要调用了 HAL camera_module_t 结构体中的 get_camera_info(…) 方法实现。
int CameraModule::getCameraInfo(int cameraId, struct camera_info *info) {
ATRACE_CALL();
Mutex::Autolock lock(mCameraInfoLock);
if (cameraId < 0) {
ALOGE("%s: Invalid camera ID %d", __FUNCTION__, cameraId);
return -EINVAL;
}
// 仅为 API2 设备覆盖 static_camera_characteristics
int apiVersion = mModule->common.module_api_version;
if (apiVersion < CAMERA_MODULE_API_VERSION_2_0) {
int ret;
ATRACE_BEGIN("camera_module->get_camera_info");
ret = mModule->get_camera_info(cameraId, info);
ATRACE_END();
return ret;
}
ssize_t index = mCameraInfoMap.indexOfKey(cameraId);
if (index == NAME_NOT_FOUND) {
// 从 raw 模块获取相机信息并缓存它
camera_info rawInfo, cameraInfo;
ATRACE_BEGIN("camera_module->get_camera_info");
int ret = mModule->get_camera_info(cameraId, &rawInfo);
ATRACE_END();
if (ret != 0) {
return ret;
}
int deviceVersion = rawInfo.device_version;
if (deviceVersion < CAMERA_DEVICE_API_VERSION_2_0) {
// static_camera_characteristics is invalid
*info = rawInfo;
return ret;
}
CameraMetadata m;
m = rawInfo.static_camera_characteristics;
deriveCameraCharacteristicsKeys(rawInfo.device_version, m);
cameraInfo = rawInfo;
cameraInfo.static_camera_characteristics = m.release();
index = mCameraInfoMap.add(cameraId, cameraInfo);
}
assert(index != NAME_NOT_FOUND);
// return the cached camera info
*info = mCameraInfoMap[index];
return OK;
}
最后来分析一下 将 CameraService 注册到 CameraDeviceFactory 和 ping CameraServiceProxy。CameraService 注册到 CameraDeviceFactory 中仅仅是做了一个赋值动作。
namespace android {
wp<CameraService> CameraDeviceFactory::sService;
......
void CameraDeviceFactory::registerService(wp<CameraService> service) {
ALOGV("%s: Registered service %p", __FUNCTION__,
service.promote().get());
sService = service;
}
}; // namespace android
最后来看 ping CameraServiceProxy 干了什么?
调用 getCameraServiceProxy() 获取 ICameraServiceProxy 代理对象
调用 ICameraServiceProxy.Stub.Proxy 类 pingForUserUpdate() 方法,实际由远端 CameraService Java 类中的成员 mCameraServiceProxy 中的 pingForUserUpdate() 方法实现
sp<ICameraServiceProxy> CameraService::getCameraServiceProxy() {
sp<IServiceManager> sm = defaultServiceManager();
sp<IBinder> binder = sm->getService(String16("media.camera.proxy"));
if (binder == nullptr) {
return nullptr;
}
sp<ICameraServiceProxy> proxyBinder = interface_cast<ICameraServiceProxy>(binder);
return proxyBinder;
}
void CameraService::pingCameraServiceProxy() {
sp<ICameraServiceProxy> proxyBinder = getCameraServiceProxy();
if (proxyBinder == nullptr) return;
proxyBinder->pingForUserUpdate();
}
pingForUserUpdate() 内部又调用了 CameraService 类 notifySwitchWithRetries(…) 方法。主要是为了完成将用户切换事件转发到在 mediaserver 进程中运行的本地相机服务。
public class CameraService extends SystemService {
......
private final ICameraServiceProxy.Stub mCameraServiceProxy = new ICameraServiceProxy.Stub() {
@Override
public void pingForUserUpdate() {
notifySwitchWithRetries(30);
}
......
};
......
private void notifySwitchWithRetries(int retries) {
synchronized(mLock) {
if (mEnabledCameraUsers == null) {
return;
}
// 将用户切换事件转发到在 mediaserver 进程中运行的本地相机服务。
if (notifyMediaserverLocked(USER_SWITCHED, mEnabledCameraUsers)) {
retries = 0;
}
}
if (retries <= 0) {
return;
}
Slog.i(TAG, "Could not notify camera service of user switch, retrying...");
// 无法通知相机服务的用户切换,30ms 后重试...
mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_SWITCH_USER, retries - 1, 0, null),
RETRY_DELAY_TIME);
}
......
}
handleMessage(…) 方法中再次调用 notifySwitchWithRetries(…) 进行了重试。
public class CameraService extends SystemService {
......
@Override
public boolean handleMessage(Message msg) {
switch(msg.what) {
case MSG_SWITCH_USER: {
notifySwitchWithRetries(msg.arg1);
} break;
default: {
Slog.e(TAG, "CameraService error, invalid message: " + msg.what);
} break;
}
return true;
}
......
}
后面继续分析 Camera HAL 中如何实现 camera_module_t 结构体中的函数指针。
QCamera2Hal.cpp 中给 hw_module_t 结构体 camera_common 进行了赋值,然后又给 camera_module_t 结构体 HAL_MODULE_INFO_SYM 赋值,HAL_MODULE_INFO_SYM 名字是固定的,这样 hw_get_module(…) 函数才能正常工作。
#include "QCamera2Factory.h"
#include "HAL3/QCamera3VendorTags.h"
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: qcamera::QCamera2Factory::open_legacy,
set_torch_mode: qcamera::QCamera2Factory::set_torch_mode,
init: NULL,
reserved: {0}
};
get_number_of_cameras 函数指针具体指向了 qcamera::QCamera2Factory::get_number_of_cameras。
如果 gQCamera2Factory 为空,则先 new 一个对象出来,然后调用其 getNumberOfCameras() 方法。
namespace qcamera {
......
int QCamera2Factory::get_number_of_cameras()
{
if (!gQCamera2Factory) {
gQCamera2Factory = new QCamera2Factory();
if (!gQCamera2Factory) {
ALOGE("%s: Failed to allocate Camera2Factory object", __func__);
return 0;
}
}
return gQCamera2Factory->getNumberOfCameras();
}
......
}
先来分析 new 一个对象做了哪些工作?
获取 camera 个数
分配 HAL 描述符表
获取每个 camera camera_info
namespace qcamera {
......
QCamera2Factory::QCamera2Factory()
{
camera_info info;
int i = 0;
mHalDescriptors = NULL;
mCallbacks = NULL;
// 获取 camera 个数
mNumOfCameras = get_num_of_cameras();
char prop[PROPERTY_VALUE_MAX];
property_get("persist.camera.HAL3.enabled", prop, "0");
int isHAL3Enabled = atoi(prop);
if ((mNumOfCameras > 0) && (mNumOfCameras <= MM_CAMERA_MAX_NUM_SENSORS)) {
// 分配 HAL 描述符表
mHalDescriptors = new hal_desc[mNumOfCameras];
if ( NULL != mHalDescriptors) {
uint32_t cameraId = 0;
for (; i < mNumOfCameras ; i++, cameraId++) {
mHalDescriptors[i].cameraId = cameraId;
if (isHAL3Enabled) {
mHalDescriptors[i].device_version = CAMERA_DEVICE_API_VERSION_3_0;
} else {
mHalDescriptors[i].device_version = CAMERA_DEVICE_API_VERSION_1_0;
}
//在此时查询 camera,以避免在随后调用 'getCameraInfo()' 时出现任何延迟
getCameraInfo(i, &info);
}
} else {
ALOGE("%s: Not enough resources to allocate HAL descriptor table!",
__func__);
}
} else {
ALOGE("%s: %d camera devices detected!", __func__, mNumOfCameras);
}
}
......
}
打开设备节点 /dev/media ~ /dev/mediaN
向 camera 驱动发送命令 MEDIA_IOC_DEVICE_INFO,获取 media_device_info
向 camera 驱动发送命令 MEDIA_IOC_ENUM_ENTITIES,获取 media_entity_desc
打开 sensor_init subdev
uint8_t get_num_of_cameras()
{
int rc = 0;
int dev_fd = 0;
struct media_device_info mdev_info;
int num_media_devices = 0;
uint8_t num_cameras = 0;
char subdev_name[32];
int32_t sd_fd = 0;
struct sensor_init_cfg_data cfg;
char prop[PROPERTY_VALUE_MAX];
property_get("persist.camera.logs", prop, "0");
gMmCameraIntfLogLevel = atoi(prop);
CDBG("%s : E", __func__);
int decrypt = property_get("vold.decrypt", prop, NULL);
if (0 < decrypt) {
if(strncmp(prop, "trigger_restart_min_framework", decrypt) == 0) {
return 0;
}
}
/* lock the mutex */
pthread_mutex_lock(&g_intf_lock);
while (1) {
int32_t num_entities = 1;
char dev_name[32];
// 打开设备节点 /dev/media ~ /dev/mediaN
snprintf(dev_name, sizeof(dev_name), "/dev/media%d", num_media_devices);
dev_fd = open(dev_name, O_RDWR | O_NONBLOCK);
if (dev_fd < 0) {
CDBG("Done discovering media devices\n");
break;
}
num_media_devices++;
// 向 camera 驱动发送命令 MEDIA_IOC_DEVICE_INFO,获取 media_device_info
rc = ioctl(dev_fd, MEDIA_IOC_DEVICE_INFO, &mdev_info);
if (rc < 0) {
CDBG_ERROR("Error: ioctl media_dev failed: %s\n", strerror(errno));
close(dev_fd);
dev_fd = -1;
break;
}
if (strncmp(mdev_info.model, MSM_CONFIGURATION_NAME,
sizeof(mdev_info.model)) != 0) {
close(dev_fd);
dev_fd = -1;
continue;
}
while (1) {
struct media_entity_desc entity;
memset(&entity, 0, sizeof(entity));
entity.id = num_entities++;
CDBG_ERROR("entity id %d", entity.id);
// 向 camera 驱动发送命令 MEDIA_IOC_ENUM_ENTITIES,获取 media_entity_desc
rc = ioctl(dev_fd, MEDIA_IOC_ENUM_ENTITIES, &entity);
if (rc < 0) {
CDBG_ERROR("Done enumerating media entities");
rc = 0;
break;
}
CDBG_ERROR("entity name %s type %d group id %d",
entity.name, entity.type, entity.group_id);
if (entity.type == MEDIA_ENT_T_V4L2_SUBDEV &&
entity.group_id == MSM_CAMERA_SUBDEV_SENSOR_INIT) {
snprintf(subdev_name, sizeof(dev_name), "/dev/%s", entity.name);
break;
}
}
close(dev_fd);
dev_fd = -1;
}
/* 打开 sensor_init subdev */
sd_fd = open(subdev_name, O_RDWR);
if (sd_fd < 0) {
CDBG_ERROR("Open sensor_init subdev failed");
return FALSE;
}
cfg.cfgtype = CFG_SINIT_PROBE_WAIT_DONE;
cfg.cfg.setting = NULL;
if (ioctl(sd_fd, VIDIOC_MSM_SENSOR_INIT_CFG, &cfg) < 0) {
CDBG_ERROR("failed");
}
close(sd_fd);
dev_fd = -1;
......
g_cam_ctrl.num_cam = num_cameras;
get_sensor_info();
/* unlock the mutex */
pthread_mutex_unlock(&g_intf_lock);
CDBG("%s: num_cameras=%d\n", __func__, g_cam_ctrl.num_cam);
return g_cam_ctrl.num_cam;
}
get_sensor_info() 中获取了 camera 的 facing(前置或后置) 和 orientation。
hardware/qcom/camera/QCamera2/stack/mm-camera-interface/src/mm_camera_interface.c
// 获取面向(后/前)和安装角度的传感器信息
void get_sensor_info()
{
......
while (1) {
......
while (1) {
struct media_entity_desc entity;
unsigned long temp;
unsigned int mount_angle;
unsigned int facing;
memset(&entity, 0, sizeof(entity));
entity.id = num_entities++;
rc = ioctl(dev_fd, MEDIA_IOC_ENUM_ENTITIES, &entity);
if (rc < 0) {
CDBG("Done enumerating media entities\n");
rc = 0;
break;
}
if(entity.type == MEDIA_ENT_T_V4L2_SUBDEV &&
entity.group_id == MSM_CAMERA_SUBDEV_SENSOR) {
temp = entity.flags >> 8;
mount_angle = (temp & 0xFF) * 90;
facing = (temp >> 8);
ALOGD("index = %d flag = %x mount_angle = %d facing = %d\n"
, num_cameras, (unsigned int)temp, (unsigned int)mount_angle,
(unsigned int)facing);
g_cam_ctrl.info[num_cameras].facing = facing;
g_cam_ctrl.info[num_cameras].orientation = mount_angle;
num_cameras++;
continue;
}
}
CDBG("%s: dev_info[id=%d,name='%s']\n",
__func__, num_cameras, g_cam_ctrl.video_dev_name[num_cameras]);
close(dev_fd);
dev_fd = -1;
}
CDBG("%s: num_cameras=%d\n", __func__, g_cam_ctrl.num_cam);
return;
}
hardware/qcom/camera/QCamera2/QCamera2Factory.cpp
QCamera2Factory 类的 getNumberOfCameras() 方法只是简单的将 QCamera2Factory 构造器中赋值的 mNumOfCameras 成员变量返回。
// 查询检测到的摄像机数量
int QCamera2Factory::getNumberOfCameras()
{
return mNumOfCameras;
}