Introduce InsetsSource#FLAG_FORCE_CONSUMING
It controls whether the insets provided by the source should be forcibly
consumed.
We have mForceConsumeSystemBars to achieve the similar logic, however,
it cannot control individual types. And when it is changed, there is no
guarantee that the new value will be sent to the clients. This CL fixes
the issues.
After this CL, the legacy "alwaysConsumeSystemBars" will be redundant,
and there will be a follow-up CL to clean it up.
Fix: 277891341
Test: Launch immersive apps in kids space and make sure their content
wouldn't be obscured by navigation bar.
Change-Id: I1c8b628660d7cde167f5bc832f8cc7568ab87d61
This commit is contained in:
@@ -797,7 +797,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
|
||||
}
|
||||
|
||||
WindowInsets insets = state.calculateInsets(mFrame, mState /* ignoringVisibilityState*/,
|
||||
mLastInsets.isRound(), mLastInsets.shouldAlwaysConsumeSystemBars(),
|
||||
mLastInsets.isRound(), false /* alwaysConsumeSystemBars */,
|
||||
mLastLegacySoftInputMode, mLastLegacyWindowFlags, mLastLegacySystemUiFlags,
|
||||
mWindowType, mLastWindowingMode, null /* idSideMap */);
|
||||
mHost.dispatchWindowInsetsAnimationProgress(insets,
|
||||
|
||||
@@ -68,10 +68,16 @@ public class InsetsSource implements Parcelable {
|
||||
*/
|
||||
public static final int FLAG_INSETS_ROUNDED_CORNER = 1 << 1;
|
||||
|
||||
/**
|
||||
* Controls whether the insets provided by this source should be forcibly consumed.
|
||||
*/
|
||||
public static final int FLAG_FORCE_CONSUMING = 1 << 2;
|
||||
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@IntDef(flag = true, prefix = "FLAG_", value = {
|
||||
FLAG_SUPPRESS_SCRIM,
|
||||
FLAG_INSETS_ROUNDED_CORNER,
|
||||
FLAG_FORCE_CONSUMING,
|
||||
})
|
||||
public @interface Flags {}
|
||||
|
||||
@@ -328,6 +334,9 @@ public class InsetsSource implements Parcelable {
|
||||
if ((flags & FLAG_INSETS_ROUNDED_CORNER) != 0) {
|
||||
joiner.add("INSETS_ROUNDED_CORNER");
|
||||
}
|
||||
if ((flags & FLAG_FORCE_CONSUMING) != 0) {
|
||||
joiner.add("FORCE_CONSUMING");
|
||||
}
|
||||
return joiner.toString();
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package android.view;
|
||||
|
||||
import static android.view.InsetsSource.FLAG_FORCE_CONSUMING;
|
||||
import static android.view.InsetsSource.FLAG_INSETS_ROUNDED_CORNER;
|
||||
import static android.view.InsetsStateProto.DISPLAY_CUTOUT;
|
||||
import static android.view.InsetsStateProto.DISPLAY_FRAME;
|
||||
@@ -144,12 +145,18 @@ public class InsetsState implements Parcelable {
|
||||
boolean[] typeVisibilityMap = new boolean[Type.SIZE];
|
||||
final Rect relativeFrame = new Rect(frame);
|
||||
final Rect relativeFrameMax = new Rect(frame);
|
||||
@InsetsType int forceConsumingTypes = 0;
|
||||
@InsetsType int suppressScrimTypes = 0;
|
||||
for (int i = mSources.size() - 1; i >= 0; i--) {
|
||||
final InsetsSource source = mSources.valueAt(i);
|
||||
final @InsetsType int type = source.getType();
|
||||
|
||||
if ((source.getFlags() & InsetsSource.FLAG_FORCE_CONSUMING) != 0) {
|
||||
forceConsumingTypes |= type;
|
||||
}
|
||||
|
||||
if ((source.getFlags() & InsetsSource.FLAG_SUPPRESS_SCRIM) != 0) {
|
||||
suppressScrimTypes |= source.getType();
|
||||
suppressScrimTypes |= type;
|
||||
}
|
||||
|
||||
processSource(source, relativeFrame, false /* ignoreVisibility */, typeInsetsMap,
|
||||
@@ -157,7 +164,7 @@ public class InsetsState implements Parcelable {
|
||||
|
||||
// IME won't be reported in max insets as the size depends on the EditorInfo of the IME
|
||||
// target.
|
||||
if (source.getType() != WindowInsets.Type.ime()) {
|
||||
if (type != WindowInsets.Type.ime()) {
|
||||
InsetsSource ignoringVisibilitySource = ignoringVisibilityState != null
|
||||
? ignoringVisibilityState.peekSource(source.getId())
|
||||
: source;
|
||||
@@ -178,13 +185,13 @@ public class InsetsState implements Parcelable {
|
||||
if ((legacyWindowFlags & FLAG_FULLSCREEN) != 0) {
|
||||
compatInsetsTypes &= ~statusBars();
|
||||
}
|
||||
if (clearsCompatInsets(windowType, legacyWindowFlags, windowingMode)
|
||||
&& !alwaysConsumeSystemBars) {
|
||||
compatInsetsTypes = 0;
|
||||
if (clearsCompatInsets(windowType, legacyWindowFlags, windowingMode)) {
|
||||
// Clear all types but forceConsumingTypes.
|
||||
compatInsetsTypes &= forceConsumingTypes;
|
||||
}
|
||||
|
||||
return new WindowInsets(typeInsetsMap, typeMaxInsetsMap, typeVisibilityMap, isScreenRound,
|
||||
alwaysConsumeSystemBars, suppressScrimTypes, calculateRelativeCutout(frame),
|
||||
forceConsumingTypes, suppressScrimTypes, calculateRelativeCutout(frame),
|
||||
calculateRelativeRoundedCorners(frame),
|
||||
calculateRelativePrivacyIndicatorBounds(frame),
|
||||
calculateRelativeDisplayShape(frame),
|
||||
@@ -290,9 +297,8 @@ public class InsetsState implements Parcelable {
|
||||
|
||||
public Insets calculateVisibleInsets(Rect frame, int windowType, int windowingMode,
|
||||
@SoftInputModeFlags int softInputMode, int windowFlags) {
|
||||
if (clearsCompatInsets(windowType, windowFlags, windowingMode)) {
|
||||
return Insets.NONE;
|
||||
}
|
||||
final boolean clearsCompatInsets = clearsCompatInsets(
|
||||
windowType, windowFlags, windowingMode);
|
||||
final int softInputAdjustMode = softInputMode & SOFT_INPUT_MASK_ADJUST;
|
||||
final int visibleInsetsTypes = softInputAdjustMode != SOFT_INPUT_ADJUST_NOTHING
|
||||
? systemBars() | ime()
|
||||
@@ -303,6 +309,9 @@ public class InsetsState implements Parcelable {
|
||||
if ((source.getType() & visibleInsetsTypes) == 0) {
|
||||
continue;
|
||||
}
|
||||
if (clearsCompatInsets && !source.hasFlags(FLAG_FORCE_CONSUMING)) {
|
||||
continue;
|
||||
}
|
||||
insets = Insets.max(source.calculateVisibleInsets(frame), insets);
|
||||
}
|
||||
return insets;
|
||||
|
||||
@@ -84,13 +84,7 @@ public final class WindowInsets {
|
||||
@Nullable private final PrivacyIndicatorBounds mPrivacyIndicatorBounds;
|
||||
@Nullable private final DisplayShape mDisplayShape;
|
||||
|
||||
/**
|
||||
* In multi-window we force show the navigation bar. Because we don't want that the surface size
|
||||
* changes in this mode, we instead have a flag whether the navigation bar size should always
|
||||
* be consumed, so the app is treated like there is no virtual navigation bar at all.
|
||||
*/
|
||||
private final boolean mAlwaysConsumeSystemBars;
|
||||
|
||||
private final @InsetsType int mForceConsumingTypes;
|
||||
private final @InsetsType int mSuppressScrimTypes;
|
||||
private final boolean mSystemWindowInsetsConsumed;
|
||||
private final boolean mStableInsetsConsumed;
|
||||
@@ -117,7 +111,7 @@ public final class WindowInsets {
|
||||
|
||||
static {
|
||||
CONSUMED = new WindowInsets(createCompatTypeMap(null), createCompatTypeMap(null),
|
||||
createCompatVisibilityMap(createCompatTypeMap(null)), false, false, 0, null,
|
||||
createCompatVisibilityMap(createCompatTypeMap(null)), false, 0, 0, null,
|
||||
null, null, null, systemBars(), false);
|
||||
}
|
||||
|
||||
@@ -137,7 +131,8 @@ public final class WindowInsets {
|
||||
@Nullable Insets[] typeMaxInsetsMap,
|
||||
boolean[] typeVisibilityMap,
|
||||
boolean isRound,
|
||||
boolean alwaysConsumeSystemBars, @InsetsType int suppressScrimTypes,
|
||||
@InsetsType int forceConsumingTypes,
|
||||
@InsetsType int suppressScrimTypes,
|
||||
DisplayCutout displayCutout,
|
||||
RoundedCorners roundedCorners,
|
||||
PrivacyIndicatorBounds privacyIndicatorBounds,
|
||||
@@ -155,7 +150,7 @@ public final class WindowInsets {
|
||||
|
||||
mTypeVisibilityMap = typeVisibilityMap;
|
||||
mIsRound = isRound;
|
||||
mAlwaysConsumeSystemBars = alwaysConsumeSystemBars;
|
||||
mForceConsumingTypes = forceConsumingTypes;
|
||||
mSuppressScrimTypes = suppressScrimTypes;
|
||||
mCompatInsetsTypes = compatInsetsTypes;
|
||||
mCompatIgnoreVisibility = compatIgnoreVisibility;
|
||||
@@ -178,7 +173,7 @@ public final class WindowInsets {
|
||||
this(src.mSystemWindowInsetsConsumed ? null : src.mTypeInsetsMap,
|
||||
src.mStableInsetsConsumed ? null : src.mTypeMaxInsetsMap,
|
||||
src.mTypeVisibilityMap, src.mIsRound,
|
||||
src.mAlwaysConsumeSystemBars, src.mSuppressScrimTypes,
|
||||
src.mForceConsumingTypes, src.mSuppressScrimTypes,
|
||||
displayCutoutCopyConstructorArgument(src),
|
||||
src.mRoundedCorners,
|
||||
src.mPrivacyIndicatorBounds,
|
||||
@@ -235,7 +230,7 @@ public final class WindowInsets {
|
||||
/** @hide */
|
||||
@UnsupportedAppUsage
|
||||
public WindowInsets(Rect systemWindowInsets) {
|
||||
this(createCompatTypeMap(systemWindowInsets), null, new boolean[SIZE], false, false, 0,
|
||||
this(createCompatTypeMap(systemWindowInsets), null, new boolean[SIZE], false, 0, 0,
|
||||
null, null, null, null, systemBars(), false /* compatIgnoreVisibility */);
|
||||
}
|
||||
|
||||
@@ -556,7 +551,7 @@ public final class WindowInsets {
|
||||
return new WindowInsets(mSystemWindowInsetsConsumed ? null : mTypeInsetsMap,
|
||||
mStableInsetsConsumed ? null : mTypeMaxInsetsMap,
|
||||
mTypeVisibilityMap,
|
||||
mIsRound, mAlwaysConsumeSystemBars, mSuppressScrimTypes,
|
||||
mIsRound, mForceConsumingTypes, mSuppressScrimTypes,
|
||||
null /* displayCutout */, mRoundedCorners, mPrivacyIndicatorBounds, mDisplayShape,
|
||||
mCompatInsetsTypes, mCompatIgnoreVisibility);
|
||||
}
|
||||
@@ -607,7 +602,7 @@ public final class WindowInsets {
|
||||
public WindowInsets consumeSystemWindowInsets() {
|
||||
return new WindowInsets(null, null,
|
||||
mTypeVisibilityMap,
|
||||
mIsRound, mAlwaysConsumeSystemBars, mSuppressScrimTypes,
|
||||
mIsRound, mForceConsumingTypes, mSuppressScrimTypes,
|
||||
// If the system window insets types contain displayCutout, we should also consume
|
||||
// it.
|
||||
(mCompatInsetsTypes & displayCutout()) != 0
|
||||
@@ -895,8 +890,8 @@ public final class WindowInsets {
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public boolean shouldAlwaysConsumeSystemBars() {
|
||||
return mAlwaysConsumeSystemBars;
|
||||
public @InsetsType int getForceConsumingTypes() {
|
||||
return mForceConsumingTypes;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -930,6 +925,8 @@ public final class WindowInsets {
|
||||
result.append("\n ");
|
||||
result.append(mDisplayShape != null ? "displayShape=" + mDisplayShape : "");
|
||||
result.append("\n ");
|
||||
result.append("forceConsumingTypes=" + Type.toString(mForceConsumingTypes));
|
||||
result.append("\n ");
|
||||
result.append("suppressScrimTypes=" + Type.toString(mSuppressScrimTypes));
|
||||
result.append("\n ");
|
||||
result.append("compatInsetsTypes=" + Type.toString(mCompatInsetsTypes));
|
||||
@@ -1027,7 +1024,7 @@ public final class WindowInsets {
|
||||
? null
|
||||
: insetInsets(mTypeMaxInsetsMap, left, top, right, bottom),
|
||||
mTypeVisibilityMap,
|
||||
mIsRound, mAlwaysConsumeSystemBars, mSuppressScrimTypes,
|
||||
mIsRound, mForceConsumingTypes, mSuppressScrimTypes,
|
||||
mDisplayCutoutConsumed
|
||||
? null
|
||||
: mDisplayCutout == null
|
||||
@@ -1050,7 +1047,7 @@ public final class WindowInsets {
|
||||
WindowInsets that = (WindowInsets) o;
|
||||
|
||||
return mIsRound == that.mIsRound
|
||||
&& mAlwaysConsumeSystemBars == that.mAlwaysConsumeSystemBars
|
||||
&& mForceConsumingTypes == that.mForceConsumingTypes
|
||||
&& mSuppressScrimTypes == that.mSuppressScrimTypes
|
||||
&& mSystemWindowInsetsConsumed == that.mSystemWindowInsetsConsumed
|
||||
&& mStableInsetsConsumed == that.mStableInsetsConsumed
|
||||
@@ -1068,7 +1065,7 @@ public final class WindowInsets {
|
||||
public int hashCode() {
|
||||
return Objects.hash(Arrays.hashCode(mTypeInsetsMap), Arrays.hashCode(mTypeMaxInsetsMap),
|
||||
Arrays.hashCode(mTypeVisibilityMap), mIsRound, mDisplayCutout, mRoundedCorners,
|
||||
mAlwaysConsumeSystemBars, mSuppressScrimTypes, mSystemWindowInsetsConsumed,
|
||||
mForceConsumingTypes, mSuppressScrimTypes, mSystemWindowInsetsConsumed,
|
||||
mStableInsetsConsumed, mDisplayCutoutConsumed, mPrivacyIndicatorBounds,
|
||||
mDisplayShape);
|
||||
}
|
||||
@@ -1134,7 +1131,7 @@ public final class WindowInsets {
|
||||
private DisplayShape mDisplayShape = DisplayShape.NONE;
|
||||
|
||||
private boolean mIsRound;
|
||||
private boolean mAlwaysConsumeSystemBars;
|
||||
private @InsetsType int mForceConsumingTypes;
|
||||
private @InsetsType int mSuppressScrimTypes;
|
||||
|
||||
private PrivacyIndicatorBounds mPrivacyIndicatorBounds = new PrivacyIndicatorBounds();
|
||||
@@ -1162,7 +1159,7 @@ public final class WindowInsets {
|
||||
mDisplayCutout = displayCutoutCopyConstructorArgument(insets);
|
||||
mRoundedCorners = insets.mRoundedCorners;
|
||||
mIsRound = insets.mIsRound;
|
||||
mAlwaysConsumeSystemBars = insets.mAlwaysConsumeSystemBars;
|
||||
mForceConsumingTypes = insets.mForceConsumingTypes;
|
||||
mSuppressScrimTypes = insets.mSuppressScrimTypes;
|
||||
mPrivacyIndicatorBounds = insets.mPrivacyIndicatorBounds;
|
||||
mDisplayShape = insets.mDisplayShape;
|
||||
@@ -1433,7 +1430,15 @@ public final class WindowInsets {
|
||||
/** @hide */
|
||||
@NonNull
|
||||
public Builder setAlwaysConsumeSystemBars(boolean alwaysConsumeSystemBars) {
|
||||
mAlwaysConsumeSystemBars = alwaysConsumeSystemBars;
|
||||
// TODO (b/277891341): Remove this and related usages. This has been replaced by
|
||||
// #setForceConsumingTypes.
|
||||
return this;
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
@NonNull
|
||||
public Builder setForceConsumingTypes(@InsetsType int forceConsumingTypes) {
|
||||
mForceConsumingTypes = forceConsumingTypes;
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -1453,7 +1458,7 @@ public final class WindowInsets {
|
||||
public WindowInsets build() {
|
||||
return new WindowInsets(mSystemInsetsConsumed ? null : mTypeInsetsMap,
|
||||
mStableInsetsConsumed ? null : mTypeMaxInsetsMap, mTypeVisibilityMap,
|
||||
mIsRound, mAlwaysConsumeSystemBars, mSuppressScrimTypes, mDisplayCutout,
|
||||
mIsRound, mForceConsumingTypes, mSuppressScrimTypes, mDisplayCutout,
|
||||
mRoundedCorners, mPrivacyIndicatorBounds, mDisplayShape, systemBars(),
|
||||
false /* compatIgnoreVisibility */);
|
||||
}
|
||||
|
||||
@@ -232,7 +232,7 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
|
||||
private boolean mLastHasRightStableInset = false;
|
||||
private boolean mLastHasLeftStableInset = false;
|
||||
private int mLastWindowFlags = 0;
|
||||
private boolean mLastShouldAlwaysConsumeSystemBars = false;
|
||||
private @InsetsType int mLastForceConsumingTypes = 0;
|
||||
private @InsetsType int mLastSuppressScrimTypes = 0;
|
||||
|
||||
private int mRootScrollY = 0;
|
||||
@@ -1111,19 +1111,19 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
|
||||
: controller.getSystemBarsAppearance();
|
||||
|
||||
if (insets != null) {
|
||||
mLastShouldAlwaysConsumeSystemBars = insets.shouldAlwaysConsumeSystemBars();
|
||||
mLastForceConsumingTypes = insets.getForceConsumingTypes();
|
||||
|
||||
final boolean clearsCompatInsets =
|
||||
clearsCompatInsets(attrs.type, attrs.flags,
|
||||
getResources().getConfiguration().windowConfiguration
|
||||
.getWindowingMode())
|
||||
&& !mLastShouldAlwaysConsumeSystemBars;
|
||||
@InsetsType int compatInsetsTypes =
|
||||
WindowInsets.Type.systemBars() | WindowInsets.Type.displayCutout();
|
||||
if (clearsCompatInsets(attrs.type, attrs.flags,
|
||||
getResources().getConfiguration().windowConfiguration.getWindowingMode())) {
|
||||
compatInsetsTypes &= mLastForceConsumingTypes;
|
||||
}
|
||||
final Insets stableBarInsets = insets.getInsetsIgnoringVisibility(
|
||||
WindowInsets.Type.systemBars());
|
||||
final Insets systemInsets = clearsCompatInsets
|
||||
final Insets systemInsets = compatInsetsTypes == 0
|
||||
? Insets.NONE
|
||||
: Insets.min(insets.getInsets(WindowInsets.Type.systemBars()
|
||||
| WindowInsets.Type.displayCutout()), stableBarInsets);
|
||||
: Insets.min(insets.getInsets(compatInsetsTypes), stableBarInsets);
|
||||
mLastTopInset = systemInsets.top;
|
||||
mLastBottomInset = systemInsets.bottom;
|
||||
mLastRightInset = systemInsets.right;
|
||||
@@ -1208,7 +1208,8 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
|
||||
&& (sysUiVisibility & SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) == 0
|
||||
&& decorFitsSystemWindows
|
||||
&& !hideNavigation)
|
||||
|| (mLastShouldAlwaysConsumeSystemBars && hideNavigation);
|
||||
|| ((mLastForceConsumingTypes & WindowInsets.Type.navigationBars()) != 0
|
||||
&& hideNavigation);
|
||||
|
||||
boolean consumingNavBar =
|
||||
((attrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0
|
||||
@@ -1224,13 +1225,15 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
|
||||
boolean fullscreen = (sysUiVisibility & SYSTEM_UI_FLAG_FULLSCREEN) != 0
|
||||
|| (attrs.flags & FLAG_FULLSCREEN) != 0
|
||||
|| (requestedVisibleTypes & WindowInsets.Type.statusBars()) == 0;
|
||||
boolean consumingStatusBar = (sysUiVisibility & SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN) == 0
|
||||
&& decorFitsSystemWindows
|
||||
&& (attrs.flags & FLAG_LAYOUT_IN_SCREEN) == 0
|
||||
&& (attrs.flags & FLAG_LAYOUT_INSET_DECOR) == 0
|
||||
&& mForceWindowDrawsBarBackgrounds
|
||||
&& mLastTopInset != 0
|
||||
|| (mLastShouldAlwaysConsumeSystemBars && fullscreen);
|
||||
boolean consumingStatusBar =
|
||||
((sysUiVisibility & SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN) == 0
|
||||
&& decorFitsSystemWindows
|
||||
&& (attrs.flags & FLAG_LAYOUT_IN_SCREEN) == 0
|
||||
&& (attrs.flags & FLAG_LAYOUT_INSET_DECOR) == 0
|
||||
&& mForceWindowDrawsBarBackgrounds
|
||||
&& mLastTopInset != 0)
|
||||
|| ((mLastForceConsumingTypes & WindowInsets.Type.statusBars()) != 0
|
||||
&& fullscreen);
|
||||
|
||||
int consumedTop = consumingStatusBar ? mLastTopInset : 0;
|
||||
int consumedRight = consumingNavBar ? mLastRightInset : 0;
|
||||
@@ -1434,9 +1437,9 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
|
||||
private void updateColorViewInt(final ColorViewState state, int color, int dividerColor,
|
||||
int size, boolean verticalBar, boolean seascape, int sideMargin, boolean animate,
|
||||
boolean force, @InsetsType int requestedVisibleTypes) {
|
||||
final @InsetsType int type = state.attributes.insetsType;
|
||||
state.present = state.attributes.isPresent(
|
||||
(requestedVisibleTypes & state.attributes.insetsType) != 0
|
||||
|| mLastShouldAlwaysConsumeSystemBars,
|
||||
(requestedVisibleTypes & type) != 0 || (mLastForceConsumingTypes & type) != 0,
|
||||
mWindow.getAttributes().flags, force);
|
||||
boolean show = state.attributes.isVisible(state.present, color,
|
||||
mWindow.getAttributes().flags, force);
|
||||
|
||||
@@ -40,14 +40,14 @@ public class WindowInsetsTest {
|
||||
@Test
|
||||
public void systemWindowInsets_afterConsuming_isConsumed() {
|
||||
assertTrue(new WindowInsets(WindowInsets.createCompatTypeMap(new Rect(1, 2, 3, 4)), null,
|
||||
null, false, false, 0, null, null, null, null,
|
||||
null, false, 0, 0, null, null, null, null,
|
||||
WindowInsets.Type.systemBars(), false)
|
||||
.consumeSystemWindowInsets().isConsumed());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multiNullConstructor_isConsumed() {
|
||||
assertTrue(new WindowInsets(null, null, null, false, false, 0, null, null, null, null,
|
||||
assertTrue(new WindowInsets(null, null, null, false, 0, 0, null, null, null, null,
|
||||
WindowInsets.Type.systemBars(), false).isConsumed());
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ public class WindowInsetsTest {
|
||||
boolean[] visible = new boolean[SIZE];
|
||||
WindowInsets.assignCompatInsets(maxInsets, new Rect(0, 10, 0, 0));
|
||||
WindowInsets.assignCompatInsets(insets, new Rect(0, 0, 0, 0));
|
||||
WindowInsets windowInsets = new WindowInsets(insets, maxInsets, visible, false, false,
|
||||
WindowInsets windowInsets = new WindowInsets(insets, maxInsets, visible, false, 0,
|
||||
0, null, null, null, DisplayShape.NONE, systemBars(),
|
||||
true /* compatIgnoreVisibility */);
|
||||
assertEquals(Insets.of(0, 10, 0, 0), windowInsets.getSystemWindowInsets());
|
||||
|
||||
@@ -169,7 +169,7 @@ public class ActionBarOverlayLayoutTest {
|
||||
|
||||
private WindowInsets insetsWith(Insets content, DisplayCutout cutout) {
|
||||
return new WindowInsets(WindowInsets.createCompatTypeMap(content.toRect()), null, null,
|
||||
false, false, 0, cutout, null, null, null, WindowInsets.Type.systemBars(), false);
|
||||
false, 0, 0, cutout, null, null, null, WindowInsets.Type.systemBars(), false);
|
||||
}
|
||||
|
||||
private ViewGroup createViewGroupWithId(int id) {
|
||||
|
||||
@@ -3701,6 +3701,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
|
||||
mInputMonitor.dump(pw, " ");
|
||||
pw.println();
|
||||
mInsetsStateController.dump(prefix, pw);
|
||||
mInsetsPolicy.dump(prefix, pw);
|
||||
mDwpcHelper.dump(prefix, pw);
|
||||
pw.println();
|
||||
}
|
||||
|
||||
@@ -327,8 +327,6 @@ public class DisplayPolicy {
|
||||
private WindowState mTopFullscreenOpaqueWindowState;
|
||||
private boolean mTopIsFullscreen;
|
||||
private int mNavBarOpacityMode = NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED;
|
||||
private boolean mForceConsumeSystemBars;
|
||||
private boolean mForceShowSystemBars;
|
||||
|
||||
/**
|
||||
* Windows that provides gesture insets. If multiple windows provide gesture insets at the same
|
||||
@@ -1286,18 +1284,10 @@ public class DisplayPolicy {
|
||||
return ANIMATION_STYLEABLE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if the system bars are forced to be consumed
|
||||
*/
|
||||
// TODO (b/277891341): Remove this and related usages. This has been replaced by
|
||||
// InsetsSource#FLAG_FORCE_CONSUMING.
|
||||
public boolean areSystemBarsForcedConsumedLw() {
|
||||
return mForceConsumeSystemBars;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if the system bars are forced to stay visible
|
||||
*/
|
||||
public boolean areSystemBarsForcedShownLw() {
|
||||
return mForceShowSystemBars;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1694,7 +1684,8 @@ public class DisplayPolicy {
|
||||
* @return Whether the top fullscreen app hides the given type of system bar.
|
||||
*/
|
||||
boolean topAppHidesSystemBar(@InsetsType int type) {
|
||||
if (mTopFullscreenOpaqueWindowState == null || mForceShowSystemBars) {
|
||||
if (mTopFullscreenOpaqueWindowState == null
|
||||
|| getInsetsPolicy().areTypesForciblyShowing(type)) {
|
||||
return false;
|
||||
}
|
||||
return !mTopFullscreenOpaqueWindowState.isRequestedVisible(type);
|
||||
@@ -2371,14 +2362,7 @@ public class DisplayPolicy {
|
||||
final boolean freeformRootTaskVisible =
|
||||
defaultTaskDisplayArea.isRootTaskVisible(WINDOWING_MODE_FREEFORM);
|
||||
|
||||
// We need to force showing system bars when adjacent tasks or freeform roots visible.
|
||||
mForceShowSystemBars = adjacentTasksVisible || freeformRootTaskVisible;
|
||||
// We need to force the consumption of the system bars if they are force shown or if they
|
||||
// are controlled by a remote insets controller.
|
||||
mForceConsumeSystemBars = mForceShowSystemBars
|
||||
|| getInsetsPolicy().remoteInsetsControllerControlsSystemBars(win)
|
||||
|| getInsetsPolicy().forcesShowingNavigationBars(win);
|
||||
mDisplayContent.getInsetsPolicy().updateBarControlTarget(win);
|
||||
getInsetsPolicy().updateSystemBars(win, adjacentTasksVisible, freeformRootTaskVisible);
|
||||
|
||||
final boolean topAppHidesStatusBar = topAppHidesSystemBar(Type.statusBars());
|
||||
if (getStatusBar() != null) {
|
||||
|
||||
@@ -64,6 +64,8 @@ import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.server.DisplayThread;
|
||||
import com.android.server.statusbar.StatusBarManagerInternal;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
|
||||
/**
|
||||
* Policy that implements who gets control over the windows generating insets.
|
||||
*/
|
||||
@@ -114,6 +116,7 @@ class InsetsPolicy {
|
||||
private final BarWindow mStatusBar = new BarWindow(StatusBarManager.WINDOW_STATUS_BAR);
|
||||
private final BarWindow mNavBar = new BarWindow(StatusBarManager.WINDOW_NAVIGATION_BAR);
|
||||
private @InsetsType int mShowingTransientTypes;
|
||||
private @InsetsType int mForcedShowingTypes;
|
||||
private boolean mAnimatingShown;
|
||||
|
||||
private final boolean mHideNavBarForKeyboard;
|
||||
@@ -127,7 +130,6 @@ class InsetsPolicy {
|
||||
mHideNavBarForKeyboard = r.getBoolean(R.bool.config_hideNavBarForKeyboard);
|
||||
}
|
||||
|
||||
|
||||
/** Updates the target which can control system bars. */
|
||||
void updateBarControlTarget(@Nullable WindowState focusedWin) {
|
||||
if (mFocusedWin != focusedWin) {
|
||||
@@ -514,7 +516,7 @@ class InsetsPolicy {
|
||||
component, focusedWin.getRequestedVisibleTypes());
|
||||
return mDisplayContent.mRemoteInsetsControlTarget;
|
||||
}
|
||||
if (mPolicy.areSystemBarsForcedShownLw()) {
|
||||
if (areTypesForciblyShowing(Type.statusBars())) {
|
||||
// Status bar is forcibly shown. 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;
|
||||
@@ -567,13 +569,6 @@ class InsetsPolicy {
|
||||
return focusedWin;
|
||||
}
|
||||
}
|
||||
if (forcesShowingNavigationBars(focusedWin)) {
|
||||
// When "force show navigation bar" is enabled, it means both force visible is true, and
|
||||
// we are in 3-button navigation. In this mode, the navigation bar is forcibly shown
|
||||
// when activity type is ACTIVITY_TYPE_STANDARD which means Launcher or Recent could
|
||||
// still control the navigation bar in this mode.
|
||||
return null;
|
||||
}
|
||||
if (remoteInsetsControllerControlsSystemBars(focusedWin)) {
|
||||
ComponentName component = focusedWin.mActivityRecord != null
|
||||
? focusedWin.mActivityRecord.mActivityComponent : null;
|
||||
@@ -581,7 +576,7 @@ class InsetsPolicy {
|
||||
component, focusedWin.getRequestedVisibleTypes());
|
||||
return mDisplayContent.mRemoteInsetsControlTarget;
|
||||
}
|
||||
if (mPolicy.areSystemBarsForcedShownLw()) {
|
||||
if (areTypesForciblyShowing(Type.navigationBars())) {
|
||||
// Navigation bar is forcibly shown. 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;
|
||||
@@ -603,7 +598,32 @@ class InsetsPolicy {
|
||||
return focusedWin;
|
||||
}
|
||||
|
||||
boolean forcesShowingNavigationBars(WindowState win) {
|
||||
boolean areTypesForciblyShowing(@InsetsType int types) {
|
||||
return (mForcedShowingTypes & types) == types;
|
||||
}
|
||||
|
||||
void updateSystemBars(WindowState win, boolean inSplitScreenMode, boolean inFreeformMode) {
|
||||
mForcedShowingTypes = (inSplitScreenMode || inFreeformMode)
|
||||
? (Type.statusBars() | Type.navigationBars())
|
||||
: forceShowingNavigationBars(win)
|
||||
? Type.navigationBars()
|
||||
: 0;
|
||||
|
||||
// The client app won't be able to control these types of system bars. Here makes the client
|
||||
// forcibly consume these types to prevent the app content from getting obscured.
|
||||
mStateController.setForcedConsumingTypes(
|
||||
mForcedShowingTypes | (remoteInsetsControllerControlsSystemBars(win)
|
||||
? (Type.statusBars() | Type.navigationBars())
|
||||
: 0));
|
||||
|
||||
updateBarControlTarget(win);
|
||||
}
|
||||
|
||||
private boolean forceShowingNavigationBars(WindowState win) {
|
||||
// When "force show navigation bar" is enabled, it means both force visible is true, and
|
||||
// we are in 3-button navigation. In this mode, the navigation bar is forcibly shown
|
||||
// when activity type is ACTIVITY_TYPE_STANDARD which means Launcher or Recent could
|
||||
// still control the navigation bar in this mode.
|
||||
return mPolicy.isForceShowNavigationBarEnabled() && win != null
|
||||
&& win.getActivityType() == ACTIVITY_TYPE_STANDARD;
|
||||
}
|
||||
@@ -696,6 +716,21 @@ class InsetsPolicy {
|
||||
wereRevealedFromSwipeOnSystemBar);
|
||||
}
|
||||
|
||||
void dump(String prefix, PrintWriter pw) {
|
||||
pw.println(prefix + "InsetsPolicy");
|
||||
prefix = prefix + " ";
|
||||
pw.println(prefix + "status: " + StatusBarManager.windowStateToString(mStatusBar.mState));
|
||||
pw.println(prefix + "nav: " + StatusBarManager.windowStateToString(mNavBar.mState));
|
||||
if (mShowingTransientTypes != 0) {
|
||||
pw.println(prefix + "mShowingTransientTypes="
|
||||
+ WindowInsets.Type.toString(mShowingTransientTypes));
|
||||
}
|
||||
if (mForcedShowingTypes != 0) {
|
||||
pw.println(prefix + "mForcedShowingTypes="
|
||||
+ WindowInsets.Type.toString(mForcedShowingTypes));
|
||||
}
|
||||
}
|
||||
|
||||
private class BarWindow {
|
||||
|
||||
private final int mId;
|
||||
|
||||
@@ -40,6 +40,7 @@ import android.graphics.Rect;
|
||||
import android.util.SparseArray;
|
||||
import android.util.proto.ProtoOutputStream;
|
||||
import android.view.InsetsSource;
|
||||
import android.view.InsetsSource.Flags;
|
||||
import android.view.InsetsSourceControl;
|
||||
import android.view.SurfaceControl;
|
||||
import android.view.SurfaceControl.Transaction;
|
||||
@@ -81,6 +82,8 @@ class InsetsSourceProvider {
|
||||
private final Rect mSourceFrame = new Rect();
|
||||
private final Rect mLastSourceFrame = new Rect();
|
||||
private @NonNull Insets mInsetsHint = Insets.NONE;
|
||||
private @Flags int mFlagsFromFrameProvider;
|
||||
private @Flags int mFlagsFromServer;
|
||||
|
||||
private final Consumer<Transaction> mSetLeashPositionConsumer = t -> {
|
||||
if (mControl != null) {
|
||||
@@ -189,6 +192,16 @@ class InsetsSourceProvider {
|
||||
}
|
||||
}
|
||||
|
||||
boolean setFlags(@Flags int flags, @Flags int mask) {
|
||||
mFlagsFromServer = (mFlagsFromServer & ~mask) | (flags & mask);
|
||||
final @Flags int mergedFlags = mFlagsFromFrameProvider | mFlagsFromServer;
|
||||
if (mSource.getFlags() != mergedFlags) {
|
||||
mSource.setFlags(mergedFlags);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* The source frame can affect the layout of other windows, so this should be called once the
|
||||
* window container gets laid out.
|
||||
@@ -217,11 +230,11 @@ class InsetsSourceProvider {
|
||||
|
||||
mSourceFrame.set(frame);
|
||||
if (mFrameProvider != null) {
|
||||
final int flags = mFrameProvider.apply(
|
||||
mFlagsFromFrameProvider = mFrameProvider.apply(
|
||||
mWindowContainer.getDisplayContent().mDisplayFrames,
|
||||
mWindowContainer,
|
||||
mSourceFrame);
|
||||
mSource.setFlags(flags);
|
||||
mSource.setFlags(mFlagsFromFrameProvider | mFlagsFromServer);
|
||||
}
|
||||
updateSourceFrameForServerVisibility();
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package com.android.server.wm;
|
||||
|
||||
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
|
||||
import static android.view.InsetsSource.FLAG_FORCE_CONSUMING;
|
||||
import static android.view.InsetsSource.ID_IME;
|
||||
import static android.view.WindowInsets.Type.displayCutout;
|
||||
import static android.view.WindowInsets.Type.ime;
|
||||
@@ -85,6 +86,8 @@ class InsetsStateController {
|
||||
}
|
||||
};
|
||||
|
||||
private @InsetsType int mForcedConsumingTypes;
|
||||
|
||||
InsetsStateController(DisplayContent displayContent) {
|
||||
mDisplayContent = displayContent;
|
||||
}
|
||||
@@ -122,6 +125,11 @@ class InsetsStateController {
|
||||
provider = id == ID_IME
|
||||
? new ImeInsetsSourceProvider(source, this, mDisplayContent)
|
||||
: new InsetsSourceProvider(source, this, mDisplayContent);
|
||||
provider.setFlags(
|
||||
(mForcedConsumingTypes & type) != 0
|
||||
? FLAG_FORCE_CONSUMING
|
||||
: 0,
|
||||
FLAG_FORCE_CONSUMING);
|
||||
mProviders.put(id, provider);
|
||||
return provider;
|
||||
}
|
||||
@@ -137,6 +145,24 @@ class InsetsStateController {
|
||||
}
|
||||
}
|
||||
|
||||
void setForcedConsumingTypes(@InsetsType int types) {
|
||||
if (mForcedConsumingTypes != types) {
|
||||
mForcedConsumingTypes = types;
|
||||
boolean changed = false;
|
||||
for (int i = mProviders.size() - 1; i >= 0; i--) {
|
||||
final InsetsSourceProvider provider = mProviders.valueAt(i);
|
||||
changed |= provider.setFlags(
|
||||
(types & provider.getSource().getType()) != 0
|
||||
? FLAG_FORCE_CONSUMING
|
||||
: 0,
|
||||
FLAG_FORCE_CONSUMING);
|
||||
}
|
||||
if (changed) {
|
||||
notifyInsetsChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a layout pass has occurred.
|
||||
*/
|
||||
@@ -391,6 +417,10 @@ class InsetsStateController {
|
||||
for (int i = mProviders.size() - 1; i >= 0; i--) {
|
||||
mProviders.valueAt(i).dump(pw, prefix + " ");
|
||||
}
|
||||
if (mForcedConsumingTypes != 0) {
|
||||
pw.println(prefix + "mForcedConsumingTypes="
|
||||
+ WindowInsets.Type.toString(mForcedConsumingTypes));
|
||||
}
|
||||
}
|
||||
|
||||
void dumpDebug(ProtoOutputStream proto, @WindowTraceLogLevel int logLevel) {
|
||||
|
||||
Reference in New Issue
Block a user