diff options
Diffstat (limited to 'libs/ui')
-rw-r--r-- | libs/ui/InputDispatcher.cpp | 59 | ||||
-rw-r--r-- | libs/ui/InputTransport.cpp | 27 | ||||
-rw-r--r-- | libs/ui/tests/InputDispatcher_test.cpp | 5 | ||||
-rw-r--r-- | libs/ui/tests/InputPublisherAndConsumer_test.cpp | 14 |
4 files changed, 80 insertions, 25 deletions
diff --git a/libs/ui/InputDispatcher.cpp b/libs/ui/InputDispatcher.cpp index f9c0b91..299b1ba 100644 --- a/libs/ui/InputDispatcher.cpp +++ b/libs/ui/InputDispatcher.cpp @@ -1770,13 +1770,14 @@ void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime, } void InputDispatcher::finishDispatchCycleLocked(nsecs_t currentTime, - const sp<Connection>& connection) { + const sp<Connection>& connection, bool handled) { #if DEBUG_DISPATCH_CYCLE LOGD("channel '%s' ~ finishDispatchCycle - %01.1fms since event, " - "%01.1fms since dispatch", + "%01.1fms since dispatch, handled=%s", connection->getInputChannelName(), connection->getEventLatencyMillis(currentTime), - connection->getDispatchLatencyMillis(currentTime)); + connection->getDispatchLatencyMillis(currentTime), + toString(handled)); #endif if (connection->status == Connection::STATUS_BROKEN @@ -1784,9 +1785,6 @@ void InputDispatcher::finishDispatchCycleLocked(nsecs_t currentTime, return; } - // Notify other system components. - onDispatchCycleFinishedLocked(currentTime, connection); - // Reset the publisher since the event has been consumed. // We do this now so that the publisher can release some of its internal resources // while waiting for the next dispatch cycle to begin. @@ -1798,7 +1796,8 @@ void InputDispatcher::finishDispatchCycleLocked(nsecs_t currentTime, return; } - startNextDispatchCycleLocked(currentTime, connection); + // Notify other system components and prepare to start the next dispatch cycle. + onDispatchCycleFinishedLocked(currentTime, connection, handled); } void InputDispatcher::startNextDispatchCycleLocked(nsecs_t currentTime, @@ -1898,7 +1897,8 @@ int InputDispatcher::handleReceiveCallback(int receiveFd, int events, void* data return 1; } - status_t status = connection->inputPublisher.receiveFinishedSignal(); + bool handled = false; + status_t status = connection->inputPublisher.receiveFinishedSignal(handled); if (status) { LOGE("channel '%s' ~ Failed to receive finished signal. status=%d", connection->getInputChannelName(), status); @@ -1907,7 +1907,7 @@ int InputDispatcher::handleReceiveCallback(int receiveFd, int events, void* data return 0; // remove the callback } - d->finishDispatchCycleLocked(currentTime, connection); + d->finishDispatchCycleLocked(currentTime, connection, handled); d->runCommandsLockedInterruptible(); return 1; } // release lock @@ -2945,7 +2945,11 @@ void InputDispatcher::onDispatchCycleStartedLocked( } void InputDispatcher::onDispatchCycleFinishedLocked( - nsecs_t currentTime, const sp<Connection>& connection) { + nsecs_t currentTime, const sp<Connection>& connection, bool handled) { + CommandEntry* commandEntry = postCommandLocked( + & InputDispatcher::doDispatchCycleFinishedLockedInterruptible); + commandEntry->connection = connection; + commandEntry->handled = handled; } void InputDispatcher::onDispatchCycleBrokenLocked( @@ -3014,9 +3018,7 @@ void InputDispatcher::doNotifyANRLockedInterruptible( void InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible( CommandEntry* commandEntry) { KeyEntry* entry = commandEntry->keyEntry; - mReusableKeyEvent.initialize(entry->deviceId, entry->source, entry->action, entry->flags, - entry->keyCode, entry->scanCode, entry->metaState, entry->repeatCount, - entry->downTime, entry->eventTime); + initializeKeyEvent(&mReusableKeyEvent, entry); mLock.unlock(); @@ -3031,6 +3033,31 @@ void InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible( mAllocator.releaseKeyEntry(entry); } +void InputDispatcher::doDispatchCycleFinishedLockedInterruptible( + CommandEntry* commandEntry) { + sp<Connection> connection = commandEntry->connection; + bool handled = commandEntry->handled; + + if (!handled && !connection->outboundQueue.isEmpty()) { + DispatchEntry* dispatchEntry = connection->outboundQueue.headSentinel.next; + if (dispatchEntry->inProgress + && dispatchEntry->hasForegroundTarget() + && dispatchEntry->eventEntry->type == EventEntry::TYPE_KEY) { + KeyEntry* keyEntry = static_cast<KeyEntry*>(dispatchEntry->eventEntry); + initializeKeyEvent(&mReusableKeyEvent, keyEntry); + + mLock.unlock(); + + mPolicy->dispatchUnhandledKey(connection->inputChannel, + & mReusableKeyEvent, keyEntry->policyFlags); + + mLock.lock(); + } + } + + startNextDispatchCycleLocked(now(), connection); +} + void InputDispatcher::doPokeUserActivityLockedInterruptible(CommandEntry* commandEntry) { mLock.unlock(); @@ -3039,6 +3066,12 @@ void InputDispatcher::doPokeUserActivityLockedInterruptible(CommandEntry* comman mLock.lock(); } +void InputDispatcher::initializeKeyEvent(KeyEvent* event, const KeyEntry* entry) { + event->initialize(entry->deviceId, entry->source, entry->action, entry->flags, + entry->keyCode, entry->scanCode, entry->metaState, entry->repeatCount, + entry->downTime, entry->eventTime); +} + void InputDispatcher::updateDispatchStatisticsLocked(nsecs_t currentTime, const EventEntry* entry, int32_t injectionResult, nsecs_t timeSpentWaitingForApplication) { // TODO Write some statistics about how long we spend waiting. diff --git a/libs/ui/InputTransport.cpp b/libs/ui/InputTransport.cpp index 2c6346e..1885691 100644 --- a/libs/ui/InputTransport.cpp +++ b/libs/ui/InputTransport.cpp @@ -35,8 +35,12 @@ static const int DEFAULT_MESSAGE_BUFFER_SIZE = 16384; static const char INPUT_SIGNAL_DISPATCH = 'D'; // Signal sent by the consumer to the producer to inform it that it has finished -// consuming the most recent message. -static const char INPUT_SIGNAL_FINISHED = 'f'; +// consuming the most recent message and it handled it. +static const char INPUT_SIGNAL_FINISHED_HANDLED = 'f'; + +// Signal sent by the consumer to the producer to inform it that it has finished +// consuming the most recent message but it did not handle it. +static const char INPUT_SIGNAL_FINISHED_UNHANDLED = 'u'; // --- InputChannel --- @@ -497,7 +501,7 @@ status_t InputPublisher::sendDispatchSignal() { return mChannel->sendSignal(INPUT_SIGNAL_DISPATCH); } -status_t InputPublisher::receiveFinishedSignal() { +status_t InputPublisher::receiveFinishedSignal(bool& outHandled) { #if DEBUG_TRANSPORT_ACTIONS LOGD("channel '%s' publisher ~ receiveFinishedSignal", mChannel->getName().string()); @@ -506,9 +510,14 @@ status_t InputPublisher::receiveFinishedSignal() { char signal; status_t result = mChannel->receiveSignal(& signal); if (result) { + outHandled = false; return result; } - if (signal != INPUT_SIGNAL_FINISHED) { + if (signal == INPUT_SIGNAL_FINISHED_HANDLED) { + outHandled = true; + } else if (signal == INPUT_SIGNAL_FINISHED_UNHANDLED) { + outHandled = false; + } else { LOGE("channel '%s' publisher ~ Received unexpected signal '%c' from consumer", mChannel->getName().string(), signal); return UNKNOWN_ERROR; @@ -626,13 +635,15 @@ status_t InputConsumer::consume(InputEventFactoryInterface* factory, InputEvent* return OK; } -status_t InputConsumer::sendFinishedSignal() { +status_t InputConsumer::sendFinishedSignal(bool handled) { #if DEBUG_TRANSPORT_ACTIONS - LOGD("channel '%s' consumer ~ sendFinishedSignal", - mChannel->getName().string()); + LOGD("channel '%s' consumer ~ sendFinishedSignal: handled=%d", + mChannel->getName().string(), handled); #endif - return mChannel->sendSignal(INPUT_SIGNAL_FINISHED); + return mChannel->sendSignal(handled + ? INPUT_SIGNAL_FINISHED_HANDLED + : INPUT_SIGNAL_FINISHED_UNHANDLED); } status_t InputConsumer::receiveDispatchSignal() { diff --git a/libs/ui/tests/InputDispatcher_test.cpp b/libs/ui/tests/InputDispatcher_test.cpp index 8874dfe..f352dbf 100644 --- a/libs/ui/tests/InputDispatcher_test.cpp +++ b/libs/ui/tests/InputDispatcher_test.cpp @@ -67,6 +67,11 @@ private: return false; } + virtual bool dispatchUnhandledKey(const sp<InputChannel>& inputChannel, + const KeyEvent* keyEvent, uint32_t policyFlags) { + return false; + } + virtual void notifySwitch(nsecs_t when, int32_t switchCode, int32_t switchValue, uint32_t policyFlags) { } diff --git a/libs/ui/tests/InputPublisherAndConsumer_test.cpp b/libs/ui/tests/InputPublisherAndConsumer_test.cpp index 952b974..c6eac25 100644 --- a/libs/ui/tests/InputPublisherAndConsumer_test.cpp +++ b/libs/ui/tests/InputPublisherAndConsumer_test.cpp @@ -118,13 +118,16 @@ void InputPublisherAndConsumerTest::PublishAndConsumeKeyEvent() { EXPECT_EQ(downTime, keyEvent->getDownTime()); EXPECT_EQ(eventTime, keyEvent->getEventTime()); - status = mConsumer->sendFinishedSignal(); + status = mConsumer->sendFinishedSignal(true); ASSERT_EQ(OK, status) << "consumer sendFinishedSignal should return OK"; - status = mPublisher->receiveFinishedSignal(); + bool handled = false; + status = mPublisher->receiveFinishedSignal(handled); ASSERT_EQ(OK, status) << "publisher receiveFinishedSignal should return OK"; + ASSERT_TRUE(handled) + << "publisher receiveFinishedSignal should have set handled to consumer's reply"; status = mPublisher->reset(); ASSERT_EQ(OK, status) @@ -279,13 +282,16 @@ void InputPublisherAndConsumerTest::PublishAndConsumeMotionEvent( EXPECT_EQ(samplePointerCoords[offset].orientation, motionEvent->getOrientation(i)); } - status = mConsumer->sendFinishedSignal(); + status = mConsumer->sendFinishedSignal(false); ASSERT_EQ(OK, status) << "consumer sendFinishedSignal should return OK"; - status = mPublisher->receiveFinishedSignal(); + bool handled = true; + status = mPublisher->receiveFinishedSignal(handled); ASSERT_EQ(OK, status) << "publisher receiveFinishedSignal should return OK"; + ASSERT_FALSE(handled) + << "publisher receiveFinishedSignal should have set handled to consumer's reply"; status = mPublisher->reset(); ASSERT_EQ(OK, status) |