Home | History | Annotate | Download | only in os
      1 /*
      2  * Copyright (C) 2006 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package android.os;
     18 
     19 import android.annotation.NonNull;
     20 import android.annotation.Nullable;
     21 
     22 /**
     23  * Handy class for starting a new thread that has a looper. The looper can then be
     24  * used to create handler classes. Note that start() must still be called.
     25  */
     26 public class HandlerThread extends Thread {
     27     int mPriority;
     28     int mTid = -1;
     29     Looper mLooper;
     30     private @Nullable Handler mHandler;
     31 
     32     public HandlerThread(String name) {
     33         super(name);
     34         mPriority = Process.THREAD_PRIORITY_DEFAULT;
     35     }
     36 
     37     /**
     38      * Constructs a HandlerThread.
     39      * @param name
     40      * @param priority The priority to run the thread at. The value supplied must be from
     41      * {@link android.os.Process} and not from java.lang.Thread.
     42      */
     43     public HandlerThread(String name, int priority) {
     44         super(name);
     45         mPriority = priority;
     46     }
     47 
     48     /**
     49      * Call back method that can be explicitly overridden if needed to execute some
     50      * setup before Looper loops.
     51      */
     52     protected void onLooperPrepared() {
     53     }
     54 
     55     @Override
     56     public void run() {
     57         mTid = Process.myTid();
     58         Looper.prepare();
     59         synchronized (this) {
     60             mLooper = Looper.myLooper();
     61             notifyAll();
     62         }
     63         Process.setThreadPriority(mPriority);
     64         onLooperPrepared();
     65         Looper.loop();
     66         mTid = -1;
     67     }
     68 
     69     /**
     70      * This method returns the Looper associated with this thread. If this thread not been started
     71      * or for any reason isAlive() returns false, this method will return null. If this thread
     72      * has been started, this method will block until the looper has been initialized.
     73      * @return The looper.
     74      */
     75     public Looper getLooper() {
     76         if (!isAlive()) {
     77             return null;
     78         }
     79 
     80         // If the thread has been started, wait until the looper has been created.
     81         synchronized (this) {
     82             while (isAlive() && mLooper == null) {
     83                 try {
     84                     wait();
     85                 } catch (InterruptedException e) {
     86                 }
     87             }
     88         }
     89         return mLooper;
     90     }
     91 
     92     /**
     93      * @return a shared {@link Handler} associated with this thread
     94      * @hide
     95      */
     96     @NonNull
     97     public Handler getThreadHandler() {
     98         if (mHandler == null) {
     99             mHandler = new Handler(getLooper());
    100         }
    101         return mHandler;
    102     }
    103 
    104     /**
    105      * Quits the handler thread's looper.
    106      * <p>
    107      * Causes the handler thread's looper to terminate without processing any
    108      * more messages in the message queue.
    109      * </p><p>
    110      * Any attempt to post messages to the queue after the looper is asked to quit will fail.
    111      * For example, the {@link Handler#sendMessage(Message)} method will return false.
    112      * </p><p class="note">
    113      * Using this method may be unsafe because some messages may not be delivered
    114      * before the looper terminates.  Consider using {@link #quitSafely} instead to ensure
    115      * that all pending work is completed in an orderly manner.
    116      * </p>
    117      *
    118      * @return True if the looper looper has been asked to quit or false if the
    119      * thread had not yet started running.
    120      *
    121      * @see #quitSafely
    122      */
    123     public boolean quit() {
    124         Looper looper = getLooper();
    125         if (looper != null) {
    126             looper.quit();
    127             return true;
    128         }
    129         return false;
    130     }
    131 
    132     /**
    133      * Quits the handler thread's looper safely.
    134      * <p>
    135      * Causes the handler thread's looper to terminate as soon as all remaining messages
    136      * in the message queue that are already due to be delivered have been handled.
    137      * Pending delayed messages with due times in the future will not be delivered.
    138      * </p><p>
    139      * Any attempt to post messages to the queue after the looper is asked to quit will fail.
    140      * For example, the {@link Handler#sendMessage(Message)} method will return false.
    141      * </p><p>
    142      * If the thread has not been started or has finished (that is if
    143      * {@link #getLooper} returns null), then false is returned.
    144      * Otherwise the looper is asked to quit and true is returned.
    145      * </p>
    146      *
    147      * @return True if the looper looper has been asked to quit or false if the
    148      * thread had not yet started running.
    149      */
    150     public boolean quitSafely() {
    151         Looper looper = getLooper();
    152         if (looper != null) {
    153             looper.quitSafely();
    154             return true;
    155         }
    156         return false;
    157     }
    158 
    159     /**
    160      * Returns the identifier of this thread. See Process.myTid().
    161      */
    162     public int getThreadId() {
    163         return mTid;
    164     }
    165 }
    166