am 23a5f44c: Merge "Fix native crash when message queue quits." into klp-dev
* commit '23a5f44c5a306b4a70821722a697da55cc3c5db8': Fix native crash when message queue quits.
This commit is contained in:
@@ -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,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) {
|
||||
@@ -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,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,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;
|
||||
}
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user