Loading core/java/android/view/InsetsState.java +14 −0 Original line number Diff line number Diff line Loading @@ -342,6 +342,20 @@ public class InsetsState implements Parcelable { } } /** * A shortcut for setting the visibility of the source. * * @param type The {@link InternalInsetsType} of the source to set the visibility * @param referenceState The {@link InsetsState} for reference */ public void setSourceVisible(@InternalInsetsType int type, InsetsState referenceState) { InsetsSource source = mSources.get(type); InsetsSource referenceSource = referenceState.mSources.get(type); if (source != null && referenceSource != null) { source.setVisible(referenceSource.isVisible()); } } public void set(InsetsState other) { set(other, false /* copySources */); } Loading services/core/java/com/android/server/wm/InsetsControlTarget.java +6 −1 Original line number Diff line number Diff line Loading @@ -23,7 +23,12 @@ import android.view.WindowInsets.Type.InsetsType; * Generalization of an object that can control insets state. */ interface InsetsControlTarget { void notifyInsetsControlChanged(); /** * Notifies the control target that the insets control has changed. */ default void notifyInsetsControlChanged() { }; /** * @return {@link WindowState} of this target, if any. Loading services/core/java/com/android/server/wm/InsetsPolicy.java +42 −44 Original line number Diff line number Diff line Loading @@ -57,9 +57,11 @@ class InsetsPolicy { private final InsetsStateController mStateController; private final DisplayContent mDisplayContent; private final DisplayPolicy mPolicy; private final TransientControlTarget mTransientControlTarget = new TransientControlTarget(); private final IntArray mShowingTransientTypes = new IntArray(); /** For resetting visibilities of insets sources. */ private final InsetsControlTarget mDummyControlTarget = new InsetsControlTarget() { }; private WindowState mFocusedWin; private BarWindow mStatusBar = new BarWindow(StatusBarManager.WINDOW_STATUS_BAR); private BarWindow mNavBar = new BarWindow(StatusBarManager.WINDOW_NAVIGATION_BAR); Loading Loading @@ -143,12 +145,15 @@ class InsetsPolicy { */ InsetsState getInsetsForDispatch(WindowState target) { InsetsState state = mStateController.getInsetsForDispatch(target); if (mShowingTransientTypes.size() == 0) { return state; } for (int i = mShowingTransientTypes.size() - 1; i >= 0; i--) { state.setSourceVisible(mShowingTransientTypes.get(i), false); } if (mFocusedWin != null && getStatusControlTarget(mFocusedWin) == mDummyControlTarget) { state.setSourceVisible(ITYPE_STATUS_BAR, mFocusedWin.getRequestedInsetsState()); } if (mFocusedWin != null && getNavControlTarget(mFocusedWin) == mDummyControlTarget) { state.setSourceVisible(ITYPE_NAVIGATION_BAR, mFocusedWin.getRequestedInsetsState()); } return state; } Loading Loading @@ -194,71 +199,71 @@ class InsetsPolicy { private @Nullable InsetsControlTarget getFakeStatusControlTarget( @Nullable WindowState focused) { if (mShowingTransientTypes.indexOf(ITYPE_STATUS_BAR) != -1) { return focused; } return null; return getStatusControlTarget(focused) == mDummyControlTarget ? focused : null; } private @Nullable InsetsControlTarget getFakeNavControlTarget(@Nullable WindowState focused) { if (mShowingTransientTypes.indexOf(ITYPE_NAVIGATION_BAR) != -1) { return focused; } return null; return getNavControlTarget(focused) == mDummyControlTarget ? focused : null; } private @Nullable InsetsControlTarget getStatusControlTarget(@Nullable WindowState focusedWin) { if (mShowingTransientTypes.indexOf(ITYPE_STATUS_BAR) != -1) { return mTransientControlTarget; return mDummyControlTarget; } if (focusedWin == mPolicy.getNotificationShade()) { // Notification shade has control anyways, no reason to force anything. return focusedWin; } if (areSystemBarsForciblyVisible() || isKeyguardOrStatusBarForciblyVisible()) { if (forceShowsSystemBarsForWindowingMode()) { // Status bar is forcibly shown for the windowing mode which is a steady state. // We don't want the client to control the status bar, and we will dispatch the real // visibility of status bar to the client. return null; } if (forceShowsStatusBarTransiently()) { // Status bar is forcibly shown transiently, and its new visibility won't be // dispatched to the client so that we can keep the layout stable. We will dispatch the // fake control to the client, so that it can re-show the bar during this scenario. return mDummyControlTarget; } return focusedWin; } private @Nullable InsetsControlTarget getNavControlTarget(@Nullable WindowState focusedWin) { if (mShowingTransientTypes.indexOf(ITYPE_NAVIGATION_BAR) != -1) { return mTransientControlTarget; return mDummyControlTarget; } if (focusedWin == mPolicy.getNotificationShade()) { // Notification shade has control anyways, no reason to force anything. return focusedWin; } if (areSystemBarsForciblyVisible() || isNavBarForciblyVisible()) { if (forceShowsSystemBarsForWindowingMode()) { // Navigation bar is forcibly shown for the windowing mode which is a steady state. // We don't want the client to control the navigation bar, and we will dispatch the real // visibility of navigation bar to the client. return null; } if (forceShowsNavigationBarTransiently()) { // Navigation bar is forcibly shown transiently, and its new visibility won't be // dispatched to the client so that we can keep the layout stable. We will dispatch the // fake control to the client, so that it can re-show the bar during this scenario. return mDummyControlTarget; } return focusedWin; } private boolean isKeyguardOrStatusBarForciblyVisible() { final WindowState statusBar = mPolicy.getStatusBar(); if (statusBar != null) { // TODO(b/118118435): Pretend to the app that it's still able to control it? if ((statusBar.mAttrs.privateFlags & PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR) != 0) { return true; } } return false; private boolean forceShowsStatusBarTransiently() { final WindowState win = mPolicy.getStatusBar(); return win != null && (win.mAttrs.privateFlags & PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR) != 0; } private boolean isNavBarForciblyVisible() { final WindowState notificationShade = mPolicy.getNotificationShade(); if (notificationShade == null) { return false; } if ((notificationShade.mAttrs.privateFlags & PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION) != 0) { return true; } return false; private boolean forceShowsNavigationBarTransiently() { final WindowState win = mPolicy.getNotificationShade(); return win != null && (win.mAttrs.privateFlags & PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION) != 0; } private boolean areSystemBarsForciblyVisible() { private boolean forceShowsSystemBarsForWindowingMode() { final boolean isDockedStackVisible = mDisplayContent.isStackVisible(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY); final boolean isFreeformStackVisible = Loading @@ -279,7 +284,7 @@ class InsetsPolicy { for (int i = showingTransientTypes.size() - 1; i >= 0; i--) { InsetsSourceProvider provider = mStateController.getSourceProvider(showingTransientTypes.get(i)); InsetsSourceControl control = provider.getControl(mTransientControlTarget); InsetsSourceControl control = provider.getControl(mDummyControlTarget); if (control == null || control.getLeash() == null) { continue; } Loading Loading @@ -412,11 +417,4 @@ class InsetsPolicy { } } } private class TransientControlTarget implements InsetsControlTarget { @Override public void notifyInsetsControlChanged() { } } } services/core/java/com/android/server/wm/InsetsStateController.java +1 −2 Original line number Diff line number Diff line Loading @@ -61,8 +61,7 @@ class InsetsStateController { w.notifyInsetsChanged(); } }; private final InsetsControlTarget mEmptyImeControlTarget = () -> { }; private final InsetsControlTarget mEmptyImeControlTarget = new InsetsControlTarget() { }; InsetsStateController(DisplayContent displayContent) { mDisplayContent = displayContent; Loading services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java +4 −5 Original line number Diff line number Diff line Loading @@ -120,7 +120,6 @@ public class InsetsPolicyTest extends WindowTestsBase { assertNull(controls); } // TODO: adjust this test if we pretend to the app that it's still able to control it. @Test public void testControlsForDispatch_forceStatusBarVisible() { addWindow(TYPE_STATUS_BAR, "statusBar").mAttrs.privateFlags |= Loading @@ -129,9 +128,9 @@ public class InsetsPolicyTest extends WindowTestsBase { final InsetsSourceControl[] controls = addAppWindowAndGetControlsForDispatch(); // The app must not control the status bar. // The focused app window can control both system bars. assertNotNull(controls); assertEquals(1, controls.length); assertEquals(2, controls.length); } @Test Loading @@ -143,9 +142,9 @@ public class InsetsPolicyTest extends WindowTestsBase { final InsetsSourceControl[] controls = addAppWindowAndGetControlsForDispatch(); // The app must not control the navigation bar. // The focused app window can control both system bars. assertNotNull(controls); assertEquals(1, controls.length); assertEquals(2, controls.length); } @Test Loading Loading
core/java/android/view/InsetsState.java +14 −0 Original line number Diff line number Diff line Loading @@ -342,6 +342,20 @@ public class InsetsState implements Parcelable { } } /** * A shortcut for setting the visibility of the source. * * @param type The {@link InternalInsetsType} of the source to set the visibility * @param referenceState The {@link InsetsState} for reference */ public void setSourceVisible(@InternalInsetsType int type, InsetsState referenceState) { InsetsSource source = mSources.get(type); InsetsSource referenceSource = referenceState.mSources.get(type); if (source != null && referenceSource != null) { source.setVisible(referenceSource.isVisible()); } } public void set(InsetsState other) { set(other, false /* copySources */); } Loading
services/core/java/com/android/server/wm/InsetsControlTarget.java +6 −1 Original line number Diff line number Diff line Loading @@ -23,7 +23,12 @@ import android.view.WindowInsets.Type.InsetsType; * Generalization of an object that can control insets state. */ interface InsetsControlTarget { void notifyInsetsControlChanged(); /** * Notifies the control target that the insets control has changed. */ default void notifyInsetsControlChanged() { }; /** * @return {@link WindowState} of this target, if any. Loading
services/core/java/com/android/server/wm/InsetsPolicy.java +42 −44 Original line number Diff line number Diff line Loading @@ -57,9 +57,11 @@ class InsetsPolicy { private final InsetsStateController mStateController; private final DisplayContent mDisplayContent; private final DisplayPolicy mPolicy; private final TransientControlTarget mTransientControlTarget = new TransientControlTarget(); private final IntArray mShowingTransientTypes = new IntArray(); /** For resetting visibilities of insets sources. */ private final InsetsControlTarget mDummyControlTarget = new InsetsControlTarget() { }; private WindowState mFocusedWin; private BarWindow mStatusBar = new BarWindow(StatusBarManager.WINDOW_STATUS_BAR); private BarWindow mNavBar = new BarWindow(StatusBarManager.WINDOW_NAVIGATION_BAR); Loading Loading @@ -143,12 +145,15 @@ class InsetsPolicy { */ InsetsState getInsetsForDispatch(WindowState target) { InsetsState state = mStateController.getInsetsForDispatch(target); if (mShowingTransientTypes.size() == 0) { return state; } for (int i = mShowingTransientTypes.size() - 1; i >= 0; i--) { state.setSourceVisible(mShowingTransientTypes.get(i), false); } if (mFocusedWin != null && getStatusControlTarget(mFocusedWin) == mDummyControlTarget) { state.setSourceVisible(ITYPE_STATUS_BAR, mFocusedWin.getRequestedInsetsState()); } if (mFocusedWin != null && getNavControlTarget(mFocusedWin) == mDummyControlTarget) { state.setSourceVisible(ITYPE_NAVIGATION_BAR, mFocusedWin.getRequestedInsetsState()); } return state; } Loading Loading @@ -194,71 +199,71 @@ class InsetsPolicy { private @Nullable InsetsControlTarget getFakeStatusControlTarget( @Nullable WindowState focused) { if (mShowingTransientTypes.indexOf(ITYPE_STATUS_BAR) != -1) { return focused; } return null; return getStatusControlTarget(focused) == mDummyControlTarget ? focused : null; } private @Nullable InsetsControlTarget getFakeNavControlTarget(@Nullable WindowState focused) { if (mShowingTransientTypes.indexOf(ITYPE_NAVIGATION_BAR) != -1) { return focused; } return null; return getNavControlTarget(focused) == mDummyControlTarget ? focused : null; } private @Nullable InsetsControlTarget getStatusControlTarget(@Nullable WindowState focusedWin) { if (mShowingTransientTypes.indexOf(ITYPE_STATUS_BAR) != -1) { return mTransientControlTarget; return mDummyControlTarget; } if (focusedWin == mPolicy.getNotificationShade()) { // Notification shade has control anyways, no reason to force anything. return focusedWin; } if (areSystemBarsForciblyVisible() || isKeyguardOrStatusBarForciblyVisible()) { if (forceShowsSystemBarsForWindowingMode()) { // Status bar is forcibly shown for the windowing mode which is a steady state. // We don't want the client to control the status bar, and we will dispatch the real // visibility of status bar to the client. return null; } if (forceShowsStatusBarTransiently()) { // Status bar is forcibly shown transiently, and its new visibility won't be // dispatched to the client so that we can keep the layout stable. We will dispatch the // fake control to the client, so that it can re-show the bar during this scenario. return mDummyControlTarget; } return focusedWin; } private @Nullable InsetsControlTarget getNavControlTarget(@Nullable WindowState focusedWin) { if (mShowingTransientTypes.indexOf(ITYPE_NAVIGATION_BAR) != -1) { return mTransientControlTarget; return mDummyControlTarget; } if (focusedWin == mPolicy.getNotificationShade()) { // Notification shade has control anyways, no reason to force anything. return focusedWin; } if (areSystemBarsForciblyVisible() || isNavBarForciblyVisible()) { if (forceShowsSystemBarsForWindowingMode()) { // Navigation bar is forcibly shown for the windowing mode which is a steady state. // We don't want the client to control the navigation bar, and we will dispatch the real // visibility of navigation bar to the client. return null; } if (forceShowsNavigationBarTransiently()) { // Navigation bar is forcibly shown transiently, and its new visibility won't be // dispatched to the client so that we can keep the layout stable. We will dispatch the // fake control to the client, so that it can re-show the bar during this scenario. return mDummyControlTarget; } return focusedWin; } private boolean isKeyguardOrStatusBarForciblyVisible() { final WindowState statusBar = mPolicy.getStatusBar(); if (statusBar != null) { // TODO(b/118118435): Pretend to the app that it's still able to control it? if ((statusBar.mAttrs.privateFlags & PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR) != 0) { return true; } } return false; private boolean forceShowsStatusBarTransiently() { final WindowState win = mPolicy.getStatusBar(); return win != null && (win.mAttrs.privateFlags & PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR) != 0; } private boolean isNavBarForciblyVisible() { final WindowState notificationShade = mPolicy.getNotificationShade(); if (notificationShade == null) { return false; } if ((notificationShade.mAttrs.privateFlags & PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION) != 0) { return true; } return false; private boolean forceShowsNavigationBarTransiently() { final WindowState win = mPolicy.getNotificationShade(); return win != null && (win.mAttrs.privateFlags & PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION) != 0; } private boolean areSystemBarsForciblyVisible() { private boolean forceShowsSystemBarsForWindowingMode() { final boolean isDockedStackVisible = mDisplayContent.isStackVisible(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY); final boolean isFreeformStackVisible = Loading @@ -279,7 +284,7 @@ class InsetsPolicy { for (int i = showingTransientTypes.size() - 1; i >= 0; i--) { InsetsSourceProvider provider = mStateController.getSourceProvider(showingTransientTypes.get(i)); InsetsSourceControl control = provider.getControl(mTransientControlTarget); InsetsSourceControl control = provider.getControl(mDummyControlTarget); if (control == null || control.getLeash() == null) { continue; } Loading Loading @@ -412,11 +417,4 @@ class InsetsPolicy { } } } private class TransientControlTarget implements InsetsControlTarget { @Override public void notifyInsetsControlChanged() { } } }
services/core/java/com/android/server/wm/InsetsStateController.java +1 −2 Original line number Diff line number Diff line Loading @@ -61,8 +61,7 @@ class InsetsStateController { w.notifyInsetsChanged(); } }; private final InsetsControlTarget mEmptyImeControlTarget = () -> { }; private final InsetsControlTarget mEmptyImeControlTarget = new InsetsControlTarget() { }; InsetsStateController(DisplayContent displayContent) { mDisplayContent = displayContent; Loading
services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java +4 −5 Original line number Diff line number Diff line Loading @@ -120,7 +120,6 @@ public class InsetsPolicyTest extends WindowTestsBase { assertNull(controls); } // TODO: adjust this test if we pretend to the app that it's still able to control it. @Test public void testControlsForDispatch_forceStatusBarVisible() { addWindow(TYPE_STATUS_BAR, "statusBar").mAttrs.privateFlags |= Loading @@ -129,9 +128,9 @@ public class InsetsPolicyTest extends WindowTestsBase { final InsetsSourceControl[] controls = addAppWindowAndGetControlsForDispatch(); // The app must not control the status bar. // The focused app window can control both system bars. assertNotNull(controls); assertEquals(1, controls.length); assertEquals(2, controls.length); } @Test Loading @@ -143,9 +142,9 @@ public class InsetsPolicyTest extends WindowTestsBase { final InsetsSourceControl[] controls = addAppWindowAndGetControlsForDispatch(); // The app must not control the navigation bar. // The focused app window can control both system bars. assertNotNull(controls); assertEquals(1, controls.length); assertEquals(2, controls.length); } @Test Loading