1 /* 2 * Copyright (C) 2009 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.cts; 18 19 import static org.junit.Assert.assertEquals; 20 import static org.junit.Assert.assertFalse; 21 import static org.junit.Assert.assertNotNull; 22 import static org.junit.Assert.assertNull; 23 import static org.junit.Assert.assertSame; 24 import static org.junit.Assert.assertTrue; 25 import static org.junit.Assert.fail; 26 27 import android.os.Handler; 28 import android.os.Looper; 29 import android.os.Message; 30 import android.os.MessageQueue; 31 import android.os.SystemClock; 32 import android.platform.test.annotations.AppModeSdkSandbox; 33 import android.platform.test.ravenwood.RavenwoodRule; 34 import android.util.Printer; 35 import android.util.StringBuilderPrinter; 36 37 import androidx.test.runner.AndroidJUnit4; 38 39 import com.android.compatibility.common.util.TestThread; 40 41 import org.junit.Rule; 42 import org.junit.Test; 43 import org.junit.runner.RunWith; 44 45 @AppModeSdkSandbox(reason = "Allow test in the SDK sandbox (does not prevent other modes).") 46 @RunWith(AndroidJUnit4.class) 47 public class LooperTest { 48 @Rule 49 public final RavenwoodRule mRavenwood = new RavenwoodRule.Builder() 50 .setProvideMainThread(true).build(); 51 52 public static final long WAIT_TIME = 1000; 53 54 private boolean mHasRun; 55 56 private Looper mLooper = null; 57 private boolean mHasQuit; 58 private Handler mLoopHandler; 59 60 @Test testDump()61 public void testDump() { 62 StringBuilderPrinter printer = new StringBuilderPrinter(new StringBuilder()); 63 final String prefix = "LooperTest"; 64 Looper.getMainLooper().dump(printer, prefix); 65 } 66 67 @Test testGetMainLooper()68 public void testGetMainLooper() { 69 Looper looper = Looper.getMainLooper(); 70 assertNotNull(looper); 71 } 72 73 @Test testLoop()74 public void testLoop() throws Throwable { 75 Thread t = new Thread(new Runnable() { 76 public void run() { 77 Looper.prepare(); 78 79 MockRunnable run = new MockRunnable(); 80 81 Handler handler = new Handler(); 82 Message msg = Message.obtain(handler, run); 83 handler.sendMessageAtTime(msg, 0); 84 assertFalse(run.runCalled); 85 Looper.loop(); 86 assertTrue(run.runCalled); 87 } 88 }); 89 t.start(); 90 t.join(); 91 } 92 93 @Test testMyLooper()94 public void testMyLooper() throws Throwable { 95 TestThread t = new TestThread(new Runnable() { 96 public void run() { 97 assertNull(Looper.myLooper()); 98 Looper.prepare(); 99 assertNotNull(Looper.myLooper()); 100 } 101 }); 102 103 t.runTest(WAIT_TIME); 104 } 105 106 @Test testIsCurrentThread()107 public void testIsCurrentThread() throws Throwable { 108 final Looper[] looper = new Looper[1]; 109 TestThread t = new TestThread(new Runnable() { 110 @Override 111 public void run() { 112 Looper.prepare(); 113 assertTrue(Looper.myLooper().isCurrentThread()); 114 looper[0] = Looper.myLooper(); 115 } 116 }); 117 118 t.runTest(WAIT_TIME); 119 assertFalse(looper[0].isCurrentThread()); 120 } 121 122 @Test testMyQueue()123 public void testMyQueue() throws Throwable { 124 TestThread t = new TestThread(new Runnable() { 125 public void run() { 126 boolean didThrow = false; 127 try { 128 assertNull(Looper.myQueue()); 129 } catch (Throwable e) { 130 // expected 131 didThrow = true; 132 } 133 if (!didThrow) { 134 fail("should throw exception"); 135 } 136 Looper.prepare(); 137 MessageQueue mq = Looper.myQueue(); 138 assertNotNull(mq); 139 } 140 }); 141 142 t.runTest(WAIT_TIME); 143 } 144 145 @Test testGetQueue()146 public void testGetQueue() throws Throwable { 147 TestThread t = new TestThread(new Runnable() { 148 public void run() { 149 Looper.prepare(); 150 assertNotNull(Looper.myLooper().getQueue()); 151 assertEquals(Looper.myLooper().getQueue(), Looper.myQueue()); 152 } 153 }); 154 155 t.runTest(WAIT_TIME); 156 } 157 158 @Test testPrepare()159 public void testPrepare() throws Throwable { 160 TestThread t = new TestThread(new Runnable() { 161 public void run() { 162 Looper.prepare(); 163 164 try { 165 Looper.prepare(); 166 fail("should throw exception"); 167 } catch (Exception e) { 168 //expected 169 } 170 } 171 }); 172 173 t.runTest(WAIT_TIME); 174 } 175 176 @Test testPrepareMainLooper()177 public void testPrepareMainLooper() throws Throwable { 178 TestThread t = new TestThread(new Runnable() { 179 public void run() { 180 try { 181 Looper.prepareMainLooper(); 182 fail("should throw exception because the main thread was already prepared"); 183 } catch (Exception e) { 184 //expected 185 } 186 } 187 }); 188 189 t.runTest(WAIT_TIME); 190 } 191 192 @Test testQuit()193 public void testQuit() throws Throwable { 194 TestThread t = new TestThread(new Runnable() { 195 public void run() { 196 mHasQuit = false; 197 Looper.prepare(); 198 mLoopHandler = new Handler(); 199 mLooper = Looper.myLooper(); 200 Looper.loop(); 201 mHasQuit = true; 202 } 203 }); 204 205 // Here doesn't call runTest() because we don't want to wait the runTest finish. 206 // Just need to handle Looper#quit(); 207 t.start(); 208 Thread.sleep(WAIT_TIME); 209 assertSame(t, mLooper.getThread()); 210 int time = 100; 211 // Send message before Looper has quit. 212 assertTrue(mLoopHandler.sendEmptyMessageAtTime(0, SystemClock.uptimeMillis() + time)); 213 Thread.sleep(WAIT_TIME); 214 215 mLooper.quit(); 216 Thread.sleep(WAIT_TIME); 217 // Send message after Looper has quit. 218 assertFalse(mLoopHandler.sendEmptyMessageAtTime(1, SystemClock.uptimeMillis() + time)); 219 assertTrue(mHasQuit); 220 221 t.joinAndCheck(WAIT_TIME); 222 } 223 224 @Test testSetMessageLogging()225 public void testSetMessageLogging() throws Throwable { 226 mHasRun = false; 227 228 TestThread t = new TestThread(new Runnable() { 229 public void run() { 230 Looper.prepare(); 231 MockPrinter mp = new MockPrinter(); 232 Looper.myLooper().setMessageLogging(mp); 233 MockRunnable run = new MockRunnable(); 234 235 Handler handler = new Handler(); 236 Message msg = Message.obtain(handler, run); 237 handler.sendMessageAtTime(msg, 0); 238 239 Looper.loop(); 240 assertNotNull(mp.str); 241 mHasRun = true; 242 } 243 }); 244 245 t.runTest(WAIT_TIME); 246 247 assertTrue(mHasRun); 248 } 249 250 @Test testToString()251 public void testToString() { 252 assertNotNull(Looper.getMainLooper().toString()); 253 } 254 255 class MockPrinter implements Printer { 256 public String str; 257 println(String x)258 public void println(String x) { 259 str = x; 260 } 261 } 262 263 private class MockRunnable implements Runnable { 264 public boolean runCalled = false; 265 run()266 public void run() { 267 runCalled = true; 268 Looper.myLooper().quit(); 269 } 270 stop()271 public void stop() { 272 Looper.myLooper().quit(); 273 } 274 } 275 } 276