Loading libs/input/Input.cpp +0 −13 Original line number Diff line number Diff line Loading @@ -20,10 +20,8 @@ #include <attestation/HmacKeyManager.h> #include <cutils/compiler.h> #include <inttypes.h> #include <limits.h> #include <string.h> #include <android-base/properties.h> #include <android-base/stringprintf.h> #include <gui/constants.h> #include <input/Input.h> Loading @@ -43,15 +41,6 @@ namespace android { namespace { // When per-window-input-rotation is enabled, InputFlinger works in the un-rotated display // coordinates and SurfaceFlinger includes the display rotation in the input window transforms. bool isPerWindowInputRotationEnabled() { static const bool PER_WINDOW_INPUT_ROTATION = base::GetBoolProperty("persist.debug.per_window_input_rotation", false); return PER_WINDOW_INPUT_ROTATION; } float transformAngle(const ui::Transform& transform, float angleRadians) { // Construct and transform a vector oriented at the specified clockwise angle from vertical. // Coordinate system: down is increasing Y, right is increasing X. Loading Loading @@ -511,8 +500,6 @@ float MotionEvent::getHistoricalRawAxisValue(int32_t axis, size_t pointerIndex, size_t historicalIndex) const { const PointerCoords* coords = getHistoricalRawPointerCoords(pointerIndex, historicalIndex); if (!isPerWindowInputRotationEnabled()) return coords->getAxisValue(axis); if (axis == AMOTION_EVENT_AXIS_X || axis == AMOTION_EVENT_AXIS_Y) { // For compatibility, convert raw coordinates into logical display space. const vec2 xy = shouldDisregardTranslation(mSource) Loading libs/input/tests/InputEvent_test.cpp +0 −22 Original line number Diff line number Diff line Loading @@ -231,36 +231,14 @@ protected: static constexpr float RAW_X_OFFSET = 12; static constexpr float RAW_Y_OFFSET = -41.1; static const std::optional<bool> INITIAL_PER_WINDOW_INPUT_ROTATION_FLAG_VALUE; int32_t mId; ui::Transform mTransform; ui::Transform mRawTransform; void SetUp() override; void TearDown() override; void initializeEventWithHistory(MotionEvent* event); void assertEqualsEventWithHistory(const MotionEvent* event); }; const std::optional<bool> MotionEventTest::INITIAL_PER_WINDOW_INPUT_ROTATION_FLAG_VALUE = !base::GetProperty("persist.debug.per_window_input_rotation", "").empty() ? std::optional(base::GetBoolProperty("persist.debug.per_window_input_rotation", false)) : std::nullopt; void MotionEventTest::SetUp() { // Ensure per_window_input_rotation is enabled. base::SetProperty("persist.debug.per_window_input_rotation", "true"); } void MotionEventTest::TearDown() { const auto val = INITIAL_PER_WINDOW_INPUT_ROTATION_FLAG_VALUE.has_value() ? (*INITIAL_PER_WINDOW_INPUT_ROTATION_FLAG_VALUE ? "true" : "false") : ""; base::SetProperty("persist.debug.per_window_input_rotation", val); } void MotionEventTest::initializeEventWithHistory(MotionEvent* event) { mId = InputEvent::nextId(); mTransform.set({X_SCALE, 0, X_OFFSET, 0, Y_SCALE, Y_OFFSET, 0, 0, 1}); Loading services/inputflinger/dispatcher/InputDispatcher.cpp +51 −3 Original line number Diff line number Diff line Loading @@ -524,6 +524,16 @@ bool isConnectionResponsive(const Connection& connection) { return true; } bool isFromSource(uint32_t source, uint32_t test) { return (source & test) == test; } 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; } } // namespace // --- InputDispatcher --- Loading Loading @@ -3962,15 +3972,19 @@ void InputDispatcher::notifyMotion(const NotifyMotionArgs* args) { mLock.lock(); if (shouldSendMotionToInputFilterLocked(args)) { ui::Transform displayTransform; if (const auto it = mDisplayInfos.find(args->displayId); it != mDisplayInfos.end()) { displayTransform = it->second.transform; } mLock.unlock(); MotionEvent event; ui::Transform identityTransform; event.initialize(args->id, args->deviceId, args->source, args->displayId, INVALID_HMAC, args->action, args->actionButton, args->flags, args->edgeFlags, args->metaState, args->buttonState, args->classification, identityTransform, args->xPrecision, args->yPrecision, args->xCursorPosition, args->yCursorPosition, identityTransform, displayTransform, args->xPrecision, args->yPrecision, args->xCursorPosition, args->yCursorPosition, displayTransform, args->downTime, args->eventTime, args->pointerCount, args->pointerProperties, args->pointerCoords); Loading Loading @@ -4220,6 +4234,7 @@ InputEventInjectionResult InputDispatcher::injectInputEvent( pointerProperties, samplePointerCoords, motionEvent.getXOffset(), motionEvent.getYOffset()); transformMotionEntryForInjectionLocked(*injectedEntry); injectedEntries.push(std::move(injectedEntry)); for (size_t i = motionEvent.getHistorySize(); i > 0; i--) { sampleEventTimes += 1; Loading @@ -4241,6 +4256,7 @@ InputEventInjectionResult InputDispatcher::injectInputEvent( uint32_t(pointerCount), pointerProperties, samplePointerCoords, motionEvent.getXOffset(), motionEvent.getYOffset()); transformMotionEntryForInjectionLocked(*nextInjectedEntry); injectedEntries.push(std::move(nextInjectedEntry)); } break; Loading Loading @@ -4404,6 +4420,38 @@ void InputDispatcher::setInjectionResult(EventEntry& entry, } } 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(); for (uint32_t i = 0; i < entry.pointerCount; i++) { PointerCoords& pc = entry.pointerCoords[i]; 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); } } void InputDispatcher::incrementPendingForegroundDispatches(EventEntry& entry) { InjectionState* injectionState = entry.injectionState; if (injectionState) { Loading services/inputflinger/dispatcher/InputDispatcher.h +1 −0 Original line number Diff line number Diff line Loading @@ -280,6 +280,7 @@ private: bool hasInjectionPermission(int32_t injectorPid, int32_t injectorUid); void setInjectionResult(EventEntry& entry, android::os::InputEventInjectionResult injectionResult); void transformMotionEntryForInjectionLocked(MotionEntry&) const REQUIRES(mLock); std::condition_variable mInjectionSyncFinished; void incrementPendingForegroundDispatches(EventEntry& entry); Loading services/inputflinger/reader/mapper/TouchInputMapper.cpp +24 −9 Original line number Diff line number Diff line Loading @@ -749,16 +749,17 @@ void TouchInputMapper::configureSurface(nsecs_t when, bool* outResetNeeded) { mPhysicalLeft = naturalPhysicalLeft; mPhysicalTop = naturalPhysicalTop; if (isPerWindowInputRotationEnabled()) { // When per-window input rotation is enabled, InputReader works in the display // space, so the surface bounds are the bounds of the display device. const int32_t oldSurfaceWidth = mRawSurfaceWidth; const int32_t oldSurfaceHeight = mRawSurfaceHeight; mRawSurfaceWidth = naturalLogicalWidth * naturalDeviceWidth / naturalPhysicalWidth; mRawSurfaceHeight = naturalLogicalHeight * naturalDeviceHeight / naturalPhysicalHeight; mSurfaceLeft = naturalPhysicalLeft * naturalLogicalWidth / naturalPhysicalWidth; mSurfaceTop = naturalPhysicalTop * naturalLogicalHeight / naturalPhysicalHeight; mSurfaceRight = mSurfaceLeft + naturalLogicalWidth; mSurfaceBottom = mSurfaceTop + naturalLogicalHeight; if (isPerWindowInputRotationEnabled()) { mRawSurfaceWidth = naturalDeviceWidth; mRawSurfaceHeight = naturalDeviceHeight; mSurfaceLeft = 0; mSurfaceTop = 0; mSurfaceRight = mRawSurfaceWidth; mSurfaceBottom = mRawSurfaceHeight; // When per-window input rotation is enabled, InputReader works in the un-rotated // coordinate space, so we don't need to do anything if the device is already // orientation-aware. If the device is not orientation-aware, then we need to apply Loading @@ -774,6 +775,14 @@ void TouchInputMapper::configureSurface(nsecs_t when, bool* outResetNeeded) { mRawSurfaceWidth == oldSurfaceWidth && mRawSurfaceHeight == oldSurfaceHeight && viewportOrientationChanged; } else { mRawSurfaceWidth = naturalLogicalWidth * naturalDeviceWidth / naturalPhysicalWidth; mRawSurfaceHeight = naturalLogicalHeight * naturalDeviceHeight / naturalPhysicalHeight; mSurfaceLeft = naturalPhysicalLeft * naturalLogicalWidth / naturalPhysicalWidth; mSurfaceTop = naturalPhysicalTop * naturalLogicalHeight / naturalPhysicalHeight; mSurfaceRight = mSurfaceLeft + naturalLogicalWidth; mSurfaceBottom = mSurfaceTop + naturalLogicalHeight; mSurfaceOrientation = mParameters.orientationAware ? mViewport.orientation : DISPLAY_ORIENTATION_0; } Loading Loading @@ -3772,6 +3781,12 @@ bool TouchInputMapper::isPointInsideSurface(int32_t x, int32_t y) { const float xScaled = (x - mRawPointerAxes.x.minValue) * mXScale; const float yScaled = (y - mRawPointerAxes.y.minValue) * mYScale; if (isPerWindowInputRotationEnabled()) { return x >= mRawPointerAxes.x.minValue && x <= mRawPointerAxes.x.maxValue && xScaled >= mPhysicalLeft && xScaled <= (mPhysicalLeft + mPhysicalWidth) && y >= mRawPointerAxes.y.minValue && y <= mRawPointerAxes.y.maxValue && yScaled >= mPhysicalTop && yScaled <= (mPhysicalTop + mPhysicalHeight); } return x >= mRawPointerAxes.x.minValue && x <= mRawPointerAxes.x.maxValue && xScaled >= mSurfaceLeft && xScaled <= mSurfaceRight && y >= mRawPointerAxes.y.minValue && y <= mRawPointerAxes.y.maxValue && Loading Loading
libs/input/Input.cpp +0 −13 Original line number Diff line number Diff line Loading @@ -20,10 +20,8 @@ #include <attestation/HmacKeyManager.h> #include <cutils/compiler.h> #include <inttypes.h> #include <limits.h> #include <string.h> #include <android-base/properties.h> #include <android-base/stringprintf.h> #include <gui/constants.h> #include <input/Input.h> Loading @@ -43,15 +41,6 @@ namespace android { namespace { // When per-window-input-rotation is enabled, InputFlinger works in the un-rotated display // coordinates and SurfaceFlinger includes the display rotation in the input window transforms. bool isPerWindowInputRotationEnabled() { static const bool PER_WINDOW_INPUT_ROTATION = base::GetBoolProperty("persist.debug.per_window_input_rotation", false); return PER_WINDOW_INPUT_ROTATION; } float transformAngle(const ui::Transform& transform, float angleRadians) { // Construct and transform a vector oriented at the specified clockwise angle from vertical. // Coordinate system: down is increasing Y, right is increasing X. Loading Loading @@ -511,8 +500,6 @@ float MotionEvent::getHistoricalRawAxisValue(int32_t axis, size_t pointerIndex, size_t historicalIndex) const { const PointerCoords* coords = getHistoricalRawPointerCoords(pointerIndex, historicalIndex); if (!isPerWindowInputRotationEnabled()) return coords->getAxisValue(axis); if (axis == AMOTION_EVENT_AXIS_X || axis == AMOTION_EVENT_AXIS_Y) { // For compatibility, convert raw coordinates into logical display space. const vec2 xy = shouldDisregardTranslation(mSource) Loading
libs/input/tests/InputEvent_test.cpp +0 −22 Original line number Diff line number Diff line Loading @@ -231,36 +231,14 @@ protected: static constexpr float RAW_X_OFFSET = 12; static constexpr float RAW_Y_OFFSET = -41.1; static const std::optional<bool> INITIAL_PER_WINDOW_INPUT_ROTATION_FLAG_VALUE; int32_t mId; ui::Transform mTransform; ui::Transform mRawTransform; void SetUp() override; void TearDown() override; void initializeEventWithHistory(MotionEvent* event); void assertEqualsEventWithHistory(const MotionEvent* event); }; const std::optional<bool> MotionEventTest::INITIAL_PER_WINDOW_INPUT_ROTATION_FLAG_VALUE = !base::GetProperty("persist.debug.per_window_input_rotation", "").empty() ? std::optional(base::GetBoolProperty("persist.debug.per_window_input_rotation", false)) : std::nullopt; void MotionEventTest::SetUp() { // Ensure per_window_input_rotation is enabled. base::SetProperty("persist.debug.per_window_input_rotation", "true"); } void MotionEventTest::TearDown() { const auto val = INITIAL_PER_WINDOW_INPUT_ROTATION_FLAG_VALUE.has_value() ? (*INITIAL_PER_WINDOW_INPUT_ROTATION_FLAG_VALUE ? "true" : "false") : ""; base::SetProperty("persist.debug.per_window_input_rotation", val); } void MotionEventTest::initializeEventWithHistory(MotionEvent* event) { mId = InputEvent::nextId(); mTransform.set({X_SCALE, 0, X_OFFSET, 0, Y_SCALE, Y_OFFSET, 0, 0, 1}); Loading
services/inputflinger/dispatcher/InputDispatcher.cpp +51 −3 Original line number Diff line number Diff line Loading @@ -524,6 +524,16 @@ bool isConnectionResponsive(const Connection& connection) { return true; } bool isFromSource(uint32_t source, uint32_t test) { return (source & test) == test; } 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; } } // namespace // --- InputDispatcher --- Loading Loading @@ -3962,15 +3972,19 @@ void InputDispatcher::notifyMotion(const NotifyMotionArgs* args) { mLock.lock(); if (shouldSendMotionToInputFilterLocked(args)) { ui::Transform displayTransform; if (const auto it = mDisplayInfos.find(args->displayId); it != mDisplayInfos.end()) { displayTransform = it->second.transform; } mLock.unlock(); MotionEvent event; ui::Transform identityTransform; event.initialize(args->id, args->deviceId, args->source, args->displayId, INVALID_HMAC, args->action, args->actionButton, args->flags, args->edgeFlags, args->metaState, args->buttonState, args->classification, identityTransform, args->xPrecision, args->yPrecision, args->xCursorPosition, args->yCursorPosition, identityTransform, displayTransform, args->xPrecision, args->yPrecision, args->xCursorPosition, args->yCursorPosition, displayTransform, args->downTime, args->eventTime, args->pointerCount, args->pointerProperties, args->pointerCoords); Loading Loading @@ -4220,6 +4234,7 @@ InputEventInjectionResult InputDispatcher::injectInputEvent( pointerProperties, samplePointerCoords, motionEvent.getXOffset(), motionEvent.getYOffset()); transformMotionEntryForInjectionLocked(*injectedEntry); injectedEntries.push(std::move(injectedEntry)); for (size_t i = motionEvent.getHistorySize(); i > 0; i--) { sampleEventTimes += 1; Loading @@ -4241,6 +4256,7 @@ InputEventInjectionResult InputDispatcher::injectInputEvent( uint32_t(pointerCount), pointerProperties, samplePointerCoords, motionEvent.getXOffset(), motionEvent.getYOffset()); transformMotionEntryForInjectionLocked(*nextInjectedEntry); injectedEntries.push(std::move(nextInjectedEntry)); } break; Loading Loading @@ -4404,6 +4420,38 @@ void InputDispatcher::setInjectionResult(EventEntry& entry, } } 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(); for (uint32_t i = 0; i < entry.pointerCount; i++) { PointerCoords& pc = entry.pointerCoords[i]; 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); } } void InputDispatcher::incrementPendingForegroundDispatches(EventEntry& entry) { InjectionState* injectionState = entry.injectionState; if (injectionState) { Loading
services/inputflinger/dispatcher/InputDispatcher.h +1 −0 Original line number Diff line number Diff line Loading @@ -280,6 +280,7 @@ private: bool hasInjectionPermission(int32_t injectorPid, int32_t injectorUid); void setInjectionResult(EventEntry& entry, android::os::InputEventInjectionResult injectionResult); void transformMotionEntryForInjectionLocked(MotionEntry&) const REQUIRES(mLock); std::condition_variable mInjectionSyncFinished; void incrementPendingForegroundDispatches(EventEntry& entry); Loading
services/inputflinger/reader/mapper/TouchInputMapper.cpp +24 −9 Original line number Diff line number Diff line Loading @@ -749,16 +749,17 @@ void TouchInputMapper::configureSurface(nsecs_t when, bool* outResetNeeded) { mPhysicalLeft = naturalPhysicalLeft; mPhysicalTop = naturalPhysicalTop; if (isPerWindowInputRotationEnabled()) { // When per-window input rotation is enabled, InputReader works in the display // space, so the surface bounds are the bounds of the display device. const int32_t oldSurfaceWidth = mRawSurfaceWidth; const int32_t oldSurfaceHeight = mRawSurfaceHeight; mRawSurfaceWidth = naturalLogicalWidth * naturalDeviceWidth / naturalPhysicalWidth; mRawSurfaceHeight = naturalLogicalHeight * naturalDeviceHeight / naturalPhysicalHeight; mSurfaceLeft = naturalPhysicalLeft * naturalLogicalWidth / naturalPhysicalWidth; mSurfaceTop = naturalPhysicalTop * naturalLogicalHeight / naturalPhysicalHeight; mSurfaceRight = mSurfaceLeft + naturalLogicalWidth; mSurfaceBottom = mSurfaceTop + naturalLogicalHeight; if (isPerWindowInputRotationEnabled()) { mRawSurfaceWidth = naturalDeviceWidth; mRawSurfaceHeight = naturalDeviceHeight; mSurfaceLeft = 0; mSurfaceTop = 0; mSurfaceRight = mRawSurfaceWidth; mSurfaceBottom = mRawSurfaceHeight; // When per-window input rotation is enabled, InputReader works in the un-rotated // coordinate space, so we don't need to do anything if the device is already // orientation-aware. If the device is not orientation-aware, then we need to apply Loading @@ -774,6 +775,14 @@ void TouchInputMapper::configureSurface(nsecs_t when, bool* outResetNeeded) { mRawSurfaceWidth == oldSurfaceWidth && mRawSurfaceHeight == oldSurfaceHeight && viewportOrientationChanged; } else { mRawSurfaceWidth = naturalLogicalWidth * naturalDeviceWidth / naturalPhysicalWidth; mRawSurfaceHeight = naturalLogicalHeight * naturalDeviceHeight / naturalPhysicalHeight; mSurfaceLeft = naturalPhysicalLeft * naturalLogicalWidth / naturalPhysicalWidth; mSurfaceTop = naturalPhysicalTop * naturalLogicalHeight / naturalPhysicalHeight; mSurfaceRight = mSurfaceLeft + naturalLogicalWidth; mSurfaceBottom = mSurfaceTop + naturalLogicalHeight; mSurfaceOrientation = mParameters.orientationAware ? mViewport.orientation : DISPLAY_ORIENTATION_0; } Loading Loading @@ -3772,6 +3781,12 @@ bool TouchInputMapper::isPointInsideSurface(int32_t x, int32_t y) { const float xScaled = (x - mRawPointerAxes.x.minValue) * mXScale; const float yScaled = (y - mRawPointerAxes.y.minValue) * mYScale; if (isPerWindowInputRotationEnabled()) { return x >= mRawPointerAxes.x.minValue && x <= mRawPointerAxes.x.maxValue && xScaled >= mPhysicalLeft && xScaled <= (mPhysicalLeft + mPhysicalWidth) && y >= mRawPointerAxes.y.minValue && y <= mRawPointerAxes.y.maxValue && yScaled >= mPhysicalTop && yScaled <= (mPhysicalTop + mPhysicalHeight); } return x >= mRawPointerAxes.x.minValue && x <= mRawPointerAxes.x.maxValue && xScaled >= mSurfaceLeft && xScaled <= mSurfaceRight && y >= mRawPointerAxes.y.minValue && y <= mRawPointerAxes.y.maxValue && Loading