diff options
7 files changed, 123 insertions, 6 deletions
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index d8720aba3f55..ee1e64f46421 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -685,6 +685,10 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp */ private boolean mInEnsureActivitiesVisible = false; + // Used to indicate that the movement of child tasks to top will not move the display to top as + // well and thus won't change the top resumed / focused record + boolean mDontMoveToTop; + private final Consumer<WindowState> mUpdateWindowsForAnimator = w -> { WindowStateAnimator winAnimator = w.mWinAnimator; final ActivityRecord activity = w.mActivityRecord; diff --git a/services/core/java/com/android/server/wm/DisplayWindowSettings.java b/services/core/java/com/android/server/wm/DisplayWindowSettings.java index b82fdd237f2b..6d5abe1e2f31 100644 --- a/services/core/java/com/android/server/wm/DisplayWindowSettings.java +++ b/services/core/java/com/android/server/wm/DisplayWindowSettings.java @@ -16,11 +16,11 @@ package com.android.server.wm; +import static android.view.WindowManager.DISPLAY_IME_POLICY_FALLBACK_DISPLAY; +import static android.view.WindowManager.DISPLAY_IME_POLICY_LOCAL; import static android.view.WindowManager.REMOVE_CONTENT_MODE_DESTROY; import static android.view.WindowManager.REMOVE_CONTENT_MODE_MOVE_TO_PRIMARY; import static android.view.WindowManager.REMOVE_CONTENT_MODE_UNDEFINED; -import static android.view.WindowManager.DISPLAY_IME_POLICY_LOCAL; -import static android.view.WindowManager.DISPLAY_IME_POLICY_FALLBACK_DISPLAY; import static com.android.server.wm.DisplayContent.FORCE_SCALING_MODE_AUTO; import static com.android.server.wm.DisplayContent.FORCE_SCALING_MODE_DISABLED; @@ -196,6 +196,14 @@ class DisplayWindowSettings { mSettingsProvider.updateOverrideSettings(displayInfo, overrideSettings); } + void setDontMoveToTop(DisplayContent dc, boolean dontMoveToTop) { + DisplayInfo displayInfo = dc.getDisplayInfo(); + SettingsProvider.SettingsEntry overrideSettings = + mSettingsProvider.getSettings(displayInfo); + overrideSettings.mDontMoveToTop = dontMoveToTop; + mSettingsProvider.updateOverrideSettings(displayInfo, overrideSettings); + } + boolean shouldShowSystemDecorsLocked(DisplayContent dc) { if (dc.getDisplayId() == Display.DEFAULT_DISPLAY) { // Default display should show system decors. @@ -274,6 +282,10 @@ class DisplayWindowSettings { final int forcedScalingMode = settings.mForcedScalingMode != null ? settings.mForcedScalingMode : FORCE_SCALING_MODE_AUTO; dc.mDisplayScalingDisabled = forcedScalingMode == FORCE_SCALING_MODE_DISABLED; + + boolean dontMoveToTop = settings.mDontMoveToTop != null + ? settings.mDontMoveToTop : false; + dc.mDontMoveToTop = dontMoveToTop; } /** @@ -358,6 +370,8 @@ class DisplayWindowSettings { Boolean mIgnoreOrientationRequest; @Nullable Boolean mIgnoreDisplayCutout; + @Nullable + Boolean mDontMoveToTop; SettingsEntry() {} @@ -432,6 +446,10 @@ class DisplayWindowSettings { mIgnoreDisplayCutout = other.mIgnoreDisplayCutout; changed = true; } + if (other.mDontMoveToTop != mDontMoveToTop) { + mDontMoveToTop = other.mDontMoveToTop; + changed = true; + } return changed; } @@ -515,6 +533,11 @@ class DisplayWindowSettings { mIgnoreDisplayCutout = delta.mIgnoreDisplayCutout; changed = true; } + if (delta.mDontMoveToTop != null + && delta.mDontMoveToTop != mDontMoveToTop) { + mDontMoveToTop = delta.mDontMoveToTop; + changed = true; + } return changed; } @@ -531,7 +554,8 @@ class DisplayWindowSettings { && mImePolicy == null && mFixedToUserRotation == null && mIgnoreOrientationRequest == null - && mIgnoreDisplayCutout == null; + && mIgnoreDisplayCutout == null + && mDontMoveToTop == null; } @Override @@ -553,7 +577,8 @@ class DisplayWindowSettings { && Objects.equals(mImePolicy, that.mImePolicy) && Objects.equals(mFixedToUserRotation, that.mFixedToUserRotation) && Objects.equals(mIgnoreOrientationRequest, that.mIgnoreOrientationRequest) - && Objects.equals(mIgnoreDisplayCutout, that.mIgnoreDisplayCutout); + && Objects.equals(mIgnoreDisplayCutout, that.mIgnoreDisplayCutout) + && Objects.equals(mDontMoveToTop, that.mDontMoveToTop); } @Override @@ -561,7 +586,8 @@ class DisplayWindowSettings { return Objects.hash(mWindowingMode, mUserRotationMode, mUserRotation, mForcedWidth, mForcedHeight, mForcedDensity, mForcedScalingMode, mRemoveContentMode, mShouldShowWithInsecureKeyguard, mShouldShowSystemDecors, mImePolicy, - mFixedToUserRotation, mIgnoreOrientationRequest, mIgnoreDisplayCutout); + mFixedToUserRotation, mIgnoreOrientationRequest, mIgnoreDisplayCutout, + mDontMoveToTop); } @Override @@ -581,6 +607,7 @@ class DisplayWindowSettings { + ", mFixedToUserRotation=" + mFixedToUserRotation + ", mIgnoreOrientationRequest=" + mIgnoreOrientationRequest + ", mIgnoreDisplayCutout=" + mIgnoreDisplayCutout + + ", mDontMoveToTop=" + mDontMoveToTop + '}'; } } diff --git a/services/core/java/com/android/server/wm/DisplayWindowSettingsProvider.java b/services/core/java/com/android/server/wm/DisplayWindowSettingsProvider.java index 5f3ab43eca7c..737f8107f83f 100644 --- a/services/core/java/com/android/server/wm/DisplayWindowSettingsProvider.java +++ b/services/core/java/com/android/server/wm/DisplayWindowSettingsProvider.java @@ -405,6 +405,9 @@ class DisplayWindowSettingsProvider implements SettingsProvider { "ignoreOrientationRequest", null /* defaultValue */); settingsEntry.mIgnoreDisplayCutout = getBooleanAttribute(parser, "ignoreDisplayCutout", null /* defaultValue */); + settingsEntry.mDontMoveToTop = getBooleanAttribute(parser, + "dontMoveToTop", null /* defaultValue */); + fileData.mSettings.put(name, settingsEntry); } XmlUtils.skipCurrentTag(parser); @@ -496,6 +499,10 @@ class DisplayWindowSettingsProvider implements SettingsProvider { out.attributeBoolean(null, "ignoreDisplayCutout", settingsEntry.mIgnoreDisplayCutout); } + if (settingsEntry.mDontMoveToTop != null) { + out.attributeBoolean(null, "dontMoveToTop", + settingsEntry.mDontMoveToTop); + } out.endTag(null, "display"); } diff --git a/services/core/java/com/android/server/wm/TaskDisplayArea.java b/services/core/java/com/android/server/wm/TaskDisplayArea.java index 63732d8d4bdc..40248c43fe5d 100644 --- a/services/core/java/com/android/server/wm/TaskDisplayArea.java +++ b/services/core/java/com/android/server/wm/TaskDisplayArea.java @@ -404,7 +404,11 @@ final class TaskDisplayArea extends DisplayArea<WindowContainer> { } // We don't allow untrusted display to top when root task moves to top, // until user tapping this display to change display position as top intentionally. - if (!mDisplayContent.isTrusted() && !getParent().isOnTop()) { + // + // Displays with {@code mDontMoveToTop} property set to {@code true} won't be + // allowed to top neither. + if ((!mDisplayContent.isTrusted() || mDisplayContent.mDontMoveToTop) + && !getParent().isOnTop()) { includingParents = false; } final int targetPosition = findPositionForRootTask(position, child, false /* adding */); diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java index 4bea9a2eea45..4c2d12436858 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java @@ -1608,6 +1608,16 @@ public class DisplayContentTests extends WindowTestsBase { } @Test + public void testGetOrCreateRootHomeTask_dontMoveToTop() { + DisplayContent display = createNewDisplay(); + display.mDontMoveToTop = true; + TaskDisplayArea taskDisplayArea = display.getDefaultTaskDisplayArea(); + + assertNull(taskDisplayArea.getRootHomeTask()); + assertNull(taskDisplayArea.getOrCreateRootHomeTask()); + } + + @Test public void testValidWindowingLayer() { final SurfaceControl windowingLayer = mDisplayContent.getWindowingLayer(); assertNotNull(windowingLayer); diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsProviderTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsProviderTests.java index 33e8fc0bd94b..3e05c86898e2 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsProviderTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsProviderTests.java @@ -217,6 +217,7 @@ public class DisplayWindowSettingsProviderTests extends WindowTestsBase { SettingsEntry overrideSettings = provider.getOverrideSettings(secondaryDisplayInfo); overrideSettings.mShouldShowSystemDecors = true; overrideSettings.mImePolicy = DISPLAY_IME_POLICY_LOCAL; + overrideSettings.mDontMoveToTop = true; provider.updateOverrideSettings(secondaryDisplayInfo, overrideSettings); assertTrue(mOverrideSettingsStorage.wasWriteSuccessful()); @@ -227,6 +228,8 @@ public class DisplayWindowSettingsProviderTests extends WindowTestsBase { getStoredDisplayAttributeValue(mOverrideSettingsStorage, "shouldShowSystemDecors")); assertEquals("Attribute value must be stored", "0", getStoredDisplayAttributeValue(mOverrideSettingsStorage, "imePolicy")); + assertEquals("Attribute value must be stored", "true", + getStoredDisplayAttributeValue(mOverrideSettingsStorage, "dontMoveToTop")); } @Test diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java index d83e9c21fae7..a3ade51970fc 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java @@ -156,6 +156,9 @@ public class TaskDisplayAreaTests extends WindowTestsBase { spyOn(mDisplayContent); doReturn(true).when(mDisplayContent).isTrusted(); + // Allow child stack to move to top. + mDisplayContent.mDontMoveToTop = false; + // The display contains pinned stack that was added in {@link #setUp}. final Task stack = createTaskStackOnDisplay(mDisplayContent); final Task task = createTaskInStack(stack, 0 /* userId */); @@ -173,6 +176,65 @@ public class TaskDisplayAreaTests extends WindowTestsBase { } @Test + public void testMovingChildTaskOnTop() { + // Make sure the display is trusted display which capable to move the stack to top. + spyOn(mDisplayContent); + doReturn(true).when(mDisplayContent).isTrusted(); + + // Allow child stack to move to top. + mDisplayContent.mDontMoveToTop = false; + + // The display contains pinned stack that was added in {@link #setUp}. + Task stack = createTaskStackOnDisplay(mDisplayContent); + Task task = createTaskInStack(stack, 0 /* userId */); + + // Add another display at top. + mWm.mRoot.positionChildAt(WindowContainer.POSITION_TOP, createNewDisplay(), + false /* includingParents */); + + // Ensure that original display ({@code mDisplayContent}) is not on top. + assertEquals("Testing DisplayContent should not be on the top", + mWm.mRoot.getChildCount() - 2, mWm.mRoot.mChildren.indexOf(mDisplayContent)); + + // Move the task of {@code mDisplayContent} to top. + stack.positionChildAt(WindowContainer.POSITION_TOP, task, true /* includingParents */); + + // Ensure that original display ({@code mDisplayContent}) is now on the top. + assertEquals("The testing DisplayContent should be moved to top with task", + mWm.mRoot.getChildCount() - 1, mWm.mRoot.mChildren.indexOf(mDisplayContent)); + } + + @Test + public void testDontMovingChildTaskOnTop() { + // Make sure the display is trusted display which capable to move the stack to top. + spyOn(mDisplayContent); + doReturn(true).when(mDisplayContent).isTrusted(); + + // Allow child stack to move to top. + mDisplayContent.mDontMoveToTop = true; + + // The display contains pinned stack that was added in {@link #setUp}. + Task stack = createTaskStackOnDisplay(mDisplayContent); + Task task = createTaskInStack(stack, 0 /* userId */); + + // Add another display at top. + mWm.mRoot.positionChildAt(WindowContainer.POSITION_TOP, createNewDisplay(), + false /* includingParents */); + + // Ensure that original display ({@code mDisplayContent}) is not on top. + assertEquals("Testing DisplayContent should not be on the top", + mWm.mRoot.getChildCount() - 2, mWm.mRoot.mChildren.indexOf(mDisplayContent)); + + // Try moving the task of {@code mDisplayContent} to top. + stack.positionChildAt(WindowContainer.POSITION_TOP, task, true /* includingParents */); + + // Ensure that original display ({@code mDisplayContent}) hasn't moved and is not + // on the top. + assertEquals("The testing DisplayContent should not be moved to top with task", + mWm.mRoot.getChildCount() - 2, mWm.mRoot.mChildren.indexOf(mDisplayContent)); + } + + @Test public void testReuseTaskAsRootTask() { final Task candidateTask = createTaskStackOnDisplay(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, mDisplayContent); |