diff --git a/media/java/android/media/ImageReader.java b/media/java/android/media/ImageReader.java index 5f02a430f3841..e2e48d35a6725 100644 --- a/media/java/android/media/ImageReader.java +++ b/media/java/android/media/ImageReader.java @@ -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; /** *
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;