1 //
2 // Copyright 2010 The Android Open Source Project
3 //
4
5 #include <gtest/gtest.h>
6 #include <time.h>
7 #include <unistd.h>
8 #include <utils/Looper.h>
9 #include <utils/StopWatch.h>
10 #include <utils/Timers.h>
11 #include <thread>
12 #include <unordered_map>
13 #include <utility>
14 #include "Looper_test_pipe.h"
15
16 #include <utils/threads.h>
17
18 // b/141212746 - increased for virtual platforms with higher volatility
19 // # of milliseconds to fudge stopwatch measurements
20 #define TIMING_TOLERANCE_MS 100
21
22 namespace android {
23
24 enum {
25 MSG_TEST1 = 1,
26 MSG_TEST2 = 2,
27 MSG_TEST3 = 3,
28 MSG_TEST4 = 4,
29 };
30
31 class DelayedTask : public Thread {
32 int mDelayMillis;
33
34 public:
DelayedTask(int delayMillis)35 explicit DelayedTask(int delayMillis) : mDelayMillis(delayMillis) { }
36
37 protected:
~DelayedTask()38 virtual ~DelayedTask() { }
39
40 virtual void doTask() = 0;
41
threadLoop()42 virtual bool threadLoop() {
43 usleep(mDelayMillis * 1000);
44 doTask();
45 return false;
46 }
47 };
48
49 class DelayedWake : public DelayedTask {
50 sp<Looper> mLooper;
51
52 public:
DelayedWake(int delayMillis,const sp<Looper> looper)53 DelayedWake(int delayMillis, const sp<Looper> looper) :
54 DelayedTask(delayMillis), mLooper(looper) {
55 }
56
57 protected:
doTask()58 virtual void doTask() {
59 mLooper->wake();
60 }
61 };
62
63 class DelayedWriteSignal : public DelayedTask {
64 Pipe* mPipe;
65
66 public:
DelayedWriteSignal(int delayMillis,Pipe * pipe)67 DelayedWriteSignal(int delayMillis, Pipe* pipe) :
68 DelayedTask(delayMillis), mPipe(pipe) {
69 }
70
71 protected:
doTask()72 virtual void doTask() {
73 mPipe->writeSignal();
74 }
75 };
76
77 class CallbackHandler {
78 public:
setCallback(const sp<Looper> & looper,int fd,int events)79 void setCallback(const sp<Looper>& looper, int fd, int events) {
80 looper->addFd(fd, 0, events, staticHandler, this);
81 }
82
83 protected:
~CallbackHandler()84 virtual ~CallbackHandler() { }
85
86 virtual int handler(int fd, int events) = 0;
87
88 private:
staticHandler(int fd,int events,void * data)89 static int staticHandler(int fd, int events, void* data) {
90 return static_cast<CallbackHandler*>(data)->handler(fd, events);
91 }
92 };
93
94 class StubCallbackHandler : public CallbackHandler {
95 public:
96 int nextResult;
97 int callbackCount;
98
99 int fd;
100 int events;
101
StubCallbackHandler(int nextResult)102 explicit StubCallbackHandler(int nextResult) : nextResult(nextResult),
103 callbackCount(0), fd(-1), events(-1) {
104 }
105
106 protected:
handler(int fd,int events)107 virtual int handler(int fd, int events) {
108 callbackCount += 1;
109 this->fd = fd;
110 this->events = events;
111 return nextResult;
112 }
113 };
114
115 class StubMessageHandler : public MessageHandler {
116 public:
117 Vector<Message> messages;
118
handleMessage(const Message & message)119 virtual void handleMessage(const Message& message) {
120 messages.push(message);
121 }
122 };
123
124 class LooperTest : public testing::Test {
125 protected:
126 sp<Looper> mLooper;
127
SetUp()128 virtual void SetUp() {
129 mLooper = new Looper(true);
130 }
131
TearDown()132 virtual void TearDown() {
133 mLooper.clear();
134 }
135 };
136
137
TEST_F(LooperTest,PollOnce_WhenNonZeroTimeoutAndNotAwoken_WaitsForTimeout)138 TEST_F(LooperTest, PollOnce_WhenNonZeroTimeoutAndNotAwoken_WaitsForTimeout) {
139 StopWatch stopWatch("pollOnce");
140 int result = mLooper->pollOnce(100);
141 int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
142
143 EXPECT_NEAR(100, elapsedMillis, TIMING_TOLERANCE_MS)
144 << "elapsed time should approx. equal timeout";
145 EXPECT_EQ(Looper::POLL_TIMEOUT, result)
146 << "pollOnce result should be LOOPER_POLL_TIMEOUT";
147 }
148
TEST_F(LooperTest,PollOnce_WhenNonZeroTimeoutAndAwokenBeforeWaiting_ImmediatelyReturns)149 TEST_F(LooperTest, PollOnce_WhenNonZeroTimeoutAndAwokenBeforeWaiting_ImmediatelyReturns) {
150 mLooper->wake();
151
152 StopWatch stopWatch("pollOnce");
153 int result = mLooper->pollOnce(1000);
154 int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
155
156 EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS)
157 << "elapsed time should approx. zero because wake() was called before waiting";
158 EXPECT_EQ(Looper::POLL_WAKE, result)
159 << "pollOnce result should be Looper::POLL_CALLBACK because loop was awoken";
160 }
161
TEST_F(LooperTest,PollOnce_WhenNonZeroTimeoutAndAwokenWhileWaiting_PromptlyReturns)162 TEST_F(LooperTest, PollOnce_WhenNonZeroTimeoutAndAwokenWhileWaiting_PromptlyReturns) {
163 sp<DelayedWake> delayedWake = new DelayedWake(100, mLooper);
164 delayedWake->run("LooperTest");
165
166 StopWatch stopWatch("pollOnce");
167 int result = mLooper->pollOnce(1000);
168 int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
169
170 EXPECT_NEAR(100, elapsedMillis, TIMING_TOLERANCE_MS)
171 << "elapsed time should approx. equal wake delay";
172 EXPECT_EQ(Looper::POLL_WAKE, result)
173 << "pollOnce result should be Looper::POLL_CALLBACK because loop was awoken";
174 }
175
TEST_F(LooperTest,PollOnce_WhenZeroTimeoutAndNoRegisteredFDs_ImmediatelyReturns)176 TEST_F(LooperTest, PollOnce_WhenZeroTimeoutAndNoRegisteredFDs_ImmediatelyReturns) {
177 StopWatch stopWatch("pollOnce");
178 int result = mLooper->pollOnce(0);
179 int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
180
181 EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS)
182 << "elapsed time should be approx. zero";
183 EXPECT_EQ(Looper::POLL_TIMEOUT, result)
184 << "pollOnce result should be Looper::POLL_TIMEOUT";
185 }
186
TEST_F(LooperTest,PollOnce_WhenZeroTimeoutAndNoSignalledFDs_ImmediatelyReturns)187 TEST_F(LooperTest, PollOnce_WhenZeroTimeoutAndNoSignalledFDs_ImmediatelyReturns) {
188 Pipe pipe;
189 StubCallbackHandler handler(true);
190
191 handler.setCallback(mLooper, pipe.receiveFd, Looper::EVENT_INPUT);
192
193 StopWatch stopWatch("pollOnce");
194 int result = mLooper->pollOnce(0);
195 int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
196
197 EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS)
198 << "elapsed time should be approx. zero";
199 EXPECT_EQ(Looper::POLL_TIMEOUT, result)
200 << "pollOnce result should be Looper::POLL_TIMEOUT";
201 EXPECT_EQ(0, handler.callbackCount)
202 << "callback should not have been invoked because FD was not signalled";
203 }
204
TEST_F(LooperTest,PollOnce_WhenZeroTimeoutAndSignalledFD_ImmediatelyInvokesCallbackAndReturns)205 TEST_F(LooperTest, PollOnce_WhenZeroTimeoutAndSignalledFD_ImmediatelyInvokesCallbackAndReturns) {
206 Pipe pipe;
207 StubCallbackHandler handler(true);
208
209 ASSERT_EQ(OK, pipe.writeSignal());
210 handler.setCallback(mLooper, pipe.receiveFd, Looper::EVENT_INPUT);
211
212 StopWatch stopWatch("pollOnce");
213 int result = mLooper->pollOnce(0);
214 int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
215
216 EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS)
217 << "elapsed time should be approx. zero";
218 EXPECT_EQ(Looper::POLL_CALLBACK, result)
219 << "pollOnce result should be Looper::POLL_CALLBACK because FD was signalled";
220 EXPECT_EQ(1, handler.callbackCount)
221 << "callback should be invoked exactly once";
222 EXPECT_EQ(pipe.receiveFd, handler.fd)
223 << "callback should have received pipe fd as parameter";
224 EXPECT_EQ(Looper::EVENT_INPUT, handler.events)
225 << "callback should have received Looper::EVENT_INPUT as events";
226 }
227
TEST_F(LooperTest,PollOnce_WhenNonZeroTimeoutAndNoSignalledFDs_WaitsForTimeoutAndReturns)228 TEST_F(LooperTest, PollOnce_WhenNonZeroTimeoutAndNoSignalledFDs_WaitsForTimeoutAndReturns) {
229 Pipe pipe;
230 StubCallbackHandler handler(true);
231
232 handler.setCallback(mLooper, pipe.receiveFd, Looper::EVENT_INPUT);
233
234 StopWatch stopWatch("pollOnce");
235 int result = mLooper->pollOnce(100);
236 int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
237
238 EXPECT_NEAR(100, elapsedMillis, TIMING_TOLERANCE_MS)
239 << "elapsed time should approx. equal timeout";
240 EXPECT_EQ(Looper::POLL_TIMEOUT, result)
241 << "pollOnce result should be Looper::POLL_TIMEOUT";
242 EXPECT_EQ(0, handler.callbackCount)
243 << "callback should not have been invoked because FD was not signalled";
244 }
245
TEST_F(LooperTest,PollOnce_WhenNonZeroTimeoutAndSignalledFDBeforeWaiting_ImmediatelyInvokesCallbackAndReturns)246 TEST_F(LooperTest, PollOnce_WhenNonZeroTimeoutAndSignalledFDBeforeWaiting_ImmediatelyInvokesCallbackAndReturns) {
247 Pipe pipe;
248 StubCallbackHandler handler(true);
249
250 pipe.writeSignal();
251 handler.setCallback(mLooper, pipe.receiveFd, Looper::EVENT_INPUT);
252
253 StopWatch stopWatch("pollOnce");
254 int result = mLooper->pollOnce(100);
255 int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
256
257 ASSERT_EQ(OK, pipe.readSignal())
258 << "signal should actually have been written";
259 EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS)
260 << "elapsed time should be approx. zero";
261 EXPECT_EQ(Looper::POLL_CALLBACK, result)
262 << "pollOnce result should be Looper::POLL_CALLBACK because FD was signalled";
263 EXPECT_EQ(1, handler.callbackCount)
264 << "callback should be invoked exactly once";
265 EXPECT_EQ(pipe.receiveFd, handler.fd)
266 << "callback should have received pipe fd as parameter";
267 EXPECT_EQ(Looper::EVENT_INPUT, handler.events)
268 << "callback should have received Looper::EVENT_INPUT as events";
269 }
270
TEST_F(LooperTest,PollOnce_WhenNonZeroTimeoutAndSignalledFDWhileWaiting_PromptlyInvokesCallbackAndReturns)271 TEST_F(LooperTest, PollOnce_WhenNonZeroTimeoutAndSignalledFDWhileWaiting_PromptlyInvokesCallbackAndReturns) {
272 Pipe pipe;
273 StubCallbackHandler handler(true);
274 sp<DelayedWriteSignal> delayedWriteSignal = new DelayedWriteSignal(100, & pipe);
275
276 handler.setCallback(mLooper, pipe.receiveFd, Looper::EVENT_INPUT);
277 delayedWriteSignal->run("LooperTest");
278
279 StopWatch stopWatch("pollOnce");
280 int result = mLooper->pollOnce(1000);
281 int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
282
283 ASSERT_EQ(OK, pipe.readSignal())
284 << "signal should actually have been written";
285 EXPECT_NEAR(100, elapsedMillis, TIMING_TOLERANCE_MS)
286 << "elapsed time should approx. equal signal delay";
287 EXPECT_EQ(Looper::POLL_CALLBACK, result)
288 << "pollOnce result should be Looper::POLL_CALLBACK because FD was signalled";
289 EXPECT_EQ(1, handler.callbackCount)
290 << "callback should be invoked exactly once";
291 EXPECT_EQ(pipe.receiveFd, handler.fd)
292 << "callback should have received pipe fd as parameter";
293 EXPECT_EQ(Looper::EVENT_INPUT, handler.events)
294 << "callback should have received Looper::EVENT_INPUT as events";
295 }
296
TEST_F(LooperTest,PollOnce_WhenCallbackAddedThenRemoved_CallbackShouldNotBeInvoked)297 TEST_F(LooperTest, PollOnce_WhenCallbackAddedThenRemoved_CallbackShouldNotBeInvoked) {
298 Pipe pipe;
299 StubCallbackHandler handler(true);
300
301 handler.setCallback(mLooper, pipe.receiveFd, Looper::EVENT_INPUT);
302 pipe.writeSignal(); // would cause FD to be considered signalled
303 mLooper->removeFd(pipe.receiveFd);
304
305 StopWatch stopWatch("pollOnce");
306 int result = mLooper->pollOnce(100);
307 int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
308
309 ASSERT_EQ(OK, pipe.readSignal())
310 << "signal should actually have been written";
311 EXPECT_NEAR(100, elapsedMillis, TIMING_TOLERANCE_MS)
312 << "elapsed time should approx. equal timeout because FD was no longer registered";
313 EXPECT_EQ(Looper::POLL_TIMEOUT, result)
314 << "pollOnce result should be Looper::POLL_TIMEOUT";
315 EXPECT_EQ(0, handler.callbackCount)
316 << "callback should not be invoked";
317 }
318
TEST_F(LooperTest,PollOnce_WhenCallbackReturnsFalse_CallbackShouldNotBeInvokedAgainLater)319 TEST_F(LooperTest, PollOnce_WhenCallbackReturnsFalse_CallbackShouldNotBeInvokedAgainLater) {
320 Pipe pipe;
321 StubCallbackHandler handler(false);
322
323 handler.setCallback(mLooper, pipe.receiveFd, Looper::EVENT_INPUT);
324
325 // First loop: Callback is registered and FD is signalled.
326 pipe.writeSignal();
327
328 StopWatch stopWatch("pollOnce");
329 int result = mLooper->pollOnce(0);
330 int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
331
332 ASSERT_EQ(OK, pipe.readSignal())
333 << "signal should actually have been written";
334 EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS)
335 << "elapsed time should approx. equal zero because FD was already signalled";
336 EXPECT_EQ(Looper::POLL_CALLBACK, result)
337 << "pollOnce result should be Looper::POLL_CALLBACK because FD was signalled";
338 EXPECT_EQ(1, handler.callbackCount)
339 << "callback should be invoked";
340
341 // Second loop: Callback is no longer registered and FD is signalled.
342 pipe.writeSignal();
343
344 stopWatch.reset();
345 result = mLooper->pollOnce(0);
346 elapsedMillis = ns2ms(stopWatch.elapsedTime());
347
348 ASSERT_EQ(OK, pipe.readSignal())
349 << "signal should actually have been written";
350 EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS)
351 << "elapsed time should approx. equal zero because timeout was zero";
352 EXPECT_EQ(Looper::POLL_TIMEOUT, result)
353 << "pollOnce result should be Looper::POLL_TIMEOUT";
354 EXPECT_EQ(1, handler.callbackCount)
355 << "callback should not be invoked this time";
356 }
357
TEST_F(LooperTest,PollOnce_WhenNonCallbackFdIsSignalled_ReturnsIdent)358 TEST_F(LooperTest, PollOnce_WhenNonCallbackFdIsSignalled_ReturnsIdent) {
359 const int expectedIdent = 5;
360 void* expectedData = this;
361
362 Pipe pipe;
363
364 pipe.writeSignal();
365 mLooper->addFd(pipe.receiveFd, expectedIdent, Looper::EVENT_INPUT, nullptr, expectedData);
366
367 StopWatch stopWatch("pollOnce");
368 int fd;
369 int events;
370 void* data;
371 int result = mLooper->pollOnce(100, &fd, &events, &data);
372 int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
373
374 ASSERT_EQ(OK, pipe.readSignal())
375 << "signal should actually have been written";
376 EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS)
377 << "elapsed time should be approx. zero";
378 EXPECT_EQ(expectedIdent, result)
379 << "pollOnce result should be the ident of the FD that was signalled";
380 EXPECT_EQ(pipe.receiveFd, fd)
381 << "pollOnce should have returned the received pipe fd";
382 EXPECT_EQ(Looper::EVENT_INPUT, events)
383 << "pollOnce should have returned Looper::EVENT_INPUT as events";
384 EXPECT_EQ(expectedData, data)
385 << "pollOnce should have returned the data";
386 }
387
TEST_F(LooperTest,AddFd_WhenCallbackAdded_ReturnsOne)388 TEST_F(LooperTest, AddFd_WhenCallbackAdded_ReturnsOne) {
389 Pipe pipe;
390 int result = mLooper->addFd(pipe.receiveFd, 0, Looper::EVENT_INPUT, nullptr, nullptr);
391
392 EXPECT_EQ(1, result)
393 << "addFd should return 1 because FD was added";
394 }
395
TEST_F(LooperTest,AddFd_WhenIdentIsNegativeAndCallbackIsNull_ReturnsError)396 TEST_F(LooperTest, AddFd_WhenIdentIsNegativeAndCallbackIsNull_ReturnsError) {
397 Pipe pipe;
398 int result = mLooper->addFd(pipe.receiveFd, -1, Looper::EVENT_INPUT, nullptr, nullptr);
399
400 EXPECT_EQ(-1, result)
401 << "addFd should return -1 because arguments were invalid";
402 }
403
TEST_F(LooperTest,AddFd_WhenNoCallbackAndAllowNonCallbacksIsFalse_ReturnsError)404 TEST_F(LooperTest, AddFd_WhenNoCallbackAndAllowNonCallbacksIsFalse_ReturnsError) {
405 Pipe pipe;
406 sp<Looper> looper = new Looper(false /*allowNonCallbacks*/);
407 int result = looper->addFd(pipe.receiveFd, 0, 0, nullptr, nullptr);
408
409 EXPECT_EQ(-1, result)
410 << "addFd should return -1 because arguments were invalid";
411 }
412
TEST_F(LooperTest,RemoveFd_WhenCallbackNotAdded_ReturnsZero)413 TEST_F(LooperTest, RemoveFd_WhenCallbackNotAdded_ReturnsZero) {
414 int result = mLooper->removeFd(1);
415
416 EXPECT_EQ(0, result)
417 << "removeFd should return 0 because FD not registered";
418 }
419
TEST_F(LooperTest,RemoveFd_WhenCallbackAddedThenRemovedTwice_ReturnsOnceFirstTimeAndReturnsZeroSecondTime)420 TEST_F(LooperTest, RemoveFd_WhenCallbackAddedThenRemovedTwice_ReturnsOnceFirstTimeAndReturnsZeroSecondTime) {
421 Pipe pipe;
422 StubCallbackHandler handler(false);
423 handler.setCallback(mLooper, pipe.receiveFd, Looper::EVENT_INPUT);
424
425 // First time.
426 int result = mLooper->removeFd(pipe.receiveFd);
427
428 EXPECT_EQ(1, result)
429 << "removeFd should return 1 first time because FD was registered";
430
431 // Second time.
432 result = mLooper->removeFd(pipe.receiveFd);
433
434 EXPECT_EQ(0, result)
435 << "removeFd should return 0 second time because FD was no longer registered";
436 }
437
TEST_F(LooperTest,PollOnce_WhenCallbackAddedTwice_OnlySecondCallbackShouldBeInvoked)438 TEST_F(LooperTest, PollOnce_WhenCallbackAddedTwice_OnlySecondCallbackShouldBeInvoked) {
439 Pipe pipe;
440 StubCallbackHandler handler1(true);
441 StubCallbackHandler handler2(true);
442
443 handler1.setCallback(mLooper, pipe.receiveFd, Looper::EVENT_INPUT);
444 handler2.setCallback(mLooper, pipe.receiveFd, Looper::EVENT_INPUT); // replace it
445 pipe.writeSignal(); // would cause FD to be considered signalled
446
447 StopWatch stopWatch("pollOnce");
448 int result = mLooper->pollOnce(100);
449 int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
450
451 ASSERT_EQ(OK, pipe.readSignal())
452 << "signal should actually have been written";
453 EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS)
454 << "elapsed time should approx. zero because FD was already signalled";
455 EXPECT_EQ(Looper::POLL_CALLBACK, result)
456 << "pollOnce result should be Looper::POLL_CALLBACK because FD was signalled";
457 EXPECT_EQ(0, handler1.callbackCount)
458 << "original handler callback should not be invoked because it was replaced";
459 EXPECT_EQ(1, handler2.callbackCount)
460 << "replacement handler callback should be invoked";
461 }
462
TEST_F(LooperTest,SendMessage_WhenOneMessageIsEnqueue_ShouldInvokeHandlerDuringNextPoll)463 TEST_F(LooperTest, SendMessage_WhenOneMessageIsEnqueue_ShouldInvokeHandlerDuringNextPoll) {
464 sp<StubMessageHandler> handler = new StubMessageHandler();
465 mLooper->sendMessage(handler, Message(MSG_TEST1));
466
467 StopWatch stopWatch("pollOnce");
468 int result = mLooper->pollOnce(100);
469 int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
470
471 EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS)
472 << "elapsed time should approx. zero because message was already sent";
473 EXPECT_EQ(Looper::POLL_CALLBACK, result)
474 << "pollOnce result should be Looper::POLL_CALLBACK because message was sent";
475 EXPECT_EQ(size_t(1), handler->messages.size())
476 << "handled message";
477 EXPECT_EQ(MSG_TEST1, handler->messages[0].what)
478 << "handled message";
479 }
480
TEST_F(LooperTest,SendMessage_WhenMultipleMessagesAreEnqueued_ShouldInvokeHandlersInOrderDuringNextPoll)481 TEST_F(LooperTest, SendMessage_WhenMultipleMessagesAreEnqueued_ShouldInvokeHandlersInOrderDuringNextPoll) {
482 sp<StubMessageHandler> handler1 = new StubMessageHandler();
483 sp<StubMessageHandler> handler2 = new StubMessageHandler();
484 mLooper->sendMessage(handler1, Message(MSG_TEST1));
485 mLooper->sendMessage(handler2, Message(MSG_TEST2));
486 mLooper->sendMessage(handler1, Message(MSG_TEST3));
487 mLooper->sendMessage(handler1, Message(MSG_TEST4));
488
489 StopWatch stopWatch("pollOnce");
490 int result = mLooper->pollOnce(1000);
491 int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
492
493 EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS)
494 << "elapsed time should approx. zero because message was already sent";
495 EXPECT_EQ(Looper::POLL_CALLBACK, result)
496 << "pollOnce result should be Looper::POLL_CALLBACK because message was sent";
497 EXPECT_EQ(size_t(3), handler1->messages.size())
498 << "handled message";
499 EXPECT_EQ(MSG_TEST1, handler1->messages[0].what)
500 << "handled message";
501 EXPECT_EQ(MSG_TEST3, handler1->messages[1].what)
502 << "handled message";
503 EXPECT_EQ(MSG_TEST4, handler1->messages[2].what)
504 << "handled message";
505 EXPECT_EQ(size_t(1), handler2->messages.size())
506 << "handled message";
507 EXPECT_EQ(MSG_TEST2, handler2->messages[0].what)
508 << "handled message";
509 }
510
TEST_F(LooperTest,SendMessageDelayed_WhenSentToTheFuture_ShouldInvokeHandlerAfterDelayTime)511 TEST_F(LooperTest, SendMessageDelayed_WhenSentToTheFuture_ShouldInvokeHandlerAfterDelayTime) {
512 sp<StubMessageHandler> handler = new StubMessageHandler();
513 mLooper->sendMessageDelayed(ms2ns(100), handler, Message(MSG_TEST1));
514
515 StopWatch stopWatch("pollOnce");
516 int result = mLooper->pollOnce(1000);
517 int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
518
519 EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS)
520 << "first poll should end quickly because next message timeout was computed";
521 EXPECT_EQ(Looper::POLL_WAKE, result)
522 << "pollOnce result should be Looper::POLL_WAKE due to wakeup";
523 EXPECT_EQ(size_t(0), handler->messages.size())
524 << "no message handled yet";
525
526 result = mLooper->pollOnce(1000);
527 elapsedMillis = ns2ms(stopWatch.elapsedTime());
528
529 EXPECT_EQ(size_t(1), handler->messages.size())
530 << "handled message";
531 EXPECT_EQ(MSG_TEST1, handler->messages[0].what)
532 << "handled message";
533 EXPECT_NEAR(100, elapsedMillis, TIMING_TOLERANCE_MS)
534 << "second poll should end around the time of the delayed message dispatch";
535 EXPECT_EQ(Looper::POLL_CALLBACK, result)
536 << "pollOnce result should be Looper::POLL_CALLBACK because message was sent";
537
538 result = mLooper->pollOnce(100);
539 elapsedMillis = ns2ms(stopWatch.elapsedTime());
540
541 EXPECT_NEAR(100 + 100, elapsedMillis, TIMING_TOLERANCE_MS)
542 << "third poll should timeout";
543 EXPECT_EQ(Looper::POLL_TIMEOUT, result)
544 << "pollOnce result should be Looper::POLL_TIMEOUT because there were no messages left";
545 }
546
TEST_F(LooperTest,SendMessageDelayed_WhenSentToThePast_ShouldInvokeHandlerDuringNextPoll)547 TEST_F(LooperTest, SendMessageDelayed_WhenSentToThePast_ShouldInvokeHandlerDuringNextPoll) {
548 sp<StubMessageHandler> handler = new StubMessageHandler();
549 mLooper->sendMessageDelayed(ms2ns(-1000), handler, Message(MSG_TEST1));
550
551 StopWatch stopWatch("pollOnce");
552 int result = mLooper->pollOnce(100);
553 int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
554
555 EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS)
556 << "elapsed time should approx. zero because message was already sent";
557 EXPECT_EQ(Looper::POLL_CALLBACK, result)
558 << "pollOnce result should be Looper::POLL_CALLBACK because message was sent";
559 EXPECT_EQ(size_t(1), handler->messages.size())
560 << "handled message";
561 EXPECT_EQ(MSG_TEST1, handler->messages[0].what)
562 << "handled message";
563 }
564
TEST_F(LooperTest,SendMessageDelayed_WhenSentToThePresent_ShouldInvokeHandlerDuringNextPoll)565 TEST_F(LooperTest, SendMessageDelayed_WhenSentToThePresent_ShouldInvokeHandlerDuringNextPoll) {
566 sp<StubMessageHandler> handler = new StubMessageHandler();
567 mLooper->sendMessageDelayed(0, handler, Message(MSG_TEST1));
568
569 StopWatch stopWatch("pollOnce");
570 int result = mLooper->pollOnce(100);
571 int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
572
573 EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS)
574 << "elapsed time should approx. zero because message was already sent";
575 EXPECT_EQ(Looper::POLL_CALLBACK, result)
576 << "pollOnce result should be Looper::POLL_CALLBACK because message was sent";
577 EXPECT_EQ(size_t(1), handler->messages.size())
578 << "handled message";
579 EXPECT_EQ(MSG_TEST1, handler->messages[0].what)
580 << "handled message";
581 }
582
TEST_F(LooperTest,SendMessageAtTime_WhenSentToTheFuture_ShouldInvokeHandlerAfterDelayTime)583 TEST_F(LooperTest, SendMessageAtTime_WhenSentToTheFuture_ShouldInvokeHandlerAfterDelayTime) {
584 nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
585 sp<StubMessageHandler> handler = new StubMessageHandler();
586 mLooper->sendMessageAtTime(now + ms2ns(100), handler, Message(MSG_TEST1));
587
588 StopWatch stopWatch("pollOnce");
589 int result = mLooper->pollOnce(1000);
590 int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
591
592 EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS)
593 << "first poll should end quickly because next message timeout was computed";
594 EXPECT_EQ(Looper::POLL_WAKE, result)
595 << "pollOnce result should be Looper::POLL_WAKE due to wakeup";
596 EXPECT_EQ(size_t(0), handler->messages.size())
597 << "no message handled yet";
598
599 result = mLooper->pollOnce(1000);
600 elapsedMillis = ns2ms(stopWatch.elapsedTime());
601
602 EXPECT_EQ(size_t(1), handler->messages.size())
603 << "handled message";
604 EXPECT_EQ(MSG_TEST1, handler->messages[0].what)
605 << "handled message";
606 EXPECT_NEAR(100, elapsedMillis, TIMING_TOLERANCE_MS)
607 << "second poll should end around the time of the delayed message dispatch";
608 EXPECT_EQ(Looper::POLL_CALLBACK, result)
609 << "pollOnce result should be Looper::POLL_CALLBACK because message was sent";
610
611 result = mLooper->pollOnce(100);
612 elapsedMillis = ns2ms(stopWatch.elapsedTime());
613
614 EXPECT_NEAR(100 + 100, elapsedMillis, TIMING_TOLERANCE_MS)
615 << "third poll should timeout";
616 EXPECT_EQ(Looper::POLL_TIMEOUT, result)
617 << "pollOnce result should be Looper::POLL_TIMEOUT because there were no messages left";
618 }
619
TEST_F(LooperTest,SendMessageAtTime_WhenSentToThePast_ShouldInvokeHandlerDuringNextPoll)620 TEST_F(LooperTest, SendMessageAtTime_WhenSentToThePast_ShouldInvokeHandlerDuringNextPoll) {
621 nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
622 sp<StubMessageHandler> handler = new StubMessageHandler();
623 mLooper->sendMessageAtTime(now - ms2ns(1000), handler, Message(MSG_TEST1));
624
625 StopWatch stopWatch("pollOnce");
626 int result = mLooper->pollOnce(100);
627 int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
628
629 EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS)
630 << "elapsed time should approx. zero because message was already sent";
631 EXPECT_EQ(Looper::POLL_CALLBACK, result)
632 << "pollOnce result should be Looper::POLL_CALLBACK because message was sent";
633 EXPECT_EQ(size_t(1), handler->messages.size())
634 << "handled message";
635 EXPECT_EQ(MSG_TEST1, handler->messages[0].what)
636 << "handled message";
637 }
638
TEST_F(LooperTest,SendMessageAtTime_WhenSentToThePresent_ShouldInvokeHandlerDuringNextPoll)639 TEST_F(LooperTest, SendMessageAtTime_WhenSentToThePresent_ShouldInvokeHandlerDuringNextPoll) {
640 nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
641 sp<StubMessageHandler> handler = new StubMessageHandler();
642 mLooper->sendMessageAtTime(now, handler, Message(MSG_TEST1));
643
644 StopWatch stopWatch("pollOnce");
645 int result = mLooper->pollOnce(100);
646 int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
647
648 EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS)
649 << "elapsed time should approx. zero because message was already sent";
650 EXPECT_EQ(Looper::POLL_CALLBACK, result)
651 << "pollOnce result should be Looper::POLL_CALLBACK because message was sent";
652 EXPECT_EQ(size_t(1), handler->messages.size())
653 << "handled message";
654 EXPECT_EQ(MSG_TEST1, handler->messages[0].what)
655 << "handled message";
656 }
657
TEST_F(LooperTest,RemoveMessage_WhenRemovingAllMessagesForHandler_ShouldRemoveThoseMessage)658 TEST_F(LooperTest, RemoveMessage_WhenRemovingAllMessagesForHandler_ShouldRemoveThoseMessage) {
659 sp<StubMessageHandler> handler = new StubMessageHandler();
660 mLooper->sendMessage(handler, Message(MSG_TEST1));
661 mLooper->sendMessage(handler, Message(MSG_TEST2));
662 mLooper->sendMessage(handler, Message(MSG_TEST3));
663 mLooper->removeMessages(handler);
664
665 StopWatch stopWatch("pollOnce");
666 int result = mLooper->pollOnce(0);
667 int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
668
669 EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS)
670 << "elapsed time should approx. zero because message was sent so looper was awoken";
671 EXPECT_EQ(Looper::POLL_WAKE, result)
672 << "pollOnce result should be Looper::POLL_WAKE because looper was awoken";
673 EXPECT_EQ(size_t(0), handler->messages.size())
674 << "no messages to handle";
675
676 result = mLooper->pollOnce(0);
677
678 EXPECT_EQ(Looper::POLL_TIMEOUT, result)
679 << "pollOnce result should be Looper::POLL_TIMEOUT because there was nothing to do";
680 EXPECT_EQ(size_t(0), handler->messages.size())
681 << "no messages to handle";
682 }
683
TEST_F(LooperTest,RemoveMessage_WhenRemovingSomeMessagesForHandler_ShouldRemoveThoseMessage)684 TEST_F(LooperTest, RemoveMessage_WhenRemovingSomeMessagesForHandler_ShouldRemoveThoseMessage) {
685 sp<StubMessageHandler> handler = new StubMessageHandler();
686 mLooper->sendMessage(handler, Message(MSG_TEST1));
687 mLooper->sendMessage(handler, Message(MSG_TEST2));
688 mLooper->sendMessage(handler, Message(MSG_TEST3));
689 mLooper->sendMessage(handler, Message(MSG_TEST4));
690 mLooper->removeMessages(handler, MSG_TEST3);
691 mLooper->removeMessages(handler, MSG_TEST1);
692
693 StopWatch stopWatch("pollOnce");
694 int result = mLooper->pollOnce(0);
695 int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
696
697 EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS)
698 << "elapsed time should approx. zero because message was sent so looper was awoken";
699 EXPECT_EQ(Looper::POLL_CALLBACK, result)
700 << "pollOnce result should be Looper::POLL_CALLBACK because two messages were sent";
701 EXPECT_EQ(size_t(2), handler->messages.size())
702 << "no messages to handle";
703 EXPECT_EQ(MSG_TEST2, handler->messages[0].what)
704 << "handled message";
705 EXPECT_EQ(MSG_TEST4, handler->messages[1].what)
706 << "handled message";
707
708 result = mLooper->pollOnce(0);
709
710 EXPECT_EQ(Looper::POLL_TIMEOUT, result)
711 << "pollOnce result should be Looper::POLL_TIMEOUT because there was nothing to do";
712 EXPECT_EQ(size_t(2), handler->messages.size())
713 << "no more messages to handle";
714 }
715
716 class LooperEventCallback : public LooperCallback {
717 public:
718 using Callback = std::function<int(int fd, int events)>;
LooperEventCallback(Callback callback)719 explicit LooperEventCallback(Callback callback) : mCallback(std::move(callback)) {}
handleEvent(int fd,int events,void *)720 int handleEvent(int fd, int events, void* /*data*/) override { return mCallback(fd, events); }
721
722 private:
723 Callback mCallback;
724 };
725
726 // A utility class that allows for pipes to be added and removed from the looper, and polls the
727 // looper from a different thread.
728 class ThreadedLooperUtil {
729 public:
ThreadedLooperUtil(const sp<Looper> & looper)730 explicit ThreadedLooperUtil(const sp<Looper>& looper) : mLooper(looper), mRunning(true) {
731 mThread = std::thread([this]() {
732 while (mRunning) {
733 static constexpr std::chrono::milliseconds POLL_TIMEOUT(500);
734 mLooper->pollOnce(POLL_TIMEOUT.count());
735 }
736 });
737 }
738
~ThreadedLooperUtil()739 ~ThreadedLooperUtil() {
740 mRunning = false;
741 mThread.join();
742 }
743
744 // Create a new pipe, and return the write end of the pipe and the id used to track the pipe.
745 // The read end of the pipe is added to the looper.
createPipe()746 std::pair<int /*id*/, base::unique_fd> createPipe() {
747 int pipeFd[2];
748 if (pipe(pipeFd)) {
749 ADD_FAILURE() << "pipe() failed.";
750 return {};
751 }
752 const int readFd = pipeFd[0];
753 const int writeFd = pipeFd[1];
754
755 int id;
756 { // acquire lock
757 std::scoped_lock l(mLock);
758
759 id = mNextId++;
760 mFds.emplace(id, readFd);
761
762 auto removeCallback = [this, id, readFd](int fd, int events) {
763 EXPECT_EQ(readFd, fd) << "Received callback for incorrect fd.";
764 if ((events & Looper::EVENT_HANGUP) == 0) {
765 return 1; // Not a hangup, keep the callback.
766 }
767 removePipe(id);
768 return 0; // Remove the callback.
769 };
770
771 mLooper->addFd(readFd, 0, Looper::EVENT_INPUT,
772 new LooperEventCallback(std::move(removeCallback)), nullptr);
773 } // release lock
774
775 return {id, base::unique_fd(writeFd)};
776 }
777
778 // Remove the pipe with the given id.
removePipe(int id)779 void removePipe(int id) {
780 std::scoped_lock l(mLock);
781 if (mFds.find(id) == mFds.end()) {
782 return;
783 }
784 mLooper->removeFd(mFds[id].get());
785 mFds.erase(id);
786 }
787
788 // Check if the pipe with the given id exists and has not been removed.
hasPipe(int id)789 bool hasPipe(int id) {
790 std::scoped_lock l(mLock);
791 return mFds.find(id) != mFds.end();
792 }
793
794 private:
795 sp<Looper> mLooper;
796 std::atomic<bool> mRunning;
797 std::thread mThread;
798
799 std::mutex mLock;
800 std::unordered_map<int, base::unique_fd> mFds GUARDED_BY(mLock);
801 int mNextId GUARDED_BY(mLock) = 0;
802 };
803
TEST_F(LooperTest,MultiThreaded_NoUnexpectedFdRemoval)804 TEST_F(LooperTest, MultiThreaded_NoUnexpectedFdRemoval) {
805 ThreadedLooperUtil util(mLooper);
806
807 // Iterate repeatedly to try to recreate a flaky instance.
808 for (int i = 0; i < 1000; i++) {
809 auto [firstPipeId, firstPipeFd] = util.createPipe();
810 const int firstFdNumber = firstPipeFd.get();
811
812 // Close the first pipe's fd, causing a fd hangup.
813 firstPipeFd.reset();
814
815 // Request to remove the pipe from this test thread. This causes a race for pipe removal
816 // between the hangup in the looper's thread and this remove request from the test thread.
817 util.removePipe(firstPipeId);
818
819 // Create the second pipe. Since the fds for the first pipe are closed, this pipe should
820 // have the same fd numbers as the first pipe because the lowest unused fd number is used.
821 const auto [secondPipeId, fd] = util.createPipe();
822 EXPECT_EQ(firstFdNumber, fd.get())
823 << "The first and second fds must match for the purposes of this test.";
824
825 // Wait for unexpected hangup to occur.
826 std::this_thread::sleep_for(std::chrono::milliseconds(1));
827
828 ASSERT_TRUE(util.hasPipe(secondPipeId)) << "The second pipe was removed unexpectedly.";
829
830 util.removePipe(secondPipeId);
831 }
832 SUCCEED() << "No unexpectedly removed fds.";
833 }
834
835 } // namespace android
836