Remove temporary DisplayTopology types

This CL removes and replaces temporary DisplayTopology related struct
and enums.

Test: atest inputflinger_tests
Bug: 367659738
Bug: 367660694
Flag: com.android.input.flags.connected_displays_cursor
Change-Id: I5ca250b762832b35167ea9991a5ce4b00177ae84
diff --git a/services/inputflinger/PointerChoreographer.cpp b/services/inputflinger/PointerChoreographer.cpp
index 811692f..5bf6ebb 100644
--- a/services/inputflinger/PointerChoreographer.cpp
+++ b/services/inputflinger/PointerChoreographer.cpp
@@ -98,6 +98,22 @@
     return privacySensitiveDisplays;
 }
 
+vec2 calculatePositionOnDestinationViewport(const DisplayViewport& destinationViewport,
+                                            float pointerOffset,
+                                            DisplayTopologyPosition sourceBoundary) {
+    // destination is opposite of the source boundary
+    switch (sourceBoundary) {
+        case DisplayTopologyPosition::RIGHT:
+            return {0, pointerOffset}; // left edge
+        case DisplayTopologyPosition::TOP:
+            return {pointerOffset, destinationViewport.logicalBottom}; // bottom edge
+        case DisplayTopologyPosition::LEFT:
+            return {destinationViewport.logicalRight, pointerOffset}; // right edge
+        case DisplayTopologyPosition::BOTTOM:
+            return {pointerOffset, 0}; // top edge
+    }
+}
+
 } // namespace
 
 // --- PointerChoreographer ---
@@ -327,19 +343,19 @@
     // except sometimes near the corners.
     // In these cases this behaviour is not noticeable. We also do not apply unconsumed delta on
     // the destination display for the same reason.
-    DisplayPosition sourceBoundary;
+    DisplayTopologyPosition sourceBoundary;
     float cursorOffset = 0.0f;
     if (rotatedUnconsumedDelta.x > 0) {
-        sourceBoundary = DisplayPosition::RIGHT;
+        sourceBoundary = DisplayTopologyPosition::RIGHT;
         cursorOffset = rotatedCursorPosition.y;
     } else if (rotatedUnconsumedDelta.x < 0) {
-        sourceBoundary = DisplayPosition::LEFT;
+        sourceBoundary = DisplayTopologyPosition::LEFT;
         cursorOffset = rotatedCursorPosition.y;
     } else if (rotatedUnconsumedDelta.y > 0) {
-        sourceBoundary = DisplayPosition::BOTTOM;
+        sourceBoundary = DisplayTopologyPosition::BOTTOM;
         cursorOffset = rotatedCursorPosition.x;
     } else {
-        sourceBoundary = DisplayPosition::TOP;
+        sourceBoundary = DisplayTopologyPosition::TOP;
         cursorOffset = rotatedCursorPosition.x;
     }
 
@@ -369,8 +385,9 @@
     pc.fade(PointerControllerInterface::Transition::IMMEDIATE);
     pc.setDisplayViewport(destinationViewport);
     vec2 destinationPosition =
-            calculateDestinationPosition(destinationViewport, cursorOffset - destinationOffset,
-                                         sourceBoundary);
+            calculatePositionOnDestinationViewport(destinationViewport,
+                                                   cursorOffset - destinationOffset,
+                                                   sourceBoundary);
 
     // Transform position back to un-rotated coordinate space before sending it to controller
     destinationPosition = pc.getDisplayTransform().inverse().transform(destinationPosition.x,
@@ -379,22 +396,6 @@
     pc.unfade(PointerControllerInterface::Transition::IMMEDIATE);
 }
 
-vec2 PointerChoreographer::calculateDestinationPosition(const DisplayViewport& destinationViewport,
-                                                        float pointerOffset,
-                                                        DisplayPosition sourceBoundary) {
-    // destination is opposite of the source boundary
-    switch (sourceBoundary) {
-        case DisplayPosition::RIGHT:
-            return {0, pointerOffset}; // left edge
-        case DisplayPosition::TOP:
-            return {pointerOffset, destinationViewport.logicalBottom}; // bottom edge
-        case DisplayPosition::LEFT:
-            return {destinationViewport.logicalRight, pointerOffset}; // right edge
-        case DisplayPosition::BOTTOM:
-            return {pointerOffset, 0}; // top edge
-    }
-}
-
 void PointerChoreographer::processDrawingTabletEventLocked(const android::NotifyMotionArgs& args) {
     if (args.displayId == ui::LogicalDisplayId::INVALID) {
         return;
@@ -540,8 +541,7 @@
 }
 
 void PointerChoreographer::onControllerAddedOrRemovedLocked() {
-    if (!com::android::input::flags::hide_pointer_indicators_for_secure_windows() &&
-        !com::android::input::flags::connected_displays_cursor()) {
+    if (!com::android::input::flags::hide_pointer_indicators_for_secure_windows()) {
         return;
     }
     bool requireListener = !mTouchPointersByDevice.empty() || !mMousePointersByDisplay.empty() ||
@@ -607,11 +607,16 @@
     mNextListener.notify(args);
 }
 
-void PointerChoreographer::setDisplayTopology(
-        const std::unordered_map<ui::LogicalDisplayId, std::vector<AdjacentDisplay>>&
-                displayTopology) {
+void PointerChoreographer::setDisplayTopology(const DisplayTopologyGraph& displayTopologyGraph) {
     std::scoped_lock _l(getLock());
-    mTopology = displayTopology;
+    mTopology = displayTopologyGraph;
+
+    // make primary display default mouse display, if it was not set
+    // or the existing display was removed
+    if (mDefaultMouseDisplayId == ui::LogicalDisplayId::INVALID ||
+        mTopology.graph.find(mDefaultMouseDisplayId) != mTopology.graph.end()) {
+        mDefaultMouseDisplayId = mTopology.primaryDisplayId;
+    }
 }
 
 void PointerChoreographer::dump(std::string& dump) {
@@ -985,73 +990,17 @@
     return ConstructorDelegate(std::move(ctor));
 }
 
-void PointerChoreographer::populateFakeDisplayTopologyLocked(
-        const std::vector<gui::DisplayInfo>& displayInfos) {
-    if (!com::android::input::flags::connected_displays_cursor()) {
-        return;
-    }
-
-    if (displayInfos.size() == mTopology.size()) {
-        bool displaysChanged = false;
-        for (const auto& displayInfo : displayInfos) {
-            if (mTopology.find(displayInfo.displayId) == mTopology.end()) {
-                displaysChanged = true;
-                break;
-            }
-        }
-
-        if (!displaysChanged) {
-            return;
-        }
-    }
-
-    // create a fake topology assuming following order
-    // default-display (top-edge) -> next-display (right-edge) -> next-display (right-edge) ...
-    // This also adds a 100px offset on corresponding edge for better manual testing
-    //   ┌────────┐
-    //   │ next   ├─────────┐
-    // ┌─└───────┐┤ next 2  │ ...
-    // │ default │└─────────┘
-    // └─────────┘
-    mTopology.clear();
-
-    // treat default display as base, in real topology it should be the primary-display
-    ui::LogicalDisplayId previousDisplay = ui::LogicalDisplayId::DEFAULT;
-    for (const auto& displayInfo : displayInfos) {
-        if (displayInfo.displayId == ui::LogicalDisplayId::DEFAULT) {
-            continue;
-        }
-        if (previousDisplay == ui::LogicalDisplayId::DEFAULT) {
-            mTopology[previousDisplay].push_back(
-                    {displayInfo.displayId, DisplayPosition::TOP, 100});
-            mTopology[displayInfo.displayId].push_back(
-                    {previousDisplay, DisplayPosition::BOTTOM, -100});
-        } else {
-            mTopology[previousDisplay].push_back(
-                    {displayInfo.displayId, DisplayPosition::RIGHT, 100});
-            mTopology[displayInfo.displayId].push_back(
-                    {previousDisplay, DisplayPosition::LEFT, -100});
-        }
-        previousDisplay = displayInfo.displayId;
-    }
-
-    // update default pointer display. In real topology it should be the primary-display
-    if (mTopology.find(mDefaultMouseDisplayId) == mTopology.end()) {
-        mDefaultMouseDisplayId = ui::LogicalDisplayId::DEFAULT;
-    }
-}
-
 std::optional<std::pair<const DisplayViewport*, float /*offset*/>>
 PointerChoreographer::findDestinationDisplayLocked(const ui::LogicalDisplayId sourceDisplayId,
-                                                   const DisplayPosition sourceBoundary,
+                                                   const DisplayTopologyPosition sourceBoundary,
                                                    float cursorOffset) const {
-    const auto& sourceNode = mTopology.find(sourceDisplayId);
-    if (sourceNode == mTopology.end()) {
+    const auto& sourceNode = mTopology.graph.find(sourceDisplayId);
+    if (sourceNode == mTopology.graph.end()) {
         // Topology is likely out of sync with viewport info, wait for it to be updated
         LOG(WARNING) << "Source display missing from topology " << sourceDisplayId;
         return std::nullopt;
     }
-    for (const AdjacentDisplay& adjacentDisplay : sourceNode->second) {
+    for (const DisplayTopologyAdjacentDisplay& adjacentDisplay : sourceNode->second) {
         if (adjacentDisplay.position != sourceBoundary) {
             continue;
         }
@@ -1064,8 +1013,8 @@
             continue;
         }
         // target position must be within target display boundary
-        const int32_t edgeSize =
-                sourceBoundary == DisplayPosition::TOP || sourceBoundary == DisplayPosition::BOTTOM
+        const int32_t edgeSize = sourceBoundary == DisplayTopologyPosition::TOP ||
+                        sourceBoundary == DisplayTopologyPosition::BOTTOM
                 ? (destinationViewport->logicalRight - destinationViewport->logicalLeft)
                 : (destinationViewport->logicalBottom - destinationViewport->logicalTop);
         if (cursorOffset >= adjacentDisplay.offsetPx &&
@@ -1093,7 +1042,6 @@
         mPrivacySensitiveDisplays = std::move(newPrivacySensitiveDisplays);
         mPointerChoreographer->onPrivacySensitiveDisplaysChangedLocked(mPrivacySensitiveDisplays);
     }
-    mPointerChoreographer->populateFakeDisplayTopologyLocked(windowInfosUpdate.displayInfos);
 }
 
 void PointerChoreographer::PointerChoreographerDisplayInfoListener::setInitialDisplayInfosLocked(
diff --git a/services/inputflinger/PointerChoreographer.h b/services/inputflinger/PointerChoreographer.h
index 939529f..c2f5ec0 100644
--- a/services/inputflinger/PointerChoreographer.h
+++ b/services/inputflinger/PointerChoreographer.h
@@ -22,6 +22,7 @@
 
 #include <android-base/thread_annotations.h>
 #include <gui/WindowInfosListener.h>
+#include <input/DisplayTopologyGraph.h>
 #include <type_traits>
 #include <unordered_set>
 
@@ -80,6 +81,11 @@
      */
     virtual void setFocusedDisplay(ui::LogicalDisplayId displayId) = 0;
 
+    /*
+     * Used by InputManager to notify changes in the DisplayTopology
+     */
+    virtual void setDisplayTopology(const DisplayTopologyGraph& displayTopologyGraph) = 0;
+
     /**
      * This method may be called on any thread (usually by the input manager on a binder thread).
      */
@@ -103,6 +109,7 @@
                         ui::LogicalDisplayId displayId, DeviceId deviceId) override;
     void setPointerIconVisibility(ui::LogicalDisplayId displayId, bool visible) override;
     void setFocusedDisplay(ui::LogicalDisplayId displayId) override;
+    void setDisplayTopology(const DisplayTopologyGraph& displayTopologyGraph);
 
     void notifyInputDevicesChanged(const NotifyInputDevicesChangedArgs& args) override;
     void notifyKey(const NotifyKeyArgs& args) override;
@@ -113,24 +120,6 @@
     void notifyDeviceReset(const NotifyDeviceResetArgs& args) override;
     void notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs& args) override;
 
-    // TODO(b/362719483) remove these when real topology is available
-    enum class DisplayPosition {
-        RIGHT,
-        TOP,
-        LEFT,
-        BOTTOM,
-        ftl_last = BOTTOM,
-    };
-
-    struct AdjacentDisplay {
-        ui::LogicalDisplayId displayId;
-        DisplayPosition position;
-        float offsetPx;
-    };
-    void setDisplayTopology(
-            const std::unordered_map<ui::LogicalDisplayId, std::vector<AdjacentDisplay>>&
-                    displayTopology);
-
     void dump(std::string& dump) override;
 
 private:
@@ -174,18 +163,16 @@
     void handleUnconsumedDeltaLocked(PointerControllerInterface& pc, const vec2& unconsumedDelta)
             REQUIRES(getLock());
 
-    void populateFakeDisplayTopologyLocked(const std::vector<gui::DisplayInfo>& displayInfos)
+    std::optional<std::pair<const DisplayViewport*, float /*offset*/>> findDestinationDisplayLocked(
+            const ui::LogicalDisplayId sourceDisplayId,
+            const DisplayTopologyPosition sourceBoundary, float cursorOffset) const
             REQUIRES(getLock());
 
-    std::optional<std::pair<const DisplayViewport*, float /*offset*/>> findDestinationDisplayLocked(
-            const ui::LogicalDisplayId sourceDisplayId, const DisplayPosition sourceBoundary,
-            float cursorOffset) const REQUIRES(getLock());
-
-    static vec2 calculateDestinationPosition(const DisplayViewport& destinationViewport,
-                                             float pointerOffset, DisplayPosition sourceBoundary);
-
-    std::unordered_map<ui::LogicalDisplayId, std::vector<AdjacentDisplay>> mTopology
-            GUARDED_BY(getLock());
+    /* Topology is initialized with default-constructed value, which is an empty topology. Till we
+     * receive setDisplayTopology call.
+     * Meanwhile Choreographer will treat every display as independent disconnected display.
+     */
+    DisplayTopologyGraph mTopology GUARDED_BY(getLock());
 
     /* This listener keeps tracks of visible privacy sensitive displays and updates the
      * choreographer if there are any changes.
diff --git a/services/inputflinger/tests/PointerChoreographer_test.cpp b/services/inputflinger/tests/PointerChoreographer_test.cpp
index 27da3d3..1ca2998 100644
--- a/services/inputflinger/tests/PointerChoreographer_test.cpp
+++ b/services/inputflinger/tests/PointerChoreographer_test.cpp
@@ -2633,16 +2633,14 @@
                            ui::ROTATION_0),
     };
 
-    std::unordered_map<ui::LogicalDisplayId, std::vector<PointerChoreographer::AdjacentDisplay>>
-            mTopology{
-                    {DISPLAY_CENTER_ID,
-                     {{DISPLAY_TOP_ID, PointerChoreographer::DisplayPosition::TOP, 10.0f},
-                      {DISPLAY_RIGHT_ID, PointerChoreographer::DisplayPosition::RIGHT, 10.0f},
-                      {DISPLAY_BOTTOM_ID, PointerChoreographer::DisplayPosition::BOTTOM, 10.0f},
-                      {DISPLAY_LEFT_ID, PointerChoreographer::DisplayPosition::LEFT, 10.0f},
-                      {DISPLAY_TOP_RIGHT_CORNER_ID, PointerChoreographer::DisplayPosition::RIGHT,
-                       -90.0f}}},
-            };
+    DisplayTopologyGraph mTopology{DISPLAY_CENTER_ID,
+                                   {{DISPLAY_CENTER_ID,
+                                     {{DISPLAY_TOP_ID, DisplayTopologyPosition::TOP, 10.0f},
+                                      {DISPLAY_RIGHT_ID, DisplayTopologyPosition::RIGHT, 10.0f},
+                                      {DISPLAY_BOTTOM_ID, DisplayTopologyPosition::BOTTOM, 10.0f},
+                                      {DISPLAY_LEFT_ID, DisplayTopologyPosition::LEFT, 10.0f},
+                                      {DISPLAY_TOP_RIGHT_CORNER_ID, DisplayTopologyPosition::RIGHT,
+                                       -90.0f}}}}};
 
 private:
     DisplayViewport createViewport(ui::LogicalDisplayId displayId, int32_t width, int32_t height,
@@ -2706,6 +2704,11 @@
         testing::Values(
                 // Note: Upon viewport transition cursor will be positioned at the boundary of the
                 // destination, as we drop any unconsumed delta.
+                std::make_tuple("PrimaryDisplayIsDefault", AINPUT_SOURCE_MOUSE,
+                                ControllerType::MOUSE, ToolType::MOUSE,
+                                vec2(50, 50) /* initial x/y */, vec2(0, 0) /* delta x/y */,
+                                PointerChoreographerDisplayTopologyTestFixture::DISPLAY_CENTER_ID,
+                                vec2(50, 50) /* destination x/y */),
                 std::make_tuple("UnchangedDisplay", AINPUT_SOURCE_MOUSE, ControllerType::MOUSE,
                                 ToolType::MOUSE, vec2(50, 50) /* initial x/y */,
                                 vec2(25, 25) /* delta x/y */,