Loading libs/gui/WindowInfo.cpp +7 −2 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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 libs/gui/include/gui/WindowInfo.h +2 −0 Original line number Diff line number Diff line Loading @@ -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. * Loading services/inputflinger/dispatcher/InputDispatcher.cpp +24 −0 Original line number Diff line number Diff line Loading @@ -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 --- Loading Loading @@ -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; Loading services/inputflinger/tests/InputDispatcher_test.cpp +18 −0 Original line number Diff line number Diff line Loading @@ -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, Loading Loading
libs/gui/WindowInfo.cpp +7 −2 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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
libs/gui/include/gui/WindowInfo.h +2 −0 Original line number Diff line number Diff line Loading @@ -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. * Loading
services/inputflinger/dispatcher/InputDispatcher.cpp +24 −0 Original line number Diff line number Diff line Loading @@ -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 --- Loading Loading @@ -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; Loading
services/inputflinger/tests/InputDispatcher_test.cpp +18 −0 Original line number Diff line number Diff line Loading @@ -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, Loading