Framework
frameworks\base\core\java\android\hardware\Camera.java
public static Camera open(int cameraId) {
return new Camera(cameraId);
}
public static Camera open() {
int numberOfCameras = getNumberOfCameras();
CameraInfo cameraInfo = new CameraInfo();
for (int i = 0; i < numberOfCameras; i++) {
getCameraInfo(i, cameraInfo);
Log.e(TAG, "Camera open 11111 id:" + i);
if (cameraInfo.facing == CameraInfo.CAMERA_FACING_BACK) {
Log.e(TAG, "Camera open 22222 id:" + i);
return new Camera(i);
}
}
return null;
}
Camera(int cameraId) {
if (cameraId >= getNumberOfCameras()) {
throw new RuntimeException("Unknown camera ID");
}
int err = cameraInitNormal(cameraId);
if (checkInitErrors(err)) {
if (err == -EACCES) {
throw new RuntimeException("Fail to connect to camera service");
} else if (err == -ENODEV) {
throw new RuntimeException("Camera initialization failed");
}
// Should never hit this.
throw new RuntimeException("Unknown camera error");
}
}
主要的初始化在cameraInitNormal中
private int cameraInitVersion(int cameraId, int halVersion) {
......省略代码......
return native_setup(new WeakReference<Camera>(this), cameraId, halVersion, packageName);
}
private int cameraInitNormal(int cameraId) {
return cameraInitVersion(cameraId, CAMERA_HAL_API_VERSION_NORMAL_CONNECT);
}
最终调用到了native_setup的jni方法
Android Runtime
frameworks\base\core\jni\android_hardware_Camera.cpp
{ "native_setup",
"(Ljava/lang/Object;IILjava/lang/String;)I",
(void*)android_hardware_Camera_native_setup },
static jint android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz,
jobject weak_this, jint cameraId, jint halVersion, jstring clientPackageName)
{
// Convert jstring to String16
const char16_t *rawClientName = reinterpret_cast<const char16_t*>(
env->GetStringChars(clientPackageName, NULL));
jsize rawClientNameLen = env->GetStringLength(clientPackageName);
String16 clientName(rawClientName, rawClientNameLen);
env->ReleaseStringChars(clientPackageName,
reinterpret_cast<const jchar*>(rawClientName));
sp<Camera> camera;
if (halVersion == CAMERA_HAL_API_VERSION_NORMAL_CONNECT) {
// Default path: hal version is don't care, do normal camera connect.
camera = Camera::connect(cameraId, clientName,
Camera::USE_CALLING_UID, Camera::USE_CALLING_PID);
} else {
jint status = Camera::connectLegacy(cameraId, halVersion, clientName,
Camera::USE_CALLING_UID, camera);
if (status != NO_ERROR) {
return status;
}
}
......省略代码......
}
Library
android_hardware_Camera_native_setup()方法通过调用Camera::connect()方法请求连接CameraService服务
frameworks\av\camera\Camera.cpp
sp<Camera> Camera::connect(int cameraId, const String16& clientPackageName,
int clientUid, int clientPid)
{
return CameraBaseT::connect(cameraId, clientPackageName, clientUid, clientPid);
}
status_t Camera::connectLegacy(int cameraId, int halVersion,
const String16& clientPackageName,
int clientUid,
sp<Camera>& camera)
{
ALOGV("%s: connect legacy camera device", __FUNCTION__);
sp<Camera> c = new Camera(cameraId);
sp<::android::hardware::ICameraClient> cl = c;
status_t status = NO_ERROR;
const sp<::android::hardware::ICameraService>& cs = CameraBaseT::getCameraService();
binder::Status ret;
if (cs != nullptr) {
ret = cs.get()->connectLegacy(cl, cameraId, halVersion, clientPackageName,
clientUid, /*out*/&(c->mCamera));
}
......省略代码......
}
connectLegacy
我们先看下connectLegacy
sp<Camera> c = new Camera(cameraId);
sp<::android::hardware::ICameraClient> cl = c;
这里把一个Camera对象直接赋值给了一个ICameraClient对象
看下Camera的定义,在Camera.h中
class Camera :
public CameraBase<Camera>,
public ::android::hardware::BnCameraClient
可以看到继承了两个父类CameraBase和BnCameraClient
我们接着看BnCameraClient
frameworks\av\include\camera\android\hardware\ICameraClient.h
class BnCameraClient: public BnInterface<ICameraClient>
{
public:
virtual status_t onTransact( uint32_t code,
const Parcel& data,
Parcel* reply,
uint32_t flags = 0);
};
可以看到BnCameraClient继承了BnInterface
frameworks\native\include\binder\IInterface.h
template<typename INTERFACE>
class BpInterface : public INTERFACE, public BpRefBase
{
public:
BpInterface(const sp<IBinder>& remote);
protected:
virtual IBinder* onAsBinder();
};
这里可以看到定义了一个模板,也就是说
BnInterface<ICameraClient>相当于就是
BnInterface : public ICameraClient,也就是说BnInterface 继承于ICameraClient,所以,回到上面的
sp<::android::hardware::ICameraClient> cl = c;可以直接赋值
const sp<::android::hardware::ICameraService>& cs = CameraBaseT::getCameraService();这里获取了CameraBase中CameraService对象,和后面的connect中一样,后面一起说
connect
connect方法位于CameraBase中,就是Camera的父类
frameworks\av\camera\CameraBase.cpp
template <typename TCam, typename TCamTraits>
sp<TCam> CameraBase<TCam, TCamTraits>::connect(int cameraId,
const String16& clientPackageName,
int clientUid, int clientPid)
{
ALOGV("%s: connect", __FUNCTION__);
sp<TCam> c = new TCam(cameraId);
sp<TCamCallbacks> cl = c;
const sp<::android::hardware::ICameraService> cs = getCameraService();
binder::Status ret;
if (cs != nullptr) {
TCamConnectService fnConnectService = TCamTraits::fnConnectService;
ret = (cs.get()->*fnConnectService)(cl, cameraId, clientPackageName, clientUid,
clientPid, /*out*/ &c->mCamera);
}
if (ret.isOk() && c->mCamera != nullptr) {
IInterface::asBinder(c->mCamera)->linkToDeath(c);
c->mStatus = NO_ERROR;
} else {
ALOGW("An error occurred while connecting to camera %d: %s", cameraId,
(cs != nullptr) ? "Service not available" : ret.toString8().string());
c.clear();
}
return c;
}
首先我们去CameraBase.h中看看定义
frameworks\av\include\camera\CameraBase.h
template <typename TCam>
struct CameraTraits {
};
template <typename TCam, typename TCamTraits = CameraTraits<TCam> >
class CameraBase : public IBinder::DeathRecipient
{
public:
typedef typename TCamTraits::TCamListener TCamListener;
typedef typename TCamTraits::TCamUser TCamUser;
typedef typename TCamTraits::TCamCallbacks TCamCallbacks;
typedef typename TCamTraits::TCamConnectService TCamConnectService;
static sp<TCam> connect(int cameraId,
const String16& clientPackageName,
int clientUid, int clientPid);
......省略代码......
protected:
CameraBase(int cameraId);
......省略代码......
typedef CameraBase<TCam> CameraBaseT;
};
在调用的时候
sp<Camera> Camera::connect(int cameraId, const String16& clientPackageName,
int clientUid, int clientPid)
{
return CameraBaseT::connect(cameraId, clientPackageName, clientUid, clientPid);
}
那么,这里的CameraBaseT其实就是CameraBase<Camera>
ok,那么TCam就是Camera
回到上面
sp<TCam> c = new TCam(cameraId);
sp<TCamCallbacks> cl = c;
这条语句就可以转换为
sp<Camera> c = new Camera(cameraId);
sp<CameraTraits<Camera>::TCamCallbacks> cl = c;
在Camera.h中
template <>
struct CameraTraits<Camera>
{
typedef CameraListener TCamListener;
typedef ::android::hardware::ICamera TCamUser;
typedef ::android::hardware::ICameraClient TCamCallbacks;
typedef ::android::binder::Status(::android::hardware::ICameraService::*TCamConnectService)
(const sp<::android::hardware::ICameraClient>&,
int, const String16&, int, int,
/*out*/
sp<::android::hardware::ICamera>*);
static TCamConnectService fnConnectService;
};
所以上面的语句就是
sp<Camera> c = new Camera(cameraId);
sp<::android::hardware::ICameraClient > cl = c;
可以看到,和之前connectLegacy中的一模一样
现在我们来看const sp<::android::hardware::ICameraService> cs = getCameraService();
getCameraService
template <typename TCam, typename TCamTraits>
const sp<::android::hardware::ICameraService> CameraBase<TCam, TCamTraits>::getCameraService()
{
Mutex::Autolock _l(gLock);
if (gCameraService.get() == 0) {
char value[PROPERTY_VALUE_MAX];
property_get("config.disable_cameraservice", value, "0");
if (strncmp(value, "0", 2) != 0 && strncasecmp(value, "false", 6) != 0) {
return gCameraService;
}
sp<IServiceManager> sm = defaultServiceManager();
sp<IBinder> binder;
do {
binder = sm->getService(String16(kCameraServiceName));
if (binder != 0) {
break;
}
ALOGW("CameraService not published, waiting...");
usleep(kCameraServicePollDelay);
} while(true);
if (gDeathNotifier == NULL) {
gDeathNotifier = new DeathNotifier();
}
binder->linkToDeath(gDeathNotifier);
gCameraService = interface_cast<::android::hardware::ICameraService>(binder);
}
ALOGE_IF(gCameraService == 0, "no CameraService!?");
return gCameraService;
}
getCameraService最终得到的是一个BpCameraService(BpBinder(handle))实例
接着往下看
fnConnectService
TCamConnectService fnConnectService = TCamTraits::fnConnectService;
ret = (cs.get()->*fnConnectService)(cl, cameraId, clientPackageName, clientUid, clientPid, &c->mCamera);
之前我们在Camera.h中看到
typedef ::android::binder::Status(::android::hardware::ICameraService::*TCamConnectService)
(const sp<::android::hardware::ICameraClient>&,
int, const String16&, int, int,
/*out*/
sp<::android::hardware::ICamera>*); //这是类成员函数指针
static TCamConnectService fnConnectService;//变量声明 指针 fnConnectService
我们看看他的实现
CameraTraits<Camera>::TCamConnectService CameraTraits<Camera>::fnConnectService =
&::android::hardware::ICameraService::connect;
其目的是用指针fnConnectService 指向ICameraService 类下的函数connect 地址
最终调用到了CameraService.cpp中的connect
CameraService::connect
frameworks\av\services\camera\libcameraservice\CameraService.cpp
Status CameraService::connect(
const sp<ICameraClient>& cameraClient,
int cameraId,
const String16& clientPackageName,
int clientUid,
int clientPid,
/*out*/
sp<ICamera>* device) {
ALOGE("CameraService cameraId:%d",cameraId);
ATRACE_CALL();
Status ret = Status::ok();
String8 id = String8::format("%d", cameraId);
sp<Client> client = nullptr;
ret = connectHelper<ICameraClient,Client>(cameraClient, id,
CAMERA_HAL_API_VERSION_UNSPECIFIED, clientPackageName, clientUid, clientPid, API_1,
/*legacyMode*/ false, /*shimUpdateOnly*/ false,
/*out*/client);
if(!ret.isOk()) {
logRejected(id, getCallingPid(), String8(clientPackageName),
ret.toString8());
return ret;
}
*device = client;
return ret;
}
Status CameraService::connectLegacy(
const sp<ICameraClient>& cameraClient,
int cameraId, int halVersion,
const String16& clientPackageName,
int clientUid,
/*out*/
sp<ICamera>* device) {
......省略代码......
Status ret = Status::ok();
sp<Client> client = nullptr;
ret = connectHelper<ICameraClient,Client>(cameraClient, id, halVersion,
clientPackageName, clientUid, USE_CALLING_PID, API_1,
/*legacyMode*/ true, /*shimUpdateOnly*/ false,
/*out*/client);
if(!ret.isOk()) {
logRejected(id, getCallingPid(), String8(clientPackageName),
ret.toString8());
return ret;
}
*device = client;
return ret;
}
核心是调用connectHelper, connectHelper实现在CameraService.h中
template<class CALLBACK, class CLIENT>
binder::Status CameraService::connectHelper(const sp<CALLBACK>& cameraCb, const String8& cameraId,
int halVersion, const String16& clientPackageName, int clientUid, int clientPid,
apiLevel effectiveApiLevel, bool legacyMode, bool shimUpdateOnly,
/*out*/sp<CLIENT>& device) {
......省略代码......
int facing = -1;
int deviceVersion = getDeviceVersion(id, /*out*/&facing);
sp<BasicClient> tmp = nullptr;
if(!(ret = makeClient(this, cameraCb, clientPackageName, id, facing, clientPid,
clientUid, getpid(), legacyMode, halVersion, deviceVersion, effectiveApiLevel,
/*out*/&tmp)).isOk()) {
return ret;
}
client = static_cast<CLIENT*>(tmp.get());
LOG_ALWAYS_FATAL_IF(client.get() == nullptr, "%s: CameraService in invalid state",
__FUNCTION__);
if ((err = client->initialize(mModule)) != OK) {
ALOGE("%s: Could not initialize client from HAL module.", __FUNCTION__);
// Errors could be from the HAL module open call or from AppOpsManager
switch(err) {
case BAD_VALUE:
return STATUS_ERROR_FMT(ERROR_ILLEGAL_ARGUMENT,
"Illegal argument to HAL module for camera \"%s\"", cameraId.string());
case -EBUSY:
return STATUS_ERROR_FMT(ERROR_CAMERA_IN_USE,
"Camera \"%s\" is already open", cameraId.string());
case -EUSERS:
return STATUS_ERROR_FMT(ERROR_MAX_CAMERAS_IN_USE,
"Too many cameras already open, cannot open camera \"%s\"",
cameraId.string());
case PERMISSION_DENIED:
return STATUS_ERROR_FMT(ERROR_PERMISSION_DENIED,
"No permission to open camera \"%s\"", cameraId.string());
case -EACCES:
return STATUS_ERROR_FMT(ERROR_DISABLED,
"Camera \"%s\" disabled by policy", cameraId.string());
case -ENODEV:
default:
return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION,
"Failed to initialize camera \"%s\": %s (%d)", cameraId.string(),
strerror(-err), err);
}
}
......省略代码......
// Important: release the mutex here so the client can call back into the service from its
// destructor (can be at the end of the call)
device = client;
return ret;
}
关键点makeClient获取CameraClient/Camera2Client对象
Status CameraService::makeClient(const sp<CameraService>& cameraService,
const sp<IInterface>& cameraCb, const String16& packageName, int cameraId,
int facing, int clientPid, uid_t clientUid, int servicePid, bool legacyMode,
int halVersion, int deviceVersion, apiLevel effectiveApiLevel,
/*out*/sp<BasicClient>* client) {
if (halVersion < 0 || halVersion == deviceVersion) {
// Default path: HAL version is unspecified by caller, create CameraClient
// based on device version reported by the HAL.
switch(deviceVersion) {
case CAMERA_DEVICE_API_VERSION_1_0:
if (effectiveApiLevel == API_1) { // Camera1 API route
sp<ICameraClient> tmp = static_cast<ICameraClient*>(cameraCb.get());
*client = new CameraClient(cameraService, tmp, packageName, cameraId, facing,
clientPid, clientUid, getpid(), legacyMode);
} else { // Camera2 API route
ALOGW("Camera using old HAL version: %d", deviceVersion);
return STATUS_ERROR_FMT(ERROR_DEPRECATED_HAL,
"Camera device \"%d\" HAL version %d does not support camera2 API",
cameraId, deviceVersion);
}
break;
case CAMERA_DEVICE_API_VERSION_3_0:
case CAMERA_DEVICE_API_VERSION_3_1:
case CAMERA_DEVICE_API_VERSION_3_2:
case CAMERA_DEVICE_API_VERSION_3_3:
case CAMERA_DEVICE_API_VERSION_3_4:
if (effectiveApiLevel == API_1) { // Camera1 API route
sp<ICameraClient> tmp = static_cast<ICameraClient*>(cameraCb.get());
*client = new Camera2Client(cameraService, tmp, packageName, cameraId, facing,
clientPid, clientUid, servicePid, legacyMode);
} else { // Camera2 API route
sp<hardware::camera2::ICameraDeviceCallbacks> tmp =
static_cast<hardware::camera2::ICameraDeviceCallbacks*>(cameraCb.get());
*client = new CameraDeviceClient(cameraService, tmp, packageName, cameraId,
facing, clientPid, clientUid, servicePid);
}
break;
default:
// Should not be reachable
ALOGE("Unknown camera device HAL version: %d", deviceVersion);
return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION,
"Camera device \"%d\" has unknown HAL version %d",
cameraId, deviceVersion);
}
} else {
// A particular HAL version is requested by caller. Create CameraClient
// based on the requested HAL version.
if (deviceVersion > CAMERA_DEVICE_API_VERSION_1_0 &&
halVersion == CAMERA_DEVICE_API_VERSION_1_0) {
// Only support higher HAL version device opened as HAL1.0 device.
sp<ICameraClient> tmp = static_cast<ICameraClient*>(cameraCb.get());
*client = new CameraClient(cameraService, tmp, packageName, cameraId, facing,
clientPid, clientUid, servicePid, legacyMode);
} else {
// Other combinations (e.g. HAL3.x open as HAL2.x) are not supported yet.
ALOGE("Invalid camera HAL version %x: HAL %x device can only be"
" opened as HAL %x device", halVersion, deviceVersion,
CAMERA_DEVICE_API_VERSION_1_0);
return STATUS_ERROR_FMT(ERROR_ILLEGAL_ARGUMENT,
"Camera device \"%d\" (HAL version %d) cannot be opened as HAL version %d",
cameraId, deviceVersion, halVersion);
}
}
return Status::ok();
}
上面根据halVersion 来判断使用哪个Client,一般来说:
我们直接调用Camera里的open方法,里面默认传的是CAMERA_HAL_API_VERSION_NORMAL_CONNECT,这个值是-2,所以一般会调用到Camera2Client
骁龙相机打开相机调用的是openLegacy,这个需要自己传VERSION,并且里面有判断halVersion < CAMERA_HAL_API_VERSION_1_0会抛异常,也就是halVersion <0x100就会报错,所以一般这个会跑CameraClient
接着就是调用Client的initialize方法
这里以CameraClient为例
status_t CameraClient::initialize(CameraModule *module) {
int callingPid = getCallingPid();
status_t res;
ALOGE("CameraService mCameraId CameraClient:%d",mCameraId);
LOG1("CameraClient::initialize E (pid %d, id %d)", callingPid, mCameraId);
// Verify ops permissions
res = startCameraOps();
if (res != OK) {
return res;
}
char camera_device_name[10];
snprintf(camera_device_name, sizeof(camera_device_name), "%d", mCameraId);
mHardware = new CameraHardwareInterface(camera_device_name);
res = mHardware->initialize(module);
if (res != OK) {
ALOGE("%s: Camera %d: unable to initialize device: %s (%d)",
__FUNCTION__, mCameraId, strerror(-res), res);
mHardware.clear();
return res;
}
mHardware->setCallbacks(notifyCallback,
dataCallback,
dataCallbackTimestamp,
(void *)(uintptr_t)mCameraId);
// Enable zoom, error, focus, and metadata messages by default
enableMsgType(CAMERA_MSG_ERROR | CAMERA_MSG_ZOOM | CAMERA_MSG_FOCUS |
CAMERA_MSG_PREVIEW_METADATA | CAMERA_MSG_FOCUS_MOVE);
LOG1("CameraClient::initialize X (pid %d, id %d)", callingPid, mCameraId);
return OK;
}
CameraHardwareInterface新建了了一个Camera硬件接口
mHardware->initialize(&module->common):调用底层硬件的初始化方法;
mHardware->setCallbacks:将CamerService处的回调函数注册到HAL处。
CameraHardwareInterface:定义了Camera的硬件抽象特征,由此进入到HAL。
tps:有的打印看不到,可以通过下面命令打开
adb shell dumpsys media.camera -v 2
HAL:CameraHardwareInterface
frameworks\av\services\camera\libcameraservice\device1\CameraHardwareInterface.h
status_t initialize(CameraModule *module)
{
ALOGI("Opening camera %s", mName.string());
camera_info info;
status_t res = module->getCameraInfo(atoi(mName.string()), &info);
if (res != OK) {
return res;
}
int rc = OK;
if (module->getModuleApiVersion() >= CAMERA_MODULE_API_VERSION_2_3 &&
info.device_version > CAMERA_DEVICE_API_VERSION_1_0) {
// Open higher version camera device as HAL1.0 device.
rc = module->openLegacy(mName.string(),
CAMERA_DEVICE_API_VERSION_1_0,
(hw_device_t **)&mDevice);
} else {
rc = module->open(mName.string(), (hw_device_t **)&mDevice);
}
if (rc != OK) {
ALOGE("Could not open camera %s: %d", mName.string(), rc);
return rc;
}
initHalPreviewWindow();
return rc;
}
在initialize()方法中,通过cameraModule->open_legacy打开摄像头模组,如果成功,对象会保存在mDevice中,initHalPreviewWindow()用于初始化Preview的相关流opspreview_stream_ops,初始化hal的预览窗口。
void setCallbacks(notify_callback notify_cb,
data_callback data_cb,
data_callback_timestamp data_cb_timestamp,
void* user)
{
mNotifyCb = notify_cb;
mDataCb = data_cb;
mDataCbTimestamp = data_cb_timestamp;
mCbUser = user;
ALOGV("%s(%s)", __FUNCTION__, mName.string());
if (mDevice->ops->set_callbacks) {
mDevice->ops->set_callbacks(mDevice,
__notify_cb,
__data_cb,
__data_cb_timestamp,
__get_memory,
this);
}
}
set_callbacks中,__notify_cb、__data_cb、__data_cb_timestamp和__get_memory分别消息回调,数据回调,时间戳回调,以及内存相关操作的回调。
关键代码
if (module->getModuleApiVersion() >= CAMERA_MODULE_API_VERSION_2_3 &&
info.device_version > CAMERA_DEVICE_API_VERSION_1_0) {
// Open higher version camera device as HAL1.0 device.
rc = module->openLegacy(mName.string(),
CAMERA_DEVICE_API_VERSION_1_0,
(hw_device_t **)&mDevice);
} else {
rc = module->open(mName.string(), (hw_device_t **)&mDevice);
}
先看看open_legacy
cameraModule->open_legacy
我们来看一下这个module怎么来的
frameworks\av\services\camera\libcameraservice\CameraService.cpp
void CameraService::onFirstRef()
{
ALOGI("CameraService process starting");
BnCameraService::onFirstRef();
// Update battery life tracking if service is restarting
BatteryNotifier& notifier(BatteryNotifier::getInstance());
notifier.noteResetCamera();
notifier.noteResetFlashlight();
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);
return;
}
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);
delete mModule;
mModule = nullptr;
return;
}
......省略代码......
}
frameworks\av\services\camera\libcameraservice\common\CameraModule.h
camera_module_t *mModule;
frameworks\av\services\camera\libcameraservice\common\CameraModule.cpp
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;
}
hw_get_module是jni层获取HAL层module的接口函数,原型为:int hw_get_module(const char *id, const struct hw_module_t **module) 这个id是hal层注册时加入的
hw_get_module详解
我们看下camera_module_t 的定义
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}
};
可以看到open_legacy实际上是调用了qcamera::QCamera2Factory::open_legacy
hardware\qcom\camera\QCamera2\QCamera2Factory.cpp
int QCamera2Factory::open_legacy(const struct hw_module_t* module,
const char* id, uint32_t halVersion, struct hw_device_t** device)
{
int rc = NO_ERROR;
if (module != &HAL_MODULE_INFO_SYM.common) {
LOGE("Invalid module. Trying to open %p, expect %p",
module, &HAL_MODULE_INFO_SYM.common);
return INVALID_OPERATION;
}
if (!id) {
LOGE("Invalid camera id");
return BAD_VALUE;
}
#ifdef QCAMERA_HAL1_SUPPORT
if(gQCameraMuxer)
rc = gQCameraMuxer->open_legacy(module, id, halVersion, device);
else
#endif
rc = gQCamera2Factory->openLegacy(atoi(id), halVersion, device);
return rc;
}
再来看先看看open
cameraModule->open
hardware\qcom\camera\QCamera2\QCamera2Factory.cpp
int QCamera2Factory::camera_device_open(
const struct hw_module_t *module, const char *id,
struct hw_device_t **hw_device)
{
int rc = NO_ERROR;
if (module != &HAL_MODULE_INFO_SYM.common) {
LOGE("Invalid module. Trying to open %p, expect %p",
module, &HAL_MODULE_INFO_SYM.common);
return INVALID_OPERATION;
}
if (!id) {
LOGE("Invalid camera id");
return BAD_VALUE;
}
#ifdef QCAMERA_HAL1_SUPPORT
if(gQCameraMuxer)
rc = gQCameraMuxer->camera_device_open(module, id, hw_device);
else
#endif
rc = gQCamera2Factory->cameraDeviceOpen(atoi(id), hw_device);
return rc;
}
struct hw_module_methods_t QCamera2Factory::mModuleMethods = {
.open = QCamera2Factory::camera_device_open,
};
可以看到,最终都是跑到了QCamera2Factory中
我们看下两者的区别
int QCamera2Factory::openLegacy(
int32_t cameraId, uint32_t halVersion, struct hw_device_t** hw_device)
{
......省略代码......
QCamera2HardwareInterface *hw =
new QCamera2HardwareInterface((uint32_t)cameraId);
if (!hw) {
LOGE("Allocation of hardware interface failed");
return NO_MEMORY;
}
rc = hw->openCamera(hw_device);
if (rc != NO_ERROR) {
delete hw;
}
......省略代码......
}
int QCamera2Factory::cameraDeviceOpen(int camera_id,
struct hw_device_t **hw_device)
{
......省略代码......
QCamera3HardwareInterface *hw = new QCamera3HardwareInterface(mHalDescriptors[camera_id].cameraId,
mCallbacks);
if (!hw) {
LOGE("Allocation of hardware interface failed");
return NO_MEMORY;
}
rc = hw->openCamera(hw_device);
if (rc != 0) {
delete hw;
}
......省略代码......
}
可以看到,一个是QCamera2HardwareInterface一个是QCamera3HardwareInterface
测试发现:
骁龙相机调用的openLegacy会跑QCamera2HardwareInterface
我们自定义的相机会通过Camera2Client会跑到QCamera3HardwareInterface
我们拿QCamera3HardwareInterface来看
从这里开始进入HAL3的流程
HAL3
QCamera3HardwareInterface定义在
hardware\qcom\camera\QCamera2\HAL3\QCamera3HWI.h
我们直接看下openCamera
hardware\qcom\camera\QCamera2\HAL3\QCamera3HWI.cpp
int QCamera3HardwareInterface::openCamera(struct hw_device_t **hw_device)
{
int rc = 0;
if (mState != CLOSED) {
*hw_device = NULL;
return PERMISSION_DENIED;
}
m_perfLock.lock_acq();
LOGI("[KPI Perf]: E PROFILE_OPEN_CAMERA camera id %d",
mCameraId);
rc = openCamera();
if (rc == 0) {
*hw_device = &mCameraDevice.common;
} else
*hw_device = NULL;
m_perfLock.lock_rel();
LOGI("[KPI Perf]: X PROFILE_OPEN_CAMERA camera id %d, rc: %d",
mCameraId, rc);
if (rc == NO_ERROR) {
mState = OPENED;
}
return rc;
}
int QCamera3HardwareInterface::openCamera()
{
int rc = 0;
......省略代码......
rc = camera_open((uint8_t)mCameraId, &mCameraHandle);
if (rc) {
LOGE("camera_open failed. rc = %d, mCameraHandle = %p", rc, mCameraHandle);
return rc;
}
......省略代码......
}
camera_open
hardware\qcom\camera\QCamera2\stack\mm-camera-interface\src\mm_camera_interface.c
int32_t camera_open(uint8_t camera_idx, mm_camera_vtbl_t **camera_vtbl)
{
int32_t rc = 0;
mm_camera_obj_t *cam_obj = NULL;
#ifdef QCAMERA_REDEFINE_LOG
mm_camera_set_dbg_log_properties();
#endif
LOGE("E camera_idx = %d\n", camera_idx);
LOGD("E camera_idx = %d\n", camera_idx);
if (camera_idx >= g_cam_ctrl.num_cam) {
LOGE("Invalid camera_idx (%d)", camera_idx);
return -EINVAL;
}
pthread_mutex_lock(&g_intf_lock);
/* opened already */
if(NULL != g_cam_ctrl.cam_obj[camera_idx]) {
/* Add reference */
g_cam_ctrl.cam_obj[camera_idx]->ref_count++;
pthread_mutex_unlock(&g_intf_lock);
LOGD("opened alreadyn");
*camera_vtbl = &g_cam_ctrl.cam_obj[camera_idx]->vtbl;
return rc;
}
cam_obj = (mm_camera_obj_t *)malloc(sizeof(mm_camera_obj_t));
if(NULL == cam_obj) {
pthread_mutex_unlock(&g_intf_lock);
LOGE("no mem");
return -EINVAL;
}
/* initialize camera obj */
memset(cam_obj, 0, sizeof(mm_camera_obj_t));
cam_obj->ctrl_fd = -1;
cam_obj->ds_fd = -1;
cam_obj->ref_count++;
cam_obj->my_hdl = mm_camera_util_generate_handler(camera_idx);
cam_obj->vtbl.camera_handle = cam_obj->my_hdl; /* set handler */
cam_obj->vtbl.ops = &mm_camera_ops;
pthread_mutex_init(&cam_obj->cam_lock, NULL);
/* unlock global interface lock, if not, in dual camera use case,
* current open will block operation of another opened camera obj*/
pthread_mutex_lock(&cam_obj->cam_lock);
pthread_mutex_unlock(&g_intf_lock);
rc = mm_camera_open(cam_obj);
pthread_mutex_lock(&g_intf_lock);
if (rc != 0) {
LOGE("mm_camera_open err = %d", rc);
pthread_mutex_destroy(&cam_obj->cam_lock);
g_cam_ctrl.cam_obj[camera_idx] = NULL;
free(cam_obj);
cam_obj = NULL;
pthread_mutex_unlock(&g_intf_lock);
*camera_vtbl = NULL;
return rc;
} else {
LOGD("Open succeded\n");
g_cam_ctrl.cam_obj[camera_idx] = cam_obj;
pthread_mutex_unlock(&g_intf_lock);
*camera_vtbl = &cam_obj->vtbl;
return 0;
}
}
mm_camera_open
hardware\qcom\camera\QCamera2\stack\mm-camera-interface\src\mm_camera.c
int32_t mm_camera_open(mm_camera_obj_t *my_obj)
{
char dev_name[MM_CAMERA_DEV_NAME_LEN];
int32_t rc = 0;
int8_t n_try=MM_CAMERA_DEV_OPEN_TRIES;
uint8_t sleep_msec=MM_CAMERA_DEV_OPEN_RETRY_SLEEP;
int cam_idx = 0;
const char *dev_name_value = NULL;
int l_errno = 0;
pthread_condattr_t cond_attr;
LOGD("begin\n");
if (NULL == my_obj) {
goto on_error;
}
dev_name_value = mm_camera_util_get_dev_name(my_obj->my_hdl);
if (NULL == dev_name_value) {
goto on_error;
}
snprintf(dev_name, sizeof(dev_name), "/dev/%s",
dev_name_value);
sscanf(dev_name, "/dev/video%d", &cam_idx);
LOGD("dev name = %s, cam_idx = %d", dev_name, cam_idx);
do{
n_try--;
errno = 0;
my_obj->ctrl_fd = open(dev_name, O_RDWR | O_NONBLOCK);
l_errno = errno;
LOGD("ctrl_fd = %d, errno == %d", my_obj->ctrl_fd, l_errno);
if((my_obj->ctrl_fd >= 0) || (errno != EIO && errno != ETIMEDOUT) || (n_try <= 0 )) {
break;
}
LOGE("Failed with %s error, retrying after %d milli-seconds",
strerror(errno), sleep_msec);
usleep(sleep_msec * 1000U);
}while (n_try > 0);
......省略代码......
}
通过open(dev_name, O_RDWR | O_NONBLOCK)来打开相机设备,接下来就会调用到Kernel层的代码
我们先看看这个dev_name_value 是怎么获取的
dev_name_value = mm_camera_util_get_dev_name(my_obj->my_hdl);
hardware\qcom\camera\QCamera2\stack\mm-camera-interface\src\mm_camera_interface.c
const char *mm_camera_util_get_dev_name(uint32_t cam_handle)
{
char *dev_name = NULL;
uint8_t cam_idx = mm_camera_util_get_index_by_handler(cam_handle);
if(cam_idx < MM_CAMERA_MAX_NUM_SENSORS) {
dev_name = g_cam_ctrl.video_dev_name[cam_idx];
}
return dev_name;
}
这里面看到先得到cam_idx
uint8_t mm_camera_util_get_index_by_handler(uint32_t handler)
{
return (handler&0x000000ff);
}
这里得到相机的id号,就是我们常见的0、1,然后通过g_cam_ctrl.video_dev_name[cam_idx];获取dev_name
我们看一下这个
static mm_camera_ctrl_t g_cam_ctrl;
hardware\qcom\camera\QCamera2\stack\mm-camera-interface\inc\mm_camera.h
typedef struct {
int8_t num_cam;
mm_camera_shim_ops_t cam_shim_ops;
char video_dev_name[MM_CAMERA_MAX_NUM_SENSORS][MM_CAMERA_DEV_NAME_LEN];
mm_camera_obj_t *cam_obj[MM_CAMERA_MAX_NUM_SENSORS];
struct camera_info info[MM_CAMERA_MAX_NUM_SENSORS];
cam_sync_type_t cam_type[MM_CAMERA_MAX_NUM_SENSORS];
cam_sync_mode_t cam_mode[MM_CAMERA_MAX_NUM_SENSORS];
uint8_t is_yuv[MM_CAMERA_MAX_NUM_SENSORS]; // 1=CAM_SENSOR_YUV, 0=CAM_SENSOR_RAW
} mm_camera_ctrl_t;
看一下初始化的地方
uint8_t get_num_of_cameras()
{
......省略代码......
while (1) {
uint32_t num_entities = 1U;
char dev_name[32];
snprintf(dev_name, sizeof(dev_name), "/dev/media%d", num_media_devices);
LOGD("g_cam_ctrl dev_name: %s\n", dev_name);
dev_fd = open(dev_name, O_RDWR | O_NONBLOCK);
......省略代码......
while (1) {
struct media_entity_desc entity;
memset(&entity, 0, sizeof(entity));
entity.id = num_entities++;
rc = ioctl(dev_fd, MEDIA_IOC_ENUM_ENTITIES, &entity);
if (rc < 0) {
LOGD("Done enumerating media entities\n");
rc = 0;
break;
}
if(entity.type == MEDIA_ENT_T_DEVNODE_V4L && entity.group_id == QCAMERA_VNODE_GROUP_ID) {
strlcpy(g_cam_ctrl.video_dev_name[num_cameras],
entity.name, sizeof(entity.name));
LOGI("dev_info[id=%d,name='%s']\n",
(int)num_cameras, g_cam_ctrl.video_dev_name[num_cameras]);
num_cameras++;
break;
}
}
close(dev_fd);
dev_fd = -1;
if (num_cameras >= MM_CAMERA_MAX_NUM_SENSORS) {
LOGW("Maximum number of camera reached %d", num_cameras);
break;
}
}
g_cam_ctrl.num_cam = num_cameras;
......省略代码......
}
这个方法在开机的时候会执行一次
网友评论