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

Commit cbf2b02d authored by Jeff Brown's avatar Jeff Brown Committed by Android Git Automerger
Browse files

am 23a5f44c: Merge "Fix native crash when message queue quits." into klp-dev

* commit '23a5f44c':
  Fix native crash when message queue quits.
parents affacbcc 23a5f44c
Loading
Loading
Loading
Loading
+31 −16
Original line number Diff line number Diff line
@@ -39,7 +39,7 @@ public final class MessageQueue {
    Message mMessages;
    private final ArrayList<IdleHandler> mIdleHandlers = new ArrayList<IdleHandler>();
    private IdleHandler[] mPendingIdleHandlers;
    private boolean mQuiting;
    private boolean mQuitting;

    // Indicates whether next() is blocked waiting in pollOnce() with a non-zero timeout.
    private boolean mBlocked;
@@ -115,6 +115,8 @@ public final class MessageQueue {
        }
    }

    // Disposes of the underlying message queue.
    // Must only be called on the looper thread or the finalizer.
    private void dispose() {
        if (mPtr != 0) {
            nativeDestroy(mPtr);
@@ -125,11 +127,13 @@ public final class MessageQueue {
    Message next() {
        int pendingIdleHandlerCount = -1; // -1 only during first iteration
        int nextPollTimeoutMillis = 0;

        for (;;) {
            if (nextPollTimeoutMillis != 0) {
                Binder.flushPendingCommands();
            }

            // We can assume mPtr != 0 because the loop is obviously still running.
            // The looper will not call this method after the loop quits.
            nativePollOnce(mPtr, nextPollTimeoutMillis);

            synchronized (this) {
@@ -167,7 +171,7 @@ public final class MessageQueue {
                }

                // Process the quit message now that all pending messages have been handled.
                if (mQuiting) {
                if (mQuitting) {
                    dispose();
                    return null;
                }
@@ -226,19 +230,21 @@ public final class MessageQueue {
        }

        synchronized (this) {
            if (mQuiting) {
            if (mQuitting) {
                return;
            }
            mQuiting = true;
            mQuitting = true;

            if (safe) {
                removeAllFutureMessagesLocked();
            } else {
                removeAllMessagesLocked();
            }
        }

            // We can assume mPtr != 0 because mQuitting was previously false.
            nativeWake(mPtr);
        }
    }

    int enqueueSyncBarrier(long when) {
        // Enqueue a new sync barrier token.
@@ -270,7 +276,6 @@ public final class MessageQueue {
    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.
        final boolean needWake;
        synchronized (this) {
            Message prev = null;
            Message p = mMessages;
@@ -282,6 +287,7 @@ public final class MessageQueue {
                throw new IllegalStateException("The specified message queue synchronization "
                        + " barrier token has not been posted or has already been removed.");
            }
            final boolean needWake;
            if (prev != null) {
                prev.next = p.next;
                needWake = false;
@@ -290,11 +296,14 @@ public final class MessageQueue {
                needWake = mMessages == null || mMessages.target != null;
            }
            p.recycle();
        }
        if (needWake) {

            // If the loop is quitting then it is already awake.
            // We can assume mPtr != 0 when mQuitting is false.
            if (needWake && !mQuitting) {
                nativeWake(mPtr);
            }
        }
    }

    boolean enqueueMessage(Message msg, long when) {
        if (msg.isInUse()) {
@@ -304,9 +313,8 @@ public final class MessageQueue {
            throw new AndroidRuntimeException("Message must have a target.");
        }

        boolean needWake;
        synchronized (this) {
            if (mQuiting) {
            if (mQuitting) {
                RuntimeException e = new RuntimeException(
                        msg.target + " sending message to a Handler on a dead thread");
                Log.w("MessageQueue", e.getMessage(), e);
@@ -315,6 +323,7 @@ public final class MessageQueue {

            msg.when = when;
            Message p = mMessages;
            boolean needWake;
            if (p == null || when == 0 || when < p.when) {
                // New head, wake up the event queue if blocked.
                msg.next = p;
@@ -339,10 +348,12 @@ public final class MessageQueue {
                msg.next = p; // invariant: p == prev.next
                prev.next = msg;
            }
        }

            // We can assume mPtr != 0 because mQuitting is false.
            if (needWake) {
                nativeWake(mPtr);
            }
        }
        return true;
    }

@@ -381,7 +392,11 @@ public final class MessageQueue {
    }

    boolean isIdling() {
        return nativeIsIdling(mPtr);
        synchronized (this) {
            // If the loop is quitting then it must not be idling.
            // We can assume mPtr != 0 when mQuitting is false.
            return !mQuitting && nativeIsIdling(mPtr);
        }
    }

    void removeMessages(Handler h, int what, Object object) {