From aa3855d5836d2a2d83baafdf6e40caf90d3dad1c Mon Sep 17 00:00:00 2001 From: Jeff Brown Date: Thu, 17 Mar 2011 01:34:19 -0700 Subject: Refactor how timeouts are calculated. Added a timeout mechanism to EventHub and InputReader so that InputMappers can request timeouts to perform delayed processing of input when needed. Change-Id: Iec2045baaf4e67690b15eef3c09a58d5cac76897 --- services/input/EventHub.cpp | 13 ++++-- services/input/EventHub.h | 9 +++- services/input/InputDispatcher.cpp | 10 +---- services/input/InputReader.cpp | 73 +++++++++++++++++++++++++++---- services/input/InputReader.h | 8 ++++ services/input/tests/InputReader_test.cpp | 5 ++- 6 files changed, 94 insertions(+), 24 deletions(-) (limited to 'services/input') diff --git a/services/input/EventHub.cpp b/services/input/EventHub.cpp index e2da740..b90571b 100644 --- a/services/input/EventHub.cpp +++ b/services/input/EventHub.cpp @@ -445,7 +445,7 @@ EventHub::Device* EventHub::getDeviceLocked(int32_t deviceId) const { 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 @@ bool EventHub::getEvent(RawEvent* outEvent) { // 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 @@ public: * 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 @@ public: 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 ff26fc9..456e0e6 100644 --- a/services/input/InputDispatcher.cpp +++ b/services/input/InputDispatcher.cpp @@ -238,15 +238,7 @@ void InputDispatcher::dispatchOnce() { // 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 @@ InputReader::InputReader(const sp& eventHub, const sp& policy, const sp& 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 @@ InputReader::~InputReader() { } void InputReader::loopOnce() { - RawEvent rawEvent; - mEventHub->getEvent(& rawEvent); + int32_t timeoutMillis = -1; + if (mNextTimeout != LLONG_MAX) { + nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC); + timeoutMillis = toMillisecondTimeoutDelay(now, mNextTimeout); + } + RawEvent 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 @@ void InputReader::consumeEvent(const RawEvent* rawEvent) { } // 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 @@ void InputReader::fadePointer() { } // 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::process(const RawEvent* rawEvent) { } } +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::configure() { 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::reset() { } 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 @@ void TouchInputMapper::syncTouch(nsecs_t when, bool havePointerIds) { } } - 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 @@ public: 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 @@ private: void configureExcludedDevices(); void consumeEvent(const RawEvent* rawEvent); + void timeoutExpired(nsecs_t when); void handleConfigurationChanged(nsecs_t when); @@ -253,6 +256,9 @@ private: 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 @@ public: 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 @@ public: 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 075eff3..120951d 100644 --- a/services/input/tests/InputReader_test.cpp +++ b/services/input/tests/InputReader_test.cpp @@ -610,7 +610,7 @@ private: mExcludedDevices.add(String8(deviceName)); } - virtual bool getEvent(RawEvent* outEvent) { + virtual bool getEvent(int timeoutMillis, RawEvent* outEvent) { if (mEvents.empty()) { return false; } @@ -768,6 +768,9 @@ private: virtual void fadePointer() { } + + virtual void requestTimeoutAtTime(nsecs_t when) { + } }; -- cgit v1.1