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
This commit is contained in:
Jeff Brown 2010-10-24 14:39:33 -07:00
parent e9bef148d2
commit 7bfdb29e53
3 changed files with 80 additions and 1 deletions

View File

@ -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;
@ -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;
@ -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,
@ -585,6 +600,7 @@ protected:
bool useBadTouchFilter;
bool useJumpyTouchFilter;
bool useAveragingTouchFilter;
nsecs_t virtualKeyQuietTime;
} mParameters;
// Immutable calibration parameters in parsed form.
@ -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);

View File

@ -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();
@ -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);
@ -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;
@ -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) {
@ -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);
}
@ -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;
@ -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;

View File

@ -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);
@ -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;
}
};