Unify RootActivityContainer and RootWindowContainer (80/n)

Bug: 80414790
Test: Existing tests pass
Change-Id: I9677de2ea5d50337f6f2902545ff993b5fb9c496
diff --git a/core/proto/android/server/activitymanagerservice.proto b/core/proto/android/server/activitymanagerservice.proto
index 9f31b59..c79f314 100644
--- a/core/proto/android/server/activitymanagerservice.proto
+++ b/core/proto/android/server/activitymanagerservice.proto
@@ -60,7 +60,7 @@
 message ActivityStackSupervisorProto {
     option (.android.msg_privacy).dest = DEST_AUTOMATIC;
 
-    optional .com.android.server.wm.ConfigurationContainerProto configuration_container = 1;
+    optional .com.android.server.wm.ConfigurationContainerProto configuration_container = 1 [deprecated=true];
     repeated ActivityDisplayProto displays = 2;
     optional KeyguardControllerProto keyguard_controller = 3;
     // TODO(b/111541062): Focused stack and resumed activity are now per-display. Topmost instances
@@ -71,6 +71,7 @@
     // know what activity types to check for when invoking splitscreen multi-window.
     optional bool is_home_recents_component = 6;
     repeated .com.android.server.wm.IdentifierProto pending_activities = 7;
+    optional .com.android.server.wm.RootWindowContainerProto root_window_container = 8;
 }
 
 /* represents ActivityStackSupervisor.ActivityDisplay */
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 331386f..0864c9c 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -825,13 +825,7 @@
         mAppWarnings = createAppWarnings(mUiContext, mH, mUiHandler, systemDir);
         mCompatModePackages = new CompatModePackages(this, systemDir, mH);
         mPendingIntentController = intentController;
-
-        mTempConfig.setToDefaults();
-        mTempConfig.setLocales(LocaleList.getDefault());
-        mConfigurationSeq = mTempConfig.seq = 1;
         mStackSupervisor = createStackSupervisor();
-        mRootActivityContainer = new RootActivityContainer(this);
-        mRootActivityContainer.onConfigurationChanged(mTempConfig);
 
         mTaskChangeNotificationController =
                 new TaskChangeNotificationController(mGlobalLock, mStackSupervisor, mH);
@@ -868,6 +862,12 @@
     public void setWindowManager(WindowManagerService wm) {
         synchronized (mGlobalLock) {
             mWindowManager = wm;
+            // TODO(merge-root): Remove cast
+            mRootActivityContainer = (RootActivityContainer) wm.mRoot;
+            mTempConfig.setToDefaults();
+            mTempConfig.setLocales(LocaleList.getDefault());
+            mConfigurationSeq = mTempConfig.seq = 1;
+            mRootActivityContainer.onConfigurationChanged(mTempConfig);
             mLockTaskController.setWindowManager(wm);
             mStackSupervisor.setWindowManager(wm);
             mRootActivityContainer.setWindowManager(wm);
@@ -5216,7 +5216,11 @@
      * also corresponds to the merged configuration of the default display.
      */
     Configuration getGlobalConfiguration() {
-        return mRootActivityContainer.getConfiguration();
+        // Return default configuration before mRootActivityContainer initialized, which happens
+        // while initializing process record for system, see {@link
+        // ActivityManagerService#setSystemProcess}.
+        return mRootActivityContainer != null ? mRootActivityContainer.getConfiguration()
+                : new Configuration();
     }
 
     boolean updateConfigurationLocked(Configuration values, ActivityRecord starting,
@@ -7277,6 +7281,11 @@
         @Override
         public WindowProcessController getTopApp() {
             synchronized (mGlobalLockWithoutBoost) {
+                if (mRootActivityContainer == null) {
+                    // Return null if mRootActivityContainer not yet initialize, while update
+                    // oomadj after AMS created.
+                    return null;
+                }
                 final ActivityRecord top = mRootActivityContainer.getTopResumedActivity();
                 return top != null ? top.app : null;
             }
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 5a5c102..391bfbe 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -1038,7 +1038,7 @@
         onDisplayChanged(this);
 
         // Add itself as a child to the root container.
-        mWmService.mRoot.addChild(this, null);
+        mWmService.mRoot.addChild(this, POSITION_BOTTOM);
 
         // TODO(b/62541591): evaluate whether this is the best spot to declare the
         // {@link DisplayContent} ready for use.
@@ -6410,7 +6410,6 @@
             stack.removeIfPossible();
         } else if (getTopStack() == null) {
             removeIfPossible();
-            mRootActivityContainer.removeChild(this);
             mRootActivityContainer.mStackSupervisor
                     .getKeyguardController().onDisplayRemoved(mDisplayId);
         }
diff --git a/services/core/java/com/android/server/wm/LockTaskController.java b/services/core/java/com/android/server/wm/LockTaskController.java
index 7a72b43..0443c40 100644
--- a/services/core/java/com/android/server/wm/LockTaskController.java
+++ b/services/core/java/com/android/server/wm/LockTaskController.java
@@ -653,7 +653,7 @@
             taskChanged = true;
         }
 
-        mSupervisor.mRootActivityContainer.mRootWindowContainer.forAllTasks(Task::setLockTaskAuth);
+        mSupervisor.mRootActivityContainer.forAllTasks(Task::setLockTaskAuth);
 
         final ActivityRecord r = mSupervisor.mRootActivityContainer.topRunningActivity();
         final Task task = (r != null) ? r.getTask() : null;
diff --git a/services/core/java/com/android/server/wm/RootActivityContainer.java b/services/core/java/com/android/server/wm/RootActivityContainer.java
index f778e4d..4ac918c 100644
--- a/services/core/java/com/android/server/wm/RootActivityContainer.java
+++ b/services/core/java/com/android/server/wm/RootActivityContainer.java
@@ -36,13 +36,13 @@
 import static android.view.WindowManager.TRANSIT_CRASHING_ACTIVITY_CLOSE;
 import static android.view.WindowManager.TRANSIT_SHOW_SINGLE_TASK_DISPLAY;
 
-import static com.android.server.am.ActivityStackSupervisorProto.CONFIGURATION_CONTAINER;
 import static com.android.server.am.ActivityStackSupervisorProto.DISPLAYS;
 import static com.android.server.am.ActivityStackSupervisorProto.FOCUSED_STACK_ID;
 import static com.android.server.am.ActivityStackSupervisorProto.IS_HOME_RECENTS_COMPONENT;
 import static com.android.server.am.ActivityStackSupervisorProto.KEYGUARD_CONTROLLER;
 import static com.android.server.am.ActivityStackSupervisorProto.PENDING_ACTIVITIES;
 import static com.android.server.am.ActivityStackSupervisorProto.RESUMED_ACTIVITY;
+import static com.android.server.am.ActivityStackSupervisorProto.ROOT_WINDOW_CONTAINER;
 import static com.android.server.wm.ActivityStack.ActivityState.PAUSED;
 import static com.android.server.wm.ActivityStack.ActivityState.RESUMED;
 import static com.android.server.wm.ActivityStack.ActivityState.STOPPED;
@@ -135,7 +135,7 @@
  * TODO: This class is mostly temporary to separate things out of ActivityStackSupervisor.java. The
  * intention is to have this merged with RootWindowContainer.java as part of unifying the hierarchy.
  */
-class RootActivityContainer extends ConfigurationContainer
+class RootActivityContainer extends RootWindowContainer
         implements DisplayManager.DisplayListener {
 
     private static final String TAG = TAG_WITH_CLASS_NAME ? "RootActivityContainer" : TAG_ATM;
@@ -168,14 +168,6 @@
     WindowManagerService mWindowManager;
     DisplayManager mDisplayManager;
     private DisplayManagerInternal mDisplayManagerInternal;
-    // TODO(root-unify): Remove after object merge with RootWindowContainer.
-    RootWindowContainer mRootWindowContainer;
-
-    /**
-     * List of displays which contain activities, sorted by z-order.
-     * The last entry in the list is the topmost.
-     */
-    private final ArrayList<DisplayContent> mDisplayContents = new ArrayList<>();
 
     /** Reference to default display so we can quickly look it up. */
     private DisplayContent mDefaultDisplay;
@@ -337,7 +329,8 @@
         }
     }
 
-    RootActivityContainer(ActivityTaskManagerService service) {
+    RootActivityContainer(ActivityTaskManagerService service, WindowManagerService wmService) {
+        super(wmService);
         mService = service;
         mStackSupervisor = service.mStackSupervisor;
         mStackSupervisor.mRootActivityContainer = this;
@@ -345,8 +338,6 @@
 
     void setWindowManager(WindowManagerService wm) {
         mWindowManager = wm;
-        mRootWindowContainer = mWindowManager.mRoot;
-        mRootWindowContainer.setRootActivityContainer(this);
         mDisplayManager = mService.mContext.getSystemService(DisplayManager.class);
         mDisplayManager.registerDisplayListener(this, mService.mUiHandler);
         mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
@@ -358,14 +349,13 @@
             if (displayContent.mDisplayId == DEFAULT_DISPLAY) {
                 mDefaultDisplay = displayContent;
             }
-            addChild(displayContent, DisplayContent.POSITION_TOP);
         }
         calculateDefaultMinimalSizeOfResizeableTasks();
 
         final DisplayContent defaultDisplay = getDefaultDisplay();
 
         defaultDisplay.getOrCreateStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, ON_TOP);
-        positionChildAt(defaultDisplay, DisplayContent.POSITION_TOP);
+        positionChildAt(POSITION_TOP, defaultDisplay, false /* includingParents */);
     }
 
     // TODO(multi-display): Look at all callpoints to make sure they make sense in multi-display.
@@ -424,7 +414,6 @@
         }
         // The display hasn't been added to ActivityManager yet, create a new record now.
         displayContent = new DisplayContent(display, this);
-        addChild(displayContent, DisplayContent.POSITION_BOTTOM);
         return displayContent;
     }
 
@@ -750,7 +739,7 @@
 
         // Force-update the orientation from the WindowManager, since we need the true configuration
         // to send to the client now.
-        final DisplayContent displayContent = mRootWindowContainer.getDisplayContent(displayId);
+        final DisplayContent displayContent = getDisplayContent(displayId);
         Configuration config = null;
         if (displayContent != null) {
             config = displayContent.updateOrientation(
@@ -1564,57 +1553,11 @@
     }
 
     @Override
-    protected int getChildCount() {
-        return mDisplayContents.size();
-    }
-
-    @Override
-    protected DisplayContent getChildAt(int index) {
-        return mDisplayContents.get(index);
-    }
-
-    @Override
-    protected ConfigurationContainer getParent() {
-        return null;
-    }
-
-    // TODO: remove after object merge with RootWindowContainer
-    void onChildPositionChanged(DisplayContent display, int position) {
-        // Assume AM lock is held from positionChildAt of controller in each hierarchy.
-        if (display != null) {
-            positionChildAt(display, position);
-        }
-    }
-
-    /** Change the z-order of the given display. */
-    private void positionChildAt(DisplayContent display, int position) {
-        if (position >= mDisplayContents.size()) {
-            position = mDisplayContents.size() - 1;
-        } else if (position < 0) {
-            position = 0;
-        }
-
-        if (mDisplayContents.isEmpty()) {
-            mDisplayContents.add(display);
-        } else if (mDisplayContents.get(position) != display) {
-            mDisplayContents.remove(display);
-            mDisplayContents.add(position, display);
-        }
+    void positionChildAt(int position, DisplayContent child, boolean includingParents) {
+        super.positionChildAt(position, child, includingParents);
         mStackSupervisor.updateTopResumedActivityIfNeeded();
     }
 
-    @VisibleForTesting
-    void addChild(DisplayContent displayContent, int position) {
-        positionChildAt(displayContent, position);
-        mRootWindowContainer.positionChildAt(position, displayContent);
-    }
-
-    void removeChild(DisplayContent displayContent) {
-        // The caller must tell the controller of {@link DisplayContent} to release its container
-        // {@link DisplayContent}. That is done in {@link DisplayContent#releaseSelfIfNeeded}).
-        mDisplayContents.remove(displayContent);
-    }
-
     Configuration getDisplayOverrideConfiguration(int displayId) {
         final DisplayContent displayContent = getDisplayContentOrCreate(displayId);
         if (displayContent == null) {
@@ -1664,7 +1607,7 @@
     }
 
     void addStartingWindowsForVisibleActivities() {
-        mRootWindowContainer.forAllActivities((r) -> {
+        forAllActivities((r) -> {
             if (r.mVisibleRequested) {
                 r.showStartingWindow(null /* prev */, false /* newTask */, true /*taskSwitch*/);
             }
@@ -1676,7 +1619,7 @@
     }
 
     void rankTaskLayersIfNeeded() {
-        if (!mTaskLayersChanged || mRootWindowContainer == null) {
+        if (!mTaskLayersChanged) {
             return;
         }
         mTaskLayersChanged = false;
@@ -1684,7 +1627,7 @@
         final PooledConsumer c = PooledLambda.obtainConsumer(
                 RootActivityContainer::rankTaskLayerForActivity, this,
                 PooledLambda.__(ActivityRecord.class));
-        mRootWindowContainer.forAllActivities(c);
+        forAllActivities(c);
         c.recycle();
     }
 
@@ -1700,7 +1643,7 @@
         final PooledConsumer c = PooledLambda.obtainConsumer(
                 RootActivityContainer::clearOtherAppTimeTrackers,
                 PooledLambda.__(ActivityRecord.class), except);
-        mRootWindowContainer.forAllActivities(c);
+        forAllActivities(c);
         c.recycle();
     }
 
@@ -1748,7 +1691,7 @@
     void handleAppCrash(WindowProcessController app) {
         final PooledConsumer c = PooledLambda.obtainConsumer(
                 RootActivityContainer::handleAppCrash, PooledLambda.__(ActivityRecord.class), app);
-        mRootWindowContainer.forAllActivities(c);
+        forAllActivities(c);
         c.recycle();
     }
 
@@ -1773,7 +1716,7 @@
         final PooledPredicate p = PooledLambda.obtainPredicate(
                 RootActivityContainer::matchesActivity, PooledLambda.__(ActivityRecord.class),
                 userId, compareIntentFilters, intent, cls);
-        final ActivityRecord r = mRootWindowContainer.getActivity(p);
+        final ActivityRecord r = getActivity(p);
         p.recycle();
         return r;
     }
@@ -2123,7 +2066,7 @@
     }
 
     void closeSystemDialogs() {
-        mRootWindowContainer.forAllActivities((r) -> {
+        forAllActivities((r) -> {
             if ((r.info.flags & ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
                 r.finishIfPossible("close-sys", true /* oomAdj */);
             }
@@ -2161,7 +2104,7 @@
             final PooledFunction f = PooledLambda.obtainFunction(
                     FinishDisabledPackageActivitiesHelper::processActivity, this,
                     PooledLambda.__(ActivityRecord.class));
-            mRootWindowContainer.forAllActivities(f);
+            forAllActivities(f);
             f.recycle();
             return mDidSomething;
         }
@@ -2213,7 +2156,7 @@
         final PooledConsumer c = PooledLambda.obtainConsumer(
                 RootActivityContainer::updateActivityApplicationInfo,
                 PooledLambda.__(ActivityRecord.class), aInfo, userId, packageName);
-        mRootWindowContainer.forAllActivities(c);
+        forAllActivities(c);
         c.recycle();
     }
 
@@ -2341,7 +2284,7 @@
             final PooledConsumer c = PooledLambda.obtainConsumer(
                     RootActivityContainer::taskTopActivityIsUser, this, PooledLambda.__(Task.class),
                     userId);
-            mRootWindowContainer.forAllTasks(c);
+            forAllTasks(c);
             c.recycle();
         } finally {
             mService.continueWindowLayout();
@@ -2409,7 +2352,7 @@
 
         final PooledPredicate p = PooledLambda.obtainPredicate(
                 Task::isTaskId, PooledLambda.__(Task.class), id);
-        Task task = mRootWindowContainer.getTask(p);
+        Task task = getTask(p);
         p.recycle();
 
         if (task != null) {
@@ -2621,10 +2564,11 @@
         return printed;
     }
 
-    protected void dumpDebug(ProtoOutputStream proto, long fieldId,
+    @Override
+    public void dumpDebug(ProtoOutputStream proto, long fieldId,
             @WindowTraceLogLevel int logLevel) {
         final long token = proto.start(fieldId);
-        super.dumpDebug(proto, CONFIGURATION_CONTAINER, logLevel);
+        dumpDebugInner(proto, ROOT_WINDOW_CONTAINER, logLevel);
         for (int displayNdx = 0; displayNdx < getChildCount(); ++displayNdx) {
             final DisplayContent displayContent = getChildAt(displayNdx);
             displayContent.dumpDebug(proto, DISPLAYS, logLevel);
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 8b08344..936d643 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -50,7 +50,6 @@
 import static com.android.server.wm.WindowSurfacePlacer.SET_UPDATE_ROTATION;
 import static com.android.server.wm.WindowSurfacePlacer.SET_WALLPAPER_ACTION_PENDING;
 
-import android.annotation.CallSuper;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.Context;
@@ -85,16 +84,12 @@
 import java.util.function.Consumer;
 
 /** Root {@link WindowContainer} for the device. */
-class RootWindowContainer extends WindowContainer<DisplayContent>
-        implements ConfigurationContainerListener {
+class RootWindowContainer extends WindowContainer<DisplayContent> {
     private static final String TAG = TAG_WITH_CLASS_NAME ? "RootWindowContainer" : TAG_WM;
 
     private static final int SET_SCREEN_BRIGHTNESS_OVERRIDE = 1;
     private static final int SET_USER_ACTIVITY_TIMEOUT = 2;
 
-    // TODO: Remove after object merge with RootActivityContainer.
-    private RootActivityContainer mRootActivityContainer;
-
     private Object mLastWindowFreezeSource = null;
     private Session mHoldScreen = null;
     private float mScreenBrightness = -1;
@@ -156,13 +151,6 @@
         mHandler = new MyHandler(service.mH.getLooper());
     }
 
-    void setRootActivityContainer(RootActivityContainer container) {
-        mRootActivityContainer = container;
-        if (container != null) {
-            container.registerConfigurationChangeListener(this);
-        }
-    }
-
     boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows) {
         mTopFocusedAppByProcess.clear();
         boolean changed = false;
@@ -1006,9 +994,7 @@
         }
     }
 
-    @CallSuper
-    @Override
-    public void dumpDebug(ProtoOutputStream proto, long fieldId,
+    public void dumpDebugInner(ProtoOutputStream proto, long fieldId,
             @WindowTraceLogLevel int logLevel) {
         if (logLevel == WindowTraceLogLevel.CRITICAL && !isVisible()) {
             return;
@@ -1037,19 +1023,6 @@
     }
 
     @Override
-    void positionChildAt(int position, DisplayContent child, boolean includingParents) {
-        super.positionChildAt(position, child, includingParents);
-        if (mRootActivityContainer != null) {
-            mRootActivityContainer.onChildPositionChanged(child, position);
-        }
-    }
-
-    void positionChildAt(int position, DisplayContent child) {
-        // Only called from controller so no need to notify the change to controller.
-        super.positionChildAt(position, child, false /* includingParents */);
-    }
-
-    @Override
     void scheduleAnimation() {
         mWmService.scheduleAnimationLocked();
     }
diff --git a/services/core/java/com/android/server/wm/RunningTasks.java b/services/core/java/com/android/server/wm/RunningTasks.java
index 5783713..53c0dd0 100644
--- a/services/core/java/com/android/server/wm/RunningTasks.java
+++ b/services/core/java/com/android/server/wm/RunningTasks.java
@@ -76,7 +76,7 @@
 
         final PooledConsumer c = PooledLambda.obtainConsumer(RunningTasks::processTask, this,
                 PooledLambda.__(Task.class));
-        root.mRootWindowContainer.forAllTasks(c, false);
+        root.forAllTasks(c, false);
         c.recycle();
 
         // Take the first {@param maxNum} tasks and create running task infos for them
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index be41891..4a4d6eb 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -1116,7 +1116,7 @@
         mDisplayWindowSettings = new DisplayWindowSettings(this);
         mPolicy = policy;
         mAnimator = new WindowAnimator(this);
-        mRoot = new RootWindowContainer(this);
+        mRoot = new RootActivityContainer(mAtmService, this);
 
         mWindowPlacerLocked = new WindowSurfacePlacer(this);
         mTaskSnapshotController = new TaskSnapshotController(this);
@@ -5787,7 +5787,7 @@
      */
     void dumpDebugLocked(ProtoOutputStream proto, @WindowTraceLogLevel int logLevel) {
         mPolicy.dumpDebug(proto, POLICY);
-        mRoot.dumpDebug(proto, ROOT_WINDOW_CONTAINER, logLevel);
+        mRoot.dumpDebugInner(proto, ROOT_WINDOW_CONTAINER, logLevel);
         final DisplayContent topFocusedDisplayContent = mRoot.getTopFocusedDisplayContent();
         if (topFocusedDisplayContent.mCurrentFocus != null) {
             topFocusedDisplayContent.mCurrentFocus.writeIdentifierToProto(proto, FOCUSED_WINDOW);
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 7e22dfc..6462d6a 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
@@ -802,7 +802,8 @@
         // Create a secondary display with an activity.
         final TestDisplayContent secondaryDisplay =
                 new TestDisplayContent.Builder(mService, 1000, 1500).build();
-        mRootActivityContainer.addChild(secondaryDisplay, POSITION_TOP);
+        mRootActivityContainer.positionChildAt(POSITION_TOP, secondaryDisplay,
+                false /* includingParents */);
         final ActivityRecord singleTaskActivity = createSingleTaskActivityOn(
                 secondaryDisplay.createStack(WINDOWING_MODE_FULLSCREEN,
                         ACTIVITY_TYPE_STANDARD, false /* onTop */));
diff --git a/services/tests/wmtests/src/com/android/server/wm/LockTaskControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/LockTaskControllerTest.java
index 0cc2626..ef5b8c5 100644
--- a/services/tests/wmtests/src/com/android/server/wm/LockTaskControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/LockTaskControllerTest.java
@@ -135,7 +135,6 @@
 
         mSupervisor.mRecentTasks = mRecentTasks;
         mSupervisor.mRootActivityContainer = mRootActivityContainer;
-        mRootActivityContainer.mRootWindowContainer = mRootWindowContainer;
 
         mLockTaskController = new LockTaskController(mContext, mSupervisor,
                 new ImmediatelyExecuteHandler());
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 07be3e4..5edd725 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java
@@ -101,7 +101,7 @@
 
         doCallRealMethod().when(mRootActivityContainer).ensureActivitiesVisible(
                 any() /* starting */, anyInt() /* configChanges */,
-                anyBoolean() /* preserveWindows */);
+                anyBoolean() /* preserveWindows */, anyBoolean() /* notifyClients */);
 
         RecentsAnimationCallbacks recentsAnimation = startRecentsActivity(
                 mRecentsComponent, true /* getRecentsAnimation */);
@@ -192,7 +192,7 @@
 
         doCallRealMethod().when(mRootActivityContainer).ensureActivitiesVisible(
                 any() /* starting */, anyInt() /* configChanges */,
-                anyBoolean() /* preserveWindows */);
+                anyBoolean() /* preserveWindows */, anyBoolean() /* notifyClients */);
         doReturn(app).when(mService).getProcessController(eq(recentActivity.processName), anyInt());
         ClientLifecycleManager lifecycleManager = mService.getLifecycleManager();
         doNothing().when(lifecycleManager).scheduleTransaction(any());
@@ -355,7 +355,7 @@
         doReturn(TEST_USER_ID).when(mService).getCurrentUserId();
         doCallRealMethod().when(mRootActivityContainer).ensureActivitiesVisible(
                 any() /* starting */, anyInt() /* configChanges */,
-                anyBoolean() /* preserveWindows */);
+                anyBoolean() /* preserveWindows */, anyBoolean() /* notifyClients */);
 
         startRecentsActivity(otherUserHomeActivity.getTask().getBaseIntent().getComponent(),
                 true);
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 2d45a59..05242e2 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
@@ -27,6 +27,7 @@
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.Display.TYPE_VIRTUAL;
 
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
@@ -91,6 +92,7 @@
     public void setUp() throws Exception {
         mFullscreenStack = mRootActivityContainer.getDefaultDisplay().createStack(
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
+        doNothing().when(mService).updateSleepIfNeededLocked();
     }
 
     /**
diff --git a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
index 811f46f..798c2c5 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
@@ -269,6 +269,14 @@
                 mContext, mImService, false, false, mWMPolicy, mAtmService, StubTransaction::new,
                 () -> mock(Surface.class), (unused) -> new MockSurfaceControlBuilder());
         spyOn(mWmService);
+        spyOn(mWmService.mRoot);
+        // Invoked during {@link ActivityStack} creation.
+        doNothing().when((RootActivityContainer) mWmService.mRoot).updateUIDsPresentOnDisplay();
+        // Always keep things awake.
+        doReturn(true).when((RootActivityContainer) mWmService.mRoot).hasAwakeDisplay();
+        // Called when moving activity to pinned stack.
+        doNothing().when((RootActivityContainer) mWmService.mRoot).ensureActivitiesVisible(any(),
+                anyInt(), anyBoolean(), anyBoolean());
 
         // Setup factory classes to prevent calls to native code.
         mTransaction = spy(StubTransaction.class);
@@ -284,8 +292,7 @@
         // Set configuration for default display
         mWmService.getDefaultDisplayContentLocked().reconfigureDisplayLocked();
 
-        // Mock root, some default display, and home stack.
-        spyOn(mWmService.mRoot);
+        // Mock default display, and home stack.
         final DisplayContent display = mAtmService.mRootActivityContainer.getDefaultDisplay();
         // Set default display to be in fullscreen mode. Devices with PC feature may start their
         // default display in freeform mode but some of tests in WmTests have implicit assumption on
@@ -311,9 +318,12 @@
         // Needs to explicitly dispose current static threads because there could be messages
         // scheduled at a later time, and all mocks are invalid when it's executed.
         DisplayThread.dispose();
+        // Dispose SurfaceAnimationThread before AnimationThread does, so it won't create a new
+        // AnimationThread after AnimationThread disposed, see {@link
+        // AnimatorListenerAdapter#onAnimationEnd()}
+        SurfaceAnimationThread.dispose();
         AnimationThread.dispose();
         UiThread.dispose();
-        SurfaceAnimationThread.dispose();
         mInputChannel.dispose();
 
         tearDownLocalServices();
@@ -443,24 +453,12 @@
             spyOn(getLifecycleManager());
             spyOn(getLockTaskController());
             spyOn(getTaskChangeNotificationController());
-            initRootActivityContainerMocks();
 
             AppWarnings appWarnings = getAppWarningsLocked();
             spyOn(appWarnings);
             doNothing().when(appWarnings).onStartActivity(any());
         }
 
-        void initRootActivityContainerMocks() {
-            spyOn(mRootActivityContainer);
-            // Invoked during {@link ActivityStack} creation.
-            doNothing().when(mRootActivityContainer).updateUIDsPresentOnDisplay();
-            // Always keep things awake.
-            doReturn(true).when(mRootActivityContainer).hasAwakeDisplay();
-            // Called when moving activity to pinned stack.
-            doNothing().when(mRootActivityContainer).ensureActivitiesVisible(any(), anyInt(),
-                    anyBoolean());
-        }
-
         @Override
         int handleIncomingUser(int callingPid, int callingUid, int userId, String name) {
             return userId;
diff --git a/services/tests/wmtests/src/com/android/server/wm/TestDisplayContent.java b/services/tests/wmtests/src/com/android/server/wm/TestDisplayContent.java
index 325cea7..ec631f1 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TestDisplayContent.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TestDisplayContent.java
@@ -147,7 +147,6 @@
             final TestDisplayContent newDisplay;
             synchronized (mService.mGlobalLock) {
                 newDisplay = new TestDisplayContent(mService.mStackSupervisor, display);
-                mService.mRootActivityContainer.addChild(newDisplay, mPosition);
             }
             // disable the normal system decorations
             final DisplayPolicy displayPolicy = newDisplay.mDisplayContent.getDisplayPolicy();
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 6f53428..f89e700 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
@@ -129,6 +129,7 @@
                         TYPE_APPLICATION_MEDIA_OVERLAY,
                         "mChildAppWindowBelow");
             }
+
             // Adding a display will cause freezing the display. Make sure to wait until it's
             // unfrozen to not run into race conditions with the tests.
             waitUntilHandlersIdle();