Merge "Camera2: Invoke onError callbacks for failure to open" into lmp-preview-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
b530848032
@@ -226,7 +226,7 @@ public final class CameraManager {
|
||||
|
||||
synchronized (mLock) {
|
||||
|
||||
ICameraDeviceUser cameraUser;
|
||||
ICameraDeviceUser cameraUser = null;
|
||||
|
||||
android.hardware.camera2.impl.CameraDeviceImpl deviceImpl =
|
||||
new android.hardware.camera2.impl.CameraDeviceImpl(
|
||||
@@ -248,8 +248,23 @@ public final class CameraManager {
|
||||
// Use legacy camera implementation for HAL1 devices
|
||||
Log.i(TAG, "Using legacy camera HAL.");
|
||||
cameraUser = CameraDeviceUserShim.connectBinderShim(callbacks, id);
|
||||
} else if (e.getReason() == CameraAccessException.CAMERA_IN_USE ||
|
||||
e.getReason() == CameraAccessException.MAX_CAMERAS_IN_USE ||
|
||||
e.getReason() == CameraAccessException.CAMERA_DISABLED ||
|
||||
e.getReason() == CameraAccessException.CAMERA_DISCONNECTED ||
|
||||
e.getReason() == CameraAccessException.CAMERA_ERROR) {
|
||||
// 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.getReason() == CameraAccessException.CAMERA_DISABLED ||
|
||||
e.getReason() == CameraAccessException.CAMERA_DISCONNECTED) {
|
||||
// Per API docs, these failures call onError and throw
|
||||
throw e;
|
||||
}
|
||||
} else {
|
||||
// Rethrow otherwise
|
||||
// Unexpected failure - rethrow
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
@@ -299,7 +314,7 @@ public final class CameraManager {
|
||||
*
|
||||
* <p>If opening the camera device fails, then the device listener's
|
||||
* {@link CameraDevice.StateListener#onError onError} method will be called, and subsequent
|
||||
* calls on the camera device will throw an {@link IllegalStateException}.</p>
|
||||
* calls on the camera device will throw a {@link CameraAccessException}.</p>
|
||||
*
|
||||
* @param cameraId
|
||||
* The unique identifier of the camera device to open
|
||||
|
||||
@@ -64,6 +64,7 @@ public class CameraDeviceImpl extends android.hardware.camera2.CameraDevice {
|
||||
private volatile StateListener mSessionStateListener;
|
||||
private final Handler mDeviceHandler;
|
||||
|
||||
private boolean mInError = false;
|
||||
private boolean mIdle = true;
|
||||
|
||||
/** map request IDs to listener/request data */
|
||||
@@ -211,6 +212,9 @@ public class CameraDeviceImpl extends android.hardware.camera2.CameraDevice {
|
||||
public void setRemoteDevice(ICameraDeviceUser remoteDevice) {
|
||||
// TODO: Move from decorator to direct binder-mediated exceptions
|
||||
synchronized(mLock) {
|
||||
// If setRemoteFailure already called, do nothing
|
||||
if (mInError) return;
|
||||
|
||||
mRemoteDevice = CameraBinderDecorator.newInstance(remoteDevice);
|
||||
|
||||
mDeviceHandler.post(mCallOnOpened);
|
||||
@@ -218,6 +222,52 @@ public class CameraDeviceImpl extends android.hardware.camera2.CameraDevice {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Call to indicate failed connection to a remote camera device.
|
||||
*
|
||||
* <p>This places the camera device in the error state and informs the listener.
|
||||
* Use in place of setRemoteDevice() when startup fails.</p>
|
||||
*/
|
||||
public void setRemoteFailure(final CameraRuntimeException failure) {
|
||||
int failureCode = StateListener.ERROR_CAMERA_DEVICE;
|
||||
boolean failureIsError = true;
|
||||
|
||||
switch (failure.getReason()) {
|
||||
case CameraAccessException.CAMERA_IN_USE:
|
||||
failureCode = StateListener.ERROR_CAMERA_IN_USE;
|
||||
break;
|
||||
case CameraAccessException.MAX_CAMERAS_IN_USE:
|
||||
failureCode = StateListener.ERROR_MAX_CAMERAS_IN_USE;
|
||||
break;
|
||||
case CameraAccessException.CAMERA_DISABLED:
|
||||
failureCode = StateListener.ERROR_CAMERA_DISABLED;
|
||||
break;
|
||||
case CameraAccessException.CAMERA_DISCONNECTED:
|
||||
failureIsError = false;
|
||||
break;
|
||||
case CameraAccessException.CAMERA_ERROR:
|
||||
failureCode = StateListener.ERROR_CAMERA_DEVICE;
|
||||
break;
|
||||
default:
|
||||
Log.wtf(TAG, "Unknown failure in opening camera device: " + failure.getReason());
|
||||
break;
|
||||
}
|
||||
final int code = failureCode;
|
||||
final boolean isError = failureIsError;
|
||||
synchronized (mLock) {
|
||||
mInError = true;
|
||||
mDeviceHandler.post(new Runnable() {
|
||||
public void run() {
|
||||
if (isError) {
|
||||
mDeviceListener.onError(CameraDeviceImpl.this, code);
|
||||
} else {
|
||||
mDeviceListener.onDisconnected(CameraDeviceImpl.this);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return mCameraId;
|
||||
@@ -230,7 +280,7 @@ public class CameraDeviceImpl extends android.hardware.camera2.CameraDevice {
|
||||
outputs = new ArrayList<Surface>();
|
||||
}
|
||||
synchronized (mLock) {
|
||||
checkIfCameraClosed();
|
||||
checkIfCameraClosedOrInError();
|
||||
|
||||
HashSet<Surface> addSet = new HashSet<Surface>(outputs); // Streams to create
|
||||
List<Integer> deleteList = new ArrayList<Integer>(); // Streams to delete
|
||||
@@ -298,7 +348,7 @@ public class CameraDeviceImpl extends android.hardware.camera2.CameraDevice {
|
||||
Log.d(TAG, "createCaptureSession");
|
||||
}
|
||||
|
||||
checkIfCameraClosed();
|
||||
checkIfCameraClosedOrInError();
|
||||
|
||||
// TODO: we must be in UNCONFIGURED mode to begin with, or using another session
|
||||
|
||||
@@ -336,7 +386,7 @@ public class CameraDeviceImpl extends android.hardware.camera2.CameraDevice {
|
||||
public CaptureRequest.Builder createCaptureRequest(int templateType)
|
||||
throws CameraAccessException {
|
||||
synchronized (mLock) {
|
||||
checkIfCameraClosed();
|
||||
checkIfCameraClosedOrInError();
|
||||
|
||||
CameraMetadataNative templatedRequest = new CameraMetadataNative();
|
||||
|
||||
@@ -456,7 +506,7 @@ public class CameraDeviceImpl extends android.hardware.camera2.CameraDevice {
|
||||
}
|
||||
|
||||
synchronized (mLock) {
|
||||
checkIfCameraClosed();
|
||||
checkIfCameraClosedOrInError();
|
||||
int requestId;
|
||||
|
||||
if (repeating) {
|
||||
@@ -528,7 +578,7 @@ public class CameraDeviceImpl extends android.hardware.camera2.CameraDevice {
|
||||
public void stopRepeating() throws CameraAccessException {
|
||||
|
||||
synchronized (mLock) {
|
||||
checkIfCameraClosed();
|
||||
checkIfCameraClosedOrInError();
|
||||
if (mRepeatingRequestId != REQUEST_ID_NONE) {
|
||||
|
||||
int requestId = mRepeatingRequestId;
|
||||
@@ -559,7 +609,7 @@ public class CameraDeviceImpl extends android.hardware.camera2.CameraDevice {
|
||||
private void waitUntilIdle() throws CameraAccessException {
|
||||
|
||||
synchronized (mLock) {
|
||||
checkIfCameraClosed();
|
||||
checkIfCameraClosedOrInError();
|
||||
if (mRepeatingRequestId != REQUEST_ID_NONE) {
|
||||
throw new IllegalStateException("Active repeating request ongoing");
|
||||
}
|
||||
@@ -580,7 +630,7 @@ public class CameraDeviceImpl extends android.hardware.camera2.CameraDevice {
|
||||
@Override
|
||||
public void flush() throws CameraAccessException {
|
||||
synchronized (mLock) {
|
||||
checkIfCameraClosed();
|
||||
checkIfCameraClosedOrInError();
|
||||
|
||||
mDeviceHandler.post(mCallOnBusy);
|
||||
try {
|
||||
@@ -614,11 +664,15 @@ public class CameraDeviceImpl extends android.hardware.camera2.CameraDevice {
|
||||
// impossible
|
||||
}
|
||||
|
||||
if (mRemoteDevice != null) {
|
||||
// Only want to fire the onClosed callback once;
|
||||
// either a normal close where the remote device is valid
|
||||
// or a close after a startup error (no remote device but in error state)
|
||||
if (mRemoteDevice != null || mInError) {
|
||||
mDeviceHandler.post(mCallOnClosed);
|
||||
}
|
||||
|
||||
mRemoteDevice = null;
|
||||
mInError = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -835,6 +889,7 @@ public class CameraDeviceImpl extends android.hardware.camera2.CameraDevice {
|
||||
if (isClosed()) return;
|
||||
|
||||
synchronized(mLock) {
|
||||
mInError = true;
|
||||
switch (errorCode) {
|
||||
case ERROR_CAMERA_DISCONNECTED:
|
||||
r = mCallOnDisconnected;
|
||||
@@ -1032,7 +1087,11 @@ public class CameraDeviceImpl extends android.hardware.camera2.CameraDevice {
|
||||
return handler;
|
||||
}
|
||||
|
||||
private void checkIfCameraClosed() {
|
||||
private void checkIfCameraClosedOrInError() throws CameraAccessException {
|
||||
if (mInError) {
|
||||
throw new CameraAccessException(CameraAccessException.CAMERA_ERROR,
|
||||
"The camera device has encountered a serious error");
|
||||
}
|
||||
if (mRemoteDevice == null) {
|
||||
throw new IllegalStateException("CameraDevice was already closed");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user