diff options
11 files changed, 86 insertions, 19 deletions
diff --git a/core/java/android/view/InsetsAnimationControlImpl.java b/core/java/android/view/InsetsAnimationControlImpl.java index ce71b07da805..7c1465b443e4 100644 --- a/core/java/android/view/InsetsAnimationControlImpl.java +++ b/core/java/android/view/InsetsAnimationControlImpl.java @@ -161,8 +161,9 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll private Insets getInsetsFromState(InsetsState state, Rect frame, @Nullable @InsetSide SparseIntArray typeSideMap) { return state.calculateInsets(frame, false /* isScreenRound */, - false /* alwaysConsumerNavBar */, null /* displayCutout */, typeSideMap) - .getInsets(mTypes); + false /* alwaysConsumerNavBar */, null /* displayCutout */, + null /* legacyContentInsets */, null /* legacyStableInsets */, typeSideMap) + .getInsets(mTypes); } private Insets sanitize(Insets insets) { diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java index c2ade764ca81..4b1d1ec15750 100644 --- a/core/java/android/view/InsetsController.java +++ b/core/java/android/view/InsetsController.java @@ -56,6 +56,9 @@ public class InsetsController implements WindowInsetsController { private final Runnable mAnimCallback; + private final Rect mLastLegacyContentInsets = new Rect(); + private final Rect mLastLegacyStableInsets = new Rect(); + public InsetsController(ViewRootImpl viewRoot) { mViewRoot = viewRoot; mAnimCallback = () -> { @@ -70,6 +73,7 @@ public class InsetsController implements WindowInsetsController { } WindowInsets insets = state.calculateInsets(mFrame, mLastInsets.isRound(), mLastInsets.shouldAlwaysConsumeNavBar(), mLastInsets.getDisplayCutout(), + mLastLegacyContentInsets, mLastLegacyStableInsets, null /* typeSideMap */); mViewRoot.mView.dispatchWindowInsetsAnimationProgress(insets); }; @@ -102,8 +106,12 @@ public class InsetsController implements WindowInsetsController { */ @VisibleForTesting public WindowInsets calculateInsets(boolean isScreenRound, - boolean alwaysConsumeNavBar, DisplayCutout cutout) { + boolean alwaysConsumeNavBar, DisplayCutout cutout, Rect legacyContentInsets, + Rect legacyStableInsets) { + mLastLegacyContentInsets.set(legacyContentInsets); + mLastLegacyStableInsets.set(legacyStableInsets); mLastInsets = mState.calculateInsets(mFrame, isScreenRound, alwaysConsumeNavBar, cutout, + legacyContentInsets, legacyStableInsets, null /* typeSideMap */); return mLastInsets; } diff --git a/core/java/android/view/InsetsState.java b/core/java/android/view/InsetsState.java index cf8c0707828d..529776e542ee 100644 --- a/core/java/android/view/InsetsState.java +++ b/core/java/android/view/InsetsState.java @@ -16,6 +16,7 @@ package android.view; +import static android.view.ViewRootImpl.NEW_INSETS_MODE_IME; import static android.view.WindowInsets.Type.indexOf; import android.annotation.IntDef; @@ -119,11 +120,17 @@ public class InsetsState implements Parcelable { */ public WindowInsets calculateInsets(Rect frame, boolean isScreenRound, boolean alwaysConsumeNavBar, DisplayCutout cutout, + @Nullable Rect legacyContentInsets, @Nullable Rect legacyStableInsets, @Nullable @InsetSide SparseIntArray typeSideMap) { Insets[] typeInsetsMap = new Insets[Type.SIZE]; Insets[] typeMaxInsetsMap = new Insets[Type.SIZE]; final Rect relativeFrame = new Rect(frame); final Rect relativeFrameMax = new Rect(frame); + if (ViewRootImpl.sNewInsetsMode == NEW_INSETS_MODE_IME + && legacyContentInsets != null && legacyStableInsets != null) { + WindowInsets.assignCompatInsets(typeInsetsMap, legacyContentInsets); + WindowInsets.assignCompatInsets(typeMaxInsetsMap, legacyStableInsets); + } for (int type = FIRST_TYPE; type <= LAST_TYPE; type++) { InsetsSource source = mSources.get(type); if (source == null) { diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index a1aa06e901dc..2131e6d7a528 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -16,6 +16,7 @@ package android.view; +import static android.view.ViewRootImpl.NEW_INSETS_MODE_FULL; import static android.view.accessibility.AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED; import static java.lang.Math.max; @@ -5123,7 +5124,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, sAcceptZeroSizeDragShadow = targetSdkVersion < Build.VERSION_CODES.P; - sBrokenInsetsDispatch = !ViewRootImpl.USE_NEW_INSETS + sBrokenInsetsDispatch = ViewRootImpl.sNewInsetsMode != NEW_INSETS_MODE_FULL || targetSdkVersion < Build.VERSION_CODES.Q; sCompatibilityDone = true; diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 27d4ea4a777a..a031b704627f 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -163,13 +163,16 @@ public final class ViewRootImpl implements ViewParent, private static final boolean MT_RENDERER_AVAILABLE = true; /** - * If set to true, the view system will switch from using rectangles retrieved from window to + * If set to 2, the view system will switch from using rectangles retrieved from window to * dispatch to the view hierarchy to using {@link InsetsController}, that derives the insets * directly from the full configuration, enabling richer information about the insets state, as * well as new APIs to control it frame-by-frame, and synchronize animations with it. * <p> - * Only switch this to true once the new insets system is productionized and the old APIs are + * Only set this to 2 once the new insets system is productionized and the old APIs are * fully migrated over. + * <p> + * If set to 1, this will switch to a mode where we only use the new approach for IME, but not + * for the status/navigation bar. */ private static final String USE_NEW_INSETS_PROPERTY = "persist.wm.new_insets"; @@ -177,8 +180,26 @@ public final class ViewRootImpl implements ViewParent, * @see #USE_NEW_INSETS_PROPERTY * @hide */ - public static final boolean USE_NEW_INSETS = - SystemProperties.getBoolean(USE_NEW_INSETS_PROPERTY, false); + public static final int sNewInsetsMode = + SystemProperties.getInt(USE_NEW_INSETS_PROPERTY, 0); + + /** + * @see #USE_NEW_INSETS_PROPERTY + * @hide + */ + public static final int NEW_INSETS_MODE_NONE = 0; + + /** + * @see #USE_NEW_INSETS_PROPERTY + * @hide + */ + public static final int NEW_INSETS_MODE_IME = 1; + + /** + * @see #USE_NEW_INSETS_PROPERTY + * @hide + */ + public static final int NEW_INSETS_MODE_FULL = 2; /** * Set this system property to true to force the view hierarchy to render @@ -1367,7 +1388,7 @@ public final class ViewRootImpl implements ViewParent, } void notifyInsetsChanged() { - if (!USE_NEW_INSETS) { + if (sNewInsetsMode == NEW_INSETS_MODE_NONE) { return; } mApplyInsetsRequested = true; @@ -1855,10 +1876,11 @@ public final class ViewRootImpl implements ViewParent, } contentInsets = ensureInsetsNonNegative(contentInsets, "content"); stableInsets = ensureInsetsNonNegative(stableInsets, "stable"); - if (USE_NEW_INSETS) { + if (sNewInsetsMode != NEW_INSETS_MODE_NONE) { mLastWindowInsets = mInsetsController.calculateInsets( mContext.getResources().getConfiguration().isScreenRound(), - mAttachInfo.mAlwaysConsumeNavBar, displayCutout); + mAttachInfo.mAlwaysConsumeNavBar, displayCutout, + contentInsets, stableInsets); } else { mLastWindowInsets = new WindowInsets(contentInsets, stableInsets, mContext.getResources().getConfiguration().isScreenRound(), diff --git a/core/java/android/view/WindowInsets.java b/core/java/android/view/WindowInsets.java index 9ac0ca96ce63..e8088303eac7 100644 --- a/core/java/android/view/WindowInsets.java +++ b/core/java/android/view/WindowInsets.java @@ -217,7 +217,10 @@ public final class WindowInsets { return typeInsetMap; } - private static void assignCompatInsets(Insets[] typeInsetMap, Rect insets) { + /** + * @hide + */ + static void assignCompatInsets(Insets[] typeInsetMap, Rect insets) { typeInsetMap[indexOf(TOP_BAR)] = Insets.of(0, insets.top, 0, 0); typeInsetMap[indexOf(SIDE_BARS)] = Insets.of(insets.left, 0, insets.right, insets.bottom); } diff --git a/core/tests/coretests/src/android/view/InsetsStateTest.java b/core/tests/coretests/src/android/view/InsetsStateTest.java index 9857b7a1e035..2db2f5f2a4fd 100644 --- a/core/tests/coretests/src/android/view/InsetsStateTest.java +++ b/core/tests/coretests/src/android/view/InsetsStateTest.java @@ -60,7 +60,7 @@ public class InsetsStateTest { mState.getSource(TYPE_IME).setVisible(true); SparseIntArray typeSideMap = new SparseIntArray(); WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), false, false, - DisplayCutout.NO_CUTOUT, typeSideMap); + DisplayCutout.NO_CUTOUT, null, null, typeSideMap); assertEquals(Insets.of(0, 100, 0, 100), insets.getSystemWindowInsets()); assertEquals(Insets.of(0, 100, 0, 100), insets.getInsets(Type.all())); assertEquals(INSET_SIDE_TOP, typeSideMap.get(TYPE_TOP_BAR)); @@ -76,7 +76,7 @@ public class InsetsStateTest { mState.getSource(TYPE_IME).setFrame(new Rect(0, 100, 100, 300)); mState.getSource(TYPE_IME).setVisible(true); WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), false, false, - DisplayCutout.NO_CUTOUT, null); + DisplayCutout.NO_CUTOUT, null, null, null); assertEquals(100, insets.getStableInsetBottom()); assertEquals(Insets.of(0, 0, 0, 100), insets.getMaxInsets(Type.all())); assertEquals(Insets.of(0, 0, 0, 200), insets.getSystemWindowInsets()); @@ -92,7 +92,7 @@ public class InsetsStateTest { mState.getSource(TYPE_NAVIGATION_BAR).setFrame(new Rect(80, 0, 100, 300)); mState.getSource(TYPE_NAVIGATION_BAR).setVisible(true); WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), false, false, - DisplayCutout.NO_CUTOUT, null); + DisplayCutout.NO_CUTOUT, null, null, null); assertEquals(Insets.of(0, 100, 20, 0), insets.getSystemWindowInsets()); assertEquals(Insets.of(0, 100, 0, 0), insets.getInsets(Type.topBar())); assertEquals(Insets.of(0, 0, 20, 0), insets.getInsets(Type.sideBars())); @@ -106,7 +106,7 @@ public class InsetsStateTest { mState.getSource(TYPE_IME).setVisible(true); mState.removeSource(TYPE_IME); WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), false, false, - DisplayCutout.NO_CUTOUT, null); + DisplayCutout.NO_CUTOUT, null, null, null); assertEquals(0, insets.getSystemWindowInsetBottom()); } diff --git a/core/tests/coretests/src/android/view/WindowInsetsTest.java b/core/tests/coretests/src/android/view/WindowInsetsTest.java index 15a96a144dd5..d57fa8f9f612 100644 --- a/core/tests/coretests/src/android/view/WindowInsetsTest.java +++ b/core/tests/coretests/src/android/view/WindowInsetsTest.java @@ -18,7 +18,7 @@ package android.view; import static android.view.WindowInsets.Type.ime; import static android.view.WindowInsets.Type.sideBars; - +import static android.view.WindowInsets.Type.topBar; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; @@ -54,6 +54,7 @@ public class WindowInsetsTest { assertTrue(new WindowInsets((Rect) null).isConsumed()); } + // TODO: Move this to CTS once API made public @Test public void typeMap() { Builder b = new WindowInsets.Builder(); @@ -62,4 +63,14 @@ public class WindowInsetsTest { WindowInsets insets = b.build(); assertEquals(300, insets.getSystemWindowInsets().bottom); } + + // TODO: Move this to CTS once API made public + @Test + public void compatInsets() { + Builder b = new WindowInsets.Builder(); + b.setSystemWindowInsets(Insets.of(0, 50, 30, 10)); + WindowInsets insets = b.build(); + assertEquals(Insets.of(0, 50, 0, 0), insets.getInsets(topBar())); + assertEquals(Insets.of(0, 0, 30, 10), insets.getInsets(sideBars())); + } } diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 6527ca0e751d..8026a04ce862 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -30,11 +30,14 @@ import static android.content.res.Configuration.ORIENTATION_PORTRAIT; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.Display.FLAG_PRIVATE; import static android.view.InsetsState.TYPE_IME; +import static android.view.InsetsState.TYPE_NAVIGATION_BAR; +import static android.view.InsetsState.TYPE_TOP_BAR; import static android.view.Surface.ROTATION_0; import static android.view.Surface.ROTATION_180; import static android.view.Surface.ROTATION_270; import static android.view.Surface.ROTATION_90; import static android.view.View.GONE; +import static android.view.ViewRootImpl.NEW_INSETS_MODE_FULL; import static android.view.WindowManager.DOCKED_BOTTOM; import static android.view.WindowManager.DOCKED_INVALID; import static android.view.WindowManager.DOCKED_TOP; @@ -164,6 +167,7 @@ import android.view.SurfaceControl; import android.view.SurfaceControl.Transaction; import android.view.SurfaceSession; import android.view.View; +import android.view.ViewRootImpl; import android.view.WindowManager; import android.view.WindowManagerPolicyConstants.PointerEventListener; @@ -1051,6 +1055,11 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo */ void setInsetProvider(@InternalInsetType int type, WindowState win, @Nullable TriConsumer<DisplayFrames, WindowState, Rect> frameProvider) { + if (ViewRootImpl.sNewInsetsMode != NEW_INSETS_MODE_FULL) { + if (type == TYPE_TOP_BAR || type == TYPE_NAVIGATION_BAR) { + return; + } + } mInsetsStateController.getSourceProvider(type).setWindow(win, frameProvider); } diff --git a/services/core/java/com/android/server/wm/InsetsSourceProvider.java b/services/core/java/com/android/server/wm/InsetsSourceProvider.java index d6f161645327..e49e4c0711bd 100644 --- a/services/core/java/com/android/server/wm/InsetsSourceProvider.java +++ b/services/core/java/com/android/server/wm/InsetsSourceProvider.java @@ -16,6 +16,8 @@ package com.android.server.wm; +import static android.view.ViewRootImpl.NEW_INSETS_MODE_NONE; + import android.annotation.NonNull; import android.annotation.Nullable; import android.graphics.Rect; @@ -159,7 +161,7 @@ class InsetsSourceProvider { } boolean isClientVisible() { - return !ViewRootImpl.USE_NEW_INSETS || mClientVisible; + return ViewRootImpl.sNewInsetsMode == NEW_INSETS_MODE_NONE || mClientVisible; } private class ControlAdapter implements AnimationAdapter { diff --git a/services/core/java/com/android/server/wm/InsetsStateController.java b/services/core/java/com/android/server/wm/InsetsStateController.java index bc01f7c2595d..32dbe96d39f7 100644 --- a/services/core/java/com/android/server/wm/InsetsStateController.java +++ b/services/core/java/com/android/server/wm/InsetsStateController.java @@ -19,6 +19,9 @@ package com.android.server.wm; import static android.view.InsetsState.TYPE_IME; import static android.view.InsetsState.TYPE_NAVIGATION_BAR; import static android.view.InsetsState.TYPE_TOP_BAR; +import static android.view.ViewRootImpl.NEW_INSETS_MODE_FULL; +import static android.view.ViewRootImpl.NEW_INSETS_MODE_NONE; +import static android.view.ViewRootImpl.sNewInsetsMode; import android.annotation.NonNull; import android.annotation.Nullable; @@ -160,7 +163,7 @@ class InsetsStateController { } private void onControlChanged(int type, @Nullable WindowState win) { - if (!ViewRootImpl.USE_NEW_INSETS) { + if (sNewInsetsMode == NEW_INSETS_MODE_NONE) { return; } final WindowState previous = mTypeWinControlMap.get(type); |