summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/res/res/values/config.xml9
-rw-r--r--services/input/InputReader.cpp53
-rw-r--r--services/input/InputReader.h17
-rw-r--r--services/input/tests/InputReader_test.cpp12
-rw-r--r--services/java/com/android/server/InputManager.java8
-rw-r--r--services/jni/com_android_server_InputManager.cpp26
6 files changed, 121 insertions, 4 deletions
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 8bb05fb..25db21d 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -433,7 +433,14 @@
from the touch driver. This code exists for one particular device,
and should not be enabled for any others. -->
<bool name="config_filterJumpyTouchEvents">false</bool>
-
+
+ <!-- Specifies 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.
+ It is recommended that this value be no more than 250 ms.
+ This feature should be disabled for most devices. -->
+ <integer name="config_virtualKeyQuietTimeMillis">0</integer>
+
<!-- Component name of the default wallpaper. This will be ImageWallpaper if not
specified -->
<string name="default_wallpaper_component">@null</string>
diff --git a/services/input/InputReader.cpp b/services/input/InputReader.cpp
index 6b66791..8e9a5a4 100644
--- a/services/input/InputReader.cpp
+++ b/services/input/InputReader.cpp
@@ -121,7 +121,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();
@@ -373,6 +373,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);
@@ -889,6 +907,12 @@ 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;
@@ -1428,6 +1452,7 @@ void TouchInputMapper::configureParameters() {
mParameters.useBadTouchFilter = getPolicy()->filterTouchEvents();
mParameters.useAveragingTouchFilter = getPolicy()->filterTouchEvents();
mParameters.useJumpyTouchFilter = getPolicy()->filterJumpyTouchEvents();
+ mParameters.virtualKeyQuietTime = getPolicy()->getVirtualKeyQuietTime();
String8 deviceTypeString;
mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_SCREEN;
@@ -2219,6 +2244,7 @@ void TouchInputMapper::syncTouch(nsecs_t when, bool havePointerIds) {
TouchResult touchResult = consumeOffScreenTouches(when, policyFlags);
if (touchResult == DISPATCH_TOUCH) {
+ detectGestures(when);
dispatchTouches(when, policyFlags);
}
@@ -2304,6 +2330,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;
@@ -2341,6 +2372,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;
diff --git a/services/input/InputReader.h b/services/input/InputReader.h
index 8b2d40a..7619682 100644
--- a/services/input/InputReader.h
+++ b/services/input/InputReader.h
@@ -78,6 +78,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 excluded device names for the platform. */
virtual void getExcludedDeviceNames(Vector<String8>& outExcludedDeviceNames) = 0;
@@ -147,6 +153,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;
@@ -234,6 +244,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,
@@ -603,6 +618,7 @@ protected:
bool useBadTouchFilter;
bool useJumpyTouchFilter;
bool useAveragingTouchFilter;
+ nsecs_t virtualKeyQuietTime;
} mParameters;
// Immutable calibration parameters in parsed form.
@@ -839,6 +855,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);
diff --git a/services/input/tests/InputReader_test.cpp b/services/input/tests/InputReader_test.cpp
index 8ec6f53..775747c 100644
--- a/services/input/tests/InputReader_test.cpp
+++ b/services/input/tests/InputReader_test.cpp
@@ -127,6 +127,10 @@ public:
mFilterJumpyTouchEvents = enabled;
}
+ virtual nsecs_t getVirtualKeyQuietTime() {
+ return 0;
+ }
+
void addExcludedDeviceName(const String8& deviceName) {
mExcludedDeviceNames.push(deviceName);
}
@@ -722,6 +726,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;
+ }
};
diff --git a/services/java/com/android/server/InputManager.java b/services/java/com/android/server/InputManager.java
index 06595ae..8d249ff 100644
--- a/services/java/com/android/server/InputManager.java
+++ b/services/java/com/android/server/InputManager.java
@@ -481,7 +481,13 @@ public class InputManager {
return mContext.getResources().getBoolean(
com.android.internal.R.bool.config_filterJumpyTouchEvents);
}
-
+
+ @SuppressWarnings("unused")
+ public int getVirtualKeyQuietTimeMillis() {
+ return mContext.getResources().getInteger(
+ com.android.internal.R.integer.config_virtualKeyQuietTimeMillis);
+ }
+
@SuppressWarnings("unused")
public String[] getExcludedDeviceNames() {
ArrayList<String> names = new ArrayList<String>();
diff --git a/services/jni/com_android_server_InputManager.cpp b/services/jni/com_android_server_InputManager.cpp
index e04e4c3..5b329bb 100644
--- a/services/jni/com_android_server_InputManager.cpp
+++ b/services/jni/com_android_server_InputManager.cpp
@@ -62,6 +62,7 @@ static struct {
jmethodID checkInjectEventsPermission;
jmethodID filterTouchEvents;
jmethodID filterJumpyTouchEvents;
+ jmethodID getVirtualKeyQuietTimeMillis;
jmethodID getExcludedDeviceNames;
jmethodID getMaxEventsPerSecond;
jmethodID getPointerLayer;
@@ -159,6 +160,7 @@ public:
int32_t* width, int32_t* height, int32_t* orientation);
virtual bool filterTouchEvents();
virtual bool filterJumpyTouchEvents();
+ virtual nsecs_t getVirtualKeyQuietTime();
virtual void getExcludedDeviceNames(Vector<String8>& outExcludedDeviceNames);
virtual sp<PointerControllerInterface> obtainPointerController(int32_t deviceId);
@@ -191,6 +193,7 @@ private:
// Cached filtering policies.
int32_t mFilterTouchEvents;
int32_t mFilterJumpyTouchEvents;
+ nsecs_t mVirtualKeyQuietTime;
// Cached throttling policy.
int32_t mMaxEventsPerSecond;
@@ -219,7 +222,7 @@ private:
NativeInputManager::NativeInputManager(jobject callbacksObj) :
- mFilterTouchEvents(-1), mFilterJumpyTouchEvents(-1),
+ mFilterTouchEvents(-1), mFilterJumpyTouchEvents(-1), mVirtualKeyQuietTime(-1),
mMaxEventsPerSecond(-1) {
JNIEnv* env = jniEnv();
@@ -355,6 +358,24 @@ bool NativeInputManager::filterJumpyTouchEvents() {
return mFilterJumpyTouchEvents;
}
+nsecs_t NativeInputManager::getVirtualKeyQuietTime() {
+ if (mVirtualKeyQuietTime < 0) {
+ JNIEnv* env = jniEnv();
+
+ jint result = env->CallIntMethod(mCallbacksObj,
+ gCallbacksClassInfo.getVirtualKeyQuietTimeMillis);
+ if (checkAndClearExceptionFromCallback(env, "getVirtualKeyQuietTimeMillis")) {
+ result = 0;
+ }
+ if (result < 0) {
+ result = 0;
+ }
+
+ mVirtualKeyQuietTime = milliseconds_to_nanoseconds(result);
+ }
+ return mVirtualKeyQuietTime;
+}
+
void NativeInputManager::getExcludedDeviceNames(Vector<String8>& outExcludedDeviceNames) {
outExcludedDeviceNames.clear();
@@ -1155,6 +1176,9 @@ int register_android_server_InputManager(JNIEnv* env) {
GET_METHOD_ID(gCallbacksClassInfo.filterJumpyTouchEvents, gCallbacksClassInfo.clazz,
"filterJumpyTouchEvents", "()Z");
+ GET_METHOD_ID(gCallbacksClassInfo.getVirtualKeyQuietTimeMillis, gCallbacksClassInfo.clazz,
+ "getVirtualKeyQuietTimeMillis", "()I");
+
GET_METHOD_ID(gCallbacksClassInfo.getExcludedDeviceNames, gCallbacksClassInfo.clazz,
"getExcludedDeviceNames", "()[Ljava/lang/String;");