blob: 75f9813b7ae70d1efd9917398080f1b01593bcd8 [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.AndroidRuntimeException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080020import android.util.Log;
Jeff Brown5182c782013-10-15 20:31:52 -070021import android.util.Printer;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080022
Jeff Brown46b9ac02010-04-22 18:58:52 -070023import java.util.ArrayList;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080024
25/**
26 * Low-level class holding the list of messages to be dispatched by a
27 * {@link Looper}. Messages are not added directly to a MessageQueue,
28 * but rather through {@link Handler} objects associated with the Looper.
29 *
30 * <p>You can retrieve the MessageQueue for the current thread with
31 * {@link Looper#myQueue() Looper.myQueue()}.
32 */
Jeff Brown67fc67c2013-04-01 13:00:33 -070033public final class MessageQueue {
Jeff Brown0f85ce32012-02-16 14:41:10 -080034 // True if the message queue can be quit.
35 private final boolean mQuitAllowed;
36
37 @SuppressWarnings("unused")
Ashok Bhat63a37152014-01-10 14:15:21 +000038 private long mPtr; // used by native code
Jeff Brown0f85ce32012-02-16 14:41:10 -080039
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080040 Message mMessages;
Jeff Brown46b9ac02010-04-22 18:58:52 -070041 private final ArrayList<IdleHandler> mIdleHandlers = new ArrayList<IdleHandler>();
Jeff Browned739322010-09-21 15:14:14 -070042 private IdleHandler[] mPendingIdleHandlers;
Jeff Brown013cf842013-09-06 16:24:36 -070043 private boolean mQuitting;
Christopher Tatefa9e7c02010-05-06 12:07:10 -070044
Jeff Brown415d8c32010-10-05 15:35:37 -070045 // Indicates whether next() is blocked waiting in pollOnce() with a non-zero timeout.
46 private boolean mBlocked;
47
Jeff Brown0f85ce32012-02-16 14:41:10 -080048 // The next barrier token.
49 // Barriers are indicated by messages with a null target whose arg1 field carries the token.
50 private int mNextBarrierToken;
Jeff Browne799cb72012-02-14 11:53:33 -080051
Ashok Bhat63a37152014-01-10 14:15:21 +000052 private native static long nativeInit();
53 private native static void nativeDestroy(long ptr);
54 private native static void nativePollOnce(long ptr, int timeoutMillis);
55 private native static void nativeWake(long ptr);
56 private native static boolean nativeIsIdling(long ptr);
Jeff Brown46b9ac02010-04-22 18:58:52 -070057
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080058 /**
59 * Callback interface for discovering when a thread is going to block
60 * waiting for more messages.
61 */
62 public static interface IdleHandler {
63 /**
64 * Called when the message queue has run out of messages and will now
65 * wait for more. Return true to keep your idle handler active, false
66 * to have it removed. This may be called if there are still messages
67 * pending in the queue, but they are all scheduled to be dispatched
68 * after the current time.
69 */
70 boolean queueIdle();
71 }
72
73 /**
74 * Add a new {@link IdleHandler} to this message queue. This may be
75 * removed automatically for you by returning false from
76 * {@link IdleHandler#queueIdle IdleHandler.queueIdle()} when it is
77 * invoked, or explicitly removing it with {@link #removeIdleHandler}.
78 *
79 * <p>This method is safe to call from any thread.
80 *
81 * @param handler The IdleHandler to be added.
82 */
Jeff Brown67fc67c2013-04-01 13:00:33 -070083 public void addIdleHandler(IdleHandler handler) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080084 if (handler == null) {
85 throw new NullPointerException("Can't add a null IdleHandler");
86 }
87 synchronized (this) {
88 mIdleHandlers.add(handler);
89 }
90 }
91
92 /**
93 * Remove an {@link IdleHandler} from the queue that was previously added
94 * with {@link #addIdleHandler}. If the given object is not currently
95 * in the idle list, nothing is done.
96 *
97 * @param handler The IdleHandler to be removed.
98 */
Jeff Brown67fc67c2013-04-01 13:00:33 -070099 public void removeIdleHandler(IdleHandler handler) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800100 synchronized (this) {
101 mIdleHandlers.remove(handler);
102 }
103 }
Jeff Browne799cb72012-02-14 11:53:33 -0800104
Jeff Brown0f85ce32012-02-16 14:41:10 -0800105 MessageQueue(boolean quitAllowed) {
106 mQuitAllowed = quitAllowed;
Jeff Brown864693462013-01-28 14:25:53 -0800107 mPtr = nativeInit();
Christopher Tatefa9e7c02010-05-06 12:07:10 -0700108 }
Jeff Brown0f85ce32012-02-16 14:41:10 -0800109
Jeff Brown46b9ac02010-04-22 18:58:52 -0700110 @Override
111 protected void finalize() throws Throwable {
112 try {
Jeff Brown864693462013-01-28 14:25:53 -0800113 dispose();
Jeff Brown46b9ac02010-04-22 18:58:52 -0700114 } finally {
115 super.finalize();
116 }
117 }
Christopher Tatefa9e7c02010-05-06 12:07:10 -0700118
Jeff Brown013cf842013-09-06 16:24:36 -0700119 // Disposes of the underlying message queue.
120 // Must only be called on the looper thread or the finalizer.
Jeff Brown864693462013-01-28 14:25:53 -0800121 private void dispose() {
122 if (mPtr != 0) {
123 nativeDestroy(mPtr);
124 mPtr = 0;
125 }
126 }
127
Jeff Brown67fc67c2013-04-01 13:00:33 -0700128 Message next() {
Jeff Browned739322010-09-21 15:14:14 -0700129 int pendingIdleHandlerCount = -1; // -1 only during first iteration
130 int nextPollTimeoutMillis = 0;
Jeff Browned739322010-09-21 15:14:14 -0700131 for (;;) {
132 if (nextPollTimeoutMillis != 0) {
133 Binder.flushPendingCommands();
134 }
Jeff Brown013cf842013-09-06 16:24:36 -0700135
136 // We can assume mPtr != 0 because the loop is obviously still running.
137 // The looper will not call this method after the loop quits.
Jeff Brown415d8c32010-10-05 15:35:37 -0700138 nativePollOnce(mPtr, nextPollTimeoutMillis);
Christopher Tatefa9e7c02010-05-06 12:07:10 -0700139
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800140 synchronized (this) {
Jeff Browned739322010-09-21 15:14:14 -0700141 // Try to retrieve the next message. Return if found.
142 final long now = SystemClock.uptimeMillis();
Jeff Browne799cb72012-02-14 11:53:33 -0800143 Message prevMsg = null;
144 Message msg = mMessages;
Jeff Brown0f85ce32012-02-16 14:41:10 -0800145 if (msg != null && msg.target == null) {
146 // Stalled by a barrier. Find the next asynchronous message in the queue.
147 do {
148 prevMsg = msg;
149 msg = msg.next;
150 } while (msg != null && !msg.isAsynchronous());
151 }
152 if (msg != null) {
153 if (now < msg.when) {
Jeff Browne799cb72012-02-14 11:53:33 -0800154 // Next message is not ready. Set a timeout to wake up when it is ready.
Jeff Brown0f85ce32012-02-16 14:41:10 -0800155 nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
156 } else {
Jeff Browne799cb72012-02-14 11:53:33 -0800157 // Got a message.
Jeff Brown415d8c32010-10-05 15:35:37 -0700158 mBlocked = false;
Jeff Browne799cb72012-02-14 11:53:33 -0800159 if (prevMsg != null) {
160 prevMsg.next = msg.next;
161 } else {
162 mMessages = msg.next;
163 }
Jeff Brown415d8c32010-10-05 15:35:37 -0700164 msg.next = null;
Joe Onorato43a17652011-04-06 19:22:23 -0700165 if (false) Log.v("MessageQueue", "Returning message: " + msg);
Jeff Brown85c3fe42010-09-21 16:45:16 -0700166 msg.markInUse();
Jeff Browned739322010-09-21 15:14:14 -0700167 return msg;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800168 }
Jeff Brown0f85ce32012-02-16 14:41:10 -0800169 } else {
170 // No more messages.
171 nextPollTimeoutMillis = -1;
Jeff Browned739322010-09-21 15:14:14 -0700172 }
173
Jeff Brown024136f2013-04-11 19:21:32 -0700174 // Process the quit message now that all pending messages have been handled.
Jeff Brown013cf842013-09-06 16:24:36 -0700175 if (mQuitting) {
Jeff Brown024136f2013-04-11 19:21:32 -0700176 dispose();
177 return null;
178 }
179
Jeff Browne799cb72012-02-14 11:53:33 -0800180 // If first time idle, then get the number of idlers to run.
Jeff Brown0f85ce32012-02-16 14:41:10 -0800181 // Idle handles only run if the queue is empty or if the first message
182 // in the queue (possibly a barrier) is due to be handled in the future.
183 if (pendingIdleHandlerCount < 0
184 && (mMessages == null || now < mMessages.when)) {
Jeff Browned739322010-09-21 15:14:14 -0700185 pendingIdleHandlerCount = mIdleHandlers.size();
186 }
Jeff Browne799cb72012-02-14 11:53:33 -0800187 if (pendingIdleHandlerCount <= 0) {
Jeff Browned739322010-09-21 15:14:14 -0700188 // No idle handlers to run. Loop and wait some more.
Jeff Brown415d8c32010-10-05 15:35:37 -0700189 mBlocked = true;
Jeff Browned739322010-09-21 15:14:14 -0700190 continue;
191 }
192
193 if (mPendingIdleHandlers == null) {
194 mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];
195 }
196 mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);
197 }
198
199 // Run the idle handlers.
200 // We only ever reach this code block during the first iteration.
201 for (int i = 0; i < pendingIdleHandlerCount; i++) {
202 final IdleHandler idler = mPendingIdleHandlers[i];
203 mPendingIdleHandlers[i] = null; // release the reference to the handler
204
205 boolean keep = false;
206 try {
207 keep = idler.queueIdle();
208 } catch (Throwable t) {
209 Log.wtf("MessageQueue", "IdleHandler threw exception", t);
210 }
211
212 if (!keep) {
213 synchronized (this) {
214 mIdleHandlers.remove(idler);
215 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800216 }
217 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800218
Jeff Browned739322010-09-21 15:14:14 -0700219 // Reset the idle handler count to 0 so we do not run them again.
220 pendingIdleHandlerCount = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800221
Jeff Browned739322010-09-21 15:14:14 -0700222 // While calling an idle handler, a new message could have been delivered
223 // so go back and look again for a pending message without waiting.
224 nextPollTimeoutMillis = 0;
225 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800226 }
227
Jeff Brown8b60e452013-04-18 15:17:48 -0700228 void quit(boolean safe) {
Jeff Brown0f85ce32012-02-16 14:41:10 -0800229 if (!mQuitAllowed) {
230 throw new RuntimeException("Main thread not allowed to quit.");
231 }
232
233 synchronized (this) {
Jeff Brown013cf842013-09-06 16:24:36 -0700234 if (mQuitting) {
Jeff Brown0f85ce32012-02-16 14:41:10 -0800235 return;
236 }
Jeff Brown013cf842013-09-06 16:24:36 -0700237 mQuitting = true;
Jeff Brown8b60e452013-04-18 15:17:48 -0700238
239 if (safe) {
240 removeAllFutureMessagesLocked();
241 } else {
242 removeAllMessagesLocked();
243 }
Jeff Brown013cf842013-09-06 16:24:36 -0700244
245 // We can assume mPtr != 0 because mQuitting was previously false.
246 nativeWake(mPtr);
Jeff Brown0f85ce32012-02-16 14:41:10 -0800247 }
Jeff Brown0f85ce32012-02-16 14:41:10 -0800248 }
249
Jeff Brown67fc67c2013-04-01 13:00:33 -0700250 int enqueueSyncBarrier(long when) {
Jeff Brown0f85ce32012-02-16 14:41:10 -0800251 // Enqueue a new sync barrier token.
252 // We don't need to wake the queue because the purpose of a barrier is to stall it.
253 synchronized (this) {
254 final int token = mNextBarrierToken++;
255 final Message msg = Message.obtain();
Jeff Brown5182c782013-10-15 20:31:52 -0700256 msg.when = when;
Jeff Brown0f85ce32012-02-16 14:41:10 -0800257 msg.arg1 = token;
258
259 Message prev = null;
260 Message p = mMessages;
261 if (when != 0) {
262 while (p != null && p.when <= when) {
263 prev = p;
264 p = p.next;
265 }
266 }
267 if (prev != null) { // invariant: p == prev.next
268 msg.next = p;
269 prev.next = msg;
270 } else {
271 msg.next = p;
272 mMessages = msg;
273 }
274 return token;
275 }
276 }
277
Jeff Brown67fc67c2013-04-01 13:00:33 -0700278 void removeSyncBarrier(int token) {
Jeff Brown0f85ce32012-02-16 14:41:10 -0800279 // Remove a sync barrier token from the queue.
280 // If the queue is no longer stalled by a barrier then wake it.
Jeff Brown0f85ce32012-02-16 14:41:10 -0800281 synchronized (this) {
282 Message prev = null;
283 Message p = mMessages;
284 while (p != null && (p.target != null || p.arg1 != token)) {
285 prev = p;
286 p = p.next;
287 }
288 if (p == null) {
289 throw new IllegalStateException("The specified message queue synchronization "
290 + " barrier token has not been posted or has already been removed.");
291 }
Jeff Brown013cf842013-09-06 16:24:36 -0700292 final boolean needWake;
Jeff Brown0f85ce32012-02-16 14:41:10 -0800293 if (prev != null) {
294 prev.next = p.next;
295 needWake = false;
296 } else {
297 mMessages = p.next;
298 needWake = mMessages == null || mMessages.target != null;
299 }
300 p.recycle();
Jeff Brown013cf842013-09-06 16:24:36 -0700301
302 // If the loop is quitting then it is already awake.
303 // We can assume mPtr != 0 when mQuitting is false.
304 if (needWake && !mQuitting) {
305 nativeWake(mPtr);
306 }
Jeff Brown0f85ce32012-02-16 14:41:10 -0800307 }
308 }
309
Jeff Brown67fc67c2013-04-01 13:00:33 -0700310 boolean enqueueMessage(Message msg, long when) {
Wink Savillea334e7c2010-08-24 10:56:30 -0700311 if (msg.isInUse()) {
Jeff Brown0f85ce32012-02-16 14:41:10 -0800312 throw new AndroidRuntimeException(msg + " This message is already in use.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800313 }
Jeff Brown0f85ce32012-02-16 14:41:10 -0800314 if (msg.target == null) {
315 throw new AndroidRuntimeException("Message must have a target.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800316 }
Jeff Brown0f85ce32012-02-16 14:41:10 -0800317
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800318 synchronized (this) {
Jeff Brown013cf842013-09-06 16:24:36 -0700319 if (mQuitting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800320 RuntimeException e = new RuntimeException(
Jeff Brown0f85ce32012-02-16 14:41:10 -0800321 msg.target + " sending message to a Handler on a dead thread");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800322 Log.w("MessageQueue", e.getMessage(), e);
323 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800324 }
325
326 msg.when = when;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800327 Message p = mMessages;
Jeff Brown013cf842013-09-06 16:24:36 -0700328 boolean needWake;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800329 if (p == null || when == 0 || when < p.when) {
Jeff Browne799cb72012-02-14 11:53:33 -0800330 // New head, wake up the event queue if blocked.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800331 msg.next = p;
332 mMessages = msg;
Jeff Browne799cb72012-02-14 11:53:33 -0800333 needWake = mBlocked;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800334 } else {
Jeff Browne799cb72012-02-14 11:53:33 -0800335 // Inserted within the middle of the queue. Usually we don't have to wake
Jeff Brown0f85ce32012-02-16 14:41:10 -0800336 // up the event queue unless there is a barrier at the head of the queue
337 // and the message is the earliest asynchronous message in the queue.
338 needWake = mBlocked && p.target == null && msg.isAsynchronous();
339 Message prev;
340 for (;;) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800341 prev = p;
342 p = p.next;
Jeff Brown0f85ce32012-02-16 14:41:10 -0800343 if (p == null || when < p.when) {
344 break;
345 }
346 if (needWake && p.isAsynchronous()) {
347 needWake = false;
348 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800349 }
Jeff Brown0f85ce32012-02-16 14:41:10 -0800350 msg.next = p; // invariant: p == prev.next
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800351 prev.next = msg;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800352 }
Jeff Brown013cf842013-09-06 16:24:36 -0700353
354 // We can assume mPtr != 0 because mQuitting is false.
355 if (needWake) {
356 nativeWake(mPtr);
357 }
Jeff Brown415d8c32010-10-05 15:35:37 -0700358 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800359 return true;
360 }
361
Jeff Brown67fc67c2013-04-01 13:00:33 -0700362 boolean hasMessages(Handler h, int what, Object object) {
Jeff Brown0f85ce32012-02-16 14:41:10 -0800363 if (h == null) {
364 return false;
365 }
366
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800367 synchronized (this) {
368 Message p = mMessages;
Jeff Brown0f85ce32012-02-16 14:41:10 -0800369 while (p != null) {
370 if (p.target == h && p.what == what && (object == null || p.obj == object)) {
371 return true;
372 }
373 p = p.next;
374 }
375 return false;
376 }
377 }
378
Jeff Brown67fc67c2013-04-01 13:00:33 -0700379 boolean hasMessages(Handler h, Runnable r, Object object) {
Romain Guyba6be8a2012-04-23 18:22:09 -0700380 if (h == null) {
381 return false;
382 }
383
384 synchronized (this) {
385 Message p = mMessages;
386 while (p != null) {
387 if (p.target == h && p.callback == r && (object == null || p.obj == object)) {
388 return true;
389 }
390 p = p.next;
391 }
392 return false;
393 }
394 }
395
Dianne Hackbornefa92b22013-05-03 14:11:43 -0700396 boolean isIdling() {
Jeff Brown013cf842013-09-06 16:24:36 -0700397 synchronized (this) {
Jeff Brown5182c782013-10-15 20:31:52 -0700398 return isIdlingLocked();
Jeff Brown013cf842013-09-06 16:24:36 -0700399 }
Dianne Hackbornefa92b22013-05-03 14:11:43 -0700400 }
401
Jeff Brown5182c782013-10-15 20:31:52 -0700402 private boolean isIdlingLocked() {
403 // If the loop is quitting then it must not be idling.
404 // We can assume mPtr != 0 when mQuitting is false.
405 return !mQuitting && nativeIsIdling(mPtr);
406 }
407
Jeff Brown67fc67c2013-04-01 13:00:33 -0700408 void removeMessages(Handler h, int what, Object object) {
Jeff Brown0f85ce32012-02-16 14:41:10 -0800409 if (h == null) {
410 return;
411 }
412
413 synchronized (this) {
414 Message p = mMessages;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800415
416 // Remove all messages at front.
417 while (p != null && p.target == h && p.what == what
418 && (object == null || p.obj == object)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800419 Message n = p.next;
420 mMessages = n;
421 p.recycle();
422 p = n;
423 }
424
425 // Remove all messages after front.
426 while (p != null) {
427 Message n = p.next;
428 if (n != null) {
429 if (n.target == h && n.what == what
430 && (object == null || n.obj == object)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800431 Message nn = n.next;
432 n.recycle();
433 p.next = nn;
434 continue;
435 }
436 }
437 p = n;
438 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800439 }
440 }
441
Jeff Brown67fc67c2013-04-01 13:00:33 -0700442 void removeMessages(Handler h, Runnable r, Object object) {
Jeff Brown0f85ce32012-02-16 14:41:10 -0800443 if (h == null || r == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800444 return;
445 }
446
447 synchronized (this) {
448 Message p = mMessages;
449
450 // Remove all messages at front.
451 while (p != null && p.target == h && p.callback == r
452 && (object == null || p.obj == object)) {
453 Message n = p.next;
454 mMessages = n;
455 p.recycle();
456 p = n;
457 }
458
459 // Remove all messages after front.
460 while (p != null) {
461 Message n = p.next;
462 if (n != null) {
463 if (n.target == h && n.callback == r
464 && (object == null || n.obj == object)) {
465 Message nn = n.next;
466 n.recycle();
467 p.next = nn;
468 continue;
469 }
470 }
471 p = n;
472 }
473 }
474 }
475
Jeff Brown67fc67c2013-04-01 13:00:33 -0700476 void removeCallbacksAndMessages(Handler h, Object object) {
Jeff Brown0f85ce32012-02-16 14:41:10 -0800477 if (h == null) {
478 return;
479 }
480
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800481 synchronized (this) {
482 Message p = mMessages;
483
484 // Remove all messages at front.
485 while (p != null && p.target == h
486 && (object == null || p.obj == object)) {
487 Message n = p.next;
488 mMessages = n;
489 p.recycle();
490 p = n;
491 }
492
493 // Remove all messages after front.
494 while (p != null) {
495 Message n = p.next;
496 if (n != null) {
497 if (n.target == h && (object == null || n.obj == object)) {
498 Message nn = n.next;
499 n.recycle();
500 p.next = nn;
501 continue;
502 }
503 }
504 p = n;
505 }
506 }
507 }
Jeff Brown8b60e452013-04-18 15:17:48 -0700508
509 private void removeAllMessagesLocked() {
510 Message p = mMessages;
511 while (p != null) {
512 Message n = p.next;
513 p.recycle();
514 p = n;
515 }
516 mMessages = null;
517 }
518
519 private void removeAllFutureMessagesLocked() {
520 final long now = SystemClock.uptimeMillis();
521 Message p = mMessages;
522 if (p != null) {
523 if (p.when > now) {
524 removeAllMessagesLocked();
525 } else {
526 Message n;
527 for (;;) {
528 n = p.next;
529 if (n == null) {
530 return;
531 }
532 if (n.when > now) {
533 break;
534 }
535 p = n;
536 }
537 p.next = null;
538 do {
539 p = n;
540 n = p.next;
541 p.recycle();
542 } while (n != null);
543 }
544 }
545 }
Jeff Brown5182c782013-10-15 20:31:52 -0700546
547 void dump(Printer pw, String prefix) {
548 synchronized (this) {
549 long now = SystemClock.uptimeMillis();
550 int n = 0;
551 for (Message msg = mMessages; msg != null; msg = msg.next) {
552 pw.println(prefix + "Message " + n + ": " + msg.toString(now));
553 n++;
554 }
555 pw.println(prefix + "(Total messages: " + n + ", idling=" + isIdlingLocked()
556 + ", quitting=" + mQuitting + ")");
557 }
558 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800559}