Add positionChildAt method to WindowContainer

Added method to change the position of a child among siblings.
It accepts int value, which can either specify a target position
or POSITION_TOP/POSITION_BOTTOM.
When child is moved to top or bottom, there is an option to also
perform same action on parents. This will effectively move the
entire branch of the hierarchy tree to top/bottom.

Test: bit FrameworksServicesTests:com.android.server.wm.WindowContainerTests
Test: #testPositionChildAt
Test: #testPositionChildAtIncludeParents
Test: #testPositionChildAtInvalid
Test: bit FrameworksServicesTests:com.android.server.wm.TaskStackContainersTests
Test: bit FrameworksServicesTests:com.android.server.wm.TaskStackTests
Change-Id: I6ade787487055f1c9a305afea64270c243196614
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 203137d..135a3dc 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -979,7 +979,10 @@
                 // It's already attached to the display...clear mDeferRemoval and move stack to
                 // appropriate z-order on display as needed.
                 stack.mDeferRemoval = false;
-                moveStack(stack, onTop);
+                // We're not moving the display to front when we're adding stacks, only when
+                // requested to change the position of stack explicitly.
+                mTaskStackContainers.positionChildAt(onTop ? POSITION_TOP : POSITION_BOTTOM, stack,
+                        false /* includingParents */);
                 attachedToDisplay = true;
             } else {
                 stack = new TaskStack(mService, stackId);
@@ -1031,10 +1034,6 @@
         return addStackToDisplay(stack.mStackId, true /* onTop */);
     }
 
-    void moveStack(TaskStack stack, boolean toTop) {
-        mTaskStackContainers.moveStack(stack, toTop);
-    }
-
     @Override
     protected void addChild(DisplayChildWindowContainer child,
             Comparator<DisplayChildWindowContainer> comparator) {
@@ -1057,6 +1056,13 @@
         throw new UnsupportedOperationException("See DisplayChildWindowContainer");
     }
 
+    @Override
+    void positionChildAt(int position, DisplayChildWindowContainer child, boolean includingParents) {
+        // Children of the display are statically ordered, so the real intention here is to perform
+        // the operation on the display and not the static direct children.
+        getParent().positionChildAt(position, this, includingParents);
+    }
+
     int taskIdFromPoint(int x, int y) {
         for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) {
             final TaskStack stack = mTaskStackContainers.get(stackNdx);
@@ -2499,20 +2505,6 @@
             stack.onRemovedFromDisplay();
         }
 
-        void moveStack(TaskStack stack, boolean toTop) {
-            if (StackId.isAlwaysOnTop(stack.mStackId) && !toTop) {
-                // This stack is always-on-top silly...
-                Slog.w(TAG_WM, "Ignoring move of always-on-top stack=" + stack + " to bottom");
-                return;
-            }
-
-            if (!mChildren.contains(stack)) {
-                Slog.wtf(TAG_WM, "moving stack that was not added: " + stack, new Throwable());
-            }
-            removeChild(stack);
-            addChild(stack, toTop);
-        }
-
         private void addChild(TaskStack stack, boolean toTop) {
             int addIndex = toTop ? mChildren.size() : 0;
 
@@ -2532,6 +2524,22 @@
         }
 
         @Override
+        void positionChildAt(int position, TaskStack child, boolean includingParents) {
+            if (StackId.isAlwaysOnTop(child.mStackId) && position != POSITION_TOP) {
+                // This stack is always-on-top, override the default behavior.
+                Slog.w(TAG_WM, "Ignoring move of always-on-top stack=" + this + " to bottom");
+
+                // Moving to its current position, as we must call super but we don't want to
+                // perform any meaningful action.
+                final int currentPosition = mChildren.indexOf(child);
+                super.positionChildAt(currentPosition, child, false /* includingParents */);
+                return;
+            }
+
+            super.positionChildAt(position, child, includingParents);
+        }
+
+        @Override
         boolean forAllWindows(ToBooleanFunction<WindowState> callback,
                 boolean traverseTopToBottom) {
             if (traverseTopToBottom) {