am 425f2a6d
: am c272d427
: Merge "Use ViewConfiguration to seed input system configuration." into honeycomb-mr2
* commit '425f2a6d71b3af058630367d75b0b924bf1aee49': Use ViewConfiguration to seed input system configuration.
This commit is contained in:
@ -222,13 +222,14 @@ InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& polic
|
|||||||
|
|
||||||
mKeyRepeatState.lastKeyEntry = NULL;
|
mKeyRepeatState.lastKeyEntry = NULL;
|
||||||
|
|
||||||
int32_t maxEventsPerSecond = policy->getMaxEventsPerSecond();
|
policy->getDispatcherConfiguration(&mConfig);
|
||||||
mThrottleState.minTimeBetweenEvents = 1000000000LL / maxEventsPerSecond;
|
|
||||||
|
mThrottleState.minTimeBetweenEvents = 1000000000LL / mConfig.maxEventsPerSecond;
|
||||||
mThrottleState.lastDeviceId = -1;
|
mThrottleState.lastDeviceId = -1;
|
||||||
|
|
||||||
#if DEBUG_THROTTLING
|
#if DEBUG_THROTTLING
|
||||||
mThrottleState.originalSampleCount = 0;
|
mThrottleState.originalSampleCount = 0;
|
||||||
LOGD("Throttling - Max events per second = %d", maxEventsPerSecond);
|
LOGD("Throttling - Max events per second = %d", mConfig.maxEventsPerSecond);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -247,13 +248,10 @@ InputDispatcher::~InputDispatcher() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void InputDispatcher::dispatchOnce() {
|
void InputDispatcher::dispatchOnce() {
|
||||||
nsecs_t keyRepeatTimeout = mPolicy->getKeyRepeatTimeout();
|
|
||||||
nsecs_t keyRepeatDelay = mPolicy->getKeyRepeatDelay();
|
|
||||||
|
|
||||||
nsecs_t nextWakeupTime = LONG_LONG_MAX;
|
nsecs_t nextWakeupTime = LONG_LONG_MAX;
|
||||||
{ // acquire lock
|
{ // acquire lock
|
||||||
AutoMutex _l(mLock);
|
AutoMutex _l(mLock);
|
||||||
dispatchOnceInnerLocked(keyRepeatTimeout, keyRepeatDelay, & nextWakeupTime);
|
dispatchOnceInnerLocked(&nextWakeupTime);
|
||||||
|
|
||||||
if (runCommandsLockedInterruptible()) {
|
if (runCommandsLockedInterruptible()) {
|
||||||
nextWakeupTime = LONG_LONG_MIN; // force next poll to wake up immediately
|
nextWakeupTime = LONG_LONG_MIN; // force next poll to wake up immediately
|
||||||
@ -266,14 +264,13 @@ void InputDispatcher::dispatchOnce() {
|
|||||||
mLooper->pollOnce(timeoutMillis);
|
mLooper->pollOnce(timeoutMillis);
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputDispatcher::dispatchOnceInnerLocked(nsecs_t keyRepeatTimeout,
|
void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) {
|
||||||
nsecs_t keyRepeatDelay, nsecs_t* nextWakeupTime) {
|
|
||||||
nsecs_t currentTime = now();
|
nsecs_t currentTime = now();
|
||||||
|
|
||||||
// Reset the key repeat timer whenever we disallow key events, even if the next event
|
// 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
|
// is not a key. This is to ensure that we abort a key repeat if the device is just coming
|
||||||
// out of sleep.
|
// out of sleep.
|
||||||
if (keyRepeatTimeout < 0) {
|
if (!mPolicy->isKeyRepeatEnabled()) {
|
||||||
resetKeyRepeatLocked();
|
resetKeyRepeatLocked();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -307,7 +304,7 @@ void InputDispatcher::dispatchOnceInnerLocked(nsecs_t keyRepeatTimeout,
|
|||||||
// Synthesize a key repeat if appropriate.
|
// Synthesize a key repeat if appropriate.
|
||||||
if (mKeyRepeatState.lastKeyEntry) {
|
if (mKeyRepeatState.lastKeyEntry) {
|
||||||
if (currentTime >= mKeyRepeatState.nextRepeatTime) {
|
if (currentTime >= mKeyRepeatState.nextRepeatTime) {
|
||||||
mPendingEvent = synthesizeKeyRepeatLocked(currentTime, keyRepeatDelay);
|
mPendingEvent = synthesizeKeyRepeatLocked(currentTime);
|
||||||
} else {
|
} else {
|
||||||
if (mKeyRepeatState.nextRepeatTime < *nextWakeupTime) {
|
if (mKeyRepeatState.nextRepeatTime < *nextWakeupTime) {
|
||||||
*nextWakeupTime = mKeyRepeatState.nextRepeatTime;
|
*nextWakeupTime = mKeyRepeatState.nextRepeatTime;
|
||||||
@ -426,8 +423,7 @@ void InputDispatcher::dispatchOnceInnerLocked(nsecs_t keyRepeatTimeout,
|
|||||||
if (dropReason == DROP_REASON_NOT_DROPPED && mNextUnblockedEvent) {
|
if (dropReason == DROP_REASON_NOT_DROPPED && mNextUnblockedEvent) {
|
||||||
dropReason = DROP_REASON_BLOCKED;
|
dropReason = DROP_REASON_BLOCKED;
|
||||||
}
|
}
|
||||||
done = dispatchKeyLocked(currentTime, typedEntry, keyRepeatTimeout,
|
done = dispatchKeyLocked(currentTime, typedEntry, &dropReason, nextWakeupTime);
|
||||||
&dropReason, nextWakeupTime);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -686,8 +682,7 @@ void InputDispatcher::resetKeyRepeatLocked() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
InputDispatcher::KeyEntry* InputDispatcher::synthesizeKeyRepeatLocked(
|
InputDispatcher::KeyEntry* InputDispatcher::synthesizeKeyRepeatLocked(nsecs_t currentTime) {
|
||||||
nsecs_t currentTime, nsecs_t keyRepeatDelay) {
|
|
||||||
KeyEntry* entry = mKeyRepeatState.lastKeyEntry;
|
KeyEntry* entry = mKeyRepeatState.lastKeyEntry;
|
||||||
|
|
||||||
// Reuse the repeated key entry if it is otherwise unreferenced.
|
// 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.
|
// mKeyRepeatState.lastKeyEntry in addition to the one we return.
|
||||||
entry->refCount += 1;
|
entry->refCount += 1;
|
||||||
|
|
||||||
mKeyRepeatState.nextRepeatTime = currentTime + keyRepeatDelay;
|
mKeyRepeatState.nextRepeatTime = currentTime + mConfig.keyRepeatDelay;
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -735,8 +730,7 @@ bool InputDispatcher::dispatchConfigurationChangedLocked(
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool InputDispatcher::dispatchKeyLocked(
|
bool InputDispatcher::dispatchKeyLocked(nsecs_t currentTime, KeyEntry* entry,
|
||||||
nsecs_t currentTime, KeyEntry* entry, nsecs_t keyRepeatTimeout,
|
|
||||||
DropReason* dropReason, nsecs_t* nextWakeupTime) {
|
DropReason* dropReason, nsecs_t* nextWakeupTime) {
|
||||||
// Preprocessing.
|
// Preprocessing.
|
||||||
if (! entry->dispatchInProgress) {
|
if (! entry->dispatchInProgress) {
|
||||||
@ -756,7 +750,7 @@ bool InputDispatcher::dispatchKeyLocked(
|
|||||||
} else {
|
} else {
|
||||||
// Not a repeat. Save key down state in case we do see a repeat later.
|
// Not a repeat. Save key down state in case we do see a repeat later.
|
||||||
resetKeyRepeatLocked();
|
resetKeyRepeatLocked();
|
||||||
mKeyRepeatState.nextRepeatTime = entry->eventTime + keyRepeatTimeout;
|
mKeyRepeatState.nextRepeatTime = entry->eventTime + mConfig.keyRepeatTimeout;
|
||||||
}
|
}
|
||||||
mKeyRepeatState.lastKeyEntry = entry;
|
mKeyRepeatState.lastKeyEntry = entry;
|
||||||
entry->refCount += 1;
|
entry->refCount += 1;
|
||||||
@ -3510,6 +3504,11 @@ void InputDispatcher::updateDispatchStatisticsLocked(nsecs_t currentTime, const
|
|||||||
void InputDispatcher::dump(String8& dump) {
|
void InputDispatcher::dump(String8& dump) {
|
||||||
dump.append("Input Dispatcher State:\n");
|
dump.append("Input Dispatcher State:\n");
|
||||||
dumpDispatchStateLocked(dump);
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -122,6 +122,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.
|
* Input dispatcher policy interface.
|
||||||
*
|
*
|
||||||
@ -148,17 +172,11 @@ public:
|
|||||||
/* Notifies the system that an input channel is unrecoverably broken. */
|
/* Notifies the system that an input channel is unrecoverably broken. */
|
||||||
virtual void notifyInputChannelBroken(const sp<InputWindowHandle>& inputWindowHandle) = 0;
|
virtual void notifyInputChannelBroken(const sp<InputWindowHandle>& inputWindowHandle) = 0;
|
||||||
|
|
||||||
/* Gets the key repeat initial timeout or -1 if automatic key repeating is disabled. */
|
/* Gets the input dispatcher configuration. */
|
||||||
virtual nsecs_t getKeyRepeatTimeout() = 0;
|
virtual void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) = 0;
|
||||||
|
|
||||||
/* Gets the key repeat inter-key delay. */
|
/* Returns true if automatic key repeating is enabled. */
|
||||||
virtual nsecs_t getKeyRepeatDelay() = 0;
|
virtual bool isKeyRepeatEnabled() = 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;
|
|
||||||
|
|
||||||
/* Intercepts a key event immediately before queueing it.
|
/* Intercepts a key event immediately before queueing it.
|
||||||
* The policy can use this method as an opportunity to perform power management functions
|
* The policy can use this method as an opportunity to perform power management functions
|
||||||
@ -757,6 +775,7 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
sp<InputDispatcherPolicyInterface> mPolicy;
|
sp<InputDispatcherPolicyInterface> mPolicy;
|
||||||
|
InputDispatcherConfiguration mConfig;
|
||||||
|
|
||||||
Mutex mLock;
|
Mutex mLock;
|
||||||
|
|
||||||
@ -769,8 +788,7 @@ private:
|
|||||||
|
|
||||||
Vector<EventEntry*> mTempCancelationEvents;
|
Vector<EventEntry*> mTempCancelationEvents;
|
||||||
|
|
||||||
void dispatchOnceInnerLocked(nsecs_t keyRepeatTimeout, nsecs_t keyRepeatDelay,
|
void dispatchOnceInnerLocked(nsecs_t* nextWakeupTime);
|
||||||
nsecs_t* nextWakeupTime);
|
|
||||||
|
|
||||||
// Batches a new sample onto a motion entry.
|
// Batches a new sample onto a motion entry.
|
||||||
// Assumes that the we have already checked that we can append samples.
|
// Assumes that the we have already checked that we can append samples.
|
||||||
@ -842,7 +860,7 @@ private:
|
|||||||
} mKeyRepeatState;
|
} mKeyRepeatState;
|
||||||
|
|
||||||
void resetKeyRepeatLocked();
|
void resetKeyRepeatLocked();
|
||||||
KeyEntry* synthesizeKeyRepeatLocked(nsecs_t currentTime, nsecs_t keyRepeatTimeout);
|
KeyEntry* synthesizeKeyRepeatLocked(nsecs_t currentTime);
|
||||||
|
|
||||||
// Deferred command processing.
|
// Deferred command processing.
|
||||||
bool runCommandsLockedInterruptible();
|
bool runCommandsLockedInterruptible();
|
||||||
@ -899,7 +917,7 @@ private:
|
|||||||
bool dispatchConfigurationChangedLocked(
|
bool dispatchConfigurationChangedLocked(
|
||||||
nsecs_t currentTime, ConfigurationChangedEntry* entry);
|
nsecs_t currentTime, ConfigurationChangedEntry* entry);
|
||||||
bool dispatchKeyLocked(
|
bool dispatchKeyLocked(
|
||||||
nsecs_t currentTime, KeyEntry* entry, nsecs_t keyRepeatTimeout,
|
nsecs_t currentTime, KeyEntry* entry,
|
||||||
DropReason* dropReason, nsecs_t* nextWakeupTime);
|
DropReason* dropReason, nsecs_t* nextWakeupTime);
|
||||||
bool dispatchMotionLocked(
|
bool dispatchMotionLocked(
|
||||||
nsecs_t currentTime, MotionEntry* entry,
|
nsecs_t currentTime, MotionEntry* entry,
|
||||||
|
@ -56,67 +56,6 @@
|
|||||||
|
|
||||||
namespace android {
|
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 ---
|
// --- Static Functions ---
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
@ -281,6 +220,8 @@ InputReader::InputReader(const sp<EventHubInterface>& eventHub,
|
|||||||
const sp<InputDispatcherInterface>& dispatcher) :
|
const sp<InputDispatcherInterface>& dispatcher) :
|
||||||
mEventHub(eventHub), mPolicy(policy), mDispatcher(dispatcher),
|
mEventHub(eventHub), mPolicy(policy), mDispatcher(dispatcher),
|
||||||
mGlobalMetaState(0), mDisableVirtualKeysTimeout(LLONG_MIN), mNextTimeout(LLONG_MAX) {
|
mGlobalMetaState(0), mDisableVirtualKeysTimeout(LLONG_MIN), mNextTimeout(LLONG_MAX) {
|
||||||
|
mPolicy->getReaderConfiguration(&mConfig);
|
||||||
|
|
||||||
configureExcludedDevices();
|
configureExcludedDevices();
|
||||||
updateGlobalMetaState();
|
updateGlobalMetaState();
|
||||||
updateInputConfiguration();
|
updateInputConfiguration();
|
||||||
@ -514,11 +455,8 @@ void InputReader::handleConfigurationChanged(nsecs_t when) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void InputReader::configureExcludedDevices() {
|
void InputReader::configureExcludedDevices() {
|
||||||
Vector<String8> excludedDeviceNames;
|
for (size_t i = 0; i < mConfig.excludedDeviceNames.size(); i++) {
|
||||||
mPolicy->getExcludedDeviceNames(excludedDeviceNames);
|
mEventHub->addExcludedDevice(mConfig.excludedDeviceNames[i]);
|
||||||
|
|
||||||
for (size_t i = 0; i < excludedDeviceNames.size(); i++) {
|
|
||||||
mEventHub->addExcludedDevice(excludedDeviceNames[i]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -752,6 +690,46 @@ void InputReader::dump(String8& dump) {
|
|||||||
mDevices.valueAt(i)->dump(dump);
|
mDevices.valueAt(i)->dump(dump);
|
||||||
}
|
}
|
||||||
} // release device registy reader lock
|
} // 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) :
|
TouchInputMapper::TouchInputMapper(InputDevice* device) :
|
||||||
InputMapper(device) {
|
InputMapper(device) {
|
||||||
|
mConfig = getConfig();
|
||||||
|
|
||||||
mLocked.surfaceOrientation = -1;
|
mLocked.surfaceOrientation = -1;
|
||||||
mLocked.surfaceWidth = -1;
|
mLocked.surfaceWidth = -1;
|
||||||
mLocked.surfaceHeight = -1;
|
mLocked.surfaceHeight = -1;
|
||||||
@ -1868,10 +1848,9 @@ void TouchInputMapper::configure() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void TouchInputMapper::configureParameters() {
|
void TouchInputMapper::configureParameters() {
|
||||||
mParameters.useBadTouchFilter = getPolicy()->filterTouchEvents();
|
mParameters.useBadTouchFilter = mConfig->filterTouchEvents;
|
||||||
mParameters.useAveragingTouchFilter = getPolicy()->filterTouchEvents();
|
mParameters.useAveragingTouchFilter = mConfig->filterTouchEvents;
|
||||||
mParameters.useJumpyTouchFilter = getPolicy()->filterJumpyTouchEvents();
|
mParameters.useJumpyTouchFilter = mConfig->filterJumpyTouchEvents;
|
||||||
mParameters.virtualKeyQuietTime = getPolicy()->getVirtualKeyQuietTime();
|
|
||||||
|
|
||||||
// TODO: select the default gesture mode based on whether the device supports
|
// TODO: select the default gesture mode based on whether the device supports
|
||||||
// distinct multitouch
|
// distinct multitouch
|
||||||
@ -2265,21 +2244,22 @@ bool TouchInputMapper::configureSurfaceLocked() {
|
|||||||
// X and Y of the same number of raw units cover the same physical distance.
|
// X and Y of the same number of raw units cover the same physical distance.
|
||||||
const float scaleFactor = 0.8f;
|
const float scaleFactor = 0.8f;
|
||||||
|
|
||||||
mLocked.pointerGestureXMovementScale = GESTURE_MOVEMENT_SPEED_RATIO
|
mLocked.pointerGestureXMovementScale = mConfig->pointerGestureMovementSpeedRatio
|
||||||
* displayDiagonal / rawDiagonal;
|
* displayDiagonal / rawDiagonal;
|
||||||
mLocked.pointerGestureYMovementScale = mLocked.pointerGestureXMovementScale;
|
mLocked.pointerGestureYMovementScale = mLocked.pointerGestureXMovementScale;
|
||||||
|
|
||||||
// Scale zooms to cover a smaller range of the display than movements do.
|
// 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
|
// This value determines the area around the pointer that is affected by freeform
|
||||||
// pointer gestures.
|
// pointer gestures.
|
||||||
mLocked.pointerGestureXZoomScale = GESTURE_ZOOM_SPEED_RATIO
|
mLocked.pointerGestureXZoomScale = mConfig->pointerGestureZoomSpeedRatio
|
||||||
* displayDiagonal / rawDiagonal;
|
* displayDiagonal / rawDiagonal;
|
||||||
mLocked.pointerGestureYZoomScale = mLocked.pointerGestureXZoomScale;
|
mLocked.pointerGestureYZoomScale = mLocked.pointerGestureXZoomScale;
|
||||||
|
|
||||||
// Max width between pointers to detect a swipe gesture is more than some fraction
|
// 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
|
// of the diagonal axis of the touch pad. Touches that are wider than this are
|
||||||
// translated into freeform gestures.
|
// translated into freeform gestures.
|
||||||
mLocked.pointerGestureMaxSwipeWidth = SWIPE_MAX_WIDTH_RATIO * rawDiagonal;
|
mLocked.pointerGestureMaxSwipeWidth =
|
||||||
|
mConfig->pointerGestureSwipeMaxWidthRatio * rawDiagonal;
|
||||||
|
|
||||||
// Reset the current pointer gesture.
|
// Reset the current pointer gesture.
|
||||||
mPointerGesture.reset();
|
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
|
// 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
|
// are layed out below the screen near to where the on screen keyboard's space bar
|
||||||
// is displayed.
|
// is displayed.
|
||||||
if (mParameters.virtualKeyQuietTime > 0 && mCurrentTouch.pointerCount != 0) {
|
if (mConfig->virtualKeyQuietTime > 0 && mCurrentTouch.pointerCount != 0) {
|
||||||
mContext->disableVirtualKeysUntil(when + mParameters.virtualKeyQuietTime);
|
mContext->disableVirtualKeysUntil(when + mConfig->virtualKeyQuietTime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3260,12 +3240,6 @@ void TouchInputMapper::prepareTouches(int32_t* outEdgeFlags,
|
|||||||
|
|
||||||
void TouchInputMapper::dispatchPointerGestures(nsecs_t when, uint32_t policyFlags,
|
void TouchInputMapper::dispatchPointerGestures(nsecs_t when, uint32_t policyFlags,
|
||||||
bool isTimeout) {
|
bool isTimeout) {
|
||||||
// Switch pointer presentation.
|
|
||||||
mPointerController->setPresentation(
|
|
||||||
mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS
|
|
||||||
? PointerControllerInterface::PRESENTATION_SPOT
|
|
||||||
: PointerControllerInterface::PRESENTATION_POINTER);
|
|
||||||
|
|
||||||
// Update current gesture coordinates.
|
// Update current gesture coordinates.
|
||||||
bool cancelPreviousGesture, finishPreviousGesture;
|
bool cancelPreviousGesture, finishPreviousGesture;
|
||||||
bool sendEvents = preparePointerGestures(when,
|
bool sendEvents = preparePointerGestures(when,
|
||||||
@ -3274,6 +3248,12 @@ void TouchInputMapper::dispatchPointerGestures(nsecs_t when, uint32_t policyFlag
|
|||||||
return;
|
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.
|
// Show or hide the pointer if needed.
|
||||||
switch (mPointerGesture.currentGestureMode) {
|
switch (mPointerGesture.currentGestureMode) {
|
||||||
case PointerGesture::NEUTRAL:
|
case PointerGesture::NEUTRAL:
|
||||||
@ -3441,9 +3421,10 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (mPointerGesture.lastGestureMode == PointerGesture::TAP) {
|
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.
|
// The tap/drag timeout has not yet expired.
|
||||||
getContext()->requestTimeoutAtTime(mPointerGesture.tapUpTime + TAP_DRAG_INTERVAL);
|
getContext()->requestTimeoutAtTime(mPointerGesture.tapUpTime
|
||||||
|
+ mConfig->pointerGestureTapDragInterval);
|
||||||
} else {
|
} else {
|
||||||
// The tap is finished.
|
// The tap is finished.
|
||||||
#if DEBUG_GESTURES
|
#if DEBUG_GESTURES
|
||||||
@ -3512,7 +3493,7 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when,
|
|||||||
if (activeTouchId < 0) {
|
if (activeTouchId < 0) {
|
||||||
mPointerGesture.resetQuietTime();
|
mPointerGesture.resetQuietTime();
|
||||||
} else {
|
} else {
|
||||||
isQuietTime = when < mPointerGesture.quietTime + QUIET_INTERVAL;
|
isQuietTime = when < mPointerGesture.quietTime + mConfig->pointerGestureQuietInterval;
|
||||||
if (!isQuietTime) {
|
if (!isQuietTime) {
|
||||||
if ((mPointerGesture.lastGestureMode == PointerGesture::PRESS
|
if ((mPointerGesture.lastGestureMode == PointerGesture::PRESS
|
||||||
|| mPointerGesture.lastGestureMode == PointerGesture::SWIPE
|
|| mPointerGesture.lastGestureMode == PointerGesture::SWIPE
|
||||||
@ -3583,7 +3564,7 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when,
|
|||||||
if (activeTouchId >= 0) {
|
if (activeTouchId >= 0) {
|
||||||
if (mCurrentTouch.pointerCount > 1) {
|
if (mCurrentTouch.pointerCount > 1) {
|
||||||
int32_t bestId = -1;
|
int32_t bestId = -1;
|
||||||
float bestSpeed = DRAG_MIN_SWITCH_SPEED;
|
float bestSpeed = mConfig->pointerGestureDragMinSwitchSpeed;
|
||||||
for (uint32_t i = 0; i < mCurrentTouch.pointerCount; i++) {
|
for (uint32_t i = 0; i < mCurrentTouch.pointerCount; i++) {
|
||||||
uint32_t id = mCurrentTouch.pointers[i].id;
|
uint32_t id = mCurrentTouch.pointers[i].id;
|
||||||
float vx, vy;
|
float vx, vy;
|
||||||
@ -3661,21 +3642,23 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when,
|
|||||||
*outFinishPreviousGesture = true;
|
*outFinishPreviousGesture = true;
|
||||||
|
|
||||||
// Watch for taps coming out of HOVER or TAP_DRAG mode.
|
// 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;
|
bool tapped = false;
|
||||||
if ((mPointerGesture.lastGestureMode == PointerGesture::HOVER
|
if ((mPointerGesture.lastGestureMode == PointerGesture::HOVER
|
||||||
|| mPointerGesture.lastGestureMode == PointerGesture::TAP_DRAG)
|
|| mPointerGesture.lastGestureMode == PointerGesture::TAP_DRAG)
|
||||||
&& mLastTouch.pointerCount == 1) {
|
&& mLastTouch.pointerCount == 1) {
|
||||||
if (when <= mPointerGesture.tapDownTime + TAP_INTERVAL) {
|
if (when <= mPointerGesture.tapDownTime + mConfig->pointerGestureTapInterval) {
|
||||||
float x, y;
|
float x, y;
|
||||||
mPointerController->getPosition(&x, &y);
|
mPointerController->getPosition(&x, &y);
|
||||||
if (fabs(x - mPointerGesture.tapX) <= TAP_SLOP
|
if (fabs(x - mPointerGesture.tapX) <= mConfig->pointerGestureTapSlop
|
||||||
&& fabs(y - mPointerGesture.tapY) <= TAP_SLOP) {
|
&& fabs(y - mPointerGesture.tapY) <= mConfig->pointerGestureTapSlop) {
|
||||||
#if DEBUG_GESTURES
|
#if DEBUG_GESTURES
|
||||||
LOGD("Gestures: TAP");
|
LOGD("Gestures: TAP");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
mPointerGesture.tapUpTime = when;
|
mPointerGesture.tapUpTime = when;
|
||||||
getContext()->requestTimeoutAtTime(when + TAP_DRAG_INTERVAL);
|
getContext()->requestTimeoutAtTime(when
|
||||||
|
+ mConfig->pointerGestureTapDragInterval);
|
||||||
|
|
||||||
mPointerGesture.activeGestureId = 0;
|
mPointerGesture.activeGestureId = 0;
|
||||||
mPointerGesture.currentGestureMode = PointerGesture::TAP;
|
mPointerGesture.currentGestureMode = PointerGesture::TAP;
|
||||||
@ -3740,11 +3723,11 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when,
|
|||||||
|
|
||||||
mPointerGesture.currentGestureMode = PointerGesture::HOVER;
|
mPointerGesture.currentGestureMode = PointerGesture::HOVER;
|
||||||
if (mPointerGesture.lastGestureMode == PointerGesture::TAP) {
|
if (mPointerGesture.lastGestureMode == PointerGesture::TAP) {
|
||||||
if (when <= mPointerGesture.tapUpTime + TAP_DRAG_INTERVAL) {
|
if (when <= mPointerGesture.tapUpTime + mConfig->pointerGestureTapDragInterval) {
|
||||||
float x, y;
|
float x, y;
|
||||||
mPointerController->getPosition(&x, &y);
|
mPointerController->getPosition(&x, &y);
|
||||||
if (fabs(x - mPointerGesture.tapX) <= TAP_SLOP
|
if (fabs(x - mPointerGesture.tapX) <= mConfig->pointerGestureTapSlop
|
||||||
&& fabs(y - mPointerGesture.tapY) <= TAP_SLOP) {
|
&& fabs(y - mPointerGesture.tapY) <= mConfig->pointerGestureTapSlop) {
|
||||||
mPointerGesture.currentGestureMode = PointerGesture::TAP_DRAG;
|
mPointerGesture.currentGestureMode = PointerGesture::TAP_DRAG;
|
||||||
} else {
|
} else {
|
||||||
#if DEBUG_GESTURES
|
#if DEBUG_GESTURES
|
||||||
@ -3838,7 +3821,8 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when,
|
|||||||
LOG_ASSERT(activeTouchId >= 0);
|
LOG_ASSERT(activeTouchId >= 0);
|
||||||
|
|
||||||
bool needReference = false;
|
bool needReference = false;
|
||||||
bool settled = when >= mPointerGesture.firstTouchTime + MULTITOUCH_SETTLE_INTERVAL;
|
bool settled = when >= mPointerGesture.firstTouchTime
|
||||||
|
+ mConfig->pointerGestureMultitouchSettleInterval;
|
||||||
if (mPointerGesture.lastGestureMode != PointerGesture::PRESS
|
if (mPointerGesture.lastGestureMode != PointerGesture::PRESS
|
||||||
&& mPointerGesture.lastGestureMode != PointerGesture::SWIPE
|
&& mPointerGesture.lastGestureMode != PointerGesture::SWIPE
|
||||||
&& mPointerGesture.lastGestureMode != PointerGesture::FREEFORM) {
|
&& mPointerGesture.lastGestureMode != PointerGesture::FREEFORM) {
|
||||||
@ -3932,14 +3916,15 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when,
|
|||||||
|
|
||||||
float speed1 = hypotf(vx1, vy1);
|
float speed1 = hypotf(vx1, vy1);
|
||||||
float speed2 = hypotf(vx2, vy2);
|
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.
|
// Calculate the dot product of the velocity vectors.
|
||||||
// When the vectors are oriented in approximately the same direction,
|
// When the vectors are oriented in approximately the same direction,
|
||||||
// the angle betweeen them is near zero and the cosine of the angle
|
// 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).
|
// approches 1.0. Recall that dot(v1, v2) = cos(angle) * mag(v1) * mag(v2).
|
||||||
float dot = vx1 * vx2 + vy1 * vy2;
|
float dot = vx1 * vx2 + vy1 * vy2;
|
||||||
float cosine = dot / (speed1 * speed2); // denominator always > 0
|
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.
|
// Pointers are moving in the same direction. Switch to SWIPE.
|
||||||
#if DEBUG_GESTURES
|
#if DEBUG_GESTURES
|
||||||
LOGD("Gestures: PRESS transitioned to SWIPE, "
|
LOGD("Gestures: PRESS transitioned to SWIPE, "
|
||||||
|
@ -39,6 +39,109 @@ class InputDevice;
|
|||||||
class InputMapper;
|
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.
|
* Input reader policy interface.
|
||||||
*
|
*
|
||||||
@ -68,24 +171,8 @@ public:
|
|||||||
virtual bool getDisplayInfo(int32_t displayId,
|
virtual bool getDisplayInfo(int32_t displayId,
|
||||||
int32_t* width, int32_t* height, int32_t* orientation) = 0;
|
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
|
/* Gets the input reader configuration. */
|
||||||
* certain device whose screen currently is not all that good.
|
virtual void getReaderConfiguration(InputReaderConfiguration* outConfig) = 0;
|
||||||
*/
|
|
||||||
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 a pointer controller associated with the specified cursor device (ie. a mouse). */
|
/* Gets a pointer controller associated with the specified cursor device (ie. a mouse). */
|
||||||
virtual sp<PointerControllerInterface> obtainPointerController(int32_t deviceId) = 0;
|
virtual sp<PointerControllerInterface> obtainPointerController(int32_t deviceId) = 0;
|
||||||
@ -162,6 +249,7 @@ public:
|
|||||||
virtual void requestTimeoutAtTime(nsecs_t when) = 0;
|
virtual void requestTimeoutAtTime(nsecs_t when) = 0;
|
||||||
|
|
||||||
virtual InputReaderPolicyInterface* getPolicy() = 0;
|
virtual InputReaderPolicyInterface* getPolicy() = 0;
|
||||||
|
virtual const InputReaderConfiguration* getConfig() = 0;
|
||||||
virtual InputDispatcherInterface* getDispatcher() = 0;
|
virtual InputDispatcherInterface* getDispatcher() = 0;
|
||||||
virtual EventHubInterface* getEventHub() = 0;
|
virtual EventHubInterface* getEventHub() = 0;
|
||||||
};
|
};
|
||||||
@ -212,7 +300,10 @@ private:
|
|||||||
sp<InputReaderPolicyInterface> mPolicy;
|
sp<InputReaderPolicyInterface> mPolicy;
|
||||||
sp<InputDispatcherInterface> mDispatcher;
|
sp<InputDispatcherInterface> mDispatcher;
|
||||||
|
|
||||||
|
InputReaderConfiguration mConfig;
|
||||||
|
|
||||||
virtual InputReaderPolicyInterface* getPolicy() { return mPolicy.get(); }
|
virtual InputReaderPolicyInterface* getPolicy() { return mPolicy.get(); }
|
||||||
|
virtual const InputReaderConfiguration* getConfig() { return &mConfig; }
|
||||||
virtual InputDispatcherInterface* getDispatcher() { return mDispatcher.get(); }
|
virtual InputDispatcherInterface* getDispatcher() { return mDispatcher.get(); }
|
||||||
virtual EventHubInterface* getEventHub() { return mEventHub.get(); }
|
virtual EventHubInterface* getEventHub() { return mEventHub.get(); }
|
||||||
|
|
||||||
@ -353,6 +444,7 @@ public:
|
|||||||
inline const String8 getDeviceName() { return mDevice->getName(); }
|
inline const String8 getDeviceName() { return mDevice->getName(); }
|
||||||
inline InputReaderContext* getContext() { return mContext; }
|
inline InputReaderContext* getContext() { return mContext; }
|
||||||
inline InputReaderPolicyInterface* getPolicy() { return mContext->getPolicy(); }
|
inline InputReaderPolicyInterface* getPolicy() { return mContext->getPolicy(); }
|
||||||
|
inline const InputReaderConfiguration* getConfig() { return mContext->getConfig(); }
|
||||||
inline InputDispatcherInterface* getDispatcher() { return mContext->getDispatcher(); }
|
inline InputDispatcherInterface* getDispatcher() { return mContext->getDispatcher(); }
|
||||||
inline EventHubInterface* getEventHub() { return mContext->getEventHub(); }
|
inline EventHubInterface* getEventHub() { return mContext->getEventHub(); }
|
||||||
|
|
||||||
@ -665,6 +757,9 @@ protected:
|
|||||||
uint32_t mTouchSource; // sources when reporting touch data
|
uint32_t mTouchSource; // sources when reporting touch data
|
||||||
uint32_t mPointerSource; // sources when reporting pointer gestures
|
uint32_t mPointerSource; // sources when reporting pointer gestures
|
||||||
|
|
||||||
|
// The reader's configuration.
|
||||||
|
const InputReaderConfiguration* mConfig;
|
||||||
|
|
||||||
// Immutable configuration parameters.
|
// Immutable configuration parameters.
|
||||||
struct Parameters {
|
struct Parameters {
|
||||||
enum DeviceType {
|
enum DeviceType {
|
||||||
@ -680,7 +775,6 @@ protected:
|
|||||||
bool useBadTouchFilter;
|
bool useBadTouchFilter;
|
||||||
bool useJumpyTouchFilter;
|
bool useJumpyTouchFilter;
|
||||||
bool useAveragingTouchFilter;
|
bool useAveragingTouchFilter;
|
||||||
nsecs_t virtualKeyQuietTime;
|
|
||||||
|
|
||||||
enum GestureMode {
|
enum GestureMode {
|
||||||
GESTURE_MODE_POINTER,
|
GESTURE_MODE_POINTER,
|
||||||
@ -939,6 +1033,8 @@ private:
|
|||||||
// Exactly one finger dragging following a tap.
|
// Exactly one finger dragging following a tap.
|
||||||
// Pointer follows the active finger.
|
// Pointer follows the active finger.
|
||||||
// Emits DOWN, MOVE and UP events at the pointer location.
|
// 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,
|
TAP_DRAG,
|
||||||
|
|
||||||
// Button is pressed.
|
// Button is pressed.
|
||||||
@ -949,6 +1045,8 @@ private:
|
|||||||
// Exactly one finger, button is not pressed.
|
// Exactly one finger, button is not pressed.
|
||||||
// Pointer follows the active finger.
|
// Pointer follows the active finger.
|
||||||
// Emits HOVER_MOVE events at the pointer location.
|
// Emits HOVER_MOVE events at the pointer location.
|
||||||
|
//
|
||||||
|
// Detect taps when the finger goes up while in HOVER mode.
|
||||||
HOVER,
|
HOVER,
|
||||||
|
|
||||||
// Exactly two fingers but neither have moved enough to clearly indicate
|
// Exactly two fingers but neither have moved enough to clearly indicate
|
||||||
|
@ -35,6 +35,8 @@ static const int32_t INJECTOR_UID = 1001;
|
|||||||
// --- FakeInputDispatcherPolicy ---
|
// --- FakeInputDispatcherPolicy ---
|
||||||
|
|
||||||
class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface {
|
class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface {
|
||||||
|
InputDispatcherConfiguration mConfig;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual ~FakeInputDispatcherPolicy() {
|
virtual ~FakeInputDispatcherPolicy() {
|
||||||
}
|
}
|
||||||
@ -55,16 +57,12 @@ private:
|
|||||||
virtual void notifyInputChannelBroken(const sp<InputWindowHandle>& inputWindowHandle) {
|
virtual void notifyInputChannelBroken(const sp<InputWindowHandle>& inputWindowHandle) {
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual nsecs_t getKeyRepeatTimeout() {
|
virtual void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) {
|
||||||
return 500 * 1000000LL;
|
*outConfig = mConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual nsecs_t getKeyRepeatDelay() {
|
virtual bool isKeyRepeatEnabled() {
|
||||||
return 50 * 1000000LL;
|
return true;
|
||||||
}
|
|
||||||
|
|
||||||
virtual int32_t getMaxEventsPerSecond() {
|
|
||||||
return 60;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void interceptKeyBeforeQueueing(const KeyEvent* keyEvent, uint32_t& policyFlags) {
|
virtual void interceptKeyBeforeQueueing(const KeyEvent* keyEvent, uint32_t& policyFlags) {
|
||||||
|
@ -120,17 +120,14 @@ class FakeInputReaderPolicy : public InputReaderPolicyInterface {
|
|||||||
};
|
};
|
||||||
|
|
||||||
KeyedVector<int32_t, DisplayInfo> mDisplayInfos;
|
KeyedVector<int32_t, DisplayInfo> mDisplayInfos;
|
||||||
bool mFilterTouchEvents;
|
InputReaderConfiguration mConfig;
|
||||||
bool mFilterJumpyTouchEvents;
|
|
||||||
Vector<String8> mExcludedDeviceNames;
|
|
||||||
KeyedVector<int32_t, sp<FakePointerController> > mPointerControllers;
|
KeyedVector<int32_t, sp<FakePointerController> > mPointerControllers;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual ~FakeInputReaderPolicy() { }
|
virtual ~FakeInputReaderPolicy() { }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FakeInputReaderPolicy() :
|
FakeInputReaderPolicy() {
|
||||||
mFilterTouchEvents(false), mFilterJumpyTouchEvents(false) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void removeDisplayInfo(int32_t displayId) {
|
void removeDisplayInfo(int32_t displayId) {
|
||||||
@ -148,11 +145,11 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void setFilterTouchEvents(bool enabled) {
|
void setFilterTouchEvents(bool enabled) {
|
||||||
mFilterTouchEvents = enabled;
|
mConfig.filterTouchEvents = enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setFilterJumpyTouchEvents(bool enabled) {
|
void setFilterJumpyTouchEvents(bool enabled) {
|
||||||
mFilterJumpyTouchEvents = enabled;
|
mConfig.filterJumpyTouchEvents = enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual nsecs_t getVirtualKeyQuietTime() {
|
virtual nsecs_t getVirtualKeyQuietTime() {
|
||||||
@ -160,7 +157,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void addExcludedDeviceName(const String8& deviceName) {
|
void addExcludedDeviceName(const String8& deviceName) {
|
||||||
mExcludedDeviceNames.push(deviceName);
|
mConfig.excludedDeviceNames.push(deviceName);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setPointerController(int32_t deviceId, const sp<FakePointerController>& controller) {
|
void setPointerController(int32_t deviceId, const sp<FakePointerController>& controller) {
|
||||||
@ -187,16 +184,8 @@ private:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool filterTouchEvents() {
|
virtual void getReaderConfiguration(InputReaderConfiguration* outConfig) {
|
||||||
return mFilterTouchEvents;
|
*outConfig = mConfig;
|
||||||
}
|
|
||||||
|
|
||||||
virtual bool filterJumpyTouchEvents() {
|
|
||||||
return mFilterJumpyTouchEvents;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void getExcludedDeviceNames(Vector<String8>& outExcludedDeviceNames) {
|
|
||||||
outExcludedDeviceNames.appendVector(mExcludedDeviceNames);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual sp<PointerControllerInterface> obtainPointerController(int32_t deviceId) {
|
virtual sp<PointerControllerInterface> obtainPointerController(int32_t deviceId) {
|
||||||
@ -739,6 +728,8 @@ class FakeInputReaderContext : public InputReaderContext {
|
|||||||
int32_t mGlobalMetaState;
|
int32_t mGlobalMetaState;
|
||||||
bool mUpdateGlobalMetaStateWasCalled;
|
bool mUpdateGlobalMetaStateWasCalled;
|
||||||
|
|
||||||
|
InputReaderConfiguration mConfig;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FakeInputReaderContext(const sp<EventHubInterface>& eventHub,
|
FakeInputReaderContext(const sp<EventHubInterface>& eventHub,
|
||||||
const sp<InputReaderPolicyInterface>& policy,
|
const sp<InputReaderPolicyInterface>& policy,
|
||||||
@ -776,6 +767,11 @@ private:
|
|||||||
return mPolicy.get();
|
return mPolicy.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual const InputReaderConfiguration* getConfig() {
|
||||||
|
mPolicy->getReaderConfiguration(&mConfig);
|
||||||
|
return &mConfig;
|
||||||
|
}
|
||||||
|
|
||||||
virtual InputDispatcherInterface* getDispatcher() {
|
virtual InputDispatcherInterface* getDispatcher() {
|
||||||
return mDispatcher.get();
|
return mDispatcher.get();
|
||||||
}
|
}
|
||||||
|
@ -495,6 +495,26 @@ public class InputManager {
|
|||||||
return ViewConfiguration.getKeyRepeatDelay();
|
return ViewConfiguration.getKeyRepeatDelay();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@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")
|
@SuppressWarnings("unused")
|
||||||
public int getMaxEventsPerSecond() {
|
public int getMaxEventsPerSecond() {
|
||||||
int result = 0;
|
int result = 0;
|
||||||
|
@ -72,6 +72,10 @@ static struct {
|
|||||||
jmethodID getKeyRepeatTimeout;
|
jmethodID getKeyRepeatTimeout;
|
||||||
jmethodID getKeyRepeatDelay;
|
jmethodID getKeyRepeatDelay;
|
||||||
jmethodID getMaxEventsPerSecond;
|
jmethodID getMaxEventsPerSecond;
|
||||||
|
jmethodID getTapTimeout;
|
||||||
|
jmethodID getDoubleTapTimeout;
|
||||||
|
jmethodID getLongPressTimeout;
|
||||||
|
jmethodID getTouchSlop;
|
||||||
jmethodID getPointerLayer;
|
jmethodID getPointerLayer;
|
||||||
jmethodID getPointerIcon;
|
jmethodID getPointerIcon;
|
||||||
} gCallbacksClassInfo;
|
} gCallbacksClassInfo;
|
||||||
@ -107,6 +111,16 @@ static struct {
|
|||||||
|
|
||||||
// --- Global functions ---
|
// --- 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,
|
static jobject getInputApplicationHandleObjLocalRef(JNIEnv* env,
|
||||||
const sp<InputApplicationHandle>& inputApplicationHandle) {
|
const sp<InputApplicationHandle>& inputApplicationHandle) {
|
||||||
if (inputApplicationHandle == NULL) {
|
if (inputApplicationHandle == NULL) {
|
||||||
@ -170,10 +184,7 @@ public:
|
|||||||
|
|
||||||
virtual bool getDisplayInfo(int32_t displayId,
|
virtual bool getDisplayInfo(int32_t displayId,
|
||||||
int32_t* width, int32_t* height, int32_t* orientation);
|
int32_t* width, int32_t* height, int32_t* orientation);
|
||||||
virtual bool filterTouchEvents();
|
virtual void getReaderConfiguration(InputReaderConfiguration* outConfig);
|
||||||
virtual bool filterJumpyTouchEvents();
|
|
||||||
virtual nsecs_t getVirtualKeyQuietTime();
|
|
||||||
virtual void getExcludedDeviceNames(Vector<String8>& outExcludedDeviceNames);
|
|
||||||
virtual sp<PointerControllerInterface> obtainPointerController(int32_t deviceId);
|
virtual sp<PointerControllerInterface> obtainPointerController(int32_t deviceId);
|
||||||
|
|
||||||
/* --- InputDispatcherPolicyInterface implementation --- */
|
/* --- InputDispatcherPolicyInterface implementation --- */
|
||||||
@ -184,9 +195,8 @@ public:
|
|||||||
virtual nsecs_t notifyANR(const sp<InputApplicationHandle>& inputApplicationHandle,
|
virtual nsecs_t notifyANR(const sp<InputApplicationHandle>& inputApplicationHandle,
|
||||||
const sp<InputWindowHandle>& inputWindowHandle);
|
const sp<InputWindowHandle>& inputWindowHandle);
|
||||||
virtual void notifyInputChannelBroken(const sp<InputWindowHandle>& inputWindowHandle);
|
virtual void notifyInputChannelBroken(const sp<InputWindowHandle>& inputWindowHandle);
|
||||||
virtual nsecs_t getKeyRepeatTimeout();
|
virtual void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig);
|
||||||
virtual nsecs_t getKeyRepeatDelay();
|
virtual bool isKeyRepeatEnabled();
|
||||||
virtual int32_t getMaxEventsPerSecond();
|
|
||||||
virtual void interceptKeyBeforeQueueing(const KeyEvent* keyEvent, uint32_t& policyFlags);
|
virtual void interceptKeyBeforeQueueing(const KeyEvent* keyEvent, uint32_t& policyFlags);
|
||||||
virtual void interceptMotionBeforeQueueing(nsecs_t when, uint32_t& policyFlags);
|
virtual void interceptMotionBeforeQueueing(nsecs_t when, uint32_t& policyFlags);
|
||||||
virtual bool interceptKeyBeforeDispatching(const sp<InputWindowHandle>& inputWindowHandle,
|
virtual bool interceptKeyBeforeDispatching(const sp<InputWindowHandle>& inputWindowHandle,
|
||||||
@ -208,18 +218,6 @@ private:
|
|||||||
jobject mCallbacksObj;
|
jobject mCallbacksObj;
|
||||||
sp<Looper> mLooper;
|
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;
|
Mutex mLock;
|
||||||
struct Locked {
|
struct Locked {
|
||||||
// Display size information.
|
// Display size information.
|
||||||
@ -255,10 +253,7 @@ private:
|
|||||||
|
|
||||||
NativeInputManager::NativeInputManager(jobject contextObj,
|
NativeInputManager::NativeInputManager(jobject contextObj,
|
||||||
jobject callbacksObj, const sp<Looper>& looper) :
|
jobject callbacksObj, const sp<Looper>& looper) :
|
||||||
mLooper(looper),
|
mLooper(looper) {
|
||||||
mFilterTouchEvents(-1), mFilterJumpyTouchEvents(-1), mVirtualKeyQuietTime(-1),
|
|
||||||
mKeyRepeatTimeout(-1), mKeyRepeatDelay(-1),
|
|
||||||
mMaxEventsPerSecond(-1) {
|
|
||||||
JNIEnv* env = jniEnv();
|
JNIEnv* env = jniEnv();
|
||||||
|
|
||||||
mContextObj = env->NewGlobalRef(contextObj);
|
mContextObj = env->NewGlobalRef(contextObj);
|
||||||
@ -371,73 +366,68 @@ bool NativeInputManager::getDisplayInfo(int32_t displayId,
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NativeInputManager::filterTouchEvents() {
|
void NativeInputManager::getReaderConfiguration(InputReaderConfiguration* outConfig) {
|
||||||
if (mFilterTouchEvents < 0) {
|
|
||||||
JNIEnv* env = jniEnv();
|
JNIEnv* env = jniEnv();
|
||||||
|
|
||||||
jboolean result = env->CallBooleanMethod(mCallbacksObj,
|
jboolean filterTouchEvents = env->CallBooleanMethod(mCallbacksObj,
|
||||||
gCallbacksClassInfo.filterTouchEvents);
|
gCallbacksClassInfo.filterTouchEvents);
|
||||||
if (checkAndClearExceptionFromCallback(env, "filterTouchEvents")) {
|
if (!checkAndClearExceptionFromCallback(env, "filterTouchEvents")) {
|
||||||
result = false;
|
outConfig->filterTouchEvents = filterTouchEvents;
|
||||||
}
|
}
|
||||||
|
|
||||||
mFilterTouchEvents = result ? 1 : 0;
|
jboolean filterJumpyTouchEvents = env->CallBooleanMethod(mCallbacksObj,
|
||||||
}
|
|
||||||
return mFilterTouchEvents;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool NativeInputManager::filterJumpyTouchEvents() {
|
|
||||||
if (mFilterJumpyTouchEvents < 0) {
|
|
||||||
JNIEnv* env = jniEnv();
|
|
||||||
|
|
||||||
jboolean result = env->CallBooleanMethod(mCallbacksObj,
|
|
||||||
gCallbacksClassInfo.filterJumpyTouchEvents);
|
gCallbacksClassInfo.filterJumpyTouchEvents);
|
||||||
if (checkAndClearExceptionFromCallback(env, "filterJumpyTouchEvents")) {
|
if (!checkAndClearExceptionFromCallback(env, "filterJumpyTouchEvents")) {
|
||||||
result = false;
|
outConfig->filterJumpyTouchEvents = filterJumpyTouchEvents;
|
||||||
}
|
}
|
||||||
|
|
||||||
mFilterJumpyTouchEvents = result ? 1 : 0;
|
jint virtualKeyQuietTime = env->CallIntMethod(mCallbacksObj,
|
||||||
}
|
|
||||||
return mFilterJumpyTouchEvents;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsecs_t NativeInputManager::getVirtualKeyQuietTime() {
|
|
||||||
if (mVirtualKeyQuietTime < 0) {
|
|
||||||
JNIEnv* env = jniEnv();
|
|
||||||
|
|
||||||
jint result = env->CallIntMethod(mCallbacksObj,
|
|
||||||
gCallbacksClassInfo.getVirtualKeyQuietTimeMillis);
|
gCallbacksClassInfo.getVirtualKeyQuietTimeMillis);
|
||||||
if (checkAndClearExceptionFromCallback(env, "getVirtualKeyQuietTimeMillis")) {
|
if (!checkAndClearExceptionFromCallback(env, "getVirtualKeyQuietTimeMillis")) {
|
||||||
result = 0;
|
outConfig->virtualKeyQuietTime = milliseconds_to_nanoseconds(virtualKeyQuietTime);
|
||||||
}
|
|
||||||
if (result < 0) {
|
|
||||||
result = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mVirtualKeyQuietTime = milliseconds_to_nanoseconds(result);
|
outConfig->excludedDeviceNames.clear();
|
||||||
}
|
jobjectArray excludedDeviceNames = jobjectArray(env->CallObjectMethod(mCallbacksObj,
|
||||||
return mVirtualKeyQuietTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
void NativeInputManager::getExcludedDeviceNames(Vector<String8>& outExcludedDeviceNames) {
|
|
||||||
outExcludedDeviceNames.clear();
|
|
||||||
|
|
||||||
JNIEnv* env = jniEnv();
|
|
||||||
|
|
||||||
jobjectArray result = jobjectArray(env->CallObjectMethod(mCallbacksObj,
|
|
||||||
gCallbacksClassInfo.getExcludedDeviceNames));
|
gCallbacksClassInfo.getExcludedDeviceNames));
|
||||||
if (! checkAndClearExceptionFromCallback(env, "getExcludedDeviceNames") && result) {
|
if (!checkAndClearExceptionFromCallback(env, "getExcludedDeviceNames") && excludedDeviceNames) {
|
||||||
jsize length = env->GetArrayLength(result);
|
jsize length = env->GetArrayLength(excludedDeviceNames);
|
||||||
for (jsize i = 0; i < length; i++) {
|
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);
|
const char* deviceNameChars = env->GetStringUTFChars(item, NULL);
|
||||||
outExcludedDeviceNames.add(String8(deviceNameChars));
|
outConfig->excludedDeviceNames.add(String8(deviceNameChars));
|
||||||
env->ReleaseStringUTFChars(item, deviceNameChars);
|
env->ReleaseStringUTFChars(item, deviceNameChars);
|
||||||
|
|
||||||
env->DeleteLocalRef(item);
|
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() {
|
void NativeInputManager::getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) {
|
||||||
if (! isScreenOn()) {
|
|
||||||
// Disable key repeat when the screen is off.
|
|
||||||
return -1;
|
|
||||||
} else {
|
|
||||||
if (mKeyRepeatTimeout < 0) {
|
|
||||||
JNIEnv* env = jniEnv();
|
JNIEnv* env = jniEnv();
|
||||||
|
|
||||||
jint result = env->CallIntMethod(mCallbacksObj,
|
jint keyRepeatTimeout = env->CallIntMethod(mCallbacksObj,
|
||||||
gCallbacksClassInfo.getKeyRepeatTimeout);
|
gCallbacksClassInfo.getKeyRepeatTimeout);
|
||||||
if (checkAndClearExceptionFromCallback(env, "getKeyRepeatTimeout")) {
|
if (!checkAndClearExceptionFromCallback(env, "getKeyRepeatTimeout")) {
|
||||||
result = 500;
|
outConfig->keyRepeatTimeout = milliseconds_to_nanoseconds(keyRepeatTimeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
mKeyRepeatTimeout = milliseconds_to_nanoseconds(result);
|
jint keyRepeatDelay = env->CallIntMethod(mCallbacksObj,
|
||||||
}
|
|
||||||
return mKeyRepeatTimeout;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
nsecs_t NativeInputManager::getKeyRepeatDelay() {
|
|
||||||
if (mKeyRepeatDelay < 0) {
|
|
||||||
JNIEnv* env = jniEnv();
|
|
||||||
|
|
||||||
jint result = env->CallIntMethod(mCallbacksObj,
|
|
||||||
gCallbacksClassInfo.getKeyRepeatDelay);
|
gCallbacksClassInfo.getKeyRepeatDelay);
|
||||||
if (checkAndClearExceptionFromCallback(env, "getKeyRepeatDelay")) {
|
if (!checkAndClearExceptionFromCallback(env, "getKeyRepeatDelay")) {
|
||||||
result = 50;
|
outConfig->keyRepeatDelay = milliseconds_to_nanoseconds(keyRepeatDelay);
|
||||||
}
|
}
|
||||||
|
|
||||||
mKeyRepeatDelay = milliseconds_to_nanoseconds(result);
|
jint maxEventsPerSecond = env->CallIntMethod(mCallbacksObj,
|
||||||
}
|
|
||||||
return mKeyRepeatDelay;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t NativeInputManager::getMaxEventsPerSecond() {
|
|
||||||
if (mMaxEventsPerSecond < 0) {
|
|
||||||
JNIEnv* env = jniEnv();
|
|
||||||
|
|
||||||
jint result = env->CallIntMethod(mCallbacksObj,
|
|
||||||
gCallbacksClassInfo.getMaxEventsPerSecond);
|
gCallbacksClassInfo.getMaxEventsPerSecond);
|
||||||
if (checkAndClearExceptionFromCallback(env, "getMaxEventsPerSecond")) {
|
if (!checkAndClearExceptionFromCallback(env, "getMaxEventsPerSecond")) {
|
||||||
result = 60;
|
outConfig->maxEventsPerSecond = maxEventsPerSecond;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mMaxEventsPerSecond = result;
|
bool NativeInputManager::isKeyRepeatEnabled() {
|
||||||
}
|
// Only enable automatic key repeating when the screen is on.
|
||||||
return mMaxEventsPerSecond;
|
return isScreenOn();
|
||||||
}
|
}
|
||||||
|
|
||||||
void NativeInputManager::setInputWindows(JNIEnv* env, jobjectArray windowObjArray) {
|
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,
|
GET_METHOD_ID(gCallbacksClassInfo.getKeyRepeatDelay, gCallbacksClassInfo.clazz,
|
||||||
"getKeyRepeatDelay", "()I");
|
"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,
|
GET_METHOD_ID(gCallbacksClassInfo.getMaxEventsPerSecond, gCallbacksClassInfo.clazz,
|
||||||
"getMaxEventsPerSecond", "()I");
|
"getMaxEventsPerSecond", "()I");
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user