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/Task.java b/services/core/java/com/android/server/wm/Task.java
index aa6e3c7..6005a99 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -23,6 +23,7 @@
 import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION;
 import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_MOVEMENT;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
 import static com.android.server.wm.WindowManagerService.H.RESIZE_TASK;
@@ -154,7 +155,7 @@
         mService.mTaskIdToTask.delete(mTaskId);
     }
 
-    // Change to use re-parenting in WC when TaskStack is switched to use WC.
+    // TODO: Change to use re-parenting in WC.
     void moveTaskToStack(TaskStack stack, boolean toTop) {
         if (stack == mStack) {
             return;
@@ -166,15 +167,20 @@
         stack.addTask(this, toTop);
     }
 
+    /** @see com.android.server.am.ActivityManagerService#positionTaskInStack(int, int, int). */
     void positionTaskInStack(TaskStack stack, int position, Rect bounds,
             Configuration overrideConfig) {
         if (mStack != null && stack != mStack) {
+            // Task is already attached to a different stack. First we need to remove it from there
+            // and add to top of the target stack. We will move it proper position afterwards.
             if (DEBUG_STACK) Slog.i(TAG, "positionTaskInStack: removing taskId=" + mTaskId
                     + " from stack=" + mStack);
             EventLog.writeEvent(EventLogTags.WM_TASK_REMOVED, mTaskId, "moveTask");
             mStack.removeChild(this);
+            stack.addTask(this, true /* toTop */);
         }
-        stack.positionTask(this, position, showForAllUsers());
+
+        stack.positionChildAt(position, this, true /* includingParents */);
         resizeLocked(bounds, overrideConfig, false /* force */);
 
         for (int activityNdx = mChildren.size() - 1; activityNdx >= 0; --activityNdx) {
@@ -183,6 +189,20 @@
     }
 
     @Override
+    void onParentSet() {
+        // Update task bounds if needed.
+        updateDisplayInfo(getDisplayContent());
+
+        if (StackId.windowsAreScaleable(mStack.mStackId)) {
+            // We force windows out of SCALING_MODE_FREEZE so that we can continue to animate them
+            // while a resize is pending.
+            forceWindowsScaleable(true /* force */);
+        } else {
+            forceWindowsScaleable(false /* force */);
+        }
+    }
+
+    @Override
     void removeChild(AppWindowToken token) {
         if (!mChildren.contains(token)) {
             Slog.e(TAG, "removeChild: token=" + this + " not found.");