diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java index dc53c22e8ceaa..13ffeecd235e6 100644 --- a/core/java/android/view/WindowManagerPolicy.java +++ b/core/java/android/view/WindowManagerPolicy.java @@ -400,6 +400,13 @@ public interface WindowManagerPolicy { */ boolean isAnimatingLw(); + /** + * @return Whether the window can affect SystemUI flags, meaning that SystemUI (system bars, + * for example) will be affected by the flags specified in this window. This is the + * case when the surface is on screen but not exiting. + */ + boolean canAffectSystemUiFlags(); + /** * Is this window considered to be gone for purposes of layout? */ diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index ae9852eb34a54..8b8e3c471006b 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -5333,11 +5333,12 @@ public class PhoneWindowManager implements WindowManagerPolicy { @Override public void applyPostLayoutPolicyLw(WindowState win, WindowManager.LayoutParams attrs, WindowState attached, WindowState imeTarget) { - final boolean visible = win.isVisibleLw() && win.getAttrs().alpha > 0f; - if (DEBUG_LAYOUT) Slog.i(TAG, "Win " + win + ": isVisible=" + visible); + final boolean affectsSystemUi = win.canAffectSystemUiFlags(); + if (DEBUG_LAYOUT) Slog.i(TAG, "Win " + win + ": affectsSystemUi=" + affectsSystemUi); applyKeyguardPolicyLw(win, imeTarget); final int fl = PolicyControl.getWindowFlags(win, attrs); - if (mTopFullscreenOpaqueWindowState == null && visible && attrs.type == TYPE_INPUT_METHOD) { + if (mTopFullscreenOpaqueWindowState == null && affectsSystemUi + && attrs.type == TYPE_INPUT_METHOD) { mForcingShowNavBar = true; mForcingShowNavBarLayer = win.getSurfaceLayer(); } @@ -5353,7 +5354,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { boolean appWindow = attrs.type >= FIRST_APPLICATION_WINDOW && attrs.type < FIRST_SYSTEM_WINDOW; final int stackId = win.getStackId(); - if (mTopFullscreenOpaqueWindowState == null && visible) { + if (mTopFullscreenOpaqueWindowState == null && affectsSystemUi) { if ((fl & FLAG_FORCE_NOT_FULLSCREEN) != 0) { mForceStatusBar = true; } @@ -5385,7 +5386,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { } // Voice interaction overrides both top fullscreen and top docked. - if (visible && win.getAttrs().type == TYPE_VOICE_INTERACTION) { + if (affectsSystemUi && win.getAttrs().type == TYPE_VOICE_INTERACTION) { if (mTopFullscreenOpaqueWindowState == null) { mTopFullscreenOpaqueWindowState = win; if (mTopFullscreenOpaqueOrDimmingWindowState == null) { @@ -5401,7 +5402,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { } // Keep track of the window if it's dimming but not necessarily fullscreen. - if (mTopFullscreenOpaqueOrDimmingWindowState == null && visible + if (mTopFullscreenOpaqueOrDimmingWindowState == null && affectsSystemUi && win.isDimming() && StackId.normallyFullscreenWindows(stackId)) { mTopFullscreenOpaqueOrDimmingWindowState = win; } @@ -5409,7 +5410,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { // We need to keep track of the top "fullscreen" opaque window for the docked stack // separately, because both the "real fullscreen" opaque window and the one for the docked // stack can control View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR. - if (mTopDockedOpaqueWindowState == null && visible && appWindow && attached == null + if (mTopDockedOpaqueWindowState == null && affectsSystemUi && appWindow && attached == null && isFullscreen(attrs) && stackId == DOCKED_STACK_ID) { mTopDockedOpaqueWindowState = win; if (mTopDockedOpaqueOrDimmingWindowState == null) { @@ -5419,7 +5420,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { // Also keep track of any windows that are dimming but not necessarily fullscreen in the // docked stack. - if (mTopDockedOpaqueOrDimmingWindowState == null && visible && win.isDimming() + if (mTopDockedOpaqueOrDimmingWindowState == null && affectsSystemUi && win.isDimming() && stackId == DOCKED_STACK_ID) { mTopDockedOpaqueOrDimmingWindowState = win; } diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 2ffa15206cb6b..acd7703836d15 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -1403,6 +1403,16 @@ class WindowState extends WindowContainer implements WindowManagerP || ((mAppToken != null) && (mAppToken.mAppAnimator.animation != null))); } + // TODO: Another visibility method that was added late in the release to minimize risk. + @Override + public boolean canAffectSystemUiFlags() { + final boolean shown = mWinAnimator.getShown(); + final boolean exiting = mAnimatingExit || mDestroying + || mAppToken != null && mAppToken.hidden; + final boolean translucent = mAttrs.alpha == 0.0f; + return shown && !exiting && !translucent; + } + /** * Like isOnScreen, but returns false if the surface hasn't yet * been drawn.