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
413 class LooperCallbackStub final : public LooperCallback {
414 public:
LooperCallbackStub(std::function<int ()> callback)415 LooperCallbackStub(std::function<int()> callback) : mCallback{callback} {}
416
handleEvent(int,int,void *)417 int handleEvent(int /*fd*/, int /*events*/, void* /*data*/) override { return mCallback(); }
418
419 private:
420 std::function<int()> mCallback;
421 };
422
TEST_F(LooperTest,getFdStateDebug_WhenFdIsInRequests_ReturnsTrue)423 TEST_F(LooperTest, getFdStateDebug_WhenFdIsInRequests_ReturnsTrue) {
424 Pipe pipe;
425 const int fd = pipe.receiveFd;
426 constexpr int expectedIdent{Looper::POLL_CALLBACK};
427 sp<LooperCallback> expectedCallback =
428 sp<LooperCallbackStub>::make([]() constexpr -> int { return 0; });
429 void* expectedData = this;
430
431 EXPECT_EQ(1, mLooper->addFd(fd, expectedIdent, Looper::EVENT_INPUT, expectedCallback,
432 expectedData));
433
434 int ident;
435 int events;
436 sp<LooperCallback> callback;
437 void* data;
438
439 EXPECT_TRUE(mLooper->getFdStateDebug(fd, &ident, &events, &callback, &data));
440
441 EXPECT_EQ(ident, expectedIdent);
442 EXPECT_EQ(events, Looper::EVENT_INPUT);
443 EXPECT_EQ(callback, expectedCallback);
444 EXPECT_EQ(data, expectedData);
445 }
446
TEST_F(LooperTest,getFdStateDebug_WhenFdIsNotInRequests_ReturnsFalse)447 TEST_F(LooperTest, getFdStateDebug_WhenFdIsNotInRequests_ReturnsFalse) {
448 Pipe pipe;
449 const int notAddedFd = pipe.receiveFd;
450
451 int ident;
452 int events;
453 sp<LooperCallback> callback;
454 void* data;
455
456 EXPECT_FALSE(mLooper->getFdStateDebug(notAddedFd, &ident, &events, &callback, &data));
457 }
458
TEST_F(LooperTest,RemoveFd_WhenCallbackNotAdded_ReturnsZero)459 TEST_F(LooperTest, RemoveFd_WhenCallbackNotAdded_ReturnsZero) {
460 int result = mLooper->removeFd(1);
461
462 EXPECT_EQ(0, result)
463 << "removeFd should return 0 because FD not registered";
464 }
465
TEST_F(LooperTest,RemoveFd_WhenCallbackAddedThenRemovedTwice_ReturnsOnceFirstTimeAndReturnsZeroSecondTime)466 TEST_F(LooperTest, RemoveFd_WhenCallbackAddedThenRemovedTwice_ReturnsOnceFirstTimeAndReturnsZeroSecondTime) {
467 Pipe pipe;
468 StubCallbackHandler handler(false);
469 handler.setCallback(mLooper, pipe.receiveFd, Looper::EVENT_INPUT);
470
471 // First time.
472 int result = mLooper->removeFd(pipe.receiveFd);
473
474 EXPECT_EQ(1, result)
475 << "removeFd should return 1 first time because FD was registered";
476
477 // Second time.
478 result = mLooper->removeFd(pipe.receiveFd);
479
480 EXPECT_EQ(0, result)
481 << "removeFd should return 0 second time because FD was no longer registered";
482 }
483
TEST_F(LooperTest,PollOnce_WhenCallbackAddedTwice_OnlySecondCallbackShouldBeInvoked)484 TEST_F(LooperTest, PollOnce_WhenCallbackAddedTwice_OnlySecondCallbackShouldBeInvoked) {
485 Pipe pipe;
486 StubCallbackHandler handler1(true);
487 StubCallbackHandler handler2(true);
488
489 handler1.setCallback(mLooper, pipe.receiveFd, Looper::EVENT_INPUT);
490 handler2.setCallback(mLooper, pipe.receiveFd, Looper::EVENT_INPUT); // replace it
491 pipe.writeSignal(); // would cause FD to be considered signalled
492
493 StopWatch stopWatch("pollOnce");
494 int result = mLooper->pollOnce(100);
495 int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
496
497 ASSERT_EQ(OK, pipe.readSignal())
498 << "signal should actually have been written";
499 EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS)
500 << "elapsed time should approx. zero because FD was already signalled";
501 EXPECT_EQ(Looper::POLL_CALLBACK, result)
502 << "pollOnce result should be Looper::POLL_CALLBACK because FD was signalled";
503 EXPECT_EQ(0, handler1.callbackCount)
504 << "original handler callback should not be invoked because it was replaced";
505 EXPECT_EQ(1, handler2.callbackCount)
506 << "replacement handler callback should be invoked";
507 }
508
TEST_F(LooperTest,SendMessage_WhenOneMessageIsEnqueue_ShouldInvokeHandlerDuringNextPoll)509 TEST_F(LooperTest, SendMessage_WhenOneMessageIsEnqueue_ShouldInvokeHandlerDuringNextPoll) {
510 sp<StubMessageHandler> handler = new StubMessageHandler();
511 mLooper->sendMessage(handler, Message(MSG_TEST1));
512
513 StopWatch stopWatch("pollOnce");
514 int result = mLooper->pollOnce(100);
515 int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
516
517 EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS)
518 << "elapsed time should approx. zero because message was already sent";
519 EXPECT_EQ(Looper::POLL_CALLBACK, result)
520 << "pollOnce result should be Looper::POLL_CALLBACK because message was sent";
521 EXPECT_EQ(size_t(1), handler->messages.size())
522 << "handled message";
523 EXPECT_EQ(MSG_TEST1, handler->messages[0].what)
524 << "handled message";
525 }
526
TEST_F(LooperTest,SendMessage_WhenMultipleMessagesAreEnqueued_ShouldInvokeHandlersInOrderDuringNextPoll)527 TEST_F(LooperTest, SendMessage_WhenMultipleMessagesAreEnqueued_ShouldInvokeHandlersInOrderDuringNextPoll) {
528 sp<StubMessageHandler> handler1 = new StubMessageHandler();
529 sp<StubMessageHandler> handler2 = new StubMessageHandler();
530 mLooper->sendMessage(handler1, Message(MSG_TEST1));
531 mLooper->sendMessage(handler2, Message(MSG_TEST2));
532 mLooper->sendMessage(handler1, Message(MSG_TEST3));
533 mLooper->sendMessage(handler1, Message(MSG_TEST4));
534
535 StopWatch stopWatch("pollOnce");
536 int result = mLooper->pollOnce(1000);
537 int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
538
539 EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS)
540 << "elapsed time should approx. zero because message was already sent";
541 EXPECT_EQ(Looper::POLL_CALLBACK, result)
542 << "pollOnce result should be Looper::POLL_CALLBACK because message was sent";
543 EXPECT_EQ(size_t(3), handler1->messages.size())
544 << "handled message";
545 EXPECT_EQ(MSG_TEST1, handler1->messages[0].what)
546 << "handled message";
547 EXPECT_EQ(MSG_TEST3, handler1->messages[1].what)
548 << "handled message";
549 EXPECT_EQ(MSG_TEST4, handler1->messages[2].what)
550 << "handled message";
551 EXPECT_EQ(size_t(1), handler2->messages.size())
552 << "handled message";
553 EXPECT_EQ(MSG_TEST2, handler2->messages[0].what)
554 << "handled message";
555 }
556
TEST_F(LooperTest,SendMessageDelayed_WhenSentToTheFuture_ShouldInvokeHandlerAfterDelayTime)557 TEST_F(LooperTest, SendMessageDelayed_WhenSentToTheFuture_ShouldInvokeHandlerAfterDelayTime) {
558 sp<StubMessageHandler> handler = new StubMessageHandler();
559 mLooper->sendMessageDelayed(ms2ns(100), handler, Message(MSG_TEST1));
560
561 StopWatch stopWatch("pollOnce");
562 int result = mLooper->pollOnce(1000);
563 int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
564
565 EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS)
566 << "first poll should end quickly because next message timeout was computed";
567 EXPECT_EQ(Looper::POLL_WAKE, result)
568 << "pollOnce result should be Looper::POLL_WAKE due to wakeup";
569 EXPECT_EQ(size_t(0), handler->messages.size())
570 << "no message handled yet";
571
572 result = mLooper->pollOnce(1000);
573 elapsedMillis = ns2ms(stopWatch.elapsedTime());
574
575 EXPECT_EQ(size_t(1), handler->messages.size())
576 << "handled message";
577 EXPECT_EQ(MSG_TEST1, handler->messages[0].what)
578 << "handled message";
579 EXPECT_NEAR(100, elapsedMillis, TIMING_TOLERANCE_MS)
580 << "second poll should end around the time of the delayed message dispatch";
581 EXPECT_EQ(Looper::POLL_CALLBACK, result)
582 << "pollOnce result should be Looper::POLL_CALLBACK because message was sent";
583
584 result = mLooper->pollOnce(100);
585 elapsedMillis = ns2ms(stopWatch.elapsedTime());
586
587 EXPECT_NEAR(100 + 100, elapsedMillis, TIMING_TOLERANCE_MS)
588 << "third poll should timeout";
589 EXPECT_EQ(Looper::POLL_TIMEOUT, result)
590 << "pollOnce result should be Looper::POLL_TIMEOUT because there were no messages left";
591 }
592
TEST_F(LooperTest,SendMessageDelayed_WhenSentToThePast_ShouldInvokeHandlerDuringNextPoll)593 TEST_F(LooperTest, SendMessageDelayed_WhenSentToThePast_ShouldInvokeHandlerDuringNextPoll) {
594 sp<StubMessageHandler> handler = new StubMessageHandler();
595 mLooper->sendMessageDelayed(ms2ns(-1000), handler, Message(MSG_TEST1));
596
597 StopWatch stopWatch("pollOnce");
598 int result = mLooper->pollOnce(100);
599 int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
600
601 EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS)
602 << "elapsed time should approx. zero because message was already sent";
603 EXPECT_EQ(Looper::POLL_CALLBACK, result)
604 << "pollOnce result should be Looper::POLL_CALLBACK because message was sent";
605 EXPECT_EQ(size_t(1), handler->messages.size())
606 << "handled message";
607 EXPECT_EQ(MSG_TEST1, handler->messages[0].what)
608 << "handled message";
609 }
610
TEST_F(LooperTest,SendMessageDelayed_WhenSentToThePresent_ShouldInvokeHandlerDuringNextPoll)611 TEST_F(LooperTest, SendMessageDelayed_WhenSentToThePresent_ShouldInvokeHandlerDuringNextPoll) {
612 sp<StubMessageHandler> handler = new StubMessageHandler();
613 mLooper->sendMessageDelayed(0, handler, Message(MSG_TEST1));
614
615 StopWatch stopWatch("pollOnce");
616 int result = mLooper->pollOnce(100);
617 int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
618
619 EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS)
620 << "elapsed time should approx. zero because message was already sent";
621 EXPECT_EQ(Looper::POLL_CALLBACK, result)
622 << "pollOnce result should be Looper::POLL_CALLBACK because message was sent";
623 EXPECT_EQ(size_t(1), handler->messages.size())
624 << "handled message";
625 EXPECT_EQ(MSG_TEST1, handler->messages[0].what)
626 << "handled message";
627 }
628
TEST_F(LooperTest,SendMessageAtTime_WhenSentToTheFuture_ShouldInvokeHandlerAfterDelayTime)629 TEST_F(LooperTest, SendMessageAtTime_WhenSentToTheFuture_ShouldInvokeHandlerAfterDelayTime) {
630 nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
631 sp<StubMessageHandler> handler = new StubMessageHandler();
632 mLooper->sendMessageAtTime(now + ms2ns(100), handler, Message(MSG_TEST1));
633
634 StopWatch stopWatch("pollOnce");
635 int result = mLooper->pollOnce(1000);
636 int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
637
638 EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS)
639 << "first poll should end quickly because next message timeout was computed";
640 EXPECT_EQ(Looper::POLL_WAKE, result)
641 << "pollOnce result should be Looper::POLL_WAKE due to wakeup";
642 EXPECT_EQ(size_t(0), handler->messages.size())
643 << "no message handled yet";
644
645 result = mLooper->pollOnce(1000);
646 elapsedMillis = ns2ms(stopWatch.elapsedTime());
647
648 EXPECT_EQ(size_t(1), handler->messages.size())
649 << "handled message";
650 EXPECT_EQ(MSG_TEST1, handler->messages[0].what)
651 << "handled message";
652 EXPECT_NEAR(100, elapsedMillis, TIMING_TOLERANCE_MS)
653 << "second poll should end around the time of the delayed message dispatch";
654 EXPECT_EQ(Looper::POLL_CALLBACK, result)
655 << "pollOnce result should be Looper::POLL_CALLBACK because message was sent";
656
657 result = mLooper->pollOnce(100);
658 elapsedMillis = ns2ms(stopWatch.elapsedTime());
659
660 EXPECT_NEAR(100 + 100, elapsedMillis, TIMING_TOLERANCE_MS)
661 << "third poll should timeout";
662 EXPECT_EQ(Looper::POLL_TIMEOUT, result)
663 << "pollOnce result should be Looper::POLL_TIMEOUT because there were no messages left";
664 }
665
TEST_F(LooperTest,SendMessageAtTime_WhenSentToThePast_ShouldInvokeHandlerDuringNextPoll)666 TEST_F(LooperTest, SendMessageAtTime_WhenSentToThePast_ShouldInvokeHandlerDuringNextPoll) {
667 nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
668 sp<StubMessageHandler> handler = new StubMessageHandler();
669 mLooper->sendMessageAtTime(now - ms2ns(1000), handler, Message(MSG_TEST1));
670
671 StopWatch stopWatch("pollOnce");
672 int result = mLooper->pollOnce(100);
673 int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
674
675 EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS)
676 << "elapsed time should approx. zero because message was already sent";
677 EXPECT_EQ(Looper::POLL_CALLBACK, result)
678 << "pollOnce result should be Looper::POLL_CALLBACK because message was sent";
679 EXPECT_EQ(size_t(1), handler->messages.size())
680 << "handled message";
681 EXPECT_EQ(MSG_TEST1, handler->messages[0].what)
682 << "handled message";
683 }
684
TEST_F(LooperTest,SendMessageAtTime_WhenSentToThePresent_ShouldInvokeHandlerDuringNextPoll)685 TEST_F(LooperTest, SendMessageAtTime_WhenSentToThePresent_ShouldInvokeHandlerDuringNextPoll) {
686 nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
687 sp<StubMessageHandler> handler = new StubMessageHandler();
688 mLooper->sendMessageAtTime(now, handler, Message(MSG_TEST1));
689
690 StopWatch stopWatch("pollOnce");
691 int result = mLooper->pollOnce(100);
692 int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
693
694 EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS)
695 << "elapsed time should approx. zero because message was already sent";
696 EXPECT_EQ(Looper::POLL_CALLBACK, result)
697 << "pollOnce result should be Looper::POLL_CALLBACK because message was sent";
698 EXPECT_EQ(size_t(1), handler->messages.size())
699 << "handled message";
700 EXPECT_EQ(MSG_TEST1, handler->messages[0].what)
701 << "handled message";
702 }
703
TEST_F(LooperTest,RemoveMessage_WhenRemovingAllMessagesForHandler_ShouldRemoveThoseMessage)704 TEST_F(LooperTest, RemoveMessage_WhenRemovingAllMessagesForHandler_ShouldRemoveThoseMessage) {
705 sp<StubMessageHandler> handler = new StubMessageHandler();
706 mLooper->sendMessage(handler, Message(MSG_TEST1));
707 mLooper->sendMessage(handler, Message(MSG_TEST2));
708 mLooper->sendMessage(handler, Message(MSG_TEST3));
709 mLooper->removeMessages(handler);
710
711 StopWatch stopWatch("pollOnce");
712 int result = mLooper->pollOnce(0);
713 int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
714
715 EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS)
716 << "elapsed time should approx. zero because message was sent so looper was awoken";
717 EXPECT_EQ(Looper::POLL_WAKE, result)
718 << "pollOnce result should be Looper::POLL_WAKE because looper was awoken";
719 EXPECT_EQ(size_t(0), handler->messages.size())
720 << "no messages to handle";
721
722 result = mLooper->pollOnce(0);
723
724 EXPECT_EQ(Looper::POLL_TIMEOUT, result)
725 << "pollOnce result should be Looper::POLL_TIMEOUT because there was nothing to do";
726 EXPECT_EQ(size_t(0), handler->messages.size())
727 << "no messages to handle";
728 }
729
TEST_F(LooperTest,RemoveMessage_WhenRemovingSomeMessagesForHandler_ShouldRemoveThoseMessage)730 TEST_F(LooperTest, RemoveMessage_WhenRemovingSomeMessagesForHandler_ShouldRemoveThoseMessage) {
731 sp<StubMessageHandler> handler = new StubMessageHandler();
732 mLooper->sendMessage(handler, Message(MSG_TEST1));
733 mLooper->sendMessage(handler, Message(MSG_TEST2));
734 mLooper->sendMessage(handler, Message(MSG_TEST3));
735 mLooper->sendMessage(handler, Message(MSG_TEST4));
736 mLooper->removeMessages(handler, MSG_TEST3);
737 mLooper->removeMessages(handler, MSG_TEST1);
738
739 StopWatch stopWatch("pollOnce");
740 int result = mLooper->pollOnce(0);
741 int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
742
743 EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS)
744 << "elapsed time should approx. zero because message was sent so looper was awoken";
745 EXPECT_EQ(Looper::POLL_CALLBACK, result)
746 << "pollOnce result should be Looper::POLL_CALLBACK because two messages were sent";
747 EXPECT_EQ(size_t(2), handler->messages.size())
748 << "no messages to handle";
749 EXPECT_EQ(MSG_TEST2, handler->messages[0].what)
750 << "handled message";
751 EXPECT_EQ(MSG_TEST4, handler->messages[1].what)
752 << "handled message";
753
754 result = mLooper->pollOnce(0);
755
756 EXPECT_EQ(Looper::POLL_TIMEOUT, result)
757 << "pollOnce result should be Looper::POLL_TIMEOUT because there was nothing to do";
758 EXPECT_EQ(size_t(2), handler->messages.size())
759 << "no more messages to handle";
760 }
761
762 class LooperEventCallback : public LooperCallback {
763 public:
764 using Callback = std::function<int(int fd, int events)>;
LooperEventCallback(Callback callback)765 explicit LooperEventCallback(Callback callback) : mCallback(std::move(callback)) {}
handleEvent(int fd,int events,void *)766 int handleEvent(int fd, int events, void* /*data*/) override { return mCallback(fd, events); }
767
768 private:
769 Callback mCallback;
770 };
771
772 // A utility class that allows for pipes to be added and removed from the looper, and polls the
773 // looper from a different thread.
774 class ThreadedLooperUtil {
775 public:
ThreadedLooperUtil(const sp<Looper> & looper)776 explicit ThreadedLooperUtil(const sp<Looper>& looper) : mLooper(looper), mRunning(true) {
777 mThread = std::thread([this]() {
778 while (mRunning) {
779 static constexpr std::chrono::milliseconds POLL_TIMEOUT(500);
780 mLooper->pollOnce(POLL_TIMEOUT.count());
781 }
782 });
783 }
784
~ThreadedLooperUtil()785 ~ThreadedLooperUtil() {
786 mRunning = false;
787 mThread.join();
788 }
789
790 // Create a new pipe, and return the write end of the pipe and the id used to track the pipe.
791 // The read end of the pipe is added to the looper.
createPipe()792 std::pair<int /*id*/, base::unique_fd> createPipe() {
793 int pipeFd[2];
794 if (pipe(pipeFd)) {
795 ADD_FAILURE() << "pipe() failed.";
796 return {};
797 }
798 const int readFd = pipeFd[0];
799 const int writeFd = pipeFd[1];
800
801 int id;
802 { // acquire lock
803 std::scoped_lock l(mLock);
804
805 id = mNextId++;
806 mFds.emplace(id, readFd);
807
808 auto removeCallback = [this, id, readFd](int fd, int events) {
809 EXPECT_EQ(readFd, fd) << "Received callback for incorrect fd.";
810 if ((events & Looper::EVENT_HANGUP) == 0) {
811 return 1; // Not a hangup, keep the callback.
812 }
813 removePipe(id);
814 return 0; // Remove the callback.
815 };
816
817 mLooper->addFd(readFd, 0, Looper::EVENT_INPUT,
818 new LooperEventCallback(std::move(removeCallback)), nullptr);
819 } // release lock
820
821 return {id, base::unique_fd(writeFd)};
822 }
823
824 // Remove the pipe with the given id.
removePipe(int id)825 void removePipe(int id) {
826 std::scoped_lock l(mLock);
827 if (mFds.find(id) == mFds.end()) {
828 return;
829 }
830 mLooper->removeFd(mFds[id].get());
831 mFds.erase(id);
832 }
833
834 // Check if the pipe with the given id exists and has not been removed.
hasPipe(int id)835 bool hasPipe(int id) {
836 std::scoped_lock l(mLock);
837 return mFds.find(id) != mFds.end();
838 }
839
840 private:
841 sp<Looper> mLooper;
842 std::atomic<bool> mRunning;
843 std::thread mThread;
844
845 std::mutex mLock;
846 std::unordered_map<int, base::unique_fd> mFds GUARDED_BY(mLock);
847 int mNextId GUARDED_BY(mLock) = 0;
848 };
849
TEST_F(LooperTest,MultiThreaded_NoUnexpectedFdRemoval)850 TEST_F(LooperTest, MultiThreaded_NoUnexpectedFdRemoval) {
851 ThreadedLooperUtil util(mLooper);
852
853 // Iterate repeatedly to try to recreate a flaky instance.
854 for (int i = 0; i < 1000; i++) {
855 auto [firstPipeId, firstPipeFd] = util.createPipe();
856 const int firstFdNumber = firstPipeFd.get();
857
858 // Close the first pipe's fd, causing a fd hangup.
859 firstPipeFd.reset();
860
861 // Request to remove the pipe from this test thread. This causes a race for pipe removal
862 // between the hangup in the looper's thread and this remove request from the test thread.
863 util.removePipe(firstPipeId);
864
865 // Create the second pipe. Since the fds for the first pipe are closed, this pipe should
866 // have the same fd numbers as the first pipe because the lowest unused fd number is used.
867 const auto [secondPipeId, fd] = util.createPipe();
868 EXPECT_EQ(firstFdNumber, fd.get())
869 << "The first and second fds must match for the purposes of this test.";
870
871 // Wait for unexpected hangup to occur.
872 std::this_thread::sleep_for(std::chrono::milliseconds(1));
873
874 ASSERT_TRUE(util.hasPipe(secondPipeId)) << "The second pipe was removed unexpectedly.";
875
876 util.removePipe(secondPipeId);
877 }
878 SUCCEED() << "No unexpectedly removed fds.";
879 }
880
881 } // namespace android
882