diff --git a/core/java/android/view/WindowContainerTransaction.java b/core/java/android/view/WindowContainerTransaction.java index f406be9ebac78..e05c3743565c6 100644 --- a/core/java/android/view/WindowContainerTransaction.java +++ b/core/java/android/view/WindowContainerTransaction.java @@ -71,6 +71,33 @@ public class WindowContainerTransaction implements Parcelable { return this; } + /** + * Resize a container's app bounds. This is the bounds used to report appWidth/Height to an + * app's DisplayInfo. It is derived by subtracting the overlapping portion of the navbar from + * the full bounds. + */ + public WindowContainerTransaction setAppBounds(IWindowContainer container, Rect appBounds) { + Change chg = getOrCreateChange(container.asBinder()); + chg.mConfiguration.windowConfiguration.setAppBounds(appBounds); + chg.mConfigSetMask |= ActivityInfo.CONFIG_WINDOW_CONFIGURATION; + chg.mWindowSetMask |= WindowConfiguration.WINDOW_CONFIG_APP_BOUNDS; + return this; + } + + /** + * Resize a container's configuration size. The configuration size is what gets reported to the + * app via screenWidth/HeightDp and influences which resources get loaded. This size is + * derived by subtracting the overlapping portions of both the statusbar and the navbar from + * the full bounds. + */ + public WindowContainerTransaction setScreenSizeDp(IWindowContainer container, int w, int h) { + Change chg = getOrCreateChange(container.asBinder()); + chg.mConfiguration.screenWidthDp = w; + chg.mConfiguration.screenHeightDp = h; + chg.mConfigSetMask |= ActivityInfo.CONFIG_SCREEN_SIZE; + return this; + } + /** * Notify activies within the hiearchy of a container that they have entered picture-in-picture * mode with the given bounds. @@ -161,7 +188,8 @@ public class WindowContainerTransaction implements Parcelable { @Override public String toString() { - return "WindowContainerTransaction { changes = " + mChanges + " }"; + return "WindowContainerTransaction { changes = " + mChanges + " hops = " + mHierarchyOps + + " }"; } @Override @@ -269,6 +297,11 @@ public class WindowContainerTransaction implements Parcelable { (mConfigSetMask & ActivityInfo.CONFIG_WINDOW_CONFIGURATION) != 0 && ((mWindowSetMask & WindowConfiguration.WINDOW_CONFIG_BOUNDS) != 0); + final boolean changesAppBounds = + (mConfigSetMask & ActivityInfo.CONFIG_WINDOW_CONFIGURATION) != 0 + && ((mWindowSetMask & WindowConfiguration.WINDOW_CONFIG_APP_BOUNDS) + != 0); + final boolean changesSs = (mConfigSetMask & ActivityInfo.CONFIG_SCREEN_SIZE) != 0; final boolean changesSss = (mConfigSetMask & ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE) != 0; StringBuilder sb = new StringBuilder(); @@ -276,9 +309,16 @@ public class WindowContainerTransaction implements Parcelable { if (changesBounds) { sb.append("bounds:" + mConfiguration.windowConfiguration.getBounds() + ","); } + if (changesAppBounds) { + sb.append("appbounds:" + mConfiguration.windowConfiguration.getAppBounds() + ","); + } if (changesSss) { sb.append("ssw:" + mConfiguration.smallestScreenWidthDp + ","); } + if (changesSs) { + sb.append("sw/h:" + mConfiguration.screenWidthDp + "x" + + mConfiguration.screenHeightDp + ","); + } if ((mChangeMask & CHANGE_FOCUSABLE) != 0) { sb.append("focusable:" + mFocusable + ","); } diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java index 333fa3ca0a2d0..c6eecf260dac1 100644 --- a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java +++ b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java @@ -17,6 +17,8 @@ package com.android.systemui.stackdivider; import static android.content.res.Configuration.ORIENTATION_LANDSCAPE; +import static android.content.res.Configuration.SCREEN_HEIGHT_DP_UNDEFINED; +import static android.content.res.Configuration.SCREEN_WIDTH_DP_UNDEFINED; import static android.view.Display.DEFAULT_DISPLAY; import android.animation.Animator; @@ -214,8 +216,22 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks, if (mTargetAdjusted) { mSplitLayout.updateAdjustedBounds(mShownTop, mHiddenTop, mShownTop); wct.setBounds(mSplits.mSecondary.token, mSplitLayout.mAdjustedSecondary); + // "Freeze" the configuration size so that the app doesn't get a config + // or relaunch. This is required because normally nav-bar contributes + // to configuration bounds (via nondecorframe). + Rect adjustAppBounds = new Rect(mSplits.mSecondary.configuration + .windowConfiguration.getAppBounds()); + adjustAppBounds.offset(0, mSplitLayout.mAdjustedSecondary.top + - mSplitLayout.mSecondary.top); + wct.setAppBounds(mSplits.mSecondary.token, adjustAppBounds); + wct.setScreenSizeDp(mSplits.mSecondary.token, + mSplits.mSecondary.configuration.screenWidthDp, + mSplits.mSecondary.configuration.screenHeightDp); } else { wct.setBounds(mSplits.mSecondary.token, mSplitLayout.mSecondary); + wct.setAppBounds(mSplits.mSecondary.token, null); + wct.setScreenSizeDp(mSplits.mSecondary.token, + SCREEN_WIDTH_DP_UNDEFINED, SCREEN_HEIGHT_DP_UNDEFINED); } try { ActivityTaskManager.getTaskOrganizerController() diff --git a/services/core/java/com/android/server/wm/TaskOrganizerController.java b/services/core/java/com/android/server/wm/TaskOrganizerController.java index 8f5d04891742a..b38c18bf15f3a 100644 --- a/services/core/java/com/android/server/wm/TaskOrganizerController.java +++ b/services/core/java/com/android/server/wm/TaskOrganizerController.java @@ -463,8 +463,9 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub int configMask = change.getConfigSetMask(); int windowMask = change.getWindowSetMask(); configMask &= ActivityInfo.CONFIG_WINDOW_CONFIGURATION - | ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE; - windowMask &= WindowConfiguration.WINDOW_CONFIG_BOUNDS; + | ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE | ActivityInfo.CONFIG_SCREEN_SIZE; + windowMask &= (WindowConfiguration.WINDOW_CONFIG_BOUNDS + | WindowConfiguration.WINDOW_CONFIG_APP_BOUNDS); int effects = 0; if (configMask != 0) { Configuration c = new Configuration(container.getRequestedOverrideConfiguration()); diff --git a/services/core/java/com/android/server/wm/TaskTile.java b/services/core/java/com/android/server/wm/TaskTile.java index 74d5c338a68d8..205b423a38dd7 100644 --- a/services/core/java/com/android/server/wm/TaskTile.java +++ b/services/core/java/com/android/server/wm/TaskTile.java @@ -147,7 +147,7 @@ public class TaskTile extends ActivityStack { */ void updateResolvedConfig(Configuration inOutResolvedConfig) { Rect resolveBounds = inOutResolvedConfig.windowConfiguration.getBounds(); - if (resolveBounds == null || resolveBounds.isEmpty()) { + if (resolveBounds.isEmpty()) { resolveBounds.set(getRequestedOverrideBounds()); } int stackMode = inOutResolvedConfig.windowConfiguration.getWindowingMode(); @@ -162,6 +162,17 @@ public class TaskTile extends ActivityStack { inOutResolvedConfig.smallestScreenWidthDp = getRequestedOverrideConfiguration().smallestScreenWidthDp; } + if (inOutResolvedConfig.screenWidthDp == Configuration.SCREEN_WIDTH_DP_UNDEFINED) { + inOutResolvedConfig.screenWidthDp = getRequestedOverrideConfiguration().screenWidthDp; + } + if (inOutResolvedConfig.screenHeightDp == Configuration.SCREEN_HEIGHT_DP_UNDEFINED) { + inOutResolvedConfig.screenHeightDp = getRequestedOverrideConfiguration().screenHeightDp; + } + Rect resolveAppBounds = inOutResolvedConfig.windowConfiguration.getAppBounds(); + if (resolveAppBounds == null || resolveAppBounds.isEmpty()) { + inOutResolvedConfig.windowConfiguration.setAppBounds( + getRequestedOverrideConfiguration().windowConfiguration.getAppBounds()); + } } @Override @@ -184,7 +195,6 @@ public class TaskTile extends ActivityStack { boolean isResizable = topTask == null || topTask.isResizeable(); info.resizeMode = isResizable ? RESIZE_MODE_RESIZEABLE : RESIZE_MODE_UNRESIZEABLE; info.topActivityType = top == null ? ACTIVITY_TYPE_UNDEFINED : top.getActivityType(); - info.configuration.setTo(getRequestedOverrideConfiguration()); } @Override diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java index e501452a2df24..48a583cad7a37 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java @@ -39,6 +39,7 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.when; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; @@ -252,6 +253,30 @@ public class TaskOrganizerTests extends WindowTestsBase { assertFalse(task.isFocusable()); } + @Test + public void testOverrideConfigSize() { + removeGlobalMinSizeRestriction(); + final ActivityStack stack = new ActivityTestsBase.StackBuilder(mWm.mRoot) + .setWindowingMode(WINDOWING_MODE_FREEFORM).build(); + final Task task = stack.getTopMostTask(); + WindowContainerTransaction t = new WindowContainerTransaction(); + t.setBounds(task.mRemoteToken, new Rect(10, 10, 100, 100)); + mWm.mAtmService.mTaskOrganizerController.applyContainerTransaction(t, null); + final int origScreenWDp = task.getConfiguration().screenHeightDp; + final int origScreenHDp = task.getConfiguration().screenHeightDp; + t = new WindowContainerTransaction(); + // verify that setting config overrides on parent restricts children. + t.setScreenSizeDp(stack.mRemoteToken, origScreenWDp, origScreenHDp); + t.setBounds(task.mRemoteToken, new Rect(10, 10, 150, 200)); + mWm.mAtmService.mTaskOrganizerController.applyContainerTransaction(t, null); + assertEquals(origScreenHDp, task.getConfiguration().screenHeightDp); + t = new WindowContainerTransaction(); + t.setScreenSizeDp(stack.mRemoteToken, Configuration.SCREEN_WIDTH_DP_UNDEFINED, + Configuration.SCREEN_HEIGHT_DP_UNDEFINED); + mWm.mAtmService.mTaskOrganizerController.applyContainerTransaction(t, null); + assertNotEquals(origScreenHDp, task.getConfiguration().screenHeightDp); + } + @Test public void testCreateDeleteRootTasks() { RunningTaskInfo info1 = mWm.mAtmService.mTaskOrganizerController.createRootTask(