Loading media/java/android/media/ImageReader.java +20 −42 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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) { Loading @@ -693,8 +691,6 @@ public class ImageReader implements AutoCloseable { mListenerExecutor = null; } mListener = listener; } finally { mListenerLock.unlockWrite(writeStamp); } } Loading @@ -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); } } Loading @@ -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 Loading Loading @@ -898,42 +889,29 @@ 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; listener = ir.mListener; } } finally { ir.mListenerLock.unlockRead(readStamp); 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); } } finally { ir.mListenerLock.unlockRead(rStamp); // 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); } }); } } /** * Builder class for {@link ImageReader} objects. Loading Loading @@ -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; Loading Loading
media/java/android/media/ImageReader.java +20 −42 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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) { Loading @@ -693,8 +691,6 @@ public class ImageReader implements AutoCloseable { mListenerExecutor = null; } mListener = listener; } finally { mListenerLock.unlockWrite(writeStamp); } } Loading @@ -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); } } Loading @@ -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 Loading Loading @@ -898,42 +889,29 @@ 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; listener = ir.mListener; } } finally { ir.mListenerLock.unlockRead(readStamp); 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); } } finally { ir.mListenerLock.unlockRead(rStamp); // 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); } }); } } /** * Builder class for {@link ImageReader} objects. Loading Loading @@ -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; Loading