diff options
| author | 2019-07-24 18:05:56 -0700 | |
|---|---|---|
| committer | 2019-11-05 15:50:19 -0800 | |
| commit | 5b47bbc7da3ee6f50e75eaf443176ff1bc4384d6 (patch) | |
| tree | 2aae7c31b0d55a5386a5248f42b36a3e3922986c | |
| parent | 968fc9aa0577dd7cd97cd3416803d2eba4ae021f (diff) | |
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>
| -rw-r--r-- | libs/gui/tests/EndToEndNativeInputTest.cpp | 13 | ||||
| -rw-r--r-- | services/surfaceflinger/Layer.cpp | 17 |
2 files changed, 24 insertions, 6 deletions
diff --git a/libs/gui/tests/EndToEndNativeInputTest.cpp b/libs/gui/tests/EndToEndNativeInputTest.cpp index ff1ba0ad17..386f731d23 100644 --- a/libs/gui/tests/EndToEndNativeInputTest.cpp +++ b/libs/gui/tests/EndToEndNativeInputTest.cpp @@ -410,6 +410,19 @@ TEST_F(InputSurfacesTest, input_respects_scaled_surface_insets) { 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 f4284fead7..efc989e554 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -2046,14 +2046,14 @@ InputWindowInfo Layer::fillInputInfo() { 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. @@ -2065,6 +2065,11 @@ InputWindowInfo Layer::fillInputInfo() { 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. |