Loading libs/input/Input.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -47,7 +47,7 @@ namespace { // 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); base::GetBoolProperty("persist.debug.per_window_input_rotation", true); return PER_WINDOW_INPUT_ROTATION; } Loading services/inputflinger/reader/mapper/TouchCursorInputMapperCommon.h +1 −3 Original line number Diff line number Diff line Loading @@ -33,9 +33,7 @@ namespace android { // projection are part of the input window's transform. This means InputReader should work in the // un-rotated coordinate space. static bool isPerWindowInputRotationEnabled() { static const bool PER_WINDOW_INPUT_ROTATION = sysprop::InputFlingerProperties::per_window_input_rotation().value_or(false); return PER_WINDOW_INPUT_ROTATION; return sysprop::InputFlingerProperties::per_window_input_rotation().value_or(true); } static int32_t getInverseRotation(int32_t orientation) { Loading services/inputflinger/tests/InputReader_test.cpp +152 −50 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ #include <CursorInputMapper.h> #include <InputDevice.h> #include <InputFlingerProperties.sysprop.h> #include <InputMapper.h> #include <InputReader.h> #include <InputReaderBase.h> Loading Loading @@ -95,6 +96,17 @@ const std::unordered_map<std::string, LightColor> LIGHT_COLORS = {{"red", LightC {"green", LightColor::GREEN}, {"blue", LightColor::BLUE}}; static int32_t getInverseRotation(int32_t orientation) { switch (orientation) { case DISPLAY_ORIENTATION_90: return DISPLAY_ORIENTATION_270; case DISPLAY_ORIENTATION_270: return DISPLAY_ORIENTATION_90; default: return orientation; } } // --- FakePointerController --- class FakePointerController : public PointerControllerInterface { Loading Loading @@ -2660,6 +2672,7 @@ protected: static const int32_t DEVICE_CONTROLLER_NUMBER; static const Flags<InputDeviceClass> DEVICE_CLASSES; static const int32_t EVENTHUB_ID; static const std::optional<bool> INITIAL_PER_WINDOW_INPUT_ROTATION_FLAG_VALUE; std::shared_ptr<FakeEventHub> mFakeEventHub; sp<FakeInputReaderPolicy> mFakePolicy; Loading @@ -2676,11 +2689,19 @@ protected: mDevice = newDevice(DEVICE_ID, DEVICE_NAME, DEVICE_LOCATION, EVENTHUB_ID, classes); } void SetUp() override { SetUp(DEVICE_CLASSES); } void SetUp() override { // Ensure per_window_input_rotation is enabled. sysprop::InputFlingerProperties::per_window_input_rotation(true); SetUp(DEVICE_CLASSES); } void TearDown() override { mFakeListener.clear(); mFakePolicy.clear(); sysprop::InputFlingerProperties::per_window_input_rotation( INITIAL_PER_WINDOW_INPUT_ROTATION_FLAG_VALUE); } void addConfigurationProperty(const char* key, const char* value) { Loading Loading @@ -2792,6 +2813,8 @@ const int32_t InputMapperTest::DEVICE_CONTROLLER_NUMBER = 0; const Flags<InputDeviceClass> InputMapperTest::DEVICE_CLASSES = Flags<InputDeviceClass>(0); // not needed for current tests const int32_t InputMapperTest::EVENTHUB_ID = 1; const std::optional<bool> InputMapperTest::INITIAL_PER_WINDOW_INPUT_ROTATION_FLAG_VALUE = sysprop::InputFlingerProperties::per_window_input_rotation(); // --- SwitchInputMapperTest --- Loading Loading @@ -4088,8 +4111,11 @@ TEST_F(CursorInputMapperTest, Process_ShouldHandleCombinedXYAndButtonUpdates) { ASSERT_NO_FATAL_FAILURE(assertCursorPointerCoords(args.pointerCoords[0], 0.0f, 0.0f, 0.0f)); } TEST_F(CursorInputMapperTest, Process_WhenNotOrientationAware_ShouldNotRotateMotions) { TEST_F(CursorInputMapperTest, Process_WhenOrientationAware_ShouldNotRotateMotions) { addConfigurationProperty("cursor.mode", "navigation"); // InputReader works in the un-rotated coordinate space, so orientation-aware devices do not // need to be rotated. addConfigurationProperty("cursor.orientationAware", "1"); CursorInputMapper& mapper = addMapperAndConfigure<CursorInputMapper>(); prepareDisplay(DISPLAY_ORIENTATION_90); Loading @@ -4103,9 +4129,10 @@ TEST_F(CursorInputMapperTest, Process_WhenNotOrientationAware_ShouldNotRotateMot ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, 1, -1, 1)); } TEST_F(CursorInputMapperTest, Process_WhenOrientationAware_ShouldRotateMotions) { TEST_F(CursorInputMapperTest, Process_WhenNotOrientationAware_ShouldRotateMotions) { addConfigurationProperty("cursor.mode", "navigation"); addConfigurationProperty("cursor.orientationAware", "1"); // Since InputReader works in the un-rotated coordinate space, only devices that are not // orientation-aware are affected by display rotation. CursorInputMapper& mapper = addMapperAndConfigure<CursorInputMapper>(); prepareDisplay(DISPLAY_ORIENTATION_0); Loading @@ -4119,14 +4146,14 @@ TEST_F(CursorInputMapperTest, Process_WhenOrientationAware_ShouldRotateMotions) ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, 1, -1, 1)); prepareDisplay(DISPLAY_ORIENTATION_90); ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 0, 1, 1, 0)); ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, 1, 1, -1)); ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, 0, 0, -1)); ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, -1, -1, -1)); ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 0, -1, -1, 0)); ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, -1, -1, 1)); ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, 0, 0, 1)); ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, 1, 1, 1)); ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 0, 1, -1, 0)); ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, 1, -1, 1)); ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, 0, 0, 1)); ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, -1, 1, 1)); ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 0, -1, 1, 0)); ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, -1, 1, -1)); ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, 0, 0, -1)); ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, 1, -1, -1)); prepareDisplay(DISPLAY_ORIENTATION_180); ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 0, 1, 0, -1)); Loading @@ -4139,14 +4166,14 @@ TEST_F(CursorInputMapperTest, Process_WhenOrientationAware_ShouldRotateMotions) ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, 1, 1, -1)); prepareDisplay(DISPLAY_ORIENTATION_270); ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 0, 1, -1, 0)); ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, 1, -1, 1)); ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, 0, 0, 1)); ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, -1, 1, 1)); ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 0, -1, 1, 0)); ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, -1, 1, -1)); ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, 0, 0, -1)); ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, 1, -1, -1)); ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 0, 1, 1, 0)); ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, 1, 1, -1)); ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, 0, 0, -1)); ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, -1, -1, -1)); ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 0, -1, -1, 0)); ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, -1, -1, 1)); ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, 0, 0, 1)); ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, 1, 1, 1)); } TEST_F(CursorInputMapperTest, Process_ShouldHandleAllButtons) { Loading Loading @@ -5368,11 +5395,12 @@ TEST_F(SingleTouchInputMapperTest, Process_NormalSingleTouchGesture) { ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled()); } TEST_F(SingleTouchInputMapperTest, Process_WhenNotOrientationAware_DoesNotRotateMotions) { TEST_F(SingleTouchInputMapperTest, Process_WhenOrientationAware_DoesNotRotateMotions) { addConfigurationProperty("touch.deviceType", "touchScreen"); prepareButtons(); prepareAxes(POSITION); addConfigurationProperty("touch.orientationAware", "0"); // InputReader works in the un-rotated coordinate space, so orientation-aware devices do not // need to be rotated. Touchscreens are orientation-aware by default. SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>(); NotifyMotionArgs args; Loading @@ -5391,10 +5419,13 @@ TEST_F(SingleTouchInputMapperTest, Process_WhenNotOrientationAware_DoesNotRotate ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled()); } TEST_F(SingleTouchInputMapperTest, Process_WhenOrientationAware_RotatesMotions) { TEST_F(SingleTouchInputMapperTest, Process_WhenNotOrientationAware_RotatesMotions) { addConfigurationProperty("touch.deviceType", "touchScreen"); prepareButtons(); prepareAxes(POSITION); // Since InputReader works in the un-rotated coordinate space, only devices that are not // orientation-aware are affected by display rotation. addConfigurationProperty("touch.orientationAware", "0"); SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>(); NotifyMotionArgs args; Loading @@ -5416,7 +5447,7 @@ TEST_F(SingleTouchInputMapperTest, Process_WhenOrientationAware_RotatesMotions) // Rotation 90. clearViewports(); prepareDisplay(DISPLAY_ORIENTATION_90); processDown(mapper, RAW_X_MAX - toRawX(75) + RAW_X_MIN, toRawY(50)); processDown(mapper, toRawX(75), RAW_Y_MAX - toRawY(50) + RAW_Y_MIN); processSync(mapper); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args)); Loading Loading @@ -5444,7 +5475,7 @@ TEST_F(SingleTouchInputMapperTest, Process_WhenOrientationAware_RotatesMotions) // Rotation 270. clearViewports(); prepareDisplay(DISPLAY_ORIENTATION_270); processDown(mapper, toRawX(75), RAW_Y_MAX - toRawY(50) + RAW_Y_MIN); processDown(mapper, RAW_X_MAX - toRawX(75) + RAW_X_MIN, toRawY(50)); processSync(mapper); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args)); Loading Loading @@ -7806,9 +7837,35 @@ TEST_F(MultiTouchInputMapperTest, VideoFrames_ReceivedByListener) { ASSERT_EQ(std::vector<TouchVideoFrame>(), motionArgs.videoFrames); } TEST_F(MultiTouchInputMapperTest, VideoFrames_AreRotated) { TEST_F(MultiTouchInputMapperTest, VideoFrames_AreNotRotated) { prepareAxes(POSITION); addConfigurationProperty("touch.deviceType", "touchScreen"); MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>(); // Unrotated video frame TouchVideoFrame frame(3, 2, {1, 2, 3, 4, 5, 6}, {1, 2}); NotifyMotionArgs motionArgs; // Test all 4 orientations for (int32_t orientation : {DISPLAY_ORIENTATION_0, DISPLAY_ORIENTATION_90, DISPLAY_ORIENTATION_180, DISPLAY_ORIENTATION_270}) { SCOPED_TRACE("Orientation " + StringPrintf("%i", orientation)); clearViewports(); prepareDisplay(orientation); std::vector<TouchVideoFrame> frames{frame}; mFakeEventHub->setVideoFrames({{EVENTHUB_ID, frames}}); processPosition(mapper, 100, 200); processSync(mapper); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); ASSERT_EQ(frames, motionArgs.videoFrames); } } TEST_F(MultiTouchInputMapperTest, VideoFrames_WhenNotOrientationAware_AreRotated) { prepareAxes(POSITION); addConfigurationProperty("touch.deviceType", "touchScreen"); // Since InputReader works in the un-rotated coordinate space, only devices that are not // orientation-aware are affected by display rotation. addConfigurationProperty("touch.orientationAware", "0"); MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>(); // Unrotated video frame TouchVideoFrame frame(3, 2, {1, 2, 3, 4, 5, 6}, {1, 2}); Loading @@ -7825,14 +7882,41 @@ TEST_F(MultiTouchInputMapperTest, VideoFrames_AreRotated) { processPosition(mapper, 100, 200); processSync(mapper); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); frames[0].rotate(orientation); // We expect the raw coordinates of the MotionEvent to be rotated in the inverse direction // compared to the display. This is so that when the window transform (which contains the // display rotation) is applied later by InputDispatcher, the coordinates end up in the // window's coordinate space. frames[0].rotate(getInverseRotation(orientation)); ASSERT_EQ(frames, motionArgs.videoFrames); } } TEST_F(MultiTouchInputMapperTest, VideoFrames_MultipleFramesAreRotated) { TEST_F(MultiTouchInputMapperTest, VideoFrames_MultipleFramesAreNotRotated) { prepareAxes(POSITION); addConfigurationProperty("touch.deviceType", "touchScreen"); MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>(); // Unrotated video frames. There's no rule that they must all have the same dimensions, // so mix these. TouchVideoFrame frame1(3, 2, {1, 2, 3, 4, 5, 6}, {1, 2}); TouchVideoFrame frame2(3, 3, {0, 1, 2, 3, 4, 5, 6, 7, 8}, {1, 3}); TouchVideoFrame frame3(2, 2, {10, 20, 10, 0}, {1, 4}); std::vector<TouchVideoFrame> frames{frame1, frame2, frame3}; NotifyMotionArgs motionArgs; prepareDisplay(DISPLAY_ORIENTATION_90); mFakeEventHub->setVideoFrames({{EVENTHUB_ID, frames}}); processPosition(mapper, 100, 200); processSync(mapper); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); ASSERT_EQ(frames, motionArgs.videoFrames); } TEST_F(MultiTouchInputMapperTest, VideoFrames_WhenNotOrientationAware_MultipleFramesAreRotated) { prepareAxes(POSITION); addConfigurationProperty("touch.deviceType", "touchScreen"); // Since InputReader works in the un-rotated coordinate space, only devices that are not // orientation-aware are affected by display rotation. addConfigurationProperty("touch.orientationAware", "0"); MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>(); // Unrotated video frames. There's no rule that they must all have the same dimensions, // so mix these. Loading @@ -7847,8 +7931,13 @@ TEST_F(MultiTouchInputMapperTest, VideoFrames_MultipleFramesAreRotated) { processPosition(mapper, 100, 200); processSync(mapper); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); std::for_each(frames.begin(), frames.end(), [](TouchVideoFrame& frame) { frame.rotate(DISPLAY_ORIENTATION_90); }); std::for_each(frames.begin(), frames.end(), [](TouchVideoFrame& frame) { // We expect the raw coordinates of the MotionEvent to be rotated in the inverse direction // compared to the display. This is so that when the window transform (which contains the // display rotation) is applied later by InputDispatcher, the coordinates end up in the // window's coordinate space. frame.rotate(getInverseRotation(DISPLAY_ORIENTATION_90)); }); ASSERT_EQ(frames, motionArgs.videoFrames); } Loading Loading @@ -8402,18 +8491,25 @@ TEST_F(MultiTouchInputMapperTest_SurfaceRange, Viewports_SurfaceRange) { // Reset. mapper.reset(ARBITRARY_TIME); // Let physical display be different to device, and make surface and physical could be 1:1. halfDisplayToCenterHorizontal(DISPLAY_ORIENTATION_0); // Let physical display be different to device, and make surface and physical could be 1:1 in // all four orientations. for (int orientation : {DISPLAY_ORIENTATION_0, DISPLAY_ORIENTATION_90, DISPLAY_ORIENTATION_180, DISPLAY_ORIENTATION_270}) { halfDisplayToCenterHorizontal(orientation); const int32_t xExpected = (x + 1) - (DISPLAY_WIDTH / 4); const int32_t yExpected = y; processPositionAndVerify(mapper, x - 1, y, x + 1, y, xExpected, yExpected); } } TEST_F(MultiTouchInputMapperTest_SurfaceRange, Viewports_SurfaceRange_90) { TEST_F(MultiTouchInputMapperTest_SurfaceRange, Viewports_SurfaceRange_90_NotOrientationAware) { addConfigurationProperty("touch.deviceType", "touchScreen"); prepareDisplay(DISPLAY_ORIENTATION_0); prepareAxes(POSITION); // Since InputReader works in the un-rotated coordinate space, only devices that are not // orientation-aware are affected by display rotation. addConfigurationProperty("touch.orientationAware", "0"); MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>(); // Half display to (width/4, 0, width * 3/4, height) and rotate 90-degrees. Loading @@ -8422,16 +8518,19 @@ TEST_F(MultiTouchInputMapperTest_SurfaceRange, Viewports_SurfaceRange_90) { const int32_t x = DISPLAY_WIDTH / 4; const int32_t y = DISPLAY_HEIGHT / 2; // expect x/y = swap x/y then reverse y. const int32_t xExpected = y; const int32_t yExpected = (DISPLAY_WIDTH * 3 / 4) - (x + 1); // expect x/y = swap x/y then reverse x. constexpr int32_t xExpected = DISPLAY_HEIGHT - y; constexpr int32_t yExpected = (x + 1) - DISPLAY_WIDTH / 4; processPositionAndVerify(mapper, x - 1, y, x + 1, y, xExpected, yExpected); } TEST_F(MultiTouchInputMapperTest_SurfaceRange, Viewports_SurfaceRange_270) { TEST_F(MultiTouchInputMapperTest_SurfaceRange, Viewports_SurfaceRange_270_NotOrientationAware) { addConfigurationProperty("touch.deviceType", "touchScreen"); prepareDisplay(DISPLAY_ORIENTATION_0); prepareAxes(POSITION); // Since InputReader works in the un-rotated coordinate space, only devices that are not // orientation-aware are affected by display rotation. addConfigurationProperty("touch.orientationAware", "0"); MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>(); // Half display to (width/4, 0, width * 3/4, height) and rotate 270-degrees. Loading @@ -8440,16 +8539,19 @@ TEST_F(MultiTouchInputMapperTest_SurfaceRange, Viewports_SurfaceRange_270) { const int32_t x = DISPLAY_WIDTH / 4; const int32_t y = DISPLAY_HEIGHT / 2; // expect x/y = swap x/y then reverse x. constexpr int32_t xExpected = DISPLAY_HEIGHT - y; constexpr int32_t yExpected = (x + 1) - DISPLAY_WIDTH / 4; // expect x/y = swap x/y then reverse y. const int32_t xExpected = y; const int32_t yExpected = (DISPLAY_WIDTH * 3 / 4) - (x + 1); processPositionAndVerify(mapper, x - 1, y, x + 1, y, xExpected, yExpected); } TEST_F(MultiTouchInputMapperTest_SurfaceRange, Viewports_SurfaceRange_Corner) { TEST_F(MultiTouchInputMapperTest_SurfaceRange, Viewports_SurfaceRange_Corner_NotOrientationAware) { addConfigurationProperty("touch.deviceType", "touchScreen"); prepareDisplay(DISPLAY_ORIENTATION_0); prepareAxes(POSITION); // Since InputReader works in the un-rotated coordinate space, only devices that are not // orientation-aware are affected by display rotation. addConfigurationProperty("touch.orientationAware", "0"); MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>(); const int32_t x = 0; Loading @@ -8461,16 +8563,16 @@ TEST_F(MultiTouchInputMapperTest_SurfaceRange, Viewports_SurfaceRange_Corner) { clearViewports(); prepareDisplay(DISPLAY_ORIENTATION_90); // expect x/y = swap x/y then reverse y. const int32_t xExpected90 = y; const int32_t yExpected90 = DISPLAY_WIDTH - 1; // expect x/y = swap x/y then reverse x. const int32_t xExpected90 = DISPLAY_HEIGHT - 1; const int32_t yExpected90 = x; processPositionAndVerify(mapper, x - 1, y, x, y, xExpected90, yExpected90); clearViewports(); prepareDisplay(DISPLAY_ORIENTATION_270); // expect x/y = swap x/y then reverse x. const int32_t xExpected270 = DISPLAY_HEIGHT - 1; const int32_t yExpected270 = x; // expect x/y = swap x/y then reverse y. const int32_t xExpected270 = y; const int32_t yExpected270 = DISPLAY_WIDTH - 1; processPositionAndVerify(mapper, x - 1, y, x, y, xExpected270, yExpected270); } Loading services/surfaceflinger/SurfaceFlinger.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -3055,7 +3055,7 @@ void SurfaceFlinger::updateInputFlinger() { bool enablePerWindowInputRotation() { static bool value = android::base::GetBoolProperty("persist.debug.per_window_input_rotation", false); android::base::GetBoolProperty("persist.debug.per_window_input_rotation", true); return value; } Loading Loading
libs/input/Input.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -47,7 +47,7 @@ namespace { // 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); base::GetBoolProperty("persist.debug.per_window_input_rotation", true); return PER_WINDOW_INPUT_ROTATION; } Loading
services/inputflinger/reader/mapper/TouchCursorInputMapperCommon.h +1 −3 Original line number Diff line number Diff line Loading @@ -33,9 +33,7 @@ namespace android { // projection are part of the input window's transform. This means InputReader should work in the // un-rotated coordinate space. static bool isPerWindowInputRotationEnabled() { static const bool PER_WINDOW_INPUT_ROTATION = sysprop::InputFlingerProperties::per_window_input_rotation().value_or(false); return PER_WINDOW_INPUT_ROTATION; return sysprop::InputFlingerProperties::per_window_input_rotation().value_or(true); } static int32_t getInverseRotation(int32_t orientation) { Loading
services/inputflinger/tests/InputReader_test.cpp +152 −50 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ #include <CursorInputMapper.h> #include <InputDevice.h> #include <InputFlingerProperties.sysprop.h> #include <InputMapper.h> #include <InputReader.h> #include <InputReaderBase.h> Loading Loading @@ -95,6 +96,17 @@ const std::unordered_map<std::string, LightColor> LIGHT_COLORS = {{"red", LightC {"green", LightColor::GREEN}, {"blue", LightColor::BLUE}}; static int32_t getInverseRotation(int32_t orientation) { switch (orientation) { case DISPLAY_ORIENTATION_90: return DISPLAY_ORIENTATION_270; case DISPLAY_ORIENTATION_270: return DISPLAY_ORIENTATION_90; default: return orientation; } } // --- FakePointerController --- class FakePointerController : public PointerControllerInterface { Loading Loading @@ -2660,6 +2672,7 @@ protected: static const int32_t DEVICE_CONTROLLER_NUMBER; static const Flags<InputDeviceClass> DEVICE_CLASSES; static const int32_t EVENTHUB_ID; static const std::optional<bool> INITIAL_PER_WINDOW_INPUT_ROTATION_FLAG_VALUE; std::shared_ptr<FakeEventHub> mFakeEventHub; sp<FakeInputReaderPolicy> mFakePolicy; Loading @@ -2676,11 +2689,19 @@ protected: mDevice = newDevice(DEVICE_ID, DEVICE_NAME, DEVICE_LOCATION, EVENTHUB_ID, classes); } void SetUp() override { SetUp(DEVICE_CLASSES); } void SetUp() override { // Ensure per_window_input_rotation is enabled. sysprop::InputFlingerProperties::per_window_input_rotation(true); SetUp(DEVICE_CLASSES); } void TearDown() override { mFakeListener.clear(); mFakePolicy.clear(); sysprop::InputFlingerProperties::per_window_input_rotation( INITIAL_PER_WINDOW_INPUT_ROTATION_FLAG_VALUE); } void addConfigurationProperty(const char* key, const char* value) { Loading Loading @@ -2792,6 +2813,8 @@ const int32_t InputMapperTest::DEVICE_CONTROLLER_NUMBER = 0; const Flags<InputDeviceClass> InputMapperTest::DEVICE_CLASSES = Flags<InputDeviceClass>(0); // not needed for current tests const int32_t InputMapperTest::EVENTHUB_ID = 1; const std::optional<bool> InputMapperTest::INITIAL_PER_WINDOW_INPUT_ROTATION_FLAG_VALUE = sysprop::InputFlingerProperties::per_window_input_rotation(); // --- SwitchInputMapperTest --- Loading Loading @@ -4088,8 +4111,11 @@ TEST_F(CursorInputMapperTest, Process_ShouldHandleCombinedXYAndButtonUpdates) { ASSERT_NO_FATAL_FAILURE(assertCursorPointerCoords(args.pointerCoords[0], 0.0f, 0.0f, 0.0f)); } TEST_F(CursorInputMapperTest, Process_WhenNotOrientationAware_ShouldNotRotateMotions) { TEST_F(CursorInputMapperTest, Process_WhenOrientationAware_ShouldNotRotateMotions) { addConfigurationProperty("cursor.mode", "navigation"); // InputReader works in the un-rotated coordinate space, so orientation-aware devices do not // need to be rotated. addConfigurationProperty("cursor.orientationAware", "1"); CursorInputMapper& mapper = addMapperAndConfigure<CursorInputMapper>(); prepareDisplay(DISPLAY_ORIENTATION_90); Loading @@ -4103,9 +4129,10 @@ TEST_F(CursorInputMapperTest, Process_WhenNotOrientationAware_ShouldNotRotateMot ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, 1, -1, 1)); } TEST_F(CursorInputMapperTest, Process_WhenOrientationAware_ShouldRotateMotions) { TEST_F(CursorInputMapperTest, Process_WhenNotOrientationAware_ShouldRotateMotions) { addConfigurationProperty("cursor.mode", "navigation"); addConfigurationProperty("cursor.orientationAware", "1"); // Since InputReader works in the un-rotated coordinate space, only devices that are not // orientation-aware are affected by display rotation. CursorInputMapper& mapper = addMapperAndConfigure<CursorInputMapper>(); prepareDisplay(DISPLAY_ORIENTATION_0); Loading @@ -4119,14 +4146,14 @@ TEST_F(CursorInputMapperTest, Process_WhenOrientationAware_ShouldRotateMotions) ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, 1, -1, 1)); prepareDisplay(DISPLAY_ORIENTATION_90); ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 0, 1, 1, 0)); ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, 1, 1, -1)); ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, 0, 0, -1)); ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, -1, -1, -1)); ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 0, -1, -1, 0)); ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, -1, -1, 1)); ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, 0, 0, 1)); ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, 1, 1, 1)); ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 0, 1, -1, 0)); ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, 1, -1, 1)); ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, 0, 0, 1)); ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, -1, 1, 1)); ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 0, -1, 1, 0)); ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, -1, 1, -1)); ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, 0, 0, -1)); ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, 1, -1, -1)); prepareDisplay(DISPLAY_ORIENTATION_180); ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 0, 1, 0, -1)); Loading @@ -4139,14 +4166,14 @@ TEST_F(CursorInputMapperTest, Process_WhenOrientationAware_ShouldRotateMotions) ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, 1, 1, -1)); prepareDisplay(DISPLAY_ORIENTATION_270); ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 0, 1, -1, 0)); ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, 1, -1, 1)); ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, 0, 0, 1)); ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, -1, 1, 1)); ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 0, -1, 1, 0)); ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, -1, 1, -1)); ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, 0, 0, -1)); ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, 1, -1, -1)); ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 0, 1, 1, 0)); ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, 1, 1, -1)); ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, 0, 0, -1)); ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, -1, -1, -1)); ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 0, -1, -1, 0)); ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, -1, -1, 1)); ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, 0, 0, 1)); ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, 1, 1, 1)); } TEST_F(CursorInputMapperTest, Process_ShouldHandleAllButtons) { Loading Loading @@ -5368,11 +5395,12 @@ TEST_F(SingleTouchInputMapperTest, Process_NormalSingleTouchGesture) { ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled()); } TEST_F(SingleTouchInputMapperTest, Process_WhenNotOrientationAware_DoesNotRotateMotions) { TEST_F(SingleTouchInputMapperTest, Process_WhenOrientationAware_DoesNotRotateMotions) { addConfigurationProperty("touch.deviceType", "touchScreen"); prepareButtons(); prepareAxes(POSITION); addConfigurationProperty("touch.orientationAware", "0"); // InputReader works in the un-rotated coordinate space, so orientation-aware devices do not // need to be rotated. Touchscreens are orientation-aware by default. SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>(); NotifyMotionArgs args; Loading @@ -5391,10 +5419,13 @@ TEST_F(SingleTouchInputMapperTest, Process_WhenNotOrientationAware_DoesNotRotate ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled()); } TEST_F(SingleTouchInputMapperTest, Process_WhenOrientationAware_RotatesMotions) { TEST_F(SingleTouchInputMapperTest, Process_WhenNotOrientationAware_RotatesMotions) { addConfigurationProperty("touch.deviceType", "touchScreen"); prepareButtons(); prepareAxes(POSITION); // Since InputReader works in the un-rotated coordinate space, only devices that are not // orientation-aware are affected by display rotation. addConfigurationProperty("touch.orientationAware", "0"); SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>(); NotifyMotionArgs args; Loading @@ -5416,7 +5447,7 @@ TEST_F(SingleTouchInputMapperTest, Process_WhenOrientationAware_RotatesMotions) // Rotation 90. clearViewports(); prepareDisplay(DISPLAY_ORIENTATION_90); processDown(mapper, RAW_X_MAX - toRawX(75) + RAW_X_MIN, toRawY(50)); processDown(mapper, toRawX(75), RAW_Y_MAX - toRawY(50) + RAW_Y_MIN); processSync(mapper); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args)); Loading Loading @@ -5444,7 +5475,7 @@ TEST_F(SingleTouchInputMapperTest, Process_WhenOrientationAware_RotatesMotions) // Rotation 270. clearViewports(); prepareDisplay(DISPLAY_ORIENTATION_270); processDown(mapper, toRawX(75), RAW_Y_MAX - toRawY(50) + RAW_Y_MIN); processDown(mapper, RAW_X_MAX - toRawX(75) + RAW_X_MIN, toRawY(50)); processSync(mapper); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args)); Loading Loading @@ -7806,9 +7837,35 @@ TEST_F(MultiTouchInputMapperTest, VideoFrames_ReceivedByListener) { ASSERT_EQ(std::vector<TouchVideoFrame>(), motionArgs.videoFrames); } TEST_F(MultiTouchInputMapperTest, VideoFrames_AreRotated) { TEST_F(MultiTouchInputMapperTest, VideoFrames_AreNotRotated) { prepareAxes(POSITION); addConfigurationProperty("touch.deviceType", "touchScreen"); MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>(); // Unrotated video frame TouchVideoFrame frame(3, 2, {1, 2, 3, 4, 5, 6}, {1, 2}); NotifyMotionArgs motionArgs; // Test all 4 orientations for (int32_t orientation : {DISPLAY_ORIENTATION_0, DISPLAY_ORIENTATION_90, DISPLAY_ORIENTATION_180, DISPLAY_ORIENTATION_270}) { SCOPED_TRACE("Orientation " + StringPrintf("%i", orientation)); clearViewports(); prepareDisplay(orientation); std::vector<TouchVideoFrame> frames{frame}; mFakeEventHub->setVideoFrames({{EVENTHUB_ID, frames}}); processPosition(mapper, 100, 200); processSync(mapper); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); ASSERT_EQ(frames, motionArgs.videoFrames); } } TEST_F(MultiTouchInputMapperTest, VideoFrames_WhenNotOrientationAware_AreRotated) { prepareAxes(POSITION); addConfigurationProperty("touch.deviceType", "touchScreen"); // Since InputReader works in the un-rotated coordinate space, only devices that are not // orientation-aware are affected by display rotation. addConfigurationProperty("touch.orientationAware", "0"); MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>(); // Unrotated video frame TouchVideoFrame frame(3, 2, {1, 2, 3, 4, 5, 6}, {1, 2}); Loading @@ -7825,14 +7882,41 @@ TEST_F(MultiTouchInputMapperTest, VideoFrames_AreRotated) { processPosition(mapper, 100, 200); processSync(mapper); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); frames[0].rotate(orientation); // We expect the raw coordinates of the MotionEvent to be rotated in the inverse direction // compared to the display. This is so that when the window transform (which contains the // display rotation) is applied later by InputDispatcher, the coordinates end up in the // window's coordinate space. frames[0].rotate(getInverseRotation(orientation)); ASSERT_EQ(frames, motionArgs.videoFrames); } } TEST_F(MultiTouchInputMapperTest, VideoFrames_MultipleFramesAreRotated) { TEST_F(MultiTouchInputMapperTest, VideoFrames_MultipleFramesAreNotRotated) { prepareAxes(POSITION); addConfigurationProperty("touch.deviceType", "touchScreen"); MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>(); // Unrotated video frames. There's no rule that they must all have the same dimensions, // so mix these. TouchVideoFrame frame1(3, 2, {1, 2, 3, 4, 5, 6}, {1, 2}); TouchVideoFrame frame2(3, 3, {0, 1, 2, 3, 4, 5, 6, 7, 8}, {1, 3}); TouchVideoFrame frame3(2, 2, {10, 20, 10, 0}, {1, 4}); std::vector<TouchVideoFrame> frames{frame1, frame2, frame3}; NotifyMotionArgs motionArgs; prepareDisplay(DISPLAY_ORIENTATION_90); mFakeEventHub->setVideoFrames({{EVENTHUB_ID, frames}}); processPosition(mapper, 100, 200); processSync(mapper); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); ASSERT_EQ(frames, motionArgs.videoFrames); } TEST_F(MultiTouchInputMapperTest, VideoFrames_WhenNotOrientationAware_MultipleFramesAreRotated) { prepareAxes(POSITION); addConfigurationProperty("touch.deviceType", "touchScreen"); // Since InputReader works in the un-rotated coordinate space, only devices that are not // orientation-aware are affected by display rotation. addConfigurationProperty("touch.orientationAware", "0"); MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>(); // Unrotated video frames. There's no rule that they must all have the same dimensions, // so mix these. Loading @@ -7847,8 +7931,13 @@ TEST_F(MultiTouchInputMapperTest, VideoFrames_MultipleFramesAreRotated) { processPosition(mapper, 100, 200); processSync(mapper); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); std::for_each(frames.begin(), frames.end(), [](TouchVideoFrame& frame) { frame.rotate(DISPLAY_ORIENTATION_90); }); std::for_each(frames.begin(), frames.end(), [](TouchVideoFrame& frame) { // We expect the raw coordinates of the MotionEvent to be rotated in the inverse direction // compared to the display. This is so that when the window transform (which contains the // display rotation) is applied later by InputDispatcher, the coordinates end up in the // window's coordinate space. frame.rotate(getInverseRotation(DISPLAY_ORIENTATION_90)); }); ASSERT_EQ(frames, motionArgs.videoFrames); } Loading Loading @@ -8402,18 +8491,25 @@ TEST_F(MultiTouchInputMapperTest_SurfaceRange, Viewports_SurfaceRange) { // Reset. mapper.reset(ARBITRARY_TIME); // Let physical display be different to device, and make surface and physical could be 1:1. halfDisplayToCenterHorizontal(DISPLAY_ORIENTATION_0); // Let physical display be different to device, and make surface and physical could be 1:1 in // all four orientations. for (int orientation : {DISPLAY_ORIENTATION_0, DISPLAY_ORIENTATION_90, DISPLAY_ORIENTATION_180, DISPLAY_ORIENTATION_270}) { halfDisplayToCenterHorizontal(orientation); const int32_t xExpected = (x + 1) - (DISPLAY_WIDTH / 4); const int32_t yExpected = y; processPositionAndVerify(mapper, x - 1, y, x + 1, y, xExpected, yExpected); } } TEST_F(MultiTouchInputMapperTest_SurfaceRange, Viewports_SurfaceRange_90) { TEST_F(MultiTouchInputMapperTest_SurfaceRange, Viewports_SurfaceRange_90_NotOrientationAware) { addConfigurationProperty("touch.deviceType", "touchScreen"); prepareDisplay(DISPLAY_ORIENTATION_0); prepareAxes(POSITION); // Since InputReader works in the un-rotated coordinate space, only devices that are not // orientation-aware are affected by display rotation. addConfigurationProperty("touch.orientationAware", "0"); MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>(); // Half display to (width/4, 0, width * 3/4, height) and rotate 90-degrees. Loading @@ -8422,16 +8518,19 @@ TEST_F(MultiTouchInputMapperTest_SurfaceRange, Viewports_SurfaceRange_90) { const int32_t x = DISPLAY_WIDTH / 4; const int32_t y = DISPLAY_HEIGHT / 2; // expect x/y = swap x/y then reverse y. const int32_t xExpected = y; const int32_t yExpected = (DISPLAY_WIDTH * 3 / 4) - (x + 1); // expect x/y = swap x/y then reverse x. constexpr int32_t xExpected = DISPLAY_HEIGHT - y; constexpr int32_t yExpected = (x + 1) - DISPLAY_WIDTH / 4; processPositionAndVerify(mapper, x - 1, y, x + 1, y, xExpected, yExpected); } TEST_F(MultiTouchInputMapperTest_SurfaceRange, Viewports_SurfaceRange_270) { TEST_F(MultiTouchInputMapperTest_SurfaceRange, Viewports_SurfaceRange_270_NotOrientationAware) { addConfigurationProperty("touch.deviceType", "touchScreen"); prepareDisplay(DISPLAY_ORIENTATION_0); prepareAxes(POSITION); // Since InputReader works in the un-rotated coordinate space, only devices that are not // orientation-aware are affected by display rotation. addConfigurationProperty("touch.orientationAware", "0"); MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>(); // Half display to (width/4, 0, width * 3/4, height) and rotate 270-degrees. Loading @@ -8440,16 +8539,19 @@ TEST_F(MultiTouchInputMapperTest_SurfaceRange, Viewports_SurfaceRange_270) { const int32_t x = DISPLAY_WIDTH / 4; const int32_t y = DISPLAY_HEIGHT / 2; // expect x/y = swap x/y then reverse x. constexpr int32_t xExpected = DISPLAY_HEIGHT - y; constexpr int32_t yExpected = (x + 1) - DISPLAY_WIDTH / 4; // expect x/y = swap x/y then reverse y. const int32_t xExpected = y; const int32_t yExpected = (DISPLAY_WIDTH * 3 / 4) - (x + 1); processPositionAndVerify(mapper, x - 1, y, x + 1, y, xExpected, yExpected); } TEST_F(MultiTouchInputMapperTest_SurfaceRange, Viewports_SurfaceRange_Corner) { TEST_F(MultiTouchInputMapperTest_SurfaceRange, Viewports_SurfaceRange_Corner_NotOrientationAware) { addConfigurationProperty("touch.deviceType", "touchScreen"); prepareDisplay(DISPLAY_ORIENTATION_0); prepareAxes(POSITION); // Since InputReader works in the un-rotated coordinate space, only devices that are not // orientation-aware are affected by display rotation. addConfigurationProperty("touch.orientationAware", "0"); MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>(); const int32_t x = 0; Loading @@ -8461,16 +8563,16 @@ TEST_F(MultiTouchInputMapperTest_SurfaceRange, Viewports_SurfaceRange_Corner) { clearViewports(); prepareDisplay(DISPLAY_ORIENTATION_90); // expect x/y = swap x/y then reverse y. const int32_t xExpected90 = y; const int32_t yExpected90 = DISPLAY_WIDTH - 1; // expect x/y = swap x/y then reverse x. const int32_t xExpected90 = DISPLAY_HEIGHT - 1; const int32_t yExpected90 = x; processPositionAndVerify(mapper, x - 1, y, x, y, xExpected90, yExpected90); clearViewports(); prepareDisplay(DISPLAY_ORIENTATION_270); // expect x/y = swap x/y then reverse x. const int32_t xExpected270 = DISPLAY_HEIGHT - 1; const int32_t yExpected270 = x; // expect x/y = swap x/y then reverse y. const int32_t xExpected270 = y; const int32_t yExpected270 = DISPLAY_WIDTH - 1; processPositionAndVerify(mapper, x - 1, y, x, y, xExpected270, yExpected270); } Loading
services/surfaceflinger/SurfaceFlinger.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -3055,7 +3055,7 @@ void SurfaceFlinger::updateInputFlinger() { bool enablePerWindowInputRotation() { static bool value = android::base::GetBoolProperty("persist.debug.per_window_input_rotation", false); android::base::GetBoolProperty("persist.debug.per_window_input_rotation", true); return value; } Loading