blob: 01a23ce9f2ab556dad593e96cf08b293dd7cb1cf [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.os;
18
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080019import android.util.Log;
Jeff Brown5182c782013-10-15 20:31:52 -070020import android.util.Printer;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080021
Jeff Brown46b9ac02010-04-22 18:58:52 -070022import java.util.ArrayList;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080023
24/**
25 * Low-level class holding the list of messages to be dispatched by a
26 * {@link Looper}. Messages are not added directly to a MessageQueue,
27 * but rather through {@link Handler} objects associated with the Looper.
28 *
29 * <p>You can retrieve the MessageQueue for the current thread with
30 * {@link Looper#myQueue() Looper.myQueue()}.
31 */
Jeff Brown67fc67c2013-04-01 13:00:33 -070032public final class MessageQueue {
Jeff Brown0f85ce32012-02-16 14:41:10 -080033 // True if the message queue can be quit.
34 private final boolean mQuitAllowed;
35
36 @SuppressWarnings("unused")
Ashok Bhat63a37152014-01-10 14:15:21 +000037 private long mPtr; // used by native code
Jeff Brown0f85ce32012-02-16 14:41:10 -080038
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080039 Message mMessages;
Jeff Brown46b9ac02010-04-22 18:58:52 -070040 private final ArrayList<IdleHandler> mIdleHandlers = new ArrayList<IdleHandler>();
Jeff Browned739322010-09-21 15:14:14 -070041 private IdleHandler[] mPendingIdleHandlers;
Jeff Brown013cf842013-09-06 16:24:36 -070042 private boolean mQuitting;
Christopher Tatefa9e7c02010-05-06 12:07:10 -070043
Jeff Brown415d8c32010-10-05 15:35:37 -070044 // Indicates whether next() is blocked waiting in pollOnce() with a non-zero timeout.
45 private boolean mBlocked;
46
Jeff Brown0f85ce32012-02-16 14:41:10 -080047 // The next barrier token.
48 // Barriers are indicated by messages with a null target whose arg1 field carries the token.
49 private int mNextBarrierToken;
Jeff Browne799cb72012-02-14 11:53:33 -080050
Ashok Bhat63a37152014-01-10 14:15:21 +000051 private native static long nativeInit();
52 private native static void nativeDestroy(long ptr);
53 private native static void nativePollOnce(long ptr, int timeoutMillis);
54 private native static void nativeWake(long ptr);
55 private native static boolean nativeIsIdling(long ptr);
Jeff Brown46b9ac02010-04-22 18:58:52 -070056
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080057 /**
58 * Callback interface for discovering when a thread is going to block
59 * waiting for more messages.
60 */
61 public static interface IdleHandler {
62 /**
63 * Called when the message queue has run out of messages and will now
64 * wait for more. Return true to keep your idle handler active, false
65 * to have it removed. This may be called if there are still messages
66 * pending in the queue, but they are all scheduled to be dispatched
67 * after the current time.
68 */
69 boolean queueIdle();
70 }
71
72 /**
73 * Add a new {@link IdleHandler} to this message queue. This may be
74 * removed automatically for you by returning false from
75 * {@link IdleHandler#queueIdle IdleHandler.queueIdle()} when it is
76 * invoked, or explicitly removing it with {@link #removeIdleHandler}.
77 *
78 * <p>This method is safe to call from any thread.
79 *
80 * @param handler The IdleHandler to be added.
81 */
Jeff Brown67fc67c2013-04-01 13:00:33 -070082 public void addIdleHandler(IdleHandler handler) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080083 if (handler == null) {
84 throw new NullPointerException("Can't add a null IdleHandler");
85 }
86 synchronized (this) {
87 mIdleHandlers.add(handler);
88 }
89 }
90
91 /**
92 * Remove an {@link IdleHandler} from the queue that was previously added
93 * with {@link #addIdleHandler}. If the given object is not currently
94 * in the idle list, nothing is done.
95 *
96 * @param handler The IdleHandler to be removed.
97 */
Jeff Brown67fc67c2013-04-01 13:00:33 -070098 public void removeIdleHandler(IdleHandler handler) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080099 synchronized (this) {
100 mIdleHandlers.remove(handler);
101 }
102 }
Jeff Browne799cb72012-02-14 11:53:33 -0800103
Jeff Brown0f85ce32012-02-16 14:41:10 -0800104 MessageQueue(boolean quitAllowed) {
105 mQuitAllowed = quitAllowed;
Jeff Brown864693462013-01-28 14:25:53 -0800106 mPtr = nativeInit();
Christopher Tatefa9e7c02010-05-06 12:07:10 -0700107 }
Jeff Brown0f85ce32012-02-16 14:41:10 -0800108
Jeff Brown46b9ac02010-04-22 18:58:52 -0700109 @Override
110 protected void finalize() throws Throwable {
111 try {
Jeff Brown864693462013-01-28 14:25:53 -0800112 dispose();
Jeff Brown46b9ac02010-04-22 18:58:52 -0700113 } finally {
114 super.finalize();
115 }
116 }
Christopher Tatefa9e7c02010-05-06 12:07:10 -0700117
Jeff Brown013cf842013-09-06 16:24:36 -0700118 // Disposes of the underlying message queue.
119 // Must only be called on the looper thread or the finalizer.
Jeff Brown864693462013-01-28 14:25:53 -0800120 private void dispose() {
121 if (mPtr != 0) {
122 nativeDestroy(mPtr);
123 mPtr = 0;
124 }
125 }
126
Jeff Brown67fc67c2013-04-01 13:00:33 -0700127 Message next() {
Jeff Brown60583902013-09-09 16:14:20 -0700128 // Return here if the message loop has already quit and been disposed.
129 // This can happen if the application tries to restart a looper after quit
130 // which is not supported.
Narayan Kamathab864342014-01-16 11:22:52 +0000131 final long ptr = mPtr;
Jeff Brown60583902013-09-09 16:14:20 -0700132 if (ptr == 0) {
133 return null;
134 }
135
Jeff Browned739322010-09-21 15:14:14 -0700136 int pendingIdleHandlerCount = -1; // -1 only during first iteration
137 int nextPollTimeoutMillis = 0;
Jeff Browned739322010-09-21 15:14:14 -0700138 for (;;) {
139 if (nextPollTimeoutMillis != 0) {
140 Binder.flushPendingCommands();
141 }
Jeff Brown013cf842013-09-06 16:24:36 -0700142
Jeff Brown60583902013-09-09 16:14:20 -0700143 nativePollOnce(ptr, nextPollTimeoutMillis);
Christopher Tatefa9e7c02010-05-06 12:07:10 -0700144
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800145 synchronized (this) {
Jeff Browned739322010-09-21 15:14:14 -0700146 // Try to retrieve the next message. Return if found.
147 final long now = SystemClock.uptimeMillis();
Jeff Browne799cb72012-02-14 11:53:33 -0800148 Message prevMsg = null;
149 Message msg = mMessages;
Jeff Brown0f85ce32012-02-16 14:41:10 -0800150 if (msg != null && msg.target == null) {
151 // Stalled by a barrier. Find the next asynchronous message in the queue.
152 do {
153 prevMsg = msg;
154 msg = msg.next;
155 } while (msg != null && !msg.isAsynchronous());
156 }
157 if (msg != null) {
158 if (now < msg.when) {
Jeff Browne799cb72012-02-14 11:53:33 -0800159 // Next message is not ready. Set a timeout to wake up when it is ready.
Jeff Brown0f85ce32012-02-16 14:41:10 -0800160 nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
161 } else {
Jeff Browne799cb72012-02-14 11:53:33 -0800162 // Got a message.
Jeff Brown415d8c32010-10-05 15:35:37 -0700163 mBlocked = false;
Jeff Browne799cb72012-02-14 11:53:33 -0800164 if (prevMsg != null) {
165 prevMsg.next = msg.next;
166 } else {
167 mMessages = msg.next;
168 }
Jeff Brown415d8c32010-10-05 15:35:37 -0700169 msg.next = null;
Joe Onorato43a17652011-04-06 19:22:23 -0700170 if (false) Log.v("MessageQueue", "Returning message: " + msg);
Jeff Browned739322010-09-21 15:14:14 -0700171 return msg;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800172 }
Jeff Brown0f85ce32012-02-16 14:41:10 -0800173 } else {
174 // No more messages.
175 nextPollTimeoutMillis = -1;
Jeff Browned739322010-09-21 15:14:14 -0700176 }
177
Jeff Brown024136f2013-04-11 19:21:32 -0700178 // Process the quit message now that all pending messages have been handled.
Jeff Brown013cf842013-09-06 16:24:36 -0700179 if (mQuitting) {
Jeff Brown024136f2013-04-11 19:21:32 -0700180 dispose();
181 return null;
182 }
183
Jeff Browne799cb72012-02-14 11:53:33 -0800184 // If first time idle, then get the number of idlers to run.
Jeff Brown0f85ce32012-02-16 14:41:10 -0800185 // Idle handles only run if the queue is empty or if the first message
186 // in the queue (possibly a barrier) is due to be handled in the future.
187 if (pendingIdleHandlerCount < 0
188 && (mMessages == null || now < mMessages.when)) {
Jeff Browned739322010-09-21 15:14:14 -0700189 pendingIdleHandlerCount = mIdleHandlers.size();
190 }
Jeff Browne799cb72012-02-14 11:53:33 -0800191 if (pendingIdleHandlerCount <= 0) {
Jeff Browned739322010-09-21 15:14:14 -0700192 // No idle handlers to run. Loop and wait some more.
Jeff Brown415d8c32010-10-05 15:35:37 -0700193 mBlocked = true;
Jeff Browned739322010-09-21 15:14:14 -0700194 continue;
195 }
196
197 if (mPendingIdleHandlers == null) {
198 mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];
199 }
200 mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);
201 }
202
203 // Run the idle handlers.
204 // We only ever reach this code block during the first iteration.
205 for (int i = 0; i < pendingIdleHandlerCount; i++) {
206 final IdleHandler idler = mPendingIdleHandlers[i];
207 mPendingIdleHandlers[i] = null; // release the reference to the handler
208
209 boolean keep = false;
210 try {
211 keep = idler.queueIdle();
212 } catch (Throwable t) {
213 Log.wtf("MessageQueue", "IdleHandler threw exception", t);
214 }
215
216 if (!keep) {
217 synchronized (this) {
218 mIdleHandlers.remove(idler);
219 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800220 }
221 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800222
Jeff Browned739322010-09-21 15:14:14 -0700223 // Reset the idle handler count to 0 so we do not run them again.
224 pendingIdleHandlerCount = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800225
Jeff Browned739322010-09-21 15:14:14 -0700226 // While calling an idle handler, a new message could have been delivered
227 // so go back and look again for a pending message without waiting.
228 nextPollTimeoutMillis = 0;
229 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800230 }
231
Jeff Brown8b60e452013-04-18 15:17:48 -0700232 void quit(boolean safe) {
Jeff Brown0f85ce32012-02-16 14:41:10 -0800233 if (!mQuitAllowed) {
Jeff Brown9867ed72014-02-28 14:00:57 -0800234 throw new IllegalStateException("Main thread not allowed to quit.");
Jeff Brown0f85ce32012-02-16 14:41:10 -0800235 }
236
237 synchronized (this) {
Jeff Brown013cf842013-09-06 16:24:36 -0700238 if (mQuitting) {
Jeff Brown0f85ce32012-02-16 14:41:10 -0800239 return;
240 }
Jeff Brown013cf842013-09-06 16:24:36 -0700241 mQuitting = true;
Jeff Brown8b60e452013-04-18 15:17:48 -0700242
243 if (safe) {
244 removeAllFutureMessagesLocked();
245 } else {
246 removeAllMessagesLocked();
247 }
Jeff Brown013cf842013-09-06 16:24:36 -0700248
249 // We can assume mPtr != 0 because mQuitting was previously false.
250 nativeWake(mPtr);
Jeff Brown0f85ce32012-02-16 14:41:10 -0800251 }
Jeff Brown0f85ce32012-02-16 14:41:10 -0800252 }
253
Jeff Brown67fc67c2013-04-01 13:00:33 -0700254 int enqueueSyncBarrier(long when) {
Jeff Brown0f85ce32012-02-16 14:41:10 -0800255 // Enqueue a new sync barrier token.
256 // We don't need to wake the queue because the purpose of a barrier is to stall it.
257 synchronized (this) {
258 final int token = mNextBarrierToken++;
259 final Message msg = Message.obtain();
Jeff Brown9867ed72014-02-28 14:00:57 -0800260 msg.markInUse();
Jeff Brown5182c782013-10-15 20:31:52 -0700261 msg.when = when;
Jeff Brown0f85ce32012-02-16 14:41:10 -0800262 msg.arg1 = token;
263
264 Message prev = null;
265 Message p = mMessages;
266 if (when != 0) {
267 while (p != null && p.when <= when) {
268 prev = p;
269 p = p.next;
270 }
271 }
272 if (prev != null) { // invariant: p == prev.next
273 msg.next = p;
274 prev.next = msg;
275 } else {
276 msg.next = p;
277 mMessages = msg;
278 }
279 return token;
280 }
281 }
282
Jeff Brown67fc67c2013-04-01 13:00:33 -0700283 void removeSyncBarrier(int token) {
Jeff Brown0f85ce32012-02-16 14:41:10 -0800284 // Remove a sync barrier token from the queue.
285 // If the queue is no longer stalled by a barrier then wake it.
Jeff Brown0f85ce32012-02-16 14:41:10 -0800286 synchronized (this) {
287 Message prev = null;
288 Message p = mMessages;
289 while (p != null && (p.target != null || p.arg1 != token)) {
290 prev = p;
291 p = p.next;
292 }
293 if (p == null) {
294 throw new IllegalStateException("The specified message queue synchronization "
295 + " barrier token has not been posted or has already been removed.");
296 }
Jeff Brown013cf842013-09-06 16:24:36 -0700297 final boolean needWake;
Jeff Brown0f85ce32012-02-16 14:41:10 -0800298 if (prev != null) {
299 prev.next = p.next;
300 needWake = false;
301 } else {
302 mMessages = p.next;
303 needWake = mMessages == null || mMessages.target != null;
304 }
Jeff Brown9867ed72014-02-28 14:00:57 -0800305 p.recycleUnchecked();
Jeff Brown013cf842013-09-06 16:24:36 -0700306
307 // If the loop is quitting then it is already awake.
308 // We can assume mPtr != 0 when mQuitting is false.
309 if (needWake && !mQuitting) {
310 nativeWake(mPtr);
311 }
Jeff Brown0f85ce32012-02-16 14:41:10 -0800312 }
313 }
314
Jeff Brown67fc67c2013-04-01 13:00:33 -0700315 boolean enqueueMessage(Message msg, long when) {
Jeff Brown0f85ce32012-02-16 14:41:10 -0800316 if (msg.target == null) {
Jeff Brown9867ed72014-02-28 14:00:57 -0800317 throw new IllegalArgumentException("Message must have a target.");
318 }
319 if (msg.isInUse()) {
320 throw new IllegalStateException(msg + " This message is already in use.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800321 }
Jeff Brown0f85ce32012-02-16 14:41:10 -0800322
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800323 synchronized (this) {
Jeff Brown013cf842013-09-06 16:24:36 -0700324 if (mQuitting) {
Jeff Brown9867ed72014-02-28 14:00:57 -0800325 IllegalStateException e = new IllegalStateException(
Jeff Brown0f85ce32012-02-16 14:41:10 -0800326 msg.target + " sending message to a Handler on a dead thread");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800327 Log.w("MessageQueue", e.getMessage(), e);
Jeff Brown9867ed72014-02-28 14:00:57 -0800328 msg.recycle();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800329 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800330 }
331
Jeff Brown9867ed72014-02-28 14:00:57 -0800332 msg.markInUse();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800333 msg.when = when;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800334 Message p = mMessages;
Jeff Brown013cf842013-09-06 16:24:36 -0700335 boolean needWake;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800336 if (p == null || when == 0 || when < p.when) {
Jeff Browne799cb72012-02-14 11:53:33 -0800337 // New head, wake up the event queue if blocked.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800338 msg.next = p;
339 mMessages = msg;
Jeff Browne799cb72012-02-14 11:53:33 -0800340 needWake = mBlocked;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800341 } else {
Jeff Browne799cb72012-02-14 11:53:33 -0800342 // Inserted within the middle of the queue. Usually we don't have to wake
Jeff Brown0f85ce32012-02-16 14:41:10 -0800343 // up the event queue unless there is a barrier at the head of the queue
344 // and the message is the earliest asynchronous message in the queue.
345 needWake = mBlocked && p.target == null && msg.isAsynchronous();
346 Message prev;
347 for (;;) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800348 prev = p;
349 p = p.next;
Jeff Brown0f85ce32012-02-16 14:41:10 -0800350 if (p == null || when < p.when) {
351 break;
352 }
353 if (needWake && p.isAsynchronous()) {
354 needWake = false;
355 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800356 }
Jeff Brown0f85ce32012-02-16 14:41:10 -0800357 msg.next = p; // invariant: p == prev.next
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800358 prev.next = msg;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800359 }
Jeff Brown013cf842013-09-06 16:24:36 -0700360
361 // We can assume mPtr != 0 because mQuitting is false.
362 if (needWake) {
363 nativeWake(mPtr);
364 }
Jeff Brown415d8c32010-10-05 15:35:37 -0700365 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800366 return true;
367 }
368
Jeff Brown67fc67c2013-04-01 13:00:33 -0700369 boolean hasMessages(Handler h, int what, Object object) {
Jeff Brown0f85ce32012-02-16 14:41:10 -0800370 if (h == null) {
371 return false;
372 }
373
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800374 synchronized (this) {
375 Message p = mMessages;
Jeff Brown0f85ce32012-02-16 14:41:10 -0800376 while (p != null) {
377 if (p.target == h && p.what == what && (object == null || p.obj == object)) {
378 return true;
379 }
380 p = p.next;
381 }
382 return false;
383 }
384 }
385
Jeff Brown67fc67c2013-04-01 13:00:33 -0700386 boolean hasMessages(Handler h, Runnable r, Object object) {
Romain Guyba6be8a2012-04-23 18:22:09 -0700387 if (h == null) {
388 return false;
389 }
390
391 synchronized (this) {
392 Message p = mMessages;
393 while (p != null) {
394 if (p.target == h && p.callback == r && (object == null || p.obj == object)) {
395 return true;
396 }
397 p = p.next;
398 }
399 return false;
400 }
401 }
402
Dianne Hackbornefa92b22013-05-03 14:11:43 -0700403 boolean isIdling() {
Jeff Brown013cf842013-09-06 16:24:36 -0700404 synchronized (this) {
Jeff Brown5182c782013-10-15 20:31:52 -0700405 return isIdlingLocked();
Jeff Brown013cf842013-09-06 16:24:36 -0700406 }
Dianne Hackbornefa92b22013-05-03 14:11:43 -0700407 }
408
Jeff Brown5182c782013-10-15 20:31:52 -0700409 private boolean isIdlingLocked() {
410 // If the loop is quitting then it must not be idling.
411 // We can assume mPtr != 0 when mQuitting is false.
412 return !mQuitting && nativeIsIdling(mPtr);
413 }
414
Jeff Brown67fc67c2013-04-01 13:00:33 -0700415 void removeMessages(Handler h, int what, Object object) {
Jeff Brown0f85ce32012-02-16 14:41:10 -0800416 if (h == null) {
417 return;
418 }
419
420 synchronized (this) {
421 Message p = mMessages;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800422
423 // Remove all messages at front.
424 while (p != null && p.target == h && p.what == what
425 && (object == null || p.obj == object)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800426 Message n = p.next;
427 mMessages = n;
Jeff Brown9867ed72014-02-28 14:00:57 -0800428 p.recycleUnchecked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800429 p = n;
430 }
431
432 // Remove all messages after front.
433 while (p != null) {
434 Message n = p.next;
435 if (n != null) {
436 if (n.target == h && n.what == what
437 && (object == null || n.obj == object)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800438 Message nn = n.next;
Jeff Brown9867ed72014-02-28 14:00:57 -0800439 n.recycleUnchecked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800440 p.next = nn;
441 continue;
442 }
443 }
444 p = n;
445 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800446 }
447 }
448
Jeff Brown67fc67c2013-04-01 13:00:33 -0700449 void removeMessages(Handler h, Runnable r, Object object) {
Jeff Brown0f85ce32012-02-16 14:41:10 -0800450 if (h == null || r == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800451 return;
452 }
453
454 synchronized (this) {
455 Message p = mMessages;
456
457 // Remove all messages at front.
458 while (p != null && p.target == h && p.callback == r
459 && (object == null || p.obj == object)) {
460 Message n = p.next;
461 mMessages = n;
Jeff Brown9867ed72014-02-28 14:00:57 -0800462 p.recycleUnchecked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800463 p = n;
464 }
465
466 // Remove all messages after front.
467 while (p != null) {
468 Message n = p.next;
469 if (n != null) {
470 if (n.target == h && n.callback == r
471 && (object == null || n.obj == object)) {
472 Message nn = n.next;
Jeff Brown9867ed72014-02-28 14:00:57 -0800473 n.recycleUnchecked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800474 p.next = nn;
475 continue;
476 }
477 }
478 p = n;
479 }
480 }
481 }
482
Jeff Brown67fc67c2013-04-01 13:00:33 -0700483 void removeCallbacksAndMessages(Handler h, Object object) {
Jeff Brown0f85ce32012-02-16 14:41:10 -0800484 if (h == null) {
485 return;
486 }
487
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800488 synchronized (this) {
489 Message p = mMessages;
490
491 // Remove all messages at front.
492 while (p != null && p.target == h
493 && (object == null || p.obj == object)) {
494 Message n = p.next;
495 mMessages = n;
Jeff Brown9867ed72014-02-28 14:00:57 -0800496 p.recycleUnchecked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800497 p = n;
498 }
499
500 // Remove all messages after front.
501 while (p != null) {
502 Message n = p.next;
503 if (n != null) {
504 if (n.target == h && (object == null || n.obj == object)) {
505 Message nn = n.next;
Jeff Brown9867ed72014-02-28 14:00:57 -0800506 n.recycleUnchecked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800507 p.next = nn;
508 continue;
509 }
510 }
511 p = n;
512 }
513 }
514 }
Jeff Brown8b60e452013-04-18 15:17:48 -0700515
516 private void removeAllMessagesLocked() {
517 Message p = mMessages;
518 while (p != null) {
519 Message n = p.next;
Jeff Brown9867ed72014-02-28 14:00:57 -0800520 p.recycleUnchecked();
Jeff Brown8b60e452013-04-18 15:17:48 -0700521 p = n;
522 }
523 mMessages = null;
524 }
525
526 private void removeAllFutureMessagesLocked() {
527 final long now = SystemClock.uptimeMillis();
528 Message p = mMessages;
529 if (p != null) {
530 if (p.when > now) {
531 removeAllMessagesLocked();
532 } else {
533 Message n;
534 for (;;) {
535 n = p.next;
536 if (n == null) {
537 return;
538 }
539 if (n.when > now) {
540 break;
541 }
542 p = n;
543 }
544 p.next = null;
545 do {
546 p = n;
547 n = p.next;
Jeff Brown9867ed72014-02-28 14:00:57 -0800548 p.recycleUnchecked();
Jeff Brown8b60e452013-04-18 15:17:48 -0700549 } while (n != null);
550 }
551 }
552 }
Jeff Brown5182c782013-10-15 20:31:52 -0700553
554 void dump(Printer pw, String prefix) {
555 synchronized (this) {
556 long now = SystemClock.uptimeMillis();
557 int n = 0;
558 for (Message msg = mMessages; msg != null; msg = msg.next) {
559 pw.println(prefix + "Message " + n + ": " + msg.toString(now));
560 n++;
561 }
562 pw.println(prefix + "(Total messages: " + n + ", idling=" + isIdlingLocked()
563 + ", quitting=" + mQuitting + ")");
564 }
565 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800566}