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;
21958d0a503699840f8f4b85cafa62f3793c89ac73Netta Pimport android.os.LooperProto;
221b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrickimport android.util.Log;
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Printer;
249957151661b8ae65da45a1fb72df5b66176302cbMakoto Onukiimport android.util.Slog;
25958d0a503699840f8f4b85cafa62f3793c89ac73Netta Pimport android.util.proto.ProtoOutputStream;
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  * Class used to run a message loop for a thread.  Threads by default do
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  * not have a message loop associated with them; to create one, call
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  * {@link #prepare} in the thread that is to run the loop, and then
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  * {@link #loop} to have it process messages until the loop is stopped.
32803c2affcbe0a0e0fbb561967e0306bfc97ee197Jeff Brown  *
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  * <p>Most interaction with a message loop is through the
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  * {@link Handler} class.
35803c2affcbe0a0e0fbb561967e0306bfc97ee197Jeff Brown  *
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  * <p>This is a typical example of the implementation of a Looper thread,
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  * using the separation of {@link #prepare} and {@link #loop} to create an
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  * initial Handler to communicate with the Looper.
391b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrick  *
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  * <pre>
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  *  class LooperThread extends Thread {
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  *      public Handler mHandler;
431b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrick  *
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  *      public void run() {
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  *          Looper.prepare();
461b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrick  *
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  *          mHandler = new Handler() {
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  *              public void handleMessage(Message msg) {
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  *                  // process incoming messages here
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  *              }
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  *          };
521b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrick  *
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  *          Looper.loop();
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  *      }
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  *  }</pre>
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  */
5767fc67cf3e1dba17b0eae4f3923f3e93a78c7575Jeff Brownpublic final class Looper {
586c7b41adf9e937a66880b8906389760f3fc82a08Jeff Brown    /*
596c7b41adf9e937a66880b8906389760f3fc82a08Jeff Brown     * API Implementation Note:
606c7b41adf9e937a66880b8906389760f3fc82a08Jeff Brown     *
616c7b41adf9e937a66880b8906389760f3fc82a08Jeff Brown     * This class contains the code required to set up and manage an event loop
626c7b41adf9e937a66880b8906389760f3fc82a08Jeff Brown     * based on MessageQueue.  APIs that affect the state of the queue should be
636c7b41adf9e937a66880b8906389760f3fc82a08Jeff Brown     * defined on MessageQueue or Handler rather than on Looper itself.  For example,
646c7b41adf9e937a66880b8906389760f3fc82a08Jeff Brown     * idle handlers and sync barriers are defined on the queue whereas preparing the
65803c2affcbe0a0e0fbb561967e0306bfc97ee197Jeff Brown     * thread, looping, and quitting are defined on the looper.
666c7b41adf9e937a66880b8906389760f3fc82a08Jeff Brown     */
676c7b41adf9e937a66880b8906389760f3fc82a08Jeff Brown
681b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrick    private static final String TAG = "Looper";
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // sThreadLocal.get() will return null unless you've called prepare().
717f9f99ea11051614a7727dfb9f9578b518e76e3cXavier Ducrohet    static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
720f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown    private static Looper sMainLooper;  // guarded by Looper.class
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final MessageQueue mQueue;
751b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrick    final Thread mThread;
761b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrick
770f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown    private Printer mLogging;
7874cd3de6f4889d54a3da930de5e7ad00b97f03e9Jeff Sharkey    private long mTraceTag;
791b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrick
80712886fd979f58b0de7cefc3bce885ad7f4493b6Makoto Onuki    /**
81712886fd979f58b0de7cefc3bce885ad7f4493b6Makoto Onuki     * If set, the looper will show a warning log if a message dispatch takes longer than this.
82712886fd979f58b0de7cefc3bce885ad7f4493b6Makoto Onuki     */
839957151661b8ae65da45a1fb72df5b66176302cbMakoto Onuki    private long mSlowDispatchThresholdMs;
849957151661b8ae65da45a1fb72df5b66176302cbMakoto Onuki
85712886fd979f58b0de7cefc3bce885ad7f4493b6Makoto Onuki    /**
86712886fd979f58b0de7cefc3bce885ad7f4493b6Makoto Onuki     * If set, the looper will show a warning log if a message delivery (actual delivery time -
87712886fd979f58b0de7cefc3bce885ad7f4493b6Makoto Onuki     * post time) takes longer than this.
88712886fd979f58b0de7cefc3bce885ad7f4493b6Makoto Onuki     */
89712886fd979f58b0de7cefc3bce885ad7f4493b6Makoto Onuki    private long mSlowDeliveryThresholdMs;
90712886fd979f58b0de7cefc3bce885ad7f4493b6Makoto Onuki
91712886fd979f58b0de7cefc3bce885ad7f4493b6Makoto Onuki    /** Initialize the current thread as a looper.
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project      * This gives you a chance to create handlers that then reference
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project      * this looper, before actually starting the loop. Be sure to call
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project      * {@link #loop()} after calling this method, and end it by calling
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project      * {@link #quit()}.
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project      */
97f9284695e8c10dad4daf3d2c84f607483bcb56caRomain Guy    public static void prepare() {
980f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown        prepare(true);
990f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown    }
1000f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown
1010f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown    private static void prepare(boolean quitAllowed) {
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (sThreadLocal.get() != null) {
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new RuntimeException("Only one Looper may be created per thread");
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1050f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown        sThreadLocal.set(new Looper(quitAllowed));
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1071b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrick
1081b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrick    /**
1091b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrick     * Initialize the current thread as a looper, marking it as an
1101b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrick     * application's main looper. The main looper for your application
1111b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrick     * is created by the Android environment, so you should never need
1121b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrick     * to call this function yourself.  See also: {@link #prepare()}
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
114f9284695e8c10dad4daf3d2c84f607483bcb56caRomain Guy    public static void prepareMainLooper() {
1150f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown        prepare(false);
1160f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown        synchronized (Looper.class) {
1170f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown            if (sMainLooper != null) {
1180f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown                throw new IllegalStateException("The main Looper has already been prepared.");
1190f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown            }
1200f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown            sMainLooper = myLooper();
1210f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown        }
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1231b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrick
124803c2affcbe0a0e0fbb561967e0306bfc97ee197Jeff Brown    /**
125803c2affcbe0a0e0fbb561967e0306bfc97ee197Jeff Brown     * Returns the application's main looper, which lives in the main thread of the application.
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1270f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown    public static Looper getMainLooper() {
1280f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown        synchronized (Looper.class) {
1290f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown            return sMainLooper;
1300f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown        }
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1341b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrick     * Run the message queue in this thread. Be sure to call
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link #quit()} to end the loop.
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
137f9284695e8c10dad4daf3d2c84f607483bcb56caRomain Guy    public static void loop() {
1380f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown        final Looper me = myLooper();
1391b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrick        if (me == null) {
1401b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrick            throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
1411b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrick        }
1420f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown        final MessageQueue queue = me.mQueue;
1430f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown
144e5dea7537cadbf79614730f96d9e92cc2b12ad5aDianne Hackborn        // Make sure the identity of this thread is that of the local process,
145e5dea7537cadbf79614730f96d9e92cc2b12ad5aDianne Hackborn        // and keep track of what that identity token actually is.
146e5dea7537cadbf79614730f96d9e92cc2b12ad5aDianne Hackborn        Binder.clearCallingIdentity();
147e5dea7537cadbf79614730f96d9e92cc2b12ad5aDianne Hackborn        final long ident = Binder.clearCallingIdentity();
1480f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown
149712886fd979f58b0de7cefc3bce885ad7f4493b6Makoto Onuki        // Allow overriding a threshold with a system prop. e.g.
150712886fd979f58b0de7cefc3bce885ad7f4493b6Makoto Onuki        // adb shell 'setprop log.looper.1000.main.slow 1 && stop && start'
151712886fd979f58b0de7cefc3bce885ad7f4493b6Makoto Onuki        final int thresholdOverride =
152712886fd979f58b0de7cefc3bce885ad7f4493b6Makoto Onuki                SystemProperties.getInt("log.looper."
153712886fd979f58b0de7cefc3bce885ad7f4493b6Makoto Onuki                        + Process.myUid() + "."
154712886fd979f58b0de7cefc3bce885ad7f4493b6Makoto Onuki                        + Thread.currentThread().getName()
155712886fd979f58b0de7cefc3bce885ad7f4493b6Makoto Onuki                        + ".slow", 0);
156712886fd979f58b0de7cefc3bce885ad7f4493b6Makoto Onuki
157712886fd979f58b0de7cefc3bce885ad7f4493b6Makoto Onuki        boolean slowDeliveryDetected = false;
158712886fd979f58b0de7cefc3bce885ad7f4493b6Makoto Onuki
1590f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown        for (;;) {
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Message msg = queue.next(); // might block
1610f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown            if (msg == null) {
1620f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown                // No message indicates that the message queue is quitting.
1630f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown                return;
1640f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown            }
165f9284695e8c10dad4daf3d2c84f607483bcb56caRomain Guy
1660f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown            // This must be in a local variable, in case a UI event sets the logger
16774cd3de6f4889d54a3da930de5e7ad00b97f03e9Jeff Sharkey            final Printer logging = me.mLogging;
1680f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown            if (logging != null) {
1690f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown                logging.println(">>>>> Dispatching to " + msg.target + " " +
1700f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown                        msg.callback + ": " + msg.what);
1710f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown            }
172f9284695e8c10dad4daf3d2c84f607483bcb56caRomain Guy
17374cd3de6f4889d54a3da930de5e7ad00b97f03e9Jeff Sharkey            final long traceTag = me.mTraceTag;
174712886fd979f58b0de7cefc3bce885ad7f4493b6Makoto Onuki            long slowDispatchThresholdMs = me.mSlowDispatchThresholdMs;
175712886fd979f58b0de7cefc3bce885ad7f4493b6Makoto Onuki            long slowDeliveryThresholdMs = me.mSlowDeliveryThresholdMs;
176712886fd979f58b0de7cefc3bce885ad7f4493b6Makoto Onuki            if (thresholdOverride > 0) {
177712886fd979f58b0de7cefc3bce885ad7f4493b6Makoto Onuki                slowDispatchThresholdMs = thresholdOverride;
178712886fd979f58b0de7cefc3bce885ad7f4493b6Makoto Onuki                slowDeliveryThresholdMs = thresholdOverride;
179712886fd979f58b0de7cefc3bce885ad7f4493b6Makoto Onuki            }
180712886fd979f58b0de7cefc3bce885ad7f4493b6Makoto Onuki            final boolean logSlowDelivery = (slowDeliveryThresholdMs > 0) && (msg.when > 0);
181712886fd979f58b0de7cefc3bce885ad7f4493b6Makoto Onuki            final boolean logSlowDispatch = (slowDispatchThresholdMs > 0);
182712886fd979f58b0de7cefc3bce885ad7f4493b6Makoto Onuki
183712886fd979f58b0de7cefc3bce885ad7f4493b6Makoto Onuki            final boolean needStartTime = logSlowDelivery || logSlowDispatch;
184712886fd979f58b0de7cefc3bce885ad7f4493b6Makoto Onuki            final boolean needEndTime = logSlowDispatch;
185712886fd979f58b0de7cefc3bce885ad7f4493b6Makoto Onuki
186407c0be727bb77360494f8cbc5aa879515e15484Jorim Jaggi            if (traceTag != 0 && Trace.isTagEnabled(traceTag)) {
18774cd3de6f4889d54a3da930de5e7ad00b97f03e9Jeff Sharkey                Trace.traceBegin(traceTag, msg.target.getTraceName(msg));
18874cd3de6f4889d54a3da930de5e7ad00b97f03e9Jeff Sharkey            }
189712886fd979f58b0de7cefc3bce885ad7f4493b6Makoto Onuki
190712886fd979f58b0de7cefc3bce885ad7f4493b6Makoto Onuki            final long dispatchStart = needStartTime ? SystemClock.uptimeMillis() : 0;
191712886fd979f58b0de7cefc3bce885ad7f4493b6Makoto Onuki            final long dispatchEnd;
19274cd3de6f4889d54a3da930de5e7ad00b97f03e9Jeff Sharkey            try {
19374cd3de6f4889d54a3da930de5e7ad00b97f03e9Jeff Sharkey                msg.target.dispatchMessage(msg);
194712886fd979f58b0de7cefc3bce885ad7f4493b6Makoto Onuki                dispatchEnd = needEndTime ? SystemClock.uptimeMillis() : 0;
19574cd3de6f4889d54a3da930de5e7ad00b97f03e9Jeff Sharkey            } finally {
19674cd3de6f4889d54a3da930de5e7ad00b97f03e9Jeff Sharkey                if (traceTag != 0) {
19774cd3de6f4889d54a3da930de5e7ad00b97f03e9Jeff Sharkey                    Trace.traceEnd(traceTag);
19874cd3de6f4889d54a3da930de5e7ad00b97f03e9Jeff Sharkey                }
19974cd3de6f4889d54a3da930de5e7ad00b97f03e9Jeff Sharkey            }
200712886fd979f58b0de7cefc3bce885ad7f4493b6Makoto Onuki            if (logSlowDelivery) {
201712886fd979f58b0de7cefc3bce885ad7f4493b6Makoto Onuki                if (slowDeliveryDetected) {
202712886fd979f58b0de7cefc3bce885ad7f4493b6Makoto Onuki                    if ((dispatchStart - msg.when) <= 10) {
203712886fd979f58b0de7cefc3bce885ad7f4493b6Makoto Onuki                        Slog.w(TAG, "Drained");
204712886fd979f58b0de7cefc3bce885ad7f4493b6Makoto Onuki                        slowDeliveryDetected = false;
205712886fd979f58b0de7cefc3bce885ad7f4493b6Makoto Onuki                    }
206712886fd979f58b0de7cefc3bce885ad7f4493b6Makoto Onuki                } else {
207712886fd979f58b0de7cefc3bce885ad7f4493b6Makoto Onuki                    if (showSlowLog(slowDeliveryThresholdMs, msg.when, dispatchStart, "delivery",
208712886fd979f58b0de7cefc3bce885ad7f4493b6Makoto Onuki                            msg)) {
209712886fd979f58b0de7cefc3bce885ad7f4493b6Makoto Onuki                        // Once we write a slow delivery log, suppress until the queue drains.
210712886fd979f58b0de7cefc3bce885ad7f4493b6Makoto Onuki                        slowDeliveryDetected = true;
211712886fd979f58b0de7cefc3bce885ad7f4493b6Makoto Onuki                    }
2129957151661b8ae65da45a1fb72df5b66176302cbMakoto Onuki                }
2139957151661b8ae65da45a1fb72df5b66176302cbMakoto Onuki            }
214712886fd979f58b0de7cefc3bce885ad7f4493b6Makoto Onuki            if (logSlowDispatch) {
215712886fd979f58b0de7cefc3bce885ad7f4493b6Makoto Onuki                showSlowLog(slowDispatchThresholdMs, dispatchStart, dispatchEnd, "dispatch", msg);
216712886fd979f58b0de7cefc3bce885ad7f4493b6Makoto Onuki            }
217f9284695e8c10dad4daf3d2c84f607483bcb56caRomain Guy
2180f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown            if (logging != null) {
2190f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown                logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
2200f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown            }
221f9284695e8c10dad4daf3d2c84f607483bcb56caRomain Guy
2220f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown            // Make sure that during the course of dispatching the
2230f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown            // identity of the thread wasn't corrupted.
2240f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown            final long newIdent = Binder.clearCallingIdentity();
2250f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown            if (ident != newIdent) {
2260f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown                Log.wtf(TAG, "Thread identity changed from 0x"
2270f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown                        + Long.toHexString(ident) + " to 0x"
2280f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown                        + Long.toHexString(newIdent) + " while dispatching to "
2290f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown                        + msg.target.getClass().getName() + " "
2300f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown                        + msg.callback + " what=" + msg.what);
2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2320f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown
2339867ed7aa98f5a719db4b50c39a290bc0ef38123Jeff Brown            msg.recycleUnchecked();
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
237712886fd979f58b0de7cefc3bce885ad7f4493b6Makoto Onuki    private static boolean showSlowLog(long threshold, long measureStart, long measureEnd,
238712886fd979f58b0de7cefc3bce885ad7f4493b6Makoto Onuki            String what, Message msg) {
239712886fd979f58b0de7cefc3bce885ad7f4493b6Makoto Onuki        final long actualTime = measureEnd - measureStart;
240712886fd979f58b0de7cefc3bce885ad7f4493b6Makoto Onuki        if (actualTime < threshold) {
241712886fd979f58b0de7cefc3bce885ad7f4493b6Makoto Onuki            return false;
242712886fd979f58b0de7cefc3bce885ad7f4493b6Makoto Onuki        }
243712886fd979f58b0de7cefc3bce885ad7f4493b6Makoto Onuki        // For slow delivery, the current message isn't really important, but log it anyway.
244712886fd979f58b0de7cefc3bce885ad7f4493b6Makoto Onuki        Slog.w(TAG, "Slow " + what + " took " + actualTime + "ms "
245712886fd979f58b0de7cefc3bce885ad7f4493b6Makoto Onuki                + Thread.currentThread().getName() + " h="
246712886fd979f58b0de7cefc3bce885ad7f4493b6Makoto Onuki                + msg.target.getClass().getName() + " c=" + msg.callback + " m=" + msg.what);
247712886fd979f58b0de7cefc3bce885ad7f4493b6Makoto Onuki        return true;
248712886fd979f58b0de7cefc3bce885ad7f4493b6Makoto Onuki    }
249712886fd979f58b0de7cefc3bce885ad7f4493b6Makoto Onuki
2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Return the Looper object associated with the current thread.  Returns
2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * null if the calling thread is not associated with a Looper.
2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
254803c2affcbe0a0e0fbb561967e0306bfc97ee197Jeff Brown    public static @Nullable Looper myLooper() {
2551b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrick        return sThreadLocal.get();
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Return the {@link MessageQueue} object associated with the current
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * thread.  This must be called from a thread running a Looper, or a
2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * NullPointerException will be thrown.
2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
263803c2affcbe0a0e0fbb561967e0306bfc97ee197Jeff Brown    public static @NonNull MessageQueue myQueue() {
2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return myLooper().mQueue;
2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2670f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown    private Looper(boolean quitAllowed) {
2680f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown        mQueue = new MessageQueue(quitAllowed);
2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mThread = Thread.currentThread();
2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2720f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown    /**
273f9e989d5f09e72f5c9a59d713521f37d3fdd93ddJeff Brown     * Returns true if the current thread is this looper's thread.
274f9e989d5f09e72f5c9a59d713521f37d3fdd93ddJeff Brown     */
275f9e989d5f09e72f5c9a59d713521f37d3fdd93ddJeff Brown    public boolean isCurrentThread() {
276f9e989d5f09e72f5c9a59d713521f37d3fdd93ddJeff Brown        return Thread.currentThread() == mThread;
277f9e989d5f09e72f5c9a59d713521f37d3fdd93ddJeff Brown    }
278f9e989d5f09e72f5c9a59d713521f37d3fdd93ddJeff Brown
279f9e989d5f09e72f5c9a59d713521f37d3fdd93ddJeff Brown    /**
280803c2affcbe0a0e0fbb561967e0306bfc97ee197Jeff Brown     * Control logging of messages as they are processed by this Looper.  If
281803c2affcbe0a0e0fbb561967e0306bfc97ee197Jeff Brown     * enabled, a log message will be written to <var>printer</var>
282803c2affcbe0a0e0fbb561967e0306bfc97ee197Jeff Brown     * at the beginning and ending of each message dispatch, identifying the
283803c2affcbe0a0e0fbb561967e0306bfc97ee197Jeff Brown     * target Handler and message contents.
284803c2affcbe0a0e0fbb561967e0306bfc97ee197Jeff Brown     *
285803c2affcbe0a0e0fbb561967e0306bfc97ee197Jeff Brown     * @param printer A Printer object that will receive log messages, or
286803c2affcbe0a0e0fbb561967e0306bfc97ee197Jeff Brown     * null to disable message logging.
287803c2affcbe0a0e0fbb561967e0306bfc97ee197Jeff Brown     */
288803c2affcbe0a0e0fbb561967e0306bfc97ee197Jeff Brown    public void setMessageLogging(@Nullable Printer printer) {
289803c2affcbe0a0e0fbb561967e0306bfc97ee197Jeff Brown        mLogging = printer;
290803c2affcbe0a0e0fbb561967e0306bfc97ee197Jeff Brown    }
291803c2affcbe0a0e0fbb561967e0306bfc97ee197Jeff Brown
29274cd3de6f4889d54a3da930de5e7ad00b97f03e9Jeff Sharkey    /** {@hide} */
29374cd3de6f4889d54a3da930de5e7ad00b97f03e9Jeff Sharkey    public void setTraceTag(long traceTag) {
29474cd3de6f4889d54a3da930de5e7ad00b97f03e9Jeff Sharkey        mTraceTag = traceTag;
29574cd3de6f4889d54a3da930de5e7ad00b97f03e9Jeff Sharkey    }
29674cd3de6f4889d54a3da930de5e7ad00b97f03e9Jeff Sharkey
297712886fd979f58b0de7cefc3bce885ad7f4493b6Makoto Onuki    /**
298712886fd979f58b0de7cefc3bce885ad7f4493b6Makoto Onuki     * Set a thresholds for slow dispatch/delivery log.
299712886fd979f58b0de7cefc3bce885ad7f4493b6Makoto Onuki     * {@hide}
300712886fd979f58b0de7cefc3bce885ad7f4493b6Makoto Onuki     */
301712886fd979f58b0de7cefc3bce885ad7f4493b6Makoto Onuki    public void setSlowLogThresholdMs(long slowDispatchThresholdMs, long slowDeliveryThresholdMs) {
3029957151661b8ae65da45a1fb72df5b66176302cbMakoto Onuki        mSlowDispatchThresholdMs = slowDispatchThresholdMs;
303712886fd979f58b0de7cefc3bce885ad7f4493b6Makoto Onuki        mSlowDeliveryThresholdMs = slowDeliveryThresholdMs;
3049957151661b8ae65da45a1fb72df5b66176302cbMakoto Onuki    }
3059957151661b8ae65da45a1fb72df5b66176302cbMakoto Onuki
306803c2affcbe0a0e0fbb561967e0306bfc97ee197Jeff Brown    /**
3070f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown     * Quits the looper.
308024136f57e5f8b4c11a4fe0fd83061eb6d372d26Jeff Brown     * <p>
3098b60e4514702edd1eb4b6f2bfc027e04a94369c0Jeff Brown     * Causes the {@link #loop} method to terminate without processing any
3108b60e4514702edd1eb4b6f2bfc027e04a94369c0Jeff Brown     * more messages in the message queue.
3118b60e4514702edd1eb4b6f2bfc027e04a94369c0Jeff Brown     * </p><p>
3128b60e4514702edd1eb4b6f2bfc027e04a94369c0Jeff Brown     * Any attempt to post messages to the queue after the looper is asked to quit will fail.
3138b60e4514702edd1eb4b6f2bfc027e04a94369c0Jeff Brown     * For example, the {@link Handler#sendMessage(Message)} method will return false.
3148b60e4514702edd1eb4b6f2bfc027e04a94369c0Jeff Brown     * </p><p class="note">
3158b60e4514702edd1eb4b6f2bfc027e04a94369c0Jeff Brown     * Using this method may be unsafe because some messages may not be delivered
3168b60e4514702edd1eb4b6f2bfc027e04a94369c0Jeff Brown     * before the looper terminates.  Consider using {@link #quitSafely} instead to ensure
3178b60e4514702edd1eb4b6f2bfc027e04a94369c0Jeff Brown     * that all pending work is completed in an orderly manner.
3188b60e4514702edd1eb4b6f2bfc027e04a94369c0Jeff Brown     * </p>
3198b60e4514702edd1eb4b6f2bfc027e04a94369c0Jeff Brown     *
3208b60e4514702edd1eb4b6f2bfc027e04a94369c0Jeff Brown     * @see #quitSafely
3218b60e4514702edd1eb4b6f2bfc027e04a94369c0Jeff Brown     */
3228b60e4514702edd1eb4b6f2bfc027e04a94369c0Jeff Brown    public void quit() {
3238b60e4514702edd1eb4b6f2bfc027e04a94369c0Jeff Brown        mQueue.quit(false);
3248b60e4514702edd1eb4b6f2bfc027e04a94369c0Jeff Brown    }
3258b60e4514702edd1eb4b6f2bfc027e04a94369c0Jeff Brown
3268b60e4514702edd1eb4b6f2bfc027e04a94369c0Jeff Brown    /**
3278b60e4514702edd1eb4b6f2bfc027e04a94369c0Jeff Brown     * Quits the looper safely.
3288b60e4514702edd1eb4b6f2bfc027e04a94369c0Jeff Brown     * <p>
329024136f57e5f8b4c11a4fe0fd83061eb6d372d26Jeff Brown     * Causes the {@link #loop} method to terminate as soon as all remaining messages
330024136f57e5f8b4c11a4fe0fd83061eb6d372d26Jeff Brown     * in the message queue that are already due to be delivered have been handled.
3318b60e4514702edd1eb4b6f2bfc027e04a94369c0Jeff Brown     * However pending delayed messages with due times in the future will not be
3328b60e4514702edd1eb4b6f2bfc027e04a94369c0Jeff Brown     * delivered before the loop terminates.
333024136f57e5f8b4c11a4fe0fd83061eb6d372d26Jeff Brown     * </p><p>
3348b60e4514702edd1eb4b6f2bfc027e04a94369c0Jeff Brown     * Any attempt to post messages to the queue after the looper is asked to quit will fail.
3358b60e4514702edd1eb4b6f2bfc027e04a94369c0Jeff Brown     * For example, the {@link Handler#sendMessage(Message)} method will return false.
336024136f57e5f8b4c11a4fe0fd83061eb6d372d26Jeff Brown     * </p>
3370f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown     */
3388b60e4514702edd1eb4b6f2bfc027e04a94369c0Jeff Brown    public void quitSafely() {
3398b60e4514702edd1eb4b6f2bfc027e04a94369c0Jeff Brown        mQueue.quit(true);
3400f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown    }
3410f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown
3420f85ce3837633a03460a61405087a5d28a4bf955Jeff Brown    /**
343803c2affcbe0a0e0fbb561967e0306bfc97ee197Jeff Brown     * Gets the Thread associated with this Looper.
344803c2affcbe0a0e0fbb561967e0306bfc97ee197Jeff Brown     *
345803c2affcbe0a0e0fbb561967e0306bfc97ee197Jeff Brown     * @return The looper's thread.
3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
347803c2affcbe0a0e0fbb561967e0306bfc97ee197Jeff Brown    public @NonNull Thread getThread() {
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mThread;
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3501b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrick
351803c2affcbe0a0e0fbb561967e0306bfc97ee197Jeff Brown    /**
352803c2affcbe0a0e0fbb561967e0306bfc97ee197Jeff Brown     * Gets this looper's message queue.
353803c2affcbe0a0e0fbb561967e0306bfc97ee197Jeff Brown     *
354803c2affcbe0a0e0fbb561967e0306bfc97ee197Jeff Brown     * @return The looper's message queue.
355803c2affcbe0a0e0fbb561967e0306bfc97ee197Jeff Brown     */
356803c2affcbe0a0e0fbb561967e0306bfc97ee197Jeff Brown    public @NonNull MessageQueue getQueue() {
357a41ca77fabe1c7ad12ebb9b69b9e786c07d49fa0Jeff Brown        return mQueue;
358a41ca77fabe1c7ad12ebb9b69b9e786c07d49fa0Jeff Brown    }
3591b29825cca9edda7ae4b3a3f27420c42fd13eef8Brad Fitzpatrick
360803c2affcbe0a0e0fbb561967e0306bfc97ee197Jeff Brown    /**
361803c2affcbe0a0e0fbb561967e0306bfc97ee197Jeff Brown     * Dumps the state of the looper for debugging purposes.
362803c2affcbe0a0e0fbb561967e0306bfc97ee197Jeff Brown     *
363803c2affcbe0a0e0fbb561967e0306bfc97ee197Jeff Brown     * @param pw A printer to receive the contents of the dump.
364803c2affcbe0a0e0fbb561967e0306bfc97ee197Jeff Brown     * @param prefix A prefix to prepend to each line which is printed.
365803c2affcbe0a0e0fbb561967e0306bfc97ee197Jeff Brown     */
366803c2affcbe0a0e0fbb561967e0306bfc97ee197Jeff Brown    public void dump(@NonNull Printer pw, @NonNull String prefix) {
3675182c780a8b42acd46a06d693ab63a0dd78c6d70Jeff Brown        pw.println(prefix + toString());
368cb01563d7efa5689abb98fe4e5d8cc86bfc2b6fcDianne Hackborn        mQueue.dump(pw, prefix + "  ", null);
369cb01563d7efa5689abb98fe4e5d8cc86bfc2b6fcDianne Hackborn    }
370cb01563d7efa5689abb98fe4e5d8cc86bfc2b6fcDianne Hackborn
371cb01563d7efa5689abb98fe4e5d8cc86bfc2b6fcDianne Hackborn    /**
372cb01563d7efa5689abb98fe4e5d8cc86bfc2b6fcDianne Hackborn     * Dumps the state of the looper for debugging purposes.
373cb01563d7efa5689abb98fe4e5d8cc86bfc2b6fcDianne Hackborn     *
374cb01563d7efa5689abb98fe4e5d8cc86bfc2b6fcDianne Hackborn     * @param pw A printer to receive the contents of the dump.
375cb01563d7efa5689abb98fe4e5d8cc86bfc2b6fcDianne Hackborn     * @param prefix A prefix to prepend to each line which is printed.
376cb01563d7efa5689abb98fe4e5d8cc86bfc2b6fcDianne Hackborn     * @param handler Only dump messages for this Handler.
377cb01563d7efa5689abb98fe4e5d8cc86bfc2b6fcDianne Hackborn     * @hide
378cb01563d7efa5689abb98fe4e5d8cc86bfc2b6fcDianne Hackborn     */
379cb01563d7efa5689abb98fe4e5d8cc86bfc2b6fcDianne Hackborn    public void dump(@NonNull Printer pw, @NonNull String prefix, Handler handler) {
380cb01563d7efa5689abb98fe4e5d8cc86bfc2b6fcDianne Hackborn        pw.println(prefix + toString());
381cb01563d7efa5689abb98fe4e5d8cc86bfc2b6fcDianne Hackborn        mQueue.dump(pw, prefix + "  ", handler);
3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
384958d0a503699840f8f4b85cafa62f3793c89ac73Netta P    /** @hide */
385958d0a503699840f8f4b85cafa62f3793c89ac73Netta P    public void writeToProto(ProtoOutputStream proto, long fieldId) {
386958d0a503699840f8f4b85cafa62f3793c89ac73Netta P        final long looperToken = proto.start(fieldId);
387958d0a503699840f8f4b85cafa62f3793c89ac73Netta P        proto.write(LooperProto.THREAD_NAME, mThread.getName());
388958d0a503699840f8f4b85cafa62f3793c89ac73Netta P        proto.write(LooperProto.THREAD_ID, mThread.getId());
389958d0a503699840f8f4b85cafa62f3793c89ac73Netta P        mQueue.writeToProto(proto, LooperProto.QUEUE);
390958d0a503699840f8f4b85cafa62f3793c89ac73Netta P        proto.end(looperToken);
391958d0a503699840f8f4b85cafa62f3793c89ac73Netta P    }
392958d0a503699840f8f4b85cafa62f3793c89ac73Netta P
393dc3eb4bf91d37ce6b8b000a59625a496b64b36fbJeff Brown    @Override
3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public String toString() {
3955182c780a8b42acd46a06d693ab63a0dd78c6d70Jeff Brown        return "Looper (" + mThread.getName() + ", tid " + mThread.getId()
3965182c780a8b42acd46a06d693ab63a0dd78c6d70Jeff Brown                + ") {" + Integer.toHexString(System.identityHashCode(this)) + "}";
3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
399