Always place stacks below pinned stack
When positioning or adding stacks we must make sure that no stack is above pinned stack. Bug: 34049027 Test: runtest frameworks-services -c com.android.server.wm.TaskStackContainersTests Change-Id: Ic92a4e07e9cde42deed53912ac1419fde4ab2f08
This commit is contained in:
@@ -2498,19 +2498,8 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
|
||||
}
|
||||
|
||||
private void addChild(TaskStack stack, boolean toTop) {
|
||||
int addIndex = toTop ? mChildren.size() : 0;
|
||||
|
||||
if (toTop
|
||||
&& mService.isStackVisibleLocked(PINNED_STACK_ID)
|
||||
&& stack.mStackId != PINNED_STACK_ID) {
|
||||
// The pinned stack is always the top most stack (always-on-top) when it is visible.
|
||||
// So, stack is moved just below the pinned stack.
|
||||
addIndex--;
|
||||
TaskStack topStack = mChildren.get(addIndex);
|
||||
if (topStack.mStackId != PINNED_STACK_ID) {
|
||||
throw new IllegalStateException("Pinned stack isn't top stack??? " + mChildren);
|
||||
}
|
||||
}
|
||||
final int addIndex = findPositionForStack(toTop ? mChildren.size() : 0, stack,
|
||||
true /* adding */);
|
||||
addChild(stack, addIndex);
|
||||
setLayoutNeeded();
|
||||
}
|
||||
@@ -2528,7 +2517,45 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
|
||||
return;
|
||||
}
|
||||
|
||||
super.positionChildAt(position, child, includingParents);
|
||||
final int targetPosition = findPositionForStack(position, child, false /* adding */);
|
||||
super.positionChildAt(targetPosition, child, includingParents);
|
||||
|
||||
setLayoutNeeded();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
private int findPositionForStack(int requestedPosition, TaskStack stack, boolean adding) {
|
||||
final int topChildPosition = mChildren.size() - 1;
|
||||
boolean toTop = requestedPosition == POSITION_TOP;
|
||||
toTop |= adding ? requestedPosition >= topChildPosition + 1
|
||||
: requestedPosition >= topChildPosition;
|
||||
int targetPosition = requestedPosition;
|
||||
|
||||
if (toTop
|
||||
&& mService.isStackVisibleLocked(PINNED_STACK_ID)
|
||||
&& stack.mStackId != PINNED_STACK_ID) {
|
||||
// The pinned stack is always the top most stack (always-on-top) when it is visible.
|
||||
TaskStack topStack = mChildren.get(topChildPosition);
|
||||
if (topStack.mStackId != PINNED_STACK_ID) {
|
||||
throw new IllegalStateException("Pinned stack isn't top stack??? " + mChildren);
|
||||
}
|
||||
|
||||
// So, stack is moved just below the pinned stack.
|
||||
// When we're adding a new stack the target is the current pinned stack position.
|
||||
// When we're positioning an existing stack the target is the position below pinned
|
||||
// stack, because WindowContainer#positionAt() first removes element and then adds it
|
||||
// to specified place.
|
||||
targetPosition = adding ? topChildPosition : topChildPosition - 1;
|
||||
}
|
||||
|
||||
return targetPosition;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -434,7 +434,7 @@ class WindowContainer<E extends WindowContainer> implements Comparable<WindowCon
|
||||
// TODO: Will this be more correct if it checks the visibility of its parents?
|
||||
// It depends...For example, Tasks and Stacks are only visible if there children are visible
|
||||
// but, WindowState are not visible if there parent are not visible. Maybe have the
|
||||
// container specify which direction to treverse for for visibility?
|
||||
// container specify which direction to traverse for visibility?
|
||||
for (int i = mChildren.size() - 1; i >= 0; --i) {
|
||||
final WindowContainer wc = mChildren.get(i);
|
||||
if (wc.isVisible()) {
|
||||
|
||||
@@ -47,14 +47,15 @@ public class TaskStackContainersTests extends WindowTestsBase {
|
||||
// Test that always-on-top stack can't be moved to position other than top.
|
||||
final TaskStack stack1 = createTaskStackOnDisplay(sDisplayContent);
|
||||
final TaskStack stack2 = createTaskStackOnDisplay(sDisplayContent);
|
||||
sDisplayContent.addStackToDisplay(PINNED_STACK_ID, true);
|
||||
final TaskStack pinnedStack = sWm.mStackIdToStack.get(PINNED_STACK_ID);
|
||||
final TaskStack pinnedStack = addPinnedStack();
|
||||
|
||||
final WindowContainer taskStackContainer = stack1.getParent();
|
||||
|
||||
final int stack1Pos = taskStackContainer.mChildren.indexOf(stack1);
|
||||
final int stack2Pos = taskStackContainer.mChildren.indexOf(stack2);
|
||||
final int pinnedStackPos = taskStackContainer.mChildren.indexOf(pinnedStack);
|
||||
assertGreaterThan(pinnedStackPos, stack2Pos);
|
||||
assertGreaterThan(stack2Pos, stack1Pos);
|
||||
|
||||
taskStackContainer.positionChildAt(WindowContainer.POSITION_BOTTOM, pinnedStack, false);
|
||||
assertEquals(taskStackContainer.mChildren.get(stack1Pos), stack1);
|
||||
@@ -66,4 +67,43 @@ public class TaskStackContainersTests extends WindowTestsBase {
|
||||
assertEquals(taskStackContainer.mChildren.get(stack2Pos), stack2);
|
||||
assertEquals(taskStackContainer.mChildren.get(pinnedStackPos), pinnedStack);
|
||||
}
|
||||
@Test
|
||||
public void testStackPositionBelowPinnedStack() throws Exception {
|
||||
// Test that no stack can be above pinned stack.
|
||||
final TaskStack pinnedStack = addPinnedStack();
|
||||
final TaskStack stack1 = createTaskStackOnDisplay(sDisplayContent);
|
||||
|
||||
final WindowContainer taskStackContainer = stack1.getParent();
|
||||
|
||||
final int stackPos = taskStackContainer.mChildren.indexOf(stack1);
|
||||
final int pinnedStackPos = taskStackContainer.mChildren.indexOf(pinnedStack);
|
||||
assertGreaterThan(pinnedStackPos, stackPos);
|
||||
|
||||
taskStackContainer.positionChildAt(WindowContainer.POSITION_TOP, stack1, false);
|
||||
assertEquals(taskStackContainer.mChildren.get(stackPos), stack1);
|
||||
assertEquals(taskStackContainer.mChildren.get(pinnedStackPos), pinnedStack);
|
||||
|
||||
taskStackContainer.positionChildAt(taskStackContainer.mChildren.size() - 1, stack1, false);
|
||||
assertEquals(taskStackContainer.mChildren.get(stackPos), stack1);
|
||||
assertEquals(taskStackContainer.mChildren.get(pinnedStackPos), pinnedStack);
|
||||
}
|
||||
|
||||
private TaskStack addPinnedStack() {
|
||||
TaskStack pinnedStack = sWm.mStackIdToStack.get(PINNED_STACK_ID);
|
||||
if (pinnedStack == null) {
|
||||
sDisplayContent.addStackToDisplay(PINNED_STACK_ID, true);
|
||||
pinnedStack = sWm.mStackIdToStack.get(PINNED_STACK_ID);
|
||||
}
|
||||
|
||||
if (!pinnedStack.isVisible()) {
|
||||
// Stack should contain visible app window to be considered visible.
|
||||
final Task pinnedTask = createTaskInStack(pinnedStack, 0 /* userId */);
|
||||
assertFalse(pinnedStack.isVisible());
|
||||
final TestAppWindowToken pinnedApp = new TestAppWindowToken(sDisplayContent);
|
||||
pinnedTask.addChild(pinnedApp, 0 /* addPos */);
|
||||
assertTrue(pinnedStack.isVisible());
|
||||
}
|
||||
|
||||
return pinnedStack;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user