Looper.java revision 1b29825cca9edda7ae4b3a3f27420c42fd13eef8
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2006 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.os;
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Config;
201b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrickimport android.util.Log;
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Printer;
221b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrickimport android.util.PrefixPrinter;
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  * Class used to run a message loop for a thread.  Threads by default do
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  * not have a message loop associated with them; to create one, call
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  * {@link #prepare} in the thread that is to run the loop, and then
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  * {@link #loop} to have it process messages until the loop is stopped.
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  *
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  * <p>Most interaction with a message loop is through the
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  * {@link Handler} class.
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  *
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  * <p>This is a typical example of the implementation of a Looper thread,
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  * using the separation of {@link #prepare} and {@link #loop} to create an
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  * initial Handler to communicate with the Looper.
361b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrick  *
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  * <pre>
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  *  class LooperThread extends Thread {
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  *      public Handler mHandler;
401b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrick  *
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  *      public void run() {
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  *          Looper.prepare();
431b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrick  *
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  *          mHandler = new Handler() {
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  *              public void handleMessage(Message msg) {
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  *                  // process incoming messages here
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  *              }
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  *          };
491b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrick  *
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  *          Looper.loop();
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  *      }
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  *  }</pre>
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  */
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class Looper {
551b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrick    private static final String TAG = "Looper";
561b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrick    private static final boolean LOG_V = Log.isLoggable(TAG, Log.VERBOSE);
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // sThreadLocal.get() will return null unless you've called prepare().
591b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrick    private static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final MessageQueue mQueue;
621b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrick    final Thread mThread;
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    volatile boolean mRun;
641b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrick
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Printer mLogging = null;
661b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrick    private static Looper mMainLooper = null;  // guarded by Looper.class
671b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrick
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     /** Initialize the current thread as a looper.
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project      * This gives you a chance to create handlers that then reference
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project      * this looper, before actually starting the loop. Be sure to call
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project      * {@link #loop()} after calling this method, and end it by calling
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project      * {@link #quit()}.
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project      */
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final void prepare() {
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (sThreadLocal.get() != null) {
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new RuntimeException("Only one Looper may be created per thread");
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        sThreadLocal.set(new Looper());
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
801b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrick
811b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrick    /**
821b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrick     * Initialize the current thread as a looper, marking it as an
831b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrick     * application's main looper. The main looper for your application
841b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrick     * is created by the Android environment, so you should never need
851b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrick     * to call this function yourself.  See also: {@link #prepare()}
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final void prepareMainLooper() {
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        prepare();
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        setMainLooper(myLooper());
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (Process.supportsProcesses()) {
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            myLooper().mQueue.mQuitAllowed = false;
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private synchronized static void setMainLooper(Looper looper) {
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mMainLooper = looper;
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
981b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrick
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** Returns the application's main looper, which lives in the main thread of the application.
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public synchronized static final Looper getMainLooper() {
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mMainLooper;
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1061b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrick     * Run the message queue in this thread. Be sure to call
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link #quit()} to end the loop.
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final void loop() {
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Looper me = myLooper();
1111b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrick        if (me == null) {
1121b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrick            throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
1131b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrick        }
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        MessageQueue queue = me.mQueue;
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        while (true) {
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Message msg = queue.next(); // might block
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (msg != null) {
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (msg.target == null) {
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // No target is a magic identifier for the quit message.
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    return;
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
1221b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrick                if (me.mLogging != null) me.mLogging.println(
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        ">>>>> Dispatching to " + msg.target + " "
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        + msg.callback + ": " + msg.what
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        );
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                msg.target.dispatchMessage(msg);
1271b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrick                if (me.mLogging != null) me.mLogging.println(
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        "<<<<< Finished to    " + msg.target + " "
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        + msg.callback);
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                msg.recycle();
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Return the Looper object associated with the current thread.  Returns
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * null if the calling thread is not associated with a Looper.
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final Looper myLooper() {
1401b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrick        return sThreadLocal.get();
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Control logging of messages as they are processed by this Looper.  If
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * enabled, a log message will be written to <var>printer</var>
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * at the beginning and ending of each message dispatch, identifying the
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * target Handler and message contents.
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param printer A Printer object that will receive log messages, or
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * null to disable message logging.
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setMessageLogging(Printer printer) {
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mLogging = printer;
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Return the {@link MessageQueue} object associated with the current
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * thread.  This must be called from a thread running a Looper, or a
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * NullPointerException will be thrown.
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final MessageQueue myQueue() {
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return myLooper().mQueue;
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Looper() {
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mQueue = new MessageQueue();
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mRun = true;
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mThread = Thread.currentThread();
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void quit() {
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Message msg = Message.obtain();
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // NOTE: By enqueueing directly into the message queue, the
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // message is left with a null target.  This is how we know it is
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // a quit message.
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mQueue.enqueueMessage(msg, 0);
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Return the Thread associated with this Looper.
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Thread getThread() {
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mThread;
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1851b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrick
186a41ca77fabe1c7ad12ebb9b69b9e786c07d49fa0Jeff Brown    /** @hide */
187a41ca77fabe1c7ad12ebb9b69b9e786c07d49fa0Jeff Brown    public MessageQueue getQueue() {
188a41ca77fabe1c7ad12ebb9b69b9e786c07d49fa0Jeff Brown        return mQueue;
189a41ca77fabe1c7ad12ebb9b69b9e786c07d49fa0Jeff Brown    }
1901b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrick
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void dump(Printer pw, String prefix) {
1921b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrick        pw = PrefixPrinter.create(pw, prefix);
1931b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrick        pw.println(this.toString());
1941b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrick        pw.println("mRun=" + mRun);
1951b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrick        pw.println("mThread=" + mThread);
1961b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrick        pw.println("mQueue=" + ((mQueue != null) ? mQueue : "(null"));
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mQueue != null) {
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized (mQueue) {
1991ebccf531d1049853b3b0630035434619682c016Dianne Hackborn                long now = SystemClock.uptimeMillis();
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Message msg = mQueue.mMessages;
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                int n = 0;
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                while (msg != null) {
2031b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrick                    pw.println("  Message " + n + ": " + msg.toString(now));
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    n++;
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    msg = msg.next;
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2071b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrick                pw.println("(Total messages: " + n + ")");
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public String toString() {
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return "Looper{"
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            + Integer.toHexString(System.identityHashCode(this))
2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            + "}";
2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static class HandlerException extends Exception {
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        HandlerException(Message message, Throwable cause) {
2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            super(createMessage(cause), cause);
2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        static String createMessage(Throwable cause) {
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String causeMsg = cause.getMessage();
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (causeMsg == null) {
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                causeMsg = cause.toString();
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return causeMsg;
2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
233