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

Commit a33a5dd3 authored by Mark Fasheh's avatar Mark Fasheh
Browse files

MessageQueue: use distinct Concurrent/Legacy methods

Test: atest MessageQueueTest
Bug: 384796380
Flag: android.os.message_queue_force_legacy
Change-Id: I670bbdbc8bfad99d535630a423c3d0aa50d3da39
parent 3e864644
Loading
Loading
Loading
Loading
+351 −180
Original line number Diff line number Diff line
@@ -237,15 +237,8 @@ public final class MessageQueue {
    }
    private final MatchDeliverableMessages mMatchDeliverableMessages =
            new MatchDeliverableMessages();
    /**
     * Returns true if the looper has no pending messages which are due to be processed.
     *
     * <p>This method is safe to call from any thread.
     *
     * @return True if the looper is idle.
     */
    public boolean isIdle() {
        if (mUseConcurrent) {

    private boolean isIdleConcurrent() {
        final long now = SystemClock.uptimeMillis();

        if (stackHasMessages(null, 0, null, null, now, mMatchDeliverableMessages, false)) {
@@ -273,12 +266,40 @@ public final class MessageQueue {
        }

        return true;
        } else {
    }

    private boolean isIdleLegacy() {
        synchronized (this) {
            final long now = SystemClock.uptimeMillis();
            return mMessages == null || now < mMessages.when;
        }
    }

    /**
     * Returns true if the looper has no pending messages which are due to be processed.
     *
     * <p>This method is safe to call from any thread.
     *
     * @return True if the looper is idle.
     */
    public boolean isIdle() {
        if (mUseConcurrent) {
            return isIdleConcurrent();
        } else {
            return isIdleLegacy();
        }
    }

    private void addIdleHandlerConcurrent(@NonNull IdleHandler handler) {
        synchronized (mIdleHandlersLock) {
            mIdleHandlers.add(handler);
        }
    }

    private void addIdleHandlerLegacy(@NonNull IdleHandler handler) {
        synchronized (this) {
            mIdleHandlers.add(handler);
        }
    }

    /**
@@ -296,13 +317,19 @@ public final class MessageQueue {
            throw new NullPointerException("Can't add a null IdleHandler");
        }
        if (mUseConcurrent) {
            addIdleHandlerConcurrent(handler);
        } else {
            addIdleHandlerLegacy(handler);
        }
    }
    private void removeIdleHandlerConcurrent(@NonNull IdleHandler handler) {
        synchronized (mIdleHandlersLock) {
                mIdleHandlers.add(handler);
            mIdleHandlers.remove(handler);
        }
        } else {
            synchronized (this) {
                mIdleHandlers.add(handler);
    }
    private void removeIdleHandlerLegacy(@NonNull IdleHandler handler) {
        synchronized (this) {
            mIdleHandlers.remove(handler);
        }
    }

@@ -317,14 +344,22 @@ public final class MessageQueue {
     */
    public void removeIdleHandler(@NonNull IdleHandler handler) {
        if (mUseConcurrent) {
            synchronized (mIdleHandlersLock) {
                mIdleHandlers.remove(handler);
            }
            removeIdleHandlerConcurrent(handler);
        } else {
            synchronized (this) {
                mIdleHandlers.remove(handler);
            removeIdleHandlerLegacy(handler);
        }
    }

    private boolean isPollingConcurrent() {
        // 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);
    }

    private boolean isPollingLegacy() {
        synchronized (this) {
            return isPollingLocked();
        }
    }

    /**
@@ -340,13 +375,9 @@ public final class MessageQueue {
     */
    public boolean isPolling() {
        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);
            return isPollingConcurrent();
        } else {
            synchronized (this) {
                return isPollingLocked();
            }
            return isPollingLegacy();
        }
    }

@@ -355,6 +386,21 @@ public final class MessageQueue {
        // We can assume mPtr != 0 when mQuitting is false.
        return !mQuitting && nativeIsPolling(mPtr);
    }
    private void addOnFileDescriptorEventListenerConcurrent(@NonNull FileDescriptor fd,
            @OnFileDescriptorEventListener.Events int events,
            @NonNull OnFileDescriptorEventListener listener) {
        synchronized (mFileDescriptorRecordsLock) {
            updateOnFileDescriptorEventListenerLocked(fd, events, listener);
        }
    }

    private void addOnFileDescriptorEventListenerLegacy(@NonNull FileDescriptor fd,
            @OnFileDescriptorEventListener.Events int events,
            @NonNull OnFileDescriptorEventListener listener) {
        synchronized (this) {
            updateOnFileDescriptorEventListenerLocked(fd, events, listener);
        }
    }

    /**
     * Adds a file descriptor listener to receive notification when file descriptor
@@ -391,13 +437,21 @@ public final class MessageQueue {
        }

        if (mUseConcurrent) {
            addOnFileDescriptorEventListenerConcurrent(fd, events, listener);
        } else {
            addOnFileDescriptorEventListenerLegacy(fd, events, listener);
        }
    }

    private void removeOnFileDescriptorEventListenerConcurrent(@NonNull FileDescriptor fd) {
        synchronized (mFileDescriptorRecordsLock) {
                updateOnFileDescriptorEventListenerLocked(fd, events, listener);
            updateOnFileDescriptorEventListenerLocked(fd, 0, null);
        }
        } else {
            synchronized (this) {
                updateOnFileDescriptorEventListenerLocked(fd, events, listener);
    }

    private void removeOnFileDescriptorEventListenerLegacy(@NonNull FileDescriptor fd) {
        synchronized (this) {
            updateOnFileDescriptorEventListenerLocked(fd, 0, null);
        }
    }

@@ -419,13 +473,9 @@ public final class MessageQueue {
            throw new IllegalArgumentException("fd must not be null");
        }
        if (mUseConcurrent) {
            synchronized (mFileDescriptorRecordsLock) {
                updateOnFileDescriptorEventListenerLocked(fd, 0, null);
            }
            removeOnFileDescriptorEventListenerConcurrent(fd);
        } else {
            synchronized (this) {
                updateOnFileDescriptorEventListenerLocked(fd, 0, null);
            }
            removeOnFileDescriptorEventListenerLegacy(fd);
        }
    }

@@ -806,12 +856,7 @@ public final class MessageQueue {
        }
    }

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

    private Message nextLegacy() {
        // Return here if the message loop has already quit and been disposed.
        // This can happen if the application tries to restart a looper after quit
        // which is not supported.
@@ -929,6 +974,15 @@ public final class MessageQueue {
        }
    }

    @UnsupportedAppUsage
    Message next() {
        if (mUseConcurrent) {
            return nextConcurrent();
        } else {
            return nextLegacy();
        }
    }

    void quit(boolean safe) {
        if (!mQuitAllowed) {
            throw new IllegalStateException("Main thread not allowed to quit.");
@@ -966,6 +1020,15 @@ public final class MessageQueue {
        }
    }

    private int postSyncBarrierConcurrent() {
        return postSyncBarrier(SystemClock.uptimeMillis());

    }

    private int postSyncBarrierLegacy() {
        return postSyncBarrier(SystemClock.uptimeMillis());
    }

    /**
     * Posts a synchronization barrier to the Looper's message queue.
     *
@@ -992,7 +1055,11 @@ public final class MessageQueue {
    @UnsupportedAppUsage
    @TestApi
    public int postSyncBarrier() {
        return postSyncBarrier(SystemClock.uptimeMillis());
        if (mUseConcurrent) {
            return postSyncBarrierConcurrent();
        } else {
            return postSyncBarrierLegacy();
        }
    }

    private int postSyncBarrier(long when) {
@@ -1077,22 +1144,7 @@ public final class MessageQueue {
        }
    }

    /**
     * Removes a synchronization barrier.
     *
     * @param token The synchronization barrier token that was returned by
     * {@link #postSyncBarrier}.
     *
     * @throws IllegalStateException if the barrier was not found.
     *
     * @hide
     */
    @UnsupportedAppUsage
    @TestApi
    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 (mUseConcurrent) {
    private void removeSyncBarrierConcurrent(int token) {
        boolean removed;
        MessageNode first;
        final MatchBarrierToken matchBarrierToken = new MatchBarrierToken(token);
@@ -1116,9 +1168,9 @@ public final class MessageQueue {
            throw new IllegalStateException("The specified message queue synchronization "
                    + " barrier token has not been posted or has already been removed.");
        }
            return;
    }

    private void removeSyncBarrierLegacy(int token) {
        synchronized (this) {
            Message prev = null;
            Message p = mMessages;
@@ -1154,12 +1206,30 @@ public final class MessageQueue {
        }
    }

    boolean enqueueMessage(Message msg, long when) {
        if (msg.target == null) {
            throw new IllegalArgumentException("Message must have a target.");
    /**
     * Removes a synchronization barrier.
     *
     * @param token The synchronization barrier token that was returned by
     * {@link #postSyncBarrier}.
     *
     * @throws IllegalStateException if the barrier was not found.
     *
     * @hide
     */
    @UnsupportedAppUsage
    @TestApi
    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 (mUseConcurrent) {
            removeSyncBarrierConcurrent(token);
        } else {
            removeSyncBarrierLegacy(token);
        }

        if (mUseConcurrent) {
    }

    private boolean enqueueMessageConcurrent(Message msg, long when) {
        if (msg.isInUse()) {
            throw new IllegalStateException(msg + " This message is already in use.");
        }
@@ -1167,6 +1237,7 @@ public final class MessageQueue {
        return enqueueMessageUnchecked(msg, when);
    }

    private boolean enqueueMessageLegacy(Message msg, long when) {
        synchronized (this) {
            if (msg.isInUse()) {
                throw new IllegalStateException(msg + " This message is already in use.");
@@ -1272,6 +1343,18 @@ public final class MessageQueue {
        return true;
    }

    boolean enqueueMessage(Message msg, long when) {
        if (msg.target == null) {
            throw new IllegalArgumentException("Message must have a target.");
        }

        if (mUseConcurrent) {
            return enqueueMessageConcurrent(msg, when);
        } else {
            return enqueueMessageLegacy(msg, when);
        }
    }

    private Message legacyPeekOrPoll(boolean peek) {
        synchronized (this) {
            // Try to retrieve the next message.  Return if found.
@@ -1432,14 +1515,13 @@ public final class MessageQueue {
    }
    private final MatchHandlerWhatAndObject mMatchHandlerWhatAndObject =
            new MatchHandlerWhatAndObject();
    boolean hasMessages(Handler h, int what, Object object) {
        if (h == null) {
            return false;
        }
        if (mUseConcurrent) {

    private boolean hasMessagesConcurrent(Handler h, int what, Object object) {
        return findOrRemoveMessages(h, what, object, null, 0, mMatchHandlerWhatAndObject,
                false);
    }

    private boolean hasMessagesLegacy(Handler h, int what, Object object) {
        synchronized (this) {
            Message p = mMessages;
            while (p != null) {
@@ -1452,6 +1534,17 @@ public final class MessageQueue {
        }
    }

    boolean hasMessages(Handler h, int what, Object object) {
        if (h == null) {
            return false;
        }
        if (mUseConcurrent) {
            return hasMessagesConcurrent(h, what, object);
        } else {
            return hasMessagesLegacy(h, what, object);
        }
    }

    private static final class MatchHandlerWhatAndObjectEquals extends MessageCompare {
        @Override
        public boolean compareMessage(MessageNode n, Handler h, int what, Object object, Runnable r,
@@ -1465,15 +1558,13 @@ public final class MessageQueue {
    }
    private final MatchHandlerWhatAndObjectEquals mMatchHandlerWhatAndObjectEquals =
            new MatchHandlerWhatAndObjectEquals();
    boolean hasEqualMessages(Handler h, int what, Object object) {
        if (h == null) {
            return false;
        }
        if (mUseConcurrent) {

    private boolean hasEqualMessagesConcurrent(Handler h, int what, Object object) {
        return findOrRemoveMessages(h, what, object, null, 0, mMatchHandlerWhatAndObjectEquals,
                false);

    }

    private boolean hasEqualMessagesLegacy(Handler h, int what, Object object) {
        synchronized (this) {
            Message p = mMessages;
            while (p != null) {
@@ -1486,6 +1577,17 @@ public final class MessageQueue {
        }
    }

    boolean hasEqualMessages(Handler h, int what, Object object) {
        if (h == null) {
            return false;
        }
        if (mUseConcurrent) {
            return hasEqualMessagesConcurrent(h, what, object);
        } else {
            return hasEqualMessagesLegacy(h, what, object);
        }
    }

    private static final class MatchHandlerRunnableAndObject extends MessageCompare {
        @Override
        public boolean compareMessage(MessageNode n, Handler h, int what, Object object, Runnable r,
@@ -1499,16 +1601,13 @@ public final class MessageQueue {
    }
    private final MatchHandlerRunnableAndObject mMatchHandlerRunnableAndObject =
            new MatchHandlerRunnableAndObject();
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    boolean hasMessages(Handler h, Runnable r, Object object) {
        if (h == null) {
            return false;
        }
        if (mUseConcurrent) {

    private boolean hasMessagesConcurrent(Handler h, Runnable r, Object object) {
        return findOrRemoveMessages(h, -1, object, r, 0, mMatchHandlerRunnableAndObject,
                false);
    }

    private boolean hasMessagesLegacy(Handler h, Runnable r, Object object) {
        synchronized (this) {
            Message p = mMessages;
            while (p != null) {
@@ -1521,6 +1620,18 @@ public final class MessageQueue {
        }
    }

    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    boolean hasMessages(Handler h, Runnable r, Object object) {
        if (h == null) {
            return false;
        }
        if (mUseConcurrent) {
            return hasMessagesConcurrent(h, r, object);
        } else {
            return hasMessagesLegacy(h, r, object);
        }
    }

    private static final class MatchHandler extends MessageCompare {
        @Override
        public boolean compareMessage(MessageNode n, Handler h, int what, Object object, Runnable r,
@@ -1529,13 +1640,12 @@ public final class MessageQueue {
        }
    }
    private final MatchHandler mMatchHandler = new MatchHandler();
    boolean hasMessages(Handler h) {
        if (h == null) {
            return false;
        }
        if (mUseConcurrent) {

    private boolean hasMessagesConcurrent(Handler h) {
        return findOrRemoveMessages(h, -1, null, null, 0, mMatchHandler, false);
    }

    private boolean hasMessagesLegacy(Handler h) {
        synchronized (this) {
            Message p = mMessages;
            while (p != null) {
@@ -1548,14 +1658,22 @@ public final class MessageQueue {
        }
    }

    void removeMessages(Handler h, int what, Object object) {
    boolean hasMessages(Handler h) {
        if (h == null) {
            return;
            return false;
        }
        if (mUseConcurrent) {
            return hasMessagesConcurrent(h);
        } else {
            return hasMessagesLegacy(h);
        }
    }

    private void removeMessagesConcurrent(Handler h, int what, Object object) {
        findOrRemoveMessages(h, what, object, null, 0, mMatchHandlerWhatAndObject, true);
            return;
    }

    private void removeMessagesLegacy(Handler h, int what, Object object) {
        synchronized (this) {
            Message p = mMessages;

@@ -1598,16 +1716,22 @@ public final class MessageQueue {
        }
    }

    void removeEqualMessages(Handler h, int what, Object object) {
    void removeMessages(Handler h, int what, Object object) {
        if (h == null) {
            return;
        }

        if (mUseConcurrent) {
            removeMessagesConcurrent(h, what, object);
        } else {
            removeMessagesLegacy(h, what, object);
        }
    }

    private void removeEqualMessagesConcurrent(Handler h, int what, Object object) {
            findOrRemoveMessages(h, what, object, null, 0, mMatchHandlerWhatAndObjectEquals, true);
            return;
    }

    private void removeEqualMessagesLegacy(Handler h, int what, Object object) {
        synchronized (this) {
            Message p = mMessages;

@@ -1650,15 +1774,23 @@ public final class MessageQueue {
        }
    }

    void removeMessages(Handler h, Runnable r, Object object) {
        if (h == null || r == null) {
    void removeEqualMessages(Handler h, int what, Object object) {
        if (h == null) {
            return;
        }

        if (mUseConcurrent) {
            removeEqualMessagesConcurrent(h, what, object);
        } else {
            removeEqualMessagesLegacy(h, what, object);
        }
    }

    private void removeMessagesConcurrent(Handler h, Runnable r, Object object) {
        findOrRemoveMessages(h, -1, object, r, 0, mMatchHandlerRunnableAndObject, true);
            return;
    }

    private void removeMessagesLegacy(Handler h, Runnable r, Object object) {
        synchronized (this) {
            Message p = mMessages;

@@ -1701,6 +1833,18 @@ public final class MessageQueue {
        }
    }

    void removeMessages(Handler h, Runnable r, Object object) {
        if (h == null || r == null) {
            return;
        }

        if (mUseConcurrent) {
            removeMessagesConcurrent(h, r, object);
        } else {
            removeMessagesLegacy(h, r, object);
        }
    }

    private static final class MatchHandlerRunnableAndObjectEquals extends MessageCompare {
        @Override
        public boolean compareMessage(MessageNode n, Handler h, int what, Object object, Runnable r,
@@ -1714,15 +1858,12 @@ public final class MessageQueue {
    }
    private final MatchHandlerRunnableAndObjectEquals mMatchHandlerRunnableAndObjectEquals =
            new MatchHandlerRunnableAndObjectEquals();
    void removeEqualMessages(Handler h, Runnable r, Object object) {
        if (h == null || r == null) {
            return;
        }

        if (mUseConcurrent) {
    private void removeEqualMessagesConcurrent(Handler h, Runnable r, Object object) {
        findOrRemoveMessages(h, -1, object, r, 0, mMatchHandlerRunnableAndObjectEquals, true);
            return;
    }

    private void removeEqualMessagesLegacy(Handler h, Runnable r, Object object) {
        synchronized (this) {
            Message p = mMessages;

@@ -1765,6 +1906,18 @@ public final class MessageQueue {
        }
    }

    void removeEqualMessages(Handler h, Runnable r, Object object) {
        if (h == null || r == null) {
            return;
        }

        if (mUseConcurrent) {
            removeEqualMessagesConcurrent(h, r, object);
        } else {
            removeEqualMessagesLegacy(h, r, object);
        }
    }

    private static final class MatchHandlerAndObject extends MessageCompare {
        @Override
        public boolean compareMessage(MessageNode n, Handler h, int what, Object object, Runnable r,
@@ -1777,15 +1930,12 @@ public final class MessageQueue {
        }
    }
    private final MatchHandlerAndObject mMatchHandlerAndObject = new MatchHandlerAndObject();
    void removeCallbacksAndMessages(Handler h, Object object) {
        if (h == null) {
            return;
        }

        if (mUseConcurrent) {
    private void removeCallbacksAndMessagesConcurrent(Handler h, Object object) {
            findOrRemoveMessages(h, -1, object, null, 0, mMatchHandlerAndObject, true);
            return;
    }

    private void removeCallbacksAndMessagesLegacy(Handler h, Object object) {
        synchronized (this) {
            Message p = mMessages;

@@ -1827,6 +1977,18 @@ public final class MessageQueue {
        }
    }

    void removeCallbacksAndMessages(Handler h, Object object) {
        if (h == null) {
            return;
        }

        if (mUseConcurrent) {
            removeCallbacksAndMessagesConcurrent(h, object);
        } else {
            removeCallbacksAndMessagesLegacy(h, object);
        }
    }

    private static final class MatchHandlerAndObjectEquals extends MessageCompare {
        @Override
        public boolean compareMessage(MessageNode n, Handler h, int what, Object object, Runnable r,
@@ -1840,15 +2002,12 @@ public final class MessageQueue {
    }
    private final MatchHandlerAndObjectEquals mMatchHandlerAndObjectEquals =
            new MatchHandlerAndObjectEquals();
    void removeCallbacksAndEqualMessages(Handler h, Object object) {
        if (h == null) {
            return;
        }

        if (mUseConcurrent) {
    void removeCallbacksAndEqualMessagesConcurrent(Handler h, Object object) {
        findOrRemoveMessages(h, -1, object, null, 0, mMatchHandlerAndObjectEquals, true);
            return;
    }

    void removeCallbacksAndEqualMessagesLegacy(Handler h, Object object) {
        synchronized (this) {
            Message p = mMessages;

@@ -1890,6 +2049,18 @@ public final class MessageQueue {
        }
    }

    void removeCallbacksAndEqualMessages(Handler h, Object object) {
        if (h == null) {
            return;
        }

        if (mUseConcurrent) {
            removeCallbacksAndEqualMessagesConcurrent(h, object);
        } else {
            removeCallbacksAndEqualMessagesLegacy(h, object);
        }
    }

    private void removeAllMessagesLocked() {
        Message p = mMessages;
        while (p != null) {