Added TaskWindowContainerController

For linking TaskRecord in AMS to Task window container in WMS.

Bug: 30060889
Test: bit FrameworksServicesTests:com.android.server.wm.AppWindowContainerControllerTests
Test: bit FrameworksServicesTests:com.android.server.wm.TaskWindowContainerControllerTests
Test: Existing test pass and manual testing.
Change-Id: I16248f3e96e5087ba24198a48a3bd10a12ae76a6
diff --git a/services/core/java/com/android/server/wm/TaskWindowContainerController.java b/services/core/java/com/android/server/wm/TaskWindowContainerController.java
new file mode 100644
index 0000000..9c303f8
--- /dev/null
+++ b/services/core/java/com/android/server/wm/TaskWindowContainerController.java
@@ -0,0 +1,245 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.wm;
+
+import android.content.res.Configuration;
+import android.graphics.Rect;
+import android.util.EventLog;
+import android.util.Slog;
+
+import static com.android.server.EventLogTags.WM_TASK_CREATED;
+import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_DOCKED_DIVIDER;
+import static com.android.server.wm.WindowContainer.POSITION_BOTTOM;
+import static com.android.server.wm.WindowContainer.POSITION_TOP;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK;
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
+
+/**
+ * Controller for the task container. This is created by activity manager to link task records to
+ * the task container they use in window manager.
+ *
+ * Test class: {@link TaskWindowContainerControllerTests}
+ */
+public class TaskWindowContainerController
+        extends WindowContainerController<Task, WindowContainerListener> {
+
+    private final int mTaskId;
+
+    public TaskWindowContainerController(int taskId, int stackId, int userId, Rect bounds,
+            Configuration overrideConfig, int resizeMode, boolean homeTask, boolean isOnTopLauncher,
+            boolean toTop, boolean showForAllUsers) {
+        super(null, WindowManagerService.getInstance());
+        mTaskId = taskId;
+
+        synchronized(mWindowMap) {
+            if (DEBUG_STACK) Slog.i(TAG_WM, "TaskWindowContainerController: taskId=" + taskId
+                    + " stackId=" + stackId + " bounds=" + bounds);
+
+            // TODO: Pass controller for the stack to get the container object when stack is
+            // switched to use controller.
+            final TaskStack stack = mService.mStackIdToStack.get(stackId);
+            if (stack == null) {
+                throw new IllegalArgumentException("TaskWindowContainerController: invalid stackId="
+                        + stackId);
+            }
+            EventLog.writeEvent(WM_TASK_CREATED, taskId, stackId);
+            final Task task = new Task(taskId, stack, userId, mService, bounds, overrideConfig,
+                    isOnTopLauncher, resizeMode, homeTask, this);
+            final int position = toTop ? POSITION_TOP : POSITION_BOTTOM;
+            stack.addTask(task, position, showForAllUsers, true /* moveParents */);
+        }
+    }
+
+    @Override
+    public void removeContainer() {
+        synchronized(mWindowMap) {
+            if (mContainer == null) {
+                if (DEBUG_STACK) Slog.i(TAG_WM, "removeTask: could not find taskId=" + mTaskId);
+                return;
+            }
+            mContainer.removeIfPossible();
+            super.removeContainer();
+        }
+    }
+
+    public void positionChildAt(AppWindowContainerController childController, int index) {
+        synchronized(mService.mWindowMap) {
+            final AppWindowToken aToken = childController.mContainer;
+            if (aToken == null) {
+                Slog.w(TAG_WM,
+                        "Attempted to position of non-existing app : " + childController);
+                return;
+            }
+
+            final Task task = mContainer;
+            if (task == null) {
+                throw new IllegalArgumentException("positionChildAt: invalid task=" + this);
+            }
+            task.addChild(aToken, index);
+        }
+    }
+
+    public void reparent(int stackId, int position) {
+        synchronized (mWindowMap) {
+            if (DEBUG_STACK) Slog.i(TAG_WM, "reparent: moving taskId=" + mTaskId
+                    + " to stackId=" + stackId + " at " + position);
+            if (mContainer == null) {
+                if (DEBUG_STACK) Slog.i(TAG_WM,
+                        "reparent: could not find taskId=" + mTaskId);
+                return;
+            }
+            final TaskStack stack = mService.mStackIdToStack.get(stackId);
+            if (stack == null) {
+                if (DEBUG_STACK) Slog.i(TAG_WM,
+                        "reparent: could not find stackId=" + stackId);
+                return;
+            }
+            mContainer.reparent(stack, position);
+            final DisplayContent displayContent = stack.getDisplayContent();
+            displayContent.setLayoutNeeded();
+            mService.mWindowPlacerLocked.performSurfacePlacement();
+        }
+    }
+
+    public void setResizeable(int resizeMode) {
+        synchronized (mWindowMap) {
+            if (mContainer != null) {
+                mContainer.setResizeable(resizeMode);
+            }
+        }
+    }
+
+    public void resize(Rect bounds, Configuration overrideConfig, boolean relayout,
+            boolean forced) {
+        synchronized (mWindowMap) {
+            if (mContainer == null) {
+                throw new IllegalArgumentException("resizeTask: taskId " + mTaskId + " not found.");
+            }
+
+            if (mContainer.resizeLocked(bounds, overrideConfig, forced) && relayout) {
+                mContainer.getDisplayContent().setLayoutNeeded();
+                mService.mWindowPlacerLocked.performSurfacePlacement();
+            }
+        }
+    }
+
+    // TODO: Move to positionChildAt() in stack controller once we have a stack controller.
+    public void positionAt(int stackId, int index, Rect bounds, Configuration overrideConfig) {
+        synchronized (mWindowMap) {
+            if (DEBUG_STACK) Slog.i(TAG_WM, "positionChildAt: positioning taskId=" + mTaskId
+                    + " in stackId=" + stackId + " at " + index);
+            if (mContainer == null) {
+                if (DEBUG_STACK) Slog.i(TAG_WM,
+                        "positionTaskInStack: could not find taskId=" + mTaskId);
+                return;
+            }
+            final TaskStack stack = mService.mStackIdToStack.get(stackId);
+            if (stack == null) {
+                if (DEBUG_STACK) Slog.i(TAG_WM,
+                        "positionTaskInStack: could not find stackId=" + stackId);
+                return;
+            }
+            mContainer.positionTaskInStack(stack, index, bounds, overrideConfig);
+            final DisplayContent displayContent = stack.getDisplayContent();
+            displayContent.setLayoutNeeded();
+            mService.mWindowPlacerLocked.performSurfacePlacement();
+        }
+    }
+
+    // TODO: Replace with moveChildToTop in stack controller?
+    public void moveToTop(boolean includingParents) {
+        synchronized(mWindowMap) {
+            if (mContainer == null) {
+                Slog.e(TAG_WM, "moveToTop: taskId=" + mTaskId + " not found");
+                return;
+            }
+            final TaskStack stack = mContainer.mStack;
+            stack.positionChildAt(POSITION_TOP, mContainer, includingParents);
+
+            if (mService.mAppTransition.isTransitionSet()) {
+                mContainer.setSendingToBottom(false);
+            }
+            stack.getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
+        }
+    }
+
+    // TODO: Replace with moveChildToBottom in stack controller?
+    public void moveToBottom() {
+        synchronized(mWindowMap) {
+            if (mContainer == null) {
+                Slog.e(TAG_WM, "moveTaskToBottom: taskId=" + mTaskId + " not found");
+                return;
+            }
+            final TaskStack stack = mContainer.mStack;
+            stack.positionChildAt(POSITION_BOTTOM, mContainer, false /* includingParents */);
+            if (mService.mAppTransition.isTransitionSet()) {
+                mContainer.setSendingToBottom(true);
+            }
+            stack.getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
+        }
+    }
+
+    public void getBounds(Rect bounds) {
+        synchronized (mWindowMap) {
+            if (mContainer != null) {
+                mContainer.getBounds(bounds);
+                return;
+            }
+            bounds.setEmpty();
+        }
+    }
+
+    /**
+     * Puts this task into docked drag resizing mode. See {@link DragResizeMode}.
+     *
+     * @param resizing Whether to put the task into drag resize mode.
+     */
+    public void setTaskDockedResizing(boolean resizing) {
+        synchronized (mWindowMap) {
+            if (mContainer == null) {
+                Slog.w(TAG_WM, "setTaskDockedResizing: taskId " + mTaskId + " not found.");
+                return;
+            }
+            mContainer.setDragResizing(resizing, DRAG_RESIZE_MODE_DOCKED_DIVIDER);
+        }
+    }
+
+    public void cancelWindowTransition() {
+        synchronized (mWindowMap) {
+            if (mContainer == null) {
+                Slog.w(TAG_WM, "cancelWindowTransition: taskId " + mTaskId + " not found.");
+                return;
+            }
+            mContainer.cancelTaskWindowTransition();
+        }
+    }
+
+    public void cancelThumbnailTransition() {
+        synchronized (mWindowMap) {
+            if (mContainer == null) {
+                Slog.w(TAG_WM, "cancelThumbnailTransition: taskId " + mTaskId + " not found.");
+                return;
+            }
+            mContainer.cancelTaskThumbnailTransition();
+        }
+    }
+
+    @Override
+    public String toString() {
+        return "{TaskWindowContainerController taskId=" + mTaskId + "}";
+    }
+}