From 097829d3492a90e2613be00ae0c3d77d20875613 Mon Sep 17 00:00:00 2001 From: Oleg Blinnikov Date: Tue, 27 Sep 2022 11:33:58 +0000 Subject: [PATCH] DisplayPolicy: Check that window provided insets This is the fix to a problem in WindowState.removeIfPossible(boolean) The core of the problem is that WindowState.removeImmediately call removes providedInsetsSources, but these are important for WindowState.providesNonDecorInsets to check if the window provided insets. This solution makes the call to WindowState.providesNonDecorInsets before calling WindowState.removeImmediately The result is that sendNewConfiguration consistently triggered during removal of navbar. Bug: 211763738 Test: atest WindowStateTests Change-Id: I2b92688437ffab02f4aee8519eb2a8e3deeb6484 --- .../java/com/android/server/wm/DisplayPolicy.java | 5 +---- .../com/android/server/wm/WindowManagerService.java | 12 ++++++++---- .../core/java/com/android/server/wm/WindowState.java | 12 ++++++++++-- .../com/android/server/wm/ActivityRecordTests.java | 3 ++- .../com/android/server/wm/DisplayPolicyTests.java | 8 ++++++-- 5 files changed, 27 insertions(+), 13 deletions(-) diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java index b26de07461d6c..4c69f87106d13 100644 --- a/services/core/java/com/android/server/wm/DisplayPolicy.java +++ b/services/core/java/com/android/server/wm/DisplayPolicy.java @@ -2168,10 +2168,7 @@ public class DisplayPolicy { * If the decor insets changes, the display configuration may be affected. The caller should * call {@link DisplayContent#sendNewConfiguration()} if this method returns {@code true}. */ - boolean updateDecorInsetsInfoIfNeeded(WindowState win) { - if (!win.providesNonDecorInsets()) { - return false; - } + boolean updateDecorInsetsInfo() { final DisplayFrames displayFrames = mDisplayContent.mDisplayFrames; final int rotation = displayFrames.mRotation; final int dw = displayFrames.mWidth; diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index c96253ccf70a0..4d37e08166399 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -1858,8 +1858,12 @@ public class WindowManagerService extends IWindowManager.Stub ProtoLog.v(WM_DEBUG_ADD_REMOVE, "addWindow: New client %s" + ": window=%s Callers=%s", client.asBinder(), win, Debug.getCallers(5)); - if ((win.isVisibleRequestedOrAdding() && displayContent.updateOrientation()) - || displayPolicy.updateDecorInsetsInfoIfNeeded(win)) { + boolean needToSendNewConfiguration = + win.isVisibleRequestedOrAdding() && displayContent.updateOrientation(); + if (win.providesNonDecorInsets()) { + needToSendNewConfiguration |= displayPolicy.updateDecorInsetsInfo(); + } + if (needToSendNewConfiguration) { displayContent.sendNewConfiguration(); } @@ -2329,8 +2333,8 @@ public class WindowManagerService extends IWindowManager.Stub & WindowManager.LayoutParams.SYSTEM_UI_VISIBILITY_CHANGED) != 0) { win.mLayoutNeeded = true; } - if (layoutChanged) { - configChanged = displayPolicy.updateDecorInsetsInfoIfNeeded(win); + if (layoutChanged && win.providesNonDecorInsets()) { + configChanged = displayPolicy.updateDecorInsetsInfo(); } if (win.mActivityRecord != null && ((flagChanges & FLAG_SHOW_WHEN_LOCKED) != 0 || (flagChanges & FLAG_DISMISS_KEYGUARD) != 0)) { diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 7c9d27704442e..42d28612c83ff 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -2627,11 +2627,19 @@ class WindowState extends WindowContainer implements WindowManagerP } } + // Check if window provides non decor insets before clearing its provided insets. + final boolean windowProvidesNonDecorInsets = providesNonDecorInsets(); + removeImmediately(); // Removing a visible window may affect the display orientation so just update it if // needed. Also recompute configuration if it provides screen decor insets. - if ((wasVisible && displayContent.updateOrientation()) - || displayContent.getDisplayPolicy().updateDecorInsetsInfoIfNeeded(this)) { + boolean needToSendNewConfiguration = wasVisible && displayContent.updateOrientation(); + if (windowProvidesNonDecorInsets) { + needToSendNewConfiguration |= + displayContent.getDisplayPolicy().updateDecorInsetsInfo(); + } + + if (needToSendNewConfiguration) { displayContent.sendNewConfiguration(); } mWmService.updateFocusedWindowLocked(isFocused() diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java index 95e9f20011d00..d5447447a7b2a 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java @@ -2992,7 +2992,8 @@ public class ActivityRecordTests extends WindowTestsBase { .setSystemDecorations(true).build(); // Add a decor insets provider window. final WindowState navbar = createNavBarWithProvidedInsets(squareDisplay); - squareDisplay.getDisplayPolicy().updateDecorInsetsInfoIfNeeded(navbar); + assertTrue(navbar.providesNonDecorInsets() + && squareDisplay.getDisplayPolicy().updateDecorInsetsInfo()); squareDisplay.sendNewConfiguration(); final Task task = new TaskBuilder(mSupervisor).setDisplay(squareDisplay).build(); diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java index e00296f4d801f..73eb1273efa38 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java @@ -292,12 +292,16 @@ public class DisplayPolicyTests extends WindowTestsBase { final DisplayPolicy displayPolicy = mDisplayContent.getDisplayPolicy(); final DisplayInfo di = mDisplayContent.getDisplayInfo(); final int prevScreenHeightDp = mDisplayContent.getConfiguration().screenHeightDp; - assertTrue(displayPolicy.updateDecorInsetsInfoIfNeeded(navbar)); + assertTrue(navbar.providesNonDecorInsets() && displayPolicy.updateDecorInsetsInfo()); assertEquals(NAV_BAR_HEIGHT, displayPolicy.getDecorInsetsInfo(di.rotation, di.logicalWidth, di.logicalHeight).mConfigInsets.bottom); mDisplayContent.sendNewConfiguration(); assertNotEquals(prevScreenHeightDp, mDisplayContent.getConfiguration().screenHeightDp); - assertFalse(displayPolicy.updateDecorInsetsInfoIfNeeded(navbar)); + assertFalse(navbar.providesNonDecorInsets() && displayPolicy.updateDecorInsetsInfo()); + + navbar.removeIfPossible(); + assertEquals(0, displayPolicy.getDecorInsetsInfo(di.rotation, di.logicalWidth, + di.logicalHeight).mNonDecorInsets.bottom); } @UseTestDisplay(addWindows = { W_NAVIGATION_BAR, W_INPUT_METHOD })