Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b142103e authored by Shai Barack's avatar Shai Barack
Browse files

Fix TestLooper to work with CombinedMessageQueue

CombinedMessageQueue uses a concurrent message queue implementation, which is not compatible with the way TestLooper works. This CL disables concurrent mode for TestLooper when CombinedMessageQueue is used.

Change-Id: Iffa2978064368755dd06a03c6c472f96288a2888
Flag: build.RELEASE_PACKAGE_MESSAGEQUEUE_IMPLEMENTATION
Bug: 336880969
Bug: 376602406
Bug: 376602402
parent 9ad90b8d
Loading
Loading
Loading
Loading
+30 −27
Original line number Diff line number Diff line
@@ -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();
@@ -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();
@@ -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)) {
@@ -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);
            }
@@ -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);
            }
@@ -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);
@@ -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);
            }
@@ -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);
            }
@@ -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) {
@@ -704,7 +707,7 @@ public final class MessageQueue {

    @UnsupportedAppUsage
    Message next() {
        if (sForceConcurrent) {
        if (sUseConcurrent) {
            return nextConcurrent();
        }

@@ -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) {
@@ -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
@@ -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);
@@ -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.");
            }
@@ -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);
        }
@@ -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);

@@ -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);
        }
@@ -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) {
@@ -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;
        }
@@ -1351,7 +1354,7 @@ public final class MessageQueue {
            return;
        }

        if (sForceConcurrent) {
        if (sUseConcurrent) {
            findOrRemoveMessages(h, what, object, null, 0, mMatchHandlerWhatAndObjectEquals, true);
            return;
        }
@@ -1403,7 +1406,7 @@ public final class MessageQueue {
            return;
        }

        if (sForceConcurrent) {
        if (sUseConcurrent) {
            findOrRemoveMessages(h, -1, object, r, 0, mMatchHandlerRunnableAndObject, true);
            return;
        }
@@ -1466,7 +1469,7 @@ public final class MessageQueue {
            return;
        }

        if (sForceConcurrent) {
        if (sUseConcurrent) {
            findOrRemoveMessages(h, -1, object, r, 0, mMatchHandlerRunnableAndObjectEquals, true);
            return;
        }
@@ -1528,7 +1531,7 @@ public final class MessageQueue {
            return;
        }

        if (sForceConcurrent) {
        if (sUseConcurrent) {
            findOrRemoveMessages(h, -1, object, null, 0, mMatchHandlerAndObject, true);
            return;
        }
@@ -1590,7 +1593,7 @@ public final class MessageQueue {
            return;
        }

        if (sForceConcurrent) {
        if (sUseConcurrent) {
            findOrRemoveMessages(h, -1, object, null, 0, mMatchHandlerAndObjectEquals, true);
            return;
        }
@@ -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;

@@ -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);
+24 −2
Original line number Diff line number Diff line
@@ -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() {