Unify Display level of window hierarchy (74/n)

Bug: 80414790
Bug: 144775502
Test: Existing tests pass
Change-Id: I041a64d001e09761b6c72dcc5acd3b6ca5b287c8
diff --git a/core/proto/android/server/activitymanagerservice.proto b/core/proto/android/server/activitymanagerservice.proto
index ce2717b..9f31b59 100644
--- a/core/proto/android/server/activitymanagerservice.proto
+++ b/core/proto/android/server/activitymanagerservice.proto
@@ -77,12 +77,14 @@
 message ActivityDisplayProto {
     option (.android.msg_privacy).dest = DEST_AUTOMATIC;
 
-    optional .com.android.server.wm.ConfigurationContainerProto configuration_container = 1;
+    // To be removed soon.
+    optional .com.android.server.wm.ConfigurationContainerProto configuration_container = 1 [deprecated=true];
     optional int32 id = 2;
     repeated ActivityStackProto stacks = 3;
     optional int32 focused_stack_id = 4;
     optional .com.android.server.wm.IdentifierProto resumed_activity = 5;
     optional bool single_task_instance = 6;
+    optional .com.android.server.wm.DisplayContentProto display = 7;
 }
 
 message ActivityStackProto {
diff --git a/services/core/java/com/android/server/wm/ActivityDisplay.java b/services/core/java/com/android/server/wm/ActivityDisplay.java
index db94cf1..9599bad 100644
--- a/services/core/java/com/android/server/wm/ActivityDisplay.java
+++ b/services/core/java/com/android/server/wm/ActivityDisplay.java
@@ -17,8 +17,6 @@
 package com.android.server.wm;
 
 import static android.app.ActivityTaskManager.INVALID_STACK_ID;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
 import static android.app.WindowConfiguration.ROTATION_UNDEFINED;
@@ -34,7 +32,7 @@
 import static android.view.Display.FLAG_PRIVATE;
 import static android.view.Display.REMOVE_MODE_DESTROY_CONTENT;
 
-import static com.android.server.am.ActivityDisplayProto.CONFIGURATION_CONTAINER;
+import static com.android.server.am.ActivityDisplayProto.DISPLAY;
 import static com.android.server.am.ActivityDisplayProto.FOCUSED_STACK_ID;
 import static com.android.server.am.ActivityDisplayProto.ID;
 import static com.android.server.am.ActivityDisplayProto.RESUMED_ACTIVITY;
@@ -52,6 +50,7 @@
 import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT;
 import static com.android.server.wm.RootActivityContainer.FindTaskResult;
 import static com.android.server.wm.RootActivityContainer.TAG_STATES;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DISPLAY;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
 import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
 
@@ -85,23 +84,19 @@
  * Exactly one of these classes per Display in the system. Capable of holding zero or more
  * attached {@link ActivityStack}s.
  */
-class ActivityDisplay extends ConfigurationContainer<ActivityStack> {
+class ActivityDisplay extends DisplayContent {
     private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityDisplay" : TAG_ATM;
     private static final String TAG_STACK = TAG + POSTFIX_STACK;
 
     static final int POSITION_TOP = Integer.MAX_VALUE;
     static final int POSITION_BOTTOM = Integer.MIN_VALUE;
 
-
     /**
      * Counter for next free stack ID to use for dynamic activity stacks. Unique across displays.
      */
     private static int sNextFreeStackId = 0;
 
-    private ActivityTaskManagerService mService;
     private RootActivityContainer mRootActivityContainer;
-    // TODO: Remove once unification is complete.
-    DisplayContent mDisplayContent;
     /** Actual Display this object tracks. */
     int mDisplayId;
     Display mDisplay;
@@ -111,7 +106,6 @@
      * stacks, bottommost behind. Accessed directly by ActivityManager package classes. Any calls
      * changing the list should also call {@link #onStackOrderChanged()}.
      */
-    private final ArrayList<ActivityStack> mStacks = new ArrayList<>();
     private ArrayList<OnStackOrderChangedListener> mStackOrderChangedCallbacks = new ArrayList<>();
 
     /** Array of all UIDs that are present on the display. */
@@ -157,13 +151,6 @@
      */
     private ActivityStack mLastFocusedStack;
 
-    // Cached reference to some special stacks we tend to get a lot so we don't need to loop
-    // through the list to find them.
-    private ActivityStack mHomeStack = null;
-    private ActivityStack mRecentsStack = null;
-    private ActivityStack mPinnedStack = null;
-    private ActivityStack mSplitScreenPrimaryStack = null;
-
     // Used in updating the display size
     private Point mTmpDisplaySize = new Point();
 
@@ -173,15 +160,24 @@
     private final FindTaskResult mTmpFindTaskResult = new FindTaskResult();
 
     ActivityDisplay(RootActivityContainer root, Display display) {
+        super(display, root.mWindowManager);
         mRootActivityContainer = root;
-        mService = root.mService;
         mDisplayId = display.getDisplayId();
         mDisplay = display;
-        mDisplayContent = mService.mWindowManager.mRoot.createDisplayContent(mDisplay, this);
-        mDisplayContent.reconfigureDisplayLocked();
-        onRequestedOverrideConfigurationChanged(
-                mDisplayContent.getRequestedOverrideConfiguration());
-        mService.mWindowManager.mDisplayNotificationController.dispatchDisplayAdded(this);
+
+        if (DEBUG_DISPLAY) Slog.v(TAG_WM, "Adding display=" + display);
+
+        mWmService.mDisplayWindowSettings.applySettingsToDisplayLocked(this);
+
+        if (mWmService.mDisplayManagerInternal != null) {
+            mWmService.mDisplayManagerInternal
+                .setDisplayInfoOverrideFromWindowManager(mDisplayId, getDisplayInfo());
+            configureDisplayPolicy();
+        }
+
+        reconfigureDisplayLocked();
+        onRequestedOverrideConfigurationChanged(getRequestedOverrideConfiguration());
+        mWmService.mDisplayNotificationController.dispatchDisplayAdded(this);
     }
 
     void onDisplayChanged() {
@@ -190,7 +186,7 @@
         if (displayId != DEFAULT_DISPLAY) {
             final int displayState = mDisplay.getState();
             if (displayState == Display.STATE_OFF && mOffToken == null) {
-                mOffToken = mService.acquireSleepToken("Display-off", displayId);
+                mOffToken = mAtmService.acquireSleepToken("Display-off", displayId);
             } else if (displayState == Display.STATE_ON && mOffToken != null) {
                 mOffToken.release();
                 mOffToken = null;
@@ -199,98 +195,72 @@
 
         mDisplay.getRealSize(mTmpDisplaySize);
         setBounds(0, 0, mTmpDisplaySize.x, mTmpDisplaySize.y);
-        if (mDisplayContent != null) {
-            mDisplayContent.updateDisplayInfo();
-            mService.mWindowManager.requestTraversal();
-        }
+        updateDisplayInfo();
+        mWmService.requestTraversal();
     }
 
-    // TODO(display-unify): Merge with addChild below.
-    void addChild(ActivityStack stack, int position) {
-        addChild(stack, position, false /*fromDc*/);
+    void addStack(ActivityStack stack, int position) {
+        setStackOnDisplay(stack, position);
+        positionStackAt(stack, position);
+        mAtmService.updateSleepIfNeededLocked();
     }
 
-    void addChild(ActivityStack stack, int position, boolean fromDc) {
-        boolean toTop = position == POSITION_TOP;
-        if (position == POSITION_BOTTOM) {
-            position = 0;
-        } else if (toTop) {
-            position = getChildCount();
+    void onStackRemoved(ActivityStack stack) {
+        if (DEBUG_STACK) {
+            Slog.v(TAG_STACK, "removeStack: detaching " + stack + " from displayId=" + mDisplayId);
         }
-        if (DEBUG_STACK) Slog.v(TAG_STACK, "addChild: attaching " + stack
-                + " to displayId=" + mDisplayId + " position=" + position);
-        addStackReferenceIfNeeded(stack);
-        if (!fromDc) {
-            mDisplayContent.setStackOnDisplay(stack, position);
-        }
-        positionChildAt(stack, position);
-        mService.updateSleepIfNeededLocked();
-    }
-
-    // TODO(display-unify): Merge with removeChild below.
-    void onChildRemoved(ActivityStack stack) {
-        if (!mStacks.remove(stack)) {
-            // Stack no longer here!
-            return;
-        }
-
-        if (DEBUG_STACK) Slog.v(TAG_STACK, "removeChild: detaching " + stack
-                + " from displayId=" + mDisplayId);
         if (mPreferredTopFocusableStack == stack) {
             mPreferredTopFocusableStack = null;
         }
-        removeStackReferenceIfNeeded(stack);
         releaseSelfIfNeeded();
-        mService.updateSleepIfNeededLocked();
+        mAtmService.updateSleepIfNeededLocked();
         onStackOrderChanged(stack);
     }
 
-    void removeChild(ActivityStack stack) {
-        mDisplayContent.removeStackFromDisplay(stack);
+    void positionStackAtTop(ActivityStack stack, boolean includingParents) {
+        positionStackAtTop(stack, includingParents, null /* updateLastFocusedStackReason */);
     }
 
-    void positionChildAtTop(ActivityStack stack, boolean includingParents) {
-        positionChildAtTop(stack, includingParents, null /* updateLastFocusedStackReason */);
-    }
-
-    void positionChildAtTop(ActivityStack stack, boolean includingParents,
+    void positionStackAtTop(ActivityStack stack, boolean includingParents,
             String updateLastFocusedStackReason) {
-        positionChildAt(stack, getChildCount(), includingParents, updateLastFocusedStackReason);
+        positionStackAt(stack, getStackCount(), includingParents, updateLastFocusedStackReason);
     }
 
-    void positionChildAtBottom(ActivityStack stack) {
-        positionChildAtBottom(stack, null /* updateLastFocusedStackReason */);
+    void positionStackAtBottom(ActivityStack stack) {
+        positionStackAtBottom(stack, null /* updateLastFocusedStackReason */);
     }
 
-    void positionChildAtBottom(ActivityStack stack, String updateLastFocusedStackReason) {
-        positionChildAt(stack, 0, false /* includingParents */, updateLastFocusedStackReason);
+    void positionStackAtBottom(ActivityStack stack, String updateLastFocusedStackReason) {
+        positionStackAt(stack, 0, false /* includingParents */, updateLastFocusedStackReason);
     }
 
-    private void positionChildAt(ActivityStack stack, int position) {
-        positionChildAt(stack, position, false /* includingParents */,
+    private void positionStackAt(ActivityStack stack, int position) {
+        positionStackAt(stack, position, false /* includingParents */,
                 null /* updateLastFocusedStackReason */);
     }
 
-    private void positionChildAt(ActivityStack stack, int position, boolean includingParents,
+    private void positionStackAt(ActivityStack stack, int position, boolean includingParents,
             String updateLastFocusedStackReason) {
         // TODO: Keep in sync with WindowContainer.positionChildAt(), once we change that to adjust
         //       the position internally, also update the logic here
         final ActivityStack prevFocusedStack = updateLastFocusedStackReason != null
                 ? getFocusedStack() : null;
-        final boolean wasContained = mStacks.remove(stack);
-        if (mSingleTaskInstance && getChildCount() > 0) {
+        final boolean wasContained = getIndexOf(stack) >= 0;
+        if (mSingleTaskInstance && getStackCount() == 1 && !wasContained) {
             throw new IllegalStateException(
-                    "positionChildAt: Can only have one child on display=" + this);
+                    "positionStackAt: Can only have one task on display=" + this);
         }
-        final int insertPosition = getTopInsertPosition(stack, position);
-        mStacks.add(insertPosition, stack);
+
+        // Since positionChildAt() is called during the creation process of pinned stacks,
+        // ActivityStack#getStack() can be null.
+        positionStackAt(position, stack, includingParents);
 
         // The insert position may be adjusted to non-top when there is always-on-top stack. Since
         // the original position is preferred to be top, the stack should have higher priority when
         // we are looking for top focusable stack. The condition {@code wasContained} restricts the
         // preferred stack is set only when moving an existing stack to top instead of adding a new
         // stack that may be too early (e.g. in the middle of launching or reparenting).
-        if (wasContained && position >= getChildCount() - 1 && stack.isFocusableAndVisible()) {
+        if (wasContained && position >= getStackCount() - 1 && stack.isFocusableAndVisible()) {
             mPreferredTopFocusableStack = stack;
         } else if (mPreferredTopFocusableStack == stack) {
             mPreferredTopFocusableStack = null;
@@ -307,67 +277,14 @@
             }
         }
 
-        // Since positionChildAt() is called during the creation process of pinned stacks,
-        // ActivityStack#getStack() can be null.
-        if (mDisplayContent != null) {
-            mDisplayContent.positionStackAt(insertPosition, stack, includingParents);
-        }
         onStackOrderChanged(stack);
     }
 
-    private int getTopInsertPosition(ActivityStack stack, int candidatePosition) {
-        int position = getChildCount();
-        if (stack.inPinnedWindowingMode()) {
-            // Stack in pinned windowing mode is z-ordered on-top of all other stacks so okay to
-            // just return the candidate position.
-            return Math.min(position, candidatePosition);
-        }
-        while (position > 0) {
-            final ActivityStack targetStack = getChildAt(position - 1);
-            if (!targetStack.isAlwaysOnTop()) {
-                // We reached a stack that isn't always-on-top.
-                break;
-            }
-            if (stack.isAlwaysOnTop() && !targetStack.inPinnedWindowingMode()) {
-                // Always on-top non-pinned windowing mode stacks can go anywhere below pinned stack.
-                break;
-            }
-            position--;
-        }
-        return Math.min(position, candidatePosition);
-    }
-
-    <T extends ActivityStack> T getStack(int stackId) {
-        for (int i = getChildCount() - 1; i >= 0; --i) {
-            final ActivityStack stack = getChildAt(i);
+    ActivityStack getStack(int stackId) {
+        for (int i = getStackCount() - 1; i >= 0; --i) {
+            final ActivityStack stack = getStackAt(i);
             if (stack.mStackId == stackId) {
-                return (T) stack;
-            }
-        }
-        return null;
-    }
-
-    /**
-     * @return the topmost stack on the display that is compatible with the input windowing mode and
-     * activity type. {@code null} means no compatible stack on the display.
-     * @see ConfigurationContainer#isCompatible(int, int)
-     */
-    <T extends ActivityStack> T getStack(int windowingMode, int activityType) {
-        if (activityType == ACTIVITY_TYPE_HOME) {
-            return (T) mHomeStack;
-        } else if (activityType == ACTIVITY_TYPE_RECENTS) {
-            return (T) mRecentsStack;
-        }
-        if (windowingMode == WINDOWING_MODE_PINNED) {
-            return (T) mPinnedStack;
-        } else if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
-            return (T) mSplitScreenPrimaryStack;
-        }
-
-        for (int i = getChildCount() - 1; i >= 0; --i) {
-            final ActivityStack stack = getChildAt(i);
-            if (stack.isCompatible(windowingMode, activityType)) {
-                return (T) stack;
+                return stack;
             }
         }
         return null;
@@ -388,10 +305,10 @@
      * @see #getStack(int, int)
      * @see #createStack(int, int, boolean)
      */
-    <T extends ActivityStack> T getOrCreateStack(int windowingMode, int activityType,
+    ActivityStack getOrCreateStack(int windowingMode, int activityType,
             boolean onTop) {
         if (!alwaysCreateStack(windowingMode, activityType)) {
-            T stack = getStack(windowingMode, activityType);
+            ActivityStack stack = getStack(windowingMode, activityType);
             if (stack != null) {
                 return stack;
             }
@@ -404,7 +321,7 @@
      * if a compatible stack doesn't exist.
      * @see #getOrCreateStack(int, int, boolean)
      */
-    <T extends ActivityStack> T getOrCreateStack(@Nullable ActivityRecord r,
+    ActivityStack getOrCreateStack(@Nullable ActivityRecord r,
             @Nullable ActivityOptions options, @Nullable Task candidateTask, int activityType,
             boolean onTop) {
         // First preference is the windowing mode in the activity options if set.
@@ -433,9 +350,9 @@
      * @param onTop If true the stack will be created at the top of the display, else at the bottom.
      * @return The newly created stack.
      */
-    <T extends ActivityStack> T createStack(int windowingMode, int activityType, boolean onTop) {
+    ActivityStack createStack(int windowingMode, int activityType, boolean onTop) {
 
-        if (mSingleTaskInstance && getChildCount() > 0) {
+        if (mSingleTaskInstance && getStackCount() > 0) {
             // Create stack on default display instead since this display can only contain 1 stack.
             // TODO: Kinda a hack, but better that having the decision at each call point. Hoping
             // this goes away once ActivityView is no longer using virtual displays.
@@ -452,17 +369,17 @@
         if (activityType != ACTIVITY_TYPE_STANDARD) {
             // For now there can be only one stack of a particular non-standard activity type on a
             // display. So, get that ignoring whatever windowing mode it is currently in.
-            T stack = getStack(WINDOWING_MODE_UNDEFINED, activityType);
+            ActivityStack stack = getStack(WINDOWING_MODE_UNDEFINED, activityType);
             if (stack != null) {
                 throw new IllegalArgumentException("Stack=" + stack + " of activityType="
                         + activityType + " already on display=" + this + ". Can't have multiple.");
             }
         }
 
-        if (!isWindowingModeSupported(windowingMode, mService.mSupportsMultiWindow,
-                mService.mSupportsSplitScreenMultiWindow,
-                mService.mSupportsFreeformWindowManagement, mService.mSupportsPictureInPicture,
-                activityType)) {
+        if (!isWindowingModeSupported(windowingMode, mAtmService.mSupportsMultiWindow,
+                mAtmService.mSupportsSplitScreenMultiWindow,
+                mAtmService.mSupportsFreeformWindowManagement,
+                mAtmService.mSupportsPictureInPicture, activityType)) {
             throw new IllegalArgumentException("Can't create stack for unsupported windowingMode="
                     + windowingMode);
         }
@@ -472,13 +389,13 @@
     }
 
     @VisibleForTesting
-    <T extends ActivityStack> T createStackUnchecked(int windowingMode, int activityType,
+    ActivityStack createStackUnchecked(int windowingMode, int activityType,
             int stackId, boolean onTop) {
         if (windowingMode == WINDOWING_MODE_PINNED && activityType != ACTIVITY_TYPE_STANDARD) {
             throw new IllegalArgumentException("Stack with windowing mode cannot with non standard "
                     + "activity type.");
         }
-        return (T) new ActivityStack(this, stackId,
+        return new ActivityStack(this, stackId,
                 mRootActivityContainer.mStackSupervisor, windowingMode, activityType, onTop);
     }
 
@@ -491,8 +408,8 @@
             return mPreferredTopFocusableStack;
         }
 
-        for (int i = getChildCount() - 1; i >= 0; --i) {
-            final ActivityStack stack = getChildAt(i);
+        for (int i = getStackCount() - 1; i >= 0; --i) {
+            final ActivityStack stack = getStackAt(i);
             if (stack.isFocusableAndVisible()) {
                 return stack;
             }
@@ -506,8 +423,8 @@
                 ? currentFocus.getWindowingMode() : WINDOWING_MODE_UNDEFINED;
 
         ActivityStack candidate = null;
-        for (int i = getChildCount() - 1; i >= 0; --i) {
-            final ActivityStack stack = getChildAt(i);
+        for (int i = getStackCount() - 1; i >= 0; --i) {
+            final ActivityStack stack = getStackAt(i);
             if (ignoreCurrent && stack == currentFocus) {
                 continue;
             }
@@ -562,8 +479,8 @@
     }
 
     boolean allResumedActivitiesComplete() {
-        for (int stackNdx = getChildCount() - 1; stackNdx >= 0; --stackNdx) {
-            final ActivityRecord r = getChildAt(stackNdx).getResumedActivity();
+        for (int stackNdx = getStackCount() - 1; stackNdx >= 0; --stackNdx) {
+            final ActivityRecord r = getStackAt(stackNdx).getResumedActivity();
             if (r != null && !r.isState(RESUMED)) {
                 return false;
             }
@@ -589,8 +506,8 @@
      */
     boolean pauseBackStacks(boolean userLeaving, ActivityRecord resuming) {
         boolean someActivityPaused = false;
-        for (int stackNdx = getChildCount() - 1; stackNdx >= 0; --stackNdx) {
-            final ActivityStack stack = getChildAt(stackNdx);
+        for (int stackNdx = getStackCount() - 1; stackNdx >= 0; --stackNdx) {
+            final ActivityStack stack = getStackAt(stackNdx);
             final ActivityRecord resumedActivity = stack.getResumedActivity();
             if (resumedActivity != null
                     && (stack.getVisibility(resuming) != STACK_VISIBILITY_VISIBLE
@@ -610,8 +527,8 @@
     void findTaskLocked(final ActivityRecord r, final boolean isPreferredDisplay,
             FindTaskResult result) {
         mTmpFindTaskResult.clear();
-        for (int stackNdx = getChildCount() - 1; stackNdx >= 0; --stackNdx) {
-            final ActivityStack stack = getChildAt(stackNdx);
+        for (int stackNdx = getStackCount() - 1; stackNdx >= 0; --stackNdx) {
+            final ActivityStack stack = getStackAt(stackNdx);
             if (!r.hasCompatibleActivityType(stack)) {
                 if (DEBUG_TASKS) {
                     Slog.d(TAG_TASKS, "Skipping stack: (mismatch activity/stack) " + stack);
@@ -654,8 +571,8 @@
         final ArrayList<ActivityStack> stacks = new ArrayList<>();
         for (int j = windowingModes.length - 1 ; j >= 0; --j) {
             final int windowingMode = windowingModes[j];
-            for (int i = getChildCount() - 1; i >= 0; --i) {
-                final ActivityStack stack = getChildAt(i);
+            for (int i = getStackCount() - 1; i >= 0; --i) {
+                final ActivityStack stack = getStackAt(i);
                 if (!stack.isActivityTypeStandardOrUndefined()) {
                     continue;
                 }
@@ -682,8 +599,8 @@
         final ArrayList<ActivityStack> stacks = new ArrayList<>();
         for (int j = activityTypes.length - 1 ; j >= 0; --j) {
             final int activityType = activityTypes[j];
-            for (int i = getChildCount() - 1; i >= 0; --i) {
-                final ActivityStack stack = getChildAt(i);
+            for (int i = getStackCount() - 1; i >= 0; --i) {
+                final ActivityStack stack = getStackAt(i);
                 if (stack.getActivityType() == activityType) {
                     stacks.add(stack);
                 }
@@ -695,67 +612,12 @@
         }
     }
 
-    void onStackWindowingModeChanged(ActivityStack stack) {
-        removeStackReferenceIfNeeded(stack);
-        addStackReferenceIfNeeded(stack);
-    }
-
-    private void addStackReferenceIfNeeded(ActivityStack stack) {
-        final int activityType = stack.getActivityType();
-        final int windowingMode = stack.getWindowingMode();
-
-        if (activityType == ACTIVITY_TYPE_HOME) {
-            if (mHomeStack != null && mHomeStack != stack) {
-                throw new IllegalArgumentException("addStackReferenceIfNeeded: home stack="
-                        + mHomeStack + " already exist on display=" + this + " stack=" + stack);
-            }
-            mHomeStack = stack;
-        } else if (activityType == ACTIVITY_TYPE_RECENTS) {
-            if (mRecentsStack != null && mRecentsStack != stack) {
-                throw new IllegalArgumentException("addStackReferenceIfNeeded: recents stack="
-                        + mRecentsStack + " already exist on display=" + this + " stack=" + stack);
-            }
-            mRecentsStack = stack;
-        }
-        if (windowingMode == WINDOWING_MODE_PINNED) {
-            if (mPinnedStack != null && mPinnedStack != stack) {
-                throw new IllegalArgumentException("addStackReferenceIfNeeded: pinned stack="
-                        + mPinnedStack + " already exist on display=" + this
-                        + " stack=" + stack);
-            }
-            mPinnedStack = stack;
-        } else if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
-            if (mSplitScreenPrimaryStack != null && mSplitScreenPrimaryStack != stack) {
-                throw new IllegalArgumentException("addStackReferenceIfNeeded:"
-                        + " split-screen-primary" + " stack=" + mSplitScreenPrimaryStack
-                        + " already exist on display=" + this + " stack=" + stack);
-            }
-            mSplitScreenPrimaryStack = stack;
-            onSplitScreenModeActivated();
-        }
-    }
-
-    private void removeStackReferenceIfNeeded(ActivityStack stack) {
-        if (stack == mHomeStack) {
-            mHomeStack = null;
-        } else if (stack == mRecentsStack) {
-            mRecentsStack = null;
-        } else if (stack == mPinnedStack) {
-            mPinnedStack = null;
-        } else if (stack == mSplitScreenPrimaryStack) {
-            mSplitScreenPrimaryStack = null;
-            // Inform the reset of the system that split-screen mode was dismissed so things like
-            // resizing all the other stacks can take place.
-            onSplitScreenModeDismissed();
-        }
-    }
-
-    private void onSplitScreenModeDismissed() {
-        mService.deferWindowLayout();
+    void onSplitScreenModeDismissed() {
+        mAtmService.deferWindowLayout();
         try {
             // Adjust the windowing mode of any stack in secondary split-screen to fullscreen.
-            for (int i = getChildCount() - 1; i >= 0; --i) {
-                final ActivityStack otherStack = getChildAt(i);
+            for (int i = getStackCount() - 1; i >= 0; --i) {
+                final ActivityStack otherStack = getStackAt(i);
                 if (!otherStack.inSplitScreenSecondaryWindowingMode()) {
                     continue;
                 }
@@ -766,26 +628,28 @@
         } finally {
             final ActivityStack topFullscreenStack =
                     getTopStackInWindowingMode(WINDOWING_MODE_FULLSCREEN);
-            if (topFullscreenStack != null && mHomeStack != null && !isTopStack(mHomeStack)) {
+            final ActivityStack homeStack = getHomeStack();
+            if (topFullscreenStack != null && homeStack != null && !isTopStack(homeStack)) {
                 // Whenever split-screen is dismissed we want the home stack directly behind the
                 // current top fullscreen stack so it shows up when the top stack is finished.
                 // TODO: Would be better to use ActivityDisplay.positionChildAt() for this, however
                 // ActivityDisplay doesn't have a direct controller to WM side yet. We can switch
                 // once we have that.
-                mHomeStack.moveToFront("onSplitScreenModeDismissed");
+                homeStack.moveToFront("onSplitScreenModeDismissed");
                 topFullscreenStack.moveToFront("onSplitScreenModeDismissed");
             }
-            mService.continueWindowLayout();
+            mAtmService.continueWindowLayout();
         }
     }
 
-    private void onSplitScreenModeActivated() {
-        mService.deferWindowLayout();
+    void onSplitScreenModeActivated() {
+        mAtmService.deferWindowLayout();
         try {
             // Adjust the windowing mode of any affected by split-screen to split-screen secondary.
-            for (int i = getChildCount() - 1; i >= 0; --i) {
-                final ActivityStack otherStack = getChildAt(i);
-                if (otherStack == mSplitScreenPrimaryStack
+            final ActivityStack splitScreenPrimaryStack = getSplitScreenPrimaryStack();
+            for (int i = getStackCount() - 1; i >= 0; --i) {
+                final ActivityStack otherStack = getStackAt(i);
+                if (otherStack == splitScreenPrimaryStack
                         || !otherStack.affectedBySplitScreenResize()) {
                     continue;
                 }
@@ -795,7 +659,7 @@
                         false /* creating */);
             }
         } finally {
-            mService.continueWindowLayout();
+            mAtmService.continueWindowLayout();
         }
     }
 
@@ -890,10 +754,10 @@
     int validateWindowingMode(int windowingMode, @Nullable ActivityRecord r, @Nullable Task task,
             int activityType) {
         // Make sure the windowing mode we are trying to use makes sense for what is supported.
-        boolean supportsMultiWindow = mService.mSupportsMultiWindow;
-        boolean supportsSplitScreen = mService.mSupportsSplitScreenMultiWindow;
-        boolean supportsFreeform = mService.mSupportsFreeformWindowManagement;
-        boolean supportsPip = mService.mSupportsPictureInPicture;
+        boolean supportsMultiWindow = mAtmService.mSupportsMultiWindow;
+        boolean supportsSplitScreen = mAtmService.mSupportsSplitScreenMultiWindow;
+        boolean supportsFreeform = mAtmService.mSupportsFreeformWindowManagement;
+        boolean supportsPip = mAtmService.mSupportsPictureInPicture;
         if (supportsMultiWindow) {
             if (task != null) {
                 supportsMultiWindow = task.isResizeable();
@@ -927,21 +791,13 @@
         return WINDOWING_MODE_UNDEFINED;
     }
 
-    /**
-     * Get the topmost stack on the display. It may be different from focused stack, because
-     * some stacks are not focusable (e.g. PiP).
-     */
-    ActivityStack getTopStack() {
-        return mStacks.isEmpty() ? null : getChildAt(getChildCount() - 1);
-    }
-
     boolean isTopStack(ActivityStack stack) {
         return stack == getTopStack();
     }
 
     boolean isTopNotPinnedStack(ActivityStack stack) {
-        for (int i = getChildCount() - 1; i >= 0; --i) {
-            final ActivityStack current = getChildAt(i);
+        for (int i = getStackCount() - 1; i >= 0; --i) {
+            final ActivityStack current = getStackAt(i);
             if (!current.inPinnedWindowingMode()) {
                 return current == stack;
             }
@@ -950,8 +806,8 @@
     }
 
     ActivityStack getTopStackInWindowingMode(int windowingMode) {
-        for (int i = getChildCount() - 1; i >= 0; --i) {
-            final ActivityStack current = getChildAt(i);
+        for (int i = getStackCount() - 1; i >= 0; --i) {
+            final ActivityStack current = getStackAt(i);
             if (windowingMode == current.getWindowingMode()) {
                 return current;
             }
@@ -981,8 +837,8 @@
 
         // Look in other focusable stacks.
         if (topRunning == null) {
-            for (int i = getChildCount() - 1; i >= 0; --i) {
-                final ActivityStack stack = getChildAt(i);
+            for (int i = getStackCount() - 1; i >= 0; --i) {
+                final ActivityStack stack = getStackAt(i);
                 // Only consider focusable stacks other than the current focused one.
                 if (stack == focusedStack || !stack.isFocusable()) {
                     continue;
@@ -1005,22 +861,18 @@
         return topRunning;
     }
 
-    int getIndexOf(ActivityStack stack) {
-        return mStacks.indexOf(stack);
-    }
-
     boolean updateDisplayOverrideConfigurationLocked() {
         Configuration values = new Configuration();
-        mDisplayContent.computeScreenConfiguration(values);
+        computeScreenConfiguration(values);
 
-        mService.mH.sendMessage(PooledLambda.obtainMessage(
-                ActivityManagerInternal::updateOomLevelsForDisplay, mService.mAmInternal,
+        mAtmService.mH.sendMessage(PooledLambda.obtainMessage(
+                ActivityManagerInternal::updateOomLevelsForDisplay, mAtmService.mAmInternal,
                 mDisplayId));
 
         Settings.System.clearConfiguration(values);
         updateDisplayOverrideConfigurationLocked(values, null /* starting */,
-                false /* deferResume */, mService.mTmpUpdateConfigurationResult);
-        return mService.mTmpUpdateConfigurationResult.changes != 0;
+                false /* deferResume */, mAtmService.mTmpUpdateConfigurationResult);
+        return mAtmService.mTmpUpdateConfigurationResult.changes != 0;
     }
 
     /**
@@ -1034,14 +886,14 @@
         int changes = 0;
         boolean kept = true;
 
-        mService.deferWindowLayout();
+        mAtmService.deferWindowLayout();
         try {
             if (values != null) {
                 if (mDisplayId == DEFAULT_DISPLAY) {
                     // Override configuration of the default display duplicates global config, so
                     // we're calling global config update instead for default display. It will also
                     // apply the correct override config.
-                    changes = mService.updateGlobalConfigurationLocked(values,
+                    changes = mAtmService.updateGlobalConfigurationLocked(values,
                             false /* initLocale */, false /* persistent */,
                             UserHandle.USER_NULL /* userId */, deferResume);
                 } else {
@@ -1049,9 +901,9 @@
                 }
             }
 
-            kept = mService.ensureConfigAndVisibilityAfterUpdate(starting, changes);
+            kept = mAtmService.ensureConfigAndVisibilityAfterUpdate(starting, changes);
         } finally {
-            mService.continueWindowLayout();
+            mAtmService.continueWindowLayout();
         }
 
         if (result != null) {
@@ -1071,17 +923,17 @@
 
             final boolean isDensityChange = (changes & ActivityInfo.CONFIG_DENSITY) != 0;
             if (isDensityChange && mDisplayId == DEFAULT_DISPLAY) {
-                mService.mAppWarnings.onDensityChanged();
+                mAtmService.mAppWarnings.onDensityChanged();
 
                 // Post message to start process to avoid possible deadlock of calling into AMS with
                 // the ATMS lock held.
                 final Message msg = PooledLambda.obtainMessage(
                         ActivityManagerInternal::killAllBackgroundProcessesExcept,
-                        mService.mAmInternal, N,
+                        mAtmService.mAmInternal, N,
                         ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND);
-                mService.mH.sendMessage(msg);
+                mAtmService.mH.sendMessage(msg);
             }
-            mService.mWindowManager.mDisplayNotificationController.dispatchDisplayChanged(
+            mWmService.mDisplayNotificationController.dispatchDisplayChanged(
                     this, getConfiguration());
         }
         return changes;
@@ -1092,43 +944,29 @@
         final int currRotation =
                 getRequestedOverrideConfiguration().windowConfiguration.getRotation();
         if (currRotation != ROTATION_UNDEFINED
-                && currRotation != overrideConfiguration.windowConfiguration.getRotation()
-                && mDisplayContent != null) {
-            mDisplayContent.applyRotationLocked(currRotation,
+                && currRotation != overrideConfiguration.windowConfiguration.getRotation()) {
+            applyRotationLocked(currRotation,
                     overrideConfiguration.windowConfiguration.getRotation());
         }
         super.onRequestedOverrideConfigurationChanged(overrideConfiguration);
-        if (mDisplayContent != null) {
-            mService.mWindowManager.setNewDisplayOverrideConfiguration(
-                    overrideConfiguration, mDisplayContent);
-        }
-        mService.addWindowLayoutReasons(
+        mWmService.setNewDisplayOverrideConfiguration(overrideConfiguration, this);
+        mAtmService.addWindowLayoutReasons(
                 ActivityTaskManagerService.LAYOUT_REASON_CONFIG_CHANGED);
     }
 
     @Override
     public void onConfigurationChanged(Configuration newParentConfig) {
         // update resources before cascade so that docked/pinned stacks use the correct info
-        if (mDisplayContent != null) {
-            mDisplayContent.preOnConfigurationChanged();
-        }
+        preOnConfigurationChanged();
         super.onConfigurationChanged(newParentConfig);
     }
 
     void onLockTaskPackagesUpdated() {
-        for (int i = getChildCount() - 1; i >= 0; --i) {
-            getChildAt(i).onLockTaskPackagesUpdated();
+        for (int i = getStackCount() - 1; i >= 0; --i) {
+            getStackAt(i).onLockTaskPackagesUpdated();
         }
     }
 
-    /** We are in the process of exiting split-screen mode. */
-    void onExitingSplitScreenMode() {
-        // Remove reference to the primary-split-screen stack so it no longer has any effect on the
-        // display. For example, we want to be able to create fullscreen stack for standard activity
-        // types when exiting split-screen mode.
-        mSplitScreenPrimaryStack = null;
-    }
-
     /** Checks whether the given activity is in size compatibility mode and notifies the change. */
     void handleActivitySizeCompatModeIfNeeded(ActivityRecord r) {
         if (!r.isState(RESUMED) || r.getWindowingMode() != WINDOWING_MODE_FULLSCREEN) {
@@ -1137,7 +975,7 @@
         }
         if (!r.inSizeCompatMode()) {
             if (mLastCompatModeActivity != null) {
-                mService.getTaskChangeNotificationController()
+                mAtmService.getTaskChangeNotificationController()
                         .notifySizeCompatModeActivityChanged(mDisplayId, null /* activityToken */);
             }
             mLastCompatModeActivity = null;
@@ -1147,44 +985,13 @@
             return;
         }
         mLastCompatModeActivity = r;
-        mService.getTaskChangeNotificationController()
+        mAtmService.getTaskChangeNotificationController()
                 .notifySizeCompatModeActivityChanged(mDisplayId, r.appToken);
     }
 
-    ActivityStack getSplitScreenPrimaryStack() {
-        return mSplitScreenPrimaryStack;
-    }
-
-    boolean hasSplitScreenPrimaryStack() {
-        return mSplitScreenPrimaryStack != null;
-    }
-
-    ActivityStack getPinnedStack() {
-        return mPinnedStack;
-    }
-
-    boolean hasPinnedStack() {
-        return mPinnedStack != null;
-    }
-
     @Override
     public String toString() {
-        return "ActivityDisplay={" + mDisplayId + " numStacks=" + getChildCount() + "}";
-    }
-
-    @Override
-    protected int getChildCount() {
-        return mStacks.size();
-    }
-
-    @Override
-    protected ActivityStack getChildAt(int index) {
-        return mStacks.get(index);
-    }
-
-    @Override
-    protected ConfigurationContainer getParent() {
-        return mRootActivityContainer;
+        return "ActivityDisplay={" + mDisplayId + " numStacks=" + getStackCount() + "}";
     }
 
     boolean isPrivate() {
@@ -1227,10 +1034,10 @@
         final ActivityDisplay toDisplay = mRootActivityContainer.getDefaultDisplay();
         mRootActivityContainer.mStackSupervisor.beginDeferResume();
         try {
-            int numStacks = getChildCount();
+            int numStacks = getStackCount();
             // Keep the order from bottom to top.
             for (int stackNdx = 0; stackNdx < numStacks; stackNdx++) {
-                final ActivityStack stack = getChildAt(stackNdx);
+                final ActivityStack stack = getStackAt(stackNdx);
                 // Always finish non-standard type stacks.
                 if (destroyContentOnRemoval || !stack.isActivityTypeStandardOrUndefined()) {
                     stack.finishAllActivitiesImmediately();
@@ -1241,14 +1048,14 @@
                     final int windowingMode = toDisplay.hasSplitScreenPrimaryStack()
                             ? WINDOWING_MODE_SPLIT_SCREEN_SECONDARY
                             : WINDOWING_MODE_UNDEFINED;
-                    stack.reparent(toDisplay.mDisplayContent, true /* onTop */);
+                    stack.reparent(toDisplay, true /* onTop */);
                     stack.setWindowingMode(windowingMode);
                     lastReparentedStack = stack;
                 }
                 // Stacks may be removed from this display. Ensure each stack will be processed and
                 // the loop will end.
-                stackNdx -= numStacks - getChildCount();
-                numStacks = getChildCount();
+                stackNdx -= numStacks - getStackCount();
+                numStacks = getStackCount();
             }
         } finally {
             mRootActivityContainer.mStackSupervisor.endDeferResume();
@@ -1265,24 +1072,23 @@
         if (!mAllSleepTokens.isEmpty()) {
             mRootActivityContainer.mSleepTokens.removeAll(mAllSleepTokens);
             mAllSleepTokens.clear();
-            mService.updateSleepIfNeededLocked();
+            mAtmService.updateSleepIfNeededLocked();
         }
     }
 
     private void releaseSelfIfNeeded() {
-        if (!mRemoved || mDisplayContent == null) {
+        if (!mRemoved) {
             return;
         }
 
-        final ActivityStack stack = getChildCount() == 1 ? getChildAt(0) : null;
+        final ActivityStack stack = getStackCount() == 1 ? getStackAt(0) : null;
         if (stack != null && stack.isActivityTypeHome() && stack.getAllTasks().isEmpty()) {
             // Release this display if an empty home stack is the only thing left.
             // Since it is the last stack, this display will be released along with the stack
             // removal.
             stack.removeIfPossible();
-        } else if (mStacks.isEmpty()) {
-            mDisplayContent.removeIfPossible();
-            mDisplayContent = null;
+        } else if (getTopStack() == null) {
+            removeIfPossible();
             mRootActivityContainer.removeChild(this);
             mRootActivityContainer.mStackSupervisor
                     .getKeyguardController().onDisplayRemoved(mDisplayId);
@@ -1302,14 +1108,6 @@
     private static void addActivityUid(ActivityRecord r, IntArray uids) {
         uids.add(r.getUid());
     }
-    /**
-     * Checks if system decorations should be shown on this display.
-     *
-     * @see Display#FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS
-     */
-    boolean supportsSystemDecorations() {
-        return mDisplayContent.supportsSystemDecorations();
-    }
 
     @VisibleForTesting
     boolean shouldDestroyContentOnRemove() {
@@ -1317,14 +1115,11 @@
     }
 
     boolean shouldSleep() {
-        return (mStacks.isEmpty() || !mAllSleepTokens.isEmpty())
-                && (mService.mRunningVoice == null);
+        return (getStackCount() == 0 || !mAllSleepTokens.isEmpty())
+                && (mAtmService.mRunningVoice == null);
     }
 
     void setFocusedApp(ActivityRecord r, boolean moveFocusNow) {
-        if (mDisplayContent == null) {
-            return;
-        }
         final ActivityRecord newFocus;
         final IBinder token = r.appToken;
         if (token == null) {
@@ -1332,7 +1127,7 @@
                     mDisplayId);
             newFocus = null;
         } else {
-            newFocus = mService.mWindowManager.mRoot.getActivityRecord(token);
+            newFocus = mWmService.mRoot.getActivityRecord(token);
             if (newFocus == null) {
                 Slog.w(TAG_WM, "Attempted to set focus to non-existing app token: " + token
                         + ", displayId=" + mDisplayId);
@@ -1342,9 +1137,9 @@
                             moveFocusNow, mDisplayId);
         }
 
-        final boolean changed = mDisplayContent.setFocusedApp(newFocus);
+        final boolean changed = setFocusedApp(newFocus);
         if (moveFocusNow && changed) {
-            mService.mWindowManager.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL,
+            mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL,
                     true /*updateInputWindows*/);
         }
     }
@@ -1354,8 +1149,8 @@
      *         already top-most.
      */
     ActivityStack getStackAbove(ActivityStack stack) {
-        final int stackIndex = mStacks.indexOf(stack) + 1;
-        return (stackIndex < getChildCount()) ? getChildAt(stackIndex) : null;
+        final int stackIndex = getIndexOf(stack) + 1;
+        return (stackIndex < getStackCount()) ? getStackAt(stackIndex) : null;
     }
 
     /**
@@ -1369,12 +1164,12 @@
         }
 
         // Move the stack to the bottom to not affect the following visibility checks
-        positionChildAtBottom(stack);
+        positionStackAtBottom(stack);
 
         // Find the next position where the stack should be placed
-        final int numStacks = getChildCount();
+        final int numStacks = getStackCount();
         for (int stackNdx = 0; stackNdx < numStacks; stackNdx++) {
-            final ActivityStack s = getChildAt(stackNdx);
+            final ActivityStack s = getStackAt(stackNdx);
             if (s == stack) {
                 continue;
             }
@@ -1383,7 +1178,7 @@
                     winMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
             if (s.shouldBeVisible(null) && isValidWindowingMode) {
                 // Move the provided stack to behind this stack
-                positionChildAt(stack, Math.max(0, stackNdx - 1));
+                positionStackAt(stack, Math.max(0, stackNdx - 1));
                 break;
             }
         }
@@ -1403,25 +1198,26 @@
         // list, so we need to adjust the insertion index to account for the removed index
         // TODO: Remove this logic when WindowContainer.positionChildAt() is updated to adjust the
         //       position internally
-        final int stackIndex = mStacks.indexOf(stack);
-        final int behindStackIndex = mStacks.indexOf(behindStack);
+        final int stackIndex = getIndexOf(stack);
+        final int behindStackIndex = getIndexOf(behindStack);
         final int insertIndex = stackIndex <= behindStackIndex
                 ? behindStackIndex - 1 : behindStackIndex;
-        positionChildAt(stack, Math.max(0, insertIndex));
+        positionStackAt(stack, Math.max(0, insertIndex));
     }
 
     void ensureActivitiesVisible(ActivityRecord starting, int configChanges,
             boolean preserveWindows, boolean notifyClients) {
-        for (int stackNdx = getChildCount() - 1; stackNdx >= 0; --stackNdx) {
-            final ActivityStack stack = getChildAt(stackNdx);
+        for (int stackNdx = getStackCount() - 1; stackNdx >= 0; --stackNdx) {
+            final ActivityStack stack = getStackAt(stackNdx);
             stack.ensureActivitiesVisible(starting, configChanges, preserveWindows,
                     notifyClients);
         }
     }
 
     void moveHomeStackToFront(String reason) {
-        if (mHomeStack != null) {
-            mHomeStack.moveToFront(reason);
+        final ActivityStack homeStack = getHomeStack();
+        if (homeStack != null) {
+            homeStack.moveToFront(reason);
         }
     }
 
@@ -1439,25 +1235,21 @@
     }
 
     @Nullable
-    ActivityStack getHomeStack() {
-        return mHomeStack;
-    }
-
-    @Nullable
     ActivityRecord getHomeActivity() {
         return getHomeActivityForUser(mRootActivityContainer.mCurrentUser);
     }
 
     @Nullable
     ActivityRecord getHomeActivityForUser(int userId) {
-        if (mHomeStack == null) {
+        final ActivityStack homeStack = getHomeStack();
+        if (homeStack == null) {
             return null;
         }
 
         final PooledPredicate p = PooledLambda.obtainPredicate(
                 ActivityDisplay::isHomeActivityForUser, PooledLambda.__(ActivityRecord.class),
                 userId);
-        final ActivityRecord r = mHomeStack.getActivity(p);
+        final ActivityRecord r = homeStack.getActivity(p);
         p.recycle();
         return r;
     }
@@ -1502,32 +1294,14 @@
         }
     }
 
-    /**
-     * See {@link DisplayContent#deferUpdateImeTarget()}
-     */
-    public void deferUpdateImeTarget() {
-        if (mDisplayContent != null) {
-            mDisplayContent.deferUpdateImeTarget();
-        }
-    }
-
-    /**
-     * See {@link DisplayContent#deferUpdateImeTarget()}
-     */
-    public void continueUpdateImeTarget() {
-        if (mDisplayContent != null) {
-            mDisplayContent.continueUpdateImeTarget();
-        }
-    }
-
     void setDisplayToSingleTaskInstance() {
-        final int childCount = getChildCount();
+        final int childCount = getStackCount();
         if (childCount > 1) {
             throw new IllegalArgumentException("Display already has multiple stacks. display="
                     + this);
         }
         if (childCount > 0) {
-            final ActivityStack stack = getChildAt(0);
+            final ActivityStack stack = getStackAt(0);
             if (stack.getChildCount() > 1) {
                 throw new IllegalArgumentException("Display stack already has multiple tasks."
                         + " display=" + this + " stack=" + stack);
@@ -1544,8 +1318,8 @@
 
     @VisibleForTesting
     void removeAllTasks() {
-        for (int i = getChildCount() - 1; i >= 0; --i) {
-            final ActivityStack stack = getChildAt(i);
+        for (int i = getStackCount() - 1; i >= 0; --i) {
+            final ActivityStack stack = getStackAt(i);
             final ArrayList<Task> tasks = stack.getAllTasks();
             for (int j = tasks.size() - 1; j >= 0; --j) {
                 stack.removeChild(tasks.get(j), "removeAllTasks");
@@ -1554,20 +1328,24 @@
     }
 
     public void dump(PrintWriter pw, String prefix) {
-        pw.println(prefix + "displayId=" + mDisplayId + " stacks=" + getChildCount()
+        pw.println(prefix + "displayId=" + mDisplayId + " stacks=" + getStackCount()
                 + (mSingleTaskInstance ? " mSingleTaskInstance" : ""));
         final String myPrefix = prefix + " ";
-        if (mHomeStack != null) {
-            pw.println(myPrefix + "mHomeStack=" + mHomeStack);
+        ActivityStack stack = getHomeStack();
+        if (stack != null) {
+            pw.println(myPrefix + "mHomeStack=" + stack);
         }
-        if (mRecentsStack != null) {
-            pw.println(myPrefix + "mRecentsStack=" + mRecentsStack);
+        stack = getRecentsStack();
+        if (stack != null) {
+            pw.println(myPrefix + "mRecentsStack=" + stack);
         }
-        if (mPinnedStack != null) {
-            pw.println(myPrefix + "mPinnedStack=" + mPinnedStack);
+        stack = getPinnedStack();
+        if (stack != null) {
+            pw.println(myPrefix + "mPinnedStack=" + stack);
         }
-        if (mSplitScreenPrimaryStack != null) {
-            pw.println(myPrefix + "mSplitScreenPrimaryStack=" + mSplitScreenPrimaryStack);
+        stack = getSplitScreenPrimaryStack();
+        if (stack != null) {
+            pw.println(myPrefix + "mSplitScreenPrimaryStack=" + stack);
         }
         if (mPreferredTopFocusableStack != null) {
             pw.println(myPrefix + "mPreferredTopFocusableStack=" + mPreferredTopFocusableStack);
@@ -1578,8 +1356,8 @@
     }
 
     public void dumpStacks(PrintWriter pw) {
-        for (int i = getChildCount() - 1; i >= 0; --i) {
-            pw.print(getChildAt(i).mStackId);
+        for (int i = getStackCount() - 1; i >= 0; --i) {
+            pw.print(getStackAt(i).mStackId);
             if (i > 0) {
                 pw.print(",");
             }
@@ -1589,7 +1367,7 @@
     public void writeToProto(ProtoOutputStream proto, long fieldId,
             @WindowTraceLogLevel int logLevel) {
         final long token = proto.start(fieldId);
-        super.writeToProto(proto, CONFIGURATION_CONTAINER, logLevel);
+        writeToProtoInner(proto, DISPLAY, logLevel);
         proto.write(ID, mDisplayId);
         proto.write(SINGLE_TASK_INSTANCE, mSingleTaskInstance);
         final ActivityStack focusedStack = getFocusedStack();
@@ -1602,8 +1380,8 @@
         } else {
             proto.write(FOCUSED_STACK_ID, INVALID_STACK_ID);
         }
-        for (int stackNdx = getChildCount() - 1; stackNdx >= 0; --stackNdx) {
-            final ActivityStack stack = getChildAt(stackNdx);
+        for (int stackNdx = getStackCount() - 1; stackNdx >= 0; --stackNdx) {
+            final ActivityStack stack = getStackAt(stackNdx);
             stack.writeToProto(proto, STACKS, logLevel);
         }
         proto.end(token);
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 6af5025..c230fb7 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -2237,7 +2237,7 @@
             }
         }
         return (getWindowConfiguration().canReceiveKeys() || isAlwaysFocusable())
-                && getParent() != null;
+                && getDisplay() != null;
     }
 
     /** Move activity with its stack to front and make the stack focused. */
@@ -2420,7 +2420,7 @@
                     final ActivityDisplay display = stack.getDisplay();
                     next = display.topRunningActivity();
                     if (next != null) {
-                        display.positionChildAtTop(next.getActivityStack(),
+                        display.positionStackAtTop(next.getActivityStack(),
                                 false /* includingParents */, "finish-display-top");
                     }
                 }
@@ -5694,8 +5694,6 @@
     @Override
     boolean isWaitingForTransitionStart() {
         final DisplayContent dc = getDisplayContent();
-        // TODO(display-unify): Test for null can be removed once unification is done.
-        if (dc == null) return false;
         return dc.mAppTransition.isTransitionSet()
                 && (dc.mOpeningApps.contains(this)
                 || dc.mClosingApps.contains(this)
diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java
index bb3126b..918d40b 100644
--- a/services/core/java/com/android/server/wm/ActivityStack.java
+++ b/services/core/java/com/android/server/wm/ActivityStack.java
@@ -750,7 +750,7 @@
         // stacks on a wrong display.
         mDisplayId = display.mDisplayId;
         setActivityType(activityType);
-        display.addChild(this, onTop ? POSITION_TOP : POSITION_BOTTOM);
+        display.addStack(this, onTop ? POSITION_TOP : POSITION_BOTTOM);
         setWindowingMode(windowingMode, false /* animate */, false /* showRecents */,
                 false /* enteringSplitScreenMode */, false /* deferEnsuringVisibility */,
                 true /* creating */);
@@ -879,7 +879,6 @@
                         newBounds /* outStackBounds */, mTmpRect2 /* outTempTaskBounds */);
                 hasNewOverrideBounds = true;
             }
-            display.onStackWindowingModeChanged(this);
         }
         if (hasNewOverrideBounds) {
             if (inSplitScreenPrimaryWindowingMode()) {
@@ -896,7 +895,7 @@
             // Since always on top is only on when the stack is freeform or pinned, the state
             // can be toggled when the windowing mode changes. We must make sure the stack is
             // placed properly when always on top state changes.
-            display.positionChildAtTop(this, false /* includingParents */);
+            display.positionStackAtTop(this, false /* includingParents */);
         }
     }
 
@@ -1337,7 +1336,7 @@
         }
 
         final boolean movingTask = task != null;
-        display.positionChildAtTop(this, !movingTask /* includingParents */, reason);
+        display.positionStackAtTop(this, !movingTask /* includingParents */, reason);
         if (movingTask) {
             // This also moves the entire hierarchy branch to top, including parents
             positionChildAtTop(task);
@@ -1353,7 +1352,7 @@
             return;
         }
 
-        getDisplay().positionChildAtBottom(this, reason);
+        getDisplay().positionStackAtBottom(this, reason);
         if (task != null) {
             positionChildAtBottom(task);
         }
@@ -1848,8 +1847,8 @@
         boolean shouldBeVisible = true;
         final int windowingMode = getWindowingMode();
         final boolean isAssistantType = isActivityTypeAssistant();
-        for (int i = display.getChildCount() - 1; i >= 0; --i) {
-            final ActivityStack other = display.getChildAt(i);
+        for (int i = display.getStackCount() - 1; i >= 0; --i) {
+            final ActivityStack other = display.getStackAt(i);
             final boolean hasRunningActivities = other.topRunningActivityLocked() != null;
             if (other == this) {
                 // Should be visible if there is no other stack occluding it, unless it doesn't
@@ -3010,7 +3009,7 @@
         if (index == 0) {
             return false;
         }
-        final ActivityStack stackBehind = display.getChildAt(index - 1);
+        final ActivityStack stackBehind = display.getStackAt(index - 1);
         return stackBehind.isActivityTypeStandard();
     }
 
@@ -3768,7 +3767,7 @@
 
         if (!hasChild()) {
             // Stack is now empty...
-          removeIfPossible();
+            removeIfPossible();
         }
 
         moveHomeStackToFrontIfNeeded(topFocused, display, reason);
@@ -3887,7 +3886,7 @@
         // always on top windows. Since the position the stack should be inserted into is calculated
         // properly in {@link ActivityDisplay#getTopInsertPosition()} in both cases, we can just
         // request that the stack is put at top here.
-        display.positionChildAtTop(this, false /* includingParents */);
+        display.positionStackAtTop(this, false /* includingParents */);
     }
 
     /** NOTE: Should only be called from {@link Task#reparent}. */
@@ -4019,7 +4018,7 @@
             final Task task = mChildren.get(0);
             setWindowingMode(WINDOWING_MODE_UNDEFINED);
 
-            getDisplay().positionChildAtTop(this, false /* includingParents */);
+            getDisplay().positionStackAtTop(this, false /* includingParents */);
 
             mStackSupervisor.scheduleUpdatePictureInPictureModeIfNeeded(task, this);
             MetricsLoggerWrapper.logPictureInPictureFullScreen(mService.mContext,
@@ -4456,20 +4455,14 @@
         }
     }
 
-    // TODO(display-unify): Remove after display unification.
-    protected void onParentChanged(ActivityDisplay newParent, ActivityDisplay oldParent) {
-        onParentChanged(
-                newParent != null ? newParent.mDisplayContent : null,
-                oldParent != null ? oldParent.mDisplayContent : null);
-    }
-
     @Override
     protected void onParentChanged(
             ConfigurationContainer newParent, ConfigurationContainer oldParent) {
+        // TODO(display-merge): Remove cast
         final ActivityDisplay display = newParent != null
-                ? ((WindowContainer) newParent).getDisplayContent().mActivityDisplay : null;
+                ? (ActivityDisplay) ((WindowContainer) newParent).getDisplayContent() : null;
         final ActivityDisplay oldDisplay = oldParent != null
-                ? ((WindowContainer) oldParent).getDisplayContent().mActivityDisplay : null;
+                ? (ActivityDisplay) ((WindowContainer) oldParent).getDisplayContent() : null;
 
         mDisplayId = (display != null) ? display.mDisplayId : INVALID_DISPLAY;
         mPrevDisplayId = (oldDisplay != null) ? oldDisplay.mDisplayId : INVALID_DISPLAY;
diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
index 0376d2c..aca3b90 100644
--- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
@@ -1501,13 +1501,11 @@
                     mRootActivityContainer.getActivityDisplay(toDisplayId);
 
             if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
-                // Tell the display we are exiting split-screen mode.
-                toDisplay.onExitingSplitScreenMode();
                 // We are moving all tasks from the docked stack to the fullscreen stack,
                 // which is dismissing the docked stack, so resize all other stacks to
                 // fullscreen here already so we don't end up with resize trashing.
-                for (int i = toDisplay.getChildCount() - 1; i >= 0; --i) {
-                    final ActivityStack otherStack = toDisplay.getChildAt(i);
+                for (int i = toDisplay.getStackCount() - 1; i >= 0; --i) {
+                    final ActivityStack otherStack = toDisplay.getStackAt(i);
                     if (!otherStack.inSplitScreenSecondaryWindowingMode()) {
                         continue;
                     }
@@ -1655,8 +1653,8 @@
                 // screen controls and is also the same for all stacks.
                 final ActivityDisplay display = mRootActivityContainer.getDefaultDisplay();
                 final Rect otherTaskRect = new Rect();
-                for (int i = display.getChildCount() - 1; i >= 0; --i) {
-                    final ActivityStack current = display.getChildAt(i);
+                for (int i = display.getStackCount() - 1; i >= 0; --i) {
+                    final ActivityStack current = display.getStackAt(i);
                     if (!current.inSplitScreenSecondaryWindowingMode()) {
                         continue;
                     }
@@ -1741,7 +1739,7 @@
              * to the fullscreen stack.  This is to guarantee that when we are removing a stack,
              * that the client receives onStop() before it is reparented.  We do this by detaching
              * the stack from the display so that it will be considered invisible when
-             * ensureActivitiesVisible() is called, and all of its activitys will be marked
+             * ensureActivitiesVisible() is called, and all of its activities will be marked
              * invisible as well and added to the stopping list.  After which we process the
              * stopping list by handling the idle.
              */
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index b046b08..a51ae51 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -138,7 +138,6 @@
 import static com.android.server.wm.utils.RegionUtils.rectListToRegion;
 
 import android.animation.AnimationHandler;
-import android.annotation.CallSuper;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -221,7 +220,7 @@
  * particular Display.
  */
 class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowContainer>
-        implements WindowManagerPolicy.DisplayContentInfo, ConfigurationContainerListener {
+        implements WindowManagerPolicy.DisplayContentInfo {
     private static final String TAG = TAG_WITH_CLASS_NAME ? "DisplayContent" : TAG_WM;
 
     /** The default scaling mode that scales content automatically. */
@@ -236,11 +235,10 @@
     @Retention(RetentionPolicy.SOURCE)
     @interface ForceScalingMode {}
 
-    /** Unique identifier of this stack. */
-    private final int mDisplayId;
+    ActivityTaskManagerService mAtmService;
 
-    // TODO: Remove once unification is complete.
-    ActivityDisplay mActivityDisplay;
+    /** Unique identifier of this display. */
+    private final int mDisplayId;
 
     /** The containers below are the only child containers the display can have. */
     // Contains all window containers that are related to apps (Activities)
@@ -842,16 +840,15 @@
      * @param service You know.
      * @param activityDisplay The ActivityDisplay for the display container.
      */
-    DisplayContent(Display display, WindowManagerService service,
-            ActivityDisplay activityDisplay) {
+    DisplayContent(Display display, WindowManagerService service) {
         super(service);
-        mActivityDisplay = activityDisplay;
         if (service.mRoot.getDisplayContent(display.getDisplayId()) != null) {
             throw new IllegalArgumentException("Display with ID=" + display.getDisplayId()
                     + " already exists=" + service.mRoot.getDisplayContent(display.getDisplayId())
                     + " new=" + display);
         }
 
+        mAtmService = mWmService.mAtmService;
         mDisplay = display;
         mDisplayId = display.getDisplayId();
         mWallpaperController = new WallpaperController(mWmService, this);
@@ -1125,20 +1122,6 @@
         mAppTransitionController.registerRemoteAnimations(definition);
     }
 
-    /**
-     * The display content may have configuration set from {@link #DisplayWindowSettings}. This
-     * callback let the owner of container know there is existing configuration to prevent the
-     * values from being replaced by the initializing {@link #ActivityDisplay}.
-     */
-    void initializeDisplayOverrideConfiguration() {
-        if (mActivityDisplay == null) {
-            return;
-        }
-        mActivityDisplay.onRequestedOverrideConfigurationChanged(
-                getResolvedOverrideConfiguration());
-        mActivityDisplay.registerConfigurationChangeListener(this);
-    }
-
     void reconfigureDisplayLocked() {
         if (!isReady()) {
             return;
@@ -1162,13 +1145,15 @@
     }
 
     void sendNewConfiguration() {
-        if (!isReady() || mActivityDisplay == null) {
+        if (!isReady()) {
             return;
         }
         if (mDisplayRotation.isWaitingForRemoteRotation()) {
             return;
         }
-        final boolean configUpdated = mActivityDisplay.updateDisplayOverrideConfigurationLocked();
+        // TODO(display-merge): Remove cast
+        final boolean configUpdated =
+                ((ActivityDisplay) this).updateDisplayOverrideConfigurationLocked();
         if (configUpdated) {
             return;
         }
@@ -1199,7 +1184,8 @@
 
         if (handled && requestingContainer instanceof ActivityRecord) {
             final ActivityRecord activityRecord = (ActivityRecord) requestingContainer;
-            final boolean kept = mActivityDisplay.updateDisplayOverrideConfigurationLocked(
+            // TODO(display-merge): Remove cast
+            final boolean kept = ((ActivityDisplay) this).updateDisplayOverrideConfigurationLocked(
                     config, activityRecord, false /* deferResume */, null /* result */);
             activityRecord.frozenBeforeDestroy = true;
             if (!kept) {
@@ -1208,7 +1194,8 @@
         } else {
             // We have a new configuration to push so we need to update ATMS for now.
             // TODO: Clean up display configuration push between ATMS and WMS after unification.
-            mActivityDisplay.updateDisplayOverrideConfigurationLocked(
+            // TODO(display-merge): Remove cast
+            ((ActivityDisplay) this.mDisplayContent).updateDisplayOverrideConfigurationLocked(
                     config, null /* starting */, false /* deferResume */, null);
         }
         return handled;
@@ -1797,12 +1784,15 @@
         return mTaskStackContainers.getHomeStack();
     }
 
+    ActivityStack getRecentsStack() {
+        return mTaskStackContainers.getRecentsStack();
+    }
+
     /**
-     * @return The primary split-screen stack, but only if it is visible, and {@code null} otherwise.
+     * @return The primary split-screen stack, and {@code null} otherwise.
      */
     ActivityStack getSplitScreenPrimaryStack() {
-        ActivityStack stack = mTaskStackContainers.getSplitScreenPrimaryStack();
-        return (stack != null && stack.isVisible()) ? stack : null;
+        return mTaskStackContainers.getSplitScreenPrimaryStack();
     }
 
     boolean hasSplitScreenPrimaryStack() {
@@ -1841,6 +1831,22 @@
         return mTaskStackContainers.getStack(windowingMode, activityType);
     }
 
+    protected int getStackCount() {
+        return mTaskStackContainers.mChildren.size();
+    }
+
+    protected ActivityStack getStackAt(int index) {
+        return mTaskStackContainers.mChildren.get(index);
+    }
+
+    int getIndexOf(ActivityStack stack) {
+        return mTaskStackContainers.getIndexOf(stack);
+    }
+
+    void removeStack(ActivityStack stack) {
+        mTaskStackContainers.removeChild(stack);
+    }
+
     @VisibleForTesting
     WindowList<ActivityStack> getStacks() {
         return mTaskStackContainers.mChildren;
@@ -2208,11 +2214,6 @@
         stack.reparent(mTaskStackContainers, onTop ? POSITION_TOP: POSITION_BOTTOM);
     }
 
-    // TODO(display-unify): No longer needed then.
-    void removeStackFromDisplay(ActivityStack stack) {
-        mTaskStackContainers.removeChild(stack);
-    }
-
     @Override
     protected void addChild(DisplayChildWindowContainer child,
             Comparator<DisplayChildWindowContainer> comparator) {
@@ -2364,9 +2365,6 @@
     void removeImmediately() {
         mRemovingDisplay = true;
         try {
-            if (mActivityDisplay != null) {
-                mActivityDisplay.unregisterConfigurationChangeListener(this);
-            }
             if (mParentWindow != null) {
                 mParentWindow.removeEmbeddedDisplayContent(this);
             }
@@ -2386,7 +2384,9 @@
             mWindowingLayer.release();
             mOverlayLayer.release();
             mInputMonitor.onDisplayRemoved();
-            mWmService.mDisplayNotificationController.dispatchDisplayRemoved(mActivityDisplay);
+            // TODO(display-merge): Remove cast
+            mWmService.mDisplayNotificationController
+                .dispatchDisplayRemoved((ActivityDisplay) this);
         } finally {
             mDisplayReady = false;
             mRemovingDisplay = false;
@@ -2599,9 +2599,8 @@
         }
     }
 
-    @CallSuper
-    @Override
-    public void writeToProto(ProtoOutputStream proto, long fieldId,
+    // TODO(proto-merge): Remove once protos for ActivityDisplay and DisplayContent are merged.
+    public void writeToProtoInner(ProtoOutputStream proto, long fieldId,
             @WindowTraceLogLevel int logLevel) {
         // Critical log level logs only visible elements to mitigate performance overheard
         if (logLevel == WindowTraceLogLevel.CRITICAL && !isVisible()) {
@@ -3929,6 +3928,7 @@
         // Cached reference to some special stacks we tend to get a lot so we don't need to loop
         // through the list to find them.
         private ActivityStack mHomeStack = null;
+        private ActivityStack mRecentsStack = null;
         private ActivityStack mPinnedStack = null;
         private ActivityStack mSplitScreenPrimaryStack = null;
 
@@ -3936,12 +3936,6 @@
             super(service);
         }
 
-        @Override
-        public void onConfigurationChanged(Configuration newParentConfig) {
-            // TODO(display-unify): Remove after unification.
-            onConfigurationChanged(newParentConfig, mActivityDisplay == null /*forwardToChildren*/);
-        }
-
         /**
          * Returns the topmost stack on the display that is compatible with the input windowing mode
          * and activity type. Null is no compatible stack on the display.
@@ -3976,6 +3970,10 @@
                     ? mTaskStackContainers.getChildAt(mTaskStackContainers.getChildCount() - 1) : null;
         }
 
+        int getIndexOf(ActivityStack stack) {
+            return mTaskStackContainers.mChildren.indexOf(stack);
+        }
+
         ActivityStack getHomeStack() {
             if (mHomeStack == null && mDisplayId == DEFAULT_DISPLAY) {
                 Slog.e(TAG_WM, "getHomeStack: Returning null from this=" + this);
@@ -3983,6 +3981,10 @@
             return mHomeStack;
         }
 
+        ActivityStack getRecentsStack() {
+            return mRecentsStack;
+        }
+
         ActivityStack getPinnedStack() {
             return mPinnedStack;
         }
@@ -4018,6 +4020,13 @@
 
                 }
                 mHomeStack = stack;
+            } else if (stack.isActivityTypeRecents()) {
+                if (mRecentsStack != null && mRecentsStack != stack) {
+                    throw new IllegalArgumentException(
+                        "addStackReferenceIfNeeded: recents stack=" + mRecentsStack
+                            + " already exist on display=" + this + " stack=" + stack);
+                }
+                mRecentsStack = stack;
             }
             final int windowingMode = stack.getWindowingMode();
             if (windowingMode == WINDOWING_MODE_PINNED) {
@@ -4034,17 +4043,23 @@
                             + " already exist on display=" + this + " stack=" + stack);
                 }
                 mSplitScreenPrimaryStack = stack;
+                // TODO(display-merge): Remove cast
+                ((ActivityDisplay) this.mDisplayContent).onSplitScreenModeActivated();
                 mDividerControllerLocked.notifyDockedStackExistsChanged(true);
             }
         }
 
-        private void removeStackReferenceIfNeeded(ActivityStack stack) {
+        void removeStackReferenceIfNeeded(ActivityStack stack) {
             if (stack == mHomeStack) {
                 mHomeStack = null;
+            } else if (stack == mRecentsStack) {
+                mRecentsStack = null;
             } else if (stack == mPinnedStack) {
                 mPinnedStack = null;
             } else if (stack == mSplitScreenPrimaryStack) {
                 mSplitScreenPrimaryStack = null;
+                // TODO(display-merge): Remove cast
+                ((ActivityDisplay) this.mDisplayContent).onSplitScreenModeDismissed();
                 // Re-set the split-screen create mode whenever the split-screen stack is removed.
                 mWmService.setDockedStackCreateStateLocked(
                         SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT, null /* initialBounds */);
@@ -4058,9 +4073,6 @@
             position = findPositionForStack(position, stack, true /* adding */);
 
             super.addChild(stack, position);
-            if (mActivityDisplay != null) {
-                mActivityDisplay.addChild(stack, position, true /*fromDc*/);
-            }
 
             // The reparenting case is handled in WindowContainer.
             if (!stack.mReparenting) {
@@ -4072,9 +4084,8 @@
         @Override
         protected void removeChild(ActivityStack stack) {
             super.removeChild(stack);
-            if (mActivityDisplay != null) {
-                mActivityDisplay.onChildRemoved(stack);
-            }
+            // TODO(display-merge): Remove cast
+            ((ActivityDisplay) this.mDisplayContent).onStackRemoved(stack);
             removeStackReferenceIfNeeded(stack);
         }
 
@@ -4087,7 +4098,7 @@
         @Override
         void positionChildAt(int position, ActivityStack child, boolean includingParents) {
             if (child.getWindowConfiguration().isAlwaysOnTop()
-                    && position != POSITION_TOP) {
+                    && position != POSITION_TOP && position != mChildren.size()) {
                 // This stack is always-on-top, override the default behavior.
                 Slog.w(TAG_WM, "Ignoring move of always-on-top stack=" + this + " to bottom");
 
@@ -4133,7 +4144,12 @@
             final int topChildPosition = mChildren.size() - 1;
             int belowAlwaysOnTopPosition = POSITION_BOTTOM;
             for (int i = topChildPosition; i >= 0; --i) {
-                if (getStacks().get(i) != stack && !getStacks().get(i).isAlwaysOnTop()) {
+                // Since a stack could be repositioned while being one of the child, return
+                // current index if that's the same stack we are positioning and it is always on
+                // top.
+                final boolean sameStack = getStacks().get(i) == stack;
+                if ((sameStack && stack.isAlwaysOnTop())
+                        || (!sameStack && !getStacks().get(i).isAlwaysOnTop())) {
                     belowAlwaysOnTopPosition = i;
                     break;
                 }
@@ -4158,10 +4174,6 @@
                         POSITION_BOTTOM ? belowAlwaysOnTopPosition : 0;
             }
 
-            int targetPosition = requestedPosition;
-            targetPosition = Math.min(targetPosition, maxPosition);
-            targetPosition = Math.max(targetPosition, minPosition);
-
             // Cap the requested position to something reasonable for the previous position check
             // below.
             if (requestedPosition == POSITION_TOP) {
@@ -4170,6 +4182,10 @@
                 requestedPosition = 0;
             }
 
+            int targetPosition = requestedPosition;
+            targetPosition = Math.min(targetPosition, maxPosition);
+            targetPosition = Math.max(targetPosition, minPosition);
+
             int prevPosition = getStacks().indexOf(stack);
             // The positions we calculated above (maxPosition, minPosition) do not take into
             // consideration the following edge cases.
diff --git a/services/core/java/com/android/server/wm/DisplayWindowListenerController.java b/services/core/java/com/android/server/wm/DisplayWindowListenerController.java
index 2da76ea..78fea74 100644
--- a/services/core/java/com/android/server/wm/DisplayWindowListenerController.java
+++ b/services/core/java/com/android/server/wm/DisplayWindowListenerController.java
@@ -63,7 +63,7 @@
         mDisplayListeners.finishBroadcast();
     }
 
-    void dispatchDisplayChanged(ActivityDisplay display, Configuration newConfig) {
+    void dispatchDisplayChanged(DisplayContent display, Configuration newConfig) {
         // Only report changed if this has actually been added to the hierarchy already.
         boolean isInHierarchy = false;
         for (int i = 0; i < display.getParent().getChildCount(); ++i) {
@@ -78,7 +78,7 @@
         for (int i = 0; i < count; ++i) {
             try {
                 mDisplayListeners.getBroadcastItem(i).onDisplayConfigurationChanged(
-                        display.mDisplayId, newConfig);
+                        display.getDisplayId(), newConfig);
             } catch (RemoteException e) {
             }
         }
diff --git a/services/core/java/com/android/server/wm/KeyguardController.java b/services/core/java/com/android/server/wm/KeyguardController.java
index 7645de5..318d88e 100644
--- a/services/core/java/com/android/server/wm/KeyguardController.java
+++ b/services/core/java/com/android/server/wm/KeyguardController.java
@@ -531,8 +531,8 @@
          * occlusion state.
          */
         private ActivityStack getStackForControllingOccluding(ActivityDisplay display) {
-            for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
-                final ActivityStack stack = display.getChildAt(stackNdx);
+            for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
+                final ActivityStack stack = display.getStackAt(stackNdx);
                 if (stack != null && stack.isFocusableAndVisible()
                         && !stack.inPinnedWindowingMode()) {
                     return stack;
diff --git a/services/core/java/com/android/server/wm/RecentsAnimation.java b/services/core/java/com/android/server/wm/RecentsAnimation.java
index f2e9505..8c01479 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimation.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimation.java
@@ -473,8 +473,8 @@
      * @return The top stack that is not always-on-top.
      */
     private ActivityStack getTopNonAlwaysOnTopStack() {
-        for (int i = mDefaultDisplay.getChildCount() - 1; i >= 0; i--) {
-            final ActivityStack s = mDefaultDisplay.getChildAt(i);
+        for (int i = mDefaultDisplay.getStackCount() - 1; i >= 0; i--) {
+            final ActivityStack s = mDefaultDisplay.getStackAt(i);
             if (s.getWindowConfiguration().isAlwaysOnTop()) {
                 continue;
             }
diff --git a/services/core/java/com/android/server/wm/RootActivityContainer.java b/services/core/java/com/android/server/wm/RootActivityContainer.java
index 5fd59fa..40e6dcc 100644
--- a/services/core/java/com/android/server/wm/RootActivityContainer.java
+++ b/services/core/java/com/android/server/wm/RootActivityContainer.java
@@ -52,7 +52,6 @@
 import static com.android.server.wm.ActivityStackSupervisor.dumpHistoryList;
 import static com.android.server.wm.ActivityStackSupervisor.printThisActivity;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_RECENTS;
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_RELEASE;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_STACK;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_STATES;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_TASKS;
@@ -770,10 +769,12 @@
             starting.frozenBeforeDestroy = true;
         }
 
-        if (displayContent != null && displayContent.mActivityDisplay != null) {
+        if (displayContent != null) {
             // Update the configuration of the activities on the display.
-            return displayContent.mActivityDisplay.updateDisplayOverrideConfigurationLocked(config,
-                    starting, deferResume, null /* result */);
+            // TODO(display-merge): Remove cast
+            return ((ActivityDisplay) displayContent)
+                .updateDisplayOverrideConfigurationLocked(config, starting, deferResume,
+                    null /* result */);
         } else {
             return true;
         }
@@ -790,8 +791,8 @@
         for (int i = mActivityDisplays.size() - 1; i >= 0; i--) {
             final ActivityDisplay display = mActivityDisplays.get(i);
             // Traverse all stacks on a display.
-            for (int j = display.getChildCount() - 1; j >= 0; --j) {
-                final ActivityStack stack = display.getChildAt(j);
+            for (int j = display.getStackCount() - 1; j >= 0; --j) {
+                final ActivityStack stack = display.getStackAt(j);
                 // Get top activity from a visible stack and add it to the list.
                 if (stack.shouldBeVisible(null /* starting */)) {
                     final ActivityRecord top = stack.getTopNonFinishingActivity();
@@ -861,8 +862,8 @@
         WindowProcessController fgApp = null;
         for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
             final ActivityDisplay display = mActivityDisplays.get(displayNdx);
-            for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
-                final ActivityStack stack = display.getChildAt(stackNdx);
+            for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
+                final ActivityStack stack = display.getStackAt(stackNdx);
                 if (isTopDisplayFocusedStack(stack)) {
                     final ActivityRecord resumedActivity = stack.getResumedActivity();
                     if (resumedActivity != null) {
@@ -988,8 +989,8 @@
         mStackSupervisor.mStartingUsers.add(uss);
         for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
             final ActivityDisplay display = mActivityDisplays.get(displayNdx);
-            for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
-                final ActivityStack stack = display.getChildAt(stackNdx);
+            for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
+                final ActivityStack stack = display.getStackAt(stackNdx);
                 stack.switchUser(userId);
                 Task task = stack.topTask();
                 if (task != null) {
@@ -1056,7 +1057,7 @@
                     + " to its current displayId=" + displayId);
         }
 
-        if (activityDisplay.isSingleTaskInstance() && activityDisplay.getChildCount() > 0) {
+        if (activityDisplay.isSingleTaskInstance() && activityDisplay.getStackCount() > 0) {
             // We don't allow moving stacks to single instance display that already has a child.
             Slog.e(TAG, "Can not move stack=" + stack
                     + " to single task instance display=" + activityDisplay);
@@ -1229,8 +1230,8 @@
             final ActivityDisplay display = mActivityDisplays.get(displayNdx);
             // It is possible that request to finish activity might also remove its task and stack,
             // so we need to be careful with indexes in the loop and check child count every time.
-            for (int stackNdx = 0; stackNdx < display.getChildCount(); ++stackNdx) {
-                final ActivityStack stack = display.getChildAt(stackNdx);
+            for (int stackNdx = 0; stackNdx < display.getStackCount(); ++stackNdx) {
+                final ActivityStack stack = display.getStackAt(stackNdx);
                 final Task t = stack.finishTopCrashedActivityLocked(app, reason);
                 if (stack == focusedStack || finishedTask == null) {
                     finishedTask = t;
@@ -1260,8 +1261,8 @@
         for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
             boolean resumedOnDisplay = false;
             final ActivityDisplay display = mActivityDisplays.get(displayNdx);
-            for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
-                final ActivityStack stack = display.getChildAt(stackNdx);
+            for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
+                final ActivityStack stack = display.getStackAt(stackNdx);
                 final ActivityRecord topRunningActivity = stack.topRunningActivityLocked();
                 if (!stack.isFocusableAndVisible() || topRunningActivity == null) {
                     continue;
@@ -1314,8 +1315,8 @@
             }
 
             // Set the sleeping state of the stacks on the display.
-            for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
-                final ActivityStack stack = display.getChildAt(stackNdx);
+            for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
+                final ActivityStack stack = display.getStackAt(stackNdx);
                 if (displayShouldSleep) {
                     stack.goToSleepIfPossible(false /* shuttingDown */);
                 } else {
@@ -1355,9 +1356,9 @@
         }
     }
 
-    protected <T extends ActivityStack> T getStack(int stackId) {
+    protected ActivityStack getStack(int stackId) {
         for (int i = mActivityDisplays.size() - 1; i >= 0; --i) {
-            final T stack = mActivityDisplays.get(i).getStack(stackId);
+            final ActivityStack stack = mActivityDisplays.get(i).getStack(stackId);
             if (stack != null) {
                 return stack;
             }
@@ -1366,9 +1367,10 @@
     }
 
     /** @see ActivityDisplay#getStack(int, int) */
-    private <T extends ActivityStack> T getStack(int windowingMode, int activityType) {
+    ActivityStack getStack(int windowingMode, int activityType) {
         for (int i = mActivityDisplays.size() - 1; i >= 0; --i) {
-            final T stack = mActivityDisplays.get(i).getStack(windowingMode, activityType);
+            final ActivityStack stack =
+                    mActivityDisplays.get(i).getStack(windowingMode, activityType);
             if (stack != null) {
                 return stack;
             }
@@ -1376,7 +1378,7 @@
         return null;
     }
 
-    private <T extends ActivityStack> T getStack(int windowingMode, int activityType,
+    private ActivityStack getStack(int windowingMode, int activityType,
             int displayId) {
         ActivityDisplay display = getActivityDisplay(displayId);
         if (display == null) {
@@ -1449,8 +1451,8 @@
         if (displayId == INVALID_DISPLAY) {
             for (int displayNdx = 0; displayNdx < mActivityDisplays.size(); ++displayNdx) {
                 final ActivityDisplay display = mActivityDisplays.get(displayNdx);
-                for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
-                    final ActivityStack stack = display.getChildAt(stackNdx);
+                for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
+                    final ActivityStack stack = display.getStackAt(stackNdx);
                     list.add(getStackInfo(stack));
                 }
             }
@@ -1460,8 +1462,8 @@
         if (display == null) {
             return list;
         }
-        for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
-            final ActivityStack stack = display.getChildAt(stackNdx);
+        for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
+            final ActivityStack stack = display.getStackAt(stackNdx);
             list.add(getStackInfo(stack));
         }
         return list;
@@ -1549,9 +1551,9 @@
     ActivityStack findStackBehind(ActivityStack stack) {
         final ActivityDisplay display = getActivityDisplay(stack.mDisplayId);
         if (display != null) {
-            for (int i = display.getChildCount() - 1; i >= 0; i--) {
-                if (display.getChildAt(i) == stack && i > 0) {
-                    return display.getChildAt(i - 1);
+            for (int i = display.getStackCount() - 1; i >= 0; i--) {
+                if (display.getStackAt(i) == stack && i > 0) {
+                    return display.getStackAt(i - 1);
                 }
             }
         }
@@ -1575,7 +1577,7 @@
     }
 
     // TODO: remove after object merge with RootWindowContainer
-    void onChildPositionChanged(ActivityDisplay display, int position) {
+    void onChildPositionChanged(DisplayContent display, int position) {
         // Assume AM lock is held from positionChildAt of controller in each hierarchy.
         if (display != null) {
             positionChildAt(display, position);
@@ -1583,18 +1585,20 @@
     }
 
     /** Change the z-order of the given display. */
-    private void positionChildAt(ActivityDisplay display, int position) {
+    private void positionChildAt(DisplayContent display, int position) {
         if (position >= mActivityDisplays.size()) {
             position = mActivityDisplays.size() - 1;
         } else if (position < 0) {
             position = 0;
         }
 
+        // TODO(display-merge): Remove cast
+        final ActivityDisplay activityDisplay = (ActivityDisplay) display;
         if (mActivityDisplays.isEmpty()) {
-            mActivityDisplays.add(display);
+            mActivityDisplays.add(activityDisplay);
         } else if (mActivityDisplays.get(position) != display) {
             mActivityDisplays.remove(display);
-            mActivityDisplays.add(position, display);
+            mActivityDisplays.add(position, activityDisplay);
         }
         mStackSupervisor.updateTopResumedActivityIfNeeded();
     }
@@ -1709,8 +1713,8 @@
     void scheduleDestroyAllActivities(WindowProcessController app, String reason) {
         for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
             final ActivityDisplay display = mActivityDisplays.get(displayNdx);
-            for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
-                final ActivityStack stack = display.getChildAt(stackNdx);
+            for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
+                final ActivityStack stack = display.getStackAt(stackNdx);
                 stack.scheduleDestroyActivities(app, reason);
             }
         }
@@ -1722,15 +1726,15 @@
         boolean allSleep = true;
         for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
             final ActivityDisplay display = mActivityDisplays.get(displayNdx);
-            for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+            for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
                 // Stacks and activities could be removed while putting activities to sleep if
                 // the app process was gone. This prevents us getting exception by accessing an
                 // invalid stack index.
-                if (stackNdx >= display.getChildCount()) {
+                if (stackNdx >= display.getStackCount()) {
                     continue;
                 }
 
-                final ActivityStack stack = display.getChildAt(stackNdx);
+                final ActivityStack stack = display.getStackAt(stackNdx);
                 if (allowDelay) {
                     allSleep &= stack.goToSleepIfPossible(shuttingDown);
                 } else {
@@ -1972,8 +1976,8 @@
                 r.getActivityType());
 
         // Return the topmost valid stack on the display.
-        for (int i = activityDisplay.getChildCount() - 1; i >= 0; --i) {
-            final ActivityStack stack = activityDisplay.getChildAt(i);
+        for (int i = activityDisplay.getStackCount() - 1; i >= 0; --i) {
+            final ActivityStack stack = activityDisplay.getStackAt(i);
             if (isValidLaunchStack(stack, r, windowingMode)) {
                 return stack;
             }
@@ -2110,8 +2114,8 @@
         boolean hasVisibleActivities = false;
         for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
             final ActivityDisplay display = mActivityDisplays.get(displayNdx);
-            for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
-                final ActivityStack stack = display.getChildAt(stackNdx);
+            for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
+                final ActivityStack stack = display.getStackAt(stackNdx);
                 hasVisibleActivities |= stack.handleAppDiedLocked(app);
             }
         }
@@ -2223,9 +2227,9 @@
     void finishVoiceTask(IVoiceInteractionSession session) {
         for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
             final ActivityDisplay display = mActivityDisplays.get(displayNdx);
-            final int numStacks = display.getChildCount();
+            final int numStacks = display.getStackCount();
             for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
-                final ActivityStack stack = display.getChildAt(stackNdx);
+                final ActivityStack stack = display.getStackAt(stackNdx);
                 stack.finishVoiceTask(session);
             }
         }
@@ -2290,8 +2294,8 @@
         boolean foundResumed = false;
         for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
             final ActivityDisplay display = mActivityDisplays.get(displayNdx);
-            for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
-                final ActivityStack stack = display.getChildAt(stackNdx);
+            for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
+                final ActivityStack stack = display.getStackAt(stackNdx);
                 final ActivityRecord r = stack.getResumedActivity();
                 if (r != null) {
                     if (!r.nowVisible) {
@@ -2308,8 +2312,8 @@
         boolean pausing = true;
         for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
             final ActivityDisplay display = mActivityDisplays.get(displayNdx);
-            for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
-                final ActivityStack stack = display.getChildAt(stackNdx);
+            for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
+                final ActivityStack stack = display.getStackAt(stackNdx);
                 final ActivityRecord r = stack.mPausingActivity;
                 if (r != null && !r.isState(PAUSED, STOPPED, STOPPING)) {
                     if (DEBUG_STATES) {
@@ -2336,8 +2340,8 @@
         try {
             for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
                 final ActivityDisplay display = mActivityDisplays.get(displayNdx);
-                for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
-                    final ActivityStack stack = display.getChildAt(stackNdx);
+                for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
+                    final ActivityStack stack = display.getStackAt(stackNdx);
                     final List<Task> tasks = stack.getAllTasks();
                     for (int taskNdx = tasks.size() - 1; taskNdx >= 0; taskNdx--) {
                         final Task task = tasks.get(taskNdx);
@@ -2380,8 +2384,8 @@
     void cancelInitializingActivities() {
         for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
             final ActivityDisplay display = mActivityDisplays.get(displayNdx);
-            for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
-                final ActivityStack stack = display.getChildAt(stackNdx);
+            for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
+                final ActivityStack stack = display.getStackAt(stackNdx);
                 stack.cancelInitializingActivities();
             }
         }
@@ -2413,8 +2417,8 @@
         int numDisplays = mActivityDisplays.size();
         for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
             final ActivityDisplay display = mActivityDisplays.get(displayNdx);
-            for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
-                final ActivityStack stack = display.getChildAt(stackNdx);
+            for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
+                final ActivityStack stack = display.getStackAt(stackNdx);
                 final Task task = stack.taskForIdLocked(id);
                 if (task == null) {
                     continue;
@@ -2471,8 +2475,8 @@
         int numDisplays = mActivityDisplays.size();
         for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
             final ActivityDisplay display = mActivityDisplays.get(displayNdx);
-            for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
-                final ActivityStack stack = display.getChildAt(stackNdx);
+            for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
+                final ActivityStack stack = display.getStackAt(stackNdx);
                 final ActivityRecord r = stack.isInStackLocked(token);
                 if (r != null) {
                     return r;
@@ -2554,8 +2558,8 @@
             int numDisplays = mActivityDisplays.size();
             for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
                 final ActivityDisplay display = mActivityDisplays.get(displayNdx);
-                for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
-                    final ActivityStack stack = display.getChildAt(stackNdx);
+                for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
+                    final ActivityStack stack = display.getStackAt(stackNdx);
                     if (!dumpVisibleStacksOnly || stack.shouldBeVisible(null)) {
                         activities.addAll(stack.getDumpActivitiesLocked(name));
                     }
@@ -2606,8 +2610,8 @@
             pw.print("Display #"); pw.print(activityDisplay.mDisplayId);
             pw.println(" (activities from top to bottom):");
             final ActivityDisplay display = mActivityDisplays.get(displayNdx);
-            for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
-                final ActivityStack stack = display.getChildAt(stackNdx);
+            for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
+                final ActivityStack stack = display.getStackAt(stackNdx);
                 pw.println();
                 printed = stack.dump(fd, pw, dumpAll, dumpClient, dumpPackage, needSep);
                 needSep = printed;
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 5ec9599..d0ad605 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -37,7 +37,6 @@
 import static com.android.server.wm.RootWindowContainerProto.DISPLAYS;
 import static com.android.server.wm.RootWindowContainerProto.WINDOWS;
 import static com.android.server.wm.RootWindowContainerProto.WINDOW_CONTAINER;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DISPLAY;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_TRACE;
@@ -71,7 +70,6 @@
 import android.util.Slog;
 import android.util.SparseIntArray;
 import android.util.proto.ProtoOutputStream;
-import android.view.Display;
 import android.view.DisplayInfo;
 import android.view.SurfaceControl;
 import android.view.WindowManager;
@@ -219,36 +217,6 @@
         return null;
     }
 
-    DisplayContent createDisplayContent(final Display display, ActivityDisplay activityDisplay) {
-        final int displayId = display.getDisplayId();
-
-        // In select scenarios, it is possible that a DisplayContent will be created on demand
-        // rather than waiting for the controller. In this case, associate the controller and return
-        // the existing display.
-        final DisplayContent existing = getDisplayContent(displayId);
-
-        if (existing != null) {
-            existing.mActivityDisplay = activityDisplay;
-            existing.initializeDisplayOverrideConfiguration();
-            return existing;
-        }
-
-        final DisplayContent dc = new DisplayContent(display, mWmService, activityDisplay);
-
-        if (DEBUG_DISPLAY) Slog.v(TAG_WM, "Adding display=" + display);
-
-        mWmService.mDisplayWindowSettings.applySettingsToDisplayLocked(dc);
-        dc.initializeDisplayOverrideConfiguration();
-
-        if (mWmService.mDisplayManagerInternal != null) {
-            mWmService.mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager(
-                    displayId, dc.getDisplayInfo());
-            dc.configureDisplayPolicy();
-        }
-
-        return dc;
-    }
-
     /**
      * Called when DisplayWindowSettings values may change.
      */
@@ -262,7 +230,6 @@
                 continue;
             }
 
-            displayContent.initializeDisplayOverrideConfiguration();
             displayContent.reconfigureDisplayLocked();
 
             // We need to update global configuration as well if config of default display has
@@ -1039,7 +1006,7 @@
             final int count = mChildren.size();
             for (int i = 0; i < count; ++i) {
                 final DisplayContent displayContent = mChildren.get(i);
-                displayContent.writeToProto(proto, DISPLAYS, logLevel);
+                displayContent.writeToProtoInner(proto, DISPLAYS, logLevel);
             }
         }
         if (logLevel == WindowTraceLogLevel.ALL) {
@@ -1059,7 +1026,7 @@
     void positionChildAt(int position, DisplayContent child, boolean includingParents) {
         super.positionChildAt(position, child, includingParents);
         if (mRootActivityContainer != null) {
-            mRootActivityContainer.onChildPositionChanged(child.mActivityDisplay, position);
+            mRootActivityContainer.onChildPositionChanged(child, position);
         }
     }
 
diff --git a/services/core/java/com/android/server/wm/RunningTasks.java b/services/core/java/com/android/server/wm/RunningTasks.java
index f2678bb..ca9d91e 100644
--- a/services/core/java/com/android/server/wm/RunningTasks.java
+++ b/services/core/java/com/android/server/wm/RunningTasks.java
@@ -52,8 +52,8 @@
         final int numDisplays = activityDisplays.size();
         for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
             final ActivityDisplay display = activityDisplays.get(displayNdx);
-            for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
-                final ActivityStack stack = display.getChildAt(stackNdx);
+            for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
+                final ActivityStack stack = display.getStackAt(stackNdx);
                 mTmpStackTasks.clear();
                 stack.getRunningTasks(mTmpStackTasks, ignoreActivityType, ignoreWindowingMode,
                         callingUid, allowed, crossUser, profileIds);
diff --git a/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java b/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
index 8ad8972..9d19cfe 100644
--- a/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
+++ b/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
@@ -705,8 +705,8 @@
     private void adjustBoundsToAvoidConflictInDisplay(@NonNull ActivityDisplay display,
             @NonNull Rect inOutBounds) {
         final List<Rect> taskBoundsToCheck = new ArrayList<>();
-        for (int i = 0; i < display.getChildCount(); ++i) {
-            final ActivityStack stack = display.getChildAt(i);
+        for (int i = 0; i < display.getStackCount(); ++i) {
+            final ActivityStack stack = display.getStackAt(i);
             if (!stack.inFreeformWindowingMode()) {
                 continue;
             }
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index 5c1491e..1b4ca41 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -288,10 +288,8 @@
         final DisplayContent dc = newParent.getDisplayContent();
 
         mReparenting = true;
-        // Oddly enough we add to the new parent before removing from the old parent to avoid
-        // issues...
-        newParent.addChild(this, position);
         oldParent.removeChild(this);
+        newParent.addChild(this, position);
         mReparenting = false;
 
         // Relayout display(s)
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index a6578f3..3b639f4 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -1732,20 +1732,7 @@
             }
         }
 
-        DisplayContent displayContent = mRoot.getDisplayContent(displayId);
-
-        // Create an instance if possible instead of waiting for the ActivityManagerService to drive
-        // the creation.
-        if (displayContent == null) {
-            final Display display = mDisplayManager.getDisplay(displayId);
-
-            if (display != null) {
-                displayContent = mRoot.createDisplayContent(display, null /* activityDisplay */);
-                displayContent.reconfigureDisplayLocked();
-            }
-        }
-
-        return displayContent;
+        return mAtmService.mRootActivityContainer.getActivityDisplayOrCreate(displayId);
     }
 
     private boolean doesAddToastWindowRequireToken(String packageName, int callingUid,
@@ -7660,7 +7647,8 @@
             // to do so because it seems possible to resume activities as part of a larger
             // transaction and it's too early to resume based on current order when performing
             // updateTopResumedActivityIfNeeded().
-            displayContent.mActivityDisplay.ensureActivitiesVisible(null /* starting */,
+            // TODO(display-merge): Remove cast
+            ((ActivityDisplay) displayContent).ensureActivitiesVisible(null /* starting */,
                     0 /* configChanges */, !PRESERVE_WINDOWS, true /* notifyClients */);
         }
     }
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java
index 5336811..de2bba2 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java
@@ -123,7 +123,7 @@
         assertTrue(stack1.isFocusedStackOnDisplay());
 
         // Stack2 should be focused after removing stack1.
-        display.removeChild(stack1);
+        display.removeStack(stack1);
         assertTrue(stack2.isFocusedStackOnDisplay());
     }
 
@@ -224,7 +224,7 @@
         final ActivityRecord activity = new ActivityBuilder(mService).setCreateTask(true)
                 .setStack(alwaysOnTopStack).build();
         alwaysOnTopStack.setAlwaysOnTop(true);
-        display.positionChildAtTop(alwaysOnTopStack, false /* includingParents */);
+        display.positionStackAtTop(alwaysOnTopStack, false /* includingParents */);
         assertTrue(alwaysOnTopStack.isAlwaysOnTop());
         // Ensure always on top state is synced to the children of the stack.
         assertTrue(alwaysOnTopStack.getTopNonFinishingActivity().isAlwaysOnTop());
@@ -238,36 +238,36 @@
         final ActivityStack anotherAlwaysOnTopStack = display.createStack(
                 WINDOWING_MODE_FREEFORM, ACTIVITY_TYPE_STANDARD, true /* onTop */);
         anotherAlwaysOnTopStack.setAlwaysOnTop(true);
-        display.positionChildAtTop(anotherAlwaysOnTopStack, false /* includingParents */);
+        display.positionStackAtTop(anotherAlwaysOnTopStack, false /* includingParents */);
         assertTrue(anotherAlwaysOnTopStack.isAlwaysOnTop());
-        int topPosition = display.getChildCount() - 1;
+        int topPosition = display.getStackCount() - 1;
         // Ensure the new alwaysOnTop stack is put below the pinned stack, but on top of the
         // existing alwaysOnTop stack.
-        assertEquals(anotherAlwaysOnTopStack, display.getChildAt(topPosition - 1));
+        assertEquals(anotherAlwaysOnTopStack, display.getStackAt(topPosition - 1));
 
         final ActivityStack nonAlwaysOnTopStack = display.createStack(
                 WINDOWING_MODE_FREEFORM, ACTIVITY_TYPE_STANDARD, true /* onTop */);
         assertEquals(display, nonAlwaysOnTopStack.getDisplay());
-        topPosition = display.getChildCount() - 1;
+        topPosition = display.getStackCount() - 1;
         // Ensure the non-alwaysOnTop stack is put below the three alwaysOnTop stacks, but above the
         // existing other non-alwaysOnTop stacks.
-        assertEquals(nonAlwaysOnTopStack, display.getChildAt(topPosition - 3));
+        assertEquals(nonAlwaysOnTopStack, display.getStackAt(topPosition - 3));
 
         anotherAlwaysOnTopStack.setAlwaysOnTop(false);
-        display.positionChildAtTop(anotherAlwaysOnTopStack, false /* includingParents */);
+        display.positionStackAtTop(anotherAlwaysOnTopStack, false /* includingParents */);
         assertFalse(anotherAlwaysOnTopStack.isAlwaysOnTop());
         // Ensure, when always on top is turned off for a stack, the stack is put just below all
         // other always on top stacks.
-        assertEquals(anotherAlwaysOnTopStack, display.getChildAt(topPosition - 2));
+        assertEquals(anotherAlwaysOnTopStack, display.getStackAt(topPosition - 2));
         anotherAlwaysOnTopStack.setAlwaysOnTop(true);
 
         // Ensure always on top state changes properly when windowing mode changes.
         anotherAlwaysOnTopStack.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
         assertFalse(anotherAlwaysOnTopStack.isAlwaysOnTop());
-        assertEquals(anotherAlwaysOnTopStack, display.getChildAt(topPosition - 2));
+        assertEquals(anotherAlwaysOnTopStack, display.getStackAt(topPosition - 2));
         anotherAlwaysOnTopStack.setWindowingMode(WINDOWING_MODE_FREEFORM);
         assertTrue(anotherAlwaysOnTopStack.isAlwaysOnTop());
-        assertEquals(anotherAlwaysOnTopStack, display.getChildAt(topPosition - 1));
+        assertEquals(anotherAlwaysOnTopStack, display.getStackAt(topPosition - 1));
     }
 
     @Test
@@ -299,14 +299,14 @@
 
         // Reordering stacks while removing stacks.
         doAnswer(invocation -> {
-            display.positionChildAtTop(stack3, false);
+            display.positionStackAtTop(stack3, false);
             return true;
         }).when(mSupervisor).removeTaskByIdLocked(eq(task4.mTaskId), anyBoolean(), anyBoolean(),
                 any());
 
         // Removing stacks from the display while removing stacks.
         doAnswer(invocation -> {
-            display.removeChild(stack2);
+            display.removeStack(stack2);
             return true;
         }).when(mSupervisor).removeTaskByIdLocked(eq(task2.mTaskId), anyBoolean(), anyBoolean(),
                 any());
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
index c2b8827..7166829 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -455,7 +455,7 @@
             verify(mService.getLifecycleManager()).scheduleTransaction(
                     eq(mActivity.app.getThread()), eq(mActivity.appToken), eq(expected));
         } finally {
-            stack.getDisplay().removeChild(stack);
+            stack.getDisplay().removeStack(stack);
         }
     }
 
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 c8795ce..7806d40 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
@@ -290,7 +290,7 @@
         verify(stack2).positionChildAtBottom(any(), eq(false) /* includingParents */);
 
         // Also move display to back because there is only one stack left.
-        display.removeChild(stack1);
+        display.removeStack(stack1);
         stack2.moveToBack("testMoveStackToBackIncludingParent", stack2.topTask());
         verify(stack2).positionChildAtBottom(any(), eq(true) /* includingParents */);
     }
@@ -576,7 +576,7 @@
 
     @Test
     public void testMoveHomeStackBehindBottomMostVisibleStack_NoMoveHomeBehindFullscreen() {
-        mDefaultDisplay.removeChild(mStack);
+        mDefaultDisplay.removeStack(mStack);
 
         final ActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */);
@@ -595,7 +595,7 @@
 
     @Test
     public void testMoveHomeStackBehindBottomMostVisibleStack_NoMoveHomeBehindTranslucent() {
-        mDefaultDisplay.removeChild(mStack);
+        mDefaultDisplay.removeStack(mStack);
 
         final ActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */);
@@ -614,7 +614,7 @@
 
     @Test
     public void testMoveHomeStackBehindBottomMostVisibleStack_NoMoveHomeOnTop() {
-        mDefaultDisplay.removeChild(mStack);
+        mDefaultDisplay.removeStack(mStack);
 
         final ActivityStack fullscreenStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
@@ -633,7 +633,7 @@
 
     @Test
     public void testMoveHomeStackBehindBottomMostVisibleStack_MoveHomeBehindFullscreen() {
-        mDefaultDisplay.removeChild(mStack);
+        mDefaultDisplay.removeStack(mStack);
 
         final ActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */);
@@ -660,7 +660,7 @@
     @Test
     public void
             testMoveHomeStackBehindBottomMostVisibleStack_MoveHomeBehindFullscreenAndTranslucent() {
-        mDefaultDisplay.removeChild(mStack);
+        mDefaultDisplay.removeStack(mStack);
 
         final ActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */);
@@ -684,7 +684,7 @@
 
     @Test
     public void testMoveHomeStackBehindStack_BehindHomeStack() {
-        mDefaultDisplay.removeChild(mStack);
+        mDefaultDisplay.removeStack(mStack);
 
         final ActivityStack fullscreenStack1 = createStackForShouldBeVisibleTest(
                 mDefaultDisplay, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
@@ -707,7 +707,7 @@
 
     @Test
     public void testMoveHomeStackBehindStack() {
-        mDefaultDisplay.removeChild(mStack);
+        mDefaultDisplay.removeStack(mStack);
 
         final ActivityStack fullscreenStack1 = createStackForShouldBeVisibleTest(
                 mDefaultDisplay, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
@@ -814,16 +814,16 @@
     }
 
     @SuppressWarnings("TypeParameterUnusedInFormals")
-    private <T extends ActivityStack> T createStackForShouldBeVisibleTest(
+    private ActivityStack createStackForShouldBeVisibleTest(
             ActivityDisplay display, int windowingMode, int activityType, boolean onTop) {
         final ActivityStack stack;
         if (activityType == ACTIVITY_TYPE_HOME) {
             // Home stack and activity are created in ActivityTestsBase#setupActivityManagerService
             stack = mDefaultDisplay.getStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME);
             if (onTop) {
-                mDefaultDisplay.positionChildAtTop(stack, false /* includingParents */);
+                mDefaultDisplay.positionStackAtTop(stack, false /* includingParents */);
             } else {
-                mDefaultDisplay.positionChildAtBottom(stack);
+                mDefaultDisplay.positionStackAtBottom(stack);
             }
         } else {
             stack = new StackBuilder(mRootActivityContainer)
@@ -834,7 +834,7 @@
                     .setCreateActivity(true)
                     .build();
         }
-        return (T) stack;
+        return stack;
     }
 
     @Test
@@ -1051,7 +1051,7 @@
         StackOrderChangedListener listener = new StackOrderChangedListener();
         mDefaultDisplay.registerStackOrderChangedListener(listener);
         try {
-            mDefaultDisplay.removeChild(mStack);
+            mDefaultDisplay.removeStack(mStack);
         } finally {
             mDefaultDisplay.unregisterStackOrderChangedListener(listener);
         }
@@ -1060,12 +1060,12 @@
 
     @Test
     public void testStackOrderChangedOnAddPositionStack() {
-        mDefaultDisplay.removeChild(mStack);
+        mDefaultDisplay.removeStack(mStack);
 
         StackOrderChangedListener listener = new StackOrderChangedListener();
         mDefaultDisplay.registerStackOrderChangedListener(listener);
         try {
-            mDefaultDisplay.addChild(mStack, 0);
+            mDefaultDisplay.addStack(mStack, 0);
         } finally {
             mDefaultDisplay.unregisterStackOrderChangedListener(listener);
         }
@@ -1080,7 +1080,7 @@
                     mDefaultDisplay, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
                     true /* onTop */);
             mDefaultDisplay.registerStackOrderChangedListener(listener);
-            mDefaultDisplay.positionChildAtBottom(fullscreenStack1);
+            mDefaultDisplay.positionStackAtBottom(fullscreenStack1);
         } finally {
             mDefaultDisplay.unregisterStackOrderChangedListener(listener);
         }
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
index c712d6d..d5fdf98 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
@@ -517,8 +517,8 @@
     }
 
     private void assertNoTasks(ActivityDisplay display) {
-        for (int i = display.getChildCount() - 1; i >= 0; --i) {
-            final ActivityStack stack = display.getChildAt(i);
+        for (int i = display.getStackCount() - 1; i >= 0; --i) {
+            final ActivityStack stack = display.getStackAt(i);
             assertThat(stack.getAllTasks()).isEmpty();
         }
     }
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 7322ac3..0021cc5 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
@@ -203,6 +203,15 @@
         }
 
         ActivityRecord build() {
+            try {
+                mService.deferWindowLayout();
+                return buildInner();
+            } finally {
+                mService.continueWindowLayout();
+            }
+        }
+
+        ActivityRecord buildInner() {
             if (mComponent == null) {
                 final int id = sCurrentActivityId++;
                 mComponent = ComponentName.createRelative(DEFAULT_COMPONENT_PACKAGE_NAME,
@@ -236,7 +245,7 @@
 
             ActivityOptions options = null;
             if (mLaunchTaskBehind) {
-                options =  ActivityOptions.makeTaskLaunchBehind();
+                options = ActivityOptions.makeTaskLaunchBehind();
             }
 
             final ActivityRecord activity = new ActivityRecord(mService, null /* caller */,
@@ -399,11 +408,18 @@
             return this;
         }
 
+        // TODO(display-merge): Remove
         StackBuilder setDisplay(ActivityDisplay display) {
             mDisplay = display;
             return this;
         }
 
+        StackBuilder setDisplay(DisplayContent display) {
+            // TODO(display-merge): Remove cast
+            mDisplay = (ActivityDisplay) display;
+            return this;
+        }
+
         StackBuilder setOnTop(boolean onTop) {
             mOnTop = onTop;
             return this;
diff --git a/services/tests/wmtests/src/com/android/server/wm/BoundsAnimationControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/BoundsAnimationControllerTests.java
index beec1a8..0ad0f95 100644
--- a/services/tests/wmtests/src/com/android/server/wm/BoundsAnimationControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/BoundsAnimationControllerTests.java
@@ -47,6 +47,7 @@
 
 import org.junit.Before;
 import org.junit.Test;
+import org.junit.runner.RunWith;
 
 /**
  * Test class for {@link BoundsAnimationController} to ensure that it sends the right callbacks
@@ -63,6 +64,7 @@
  */
 @SmallTest
 @Presubmit
+@RunWith(WindowTestRunner.class)
 public class BoundsAnimationControllerTests extends WindowTestsBase {
 
     /**
diff --git a/services/tests/wmtests/src/com/android/server/wm/DimmerTests.java b/services/tests/wmtests/src/com/android/server/wm/DimmerTests.java
index 73420a0..0aa6961 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DimmerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DimmerTests.java
@@ -36,12 +36,14 @@
 
 import org.junit.Before;
 import org.junit.Test;
+import org.junit.runner.RunWith;
 
 /**
  * Build/Install/Run:
  *  atest FrameworksServicesTests:DimmerTests
  */
 @Presubmit
+@RunWith(WindowTestRunner.class)
 public class DimmerTests extends WindowTestsBase {
 
     private static class TestWindowContainer extends WindowContainer<TestWindowContainer> {
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
index 5070fb6..5fbfd7d 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -708,13 +708,13 @@
 
         final ActivityStack stack =
                 new ActivityTestsBase.StackBuilder(mWm.mAtmService.mRootActivityContainer)
-                        .setDisplay(dc.mActivityDisplay)
+                        .setDisplay(dc)
                         .build();
         doReturn(true).when(stack).isVisible();
 
         final ActivityStack freeformStack =
                 new ActivityTestsBase.StackBuilder(mWm.mAtmService.mRootActivityContainer)
-                        .setDisplay(dc.mActivityDisplay)
+                        .setDisplay(dc)
                         .setWindowingMode(WINDOWING_MODE_FREEFORM)
                         .build();
         doReturn(true).when(freeformStack).isVisible();
@@ -742,7 +742,7 @@
 
         final ActivityStack stack =
                 new ActivityTestsBase.StackBuilder(mWm.mAtmService.mRootActivityContainer)
-                        .setDisplay(dc.mActivityDisplay).build();
+                        .setDisplay(dc).build();
         final ActivityRecord activity = stack.topTask().getTopNonFinishingActivity();
 
         activity.setRequestedOrientation(newOrientation);
@@ -764,12 +764,13 @@
 
         final ActivityStack stack =
                 new ActivityTestsBase.StackBuilder(mWm.mAtmService.mRootActivityContainer)
-                        .setDisplay(dc.mActivityDisplay).build();
+                        .setDisplay(dc).build();
         final ActivityRecord activity = stack.topTask().getTopNonFinishingActivity();
 
         activity.setRequestedOrientation(newOrientation);
 
-        verify(dc.mActivityDisplay, never()).updateDisplayOverrideConfigurationLocked(any(),
+        // TODO(display-merge): Remove cast
+        verify((ActivityDisplay) dc, never()).updateDisplayOverrideConfigurationLocked(any(),
                 eq(activity), anyBoolean(), same(null));
         assertEquals(dc.getDisplayRotation().getUserRotation(), dc.getRotation());
     }
@@ -939,6 +940,7 @@
         final DisplayContent displayContent = createNewDisplay();
         Mockito.doReturn(mockLogger).when(displayContent).getMetricsLogger();
         Mockito.doReturn(oldConfig).doReturn(newConfig).when(displayContent).getConfiguration();
+        doNothing().when(displayContent).preOnConfigurationChanged();
 
         displayContent.onConfigurationChanged(newConfig);
 
@@ -958,12 +960,12 @@
         Mockito.doCallRealMethod().when(dr).updateRotationUnchecked(anyBoolean());
         Mockito.doReturn(ROTATION_90).when(dr).rotationForOrientation(anyInt(), anyInt());
         final boolean[] continued = new boolean[1];
-        spyOn(dc.mActivityDisplay);
+        // TODO(display-merge): Remove cast
         Mockito.doAnswer(
                 invocation -> {
                     continued[0] = true;
                     return true;
-                }).when(dc.mActivityDisplay).updateDisplayOverrideConfigurationLocked();
+                }).when((ActivityDisplay) dc).updateDisplayOverrideConfigurationLocked();
         final boolean[] called = new boolean[1];
         mWm.mDisplayRotationController =
                 new IDisplayWindowRotationController.Stub() {
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyInsetsTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyInsetsTests.java
index 6767465..f754c59 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyInsetsTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyInsetsTests.java
@@ -32,9 +32,11 @@
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ErrorCollector;
+import org.junit.runner.RunWith;
 
 @SmallTest
 @Presubmit
+@RunWith(WindowTestRunner.class)
 public class DisplayPolicyInsetsTests extends DisplayPolicyTestsBase {
 
     @Rule
diff --git a/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java b/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java
index 79ad0c4..9e5d9da 100644
--- a/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java
@@ -46,6 +46,7 @@
 
 import org.junit.Before;
 import org.junit.Test;
+import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
 
 import java.io.File;
@@ -63,6 +64,7 @@
  */
 @MediumTest
 @Presubmit
+@RunWith(WindowTestRunner.class)
 public class LaunchParamsPersisterTests extends ActivityTestsBase {
     private static final int TEST_USER_ID = 3;
     private static final int ALTERNATIVE_USER_ID = 0;
diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
index 4f2d5d2..9f97c48 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
@@ -977,9 +977,9 @@
     private void assertNotRestoreTask(Runnable action) {
         // Verify stack count doesn't change because task with fullscreen mode and standard type
         // would have its own stack.
-        final int orignalStackCount = mDisplay.getChildCount();
+        final int originalStackCount = mDisplay.getStackCount();
         action.run();
-        assertEquals(orignalStackCount, mDisplay.getChildCount());
+        assertEquals(originalStackCount, mDisplay.getStackCount());
     }
 
     @Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
index 1abd366..2374847 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
@@ -138,7 +138,8 @@
     @Test
     public void testIncludedApps_expectTargetAndVisible() {
         mWm.setRecentsAnimationController(mController);
-        final ActivityStack homeStack = mDisplayContent.mActivityDisplay.getOrCreateStack(
+        // TODO(display-merge): Remove cast
+        final ActivityStack homeStack = ((ActivityDisplay) mDisplayContent).getOrCreateStack(
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, ON_TOP);
         final ActivityRecord homeActivity =
                 new ActivityTestsBase.ActivityBuilder(mWm.mAtmService)
@@ -163,7 +164,8 @@
     @Test
     public void testWallpaperIncluded_expectTarget() throws Exception {
         mWm.setRecentsAnimationController(mController);
-        final ActivityStack homeStack = mDisplayContent.mActivityDisplay.getOrCreateStack(
+        // TODO(display-merge): Remove cast
+        final ActivityStack homeStack = ((ActivityDisplay) mDisplayContent).getOrCreateStack(
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, ON_TOP);
         final ActivityRecord homeAppWindow =
                 new ActivityTestsBase.ActivityBuilder(mWm.mAtmService)
@@ -192,7 +194,8 @@
     @Test
     public void testWallpaperAnimatorCanceled_expectAnimationKeepsRunning() throws Exception {
         mWm.setRecentsAnimationController(mController);
-        final ActivityStack homeStack = mDisplayContent.mActivityDisplay.getOrCreateStack(
+        // TODO(display-merge): Remove cast
+        final ActivityStack homeStack = ((ActivityDisplay) mDisplayContent).getOrCreateStack(
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, ON_TOP);
         final ActivityRecord homeActivity =
                 new ActivityTestsBase.ActivityBuilder(mWm.mAtmService)
@@ -223,7 +226,8 @@
     @Test
     public void testFinish_expectTargetAndWallpaperAdaptersRemoved() {
         mWm.setRecentsAnimationController(mController);
-        final ActivityStack homeStack = mDisplayContent.mActivityDisplay.getOrCreateStack(
+        // TODO(display-merge): Remove cast
+        final ActivityStack homeStack = ((ActivityDisplay) mDisplayContent).getOrCreateStack(
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, ON_TOP);
         final ActivityRecord homeActivity =
                 new ActivityTestsBase.ActivityBuilder(mWm.mAtmService)
diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java
index e67380c..4abab63 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java
@@ -119,7 +119,7 @@
         final ActivityDisplay defaultDisplay = mRootActivityContainer.getDefaultDisplay();
         final ActivityStack homeStack =
                 defaultDisplay.getStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME);
-        defaultDisplay.positionChildAtTop(homeStack, false /* includingParents */);
+        defaultDisplay.positionStackAtTop(homeStack, false /* includingParents */);
         ActivityRecord topRunningHomeActivity = homeStack.topRunningActivityLocked();
         if (topRunningHomeActivity == null) {
             topRunningHomeActivity = new ActivityBuilder(mService)
diff --git a/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java
index e353903..112479b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java
@@ -54,6 +54,7 @@
 
 import org.junit.Before;
 import org.junit.Test;
+import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
@@ -64,6 +65,7 @@
  */
 @SmallTest
 @Presubmit
+@RunWith(WindowTestRunner.class)
 public class RemoteAnimationControllerTest extends WindowTestsBase {
 
     @Mock SurfaceControl mMockLeash;
@@ -84,7 +86,7 @@
         when(mMockRunner.asBinder()).thenReturn(new Binder());
         mAdapter = new RemoteAnimationAdapter(mMockRunner, 100, 50, true /* changeNeedsSnapshot */);
         mAdapter.setCallingPidUid(123, 456);
-        mWm.mH.runWithScissors(() -> mHandler = new TestHandler(null, mClock), 0);
+        runWithScissors(mWm.mH, () -> mHandler = new TestHandler(null, mClock), 0);
         mController = new RemoteAnimationController(mWm, mAdapter, mHandler);
     }
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
index 4257249..59c7c02 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
@@ -226,20 +226,20 @@
     @Test
     public void testRemovingStackOnAppCrash() {
         final ActivityDisplay defaultDisplay = mRootActivityContainer.getDefaultDisplay();
-        final int originalStackCount = defaultDisplay.getChildCount();
+        final int originalStackCount = defaultDisplay.getStackCount();
         final ActivityStack stack = mRootActivityContainer.getDefaultDisplay().createStack(
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, false /* onTop */);
         final ActivityRecord firstActivity = new ActivityBuilder(mService).setCreateTask(true)
                 .setStack(stack).build();
 
-        assertEquals(originalStackCount + 1, defaultDisplay.getChildCount());
+        assertEquals(originalStackCount + 1, defaultDisplay.getStackCount());
 
         // Let's pretend that the app has crashed.
         firstActivity.app.setThread(null);
         mRootActivityContainer.finishTopCrashedActivities(firstActivity.app, "test");
 
         // Verify that the stack was removed.
-        assertEquals(originalStackCount, defaultDisplay.getChildCount());
+        assertEquals(originalStackCount, defaultDisplay.getStackCount());
     }
 
     @Test
@@ -392,7 +392,7 @@
                 ACTIVITY_TYPE_STANDARD, false /* onTop */));
         final Task task = new TaskBuilder(mSupervisor).setStack(targetStack).build();
         final ActivityRecord activity = new ActivityBuilder(mService).setTask(task).build();
-        display.positionChildAtBottom(targetStack);
+        display.positionStackAtBottom(targetStack);
 
         // Assume the stack is not at the topmost position (e.g. behind always-on-top stacks) but it
         // is the current top focused stack.
@@ -493,7 +493,7 @@
         final Task task = new TaskBuilder(mSupervisor).setStack(targetStack).build();
         final ActivityRecord activity = new ActivityBuilder(mService).setTask(task).build();
         activity.setState(ActivityState.RESUMED, "test");
-        display.positionChildAtBottom(targetStack);
+        display.positionStackAtBottom(targetStack);
 
         // Assume the stack is at the topmost position
         assertFalse(targetStack.isTopStackOnDisplay());
diff --git a/services/tests/wmtests/src/com/android/server/wm/RunningTasksTest.java b/services/tests/wmtests/src/com/android/server/wm/RunningTasksTest.java
index eba2bc8..5c9ccae 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RunningTasksTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RunningTasksTest.java
@@ -74,7 +74,7 @@
         final int numTasks = 10;
         int activeTime = 0;
         for (int i = 0; i < numTasks; i++) {
-            createTask(display.getChildAt(i % numStacks), ".Task" + i, i, activeTime++);
+            createTask(display.getStackAt(i % numStacks), ".Task" + i, i, activeTime++);
         }
 
         // Ensure that the latest tasks were returned in order of decreasing last active time,
diff --git a/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimationRunnerTest.java b/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimationRunnerTest.java
index c483489..3008a75 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimationRunnerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimationRunnerTest.java
@@ -50,6 +50,7 @@
 
 import org.junit.Before;
 import org.junit.Test;
+import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
@@ -63,6 +64,7 @@
  */
 @SmallTest
 @Presubmit
+@RunWith(WindowTestRunner.class)
 public class SurfaceAnimationRunnerTest extends WindowTestsBase {
 
     @Mock SurfaceControl mMockSurface;
@@ -98,6 +100,7 @@
         verify(mMockTransaction, atLeastOnce()).setMatrix(eq(mMockSurface), eq(m), any());
         verify(mMockTransaction, atLeastOnce()).setAlpha(eq(mMockSurface), eq(1.0f));
 
+        waitHandlerIdle(SurfaceAnimationThread.getHandler());
         mFinishCallbackLatch.await(1, SECONDS);
         assertFinishCallbackCalled();
 
@@ -176,6 +179,7 @@
         assertTrue(mSurfaceAnimationRunner.mRunningAnimations.isEmpty());
         mSurfaceAnimationRunner.continueStartingAnimations();
         waitUntilNextFrame();
+        waitHandlerIdle(SurfaceAnimationThread.getHandler());
         assertFalse(mSurfaceAnimationRunner.mRunningAnimations.isEmpty());
         mFinishCallbackLatch.await(1, SECONDS);
         assertFinishCallbackCalled();
diff --git a/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimatorTest.java b/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimatorTest.java
index 979aab6..2894241 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimatorTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimatorTest.java
@@ -44,6 +44,7 @@
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
+import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
@@ -56,6 +57,7 @@
  */
 @SmallTest
 @Presubmit
+@RunWith(WindowTestRunner.class)
 public class SurfaceAnimatorTest extends WindowTestsBase {
 
     @Mock AnimationAdapter mSpec;
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java
index 27ebd5a..9a91efe 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java
@@ -53,6 +53,7 @@
 
 import org.junit.Before;
 import org.junit.Test;
+import org.junit.runner.RunWith;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -66,6 +67,7 @@
  */
 @SmallTest
 @Presubmit
+@RunWith(WindowTestRunner.class)
 public class TaskLaunchParamsModifierTests extends ActivityTestsBase {
     private static final Rect DISPLAY_BOUNDS = new Rect(/* left */ 0, /* top */ 0,
             /* right */ 1920, /* bottom */ 1080);
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskPositionerTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskPositionerTests.java
index 9275512b..8970571 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskPositionerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskPositionerTests.java
@@ -19,7 +19,6 @@
 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
 import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
 
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
 import static com.android.server.wm.TaskPositioner.MIN_ASPECT;
 import static com.android.server.wm.WindowManagerService.dipToPixel;
@@ -33,7 +32,6 @@
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
 
-import android.app.IActivityTaskManager;
 import android.graphics.Rect;
 import android.platform.test.annotations.Presubmit;
 import android.util.DisplayMetrics;
@@ -46,6 +44,7 @@
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
+import org.junit.runner.RunWith;
 
 /**
  * Tests for the {@link TaskPositioner} class.
@@ -55,6 +54,7 @@
  */
 @SmallTest
 @Presubmit
+@RunWith(WindowTestRunner.class)
 public class TaskPositionerTests extends WindowTestsBase {
 
     private static final boolean DEBUGGING = false;
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotCacheTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotCacheTest.java
index f595e05..0274b7d 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotCacheTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotCacheTest.java
@@ -18,21 +18,21 @@
 
 import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
 
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
 import static junit.framework.Assert.assertEquals;
 
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import android.app.ActivityManager.TaskSnapshot;
 import android.platform.test.annotations.Presubmit;
 
 import androidx.test.filters.SmallTest;
 
-import android.app.ActivityManager.TaskSnapshot;
-
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
 import org.junit.Before;
 import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
 
 /**
  * Test class for {@link TaskSnapshotCache}.
@@ -42,6 +42,7 @@
  */
 @SmallTest
 @Presubmit
+@RunWith(WindowTestRunner.class)
 public class TaskSnapshotCacheTest extends TaskSnapshotPersisterTestBase {
 
     private TaskSnapshotCache mCache;
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotControllerTest.java
index 3b11003..6ebaf29 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotControllerTest.java
@@ -33,6 +33,7 @@
 import com.google.android.collect.Sets;
 
 import org.junit.Test;
+import org.junit.runner.RunWith;
 
 /**
  * Test class for {@link TaskSnapshotController}.
@@ -42,6 +43,7 @@
  */
 @SmallTest
 @Presubmit
+@RunWith(WindowTestRunner.class)
 public class TaskSnapshotControllerTest extends WindowTestsBase {
 
     @Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java
index b29453a..b5a5790 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java
@@ -38,6 +38,7 @@
 import com.android.server.wm.TaskSnapshotPersister.RemoveObsoleteFilesQueueItem;
 
 import org.junit.Test;
+import org.junit.runner.RunWith;
 
 import java.io.File;
 import java.util.function.Predicate;
@@ -50,6 +51,7 @@
  */
 @MediumTest
 @Presubmit
+@RunWith(WindowTestRunner.class)
 public class TaskSnapshotPersisterLoaderTest extends TaskSnapshotPersisterTestBase {
 
     private static final Rect TEST_INSETS = new Rect(10, 20, 30, 40);
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java
index 74db820..817344f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java
@@ -47,6 +47,7 @@
 import com.android.server.wm.TaskSnapshotSurface.Window;
 
 import org.junit.Test;
+import org.junit.runner.RunWith;
 
 /**
  * Test class for {@link TaskSnapshotSurface}.
@@ -56,6 +57,7 @@
  */
 @SmallTest
 @Presubmit
+@RunWith(WindowTestRunner.class)
 public class TaskSnapshotSurfaceTest extends WindowTestsBase {
 
     private TaskSnapshotSurface mSurface;
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowConfigurationTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowConfigurationTests.java
index 64ac547..c359fb1 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowConfigurationTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowConfigurationTests.java
@@ -48,6 +48,7 @@
 
 import org.junit.Before;
 import org.junit.Test;
+import org.junit.runner.RunWith;
 
 /**
  * Test class to for {@link android.app.WindowConfiguration}.
@@ -57,6 +58,7 @@
  */
 @SmallTest
 @Presubmit
+@RunWith(WindowTestRunner.class)
 public class WindowConfigurationTests extends WindowTestsBase {
     private Rect mParentBounds;
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java
index 8140045..13cf22d 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java
@@ -56,6 +56,7 @@
 import androidx.test.filters.SmallTest;
 
 import org.junit.Test;
+import org.junit.runner.RunWith;
 import org.mockito.Mockito;
 
 import java.util.Comparator;
@@ -68,6 +69,7 @@
  */
 @SmallTest
 @Presubmit
+@RunWith(WindowTestRunner.class)
 public class WindowContainerTests extends WindowTestsBase {
 
     @Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowContainerTraversalTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTraversalTests.java
index 4b666f5..8936aad 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowContainerTraversalTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTraversalTests.java
@@ -31,6 +31,7 @@
 import androidx.test.filters.SmallTest;
 
 import org.junit.Test;
+import org.junit.runner.RunWith;
 
 import java.util.function.Consumer;
 
@@ -42,6 +43,7 @@
  */
 @SmallTest
 @Presubmit
+@RunWith(WindowTestRunner.class)
 public class WindowContainerTraversalTests extends WindowTestsBase {
 
     @Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowManagerSettingsTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowManagerSettingsTests.java
index 1c9eed2..ce6efdf 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowManagerSettingsTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowManagerSettingsTests.java
@@ -32,6 +32,7 @@
 import androidx.test.filters.SmallTest;
 
 import org.junit.Test;
+import org.junit.runner.RunWith;
 
 /**
  * Test for {@link WindowManagerService.SettingsObserver}.
@@ -40,6 +41,7 @@
  *  atest WmTests:WindowManagerSettingsTests
  */
 @SmallTest
+@RunWith(WindowTestRunner.class)
 public class WindowManagerSettingsTests extends WindowTestsBase {
 
     @Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
index 437b84b..22ba90b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
@@ -320,7 +320,7 @@
         synchronized (mWm.mGlobalLock) {
             return new ActivityTestsBase.StackBuilder(
                     dc.mWmService.mAtmService.mRootActivityContainer)
-                    .setDisplay(dc.mActivityDisplay)
+                    .setDisplay(dc)
                     .setWindowingMode(windowingMode)
                     .setActivityType(activityType)
                     .setCreateActivity(false)
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTokenTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowTokenTests.java
index 4cdbea0..e6aed49 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTokenTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTokenTests.java
@@ -31,6 +31,7 @@
 import androidx.test.filters.SmallTest;
 
 import org.junit.Test;
+import org.junit.runner.RunWith;
 
 /**
  * Tests for the {@link WindowToken} class.
@@ -40,6 +41,7 @@
  */
 @SmallTest
 @Presubmit
+@RunWith(WindowTestRunner.class)
 public class WindowTokenTests extends WindowTestsBase {
 
     @Test