在上一篇文章《Android Camera原理之openCamera模块(一)》咱们主要介绍了openCamera的调用流程以及camera模块涉及到的4个层次之间的调用关系,可是一些细节问题并无阐释到,本文咱们补充一下细节问题,力求丰满整个openCamera模块的知识体系。
在《Android Camera模块解析之拍照》一文中谈到了调用openCamera方法:android
manager.openCamera(mCameraId, mStateCallback, mBackgroundHandler);
这个manager就是CameraManager实例,openCamera方法上一篇文章已经介绍地比较清楚了,可是第二个参数mStateCallback没有深刻讲解,你们只知道是一个相机状态的回调,可是这个状态很重要。这个状态回调会告知开发者当前的camera处于什么状态,在确切得到这个状态以后,才能进行下一步的操做。例如我打开camera是成功仍是失败了,若是不知道的话是不能进行下一步的操做的。安全
private final CameraDevice.StateCallback mStateCallback = new CameraDevice.StateCallback() { @Override public void onOpened(@NonNull CameraDevice cameraDevice) { // This method is called when the camera is opened. We start camera preview here. mCameraOpenCloseLock.release(); mCameraDevice = cameraDevice; createCameraPreviewSession(); } @Override public void onDisconnected(@NonNull CameraDevice cameraDevice) { mCameraOpenCloseLock.release(); cameraDevice.close(); mCameraDevice = null; } @Override public void onError(@NonNull CameraDevice cameraDevice, int error) { mCameraOpenCloseLock.release(); cameraDevice.close(); mCameraDevice = null; Activity activity = getActivity(); if (null != activity) { activity.finish(); } } };
本文想搞清楚的一点是:Camera状态是如何回调的?
因为上一篇openCamera的文章已经谈到了详细的调用流程,这里不会赘述了。session
openCamera会调用到openCameraDeviceUserAsync(...)中,固然也会把它的StateCallback参数传进来,这个参数和获取到的CameraCharacteristics一块儿传入CameraDeviceImpl的构造函数中。app
android.hardware.camera2.impl.CameraDeviceImpl deviceImpl = new android.hardware.camera2.impl.CameraDeviceImpl( cameraId, callback, executor, characteristics, mContext.getApplicationInfo().targetSdkVersion);
可是传入cameraService的回调参数却不是这个回调,看一下代码:ide
ICameraDeviceCallbacks callbacks = deviceImpl.getCallbacks(); //...... cameraUser = cameraService.connectDevice(callbacks, cameraId, mContext.getOpPackageName(), uid);
这个callbacks是CameraDeviceImpl实例中的参数,那么这个callbacks和咱们传入的StateCallback有什么关系了,仍是要去CameraDeviceImpl看一下。函数
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; final int MAX_TAG_LEN = 23; String tag = String.format("CameraDevice-JV-%s", mCameraId); if (tag.length() > MAX_TAG_LEN) { tag = tag.substring(0, MAX_TAG_LEN); } TAG = tag; Integer partialCount = mCharacteristics.get(CameraCharacteristics.REQUEST_PARTIAL_RESULT_COUNT); if (partialCount == null) { // 1 means partial result is not supported. mTotalPartialCount = 1; } else { mTotalPartialCount = partialCount; } }
- 构造函数中传入的StateCallback赋给了CameraDeviceImpl中的mDeviceCallback
private final CameraDeviceCallbacks mCallbacks = new CameraDeviceCallbacks(); public CameraDeviceCallbacks getCallbacks() { return mCallbacks; } public class CameraDeviceCallbacks extends ICameraDeviceCallbacks.Stub { //...... }
- CameraDeviceCallbacks继承ICameraDeviceCallbacks.Stub,而ICameraDeviceCallbacks.Stub是能够在Binder IPC中传输的对象,很显然这个才是应用程序与CameraService通讯的回调,在这个回调中的执行方法标识当前的camera的执行状态
ICameraDeviceCallbacks.aidl自动生成的android/hardware/camera2/ICameraDeviceCallbacks.h文件post
class ICameraDeviceCallbacksDefault : public ICameraDeviceCallbacks { public: ::android::IBinder* onAsBinder() override; ::android::binder::Status onDeviceError(int32_t errorCode, const ::android::hardware::camera2::impl::CaptureResultExtras& resultExtras) override; ::android::binder::Status onDeviceIdle() override; ::android::binder::Status onCaptureStarted(const ::android::hardware::camera2::impl::CaptureResultExtras& resultExtras, int64_t timestamp) override; ::android::binder::Status onResultReceived(const ::android::hardware::camera2::impl::CameraMetadataNative& result, const ::android::hardware::camera2::impl::CaptureResultExtras& resultExtras, const ::std::vector<::android::hardware::camera2::impl::PhysicalCaptureResultInfo>& physicalCaptureResultInfos) override; ::android::binder::Status onPrepared(int32_t streamId) override; ::android::binder::Status onRepeatingRequestError(int64_t lastFrameNumber, int32_t repeatingRequestId) override; ::android::binder::Status onRequestQueueEmpty() override; };
这个回调函数是从CameraService中调上来的。下面的回调包含了Camera执行过程当中的各类状态,执行成功、执行失败、数据接收成功等等。这儿暂时不展开描述,等后面capture image的时候会详细阐释。学习
- onDeviceError
- onDeviceIdle
- onCaptureStarted
- onResultReceived
- onPrepared
- onRepeatingRequestError
- onRequestQueueEmpty
StateCallback是openCamera传入的3个参数中的一个,这是一个标识当前camera链接状态的回调。ui
public static abstract class StateCallback { public static final int ERROR_CAMERA_IN_USE = 1; public static final int ERROR_MAX_CAMERAS_IN_USE = 2; public static final int ERROR_CAMERA_DISABLED = 3; public static final int ERROR_CAMERA_DEVICE = 4; public static final int ERROR_CAMERA_SERVICE = 5; /** @hide */ @Retention(RetentionPolicy.SOURCE) @IntDef(prefix = {"ERROR_"}, value = {ERROR_CAMERA_IN_USE, ERROR_MAX_CAMERAS_IN_USE, ERROR_CAMERA_DISABLED, ERROR_CAMERA_DEVICE, ERROR_CAMERA_SERVICE }) public @interface ErrorCode {}; public abstract void onOpened(@NonNull CameraDevice camera); // Must implement public void onClosed(@NonNull CameraDevice camera) { // Default empty implementation } public abstract void onDisconnected(@NonNull CameraDevice camera); // Must implement public abstract void onError(@NonNull CameraDevice camera, @ErrorCode int error); // Must implement }
- onOpened回调:
当前camera device已经被打开了,会触发这个回调。探明camera的状态是opened了,这是能够开始createCaptureSession开始使用camera 捕捉图片或者视频了。
触发onOpened回调的地方在setRemoteDevice(...),这个函数在connectDevice(...)链接成功以后执行,代表当前的camera device已经链接成功了,触发camera 可以打开的回调。this
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 { 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); } } 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(CameraDeviceImpl.this); } };
- onClosed回调:
camera device已经被关闭,这个回调被触发。通常是终端开发者closeCamera的时候会释放当前持有的camera device,这是正常的现象。
public void close() { synchronized (mInterfaceLock) { if (mClosing.getAndSet(true)) { return; } if (mRemoteDevice != null) { mRemoteDevice.disconnect(); mRemoteDevice.unlinkToDeath(this, /*flags*/0); } if (mRemoteDevice != null || mInError) { mDeviceExecutor.execute(mCallOnClosed); } mRemoteDevice = null; } } private final Runnable mCallOnClosed = new Runnable() { private boolean mClosedOnce = false; @Override public void run() { if (mClosedOnce) { throw new AssertionError("Don't post #onClosed more than once"); } StateCallbackKK sessionCallback = null; synchronized(mInterfaceLock) { sessionCallback = mSessionStateCallback; } if (sessionCallback != null) { sessionCallback.onClosed(CameraDeviceImpl.this); } mDeviceCallback.onClosed(CameraDeviceImpl.this); mClosedOnce = true; } };
- onDisconnected回调:
camera device再也不可用,打开camera device失败了,通常是由于权限或者安全策略问题致使camera device打不开。一旦链接camera device出现ERROR_CAMERA_DISCONNECTED问题了,这是函数就会被回调,表示当前camera device处于断开的状态。- onError回调:
调用camera device的时候出现了严重的问题。执行CameraService-->connectDevice 出现异常了
} 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 deviceImpl.setRemoteFailure(e); if (e.errorCode == ICameraService.ERROR_DISABLED || e.errorCode == ICameraService.ERROR_DISCONNECTED || e.errorCode == ICameraService.ERROR_CAMERA_IN_USE) { // Per API docs, these failures call onError and throw throwAsPublicException(e); } } else { // Unexpected failure - rethrow throwAsPublicException(e); } } catch (RemoteException e) { // Camera service died - act as if it's a CAMERA_DISCONNECTED case ServiceSpecificException sse = new ServiceSpecificException( ICameraService.ERROR_DISCONNECTED, "Camera service is currently unavailable"); deviceImpl.setRemoteFailure(sse); throwAsPublicException(sse); }
deviceImpl.setRemoteFailure(e);是执行onError回调的函数。
Camera的知识点很是多,咱们从openCamera讲起,也是但愿从代码实践中真正了解camera的调用流程,由浅入深的学习camera知识。下面咱们会继续讲解链接成功以后,也就是StateCallback-->onOpened回调中camera会如何操做。敬请期待,不足之处,敬请谅解。