简介
frameworks\base\core\java\android\hardware\camera2
Camera2在Android 5.0上首次出现,主要重新定义了一套Camera 的使用接口API,设计思想出现了变化,具体的可自行搜索,此处主要介绍下Camera2的常见类以及使用流程。
CameraCaptureSession 类 会话类,即用户发起操作Camera设备的动作类,如录像拍照等
CaptureRequest类 请求类,用户对Camera发起请求的抽象封装类
CameraDevice类 Camera抽象类,类似于Camaera的一个客户端
CameraCharacteristics类 相机参数类,比如相机支持哪些特性,如分辨率集合等
除此之外这些类中还会存在内部类,内部类的作用是Camera Framework 层完成配置异步返回结果的抽象类
以上几个主要的类都在base/core下面,在对外发布API的时候App均可使用
frameworks\base\media
ImageReader类 相机采集回来的数据承载类,即相机的YUV元数据承载类
在APP层使用相机拍照 录制视频 等过程中上述主要类均离不开,本系列主要围绕关键类,介绍其关键流程,本文主要介绍openCamera流程
1: openCamera 基本流程
Framework层流程也是针对上诉几个关键步骤进行分析的,我们逐个往下分析
首先看下App层在openCamera的时候Framework层发生了什么,做了什么
frameworks\base\core\java\android\hardware\camera2\CameraManager.java
@RequiresPermission(android.Manifest.permission.CAMERA)
public void openCamera(@NonNull String cameraId,
@NonNull final CameraDevice.StateCallback callback, @Nullable Handler handler)
throws CameraAccessException {
openCameraForUid(cameraId, callback, handler, USE_CALLING_UID);
}
检查参数
public void openCameraForUid(@NonNull String cameraId,
@NonNull final CameraDevice.StateCallback callback, @Nullable Handler handler,
int clientUid)
throws CameraAccessException {
if(TdDeviceManager.disallowOp(TdDeviceManager.DISABLED_CAMERA)) {
throw new IllegalArgumentException("camera is disabled by MDM");
}
if (cameraId == null) {
throw new IllegalArgumentException("cameraId was null");
} else if (callback == null) {
throw new IllegalArgumentException("callback was null");
} else if (handler == null) {
if (Looper.myLooper() != null) {
handler = new Handler();
} else {
throw new IllegalArgumentException(
"Handler argument is null, but no looper exists in the calling thread");
}
}
openCameraDeviceUserAsync(cameraId, callback, handler, clientUid);
}
关键方法
/**
* Helper for opening a connection to a camera with the given ID.
*
* @param cameraId The unique identifier of the camera device to open
* @param callback The callback for the camera. Must not be null.
* @param handler The handler to invoke the callback on. Must not be null.
* @param uid The UID of the application actually opening the camera.
* Must be USE_CALLING_UID unless the caller is a service
* that is trusted to open the device on behalf of an
* application and to forward the real UID.
*
* @throws CameraAccessException if the camera is disabled by device policy,
* too many camera devices are already open, or the cameraId does not match
* any currently available camera device.
*
* @throws SecurityException if the application does not have permission to
* access the camera
* @throws IllegalArgumentException if callback or handler is null.
* @return A handle to the newly-created camera device.
*
* @see #getCameraIdList
* @see android.app.admin.DevicePolicyManager#setCameraDisabled
*/
private CameraDevice openCameraDeviceUserAsync(String cameraId,
CameraDevice.StateCallback callback, Handler handler, final int uid)
throws CameraAccessException {
CameraCharacteristics characteristics = getCameraCharacteristics(cameraId);
CameraDevice device = null;
synchronized (mLock) {
ICameraDeviceUser cameraUser = null;
android.hardware.camera2.impl.CameraDeviceImpl deviceImpl =
new android.hardware.camera2.impl.CameraDeviceImpl(
cameraId,
callback,
handler,
characteristics,
mContext.getApplicationInfo().targetSdkVersion);
ICameraDeviceCallbacks callbacks = deviceImpl.getCallbacks();
try {
if (supportsCamera2ApiLocked(cameraId)) {
// Use cameraservice's cameradeviceclient implementation for HAL3.2+ devices
//[HSM]
if(!HwSystemManager.allowOp(HwSystemManager.PERMISSION_CAMERA)) {
ServiceSpecificException e = new ServiceSpecificException(ICameraService.ERROR_DISABLED);
throwAsPublicException(e);
}
Log.i(TAG, "open camera: " + cameraId + ", package name: " + mContext.getOpPackageName());
HwSystemManager.notifyBackgroundMgr(mContext.getOpPackageName(),
Binder.getCallingPid(),
Binder.getCallingUid(),
HwSystemManager.CAMARA_SERVICE_NOTIFY,
HwSystemManager.BACKGROUND_POLICY_OPEN);
ICameraService cameraService = CameraManagerGlobal.get().getCameraService();
if (cameraService == null) {
throw new ServiceSpecificException(
ICameraService.ERROR_DISCONNECTED,
"Camera service is currently unavailable");
}
cameraUser = cameraService.connectDevice(callbacks, cameraId,
mContext.getOpPackageName(), uid);
} else {
// Use legacy camera implementation for HAL1 devices
int id;
try {
id = Integer.parseInt(cameraId);
} catch (NumberFormatException e) {
throw new IllegalArgumentException("Expected cameraId to be numeric, but it was: "
+ cameraId);
}
Log.i(TAG, "Using legacy camera HAL.");
cameraUser = CameraDeviceUserShim.connectBinderShim(callbacks, id);
}
} catch (ServiceSpecificException e) {
if (e.errorCode == ICameraService.ERROR_DEPRECATED_HAL) {
throw new AssertionError("Should've gone down the shim path");
} else if (e.errorCode == ICameraService.ERROR_CAMERA_IN_USE ||
e.errorCode == ICameraService.ERROR_MAX_CAMERAS_IN_USE ||
e.errorCode == ICameraService.ERROR_DISABLED ||
e.errorCode == ICameraService.ERROR_DISCONNECTED ||
e.errorCode == ICameraService.ERROR_INVALID_OPERATION) {
// Received one of the known connection errors
// The remote camera device cannot be connected to, so
// set the local camera to the startup error state
devic