In my application I am using the Camera2 API to do some processing in the background. I am using the well known Camera2Basic (albeit now heavily modified). Everything runs great, but there is an obvious issue - when the user requests the camera for something (like launching a camera app to take a photo), my Camera2 quits, please see the LOGCAT:
E/Camera: Error 2
I/RequestThread-1: Flushing all pending requests.
I/RequestQueue: Repeating capture request cancelled.
I/CameraDeviceState: Legacy camera service transitioning to state ERROR
E/RequestQueue: cancel failed: no repeating request exists for request id: 0
E/CameraDeviceState: Cannot receive result while in state: 0
W/CaptureCollector: previewProduced called with no preview request on queue!
W/MessageQueue: Handler (android.os.Handler) {32bb202} sending message to a Handler on a dead thread
java.lang.IllegalStateException: Handler (android.os.Handler) {32bb202} sending message to a Handler on a dead thread
... (irrelevant) ...
at android.os.Looper.loop(Looper.java:154)
at android.os.HandlerThread.run(HandlerThread.java:61)
E/MyApp: disconnected
D/gralloc: gralloc_lock_ycbcr success. format : 11, usage: 3, ycbcr.y: 0x66903000, .cb: 0x66afd401, .cr: 0x66afd400, .ystride: 1920 , .cstride: 1920, .chroma_step: 2
E/BufferItemConsumer: [ImageReader-1920x1080f23m1-19683-0] Failed to release buffer: Unknown error -1 (1)
E/MyApp: closed
Now... in Camera1 API I was able to intercept and act precisely at the moment the E/Camera Error 2 was reported, using this:
mCamera.setErrorCallback(errorCallback);
But in Camera2 API the situation is funny because even though I have configured my StateCallback (please notice the Log.e() correspond to the above LOGCAT output), the onError() doesn't fire at all and onClosed() and onDisconnected() trigger too late (!):
private CameraDevice.StateCallback mStateCallback = new CameraDevice.StateCallback() {
@Override
public void onOpened(@NonNull CameraDevice cameraDevice) {
mCameraOpenCloseLock.release();
mCameraDevice = cameraDevice;
createCameraPreviewSession();
}
@Override
public void onDisconnected(@NonNull CameraDevice cameraDevice) {
mCameraOpenCloseLock.release();
cameraDevice.close();
mCameraDevice = null;
Log.e("MyApp", "disconnected");
}
@Override
public void onClosed(@NonNull CameraDevice cameraDevice) {
super.onClosed(cameraDevice);
Log.e("MyApp", "closed");
}
@Override
public void onError(@NonNull CameraDevice cameraDevice, int error) {
Log.e("MyApp", "Here we are "+error);
mCameraOpenCloseLock.release();
cameraDevice.close();
mCameraDevice = null;
}
};
Why wouldn't onError() trigger in case the camera becomes taken over by a user's request? How can I detect such a condition? I think that being able to "tap into" any of the following events would do the trick:
I/CameraDeviceState: Legacy camera service transitioning to state ERROR
E/RequestQueue: cancel failed: no repeating request exists for request id: 0
E/CameraDeviceState: Cannot receive result while in state: 0
Thank you kindly for any feedback. M.