From 2da185d516d4441f0ea6aab4e42ea77845607fc9 Mon Sep 17 00:00:00 2001 From: Evan Rosky Date: Thu, 19 Nov 2020 20:20:53 -0800 Subject: [PATCH] Don't updateSurfacePosition with invalid window frames updateSurfacePosition runs pretty frequently (during configuration update). However, the WindowState override relies on mWindowFrames which is calculated during layout. This means that surface positions are frequently calculated with out-of-date mWindowFrames (most commonly when the onConfigurationChange cascade is called). This can easily cause visible glitching based on the timings of SFTransaction applications -- particularly when mixed with syncTransactions since those aren't serialized with layout. This CL prevents WindowState's updateSurfacePosition from running when layout is deferred or when the window is goneForLayout. Bug: 169035082 Test: With new split-screen transitions, launch a non-resizable task while in split-screen and observe that home surface doesn't get repositioned incorrectly. Change-Id: If35fb3560eed83fe1c944a1cb7cbb685f58a3b90 --- services/core/java/com/android/server/wm/WindowState.java | 6 ++++++ .../wmtests/src/com/android/server/wm/WindowStateTests.java | 2 ++ 2 files changed, 8 insertions(+) diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index b5509f62f92a8..008a7a68ab334 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -5262,6 +5262,12 @@ class WindowState extends WindowContainer implements WindowManagerP if (mSurfaceControl == null) { return; } + if (mWmService.mWindowPlacerLocked.isLayoutDeferred() || isGoneForLayout()) { + // Since this relies on mWindowFrames, changes made while layout is deferred are + // likely to be invalid. Similarly, if it's goneForLayout, mWindowFrames may not be + // up-to-date and thus can't be relied on. + return; + } transformFrameToSurfacePosition(mWindowFrames.mFrame.left, mWindowFrames.mFrame.top, mSurfacePosition); diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java index 75d2c5159187a..12746b1bd4c3f 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java @@ -647,6 +647,8 @@ public class WindowStateTests extends WindowTestsBase { win1.mSurfaceControl = mock(SurfaceControl.class); win1.mAttrs.surfaceInsets.set(1, 2, 3, 4); win1.getFrame().offsetTo(WINDOW_OFFSET, 0); + // Simulate layout + win1.mRelayoutCalled = true; win1.updateSurfacePosition(t); win1.getTransformationMatrix(values, matrix);