Merge "Revert "Prevent onImageAvailable from being called on stale listeners""

This commit is contained in:
Avichal Rakesh
2022-02-05 00:19:24 +00:00
committed by Android (Google) Code Review

View File

@@ -43,7 +43,6 @@ import java.util.Objects;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.StampedLock;
/**
* <p>The ImageReader class allows direct application access to image data
@@ -676,8 +675,7 @@ public class ImageReader implements AutoCloseable {
* If no handler specified and the calling thread has no looper.
*/
public void setOnImageAvailableListener(OnImageAvailableListener listener, Handler handler) {
long writeStamp = mListenerLock.writeLock();
try {
synchronized (mListenerLock) {
if (listener != null) {
Looper looper = handler != null ? handler.getLooper() : Looper.myLooper();
if (looper == null) {
@@ -693,8 +691,6 @@ public class ImageReader implements AutoCloseable {
mListenerExecutor = null;
}
mListener = listener;
} finally {
mListenerLock.unlockWrite(writeStamp);
}
}
@@ -717,12 +713,9 @@ public class ImageReader implements AutoCloseable {
throw new IllegalArgumentException("executor must not be null");
}
long writeStamp = mListenerLock.writeLock();
try {
synchronized (mListenerLock) {
mListenerExecutor = executor;
mListener = listener;
} finally {
mListenerLock.unlockWrite(writeStamp);
}
}
@@ -738,8 +731,6 @@ public class ImageReader implements AutoCloseable {
/**
* Callback that is called when a new image is available from ImageReader.
*
* This callback must not modify or close the passed {@code reader}.
*
* @param reader the ImageReader the callback is associated with.
* @see ImageReader
* @see Image
@@ -898,41 +889,28 @@ public class ImageReader implements AutoCloseable {
return;
}
synchronized (ir.mCloseLock) {
if (!ir.mIsReaderValid) {
// It's dangerous to fire onImageAvailable() callback when the ImageReader
// is being closed, as application could acquire next image in the
// onImageAvailable() callback.
return;
}
}
final Executor executor;
final long readStamp = ir.mListenerLock.readLock();
try {
final OnImageAvailableListener listener;
synchronized (ir.mListenerLock) {
executor = ir.mListenerExecutor;
if (executor == null) {
return;
}
} finally {
ir.mListenerLock.unlockRead(readStamp);
listener = ir.mListener;
}
final boolean isReaderValid;
synchronized (ir.mCloseLock) {
isReaderValid = ir.mIsReaderValid;
}
executor.execute(() -> {
// Acquire readlock to ensure that the ImageReader does not change its
// state while a listener is actively processing.
final long rStamp = ir.mListenerLock.readLock();
try {
// Fire onImageAvailable of the latest non-null listener
// This ensures that if the listener changes while messages are in queue, the
// in-flight messages will call onImageAvailable of the new listener instead
if (ir.mListener != null) {
ir.mListener.onImageAvailable(ir);
// It's dangerous to fire onImageAvailable() callback when the ImageReader
// is being closed, as application could acquire next image in the
// onImageAvailable() callback.
if (executor != null && listener != null && isReaderValid) {
executor.execute(new Runnable() {
@Override
public void run() {
listener.onImageAvailable(ir);
}
} finally {
ir.mListenerLock.unlockRead(rStamp);
}
});
});
}
}
/**
@@ -1092,7 +1070,7 @@ public class ImageReader implements AutoCloseable {
private Surface mSurface;
private int mEstimatedNativeAllocBytes;
private final StampedLock mListenerLock = new StampedLock();
private final Object mListenerLock = new Object();
private final Object mCloseLock = new Object();
private boolean mIsReaderValid = false;
private OnImageAvailableListener mListener;