From f6205bfa49c4f88e8c3d4196ef242ed6a86904f1 Mon Sep 17 00:00:00 2001 From: Tiger Huang Date: Thu, 29 Jul 2021 23:48:44 +0800 Subject: [PATCH] Refine updateSystemUiVisibilityLw for performance - It doesn't change the visibilities of system bars, but some other attributes, such as appearance, behavior, and disable flags. So this CL renames it to updateSystemBarAttributes. - Changing the attributes won't affect any window layout at all, so we don't re-do layout after executing it. The method returns void now. This CL also avoids redundant calls to performSurfacePlacement while the visibilities of insets are changed. setClientVisible can be called in a row while the visibilities of multiple types are changed. In this case, only one LAYOUT_AND_ASSIGN_WINDOW_LAYERS_IF_NEEDED is needed to be scheduled. Fix: 194186241 Test: atest WindowAddRemovePerfTest DisplayPolicyLayoutTests Test: Use "Window Insets Tests" > "Window Insets Controller" to show/hide system bars, and see if the window layout is expected. Change-Id: Ic66c00b1ad205c466424c033d27e7eaa2acd8fc1 --- .../com/android/server/wm/DisplayContent.java | 15 ++------- .../com/android/server/wm/DisplayPolicy.java | 33 ++++++------------- .../server/wm/InsetsSourceProvider.java | 7 ++-- .../server/wm/InsetsStateController.java | 2 +- .../server/wm/WindowManagerService.java | 3 +- .../server/wm/DisplayPolicyLayoutTests.java | 2 +- 6 files changed, 21 insertions(+), 41 deletions(-) diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 369e58cf36e6b..f5aa6c9417a89 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -134,7 +134,6 @@ import static com.android.server.wm.WindowManagerService.H.REPORT_HARD_KEYBOARD_ import static com.android.server.wm.WindowManagerService.H.WINDOW_HIDE_TIMEOUT; import static com.android.server.wm.WindowManagerService.LAYOUT_REPEAT_THRESHOLD; import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_PLACING_SURFACES; -import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_REMOVING_FOCUS; import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_ASSIGN_LAYERS; import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES; import static com.android.server.wm.WindowManagerService.WINDOWS_FREEZING_SCREENS_TIMEOUT; @@ -434,6 +433,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp // Accessed directly by all users. private boolean mLayoutNeeded; int pendingLayoutChanges; + boolean mLayoutAndAssignWindowLayersScheduled; /** * Used to gate application window layout until we have sent the complete configuration. @@ -3424,13 +3424,12 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp } } - int focusChanged = getDisplayPolicy().focusChangedLw(oldFocus, newFocus); + getDisplayPolicy().focusChangedLw(oldFocus, newFocus); if (imWindowChanged && oldFocus != mInputMethodWindow) { // Focus of the input method window changed. Perform layout if needed. if (mode == UPDATE_FOCUS_PLACING_SURFACES) { performLayout(true /*initial*/, updateInputWindows); - focusChanged &= ~FINISH_LAYOUT_REDO_LAYOUT; } else if (mode == UPDATE_FOCUS_WILL_PLACE_SURFACES) { // Client will do the layout, but we need to assign layers // for handleNewWindowLocked() below. @@ -3438,16 +3437,6 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp } } - if ((focusChanged & FINISH_LAYOUT_REDO_LAYOUT) != 0) { - // The change in focus caused us to need to do a layout. Okay. - setLayoutNeeded(); - if (mode == UPDATE_FOCUS_PLACING_SURFACES) { - performLayout(true /*initial*/, updateInputWindows); - } else if (mode == UPDATE_FOCUS_REMOVING_FOCUS) { - mWmService.mRoot.performSurfacePlacement(); - } - } - if (mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS) { // If we defer assigning layers, then the caller is responsible for doing this part. getInputMonitor().setInputFocusLw(newFocus, updateInputWindows); diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java index 686472f71fb4f..c1d6c1765a7a6 100644 --- a/services/core/java/com/android/server/wm/DisplayPolicy.java +++ b/services/core/java/com/android/server/wm/DisplayPolicy.java @@ -1984,11 +1984,7 @@ public class DisplayPolicy { mTopIsFullscreen = topIsFullscreen; } - if (updateSystemUiVisibilityLw()) { - // If the navigation bar has been hidden or shown, we need to do another - // layout pass to update that window. - changes |= FINISH_LAYOUT_REDO_LAYOUT; - } + updateSystemBarAttributes(); if (mShowingDream != mLastShowingDream) { mLastShowingDream = mShowingDream; @@ -2524,18 +2520,13 @@ public class DisplayPolicy { /** * A new window has been focused. */ - public int focusChangedLw(WindowState lastFocus, WindowState newFocus) { + public void focusChangedLw(WindowState lastFocus, WindowState newFocus) { mFocusedWindow = newFocus; mLastFocusedWindow = lastFocus; if (mDisplayContent.isDefaultDisplay) { mService.mPolicy.onDefaultDisplayFocusChangedLw(newFocus); } - if (updateSystemUiVisibilityLw()) { - // If the navigation bar has been hidden or shown, we need to do another - // layout pass to update that window. - return FINISH_LAYOUT_REDO_LAYOUT; - } - return 0; + updateSystemBarAttributes(); } private void requestTransientBars(WindowState swipeTarget) { @@ -2611,21 +2602,18 @@ public class DisplayPolicy { return mDisplayContent.getInsetsPolicy(); } - void resetSystemUiVisibilityLw() { + void resetSystemBarAttributes() { mLastDisableFlags = 0; - updateSystemUiVisibilityLw(); + updateSystemBarAttributes(); } - /** - * @return {@code true} if the update may affect the layout. - */ - boolean updateSystemUiVisibilityLw() { + void updateSystemBarAttributes() { // If there is no window focused, there will be nobody to handle the events // anyway, so just hang on in whatever state we're in until things settle down. WindowState winCandidate = mFocusedWindow != null ? mFocusedWindow : mTopFullscreenOpaqueWindowState; if (winCandidate == null) { - return false; + return; } // The immersive mode confirmation should never affect the system bar visibility, otherwise @@ -2641,7 +2629,7 @@ public class DisplayPolicy { : lastFocusCanReceiveKeys ? mLastFocusedWindow : mTopFullscreenOpaqueWindowState; if (winCandidate == null) { - return false; + return; } } final WindowState win = winCandidate; @@ -2680,7 +2668,7 @@ public class DisplayPolicy { && Objects.equals(mFocusedApp, focusedApp) && mLastFocusIsFullscreen == isFullscreen && Arrays.equals(mLastStatusBarAppearanceRegions, appearanceRegions)) { - return false; + return; } if (mDisplayContent.isDefaultDisplay && mLastFocusIsFullscreen != isFullscreen && ((mLastAppearance ^ appearance) & APPEARANCE_LOW_PROFILE_BARS) != 0) { @@ -2698,7 +2686,6 @@ public class DisplayPolicy { callStatusBarSafely(statusBar -> statusBar.onSystemBarAttributesChanged(displayId, appearance, appearanceRegions, isNavbarColorManagedByIme, behavior, requestedVisibilities, focusedApp)); - return true; } private int getStatusBarAppearance(WindowState opaque, WindowState opaqueOrDimming) { @@ -2970,7 +2957,7 @@ public class DisplayPolicy { return; } mPendingPanicGestureUptime = SystemClock.uptimeMillis(); - updateSystemUiVisibilityLw(); + updateSystemBarAttributes(); } } }; diff --git a/services/core/java/com/android/server/wm/InsetsSourceProvider.java b/services/core/java/com/android/server/wm/InsetsSourceProvider.java index cbd1314b104a5..f3e52f28ba8b6 100644 --- a/services/core/java/com/android/server/wm/InsetsSourceProvider.java +++ b/services/core/java/com/android/server/wm/InsetsSourceProvider.java @@ -376,8 +376,11 @@ class InsetsSourceProvider { return; } mClientVisible = clientVisible; - mDisplayContent.mWmService.mH.obtainMessage( - LAYOUT_AND_ASSIGN_WINDOW_LAYERS_IF_NEEDED, mDisplayContent).sendToTarget(); + if (!mDisplayContent.mLayoutAndAssignWindowLayersScheduled) { + mDisplayContent.mLayoutAndAssignWindowLayersScheduled = true; + mDisplayContent.mWmService.mH.obtainMessage( + LAYOUT_AND_ASSIGN_WINDOW_LAYERS_IF_NEEDED, mDisplayContent).sendToTarget(); + } updateVisibility(); } diff --git a/services/core/java/com/android/server/wm/InsetsStateController.java b/services/core/java/com/android/server/wm/InsetsStateController.java index 655007cf3cd1a..2c4adcbf14044 100644 --- a/services/core/java/com/android/server/wm/InsetsStateController.java +++ b/services/core/java/com/android/server/wm/InsetsStateController.java @@ -385,7 +385,7 @@ class InsetsStateController { if (changed) { notifyInsetsChanged(); mDisplayContent.updateSystemGestureExclusion(); - mDisplayContent.getDisplayPolicy().updateSystemUiVisibilityLw(); + mDisplayContent.getDisplayPolicy().updateSystemBarAttributes(); } } diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 7f6dce40fce8c..bbbbde902f6ca 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -3050,7 +3050,7 @@ public class WindowManagerService extends IWindowManager.Stub mSettingsObserver.updateSystemUiSettings(true /* handleChange */); synchronized (mGlobalLock) { // force a re-application of focused window sysui visibility on each display. - mRoot.forAllDisplayPolicies(DisplayPolicy::resetSystemUiVisibilityLw); + mRoot.forAllDisplayPolicies(DisplayPolicy::resetSystemBarAttributes); } } @@ -5292,6 +5292,7 @@ public class WindowManagerService extends IWindowManager.Stub case LAYOUT_AND_ASSIGN_WINDOW_LAYERS_IF_NEEDED: { synchronized (mGlobalLock) { final DisplayContent displayContent = (DisplayContent) msg.obj; + displayContent.mLayoutAndAssignWindowLayersScheduled = false; displayContent.layoutAndAssignWindowLayersIfNeeded(); } break; diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java index 3c7c4fdb4071f..4957ab96ace1a 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java @@ -115,7 +115,7 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase { spyOn(mNavBarWindow); // Disabling this call for most tests since it can override the systemUiFlags when called. - doReturn(false).when(mDisplayPolicy).updateSystemUiVisibilityLw(); + doNothing().when(mDisplayPolicy).updateSystemBarAttributes(); updateDisplayFrames(); }