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:
@@ -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 {
|
||||||
|
|||||||
Reference in New Issue
Block a user