diff options
author | Jeff Brown <jeffbrown@google.com> | 2011-07-01 17:37:58 -0700 |
---|---|---|
committer | Jeff Brown <jeffbrown@google.com> | 2011-07-25 20:04:18 -0700 |
commit | 49754db5a304d995c1cc108ff6f19e4ba4265572 (patch) | |
tree | cb09f23e7dd81ea505f90962fd550e36afbbc422 /services/input | |
parent | 44e504e089b7483448c386741c5ee31d2c325400 (diff) | |
download | frameworks_base-49754db5a304d995c1cc108ff6f19e4ba4265572.zip frameworks_base-49754db5a304d995c1cc108ff6f19e4ba4265572.tar.gz frameworks_base-49754db5a304d995c1cc108ff6f19e4ba4265572.tar.bz2 |
Handle stylus buttons and tool types.
Added TOOL_TYPE_ERASER.
Refactored the InputReader to share more code between the
various input mappers that handle button states and to
simplify the accumulator implementations by having each
one only handle a single type of input.
Removed the concept of direct/indirect tool types from the API.
If we add it back, it should be done in a manner that is orthogonal
to the tool type itself, perhaps as a flags field on the pointer.
The device source may well provide sufficient information anyhow.
Change-Id: I811c22d95e8304269b6ee4f6d11a6b04f3cfc1b2
Diffstat (limited to 'services/input')
-rw-r--r-- | services/input/EventHub.cpp | 11 | ||||
-rw-r--r-- | services/input/EventHub.h | 2 | ||||
-rw-r--r-- | services/input/InputReader.cpp | 944 | ||||
-rw-r--r-- | services/input/InputReader.h | 322 | ||||
-rw-r--r-- | services/input/tests/InputReader_test.cpp | 39 |
5 files changed, 737 insertions, 581 deletions
diff --git a/services/input/EventHub.cpp b/services/input/EventHub.cpp index ca2540b..7ea3de2 100644 --- a/services/input/EventHub.cpp +++ b/services/input/EventHub.cpp @@ -460,6 +460,17 @@ void EventHub::setExcludedDevices(const Vector<String8>& devices) { mExcludedDevices = devices; } +bool EventHub::hasScanCode(int32_t deviceId, int32_t scanCode) const { + AutoMutex _l(mLock); + Device* device = getDeviceLocked(deviceId); + if (device && scanCode >= 0 && scanCode <= KEY_MAX) { + if (test_bit(scanCode, device->keyBitmask)) { + return true; + } + } + return false; +} + bool EventHub::hasLed(int32_t deviceId, int32_t led) const { AutoMutex _l(mLock); Device* device = getDeviceLocked(deviceId); diff --git a/services/input/EventHub.h b/services/input/EventHub.h index 695dfdf..293a1a0 100644 --- a/services/input/EventHub.h +++ b/services/input/EventHub.h @@ -195,6 +195,7 @@ public: virtual bool markSupportedKeyCodes(int32_t deviceId, size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) const = 0; + virtual bool hasScanCode(int32_t deviceId, int32_t scanCode) const = 0; virtual bool hasLed(int32_t deviceId, int32_t led) const = 0; virtual void setLedState(int32_t deviceId, int32_t led, bool on) = 0; @@ -246,6 +247,7 @@ public: virtual size_t getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize); + virtual bool hasScanCode(int32_t deviceId, int32_t scanCode) const; virtual bool hasLed(int32_t deviceId, int32_t led) const; virtual void setLedState(int32_t deviceId, int32_t led, bool on); diff --git a/services/input/InputReader.cpp b/services/input/InputReader.cpp index 3e041f3..9d69c60 100644 --- a/services/input/InputReader.cpp +++ b/services/input/InputReader.cpp @@ -151,30 +151,6 @@ 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: - return AMOTION_EVENT_BUTTON_PRIMARY; - case BTN_RIGHT: - case BTN_STYLUS: - return AMOTION_EVENT_BUTTON_SECONDARY; - case BTN_MIDDLE: - case BTN_STYLUS2: - return AMOTION_EVENT_BUTTON_TERTIARY; - case BTN_SIDE: - return AMOTION_EVENT_BUTTON_BACK; - case BTN_FORWARD: - case BTN_EXTRA: - return AMOTION_EVENT_BUTTON_FORWARD; - case BTN_BACK: - return AMOTION_EVENT_BUTTON_BACK; - case BTN_TASK: - default: - return 0; - } -} - // Returns true if the pointer should be reported as being down given the specified // button states. This determines whether the event is reported as a touch event. static bool isPointerDown(int32_t buttonState) { @@ -1007,6 +983,378 @@ void InputDevice::fadePointer() { } +// --- CursorButtonAccumulator --- + +CursorButtonAccumulator::CursorButtonAccumulator() { + clearButtons(); +} + +void CursorButtonAccumulator::clearButtons() { + mBtnLeft = 0; + mBtnRight = 0; + mBtnMiddle = 0; + mBtnBack = 0; + mBtnSide = 0; + mBtnForward = 0; + mBtnExtra = 0; + mBtnTask = 0; +} + +void CursorButtonAccumulator::process(const RawEvent* rawEvent) { + if (rawEvent->type == EV_KEY) { + switch (rawEvent->scanCode) { + case BTN_LEFT: + mBtnLeft = rawEvent->value; + break; + case BTN_RIGHT: + mBtnRight = rawEvent->value; + break; + case BTN_MIDDLE: + mBtnMiddle = rawEvent->value; + break; + case BTN_BACK: + mBtnBack = rawEvent->value; + break; + case BTN_SIDE: + mBtnSide = rawEvent->value; + break; + case BTN_FORWARD: + mBtnForward = rawEvent->value; + break; + case BTN_EXTRA: + mBtnExtra = rawEvent->value; + break; + case BTN_TASK: + mBtnTask = rawEvent->value; + break; + } + } +} + +uint32_t CursorButtonAccumulator::getButtonState() const { + uint32_t result = 0; + if (mBtnLeft) { + result |= AMOTION_EVENT_BUTTON_PRIMARY; + } + if (mBtnRight) { + result |= AMOTION_EVENT_BUTTON_SECONDARY; + } + if (mBtnMiddle) { + result |= AMOTION_EVENT_BUTTON_TERTIARY; + } + if (mBtnBack || mBtnSide) { + result |= AMOTION_EVENT_BUTTON_BACK; + } + if (mBtnForward || mBtnExtra) { + result |= AMOTION_EVENT_BUTTON_FORWARD; + } + return result; +} + + +// --- CursorMotionAccumulator --- + +CursorMotionAccumulator::CursorMotionAccumulator() : + mHaveRelWheel(false), mHaveRelHWheel(false) { + clearRelativeAxes(); +} + +void CursorMotionAccumulator::configure(InputDevice* device) { + mHaveRelWheel = device->getEventHub()->hasRelativeAxis(device->getId(), REL_WHEEL); + mHaveRelHWheel = device->getEventHub()->hasRelativeAxis(device->getId(), REL_HWHEEL); +} + +void CursorMotionAccumulator::clearRelativeAxes() { + mRelX = 0; + mRelY = 0; + mRelWheel = 0; + mRelHWheel = 0; +} + +void CursorMotionAccumulator::process(const RawEvent* rawEvent) { + if (rawEvent->type == EV_REL) { + switch (rawEvent->scanCode) { + case REL_X: + mRelX = rawEvent->value; + break; + case REL_Y: + mRelY = rawEvent->value; + break; + case REL_WHEEL: + mRelWheel = rawEvent->value; + break; + case REL_HWHEEL: + mRelHWheel = rawEvent->value; + break; + } + } +} + + +// --- TouchButtonAccumulator --- + +TouchButtonAccumulator::TouchButtonAccumulator() : + mHaveBtnTouch(false) { + clearButtons(); +} + +void TouchButtonAccumulator::configure(InputDevice* device) { + mHaveBtnTouch = device->getEventHub()->hasScanCode(device->getId(), BTN_TOUCH); +} + +void TouchButtonAccumulator::clearButtons() { + mBtnTouch = 0; + mBtnStylus = 0; + mBtnStylus2 = 0; + mBtnToolFinger = 0; + mBtnToolPen = 0; + mBtnToolRubber = 0; +} + +void TouchButtonAccumulator::process(const RawEvent* rawEvent) { + if (rawEvent->type == EV_KEY) { + switch (rawEvent->scanCode) { + case BTN_TOUCH: + mBtnTouch = rawEvent->value; + break; + case BTN_STYLUS: + mBtnStylus = rawEvent->value; + break; + case BTN_STYLUS2: + mBtnStylus2 = rawEvent->value; + break; + case BTN_TOOL_FINGER: + mBtnToolFinger = rawEvent->value; + break; + case BTN_TOOL_PEN: + mBtnToolPen = rawEvent->value; + break; + case BTN_TOOL_RUBBER: + mBtnToolRubber = rawEvent->value; + break; + } + } +} + +uint32_t TouchButtonAccumulator::getButtonState() const { + uint32_t result = 0; + if (mBtnStylus) { + result |= AMOTION_EVENT_BUTTON_SECONDARY; + } + if (mBtnStylus2) { + result |= AMOTION_EVENT_BUTTON_TERTIARY; + } + return result; +} + +int32_t TouchButtonAccumulator::getToolType() const { + if (mBtnToolRubber) { + return AMOTION_EVENT_TOOL_TYPE_ERASER; + } + if (mBtnToolPen) { + return AMOTION_EVENT_TOOL_TYPE_STYLUS; + } + if (mBtnToolFinger) { + return AMOTION_EVENT_TOOL_TYPE_FINGER; + } + return AMOTION_EVENT_TOOL_TYPE_UNKNOWN; +} + +bool TouchButtonAccumulator::isActive() const { + return mBtnTouch || mBtnToolFinger || mBtnToolPen + || mBtnToolRubber || mBtnStylus || mBtnStylus2; +} + +bool TouchButtonAccumulator::isHovering() const { + return mHaveBtnTouch && !mBtnTouch; +} + + +// --- SingleTouchMotionAccumulator --- + +SingleTouchMotionAccumulator::SingleTouchMotionAccumulator() { + clearAbsoluteAxes(); +} + +void SingleTouchMotionAccumulator::clearAbsoluteAxes() { + mAbsX = 0; + mAbsY = 0; + mAbsPressure = 0; + mAbsToolWidth = 0; + mAbsDistance = 0; +} + +void SingleTouchMotionAccumulator::process(const RawEvent* rawEvent) { + if (rawEvent->type == EV_ABS) { + switch (rawEvent->scanCode) { + case ABS_X: + mAbsX = rawEvent->value; + break; + case ABS_Y: + mAbsY = rawEvent->value; + break; + case ABS_PRESSURE: + mAbsPressure = rawEvent->value; + break; + case ABS_TOOL_WIDTH: + mAbsToolWidth = rawEvent->value; + break; + case ABS_DISTANCE: + mAbsDistance = rawEvent->value; + break; + } + } +} + + +// --- MultiTouchMotionAccumulator --- + +MultiTouchMotionAccumulator::MultiTouchMotionAccumulator() : + mCurrentSlot(-1), mSlots(NULL), mSlotCount(0), mUsingSlotsProtocol(false) { +} + +MultiTouchMotionAccumulator::~MultiTouchMotionAccumulator() { + delete[] mSlots; +} + +void MultiTouchMotionAccumulator::configure(size_t slotCount, bool usingSlotsProtocol) { + mSlotCount = slotCount; + mUsingSlotsProtocol = usingSlotsProtocol; + + delete[] mSlots; + mSlots = new Slot[slotCount]; +} + +void MultiTouchMotionAccumulator::clearSlots(int32_t initialSlot) { + for (size_t i = 0; i < mSlotCount; i++) { + mSlots[i].clearIfInUse(); + } + mCurrentSlot = initialSlot; +} + +void MultiTouchMotionAccumulator::process(const RawEvent* rawEvent) { + if (rawEvent->type == EV_ABS) { + bool newSlot = false; + if (mUsingSlotsProtocol) { + if (rawEvent->scanCode == ABS_MT_SLOT) { + mCurrentSlot = rawEvent->value; + newSlot = true; + } + } else if (mCurrentSlot < 0) { + mCurrentSlot = 0; + } + + if (mCurrentSlot < 0 || size_t(mCurrentSlot) >= mSlotCount) { +#if DEBUG_POINTERS + if (newSlot) { + LOGW("MultiTouch device emitted invalid slot index %d but it " + "should be between 0 and %d; ignoring this slot.", + mCurrentSlot, mSlotCount - 1); + } +#endif + } else { + Slot* slot = &mSlots[mCurrentSlot]; + + switch (rawEvent->scanCode) { + case ABS_MT_POSITION_X: + slot->mInUse = true; + slot->mAbsMTPositionX = rawEvent->value; + break; + case ABS_MT_POSITION_Y: + slot->mInUse = true; + slot->mAbsMTPositionY = rawEvent->value; + break; + case ABS_MT_TOUCH_MAJOR: + slot->mInUse = true; + slot->mAbsMTTouchMajor = rawEvent->value; + break; + case ABS_MT_TOUCH_MINOR: + slot->mInUse = true; + slot->mAbsMTTouchMinor = rawEvent->value; + slot->mHaveAbsMTTouchMinor = true; + break; + case ABS_MT_WIDTH_MAJOR: + slot->mInUse = true; + slot->mAbsMTWidthMajor = rawEvent->value; + break; + case ABS_MT_WIDTH_MINOR: + slot->mInUse = true; + slot->mAbsMTWidthMinor = rawEvent->value; + slot->mHaveAbsMTWidthMinor = true; + break; + case ABS_MT_ORIENTATION: + slot->mInUse = true; + slot->mAbsMTOrientation = rawEvent->value; + break; + case ABS_MT_TRACKING_ID: + if (mUsingSlotsProtocol && rawEvent->value < 0) { + slot->clearIfInUse(); + } else { + slot->mInUse = true; + slot->mAbsMTTrackingId = rawEvent->value; + } + break; + case ABS_MT_PRESSURE: + slot->mInUse = true; + slot->mAbsMTPressure = rawEvent->value; + break; + case ABS_MT_TOOL_TYPE: + slot->mInUse = true; + slot->mAbsMTToolType = rawEvent->value; + slot->mHaveAbsMTToolType = true; + break; + } + } + } else if (rawEvent->type == EV_SYN && rawEvent->scanCode == SYN_MT_REPORT) { + // MultiTouch Sync: The driver has returned all data for *one* of the pointers. + mCurrentSlot += 1; + } +} + + +// --- MultiTouchMotionAccumulator::Slot --- + +MultiTouchMotionAccumulator::Slot::Slot() { + clear(); +} + +void MultiTouchMotionAccumulator::Slot::clearIfInUse() { + if (mInUse) { + clear(); + } +} + +void MultiTouchMotionAccumulator::Slot::clear() { + mInUse = false; + mHaveAbsMTTouchMinor = false; + mHaveAbsMTWidthMinor = false; + mHaveAbsMTToolType = false; + mAbsMTPositionX = 0; + mAbsMTPositionY = 0; + mAbsMTTouchMajor = 0; + mAbsMTTouchMinor = 0; + mAbsMTWidthMajor = 0; + mAbsMTWidthMinor = 0; + mAbsMTOrientation = 0; + mAbsMTTrackingId = -1; + mAbsMTPressure = 0; + mAbsMTToolType = 0; + mAbsMTDistance = 0; +} + +int32_t MultiTouchMotionAccumulator::Slot::getToolType() const { + if (mHaveAbsMTToolType) { + switch (mAbsMTToolType) { + case MT_TOOL_FINGER: + return AMOTION_EVENT_TOOL_TYPE_FINGER; + case MT_TOOL_PEN: + return AMOTION_EVENT_TOOL_TYPE_STYLUS; + } + } + return AMOTION_EVENT_TOOL_TYPE_UNKNOWN; +} + + // --- InputMapper --- InputMapper::InputMapper(InputDevice* device) : @@ -1399,10 +1747,10 @@ void CursorInputMapper::populateDeviceInfo(InputDeviceInfo* info) { } info->addMotionRange(AMOTION_EVENT_AXIS_PRESSURE, mSource, 0.0f, 1.0f, 0.0f, 0.0f); - if (mHaveVWheel) { + if (mCursorMotionAccumulator.haveRelativeVWheel()) { info->addMotionRange(AMOTION_EVENT_AXIS_VSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f); } - if (mHaveHWheel) { + if (mCursorMotionAccumulator.haveRelativeHWheel()) { info->addMotionRange(AMOTION_EVENT_AXIS_HSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f); } } @@ -1416,8 +1764,10 @@ void CursorInputMapper::dump(String8& dump) { dump.appendFormat(INDENT3 "YScale: %0.3f\n", mYScale); dump.appendFormat(INDENT3 "XPrecision: %0.3f\n", mXPrecision); dump.appendFormat(INDENT3 "YPrecision: %0.3f\n", mYPrecision); - dump.appendFormat(INDENT3 "HaveVWheel: %s\n", toString(mHaveVWheel)); - dump.appendFormat(INDENT3 "HaveHWheel: %s\n", toString(mHaveHWheel)); + dump.appendFormat(INDENT3 "HaveVWheel: %s\n", + toString(mCursorMotionAccumulator.haveRelativeVWheel())); + dump.appendFormat(INDENT3 "HaveHWheel: %s\n", + toString(mCursorMotionAccumulator.haveRelativeHWheel())); dump.appendFormat(INDENT3 "VWheelScale: %0.3f\n", mVWheelScale); dump.appendFormat(INDENT3 "HWheelScale: %0.3f\n", mHWheelScale); dump.appendFormat(INDENT3 "ButtonState: 0x%08x\n", mLocked.buttonState); @@ -1430,6 +1780,8 @@ void CursorInputMapper::configure(const InputReaderConfiguration* config, uint32 InputMapper::configure(config, changes); if (!changes) { // first time only + mCursorMotionAccumulator.configure(getDevice()); + // Configure basic parameters. configureParameters(); @@ -1454,9 +1806,6 @@ void CursorInputMapper::configure(const InputReaderConfiguration* config, uint32 mVWheelScale = 1.0f; mHWheelScale = 1.0f; - - mHaveVWheel = getEventHub()->hasRelativeAxis(getDeviceId(), REL_WHEEL); - mHaveHWheel = getEventHub()->hasRelativeAxis(getDeviceId(), REL_HWHEEL); } if (!changes || (changes & InputReaderConfiguration::CHANGE_POINTER_SPEED)) { @@ -1506,7 +1855,8 @@ void CursorInputMapper::dumpParameters(String8& dump) { } void CursorInputMapper::initializeLocked() { - mAccumulator.clear(); + mCursorButtonAccumulator.clearButtons(); + mCursorMotionAccumulator.clearRelativeAxes(); mLocked.buttonState = 0; mLocked.downTime = 0; @@ -1532,10 +1882,8 @@ void CursorInputMapper::reset() { // Synthesize button up event on reset. nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC); - mAccumulator.clear(); - mAccumulator.buttonDown = 0; - mAccumulator.buttonUp = buttonState; - mAccumulator.fields = Accumulator::FIELD_BUTTONS; + mCursorButtonAccumulator.clearButtons(); + mCursorMotionAccumulator.clearRelativeAxes(); sync(when); } @@ -1543,64 +1891,15 @@ void CursorInputMapper::reset() { } void CursorInputMapper::process(const RawEvent* rawEvent) { - switch (rawEvent->type) { - case EV_KEY: { - int32_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; + mCursorButtonAccumulator.process(rawEvent); + mCursorMotionAccumulator.process(rawEvent); - // 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) { - case REL_X: - mAccumulator.fields |= Accumulator::FIELD_REL_X; - mAccumulator.relX = rawEvent->value; - break; - case REL_Y: - mAccumulator.fields |= Accumulator::FIELD_REL_Y; - mAccumulator.relY = rawEvent->value; - break; - case REL_WHEEL: - mAccumulator.fields |= Accumulator::FIELD_REL_WHEEL; - mAccumulator.relWheel = rawEvent->value; - break; - case REL_HWHEEL: - mAccumulator.fields |= Accumulator::FIELD_REL_HWHEEL; - mAccumulator.relHWheel = rawEvent->value; - break; - } - break; - - case EV_SYN: - switch (rawEvent->scanCode) { - case SYN_REPORT: - sync(rawEvent->when); - break; - } - break; + if (rawEvent->type == EV_SYN && rawEvent->scanCode == SYN_REPORT) { + sync(rawEvent->when); } } void CursorInputMapper::sync(nsecs_t when) { - uint32_t fields = mAccumulator.fields; - if (fields == 0) { - return; // no new state changes, so nothing to do - } - int32_t motionEventAction; int32_t lastButtonState, currentButtonState; PointerProperties pointerProperties; @@ -1611,34 +1910,21 @@ void CursorInputMapper::sync(nsecs_t when) { AutoMutex _l(mLock); lastButtonState = mLocked.buttonState; + currentButtonState = mCursorButtonAccumulator.getButtonState(); + mLocked.buttonState = currentButtonState; - bool down, downChanged; - bool wasDown = isPointerDown(mLocked.buttonState); - bool buttonsChanged = fields & Accumulator::FIELD_BUTTONS; - if (buttonsChanged) { - mLocked.buttonState = (mLocked.buttonState | mAccumulator.buttonDown) - & ~mAccumulator.buttonUp; - - down = isPointerDown(mLocked.buttonState); - - if (!wasDown && down) { - mLocked.downTime = when; - downChanged = true; - } else if (wasDown && !down) { - downChanged = true; - } else { - downChanged = false; - } + bool wasDown = isPointerDown(lastButtonState); + bool down = isPointerDown(currentButtonState); + bool downChanged; + if (!wasDown && down) { + mLocked.downTime = when; + downChanged = true; + } else if (wasDown && !down) { + downChanged = true; } else { - down = wasDown; downChanged = false; } - - currentButtonState = mLocked.buttonState; - downTime = mLocked.downTime; - float deltaX = fields & Accumulator::FIELD_REL_X ? mAccumulator.relX * mXScale : 0.0f; - float deltaY = fields & Accumulator::FIELD_REL_Y ? mAccumulator.relY * mYScale : 0.0f; if (downChanged) { motionEventAction = down ? AMOTION_EVENT_ACTION_DOWN : AMOTION_EVENT_ACTION_UP; @@ -1648,6 +1934,9 @@ void CursorInputMapper::sync(nsecs_t when) { motionEventAction = AMOTION_EVENT_ACTION_HOVER_MOVE; } + float deltaX = mCursorMotionAccumulator.getRelativeX() * mXScale; + float deltaY = mCursorMotionAccumulator.getRelativeY() * mYScale; + if (mParameters.orientationAware && mParameters.associatedDisplayId >= 0 && (deltaX != 0.0f || deltaY != 0.0f)) { // Rotate motion based on display orientation if needed. @@ -1667,25 +1956,17 @@ void CursorInputMapper::sync(nsecs_t when) { pointerCoords.clear(); - if (mHaveVWheel && (fields & Accumulator::FIELD_REL_WHEEL)) { - vscroll = mAccumulator.relWheel; - } else { - vscroll = 0; - } - mWheelYVelocityControl.move(when, NULL, &vscroll); + vscroll = mCursorMotionAccumulator.getRelativeVWheel(); + hscroll = mCursorMotionAccumulator.getRelativeHWheel(); - if (mHaveHWheel && (fields & Accumulator::FIELD_REL_HWHEEL)) { - hscroll = mAccumulator.relHWheel; - } else { - hscroll = 0; - } + mWheelYVelocityControl.move(when, NULL, &vscroll); mWheelXVelocityControl.move(when, &hscroll, NULL); mPointerVelocityControl.move(when, &deltaX, &deltaY); if (mPointerController != NULL) { if (deltaX != 0 || deltaY != 0 || vscroll != 0 || hscroll != 0 - || buttonsChanged) { + || currentButtonState != lastButtonState) { mPointerController->setPresentation( PointerControllerInterface::PRESENTATION_POINTER); @@ -1693,8 +1974,8 @@ void CursorInputMapper::sync(nsecs_t when) { mPointerController->move(deltaX, deltaY); } - if (buttonsChanged) { - mPointerController->setButtonState(mLocked.buttonState); + if (currentButtonState != lastButtonState) { + mPointerController->setButtonState(currentButtonState); } mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE); @@ -1755,7 +2036,7 @@ void CursorInputMapper::sync(nsecs_t when) { synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_UP, when, getDeviceId(), mSource, policyFlags, lastButtonState, currentButtonState); - mAccumulator.clear(); + mCursorMotionAccumulator.clearRelativeAxes(); } int32_t CursorInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) { @@ -1881,10 +2162,11 @@ void TouchInputMapper::dump(String8& dump) { const PointerData& pointer = mLastTouch.pointers[i]; dump.appendFormat(INDENT5 "[%d]: id=%d, x=%d, y=%d, pressure=%d, " "touchMajor=%d, touchMinor=%d, toolMajor=%d, toolMinor=%d, " - "orientation=%d, distance=%d, isStylus=%s\n", i, + "orientation=%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, toString(pointer.isStylus)); + pointer.orientation, pointer.distance, + pointer.toolType, toString(pointer.isHovering)); } if (mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER) { @@ -2924,6 +3206,7 @@ void TouchInputMapper::syncTouch(nsecs_t when, bool havePointerIds) { calculatePointerIds(); } + // Handle initial down events. uint32_t policyFlags = 0; if (mLastTouch.pointerCount == 0 && mCurrentTouch.pointerCount != 0) { if (mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN) { @@ -3420,7 +3703,7 @@ void TouchInputMapper::prepareTouches(float* outXPrecision, float* outYPrecision PointerProperties& properties = mCurrentTouchProperties[i]; properties.clear(); properties.id = mCurrentTouch.pointers[i].id; - properties.toolType = getTouchToolType(mCurrentTouch.pointers[i].isStylus); + properties.toolType = mCurrentTouch.pointers[i].toolType; } *outXPrecision = mLocked.orientedXPrecision; @@ -3604,7 +3887,7 @@ void TouchInputMapper::dispatchPointerGestures(nsecs_t when, uint32_t policyFlag PointerProperties pointerProperties; pointerProperties.clear(); pointerProperties.id = 0; - pointerProperties.toolType = AMOTION_EVENT_TOOL_TYPE_INDIRECT_FINGER; + pointerProperties.toolType = AMOTION_EVENT_TOOL_TYPE_FINGER; PointerCoords pointerCoords; pointerCoords.clear(); @@ -3838,8 +4121,7 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0; mPointerGesture.currentGestureProperties[0].clear(); mPointerGesture.currentGestureProperties[0].id = mPointerGesture.activeGestureId; - mPointerGesture.currentGestureProperties[0].toolType = - AMOTION_EVENT_TOOL_TYPE_INDIRECT_FINGER; + mPointerGesture.currentGestureProperties[0].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER; mPointerGesture.currentGestureCoords[0].clear(); mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, x); mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, y); @@ -3880,7 +4162,7 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, mPointerGesture.currentGestureProperties[0].id = mPointerGesture.activeGestureId; mPointerGesture.currentGestureProperties[0].toolType = - AMOTION_EVENT_TOOL_TYPE_INDIRECT_FINGER; + AMOTION_EVENT_TOOL_TYPE_FINGER; mPointerGesture.currentGestureCoords[0].clear(); mPointerGesture.currentGestureCoords[0].setAxisValue( AMOTION_EVENT_AXIS_X, mPointerGesture.tapX); @@ -3993,7 +4275,7 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, mPointerGesture.currentGestureProperties[0].clear(); mPointerGesture.currentGestureProperties[0].id = mPointerGesture.activeGestureId; mPointerGesture.currentGestureProperties[0].toolType = - AMOTION_EVENT_TOOL_TYPE_INDIRECT_FINGER; + AMOTION_EVENT_TOOL_TYPE_FINGER; mPointerGesture.currentGestureCoords[0].clear(); mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, x); mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, y); @@ -4240,7 +4522,7 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, mPointerGesture.currentGestureProperties[0].clear(); mPointerGesture.currentGestureProperties[0].id = mPointerGesture.activeGestureId; mPointerGesture.currentGestureProperties[0].toolType = - AMOTION_EVENT_TOOL_TYPE_INDIRECT_FINGER; + AMOTION_EVENT_TOOL_TYPE_FINGER; mPointerGesture.currentGestureCoords[0].clear(); mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, mPointerGesture.referenceGestureX); @@ -4331,7 +4613,7 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, mPointerGesture.currentGestureProperties[i].clear(); mPointerGesture.currentGestureProperties[i].id = gestureId; mPointerGesture.currentGestureProperties[i].toolType = - AMOTION_EVENT_TOOL_TYPE_INDIRECT_FINGER; + AMOTION_EVENT_TOOL_TYPE_FINGER; mPointerGesture.currentGestureCoords[i].clear(); mPointerGesture.currentGestureCoords[i].setAxisValue( AMOTION_EVENT_AXIS_X, mPointerGesture.referenceGestureX + deltaX); @@ -4473,15 +4755,6 @@ void TouchInputMapper::fadePointer() { } // release lock } -int32_t TouchInputMapper::getTouchToolType(bool isStylus) const { - if (mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN) { - return isStylus ? AMOTION_EVENT_TOOL_TYPE_STYLUS : AMOTION_EVENT_TOOL_TYPE_FINGER; - } else { - return isStylus ? AMOTION_EVENT_TOOL_TYPE_INDIRECT_STYLUS - : AMOTION_EVENT_TOOL_TYPE_INDIRECT_FINGER; - } -} - bool TouchInputMapper::isPointInsideSurfaceLocked(int32_t x, int32_t y) { return x >= mRawAxes.x.minValue && x <= mRawAxes.x.maxValue && y >= mRawAxes.y.minValue && y <= mRawAxes.y.maxValue; @@ -4760,14 +5033,9 @@ SingleTouchInputMapper::~SingleTouchInputMapper() { } void SingleTouchInputMapper::clearState() { - mAccumulator.clear(); - - mDown = false; - mX = 0; - mY = 0; - mPressure = 0; // default to 0 for devices that don't report pressure - mToolWidth = 0; // default to 0 for devices that don't report tool width - mButtonState = 0; + mCursorButtonAccumulator.clearButtons(); + mTouchButtonAccumulator.clearButtons(); + mSingleTouchMotionAccumulator.clearAbsoluteAxes(); } void SingleTouchInputMapper::reset() { @@ -4777,144 +5045,79 @@ void SingleTouchInputMapper::reset() { } void SingleTouchInputMapper::process(const RawEvent* rawEvent) { - switch (rawEvent->type) { - case EV_KEY: - switch (rawEvent->scanCode) { - case BTN_TOUCH: - mAccumulator.fields |= Accumulator::FIELD_BTN_TOUCH; - mAccumulator.btnTouch = rawEvent->value != 0; - // Don't sync immediately. Wait until the next SYN_REPORT since we might - // not have received valid position information yet. This logic assumes that - // BTN_TOUCH is always followed by SYN_REPORT as part of a complete packet. - break; - default: - if (mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER) { - int32_t buttonState = getButtonStateForScanCode(rawEvent->scanCode); - if (buttonState) { - if (rawEvent->value) { - mAccumulator.buttonDown |= buttonState; - } else { - mAccumulator.buttonUp |= buttonState; - } - mAccumulator.fields |= Accumulator::FIELD_BUTTONS; - } - } - break; - } - break; - - case EV_ABS: - switch (rawEvent->scanCode) { - case ABS_X: - mAccumulator.fields |= Accumulator::FIELD_ABS_X; - mAccumulator.absX = rawEvent->value; - break; - case ABS_Y: - mAccumulator.fields |= Accumulator::FIELD_ABS_Y; - mAccumulator.absY = rawEvent->value; - break; - case ABS_PRESSURE: - mAccumulator.fields |= Accumulator::FIELD_ABS_PRESSURE; - mAccumulator.absPressure = rawEvent->value; - break; - case ABS_TOOL_WIDTH: - mAccumulator.fields |= Accumulator::FIELD_ABS_TOOL_WIDTH; - mAccumulator.absToolWidth = rawEvent->value; - break; - } - break; + mCursorButtonAccumulator.process(rawEvent); + mTouchButtonAccumulator.process(rawEvent); + mSingleTouchMotionAccumulator.process(rawEvent); - case EV_SYN: - switch (rawEvent->scanCode) { - case SYN_REPORT: - sync(rawEvent->when); - break; - } - break; + if (rawEvent->type == EV_SYN && rawEvent->scanCode == SYN_REPORT) { + sync(rawEvent->when); } } void SingleTouchInputMapper::sync(nsecs_t when) { - uint32_t fields = mAccumulator.fields; - if (fields == 0) { - return; // no new state changes, so nothing to do - } - - if (fields & Accumulator::FIELD_BTN_TOUCH) { - mDown = mAccumulator.btnTouch; - } - - if (fields & Accumulator::FIELD_ABS_X) { - mX = mAccumulator.absX; - } - - if (fields & Accumulator::FIELD_ABS_Y) { - mY = mAccumulator.absY; - } - - if (fields & Accumulator::FIELD_ABS_PRESSURE) { - mPressure = mAccumulator.absPressure; - } - - if (fields & Accumulator::FIELD_ABS_TOOL_WIDTH) { - mToolWidth = mAccumulator.absToolWidth; - } - - if (fields & Accumulator::FIELD_BUTTONS) { - mButtonState = (mButtonState | mAccumulator.buttonDown) & ~mAccumulator.buttonUp; - } - mCurrentTouch.clear(); - if (mDown) { + if (mTouchButtonAccumulator.isActive()) { + uint32_t buttonState = mTouchButtonAccumulator.getButtonState(); + bool isHovering = mTouchButtonAccumulator.isHovering(); + if (mSingleTouchMotionAccumulator.getAbsoluteDistance() > 0) { + isHovering = true; + } + mCurrentTouch.pointerCount = 1; - mCurrentTouch.pointers[0].id = 0; - mCurrentTouch.pointers[0].x = mX; - mCurrentTouch.pointers[0].y = mY; - mCurrentTouch.pointers[0].pressure = mPressure; - mCurrentTouch.pointers[0].touchMajor = 0; - mCurrentTouch.pointers[0].touchMinor = 0; - mCurrentTouch.pointers[0].toolMajor = mToolWidth; - mCurrentTouch.pointers[0].toolMinor = mToolWidth; - mCurrentTouch.pointers[0].orientation = 0; - mCurrentTouch.pointers[0].distance = 0; - mCurrentTouch.pointers[0].isStylus = false; // TODO: Set stylus mCurrentTouch.idToIndex[0] = 0; mCurrentTouch.idBits.markBit(0); - mCurrentTouch.buttonState = mButtonState; + mCurrentTouch.buttonState = buttonState; + + PointerData& outPointer = mCurrentTouch.pointers[0]; + outPointer.id = 0; + outPointer.x = mSingleTouchMotionAccumulator.getAbsoluteX(); + outPointer.y = mSingleTouchMotionAccumulator.getAbsoluteY(); + outPointer.pressure = mSingleTouchMotionAccumulator.getAbsolutePressure(); + outPointer.touchMajor = 0; + outPointer.touchMinor = 0; + outPointer.toolMajor = mSingleTouchMotionAccumulator.getAbsoluteToolWidth(); + outPointer.toolMinor = mSingleTouchMotionAccumulator.getAbsoluteToolWidth(); + outPointer.orientation = 0; + outPointer.distance = mSingleTouchMotionAccumulator.getAbsoluteDistance(); + outPointer.toolType = mTouchButtonAccumulator.getToolType(); + if (outPointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) { + outPointer.toolType = AMOTION_EVENT_TOOL_TYPE_FINGER; + } + outPointer.isHovering = isHovering; } syncTouch(when, true); - - mAccumulator.clear(); } void SingleTouchInputMapper::configureRawAxes() { TouchInputMapper::configureRawAxes(); + mTouchButtonAccumulator.configure(getDevice()); + getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_X, & mRawAxes.x); getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_Y, & mRawAxes.y); getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_PRESSURE, & mRawAxes.pressure); getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_TOOL_WIDTH, & mRawAxes.toolMajor); + getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_DISTANCE, & mRawAxes.distance); } // --- MultiTouchInputMapper --- MultiTouchInputMapper::MultiTouchInputMapper(InputDevice* device) : - TouchInputMapper(device), mSlotCount(0), mUsingSlotsProtocol(false) { + TouchInputMapper(device) { } MultiTouchInputMapper::~MultiTouchInputMapper() { } void MultiTouchInputMapper::clearState() { - mAccumulator.clearSlots(mSlotCount); - mAccumulator.clearButtons(); - mButtonState = 0; + mCursorButtonAccumulator.clearButtons(); + mTouchButtonAccumulator.clearButtons(); mPointerIdBits.clear(); - if (mUsingSlotsProtocol) { + 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 @@ -4924,12 +5127,16 @@ void MultiTouchInputMapper::clearState() { // 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, - &mAccumulator.currentSlot); + &initialSlot); if (status) { LOGW("Could not retrieve current multitouch slot index. status=%d", status); - mAccumulator.currentSlot = -1; + initialSlot = -1; } + mMultiTouchMotionAccumulator.clearSlots(initialSlot); + } else { + mMultiTouchMotionAccumulator.clearSlots(-1); } } @@ -4940,124 +5147,26 @@ void MultiTouchInputMapper::reset() { } void MultiTouchInputMapper::process(const RawEvent* rawEvent) { - switch (rawEvent->type) { - case EV_KEY: { - if (mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER) { - int32_t buttonState = getButtonStateForScanCode(rawEvent->scanCode); - if (buttonState) { - if (rawEvent->value) { - mAccumulator.buttonDown |= buttonState; - } else { - mAccumulator.buttonUp |= buttonState; - } - } - } - break; - } - - case EV_ABS: { - bool newSlot = false; - if (mUsingSlotsProtocol && rawEvent->scanCode == ABS_MT_SLOT) { - mAccumulator.currentSlot = rawEvent->value; - newSlot = true; - } - - if (mAccumulator.currentSlot < 0 || size_t(mAccumulator.currentSlot) >= mSlotCount) { -#if DEBUG_POINTERS - if (newSlot) { - LOGW("MultiTouch device %s emitted invalid slot index %d but it " - "should be between 0 and %d; ignoring this slot.", - getDeviceName().string(), mAccumulator.currentSlot, mSlotCount); - } -#endif - break; - } - - Accumulator::Slot* slot = &mAccumulator.slots[mAccumulator.currentSlot]; - - switch (rawEvent->scanCode) { - case ABS_MT_POSITION_X: - slot->fields |= Accumulator::FIELD_ABS_MT_POSITION_X; - slot->absMTPositionX = rawEvent->value; - break; - case ABS_MT_POSITION_Y: - slot->fields |= Accumulator::FIELD_ABS_MT_POSITION_Y; - slot->absMTPositionY = rawEvent->value; - break; - case ABS_MT_TOUCH_MAJOR: - slot->fields |= Accumulator::FIELD_ABS_MT_TOUCH_MAJOR; - slot->absMTTouchMajor = rawEvent->value; - break; - case ABS_MT_TOUCH_MINOR: - slot->fields |= Accumulator::FIELD_ABS_MT_TOUCH_MINOR; - slot->absMTTouchMinor = rawEvent->value; - break; - case ABS_MT_WIDTH_MAJOR: - slot->fields |= Accumulator::FIELD_ABS_MT_WIDTH_MAJOR; - slot->absMTWidthMajor = rawEvent->value; - break; - case ABS_MT_WIDTH_MINOR: - slot->fields |= Accumulator::FIELD_ABS_MT_WIDTH_MINOR; - slot->absMTWidthMinor = rawEvent->value; - break; - case ABS_MT_ORIENTATION: - slot->fields |= Accumulator::FIELD_ABS_MT_ORIENTATION; - slot->absMTOrientation = rawEvent->value; - break; - case ABS_MT_TRACKING_ID: - if (mUsingSlotsProtocol && rawEvent->value < 0) { - slot->clear(); - } else { - slot->fields |= Accumulator::FIELD_ABS_MT_TRACKING_ID; - slot->absMTTrackingId = rawEvent->value; - } - break; - case ABS_MT_PRESSURE: - slot->fields |= Accumulator::FIELD_ABS_MT_PRESSURE; - slot->absMTPressure = rawEvent->value; - break; - case ABS_MT_TOOL_TYPE: - slot->fields |= Accumulator::FIELD_ABS_MT_TOOL_TYPE; - slot->absMTToolType = rawEvent->value; - break; - } - break; - } + mCursorButtonAccumulator.process(rawEvent); + mTouchButtonAccumulator.process(rawEvent); + mMultiTouchMotionAccumulator.process(rawEvent); - case EV_SYN: - switch (rawEvent->scanCode) { - case SYN_MT_REPORT: { - // MultiTouch Sync: The driver has returned all data for *one* of the pointers. - mAccumulator.currentSlot += 1; - break; - } - - case SYN_REPORT: - sync(rawEvent->when); - break; - } - break; + if (rawEvent->type == EV_SYN && rawEvent->scanCode == SYN_REPORT) { + sync(rawEvent->when); } } void MultiTouchInputMapper::sync(nsecs_t when) { - static const uint32_t REQUIRED_FIELDS = - Accumulator::FIELD_ABS_MT_POSITION_X | Accumulator::FIELD_ABS_MT_POSITION_Y; - - size_t inCount = mSlotCount; + size_t inCount = mMultiTouchMotionAccumulator.getSlotCount(); size_t outCount = 0; bool havePointerIds = true; mCurrentTouch.clear(); for (size_t inIndex = 0; inIndex < inCount; inIndex++) { - const Accumulator::Slot& inSlot = mAccumulator.slots[inIndex]; - uint32_t fields = inSlot.fields; - - if ((fields & REQUIRED_FIELDS) != REQUIRED_FIELDS) { - // Some drivers send empty MT sync packets without X / Y to indicate a pointer up. - // This may also indicate an unused slot. - // Drop this finger. + const MultiTouchMotionAccumulator::Slot* inSlot = + mMultiTouchMotionAccumulator.getSlot(inIndex); + if (!inSlot->isInUse()) { continue; } @@ -5071,71 +5180,32 @@ void MultiTouchInputMapper::sync(nsecs_t when) { } PointerData& outPointer = mCurrentTouch.pointers[outCount]; - outPointer.x = inSlot.absMTPositionX; - outPointer.y = inSlot.absMTPositionY; - - if (fields & Accumulator::FIELD_ABS_MT_PRESSURE) { - outPointer.pressure = inSlot.absMTPressure; - } else { - // Default pressure to 0 if absent. - outPointer.pressure = 0; - } - - if (fields & Accumulator::FIELD_ABS_MT_TOUCH_MAJOR) { - outPointer.touchMajor = inSlot.absMTTouchMajor; - } else { - // Default touch area to 0 if absent. - outPointer.touchMajor = 0; - } - - if (fields & Accumulator::FIELD_ABS_MT_TOUCH_MINOR) { - outPointer.touchMinor = inSlot.absMTTouchMinor; - } else { - // Assume touch area is circular. - outPointer.touchMinor = outPointer.touchMajor; - } - - if (fields & Accumulator::FIELD_ABS_MT_WIDTH_MAJOR) { - outPointer.toolMajor = inSlot.absMTWidthMajor; - } else { - // Default tool area to 0 if absent. - outPointer.toolMajor = 0; - } - - if (fields & Accumulator::FIELD_ABS_MT_WIDTH_MINOR) { - outPointer.toolMinor = inSlot.absMTWidthMinor; - } else { - // Assume tool area is circular. - outPointer.toolMinor = outPointer.toolMajor; - } - - if (fields & Accumulator::FIELD_ABS_MT_ORIENTATION) { - outPointer.orientation = inSlot.absMTOrientation; - } else { - // Default orientation to vertical if absent. - outPointer.orientation = 0; - } - - if (fields & Accumulator::FIELD_ABS_MT_DISTANCE) { - outPointer.distance = inSlot.absMTDistance; - } else { - // Default distance is 0 (direct contact). - outPointer.distance = 0; + outPointer.x = inSlot->getX(); + outPointer.y = inSlot->getY(); + outPointer.pressure = inSlot->getPressure(); + outPointer.touchMajor = inSlot->getTouchMajor(); + outPointer.touchMinor = inSlot->getTouchMinor(); + outPointer.toolMajor = inSlot->getToolMajor(); + outPointer.toolMinor = inSlot->getToolMinor(); + outPointer.orientation = inSlot->getOrientation(); + outPointer.distance = inSlot->getDistance(); + + outPointer.toolType = inSlot->getToolType(); + if (outPointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) { + outPointer.toolType = mTouchButtonAccumulator.getToolType(); + if (outPointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) { + outPointer.toolType = AMOTION_EVENT_TOOL_TYPE_FINGER; + } } - if (fields & Accumulator::FIELD_ABS_MT_TOOL_TYPE) { - outPointer.isStylus = (inSlot.absMTToolType == MT_TOOL_PEN); - } else { - // Assume this is not a stylus. - outPointer.isStylus = false; - } + outPointer.isHovering = mTouchButtonAccumulator.isHovering() + || inSlot->getDistance() > 0; // Assign pointer id using tracking id if available. if (havePointerIds) { + int32_t trackingId = inSlot->getTrackingId(); int32_t id = -1; - if (fields & Accumulator::FIELD_ABS_MT_TRACKING_ID) { - int32_t trackingId = inSlot.absMTTrackingId; - + if (trackingId >= 0) { for (BitSet32 idBits(mPointerIdBits); !idBits.isEmpty(); ) { uint32_t n = idBits.firstMarkedBit(); idBits.clearBit(n); @@ -5165,23 +5235,22 @@ void MultiTouchInputMapper::sync(nsecs_t when) { } mCurrentTouch.pointerCount = outCount; - - mButtonState = (mButtonState | mAccumulator.buttonDown) & ~mAccumulator.buttonUp; - mCurrentTouch.buttonState = mButtonState; + mCurrentTouch.buttonState = mTouchButtonAccumulator.getButtonState(); mPointerIdBits = mCurrentTouch.idBits; syncTouch(when, havePointerIds); - if (!mUsingSlotsProtocol) { - mAccumulator.clearSlots(mSlotCount); + if (!mMultiTouchMotionAccumulator.isUsingSlotsProtocol()) { + mMultiTouchMotionAccumulator.clearSlots(-1); } - mAccumulator.clearButtons(); } void MultiTouchInputMapper::configureRawAxes() { TouchInputMapper::configureRawAxes(); + mTouchButtonAccumulator.configure(getDevice()); + getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_POSITION_X, &mRawAxes.x); getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_POSITION_Y, &mRawAxes.y); getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_TOUCH_MAJOR, &mRawAxes.touchMajor); @@ -5196,21 +5265,18 @@ void MultiTouchInputMapper::configureRawAxes() { if (mRawAxes.trackingId.valid && mRawAxes.slot.valid && mRawAxes.slot.minValue == 0 && mRawAxes.slot.maxValue > 0) { - mSlotCount = mRawAxes.slot.maxValue + 1; - if (mSlotCount > MAX_SLOTS) { + size_t slotCount = mRawAxes.slot.maxValue + 1; + if (slotCount > MAX_SLOTS) { LOGW("MultiTouch Device %s reported %d slots but the framework " "only supports a maximum of %d slots at this time.", - getDeviceName().string(), mSlotCount, MAX_SLOTS); - mSlotCount = MAX_SLOTS; + getDeviceName().string(), slotCount, MAX_SLOTS); + slotCount = MAX_SLOTS; } - mUsingSlotsProtocol = true; + mMultiTouchMotionAccumulator.configure(slotCount, true /*usingSlotsProtocol*/); } else { - mSlotCount = MAX_POINTERS; - mUsingSlotsProtocol = false; + mMultiTouchMotionAccumulator.configure(MAX_POINTERS, false /*usingSlotsProtocol*/); } - mAccumulator.allocateSlots(mSlotCount); - clearState(); } diff --git a/services/input/InputReader.h b/services/input/InputReader.h index b1fdcf2..f9750d0 100644 --- a/services/input/InputReader.h +++ b/services/input/InputReader.h @@ -430,9 +430,8 @@ public: void fadePointer(); - inline const PropertyMap& getConfiguration() { - return mConfiguration; - } + inline const PropertyMap& getConfiguration() { return mConfiguration; } + inline EventHubInterface* getEventHub() { return mContext->getEventHub(); } private: InputReaderContext* mContext; @@ -452,6 +451,171 @@ private: }; +/* Keeps track of the state of mouse or touch pad buttons. */ +class CursorButtonAccumulator { +public: + CursorButtonAccumulator(); + + void clearButtons(); + void process(const RawEvent* rawEvent); + + uint32_t getButtonState() const; + +private: + bool mBtnLeft; + bool mBtnRight; + bool mBtnMiddle; + bool mBtnBack; + bool mBtnSide; + bool mBtnForward; + bool mBtnExtra; + bool mBtnTask; +}; + + +/* Keeps track of cursor movements. */ + +class CursorMotionAccumulator { +public: + CursorMotionAccumulator(); + void configure(InputDevice* device); + + void clearRelativeAxes(); + void process(const RawEvent* rawEvent); + + inline bool haveRelativeVWheel() const { return mHaveRelWheel; } + inline bool haveRelativeHWheel() const { return mHaveRelHWheel; } + + inline int32_t getRelativeX() const { return mRelX; } + inline int32_t getRelativeY() const { return mRelY; } + inline int32_t getRelativeVWheel() const { return mRelWheel; } + inline int32_t getRelativeHWheel() const { return mRelHWheel; } + +private: + bool mHaveRelWheel; + bool mHaveRelHWheel; + + int32_t mRelX; + int32_t mRelY; + int32_t mRelWheel; + int32_t mRelHWheel; +}; + + +/* Keeps track of the state of touch, stylus and tool buttons. */ +class TouchButtonAccumulator { +public: + TouchButtonAccumulator(); + void configure(InputDevice* device); + + void clearButtons(); + void process(const RawEvent* rawEvent); + + uint32_t getButtonState() const; + int32_t getToolType() const; + bool isActive() const; + bool isHovering() const; + +private: + bool mHaveBtnTouch; + + bool mBtnTouch; + bool mBtnStylus; + bool mBtnStylus2; + bool mBtnToolFinger; + bool mBtnToolPen; + bool mBtnToolRubber; +}; + + +/* Keeps track of the state of single-touch protocol. */ +class SingleTouchMotionAccumulator { +public: + SingleTouchMotionAccumulator(); + + void clearAbsoluteAxes(); + void process(const RawEvent* rawEvent); + + 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; } + +private: + int32_t mAbsX; + int32_t mAbsY; + int32_t mAbsPressure; + int32_t mAbsToolWidth; + int32_t mAbsDistance; +}; + + +/* Keeps track of the state of multi-touch protocol. */ +class MultiTouchMotionAccumulator { +public: + class Slot { + public: + inline bool isInUse() const { return mInUse; } + inline int32_t getX() const { return mAbsMTPositionX; } + inline int32_t getY() const { return mAbsMTPositionY; } + inline int32_t getTouchMajor() const { return mAbsMTTouchMajor; } + inline int32_t getTouchMinor() const { + return mHaveAbsMTTouchMinor ? mAbsMTTouchMinor : mAbsMTTouchMajor; } + inline int32_t getToolMajor() const { return mAbsMTWidthMajor; } + inline int32_t getToolMinor() const { + return mHaveAbsMTWidthMinor ? mAbsMTWidthMinor : mAbsMTWidthMajor; } + inline int32_t getOrientation() const { return mAbsMTOrientation; } + inline int32_t getTrackingId() const { return mAbsMTTrackingId; } + inline int32_t getPressure() const { return mAbsMTPressure; } + inline int32_t getDistance() const { return mAbsMTDistance; } + inline int32_t getToolType() const; + + private: + friend class MultiTouchMotionAccumulator; + + bool mInUse; + bool mHaveAbsMTTouchMinor; + bool mHaveAbsMTWidthMinor; + bool mHaveAbsMTToolType; + + int32_t mAbsMTPositionX; + int32_t mAbsMTPositionY; + int32_t mAbsMTTouchMajor; + int32_t mAbsMTTouchMinor; + int32_t mAbsMTWidthMajor; + int32_t mAbsMTWidthMinor; + int32_t mAbsMTOrientation; + int32_t mAbsMTTrackingId; + int32_t mAbsMTPressure; + int32_t mAbsMTToolType; + int32_t mAbsMTDistance; + + Slot(); + void clearIfInUse(); + void clear(); + }; + + MultiTouchMotionAccumulator(); + ~MultiTouchMotionAccumulator(); + + void configure(size_t slotCount, bool usingSlotsProtocol); + void process(const RawEvent* rawEvent); + + 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]; } + +private: + int32_t mCurrentSlot; + Slot* mSlots; + size_t mSlotCount; + bool mUsingSlotsProtocol; +}; + + /* 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. @@ -615,29 +779,8 @@ private: bool orientationAware; } mParameters; - struct Accumulator { - enum { - FIELD_BUTTONS = 1, - FIELD_REL_X = 2, - FIELD_REL_Y = 4, - FIELD_REL_WHEEL = 8, - FIELD_REL_HWHEEL = 16, - }; - - uint32_t fields; - - uint32_t buttonDown; - uint32_t buttonUp; - - int32_t relX; - int32_t relY; - int32_t relWheel; - int32_t relHWheel; - - inline void clear() { - fields = 0; - } - } mAccumulator; + CursorButtonAccumulator mCursorButtonAccumulator; + CursorMotionAccumulator mCursorMotionAccumulator; int32_t mSource; float mXScale; @@ -645,8 +788,6 @@ private: float mXPrecision; float mYPrecision; - bool mHaveVWheel; - bool mHaveHWheel; float mVWheelScale; float mHWheelScale; @@ -722,7 +863,8 @@ protected: int32_t toolMinor; int32_t orientation; int32_t distance; - bool isStylus; + int32_t toolType; // AMOTION_EVENT_TOOL_TYPE constant + bool isHovering; inline bool operator== (const PointerData& other) const { return id == other.id @@ -734,7 +876,9 @@ protected: && toolMajor == other.toolMajor && toolMinor == other.toolMinor && orientation == other.orientation - && distance == other.distance; + && distance == other.distance + && toolType == other.toolType + && isHovering == other.isHovering; } inline bool operator!= (const PointerData& other) const { return !(*this == other); @@ -1201,7 +1345,6 @@ private: void suppressSwipeOntoVirtualKeys(nsecs_t when); - int32_t getTouchToolType(bool isStylus) const; bool isPointInsideSurfaceLocked(int32_t x, int32_t y); const VirtualKey* findVirtualKeyHitLocked(int32_t x, int32_t y); @@ -1221,40 +1364,9 @@ protected: virtual void configureRawAxes(); private: - struct Accumulator { - enum { - FIELD_BTN_TOUCH = 1, - FIELD_ABS_X = 2, - FIELD_ABS_Y = 4, - FIELD_ABS_PRESSURE = 8, - FIELD_ABS_TOOL_WIDTH = 16, - FIELD_BUTTONS = 32, - }; - - uint32_t fields; - - bool btnTouch; - int32_t absX; - int32_t absY; - int32_t absPressure; - int32_t absToolWidth; - - uint32_t buttonDown; - uint32_t buttonUp; - - inline void clear() { - fields = 0; - buttonDown = 0; - buttonUp = 0; - } - } mAccumulator; - - bool mDown; - int32_t mX; - int32_t mY; - int32_t mPressure; - int32_t mToolWidth; - int32_t mButtonState; + CursorButtonAccumulator mCursorButtonAccumulator; + TouchButtonAccumulator mTouchButtonAccumulator; + SingleTouchMotionAccumulator mSingleTouchMotionAccumulator; void clearState(); @@ -1274,83 +1386,9 @@ protected: virtual void configureRawAxes(); private: - struct Accumulator { - enum { - FIELD_ABS_MT_POSITION_X = 1 << 0, - FIELD_ABS_MT_POSITION_Y = 1 << 1, - FIELD_ABS_MT_TOUCH_MAJOR = 1 << 2, - FIELD_ABS_MT_TOUCH_MINOR = 1 << 3, - FIELD_ABS_MT_WIDTH_MAJOR = 1 << 4, - FIELD_ABS_MT_WIDTH_MINOR = 1 << 5, - FIELD_ABS_MT_ORIENTATION = 1 << 6, - FIELD_ABS_MT_TRACKING_ID = 1 << 7, - FIELD_ABS_MT_PRESSURE = 1 << 8, - FIELD_ABS_MT_TOOL_TYPE = 1 << 9, - FIELD_ABS_MT_DISTANCE = 1 << 10, - }; - - struct Slot { - uint32_t fields; // 0 if slot is unused - - int32_t absMTPositionX; - int32_t absMTPositionY; - int32_t absMTTouchMajor; - int32_t absMTTouchMinor; - int32_t absMTWidthMajor; - int32_t absMTWidthMinor; - int32_t absMTOrientation; - int32_t absMTTrackingId; - int32_t absMTPressure; - int32_t absMTToolType; - int32_t absMTDistance; - - inline Slot() { - clear(); - } - - inline void clear() { - fields = 0; - } - }; - - // Current slot index. - int32_t currentSlot; - - // Array of slots. - Slot* slots; - - // Bitfield of buttons that went down or up. - uint32_t buttonDown; - uint32_t buttonUp; - - Accumulator() : currentSlot(0), slots(NULL), buttonDown(0), buttonUp(0) { - } - - ~Accumulator() { - delete[] slots; - } - - void allocateSlots(size_t slotCount) { - slots = new Slot[slotCount]; - } - - void clearSlots(size_t slotCount) { - for (size_t i = 0; i < slotCount; i++) { - slots[i].clear(); - } - currentSlot = 0; - } - - void clearButtons() { - buttonDown = 0; - buttonUp = 0; - } - } mAccumulator; - - size_t mSlotCount; - bool mUsingSlotsProtocol; - - int32_t mButtonState; + CursorButtonAccumulator mCursorButtonAccumulator; + TouchButtonAccumulator mTouchButtonAccumulator; + MultiTouchMotionAccumulator mMultiTouchMotionAccumulator; // Specifies the pointer id bits that are in use, and their associated tracking id. BitSet32 mPointerIdBits; diff --git a/services/input/tests/InputReader_test.cpp b/services/input/tests/InputReader_test.cpp index 131894a..7a6af25 100644 --- a/services/input/tests/InputReader_test.cpp +++ b/services/input/tests/InputReader_test.cpp @@ -707,6 +707,15 @@ private: return result; } + virtual bool hasScanCode(int32_t deviceId, int32_t scanCode) const { + Device* device = getDevice(deviceId); + if (device) { + ssize_t index = device->keys.indexOfKey(scanCode); + return index >= 0; + } + return false; + } + virtual bool hasLed(int32_t deviceId, int32_t led) const { Device* device = getDevice(deviceId); return device && device->leds.indexOfKey(led) >= 0; @@ -2116,6 +2125,7 @@ TEST_F(CursorInputMapperTest, Process_ShouldSetAllFieldsAndIncludeGlobalMetaStat // Button press. // Mostly testing non x/y behavior here so we don't need to check again elsewhere. 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(mFakeDispatcher->assertNotifyMotionWasCalled(&args)); ASSERT_EQ(ARBITRARY_TIME, args.eventTime); ASSERT_EQ(DEVICE_ID, args.deviceId); @@ -2137,6 +2147,7 @@ TEST_F(CursorInputMapperTest, Process_ShouldSetAllFieldsAndIncludeGlobalMetaStat // Button release. Should have same down time. process(mapper, ARBITRARY_TIME + 1, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 0, 0); + process(mapper, ARBITRARY_TIME + 1, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0); ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args)); ASSERT_EQ(ARBITRARY_TIME + 1, args.eventTime); ASSERT_EQ(DEVICE_ID, args.deviceId); @@ -2190,6 +2201,7 @@ TEST_F(CursorInputMapperTest, Process_ShouldHandleIndependentButtonUpdates) { // Button press without following sync. 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(mFakeDispatcher->assertNotifyMotionWasCalled(&args)); ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action); ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0], @@ -2197,6 +2209,7 @@ TEST_F(CursorInputMapperTest, Process_ShouldHandleIndependentButtonUpdates) { // Button release without following sync. 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(mFakeDispatcher->assertNotifyMotionWasCalled(&args)); ASSERT_EQ(AMOTION_EVENT_ACTION_UP, args.action); ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0], @@ -2233,6 +2246,7 @@ TEST_F(CursorInputMapperTest, Process_ShouldHandleCombinedXYAndButtonUpdates) { // Release Button. 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(mFakeDispatcher->assertNotifyMotionWasCalled(&args)); ASSERT_EQ(AMOTION_EVENT_ACTION_UP, args.action); ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0], @@ -2248,10 +2262,12 @@ TEST_F(CursorInputMapperTest, Reset_WhenButtonIsNotDown_ShouldNotSynthesizeButto // 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(mFakeDispatcher->assertNotifyMotionWasCalled(&args)); // 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(mFakeDispatcher->assertNotifyMotionWasCalled(&args)); // Reset. Should not synthesize button up since button is not pressed. @@ -2269,6 +2285,7 @@ TEST_F(CursorInputMapperTest, Reset_WhenButtonIsDown_ShouldSynthesizeButtonUp) { // 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(mFakeDispatcher->assertNotifyMotionWasCalled(&args)); // Reset. Should synthesize button up. @@ -2445,6 +2462,7 @@ float TouchInputMapperTest::toDisplayY(int32_t rawY) { class SingleTouchInputMapperTest : public TouchInputMapperTest { protected: + void prepareButtons(); void prepareAxes(int axes); void processDown(SingleTouchInputMapper* mapper, int32_t x, int32_t y); @@ -2455,6 +2473,10 @@ protected: void processSync(SingleTouchInputMapper* mapper); }; +void SingleTouchInputMapperTest::prepareButtons() { + mFakeEventHub->addKey(DEVICE_ID, BTN_TOUCH, AKEYCODE_UNKNOWN, 0); +} + void SingleTouchInputMapperTest::prepareAxes(int axes) { if (axes & POSITION) { mFakeEventHub->addAbsoluteAxis(DEVICE_ID, ABS_X, @@ -2504,6 +2526,7 @@ void SingleTouchInputMapperTest::processSync(SingleTouchInputMapper* mapper) { TEST_F(SingleTouchInputMapperTest, GetSources_WhenDeviceTypeIsNotSpecifiedAndNotACursor_ReturnsPointer) { SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice); + prepareButtons(); prepareAxes(POSITION); addMapperAndConfigure(mapper); @@ -2514,6 +2537,7 @@ TEST_F(SingleTouchInputMapperTest, GetSources_WhenDeviceTypeIsNotSpecifiedAndIsA SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice); mFakeEventHub->addRelativeAxis(DEVICE_ID, REL_X); mFakeEventHub->addRelativeAxis(DEVICE_ID, REL_Y); + prepareButtons(); prepareAxes(POSITION); addMapperAndConfigure(mapper); @@ -2522,6 +2546,7 @@ TEST_F(SingleTouchInputMapperTest, GetSources_WhenDeviceTypeIsNotSpecifiedAndIsA TEST_F(SingleTouchInputMapperTest, GetSources_WhenDeviceTypeIsTouchPad_ReturnsTouchPad) { SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice); + prepareButtons(); prepareAxes(POSITION); addConfigurationProperty("touch.deviceType", "touchPad"); addMapperAndConfigure(mapper); @@ -2531,6 +2556,7 @@ TEST_F(SingleTouchInputMapperTest, GetSources_WhenDeviceTypeIsTouchPad_ReturnsTo TEST_F(SingleTouchInputMapperTest, GetSources_WhenDeviceTypeIsTouchScreen_ReturnsTouchScreen) { SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice); + prepareButtons(); prepareAxes(POSITION); addConfigurationProperty("touch.deviceType", "touchScreen"); addMapperAndConfigure(mapper); @@ -2542,6 +2568,7 @@ TEST_F(SingleTouchInputMapperTest, GetKeyCodeState) { SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice); addConfigurationProperty("touch.deviceType", "touchScreen"); prepareDisplay(DISPLAY_ORIENTATION_0); + prepareButtons(); prepareAxes(POSITION); prepareVirtualKeys(); addMapperAndConfigure(mapper); @@ -2570,6 +2597,7 @@ TEST_F(SingleTouchInputMapperTest, GetScanCodeState) { SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice); addConfigurationProperty("touch.deviceType", "touchScreen"); prepareDisplay(DISPLAY_ORIENTATION_0); + prepareButtons(); prepareAxes(POSITION); prepareVirtualKeys(); addMapperAndConfigure(mapper); @@ -2598,6 +2626,7 @@ TEST_F(SingleTouchInputMapperTest, MarkSupportedKeyCodes) { SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice); addConfigurationProperty("touch.deviceType", "touchScreen"); prepareDisplay(DISPLAY_ORIENTATION_0); + prepareButtons(); prepareAxes(POSITION); prepareVirtualKeys(); addMapperAndConfigure(mapper); @@ -2615,6 +2644,7 @@ TEST_F(SingleTouchInputMapperTest, Reset_WhenVirtualKeysAreDown_SendsUp) { SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice); addConfigurationProperty("touch.deviceType", "touchScreen"); prepareDisplay(DISPLAY_ORIENTATION_0); + prepareButtons(); prepareAxes(POSITION); prepareVirtualKeys(); addMapperAndConfigure(mapper); @@ -2649,6 +2679,7 @@ 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); @@ -2676,6 +2707,7 @@ TEST_F(SingleTouchInputMapperTest, Process_WhenVirtualKeyIsPressedAndReleasedNor SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice); addConfigurationProperty("touch.deviceType", "touchScreen"); prepareDisplay(DISPLAY_ORIENTATION_0); + prepareButtons(); prepareAxes(POSITION); prepareVirtualKeys(); addMapperAndConfigure(mapper); @@ -2726,6 +2758,7 @@ TEST_F(SingleTouchInputMapperTest, Process_WhenVirtualKeyIsPressedAndMovedOutOfB SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice); addConfigurationProperty("touch.deviceType", "touchScreen"); prepareDisplay(DISPLAY_ORIENTATION_0); + prepareButtons(); prepareAxes(POSITION); prepareVirtualKeys(); addMapperAndConfigure(mapper); @@ -2847,6 +2880,7 @@ TEST_F(SingleTouchInputMapperTest, Process_WhenTouchStartsOutsideDisplayAndMoves SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice); addConfigurationProperty("touch.deviceType", "touchScreen"); prepareDisplay(DISPLAY_ORIENTATION_0); + prepareButtons(); prepareAxes(POSITION); prepareVirtualKeys(); addMapperAndConfigure(mapper); @@ -2920,6 +2954,7 @@ TEST_F(SingleTouchInputMapperTest, Process_NormalSingleTouchGesture) { SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice); addConfigurationProperty("touch.deviceType", "touchScreen"); prepareDisplay(DISPLAY_ORIENTATION_0); + prepareButtons(); prepareAxes(POSITION); prepareVirtualKeys(); addMapperAndConfigure(mapper); @@ -3009,6 +3044,7 @@ TEST_F(SingleTouchInputMapperTest, Process_NormalSingleTouchGesture) { TEST_F(SingleTouchInputMapperTest, Process_WhenNotOrientationAware_DoesNotRotateMotions) { SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice); addConfigurationProperty("touch.deviceType", "touchScreen"); + prepareButtons(); prepareAxes(POSITION); addConfigurationProperty("touch.orientationAware", "0"); addMapperAndConfigure(mapper); @@ -3032,6 +3068,7 @@ TEST_F(SingleTouchInputMapperTest, Process_WhenNotOrientationAware_DoesNotRotate TEST_F(SingleTouchInputMapperTest, Process_WhenOrientationAware_RotatesMotions) { SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice); addConfigurationProperty("touch.deviceType", "touchScreen"); + prepareButtons(); prepareAxes(POSITION); addMapperAndConfigure(mapper); @@ -3094,6 +3131,7 @@ TEST_F(SingleTouchInputMapperTest, Process_AllAxes_DefaultCalibration) { SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice); addConfigurationProperty("touch.deviceType", "touchScreen"); prepareDisplay(DISPLAY_ORIENTATION_0); + prepareButtons(); prepareAxes(POSITION | PRESSURE | TOOL); addMapperAndConfigure(mapper); @@ -3815,6 +3853,7 @@ TEST_F(MultiTouchInputMapperTest, Process_TouchToolPressureSizeAxes_SummedLinear FakeInputDispatcher::NotifyMotionArgs args; ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args)); ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action); + ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args)); ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT), args.action); |