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