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 * A {@link Thread} that has a {@link Looper}. 24 * The {@link Looper} can then be used to create {@link Handler}s. 25 * <p> 26 * Note that just like with a regular {@link Thread}, {@link #start()} must still be called. 27 */ 28 public class HandlerThread extends Thread { 29 int mPriority; 30 int mTid = -1; 31 Looper mLooper; 32 private @Nullable Handler mHandler; 33 HandlerThread(String name)34 public HandlerThread(String name) { 35 super(name); 36 mPriority = Process.THREAD_PRIORITY_DEFAULT; 37 } 38 39 /** 40 * Constructs a HandlerThread. 41 * @param name 42 * @param priority The priority to run the thread at. The value supplied must be from 43 * {@link android.os.Process} and not from java.lang.Thread. 44 */ HandlerThread(String name, int priority)45 public HandlerThread(String name, int priority) { 46 super(name); 47 mPriority = priority; 48 } 49 50 /** 51 * Call back method that can be explicitly overridden if needed to execute some 52 * setup before Looper loops. 53 */ onLooperPrepared()54 protected void onLooperPrepared() { 55 } 56 57 @Override run()58 public void run() { 59 mTid = Process.myTid(); 60 Looper.prepare(); 61 synchronized (this) { 62 mLooper = Looper.myLooper(); 63 notifyAll(); 64 } 65 Process.setThreadPriority(mPriority); 66 onLooperPrepared(); 67 Looper.loop(); 68 mTid = -1; 69 } 70 71 /** 72 * This method returns the Looper associated with this thread. If this thread not been started 73 * or for any reason isAlive() returns false, this method will return null. If this thread 74 * has been started, this method will block until the looper has been initialized. 75 * @return The looper. 76 */ getLooper()77 public Looper getLooper() { 78 if (!isAlive()) { 79 return null; 80 } 81 82 // If the thread has been started, wait until the looper has been created. 83 synchronized (this) { 84 while (isAlive() && mLooper == null) { 85 try { 86 wait(); 87 } catch (InterruptedException e) { 88 } 89 } 90 } 91 return mLooper; 92 } 93 94 /** 95 * @return a shared {@link Handler} associated with this thread 96 * @hide 97 */ 98 @NonNull getThreadHandler()99 public Handler getThreadHandler() { 100 if (mHandler == null) { 101 mHandler = new Handler(getLooper()); 102 } 103 return mHandler; 104 } 105 106 /** 107 * Quits the handler thread's looper. 108 * <p> 109 * Causes the handler thread's looper to terminate without processing any 110 * more messages in the message queue. 111 * </p><p> 112 * Any attempt to post messages to the queue after the looper is asked to quit will fail. 113 * For example, the {@link Handler#sendMessage(Message)} method will return false. 114 * </p><p class="note"> 115 * Using this method may be unsafe because some messages may not be delivered 116 * before the looper terminates. Consider using {@link #quitSafely} instead to ensure 117 * that all pending work is completed in an orderly manner. 118 * </p> 119 * 120 * @return True if the looper looper has been asked to quit or false if the 121 * thread had not yet started running. 122 * 123 * @see #quitSafely 124 */ quit()125 public boolean quit() { 126 Looper looper = getLooper(); 127 if (looper != null) { 128 looper.quit(); 129 return true; 130 } 131 return false; 132 } 133 134 /** 135 * Quits the handler thread's looper safely. 136 * <p> 137 * Causes the handler thread's looper to terminate as soon as all remaining messages 138 * in the message queue that are already due to be delivered have been handled. 139 * Pending delayed messages with due times in the future will not be delivered. 140 * </p><p> 141 * Any attempt to post messages to the queue after the looper is asked to quit will fail. 142 * For example, the {@link Handler#sendMessage(Message)} method will return false. 143 * </p><p> 144 * If the thread has not been started or has finished (that is if 145 * {@link #getLooper} returns null), then false is returned. 146 * Otherwise the looper is asked to quit and true is returned. 147 * </p> 148 * 149 * @return True if the looper looper has been asked to quit or false if the 150 * thread had not yet started running. 151 */ quitSafely()152 public boolean quitSafely() { 153 Looper looper = getLooper(); 154 if (looper != null) { 155 looper.quitSafely(); 156 return true; 157 } 158 return false; 159 } 160 161 /** 162 * Returns the identifier of this thread. See Process.myTid(). 163 */ getThreadId()164 public int getThreadId() { 165 return mTid; 166 } 167 } 168