summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/inputflinger/dispatcher/InputDispatcher.cpp13
-rw-r--r--services/inputflinger/tests/InputDispatcher_test.cpp54
2 files changed, 67 insertions, 0 deletions
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index 15043db7fb..fcd784d38a 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -4878,6 +4878,19 @@ InputEventInjectionResult InputDispatcher::injectInputEvent(const InputEvent* ev
return InputEventInjectionResult::FAILED;
}
+ if (!(policyFlags & POLICY_FLAG_PASS_TO_USER)) {
+ // Set the flag anyway if we already have an ongoing motion gesture. That
+ // would allow us to complete the processing of the current stroke.
+ const auto touchStateIt = mTouchStatesByDisplay.find(displayId);
+ if (touchStateIt != mTouchStatesByDisplay.end()) {
+ const TouchState& touchState = touchStateIt->second;
+ if (touchState.hasTouchingPointers(resolvedDeviceId) ||
+ touchState.hasHoveringPointers(resolvedDeviceId)) {
+ policyFlags |= POLICY_FLAG_PASS_TO_USER;
+ }
+ }
+ }
+
const nsecs_t* sampleEventTimes = motionEvent.getSampleEventTimes();
const size_t pointerCount = motionEvent.getPointerCount();
const std::vector<PointerProperties>
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index 6ec08892c0..685645cfbb 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -1570,6 +1570,60 @@ TEST_F(InputDispatcherTest, HoverEventInconsistentPolicy) {
window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
}
+// Still send inject motion events to window which already be touched.
+TEST_F(InputDispatcherTest, AlwaysDispatchInjectMotionEventWhenAlreadyDownForWindow) {
+ std::shared_ptr<FakeApplicationHandle> application1 = std::make_shared<FakeApplicationHandle>();
+ sp<FakeWindowHandle> window1 =
+ sp<FakeWindowHandle>::make(application1, mDispatcher, "window1",
+ ui::LogicalDisplayId::DEFAULT);
+ window1->setFrame(Rect(0, 0, 100, 100));
+ window1->setWatchOutsideTouch(false);
+
+ std::shared_ptr<FakeApplicationHandle> application2 = std::make_shared<FakeApplicationHandle>();
+ sp<FakeWindowHandle> window2 =
+ sp<FakeWindowHandle>::make(application2, mDispatcher, "window2",
+ ui::LogicalDisplayId::DEFAULT);
+ window2->setFrame(Rect(50, 50, 100, 100));
+ window2->setWatchOutsideTouch(true);
+ mDispatcher->onWindowInfosChanged({{*window2->getInfo(), *window1->getInfo()}, {}, 0, 0});
+
+ std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT;
+ InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT;
+ std::optional<gui::Uid> targetUid = {};
+ uint32_t policyFlags = DEFAULT_POLICY_FLAGS;
+
+ const MotionEvent eventDown1 = MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
+ .pointer(PointerBuilder(0, ToolType::FINGER).x(60).y(60)).deviceId(-1)
+ .build();
+ injectMotionEvent(*mDispatcher, eventDown1, injectionTimeout, injectionMode, targetUid,
+ policyFlags);
+ window2->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
+
+ const MotionEvent eventUp1 = MotionEventBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
+ .pointer(PointerBuilder(0, ToolType::FINGER).x(60).y(60)).deviceId(-1)
+ .downTime(eventDown1.getDownTime()).build();
+ // Inject UP event, without the POLICY_FLAG_PASS_TO_USER (to simulate policy behaviour
+ // when screen is off).
+ injectMotionEvent(*mDispatcher, eventUp1, injectionTimeout, injectionMode, targetUid,
+ /*policyFlags=*/0);
+ window2->consumeMotionEvent(WithMotionAction(ACTION_UP));
+ const MotionEvent eventDown2 = MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
+ .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(40)).deviceId(-1)
+ .build();
+ injectMotionEvent(*mDispatcher, eventDown2, injectionTimeout, injectionMode, targetUid,
+ policyFlags);
+ window1->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
+ window2->consumeMotionEvent(WithMotionAction(ACTION_OUTSIDE));
+
+ const MotionEvent eventUp2 = MotionEventBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
+ .pointer(PointerBuilder(0, ToolType::FINGER).x(60).y(60)).deviceId(-1)
+ .downTime(eventDown2.getDownTime()).build();
+ injectMotionEvent(*mDispatcher, eventUp2, injectionTimeout, injectionMode, targetUid,
+ /*policyFlags=*/0);
+ window1->consumeMotionEvent(WithMotionAction(ACTION_UP));
+ window2->assertNoEvents();
+}
+
/**
* Two windows: a window on the left and a window on the right.
* Mouse is hovered from the right window into the left window.