blob: a7a9987a7745eea65b7811d3766c37c98639276a [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
Paul Ramirez7d9c9af2024-09-16 20:44:57 +0000413class LooperCallbackStub final : public LooperCallback {
414 public:
415 LooperCallbackStub(std::function<int()> callback) : mCallback{callback} {}
416
417 int handleEvent(int /*fd*/, int /*events*/, void* /*data*/) override { return mCallback(); }
418
419 private:
420 std::function<int()> mCallback;
421};
422
423TEST_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
447TEST_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
Jeff Brown7901eb22010-09-13 23:17:30 -0700459TEST_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
466TEST_F(LooperTest, RemoveFd_WhenCallbackAddedThenRemovedTwice_ReturnsOnceFirstTimeAndReturnsZeroSecondTime) {
467 Pipe pipe;
468 StubCallbackHandler handler(false);
Brian Carlstrom1693d7e2013-12-11 22:46:45 -0800469 handler.setCallback(mLooper, pipe.receiveFd, Looper::EVENT_INPUT);
Jeff Brown7901eb22010-09-13 23:17:30 -0700470
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
484TEST_F(LooperTest, PollOnce_WhenCallbackAddedTwice_OnlySecondCallbackShouldBeInvoked) {
485 Pipe pipe;
486 StubCallbackHandler handler1(true);
487 StubCallbackHandler handler2(true);
488
Brian Carlstrom1693d7e2013-12-11 22:46:45 -0800489 handler1.setCallback(mLooper, pipe.receiveFd, Looper::EVENT_INPUT);
490 handler2.setCallback(mLooper, pipe.receiveFd, Looper::EVENT_INPUT); // replace it
Jeff Brown7901eb22010-09-13 23:17:30 -0700491 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";
Brian Carlstrom1693d7e2013-12-11 22:46:45 -0800501 EXPECT_EQ(Looper::POLL_CALLBACK, result)
502 << "pollOnce result should be Looper::POLL_CALLBACK because FD was signalled";
Jeff Brown7901eb22010-09-13 23:17:30 -0700503 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
Jeff Brown3e2e38b2011-03-02 14:41:58 -0800509TEST_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";
Brian Carlstrom1693d7e2013-12-11 22:46:45 -0800519 EXPECT_EQ(Looper::POLL_CALLBACK, result)
520 << "pollOnce result should be Looper::POLL_CALLBACK because message was sent";
Jeff Brown3e2e38b2011-03-02 14:41:58 -0800521 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
527TEST_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";
Brian Carlstrom1693d7e2013-12-11 22:46:45 -0800541 EXPECT_EQ(Looper::POLL_CALLBACK, result)
542 << "pollOnce result should be Looper::POLL_CALLBACK because message was sent";
Jeff Brown3e2e38b2011-03-02 14:41:58 -0800543 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
557TEST_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";
Brian Carlstrom1693d7e2013-12-11 22:46:45 -0800567 EXPECT_EQ(Looper::POLL_WAKE, result)
568 << "pollOnce result should be Looper::POLL_WAKE due to wakeup";
Jeff Brown3e2e38b2011-03-02 14:41:58 -0800569 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";
Brian Carlstrom1693d7e2013-12-11 22:46:45 -0800581 EXPECT_EQ(Looper::POLL_CALLBACK, result)
582 << "pollOnce result should be Looper::POLL_CALLBACK because message was sent";
Jeff Brown3e2e38b2011-03-02 14:41:58 -0800583
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";
Brian Carlstrom1693d7e2013-12-11 22:46:45 -0800589 EXPECT_EQ(Looper::POLL_TIMEOUT, result)
590 << "pollOnce result should be Looper::POLL_TIMEOUT because there were no messages left";
Jeff Brown3e2e38b2011-03-02 14:41:58 -0800591}
592
593TEST_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";
Brian Carlstrom1693d7e2013-12-11 22:46:45 -0800603 EXPECT_EQ(Looper::POLL_CALLBACK, result)
604 << "pollOnce result should be Looper::POLL_CALLBACK because message was sent";
Jeff Brown3e2e38b2011-03-02 14:41:58 -0800605 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
611TEST_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";
Brian Carlstrom1693d7e2013-12-11 22:46:45 -0800621 EXPECT_EQ(Looper::POLL_CALLBACK, result)
622 << "pollOnce result should be Looper::POLL_CALLBACK because message was sent";
Jeff Brown3e2e38b2011-03-02 14:41:58 -0800623 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
629TEST_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";
Brian Carlstrom1693d7e2013-12-11 22:46:45 -0800640 EXPECT_EQ(Looper::POLL_WAKE, result)
641 << "pollOnce result should be Looper::POLL_WAKE due to wakeup";
Jeff Brown3e2e38b2011-03-02 14:41:58 -0800642 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";
Brian Carlstrom1693d7e2013-12-11 22:46:45 -0800654 EXPECT_EQ(Looper::POLL_CALLBACK, result)
655 << "pollOnce result should be Looper::POLL_CALLBACK because message was sent";
Jeff Brown3e2e38b2011-03-02 14:41:58 -0800656
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";
Brian Carlstrom1693d7e2013-12-11 22:46:45 -0800662 EXPECT_EQ(Looper::POLL_TIMEOUT, result)
663 << "pollOnce result should be Looper::POLL_TIMEOUT because there were no messages left";
Jeff Brown3e2e38b2011-03-02 14:41:58 -0800664}
665
666TEST_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";
Brian Carlstrom1693d7e2013-12-11 22:46:45 -0800677 EXPECT_EQ(Looper::POLL_CALLBACK, result)
678 << "pollOnce result should be Looper::POLL_CALLBACK because message was sent";
Jeff Brown3e2e38b2011-03-02 14:41:58 -0800679 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
685TEST_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";
Brian Carlstrom1693d7e2013-12-11 22:46:45 -0800696 EXPECT_EQ(Looper::POLL_CALLBACK, result)
697 << "pollOnce result should be Looper::POLL_CALLBACK because message was sent";
Jeff Brown3e2e38b2011-03-02 14:41:58 -0800698 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
704TEST_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";
Brian Carlstrom1693d7e2013-12-11 22:46:45 -0800717 EXPECT_EQ(Looper::POLL_WAKE, result)
718 << "pollOnce result should be Looper::POLL_WAKE because looper was awoken";
Jeff Brown3e2e38b2011-03-02 14:41:58 -0800719 EXPECT_EQ(size_t(0), handler->messages.size())
720 << "no messages to handle";
721
722 result = mLooper->pollOnce(0);
723
Brian Carlstrom1693d7e2013-12-11 22:46:45 -0800724 EXPECT_EQ(Looper::POLL_TIMEOUT, result)
725 << "pollOnce result should be Looper::POLL_TIMEOUT because there was nothing to do";
Jeff Brown3e2e38b2011-03-02 14:41:58 -0800726 EXPECT_EQ(size_t(0), handler->messages.size())
727 << "no messages to handle";
728}
729
730TEST_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";
Brian Carlstrom1693d7e2013-12-11 22:46:45 -0800745 EXPECT_EQ(Looper::POLL_CALLBACK, result)
746 << "pollOnce result should be Looper::POLL_CALLBACK because two messages were sent";
Jeff Brown3e2e38b2011-03-02 14:41:58 -0800747 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
Brian Carlstrom1693d7e2013-12-11 22:46:45 -0800756 EXPECT_EQ(Looper::POLL_TIMEOUT, result)
757 << "pollOnce result should be Looper::POLL_TIMEOUT because there was nothing to do";
Jeff Brown3e2e38b2011-03-02 14:41:58 -0800758 EXPECT_EQ(size_t(2), handler->messages.size())
759 << "no more messages to handle";
760}
Jeff Brown7901eb22010-09-13 23:17:30 -0700761
Prabir Pradhan729057a2021-08-12 12:36:31 -0700762class LooperEventCallback : public LooperCallback {
763 public:
764 using Callback = std::function<int(int fd, int events)>;
765 explicit LooperEventCallback(Callback callback) : mCallback(std::move(callback)) {}
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.
774class ThreadedLooperUtil {
775 public:
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
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.
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.
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.
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
850TEST_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
Jeff Brown7901eb22010-09-13 23:17:30 -0700881} // namespace android