summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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
}