diff options
author | Jeff Brown <jeffbrown@google.com> | 2011-03-02 14:41:58 -0800 |
---|---|---|
committer | Jeff Brown <jeffbrown@google.com> | 2011-03-02 15:37:57 -0800 |
commit | 05dc66ada6b61a6bdf806ffaa62617ac5394695d (patch) | |
tree | a7e395476241706de31498185a5c2ccb979bcb54 /libs | |
parent | e43111fad31ad8e36a66df52a8c6002799996413 (diff) | |
download | frameworks_base-05dc66ada6b61a6bdf806ffaa62617ac5394695d.zip frameworks_base-05dc66ada6b61a6bdf806ffaa62617ac5394695d.tar.gz frameworks_base-05dc66ada6b61a6bdf806ffaa62617ac5394695d.tar.bz2 |
Fade out the mouse pointer after inactivity or other events.
Fades out the mouse pointer:
- after 15 seconds of inactivity normally
- after 3 seconds of inactivity in lights out mode
- after a non-modifier key down
- after a touch down
Extended the native Looper to support enqueuing time delayed
messages. This is used by the PointerController to control
pointer fade timing.
Change-Id: I87792fea7dbe2d9376c78cf354fe3189a484d9da
Diffstat (limited to 'libs')
-rw-r--r-- | libs/ui/Keyboard.cpp | 21 | ||||
-rw-r--r-- | libs/utils/Looper.cpp | 212 | ||||
-rw-r--r-- | libs/utils/tests/Looper_test.cpp | 268 |
3 files changed, 471 insertions, 30 deletions
diff --git a/libs/ui/Keyboard.cpp b/libs/ui/Keyboard.cpp index 8b6300a..600a951 100644 --- a/libs/ui/Keyboard.cpp +++ b/libs/ui/Keyboard.cpp @@ -322,5 +322,26 @@ int32_t updateMetaState(int32_t keyCode, bool down, int32_t oldMetaState) { } } +bool isMetaKey(int32_t keyCode) { + switch (keyCode) { + case AKEYCODE_ALT_LEFT: + case AKEYCODE_ALT_RIGHT: + case AKEYCODE_SHIFT_LEFT: + case AKEYCODE_SHIFT_RIGHT: + case AKEYCODE_SYM: + case AKEYCODE_FUNCTION: + case AKEYCODE_CTRL_LEFT: + case AKEYCODE_CTRL_RIGHT: + case AKEYCODE_META_LEFT: + case AKEYCODE_META_RIGHT: + case AKEYCODE_CAPS_LOCK: + case AKEYCODE_NUM_LOCK: + case AKEYCODE_SCROLL_LOCK: + return true; + default: + return false; + } +} + } // namespace android diff --git a/libs/utils/Looper.cpp b/libs/utils/Looper.cpp index a5363d6..18f858b 100644 --- a/libs/utils/Looper.cpp +++ b/libs/utils/Looper.cpp @@ -19,10 +19,27 @@ #include <unistd.h> #include <fcntl.h> +#include <limits.h> namespace android { +// --- WeakMessageHandler --- + +WeakMessageHandler::WeakMessageHandler(const wp<MessageHandler>& handler) : + mHandler(handler) { +} + +void WeakMessageHandler::handleMessage(const Message& message) { + sp<MessageHandler> handler = mHandler.promote(); + if (handler != NULL) { + handler->handleMessage(message); + } +} + + +// --- Looper --- + #ifdef LOOPER_USES_EPOLL // Hint for number of file descriptors to be associated with the epoll instance. static const int EPOLL_SIZE_HINT = 8; @@ -35,8 +52,8 @@ static pthread_once_t gTLSOnce = PTHREAD_ONCE_INIT; static pthread_key_t gTLSKey = 0; Looper::Looper(bool allowNonCallbacks) : - mAllowNonCallbacks(allowNonCallbacks), - mResponseIndex(0) { + mAllowNonCallbacks(allowNonCallbacks), mSendingMessage(false), + mResponseIndex(0), mNextMessageUptime(LLONG_MAX) { int wakeFds[2]; int result = pipe(wakeFds); LOG_ALWAYS_FATAL_IF(result != 0, "Could not create wake pipe. errno=%d", errno); @@ -161,17 +178,21 @@ int Looper::pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outDa for (;;) { while (mResponseIndex < mResponses.size()) { const Response& response = mResponses.itemAt(mResponseIndex++); - if (! response.request.callback) { + ALooper_callbackFunc callback = response.request.callback; + if (!callback) { + int ident = response.request.ident; + int fd = response.request.fd; + int events = response.events; + void* data = response.request.data; #if DEBUG_POLL_AND_WAKE LOGD("%p ~ pollOnce - returning signalled identifier %d: " - "fd=%d, events=0x%x, data=%p", this, - response.request.ident, response.request.fd, - response.events, response.request.data); + "fd=%d, events=0x%x, data=%p", + this, ident, fd, events, data); #endif - if (outFd != NULL) *outFd = response.request.fd; - if (outEvents != NULL) *outEvents = response.events; - if (outData != NULL) *outData = response.request.data; - return response.request.ident; + if (outFd != NULL) *outFd = fd; + if (outEvents != NULL) *outEvents = events; + if (outData != NULL) *outData = data; + return ident; } } @@ -194,6 +215,25 @@ int Looper::pollInner(int timeoutMillis) { LOGD("%p ~ pollOnce - waiting: timeoutMillis=%d", this, timeoutMillis); #endif + // Adjust the timeout based on when the next message is due. + if (timeoutMillis != 0 && mNextMessageUptime != LLONG_MAX) { + nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC); + if (mNextMessageUptime <= now) { + timeoutMillis = 0; + } else { + uint64_t delay = (mNextMessageUptime - now + 999999LL) / 1000000LL; + if (delay < INT_MAX + && (timeoutMillis < 0 || int(delay) < timeoutMillis)) { + timeoutMillis = int(delay); + } + } +#if DEBUG_POLL_AND_WAKE + LOGD("%p ~ pollOnce - next message in %lldns, adjusted timeout: timeoutMillis=%d", + this, mNextMessageUptime - now, timeoutMillis); +#endif + } + + // Poll. int result = ALOOPER_POLL_WAKE; mResponses.clear(); mResponseIndex = 0; @@ -205,7 +245,6 @@ int Looper::pollInner(int timeoutMillis) { #ifdef LOOPER_USES_EPOLL struct epoll_event eventItems[EPOLL_MAX_EVENTS]; int eventCount = epoll_wait(mEpollFd, eventItems, EPOLL_MAX_EVENTS, timeoutMillis); - bool acquiredLock = false; #else // Wait for wakeAndLock() waiters to run then set mPolling to true. mLock.lock(); @@ -219,16 +258,20 @@ int Looper::pollInner(int timeoutMillis) { int eventCount = poll(mRequestedFds.editArray(), requestedCount, timeoutMillis); #endif + // Acquire lock. + mLock.lock(); + + // Check for poll error. if (eventCount < 0) { if (errno == EINTR) { goto Done; } - LOGW("Poll failed with an unexpected error, errno=%d", errno); result = ALOOPER_POLL_ERROR; goto Done; } + // Check for poll timeout. if (eventCount == 0) { #if DEBUG_POLL_AND_WAKE LOGD("%p ~ pollOnce - timeout", this); @@ -237,6 +280,7 @@ int Looper::pollInner(int timeoutMillis) { goto Done; } + // Handle all events. #if DEBUG_POLL_AND_WAKE LOGD("%p ~ pollOnce - handling events from %d fds", this, eventCount); #endif @@ -252,11 +296,6 @@ int Looper::pollInner(int timeoutMillis) { LOGW("Ignoring unexpected epoll events 0x%x on wake read pipe.", epollEvents); } } else { - if (! acquiredLock) { - mLock.lock(); - acquiredLock = true; - } - ssize_t requestIndex = mRequests.indexOfKey(fd); if (requestIndex >= 0) { int events = 0; @@ -271,9 +310,6 @@ int Looper::pollInner(int timeoutMillis) { } } } - if (acquiredLock) { - mLock.unlock(); - } Done: ; #else for (size_t i = 0; i < requestedCount; i++) { @@ -301,15 +337,12 @@ Done: ; } } } - Done: // Set mPolling to false and wake up the wakeAndLock() waiters. - mLock.lock(); mPolling = false; if (mWaiters != 0) { mAwake.broadcast(); } - mLock.unlock(); #endif #ifdef LOOPER_STATISTICS @@ -335,19 +368,59 @@ Done: } #endif + // Invoke pending message callbacks. + mNextMessageUptime = LLONG_MAX; + while (mMessageEnvelopes.size() != 0) { + nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC); + const MessageEnvelope& messageEnvelope = mMessageEnvelopes.itemAt(0); + if (messageEnvelope.uptime <= now) { + // Remove the envelope from the list. + // We keep a strong reference to the handler until the call to handleMessage + // finishes. Then we drop it so that the handler can be deleted *before* + // we reacquire our lock. + { // obtain handler + sp<MessageHandler> handler = messageEnvelope.handler; + Message message = messageEnvelope.message; + mMessageEnvelopes.removeAt(0); + mSendingMessage = true; + mLock.unlock(); + +#if DEBUG_POLL_AND_WAKE || DEBUG_CALLBACKS + LOGD("%p ~ pollOnce - sending message: handler=%p, what=%d", + this, handler.get(), message.what); +#endif + handler->handleMessage(message); + } // release handler + + mLock.lock(); + mSendingMessage = false; + result = ALOOPER_POLL_CALLBACK; + } else { + // The last message left at the head of the queue determines the next wakeup time. + mNextMessageUptime = messageEnvelope.uptime; + break; + } + } + + // Release lock. + mLock.unlock(); + + // Invoke all response callbacks. for (size_t i = 0; i < mResponses.size(); i++) { const Response& response = mResponses.itemAt(i); - if (response.request.callback) { + ALooper_callbackFunc callback = response.request.callback; + if (callback) { + int fd = response.request.fd; + int events = response.events; + void* data = response.request.data; #if DEBUG_POLL_AND_WAKE || DEBUG_CALLBACKS - LOGD("%p ~ pollOnce - invoking callback: fd=%d, events=0x%x, data=%p", this, - response.request.fd, response.events, response.request.data); + LOGD("%p ~ pollOnce - invoking fd event callback %p: fd=%d, events=0x%x, data=%p", + this, callback, fd, events, data); #endif - int callbackResult = response.request.callback( - response.request.fd, response.events, response.request.data); + int callbackResult = callback(fd, events, data); if (callbackResult == 0) { - removeFd(response.request.fd); + removeFd(fd); } - result = ALOOPER_POLL_CALLBACK; } } @@ -593,4 +666,83 @@ void Looper::wakeAndLock() { } #endif +void Looper::sendMessage(const sp<MessageHandler>& handler, const Message& message) { + sendMessageAtTime(LLONG_MIN, handler, message); +} + +void Looper::sendMessageDelayed(nsecs_t uptimeDelay, const sp<MessageHandler>& handler, + const Message& message) { + nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC); + sendMessageAtTime(now + uptimeDelay, handler, message); +} + +void Looper::sendMessageAtTime(nsecs_t uptime, const sp<MessageHandler>& handler, + const Message& message) { +#if DEBUG_CALLBACKS + LOGD("%p ~ sendMessageAtTime - uptime=%lld, handler=%p, what=%d", + this, uptime, handler.get(), message.what); +#endif + + size_t i = 0; + { // acquire lock + AutoMutex _l(mLock); + + size_t messageCount = mMessageEnvelopes.size(); + while (i < messageCount && uptime >= mMessageEnvelopes.itemAt(i).uptime) { + i += 1; + } + + MessageEnvelope messageEnvelope(uptime, handler, message); + mMessageEnvelopes.insertAt(messageEnvelope, i, 1); + + // Optimization: If the Looper is currently sending a message, then we can skip + // the call to wake() because the next thing the Looper will do after processing + // messages is to decide when the next wakeup time should be. In fact, it does + // not even matter whether this code is running on the Looper thread. + if (mSendingMessage) { + return; + } + } // release lock + + // Wake the poll loop only when we enqueue a new message at the head. + if (i == 0) { + wake(); + } +} + +void Looper::removeMessages(const sp<MessageHandler>& handler) { +#if DEBUG_CALLBACKS + LOGD("%p ~ removeMessages - handler=%p", this, handler.get()); +#endif + + { // acquire lock + AutoMutex _l(mLock); + + for (size_t i = mMessageEnvelopes.size(); i != 0; ) { + const MessageEnvelope& messageEnvelope = mMessageEnvelopes.itemAt(--i); + if (messageEnvelope.handler == handler) { + mMessageEnvelopes.removeAt(i); + } + } + } // release lock +} + +void Looper::removeMessages(const sp<MessageHandler>& handler, int what) { +#if DEBUG_CALLBACKS + LOGD("%p ~ removeMessages - handler=%p, what=%d", this, handler.get(), what); +#endif + + { // acquire lock + AutoMutex _l(mLock); + + for (size_t i = mMessageEnvelopes.size(); i != 0; ) { + const MessageEnvelope& messageEnvelope = mMessageEnvelopes.itemAt(--i); + if (messageEnvelope.handler == handler + && messageEnvelope.message.what == what) { + mMessageEnvelopes.removeAt(i); + } + } + } // release lock +} + } // namespace android diff --git a/libs/utils/tests/Looper_test.cpp b/libs/utils/tests/Looper_test.cpp index cea1313..8bf2ba2 100644 --- a/libs/utils/tests/Looper_test.cpp +++ b/libs/utils/tests/Looper_test.cpp @@ -16,6 +16,13 @@ namespace android { +enum { + MSG_TEST1 = 1, + MSG_TEST2 = 2, + MSG_TEST3 = 3, + MSG_TEST4 = 4, +}; + class DelayedWake : public DelayedTask { sp<Looper> mLooper; @@ -82,6 +89,15 @@ protected: } }; +class StubMessageHandler : public MessageHandler { +public: + Vector<Message> messages; + + virtual void handleMessage(const Message& message) { + messages.push(message); + } +}; + class LooperTest : public testing::Test { protected: sp<Looper> mLooper; @@ -421,5 +437,257 @@ TEST_F(LooperTest, PollOnce_WhenCallbackAddedTwice_OnlySecondCallbackShouldBeInv << "replacement handler callback should be invoked"; } +TEST_F(LooperTest, SendMessage_WhenOneMessageIsEnqueue_ShouldInvokeHandlerDuringNextPoll) { + sp<StubMessageHandler> handler = new StubMessageHandler(); + mLooper->sendMessage(handler, Message(MSG_TEST1)); + + StopWatch stopWatch("pollOnce"); + int result = mLooper->pollOnce(100); + int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime()); + + EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS) + << "elapsed time should approx. zero because message was already sent"; + EXPECT_EQ(ALOOPER_POLL_CALLBACK, result) + << "pollOnce result should be ALOOPER_POLL_CALLBACK because message was sent"; + EXPECT_EQ(size_t(1), handler->messages.size()) + << "handled message"; + EXPECT_EQ(MSG_TEST1, handler->messages[0].what) + << "handled message"; +} + +TEST_F(LooperTest, SendMessage_WhenMultipleMessagesAreEnqueued_ShouldInvokeHandlersInOrderDuringNextPoll) { + sp<StubMessageHandler> handler1 = new StubMessageHandler(); + sp<StubMessageHandler> handler2 = new StubMessageHandler(); + mLooper->sendMessage(handler1, Message(MSG_TEST1)); + mLooper->sendMessage(handler2, Message(MSG_TEST2)); + mLooper->sendMessage(handler1, Message(MSG_TEST3)); + mLooper->sendMessage(handler1, Message(MSG_TEST4)); + + StopWatch stopWatch("pollOnce"); + int result = mLooper->pollOnce(1000); + int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime()); + + EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS) + << "elapsed time should approx. zero because message was already sent"; + EXPECT_EQ(ALOOPER_POLL_CALLBACK, result) + << "pollOnce result should be ALOOPER_POLL_CALLBACK because message was sent"; + EXPECT_EQ(size_t(3), handler1->messages.size()) + << "handled message"; + EXPECT_EQ(MSG_TEST1, handler1->messages[0].what) + << "handled message"; + EXPECT_EQ(MSG_TEST3, handler1->messages[1].what) + << "handled message"; + EXPECT_EQ(MSG_TEST4, handler1->messages[2].what) + << "handled message"; + EXPECT_EQ(size_t(1), handler2->messages.size()) + << "handled message"; + EXPECT_EQ(MSG_TEST2, handler2->messages[0].what) + << "handled message"; +} + +TEST_F(LooperTest, SendMessageDelayed_WhenSentToTheFuture_ShouldInvokeHandlerAfterDelayTime) { + sp<StubMessageHandler> handler = new StubMessageHandler(); + mLooper->sendMessageDelayed(ms2ns(100), handler, Message(MSG_TEST1)); + + StopWatch stopWatch("pollOnce"); + int result = mLooper->pollOnce(1000); + int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime()); + + EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS) + << "first poll should end quickly because next message timeout was computed"; + EXPECT_EQ(ALOOPER_POLL_WAKE, result) + << "pollOnce result should be ALOOPER_POLL_WAKE due to wakeup"; + EXPECT_EQ(size_t(0), handler->messages.size()) + << "no message handled yet"; + + result = mLooper->pollOnce(1000); + elapsedMillis = ns2ms(stopWatch.elapsedTime()); + + EXPECT_EQ(size_t(1), handler->messages.size()) + << "handled message"; + EXPECT_EQ(MSG_TEST1, handler->messages[0].what) + << "handled message"; + EXPECT_NEAR(100, elapsedMillis, TIMING_TOLERANCE_MS) + << "second poll should end around the time of the delayed message dispatch"; + EXPECT_EQ(ALOOPER_POLL_CALLBACK, result) + << "pollOnce result should be ALOOPER_POLL_CALLBACK because message was sent"; + + result = mLooper->pollOnce(100); + elapsedMillis = ns2ms(stopWatch.elapsedTime()); + + EXPECT_NEAR(100 + 100, elapsedMillis, TIMING_TOLERANCE_MS) + << "third poll should timeout"; + EXPECT_EQ(ALOOPER_POLL_TIMEOUT, result) + << "pollOnce result should be ALOOPER_POLL_TIMEOUT because there were no messages left"; +} + +TEST_F(LooperTest, SendMessageDelayed_WhenSentToThePast_ShouldInvokeHandlerDuringNextPoll) { + sp<StubMessageHandler> handler = new StubMessageHandler(); + mLooper->sendMessageDelayed(ms2ns(-1000), handler, Message(MSG_TEST1)); + + StopWatch stopWatch("pollOnce"); + int result = mLooper->pollOnce(100); + int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime()); + + EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS) + << "elapsed time should approx. zero because message was already sent"; + EXPECT_EQ(ALOOPER_POLL_CALLBACK, result) + << "pollOnce result should be ALOOPER_POLL_CALLBACK because message was sent"; + EXPECT_EQ(size_t(1), handler->messages.size()) + << "handled message"; + EXPECT_EQ(MSG_TEST1, handler->messages[0].what) + << "handled message"; +} + +TEST_F(LooperTest, SendMessageDelayed_WhenSentToThePresent_ShouldInvokeHandlerDuringNextPoll) { + sp<StubMessageHandler> handler = new StubMessageHandler(); + mLooper->sendMessageDelayed(0, handler, Message(MSG_TEST1)); + + StopWatch stopWatch("pollOnce"); + int result = mLooper->pollOnce(100); + int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime()); + + EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS) + << "elapsed time should approx. zero because message was already sent"; + EXPECT_EQ(ALOOPER_POLL_CALLBACK, result) + << "pollOnce result should be ALOOPER_POLL_CALLBACK because message was sent"; + EXPECT_EQ(size_t(1), handler->messages.size()) + << "handled message"; + EXPECT_EQ(MSG_TEST1, handler->messages[0].what) + << "handled message"; +} + +TEST_F(LooperTest, SendMessageAtTime_WhenSentToTheFuture_ShouldInvokeHandlerAfterDelayTime) { + nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC); + sp<StubMessageHandler> handler = new StubMessageHandler(); + mLooper->sendMessageAtTime(now + ms2ns(100), handler, Message(MSG_TEST1)); + + StopWatch stopWatch("pollOnce"); + int result = mLooper->pollOnce(1000); + int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime()); + + EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS) + << "first poll should end quickly because next message timeout was computed"; + EXPECT_EQ(ALOOPER_POLL_WAKE, result) + << "pollOnce result should be ALOOPER_POLL_WAKE due to wakeup"; + EXPECT_EQ(size_t(0), handler->messages.size()) + << "no message handled yet"; + + result = mLooper->pollOnce(1000); + elapsedMillis = ns2ms(stopWatch.elapsedTime()); + + EXPECT_EQ(size_t(1), handler->messages.size()) + << "handled message"; + EXPECT_EQ(MSG_TEST1, handler->messages[0].what) + << "handled message"; + EXPECT_NEAR(100, elapsedMillis, TIMING_TOLERANCE_MS) + << "second poll should end around the time of the delayed message dispatch"; + EXPECT_EQ(ALOOPER_POLL_CALLBACK, result) + << "pollOnce result should be ALOOPER_POLL_CALLBACK because message was sent"; + + result = mLooper->pollOnce(100); + elapsedMillis = ns2ms(stopWatch.elapsedTime()); + + EXPECT_NEAR(100 + 100, elapsedMillis, TIMING_TOLERANCE_MS) + << "third poll should timeout"; + EXPECT_EQ(ALOOPER_POLL_TIMEOUT, result) + << "pollOnce result should be ALOOPER_POLL_TIMEOUT because there were no messages left"; +} + +TEST_F(LooperTest, SendMessageAtTime_WhenSentToThePast_ShouldInvokeHandlerDuringNextPoll) { + nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC); + sp<StubMessageHandler> handler = new StubMessageHandler(); + mLooper->sendMessageAtTime(now - ms2ns(1000), handler, Message(MSG_TEST1)); + + StopWatch stopWatch("pollOnce"); + int result = mLooper->pollOnce(100); + int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime()); + + EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS) + << "elapsed time should approx. zero because message was already sent"; + EXPECT_EQ(ALOOPER_POLL_CALLBACK, result) + << "pollOnce result should be ALOOPER_POLL_CALLBACK because message was sent"; + EXPECT_EQ(size_t(1), handler->messages.size()) + << "handled message"; + EXPECT_EQ(MSG_TEST1, handler->messages[0].what) + << "handled message"; +} + +TEST_F(LooperTest, SendMessageAtTime_WhenSentToThePresent_ShouldInvokeHandlerDuringNextPoll) { + nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC); + sp<StubMessageHandler> handler = new StubMessageHandler(); + mLooper->sendMessageAtTime(now, handler, Message(MSG_TEST1)); + + StopWatch stopWatch("pollOnce"); + int result = mLooper->pollOnce(100); + int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime()); + + EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS) + << "elapsed time should approx. zero because message was already sent"; + EXPECT_EQ(ALOOPER_POLL_CALLBACK, result) + << "pollOnce result should be ALOOPER_POLL_CALLBACK because message was sent"; + EXPECT_EQ(size_t(1), handler->messages.size()) + << "handled message"; + EXPECT_EQ(MSG_TEST1, handler->messages[0].what) + << "handled message"; +} + +TEST_F(LooperTest, RemoveMessage_WhenRemovingAllMessagesForHandler_ShouldRemoveThoseMessage) { + sp<StubMessageHandler> handler = new StubMessageHandler(); + mLooper->sendMessage(handler, Message(MSG_TEST1)); + mLooper->sendMessage(handler, Message(MSG_TEST2)); + mLooper->sendMessage(handler, Message(MSG_TEST3)); + mLooper->removeMessages(handler); + + StopWatch stopWatch("pollOnce"); + int result = mLooper->pollOnce(0); + int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime()); + + EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS) + << "elapsed time should approx. zero because message was sent so looper was awoken"; + EXPECT_EQ(ALOOPER_POLL_WAKE, result) + << "pollOnce result should be ALOOPER_POLL_WAKE because looper was awoken"; + EXPECT_EQ(size_t(0), handler->messages.size()) + << "no messages to handle"; + + result = mLooper->pollOnce(0); + + EXPECT_EQ(ALOOPER_POLL_TIMEOUT, result) + << "pollOnce result should be ALOOPER_POLL_TIMEOUT because there was nothing to do"; + EXPECT_EQ(size_t(0), handler->messages.size()) + << "no messages to handle"; +} + +TEST_F(LooperTest, RemoveMessage_WhenRemovingSomeMessagesForHandler_ShouldRemoveThoseMessage) { + sp<StubMessageHandler> handler = new StubMessageHandler(); + mLooper->sendMessage(handler, Message(MSG_TEST1)); + mLooper->sendMessage(handler, Message(MSG_TEST2)); + mLooper->sendMessage(handler, Message(MSG_TEST3)); + mLooper->sendMessage(handler, Message(MSG_TEST4)); + mLooper->removeMessages(handler, MSG_TEST3); + mLooper->removeMessages(handler, MSG_TEST1); + + StopWatch stopWatch("pollOnce"); + int result = mLooper->pollOnce(0); + int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime()); + + EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS) + << "elapsed time should approx. zero because message was sent so looper was awoken"; + EXPECT_EQ(ALOOPER_POLL_CALLBACK, result) + << "pollOnce result should be ALOOPER_POLL_CALLBACK because two messages were sent"; + EXPECT_EQ(size_t(2), handler->messages.size()) + << "no messages to handle"; + EXPECT_EQ(MSG_TEST2, handler->messages[0].what) + << "handled message"; + EXPECT_EQ(MSG_TEST4, handler->messages[1].what) + << "handled message"; + + result = mLooper->pollOnce(0); + + EXPECT_EQ(ALOOPER_POLL_TIMEOUT, result) + << "pollOnce result should be ALOOPER_POLL_TIMEOUT because there was nothing to do"; + EXPECT_EQ(size_t(2), handler->messages.size()) + << "no more messages to handle"; +} } // namespace android |