diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 5f47986501849..7af0c257cb259 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -1823,21 +1823,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; } /** @@ -1884,6 +1890,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 152a575c847dc..157740f567dc1 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java @@ -956,4 +956,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()); + } }