Refactor how timeouts are calculated. (DO NOT MERGE)
Added a timeout mechanism to EventHub and InputReader so that
InputMappers can request timeouts to perform delayed processing of
input when needed.
Change-Id: I89c1171c9326c6e413042e3ee13aa9f7f1fc0454
diff --git a/services/input/EventHub.cpp b/services/input/EventHub.cpp
index 853dda4..41993fd 100644
--- a/services/input/EventHub.cpp
+++ b/services/input/EventHub.cpp
@@ -445,7 +445,7 @@
return NULL;
}
-bool EventHub::getEvent(RawEvent* outEvent) {
+bool EventHub::getEvent(int timeoutMillis, RawEvent* outEvent) {
outEvent->deviceId = 0;
outEvent->type = 0;
outEvent->scanCode = 0;
@@ -598,13 +598,20 @@
// when this happens, the EventHub holds onto its own user wake lock while the client
// is processing events. Thus the system can only sleep if there are no events
// pending or currently being processed.
+ //
+ // The timeout is advisory only. If the device is asleep, it will not wake just to
+ // service the timeout.
release_wake_lock(WAKE_LOCK_ID);
- int pollResult = poll(mFds.editArray(), mFds.size(), -1);
+ int pollResult = poll(mFds.editArray(), mFds.size(), timeoutMillis);
acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID);
- if (pollResult <= 0) {
+ if (pollResult == 0) {
+ // Timed out.
+ return false;
+ }
+ if (pollResult < 0) {
if (errno != EINTR) {
LOGW("poll failed (errno=%d)\n", errno);
usleep(100000);
diff --git a/services/input/EventHub.h b/services/input/EventHub.h
index 7053a94..1d287ac 100644
--- a/services/input/EventHub.h
+++ b/services/input/EventHub.h
@@ -186,8 +186,13 @@
* This ensures that the device will not go to sleep while the event is being processed.
* If the device needs to remain awake longer than that, then the caller is responsible
* for taking care of it (say, by poking the power manager user activity timer).
+ *
+ * The timeout is advisory only. If the device is asleep, it will not wake just to
+ * service the timeout.
+ *
+ * Returns true if an event was obtained, false if the timeout expired.
*/
- virtual bool getEvent(RawEvent* outEvent) = 0;
+ virtual bool getEvent(int timeoutMillis, RawEvent* outEvent) = 0;
/*
* Query current input state.
@@ -244,7 +249,7 @@
virtual bool markSupportedKeyCodes(int32_t deviceId, size_t numCodes,
const int32_t* keyCodes, uint8_t* outFlags) const;
- virtual bool getEvent(RawEvent* outEvent);
+ virtual bool getEvent(int timeoutMillis, RawEvent* outEvent);
virtual bool hasLed(int32_t deviceId, int32_t led) const;
virtual void setLedState(int32_t deviceId, int32_t led, bool on);
diff --git a/services/input/InputDispatcher.cpp b/services/input/InputDispatcher.cpp
index 53dc769..ce8f076 100644
--- a/services/input/InputDispatcher.cpp
+++ b/services/input/InputDispatcher.cpp
@@ -246,15 +246,7 @@
// Wait for callback or timeout or wake. (make sure we round up, not down)
nsecs_t currentTime = now();
- int32_t timeoutMillis;
- if (nextWakeupTime > currentTime) {
- uint64_t timeout = uint64_t(nextWakeupTime - currentTime);
- timeout = (timeout + 999999LL) / 1000000LL;
- timeoutMillis = timeout > INT_MAX ? -1 : int32_t(timeout);
- } else {
- timeoutMillis = 0;
- }
-
+ int timeoutMillis = toMillisecondTimeoutDelay(currentTime, nextWakeupTime);
mLooper->pollOnce(timeoutMillis);
}
diff --git a/services/input/InputReader.cpp b/services/input/InputReader.cpp
index 592939f..182bd50 100644
--- a/services/input/InputReader.cpp
+++ b/services/input/InputReader.cpp
@@ -231,7 +231,7 @@
const sp<InputReaderPolicyInterface>& policy,
const sp<InputDispatcherInterface>& dispatcher) :
mEventHub(eventHub), mPolicy(policy), mDispatcher(dispatcher),
- mGlobalMetaState(0), mDisableVirtualKeysTimeout(-1) {
+ mGlobalMetaState(0), mDisableVirtualKeysTimeout(LLONG_MIN), mNextTimeout(LLONG_MAX) {
configureExcludedDevices();
updateGlobalMetaState();
updateInputConfiguration();
@@ -244,16 +244,28 @@
}
void InputReader::loopOnce() {
+ int32_t timeoutMillis = -1;
+ if (mNextTimeout != LLONG_MAX) {
+ nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
+ timeoutMillis = toMillisecondTimeoutDelay(now, mNextTimeout);
+ }
+
RawEvent rawEvent;
- mEventHub->getEvent(& rawEvent);
-
+ if (mEventHub->getEvent(timeoutMillis, &rawEvent)) {
#if DEBUG_RAW_EVENTS
- LOGD("Input event: device=%d type=0x%04x scancode=0x%04x keycode=0x%04x value=0x%04x",
- rawEvent.deviceId, rawEvent.type, rawEvent.scanCode, rawEvent.keyCode,
- rawEvent.value);
+ LOGD("Input event: device=%d type=0x%04x scancode=0x%04x keycode=0x%04x value=0x%04x",
+ rawEvent.deviceId, rawEvent.type, rawEvent.scanCode, rawEvent.keyCode,
+ rawEvent.value);
#endif
-
- process(& rawEvent);
+ process(&rawEvent);
+ } else {
+ nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
+#if DEBUG_RAW_EVENTS
+ LOGD("Timeout expired, latency=%0.3fms", (now - mNextTimeout) * 0.000001f);
+#endif
+ mNextTimeout = LLONG_MAX;
+ timeoutExpired(now);
+ }
}
void InputReader::process(const RawEvent* rawEvent) {
@@ -415,6 +427,19 @@
} // release device registry reader lock
}
+void InputReader::timeoutExpired(nsecs_t when) {
+ { // acquire device registry reader lock
+ RWLock::AutoRLock _rl(mDeviceRegistryLock);
+
+ for (size_t i = 0; i < mDevices.size(); i++) {
+ InputDevice* device = mDevices.valueAt(i);
+ if (!device->isIgnored()) {
+ device->timeoutExpired(when);
+ }
+ }
+ } // release device registry reader lock
+}
+
void InputReader::handleConfigurationChanged(nsecs_t when) {
// Reset global meta state because it depends on the list of all configured devices.
updateGlobalMetaState();
@@ -525,6 +550,12 @@
} // release device registry reader lock
}
+void InputReader::requestTimeoutAtTime(nsecs_t when) {
+ if (when < mNextTimeout) {
+ mNextTimeout = when;
+ }
+}
+
void InputReader::getInputConfiguration(InputConfiguration* outConfiguration) {
{ // acquire state lock
AutoMutex _l(mStateLock);
@@ -762,6 +793,14 @@
}
}
+void InputDevice::timeoutExpired(nsecs_t when) {
+ size_t numMappers = mMappers.size();
+ for (size_t i = 0; i < numMappers; i++) {
+ InputMapper* mapper = mMappers[i];
+ mapper->timeoutExpired(when);
+ }
+}
+
void InputDevice::getDeviceInfo(InputDeviceInfo* outDeviceInfo) {
outDeviceInfo->initialize(mId, mName);
@@ -853,6 +892,9 @@
void InputMapper::reset() {
}
+void InputMapper::timeoutExpired(nsecs_t when) {
+}
+
int32_t InputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
return AKEY_STATE_UNKNOWN;
}
@@ -2556,6 +2598,19 @@
}
void TouchInputMapper::syncTouch(nsecs_t when, bool havePointerIds) {
+#if DEBUG_RAW_EVENTS
+ if (!havePointerIds) {
+ LOGD("syncTouch: pointerCount=%d, no pointer ids", mCurrentTouch.pointerCount);
+ } else {
+ LOGD("syncTouch: pointerCount=%d, up=0x%08x, down=0x%08x, move=0x%08x, "
+ "last=0x%08x, current=0x%08x", mCurrentTouch.pointerCount,
+ mLastTouch.idBits.value & ~mCurrentTouch.idBits.value,
+ mCurrentTouch.idBits.value & ~mLastTouch.idBits.value,
+ mLastTouch.idBits.value & mCurrentTouch.idBits.value,
+ mLastTouch.idBits.value, mCurrentTouch.idBits.value);
+ }
+#endif
+
// Preprocess pointer data.
if (mParameters.useBadTouchFilter) {
if (applyBadTouchFilter()) {
@@ -2569,7 +2624,7 @@
}
}
- if (! havePointerIds) {
+ if (!havePointerIds) {
calculatePointerIds();
}
diff --git a/services/input/InputReader.h b/services/input/InputReader.h
index 55ab479..fdb4cfc 100644
--- a/services/input/InputReader.h
+++ b/services/input/InputReader.h
@@ -159,6 +159,8 @@
virtual void fadePointer() = 0;
+ virtual void requestTimeoutAtTime(nsecs_t when) = 0;
+
virtual InputReaderPolicyInterface* getPolicy() = 0;
virtual InputDispatcherInterface* getDispatcher() = 0;
virtual EventHubInterface* getEventHub() = 0;
@@ -233,6 +235,7 @@
void configureExcludedDevices();
void consumeEvent(const RawEvent* rawEvent);
+ void timeoutExpired(nsecs_t when);
void handleConfigurationChanged(nsecs_t when);
@@ -253,6 +256,9 @@
virtual bool shouldDropVirtualKey(nsecs_t now,
InputDevice* device, int32_t keyCode, int32_t scanCode);
+ nsecs_t mNextTimeout;
+ virtual void requestTimeoutAtTime(nsecs_t when);
+
// state queries
typedef int32_t (InputDevice::*GetStateFunc)(uint32_t sourceMask, int32_t code);
int32_t getState(int32_t deviceId, uint32_t sourceMask, int32_t code,
@@ -296,6 +302,7 @@
void configure();
void reset();
void process(const RawEvent* rawEvent);
+ void timeoutExpired(nsecs_t when);
void getDeviceInfo(InputDeviceInfo* outDeviceInfo);
int32_t getKeyCodeState(uint32_t sourceMask, int32_t keyCode);
@@ -352,6 +359,7 @@
virtual void configure();
virtual void reset();
virtual void process(const RawEvent* rawEvent) = 0;
+ virtual void timeoutExpired(nsecs_t when);
virtual int32_t getKeyCodeState(uint32_t sourceMask, int32_t keyCode);
virtual int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode);
diff --git a/services/input/tests/InputReader_test.cpp b/services/input/tests/InputReader_test.cpp
index 60d5ede..4d92207 100644
--- a/services/input/tests/InputReader_test.cpp
+++ b/services/input/tests/InputReader_test.cpp
@@ -622,7 +622,7 @@
mExcludedDevices.add(String8(deviceName));
}
- virtual bool getEvent(RawEvent* outEvent) {
+ virtual bool getEvent(int timeoutMillis, RawEvent* outEvent) {
if (mEvents.empty()) {
return false;
}
@@ -780,6 +780,9 @@
virtual void fadePointer() {
}
+
+ virtual void requestTimeoutAtTime(nsecs_t when) {
+ }
};