SF: Clean up input info calculations

This CL simplifies the calculation of the input transform and frame for
Layers.

It also switches the calculations to use floats rather than intergers
for greater precesion when scaling.

Bug: 200787840
Bug: 179274888
Test: atest libgui_test
Change-Id: Ia1ed53b669caa867e5b98e72d5d71ed615222f8f
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 8c77a8b..fc73181 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -2166,9 +2166,9 @@
     return getCroppedBufferSize(getDrawingState());
 }
 
-void Layer::fillInputFrameInfo(WindowInfo& info, const ui::Transform& displayTransform) {
-    Rect layerBounds = getInputBounds();
-    if (!layerBounds.isValid()) {
+void Layer::fillInputFrameInfo(WindowInfo& info, const ui::Transform& screenToDisplay) {
+    Rect tmpBounds = getInputBounds();
+    if (!tmpBounds.isValid()) {
         info.flags = WindowInfo::Flag::NOT_TOUCH_MODAL | WindowInfo::Flag::NOT_FOCUSABLE;
         info.focusable = false;
         info.touchableRegion.clear();
@@ -2176,82 +2176,61 @@
         // replaceTouchableRegionWithCrop. For that case, the input transform needs to be calculated
         // correctly to determine the coordinate space for input events. Use an empty rect so that
         // the layer will receive input in its own layer space.
-        layerBounds = Rect::EMPTY_RECT;
+        tmpBounds = Rect::EMPTY_RECT;
     }
 
-    const ui::Transform layerTransform = getInputTransform();
-    // Transform that takes window coordinates to non-rotated display coordinates
-    ui::Transform t = displayTransform * layerTransform;
-    int32_t xSurfaceInset = info.surfaceInset;
-    int32_t ySurfaceInset = info.surfaceInset;
-    // Bring screenBounds into non-unrotated space
-    Rect screenBounds = displayTransform.transform(Rect{mScreenBounds});
+    // InputDispatcher works in the display device's coordinate space. Here, we calculate the
+    // frame and transform used for the layer, which determines the bounds and the coordinate space
+    // within which the layer will receive input.
+    //
+    // The coordinate space within which each of the bounds are specified is explicitly documented
+    // in the variable name. For example "inputBoundsInLayer" is specified in layer space. A
+    // Transform converts one coordinate space to another, which is apparent in its naming. For
+    // example, "layerToDisplay" transforms layer space to display space.
+    //
+    // Coordinate space definitions:
+    //   - display: The display device's coordinate space. Correlates to pixels on the display.
+    //   - screen: The post-rotation coordinate space for the display, a.k.a. logical display space.
+    //   - layer: The coordinate space of this layer.
+    //   - input: The coordinate space in which this layer will receive input events. This could be
+    //            different than layer space if a surfaceInset is used, which changes the origin
+    //            of the input space.
+    const FloatRect inputBoundsInLayer = tmpBounds.toFloatRect();
 
-    const float xScale = t.getScaleX();
-    const float yScale = t.getScaleY();
-    if (xScale != 1.0f || yScale != 1.0f) {
-        xSurfaceInset = std::round(xSurfaceInset * xScale);
-        ySurfaceInset = std::round(ySurfaceInset * yScale);
-    }
+    // Clamp surface inset to the input bounds.
+    const auto surfaceInset = static_cast<float>(info.surfaceInset);
+    const float xSurfaceInset =
+            std::max(0.f, std::min(surfaceInset, inputBoundsInLayer.getWidth() / 2.f));
+    const float ySurfaceInset =
+            std::max(0.f, std::min(surfaceInset, inputBoundsInLayer.getHeight() / 2.f));
 
-    // Transform the layer bounds from layer coordinate space to display coordinate space.
-    Rect transformedLayerBounds = t.transform(layerBounds);
+    // Apply the insets to the input bounds.
+    const FloatRect insetBoundsInLayer(inputBoundsInLayer.left + xSurfaceInset,
+                                       inputBoundsInLayer.top + ySurfaceInset,
+                                       inputBoundsInLayer.right - xSurfaceInset,
+                                       inputBoundsInLayer.bottom - ySurfaceInset);
 
-    // clamp inset to layer bounds
-    xSurfaceInset = (xSurfaceInset >= 0)
-            ? std::min(xSurfaceInset, transformedLayerBounds.getWidth() / 2)
-            : 0;
-    ySurfaceInset = (ySurfaceInset >= 0)
-            ? std::min(ySurfaceInset, transformedLayerBounds.getHeight() / 2)
-            : 0;
+    // Crop the input bounds to ensure it is within the parent's bounds.
+    const FloatRect croppedInsetBoundsInLayer = mBounds.intersect(insetBoundsInLayer);
 
-    // inset while protecting from overflow TODO(b/161235021): What is going wrong
-    // in the overflow scenario?
-    {
-    int32_t tmp;
-    if (!__builtin_add_overflow(transformedLayerBounds.left, xSurfaceInset, &tmp))
-        transformedLayerBounds.left = tmp;
-    if (!__builtin_sub_overflow(transformedLayerBounds.right, xSurfaceInset, &tmp))
-        transformedLayerBounds.right = tmp;
-    if (!__builtin_add_overflow(transformedLayerBounds.top, ySurfaceInset, &tmp))
-        transformedLayerBounds.top = tmp;
-    if (!__builtin_sub_overflow(transformedLayerBounds.bottom, ySurfaceInset, &tmp))
-        transformedLayerBounds.bottom = tmp;
-    }
+    const ui::Transform layerToScreen = getInputTransform();
+    const ui::Transform layerToDisplay = screenToDisplay * layerToScreen;
 
-    // Compute the correct transform to send to input. This will allow it to transform the
-    // input coordinates from display space into window space. Therefore, it needs to use the
-    // final layer frame to create the inverse transform. Since surface insets are added later,
-    // along with the overflow, the best way to ensure we get the correct transform is to use
-    // the final frame calculated.
-    // 1. Take the original transform set on the window and get the inverse transform. This is
-    //    used to get the final bounds in display space (ignorning the transform). Apply the
-    //    inverse transform on the layerBounds to get the untransformed frame (in layer space)
-    // 2. Take the top and left of the untransformed frame to get the real position on screen.
-    //    Apply the layer transform on top/left so it includes any scale or rotation. These will
-    //    be the new translation values for the transform.
-    // 3. Update the translation of the original transform to the new translation values.
-    // 4. Send the inverse transform to input so the coordinates can be transformed back into
-    //    window space.
-    ui::Transform inverseTransform = t.inverse();
-    Rect nonTransformedBounds = inverseTransform.transform(transformedLayerBounds);
-    vec2 translation = t.transform(nonTransformedBounds.left, nonTransformedBounds.top);
-    ui::Transform inputTransform(t);
-    inputTransform.set(translation.x, translation.y);
-    info.transform = inputTransform.inverse();
+    const Rect roundedFrameInDisplay{layerToDisplay.transform(croppedInsetBoundsInLayer)};
+    info.frameLeft = roundedFrameInDisplay.left;
+    info.frameTop = roundedFrameInDisplay.top;
+    info.frameRight = roundedFrameInDisplay.right;
+    info.frameBottom = roundedFrameInDisplay.bottom;
 
-    // We need to send the layer bounds cropped to the screenbounds since the layer can be cropped.
-    // The frame should be the area the user sees on screen since it's used for occlusion
-    // detection.
-    transformedLayerBounds.intersect(screenBounds, &transformedLayerBounds);
-    info.frameLeft = transformedLayerBounds.left;
-    info.frameTop = transformedLayerBounds.top;
-    info.frameRight = transformedLayerBounds.right;
-    info.frameBottom = transformedLayerBounds.bottom;
+    ui::Transform inputToLayer;
+    inputToLayer.set(insetBoundsInLayer.left, insetBoundsInLayer.top);
+    const ui::Transform inputToDisplay = layerToDisplay * inputToLayer;
 
-    // Position the touchable region relative to frame screen location and restrict it to frame
-    // bounds.
-    info.touchableRegion = inputTransform.transform(info.touchableRegion);
+    // InputDispatcher expects a display-to-input transform.
+    info.transform = inputToDisplay.inverse();
+
+    // The touchable region is specified in the input coordinate space. Change it to display space.
+    info.touchableRegion = inputToDisplay.transform(info.touchableRegion);
 }
 
 void Layer::fillTouchOcclusionMode(WindowInfo& info) {