TouchInputMapper: Index input device pixels in rotated display space

Redo the way we calculate input transforms so that each discrete raw
pixel is indexed in the current display orientation. InputReader should
still be sending events in the unrotated display space.

See the following file for more information about improper indexing of
pixels when converting discrete coordinates into the continuous space:

//frameworks/native/services/inputflinger/docs/input_coordinates.md

Bug: 257118693
Test: atest inputflinger_tests
Change-Id: Id6633d3a58bada3a7ec03ccd5cfe71fbb719ea6a
diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.cpp b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
index 3ba6cd0..55373a8 100644
--- a/services/inputflinger/reader/mapper/TouchInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
@@ -838,38 +838,60 @@
 }
 
 void TouchInputMapper::computeInputTransforms() {
-    const ui::Size rawSize{mRawPointerAxes.getRawWidth(), mRawPointerAxes.getRawHeight()};
+    constexpr auto isRotated = [](const ui::Transform::RotationFlags& rotation) {
+        return rotation == ui::Transform::ROT_90 || rotation == ui::Transform::ROT_270;
+    };
 
-    ui::Size rotatedRawSize = rawSize;
-    if (mInputDeviceOrientation == ui::ROTATION_270 || mInputDeviceOrientation == ui::ROTATION_90) {
-        std::swap(rotatedRawSize.width, rotatedRawSize.height);
-    }
-    const auto rotationFlags = ui::Transform::toRotationFlags(-mInputDeviceOrientation);
-    mRawRotation = ui::Transform{rotationFlags};
+    // See notes about input coordinates in the inputflinger docs:
+    // //frameworks/native/services/inputflinger/docs/input_coordinates.md
 
     // Step 1: Undo the raw offset so that the raw coordinate space now starts at (0, 0).
-    ui::Transform undoRawOffset;
-    undoRawOffset.set(-mRawPointerAxes.x.minValue, -mRawPointerAxes.y.minValue);
+    ui::Transform undoOffsetInRaw;
+    undoOffsetInRaw.set(-mRawPointerAxes.x.minValue, -mRawPointerAxes.y.minValue);
 
-    // Step 2: Rotate the raw coordinates to the expected orientation.
-    ui::Transform rotate;
-    // When rotating raw coordinates, the raw size will be used as an offset.
-    // Account for the extra unit added to the raw range when the raw size was calculated.
-    rotate.set(rotationFlags, rotatedRawSize.width - 1, rotatedRawSize.height - 1);
+    // Step 2: Rotate the raw coordinates to account for input device orientation. The coordinates
+    // will now be in the same orientation as the display in ROTATION_0.
+    // Note: Negating an ui::Rotation value will give its inverse rotation.
+    const auto inputDeviceOrientation = ui::Transform::toRotationFlags(-mParameters.orientation);
+    const ui::Size orientedRawSize = isRotated(inputDeviceOrientation)
+            ? ui::Size{mRawPointerAxes.getRawHeight(), mRawPointerAxes.getRawWidth()}
+            : ui::Size{mRawPointerAxes.getRawWidth(), mRawPointerAxes.getRawHeight()};
+    // When rotating raw values, account for the extra unit added when calculating the raw range.
+    const auto orientInRaw = ui::Transform(inputDeviceOrientation, orientedRawSize.width - 1,
+                                           orientedRawSize.height - 1);
 
-    // Step 3: Scale the raw coordinates to the display space.
-    ui::Transform scaleToDisplay;
-    const float xScale = static_cast<float>(mDisplayBounds.width) / rotatedRawSize.width;
-    const float yScale = static_cast<float>(mDisplayBounds.height) / rotatedRawSize.height;
-    scaleToDisplay.set(xScale, 0, 0, yScale);
+    // Step 3: Rotate the raw coordinates to account for the display rotation. The coordinates will
+    // now be in the same orientation as the rotated display. There is no need to rotate the
+    // coordinates to the display rotation if the device is not orientation-aware.
+    const auto viewportRotation = ui::Transform::toRotationFlags(-mViewport.orientation);
+    const auto rotatedRawSize = mParameters.orientationAware && isRotated(viewportRotation)
+            ? ui::Size{orientedRawSize.height, orientedRawSize.width}
+            : orientedRawSize;
+    // When rotating raw values, account for the extra unit added when calculating the raw range.
+    const auto rotateInRaw = mParameters.orientationAware
+            ? ui::Transform(viewportRotation, rotatedRawSize.width - 1, rotatedRawSize.height - 1)
+            : ui::Transform();
 
-    mRawToDisplay = (scaleToDisplay * (rotate * undoRawOffset));
+    // Step 4: Scale the raw coordinates to the display space.
+    // - Here, we assume that the raw surface of the touch device maps perfectly to the surface
+    //   of the display panel. This is usually true for touchscreens.
+    // - From this point onward, we are no longer in the discrete space of the raw coordinates but
+    //   are in the continuous space of the logical display.
+    ui::Transform scaleRawToDisplay;
+    const float xScale = static_cast<float>(mViewport.deviceWidth) / rotatedRawSize.width;
+    const float yScale = static_cast<float>(mViewport.deviceHeight) / rotatedRawSize.height;
+    scaleRawToDisplay.set(xScale, 0, 0, yScale);
 
-    // Calculate the transform that takes raw coordinates to the rotated display space.
-    ui::Transform displayToRotatedDisplay;
-    displayToRotatedDisplay.set(ui::Transform::toRotationFlags(-mViewport.orientation),
-                                mViewport.deviceWidth, mViewport.deviceHeight);
-    mRawToRotatedDisplay = displayToRotatedDisplay * mRawToDisplay;
+    // Step 5: Undo the display rotation to bring us back to the un-rotated display coordinate space
+    // that InputReader uses.
+    const auto undoRotateInDisplay =
+            ui::Transform(viewportRotation, mViewport.deviceWidth, mViewport.deviceHeight)
+                    .inverse();
+
+    // Now put it all together!
+    mRawToRotatedDisplay = (scaleRawToDisplay * (rotateInRaw * (orientInRaw * undoOffsetInRaw)));
+    mRawToDisplay = (undoRotateInDisplay * mRawToRotatedDisplay);
+    mRawRotation = ui::Transform{mRawToDisplay.getOrientation()};
 }
 
 void TouchInputMapper::configureInputDevice(nsecs_t when, bool* outResetNeeded) {
@@ -945,6 +967,9 @@
             mPhysicalFrameInRotatedDisplay = {mViewport.physicalLeft, mViewport.physicalTop,
                                               mViewport.physicalRight, mViewport.physicalBottom};
 
+            // TODO(b/257118693): Remove the dependence on the old orientation/rotation logic that
+            //     uses mInputDeviceOrientation. The new logic uses the transforms calculated in
+            //     computeInputTransforms().
             // InputReader works in the un-rotated display coordinate space, so we don't need to do
             // anything if the device is already orientation-aware. If the device is not
             // orientation-aware, then we need to apply the inverse rotation of the display so that