SurfaceFlinger: prevent division by 0 in Layer::fillInputInfo

Check if scale is 0 before trying to apply it on the window scale.

Bug: 137560795
Bug: 139945549
Test: Set Window Scale Animation to off from developer options menu
Change-Id: Id372d75de5787f62a9cce7c22699216e135bd0f6
Merged-in: I7ae84e2838b1562ff62cdd94484bedba954e1f33
Signed-off-by: Nick Desaulniers <ndesaulniers@google.com>
(cherry picked from commit 5b47bbc7da3ee6f50e75eaf443176ff1bc4384d6)
diff --git a/libs/gui/tests/EndToEndNativeInputTest.cpp b/libs/gui/tests/EndToEndNativeInputTest.cpp
index 66a8a04..03b9cd7 100644
--- a/libs/gui/tests/EndToEndNativeInputTest.cpp
+++ b/libs/gui/tests/EndToEndNativeInputTest.cpp
@@ -380,6 +380,19 @@
     bgSurface->expectTap(1, 1);
 }
 
+TEST_F(InputSurfacesTest, input_respects_scaled_surface_insets_overflow) {
+    std::unique_ptr<InputSurface> fgSurface = makeSurface(100, 100);
+    // In case we pass the very big inset without any checking.
+    fgSurface->mInputInfo.surfaceInset = INT32_MAX;
+    fgSurface->showAt(100, 100);
+
+    fgSurface->doTransaction([&](auto &t, auto &sc) { t.setMatrix(sc, 2.0, 0, 0, 2.0); });
+
+    // expect no crash for overflow, and inset size to be clamped to surface size
+    injectTap(202, 202);
+    fgSurface->expectTap(1, 1);
+}
+
 // Ensure we ignore transparent region when getting screen bounds when positioning input frame.
 TEST_F(InputSurfacesTest, input_ignores_transparent_region) {
     std::unique_ptr<InputSurface> surface = makeSurface(100, 100);
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 6f87fb0..9f8605e 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -2047,14 +2047,14 @@
     ui::Transform t = getTransform();
     const float xScale = t.sx();
     const float yScale = t.sy();
-    float xSurfaceInset = info.surfaceInset;
-    float ySurfaceInset = info.surfaceInset;
+    int32_t xSurfaceInset = info.surfaceInset;
+    int32_t ySurfaceInset = info.surfaceInset;
     if (xScale != 1.0f || yScale != 1.0f) {
-        info.windowXScale *= 1.0f / xScale;
-        info.windowYScale *= 1.0f / yScale;
+        info.windowXScale *= (xScale != 0.0f) ? 1.0f / xScale : 0.0f;
+        info.windowYScale *= (yScale != 0.0f) ? 1.0f / yScale : 0.0f;
         info.touchableRegion.scaleSelf(xScale, yScale);
-        xSurfaceInset *= xScale;
-        ySurfaceInset *= yScale;
+        xSurfaceInset = std::round(xSurfaceInset * xScale);
+        ySurfaceInset = std::round(ySurfaceInset * yScale);
     }
 
     // Transform layer size to screen space and inset it by surface insets.
@@ -2066,6 +2066,11 @@
         layerBounds = getCroppedBufferSize(getDrawingState());
     }
     layerBounds = t.transform(layerBounds);
+
+    // clamp inset to layer bounds
+    xSurfaceInset = (xSurfaceInset >= 0) ? std::min(xSurfaceInset, layerBounds.getWidth() / 2) : 0;
+    ySurfaceInset = (ySurfaceInset >= 0) ? std::min(ySurfaceInset, layerBounds.getHeight() / 2) : 0;
+
     layerBounds.inset(xSurfaceInset, ySurfaceInset, xSurfaceInset, ySurfaceInset);
 
     // Input coordinate should match the layer bounds.