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