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
19803c2affcbe0a0e0fbb561967e0306bfc97ee197Jeff Brownimport android.annotation.NonNull;
20803c2affcbe0a0e0fbb561967e0306bfc97ee197Jeff Brownimport android.annotation.Nullable;
211b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrickimport android.util.Log;
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Printer;
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.
29803c2affcbe0a0e0fbb561967e0306bfc97ee197Jeff Brown  *
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  * <p>Most interaction with a message loop is through the
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  * {@link Handler} class.
32803c2affcbe0a0e0fbb561967e0306bfc97ee197Jeff Brown  *
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  */
5467fc67cf3e1dba17b0eae4f3923f3e93a78c7575Jeff Brownpublic final class Looper {
556c7b41adf9e937a66880b8906389760f3fc82a08Jeff Brown    /*
566c7b41adf9e937a66880b8906389760f3fc82a08Jeff Brown     * API Implementation Note:
576c7b41adf9e937a66880b8906389760f3fc82a08Jeff Brown     *
586c7b41adf9e937a66880b8906389760f3fc82a08Jeff Brown     * This class contains the code required to set up and manage an event loop
596c7b41adf9e937a66880b8906389760f3fc82a08Jeff Brown     * based on MessageQueue.  APIs that affect the state of the queue should be
606c7b41adf9e937a66880b8906389760f3fc82a08Jeff Brown     * defined on MessageQueue or Handler rather than on Looper itself.  For example,
616c7b41adf9e937a66880b8906389760f3fc82a08Jeff Brown     * idle handlers and sync barriers are defined on the queue whereas preparing the
62803c2affcbe0a0e0fbb561967e0306bfc97ee197Jeff Brown     * thread, looping, and quitting are defined on the looper.
636c7b41adf9e937a66880b8906389760f3fc82a08Jeff Brown     */
646c7b41adf9e937a66880b8906389760f3fc82a08Jeff Brown
651b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrick    private static final String TAG = "Looper";
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // sThreadLocal.get() will return null unless you've called prepare().
687f9f99ea11051614a7727dfb9f9578b518e76e3cXavier Ducrohet    static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
690f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown    private static Looper sMainLooper;  // guarded by Looper.class
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final MessageQueue mQueue;
721b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrick    final Thread mThread;
731b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrick
740f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown    private Printer mLogging;
7574cd3de6f4889d54a3da930de5e7ad00b97f03e9Jeff Sharkey    private long mTraceTag;
761b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrick
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     /** Initialize the current thread as a looper.
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project      * This gives you a chance to create handlers that then reference
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project      * this looper, before actually starting the loop. Be sure to call
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project      * {@link #loop()} after calling this method, and end it by calling
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project      * {@link #quit()}.
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project      */
83f9284695e8c10dad4daf3d2c84f607483bcb56caRomain Guy    public static void prepare() {
840f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown        prepare(true);
850f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown    }
860f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown
870f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown    private static void prepare(boolean quitAllowed) {
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (sThreadLocal.get() != null) {
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new RuntimeException("Only one Looper may be created per thread");
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
910f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown        sThreadLocal.set(new Looper(quitAllowed));
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
931b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrick
941b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrick    /**
951b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrick     * Initialize the current thread as a looper, marking it as an
961b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrick     * application's main looper. The main looper for your application
971b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrick     * is created by the Android environment, so you should never need
981b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrick     * to call this function yourself.  See also: {@link #prepare()}
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
100f9284695e8c10dad4daf3d2c84f607483bcb56caRomain Guy    public static void prepareMainLooper() {
1010f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown        prepare(false);
1020f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown        synchronized (Looper.class) {
1030f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown            if (sMainLooper != null) {
1040f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown                throw new IllegalStateException("The main Looper has already been prepared.");
1050f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown            }
1060f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown            sMainLooper = myLooper();
1070f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown        }
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1091b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrick
110803c2affcbe0a0e0fbb561967e0306bfc97ee197Jeff Brown    /**
111803c2affcbe0a0e0fbb561967e0306bfc97ee197Jeff Brown     * Returns the application's main looper, which lives in the main thread of the application.
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1130f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown    public static Looper getMainLooper() {
1140f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown        synchronized (Looper.class) {
1150f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown            return sMainLooper;
1160f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown        }
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1201b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrick     * Run the message queue in this thread. Be sure to call
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link #quit()} to end the loop.
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
123f9284695e8c10dad4daf3d2c84f607483bcb56caRomain Guy    public static void loop() {
1240f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown        final Looper me = myLooper();
1251b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrick        if (me == null) {
1261b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrick            throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
1271b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrick        }
1280f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown        final MessageQueue queue = me.mQueue;
1290f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown
130e5dea7537cadbf79614730f96d9e92cc2b12ad5aDianne Hackborn        // Make sure the identity of this thread is that of the local process,
131e5dea7537cadbf79614730f96d9e92cc2b12ad5aDianne Hackborn        // and keep track of what that identity token actually is.
132e5dea7537cadbf79614730f96d9e92cc2b12ad5aDianne Hackborn        Binder.clearCallingIdentity();
133e5dea7537cadbf79614730f96d9e92cc2b12ad5aDianne Hackborn        final long ident = Binder.clearCallingIdentity();
1340f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown
1350f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown        for (;;) {
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Message msg = queue.next(); // might block
1370f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown            if (msg == null) {
1380f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown                // No message indicates that the message queue is quitting.
1390f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown                return;
1400f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown            }
141f9284695e8c10dad4daf3d2c84f607483bcb56caRomain Guy
1420f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown            // This must be in a local variable, in case a UI event sets the logger
14374cd3de6f4889d54a3da930de5e7ad00b97f03e9Jeff Sharkey            final Printer logging = me.mLogging;
1440f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown            if (logging != null) {
1450f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown                logging.println(">>>>> Dispatching to " + msg.target + " " +
1460f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown                        msg.callback + ": " + msg.what);
1470f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown            }
148f9284695e8c10dad4daf3d2c84f607483bcb56caRomain Guy
14974cd3de6f4889d54a3da930de5e7ad00b97f03e9Jeff Sharkey            final long traceTag = me.mTraceTag;
15074cd3de6f4889d54a3da930de5e7ad00b97f03e9Jeff Sharkey            if (traceTag != 0) {
15174cd3de6f4889d54a3da930de5e7ad00b97f03e9Jeff Sharkey                Trace.traceBegin(traceTag, msg.target.getTraceName(msg));
15274cd3de6f4889d54a3da930de5e7ad00b97f03e9Jeff Sharkey            }
15374cd3de6f4889d54a3da930de5e7ad00b97f03e9Jeff Sharkey            try {
15474cd3de6f4889d54a3da930de5e7ad00b97f03e9Jeff Sharkey                msg.target.dispatchMessage(msg);
15574cd3de6f4889d54a3da930de5e7ad00b97f03e9Jeff Sharkey            } finally {
15674cd3de6f4889d54a3da930de5e7ad00b97f03e9Jeff Sharkey                if (traceTag != 0) {
15774cd3de6f4889d54a3da930de5e7ad00b97f03e9Jeff Sharkey                    Trace.traceEnd(traceTag);
15874cd3de6f4889d54a3da930de5e7ad00b97f03e9Jeff Sharkey                }
15974cd3de6f4889d54a3da930de5e7ad00b97f03e9Jeff Sharkey            }
160f9284695e8c10dad4daf3d2c84f607483bcb56caRomain Guy
1610f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown            if (logging != null) {
1620f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown                logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
1630f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown            }
164f9284695e8c10dad4daf3d2c84f607483bcb56caRomain Guy
1650f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown            // Make sure that during the course of dispatching the
1660f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown            // identity of the thread wasn't corrupted.
1670f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown            final long newIdent = Binder.clearCallingIdentity();
1680f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown            if (ident != newIdent) {
1690f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown                Log.wtf(TAG, "Thread identity changed from 0x"
1700f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown                        + Long.toHexString(ident) + " to 0x"
1710f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown                        + Long.toHexString(newIdent) + " while dispatching to "
1720f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown                        + msg.target.getClass().getName() + " "
1730f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown                        + msg.callback + " what=" + msg.what);
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1750f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown
1769867ed7aa98f5a719db4b50c39a290bc0ef38123Jeff Brown            msg.recycleUnchecked();
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Return the Looper object associated with the current thread.  Returns
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * null if the calling thread is not associated with a Looper.
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
184803c2affcbe0a0e0fbb561967e0306bfc97ee197Jeff Brown    public static @Nullable Looper myLooper() {
1851b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrick        return sThreadLocal.get();
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Return the {@link MessageQueue} object associated with the current
1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * thread.  This must be called from a thread running a Looper, or a
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * NullPointerException will be thrown.
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
193803c2affcbe0a0e0fbb561967e0306bfc97ee197Jeff Brown    public static @NonNull MessageQueue myQueue() {
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return myLooper().mQueue;
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1970f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown    private Looper(boolean quitAllowed) {
1980f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown        mQueue = new MessageQueue(quitAllowed);
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mThread = Thread.currentThread();
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2020f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown    /**
203f9e989d5f09e72f5c9a59d713521f37d3fdd93ddJeff Brown     * Returns true if the current thread is this looper's thread.
204f9e989d5f09e72f5c9a59d713521f37d3fdd93ddJeff Brown     */
205f9e989d5f09e72f5c9a59d713521f37d3fdd93ddJeff Brown    public boolean isCurrentThread() {
206f9e989d5f09e72f5c9a59d713521f37d3fdd93ddJeff Brown        return Thread.currentThread() == mThread;
207f9e989d5f09e72f5c9a59d713521f37d3fdd93ddJeff Brown    }
208f9e989d5f09e72f5c9a59d713521f37d3fdd93ddJeff Brown
209f9e989d5f09e72f5c9a59d713521f37d3fdd93ddJeff Brown    /**
210803c2affcbe0a0e0fbb561967e0306bfc97ee197Jeff Brown     * Control logging of messages as they are processed by this Looper.  If
211803c2affcbe0a0e0fbb561967e0306bfc97ee197Jeff Brown     * enabled, a log message will be written to <var>printer</var>
212803c2affcbe0a0e0fbb561967e0306bfc97ee197Jeff Brown     * at the beginning and ending of each message dispatch, identifying the
213803c2affcbe0a0e0fbb561967e0306bfc97ee197Jeff Brown     * target Handler and message contents.
214803c2affcbe0a0e0fbb561967e0306bfc97ee197Jeff Brown     *
215803c2affcbe0a0e0fbb561967e0306bfc97ee197Jeff Brown     * @param printer A Printer object that will receive log messages, or
216803c2affcbe0a0e0fbb561967e0306bfc97ee197Jeff Brown     * null to disable message logging.
217803c2affcbe0a0e0fbb561967e0306bfc97ee197Jeff Brown     */
218803c2affcbe0a0e0fbb561967e0306bfc97ee197Jeff Brown    public void setMessageLogging(@Nullable Printer printer) {
219803c2affcbe0a0e0fbb561967e0306bfc97ee197Jeff Brown        mLogging = printer;
220803c2affcbe0a0e0fbb561967e0306bfc97ee197Jeff Brown    }
221803c2affcbe0a0e0fbb561967e0306bfc97ee197Jeff Brown
22274cd3de6f4889d54a3da930de5e7ad00b97f03e9Jeff Sharkey    /** {@hide} */
22374cd3de6f4889d54a3da930de5e7ad00b97f03e9Jeff Sharkey    public void setTraceTag(long traceTag) {
22474cd3de6f4889d54a3da930de5e7ad00b97f03e9Jeff Sharkey        mTraceTag = traceTag;
22574cd3de6f4889d54a3da930de5e7ad00b97f03e9Jeff Sharkey    }
22674cd3de6f4889d54a3da930de5e7ad00b97f03e9Jeff Sharkey
227803c2affcbe0a0e0fbb561967e0306bfc97ee197Jeff Brown    /**
2280f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown     * Quits the looper.
229024136f57e5f8b4c11a4fe0fd83061eb6d372d26Jeff Brown     * <p>
2308b60e4514702edd1eb4b6f2bfc027e04a94369c0Jeff Brown     * Causes the {@link #loop} method to terminate without processing any
2318b60e4514702edd1eb4b6f2bfc027e04a94369c0Jeff Brown     * more messages in the message queue.
2328b60e4514702edd1eb4b6f2bfc027e04a94369c0Jeff Brown     * </p><p>
2338b60e4514702edd1eb4b6f2bfc027e04a94369c0Jeff Brown     * Any attempt to post messages to the queue after the looper is asked to quit will fail.
2348b60e4514702edd1eb4b6f2bfc027e04a94369c0Jeff Brown     * For example, the {@link Handler#sendMessage(Message)} method will return false.
2358b60e4514702edd1eb4b6f2bfc027e04a94369c0Jeff Brown     * </p><p class="note">
2368b60e4514702edd1eb4b6f2bfc027e04a94369c0Jeff Brown     * Using this method may be unsafe because some messages may not be delivered
2378b60e4514702edd1eb4b6f2bfc027e04a94369c0Jeff Brown     * before the looper terminates.  Consider using {@link #quitSafely} instead to ensure
2388b60e4514702edd1eb4b6f2bfc027e04a94369c0Jeff Brown     * that all pending work is completed in an orderly manner.
2398b60e4514702edd1eb4b6f2bfc027e04a94369c0Jeff Brown     * </p>
2408b60e4514702edd1eb4b6f2bfc027e04a94369c0Jeff Brown     *
2418b60e4514702edd1eb4b6f2bfc027e04a94369c0Jeff Brown     * @see #quitSafely
2428b60e4514702edd1eb4b6f2bfc027e04a94369c0Jeff Brown     */
2438b60e4514702edd1eb4b6f2bfc027e04a94369c0Jeff Brown    public void quit() {
2448b60e4514702edd1eb4b6f2bfc027e04a94369c0Jeff Brown        mQueue.quit(false);
2458b60e4514702edd1eb4b6f2bfc027e04a94369c0Jeff Brown    }
2468b60e4514702edd1eb4b6f2bfc027e04a94369c0Jeff Brown
2478b60e4514702edd1eb4b6f2bfc027e04a94369c0Jeff Brown    /**
2488b60e4514702edd1eb4b6f2bfc027e04a94369c0Jeff Brown     * Quits the looper safely.
2498b60e4514702edd1eb4b6f2bfc027e04a94369c0Jeff Brown     * <p>
250024136f57e5f8b4c11a4fe0fd83061eb6d372d26Jeff Brown     * Causes the {@link #loop} method to terminate as soon as all remaining messages
251024136f57e5f8b4c11a4fe0fd83061eb6d372d26Jeff Brown     * in the message queue that are already due to be delivered have been handled.
2528b60e4514702edd1eb4b6f2bfc027e04a94369c0Jeff Brown     * However pending delayed messages with due times in the future will not be
2538b60e4514702edd1eb4b6f2bfc027e04a94369c0Jeff Brown     * delivered before the loop terminates.
254024136f57e5f8b4c11a4fe0fd83061eb6d372d26Jeff Brown     * </p><p>
2558b60e4514702edd1eb4b6f2bfc027e04a94369c0Jeff Brown     * Any attempt to post messages to the queue after the looper is asked to quit will fail.
2568b60e4514702edd1eb4b6f2bfc027e04a94369c0Jeff Brown     * For example, the {@link Handler#sendMessage(Message)} method will return false.
257024136f57e5f8b4c11a4fe0fd83061eb6d372d26Jeff Brown     * </p>
2580f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown     */
2598b60e4514702edd1eb4b6f2bfc027e04a94369c0Jeff Brown    public void quitSafely() {
2608b60e4514702edd1eb4b6f2bfc027e04a94369c0Jeff Brown        mQueue.quit(true);
2610f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown    }
2620f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown
2630f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown    /**
264803c2affcbe0a0e0fbb561967e0306bfc97ee197Jeff Brown     * Gets the Thread associated with this Looper.
265803c2affcbe0a0e0fbb561967e0306bfc97ee197Jeff Brown     *
266803c2affcbe0a0e0fbb561967e0306bfc97ee197Jeff Brown     * @return The looper's thread.
2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
268803c2affcbe0a0e0fbb561967e0306bfc97ee197Jeff Brown    public @NonNull Thread getThread() {
2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mThread;
2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2711b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrick
272803c2affcbe0a0e0fbb561967e0306bfc97ee197Jeff Brown    /**
273803c2affcbe0a0e0fbb561967e0306bfc97ee197Jeff Brown     * Gets this looper's message queue.
274803c2affcbe0a0e0fbb561967e0306bfc97ee197Jeff Brown     *
275803c2affcbe0a0e0fbb561967e0306bfc97ee197Jeff Brown     * @return The looper's message queue.
276803c2affcbe0a0e0fbb561967e0306bfc97ee197Jeff Brown     */
277803c2affcbe0a0e0fbb561967e0306bfc97ee197Jeff Brown    public @NonNull MessageQueue getQueue() {
278a41ca77fabe1c7ad12ebb9b69b9e786c07d49fa0Jeff Brown        return mQueue;
279a41ca77fabe1c7ad12ebb9b69b9e786c07d49fa0Jeff Brown    }
2801b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrick
281803c2affcbe0a0e0fbb561967e0306bfc97ee197Jeff Brown    /**
282803c2affcbe0a0e0fbb561967e0306bfc97ee197Jeff Brown     * Dumps the state of the looper for debugging purposes.
283803c2affcbe0a0e0fbb561967e0306bfc97ee197Jeff Brown     *
284803c2affcbe0a0e0fbb561967e0306bfc97ee197Jeff Brown     * @param pw A printer to receive the contents of the dump.
285803c2affcbe0a0e0fbb561967e0306bfc97ee197Jeff Brown     * @param prefix A prefix to prepend to each line which is printed.
286803c2affcbe0a0e0fbb561967e0306bfc97ee197Jeff Brown     */
287803c2affcbe0a0e0fbb561967e0306bfc97ee197Jeff Brown    public void dump(@NonNull Printer pw, @NonNull String prefix) {
2885182c780a8b42acd46a06d693ab63a0dd78c6d70Jeff Brown        pw.println(prefix + toString());
2895182c780a8b42acd46a06d693ab63a0dd78c6d70Jeff Brown        mQueue.dump(pw, prefix + "  ");
2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
292dc3eb4bf91d37ce6b8b000a59625a496b64b36fbJeff Brown    @Override
2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public String toString() {
2945182c780a8b42acd46a06d693ab63a0dd78c6d70Jeff Brown        return "Looper (" + mThread.getName() + ", tid " + mThread.getId()
2955182c780a8b42acd46a06d693ab63a0dd78c6d70Jeff Brown                + ") {" + Integer.toHexString(System.identityHashCode(this)) + "}";
2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
298