summaryrefslogtreecommitdiff
path: root/core/java/android/os/MessageQueue.java
diff options
context:
space:
mode:
Diffstat (limited to 'core/java/android/os/MessageQueue.java')
-rw-r--r--core/java/android/os/MessageQueue.java50
1 files changed, 35 insertions, 15 deletions
diff --git a/core/java/android/os/MessageQueue.java b/core/java/android/os/MessageQueue.java
index bf7e5caf7024..d1b8213d95fc 100644
--- a/core/java/android/os/MessageQueue.java
+++ b/core/java/android/os/MessageQueue.java
@@ -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;
@@ -52,6 +52,7 @@ public final class MessageQueue {
private native static void nativeDestroy(int ptr);
private native static void nativePollOnce(int ptr, int timeoutMillis);
private native static void nativeWake(int ptr);
+ private native static boolean nativeIsIdling(int ptr);
/**
* Callback interface for discovering when a thread is going to block
@@ -114,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);
@@ -124,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) {
@@ -166,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;
}
@@ -225,18 +230,20 @@ 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);
}
- nativeWake(mPtr);
}
int enqueueSyncBarrier(long when) {
@@ -269,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;
@@ -281,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;
@@ -289,9 +296,12 @@ public final class MessageQueue {
needWake = mMessages == null || mMessages.target != null;
}
p.recycle();
- }
- if (needWake) {
- nativeWake(mPtr);
+
+ // If the loop is quitting then it is already awake.
+ // We can assume mPtr != 0 when mQuitting is false.
+ if (needWake && !mQuitting) {
+ nativeWake(mPtr);
+ }
}
}
@@ -303,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);
@@ -314,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;
@@ -338,9 +348,11 @@ public final class MessageQueue {
msg.next = p; // invariant: p == prev.next
prev.next = msg;
}
- }
- if (needWake) {
- nativeWake(mPtr);
+
+ // We can assume mPtr != 0 because mQuitting is false.
+ if (needWake) {
+ nativeWake(mPtr);
+ }
}
return true;
}
@@ -379,6 +391,14 @@ public final class MessageQueue {
}
}
+ boolean isIdling() {
+ 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) {
if (h == null) {
return;