From 849d65f38c4272a05bd78afbd0d4d156357fc818 Mon Sep 17 00:00:00 2001 From: Garfield Tan Date: Thu, 16 Feb 2023 12:22:59 -0800 Subject: [PATCH] Hard code caption insets for caption in WM shell We attempted to remove the hard coded caption insets for captions in WM shell before, but it revealed a synchronization issue of window frames and caption inset frames being updated separately. The proper fix to this issue is more complicated than I initially thought, so we restore the workaround in a similar way as the workaround we had for the legacy DecorCaptionView in short term. For now InsetsPolicy drops caption insets if the the layout attributes indicate the window is floating. Also restore unit tests removed because the old workaround was removed for caption in WM shell. Bug: 254128050 Test: Caption insets look correct for regular activities. Test: Floating windows (dialogs) don't get caption insets. Test: atest InsetsSourceTest Test: atest InsetsStateTest Change-Id: I15616974bbccc8662124e9efa956c180dc329cbf --- core/java/android/view/InsetsSource.java | 3 +-- .../src/android/view/InsetsSourceTest.java | 14 ++++++++++++++ .../src/android/view/InsetsStateTest.java | 12 ++++++++++++ .../java/com/android/server/wm/InsetsPolicy.java | 13 +++++++++++++ 4 files changed, 40 insertions(+), 2 deletions(-) diff --git a/core/java/android/view/InsetsSource.java b/core/java/android/view/InsetsSource.java index e02e600f53c8e..39477380e196f 100644 --- a/core/java/android/view/InsetsSource.java +++ b/core/java/android/view/InsetsSource.java @@ -20,7 +20,6 @@ import static android.view.InsetsSourceProto.FRAME; import static android.view.InsetsSourceProto.TYPE; import static android.view.InsetsSourceProto.VISIBLE; import static android.view.InsetsSourceProto.VISIBLE_FRAME; -import static android.view.ViewRootImpl.CAPTION_ON_SHELL; import static android.view.WindowInsets.Type.ime; import android.annotation.IntRange; @@ -169,7 +168,7 @@ public class InsetsSource implements Parcelable { // During drag-move and drag-resizing, the caption insets position may not get updated // before the app frame get updated. To layout the app content correctly during drag events, // we always return the insets with the corresponding height covering the top. - if (!CAPTION_ON_SHELL && getType() == WindowInsets.Type.captionBar()) { + if (getType() == WindowInsets.Type.captionBar()) { return Insets.of(0, frame.height(), 0, 0); } // Checks for whether there is shared edge with insets for 0-width/height window. diff --git a/core/tests/coretests/src/android/view/InsetsSourceTest.java b/core/tests/coretests/src/android/view/InsetsSourceTest.java index 1db6587e12836..6fa8f11173438 100644 --- a/core/tests/coretests/src/android/view/InsetsSourceTest.java +++ b/core/tests/coretests/src/android/view/InsetsSourceTest.java @@ -19,6 +19,7 @@ package android.view; import static android.view.WindowInsets.Type.FIRST; import static android.view.WindowInsets.Type.LAST; import static android.view.WindowInsets.Type.SIZE; +import static android.view.WindowInsets.Type.captionBar; import static android.view.WindowInsets.Type.ime; import static android.view.WindowInsets.Type.navigationBars; @@ -51,11 +52,13 @@ public class InsetsSourceTest { private final InsetsSource mSource = new InsetsSource(0 /* id */, navigationBars()); private final InsetsSource mImeSource = new InsetsSource(1 /* id */, ime()); + private final InsetsSource mCaptionSource = new InsetsSource(2 /* id */, captionBar()); @Before public void setUp() { mSource.setVisible(true); mImeSource.setVisible(true); + mCaptionSource.setVisible(true); } @Test @@ -106,6 +109,17 @@ public class InsetsSourceTest { assertEquals(Insets.of(0, 0, 0, 100), insets); } + @Test + public void testCalculateInsets_caption_resizing() { + mCaptionSource.setFrame(new Rect(0, 0, 100, 100)); + Insets insets = mCaptionSource.calculateInsets(new Rect(0, 0, 200, 200), false); + assertEquals(Insets.of(0, 100, 0, 0), insets); + insets = mCaptionSource.calculateInsets(new Rect(0, 0, 50, 200), false); + assertEquals(Insets.of(0, 100, 0, 0), insets); + insets = mCaptionSource.calculateInsets(new Rect(100, 100, 200, 500), false); + assertEquals(Insets.of(0, 100, 0, 0), insets); + } + @Test public void testCalculateInsets_invisible() { mSource.setFrame(new Rect(0, 0, 500, 100)); diff --git a/core/tests/coretests/src/android/view/InsetsStateTest.java b/core/tests/coretests/src/android/view/InsetsStateTest.java index b035c23cb98b7..fde1a6d7b04c4 100644 --- a/core/tests/coretests/src/android/view/InsetsStateTest.java +++ b/core/tests/coretests/src/android/view/InsetsStateTest.java @@ -247,6 +247,18 @@ public class InsetsStateTest { assertEquals(Insets.of(0, 300, 0, 0), visibleInsets); } + @Test + public void testCalculateInsets_captionBarOffset() { + mState.getOrCreateSource(ID_CAPTION_BAR, captionBar()) + .setFrame(new Rect(0, 0, 100, 300)) + .setVisible(true); + + Insets visibleInsets = mState.calculateVisibleInsets( + new Rect(0, 0, 150, 400), TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED, + SOFT_INPUT_ADJUST_NOTHING, 0 /* windowFlags */); + assertEquals(Insets.of(0, 300, 0, 0), visibleInsets); + } + @Test public void testCalculateInsets_extraNavRightStatusTop() { mState.getOrCreateSource(ID_STATUS_BAR, statusBars()) diff --git a/services/core/java/com/android/server/wm/InsetsPolicy.java b/services/core/java/com/android/server/wm/InsetsPolicy.java index 25ce5699ab71c..210a7d9538c78 100644 --- a/services/core/java/com/android/server/wm/InsetsPolicy.java +++ b/services/core/java/com/android/server/wm/InsetsPolicy.java @@ -344,6 +344,19 @@ class InsetsPolicy { } } + if (!attrs.isFullscreen() || attrs.getFitInsetsTypes() != 0) { + if (state == originalState) { + state = new InsetsState(originalState); + } + // Explicitly exclude floating windows from receiving caption insets. This is because we + // hard code caption insets for windows due to a synchronization issue that leads to + // flickering that bypasses insets frame calculation, which consequently needs us to + // remove caption insets from floating windows. + // TODO(b/254128050): Remove this workaround after we find a way to update window frames + // and caption insets frames simultaneously. + state.removeSource(InsetsState.ITYPE_CAPTION_BAR); + } + final SparseArray providers = mStateController.getSourceProviders(); final int windowType = attrs.type;