summaryrefslogtreecommitdiff
path: root/services/inputflinger/InputReader.cpp
diff options
context:
space:
mode:
author Michael Wright <michaelwr@google.com> 2015-04-21 19:02:58 +0100
committer Michael Wright <michaelwr@google.com> 2015-05-12 14:08:47 +0100
commit43fd19fd1a22d95ed985a0680fd8806d918f3ba7 (patch)
tree62e046c09126bba5649cc7f72a61ab8b997ce824 /services/inputflinger/InputReader.cpp
parent79e287890da9de37a834cceebdefe32a7d3ac0ac (diff)
Synthesize events for pressure and button changes.
Even when there isn't movement on the touchscreen we should produce events for pressure and button state changes generated by external stylii. Change-Id: I9fd7ba85902d5d6bfb28d5e5ff5d8f340a94c2bf
Diffstat (limited to 'services/inputflinger/InputReader.cpp')
-rw-r--r--services/inputflinger/InputReader.cpp58
1 files changed, 39 insertions, 19 deletions
diff --git a/services/inputflinger/InputReader.cpp b/services/inputflinger/InputReader.cpp
index 8709692060..c6389a9c9a 100644
--- a/services/inputflinger/InputReader.cpp
+++ b/services/inputflinger/InputReader.cpp
@@ -73,6 +73,13 @@ static const size_t MAX_SLOTS = 32;
// external stylus.
static const nsecs_t EXTERNAL_STYLUS_DATA_TIMEOUT = ms2ns(72);
+// Maximum amount of time to wait on touch data before pushing out new pressure data.
+static const nsecs_t TOUCH_DATA_TIMEOUT = ms2ns(20);
+
+// Artificial latency on synthetic events created from stylus data without corresponding touch
+// data.
+static const nsecs_t STYLUS_DATA_LATENCY = ms2ns(10);
+
// --- Static Functions ---
template<typename T>
@@ -2827,7 +2834,7 @@ void TouchInputMapper::dump(String8& dump) {
toString(mExternalStylusConnected));
dump.appendFormat(INDENT4 "External Stylus ID: %" PRId64 "\n", mExternalStylusId);
dump.appendFormat(INDENT4 "External Stylus Data Timeout: %" PRId64 "\n",
- mExternalStylusDataTimeout);
+ mExternalStylusFusionTimeout);
dump.append(INDENT3 "External Stylus State:\n");
dumpStylusState(dump, mExternalStylusState);
@@ -3836,8 +3843,13 @@ void TouchInputMapper::reset(nsecs_t when) {
void TouchInputMapper::resetExternalStylus() {
mExternalStylusState.clear();
mExternalStylusId = -1;
- mExternalStylusDataTimeout = LLONG_MAX;
+ mExternalStylusFusionTimeout = LLONG_MAX;
+ mExternalStylusDataPending = false;
+}
+
+void TouchInputMapper::clearStylusDataPendingFlags() {
mExternalStylusDataPending = false;
+ mExternalStylusFusionTimeout = LLONG_MAX;
}
void TouchInputMapper::process(const RawEvent* rawEvent) {
@@ -3915,19 +3927,30 @@ void TouchInputMapper::processRawTouches(bool timeout) {
}
// All ready to go.
- mExternalStylusDataPending = false;
+ clearStylusDataPendingFlags();
mCurrentRawState.copyFrom(next);
+ if (mCurrentRawState.when < mLastRawState.when) {
+ mCurrentRawState.when = mLastRawState.when;
+ }
cookAndDispatch(mCurrentRawState.when);
}
if (count != 0) {
mRawStatesPending.removeItemsAt(0, count);
}
- // TODO: If we still have pending stylus data that hasn't been mapped to a touch yet
- // then set a timeout to synthesize a new touch event with the new data. Otherwise
- // we will lose button and pressure information while the touch is stationary.
if (mExternalStylusDataPending) {
- ALOGD("STYLUS TODO: Wiggle wiggle wiggle.");
+ if (timeout) {
+ nsecs_t when = mExternalStylusFusionTimeout - STYLUS_DATA_LATENCY;
+ clearStylusDataPendingFlags();
+ mCurrentRawState.copyFrom(mLastRawState);
+#if DEBUG_STYLUS_FUSION
+ ALOGD("Timeout expired, synthesizing event with new stylus data");
+#endif
+ cookAndDispatch(when);
+ } else if (mExternalStylusFusionTimeout == LLONG_MAX) {
+ mExternalStylusFusionTimeout = mExternalStylusState.when + TOUCH_DATA_TIMEOUT;
+ getContext()->requestTimeoutAtTime(mExternalStylusFusionTimeout);
+ }
}
}
@@ -4086,15 +4109,14 @@ bool TouchInputMapper::assignExternalStylusId(const RawState& state, bool timeou
#endif
resetExternalStylus();
} else {
- nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
- if (mExternalStylusDataTimeout == LLONG_MAX) {
- mExternalStylusDataTimeout = now + EXTERNAL_STYLUS_DATA_TIMEOUT;
+ if (mExternalStylusFusionTimeout == LLONG_MAX) {
+ mExternalStylusFusionTimeout = state.when + EXTERNAL_STYLUS_DATA_TIMEOUT;
}
#if DEBUG_STYLUS_FUSION
ALOGD("No stylus data but stylus is connected, requesting timeout "
- "(%" PRId64 "ms)", mExternalStylusDataTimeout);
+ "(%" PRId64 "ms)", mExternalStylusFusionTimeout);
#endif
- getContext()->requestTimeoutAtTime(mExternalStylusDataTimeout);
+ getContext()->requestTimeoutAtTime(mExternalStylusFusionTimeout);
return true;
}
}
@@ -4117,22 +4139,20 @@ void TouchInputMapper::timeoutExpired(nsecs_t when) {
dispatchPointerGestures(when, 0 /*policyFlags*/, true /*isTimeout*/);
}
} else if (mDeviceMode == DEVICE_MODE_DIRECT) {
- if (mExternalStylusDataTimeout < when) {
- mExternalStylusDataTimeout = LLONG_MAX;
+ if (mExternalStylusFusionTimeout < when) {
processRawTouches(true /*timeout*/);
- } else if (mExternalStylusDataTimeout != LLONG_MAX) {
- getContext()->requestTimeoutAtTime(mExternalStylusDataTimeout);
+ } else if (mExternalStylusFusionTimeout != LLONG_MAX) {
+ getContext()->requestTimeoutAtTime(mExternalStylusFusionTimeout);
}
}
}
void TouchInputMapper::updateExternalStylusState(const StylusState& state) {
mExternalStylusState.copyFrom(state);
- if (mExternalStylusId != -1 || mExternalStylusDataTimeout != LLONG_MAX) {
+ if (mExternalStylusId != -1 || mExternalStylusFusionTimeout != LLONG_MAX) {
// We're either in the middle of a fused stream of data or we're waiting on data before
// dispatching the initial down, so go ahead and dispatch now that we have fresh stylus
// data.
- mExternalStylusDataTimeout = LLONG_MAX;
mExternalStylusDataPending = true;
processRawTouches(false /*timeout*/);
}
@@ -4310,7 +4330,7 @@ void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) {
// Dispatch move events if any of the remaining pointers moved from their old locations.
// Although applications receive new locations as part of individual pointer up
// events, they do not generally handle them except when presented in a move event.
- if (moveNeeded) {
+ if (moveNeeded && !moveIdBits.isEmpty()) {
ALOG_ASSERT(moveIdBits.value == dispatchedIdBits.value);
dispatchMotion(when, policyFlags, mSource,
AMOTION_EVENT_ACTION_MOVE, 0, metaState, buttonState, 0,