Loading core/java/android/os/CombinedMessageQueue/MessageQueue.java +26 −31 Original line number Diff line number Diff line Loading @@ -93,9 +93,7 @@ public final class MessageQueue { * system processes and provides a higher level of concurrency and higher enqueue throughput * than the legacy implementation. */ private static boolean sUseConcurrent; private static boolean sUseConcurrentInitialized = false; private boolean mUseConcurrent; @RavenwoodRedirect private native static long nativeInit(); Loading @@ -112,10 +110,7 @@ public final class MessageQueue { private native static void nativeSetFileDescriptorEvents(long ptr, int fd, int events); MessageQueue(boolean quitAllowed) { if (!sUseConcurrentInitialized) { sUseConcurrent = UserHandle.isCore(Process.myUid()); sUseConcurrentInitialized = true; } mUseConcurrent = UserHandle.isCore(Process.myUid()); mQuitAllowed = quitAllowed; mPtr = nativeInit(); } Loading Loading @@ -158,7 +153,7 @@ public final class MessageQueue { * @return True if the looper is idle. */ public boolean isIdle() { if (sUseConcurrent) { if (mUseConcurrent) { final long now = SystemClock.uptimeMillis(); if (stackHasMessages(null, 0, null, null, now, mMatchDeliverableMessages, false)) { Loading Loading @@ -208,7 +203,7 @@ public final class MessageQueue { if (handler == null) { throw new NullPointerException("Can't add a null IdleHandler"); } if (sUseConcurrent) { if (mUseConcurrent) { synchronized (mIdleHandlersLock) { mIdleHandlers.add(handler); } Loading @@ -229,7 +224,7 @@ public final class MessageQueue { * @param handler The IdleHandler to be removed. */ public void removeIdleHandler(@NonNull IdleHandler handler) { if (sUseConcurrent) { if (mUseConcurrent) { synchronized (mIdleHandlersLock) { mIdleHandlers.remove(handler); } Loading @@ -252,7 +247,7 @@ public final class MessageQueue { * @hide */ public boolean isPolling() { if (sUseConcurrent) { if (mUseConcurrent) { // If the loop is quitting then it must not be idling. // We can assume mPtr != 0 when sQuitting is false. return !((boolean) sQuitting.getVolatile(this)) && nativeIsPolling(mPtr); Loading Loading @@ -303,7 +298,7 @@ public final class MessageQueue { throw new IllegalArgumentException("listener must not be null"); } if (sUseConcurrent) { if (mUseConcurrent) { synchronized (mFileDescriptorRecordsLock) { updateOnFileDescriptorEventListenerLocked(fd, events, listener); } Loading Loading @@ -331,7 +326,7 @@ public final class MessageQueue { if (fd == null) { throw new IllegalArgumentException("fd must not be null"); } if (sUseConcurrent) { if (mUseConcurrent) { synchronized (mFileDescriptorRecordsLock) { updateOnFileDescriptorEventListenerLocked(fd, 0, null); } Loading Loading @@ -388,7 +383,7 @@ public final class MessageQueue { final int oldWatchedEvents; final OnFileDescriptorEventListener listener; final int seq; if (sUseConcurrent) { if (mUseConcurrent) { synchronized (mFileDescriptorRecordsLock) { record = mFileDescriptorRecords.get(fd); if (record == null) { Loading Loading @@ -708,7 +703,7 @@ public final class MessageQueue { @UnsupportedAppUsage Message next() { if (sUseConcurrent) { if (mUseConcurrent) { return nextConcurrent(); } Loading Loading @@ -834,7 +829,7 @@ public final class MessageQueue { throw new IllegalStateException("Main thread not allowed to quit."); } if (sUseConcurrent) { if (mUseConcurrent) { synchronized (mIdleHandlersLock) { if (sQuitting.compareAndSet(this, false, true)) { if (safe) { Loading Loading @@ -898,7 +893,7 @@ public final class MessageQueue { private int postSyncBarrier(long when) { // Enqueue a new sync barrier token. // We don't need to wake the queue because the purpose of a barrier is to stall it. if (sUseConcurrent) { if (mUseConcurrent) { final int token = mNextBarrierTokenAtomic.getAndIncrement(); // b/376573804: apps and tests may expect to be able to use reflection Loading Loading @@ -991,7 +986,7 @@ public final class MessageQueue { public void removeSyncBarrier(int token) { // Remove a sync barrier token from the queue. // If the queue is no longer stalled by a barrier then wake it. if (sUseConcurrent) { if (mUseConcurrent) { boolean removed; MessageNode first; final MatchBarrierToken matchBarrierToken = new MatchBarrierToken(token); Loading Loading @@ -1058,7 +1053,7 @@ public final class MessageQueue { throw new IllegalArgumentException("Message must have a target."); } if (sUseConcurrent) { if (mUseConcurrent) { if (msg.isInUse()) { throw new IllegalStateException(msg + " This message is already in use."); } Loading Loading @@ -1187,7 +1182,7 @@ public final class MessageQueue { if (h == null) { return false; } if (sUseConcurrent) { if (mUseConcurrent) { return findOrRemoveMessages(h, what, object, null, 0, mMatchHandlerWhatAndObject, false); } Loading Loading @@ -1219,7 +1214,7 @@ public final class MessageQueue { if (h == null) { return false; } if (sUseConcurrent) { if (mUseConcurrent) { return findOrRemoveMessages(h, what, object, null, 0, mMatchHandlerWhatAndObjectEquals, false); Loading Loading @@ -1253,7 +1248,7 @@ public final class MessageQueue { if (h == null) { return false; } if (sUseConcurrent) { if (mUseConcurrent) { return findOrRemoveMessages(h, -1, object, r, 0, mMatchHandlerRunnableAndObject, false); } Loading Loading @@ -1285,7 +1280,7 @@ public final class MessageQueue { if (h == null) { return false; } if (sUseConcurrent) { if (mUseConcurrent) { return findOrRemoveMessages(h, -1, null, null, 0, mMatchHandler, false); } synchronized (this) { Loading @@ -1304,7 +1299,7 @@ public final class MessageQueue { if (h == null) { return; } if (sUseConcurrent) { if (mUseConcurrent) { findOrRemoveMessages(h, what, object, null, 0, mMatchHandlerWhatAndObject, true); return; } Loading Loading @@ -1355,7 +1350,7 @@ public final class MessageQueue { return; } if (sUseConcurrent) { if (mUseConcurrent) { findOrRemoveMessages(h, what, object, null, 0, mMatchHandlerWhatAndObjectEquals, true); return; } Loading Loading @@ -1407,7 +1402,7 @@ public final class MessageQueue { return; } if (sUseConcurrent) { if (mUseConcurrent) { findOrRemoveMessages(h, -1, object, r, 0, mMatchHandlerRunnableAndObject, true); return; } Loading Loading @@ -1470,7 +1465,7 @@ public final class MessageQueue { return; } if (sUseConcurrent) { if (mUseConcurrent) { findOrRemoveMessages(h, -1, object, r, 0, mMatchHandlerRunnableAndObjectEquals, true); return; } Loading Loading @@ -1532,7 +1527,7 @@ public final class MessageQueue { return; } if (sUseConcurrent) { if (mUseConcurrent) { findOrRemoveMessages(h, -1, object, null, 0, mMatchHandlerAndObject, true); return; } Loading Loading @@ -1594,7 +1589,7 @@ public final class MessageQueue { return; } if (sUseConcurrent) { if (mUseConcurrent) { findOrRemoveMessages(h, -1, object, null, 0, mMatchHandlerAndObjectEquals, true); return; } Loading Loading @@ -1742,7 +1737,7 @@ public final class MessageQueue { @NeverCompile void dump(Printer pw, String prefix, Handler h) { if (sUseConcurrent) { if (mUseConcurrent) { long now = SystemClock.uptimeMillis(); int n = 0; Loading Loading @@ -1803,7 +1798,7 @@ public final class MessageQueue { @NeverCompile void dumpDebug(ProtoOutputStream proto, long fieldId) { if (sUseConcurrent) { if (mUseConcurrent) { final long messageQueueToken = proto.start(fieldId); StackNode node = (StackNode) sState.getVolatile(this); Loading tests/testables/src/android/testing/TestableLooper.java +18 −0 Original line number Diff line number Diff line Loading @@ -53,6 +53,7 @@ public class TestableLooper { private static final Field MESSAGE_QUEUE_MESSAGES_FIELD; private static final Field MESSAGE_NEXT_FIELD; private static final Field MESSAGE_WHEN_FIELD; private static Field MESSAGE_QUEUE_USE_CONCURRENT_FIELD = null; private Looper mLooper; private MessageQueue mQueue; Loading @@ -62,6 +63,14 @@ public class TestableLooper { private TestLooperManager mQueueWrapper; static { try { MESSAGE_QUEUE_USE_CONCURRENT_FIELD = MessageQueue.class.getDeclaredField("mUseConcurrent"); MESSAGE_QUEUE_USE_CONCURRENT_FIELD.setAccessible(true); } catch (NoSuchFieldException ignored) { // Ignore - maybe this is not CombinedMessageQueue? } try { MESSAGE_QUEUE_MESSAGES_FIELD = MessageQueue.class.getDeclaredField("mMessages"); MESSAGE_QUEUE_MESSAGES_FIELD.setAccessible(true); Loading Loading @@ -146,6 +155,15 @@ public class TestableLooper { mLooper = l; mQueue = mLooper.getQueue(); mHandler = new Handler(mLooper); // If we are using CombinedMessageQueue, we need to disable concurrent mode for testing. if (MESSAGE_QUEUE_USE_CONCURRENT_FIELD != null) { try { MESSAGE_QUEUE_USE_CONCURRENT_FIELD.set(mQueue, false); } catch (IllegalAccessException e) { throw new RuntimeException(e); } } } /** Loading tests/utils/testutils/java/android/os/test/TestLooper.java +12 −22 Original line number Diff line number Diff line Loading @@ -90,20 +90,6 @@ public class TestLooper { * and call {@link #dispatchAll()}. */ public TestLooper(Clock clock) { Field messageQueueUseConcurrentField = null; boolean previousUseConcurrentValue = false; try { messageQueueUseConcurrentField = MessageQueue.class.getDeclaredField("sUseConcurrent"); messageQueueUseConcurrentField.setAccessible(true); previousUseConcurrentValue = messageQueueUseConcurrentField.getBoolean(null); // If we are using CombinedMessageQueue, we need to disable concurrent mode for testing. messageQueueUseConcurrentField.set(null, false); } catch (NoSuchFieldException e) { // Ignore - maybe this is not CombinedMessageQueue? } catch (IllegalAccessException e) { throw new RuntimeException("Reflection error constructing or accessing looper", e); } try { mLooper = LOOPER_CONSTRUCTOR.newInstance(false); Loading @@ -114,15 +100,19 @@ public class TestLooper { throw new RuntimeException("Reflection error constructing or accessing looper", e); } mClock = clock; if (messageQueueUseConcurrentField != null) { // If we are using CombinedMessageQueue, we need to disable concurrent mode for testing. try { messageQueueUseConcurrentField.set(null, previousUseConcurrentValue); Field messageQueueUseConcurrentField = MessageQueue.class.getDeclaredField("mUseConcurrent"); messageQueueUseConcurrentField.setAccessible(true); messageQueueUseConcurrentField.set(mLooper.getQueue(), false); } catch (NoSuchFieldException e) { // Ignore - maybe this is not CombinedMessageQueue? } catch (IllegalAccessException e) { throw new RuntimeException("Reflection error constructing or accessing looper", e); } } mClock = clock; } public Looper getLooper() { Loading Loading
core/java/android/os/CombinedMessageQueue/MessageQueue.java +26 −31 Original line number Diff line number Diff line Loading @@ -93,9 +93,7 @@ public final class MessageQueue { * system processes and provides a higher level of concurrency and higher enqueue throughput * than the legacy implementation. */ private static boolean sUseConcurrent; private static boolean sUseConcurrentInitialized = false; private boolean mUseConcurrent; @RavenwoodRedirect private native static long nativeInit(); Loading @@ -112,10 +110,7 @@ public final class MessageQueue { private native static void nativeSetFileDescriptorEvents(long ptr, int fd, int events); MessageQueue(boolean quitAllowed) { if (!sUseConcurrentInitialized) { sUseConcurrent = UserHandle.isCore(Process.myUid()); sUseConcurrentInitialized = true; } mUseConcurrent = UserHandle.isCore(Process.myUid()); mQuitAllowed = quitAllowed; mPtr = nativeInit(); } Loading Loading @@ -158,7 +153,7 @@ public final class MessageQueue { * @return True if the looper is idle. */ public boolean isIdle() { if (sUseConcurrent) { if (mUseConcurrent) { final long now = SystemClock.uptimeMillis(); if (stackHasMessages(null, 0, null, null, now, mMatchDeliverableMessages, false)) { Loading Loading @@ -208,7 +203,7 @@ public final class MessageQueue { if (handler == null) { throw new NullPointerException("Can't add a null IdleHandler"); } if (sUseConcurrent) { if (mUseConcurrent) { synchronized (mIdleHandlersLock) { mIdleHandlers.add(handler); } Loading @@ -229,7 +224,7 @@ public final class MessageQueue { * @param handler The IdleHandler to be removed. */ public void removeIdleHandler(@NonNull IdleHandler handler) { if (sUseConcurrent) { if (mUseConcurrent) { synchronized (mIdleHandlersLock) { mIdleHandlers.remove(handler); } Loading @@ -252,7 +247,7 @@ public final class MessageQueue { * @hide */ public boolean isPolling() { if (sUseConcurrent) { if (mUseConcurrent) { // If the loop is quitting then it must not be idling. // We can assume mPtr != 0 when sQuitting is false. return !((boolean) sQuitting.getVolatile(this)) && nativeIsPolling(mPtr); Loading Loading @@ -303,7 +298,7 @@ public final class MessageQueue { throw new IllegalArgumentException("listener must not be null"); } if (sUseConcurrent) { if (mUseConcurrent) { synchronized (mFileDescriptorRecordsLock) { updateOnFileDescriptorEventListenerLocked(fd, events, listener); } Loading Loading @@ -331,7 +326,7 @@ public final class MessageQueue { if (fd == null) { throw new IllegalArgumentException("fd must not be null"); } if (sUseConcurrent) { if (mUseConcurrent) { synchronized (mFileDescriptorRecordsLock) { updateOnFileDescriptorEventListenerLocked(fd, 0, null); } Loading Loading @@ -388,7 +383,7 @@ public final class MessageQueue { final int oldWatchedEvents; final OnFileDescriptorEventListener listener; final int seq; if (sUseConcurrent) { if (mUseConcurrent) { synchronized (mFileDescriptorRecordsLock) { record = mFileDescriptorRecords.get(fd); if (record == null) { Loading Loading @@ -708,7 +703,7 @@ public final class MessageQueue { @UnsupportedAppUsage Message next() { if (sUseConcurrent) { if (mUseConcurrent) { return nextConcurrent(); } Loading Loading @@ -834,7 +829,7 @@ public final class MessageQueue { throw new IllegalStateException("Main thread not allowed to quit."); } if (sUseConcurrent) { if (mUseConcurrent) { synchronized (mIdleHandlersLock) { if (sQuitting.compareAndSet(this, false, true)) { if (safe) { Loading Loading @@ -898,7 +893,7 @@ public final class MessageQueue { private int postSyncBarrier(long when) { // Enqueue a new sync barrier token. // We don't need to wake the queue because the purpose of a barrier is to stall it. if (sUseConcurrent) { if (mUseConcurrent) { final int token = mNextBarrierTokenAtomic.getAndIncrement(); // b/376573804: apps and tests may expect to be able to use reflection Loading Loading @@ -991,7 +986,7 @@ public final class MessageQueue { public void removeSyncBarrier(int token) { // Remove a sync barrier token from the queue. // If the queue is no longer stalled by a barrier then wake it. if (sUseConcurrent) { if (mUseConcurrent) { boolean removed; MessageNode first; final MatchBarrierToken matchBarrierToken = new MatchBarrierToken(token); Loading Loading @@ -1058,7 +1053,7 @@ public final class MessageQueue { throw new IllegalArgumentException("Message must have a target."); } if (sUseConcurrent) { if (mUseConcurrent) { if (msg.isInUse()) { throw new IllegalStateException(msg + " This message is already in use."); } Loading Loading @@ -1187,7 +1182,7 @@ public final class MessageQueue { if (h == null) { return false; } if (sUseConcurrent) { if (mUseConcurrent) { return findOrRemoveMessages(h, what, object, null, 0, mMatchHandlerWhatAndObject, false); } Loading Loading @@ -1219,7 +1214,7 @@ public final class MessageQueue { if (h == null) { return false; } if (sUseConcurrent) { if (mUseConcurrent) { return findOrRemoveMessages(h, what, object, null, 0, mMatchHandlerWhatAndObjectEquals, false); Loading Loading @@ -1253,7 +1248,7 @@ public final class MessageQueue { if (h == null) { return false; } if (sUseConcurrent) { if (mUseConcurrent) { return findOrRemoveMessages(h, -1, object, r, 0, mMatchHandlerRunnableAndObject, false); } Loading Loading @@ -1285,7 +1280,7 @@ public final class MessageQueue { if (h == null) { return false; } if (sUseConcurrent) { if (mUseConcurrent) { return findOrRemoveMessages(h, -1, null, null, 0, mMatchHandler, false); } synchronized (this) { Loading @@ -1304,7 +1299,7 @@ public final class MessageQueue { if (h == null) { return; } if (sUseConcurrent) { if (mUseConcurrent) { findOrRemoveMessages(h, what, object, null, 0, mMatchHandlerWhatAndObject, true); return; } Loading Loading @@ -1355,7 +1350,7 @@ public final class MessageQueue { return; } if (sUseConcurrent) { if (mUseConcurrent) { findOrRemoveMessages(h, what, object, null, 0, mMatchHandlerWhatAndObjectEquals, true); return; } Loading Loading @@ -1407,7 +1402,7 @@ public final class MessageQueue { return; } if (sUseConcurrent) { if (mUseConcurrent) { findOrRemoveMessages(h, -1, object, r, 0, mMatchHandlerRunnableAndObject, true); return; } Loading Loading @@ -1470,7 +1465,7 @@ public final class MessageQueue { return; } if (sUseConcurrent) { if (mUseConcurrent) { findOrRemoveMessages(h, -1, object, r, 0, mMatchHandlerRunnableAndObjectEquals, true); return; } Loading Loading @@ -1532,7 +1527,7 @@ public final class MessageQueue { return; } if (sUseConcurrent) { if (mUseConcurrent) { findOrRemoveMessages(h, -1, object, null, 0, mMatchHandlerAndObject, true); return; } Loading Loading @@ -1594,7 +1589,7 @@ public final class MessageQueue { return; } if (sUseConcurrent) { if (mUseConcurrent) { findOrRemoveMessages(h, -1, object, null, 0, mMatchHandlerAndObjectEquals, true); return; } Loading Loading @@ -1742,7 +1737,7 @@ public final class MessageQueue { @NeverCompile void dump(Printer pw, String prefix, Handler h) { if (sUseConcurrent) { if (mUseConcurrent) { long now = SystemClock.uptimeMillis(); int n = 0; Loading Loading @@ -1803,7 +1798,7 @@ public final class MessageQueue { @NeverCompile void dumpDebug(ProtoOutputStream proto, long fieldId) { if (sUseConcurrent) { if (mUseConcurrent) { final long messageQueueToken = proto.start(fieldId); StackNode node = (StackNode) sState.getVolatile(this); Loading
tests/testables/src/android/testing/TestableLooper.java +18 −0 Original line number Diff line number Diff line Loading @@ -53,6 +53,7 @@ public class TestableLooper { private static final Field MESSAGE_QUEUE_MESSAGES_FIELD; private static final Field MESSAGE_NEXT_FIELD; private static final Field MESSAGE_WHEN_FIELD; private static Field MESSAGE_QUEUE_USE_CONCURRENT_FIELD = null; private Looper mLooper; private MessageQueue mQueue; Loading @@ -62,6 +63,14 @@ public class TestableLooper { private TestLooperManager mQueueWrapper; static { try { MESSAGE_QUEUE_USE_CONCURRENT_FIELD = MessageQueue.class.getDeclaredField("mUseConcurrent"); MESSAGE_QUEUE_USE_CONCURRENT_FIELD.setAccessible(true); } catch (NoSuchFieldException ignored) { // Ignore - maybe this is not CombinedMessageQueue? } try { MESSAGE_QUEUE_MESSAGES_FIELD = MessageQueue.class.getDeclaredField("mMessages"); MESSAGE_QUEUE_MESSAGES_FIELD.setAccessible(true); Loading Loading @@ -146,6 +155,15 @@ public class TestableLooper { mLooper = l; mQueue = mLooper.getQueue(); mHandler = new Handler(mLooper); // If we are using CombinedMessageQueue, we need to disable concurrent mode for testing. if (MESSAGE_QUEUE_USE_CONCURRENT_FIELD != null) { try { MESSAGE_QUEUE_USE_CONCURRENT_FIELD.set(mQueue, false); } catch (IllegalAccessException e) { throw new RuntimeException(e); } } } /** Loading
tests/utils/testutils/java/android/os/test/TestLooper.java +12 −22 Original line number Diff line number Diff line Loading @@ -90,20 +90,6 @@ public class TestLooper { * and call {@link #dispatchAll()}. */ public TestLooper(Clock clock) { Field messageQueueUseConcurrentField = null; boolean previousUseConcurrentValue = false; try { messageQueueUseConcurrentField = MessageQueue.class.getDeclaredField("sUseConcurrent"); messageQueueUseConcurrentField.setAccessible(true); previousUseConcurrentValue = messageQueueUseConcurrentField.getBoolean(null); // If we are using CombinedMessageQueue, we need to disable concurrent mode for testing. messageQueueUseConcurrentField.set(null, false); } catch (NoSuchFieldException e) { // Ignore - maybe this is not CombinedMessageQueue? } catch (IllegalAccessException e) { throw new RuntimeException("Reflection error constructing or accessing looper", e); } try { mLooper = LOOPER_CONSTRUCTOR.newInstance(false); Loading @@ -114,15 +100,19 @@ public class TestLooper { throw new RuntimeException("Reflection error constructing or accessing looper", e); } mClock = clock; if (messageQueueUseConcurrentField != null) { // If we are using CombinedMessageQueue, we need to disable concurrent mode for testing. try { messageQueueUseConcurrentField.set(null, previousUseConcurrentValue); Field messageQueueUseConcurrentField = MessageQueue.class.getDeclaredField("mUseConcurrent"); messageQueueUseConcurrentField.setAccessible(true); messageQueueUseConcurrentField.set(mLooper.getQueue(), false); } catch (NoSuchFieldException e) { // Ignore - maybe this is not CombinedMessageQueue? } catch (IllegalAccessException e) { throw new RuntimeException("Reflection error constructing or accessing looper", e); } } mClock = clock; } public Looper getLooper() { Loading