xref: /aosp_15_r20/system/core/libutils/Looper_test.cpp (revision 00c7fec1bb09f3284aad6a6f96d2f63dfc3650ad)
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