Merge "Prevent causing insets if the system bar is shown forcibly" into rvc-dev
This commit is contained in:
@@ -342,6 +342,20 @@ public class InsetsState implements Parcelable {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A shortcut for setting the visibility of the source.
|
||||
*
|
||||
* @param type The {@link InternalInsetsType} of the source to set the visibility
|
||||
* @param referenceState The {@link InsetsState} for reference
|
||||
*/
|
||||
public void setSourceVisible(@InternalInsetsType int type, InsetsState referenceState) {
|
||||
InsetsSource source = mSources.get(type);
|
||||
InsetsSource referenceSource = referenceState.mSources.get(type);
|
||||
if (source != null && referenceSource != null) {
|
||||
source.setVisible(referenceSource.isVisible());
|
||||
}
|
||||
}
|
||||
|
||||
public void set(InsetsState other) {
|
||||
set(other, false /* copySources */);
|
||||
}
|
||||
|
||||
@@ -23,7 +23,12 @@ import android.view.WindowInsets.Type.InsetsType;
|
||||
* Generalization of an object that can control insets state.
|
||||
*/
|
||||
interface InsetsControlTarget {
|
||||
void notifyInsetsControlChanged();
|
||||
|
||||
/**
|
||||
* Notifies the control target that the insets control has changed.
|
||||
*/
|
||||
default void notifyInsetsControlChanged() {
|
||||
};
|
||||
|
||||
/**
|
||||
* @return {@link WindowState} of this target, if any.
|
||||
|
||||
@@ -57,9 +57,11 @@ class InsetsPolicy {
|
||||
private final InsetsStateController mStateController;
|
||||
private final DisplayContent mDisplayContent;
|
||||
private final DisplayPolicy mPolicy;
|
||||
private final TransientControlTarget mTransientControlTarget = new TransientControlTarget();
|
||||
private final IntArray mShowingTransientTypes = new IntArray();
|
||||
|
||||
/** For resetting visibilities of insets sources. */
|
||||
private final InsetsControlTarget mDummyControlTarget = new InsetsControlTarget() { };
|
||||
|
||||
private WindowState mFocusedWin;
|
||||
private BarWindow mStatusBar = new BarWindow(StatusBarManager.WINDOW_STATUS_BAR);
|
||||
private BarWindow mNavBar = new BarWindow(StatusBarManager.WINDOW_NAVIGATION_BAR);
|
||||
@@ -143,12 +145,15 @@ class InsetsPolicy {
|
||||
*/
|
||||
InsetsState getInsetsForDispatch(WindowState target) {
|
||||
InsetsState state = mStateController.getInsetsForDispatch(target);
|
||||
if (mShowingTransientTypes.size() == 0) {
|
||||
return state;
|
||||
}
|
||||
for (int i = mShowingTransientTypes.size() - 1; i >= 0; i--) {
|
||||
state.setSourceVisible(mShowingTransientTypes.get(i), false);
|
||||
}
|
||||
if (mFocusedWin != null && getStatusControlTarget(mFocusedWin) == mDummyControlTarget) {
|
||||
state.setSourceVisible(ITYPE_STATUS_BAR, mFocusedWin.getRequestedInsetsState());
|
||||
}
|
||||
if (mFocusedWin != null && getNavControlTarget(mFocusedWin) == mDummyControlTarget) {
|
||||
state.setSourceVisible(ITYPE_NAVIGATION_BAR, mFocusedWin.getRequestedInsetsState());
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
@@ -194,71 +199,71 @@ class InsetsPolicy {
|
||||
|
||||
private @Nullable InsetsControlTarget getFakeStatusControlTarget(
|
||||
@Nullable WindowState focused) {
|
||||
if (mShowingTransientTypes.indexOf(ITYPE_STATUS_BAR) != -1) {
|
||||
return focused;
|
||||
}
|
||||
return null;
|
||||
return getStatusControlTarget(focused) == mDummyControlTarget ? focused : null;
|
||||
}
|
||||
|
||||
private @Nullable InsetsControlTarget getFakeNavControlTarget(@Nullable WindowState focused) {
|
||||
if (mShowingTransientTypes.indexOf(ITYPE_NAVIGATION_BAR) != -1) {
|
||||
return focused;
|
||||
}
|
||||
return null;
|
||||
return getNavControlTarget(focused) == mDummyControlTarget ? focused : null;
|
||||
}
|
||||
|
||||
private @Nullable InsetsControlTarget getStatusControlTarget(@Nullable WindowState focusedWin) {
|
||||
if (mShowingTransientTypes.indexOf(ITYPE_STATUS_BAR) != -1) {
|
||||
return mTransientControlTarget;
|
||||
return mDummyControlTarget;
|
||||
}
|
||||
if (focusedWin == mPolicy.getNotificationShade()) {
|
||||
// Notification shade has control anyways, no reason to force anything.
|
||||
return focusedWin;
|
||||
}
|
||||
if (areSystemBarsForciblyVisible() || isKeyguardOrStatusBarForciblyVisible()) {
|
||||
if (forceShowsSystemBarsForWindowingMode()) {
|
||||
// Status bar is forcibly shown for the windowing mode which is a steady state.
|
||||
// We don't want the client to control the status bar, and we will dispatch the real
|
||||
// visibility of status bar to the client.
|
||||
return null;
|
||||
}
|
||||
if (forceShowsStatusBarTransiently()) {
|
||||
// Status bar is forcibly shown transiently, and its new visibility won't be
|
||||
// dispatched to the client so that we can keep the layout stable. We will dispatch the
|
||||
// fake control to the client, so that it can re-show the bar during this scenario.
|
||||
return mDummyControlTarget;
|
||||
}
|
||||
return focusedWin;
|
||||
}
|
||||
|
||||
private @Nullable InsetsControlTarget getNavControlTarget(@Nullable WindowState focusedWin) {
|
||||
if (mShowingTransientTypes.indexOf(ITYPE_NAVIGATION_BAR) != -1) {
|
||||
return mTransientControlTarget;
|
||||
return mDummyControlTarget;
|
||||
}
|
||||
if (focusedWin == mPolicy.getNotificationShade()) {
|
||||
// Notification shade has control anyways, no reason to force anything.
|
||||
return focusedWin;
|
||||
}
|
||||
if (areSystemBarsForciblyVisible() || isNavBarForciblyVisible()) {
|
||||
if (forceShowsSystemBarsForWindowingMode()) {
|
||||
// Navigation bar is forcibly shown for the windowing mode which is a steady state.
|
||||
// We don't want the client to control the navigation bar, and we will dispatch the real
|
||||
// visibility of navigation bar to the client.
|
||||
return null;
|
||||
}
|
||||
if (forceShowsNavigationBarTransiently()) {
|
||||
// Navigation bar is forcibly shown transiently, and its new visibility won't be
|
||||
// dispatched to the client so that we can keep the layout stable. We will dispatch the
|
||||
// fake control to the client, so that it can re-show the bar during this scenario.
|
||||
return mDummyControlTarget;
|
||||
}
|
||||
return focusedWin;
|
||||
}
|
||||
|
||||
private boolean isKeyguardOrStatusBarForciblyVisible() {
|
||||
final WindowState statusBar = mPolicy.getStatusBar();
|
||||
if (statusBar != null) {
|
||||
// TODO(b/118118435): Pretend to the app that it's still able to control it?
|
||||
if ((statusBar.mAttrs.privateFlags & PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR) != 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
private boolean forceShowsStatusBarTransiently() {
|
||||
final WindowState win = mPolicy.getStatusBar();
|
||||
return win != null && (win.mAttrs.privateFlags & PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR) != 0;
|
||||
}
|
||||
|
||||
private boolean isNavBarForciblyVisible() {
|
||||
final WindowState notificationShade = mPolicy.getNotificationShade();
|
||||
if (notificationShade == null) {
|
||||
return false;
|
||||
}
|
||||
if ((notificationShade.mAttrs.privateFlags
|
||||
& PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION) != 0) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
private boolean forceShowsNavigationBarTransiently() {
|
||||
final WindowState win = mPolicy.getNotificationShade();
|
||||
return win != null
|
||||
&& (win.mAttrs.privateFlags & PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION) != 0;
|
||||
}
|
||||
|
||||
private boolean areSystemBarsForciblyVisible() {
|
||||
private boolean forceShowsSystemBarsForWindowingMode() {
|
||||
final boolean isDockedStackVisible =
|
||||
mDisplayContent.isStackVisible(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
|
||||
final boolean isFreeformStackVisible =
|
||||
@@ -279,7 +284,7 @@ class InsetsPolicy {
|
||||
for (int i = showingTransientTypes.size() - 1; i >= 0; i--) {
|
||||
InsetsSourceProvider provider =
|
||||
mStateController.getSourceProvider(showingTransientTypes.get(i));
|
||||
InsetsSourceControl control = provider.getControl(mTransientControlTarget);
|
||||
InsetsSourceControl control = provider.getControl(mDummyControlTarget);
|
||||
if (control == null || control.getLeash() == null) {
|
||||
continue;
|
||||
}
|
||||
@@ -412,11 +417,4 @@ class InsetsPolicy {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class TransientControlTarget implements InsetsControlTarget {
|
||||
|
||||
@Override
|
||||
public void notifyInsetsControlChanged() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,8 +61,7 @@ class InsetsStateController {
|
||||
w.notifyInsetsChanged();
|
||||
}
|
||||
};
|
||||
private final InsetsControlTarget mEmptyImeControlTarget = () -> {
|
||||
};
|
||||
private final InsetsControlTarget mEmptyImeControlTarget = new InsetsControlTarget() { };
|
||||
|
||||
InsetsStateController(DisplayContent displayContent) {
|
||||
mDisplayContent = displayContent;
|
||||
|
||||
@@ -120,7 +120,6 @@ public class InsetsPolicyTest extends WindowTestsBase {
|
||||
assertNull(controls);
|
||||
}
|
||||
|
||||
// TODO: adjust this test if we pretend to the app that it's still able to control it.
|
||||
@Test
|
||||
public void testControlsForDispatch_forceStatusBarVisible() {
|
||||
addWindow(TYPE_STATUS_BAR, "statusBar").mAttrs.privateFlags |=
|
||||
@@ -129,9 +128,9 @@ public class InsetsPolicyTest extends WindowTestsBase {
|
||||
|
||||
final InsetsSourceControl[] controls = addAppWindowAndGetControlsForDispatch();
|
||||
|
||||
// The app must not control the status bar.
|
||||
// The focused app window can control both system bars.
|
||||
assertNotNull(controls);
|
||||
assertEquals(1, controls.length);
|
||||
assertEquals(2, controls.length);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -143,9 +142,9 @@ public class InsetsPolicyTest extends WindowTestsBase {
|
||||
|
||||
final InsetsSourceControl[] controls = addAppWindowAndGetControlsForDispatch();
|
||||
|
||||
// The app must not control the navigation bar.
|
||||
// The focused app window can control both system bars.
|
||||
assertNotNull(controls);
|
||||
assertEquals(1, controls.length);
|
||||
assertEquals(2, controls.length);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user