Loading services/core/java/com/android/server/wm/InsetsPolicy.java +54 −26 Original line number Diff line number Diff line Loading @@ -75,6 +75,18 @@ class InsetsPolicy { /** Used to show system bars permanently. This will affect the layout. */ private final InsetsControlTarget mPermanentControlTarget; /** * Used to override the visibility of {@link Type#statusBars()} when dispatching insets to * clients. */ private InsetsControlTarget mFakeStatusControlTarget; /** * Used to override the visibility of {@link Type#navigationBars()} when dispatching insets to * clients. */ private InsetsControlTarget mFakeNavControlTarget; private WindowState mFocusedWin; private final BarWindow mStatusBar = new BarWindow(StatusBarManager.WINDOW_STATUS_BAR); private final BarWindow mNavBar = new BarWindow(StatusBarManager.WINDOW_NAVIGATION_BAR); Loading @@ -101,25 +113,25 @@ class InsetsPolicy { abortTransient(); } mFocusedWin = focusedWin; final InsetsControlTarget statusControlTarget = getStatusControlTarget(focusedWin, false /* fake */); final InsetsControlTarget navControlTarget = getNavControlTarget(focusedWin, false /* fake */); final WindowState notificationShade = mPolicy.getNotificationShade(); final WindowState topApp = mPolicy.getTopFullscreenOpaqueWindow(); mStateController.onBarControlTargetChanged( statusControlTarget, statusControlTarget == mTransientControlTarget final InsetsControlTarget statusControlTarget = getStatusControlTarget(focusedWin, false /* fake */); mFakeStatusControlTarget = statusControlTarget == mTransientControlTarget ? getStatusControlTarget(focusedWin, true /* fake */) : statusControlTarget == notificationShade ? getStatusControlTarget(topApp, true /* fake */) : null, navControlTarget, navControlTarget == mTransientControlTarget : null; final InsetsControlTarget navControlTarget = getNavControlTarget(focusedWin, false /* fake */); mFakeNavControlTarget = navControlTarget == mTransientControlTarget ? getNavControlTarget(focusedWin, true /* fake */) : navControlTarget == notificationShade ? getNavControlTarget(topApp, true /* fake */) : null); : null; mStateController.onBarControlTargetChanged( statusControlTarget, mFakeStatusControlTarget, navControlTarget, mFakeNavControlTarget); mStatusBar.updateVisibility(statusControlTarget, Type.statusBars()); mNavBar.updateVisibility(navControlTarget, Type.navigationBars()); } Loading Loading @@ -204,7 +216,7 @@ class InsetsPolicy { boolean includesTransient) { InsetsState state; if (!includesTransient) { state = adjustVisibilityForTransientTypes(originalState); state = adjustVisibilityForFakeControllingSources(originalState); } else { state = originalState; } Loading Loading @@ -319,21 +331,37 @@ class InsetsPolicy { return state; } private InsetsState adjustVisibilityForTransientTypes(InsetsState originalState) { private InsetsState adjustVisibilityForFakeControllingSources(InsetsState originalState) { if (mFakeStatusControlTarget == null && mFakeNavControlTarget == null) { return originalState; } InsetsState state = originalState; for (int i = state.sourceSize() - 1; i >= 0; i--) { final InsetsSource source = state.sourceAt(i); if (isTransient(source.getType()) && source.isVisible()) { if (state == originalState) { // The source will be modified, create a non-deep copy to store the new one. state = new InsetsState(originalState); state = adjustVisibilityForFakeControllingSource(state, Type.statusBars(), source, mFakeStatusControlTarget); state = adjustVisibilityForFakeControllingSource(state, Type.navigationBars(), source, mFakeNavControlTarget); } // Replace the source with a copy in invisible state. final InsetsSource outSource = new InsetsSource(source); outSource.setVisible(false); state.addSource(outSource); return state; } private static InsetsState adjustVisibilityForFakeControllingSource(InsetsState originalState, @InsetsType int type, InsetsSource source, InsetsControlTarget target) { if (source.getType() != type || target == null) { return originalState; } final boolean isRequestedVisible = target.isRequestedVisible(type); if (source.isVisible() == isRequestedVisible) { return originalState; } // The source will be modified, create a non-deep copy to store the new one. final InsetsState state = new InsetsState(originalState); // Replace the source with a copy with the overridden visibility. final InsetsSource outSource = new InsetsSource(source); outSource.setVisible(isRequestedVisible); state.addSource(outSource); return state; } Loading services/core/java/com/android/server/wm/Session.java +1 −1 Original line number Diff line number Diff line Loading @@ -108,7 +108,7 @@ class Session extends IWindowSession.Stub implements IBinder.DeathRecipient { private final ArraySet<WindowSurfaceController> mAlertWindowSurfaces = new ArraySet<>(); private final DragDropController mDragDropController; final boolean mCanAddInternalSystemWindow; final boolean mCanForceShowingInsets; boolean mCanForceShowingInsets; private final boolean mCanStartTasksFromRecents; final boolean mCanCreateSystemApplicationOverlay; Loading services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java +45 −0 Original line number Diff line number Diff line Loading @@ -327,6 +327,7 @@ public class InsetsPolicyTest extends WindowTestsBase { addNavigationBar().getControllableInsetProvider().getSource(); statusBarSource.setVisible(false); navBarSource.setVisible(false); mAppWindow.setRequestedVisibleTypes(0, navigationBars() | statusBars()); mAppWindow.mAboveInsetsState.addSource(navBarSource); mAppWindow.mAboveInsetsState.addSource(statusBarSource); final InsetsPolicy policy = mDisplayContent.getInsetsPolicy(); Loading Loading @@ -387,6 +388,50 @@ public class InsetsPolicyTest extends WindowTestsBase { assertFalse(policy.isTransient(navigationBars())); } @Test public void testFakeControlTarget_overrideVisibilityReceivedByWindows() { final WindowState statusBar = addStatusBar(); final InsetsSourceProvider statusBarProvider = statusBar.getControllableInsetProvider(); statusBar.mSession.mCanForceShowingInsets = true; statusBar.setHasSurface(true); statusBarProvider.setServerVisible(true); final InsetsSource statusBarSource = statusBarProvider.getSource(); final int statusBarId = statusBarSource.getId(); assertTrue(statusBarSource.isVisible()); final WindowState app1 = addWindow(TYPE_APPLICATION, "app1"); app1.mAboveInsetsState.addSource(statusBarSource); assertTrue(app1.getInsetsState().peekSource(statusBarId).isVisible()); final WindowState app2 = addWindow(TYPE_APPLICATION, "app2"); app2.mAboveInsetsState.addSource(statusBarSource); assertTrue(app2.getInsetsState().peekSource(statusBarId).isVisible()); app2.setRequestedVisibleTypes(0, navigationBars() | statusBars()); mDisplayContent.getInsetsPolicy().updateBarControlTarget(app2); waitUntilWindowAnimatorIdle(); // app2 is the real control target now. It can override the visibility of all sources that // it controls. assertFalse(statusBarSource.isVisible()); assertFalse(app1.getInsetsState().peekSource(statusBarId).isVisible()); assertFalse(app2.getInsetsState().peekSource(statusBarId).isVisible()); statusBar.mAttrs.forciblyShownTypes = statusBars(); mDisplayContent.getDisplayPolicy().applyPostLayoutPolicyLw( statusBar, statusBar.mAttrs, null, null); mDisplayContent.getInsetsPolicy().updateBarControlTarget(app2); waitUntilWindowAnimatorIdle(); // app2 is the fake control target now. It can only override the visibility of sources // received by windows, but not the raw source. assertTrue(statusBarSource.isVisible()); assertFalse(app1.getInsetsState().peekSource(statusBarId).isVisible()); assertFalse(app2.getInsetsState().peekSource(statusBarId).isVisible()); } private WindowState addNavigationBar() { final Binder owner = new Binder(); final WindowState win = createWindow(null, TYPE_NAVIGATION_BAR, "navBar"); Loading services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java +3 −1 Original line number Diff line number Diff line Loading @@ -367,9 +367,11 @@ public class InsetsStateControllerTest extends WindowTestsBase { doReturn(rotatedState).when(app.mToken).getFixedRotationTransformInsetsState(); assertTrue(rotatedState.isSourceOrDefaultVisible(ID_STATUS_BAR, statusBars())); provider.getSource().setVisible(false); app.setRequestedVisibleTypes(0, statusBars()); mDisplayContent.getInsetsPolicy().updateBarControlTarget(app); mDisplayContent.getInsetsPolicy().showTransient(statusBars(), true /* isGestureOnSystemBar */); waitUntilWindowAnimatorIdle(); assertTrue(mDisplayContent.getInsetsPolicy().isTransient(statusBars())); assertFalse(app.getInsetsState().isSourceOrDefaultVisible(ID_STATUS_BAR, statusBars())); Loading Loading
services/core/java/com/android/server/wm/InsetsPolicy.java +54 −26 Original line number Diff line number Diff line Loading @@ -75,6 +75,18 @@ class InsetsPolicy { /** Used to show system bars permanently. This will affect the layout. */ private final InsetsControlTarget mPermanentControlTarget; /** * Used to override the visibility of {@link Type#statusBars()} when dispatching insets to * clients. */ private InsetsControlTarget mFakeStatusControlTarget; /** * Used to override the visibility of {@link Type#navigationBars()} when dispatching insets to * clients. */ private InsetsControlTarget mFakeNavControlTarget; private WindowState mFocusedWin; private final BarWindow mStatusBar = new BarWindow(StatusBarManager.WINDOW_STATUS_BAR); private final BarWindow mNavBar = new BarWindow(StatusBarManager.WINDOW_NAVIGATION_BAR); Loading @@ -101,25 +113,25 @@ class InsetsPolicy { abortTransient(); } mFocusedWin = focusedWin; final InsetsControlTarget statusControlTarget = getStatusControlTarget(focusedWin, false /* fake */); final InsetsControlTarget navControlTarget = getNavControlTarget(focusedWin, false /* fake */); final WindowState notificationShade = mPolicy.getNotificationShade(); final WindowState topApp = mPolicy.getTopFullscreenOpaqueWindow(); mStateController.onBarControlTargetChanged( statusControlTarget, statusControlTarget == mTransientControlTarget final InsetsControlTarget statusControlTarget = getStatusControlTarget(focusedWin, false /* fake */); mFakeStatusControlTarget = statusControlTarget == mTransientControlTarget ? getStatusControlTarget(focusedWin, true /* fake */) : statusControlTarget == notificationShade ? getStatusControlTarget(topApp, true /* fake */) : null, navControlTarget, navControlTarget == mTransientControlTarget : null; final InsetsControlTarget navControlTarget = getNavControlTarget(focusedWin, false /* fake */); mFakeNavControlTarget = navControlTarget == mTransientControlTarget ? getNavControlTarget(focusedWin, true /* fake */) : navControlTarget == notificationShade ? getNavControlTarget(topApp, true /* fake */) : null); : null; mStateController.onBarControlTargetChanged( statusControlTarget, mFakeStatusControlTarget, navControlTarget, mFakeNavControlTarget); mStatusBar.updateVisibility(statusControlTarget, Type.statusBars()); mNavBar.updateVisibility(navControlTarget, Type.navigationBars()); } Loading Loading @@ -204,7 +216,7 @@ class InsetsPolicy { boolean includesTransient) { InsetsState state; if (!includesTransient) { state = adjustVisibilityForTransientTypes(originalState); state = adjustVisibilityForFakeControllingSources(originalState); } else { state = originalState; } Loading Loading @@ -319,21 +331,37 @@ class InsetsPolicy { return state; } private InsetsState adjustVisibilityForTransientTypes(InsetsState originalState) { private InsetsState adjustVisibilityForFakeControllingSources(InsetsState originalState) { if (mFakeStatusControlTarget == null && mFakeNavControlTarget == null) { return originalState; } InsetsState state = originalState; for (int i = state.sourceSize() - 1; i >= 0; i--) { final InsetsSource source = state.sourceAt(i); if (isTransient(source.getType()) && source.isVisible()) { if (state == originalState) { // The source will be modified, create a non-deep copy to store the new one. state = new InsetsState(originalState); state = adjustVisibilityForFakeControllingSource(state, Type.statusBars(), source, mFakeStatusControlTarget); state = adjustVisibilityForFakeControllingSource(state, Type.navigationBars(), source, mFakeNavControlTarget); } // Replace the source with a copy in invisible state. final InsetsSource outSource = new InsetsSource(source); outSource.setVisible(false); state.addSource(outSource); return state; } private static InsetsState adjustVisibilityForFakeControllingSource(InsetsState originalState, @InsetsType int type, InsetsSource source, InsetsControlTarget target) { if (source.getType() != type || target == null) { return originalState; } final boolean isRequestedVisible = target.isRequestedVisible(type); if (source.isVisible() == isRequestedVisible) { return originalState; } // The source will be modified, create a non-deep copy to store the new one. final InsetsState state = new InsetsState(originalState); // Replace the source with a copy with the overridden visibility. final InsetsSource outSource = new InsetsSource(source); outSource.setVisible(isRequestedVisible); state.addSource(outSource); return state; } Loading
services/core/java/com/android/server/wm/Session.java +1 −1 Original line number Diff line number Diff line Loading @@ -108,7 +108,7 @@ class Session extends IWindowSession.Stub implements IBinder.DeathRecipient { private final ArraySet<WindowSurfaceController> mAlertWindowSurfaces = new ArraySet<>(); private final DragDropController mDragDropController; final boolean mCanAddInternalSystemWindow; final boolean mCanForceShowingInsets; boolean mCanForceShowingInsets; private final boolean mCanStartTasksFromRecents; final boolean mCanCreateSystemApplicationOverlay; Loading
services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java +45 −0 Original line number Diff line number Diff line Loading @@ -327,6 +327,7 @@ public class InsetsPolicyTest extends WindowTestsBase { addNavigationBar().getControllableInsetProvider().getSource(); statusBarSource.setVisible(false); navBarSource.setVisible(false); mAppWindow.setRequestedVisibleTypes(0, navigationBars() | statusBars()); mAppWindow.mAboveInsetsState.addSource(navBarSource); mAppWindow.mAboveInsetsState.addSource(statusBarSource); final InsetsPolicy policy = mDisplayContent.getInsetsPolicy(); Loading Loading @@ -387,6 +388,50 @@ public class InsetsPolicyTest extends WindowTestsBase { assertFalse(policy.isTransient(navigationBars())); } @Test public void testFakeControlTarget_overrideVisibilityReceivedByWindows() { final WindowState statusBar = addStatusBar(); final InsetsSourceProvider statusBarProvider = statusBar.getControllableInsetProvider(); statusBar.mSession.mCanForceShowingInsets = true; statusBar.setHasSurface(true); statusBarProvider.setServerVisible(true); final InsetsSource statusBarSource = statusBarProvider.getSource(); final int statusBarId = statusBarSource.getId(); assertTrue(statusBarSource.isVisible()); final WindowState app1 = addWindow(TYPE_APPLICATION, "app1"); app1.mAboveInsetsState.addSource(statusBarSource); assertTrue(app1.getInsetsState().peekSource(statusBarId).isVisible()); final WindowState app2 = addWindow(TYPE_APPLICATION, "app2"); app2.mAboveInsetsState.addSource(statusBarSource); assertTrue(app2.getInsetsState().peekSource(statusBarId).isVisible()); app2.setRequestedVisibleTypes(0, navigationBars() | statusBars()); mDisplayContent.getInsetsPolicy().updateBarControlTarget(app2); waitUntilWindowAnimatorIdle(); // app2 is the real control target now. It can override the visibility of all sources that // it controls. assertFalse(statusBarSource.isVisible()); assertFalse(app1.getInsetsState().peekSource(statusBarId).isVisible()); assertFalse(app2.getInsetsState().peekSource(statusBarId).isVisible()); statusBar.mAttrs.forciblyShownTypes = statusBars(); mDisplayContent.getDisplayPolicy().applyPostLayoutPolicyLw( statusBar, statusBar.mAttrs, null, null); mDisplayContent.getInsetsPolicy().updateBarControlTarget(app2); waitUntilWindowAnimatorIdle(); // app2 is the fake control target now. It can only override the visibility of sources // received by windows, but not the raw source. assertTrue(statusBarSource.isVisible()); assertFalse(app1.getInsetsState().peekSource(statusBarId).isVisible()); assertFalse(app2.getInsetsState().peekSource(statusBarId).isVisible()); } private WindowState addNavigationBar() { final Binder owner = new Binder(); final WindowState win = createWindow(null, TYPE_NAVIGATION_BAR, "navBar"); Loading
services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java +3 −1 Original line number Diff line number Diff line Loading @@ -367,9 +367,11 @@ public class InsetsStateControllerTest extends WindowTestsBase { doReturn(rotatedState).when(app.mToken).getFixedRotationTransformInsetsState(); assertTrue(rotatedState.isSourceOrDefaultVisible(ID_STATUS_BAR, statusBars())); provider.getSource().setVisible(false); app.setRequestedVisibleTypes(0, statusBars()); mDisplayContent.getInsetsPolicy().updateBarControlTarget(app); mDisplayContent.getInsetsPolicy().showTransient(statusBars(), true /* isGestureOnSystemBar */); waitUntilWindowAnimatorIdle(); assertTrue(mDisplayContent.getInsetsPolicy().isTransient(statusBars())); assertFalse(app.getInsetsState().isSourceOrDefaultVisible(ID_STATUS_BAR, statusBars())); Loading