summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libs/gui/WindowInfo.cpp9
-rw-r--r--libs/gui/include/gui/WindowInfo.h2
-rw-r--r--services/inputflinger/dispatcher/InputDispatcher.cpp24
-rw-r--r--services/inputflinger/tests/InputDispatcher_test.cpp18
4 files changed, 51 insertions, 2 deletions
diff --git a/libs/gui/WindowInfo.cpp b/libs/gui/WindowInfo.cpp
index ba1d196e9c..95b2641f04 100644
--- a/libs/gui/WindowInfo.cpp
+++ b/libs/gui/WindowInfo.cpp
@@ -258,8 +258,7 @@ void WindowInfoHandle::updateFrom(sp<WindowInfoHandle> handle) {
mInfo = handle->mInfo;
}
-std::ostream& operator<<(std::ostream& out, const WindowInfoHandle& window) {
- const WindowInfo& info = *window.getInfo();
+std::ostream& operator<<(std::ostream& out, const WindowInfo& info) {
std::string transform;
info.transform.dump(transform, "transform", " ");
out << "name=" << info.name << ", id=" << info.id << ", displayId=" << info.displayId
@@ -277,4 +276,10 @@ std::ostream& operator<<(std::ostream& out, const WindowInfoHandle& window) {
return out;
}
+std::ostream& operator<<(std::ostream& out, const WindowInfoHandle& window) {
+ const WindowInfo& info = *window.getInfo();
+ out << info;
+ return out;
+}
+
} // namespace android::gui
diff --git a/libs/gui/include/gui/WindowInfo.h b/libs/gui/include/gui/WindowInfo.h
index b72b71a3ce..e72fd59147 100644
--- a/libs/gui/include/gui/WindowInfo.h
+++ b/libs/gui/include/gui/WindowInfo.h
@@ -269,6 +269,8 @@ struct WindowInfo : public Parcelable {
status_t readFromParcel(const android::Parcel* parcel) override;
};
+std::ostream& operator<<(std::ostream& out, const WindowInfo& window);
+
/*
* Handle for a window that can receive input.
*
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index 162a7bd6c5..39657f2ced 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -763,6 +763,21 @@ bool isStylusActiveInDisplay(
return state.hasActiveStylus();
}
+Result<void> validateWindowInfosUpdate(const gui::WindowInfosUpdate& update) {
+ struct HashFunction {
+ size_t operator()(const WindowInfo& info) const { return info.id; }
+ };
+
+ std::unordered_set<WindowInfo, HashFunction> windowSet;
+ for (const WindowInfo& info : update.windowInfos) {
+ const auto [_, inserted] = windowSet.insert(info);
+ if (!inserted) {
+ return Error() << "Duplicate entry for " << info;
+ }
+ }
+ return {};
+}
+
} // namespace
// --- InputDispatcher ---
@@ -6762,6 +6777,15 @@ void InputDispatcher::displayRemoved(int32_t displayId) {
}
void InputDispatcher::onWindowInfosChanged(const gui::WindowInfosUpdate& update) {
+ if (auto result = validateWindowInfosUpdate(update); !result.ok()) {
+ {
+ // acquire lock
+ std::scoped_lock _l(mLock);
+ logDispatchStateLocked();
+ }
+ LOG_ALWAYS_FATAL("Incorrect WindowInfosUpdate provided: %s",
+ result.error().message().c_str());
+ };
// The listener sends the windows as a flattened array. Separate the windows by display for
// more convenient parsing.
std::unordered_map<int32_t, std::vector<sp<WindowInfoHandle>>> handlesPerDisplay;
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index 8be1b3ba00..5c5dfe1bf1 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -1680,6 +1680,24 @@ TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
}
+using InputDispatcherDeathTest = InputDispatcherTest;
+
+/**
+ * When 'onWindowInfosChanged' arguments contain a duplicate entry for the same window, dispatcher
+ * should crash.
+ */
+TEST_F(InputDispatcherDeathTest, DuplicateWindowInfosAbortDispatcher) {
+ testing::GTEST_FLAG(death_test_style) = "threadsafe";
+ ScopedSilentDeath _silentDeath;
+
+ std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
+ sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
+ "Fake Window", ADISPLAY_ID_DEFAULT);
+ ASSERT_DEATH(mDispatcher->onWindowInfosChanged(
+ {{*window->getInfo(), *window->getInfo()}, {}, 0, 0}),
+ "Incorrect WindowInfosUpdate provided");
+}
+
TEST_F(InputDispatcherTest, WhenDisplayNotSpecified_InjectMotionToDefaultDisplay) {
std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,