summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/wm/TaskDisplayArea.java114
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java24
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java57
3 files changed, 139 insertions, 56 deletions
diff --git a/services/core/java/com/android/server/wm/TaskDisplayArea.java b/services/core/java/com/android/server/wm/TaskDisplayArea.java
index 25791c762e42..3dc672396c29 100644
--- a/services/core/java/com/android/server/wm/TaskDisplayArea.java
+++ b/services/core/java/com/android/server/wm/TaskDisplayArea.java
@@ -123,6 +123,10 @@ final class TaskDisplayArea extends DisplayArea<ActivityStack> {
private final RootWindowContainer.FindTaskResult
mTmpFindTaskResult = new RootWindowContainer.FindTaskResult();
+ // Indicates whether the Assistant should show on top of the Dream (respectively, above
+ // everything else on screen). Otherwise, it will be put under always-on-top stacks.
+ private final boolean mAssistantOnTopOfDream;
+
/**
* If this is the same as {@link #getFocusedStack} then the activity on the top of the focused
* stack has been resumed. If stacks are changing position this will hold the old stack until
@@ -148,6 +152,9 @@ final class TaskDisplayArea extends DisplayArea<ActivityStack> {
mDisplayContent = displayContent;
mRootWindowContainer = service.mRoot;
mAtmService = service.mAtmService;
+
+ mAssistantOnTopOfDream = mWmService.mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_assistantOnTopOfDream);
}
/**
@@ -327,55 +334,80 @@ final class TaskDisplayArea extends DisplayArea<ActivityStack> {
}
/**
- * When stack is added or repositioned, find a proper position for it.
- * This will make sure that pinned stack always stays on top.
- * @param requestedPosition Position requested by caller.
- * @param stack Stack to be added or positioned.
- * @param adding Flag indicates whether we're adding a new stack or positioning an existing.
- * @return The proper position for the stack.
+ * Assigns a priority number to stack types. This priority defines an order between the types
+ * of stacks that are added to the task display area.
+ *
+ * Higher priority number indicates that the stack should have a higher z-order.
+ *
+ * @return the priority of the stack
*/
- private int findPositionForStack(int requestedPosition, ActivityStack stack,
- boolean adding) {
- if (stack.isActivityTypeDream()) {
- return POSITION_TOP;
- }
-
- if (stack.inPinnedWindowingMode()) {
- return POSITION_TOP;
- }
-
- final int topChildPosition = mChildren.size() - 1;
- int belowAlwaysOnTopPosition = POSITION_BOTTOM;
- for (int i = topChildPosition; i >= 0; --i) {
- // Since a stack could be repositioned while being one of the child, return
- // current index if that's the same stack we are positioning and it is always on
- // top.
- final boolean sameStack = mChildren.get(i) == stack;
- if ((sameStack && stack.isAlwaysOnTop())
- || (!sameStack && !mChildren.get(i).isAlwaysOnTop())) {
- belowAlwaysOnTopPosition = i;
+ private int getPriority(ActivityStack stack) {
+ if (mAssistantOnTopOfDream && stack.isActivityTypeAssistant()) return 4;
+ if (stack.isActivityTypeDream()) return 3;
+ if (stack.inPinnedWindowingMode()) return 2;
+ if (stack.isAlwaysOnTop()) return 1;
+ return 0;
+ }
+
+ private int findMinPositionForStack(ActivityStack stack) {
+ int minPosition = POSITION_BOTTOM;
+ for (int i = 0; i < mChildren.size(); ++i) {
+ if (getPriority(getStackAt(i)) < getPriority(stack)) {
+ minPosition = i;
+ } else {
break;
}
}
- // The max possible position we can insert the stack at.
- int maxPosition = POSITION_TOP;
- // The min possible position we can insert the stack at.
- int minPosition = POSITION_BOTTOM;
-
if (stack.isAlwaysOnTop()) {
- if (hasPinnedTask()) {
- // Always-on-top stacks go below the pinned stack.
- maxPosition = mChildren.indexOf(mRootPinnedTask) - 1;
+ // Since a stack could be repositioned while still being one of the children, we check
+ // if this always-on-top stack already exists and if so, set the minPosition to its
+ // previous position.
+ final int currentIndex = getIndexOf(stack);
+ if (currentIndex > minPosition) {
+ minPosition = currentIndex;
}
- // Always-on-top stacks need to be above all other stacks.
- minPosition = belowAlwaysOnTopPosition
- != POSITION_BOTTOM ? belowAlwaysOnTopPosition : topChildPosition;
- } else {
- // Other stacks need to be below the always-on-top stacks.
- maxPosition = belowAlwaysOnTopPosition
- != POSITION_BOTTOM ? belowAlwaysOnTopPosition : 0;
}
+ return minPosition;
+ }
+
+ private int findMaxPositionForStack(ActivityStack stack) {
+ for (int i = mChildren.size() - 1; i >= 0; --i) {
+ final ActivityStack curr = getStackAt(i);
+ // Since a stack could be repositioned while still being one of the children, we check
+ // if 'curr' is the same stack and skip it if so
+ final boolean sameStack = curr == stack;
+ if (getPriority(curr) <= getPriority(stack) && !sameStack) {
+ return i;
+ }
+ }
+ return 0;
+ }
+
+ /**
+ * When stack is added or repositioned, find a proper position for it.
+ *
+ * The order is defined as:
+ * - Dream is on top of everything
+ * - PiP is directly below the Dream
+ * - always-on-top stacks are directly below PiP; new always-on-top stacks are added above
+ * existing ones
+ * - other non-always-on-top stacks come directly below always-on-top stacks; new
+ * non-always-on-top stacks are added directly below always-on-top stacks and above existing
+ * non-always-on-top stacks
+ * - if {@link #mAssistantOnTopOfDream} is enabled, then Assistant is on top of everything
+ * (including the Dream); otherwise, it is a normal non-always-on-top stack
+ *
+ * @param requestedPosition Position requested by caller.
+ * @param stack Stack to be added or positioned.
+ * @param adding Flag indicates whether we're adding a new stack or positioning an existing.
+ * @return The proper position for the stack.
+ */
+ private int findPositionForStack(int requestedPosition, ActivityStack stack, boolean adding) {
+ // The max possible position we can insert the stack at.
+ int maxPosition = findMaxPositionForStack(stack);
+ // The min possible position we can insert the stack at.
+ int minPosition = findMinPositionForStack(stack);
// Cap the requested position to something reasonable for the previous position check
// below.
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java
index 1debd8c9ffb1..e3bb1b6ca9f3 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java
@@ -16,6 +16,8 @@
package com.android.server.wm;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_DREAM;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
@@ -270,6 +272,28 @@ public class ActivityDisplayTests extends ActivityTestsBase {
anotherAlwaysOnTopStack.setWindowingMode(WINDOWING_MODE_FREEFORM);
assertTrue(anotherAlwaysOnTopStack.isAlwaysOnTop());
assertEquals(anotherAlwaysOnTopStack, taskDisplayArea.getStackAt(topPosition - 1));
+
+ final ActivityStack dreamStack = taskDisplayArea.createStack(
+ WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_DREAM, true /* onTop */);
+ assertEquals(taskDisplayArea, dreamStack.getDisplayArea());
+ assertTrue(dreamStack.isAlwaysOnTop());
+ topPosition = taskDisplayArea.getStackCount() - 1;
+ // Ensure dream shows above all activities, including PiP
+ assertEquals(dreamStack, taskDisplayArea.getTopStack());
+ assertEquals(pinnedStack, taskDisplayArea.getStackAt(topPosition - 1));
+
+ final ActivityStack assistStack = taskDisplayArea.createStack(
+ WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_ASSISTANT, true /* onTop */);
+ assertEquals(taskDisplayArea, assistStack.getDisplayArea());
+ assertFalse(assistStack.isAlwaysOnTop());
+ topPosition = taskDisplayArea.getStackCount() - 1;
+
+ // Ensure Assistant shows as a non-always-on-top activity when config_assistantOnTopOfDream
+ // is false and on top of everything when true.
+ final boolean isAssistantOnTop = mContext.getResources()
+ .getBoolean(com.android.internal.R.bool.config_assistantOnTopOfDream);
+ assertEquals(assistStack, taskDisplayArea.getStackAt(
+ isAssistantOnTop ? topPosition : topPosition - 4));
}
@Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
index 93ded1b6b2f3..6c209e496cf6 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
@@ -471,23 +471,39 @@ public class ActivityStackTests extends ActivityTestsBase {
assertEquals(STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT,
splitScreenSecondary2.getVisibility(null /* starting */));
- // Assistant stack shouldn't be visible behind translucent split-screen stack
+ // Assistant stack shouldn't be visible behind translucent split-screen stack,
+ // unless it is configured to show on top of everything.
doReturn(false).when(assistantStack).isTranslucent(any());
doReturn(true).when(splitScreenPrimary).isTranslucent(any());
doReturn(true).when(splitScreenSecondary2).isTranslucent(any());
splitScreenSecondary2.moveToFront("testShouldBeVisible_SplitScreen");
splitScreenPrimary.moveToFront("testShouldBeVisible_SplitScreen");
- assertFalse(assistantStack.shouldBeVisible(null /* starting */));
- assertTrue(splitScreenPrimary.shouldBeVisible(null /* starting */));
- assertTrue(splitScreenSecondary2.shouldBeVisible(null /* starting */));
- assertEquals(STACK_VISIBILITY_INVISIBLE,
- assistantStack.getVisibility(null /* starting */));
- assertEquals(STACK_VISIBILITY_VISIBLE,
- splitScreenPrimary.getVisibility(null /* starting */));
- assertEquals(STACK_VISIBILITY_INVISIBLE,
- splitScreenSecondary.getVisibility(null /* starting */));
- assertEquals(STACK_VISIBILITY_VISIBLE,
- splitScreenSecondary2.getVisibility(null /* starting */));
+
+ if (isAssistantOnTop()) {
+ assertTrue(assistantStack.shouldBeVisible(null /* starting */));
+ assertFalse(splitScreenPrimary.shouldBeVisible(null /* starting */));
+ assertFalse(splitScreenSecondary2.shouldBeVisible(null /* starting */));
+ assertEquals(STACK_VISIBILITY_VISIBLE,
+ assistantStack.getVisibility(null /* starting */));
+ assertEquals(STACK_VISIBILITY_INVISIBLE,
+ splitScreenPrimary.getVisibility(null /* starting */));
+ assertEquals(STACK_VISIBILITY_INVISIBLE,
+ splitScreenSecondary.getVisibility(null /* starting */));
+ assertEquals(STACK_VISIBILITY_INVISIBLE,
+ splitScreenSecondary2.getVisibility(null /* starting */));
+ } else {
+ assertFalse(assistantStack.shouldBeVisible(null /* starting */));
+ assertTrue(splitScreenPrimary.shouldBeVisible(null /* starting */));
+ assertTrue(splitScreenSecondary2.shouldBeVisible(null /* starting */));
+ assertEquals(STACK_VISIBILITY_INVISIBLE,
+ assistantStack.getVisibility(null /* starting */));
+ assertEquals(STACK_VISIBILITY_VISIBLE,
+ splitScreenPrimary.getVisibility(null /* starting */));
+ assertEquals(STACK_VISIBILITY_INVISIBLE,
+ splitScreenSecondary.getVisibility(null /* starting */));
+ assertEquals(STACK_VISIBILITY_VISIBLE,
+ splitScreenSecondary2.getVisibility(null /* starting */));
+ }
}
@Test
@@ -927,9 +943,15 @@ public class ActivityStackTests extends ActivityTestsBase {
splitScreenSecondary.moveToFront("testSplitScreenMoveToFront");
- assertTrue(splitScreenPrimary.shouldBeVisible(null /* starting */));
- assertTrue(splitScreenSecondary.shouldBeVisible(null /* starting */));
- assertFalse(assistantStack.shouldBeVisible(null /* starting */));
+ if (isAssistantOnTop()) {
+ assertFalse(splitScreenPrimary.shouldBeVisible(null /* starting */));
+ assertFalse(splitScreenSecondary.shouldBeVisible(null /* starting */));
+ assertTrue(assistantStack.shouldBeVisible(null /* starting */));
+ } else {
+ assertTrue(splitScreenPrimary.shouldBeVisible(null /* starting */));
+ assertTrue(splitScreenSecondary.shouldBeVisible(null /* starting */));
+ assertFalse(assistantStack.shouldBeVisible(null /* starting */));
+ }
}
private ActivityStack createStandardStackForVisibilityTest(int windowingMode,
@@ -1344,6 +1366,11 @@ public class ActivityStackTests extends ActivityTestsBase {
anyBoolean());
}
+ private boolean isAssistantOnTop() {
+ return mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_assistantOnTopOfDream);
+ }
+
private void verifyShouldSleepActivities(boolean focusedStack,
boolean keyguardGoingAway, boolean displaySleeping, boolean expected) {
final DisplayContent display = mock(DisplayContent.class);