summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArthur Hung <arthurhung@google.com>2022-11-15 03:30:48 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-12-14 02:25:07 +0000
commit45f243437bd453fe6d6a8f41845302375fe163ee (patch)
tree886dc6936c4c5f2a93d6f8ab053adf7c460d9300
parent26ff024b142760e6ce306e3076931f9d0430460e (diff)
downloadnative-45f243437bd453fe6d6a8f41845302375fe163ee.tar.gz
Fix ACTION_POINTER_DOWN reports wrong pointers
This fix the second pointer will use the identity transform because the returned touched windows should be refreshed after updating the new pointerIds to the temporary touch state. This also fixed wallpaper window can't receive up event. Bug: 258382964 Bug: 240308355 Test: atest inputflinger_tests Change-Id: I96a738dcb01bf1c9e2792d3fee547c147dba33b5 Merged-In: I96a738dcb01bf1c9e2792d3fee547c147dba33b5 Merged-In: Ibf82b494e45e35babe9ba9f3dd1236fee8bcea6d (cherry picked from commit 69d7557788c62040776e2e3d524034d9924704e6) Merged-In: I96a738dcb01bf1c9e2792d3fee547c147dba33b5
-rw-r--r--services/inputflinger/dispatcher/InputDispatcher.cpp29
-rw-r--r--services/inputflinger/tests/InputDispatcher_test.cpp95
2 files changed, 112 insertions, 12 deletions
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index d8120fcb5e..5c47be9be0 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -2276,6 +2276,20 @@ InputEventInjectionResult InputDispatcher::findTouchedWindowTargetsLocked(
tempTouchState.addOrUpdateWindow(newTouchedWindowHandle, targetFlags, pointerIds);
}
}
+
+ // Update the pointerIds for non-splittable when it received pointer down.
+ if (!isSplit && maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN) {
+ // If no split, we suppose all touched windows should receive pointer down.
+ const int32_t pointerIndex = getMotionEventActionPointerIndex(action);
+ for (size_t i = 0; i < tempTouchState.windows.size(); i++) {
+ TouchedWindow& touchedWindow = tempTouchState.windows[i];
+ // Ignore drag window for it should just track one pointer.
+ if (mDragState && mDragState->dragWindow == touchedWindow.windowHandle) {
+ continue;
+ }
+ touchedWindow.pointerIds.markBit(entry.pointerProperties[pointerIndex].id);
+ }
+ }
}
// Update dispatching for hover enter and exit.
@@ -2384,13 +2398,15 @@ InputEventInjectionResult InputDispatcher::findTouchedWindowTargetsLocked(
if (info->displayId == displayId &&
windowHandle->getInfo()->inputConfig.test(
WindowInfo::InputConfig::IS_WALLPAPER)) {
+ BitSet32 pointerIds;
+ pointerIds.markBit(entry.pointerProperties[0].id);
tempTouchState
.addOrUpdateWindow(windowHandle,
InputTarget::FLAG_WINDOW_IS_OBSCURED |
InputTarget::
FLAG_WINDOW_IS_PARTIALLY_OBSCURED |
InputTarget::FLAG_DISPATCH_AS_IS,
- BitSet32(0));
+ pointerIds);
}
}
}
@@ -2460,17 +2476,6 @@ Failed:
}
i += 1;
}
- } else if (!isSplit && maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN) {
- // If no split, we suppose all touched windows should receive pointer down.
- const int32_t pointerIndex = getMotionEventActionPointerIndex(action);
- for (size_t i = 0; i < tempTouchState.windows.size(); i++) {
- TouchedWindow& touchedWindow = tempTouchState.windows[i];
- // Ignore drag window for it should just track one pointer.
- if (mDragState && mDragState->dragWindow == touchedWindow.windowHandle) {
- continue;
- }
- touchedWindow.pointerIds.markBit(entry.pointerProperties[pointerIndex].id);
- }
}
// Save changes unless the action was scroll in which case the temporary touch
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index df1a230002..58617f7383 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -1887,6 +1887,64 @@ TEST_F(InputDispatcherTest, TwoWindows_SplitWallpaperTouch) {
wallpaperWindow->assertNoEvents();
}
+TEST_F(InputDispatcherTest, WallpaperWindowReceivesMultiTouch) {
+ std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
+ sp<FakeWindowHandle> window =
+ sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
+ window->setDupTouchToWallpaper(true);
+
+ sp<FakeWindowHandle> wallpaperWindow =
+ sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
+ wallpaperWindow->setIsWallpaper(true);
+ constexpr int expectedWallpaperFlags =
+ AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED | AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
+ wallpaperWindow->setPreventSplitting(true);
+
+ mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, wallpaperWindow}}});
+
+ ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
+ injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
+ {50, 50}))
+ << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
+ window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
+ wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
+
+ const MotionEvent secondFingerDownEvent =
+ MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
+ .displayId(ADISPLAY_ID_DEFAULT)
+ .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
+ .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
+ .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(10).y(10))
+ .build();
+ ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
+ injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
+ InputEventInjectionSync::WAIT_FOR_RESULT))
+ << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
+
+ window->consumeMotionPointerDown(1);
+ wallpaperWindow->consumeMotionPointerDown(1, ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
+
+ const MotionEvent secondFingerUpEvent =
+ MotionEventBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
+ .displayId(ADISPLAY_ID_DEFAULT)
+ .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
+ .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
+ .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(10).y(10))
+ .build();
+ ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
+ injectMotionEvent(mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
+ InputEventInjectionSync::WAIT_FOR_RESULT))
+ << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
+ window->consumeMotionPointerUp(1);
+ wallpaperWindow->consumeMotionPointerUp(1, ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
+
+ ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
+ injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {50, 50}))
+ << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
+ window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
+ wallpaperWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
+}
+
/**
* On the display, have a single window, and also an area where there's no window.
* First pointer touches the "no window" area of the screen. Second pointer touches the window.
@@ -2322,6 +2380,43 @@ TEST_F(InputDispatcherTest, OnWindowInfosChanged_RemoveAllWindowsOnDisplay) {
window->assertNoEvents();
}
+TEST_F(InputDispatcherTest, NonSplitTouchableWindowReceivesMultiTouch) {
+ std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
+ sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
+ "Fake Window", ADISPLAY_ID_DEFAULT);
+ // Ensure window is non-split and have some transform.
+ window->setPreventSplitting(true);
+ window->setWindowOffset(20, 40);
+ mDispatcher->onWindowInfosChanged({*window->getInfo()}, {});
+
+ ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
+ injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
+ {50, 50}))
+ << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
+ window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
+
+ const MotionEvent secondFingerDownEvent =
+ MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
+ .displayId(ADISPLAY_ID_DEFAULT)
+ .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
+ .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
+ .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER)
+ .x(-30)
+ .y(-50))
+ .build();
+ ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
+ injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
+ InputEventInjectionSync::WAIT_FOR_RESULT))
+ << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
+
+ const MotionEvent* event = window->consumeMotion();
+ EXPECT_EQ(POINTER_1_DOWN, event->getAction());
+ EXPECT_EQ(70, event->getX(0)); // 50 + 20
+ EXPECT_EQ(90, event->getY(0)); // 50 + 40
+ EXPECT_EQ(-10, event->getX(1)); // -30 + 20
+ EXPECT_EQ(-10, event->getY(1)); // -50 + 40
+}
+
/**
* Ensure the correct coordinate spaces are used by InputDispatcher.
*