diff options
| -rw-r--r-- | core/java/android/hardware/camera2/CameraCaptureSession.java | 5 | ||||
| -rw-r--r-- | media/java/android/media/ImageWriter.java | 24 | ||||
| -rw-r--r-- | media/jni/android_media_ImageWriter.cpp | 44 |
3 files changed, 60 insertions, 13 deletions
diff --git a/core/java/android/hardware/camera2/CameraCaptureSession.java b/core/java/android/hardware/camera2/CameraCaptureSession.java index c547b06d72b0..62ebfb36f3a6 100644 --- a/core/java/android/hardware/camera2/CameraCaptureSession.java +++ b/core/java/android/hardware/camera2/CameraCaptureSession.java @@ -497,8 +497,9 @@ public abstract class CameraCaptureSession implements AutoCloseable { * * <p>Each reprocessable capture session has an input {@link Surface} where the reprocess * capture requests get the input images from, rather than the camera device. The application - * can create a {@link android.media.ImageWriter} with this input {@link Surface} and use it to - * provide input images for reprocess capture requests.</p> + * can create a {@link android.media.ImageWriter ImageWriter} with this input {@link Surface} + * and use it to provide input images for reprocess capture requests. When the reprocessable + * capture session is closed, the input {@link Surface} is abandoned and becomes invalid.</p> * * @return The {@link Surface} where reprocessing capture requests get the input images from. If * this is not a reprocess capture session, {@code null} will be returned. diff --git a/media/java/android/media/ImageWriter.java b/media/java/android/media/ImageWriter.java index 2ef251959a4d..9fb328627612 100644 --- a/media/java/android/media/ImageWriter.java +++ b/media/java/android/media/ImageWriter.java @@ -40,8 +40,8 @@ import java.util.List; * Several Android API classes can provide input {@link android.view.Surface * Surface} objects for ImageWriter to produce data into, including * {@link MediaCodec MediaCodec} (encoder), - * {@link android.hardware.camera2.CameraDevice CameraDevice} (reprocessing - * input), {@link ImageReader}, etc. + * {@link android.hardware.camera2.CameraCaptureSession CameraCaptureSession} + * (reprocessing input), {@link ImageReader}, etc. * </p> * <p> * The input Image data is encapsulated in {@link Image} objects. To produce @@ -64,7 +64,14 @@ import java.util.List; * {@link android.hardware.camera2.CameraDevice}) to consume the Images. If the * downstream components cannot consume the Images at least as fast as the * ImageWriter production rate, the {@link #dequeueInputImage} call will - * eventually block and the application will have to drop input frames. </p> + * eventually block and the application will have to drop input frames. + * </p> + * <p> + * If the consumer component that provided the input {@link android.view.Surface Surface} + * abandons the {@link android.view.Surface Surface}, {@link #queueInputImage queueing} + * or {@link #dequeueInputImage dequeueing} an {@link Image} will throw an + * {@link IllegalStateException}. + * </p> */ public class ImageWriter implements AutoCloseable { private final Object mListenerLock = new Object(); @@ -188,7 +195,9 @@ public class ImageWriter implements AutoCloseable { * @return The next available input Image from this ImageWriter. * @throws IllegalStateException if {@code maxImages} Images are currently * dequeued, or the ImageWriter format is - * {@link ImageFormat#PRIVATE PRIVATE}. + * {@link ImageFormat#PRIVATE PRIVATE}, or the input + * {@link android.view.Surface Surface} has been abandoned by the + * consumer component that provided the {@link android.view.Surface Surface}. * @see #queueInputImage * @see Image#close */ @@ -254,6 +263,11 @@ public class ImageWriter implements AutoCloseable { * * @param image The Image to be queued back to ImageWriter for future * consumption. + * @throws IllegalStateException if the image was already queued previously, + * or the image was aborted previously, or the input + * {@link android.view.Surface Surface} has been abandoned by the + * consumer component that provided the + * {@link android.view.Surface Surface}. * @see #dequeueInputImage() */ public void queueInputImage(Image image) { @@ -699,7 +713,7 @@ public class ImageWriter implements AutoCloseable { } private void clearSurfacePlanes() { - if (mIsImageValid) { + if (mIsImageValid && mPlanes != null) { for (int i = 0; i < mPlanes.length; i++) { if (mPlanes[i] != null) { mPlanes[i].clearBuffer(); diff --git a/media/jni/android_media_ImageWriter.cpp b/media/jni/android_media_ImageWriter.cpp index ba7634cd3276..f92a8eff3919 100644 --- a/media/jni/android_media_ImageWriter.cpp +++ b/media/jni/android_media_ImageWriter.cpp @@ -338,9 +338,16 @@ static void ImageWriter_dequeueImage(JNIEnv* env, jobject thiz, jlong nativeCtx, int fenceFd = -1; status_t res = anw->dequeueBuffer(anw.get(), &anb, &fenceFd); if (res != OK) { - // TODO: handle different error cases here. ALOGE("%s: Dequeue buffer failed: %s (%d)", __FUNCTION__, strerror(-res), res); - jniThrowRuntimeException(env, "dequeue buffer failed"); + switch (res) { + case NO_INIT: + jniThrowException(env, "java/lang/IllegalStateException", + "Surface has been abandoned"); + break; + default: + // TODO: handle other error cases here. + jniThrowRuntimeException(env, "dequeue buffer failed"); + } return; } // New GraphicBuffer object doesn't own the handle, thus the native buffer @@ -468,7 +475,16 @@ static void ImageWriter_queueImage(JNIEnv* env, jobject thiz, jlong nativeCtx, j // Finally, queue input buffer res = anw->queueBuffer(anw.get(), buffer, fenceFd); if (res != OK) { - jniThrowRuntimeException(env, "Queue input buffer failed"); + ALOGE("%s: Queue buffer failed: %s (%d)", __FUNCTION__, strerror(-res), res); + switch (res) { + case NO_INIT: + jniThrowException(env, "java/lang/IllegalStateException", + "Surface has been abandoned"); + break; + default: + // TODO: handle other error cases here. + jniThrowRuntimeException(env, "Queue input buffer failed"); + } return; } @@ -514,9 +530,16 @@ static jint ImageWriter_attachAndQueueImage(JNIEnv* env, jobject thiz, jlong nat // Step 1. Attach Image res = surface->attachBuffer(opaqueBuffer->mGraphicBuffer.get()); if (res != OK) { - // TODO: handle different error case separately. ALOGE("Attach image failed: %s (%d)", strerror(-res), res); - jniThrowRuntimeException(env, "nativeAttachImage failed!!!"); + switch (res) { + case NO_INIT: + jniThrowException(env, "java/lang/IllegalStateException", + "Surface has been abandoned"); + break; + default: + // TODO: handle other error cases here. + jniThrowRuntimeException(env, "nativeAttachImage failed!!!"); + } return res; } sp < ANativeWindow > anw = surface; @@ -545,7 +568,16 @@ static jint ImageWriter_attachAndQueueImage(JNIEnv* env, jobject thiz, jlong nat res = anw->queueBuffer(anw.get(), opaqueBuffer->mGraphicBuffer.get(), /*fenceFd*/ -1); if (res != OK) { - jniThrowRuntimeException(env, "Queue input buffer failed"); + ALOGE("%s: Queue buffer failed: %s (%d)", __FUNCTION__, strerror(-res), res); + switch (res) { + case NO_INIT: + jniThrowException(env, "java/lang/IllegalStateException", + "Surface has been abandoned"); + break; + default: + // TODO: handle other error cases here. + jniThrowRuntimeException(env, "Queue input buffer failed"); + } return res; } |