Merge "Make ImageWriter thread safe" into tm-qpr-dev am: 59294af84a

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/20724431

Change-Id: I9cba19f0bf6de8339e9e972895169e7837b96bb1
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Avichal Rakesh
2022-12-15 19:27:04 +00:00
committed by Automerger Merge Worker

View File

@@ -99,6 +99,8 @@ public class ImageWriter implements AutoCloseable {
private final Object mListenerLock = new Object(); private final Object mListenerLock = new Object();
private OnImageReleasedListener mListener; private OnImageReleasedListener mListener;
private ListenerHandler mListenerHandler; private ListenerHandler mListenerHandler;
private final Object mCloseLock = new Object();
private boolean mIsWriterValid = false;
private long mNativeContext; private long mNativeContext;
private int mWidth; private int mWidth;
@@ -282,6 +284,8 @@ public class ImageWriter implements AutoCloseable {
mEstimatedNativeAllocBytes = ImageUtils.getEstimatedNativeAllocBytes(mWidth, mHeight, mEstimatedNativeAllocBytes = ImageUtils.getEstimatedNativeAllocBytes(mWidth, mHeight,
imageFormat, /*buffer count*/ 1); imageFormat, /*buffer count*/ 1);
VMRuntime.getRuntime().registerNativeAllocation(mEstimatedNativeAllocBytes); VMRuntime.getRuntime().registerNativeAllocation(mEstimatedNativeAllocBytes);
mIsWriterValid = true;
} }
private ImageWriter(Surface surface, int maxImages, boolean useSurfaceImageFormatInfo, private ImageWriter(Surface surface, int maxImages, boolean useSurfaceImageFormatInfo,
@@ -427,8 +431,10 @@ public class ImageWriter implements AutoCloseable {
* @see Image#close * @see Image#close
*/ */
public Image dequeueInputImage() { public Image dequeueInputImage() {
synchronized (mCloseLock) {
if (mDequeuedImages.size() >= mMaxImages) { if (mDequeuedImages.size() >= mMaxImages) {
throw new IllegalStateException("Already dequeued max number of Images " + mMaxImages); throw new IllegalStateException(
"Already dequeued max number of Images " + mMaxImages);
} }
WriterSurfaceImage newImage = new WriterSurfaceImage(this); WriterSurfaceImage newImage = new WriterSurfaceImage(this);
nativeDequeueInputImage(mNativeContext, newImage); nativeDequeueInputImage(mNativeContext, newImage);
@@ -436,6 +442,7 @@ public class ImageWriter implements AutoCloseable {
newImage.mIsImageValid = true; newImage.mIsImageValid = true;
return newImage; return newImage;
} }
}
/** /**
* <p> * <p>
@@ -492,6 +499,8 @@ public class ImageWriter implements AutoCloseable {
if (image == null) { if (image == null) {
throw new IllegalArgumentException("image shouldn't be null"); throw new IllegalArgumentException("image shouldn't be null");
} }
synchronized (mCloseLock) {
boolean ownedByMe = isImageOwnedByMe(image); boolean ownedByMe = isImageOwnedByMe(image);
if (ownedByMe && !(((WriterSurfaceImage) image).mIsImageValid)) { if (ownedByMe && !(((WriterSurfaceImage) image).mIsImageValid)) {
throw new IllegalStateException("Image from ImageWriter is invalid"); throw new IllegalStateException("Image from ImageWriter is invalid");
@@ -505,7 +514,8 @@ public class ImageWriter implements AutoCloseable {
prevOwner.detachImage(image); prevOwner.detachImage(image);
} else if (image.getOwner() != null) { } else if (image.getOwner() != null) {
throw new IllegalArgumentException("Only images from ImageReader can be queued to" throw new IllegalArgumentException(
"Only images from ImageReader can be queued to"
+ " ImageWriter, other image source is not supported yet!"); + " ImageWriter, other image source is not supported yet!");
} }
@@ -537,6 +547,7 @@ public class ImageWriter implements AutoCloseable {
wi.mIsImageValid = false; wi.mIsImageValid = false;
} }
} }
}
/** /**
* Get the ImageWriter format. * Get the ImageWriter format.
@@ -670,6 +681,10 @@ public class ImageWriter implements AutoCloseable {
*/ */
@Override @Override
public void close() { public void close() {
synchronized (mCloseLock) {
if (!mIsWriterValid) {
return;
}
setOnImageReleasedListener(null, null); setOnImageReleasedListener(null, null);
for (Image image : mDequeuedImages) { for (Image image : mDequeuedImages) {
image.close(); image.close();
@@ -682,6 +697,8 @@ public class ImageWriter implements AutoCloseable {
VMRuntime.getRuntime().registerNativeFree(mEstimatedNativeAllocBytes); VMRuntime.getRuntime().registerNativeFree(mEstimatedNativeAllocBytes);
mEstimatedNativeAllocBytes = 0; mEstimatedNativeAllocBytes = 0;
} }
mIsWriterValid = false;
}
} }
@Override @Override
@@ -771,10 +788,16 @@ public class ImageWriter implements AutoCloseable {
@Override @Override
public void handleMessage(Message msg) { public void handleMessage(Message msg) {
OnImageReleasedListener listener; OnImageReleasedListener listener;
synchronized (mListenerLock) { boolean isWriterValid;
synchronized (ImageWriter.this.mListenerLock) {
listener = mListener; listener = mListener;
} }
if (listener != null) { // Check to make sure we don't accidentally queue images after the writer is
// closed or closing
synchronized (ImageWriter.this.mCloseLock) {
isWriterValid = ImageWriter.this.mIsWriterValid;
}
if (listener != null && isWriterValid) {
listener.onImageReleased(ImageWriter.this); listener.onImageReleased(ImageWriter.this);
} }
} }
@@ -794,10 +817,14 @@ public class ImageWriter implements AutoCloseable {
} }
final Handler handler; final Handler handler;
final boolean isWriterValid;
synchronized (iw.mListenerLock) { synchronized (iw.mListenerLock) {
handler = iw.mListenerHandler; handler = iw.mListenerHandler;
} }
if (handler != null) { synchronized (iw.mCloseLock) {
isWriterValid = iw.mIsWriterValid;
}
if (handler != null && isWriterValid) {
handler.sendEmptyMessage(0); handler.sendEmptyMessage(0);
} }
} }
@@ -1031,6 +1058,9 @@ public class ImageWriter implements AutoCloseable {
private int mTransform = 0; //Default no transform private int mTransform = 0; //Default no transform
private int mScalingMode = 0; //Default frozen scaling mode private int mScalingMode = 0; //Default frozen scaling mode
private final Object mCloseLock = new Object(); // lock to protect against multiple
// simultaneous calls to close()
public WriterSurfaceImage(ImageWriter writer) { public WriterSurfaceImage(ImageWriter writer) {
mOwner = writer; mOwner = writer;
mWidth = writer.mWidth; mWidth = writer.mWidth;
@@ -1172,10 +1202,12 @@ public class ImageWriter implements AutoCloseable {
@Override @Override
public void close() { public void close() {
synchronized (mCloseLock) {
if (mIsImageValid) { if (mIsImageValid) {
getOwner().abortImage(this); getOwner().abortImage(this);
} }
} }
}
@Override @Override
protected final void finalize() throws Throwable { protected final void finalize() throws Throwable {