summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeff Brown <jeffbrown@android.com>2011-05-31 15:42:18 -0700
committerAndroid (Google) Code Review <android-gerrit@google.com>2011-05-31 15:42:18 -0700
commitc272d4279493000928b8b7c6dbcf2d2b7d8d08b2 (patch)
tree63921d7f9beaa9580876bdacca8df46e4bcc38e7
parentd854304c2bcadbda37a7f1b24723dbc0030073ca (diff)
parent214eaf48878bba00cbd5831871bcbd82632b6e34 (diff)
downloadframeworks_base-c272d4279493000928b8b7c6dbcf2d2b7d8d08b2.zip
frameworks_base-c272d4279493000928b8b7c6dbcf2d2b7d8d08b2.tar.gz
frameworks_base-c272d4279493000928b8b7c6dbcf2d2b7d8d08b2.tar.bz2
Merge "Use ViewConfiguration to seed input system configuration." into honeycomb-mr2
-rw-r--r--services/input/InputDispatcher.cpp37
-rw-r--r--services/input/InputDispatcher.h46
-rw-r--r--services/input/InputReader.cpp175
-rw-r--r--services/input/InputReader.h136
-rw-r--r--services/input/tests/InputDispatcher_test.cpp14
-rw-r--r--services/input/tests/InputReader_test.cpp32
-rw-r--r--services/java/com/android/server/wm/InputManager.java20
-rw-r--r--services/jni/com_android_server_InputManager.cpp215
8 files changed, 384 insertions, 291 deletions
diff --git a/services/input/InputDispatcher.cpp b/services/input/InputDispatcher.cpp
index 9a77af3..5ea12c7 100644
--- a/services/input/InputDispatcher.cpp
+++ b/services/input/InputDispatcher.cpp
@@ -222,13 +222,14 @@ InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& polic
mKeyRepeatState.lastKeyEntry = NULL;
- int32_t maxEventsPerSecond = policy->getMaxEventsPerSecond();
- mThrottleState.minTimeBetweenEvents = 1000000000LL / maxEventsPerSecond;
+ policy->getDispatcherConfiguration(&mConfig);
+
+ mThrottleState.minTimeBetweenEvents = 1000000000LL / mConfig.maxEventsPerSecond;
mThrottleState.lastDeviceId = -1;
#if DEBUG_THROTTLING
mThrottleState.originalSampleCount = 0;
- LOGD("Throttling - Max events per second = %d", maxEventsPerSecond);
+ LOGD("Throttling - Max events per second = %d", mConfig.maxEventsPerSecond);
#endif
}
@@ -247,13 +248,10 @@ InputDispatcher::~InputDispatcher() {
}
void InputDispatcher::dispatchOnce() {
- nsecs_t keyRepeatTimeout = mPolicy->getKeyRepeatTimeout();
- nsecs_t keyRepeatDelay = mPolicy->getKeyRepeatDelay();
-
nsecs_t nextWakeupTime = LONG_LONG_MAX;
{ // acquire lock
AutoMutex _l(mLock);
- dispatchOnceInnerLocked(keyRepeatTimeout, keyRepeatDelay, & nextWakeupTime);
+ dispatchOnceInnerLocked(&nextWakeupTime);
if (runCommandsLockedInterruptible()) {
nextWakeupTime = LONG_LONG_MIN; // force next poll to wake up immediately
@@ -266,14 +264,13 @@ void InputDispatcher::dispatchOnce() {
mLooper->pollOnce(timeoutMillis);
}
-void InputDispatcher::dispatchOnceInnerLocked(nsecs_t keyRepeatTimeout,
- nsecs_t keyRepeatDelay, nsecs_t* nextWakeupTime) {
+void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) {
nsecs_t currentTime = now();
// Reset the key repeat timer whenever we disallow key events, even if the next event
// is not a key. This is to ensure that we abort a key repeat if the device is just coming
// out of sleep.
- if (keyRepeatTimeout < 0) {
+ if (!mPolicy->isKeyRepeatEnabled()) {
resetKeyRepeatLocked();
}
@@ -307,7 +304,7 @@ void InputDispatcher::dispatchOnceInnerLocked(nsecs_t keyRepeatTimeout,
// Synthesize a key repeat if appropriate.
if (mKeyRepeatState.lastKeyEntry) {
if (currentTime >= mKeyRepeatState.nextRepeatTime) {
- mPendingEvent = synthesizeKeyRepeatLocked(currentTime, keyRepeatDelay);
+ mPendingEvent = synthesizeKeyRepeatLocked(currentTime);
} else {
if (mKeyRepeatState.nextRepeatTime < *nextWakeupTime) {
*nextWakeupTime = mKeyRepeatState.nextRepeatTime;
@@ -426,8 +423,7 @@ void InputDispatcher::dispatchOnceInnerLocked(nsecs_t keyRepeatTimeout,
if (dropReason == DROP_REASON_NOT_DROPPED && mNextUnblockedEvent) {
dropReason = DROP_REASON_BLOCKED;
}
- done = dispatchKeyLocked(currentTime, typedEntry, keyRepeatTimeout,
- &dropReason, nextWakeupTime);
+ done = dispatchKeyLocked(currentTime, typedEntry, &dropReason, nextWakeupTime);
break;
}
@@ -686,8 +682,7 @@ void InputDispatcher::resetKeyRepeatLocked() {
}
}
-InputDispatcher::KeyEntry* InputDispatcher::synthesizeKeyRepeatLocked(
- nsecs_t currentTime, nsecs_t keyRepeatDelay) {
+InputDispatcher::KeyEntry* InputDispatcher::synthesizeKeyRepeatLocked(nsecs_t currentTime) {
KeyEntry* entry = mKeyRepeatState.lastKeyEntry;
// Reuse the repeated key entry if it is otherwise unreferenced.
@@ -715,7 +710,7 @@ InputDispatcher::KeyEntry* InputDispatcher::synthesizeKeyRepeatLocked(
// mKeyRepeatState.lastKeyEntry in addition to the one we return.
entry->refCount += 1;
- mKeyRepeatState.nextRepeatTime = currentTime + keyRepeatDelay;
+ mKeyRepeatState.nextRepeatTime = currentTime + mConfig.keyRepeatDelay;
return entry;
}
@@ -735,8 +730,7 @@ bool InputDispatcher::dispatchConfigurationChangedLocked(
return true;
}
-bool InputDispatcher::dispatchKeyLocked(
- nsecs_t currentTime, KeyEntry* entry, nsecs_t keyRepeatTimeout,
+bool InputDispatcher::dispatchKeyLocked(nsecs_t currentTime, KeyEntry* entry,
DropReason* dropReason, nsecs_t* nextWakeupTime) {
// Preprocessing.
if (! entry->dispatchInProgress) {
@@ -756,7 +750,7 @@ bool InputDispatcher::dispatchKeyLocked(
} else {
// Not a repeat. Save key down state in case we do see a repeat later.
resetKeyRepeatLocked();
- mKeyRepeatState.nextRepeatTime = entry->eventTime + keyRepeatTimeout;
+ mKeyRepeatState.nextRepeatTime = entry->eventTime + mConfig.keyRepeatTimeout;
}
mKeyRepeatState.lastKeyEntry = entry;
entry->refCount += 1;
@@ -3510,6 +3504,11 @@ void InputDispatcher::updateDispatchStatisticsLocked(nsecs_t currentTime, const
void InputDispatcher::dump(String8& dump) {
dump.append("Input Dispatcher State:\n");
dumpDispatchStateLocked(dump);
+
+ dump.append(INDENT "Configuration:\n");
+ dump.appendFormat(INDENT2 "MaxEventsPerSecond: %d\n", mConfig.maxEventsPerSecond);
+ dump.appendFormat(INDENT2 "KeyRepeatDelay: %0.1fms\n", mConfig.keyRepeatDelay * 0.000001f);
+ dump.appendFormat(INDENT2 "KeyRepeatTimeout: %0.1fms\n", mConfig.keyRepeatTimeout * 0.000001f);
}
diff --git a/services/input/InputDispatcher.h b/services/input/InputDispatcher.h
index 39fa203..5631ef9 100644
--- a/services/input/InputDispatcher.h
+++ b/services/input/InputDispatcher.h
@@ -123,6 +123,30 @@ struct InputTarget {
/*
+ * Input dispatcher configuration.
+ *
+ * Specifies various options that modify the behavior of the input dispatcher.
+ */
+struct InputDispatcherConfiguration {
+ // The key repeat initial timeout.
+ nsecs_t keyRepeatTimeout;
+
+ // The key repeat inter-key delay.
+ nsecs_t keyRepeatDelay;
+
+ // The maximum suggested event delivery rate per second.
+ // This value is used to throttle motion event movement actions on a per-device
+ // basis. It is not intended to be a hard limit.
+ int32_t maxEventsPerSecond;
+
+ InputDispatcherConfiguration() :
+ keyRepeatTimeout(500 * 1000000LL),
+ keyRepeatDelay(50 * 1000000LL),
+ maxEventsPerSecond(60) { }
+};
+
+
+/*
* Input dispatcher policy interface.
*
* The input reader policy is used by the input reader to interact with the Window Manager
@@ -148,17 +172,11 @@ public:
/* Notifies the system that an input channel is unrecoverably broken. */
virtual void notifyInputChannelBroken(const sp<InputWindowHandle>& inputWindowHandle) = 0;
- /* Gets the key repeat initial timeout or -1 if automatic key repeating is disabled. */
- virtual nsecs_t getKeyRepeatTimeout() = 0;
-
- /* Gets the key repeat inter-key delay. */
- virtual nsecs_t getKeyRepeatDelay() = 0;
+ /* Gets the input dispatcher configuration. */
+ virtual void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) = 0;
- /* Gets the maximum suggested event delivery rate per second.
- * This value is used to throttle motion event movement actions on a per-device
- * basis. It is not intended to be a hard limit.
- */
- virtual int32_t getMaxEventsPerSecond() = 0;
+ /* Returns true if automatic key repeating is enabled. */
+ virtual bool isKeyRepeatEnabled() = 0;
/* Intercepts a key event immediately before queueing it.
* The policy can use this method as an opportunity to perform power management functions
@@ -757,6 +775,7 @@ private:
};
sp<InputDispatcherPolicyInterface> mPolicy;
+ InputDispatcherConfiguration mConfig;
Mutex mLock;
@@ -769,8 +788,7 @@ private:
Vector<EventEntry*> mTempCancelationEvents;
- void dispatchOnceInnerLocked(nsecs_t keyRepeatTimeout, nsecs_t keyRepeatDelay,
- nsecs_t* nextWakeupTime);
+ void dispatchOnceInnerLocked(nsecs_t* nextWakeupTime);
// Batches a new sample onto a motion entry.
// Assumes that the we have already checked that we can append samples.
@@ -842,7 +860,7 @@ private:
} mKeyRepeatState;
void resetKeyRepeatLocked();
- KeyEntry* synthesizeKeyRepeatLocked(nsecs_t currentTime, nsecs_t keyRepeatTimeout);
+ KeyEntry* synthesizeKeyRepeatLocked(nsecs_t currentTime);
// Deferred command processing.
bool runCommandsLockedInterruptible();
@@ -899,7 +917,7 @@ private:
bool dispatchConfigurationChangedLocked(
nsecs_t currentTime, ConfigurationChangedEntry* entry);
bool dispatchKeyLocked(
- nsecs_t currentTime, KeyEntry* entry, nsecs_t keyRepeatTimeout,
+ nsecs_t currentTime, KeyEntry* entry,
DropReason* dropReason, nsecs_t* nextWakeupTime);
bool dispatchMotionLocked(
nsecs_t currentTime, MotionEntry* entry,
diff --git a/services/input/InputReader.cpp b/services/input/InputReader.cpp
index 155fd2d..f2b34dd 100644
--- a/services/input/InputReader.cpp
+++ b/services/input/InputReader.cpp
@@ -56,67 +56,6 @@
namespace android {
-// --- Constants ---
-
-// Quiet time between certain gesture transitions.
-// Time to allow for all fingers or buttons to settle into a stable state before
-// starting a new gesture.
-static const nsecs_t QUIET_INTERVAL = 100 * 1000000; // 100 ms
-
-// The minimum speed that a pointer must travel for us to consider switching the active
-// touch pointer to it during a drag. This threshold is set to avoid switching due
-// to noise from a finger resting on the touch pad (perhaps just pressing it down).
-static const float DRAG_MIN_SWITCH_SPEED = 50.0f; // pixels per second
-
-// Tap gesture delay time.
-// The time between down and up must be less than this to be considered a tap.
-static const nsecs_t TAP_INTERVAL = 150 * 1000000; // 150 ms
-
-// Tap drag gesture delay time.
-// The time between up and the next up must be greater than this to be considered a
-// drag. Otherwise, the previous tap is finished and a new tap begins.
-static const nsecs_t TAP_DRAG_INTERVAL = 150 * 1000000; // 150 ms
-
-// The distance in pixels that the pointer is allowed to move from initial down
-// to up and still be called a tap.
-static const float TAP_SLOP = 10.0f; // 10 pixels
-
-// Time after the first touch points go down to settle on an initial centroid.
-// This is intended to be enough time to handle cases where the user puts down two
-// fingers at almost but not quite exactly the same time.
-static const nsecs_t MULTITOUCH_SETTLE_INTERVAL = 100 * 1000000; // 100ms
-
-// The transition from PRESS to SWIPE or FREEFORM gesture mode is made when
-// both of the pointers are moving at least this fast.
-static const float MULTITOUCH_MIN_SPEED = 150.0f; // pixels per second
-
-// The transition from PRESS to SWIPE gesture mode can only occur when the
-// cosine of the angle between the two vectors is greater than or equal to than this value
-// which indicates that the vectors are oriented in the same direction.
-// When the vectors are oriented in the exactly same direction, the cosine is 1.0.
-// (In exactly opposite directions, the cosine is -1.0.)
-static const float SWIPE_TRANSITION_ANGLE_COSINE = 0.5f; // cosine of 45 degrees
-
-// The transition from PRESS to SWIPE gesture mode can only occur when the
-// fingers are no more than this far apart relative to the diagonal size of
-// the touch pad. For example, a ratio of 0.5 means that the fingers must be
-// no more than half the diagonal size of the touch pad apart.
-static const float SWIPE_MAX_WIDTH_RATIO = 0.333f; // 1/3
-
-// The gesture movement speed factor relative to the size of the display.
-// Movement speed applies when the fingers are moving in the same direction.
-// Without acceleration, a full swipe of the touch pad diagonal in movement mode
-// will cover this portion of the display diagonal.
-static const float GESTURE_MOVEMENT_SPEED_RATIO = 0.8f;
-
-// The gesture zoom speed factor relative to the size of the display.
-// Zoom speed applies when the fingers are mostly moving relative to each other
-// to execute a scale gesture or similar.
-// Without acceleration, a full swipe of the touch pad diagonal in zoom mode
-// will cover this portion of the display diagonal.
-static const float GESTURE_ZOOM_SPEED_RATIO = 0.3f;
-
-
// --- Static Functions ---
template<typename T>
@@ -281,6 +220,8 @@ InputReader::InputReader(const sp<EventHubInterface>& eventHub,
const sp<InputDispatcherInterface>& dispatcher) :
mEventHub(eventHub), mPolicy(policy), mDispatcher(dispatcher),
mGlobalMetaState(0), mDisableVirtualKeysTimeout(LLONG_MIN), mNextTimeout(LLONG_MAX) {
+ mPolicy->getReaderConfiguration(&mConfig);
+
configureExcludedDevices();
updateGlobalMetaState();
updateInputConfiguration();
@@ -514,11 +455,8 @@ void InputReader::handleConfigurationChanged(nsecs_t when) {
}
void InputReader::configureExcludedDevices() {
- Vector<String8> excludedDeviceNames;
- mPolicy->getExcludedDeviceNames(excludedDeviceNames);
-
- for (size_t i = 0; i < excludedDeviceNames.size(); i++) {
- mEventHub->addExcludedDevice(excludedDeviceNames[i]);
+ for (size_t i = 0; i < mConfig.excludedDeviceNames.size(); i++) {
+ mEventHub->addExcludedDevice(mConfig.excludedDeviceNames[i]);
}
}
@@ -752,6 +690,46 @@ void InputReader::dump(String8& dump) {
mDevices.valueAt(i)->dump(dump);
}
} // release device registy reader lock
+
+ dump.append(INDENT "Configuration:\n");
+ dump.append(INDENT2 "ExcludedDeviceNames: [");
+ for (size_t i = 0; i < mConfig.excludedDeviceNames.size(); i++) {
+ if (i != 0) {
+ dump.append(", ");
+ }
+ dump.append(mConfig.excludedDeviceNames.itemAt(i).string());
+ }
+ dump.append("]\n");
+ dump.appendFormat(INDENT2 "FilterTouchEvents: %s\n",
+ toString(mConfig.filterTouchEvents));
+ dump.appendFormat(INDENT2 "FilterJumpyTouchEvents: %s\n",
+ toString(mConfig.filterJumpyTouchEvents));
+ dump.appendFormat(INDENT2 "VirtualKeyQuietTime: %0.1fms\n",
+ mConfig.virtualKeyQuietTime * 0.000001f);
+
+ dump.appendFormat(INDENT2 "PointerGesture:\n");
+ dump.appendFormat(INDENT3 "QuietInterval: %0.1fms\n",
+ mConfig.pointerGestureQuietInterval * 0.000001f);
+ dump.appendFormat(INDENT3 "DragMinSwitchSpeed: %0.1fpx/s\n",
+ mConfig.pointerGestureDragMinSwitchSpeed);
+ dump.appendFormat(INDENT3 "TapInterval: %0.1fms\n",
+ mConfig.pointerGestureTapInterval * 0.000001f);
+ dump.appendFormat(INDENT3 "TapDragInterval: %0.1fms\n",
+ mConfig.pointerGestureTapDragInterval * 0.000001f);
+ dump.appendFormat(INDENT3 "TapSlop: %0.1fpx\n",
+ mConfig.pointerGestureTapSlop);
+ dump.appendFormat(INDENT3 "MultitouchSettleInterval: %0.1fms\n",
+ mConfig.pointerGestureMultitouchSettleInterval * 0.000001f);
+ dump.appendFormat(INDENT3 "MultitouchMinSpeed: %0.1fpx/s\n",
+ mConfig.pointerGestureMultitouchMinSpeed);
+ dump.appendFormat(INDENT3 "SwipeTransitionAngleCosine: %0.1f\n",
+ mConfig.pointerGestureSwipeTransitionAngleCosine);
+ dump.appendFormat(INDENT3 "SwipeMaxWidthRatio: %0.1f\n",
+ mConfig.pointerGestureSwipeMaxWidthRatio);
+ dump.appendFormat(INDENT3 "MovementSpeedRatio: %0.1f\n",
+ mConfig.pointerGestureMovementSpeedRatio);
+ dump.appendFormat(INDENT3 "ZoomSpeedRatio: %0.1f\n",
+ mConfig.pointerGestureZoomSpeedRatio);
}
@@ -1696,6 +1674,8 @@ void CursorInputMapper::fadePointer() {
TouchInputMapper::TouchInputMapper(InputDevice* device) :
InputMapper(device) {
+ mConfig = getConfig();
+
mLocked.surfaceOrientation = -1;
mLocked.surfaceWidth = -1;
mLocked.surfaceHeight = -1;
@@ -1868,10 +1848,9 @@ void TouchInputMapper::configure() {
}
void TouchInputMapper::configureParameters() {
- mParameters.useBadTouchFilter = getPolicy()->filterTouchEvents();
- mParameters.useAveragingTouchFilter = getPolicy()->filterTouchEvents();
- mParameters.useJumpyTouchFilter = getPolicy()->filterJumpyTouchEvents();
- mParameters.virtualKeyQuietTime = getPolicy()->getVirtualKeyQuietTime();
+ mParameters.useBadTouchFilter = mConfig->filterTouchEvents;
+ mParameters.useAveragingTouchFilter = mConfig->filterTouchEvents;
+ mParameters.useJumpyTouchFilter = mConfig->filterJumpyTouchEvents;
// TODO: select the default gesture mode based on whether the device supports
// distinct multitouch
@@ -2265,21 +2244,22 @@ bool TouchInputMapper::configureSurfaceLocked() {
// X and Y of the same number of raw units cover the same physical distance.
const float scaleFactor = 0.8f;
- mLocked.pointerGestureXMovementScale = GESTURE_MOVEMENT_SPEED_RATIO
+ mLocked.pointerGestureXMovementScale = mConfig->pointerGestureMovementSpeedRatio
* displayDiagonal / rawDiagonal;
mLocked.pointerGestureYMovementScale = mLocked.pointerGestureXMovementScale;
// Scale zooms to cover a smaller range of the display than movements do.
// This value determines the area around the pointer that is affected by freeform
// pointer gestures.
- mLocked.pointerGestureXZoomScale = GESTURE_ZOOM_SPEED_RATIO
+ mLocked.pointerGestureXZoomScale = mConfig->pointerGestureZoomSpeedRatio
* displayDiagonal / rawDiagonal;
mLocked.pointerGestureYZoomScale = mLocked.pointerGestureXZoomScale;
// Max width between pointers to detect a swipe gesture is more than some fraction
// of the diagonal axis of the touch pad. Touches that are wider than this are
// translated into freeform gestures.
- mLocked.pointerGestureMaxSwipeWidth = SWIPE_MAX_WIDTH_RATIO * rawDiagonal;
+ mLocked.pointerGestureMaxSwipeWidth =
+ mConfig->pointerGestureSwipeMaxWidthRatio * rawDiagonal;
// Reset the current pointer gesture.
mPointerGesture.reset();
@@ -2945,8 +2925,8 @@ void TouchInputMapper::suppressSwipeOntoVirtualKeys(nsecs_t when) {
// 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);
+ if (mConfig->virtualKeyQuietTime > 0 && mCurrentTouch.pointerCount != 0) {
+ mContext->disableVirtualKeysUntil(when + mConfig->virtualKeyQuietTime);
}
}
@@ -3260,12 +3240,6 @@ void TouchInputMapper::prepareTouches(int32_t* outEdgeFlags,
void TouchInputMapper::dispatchPointerGestures(nsecs_t when, uint32_t policyFlags,
bool isTimeout) {
- // Switch pointer presentation.
- mPointerController->setPresentation(
- mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS
- ? PointerControllerInterface::PRESENTATION_SPOT
- : PointerControllerInterface::PRESENTATION_POINTER);
-
// Update current gesture coordinates.
bool cancelPreviousGesture, finishPreviousGesture;
bool sendEvents = preparePointerGestures(when,
@@ -3274,6 +3248,12 @@ void TouchInputMapper::dispatchPointerGestures(nsecs_t when, uint32_t policyFlag
return;
}
+ // Switch pointer presentation.
+ mPointerController->setPresentation(
+ mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS
+ ? PointerControllerInterface::PRESENTATION_SPOT
+ : PointerControllerInterface::PRESENTATION_POINTER);
+
// Show or hide the pointer if needed.
switch (mPointerGesture.currentGestureMode) {
case PointerGesture::NEUTRAL:
@@ -3441,9 +3421,10 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when,
#endif
if (mPointerGesture.lastGestureMode == PointerGesture::TAP) {
- if (when <= mPointerGesture.tapUpTime + TAP_DRAG_INTERVAL) {
+ if (when <= mPointerGesture.tapUpTime + mConfig->pointerGestureTapDragInterval) {
// The tap/drag timeout has not yet expired.
- getContext()->requestTimeoutAtTime(mPointerGesture.tapUpTime + TAP_DRAG_INTERVAL);
+ getContext()->requestTimeoutAtTime(mPointerGesture.tapUpTime
+ + mConfig->pointerGestureTapDragInterval);
} else {
// The tap is finished.
#if DEBUG_GESTURES
@@ -3512,7 +3493,7 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when,
if (activeTouchId < 0) {
mPointerGesture.resetQuietTime();
} else {
- isQuietTime = when < mPointerGesture.quietTime + QUIET_INTERVAL;
+ isQuietTime = when < mPointerGesture.quietTime + mConfig->pointerGestureQuietInterval;
if (!isQuietTime) {
if ((mPointerGesture.lastGestureMode == PointerGesture::PRESS
|| mPointerGesture.lastGestureMode == PointerGesture::SWIPE
@@ -3583,7 +3564,7 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when,
if (activeTouchId >= 0) {
if (mCurrentTouch.pointerCount > 1) {
int32_t bestId = -1;
- float bestSpeed = DRAG_MIN_SWITCH_SPEED;
+ float bestSpeed = mConfig->pointerGestureDragMinSwitchSpeed;
for (uint32_t i = 0; i < mCurrentTouch.pointerCount; i++) {
uint32_t id = mCurrentTouch.pointers[i].id;
float vx, vy;
@@ -3661,21 +3642,23 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when,
*outFinishPreviousGesture = true;
// Watch for taps coming out of HOVER or TAP_DRAG mode.
+ // Checking for taps after TAP_DRAG allows us to detect double-taps.
bool tapped = false;
if ((mPointerGesture.lastGestureMode == PointerGesture::HOVER
|| mPointerGesture.lastGestureMode == PointerGesture::TAP_DRAG)
&& mLastTouch.pointerCount == 1) {
- if (when <= mPointerGesture.tapDownTime + TAP_INTERVAL) {
+ if (when <= mPointerGesture.tapDownTime + mConfig->pointerGestureTapInterval) {
float x, y;
mPointerController->getPosition(&x, &y);
- if (fabs(x - mPointerGesture.tapX) <= TAP_SLOP
- && fabs(y - mPointerGesture.tapY) <= TAP_SLOP) {
+ if (fabs(x - mPointerGesture.tapX) <= mConfig->pointerGestureTapSlop
+ && fabs(y - mPointerGesture.tapY) <= mConfig->pointerGestureTapSlop) {
#if DEBUG_GESTURES
LOGD("Gestures: TAP");
#endif
mPointerGesture.tapUpTime = when;
- getContext()->requestTimeoutAtTime(when + TAP_DRAG_INTERVAL);
+ getContext()->requestTimeoutAtTime(when
+ + mConfig->pointerGestureTapDragInterval);
mPointerGesture.activeGestureId = 0;
mPointerGesture.currentGestureMode = PointerGesture::TAP;
@@ -3740,11 +3723,11 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when,
mPointerGesture.currentGestureMode = PointerGesture::HOVER;
if (mPointerGesture.lastGestureMode == PointerGesture::TAP) {
- if (when <= mPointerGesture.tapUpTime + TAP_DRAG_INTERVAL) {
+ if (when <= mPointerGesture.tapUpTime + mConfig->pointerGestureTapDragInterval) {
float x, y;
mPointerController->getPosition(&x, &y);
- if (fabs(x - mPointerGesture.tapX) <= TAP_SLOP
- && fabs(y - mPointerGesture.tapY) <= TAP_SLOP) {
+ if (fabs(x - mPointerGesture.tapX) <= mConfig->pointerGestureTapSlop
+ && fabs(y - mPointerGesture.tapY) <= mConfig->pointerGestureTapSlop) {
mPointerGesture.currentGestureMode = PointerGesture::TAP_DRAG;
} else {
#if DEBUG_GESTURES
@@ -3838,7 +3821,8 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when,
LOG_ASSERT(activeTouchId >= 0);
bool needReference = false;
- bool settled = when >= mPointerGesture.firstTouchTime + MULTITOUCH_SETTLE_INTERVAL;
+ bool settled = when >= mPointerGesture.firstTouchTime
+ + mConfig->pointerGestureMultitouchSettleInterval;
if (mPointerGesture.lastGestureMode != PointerGesture::PRESS
&& mPointerGesture.lastGestureMode != PointerGesture::SWIPE
&& mPointerGesture.lastGestureMode != PointerGesture::FREEFORM) {
@@ -3932,14 +3916,15 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when,
float speed1 = hypotf(vx1, vy1);
float speed2 = hypotf(vx2, vy2);
- if (speed1 >= MULTITOUCH_MIN_SPEED && speed2 >= MULTITOUCH_MIN_SPEED) {
+ if (speed1 >= mConfig->pointerGestureMultitouchMinSpeed
+ && speed2 >= mConfig->pointerGestureMultitouchMinSpeed) {
// Calculate the dot product of the velocity vectors.
// When the vectors are oriented in approximately the same direction,
// the angle betweeen them is near zero and the cosine of the angle
// approches 1.0. Recall that dot(v1, v2) = cos(angle) * mag(v1) * mag(v2).
float dot = vx1 * vx2 + vy1 * vy2;
float cosine = dot / (speed1 * speed2); // denominator always > 0
- if (cosine >= SWIPE_TRANSITION_ANGLE_COSINE) {
+ if (cosine >= mConfig->pointerGestureSwipeTransitionAngleCosine) {
// Pointers are moving in the same direction. Switch to SWIPE.
#if DEBUG_GESTURES
LOGD("Gestures: PRESS transitioned to SWIPE, "
diff --git a/services/input/InputReader.h b/services/input/InputReader.h
index 0fbc93c..db4679b 100644
--- a/services/input/InputReader.h
+++ b/services/input/InputReader.h
@@ -40,6 +40,109 @@ class InputMapper;
/*
+ * Input reader configuration.
+ *
+ * Specifies various options that modify the behavior of the input reader.
+ */
+struct InputReaderConfiguration {
+ // Determines whether to turn on some hacks we have to improve the touch interaction with a
+ // certain device whose screen currently is not all that good.
+ bool filterTouchEvents;
+
+ // Determines whether to turn on some hacks to improve touch interaction with another device
+ // where touch coordinate data can get corrupted.
+ bool filterJumpyTouchEvents;
+
+ // 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.
+ nsecs_t virtualKeyQuietTime;
+
+ // The excluded device names for the platform.
+ // Devices with these names will be ignored.
+ Vector<String8> excludedDeviceNames;
+
+ // Quiet time between certain pointer gesture transitions.
+ // Time to allow for all fingers or buttons to settle into a stable state before
+ // starting a new gesture.
+ nsecs_t pointerGestureQuietInterval;
+
+ // The minimum speed that a pointer must travel for us to consider switching the active
+ // touch pointer to it during a drag. This threshold is set to avoid switching due
+ // to noise from a finger resting on the touch pad (perhaps just pressing it down).
+ float pointerGestureDragMinSwitchSpeed; // in pixels per second
+
+ // Tap gesture delay time.
+ // The time between down and up must be less than this to be considered a tap.
+ nsecs_t pointerGestureTapInterval;
+
+ // Tap drag gesture delay time.
+ // The time between the previous tap's up and the next down must be less than
+ // this to be considered a drag. Otherwise, the previous tap is finished and a
+ // new tap begins.
+ //
+ // Note that the previous tap will be held down for this entire duration so this
+ // interval must be shorter than the long press timeout.
+ nsecs_t pointerGestureTapDragInterval;
+
+ // The distance in pixels that the pointer is allowed to move from initial down
+ // to up and still be called a tap.
+ float pointerGestureTapSlop; // in pixels
+
+ // Time after the first touch points go down to settle on an initial centroid.
+ // This is intended to be enough time to handle cases where the user puts down two
+ // fingers at almost but not quite exactly the same time.
+ nsecs_t pointerGestureMultitouchSettleInterval;
+
+ // The transition from PRESS to SWIPE or FREEFORM gesture mode is made when
+ // both of the pointers are moving at least this fast.
+ float pointerGestureMultitouchMinSpeed; // in pixels per second
+
+ // The transition from PRESS to SWIPE gesture mode can only occur when the
+ // cosine of the angle between the two vectors is greater than or equal to than this value
+ // which indicates that the vectors are oriented in the same direction.
+ // When the vectors are oriented in the exactly same direction, the cosine is 1.0.
+ // (In exactly opposite directions, the cosine is -1.0.)
+ float pointerGestureSwipeTransitionAngleCosine;
+
+ // The transition from PRESS to SWIPE gesture mode can only occur when the
+ // fingers are no more than this far apart relative to the diagonal size of
+ // the touch pad. For example, a ratio of 0.5 means that the fingers must be
+ // no more than half the diagonal size of the touch pad apart.
+ float pointerGestureSwipeMaxWidthRatio;
+
+ // The gesture movement speed factor relative to the size of the display.
+ // Movement speed applies when the fingers are moving in the same direction.
+ // Without acceleration, a full swipe of the touch pad diagonal in movement mode
+ // will cover this portion of the display diagonal.
+ float pointerGestureMovementSpeedRatio;
+
+ // The gesture zoom speed factor relative to the size of the display.
+ // Zoom speed applies when the fingers are mostly moving relative to each other
+ // to execute a scale gesture or similar.
+ // Without acceleration, a full swipe of the touch pad diagonal in zoom mode
+ // will cover this portion of the display diagonal.
+ float pointerGestureZoomSpeedRatio;
+
+ InputReaderConfiguration() :
+ filterTouchEvents(false),
+ filterJumpyTouchEvents(false),
+ virtualKeyQuietTime(0),
+ pointerGestureQuietInterval(100 * 1000000LL), // 100 ms
+ pointerGestureDragMinSwitchSpeed(50), // 50 pixels per second
+ pointerGestureTapInterval(150 * 1000000LL), // 150 ms
+ pointerGestureTapDragInterval(150 * 1000000LL), // 150 ms
+ pointerGestureTapSlop(10.0f), // 10 pixels
+ pointerGestureMultitouchSettleInterval(100 * 1000000LL), // 100 ms
+ pointerGestureMultitouchMinSpeed(150.0f), // 150 pixels per second
+ pointerGestureSwipeTransitionAngleCosine(0.5f), // cosine of 45degrees
+ pointerGestureSwipeMaxWidthRatio(0.333f),
+ pointerGestureMovementSpeedRatio(0.8f),
+ pointerGestureZoomSpeedRatio(0.3f) { }
+};
+
+
+/*
* Input reader policy interface.
*
* The input reader policy is used by the input reader to interact with the Window Manager
@@ -68,24 +171,8 @@ public:
virtual bool getDisplayInfo(int32_t displayId,
int32_t* width, int32_t* height, int32_t* orientation) = 0;
- /* Determines whether to turn on some hacks we have to improve the touch interaction with a
- * certain device whose screen currently is not all that good.
- */
- virtual bool filterTouchEvents() = 0;
-
- /* Determines whether to turn on some hacks to improve touch interaction with another device
- * where touch coordinate data can get corrupted.
- */
- 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;
+ /* Gets the input reader configuration. */
+ virtual void getReaderConfiguration(InputReaderConfiguration* outConfig) = 0;
/* Gets a pointer controller associated with the specified cursor device (ie. a mouse). */
virtual sp<PointerControllerInterface> obtainPointerController(int32_t deviceId) = 0;
@@ -162,6 +249,7 @@ public:
virtual void requestTimeoutAtTime(nsecs_t when) = 0;
virtual InputReaderPolicyInterface* getPolicy() = 0;
+ virtual const InputReaderConfiguration* getConfig() = 0;
virtual InputDispatcherInterface* getDispatcher() = 0;
virtual EventHubInterface* getEventHub() = 0;
};
@@ -212,7 +300,10 @@ private:
sp<InputReaderPolicyInterface> mPolicy;
sp<InputDispatcherInterface> mDispatcher;
+ InputReaderConfiguration mConfig;
+
virtual InputReaderPolicyInterface* getPolicy() { return mPolicy.get(); }
+ virtual const InputReaderConfiguration* getConfig() { return &mConfig; }
virtual InputDispatcherInterface* getDispatcher() { return mDispatcher.get(); }
virtual EventHubInterface* getEventHub() { return mEventHub.get(); }
@@ -353,6 +444,7 @@ public:
inline const String8 getDeviceName() { return mDevice->getName(); }
inline InputReaderContext* getContext() { return mContext; }
inline InputReaderPolicyInterface* getPolicy() { return mContext->getPolicy(); }
+ inline const InputReaderConfiguration* getConfig() { return mContext->getConfig(); }
inline InputDispatcherInterface* getDispatcher() { return mContext->getDispatcher(); }
inline EventHubInterface* getEventHub() { return mContext->getEventHub(); }
@@ -665,6 +757,9 @@ protected:
uint32_t mTouchSource; // sources when reporting touch data
uint32_t mPointerSource; // sources when reporting pointer gestures
+ // The reader's configuration.
+ const InputReaderConfiguration* mConfig;
+
// Immutable configuration parameters.
struct Parameters {
enum DeviceType {
@@ -680,7 +775,6 @@ protected:
bool useBadTouchFilter;
bool useJumpyTouchFilter;
bool useAveragingTouchFilter;
- nsecs_t virtualKeyQuietTime;
enum GestureMode {
GESTURE_MODE_POINTER,
@@ -939,6 +1033,8 @@ private:
// Exactly one finger dragging following a tap.
// Pointer follows the active finger.
// Emits DOWN, MOVE and UP events at the pointer location.
+ //
+ // Detect double-taps when the finger goes up while in TAP_DRAG mode.
TAP_DRAG,
// Button is pressed.
@@ -949,6 +1045,8 @@ private:
// Exactly one finger, button is not pressed.
// Pointer follows the active finger.
// Emits HOVER_MOVE events at the pointer location.
+ //
+ // Detect taps when the finger goes up while in HOVER mode.
HOVER,
// Exactly two fingers but neither have moved enough to clearly indicate
diff --git a/services/input/tests/InputDispatcher_test.cpp b/services/input/tests/InputDispatcher_test.cpp
index 2f846c4..0a29bc6 100644
--- a/services/input/tests/InputDispatcher_test.cpp
+++ b/services/input/tests/InputDispatcher_test.cpp
@@ -35,6 +35,8 @@ static const int32_t INJECTOR_UID = 1001;
// --- FakeInputDispatcherPolicy ---
class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface {
+ InputDispatcherConfiguration mConfig;
+
protected:
virtual ~FakeInputDispatcherPolicy() {
}
@@ -55,16 +57,12 @@ private:
virtual void notifyInputChannelBroken(const sp<InputWindowHandle>& inputWindowHandle) {
}
- virtual nsecs_t getKeyRepeatTimeout() {
- return 500 * 1000000LL;
- }
-
- virtual nsecs_t getKeyRepeatDelay() {
- return 50 * 1000000LL;
+ virtual void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) {
+ *outConfig = mConfig;
}
- virtual int32_t getMaxEventsPerSecond() {
- return 60;
+ virtual bool isKeyRepeatEnabled() {
+ return true;
}
virtual void interceptKeyBeforeQueueing(const KeyEvent* keyEvent, uint32_t& policyFlags) {
diff --git a/services/input/tests/InputReader_test.cpp b/services/input/tests/InputReader_test.cpp
index 8b3e731..b5f603a 100644
--- a/services/input/tests/InputReader_test.cpp
+++ b/services/input/tests/InputReader_test.cpp
@@ -120,17 +120,14 @@ class FakeInputReaderPolicy : public InputReaderPolicyInterface {
};
KeyedVector<int32_t, DisplayInfo> mDisplayInfos;
- bool mFilterTouchEvents;
- bool mFilterJumpyTouchEvents;
- Vector<String8> mExcludedDeviceNames;
+ InputReaderConfiguration mConfig;
KeyedVector<int32_t, sp<FakePointerController> > mPointerControllers;
protected:
virtual ~FakeInputReaderPolicy() { }
public:
- FakeInputReaderPolicy() :
- mFilterTouchEvents(false), mFilterJumpyTouchEvents(false) {
+ FakeInputReaderPolicy() {
}
void removeDisplayInfo(int32_t displayId) {
@@ -148,11 +145,11 @@ public:
}
void setFilterTouchEvents(bool enabled) {
- mFilterTouchEvents = enabled;
+ mConfig.filterTouchEvents = enabled;
}
void setFilterJumpyTouchEvents(bool enabled) {
- mFilterJumpyTouchEvents = enabled;
+ mConfig.filterJumpyTouchEvents = enabled;
}
virtual nsecs_t getVirtualKeyQuietTime() {
@@ -160,7 +157,7 @@ public:
}
void addExcludedDeviceName(const String8& deviceName) {
- mExcludedDeviceNames.push(deviceName);
+ mConfig.excludedDeviceNames.push(deviceName);
}
void setPointerController(int32_t deviceId, const sp<FakePointerController>& controller) {
@@ -187,16 +184,8 @@ private:
return false;
}
- virtual bool filterTouchEvents() {
- return mFilterTouchEvents;
- }
-
- virtual bool filterJumpyTouchEvents() {
- return mFilterJumpyTouchEvents;
- }
-
- virtual void getExcludedDeviceNames(Vector<String8>& outExcludedDeviceNames) {
- outExcludedDeviceNames.appendVector(mExcludedDeviceNames);
+ virtual void getReaderConfiguration(InputReaderConfiguration* outConfig) {
+ *outConfig = mConfig;
}
virtual sp<PointerControllerInterface> obtainPointerController(int32_t deviceId) {
@@ -739,6 +728,8 @@ class FakeInputReaderContext : public InputReaderContext {
int32_t mGlobalMetaState;
bool mUpdateGlobalMetaStateWasCalled;
+ InputReaderConfiguration mConfig;
+
public:
FakeInputReaderContext(const sp<EventHubInterface>& eventHub,
const sp<InputReaderPolicyInterface>& policy,
@@ -776,6 +767,11 @@ private:
return mPolicy.get();
}
+ virtual const InputReaderConfiguration* getConfig() {
+ mPolicy->getReaderConfiguration(&mConfig);
+ return &mConfig;
+ }
+
virtual InputDispatcherInterface* getDispatcher() {
return mDispatcher.get();
}
diff --git a/services/java/com/android/server/wm/InputManager.java b/services/java/com/android/server/wm/InputManager.java
index becd44a..ab781f4 100644
--- a/services/java/com/android/server/wm/InputManager.java
+++ b/services/java/com/android/server/wm/InputManager.java
@@ -496,6 +496,26 @@ public class InputManager {
}
@SuppressWarnings("unused")
+ public int getTapTimeout() {
+ return ViewConfiguration.getTapTimeout();
+ }
+
+ @SuppressWarnings("unused")
+ public int getDoubleTapTimeout() {
+ return ViewConfiguration.getDoubleTapTimeout();
+ }
+
+ @SuppressWarnings("unused")
+ public int getLongPressTimeout() {
+ return ViewConfiguration.getLongPressTimeout();
+ }
+
+ @SuppressWarnings("unused")
+ public int getTouchSlop() {
+ return ViewConfiguration.get(mContext).getScaledTouchSlop();
+ }
+
+ @SuppressWarnings("unused")
public int getMaxEventsPerSecond() {
int result = 0;
try {
diff --git a/services/jni/com_android_server_InputManager.cpp b/services/jni/com_android_server_InputManager.cpp
index dde4776..fef41c9 100644
--- a/services/jni/com_android_server_InputManager.cpp
+++ b/services/jni/com_android_server_InputManager.cpp
@@ -72,6 +72,10 @@ static struct {
jmethodID getKeyRepeatTimeout;
jmethodID getKeyRepeatDelay;
jmethodID getMaxEventsPerSecond;
+ jmethodID getTapTimeout;
+ jmethodID getDoubleTapTimeout;
+ jmethodID getLongPressTimeout;
+ jmethodID getTouchSlop;
jmethodID getPointerLayer;
jmethodID getPointerIcon;
} gCallbacksClassInfo;
@@ -107,6 +111,16 @@ static struct {
// --- Global functions ---
+template<typename T>
+inline static T min(const T& a, const T& b) {
+ return a < b ? a : b;
+}
+
+template<typename T>
+inline static T max(const T& a, const T& b) {
+ return a > b ? a : b;
+}
+
static jobject getInputApplicationHandleObjLocalRef(JNIEnv* env,
const sp<InputApplicationHandle>& inputApplicationHandle) {
if (inputApplicationHandle == NULL) {
@@ -170,10 +184,7 @@ public:
virtual bool getDisplayInfo(int32_t displayId,
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 void getReaderConfiguration(InputReaderConfiguration* outConfig);
virtual sp<PointerControllerInterface> obtainPointerController(int32_t deviceId);
/* --- InputDispatcherPolicyInterface implementation --- */
@@ -184,9 +195,8 @@ public:
virtual nsecs_t notifyANR(const sp<InputApplicationHandle>& inputApplicationHandle,
const sp<InputWindowHandle>& inputWindowHandle);
virtual void notifyInputChannelBroken(const sp<InputWindowHandle>& inputWindowHandle);
- virtual nsecs_t getKeyRepeatTimeout();
- virtual nsecs_t getKeyRepeatDelay();
- virtual int32_t getMaxEventsPerSecond();
+ virtual void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig);
+ virtual bool isKeyRepeatEnabled();
virtual void interceptKeyBeforeQueueing(const KeyEvent* keyEvent, uint32_t& policyFlags);
virtual void interceptMotionBeforeQueueing(nsecs_t when, uint32_t& policyFlags);
virtual bool interceptKeyBeforeDispatching(const sp<InputWindowHandle>& inputWindowHandle,
@@ -208,18 +218,6 @@ private:
jobject mCallbacksObj;
sp<Looper> mLooper;
- // Cached filtering policies.
- int32_t mFilterTouchEvents;
- int32_t mFilterJumpyTouchEvents;
- nsecs_t mVirtualKeyQuietTime;
-
- // Cached key repeat policy.
- nsecs_t mKeyRepeatTimeout;
- nsecs_t mKeyRepeatDelay;
-
- // Cached throttling policy.
- int32_t mMaxEventsPerSecond;
-
Mutex mLock;
struct Locked {
// Display size information.
@@ -255,10 +253,7 @@ private:
NativeInputManager::NativeInputManager(jobject contextObj,
jobject callbacksObj, const sp<Looper>& looper) :
- mLooper(looper),
- mFilterTouchEvents(-1), mFilterJumpyTouchEvents(-1), mVirtualKeyQuietTime(-1),
- mKeyRepeatTimeout(-1), mKeyRepeatDelay(-1),
- mMaxEventsPerSecond(-1) {
+ mLooper(looper) {
JNIEnv* env = jniEnv();
mContextObj = env->NewGlobalRef(contextObj);
@@ -371,73 +366,68 @@ bool NativeInputManager::getDisplayInfo(int32_t displayId,
return result;
}
-bool NativeInputManager::filterTouchEvents() {
- if (mFilterTouchEvents < 0) {
- JNIEnv* env = jniEnv();
-
- jboolean result = env->CallBooleanMethod(mCallbacksObj,
- gCallbacksClassInfo.filterTouchEvents);
- if (checkAndClearExceptionFromCallback(env, "filterTouchEvents")) {
- result = false;
- }
+void NativeInputManager::getReaderConfiguration(InputReaderConfiguration* outConfig) {
+ JNIEnv* env = jniEnv();
- mFilterTouchEvents = result ? 1 : 0;
+ jboolean filterTouchEvents = env->CallBooleanMethod(mCallbacksObj,
+ gCallbacksClassInfo.filterTouchEvents);
+ if (!checkAndClearExceptionFromCallback(env, "filterTouchEvents")) {
+ outConfig->filterTouchEvents = filterTouchEvents;
}
- return mFilterTouchEvents;
-}
-
-bool NativeInputManager::filterJumpyTouchEvents() {
- if (mFilterJumpyTouchEvents < 0) {
- JNIEnv* env = jniEnv();
-
- jboolean result = env->CallBooleanMethod(mCallbacksObj,
- gCallbacksClassInfo.filterJumpyTouchEvents);
- if (checkAndClearExceptionFromCallback(env, "filterJumpyTouchEvents")) {
- result = false;
- }
- mFilterJumpyTouchEvents = result ? 1 : 0;
+ jboolean filterJumpyTouchEvents = env->CallBooleanMethod(mCallbacksObj,
+ gCallbacksClassInfo.filterJumpyTouchEvents);
+ if (!checkAndClearExceptionFromCallback(env, "filterJumpyTouchEvents")) {
+ outConfig->filterJumpyTouchEvents = 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);
+ jint virtualKeyQuietTime = env->CallIntMethod(mCallbacksObj,
+ gCallbacksClassInfo.getVirtualKeyQuietTimeMillis);
+ if (!checkAndClearExceptionFromCallback(env, "getVirtualKeyQuietTimeMillis")) {
+ outConfig->virtualKeyQuietTime = milliseconds_to_nanoseconds(virtualKeyQuietTime);
}
- return mVirtualKeyQuietTime;
-}
-
-void NativeInputManager::getExcludedDeviceNames(Vector<String8>& outExcludedDeviceNames) {
- outExcludedDeviceNames.clear();
-
- JNIEnv* env = jniEnv();
- jobjectArray result = jobjectArray(env->CallObjectMethod(mCallbacksObj,
+ outConfig->excludedDeviceNames.clear();
+ jobjectArray excludedDeviceNames = jobjectArray(env->CallObjectMethod(mCallbacksObj,
gCallbacksClassInfo.getExcludedDeviceNames));
- if (! checkAndClearExceptionFromCallback(env, "getExcludedDeviceNames") && result) {
- jsize length = env->GetArrayLength(result);
+ if (!checkAndClearExceptionFromCallback(env, "getExcludedDeviceNames") && excludedDeviceNames) {
+ jsize length = env->GetArrayLength(excludedDeviceNames);
for (jsize i = 0; i < length; i++) {
- jstring item = jstring(env->GetObjectArrayElement(result, i));
-
+ jstring item = jstring(env->GetObjectArrayElement(excludedDeviceNames, i));
const char* deviceNameChars = env->GetStringUTFChars(item, NULL);
- outExcludedDeviceNames.add(String8(deviceNameChars));
+ outConfig->excludedDeviceNames.add(String8(deviceNameChars));
env->ReleaseStringUTFChars(item, deviceNameChars);
-
env->DeleteLocalRef(item);
}
- env->DeleteLocalRef(result);
+ env->DeleteLocalRef(excludedDeviceNames);
+ }
+
+ jint tapTimeout = env->CallIntMethod(mCallbacksObj,
+ gCallbacksClassInfo.getTapTimeout);
+ if (!checkAndClearExceptionFromCallback(env, "getTapTimeout")) {
+ jint doubleTapTimeout = env->CallIntMethod(mCallbacksObj,
+ gCallbacksClassInfo.getDoubleTapTimeout);
+ if (!checkAndClearExceptionFromCallback(env, "getDoubleTapTimeout")) {
+ jint longPressTimeout = env->CallIntMethod(mCallbacksObj,
+ gCallbacksClassInfo.getLongPressTimeout);
+ if (!checkAndClearExceptionFromCallback(env, "getLongPressTimeout")) {
+ outConfig->pointerGestureTapInterval = milliseconds_to_nanoseconds(tapTimeout);
+
+ // We must ensure that the tap-drag interval is significantly shorter than
+ // the long-press timeout because the tap is held down for the entire duration
+ // of the double-tap timeout.
+ jint tapDragInterval = max(min(longPressTimeout - 100,
+ doubleTapTimeout), tapTimeout);
+ outConfig->pointerGestureTapDragInterval =
+ milliseconds_to_nanoseconds(tapDragInterval);
+ }
+ }
+ }
+
+ jint touchSlop = env->CallIntMethod(mCallbacksObj,
+ gCallbacksClassInfo.getTouchSlop);
+ if (!checkAndClearExceptionFromCallback(env, "getTouchSlop")) {
+ outConfig->pointerGestureTapSlop = touchSlop;
}
}
@@ -559,54 +549,31 @@ void NativeInputManager::notifyInputChannelBroken(const sp<InputWindowHandle>& i
}
}
-nsecs_t NativeInputManager::getKeyRepeatTimeout() {
- if (! isScreenOn()) {
- // Disable key repeat when the screen is off.
- return -1;
- } else {
- if (mKeyRepeatTimeout < 0) {
- JNIEnv* env = jniEnv();
-
- jint result = env->CallIntMethod(mCallbacksObj,
- gCallbacksClassInfo.getKeyRepeatTimeout);
- if (checkAndClearExceptionFromCallback(env, "getKeyRepeatTimeout")) {
- result = 500;
- }
+void NativeInputManager::getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) {
+ JNIEnv* env = jniEnv();
- mKeyRepeatTimeout = milliseconds_to_nanoseconds(result);
- }
- return mKeyRepeatTimeout;
+ jint keyRepeatTimeout = env->CallIntMethod(mCallbacksObj,
+ gCallbacksClassInfo.getKeyRepeatTimeout);
+ if (!checkAndClearExceptionFromCallback(env, "getKeyRepeatTimeout")) {
+ outConfig->keyRepeatTimeout = milliseconds_to_nanoseconds(keyRepeatTimeout);
}
-}
-nsecs_t NativeInputManager::getKeyRepeatDelay() {
- if (mKeyRepeatDelay < 0) {
- JNIEnv* env = jniEnv();
-
- jint result = env->CallIntMethod(mCallbacksObj,
- gCallbacksClassInfo.getKeyRepeatDelay);
- if (checkAndClearExceptionFromCallback(env, "getKeyRepeatDelay")) {
- result = 50;
- }
+ jint keyRepeatDelay = env->CallIntMethod(mCallbacksObj,
+ gCallbacksClassInfo.getKeyRepeatDelay);
+ if (!checkAndClearExceptionFromCallback(env, "getKeyRepeatDelay")) {
+ outConfig->keyRepeatDelay = milliseconds_to_nanoseconds(keyRepeatDelay);
+ }
- mKeyRepeatDelay = milliseconds_to_nanoseconds(result);
+ jint maxEventsPerSecond = env->CallIntMethod(mCallbacksObj,
+ gCallbacksClassInfo.getMaxEventsPerSecond);
+ if (!checkAndClearExceptionFromCallback(env, "getMaxEventsPerSecond")) {
+ outConfig->maxEventsPerSecond = maxEventsPerSecond;
}
- return mKeyRepeatDelay;
}
-int32_t NativeInputManager::getMaxEventsPerSecond() {
- if (mMaxEventsPerSecond < 0) {
- JNIEnv* env = jniEnv();
-
- jint result = env->CallIntMethod(mCallbacksObj,
- gCallbacksClassInfo.getMaxEventsPerSecond);
- if (checkAndClearExceptionFromCallback(env, "getMaxEventsPerSecond")) {
- result = 60;
- }
-
- mMaxEventsPerSecond = result;
- }
- return mMaxEventsPerSecond;
+bool NativeInputManager::isKeyRepeatEnabled() {
+ // Only enable automatic key repeating when the screen is on.
+ return isScreenOn();
}
void NativeInputManager::setInputWindows(JNIEnv* env, jobjectArray windowObjArray) {
@@ -1342,6 +1309,18 @@ int register_android_server_InputManager(JNIEnv* env) {
GET_METHOD_ID(gCallbacksClassInfo.getKeyRepeatDelay, gCallbacksClassInfo.clazz,
"getKeyRepeatDelay", "()I");
+ GET_METHOD_ID(gCallbacksClassInfo.getTapTimeout, gCallbacksClassInfo.clazz,
+ "getTapTimeout", "()I");
+
+ GET_METHOD_ID(gCallbacksClassInfo.getDoubleTapTimeout, gCallbacksClassInfo.clazz,
+ "getDoubleTapTimeout", "()I");
+
+ GET_METHOD_ID(gCallbacksClassInfo.getLongPressTimeout, gCallbacksClassInfo.clazz,
+ "getLongPressTimeout", "()I");
+
+ GET_METHOD_ID(gCallbacksClassInfo.getTouchSlop, gCallbacksClassInfo.clazz,
+ "getTouchSlop", "()I");
+
GET_METHOD_ID(gCallbacksClassInfo.getMaxEventsPerSecond, gCallbacksClassInfo.clazz,
"getMaxEventsPerSecond", "()I");