From 2fe072693bafb10896daf21e01055dec0936e100 Mon Sep 17 00:00:00 2001 From: Yongjin Kwon Date: Tue, 3 Sep 2019 10:47:28 +0900 Subject: [PATCH] [wm]: Fixed layout problem in PolicyControl immersive mode If immersive mode is enabled by policy_control Setting, immersive mode is forcibly applied to all windows. And systemui flags for immersive mode are added to non fullscreen window by system. If non fullscreen window requests BOTTOM gravity layout, it is covered by input method window. Ensure content frame according to input method window. Test: manual - manually enable immersive mode with next command. adb shell settings put global policy_control "immersive.full=*" And select input field in dialog window which has BOTTOM gravity. Test: atest WmTests:DisplayPolicyLayoutTests Bug: 129711077 Change-Id: I22617878d2025327b8323ef4dd03d043da2da552 (cherry picked from commit d90433afee1438c5a4a1a9be92343a197fa53cd7) --- .../com/android/server/wm/PolicyControl.java | 18 ++- .../server/wm/DisplayPolicyLayoutTests.java | 114 ++++++++++++++++++ .../server/wm/DisplayPolicyTestsBase.java | 1 + 3 files changed, 128 insertions(+), 5 deletions(-) diff --git a/services/core/java/com/android/server/wm/PolicyControl.java b/services/core/java/com/android/server/wm/PolicyControl.java index 4c8ce9ebb72cc..0f92bc83a6666 100644 --- a/services/core/java/com/android/server/wm/PolicyControl.java +++ b/services/core/java/com/android/server/wm/PolicyControl.java @@ -26,6 +26,8 @@ import android.view.View; import android.view.WindowManager; import android.view.WindowManager.LayoutParams; +import com.android.internal.annotations.VisibleForTesting; + import java.io.PrintWriter; import java.io.StringWriter; @@ -51,7 +53,8 @@ class PolicyControl { private static final String TAG = "PolicyControl"; private static final boolean DEBUG = false; - private static final String NAME_IMMERSIVE_FULL = "immersive.full"; + @VisibleForTesting + static final String NAME_IMMERSIVE_FULL = "immersive.full"; private static final String NAME_IMMERSIVE_STATUS = "immersive.status"; private static final String NAME_IMMERSIVE_NAVIGATION = "immersive.navigation"; private static final String NAME_IMMERSIVE_PRECONFIRMATIONS = "immersive.preconfirms"; @@ -67,15 +70,19 @@ class PolicyControl { : (attrs.systemUiVisibility | attrs.subtreeSystemUiVisibility); if (sImmersiveStatusFilter != null && sImmersiveStatusFilter.matches(attrs)) { vis |= View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY - | View.SYSTEM_UI_FLAG_FULLSCREEN - | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN; + | View.SYSTEM_UI_FLAG_FULLSCREEN; + if (attrs.isFullscreen()) { + vis |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN; + } vis &= ~(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.STATUS_BAR_TRANSLUCENT); } if (sImmersiveNavigationFilter != null && sImmersiveNavigationFilter.matches(attrs)) { vis |= View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY - | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; + if (attrs.isFullscreen()) { + vis |= View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION; + } vis &= ~(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.NAVIGATION_BAR_TRANSLUCENT); } @@ -144,7 +151,8 @@ class PolicyControl { } } - private static void setFilters(String value) { + @VisibleForTesting + static void setFilters(String value) { if (DEBUG) Slog.d(TAG, "setFilters: " + value); sImmersiveStatusFilter = null; sImmersiveNavigationFilter = null; diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java index 2a3731a2e4835..67b7a66b4794e 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java @@ -24,6 +24,7 @@ import static android.view.Surface.ROTATION_0; import static android.view.Surface.ROTATION_270; import static android.view.Surface.ROTATION_90; import static android.view.View.SYSTEM_UI_FLAG_FULLSCREEN; +import static android.view.View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; 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.ViewGroup.LayoutParams.MATCH_PARENT; @@ -56,15 +57,23 @@ import android.view.DisplayCutout; import android.view.DisplayInfo; import android.view.WindowManager; +import androidx.test.filters.FlakyTest; import androidx.test.filters.SmallTest; import com.android.server.policy.WindowManagerPolicy; import com.android.server.wm.utils.WmDisplayCutout; +import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +/** + * Tests for the {@link DisplayPolicy} class. + * + * Build/Install/Run: + * atest WmTests:DisplayPolicyLayoutTests + */ @SmallTest @Presubmit @RunWith(WindowTestRunner.class) @@ -93,6 +102,12 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase { attrs.format = PixelFormat.TRANSLUCENT; } + @After + public void tearDown() { + PolicyControl.setFilters(""); + mWindow.getDisplayContent().mInputMethodTarget = null; + } + public void setRotation(int rotation) { mRotation = rotation; updateDisplayFrames(); @@ -393,6 +408,105 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase { assertInsetBy(mWindow.getDisplayFrameLw(), 0, 0, 0, 0); } + @FlakyTest(bugId = 129711077) + @Test + public void layoutWindowLw_withImmersive_SoftInputAdjustResize() { + synchronized (mWm.mGlobalLock) { + mWindow.mAttrs.softInputMode = SOFT_INPUT_ADJUST_RESIZE; + mWindow.mAttrs.flags = 0; + mWindow.mAttrs.systemUiVisibility = + SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION + | SYSTEM_UI_FLAG_FULLSCREEN | SYSTEM_UI_FLAG_HIDE_NAVIGATION; + + addWindow(mWindow); + + mWindow.getDisplayContent().mInputMethodTarget = mWindow; + mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); + mFrames.mContent.bottom = mFrames.mVoiceContent.bottom = INPUT_METHOD_WINDOW_TOP; + mFrames.mCurrent.bottom = INPUT_METHOD_WINDOW_TOP; + mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); + + int bottomInset = mFrames.mDisplayHeight - INPUT_METHOD_WINDOW_TOP; + assertInsetByTopBottom(mWindow.getParentFrame(), 0, 0); + assertInsetByTopBottom(mWindow.getContentFrameLw(), 0, 0); + assertInsetByTopBottom(mWindow.getVisibleFrameLw(), STATUS_BAR_HEIGHT, bottomInset); + } + } + + @FlakyTest(bugId = 129711077) + @Test + public void layoutWindowLw_withImmersive_SoftInputAdjustNothing() { + synchronized (mWm.mGlobalLock) { + mWindow.mAttrs.softInputMode = SOFT_INPUT_ADJUST_NOTHING; + mWindow.mAttrs.flags = 0; + mWindow.mAttrs.systemUiVisibility = + SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION + | SYSTEM_UI_FLAG_FULLSCREEN | SYSTEM_UI_FLAG_HIDE_NAVIGATION; + + addWindow(mWindow); + + mWindow.getDisplayContent().mInputMethodTarget = mWindow; + mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); + mFrames.mContent.bottom = mFrames.mVoiceContent.bottom = INPUT_METHOD_WINDOW_TOP; + mFrames.mCurrent.bottom = INPUT_METHOD_WINDOW_TOP; + mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); + + assertInsetByTopBottom(mWindow.getParentFrame(), 0, 0); + assertInsetByTopBottom(mWindow.getContentFrameLw(), 0, 0); + assertInsetByTopBottom(mWindow.getVisibleFrameLw(), 0, 0); + } + } + + @FlakyTest(bugId = 129711077) + @Test + public void layoutWindowLw_withForceImmersive_fullscreen() { + synchronized (mWm.mGlobalLock) { + mWindow.mAttrs.softInputMode = SOFT_INPUT_ADJUST_RESIZE; + mWindow.mAttrs.flags = 0; + mWindow.mAttrs.systemUiVisibility = 0; + PolicyControl.setFilters(PolicyControl.NAME_IMMERSIVE_FULL + "=*"); + + addWindow(mWindow); + + mWindow.getDisplayContent().mInputMethodTarget = mWindow; + mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); + mFrames.mContent.bottom = mFrames.mVoiceContent.bottom = INPUT_METHOD_WINDOW_TOP; + mFrames.mCurrent.bottom = INPUT_METHOD_WINDOW_TOP; + mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); + + int bottomInset = mFrames.mDisplayHeight - INPUT_METHOD_WINDOW_TOP; + assertInsetByTopBottom(mWindow.getParentFrame(), 0, 0); + assertInsetByTopBottom(mWindow.getContentFrameLw(), 0, 0); + assertInsetByTopBottom(mWindow.getVisibleFrameLw(), STATUS_BAR_HEIGHT, bottomInset); + } + } + + @FlakyTest(bugId = 129711077) + @Test + public void layoutWindowLw_withForceImmersive_nonFullscreen() { + synchronized (mWm.mGlobalLock) { + mWindow.mAttrs.softInputMode = SOFT_INPUT_ADJUST_RESIZE; + mWindow.mAttrs.flags = 0; + mWindow.mAttrs.systemUiVisibility = 0; + mWindow.mAttrs.width = DISPLAY_WIDTH / 2; + mWindow.mAttrs.height = DISPLAY_HEIGHT / 2; + PolicyControl.setFilters(PolicyControl.NAME_IMMERSIVE_FULL + "=*"); + + addWindow(mWindow); + + mWindow.getDisplayContent().mInputMethodTarget = mWindow; + mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); + mFrames.mContent.bottom = mFrames.mVoiceContent.bottom = INPUT_METHOD_WINDOW_TOP; + mFrames.mCurrent.bottom = INPUT_METHOD_WINDOW_TOP; + mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); + + int bottomInset = mFrames.mDisplayHeight - INPUT_METHOD_WINDOW_TOP; + assertInsetByTopBottom(mWindow.getParentFrame(), STATUS_BAR_HEIGHT, bottomInset); + assertInsetByTopBottom(mWindow.getContentFrameLw(), STATUS_BAR_HEIGHT, bottomInset); + assertInsetByTopBottom(mWindow.getVisibleFrameLw(), STATUS_BAR_HEIGHT, bottomInset); + } + } + @Test public void layoutHint_appWindow() { // Initialize DisplayFrames diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTestsBase.java index 2933b4a460d82..d4558dc29fda0 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTestsBase.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTestsBase.java @@ -62,6 +62,7 @@ public class DisplayPolicyTestsBase extends WindowTestsBase { static final int STATUS_BAR_HEIGHT = 10; static final int NAV_BAR_HEIGHT = 15; static final int DISPLAY_CUTOUT_HEIGHT = 8; + static final int INPUT_METHOD_WINDOW_TOP = 585; DisplayPolicy mDisplayPolicy;