summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeff Brown <jeffbrown@google.com>2011-08-18 11:20:58 -0700
committerJeff Brown <jeffbrown@google.com>2011-08-19 15:02:26 -0700
commit65fd251c3913fc921468a3dad190810db19eb9df (patch)
tree7cc9e086b96a4e2c77ec5b77aab6bed5679e89f0
parentc0a2222552f48a2543a64a4cbe913d0b9ffc3cbf (diff)
downloadframeworks_base-65fd251c3913fc921468a3dad190810db19eb9df.zip
frameworks_base-65fd251c3913fc921468a3dad190810db19eb9df.tar.gz
frameworks_base-65fd251c3913fc921468a3dad190810db19eb9df.tar.bz2
Input system bug fixes, particularly for stylus.
Bug: 5049148 Finished stylus support, including support for indirect stylus and mouse tools. Added TILT axis. When stylus tilt X/Y is available, it is transformed into an orientation and tilt inclination which is a more convenient representation and a simpler extension to the exiting API. Touch devices now only report touch data using a single input source. Previously touch devices in pointer mode would report both absolute touch pad data and cooked pointer gestures. Now we just pick one. The touch device switches modes as needed when the focused application enables/disables pointer gestures. This change greatly simplifies the code and reduces the load on the input dispatcher. Fixed an incorrect assumption that the value of ABS_(MT_)DISTANCE would be zero whenever the stylus was in direct contact. It appears that the correct way to determine whether the stylus is in direct contact (rather than hovering) is by checking for a non-zero reported pressure. Added code to read the initial state of tool buttons and axis values when the input devices are initialized or reset. This fixes problems where the input mapper state might have the wrong initial state. Moved responsibility for cancelling pending inputs (keys down, touches, etc.) to the InputDispatcher by sending it a device reset notification. This frees the InputReader from having to synthesize events during reset, which was cumbersome and somewhat brittle to begin with. Consolidated more of the common accumulator logic from SingleTouchInputMapper and MultiTouchInputMapper into TouchInputMapper. Improved the PointerLocation output. Change-Id: I595d3647f7fd7cb1e3eff8b3c76b85043b5fe2f0
-rw-r--r--api/current.txt1
-rw-r--r--core/java/android/view/MotionEvent.java28
-rw-r--r--core/java/com/android/internal/widget/PointerLocationView.java91
-rwxr-xr-xinclude/ui/KeycodeLabels.h2
-rw-r--r--native/include/android/input.h1
-rw-r--r--services/input/InputDispatcher.cpp59
-rw-r--r--services/input/InputDispatcher.h18
-rw-r--r--services/input/InputListener.cpp19
-rw-r--r--services/input/InputListener.h20
-rw-r--r--services/input/InputReader.cpp1536
-rw-r--r--services/input/InputReader.h309
-rw-r--r--services/input/tests/InputReader_test.cpp509
-rw-r--r--services/jni/com_android_server_InputManager.cpp68
13 files changed, 1747 insertions, 914 deletions
diff --git a/api/current.txt b/api/current.txt
index 4332833..eb58ae4 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -22315,6 +22315,7 @@ package android.view {
field public static final int AXIS_RZ = 14; // 0xe
field public static final int AXIS_SIZE = 3; // 0x3
field public static final int AXIS_THROTTLE = 19; // 0x13
+ field public static final int AXIS_TILT = 25; // 0x19
field public static final int AXIS_TOOL_MAJOR = 6; // 0x6
field public static final int AXIS_TOOL_MINOR = 7; // 0x7
field public static final int AXIS_TOUCH_MAJOR = 4; // 0x4
diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java
index da5c7b2..8e0ab1a 100644
--- a/core/java/android/view/MotionEvent.java
+++ b/core/java/android/view/MotionEvent.java
@@ -619,6 +619,11 @@ public final class MotionEvent extends InputEvent implements Parcelable {
* indicates that the major axis of contact is oriented to the left.
* The full range is from -PI/2 radians (finger pointing fully left) to PI/2 radians
* (finger pointing fully right).
+ * <li>For a stylus, the orientation indicates the direction in which the stylus
+ * is pointing in relation to the vertical axis of the current orientation of the screen.
+ * The range is from -PI radians to PI radians, where 0 is pointing up,
+ * -PI/2 radians is pointing left, -PI or PI radians is pointing down, and PI/2 radians
+ * is pointing right. See also {@link #AXIS_TILT}.
* </ul>
* </p>
*
@@ -883,8 +888,8 @@ public final class MotionEvent extends InputEvent implements Parcelable {
* <p>
* <ul>
* <li>For a stylus, reports the distance of the stylus from the screen.
- * The value is nominally measured in millimeters where 0.0 indicates direct contact
- * and larger values indicate increasing distance from the surface.
+ * A value of 0.0 indicates direct contact and larger values indicate increasing
+ * distance from the surface.
* </ul>
* </p>
*
@@ -896,6 +901,24 @@ public final class MotionEvent extends InputEvent implements Parcelable {
public static final int AXIS_DISTANCE = 24;
/**
+ * Axis constant: Tilt axis of a motion event.
+ * <p>
+ * <ul>
+ * <li>For a stylus, reports the tilt angle of the stylus in radians where
+ * 0 radians indicates that the stylus is being held perpendicular to the
+ * surface, and PI/2 radians indicates that the stylus is being held flat
+ * against the surface.
+ * </ul>
+ * </p>
+ *
+ * @see #getAxisValue(int, int)
+ * @see #getHistoricalAxisValue(int, int, int)
+ * @see MotionEvent.PointerCoords#getAxisValue(int, int)
+ * @see InputDevice#getMotionRange
+ */
+ public static final int AXIS_TILT = 25;
+
+ /**
* Axis constant: Generic 1 axis of a motion event.
* The interpretation of a generic axis is device-specific.
*
@@ -1104,6 +1127,7 @@ public final class MotionEvent extends InputEvent implements Parcelable {
names.append(AXIS_GAS, "AXIS_GAS");
names.append(AXIS_BRAKE, "AXIS_BRAKE");
names.append(AXIS_DISTANCE, "AXIS_DISTANCE");
+ names.append(AXIS_TILT, "AXIS_TILT");
names.append(AXIS_GENERIC_1, "AXIS_GENERIC_1");
names.append(AXIS_GENERIC_2, "AXIS_GENERIC_2");
names.append(AXIS_GENERIC_3, "AXIS_GENERIC_3");
diff --git a/core/java/com/android/internal/widget/PointerLocationView.java b/core/java/com/android/internal/widget/PointerLocationView.java
index bf1c637..158291b 100644
--- a/core/java/com/android/internal/widget/PointerLocationView.java
+++ b/core/java/com/android/internal/widget/PointerLocationView.java
@@ -46,6 +46,7 @@ public class PointerLocationView extends View {
// Most recent coordinates.
private PointerCoords mCoords = new PointerCoords();
+ private int mToolType;
// Most recent velocity.
private float mXVelocity;
@@ -88,7 +89,7 @@ public class PointerLocationView extends View {
private int mMaxNumPointers;
private int mActivePointerId;
private final ArrayList<PointerState> mPointers = new ArrayList<PointerState>();
- private final PointerCoords mHoverCoords = new PointerCoords();
+ private final PointerCoords mTempCoords = new PointerCoords();
private final VelocityTracker mVelocity;
@@ -306,22 +307,66 @@ public class PointerLocationView extends View {
ps.mCoords.toolMinor, ps.mCoords.orientation, mPaint);
// Draw the orientation arrow.
+ float arrowSize = ps.mCoords.toolMajor * 0.7f;
+ if (arrowSize < 20) {
+ arrowSize = 20;
+ }
mPaint.setARGB(255, pressureLevel, 255, 0);
- float orientationVectorX = (float) (Math.sin(-ps.mCoords.orientation)
- * ps.mCoords.toolMajor * 0.7);
- float orientationVectorY = (float) (Math.cos(-ps.mCoords.orientation)
- * ps.mCoords.toolMajor * 0.7);
- canvas.drawLine(
- ps.mCoords.x - orientationVectorX, ps.mCoords.y - orientationVectorY,
- ps.mCoords.x + orientationVectorX, ps.mCoords.y + orientationVectorY,
- mPaint);
+ float orientationVectorX = (float) (Math.sin(ps.mCoords.orientation)
+ * arrowSize);
+ float orientationVectorY = (float) (-Math.cos(ps.mCoords.orientation)
+ * arrowSize);
+ if (ps.mToolType == MotionEvent.TOOL_TYPE_STYLUS
+ || ps.mToolType == MotionEvent.TOOL_TYPE_ERASER) {
+ // Show full circle orientation.
+ canvas.drawLine(ps.mCoords.x, ps.mCoords.y,
+ ps.mCoords.x + orientationVectorX,
+ ps.mCoords.y + orientationVectorY,
+ mPaint);
+ } else {
+ // Show half circle orientation.
+ canvas.drawLine(
+ ps.mCoords.x - orientationVectorX,
+ ps.mCoords.y - orientationVectorY,
+ ps.mCoords.x + orientationVectorX,
+ ps.mCoords.y + orientationVectorY,
+ mPaint);
+ }
+
+ // Draw the tilt point along the orientation arrow.
+ float tiltScale = (float) Math.sin(
+ ps.mCoords.getAxisValue(MotionEvent.AXIS_TILT));
+ canvas.drawCircle(
+ ps.mCoords.x + orientationVectorX * tiltScale,
+ ps.mCoords.y + orientationVectorY * tiltScale,
+ 3.0f, mPaint);
}
}
}
}
-
- private void logPointerCoords(int action, int index, MotionEvent.PointerCoords coords, int id,
- int toolType, int buttonState) {
+
+ private void logMotionEvent(String type, MotionEvent event) {
+ final int action = event.getAction();
+ final int N = event.getHistorySize();
+ final int NI = event.getPointerCount();
+ for (int historyPos = 0; historyPos < N; historyPos++) {
+ for (int i = 0; i < NI; i++) {
+ final int id = event.getPointerId(i);
+ event.getHistoricalPointerCoords(i, historyPos, mTempCoords);
+ logCoords(type, action, i, mTempCoords, id,
+ event.getToolType(i), event.getButtonState());
+ }
+ }
+ for (int i = 0; i < NI; i++) {
+ final int id = event.getPointerId(i);
+ event.getPointerCoords(i, mTempCoords);
+ logCoords(type, action, i, mTempCoords, id,
+ event.getToolType(i), event.getButtonState());
+ }
+ }
+
+ private void logCoords(String type, int action, int index,
+ MotionEvent.PointerCoords coords, int id, int toolType, int buttonState) {
final String prefix;
switch (action & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
@@ -373,7 +418,7 @@ public class PointerLocationView extends View {
}
Log.i(TAG, mText.clear()
- .append("Pointer ").append(id + 1)
+ .append(type).append(" id ").append(id + 1)
.append(": ")
.append(prefix)
.append(" (").append(coords.x, 3).append(", ").append(coords.y, 3)
@@ -385,6 +430,9 @@ public class PointerLocationView extends View {
.append(" ToolMinor=").append(coords.toolMinor, 3)
.append(" Orientation=").append((float)(coords.orientation * 180 / Math.PI), 1)
.append("deg")
+ .append(" Tilt=").append((float)(
+ coords.getAxisValue(MotionEvent.AXIS_TILT) * 180 / Math.PI), 1)
+ .append("deg")
.append(" Distance=").append(coords.getAxisValue(MotionEvent.AXIS_DISTANCE), 1)
.append(" VScroll=").append(coords.getAxisValue(MotionEvent.AXIS_VSCROLL), 1)
.append(" HScroll=").append(coords.getAxisValue(MotionEvent.AXIS_HSCROLL), 1)
@@ -445,10 +493,10 @@ public class PointerLocationView extends View {
for (int i = 0; i < NI; i++) {
final int id = event.getPointerId(i);
final PointerState ps = mCurDown ? mPointers.get(id) : null;
- final PointerCoords coords = ps != null ? ps.mCoords : mHoverCoords;
+ final PointerCoords coords = ps != null ? ps.mCoords : mTempCoords;
event.getHistoricalPointerCoords(i, historyPos, coords);
if (mPrintCoords) {
- logPointerCoords(action, i, coords, id,
+ logCoords("Pointer", action, i, coords, id,
event.getToolType(i), event.getButtonState());
}
if (ps != null) {
@@ -459,16 +507,17 @@ public class PointerLocationView extends View {
for (int i = 0; i < NI; i++) {
final int id = event.getPointerId(i);
final PointerState ps = mCurDown ? mPointers.get(id) : null;
- final PointerCoords coords = ps != null ? ps.mCoords : mHoverCoords;
+ final PointerCoords coords = ps != null ? ps.mCoords : mTempCoords;
event.getPointerCoords(i, coords);
if (mPrintCoords) {
- logPointerCoords(action, i, coords, id,
+ logCoords("Pointer", action, i, coords, id,
event.getToolType(i), event.getButtonState());
}
if (ps != null) {
ps.addTrace(coords.x, coords.y);
ps.mXVelocity = mVelocity.getXVelocity(id);
ps.mYVelocity = mVelocity.getYVelocity(id);
+ ps.mToolType = event.getToolType(i);
}
}
@@ -515,11 +564,11 @@ public class PointerLocationView extends View {
if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
addPointerEvent(event);
} else if ((source & InputDevice.SOURCE_CLASS_JOYSTICK) != 0) {
- Log.i(TAG, "Joystick: " + event);
+ logMotionEvent("Joystick", event);
} else if ((source & InputDevice.SOURCE_CLASS_POSITION) != 0) {
- Log.i(TAG, "Position: " + event);
+ logMotionEvent("Position", event);
} else {
- Log.i(TAG, "Generic: " + event);
+ logMotionEvent("Generic", event);
}
return true;
}
@@ -563,7 +612,7 @@ public class PointerLocationView extends View {
@Override
public boolean onTrackballEvent(MotionEvent event) {
- Log.i(TAG, "Trackball: " + event);
+ logMotionEvent("Trackball", event);
return true;
}
diff --git a/include/ui/KeycodeLabels.h b/include/ui/KeycodeLabels.h
index 8383957..2efe8ca 100755
--- a/include/ui/KeycodeLabels.h
+++ b/include/ui/KeycodeLabels.h
@@ -278,6 +278,8 @@ static const KeycodeLabel AXES[] = {
{ "WHEEL", 21 },
{ "GAS", 22 },
{ "BRAKE", 23 },
+ { "DISTANCE", 24 },
+ { "TILT", 25 },
{ "GENERIC_1", 32 },
{ "GENERIC_2", 33 },
{ "GENERIC_3", 34 },
diff --git a/native/include/android/input.h b/native/include/android/input.h
index 7a0dcd3..f2befa9 100644
--- a/native/include/android/input.h
+++ b/native/include/android/input.h
@@ -373,6 +373,7 @@ enum {
AMOTION_EVENT_AXIS_GAS = 22,
AMOTION_EVENT_AXIS_BRAKE = 23,
AMOTION_EVENT_AXIS_DISTANCE = 24,
+ AMOTION_EVENT_AXIS_TILT = 25,
AMOTION_EVENT_AXIS_GENERIC_1 = 32,
AMOTION_EVENT_AXIS_GENERIC_2 = 33,
AMOTION_EVENT_AXIS_GENERIC_3 = 34,
diff --git a/services/input/InputDispatcher.cpp b/services/input/InputDispatcher.cpp
index 3cd3ac3..f6ce44c 100644
--- a/services/input/InputDispatcher.cpp
+++ b/services/input/InputDispatcher.cpp
@@ -401,6 +401,14 @@ void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) {
break;
}
+ case EventEntry::TYPE_DEVICE_RESET: {
+ DeviceResetEntry* typedEntry =
+ static_cast<DeviceResetEntry*>(mPendingEvent);
+ done = dispatchDeviceResetLocked(currentTime, typedEntry);
+ dropReason = DROP_REASON_NOT_DROPPED; // device resets are never dropped
+ break;
+ }
+
case EventEntry::TYPE_KEY: {
KeyEntry* typedEntry = static_cast<KeyEntry*>(mPendingEvent);
if (isAppSwitchDue) {
@@ -727,6 +735,19 @@ bool InputDispatcher::dispatchConfigurationChangedLocked(
return true;
}
+bool InputDispatcher::dispatchDeviceResetLocked(
+ nsecs_t currentTime, DeviceResetEntry* entry) {
+#if DEBUG_OUTBOUND_EVENT_DETAILS
+ LOGD("dispatchDeviceReset - eventTime=%lld, deviceId=%d", entry->eventTime, entry->deviceId);
+#endif
+
+ CancelationOptions options(CancelationOptions::CANCEL_ALL_EVENTS,
+ "device was reset");
+ options.deviceId = entry->deviceId;
+ synthesizeCancelationEventsForAllConnectionsLocked(options);
+ return true;
+}
+
bool InputDispatcher::dispatchKeyLocked(nsecs_t currentTime, KeyEntry* entry,
DropReason* dropReason, nsecs_t* nextWakeupTime) {
// Preprocessing.
@@ -2921,6 +2942,25 @@ void InputDispatcher::notifySwitch(const NotifySwitchArgs* args) {
args->switchCode, args->switchValue, policyFlags);
}
+void InputDispatcher::notifyDeviceReset(const NotifyDeviceResetArgs* args) {
+#if DEBUG_INBOUND_EVENT_DETAILS
+ LOGD("notifyDeviceReset - eventTime=%lld, deviceId=%d",
+ args->eventTime, args->deviceId);
+#endif
+
+ bool needWake;
+ { // acquire lock
+ AutoMutex _l(mLock);
+
+ DeviceResetEntry* newEntry = new DeviceResetEntry(args->eventTime, args->deviceId);
+ needWake = enqueueInboundEventLocked(newEntry);
+ } // release lock
+
+ if (needWake) {
+ mLooper->wake();
+ }
+}
+
int32_t InputDispatcher::injectInputEvent(const InputEvent* event,
int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis,
uint32_t policyFlags) {
@@ -4016,6 +4056,17 @@ InputDispatcher::ConfigurationChangedEntry::~ConfigurationChangedEntry() {
}
+// --- InputDispatcher::DeviceResetEntry ---
+
+InputDispatcher::DeviceResetEntry::DeviceResetEntry(nsecs_t eventTime, int32_t deviceId) :
+ EventEntry(TYPE_DEVICE_RESET, eventTime, 0),
+ deviceId(deviceId) {
+}
+
+InputDispatcher::DeviceResetEntry::~DeviceResetEntry() {
+}
+
+
// --- InputDispatcher::KeyEntry ---
InputDispatcher::KeyEntry::KeyEntry(nsecs_t eventTime,
@@ -4407,6 +4458,10 @@ bool InputDispatcher::InputState::shouldCancelKey(const KeyMemento& memento,
return false;
}
+ if (options.deviceId != -1 && memento.deviceId != options.deviceId) {
+ return false;
+ }
+
switch (options.mode) {
case CancelationOptions::CANCEL_ALL_EVENTS:
case CancelationOptions::CANCEL_NON_POINTER_EVENTS:
@@ -4420,6 +4475,10 @@ bool InputDispatcher::InputState::shouldCancelKey(const KeyMemento& memento,
bool InputDispatcher::InputState::shouldCancelMotion(const MotionMemento& memento,
const CancelationOptions& options) {
+ if (options.deviceId != -1 && memento.deviceId != options.deviceId) {
+ return false;
+ }
+
switch (options.mode) {
case CancelationOptions::CANCEL_ALL_EVENTS:
return true;
diff --git a/services/input/InputDispatcher.h b/services/input/InputDispatcher.h
index cae1610..3c83691 100644
--- a/services/input/InputDispatcher.h
+++ b/services/input/InputDispatcher.h
@@ -381,6 +381,7 @@ public:
virtual void notifyKey(const NotifyKeyArgs* args);
virtual void notifyMotion(const NotifyMotionArgs* args);
virtual void notifySwitch(const NotifySwitchArgs* args);
+ virtual void notifyDeviceReset(const NotifyDeviceResetArgs* args);
virtual int32_t injectInputEvent(const InputEvent* event,
int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis,
@@ -424,6 +425,7 @@ private:
struct EventEntry : Link<EventEntry> {
enum {
TYPE_CONFIGURATION_CHANGED,
+ TYPE_DEVICE_RESET,
TYPE_KEY,
TYPE_MOTION
};
@@ -453,6 +455,15 @@ private:
virtual ~ConfigurationChangedEntry();
};
+ struct DeviceResetEntry : EventEntry {
+ int32_t deviceId;
+
+ DeviceResetEntry(nsecs_t eventTime, int32_t deviceId);
+
+ protected:
+ virtual ~DeviceResetEntry();
+ };
+
struct KeyEntry : EventEntry {
int32_t deviceId;
uint32_t source;
@@ -688,8 +699,11 @@ private:
// The specific keycode of the key event to cancel, or -1 to cancel any key event.
int32_t keyCode;
+ // The specific device id of events to cancel, or -1 to cancel events from any device.
+ int32_t deviceId;
+
CancelationOptions(Mode mode, const char* reason) :
- mode(mode), reason(reason), keyCode(-1) { }
+ mode(mode), reason(reason), keyCode(-1), deviceId(-1) { }
};
/* Tracks dispatched key and motion event state so that cancelation events can be
@@ -982,6 +996,8 @@ private:
// Dispatch inbound events.
bool dispatchConfigurationChangedLocked(
nsecs_t currentTime, ConfigurationChangedEntry* entry);
+ bool dispatchDeviceResetLocked(
+ nsecs_t currentTime, DeviceResetEntry* entry);
bool dispatchKeyLocked(
nsecs_t currentTime, KeyEntry* entry,
DropReason* dropReason, nsecs_t* nextWakeupTime);
diff --git a/services/input/InputListener.cpp b/services/input/InputListener.cpp
index 4f9fe90..657a6b9 100644
--- a/services/input/InputListener.cpp
+++ b/services/input/InputListener.cpp
@@ -118,6 +118,21 @@ void NotifySwitchArgs::notify(const sp<InputListenerInterface>& listener) const
}
+// --- NotifyDeviceResetArgs ---
+
+NotifyDeviceResetArgs::NotifyDeviceResetArgs(nsecs_t eventTime, int32_t deviceId) :
+ eventTime(eventTime), deviceId(deviceId) {
+}
+
+NotifyDeviceResetArgs::NotifyDeviceResetArgs(const NotifyDeviceResetArgs& other) :
+ eventTime(other.eventTime), deviceId(other.deviceId) {
+}
+
+void NotifyDeviceResetArgs::notify(const sp<InputListenerInterface>& listener) const {
+ listener->notifyDeviceReset(this);
+}
+
+
// --- QueuedInputListener ---
QueuedInputListener::QueuedInputListener(const sp<InputListenerInterface>& innerListener) :
@@ -148,6 +163,10 @@ void QueuedInputListener::notifySwitch(const NotifySwitchArgs* args) {
mArgsQueue.push(new NotifySwitchArgs(*args));
}
+void QueuedInputListener::notifyDeviceReset(const NotifyDeviceResetArgs* args) {
+ mArgsQueue.push(new NotifyDeviceResetArgs(*args));
+}
+
void QueuedInputListener::flush() {
size_t count = mArgsQueue.size();
for (size_t i = 0; i < count; i++) {
diff --git a/services/input/InputListener.h b/services/input/InputListener.h
index 3fef132..f920cd1 100644
--- a/services/input/InputListener.h
+++ b/services/input/InputListener.h
@@ -131,6 +131,24 @@ struct NotifySwitchArgs : public NotifyArgs {
};
+/* Describes a device reset event, such as when a device is added,
+ * reconfigured, or removed. */
+struct NotifyDeviceResetArgs : public NotifyArgs {
+ nsecs_t eventTime;
+ int32_t deviceId;
+
+ inline NotifyDeviceResetArgs() { }
+
+ NotifyDeviceResetArgs(nsecs_t eventTime, int32_t deviceId);
+
+ NotifyDeviceResetArgs(const NotifyDeviceResetArgs& other);
+
+ virtual ~NotifyDeviceResetArgs() { }
+
+ virtual void notify(const sp<InputListenerInterface>& listener) const;
+};
+
+
/*
* The interface used by the InputReader to notify the InputListener about input events.
*/
@@ -144,6 +162,7 @@ public:
virtual void notifyKey(const NotifyKeyArgs* args) = 0;
virtual void notifyMotion(const NotifyMotionArgs* args) = 0;
virtual void notifySwitch(const NotifySwitchArgs* args) = 0;
+ virtual void notifyDeviceReset(const NotifyDeviceResetArgs* args) = 0;
};
@@ -162,6 +181,7 @@ public:
virtual void notifyKey(const NotifyKeyArgs* args);
virtual void notifyMotion(const NotifyMotionArgs* args);
virtual void notifySwitch(const NotifySwitchArgs* args);
+ virtual void notifyDeviceReset(const NotifyDeviceResetArgs* args);
void flush();
diff --git a/services/input/InputReader.cpp b/services/input/InputReader.cpp
index 2035a4b..88378ef 100644
--- a/services/input/InputReader.cpp
+++ b/services/input/InputReader.cpp
@@ -198,6 +198,39 @@ static void synthesizeButtonKeys(InputReaderContext* context, int32_t action,
}
+// --- InputReaderConfiguration ---
+
+bool InputReaderConfiguration::getDisplayInfo(int32_t displayId, bool external,
+ int32_t* width, int32_t* height, int32_t* orientation) const {
+ if (displayId == 0) {
+ const DisplayInfo& info = external ? mExternalDisplay : mInternalDisplay;
+ if (info.width > 0 && info.height > 0) {
+ if (width) {
+ *width = info.width;
+ }
+ if (height) {
+ *height = info.height;
+ }
+ if (orientation) {
+ *orientation = info.orientation;
+ }
+ return true;
+ }
+ }
+ return false;
+}
+
+void InputReaderConfiguration::setDisplayInfo(int32_t displayId, bool external,
+ int32_t width, int32_t height, int32_t orientation) {
+ if (displayId == 0) {
+ DisplayInfo& info = external ? mExternalDisplay : mInternalDisplay;
+ info.width = width;
+ info.height = height;
+ info.orientation = orientation;
+ }
+}
+
+
// --- InputReader ---
InputReader::InputReader(const sp<EventHubInterface>& eventHub,
@@ -289,10 +322,10 @@ void InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count) {
} else {
switch (rawEvent->type) {
case EventHubInterface::DEVICE_ADDED:
- addDeviceLocked(rawEvent->deviceId);
+ addDeviceLocked(rawEvent->when, rawEvent->deviceId);
break;
case EventHubInterface::DEVICE_REMOVED:
- removeDeviceLocked(rawEvent->deviceId);
+ removeDeviceLocked(rawEvent->when, rawEvent->deviceId);
break;
case EventHubInterface::FINISHED_DEVICE_SCAN:
handleConfigurationChangedLocked(rawEvent->when);
@@ -307,12 +340,13 @@ void InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count) {
}
}
-void InputReader::addDeviceLocked(int32_t deviceId) {
+void InputReader::addDeviceLocked(nsecs_t when, int32_t deviceId) {
String8 name = mEventHub->getDeviceName(deviceId);
uint32_t classes = mEventHub->getDeviceClasses(deviceId);
InputDevice* device = createDeviceLocked(deviceId, name, classes);
- device->configure(&mConfig, 0);
+ device->configure(when, &mConfig, 0);
+ device->reset(when);
if (device->isIgnored()) {
LOGI("Device added: id=%d, name='%s' (ignored non-input device)", deviceId, name.string());
@@ -331,7 +365,7 @@ void InputReader::addDeviceLocked(int32_t deviceId) {
}
}
-void InputReader::removeDeviceLocked(int32_t deviceId) {
+void InputReader::removeDeviceLocked(nsecs_t when, int32_t deviceId) {
InputDevice* device = NULL;
ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
if (deviceIndex >= 0) {
@@ -350,8 +384,7 @@ void InputReader::removeDeviceLocked(int32_t deviceId) {
device->getId(), device->getName().string(), device->getSources());
}
- device->reset();
-
+ device->reset(when);
delete device;
}
@@ -453,13 +486,14 @@ void InputReader::refreshConfigurationLocked(uint32_t changes) {
if (changes) {
LOGI("Reconfiguring input devices. changes=0x%08x", changes);
+ nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
if (changes & InputReaderConfiguration::CHANGE_MUST_REOPEN) {
mEventHub->requestReopenDevices();
} else {
for (size_t i = 0; i < mDevices.size(); i++) {
InputDevice* device = mDevices.valueAt(i);
- device->configure(&mConfig, changes);
+ device->configure(now, &mConfig, changes);
}
}
}
@@ -861,7 +895,7 @@ void InputDevice::addMapper(InputMapper* mapper) {
mMappers.add(mapper);
}
-void InputDevice::configure(const InputReaderConfiguration* config, uint32_t changes) {
+void InputDevice::configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes) {
mSources = 0;
if (!isIgnored()) {
@@ -872,18 +906,22 @@ void InputDevice::configure(const InputReaderConfiguration* config, uint32_t cha
size_t numMappers = mMappers.size();
for (size_t i = 0; i < numMappers; i++) {
InputMapper* mapper = mMappers[i];
- mapper->configure(config, changes);
+ mapper->configure(when, config, changes);
mSources |= mapper->getSources();
}
}
}
-void InputDevice::reset() {
+void InputDevice::reset(nsecs_t when) {
size_t numMappers = mMappers.size();
for (size_t i = 0; i < numMappers; i++) {
InputMapper* mapper = mMappers[i];
- mapper->reset();
+ mapper->reset(when);
}
+
+ mContext->updateGlobalMetaState();
+
+ notifyReset(when);
}
void InputDevice::process(const RawEvent* rawEvents, size_t count) {
@@ -915,7 +953,7 @@ void InputDevice::process(const RawEvent* rawEvents, size_t count) {
} else if (rawEvent->type == EV_SYN && rawEvent->scanCode == SYN_DROPPED) {
LOGI("Detected input event buffer overrun for device %s.", mName.string());
mDropUntilNextSync = true;
- reset();
+ reset(rawEvent->when);
} else {
for (size_t i = 0; i < numMappers; i++) {
InputMapper* mapper = mMappers[i];
@@ -1001,6 +1039,11 @@ void InputDevice::fadePointer() {
}
}
+void InputDevice::notifyReset(nsecs_t when) {
+ NotifyDeviceResetArgs args(when, mId);
+ mContext->getListener()->notifyDeviceReset(&args);
+}
+
// --- CursorButtonAccumulator ---
@@ -1008,6 +1051,17 @@ CursorButtonAccumulator::CursorButtonAccumulator() {
clearButtons();
}
+void CursorButtonAccumulator::reset(InputDevice* device) {
+ mBtnLeft = device->isKeyPressed(BTN_LEFT);
+ mBtnRight = device->isKeyPressed(BTN_RIGHT);
+ mBtnMiddle = device->isKeyPressed(BTN_MIDDLE);
+ mBtnBack = device->isKeyPressed(BTN_BACK);
+ mBtnSide = device->isKeyPressed(BTN_SIDE);
+ mBtnForward = device->isKeyPressed(BTN_FORWARD);
+ mBtnExtra = device->isKeyPressed(BTN_EXTRA);
+ mBtnTask = device->isKeyPressed(BTN_TASK);
+}
+
void CursorButtonAccumulator::clearButtons() {
mBtnLeft = 0;
mBtnRight = 0;
@@ -1073,21 +1127,17 @@ uint32_t CursorButtonAccumulator::getButtonState() const {
// --- CursorMotionAccumulator ---
-CursorMotionAccumulator::CursorMotionAccumulator() :
- mHaveRelWheel(false), mHaveRelHWheel(false) {
+CursorMotionAccumulator::CursorMotionAccumulator() {
clearRelativeAxes();
}
-void CursorMotionAccumulator::configure(InputDevice* device) {
- mHaveRelWheel = device->getEventHub()->hasRelativeAxis(device->getId(), REL_WHEEL);
- mHaveRelHWheel = device->getEventHub()->hasRelativeAxis(device->getId(), REL_HWHEEL);
+void CursorMotionAccumulator::reset(InputDevice* device) {
+ clearRelativeAxes();
}
void CursorMotionAccumulator::clearRelativeAxes() {
mRelX = 0;
mRelY = 0;
- mRelWheel = 0;
- mRelHWheel = 0;
}
void CursorMotionAccumulator::process(const RawEvent* rawEvent) {
@@ -1099,6 +1149,39 @@ void CursorMotionAccumulator::process(const RawEvent* rawEvent) {
case REL_Y:
mRelY = rawEvent->value;
break;
+ }
+ }
+}
+
+void CursorMotionAccumulator::finishSync() {
+ clearRelativeAxes();
+}
+
+
+// --- CursorScrollAccumulator ---
+
+CursorScrollAccumulator::CursorScrollAccumulator() :
+ mHaveRelWheel(false), mHaveRelHWheel(false) {
+ clearRelativeAxes();
+}
+
+void CursorScrollAccumulator::configure(InputDevice* device) {
+ mHaveRelWheel = device->getEventHub()->hasRelativeAxis(device->getId(), REL_WHEEL);
+ mHaveRelHWheel = device->getEventHub()->hasRelativeAxis(device->getId(), REL_HWHEEL);
+}
+
+void CursorScrollAccumulator::reset(InputDevice* device) {
+ clearRelativeAxes();
+}
+
+void CursorScrollAccumulator::clearRelativeAxes() {
+ mRelWheel = 0;
+ mRelHWheel = 0;
+}
+
+void CursorScrollAccumulator::process(const RawEvent* rawEvent) {
+ if (rawEvent->type == EV_REL) {
+ switch (rawEvent->scanCode) {
case REL_WHEEL:
mRelWheel = rawEvent->value;
break;
@@ -1109,6 +1192,10 @@ void CursorMotionAccumulator::process(const RawEvent* rawEvent) {
}
}
+void CursorScrollAccumulator::finishSync() {
+ clearRelativeAxes();
+}
+
// --- TouchButtonAccumulator ---
@@ -1118,7 +1205,21 @@ TouchButtonAccumulator::TouchButtonAccumulator() :
}
void TouchButtonAccumulator::configure(InputDevice* device) {
- mHaveBtnTouch = device->getEventHub()->hasScanCode(device->getId(), BTN_TOUCH);
+ mHaveBtnTouch = device->hasKey(BTN_TOUCH);
+}
+
+void TouchButtonAccumulator::reset(InputDevice* device) {
+ mBtnTouch = device->isKeyPressed(BTN_TOUCH);
+ mBtnStylus = device->isKeyPressed(BTN_STYLUS);
+ mBtnStylus2 = device->isKeyPressed(BTN_STYLUS);
+ mBtnToolFinger = device->isKeyPressed(BTN_TOOL_FINGER);
+ mBtnToolPen = device->isKeyPressed(BTN_TOOL_PEN);
+ mBtnToolRubber = device->isKeyPressed(BTN_TOOL_RUBBER);
+ mBtnToolBrush = device->isKeyPressed(BTN_TOOL_BRUSH);
+ mBtnToolPencil = device->isKeyPressed(BTN_TOOL_PENCIL);
+ mBtnToolAirbrush = device->isKeyPressed(BTN_TOOL_AIRBRUSH);
+ mBtnToolMouse = device->isKeyPressed(BTN_TOOL_MOUSE);
+ mBtnToolLens = device->isKeyPressed(BTN_TOOL_LENS);
}
void TouchButtonAccumulator::clearButtons() {
@@ -1128,6 +1229,11 @@ void TouchButtonAccumulator::clearButtons() {
mBtnToolFinger = 0;
mBtnToolPen = 0;
mBtnToolRubber = 0;
+ mBtnToolBrush = 0;
+ mBtnToolPencil = 0;
+ mBtnToolAirbrush = 0;
+ mBtnToolMouse = 0;
+ mBtnToolLens = 0;
}
void TouchButtonAccumulator::process(const RawEvent* rawEvent) {
@@ -1151,6 +1257,21 @@ void TouchButtonAccumulator::process(const RawEvent* rawEvent) {
case BTN_TOOL_RUBBER:
mBtnToolRubber = rawEvent->value;
break;
+ case BTN_TOOL_BRUSH:
+ mBtnToolBrush = rawEvent->value;
+ break;
+ case BTN_TOOL_PENCIL:
+ mBtnToolPencil = rawEvent->value;
+ break;
+ case BTN_TOOL_AIRBRUSH:
+ mBtnToolAirbrush = rawEvent->value;
+ break;
+ case BTN_TOOL_MOUSE:
+ mBtnToolMouse = rawEvent->value;
+ break;
+ case BTN_TOOL_LENS:
+ mBtnToolLens = rawEvent->value;
+ break;
}
}
}
@@ -1167,10 +1288,13 @@ uint32_t TouchButtonAccumulator::getButtonState() const {
}
int32_t TouchButtonAccumulator::getToolType() const {
+ if (mBtnToolMouse || mBtnToolLens) {
+ return AMOTION_EVENT_TOOL_TYPE_MOUSE;
+ }
if (mBtnToolRubber) {
return AMOTION_EVENT_TOOL_TYPE_ERASER;
}
- if (mBtnToolPen) {
+ if (mBtnToolPen || mBtnToolBrush || mBtnToolPencil || mBtnToolAirbrush) {
return AMOTION_EVENT_TOOL_TYPE_STYLUS;
}
if (mBtnToolFinger) {
@@ -1180,7 +1304,9 @@ int32_t TouchButtonAccumulator::getToolType() const {
}
bool TouchButtonAccumulator::isToolActive() const {
- return mBtnTouch || mBtnToolFinger || mBtnToolPen || mBtnToolRubber;
+ return mBtnTouch || mBtnToolFinger || mBtnToolPen || mBtnToolRubber
+ || mBtnToolBrush || mBtnToolPencil || mBtnToolAirbrush
+ || mBtnToolMouse || mBtnToolLens;
}
bool TouchButtonAccumulator::isHovering() const {
@@ -1204,6 +1330,8 @@ void RawPointerAxes::clear() {
toolMinor.clear();
orientation.clear();
distance.clear();
+ tiltX.clear();
+ tiltY.clear();
trackingId.clear();
slot.clear();
}
@@ -1284,12 +1412,24 @@ SingleTouchMotionAccumulator::SingleTouchMotionAccumulator() {
clearAbsoluteAxes();
}
+void SingleTouchMotionAccumulator::reset(InputDevice* device) {
+ mAbsX = device->getAbsoluteAxisValue(ABS_X);
+ mAbsY = device->getAbsoluteAxisValue(ABS_Y);
+ mAbsPressure = device->getAbsoluteAxisValue(ABS_PRESSURE);
+ mAbsToolWidth = device->getAbsoluteAxisValue(ABS_TOOL_WIDTH);
+ mAbsDistance = device->getAbsoluteAxisValue(ABS_DISTANCE);
+ mAbsTiltX = device->getAbsoluteAxisValue(ABS_TILT_X);
+ mAbsTiltY = device->getAbsoluteAxisValue(ABS_TILT_Y);
+}
+
void SingleTouchMotionAccumulator::clearAbsoluteAxes() {
mAbsX = 0;
mAbsY = 0;
mAbsPressure = 0;
mAbsToolWidth = 0;
mAbsDistance = 0;
+ mAbsTiltX = 0;
+ mAbsTiltY = 0;
}
void SingleTouchMotionAccumulator::process(const RawEvent* rawEvent) {
@@ -1310,6 +1450,12 @@ void SingleTouchMotionAccumulator::process(const RawEvent* rawEvent) {
case ABS_DISTANCE:
mAbsDistance = rawEvent->value;
break;
+ case ABS_TILT_X:
+ mAbsTiltX = rawEvent->value;
+ break;
+ case ABS_TILT_Y:
+ mAbsTiltY = rawEvent->value;
+ break;
}
}
}
@@ -1333,9 +1479,37 @@ void MultiTouchMotionAccumulator::configure(size_t slotCount, bool usingSlotsPro
mSlots = new Slot[slotCount];
}
+void MultiTouchMotionAccumulator::reset(InputDevice* device) {
+ // Unfortunately there is no way to read the initial contents of the slots.
+ // So when we reset the accumulator, we must assume they are all zeroes.
+ if (mUsingSlotsProtocol) {
+ // Query the driver for the current slot index and use it as the initial slot
+ // before we start reading events from the device. It is possible that the
+ // current slot index will not be the same as it was when the first event was
+ // written into the evdev buffer, which means the input mapper could start
+ // out of sync with the initial state of the events in the evdev buffer.
+ // In the extremely unlikely case that this happens, the data from
+ // two slots will be confused until the next ABS_MT_SLOT event is received.
+ // This can cause the touch point to "jump", but at least there will be
+ // no stuck touches.
+ int32_t initialSlot;
+ status_t status = device->getEventHub()->getAbsoluteAxisValue(device->getId(),
+ ABS_MT_SLOT, &initialSlot);
+ if (status) {
+ LOGD("Could not retrieve current multitouch slot index. status=%d", status);
+ initialSlot = -1;
+ }
+ clearSlots(initialSlot);
+ } else {
+ clearSlots(-1);
+ }
+}
+
void MultiTouchMotionAccumulator::clearSlots(int32_t initialSlot) {
- for (size_t i = 0; i < mSlotCount; i++) {
- mSlots[i].clear();
+ if (mSlots) {
+ for (size_t i = 0; i < mSlotCount; i++) {
+ mSlots[i].clear();
+ }
}
mCurrentSlot = initialSlot;
}
@@ -1425,6 +1599,12 @@ void MultiTouchMotionAccumulator::process(const RawEvent* rawEvent) {
}
}
+void MultiTouchMotionAccumulator::finishSync() {
+ if (!mUsingSlotsProtocol) {
+ clearSlots(-1);
+ }
+}
+
// --- MultiTouchMotionAccumulator::Slot ---
@@ -1479,10 +1659,11 @@ void InputMapper::populateDeviceInfo(InputDeviceInfo* info) {
void InputMapper::dump(String8& dump) {
}
-void InputMapper::configure(const InputReaderConfiguration* config, uint32_t changes) {
+void InputMapper::configure(nsecs_t when,
+ const InputReaderConfiguration* config, uint32_t changes) {
}
-void InputMapper::reset() {
+void InputMapper::reset(nsecs_t when) {
}
void InputMapper::timeoutExpired(nsecs_t when) {
@@ -1564,17 +1745,11 @@ KeyboardInputMapper::KeyboardInputMapper(InputDevice* device,
uint32_t source, int32_t keyboardType) :
InputMapper(device), mSource(source),
mKeyboardType(keyboardType) {
- initialize();
}
KeyboardInputMapper::~KeyboardInputMapper() {
}
-void KeyboardInputMapper::initialize() {
- mMetaState = AMETA_NONE;
- mDownTime = 0;
-}
-
uint32_t KeyboardInputMapper::getSources() {
return mSource;
}
@@ -1589,21 +1764,31 @@ void KeyboardInputMapper::dump(String8& dump) {
dump.append(INDENT2 "Keyboard Input Mapper:\n");
dumpParameters(dump);
dump.appendFormat(INDENT3 "KeyboardType: %d\n", mKeyboardType);
+ dump.appendFormat(INDENT3 "Orientation: %d\n", mOrientation);
dump.appendFormat(INDENT3 "KeyDowns: %d keys currently down\n", mKeyDowns.size());
dump.appendFormat(INDENT3 "MetaState: 0x%0x\n", mMetaState);
dump.appendFormat(INDENT3 "DownTime: %lld\n", mDownTime);
}
-void KeyboardInputMapper::configure(const InputReaderConfiguration* config, uint32_t changes) {
- InputMapper::configure(config, changes);
+void KeyboardInputMapper::configure(nsecs_t when,
+ const InputReaderConfiguration* config, uint32_t changes) {
+ InputMapper::configure(when, config, changes);
if (!changes) { // first time only
// Configure basic parameters.
configureParameters();
+ }
- // Reset LEDs.
- resetLedState();
+ if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) {
+ if (mParameters.orientationAware && mParameters.associatedDisplayId >= 0) {
+ if (!config->getDisplayInfo(mParameters.associatedDisplayId,
+ false /*external*/, NULL, NULL, &mOrientation)) {
+ mOrientation = DISPLAY_ORIENTATION_0;
+ }
+ } else {
+ mOrientation = DISPLAY_ORIENTATION_0;
+ }
}
}
@@ -1626,19 +1811,14 @@ void KeyboardInputMapper::dumpParameters(String8& dump) {
toString(mParameters.orientationAware));
}
-void KeyboardInputMapper::reset() {
- // Synthesize key up event on reset if keys are currently down.
- while (!mKeyDowns.isEmpty()) {
- const KeyDown& keyDown = mKeyDowns.top();
- nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
- processKey(when, false, keyDown.keyCode, keyDown.scanCode, 0);
- }
+void KeyboardInputMapper::reset(nsecs_t when) {
+ mMetaState = AMETA_NONE;
+ mDownTime = 0;
+ mKeyDowns.clear();
- initialize();
resetLedState();
- InputMapper::reset();
- getContext()->updateGlobalMetaState();
+ InputMapper::reset(when);
}
void KeyboardInputMapper::process(const RawEvent* rawEvent) {
@@ -1666,15 +1846,8 @@ void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t keyCode,
if (down) {
// Rotate key codes according to orientation if needed.
- // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
if (mParameters.orientationAware && mParameters.associatedDisplayId >= 0) {
- int32_t orientation;
- if (!getPolicy()->getDisplayInfo(mParameters.associatedDisplayId,
- false /*external*/, NULL, NULL, & orientation)) {
- orientation = DISPLAY_ORIENTATION_0;
- }
-
- keyCode = rotateKeyCode(keyCode, orientation);
+ keyCode = rotateKeyCode(keyCode, mOrientation);
}
// Add key down.
@@ -1813,7 +1986,6 @@ void KeyboardInputMapper::updateLedStateForModifier(LedState& ledState,
CursorInputMapper::CursorInputMapper(InputDevice* device) :
InputMapper(device) {
- initialize();
}
CursorInputMapper::~CursorInputMapper() {
@@ -1838,10 +2010,10 @@ void CursorInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
}
info->addMotionRange(AMOTION_EVENT_AXIS_PRESSURE, mSource, 0.0f, 1.0f, 0.0f, 0.0f);
- if (mCursorMotionAccumulator.haveRelativeVWheel()) {
+ if (mCursorScrollAccumulator.haveRelativeVWheel()) {
info->addMotionRange(AMOTION_EVENT_AXIS_VSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f);
}
- if (mCursorMotionAccumulator.haveRelativeHWheel()) {
+ if (mCursorScrollAccumulator.haveRelativeHWheel()) {
info->addMotionRange(AMOTION_EVENT_AXIS_HSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f);
}
}
@@ -1854,21 +2026,23 @@ void CursorInputMapper::dump(String8& dump) {
dump.appendFormat(INDENT3 "XPrecision: %0.3f\n", mXPrecision);
dump.appendFormat(INDENT3 "YPrecision: %0.3f\n", mYPrecision);
dump.appendFormat(INDENT3 "HaveVWheel: %s\n",
- toString(mCursorMotionAccumulator.haveRelativeVWheel()));
+ toString(mCursorScrollAccumulator.haveRelativeVWheel()));
dump.appendFormat(INDENT3 "HaveHWheel: %s\n",
- toString(mCursorMotionAccumulator.haveRelativeHWheel()));
+ toString(mCursorScrollAccumulator.haveRelativeHWheel()));
dump.appendFormat(INDENT3 "VWheelScale: %0.3f\n", mVWheelScale);
dump.appendFormat(INDENT3 "HWheelScale: %0.3f\n", mHWheelScale);
+ dump.appendFormat(INDENT3 "Orientation: %d\n", mOrientation);
dump.appendFormat(INDENT3 "ButtonState: 0x%08x\n", mButtonState);
dump.appendFormat(INDENT3 "Down: %s\n", toString(isPointerDown(mButtonState)));
dump.appendFormat(INDENT3 "DownTime: %lld\n", mDownTime);
}
-void CursorInputMapper::configure(const InputReaderConfiguration* config, uint32_t changes) {
- InputMapper::configure(config, changes);
+void CursorInputMapper::configure(nsecs_t when,
+ const InputReaderConfiguration* config, uint32_t changes) {
+ InputMapper::configure(when, config, changes);
if (!changes) { // first time only
- mCursorMotionAccumulator.configure(getDevice());
+ mCursorScrollAccumulator.configure(getDevice());
// Configure basic parameters.
configureParameters();
@@ -1901,6 +2075,17 @@ void CursorInputMapper::configure(const InputReaderConfiguration* config, uint32
mWheelXVelocityControl.setParameters(config->wheelVelocityControlParameters);
mWheelYVelocityControl.setParameters(config->wheelVelocityControlParameters);
}
+
+ if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) {
+ if (mParameters.orientationAware && mParameters.associatedDisplayId >= 0) {
+ if (!config->getDisplayInfo(mParameters.associatedDisplayId,
+ false /*external*/, NULL, NULL, &mOrientation)) {
+ mOrientation = DISPLAY_ORIENTATION_0;
+ }
+ } else {
+ mOrientation = DISPLAY_ORIENTATION_0;
+ }
+ }
}
void CursorInputMapper::configureParameters() {
@@ -1944,34 +2129,25 @@ void CursorInputMapper::dumpParameters(String8& dump) {
toString(mParameters.orientationAware));
}
-void CursorInputMapper::initialize() {
- mCursorButtonAccumulator.clearButtons();
- mCursorMotionAccumulator.clearRelativeAxes();
-
+void CursorInputMapper::reset(nsecs_t when) {
mButtonState = 0;
mDownTime = 0;
-}
-void CursorInputMapper::reset() {
- // Reset velocity.
mPointerVelocityControl.reset();
mWheelXVelocityControl.reset();
mWheelYVelocityControl.reset();
- // Synthesize button up event on reset.
- nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
- mCursorButtonAccumulator.clearButtons();
- mCursorMotionAccumulator.clearRelativeAxes();
- sync(when);
-
- initialize();
+ mCursorButtonAccumulator.reset(getDevice());
+ mCursorMotionAccumulator.reset(getDevice());
+ mCursorScrollAccumulator.reset(getDevice());
- InputMapper::reset();
+ InputMapper::reset(when);
}
void CursorInputMapper::process(const RawEvent* rawEvent) {
mCursorButtonAccumulator.process(rawEvent);
mCursorMotionAccumulator.process(rawEvent);
+ mCursorScrollAccumulator.process(rawEvent);
if (rawEvent->type == EV_SYN && rawEvent->scanCode == SYN_REPORT) {
sync(rawEvent->when);
@@ -2001,19 +2177,13 @@ void CursorInputMapper::sync(nsecs_t when) {
float deltaY = mCursorMotionAccumulator.getRelativeY() * mYScale;
bool moved = deltaX != 0 || deltaY != 0;
+ // Rotate delta according to orientation if needed.
if (mParameters.orientationAware && mParameters.associatedDisplayId >= 0
&& (deltaX != 0.0f || deltaY != 0.0f)) {
- // Rotate motion based on display orientation if needed.
- // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
- int32_t orientation;
- if (! getPolicy()->getDisplayInfo(mParameters.associatedDisplayId,
- false /*external*/, NULL, NULL, & orientation)) {
- orientation = DISPLAY_ORIENTATION_0;
- }
-
- rotateDelta(orientation, &deltaX, &deltaY);
+ rotateDelta(mOrientation, &deltaX, &deltaY);
}
+ // Move the pointer.
PointerProperties pointerProperties;
pointerProperties.clear();
pointerProperties.id = 0;
@@ -2022,8 +2192,8 @@ void CursorInputMapper::sync(nsecs_t when) {
PointerCoords pointerCoords;
pointerCoords.clear();
- float vscroll = mCursorMotionAccumulator.getRelativeVWheel();
- float hscroll = mCursorMotionAccumulator.getRelativeHWheel();
+ float vscroll = mCursorScrollAccumulator.getRelativeVWheel();
+ float hscroll = mCursorScrollAccumulator.getRelativeHWheel();
bool scrolled = vscroll != 0 || hscroll != 0;
mWheelYVelocityControl.move(when, NULL, &vscroll);
@@ -2115,7 +2285,8 @@ void CursorInputMapper::sync(nsecs_t when) {
synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_UP, when, getDeviceId(), mSource,
policyFlags, lastButtonState, currentButtonState);
- mCursorMotionAccumulator.clearRelativeAxes();
+ mCursorMotionAccumulator.finishSync();
+ mCursorScrollAccumulator.finishSync();
}
int32_t CursorInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
@@ -2137,65 +2308,57 @@ void CursorInputMapper::fadePointer() {
TouchInputMapper::TouchInputMapper(InputDevice* device) :
InputMapper(device),
+ mSource(0), mDeviceMode(DEVICE_MODE_DISABLED),
mSurfaceOrientation(-1), mSurfaceWidth(-1), mSurfaceHeight(-1) {
- initialize();
}
TouchInputMapper::~TouchInputMapper() {
}
uint32_t TouchInputMapper::getSources() {
- return mTouchSource | mPointerSource;
+ return mSource;
}
void TouchInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
InputMapper::populateDeviceInfo(info);
- // Ensure surface information is up to date so that orientation changes are
- // noticed immediately.
- if (!configureSurface()) {
- return;
- }
-
- info->addMotionRange(mOrientedRanges.x);
- info->addMotionRange(mOrientedRanges.y);
-
- if (mOrientedRanges.havePressure) {
+ if (mDeviceMode != DEVICE_MODE_DISABLED) {
+ info->addMotionRange(mOrientedRanges.x);
+ info->addMotionRange(mOrientedRanges.y);
info->addMotionRange(mOrientedRanges.pressure);
- }
- if (mOrientedRanges.haveSize) {
- info->addMotionRange(mOrientedRanges.size);
- }
+ if (mOrientedRanges.haveSize) {
+ info->addMotionRange(mOrientedRanges.size);
+ }
- if (mOrientedRanges.haveTouchSize) {
- info->addMotionRange(mOrientedRanges.touchMajor);
- info->addMotionRange(mOrientedRanges.touchMinor);
- }
+ if (mOrientedRanges.haveTouchSize) {
+ info->addMotionRange(mOrientedRanges.touchMajor);
+ info->addMotionRange(mOrientedRanges.touchMinor);
+ }
- if (mOrientedRanges.haveToolSize) {
- info->addMotionRange(mOrientedRanges.toolMajor);
- info->addMotionRange(mOrientedRanges.toolMinor);
- }
+ if (mOrientedRanges.haveToolSize) {
+ info->addMotionRange(mOrientedRanges.toolMajor);
+ info->addMotionRange(mOrientedRanges.toolMinor);
+ }
- if (mOrientedRanges.haveOrientation) {
- info->addMotionRange(mOrientedRanges.orientation);
- }
+ if (mOrientedRanges.haveOrientation) {
+ info->addMotionRange(mOrientedRanges.orientation);
+ }
- if (mOrientedRanges.haveDistance) {
- info->addMotionRange(mOrientedRanges.distance);
- }
+ if (mOrientedRanges.haveDistance) {
+ info->addMotionRange(mOrientedRanges.distance);
+ }
- if (mPointerController != NULL) {
- float minX, minY, maxX, maxY;
- if (mPointerController->getBounds(&minX, &minY, &maxX, &maxY)) {
- info->addMotionRange(AMOTION_EVENT_AXIS_X, mPointerSource,
- minX, maxX, 0.0f, 0.0f);
- info->addMotionRange(AMOTION_EVENT_AXIS_Y, mPointerSource,
- minY, maxY, 0.0f, 0.0f);
+ if (mOrientedRanges.haveTilt) {
+ info->addMotionRange(mOrientedRanges.tilt);
+ }
+
+ if (mCursorScrollAccumulator.haveRelativeVWheel()) {
+ info->addMotionRange(AMOTION_EVENT_AXIS_VSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f);
+ }
+ if (mCursorScrollAccumulator.haveRelativeHWheel()) {
+ info->addMotionRange(AMOTION_EVENT_AXIS_HSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f);
}
- info->addMotionRange(AMOTION_EVENT_AXIS_PRESSURE, mPointerSource,
- 0.0f, 1.0f, 0.0f, 0.0f);
}
}
@@ -2215,8 +2378,14 @@ void TouchInputMapper::dump(String8& dump) {
dump.appendFormat(INDENT4 "GeometricScale: %0.3f\n", mGeometricScale);
dump.appendFormat(INDENT4 "PressureScale: %0.3f\n", mPressureScale);
dump.appendFormat(INDENT4 "SizeScale: %0.3f\n", mSizeScale);
+ dump.appendFormat(INDENT4 "OrientationCenter: %0.3f\n", mOrientationCenter);
dump.appendFormat(INDENT4 "OrientationScale: %0.3f\n", mOrientationScale);
dump.appendFormat(INDENT4 "DistanceScale: %0.3f\n", mDistanceScale);
+ dump.appendFormat(INDENT4 "HaveTilt: %s\n", toString(mHaveTilt));
+ dump.appendFormat(INDENT4 "TiltXCenter: %0.3f\n", mTiltXCenter);
+ dump.appendFormat(INDENT4 "TiltXScale: %0.3f\n", mTiltXScale);
+ dump.appendFormat(INDENT4 "TiltYCenter: %0.3f\n", mTiltYCenter);
+ dump.appendFormat(INDENT4 "TiltYScale: %0.3f\n", mTiltYScale);
dump.appendFormat(INDENT3 "Last Button State: 0x%08x\n", mLastButtonState);
@@ -2226,11 +2395,12 @@ void TouchInputMapper::dump(String8& dump) {
const RawPointerData::Pointer& pointer = mLastRawPointerData.pointers[i];
dump.appendFormat(INDENT4 "[%d]: id=%d, x=%d, y=%d, pressure=%d, "
"touchMajor=%d, touchMinor=%d, toolMajor=%d, toolMinor=%d, "
- "orientation=%d, distance=%d, toolType=%d, isHovering=%s\n", i,
+ "orientation=%d, tiltX=%d, tiltY=%d, distance=%d, "
+ "toolType=%d, isHovering=%s\n", i,
pointer.id, pointer.x, pointer.y, pointer.pressure,
pointer.touchMajor, pointer.touchMinor,
pointer.toolMajor, pointer.toolMinor,
- pointer.orientation, pointer.distance,
+ pointer.orientation, pointer.tiltX, pointer.tiltY, pointer.distance,
pointer.toolType, toString(pointer.isHovering));
}
@@ -2241,7 +2411,8 @@ void TouchInputMapper::dump(String8& dump) {
const PointerCoords& pointerCoords = mLastCookedPointerData.pointerCoords[i];
dump.appendFormat(INDENT4 "[%d]: id=%d, x=%0.3f, y=%0.3f, pressure=%0.3f, "
"touchMajor=%0.3f, touchMinor=%0.3f, toolMajor=%0.3f, toolMinor=%0.3f, "
- "orientation=%0.3f, distance=%0.3f, toolType=%d, isHovering=%s\n", i,
+ "orientation=%0.3f, tilt=%0.3f, distance=%0.3f, "
+ "toolType=%d, isHovering=%s\n", i,
pointerProperties.id,
pointerCoords.getX(),
pointerCoords.getY(),
@@ -2251,50 +2422,30 @@ void TouchInputMapper::dump(String8& dump) {
pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR),
pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR),
pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION),
+ pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TILT),
pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_DISTANCE),
pointerProperties.toolType,
toString(mLastCookedPointerData.isHovering(i)));
}
- if (mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER) {
+ if (mDeviceMode == DEVICE_MODE_POINTER) {
dump.appendFormat(INDENT3 "Pointer Gesture Detector:\n");
dump.appendFormat(INDENT4 "XMovementScale: %0.3f\n",
- mPointerGestureXMovementScale);
+ mPointerXMovementScale);
dump.appendFormat(INDENT4 "YMovementScale: %0.3f\n",
- mPointerGestureYMovementScale);
+ mPointerYMovementScale);
dump.appendFormat(INDENT4 "XZoomScale: %0.3f\n",
- mPointerGestureXZoomScale);
+ mPointerXZoomScale);
dump.appendFormat(INDENT4 "YZoomScale: %0.3f\n",
- mPointerGestureYZoomScale);
+ mPointerYZoomScale);
dump.appendFormat(INDENT4 "MaxSwipeWidth: %f\n",
mPointerGestureMaxSwipeWidth);
}
}
-void TouchInputMapper::initialize() {
- mCurrentRawPointerData.clear();
- mLastRawPointerData.clear();
- mCurrentCookedPointerData.clear();
- mLastCookedPointerData.clear();
- mCurrentButtonState = 0;
- mLastButtonState = 0;
- mSentHoverEnter = false;
- mDownTime = 0;
-
- mCurrentVirtualKey.down = false;
-
- mOrientedRanges.havePressure = false;
- mOrientedRanges.haveSize = false;
- mOrientedRanges.haveTouchSize = false;
- mOrientedRanges.haveToolSize = false;
- mOrientedRanges.haveOrientation = false;
- mOrientedRanges.haveDistance = false;
-
- mPointerGesture.reset();
-}
-
-void TouchInputMapper::configure(const InputReaderConfiguration* config, uint32_t changes) {
- InputMapper::configure(config, changes);
+void TouchInputMapper::configure(nsecs_t when,
+ const InputReaderConfiguration* config, uint32_t changes) {
+ InputMapper::configure(when, config, changes);
mConfig = *config;
@@ -2302,23 +2453,9 @@ void TouchInputMapper::configure(const InputReaderConfiguration* config, uint32_
// Configure basic parameters.
configureParameters();
- // Configure sources.
- switch (mParameters.deviceType) {
- case Parameters::DEVICE_TYPE_TOUCH_SCREEN:
- mTouchSource = AINPUT_SOURCE_TOUCHSCREEN;
- mPointerSource = 0;
- break;
- case Parameters::DEVICE_TYPE_TOUCH_PAD:
- mTouchSource = AINPUT_SOURCE_TOUCHPAD;
- mPointerSource = 0;
- break;
- case Parameters::DEVICE_TYPE_POINTER:
- mTouchSource = AINPUT_SOURCE_TOUCHPAD;
- mPointerSource = AINPUT_SOURCE_MOUSE;
- break;
- default:
- LOG_ASSERT(false);
- }
+ // Configure common accumulators.
+ mCursorScrollAccumulator.configure(getDevice());
+ mTouchButtonAccumulator.configure(getDevice());
// Configure absolute axis information.
configureRawPointerAxes();
@@ -2326,19 +2463,27 @@ void TouchInputMapper::configure(const InputReaderConfiguration* config, uint32_
// Prepare input device calibration.
parseCalibration();
resolveCalibration();
-
- // Configure surface dimensions and orientation.
- configureSurface();
}
if (!changes || (changes & InputReaderConfiguration::CHANGE_POINTER_SPEED)) {
- mPointerGesture.pointerVelocityControl.setParameters(
- mConfig.pointerVelocityControlParameters);
+ // Update pointer speed.
+ mPointerVelocityControl.setParameters(mConfig.pointerVelocityControlParameters);
+ mWheelXVelocityControl.setParameters(mConfig.wheelVelocityControlParameters);
+ mWheelYVelocityControl.setParameters(mConfig.wheelVelocityControlParameters);
}
- if (!changes || (changes & InputReaderConfiguration::CHANGE_POINTER_GESTURE_ENABLEMENT)) {
- // Reset the touch screen when pointer gesture enablement changes.
- reset();
+ bool resetNeeded = false;
+ if (!changes || (changes & (InputReaderConfiguration::CHANGE_DISPLAY_INFO
+ | InputReaderConfiguration::CHANGE_POINTER_GESTURE_ENABLEMENT))) {
+ // Configure device sources, surface dimensions, orientation and
+ // scaling factors.
+ configureSurface(when, &resetNeeded);
+ }
+
+ if (changes && resetNeeded) {
+ // Send reset, unless this is the first time the device has been configured,
+ // in which case the reader will call reset itself after all mappers are ready.
+ getDevice()->notifyReset(when);
}
}
@@ -2435,8 +2580,8 @@ void TouchInputMapper::dumpParameters(String8& dump) {
LOG_ASSERT(false);
}
- dump.appendFormat(INDENT4 "AssociatedDisplayId: %d\n",
- mParameters.associatedDisplayId);
+ dump.appendFormat(INDENT4 "AssociatedDisplay: id=%d, isExternal=%s\n",
+ mParameters.associatedDisplayId, toString(mParameters.associatedDisplayIsExternal));
dump.appendFormat(INDENT4 "OrientationAware: %s\n",
toString(mParameters.orientationAware));
}
@@ -2456,47 +2601,79 @@ void TouchInputMapper::dumpRawPointerAxes(String8& dump) {
dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.toolMinor, "ToolMinor");
dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.orientation, "Orientation");
dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.distance, "Distance");
+ dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.tiltX, "TiltX");
+ dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.tiltY, "TiltY");
dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.trackingId, "TrackingId");
dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.slot, "Slot");
}
-bool TouchInputMapper::configureSurface() {
+void TouchInputMapper::configureSurface(nsecs_t when, bool* outResetNeeded) {
+ int32_t oldDeviceMode = mDeviceMode;
+
+ // Determine device mode.
+ if (mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER
+ && mConfig.pointerGesturesEnabled) {
+ mSource = AINPUT_SOURCE_MOUSE;
+ mDeviceMode = DEVICE_MODE_POINTER;
+ } else if (mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN
+ && mParameters.associatedDisplayId >= 0) {
+ mSource = AINPUT_SOURCE_TOUCHSCREEN;
+ mDeviceMode = DEVICE_MODE_DIRECT;
+ } else {
+ mSource = AINPUT_SOURCE_TOUCHPAD;
+ mDeviceMode = DEVICE_MODE_UNSCALED;
+ }
+
// Ensure we have valid X and Y axes.
if (!mRawPointerAxes.x.valid || !mRawPointerAxes.y.valid) {
LOGW(INDENT "Touch device '%s' did not report support for X or Y axis! "
"The device will be inoperable.", getDeviceName().string());
- return false;
+ mDeviceMode = DEVICE_MODE_DISABLED;
+ return;
}
- // Update orientation and dimensions if needed.
- int32_t orientation = DISPLAY_ORIENTATION_0;
- int32_t width = mRawPointerAxes.x.maxValue - mRawPointerAxes.x.minValue + 1;
- int32_t height = mRawPointerAxes.y.maxValue - mRawPointerAxes.y.minValue + 1;
-
+ // Get associated display dimensions.
if (mParameters.associatedDisplayId >= 0) {
- // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
- if (! getPolicy()->getDisplayInfo(mParameters.associatedDisplayId,
+ if (!mConfig.getDisplayInfo(mParameters.associatedDisplayId,
mParameters.associatedDisplayIsExternal,
&mAssociatedDisplayWidth, &mAssociatedDisplayHeight,
&mAssociatedDisplayOrientation)) {
- return false;
+ LOGI(INDENT "Touch device '%s' could not query the properties of its associated "
+ "display %d. The device will be inoperable until the display size "
+ "becomes available.",
+ getDeviceName().string(), mParameters.associatedDisplayId);
+ mDeviceMode = DEVICE_MODE_DISABLED;
+ return;
}
+ }
- // A touch screen inherits the dimensions of the display.
- if (mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN) {
- width = mAssociatedDisplayWidth;
- height = mAssociatedDisplayHeight;
- }
+ // Configure dimensions.
+ int32_t width, height, orientation;
+ if (mDeviceMode == DEVICE_MODE_DIRECT || mDeviceMode == DEVICE_MODE_POINTER) {
+ width = mAssociatedDisplayWidth;
+ height = mAssociatedDisplayHeight;
+ orientation = mParameters.orientationAware ?
+ mAssociatedDisplayOrientation : DISPLAY_ORIENTATION_0;
+ } else {
+ width = mRawPointerAxes.x.maxValue - mRawPointerAxes.x.minValue + 1;
+ height = mRawPointerAxes.y.maxValue - mRawPointerAxes.y.minValue + 1;
+ orientation = DISPLAY_ORIENTATION_0;
+ }
+
+ // If moving between pointer modes, need to reset some state.
+ bool deviceModeChanged;
+ if (mDeviceMode != oldDeviceMode) {
+ deviceModeChanged = true;
- // The device inherits the orientation of the display if it is orientation aware.
- if (mParameters.orientationAware) {
- orientation = mAssociatedDisplayOrientation;
+ if (mDeviceMode == DEVICE_MODE_POINTER) {
+ if (mPointerController == NULL) {
+ mPointerController = getPolicy()->obtainPointerController(getDeviceId());
+ }
+ } else {
+ mPointerController.clear();
}
- }
- if (mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER
- && mPointerController == NULL) {
- mPointerController = getPolicy()->obtainPointerController(getDeviceId());
+ mOrientedRanges.clear();
}
bool orientationChanged = mSurfaceOrientation != orientation;
@@ -2505,9 +2682,9 @@ bool TouchInputMapper::configureSurface() {
}
bool sizeChanged = mSurfaceWidth != width || mSurfaceHeight != height;
- if (sizeChanged) {
- LOGI("Device reconfigured: id=%d, name='%s', surface size is now %dx%d",
- getDeviceId(), getDeviceName().string(), width, height);
+ if (sizeChanged || deviceModeChanged) {
+ LOGI("Device reconfigured: id=%d, name='%s', surface size is now %dx%d, mode is %d",
+ getDeviceId(), getDeviceName().string(), width, height, mDeviceMode);
mSurfaceWidth = width;
mSurfaceHeight = height;
@@ -2519,9 +2696,9 @@ bool TouchInputMapper::configureSurface() {
mYPrecision = 1.0f / mYScale;
mOrientedRanges.x.axis = AMOTION_EVENT_AXIS_X;
- mOrientedRanges.x.source = mTouchSource;
+ mOrientedRanges.x.source = mSource;
mOrientedRanges.y.axis = AMOTION_EVENT_AXIS_Y;
- mOrientedRanges.y.source = mTouchSource;
+ mOrientedRanges.y.source = mSource;
configureVirtualKeys();
@@ -2550,7 +2727,7 @@ bool TouchInputMapper::configureSurface() {
mOrientedRanges.haveSize = true;
mOrientedRanges.touchMajor.axis = AMOTION_EVENT_AXIS_TOUCH_MAJOR;
- mOrientedRanges.touchMajor.source = mTouchSource;
+ mOrientedRanges.touchMajor.source = mSource;
mOrientedRanges.touchMajor.min = 0;
mOrientedRanges.touchMajor.max = diagonalSize;
mOrientedRanges.touchMajor.flat = 0;
@@ -2560,7 +2737,7 @@ bool TouchInputMapper::configureSurface() {
mOrientedRanges.touchMinor.axis = AMOTION_EVENT_AXIS_TOUCH_MINOR;
mOrientedRanges.toolMajor.axis = AMOTION_EVENT_AXIS_TOOL_MAJOR;
- mOrientedRanges.toolMajor.source = mTouchSource;
+ mOrientedRanges.toolMajor.source = mSource;
mOrientedRanges.toolMajor.min = 0;
mOrientedRanges.toolMajor.max = diagonalSize;
mOrientedRanges.toolMajor.flat = 0;
@@ -2570,7 +2747,7 @@ bool TouchInputMapper::configureSurface() {
mOrientedRanges.toolMinor.axis = AMOTION_EVENT_AXIS_TOOL_MINOR;
mOrientedRanges.size.axis = AMOTION_EVENT_AXIS_SIZE;
- mOrientedRanges.size.source = mTouchSource;
+ mOrientedRanges.size.source = mSource;
mOrientedRanges.size.min = 0;
mOrientedRanges.size.max = 1.0;
mOrientedRanges.size.flat = 0;
@@ -2581,44 +2758,77 @@ bool TouchInputMapper::configureSurface() {
// Pressure factors.
mPressureScale = 0;
- if (mCalibration.pressureCalibration != Calibration::PRESSURE_CALIBRATION_NONE) {
- if (mCalibration.pressureCalibration == Calibration::PRESSURE_CALIBRATION_PHYSICAL
- || mCalibration.pressureCalibration
- == Calibration::PRESSURE_CALIBRATION_AMPLITUDE) {
- if (mCalibration.havePressureScale) {
- mPressureScale = mCalibration.pressureScale;
- } else if (mRawPointerAxes.pressure.valid
- && mRawPointerAxes.pressure.maxValue != 0) {
- mPressureScale = 1.0f / mRawPointerAxes.pressure.maxValue;
- }
+ if (mCalibration.pressureCalibration == Calibration::PRESSURE_CALIBRATION_PHYSICAL
+ || mCalibration.pressureCalibration
+ == Calibration::PRESSURE_CALIBRATION_AMPLITUDE) {
+ if (mCalibration.havePressureScale) {
+ mPressureScale = mCalibration.pressureScale;
+ } else if (mRawPointerAxes.pressure.valid
+ && mRawPointerAxes.pressure.maxValue != 0) {
+ mPressureScale = 1.0f / mRawPointerAxes.pressure.maxValue;
}
+ }
- mOrientedRanges.havePressure = true;
-
- mOrientedRanges.pressure.axis = AMOTION_EVENT_AXIS_PRESSURE;
- mOrientedRanges.pressure.source = mTouchSource;
- mOrientedRanges.pressure.min = 0;
- mOrientedRanges.pressure.max = 1.0;
- mOrientedRanges.pressure.flat = 0;
- mOrientedRanges.pressure.fuzz = 0;
+ mOrientedRanges.pressure.axis = AMOTION_EVENT_AXIS_PRESSURE;
+ mOrientedRanges.pressure.source = mSource;
+ mOrientedRanges.pressure.min = 0;
+ mOrientedRanges.pressure.max = 1.0;
+ mOrientedRanges.pressure.flat = 0;
+ mOrientedRanges.pressure.fuzz = 0;
+
+ // Tilt
+ mTiltXCenter = 0;
+ mTiltXScale = 0;
+ mTiltYCenter = 0;
+ mTiltYScale = 0;
+ mHaveTilt = mRawPointerAxes.tiltX.valid && mRawPointerAxes.tiltY.valid;
+ if (mHaveTilt) {
+ mTiltXCenter = avg(mRawPointerAxes.tiltX.minValue,
+ mRawPointerAxes.tiltX.maxValue);
+ mTiltYCenter = avg(mRawPointerAxes.tiltY.minValue,
+ mRawPointerAxes.tiltY.maxValue);
+ mTiltXScale = M_PI / 180;
+ mTiltYScale = M_PI / 180;
+
+ mOrientedRanges.haveTilt = true;
+
+ mOrientedRanges.tilt.axis = AMOTION_EVENT_AXIS_TILT;
+ mOrientedRanges.tilt.source = mSource;
+ mOrientedRanges.tilt.min = 0;
+ mOrientedRanges.tilt.max = M_PI_2;
+ mOrientedRanges.tilt.flat = 0;
+ mOrientedRanges.tilt.fuzz = 0;
}
// Orientation
+ mOrientationCenter = 0;
mOrientationScale = 0;
- if (mCalibration.orientationCalibration != Calibration::ORIENTATION_CALIBRATION_NONE) {
+ if (mHaveTilt) {
+ mOrientedRanges.haveOrientation = true;
+
+ mOrientedRanges.orientation.axis = AMOTION_EVENT_AXIS_ORIENTATION;
+ mOrientedRanges.orientation.source = mSource;
+ mOrientedRanges.orientation.min = -M_PI;
+ mOrientedRanges.orientation.max = M_PI;
+ mOrientedRanges.orientation.flat = 0;
+ mOrientedRanges.orientation.fuzz = 0;
+ } else if (mCalibration.orientationCalibration !=
+ Calibration::ORIENTATION_CALIBRATION_NONE) {
if (mCalibration.orientationCalibration
== Calibration::ORIENTATION_CALIBRATION_INTERPOLATED) {
- if (mRawPointerAxes.orientation.valid
- && mRawPointerAxes.orientation.maxValue != 0) {
- mOrientationScale = float(M_PI_2) / mRawPointerAxes.orientation.maxValue;
+ if (mRawPointerAxes.orientation.valid) {
+ mOrientationCenter = avg(mRawPointerAxes.orientation.minValue,
+ mRawPointerAxes.orientation.maxValue);
+ mOrientationScale = M_PI / (mRawPointerAxes.orientation.maxValue -
+ mRawPointerAxes.orientation.minValue);
}
}
mOrientedRanges.haveOrientation = true;
mOrientedRanges.orientation.axis = AMOTION_EVENT_AXIS_ORIENTATION;
- mOrientedRanges.orientation.source = mTouchSource;
- mOrientedRanges.orientation.min = - M_PI_2;
+ mOrientedRanges.orientation.source = mSource;
+ mOrientedRanges.orientation.min = -M_PI_2;
mOrientedRanges.orientation.max = M_PI_2;
mOrientedRanges.orientation.flat = 0;
mOrientedRanges.orientation.fuzz = 0;
@@ -2639,7 +2849,7 @@ bool TouchInputMapper::configureSurface() {
mOrientedRanges.haveDistance = true;
mOrientedRanges.distance.axis = AMOTION_EVENT_AXIS_DISTANCE;
- mOrientedRanges.distance.source = mTouchSource;
+ mOrientedRanges.distance.source = mSource;
mOrientedRanges.distance.min =
mRawPointerAxes.distance.minValue * mDistanceScale;
mOrientedRanges.distance.max =
@@ -2650,7 +2860,7 @@ bool TouchInputMapper::configureSurface() {
}
}
- if (orientationChanged || sizeChanged) {
+ if (orientationChanged || sizeChanged || deviceModeChanged) {
// Compute oriented surface dimensions, precision, scales and ranges.
// Note that the maximum value reported is an inclusive maximum value so it is one
// unit less than the total width or height of surface.
@@ -2698,7 +2908,7 @@ bool TouchInputMapper::configureSurface() {
}
// Compute pointer gesture detection parameters.
- if (mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER) {
+ if (mDeviceMode == DEVICE_MODE_POINTER) {
int32_t rawWidth = mRawPointerAxes.x.maxValue - mRawPointerAxes.x.minValue + 1;
int32_t rawHeight = mRawPointerAxes.y.maxValue - mRawPointerAxes.y.minValue + 1;
float rawDiagonal = hypotf(rawWidth, rawHeight);
@@ -2710,34 +2920,30 @@ bool TouchInputMapper::configureSurface() {
// is applied.
// Assume that the touch pad has a square aspect ratio such that movements in
// X and Y of the same number of raw units cover the same physical distance.
- mPointerGestureXMovementScale = mConfig.pointerGestureMovementSpeedRatio
+ mPointerXMovementScale = mConfig.pointerGestureMovementSpeedRatio
* displayDiagonal / rawDiagonal;
- mPointerGestureYMovementScale = mPointerGestureXMovementScale;
+ mPointerYMovementScale = mPointerXMovementScale;
// 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.
- mPointerGestureXZoomScale = mConfig.pointerGestureZoomSpeedRatio
+ mPointerXZoomScale = mConfig.pointerGestureZoomSpeedRatio
* displayDiagonal / rawDiagonal;
- mPointerGestureYZoomScale = mPointerGestureXZoomScale;
+ mPointerYZoomScale = mPointerXZoomScale;
// 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.
mPointerGestureMaxSwipeWidth =
mConfig.pointerGestureSwipeMaxWidthRatio * rawDiagonal;
+ }
- // Reset the current pointer gesture.
- mPointerGesture.reset();
+ // Abort current pointer usages because the state has changed.
+ abortPointerUsage(when, 0 /*policyFlags*/);
- // Remove any current spots.
- if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) {
- mPointerController->clearSpots();
- }
- }
+ // Inform the dispatcher about the changes.
+ *outResetNeeded = true;
}
-
- return true;
}
void TouchInputMapper::dumpSurface(String8& dump) {
@@ -3023,26 +3229,71 @@ void TouchInputMapper::dumpCalibration(String8& dump) {
}
}
-void TouchInputMapper::reset() {
- // Synthesize touch up event.
- // This will also take care of finishing virtual key processing if needed.
- nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
+void TouchInputMapper::reset(nsecs_t when) {
+ mCursorButtonAccumulator.reset(getDevice());
+ mCursorScrollAccumulator.reset(getDevice());
+ mTouchButtonAccumulator.reset(getDevice());
+
+ mPointerVelocityControl.reset();
+ mWheelXVelocityControl.reset();
+ mWheelYVelocityControl.reset();
+
mCurrentRawPointerData.clear();
+ mLastRawPointerData.clear();
+ mCurrentCookedPointerData.clear();
+ mLastCookedPointerData.clear();
mCurrentButtonState = 0;
- syncTouch(when, true);
+ mLastButtonState = 0;
+ mCurrentRawVScroll = 0;
+ mCurrentRawHScroll = 0;
+ mCurrentFingerIdBits.clear();
+ mLastFingerIdBits.clear();
+ mCurrentStylusIdBits.clear();
+ mLastStylusIdBits.clear();
+ mCurrentMouseIdBits.clear();
+ mLastMouseIdBits.clear();
+ mPointerUsage = POINTER_USAGE_NONE;
+ mSentHoverEnter = false;
+ mDownTime = 0;
- initialize();
+ mCurrentVirtualKey.down = false;
+
+ mPointerGesture.reset();
+ mPointerSimple.reset();
- if (mPointerController != NULL
- && mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) {
+ if (mPointerController != NULL) {
mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
mPointerController->clearSpots();
}
- InputMapper::reset();
+ InputMapper::reset(when);
}
-void TouchInputMapper::syncTouch(nsecs_t when, bool havePointerIds) {
+void TouchInputMapper::process(const RawEvent* rawEvent) {
+ mCursorButtonAccumulator.process(rawEvent);
+ mCursorScrollAccumulator.process(rawEvent);
+ mTouchButtonAccumulator.process(rawEvent);
+
+ if (rawEvent->type == EV_SYN && rawEvent->scanCode == SYN_REPORT) {
+ sync(rawEvent->when);
+ }
+}
+
+void TouchInputMapper::sync(nsecs_t when) {
+ // Sync button state.
+ mCurrentButtonState = mTouchButtonAccumulator.getButtonState()
+ | mCursorButtonAccumulator.getButtonState();
+
+ // Sync scroll state.
+ mCurrentRawVScroll = mCursorScrollAccumulator.getRelativeVWheel();
+ mCurrentRawHScroll = mCursorScrollAccumulator.getRelativeHWheel();
+ mCursorScrollAccumulator.finishSync();
+
+ // Sync touch state.
+ bool havePointerIds = true;
+ mCurrentRawPointerData.clear();
+ syncTouch(when, &havePointerIds);
+
#if DEBUG_RAW_EVENTS
if (!havePointerIds) {
LOGD("syncTouch: pointerCount %d -> %d, no pointer ids",
@@ -3060,66 +3311,123 @@ void TouchInputMapper::syncTouch(nsecs_t when, bool havePointerIds) {
}
#endif
- // Configure the surface now, if possible.
- if (!configureSurface()) {
- mLastRawPointerData.clear();
- mLastCookedPointerData.clear();
- mLastButtonState = 0;
- return;
- }
+ // Reset state that we will compute below.
+ mCurrentFingerIdBits.clear();
+ mCurrentStylusIdBits.clear();
+ mCurrentMouseIdBits.clear();
+ mCurrentCookedPointerData.clear();
- // Preprocess pointer data.
- if (!havePointerIds) {
- assignPointerIds();
- }
+ if (mDeviceMode == DEVICE_MODE_DISABLED) {
+ // Drop all input if the device is disabled.
+ mCurrentRawPointerData.clear();
+ mCurrentButtonState = 0;
+ } else {
+ // Preprocess pointer data.
+ if (!havePointerIds) {
+ assignPointerIds();
+ }
- // Handle policy on initial down or hover events.
- uint32_t policyFlags = 0;
- if (mLastRawPointerData.pointerCount == 0 && mCurrentRawPointerData.pointerCount != 0) {
- if (mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN) {
- // If this is a touch screen, hide the pointer on an initial down.
- getContext()->fadePointer();
+ // Handle policy on initial down or hover events.
+ uint32_t policyFlags = 0;
+ if (mLastRawPointerData.pointerCount == 0 && mCurrentRawPointerData.pointerCount != 0) {
+ if (mDeviceMode == DEVICE_MODE_DIRECT) {
+ // If this is a touch screen, hide the pointer on an initial down.
+ getContext()->fadePointer();
+ }
+
+ // Initial downs on external touch devices should wake the device.
+ // We don't do this for internal touch screens to prevent them from waking
+ // up in your pocket.
+ // TODO: Use the input device configuration to control this behavior more finely.
+ if (getDevice()->isExternal()) {
+ policyFlags |= POLICY_FLAG_WAKE_DROPPED;
+ }
}
- // Initial downs on external touch devices should wake the device.
- // We don't do this for internal touch screens to prevent them from waking
- // up in your pocket.
- // TODO: Use the input device configuration to control this behavior more finely.
- if (getDevice()->isExternal()) {
- policyFlags |= POLICY_FLAG_WAKE_DROPPED;
+ // Synthesize key down from raw buttons if needed.
+ synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_DOWN, when, getDeviceId(), mSource,
+ policyFlags, mLastButtonState, mCurrentButtonState);
+
+ // Consume raw off-screen touches before cooking pointer data.
+ // If touches are consumed, subsequent code will not receive any pointer data.
+ if (consumeRawTouches(when, policyFlags)) {
+ mCurrentRawPointerData.clear();
}
- }
- // Synthesize key down from raw buttons if needed.
- synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_DOWN, when, getDeviceId(), mTouchSource,
- policyFlags, mLastButtonState, mCurrentButtonState);
+ // Cook pointer data. This call populates the mCurrentCookedPointerData structure
+ // with cooked pointer data that has the same ids and indices as the raw data.
+ // The following code can use either the raw or cooked data, as needed.
+ cookPointerData();
- if (consumeRawTouches(when, policyFlags)) {
- mCurrentRawPointerData.clear();
- }
+ // Dispatch the touches either directly or by translation through a pointer on screen.
+ if (mPointerController != NULL) {
+ for (BitSet32 idBits(mCurrentRawPointerData.touchingIdBits); !idBits.isEmpty(); ) {
+ uint32_t id = idBits.clearFirstMarkedBit();
+ const RawPointerData::Pointer& pointer = mCurrentRawPointerData.pointerForId(id);
+ if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_STYLUS
+ || pointer.toolType == AMOTION_EVENT_TOOL_TYPE_ERASER) {
+ mCurrentStylusIdBits.markBit(id);
+ } else if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_FINGER
+ || pointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
+ mCurrentFingerIdBits.markBit(id);
+ } else if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_MOUSE) {
+ mCurrentMouseIdBits.markBit(id);
+ }
+ }
+ for (BitSet32 idBits(mCurrentRawPointerData.hoveringIdBits); !idBits.isEmpty(); ) {
+ uint32_t id = idBits.clearFirstMarkedBit();
+ const RawPointerData::Pointer& pointer = mCurrentRawPointerData.pointerForId(id);
+ if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_STYLUS
+ || pointer.toolType == AMOTION_EVENT_TOOL_TYPE_ERASER) {
+ mCurrentStylusIdBits.markBit(id);
+ }
+ }
- if (mPointerController != NULL && mConfig.pointerGesturesEnabled) {
- dispatchPointerGestures(when, policyFlags, false /*isTimeout*/);
- }
+ // Stylus takes precedence over all tools, then mouse, then finger.
+ PointerUsage pointerUsage = mPointerUsage;
+ if (!mCurrentStylusIdBits.isEmpty()) {
+ mCurrentMouseIdBits.clear();
+ mCurrentFingerIdBits.clear();
+ pointerUsage = POINTER_USAGE_STYLUS;
+ } else if (!mCurrentMouseIdBits.isEmpty()) {
+ mCurrentFingerIdBits.clear();
+ pointerUsage = POINTER_USAGE_MOUSE;
+ } else if (!mCurrentFingerIdBits.isEmpty() || isPointerDown(mCurrentButtonState)) {
+ pointerUsage = POINTER_USAGE_GESTURES;
+ } else {
+ pointerUsage = POINTER_USAGE_NONE;
+ }
- cookPointerData();
- dispatchHoverExit(when, policyFlags);
- dispatchTouches(when, policyFlags);
- dispatchHoverEnterAndMove(when, policyFlags);
+ dispatchPointerUsage(when, policyFlags, pointerUsage);
+ } else {
+ dispatchHoverExit(when, policyFlags);
+ dispatchTouches(when, policyFlags);
+ dispatchHoverEnterAndMove(when, policyFlags);
+ }
- // Synthesize key up from raw buttons if needed.
- synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_UP, when, getDeviceId(), mTouchSource,
- policyFlags, mLastButtonState, mCurrentButtonState);
+ // Synthesize key up from raw buttons if needed.
+ synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_UP, when, getDeviceId(), mSource,
+ policyFlags, mLastButtonState, mCurrentButtonState);
+ }
// Copy current touch to last touch in preparation for the next cycle.
mLastRawPointerData.copyFrom(mCurrentRawPointerData);
mLastCookedPointerData.copyFrom(mCurrentCookedPointerData);
mLastButtonState = mCurrentButtonState;
+ mLastFingerIdBits = mCurrentFingerIdBits;
+ mLastStylusIdBits = mCurrentStylusIdBits;
+ mLastMouseIdBits = mCurrentMouseIdBits;
+
+ // Clear some transient state.
+ mCurrentRawVScroll = 0;
+ mCurrentRawHScroll = 0;
}
void TouchInputMapper::timeoutExpired(nsecs_t when) {
if (mPointerController != NULL) {
- dispatchPointerGestures(when, 0 /*policyFlags*/, true /*isTimeout*/);
+ if (mPointerUsage == POINTER_USAGE_GESTURES) {
+ dispatchPointerGestures(when, 0 /*policyFlags*/, true /*isTimeout*/);
+ }
}
}
@@ -3245,7 +3553,7 @@ void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) {
if (!currentIdBits.isEmpty()) {
// No pointer id changes so this is a move event.
// The listener takes care of batching moves so we don't have to deal with that here.
- dispatchMotion(when, policyFlags, mTouchSource,
+ dispatchMotion(when, policyFlags, mSource,
AMOTION_EVENT_ACTION_MOVE, 0, metaState, buttonState,
AMOTION_EVENT_EDGE_FLAG_NONE,
mCurrentCookedPointerData.pointerProperties,
@@ -3280,7 +3588,7 @@ void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) {
while (!upIdBits.isEmpty()) {
uint32_t upId = upIdBits.clearFirstMarkedBit();
- dispatchMotion(when, policyFlags, mTouchSource,
+ dispatchMotion(when, policyFlags, mSource,
AMOTION_EVENT_ACTION_POINTER_UP, 0, metaState, buttonState, 0,
mLastCookedPointerData.pointerProperties,
mLastCookedPointerData.pointerCoords,
@@ -3295,7 +3603,7 @@ void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) {
// events, they do not generally handle them except when presented in a move event.
if (moveNeeded) {
LOG_ASSERT(moveIdBits.value == dispatchedIdBits.value);
- dispatchMotion(when, policyFlags, mTouchSource,
+ dispatchMotion(when, policyFlags, mSource,
AMOTION_EVENT_ACTION_MOVE, 0, metaState, buttonState, 0,
mCurrentCookedPointerData.pointerProperties,
mCurrentCookedPointerData.pointerCoords,
@@ -3314,7 +3622,7 @@ void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) {
mDownTime = when;
}
- dispatchMotion(when, policyFlags, mTouchSource,
+ dispatchMotion(when, policyFlags, mSource,
AMOTION_EVENT_ACTION_POINTER_DOWN, 0, metaState, buttonState, 0,
mCurrentCookedPointerData.pointerProperties,
mCurrentCookedPointerData.pointerCoords,
@@ -3330,7 +3638,7 @@ void TouchInputMapper::dispatchHoverExit(nsecs_t when, uint32_t policyFlags) {
(mCurrentCookedPointerData.hoveringIdBits.isEmpty()
|| !mCurrentCookedPointerData.touchingIdBits.isEmpty())) {
int32_t metaState = getContext()->getGlobalMetaState();
- dispatchMotion(when, policyFlags, mTouchSource,
+ dispatchMotion(when, policyFlags, mSource,
AMOTION_EVENT_ACTION_HOVER_EXIT, 0, metaState, mLastButtonState, 0,
mLastCookedPointerData.pointerProperties,
mLastCookedPointerData.pointerCoords,
@@ -3346,7 +3654,7 @@ void TouchInputMapper::dispatchHoverEnterAndMove(nsecs_t when, uint32_t policyFl
&& !mCurrentCookedPointerData.hoveringIdBits.isEmpty()) {
int32_t metaState = getContext()->getGlobalMetaState();
if (!mSentHoverEnter) {
- dispatchMotion(when, policyFlags, mTouchSource,
+ dispatchMotion(when, policyFlags, mSource,
AMOTION_EVENT_ACTION_HOVER_ENTER, 0, metaState, mCurrentButtonState, 0,
mCurrentCookedPointerData.pointerProperties,
mCurrentCookedPointerData.pointerCoords,
@@ -3356,7 +3664,7 @@ void TouchInputMapper::dispatchHoverEnterAndMove(nsecs_t when, uint32_t policyFl
mSentHoverEnter = true;
}
- dispatchMotion(when, policyFlags, mTouchSource,
+ dispatchMotion(when, policyFlags, mSource,
AMOTION_EVENT_ACTION_HOVER_MOVE, 0, metaState, mCurrentButtonState, 0,
mCurrentCookedPointerData.pointerProperties,
mCurrentCookedPointerData.pointerCoords,
@@ -3467,30 +3775,40 @@ void TouchInputMapper::cookPointerData() {
break;
}
- // Orientation
+ // Tilt and Orientation
+ float tilt;
float orientation;
- switch (mCalibration.orientationCalibration) {
- case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
- orientation = in.orientation * mOrientationScale;
- break;
- case Calibration::ORIENTATION_CALIBRATION_VECTOR: {
- int32_t c1 = signExtendNybble((in.orientation & 0xf0) >> 4);
- int32_t c2 = signExtendNybble(in.orientation & 0x0f);
- if (c1 != 0 || c2 != 0) {
- orientation = atan2f(c1, c2) * 0.5f;
- float confidence = hypotf(c1, c2);
- float scale = 1.0f + confidence / 16.0f;
- touchMajor *= scale;
- touchMinor /= scale;
- toolMajor *= scale;
- toolMinor /= scale;
- } else {
+ if (mHaveTilt) {
+ float tiltXAngle = (in.tiltX - mTiltXCenter) * mTiltXScale;
+ float tiltYAngle = (in.tiltY - mTiltYCenter) * mTiltYScale;
+ orientation = atan2f(-sinf(tiltXAngle), sinf(tiltYAngle));
+ tilt = acosf(cosf(tiltXAngle) * cosf(tiltYAngle));
+ } else {
+ tilt = 0;
+
+ switch (mCalibration.orientationCalibration) {
+ case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
+ orientation = (in.orientation - mOrientationCenter) * mOrientationScale;
+ break;
+ case Calibration::ORIENTATION_CALIBRATION_VECTOR: {
+ int32_t c1 = signExtendNybble((in.orientation & 0xf0) >> 4);
+ int32_t c2 = signExtendNybble(in.orientation & 0x0f);
+ if (c1 != 0 || c2 != 0) {
+ orientation = atan2f(c1, c2) * 0.5f;
+ float confidence = hypotf(c1, c2);
+ float scale = 1.0f + confidence / 16.0f;
+ touchMajor *= scale;
+ touchMinor /= scale;
+ toolMajor *= scale;
+ toolMinor /= scale;
+ } else {
+ orientation = 0;
+ }
+ break;
+ }
+ default:
orientation = 0;
}
- break;
- }
- default:
- orientation = 0;
}
// Distance
@@ -3545,6 +3863,7 @@ void TouchInputMapper::cookPointerData() {
out.setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, toolMajor);
out.setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR, toolMinor);
out.setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, orientation);
+ out.setAxisValue(AMOTION_EVENT_AXIS_TILT, tilt);
out.setAxisValue(AMOTION_EVENT_AXIS_DISTANCE, distance);
// Write output properties.
@@ -3559,6 +3878,46 @@ void TouchInputMapper::cookPointerData() {
}
}
+void TouchInputMapper::dispatchPointerUsage(nsecs_t when, uint32_t policyFlags,
+ PointerUsage pointerUsage) {
+ if (pointerUsage != mPointerUsage) {
+ abortPointerUsage(when, policyFlags);
+ mPointerUsage = pointerUsage;
+ }
+
+ switch (mPointerUsage) {
+ case POINTER_USAGE_GESTURES:
+ dispatchPointerGestures(when, policyFlags, false /*isTimeout*/);
+ break;
+ case POINTER_USAGE_STYLUS:
+ dispatchPointerStylus(when, policyFlags);
+ break;
+ case POINTER_USAGE_MOUSE:
+ dispatchPointerMouse(when, policyFlags);
+ break;
+ default:
+ break;
+ }
+}
+
+void TouchInputMapper::abortPointerUsage(nsecs_t when, uint32_t policyFlags) {
+ switch (mPointerUsage) {
+ case POINTER_USAGE_GESTURES:
+ abortPointerGestures(when, policyFlags);
+ break;
+ case POINTER_USAGE_STYLUS:
+ abortPointerStylus(when, policyFlags);
+ break;
+ case POINTER_USAGE_MOUSE:
+ abortPointerMouse(when, policyFlags);
+ break;
+ default:
+ break;
+ }
+
+ mPointerUsage = POINTER_USAGE_NONE;
+}
+
void TouchInputMapper::dispatchPointerGestures(nsecs_t when, uint32_t policyFlags,
bool isTimeout) {
// Update current gesture coordinates.
@@ -3649,7 +4008,7 @@ void TouchInputMapper::dispatchPointerGestures(nsecs_t when, uint32_t policyFlag
BitSet32 dispatchedGestureIdBits(mPointerGesture.lastGestureIdBits);
if (!dispatchedGestureIdBits.isEmpty()) {
if (cancelPreviousGesture) {
- dispatchMotion(when, policyFlags, mPointerSource,
+ dispatchMotion(when, policyFlags, mSource,
AMOTION_EVENT_ACTION_CANCEL, 0, metaState, buttonState,
AMOTION_EVENT_EDGE_FLAG_NONE,
mPointerGesture.lastGestureProperties,
@@ -3669,7 +4028,7 @@ void TouchInputMapper::dispatchPointerGestures(nsecs_t when, uint32_t policyFlag
while (!upGestureIdBits.isEmpty()) {
uint32_t id = upGestureIdBits.clearFirstMarkedBit();
- dispatchMotion(when, policyFlags, mPointerSource,
+ dispatchMotion(when, policyFlags, mSource,
AMOTION_EVENT_ACTION_POINTER_UP, 0,
metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
mPointerGesture.lastGestureProperties,
@@ -3684,7 +4043,7 @@ void TouchInputMapper::dispatchPointerGestures(nsecs_t when, uint32_t policyFlag
// Send motion events for all pointers that moved.
if (moveNeeded) {
- dispatchMotion(when, policyFlags, mPointerSource,
+ dispatchMotion(when, policyFlags, mSource,
AMOTION_EVENT_ACTION_MOVE, 0, metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
mPointerGesture.currentGestureProperties,
mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex,
@@ -3704,7 +4063,7 @@ void TouchInputMapper::dispatchPointerGestures(nsecs_t when, uint32_t policyFlag
mPointerGesture.downTime = when;
}
- dispatchMotion(when, policyFlags, mPointerSource,
+ dispatchMotion(when, policyFlags, mSource,
AMOTION_EVENT_ACTION_POINTER_DOWN, 0, metaState, buttonState, 0,
mPointerGesture.currentGestureProperties,
mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex,
@@ -3715,7 +4074,7 @@ void TouchInputMapper::dispatchPointerGestures(nsecs_t when, uint32_t policyFlag
// Send motion events for hover.
if (mPointerGesture.currentGestureMode == PointerGesture::HOVER) {
- dispatchMotion(when, policyFlags, mPointerSource,
+ dispatchMotion(when, policyFlags, mSource,
AMOTION_EVENT_ACTION_HOVER_MOVE, 0,
metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
mPointerGesture.currentGestureProperties,
@@ -3741,7 +4100,7 @@ void TouchInputMapper::dispatchPointerGestures(nsecs_t when, uint32_t policyFlag
pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
- NotifyMotionArgs args(when, getDeviceId(), mPointerSource, policyFlags,
+ NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
AMOTION_EVENT_ACTION_HOVER_MOVE, 0,
metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
1, &pointerProperties, &pointerCoords, 0, 0, mPointerGesture.downTime);
@@ -3766,6 +4125,31 @@ void TouchInputMapper::dispatchPointerGestures(nsecs_t when, uint32_t policyFlag
}
}
+void TouchInputMapper::abortPointerGestures(nsecs_t when, uint32_t policyFlags) {
+ // Cancel previously dispatches pointers.
+ if (!mPointerGesture.lastGestureIdBits.isEmpty()) {
+ int32_t metaState = getContext()->getGlobalMetaState();
+ int32_t buttonState = mCurrentButtonState;
+ dispatchMotion(when, policyFlags, mSource,
+ AMOTION_EVENT_ACTION_CANCEL, 0, metaState, buttonState,
+ AMOTION_EVENT_EDGE_FLAG_NONE,
+ mPointerGesture.lastGestureProperties,
+ mPointerGesture.lastGestureCoords, mPointerGesture.lastGestureIdToIndex,
+ mPointerGesture.lastGestureIdBits, -1,
+ 0, 0, mPointerGesture.downTime);
+ }
+
+ // Reset the current pointer gesture.
+ mPointerGesture.reset();
+ mPointerVelocityControl.reset();
+
+ // Remove any current spots.
+ if (mPointerController != NULL) {
+ mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
+ mPointerController->clearSpots();
+ }
+}
+
bool TouchInputMapper::preparePointerGestures(nsecs_t when,
bool* outCancelPreviousGesture, bool* outFinishPreviousGesture, bool isTimeout) {
*outCancelPreviousGesture = false;
@@ -3793,7 +4177,7 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when,
mPointerGesture.currentGestureMode = PointerGesture::NEUTRAL;
mPointerGesture.currentGestureIdBits.clear();
- mPointerGesture.pointerVelocityControl.reset();
+ mPointerVelocityControl.reset();
return true;
}
}
@@ -3802,18 +4186,21 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when,
return false;
}
+ const uint32_t currentFingerCount = mCurrentFingerIdBits.count();
+ const uint32_t lastFingerCount = mLastFingerIdBits.count();
+
// Update the velocity tracker.
{
VelocityTracker::Position positions[MAX_POINTERS];
uint32_t count = 0;
- for (BitSet32 idBits(mCurrentRawPointerData.touchingIdBits); !idBits.isEmpty(); count++) {
+ for (BitSet32 idBits(mCurrentFingerIdBits); !idBits.isEmpty(); count++) {
uint32_t id = idBits.clearFirstMarkedBit();
const RawPointerData::Pointer& pointer = mCurrentRawPointerData.pointerForId(id);
- positions[count].x = pointer.x * mPointerGestureXMovementScale;
- positions[count].y = pointer.y * mPointerGestureYMovementScale;
+ positions[count].x = pointer.x * mPointerXMovementScale;
+ positions[count].y = pointer.y * mPointerYMovementScale;
}
mPointerGesture.velocityTracker.addMovement(when,
- mCurrentRawPointerData.touchingIdBits, positions);
+ mCurrentFingerIdBits, positions);
}
// Pick a new active touch id if needed.
@@ -3825,25 +4212,22 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when,
int32_t lastActiveTouchId = mPointerGesture.activeTouchId;
int32_t activeTouchId = lastActiveTouchId;
if (activeTouchId < 0) {
- if (!mCurrentRawPointerData.touchingIdBits.isEmpty()) {
+ if (!mCurrentFingerIdBits.isEmpty()) {
activeTouchChanged = true;
activeTouchId = mPointerGesture.activeTouchId =
- mCurrentRawPointerData.touchingIdBits.firstMarkedBit();
+ mCurrentFingerIdBits.firstMarkedBit();
mPointerGesture.firstTouchTime = when;
}
- } else if (!mCurrentRawPointerData.touchingIdBits.hasBit(activeTouchId)) {
+ } else if (!mCurrentFingerIdBits.hasBit(activeTouchId)) {
activeTouchChanged = true;
- if (!mCurrentRawPointerData.touchingIdBits.isEmpty()) {
+ if (!mCurrentFingerIdBits.isEmpty()) {
activeTouchId = mPointerGesture.activeTouchId =
- mCurrentRawPointerData.touchingIdBits.firstMarkedBit();
+ mCurrentFingerIdBits.firstMarkedBit();
} else {
activeTouchId = mPointerGesture.activeTouchId = -1;
}
}
- uint32_t currentTouchingPointerCount = mCurrentRawPointerData.touchingIdBits.count();
- uint32_t lastTouchingPointerCount = mLastRawPointerData.touchingIdBits.count();
-
// Determine whether we are in quiet time.
bool isQuietTime = false;
if (activeTouchId < 0) {
@@ -3854,13 +4238,13 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when,
if ((mPointerGesture.lastGestureMode == PointerGesture::PRESS
|| mPointerGesture.lastGestureMode == PointerGesture::SWIPE
|| mPointerGesture.lastGestureMode == PointerGesture::FREEFORM)
- && currentTouchingPointerCount < 2) {
+ && currentFingerCount < 2) {
// Enter quiet time when exiting swipe or freeform state.
// This is to prevent accidentally entering the hover state and flinging the
// pointer when finishing a swipe and there is still one pointer left onscreen.
isQuietTime = true;
} else if (mPointerGesture.lastGestureMode == PointerGesture::BUTTON_CLICK_OR_DRAG
- && currentTouchingPointerCount >= 2
+ && currentFingerCount >= 2
&& !isPointerDown(mCurrentButtonState)) {
// Enter quiet time when releasing the button and there are still two or more
// fingers down. This may indicate that one finger was used to press the button
@@ -3888,7 +4272,7 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when,
mPointerGesture.currentGestureMode = PointerGesture::QUIET;
mPointerGesture.currentGestureIdBits.clear();
- mPointerGesture.pointerVelocityControl.reset();
+ mPointerVelocityControl.reset();
} else if (isPointerDown(mCurrentButtonState)) {
// Case 2: Button is pressed. (BUTTON_CLICK_OR_DRAG)
// The pointer follows the active touch point.
@@ -3905,7 +4289,7 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when,
// being dragged.
#if DEBUG_GESTURES
LOGD("Gestures: BUTTON_CLICK_OR_DRAG activeTouchId=%d, "
- "currentTouchingPointerCount=%d", activeTouchId, currentTouchingPointerCount);
+ "currentFingerCount=%d", activeTouchId, currentFingerCount);
#endif
// Reset state when just starting.
if (mPointerGesture.lastGestureMode != PointerGesture::BUTTON_CLICK_OR_DRAG) {
@@ -3915,10 +4299,10 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when,
// Switch pointers if needed.
// Find the fastest pointer and follow it.
- if (activeTouchId >= 0 && currentTouchingPointerCount > 1) {
+ if (activeTouchId >= 0 && currentFingerCount > 1) {
int32_t bestId = -1;
float bestSpeed = mConfig.pointerGestureDragMinSwitchSpeed;
- for (BitSet32 idBits(mCurrentRawPointerData.touchingIdBits); !idBits.isEmpty(); ) {
+ for (BitSet32 idBits(mCurrentFingerIdBits); !idBits.isEmpty(); ) {
uint32_t id = idBits.clearFirstMarkedBit();
float vx, vy;
if (mPointerGesture.velocityTracker.getVelocity(id, &vx, &vy)) {
@@ -3939,23 +4323,23 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when,
}
}
- if (activeTouchId >= 0 && mLastRawPointerData.touchingIdBits.hasBit(activeTouchId)) {
+ if (activeTouchId >= 0 && mLastFingerIdBits.hasBit(activeTouchId)) {
const RawPointerData::Pointer& currentPointer =
mCurrentRawPointerData.pointerForId(activeTouchId);
const RawPointerData::Pointer& lastPointer =
mLastRawPointerData.pointerForId(activeTouchId);
- float deltaX = (currentPointer.x - lastPointer.x) * mPointerGestureXMovementScale;
- float deltaY = (currentPointer.y - lastPointer.y) * mPointerGestureYMovementScale;
+ float deltaX = (currentPointer.x - lastPointer.x) * mPointerXMovementScale;
+ float deltaY = (currentPointer.y - lastPointer.y) * mPointerYMovementScale;
rotateDelta(mSurfaceOrientation, &deltaX, &deltaY);
- mPointerGesture.pointerVelocityControl.move(when, &deltaX, &deltaY);
+ mPointerVelocityControl.move(when, &deltaX, &deltaY);
// Move the pointer using a relative motion.
// When using spots, the click will occur at the position of the anchor
// spot and all other spots will move there.
mPointerController->move(deltaX, deltaY);
} else {
- mPointerGesture.pointerVelocityControl.reset();
+ mPointerVelocityControl.reset();
}
float x, y;
@@ -3972,7 +4356,7 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when,
mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, x);
mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, y);
mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
- } else if (currentTouchingPointerCount == 0) {
+ } else if (currentFingerCount == 0) {
// Case 3. No fingers down and button is not pressed. (NEUTRAL)
if (mPointerGesture.lastGestureMode != PointerGesture::NEUTRAL) {
*outFinishPreviousGesture = true;
@@ -3983,7 +4367,7 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when,
bool tapped = false;
if ((mPointerGesture.lastGestureMode == PointerGesture::HOVER
|| mPointerGesture.lastGestureMode == PointerGesture::TAP_DRAG)
- && lastTouchingPointerCount == 1) {
+ && lastFingerCount == 1) {
if (when <= mPointerGesture.tapDownTime + mConfig.pointerGestureTapInterval) {
float x, y;
mPointerController->getPosition(&x, &y);
@@ -4033,7 +4417,7 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when,
}
}
- mPointerGesture.pointerVelocityControl.reset();
+ mPointerVelocityControl.reset();
if (!tapped) {
#if DEBUG_GESTURES
@@ -4043,7 +4427,7 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when,
mPointerGesture.currentGestureMode = PointerGesture::NEUTRAL;
mPointerGesture.currentGestureIdBits.clear();
}
- } else if (currentTouchingPointerCount == 1) {
+ } else if (currentFingerCount == 1) {
// Case 4. Exactly one finger down, button is not pressed. (HOVER or TAP_DRAG)
// The pointer follows the active touch point.
// When in HOVER, emit HOVER_MOVE events at the pointer location.
@@ -4075,24 +4459,24 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when,
mPointerGesture.currentGestureMode = PointerGesture::TAP_DRAG;
}
- if (mLastRawPointerData.touchingIdBits.hasBit(activeTouchId)) {
+ if (mLastFingerIdBits.hasBit(activeTouchId)) {
const RawPointerData::Pointer& currentPointer =
mCurrentRawPointerData.pointerForId(activeTouchId);
const RawPointerData::Pointer& lastPointer =
mLastRawPointerData.pointerForId(activeTouchId);
float deltaX = (currentPointer.x - lastPointer.x)
- * mPointerGestureXMovementScale;
+ * mPointerXMovementScale;
float deltaY = (currentPointer.y - lastPointer.y)
- * mPointerGestureYMovementScale;
+ * mPointerYMovementScale;
rotateDelta(mSurfaceOrientation, &deltaX, &deltaY);
- mPointerGesture.pointerVelocityControl.move(when, &deltaX, &deltaY);
+ mPointerVelocityControl.move(when, &deltaX, &deltaY);
// Move the pointer using a relative motion.
// When using spots, the hover or drag will occur at the position of the anchor spot.
mPointerController->move(deltaX, deltaY);
} else {
- mPointerGesture.pointerVelocityControl.reset();
+ mPointerVelocityControl.reset();
}
bool down;
@@ -4128,7 +4512,7 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when,
mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE,
down ? 1.0f : 0.0f);
- if (lastTouchingPointerCount == 0 && currentTouchingPointerCount != 0) {
+ if (lastFingerCount == 0 && currentFingerCount != 0) {
mPointerGesture.resetTap();
mPointerGesture.tapDownTime = when;
mPointerGesture.tapX = x;
@@ -4156,7 +4540,7 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when,
&& mPointerGesture.lastGestureMode != PointerGesture::SWIPE
&& mPointerGesture.lastGestureMode != PointerGesture::FREEFORM) {
*outFinishPreviousGesture = true;
- } else if (!settled && currentTouchingPointerCount > lastTouchingPointerCount) {
+ } else if (!settled && currentFingerCount > lastFingerCount) {
// Additional pointers have gone down but not yet settled.
// Reset the gesture.
#if DEBUG_GESTURES
@@ -4175,7 +4559,7 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when,
mPointerGesture.currentGestureMode = PointerGesture::PRESS;
mPointerGesture.activeGestureId = 0;
mPointerGesture.referenceIdBits.clear();
- mPointerGesture.pointerVelocityControl.reset();
+ mPointerVelocityControl.reset();
// Use the centroid and pointer location as the reference points for the gesture.
#if DEBUG_GESTURES
@@ -4192,18 +4576,18 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when,
}
// Clear the reference deltas for fingers not yet included in the reference calculation.
- for (BitSet32 idBits(mCurrentRawPointerData.touchingIdBits.value
+ for (BitSet32 idBits(mCurrentFingerIdBits.value
& ~mPointerGesture.referenceIdBits.value); !idBits.isEmpty(); ) {
uint32_t id = idBits.clearFirstMarkedBit();
mPointerGesture.referenceDeltas[id].dx = 0;
mPointerGesture.referenceDeltas[id].dy = 0;
}
- mPointerGesture.referenceIdBits = mCurrentRawPointerData.touchingIdBits;
+ mPointerGesture.referenceIdBits = mCurrentFingerIdBits;
// Add delta for all fingers and calculate a common movement delta.
float commonDeltaX = 0, commonDeltaY = 0;
- BitSet32 commonIdBits(mLastRawPointerData.touchingIdBits.value
- & mCurrentRawPointerData.touchingIdBits.value);
+ BitSet32 commonIdBits(mLastFingerIdBits.value
+ & mCurrentFingerIdBits.value);
for (BitSet32 idBits(commonIdBits); !idBits.isEmpty(); ) {
bool first = (idBits == commonIdBits);
uint32_t id = idBits.clearFirstMarkedBit();
@@ -4229,8 +4613,8 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when,
for (BitSet32 idBits(mPointerGesture.referenceIdBits); !idBits.isEmpty(); ) {
uint32_t id = idBits.clearFirstMarkedBit();
PointerGesture::Delta& delta = mPointerGesture.referenceDeltas[id];
- dist[id] = hypotf(delta.dx * mPointerGestureXZoomScale,
- delta.dy * mPointerGestureYZoomScale);
+ dist[id] = hypotf(delta.dx * mPointerXZoomScale,
+ delta.dy * mPointerYZoomScale);
if (dist[id] > mConfig.pointerGestureMultitouchMinDistance) {
distOverThreshold += 1;
}
@@ -4239,17 +4623,17 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when,
// Only transition when at least two pointers have moved further than
// the minimum distance threshold.
if (distOverThreshold >= 2) {
- if (currentTouchingPointerCount > 2) {
+ if (currentFingerCount > 2) {
// There are more than two pointers, switch to FREEFORM.
#if DEBUG_GESTURES
LOGD("Gestures: PRESS transitioned to FREEFORM, number of pointers %d > 2",
- currentTouchingPointerCount);
+ currentFingerCount);
#endif
*outCancelPreviousGesture = true;
mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
} else {
// There are exactly two pointers.
- BitSet32 idBits(mCurrentRawPointerData.touchingIdBits);
+ BitSet32 idBits(mCurrentFingerIdBits);
uint32_t id1 = idBits.clearFirstMarkedBit();
uint32_t id2 = idBits.firstMarkedBit();
const RawPointerData::Pointer& p1 = mCurrentRawPointerData.pointerForId(id1);
@@ -4277,10 +4661,10 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when,
// approches 1.0. Recall that dot(v1, v2) = cos(angle) * mag(v1) * mag(v2).
PointerGesture::Delta& delta1 = mPointerGesture.referenceDeltas[id1];
PointerGesture::Delta& delta2 = mPointerGesture.referenceDeltas[id2];
- float dx1 = delta1.dx * mPointerGestureXZoomScale;
- float dy1 = delta1.dy * mPointerGestureYZoomScale;
- float dx2 = delta2.dx * mPointerGestureXZoomScale;
- float dy2 = delta2.dy * mPointerGestureYZoomScale;
+ float dx1 = delta1.dx * mPointerXZoomScale;
+ float dy1 = delta1.dy * mPointerYZoomScale;
+ float dx2 = delta2.dx * mPointerXZoomScale;
+ float dy2 = delta2.dy * mPointerYZoomScale;
float dot = dx1 * dx2 + dy1 * dy2;
float cosine = dot / (dist1 * dist2); // denominator always > 0
if (cosine >= mConfig.pointerGestureSwipeTransitionAngleCosine) {
@@ -4314,10 +4698,10 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when,
} else if (mPointerGesture.currentGestureMode == PointerGesture::SWIPE) {
// Switch from SWIPE to FREEFORM if additional pointers go down.
// Cancel previous gesture.
- if (currentTouchingPointerCount > 2) {
+ if (currentFingerCount > 2) {
#if DEBUG_GESTURES
LOGD("Gestures: SWIPE transitioned to FREEFORM, number of pointers %d > 2",
- currentTouchingPointerCount);
+ currentFingerCount);
#endif
*outCancelPreviousGesture = true;
mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
@@ -4338,11 +4722,11 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when,
mPointerGesture.referenceTouchX += commonDeltaX;
mPointerGesture.referenceTouchY += commonDeltaY;
- commonDeltaX *= mPointerGestureXMovementScale;
- commonDeltaY *= mPointerGestureYMovementScale;
+ commonDeltaX *= mPointerXMovementScale;
+ commonDeltaY *= mPointerYMovementScale;
rotateDelta(mSurfaceOrientation, &commonDeltaX, &commonDeltaY);
- mPointerGesture.pointerVelocityControl.move(when, &commonDeltaX, &commonDeltaY);
+ mPointerVelocityControl.move(when, &commonDeltaX, &commonDeltaY);
mPointerGesture.referenceGestureX += commonDeltaX;
mPointerGesture.referenceGestureY += commonDeltaY;
@@ -4355,7 +4739,7 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when,
#if DEBUG_GESTURES
LOGD("Gestures: PRESS or SWIPE activeTouchId=%d,"
"activeGestureId=%d, currentTouchPointerCount=%d",
- activeTouchId, mPointerGesture.activeGestureId, currentTouchingPointerCount);
+ activeTouchId, mPointerGesture.activeGestureId, currentFingerCount);
#endif
LOG_ASSERT(mPointerGesture.activeGestureId >= 0);
@@ -4377,7 +4761,7 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when,
#if DEBUG_GESTURES
LOGD("Gestures: FREEFORM activeTouchId=%d,"
"activeGestureId=%d, currentTouchPointerCount=%d",
- activeTouchId, mPointerGesture.activeGestureId, currentTouchingPointerCount);
+ activeTouchId, mPointerGesture.activeGestureId, currentFingerCount);
#endif
LOG_ASSERT(mPointerGesture.activeGestureId >= 0);
@@ -4399,14 +4783,14 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when,
} else {
// Otherwise, assume we mapped all touches from the previous frame.
// Reuse all mappings that are still applicable.
- mappedTouchIdBits.value = mLastRawPointerData.touchingIdBits.value
- & mCurrentRawPointerData.touchingIdBits.value;
+ mappedTouchIdBits.value = mLastFingerIdBits.value
+ & mCurrentFingerIdBits.value;
usedGestureIdBits = mPointerGesture.lastGestureIdBits;
// Check whether we need to choose a new active gesture id because the
// current went went up.
- for (BitSet32 upTouchIdBits(mLastRawPointerData.touchingIdBits.value
- & ~mCurrentRawPointerData.touchingIdBits.value);
+ for (BitSet32 upTouchIdBits(mLastFingerIdBits.value
+ & ~mCurrentFingerIdBits.value);
!upTouchIdBits.isEmpty(); ) {
uint32_t upTouchId = upTouchIdBits.clearFirstMarkedBit();
uint32_t upGestureId = mPointerGesture.freeformTouchToGestureIdMap[upTouchId];
@@ -4425,8 +4809,8 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when,
mPointerGesture.activeGestureId);
#endif
- BitSet32 idBits(mCurrentRawPointerData.touchingIdBits);
- for (uint32_t i = 0; i < currentTouchingPointerCount; i++) {
+ BitSet32 idBits(mCurrentFingerIdBits);
+ for (uint32_t i = 0; i < currentFingerCount; i++) {
uint32_t touchId = idBits.clearFirstMarkedBit();
uint32_t gestureId;
if (!mappedTouchIdBits.hasBit(touchId)) {
@@ -4451,9 +4835,9 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when,
const RawPointerData::Pointer& pointer =
mCurrentRawPointerData.pointerForId(touchId);
float deltaX = (pointer.x - mPointerGesture.referenceTouchX)
- * mPointerGestureXZoomScale;
+ * mPointerXZoomScale;
float deltaY = (pointer.y - mPointerGesture.referenceTouchY)
- * mPointerGestureYZoomScale;
+ * mPointerYZoomScale;
rotateDelta(mSurfaceOrientation, &deltaX, &deltaY);
mPointerGesture.currentGestureProperties[i].clear();
@@ -4517,6 +4901,215 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when,
return true;
}
+void TouchInputMapper::dispatchPointerStylus(nsecs_t when, uint32_t policyFlags) {
+ mPointerSimple.currentCoords.clear();
+ mPointerSimple.currentProperties.clear();
+
+ bool down, hovering;
+ if (!mCurrentStylusIdBits.isEmpty()) {
+ uint32_t id = mCurrentStylusIdBits.firstMarkedBit();
+ uint32_t index = mCurrentCookedPointerData.idToIndex[id];
+ float x = mCurrentCookedPointerData.pointerCoords[index].getX();
+ float y = mCurrentCookedPointerData.pointerCoords[index].getY();
+ mPointerController->setPosition(x, y);
+
+ hovering = mCurrentCookedPointerData.hoveringIdBits.hasBit(id);
+ down = !hovering;
+
+ mPointerController->getPosition(&x, &y);
+ mPointerSimple.currentCoords.copyFrom(mCurrentCookedPointerData.pointerCoords[index]);
+ mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
+ mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
+ mPointerSimple.currentProperties.id = 0;
+ mPointerSimple.currentProperties.toolType =
+ mCurrentCookedPointerData.pointerProperties[index].toolType;
+ } else {
+ down = false;
+ hovering = false;
+ }
+
+ dispatchPointerSimple(when, policyFlags, down, hovering);
+}
+
+void TouchInputMapper::abortPointerStylus(nsecs_t when, uint32_t policyFlags) {
+ abortPointerSimple(when, policyFlags);
+}
+
+void TouchInputMapper::dispatchPointerMouse(nsecs_t when, uint32_t policyFlags) {
+ mPointerSimple.currentCoords.clear();
+ mPointerSimple.currentProperties.clear();
+
+ bool down, hovering;
+ if (!mCurrentMouseIdBits.isEmpty()) {
+ uint32_t id = mCurrentMouseIdBits.firstMarkedBit();
+ uint32_t currentIndex = mCurrentRawPointerData.idToIndex[id];
+ if (mLastMouseIdBits.hasBit(id)) {
+ uint32_t lastIndex = mCurrentRawPointerData.idToIndex[id];
+ float deltaX = (mCurrentRawPointerData.pointers[currentIndex].x
+ - mLastRawPointerData.pointers[lastIndex].x)
+ * mPointerXMovementScale;
+ float deltaY = (mCurrentRawPointerData.pointers[currentIndex].y
+ - mLastRawPointerData.pointers[lastIndex].y)
+ * mPointerYMovementScale;
+
+ rotateDelta(mSurfaceOrientation, &deltaX, &deltaY);
+ mPointerVelocityControl.move(when, &deltaX, &deltaY);
+
+ mPointerController->move(deltaX, deltaY);
+ } else {
+ mPointerVelocityControl.reset();
+ }
+
+ down = isPointerDown(mCurrentButtonState);
+ hovering = !down;
+
+ float x, y;
+ mPointerController->getPosition(&x, &y);
+ mPointerSimple.currentCoords.copyFrom(
+ mCurrentCookedPointerData.pointerCoords[currentIndex]);
+ mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
+ mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
+ mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE,
+ hovering ? 0.0f : 1.0f);
+ mPointerSimple.currentProperties.id = 0;
+ mPointerSimple.currentProperties.toolType =
+ mCurrentCookedPointerData.pointerProperties[currentIndex].toolType;
+ } else {
+ mPointerVelocityControl.reset();
+
+ down = false;
+ hovering = false;
+ }
+
+ dispatchPointerSimple(when, policyFlags, down, hovering);
+}
+
+void TouchInputMapper::abortPointerMouse(nsecs_t when, uint32_t policyFlags) {
+ abortPointerSimple(when, policyFlags);
+
+ mPointerVelocityControl.reset();
+}
+
+void TouchInputMapper::dispatchPointerSimple(nsecs_t when, uint32_t policyFlags,
+ bool down, bool hovering) {
+ int32_t metaState = getContext()->getGlobalMetaState();
+
+ if (mPointerController != NULL) {
+ if (down || hovering) {
+ mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_POINTER);
+ mPointerController->clearSpots();
+ mPointerController->setButtonState(mCurrentButtonState);
+ mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
+ } else if (!down && !hovering && (mPointerSimple.down || mPointerSimple.hovering)) {
+ mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
+ }
+ }
+
+ if (mPointerSimple.down && !down) {
+ mPointerSimple.down = false;
+
+ // Send up.
+ NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
+ AMOTION_EVENT_ACTION_UP, 0, metaState, mLastButtonState, 0,
+ 1, &mPointerSimple.lastProperties, &mPointerSimple.lastCoords,
+ mOrientedXPrecision, mOrientedYPrecision,
+ mPointerSimple.downTime);
+ getListener()->notifyMotion(&args);
+ }
+
+ if (mPointerSimple.hovering && !hovering) {
+ mPointerSimple.hovering = false;
+
+ // Send hover exit.
+ NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
+ AMOTION_EVENT_ACTION_HOVER_EXIT, 0, metaState, mLastButtonState, 0,
+ 1, &mPointerSimple.lastProperties, &mPointerSimple.lastCoords,
+ mOrientedXPrecision, mOrientedYPrecision,
+ mPointerSimple.downTime);
+ getListener()->notifyMotion(&args);
+ }
+
+ if (down) {
+ if (!mPointerSimple.down) {
+ mPointerSimple.down = true;
+ mPointerSimple.downTime = when;
+
+ // Send down.
+ NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
+ AMOTION_EVENT_ACTION_DOWN, 0, metaState, mCurrentButtonState, 0,
+ 1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
+ mOrientedXPrecision, mOrientedYPrecision,
+ mPointerSimple.downTime);
+ getListener()->notifyMotion(&args);
+ }
+
+ // Send move.
+ NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
+ AMOTION_EVENT_ACTION_MOVE, 0, metaState, mCurrentButtonState, 0,
+ 1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
+ mOrientedXPrecision, mOrientedYPrecision,
+ mPointerSimple.downTime);
+ getListener()->notifyMotion(&args);
+ }
+
+ if (hovering) {
+ if (!mPointerSimple.hovering) {
+ mPointerSimple.hovering = true;
+
+ // Send hover enter.
+ NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
+ AMOTION_EVENT_ACTION_HOVER_ENTER, 0, metaState, mCurrentButtonState, 0,
+ 1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
+ mOrientedXPrecision, mOrientedYPrecision,
+ mPointerSimple.downTime);
+ getListener()->notifyMotion(&args);
+ }
+
+ // Send hover move.
+ NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
+ AMOTION_EVENT_ACTION_HOVER_MOVE, 0, metaState, mCurrentButtonState, 0,
+ 1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
+ mOrientedXPrecision, mOrientedYPrecision,
+ mPointerSimple.downTime);
+ getListener()->notifyMotion(&args);
+ }
+
+ if (mCurrentRawVScroll || mCurrentRawHScroll) {
+ float vscroll = mCurrentRawVScroll;
+ float hscroll = mCurrentRawHScroll;
+ mWheelYVelocityControl.move(when, NULL, &vscroll);
+ mWheelXVelocityControl.move(when, &hscroll, NULL);
+
+ // Send scroll.
+ PointerCoords pointerCoords;
+ pointerCoords.copyFrom(mPointerSimple.currentCoords);
+ pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_VSCROLL, vscroll);
+ pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, hscroll);
+
+ NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
+ AMOTION_EVENT_ACTION_SCROLL, 0, metaState, mCurrentButtonState, 0,
+ 1, &mPointerSimple.currentProperties, &pointerCoords,
+ mOrientedXPrecision, mOrientedYPrecision,
+ mPointerSimple.downTime);
+ getListener()->notifyMotion(&args);
+ }
+
+ // Save state.
+ if (down || hovering) {
+ mPointerSimple.lastCoords.copyFrom(mPointerSimple.currentCoords);
+ mPointerSimple.lastProperties.copyFrom(mPointerSimple.currentProperties);
+ } else {
+ mPointerSimple.reset();
+ }
+}
+
+void TouchInputMapper::abortPointerSimple(nsecs_t when, uint32_t policyFlags) {
+ mPointerSimple.currentCoords.clear();
+ mPointerSimple.currentProperties.clear();
+
+ dispatchPointerSimple(when, policyFlags, false, false);
+}
+
void TouchInputMapper::dispatchMotion(nsecs_t when, uint32_t policyFlags, uint32_t source,
int32_t action, int32_t flags, int32_t metaState, int32_t buttonState, int32_t edgeFlags,
const PointerProperties* properties, const PointerCoords* coords,
@@ -4862,44 +5455,32 @@ bool TouchInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCode
SingleTouchInputMapper::SingleTouchInputMapper(InputDevice* device) :
TouchInputMapper(device) {
- clearState();
}
SingleTouchInputMapper::~SingleTouchInputMapper() {
}
-void SingleTouchInputMapper::clearState() {
- mCursorButtonAccumulator.clearButtons();
- mTouchButtonAccumulator.clearButtons();
- mSingleTouchMotionAccumulator.clearAbsoluteAxes();
-}
+void SingleTouchInputMapper::reset(nsecs_t when) {
+ mSingleTouchMotionAccumulator.reset(getDevice());
-void SingleTouchInputMapper::reset() {
- TouchInputMapper::reset();
-
- clearState();
- }
+ TouchInputMapper::reset(when);
+}
void SingleTouchInputMapper::process(const RawEvent* rawEvent) {
- mCursorButtonAccumulator.process(rawEvent);
- mTouchButtonAccumulator.process(rawEvent);
- mSingleTouchMotionAccumulator.process(rawEvent);
+ TouchInputMapper::process(rawEvent);
- if (rawEvent->type == EV_SYN && rawEvent->scanCode == SYN_REPORT) {
- sync(rawEvent->when);
- }
+ mSingleTouchMotionAccumulator.process(rawEvent);
}
-void SingleTouchInputMapper::sync(nsecs_t when) {
- mCurrentRawPointerData.clear();
- mCurrentButtonState = 0;
-
+void SingleTouchInputMapper::syncTouch(nsecs_t when, bool* outHavePointerIds) {
if (mTouchButtonAccumulator.isToolActive()) {
mCurrentRawPointerData.pointerCount = 1;
mCurrentRawPointerData.idToIndex[0] = 0;
- bool isHovering = mTouchButtonAccumulator.isHovering()
- || mSingleTouchMotionAccumulator.getAbsoluteDistance() > 0;
+ bool isHovering = mTouchButtonAccumulator.getToolType() != AMOTION_EVENT_TOOL_TYPE_MOUSE
+ && (mTouchButtonAccumulator.isHovering()
+ || (mRawPointerAxes.pressure.valid
+ && mSingleTouchMotionAccumulator.getAbsolutePressure() <= 0));
mCurrentRawPointerData.markIdBit(0, isHovering);
RawPointerData::Pointer& outPointer = mCurrentRawPointerData.pointers[0];
@@ -4913,29 +5494,26 @@ void SingleTouchInputMapper::sync(nsecs_t when) {
outPointer.toolMinor = mSingleTouchMotionAccumulator.getAbsoluteToolWidth();
outPointer.orientation = 0;
outPointer.distance = mSingleTouchMotionAccumulator.getAbsoluteDistance();
+ outPointer.tiltX = mSingleTouchMotionAccumulator.getAbsoluteTiltX();
+ outPointer.tiltY = mSingleTouchMotionAccumulator.getAbsoluteTiltY();
outPointer.toolType = mTouchButtonAccumulator.getToolType();
if (outPointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
outPointer.toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
}
outPointer.isHovering = isHovering;
}
-
- mCurrentButtonState = mTouchButtonAccumulator.getButtonState()
- | mCursorButtonAccumulator.getButtonState();
-
- syncTouch(when, true);
}
void SingleTouchInputMapper::configureRawPointerAxes() {
TouchInputMapper::configureRawPointerAxes();
- mTouchButtonAccumulator.configure(getDevice());
-
getAbsoluteAxisInfo(ABS_X, &mRawPointerAxes.x);
getAbsoluteAxisInfo(ABS_Y, &mRawPointerAxes.y);
getAbsoluteAxisInfo(ABS_PRESSURE, &mRawPointerAxes.pressure);
getAbsoluteAxisInfo(ABS_TOOL_WIDTH, &mRawPointerAxes.toolMajor);
getAbsoluteAxisInfo(ABS_DISTANCE, &mRawPointerAxes.distance);
+ getAbsoluteAxisInfo(ABS_TILT_X, &mRawPointerAxes.tiltX);
+ getAbsoluteAxisInfo(ABS_TILT_Y, &mRawPointerAxes.tiltY);
}
@@ -4948,58 +5526,25 @@ MultiTouchInputMapper::MultiTouchInputMapper(InputDevice* device) :
MultiTouchInputMapper::~MultiTouchInputMapper() {
}
-void MultiTouchInputMapper::clearState() {
- mCursorButtonAccumulator.clearButtons();
- mTouchButtonAccumulator.clearButtons();
- mPointerIdBits.clear();
+void MultiTouchInputMapper::reset(nsecs_t when) {
+ mMultiTouchMotionAccumulator.reset(getDevice());
- if (mMultiTouchMotionAccumulator.isUsingSlotsProtocol()) {
- // Query the driver for the current slot index and use it as the initial slot
- // before we start reading events from the device. It is possible that the
- // current slot index will not be the same as it was when the first event was
- // written into the evdev buffer, which means the input mapper could start
- // out of sync with the initial state of the events in the evdev buffer.
- // In the extremely unlikely case that this happens, the data from
- // two slots will be confused until the next ABS_MT_SLOT event is received.
- // This can cause the touch point to "jump", but at least there will be
- // no stuck touches.
- int32_t initialSlot;
- status_t status = getEventHub()->getAbsoluteAxisValue(getDeviceId(), ABS_MT_SLOT,
- &initialSlot);
- if (status) {
- LOGW("Could not retrieve current multitouch slot index. status=%d", status);
- initialSlot = -1;
- }
- mMultiTouchMotionAccumulator.clearSlots(initialSlot);
- } else {
- mMultiTouchMotionAccumulator.clearSlots(-1);
- }
-}
-
-void MultiTouchInputMapper::reset() {
- TouchInputMapper::reset();
+ mPointerIdBits.clear();
- clearState();
+ TouchInputMapper::reset(when);
}
void MultiTouchInputMapper::process(const RawEvent* rawEvent) {
- mCursorButtonAccumulator.process(rawEvent);
- mTouchButtonAccumulator.process(rawEvent);
- mMultiTouchMotionAccumulator.process(rawEvent);
+ TouchInputMapper::process(rawEvent);
- if (rawEvent->type == EV_SYN && rawEvent->scanCode == SYN_REPORT) {
- sync(rawEvent->when);
- }
+ mMultiTouchMotionAccumulator.process(rawEvent);
}
-void MultiTouchInputMapper::sync(nsecs_t when) {
+void MultiTouchInputMapper::syncTouch(nsecs_t when, bool* outHavePointerIds) {
size_t inCount = mMultiTouchMotionAccumulator.getSlotCount();
size_t outCount = 0;
- bool havePointerIds = true;
BitSet32 newPointerIdBits;
- mCurrentRawPointerData.clear();
-
for (size_t inIndex = 0; inIndex < inCount; inIndex++) {
const MultiTouchMotionAccumulator::Slot* inSlot =
mMultiTouchMotionAccumulator.getSlot(inIndex);
@@ -5026,6 +5571,8 @@ void MultiTouchInputMapper::sync(nsecs_t when) {
outPointer.toolMinor = inSlot->getToolMinor();
outPointer.orientation = inSlot->getOrientation();
outPointer.distance = inSlot->getDistance();
+ outPointer.tiltX = 0;
+ outPointer.tiltY = 0;
outPointer.toolType = inSlot->getToolType();
if (outPointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
@@ -5035,12 +5582,13 @@ void MultiTouchInputMapper::sync(nsecs_t when) {
}
}
- bool isHovering = mTouchButtonAccumulator.isHovering()
- || inSlot->getDistance() > 0;
+ bool isHovering = mTouchButtonAccumulator.getToolType() != AMOTION_EVENT_TOOL_TYPE_MOUSE
+ && (mTouchButtonAccumulator.isHovering()
+ || (mRawPointerAxes.pressure.valid && inSlot->getPressure() <= 0));
outPointer.isHovering = isHovering;
// Assign pointer id using tracking id if available.
- if (havePointerIds) {
+ if (*outHavePointerIds) {
int32_t trackingId = inSlot->getTrackingId();
int32_t id = -1;
if (trackingId >= 0) {
@@ -5057,7 +5605,7 @@ void MultiTouchInputMapper::sync(nsecs_t when) {
}
}
if (id < 0) {
- havePointerIds = false;
+ *outHavePointerIds = false;
mCurrentRawPointerData.clearIdBits();
newPointerIdBits.clear();
} else {
@@ -5072,23 +5620,14 @@ void MultiTouchInputMapper::sync(nsecs_t when) {
}
mCurrentRawPointerData.pointerCount = outCount;
- mCurrentButtonState = mTouchButtonAccumulator.getButtonState()
- | mCursorButtonAccumulator.getButtonState();
-
mPointerIdBits = newPointerIdBits;
- syncTouch(when, havePointerIds);
-
- if (!mMultiTouchMotionAccumulator.isUsingSlotsProtocol()) {
- mMultiTouchMotionAccumulator.clearSlots(-1);
- }
+ mMultiTouchMotionAccumulator.finishSync();
}
void MultiTouchInputMapper::configureRawPointerAxes() {
TouchInputMapper::configureRawPointerAxes();
- mTouchButtonAccumulator.configure(getDevice());
-
getAbsoluteAxisInfo(ABS_MT_POSITION_X, &mRawPointerAxes.x);
getAbsoluteAxisInfo(ABS_MT_POSITION_Y, &mRawPointerAxes.y);
getAbsoluteAxisInfo(ABS_MT_TOUCH_MAJOR, &mRawPointerAxes.touchMajor);
@@ -5115,8 +5654,6 @@ void MultiTouchInputMapper::configureRawPointerAxes() {
} else {
mMultiTouchMotionAccumulator.configure(MAX_POINTERS, false /*usingSlotsProtocol*/);
}
-
- clearState();
}
@@ -5184,8 +5721,9 @@ void JoystickInputMapper::dump(String8& dump) {
}
}
-void JoystickInputMapper::configure(const InputReaderConfiguration* config, uint32_t changes) {
- InputMapper::configure(config, changes);
+void JoystickInputMapper::configure(nsecs_t when,
+ const InputReaderConfiguration* config, uint32_t changes) {
+ InputMapper::configure(when, config, changes);
if (!changes) { // first time only
// Collect all axes.
@@ -5314,19 +5852,15 @@ bool JoystickInputMapper::isCenteredAxis(int32_t axis) {
}
}
-void JoystickInputMapper::reset() {
+void JoystickInputMapper::reset(nsecs_t when) {
// Recenter all axes.
- nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
-
size_t numAxes = mAxes.size();
for (size_t i = 0; i < numAxes; i++) {
Axis& axis = mAxes.editValueAt(i);
axis.resetValue();
}
- sync(when, true /*force*/);
-
- InputMapper::reset();
+ InputMapper::reset(when);
}
void JoystickInputMapper::process(const RawEvent* rawEvent) {
diff --git a/services/input/InputReader.h b/services/input/InputReader.h
index 72802fc..76d77f1 100644
--- a/services/input/InputReader.h
+++ b/services/input/InputReader.h
@@ -53,6 +53,9 @@ struct InputReaderConfiguration {
// The pointer gesture control changed.
CHANGE_POINTER_GESTURE_ENABLEMENT = 1 << 1,
+ // The display size or orientation changed.
+ CHANGE_DISPLAY_INFO = 1 << 2,
+
// All devices must be reopened.
CHANGE_MUST_REOPEN = 1 << 31,
};
@@ -153,6 +156,26 @@ struct InputReaderConfiguration {
pointerGestureSwipeMaxWidthRatio(0.25f),
pointerGestureMovementSpeedRatio(0.8f),
pointerGestureZoomSpeedRatio(0.3f) { }
+
+ bool getDisplayInfo(int32_t displayId, bool external,
+ int32_t* width, int32_t* height, int32_t* orientation) const;
+
+ void setDisplayInfo(int32_t displayId, bool external,
+ int32_t width, int32_t height, int32_t orientation);
+
+private:
+ struct DisplayInfo {
+ int32_t width;
+ int32_t height;
+ int32_t orientation;
+
+ DisplayInfo() :
+ width(-1), height(-1), orientation(DISPLAY_ORIENTATION_0) {
+ }
+ };
+
+ DisplayInfo mInternalDisplay;
+ DisplayInfo mExternalDisplay;
};
@@ -174,22 +197,6 @@ protected:
virtual ~InputReaderPolicyInterface() { }
public:
- /* Display orientations. */
- enum {
- ROTATION_0 = 0,
- ROTATION_90 = 1,
- ROTATION_180 = 2,
- ROTATION_270 = 3
- };
-
- /* Gets information about the display with the specified id.
- * If external is true, returns the size of the external mirrored
- * counterpart of the specified display.
- * Returns true if the display info is available, false otherwise.
- */
- virtual bool getDisplayInfo(int32_t displayId, bool external,
- int32_t* width, int32_t* height, int32_t* orientation) = 0;
-
/* Gets the input reader configuration. */
virtual void getReaderConfiguration(InputReaderConfiguration* outConfig) = 0;
@@ -364,8 +371,8 @@ private:
// low-level input event decoding and device management
void processEventsLocked(const RawEvent* rawEvents, size_t count);
- void addDeviceLocked(int32_t deviceId);
- void removeDeviceLocked(int32_t deviceId);
+ void addDeviceLocked(nsecs_t when, int32_t deviceId);
+ void removeDeviceLocked(nsecs_t when, int32_t deviceId);
void processEventsForDeviceLocked(int32_t deviceId, const RawEvent* rawEvents, size_t count);
void timeoutExpiredLocked(nsecs_t when);
@@ -431,8 +438,8 @@ public:
void dump(String8& dump);
void addMapper(InputMapper* mapper);
- void configure(const InputReaderConfiguration* config, uint32_t changes);
- void reset();
+ void configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes);
+ void reset(nsecs_t when);
void process(const RawEvent* rawEvents, size_t count);
void timeoutExpired(nsecs_t when);
@@ -447,9 +454,25 @@ public:
void fadePointer();
+ void notifyReset(nsecs_t when);
+
inline const PropertyMap& getConfiguration() { return mConfiguration; }
inline EventHubInterface* getEventHub() { return mContext->getEventHub(); }
+ bool hasKey(int32_t code) {
+ return getEventHub()->hasScanCode(mId, code);
+ }
+
+ bool isKeyPressed(int32_t code) {
+ return getEventHub()->getScanCodeState(mId, code) == AKEY_STATE_DOWN;
+ }
+
+ int32_t getAbsoluteAxisValue(int32_t code) {
+ int32_t value;
+ getEventHub()->getAbsoluteAxisValue(mId, code, &value);
+ return value;
+ }
+
private:
InputReaderContext* mContext;
int32_t mId;
@@ -472,8 +495,8 @@ private:
class CursorButtonAccumulator {
public:
CursorButtonAccumulator();
+ void reset(InputDevice* device);
- void clearButtons();
void process(const RawEvent* rawEvent);
uint32_t getButtonState() const;
@@ -487,6 +510,8 @@ private:
bool mBtnForward;
bool mBtnExtra;
bool mBtnTask;
+
+ void clearButtons();
};
@@ -495,10 +520,32 @@ private:
class CursorMotionAccumulator {
public:
CursorMotionAccumulator();
- void configure(InputDevice* device);
+ void reset(InputDevice* device);
+
+ void process(const RawEvent* rawEvent);
+ void finishSync();
+
+ inline int32_t getRelativeX() const { return mRelX; }
+ inline int32_t getRelativeY() const { return mRelY; }
+
+private:
+ int32_t mRelX;
+ int32_t mRelY;
void clearRelativeAxes();
+};
+
+
+/* Keeps track of cursor scrolling motions. */
+
+class CursorScrollAccumulator {
+public:
+ CursorScrollAccumulator();
+ void configure(InputDevice* device);
+ void reset(InputDevice* device);
+
void process(const RawEvent* rawEvent);
+ void finishSync();
inline bool haveRelativeVWheel() const { return mHaveRelWheel; }
inline bool haveRelativeHWheel() const { return mHaveRelHWheel; }
@@ -516,6 +563,8 @@ private:
int32_t mRelY;
int32_t mRelWheel;
int32_t mRelHWheel;
+
+ void clearRelativeAxes();
};
@@ -524,8 +573,8 @@ class TouchButtonAccumulator {
public:
TouchButtonAccumulator();
void configure(InputDevice* device);
+ void reset(InputDevice* device);
- void clearButtons();
void process(const RawEvent* rawEvent);
uint32_t getButtonState() const;
@@ -542,6 +591,13 @@ private:
bool mBtnToolFinger;
bool mBtnToolPen;
bool mBtnToolRubber;
+ bool mBtnToolBrush;
+ bool mBtnToolPencil;
+ bool mBtnToolAirbrush;
+ bool mBtnToolMouse;
+ bool mBtnToolLens;
+
+ void clearButtons();
};
@@ -556,6 +612,8 @@ struct RawPointerAxes {
RawAbsoluteAxisInfo toolMinor;
RawAbsoluteAxisInfo orientation;
RawAbsoluteAxisInfo distance;
+ RawAbsoluteAxisInfo tiltX;
+ RawAbsoluteAxisInfo tiltY;
RawAbsoluteAxisInfo trackingId;
RawAbsoluteAxisInfo slot;
@@ -577,6 +635,8 @@ struct RawPointerData {
int32_t toolMinor;
int32_t orientation;
int32_t distance;
+ int32_t tiltX;
+ int32_t tiltY;
int32_t toolType; // a fully decoded AMOTION_EVENT_TOOL_TYPE constant
bool isHovering;
};
@@ -637,14 +697,16 @@ class SingleTouchMotionAccumulator {
public:
SingleTouchMotionAccumulator();
- void clearAbsoluteAxes();
void process(const RawEvent* rawEvent);
+ void reset(InputDevice* device);
inline int32_t getAbsoluteX() const { return mAbsX; }
inline int32_t getAbsoluteY() const { return mAbsY; }
inline int32_t getAbsolutePressure() const { return mAbsPressure; }
inline int32_t getAbsoluteToolWidth() const { return mAbsToolWidth; }
inline int32_t getAbsoluteDistance() const { return mAbsDistance; }
+ inline int32_t getAbsoluteTiltX() const { return mAbsTiltX; }
+ inline int32_t getAbsoluteTiltY() const { return mAbsTiltY; }
private:
int32_t mAbsX;
@@ -652,6 +714,10 @@ private:
int32_t mAbsPressure;
int32_t mAbsToolWidth;
int32_t mAbsDistance;
+ int32_t mAbsTiltX;
+ int32_t mAbsTiltY;
+
+ void clearAbsoluteAxes();
};
@@ -703,11 +769,10 @@ public:
~MultiTouchMotionAccumulator();
void configure(size_t slotCount, bool usingSlotsProtocol);
+ void reset(InputDevice* device);
void process(const RawEvent* rawEvent);
+ void finishSync();
- void clearSlots(int32_t initialSlot);
-
- inline bool isUsingSlotsProtocol() const { return mUsingSlotsProtocol; }
inline size_t getSlotCount() const { return mSlotCount; }
inline const Slot* getSlot(size_t index) const { return &mSlots[index]; }
@@ -716,12 +781,22 @@ private:
Slot* mSlots;
size_t mSlotCount;
bool mUsingSlotsProtocol;
+
+ void clearSlots(int32_t initialSlot);
};
/* An input mapper transforms raw input events into cooked event data.
* A single input device can have multiple associated input mappers in order to interpret
* different classes of events.
+ *
+ * InputMapper lifecycle:
+ * - create
+ * - configure with 0 changes
+ * - reset
+ * - process, process, process (may occasionally reconfigure with non-zero changes or reset)
+ * - reset
+ * - destroy
*/
class InputMapper {
public:
@@ -739,8 +814,8 @@ public:
virtual uint32_t getSources() = 0;
virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo);
virtual void dump(String8& dump);
- virtual void configure(const InputReaderConfiguration* config, uint32_t changes);
- virtual void reset();
+ virtual void configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes);
+ virtual void reset(nsecs_t when);
virtual void process(const RawEvent* rawEvent) = 0;
virtual void timeoutExpired(nsecs_t when);
@@ -788,8 +863,8 @@ public:
virtual uint32_t getSources();
virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo);
virtual void dump(String8& dump);
- virtual void configure(const InputReaderConfiguration* config, uint32_t changes);
- virtual void reset();
+ virtual void configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes);
+ virtual void reset(nsecs_t when);
virtual void process(const RawEvent* rawEvent);
virtual int32_t getKeyCodeState(uint32_t sourceMask, int32_t keyCode);
@@ -800,8 +875,6 @@ public:
virtual int32_t getMetaState();
private:
- Mutex mLock;
-
struct KeyDown {
int32_t keyCode;
int32_t scanCode;
@@ -810,6 +883,8 @@ private:
uint32_t mSource;
int32_t mKeyboardType;
+ int32_t mOrientation; // orientation for dpad keys
+
Vector<KeyDown> mKeyDowns; // keys that are down
int32_t mMetaState;
nsecs_t mDownTime; // time of most recent key down
@@ -828,8 +903,6 @@ private:
bool orientationAware;
} mParameters;
- void initialize();
-
void configureParameters();
void dumpParameters(String8& dump);
@@ -856,8 +929,8 @@ public:
virtual uint32_t getSources();
virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo);
virtual void dump(String8& dump);
- virtual void configure(const InputReaderConfiguration* config, uint32_t changes);
- virtual void reset();
+ virtual void configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes);
+ virtual void reset(nsecs_t when);
virtual void process(const RawEvent* rawEvent);
virtual int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode);
@@ -882,6 +955,7 @@ private:
CursorButtonAccumulator mCursorButtonAccumulator;
CursorMotionAccumulator mCursorMotionAccumulator;
+ CursorScrollAccumulator mCursorScrollAccumulator;
int32_t mSource;
float mXScale;
@@ -898,13 +972,13 @@ private:
VelocityControl mWheelXVelocityControl;
VelocityControl mWheelYVelocityControl;
+ int32_t mOrientation;
+
sp<PointerControllerInterface> mPointerController;
int32_t mButtonState;
nsecs_t mDownTime;
- void initialize();
-
void configureParameters();
void dumpParameters(String8& dump);
@@ -920,8 +994,9 @@ public:
virtual uint32_t getSources();
virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo);
virtual void dump(String8& dump);
- virtual void configure(const InputReaderConfiguration* config, uint32_t changes);
- virtual void reset();
+ virtual void configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes);
+ virtual void reset(nsecs_t when);
+ virtual void process(const RawEvent* rawEvent);
virtual int32_t getKeyCodeState(uint32_t sourceMask, int32_t keyCode);
virtual int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode);
@@ -932,6 +1007,10 @@ public:
virtual void timeoutExpired(nsecs_t when);
protected:
+ CursorButtonAccumulator mCursorButtonAccumulator;
+ CursorScrollAccumulator mCursorScrollAccumulator;
+ TouchButtonAccumulator mTouchButtonAccumulator;
+
struct VirtualKey {
int32_t keyCode;
int32_t scanCode;
@@ -948,9 +1027,16 @@ protected:
}
};
- // Input sources supported by the device.
- uint32_t mTouchSource; // sources when reporting touch data
- uint32_t mPointerSource; // sources when reporting pointer gestures
+ // Input sources and device mode.
+ uint32_t mSource;
+
+ enum DeviceMode {
+ DEVICE_MODE_DISABLED, // input is disabled
+ DEVICE_MODE_DIRECT, // direct mapping (touchscreen)
+ DEVICE_MODE_UNSCALED, // unscaled mapping (touchpad)
+ DEVICE_MODE_POINTER, // pointer mapping (pointer)
+ };
+ DeviceMode mDeviceMode;
// The reader's configuration.
InputReaderConfiguration mConfig;
@@ -1053,6 +1139,18 @@ protected:
int32_t mCurrentButtonState;
int32_t mLastButtonState;
+ // Scroll state.
+ int32_t mCurrentRawVScroll;
+ int32_t mCurrentRawHScroll;
+
+ // Id bits used to differentiate fingers, stylus and mouse tools.
+ BitSet32 mCurrentFingerIdBits; // finger or unknown
+ BitSet32 mLastFingerIdBits;
+ BitSet32 mCurrentStylusIdBits; // stylus or eraser
+ BitSet32 mLastStylusIdBits;
+ BitSet32 mCurrentMouseIdBits; // mouse or lens
+ BitSet32 mLastMouseIdBits;
+
// True if we sent a HOVER_ENTER event.
bool mSentHoverEnter;
@@ -1068,7 +1166,7 @@ protected:
virtual void dumpParameters(String8& dump);
virtual void configureRawPointerAxes();
virtual void dumpRawPointerAxes(String8& dump);
- virtual bool configureSurface();
+ virtual void configureSurface(nsecs_t when, bool* outResetNeeded);
virtual void dumpSurface(String8& dump);
virtual void configureVirtualKeys();
virtual void dumpVirtualKeys(String8& dump);
@@ -1076,7 +1174,7 @@ protected:
virtual void resolveCalibration();
virtual void dumpCalibration(String8& dump);
- void syncTouch(nsecs_t when, bool havePointerIds);
+ virtual void syncTouch(nsecs_t when, bool* outHavePointerIds) = 0;
private:
// The surface orientation and width and height set by configureSurface().
@@ -1102,16 +1200,21 @@ private:
float mSizeScale;
+ float mOrientationCenter;
float mOrientationScale;
float mDistanceScale;
+ bool mHaveTilt;
+ float mTiltXCenter;
+ float mTiltXScale;
+ float mTiltYCenter;
+ float mTiltYScale;
+
// Oriented motion ranges for input device info.
struct OrientedRanges {
InputDeviceInfo::MotionRange x;
InputDeviceInfo::MotionRange y;
-
- bool havePressure;
InputDeviceInfo::MotionRange pressure;
bool haveSize;
@@ -1130,6 +1233,22 @@ private:
bool haveDistance;
InputDeviceInfo::MotionRange distance;
+
+ bool haveTilt;
+ InputDeviceInfo::MotionRange tilt;
+
+ OrientedRanges() {
+ clear();
+ }
+
+ void clear() {
+ haveSize = false;
+ haveTouchSize = false;
+ haveToolSize = false;
+ haveOrientation = false;
+ haveDistance = false;
+ haveTilt = false;
+ }
} mOrientedRanges;
// Oriented dimensions and precision.
@@ -1146,13 +1265,13 @@ private:
int32_t scanCode;
} mCurrentVirtualKey;
- // Scale factor for gesture based pointer movements.
- float mPointerGestureXMovementScale;
- float mPointerGestureYMovementScale;
+ // Scale factor for gesture or mouse based pointer movements.
+ float mPointerXMovementScale;
+ float mPointerYMovementScale;
// Scale factor for gesture based zooming and other freeform motions.
- float mPointerGestureXZoomScale;
- float mPointerGestureYZoomScale;
+ float mPointerXZoomScale;
+ float mPointerYZoomScale;
// The maximum swipe width.
float mPointerGestureMaxSwipeWidth;
@@ -1163,6 +1282,14 @@ private:
uint64_t distance : 48; // squared distance
};
+ enum PointerUsage {
+ POINTER_USAGE_NONE,
+ POINTER_USAGE_GESTURES,
+ POINTER_USAGE_STYLUS,
+ POINTER_USAGE_MOUSE,
+ };
+ PointerUsage mPointerUsage;
+
struct PointerGesture {
enum Mode {
// No fingers, button is not pressed.
@@ -1273,9 +1400,6 @@ private:
// A velocity tracker for determining whether to switch active pointers during drags.
VelocityTracker velocityTracker;
- // Velocity control for pointer movements.
- VelocityControl pointerVelocityControl;
-
void reset() {
firstTouchTime = LLONG_MIN;
activeTouchId = -1;
@@ -1288,7 +1412,6 @@ private:
velocityTracker.clear();
resetTap();
resetQuietTime();
- pointerVelocityControl.reset();
}
void resetTap() {
@@ -1301,7 +1424,38 @@ private:
}
} mPointerGesture;
- void initialize();
+ struct PointerSimple {
+ PointerCoords currentCoords;
+ PointerProperties currentProperties;
+ PointerCoords lastCoords;
+ PointerProperties lastProperties;
+
+ // True if the pointer is down.
+ bool down;
+
+ // True if the pointer is hovering.
+ bool hovering;
+
+ // Time the pointer last went down.
+ nsecs_t downTime;
+
+ void reset() {
+ currentCoords.clear();
+ currentProperties.clear();
+ lastCoords.clear();
+ lastProperties.clear();
+ down = false;
+ hovering = false;
+ downTime = 0;
+ }
+ } mPointerSimple;
+
+ // The pointer and scroll velocity controls.
+ VelocityControl mPointerVelocityControl;
+ VelocityControl mWheelXVelocityControl;
+ VelocityControl mWheelYVelocityControl;
+
+ void sync(nsecs_t when);
bool consumeRawTouches(nsecs_t when, uint32_t policyFlags);
void dispatchVirtualKey(nsecs_t when, uint32_t policyFlags,
@@ -1312,9 +1466,24 @@ private:
void dispatchHoverEnterAndMove(nsecs_t when, uint32_t policyFlags);
void cookPointerData();
+ void dispatchPointerUsage(nsecs_t when, uint32_t policyFlags, PointerUsage pointerUsage);
+ void abortPointerUsage(nsecs_t when, uint32_t policyFlags);
+
void dispatchPointerGestures(nsecs_t when, uint32_t policyFlags, bool isTimeout);
+ void abortPointerGestures(nsecs_t when, uint32_t policyFlags);
bool preparePointerGestures(nsecs_t when,
- bool* outCancelPreviousGesture, bool* outFinishPreviousGesture, bool isTimeout);
+ bool* outCancelPreviousGesture, bool* outFinishPreviousGesture,
+ bool isTimeout);
+
+ void dispatchPointerStylus(nsecs_t when, uint32_t policyFlags);
+ void abortPointerStylus(nsecs_t when, uint32_t policyFlags);
+
+ void dispatchPointerMouse(nsecs_t when, uint32_t policyFlags);
+ void abortPointerMouse(nsecs_t when, uint32_t policyFlags);
+
+ void dispatchPointerSimple(nsecs_t when, uint32_t policyFlags,
+ bool down, bool hovering);
+ void abortPointerSimple(nsecs_t when, uint32_t policyFlags);
// Dispatches a motion event.
// If the changedId is >= 0 and the action is POINTER_DOWN or POINTER_UP, the
@@ -1346,20 +1515,15 @@ public:
SingleTouchInputMapper(InputDevice* device);
virtual ~SingleTouchInputMapper();
- virtual void reset();
+ virtual void reset(nsecs_t when);
virtual void process(const RawEvent* rawEvent);
protected:
+ virtual void syncTouch(nsecs_t when, bool* outHavePointerIds);
virtual void configureRawPointerAxes();
private:
- CursorButtonAccumulator mCursorButtonAccumulator;
- TouchButtonAccumulator mTouchButtonAccumulator;
SingleTouchMotionAccumulator mSingleTouchMotionAccumulator;
-
- void clearState();
-
- void sync(nsecs_t when);
};
@@ -1368,24 +1532,19 @@ public:
MultiTouchInputMapper(InputDevice* device);
virtual ~MultiTouchInputMapper();
- virtual void reset();
+ virtual void reset(nsecs_t when);
virtual void process(const RawEvent* rawEvent);
protected:
+ virtual void syncTouch(nsecs_t when, bool* outHavePointerIds);
virtual void configureRawPointerAxes();
private:
- CursorButtonAccumulator mCursorButtonAccumulator;
- TouchButtonAccumulator mTouchButtonAccumulator;
MultiTouchMotionAccumulator mMultiTouchMotionAccumulator;
// Specifies the pointer id bits that are in use, and their associated tracking id.
BitSet32 mPointerIdBits;
int32_t mPointerTrackingIdMap[MAX_POINTER_ID + 1];
-
- void clearState();
-
- void sync(nsecs_t when);
};
@@ -1397,8 +1556,8 @@ public:
virtual uint32_t getSources();
virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo);
virtual void dump(String8& dump);
- virtual void configure(const InputReaderConfiguration* config, uint32_t changes);
- virtual void reset();
+ virtual void configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes);
+ virtual void reset(nsecs_t when);
virtual void process(const RawEvent* rawEvent);
private:
diff --git a/services/input/tests/InputReader_test.cpp b/services/input/tests/InputReader_test.cpp
index ebf66aa..4796958 100644
--- a/services/input/tests/InputReader_test.cpp
+++ b/services/input/tests/InputReader_test.cpp
@@ -125,13 +125,6 @@ private:
// --- FakeInputReaderPolicy ---
class FakeInputReaderPolicy : public InputReaderPolicyInterface {
- struct DisplayInfo {
- int32_t width;
- int32_t height;
- int32_t orientation;
- };
-
- KeyedVector<int32_t, DisplayInfo> mDisplayInfos;
InputReaderConfiguration mConfig;
KeyedVector<int32_t, sp<FakePointerController> > mPointerControllers;
@@ -142,18 +135,10 @@ public:
FakeInputReaderPolicy() {
}
- void removeDisplayInfo(int32_t displayId) {
- mDisplayInfos.removeItem(displayId);
- }
-
void setDisplayInfo(int32_t displayId, int32_t width, int32_t height, int32_t orientation) {
- removeDisplayInfo(displayId);
-
- DisplayInfo info;
- info.width = width;
- info.height = height;
- info.orientation = orientation;
- mDisplayInfos.add(displayId, info);
+ // Set the size of both the internal and external display at the same time.
+ mConfig.setDisplayInfo(displayId, false /*external*/, width, height, orientation);
+ mConfig.setDisplayInfo(displayId, true /*external*/, width, height, orientation);
}
virtual nsecs_t getVirtualKeyQuietTime() {
@@ -168,26 +153,11 @@ public:
mPointerControllers.add(deviceId, controller);
}
-private:
- virtual bool getDisplayInfo(int32_t displayId, bool external /*currently ignored*/,
- int32_t* width, int32_t* height, int32_t* orientation) {
- ssize_t index = mDisplayInfos.indexOfKey(displayId);
- if (index >= 0) {
- const DisplayInfo& info = mDisplayInfos.valueAt(index);
- if (width) {
- *width = info.width;
- }
- if (height) {
- *height = info.height;
- }
- if (orientation) {
- *orientation = info.orientation;
- }
- return true;
- }
- return false;
+ const InputReaderConfiguration* getReaderConfiguration() const {
+ return &mConfig;
}
+private:
virtual void getReaderConfiguration(InputReaderConfiguration* outConfig) {
*outConfig = mConfig;
}
@@ -203,6 +173,7 @@ private:
class FakeInputListener : public InputListenerInterface {
private:
List<NotifyConfigurationChangedArgs> mNotifyConfigurationChangedArgsQueue;
+ List<NotifyDeviceResetArgs> mNotifyDeviceResetArgsQueue;
List<NotifyKeyArgs> mNotifyKeyArgsQueue;
List<NotifyMotionArgs> mNotifyMotionArgsQueue;
List<NotifySwitchArgs> mNotifySwitchArgsQueue;
@@ -224,6 +195,16 @@ public:
mNotifyConfigurationChangedArgsQueue.erase(mNotifyConfigurationChangedArgsQueue.begin());
}
+ void assertNotifyDeviceResetWasCalled(
+ NotifyDeviceResetArgs* outEventArgs = NULL) {
+ ASSERT_FALSE(mNotifyDeviceResetArgsQueue.empty())
+ << "Expected notifyDeviceReset() to have been called.";
+ if (outEventArgs) {
+ *outEventArgs = *mNotifyDeviceResetArgsQueue.begin();
+ }
+ mNotifyDeviceResetArgsQueue.erase(mNotifyDeviceResetArgsQueue.begin());
+ }
+
void assertNotifyKeyWasCalled(NotifyKeyArgs* outEventArgs = NULL) {
ASSERT_FALSE(mNotifyKeyArgsQueue.empty())
<< "Expected notifyKey() to have been called.";
@@ -266,6 +247,10 @@ private:
mNotifyConfigurationChangedArgsQueue.push_back(*args);
}
+ virtual void notifyDeviceReset(const NotifyDeviceResetArgs* args) {
+ mNotifyDeviceResetArgsQueue.push_back(*args);
+ }
+
virtual void notifyKey(const NotifyKeyArgs* args) {
mNotifyKeyArgsQueue.push_back(*args);
}
@@ -792,11 +777,12 @@ private:
}
}
- virtual void configure(const InputReaderConfiguration* config, uint32_t changes) {
+ virtual void configure(nsecs_t when,
+ const InputReaderConfiguration* config, uint32_t changes) {
mConfigureWasCalled = true;
}
- virtual void reset() {
+ virtual void reset(nsecs_t when) {
mResetWasCalled = true;
}
@@ -913,6 +899,7 @@ protected:
void addDevice(int32_t deviceId, const String8& name, uint32_t classes,
const PropertyMap* configuration) {
mFakeEventHub->addDevice(deviceId, name, classes);
+
if (configuration) {
mFakeEventHub->addConfigurationMap(deviceId, configuration);
}
@@ -1263,7 +1250,15 @@ TEST_F(InputDeviceTest, ImmutableProperties) {
TEST_F(InputDeviceTest, WhenNoMappersAreRegistered_DeviceIsIgnored) {
// Configuration.
InputReaderConfiguration config;
- mDevice->configure(&config, 0);
+ mDevice->configure(ARBITRARY_TIME, &config, 0);
+
+ // Reset.
+ mDevice->reset(ARBITRARY_TIME);
+
+ NotifyDeviceResetArgs resetArgs;
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
+ ASSERT_EQ(ARBITRARY_TIME, resetArgs.eventTime);
+ ASSERT_EQ(DEVICE_ID, resetArgs.deviceId);
// Metadata.
ASSERT_TRUE(mDevice->isIgnored());
@@ -1292,9 +1287,6 @@ TEST_F(InputDeviceTest, WhenNoMappersAreRegistered_DeviceIsIgnored) {
<< "Ignored device should never mark any key codes.";
ASSERT_EQ(0, flags[0]) << "Flag for unsupported key should be unchanged.";
ASSERT_EQ(1, flags[1]) << "Flag for unsupported key should be unchanged.";
-
- // Reset.
- mDevice->reset();
}
TEST_F(InputDeviceTest, WhenMappersAreRegistered_DeviceIsNotIgnoredAndForwardsRequestsToMappers) {
@@ -1318,7 +1310,7 @@ TEST_F(InputDeviceTest, WhenMappersAreRegistered_DeviceIsNotIgnoredAndForwardsRe
mDevice->addMapper(mapper2);
InputReaderConfiguration config;
- mDevice->configure(&config, 0);
+ mDevice->configure(ARBITRARY_TIME, &config, 0);
String8 propertyValue;
ASSERT_TRUE(mDevice->getConfiguration().tryGetProperty(String8("key"), propertyValue))
@@ -1328,6 +1320,16 @@ TEST_F(InputDeviceTest, WhenMappersAreRegistered_DeviceIsNotIgnoredAndForwardsRe
ASSERT_NO_FATAL_FAILURE(mapper1->assertConfigureWasCalled());
ASSERT_NO_FATAL_FAILURE(mapper2->assertConfigureWasCalled());
+ // Reset
+ mDevice->reset(ARBITRARY_TIME);
+ ASSERT_NO_FATAL_FAILURE(mapper1->assertResetWasCalled());
+ ASSERT_NO_FATAL_FAILURE(mapper2->assertResetWasCalled());
+
+ NotifyDeviceResetArgs resetArgs;
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
+ ASSERT_EQ(ARBITRARY_TIME, resetArgs.eventTime);
+ ASSERT_EQ(DEVICE_ID, resetArgs.deviceId);
+
// Metadata.
ASSERT_FALSE(mDevice->isIgnored());
ASSERT_EQ(uint32_t(AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TOUCHSCREEN), mDevice->getSources());
@@ -1379,12 +1381,6 @@ TEST_F(InputDeviceTest, WhenMappersAreRegistered_DeviceIsNotIgnoredAndForwardsRe
ASSERT_NO_FATAL_FAILURE(mapper1->assertProcessWasCalled());
ASSERT_NO_FATAL_FAILURE(mapper2->assertProcessWasCalled());
-
- // Reset.
- mDevice->reset();
-
- ASSERT_NO_FATAL_FAILURE(mapper1->assertResetWasCalled());
- ASSERT_NO_FATAL_FAILURE(mapper2->assertResetWasCalled());
}
@@ -1424,10 +1420,16 @@ protected:
}
void addMapperAndConfigure(InputMapper* mapper) {
- InputReaderConfiguration config;
-
mDevice->addMapper(mapper);
- mDevice->configure(&config, 0);
+ mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(), 0);
+ mDevice->reset(ARBITRARY_TIME);
+ }
+
+ void setDisplayInfoAndReconfigure(int32_t displayId, int32_t width, int32_t height,
+ int32_t orientation) {
+ mFakePolicy->setDisplayInfo(displayId, width, height, orientation);
+ mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
+ InputReaderConfiguration::CHANGE_DISPLAY_INFO);
}
static void process(InputMapper* mapper, nsecs_t when, int32_t deviceId, int32_t type,
@@ -1593,71 +1595,6 @@ TEST_F(KeyboardInputMapperTest, Process_SimpleKeyPress) {
ASSERT_EQ(ARBITRARY_TIME, args.downTime);
}
-TEST_F(KeyboardInputMapperTest, Reset_WhenKeysAreNotDown_DoesNotSynthesizeKeyUp) {
- KeyboardInputMapper* mapper = new KeyboardInputMapper(mDevice,
- AINPUT_SOURCE_KEYBOARD, AINPUT_KEYBOARD_TYPE_ALPHABETIC);
- addMapperAndConfigure(mapper);
-
- // Key down.
- process(mapper, ARBITRARY_TIME, DEVICE_ID,
- EV_KEY, KEY_HOME, AKEYCODE_HOME, 1, POLICY_FLAG_WAKE);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled());
-
- // Key up.
- process(mapper, ARBITRARY_TIME, DEVICE_ID,
- EV_KEY, KEY_HOME, AKEYCODE_HOME, 0, POLICY_FLAG_WAKE);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled());
-
- // Reset. Since no keys still down, should not synthesize any key ups.
- mapper->reset();
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
-}
-
-TEST_F(KeyboardInputMapperTest, Reset_WhenKeysAreDown_SynthesizesKeyUps) {
- KeyboardInputMapper* mapper = new KeyboardInputMapper(mDevice,
- AINPUT_SOURCE_KEYBOARD, AINPUT_KEYBOARD_TYPE_ALPHABETIC);
- addMapperAndConfigure(mapper);
-
- // Metakey down.
- process(mapper, ARBITRARY_TIME, DEVICE_ID,
- EV_KEY, KEY_LEFTSHIFT, AKEYCODE_SHIFT_LEFT, 1, 0);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled());
-
- // Key down.
- process(mapper, ARBITRARY_TIME + 1, DEVICE_ID,
- EV_KEY, KEY_A, AKEYCODE_A, 1, 0);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled());
-
- // Reset. Since two keys are still down, should synthesize two key ups in reverse order.
- mapper->reset();
-
- NotifyKeyArgs args;
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
- ASSERT_EQ(DEVICE_ID, args.deviceId);
- ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
- ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
- ASSERT_EQ(AKEYCODE_A, args.keyCode);
- ASSERT_EQ(KEY_A, args.scanCode);
- ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
- ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
- ASSERT_EQ(uint32_t(0), args.policyFlags);
- ASSERT_EQ(ARBITRARY_TIME + 1, args.downTime);
-
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
- ASSERT_EQ(DEVICE_ID, args.deviceId);
- ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
- ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
- ASSERT_EQ(AKEYCODE_SHIFT_LEFT, args.keyCode);
- ASSERT_EQ(KEY_LEFTSHIFT, args.scanCode);
- ASSERT_EQ(AMETA_NONE, args.metaState);
- ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
- ASSERT_EQ(uint32_t(0), args.policyFlags);
- ASSERT_EQ(ARBITRARY_TIME + 1, args.downTime);
-
- // And that's it.
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
-}
-
TEST_F(KeyboardInputMapperTest, Process_ShouldUpdateMetaState) {
KeyboardInputMapper* mapper = new KeyboardInputMapper(mDevice,
AINPUT_SOURCE_KEYBOARD, AINPUT_KEYBOARD_TYPE_ALPHABETIC);
@@ -1703,7 +1640,7 @@ TEST_F(KeyboardInputMapperTest, Process_WhenNotOrientationAware_ShouldNotRotateD
AINPUT_SOURCE_KEYBOARD, AINPUT_KEYBOARD_TYPE_ALPHABETIC);
addMapperAndConfigure(mapper);
- mFakePolicy->setDisplayInfo(DISPLAY_ID,
+ setDisplayInfoAndReconfigure(DISPLAY_ID,
DISPLAY_WIDTH, DISPLAY_HEIGHT,
DISPLAY_ORIENTATION_90);
ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
@@ -1722,7 +1659,7 @@ TEST_F(KeyboardInputMapperTest, Process_WhenOrientationAware_ShouldRotateDPad) {
addConfigurationProperty("keyboard.orientationAware", "1");
addMapperAndConfigure(mapper);
- mFakePolicy->setDisplayInfo(DISPLAY_ID,
+ setDisplayInfoAndReconfigure(DISPLAY_ID,
DISPLAY_WIDTH, DISPLAY_HEIGHT,
DISPLAY_ORIENTATION_0);
ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
@@ -1734,7 +1671,7 @@ TEST_F(KeyboardInputMapperTest, Process_WhenOrientationAware_ShouldRotateDPad) {
ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
KEY_LEFT, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_LEFT));
- mFakePolicy->setDisplayInfo(DISPLAY_ID,
+ setDisplayInfoAndReconfigure(DISPLAY_ID,
DISPLAY_WIDTH, DISPLAY_HEIGHT,
DISPLAY_ORIENTATION_90);
ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
@@ -1746,7 +1683,7 @@ TEST_F(KeyboardInputMapperTest, Process_WhenOrientationAware_ShouldRotateDPad) {
ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
KEY_LEFT, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN));
- mFakePolicy->setDisplayInfo(DISPLAY_ID,
+ setDisplayInfoAndReconfigure(DISPLAY_ID,
DISPLAY_WIDTH, DISPLAY_HEIGHT,
DISPLAY_ORIENTATION_180);
ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
@@ -1758,7 +1695,7 @@ TEST_F(KeyboardInputMapperTest, Process_WhenOrientationAware_ShouldRotateDPad) {
ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
KEY_LEFT, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_RIGHT));
- mFakePolicy->setDisplayInfo(DISPLAY_ID,
+ setDisplayInfoAndReconfigure(DISPLAY_ID,
DISPLAY_WIDTH, DISPLAY_HEIGHT,
DISPLAY_ORIENTATION_270);
ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
@@ -1774,7 +1711,7 @@ TEST_F(KeyboardInputMapperTest, Process_WhenOrientationAware_ShouldRotateDPad) {
// in the key up as we did in the key down.
NotifyKeyArgs args;
- mFakePolicy->setDisplayInfo(DISPLAY_ID,
+ setDisplayInfoAndReconfigure(DISPLAY_ID,
DISPLAY_WIDTH, DISPLAY_HEIGHT,
DISPLAY_ORIENTATION_270);
process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, KEY_UP, AKEYCODE_DPAD_UP, 1, 0);
@@ -1783,7 +1720,7 @@ TEST_F(KeyboardInputMapperTest, Process_WhenOrientationAware_ShouldRotateDPad) {
ASSERT_EQ(KEY_UP, args.scanCode);
ASSERT_EQ(AKEYCODE_DPAD_RIGHT, args.keyCode);
- mFakePolicy->setDisplayInfo(DISPLAY_ID,
+ setDisplayInfoAndReconfigure(DISPLAY_ID,
DISPLAY_WIDTH, DISPLAY_HEIGHT,
DISPLAY_ORIENTATION_180);
process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, KEY_UP, AKEYCODE_DPAD_UP, 0, 0);
@@ -2149,58 +2086,12 @@ TEST_F(CursorInputMapperTest, Process_ShouldHandleCombinedXYAndButtonUpdates) {
0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
}
-TEST_F(CursorInputMapperTest, Reset_WhenButtonIsNotDown_ShouldNotSynthesizeButtonUp) {
- CursorInputMapper* mapper = new CursorInputMapper(mDevice);
- addConfigurationProperty("cursor.mode", "navigation");
- addMapperAndConfigure(mapper);
-
- NotifyMotionArgs args;
-
- // Button press.
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 1, 0);
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
- ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
-
- // Button release.
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 0, 0);
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
- ASSERT_EQ(AMOTION_EVENT_ACTION_UP, args.action);
-
- // Reset. Should not synthesize button up since button is not pressed.
- mapper->reset();
-
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
-}
-
-TEST_F(CursorInputMapperTest, Reset_WhenButtonIsDown_ShouldSynthesizeButtonUp) {
- CursorInputMapper* mapper = new CursorInputMapper(mDevice);
- addConfigurationProperty("cursor.mode", "navigation");
- addMapperAndConfigure(mapper);
-
- NotifyMotionArgs args;
-
- // Button press.
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 1, 0);
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
-
- // Reset. Should synthesize button up.
- mapper->reset();
-
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
- ASSERT_EQ(AMOTION_EVENT_ACTION_UP, args.action);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
- 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
-}
-
TEST_F(CursorInputMapperTest, Process_WhenNotOrientationAware_ShouldNotRotateMotions) {
CursorInputMapper* mapper = new CursorInputMapper(mDevice);
addConfigurationProperty("cursor.mode", "navigation");
addMapperAndConfigure(mapper);
- mFakePolicy->setDisplayInfo(DISPLAY_ID,
+ setDisplayInfoAndReconfigure(DISPLAY_ID,
DISPLAY_WIDTH, DISPLAY_HEIGHT,
DISPLAY_ORIENTATION_90);
ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 0, 1, 0, 1));
@@ -2219,7 +2110,7 @@ TEST_F(CursorInputMapperTest, Process_WhenOrientationAware_ShouldRotateMotions)
addConfigurationProperty("cursor.orientationAware", "1");
addMapperAndConfigure(mapper);
- mFakePolicy->setDisplayInfo(DISPLAY_ID,
+ setDisplayInfoAndReconfigure(DISPLAY_ID,
DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_ORIENTATION_0);
ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 0, 1, 0, 1));
ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, 1, 1, 1));
@@ -2230,7 +2121,7 @@ TEST_F(CursorInputMapperTest, Process_WhenOrientationAware_ShouldRotateMotions)
ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, 0, -1, 0));
ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, 1, -1, 1));
- mFakePolicy->setDisplayInfo(DISPLAY_ID,
+ setDisplayInfoAndReconfigure(DISPLAY_ID,
DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_ORIENTATION_90);
ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 0, 1, 1, 0));
ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, 1, 1, -1));
@@ -2241,7 +2132,7 @@ TEST_F(CursorInputMapperTest, Process_WhenOrientationAware_ShouldRotateMotions)
ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, 0, 0, 1));
ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, 1, 1, 1));
- mFakePolicy->setDisplayInfo(DISPLAY_ID,
+ setDisplayInfoAndReconfigure(DISPLAY_ID,
DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_ORIENTATION_180);
ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 0, 1, 0, -1));
ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, 1, -1, -1));
@@ -2252,7 +2143,7 @@ TEST_F(CursorInputMapperTest, Process_WhenOrientationAware_ShouldRotateMotions)
ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, 0, 1, 0));
ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, 1, 1, -1));
- mFakePolicy->setDisplayInfo(DISPLAY_ID,
+ setDisplayInfoAndReconfigure(DISPLAY_ID,
DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_ORIENTATION_270);
ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 0, 1, -1, 0));
ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, 1, -1, 1));
@@ -2480,6 +2371,8 @@ protected:
static const int32_t RAW_ORIENTATION_MAX;
static const int32_t RAW_DISTANCE_MIN;
static const int32_t RAW_DISTANCE_MAX;
+ static const int32_t RAW_TILT_MIN;
+ static const int32_t RAW_TILT_MAX;
static const int32_t RAW_ID_MIN;
static const int32_t RAW_ID_MAX;
static const int32_t RAW_SLOT_MIN;
@@ -2500,8 +2393,9 @@ protected:
MINOR = 1 << 5,
ID = 1 << 6,
DISTANCE = 1 << 7,
- SLOT = 1 << 8,
- TOOL_TYPE = 1 << 9,
+ TILT = 1 << 8,
+ SLOT = 1 << 9,
+ TOOL_TYPE = 1 << 10,
};
void prepareDisplay(int32_t orientation);
@@ -2526,6 +2420,8 @@ const int32_t TouchInputMapperTest::RAW_ORIENTATION_MIN = -7;
const int32_t TouchInputMapperTest::RAW_ORIENTATION_MAX = 7;
const int32_t TouchInputMapperTest::RAW_DISTANCE_MIN = 0;
const int32_t TouchInputMapperTest::RAW_DISTANCE_MAX = 7;
+const int32_t TouchInputMapperTest::RAW_TILT_MIN = 0;
+const int32_t TouchInputMapperTest::RAW_TILT_MAX = 150;
const int32_t TouchInputMapperTest::RAW_ID_MIN = 0;
const int32_t TouchInputMapperTest::RAW_ID_MAX = 9;
const int32_t TouchInputMapperTest::RAW_SLOT_MIN = 0;
@@ -2543,7 +2439,7 @@ const VirtualKeyDefinition TouchInputMapperTest::VIRTUAL_KEYS[2] = {
};
void TouchInputMapperTest::prepareDisplay(int32_t orientation) {
- mFakePolicy->setDisplayInfo(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, orientation);
+ setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, orientation);
}
void TouchInputMapperTest::prepareVirtualKeys() {
@@ -2583,6 +2479,7 @@ protected:
void processPressure(SingleTouchInputMapper* mapper, int32_t pressure);
void processToolMajor(SingleTouchInputMapper* mapper, int32_t toolMajor);
void processDistance(SingleTouchInputMapper* mapper, int32_t distance);
+ void processTilt(SingleTouchInputMapper* mapper, int32_t tiltX, int32_t tiltY);
void processKey(SingleTouchInputMapper* mapper, int32_t code, int32_t value);
void processSync(SingleTouchInputMapper* mapper);
};
@@ -2610,6 +2507,12 @@ void SingleTouchInputMapperTest::prepareAxes(int axes) {
mFakeEventHub->addAbsoluteAxis(DEVICE_ID, ABS_DISTANCE,
RAW_DISTANCE_MIN, RAW_DISTANCE_MAX, 0, 0);
}
+ if (axes & TILT) {
+ mFakeEventHub->addAbsoluteAxis(DEVICE_ID, ABS_TILT_X,
+ RAW_TILT_MIN, RAW_TILT_MAX, 0, 0);
+ mFakeEventHub->addAbsoluteAxis(DEVICE_ID, ABS_TILT_Y,
+ RAW_TILT_MIN, RAW_TILT_MAX, 0, 0);
+ }
}
void SingleTouchInputMapperTest::processDown(SingleTouchInputMapper* mapper, int32_t x, int32_t y) {
@@ -2642,6 +2545,12 @@ void SingleTouchInputMapperTest::processDistance(
process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_DISTANCE, 0, distance, 0);
}
+void SingleTouchInputMapperTest::processTilt(
+ SingleTouchInputMapper* mapper, int32_t tiltX, int32_t tiltY) {
+ process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_TILT_X, 0, tiltX, 0);
+ process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_TILT_Y, 0, tiltY, 0);
+}
+
void SingleTouchInputMapperTest::processKey(
SingleTouchInputMapper* mapper, int32_t code, int32_t value) {
process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, code, 0, value, 0);
@@ -2658,7 +2567,7 @@ TEST_F(SingleTouchInputMapperTest, GetSources_WhenDeviceTypeIsNotSpecifiedAndNot
prepareAxes(POSITION);
addMapperAndConfigure(mapper);
- ASSERT_EQ(AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_TOUCHPAD, mapper->getSources());
+ ASSERT_EQ(AINPUT_SOURCE_MOUSE, mapper->getSources());
}
TEST_F(SingleTouchInputMapperTest, GetSources_WhenDeviceTypeIsNotSpecifiedAndIsACursor_ReturnsTouchPad) {
@@ -2766,71 +2675,6 @@ TEST_F(SingleTouchInputMapperTest, MarkSupportedKeyCodes) {
ASSERT_FALSE(flags[1]);
}
-TEST_F(SingleTouchInputMapperTest, Reset_WhenVirtualKeysAreDown_SendsUp) {
- // Note: Ideally we should send cancels but the implementation is more straightforward
- // with up and this will only happen if a device is forcibly removed.
- SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
- addConfigurationProperty("touch.deviceType", "touchScreen");
- prepareDisplay(DISPLAY_ORIENTATION_0);
- prepareButtons();
- prepareAxes(POSITION);
- prepareVirtualKeys();
- addMapperAndConfigure(mapper);
-
- mFakeContext->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
-
- // Press virtual key.
- int32_t x = toRawX(VIRTUAL_KEYS[0].centerX);
- int32_t y = toRawY(VIRTUAL_KEYS[0].centerY);
- processDown(mapper, x, y);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled());
-
- // Reset. Since key is down, synthesize key up.
- mapper->reset();
-
- NotifyKeyArgs args;
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
- //ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
- ASSERT_EQ(DEVICE_ID, args.deviceId);
- ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
- ASSERT_EQ(POLICY_FLAG_VIRTUAL, args.policyFlags);
- ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
- ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY, args.flags);
- ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
- ASSERT_EQ(KEY_HOME, args.scanCode);
- ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
- ASSERT_EQ(ARBITRARY_TIME, args.downTime);
-}
-
-TEST_F(SingleTouchInputMapperTest, Reset_WhenNothingIsPressed_NothingMuchHappens) {
- SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
- addConfigurationProperty("touch.deviceType", "touchScreen");
- prepareDisplay(DISPLAY_ORIENTATION_0);
- prepareButtons();
- prepareAxes(POSITION);
- prepareVirtualKeys();
- addMapperAndConfigure(mapper);
-
- // Press virtual key.
- int32_t x = toRawX(VIRTUAL_KEYS[0].centerX);
- int32_t y = toRawY(VIRTUAL_KEYS[0].centerY);
- processDown(mapper, x, y);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled());
-
- // Release virtual key.
- processUp(mapper);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled());
-
- // Reset. Since no key is down, nothing happens.
- mapper->reset();
-
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
-}
-
TEST_F(SingleTouchInputMapperTest, Process_WhenVirtualKeyIsPressedAndReleasedNormally_SendsKeyDownAndKeyUp) {
SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
addConfigurationProperty("touch.deviceType", "touchScreen");
@@ -3260,7 +3104,7 @@ TEST_F(SingleTouchInputMapperTest, Process_AllAxes_DefaultCalibration) {
addConfigurationProperty("touch.deviceType", "touchScreen");
prepareDisplay(DISPLAY_ORIENTATION_0);
prepareButtons();
- prepareAxes(POSITION | PRESSURE | TOOL | DISTANCE);
+ prepareAxes(POSITION | PRESSURE | TOOL | DISTANCE | TILT);
addMapperAndConfigure(mapper);
// These calculations are based on the input device calibration documentation.
@@ -3268,7 +3112,9 @@ TEST_F(SingleTouchInputMapperTest, Process_AllAxes_DefaultCalibration) {
int32_t rawY = 200;
int32_t rawPressure = 10;
int32_t rawToolMajor = 12;
- int32_t rawDistance = 0;
+ int32_t rawDistance = 2;
+ int32_t rawTiltX = 30;
+ int32_t rawTiltY = 110;
float x = toDisplayX(rawX);
float y = toDisplayY(rawY);
@@ -3277,16 +3123,25 @@ TEST_F(SingleTouchInputMapperTest, Process_AllAxes_DefaultCalibration) {
float tool = float(rawToolMajor) * GEOMETRIC_SCALE;
float distance = float(rawDistance);
+ float tiltCenter = (RAW_TILT_MAX + RAW_TILT_MIN) * 0.5f;
+ float tiltScale = M_PI / 180;
+ float tiltXAngle = (rawTiltX - tiltCenter) * tiltScale;
+ float tiltYAngle = (rawTiltY - tiltCenter) * tiltScale;
+ float orientation = atan2f(-sinf(tiltXAngle), sinf(tiltYAngle));
+ float tilt = acosf(cosf(tiltXAngle) * cosf(tiltYAngle));
+
processDown(mapper, rawX, rawY);
processPressure(mapper, rawPressure);
processToolMajor(mapper, rawToolMajor);
processDistance(mapper, rawDistance);
+ processTilt(mapper, rawTiltX, rawTiltY);
processSync(mapper);
NotifyMotionArgs args;
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
- x, y, pressure, size, tool, tool, tool, tool, 0, distance));
+ x, y, pressure, size, tool, tool, tool, tool, orientation, distance));
+ ASSERT_EQ(tilt, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_TILT));
}
TEST_F(SingleTouchInputMapperTest, Process_ShouldHandleAllButtons) {
@@ -3482,8 +3337,48 @@ TEST_F(SingleTouchInputMapperTest, Process_ShouldHandleAllToolTypes) {
ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_STYLUS, motionArgs.pointerProperties[0].toolType);
- // finger
+ // brush
processKey(mapper, BTN_TOOL_PEN, 0);
+ processKey(mapper, BTN_TOOL_BRUSH, 1);
+ processSync(mapper);
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
+ ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
+ ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_STYLUS, motionArgs.pointerProperties[0].toolType);
+
+ // pencil
+ processKey(mapper, BTN_TOOL_BRUSH, 0);
+ processKey(mapper, BTN_TOOL_PENCIL, 1);
+ processSync(mapper);
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
+ ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
+ ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_STYLUS, motionArgs.pointerProperties[0].toolType);
+
+ // airbrush
+ processKey(mapper, BTN_TOOL_PENCIL, 0);
+ processKey(mapper, BTN_TOOL_AIRBRUSH, 1);
+ processSync(mapper);
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
+ ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
+ ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_STYLUS, motionArgs.pointerProperties[0].toolType);
+
+ // mouse
+ processKey(mapper, BTN_TOOL_AIRBRUSH, 0);
+ processKey(mapper, BTN_TOOL_MOUSE, 1);
+ processSync(mapper);
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
+ ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
+ ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_MOUSE, motionArgs.pointerProperties[0].toolType);
+
+ // lens
+ processKey(mapper, BTN_TOOL_MOUSE, 0);
+ processKey(mapper, BTN_TOOL_LENS, 1);
+ processSync(mapper);
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
+ ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
+ ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_MOUSE, motionArgs.pointerProperties[0].toolType);
+
+ // finger
+ processKey(mapper, BTN_TOOL_LENS, 0);
processKey(mapper, BTN_TOOL_FINGER, 1);
processSync(mapper);
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
@@ -3504,7 +3399,15 @@ TEST_F(SingleTouchInputMapperTest, Process_ShouldHandleAllToolTypes) {
ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_ERASER, motionArgs.pointerProperties[0].toolType);
+ // mouse trumps eraser
+ processKey(mapper, BTN_TOOL_MOUSE, 1);
+ processSync(mapper);
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
+ ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
+ ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_MOUSE, motionArgs.pointerProperties[0].toolType);
+
// back to default tool type
+ processKey(mapper, BTN_TOOL_MOUSE, 0);
processKey(mapper, BTN_TOOL_RUBBER, 0);
processKey(mapper, BTN_TOOL_PEN, 0);
processKey(mapper, BTN_TOOL_FINGER, 0);
@@ -3587,29 +3490,29 @@ TEST_F(SingleTouchInputMapperTest, Process_WhenBtnTouchPresent_HoversIfItsValueI
toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
}
-TEST_F(SingleTouchInputMapperTest, Process_WhenAbsDistanceIsPresent_HoversIfItsValueIsGreaterThanZero) {
+TEST_F(SingleTouchInputMapperTest, Process_WhenAbsPressureIsPresent_HoversIfItsValueIsZero) {
SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
addConfigurationProperty("touch.deviceType", "touchScreen");
prepareDisplay(DISPLAY_ORIENTATION_0);
prepareButtons();
- prepareAxes(POSITION | DISTANCE);
+ prepareAxes(POSITION | PRESSURE);
addMapperAndConfigure(mapper);
NotifyMotionArgs motionArgs;
- // initially hovering because distance is 1, pressure defaults to 0
+ // initially hovering because pressure is 0
processDown(mapper, 100, 200);
- processDistance(mapper, 1);
+ processPressure(mapper, 0);
processSync(mapper);
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action);
ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 1));
+ toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0));
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 1));
+ toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0));
// move a little
processMove(mapper, 150, 250);
@@ -3617,23 +3520,23 @@ TEST_F(SingleTouchInputMapperTest, Process_WhenAbsDistanceIsPresent_HoversIfItsV
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 1));
+ toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
- // down when distance goes to 0, pressure defaults to 1
- processDistance(mapper, 0);
+ // down when pressure is non-zero
+ processPressure(mapper, RAW_PRESSURE_MAX);
processSync(mapper);
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action);
ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 1));
+ toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0));
- // up when distance goes to 1, hover restored
- processDistance(mapper, 1);
+ // up when pressure becomes 0, hover restored
+ processPressure(mapper, 0);
processSync(mapper);
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
@@ -3643,12 +3546,12 @@ TEST_F(SingleTouchInputMapperTest, Process_WhenAbsDistanceIsPresent_HoversIfItsV
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action);
ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 1));
+ toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 1));
+ toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
// exit hover when pointer goes away
processUp(mapper);
@@ -3656,7 +3559,7 @@ TEST_F(SingleTouchInputMapperTest, Process_WhenAbsDistanceIsPresent_HoversIfItsV
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action);
ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 1));
+ toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
}
@@ -4823,8 +4726,48 @@ TEST_F(MultiTouchInputMapperTest, Process_ShouldHandleAllToolTypes) {
ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_STYLUS, motionArgs.pointerProperties[0].toolType);
- // finger
+ // brush
processKey(mapper, BTN_TOOL_PEN, 0);
+ processKey(mapper, BTN_TOOL_BRUSH, 1);
+ processSync(mapper);
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
+ ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
+ ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_STYLUS, motionArgs.pointerProperties[0].toolType);
+
+ // pencil
+ processKey(mapper, BTN_TOOL_BRUSH, 0);
+ processKey(mapper, BTN_TOOL_PENCIL, 1);
+ processSync(mapper);
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
+ ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
+ ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_STYLUS, motionArgs.pointerProperties[0].toolType);
+
+ // airbrush
+ processKey(mapper, BTN_TOOL_PENCIL, 0);
+ processKey(mapper, BTN_TOOL_AIRBRUSH, 1);
+ processSync(mapper);
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
+ ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
+ ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_STYLUS, motionArgs.pointerProperties[0].toolType);
+
+ // mouse
+ processKey(mapper, BTN_TOOL_AIRBRUSH, 0);
+ processKey(mapper, BTN_TOOL_MOUSE, 1);
+ processSync(mapper);
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
+ ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
+ ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_MOUSE, motionArgs.pointerProperties[0].toolType);
+
+ // lens
+ processKey(mapper, BTN_TOOL_MOUSE, 0);
+ processKey(mapper, BTN_TOOL_LENS, 1);
+ processSync(mapper);
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
+ ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
+ ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_MOUSE, motionArgs.pointerProperties[0].toolType);
+
+ // finger
+ processKey(mapper, BTN_TOOL_LENS, 0);
processKey(mapper, BTN_TOOL_FINGER, 1);
processSync(mapper);
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
@@ -4845,6 +4788,13 @@ TEST_F(MultiTouchInputMapperTest, Process_ShouldHandleAllToolTypes) {
ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_ERASER, motionArgs.pointerProperties[0].toolType);
+ // mouse trumps eraser
+ processKey(mapper, BTN_TOOL_MOUSE, 1);
+ processSync(mapper);
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
+ ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
+ ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_MOUSE, motionArgs.pointerProperties[0].toolType);
+
// MT tool type trumps BTN tool types: MT_TOOL_FINGER
processToolType(mapper, MT_TOOL_FINGER); // this is the first time we send MT_TOOL_TYPE
processSync(mapper);
@@ -4861,6 +4811,7 @@ TEST_F(MultiTouchInputMapperTest, Process_ShouldHandleAllToolTypes) {
// back to default tool type
processToolType(mapper, -1); // use a deliberately undefined tool type, for testing
+ processKey(mapper, BTN_TOOL_MOUSE, 0);
processKey(mapper, BTN_TOOL_RUBBER, 0);
processKey(mapper, BTN_TOOL_PEN, 0);
processKey(mapper, BTN_TOOL_FINGER, 0);
@@ -4942,29 +4893,29 @@ TEST_F(MultiTouchInputMapperTest, Process_WhenBtnTouchPresent_HoversIfItsValueIs
toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
}
-TEST_F(MultiTouchInputMapperTest, Process_WhenAbsMTDistanceIsPresent_HoversIfItsValueIsGreaterThanZero) {
+TEST_F(MultiTouchInputMapperTest, Process_WhenAbsMTPressureIsPresent_HoversIfItsValueIsZero) {
MultiTouchInputMapper* mapper = new MultiTouchInputMapper(mDevice);
addConfigurationProperty("touch.deviceType", "touchScreen");
prepareDisplay(DISPLAY_ORIENTATION_0);
- prepareAxes(POSITION | ID | SLOT | DISTANCE);
+ prepareAxes(POSITION | ID | SLOT | PRESSURE);
addMapperAndConfigure(mapper);
NotifyMotionArgs motionArgs;
- // initially hovering because distance is 1, pressure defaults to 0
+ // initially hovering because pressure is 0
processId(mapper, 1);
processPosition(mapper, 100, 200);
- processDistance(mapper, 1);
+ processPressure(mapper, 0);
processSync(mapper);
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action);
ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 1));
+ toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0));
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 1));
+ toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0));
// move a little
processPosition(mapper, 150, 250);
@@ -4972,23 +4923,23 @@ TEST_F(MultiTouchInputMapperTest, Process_WhenAbsMTDistanceIsPresent_HoversIfIts
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 1));
+ toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
- // down when distance goes to 0, pressure defaults to 1
- processDistance(mapper, 0);
+ // down when pressure becomes non-zero
+ processPressure(mapper, RAW_PRESSURE_MAX);
processSync(mapper);
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action);
ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 1));
+ toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0));
- // up when distance goes to 1, hover restored
- processDistance(mapper, 1);
+ // up when pressure becomes 0, hover restored
+ processPressure(mapper, 0);
processSync(mapper);
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
@@ -4998,12 +4949,12 @@ TEST_F(MultiTouchInputMapperTest, Process_WhenAbsMTDistanceIsPresent_HoversIfIts
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action);
ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 1));
+ toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 1));
+ toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
// exit hover when pointer goes away
processId(mapper, -1);
@@ -5011,7 +4962,7 @@ TEST_F(MultiTouchInputMapperTest, Process_WhenAbsMTDistanceIsPresent_HoversIfIts
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action);
ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 1));
+ toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
}
diff --git a/services/jni/com_android_server_InputManager.cpp b/services/jni/com_android_server_InputManager.cpp
index 7c84e43..f2a0a71 100644
--- a/services/jni/com_android_server_InputManager.cpp
+++ b/services/jni/com_android_server_InputManager.cpp
@@ -182,8 +182,6 @@ public:
/* --- InputReaderPolicyInterface implementation --- */
- virtual bool getDisplayInfo(int32_t displayId, bool external,
- int32_t* width, int32_t* height, int32_t* orientation);
virtual void getReaderConfiguration(InputReaderConfiguration* outConfig);
virtual sp<PointerControllerInterface> obtainPointerController(int32_t deviceId);
@@ -273,7 +271,7 @@ NativeInputManager::NativeInputManager(jobject contextObj,
mLocked.displayHeight = -1;
mLocked.displayExternalWidth = -1;
mLocked.displayExternalHeight = -1;
- mLocked.displayOrientation = ROTATION_0;
+ mLocked.displayOrientation = DISPLAY_ORIENTATION_0;
mLocked.systemUiVisibility = ASYSTEM_UI_VISIBILITY_STATUS_BAR_VISIBLE;
mLocked.pointerSpeed = 0;
@@ -311,31 +309,42 @@ bool NativeInputManager::checkAndClearExceptionFromCallback(JNIEnv* env, const c
void NativeInputManager::setDisplaySize(int32_t displayId, int32_t width, int32_t height,
int32_t externalWidth, int32_t externalHeight) {
+ bool changed = false;
if (displayId == 0) {
- { // acquire lock
- AutoMutex _l(mLock);
+ AutoMutex _l(mLock);
- if (mLocked.displayWidth != width || mLocked.displayHeight != height) {
- mLocked.displayWidth = width;
- mLocked.displayHeight = height;
+ if (mLocked.displayWidth != width || mLocked.displayHeight != height) {
+ changed = true;
+ mLocked.displayWidth = width;
+ mLocked.displayHeight = height;
- sp<PointerController> controller = mLocked.pointerController.promote();
- if (controller != NULL) {
- controller->setDisplaySize(width, height);
- }
+ sp<PointerController> controller = mLocked.pointerController.promote();
+ if (controller != NULL) {
+ controller->setDisplaySize(width, height);
}
+ }
+ if (mLocked.displayExternalWidth != externalWidth
+ || mLocked.displayExternalHeight != externalHeight) {
+ changed = true;
mLocked.displayExternalWidth = externalWidth;
mLocked.displayExternalHeight = externalHeight;
- } // release lock
+ }
+ }
+
+ if (changed) {
+ mInputManager->getReader()->requestRefreshConfiguration(
+ InputReaderConfiguration::CHANGE_DISPLAY_INFO);
}
}
void NativeInputManager::setDisplayOrientation(int32_t displayId, int32_t orientation) {
+ bool changed = false;
if (displayId == 0) {
AutoMutex _l(mLock);
if (mLocked.displayOrientation != orientation) {
+ changed = true;
mLocked.displayOrientation = orientation;
sp<PointerController> controller = mLocked.pointerController.promote();
@@ -344,6 +353,11 @@ void NativeInputManager::setDisplayOrientation(int32_t displayId, int32_t orient
}
}
}
+
+ if (changed) {
+ mInputManager->getReader()->requestRefreshConfiguration(
+ InputReaderConfiguration::CHANGE_DISPLAY_INFO);
+ }
}
status_t NativeInputManager::registerInputChannel(JNIEnv* env,
@@ -358,28 +372,6 @@ status_t NativeInputManager::unregisterInputChannel(JNIEnv* env,
return mInputManager->getDispatcher()->unregisterInputChannel(inputChannel);
}
-bool NativeInputManager::getDisplayInfo(int32_t displayId, bool external,
- int32_t* width, int32_t* height, int32_t* orientation) {
- bool result = false;
- if (displayId == 0) {
- AutoMutex _l(mLock);
-
- if (mLocked.displayWidth > 0 && mLocked.displayHeight > 0) {
- if (width) {
- *width = external ? mLocked.displayExternalWidth : mLocked.displayWidth;
- }
- if (height) {
- *height = external ? mLocked.displayExternalHeight : mLocked.displayHeight;
- }
- if (orientation) {
- *orientation = mLocked.displayOrientation;
- }
- result = true;
- }
- }
- return result;
-}
-
void NativeInputManager::getReaderConfiguration(InputReaderConfiguration* outConfig) {
JNIEnv* env = jniEnv();
@@ -438,6 +430,12 @@ void NativeInputManager::getReaderConfiguration(InputReaderConfiguration* outCon
outConfig->pointerVelocityControlParameters.scale = exp2f(mLocked.pointerSpeed
* POINTER_SPEED_EXPONENT);
outConfig->pointerGesturesEnabled = mLocked.pointerGesturesEnabled;
+
+ outConfig->setDisplayInfo(0, false /*external*/,
+ mLocked.displayWidth, mLocked.displayHeight, mLocked.displayOrientation);
+ outConfig->setDisplayInfo(0, true /*external*/,
+ mLocked.displayExternalWidth, mLocked.displayExternalHeight,
+ mLocked.displayOrientation);
} // release lock
}