Loading include/input/DisplayTopologyGraph.h +6 −2 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ #include <android-base/result.h> #include <ftl/enum.h> #include <ui/FloatRect.h> #include <ui/LogicalDisplayId.h> #include <cinttypes> Loading Loading @@ -58,6 +59,7 @@ struct DisplayTopologyGraph { ui::LogicalDisplayId primaryDisplayId = ui::LogicalDisplayId::INVALID; std::unordered_map<ui::LogicalDisplayId, std::vector<DisplayTopologyAdjacentDisplay>> graph; std::unordered_map<ui::LogicalDisplayId, int> displaysDensity; std::unordered_map<ui::LogicalDisplayId, FloatRect> boundsInGlobalDp; DisplayTopologyGraph() = default; std::string dump() const; Loading @@ -68,14 +70,16 @@ struct DisplayTopologyGraph { ui::LogicalDisplayId primaryDisplay, std::unordered_map<ui::LogicalDisplayId, std::vector<DisplayTopologyAdjacentDisplay>>&& adjacencyGraph, std::unordered_map<ui::LogicalDisplayId, int>&& displaysDensityMap); std::unordered_map<ui::LogicalDisplayId, int>&& displaysDensityMap, std::unordered_map<ui::LogicalDisplayId, FloatRect>&& boundsInGlobalDpMap); private: DisplayTopologyGraph( ui::LogicalDisplayId primaryDisplay, std::unordered_map<ui::LogicalDisplayId, std::vector<DisplayTopologyAdjacentDisplay>>&& adjacencyGraph, std::unordered_map<ui::LogicalDisplayId, int>&& displaysDensityMap); std::unordered_map<ui::LogicalDisplayId, int>&& displaysDensityMap, std::unordered_map<ui::LogicalDisplayId, FloatRect>&& boundsInGlobalDp); }; } // namespace android libs/input/DisplayTopologyGraph.cpp +23 −7 Original line number Diff line number Diff line Loading @@ -121,6 +121,13 @@ std::string adjacentDisplayVectorToString( return dumpVector(adjacentDisplays, adjacentDisplayToString); } std::string floatRectToString(const FloatRect& floatRect) { std::string dump; dump += base::StringPrintf("FloatRect(%f, %f, %f, %f)", floatRect.left, floatRect.top, floatRect.right, floatRect.bottom); return dump; } bool areTopologyGraphComponentsValid( ui::LogicalDisplayId primaryDisplayId, const std::unordered_map<ui::LogicalDisplayId, std::vector<DisplayTopologyAdjacentDisplay>>& Loading @@ -137,7 +144,8 @@ std::string dumpTopologyGraphComponents( ui::LogicalDisplayId primaryDisplayId, const std::unordered_map<ui::LogicalDisplayId, std::vector<DisplayTopologyAdjacentDisplay>>& graph, const std::unordered_map<ui::LogicalDisplayId, int>& displaysDensity) { const std::unordered_map<ui::LogicalDisplayId, int>& displaysDensity, const std::unordered_map<ui::LogicalDisplayId, FloatRect> boundsInGlobalDp) { std::string dump; dump += base::StringPrintf("PrimaryDisplayId: %d\n", primaryDisplayId.val()); dump += base::StringPrintf("TopologyGraph:\n"); Loading @@ -147,6 +155,10 @@ std::string dumpTopologyGraphComponents( dump += base::StringPrintf("DisplaysDensity:\n"); dump += addLinePrefix(dumpMap(displaysDensity, logicalDisplayIdToString), INDENT); dump += "\n"; dump += base::StringPrintf("DisplaysBoundsInGlobalDp:\n"); dump += addLinePrefix(dumpMap(boundsInGlobalDp, logicalDisplayIdToString, floatRectToString), INDENT); return dump; } Loading @@ -164,27 +176,31 @@ DisplayTopologyGraph::DisplayTopologyGraph( ui::LogicalDisplayId primaryDisplay, std::unordered_map<ui::LogicalDisplayId, std::vector<DisplayTopologyAdjacentDisplay>>&& adjacencyGraph, std::unordered_map<ui::LogicalDisplayId, int>&& displaysDensityMap) std::unordered_map<ui::LogicalDisplayId, int>&& displaysDensityMap, std::unordered_map<ui::LogicalDisplayId, FloatRect>&& boundsInGlobalDpMap) : primaryDisplayId(primaryDisplay), graph(std::move(adjacencyGraph)), displaysDensity(std::move(displaysDensityMap)) {} displaysDensity(std::move(displaysDensityMap)), boundsInGlobalDp(std::move(boundsInGlobalDpMap)) {} std::string DisplayTopologyGraph::dump() const { return dumpTopologyGraphComponents(primaryDisplayId, graph, displaysDensity); return dumpTopologyGraphComponents(primaryDisplayId, graph, displaysDensity, boundsInGlobalDp); } base::Result<const DisplayTopologyGraph> DisplayTopologyGraph::create( ui::LogicalDisplayId primaryDisplay, std::unordered_map<ui::LogicalDisplayId, std::vector<DisplayTopologyAdjacentDisplay>>&& adjacencyGraph, std::unordered_map<ui::LogicalDisplayId, int>&& displaysDensityMap) { std::unordered_map<ui::LogicalDisplayId, int>&& displaysDensityMap, std::unordered_map<ui::LogicalDisplayId, FloatRect>&& boundsInGlobalDp) { // Todo(b/401220484): add validation for display bounds if (areTopologyGraphComponentsValid(primaryDisplay, adjacencyGraph, displaysDensityMap)) { return DisplayTopologyGraph(primaryDisplay, std::move(adjacencyGraph), std::move(displaysDensityMap)); std::move(displaysDensityMap), std::move(boundsInGlobalDp)); } return base::Error() << "Invalid display topology components: " << dumpTopologyGraphComponents(primaryDisplay, adjacencyGraph, displaysDensityMap); displaysDensityMap, boundsInGlobalDp); } } // namespace android services/inputflinger/tests/DisplayTopologyGraph_test.cpp +2 −1 Original line number Diff line number Diff line Loading @@ -50,7 +50,8 @@ TEST_P(DisplayTopologyGraphTestFixture, DisplayTopologyGraphTest) { SCOPED_FLAG_OVERRIDE(enable_display_topology_validation, true); auto [_, primaryDisplayId, graph, displaysDensity, isValid] = GetParam(); auto result = DisplayTopologyGraph::create(primaryDisplayId, std::move(graph), std::move(displaysDensity)); std::move(displaysDensity), /*boundsInGlobalDpMap=*/{}); EXPECT_EQ(isValid, result.ok()); } Loading services/inputflinger/tests/InputDispatcher_test.cpp +4 −1 Original line number Diff line number Diff line Loading @@ -15501,7 +15501,10 @@ protected: {{DISPLAY_ID, DisplayTopologyPosition::BOTTOM, 0.0f}}}}, /*displaysDensity=*/ {{DISPLAY_ID, DENSITY_MEDIUM}, {SECOND_DISPLAY_ID, DENSITY_MEDIUM}}) {SECOND_DISPLAY_ID, DENSITY_MEDIUM}}, /*absoluteDisplayBoundsDp=*/ {{DISPLAY_ID, FloatRect(0, -500, 500, 0)}, {SECOND_DISPLAY_ID, FloatRect(0, 0, 500, 5000)}}) .value(); void SetUp() override { services/inputflinger/tests/PointerChoreographer_test.cpp +28 −8 Original line number Diff line number Diff line Loading @@ -153,7 +153,9 @@ protected: mChoreographer.setDisplayTopology( DisplayTopologyGraph::create(/*primaryDisplayId=*/displayId, /*adjacencyGraph=*/{}, /*displaysDensity=*/{{displayId, DENSITY_MEDIUM}}) /*displaysDensity=*/{{displayId, DENSITY_MEDIUM}}, /*absoluteDisplayBoundsDp=*/ {{displayId, FloatRect(0, 0, 500, 500)}}) .value()); } else { mChoreographer.setDefaultMouseDisplayId(displayId); Loading Loading @@ -2820,7 +2822,8 @@ protected: {DISPLAY_BOTTOM_ID, DENSITY_MEDIUM}, {DISPLAY_LEFT_ID, DENSITY_MEDIUM}, {DISPLAY_TOP_RIGHT_CORNER_ID, DENSITY_MEDIUM}, {DISPLAY_HIGH_DENSITY_ID, DENSITY_HIGH}}) {DISPLAY_HIGH_DENSITY_ID, DENSITY_HIGH}}, /*absoluteDisplayBoundsDp=*/{}) .value(); }; Loading Loading @@ -2960,10 +2963,12 @@ protected: static constexpr ui::LogicalDisplayId FIRST_DISPLAY_ID = ui::LogicalDisplayId{10}; static constexpr ui::LogicalDisplayId SECOND_DISPLAY_ID = ui::LogicalDisplayId{20}; static constexpr ui::LogicalDisplayId THIRD_DISPLAY_ID = ui::LogicalDisplayId{30}; static constexpr int32_t DISPLAY_WIDTH = 100; static constexpr int32_t DISPLAY_HEIGHT = 100; DisplayViewport createViewport(ui::LogicalDisplayId displayId) { return PointerChoreographerDisplayTopologyTests::createViewport(displayId, /*width=*/100, /*height=*/100, return PointerChoreographerDisplayTopologyTests::createViewport(displayId, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0); } Loading @@ -2979,6 +2984,11 @@ protected: std::unordered_map<ui::LogicalDisplayId, int> displaysDensity; displaysDensity[primaryDisplayId] = DENSITY_MEDIUM; std::unordered_map<ui::LogicalDisplayId, FloatRect> absoluteDisplayBoundsDp; absoluteDisplayBoundsDp.emplace(std::piecewise_construct, std::forward_as_tuple(primaryDisplayId), std::forward_as_tuple(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT)); for (ui::LogicalDisplayId adjacentDisplayId : adjacentDisplays) { topologyGraph[previousDisplay].push_back({.displayId = adjacentDisplayId, .position = DisplayTopologyPosition::RIGHT, Loading @@ -2988,12 +2998,22 @@ protected: .offsetDp = 0.0f}); displaysDensity[adjacentDisplayId] = DENSITY_MEDIUM; const auto& previousDisplayBounds = absoluteDisplayBoundsDp[previousDisplay]; absoluteDisplayBoundsDp.emplace(std::piecewise_construct, std::forward_as_tuple(adjacentDisplayId), std::forward_as_tuple(previousDisplayBounds.right, 0, previousDisplayBounds.right + DISPLAY_WIDTH, DISPLAY_HEIGHT)); previousDisplay = adjacentDisplayId; } mChoreographer.setDisplayTopology(DisplayTopologyGraph::create(primaryDisplayId, std::move(topologyGraph), std::move(displaysDensity)) mChoreographer.setDisplayTopology( DisplayTopologyGraph::create(primaryDisplayId, std::move(topologyGraph), std::move(displaysDensity), std::move(absoluteDisplayBoundsDp)) .value()); } }; Loading Loading
include/input/DisplayTopologyGraph.h +6 −2 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ #include <android-base/result.h> #include <ftl/enum.h> #include <ui/FloatRect.h> #include <ui/LogicalDisplayId.h> #include <cinttypes> Loading Loading @@ -58,6 +59,7 @@ struct DisplayTopologyGraph { ui::LogicalDisplayId primaryDisplayId = ui::LogicalDisplayId::INVALID; std::unordered_map<ui::LogicalDisplayId, std::vector<DisplayTopologyAdjacentDisplay>> graph; std::unordered_map<ui::LogicalDisplayId, int> displaysDensity; std::unordered_map<ui::LogicalDisplayId, FloatRect> boundsInGlobalDp; DisplayTopologyGraph() = default; std::string dump() const; Loading @@ -68,14 +70,16 @@ struct DisplayTopologyGraph { ui::LogicalDisplayId primaryDisplay, std::unordered_map<ui::LogicalDisplayId, std::vector<DisplayTopologyAdjacentDisplay>>&& adjacencyGraph, std::unordered_map<ui::LogicalDisplayId, int>&& displaysDensityMap); std::unordered_map<ui::LogicalDisplayId, int>&& displaysDensityMap, std::unordered_map<ui::LogicalDisplayId, FloatRect>&& boundsInGlobalDpMap); private: DisplayTopologyGraph( ui::LogicalDisplayId primaryDisplay, std::unordered_map<ui::LogicalDisplayId, std::vector<DisplayTopologyAdjacentDisplay>>&& adjacencyGraph, std::unordered_map<ui::LogicalDisplayId, int>&& displaysDensityMap); std::unordered_map<ui::LogicalDisplayId, int>&& displaysDensityMap, std::unordered_map<ui::LogicalDisplayId, FloatRect>&& boundsInGlobalDp); }; } // namespace android
libs/input/DisplayTopologyGraph.cpp +23 −7 Original line number Diff line number Diff line Loading @@ -121,6 +121,13 @@ std::string adjacentDisplayVectorToString( return dumpVector(adjacentDisplays, adjacentDisplayToString); } std::string floatRectToString(const FloatRect& floatRect) { std::string dump; dump += base::StringPrintf("FloatRect(%f, %f, %f, %f)", floatRect.left, floatRect.top, floatRect.right, floatRect.bottom); return dump; } bool areTopologyGraphComponentsValid( ui::LogicalDisplayId primaryDisplayId, const std::unordered_map<ui::LogicalDisplayId, std::vector<DisplayTopologyAdjacentDisplay>>& Loading @@ -137,7 +144,8 @@ std::string dumpTopologyGraphComponents( ui::LogicalDisplayId primaryDisplayId, const std::unordered_map<ui::LogicalDisplayId, std::vector<DisplayTopologyAdjacentDisplay>>& graph, const std::unordered_map<ui::LogicalDisplayId, int>& displaysDensity) { const std::unordered_map<ui::LogicalDisplayId, int>& displaysDensity, const std::unordered_map<ui::LogicalDisplayId, FloatRect> boundsInGlobalDp) { std::string dump; dump += base::StringPrintf("PrimaryDisplayId: %d\n", primaryDisplayId.val()); dump += base::StringPrintf("TopologyGraph:\n"); Loading @@ -147,6 +155,10 @@ std::string dumpTopologyGraphComponents( dump += base::StringPrintf("DisplaysDensity:\n"); dump += addLinePrefix(dumpMap(displaysDensity, logicalDisplayIdToString), INDENT); dump += "\n"; dump += base::StringPrintf("DisplaysBoundsInGlobalDp:\n"); dump += addLinePrefix(dumpMap(boundsInGlobalDp, logicalDisplayIdToString, floatRectToString), INDENT); return dump; } Loading @@ -164,27 +176,31 @@ DisplayTopologyGraph::DisplayTopologyGraph( ui::LogicalDisplayId primaryDisplay, std::unordered_map<ui::LogicalDisplayId, std::vector<DisplayTopologyAdjacentDisplay>>&& adjacencyGraph, std::unordered_map<ui::LogicalDisplayId, int>&& displaysDensityMap) std::unordered_map<ui::LogicalDisplayId, int>&& displaysDensityMap, std::unordered_map<ui::LogicalDisplayId, FloatRect>&& boundsInGlobalDpMap) : primaryDisplayId(primaryDisplay), graph(std::move(adjacencyGraph)), displaysDensity(std::move(displaysDensityMap)) {} displaysDensity(std::move(displaysDensityMap)), boundsInGlobalDp(std::move(boundsInGlobalDpMap)) {} std::string DisplayTopologyGraph::dump() const { return dumpTopologyGraphComponents(primaryDisplayId, graph, displaysDensity); return dumpTopologyGraphComponents(primaryDisplayId, graph, displaysDensity, boundsInGlobalDp); } base::Result<const DisplayTopologyGraph> DisplayTopologyGraph::create( ui::LogicalDisplayId primaryDisplay, std::unordered_map<ui::LogicalDisplayId, std::vector<DisplayTopologyAdjacentDisplay>>&& adjacencyGraph, std::unordered_map<ui::LogicalDisplayId, int>&& displaysDensityMap) { std::unordered_map<ui::LogicalDisplayId, int>&& displaysDensityMap, std::unordered_map<ui::LogicalDisplayId, FloatRect>&& boundsInGlobalDp) { // Todo(b/401220484): add validation for display bounds if (areTopologyGraphComponentsValid(primaryDisplay, adjacencyGraph, displaysDensityMap)) { return DisplayTopologyGraph(primaryDisplay, std::move(adjacencyGraph), std::move(displaysDensityMap)); std::move(displaysDensityMap), std::move(boundsInGlobalDp)); } return base::Error() << "Invalid display topology components: " << dumpTopologyGraphComponents(primaryDisplay, adjacencyGraph, displaysDensityMap); displaysDensityMap, boundsInGlobalDp); } } // namespace android
services/inputflinger/tests/DisplayTopologyGraph_test.cpp +2 −1 Original line number Diff line number Diff line Loading @@ -50,7 +50,8 @@ TEST_P(DisplayTopologyGraphTestFixture, DisplayTopologyGraphTest) { SCOPED_FLAG_OVERRIDE(enable_display_topology_validation, true); auto [_, primaryDisplayId, graph, displaysDensity, isValid] = GetParam(); auto result = DisplayTopologyGraph::create(primaryDisplayId, std::move(graph), std::move(displaysDensity)); std::move(displaysDensity), /*boundsInGlobalDpMap=*/{}); EXPECT_EQ(isValid, result.ok()); } Loading
services/inputflinger/tests/InputDispatcher_test.cpp +4 −1 Original line number Diff line number Diff line Loading @@ -15501,7 +15501,10 @@ protected: {{DISPLAY_ID, DisplayTopologyPosition::BOTTOM, 0.0f}}}}, /*displaysDensity=*/ {{DISPLAY_ID, DENSITY_MEDIUM}, {SECOND_DISPLAY_ID, DENSITY_MEDIUM}}) {SECOND_DISPLAY_ID, DENSITY_MEDIUM}}, /*absoluteDisplayBoundsDp=*/ {{DISPLAY_ID, FloatRect(0, -500, 500, 0)}, {SECOND_DISPLAY_ID, FloatRect(0, 0, 500, 5000)}}) .value(); void SetUp() override {
services/inputflinger/tests/PointerChoreographer_test.cpp +28 −8 Original line number Diff line number Diff line Loading @@ -153,7 +153,9 @@ protected: mChoreographer.setDisplayTopology( DisplayTopologyGraph::create(/*primaryDisplayId=*/displayId, /*adjacencyGraph=*/{}, /*displaysDensity=*/{{displayId, DENSITY_MEDIUM}}) /*displaysDensity=*/{{displayId, DENSITY_MEDIUM}}, /*absoluteDisplayBoundsDp=*/ {{displayId, FloatRect(0, 0, 500, 500)}}) .value()); } else { mChoreographer.setDefaultMouseDisplayId(displayId); Loading Loading @@ -2820,7 +2822,8 @@ protected: {DISPLAY_BOTTOM_ID, DENSITY_MEDIUM}, {DISPLAY_LEFT_ID, DENSITY_MEDIUM}, {DISPLAY_TOP_RIGHT_CORNER_ID, DENSITY_MEDIUM}, {DISPLAY_HIGH_DENSITY_ID, DENSITY_HIGH}}) {DISPLAY_HIGH_DENSITY_ID, DENSITY_HIGH}}, /*absoluteDisplayBoundsDp=*/{}) .value(); }; Loading Loading @@ -2960,10 +2963,12 @@ protected: static constexpr ui::LogicalDisplayId FIRST_DISPLAY_ID = ui::LogicalDisplayId{10}; static constexpr ui::LogicalDisplayId SECOND_DISPLAY_ID = ui::LogicalDisplayId{20}; static constexpr ui::LogicalDisplayId THIRD_DISPLAY_ID = ui::LogicalDisplayId{30}; static constexpr int32_t DISPLAY_WIDTH = 100; static constexpr int32_t DISPLAY_HEIGHT = 100; DisplayViewport createViewport(ui::LogicalDisplayId displayId) { return PointerChoreographerDisplayTopologyTests::createViewport(displayId, /*width=*/100, /*height=*/100, return PointerChoreographerDisplayTopologyTests::createViewport(displayId, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0); } Loading @@ -2979,6 +2984,11 @@ protected: std::unordered_map<ui::LogicalDisplayId, int> displaysDensity; displaysDensity[primaryDisplayId] = DENSITY_MEDIUM; std::unordered_map<ui::LogicalDisplayId, FloatRect> absoluteDisplayBoundsDp; absoluteDisplayBoundsDp.emplace(std::piecewise_construct, std::forward_as_tuple(primaryDisplayId), std::forward_as_tuple(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT)); for (ui::LogicalDisplayId adjacentDisplayId : adjacentDisplays) { topologyGraph[previousDisplay].push_back({.displayId = adjacentDisplayId, .position = DisplayTopologyPosition::RIGHT, Loading @@ -2988,12 +2998,22 @@ protected: .offsetDp = 0.0f}); displaysDensity[adjacentDisplayId] = DENSITY_MEDIUM; const auto& previousDisplayBounds = absoluteDisplayBoundsDp[previousDisplay]; absoluteDisplayBoundsDp.emplace(std::piecewise_construct, std::forward_as_tuple(adjacentDisplayId), std::forward_as_tuple(previousDisplayBounds.right, 0, previousDisplayBounds.right + DISPLAY_WIDTH, DISPLAY_HEIGHT)); previousDisplay = adjacentDisplayId; } mChoreographer.setDisplayTopology(DisplayTopologyGraph::create(primaryDisplayId, std::move(topologyGraph), std::move(displaysDensity)) mChoreographer.setDisplayTopology( DisplayTopologyGraph::create(primaryDisplayId, std::move(topologyGraph), std::move(displaysDensity), std::move(absoluteDisplayBoundsDp)) .value()); } }; Loading