diff options
author | Jeff Brown <jeffbrown@google.com> | 2011-01-18 15:10:10 -0800 |
---|---|---|
committer | Jeff Brown <jeffbrown@google.com> | 2011-01-18 15:10:45 -0800 |
commit | fe50892af3b365806a767298dfd8e86447682581 (patch) | |
tree | 87df90a1ee452db7b6c096570e51181bcd919e74 | |
parent | c10803924e45e9a607b3c5bb74316c0a84d78cd8 (diff) | |
download | frameworks_base-fe50892af3b365806a767298dfd8e86447682581.zip frameworks_base-fe50892af3b365806a767298dfd8e86447682581.tar.gz frameworks_base-fe50892af3b365806a767298dfd8e86447682581.tar.bz2 |
Filter virtual keys after touches.
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: Ib912d4f8a4df9966a39cd537d3ec7c24afab7225
-rw-r--r-- | core/res/res/values/config.xml | 9 | ||||
-rw-r--r-- | services/input/InputReader.cpp | 53 | ||||
-rw-r--r-- | services/input/InputReader.h | 17 | ||||
-rw-r--r-- | services/input/tests/InputReader_test.cpp | 12 | ||||
-rw-r--r-- | services/java/com/android/server/InputManager.java | 8 | ||||
-rw-r--r-- | services/jni/com_android_server_InputManager.cpp | 26 |
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;"); |