diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 1a468d9f4ee9f..53271207bbe34 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -1842,21 +1842,27 @@ class WindowState extends WindowContainer implements WindowManagerP return super.hasContentToDisplay(); } - @Override - boolean isVisible() { - return wouldBeVisibleIfPolicyIgnored() && isVisibleByPolicy() + private boolean isVisibleByPolicyOrInsets() { + return isVisibleByPolicy() // If we don't have a provider, this window isn't used as a window generating // insets, so nobody can hide it over the inset APIs. && (mControllableInsetProvider == null || mControllableInsetProvider.isClientVisible()); } + @Override + boolean isVisible() { + return wouldBeVisibleIfPolicyIgnored() && isVisibleByPolicyOrInsets(); + } + @Override boolean isVisibleRequested() { - if (shouldCheckTokenVisibleRequested()) { - return isVisible() && mToken.isVisibleRequested(); + final boolean localVisibleRequested = + wouldBeVisibleRequestedIfPolicyIgnored() && isVisibleByPolicyOrInsets(); + if (localVisibleRequested && shouldCheckTokenVisibleRequested()) { + return mToken.isVisibleRequested(); } - return isVisible(); + return localVisibleRequested; } /** @@ -1903,6 +1909,16 @@ class WindowState extends WindowContainer implements WindowManagerP return !isWallpaper || mToken.isVisible(); } + private boolean wouldBeVisibleRequestedIfPolicyIgnored() { + final WindowState parent = getParentWindow(); + final boolean isParentHiddenRequested = parent != null && !parent.isVisibleRequested(); + if (isParentHiddenRequested || mAnimatingExit || mDestroying) { + return false; + } + final boolean isWallpaper = mToken.asWallpaperToken() != null; + return !isWallpaper || mToken.isVisibleRequested(); + } + /** * Is this window visible, ignoring its app token? It is not visible if there is no surface, * or we are in the process of running an exit animation that will remove the surface. 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 92b670ed96995..e83db78409b81 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java @@ -946,4 +946,19 @@ public class WindowStateTests extends WindowTestsBase { assertNotNull(state.peekSource(ITYPE_IME)); assertTrue(state.getSource(ITYPE_IME).isVisible()); } + + @Test + public void testRequestedVisibility() { + final WindowState app = createWindow(null, TYPE_APPLICATION, "app"); + app.mActivityRecord.setVisible(false); + app.mActivityRecord.setVisibility(false /* visible */, false /* deferHidingClient */); + assertFalse(app.isVisibleRequested()); + + // It doesn't have a surface yet, but should still be visible requested. + app.setHasSurface(false); + app.mActivityRecord.setVisibility(true /* visible */, false /* deferHidingClient */); + + assertFalse(app.isVisible()); + assertTrue(app.isVisibleRequested()); + } }