From 16ec9faad5b9b1808a100d6a4116ef6346a14664 Mon Sep 17 00:00:00 2001 From: Jerry Chang Date: Mon, 24 May 2021 15:41:53 +0000 Subject: [PATCH] Prevent rendering divider bar into wrong orientation The display area's bounds and orientation changed might be callbacked seperatedly when the device's folded state changed, causing the SplitLayout rendered divider bar into wrong orientation. This makes sure to update divider bar and split layout correspondingly when the orientation, rotation and root bounds chagned. Fix: 189101216 Test: atest WMShellUnitTests Change-Id: Ie5d7132e4122b82d9b5b404a40f97cca3095ce2c --- .../wm/shell/common/split/SplitLayout.java | 44 +++++++++++++------ .../shell/common/split/SplitLayoutTests.java | 27 +++++++++--- 2 files changed, 51 insertions(+), 20 deletions(-) diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java index e42f511eb3914..a445707d85a07 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java @@ -92,12 +92,16 @@ public final class SplitLayout { private DividerSnapAlgorithm mDividerSnapAlgorithm; private int mDividePosition; private boolean mInitialized = false; + private int mOrientation; + private int mRotation; public SplitLayout(String windowName, Context context, Configuration configuration, SplitLayoutHandler splitLayoutHandler, SplitWindowManager.ParentContainerCallbacks parentContainerCallbacks, DisplayImeController displayImeController, ShellTaskOrganizer taskOrganizer) { mContext = context.createConfigurationContext(configuration); + mOrientation = configuration.orientation; + mRotation = configuration.windowConfiguration.getRotation(); mSplitLayoutHandler = splitLayoutHandler; mDisplayImeController = displayImeController; mSplitWindowManager = new SplitWindowManager( @@ -144,25 +148,37 @@ public final class SplitLayout { /** Applies new configuration, returns {@code false} if there's no effect to the layout. */ public boolean updateConfiguration(Configuration configuration) { + boolean affectsLayout = false; + + // Make sure to render the divider bar with proper resources that matching the screen + // orientation. + final int orientation = configuration.orientation; + if (orientation != mOrientation) { + mOrientation = orientation; + mContext = mContext.createConfigurationContext(configuration); + mSplitWindowManager.setConfiguration(configuration); + affectsLayout = true; + } + + // Update the split bounds when necessary. Besides root bounds changed, split bounds need to + // be updated when the rotation changed to cover the case that users rotated the screen 180 + // degrees. + final int rotation = configuration.windowConfiguration.getRotation(); final Rect rootBounds = configuration.windowConfiguration.getBounds(); - if (mRootBounds.equals(rootBounds)) { - return false; + if (rotation != mRotation || !mRootBounds.equals(rootBounds)) { + mRootBounds.set(rootBounds); + mDividerSnapAlgorithm = getSnapAlgorithm(mContext, mRootBounds); + resetDividerPosition(); + affectsLayout = true; } - mContext = mContext.createConfigurationContext(configuration); - mSplitWindowManager.setConfiguration(configuration); - mRootBounds.set(rootBounds); - mDividerSnapAlgorithm = getSnapAlgorithm(mContext, mRootBounds); - resetDividerPosition(); - - // Don't inflate divider bar if it is not initialized. - if (!mInitialized) { - return false; + if (mInitialized && affectsLayout) { + release(); + init(); + return true; } - release(); - init(); - return true; + return false; } /** Updates recording bounds of divider window and both of the splits. */ diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java index 952dc31cdaee6..d865f71db5b6d 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java @@ -61,7 +61,7 @@ public class SplitLayoutTests extends ShellTestCase { mSplitLayout = new SplitLayout( "TestSplitLayout", mContext, - getConfiguration(false), + getConfiguration(), mSplitLayoutHandler, b -> b.setParent(mRootLeash), mDisplayImeController, @@ -71,9 +71,23 @@ public class SplitLayoutTests extends ShellTestCase { @Test @UiThreadTest public void testUpdateConfiguration() { + final Configuration config = getConfiguration(); mSplitLayout.init(); - assertThat(mSplitLayout.updateConfiguration(getConfiguration(false))).isFalse(); - assertThat(mSplitLayout.updateConfiguration(getConfiguration(true))).isTrue(); + + // Verify it returns true if new config won't affect split layout. + assertThat(mSplitLayout.updateConfiguration(config)).isFalse(); + + // Verify updateConfiguration returns true if the orientation changed. + config.orientation = ORIENTATION_LANDSCAPE; + assertThat(mSplitLayout.updateConfiguration(config)).isTrue(); + + // Verify updateConfiguration returns true if it rotated. + config.windowConfiguration.setRotation(1); + assertThat(mSplitLayout.updateConfiguration(config)).isTrue(); + + // Verify updateConfiguration returns true if the root bounds changed. + config.windowConfiguration.setBounds(new Rect(0, 0, 2160, 1080)); + assertThat(mSplitLayout.updateConfiguration(config)).isTrue(); } @Test @@ -108,12 +122,13 @@ public class SplitLayoutTests extends ShellTestCase { verify(mSplitLayoutHandler).onSnappedToDismiss(eq(true)); } - private static Configuration getConfiguration(boolean isLandscape) { + private static Configuration getConfiguration() { final Configuration configuration = new Configuration(); configuration.unset(); - configuration.orientation = isLandscape ? ORIENTATION_LANDSCAPE : ORIENTATION_PORTRAIT; + configuration.orientation = ORIENTATION_PORTRAIT; + configuration.windowConfiguration.setRotation(0); configuration.windowConfiguration.setBounds( - new Rect(0, 0, isLandscape ? 2160 : 1080, isLandscape ? 1080 : 2160)); + new Rect(0, 0, 1080, 2160)); return configuration; }