1 CameraManager.openCamera分析
frameworks/base/core/java/android/hardware/camera2/CameraManager.java)
public void openCamera(@NonNull String cameraId, @NonNull final CameraDevice.StateCallback callback, @Nullable Handler handler) throws CameraAccessException {
openCameraForUid(cameraId, callback,
CameraDeviceImpl.checkAndWrapHandler(handler),
USE_CALLING_UID);
}
其会调用:
private CameraDevice openCameraDeviceUserAsync(String cameraId, CameraDevice.StateCallback callback, Executor executor, final int uid) throws CameraAccessException {
CameraCharacteristics characteristics = getCameraCharacteristics(cameraId);
CameraDevice device = null;
................
ICameraDeviceUser cameraUser = null;
// step 1
android.hardware.camera2.impl.CameraDeviceImpl deviceImpl =
new android.hardware.camera2.impl.CameraDeviceImpl(
cameraId, callback, executor,
characteristics,
mContext.getApplicationInfo().targetSdkVersion);
ICameraDeviceCallbacks callbacks = deviceImpl.getCallbacks();
if (supportsCamera2ApiLocked(cameraId)) {
ICameraService cameraService = CameraManagerGlobal.get().getCameraService();
................
// step 2
cameraUser = cameraService.connectDevice(callbacks,
cameraId,
mContext.getOpPackageName(),
uid);
}
................
// step 3
deviceImpl.setRemoteDevice(cameraUser);
device = deviceImpl;
return device;
}
上述调用可以总结为三步:
- 构建CameraDeviceImpl;
- 得到CameraService代理,并调用connectDevice,并获得实现了ICameraDeviceUser接口的对象(实际类型是CameraDeviceClient);
- CameraDeviceImpl调用setRemoteDevice,触发onOpened的回调给app;onOpened将把本阶段创建的CameraDeviceImpl对象抛送给app。
2 openCamera各个步骤分析
2.1 【step 1】构造CameraDeviceImpl
step1中直接调用构造器创建CameraDeviceImpl:
public CameraDeviceImpl(String cameraId, StateCallback callback,
Executor executor,
CameraCharacteristics characteristics,
int appTargetSdkVersion)
{
mCameraId = cameraId;
mDeviceCallback = callback;
mDeviceExecutor = executor;
mCharacteristics = characteristics;
mAppTargetSdkVersion = appTargetSdkVersion;
...............
}
app传入的callback赋值给了mDeviceCallback;
在3.5中,camera在打开后,mDeviceCallback会给app提供回调。
2.2 【step 2】CameraService::connectDevice
调用connectDevice,通过aidl,进行了一次跨进程通信:
frameworks/av/services/camera/libcameraservice/CameraService.cpp)
Status CameraService::connectDevice(
const sp<hardware::camera2::ICameraDeviceCallbacks>& cameraCb,
const String16& cameraId,
const String16& clientPackageName,
int clientUid,
// device作为输出参数,即java层connectDevice的返回值
/*out*/sp<hardware::camera2::ICameraDeviceUser>* device)
{
Status ret = Status::ok();
String8 id = String8(cameraId);
sp<CameraDeviceClient> client = nullptr;
// <CALLBACK, CLIENT = CameraDeviceClient>为泛型模板类
ret = connectHelper<hardware::camera2::ICameraDeviceCallbacks,CameraDeviceClient>
(cameraCb, id, /*api1CameraId*/-1,
CAMERA_HAL_API_VERSION_UNSPECIFIED, clientPackageName,
clientUid, USE_CALLING_PID, API_2,
/*legacyMode*/ false, /*shimUpdateOnly*/ false,
/*out*/client);
*device = client;
return ret;
}
将调用connectHelper:
Status CameraService::connectHelper(
const sp<CALLBACK>& cameraCb, const String8& cameraId,
/*-1*/int api1CameraId, /*UNSPECIFIED*/int halVersion,
const String16& clientPackageName,
int clientUid, int clientPid, /*API_2*/apiLevel effectiveApiLevel,
/*false*/bool legacyMode, /*false*/bool shimUpdateOnly,
/*out*/sp<CLIENT>& device)
{
binder::Status ret = binder::Status::ok();
String8 clientName8(clientPackageName);
int originalClientPid = 0;
// CLIENT = CameraDeviceClient
sp<CLIENT> client = nullptr;
................
int facing = -1;
// step 1:获取指定id的camera设备版本
int deviceVersion = getDeviceVersion(cameraId, /*out*/&facing);
sp<BasicClient> tmp = nullptr;
// step 2:创建CameraDeviceClient对象(最后的输出对象)
if(!(ret = makeClient(this, cameraCb, clientPackageName,
cameraId, /*-1*/api1CameraId, facing,
clientPid, clientUid, getpid(),
/*false*/legacyMode, /*UNSPECIFIED*/halVersion,
deviceVersion, /*API_2*/effectiveApiLevel,
/*out*/&tmp)).isOk())
{
return ret;
}
client = static_cast<CLIENT*>(tmp.get());
// step 3:初始化CameraDeviceClient
err = client->initialize(mCameraProviderManager, mMonitorTags);
................
// 设置输出参数
device = client;
return ret;
}
综上,CameraService::connectDevice也可大致分为三个步骤:
- 根据id获取设备版本;
- 创建CameraDeviceClient对象;
- CameraDeviceClient初始化。
(2.2-1) connectHelper::step1--根据id获取设备版本
CameraService::getDeviceVersion(const String8& cameraId, int* facing) {
int deviceVersion = 0;
status_t res;
hardware::hidl_version maxVersion{0,0};
// CameraProviderManager封装了device的信息
// 其会根据id找到对应的device,并赋值
res = mCameraProviderManager->getHighestSupportedVersion(
cameraId.string(), &maxVersion);
deviceVersion = HARDWARE_DEVICE_API_VERSION(maxVersion.get_major(), maxVersion.get_minor());
hardware::CameraInfo info;
// -1
if (facing) {
................
}
return deviceVersion;
}
根据id从CameraProviderManager找到设备,并获得其version信息。
CameraService初始化时,同时会初始化CameraProviderManager,其会从hal层获取设备信息,并缓存。
该过程可参考下述文章:[Android]Camera2——(1) camera模块初始化
(2.2-2) connectHelper::step2--makeClient创建CameraDeviceClient
Status CameraService::makeClient(const sp<CameraService>& cameraService,
const sp<IInterface>& cameraCb, const String16& packageName, const String8& cameraId,
/*-1*/int api1CameraId, int facing, int clientPid, uid_t clientUid, int servicePid,
/*false*/bool legacyMode, /*UNSPECIFIED*/int halVersion, int deviceVersion, /*API_2*/apiLevel effectiveApiLevel,
/*out*/sp<BasicClient>* client)
{
// halVersion为UNSPECIFIED, 数值为-1
if (halVersion < 0 || halVersion == deviceVersion) {
switch(deviceVersion) {
................
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
................
} else { // Camera2 API route
sp<hardware::camera2::ICameraDeviceCallbacks> tmp =
static_cast<hardware::camera2::ICameraDeviceCallbacks*>(cameraCb.get());
// 构建CameraDeviceClient
*client = new CameraDeviceClient(cameraService, tmp, packageName, cameraId,
facing, clientPid, clientUid, servicePid);
}
break;
................
} //switch ends
} else {
................
}
return Status::ok();
}
makeClient实际根据版本信息,创建了CameraDeviceClient对象。
step 3是CameraDeviceClient初始化。在3.3、3.4中,了解CameraDeviceClient的同时,了解其初始化流程。
2.3 CameraDeviceClient构造、初始化
(2.3-1) CameraDeviceClient构造
类声明如下:
class CameraDeviceClient :
public Camera2ClientBase<CameraDeviceClientBase>,
public camera2::FrameProcessorBase::FilteredListener
{
...............
}
父类Camera2ClientBase传入的泛型类实例为CameraDeviceClientBase。
CameraDeviceClient::CameraDeviceClient(const sp<CameraService>& cameraService,
const sp<hardware::camera2::ICameraDeviceCallbacks>& remoteCallback,
const String16& clientPackageName,
const String8& cameraId,
int cameraFacing,
int clientPid,
uid_t clientUid,
int servicePid) :
Camera2ClientBase(cameraService, remoteCallback, clientPackageName,
cameraId, /*API1 camera ID*/ -1,
cameraFacing, clientPid, clientUid, servicePid),
mInputStream(),
mStreamingRequestId(REQUEST_ID_NONE),
mRequestIdCounter(0)
{
ATRACE_CALL();
ALOGI("CameraDeviceClient %s: Opened", cameraId.string());
}
CameraDeviceClient构造中,主要调用了父类Camera2ClientBase的构造。
(2.3-2) Camera2ClientBase构造,创建Camera3Device内部对象
// TClientBase实际为CameraDeviceClientBase
template <typename TClientBase>
Camera2ClientBase<TClientBase>::Camera2ClientBase(
const sp<CameraService>& cameraService,
const sp<TCamCallbacks>& remoteCallback,
const String16& clientPackageName,
const String8& cameraId,
int api1CameraId,
int cameraFacing,
int clientPid,
uid_t clientUid,
int servicePid)
:
TClientBase(cameraService, remoteCallback, clientPackageName,
cameraId, api1CameraId, cameraFacing, clientPid, clientUid,
servicePid),
mSharedCameraCallbacks(remoteCallback),
mDeviceVersion(cameraService->getDeviceVersion(TClientBase::mCameraIdStr)),
mDeviceActive(false),
mApi1CameraId(api1CameraId)
{
mInitialClientPid = clientPid;
mDevice = new Camera3Device(cameraId);
}
父类中,主要构造了Camera3Device。
(2.3-3) CameraDeviceClient初始化
在(3.2-1)中已经看到,当CameraDeviceClient被创建后,即调用initialize()初始化。
status_t CameraDeviceClient::initialize(sp<CameraProviderManager> manager,
const String8& monitorTags)
{
return initializeImpl(manager, monitorTags);
}
继续调用initializeImpl:
template<typename TProviderPtr>
status_t CameraDeviceClient::initializeImpl(TProviderPtr providerPtr, const String8& monitorTags)
{
status_t res;
res = Camera2ClientBase::initialize(providerPtr, monitorTags);
String8 threadName;
mFrameProcessor = new FrameProcessorBase(mDevice);
threadName = String8::format("CDU-%s-FrameProc", mCameraIdStr.string());
mFrameProcessor->run(threadName.string());
mFrameProcessor->registerListener(FRAME_PROCESSOR_LISTENER_MIN_ID,
FRAME_PROCESSOR_LISTENER_MAX_ID,
/*listener*/this,
/*sendPartials*/true);
................
return OK;
}
主要调用了父类的initialize方法,并初始化了FrameProcessor。
(2.3-4) Camera2ClientBase::initialize--初始化Camera3Device
最终会调用Camera2ClientBase::initializeImpl:
template <typename TClientBase>
template <typename TProviderPtr>
status_t Camera2ClientBase<TClientBase>::initializeImpl(TProviderPtr providerPtr,
const String8& monitorTags)
{
status_t res;
// Verify ops permissions
res = TClientBase::startCameraOps();
// Camera3Device
res = mDevice->initialize(providerPtr, monitorTags);
wp<CameraDeviceBase::NotificationListener> weakThis(this);
res = mDevice->setNotifyCallback(weakThis);
return OK;
}
实际上初始化Camera3Device,并传入了CameraProviderManager。
2.4 Camera3Device构造、初始化
(2.4-1) Camera3Device构造
Camera3Device::Camera3Device(const String8 &id):
mId(id),
mOperatingMode(NO_MODE),
mIsConstrainedHighSpeedConfiguration(false),
mStatus(STATUS_UNINITIALIZED),
mStatusWaiters(0),
mUsePartialResult(false),
mNumPartialResults(1),
mTimestampOffset(0),
mNextResultFrameNumber(0),
mNextReprocessResultFrameNumber(0),
mNextShutterFrameNumber(0),
mNextReprocessShutterFrameNumber(0),
mListener(NULL),
mVendorTagId(CAMERA_METADATA_INVALID_VENDOR_ID),
mLastTemplateId(-1)
{
camera3_callback_ops::notify = &sNotify;
camera3_callback_ops::process_capture_result = &sProcessCaptureResult;
}
初始化内部域,并指定了两个hal的回调函数。
(2.4-2) 初始化Camera3Device,创建当前camera会话
status_t Camera3Device::initialize(sp<CameraProviderManager> manager, const String8& monitorTags) {
Mutex::Autolock il(mInterfaceLock);
Mutex::Autolock l(mLock);
ALOGV("%s: Initializing HIDL device for camera %s", __FUNCTION__, mId.string());
................
sp<ICameraDeviceSession> session;
// openSession会通过camera id找到CameraProviderManager初始化时缓存的camera设备
// hal层的CameraDevice会调用open方法,通过camera module获得camera3_device_t*
// 创建CameraDeviceSession,代表当前camera会话,并返回给framework
status_t res = manager->openSession(mId.string(), this, /*out*/ &session);
................
res = manager->getCameraCharacteristics(mId.string(), &mDeviceInfo);
................
................
// queue为RequestMetadataQueue
// 通过hidl接口从CameraDeviceSession获得
mInterface = new HalInterface(session, queue);
................
return initializeCommonLocked();
}
Camera3Device::initialize的流程可简述为如下:
step 1:CameraProviderManager::openSession,其内部通过cameraId找到CameraProviderManager初始化时缓存的camera设备信息(hal层CameraDevice的远程接口);#[Android]Camera2——(1) camera模块初始化
step 2:hal的CameraDevice内部持有CameraModule(camera驱动封装),CameraDevice调用open;
step 3:CameraDevice::open通过CameraModule获得cameraId所代表的camera硬件设备索引camera3_device_t*,通过该索引创建CameraDeviceSession,代表当前camera会话,返回给framework;
step 4:在Camera3Device内部封装HalInterface对象,其内部会持有CameraDeviceSession的远程代理;
step 5:调用initializeCommonLocked(),其中涉及到过多细节,暂不在这里累述。
综上,3.3和3.4详述了3.2-step3中提及到的CameraDeviceClient初始化。
2.5 【step 3】CameraDeviceImpl::setRemoteDevice产生onOpened回调
回到应用层的CameraDeviceImpl:
// 输入参数为CameraDeviceClient的代理
public void setRemoteDevice(ICameraDeviceUser remoteDevice) throws CameraAccessException {
synchronized(mInterfaceLock) {
................
mRemoteDevice = new ICameraDeviceUserWrapper(remoteDevice);
................
mDeviceExecutor.execute(mCallOnOpened);
mDeviceExecutor.execute(mCallOnUnconfigured);
}
}
mCallOnOpened是一个runnable:
private final Runnable mCallOnOpened = new Runnable() {
@Override
public void run() {
StateCallbackKK sessionCallback = null;
synchronized(mInterfaceLock) {
if (mRemoteDevice == null) return; // Camera already closed
sessionCallback = mSessionStateCallback;
}
if (sessionCallback != null) {
sessionCallback.onOpened(CameraDeviceImpl.this);
}
// mDeviceCallback将onOpened的回调提供给app
mDeviceCallback.onOpened(CameraDeviceImpl.this);
}
};
mDeviceCallback将onOpened的回调提供给app。
3 打开camera简易时序图
4 camera2架构中各类层级整理
下图来自Android官网,用于加深对openCamera过程中各个模块的理解: