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
* 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());
}
/**

View File

@@ -117,13 +117,8 @@ class InsetsPolicy {
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 @@ class InsetsPolicy {
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 @@ class InsetsPolicy {
if (abortTypes.size() > 0) {
mPolicy.getStatusBarManagerInternal().abortTransient(mDisplayContent.getDisplayId(),
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.
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 @@ class InsetsPolicy {
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) {

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.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;
@@ -182,6 +183,47 @@ public class InsetsPolicyTest extends WindowTestsBase {
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
public void testShowTransientBars_bothCanBeTransient_appGetsBothFakeControls() {
addNonFocusableWindow(TYPE_STATUS_BAR, "statusBar")