Loading media/java/android/media/ImageReader.java +52 −9 Original line number Diff line number Diff line Loading @@ -18,7 +18,11 @@ package android.media; import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SuppressLint; import android.app.compat.CompatChanges; import android.compat.annotation.ChangeId; import android.compat.annotation.EnabledAfter; import android.graphics.GraphicBuffer; import android.graphics.ImageFormat; import android.graphics.ImageFormat.Format; Loading @@ -29,6 +33,7 @@ import android.hardware.HardwareBuffer; import android.hardware.HardwareBuffer.Usage; import android.hardware.SyncFence; import android.hardware.camera2.MultiResolutionImageReader; import android.os.Build; import android.os.Handler; import android.os.Looper; import android.os.ParcelFileDescriptor; Loading Loading @@ -85,6 +90,38 @@ public class ImageReader implements AutoCloseable { */ private static final int ACQUIRE_MAX_IMAGES = 2; /** * <p> * Flag to gate correct exception thrown by {@code #detachImage}. * </p> * <p> * {@code #detachImage} is documented as throwing {@link java.lang.IllegalStateException} in * the event of an error; a native helper method to this threw * {@link java.lang.RuntimeException} if the surface was abandoned while detaching the * {@code Image}. * <p> * This previously undocumented exception behavior continues through Android T. * </p> * <p> * After Android T, the native helper method only throws {@code IllegalStateExceptions} in * accordance with the documentation. * </p> * <p> * {@code #detachImage} will now throw only ISEs if it runs into errors while detaching * the image. Behavior on apps targeting API levels <= T remains unchanged. * </p> */ @ChangeId @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.TIRAMISU) private static final long DETACH_THROWS_ISE_ONLY = 236825255L; /** * Cached value of {@link #DETACH_THROWS_ISE_ONLY} flag to prevent repeated calls when * detaching image. */ private final boolean mDetachThrowsIseOnly = CompatChanges.isChangeEnabled(DETACH_THROWS_ISE_ONLY); /** * <p> * Create a new reader for images of the desired size and format. Loading Loading @@ -825,10 +862,10 @@ public class ImageReader implements AutoCloseable { * </p> * <p> * After this call, the ImageReader no longer owns this image, and the image * ownership can be transfered to another entity like {@link ImageWriter} * ownership can be transferred to another entity like {@link ImageWriter} * via {@link ImageWriter#queueInputImage}. It's up to the new owner to * release the resources held by this image. For example, if the ownership * of this image is transfered to an {@link ImageWriter}, the image will be * of this image is transferred to an {@link ImageWriter}, the image will be * freed by the ImageWriter after the image data consumption is done. * </p> * <p> Loading @@ -849,9 +886,15 @@ public class ImageReader implements AutoCloseable { * @throws IllegalStateException If the ImageReader or image have been * closed, or the has been detached, or has not yet been * acquired. * @throws RuntimeException If there is an error detaching {@code Image} from {@code Surface}. * {@code RuntimeException} is only thrown for applications targeting SDK <= * {@link android.os.Build.VERSION_CODES#TIRAMISU}. * For applications targeting SDK > * {@link android.os.Build.VERSION_CODES#TIRAMISU}, * this method only throws {@code IllegalStateException}. * @hide */ public void detachImage(Image image) { public void detachImage(@Nullable Image image) { if (image == null) { throw new IllegalArgumentException("input image must not be null"); } Loading @@ -867,7 +910,7 @@ public class ImageReader implements AutoCloseable { throw new IllegalStateException("Image was already detached from this ImageReader"); } nativeDetachImage(image); nativeDetachImage(image, mDetachThrowsIseOnly); si.clearSurfacePlanes(); si.mPlanes = null; si.setDetached(true); Loading Loading @@ -1408,7 +1451,7 @@ public class ImageReader implements AutoCloseable { private synchronized native void nativeClose(); private synchronized native void nativeReleaseImage(Image i); private synchronized native Surface nativeGetSurface(); private synchronized native int nativeDetachImage(Image i); private synchronized native int nativeDetachImage(Image i, boolean throwISEOnly); private synchronized native void nativeDiscardFreeBuffers(); /** Loading media/jni/android_media_ImageReader.cpp +9 −4 Original line number Diff line number Diff line Loading @@ -643,7 +643,8 @@ static jint ImageReader_imageSetup(JNIEnv* env, jobject thiz, jobject image, return ACQUIRE_SUCCESS; } static jint ImageReader_detachImage(JNIEnv* env, jobject thiz, jobject image) { static jint ImageReader_detachImage(JNIEnv* env, jobject thiz, jobject image, jboolean throwISEOnly) { ALOGV("%s:", __FUNCTION__); JNIImageReaderContext* ctx = ImageReader_getContext(env, thiz); if (ctx == NULL) { Loading @@ -666,8 +667,12 @@ static jint ImageReader_detachImage(JNIEnv* env, jobject thiz, jobject image) { res = bufferConsumer->detachBuffer(buffer->mSlot); if (res != OK) { ALOGE("Image detach failed: %s (%d)!!!", strerror(-res), res); jniThrowRuntimeException(env, if ((bool) throwISEOnly) { jniThrowException(env, "java/lang/IllegalStateException", "nativeDetachImage failed for image!!!"); } else { jniThrowRuntimeException(env, "nativeDetachImage failed for image!!!"); } return res; } return OK; Loading Loading @@ -965,7 +970,7 @@ static const JNINativeMethod gImageReaderMethods[] = { {"nativeReleaseImage", "(Landroid/media/Image;)V", (void*)ImageReader_imageRelease }, {"nativeImageSetup", "(Landroid/media/Image;Z)I", (void*)ImageReader_imageSetup }, {"nativeGetSurface", "()Landroid/view/Surface;", (void*)ImageReader_getSurface }, {"nativeDetachImage", "(Landroid/media/Image;)I", (void*)ImageReader_detachImage }, {"nativeDetachImage", "(Landroid/media/Image;Z)I", (void*)ImageReader_detachImage }, {"nativeCreateImagePlanes", "(ILandroid/graphics/GraphicBuffer;IIIIII)[Landroid/media/ImageReader$ImagePlane;", (void*)ImageReader_createImagePlanes }, Loading Loading
media/java/android/media/ImageReader.java +52 −9 Original line number Diff line number Diff line Loading @@ -18,7 +18,11 @@ package android.media; import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SuppressLint; import android.app.compat.CompatChanges; import android.compat.annotation.ChangeId; import android.compat.annotation.EnabledAfter; import android.graphics.GraphicBuffer; import android.graphics.ImageFormat; import android.graphics.ImageFormat.Format; Loading @@ -29,6 +33,7 @@ import android.hardware.HardwareBuffer; import android.hardware.HardwareBuffer.Usage; import android.hardware.SyncFence; import android.hardware.camera2.MultiResolutionImageReader; import android.os.Build; import android.os.Handler; import android.os.Looper; import android.os.ParcelFileDescriptor; Loading Loading @@ -85,6 +90,38 @@ public class ImageReader implements AutoCloseable { */ private static final int ACQUIRE_MAX_IMAGES = 2; /** * <p> * Flag to gate correct exception thrown by {@code #detachImage}. * </p> * <p> * {@code #detachImage} is documented as throwing {@link java.lang.IllegalStateException} in * the event of an error; a native helper method to this threw * {@link java.lang.RuntimeException} if the surface was abandoned while detaching the * {@code Image}. * <p> * This previously undocumented exception behavior continues through Android T. * </p> * <p> * After Android T, the native helper method only throws {@code IllegalStateExceptions} in * accordance with the documentation. * </p> * <p> * {@code #detachImage} will now throw only ISEs if it runs into errors while detaching * the image. Behavior on apps targeting API levels <= T remains unchanged. * </p> */ @ChangeId @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.TIRAMISU) private static final long DETACH_THROWS_ISE_ONLY = 236825255L; /** * Cached value of {@link #DETACH_THROWS_ISE_ONLY} flag to prevent repeated calls when * detaching image. */ private final boolean mDetachThrowsIseOnly = CompatChanges.isChangeEnabled(DETACH_THROWS_ISE_ONLY); /** * <p> * Create a new reader for images of the desired size and format. Loading Loading @@ -825,10 +862,10 @@ public class ImageReader implements AutoCloseable { * </p> * <p> * After this call, the ImageReader no longer owns this image, and the image * ownership can be transfered to another entity like {@link ImageWriter} * ownership can be transferred to another entity like {@link ImageWriter} * via {@link ImageWriter#queueInputImage}. It's up to the new owner to * release the resources held by this image. For example, if the ownership * of this image is transfered to an {@link ImageWriter}, the image will be * of this image is transferred to an {@link ImageWriter}, the image will be * freed by the ImageWriter after the image data consumption is done. * </p> * <p> Loading @@ -849,9 +886,15 @@ public class ImageReader implements AutoCloseable { * @throws IllegalStateException If the ImageReader or image have been * closed, or the has been detached, or has not yet been * acquired. * @throws RuntimeException If there is an error detaching {@code Image} from {@code Surface}. * {@code RuntimeException} is only thrown for applications targeting SDK <= * {@link android.os.Build.VERSION_CODES#TIRAMISU}. * For applications targeting SDK > * {@link android.os.Build.VERSION_CODES#TIRAMISU}, * this method only throws {@code IllegalStateException}. * @hide */ public void detachImage(Image image) { public void detachImage(@Nullable Image image) { if (image == null) { throw new IllegalArgumentException("input image must not be null"); } Loading @@ -867,7 +910,7 @@ public class ImageReader implements AutoCloseable { throw new IllegalStateException("Image was already detached from this ImageReader"); } nativeDetachImage(image); nativeDetachImage(image, mDetachThrowsIseOnly); si.clearSurfacePlanes(); si.mPlanes = null; si.setDetached(true); Loading Loading @@ -1408,7 +1451,7 @@ public class ImageReader implements AutoCloseable { private synchronized native void nativeClose(); private synchronized native void nativeReleaseImage(Image i); private synchronized native Surface nativeGetSurface(); private synchronized native int nativeDetachImage(Image i); private synchronized native int nativeDetachImage(Image i, boolean throwISEOnly); private synchronized native void nativeDiscardFreeBuffers(); /** Loading
media/jni/android_media_ImageReader.cpp +9 −4 Original line number Diff line number Diff line Loading @@ -643,7 +643,8 @@ static jint ImageReader_imageSetup(JNIEnv* env, jobject thiz, jobject image, return ACQUIRE_SUCCESS; } static jint ImageReader_detachImage(JNIEnv* env, jobject thiz, jobject image) { static jint ImageReader_detachImage(JNIEnv* env, jobject thiz, jobject image, jboolean throwISEOnly) { ALOGV("%s:", __FUNCTION__); JNIImageReaderContext* ctx = ImageReader_getContext(env, thiz); if (ctx == NULL) { Loading @@ -666,8 +667,12 @@ static jint ImageReader_detachImage(JNIEnv* env, jobject thiz, jobject image) { res = bufferConsumer->detachBuffer(buffer->mSlot); if (res != OK) { ALOGE("Image detach failed: %s (%d)!!!", strerror(-res), res); jniThrowRuntimeException(env, if ((bool) throwISEOnly) { jniThrowException(env, "java/lang/IllegalStateException", "nativeDetachImage failed for image!!!"); } else { jniThrowRuntimeException(env, "nativeDetachImage failed for image!!!"); } return res; } return OK; Loading Loading @@ -965,7 +970,7 @@ static const JNINativeMethod gImageReaderMethods[] = { {"nativeReleaseImage", "(Landroid/media/Image;)V", (void*)ImageReader_imageRelease }, {"nativeImageSetup", "(Landroid/media/Image;Z)I", (void*)ImageReader_imageSetup }, {"nativeGetSurface", "()Landroid/view/Surface;", (void*)ImageReader_getSurface }, {"nativeDetachImage", "(Landroid/media/Image;)I", (void*)ImageReader_detachImage }, {"nativeDetachImage", "(Landroid/media/Image;Z)I", (void*)ImageReader_detachImage }, {"nativeCreateImagePlanes", "(ILandroid/graphics/GraphicBuffer;IIIIII)[Landroid/media/ImageReader$ImagePlane;", (void*)ImageReader_createImagePlanes }, Loading