这篇文章主要是介绍Camera2中openCamera
函数的执行过程, 下面开始一起看源码吧!
在开发中我们要使用Camera需要先获取一个CameraManager,获取到CameraManager 通过openCamera
函数打开Camera
frameworks/base/core/java/android/hardware/camera2/CameraManager.java
private static final int USE_CALLING_UID = -1;
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);
}
public void openCameraForUid(@NonNull String cameraId,
@NonNull final CameraDevice.StateCallback callback, @NonNull Executor executor,
int clientUid) throws CameraAccessException {
openCameraForUid(cameraId, callback, executor, clientUid, /*oomScoreOffset*/0,
shouldOverrideToPortrait(mContext));
}
public void openCameraForUid(@NonNull String cameraId,
@NonNull final CameraDevice.StateCallback callback, @NonNull Executor executor,
int clientUid, int oomScoreOffset, boolean overrideToPortrait)
throws CameraAccessException {
// 省略无关细节代码 .....
openCameraDeviceUserAsync(cameraId, callback, executor, clientUid, oomScoreOffset,
overrideToPortrait);
}
private CameraDevice openCameraDeviceUserAsync(String cameraId,
CameraDevice.StateCallback callback, Executor executor, final int uid,
final int oomScoreOffset, boolean overrideToPortrait) throws CameraAccessException {
// 获取指定Camera Id 的参数
CameraCharacteristics characteristics = getCameraCharacteristics(cameraId);
CameraDevice device = null;
// 获取所有物理Camera设备的参数
Map<String, CameraCharacteristics> physicalIdsToChars =
getPhysicalIdToCharsMap(characteristics);
synchronized (mLock) {
ICameraDeviceUser cameraUser = null;
// 创建CameraDeviceImpl
android.hardware.camera2.impl.CameraDeviceImpl deviceImpl =
new android.hardware.camera2.impl.CameraDeviceImpl(
cameraId,
callback,
executor,
characteristics,
physicalIdsToChars,
mContext.getApplicationInfo().targetSdkVersion,
mContext);
ICameraDeviceCallbacks callbacks = deviceImpl.getCallbacks();
try {
// 获取CameraService
ICameraService cameraService = CameraManagerGlobal.get().getCameraService();
if (cameraService == null) {
throw new ServiceSpecificException(
ICameraService.ERROR_DISCONNECTED,
"Camera service is currently unavailable");
}
// 连接Devices
cameraUser = cameraService.connectDevice(callbacks, cameraId,
mContext.getOpPackageName(), mContext.getAttributionTag(), uid,
oomScoreOffset, mContext.getApplicationInfo().targetSdkVersion,
overrideToPortrait);
} catch (ServiceSpecificException e) {
// 省略异常处理代码.....
// 这段异常处理的代码很大一部分都异常都会导致onDisconnected函数回调
} catch (RemoteException e) {
// 省略异常处理代码.....
}
deviceImpl.setRemoteDevice(cameraUser);
device = deviceImpl;
}
return device;
}
上面的代码是使用openCamera
函数Java部分启动过程,看到这里有几个问题,
- 为什么在调用
openCamera
函数的时候一定要在有handler的线程中调用? openCamera
函数成功调用后如何调用Callback ?
问题1:为什么在调用openCamera
函数的时候一定要在有handler的线程中调用?
在openCamera
函数中有这样一段代码CameraDeviceImpl.checkAndWrapHandler(handler)
下面看一下这个实现就会很清楚原因了
public static Executor checkAndWrapHandler(Handler handler) {
return new CameraHandlerExecutor(checkHandler(handler));
}
static Handler checkHandler(Handler handler) {
if (handler == null) {
Looper looper = Looper.myLooper();
if (looper == null) {
throw new IllegalArgumentException(
"No handler given, and current thread has no looper!");
}
handler = new Handler(looper);
}
return handler;
}
其实就是判断openCamera
函数调用时候传入的handler是否为null,如果为null 就获取一下当前线程的looper, 如果当前线程没有looper ,不满足条件,抛异常,否则就正常执行
问题2:openCamera
函数成功调用后如何调用Callback ?
首先要看一下CameraDeviceImpl.java
的构造函数
public CameraDeviceImpl(String cameraId, StateCallback callback, Executor executor,
CameraCharacteristics characteristics, int appTargetSdkVersion) {
if (cameraId == null || callback == null || executor == null || characteristics == null) {
throw new IllegalArgumentException("Null argument given");
}
mCameraId = cameraId;
mDeviceCallback = callback; // 回调
mDeviceExecutor = executor; // 执行任务
mCharacteristics = characteristics;
mAppTargetSdkVersion = appTargetSdkVersion; //
// 省略无关细节代码 .....
}
从构造函数中可以看到有mDeviceCallback
,mDeviceExecutor
回调和任务执行线程,
下面看一下deviceImpl.setRemoteDevice(cameraUser);
执行
public void setRemoteDevice(ICameraDeviceUser remoteDevice) throws CameraAccessException {
synchronized(mInterfaceLock) {
// TODO: Move from decorator to direct binder-mediated exceptions
// If setRemoteFailure already called, do nothing
if (mInError) return;
mRemoteDevice = new ICameraDeviceUserWrapper(remoteDevice);
IBinder remoteDeviceBinder = remoteDevice.asBinder();
// For legacy camera device, remoteDevice is in the same process, and
// asBinder returns NULL.
if (remoteDeviceBinder != null) {
try {
// 设置binder death 监听, 如果发生错误会回调 call back onDisconnected
remoteDeviceBinder.linkToDeath(this, /*flag*/ 0);
} catch (RemoteException e) {
CameraDeviceImpl.this.mDeviceExecutor.execute(mCallOnDisconnected);
throw new CameraAccessException(CameraAccessException.CAMERA_DISCONNECTED,
"The camera device has encountered a serious error");
}
}
// 执行打开成功回调
mDeviceExecutor.execute(mCallOnOpened);
mDeviceExecutor.execute(mCallOnUnconfigured);
mRemoteDeviceInit = true;
}
}
private final Runnable mCallOnOpened = new Runnable() {
@Override
public void run() {
StateCallbackKK sessionCallback = null;
synchronized(mInterfaceLock) {
// 检测camera 是否关闭
if (mRemoteDevice == null) return; // Camera already closed
sessionCallback = mSessionStateCallback;
}
if (sessionCallback != null) {
sessionCallback.onOpened(CameraDeviceImpl.this);
}
mDeviceCallback.onOpened(CameraDeviceImpl.this);
}
};
private final Runnable mCallOnDisconnected = new Runnable() {
@Override
public void run() {
StateCallbackKK sessionCallback = null;
synchronized(mInterfaceLock) {
// 检测camera 是否关闭
if (mRemoteDevice == null) return; // Camera already closed
sessionCallback = mSessionStateCallback;
}
if (sessionCallback != null) {
sessionCallback.onDisconnected(CameraDeviceImpl.this);
}
mDeviceCallback.onDisconnected(CameraDeviceImpl.this);
}
};
从上面代码可以很清楚看到,设置了binder death 监听, 如果发生错误会回调 callback的onDisconnected
函数, 如果Camera 已经关闭将不会回调, 当一切都正常执行后会回调打开成功回调。
App层打开逻辑比较好理解,看一下App层是怎么获取到CameraService
并且打开Camera的,在上面代码可以清晰看到
// Use cameraservice's cameradeviceclient implementation for HAL3.2+ devices
ICameraService cameraService = CameraManagerGlobal.get().getCameraService();
可以看到 CameraManagerGlobal
是个单例,在该单例中获取CameraService
,进一步查看代码
public ICameraService getCameraService() {
synchronized(mLock) {
connectCameraServiceLocked();
if (mCameraService == null && !sCameraServiceDisabled) {
Log.e(TAG, "Camera service is unavailable");
}
return mCameraService;
}
}
// 这个字符串是不是很熟悉, 在camera 开机初始化的时候见到过
private static final String CAMERA_SERVICE_BINDER_NAME = "media.camera";
private void connectCameraServiceLocked() {
// Only reconnect if necessary
if (mCameraService != null || sCameraServiceDisabled) return;
Log.i(TAG, "Connecting to camera service");
// 获取Camera 服务
IBinder cameraServiceBinder = ServiceManager.getService(CAMERA_SERVICE_BINDER_NAME);
if (cameraServiceBinder == null) {
// Camera service is now down, leave mCameraService as null
return;
}
try {
// 设置Camera 服务的bind death 监听
cameraServiceBinder.linkToDeath(this, /*flags*/ 0);
} catch (RemoteException e) {
// Camera service is now down, leave mCameraService as null
return;
}
ICameraService cameraService = ICameraService.Stub.asInterface(cameraServiceBinder);
// 省略无关代码....
try {
// 省略无关代码....
// 赋值mCameraService
mCameraService = cameraService;
} catch(ServiceSpecificException e) {
// Unexpected failure
throw new IllegalStateException("Failed to register a camera service listener", e);
} catch (RemoteException e) {
// Camera service is now down, leave mCameraService as null
}
// 省略无关代码....
}
上面代码通过binder通信,ServiceManager
获取到ICameraService
。
下面到CameraService
,下面看一下调用cameraService.connectDevice(callbacks, cameraId,mContext.getOpPackageName(), uid);
这个连接函数后在CameraService
中都做了什么。
CameraService
在framework中的位置:/frameworks/av/services/camera/libcameraservice/CameraService.cpp
看一下在CameraService.cpp
的实现:
Status CameraService::connectDevice(
const sp<hardware::camera2::ICameraDeviceCallbacks>& cameraCb,
const String16& cameraId,
const String16& clientPackageName,
const std::optional<String16>& clientFeatureId,
int clientUid, int oomScoreOffset, int targetSdkVersion,
bool overrideToPortrait,
/*out*/
sp<hardware::camera2::ICameraDeviceUser>* device) {
ATRACE_CALL();
Status ret = Status::ok();
String8 id = String8(cameraId);
sp<CameraDeviceClient> client = nullptr;
String16 clientPackageNameAdj = clientPackageName;
int callingPid = CameraThreadState::getCallingPid();
// 省略无关细节代码 .....
ret = connectHelper<hardware::camera2::ICameraDeviceCallbacks,CameraDeviceClient>(cameraCb, id,
/*api1CameraId*/-1, clientPackageNameAdj, systemNativeClient,clientFeatureId,
clientUid, USE_CALLING_PID, API_2, /*shimUpdateOnly*/ false, oomScoreOffset,
targetSdkVersion, overrideToPortrait, /*forceSlowJpegMode*/false,
/*out*/client);
// 省略无关细节代码 .....
*device = client;
// 省略无关细节代码 .....
return ret;
}
进入CameraService::connectHelper
看一下具体实现
// 3 second busy timeout when other clients are connecting
static const nsecs_t DEFAULT_CONNECT_TIMEOUT_NS = 3000000000;
template<class CALLBACK, class CLIENT>
Status CameraService::connectHelper(const sp<CALLBACK>& cameraCb, const String8& cameraId,
int api1CameraId, const String16& clientPackageNameMaybe, bool systemNativeClient,
const std::optional<String16>& clientFeatureId, int clientUid, int clientPid,
apiLevel effectiveApiLevel, bool shimUpdateOnly, int oomScoreOffset, int targetSdkVersion,
bool overrideToPortrait, bool forceSlowJpegMode,
/*out*/sp<CLIENT>& device) {
binder::Status ret = binder::Status::ok();
// 省略无关代码.....
String8 clientName8(clientPackageName);
int originalClientPid = 0;
// 省略无关代码.....
nsecs_t openTimeNs = systemTime();
sp<CLIENT> client = nullptr;
int facing = -1;
int orientation = 0;
{
// Acquire mServiceLock and prevent other clients from connecting
// 获取一个锁
std::unique_ptr<AutoConditionLock> lock =
AutoConditionLock::waitAndAcquire(mServiceLockWrapper, DEFAULT_CONNECT_TIMEOUT_NS);
if (lock == nullptr) {
ALOGE("CameraService::connect (PID %d) rejected (too many other clients connecting)."
, clientPid);
return STATUS_ERROR_FMT(ERROR_MAX_CAMERAS_IN_USE,
"Cannot open camera %s for \"%s\" (PID %d): Too many other clients connecting",
cameraId.string(), clientName8.string(), clientPid);
}
// Enforce client permissions and do basic validity checks
// 检查权限
if(!(ret = validateConnectLocked(cameraId, clientName8,
/*inout*/clientUid, /*inout*/clientPid, /*out*/originalClientPid)).isOk()) {
return ret;
}
// 省略无关代码.....
status_t err;
sp<BasicClient> clientTmp = nullptr;
std::shared_ptr<resource_policy::ClientDescriptor<String8, sp<BasicClient>>> partial;
// 检查当前启动Camera 请求的优先级
if ((err = handleEvictionsLocked(cameraId, originalClientPid, effectiveApiLevel,
IInterface::asBinder(cameraCb), clientName8, oomScoreOffset, systemNativeClient,
/*out*/&clientTmp, /*out*/&partial)) != NO_ERROR) {
switch (err) {
case -ENODEV:
return STATUS_ERROR_FMT(ERROR_DISCONNECTED,
"No camera device with ID \"%s\" currently available",
cameraId.string());
case -EBUSY:
return STATUS_ERROR_FMT(ERROR_CAMERA_IN_USE,
"Higher-priority client using camera, ID \"%s\" currently unavailable",
cameraId.string());
case -EUSERS:
return STATUS_ERROR_FMT(ERROR_MAX_CAMERAS_IN_USE,
"Too many cameras already open, cannot open camera \"%s\"",
cameraId.string());
default:
return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION,
"Unexpected error %s (%d) opening camera \"%s\"",
strerror(-err), err, cameraId.string());
}
}
// 省略无关代码.....
// 创建Camera连接
if(!(ret = makeClient(this, cameraCb, clientPackageName, systemNativeClient,
clientFeatureId, cameraId, api1CameraId, facing, orientation,
clientPid, clientUid, getpid(),
deviceVersionAndTransport, effectiveApiLevel, overrideForPerfClass,
overrideToPortrait, forceSlowJpegMode,
/*out*/&tmp)).isOk()) {
return ret;
}
client = static_cast<CLIENT*>(tmp.get());
LOG_ALWAYS_FATAL_IF(client.get() == nullptr, "%s: CameraService in invalid state",
__FUNCTION__);
String8 monitorTags = isClientWatched(client.get()) ? mMonitorTags : String8("");
// 初始化当前Camera 连接
err = client->initialize(mCameraProviderManager, monitorTags);
if (err != OK) {
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());
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);
}
}
// 省略无关代码.....
if (shimUpdateOnly) {
// If only updating legacy shim parameters, immediately disconnect client
mServiceLock.unlock();
client->disconnect();
mServiceLock.lock();
} else {
// Otherwise, add client to active clients list
// 连接创建完成
finishConnectLocked(client, partial, oomScoreOffset, systemNativeClient);
}
client->setImageDumpMask(mImageDumpMask);
client->setStreamUseCaseOverrides(mStreamUseCaseOverrides);
client->setZoomOverride(mZoomOverrideValue);
} // lock is destroyed, allow further connect calls
// 省略无关代码.....
return ret;
}
简单介绍一下handleEvictionsLocked
函数, 这个函数主要检测当前要打开的连接和已经打开的连接是否有冲突,产生冲突将终止,否则继续执行,这里涉及到App打开Camera优先级问题,这里不详细介绍,对这块感兴趣可以阅读《Android14 Camera-启动时Camera 的优先级》这篇文章。
上面handleEvictionsLocked
这个函数执行完返回的不是异常code将会进入创建makeClient
函数
Status CameraService::makeClient(const sp<CameraService>& cameraService,
const sp<IInterface>& cameraCb, const String16& packageName, bool systemNativeClient,
const std::optional<String16>& featureId, const String8& cameraId,
int api1CameraId, int facing, int sensorOrientation, int clientPid, uid_t clientUid,
int servicePid, std::pair<int, IPCTransport> deviceVersionAndTransport,
apiLevel effectiveApiLevel, bool overrideForPerfClass, bool overrideToPortrait,
bool forceSlowJpegMode, /*out*/sp<BasicClient>* client) {
// For HIDL devices
if (deviceVersionAndTransport.second == IPCTransport::HIDL) {
// Create CameraClient based on device version reported by the HAL.
int deviceVersion = deviceVersionAndTransport.first;
switch(deviceVersion) {
case CAMERA_DEVICE_API_VERSION_1_0:
ALOGE("Camera using old HAL version: %d", deviceVersion);
return STATUS_ERROR_FMT(ERROR_DEPRECATED_HAL,
"Camera device \"%s\" HAL version %d no longer supported",
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:
case CAMERA_DEVICE_API_VERSION_3_5:
case CAMERA_DEVICE_API_VERSION_3_6:
case CAMERA_DEVICE_API_VERSION_3_7:
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);
}
}
// 根据effectiveApiLevel 判断创建哪个API
if (effectiveApiLevel == API_1) { // Camera1 API route
sp<ICameraClient> tmp = static_cast<ICameraClient*>(cameraCb.get());
*client = new Camera2Client(cameraService, tmp, cameraService->mCameraServiceProxyWrapper,
packageName, featureId, cameraId, api1CameraId, facing, sensorOrientation,
clientPid, clientUid, servicePid, overrideForPerfClass, overrideToPortrait,
forceSlowJpegMode);
ALOGI("%s: Camera1 API (legacy), override to portrait %d, forceSlowJpegMode %d",
__FUNCTION__, overrideToPortrait, forceSlowJpegMode);
} else { // Camera2 API route
sp<hardware::camera2::ICameraDeviceCallbacks> tmp =
static_cast<hardware::camera2::ICameraDeviceCallbacks*>(cameraCb.get());
*client = new CameraDeviceClient(cameraService, tmp,
cameraService->mCameraServiceProxyWrapper, packageName, systemNativeClient,
featureId, cameraId, facing, sensorOrientation, clientPid, clientUid, servicePid,
overrideForPerfClass, overrideToPortrait);
ALOGI("%s: Camera2 API, override to portrait %d", __FUNCTION__, overrideToPortrait);
}
return Status::ok();
}
到这里会根据effectiveApiLevel
创建Camera2Client
还是CameraDeviceClient
, 他们都继承自Camera2ClientBase
,继承关系如下,
graph TD
A["Camera2Client (API_1)" ] --> C
B["CameraDeviceClient (API_2)"] --> C
C[Camera2ClientBase ]
这里主要介绍API_2
过程,API_1
可以自行查看
在阅读源码的时候需要注意CameraDeviceClient
和Camera2ClientBase
都有实现initialize
和initializeImpl
方法切都被调用
源码路径:
frameworks/av/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
frameworks/av/services/camera/libcameraservice/common/Camera2ClientBase.cpp
CameraDeviceClient::CameraDeviceClient(const sp<CameraService>& cameraService,
const sp<hardware::camera2::ICameraDeviceCallbacks>& remoteCallback,
std::shared_ptr<CameraServiceProxyWrapper> cameraServiceProxyWrapper,
const String16& clientPackageName,
bool systemNativeClient,
const std::optional<String16>& clientFeatureId,
const String8& cameraId,
int cameraFacing,
int sensorOrientation,
int clientPid,
uid_t clientUid,
int servicePid,
bool overrideForPerfClass,
bool overrideToPortrait) :
Camera2ClientBase(cameraService, remoteCallback, cameraServiceProxyWrapper, clientPackageName,
systemNativeClient, clientFeatureId, cameraId, /*API1 camera ID*/ -1, cameraFacing,
sensorOrientation, clientPid, clientUid, servicePid, overrideForPerfClass,
overrideToPortrait),
mInputStream(),
mStreamingRequestId(REQUEST_ID_NONE),
mRequestIdCounter(0),
mPrivilegedClient(false),
mOverrideForPerfClass(overrideForPerfClass) {
ATRACE_CALL();
ALOGI("CameraDeviceClient %s: Opened", cameraId.string());
}
template <typename TClientBase>
Camera2ClientBase<TClientBase>::Camera2ClientBase(
const sp<CameraService>& cameraService,
const sp<TCamCallbacks>& remoteCallback,
std::shared_ptr<CameraServiceProxyWrapper> cameraServiceProxyWrapper,
const String16& clientPackageName,
bool systemNativeClient,
const std::optional<String16>& clientFeatureId,
const String8& cameraId,
int api1CameraId,
int cameraFacing,
int sensorOrientation,
int clientPid,
uid_t clientUid,
int servicePid,
bool overrideForPerfClass,
bool overrideToPortrait,
bool legacyClient):
TClientBase(cameraService, remoteCallback, clientPackageName, systemNativeClient,
clientFeatureId, cameraId, api1CameraId, cameraFacing, sensorOrientation, clientPid,
clientUid, servicePid, overrideToPortrait),
mSharedCameraCallbacks(remoteCallback),
mCameraServiceProxyWrapper(cameraServiceProxyWrapper),
mDeviceActive(false), mApi1CameraId(api1CameraId)
{
ALOGI("Camera %s: Opened. Client: %s (PID %d, UID %d)", cameraId.string(),
String8(clientPackageName).string(), clientPid, clientUid);
mClientPackageName = clientPackageName;
mInitialClientPid = clientPid;
mOverrideForPerfClass = overrideForPerfClass;
mLegacyClient = legacyClient;
}
这里看一下CameraDeviceClient
构造函数中 mInputStream
这个变量是个结构体,看一下这个结构体
struct InputStreamConfiguration {
bool configured;
int32_t width;
int32_t height;
int32_t format;
int32_t id;
} mInputStream;
这个结构体有宽,有高,有格式,猜想一定和图像输入有关。
在回头看connectHelper
中代码:
Status CameraService::connectHelper(const sp<CALLBACK>& cameraCb, const String8& cameraId,
int api1CameraId, int halVersion, const String16& clientPackageName, int clientUid,
int clientPid, apiLevel effectiveApiLevel, bool shimUpdateOnly,
/*out*/sp<CLIENT>& device) {
// 省略无关细节代码 .....
sp<CLIENT> client = nullptr;
{
// 省略无关细节代码 .....
sp<BasicClient> tmp = nullptr;
// 创建连接,
bool overrideForPerfClass = SessionConfigurationUtils::targetPerfClassPrimaryCamera(
mPerfClassPrimaryCameraIds, cameraId.string(), targetSdkVersion);
if(!(ret = makeClient(this, cameraCb, clientPackageName, systemNativeClient,
clientFeatureId, cameraId, api1CameraId, facing, orientation,
clientPid, clientUid, getpid(),
deviceVersionAndTransport, effectiveApiLevel, overrideForPerfClass,
overrideToPortrait, forceSlowJpegMode,
/*out*/&tmp)).isOk()) {
return ret;
}
// 获取创建的 CameraDeviceClient
client = static_cast<CLIENT*>(tmp.get());
// 省略无关细节代码 .....
// 初始化 deviceCline
err = client->initialize(mCameraProviderManager, monitorTags);
// 省略无关细节代码 .....
}
device = client;
return ret;
}
创建client
后就紧接着进行了初始化。这里需要注意一下,传入的mCameraProviderManager
是在系统启动的时候加载CameraServices
的时候创建的CameraProviderManager
, 不了解的可以查看《Android12 Camera -开机初始化过程》
CameraDeviceClient
初始化过程
status_t CameraDeviceClient::initialize(sp<CameraProviderManager> manager,
const String8& monitorTags) {
return initializeImpl(manager, monitorTags);
}
template<typename TProviderPtr>
status_t CameraDeviceClient::initializeImpl(TProviderPtr providerPtr, const String8& monitorTags) {
ATRACE_CALL();
status_t res;
// 调用父类Camera2ClientBase 进行初始化
res = Camera2ClientBase::initialize(providerPtr, monitorTags);
if (res != OK) {
return res;
}
String8 threadName;
// 创建frame 数据处理线程
mFrameProcessor = new FrameProcessorBase(mDevice);
threadName = String8::format("CDU-%s-FrameProc", mCameraIdStr.string());
// 启动线程
res = mFrameProcessor->run(threadName.string());
if (res != OK) {
ALOGE("%s: Unable to start frame processor thread: %s (%d)",
__FUNCTION__, strerror(-res), res);
return res;
}
mFrameProcessor->registerListener(camera2::FrameProcessorBase::FRAME_PROCESSOR_LISTENER_MIN_ID,
camera2::FrameProcessorBase::FRAME_PROCESSOR_LISTENER_MAX_ID,
/*listener*/this,
/*sendPartials*/true);
const CameraMetadata &deviceInfo = mDevice->info();
//省略无关代码......
mProviderManager = providerPtr;
// Cache physical camera ids corresponding to this device and also the high
// resolution sensors in this device + physical camera ids
mProviderManager->isLogicalCamera(mCameraIdStr.string(), &mPhysicalCameraIds);
return OK;
}
上面初始化注意到在开始的位置便调用了Camera2ClientBase
的初始化函数,在创建FrameProcessorBase
时构造函数中传入了一个mDevice
,下面看一下Camera2ClientBase
是初始化都做了什么?mDevice
是什么时候被创建的?
template <typename TClientBase>
status_t Camera2ClientBase<TClientBase>::initialize(sp<CameraProviderManager> manager,
const String8& monitorTags) {
return initializeImpl(manager, monitorTags);
}
template <typename TClientBase>
template <typename TProviderPtr>
status_t Camera2ClientBase<TClientBase>::initializeImpl(TProviderPtr providerPtr,
const String8& monitorTags) {
ATRACE_CALL();
ALOGV("%s: Initializing client for camera %s", __FUNCTION__,
TClientBase::mCameraIdStr.string());
status_t res;
IPCTransport providerTransport = IPCTransport::INVALID;
// 获取驱动的通讯方式
res = providerPtr->getCameraIdIPCTransport(TClientBase::mCameraIdStr.string(),
&providerTransport);
if (res != OK) {
return res;
}
switch (providerTransport) {
case IPCTransport::HIDL:
mDevice =
new HidlCamera3Device(mCameraServiceProxyWrapper,
TClientBase::mCameraIdStr, mOverrideForPerfClass,
TClientBase::mOverrideToPortrait, mLegacyClient);
break;
case IPCTransport::AIDL:
mDevice =
new AidlCamera3Device(mCameraServiceProxyWrapper,
TClientBase::mCameraIdStr, mOverrideForPerfClass,
TClientBase::mOverrideToPortrait, mLegacyClient);
break;
default:
ALOGE("%s Invalid transport for camera id %s", __FUNCTION__,
TClientBase::mCameraIdStr.string());
return NO_INIT;
}
if (mDevice == NULL) {
ALOGE("%s: Camera %s: No device connected",
__FUNCTION__, TClientBase::mCameraIdStr.string());
return NO_INIT;
}
// 初始化报名
res = mDevice->initializePackageName(TClientBase::mClientPackageName);
// 初始化Device
res = mDevice->initialize(providerPtr, monitorTags);
if (res != OK) {
ALOGE("%s: Camera %s: unable to initialize device: %s (%d)",
__FUNCTION__, TClientBase::mCameraIdStr.string(), strerror(-res), res);
return res;
}
// Verify ops permissions
// 检查权限
res = TClientBase::startCameraOps();
if (res != OK) {
TClientBase::finishCameraOps();
return res;
}
wp<NotificationListener> weakThis(this);
// 设置监听
res = mDevice->setNotifyCallback(weakThis);
if (res != OK) {
ALOGE("%s: Camera %s: Unable to set notify callback: %s (%d)",
__FUNCTION__, TClientBase::mCameraIdStr.string(), strerror(-res), res);
return res;
}
// 省略无关代码.......
return OK;
}
在Camera2ClientBase
中会判断初始化HidlCamera3Device
还是AidlCamera3Device
, 他们都继承自Camera3Device
,继承关系如下:
graph TD
A["HidlCamera3Device" ] --> C
B["AidlCamera3Device"] --> C
C[Camera3Device ]
上面是他们三个的关系,下面看一下Device
的初始化, 这里需要注意一下,HidlCamera3Device
, AidlCamera3Device
,Camera3Device
都有initialize
函数,但是在Android14中Camera3Device
中的initialize
函数没有被调用,下面我们就只看AidlCamera3Device
和HidlCamera3Device
的初始话函数
status_t HidlCamera3Device::initialize(sp<CameraProviderManager> manager,
const String8& monitorTags) {
ATRACE_CALL();
Mutex::Autolock il(mInterfaceLock);
Mutex::Autolock l(mLock);
ALOGV("%s: Initializing HIDL device for camera %s", __FUNCTION__, mId.string());
if (mStatus != STATUS_UNINITIALIZED) {
CLOGE("Already initialized!");
return INVALID_OPERATION;
}
if (manager == nullptr) return INVALID_OPERATION;
sp<ICameraDeviceSession> session;
ATRACE_BEGIN("CameraHal::openSession");
// 打开一个和Hal层通讯的会话
status_t res = manager->openHidlSession(mId.string(), this,
/*out*/ &session);
ATRACE_END();
if (res != OK) {
SET_ERR_L("Could not open camera session: %s (%d)", strerror(-res), res);
return res;
}
// 过去Camera 参数
res = manager->getCameraCharacteristics(mId.string(), mOverrideForPerfClass, &mDeviceInfo,
/*overrideToPortrait*/false);
if (res != OK) {
SET_ERR_L("Could not retrieve camera characteristics: %s (%d)", strerror(-res), res);
session->close();
return res;
}
mSupportNativeZoomRatio = manager->supportNativeZoomRatio(mId.string());
// 省略部分代码
// 获取请求参数队列
std::shared_ptr<RequestMetadataQueue> queue;
auto requestQueueRet = session->getCaptureRequestMetadataQueue(
[&queue](const auto& descriptor) {
queue = std::make_shared<RequestMetadataQueue>(descriptor);
if (!queue->isValid() || queue->availableToWrite() <= 0) {
ALOGE("HAL returns empty request metadata fmq, not use it");
queue = nullptr;
// don't use the queue onwards.
}
});
if (!requestQueueRet.isOk()) {
ALOGE("Transaction error when getting request metadata fmq: %s, not use it",
requestQueueRet.description().c_str());
return DEAD_OBJECT;
}
//结果参数队列
std::unique_ptr<ResultMetadataQueue>& resQueue = mResultMetadataQueue;
auto resultQueueRet = session->getCaptureResultMetadataQueue(
[&resQueue](const auto& descriptor) {
resQueue = std::make_unique<ResultMetadataQueue>(descriptor);
if (!resQueue->isValid() || resQueue->availableToWrite() <= 0) {
ALOGE("HAL returns empty result metadata fmq, not use it");
resQueue = nullptr;
// Don't use the resQueue onwards.
}
});
if (!resultQueueRet.isOk()) {
ALOGE("Transaction error when getting result metadata queue from camera session: %s",
resultQueueRet.description().c_str());
return DEAD_OBJECT;
}
// 省略部分代码
camera_metadata_entry bufMgrMode =
mDeviceInfo.find(ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION);
if (bufMgrMode.count > 0) {
mUseHalBufManager = (bufMgrMode.data.u8[0] ==
ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION_HIDL_DEVICE_3_5);
}
camera_metadata_entry_t capabilities = mDeviceInfo.find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
for (size_t i = 0; i < capabilities.count; i++) {
uint8_t capability = capabilities.data.u8[i];
if (capability == ANDROID_REQUEST_AVAILABLE_CAPABILITIES_OFFLINE_PROCESSING) {
mSupportOfflineProcessing = true;
}
}
// 创建Hidl Hal调用接口
mInterface = new HidlHalInterface(session, queue, mUseHalBufManager, mSupportOfflineProcessing);
std::string providerType;
mVendorTagId = manager->getProviderTagIdLocked(mId.string());
mTagMonitor.initialize(mVendorTagId);
if (!monitorTags.isEmpty()) {
mTagMonitor.parseTagsToMonitor(String8(monitorTags));
}
// Metadata tags needs fixup for monochrome camera device version less
// than 3.5.
hardware::hidl_version maxVersion{0,0};
IPCTransport transport = IPCTransport::HIDL;
res = manager->getHighestSupportedVersion(mId.string(), &maxVersion, &transport);
if (res != OK) {
ALOGE("%s: Error in getting camera device version id: %s (%d)",
__FUNCTION__, strerror(-res), res);
return res;
}
int deviceVersion = HARDWARE_DEVICE_API_VERSION(
maxVersion.get_major(), maxVersion.get_minor());
bool isMonochrome = false;
for (size_t i = 0; i < capabilities.count; i++) {
uint8_t capability = capabilities.data.u8[i];
if (capability == ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MONOCHROME) {
isMonochrome = true;
}
}
mNeedFixupMonochromeTags = (isMonochrome && deviceVersion < CAMERA_DEVICE_API_VERSION_3_5);
return initializeCommonLocked();
}
上面代码主要步骤:
- 通过
CameraProviderManager
去打开一个会话openHidlSession
, - 创建一个Hidl类型的Hal调用接口
HidlHalInterface
- 调用
initializeCommonLocked
函数
AidlCamera3Device
初始化过程类似,这里不在介绍。
到这里看下上面提到的openHidlSession
函数实现,openHidlSession
实现在 CameraProviderManager.cpp
中, 这里通过CameraProviderManager
的openHidlSession
获得一个ICameraDeviceSession
frameworks/av/services/camera/libcameraservice/common/CameraProviderManager.cpp
status_t CameraProviderManager::openHidlSession(const std::string &id,
const sp<device::V3_2::ICameraDeviceCallback>& callback,
/*out*/
sp<device::V3_2::ICameraDeviceSession> *session) {
std::lock_guard<std::mutex> lock(mInterfaceMutex);
// 根据id 查找对应Camera 驱动信息
auto deviceInfo = findDeviceInfoLocked(id);
if (deviceInfo == nullptr) return NAME_NOT_FOUND;
auto *hidlDeviceInfo3 = static_cast<HidlProviderInfo::HidlDeviceInfo3*>(deviceInfo);
// 通过开机时加载的 Camera device 获取对应的 ProviderInfo
sp<ProviderInfo> parentProvider = deviceInfo->mParentProvider.promote();
if (parentProvider == nullptr) {
return DEAD_OBJECT;
}
// 通过binder 获取hal CameraProvider 服务调用接口, 下面会分析
const sp<provider::V2_4::ICameraProvider> provider =
static_cast<HidlProviderInfo *>(parentProvider.get())->startProviderInterface();
if (provider == nullptr) {
return DEAD_OBJECT;
}
std::shared_ptr<HalCameraProvider> halCameraProvider =
std::make_shared<HidlHalCameraProvider>(provider, provider->descriptor);
saveRef(DeviceMode::CAMERA, id, halCameraProvider);
Status status;
hardware::Return<void> ret;
// 获取Camera device 接口
auto interface = hidlDeviceInfo3->startDeviceInterface();
if (interface == nullptr) {
return DEAD_OBJECT;
}
// 打开 Camera device
ret = interface->open(callback, [&status, &session]
(Status s, const sp<device::V3_2::ICameraDeviceSession>& cameraSession) {
status = s;
if (status == Status::OK) {
// 打开成功返回打开的 camera device session
// 这个 *session 是调用函数是传入的指针
*session = cameraSession;
}
});
if (!ret.isOk()) {
removeRef(DeviceMode::CAMERA, id);
ALOGE("%s: Transaction error opening a session for camera device %s: %s",
__FUNCTION__, id.c_str(), ret.description().c_str());
return DEAD_OBJECT;
}
return HidlProviderInfo::mapToStatusT(status);
}
执行步骤:
- 获取
CameraProvider
服务的binderstartProviderInterface()
- 获取驱动的接口
startDeviceInterface()
- 执行打开驱动
下面看一下上面提到的调用startProviderInterface
函数获取CameraProvider
服务的binder的过程:
frameworks/av/services/camera/libcameraservice/common/hidl/HidlProviderInfo.cpp
const sp<provider::V2_4::ICameraProvider>
HidlProviderInfo::startProviderInterface() {
// 省略无关细节代码 .....
auto interface = mActiveInterface.promote();
if (interface == nullptr) {
// Try to get service without starting
// 获取 ICameraProvider binder接口
interface = mManager->mHidlServiceProxy->tryGetService(mProviderName);
if (interface == nullptr) {
ALOGV("Camera provider actually needs restart, calling getService(%s)",
mProviderName.c_str());
// 获取 ICameraProvider binder接口
interface = mManager->mHidlServiceProxy->getService(mProviderName);
for (auto& device : mDevices) {
device->mIsDeviceAvailable = false;
}
interface->setCallback(this);
// 设置bind 断开监听
hardware::Return<bool>linked = interface->linkToDeath(this, /*cookie*/ mId);
if (!linked.isOk()) {
mManager->removeProvider(mProviderInstance);
return nullptr;
} else if (!linked) {
ALOGW("%s: Unable to link to provider '%s' death notifications",
__FUNCTION__, mProviderName.c_str());
}
// Send current device state
if (mMinorVersion >= 5) {
auto castResult =
provider::V2_5::ICameraProvider::castFrom(interface);
if (castResult.isOk()) {
sp<provider::V2_5::ICameraProvider> interface_2_5 = castResult;
if (interface_2_5 != nullptr) {
ALOGV("%s: Initial device state for %s: 0x %" PRIx64,
__FUNCTION__, mProviderName.c_str(), mDeviceState);
interface_2_5->notifyDeviceStateChange(mDeviceState);
}
}
}
}
mActiveInterface = interface;
} else {
ALOGV("Camera provider (%s) already in use. Re-using instance.",
mProviderName.c_str());
}
return interface;
}
看一下获取驱动的接口startDeviceInterface()
,这个函数也在HidlProviderInfo.cpp
中。
sp<hardware::camera::device::V3_2::ICameraDevice>
HidlProviderInfo::HidlDeviceInfo3::startDeviceInterface() {
Mutex::Autolock l(mDeviceAvailableLock);
sp<hardware::camera::device::V3_2::ICameraDevice> device;
ATRACE_CALL();
if (mSavedInterface == nullptr) {
sp<HidlProviderInfo> parentProvider = static_cast<HidlProviderInfo *>(mParentProvider.promote().get());
if (parentProvider != nullptr) {
// Wait for lazy HALs to confirm device availability
if (parentProvider->isExternalLazyHAL() && !mIsDeviceAvailable) {
ALOGV("%s: Wait for external device to become available %s",
__FUNCTION__,
mId.c_str());
auto res = mDeviceAvailableSignal.waitRelative(mDeviceAvailableLock,
kDeviceAvailableTimeout);
if (res != OK) {
ALOGE("%s: Failed waiting for device to become available",
__FUNCTION__);
return nullptr;
}
}
device = parentProvider->startDeviceInterface(mName);
}
} else {
device = (hardware::camera::device::V3_2::ICameraDevice *) mSavedInterface.get();
}
return device;
}
sp<device::V3_2::ICameraDevice>
HidlProviderInfo::startDeviceInterface(const std::string &name) {
Status status;
sp<device::V3_2::ICameraDevice> cameraInterface;
hardware::Return<void> ret;
// 这里又调用了startProviderInterface();函数获取了ICameraProvider
const sp<provider::V2_4::ICameraProvider> interface = startProviderInterface();
if (interface == nullptr) {
return nullptr;
}
ret = interface->getCameraDeviceInterface_V3_x(name, [&status, &cameraInterface](
Status s, sp<device::V3_2::ICameraDevice> interface) {
status = s;
// 成功获取到Camera Device 接口
cameraInterface = interface;
});
if (!ret.isOk()) {
ALOGE("%s: Transaction error trying to obtain interface for camera device %s: %s",
__FUNCTION__, name.c_str(), ret.description().c_str());
return nullptr;
}
if (status != Status::OK) {
ALOGE("%s: Unable to obtain interface for camera device %s: %s", __FUNCTION__,
name.c_str(), statusToString(status));
return nullptr;
}
return cameraInterface;
}
执行步骤:
- 获取
CameraProvider
服务的binderstartProviderInterface()
- 调用
getCameraDeviceInterface_V3_x
函数获取Camera Device 的引用
到这里调用了ICameraProvider
两个函数:
interface->getCameraDeviceInterface_V3_x
interface->open
上面这两个函数调用是调用到Camera Hal中,代码位置:
Device:hardware/interfaces/camera/device
Provide:hardware/interfaces/camera/provider
这里不介绍,感兴趣可以自己查看
在interface->open
函数调用完,Camera便已经打开了,最后看一下initializeCommonLocked();
函数
上面是打开hal
层Camera 到获取到 *session
的过程。下面我们看一下获取到*session
之后还做了些什么,下面继续看Camera3Device.cpp
中initialize
函数最后一行的initializeCommonLocked()
函数
status_t Camera3Device::initializeCommonLocked() {
// 启动一个线程获取状态
mStatusTracker = new StatusTracker(this);
status_t res = mStatusTracker->run(String8::format("C3Dev-%s-Status", mId.string()).string());
//省略无关细节代码 .....
// 创建一个相机图像输出流 buffer管理器
mBufferManager = new Camera3BufferManager();
//省略无关细节代码 .....
// 启动请求队列线程
mRequestThread = createNewRequestThread(
this, mStatusTracker, mInterface, sessionParamKeys,
mUseHalBufManager, mSupportCameraMute, mOverrideToPortrait,
mSupportZoomOverride);
res = mRequestThread->run(String8::format("C3Dev-%s-ReqQueue", mId.string()).string());
//省略无关细节代码 .....
mPreparerThread = new PreparerThread();
//省略无关细节代码 .....
// Hidl/AidlCamera3DeviceInjectionMethods
mInjectionMethods = createCamera3DeviceInjectionMethods(this);
//省略无关细节代码 .....
return OK;
}
执行到这里,初始化的过程就执行完毕了。
最后在看一下CameraService::connectHelper
函数中
// 3 second busy timeout when other clients are connecting
static const nsecs_t DEFAULT_CONNECT_TIMEOUT_NS = 3000000000;
template<class CALLBACK, class CLIENT>
Status CameraService::connectHelper(const sp<CALLBACK>& cameraCb, const String8& cameraId,
int api1CameraId, const String16& clientPackageNameMaybe, bool systemNativeClient,
const std::optional<String16>& clientFeatureId, int clientUid, int clientPid,
apiLevel effectiveApiLevel, bool shimUpdateOnly, int oomScoreOffset, int targetSdkVersion,
bool overrideToPortrait, bool forceSlowJpegMode,
/*out*/sp<CLIENT>& device) {
// 省略无关代码.....
{
// 省略无关代码.....
// 创建Camera连接
if(!(ret = makeClient(this, cameraCb, clientPackageName, systemNativeClient,
clientFeatureId, cameraId, api1CameraId, facing, orientation,
clientPid, clientUid, getpid(),
deviceVersionAndTransport, effectiveApiLevel, overrideForPerfClass,
overrideToPortrait, forceSlowJpegMode,
/*out*/&tmp)).isOk()) {
return ret;
}
client = static_cast<CLIENT*>(tmp.get());
LOG_ALWAYS_FATAL_IF(client.get() == nullptr, "%s: CameraService in invalid state",
__FUNCTION__);
String8 monitorTags = isClientWatched(client.get()) ? mMonitorTags : String8("");
// 初始化当前Camera 连接
err = client->initialize(mCameraProviderManager, monitorTags);
// 省略无关代码.....
if (shimUpdateOnly) {
// If only updating legacy shim parameters, immediately disconnect client
mServiceLock.unlock();
client->disconnect();
mServiceLock.lock();
} else {
// Otherwise, add client to active clients list
// 连接创建完成
finishConnectLocked(client, partial, oomScoreOffset, systemNativeClient);
}
// 省略无关代码.....
} // lock is destroyed, allow further connect calls
// 省略无关代码.....
return ret;
}
上面是再次精简后的代码代码, 初始化完成后执行到finishConnectLocked
函数。
void CameraService::finishConnectLocked(const sp<BasicClient>& client,
const CameraService::DescriptorPtr& desc, int oomScoreOffset, bool systemNativeClient) {
// 创建一个Camera连接描述
auto clientDescriptor =CameraService::CameraClientManager::makeClientDescriptor(client, desc,
oomScoreOffset, systemNativeClient);
// 将成功打开的连接添加到管理器中
auto evicted = mActiveClientManager.addAndEvict(clientDescriptor);
// 省略无关代码.....
sp<IBinder> remoteCallback = client->getRemote();
if (remoteCallback != nullptr) {
remoteCallback->linkToDeath(this);
}
}
在这个函数中主要创建一个Camera的连接描述(ClientDescriptor
), 然后将这个描述添加的CameraClientManager
中进行管理。
到这里Camera2中openCamera
函数的执行过程就介绍完了。