Get mouse cursor position from PointerController instead of WM

PointerController is the source of truth of the mouse cursor position.
When the VirtualDevice APIs queried the cursor position, we were
previously getting the position from WM. WM's values only update once
system_server's global monitor has processed the input event, which
leads us into a race condition.

Remove the race consition by querying the mouse cursor position directly
from PointerController.

Bug: 266687189
Test: atest VirtualMouseTest
Change-Id: Id0e0e20a0d547f969d3a27d43fdfdca34d0fa7c0
diff --git a/libs/input/PointerController.cpp b/libs/input/PointerController.cpp
index fedf58d..e748c69 100644
--- a/libs/input/PointerController.cpp
+++ b/libs/input/PointerController.cpp
@@ -262,19 +262,34 @@
 }
 
 void PointerController::setDisplayViewport(const DisplayViewport& viewport) {
-    std::scoped_lock lock(getLock());
+    struct PointerDisplayChangeArgs {
+        int32_t displayId;
+        float x, y;
+    };
+    std::optional<PointerDisplayChangeArgs> pointerDisplayChanged;
 
-    bool getAdditionalMouseResources = false;
-    if (mLocked.presentation == PointerController::Presentation::POINTER ||
-        mLocked.presentation == PointerController::Presentation::STYLUS_HOVER) {
-        getAdditionalMouseResources = true;
-    }
-    mCursorController.setDisplayViewport(viewport, getAdditionalMouseResources);
-    if (viewport.displayId != mLocked.pointerDisplayId) {
-        float xPos, yPos;
-        mCursorController.getPosition(&xPos, &yPos);
-        mContext.getPolicy()->onPointerDisplayIdChanged(viewport.displayId, xPos, yPos);
-        mLocked.pointerDisplayId = viewport.displayId;
+    { // acquire lock
+        std::scoped_lock lock(getLock());
+
+        bool getAdditionalMouseResources = false;
+        if (mLocked.presentation == PointerController::Presentation::POINTER ||
+            mLocked.presentation == PointerController::Presentation::STYLUS_HOVER) {
+            getAdditionalMouseResources = true;
+        }
+        mCursorController.setDisplayViewport(viewport, getAdditionalMouseResources);
+        if (viewport.displayId != mLocked.pointerDisplayId) {
+            float xPos, yPos;
+            mCursorController.getPosition(&xPos, &yPos);
+            mLocked.pointerDisplayId = viewport.displayId;
+            pointerDisplayChanged = {viewport.displayId, xPos, yPos};
+        }
+    } // release lock
+
+    if (pointerDisplayChanged) {
+        // Notify the policy without holding the pointer controller lock.
+        mContext.getPolicy()->onPointerDisplayIdChanged(pointerDisplayChanged->displayId,
+                                                        pointerDisplayChanged->x,
+                                                        pointerDisplayChanged->y);
     }
 }