summaryrefslogtreecommitdiffstats
path: root/libs/ui
diff options
context:
space:
mode:
Diffstat (limited to 'libs/ui')
-rw-r--r--libs/ui/InputDispatcher.cpp59
-rw-r--r--libs/ui/InputTransport.cpp27
-rw-r--r--libs/ui/tests/InputDispatcher_test.cpp5
-rw-r--r--libs/ui/tests/InputPublisherAndConsumer_test.cpp14
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)