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 HandlerThread(String name)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 */ HandlerThread(String name, int priority)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 */ onLooperPrepared()52 protected void onLooperPrepared() { 53 } 54 55 @Override run()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 */ getLooper()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 getThreadHandler()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 */ quit()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 */ quitSafely()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 */ getThreadId()162 public int getThreadId() { 163 return mTid; 164 } 165 } 166