am f4368c95: Merge "Filter virtual keys after touches." into honeycomb

* commit 'f4368c959fa9436d75feb2543cb65da0d46521e5':
  Filter virtual keys after touches.
This commit is contained in:
Jeff Brown
2011-01-18 15:29:28 -08:00
committed by Android Git Automerger
6 changed files with 121 additions and 4 deletions

View File

@ -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>

View File

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

View File

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

View File

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

View File

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

View File

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