Pointer icon refactor for touchpad

With PointerChoreographer enabled, touchpads work similar to mice,
using MousePointerController of the associated display.
For some gestures like scroll or multi-finger swipes,
TouchpadInputMapper sets fake finger coordinates and
PointerChoreographer combines cursor position with them.

Test: atest inputflinger_tests
Bug: 293587049
Change-Id: I0f6588c79004284df98d99351ea3c3e64b636a74
diff --git a/services/inputflinger/reader/mapper/CursorInputMapper.cpp b/services/inputflinger/reader/mapper/CursorInputMapper.cpp
index 7aeb215..58e35a6 100644
--- a/services/inputflinger/reader/mapper/CursorInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/CursorInputMapper.cpp
@@ -527,10 +527,8 @@
         if (mEnablePointerChoreographer) {
             // Always use DISPLAY_ID_NONE for mouse events.
             // PointerChoreographer will make it target the correct the displayId later.
-            const auto pointerViewport =
-                    getContext()->getPolicy()->getPointerViewportForAssociatedDisplay();
-            mDisplayId = pointerViewport ? std::make_optional(ADISPLAY_ID_NONE) : std::nullopt;
-            resolvedViewport = pointerViewport;
+            resolvedViewport = getContext()->getPolicy()->getPointerViewportForAssociatedDisplay();
+            mDisplayId = resolvedViewport ? std::make_optional(ADISPLAY_ID_NONE) : std::nullopt;
         } else {
             mDisplayId = mPointerController->getDisplayId();
             if (auto v = config.getDisplayViewportById(*mDisplayId); v) {
diff --git a/services/inputflinger/reader/mapper/TouchpadInputMapper.cpp b/services/inputflinger/reader/mapper/TouchpadInputMapper.cpp
index c76fec7..34ca0b3 100644
--- a/services/inputflinger/reader/mapper/TouchpadInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/TouchpadInputMapper.cpp
@@ -246,7 +246,8 @@
         mStateConverter(deviceContext, mMotionAccumulator),
         mGestureConverter(*getContext(), deviceContext, getDeviceId()),
         mCapturedEventConverter(*getContext(), deviceContext, mMotionAccumulator, getDeviceId()),
-        mMetricsId(metricsIdFromInputDeviceIdentifier(deviceContext.getDeviceIdentifier())) {
+        mMetricsId(metricsIdFromInputDeviceIdentifier(deviceContext.getDeviceIdentifier())),
+        mEnablePointerChoreographer(input_flags::enable_pointer_choreographer()) {
     RawAbsoluteAxisInfo slotAxisInfo;
     deviceContext.getAbsoluteAxisInfo(ABS_MT_SLOT, &slotAxisInfo);
     if (!slotAxisInfo.valid || slotAxisInfo.maxValue <= 0) {
@@ -331,31 +332,56 @@
 
     if (!changes.any() || changes.test(InputReaderConfiguration::Change::DISPLAY_INFO)) {
         mDisplayId = ADISPLAY_ID_NONE;
-        if (auto viewport = mDeviceContext.getAssociatedViewport(); viewport) {
+        std::optional<DisplayViewport> resolvedViewport;
+        std::optional<FloatRect> boundsInLogicalDisplay;
+        if (auto assocViewport = mDeviceContext.getAssociatedViewport(); assocViewport) {
             // This InputDevice is associated with a viewport.
             // Only generate events for the associated display.
-            const bool mismatchedPointerDisplay =
-                    (viewport->displayId != mPointerController->getDisplayId());
-            if (mismatchedPointerDisplay) {
-                ALOGW("Touchpad \"%s\" associated viewport display does not match pointer "
-                      "controller",
-                      mDeviceContext.getName().c_str());
+            mDisplayId = assocViewport->displayId;
+            resolvedViewport = *assocViewport;
+            if (!mEnablePointerChoreographer) {
+                const bool mismatchedPointerDisplay =
+                        (assocViewport->displayId != mPointerController->getDisplayId());
+                if (mismatchedPointerDisplay) {
+                    ALOGW("Touchpad \"%s\" associated viewport display does not match pointer "
+                          "controller",
+                          mDeviceContext.getName().c_str());
+                    mDisplayId.reset();
+                }
             }
-            mDisplayId = mismatchedPointerDisplay ? std::nullopt
-                                                  : std::make_optional(viewport->displayId);
         } else {
             // The InputDevice is not associated with a viewport, but it controls the mouse pointer.
-            mDisplayId = mPointerController->getDisplayId();
-        }
-
-        ui::Rotation orientation = ui::ROTATION_0;
-        if (mDisplayId.has_value()) {
-            if (auto viewport = config.getDisplayViewportById(*mDisplayId); viewport) {
-                orientation = getInverseRotation(viewport->orientation);
+            if (mEnablePointerChoreographer) {
+                // Always use DISPLAY_ID_NONE for touchpad events.
+                // PointerChoreographer will make it target the correct the displayId later.
+                resolvedViewport =
+                        getContext()->getPolicy()->getPointerViewportForAssociatedDisplay();
+                mDisplayId = resolvedViewport ? std::make_optional(ADISPLAY_ID_NONE) : std::nullopt;
+            } else {
+                mDisplayId = mPointerController->getDisplayId();
+                if (auto v = config.getDisplayViewportById(*mDisplayId); v) {
+                    resolvedViewport = *v;
+                }
+                if (auto bounds = mPointerController->getBounds(); bounds) {
+                    boundsInLogicalDisplay = *bounds;
+                }
             }
         }
+
         mGestureConverter.setDisplayId(mDisplayId);
-        mGestureConverter.setOrientation(orientation);
+        mGestureConverter.setOrientation(resolvedViewport
+                                                 ? getInverseRotation(resolvedViewport->orientation)
+                                                 : ui::ROTATION_0);
+
+        if (!boundsInLogicalDisplay) {
+            boundsInLogicalDisplay = resolvedViewport
+                    ? FloatRect{static_cast<float>(resolvedViewport->logicalLeft),
+                                static_cast<float>(resolvedViewport->logicalTop),
+                                static_cast<float>(resolvedViewport->logicalRight - 1),
+                                static_cast<float>(resolvedViewport->logicalBottom - 1)}
+                    : FloatRect{0, 0, 0, 0};
+        }
+        mGestureConverter.setBoundsInLogicalDisplay(*boundsInLogicalDisplay);
     }
     if (!changes.any() || changes.test(InputReaderConfiguration::Change::TOUCHPAD_SETTINGS)) {
         mPropertyProvider.getProperty("Use Custom Touchpad Pointer Accel Curve")
diff --git a/services/inputflinger/reader/mapper/TouchpadInputMapper.h b/services/inputflinger/reader/mapper/TouchpadInputMapper.h
index a68ae43..ece0eca 100644
--- a/services/inputflinger/reader/mapper/TouchpadInputMapper.h
+++ b/services/inputflinger/reader/mapper/TouchpadInputMapper.h
@@ -107,6 +107,8 @@
     // Tracking IDs for touches that have at some point been reported as palms by the touchpad.
     std::set<int32_t> mPalmTrackingIds;
 
+    const bool mEnablePointerChoreographer;
+
     // The display that events generated by this mapper should target. This can be set to
     // ADISPLAY_ID_NONE to target the focused display. If there is no display target (i.e.
     // std::nullopt), all events will be ignored.
diff --git a/services/inputflinger/reader/mapper/gestures/GestureConverter.cpp b/services/inputflinger/reader/mapper/gestures/GestureConverter.cpp
index 4d2b66d..9552104 100644
--- a/services/inputflinger/reader/mapper/gestures/GestureConverter.cpp
+++ b/services/inputflinger/reader/mapper/gestures/GestureConverter.cpp
@@ -60,7 +60,8 @@
                                    const InputDeviceContext& deviceContext, int32_t deviceId)
       : mDeviceId(deviceId),
         mReaderContext(readerContext),
-        mPointerController(readerContext.getPointerController(deviceId)) {
+        mPointerController(readerContext.getPointerController(deviceId)),
+        mEnablePointerChoreographer(input_flags::enable_pointer_choreographer()) {
     deviceContext.getAbsoluteAxisInfo(ABS_MT_POSITION_X, &mXAxisInfo);
     deviceContext.getAbsoluteAxisInfo(ABS_MT_POSITION_Y, &mYAxisInfo);
 }
@@ -110,9 +111,11 @@
 
     // TODO(b/259547750): set this using the raw axis ranges from the touchpad when pointer capture
     // is enabled.
-    if (std::optional<FloatRect> rect = mPointerController->getBounds(); rect.has_value()) {
-        info.addMotionRange(AMOTION_EVENT_AXIS_X, SOURCE, rect->left, rect->right, 0, 0, 0);
-        info.addMotionRange(AMOTION_EVENT_AXIS_Y, SOURCE, rect->top, rect->bottom, 0, 0, 0);
+    if (!mBoundsInLogicalDisplay.isEmpty()) {
+        info.addMotionRange(AMOTION_EVENT_AXIS_X, SOURCE, mBoundsInLogicalDisplay.left,
+                            mBoundsInLogicalDisplay.right, 0, 0, 0);
+        info.addMotionRange(AMOTION_EVENT_AXIS_Y, SOURCE, mBoundsInLogicalDisplay.top,
+                            mBoundsInLogicalDisplay.bottom, 0, 0, 0);
     }
 
     info.addMotionRange(AMOTION_EVENT_AXIS_GESTURE_X_OFFSET, SOURCE, -1.0f, 1.0f, 0, 0, 0);
@@ -172,7 +175,8 @@
     mPointerController->move(deltaX, deltaY);
     mPointerController->unfade(PointerControllerInterface::Transition::IMMEDIATE);
 
-    const auto [xCursorPosition, yCursorPosition] = mPointerController->getPosition();
+    const auto [xCursorPosition, yCursorPosition] =
+            mEnablePointerChoreographer ? FloatPoint{0, 0} : mPointerController->getPosition();
 
     PointerCoords coords;
     coords.clear();
@@ -196,7 +200,8 @@
     mPointerController->setPresentation(PointerControllerInterface::Presentation::POINTER);
     mPointerController->unfade(PointerControllerInterface::Transition::IMMEDIATE);
 
-    const auto [xCursorPosition, yCursorPosition] = mPointerController->getPosition();
+    const auto [xCursorPosition, yCursorPosition] =
+            mEnablePointerChoreographer ? FloatPoint{0, 0} : mPointerController->getPosition();
 
     PointerCoords coords;
     coords.clear();
@@ -273,7 +278,8 @@
 
 std::list<NotifyArgs> GestureConverter::releaseAllButtons(nsecs_t when, nsecs_t readTime) {
     std::list<NotifyArgs> out;
-    const auto [xCursorPosition, yCursorPosition] = mPointerController->getPosition();
+    const auto [xCursorPosition, yCursorPosition] =
+            mEnablePointerChoreographer ? FloatPoint{0, 0} : mPointerController->getPosition();
 
     PointerCoords coords;
     coords.clear();
@@ -308,7 +314,8 @@
                                                      const Gesture& gesture) {
     std::list<NotifyArgs> out;
     PointerCoords& coords = mFakeFingerCoords[0];
-    const auto [xCursorPosition, yCursorPosition] = mPointerController->getPosition();
+    const auto [xCursorPosition, yCursorPosition] =
+            mEnablePointerChoreographer ? FloatPoint{0, 0} : mPointerController->getPosition();
     if (mCurrentClassification != MotionClassification::TWO_FINGER_SWIPE) {
         mCurrentClassification = MotionClassification::TWO_FINGER_SWIPE;
         coords.setAxisValue(AMOTION_EVENT_AXIS_X, xCursorPosition);
@@ -376,7 +383,8 @@
 }
 
 NotifyMotionArgs GestureConverter::endScroll(nsecs_t when, nsecs_t readTime) {
-    const auto [xCursorPosition, yCursorPosition] = mPointerController->getPosition();
+    const auto [xCursorPosition, yCursorPosition] =
+            mEnablePointerChoreographer ? FloatPoint{0, 0} : mPointerController->getPosition();
     mFakeFingerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_GESTURE_SCROLL_X_DISTANCE, 0);
     mFakeFingerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_GESTURE_SCROLL_Y_DISTANCE, 0);
     NotifyMotionArgs args =
@@ -394,7 +402,8 @@
                                                                              float dx, float dy) {
     std::list<NotifyArgs> out = {};
 
-    const auto [xCursorPosition, yCursorPosition] = mPointerController->getPosition();
+    const auto [xCursorPosition, yCursorPosition] =
+            mEnablePointerChoreographer ? FloatPoint{0, 0} : mPointerController->getPosition();
     if (mCurrentClassification != MotionClassification::MULTI_FINGER_SWIPE) {
         // If the user changes the number of fingers mid-way through a swipe (e.g. they start with
         // three and then put a fourth finger down), the gesture library will treat it as two
@@ -457,7 +466,8 @@
     if (mCurrentClassification != MotionClassification::MULTI_FINGER_SWIPE) {
         return out;
     }
-    const auto [xCursorPosition, yCursorPosition] = mPointerController->getPosition();
+    const auto [xCursorPosition, yCursorPosition] =
+            mEnablePointerChoreographer ? FloatPoint{0, 0} : mPointerController->getPosition();
     mFakeFingerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_GESTURE_X_OFFSET, 0);
     mFakeFingerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_GESTURE_Y_OFFSET, 0);
 
@@ -481,7 +491,8 @@
 
 [[nodiscard]] std::list<NotifyArgs> GestureConverter::handlePinch(nsecs_t when, nsecs_t readTime,
                                                                   const Gesture& gesture) {
-    const auto [xCursorPosition, yCursorPosition] = mPointerController->getPosition();
+    const auto [xCursorPosition, yCursorPosition] =
+            mEnablePointerChoreographer ? FloatPoint{0, 0} : mPointerController->getPosition();
 
     // Pinch gesture phases are reported a little differently from others, in that the same details
     // struct is used for all phases of the gesture, just with different zoom_state values. When
@@ -538,7 +549,8 @@
 
 std::list<NotifyArgs> GestureConverter::endPinch(nsecs_t when, nsecs_t readTime) {
     std::list<NotifyArgs> out;
-    const auto [xCursorPosition, yCursorPosition] = mPointerController->getPosition();
+    const auto [xCursorPosition, yCursorPosition] =
+            mEnablePointerChoreographer ? FloatPoint{0, 0} : mPointerController->getPosition();
 
     mFakeFingerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_GESTURE_PINCH_SCALE_FACTOR, 1.0);
     out.push_back(makeMotionArgs(when, readTime,
diff --git a/services/inputflinger/reader/mapper/gestures/GestureConverter.h b/services/inputflinger/reader/mapper/gestures/GestureConverter.h
index e6cf617..732a4b2 100644
--- a/services/inputflinger/reader/mapper/gestures/GestureConverter.h
+++ b/services/inputflinger/reader/mapper/gestures/GestureConverter.h
@@ -48,6 +48,8 @@
 
     void setDisplayId(std::optional<int32_t> displayId) { mDisplayId = displayId; }
 
+    void setBoundsInLogicalDisplay(FloatRect bounds) { mBoundsInLogicalDisplay = bounds; }
+
     void populateMotionRanges(InputDeviceInfo& info) const;
 
     [[nodiscard]] std::list<NotifyArgs> handleGesture(nsecs_t when, nsecs_t readTime,
@@ -85,8 +87,10 @@
     const int32_t mDeviceId;
     InputReaderContext& mReaderContext;
     std::shared_ptr<PointerControllerInterface> mPointerController;
+    const bool mEnablePointerChoreographer;
 
     std::optional<int32_t> mDisplayId;
+    FloatRect mBoundsInLogicalDisplay{};
     ui::Rotation mOrientation = ui::ROTATION_0;
     RawAbsoluteAxisInfo mXAxisInfo;
     RawAbsoluteAxisInfo mYAxisInfo;