Remove TaskWindowContainerController & TaskWindowContainerListener (44/n)

Rename the TaskWindowContainerControllerTests to TaskTests and keep the
tests still make sense after removing the container.

TaskRecord and Task hold each other as a member. TaskRecord will create
Task while constructing.

Test: atest WmTests
Test: go/wm-smoke
Bug: 80414790
Change-Id: Iac9dc9cafdbb22ddbe325f8ff178874f3790f251
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 4e9c5ab..5f380e5 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -1035,8 +1035,6 @@
 
         inHistory = true;
 
-        final TaskWindowContainerController taskController = task.getWindowContainerController();
-
         // TODO(b/36505427): Maybe this call should be moved inside updateOverrideConfiguration()
         task.updateOverrideConfigurationFromLaunchBounds();
         // Make sure override configuration is up-to-date before using to create window controller.
@@ -1048,10 +1046,9 @@
             // TODO: Should this throw an exception instead?
             Slog.w(TAG, "Attempted to add existing app token: " + appToken);
         } else {
-            final Task container = taskController.mContainer;
+            final Task container = task.getTask();
             if (container == null) {
-                throw new IllegalArgumentException("AppWindowContainerController: invalid "
-                        + " controller=" + taskController);
+                throw new IllegalArgumentException("createAppWindowToken: invalid task =" + task);
             }
             mAppWindowToken = createAppWindow(mAtmService.mWindowManager, appToken,
                     task.voiceSession != null, container.getDisplayContent(),
@@ -1062,7 +1059,7 @@
                     mLaunchTaskBehind, isAlwaysFocusable());
             if (DEBUG_TOKEN_MOVEMENT || DEBUG_ADD_REMOVE) {
                 Slog.v(TAG, "addAppToken: "
-                        + mAppWindowToken + " controller=" + taskController + " at "
+                        + mAppWindowToken + " task=" + container + " at "
                         + Integer.MAX_VALUE);
             }
             container.addChild(mAppWindowToken, Integer.MAX_VALUE /* add on top */);
@@ -1148,7 +1145,7 @@
                     + " r=" + this + " (" + prevTask.getStackId() + ")");
         }
 
-        mAppWindowToken.reparent(newTask.getWindowContainerController(), position);
+        mAppWindowToken.reparent(newTask.getTask(), position);
 
         // Reparenting prevents informing the parent stack of activity removal in the case that
         // the new stack has the same parent. we must manually signal here if this is not the case.
@@ -2774,7 +2771,7 @@
             final boolean hasResizeChange = hasResizeChange(changes & ~info.getRealConfigChanged());
             if (hasResizeChange) {
                 final boolean isDragResizing =
-                        getTaskRecord().getWindowContainerController().isDragResizing();
+                        getTaskRecord().getTask().isDragResizing();
                 mRelaunchReason = isDragResizing ? RELAUNCH_REASON_FREE_RESIZE
                         : RELAUNCH_REASON_WINDOWING_MODE_RESIZE;
             } else {
diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java
index 7683172..bbb106b 100644
--- a/services/core/java/com/android/server/wm/ActivityStack.java
+++ b/services/core/java/com/android/server/wm/ActivityStack.java
@@ -911,7 +911,7 @@
     }
 
     void positionChildWindowContainerAtTop(TaskRecord child) {
-        mWindowContainerController.positionChildAtTop(child.getWindowContainerController(),
+        mWindowContainerController.positionChildAtTop(child.getTask(),
                 true /* includingParents */);
     }
 
@@ -921,7 +921,7 @@
         // task to bottom, the next focusable stack on the same display should be focused.
         final ActivityStack nextFocusableStack = getDisplay().getNextFocusableStack(
                 child.getStack(), true /* ignoreCurrent */);
-        mWindowContainerController.positionChildAtBottom(child.getWindowContainerController(),
+        mWindowContainerController.positionChildAtBottom(child.getTask(),
                 nextFocusableStack == null /* includingParents */);
     }
 
@@ -2984,7 +2984,7 @@
         position = getAdjustedPositionForTask(task, position, null /* starting */);
         mTaskHistory.remove(task);
         mTaskHistory.add(position, task);
-        mWindowContainerController.positionChildAt(task.getWindowContainerController(), position);
+        mWindowContainerController.positionChildAt(task.getTask(), position);
         updateTaskMovement(task, true);
     }
 
@@ -5349,7 +5349,7 @@
                 && !matchParentBounds() && task.isResizeable() && !isLockscreenShown) {
             task.updateOverrideConfiguration(getRequestedOverrideBounds());
         }
-        task.createWindowContainer(toTop, (info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0);
+        task.createTask(toTop, (info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0);
         return task;
     }
 
diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
index e761ad8..6a5954f 100644
--- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
@@ -1868,7 +1868,7 @@
 
         stack.addTask(task, onTop, "restoreRecentTask");
         // TODO: move call for creation here and other place into Stack.addTask()
-        task.createWindowContainer(onTop, true /* showForAllUsers */);
+        task.createTask(onTop, true /* showForAllUsers */);
         if (DEBUG_RECENTS) Slog.v(TAG_RECENTS,
                 "Added restored task=" + task + " to stack=" + stack);
         final ArrayList<ActivityRecord> activities = task.mActivities;
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index c458c94..e0d3fbe 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -1175,21 +1175,14 @@
         }
     }
 
-    void reparent(TaskWindowContainerController taskController, int position) {
+    void reparent(Task task, int position) {
         if (DEBUG_ADD_REMOVE) {
             Slog.i(TAG_WM, "reparent: moving app token=" + this
-                    + " to task=" + taskController + " at " + position);
+                    + " to task=" + task.mTaskId + " at " + position);
         }
-        final Task task = taskController.mContainer;
         if (task == null) {
-            throw new IllegalArgumentException("reparent: could not find task="
-                    + taskController);
+            throw new IllegalArgumentException("reparent: could not find task");
         }
-        reparent(task, position);
-        getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
-    }
-
-    void reparent(Task task, int position) {
         final Task currentTask = getTask();
         if (task == currentTask) {
             throw new IllegalArgumentException(
@@ -1220,6 +1213,7 @@
             onDisplayChanged(displayContent);
             prevDisplayContent.setLayoutNeeded();
         }
+        getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
     }
 
     @Override
diff --git a/services/core/java/com/android/server/wm/StackWindowController.java b/services/core/java/com/android/server/wm/StackWindowController.java
index 8f18aa5..0452977 100644
--- a/services/core/java/com/android/server/wm/StackWindowController.java
+++ b/services/core/java/com/android/server/wm/StackWindowController.java
@@ -67,107 +67,87 @@
         mStackId = stackId;
         mHandler = new H(new WeakReference<>(this), service.mH.getLooper());
 
-        synchronized (mGlobalLock) {
-            final DisplayContent dc = mRoot.getDisplayContent(displayId);
-            if (dc == null) {
-                throw new IllegalArgumentException("Trying to add stackId=" + stackId
-                        + " to unknown displayId=" + displayId);
-            }
-
-            dc.createStack(stackId, onTop, this);
-            getRawBounds(outBounds);
+        final DisplayContent dc = mRoot.getDisplayContent(displayId);
+        if (dc == null) {
+            throw new IllegalArgumentException("Trying to add stackId=" + stackId
+                    + " to unknown displayId=" + displayId);
         }
+
+        dc.createStack(stackId, onTop, this);
+        getRawBounds(outBounds);
     }
 
     @Override
     public void removeContainer() {
-        synchronized (mGlobalLock) {
-            if (mContainer != null) {
-                mContainer.removeIfPossible();
-                super.removeContainer();
-            }
+        if (mContainer != null) {
+            mContainer.removeIfPossible();
+            super.removeContainer();
         }
     }
 
-    public void reparent(int displayId, Rect outStackBounds, boolean onTop) {
-        synchronized (mGlobalLock) {
-            if (mContainer == null) {
-                throw new IllegalArgumentException("Trying to move unknown stackId=" + mStackId
-                        + " to displayId=" + displayId);
-            }
-
-            final DisplayContent targetDc = mRoot.getDisplayContent(displayId);
-            if (targetDc == null) {
-                throw new IllegalArgumentException("Trying to move stackId=" + mStackId
-                        + " to unknown displayId=" + displayId);
-            }
-
-            targetDc.moveStackToDisplay(mContainer, onTop);
-            getRawBounds(outStackBounds);
+    void reparent(int displayId, Rect outStackBounds, boolean onTop) {
+        if (mContainer == null) {
+            throw new IllegalArgumentException("Trying to move unknown stackId=" + mStackId
+                    + " to displayId=" + displayId);
         }
+
+        final DisplayContent targetDc = mRoot.getDisplayContent(displayId);
+        if (targetDc == null) {
+            throw new IllegalArgumentException("Trying to move stackId=" + mStackId
+                    + " to unknown displayId=" + displayId);
+        }
+
+        targetDc.moveStackToDisplay(mContainer, onTop);
+        getRawBounds(outStackBounds);
     }
 
-    public void positionChildAt(TaskWindowContainerController child, int position) {
-        synchronized (mGlobalLock) {
-            if (DEBUG_STACK) Slog.i(TAG_WM, "positionChildAt: positioning task=" + child
-                    + " at " + position);
-            if (child.mContainer == null) {
-                if (DEBUG_STACK) Slog.i(TAG_WM,
-                        "positionChildAt: could not find task=" + this);
-                return;
-            }
-            if (mContainer == null) {
-                if (DEBUG_STACK) Slog.i(TAG_WM,
-                        "positionChildAt: could not find stack for task=" + mContainer);
-                return;
-            }
-            child.mContainer.positionAt(position);
-            mContainer.getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
+    void positionChildAt(Task child, int position) {
+        if (DEBUG_STACK) {
+            Slog.i(TAG_WM, "positionChildAt: positioning task=" + child + " at " + position);
         }
+        if (child == null) {
+            if (DEBUG_STACK) {
+                Slog.i(TAG_WM, "positionChildAt: could not find task=" + this);
+            }
+            return;
+        }
+        if (mContainer == null) {
+            if (DEBUG_STACK) {
+                Slog.i(TAG_WM, "positionChildAt: could not find stack for task=" + mContainer);
+            }
+            return;
+        }
+        child.positionAt(position);
+        mContainer.getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
     }
 
-    public void positionChildAtTop(TaskWindowContainerController child, boolean includingParents) {
+    void positionChildAtTop(Task child, boolean includingParents) {
         if (child == null) {
             // TODO: Fix the call-points that cause this to happen.
             return;
         }
 
-        synchronized (mGlobalLock) {
-            final Task childTask = child.mContainer;
-            if (childTask == null) {
-                Slog.e(TAG_WM, "positionChildAtTop: task=" + child + " not found");
-                return;
-            }
-            mContainer.positionChildAt(POSITION_TOP, childTask, includingParents);
+        mContainer.positionChildAt(POSITION_TOP, child, includingParents);
 
-            final DisplayContent displayContent = mContainer.getDisplayContent();
-            if (displayContent.mAppTransition.isTransitionSet()) {
-                childTask.setSendingToBottom(false);
-            }
-            displayContent.layoutAndAssignWindowLayersIfNeeded();
+        final DisplayContent displayContent = mContainer.getDisplayContent();
+        if (displayContent.mAppTransition.isTransitionSet()) {
+            child.setSendingToBottom(false);
         }
+        displayContent.layoutAndAssignWindowLayersIfNeeded();
     }
 
-    public void positionChildAtBottom(TaskWindowContainerController child,
-            boolean includingParents) {
+    void positionChildAtBottom(Task child, boolean includingParents) {
         if (child == null) {
             // TODO: Fix the call-points that cause this to happen.
             return;
         }
 
-        synchronized (mGlobalLock) {
-            final Task childTask = child.mContainer;
-            if (childTask == null) {
-                Slog.e(TAG_WM, "positionChildAtBottom: task=" + child + " not found");
-                return;
-            }
-            mContainer.positionChildAt(POSITION_BOTTOM, childTask, includingParents);
+        mContainer.positionChildAt(POSITION_BOTTOM, child, includingParents);
 
-            if (mContainer.getDisplayContent().mAppTransition.isTransitionSet()) {
-                childTask.setSendingToBottom(true);
-            }
-            mContainer.getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
+        if (mContainer.getDisplayContent().mAppTransition.isTransitionSet()) {
+            child.setSendingToBottom(true);
         }
+        mContainer.getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
     }
 
     /**
@@ -179,24 +159,20 @@
      */
     public void resize(Rect bounds, SparseArray<Rect> taskBounds,
             SparseArray<Rect> taskTempInsetBounds) {
-        synchronized (mGlobalLock) {
-            if (mContainer == null) {
-                throw new IllegalArgumentException("resizeStack: stack " + this + " not found.");
-            }
-            // We might trigger a configuration change. Save the current task bounds for freezing.
-            mContainer.prepareFreezingTaskBounds();
-            if (mContainer.setBounds(bounds, taskBounds, taskTempInsetBounds)
-                    && mContainer.isVisible()) {
-                mContainer.getDisplayContent().setLayoutNeeded();
-                mService.mWindowPlacerLocked.performSurfacePlacement();
-            }
+        if (mContainer == null) {
+            throw new IllegalArgumentException("resizeStack: stack " + this + " not found.");
+        }
+        // We might trigger a configuration change. Save the current task bounds for freezing.
+        mContainer.prepareFreezingTaskBounds();
+        if (mContainer.setBounds(bounds, taskBounds, taskTempInsetBounds)
+                && mContainer.isVisible()) {
+            mContainer.getDisplayContent().setLayoutNeeded();
+            mService.mWindowPlacerLocked.performSurfacePlacement();
         }
     }
 
     public void onPipAnimationEndResize() {
-        synchronized (mService.mGlobalLock) {
-            mContainer.onPipAnimationEndResize();
-        }
+        mContainer.onPipAnimationEndResize();
     }
 
     /**
@@ -205,45 +181,37 @@
     public void getStackDockedModeBounds(Configuration parentConfig, Rect dockedBounds,
             Rect currentTempTaskBounds,
             Rect outStackBounds, Rect outTempTaskBounds) {
-        synchronized (mGlobalLock) {
-            if (mContainer != null) {
-                mContainer.getStackDockedModeBoundsLocked(parentConfig, dockedBounds,
-                        currentTempTaskBounds, outStackBounds, outTempTaskBounds);
-                return;
-            }
-            outStackBounds.setEmpty();
-            outTempTaskBounds.setEmpty();
+        if (mContainer != null) {
+            mContainer.getStackDockedModeBoundsLocked(parentConfig, dockedBounds,
+                    currentTempTaskBounds, outStackBounds, outTempTaskBounds);
+            return;
         }
+        outStackBounds.setEmpty();
+        outTempTaskBounds.setEmpty();
     }
 
     public void prepareFreezingTaskBounds() {
-        synchronized (mGlobalLock) {
-            if (mContainer == null) {
-                throw new IllegalArgumentException("prepareFreezingTaskBounds: stack " + this
-                        + " not found.");
-            }
-            mContainer.prepareFreezingTaskBounds();
+        if (mContainer == null) {
+            throw new IllegalArgumentException("prepareFreezingTaskBounds: stack " + this
+                    + " not found.");
         }
+        mContainer.prepareFreezingTaskBounds();
     }
 
     public void getRawBounds(Rect outBounds) {
-        synchronized (mGlobalLock) {
-            if (mContainer.matchParentBounds()) {
-                outBounds.setEmpty();
-            } else {
-                mContainer.getRawBounds(outBounds);
-            }
+        if (mContainer.matchParentBounds()) {
+            outBounds.setEmpty();
+        } else {
+            mContainer.getRawBounds(outBounds);
         }
     }
 
     public void getBounds(Rect outBounds) {
-        synchronized (mGlobalLock) {
-            if (mContainer != null) {
-                mContainer.getBounds(outBounds);
-                return;
-            }
-            outBounds.setEmpty();
+        if (mContainer != null) {
+            mContainer.getBounds(outBounds);
+            return;
         }
+        outBounds.setEmpty();
     }
 
     /**
@@ -256,73 +224,71 @@
             Rect nonDecorBounds, Rect stableBounds, boolean overrideWidth,
             boolean overrideHeight, float density, Configuration config,
             Configuration parentConfig, int windowingMode) {
-        synchronized (mGlobalLock) {
-            final TaskStack stack = mContainer;
-            final DisplayContent displayContent = stack.getDisplayContent();
-            final DisplayInfo di = displayContent.getDisplayInfo();
-            final DisplayCutout displayCutout = di.displayCutout;
-            final DisplayPolicy displayPolicy = displayContent.getDisplayPolicy();
+        final TaskStack stack = mContainer;
+        final DisplayContent displayContent = stack.getDisplayContent();
+        final DisplayInfo di = displayContent.getDisplayInfo();
+        final DisplayCutout displayCutout = di.displayCutout;
+        final DisplayPolicy displayPolicy = displayContent.getDisplayPolicy();
 
-            // Get the insets and display bounds
-            displayPolicy.getStableInsetsLw(di.rotation, di.logicalWidth, di.logicalHeight,
-                    displayCutout, mTmpStableInsets);
-            displayPolicy.getNonDecorInsetsLw(di.rotation, di.logicalWidth, di.logicalHeight,
-                    displayCutout, mTmpNonDecorInsets);
-            mTmpDisplayBounds.set(0, 0, di.logicalWidth, di.logicalHeight);
+        // Get the insets and display bounds
+        displayPolicy.getStableInsetsLw(di.rotation, di.logicalWidth, di.logicalHeight,
+                displayCutout, mTmpStableInsets);
+        displayPolicy.getNonDecorInsetsLw(di.rotation, di.logicalWidth, di.logicalHeight,
+                displayCutout, mTmpNonDecorInsets);
+        mTmpDisplayBounds.set(0, 0, di.logicalWidth, di.logicalHeight);
 
-            int width;
-            int height;
+        int width;
+        int height;
 
-            final Rect parentAppBounds = parentConfig.windowConfiguration.getAppBounds();
+        final Rect parentAppBounds = parentConfig.windowConfiguration.getAppBounds();
 
-            config.windowConfiguration.setBounds(bounds);
-            config.windowConfiguration.setAppBounds(!bounds.isEmpty() ? bounds : null);
-            boolean intersectParentBounds = false;
+        config.windowConfiguration.setBounds(bounds);
+        config.windowConfiguration.setAppBounds(!bounds.isEmpty() ? bounds : null);
+        boolean intersectParentBounds = false;
 
-            if (WindowConfiguration.isFloating(windowingMode)) {
-                // Floating tasks should not be resized to the screen's bounds.
+        if (WindowConfiguration.isFloating(windowingMode)) {
+            // Floating tasks should not be resized to the screen's bounds.
 
-                if (windowingMode == WindowConfiguration.WINDOWING_MODE_PINNED
-                        && bounds.width() == mTmpDisplayBounds.width()
-                        && bounds.height() == mTmpDisplayBounds.height()) {
-                    // If the bounds we are animating is the same as the fullscreen stack
-                    // dimensions, then apply the same inset calculations that we normally do for
-                    // the fullscreen stack, without intersecting it with the display bounds
-                    stableBounds.inset(mTmpStableInsets);
-                    nonDecorBounds.inset(mTmpNonDecorInsets);
-                    // Move app bounds to zero to apply intersection with parent correctly. They are
-                    // used only for evaluating width and height, so it's OK to move them around.
-                    config.windowConfiguration.getAppBounds().offsetTo(0, 0);
-                    intersectParentBounds = true;
-                }
-                width = (int) (stableBounds.width() / density);
-                height = (int) (stableBounds.height() / density);
-            } else {
-                // For calculating screenWidthDp, screenWidthDp, we use the stable inset screen
-                // area, i.e. the screen area without the system bars.
-                // Additionally task dimensions should not be bigger than its parents dimensions.
-                // The non decor inset are areas that could never be removed in Honeycomb. See
-                // {@link WindowManagerPolicy#getNonDecorInsetsLw}.
-                intersectDisplayBoundsExcludeInsets(nonDecorBounds, bounds, mTmpNonDecorInsets,
-                        mTmpDisplayBounds, overrideWidth, overrideHeight);
-                intersectDisplayBoundsExcludeInsets(stableBounds, bounds, mTmpStableInsets,
-                        mTmpDisplayBounds, overrideWidth, overrideHeight);
-                width = Math.min((int) (stableBounds.width() / density),
-                        parentConfig.screenWidthDp);
-                height = Math.min((int) (stableBounds.height() / density),
-                        parentConfig.screenHeightDp);
+            if (windowingMode == WindowConfiguration.WINDOWING_MODE_PINNED
+                    && bounds.width() == mTmpDisplayBounds.width()
+                    && bounds.height() == mTmpDisplayBounds.height()) {
+                // If the bounds we are animating is the same as the fullscreen stack
+                // dimensions, then apply the same inset calculations that we normally do for
+                // the fullscreen stack, without intersecting it with the display bounds
+                stableBounds.inset(mTmpStableInsets);
+                nonDecorBounds.inset(mTmpNonDecorInsets);
+                // Move app bounds to zero to apply intersection with parent correctly. They are
+                // used only for evaluating width and height, so it's OK to move them around.
+                config.windowConfiguration.getAppBounds().offsetTo(0, 0);
                 intersectParentBounds = true;
             }
-
-            if (intersectParentBounds && config.windowConfiguration.getAppBounds() != null) {
-                config.windowConfiguration.getAppBounds().intersect(parentAppBounds);
-            }
-
-            config.screenWidthDp = width;
-            config.screenHeightDp = height;
-            config.smallestScreenWidthDp = getSmallestWidthForTaskBounds(
-                    bounds, density, windowingMode);
+            width = (int) (stableBounds.width() / density);
+            height = (int) (stableBounds.height() / density);
+        } else {
+            // For calculating screenWidthDp, screenWidthDp, we use the stable inset screen
+            // area, i.e. the screen area without the system bars.
+            // Additionally task dimensions should not be bigger than its parents dimensions.
+            // The non decor inset are areas that could never be removed in Honeycomb. See
+            // {@link WindowManagerPolicy#getNonDecorInsetsLw}.
+            intersectDisplayBoundsExcludeInsets(nonDecorBounds, bounds, mTmpNonDecorInsets,
+                    mTmpDisplayBounds, overrideWidth, overrideHeight);
+            intersectDisplayBoundsExcludeInsets(stableBounds, bounds, mTmpStableInsets,
+                    mTmpDisplayBounds, overrideWidth, overrideHeight);
+            width = Math.min((int) (stableBounds.width() / density),
+                    parentConfig.screenWidthDp);
+            height = Math.min((int) (stableBounds.height() / density),
+                    parentConfig.screenHeightDp);
+            intersectParentBounds = true;
         }
+
+        if (intersectParentBounds && config.windowConfiguration.getAppBounds() != null) {
+            config.windowConfiguration.getAppBounds().intersect(parentAppBounds);
+        }
+
+        config.screenWidthDp = width;
+        config.screenHeightDp = height;
+        config.smallestScreenWidthDp = getSmallestWidthForTaskBounds(
+                bounds, density, windowingMode);
     }
 
     /**
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 67657d0..69d9810 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -24,6 +24,7 @@
 import static android.content.res.Configuration.EMPTY;
 
 import static com.android.server.EventLogTags.WM_TASK_REMOVED;
+import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_DOCKED_DIVIDER;
 import static com.android.server.wm.TaskProto.APP_WINDOW_TOKENS;
 import static com.android.server.wm.TaskProto.BOUNDS;
 import static com.android.server.wm.TaskProto.DEFER_REMOVAL;
@@ -38,6 +39,7 @@
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
 
 import android.annotation.CallSuper;
+import android.app.ActivityManager;
 import android.app.ActivityManager.TaskDescription;
 import android.content.pm.ActivityInfo;
 import android.content.res.Configuration;
@@ -54,7 +56,7 @@
 import java.io.PrintWriter;
 import java.util.function.Consumer;
 
-class Task extends WindowContainer<AppWindowToken> {
+class Task extends WindowContainer<AppWindowToken> implements ConfigurationContainerListener{
     static final String TAG = TAG_WITH_CLASS_NAME ? "Task" : TAG_WM;
 
     // TODO: Track parent marks like this in WindowContainer.
@@ -109,16 +111,24 @@
     /** @see #setCanAffectSystemUiFlags */
     private boolean mCanAffectSystemUiFlags = true;
 
+    // TODO: remove after unification
+    TaskRecord mTaskRecord;
+
     Task(int taskId, TaskStack stack, int userId, WindowManagerService service, int resizeMode,
             boolean supportsPictureInPicture, TaskDescription taskDescription,
-            TaskWindowContainerController controller) {
+            TaskRecord taskRecord) {
         super(service);
         mTaskId = taskId;
         mStack = stack;
         mUserId = userId;
         mResizeMode = resizeMode;
         mSupportsPictureInPicture = supportsPictureInPicture;
-        setController(controller);
+        mTaskRecord = taskRecord;
+        if (mTaskRecord != null) {
+            // This can be null when we call createTaskInStack in WindowTestUtils. Remove this after
+            // unification.
+            mTaskRecord.registerConfigurationChangeListener(this);
+        }
         setBounds(getRequestedOverrideBounds());
         mTaskDescription = taskDescription;
 
@@ -195,6 +205,21 @@
         super.removeImmediately();
     }
 
+    void reparent(StackWindowController stackController, int position, boolean moveParents) {
+        if (DEBUG_STACK) {
+            Slog.i(TAG_WM, "reparent: moving taskId=" + mTaskId
+                    + " to stack=" + stackController + " at " + position);
+        }
+        final TaskStack stack = stackController.mContainer;
+        if (stack == null) {
+            throw new IllegalArgumentException("reparent: could not find stack="
+                    + stackController);
+        }
+        reparent(stack, position, moveParents);
+        getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
+    }
+
+
     void reparent(TaskStack stack, int position, boolean moveParents) {
         if (stack == mStack) {
             throw new IllegalArgumentException(
@@ -300,6 +325,12 @@
         return boundsChange;
     }
 
+    void resize(boolean relayout, boolean forced) {
+        if (setBounds(getRequestedOverrideBounds(), forced) != BOUNDS_CHANGE_NONE && relayout) {
+            getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
+        }
+    }
+
     @Override
     void onDisplayChanged(DisplayContent dc) {
         adjustBoundsForDisplayChangeIfNeeded(dc);
@@ -515,6 +546,15 @@
         return mDragResizeMode;
     }
 
+    /**
+     * 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) {
+        setDragResizing(resizing, DRAG_RESIZE_MODE_DOCKED_DIVIDER);
+    }
+
     private void adjustBoundsForDisplayChangeIfNeeded(final DisplayContent displayContent) {
         if (displayContent == null) {
             return;
@@ -556,9 +596,8 @@
 
         displayContent.rotateBounds(mRotation, newRotation, mTmpRect2);
         if (setBounds(mTmpRect2) != BOUNDS_CHANGE_NONE) {
-            final TaskWindowContainerController controller = getController();
-            if (controller != null) {
-                controller.requestResize(getBounds(), RESIZE_MODE_SYSTEM_SCREEN_ROTATION);
+            if (mTaskRecord != null) {
+                mTaskRecord.requestResize(getBounds(), RESIZE_MODE_SYSTEM_SCREEN_ROTATION);
             }
         }
     }
@@ -631,6 +670,20 @@
         return null;
     }
 
+    void positionChildAtTop(AppWindowToken aToken) {
+        positionChildAt(aToken, POSITION_TOP);
+    }
+
+    void positionChildAt(AppWindowToken aToken, int position) {
+        if (aToken == null) {
+            Slog.w(TAG_WM,
+                    "Attempted to position of non-existing app");
+            return;
+        }
+
+        positionChildAt(position, aToken, false /* includeParents */);
+    }
+
     boolean isFullscreen() {
         if (useCurrentBounds()) {
             return matchParentBounds();
@@ -656,6 +709,10 @@
         mTaskDescription = taskDescription;
     }
 
+    void onSnapshotChanged(ActivityManager.TaskSnapshot snapshot) {
+        mTaskRecord.onSnapshotChanged(snapshot);
+    }
+
     TaskDescription getTaskDescription() {
         return mTaskDescription;
     }
@@ -666,11 +723,6 @@
     }
 
     @Override
-    TaskWindowContainerController getController() {
-        return (TaskWindowContainerController) super.getController();
-    }
-
-    @Override
     void forAllTasks(Consumer<Task> callback) {
         callback.accept(this);
     }
diff --git a/services/core/java/com/android/server/wm/TaskRecord.java b/services/core/java/com/android/server/wm/TaskRecord.java
index b6a6009..56e634a 100644
--- a/services/core/java/com/android/server/wm/TaskRecord.java
+++ b/services/core/java/com/android/server/wm/TaskRecord.java
@@ -47,6 +47,7 @@
 import static android.provider.Settings.Secure.USER_SETUP_COMPLETE;
 import static android.view.Display.DEFAULT_DISPLAY;
 
+import static com.android.server.EventLogTags.WM_TASK_CREATED;
 import static com.android.server.am.TaskRecordProto.ACTIVITIES;
 import static com.android.server.am.TaskRecordProto.ACTIVITY_TYPE;
 import static com.android.server.am.TaskRecordProto.BOUNDS;
@@ -76,6 +77,10 @@
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_TASKS;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
+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;
 
 import static java.lang.Integer.MAX_VALUE;
 
@@ -106,6 +111,7 @@
 import android.provider.Settings;
 import android.service.voice.IVoiceInteractionSession;
 import android.util.DisplayMetrics;
+import android.util.EventLog;
 import android.util.Slog;
 import android.util.proto.ProtoOutputStream;
 
@@ -125,8 +131,7 @@
 import java.util.ArrayList;
 import java.util.Objects;
 
-// TODO: Make package private again once move to WM package is complete.
-public class TaskRecord extends ConfigurationContainer implements TaskWindowContainerListener {
+class TaskRecord extends ConfigurationContainer {
     private static final String TAG = TAG_WITH_CLASS_NAME ? "TaskRecord" : TAG_ATM;
     private static final String TAG_ADD_REMOVE = TAG + POSTFIX_ADD_REMOVE;
     private static final String TAG_RECENTS = TAG + POSTFIX_RECENTS;
@@ -318,7 +323,8 @@
     /** Helper object used for updating override configuration. */
     private Configuration mTmpConfig = new Configuration();
 
-    private TaskWindowContainerController mWindowContainerController;
+    // TODO: remove after unification
+    Task mTask;
 
     /**
      * Don't use constructor directly. Use {@link #create(ActivityTaskManagerService, int,
@@ -424,43 +430,54 @@
         mService.getTaskChangeNotificationController().notifyTaskCreated(_taskId, realActivity);
     }
 
-    TaskWindowContainerController getWindowContainerController() {
-        return mWindowContainerController;
+    Task getTask() {
+        return mTask;
     }
 
-    void createWindowContainer(boolean onTop, boolean showForAllUsers) {
-        if (mWindowContainerController != null) {
-            throw new IllegalArgumentException("Window container=" + mWindowContainerController
+    void createTask(boolean onTop, boolean showForAllUsers) {
+        if (mTask != null) {
+            throw new IllegalArgumentException("mTask=" + mTask
                     + " already created for task=" + this);
         }
 
         final Rect bounds = updateOverrideConfigurationFromLaunchBounds();
-        setWindowContainerController(new TaskWindowContainerController(taskId, this,
-                getStack().getWindowContainerController(), userId, bounds,
-                mResizeMode, mSupportsPictureInPicture, onTop,
-                showForAllUsers, lastTaskDescription));
+        final StackWindowController stackController = getStack().getWindowContainerController();
+
+        if (DEBUG_STACK) {
+            Slog.i(TAG_WM, "TaskRecord: taskId=" + taskId
+                    + " stack=" + stackController + " bounds=" + bounds);
+        }
+
+        final TaskStack stack = stackController.mContainer;
+        if (stack == null) {
+            throw new IllegalArgumentException("TaskRecord: invalid stack="
+                    + stackController);
+        }
+        EventLog.writeEvent(WM_TASK_CREATED, taskId, stack.mStackId);
+        mTask = new Task(taskId, stack, userId, mService.mWindowManager, mResizeMode,
+                mSupportsPictureInPicture, lastTaskDescription, this);
+        final int position = onTop ? POSITION_TOP : POSITION_BOTTOM;
+
+        if (!mDisplayedBounds.isEmpty()) {
+            mTask.setOverrideDisplayedBounds(mDisplayedBounds);
+        }
+        // We only want to move the parents to the parents if we are creating this task at the
+        // top of its stack.
+        stack.addTask(mTask, position, showForAllUsers, onTop /* moveParents */);
     }
 
-    /**
-     * Should only be invoked from {@link #createWindowContainer(boolean, boolean)}.
-     */
-    @VisibleForTesting
-    protected void setWindowContainerController(TaskWindowContainerController controller) {
-        if (mWindowContainerController != null) {
-            throw new IllegalArgumentException("Window container=" + mWindowContainerController
-                    + " already created for task=" + this);
-        }
-
-        mWindowContainerController = controller;
-        if (!mDisplayedBounds.isEmpty() && controller.mContainer != null) {
-            controller.mContainer.setOverrideDisplayedBounds(mDisplayedBounds);
-        }
+    void setTask(Task task) {
+        mTask = task;
     }
 
     void removeWindowContainer() {
         mService.getLockTaskController().clearLockedTask(this);
-        mWindowContainerController.removeContainer();
-        mWindowContainerController = null;
+        if (mTask == null) {
+            if (DEBUG_STACK) Slog.i(TAG_WM, "removeTask: could not find taskId=" + taskId);
+            return;
+        }
+        mTask.removeIfPossible();
+        mTask = null;
         if (!getWindowConfiguration().persistTaskBounds()) {
             // Reset current bounds for task whose bounds shouldn't be persisted so it uses
             // default configuration the next time it launches.
@@ -469,7 +486,6 @@
         mService.getTaskChangeNotificationController().notifyTaskRemoved(taskId);
     }
 
-    @Override
     public void onSnapshotChanged(TaskSnapshot snapshot) {
         mService.getTaskChangeNotificationController().notifyTaskSnapshotChanged(taskId, snapshot);
     }
@@ -479,17 +495,20 @@
             return;
         }
         mResizeMode = resizeMode;
-        mWindowContainerController.setResizeable(resizeMode);
+        mTask.setResizeable(resizeMode);
         mService.mRootActivityContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
         mService.mRootActivityContainer.resumeFocusedStacksTopActivities();
     }
 
     void setTaskDockedResizing(boolean resizing) {
-        mWindowContainerController.setTaskDockedResizing(resizing);
+        if (mTask == null) {
+            Slog.w(TAG_WM, "setTaskDockedResizing: taskId " + taskId + " not found.");
+            return;
+        }
+        mTask.setTaskDockedResizing(resizing);
     }
 
     // TODO: Consolidate this with the resize() method below.
-    @Override
     public void requestResize(Rect bounds, int resizeMode) {
         mService.resizeTask(taskId, bounds, resizeMode);
     }
@@ -511,7 +530,7 @@
                 return true;
             }
 
-            if (mWindowContainerController == null) {
+            if (mTask == null) {
                 // Task doesn't exist in window manager yet (e.g. was restored from recents).
                 // All we can do for now is update the bounds so it can be used when the task is
                 // added to window manager.
@@ -558,7 +577,7 @@
                     }
                 }
             }
-            mWindowContainerController.resize(kept, forced);
+            mTask.resize(kept, forced);
 
             saveLaunchingStateIfNeeded();
 
@@ -571,11 +590,15 @@
 
     // TODO: Investigate combining with the resize() method above.
     void resizeWindowContainer() {
-        mWindowContainerController.resize(false /* relayout */, false /* forced */);
+        mTask.resize(false /* relayout */, false /* forced */);
     }
 
     void getWindowContainerBounds(Rect bounds) {
-        mWindowContainerController.getBounds(bounds);
+        if (mTask != null) {
+            mTask.getBounds(bounds);
+        } else {
+            bounds.setEmpty();
+        }
     }
 
     /**
@@ -679,7 +702,7 @@
 
             // Must reparent first in window manager to avoid a situation where AM can delete the
             // we are coming from in WM before we reparent because it became empty.
-            mWindowContainerController.reparent(toStack.getWindowContainerController(), position,
+            mTask.reparent(toStack.getWindowContainerController(), position,
                     moveStackMode == REPARENT_MOVE_STACK_TO_FRONT);
 
             final boolean moveStackToFront = moveStackMode == REPARENT_MOVE_STACK_TO_FRONT
@@ -779,7 +802,11 @@
     }
 
     void cancelWindowTransition() {
-        mWindowContainerController.cancelWindowTransition();
+        if (mTask == null) {
+            Slog.w(TAG_WM, "cancelWindowTransition: taskId " + taskId + " not found.");
+            return;
+        }
+        mTask.cancelTaskWindowTransition();
     }
 
     /**
@@ -1190,7 +1217,7 @@
         mActivities.add(newTop);
 
         // Make sure window manager is aware of the position change.
-        mWindowContainerController.positionChildAtTop(newTop.mAppWindowToken);
+        mTask.positionChildAtTop(newTop.mAppWindowToken);
         updateEffectiveIntent();
 
         setFrontOfTask();
@@ -1275,7 +1302,7 @@
         if (r.mAppWindowToken != null) {
             // Only attempt to move in WM if the child has a controller. It is possible we haven't
             // created controller for the activity we are starting yet.
-            mWindowContainerController.positionChildAt(r.mAppWindowToken, index);
+            mTask.positionChildAt(r.mAppWindowToken, index);
         }
 
         // Make sure the list of display UID whitelists is updated
@@ -1643,8 +1670,8 @@
             }
             lastTaskDescription = new TaskDescription(label, null, iconResource, iconFilename,
                     colorPrimary, colorBackground, statusBarColor, navigationBarColor);
-            if (mWindowContainerController != null) {
-                mWindowContainerController.setTaskDescription(lastTaskDescription);
+            if (mTask != null) {
+                mTask.setTaskDescription(lastTaskDescription);
             }
             // Update the task affiliation color if we are the parent of the group
             if (taskId == mAffiliatedTaskId) {
@@ -1879,9 +1906,8 @@
         } else {
             mDisplayedBounds.set(bounds);
         }
-        final TaskWindowContainerController controller = getWindowContainerController();
-        if (controller != null && controller.mContainer != null) {
-            controller.mContainer.setOverrideDisplayedBounds(
+        if (mTask != null) {
+            mTask.setOverrideDisplayedBounds(
                     mDisplayedBounds.isEmpty() ? null : mDisplayedBounds);
         }
     }
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java
index 7ab4d08..01a5622 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotController.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java
@@ -191,9 +191,7 @@
                 } else {
                     mCache.putSnapshot(task, snapshot);
                     mPersister.persistSnapshot(task.mTaskId, task.mUserId, snapshot);
-                    if (task.getController() != null) {
-                        task.getController().reportSnapshotChanged(snapshot);
-                    }
+                    task.onSnapshotChanged(snapshot);
                 }
             }
         }
diff --git a/services/core/java/com/android/server/wm/TaskWindowContainerController.java b/services/core/java/com/android/server/wm/TaskWindowContainerController.java
deleted file mode 100644
index b87b65e..0000000
--- a/services/core/java/com/android/server/wm/TaskWindowContainerController.java
+++ /dev/null
@@ -1,262 +0,0 @@
-/*
- * 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 static com.android.server.EventLogTags.WM_TASK_CREATED;
-import static com.android.server.wm.ConfigurationContainer.BOUNDS_CHANGE_NONE;
-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;
-
-import android.app.ActivityManager.TaskDescription;
-import android.app.ActivityManager.TaskSnapshot;
-import android.graphics.Rect;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-import android.util.EventLog;
-import android.util.Slog;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-import java.lang.ref.WeakReference;
-
-/**
- * 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, TaskWindowContainerListener> {
-
-    private final int mTaskId;
-    private final H mHandler;
-
-    public TaskWindowContainerController(int taskId, TaskWindowContainerListener listener,
-            StackWindowController stackController, int userId, Rect bounds, int resizeMode,
-            boolean supportsPictureInPicture, boolean toTop, boolean showForAllUsers,
-            TaskDescription taskDescription) {
-        this(taskId, listener, stackController, userId, bounds, resizeMode,
-                supportsPictureInPicture, toTop, showForAllUsers, taskDescription,
-                WindowManagerService.getInstance());
-    }
-
-    public TaskWindowContainerController(int taskId, TaskWindowContainerListener listener,
-            StackWindowController stackController, int userId, Rect bounds, int resizeMode,
-            boolean supportsPictureInPicture, boolean toTop, boolean showForAllUsers,
-            TaskDescription taskDescription, WindowManagerService service) {
-        super(listener, service);
-        mTaskId = taskId;
-        mHandler = new H(new WeakReference<>(this), service.mH.getLooper());
-
-        synchronized (mGlobalLock) {
-            if (DEBUG_STACK) Slog.i(TAG_WM, "TaskWindowContainerController: taskId=" + taskId
-                    + " stack=" + stackController + " bounds=" + bounds);
-
-            final TaskStack stack = stackController.mContainer;
-            if (stack == null) {
-                throw new IllegalArgumentException("TaskWindowContainerController: invalid stack="
-                        + stackController);
-            }
-            EventLog.writeEvent(WM_TASK_CREATED, taskId, stack.mStackId);
-            final Task task = createTask(taskId, stack, userId, resizeMode,
-                    supportsPictureInPicture, taskDescription);
-            final int position = toTop ? POSITION_TOP : POSITION_BOTTOM;
-            // We only want to move the parents to the parents if we are creating this task at the
-            // top of its stack.
-            stack.addTask(task, position, showForAllUsers, toTop /* moveParents */);
-        }
-    }
-
-    @VisibleForTesting
-    Task createTask(int taskId, TaskStack stack, int userId, int resizeMode,
-            boolean supportsPictureInPicture, TaskDescription taskDescription) {
-        return new Task(taskId, stack, userId, mService, resizeMode, supportsPictureInPicture,
-                taskDescription, this);
-    }
-
-    @Override
-    public void removeContainer() {
-        synchronized (mGlobalLock) {
-            if (mContainer == null) {
-                if (DEBUG_STACK) Slog.i(TAG_WM, "removeTask: could not find taskId=" + mTaskId);
-                return;
-            }
-            mContainer.removeIfPossible();
-            super.removeContainer();
-        }
-    }
-
-    void positionChildAtTop(AppWindowToken aToken) {
-        positionChildAt(aToken, POSITION_TOP);
-    }
-
-    void positionChildAt(AppWindowToken aToken, int position) {
-        synchronized (mService.mGlobalLock) {
-            if (aToken == null) {
-                Slog.w(TAG_WM,
-                        "Attempted to position of non-existing app");
-                return;
-            }
-
-            final Task task = mContainer;
-            if (task == null) {
-                throw new IllegalArgumentException("positionChildAt: invalid task=" + this);
-            }
-            task.positionChildAt(position, aToken, false /* includeParents */);
-        }
-    }
-
-    public void reparent(StackWindowController stackController, int position, boolean moveParents) {
-        synchronized (mGlobalLock) {
-            if (DEBUG_STACK) Slog.i(TAG_WM, "reparent: moving taskId=" + mTaskId
-                    + " to stack=" + stackController + " at " + position);
-            if (mContainer == null) {
-                if (DEBUG_STACK) Slog.i(TAG_WM,
-                        "reparent: could not find taskId=" + mTaskId);
-                return;
-            }
-            final TaskStack stack = stackController.mContainer;
-            if (stack == null) {
-                throw new IllegalArgumentException("reparent: could not find stack="
-                        + stackController);
-            }
-            mContainer.reparent(stack, position, moveParents);
-            mContainer.getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
-        }
-    }
-
-    public void setResizeable(int resizeMode) {
-        synchronized (mGlobalLock) {
-            if (mContainer != null) {
-                mContainer.setResizeable(resizeMode);
-            }
-        }
-    }
-
-    public void resize(boolean relayout, boolean forced) {
-        synchronized (mGlobalLock) {
-            if (mContainer == null) {
-                throw new IllegalArgumentException("resizeTask: taskId " + mTaskId + " not found.");
-            }
-
-            if (mContainer.setBounds(
-                    mContainer.getRequestedOverrideBounds(), forced) != BOUNDS_CHANGE_NONE
-                    && relayout) {
-                mContainer.getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
-            }
-        }
-    }
-
-    public void getBounds(Rect bounds) {
-        synchronized (mGlobalLock) {
-            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 (mGlobalLock) {
-            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 (mGlobalLock) {
-            if (mContainer == null) {
-                Slog.w(TAG_WM, "cancelWindowTransition: taskId " + mTaskId + " not found.");
-                return;
-            }
-            mContainer.cancelTaskWindowTransition();
-        }
-    }
-
-    public void setTaskDescription(TaskDescription taskDescription) {
-        synchronized (mGlobalLock) {
-            if (mContainer == null) {
-                Slog.w(TAG_WM, "setTaskDescription: taskId " + mTaskId + " not found.");
-                return;
-            }
-            mContainer.setTaskDescription(taskDescription);
-        }
-    }
-
-    public boolean isDragResizing() {
-        synchronized (mGlobalLock) {
-            return mContainer.isDragResizing();
-        }
-    }
-
-    void reportSnapshotChanged(TaskSnapshot snapshot) {
-        mHandler.obtainMessage(H.REPORT_SNAPSHOT_CHANGED, snapshot).sendToTarget();
-    }
-
-    void requestResize(Rect bounds, int resizeMode) {
-        mHandler.obtainMessage(H.REQUEST_RESIZE, resizeMode, 0, bounds).sendToTarget();
-    }
-
-    @Override
-    public String toString() {
-        return "{TaskWindowContainerController taskId=" + mTaskId + "}";
-    }
-
-    private static final class H extends Handler {
-
-        static final int REPORT_SNAPSHOT_CHANGED = 0;
-        static final int REQUEST_RESIZE = 1;
-
-        private final WeakReference<TaskWindowContainerController> mController;
-
-        H(WeakReference<TaskWindowContainerController> controller, Looper looper) {
-            super(looper);
-            mController = controller;
-        }
-
-        @Override
-        public void handleMessage(Message msg) {
-            final TaskWindowContainerController controller = mController.get();
-            final TaskWindowContainerListener listener = (controller != null)
-                    ? controller.mListener : null;
-            if (listener == null) {
-                return;
-            }
-            switch (msg.what) {
-                case REPORT_SNAPSHOT_CHANGED:
-                    listener.onSnapshotChanged((TaskSnapshot) msg.obj);
-                    break;
-                case REQUEST_RESIZE:
-                    listener.requestResize((Rect) msg.obj, msg.arg1);
-                    break;
-            }
-        }
-    }
-}
diff --git a/services/core/java/com/android/server/wm/TaskWindowContainerListener.java b/services/core/java/com/android/server/wm/TaskWindowContainerListener.java
deleted file mode 100644
index af67de3..0000000
--- a/services/core/java/com/android/server/wm/TaskWindowContainerListener.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2017 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.app.ActivityManager.TaskSnapshot;
-import android.graphics.Rect;
-
-/**
- * Interface used by the creator of {@link TaskWindowContainerController} to listen to changes with
- * the task container.
- */
-public interface TaskWindowContainerListener extends WindowContainerListener {
-
-    /** Called when the snapshot of this task has changed. */
-    void onSnapshotChanged(TaskSnapshot snapshot);
-
-    /** Called when the task container would like its controller to resize. */
-    void requestResize(Rect bounds, int resizeMode);
-}
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 f6871b3..85410f5 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
@@ -82,17 +82,17 @@
 
     @Test
     public void testEmptyTaskCleanupOnRemove() {
-        assertNotNull(mTask.getWindowContainerController());
+        assertNotNull(mTask.getTask());
         mStack.removeTask(mTask, "testEmptyTaskCleanupOnRemove", REMOVE_TASK_MODE_DESTROYING);
-        assertNull(mTask.getWindowContainerController());
+        assertNull(mTask.getTask());
     }
 
     @Test
     public void testOccupiedTaskCleanupOnRemove() {
         final ActivityRecord r = new ActivityBuilder(mService).setTask(mTask).build();
-        assertNotNull(mTask.getWindowContainerController());
+        assertNotNull(mTask.getTask());
         mStack.removeTask(mTask, "testOccupiedTaskCleanupOnRemove", REMOVE_TASK_MODE_DESTROYING);
-        assertNotNull(mTask.getWindowContainerController());
+        assertNotNull(mTask.getTask());
     }
 
     @Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
index f553c35..79a052c 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
@@ -345,7 +345,7 @@
                 mStack.moveToFront("test");
                 mStack.addTask(task, true, "creating test task");
                 task.setStack(mStack);
-                task.setWindowContainerController();
+                task.setTask();
             }
 
             task.touchActiveTime();
@@ -361,12 +361,12 @@
             }
 
             @Override
-            void createWindowContainer(boolean onTop, boolean showForAllUsers) {
-                setWindowContainerController();
+            void createTask(boolean onTop, boolean showForAllUsers) {
+                setTask();
             }
 
-            private void setWindowContainerController() {
-                setWindowContainerController(mock(TaskWindowContainerController.class));
+            private void setTask() {
+                setTask(mock(Task.class));
             }
         }
     }
diff --git a/services/tests/wmtests/src/com/android/server/wm/StackWindowControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/StackWindowControllerTests.java
index ce5b13c..5690b58 100644
--- a/services/tests/wmtests/src/com/android/server/wm/StackWindowControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/StackWindowControllerTests.java
@@ -41,17 +41,14 @@
     public void testRemoveContainer() {
         final StackWindowController stackController =
                 createStackControllerOnDisplay(mDisplayContent);
-        final WindowTestUtils.TestTaskWindowContainerController taskController =
-                new WindowTestUtils.TestTaskWindowContainerController(stackController);
+        final WindowTestUtils.TestTask task = WindowTestUtils.createTestTask(stackController);
 
         final TaskStack stack = stackController.mContainer;
-        final Task task = taskController.mContainer;
         assertNotNull(stack);
         assertNotNull(task);
         stackController.removeContainer();
         // Assert that the container was removed.
         assertNull(stackController.mContainer);
-        assertNull(taskController.mContainer);
         assertNull(stack.getDisplayContent());
         assertNull(task.getDisplayContent());
         assertNull(task.mStack);
@@ -61,11 +58,9 @@
     public void testRemoveContainer_deferRemoval() {
         final StackWindowController stackController =
                 createStackControllerOnDisplay(mDisplayContent);
-        final WindowTestUtils.TestTaskWindowContainerController taskController =
-                new WindowTestUtils.TestTaskWindowContainerController(stackController);
+        final WindowTestUtils.TestTask task = WindowTestUtils.createTestTask(stackController);
 
         final TaskStack stack = stackController.mContainer;
-        final WindowTestUtils.TestTask task = (WindowTestUtils.TestTask) taskController.mContainer;
         // Stack removal is deferred if one of its child is animating.
         task.setLocalIsAnimating(true);
 
@@ -75,11 +70,12 @@
         // the stack window container is removed.
         assertNull(stackController.mContainer);
         assertNull(stack.getController());
-        assertNotNull(taskController.mContainer);
-        assertNotNull(task.getController());
+        assertNotNull(task);
 
         stack.removeImmediately();
-        assertNull(taskController.mContainer);
+        // After removing, the task will be isolated.
+        assertNull(task.getParent());
+        assertEquals(task.getChildCount(), 0);
         assertNull(task.getController());
     }
 
@@ -89,9 +85,7 @@
         final StackWindowController stack1Controller =
                 createStackControllerOnDisplay(mDisplayContent);
         final TaskStack stack1 = stack1Controller.mContainer;
-        final WindowTestUtils.TestTaskWindowContainerController taskController =
-                new WindowTestUtils.TestTaskWindowContainerController(stack1Controller);
-        final WindowTestUtils.TestTask task1 = (WindowTestUtils.TestTask) taskController.mContainer;
+        final WindowTestUtils.TestTask task1 = WindowTestUtils.createTestTask(stack1Controller);
         task1.mOnDisplayChangedCalled = false;
 
         // Create second display and put second stack on it.
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
new file mode 100644
index 0000000..3e32ed3
--- /dev/null
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2017 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 static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import android.platform.test.annotations.Presubmit;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.Test;
+
+/**
+ * Test class for {@link Task}.
+ *
+ * Build/Install/Run:
+ *  atest FrameworksServicesTests:TaskTests
+ */
+@SmallTest
+@Presubmit
+public class TaskTests extends WindowTestsBase {
+
+    @Test
+    public void testRemoveContainer() {
+        final StackWindowController stackController1 =
+                createStackControllerOnDisplay(mDisplayContent);
+        final WindowTestUtils.TestTask task = WindowTestUtils.createTestTask(stackController1);
+        final WindowTestUtils.TestAppWindowToken appToken =
+                WindowTestUtils.createAppWindowTokenInTask(mDisplayContent, task);
+
+        task.removeIfPossible();
+        // Assert that the container was removed.
+        assertNull(task.getParent());
+        assertEquals(task.getChildCount(), 0);
+        assertNull(appToken.getParent());
+    }
+
+    @Test
+    public void testRemoveContainer_deferRemoval() {
+        final StackWindowController stackController1 =
+                createStackControllerOnDisplay(mDisplayContent);
+        final WindowTestUtils.TestTask task = WindowTestUtils.createTestTask(stackController1);
+        final WindowTestUtils.TestAppWindowToken appToken =
+                WindowTestUtils.createAppWindowTokenInTask(mDisplayContent, task);
+
+        task.mShouldDeferRemoval = true;
+
+        task.removeIfPossible();
+        // For the case of deferred removal the task will still be connected to the its app token
+        // until the task window container is removed.
+        assertNotNull(task.getParent());
+        assertNotEquals(task.getChildCount(), 0);
+        assertNotNull(appToken.getParent());
+
+        task.removeImmediately();
+        assertNull(task.getParent());
+        assertEquals(task.getChildCount(), 0);
+        assertNull(appToken.getParent());
+    }
+
+    @Test
+    public void testReparent() {
+        final StackWindowController stackController1 =
+                createStackControllerOnDisplay(mDisplayContent);
+        final WindowTestUtils.TestTask task = WindowTestUtils.createTestTask(stackController1);
+        final StackWindowController stackController2 =
+                createStackControllerOnDisplay(mDisplayContent);
+        final WindowTestUtils.TestTask task2 = WindowTestUtils.createTestTask(stackController2);
+
+        boolean gotException = false;
+        try {
+            task.reparent(stackController1, 0, false/* moveParents */);
+        } catch (IllegalArgumentException e) {
+            gotException = true;
+        }
+        assertTrue("Should not be able to reparent to the same parent", gotException);
+
+        final StackWindowController stackController3 =
+                createStackControllerOnDisplay(mDisplayContent);
+        stackController3.setContainer(null);
+        gotException = false;
+        try {
+            task.reparent(stackController3, 0, false/* moveParents */);
+        } catch (IllegalArgumentException e) {
+            gotException = true;
+        }
+        assertTrue("Should not be able to reparent to a stack that doesn't have a container",
+                gotException);
+
+        task.reparent(stackController2, 0, false/* moveParents */);
+        assertEquals(stackController2.mContainer, task.getParent());
+        assertEquals(0, task.positionInParent());
+        assertEquals(1, task2.positionInParent());
+    }
+
+    @Test
+    public void testReparent_BetweenDisplays() {
+        // Create first stack on primary display.
+        final StackWindowController stack1Controller =
+                createStackControllerOnDisplay(mDisplayContent);
+        final TaskStack stack1 = stack1Controller.mContainer;
+        final WindowTestUtils.TestTask task = WindowTestUtils.createTestTask(stack1Controller);
+        task.mOnDisplayChangedCalled = false;
+        assertEquals(mDisplayContent, stack1.getDisplayContent());
+
+        // Create second display and put second stack on it.
+        final DisplayContent dc = createNewDisplay();
+        final StackWindowController stack2Controller = createStackControllerOnDisplay(dc);
+        final TaskStack stack2 = stack2Controller.mContainer;
+        final WindowTestUtils.TestTask task2 = WindowTestUtils.createTestTask(stack2Controller);
+        // Reparent and check state
+        task.reparent(stack2Controller, 0, false /* moveParents */);
+        assertEquals(stack2, task.getParent());
+        assertEquals(0, task.positionInParent());
+        assertEquals(1, task2.positionInParent());
+        assertTrue(task.mOnDisplayChangedCalled);
+    }
+}
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskWindowContainerControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskWindowContainerControllerTests.java
deleted file mode 100644
index bbf508d..0000000
--- a/services/tests/wmtests/src/com/android/server/wm/TaskWindowContainerControllerTests.java
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * Copyright (C) 2017 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 static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-import android.platform.test.annotations.Presubmit;
-
-import androidx.test.filters.SmallTest;
-
-import org.junit.Test;
-
-/**
- * Test class for {@link TaskWindowContainerController}.
- *
- * Build/Install/Run:
- *  atest FrameworksServicesTests:TaskWindowContainerControllerTests
- */
-@SmallTest
-@Presubmit
-public class TaskWindowContainerControllerTests extends WindowTestsBase {
-
-    /* Comment out due to removal of AppWindowContainerController
-    @Test
-    public void testRemoveContainer() {
-        final WindowTestUtils.TestTaskWindowContainerController taskController =
-                new WindowTestUtils.TestTaskWindowContainerController(this);
-        final WindowTestUtils.TestAppWindowContainerController appController =
-                new WindowTestUtils.TestAppWindowContainerController(taskController);
-
-        taskController.removeContainer();
-        // Assert that the container was removed.
-        assertNull(taskController.mContainer);
-        assertNull(appController.mContainer);
-    }
-    */
-
-    /* Comment out due to removal of AppWindowContainerController
-    @Test
-    public void testRemoveContainer_deferRemoval() {
-        final WindowTestUtils.TestTaskWindowContainerController taskController =
-                new WindowTestUtils.TestTaskWindowContainerController(this);
-        final WindowTestUtils.TestAppWindowContainerController appController =
-                new WindowTestUtils.TestAppWindowContainerController(taskController);
-
-        final WindowTestUtils.TestTask task = (WindowTestUtils.TestTask) taskController.mContainer;
-        final AppWindowToken app = appController.mContainer;
-        task.mShouldDeferRemoval = true;
-
-        taskController.removeContainer();
-        // For the case of deferred removal the task controller will no longer be connected to the
-        // container, but the app controller will still be connected to the its container until
-        // the task window container is removed.
-        assertNull(taskController.mContainer);
-        assertNull(task.getController());
-        assertNotNull(appController.mContainer);
-        assertNotNull(app.getController());
-
-        task.removeImmediately();
-        assertNull(appController.mContainer);
-        assertNull(app.getController());
-    }
-    */
-
-    @Test
-    public void testReparent() {
-        final StackWindowController stackController1 =
-                createStackControllerOnDisplay(mDisplayContent);
-        final WindowTestUtils.TestTaskWindowContainerController taskController =
-                new WindowTestUtils.TestTaskWindowContainerController(stackController1);
-        final StackWindowController stackController2 =
-                createStackControllerOnDisplay(mDisplayContent);
-        final WindowTestUtils.TestTaskWindowContainerController taskController2 =
-                new WindowTestUtils.TestTaskWindowContainerController(stackController2);
-
-        boolean gotException = false;
-        try {
-            taskController.reparent(stackController1, 0, false/* moveParents */);
-        } catch (IllegalArgumentException e) {
-            gotException = true;
-        }
-        assertTrue("Should not be able to reparent to the same parent", gotException);
-
-        final StackWindowController stackController3 =
-                createStackControllerOnDisplay(mDisplayContent);
-        stackController3.setContainer(null);
-        gotException = false;
-        try {
-            taskController.reparent(stackController3, 0, false/* moveParents */);
-        } catch (IllegalArgumentException e) {
-            gotException = true;
-        }
-        assertTrue("Should not be able to reparent to a stack that doesn't have a container",
-                gotException);
-
-        taskController.reparent(stackController2, 0, false/* moveParents */);
-        assertEquals(stackController2.mContainer, taskController.mContainer.getParent());
-        assertEquals(0, ((WindowTestUtils.TestTask) taskController.mContainer).positionInParent());
-        assertEquals(1, ((WindowTestUtils.TestTask) taskController2.mContainer).positionInParent());
-    }
-
-    @Test
-    public void testReparent_BetweenDisplays() {
-        // Create first stack on primary display.
-        final StackWindowController stack1Controller =
-                createStackControllerOnDisplay(mDisplayContent);
-        final TaskStack stack1 = stack1Controller.mContainer;
-        final WindowTestUtils.TestTaskWindowContainerController taskController =
-                new WindowTestUtils.TestTaskWindowContainerController(stack1Controller);
-        final WindowTestUtils.TestTask task1 = (WindowTestUtils.TestTask) taskController.mContainer;
-        task1.mOnDisplayChangedCalled = false;
-        assertEquals(mDisplayContent, stack1.getDisplayContent());
-
-        // Create second display and put second stack on it.
-        final DisplayContent dc = createNewDisplay();
-        final StackWindowController stack2Controller = createStackControllerOnDisplay(dc);
-        final TaskStack stack2 = stack2Controller.mContainer;
-        final WindowTestUtils.TestTaskWindowContainerController taskController2 =
-                new WindowTestUtils.TestTaskWindowContainerController(stack2Controller);
-        final WindowTestUtils.TestTask task2 =
-                (WindowTestUtils.TestTask) taskController2.mContainer;
-
-        // Reparent and check state
-        taskController.reparent(stack2Controller, 0, false /* moveParents */);
-        assertEquals(stack2, task1.getParent());
-        assertEquals(0, task1.positionInParent());
-        assertEquals(1, task2.positionInParent());
-        assertTrue(task1.mOnDisplayChangedCalled);
-    }
-}
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java
index 65e1835..3170f5a 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java
@@ -141,6 +141,13 @@
         }
     }
 
+    /** Creates an {@link AppWindowToken} and adds it to the specified {@link Task}. */
+    public static TestAppWindowToken createAppWindowTokenInTask(DisplayContent dc, Task task) {
+        final TestAppWindowToken newToken = createTestAppWindowToken(dc);
+        task.addChild(newToken, POSITION_TOP);
+        return newToken;
+    }
+
     /**
      * An extension of {@link TestTaskStack}, which overrides package scoped methods that would not
      * normally be mocked out.
@@ -264,9 +271,10 @@
 
         TestTask(int taskId, TaskStack stack, int userId, WindowManagerService service,
                 int resizeMode, boolean supportsPictureInPicture,
-                TaskWindowContainerController controller) {
+                TaskRecord taskRecord) {
             super(taskId, stack, userId, service, resizeMode, supportsPictureInPicture,
-                    new ActivityManager.TaskDescription(), controller);
+                    new ActivityManager.TaskDescription(), taskRecord);
+            stack.addTask(this, POSITION_TOP);
         }
 
         boolean shouldDeferRemoval() {
@@ -293,49 +301,10 @@
         }
     }
 
-    /**
-     * Used so we can gain access to some protected members of {@link TaskWindowContainerController}
-     * class.
-     */
-    public static class TestTaskWindowContainerController extends TaskWindowContainerController {
-
-        static final TaskWindowContainerListener NOP_LISTENER = new TaskWindowContainerListener() {
-            @Override
-            public void registerConfigurationChangeListener(
-                    ConfigurationContainerListener listener) {
-            }
-
-            @Override
-            public void unregisterConfigurationChangeListener(
-                    ConfigurationContainerListener listener) {
-            }
-
-            @Override
-            public void onSnapshotChanged(ActivityManager.TaskSnapshot snapshot) {
-            }
-
-            @Override
-            public void requestResize(Rect bounds, int resizeMode) {
-            }
-        };
-
-        TestTaskWindowContainerController(WindowTestsBase testsBase) {
-            this(testsBase.createStackControllerOnDisplay(testsBase.mDisplayContent));
-        }
-
-        TestTaskWindowContainerController(StackWindowController stackController) {
-            super(sNextTaskId++, NOP_LISTENER, stackController, 0 /* userId */, null /* bounds */,
-                    RESIZE_MODE_UNRESIZEABLE, false /* supportsPictureInPicture */, true /* toTop*/,
-                    true /* showForAllUsers */, new ActivityManager.TaskDescription(),
-                    stackController.mService);
-        }
-
-        @Override
-        TestTask createTask(int taskId, TaskStack stack, int userId, int resizeMode,
-                boolean supportsPictureInPicture, ActivityManager.TaskDescription taskDescription) {
-            return new TestTask(taskId, stack, userId, mService, resizeMode,
-                    supportsPictureInPicture, this);
-        }
+    public static TestTask createTestTask(StackWindowController stackWindowController) {
+        return new TestTask(sNextTaskId++, stackWindowController.mContainer, 0,
+                stackWindowController.mService, RESIZE_MODE_UNRESIZEABLE, false,
+                mock(TaskRecord.class));
     }
 
     public static class TestIApplicationToken implements IApplicationToken {