Loading core/java/android/os/CombinedMessageQueue/MessageQueue.java +30 −27 Original line number Diff line number Diff line Loading @@ -92,7 +92,9 @@ public final class MessageQueue { * system processes and provides a higher level of concurrency and higher enqueue throughput * than the legacy implementation. */ private static boolean sForceConcurrent = false; private static boolean sUseConcurrent; private static boolean sUseConcurrentInitialized = false; @RavenwoodRedirect private native static long nativeInit(); Loading @@ -109,8 +111,9 @@ public final class MessageQueue { private native static void nativeSetFileDescriptorEvents(long ptr, int fd, int events); MessageQueue(boolean quitAllowed) { if (!sForceConcurrent) { sForceConcurrent = Process.myUid() < Process.FIRST_APPLICATION_UID; if (!sUseConcurrentInitialized) { sUseConcurrent = Process.myUid() < Process.FIRST_APPLICATION_UID; sUseConcurrentInitialized = true; } mQuitAllowed = quitAllowed; mPtr = nativeInit(); Loading Loading @@ -154,7 +157,7 @@ public final class MessageQueue { * @return True if the looper is idle. */ public boolean isIdle() { if (sForceConcurrent) { if (sUseConcurrent) { final long now = SystemClock.uptimeMillis(); if (stackHasMessages(null, 0, null, null, now, mMatchDeliverableMessages, false)) { Loading Loading @@ -204,7 +207,7 @@ public final class MessageQueue { if (handler == null) { throw new NullPointerException("Can't add a null IdleHandler"); } if (sForceConcurrent) { if (sUseConcurrent) { synchronized (mIdleHandlersLock) { mIdleHandlers.add(handler); } Loading @@ -225,7 +228,7 @@ public final class MessageQueue { * @param handler The IdleHandler to be removed. */ public void removeIdleHandler(@NonNull IdleHandler handler) { if (sForceConcurrent) { if (sUseConcurrent) { synchronized (mIdleHandlersLock) { mIdleHandlers.remove(handler); } Loading @@ -248,7 +251,7 @@ public final class MessageQueue { * @hide */ public boolean isPolling() { if (sForceConcurrent) { if (sUseConcurrent) { // 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 @@ -299,7 +302,7 @@ public final class MessageQueue { throw new IllegalArgumentException("listener must not be null"); } if (sForceConcurrent) { if (sUseConcurrent) { synchronized (mFileDescriptorRecordsLock) { updateOnFileDescriptorEventListenerLocked(fd, events, listener); } Loading Loading @@ -327,7 +330,7 @@ public final class MessageQueue { if (fd == null) { throw new IllegalArgumentException("fd must not be null"); } if (sForceConcurrent) { if (sUseConcurrent) { synchronized (mFileDescriptorRecordsLock) { updateOnFileDescriptorEventListenerLocked(fd, 0, null); } Loading Loading @@ -384,7 +387,7 @@ public final class MessageQueue { final int oldWatchedEvents; final OnFileDescriptorEventListener listener; final int seq; if (sForceConcurrent) { if (sUseConcurrent) { synchronized (mFileDescriptorRecordsLock) { record = mFileDescriptorRecords.get(fd); if (record == null) { Loading Loading @@ -704,7 +707,7 @@ public final class MessageQueue { @UnsupportedAppUsage Message next() { if (sForceConcurrent) { if (sUseConcurrent) { return nextConcurrent(); } Loading Loading @@ -830,7 +833,7 @@ public final class MessageQueue { throw new IllegalStateException("Main thread not allowed to quit."); } if (sForceConcurrent) { if (sUseConcurrent) { synchronized (mIdleHandlersLock) { if (sQuitting.compareAndSet(this, false, true)) { if (safe) { Loading Loading @@ -894,7 +897,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 (sForceConcurrent) { if (sUseConcurrent) { final int token = mNextBarrierTokenAtomic.getAndIncrement(); // b/376573804: apps and tests may expect to be able to use reflection Loading Loading @@ -987,7 +990,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 (sForceConcurrent) { if (sUseConcurrent) { boolean removed; MessageNode first; final MatchBarrierToken matchBarrierToken = new MatchBarrierToken(token); Loading Loading @@ -1054,7 +1057,7 @@ public final class MessageQueue { throw new IllegalArgumentException("Message must have a target."); } if (sForceConcurrent) { if (sUseConcurrent) { if (msg.isInUse()) { throw new IllegalStateException(msg + " This message is already in use."); } Loading Loading @@ -1183,7 +1186,7 @@ public final class MessageQueue { if (h == null) { return false; } if (sForceConcurrent) { if (sUseConcurrent) { return findOrRemoveMessages(h, what, object, null, 0, mMatchHandlerWhatAndObject, false); } Loading Loading @@ -1215,7 +1218,7 @@ public final class MessageQueue { if (h == null) { return false; } if (sForceConcurrent) { if (sUseConcurrent) { return findOrRemoveMessages(h, what, object, null, 0, mMatchHandlerWhatAndObjectEquals, false); Loading Loading @@ -1249,7 +1252,7 @@ public final class MessageQueue { if (h == null) { return false; } if (sForceConcurrent) { if (sUseConcurrent) { return findOrRemoveMessages(h, -1, object, r, 0, mMatchHandlerRunnableAndObject, false); } Loading Loading @@ -1281,7 +1284,7 @@ public final class MessageQueue { if (h == null) { return false; } if (sForceConcurrent) { if (sUseConcurrent) { return findOrRemoveMessages(h, -1, null, null, 0, mMatchHandler, false); } synchronized (this) { Loading @@ -1300,7 +1303,7 @@ public final class MessageQueue { if (h == null) { return; } if (sForceConcurrent) { if (sUseConcurrent) { findOrRemoveMessages(h, what, object, null, 0, mMatchHandlerWhatAndObject, true); return; } Loading Loading @@ -1351,7 +1354,7 @@ public final class MessageQueue { return; } if (sForceConcurrent) { if (sUseConcurrent) { findOrRemoveMessages(h, what, object, null, 0, mMatchHandlerWhatAndObjectEquals, true); return; } Loading Loading @@ -1403,7 +1406,7 @@ public final class MessageQueue { return; } if (sForceConcurrent) { if (sUseConcurrent) { findOrRemoveMessages(h, -1, object, r, 0, mMatchHandlerRunnableAndObject, true); return; } Loading Loading @@ -1466,7 +1469,7 @@ public final class MessageQueue { return; } if (sForceConcurrent) { if (sUseConcurrent) { findOrRemoveMessages(h, -1, object, r, 0, mMatchHandlerRunnableAndObjectEquals, true); return; } Loading Loading @@ -1528,7 +1531,7 @@ public final class MessageQueue { return; } if (sForceConcurrent) { if (sUseConcurrent) { findOrRemoveMessages(h, -1, object, null, 0, mMatchHandlerAndObject, true); return; } Loading Loading @@ -1590,7 +1593,7 @@ public final class MessageQueue { return; } if (sForceConcurrent) { if (sUseConcurrent) { findOrRemoveMessages(h, -1, object, null, 0, mMatchHandlerAndObjectEquals, true); return; } Loading Loading @@ -1738,7 +1741,7 @@ public final class MessageQueue { @NeverCompile void dump(Printer pw, String prefix, Handler h) { if (sForceConcurrent) { if (sUseConcurrent) { long now = SystemClock.uptimeMillis(); int n = 0; Loading Loading @@ -1799,7 +1802,7 @@ public final class MessageQueue { @NeverCompile void dumpDebug(ProtoOutputStream proto, long fieldId) { if (sForceConcurrent) { if (sUseConcurrent) { final long messageQueueToken = proto.start(fieldId); StackNode node = (StackNode) sState.getVolatile(this); Loading tests/utils/testutils/java/android/os/test/TestLooper.java +24 −2 Original line number Diff line number Diff line Loading @@ -90,17 +90,39 @@ 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); ThreadLocal<Looper> threadLocalLooper = (ThreadLocal<Looper>) THREAD_LOCAL_LOOPER_FIELD .get(null); ThreadLocal<Looper> threadLocalLooper = (ThreadLocal<Looper>) THREAD_LOCAL_LOOPER_FIELD.get(null); threadLocalLooper.set(mLooper); } catch (IllegalAccessException | InstantiationException | InvocationTargetException e) { throw new RuntimeException("Reflection error constructing or accessing looper", e); } mClock = clock; if (messageQueueUseConcurrentField != null) { try { messageQueueUseConcurrentField.set(null, previousUseConcurrentValue); } catch (IllegalAccessException e) { throw new RuntimeException("Reflection error constructing or accessing looper", e); } } } public Looper getLooper() { Loading Loading
core/java/android/os/CombinedMessageQueue/MessageQueue.java +30 −27 Original line number Diff line number Diff line Loading @@ -92,7 +92,9 @@ public final class MessageQueue { * system processes and provides a higher level of concurrency and higher enqueue throughput * than the legacy implementation. */ private static boolean sForceConcurrent = false; private static boolean sUseConcurrent; private static boolean sUseConcurrentInitialized = false; @RavenwoodRedirect private native static long nativeInit(); Loading @@ -109,8 +111,9 @@ public final class MessageQueue { private native static void nativeSetFileDescriptorEvents(long ptr, int fd, int events); MessageQueue(boolean quitAllowed) { if (!sForceConcurrent) { sForceConcurrent = Process.myUid() < Process.FIRST_APPLICATION_UID; if (!sUseConcurrentInitialized) { sUseConcurrent = Process.myUid() < Process.FIRST_APPLICATION_UID; sUseConcurrentInitialized = true; } mQuitAllowed = quitAllowed; mPtr = nativeInit(); Loading Loading @@ -154,7 +157,7 @@ public final class MessageQueue { * @return True if the looper is idle. */ public boolean isIdle() { if (sForceConcurrent) { if (sUseConcurrent) { final long now = SystemClock.uptimeMillis(); if (stackHasMessages(null, 0, null, null, now, mMatchDeliverableMessages, false)) { Loading Loading @@ -204,7 +207,7 @@ public final class MessageQueue { if (handler == null) { throw new NullPointerException("Can't add a null IdleHandler"); } if (sForceConcurrent) { if (sUseConcurrent) { synchronized (mIdleHandlersLock) { mIdleHandlers.add(handler); } Loading @@ -225,7 +228,7 @@ public final class MessageQueue { * @param handler The IdleHandler to be removed. */ public void removeIdleHandler(@NonNull IdleHandler handler) { if (sForceConcurrent) { if (sUseConcurrent) { synchronized (mIdleHandlersLock) { mIdleHandlers.remove(handler); } Loading @@ -248,7 +251,7 @@ public final class MessageQueue { * @hide */ public boolean isPolling() { if (sForceConcurrent) { if (sUseConcurrent) { // 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 @@ -299,7 +302,7 @@ public final class MessageQueue { throw new IllegalArgumentException("listener must not be null"); } if (sForceConcurrent) { if (sUseConcurrent) { synchronized (mFileDescriptorRecordsLock) { updateOnFileDescriptorEventListenerLocked(fd, events, listener); } Loading Loading @@ -327,7 +330,7 @@ public final class MessageQueue { if (fd == null) { throw new IllegalArgumentException("fd must not be null"); } if (sForceConcurrent) { if (sUseConcurrent) { synchronized (mFileDescriptorRecordsLock) { updateOnFileDescriptorEventListenerLocked(fd, 0, null); } Loading Loading @@ -384,7 +387,7 @@ public final class MessageQueue { final int oldWatchedEvents; final OnFileDescriptorEventListener listener; final int seq; if (sForceConcurrent) { if (sUseConcurrent) { synchronized (mFileDescriptorRecordsLock) { record = mFileDescriptorRecords.get(fd); if (record == null) { Loading Loading @@ -704,7 +707,7 @@ public final class MessageQueue { @UnsupportedAppUsage Message next() { if (sForceConcurrent) { if (sUseConcurrent) { return nextConcurrent(); } Loading Loading @@ -830,7 +833,7 @@ public final class MessageQueue { throw new IllegalStateException("Main thread not allowed to quit."); } if (sForceConcurrent) { if (sUseConcurrent) { synchronized (mIdleHandlersLock) { if (sQuitting.compareAndSet(this, false, true)) { if (safe) { Loading Loading @@ -894,7 +897,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 (sForceConcurrent) { if (sUseConcurrent) { final int token = mNextBarrierTokenAtomic.getAndIncrement(); // b/376573804: apps and tests may expect to be able to use reflection Loading Loading @@ -987,7 +990,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 (sForceConcurrent) { if (sUseConcurrent) { boolean removed; MessageNode first; final MatchBarrierToken matchBarrierToken = new MatchBarrierToken(token); Loading Loading @@ -1054,7 +1057,7 @@ public final class MessageQueue { throw new IllegalArgumentException("Message must have a target."); } if (sForceConcurrent) { if (sUseConcurrent) { if (msg.isInUse()) { throw new IllegalStateException(msg + " This message is already in use."); } Loading Loading @@ -1183,7 +1186,7 @@ public final class MessageQueue { if (h == null) { return false; } if (sForceConcurrent) { if (sUseConcurrent) { return findOrRemoveMessages(h, what, object, null, 0, mMatchHandlerWhatAndObject, false); } Loading Loading @@ -1215,7 +1218,7 @@ public final class MessageQueue { if (h == null) { return false; } if (sForceConcurrent) { if (sUseConcurrent) { return findOrRemoveMessages(h, what, object, null, 0, mMatchHandlerWhatAndObjectEquals, false); Loading Loading @@ -1249,7 +1252,7 @@ public final class MessageQueue { if (h == null) { return false; } if (sForceConcurrent) { if (sUseConcurrent) { return findOrRemoveMessages(h, -1, object, r, 0, mMatchHandlerRunnableAndObject, false); } Loading Loading @@ -1281,7 +1284,7 @@ public final class MessageQueue { if (h == null) { return false; } if (sForceConcurrent) { if (sUseConcurrent) { return findOrRemoveMessages(h, -1, null, null, 0, mMatchHandler, false); } synchronized (this) { Loading @@ -1300,7 +1303,7 @@ public final class MessageQueue { if (h == null) { return; } if (sForceConcurrent) { if (sUseConcurrent) { findOrRemoveMessages(h, what, object, null, 0, mMatchHandlerWhatAndObject, true); return; } Loading Loading @@ -1351,7 +1354,7 @@ public final class MessageQueue { return; } if (sForceConcurrent) { if (sUseConcurrent) { findOrRemoveMessages(h, what, object, null, 0, mMatchHandlerWhatAndObjectEquals, true); return; } Loading Loading @@ -1403,7 +1406,7 @@ public final class MessageQueue { return; } if (sForceConcurrent) { if (sUseConcurrent) { findOrRemoveMessages(h, -1, object, r, 0, mMatchHandlerRunnableAndObject, true); return; } Loading Loading @@ -1466,7 +1469,7 @@ public final class MessageQueue { return; } if (sForceConcurrent) { if (sUseConcurrent) { findOrRemoveMessages(h, -1, object, r, 0, mMatchHandlerRunnableAndObjectEquals, true); return; } Loading Loading @@ -1528,7 +1531,7 @@ public final class MessageQueue { return; } if (sForceConcurrent) { if (sUseConcurrent) { findOrRemoveMessages(h, -1, object, null, 0, mMatchHandlerAndObject, true); return; } Loading Loading @@ -1590,7 +1593,7 @@ public final class MessageQueue { return; } if (sForceConcurrent) { if (sUseConcurrent) { findOrRemoveMessages(h, -1, object, null, 0, mMatchHandlerAndObjectEquals, true); return; } Loading Loading @@ -1738,7 +1741,7 @@ public final class MessageQueue { @NeverCompile void dump(Printer pw, String prefix, Handler h) { if (sForceConcurrent) { if (sUseConcurrent) { long now = SystemClock.uptimeMillis(); int n = 0; Loading Loading @@ -1799,7 +1802,7 @@ public final class MessageQueue { @NeverCompile void dumpDebug(ProtoOutputStream proto, long fieldId) { if (sForceConcurrent) { if (sUseConcurrent) { final long messageQueueToken = proto.start(fieldId); StackNode node = (StackNode) sState.getVolatile(this); Loading
tests/utils/testutils/java/android/os/test/TestLooper.java +24 −2 Original line number Diff line number Diff line Loading @@ -90,17 +90,39 @@ 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); ThreadLocal<Looper> threadLocalLooper = (ThreadLocal<Looper>) THREAD_LOCAL_LOOPER_FIELD .get(null); ThreadLocal<Looper> threadLocalLooper = (ThreadLocal<Looper>) THREAD_LOCAL_LOOPER_FIELD.get(null); threadLocalLooper.set(mLooper); } catch (IllegalAccessException | InstantiationException | InvocationTargetException e) { throw new RuntimeException("Reflection error constructing or accessing looper", e); } mClock = clock; if (messageQueueUseConcurrentField != null) { try { messageQueueUseConcurrentField.set(null, previousUseConcurrentValue); } catch (IllegalAccessException e) { throw new RuntimeException("Reflection error constructing or accessing looper", e); } } } public Looper getLooper() { Loading