summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Siarhei Vishniakou <svv@google.com> 2024-08-02 12:10:05 -0700
committer Siarhei Vishniakou <svv@google.com> 2024-08-02 20:25:42 +0000
commit9d0d65e174e7fe5fe9dea9474b5297ef1e5761bf (patch)
tree551836ffffed10f8ac3d044edd048ef31435bce3
parent9b4b490937f1194bdfc5960ab54517c727ae3b51 (diff)
Reject invalid events injected by accessibility
This will avoid the processing of inconsistent event streams inside dispatcher, which can lead to crashes. Going forward, we should reject all inconsistent injected events, not just those from a11y. Bug: 356662669 Flag: EXEMPT bugfix Test: TEST=inputflinger_tests; m $TEST && $ANDROID_HOST_OUT/nativetest64/$TEST/$TEST --gtest_filter="*InvalidA11yEventsGetRejected" Change-Id: Ia127bcedf2288a2522d33d046fbbc8eb389babfb
-rw-r--r--include/input/InputEventBuilders.h16
-rw-r--r--services/inputflinger/dispatcher/InputDispatcher.cpp4
-rw-r--r--services/inputflinger/tests/InputDispatcher_test.cpp48
3 files changed, 61 insertions, 7 deletions
diff --git a/include/input/InputEventBuilders.h b/include/input/InputEventBuilders.h
index 25d35e9fe7..55e058332d 100644
--- a/include/input/InputEventBuilders.h
+++ b/include/input/InputEventBuilders.h
@@ -127,7 +127,7 @@ public:
return *this;
}
- MotionEvent build() {
+ MotionEvent build() const {
std::vector<PointerProperties> pointerProperties;
std::vector<PointerCoords> pointerCoords;
for (const PointerBuilder& pointer : mPointers) {
@@ -135,20 +135,22 @@ public:
pointerCoords.push_back(pointer.buildCoords());
}
+ auto [xCursorPosition, yCursorPosition] =
+ std::make_pair(mRawXCursorPosition, mRawYCursorPosition);
// Set mouse cursor position for the most common cases to avoid boilerplate.
if (mSource == AINPUT_SOURCE_MOUSE &&
- !MotionEvent::isValidCursorPosition(mRawXCursorPosition, mRawYCursorPosition)) {
- mRawXCursorPosition = pointerCoords[0].getX();
- mRawYCursorPosition = pointerCoords[0].getY();
+ !MotionEvent::isValidCursorPosition(xCursorPosition, yCursorPosition)) {
+ xCursorPosition = pointerCoords[0].getX();
+ yCursorPosition = pointerCoords[0].getY();
}
MotionEvent event;
event.initialize(InputEvent::nextId(), mDeviceId, mSource, mDisplayId, INVALID_HMAC,
mAction, mActionButton, mFlags, /*edgeFlags=*/0, AMETA_NONE, mButtonState,
MotionClassification::NONE, mTransform,
- /*xPrecision=*/0, /*yPrecision=*/0, mRawXCursorPosition,
- mRawYCursorPosition, mRawTransform, mDownTime, mEventTime,
- mPointers.size(), pointerProperties.data(), pointerCoords.data());
+ /*xPrecision=*/0, /*yPrecision=*/0, xCursorPosition, yCursorPosition,
+ mRawTransform, mDownTime, mEventTime, mPointers.size(),
+ pointerProperties.data(), pointerCoords.data());
return event;
}
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index af4a04d9eb..faafa50eb8 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -4879,6 +4879,10 @@ InputEventInjectionResult InputDispatcher::injectInputEvent(const InputEvent* ev
logDispatchStateLocked();
LOG(ERROR) << "Inconsistent event: " << motionEvent
<< ", reason: " << result.error();
+ if (policyFlags & POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY) {
+ mLock.unlock();
+ return InputEventInjectionResult::FAILED;
+ }
}
}
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index e5058507eb..d418a9b5ec 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -5037,6 +5037,54 @@ TEST_F_WITH_FLAGS(InputDispatcherTest, InvalidA11yHoverStreamDoesNotCrash,
}
/**
+ * Invalid events injected by input filter are rejected.
+ */
+TEST_F(InputDispatcherTest, InvalidA11yEventsGetRejected) {
+ std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
+ sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
+ ui::LogicalDisplayId::DEFAULT);
+
+ mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
+
+ mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
+
+ // a11y sets 'POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY' policy flag during injection, so define
+ // a custom injection function here for convenience.
+ auto injectFromAccessibility = [&](int32_t action, float x, float y) {
+ MotionEvent event = MotionEventBuilder(action, AINPUT_SOURCE_TOUCHSCREEN)
+ .pointer(PointerBuilder(0, ToolType::FINGER).x(x).y(y))
+ .addFlag(AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT)
+ .build();
+ return injectMotionEvent(*mDispatcher, event, 100ms,
+ InputEventInjectionSync::WAIT_FOR_RESULT, /*targetUid=*/{},
+ POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_FILTERED |
+ POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY);
+ };
+
+ ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
+ injectFromAccessibility(ACTION_DOWN, /*x=*/300, /*y=*/400));
+ ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
+ injectFromAccessibility(ACTION_MOVE, /*x=*/310, /*y=*/420));
+ window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
+ window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
+ // finger is still down, so a new DOWN event should be rejected!
+ ASSERT_EQ(InputEventInjectionResult::FAILED,
+ injectFromAccessibility(ACTION_DOWN, /*x=*/340, /*y=*/410));
+
+ // if the gesture is correctly finished, new down event will succeed
+ ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
+ injectFromAccessibility(ACTION_MOVE, /*x=*/320, /*y=*/430));
+ ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
+ injectFromAccessibility(ACTION_UP, /*x=*/320, /*y=*/430));
+ window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
+ window->consumeMotionEvent(WithMotionAction(ACTION_UP));
+
+ ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
+ injectFromAccessibility(ACTION_DOWN, /*x=*/350, /*y=*/460));
+ window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
+}
+
+/**
* If mouse is hovering when the touch goes down, the hovering should be stopped via HOVER_EXIT.
*/
TEST_F(InputDispatcherTest, TouchDownAfterMouseHover_legacy) {