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
191b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrickimport android.util.Log;
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Printer;
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  * Class used to run a message loop for a thread.  Threads by default do
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  * not have a message loop associated with them; to create one, call
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  * {@link #prepare} in the thread that is to run the loop, and then
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  * {@link #loop} to have it process messages until the loop is stopped.
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  *
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  * <p>Most interaction with a message loop is through the
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  * {@link Handler} class.
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  *
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  * <p>This is a typical example of the implementation of a Looper thread,
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  * using the separation of {@link #prepare} and {@link #loop} to create an
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  * initial Handler to communicate with the Looper.
341b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrick  *
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  * <pre>
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  *  class LooperThread extends Thread {
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  *      public Handler mHandler;
381b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrick  *
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  *      public void run() {
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  *          Looper.prepare();
411b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrick  *
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  *          mHandler = new Handler() {
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  *              public void handleMessage(Message msg) {
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  *                  // process incoming messages here
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  *              }
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  *          };
471b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrick  *
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  *          Looper.loop();
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  *      }
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  *  }</pre>
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  */
5267fc67cf3e1dba17b0eae4f3923f3e93a78c7575Jeff Brownpublic final class Looper {
531b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrick    private static final String TAG = "Looper";
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // sThreadLocal.get() will return null unless you've called prepare().
567f9f99ea11051614a7727dfb9f9578b518e76e3cXavier Ducrohet    static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
570f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown    private static Looper sMainLooper;  // guarded by Looper.class
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final MessageQueue mQueue;
601b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrick    final Thread mThread;
611b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrick
620f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown    private Printer mLogging;
631b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrick
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     /** Initialize the current thread as a looper.
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project      * This gives you a chance to create handlers that then reference
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project      * this looper, before actually starting the loop. Be sure to call
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project      * {@link #loop()} after calling this method, and end it by calling
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project      * {@link #quit()}.
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project      */
70f9284695e8c10dad4daf3d2c84f607483bcb56caRomain Guy    public static void prepare() {
710f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown        prepare(true);
720f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown    }
730f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown
740f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown    private static void prepare(boolean quitAllowed) {
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        }
780f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown        sThreadLocal.set(new Looper(quitAllowed));
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     */
87f9284695e8c10dad4daf3d2c84f607483bcb56caRomain Guy    public static void prepareMainLooper() {
880f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown        prepare(false);
890f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown        synchronized (Looper.class) {
900f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown            if (sMainLooper != null) {
910f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown                throw new IllegalStateException("The main Looper has already been prepared.");
920f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown            }
930f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown            sMainLooper = myLooper();
940f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown        }
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
961b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrick
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** Returns the application's main looper, which lives in the main thread of the application.
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
990f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown    public static Looper getMainLooper() {
1000f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown        synchronized (Looper.class) {
1010f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown            return sMainLooper;
1020f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown        }
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     */
109f9284695e8c10dad4daf3d2c84f607483bcb56caRomain Guy    public static void loop() {
1100f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown        final 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        }
1140f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown        final MessageQueue queue = me.mQueue;
1150f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown
116e5dea7537cadbf79614730f96d9e92cc2b12ad5aDianne Hackborn        // Make sure the identity of this thread is that of the local process,
117e5dea7537cadbf79614730f96d9e92cc2b12ad5aDianne Hackborn        // and keep track of what that identity token actually is.
118e5dea7537cadbf79614730f96d9e92cc2b12ad5aDianne Hackborn        Binder.clearCallingIdentity();
119e5dea7537cadbf79614730f96d9e92cc2b12ad5aDianne Hackborn        final long ident = Binder.clearCallingIdentity();
1200f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown
1210f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown        for (;;) {
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Message msg = queue.next(); // might block
1230f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown            if (msg == null) {
1240f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown                // No message indicates that the message queue is quitting.
1250f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown                return;
1260f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown            }
127f9284695e8c10dad4daf3d2c84f607483bcb56caRomain Guy
1280f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown            // This must be in a local variable, in case a UI event sets the logger
1290f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown            Printer logging = me.mLogging;
1300f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown            if (logging != null) {
1310f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown                logging.println(">>>>> Dispatching to " + msg.target + " " +
1320f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown                        msg.callback + ": " + msg.what);
1330f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown            }
134f9284695e8c10dad4daf3d2c84f607483bcb56caRomain Guy
1350f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown            msg.target.dispatchMessage(msg);
136f9284695e8c10dad4daf3d2c84f607483bcb56caRomain Guy
1370f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown            if (logging != null) {
1380f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown                logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
1390f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown            }
140f9284695e8c10dad4daf3d2c84f607483bcb56caRomain Guy
1410f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown            // Make sure that during the course of dispatching the
1420f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown            // identity of the thread wasn't corrupted.
1430f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown            final long newIdent = Binder.clearCallingIdentity();
1440f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown            if (ident != newIdent) {
1450f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown                Log.wtf(TAG, "Thread identity changed from 0x"
1460f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown                        + Long.toHexString(ident) + " to 0x"
1470f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown                        + Long.toHexString(newIdent) + " while dispatching to "
1480f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown                        + msg.target.getClass().getName() + " "
1490f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown                        + msg.callback + " what=" + msg.what);
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1510f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown
1529867ed7aa98f5a719db4b50c39a290bc0ef38123Jeff Brown            msg.recycleUnchecked();
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Return the Looper object associated with the current thread.  Returns
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * null if the calling thread is not associated with a Looper.
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
160f9284695e8c10dad4daf3d2c84f607483bcb56caRomain Guy    public static Looper myLooper() {
1611b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrick        return sThreadLocal.get();
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Control logging of messages as they are processed by this Looper.  If
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * enabled, a log message will be written to <var>printer</var>
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * at the beginning and ending of each message dispatch, identifying the
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * target Handler and message contents.
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param printer A Printer object that will receive log messages, or
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * null to disable message logging.
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setMessageLogging(Printer printer) {
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mLogging = printer;
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Return the {@link MessageQueue} object associated with the current
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * thread.  This must be called from a thread running a Looper, or a
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * NullPointerException will be thrown.
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
182f9284695e8c10dad4daf3d2c84f607483bcb56caRomain Guy    public static MessageQueue myQueue() {
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return myLooper().mQueue;
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1860f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown    private Looper(boolean quitAllowed) {
1870f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown        mQueue = new MessageQueue(quitAllowed);
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mThread = Thread.currentThread();
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1910f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown    /**
192f9e989d5f09e72f5c9a59d713521f37d3fdd93ddJeff Brown     * Returns true if the current thread is this looper's thread.
193f9e989d5f09e72f5c9a59d713521f37d3fdd93ddJeff Brown     * @hide
194f9e989d5f09e72f5c9a59d713521f37d3fdd93ddJeff Brown     */
195f9e989d5f09e72f5c9a59d713521f37d3fdd93ddJeff Brown    public boolean isCurrentThread() {
196f9e989d5f09e72f5c9a59d713521f37d3fdd93ddJeff Brown        return Thread.currentThread() == mThread;
197f9e989d5f09e72f5c9a59d713521f37d3fdd93ddJeff Brown    }
198f9e989d5f09e72f5c9a59d713521f37d3fdd93ddJeff Brown
199f9e989d5f09e72f5c9a59d713521f37d3fdd93ddJeff Brown    /**
2000f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown     * Quits the looper.
201024136f57e5f8b4c11a4fe0fd83061eb6d372d26Jeff Brown     * <p>
2028b60e4514702edd1eb4b6f2bfc027e04a94369c0Jeff Brown     * Causes the {@link #loop} method to terminate without processing any
2038b60e4514702edd1eb4b6f2bfc027e04a94369c0Jeff Brown     * more messages in the message queue.
2048b60e4514702edd1eb4b6f2bfc027e04a94369c0Jeff Brown     * </p><p>
2058b60e4514702edd1eb4b6f2bfc027e04a94369c0Jeff Brown     * Any attempt to post messages to the queue after the looper is asked to quit will fail.
2068b60e4514702edd1eb4b6f2bfc027e04a94369c0Jeff Brown     * For example, the {@link Handler#sendMessage(Message)} method will return false.
2078b60e4514702edd1eb4b6f2bfc027e04a94369c0Jeff Brown     * </p><p class="note">
2088b60e4514702edd1eb4b6f2bfc027e04a94369c0Jeff Brown     * Using this method may be unsafe because some messages may not be delivered
2098b60e4514702edd1eb4b6f2bfc027e04a94369c0Jeff Brown     * before the looper terminates.  Consider using {@link #quitSafely} instead to ensure
2108b60e4514702edd1eb4b6f2bfc027e04a94369c0Jeff Brown     * that all pending work is completed in an orderly manner.
2118b60e4514702edd1eb4b6f2bfc027e04a94369c0Jeff Brown     * </p>
2128b60e4514702edd1eb4b6f2bfc027e04a94369c0Jeff Brown     *
2138b60e4514702edd1eb4b6f2bfc027e04a94369c0Jeff Brown     * @see #quitSafely
2148b60e4514702edd1eb4b6f2bfc027e04a94369c0Jeff Brown     */
2158b60e4514702edd1eb4b6f2bfc027e04a94369c0Jeff Brown    public void quit() {
2168b60e4514702edd1eb4b6f2bfc027e04a94369c0Jeff Brown        mQueue.quit(false);
2178b60e4514702edd1eb4b6f2bfc027e04a94369c0Jeff Brown    }
2188b60e4514702edd1eb4b6f2bfc027e04a94369c0Jeff Brown
2198b60e4514702edd1eb4b6f2bfc027e04a94369c0Jeff Brown    /**
2208b60e4514702edd1eb4b6f2bfc027e04a94369c0Jeff Brown     * Quits the looper safely.
2218b60e4514702edd1eb4b6f2bfc027e04a94369c0Jeff Brown     * <p>
222024136f57e5f8b4c11a4fe0fd83061eb6d372d26Jeff Brown     * Causes the {@link #loop} method to terminate as soon as all remaining messages
223024136f57e5f8b4c11a4fe0fd83061eb6d372d26Jeff Brown     * in the message queue that are already due to be delivered have been handled.
2248b60e4514702edd1eb4b6f2bfc027e04a94369c0Jeff Brown     * However pending delayed messages with due times in the future will not be
2258b60e4514702edd1eb4b6f2bfc027e04a94369c0Jeff Brown     * delivered before the loop terminates.
226024136f57e5f8b4c11a4fe0fd83061eb6d372d26Jeff Brown     * </p><p>
2278b60e4514702edd1eb4b6f2bfc027e04a94369c0Jeff Brown     * Any attempt to post messages to the queue after the looper is asked to quit will fail.
2288b60e4514702edd1eb4b6f2bfc027e04a94369c0Jeff Brown     * For example, the {@link Handler#sendMessage(Message)} method will return false.
229024136f57e5f8b4c11a4fe0fd83061eb6d372d26Jeff Brown     * </p>
2300f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown     */
2318b60e4514702edd1eb4b6f2bfc027e04a94369c0Jeff Brown    public void quitSafely() {
2328b60e4514702edd1eb4b6f2bfc027e04a94369c0Jeff Brown        mQueue.quit(true);
2330f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown    }
2340f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown
2350f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown    /**
2360f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown     * Posts a synchronization barrier to the Looper's message queue.
2370f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown     *
2380f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown     * Message processing occurs as usual until the message queue encounters the
2390f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown     * synchronization barrier that has been posted.  When the barrier is encountered,
2400f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown     * later synchronous messages in the queue are stalled (prevented from being executed)
2410f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown     * until the barrier is released by calling {@link #removeSyncBarrier} and specifying
2420f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown     * the token that identifies the synchronization barrier.
2430f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown     *
2440f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown     * This method is used to immediately postpone execution of all subsequently posted
2450f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown     * synchronous messages until a condition is met that releases the barrier.
2460f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown     * Asynchronous messages (see {@link Message#isAsynchronous} are exempt from the barrier
2470f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown     * and continue to be processed as usual.
2480f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown     *
2490f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown     * This call must be always matched by a call to {@link #removeSyncBarrier} with
2500f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown     * the same token to ensure that the message queue resumes normal operation.
2510f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown     * Otherwise the application will probably hang!
2520f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown     *
2530f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown     * @return A token that uniquely identifies the barrier.  This token must be
2540f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown     * passed to {@link #removeSyncBarrier} to release the barrier.
2550f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown     *
2560f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown     * @hide
2570f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown     */
25867fc67cf3e1dba17b0eae4f3923f3e93a78c7575Jeff Brown    public int postSyncBarrier() {
2590f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown        return mQueue.enqueueSyncBarrier(SystemClock.uptimeMillis());
2600f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown    }
2610f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown
2620f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown
2630f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown    /**
2640f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown     * Removes a synchronization barrier.
2650f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown     *
2660f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown     * @param token The synchronization barrier token that was returned by
2670f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown     * {@link #postSyncBarrier}.
2680f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown     *
2690f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown     * @throws IllegalStateException if the barrier was not found.
2700f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown     *
2710f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown     * @hide
2720f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown     */
27367fc67cf3e1dba17b0eae4f3923f3e93a78c7575Jeff Brown    public void removeSyncBarrier(int token) {
2740f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown        mQueue.removeSyncBarrier(token);
2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Return the Thread associated with this Looper.
2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Thread getThread() {
2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mThread;
2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2831b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrick
284a41ca77fabe1c7ad12ebb9b69b9e786c07d49fa0Jeff Brown    /** @hide */
285a41ca77fabe1c7ad12ebb9b69b9e786c07d49fa0Jeff Brown    public MessageQueue getQueue() {
286a41ca77fabe1c7ad12ebb9b69b9e786c07d49fa0Jeff Brown        return mQueue;
287a41ca77fabe1c7ad12ebb9b69b9e786c07d49fa0Jeff Brown    }
2881b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrick
289efa92b2182ab581873aa8e75d596e2e363bd5e6dDianne Hackborn    /**
290efa92b2182ab581873aa8e75d596e2e363bd5e6dDianne Hackborn     * Return whether this looper's thread is currently idle, waiting for new work
291efa92b2182ab581873aa8e75d596e2e363bd5e6dDianne Hackborn     * to do.  This is intrinsically racy, since its state can change before you get
292efa92b2182ab581873aa8e75d596e2e363bd5e6dDianne Hackborn     * the result back.
293efa92b2182ab581873aa8e75d596e2e363bd5e6dDianne Hackborn     * @hide
294efa92b2182ab581873aa8e75d596e2e363bd5e6dDianne Hackborn     */
295efa92b2182ab581873aa8e75d596e2e363bd5e6dDianne Hackborn    public boolean isIdling() {
296efa92b2182ab581873aa8e75d596e2e363bd5e6dDianne Hackborn        return mQueue.isIdling();
297efa92b2182ab581873aa8e75d596e2e363bd5e6dDianne Hackborn    }
298efa92b2182ab581873aa8e75d596e2e363bd5e6dDianne Hackborn
2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void dump(Printer pw, String prefix) {
3005182c780a8b42acd46a06d693ab63a0dd78c6d70Jeff Brown        pw.println(prefix + toString());
3015182c780a8b42acd46a06d693ab63a0dd78c6d70Jeff Brown        mQueue.dump(pw, prefix + "  ");
3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public String toString() {
3055182c780a8b42acd46a06d693ab63a0dd78c6d70Jeff Brown        return "Looper (" + mThread.getName() + ", tid " + mThread.getId()
3065182c780a8b42acd46a06d693ab63a0dd78c6d70Jeff Brown                + ") {" + Integer.toHexString(System.identityHashCode(this)) + "}";
3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
309