Loading include/ui/InputReader.h +17 −0 Original line number Diff line number Diff line Loading @@ -103,6 +103,12 @@ public: */ virtual bool filterJumpyTouchEvents() = 0; /* Gets the amount of time to disable virtual keys after the screen is touched * in order to filter out accidental virtual key presses due to swiping gestures * or taps near the edge of the display. May be 0 to disable the feature. */ virtual nsecs_t getVirtualKeyQuietTime() = 0; /* Gets the configured virtual key definitions for an input device. */ virtual void getVirtualKeyDefinitions(const String8& deviceName, Vector<VirtualKeyDefinition>& outVirtualKeyDefinitions) = 0; Loading Loading @@ -177,6 +183,10 @@ public: virtual void updateGlobalMetaState() = 0; virtual int32_t getGlobalMetaState() = 0; virtual void disableVirtualKeysUntil(nsecs_t time) = 0; virtual bool shouldDropVirtualKey(nsecs_t now, InputDevice* device, int32_t keyCode, int32_t scanCode) = 0; virtual InputReaderPolicyInterface* getPolicy() = 0; virtual InputDispatcherInterface* getDispatcher() = 0; virtual EventHubInterface* getEventHub() = 0; Loading Loading @@ -264,6 +274,11 @@ private: InputConfiguration mInputConfiguration; void updateInputConfiguration(); nsecs_t mDisableVirtualKeysTimeout; virtual void disableVirtualKeysUntil(nsecs_t time); virtual bool shouldDropVirtualKey(nsecs_t now, InputDevice* device, int32_t keyCode, int32_t scanCode); // 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, Loading Loading @@ -585,6 +600,7 @@ protected: bool useBadTouchFilter; bool useJumpyTouchFilter; bool useAveragingTouchFilter; nsecs_t virtualKeyQuietTime; } mParameters; // Immutable calibration parameters in parsed form. Loading Loading @@ -810,6 +826,7 @@ private: void dispatchTouch(nsecs_t when, uint32_t policyFlags, TouchData* touch, BitSet32 idBits, uint32_t changedId, uint32_t pointerCount, int32_t motionEventAction); void detectGestures(nsecs_t when); bool isPointInsideSurfaceLocked(int32_t x, int32_t y); const VirtualKey* findVirtualKeyHitLocked(int32_t x, int32_t y); Loading libs/ui/InputReader.cpp +51 −1 Original line number Diff line number Diff line Loading @@ -198,7 +198,7 @@ InputReader::InputReader(const sp<EventHubInterface>& eventHub, const sp<InputReaderPolicyInterface>& policy, const sp<InputDispatcherInterface>& dispatcher) : mEventHub(eventHub), mPolicy(policy), mDispatcher(dispatcher), mGlobalMetaState(0) { mGlobalMetaState(0), mDisableVirtualKeysTimeout(-1) { configureExcludedDevices(); updateGlobalMetaState(); updateInputConfiguration(); Loading Loading @@ -453,6 +453,24 @@ void InputReader::updateInputConfiguration() { } // release state lock } void InputReader::disableVirtualKeysUntil(nsecs_t time) { mDisableVirtualKeysTimeout = time; } bool InputReader::shouldDropVirtualKey(nsecs_t now, InputDevice* device, int32_t keyCode, int32_t scanCode) { if (now < mDisableVirtualKeysTimeout) { LOGI("Dropping virtual key from device %s because virtual keys are " "temporarily disabled for the next %0.3fms. keyCode=%d, scanCode=%d", device->getName().string(), (mDisableVirtualKeysTimeout - now) * 0.000001, keyCode, scanCode); return true; } else { return false; } } void InputReader::getInputConfiguration(InputConfiguration* outConfiguration) { { // acquire state lock AutoMutex _l(mStateLock); Loading Loading @@ -937,6 +955,11 @@ void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t keyCode, keyCode = mLocked.keyDowns.itemAt(keyDownIndex).keyCode; } else { // key down if ((policyFlags & POLICY_FLAG_VIRTUAL) && mContext->shouldDropVirtualKey(when, getDevice(), keyCode, scanCode)) { return; } mLocked.keyDowns.push(); KeyDown& keyDown = mLocked.keyDowns.editTop(); keyDown.keyCode = keyCode; Loading Loading @@ -1340,6 +1363,7 @@ void TouchInputMapper::configureParameters() { mParameters.useBadTouchFilter = getPolicy()->filterTouchEvents(); mParameters.useAveragingTouchFilter = getPolicy()->filterTouchEvents(); mParameters.useJumpyTouchFilter = getPolicy()->filterJumpyTouchEvents(); mParameters.virtualKeyQuietTime = getPolicy()->getVirtualKeyQuietTime(); } void TouchInputMapper::dumpParameters(String8& dump) { Loading Loading @@ -2060,6 +2084,7 @@ void TouchInputMapper::syncTouch(nsecs_t when, bool havePointerIds) { TouchResult touchResult = consumeOffScreenTouches(when, policyFlags); if (touchResult == DISPATCH_TOUCH) { detectGestures(when); dispatchTouches(when, policyFlags); } Loading Loading @@ -2145,6 +2170,11 @@ TouchInputMapper::TouchResult TouchInputMapper::consumeOffScreenTouches( if (mCurrentTouch.pointerCount == 1) { const VirtualKey* virtualKey = findVirtualKeyHitLocked(x, y); if (virtualKey) { if (mContext->shouldDropVirtualKey(when, getDevice(), virtualKey->keyCode, virtualKey->scanCode)) { return DROP_STROKE; } mLocked.currentVirtualKey.down = true; mLocked.currentVirtualKey.downTime = when; mLocked.currentVirtualKey.keyCode = virtualKey->keyCode; Loading Loading @@ -2182,6 +2212,26 @@ TouchInputMapper::TouchResult TouchInputMapper::consumeOffScreenTouches( return touchResult; } void TouchInputMapper::detectGestures(nsecs_t when) { // Disable all virtual key touches that happen within a short time interval of the // most recent touch. The idea is to filter out stray virtual key presses when // interacting with the touch screen. // // Problems we're trying to solve: // // 1. While scrolling a list or dragging the window shade, the user swipes down into a // virtual key area that is implemented by a separate touch panel and accidentally // triggers a virtual key. // // 2. While typing in the on screen keyboard, the user taps slightly outside the screen // area and accidentally triggers a virtual key. This often happens when virtual keys // are layed out below the screen near to where the on screen keyboard's space bar // is displayed. if (mParameters.virtualKeyQuietTime > 0 && mCurrentTouch.pointerCount != 0) { mContext->disableVirtualKeysUntil(when + mParameters.virtualKeyQuietTime); } } void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) { uint32_t currentPointerCount = mCurrentTouch.pointerCount; uint32_t lastPointerCount = mLastTouch.pointerCount; Loading libs/ui/tests/InputReader_test.cpp +12 −0 Original line number Diff line number Diff line Loading @@ -131,6 +131,10 @@ private: return mFilterJumpyTouchEvents; } virtual nsecs_t getVirtualKeyQuietTime() { return 0; } virtual void getVirtualKeyDefinitions(const String8& deviceName, Vector<VirtualKeyDefinition>& outVirtualKeyDefinitions) { ssize_t index = mVirtualKeyDefinitions.indexOfKey(deviceName); Loading Loading @@ -631,6 +635,14 @@ private: virtual InputDispatcherInterface* getDispatcher() { return mDispatcher.get(); } virtual void disableVirtualKeysUntil(nsecs_t time) { } virtual bool shouldDropVirtualKey(nsecs_t now, InputDevice* device, int32_t keyCode, int32_t scanCode) { return false; } }; Loading Loading
include/ui/InputReader.h +17 −0 Original line number Diff line number Diff line Loading @@ -103,6 +103,12 @@ public: */ virtual bool filterJumpyTouchEvents() = 0; /* Gets the amount of time to disable virtual keys after the screen is touched * in order to filter out accidental virtual key presses due to swiping gestures * or taps near the edge of the display. May be 0 to disable the feature. */ virtual nsecs_t getVirtualKeyQuietTime() = 0; /* Gets the configured virtual key definitions for an input device. */ virtual void getVirtualKeyDefinitions(const String8& deviceName, Vector<VirtualKeyDefinition>& outVirtualKeyDefinitions) = 0; Loading Loading @@ -177,6 +183,10 @@ public: virtual void updateGlobalMetaState() = 0; virtual int32_t getGlobalMetaState() = 0; virtual void disableVirtualKeysUntil(nsecs_t time) = 0; virtual bool shouldDropVirtualKey(nsecs_t now, InputDevice* device, int32_t keyCode, int32_t scanCode) = 0; virtual InputReaderPolicyInterface* getPolicy() = 0; virtual InputDispatcherInterface* getDispatcher() = 0; virtual EventHubInterface* getEventHub() = 0; Loading Loading @@ -264,6 +274,11 @@ private: InputConfiguration mInputConfiguration; void updateInputConfiguration(); nsecs_t mDisableVirtualKeysTimeout; virtual void disableVirtualKeysUntil(nsecs_t time); virtual bool shouldDropVirtualKey(nsecs_t now, InputDevice* device, int32_t keyCode, int32_t scanCode); // 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, Loading Loading @@ -585,6 +600,7 @@ protected: bool useBadTouchFilter; bool useJumpyTouchFilter; bool useAveragingTouchFilter; nsecs_t virtualKeyQuietTime; } mParameters; // Immutable calibration parameters in parsed form. Loading Loading @@ -810,6 +826,7 @@ private: void dispatchTouch(nsecs_t when, uint32_t policyFlags, TouchData* touch, BitSet32 idBits, uint32_t changedId, uint32_t pointerCount, int32_t motionEventAction); void detectGestures(nsecs_t when); bool isPointInsideSurfaceLocked(int32_t x, int32_t y); const VirtualKey* findVirtualKeyHitLocked(int32_t x, int32_t y); Loading
libs/ui/InputReader.cpp +51 −1 Original line number Diff line number Diff line Loading @@ -198,7 +198,7 @@ InputReader::InputReader(const sp<EventHubInterface>& eventHub, const sp<InputReaderPolicyInterface>& policy, const sp<InputDispatcherInterface>& dispatcher) : mEventHub(eventHub), mPolicy(policy), mDispatcher(dispatcher), mGlobalMetaState(0) { mGlobalMetaState(0), mDisableVirtualKeysTimeout(-1) { configureExcludedDevices(); updateGlobalMetaState(); updateInputConfiguration(); Loading Loading @@ -453,6 +453,24 @@ void InputReader::updateInputConfiguration() { } // release state lock } void InputReader::disableVirtualKeysUntil(nsecs_t time) { mDisableVirtualKeysTimeout = time; } bool InputReader::shouldDropVirtualKey(nsecs_t now, InputDevice* device, int32_t keyCode, int32_t scanCode) { if (now < mDisableVirtualKeysTimeout) { LOGI("Dropping virtual key from device %s because virtual keys are " "temporarily disabled for the next %0.3fms. keyCode=%d, scanCode=%d", device->getName().string(), (mDisableVirtualKeysTimeout - now) * 0.000001, keyCode, scanCode); return true; } else { return false; } } void InputReader::getInputConfiguration(InputConfiguration* outConfiguration) { { // acquire state lock AutoMutex _l(mStateLock); Loading Loading @@ -937,6 +955,11 @@ void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t keyCode, keyCode = mLocked.keyDowns.itemAt(keyDownIndex).keyCode; } else { // key down if ((policyFlags & POLICY_FLAG_VIRTUAL) && mContext->shouldDropVirtualKey(when, getDevice(), keyCode, scanCode)) { return; } mLocked.keyDowns.push(); KeyDown& keyDown = mLocked.keyDowns.editTop(); keyDown.keyCode = keyCode; Loading Loading @@ -1340,6 +1363,7 @@ void TouchInputMapper::configureParameters() { mParameters.useBadTouchFilter = getPolicy()->filterTouchEvents(); mParameters.useAveragingTouchFilter = getPolicy()->filterTouchEvents(); mParameters.useJumpyTouchFilter = getPolicy()->filterJumpyTouchEvents(); mParameters.virtualKeyQuietTime = getPolicy()->getVirtualKeyQuietTime(); } void TouchInputMapper::dumpParameters(String8& dump) { Loading Loading @@ -2060,6 +2084,7 @@ void TouchInputMapper::syncTouch(nsecs_t when, bool havePointerIds) { TouchResult touchResult = consumeOffScreenTouches(when, policyFlags); if (touchResult == DISPATCH_TOUCH) { detectGestures(when); dispatchTouches(when, policyFlags); } Loading Loading @@ -2145,6 +2170,11 @@ TouchInputMapper::TouchResult TouchInputMapper::consumeOffScreenTouches( if (mCurrentTouch.pointerCount == 1) { const VirtualKey* virtualKey = findVirtualKeyHitLocked(x, y); if (virtualKey) { if (mContext->shouldDropVirtualKey(when, getDevice(), virtualKey->keyCode, virtualKey->scanCode)) { return DROP_STROKE; } mLocked.currentVirtualKey.down = true; mLocked.currentVirtualKey.downTime = when; mLocked.currentVirtualKey.keyCode = virtualKey->keyCode; Loading Loading @@ -2182,6 +2212,26 @@ TouchInputMapper::TouchResult TouchInputMapper::consumeOffScreenTouches( return touchResult; } void TouchInputMapper::detectGestures(nsecs_t when) { // Disable all virtual key touches that happen within a short time interval of the // most recent touch. The idea is to filter out stray virtual key presses when // interacting with the touch screen. // // Problems we're trying to solve: // // 1. While scrolling a list or dragging the window shade, the user swipes down into a // virtual key area that is implemented by a separate touch panel and accidentally // triggers a virtual key. // // 2. While typing in the on screen keyboard, the user taps slightly outside the screen // area and accidentally triggers a virtual key. This often happens when virtual keys // are layed out below the screen near to where the on screen keyboard's space bar // is displayed. if (mParameters.virtualKeyQuietTime > 0 && mCurrentTouch.pointerCount != 0) { mContext->disableVirtualKeysUntil(when + mParameters.virtualKeyQuietTime); } } void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) { uint32_t currentPointerCount = mCurrentTouch.pointerCount; uint32_t lastPointerCount = mLastTouch.pointerCount; Loading
libs/ui/tests/InputReader_test.cpp +12 −0 Original line number Diff line number Diff line Loading @@ -131,6 +131,10 @@ private: return mFilterJumpyTouchEvents; } virtual nsecs_t getVirtualKeyQuietTime() { return 0; } virtual void getVirtualKeyDefinitions(const String8& deviceName, Vector<VirtualKeyDefinition>& outVirtualKeyDefinitions) { ssize_t index = mVirtualKeyDefinitions.indexOfKey(deviceName); Loading Loading @@ -631,6 +635,14 @@ private: virtual InputDispatcherInterface* getDispatcher() { return mDispatcher.get(); } virtual void disableVirtualKeysUntil(nsecs_t time) { } virtual bool shouldDropVirtualKey(nsecs_t now, InputDevice* device, int32_t keyCode, int32_t scanCode) { return false; } }; Loading