Merge "Let top-fullscreen-app window keep controlling status bar" into rvc-dev

This commit is contained in:
Tiger Huang
2020-05-22 20:35:28 +00:00
committed by Android (Google) Code Review
3 changed files with 67 additions and 24 deletions

View File

@@ -2756,19 +2756,22 @@ public class DisplayPolicy {
* @return Whether the top app should hide the statusbar based on the top fullscreen opaque * @return Whether the top app should hide the statusbar based on the top fullscreen opaque
* window. * window.
*/ */
private boolean topAppHidesStatusBar() { boolean topAppHidesStatusBar() {
if (mTopFullscreenOpaqueWindowState == null || mForceShowSystemBars) { if (mTopFullscreenOpaqueWindowState == null || mForceShowSystemBars) {
return false; return false;
} }
final int fl = PolicyControl.getWindowFlags(null, final LayoutParams attrs = mTopFullscreenOpaqueWindowState.getAttrs();
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) { if (WindowManagerDebugConfig.DEBUG) {
Slog.d(TAG, "frame: " + mTopFullscreenOpaqueWindowState.getFrameLw()); Slog.d(TAG, "frame: " + mTopFullscreenOpaqueWindowState.getFrameLw());
Slog.d(TAG, "attr: " + mTopFullscreenOpaqueWindowState.getAttrs() Slog.d(TAG, "attr: " + attrs + " request: " + request);
+ " lp.flags=0x" + Integer.toHexString(fl));
} }
return (fl & LayoutParams.FLAG_FULLSCREEN) != 0 return (fl & LayoutParams.FLAG_FULLSCREEN) != 0
|| (mLastSystemUiFlags & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0; || (sysui & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0
|| (request != null && !request.isVisible());
} }
/** /**

View File

@@ -117,13 +117,8 @@ class InsetsPolicy {
if (ViewRootImpl.sNewInsetsMode != ViewRootImpl.NEW_INSETS_MODE_FULL) { if (ViewRootImpl.sNewInsetsMode != ViewRootImpl.NEW_INSETS_MODE_FULL) {
return; return;
} }
mStatusBar.setVisible(focusedWin == null mStatusBar.updateVisibility(getStatusControlTarget(focusedWin), ITYPE_STATUS_BAR);
|| focusedWin != getStatusControlTarget(focusedWin) mNavBar.updateVisibility(getNavControlTarget(focusedWin), ITYPE_NAVIGATION_BAR);
|| focusedWin.getRequestedInsetsState().getSource(ITYPE_STATUS_BAR).isVisible());
mNavBar.setVisible(focusedWin == null
|| focusedWin != getNavControlTarget(focusedWin)
|| focusedWin.getRequestedInsetsState().getSource(ITYPE_NAVIGATION_BAR)
.isVisible());
mPolicy.updateHideNavInputEventReceiver(); mPolicy.updateHideNavInputEventReceiver();
} }
@@ -215,16 +210,7 @@ class InsetsPolicy {
void onInsetsModified(WindowState windowState, InsetsState state) { void onInsetsModified(WindowState windowState, InsetsState state) {
mStateController.onInsetsModified(windowState, state); mStateController.onInsetsModified(windowState, state);
checkAbortTransient(windowState, state); checkAbortTransient(windowState, state);
if (ViewRootImpl.sNewInsetsMode != ViewRootImpl.NEW_INSETS_MODE_FULL) { updateBarControlTarget(mFocusedWin);
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();
} }
/** /**
@@ -248,7 +234,6 @@ class InsetsPolicy {
if (abortTypes.size() > 0) { if (abortTypes.size() > 0) {
mPolicy.getStatusBarManagerInternal().abortTransient(mDisplayContent.getDisplayId(), mPolicy.getStatusBarManagerInternal().abortTransient(mDisplayContent.getDisplayId(),
abortTypes.toArray()); abortTypes.toArray());
updateBarControlTarget(mFocusedWin);
} }
} }
} }
@@ -289,6 +274,11 @@ class InsetsPolicy {
// fake control to the client, so that it can re-show the bar during this scenario. // fake control to the client, so that it can re-show the bar during this scenario.
return mDummyControlTarget; 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; return focusedWin;
} }
@@ -378,6 +368,14 @@ class InsetsPolicy {
mId = id; 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) { private void setVisible(boolean visible) {
final int state = visible ? WINDOW_STATE_SHOWING : WINDOW_STATE_HIDDEN; final int state = visible ? WINDOW_STATE_SHOWING : WINDOW_STATE_HIDDEN;
if (mState != state) { if (mState != state) {

View File

@@ -21,6 +21,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY; import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.view.InsetsState.ITYPE_NAVIGATION_BAR; import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
import static android.view.InsetsState.ITYPE_STATUS_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.ViewRootImpl.NEW_INSETS_MODE_FULL;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR;
@@ -182,6 +183,47 @@ public class InsetsPolicyTest extends WindowTestsBase {
assertNull(controls); assertNull(controls);
} }
@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 @Test
public void testShowTransientBars_bothCanBeTransient_appGetsBothFakeControls() { public void testShowTransientBars_bothCanBeTransient_appGetsBothFakeControls() {
addNonFocusableWindow(TYPE_STATUS_BAR, "statusBar") addNonFocusableWindow(TYPE_STATUS_BAR, "statusBar")