From ea5f48562f33acaa22deb2863b5fe2d6a3b11e42 Mon Sep 17 00:00:00 2001 From: Evan Rosky Date: Tue, 18 Aug 2020 13:52:04 -0700 Subject: [PATCH] Fix screenlayout calculation with overridden screenW/Hdp Split-screen adjust-for-ime overrides screenW/Hdp in order to prevent the app-configuration from changing. However, the logic in Task#computeConfigResourceOverrides was ignoring the overrides and blindly using the display's non-decor bounds. This means that on loong screens, the app will flip into/out-of long layout when adjusting (non-adjusted task has no screenSizeDp overrides so it goes through logic which crops mTmpNonDecorBounds). Fix this by honoring the screenW/Hdp overrides when calculating screenLayout. Bug: 163848060 Test: On long screen (eg 21:9 aspect), open ime in second split. Also added regression unit-test. Change-Id: I0fcec4f035e466fafedc31be5925c0b04a6580f7 --- .../core/java/com/android/server/wm/Task.java | 12 +++++++-- .../server/wm/ActivityRecordTests.java | 2 +- .../android/server/wm/TaskRecordTests.java | 25 +++++++++++++++++++ 3 files changed, 36 insertions(+), 3 deletions(-) diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index 50c269e23c534..c2f7b7c8269b0 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -2788,8 +2788,16 @@ class Task extends WindowContainer { // For calculating screen layout, we need to use the non-decor inset screen area for the // calculation for compatibility reasons, i.e. screen area without system bars that // could never go away in Honeycomb. - final int compatScreenWidthDp = (int) (mTmpNonDecorBounds.width() / density); - final int compatScreenHeightDp = (int) (mTmpNonDecorBounds.height() / density); + int compatScreenWidthDp = (int) (mTmpNonDecorBounds.width() / density); + int compatScreenHeightDp = (int) (mTmpNonDecorBounds.height() / density); + // Use overrides if provided. If both overrides are provided, mTmpNonDecorBounds is + // undefined so it can't be used. + if (inOutConfig.screenWidthDp != Configuration.SCREEN_WIDTH_DP_UNDEFINED) { + compatScreenWidthDp = inOutConfig.screenWidthDp; + } + if (inOutConfig.screenHeightDp != Configuration.SCREEN_HEIGHT_DP_UNDEFINED) { + compatScreenHeightDp = inOutConfig.screenHeightDp; + } // Reducing the screen layout starting from its parent config. inOutConfig.screenLayout = computeScreenLayoutOverride(parentConfig.screenLayout, compatScreenWidthDp, compatScreenHeightDp); diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java index f860e174fd153..708d802a75331 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java @@ -544,7 +544,7 @@ public class ActivityRecordTests extends WindowTestsBase { mActivity = new ActivityBuilder(mAtm) .setTask(mTask) .setLaunchTaskBehind(true) - .setConfigChanges(CONFIG_ORIENTATION) + .setConfigChanges(CONFIG_ORIENTATION | CONFIG_SCREEN_LAYOUT) .build(); mActivity.setState(Task.ActivityState.STOPPED, "Testing"); diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java index 0fe6510b0fcee..08537a4ea9c1a 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java @@ -431,6 +431,31 @@ public class TaskRecordTests extends WindowTestsBase { assertEquals(Configuration.ORIENTATION_LANDSCAPE, inOutConfig.orientation); } + @Test + public void testComputeConfigResourceLayoutOverrides() { + final Rect fullScreenBounds = new Rect(0, 0, 1000, 2500); + TestDisplayContent display = new TestDisplayContent.Builder( + mAtm, fullScreenBounds.width(), fullScreenBounds.height()).build(); + final Task task = new TaskBuilder(mSupervisor).setDisplay(display).build(); + final Configuration inOutConfig = new Configuration(); + final Configuration parentConfig = new Configuration(); + final Rect nonLongBounds = new Rect(0, 0, 1000, 1250); + parentConfig.windowConfiguration.setBounds(fullScreenBounds); + parentConfig.windowConfiguration.setAppBounds(fullScreenBounds); + parentConfig.densityDpi = 400; + parentConfig.screenHeightDp = (fullScreenBounds.bottom * 160) / parentConfig.densityDpi; + parentConfig.screenWidthDp = (fullScreenBounds.right * 160) / parentConfig.densityDpi; + parentConfig.windowConfiguration.setRotation(ROTATION_0); + + // Set BOTH screenW/H to an override value + inOutConfig.screenWidthDp = nonLongBounds.width() * 160 / parentConfig.densityDpi; + inOutConfig.screenHeightDp = nonLongBounds.height() * 160 / parentConfig.densityDpi; + task.computeConfigResourceOverrides(inOutConfig, parentConfig); + + // screenLayout should honor override when both screenW/H are set. + assertTrue((inOutConfig.screenLayout & Configuration.SCREENLAYOUT_LONG_NO) != 0); + } + @Test public void testComputeNestedConfigResourceOverrides() { final Task task = new TaskBuilder(mSupervisor).build();