Loading services/core/java/com/android/server/wm/InsetsPolicy.java +29 −5 Original line number Diff line number Diff line Loading @@ -36,6 +36,7 @@ import android.view.InsetsAnimationControlCallbacks; import android.view.InsetsAnimationControlImpl; import android.view.InsetsAnimationControlRunner; import android.view.InsetsController; import android.view.InsetsSource; import android.view.InsetsSourceControl; import android.view.InsetsState; import android.view.InsetsState.InternalInsetsType; Loading Loading @@ -212,11 +213,21 @@ class InsetsPolicy { * @see InsetsStateController#getInsetsForDispatch */ InsetsState getInsetsForDispatch(WindowState target) { InsetsState originalState = mStateController.getInsetsForDispatch(target); final InsetsState originalState = mStateController.getInsetsForDispatch(target); InsetsState state = originalState; for (int i = mShowingTransientTypes.size() - 1; i >= 0; i--) { state = new InsetsState(state); state.setSourceVisible(mShowingTransientTypes.get(i), false); final int type = mShowingTransientTypes.get(i); final InsetsSource originalSource = state.peekSource(type); if (originalSource != null && originalSource.isVisible()) { if (state == originalState) { // The source will be modified, create a non-deep copy to store the new one. state = new InsetsState(originalState); } // Replace the source with a copy in invisible state. final InsetsSource source = new InsetsSource(originalSource); source.setVisible(false); state.addSource(source); } } return state; } Loading Loading @@ -252,11 +263,14 @@ class InsetsPolicy { } } /** * If the caller is not {@link #updateBarControlTarget}, it should call * updateBarControlTarget(mFocusedWin) after this invocation. */ private void abortTransient() { mPolicy.getStatusBarManagerInternal().abortTransient(mDisplayContent.getDisplayId(), mShowingTransientTypes.toArray()); mShowingTransientTypes.clear(); updateBarControlTarget(mFocusedWin); } private @Nullable InsetsControlTarget getFakeControlTarget(@Nullable WindowState focused, Loading Loading @@ -290,7 +304,7 @@ class InsetsPolicy { // fake control to the client, so that it can re-show the bar during this scenario. return mDummyControlTarget; } if (mPolicy.topAppHidesStatusBar()) { if (!canBeTopFullscreenOpaqueWindow(focusedWin) && mPolicy.topAppHidesStatusBar()) { // Non-fullscreen focused window should not break the state that the top-fullscreen-app // window hides status bar. return mPolicy.getTopFullscreenOpaqueWindow(); Loading @@ -298,6 +312,16 @@ class InsetsPolicy { return focusedWin; } private static boolean canBeTopFullscreenOpaqueWindow(@Nullable WindowState win) { // The condition doesn't use WindowState#canAffectSystemUiFlags because the window may // haven't drawn or committed the visibility. final boolean nonAttachedAppWindow = win != null && win.mAttrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW && win.mAttrs.type <= WindowManager.LayoutParams.LAST_APPLICATION_WINDOW; return nonAttachedAppWindow && win.mAttrs.isFullscreen() && !win.isFullyTransparent() && !win.inMultiWindowMode(); } private @Nullable InsetsControlTarget getNavControlTarget(@Nullable WindowState focusedWin, boolean forceShowsSystemBarsForWindowingMode) { if (mShowingTransientTypes.indexOf(ITYPE_NAVIGATION_BAR) != -1) { Loading services/core/java/com/android/server/wm/TaskSnapshotController.java +1 −3 Original line number Diff line number Diff line Loading @@ -480,9 +480,7 @@ class TaskSnapshotController { final int color = ColorUtils.setAlphaComponent( task.getTaskDescription().getBackgroundColor(), 255); final LayoutParams attrs = mainWindow.getAttrs(); final InsetsPolicy insetsPolicy = mainWindow.getDisplayContent().getInsetsPolicy(); final InsetsState insetsState = new InsetsState(insetsPolicy.getInsetsForDispatch(mainWindow)); final InsetsState insetsState = new InsetsState(mainWindow.getInsetsState()); mergeInsetsSources(insetsState, mainWindow.getRequestedInsetsState()); final Rect systemBarInsets = getSystemBarInsets(mainWindow.getFrameLw(), insetsState); final SystemBarBackgroundPainter decorPainter = new SystemBarBackgroundPainter(attrs.flags, Loading services/core/java/com/android/server/wm/TaskSnapshotSurface.java +1 −5 Original line number Diff line number Diff line Loading @@ -245,11 +245,7 @@ class TaskSnapshotSurface implements StartingSurface { task.getBounds(taskBounds); currentOrientation = topFullscreenOpaqueWindow.getConfiguration().orientation; activityType = activity.getActivityType(); final InsetsPolicy insetsPolicy = topFullscreenOpaqueWindow.getDisplayContent() .getInsetsPolicy(); insetsState = new InsetsState(insetsPolicy.getInsetsForDispatch(topFullscreenOpaqueWindow)); insetsState = new InsetsState(topFullscreenOpaqueWindow.getInsetsState()); mergeInsetsSources(insetsState, topFullscreenOpaqueWindow.getRequestedInsetsState()); } try { Loading services/core/java/com/android/server/wm/WindowState.java +4 −0 Original line number Diff line number Diff line Loading @@ -1525,6 +1525,10 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP return getDisplayContent().getDisplayInfo(); } /** * Returns the insets state for the client. Its sources may be the copies with visibility * modification according to the state of transient bars. */ InsetsState getInsetsState() { return getDisplayContent().getInsetsPolicy().getInsetsForDispatch(this); } Loading services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java +31 −0 Original line number Diff line number Diff line Loading @@ -38,10 +38,13 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import android.app.StatusBarManager; import android.platform.test.annotations.Presubmit; import android.view.InsetsSourceControl; import android.view.InsetsState; Loading @@ -49,6 +52,8 @@ import android.view.test.InsetsModeSession; import androidx.test.filters.SmallTest; import com.android.server.statusbar.StatusBarManagerInternal; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; Loading Loading @@ -222,6 +227,23 @@ public class InsetsPolicyTest extends WindowTestsBase { assertNotNull(fullscreenAppControls); assertEquals(1, fullscreenAppControls.length); assertEquals(ITYPE_STATUS_BAR, fullscreenAppControls[0].getType()); // Assume mFocusedWindow is updated but mTopFullscreenOpaqueWindowState hasn't. final WindowState newFocusedFullscreenApp = addWindow(TYPE_APPLICATION, "newFullscreenApp"); final InsetsState newRequestedState = new InsetsState(); newRequestedState.getSource(ITYPE_STATUS_BAR).setVisible(true); newFocusedFullscreenApp.updateRequestedInsetsState(newRequestedState); // Make sure status bar is hidden by previous insets state. mDisplayContent.getInsetsPolicy().updateBarControlTarget(fullscreenApp); final StatusBarManagerInternal sbmi = mDisplayContent.getDisplayPolicy().getStatusBarManagerInternal(); clearInvocations(sbmi); mDisplayContent.getInsetsPolicy().updateBarControlTarget(newFocusedFullscreenApp); // The status bar should be shown by newFocusedFullscreenApp even // mTopFullscreenOpaqueWindowState is still fullscreenApp. verify(sbmi).setWindowState(mDisplayContent.mDisplayId, StatusBarManager.WINDOW_STATUS_BAR, StatusBarManager.WINDOW_STATE_SHOWING); } @Test Loading Loading @@ -309,6 +331,15 @@ public class InsetsPolicyTest extends WindowTestsBase { final InsetsState state = policy.getInsetsForDispatch(mAppWindow); state.setSourceVisible(ITYPE_STATUS_BAR, true); state.setSourceVisible(ITYPE_NAVIGATION_BAR, true); final InsetsState clientState = mAppWindow.getInsetsState(); // The transient bar states for client should be invisible. assertFalse(clientState.getSource(ITYPE_STATUS_BAR).isVisible()); assertFalse(clientState.getSource(ITYPE_NAVIGATION_BAR).isVisible()); // The original state shouldn't be modified. assertTrue(state.getSource(ITYPE_STATUS_BAR).isVisible()); assertTrue(state.getSource(ITYPE_NAVIGATION_BAR).isVisible()); policy.onInsetsModified(mAppWindow, state); waitUntilWindowAnimatorIdle(); Loading Loading
services/core/java/com/android/server/wm/InsetsPolicy.java +29 −5 Original line number Diff line number Diff line Loading @@ -36,6 +36,7 @@ import android.view.InsetsAnimationControlCallbacks; import android.view.InsetsAnimationControlImpl; import android.view.InsetsAnimationControlRunner; import android.view.InsetsController; import android.view.InsetsSource; import android.view.InsetsSourceControl; import android.view.InsetsState; import android.view.InsetsState.InternalInsetsType; Loading Loading @@ -212,11 +213,21 @@ class InsetsPolicy { * @see InsetsStateController#getInsetsForDispatch */ InsetsState getInsetsForDispatch(WindowState target) { InsetsState originalState = mStateController.getInsetsForDispatch(target); final InsetsState originalState = mStateController.getInsetsForDispatch(target); InsetsState state = originalState; for (int i = mShowingTransientTypes.size() - 1; i >= 0; i--) { state = new InsetsState(state); state.setSourceVisible(mShowingTransientTypes.get(i), false); final int type = mShowingTransientTypes.get(i); final InsetsSource originalSource = state.peekSource(type); if (originalSource != null && originalSource.isVisible()) { if (state == originalState) { // The source will be modified, create a non-deep copy to store the new one. state = new InsetsState(originalState); } // Replace the source with a copy in invisible state. final InsetsSource source = new InsetsSource(originalSource); source.setVisible(false); state.addSource(source); } } return state; } Loading Loading @@ -252,11 +263,14 @@ class InsetsPolicy { } } /** * If the caller is not {@link #updateBarControlTarget}, it should call * updateBarControlTarget(mFocusedWin) after this invocation. */ private void abortTransient() { mPolicy.getStatusBarManagerInternal().abortTransient(mDisplayContent.getDisplayId(), mShowingTransientTypes.toArray()); mShowingTransientTypes.clear(); updateBarControlTarget(mFocusedWin); } private @Nullable InsetsControlTarget getFakeControlTarget(@Nullable WindowState focused, Loading Loading @@ -290,7 +304,7 @@ class InsetsPolicy { // fake control to the client, so that it can re-show the bar during this scenario. return mDummyControlTarget; } if (mPolicy.topAppHidesStatusBar()) { if (!canBeTopFullscreenOpaqueWindow(focusedWin) && mPolicy.topAppHidesStatusBar()) { // Non-fullscreen focused window should not break the state that the top-fullscreen-app // window hides status bar. return mPolicy.getTopFullscreenOpaqueWindow(); Loading @@ -298,6 +312,16 @@ class InsetsPolicy { return focusedWin; } private static boolean canBeTopFullscreenOpaqueWindow(@Nullable WindowState win) { // The condition doesn't use WindowState#canAffectSystemUiFlags because the window may // haven't drawn or committed the visibility. final boolean nonAttachedAppWindow = win != null && win.mAttrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW && win.mAttrs.type <= WindowManager.LayoutParams.LAST_APPLICATION_WINDOW; return nonAttachedAppWindow && win.mAttrs.isFullscreen() && !win.isFullyTransparent() && !win.inMultiWindowMode(); } private @Nullable InsetsControlTarget getNavControlTarget(@Nullable WindowState focusedWin, boolean forceShowsSystemBarsForWindowingMode) { if (mShowingTransientTypes.indexOf(ITYPE_NAVIGATION_BAR) != -1) { Loading
services/core/java/com/android/server/wm/TaskSnapshotController.java +1 −3 Original line number Diff line number Diff line Loading @@ -480,9 +480,7 @@ class TaskSnapshotController { final int color = ColorUtils.setAlphaComponent( task.getTaskDescription().getBackgroundColor(), 255); final LayoutParams attrs = mainWindow.getAttrs(); final InsetsPolicy insetsPolicy = mainWindow.getDisplayContent().getInsetsPolicy(); final InsetsState insetsState = new InsetsState(insetsPolicy.getInsetsForDispatch(mainWindow)); final InsetsState insetsState = new InsetsState(mainWindow.getInsetsState()); mergeInsetsSources(insetsState, mainWindow.getRequestedInsetsState()); final Rect systemBarInsets = getSystemBarInsets(mainWindow.getFrameLw(), insetsState); final SystemBarBackgroundPainter decorPainter = new SystemBarBackgroundPainter(attrs.flags, Loading
services/core/java/com/android/server/wm/TaskSnapshotSurface.java +1 −5 Original line number Diff line number Diff line Loading @@ -245,11 +245,7 @@ class TaskSnapshotSurface implements StartingSurface { task.getBounds(taskBounds); currentOrientation = topFullscreenOpaqueWindow.getConfiguration().orientation; activityType = activity.getActivityType(); final InsetsPolicy insetsPolicy = topFullscreenOpaqueWindow.getDisplayContent() .getInsetsPolicy(); insetsState = new InsetsState(insetsPolicy.getInsetsForDispatch(topFullscreenOpaqueWindow)); insetsState = new InsetsState(topFullscreenOpaqueWindow.getInsetsState()); mergeInsetsSources(insetsState, topFullscreenOpaqueWindow.getRequestedInsetsState()); } try { Loading
services/core/java/com/android/server/wm/WindowState.java +4 −0 Original line number Diff line number Diff line Loading @@ -1525,6 +1525,10 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP return getDisplayContent().getDisplayInfo(); } /** * Returns the insets state for the client. Its sources may be the copies with visibility * modification according to the state of transient bars. */ InsetsState getInsetsState() { return getDisplayContent().getInsetsPolicy().getInsetsForDispatch(this); } Loading
services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java +31 −0 Original line number Diff line number Diff line Loading @@ -38,10 +38,13 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import android.app.StatusBarManager; import android.platform.test.annotations.Presubmit; import android.view.InsetsSourceControl; import android.view.InsetsState; Loading @@ -49,6 +52,8 @@ import android.view.test.InsetsModeSession; import androidx.test.filters.SmallTest; import com.android.server.statusbar.StatusBarManagerInternal; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; Loading Loading @@ -222,6 +227,23 @@ public class InsetsPolicyTest extends WindowTestsBase { assertNotNull(fullscreenAppControls); assertEquals(1, fullscreenAppControls.length); assertEquals(ITYPE_STATUS_BAR, fullscreenAppControls[0].getType()); // Assume mFocusedWindow is updated but mTopFullscreenOpaqueWindowState hasn't. final WindowState newFocusedFullscreenApp = addWindow(TYPE_APPLICATION, "newFullscreenApp"); final InsetsState newRequestedState = new InsetsState(); newRequestedState.getSource(ITYPE_STATUS_BAR).setVisible(true); newFocusedFullscreenApp.updateRequestedInsetsState(newRequestedState); // Make sure status bar is hidden by previous insets state. mDisplayContent.getInsetsPolicy().updateBarControlTarget(fullscreenApp); final StatusBarManagerInternal sbmi = mDisplayContent.getDisplayPolicy().getStatusBarManagerInternal(); clearInvocations(sbmi); mDisplayContent.getInsetsPolicy().updateBarControlTarget(newFocusedFullscreenApp); // The status bar should be shown by newFocusedFullscreenApp even // mTopFullscreenOpaqueWindowState is still fullscreenApp. verify(sbmi).setWindowState(mDisplayContent.mDisplayId, StatusBarManager.WINDOW_STATUS_BAR, StatusBarManager.WINDOW_STATE_SHOWING); } @Test Loading Loading @@ -309,6 +331,15 @@ public class InsetsPolicyTest extends WindowTestsBase { final InsetsState state = policy.getInsetsForDispatch(mAppWindow); state.setSourceVisible(ITYPE_STATUS_BAR, true); state.setSourceVisible(ITYPE_NAVIGATION_BAR, true); final InsetsState clientState = mAppWindow.getInsetsState(); // The transient bar states for client should be invisible. assertFalse(clientState.getSource(ITYPE_STATUS_BAR).isVisible()); assertFalse(clientState.getSource(ITYPE_NAVIGATION_BAR).isVisible()); // The original state shouldn't be modified. assertTrue(state.getSource(ITYPE_STATUS_BAR).isVisible()); assertTrue(state.getSource(ITYPE_NAVIGATION_BAR).isVisible()); policy.onInsetsModified(mAppWindow, state); waitUntilWindowAnimatorIdle(); Loading