diff options
-rw-r--r-- | api/current.xml | 41 | ||||
-rwxr-xr-x | core/java/android/view/InputDevice.java | 114 | ||||
-rw-r--r-- | include/ui/Input.h | 21 | ||||
-rw-r--r-- | libs/ui/Input.cpp | 23 | ||||
-rw-r--r-- | services/input/InputDispatcher.cpp | 10 | ||||
-rw-r--r-- | services/input/InputReader.cpp | 317 | ||||
-rw-r--r-- | services/input/InputReader.h | 24 | ||||
-rw-r--r-- | services/input/PointerController.h | 4 | ||||
-rw-r--r-- | services/input/tests/InputReader_test.cpp | 96 | ||||
-rw-r--r-- | services/jni/com_android_server_InputManager.cpp | 9 |
10 files changed, 437 insertions, 222 deletions
diff --git a/api/current.xml b/api/current.xml index cbccf93..cd3a7fb 100644 --- a/api/current.xml +++ b/api/current.xml @@ -211374,9 +211374,11 @@ deprecated="not deprecated" visibility="public" > +<parameter name="axis" type="int"> +</parameter> </method> -<method name="getMotionAxes" - return="int[]" +<method name="getMotionRange" + return="android.view.InputDevice.MotionRange" abstract="false" native="false" synchronized="false" @@ -211398,6 +211400,19 @@ > <parameter name="axis" type="int"> </parameter> +<parameter name="source" type="int"> +</parameter> +</method> +<method name="getMotionRanges" + return="java.util.List<android.view.InputDevice.MotionRange>" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> </method> <method name="getName" return="java.lang.String" @@ -211763,6 +211778,17 @@ deprecated="not deprecated" visibility="public" > +<method name="getAxis" + return="int" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</method> <method name="getFlat" return="float" abstract="false" @@ -211818,6 +211844,17 @@ visibility="public" > </method> +<method name="getSource" + return="int" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</method> </class> <class name="InputEvent" extends="java.lang.Object" diff --git a/core/java/android/view/InputDevice.java b/core/java/android/view/InputDevice.java index def1161..98d4eb9 100755 --- a/core/java/android/view/InputDevice.java +++ b/core/java/android/view/InputDevice.java @@ -20,7 +20,9 @@ import android.os.Parcel; import android.os.Parcelable; import android.os.RemoteException; import android.os.ServiceManager; -import android.util.SparseArray; + +import java.util.ArrayList; +import java.util.List; /** * Describes the capabilities of a particular input device. @@ -43,8 +45,7 @@ public final class InputDevice implements Parcelable { private int mSources; private int mKeyboardType; - private final SparseArray<MotionRange> mMotionRanges = new SparseArray<MotionRange>(); - private int[] mMotionAxes; + private final ArrayList<MotionRange> mMotionRanges = new ArrayList<MotionRange>(); /** * A mask for input source classes. @@ -354,6 +355,11 @@ public final class InputDevice implements Parcelable { /** * Gets information about the range of values for a particular {@link MotionEvent} axis. + * If the device supports multiple sources, the same axis may have different meanings + * for each source. Returns information about the first axis found for any source. + * To obtain information about the axis for a specific source, use + * {@link #getMotionRange(int, int)}. + * * @param axis The axis constant. * @return The range of values, or null if the requested axis is not * supported by the device. @@ -363,30 +369,55 @@ public final class InputDevice implements Parcelable { * @see #getSupportedAxes() */ public MotionRange getMotionRange(int axis) { - return mMotionRanges.get(axis); + final int numRanges = mMotionRanges.size(); + for (int i = 0; i < numRanges; i++) { + final MotionRange range = mMotionRanges.get(i); + if (range.mAxis == axis) { + return range; + } + } + return null; } /** - * Gets the axis ids of all motion axes supported by this device. - * @return The axis ids of all motion axes supported by this device. + * Gets information about the range of values for a particular {@link MotionEvent} axis + * used by a particular source on the device. + * If the device supports multiple sources, the same axis may have different meanings + * for each source. + * + * @param axis The axis constant. + * @param source The source for which to return information. + * @return The range of values, or null if the requested axis is not + * supported by the device. * - * @see #getMotionRange(int) - */ - public int[] getMotionAxes() { - synchronized (this) { - if (mMotionAxes == null) { - final int count = mMotionRanges.size(); - mMotionAxes = new int[count]; - for (int i = 0; i < count; i++) { - mMotionAxes[i] = mMotionRanges.keyAt(i); - } + * @see MotionEvent#AXIS_X + * @see MotionEvent#AXIS_Y + * @see #getSupportedAxes() + */ + public MotionRange getMotionRange(int axis, int source) { + final int numRanges = mMotionRanges.size(); + for (int i = 0; i < numRanges; i++) { + final MotionRange range = mMotionRanges.get(i); + if (range.mAxis == axis && range.mSource == source) { + return range; } - return mMotionAxes; } + return null; } - private void addMotionRange(int axis, float min, float max, float flat, float fuzz) { - mMotionRanges.append(axis, new MotionRange(min, max, flat, fuzz)); + /** + * Gets the ranges for all axes supported by the device. + * @return The motion ranges for the device. + * + * @see #getMotionRange(int, int) + */ + public List<MotionRange> getMotionRanges() { + return mMotionRanges; + } + + private void addMotionRange(int axis, int source, + float min, float max, float flat, float fuzz) { + mMotionRanges.add(new MotionRange(axis, source, min, max, flat, fuzz)); } /** @@ -395,12 +426,16 @@ public final class InputDevice implements Parcelable { * @see InputDevice#getMotionRange(int) */ public static final class MotionRange { + private int mAxis; + private int mSource; private float mMin; private float mMax; private float mFlat; private float mFuzz; - private MotionRange(float min, float max, float flat, float fuzz) { + private MotionRange(int axis, int source, float min, float max, float flat, float fuzz) { + mAxis = axis; + mSource = source; mMin = min; mMax = max; mFlat = flat; @@ -408,6 +443,22 @@ public final class InputDevice implements Parcelable { } /** + * Gets the axis id. + * @return The axis id. + */ + public int getAxis() { + return mAxis; + } + + /** + * Gets the source for which the axis is defined. + * @return The source. + */ + public int getSource() { + return mSource; + } + + /** * Gets the inclusive minimum value for the axis. * @return The inclusive minimum value. */ @@ -480,7 +531,8 @@ public final class InputDevice implements Parcelable { if (axis < 0) { break; } - addMotionRange(axis, in.readFloat(), in.readFloat(), in.readFloat(), in.readFloat()); + addMotionRange(axis, in.readInt(), + in.readFloat(), in.readFloat(), in.readFloat(), in.readFloat()); } } @@ -491,11 +543,11 @@ public final class InputDevice implements Parcelable { out.writeInt(mSources); out.writeInt(mKeyboardType); - final int numAxes = mMotionRanges.size(); - for (int i = 0; i < numAxes; i++) { - int axis = mMotionRanges.keyAt(i); - MotionRange range = mMotionRanges.valueAt(i); - out.writeInt(axis); + final int numRanges = mMotionRanges.size(); + for (int i = 0; i < numRanges; i++) { + MotionRange range = mMotionRanges.get(i); + out.writeInt(range.mAxis); + out.writeInt(range.mSource); out.writeFloat(range.mMin); out.writeFloat(range.mMax); out.writeFloat(range.mFlat); @@ -528,7 +580,7 @@ public final class InputDevice implements Parcelable { } description.append("\n"); - description.append(" Sources: ").append(Integer.toHexString(mSources)).append(" ("); + description.append(" Sources: 0x").append(Integer.toHexString(mSources)).append(" ("); appendSourceDescriptionIfApplicable(description, SOURCE_KEYBOARD, "keyboard"); appendSourceDescriptionIfApplicable(description, SOURCE_DPAD, "dpad"); appendSourceDescriptionIfApplicable(description, SOURCE_TOUCHSCREEN, "touchscreen"); @@ -541,10 +593,10 @@ public final class InputDevice implements Parcelable { final int numAxes = mMotionRanges.size(); for (int i = 0; i < numAxes; i++) { - int axis = mMotionRanges.keyAt(i); - MotionRange range = mMotionRanges.valueAt(i); - description.append(" ").append(MotionEvent.axisToString(axis)); - description.append(": min=").append(range.mMin); + MotionRange range = mMotionRanges.get(i); + description.append(" ").append(MotionEvent.axisToString(range.mAxis)); + description.append(": source=0x").append(Integer.toHexString(range.mSource)); + description.append(" min=").append(range.mMin); description.append(" max=").append(range.mMax); description.append(" flat=").append(range.mFlat); description.append(" fuzz=").append(range.mFuzz); diff --git a/include/ui/Input.h b/include/ui/Input.h index e92d7f5..d9d77c4 100644 --- a/include/ui/Input.h +++ b/include/ui/Input.h @@ -144,6 +144,14 @@ enum { }; /* + * Button state. + */ +enum { + // Primary button pressed (left mouse button). + BUTTON_STATE_PRIMARY = 1 << 0, +}; + +/* * Describes the basic configuration of input devices that are present. */ struct InputConfiguration { @@ -544,6 +552,8 @@ public: ~InputDeviceInfo(); struct MotionRange { + int32_t axis; + uint32_t source; float min; float max; float flat; @@ -556,16 +566,17 @@ public: inline const String8 getName() const { return mName; } inline uint32_t getSources() const { return mSources; } - const MotionRange* getMotionRange(int32_t axis) const; + const MotionRange* getMotionRange(int32_t axis, uint32_t source) const; void addSource(uint32_t source); - void addMotionRange(int32_t axis, float min, float max, float flat, float fuzz); - void addMotionRange(int32_t axis, const MotionRange& range); + void addMotionRange(int32_t axis, uint32_t source, + float min, float max, float flat, float fuzz); + void addMotionRange(const MotionRange& range); inline void setKeyboardType(int32_t keyboardType) { mKeyboardType = keyboardType; } inline int32_t getKeyboardType() const { return mKeyboardType; } - inline const KeyedVector<int32_t, MotionRange> getMotionRanges() const { + inline const Vector<MotionRange>& getMotionRanges() const { return mMotionRanges; } @@ -575,7 +586,7 @@ private: uint32_t mSources; int32_t mKeyboardType; - KeyedVector<int32_t, MotionRange> mMotionRanges; + Vector<MotionRange> mMotionRanges; }; /* diff --git a/libs/ui/Input.cpp b/libs/ui/Input.cpp index 0ed0866..e2e698e 100644 --- a/libs/ui/Input.cpp +++ b/libs/ui/Input.cpp @@ -657,23 +657,30 @@ void InputDeviceInfo::initialize(int32_t id, const String8& name) { mMotionRanges.clear(); } -const InputDeviceInfo::MotionRange* InputDeviceInfo::getMotionRange(int32_t axis) const { - ssize_t index = mMotionRanges.indexOfKey(axis); - return index >= 0 ? & mMotionRanges.valueAt(index) : NULL; +const InputDeviceInfo::MotionRange* InputDeviceInfo::getMotionRange( + int32_t axis, uint32_t source) const { + size_t numRanges = mMotionRanges.size(); + for (size_t i = 0; i < numRanges; i++) { + const MotionRange& range = mMotionRanges.itemAt(i); + if (range.axis == axis && range.source == source) { + return ⦥ + } + } + return NULL; } void InputDeviceInfo::addSource(uint32_t source) { mSources |= source; } -void InputDeviceInfo::addMotionRange(int32_t axis, float min, float max, +void InputDeviceInfo::addMotionRange(int32_t axis, uint32_t source, float min, float max, float flat, float fuzz) { - MotionRange range = { min, max, flat, fuzz }; - addMotionRange(axis, range); + MotionRange range = { axis, source, min, max, flat, fuzz }; + mMotionRanges.add(range); } -void InputDeviceInfo::addMotionRange(int32_t axis, const MotionRange& range) { - mMotionRanges.add(axis, range); +void InputDeviceInfo::addMotionRange(const MotionRange& range) { + mMotionRanges.add(range); } } // namespace android diff --git a/services/input/InputDispatcher.cpp b/services/input/InputDispatcher.cpp index 487ecff..19295e6 100644 --- a/services/input/InputDispatcher.cpp +++ b/services/input/InputDispatcher.cpp @@ -2343,17 +2343,17 @@ void InputDispatcher::notifyMotion(nsecs_t eventTime, int32_t deviceId, uint32_t } MotionEntry* motionEntry = static_cast<MotionEntry*>(entry); - if (motionEntry->deviceId != deviceId) { - // Keep looking for this device. + if (motionEntry->deviceId != deviceId + || motionEntry->source != source) { + // Keep looking for this device and source. continue; } if (motionEntry->action != action - || motionEntry->source != source || motionEntry->pointerCount != pointerCount || motionEntry->isInjected()) { - // Last motion event in the queue for this device is not compatible for - // appending new samples. Stop here. + // Last motion event in the queue for this device and source is + // not compatible for appending new samples. Stop here. goto NoBatchingOrStreaming; } diff --git a/services/input/InputReader.cpp b/services/input/InputReader.cpp index 3688bfc..3029028 100644 --- a/services/input/InputReader.cpp +++ b/services/input/InputReader.cpp @@ -33,6 +33,7 @@ // Log debug messages about pointer assignment calculations. #define DEBUG_POINTER_ASSIGNMENT 0 + #include "InputReader.h" #include <cutils/log.h> @@ -140,6 +141,48 @@ static inline bool sourcesMatchMask(uint32_t sources, uint32_t sourceMask) { return (sources & sourceMask & ~ AINPUT_SOURCE_CLASS_MASK) != 0; } +static uint32_t getButtonStateForScanCode(int32_t scanCode) { + // Currently all buttons are mapped to the primary button. + switch (scanCode) { + case BTN_LEFT: + case BTN_RIGHT: + case BTN_MIDDLE: + case BTN_SIDE: + case BTN_EXTRA: + case BTN_FORWARD: + case BTN_BACK: + case BTN_TASK: + return BUTTON_STATE_PRIMARY; + default: + return 0; + } +} + +// Returns true if the pointer should be reported as being down given the specified +// button states. +static bool isPointerDown(uint32_t buttonState) { + return buttonState & BUTTON_STATE_PRIMARY; +} + +static int32_t calculateEdgeFlagsUsingPointerBounds( + const sp<PointerControllerInterface>& pointerController, float x, float y) { + int32_t edgeFlags = 0; + float minX, minY, maxX, maxY; + if (pointerController->getBounds(&minX, &minY, &maxX, &maxY)) { + if (x <= minX) { + edgeFlags |= AMOTION_EVENT_EDGE_FLAG_LEFT; + } else if (x >= maxX) { + edgeFlags |= AMOTION_EVENT_EDGE_FLAG_RIGHT; + } + if (y <= minY) { + edgeFlags |= AMOTION_EVENT_EDGE_FLAG_TOP; + } else if (y >= maxY) { + edgeFlags |= AMOTION_EVENT_EDGE_FLAG_BOTTOM; + } + } + return edgeFlags; +} + // --- InputReader --- @@ -270,23 +313,23 @@ InputDevice* InputReader::createDevice(int32_t deviceId, const String8& name, ui } // Keyboard-like devices. - uint32_t keyboardSources = 0; + uint32_t keyboardSource = 0; int32_t keyboardType = AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC; if (classes & INPUT_DEVICE_CLASS_KEYBOARD) { - keyboardSources |= AINPUT_SOURCE_KEYBOARD; + keyboardSource |= AINPUT_SOURCE_KEYBOARD; } if (classes & INPUT_DEVICE_CLASS_ALPHAKEY) { keyboardType = AINPUT_KEYBOARD_TYPE_ALPHABETIC; } if (classes & INPUT_DEVICE_CLASS_DPAD) { - keyboardSources |= AINPUT_SOURCE_DPAD; + keyboardSource |= AINPUT_SOURCE_DPAD; } if (classes & INPUT_DEVICE_CLASS_GAMEPAD) { - keyboardSources |= AINPUT_SOURCE_GAMEPAD; + keyboardSource |= AINPUT_SOURCE_GAMEPAD; } - if (keyboardSources != 0) { - device->addMapper(new KeyboardInputMapper(device, keyboardSources, keyboardType)); + if (keyboardSource != 0) { + device->addMapper(new KeyboardInputMapper(device, keyboardSource, keyboardType)); } // Cursor-like devices. @@ -617,22 +660,22 @@ void InputDevice::dump(String8& dump) { dump.appendFormat(INDENT2 "Sources: 0x%08x\n", deviceInfo.getSources()); dump.appendFormat(INDENT2 "KeyboardType: %d\n", deviceInfo.getKeyboardType()); - const KeyedVector<int32_t, InputDeviceInfo::MotionRange> ranges = deviceInfo.getMotionRanges(); + const Vector<InputDeviceInfo::MotionRange>& ranges = deviceInfo.getMotionRanges(); if (!ranges.isEmpty()) { dump.append(INDENT2 "Motion Ranges:\n"); for (size_t i = 0; i < ranges.size(); i++) { - int32_t axis = ranges.keyAt(i); - const char* label = getAxisLabel(axis); + const InputDeviceInfo::MotionRange& range = ranges.itemAt(i); + const char* label = getAxisLabel(range.axis); char name[32]; if (label) { strncpy(name, label, sizeof(name)); name[sizeof(name) - 1] = '\0'; } else { - snprintf(name, sizeof(name), "%d", axis); + snprintf(name, sizeof(name), "%d", range.axis); } - const InputDeviceInfo::MotionRange& range = ranges.valueAt(i); - dump.appendFormat(INDENT3 "%s: min=%0.3f, max=%0.3f, flat=%0.3f, fuzz=%0.3f\n", - name, range.min, range.max, range.flat, range.fuzz); + dump.appendFormat(INDENT3 "%s: source=0x%08x, " + "min=%0.3f, max=%0.3f, flat=%0.3f, fuzz=%0.3f\n", + name, range.source, range.min, range.max, range.flat, range.fuzz); } } @@ -837,8 +880,8 @@ int32_t SwitchInputMapper::getSwitchState(uint32_t sourceMask, int32_t switchCod // --- KeyboardInputMapper --- KeyboardInputMapper::KeyboardInputMapper(InputDevice* device, - uint32_t sources, int32_t keyboardType) : - InputMapper(device), mSources(sources), + uint32_t source, int32_t keyboardType) : + InputMapper(device), mSource(source), mKeyboardType(keyboardType) { initializeLocked(); } @@ -852,7 +895,7 @@ void KeyboardInputMapper::initializeLocked() { } uint32_t KeyboardInputMapper::getSources() { - return mSources; + return mSource; } void KeyboardInputMapper::populateDeviceInfo(InputDeviceInfo* info) { @@ -1036,7 +1079,7 @@ void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t keyCode, getContext()->fadePointer(); } - getDispatcher()->notifyKey(when, getDeviceId(), mSources, policyFlags, + getDispatcher()->notifyKey(when, getDeviceId(), mSource, policyFlags, down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP, AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, newMetaState, downTime); } @@ -1116,7 +1159,7 @@ CursorInputMapper::~CursorInputMapper() { } uint32_t CursorInputMapper::getSources() { - return mSources; + return mSource; } void CursorInputMapper::populateDeviceInfo(InputDeviceInfo* info) { @@ -1125,20 +1168,20 @@ void CursorInputMapper::populateDeviceInfo(InputDeviceInfo* info) { if (mParameters.mode == Parameters::MODE_POINTER) { float minX, minY, maxX, maxY; if (mPointerController->getBounds(&minX, &minY, &maxX, &maxY)) { - info->addMotionRange(AMOTION_EVENT_AXIS_X, minX, maxX, 0.0f, 0.0f); - info->addMotionRange(AMOTION_EVENT_AXIS_Y, minY, maxY, 0.0f, 0.0f); + info->addMotionRange(AMOTION_EVENT_AXIS_X, mSource, minX, maxX, 0.0f, 0.0f); + info->addMotionRange(AMOTION_EVENT_AXIS_Y, mSource, minY, maxY, 0.0f, 0.0f); } } else { - info->addMotionRange(AMOTION_EVENT_AXIS_X, -1.0f, 1.0f, 0.0f, mXScale); - info->addMotionRange(AMOTION_EVENT_AXIS_Y, -1.0f, 1.0f, 0.0f, mYScale); + info->addMotionRange(AMOTION_EVENT_AXIS_X, mSource, -1.0f, 1.0f, 0.0f, mXScale); + info->addMotionRange(AMOTION_EVENT_AXIS_Y, mSource, -1.0f, 1.0f, 0.0f, mYScale); } - info->addMotionRange(AMOTION_EVENT_AXIS_PRESSURE, 0.0f, 1.0f, 0.0f, 0.0f); + info->addMotionRange(AMOTION_EVENT_AXIS_PRESSURE, mSource, 0.0f, 1.0f, 0.0f, 0.0f); if (mHaveVWheel) { - info->addMotionRange(AMOTION_EVENT_AXIS_VSCROLL, -1.0f, 1.0f, 0.0f, 0.0f); + info->addMotionRange(AMOTION_EVENT_AXIS_VSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f); } if (mHaveHWheel) { - info->addMotionRange(AMOTION_EVENT_AXIS_HSCROLL, -1.0f, 1.0f, 0.0f, 0.0f); + info->addMotionRange(AMOTION_EVENT_AXIS_HSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f); } } @@ -1155,7 +1198,8 @@ void CursorInputMapper::dump(String8& dump) { dump.appendFormat(INDENT3 "HaveHWheel: %s\n", toString(mHaveHWheel)); dump.appendFormat(INDENT3 "VWheelScale: %0.3f\n", mVWheelScale); dump.appendFormat(INDENT3 "HWheelScale: %0.3f\n", mHWheelScale); - dump.appendFormat(INDENT3 "Down: %s\n", toString(mLocked.down)); + dump.appendFormat(INDENT3 "ButtonState: 0x%08x\n", mLocked.buttonState); + dump.appendFormat(INDENT3 "Down: %s\n", toString(isPointerDown(mLocked.buttonState))); dump.appendFormat(INDENT3 "DownTime: %lld\n", mLocked.downTime); } // release lock } @@ -1169,7 +1213,7 @@ void CursorInputMapper::configure() { // Configure device mode. switch (mParameters.mode) { case Parameters::MODE_POINTER: - mSources = AINPUT_SOURCE_MOUSE; + mSource = AINPUT_SOURCE_MOUSE; mXPrecision = 1.0f; mYPrecision = 1.0f; mXScale = 1.0f; @@ -1177,7 +1221,7 @@ void CursorInputMapper::configure() { mPointerController = getPolicy()->obtainPointerController(getDeviceId()); break; case Parameters::MODE_NAVIGATION: - mSources = AINPUT_SOURCE_TRACKBALL; + mSource = AINPUT_SOURCE_TRACKBALL; mXPrecision = TRACKBALL_MOVEMENT_THRESHOLD; mYPrecision = TRACKBALL_MOVEMENT_THRESHOLD; mXScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD; @@ -1234,16 +1278,18 @@ void CursorInputMapper::dumpParameters(String8& dump) { void CursorInputMapper::initializeLocked() { mAccumulator.clear(); - mLocked.down = false; + mLocked.buttonState = 0; mLocked.downTime = 0; } void CursorInputMapper::reset() { for (;;) { + uint32_t buttonState; { // acquire lock AutoMutex _l(mLock); - if (! mLocked.down) { + buttonState = mLocked.buttonState; + if (!buttonState) { initializeLocked(); break; // done } @@ -1251,8 +1297,10 @@ void CursorInputMapper::reset() { // Synthesize button up event on reset. nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC); - mAccumulator.fields = Accumulator::FIELD_BTN_MOUSE; - mAccumulator.btnMouse = false; + mAccumulator.clear(); + mAccumulator.buttonDown = 0; + mAccumulator.buttonUp = buttonState; + mAccumulator.fields = Accumulator::FIELD_BUTTONS; sync(when); } @@ -1261,24 +1309,25 @@ void CursorInputMapper::reset() { void CursorInputMapper::process(const RawEvent* rawEvent) { switch (rawEvent->type) { - case EV_KEY: - switch (rawEvent->scanCode) { - case BTN_LEFT: - case BTN_RIGHT: - case BTN_MIDDLE: - case BTN_SIDE: - case BTN_EXTRA: - case BTN_FORWARD: - case BTN_BACK: - case BTN_TASK: - mAccumulator.fields |= Accumulator::FIELD_BTN_MOUSE; - mAccumulator.btnMouse = rawEvent->value != 0; + case EV_KEY: { + uint32_t buttonState = getButtonStateForScanCode(rawEvent->scanCode); + if (buttonState) { + if (rawEvent->value) { + mAccumulator.buttonDown = buttonState; + mAccumulator.buttonUp = 0; + } else { + mAccumulator.buttonDown = 0; + mAccumulator.buttonUp = buttonState; + } + mAccumulator.fields |= Accumulator::FIELD_BUTTONS; + // Sync now since BTN_MOUSE is not necessarily followed by SYN_REPORT and // we need to ensure that we report the up/down promptly. sync(rawEvent->when); break; } break; + } case EV_REL: switch (rawEvent->scanCode) { @@ -1325,23 +1374,26 @@ void CursorInputMapper::sync(nsecs_t when) { { // acquire lock AutoMutex _l(mLock); - bool downChanged = fields & Accumulator::FIELD_BTN_MOUSE; + bool down, downChanged; + bool wasDown = isPointerDown(mLocked.buttonState); + bool buttonsChanged = fields & Accumulator::FIELD_BUTTONS; + if (buttonsChanged) { + mLocked.buttonState = (mLocked.buttonState | mAccumulator.buttonDown) + & ~mAccumulator.buttonUp; - if (downChanged) { - if (mAccumulator.btnMouse) { - if (!mLocked.down) { - mLocked.down = true; - mLocked.downTime = when; - } else { - downChanged = false; - } + down = isPointerDown(mLocked.buttonState); + + if (!wasDown && down) { + mLocked.downTime = when; + downChanged = true; + } else if (wasDown && !down) { + downChanged = true; } else { - if (mLocked.down) { - mLocked.down = false; - } else { - downChanged = false; - } + downChanged = false; } + } else { + down = wasDown; + downChanged = false; } downTime = mLocked.downTime; @@ -1349,8 +1401,8 @@ void CursorInputMapper::sync(nsecs_t when) { float deltaY = fields & Accumulator::FIELD_REL_Y ? mAccumulator.relY * mYScale : 0.0f; if (downChanged) { - motionEventAction = mLocked.down ? AMOTION_EVENT_ACTION_DOWN : AMOTION_EVENT_ACTION_UP; - } else if (mLocked.down || mPointerController == NULL) { + motionEventAction = down ? AMOTION_EVENT_ACTION_DOWN : AMOTION_EVENT_ACTION_UP; + } else if (down || mPointerController == NULL) { motionEventAction = AMOTION_EVENT_ACTION_MOVE; } else { motionEventAction = AMOTION_EVENT_ACTION_HOVER_MOVE; @@ -1393,35 +1445,25 @@ void CursorInputMapper::sync(nsecs_t when) { if (mPointerController != NULL) { mPointerController->move(deltaX, deltaY); - if (downChanged) { - mPointerController->setButtonState(mLocked.down ? POINTER_BUTTON_1 : 0); + if (buttonsChanged) { + mPointerController->setButtonState(mLocked.buttonState); } + float x, y; mPointerController->getPosition(&x, &y); pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x); pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y); if (motionEventAction == AMOTION_EVENT_ACTION_DOWN) { - float minX, minY, maxX, maxY; - if (mPointerController->getBounds(&minX, &minY, &maxX, &maxY)) { - if (x <= minX) { - motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_LEFT; - } else if (x >= maxX) { - motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_RIGHT; - } - if (y <= minY) { - motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_TOP; - } else if (y >= maxY) { - motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_BOTTOM; - } - } + motionEventEdgeFlags = calculateEdgeFlagsUsingPointerBounds( + mPointerController, x, y); } } else { pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, deltaX); pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, deltaY); } - pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, mLocked.down ? 1.0f : 0.0f); + pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, down ? 1.0f : 0.0f); if (mHaveVWheel && (fields & Accumulator::FIELD_REL_WHEEL)) { vscroll = mAccumulator.relWheel; @@ -1449,7 +1491,7 @@ void CursorInputMapper::sync(nsecs_t when) { int32_t metaState = mContext->getGlobalMetaState(); int32_t pointerId = 0; - getDispatcher()->notifyMotion(when, getDeviceId(), mSources, policyFlags, + getDispatcher()->notifyMotion(when, getDeviceId(), mSource, policyFlags, motionEventAction, 0, metaState, motionEventEdgeFlags, 1, &pointerId, &pointerCoords, mXPrecision, mYPrecision, downTime); @@ -1459,7 +1501,7 @@ void CursorInputMapper::sync(nsecs_t when) { pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_VSCROLL, vscroll); pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, hscroll); - getDispatcher()->notifyMotion(when, getDeviceId(), mSources, policyFlags, + getDispatcher()->notifyMotion(when, getDeviceId(), mSource, policyFlags, AMOTION_EVENT_ACTION_SCROLL, 0, metaState, AMOTION_EVENT_EDGE_FLAG_NONE, 1, &pointerId, &pointerCoords, mXPrecision, mYPrecision, downTime); } @@ -1476,7 +1518,9 @@ int32_t CursorInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCod void CursorInputMapper::fadePointer() { { // acquire lock AutoMutex _l(mLock); - mPointerController->fade(); + if (mPointerController != NULL) { + mPointerController->fade(); + } } // release lock } @@ -1496,7 +1540,7 @@ TouchInputMapper::~TouchInputMapper() { } uint32_t TouchInputMapper::getSources() { - return mSources; + return mTouchSource; } void TouchInputMapper::populateDeviceInfo(InputDeviceInfo* info) { @@ -1507,38 +1551,33 @@ void TouchInputMapper::populateDeviceInfo(InputDeviceInfo* info) { // Ensure surface information is up to date so that orientation changes are // noticed immediately. - configureSurfaceLocked(); + if (!configureSurfaceLocked()) { + return; + } - info->addMotionRange(AMOTION_EVENT_AXIS_X, mLocked.orientedRanges.x); - info->addMotionRange(AMOTION_EVENT_AXIS_Y, mLocked.orientedRanges.y); + info->addMotionRange(mLocked.orientedRanges.x); + info->addMotionRange(mLocked.orientedRanges.y); if (mLocked.orientedRanges.havePressure) { - info->addMotionRange(AMOTION_EVENT_AXIS_PRESSURE, - mLocked.orientedRanges.pressure); + info->addMotionRange(mLocked.orientedRanges.pressure); } if (mLocked.orientedRanges.haveSize) { - info->addMotionRange(AMOTION_EVENT_AXIS_SIZE, - mLocked.orientedRanges.size); + info->addMotionRange(mLocked.orientedRanges.size); } if (mLocked.orientedRanges.haveTouchSize) { - info->addMotionRange(AMOTION_EVENT_AXIS_TOUCH_MAJOR, - mLocked.orientedRanges.touchMajor); - info->addMotionRange(AMOTION_EVENT_AXIS_TOUCH_MINOR, - mLocked.orientedRanges.touchMinor); + info->addMotionRange(mLocked.orientedRanges.touchMajor); + info->addMotionRange(mLocked.orientedRanges.touchMinor); } if (mLocked.orientedRanges.haveToolSize) { - info->addMotionRange(AMOTION_EVENT_AXIS_TOOL_MAJOR, - mLocked.orientedRanges.toolMajor); - info->addMotionRange(AMOTION_EVENT_AXIS_TOOL_MINOR, - mLocked.orientedRanges.toolMinor); + info->addMotionRange(mLocked.orientedRanges.toolMajor); + info->addMotionRange(mLocked.orientedRanges.toolMinor); } if (mLocked.orientedRanges.haveOrientation) { - info->addMotionRange(AMOTION_EVENT_AXIS_ORIENTATION, - mLocked.orientedRanges.orientation); + info->addMotionRange(mLocked.orientedRanges.orientation); } } // release lock } @@ -1552,6 +1591,7 @@ void TouchInputMapper::dump(String8& dump) { dumpRawAxes(dump); dumpCalibration(dump); dumpSurfaceLocked(dump); + dump.appendFormat(INDENT3 "Translation and Scaling Factors:\n"); dump.appendFormat(INDENT4 "XScale: %0.3f\n", mLocked.xScale); dump.appendFormat(INDENT4 "YScale: %0.3f\n", mLocked.yScale); @@ -1564,7 +1604,10 @@ void TouchInputMapper::dump(String8& dump) { dump.appendFormat(INDENT4 "ToolSizeAreaBias: %0.3f\n", mLocked.toolSizeAreaBias); dump.appendFormat(INDENT4 "PressureScale: %0.3f\n", mLocked.pressureScale); dump.appendFormat(INDENT4 "SizeScale: %0.3f\n", mLocked.sizeScale); - dump.appendFormat(INDENT4 "OrientationSCale: %0.3f\n", mLocked.orientationScale); + dump.appendFormat(INDENT4 "OrientationScale: %0.3f\n", mLocked.orientationScale); + + dump.appendFormat(INDENT3 "Last Touch:\n"); + dump.appendFormat(INDENT4 "Pointer Count: %d\n", mLastTouch.pointerCount); } // release lock } @@ -1598,10 +1641,10 @@ void TouchInputMapper::configure() { // Configure sources. switch (mParameters.deviceType) { case Parameters::DEVICE_TYPE_TOUCH_SCREEN: - mSources = AINPUT_SOURCE_TOUCHSCREEN; + mTouchSource = AINPUT_SOURCE_TOUCHSCREEN; break; case Parameters::DEVICE_TYPE_TOUCH_PAD: - mSources = AINPUT_SOURCE_TOUCHPAD; + mTouchSource = AINPUT_SOURCE_TOUCHPAD; break; default: assert(false); @@ -1634,17 +1677,20 @@ void TouchInputMapper::configureParameters() { deviceTypeString)) { if (deviceTypeString == "touchScreen") { mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_SCREEN; - } else if (deviceTypeString != "touchPad") { + } else if (deviceTypeString == "touchPad") { + mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_PAD; + } else { LOGW("Invalid value for touch.deviceType: '%s'", deviceTypeString.string()); } } - bool isTouchScreen = mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN; - mParameters.orientationAware = isTouchScreen; + mParameters.orientationAware = mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN; getDevice()->getConfiguration().tryGetProperty(String8("touch.orientationAware"), mParameters.orientationAware); - mParameters.associatedDisplayId = mParameters.orientationAware || isTouchScreen ? 0 : -1; + mParameters.associatedDisplayId = mParameters.orientationAware + || mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN + ? 0 : -1; } void TouchInputMapper::dumpParameters(String8& dump) { @@ -1711,15 +1757,23 @@ bool TouchInputMapper::configureSurfaceLocked() { int32_t height = mRawAxes.y.maxValue - mRawAxes.y.minValue + 1; if (mParameters.associatedDisplayId >= 0) { - bool wantSize = mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN; - bool wantOrientation = mParameters.orientationAware; - // Note: getDisplayInfo is non-reentrant so we can continue holding the lock. if (! getPolicy()->getDisplayInfo(mParameters.associatedDisplayId, - wantSize ? &width : NULL, wantSize ? &height : NULL, - wantOrientation ? &orientation : NULL)) { + &mLocked.associatedDisplayWidth, &mLocked.associatedDisplayHeight, + &mLocked.associatedDisplayOrientation)) { return false; } + + // A touch screen inherits the dimensions of the display. + if (mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN) { + width = mLocked.associatedDisplayWidth; + height = mLocked.associatedDisplayHeight; + } + + // The device inherits the orientation of the display if it is orientation aware. + if (mParameters.orientationAware) { + orientation = mLocked.associatedDisplayOrientation; + } } bool orientationChanged = mLocked.surfaceOrientation != orientation; @@ -1729,7 +1783,7 @@ bool TouchInputMapper::configureSurfaceLocked() { bool sizeChanged = mLocked.surfaceWidth != width || mLocked.surfaceHeight != height; if (sizeChanged) { - LOGI("Device reconfigured: id=%d, name='%s', display size is now %dx%d", + LOGI("Device reconfigured: id=%d, name='%s', surface size is now %dx%d", getDeviceId(), getDeviceName().string(), width, height); mLocked.surfaceWidth = width; @@ -1741,6 +1795,11 @@ bool TouchInputMapper::configureSurfaceLocked() { mLocked.xPrecision = 1.0f / mLocked.xScale; mLocked.yPrecision = 1.0f / mLocked.yScale; + mLocked.orientedRanges.x.axis = AMOTION_EVENT_AXIS_X; + mLocked.orientedRanges.x.source = mTouchSource; + mLocked.orientedRanges.y.axis = AMOTION_EVENT_AXIS_Y; + mLocked.orientedRanges.y.source = mTouchSource; + configureVirtualKeysLocked(); // Scale factor for terms that are not oriented in a particular axis. @@ -1754,11 +1813,16 @@ bool TouchInputMapper::configureSurfaceLocked() { // TouchMajor and TouchMinor factors. if (mCalibration.touchSizeCalibration != Calibration::TOUCH_SIZE_CALIBRATION_NONE) { mLocked.orientedRanges.haveTouchSize = true; + + mLocked.orientedRanges.touchMajor.axis = AMOTION_EVENT_AXIS_TOUCH_MAJOR; + mLocked.orientedRanges.touchMajor.source = mTouchSource; mLocked.orientedRanges.touchMajor.min = 0; mLocked.orientedRanges.touchMajor.max = diagonalSize; mLocked.orientedRanges.touchMajor.flat = 0; mLocked.orientedRanges.touchMajor.fuzz = 0; + mLocked.orientedRanges.touchMinor = mLocked.orientedRanges.touchMajor; + mLocked.orientedRanges.touchMinor.axis = AMOTION_EVENT_AXIS_TOUCH_MINOR; } // ToolMajor and ToolMinor factors. @@ -1802,11 +1866,16 @@ bool TouchInputMapper::configureSurfaceLocked() { } mLocked.orientedRanges.haveToolSize = true; + + mLocked.orientedRanges.toolMajor.axis = AMOTION_EVENT_AXIS_TOOL_MAJOR; + mLocked.orientedRanges.toolMajor.source = mTouchSource; mLocked.orientedRanges.toolMajor.min = 0; mLocked.orientedRanges.toolMajor.max = diagonalSize; mLocked.orientedRanges.toolMajor.flat = 0; mLocked.orientedRanges.toolMajor.fuzz = 0; + mLocked.orientedRanges.toolMinor = mLocked.orientedRanges.toolMajor; + mLocked.orientedRanges.toolMinor.axis = AMOTION_EVENT_AXIS_TOOL_MINOR; } // Pressure factors. @@ -1835,6 +1904,9 @@ bool TouchInputMapper::configureSurfaceLocked() { } mLocked.orientedRanges.havePressure = true; + + mLocked.orientedRanges.pressure.axis = AMOTION_EVENT_AXIS_PRESSURE; + mLocked.orientedRanges.pressure.source = mTouchSource; mLocked.orientedRanges.pressure.min = 0; mLocked.orientedRanges.pressure.max = 1.0; mLocked.orientedRanges.pressure.flat = 0; @@ -1851,6 +1923,9 @@ bool TouchInputMapper::configureSurfaceLocked() { } mLocked.orientedRanges.haveSize = true; + + mLocked.orientedRanges.size.axis = AMOTION_EVENT_AXIS_SIZE; + mLocked.orientedRanges.size.source = mTouchSource; mLocked.orientedRanges.size.min = 0; mLocked.orientedRanges.size.max = 1.0; mLocked.orientedRanges.size.flat = 0; @@ -1867,6 +1942,8 @@ bool TouchInputMapper::configureSurfaceLocked() { } } + mLocked.orientedRanges.orientation.axis = AMOTION_EVENT_AXIS_ORIENTATION; + mLocked.orientedRanges.orientation.source = mTouchSource; mLocked.orientedRanges.orientation.min = - M_PI_2; mLocked.orientedRanges.orientation.max = M_PI_2; mLocked.orientedRanges.orientation.flat = 0; @@ -2381,8 +2458,10 @@ void TouchInputMapper::syncTouch(nsecs_t when, bool havePointerIds) { uint32_t policyFlags = 0; if (mLastTouch.pointerCount == 0 && mCurrentTouch.pointerCount != 0) { - // Hide the pointer on an initial down. - getContext()->fadePointer(); + if (mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN) { + // 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 @@ -2396,7 +2475,7 @@ void TouchInputMapper::syncTouch(nsecs_t when, bool havePointerIds) { // Process touches and virtual keys. TouchResult touchResult = consumeOffScreenTouches(when, policyFlags); if (touchResult == DISPATCH_TOUCH) { - detectGestures(when); + suppressSwipeOntoVirtualKeys(when); dispatchTouches(when, policyFlags); } @@ -2523,7 +2602,7 @@ TouchInputMapper::TouchResult TouchInputMapper::consumeOffScreenTouches( return touchResult; } -void TouchInputMapper::detectGestures(nsecs_t when) { +void TouchInputMapper::suppressSwipeOntoVirtualKeys(nsecs_t when) { // Disable all virtual key touches that happen within a short time interval of the // most recent touch. The idea is to filter out stray virtual key presses when // interacting with the touch screen. @@ -2648,7 +2727,7 @@ void TouchInputMapper::dispatchTouch(nsecs_t when, uint32_t policyFlags, AutoMutex _l(mLock); // Walk through the the active pointers and map touch screen coordinates (TouchData) into - // display coordinates (PointerCoords) and adjust for display orientation. + // display or surface coordinates (PointerCoords) and adjust for display orientation. for (uint32_t outIndex = 0; ! idBits.isEmpty(); outIndex++) { uint32_t id = idBits.firstMarkedBit(); idBits.clearBit(id); @@ -2869,7 +2948,7 @@ void TouchInputMapper::dispatchTouch(nsecs_t when, uint32_t policyFlags, yPrecision = mLocked.orientedYPrecision; } // release lock - getDispatcher()->notifyMotion(when, getDeviceId(), mSources, policyFlags, + getDispatcher()->notifyMotion(when, getDeviceId(), mTouchSource, policyFlags, motionEventAction, 0, getContext()->getGlobalMetaState(), motionEventEdgeFlags, pointerCount, pointerIds, pointerCoords, xPrecision, yPrecision, mDownTime); @@ -3860,9 +3939,11 @@ void JoystickInputMapper::populateDeviceInfo(InputDeviceInfo* info) { for (size_t i = 0; i < mAxes.size(); i++) { const Axis& axis = mAxes.valueAt(i); - info->addMotionRange(axis.axisInfo.axis, axis.min, axis.max, axis.flat, axis.fuzz); + info->addMotionRange(axis.axisInfo.axis, AINPUT_SOURCE_JOYSTICK, + axis.min, axis.max, axis.flat, axis.fuzz); if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) { - info->addMotionRange(axis.axisInfo.highAxis, axis.min, axis.max, axis.flat, axis.fuzz); + info->addMotionRange(axis.axisInfo.highAxis, AINPUT_SOURCE_JOYSTICK, + axis.min, axis.max, axis.flat, axis.fuzz); } } } diff --git a/services/input/InputReader.h b/services/input/InputReader.h index b9e3494..68002ca 100644 --- a/services/input/InputReader.h +++ b/services/input/InputReader.h @@ -389,7 +389,7 @@ private: class KeyboardInputMapper : public InputMapper { public: - KeyboardInputMapper(InputDevice* device, uint32_t sources, int32_t keyboardType); + KeyboardInputMapper(InputDevice* device, uint32_t source, int32_t keyboardType); virtual ~KeyboardInputMapper(); virtual uint32_t getSources(); @@ -414,7 +414,7 @@ private: int32_t scanCode; }; - uint32_t mSources; + uint32_t mSource; int32_t mKeyboardType; // Immutable configuration parameters. @@ -493,7 +493,7 @@ private: struct Accumulator { enum { - FIELD_BTN_MOUSE = 1, + FIELD_BUTTONS = 1, FIELD_REL_X = 2, FIELD_REL_Y = 4, FIELD_REL_WHEEL = 8, @@ -502,7 +502,9 @@ private: uint32_t fields; - bool btnMouse; + uint32_t buttonDown; + uint32_t buttonUp; + int32_t relX; int32_t relY; int32_t relWheel; @@ -513,7 +515,7 @@ private: } } mAccumulator; - int32_t mSources; + int32_t mSource; float mXScale; float mYScale; float mXPrecision; @@ -527,7 +529,7 @@ private: sp<PointerControllerInterface> mPointerController; struct LockedState { - bool down; + uint32_t buttonState; nsecs_t downTime; } mLocked; @@ -629,7 +631,7 @@ protected: }; // Input sources supported by the device. - int32_t mSources; + uint32_t mTouchSource; // sources when reporting touch data // Immutable configuration parameters. struct Parameters { @@ -745,6 +747,10 @@ protected: int32_t surfaceOrientation; int32_t surfaceWidth, surfaceHeight; + // The associated display orientation and width and height set by configureSurfaceLocked(). + int32_t associatedDisplayOrientation; + int32_t associatedDisplayWidth, associatedDisplayHeight; + // Translation and scaling factors, orientation-independent. float xScale; float xPrecision; @@ -870,7 +876,7 @@ private: void dispatchTouch(nsecs_t when, uint32_t policyFlags, TouchData* touch, BitSet32 idBits, uint32_t changedId, uint32_t pointerCount, int32_t motionEventAction); - void detectGestures(nsecs_t when); + void suppressSwipeOntoVirtualKeys(nsecs_t when); bool isPointInsideSurfaceLocked(int32_t x, int32_t y); const VirtualKey* findVirtualKeyHitLocked(int32_t x, int32_t y); @@ -900,7 +906,7 @@ private: FIELD_ABS_X = 2, FIELD_ABS_Y = 4, FIELD_ABS_PRESSURE = 8, - FIELD_ABS_TOOL_WIDTH = 16 + FIELD_ABS_TOOL_WIDTH = 16, }; uint32_t fields; diff --git a/services/input/PointerController.h b/services/input/PointerController.h index e28dd7d..e1dab5c 100644 --- a/services/input/PointerController.h +++ b/services/input/PointerController.h @@ -31,10 +31,6 @@ namespace android { -enum { - POINTER_BUTTON_1 = 1 << 0, -}; - /** * Interface for tracking a single (mouse) pointer. * diff --git a/services/input/tests/InputReader_test.cpp b/services/input/tests/InputReader_test.cpp index f7e1890..67a2e21 100644 --- a/services/input/tests/InputReader_test.cpp +++ b/services/input/tests/InputReader_test.cpp @@ -405,7 +405,8 @@ class FakeEventHub : public EventHubInterface { String8 name; uint32_t classes; PropertyMap configuration; - KeyedVector<int, RawAbsoluteAxisInfo> axes; + KeyedVector<int, RawAbsoluteAxisInfo> absoluteAxes; + KeyedVector<int, bool> relativeAxes; KeyedVector<int32_t, int32_t> keyCodeStates; KeyedVector<int32_t, int32_t> scanCodeStates; KeyedVector<int32_t, int32_t> switchStates; @@ -460,7 +461,7 @@ public: device->configuration.addAll(configuration); } - void addAxis(int32_t deviceId, int axis, + void addAbsoluteAxis(int32_t deviceId, int axis, int32_t minValue, int32_t maxValue, int flat, int fuzz) { Device* device = getDevice(deviceId); @@ -470,7 +471,12 @@ public: info.maxValue = maxValue; info.flat = flat; info.fuzz = fuzz; - device->axes.add(axis, info); + device->absoluteAxes.add(axis, info); + } + + void addRelativeAxis(int32_t deviceId, int32_t axis) { + Device* device = getDevice(deviceId); + device->relativeAxes.add(axis, true); } void setKeyCodeState(int32_t deviceId, int32_t keyCode, int32_t state) { @@ -560,9 +566,9 @@ private: RawAbsoluteAxisInfo* outAxisInfo) const { Device* device = getDevice(deviceId); if (device) { - ssize_t index = device->axes.indexOfKey(axis); + ssize_t index = device->absoluteAxes.indexOfKey(axis); if (index >= 0) { - *outAxisInfo = device->axes.valueAt(index); + *outAxisInfo = device->absoluteAxes.valueAt(index); return OK; } } @@ -570,6 +576,10 @@ private: } virtual bool hasRelativeAxis(int32_t deviceId, int axis) const { + Device* device = getDevice(deviceId); + if (device) { + return device->relativeAxes.indexOfKey(axis) >= 0; + } return false; } @@ -1487,13 +1497,15 @@ protected: } static void assertMotionRange(const InputDeviceInfo& info, - int32_t rangeType, float min, float max, float flat, float fuzz) { - const InputDeviceInfo::MotionRange* range = info.getMotionRange(rangeType); - ASSERT_TRUE(range != NULL) << "Range: " << rangeType; - ASSERT_NEAR(min, range->min, EPSILON) << "Range: " << rangeType; - ASSERT_NEAR(max, range->max, EPSILON) << "Range: " << rangeType; - ASSERT_NEAR(flat, range->flat, EPSILON) << "Range: " << rangeType; - ASSERT_NEAR(fuzz, range->fuzz, EPSILON) << "Range: " << rangeType; + int32_t axis, uint32_t source, float min, float max, float flat, float fuzz) { + const InputDeviceInfo::MotionRange* range = info.getMotionRange(axis, source); + ASSERT_TRUE(range != NULL) << "Axis: " << axis << " Source: " << source; + ASSERT_EQ(axis, range->axis) << "Axis: " << axis << " Source: " << source; + ASSERT_EQ(source, range->source) << "Axis: " << axis << " Source: " << source; + ASSERT_NEAR(min, range->min, EPSILON) << "Axis: " << axis << " Source: " << source; + ASSERT_NEAR(max, range->max, EPSILON) << "Axis: " << axis << " Source: " << source; + ASSERT_NEAR(flat, range->flat, EPSILON) << "Axis: " << axis << " Source: " << source; + ASSERT_NEAR(fuzz, range->fuzz, EPSILON) << "Axis: " << axis << " Source: " << source; } static void assertPointerCoords(const PointerCoords& coords, @@ -2001,10 +2013,10 @@ TEST_F(CursorInputMapperTest, WhenModeIsPointer_PopulateDeviceInfo_ReturnsRangeF mapper->populateDeviceInfo(&info); // Initially there may not be a valid motion range. - ASSERT_EQ(NULL, info.getMotionRange(AINPUT_MOTION_RANGE_X)); - ASSERT_EQ(NULL, info.getMotionRange(AINPUT_MOTION_RANGE_Y)); - ASSERT_NO_FATAL_FAILURE(assertMotionRange(info, AINPUT_MOTION_RANGE_PRESSURE, - 0.0f, 1.0f, 0.0f, 0.0f)); + ASSERT_EQ(NULL, info.getMotionRange(AINPUT_MOTION_RANGE_X, AINPUT_SOURCE_MOUSE)); + ASSERT_EQ(NULL, info.getMotionRange(AINPUT_MOTION_RANGE_Y, AINPUT_SOURCE_MOUSE)); + ASSERT_NO_FATAL_FAILURE(assertMotionRange(info, + AINPUT_MOTION_RANGE_PRESSURE, AINPUT_SOURCE_MOUSE, 0.0f, 1.0f, 0.0f, 0.0f)); // When the bounds are set, then there should be a valid motion range. mFakePointerController->setBounds(1, 2, 800 - 1, 480 - 1); @@ -2012,11 +2024,14 @@ TEST_F(CursorInputMapperTest, WhenModeIsPointer_PopulateDeviceInfo_ReturnsRangeF InputDeviceInfo info2; mapper->populateDeviceInfo(&info2); - ASSERT_NO_FATAL_FAILURE(assertMotionRange(info2, AINPUT_MOTION_RANGE_X, + ASSERT_NO_FATAL_FAILURE(assertMotionRange(info2, + AINPUT_MOTION_RANGE_X, AINPUT_SOURCE_MOUSE, 1, 800 - 1, 0.0f, 0.0f)); - ASSERT_NO_FATAL_FAILURE(assertMotionRange(info2, AINPUT_MOTION_RANGE_Y, + ASSERT_NO_FATAL_FAILURE(assertMotionRange(info2, + AINPUT_MOTION_RANGE_Y, AINPUT_SOURCE_MOUSE, 2, 480 - 1, 0.0f, 0.0f)); - ASSERT_NO_FATAL_FAILURE(assertMotionRange(info2, AINPUT_MOTION_RANGE_PRESSURE, + ASSERT_NO_FATAL_FAILURE(assertMotionRange(info2, + AINPUT_MOTION_RANGE_PRESSURE, AINPUT_SOURCE_MOUSE, 0.0f, 1.0f, 0.0f, 0.0f)); } @@ -2028,11 +2043,14 @@ TEST_F(CursorInputMapperTest, WhenModeIsNavigation_PopulateDeviceInfo_ReturnsSca InputDeviceInfo info; mapper->populateDeviceInfo(&info); - ASSERT_NO_FATAL_FAILURE(assertMotionRange(info, AINPUT_MOTION_RANGE_X, + ASSERT_NO_FATAL_FAILURE(assertMotionRange(info, + AINPUT_MOTION_RANGE_X, AINPUT_SOURCE_TRACKBALL, -1.0f, 1.0f, 0.0f, 1.0f / TRACKBALL_MOVEMENT_THRESHOLD)); - ASSERT_NO_FATAL_FAILURE(assertMotionRange(info, AINPUT_MOTION_RANGE_Y, + ASSERT_NO_FATAL_FAILURE(assertMotionRange(info, + AINPUT_MOTION_RANGE_Y, AINPUT_SOURCE_TRACKBALL, -1.0f, 1.0f, 0.0f, 1.0f / TRACKBALL_MOVEMENT_THRESHOLD)); - ASSERT_NO_FATAL_FAILURE(assertMotionRange(info, AINPUT_MOTION_RANGE_PRESSURE, + ASSERT_NO_FATAL_FAILURE(assertMotionRange(info, + AINPUT_MOTION_RANGE_PRESSURE, AINPUT_SOURCE_TRACKBALL, 0.0f, 1.0f, 0.0f, 0.0f)); } @@ -2385,14 +2403,18 @@ protected: void SingleTouchInputMapperTest::prepareAxes(int axes) { if (axes & POSITION) { - mFakeEventHub->addAxis(DEVICE_ID, ABS_X, RAW_X_MIN, RAW_X_MAX, 0, 0); - mFakeEventHub->addAxis(DEVICE_ID, ABS_Y, RAW_Y_MIN, RAW_Y_MAX, 0, 0); + mFakeEventHub->addAbsoluteAxis(DEVICE_ID, ABS_X, + RAW_X_MIN, RAW_X_MAX, 0, 0); + mFakeEventHub->addAbsoluteAxis(DEVICE_ID, ABS_Y, + RAW_Y_MIN, RAW_Y_MAX, 0, 0); } if (axes & PRESSURE) { - mFakeEventHub->addAxis(DEVICE_ID, ABS_PRESSURE, RAW_PRESSURE_MIN, RAW_PRESSURE_MAX, 0, 0); + mFakeEventHub->addAbsoluteAxis(DEVICE_ID, ABS_PRESSURE, + RAW_PRESSURE_MIN, RAW_PRESSURE_MAX, 0, 0); } if (axes & TOOL) { - mFakeEventHub->addAxis(DEVICE_ID, ABS_TOOL_WIDTH, RAW_TOOL_MIN, RAW_TOOL_MAX, 0, 0); + mFakeEventHub->addAbsoluteAxis(DEVICE_ID, ABS_TOOL_WIDTH, + RAW_TOOL_MIN, RAW_TOOL_MAX, 0, 0); } } @@ -3040,33 +3062,37 @@ protected: void MultiTouchInputMapperTest::prepareAxes(int axes) { if (axes & POSITION) { - mFakeEventHub->addAxis(DEVICE_ID, ABS_MT_POSITION_X, RAW_X_MIN, RAW_X_MAX, 0, 0); - mFakeEventHub->addAxis(DEVICE_ID, ABS_MT_POSITION_Y, RAW_Y_MIN, RAW_Y_MAX, 0, 0); + mFakeEventHub->addAbsoluteAxis(DEVICE_ID, ABS_MT_POSITION_X, + RAW_X_MIN, RAW_X_MAX, 0, 0); + mFakeEventHub->addAbsoluteAxis(DEVICE_ID, ABS_MT_POSITION_Y, + RAW_Y_MIN, RAW_Y_MAX, 0, 0); } if (axes & TOUCH) { - mFakeEventHub->addAxis(DEVICE_ID, ABS_MT_TOUCH_MAJOR, RAW_TOUCH_MIN, RAW_TOUCH_MAX, 0, 0); + mFakeEventHub->addAbsoluteAxis(DEVICE_ID, ABS_MT_TOUCH_MAJOR, + RAW_TOUCH_MIN, RAW_TOUCH_MAX, 0, 0); if (axes & MINOR) { - mFakeEventHub->addAxis(DEVICE_ID, ABS_MT_TOUCH_MINOR, + mFakeEventHub->addAbsoluteAxis(DEVICE_ID, ABS_MT_TOUCH_MINOR, RAW_TOUCH_MIN, RAW_TOUCH_MAX, 0, 0); } } if (axes & TOOL) { - mFakeEventHub->addAxis(DEVICE_ID, ABS_MT_WIDTH_MAJOR, RAW_TOOL_MIN, RAW_TOOL_MAX, 0, 0); + mFakeEventHub->addAbsoluteAxis(DEVICE_ID, ABS_MT_WIDTH_MAJOR, + RAW_TOOL_MIN, RAW_TOOL_MAX, 0, 0); if (axes & MINOR) { - mFakeEventHub->addAxis(DEVICE_ID, ABS_MT_WIDTH_MINOR, + mFakeEventHub->addAbsoluteAxis(DEVICE_ID, ABS_MT_WIDTH_MINOR, RAW_TOOL_MAX, RAW_TOOL_MAX, 0, 0); } } if (axes & ORIENTATION) { - mFakeEventHub->addAxis(DEVICE_ID, ABS_MT_ORIENTATION, + mFakeEventHub->addAbsoluteAxis(DEVICE_ID, ABS_MT_ORIENTATION, RAW_ORIENTATION_MIN, RAW_ORIENTATION_MAX, 0, 0); } if (axes & PRESSURE) { - mFakeEventHub->addAxis(DEVICE_ID, ABS_MT_PRESSURE, + mFakeEventHub->addAbsoluteAxis(DEVICE_ID, ABS_MT_PRESSURE, RAW_PRESSURE_MIN, RAW_PRESSURE_MAX, 0, 0); } if (axes & ID) { - mFakeEventHub->addAxis(DEVICE_ID, ABS_MT_TRACKING_ID, + mFakeEventHub->addAbsoluteAxis(DEVICE_ID, ABS_MT_TRACKING_ID, RAW_ID_MIN, RAW_ID_MAX, 0, 0); } } diff --git a/services/jni/com_android_server_InputManager.cpp b/services/jni/com_android_server_InputManager.cpp index bd4e787..80dddc2 100644 --- a/services/jni/com_android_server_InputManager.cpp +++ b/services/jni/com_android_server_InputManager.cpp @@ -1103,12 +1103,11 @@ static jobject android_server_InputManager_nativeGetInputDevice(JNIEnv* env, env->SetIntField(deviceObj, gInputDeviceClassInfo.mSources, deviceInfo.getSources()); env->SetIntField(deviceObj, gInputDeviceClassInfo.mKeyboardType, deviceInfo.getKeyboardType()); - const KeyedVector<int, InputDeviceInfo::MotionRange>& ranges = deviceInfo.getMotionRanges(); + const Vector<InputDeviceInfo::MotionRange>& ranges = deviceInfo.getMotionRanges(); for (size_t i = 0; i < ranges.size(); i++) { - int rangeType = ranges.keyAt(i); - const InputDeviceInfo::MotionRange& range = ranges.valueAt(i); + const InputDeviceInfo::MotionRange& range = ranges.itemAt(i); env->CallVoidMethod(deviceObj, gInputDeviceClassInfo.addMotionRange, - rangeType, range.min, range.max, range.flat, range.fuzz); + range.axis, range.source, range.min, range.max, range.flat, range.fuzz); if (env->ExceptionCheck()) { return NULL; } @@ -1321,7 +1320,7 @@ int register_android_server_InputManager(JNIEnv* env) { "<init>", "()V"); GET_METHOD_ID(gInputDeviceClassInfo.addMotionRange, gInputDeviceClassInfo.clazz, - "addMotionRange", "(IFFFF)V"); + "addMotionRange", "(IIFFFF)V"); GET_FIELD_ID(gInputDeviceClassInfo.mId, gInputDeviceClassInfo.clazz, "mId", "I"); |