diff options
5 files changed, 87 insertions, 2 deletions
diff --git a/api/current.txt b/api/current.txt index 936eb39..585912e 100644 --- a/api/current.txt +++ b/api/current.txt @@ -10715,6 +10715,7 @@ package android.hardware.camera2 { method public abstract void close() throws java.lang.Exception; method public abstract void configureOutputs(java.util.List<android.view.Surface>) throws android.hardware.camera2.CameraAccessException; method public abstract android.hardware.camera2.CaptureRequest createCaptureRequest(int) throws android.hardware.camera2.CameraAccessException; + method public abstract void flush() throws android.hardware.camera2.CameraAccessException; method public abstract android.hardware.camera2.CameraProperties getProperties() throws android.hardware.camera2.CameraAccessException; method public abstract void setErrorListener(android.hardware.camera2.CameraDevice.ErrorListener); method public abstract void setRepeatingBurst(java.util.List<android.hardware.camera2.CaptureRequest>, android.hardware.camera2.CameraDevice.CaptureListener) throws android.hardware.camera2.CameraAccessException; diff --git a/core/java/android/hardware/camera2/CameraDevice.java b/core/java/android/hardware/camera2/CameraDevice.java index 848d7bc..a4a56d7 100644 --- a/core/java/android/hardware/camera2/CameraDevice.java +++ b/core/java/android/hardware/camera2/CameraDevice.java @@ -303,7 +303,8 @@ public interface CameraDevice extends AutoCloseable { * preview or other continuous stream of frames, without having to submit * requests through {@link #capture} at video rates.</p> * - * <p>To stop the repeating capture, call {@link #stopRepeating}</p> + * <p>To stop the repeating capture, call {@link #stopRepeating}. Calling + * {@link #flush} will also clear the request.</p> * * <p>Calling repeat will replace a burst set up by {@link * #setRepeatingBurst}, although any in-progress burst will be @@ -323,6 +324,8 @@ public interface CameraDevice extends AutoCloseable { * @see #capture * @see #captureBurst * @see #setRepeatingBurst + * @see #stopRepeating + * @see #flush */ public void setRepeatingRequest(CaptureRequest request, CaptureListener listener) throws CameraAccessException; @@ -348,7 +351,8 @@ public interface CameraDevice extends AutoCloseable { * requests through {@link #capture} at video rates.</p> * * <p>To stop the repeating capture, call {@link #stopRepeating}. Any - * ongoing burst will still be completed, however.</p> + * ongoing burst will still be completed, however. Calling + * {@link #flush} will also clear the request.</p> * * <p>Calling repeatBurst will replace a repeating request set up by * {@link #setRepeatingRequest}, although any in-progress capture will be completed @@ -367,6 +371,8 @@ public interface CameraDevice extends AutoCloseable { * @see #capture * @see #captureBurst * @see #setRepeatingRequest + * @see #stopRepeating + * @see #flush */ public void setRepeatingBurst(List<CaptureRequest> requests, CaptureListener listener) throws CameraAccessException; @@ -435,6 +441,38 @@ public interface CameraDevice extends AutoCloseable { public void setErrorListener(ErrorListener listener); /** + * Flush all captures currently pending and in-progress as fast as + * possible. + * + * <p>The camera device will discard all of its current work as fast as + * possible. Some in-flight captures may complete successfully and call + * {@link CaptureListener#onCaptureComplete}, while others will trigger + * their {@link CaptureListener#onCaptureFailed} callbacks. If a repeating + * request or a repeating burst is set, it will be cleared by the flush.</p> + * + * <p>This method is the fastest way to idle the camera device for + * reconfiguration with {@link #configureOutputs}, at the cost of discarding + * in-progress work. Once the flush is complete, the idle callback will be + * called.</p> + * + * <p>Flushing will introduce at least a brief pause in the stream of data + * from the camera device, since once the flush is complete, the first new + * request has to make it through the entire camera pipeline before new + * output buffers are produced.</p> + * + * <p>This means that using {@code flush()} to simply remove pending + * requests is not recommended; it's best used for quickly switching output + * configurations, or for cancelling long in-progress requests (such as a + * multi-second capture).</p> + * + * @throws CameraAccessException if the camera device is no longer connected + * @see #setRepeatingRequest + * @see #setRepeatingBurst + * @see #configureOutputs + */ + public void flush() throws CameraAccessException; + + /** * Close the connection to this camera device. After this call, all calls to * the camera device interface will throw a {@link IllegalStateException}, * except for calls to close(). diff --git a/core/java/android/hardware/camera2/ICameraDeviceUser.aidl b/core/java/android/hardware/camera2/ICameraDeviceUser.aidl index 5a9b72f..b1724de 100644 --- a/core/java/android/hardware/camera2/ICameraDeviceUser.aidl +++ b/core/java/android/hardware/camera2/ICameraDeviceUser.aidl @@ -45,4 +45,6 @@ interface ICameraDeviceUser int getCameraInfo(out CameraMetadata info); int waitUntilIdle(); + + int flush(); } diff --git a/core/java/android/hardware/camera2/impl/CameraDevice.java b/core/java/android/hardware/camera2/impl/CameraDevice.java index e7495d3..ee199bc 100644 --- a/core/java/android/hardware/camera2/impl/CameraDevice.java +++ b/core/java/android/hardware/camera2/impl/CameraDevice.java @@ -242,6 +242,20 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice { } @Override + public void flush() throws CameraAccessException { + synchronized (mLock) { + try { + mRemoteDevice.flush(); + } catch (CameraRuntimeException e) { + throw e.asChecked(); + } catch (RemoteException e) { + // impossible + return; + } + } + } + + @Override public void close() throws Exception { // TODO: every method should throw IllegalStateException after close has been called diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java index 722087c..2f271bb 100644 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java @@ -309,4 +309,34 @@ public class CameraDeviceBinderTest extends AndroidTestCase { argThat(matcher)); request.close(); } + + @SmallTest + public void testFlush() throws Exception { + int status; + + // Initial flush should work + status = mCameraUser.flush(); + assertEquals(CameraBinderTestUtils.NO_ERROR, status); + + // Then set up a stream + CaptureRequest request = createDefaultRequest(/* needStream */true); + + // Flush should still be a no-op, really + status = mCameraUser.flush(); + assertEquals(CameraBinderTestUtils.NO_ERROR, status); + + // Submit a few capture requests + int requestId1 = submitCameraRequest(request, /* streaming */false); + int requestId2 = submitCameraRequest(request, /* streaming */false); + int requestId3 = submitCameraRequest(request, /* streaming */false); + int requestId4 = submitCameraRequest(request, /* streaming */false); + int requestId5 = submitCameraRequest(request, /* streaming */false); + + // Then flush + status = mCameraUser.flush(); + assertEquals(CameraBinderTestUtils.NO_ERROR, status); + + // TODO: When errors are hooked up, count that errors + successful + // requests equal to 5. + } } |