之前已经写过一篇关于camera框架的文章,现在开始写camera相关的功能流程,总结一下常用的camera流程,算是对camera开发的一个回顾。
Android 8.1 MTK Camera(api1)源码框架分析
首先先看下camera open流程,基于mtk release代码,使用camera api1+hal1.0的组合。
api中定义的有两种open方式,分别是:
return Camera.open(cameraId); //指定打开某一个摄像头
return Camera.open(); //默认打开后置摄像头
open函数的参数cameraID,表示要访问的是哪一个硬件摄像头:介于0和getNumberOfCameras()-1之间。
而mtk的release代码中,新增了一种open方式,增加了指定hal版本的参数:
//指定hal api版本以及指定打开某个摄像头,如果当前设备不支持指定的hal版本,则抛出RuntimeException。
return Camera.openLegacy(cameraId, halVersion);
这三种方式实际都是去new Camera(),只是构造函数中的参数不一样。都返回Camera句柄。
frameworks/base/core/java/android/hardware/Camera.java 中的open函数定义:
方式一:
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);
//这里通过遍历到back camera时,就new Camera(i)
if (cameraInfo.facing == CameraInfo.CAMERA_FACING_BACK) {
return new Camera(i);
}
}
return null;
}
方式三:
public static Camera openLegacy(int cameraId, int halVersion) {
if (halVersion < CAMERA_HAL_API_VERSION_1_0) {
throw new IllegalArgumentException("Invalid HAL version " + halVersion);
}
//new camera时,传入hal版本的参数
return new Camera(cameraId, halVersion);
}
三种方式都是去new Camera,所以看到Camera同名不同参的两个构造函数。
构造函数一:
/** used by Camera#open, Camera#open(int) */
Camera(int cameraId) {
int err = cameraInitNormal(cameraId); //init
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");
}
}
构造函数二:
/**
* Create a legacy camera object.
*
* @param cameraId The hardware camera to access, between 0 and
* {@link #getNumberOfCameras()}-1.
* @param halVersion The HAL API version this camera device to be opened as.
*/
private Camera(int cameraId, int halVersion) {
int err = cameraInitVersion(cameraId, halVersion);//init
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");
} else if (err == -ENOSYS) {
throw new RuntimeException("Camera initialization failed because some methods"
+ " are not implemented");
} else if (err == -EOPNOTSUPP) {
throw new RuntimeException("Camera initialization failed because the hal"
+ " version is not supported by this device");
} else if (err == -EINVAL) {
throw new RuntimeException("Camera initialization failed because the input"
+ " arugments are invalid");
} else if (err == -EBUSY) {
throw new RuntimeException("Camera initialization failed because the camera"
+ " device was already opened");
} else if (err == -EUSERS) {
throw new RuntimeException("Camera initialization failed because the max"
+ " number of camera devices were already opened");
}
// Should never hit this.
throw new RuntimeException("Unknown camera error");
}
}
构造函数中,都通过cameraInit函数的返回值来判断camera是否打开成功,如失败则抛出异常。真正的去执行open操作也是在cameraInit函数中调用jni函数native_setup。
-----cameraInitNormal中的参数指定为CAMERA_HAL_API_VERSION_NORMAL_CONNECT = -2;这个代表的是使用当前系统底层默认的hal版本。
private int cameraInitNormal(int cameraId) {
return cameraInitVersion(cameraId, CAMERA_HAL_API_VERSION_NORMAL_CONNECT);
}
-----而cameraInitVersion中参数是由调用者设置的。一般设置CAMERA_HAL_API_VERSION_1_0 = 0x100; 表明Camera HAL device API version 1.0。
private int cameraInitVersion(int cameraId, int halVersion) {
mShutterCallback = null;
mRawImageCallback = null;
mJpegCallback = null;
mPreviewCallback = null;
mPostviewCallback = null;
mUsingPreviewAllocation = false;
mZoomListener = null;
Looper looper;
if ((looper = Looper.myLooper()) != null) {
mEventHandler = new EventHandler(this, looper);
} else if ((looper = Looper.getMainLooper()) != null) {
mEventHandler = new EventHandler(this, looper);
} else {
mEventHandler = null;
}
return native_setup(new WeakReference<Camera>(this), cameraId, halVersion,
ActivityThread.currentOpPackageName());
}
根据jni函数命名规则,可找到native_setup函数所在文件目录:frameworks\base\core\jni\android_hardware_Camera.cpp。
native_setup()被动态注册到JNI,指向android_hardware_Camera_native_setup()方法。
static const JNINativeMethod camMethods[] = {
......
{ "native_setup",
"(Ljava/lang/Object;IILjava/lang/String;)I",
(void*)android_hardware_Camera_native_setup },
......
android_hardware_Camera_native_setup函数自带了两个原生参数JNIEnv *env, jobject thiz,而后面4个参数就是从camera.java中native_setup函数传下来的。
// connect to camera service
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));
//根据halVersion来决定走哪一个connect函数
sp<Camera> camera; //这里是指向Camera.cpp/Camera.h
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;
}
}
//判断camera的相关状态,返回相关error信息
if (camera == NULL) {
return -EACCES;
}
// make sure camera hardware is alive
if (camera->getStatus() != NO_ERROR) {
return NO_INIT;
}
jclass clazz = env->GetObjectClass(thiz);
if (clazz == NULL) {
// This should never happen
jniThrowRuntimeException(env, "Can't find android/hardware/Camera");
return INVALID_OPERATION;
}
......
return NO_ERROR;
}
通过将clientPackageName从jstring转换为String16格式得到clientName。
函数中根据halVersion来决定走哪一个connect函数,如是CAMERA_HAL_API_VERSION_NORMAL_CONNECT,则走的默认的;否则走指定的hal版本。
调用Camera::connect()/connectLegacy()方法去请求连接CameraService服务,这个camera指向的就是Camera.h/Camera.cpp了,有此进入到了camera client端。
Camera.h头文件路径:\frameworks\av\camera\include\camera,函数声明:
static sp<Camera> connect(int cameraId,
const String16& clientPackageName,
int clientUid, int clientPid);
static status_t connectLegacy(int cameraId, int halVersion,
const String16& clientPackageName,
int clientUid, sp<Camera>& camera);
由于mtk在Android P之前hal层基本使用的hal1.0,所以这里就看connectLegacy函数。
在frameworks\av\camera\Camera.cpp文件中:
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); //拿到已经被打开的camera的,ICamera接口
sp<::android::hardware::ICameraClient> cl = c; //拿到ICameraClient接口
status_t status = NO_ERROR;
//通过CameraBaseT::getCameraService()拿到ICameraService接口
const sp<::android::hardware::ICameraService>& cs = CameraBaseT::getCameraService();
binder::Status ret;
if (cs != nullptr) {
//这里cs.get是拿到CameraService,并调用connectLegacy,传入参数
ret = cs.get()->connectLegacy(cl, cameraId, halVersion, clientPackageName,
clientUid, /*out*/&(c->mCamera)); //c->mCamera指向的就是ICamera
}
if (ret.isOk() && c->mCamera != nullptr) {
IInterface::asBinder(c->mCamera)->linkToDeath(c); //binder间通讯
c->mStatus = NO_ERROR;
camera = c;
} else {
switch(ret.serviceSpecificErrorCode()) {//遍历error code,赋值status
case hardware::ICameraService::ERROR_DISCONNECTED:
status = -ENODEV;
break;
case hardware::ICameraService::ERROR_CAMERA_IN_USE:
status = -EBUSY;
break;
case hardware::ICameraService::ERROR_INVALID_OPERATION:
status = -EINVAL;
break;
case hardware::ICameraService::ERROR_MAX_CAMERAS_IN_USE:
status = -EUSERS;
break;
case hardware::ICameraService::ERROR_ILLEGAL_ARGUMENT:
status = BAD_VALUE;
break;
case hardware::ICameraService::ERROR_DEPRECATED_HAL:
status = -EOPNOTSUPP;
break;
case hardware::ICameraService::ERROR_DISABLED:
status = -EACCES;
break;
case hardware::ICameraService::ERROR_PERMISSION_DENIED:
status = PERMISSION_DENIED;
break;
default:
status = -EINVAL;
ALOGW("An error occurred while connecting to camera %d: %s", cameraId,
(cs != nullptr) ? "Service not available" : ret.toString8().string());
break;
}
c.clear();
}
return status;
}
connectLegacy函数中,先是拿到已经被打开的camera的ICamera接口,再获取ICameraClient接口,通过CameraBaseT::getCameraService()再拿到ICameraService接口,通过cs.get是拿到CameraService,并调用connectLegacy,传入ICameraClient cl、ICamera /out/&(c->mCamera)等参数。
CameraBaseT是CameraBase的模板类,CameraBaseT是定义在CameraBase.h中的变量。
typedef CameraBase<TCam> CameraBaseT;
所以可以在CameraBase.cpp中看下CameraBaseT::getCameraService()函数,通过binder方式拿到ICameraService。
// establish binder interface to camera service
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;
}
文件路径:frameworks\av\services\camera\libcameraservice。
cs.get()->connectLegacy指向到CameraSerive中,看到CameraService.h头文件中声明:
virtual binder::Status connectLegacy(const sp<hardware::ICameraClient>& cameraClient,
int32_t cameraId, int32_t halVersion,
const String16& clientPackageName, int32_t clientUid,
/*out*/
sp<hardware::ICamera>* device);
到具体的实现,在CameraService.cpp中:
Status CameraService::connectLegacy(
const sp<ICameraClient>& cameraClient,
int cameraId, int halVersion,
const String16& clientPackageName,
int clientUid,
/*out*/
sp<ICamera>* device) {
ATRACE_CALL();
String8 id = String8::format("%d", cameraId);
Status ret = Status::ok();
sp<Client> client = nullptr;
//调用封装的函数connectHelper,默认指定API_1
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:
template<class CALLBACK, class CLIENT>
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) {
binder::Status ret = binder::Status::ok();
String8 clientName8(clientPackageName);//将string16转换为String8
int originalClientPid = 0;
ALOGI("CameraService::connect call (PID %d \"%s\", camera ID %s) for HAL version %s and "
"Camera API version %d", clientPid, clientName8.string(), cameraId.string(),
(halVersion == -1) ? "default" : std::to_string(halVersion).c_str(),
static_cast<int>(effectiveApiLevel)); //打印连接信息
sp<CLIENT> client = nullptr;
{
......
sp<BasicClient> tmp = nullptr;
if(!(ret = makeClient(this, cameraCb, clientPackageName, cameraId, facing, clientPid,
clientUid, getpid(), legacyMode, halVersion, deviceVersion, effectiveApiLevel,
/*out*/&tmp)).isOk()) { //调用makeClient去拿到Client
return ret;
}
client = static_cast<CLIENT*>(tmp.get());
LOG_ALWAYS_FATAL_IF(client.get() == nullptr, "%s: CameraService in invalid state",
__FUNCTION__);
//调用client->initialize去初始化CameraClient
err = client->initialize(mCameraProviderManager);
if (err != OK) { //error信息判断
ALOGE("%s: Could not initialize client from HAL.", __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());
......
default:
return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION,
"Failed to initialize camera \"%s\": %s (%d)", cameraId.string(),
strerror(-err), err);
}
}
......
} // lock is destroyed, allow further connect calls
// 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去拿到Client,并调用client->initialize去初始化CameraClient。
BaseClient声明在CameraService.h头文件中的类:
class BasicClient : public virtual RefBase {
再看makeClient函数,通过判断hal版本,走不同的client创建,如判断走api1,new CameraClient返回给sp BasicClient* client,connectHelper中拿到了new CameraClient的返回值后,通过该返回值来调用init函数,也就是上面说到的client->initialize。
Status CameraService::makeClient(const sp<CameraService>& cameraService,
const sp<IInterface>& cameraCb, const String16& packageName, const String8& 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) { //判断hal版本,走不同的client创建
case CAMERA_DEVICE_API_VERSION_1_0:
if (effectiveApiLevel == API_1) { // Camera1 API route
//判断走api1,new CameraClient返回给sp* client
sp<ICameraClient> tmp = static_cast<ICameraClient*>(cameraCb.get());
*client = new CameraClient(cameraService, tmp, packageName, cameraIdToInt(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 \"%s\" HAL version %d does not support camera2 API",
cameraId.string(), 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, cameraIdToInt(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 \"%s\" has unknown HAL version %d",
cameraId.string(), deviceVersion);
}
} else {
......
}
return Status::ok();
}
makeClient函数中new CameraClient,CameraClient文件路径在:frameworks\av\services\camera\libcameraservice\api1
CameraClient.cpp构造:
CameraClient::CameraClient(const sp<CameraService>& cameraService,
const sp<hardware::ICameraClient>& cameraClient,
const String16& clientPackageName,
int cameraId, int cameraFacing,
int clientPid, int clientUid,
int servicePid, bool legacyMode):
Client(cameraService, cameraClient, clientPackageName,
String8::format("%d", cameraId), cameraFacing, clientPid,
clientUid, servicePid)
{
int callingPid = getCallingPid();
LOG1("CameraClient::CameraClient E (pid %d, id %d)", callingPid, cameraId);
mHardware = NULL;
mMsgEnabled = 0;
mSurface = 0;
mPreviewWindow = 0;
mDestructionStarted = false;
// Callback is disabled by default
mPreviewCallbackFlag = CAMERA_FRAME_CALLBACK_FLAG_NOOP;
mOrientation = getOrientation(0, mCameraFacing == CAMERA_FACING_FRONT);
mLegacyMode = legacyMode;
mPlayShutterSound = true;
LOG1("CameraClient::CameraClient X (pid %d, id %d)", callingPid, cameraId);
}
再看connectHelper中client->initialize:
status_t CameraClient::initialize(sp<CameraProviderManager> manager) {
int callingPid = getCallingPid();
status_t res;
LOG1("CameraClient::initialize E (pid %d, id %d)", callingPid, mCameraId);
// Verify ops permissions
res = startCameraOps();
if (res != OK) {
return res;
}
//通过传入的cameraId来获取将要指定打开的camera设备名称
char camera_device_name[10];
snprintf(camera_device_name, sizeof(camera_device_name), "%d", mCameraId);
//创建一个Camera硬件接口对象
mHardware = new CameraHardwareInterface(camera_device_name);
//调用mHardware->initialize底层硬件初始化函数
res = mHardware->initialize(manager);
if (res != OK) {
ALOGE("%s: Camera %d: unable to initialize device: %s (%d)",
__FUNCTION__, mCameraId, strerror(-res), res);
mHardware.clear();
return res;
}
//将cameraservice中的消息回调、数据回调等回调注册到hal层
mHardware->setCallbacks(notifyCallback,
dataCallback,
dataCallbackTimestamp,
handleCallbackTimestampBatch,
(void *)(uintptr_t)mCameraId);
......
LOG1("CameraClient::initialize X (pid %d, id %d)", callingPid, mCameraId);
return OK;
}
CameraClient中的init函数主要是通过传入的cameraId来获取将要指定打开的camera设备名称,再通过设备名称创建一个Camera硬件接口对象,调用mHardware->initialize去实现底层硬件初始化,再将cameraservice中的消息回调、数据回调等回调注册到hal层,方便hal层与cameraService及时通信。
到这里基本就调用到了CameraHardwareInterface中,也就是调用到CameraHardwareInterface.h通往hal的接口。
文件路径:\frameworks\av\services\camera\libcameraservice\device1
CameraHardwareInterface.h头文件声明:
......
status_t initialize(sp<CameraProviderManager> manager);
/** Set the notification and data callbacks */
void setCallbacks(notify_callback notify_cb,
data_callback data_cb,
data_callback_timestamp data_cb_timestamp,
data_callback_timestamp_batch data_cb_timestamp_batch,
void* user);
......
CameraHardwareInterface.cpp实现:
status_t CameraHardwareInterface::initialize(sp<CameraProviderManager> manager) {
ALOGI("Opening camera %s", mName.string());
status_t ret = manager->openSession(mName.string(), this, &mHidlDevice);
if (ret != OK) {
ALOGE("%s: openSession failed! %s (%d)", __FUNCTION__, strerror(-ret), ret);
}
return ret;
}
可以看到initialize函数中,主要就是调用了CameraProviderManager.cpp的openSession函数。CameraProviderManager manager是有cameraService.cpp中的connect中传过来的参数。
文件路径:\frameworks\av\services\camera\libcameraservice\common\CameraProviderManager.cpp。
由于hal版本可能不一致,所以openSession的参数也区分了,主要是device的不同:
函数一:
status_t CameraProviderManager::openSession(const std::string &id,
const sp<hardware::camera::device::V3_2::ICameraDeviceCallback>& callback,
/*out*/
sp<hardware::camera::device::V3_2::ICameraDeviceSession> *session) {
函数二:
status_t CameraProviderManager::openSession(const std::string &id,
const sp<hardware::camera::device::V1_0::ICameraDeviceCallback>& callback,
/*out*/
sp<hardware::camera::device::V1_0::ICameraDevice> *session) {
这里就看函数二。
status_t CameraProviderManager::openSession(const std::string &id,
const sp<hardware::camera::device::V1_0::ICameraDeviceCallback>& callback,
/*out*/
sp<hardware::camera::device::V1_0::ICameraDevice> *session) {
std::lock_guard<std::mutex> lock(mInterfaceMutex);
//获取设备信息
auto deviceInfo = findDeviceInfoLocked(id,
/*minVersion*/ {1,0}, /*maxVersion*/ {2,0});
if (deviceInfo == nullptr) return NAME_NOT_FOUND;
auto *deviceInfo1 = static_cast<ProviderInfo::DeviceInfo1*>(deviceInfo);
//调用hal设备节点接口去open函数,并将callback传下去
hardware::Return<Status> status = deviceInfo1->mInterface->open(callback);
if (!status.isOk()) {
ALOGE("%s: Transaction error opening a session for camera device %s: %s",
__FUNCTION__, id.c_str(), status.description().c_str());
return DEAD_OBJECT;
}
if (status == Status::OK) {
*session = deviceInfo1->mInterface;
}
return mapToStatusT(status);
}
openSession主要就是调用底层camera设备节点接口去open函数,并将service注册的callback传下去。这样hal层和service层就能通过回调,接收相关消息,再来通知client端。
而deviceInfo的获取,是通过findDeviceInfoLocked函数,里面是遍历了mProviders。
CameraProviderManager::ProviderInfo::DeviceInfo* CameraProviderManager::findDeviceInfoLocked(
const std::string& id,
hardware::hidl_version minVersion, hardware::hidl_version maxVersion) const {
for (auto& provider : mProviders) {
for (auto& deviceInfo : provider->mDevices) {
if (deviceInfo->mId == id &&
minVersion <= deviceInfo->mVersion && maxVersion >= deviceInfo->mVersion) {
return deviceInfo.get();
}
}
}
return nullptr;
}
mProviders的生成是在CameraService被初始化启动的时候,再CameraProviderManager初始化逻辑中,通过调用addProviderLocked函数生成具体的DeviceInfo对象,再添加到mProviders成员变量中。可以看下函数:
status_t CameraProviderManager::addProviderLocked(const std::string& newProvider, bool expected) {
for (const auto& providerInfo : mProviders) {
if (providerInfo->mProviderName == newProvider) {
ALOGW("%s: Camera provider HAL with name '%s' already registered", __FUNCTION__,
newProvider.c_str());
return ALREADY_EXISTS;
}
}
sp<provider::V2_4::ICameraProvider> interface;
interface = mServiceProxy->getService(newProvider);
if (interface == nullptr) {
if (expected) {
ALOGE("%s: Camera provider HAL '%s' is not actually available", __FUNCTION__,
newProvider.c_str());
return BAD_VALUE;
} else {
return OK;
}
}
sp<ProviderInfo> providerInfo =
new ProviderInfo(newProvider, interface, this);
status_t res = providerInfo->initialize();
if (res != OK) {
return res;
}
mProviders.push_back(providerInfo);
return OK;
}
回到openSession方法,deviceInfo1->mInterface->open,mInterface就是在构造ProviderInfo时获取到的binder对象。实际是\hardware\interfaces\camera\device\1.0\default\CameraDevice.cpp对象。这里接着往下走,就又是binder进程间通信机制了。
\hardware\interfaces\camera\device里面有1.0、3.2、3.3等多个文件,具体哪一个就看openSession函数的第二个、第三参数了。
在看\hardware\interfaces\camera\device\1.0\default\CameraDevice.cpp对象,这里实际已经调用到hardware层了,看open方法源码:
Return<Status> CameraDevice::open(const sp<ICameraDeviceCallback>& callback) {
ALOGI("Opening camera %s", mCameraId.c_str());
Mutex::Autolock _l(mLock);
camera_info info;
status_t res = mModule->getCameraInfo(mCameraIdInt, &info);
if (res != OK) {
ALOGE("Could not get camera info: %s: %d", mCameraId.c_str(), res);
return getHidlStatus(res);
}
int rc = OK;
if (mModule->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 = mModule->openLegacy(mCameraId.c_str(),
CAMERA_DEVICE_API_VERSION_1_0,
(hw_device_t **)&mDevice);
} else { //调用mModule->open,传入hw_device_t
rc = mModule->open(mCameraId.c_str(), (hw_device_t **)&mDevice);
}
if (rc != OK) {
mDevice = nullptr;
ALOGE("Could not open camera %s: %d", mCameraId.c_str(), rc);
return getHidlStatus(rc);
}
initHalPreviewWindow(); //初始化预览窗口
mDeviceCallback = callback;
if (mDevice->ops->set_callbacks) {//设置callback给device
mDevice->ops->set_callbacks(mDevice,
sNotifyCb, sDataCb, sDataCbTimestamp, sGetMemory, this);
}
return getHidlStatus(rc);
}
该open函数中rc = mModule->open(mCameraId.c_str(), (hw_device_t **)&mDevice);是实际来操作打开相机的。mModule是CameraDevice::CameraDevice构造中初始化的。再看CameraDevice::CameraDevice类的实例化,找到了位置是在\hardware\interfaces\camera\provider\2.4\default\CameraProvider.cpp,看到这个文件里面函数CameraProvider::getCameraDeviceInterface_V1_x,这个从名称看出来是针对api1 + hal1.0的,当然还有另一个函数是getCameraDeviceInterface_V3_x针对hal3.0的。
Return<void> CameraProvider::getCameraDeviceInterface_V1_x(
const hidl_string& cameraDeviceName, getCameraDeviceInterface_V1_x_cb _hidl_cb) {
std::string cameraId, deviceVersion;
bool match = matchDeviceName(cameraDeviceName, &deviceVersion, &cameraId);
if (!match) {
_hidl_cb(Status::ILLEGAL_ARGUMENT, nullptr);
return Void();
}
std::string deviceName(cameraDeviceName.c_str());
ssize_t index = mCameraDeviceNames.indexOf(std::make_pair(cameraId, deviceName));
if (index == NAME_NOT_FOUND) { // Either an illegal name or a device version mismatch
Status status = Status::OK;
ssize_t idx = mCameraIds.indexOf(cameraId);
if (idx == NAME_NOT_FOUND) {
ALOGE("%s: cannot find camera %s!", __FUNCTION__, cameraId.c_str());
status = Status::ILLEGAL_ARGUMENT;
} else { // invalid version
ALOGE("%s: camera device %s does not support version %s!",
__FUNCTION__, cameraId.c_str(), deviceVersion.c_str());
status = Status::OPERATION_NOT_SUPPORTED;
}
_hidl_cb(status, nullptr);
return Void();
}
if (mCameraStatusMap.count(cameraId) == 0 ||
mCameraStatusMap[cameraId] != CAMERA_DEVICE_STATUS_PRESENT) {
_hidl_cb(Status::ILLEGAL_ARGUMENT, nullptr);
return Void();
}
//实例化CameraDevice,传入了这个CameraModule对象mModule
sp<android::hardware::camera::device::V1_0::implementation::CameraDevice> device =
new android::hardware::camera::device::V1_0::implementation::CameraDevice(
mModule, cameraId, mCameraDeviceNames);
if (device == nullptr) {
ALOGE("%s: cannot allocate camera device for id %s", __FUNCTION__, cameraId.c_str());
_hidl_cb(Status::INTERNAL_ERROR, nullptr);
return Void();
}
if (device->isInitFailed()) {
ALOGE("%s: camera device %s init failed!", __FUNCTION__, cameraId.c_str());
device = nullptr;
_hidl_cb(Status::INTERNAL_ERROR, nullptr);
return Void();
}
_hidl_cb (Status::OK, device);
return Void();
}
这个函数中实例化了CameraDevice,传入了这个CameraModule的对象mModule。mModule定义在了头文件\hardware\interfaces\camera\provider\2.4\default中。
using ::android::hardware::camera::common::V1_0::helper::CameraModule;
......
sp<CameraModule> mModule;
CameraModule的对象mModule,在CameraProvider.cpp中initialize()函数进行init:
bool CameraProvider::initialize() {
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));
return true;
}
mModule = new CameraModule(rawModule);
err = mModule->init();
if (err != OK) {
ALOGE("Could not initialize camera HAL module: %d (%s)", err, strerror(-err));
mModule.clear();
return true;
}
ALOGI("Loaded \"%s\" camera module", mModule->getModuleName());
......
之前在\hardware\interfaces\camera\device\1.0\default\CameraDevice.cpp中,open函数中rc = mModule->open(mCameraId.c_str(), (hw_device_t **)&mDevice);,实际是调用到CameraModule.open函数。所以接着去看CameraModule.cpp文件,路径hardware\interfaces\camera\common\1.0\default\CameraModule.cpp。也是定义了open和openLegacy函数两套。核心都是使用mModul->common。只不过open函数是通过mModule->common.methods->open方式,而openLegacy是通过mModule->open_legacy方式。这里就看mModule->open_legacy函数。
int CameraModule::open(const char* id, struct hw_device_t** device) {
int res;
ATRACE_BEGIN("camera_module->open");
res = filterOpenErrorCode(mModule->common.methods->open(&mModule->common, id, device));
ATRACE_END();
return res;
}
int CameraModule::openLegacy(
const char* id, uint32_t halVersion, struct hw_device_t** device) {
int res;
ATRACE_BEGIN("camera_module->open_legacy");
res = mModule->open_legacy(&mModule->common, id, halVersion, device);
ATRACE_END();
return res;
}
mModule是在构造中获得的。
CameraModule::CameraModule(camera_module_t *module) {
if (module == NULL) {
ALOGE("%s: camera hardware module must not be null", __FUNCTION__);
assert(0);
}
mModule = module;
}
而CameraModule的实例化是在CameraProvider::initialize()中进行的,之前已经贴过源码了。
bool CameraProvider::initialize() {
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));
return true;
}
mModule = new CameraModule(rawModule);
实例化mModule = new CameraModule(rawModule); ,传入的camera_module_t *rawModule参数。rawModule参数通过函数hw_get_module(CAMERA_HARDWARE_MODULE_ID,(const hw_module_t **)&rawModule)来进行获取。所以之前mModule->open_legacy,也就是调用到rawModule->open_legacy。CAMERA_HARDWARE_MODULE_ID是指的hal层定义的module,hw_get_module就是通过module来获得camera模块,在通过获得的这个模块去调用hal层数。hw_get_module获取具体的module就与产商或设备有关系了。rawModule的类型是camera_module_t,所以也就是会通过camera_module_t这个结构体的open_legacy函数来执行open操作。hw_module_t也是一个结构体,在接着往下走,就要看hw_module_t和camera_module_t结构体的具体定义了。
搜索发现hw_get_module定义在hardware\libhardware\hardware.c中:
int hw_get_module(const char *id, const struct hw_module_t **module)
{
return hw_get_module_by_class(id, NULL, module);
}
int hw_get_module_by_class(const char *class_id, const char *inst,
const struct hw_module_t **module)
{
int i = 0;
char prop[PATH_MAX] = {0};
char path[PATH_MAX] = {0};
char name[PATH_MAX] = {0};
char prop_name[PATH_MAX] = {0};
if (inst)
snprintf(name, PATH_MAX, "%s.%s", class_id, inst);
else
strlcpy(name, class_id, PATH_MAX);
/*
* Here we rely on the fact that calling dlopen multiple times on
* the same .so will simply increment a refcount (and not load
* a new copy of the library).
* We also assume that dlopen() is thread-safe.
*/
/* First try a property specific to the class and possibly instance */
snprintf(prop_name, sizeof(prop_name), "ro.hardware.%s", name);
if (property_get(prop_name, prop, NULL) > 0) {
if (hw_module_exists(path, sizeof(path), name, prop) == 0) {
goto found;
}
}
/* Loop through the configuration variants looking for a module */
for (i=0 ; i<HAL_VARIANT_KEYS_COUNT; i++) {
if (property_get(variant_keys[i], prop, NULL) == 0) {
continue;
}
if (hw_module_exists(path, sizeof(path), name, prop) == 0) {
goto found;
}
}
/* Nothing found, try the default */
if (hw_module_exists(path, sizeof(path), name, "default") == 0) {
goto found;
}
return -ENOENT;
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);
}
再在device中搜索camera_module_t结构体,结果如下,基本在device/huawei、device/google、device/generic、device/lge几个目录中,这几个目录是源码中提供的几个厂商的实现。
device/huawei/angler/camera/QCamera2/QCamera2Factory.cpp: * @halVersion: Based on camera_module_t.common.module_api_version
device/huawei/angler/camera/QCamera2/QCamera2Factory.cpp: * @halVersion: Based on camera_module_t.common.module_api_version
device/huawei/angler/camera/QCamera2/QCamera2Factory.h:extern camera_module_t HAL_MODULE_INFO_SYM;
device/huawei/angler/camera/QCamera2/QCamera2Hal.cpp:camera_module_t HAL_MODULE_INFO_SYM = {
device/google/marlin/camera/QCamera2/QCamera2Factory.cpp: * @halVersion: Based on camera_module_t.common.module_api_version
device/google/marlin/camera/QCamera2/QCamera2Factory.cpp: * @halVersion: Based on camera_module_t.common.module_api_version
device/google/marlin/camera/QCamera2/QCamera2Factory.h:extern camera_module_t HAL_MODULE_INFO_SYM;
device/google/marlin/camera/QCamera2/QCamera2Hal.cpp:camera_module_t HAL_MODULE_INFO_SYM = {
device/generic/goldfish/camera/EmulatedBaseCamera.h: * are common across all versions of the camera_device_t/camera_module_t
device/generic/goldfish/camera/EmulatedBaseCamera.h: * This method is called in response to camera_module_t::get_camera_info
device/generic/goldfish/camera/EmulatedCameraFactory.h: * - camera_module_t::get_number_of_cameras entry point
device/generic/goldfish/camera/EmulatedCameraFactory.h: * - camera_module_t::get_camera_info entry point
device/generic/goldfish/camera/EmulatedCameraFactory.h: * This method is called in response to camera_module_t::get_camera_info callback.
device/generic/goldfish/camera/EmulatedCameraFactory.h: * This method is called in response to camera_module_t::set_callbacks callback.
device/generic/goldfish/camera/EmulatedCameraFactory.h: * This method is called in response to camera_module_t::get_vendor_tag_ops callback.
device/generic/goldfish/camera/EmulatedCameraFactory.h: /* camera_module_t::get_number_of_cameras callback entry point. */
device/generic/goldfish/camera/EmulatedCameraFactory.h: /* camera_module_t::get_camera_info callback entry point. */
device/generic/goldfish/camera/EmulatedCameraFactory.h: /* camera_module_t::set_callbacks callback entry point. */
device/generic/goldfish/camera/EmulatedCameraFactory.h: /* camera_module_t::get_vendor_tag_ops callback entry point */
device/generic/goldfish/camera/EmulatedCameraFactory.h: /* camera_module_t::open_legacy callback entry point */
device/generic/goldfish/camera/EmulatedCameraFactory.cpp:extern camera_module_t HAL_MODULE_INFO_SYM;
device/generic/goldfish/camera/EmulatedBaseCamera.cpp: * camera_device_t/camera_module_t structures.
device/generic/goldfish/camera/EmulatedCameraHal.cpp:camera_module_t HAL_MODULE_INFO_SYM = {
device/lge/bullhead/camera/QCamera2/QCamera2Factory.cpp: * @halVersion: Based on camera_module_t.common.module_api_version
device/lge/bullhead/camera/QCamera2/QCamera2Factory.cpp: * @halVersion: Based on camera_module_t.common.module_api_version
device/lge/bullhead/camera/QCamera2/QCamera2Factory.h:extern camera_module_t HAL_MODULE_INFO_SYM;
device/lge/bullhead/camera/QCamera2/QCamera2Hal.cpp:camera_module_t HAL_MODULE_INFO_SYM = {
这里就看一下device/google/marlin/camera/QCamera2/QCamera2Hal.cpp文件源码,定义了open_legacy和set_callbacks等函数、定义了hw_module_t 和camera_module_t 结构体。
// Camera dependencies
#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 = NULL,
.set_torch_mode = qcamera::QCamera2Factory::set_torch_mode,
.init = NULL,
.reserved = {0}
};
我们根据之前mModule->open_legacy来找,camera_module_t结构体中定义的.open_legacy。发现这里定义的是NUll,所以接着找device/google之外的其他三个目录,发现也是一样。其实如果在\hardware\interfaces\camera\device\1.0\default\CameraDevice.cpp中如果走的是mModule->common.methods->open,那么就好找多了,直接就能找到&qcamera::QCamera2Factory::mModuleMethods再对应去找open函数。
所以还需接着在hardware中搜索一下吧。
hardware/libhardware/modules/usbcamera/CameraHAL.cpp:camera_module_t HAL_MODULE_INFO_SYM __attribute__ ((visibility("default"))) = {
hardware/libhardware/modules/camera/3_4/v4l2_camera_hal.h:extern camera_module_t HAL_MODULE_INFO_SYM;
hardware/libhardware/modules/camera/3_4/v4l2_camera_hal.cpp:camera_module_t HAL_MODULE_INFO_SYM __attribute__((visibility("default"))) = {
hardware/libhardware/modules/camera/3_0/CameraHAL.cpp:camera_module_t HAL_MODULE_INFO_SYM __attribute__ ((visibility("default"))) = {
hardware/libhardware/include/hardware/camera.h: * Camera modules that implement version 2.0 or higher of camera_module_t must
看到hardware/libhardware/modules/camera/3_4/v4l2_camera_hal.cpp文件中的定义:
camera_module_t HAL_MODULE_INFO_SYM __attribute__((visibility("default"))) = {
.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 = "V4L2 Camera HAL v3",
.author = "The Android Open Source Project",
.methods = &v4l2_module_methods,
.dso = nullptr,
.reserved = {0},
},
.get_number_of_cameras = v4l2_camera_hal::get_number_of_cameras,
.get_camera_info = v4l2_camera_hal::get_camera_info,
.set_callbacks = v4l2_camera_hal::set_callbacks,
.get_vendor_tag_ops = v4l2_camera_hal::get_vendor_tag_ops,
.open_legacy = v4l2_camera_hal::open_legacy,
.set_torch_mode = v4l2_camera_hal::set_torch_mode,
.init = nullptr,
.reserved = {nullptr, nullptr, nullptr, nullptr, nullptr}};
在看v4l2_camera_hal::open_legacy。
static int open_legacy(const hw_module_t* module,
const char* id,
uint32_t halVersion,
hw_device_t** device) {
return gCameraHAL.openLegacy(module, id, halVersion, device);
}
// Default global camera hal.
static V4L2CameraHAL gCameraHAL;
int V4L2CameraHAL::openLegacy(const hw_module_t* module,
const char* id,
uint32_t halVersion,
hw_device_t** device) {
HAL_LOG_ENTER();
// Not supported.
return -ENOSYS;
}
看到Not supported,知道又找错地方了。哎。看了这个mtk的代码实现还是有些凌乱了。
那就看下\hardware\interfaces\camera\device\1.0\default\CameraDevice.cpp中如果走的是mModule->common.methods->open的情况吧,那么就回到了device\google\marlin\camera\QCamera2\QCamera2Hal.cpp中的common的定义,指向的是&qcamera::QCamera2Factory::mModuleMethods。
.methods = &qcamera::QCamera2Factory::mModuleMethods,
看到\device\google\marlin\camera\QCamera2\QCamera2Factory.cpp文件mModuleMethods的源码:
struct hw_module_methods_t QCamera2Factory::mModuleMethods = {
open: QCamera2Factory::camera_device_open,
};
再指向了camera_device_open:
int QCamera2Factory::camera_device_open(
const struct hw_module_t *module, const char *id,
struct hw_device_t **hw_device)
{
if (module != &HAL_MODULE_INFO_SYM.common) {
ALOGE("Invalid module. Trying to open %p, expect %p",
module, &HAL_MODULE_INFO_SYM.common);
return INVALID_OPERATION;
}
if (!id) {
ALOGE("Invalid camera id");
return BAD_VALUE;
}
return gQCamera2Factory->cameraDeviceOpen(atoi(id), hw_device);
}
再指向了cameraDeviceOpen:
int QCamera2Factory::cameraDeviceOpen(int camera_id,
struct hw_device_t **hw_device)
{
int rc = NO_ERROR;
if (camera_id < 0 || camera_id >= mNumOfCameras)
return -ENODEV;
if ( NULL == mHalDescriptors ) {
ALOGE("%s : Hal descriptor table is not initialized!", __func__);
return NO_INIT;
}
if ( mHalDescriptors[camera_id].device_version == CAMERA_DEVICE_API_VERSION_3_0 ) {
QCamera3HardwareInterface *hw = new QCamera3HardwareInterface(mHalDescriptors[camera_id].cameraId,
mCallbacks);
if (!hw) {
ALOGE("Allocation of hardware interface failed");
return NO_MEMORY;
}
rc = hw->openCamera(hw_device);
if (rc != 0) {
delete hw;
}
} else if (mHalDescriptors[camera_id].device_version == CAMERA_DEVICE_API_VERSION_1_0) {
QCamera2HardwareInterface *hw = new QCamera2HardwareInterface((uint32_t)camera_id);
if (!hw) {
ALOGE("Allocation of hardware interface failed");
return NO_MEMORY;
}
rc = hw->openCamera(hw_device);
if (rc != NO_ERROR) {
delete hw;
}
} else {
ALOGE("%s: Device version for camera id %d invalid %d",
__func__,
camera_id,
mHalDescriptors[camera_id].device_version);
return BAD_VALUE;
}
return rc;
}
cameraDeviceOpen函数先判断了camera id是否正常,再通过判断不同的hal版本,拿到HardwareInterface,再去调用openCamera。这里就看下CAMERA_DEVICE_API_VERSION_1_0这种情况吧,它拿到的是QCamera2HardwareInterface。路径在device\google\marlin\camera\QCamera2\HAL\QCamera2HWI.cpp中。看他的openCamera函数。
int QCamera2HardwareInterface::openCamera(struct hw_device_t **hw_device)
{
KPI_ATRACE_CALL();
int rc = NO_ERROR;
if (mCameraOpened) {
*hw_device = NULL;
LOGE("Permission Denied");
return PERMISSION_DENIED;
}
LOGI("[KPI Perf]: E PROFILE_OPEN_CAMERA camera id %d",
mCameraId);
m_perfLock.lock_acq_timed(CAMERA_OPEN_PERF_TIME_OUT);
rc = openCamera();
if (rc == NO_ERROR){
*hw_device = &mCameraDevice.common;
if (m_thermalAdapter.init(this) != 0) {
LOGW("Init thermal adapter failed");
}
}
else
*hw_device = NULL;
LOGI("[KPI Perf]: X PROFILE_OPEN_CAMERA camera id %d, rc: %d",
mCameraId, rc);
return rc;
}
调用到openCamera():
int QCamera2HardwareInterface::openCamera()
{
int32_t rc = NO_ERROR;
char value[PROPERTY_VALUE_MAX];
if (mCameraHandle) {
LOGE("Failure: Camera already opened");
return ALREADY_EXISTS;
}
rc = QCameraFlash::getInstance().reserveFlashForCamera(mCameraId);
if (rc < 0) {
LOGE("Failed to reserve flash for camera id: %d",
mCameraId);
return UNKNOWN_ERROR;
}
// alloc param buffer
DeferWorkArgs args;
memset(&args, 0, sizeof(args));
mParamAllocJob = queueDeferredWork(CMD_DEF_PARAM_ALLOC, args);
if (mParamAllocJob == 0) {
LOGE("Failed queueing PARAM_ALLOC job");
return -ENOMEM;
}
if (gCamCapability[mCameraId] != NULL) {
// allocate metadata buffers
DeferWorkArgs args;
DeferMetadataAllocArgs metadataAllocArgs;
memset(&args, 0, sizeof(args));
memset(&metadataAllocArgs, 0, sizeof(metadataAllocArgs));
uint32_t padding =
gCamCapability[mCameraId]->padding_info.plane_padding;
metadataAllocArgs.size = PAD_TO_SIZE(sizeof(metadata_buffer_t),
padding);
metadataAllocArgs.bufferCnt = CAMERA_MIN_METADATA_BUFFERS;
args.metadataAllocArgs = metadataAllocArgs;
mMetadataAllocJob = queueDeferredWork(CMD_DEF_METADATA_ALLOC, args);
if (mMetadataAllocJob == 0) {
LOGE("Failed to allocate metadata buffer");
rc = -ENOMEM;
goto error_exit1;
}
rc = camera_open((uint8_t)mCameraId, &mCameraHandle);
if (rc) {
LOGE("camera_open failed. rc = %d, mCameraHandle = %p",
rc, mCameraHandle);
goto error_exit2;
}
mCameraHandle->ops->register_event_notify(mCameraHandle->camera_handle,
camEvtHandle,
(void *) this);
} else {
LOGH("Capabilities not inited, initializing now.");
rc = camera_open((uint8_t)mCameraId, &mCameraHandle);
if (rc) {
LOGE("camera_open failed. rc = %d, mCameraHandle = %p",
rc, mCameraHandle);
goto error_exit2;
}
if(NO_ERROR != initCapabilities(mCameraId,mCameraHandle)) {
LOGE("initCapabilities failed.");
rc = UNKNOWN_ERROR;
goto error_exit3;
}
mCameraHandle->ops->register_event_notify(mCameraHandle->camera_handle,
camEvtHandle,
(void *) this);
}
// Init params in the background
// 1. It's safe to queue init job, even if alloc job is not yet complete.
// It will be queued to the same thread, so the alloc is guaranteed to
// finish first.
// 2. However, it is not safe to begin param init until after camera is
// open. That is why we wait until after camera open completes to schedule
// this task.
memset(&args, 0, sizeof(args));
mParamInitJob = queueDeferredWork(CMD_DEF_PARAM_INIT, args);
if (mParamInitJob == 0) {
LOGE("Failed queuing PARAM_INIT job");
rc = -ENOMEM;
goto error_exit3;
}
mCameraOpened = true;
//Notify display HAL that a camera session is active.
//But avoid calling the same during bootup because camera service might open/close
//cameras at boot time during its initialization and display service will also internally
//wait for camera service to initialize first while calling this display API, resulting in a
//deadlock situation. Since boot time camera open/close calls are made only to fetch
//capabilities, no need of this display bw optimization.
//Use "service.bootanim.exit" property to know boot status.
property_get("service.bootanim.exit", value, "0");
if (atoi(value) == 1) {
pthread_mutex_lock(&gCamLock);
if (gNumCameraSessions++ == 0) {
setCameraLaunchStatus(true);
}
pthread_mutex_unlock(&gCamLock);
}
memset(value, 0, sizeof(value));
property_get("persist.camera.cache.optimize", value, "1");
m_bOptimizeCacheOps = atoi(value);
return NO_ERROR;
error_exit3:
if(mJpegClientHandle) {
deinitJpegHandle();
}
mCameraHandle->ops->close_camera(mCameraHandle->camera_handle);
mCameraHandle = NULL;
error_exit2:
waitDeferredWork(mMetadataAllocJob);
error_exit1:
waitDeferredWork(mParamAllocJob);
return rc;
}
关键的实现rc = camera_open((uint8_t)mCameraId, &mCameraHandle);,也有error_exit处理机制。
在\device\google\marlin\camera\QCamera2\stack\mm-camera-interface\src中搜索到了camera_open函数的声明。mm_camera_interface.c中的camera_open函数。
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
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之前进行相关初始化操作,如调用malloc、memset进行内存分配操作。所以又到了
mm_camera_open(cam_obj)函数,定义在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;
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);
if (my_obj->ctrl_fd < 0) {
LOGE("cannot open control fd of '%s' (%s)\n",
dev_name, strerror(l_errno));
if (l_errno == EBUSY)
rc = -EUSERS;
else
rc = -1;
goto on_error;
} else {
mm_camera_get_session_id(my_obj, &my_obj->sessionid);
LOGH("Camera Opened id = %d sessionid = %d", cam_idx, my_obj->sessionid);
}
#ifdef DAEMON_PRESENT
/* open domain socket*/
n_try = MM_CAMERA_DEV_OPEN_TRIES;
do {
n_try--;
my_obj->ds_fd = mm_camera_socket_create(cam_idx, MM_CAMERA_SOCK_TYPE_UDP);
l_errno = errno;
LOGD("ds_fd = %d, errno = %d", my_obj->ds_fd, l_errno);
if((my_obj->ds_fd >= 0) || (n_try <= 0 )) {
LOGD("opened, break out while loop");
break;
}
LOGD("failed with I/O error retrying after %d milli-seconds",
sleep_msec);
usleep(sleep_msec * 1000U);
} while (n_try > 0);
if (my_obj->ds_fd < 0) {
LOGE("cannot open domain socket fd of '%s'(%s)\n",
dev_name, strerror(l_errno));
rc = -1;
goto on_error;
}
#else /* DAEMON_PRESENT */
cam_status_t cam_status;
cam_status = mm_camera_module_open_session(my_obj->sessionid,
mm_camera_module_event_handler);
if (cam_status < 0) {
LOGE("Failed to open session");
if (cam_status == CAM_STATUS_BUSY) {
rc = -EUSERS;
} else {
rc = -1;
}
goto on_error;
}
#endif /* DAEMON_PRESENT */
pthread_mutex_init(&my_obj->msg_lock, NULL);
pthread_mutex_init(&my_obj->cb_lock, NULL);
pthread_mutex_init(&my_obj->evt_lock, NULL);
PTHREAD_COND_INIT(&my_obj->evt_cond);
LOGD("Launch evt Thread in Cam Open");
snprintf(my_obj->evt_thread.threadName, THREAD_NAME_SIZE, "CAM_Dispatch");
mm_camera_cmd_thread_launch(&my_obj->evt_thread,
mm_camera_dispatch_app_event,
(void *)my_obj);
/* launch event poll thread
* we will add evt fd into event poll thread upon user first register for evt */
LOGD("Launch evt Poll Thread in Cam Open");
snprintf(my_obj->evt_poll_thread.threadName, THREAD_NAME_SIZE, "CAM_evntPoll");
mm_camera_poll_thread_launch(&my_obj->evt_poll_thread,
MM_CAMERA_POLL_TYPE_EVT);
mm_camera_evt_sub(my_obj, TRUE);
/* unlock cam_lock, we need release global intf_lock in camera_open(),
* in order not block operation of other Camera in dual camera use case.*/
pthread_mutex_unlock(&my_obj->cam_lock);
LOGD("end (rc = %d)\n", rc);
return rc;
on_error:
if (NULL == dev_name_value) {
LOGE("Invalid device name\n");
rc = -1;
}
if (NULL == my_obj) {
LOGE("Invalid camera object\n");
rc = -1;
} else {
if (my_obj->ctrl_fd >= 0) {
close(my_obj->ctrl_fd);
my_obj->ctrl_fd = -1;
}
#ifdef DAEMON_PRESENT
if (my_obj->ds_fd >= 0) {
mm_camera_socket_close(my_obj->ds_fd);
my_obj->ds_fd = -1;
}
#endif
}
/* unlock cam_lock, we need release global intf_lock in camera_open(),
* in order not block operation of other Camera in dual camera use case.*/
pthread_mutex_unlock(&my_obj->cam_lock);
return rc;
}
这个函数首先就是获取设备名称dev_name_value = mm_camera_util_get_dev_name(my_obj->my_hdl);,然后定义了一个值n_try,意义表示的是camera open的尝试次数,定义是20。
device/google/marlin/camera/QCamera2/stack/mm-camera-interface/inc/mm_camera.h:#define MM_CAMERA_DEV_OPEN_TRIES 20
int8_t n_try=MM_CAMERA_DEV_OPEN_TRIES;
然后执行了do{my_obj->ctrl_fd = open(dev_name, O_RDWR | O_NONBLOCK); }while (n_try > 0);循环,知道n_try次数尝试完毕。my_obj->ctrl_fd = open(dev_name, O_RDWR | O_NONBLOCK);这个就是实际打开camera的操作,do逻辑代码里面,判断满足if((my_obj->ctrl_fd >= 0) || (errno != EIO && errno != ETIMEDOUT) || (n_try <= 0 ))任意条件就可以break跳出循环,其中(my_obj->ctrl_fd >= 0)表示的camera open成功,没有出现异常,error表示出现了超时连接或者IO流异常,n_try表明open尝试次数已经用完,三种跳出循环的情况。从这看底层对于openCamera也是做了多次尝试连接的保险操作的。
而my_obj->ctrl_fd = open(dev_name, O_RDWR | O_NONBLOCK)中的open就是属于系统函数的调用了,会调用到驱动内核层来实现处理。流程差不多就结束了,后面到驱动层内核层了。
再回到QCamera2Hal.cpp中,虽然camera_module_t中openLegacy定义为null,但是在QCamera2Factory.cpp里面还是定义了openLegacy函数的。
int QCamera2Factory::open_legacy(const struct hw_module_t* module,
const char* id, uint32_t halVersion, struct hw_device_t** device)
{
if (module != &HAL_MODULE_INFO_SYM.common) {
ALOGE("Invalid module. Trying to open %p, expect %p",
module, &HAL_MODULE_INFO_SYM.common);
return INVALID_OPERATION;
}
if (!id) {
ALOGE("Invalid camera id");
return BAD_VALUE;
}
return gQCamera2Factory->openLegacy(atoi(id), halVersion, device);
}
然后看到,函数中,就只针对CAMERA_DEVICE_API_VERSION_1_0来了,而流程与上一段一致了调用hw->openCamera。
int QCamera2Factory::openLegacy(
int32_t cameraId, uint32_t halVersion, struct hw_device_t** hw_device)
{
int rc = NO_ERROR;
ALOGI(":%s openLegacy halVersion: %d", __func__, halVersion);
//Assumption: all cameras can support legacy API version
if (cameraId < 0 || cameraId >= gQCamera2Factory->getNumberOfCameras())
return -ENODEV;
switch(halVersion)
{
case CAMERA_DEVICE_API_VERSION_1_0:
{
QCamera2HardwareInterface *hw =
new QCamera2HardwareInterface((uint32_t)cameraId);
if (!hw) {
ALOGE("%s: Allocation of hardware interface failed", __func__);
return NO_MEMORY;
}
rc = hw->openCamera(hw_device);
if (rc != NO_ERROR) {
delete hw;
}
break;
}
default:
ALOGE("%s: Device API version: %d for camera id %d invalid",
__func__, halVersion, cameraId);
return BAD_VALUE;
}
return rc;
}
接着往下连接到底层驱动。camera_module_t的实现还是与厂商的实现方式有很大关系了。
总的来说,openCamera的流程确实是很复杂麻烦了,不过日常工作上,从framework层到ap流程上一般不会出现问题,我们从af方向上debug了解这些基本就可以了,而driver到hal也需要专门的分析人员了。camera的流程繁杂,简单的架构我们也许可以说清楚,但是越往下走越觉得需要了解的越多,知识是无涯的,还是要不断学习啊。