diff options
| -rw-r--r-- | services/inputflinger/dispatcher/InputDispatcher.cpp | 55 | ||||
| -rw-r--r-- | services/inputflinger/dispatcher/InputDispatcher.h | 4 | ||||
| -rw-r--r-- | services/inputflinger/tests/InputDispatcher_test.cpp | 27 |
3 files changed, 36 insertions, 50 deletions
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp index 3fd1c8aa27..7f68d1b8b1 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.cpp +++ b/services/inputflinger/dispatcher/InputDispatcher.cpp @@ -506,6 +506,12 @@ bool isConnectionResponsive(const Connection& connection) { return true; } +vec2 transformWithoutTranslation(const ui::Transform& transform, float x, float y) { + const vec2 transformedXy = transform.transform(x, y); + const vec2 transformedOrigin = transform.transform(0, 0); + return transformedXy - transformedOrigin; +} + // Returns true if the event type passed as argument represents a user activity. bool isUserActivityEvent(const EventEntry& eventEntry) { switch (eventEntry.type) { @@ -4208,8 +4214,10 @@ InputEventInjectionResult InputDispatcher::injectInputEvent( motionEvent.getRawXCursorPosition(), motionEvent.getRawYCursorPosition(), motionEvent.getDownTime(), uint32_t(pointerCount), - pointerProperties, samplePointerCoords, 0, 0); - transformMotionEntryForInjectionLocked(*injectedEntry, motionEvent.getTransform()); + pointerProperties, samplePointerCoords, + motionEvent.getXOffset(), + motionEvent.getYOffset()); + transformMotionEntryForInjectionLocked(*injectedEntry); injectedEntries.push(std::move(injectedEntry)); for (size_t i = motionEvent.getHistorySize(); i > 0; i--) { sampleEventTimes += 1; @@ -4228,9 +4236,9 @@ InputEventInjectionResult InputDispatcher::injectInputEvent( motionEvent.getRawYCursorPosition(), motionEvent.getDownTime(), uint32_t(pointerCount), pointerProperties, - samplePointerCoords, 0, 0); - transformMotionEntryForInjectionLocked(*nextInjectedEntry, - motionEvent.getTransform()); + samplePointerCoords, motionEvent.getXOffset(), + motionEvent.getYOffset()); + transformMotionEntryForInjectionLocked(*nextInjectedEntry); injectedEntries.push(std::move(nextInjectedEntry)); } break; @@ -4394,28 +4402,35 @@ void InputDispatcher::setInjectionResult(EventEntry& entry, } } -void InputDispatcher::transformMotionEntryForInjectionLocked( - MotionEntry& entry, const ui::Transform& injectedTransform) const { +void InputDispatcher::transformMotionEntryForInjectionLocked(MotionEntry& entry) const { + const bool isRelativeMouseEvent = isFromSource(entry.source, AINPUT_SOURCE_MOUSE_RELATIVE); + if (!isRelativeMouseEvent && !isFromSource(entry.source, AINPUT_SOURCE_CLASS_POINTER)) { + return; + } + // Input injection works in the logical display coordinate space, but the input pipeline works // display space, so we need to transform the injected events accordingly. const auto it = mDisplayInfos.find(entry.displayId); if (it == mDisplayInfos.end()) return; - const auto& transformToDisplay = it->second.transform.inverse() * injectedTransform; + const auto& transformToDisplay = it->second.transform.inverse(); for (uint32_t i = 0; i < entry.pointerCount; i++) { PointerCoords& pc = entry.pointerCoords[i]; - // Make a copy of the injected coords. We cannot change them in place because some of them - // are interdependent (for example, X coordinate might depend on the Y coordinate). - PointerCoords injectedCoords = entry.pointerCoords[i]; - - BitSet64 bits(injectedCoords.bits); - while (!bits.isEmpty()) { - const auto axis = static_cast<int32_t>(bits.clearFirstMarkedBit()); - const float value = - MotionEvent::calculateTransformedAxisValue(axis, entry.source, - transformToDisplay, injectedCoords); - pc.setAxisValue(axis, value); - } + const auto xy = isRelativeMouseEvent + ? transformWithoutTranslation(transformToDisplay, pc.getX(), pc.getY()) + : transformToDisplay.transform(pc.getXYValue()); + pc.setAxisValue(AMOTION_EVENT_AXIS_X, xy.x); + pc.setAxisValue(AMOTION_EVENT_AXIS_Y, xy.y); + + // Axes with relative values never represent points on a screen, so they should never have + // translation applied. If a device does not report relative values, these values are always + // 0, and will remain unaffected by the following operation. + const auto rel = + transformWithoutTranslation(transformToDisplay, + pc.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X), + pc.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y)); + pc.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, rel.x); + pc.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, rel.y); } } diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h index 6f05670943..8a551cfca1 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.h +++ b/services/inputflinger/dispatcher/InputDispatcher.h @@ -280,9 +280,7 @@ private: bool hasInjectionPermission(int32_t injectorPid, int32_t injectorUid); void setInjectionResult(EventEntry& entry, android::os::InputEventInjectionResult injectionResult); - void transformMotionEntryForInjectionLocked(MotionEntry&, - const ui::Transform& injectedTransform) const - REQUIRES(mLock); + void transformMotionEntryForInjectionLocked(MotionEntry&) const REQUIRES(mLock); std::condition_variable mInjectionSyncFinished; void incrementPendingForegroundDispatches(EventEntry& entry); diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp index eaea4e26c4..515a01e137 100644 --- a/services/inputflinger/tests/InputDispatcher_test.cpp +++ b/services/inputflinger/tests/InputDispatcher_test.cpp @@ -2079,33 +2079,6 @@ TEST_F(InputDispatcherDisplayProjectionTest, InjectionInLogicalDisplaySpace) { secondWindow->assertNoEvents(); } -// Ensure that when a MotionEvent that has a custom transform is injected, the post-transformed -// event should be treated as being in the logical display space. -TEST_F(InputDispatcherDisplayProjectionTest, InjectionWithTransformInLogicalDisplaySpace) { - auto [firstWindow, secondWindow] = setupScaledDisplayScenario(); - - const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0}; - ui::Transform injectedEventTransform; - injectedEventTransform.set(matrix); - const vec2 expectedPoint{75, 55}; // The injected point in the logical display space. - const vec2 untransformedPoint = injectedEventTransform.inverse().transform(expectedPoint); - - MotionEvent event = MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN) - .displayId(ADISPLAY_ID_DEFAULT) - .eventTime(systemTime(SYSTEM_TIME_MONOTONIC)) - .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER) - .x(untransformedPoint.x) - .y(untransformedPoint.y)) - .build(); - event.transform(matrix); - - injectMotionEvent(mDispatcher, event, INJECT_EVENT_TIMEOUT, - InputEventInjectionSync::WAIT_FOR_RESULT); - - firstWindow->consumeMotionDown(); - secondWindow->assertNoEvents(); -} - TEST_F(InputDispatcherDisplayProjectionTest, WindowGetsEventsInCorrectCoordinateSpace) { auto [firstWindow, secondWindow] = setupScaledDisplayScenario(); |