Filter virtual keys after touches. (DO NOT MERGE)
Adds a new virtualKeyQuietTimeMillis configuration resource that sets
the duration for which virtual keys will be dropped after recent touches
on screen. The default value is 0; it is intended to be overridden
per device using a resource overlay.
This change is designed to help in two cases:
1. Swipes from touchscreen into virtual key area.
2. Accidental taps in virtual key area while using on-screen keyboard.
Bug: 3089163
Change-Id: Id6733c83c2e2bc8d9553aa0e5c1fd74b741bec6e
diff --git a/include/ui/InputReader.h b/include/ui/InputReader.h
index 49351b0..7568ba7 100644
--- a/include/ui/InputReader.h
+++ b/include/ui/InputReader.h
@@ -103,6 +103,12 @@
*/
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;
@@ -177,6 +183,10 @@
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;
@@ -264,6 +274,11 @@
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,
@@ -585,6 +600,7 @@
bool useBadTouchFilter;
bool useJumpyTouchFilter;
bool useAveragingTouchFilter;
+ nsecs_t virtualKeyQuietTime;
} mParameters;
// Immutable calibration parameters in parsed form.
@@ -810,6 +826,7 @@
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);
diff --git a/libs/ui/InputReader.cpp b/libs/ui/InputReader.cpp
index 3197ab2..83b382b 100644
--- a/libs/ui/InputReader.cpp
+++ b/libs/ui/InputReader.cpp
@@ -198,7 +198,7 @@
const sp<InputReaderPolicyInterface>& policy,
const sp<InputDispatcherInterface>& dispatcher) :
mEventHub(eventHub), mPolicy(policy), mDispatcher(dispatcher),
- mGlobalMetaState(0) {
+ mGlobalMetaState(0), mDisableVirtualKeysTimeout(-1) {
configureExcludedDevices();
updateGlobalMetaState();
updateInputConfiguration();
@@ -453,6 +453,24 @@
} // 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);
@@ -937,6 +955,11 @@
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;
@@ -1340,6 +1363,7 @@
mParameters.useBadTouchFilter = getPolicy()->filterTouchEvents();
mParameters.useAveragingTouchFilter = getPolicy()->filterTouchEvents();
mParameters.useJumpyTouchFilter = getPolicy()->filterJumpyTouchEvents();
+ mParameters.virtualKeyQuietTime = getPolicy()->getVirtualKeyQuietTime();
}
void TouchInputMapper::dumpParameters(String8& dump) {
@@ -2060,6 +2084,7 @@
TouchResult touchResult = consumeOffScreenTouches(when, policyFlags);
if (touchResult == DISPATCH_TOUCH) {
+ detectGestures(when);
dispatchTouches(when, policyFlags);
}
@@ -2145,6 +2170,11 @@
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;
@@ -2182,6 +2212,26 @@
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;
diff --git a/libs/ui/tests/InputReader_test.cpp b/libs/ui/tests/InputReader_test.cpp
index de4b05a..f31a6be 100644
--- a/libs/ui/tests/InputReader_test.cpp
+++ b/libs/ui/tests/InputReader_test.cpp
@@ -131,6 +131,10 @@
return mFilterJumpyTouchEvents;
}
+ virtual nsecs_t getVirtualKeyQuietTime() {
+ return 0;
+ }
+
virtual void getVirtualKeyDefinitions(const String8& deviceName,
Vector<VirtualKeyDefinition>& outVirtualKeyDefinitions) {
ssize_t index = mVirtualKeyDefinitions.indexOfKey(deviceName);
@@ -631,6 +635,14 @@
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;
+ }
};