From 3404601e073ee2fb7867e3aa50a730bcf51eda07 Mon Sep 17 00:00:00 2001 From: Tiger Huang Date: Fri, 29 Jun 2018 15:26:52 +0800 Subject: [PATCH] Don't flash system bars while showing an immersive app on lockscreen Before applying this patch, when a show-when-locked immersive app is showing, the system bars would quickly show and hide, which are redundant to the user. The root cause is that, for nav bar, we have a policy to show nav bar if the width and height of status bar are MATCH_PARENT and status bar has no PRIVATE_FLAG_KEYGUARD. When keyguard is becoming status bar, its keyguard flag would be removed first, and then the height would be changed to the bar height. So the nav bar would be shown between these events. For status bar, we force showing it when it is expanded by checking its width and height are MATCH_PARENT or not. To fix the issue, this change introduces a new private flag which indicates that the status bar window is now in an explicit expanded state. We check this flag instead of checking the width and height of status bar. This change also fix a bug that: when AOD is enabled, if the foreground app has FLAG_SHOW_WHEN_LOCKED, FLAG_TURN_SCREEN_ON, and FLAG_FULLSCREEN, clicking on the power key would make it show the app again instead of AOD. (not 100%, but chances) Bug: 80147982 Test: 1. go/wm-smoke 2. Launch a show-when-locked turn-screen-on immersive app on AOD, and see if any system bar flashes. 3. Launch a show-when-locked turn-screen-on immersive app on lockscreen, and see if any system bar flashes. 4. a. Enable AOD in Settings. b. Open a show-when-locked turn-screen-on immersive app. c. Click on power key, and see if AOD shows. 5. Launch an immersive app and drag down the status bar, see if nav bar keeps there as long as status bar is expanded. Change-Id: Ie885d504eb73ae8a86736b2c3ed4fb03eb9f739e --- core/java/android/view/WindowManager.java | 15 ++++++++++++++- .../statusbar/phone/StatusBarWindowManager.java | 10 ++++++++++ .../com/android/server/policy/BarController.java | 2 +- .../android/server/policy/PhoneWindowManager.java | 11 +++++------ 4 files changed, 30 insertions(+), 8 deletions(-) diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index 4d7b73cb7c089..8c7ac731b3e3f 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -1691,6 +1691,15 @@ public interface WindowManager extends ViewManager { @RequiresPermission(permission.STATUS_BAR_SERVICE) public static final int PRIVATE_FLAG_IS_SCREEN_DECOR = 0x00400000; + /** + * Flag to indicate that the status bar window is now in an explicit expanded state, meaning + * that status bar will not be hidden by any window with flag {@link #FLAG_FULLSCREEN} or + * {@link View#SYSTEM_UI_FLAG_FULLSCREEN} set. + * This can only be set by {@link LayoutParams#TYPE_STATUS_BAR}. + * @hide + */ + public static final int PRIVATE_FLAG_STATUS_BAR_EXPANDED = 0x00800000; + /** * Control flags that are private to the platform. * @hide @@ -1779,7 +1788,11 @@ public interface WindowManager extends ViewManager { @ViewDebug.FlagToString( mask = PRIVATE_FLAG_IS_SCREEN_DECOR, equals = PRIVATE_FLAG_IS_SCREEN_DECOR, - name = "IS_SCREEN_DECOR") + name = "IS_SCREEN_DECOR"), + @ViewDebug.FlagToString( + mask = PRIVATE_FLAG_STATUS_BAR_EXPANDED, + equals = PRIVATE_FLAG_STATUS_BAR_EXPANDED, + name = "STATUS_BAR_EXPANDED") }) @TestApi public int privateFlags; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java index fadc0eac9e735..a38328a8161ee 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java @@ -180,6 +180,15 @@ public class StatusBarWindowManager implements RemoteInputController.Callback, D mLpChanged.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE; } + private void applyExpandedFlag(State state) { + if (state.panelExpanded || state.isKeyguardShowingAndNotOccluded() || state.bouncerShowing + || ENABLE_REMOTE_INPUT && state.remoteInputActive) { + mLpChanged.privateFlags |= LayoutParams.PRIVATE_FLAG_STATUS_BAR_EXPANDED; + } else { + mLpChanged.privateFlags &= ~LayoutParams.PRIVATE_FLAG_STATUS_BAR_EXPANDED; + } + } + private void applyHeight(State state) { boolean expanded = isExpanded(state); if (state.forcePluginOpen) { @@ -234,6 +243,7 @@ public class StatusBarWindowManager implements RemoteInputController.Callback, D applyKeyguardFlags(state); applyForceStatusBarVisibleFlag(state); applyFocusableFlag(state); + applyExpandedFlag(state); adjustScreenOrientation(state); applyHeight(state); applyUserActivityTimeout(state); diff --git a/services/core/java/com/android/server/policy/BarController.java b/services/core/java/com/android/server/policy/BarController.java index eca6f9f1ec478..14c985c090a37 100644 --- a/services/core/java/com/android/server/policy/BarController.java +++ b/services/core/java/com/android/server/policy/BarController.java @@ -196,7 +196,7 @@ public class BarController { } protected boolean skipAnimation() { - return false; + return !mWin.isDrawnLw(); } private int computeStateLw(boolean wasVis, boolean wasAnim, WindowState win, boolean change) { diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index b99f8d6c81709..5bc35e7296c3f 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -76,6 +76,7 @@ import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_IS_ROUNDED_CO import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_IS_SCREEN_DECOR; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS; +import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_STATUS_BAR_EXPANDED; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SYSTEM_ERROR; import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_CROSSFADE; import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_JUMPCUT; @@ -4686,8 +4687,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { navTranslucent &= areTranslucentBarsAllowed(); } boolean statusBarExpandedNotKeyguard = !isKeyguardShowing && mStatusBar != null - && mStatusBar.getAttrs().height == MATCH_PARENT - && mStatusBar.getAttrs().width == MATCH_PARENT; + && (mStatusBar.getAttrs().privateFlags & PRIVATE_FLAG_STATUS_BAR_EXPANDED) != 0; // When the navigation bar isn't visible, we put up a fake input window to catch all // touch events. This way we can detect when the user presses anywhere to bring back the @@ -5690,7 +5690,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { } // Take note if a window wants to acquire a sleep token. - if (win.isVisibleLw() && (attrs.privateFlags & PRIVATE_FLAG_ACQUIRES_SLEEP_TOKEN) != 0 + if ((attrs.privateFlags & PRIVATE_FLAG_ACQUIRES_SLEEP_TOKEN) != 0 && win.canAcquireSleepToken()) { mWindowSleepTokenNeeded = true; } @@ -5746,9 +5746,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { mStatusBarController.setShowTransparent(true /* transparent */); } - WindowManager.LayoutParams statusBarAttrs = mStatusBar.getAttrs(); - boolean statusBarExpanded = statusBarAttrs.height == MATCH_PARENT - && statusBarAttrs.width == MATCH_PARENT; + boolean statusBarExpanded = + (mStatusBar.getAttrs().privateFlags & PRIVATE_FLAG_STATUS_BAR_EXPANDED) != 0; boolean topAppHidesStatusBar = topAppHidesStatusBar(); if (mForceStatusBar || mForceStatusBarFromKeyguard || mForceStatusBarTransparent || statusBarExpanded) {