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

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

Don't call nativePollOnce unnecessarily

Fixes: 410218466
Flag: android.os.message_queue_native_poll_once_and_for_all
Test: MessageQueueTest
Change-Id: I6b31374b914c16b90cd3e63cebbfca7e870cb1ed
parent 43661d7a
Loading
Loading
Loading
Loading
+25 −6
Original line number Diff line number Diff line
@@ -98,6 +98,7 @@ public final class MessageQueue {
    @UnsupportedAppUsage
    private final ArrayList<IdleHandler> mIdleHandlers = new ArrayList<IdleHandler>();
    private SparseArray<FileDescriptorRecord> mFileDescriptorRecords;
    private volatile boolean mHasFileDescriptorRecords;
    private IdleHandler[] mPendingIdleHandlers;
    private boolean mQuitting;

@@ -584,6 +585,16 @@ public final class MessageQueue {

            setFileDescriptorEvents(fdNum, 0);
        }

        // Indicate to maybePollOnce() if we have file descriptor records that
        // need to be polled for events.
        // We write this volatile field here and read it from the worker thread.
        // Adding an FD on a client thread and polling for events on the worker thread are
        // inherently racy. If the worker thread skips polling because it thinks there are
        // no FDs to watch and there is a Message to handle, then the worker will still
        // poll for the same events the next time. Events won't be missed, they'll just be
        // interleaved with Message handling in undefined ways.
        mHasFileDescriptorRecords = mFileDescriptorRecords.size() > 0;
    }

    // Called from native code.
@@ -853,9 +864,18 @@ public final class MessageQueue {
        }
    }

    private void maybePollOnce(int nextPollTimeoutMillis) {
        if (!Flags.messageQueueNativePollOnceAndForAll()) {
            // If nativePollOnce optimization is not in effect, poll unconditionally.
            nativePollOnce(mPtr, nextPollTimeoutMillis);
        } else if (nextPollTimeoutMillis != 0 || mHasFileDescriptorRecords || getQuitting()) {
            // We need to wait for the next message, or we need to poll for file descriptor events.
            nativePollOnce(mPtr, nextPollTimeoutMillis);
        }
    }

    private Message nextConcurrent() {
        final long ptr = mPtr;
        if (ptr == 0) {
        if (mPtr == 0) {
            return null;
        }

@@ -867,7 +887,7 @@ public final class MessageQueue {
            }

            mMessageDirectlyQueued = false;
            nativePollOnce(ptr, mNextPollTimeoutMillis);
            maybePollOnce(mNextPollTimeoutMillis);

            Message msg = nextMessage(false, false);
            if (msg != null) {
@@ -934,8 +954,7 @@ public final class MessageQueue {
        // 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.
        final long ptr = mPtr;
        if (ptr == 0) {
        if (mPtr == 0) {
            return null;
        }

@@ -946,7 +965,7 @@ public final class MessageQueue {
                Binder.flushPendingCommands();
            }

            nativePollOnce(ptr, nextPollTimeoutMillis);
            maybePollOnce(nextPollTimeoutMillis);

            synchronized (this) {
                // Try to retrieve the next message.  Return if found.
+22 −1
Original line number Diff line number Diff line
@@ -438,6 +438,7 @@ public final class MessageQueue {
    private final Object mFileDescriptorRecordsLock = new Object();
    @GuardedBy("mFileDescriptorRecordsLock")
    private SparseArray<FileDescriptorRecord> mFileDescriptorRecords;
    private volatile boolean mHasFileDescriptorRecords;

    // The next barrier token.
    // Barriers are indicated by messages with a null target whose arg1 field carries the token.
@@ -885,6 +886,16 @@ public final class MessageQueue {
        }
    }

    private void maybePollOnce(int nextPollTimeoutMillis) {
        if (!Flags.messageQueueNativePollOnceAndForAll()) {
            // If nativePollOnce optimization is not in effect, poll unconditionally.
            nativePollOnce(mPtr, nextPollTimeoutMillis);
        } else if (nextPollTimeoutMillis != 0 || mHasFileDescriptorRecords || getQuitting()) {
            // We need to wait for the next message, or we need to poll for file descriptor events.
            nativePollOnce(mPtr, nextPollTimeoutMillis);
        }
    }

    Message next() {
        final long ptr = mPtr;
        if (ptr == 0) {
@@ -899,7 +910,7 @@ public final class MessageQueue {
            }

            mMessageDirectlyQueued = false;
            nativePollOnce(ptr, mNextPollTimeoutMillis);
            maybePollOnce(mNextPollTimeoutMillis);

            Message msg = nextMessage(false, false);
            if (msg != null) {
@@ -1750,6 +1761,16 @@ public final class MessageQueue {
            mFileDescriptorRecords.removeAt(index);
            setFileDescriptorEvents(fdNum, 0);
        }

        // Indicate to maybePollOnce() if we have file descriptor records that
        // need to be polled for events.
        // We write this volatile field here and read it from the worker thread.
        // Adding an FD on a client thread and polling for events on the worker thread are
        // inherently racy. If the worker thread skips polling because it thinks there are
        // no FDs to watch and there is a Message to handle, then the worker will still
        // poll for the same events the next time. Events won't be missed, they'll just be
        // interleaved with Message handling in undefined ways.
        mHasFileDescriptorRecords = mFileDescriptorRecords.size() > 0;
    }

    // Called from native code.
+22 −1
Original line number Diff line number Diff line
@@ -71,6 +71,7 @@ public final class MessageQueue {
    @UnsupportedAppUsage
    private final ArrayList<IdleHandler> mIdleHandlers = new ArrayList<IdleHandler>();
    private SparseArray<FileDescriptorRecord> mFileDescriptorRecords;
    private volatile boolean mHasFileDescriptorRecords;
    private IdleHandler[] mPendingIdleHandlers;
    private boolean mQuitting;

@@ -326,6 +327,16 @@ public final class MessageQueue {
            mFileDescriptorRecords.removeAt(index);
            nativeSetFileDescriptorEvents(mPtr, fdNum, 0);
        }

        // Indicate to maybePollOnce() if we have file descriptor records that
        // need to be polled for events.
        // We write this volatile field here and read it from the worker thread.
        // Adding an FD on a client thread and polling for events on the worker thread are
        // inherently racy. If the worker thread skips polling because it thinks there are
        // no FDs to watch and there is a Message to handle, then the worker will still
        // poll for the same events the next time. Events won't be missed, they'll just be
        // interleaved with Message handling in undefined ways.
        mHasFileDescriptorRecords = mFileDescriptorRecords.size() > 0;
    }

    // Called from native code.
@@ -380,6 +391,16 @@ public final class MessageQueue {

    private static final AtomicLong mMessagesDelivered = new AtomicLong();

    private void maybePollOnce(int nextPollTimeoutMillis) {
        if (!Flags.messageQueueNativePollOnceAndForAll()) {
            // If nativePollOnce optimization is not in effect, poll unconditionally.
            nativePollOnce(mPtr, nextPollTimeoutMillis);
        } else if (nextPollTimeoutMillis != 0 || mHasFileDescriptorRecords) {
            // We need to wait for the next message, or we need to poll for file descriptor events.
            nativePollOnce(mPtr, nextPollTimeoutMillis);
        }
    }

    @UnsupportedAppUsage
    Message next() {
        // Return here if the message loop has already quit and been disposed.
@@ -397,7 +418,7 @@ public final class MessageQueue {
                Binder.flushPendingCommands();
            }

            nativePollOnce(ptr, nextPollTimeoutMillis);
            maybePollOnce(nextPollTimeoutMillis);

            synchronized (this) {
                // Try to retrieve the next message.  Return if found.
+8 −0
Original line number Diff line number Diff line
@@ -310,6 +310,14 @@ flag {
    is_exported: true
}

flag {
    name: "message_queue_native_poll_once_and_for_all"
    namespace: "system_performance"
    description: "Don't call nativePollOnce unnecessarily."
    bug: "410218466"
    is_fixed_read_only: false
}

flag {
     name: "message_queue_testability"
     namespace: "system_performance"