Merge "Let top-fullscreen-app window keep controlling status bar" into rvc-dev
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index 2f18a0d..e244b55 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -2756,19 +2756,22 @@
* @return Whether the top app should hide the statusbar based on the top fullscreen opaque
* window.
*/
- private boolean topAppHidesStatusBar() {
+ boolean topAppHidesStatusBar() {
if (mTopFullscreenOpaqueWindowState == null || mForceShowSystemBars) {
return false;
}
- final int fl = PolicyControl.getWindowFlags(null,
- mTopFullscreenOpaqueWindowState.getAttrs());
+ final LayoutParams attrs = mTopFullscreenOpaqueWindowState.getAttrs();
+ final int fl = PolicyControl.getWindowFlags(null, attrs);
+ final int sysui = PolicyControl.getSystemUiVisibility(null, attrs);
+ final InsetsSource request = mTopFullscreenOpaqueWindowState.getRequestedInsetsState()
+ .peekSource(ITYPE_STATUS_BAR);
if (WindowManagerDebugConfig.DEBUG) {
Slog.d(TAG, "frame: " + mTopFullscreenOpaqueWindowState.getFrameLw());
- Slog.d(TAG, "attr: " + mTopFullscreenOpaqueWindowState.getAttrs()
- + " lp.flags=0x" + Integer.toHexString(fl));
+ Slog.d(TAG, "attr: " + attrs + " request: " + request);
}
return (fl & LayoutParams.FLAG_FULLSCREEN) != 0
- || (mLastSystemUiFlags & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0;
+ || (sysui & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0
+ || (request != null && !request.isVisible());
}
/**
diff --git a/services/core/java/com/android/server/wm/InsetsPolicy.java b/services/core/java/com/android/server/wm/InsetsPolicy.java
index d02be88..035f201 100644
--- a/services/core/java/com/android/server/wm/InsetsPolicy.java
+++ b/services/core/java/com/android/server/wm/InsetsPolicy.java
@@ -117,13 +117,8 @@
if (ViewRootImpl.sNewInsetsMode != ViewRootImpl.NEW_INSETS_MODE_FULL) {
return;
}
- mStatusBar.setVisible(focusedWin == null
- || focusedWin != getStatusControlTarget(focusedWin)
- || focusedWin.getRequestedInsetsState().getSource(ITYPE_STATUS_BAR).isVisible());
- mNavBar.setVisible(focusedWin == null
- || focusedWin != getNavControlTarget(focusedWin)
- || focusedWin.getRequestedInsetsState().getSource(ITYPE_NAVIGATION_BAR)
- .isVisible());
+ mStatusBar.updateVisibility(getStatusControlTarget(focusedWin), ITYPE_STATUS_BAR);
+ mNavBar.updateVisibility(getNavControlTarget(focusedWin), ITYPE_NAVIGATION_BAR);
mPolicy.updateHideNavInputEventReceiver();
}
@@ -215,16 +210,7 @@
void onInsetsModified(WindowState windowState, InsetsState state) {
mStateController.onInsetsModified(windowState, state);
checkAbortTransient(windowState, state);
- if (ViewRootImpl.sNewInsetsMode != ViewRootImpl.NEW_INSETS_MODE_FULL) {
- return;
- }
- if (windowState == getStatusControlTarget(mFocusedWin)) {
- mStatusBar.setVisible(state.getSource(ITYPE_STATUS_BAR).isVisible());
- }
- if (windowState == getNavControlTarget(mFocusedWin)) {
- mNavBar.setVisible(state.getSource(ITYPE_NAVIGATION_BAR).isVisible());
- }
- mPolicy.updateHideNavInputEventReceiver();
+ updateBarControlTarget(mFocusedWin);
}
/**
@@ -248,7 +234,6 @@
if (abortTypes.size() > 0) {
mPolicy.getStatusBarManagerInternal().abortTransient(mDisplayContent.getDisplayId(),
abortTypes.toArray());
- updateBarControlTarget(mFocusedWin);
}
}
}
@@ -289,6 +274,11 @@
// fake control to the client, so that it can re-show the bar during this scenario.
return mDummyControlTarget;
}
+ if (mPolicy.topAppHidesStatusBar()) {
+ // Non-fullscreen focused window should not break the state that the top-fullscreen-app
+ // window hides status bar.
+ return mPolicy.getTopFullscreenOpaqueWindow();
+ }
return focusedWin;
}
@@ -378,6 +368,14 @@
mId = id;
}
+ private void updateVisibility(InsetsControlTarget controlTarget,
+ @InternalInsetsType int type) {
+ final WindowState controllingWin =
+ controlTarget instanceof WindowState ? (WindowState) controlTarget : null;
+ setVisible(controllingWin == null
+ || controllingWin.getRequestedInsetsState().getSource(type).isVisible());
+ }
+
private void setVisible(boolean visible) {
final int state = visible ? WINDOW_STATE_SHOWING : WINDOW_STATE_HIDDEN;
if (mState != state) {
diff --git a/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java
index 2444c24..c794e1a 100644
--- a/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java
@@ -21,6 +21,7 @@
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
import static android.view.InsetsState.ITYPE_STATUS_BAR;
+import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
import static android.view.ViewRootImpl.NEW_INSETS_MODE_FULL;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR;
@@ -183,6 +184,47 @@
}
@Test
+ public void testControlsForDispatch_topAppHidesStatusBar() {
+ addWindow(TYPE_STATUS_BAR, "statusBar");
+ addWindow(TYPE_NAVIGATION_BAR, "navBar");
+
+ // Add a fullscreen (MATCH_PARENT x MATCH_PARENT) app window which hides status bar.
+ final WindowState fullscreenApp = addWindow(TYPE_APPLICATION, "fullscreenApp");
+ final InsetsState requestedState = new InsetsState();
+ requestedState.getSource(ITYPE_STATUS_BAR).setVisible(false);
+ fullscreenApp.updateRequestedInsetsState(requestedState);
+
+ // Add a non-fullscreen dialog window.
+ final WindowState dialog = addWindow(TYPE_APPLICATION, "dialog");
+ dialog.mAttrs.width = WRAP_CONTENT;
+ dialog.mAttrs.height = WRAP_CONTENT;
+
+ // Let fullscreenApp be mTopFullscreenOpaqueWindowState.
+ final DisplayPolicy displayPolicy = mDisplayContent.getDisplayPolicy();
+ displayPolicy.beginPostLayoutPolicyLw();
+ displayPolicy.applyPostLayoutPolicyLw(dialog, dialog.mAttrs, fullscreenApp, null);
+ displayPolicy.applyPostLayoutPolicyLw(fullscreenApp, fullscreenApp.mAttrs, null, null);
+ displayPolicy.finishPostLayoutPolicyLw();
+ mDisplayContent.getInsetsPolicy().updateBarControlTarget(dialog);
+
+ assertEquals(fullscreenApp, displayPolicy.getTopFullscreenOpaqueWindow());
+
+ // dialog is the focused window, but it can only control navigation bar.
+ final InsetsSourceControl[] dialogControls =
+ mDisplayContent.getInsetsStateController().getControlsForDispatch(dialog);
+ assertNotNull(dialogControls);
+ assertEquals(1, dialogControls.length);
+ assertEquals(ITYPE_NAVIGATION_BAR, dialogControls[0].getType());
+
+ // fullscreenApp is hiding status bar, and it can keep controlling status bar.
+ final InsetsSourceControl[] fullscreenAppControls =
+ mDisplayContent.getInsetsStateController().getControlsForDispatch(fullscreenApp);
+ assertNotNull(fullscreenAppControls);
+ assertEquals(1, fullscreenAppControls.length);
+ assertEquals(ITYPE_STATUS_BAR, fullscreenAppControls[0].getType());
+ }
+
+ @Test
public void testShowTransientBars_bothCanBeTransient_appGetsBothFakeControls() {
addNonFocusableWindow(TYPE_STATUS_BAR, "statusBar")
.getControllableInsetProvider().getSource().setVisible(false);