Merge "camera2: Make legacy error handling more robust." into lmp-mr1-dev

This commit is contained in:
Ruben Brunk
2015-02-05 19:54:36 +00:00
committed by Android (Google) Code Review

View File

@@ -44,6 +44,7 @@ import java.util.Collections;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import static com.android.internal.util.Preconditions.*; import static com.android.internal.util.Preconditions.*;
@@ -68,7 +69,7 @@ public class RequestThreadManager {
// For slightly more spammy messages that will get repeated every frame // For slightly more spammy messages that will get repeated every frame
private static final boolean VERBOSE = private static final boolean VERBOSE =
Log.isLoggable(LegacyCameraDevice.DEBUG_PROP, Log.VERBOSE); Log.isLoggable(LegacyCameraDevice.DEBUG_PROP, Log.VERBOSE);
private final Camera mCamera; private Camera mCamera;
private final CameraCharacteristics mCharacteristics; private final CameraCharacteristics mCharacteristics;
private final CameraDeviceState mDeviceState; private final CameraDeviceState mDeviceState;
@@ -83,8 +84,8 @@ public class RequestThreadManager {
private static final int MAX_IN_FLIGHT_REQUESTS = 2; private static final int MAX_IN_FLIGHT_REQUESTS = 2;
private static final int PREVIEW_FRAME_TIMEOUT = 1000; // ms private static final int PREVIEW_FRAME_TIMEOUT = 1000; // ms
private static final int JPEG_FRAME_TIMEOUT = 3000; // ms (same as CTS for API2) private static final int JPEG_FRAME_TIMEOUT = 4000; // ms (same as CTS for API2)
private static final int REQUEST_COMPLETE_TIMEOUT = 3000; // ms (same as JPEG timeout) private static final int REQUEST_COMPLETE_TIMEOUT = JPEG_FRAME_TIMEOUT; // ms (same as JPEG timeout)
private static final float ASPECT_RATIO_TOLERANCE = 0.01f; private static final float ASPECT_RATIO_TOLERANCE = 0.01f;
private boolean mPreviewRunning = false; private boolean mPreviewRunning = false;
@@ -108,6 +109,8 @@ public class RequestThreadManager {
private final FpsCounter mPrevCounter = new FpsCounter("Incoming Preview"); private final FpsCounter mPrevCounter = new FpsCounter("Incoming Preview");
private final FpsCounter mRequestCounter = new FpsCounter("Incoming Requests"); private final FpsCounter mRequestCounter = new FpsCounter("Incoming Requests");
private final AtomicBoolean mQuit = new AtomicBoolean(false);
// Stuff JPEGs into HAL_PIXEL_FORMAT_RGBA_8888 gralloc buffers to get around SW write // Stuff JPEGs into HAL_PIXEL_FORMAT_RGBA_8888 gralloc buffers to get around SW write
// limitations for (b/17379185). // limitations for (b/17379185).
private static final boolean USE_BLOB_FORMAT_OVERRIDE = true; private static final boolean USE_BLOB_FORMAT_OVERRIDE = true;
@@ -325,7 +328,15 @@ public class RequestThreadManager {
Log.d(TAG, "configureOutputs with " + outputsStr); Log.d(TAG, "configureOutputs with " + outputsStr);
} }
try {
stopPreview(); stopPreview();
} catch (RuntimeException e) {
Log.e(TAG, "Received device exception in configure call: ", e);
mDeviceState.setError(
CameraDeviceImpl.CameraDeviceCallbacks.ERROR_CAMERA_DEVICE);
return;
}
/* /*
* Try to release the previous preview's surface texture earlier if we end up * Try to release the previous preview's surface texture earlier if we end up
* using a different one; this also reduces the likelihood of getting into a deadlock * using a different one; this also reduces the likelihood of getting into a deadlock
@@ -335,6 +346,11 @@ public class RequestThreadManager {
mCamera.setPreviewTexture(/*surfaceTexture*/null); mCamera.setPreviewTexture(/*surfaceTexture*/null);
} catch (IOException e) { } catch (IOException e) {
Log.w(TAG, "Failed to clear prior SurfaceTexture, may cause GL deadlock: ", e); Log.w(TAG, "Failed to clear prior SurfaceTexture, may cause GL deadlock: ", e);
} catch (RuntimeException e) {
Log.e(TAG, "Received device exception in configure call: ", e);
mDeviceState.setError(
CameraDeviceImpl.CameraDeviceCallbacks.ERROR_CAMERA_DEVICE);
return;
} }
if (mGLThreadManager != null) { if (mGLThreadManager != null) {
@@ -470,7 +486,14 @@ public class RequestThreadManager {
mPreviewTexture.setOnFrameAvailableListener(mPreviewCallback); mPreviewTexture.setOnFrameAvailableListener(mPreviewCallback);
} }
try {
mCamera.setParameters(mParams); mCamera.setParameters(mParams);
} catch (RuntimeException e) {
Log.e(TAG, "Received device exception while configuring: ", e);
mDeviceState.setError(
CameraDeviceImpl.CameraDeviceCallbacks.ERROR_CAMERA_DEVICE);
}
} }
private void resetJpegSurfaceFormats(Collection<Surface> surfaces) { private void resetJpegSurfaceFormats(Collection<Surface> surfaces) {
@@ -793,7 +816,7 @@ public class RequestThreadManager {
} }
} catch (IOException e) { } catch (IOException e) {
Log.e(TAG, "Received device exception: ", e); Log.e(TAG, "Received device exception during capture call: ", e);
mDeviceState.setError( mDeviceState.setError(
CameraDeviceImpl.CameraDeviceCallbacks.ERROR_CAMERA_DEVICE); CameraDeviceImpl.CameraDeviceCallbacks.ERROR_CAMERA_DEVICE);
break; break;
@@ -802,6 +825,11 @@ public class RequestThreadManager {
mDeviceState.setError( mDeviceState.setError(
CameraDeviceImpl.CameraDeviceCallbacks.ERROR_CAMERA_DEVICE); CameraDeviceImpl.CameraDeviceCallbacks.ERROR_CAMERA_DEVICE);
break; break;
} catch (RuntimeException e) {
Log.e(TAG, "Received device exception during capture call: ", e);
mDeviceState.setError(
CameraDeviceImpl.CameraDeviceCallbacks.ERROR_CAMERA_DEVICE);
break;
} }
if (paramsChanged) { if (paramsChanged) {
@@ -878,9 +906,11 @@ public class RequestThreadManager {
} }
if (mGLThreadManager != null) { if (mGLThreadManager != null) {
mGLThreadManager.quit(); mGLThreadManager.quit();
mGLThreadManager = null;
} }
if (mCamera != null) { if (mCamera != null) {
mCamera.release(); mCamera.release();
mCamera = null;
} }
resetJpegSurfaceFormats(mCallbackOutputs); resetJpegSurfaceFormats(mCallbackOutputs);
break; break;
@@ -942,6 +972,7 @@ public class RequestThreadManager {
* Quit the request thread, and clean up everything. * Quit the request thread, and clean up everything.
*/ */
public void quit() { public void quit() {
if (!mQuit.getAndSet(true)) { // Avoid sending messages on dead thread's handler.
Handler handler = mRequestThread.waitAndGetHandler(); Handler handler = mRequestThread.waitAndGetHandler();
handler.sendMessageAtFrontOfQueue(handler.obtainMessage(MSG_CLEANUP)); handler.sendMessageAtFrontOfQueue(handler.obtainMessage(MSG_CLEANUP));
mRequestThread.quitSafely(); mRequestThread.quitSafely();
@@ -952,6 +983,7 @@ public class RequestThreadManager {
mRequestThread.getName(), mRequestThread.getId())); mRequestThread.getName(), mRequestThread.getId()));
} }
} }
}
/** /**
* Submit the given burst of requests to be captured. * Submit the given burst of requests to be captured.