blob: c859f9c61802fc80ec9d82ffcbde97a4272bd655 [file] [log] [blame]
Jeff Brown7901eb22010-09-13 23:17:30 -07001//
2// Copyright 2010 The Android Open Source Project
3//
4
Jeff Brown7901eb22010-09-13 23:17:30 -07005#include <gtest/gtest.h>
Jeff Brown7901eb22010-09-13 23:17:30 -07006#include <time.h>
Dylan Katz7168f272020-07-02 11:51:44 -07007#include <unistd.h>
8#include <utils/Looper.h>
9#include <utils/StopWatch.h>
10#include <utils/Timers.h>
Prabir Pradhan729057a2021-08-12 12:36:31 -070011#include <thread>
12#include <unordered_map>
13#include <utility>
Dylan Katz7168f272020-07-02 11:51:44 -070014#include "Looper_test_pipe.h"
Jeff Brown7901eb22010-09-13 23:17:30 -070015
Elliott Hughes01705e42019-02-07 12:41:37 -080016#include <utils/threads.h>
Jeff Brown7901eb22010-09-13 23:17:30 -070017
Steven Morelandc1e04d82019-09-18 12:12:11 -070018// b/141212746 - increased for virtual platforms with higher volatility
Jeff Brown7901eb22010-09-13 23:17:30 -070019// # of milliseconds to fudge stopwatch measurements
Steven Morelandc1e04d82019-09-18 12:12:11 -070020#define TIMING_TOLERANCE_MS 100
Jeff Brown7901eb22010-09-13 23:17:30 -070021
22namespace android {
23
Jeff Brown3e2e38b2011-03-02 14:41:58 -080024enum {
25 MSG_TEST1 = 1,
26 MSG_TEST2 = 2,
27 MSG_TEST3 = 3,
28 MSG_TEST4 = 4,
29};
30
Elliott Hughes01705e42019-02-07 12:41:37 -080031class DelayedTask : public Thread {
32 int mDelayMillis;
33
34public:
35 explicit DelayedTask(int delayMillis) : mDelayMillis(delayMillis) { }
36
37protected:
38 virtual ~DelayedTask() { }
39
40 virtual void doTask() = 0;
41
42 virtual bool threadLoop() {
43 usleep(mDelayMillis * 1000);
44 doTask();
45 return false;
46 }
47};
48
Jeff Brown7901eb22010-09-13 23:17:30 -070049class DelayedWake : public DelayedTask {
50 sp<Looper> mLooper;
51
52public:
53 DelayedWake(int delayMillis, const sp<Looper> looper) :
54 DelayedTask(delayMillis), mLooper(looper) {
55 }
56
57protected:
58 virtual void doTask() {
59 mLooper->wake();
60 }
61};
62
63class DelayedWriteSignal : public DelayedTask {
64 Pipe* mPipe;
65
66public:
67 DelayedWriteSignal(int delayMillis, Pipe* pipe) :
68 DelayedTask(delayMillis), mPipe(pipe) {
69 }
70
71protected:
72 virtual void doTask() {
73 mPipe->writeSignal();
74 }
75};
76
77class CallbackHandler {
78public:
79 void setCallback(const sp<Looper>& looper, int fd, int events) {
80 looper->addFd(fd, 0, events, staticHandler, this);
81 }
82
83protected:
84 virtual ~CallbackHandler() { }
85
86 virtual int handler(int fd, int events) = 0;
87
88private:
89 static int staticHandler(int fd, int events, void* data) {
90 return static_cast<CallbackHandler*>(data)->handler(fd, events);
91 }
92};
93
94class StubCallbackHandler : public CallbackHandler {
95public:
96 int nextResult;
97 int callbackCount;
98
99 int fd;
100 int events;
101
Chih-Hung Hsieh034c4752016-07-12 13:50:44 -0700102 explicit StubCallbackHandler(int nextResult) : nextResult(nextResult),
Jeff Brown7901eb22010-09-13 23:17:30 -0700103 callbackCount(0), fd(-1), events(-1) {
104 }
105
106protected:
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
Jeff Brown3e2e38b2011-03-02 14:41:58 -0800115class StubMessageHandler : public MessageHandler {
116public:
117 Vector<Message> messages;
118
119 virtual void handleMessage(const Message& message) {
120 messages.push(message);
121 }
122};
123
Jeff Brown7901eb22010-09-13 23:17:30 -0700124class LooperTest : public testing::Test {
125protected:
126 sp<Looper> mLooper;
127
128 virtual void SetUp() {
129 mLooper = new Looper(true);
130 }
131
132 virtual void TearDown() {
133 mLooper.clear();
134 }
135};
136
137
138TEST_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";
Brian Carlstrom1693d7e2013-12-11 22:46:45 -0800145 EXPECT_EQ(Looper::POLL_TIMEOUT, result)
146 << "pollOnce result should be LOOPER_POLL_TIMEOUT";
Jeff Brown7901eb22010-09-13 23:17:30 -0700147}
148
149TEST_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";
Brian Carlstrom1693d7e2013-12-11 22:46:45 -0800158 EXPECT_EQ(Looper::POLL_WAKE, result)
159 << "pollOnce result should be Looper::POLL_CALLBACK because loop was awoken";
Jeff Brown7901eb22010-09-13 23:17:30 -0700160}
161
162TEST_F(LooperTest, PollOnce_WhenNonZeroTimeoutAndAwokenWhileWaiting_PromptlyReturns) {
163 sp<DelayedWake> delayedWake = new DelayedWake(100, mLooper);
Brian Carlstrome71b9142016-03-12 16:08:12 -0800164 delayedWake->run("LooperTest");
Jeff Brown7901eb22010-09-13 23:17:30 -0700165
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";
Brian Carlstrom1693d7e2013-12-11 22:46:45 -0800172 EXPECT_EQ(Looper::POLL_WAKE, result)
173 << "pollOnce result should be Looper::POLL_CALLBACK because loop was awoken";
Jeff Brown7901eb22010-09-13 23:17:30 -0700174}
175
176TEST_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";
Brian Carlstrom1693d7e2013-12-11 22:46:45 -0800183 EXPECT_EQ(Looper::POLL_TIMEOUT, result)
184 << "pollOnce result should be Looper::POLL_TIMEOUT";
Jeff Brown7901eb22010-09-13 23:17:30 -0700185}
186
187TEST_F(LooperTest, PollOnce_WhenZeroTimeoutAndNoSignalledFDs_ImmediatelyReturns) {
188 Pipe pipe;
189 StubCallbackHandler handler(true);
190
Brian Carlstrom1693d7e2013-12-11 22:46:45 -0800191 handler.setCallback(mLooper, pipe.receiveFd, Looper::EVENT_INPUT);
Jeff Brown7901eb22010-09-13 23:17:30 -0700192
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";
Brian Carlstrom1693d7e2013-12-11 22:46:45 -0800199 EXPECT_EQ(Looper::POLL_TIMEOUT, result)
200 << "pollOnce result should be Looper::POLL_TIMEOUT";
Jeff Brown7901eb22010-09-13 23:17:30 -0700201 EXPECT_EQ(0, handler.callbackCount)
202 << "callback should not have been invoked because FD was not signalled";
203}
204
205TEST_F(LooperTest, PollOnce_WhenZeroTimeoutAndSignalledFD_ImmediatelyInvokesCallbackAndReturns) {
206 Pipe pipe;
207 StubCallbackHandler handler(true);
208
209 ASSERT_EQ(OK, pipe.writeSignal());
Brian Carlstrom1693d7e2013-12-11 22:46:45 -0800210 handler.setCallback(mLooper, pipe.receiveFd, Looper::EVENT_INPUT);
Jeff Brown7901eb22010-09-13 23:17:30 -0700211
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";
Brian Carlstrom1693d7e2013-12-11 22:46:45 -0800218 EXPECT_EQ(Looper::POLL_CALLBACK, result)
219 << "pollOnce result should be Looper::POLL_CALLBACK because FD was signalled";
Jeff Brown7901eb22010-09-13 23:17:30 -0700220 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";
Brian Carlstrom1693d7e2013-12-11 22:46:45 -0800224 EXPECT_EQ(Looper::EVENT_INPUT, handler.events)
225 << "callback should have received Looper::EVENT_INPUT as events";
Jeff Brown7901eb22010-09-13 23:17:30 -0700226}
227
228TEST_F(LooperTest, PollOnce_WhenNonZeroTimeoutAndNoSignalledFDs_WaitsForTimeoutAndReturns) {
229 Pipe pipe;
230 StubCallbackHandler handler(true);
231
Brian Carlstrom1693d7e2013-12-11 22:46:45 -0800232 handler.setCallback(mLooper, pipe.receiveFd, Looper::EVENT_INPUT);
Jeff Brown7901eb22010-09-13 23:17:30 -0700233
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";
Brian Carlstrom1693d7e2013-12-11 22:46:45 -0800240 EXPECT_EQ(Looper::POLL_TIMEOUT, result)
241 << "pollOnce result should be Looper::POLL_TIMEOUT";
Jeff Brown7901eb22010-09-13 23:17:30 -0700242 EXPECT_EQ(0, handler.callbackCount)
243 << "callback should not have been invoked because FD was not signalled";
244}
245
246TEST_F(LooperTest, PollOnce_WhenNonZeroTimeoutAndSignalledFDBeforeWaiting_ImmediatelyInvokesCallbackAndReturns) {
247 Pipe pipe;
248 StubCallbackHandler handler(true);
249
250 pipe.writeSignal();
Brian Carlstrom1693d7e2013-12-11 22:46:45 -0800251 handler.setCallback(mLooper, pipe.receiveFd, Looper::EVENT_INPUT);
Jeff Brown7901eb22010-09-13 23:17:30 -0700252
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";
Brian Carlstrom1693d7e2013-12-11 22:46:45 -0800261 EXPECT_EQ(Looper::POLL_CALLBACK, result)
262 << "pollOnce result should be Looper::POLL_CALLBACK because FD was signalled";
Jeff Brown7901eb22010-09-13 23:17:30 -0700263 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";
Brian Carlstrom1693d7e2013-12-11 22:46:45 -0800267 EXPECT_EQ(Looper::EVENT_INPUT, handler.events)
268 << "callback should have received Looper::EVENT_INPUT as events";
Jeff Brown7901eb22010-09-13 23:17:30 -0700269}
270
271TEST_F(LooperTest, PollOnce_WhenNonZeroTimeoutAndSignalledFDWhileWaiting_PromptlyInvokesCallbackAndReturns) {
272 Pipe pipe;
273 StubCallbackHandler handler(true);
274 sp<DelayedWriteSignal> delayedWriteSignal = new DelayedWriteSignal(100, & pipe);
275
Brian Carlstrom1693d7e2013-12-11 22:46:45 -0800276 handler.setCallback(mLooper, pipe.receiveFd, Looper::EVENT_INPUT);
Brian Carlstrome71b9142016-03-12 16:08:12 -0800277 delayedWriteSignal->run("LooperTest");
Jeff Brown7901eb22010-09-13 23:17:30 -0700278
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";
Brian Carlstrom1693d7e2013-12-11 22:46:45 -0800287 EXPECT_EQ(Looper::POLL_CALLBACK, result)
288 << "pollOnce result should be Looper::POLL_CALLBACK because FD was signalled";
Jeff Brown7901eb22010-09-13 23:17:30 -0700289 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";
Brian Carlstrom1693d7e2013-12-11 22:46:45 -0800293 EXPECT_EQ(Looper::EVENT_INPUT, handler.events)
294 << "callback should have received Looper::EVENT_INPUT as events";
Jeff Brown7901eb22010-09-13 23:17:30 -0700295}
296
297TEST_F(LooperTest, PollOnce_WhenCallbackAddedThenRemoved_CallbackShouldNotBeInvoked) {
298 Pipe pipe;
299 StubCallbackHandler handler(true);
300
Brian Carlstrom1693d7e2013-12-11 22:46:45 -0800301 handler.setCallback(mLooper, pipe.receiveFd, Looper::EVENT_INPUT);
Jeff Brown7901eb22010-09-13 23:17:30 -0700302 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";
Brian Carlstrom1693d7e2013-12-11 22:46:45 -0800313 EXPECT_EQ(Looper::POLL_TIMEOUT, result)
314 << "pollOnce result should be Looper::POLL_TIMEOUT";
Jeff Brown7901eb22010-09-13 23:17:30 -0700315 EXPECT_EQ(0, handler.callbackCount)
316 << "callback should not be invoked";
317}
318
319TEST_F(LooperTest, PollOnce_WhenCallbackReturnsFalse_CallbackShouldNotBeInvokedAgainLater) {
320 Pipe pipe;
321 StubCallbackHandler handler(false);
322
Brian Carlstrom1693d7e2013-12-11 22:46:45 -0800323 handler.setCallback(mLooper, pipe.receiveFd, Looper::EVENT_INPUT);
Jeff Brown7901eb22010-09-13 23:17:30 -0700324
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";
Brian Carlstrom1693d7e2013-12-11 22:46:45 -0800336 EXPECT_EQ(Looper::POLL_CALLBACK, result)
337 << "pollOnce result should be Looper::POLL_CALLBACK because FD was signalled";
Jeff Brown7901eb22010-09-13 23:17:30 -0700338 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";
Brian Carlstrom1693d7e2013-12-11 22:46:45 -0800352 EXPECT_EQ(Looper::POLL_TIMEOUT, result)
353 << "pollOnce result should be Looper::POLL_TIMEOUT";
Jeff Brown7901eb22010-09-13 23:17:30 -0700354 EXPECT_EQ(1, handler.callbackCount)
355 << "callback should not be invoked this time";
356}
357
358TEST_F(LooperTest, PollOnce_WhenNonCallbackFdIsSignalled_ReturnsIdent) {
359 const int expectedIdent = 5;
360 void* expectedData = this;
361
362 Pipe pipe;
363
364 pipe.writeSignal();
Yi Konge1731a42018-07-16 18:11:34 -0700365 mLooper->addFd(pipe.receiveFd, expectedIdent, Looper::EVENT_INPUT, nullptr, expectedData);
Jeff Brown7901eb22010-09-13 23:17:30 -0700366
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";
Brian Carlstrom1693d7e2013-12-11 22:46:45 -0800382 EXPECT_EQ(Looper::EVENT_INPUT, events)
383 << "pollOnce should have returned Looper::EVENT_INPUT as events";
Jeff Brown7901eb22010-09-13 23:17:30 -0700384 EXPECT_EQ(expectedData, data)
385 << "pollOnce should have returned the data";
386}
387
388TEST_F(LooperTest, AddFd_WhenCallbackAdded_ReturnsOne) {
389 Pipe pipe;
Yi Konge1731a42018-07-16 18:11:34 -0700390 int result = mLooper->addFd(pipe.receiveFd, 0, Looper::EVENT_INPUT, nullptr, nullptr);
Jeff Brown7901eb22010-09-13 23:17:30 -0700391
392 EXPECT_EQ(1, result)
393 << "addFd should return 1 because FD was added";
394}
395
Jeff Brown7901eb22010-09-13 23:17:30 -0700396TEST_F(LooperTest, AddFd_WhenIdentIsNegativeAndCallbackIsNull_ReturnsError) {
397 Pipe pipe;
Yi Konge1731a42018-07-16 18:11:34 -0700398 int result = mLooper->addFd(pipe.receiveFd, -1, Looper::EVENT_INPUT, nullptr, nullptr);
Jeff Brown7901eb22010-09-13 23:17:30 -0700399
400 EXPECT_EQ(-1, result)
401 << "addFd should return -1 because arguments were invalid";
402}
403
404TEST_F(LooperTest, AddFd_WhenNoCallbackAndAllowNonCallbacksIsFalse_ReturnsError) {
405 Pipe pipe;
406 sp<Looper> looper = new Looper(false /*allowNonCallbacks*/);
Yi Konge1731a42018-07-16 18:11:34 -0700407 int result = looper->addFd(pipe.receiveFd, 0, 0, nullptr, nullptr);
Jeff Brown7901eb22010-09-13 23:17:30 -0700408
409 EXPECT_EQ(-1, result)
410 << "addFd should return -1 because arguments were invalid";
411}
412
413TEST_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
420TEST_F(LooperTest, RemoveFd_WhenCallbackAddedThenRemovedTwice_ReturnsOnceFirstTimeAndReturnsZeroSecondTime) {
421 Pipe pipe;
422 StubCallbackHandler handler(false);
Brian Carlstrom1693d7e2013-12-11 22:46:45 -0800423 handler.setCallback(mLooper, pipe.receiveFd, Looper::EVENT_INPUT);
Jeff Brown7901eb22010-09-13 23:17:30 -0700424
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
438TEST_F(LooperTest, PollOnce_WhenCallbackAddedTwice_OnlySecondCallbackShouldBeInvoked) {
439 Pipe pipe;
440 StubCallbackHandler handler1(true);
441 StubCallbackHandler handler2(true);
442
Brian Carlstrom1693d7e2013-12-11 22:46:45 -0800443 handler1.setCallback(mLooper, pipe.receiveFd, Looper::EVENT_INPUT);
444 handler2.setCallback(mLooper, pipe.receiveFd, Looper::EVENT_INPUT); // replace it
Jeff Brown7901eb22010-09-13 23:17:30 -0700445 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";
Brian Carlstrom1693d7e2013-12-11 22:46:45 -0800455 EXPECT_EQ(Looper::POLL_CALLBACK, result)
456 << "pollOnce result should be Looper::POLL_CALLBACK because FD was signalled";
Jeff Brown7901eb22010-09-13 23:17:30 -0700457 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
Jeff Brown3e2e38b2011-03-02 14:41:58 -0800463TEST_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";
Brian Carlstrom1693d7e2013-12-11 22:46:45 -0800473 EXPECT_EQ(Looper::POLL_CALLBACK, result)
474 << "pollOnce result should be Looper::POLL_CALLBACK because message was sent";
Jeff Brown3e2e38b2011-03-02 14:41:58 -0800475 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
481TEST_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";
Brian Carlstrom1693d7e2013-12-11 22:46:45 -0800495 EXPECT_EQ(Looper::POLL_CALLBACK, result)
496 << "pollOnce result should be Looper::POLL_CALLBACK because message was sent";
Jeff Brown3e2e38b2011-03-02 14:41:58 -0800497 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
511TEST_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";
Brian Carlstrom1693d7e2013-12-11 22:46:45 -0800521 EXPECT_EQ(Looper::POLL_WAKE, result)
522 << "pollOnce result should be Looper::POLL_WAKE due to wakeup";
Jeff Brown3e2e38b2011-03-02 14:41:58 -0800523 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";
Brian Carlstrom1693d7e2013-12-11 22:46:45 -0800535 EXPECT_EQ(Looper::POLL_CALLBACK, result)
536 << "pollOnce result should be Looper::POLL_CALLBACK because message was sent";
Jeff Brown3e2e38b2011-03-02 14:41:58 -0800537
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";
Brian Carlstrom1693d7e2013-12-11 22:46:45 -0800543 EXPECT_EQ(Looper::POLL_TIMEOUT, result)
544 << "pollOnce result should be Looper::POLL_TIMEOUT because there were no messages left";
Jeff Brown3e2e38b2011-03-02 14:41:58 -0800545}
546
547TEST_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";
Brian Carlstrom1693d7e2013-12-11 22:46:45 -0800557 EXPECT_EQ(Looper::POLL_CALLBACK, result)
558 << "pollOnce result should be Looper::POLL_CALLBACK because message was sent";
Jeff Brown3e2e38b2011-03-02 14:41:58 -0800559 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
565TEST_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";
Brian Carlstrom1693d7e2013-12-11 22:46:45 -0800575 EXPECT_EQ(Looper::POLL_CALLBACK, result)
576 << "pollOnce result should be Looper::POLL_CALLBACK because message was sent";
Jeff Brown3e2e38b2011-03-02 14:41:58 -0800577 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
583TEST_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";
Brian Carlstrom1693d7e2013-12-11 22:46:45 -0800594 EXPECT_EQ(Looper::POLL_WAKE, result)
595 << "pollOnce result should be Looper::POLL_WAKE due to wakeup";
Jeff Brown3e2e38b2011-03-02 14:41:58 -0800596 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";
Brian Carlstrom1693d7e2013-12-11 22:46:45 -0800608 EXPECT_EQ(Looper::POLL_CALLBACK, result)
609 << "pollOnce result should be Looper::POLL_CALLBACK because message was sent";
Jeff Brown3e2e38b2011-03-02 14:41:58 -0800610
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";
Brian Carlstrom1693d7e2013-12-11 22:46:45 -0800616 EXPECT_EQ(Looper::POLL_TIMEOUT, result)
617 << "pollOnce result should be Looper::POLL_TIMEOUT because there were no messages left";
Jeff Brown3e2e38b2011-03-02 14:41:58 -0800618}
619
620TEST_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";
Brian Carlstrom1693d7e2013-12-11 22:46:45 -0800631 EXPECT_EQ(Looper::POLL_CALLBACK, result)
632 << "pollOnce result should be Looper::POLL_CALLBACK because message was sent";
Jeff Brown3e2e38b2011-03-02 14:41:58 -0800633 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
639TEST_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";
Brian Carlstrom1693d7e2013-12-11 22:46:45 -0800650 EXPECT_EQ(Looper::POLL_CALLBACK, result)
651 << "pollOnce result should be Looper::POLL_CALLBACK because message was sent";
Jeff Brown3e2e38b2011-03-02 14:41:58 -0800652 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
658TEST_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";
Brian Carlstrom1693d7e2013-12-11 22:46:45 -0800671 EXPECT_EQ(Looper::POLL_WAKE, result)
672 << "pollOnce result should be Looper::POLL_WAKE because looper was awoken";
Jeff Brown3e2e38b2011-03-02 14:41:58 -0800673 EXPECT_EQ(size_t(0), handler->messages.size())
674 << "no messages to handle";
675
676 result = mLooper->pollOnce(0);
677
Brian Carlstrom1693d7e2013-12-11 22:46:45 -0800678 EXPECT_EQ(Looper::POLL_TIMEOUT, result)
679 << "pollOnce result should be Looper::POLL_TIMEOUT because there was nothing to do";
Jeff Brown3e2e38b2011-03-02 14:41:58 -0800680 EXPECT_EQ(size_t(0), handler->messages.size())
681 << "no messages to handle";
682}
683
684TEST_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";
Brian Carlstrom1693d7e2013-12-11 22:46:45 -0800699 EXPECT_EQ(Looper::POLL_CALLBACK, result)
700 << "pollOnce result should be Looper::POLL_CALLBACK because two messages were sent";
Jeff Brown3e2e38b2011-03-02 14:41:58 -0800701 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
Brian Carlstrom1693d7e2013-12-11 22:46:45 -0800710 EXPECT_EQ(Looper::POLL_TIMEOUT, result)
711 << "pollOnce result should be Looper::POLL_TIMEOUT because there was nothing to do";
Jeff Brown3e2e38b2011-03-02 14:41:58 -0800712 EXPECT_EQ(size_t(2), handler->messages.size())
713 << "no more messages to handle";
714}
Jeff Brown7901eb22010-09-13 23:17:30 -0700715
Prabir Pradhan729057a2021-08-12 12:36:31 -0700716class LooperEventCallback : public LooperCallback {
717 public:
718 using Callback = std::function<int(int fd, int events)>;
719 explicit LooperEventCallback(Callback callback) : mCallback(std::move(callback)) {}
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.
728class ThreadedLooperUtil {
729 public:
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
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.
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.
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.
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
804TEST_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
Jeff Brown7901eb22010-09-13 23:17:30 -0700835} // namespace android