From 7dbb0540c0ffed0dde7fab11d477188ffc25c32b Mon Sep 17 00:00:00 2001 From: Tiger Huang Date: Wed, 6 Jan 2021 19:10:02 +0800 Subject: Preserve the controlling state of appearance and behavior Make sure the appearance or the behavior controlled by the new APIs won't be affected by setting new LayoutParams. This CL also makes ViewRootImpl#setLayoutParams won't modify the caller's LayoutParams. Fix: 175169461 Test: atest ViewRootImplTest Change-Id: I4cdd846e8638f9813146e6461134e4dd1606bd50 --- core/java/android/view/ViewRootImpl.java | 28 ++++++++++++++-------- .../src/android/view/ViewRootImplTest.java | 17 ++++++++++--- 2 files changed, 32 insertions(+), 13 deletions(-) diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 24989b60cf46..7d309eb36483 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -1389,7 +1389,8 @@ public final class ViewRootImpl implements ViewParent, return mLocation; } - void setLayoutParams(WindowManager.LayoutParams attrs, boolean newView) { + @VisibleForTesting + public void setLayoutParams(WindowManager.LayoutParams attrs, boolean newView) { synchronized (this) { final int oldInsetLeft = mWindowAttributes.surfaceInsets.left; final int oldInsetTop = mWindowAttributes.surfaceInsets.top; @@ -1411,13 +1412,15 @@ public final class ViewRootImpl implements ViewParent, final int compatibleWindowFlag = mWindowAttributes.privateFlags & WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW; - // Transfer over system UI visibility values as they carry current state. - attrs.systemUiVisibility = mWindowAttributes.systemUiVisibility; - attrs.subtreeSystemUiVisibility = mWindowAttributes.subtreeSystemUiVisibility; + // Preserve system UI visibility. + final int systemUiVisibility = mWindowAttributes.systemUiVisibility; + final int subtreeSystemUiVisibility = mWindowAttributes.subtreeSystemUiVisibility; - // Transfer over appearance and behavior values as they carry current state. - attrs.insetsFlags.appearance = mWindowAttributes.insetsFlags.appearance; - attrs.insetsFlags.behavior = mWindowAttributes.insetsFlags.behavior; + // Preserve appearance and behavior. + final int appearance = mWindowAttributes.insetsFlags.appearance; + final int behavior = mWindowAttributes.insetsFlags.behavior; + final int appearanceAndBehaviorPrivateFlags = mWindowAttributes.privateFlags + & (PRIVATE_FLAG_APPEARANCE_CONTROLLED | PRIVATE_FLAG_BEHAVIOR_CONTROLLED); final int changes = mWindowAttributes.copyFrom(attrs); if ((changes & WindowManager.LayoutParams.TRANSLUCENT_FLAGS_CHANGED) != 0) { @@ -1431,10 +1434,15 @@ public final class ViewRootImpl implements ViewParent, if (mWindowAttributes.packageName == null) { mWindowAttributes.packageName = mBasePackageName; } - mWindowAttributes.privateFlags |= compatibleWindowFlag; - mWindowAttributes.privateFlags |= - WindowManager.LayoutParams.PRIVATE_FLAG_USE_BLAST; + // Restore preserved flags. + mWindowAttributes.systemUiVisibility = systemUiVisibility; + mWindowAttributes.subtreeSystemUiVisibility = subtreeSystemUiVisibility; + mWindowAttributes.insetsFlags.appearance = appearance; + mWindowAttributes.insetsFlags.behavior = behavior; + mWindowAttributes.privateFlags |= compatibleWindowFlag + | appearanceAndBehaviorPrivateFlags + | WindowManager.LayoutParams.PRIVATE_FLAG_USE_BLAST; if (mWindowAttributes.preservePreviousSurfaceInsets) { // Restore old surface insets. diff --git a/core/tests/coretests/src/android/view/ViewRootImplTest.java b/core/tests/coretests/src/android/view/ViewRootImplTest.java index 4cf6715ba0ca..830771c5c4d8 100644 --- a/core/tests/coretests/src/android/view/ViewRootImplTest.java +++ b/core/tests/coretests/src/android/view/ViewRootImplTest.java @@ -22,7 +22,8 @@ import static android.view.View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION; 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.WindowInsetsController.APPEARANCE_OPAQUE_STATUS_BARS; +import static android.view.WindowInsetsController.BEHAVIOR_SHOW_BARS_BY_SWIPE; import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN; import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION; @@ -153,7 +154,7 @@ public class ViewRootImplTest { public void adjustLayoutParamsForCompatibility_noAdjustAppearance() { final WindowInsetsController controller = mViewRootImpl.getInsetsController(); final WindowManager.LayoutParams attrs = mViewRootImpl.mWindowAttributes; - final int appearance = 0; + final int appearance = APPEARANCE_OPAQUE_STATUS_BARS; controller.setSystemBarsAppearance(appearance, 0xffffffff); attrs.systemUiVisibility = SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_LIGHT_STATUS_BAR @@ -163,13 +164,18 @@ public class ViewRootImplTest { // Appearance must not be adjusted due to legacy system UI visibility after calling // setSystemBarsAppearance. assertEquals(appearance, controller.getSystemBarsAppearance()); + + mViewRootImpl.setLayoutParams(new WindowManager.LayoutParams(), false); + + // Appearance must not be adjusted due to setting new LayoutParams. + assertEquals(appearance, controller.getSystemBarsAppearance()); } @Test public void adjustLayoutParamsForCompatibility_noAdjustBehavior() { final WindowInsetsController controller = mViewRootImpl.getInsetsController(); final WindowManager.LayoutParams attrs = mViewRootImpl.mWindowAttributes; - final int behavior = BEHAVIOR_SHOW_BARS_BY_TOUCH; + final int behavior = BEHAVIOR_SHOW_BARS_BY_SWIPE; controller.setSystemBarsBehavior(behavior); attrs.systemUiVisibility = SYSTEM_UI_FLAG_IMMERSIVE_STICKY; ViewRootImpl.adjustLayoutParamsForCompatibility(attrs); @@ -177,5 +183,10 @@ public class ViewRootImplTest { // Behavior must not be adjusted due to legacy system UI visibility after calling // setSystemBarsBehavior. assertEquals(behavior, controller.getSystemBarsBehavior()); + + mViewRootImpl.setLayoutParams(new WindowManager.LayoutParams(), false); + + // Behavior must not be adjusted due to setting new LayoutParams. + assertEquals(behavior, controller.getSystemBarsBehavior()); } } -- cgit v1.2.3-59-g8ed1b