From 5fb9ab7ddf27330d099581bd78753a5f17a20ac3 Mon Sep 17 00:00:00 2001 From: Tiger Huang Date: Mon, 2 Mar 2020 16:16:01 +0800 Subject: [PATCH] Refine adjustLayoutParamsForCompatibility about fitting insets By the compatible logic in DisplayPolicy.layoutWidnowLw(), if a regular window (non-TYPE_STATUS_BAR_PANEL, non-TYPE_TOAST, and non-TYPE_SYSTEM_ALERT) doesn't extend into any of system bars, it should fit IME. The logic was implemented by pf.set(displayFrames.mContent) in the legacy insets mode, where mContent would be adjusted after processing IME. Fix: 149838078 Test: Steps in the target issue Test: atest ViewRootImplTest Change-Id: I6eb685fa1e3ad9789621e5647fc490300054db8b --- core/java/android/view/ViewRootImpl.java | 9 +-- .../src/android/view/ViewRootImplTest.java | 74 ++++++++++++++++--- 2 files changed, 67 insertions(+), 16 deletions(-) diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 9733448b890b0..36257d9f5fd9f 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -52,8 +52,6 @@ import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_APPEARANCE_CO import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_BEHAVIOR_CONTROLLED; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FIT_INSETS_CONTROLLED; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DECOR_VIEW_VISIBILITY; -import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE; -import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST; import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD; import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL; import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ALERT; @@ -2009,7 +2007,6 @@ public final class ViewRootImpl implements ViewParent, final int sysUiVis = inOutParams.systemUiVisibility | inOutParams.subtreeSystemUiVisibility; final int flags = inOutParams.flags; final int type = inOutParams.type; - final int adjust = inOutParams.softInputMode & SOFT_INPUT_MASK_ADJUST; if ((inOutParams.privateFlags & PRIVATE_FLAG_APPEARANCE_CONTROLLED) == 0) { inOutParams.insetsFlags.appearance = 0; @@ -2054,8 +2051,7 @@ public final class ViewRootImpl implements ViewParent, } if (type == TYPE_TOAST || type == TYPE_SYSTEM_ALERT) { ignoreVis = true; - } else if ((types & Type.systemBars()) == Type.systemBars() - && adjust == SOFT_INPUT_ADJUST_RESIZE) { + } else if ((types & Type.systemBars()) == Type.systemBars()) { types |= Type.ime(); } inOutParams.setFitInsetsTypes(types); @@ -2261,7 +2257,8 @@ public final class ViewRootImpl implements ViewParent, mAttachInfo.mVisibleInsets.set(visibleInsets); } - InsetsController getInsetsController() { + @VisibleForTesting + public InsetsController getInsetsController() { return mInsetsController; } diff --git a/core/tests/coretests/src/android/view/ViewRootImplTest.java b/core/tests/coretests/src/android/view/ViewRootImplTest.java index e2adbcc600d7d..0d497e113537c 100644 --- a/core/tests/coretests/src/android/view/ViewRootImplTest.java +++ b/core/tests/coretests/src/android/view/ViewRootImplTest.java @@ -16,9 +16,13 @@ package android.view; +import static android.view.View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY; import static android.view.View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN; import static android.view.View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION; -import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS; +import static android.view.View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR; +import static android.view.View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; +import static android.view.View.SYSTEM_UI_FLAG_LOW_PROFILE; +import static android.view.WindowInsetsController.BEHAVIOR_SHOW_BARS_BY_TOUCH; import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION; import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ALERT; @@ -102,79 +106,129 @@ public class ViewRootImplTest { } @Test - public void adjustLayoutParamsForInsets_layoutFullscreen() { + public void adjustLayoutParamsForCompatibility_layoutFullscreen() { assumeTrue(ViewRootImpl.sNewInsetsMode == ViewRootImpl.NEW_INSETS_MODE_FULL); final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(TYPE_APPLICATION); attrs.systemUiVisibility = SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN; ViewRootImpl.adjustLayoutParamsForCompatibility(attrs); + // Type.statusBars() must be removed. assertEquals(0, attrs.getFitInsetsTypes() & Type.statusBars()); } @Test - public void adjustLayoutParamsForInsets_layoutInScreen() { + public void adjustLayoutParamsForCompatibility_layoutInScreen() { assumeTrue(ViewRootImpl.sNewInsetsMode == ViewRootImpl.NEW_INSETS_MODE_FULL); final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(TYPE_APPLICATION); attrs.flags = FLAG_LAYOUT_IN_SCREEN; ViewRootImpl.adjustLayoutParamsForCompatibility(attrs); + // Type.statusBars() must be removed. assertEquals(0, attrs.getFitInsetsTypes() & Type.statusBars()); } @Test - public void adjustLayoutParamsForInsets_layoutHideNavigation() { + public void adjustLayoutParamsForCompatibility_layoutHideNavigation() { assumeTrue(ViewRootImpl.sNewInsetsMode == ViewRootImpl.NEW_INSETS_MODE_FULL); final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(TYPE_APPLICATION); attrs.systemUiVisibility = SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION; ViewRootImpl.adjustLayoutParamsForCompatibility(attrs); + // Type.systemBars() must be removed. assertEquals(0, attrs.getFitInsetsTypes() & Type.systemBars()); } @Test - public void adjustLayoutParamsForInsets_toast() { + public void adjustLayoutParamsForCompatibility_toast() { assumeTrue(ViewRootImpl.sNewInsetsMode == ViewRootImpl.NEW_INSETS_MODE_FULL); final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(TYPE_TOAST); ViewRootImpl.adjustLayoutParamsForCompatibility(attrs); - assertEquals(Type.systemBars(), attrs.getFitInsetsTypes() & Type.systemBars()); assertEquals(true, attrs.isFitInsetsIgnoringVisibility()); } @Test - public void adjustLayoutParamsForInsets_systemAlert() { + public void adjustLayoutParamsForCompatibility_systemAlert() { assumeTrue(ViewRootImpl.sNewInsetsMode == ViewRootImpl.NEW_INSETS_MODE_FULL); final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(TYPE_SYSTEM_ALERT); ViewRootImpl.adjustLayoutParamsForCompatibility(attrs); - assertEquals(Type.systemBars(), attrs.getFitInsetsTypes() & Type.systemBars()); assertEquals(true, attrs.isFitInsetsIgnoringVisibility()); } @Test - public void adjustLayoutParamsForInsets_noAdjust() { + public void adjustLayoutParamsForCompatibility_fitSystemBars() { + assumeTrue(ViewRootImpl.sNewInsetsMode == ViewRootImpl.NEW_INSETS_MODE_FULL); + + final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(TYPE_APPLICATION); + ViewRootImpl.adjustLayoutParamsForCompatibility(attrs); + + // A window which fits system bars must fit IME, unless its type is toast or system alert. + assertEquals(Type.systemBars() | Type.ime(), attrs.getFitInsetsTypes()); + } + + @Test + public void adjustLayoutParamsForCompatibility_noAdjustLayout() { assumeTrue(ViewRootImpl.sNewInsetsMode == ViewRootImpl.NEW_INSETS_MODE_FULL); final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(TYPE_APPLICATION); final int types = Type.all(); final int sides = Side.TOP | Side.LEFT; final boolean fitMaxInsets = true; - attrs.flags = FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS; + attrs.systemUiVisibility = SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN; attrs.setFitInsetsTypes(types); attrs.setFitInsetsSides(sides); attrs.setFitInsetsIgnoringVisibility(fitMaxInsets); ViewRootImpl.adjustLayoutParamsForCompatibility(attrs); + // Fit-insets related fields must not be adjusted due to legacy system UI visibility + // after calling fit-insets related methods. assertEquals(types, attrs.getFitInsetsTypes()); assertEquals(sides, attrs.getFitInsetsSides()); assertEquals(fitMaxInsets, attrs.isFitInsetsIgnoringVisibility()); } + @Test + public void adjustLayoutParamsForCompatibility_noAdjustAppearance() { + assumeTrue(ViewRootImpl.sNewInsetsMode == ViewRootImpl.NEW_INSETS_MODE_FULL); + + final ViewRootImpl viewRoot = mViewRootImpl.get(); + final WindowInsetsController controller = viewRoot.getInsetsController(); + final WindowManager.LayoutParams attrs = viewRoot.mWindowAttributes; + final int appearance = 0; + controller.setSystemBarsAppearance(appearance, 0xffffffff); + attrs.systemUiVisibility = SYSTEM_UI_FLAG_LOW_PROFILE + | SYSTEM_UI_FLAG_LIGHT_STATUS_BAR + | SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR; + ViewRootImpl.adjustLayoutParamsForCompatibility(attrs); + + // Appearance must not be adjusted due to legacy system UI visibility after calling + // setSystemBarsAppearance. + assertEquals(appearance, controller.getSystemBarsAppearance()); + } + + @Test + public void adjustLayoutParamsForCompatibility_noAdjustBehavior() { + assumeTrue(ViewRootImpl.sNewInsetsMode == ViewRootImpl.NEW_INSETS_MODE_FULL); + + final ViewRootImpl viewRoot = mViewRootImpl.get(); + final WindowInsetsController controller = viewRoot.getInsetsController(); + final WindowManager.LayoutParams attrs = viewRoot.mWindowAttributes; + final int behavior = BEHAVIOR_SHOW_BARS_BY_TOUCH; + controller.setSystemBarsBehavior(behavior); + attrs.systemUiVisibility = SYSTEM_UI_FLAG_IMMERSIVE_STICKY; + ViewRootImpl.adjustLayoutParamsForCompatibility(attrs); + + // Behavior must not be adjusted due to legacy system UI visibility after calling + // setSystemBarsBehavior. + assertEquals(behavior, controller.getSystemBarsBehavior()); + } + private static class ViewRootImplAccessor { private final ViewRootImpl mViewRootImpl;