Unify WM test setup for system services (47/n)

Needed before we can unify objects in hierarchy.

Bug: 80414790
Bug: 122846381
Test: Existing test pass
Change-Id: Ib3bca1f7ad2b15b5426d198d3c5608e3cba640f7
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 19c818f..d759be2 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -1480,8 +1480,9 @@
     public ActivityTaskManagerService mActivityTaskManager;
     @VisibleForTesting
     public ActivityTaskManagerInternal mAtmInternal;
+    UriGrantsManagerInternal mUgmInternal;
     @VisibleForTesting
-    public UriGrantsManagerInternal mUgmInternal;
+    public final ActivityManagerInternal mInternal;
     final ActivityThread mSystemThread;
 
     private final class AppDeathRecipient implements IBinder.DeathRecipient {
@@ -2413,6 +2414,8 @@
         mProcStartHandler = null;
         mHiddenApiBlacklist = null;
         mFactoryTest = FACTORY_TEST_OFF;
+        mUgmInternal = LocalServices.getService(UriGrantsManagerInternal.class);
+        mInternal = new LocalService();
     }
 
     // Note: This method is invoked on the main thread but may need to attach various
@@ -2566,6 +2569,7 @@
             Slog.w(TAG, "Setting background thread cpuset failed");
         }
 
+        mInternal = new LocalService();
     }
 
     public void setSystemServiceManager(SystemServiceManager mgr) {
@@ -2583,7 +2587,7 @@
         mBatteryStatsService.publish();
         mAppOpsService.publish(mContext);
         Slog.d("AppOps", "AppOpsService published");
-        LocalServices.addService(ActivityManagerInternal.class, new LocalService());
+        LocalServices.addService(ActivityManagerInternal.class, mInternal);
         mActivityTaskManager.onActivityManagerInternalAdded();
         mUgmInternal.onActivityManagerInternalAdded();
         mPendingIntentController.onActivityManagerInternalAdded();
diff --git a/services/core/java/com/android/server/wm/ActivityDisplay.java b/services/core/java/com/android/server/wm/ActivityDisplay.java
index f1cd721..5a0dfd0 100644
--- a/services/core/java/com/android/server/wm/ActivityDisplay.java
+++ b/services/core/java/com/android/server/wm/ActivityDisplay.java
@@ -41,6 +41,7 @@
 import static com.android.server.am.ActivityDisplayProto.SINGLE_TASK_INSTANCE;
 import static com.android.server.am.ActivityDisplayProto.STACKS;
 import static com.android.server.wm.ActivityStack.ActivityState.RESUMED;
+import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_DESTROYING;
 import static com.android.server.wm.ActivityStack.STACK_VISIBILITY_VISIBLE;
 import static com.android.server.wm.ActivityStackSupervisor.TAG_TASKS;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_STACK;
@@ -173,18 +174,10 @@
         mService = root.mService;
         mDisplayId = display.getDisplayId();
         mDisplay = display;
-        mDisplayContent = createDisplayContent();
+        mDisplayContent = mService.mWindowManager.mRoot.createDisplayContent(mDisplay, this);
         mDisplayContent.reconfigureDisplayLocked();
-        updateBounds();
-    }
-
-    protected DisplayContent createDisplayContent() {
-        return mService.mWindowManager.mRoot.createDisplayContent(mDisplay, this);
-    }
-
-    private void updateBounds() {
-        mDisplay.getRealSize(mTmpDisplaySize);
-        setBounds(0, 0, mTmpDisplaySize.x, mTmpDisplaySize.y);
+        onRequestedOverrideConfigurationChanged(
+                mDisplayContent.getRequestedOverrideConfiguration());
     }
 
     void onDisplayChanged() {
@@ -200,7 +193,8 @@
             }
         }
 
-        updateBounds();
+        mDisplay.getRealSize(mTmpDisplaySize);
+        setBounds(0, 0, mTmpDisplaySize.x, mTmpDisplaySize.y);
         if (mDisplayContent != null) {
             mDisplayContent.updateDisplayInfo();
             mService.mWindowManager.requestTraversal();
@@ -1541,6 +1535,17 @@
         return mSingleTaskInstance;
     }
 
+    @VisibleForTesting
+    void removeAllTasks() {
+        for (int i = getChildCount() - 1; i >= 0; --i) {
+            final ActivityStack stack = getChildAt(i);
+            final ArrayList<TaskRecord> tasks = stack.getAllTasks();
+            for (int j = tasks.size() - 1; j >= 0; --j) {
+                stack.removeTask(tasks.get(j), "removeAllTasks", REMOVE_TASK_MODE_DESTROYING);
+            }
+        }
+    }
+
     public void dump(PrintWriter pw, String prefix) {
         pw.println(prefix + "displayId=" + mDisplayId + " stacks=" + mStacks.size()
                 + (mSingleTaskInstance ? " mSingleTaskInstance" : ""));
diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java
index 12eab50..b7f8d76 100644
--- a/services/core/java/com/android/server/wm/ActivityStack.java
+++ b/services/core/java/com/android/server/wm/ActivityStack.java
@@ -2813,7 +2813,7 @@
         // Launching this app's activity, make sure the app is no longer
         // considered stopped.
         try {
-            AppGlobals.getPackageManager().setPackageStoppedState(
+            mService.getPackageManager().setPackageStoppedState(
                     next.packageName, false, next.mUserId); /* TODO: Verify if correct userid */
         } catch (RemoteException e1) {
         } catch (IllegalArgumentException e) {
diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
index 1c56a10..9639125 100644
--- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
@@ -250,7 +250,7 @@
     RecentTasks mRecentTasks;
 
     /** Helper class to abstract out logic for fetching the set of currently running tasks */
-    RunningTasks mRunningTasks;
+    private RunningTasks mRunningTasks;
 
     final ActivityStackSupervisorHandler mHandler;
     final Looper mLooper;
@@ -444,7 +444,7 @@
         }
 
         mInitialized = true;
-        mRunningTasks = createRunningTasks();
+        setRunningTasks(new RunningTasks());
 
         mActivityMetricsLogger = new ActivityMetricsLogger(this, mService.mContext,
                 mHandler.getLooper());
@@ -485,13 +485,20 @@
     }
 
     void setRecentTasks(RecentTasks recentTasks) {
+        if (mRecentTasks != null) {
+            mRecentTasks.unregisterCallback(this);
+        }
         mRecentTasks = recentTasks;
         mRecentTasks.registerCallback(this);
     }
 
     @VisibleForTesting
-    RunningTasks createRunningTasks() {
-        return new RunningTasks();
+    void setRunningTasks(RunningTasks runningTasks) {
+        mRunningTasks = runningTasks;
+    }
+
+    RunningTasks getRunningTasks() {
+        return mRunningTasks;
     }
 
     /**
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index a3ab27e..88b330b 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -43,7 +43,6 @@
 import static android.content.pm.ConfigurationInfo.GL_ES_VERSION_UNDEFINED;
 import static android.content.pm.PackageManager.FEATURE_ACTIVITIES_ON_SECONDARY_DISPLAYS;
 import static android.content.pm.PackageManager.FEATURE_FREEFORM_WINDOW_MANAGEMENT;
-import static android.content.pm.PackageManager.FEATURE_PC;
 import static android.content.pm.PackageManager.FEATURE_PICTURE_IN_PICTURE;
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
 import static android.content.res.Configuration.UI_MODE_TYPE_TELEVISION;
@@ -361,7 +360,7 @@
     /* Global service lock used by the package the owns this service. */
     final WindowManagerGlobalLock mGlobalLock = new WindowManagerGlobalLock();
     /**
-     * It is the same instance as {@link mGlobalLock}, just declared as a type that the
+     * It is the same instance as {@link #mGlobalLock}, just declared as a type that the
      * locked-region-code-injection does't recognize it. It is used to skip wrapping priority
      * booster for places that are already in the scope of another booster (e.g. computing oom-adj).
      *
@@ -730,7 +729,6 @@
         final boolean forceRtl = Settings.Global.getInt(resolver, DEVELOPMENT_FORCE_RTL, 0) != 0;
         final boolean forceResizable = Settings.Global.getInt(
                 resolver, DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES, 0) != 0;
-        final boolean isPc = mContext.getPackageManager().hasSystemFeature(FEATURE_PC);
 
         // Transfer any global setting for forcing RTL layout, into a System Property
         DisplayProperties.debug_force_rtl(forceRtl);
@@ -761,10 +759,6 @@
                 mSupportsPictureInPicture = false;
                 mSupportsMultiDisplay = false;
             }
-            mWindowManager.setForceResizableTasks(mForceResizableActivities);
-            mWindowManager.setSupportsPictureInPicture(mSupportsPictureInPicture);
-            mWindowManager.setSupportsFreeformWindowManagement(mSupportsFreeformWindowManagement);
-            mWindowManager.setIsPc(isPc);
             mWindowManager.mRoot.onSettingsRetrieved();
             // This happens before any activities are started, so we can change global configuration
             // in-place.
@@ -821,8 +815,7 @@
                 new TaskChangeNotificationController(mGlobalLock, mStackSupervisor, mH);
         mLockTaskController = new LockTaskController(mContext, mStackSupervisor, mH);
         mActivityStartController = new ActivityStartController(this);
-        mRecentTasks = createRecentTasks();
-        mStackSupervisor.setRecentTasks(mRecentTasks);
+        setRecentTasks(new RecentTasks(this, mStackSupervisor));
         mVrController = new VrController(mGlobalLock);
         mKeyguardController = mStackSupervisor.getKeyguardController();
     }
@@ -890,8 +883,10 @@
         return mode == AppOpsManager.MODE_ALLOWED;
     }
 
-    protected RecentTasks createRecentTasks() {
-        return new RecentTasks(this, mStackSupervisor);
+    @VisibleForTesting
+    protected void setRecentTasks(RecentTasks recentTasks) {
+        mRecentTasks = recentTasks;
+        mStackSupervisor.setRecentTasks(recentTasks);
     }
 
     RecentTasks getRecentTasks() {
diff --git a/services/core/java/com/android/server/wm/DisplayRotation.java b/services/core/java/com/android/server/wm/DisplayRotation.java
index 282ed42..410cc94 100644
--- a/services/core/java/com/android/server/wm/DisplayRotation.java
+++ b/services/core/java/com/android/server/wm/DisplayRotation.java
@@ -295,7 +295,8 @@
                 false /* forceRelayout */);
     }
 
-    private void setUserRotation(int userRotationMode, int userRotation) {
+    @VisibleForTesting
+    void setUserRotation(int userRotationMode, int userRotation) {
         if (isDefaultDisplay) {
             // We'll be notified via settings listener, so we don't need to update internal values.
             final ContentResolver res = mContext.getContentResolver();
diff --git a/services/core/java/com/android/server/wm/DisplayWindowSettings.java b/services/core/java/com/android/server/wm/DisplayWindowSettings.java
index 207e8ef..8507918 100644
--- a/services/core/java/com/android/server/wm/DisplayWindowSettings.java
+++ b/services/core/java/com/android/server/wm/DisplayWindowSettings.java
@@ -275,14 +275,14 @@
         // This display used to be in freeform, but we don't support freeform anymore, so fall
         // back to fullscreen.
         if (windowingMode == WindowConfiguration.WINDOWING_MODE_FREEFORM
-                && !mService.mSupportsFreeformWindowManagement) {
+                && !mService.mAtmService.mSupportsFreeformWindowManagement) {
             return WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
         }
         // No record is present so use default windowing mode policy.
         if (windowingMode == WindowConfiguration.WINDOWING_MODE_UNDEFINED) {
             final boolean forceDesktopMode = mService.mForceDesktopModeOnExternalDisplays
                     && displayId != Display.DEFAULT_DISPLAY;
-            windowingMode = mService.mSupportsFreeformWindowManagement
+            windowingMode = mService.mAtmService.mSupportsFreeformWindowManagement
                     && (mService.mIsPc || forceDesktopMode)
                     ? WindowConfiguration.WINDOWING_MODE_FREEFORM
                     : WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
diff --git a/services/core/java/com/android/server/wm/DockedStackDividerController.java b/services/core/java/com/android/server/wm/DockedStackDividerController.java
index b1bc2197..120ce3e 100644
--- a/services/core/java/com/android/server/wm/DockedStackDividerController.java
+++ b/services/core/java/com/android/server/wm/DockedStackDividerController.java
@@ -355,7 +355,9 @@
 
     void getTouchRegion(Rect outRegion) {
         outRegion.set(mTouchRegion);
-        outRegion.offset(mWindow.getFrameLw().left, mWindow.getFrameLw().top);
+        if (mWindow != null) {
+            outRegion.offset(mWindow.getFrameLw().left, mWindow.getFrameLw().top);
+        }
     }
 
     private void resetDragResizingChangeReported() {
diff --git a/services/core/java/com/android/server/wm/RootActivityContainer.java b/services/core/java/com/android/server/wm/RootActivityContainer.java
index 66d42db..3401de6 100644
--- a/services/core/java/com/android/server/wm/RootActivityContainer.java
+++ b/services/core/java/com/android/server/wm/RootActivityContainer.java
@@ -227,15 +227,10 @@
         mStackSupervisor.mRootActivityContainer = this;
     }
 
-    @VisibleForTesting
-    void setWindowContainer(RootWindowContainer container) {
-        mRootWindowContainer = container;
-        mRootWindowContainer.setRootActivityContainer(this);
-    }
-
     void setWindowManager(WindowManagerService wm) {
         mWindowManager = wm;
-        setWindowContainer(mWindowManager.mRoot);
+        mRootWindowContainer = mWindowManager.mRoot;
+        mRootWindowContainer.setRootActivityContainer(this);
         mDisplayManager = mService.mContext.getSystemService(DisplayManager.class);
         mDisplayManager.registerDisplayListener(this, mService.mUiHandler);
         mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
@@ -2266,7 +2261,7 @@
             @WindowConfiguration.ActivityType int ignoreActivityType,
             @WindowConfiguration.WindowingMode int ignoreWindowingMode, int callingUid,
             boolean allowed) {
-        mStackSupervisor.mRunningTasks.getTasks(maxNum, list, ignoreActivityType,
+        mStackSupervisor.getRunningTasks().getTasks(maxNum, list, ignoreActivityType,
                 ignoreWindowingMode, mActivityDisplays, callingUid, allowed);
     }
 
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index fd86faa..3a2eb57 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -380,7 +380,7 @@
 
     boolean isResizeable() {
         return ActivityInfo.isResizeableMode(mResizeMode) || mSupportsPictureInPicture
-                || mWmService.mForceResizableTasks;
+                || mWmService.mAtmService.mForceResizableActivities;
     }
 
     /**
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index 79367a0..cc2112e 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -1666,7 +1666,7 @@
      *         default bounds.
      */
     Rect getPictureInPictureBounds(float aspectRatio, Rect stackBounds) {
-        if (!mWmService.mSupportsPictureInPicture) {
+        if (!mWmService.mAtmService.mSupportsPictureInPicture) {
             return null;
         }
 
@@ -1762,7 +1762,7 @@
      * Sets the current picture-in-picture aspect ratio.
      */
     void setPictureInPictureAspectRatio(float aspectRatio) {
-        if (!mWmService.mSupportsPictureInPicture) {
+        if (!mWmService.mAtmService.mSupportsPictureInPicture) {
             return;
         }
 
@@ -1792,7 +1792,7 @@
      * Sets the current picture-in-picture actions.
      */
     void setPictureInPictureActions(List<RemoteAction> actions) {
-        if (!mWmService.mSupportsPictureInPicture) {
+        if (!mWmService.mAtmService.mSupportsPictureInPicture) {
             return;
         }
 
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index bbef261..29d232f 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -767,11 +767,11 @@
      */
     void setOrientation(int orientation, @Nullable IBinder freezeDisplayToken,
             @Nullable ConfigurationContainer requestingContainer) {
-        final boolean changed = mOrientation != orientation;
-        mOrientation = orientation;
-        if (!changed) {
+        if (mOrientation == orientation) {
             return;
         }
+
+        mOrientation = orientation;
         final WindowContainer parent = getParent();
         if (parent != null) {
             onDescendantOrientationChanged(freezeDisplayToken, requestingContainer);
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 86faad0..db77a33 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -28,6 +28,7 @@
 import static android.app.AppOpsManager.OP_SYSTEM_ALERT_WINDOW;
 import static android.app.StatusBarManager.DISABLE_MASK;
 import static android.app.admin.DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED;
+import static android.content.pm.PackageManager.FEATURE_PC;
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
 import static android.os.Process.SYSTEM_UID;
 import static android.os.Process.myPid;
@@ -591,9 +592,6 @@
     int mDockedStackCreateMode = SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT;
     Rect mDockedStackCreateBounds;
 
-    boolean mForceResizableTasks;
-    boolean mSupportsPictureInPicture;
-    boolean mSupportsFreeformWindowManagement;
     boolean mIsPc;
     /**
      * Flag that indicates that desktop mode is forced for public secondary screens.
@@ -819,7 +817,7 @@
     int mTransactionSequence;
 
     final WindowAnimator mAnimator;
-    final SurfaceAnimationRunner mSurfaceAnimationRunner;
+    SurfaceAnimationRunner mSurfaceAnimationRunner;
 
     /**
      * Keeps track of which animations got transferred to which animators. Entries will get cleaned
@@ -957,6 +955,9 @@
 
     final ArrayList<AppFreezeListener> mAppFreezeListeners = new ArrayList<>();
 
+    @VisibleForTesting
+    final DeviceConfig.OnPropertiesChangedListener mPropertiesChangedListener;
+
     interface AppFreezeListener {
         void onAppFreezeTimeout();
     }
@@ -1010,6 +1011,7 @@
         mGlobalLock = atm.getGlobalLock();
         mAtmService = atm;
         mContext = context;
+        mIsPc = mContext.getPackageManager().hasSystemFeature(FEATURE_PC);
         mAllowBootMessages = showBootMsgs;
         mOnlyCore = onlyCore;
         mLimitedAlphaCompositing = context.getResources().getBoolean(
@@ -1159,26 +1161,28 @@
         mSystemGestureExcludedByPreQStickyImmersive =
                 DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
                         KEY_SYSTEM_GESTURES_EXCLUDED_BY_PRE_Q_STICKY_IMMERSIVE, false);
-        DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
-                new HandlerExecutor(mH), properties -> {
-                    synchronized (mGlobalLock) {
-                        final int exclusionLimitDp = Math.max(MIN_GESTURE_EXCLUSION_LIMIT_DP,
-                                properties.getInt(KEY_SYSTEM_GESTURE_EXCLUSION_LIMIT_DP, 0));
-                        final boolean excludedByPreQSticky = DeviceConfig.getBoolean(
-                                DeviceConfig.NAMESPACE_WINDOW_MANAGER,
-                                KEY_SYSTEM_GESTURES_EXCLUDED_BY_PRE_Q_STICKY_IMMERSIVE, false);
-                        if (mSystemGestureExcludedByPreQStickyImmersive != excludedByPreQSticky
-                                || mSystemGestureExclusionLimitDp != exclusionLimitDp) {
-                            mSystemGestureExclusionLimitDp = exclusionLimitDp;
-                            mSystemGestureExcludedByPreQStickyImmersive = excludedByPreQSticky;
-                            mRoot.forAllDisplays(DisplayContent::updateSystemGestureExclusionLimit);
-                        }
 
-                        mSystemGestureExclusionLogDebounceTimeoutMillis =
-                                DeviceConfig.getInt(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
-                                        KEY_SYSTEM_GESTURE_EXCLUSION_LOG_DEBOUNCE_MILLIS, 0);
-                    }
-                });
+        mPropertiesChangedListener = properties -> {
+            synchronized (mGlobalLock) {
+                final int exclusionLimitDp = Math.max(MIN_GESTURE_EXCLUSION_LIMIT_DP,
+                        properties.getInt(KEY_SYSTEM_GESTURE_EXCLUSION_LIMIT_DP, 0));
+                final boolean excludedByPreQSticky = DeviceConfig.getBoolean(
+                        DeviceConfig.NAMESPACE_WINDOW_MANAGER,
+                        KEY_SYSTEM_GESTURES_EXCLUDED_BY_PRE_Q_STICKY_IMMERSIVE, false);
+                if (mSystemGestureExcludedByPreQStickyImmersive != excludedByPreQSticky
+                        || mSystemGestureExclusionLimitDp != exclusionLimitDp) {
+                    mSystemGestureExclusionLimitDp = exclusionLimitDp;
+                    mSystemGestureExcludedByPreQStickyImmersive = excludedByPreQSticky;
+                    mRoot.forAllDisplays(DisplayContent::updateSystemGestureExclusionLimit);
+                }
+
+                mSystemGestureExclusionLogDebounceTimeoutMillis =
+                        DeviceConfig.getInt(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
+                                KEY_SYSTEM_GESTURE_EXCLUSION_LOG_DEBOUNCE_MILLIS, 0);
+            }
+        };
+        DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
+                new HandlerExecutor(mH), mPropertiesChangedListener);
 
         LocalServices.addService(WindowManagerInternal.class, new LocalService());
     }
@@ -4847,8 +4851,10 @@
                 case UPDATE_DOCKED_STACK_DIVIDER: {
                     synchronized (mGlobalLock) {
                         final DisplayContent displayContent = getDefaultDisplayContentLocked();
-                        displayContent.getDockedDividerController().reevaluateVisibility(false);
-                        displayContent.adjustForImeIfNeeded();
+                        if (displayContent != null) {
+                            displayContent.getDockedDividerController().reevaluateVisibility(false);
+                            displayContent.adjustForImeIfNeeded();
+                        }
                     }
                     break;
                 }
@@ -6495,31 +6501,14 @@
         }
     }
 
-    public void setForceResizableTasks(boolean forceResizableTasks) {
-        synchronized (mGlobalLock) {
-            mForceResizableTasks = forceResizableTasks;
-        }
-    }
-
-    public void setSupportsPictureInPicture(boolean supportsPictureInPicture) {
-        synchronized (mGlobalLock) {
-            mSupportsPictureInPicture = supportsPictureInPicture;
-        }
-    }
-
-    public void setSupportsFreeformWindowManagement(boolean supportsFreeformWindowManagement) {
-        synchronized (mGlobalLock) {
-            mSupportsFreeformWindowManagement = supportsFreeformWindowManagement;
-        }
-    }
-
     void setForceDesktopModeOnExternalDisplays(boolean forceDesktopModeOnExternalDisplays) {
         synchronized (mGlobalLock) {
             mForceDesktopModeOnExternalDisplays = forceDesktopModeOnExternalDisplays;
         }
     }
 
-    public void setIsPc(boolean isPc) {
+    @VisibleForTesting
+    void setIsPc(boolean isPc) {
         synchronized (mGlobalLock) {
             mIsPc = isPc;
         }
@@ -6546,7 +6535,7 @@
                 "registerPinnedStackListener()")) {
             return;
         }
-        if (!mSupportsPictureInPicture) {
+        if (!mAtmService.mSupportsPictureInPicture) {
             return;
         }
         synchronized (mGlobalLock) {
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 63b9198..6c78f6f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java
@@ -28,6 +28,7 @@
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.reset;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
 import static com.android.server.wm.ActivityStackSupervisor.ON_TOP;
 
@@ -140,7 +141,8 @@
     public void testNotResumeHomeStackOnRemovingDisplay() {
         // Create a display which supports system decoration and allows reparenting stacks to
         // another display when the display is removed.
-        final ActivityDisplay display = spy(createNewActivityDisplay());
+        final ActivityDisplay display = createNewActivityDisplay();
+        spyOn(display);
         doReturn(false).when(display).shouldDestroyContentOnRemove();
         doReturn(true).when(display).supportsSystemDecorations();
         mRootActivityContainer.addChild(display, ActivityDisplay.POSITION_TOP);
@@ -304,14 +306,18 @@
                 ACTIVITY_TYPE_STANDARD, ON_TOP);
         final ActivityStack stack4 = display.createStack(WINDOWING_MODE_FULLSCREEN,
                 ACTIVITY_TYPE_STANDARD, ON_TOP);
-        final TaskRecord task1 = new TaskBuilder(mService.mStackSupervisor).setStack(
-                stack1).setTaskId(1).build();
-        final TaskRecord task2 = new TaskBuilder(mService.mStackSupervisor).setStack(
-                stack2).setTaskId(2).build();
-        final TaskRecord task3 = new TaskBuilder(mService.mStackSupervisor).setStack(
-                stack3).setTaskId(3).build();
-        final TaskRecord task4 = new TaskBuilder(mService.mStackSupervisor).setStack(
-                stack4).setTaskId(4).build();
+        final TaskRecord task1 = new TaskBuilder(mService.mStackSupervisor)
+                .setStack(stack1)
+                .build();
+        final TaskRecord task2 = new TaskBuilder(mService.mStackSupervisor)
+                .setStack(stack2)
+                .build();
+        final TaskRecord task3 = new TaskBuilder(mService.mStackSupervisor)
+                .setStack(stack3)
+                .build();
+        final TaskRecord task4 = new TaskBuilder(mService.mStackSupervisor)
+                .setStack(stack4)
+                .build();
 
         // Reordering stacks while removing stacks.
         doAnswer(invocation -> {
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
index 23bae88..977dd8e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
@@ -61,13 +61,13 @@
     private ActivityMetricsLaunchObserver mLaunchObserver;
     private ActivityMetricsLaunchObserverRegistry mLaunchObserverRegistry;
 
-    private TestActivityStack mStack;
+    private ActivityStack mStack;
     private TaskRecord mTask;
     private ActivityRecord mActivityRecord;
     private ActivityRecord mActivityRecordTrampoline;
 
     @Before
-    public void setUpAMLO() throws Exception {
+    public void setUpAMLO() {
         mLaunchObserver = mock(ActivityMetricsLaunchObserver.class);
 
         // ActivityStackSupervisor always creates its own instance of ActivityMetricsLogger.
@@ -78,15 +78,19 @@
 
         // Sometimes we need an ActivityRecord for ActivityMetricsLogger to do anything useful.
         // This seems to be the easiest way to create an ActivityRecord.
-        mStack = mRootActivityContainer.getDefaultDisplay().createStack(
-                WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
-        mTask = new TaskBuilder(mSupervisor).setStack(mStack).build();
-        mActivityRecord = new ActivityBuilder(mService).setTask(mTask).build();
+        mStack = new StackBuilder(mRootActivityContainer)
+                .setActivityType(ACTIVITY_TYPE_STANDARD)
+                .setWindowingMode(WINDOWING_MODE_FULLSCREEN)
+                .setOnTop(true)
+                .setCreateActivity(true)
+                .build();
+        mTask = mStack.topTask();
+        mActivityRecord = mTask.getTopActivity();
         mActivityRecordTrampoline = new ActivityBuilder(mService).setTask(mTask).build();
     }
 
     @After
-    public void tearDownAMLO() throws Exception {
+    public void tearDownAMLO() {
         if (mLaunchObserverRegistry != null) {  // Don't NPE if setUp failed.
             mLaunchObserverRegistry.unregisterLaunchObserver(mLaunchObserver);
         }
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 7b252cb..787ce28 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -16,6 +16,12 @@
 
 package com.android.server.wm;
 
+import static android.content.pm.ActivityInfo.CONFIG_ORIENTATION;
+import static android.content.pm.ActivityInfo.CONFIG_SCREEN_LAYOUT;
+import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
+import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
+import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
 import static android.os.Process.NOBODY_UID;
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.Surface.ROTATION_0;
@@ -29,6 +35,7 @@
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.eq;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.times;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
 import static com.android.server.wm.ActivityRecord.FINISH_RESULT_CANCELLED;
@@ -71,6 +78,7 @@
 import android.platform.test.annotations.Presubmit;
 import android.util.MergedConfiguration;
 import android.util.MutableBoolean;
+import android.view.DisplayInfo;
 import android.view.IRemoteAnimationFinishedCallback;
 import android.view.IRemoteAnimationRunner.Stub;
 import android.view.RemoteAnimationAdapter;
@@ -79,7 +87,6 @@
 import androidx.test.filters.MediumTest;
 
 import com.android.internal.R;
-import com.android.server.wm.utils.WmDisplayCutout;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -96,13 +103,13 @@
 @MediumTest
 @Presubmit
 public class ActivityRecordTests extends ActivityTestsBase {
-    private TestActivityStack mStack;
+    private ActivityStack mStack;
     private TaskRecord mTask;
     private ActivityRecord mActivity;
 
     @Before
     public void setUp() throws Exception {
-        mStack = (TestActivityStack) new StackBuilder(mRootActivityContainer).build();
+        mStack = new StackBuilder(mRootActivityContainer).build();
         mTask = mStack.getChildAt(0);
         mActivity = mTask.getTopActivity();
 
@@ -113,13 +120,13 @@
     @Test
     public void testStackCleanupOnClearingTask() {
         mActivity.setTask(null);
-        assertEquals(mStack.onActivityRemovedFromStackInvocationCount(), 1);
+        verify(mStack, times(1)).onActivityRemovedFromStack(any());
     }
 
     @Test
     public void testStackCleanupOnActivityRemoval() {
         mTask.removeActivity(mActivity);
-        assertEquals(mStack.onActivityRemovedFromStackInvocationCount(),  1);
+        verify(mStack, times(1)).onActivityRemovedFromStack(any());
     }
 
     @Test
@@ -134,7 +141,7 @@
         final TaskRecord newTask = new TaskBuilder(mService.mStackSupervisor).setStack(mStack)
                 .build();
         mActivity.reparent(newTask, 0, null /*reason*/);
-        assertEquals(mStack.onActivityRemovedFromStackInvocationCount(), 0);
+        verify(mStack, times(0)).onActivityRemovedFromStack(any());
     }
 
     @Test
@@ -261,8 +268,8 @@
     public void testNewParentConfigurationIncrementsSeq() {
         final Configuration newConfig = new Configuration(
                 mTask.getRequestedOverrideConfiguration());
-        newConfig.orientation = newConfig.orientation == Configuration.ORIENTATION_PORTRAIT
-                ? Configuration.ORIENTATION_LANDSCAPE : Configuration.ORIENTATION_PORTRAIT;
+        newConfig.orientation = newConfig.orientation == ORIENTATION_PORTRAIT
+                ? ORIENTATION_LANDSCAPE : ORIENTATION_PORTRAIT;
 
         final int prevSeq = mActivity.getMergedOverrideConfiguration().seq;
         mTask.onRequestedOverrideConfigurationChanged(newConfig);
@@ -277,7 +284,7 @@
                 .getRequestedOverrideConfiguration();
 
         final Configuration newConfig = new Configuration();
-        newConfig.orientation = Configuration.ORIENTATION_PORTRAIT;
+        newConfig.orientation = ORIENTATION_PORTRAIT;
 
         final int prevSeq = mActivity.getMergedOverrideConfiguration().seq;
         mActivity.onRequestedOverrideConfigurationChanged(newConfig);
@@ -293,10 +300,11 @@
         mActivity.setLastReportedConfiguration(new MergedConfiguration(new Configuration(),
                 mActivity.getConfiguration()));
 
-        mActivity.info.configChanges &= ~ActivityInfo.CONFIG_ORIENTATION;
+        mActivity.info.configChanges &= ~CONFIG_ORIENTATION;
         final Configuration newConfig = new Configuration(mTask.getConfiguration());
-        newConfig.orientation = newConfig.orientation == Configuration.ORIENTATION_PORTRAIT
-                ? Configuration.ORIENTATION_LANDSCAPE : Configuration.ORIENTATION_PORTRAIT;
+        newConfig.orientation = newConfig.orientation == ORIENTATION_PORTRAIT
+                ? ORIENTATION_LANDSCAPE
+                : ORIENTATION_PORTRAIT;
         mTask.onRequestedOverrideConfigurationChanged(newConfig);
 
         mActivity.mRelaunchReason = ActivityTaskManagerService.RELAUNCH_REASON_NONE;
@@ -315,13 +323,14 @@
         mActivity.setLastReportedConfiguration(new MergedConfiguration(new Configuration(),
                 mActivity.getConfiguration()));
 
-        mActivity.info.configChanges &= ~ActivityInfo.CONFIG_ORIENTATION;
+        mActivity.info.configChanges &= ~CONFIG_ORIENTATION;
         final Configuration newConfig = new Configuration(mTask.getConfiguration());
-        newConfig.orientation = newConfig.orientation == Configuration.ORIENTATION_PORTRAIT
-                ? Configuration.ORIENTATION_LANDSCAPE : Configuration.ORIENTATION_PORTRAIT;
+        newConfig.orientation = newConfig.orientation == ORIENTATION_PORTRAIT
+                ? ORIENTATION_LANDSCAPE
+                : ORIENTATION_PORTRAIT;
         mTask.onRequestedOverrideConfigurationChanged(newConfig);
 
-        doReturn(true).when(mTask.getTask()).isDragResizing();
+        doReturn(true).when(mTask.mTask).isDragResizing();
 
         mActivity.mRelaunchReason = ActivityTaskManagerService.RELAUNCH_REASON_NONE;
 
@@ -355,30 +364,39 @@
 
     @Test
     public void testSetRequestedOrientationUpdatesConfiguration() throws Exception {
+        mActivity = new ActivityBuilder(mService)
+                .setTask(mTask)
+                .setConfigChanges(CONFIG_ORIENTATION | CONFIG_SCREEN_LAYOUT)
+                .build();
         mActivity.setState(ActivityStack.ActivityState.RESUMED, "Testing");
 
-        mTask.onRequestedOverrideConfigurationChanged(mTask.getConfiguration());
         mActivity.setLastReportedConfiguration(new MergedConfiguration(new Configuration(),
                 mActivity.getConfiguration()));
 
-        mActivity.info.configChanges |= ActivityInfo.CONFIG_ORIENTATION;
         final Configuration newConfig = new Configuration(mActivity.getConfiguration());
-        newConfig.orientation = newConfig.orientation == Configuration.ORIENTATION_PORTRAIT
-                ? Configuration.ORIENTATION_LANDSCAPE
-                : Configuration.ORIENTATION_PORTRAIT;
+        final int shortSide = Math.min(newConfig.screenWidthDp, newConfig.screenHeightDp);
+        final int longSide = Math.max(newConfig.screenWidthDp, newConfig.screenHeightDp);
+        if (newConfig.orientation == ORIENTATION_PORTRAIT) {
+            newConfig.orientation = ORIENTATION_LANDSCAPE;
+            newConfig.screenWidthDp = longSide;
+            newConfig.screenHeightDp = shortSide;
+        } else {
+            newConfig.orientation = ORIENTATION_PORTRAIT;
+            newConfig.screenWidthDp = shortSide;
+            newConfig.screenHeightDp = longSide;
+        }
 
         // Mimic the behavior that display doesn't handle app's requested orientation.
-        doAnswer(invocation -> {
-            mTask.onConfigurationChanged(newConfig);
-            return null;
-        }).when(mActivity.mAppWindowToken).setOrientation(anyInt(), any(), any());
+        final DisplayContent dc = mTask.mTask.getDisplayContent();
+        doReturn(false).when(dc).onDescendantOrientationChanged(any(), any());
+        doReturn(false).when(dc).handlesOrientationChangeFromDescendant();
 
         final int requestedOrientation;
         switch (newConfig.orientation) {
-            case Configuration.ORIENTATION_LANDSCAPE:
-                requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
+            case ORIENTATION_LANDSCAPE:
+                requestedOrientation = SCREEN_ORIENTATION_LANDSCAPE;
                 break;
-            case Configuration.ORIENTATION_PORTRAIT:
+            case ORIENTATION_PORTRAIT:
                 requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
                 break;
             default:
@@ -421,24 +439,33 @@
 
     @Test
     public void testPushConfigurationWhenLaunchTaskBehind() throws Exception {
+        mActivity = new ActivityBuilder(mService)
+                .setTask(mTask)
+                .setLaunchTaskBehind(true)
+                .setConfigChanges(CONFIG_ORIENTATION)
+                .build();
         mActivity.setState(ActivityStack.ActivityState.STOPPED, "Testing");
 
-        final TestActivityStack stack = (TestActivityStack) new StackBuilder(mRootActivityContainer)
-                .build();
+        final ActivityStack stack = new StackBuilder(mRootActivityContainer).build();
         try {
-            stack.setIsTranslucent(false);
+            doReturn(false).when(stack).isStackTranslucent(any());
             assertFalse(mStack.shouldBeVisible(null /* starting */));
 
-            mTask.onRequestedOverrideConfigurationChanged(mTask.getConfiguration());
             mActivity.setLastReportedConfiguration(new MergedConfiguration(new Configuration(),
                     mActivity.getConfiguration()));
 
-            mActivity.mLaunchTaskBehind = true;
-            mActivity.info.configChanges |= ActivityInfo.CONFIG_ORIENTATION;
             final Configuration newConfig = new Configuration(mActivity.getConfiguration());
-            newConfig.orientation = newConfig.orientation == Configuration.ORIENTATION_PORTRAIT
-                    ? Configuration.ORIENTATION_LANDSCAPE
-                    : Configuration.ORIENTATION_PORTRAIT;
+            final int shortSide = Math.min(newConfig.screenWidthDp, newConfig.screenHeightDp);
+            final int longSide = Math.max(newConfig.screenWidthDp, newConfig.screenHeightDp);
+            if (newConfig.orientation == ORIENTATION_PORTRAIT) {
+                newConfig.orientation = ORIENTATION_LANDSCAPE;
+                newConfig.screenWidthDp = longSide;
+                newConfig.screenHeightDp = shortSide;
+            } else {
+                newConfig.orientation = ORIENTATION_PORTRAIT;
+                newConfig.screenWidthDp = shortSide;
+                newConfig.screenHeightDp = longSide;
+            }
 
             mTask.onConfigurationChanged(newConfig);
 
@@ -468,6 +495,7 @@
         setupDisplayContentForCompatDisplayInsets();
         final int decorHeight = 200; // e.g. The device has cutout.
         final DisplayPolicy policy = setupDisplayAndParentSize(600, 800).getDisplayPolicy();
+        spyOn(policy);
         doAnswer(invocationOnMock -> {
             final int rotation = invocationOnMock.<Integer>getArgument(0);
             final Rect insets = invocationOnMock.<Rect>getArgument(4);
@@ -482,7 +510,7 @@
 
         doReturn(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED)
                 .when(mActivity.mAppWindowToken).getOrientationIgnoreVisibility();
-        mActivity.info.resizeMode = ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
+        mActivity.info.resizeMode = RESIZE_MODE_UNRESIZEABLE;
         mActivity.info.minAspectRatio = mActivity.info.maxAspectRatio = 1;
         ensureActivityConfiguration();
         // The parent configuration doesn't change since the first resolved configuration, so the
@@ -506,19 +534,28 @@
     @Test
     public void testSizeCompatMode_FixedScreenConfigurationWhenMovingToDisplay() {
         // Initialize different bounds on a new display.
-        final ActivityDisplay newDisplay = addNewActivityDisplayAt(ActivityDisplay.POSITION_TOP);
-        newDisplay.getWindowConfiguration().setAppBounds(new Rect(0, 0, 1000, 2000));
-        newDisplay.getConfiguration().densityDpi = 300;
+        final Rect newDisplayBounds = new Rect(0, 0, 1000, 2000);
+        DisplayInfo info = new DisplayInfo();
+        mService.mContext.getDisplay().getDisplayInfo(info);
+        info.logicalWidth = newDisplayBounds.width();
+        info.logicalHeight = newDisplayBounds.height();
+        info.logicalDensityDpi = 300;
+
+        final ActivityDisplay newDisplay =
+                addNewActivityDisplayAt(info, ActivityDisplay.POSITION_TOP);
 
         mTask.getConfiguration().densityDpi = 200;
-        prepareFixedAspectRatioUnresizableActivity();
+        mActivity = new ActivityBuilder(mService)
+                .setTask(mTask)
+                .setResizeMode(RESIZE_MODE_UNRESIZEABLE)
+                .setMaxAspectRatio(1.5f)
+                .build();
 
         final Rect originalBounds = new Rect(mActivity.getBounds());
         final int originalDpi = mActivity.getConfiguration().densityDpi;
 
         // Move the non-resizable activity to the new display.
         mStack.reparent(newDisplay, true /* onTop */, false /* displayRemoved */);
-        ensureActivityConfiguration();
 
         assertEquals(originalBounds, mActivity.getBounds());
         assertEquals(originalDpi, mActivity.getConfiguration().densityDpi);
@@ -531,9 +568,9 @@
         when(mActivity.mAppWindowToken.getOrientationIgnoreVisibility()).thenReturn(
                 ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
         mTask.getWindowConfiguration().setAppBounds(mStack.getDisplay().getBounds());
-        mTask.getConfiguration().orientation = Configuration.ORIENTATION_PORTRAIT;
+        mTask.getConfiguration().orientation = ORIENTATION_PORTRAIT;
         mActivity.info.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
-        mActivity.info.resizeMode = ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
+        mActivity.info.resizeMode = RESIZE_MODE_UNRESIZEABLE;
         ensureActivityConfiguration();
         final Rect originalBounds = new Rect(mActivity.getBounds());
 
@@ -579,7 +616,7 @@
         mTask.getWindowConfiguration().setAppBounds(new Rect(0, 0, 600, 1200));
 
         // Simulate the display changes orientation.
-        doReturn(ActivityInfo.CONFIG_SCREEN_SIZE | ActivityInfo.CONFIG_ORIENTATION
+        doReturn(ActivityInfo.CONFIG_SCREEN_SIZE | CONFIG_ORIENTATION
                 | ActivityInfo.CONFIG_WINDOW_CONFIGURATION)
                         .when(display).getLastOverrideConfigurationChanges();
         mActivity.onConfigurationChanged(mTask.getConfiguration());
@@ -754,24 +791,17 @@
     /** Setup {@link #mActivity} as a size-compat-mode-able activity without fixed orientation. */
     private void prepareFixedAspectRatioUnresizableActivity() {
         setupDisplayContentForCompatDisplayInsets();
-        when(mActivity.mAppWindowToken.getOrientationIgnoreVisibility()).thenReturn(
-                ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
-        mActivity.info.resizeMode = ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
+        mActivity.info.resizeMode = RESIZE_MODE_UNRESIZEABLE;
         mActivity.info.maxAspectRatio = 1.5f;
         ensureActivityConfiguration();
     }
 
     private void setupDisplayContentForCompatDisplayInsets() {
         final Rect displayBounds = mStack.getDisplay().getBounds();
-        final DisplayContent displayContent = setupDisplayAndParentSize(
-                displayBounds.width(), displayBounds.height());
-        doReturn(mock(DisplayPolicy.class)).when(displayContent).getDisplayPolicy();
-        doReturn(mock(WmDisplayCutout.class)).when(displayContent)
-                .calculateDisplayCutoutForRotation(anyInt());
+        setupDisplayAndParentSize(displayBounds.width(), displayBounds.height());
     }
 
     private DisplayContent setupDisplayAndParentSize(int width, int height) {
-        // The DisplayContent is already a mocked object.
         final DisplayContent displayContent = mStack.getDisplay().mDisplayContent;
         displayContent.mBaseDisplayWidth = width;
         displayContent.mBaseDisplayHeight = height;
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 e5278d8..ff7b1fa 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
@@ -29,7 +29,7 @@
 
 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.spy;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
 import static com.android.server.wm.ActivityStack.ActivityState.DESTROYING;
 import static com.android.server.wm.ActivityStack.ActivityState.FINISHING;
@@ -44,6 +44,7 @@
 import static com.android.server.wm.ActivityStack.STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT;
 import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_FREE_RESIZE;
 import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_WINDOWING_MODE_RESIZE;
+import static com.android.server.wm.TaskRecord.REPARENT_MOVE_STACK_TO_FRONT;
 
 import static com.google.common.truth.Truth.assertThat;
 
@@ -83,8 +84,9 @@
     @Before
     public void setUp() throws Exception {
         mDefaultDisplay = mRootActivityContainer.getDefaultDisplay();
-        mStack = spy(mDefaultDisplay.createStack(WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_STANDARD,
-                true /* onTop */));
+        mStack = mDefaultDisplay.createStack(WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_STANDARD,
+                true /* onTop */);
+        spyOn(mStack);
         mTask = new TaskBuilder(mSupervisor).setStack(mStack).build();
     }
 
@@ -140,10 +142,8 @@
 
         final ActivityStack destStack = mRootActivityContainer.getDefaultDisplay().createStack(
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
-        final TaskRecord destTask = new TaskBuilder(mSupervisor).setStack(destStack).build();
-
-        mTask.removeActivity(r);
-        destTask.addActivityToTop(r);
+        mTask.reparent(destStack, true /*toTop*/, REPARENT_MOVE_STACK_TO_FRONT, false, false,
+                "testResumedActivityFromActivityReparenting");
 
         assertNull(mStack.getResumedActivity());
         assertEquals(r, destStack.getResumedActivity());
@@ -313,45 +313,50 @@
 
     @Test
     public void testShouldBeVisible_Fullscreen() {
-        final TestActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
+        final ActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */);
         final ActivityStack pinnedStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
                 WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD, true /* onTop */);
+        // Add an activity to the pinned stack so it isn't considered empty for visibility check.
+        final ActivityRecord pinnedActivity = new ActivityBuilder(mService)
+                .setCreateTask(true)
+                .setStack(pinnedStack)
+                .build();
 
         assertTrue(homeStack.shouldBeVisible(null /* starting */));
         assertTrue(pinnedStack.shouldBeVisible(null /* starting */));
 
-        final TestActivityStack fullscreenStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
+        final ActivityStack fullscreenStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
         // Home stack shouldn't be visible behind an opaque fullscreen stack, but pinned stack
         // should be visible since it is always on-top.
-        fullscreenStack.setIsTranslucent(false);
+        doReturn(false).when(fullscreenStack).isStackTranslucent(any());
         assertFalse(homeStack.shouldBeVisible(null /* starting */));
         assertTrue(pinnedStack.shouldBeVisible(null /* starting */));
         assertTrue(fullscreenStack.shouldBeVisible(null /* starting */));
 
         // Home stack should be visible behind a translucent fullscreen stack.
-        fullscreenStack.setIsTranslucent(true);
+        doReturn(true).when(fullscreenStack).isStackTranslucent(any());
         assertTrue(homeStack.shouldBeVisible(null /* starting */));
         assertTrue(pinnedStack.shouldBeVisible(null /* starting */));
     }
 
     @Test
     public void testShouldBeVisible_SplitScreen() {
-        final TestActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
+        final ActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */);
         // Home stack should always be fullscreen for this test.
-        homeStack.setSupportsSplitScreen(false);
-        final TestActivityStack splitScreenPrimary =
+        doReturn(false).when(homeStack).supportsSplitScreenWindowingMode();
+        final ActivityStack splitScreenPrimary =
                 createStackForShouldBeVisibleTest(mDefaultDisplay,
                 WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD, true /* onTop */);
-        final TestActivityStack splitScreenSecondary =
+        final ActivityStack splitScreenSecondary =
                 createStackForShouldBeVisibleTest(mDefaultDisplay,
                 WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, ACTIVITY_TYPE_STANDARD, true /* onTop */);
 
         // Home stack shouldn't be visible if both halves of split-screen are opaque.
-        splitScreenPrimary.setIsTranslucent(false);
-        splitScreenSecondary.setIsTranslucent(false);
+        doReturn(false).when(splitScreenPrimary).isStackTranslucent(any());
+        doReturn(false).when(splitScreenSecondary).isStackTranslucent(any());
         assertFalse(homeStack.shouldBeVisible(null /* starting */));
         assertTrue(splitScreenPrimary.shouldBeVisible(null /* starting */));
         assertTrue(splitScreenSecondary.shouldBeVisible(null /* starting */));
@@ -362,7 +367,7 @@
                 splitScreenSecondary.getVisibility(null /* starting */));
 
         // Home stack should be visible if one of the halves of split-screen is translucent.
-        splitScreenPrimary.setIsTranslucent(true);
+        doReturn(true).when(splitScreenPrimary).isStackTranslucent(any());
         assertTrue(homeStack.shouldBeVisible(null /* starting */));
         assertTrue(splitScreenPrimary.shouldBeVisible(null /* starting */));
         assertTrue(splitScreenSecondary.shouldBeVisible(null /* starting */));
@@ -373,12 +378,12 @@
         assertEquals(STACK_VISIBILITY_VISIBLE,
                 splitScreenSecondary.getVisibility(null /* starting */));
 
-        final TestActivityStack splitScreenSecondary2 =
+        final ActivityStack splitScreenSecondary2 =
                 createStackForShouldBeVisibleTest(mDefaultDisplay,
                 WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, ACTIVITY_TYPE_STANDARD, true /* onTop */);
         // First split-screen secondary shouldn't be visible behind another opaque split-split
         // secondary.
-        splitScreenSecondary2.setIsTranslucent(false);
+        doReturn(false).when(splitScreenSecondary2).isStackTranslucent(any());
         assertFalse(splitScreenSecondary.shouldBeVisible(null /* starting */));
         assertTrue(splitScreenSecondary2.shouldBeVisible(null /* starting */));
         assertEquals(STACK_VISIBILITY_INVISIBLE,
@@ -388,7 +393,7 @@
 
         // First split-screen secondary should be visible behind another translucent split-screen
         // secondary.
-        splitScreenSecondary2.setIsTranslucent(true);
+        doReturn(true).when(splitScreenSecondary2).isStackTranslucent(any());
         assertTrue(splitScreenSecondary.shouldBeVisible(null /* starting */));
         assertTrue(splitScreenSecondary2.shouldBeVisible(null /* starting */));
         assertEquals(STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT,
@@ -396,11 +401,11 @@
         assertEquals(STACK_VISIBILITY_VISIBLE,
                 splitScreenSecondary2.getVisibility(null /* starting */));
 
-        final TestActivityStack assistantStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
+        final ActivityStack assistantStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_ASSISTANT, true /* onTop */);
 
         // Split-screen stacks shouldn't be visible behind an opaque fullscreen stack.
-        assistantStack.setIsTranslucent(false);
+        doReturn(false).when(assistantStack).isStackTranslucent(any());
         assertTrue(assistantStack.shouldBeVisible(null /* starting */));
         assertFalse(splitScreenPrimary.shouldBeVisible(null /* starting */));
         assertFalse(splitScreenSecondary.shouldBeVisible(null /* starting */));
@@ -415,7 +420,7 @@
                 splitScreenSecondary2.getVisibility(null /* starting */));
 
         // Split-screen stacks should be visible behind a translucent fullscreen stack.
-        assistantStack.setIsTranslucent(true);
+        doReturn(true).when(assistantStack).isStackTranslucent(any());
         assertTrue(assistantStack.shouldBeVisible(null /* starting */));
         assertTrue(splitScreenPrimary.shouldBeVisible(null /* starting */));
         assertTrue(splitScreenSecondary.shouldBeVisible(null /* starting */));
@@ -430,9 +435,9 @@
                 splitScreenSecondary2.getVisibility(null /* starting */));
 
         // Assistant stack shouldn't be visible behind translucent split-screen stack
-        assistantStack.setIsTranslucent(false);
-        splitScreenPrimary.setIsTranslucent(true);
-        splitScreenSecondary2.setIsTranslucent(true);
+        doReturn(false).when(assistantStack).isStackTranslucent(any());
+        doReturn(true).when(splitScreenPrimary).isStackTranslucent(any());
+        doReturn(true).when(splitScreenSecondary2).isStackTranslucent(any());
         splitScreenSecondary2.moveToFront("testShouldBeVisible_SplitScreen");
         splitScreenPrimary.moveToFront("testShouldBeVisible_SplitScreen");
         assertFalse(assistantStack.shouldBeVisible(null /* starting */));
@@ -450,10 +455,10 @@
 
     @Test
     public void testGetVisibility_FullscreenBehindTranslucent() {
-        final TestActivityStack bottomStack =
+        final ActivityStack bottomStack =
                 createStandardStackForVisibilityTest(WINDOWING_MODE_FULLSCREEN,
                         false /* translucent */);
-        final TestActivityStack translucentStack =
+        final ActivityStack translucentStack =
                 createStandardStackForVisibilityTest(WINDOWING_MODE_FULLSCREEN,
                         true /* translucent */);
 
@@ -465,13 +470,13 @@
 
     @Test
     public void testGetVisibility_FullscreenBehindTranslucentAndOpaque() {
-        final TestActivityStack bottomStack =
+        final ActivityStack bottomStack =
                 createStandardStackForVisibilityTest(WINDOWING_MODE_FULLSCREEN,
                         false /* translucent */);
-        final TestActivityStack translucentStack =
+        final ActivityStack translucentStack =
                 createStandardStackForVisibilityTest(WINDOWING_MODE_FULLSCREEN,
                         true /* translucent */);
-        final TestActivityStack opaqueStack =
+        final ActivityStack opaqueStack =
                 createStandardStackForVisibilityTest(WINDOWING_MODE_FULLSCREEN,
                         false /* translucent */);
 
@@ -483,13 +488,13 @@
 
     @Test
     public void testGetVisibility_FullscreenBehindOpaqueAndTranslucent() {
-        final TestActivityStack bottomStack =
+        final ActivityStack bottomStack =
                 createStandardStackForVisibilityTest(WINDOWING_MODE_FULLSCREEN,
                         false /* translucent */);
-        final TestActivityStack opaqueStack =
+        final ActivityStack opaqueStack =
                 createStandardStackForVisibilityTest(WINDOWING_MODE_FULLSCREEN,
                         false /* translucent */);
-        final TestActivityStack translucentStack =
+        final ActivityStack translucentStack =
                 createStandardStackForVisibilityTest(WINDOWING_MODE_FULLSCREEN,
                         true /* translucent */);
 
@@ -502,10 +507,10 @@
 
     @Test
     public void testGetVisibility_FullscreenTranslucentBehindTranslucent() {
-        final TestActivityStack bottomTranslucentStack =
+        final ActivityStack bottomTranslucentStack =
                 createStandardStackForVisibilityTest(WINDOWING_MODE_FULLSCREEN,
                         true /* translucent */);
-        final TestActivityStack translucentStack =
+        final ActivityStack translucentStack =
                 createStandardStackForVisibilityTest(WINDOWING_MODE_FULLSCREEN,
                         true /* translucent */);
 
@@ -517,10 +522,10 @@
 
     @Test
     public void testGetVisibility_FullscreenTranslucentBehindOpaque() {
-        final TestActivityStack bottomTranslucentStack =
+        final ActivityStack bottomTranslucentStack =
                 createStandardStackForVisibilityTest(WINDOWING_MODE_FULLSCREEN,
                         true /* translucent */);
-        final TestActivityStack opaqueStack =
+        final ActivityStack opaqueStack =
                 createStandardStackForVisibilityTest(WINDOWING_MODE_FULLSCREEN,
                         false /* translucent */);
 
@@ -531,10 +536,10 @@
 
     @Test
     public void testGetVisibility_FullscreenBehindTranslucentAndPip() {
-        final TestActivityStack bottomStack =
+        final ActivityStack bottomStack =
                 createStandardStackForVisibilityTest(WINDOWING_MODE_FULLSCREEN,
                         false /* translucent */);
-        final TestActivityStack translucentStack =
+        final ActivityStack translucentStack =
                 createStandardStackForVisibilityTest(WINDOWING_MODE_FULLSCREEN,
                         true /* translucent */);
         final ActivityStack pinnedStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
@@ -544,22 +549,34 @@
                 bottomStack.getVisibility(null /* starting */));
         assertEquals(STACK_VISIBILITY_VISIBLE,
                 translucentStack.getVisibility(null /* starting */));
+        // Add an activity to the pinned stack so it isn't considered empty for visibility check.
+        final ActivityRecord pinnedActivity = new ActivityBuilder(mService)
+                .setCreateTask(true)
+                .setStack(pinnedStack)
+                .build();
         assertEquals(STACK_VISIBILITY_VISIBLE, pinnedStack.getVisibility(null /* starting */));
     }
 
     @Test
     public void testShouldBeVisible_Finishing() {
-        final TestActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
+        final ActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */);
-        final TestActivityStack translucentStack = createStackForShouldBeVisibleTest(
+        ActivityRecord topRunningHomeActivity = homeStack.topRunningActivityLocked();
+        if (topRunningHomeActivity == null) {
+            topRunningHomeActivity = new ActivityBuilder(mService)
+                    .setStack(homeStack)
+                    .setCreateTask(true)
+                    .build();
+        }
+
+        final ActivityStack translucentStack = createStackForShouldBeVisibleTest(
                 mDefaultDisplay, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
                 true /* onTop */);
-        translucentStack.setIsTranslucent(true);
+        doReturn(true).when(translucentStack).isStackTranslucent(any());
 
         assertTrue(homeStack.shouldBeVisible(null /* starting */));
         assertTrue(translucentStack.shouldBeVisible(null /* starting */));
 
-        final ActivityRecord topRunningHomeActivity = homeStack.topRunningActivityLocked();
         topRunningHomeActivity.finishing = true;
         final ActivityRecord topRunningTranslucentActivity =
                 translucentStack.topRunningActivityLocked();
@@ -577,13 +594,13 @@
     public void testMoveHomeStackBehindBottomMostVisibleStack_NoMoveHomeBehindFullscreen() {
         mDefaultDisplay.removeChild(mStack);
 
-        final TestActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
+        final ActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */);
-        final TestActivityStack fullscreenStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
+        final ActivityStack fullscreenStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
 
-        homeStack.setIsTranslucent(false);
-        fullscreenStack.setIsTranslucent(false);
+        doReturn(false).when(homeStack).isStackTranslucent(any());
+        doReturn(false).when(fullscreenStack).isStackTranslucent(any());
 
         // Ensure that we don't move the home stack if it is already behind the top fullscreen stack
         int homeStackIndex = mDefaultDisplay.getIndexOf(homeStack);
@@ -596,13 +613,13 @@
     public void testMoveHomeStackBehindBottomMostVisibleStack_NoMoveHomeBehindTranslucent() {
         mDefaultDisplay.removeChild(mStack);
 
-        final TestActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
+        final ActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */);
-        final TestActivityStack fullscreenStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
+        final ActivityStack fullscreenStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
 
-        homeStack.setIsTranslucent(false);
-        fullscreenStack.setIsTranslucent(true);
+        doReturn(false).when(homeStack).isStackTranslucent(any());
+        doReturn(true).when(fullscreenStack).isStackTranslucent(any());
 
         // Ensure that we don't move the home stack if it is already behind the top fullscreen stack
         int homeStackIndex = mDefaultDisplay.getIndexOf(homeStack);
@@ -615,13 +632,13 @@
     public void testMoveHomeStackBehindBottomMostVisibleStack_NoMoveHomeOnTop() {
         mDefaultDisplay.removeChild(mStack);
 
-        final TestActivityStack fullscreenStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
+        final ActivityStack fullscreenStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
-        final TestActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
+        final ActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */);
 
-        homeStack.setIsTranslucent(false);
-        fullscreenStack.setIsTranslucent(false);
+        doReturn(false).when(homeStack).isStackTranslucent(any());
+        doReturn(false).when(fullscreenStack).isStackTranslucent(any());
 
         // Ensure we don't move the home stack if it is already on top
         int homeStackIndex = mDefaultDisplay.getIndexOf(homeStack);
@@ -634,20 +651,20 @@
     public void testMoveHomeStackBehindBottomMostVisibleStack_MoveHomeBehindFullscreen() {
         mDefaultDisplay.removeChild(mStack);
 
-        final TestActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
+        final ActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */);
-        final TestActivityStack fullscreenStack1 = createStackForShouldBeVisibleTest(
+        final ActivityStack fullscreenStack1 = createStackForShouldBeVisibleTest(
                 mDefaultDisplay, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
                 true /* onTop */);
-        final TestActivityStack fullscreenStack2 = createStackForShouldBeVisibleTest(
+        final ActivityStack fullscreenStack2 = createStackForShouldBeVisibleTest(
                 mDefaultDisplay, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
                 true /* onTop */);
         final ActivityStack pinnedStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
                 WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD, true /* onTop */);
 
-        homeStack.setIsTranslucent(false);
-        fullscreenStack1.setIsTranslucent(false);
-        fullscreenStack2.setIsTranslucent(false);
+        doReturn(false).when(homeStack).isStackTranslucent(any());
+        doReturn(false).when(fullscreenStack1).isStackTranslucent(any());
+        doReturn(false).when(fullscreenStack2).isStackTranslucent(any());
 
         // Ensure that we move the home stack behind the bottom most fullscreen stack, ignoring the
         // pinned stack
@@ -661,18 +678,18 @@
             testMoveHomeStackBehindBottomMostVisibleStack_MoveHomeBehindFullscreenAndTranslucent() {
         mDefaultDisplay.removeChild(mStack);
 
-        final TestActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
+        final ActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */);
-        final TestActivityStack fullscreenStack1 = createStackForShouldBeVisibleTest(
+        final ActivityStack fullscreenStack1 = createStackForShouldBeVisibleTest(
                 mDefaultDisplay, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
                 true /* onTop */);
-        final TestActivityStack fullscreenStack2 = createStackForShouldBeVisibleTest(
+        final ActivityStack fullscreenStack2 = createStackForShouldBeVisibleTest(
                 mDefaultDisplay, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
                 true /* onTop */);
 
-        homeStack.setIsTranslucent(false);
-        fullscreenStack1.setIsTranslucent(false);
-        fullscreenStack2.setIsTranslucent(true);
+        doReturn(false).when(homeStack).isStackTranslucent(any());
+        doReturn(false).when(fullscreenStack1).isStackTranslucent(any());
+        doReturn(true).when(fullscreenStack2).isStackTranslucent(any());
 
         // Ensure that we move the home stack behind the bottom most non-translucent fullscreen
         // stack
@@ -685,18 +702,18 @@
     public void testMoveHomeStackBehindStack_BehindHomeStack() {
         mDefaultDisplay.removeChild(mStack);
 
-        final TestActivityStack fullscreenStack1 = createStackForShouldBeVisibleTest(
+        final ActivityStack fullscreenStack1 = createStackForShouldBeVisibleTest(
                 mDefaultDisplay, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
                 true /* onTop */);
-        final TestActivityStack fullscreenStack2 = createStackForShouldBeVisibleTest(
+        final ActivityStack fullscreenStack2 = createStackForShouldBeVisibleTest(
                 mDefaultDisplay, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
                 true /* onTop */);
-        final TestActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
+        final ActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */);
 
-        homeStack.setIsTranslucent(false);
-        fullscreenStack1.setIsTranslucent(false);
-        fullscreenStack2.setIsTranslucent(false);
+        doReturn(false).when(homeStack).isStackTranslucent(any());
+        doReturn(false).when(fullscreenStack1).isStackTranslucent(any());
+        doReturn(false).when(fullscreenStack2).isStackTranslucent(any());
 
         // Ensure we don't move the home stack behind itself
         int homeStackIndex = mDefaultDisplay.getIndexOf(homeStack);
@@ -708,19 +725,19 @@
     public void testMoveHomeStackBehindStack() {
         mDefaultDisplay.removeChild(mStack);
 
-        final TestActivityStack fullscreenStack1 = createStackForShouldBeVisibleTest(
+        final ActivityStack fullscreenStack1 = createStackForShouldBeVisibleTest(
                 mDefaultDisplay, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
                 true /* onTop */);
-        final TestActivityStack fullscreenStack2 = createStackForShouldBeVisibleTest(
+        final ActivityStack fullscreenStack2 = createStackForShouldBeVisibleTest(
                 mDefaultDisplay, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
                 true /* onTop */);
-        final TestActivityStack fullscreenStack3 = createStackForShouldBeVisibleTest(
+        final ActivityStack fullscreenStack3 = createStackForShouldBeVisibleTest(
                 mDefaultDisplay, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
                 true /* onTop */);
-        final TestActivityStack fullscreenStack4 = createStackForShouldBeVisibleTest(
+        final ActivityStack fullscreenStack4 = createStackForShouldBeVisibleTest(
                 mDefaultDisplay, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
                 true /* onTop */);
-        final TestActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
+        final ActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */);
 
         mDefaultDisplay.moveStackBehindStack(homeStack, fullscreenStack1);
@@ -735,13 +752,13 @@
 
     @Test
     public void testSetAlwaysOnTop() {
-        final TestActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
+        final ActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */);
         final ActivityStack pinnedStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
                 WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD, true /* onTop */);
         assertEquals(pinnedStack, mDefaultDisplay.getStackAbove(homeStack));
 
-        final TestActivityStack alwaysOnTopStack = createStackForShouldBeVisibleTest(
+        final ActivityStack alwaysOnTopStack = createStackForShouldBeVisibleTest(
                 mDefaultDisplay, WINDOWING_MODE_FREEFORM, ACTIVITY_TYPE_STANDARD,
                 true /* onTop */);
         alwaysOnTopStack.setAlwaysOnTop(true);
@@ -749,13 +766,13 @@
         // Ensure (non-pinned) always on top stack is put below pinned stack.
         assertEquals(pinnedStack, mDefaultDisplay.getStackAbove(alwaysOnTopStack));
 
-        final TestActivityStack nonAlwaysOnTopStack = createStackForShouldBeVisibleTest(
+        final ActivityStack nonAlwaysOnTopStack = createStackForShouldBeVisibleTest(
                 mDefaultDisplay, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
                 true /* onTop */);
         // Ensure non always on top stack is put below always on top stacks.
         assertEquals(alwaysOnTopStack, mDefaultDisplay.getStackAbove(nonAlwaysOnTopStack));
 
-        final TestActivityStack alwaysOnTopStack2 = createStackForShouldBeVisibleTest(
+        final ActivityStack alwaysOnTopStack2 = createStackForShouldBeVisibleTest(
                 mDefaultDisplay, WINDOWING_MODE_FREEFORM, ACTIVITY_TYPE_STANDARD,
                 true /* onTop */);
         alwaysOnTopStack2.setAlwaysOnTop(true);
@@ -780,18 +797,18 @@
 
     @Test
     public void testSplitScreenMoveToFront() {
-        final TestActivityStack splitScreenPrimary = createStackForShouldBeVisibleTest(
+        final ActivityStack splitScreenPrimary = createStackForShouldBeVisibleTest(
                 mDefaultDisplay, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD,
                 true /* onTop */);
-        final TestActivityStack splitScreenSecondary = createStackForShouldBeVisibleTest(
+        final ActivityStack splitScreenSecondary = createStackForShouldBeVisibleTest(
                 mDefaultDisplay, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, ACTIVITY_TYPE_STANDARD,
                 true /* onTop */);
-        final TestActivityStack assistantStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
+        final ActivityStack assistantStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_ASSISTANT, true /* onTop */);
 
-        splitScreenPrimary.setIsTranslucent(false);
-        splitScreenSecondary.setIsTranslucent(false);
-        assistantStack.setIsTranslucent(false);
+        doReturn(false).when(splitScreenPrimary).isStackTranslucent(any());
+        doReturn(false).when(splitScreenSecondary).isStackTranslucent(any());
+        doReturn(false).when(assistantStack).isStackTranslucent(any());
 
         assertFalse(splitScreenPrimary.shouldBeVisible(null /* starting */));
         assertFalse(splitScreenSecondary.shouldBeVisible(null /* starting */));
@@ -804,18 +821,18 @@
         assertFalse(assistantStack.shouldBeVisible(null /* starting */));
     }
 
-    private TestActivityStack createStandardStackForVisibilityTest(int windowingMode,
+    private ActivityStack createStandardStackForVisibilityTest(int windowingMode,
             boolean translucent) {
-        final TestActivityStack stack = createStackForShouldBeVisibleTest(mDefaultDisplay,
+        final ActivityStack stack = createStackForShouldBeVisibleTest(mDefaultDisplay,
                 windowingMode, ACTIVITY_TYPE_STANDARD, true /* onTop */);
-        stack.setIsTranslucent(translucent);
+        doReturn(translucent).when(stack).isStackTranslucent(any());
         return stack;
     }
 
     @SuppressWarnings("TypeParameterUnusedInFormals")
     private <T extends ActivityStack> T createStackForShouldBeVisibleTest(
             ActivityDisplay display, int windowingMode, int activityType, boolean onTop) {
-        final T stack;
+        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);
@@ -825,11 +842,15 @@
                 mDefaultDisplay.positionChildAtBottom(stack);
             }
         } else {
-            stack = display.createStack(windowingMode, activityType, onTop);
-            final ActivityRecord r = new ActivityBuilder(mService).setUid(0).setStack(stack)
-                    .setCreateTask(true).build();
+            stack = new StackBuilder(mRootActivityContainer)
+                    .setDisplay(display)
+                    .setWindowingMode(windowingMode)
+                    .setActivityType(activityType)
+                    .setOnTop(onTop)
+                    .setCreateActivity(true)
+                    .build();
         }
-        return stack;
+        return (T) stack;
     }
 
     @Test
@@ -961,11 +982,16 @@
 
     @Test
     public void testAdjustFocusedStackToHomeWhenNoActivity() {
+        final ActivityStack homeStask = mDefaultDisplay.getHomeStack();
+        TaskRecord homeTask = homeStask.topTask();
+        if (homeTask == null) {
+            // Create home task if there isn't one.
+            homeTask = new TaskBuilder(mSupervisor).setStack(homeStask).build();
+        }
+
         final ActivityRecord topActivity = new ActivityBuilder(mService).setTask(mTask).build();
         mStack.moveToFront("testAdjustFocusedStack");
 
-        final ActivityStack homeStask = mDefaultDisplay.getHomeStack();
-        final TaskRecord homeTask = homeStask.topTask();
         // Simulate that home activity has not been started or is force-stopped.
         homeStask.removeTask(homeTask, "testAdjustFocusedStack", REMOVE_TASK_MODE_DESTROYING);
 
@@ -981,6 +1007,14 @@
         final ActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */);
 
+        ActivityRecord activity = homeStack.topRunningActivityLocked();
+        if (activity == null) {
+            activity = new ActivityBuilder(mService)
+                    .setStack(homeStack)
+                    .setCreateTask(true)
+                    .build();
+        }
+
         // Home stack should not be destroyed immediately.
         final ActivityRecord activity1 = finishCurrentActivity(homeStack);
         assertEquals(FINISHING, activity1.getState());
@@ -1068,7 +1102,7 @@
     public void testStackOrderChangedOnPositionStack() {
         StackOrderChangedListener listener = new StackOrderChangedListener();
         try {
-            final TestActivityStack fullscreenStack1 = createStackForShouldBeVisibleTest(
+            final ActivityStack fullscreenStack1 = createStackForShouldBeVisibleTest(
                     mDefaultDisplay, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
                     true /* onTop */);
             mDefaultDisplay.registerStackOrderChangedListener(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 3d94467..40a029c 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
@@ -329,9 +329,6 @@
                 any(), any(), any(), anyInt(), anyInt(), anyInt(), any(),
                 anyBoolean(), anyBoolean(), any(), any(), any());
 
-        // Use factory that only returns spy task.
-        mockTaskRecordFactory();
-
         if (mockGetLaunchStack) {
             // Instrument the stack and task used.
             final ActivityStack stack = mRootActivityContainer.getDefaultDisplay().createStack(
@@ -482,7 +479,7 @@
     @Test
     public void testTaskModeViolation() {
         final ActivityDisplay display = mService.mRootActivityContainer.getDefaultDisplay();
-        ((TestActivityDisplay) display).removeAllTasks();
+        display.removeAllTasks();
         assertNoTasks(display);
 
         final ActivityStarter starter = prepareStarter(0);
@@ -676,18 +673,27 @@
         doReturn(isCallingUidDeviceOwner).when(mService).isDeviceOwner(callingUid);
 
         final ActivityOptions options = spy(ActivityOptions.makeBasic());
+        ActivityRecord[] outActivity = new ActivityRecord[1];
         ActivityStarter starter = prepareStarter(FLAG_ACTIVITY_NEW_TASK)
                 .setCallingPackage("com.whatever.dude")
                 .setCaller(caller)
                 .setCallingUid(callingUid)
                 .setRealCallingUid(realCallingUid)
-                .setActivityOptions(new SafeActivityOptions(options));
+                .setActivityOptions(new SafeActivityOptions(options))
+                .setOutActivity(outActivity);
 
         final int result = starter.setReason("testBackgroundActivityStarts_" + name).execute();
 
         assertEquals(ActivityStarter.getExternalResult(
                 shouldHaveAborted ? START_ABORTED : START_SUCCESS), result);
         verify(options, times(shouldHaveAborted ? 1 : 0)).abort();
+
+        final ActivityRecord startedActivity = outActivity[0];
+        if (startedActivity != null && startedActivity.getTaskRecord() != null) {
+            // Remove the activity so it doesn't interfere with with subsequent activity launch
+            // tests from this method.
+            startedActivity.getTaskRecord().removeActivity(startedActivity);
+        }
     }
 
     /**
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
index d8a9bb0..297aa7e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
@@ -45,8 +45,7 @@
     /** Verify that activity is finished correctly upon request. */
     @Test
     public void testActivityFinish() {
-        final TestActivityStack stack =
-                (TestActivityStack) new StackBuilder(mRootActivityContainer).build();
+        final ActivityStack stack = new StackBuilder(mRootActivityContainer).build();
         final ActivityRecord activity = stack.getChildAt(0).getTopActivity();
         assertTrue("Activity must be finished", mService.finishActivity(activity.appToken,
                 0 /* resultCode */, null /* resultData */,
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 ab2da2b..2e7218d 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
@@ -16,89 +16,55 @@
 
 package com.android.server.wm;
 
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
-import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
-import static android.view.Display.DEFAULT_DISPLAY;
-import static android.view.DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS;
+import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
 
 import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
 
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.any;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyBoolean;
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyInt;
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyString;
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.doCallRealMethod;
 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.reset;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
-import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_DESTROYING;
-import static com.android.server.wm.ActivityStackSupervisor.ON_TOP;
 
-import android.app.ActivityManagerInternal;
 import android.app.ActivityOptions;
-import android.app.AppOpsManager;
 import android.app.IApplicationThread;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
-import android.content.pm.IPackageManager;
-import android.content.pm.PackageManagerInternal;
 import android.content.res.Configuration;
 import android.graphics.Rect;
-import android.hardware.display.DisplayManager;
-import android.hardware.display.DisplayManagerGlobal;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.PowerManager;
-import android.os.Process;
 import android.os.UserHandle;
 import android.service.voice.IVoiceInteractionSession;
 import android.testing.DexmakerShareClassLoaderRule;
-import android.view.Display;
 import android.view.DisplayInfo;
 
-import com.android.internal.app.IVoiceInteractor;
 import com.android.server.AttributeCache;
-import com.android.server.ServiceThread;
-import com.android.server.am.ActivityManagerService;
-import com.android.server.am.PendingIntentController;
-import com.android.server.appop.AppOpsService;
-import com.android.server.firewall.IntentFirewall;
-import com.android.server.policy.PermissionPolicyInternal;
-import com.android.server.uri.UriGrantsManagerInternal;
-import com.android.server.wm.TaskRecord.TaskRecordFactory;
 import com.android.server.wm.utils.MockTracker;
 
 import org.junit.After;
 import org.junit.Before;
 import org.junit.BeforeClass;
 import org.junit.Rule;
-import org.mockito.invocation.InvocationOnMock;
-
-import java.io.File;
-import java.util.List;
-import java.util.function.Consumer;
 
 /**
  * A base class to handle common operations in activity related unit tests.
  */
 class ActivityTestsBase {
-    private static int sNextDisplayId = DEFAULT_DISPLAY + 1;
 
     @Rule
     public final DexmakerShareClassLoaderRule mDexmakerShareClassLoaderRule =
             new DexmakerShareClassLoaderRule();
 
+    @Rule
+    public final SystemServicesTestRule mSystemServicesTestRule = new SystemServicesTestRule();
+
     final Context mContext = getInstrumentation().getTargetContext();
-    final TestInjector mTestInjector = new TestInjector(mContext);
 
     ActivityTaskManagerService mService;
     RootActivityContainer mRootActivityContainer;
@@ -121,35 +87,24 @@
     public void setUpBase() {
         mMockTracker = new MockTracker();
 
-        mTestInjector.setUp();
-
-        mService = new TestActivityTaskManagerService(mContext);
+        mService = mSystemServicesTestRule.getActivityTaskManagerService();
         mSupervisor = mService.mStackSupervisor;
         mRootActivityContainer = mService.mRootActivityContainer;
     }
 
     @After
     public void tearDownBase() {
-        mTestInjector.tearDown();
-        if (mService != null) {
-            mService.setWindowManager(null);
-            mService = null;
-        }
-        if (sMockWindowManagerService != null) {
-            reset(sMockWindowManagerService);
-        }
-
         mMockTracker.close();
         mMockTracker = null;
     }
 
     /** Creates a {@link TestActivityDisplay}. */
     TestActivityDisplay createNewActivityDisplay() {
-        return TestActivityDisplay.create(mSupervisor, sNextDisplayId++);
+        return TestActivityDisplay.create(mSupervisor);
     }
 
     TestActivityDisplay createNewActivityDisplay(DisplayInfo info) {
-        return TestActivityDisplay.create(mSupervisor, sNextDisplayId++, info);
+        return TestActivityDisplay.create(mSupervisor, info);
     }
 
     /** Creates and adds a {@link TestActivityDisplay} to supervisor at the given position. */
@@ -166,25 +121,9 @@
         return display;
     }
 
-    /**
-     * Delegates task creation to {@link #TaskBuilder} to avoid the dependency of window hierarchy
-     * when starting activity in unit tests.
-     */
-    void mockTaskRecordFactory(Consumer<TaskBuilder> taskBuilderSetup) {
-        final TaskBuilder taskBuilder = new TaskBuilder(mSupervisor).setCreateStack(false);
-        if (taskBuilderSetup != null) {
-            taskBuilderSetup.accept(taskBuilder);
-        }
-        final TaskRecord task = taskBuilder.build();
-        final TaskRecordFactory factory = mock(TaskRecordFactory.class);
-        TaskRecord.setTaskRecordFactory(factory);
-        doReturn(task).when(factory).create(any() /* service */, anyInt() /* taskId */,
-                any() /* info */, any() /* intent */, any() /* voiceSession */,
-                any() /* voiceInteractor */);
-    }
-
-    void mockTaskRecordFactory() {
-        mockTaskRecordFactory(null /* taskBuilderSetup */);
+    /** Sets the default minimum task size to 1 so that tests can use small task sizes */
+    public void removeGlobalMinSizeRestriction() {
+        mService.mRootActivityContainer.mDefaultMinSizeOfResizeableTaskDp = 1;
     }
 
     /**
@@ -204,6 +143,11 @@
         private ActivityStack mStack;
         private int mActivityFlags;
         private int mLaunchMode;
+        private int mResizeMode = RESIZE_MODE_RESIZEABLE;
+        private float mMaxAspectRatio;
+        private int mScreenOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
+        private boolean mLaunchTaskBehind;
+        private int mConfigChanges;
 
         ActivityBuilder(ActivityTaskManagerService service) {
             mService = service;
@@ -254,6 +198,31 @@
             return this;
         }
 
+        ActivityBuilder setResizeMode(int resizeMode) {
+            mResizeMode = resizeMode;
+            return this;
+        }
+
+        ActivityBuilder setMaxAspectRatio(float maxAspectRatio) {
+            mMaxAspectRatio = maxAspectRatio;
+            return this;
+        }
+
+        ActivityBuilder setScreenOrientation(int screenOrientation) {
+            mScreenOrientation = screenOrientation;
+            return this;
+        }
+
+        ActivityBuilder setLaunchTaskBehind(boolean launchTaskBehind) {
+            mLaunchTaskBehind = launchTaskBehind;
+            return this;
+        }
+
+        ActivityBuilder setConfigChanges(int configChanges) {
+            mConfigChanges = configChanges;
+            return this;
+        }
+
         ActivityRecord build() {
             if (mComponent == null) {
                 final int id = sCurrentActivityId++;
@@ -279,24 +248,31 @@
             }
             aInfo.flags |= mActivityFlags;
             aInfo.launchMode = mLaunchMode;
+            aInfo.resizeMode = mResizeMode;
+            aInfo.maxAspectRatio = mMaxAspectRatio;
+            aInfo.screenOrientation = mScreenOrientation;
+            aInfo.configChanges |= mConfigChanges;
+
+            ActivityOptions options = null;
+            if (mLaunchTaskBehind) {
+                options =  ActivityOptions.makeTaskLaunchBehind();
+            }
 
             final ActivityRecord activity = new ActivityRecord(mService, null /* caller */,
                     0 /* launchedFromPid */, 0, null, intent, null,
                     aInfo /*aInfo*/, new Configuration(), null /* resultTo */, null /* resultWho */,
                     0 /* reqCode */, false /*componentSpecified*/, false /* rootVoiceInteraction */,
-                    mService.mStackSupervisor, null /* options */, null /* sourceRecord */);
+                    mService.mStackSupervisor, options, null /* sourceRecord */);
             spyOn(activity);
-            activity.mAppWindowToken = mock(AppWindowToken.class);
-            doCallRealMethod().when(activity.mAppWindowToken).getOrientationIgnoreVisibility();
-            doCallRealMethod().when(activity.mAppWindowToken)
-                    .setOrientation(anyInt(), any(), any());
-            doCallRealMethod().when(activity.mAppWindowToken).setOrientation(anyInt());
-            doNothing().when(activity).removeWindowContainer();
-            doReturn(mock(Configuration.class)).when(activity.mAppWindowToken)
-                    .getRequestedOverrideConfiguration();
-
             if (mTaskRecord != null) {
-                mTaskRecord.addActivityToTop(activity);
+                // fullscreen value is normally read from resources in ctor, so for testing we need
+                // to set it somewhere else since we can't mock resources.
+                activity.fullscreen = true;
+                activity.setTask(mTaskRecord);
+                activity.createAppWindowToken();
+                spyOn(activity.mAppWindowToken);
+                // Make visible by default...
+                activity.mAppWindowToken.setHidden(false);
             }
 
             final WindowProcessController wpc = new WindowProcessController(mService,
@@ -305,6 +281,9 @@
                     mock(WindowProcessListener.class));
             wpc.setThread(mock(IApplicationThread.class));
             activity.setProcess(wpc);
+
+            // Resume top activities to make sure all other signals in the system are connected.
+            mService.mRootActivityContainer.resumeFocusedStacksTopActivities();
             return activity;
         }
     }
@@ -313,16 +292,13 @@
      * Builder for creating new tasks.
      */
     protected static class TaskBuilder {
-        // Default package name
-        static final String DEFAULT_PACKAGE = "com.bar";
-
         private final ActivityStackSupervisor mSupervisor;
 
         private ComponentName mComponent;
         private String mPackage;
         private int mFlags = 0;
         // Task id 0 is reserved in ARC for the home app.
-        private int mTaskId = 1;
+        private int mTaskId = SystemServicesTestRule.sNextTaskId++;
         private int mUserId = 0;
         private IVoiceInteractionSession mVoiceSession;
         private boolean mCreateStack = true;
@@ -381,6 +357,7 @@
             if (mStack == null && mCreateStack) {
                 mStack = mSupervisor.mRootActivityContainer.getDefaultDisplay().createStack(
                         WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
+                spyOn(mStack);
             }
 
             final ActivityInfo aInfo = new ActivityInfo();
@@ -396,450 +373,22 @@
             intent.setComponent(mComponent);
             intent.setFlags(mFlags);
 
-            final TestTaskRecord task = new TestTaskRecord(mSupervisor.mService, mTaskId, aInfo,
+            final TaskRecord task = new TaskRecord(mSupervisor.mService, mTaskId, aInfo,
                     intent /*intent*/, mVoiceSession, null /*_voiceInteractor*/);
+            spyOn(task);
             task.userId = mUserId;
 
             if (mStack != null) {
                 mStack.moveToFront("test");
                 mStack.addTask(task, true, "creating test task");
-                task.setStack(mStack);
-                task.setTask();
-                mStack.getTaskStack().addChild(task.mTask, 0);
+                task.createTask(true, true);
+                spyOn(task.mTask);
             }
 
             task.touchActiveTime();
 
             return task;
         }
-
-        private static class TestTaskRecord extends TaskRecord {
-            TestTaskRecord(ActivityTaskManagerService service, int taskId, ActivityInfo info,
-                       Intent intent, IVoiceInteractionSession voiceSession,
-                       IVoiceInteractor voiceInteractor) {
-                super(service, taskId, info, intent, voiceSession, voiceInteractor);
-            }
-
-            @Override
-            void createTask(boolean onTop, boolean showForAllUsers) {
-                setTask();
-            }
-
-            void setTask() {
-                Task mockTask = mock(Task.class);
-                mockTask.mTaskRecord = this;
-                doCallRealMethod().when(mockTask).onDescendantOrientationChanged(any(), any());
-                setTask(mock(Task.class));
-            }
-        }
-    }
-
-    protected class TestActivityTaskManagerService extends ActivityTaskManagerService {
-        private PackageManagerInternal mPmInternal;
-        private PermissionPolicyInternal mPermissionPolicyInternal;
-
-        // ActivityStackSupervisor may be created more than once while setting up AMS and ATMS.
-        // We keep the reference in order to prevent creating it twice.
-        ActivityStackSupervisor mTestStackSupervisor;
-
-        ActivityDisplay mDefaultDisplay;
-        AppOpsService mAppOpsService;
-
-        TestActivityTaskManagerService(Context context) {
-            super(context);
-            spyOn(this);
-
-            mUgmInternal = mock(UriGrantsManagerInternal.class);
-            mAppOpsService = mock(AppOpsService.class);
-
-            // Make sure permission checks aren't overridden.
-            doReturn(AppOpsManager.MODE_DEFAULT)
-                    .when(mAppOpsService).noteOperation(anyInt(), anyInt(), anyString());
-
-            mSupportsMultiWindow = true;
-            mSupportsMultiDisplay = true;
-            mSupportsSplitScreenMultiWindow = true;
-            mSupportsFreeformWindowManagement = true;
-            mSupportsPictureInPicture = true;
-
-            final TestActivityManagerService am =
-                    new TestActivityManagerService(mTestInjector, this);
-
-            spyOn(getLifecycleManager());
-            spyOn(getLockTaskController());
-            spyOn(getTaskChangeNotificationController());
-            doReturn(mock(IPackageManager.class)).when(this).getPackageManager();
-            // allow background activity starts by default
-            doReturn(true).when(this).isBackgroundActivityStartsEnabled();
-            doNothing().when(this).updateCpuStats();
-        }
-
-        void setup(IntentFirewall intentFirewall, PendingIntentController intentController,
-                ActivityManagerInternal amInternal, WindowManagerService wm, Looper looper) {
-            mAmInternal = amInternal;
-            initialize(intentFirewall, intentController, looper);
-            initRootActivityContainerMocks(wm);
-            setWindowManager(wm);
-            createDefaultDisplay();
-        }
-
-        void initRootActivityContainerMocks(WindowManagerService wm) {
-            spyOn(mRootActivityContainer);
-            mRootActivityContainer.setWindowContainer(mock(RootWindowContainer.class));
-            mRootActivityContainer.mWindowManager = wm;
-            mRootActivityContainer.mDisplayManager =
-                    (DisplayManager) mContext.getSystemService(Context.DISPLAY_SERVICE);
-            doNothing().when(mRootActivityContainer).setWindowManager(any());
-            // 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());
-        }
-
-        void createDefaultDisplay() {
-            // Create a default display and put a home stack on it so that we'll always have
-            // something focusable.
-            mDefaultDisplay = TestActivityDisplay.create(mStackSupervisor, DEFAULT_DISPLAY);
-            spyOn(mDefaultDisplay);
-            mRootActivityContainer.addChild(mDefaultDisplay, ActivityDisplay.POSITION_TOP);
-            mDefaultDisplay.createStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, ON_TOP);
-            final TaskRecord task = new TaskBuilder(mStackSupervisor)
-                    .setStack(mDefaultDisplay.getHomeStack()).build();
-            new ActivityBuilder(this).setTask(task).build();
-
-            doReturn(mDefaultDisplay).when(mRootActivityContainer).getDefaultDisplay();
-        }
-
-        @Override
-        int handleIncomingUser(int callingPid, int callingUid, int userId, String name) {
-            return userId;
-        }
-
-        @Override
-        AppOpsService getAppOpsService() {
-            return mAppOpsService;
-        }
-
-        @Override
-        void updateCpuStats() {
-        }
-
-        @Override
-        void updateBatteryStats(ActivityRecord component, boolean resumed) {
-        }
-
-        @Override
-        void updateActivityUsageStats(ActivityRecord activity, int event) {
-        }
-
-        @Override
-        protected ActivityStackSupervisor createStackSupervisor() {
-            if (mTestStackSupervisor == null) {
-                mTestStackSupervisor = new TestActivityStackSupervisor(this, mH.getLooper());
-            }
-            return mTestStackSupervisor;
-        }
-
-        @Override
-        PackageManagerInternal getPackageManagerInternalLocked() {
-            if (mPmInternal == null) {
-                mPmInternal = mock(PackageManagerInternal.class);
-                doReturn(false)
-                        .when(mPmInternal)
-                        .isPermissionsReviewRequired(anyString(), anyInt());
-            }
-            return mPmInternal;
-        }
-
-        @Override
-        PermissionPolicyInternal getPermissionPolicyInternal() {
-            if (mPermissionPolicyInternal == null) {
-                mPermissionPolicyInternal = mock(PermissionPolicyInternal.class);
-                doReturn(true).when(mPermissionPolicyInternal).checkStartActivity(any(), anyInt(),
-                        any());
-            }
-            return mPermissionPolicyInternal;
-        }
-    }
-
-    private static class TestInjector extends ActivityManagerService.Injector {
-        private ServiceThread mHandlerThread;
-
-        TestInjector(Context context) {
-            super(context);
-        }
-
-        @Override
-        public AppOpsService getAppOpsService(File file, Handler handler) {
-            return null;
-        }
-
-        @Override
-        public Handler getUiHandler(ActivityManagerService service) {
-            return mHandlerThread.getThreadHandler();
-        }
-
-        @Override
-        public boolean isNetworkRestrictedForUid(int uid) {
-            return false;
-        }
-
-        void setUp() {
-            mHandlerThread = new ServiceThread("ActivityTestsThread",
-                    Process.THREAD_PRIORITY_DEFAULT, true /* allowIo */);
-            mHandlerThread.start();
-        }
-
-        void tearDown() {
-            // Make sure there are no running messages and then quit the thread so the next test
-            // won't be affected.
-            mHandlerThread.getThreadHandler().runWithScissors(mHandlerThread::quit,
-                    0 /* timeout */);
-        }
-    }
-
-    // TODO: Replace this with a mock object since we are no longer in AMS package.
-    /**
-     * An {@link ActivityManagerService} subclass which provides a test
-     * {@link ActivityStackSupervisor}.
-     */
-    class TestActivityManagerService extends ActivityManagerService {
-
-        TestActivityManagerService(TestInjector testInjector, TestActivityTaskManagerService atm) {
-            super(testInjector, testInjector.mHandlerThread);
-            spyOn(this);
-
-            mWindowManager = prepareMockWindowManager();
-            mUgmInternal = mock(UriGrantsManagerInternal.class);
-
-            atm.setup(mIntentFirewall, mPendingIntentController, new LocalService(), mWindowManager,
-                    testInjector.mHandlerThread.getLooper());
-
-            mActivityTaskManager = atm;
-            mAtmInternal = atm.mInternal;
-
-            doReturn(mock(IPackageManager.class)).when(this).getPackageManager();
-            PackageManagerInternal mockPackageManager = mock(PackageManagerInternal.class);
-            doReturn(mockPackageManager).when(this).getPackageManagerInternalLocked();
-            doReturn(null).when(mockPackageManager).getDefaultHomeActivity(anyInt());
-            doNothing().when(this).grantEphemeralAccessLocked(anyInt(), any(), anyInt(), anyInt());
-        }
-    }
-
-    /**
-     * An {@link ActivityStackSupervisor} which stubs out certain methods that depend on
-     * setup not available in the test environment. Also specifies an injector for
-     */
-    protected class TestActivityStackSupervisor extends ActivityStackSupervisor {
-        private KeyguardController mKeyguardController;
-
-        TestActivityStackSupervisor(ActivityTaskManagerService service, Looper looper) {
-            super(service, looper);
-            spyOn(this);
-            mWindowManager = prepareMockWindowManager();
-            mKeyguardController = mock(KeyguardController.class);
-
-            // Do not schedule idle that may touch methods outside the scope of the test.
-            doNothing().when(this).scheduleIdleLocked();
-            doNothing().when(this).scheduleIdleTimeoutLocked(any());
-            // unit test version does not handle launch wake lock
-            doNothing().when(this).acquireLaunchWakelock();
-            doReturn(mKeyguardController).when(this).getKeyguardController();
-
-            mLaunchingActivityWakeLock = mock(PowerManager.WakeLock.class);
-
-            initialize();
-        }
-
-        @Override
-        public KeyguardController getKeyguardController() {
-            return mKeyguardController;
-        }
-
-        @Override
-        void setWindowManager(WindowManagerService wm) {
-            mWindowManager = wm;
-        }
-    }
-
-    protected static class TestActivityDisplay extends ActivityDisplay {
-        private final ActivityStackSupervisor mSupervisor;
-
-        static TestActivityDisplay create(ActivityStackSupervisor supervisor, int displayId) {
-            return create(supervisor, displayId, new DisplayInfo());
-        }
-
-        static TestActivityDisplay create(ActivityStackSupervisor supervisor, int displayId,
-                DisplayInfo info) {
-            if (displayId == DEFAULT_DISPLAY) {
-                return new TestActivityDisplay(supervisor,
-                        supervisor.mRootActivityContainer.mDisplayManager.getDisplay(displayId));
-            }
-            final Display display = new Display(DisplayManagerGlobal.getInstance(), displayId,
-                    info, DEFAULT_DISPLAY_ADJUSTMENTS);
-            return new TestActivityDisplay(supervisor, display);
-        }
-
-        TestActivityDisplay(ActivityStackSupervisor supervisor, Display display) {
-            super(supervisor.mService.mRootActivityContainer, display);
-            // Normally this comes from display-properties as exposed by WM. Without that, just
-            // hard-code to FULLSCREEN for tests.
-            setWindowingMode(WINDOWING_MODE_FULLSCREEN);
-            mSupervisor = supervisor;
-        }
-
-        @SuppressWarnings("TypeParameterUnusedInFormals")
-        @Override
-        ActivityStack createStackUnchecked(int windowingMode, int activityType,
-                int stackId, boolean onTop) {
-            return new StackBuilder(mSupervisor.mRootActivityContainer).setDisplay(this)
-                    .setWindowingMode(windowingMode).setActivityType(activityType)
-                    .setStackId(stackId).setOnTop(onTop).setCreateActivity(false).build();
-        }
-
-        @Override
-        protected DisplayContent createDisplayContent() {
-            final DisplayContent displayContent = mock(DisplayContent.class);
-            DockedStackDividerController divider = mock(DockedStackDividerController.class);
-            doReturn(divider).when(displayContent).getDockedDividerController();
-            return displayContent;
-        }
-
-        void removeAllTasks() {
-            for (int i = 0; i < getChildCount(); i++) {
-                final ActivityStack stack = getChildAt(i);
-                for (TaskRecord task : (List<TaskRecord>) stack.getAllTasks()) {
-                    stack.removeTask(task, "removeAllTasks", REMOVE_TASK_MODE_DESTROYING);
-                }
-            }
-        }
-    }
-
-    private static WindowManagerService sMockWindowManagerService;
-
-    private static WindowManagerService prepareMockWindowManager() {
-        if (sMockWindowManagerService == null) {
-            sMockWindowManagerService = mock(WindowManagerService.class);
-        }
-
-        sMockWindowManagerService.mRoot = mock(RootWindowContainer.class);
-
-        doAnswer((InvocationOnMock invocationOnMock) -> {
-            final Runnable runnable = invocationOnMock.<Runnable>getArgument(0);
-            if (runnable != null) {
-                runnable.run();
-            }
-            return null;
-        }).when(sMockWindowManagerService).inSurfaceTransaction(any());
-
-        return sMockWindowManagerService;
-    }
-
-    /**
-     * Overridden {@link ActivityStack} that tracks test metrics, such as the number of times a
-     * method is called. Note that its functionality depends on the implementations of the
-     * construction arguments.
-     */
-    protected static class TestActivityStack
-            extends ActivityStack {
-        private int mOnActivityRemovedFromStackCount = 0;
-
-        static final int IS_TRANSLUCENT_UNSET = 0;
-        static final int IS_TRANSLUCENT_FALSE = 1;
-        static final int IS_TRANSLUCENT_TRUE = 2;
-        private int mIsTranslucent = IS_TRANSLUCENT_UNSET;
-
-        static final int SUPPORTS_SPLIT_SCREEN_UNSET = 0;
-        static final int SUPPORTS_SPLIT_SCREEN_FALSE = 1;
-        static final int SUPPORTS_SPLIT_SCREEN_TRUE = 2;
-        private int mSupportsSplitScreen = SUPPORTS_SPLIT_SCREEN_UNSET;
-
-        TestActivityStack(ActivityDisplay display, int stackId, ActivityStackSupervisor supervisor,
-                int windowingMode, int activityType, boolean onTop, boolean createActivity) {
-            super(display, stackId, supervisor, windowingMode, activityType, onTop);
-            if (createActivity) {
-                new ActivityBuilder(mService).setCreateTask(true).setStack(this).build();
-                if (onTop) {
-                    // We move the task to front again in order to regain focus after activity
-                    // added to the stack. Or {@link ActivityDisplay#mPreferredTopFocusableStack}
-                    // could be other stacks (e.g. home stack).
-                    moveToFront("createActivityStack");
-                } else {
-                    moveToBack("createActivityStack", null);
-                }
-            }
-        }
-
-        @Override
-        void onActivityRemovedFromStack(ActivityRecord r) {
-            mOnActivityRemovedFromStackCount++;
-            super.onActivityRemovedFromStack(r);
-        }
-
-        // Returns the number of times {@link #onActivityRemovedFromStack} has been called
-        int onActivityRemovedFromStackInvocationCount() {
-            return mOnActivityRemovedFromStackCount;
-        }
-
-        @Override
-        protected void createTaskStack(int displayId, boolean onTop, Rect outBounds) {
-            mTaskStack = mock(TaskStack.class);
-
-            // Primary pinned stacks require a non-empty out bounds to be set or else all tasks
-            // will be moved to the full screen stack.
-            if (getWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
-                outBounds.set(0, 0, 100, 100);
-            }
-        }
-
-        @Override
-        TaskStack getTaskStack() {
-            return mTaskStack;
-        }
-
-        void setIsTranslucent(boolean isTranslucent) {
-            mIsTranslucent = isTranslucent ? IS_TRANSLUCENT_TRUE : IS_TRANSLUCENT_FALSE;
-        }
-
-        @Override
-        boolean isStackTranslucent(ActivityRecord starting) {
-            switch (mIsTranslucent) {
-                case IS_TRANSLUCENT_TRUE:
-                    return true;
-                case IS_TRANSLUCENT_FALSE:
-                    return false;
-                case IS_TRANSLUCENT_UNSET:
-                default:
-                    return super.isStackTranslucent(starting);
-            }
-        }
-
-        void setSupportsSplitScreen(boolean supportsSplitScreen) {
-            mSupportsSplitScreen = supportsSplitScreen
-                    ? SUPPORTS_SPLIT_SCREEN_TRUE : SUPPORTS_SPLIT_SCREEN_FALSE;
-        }
-
-        @Override
-        public boolean supportsSplitScreenWindowingMode() {
-            switch (mSupportsSplitScreen) {
-                case SUPPORTS_SPLIT_SCREEN_TRUE:
-                    return true;
-                case SUPPORTS_SPLIT_SCREEN_FALSE:
-                    return false;
-                case SUPPORTS_SPLIT_SCREEN_UNSET:
-                default:
-                    return super.supportsSplitScreenWindowingMode();
-            }
-        }
-
-        @Override
-        void startActivityLocked(ActivityRecord r, ActivityRecord focusedTopActivity,
-                                 boolean newTask, boolean keepCurTransition,
-                                 ActivityOptions options) {
-        }
     }
 
     static class StackBuilder {
@@ -886,27 +435,45 @@
             return this;
         }
 
-        @SuppressWarnings("TypeParameterUnusedInFormals")
         ActivityStack build() {
             final int stackId = mStackId >= 0 ? mStackId : mDisplay.getNextStackId();
+            final ActivityStack stack;
+            final ActivityStackSupervisor supervisor = mRootActivityContainer.mStackSupervisor;
             if (mWindowingMode == WINDOWING_MODE_PINNED) {
-                return new ActivityStack(mDisplay, stackId, mRootActivityContainer.mStackSupervisor,
+                stack = new ActivityStack(mDisplay, stackId, supervisor,
                         mWindowingMode, ACTIVITY_TYPE_STANDARD, mOnTop) {
                     @Override
                     Rect getDefaultPictureInPictureBounds(float aspectRatio) {
                         return new Rect(50, 50, 100, 100);
                     }
-
-                    @Override
-                    void createTaskStack(int displayId, boolean onTop, Rect outBounds) {
-                        mTaskStack = mock(TaskStack.class);
-                    }
                 };
             } else {
-                return new TestActivityStack(mDisplay, stackId,
-                        mRootActivityContainer.mStackSupervisor, mWindowingMode,
-                        mActivityType, mOnTop, mCreateActivity);
+                stack = new ActivityStack(mDisplay, stackId, supervisor,
+                        mWindowingMode, mActivityType, mOnTop);
+
+                if (mCreateActivity) {
+                    new ActivityBuilder(supervisor.mService)
+                            .setCreateTask(true)
+                            .setStack(stack)
+                            .build();
+                    if (mOnTop) {
+                        // We move the task to front again in order to regain focus after activity
+                        // added to the stack.
+                        // Or {@link ActivityDisplay#mPreferredTopFocusableStack} could be other
+                        // stacks (e.g. home stack).
+                        stack.moveToFront("createActivityStack");
+                    } else {
+                        stack.moveToBack("createActivityStack", null);
+                    }
+                }
             }
+
+            spyOn(stack);
+            spyOn(stack.mTaskStack);
+            doNothing().when(stack).startActivityLocked(
+                    any(), any(), anyBoolean(), anyBoolean(), any());
+
+            return stack;
         }
 
     }
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
index d1dc382..c162b6a 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
@@ -30,12 +30,14 @@
 
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyBoolean;
 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.spyOn;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
 
 import android.graphics.Rect;
 import android.os.IBinder;
@@ -195,6 +197,7 @@
     @Test
     public void testCancelRemoteAnimationWhenFreeze() {
         final DisplayContent dc = createNewDisplay(Display.STATE_ON);
+        doReturn(false).when(dc).onDescendantOrientationChanged(any(), any());
         final WindowState exitingAppWindow = createWindow(null /* parent */, TYPE_BASE_APPLICATION,
                 dc, "exiting app");
         final AppWindowToken exitingAppToken = exitingAppWindow.mAppToken;
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
index d9566a3..db2895b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
@@ -36,7 +36,7 @@
 import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
 
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
 import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_AFTER_ANIM;
 import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_BEFORE_ANIM;
 import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_NONE;
@@ -152,10 +152,6 @@
     @Test
     @FlakyTest(bugId = 131005232)
     public void testLandscapeSeascapeRotationByApp() {
-        // Some plumbing to get the service ready for rotation updates.
-        mWm.mDisplayReady = true;
-        mWm.mDisplayEnabled = true;
-
         final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(
                 TYPE_BASE_APPLICATION);
         attrs.setTitle("AppWindow");
@@ -185,25 +181,21 @@
 
     @Test
     public void testLandscapeSeascapeRotationByPolicy() {
-        // Some plumbing to get the service ready for rotation updates.
-        mWm.mDisplayReady = true;
-        mWm.mDisplayEnabled = true;
-
-        final DisplayRotation spiedRotation = spy(mDisplayContent.getDisplayRotation());
-        mDisplayContent.setDisplayRotation(spiedRotation);
+        final DisplayRotation displayRotation = mDisplayContent.getDisplayRotation();
+        spyOn(displayRotation);
 
         final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(
                 TYPE_BASE_APPLICATION);
-        attrs.setTitle("AppWindow");
+        attrs.setTitle("RotationByPolicy");
         final WindowTestUtils.TestWindowState appWindow = createWindowState(attrs, mToken);
         mToken.addWindow(appWindow);
 
         // Set initial orientation and update.
-        performRotation(spiedRotation, Surface.ROTATION_90);
+        performRotation(displayRotation, Surface.ROTATION_90);
         appWindow.mResizeReported = false;
 
         // Update the rotation to perform 180 degree rotation and check that resize was reported.
-        performRotation(spiedRotation, Surface.ROTATION_270);
+        performRotation(displayRotation, Surface.ROTATION_270);
         assertTrue(appWindow.mResizeReported);
 
         appWindow.removeImmediately();
@@ -211,14 +203,7 @@
 
     private void performRotation(DisplayRotation spiedRotation, int rotationToReport) {
         doReturn(rotationToReport).when(spiedRotation).rotationForOrientation(anyInt(), anyInt());
-        int oldRotation = mDisplayContent.getRotation();
         mWm.updateRotation(false, false);
-        // Must manually apply here since ATM doesn't know about the display during this test
-        // (meaning it can't perform the normal sendNewConfiguration flow).
-        mDisplayContent.applyRotationLocked(oldRotation, mDisplayContent.getRotation());
-        // Prevent the next rotation from being deferred by animation.
-        mWm.mAnimator.setScreenRotationAnimationLocked(mDisplayContent.getDisplayId(), null);
-        mWm.mRoot.performSurfacePlacement(false /* recoveringMemory */);
     }
 
     @Test
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 388658d..6289768 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -83,7 +83,6 @@
 
 import androidx.test.filters.SmallTest;
 
-import com.android.dx.mockito.inline.extended.ExtendedMockito;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto;
 import com.android.server.wm.utils.WmDisplayCutout;
@@ -653,25 +652,27 @@
     @Test
     public void testOnDescendantOrientationRequestChanged() {
         final DisplayContent dc = createNewDisplay();
-        mWm.mAtmService.mRootActivityContainer = mock(RootActivityContainer.class);
+        dc.getDisplayRotation().setFixedToUserRotation(
+                DisplayRotation.FIXED_TO_USER_ROTATION_DISABLED);
         final int newOrientation = dc.getLastOrientation() == SCREEN_ORIENTATION_LANDSCAPE
                 ? SCREEN_ORIENTATION_PORTRAIT
                 : SCREEN_ORIENTATION_LANDSCAPE;
 
-        final WindowState window = createWindow(null /* parent */, TYPE_BASE_APPLICATION, dc, "w");
-        window.getTask().mTaskRecord = mock(TaskRecord.class, ExtendedMockito.RETURNS_DEEP_STUBS);
-        window.mAppToken.setOrientation(newOrientation);
+        final ActivityStack stack =
+                new ActivityTestsBase.StackBuilder(mWm.mAtmService.mRootActivityContainer)
+                        .setDisplay(dc.mAcitvityDisplay).build();
+        final ActivityRecord activity = stack.topTask().getTopActivity();
 
-        ActivityRecord activityRecord = mock(ActivityRecord.class);
-
-        assertTrue("Display should rotate to handle orientation request by default.",
-                dc.onDescendantOrientationChanged(window.mToken.token, activityRecord));
+        activity.setRequestedOrientation(newOrientation);
 
         final ArgumentCaptor<Configuration> captor = ArgumentCaptor.forClass(Configuration.class);
         verify(dc.mAcitvityDisplay).updateDisplayOverrideConfigurationLocked(captor.capture(),
-                same(activityRecord), anyBoolean(), same(null));
+                same(activity), anyBoolean(), same(null));
         final Configuration newDisplayConfig = captor.getValue();
-        assertEquals(Configuration.ORIENTATION_PORTRAIT, newDisplayConfig.orientation);
+        final int expectedOrientation = newOrientation == SCREEN_ORIENTATION_PORTRAIT
+                ? Configuration.ORIENTATION_PORTRAIT
+                : Configuration.ORIENTATION_LANDSCAPE;
+        assertEquals(expectedOrientation, newDisplayConfig.orientation);
     }
 
     @Test
@@ -679,22 +680,20 @@
         final DisplayContent dc = createNewDisplay();
         dc.getDisplayRotation().setFixedToUserRotation(
                 DisplayRotation.FIXED_TO_USER_ROTATION_ENABLED);
-        mWm.mAtmService.mRootActivityContainer = mock(RootActivityContainer.class);
         final int newOrientation = dc.getLastOrientation() == SCREEN_ORIENTATION_LANDSCAPE
                 ? SCREEN_ORIENTATION_PORTRAIT
                 : SCREEN_ORIENTATION_LANDSCAPE;
 
-        final WindowState window = createWindow(null /* parent */, TYPE_BASE_APPLICATION, dc, "w");
-        window.getTask().mTaskRecord = mock(TaskRecord.class, ExtendedMockito.RETURNS_DEEP_STUBS);
-        window.mAppToken.setOrientation(newOrientation);
+        final ActivityStack stack =
+                new ActivityTestsBase.StackBuilder(mWm.mAtmService.mRootActivityContainer)
+                        .setDisplay(dc.mAcitvityDisplay).build();
+        final ActivityRecord activity = stack.topTask().getTopActivity();
 
-        ActivityRecord activityRecord = mock(ActivityRecord.class);
+        activity.setRequestedOrientation(newOrientation);
 
-        assertFalse("Display shouldn't rotate to handle orientation request if fixed to"
-                        + " user rotation.",
-                dc.onDescendantOrientationChanged(window.mToken.token, activityRecord));
         verify(dc.mAcitvityDisplay, never()).updateDisplayOverrideConfigurationLocked(any(),
-                eq(activityRecord), anyBoolean(), same(null));
+                eq(activity), anyBoolean(), same(null));
+        assertEquals(dc.getDisplayRotation().getUserRotation(), dc.getRotation());
     }
 
     @Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java
index bfede51..f6f8811 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java
@@ -95,7 +95,7 @@
     public void setUp() throws Exception {
         deleteRecursively(TEST_FOLDER);
 
-        mWm.setSupportsFreeformWindowManagement(false);
+        mWm.mAtmService.mSupportsFreeformWindowManagement = false;
         mWm.setIsPc(false);
         mWm.setForceDesktopModeOnExternalDisplays(false);
 
@@ -134,7 +134,7 @@
 
     @Test
     public void testPrimaryDisplayDefaultToFullscreen_HasFreeformSupport_NonPc_NoDesktopMode() {
-        mWm.setSupportsFreeformWindowManagement(true);
+        mWm.mAtmService.mSupportsFreeformWindowManagement = true;
 
         mTarget.applySettingsToDisplayLocked(mPrimaryDisplay);
 
@@ -144,7 +144,7 @@
 
     @Test
     public void testPrimaryDisplayDefaultToFullscreen_HasFreeformSupport_NonPc_HasDesktopMode() {
-        mWm.setSupportsFreeformWindowManagement(true);
+        mWm.mAtmService.mSupportsFreeformWindowManagement = true;
         mWm.setForceDesktopModeOnExternalDisplays(true);
 
         mTarget.applySettingsToDisplayLocked(mPrimaryDisplay);
@@ -155,7 +155,7 @@
 
     @Test
     public void testPrimaryDisplayDefaultToFreeform_HasFreeformSupport_IsPc() {
-        mWm.setSupportsFreeformWindowManagement(true);
+        mWm.mAtmService.mSupportsFreeformWindowManagement = true;
         mWm.setIsPc(true);
 
         mTarget.applySettingsToDisplayLocked(mPrimaryDisplay);
@@ -168,7 +168,7 @@
     public void testPrimaryDisplayUpdateToFreeform_HasFreeformSupport_IsPc() {
         mTarget.applySettingsToDisplayLocked(mPrimaryDisplay);
 
-        mWm.setSupportsFreeformWindowManagement(true);
+        mWm.mAtmService.mSupportsFreeformWindowManagement = true;
         mWm.setIsPc(true);
 
         mTarget.updateSettingsForDisplay(mPrimaryDisplay);
@@ -187,7 +187,7 @@
 
     @Test
     public void testSecondaryDisplayDefaultToFreeform_HasFreeformSupport_NonPc_NoDesktopMode() {
-        mWm.setSupportsFreeformWindowManagement(true);
+        mWm.mAtmService.mSupportsFreeformWindowManagement = true;
 
         mTarget.applySettingsToDisplayLocked(mSecondaryDisplay);
 
@@ -197,7 +197,7 @@
 
     @Test
     public void testSecondaryDisplayDefaultToFreeform_HasFreeformSupport_NonPc_HasDesktopMode() {
-        mWm.setSupportsFreeformWindowManagement(true);
+        mWm.mAtmService.mSupportsFreeformWindowManagement = true;
         mWm.setForceDesktopModeOnExternalDisplays(true);
 
         mTarget.applySettingsToDisplayLocked(mSecondaryDisplay);
@@ -208,7 +208,7 @@
 
     @Test
     public void testSecondaryDisplayDefaultToFreeform_HasFreeformSupport_IsPc() {
-        mWm.setSupportsFreeformWindowManagement(true);
+        mWm.mAtmService.mSupportsFreeformWindowManagement = true;
         mWm.setIsPc(true);
 
         mTarget.applySettingsToDisplayLocked(mSecondaryDisplay);
diff --git a/services/tests/wmtests/src/com/android/server/wm/LaunchParamsControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/LaunchParamsControllerTests.java
index b28ae40..be2ee29 100644
--- a/services/tests/wmtests/src/com/android/server/wm/LaunchParamsControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/LaunchParamsControllerTests.java
@@ -331,7 +331,9 @@
 
         mController.layoutTask(task, null /* windowLayout */);
 
-        assertEquals(expected, task.getBounds());
+        // TaskRecord will make adjustments to requested bounds. We only need to guarantee that the
+        // reuqested bounds are expected.
+        assertEquals(expected, task.getRequestedOverrideBounds());
     }
 
     /**
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 e4d3770..49d778f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java
@@ -104,6 +104,7 @@
 
         mDisplayUniqueId = "test:" + Integer.toString(sNextUniqueId++);
         final DisplayInfo info = new DisplayInfo();
+        mService.mContext.getDisplay().getDisplayInfo(info);
         info.uniqueId = mDisplayUniqueId;
         mTestDisplay = createNewActivityDisplay(info);
         mRootActivityContainer.addChild(mTestDisplay, ActivityDisplay.POSITION_TOP);
diff --git a/services/tests/wmtests/src/com/android/server/wm/PinnedStackControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/PinnedStackControllerTest.java
index 63d9fb9..efd468f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/PinnedStackControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/PinnedStackControllerTest.java
@@ -61,7 +61,7 @@
 
     @Test
     public void setShelfHeight_shelfVisibilityChangedTriggered() throws RemoteException {
-        mWm.mSupportsPictureInPicture = true;
+        mWm.mAtmService.mSupportsPictureInPicture = true;
         mWm.registerPinnedStackListener(DEFAULT_DISPLAY, mIPinnedStackListener);
 
         verify(mIPinnedStackListener).onImeVisibilityChanged(false, 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 b7a85d7..fb4e330 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
@@ -32,7 +32,7 @@
 
 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.spy;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
 
 import static com.google.common.truth.Truth.assertThat;
 import static com.google.common.truth.Truth.assertWithMessage;
@@ -53,14 +53,12 @@
 import android.app.ActivityTaskManager;
 import android.app.WindowConfiguration;
 import android.content.ComponentName;
-import android.content.Context;
 import android.content.pm.PackageManager;
 import android.content.pm.ParceledListSlice;
 import android.content.pm.UserInfo;
 import android.content.res.Configuration;
 import android.graphics.Rect;
 import android.os.Bundle;
-import android.os.Looper;
 import android.os.RemoteException;
 import android.os.SystemClock;
 import android.platform.test.annotations.Presubmit;
@@ -93,11 +91,8 @@
     private static final int TEST_QUIET_USER_ID = 20;
     private static final UserInfo DEFAULT_USER_INFO = new UserInfo();
     private static final UserInfo QUIET_USER_INFO = new UserInfo();
-    private static int sLastTaskId = 1;
-    private static int sLastStackId = 1;
     private static final int INVALID_STACK_ID = 999;
 
-    private TestActivityTaskManagerService mTestService;
     private ActivityDisplay mDisplay;
     private ActivityDisplay mOtherDisplay;
     private ActivityDisplay mSingleTaskDisplay;
@@ -115,13 +110,29 @@
     @Before
     public void setUp() throws Exception {
         mTaskPersister = new TestTaskPersister(mContext.getFilesDir());
-        mTestService = new MyTestActivityTaskManagerService(mContext);
-        mRecentTasks = (TestRecentTasks) mTestService.getRecentTasks();
+
+        // Set testing displays
+        mDisplay = mRootActivityContainer.getActivityDisplay(DEFAULT_DISPLAY);
+        mOtherDisplay = createNewActivityDisplay();
+        mSingleTaskDisplay = createNewActivityDisplay();
+        mSingleTaskDisplay.setDisplayToSingleTaskInstance();
+        mRootActivityContainer.addChild(mOtherDisplay, ActivityDisplay.POSITION_TOP);
+        mRootActivityContainer.addChild(mDisplay, ActivityDisplay.POSITION_TOP);
+        mRootActivityContainer.addChild(mSingleTaskDisplay, ActivityDisplay.POSITION_TOP);
+
+        // Set the recent tasks we should use for testing in this class.
+        mRecentTasks = new TestRecentTasks(mService, mTaskPersister);
+        spyOn(mRecentTasks);
+        mService.setRecentTasks(mRecentTasks);
         mRecentTasks.loadParametersFromResources(mContext.getResources());
-        mRunningTasks = (TestRunningTasks) mTestService.mStackSupervisor.mRunningTasks;
-        mHomeStack = mTestService.mRootActivityContainer.getDefaultDisplay().getOrCreateStack(
+
+        // Set the running tasks we should use for testing in this class.
+        mRunningTasks = new TestRunningTasks();
+        mService.mStackSupervisor.setRunningTasks(mRunningTasks);
+
+        mHomeStack = mDisplay.getOrCreateStack(
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */);
-        mStack = mTestService.mRootActivityContainer.getDefaultDisplay().createStack(
+        mStack = mDisplay.createStack(
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
         mCallbacksRecorder = new CallbacksRecorder();
         mRecentTasks.registerCallback(mCallbacksRecorder);
@@ -723,7 +734,7 @@
 
         ActivityStack stack = mTasks.get(2).getStack();
         stack.moveToFront("", mTasks.get(2));
-        doReturn(stack).when(mTestService.mRootActivityContainer).getTopDisplayFocusedStack();
+        doReturn(stack).when(mService.mRootActivityContainer).getTopDisplayFocusedStack();
 
         // Simulate the reset from the timeout
         mRecentTasks.resetFreezeTaskListReorderingOnTimeout();
@@ -742,10 +753,9 @@
     public void testBackStackTasks_expectNoTrim() {
         mRecentTasks.setParameters(-1 /* min */, 1 /* max */, -1 /* ms */);
 
-        final MyTestActivityStackSupervisor supervisor =
-                (MyTestActivityStackSupervisor) mTestService.mStackSupervisor;
         final ActivityStack homeStack = mDisplay.getHomeStack();
-        final ActivityStack aboveHomeStack = new MyTestActivityStack(mDisplay, supervisor);
+        final ActivityStack aboveHomeStack = mDisplay.createStack(
+                WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
 
         // Add a number of tasks (beyond the max) but ensure that nothing is trimmed because all
         // the tasks belong in stacks above the home stack
@@ -761,11 +771,11 @@
     public void testBehindHomeStackTasks_expectTaskTrimmed() {
         mRecentTasks.setParameters(-1 /* min */, 1 /* max */, -1 /* ms */);
 
-        final MyTestActivityStackSupervisor supervisor =
-                (MyTestActivityStackSupervisor) mTestService.mStackSupervisor;
-        final ActivityStack behindHomeStack = new MyTestActivityStack(mDisplay, supervisor);
+        final ActivityStack behindHomeStack = mDisplay.createStack(
+                WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
         final ActivityStack homeStack = mDisplay.getHomeStack();
-        final ActivityStack aboveHomeStack = new MyTestActivityStack(mDisplay, supervisor);
+        final ActivityStack aboveHomeStack = mDisplay.createStack(
+                WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
 
         // Add a number of tasks (beyond the max) but ensure that only the task in the stack behind
         // the home stack is trimmed once a new task is added
@@ -783,10 +793,9 @@
     public void testOtherDisplayTasks_expectNoTrim() {
         mRecentTasks.setParameters(-1 /* min */, 1 /* max */, -1 /* ms */);
 
-        final MyTestActivityStackSupervisor supervisor =
-                (MyTestActivityStackSupervisor) mTestService.mStackSupervisor;
         final ActivityStack homeStack = mDisplay.getHomeStack();
-        final ActivityStack otherDisplayStack = new MyTestActivityStack(mOtherDisplay, supervisor);
+        final ActivityStack otherDisplayStack = mOtherDisplay.createStack(
+                WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
 
         // Add a number of tasks (beyond the max) on each display, ensure that the tasks are not
         // removed
@@ -887,16 +896,16 @@
         mStack.remove();
 
         // The following APIs should not restore task from recents to the active list.
-        assertNotRestoreTask(() -> mTestService.setFocusedTask(taskId));
-        assertNotRestoreTask(() -> mTestService.startSystemLockTaskMode(taskId));
-        assertNotRestoreTask(() -> mTestService.cancelTaskWindowTransition(taskId));
+        assertNotRestoreTask(() -> mService.setFocusedTask(taskId));
+        assertNotRestoreTask(() -> mService.startSystemLockTaskMode(taskId));
+        assertNotRestoreTask(() -> mService.cancelTaskWindowTransition(taskId));
         assertNotRestoreTask(
-                () -> mTestService.resizeTask(taskId, null /* bounds */, 0 /* resizeMode */));
+                () -> mService.resizeTask(taskId, null /* bounds */, 0 /* resizeMode */));
         assertNotRestoreTask(
-                () -> mTestService.setTaskWindowingMode(taskId, WINDOWING_MODE_FULLSCREEN,
+                () -> mService.setTaskWindowingMode(taskId, WINDOWING_MODE_FULLSCREEN,
                         false/* toTop */));
         assertNotRestoreTask(
-                () -> mTestService.setTaskWindowingModeSplitScreenPrimary(taskId,
+                () -> mService.setTaskWindowingModeSplitScreenPrimary(taskId,
                         SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT,
                         false /* toTop */, false /* animate */, null /* initialBounds */,
                         true /* showRecents */));
@@ -910,7 +919,7 @@
         mRecentTasks.remove(task);
 
         TaskChangeNotificationController controller =
-                mTestService.getTaskChangeNotificationController();
+                mService.getTaskChangeNotificationController();
         verify(controller, times(2)).notifyTaskListUpdated();
     }
 
@@ -923,7 +932,7 @@
 
         // 2 calls - Once for add and once for remove
         TaskChangeNotificationController controller =
-                mTestService.getTaskChangeNotificationController();
+                mService.getTaskChangeNotificationController();
         verify(controller, times(2)).notifyTaskListUpdated();
     }
 
@@ -938,7 +947,7 @@
 
         // 4 calls - Twice for add and twice for remove
         TaskChangeNotificationController controller =
-                mTestService.getTaskChangeNotificationController();
+                mService.getTaskChangeNotificationController();
         verify(controller, times(4)).notifyTaskListUpdated();
     }
 
@@ -980,7 +989,7 @@
 
     @Test
     public void testNotRecentsComponent_denyApiAccess() throws Exception {
-        doReturn(PackageManager.PERMISSION_DENIED).when(mTestService)
+        doReturn(PackageManager.PERMISSION_DENIED).when(mService)
                 .checkGetTasksPermission(anyString(), anyInt(), anyInt());
         // Expect the following methods to fail due to recents component not being set
         mRecentTasks.setIsCallerRecentsOverride(TestRecentTasks.DENY_THROW_SECURITY_EXCEPTION);
@@ -992,7 +1001,7 @@
 
     @Test
     public void testRecentsComponent_allowApiAccessWithoutPermissions() {
-        doReturn(PackageManager.PERMISSION_DENIED).when(mTestService)
+        doReturn(PackageManager.PERMISSION_DENIED).when(mService)
                 .checkGetTasksPermission(anyString(), anyInt(), anyInt());
 
         // Set the recents component and ensure that the following calls do not fail
@@ -1002,62 +1011,62 @@
     }
 
     private void doTestRecentTasksApis(boolean expectCallable) {
-        assertSecurityException(expectCallable, () -> mTestService.removeStack(INVALID_STACK_ID));
+        assertSecurityException(expectCallable, () -> mService.removeStack(INVALID_STACK_ID));
         assertSecurityException(expectCallable,
-                () -> mTestService.removeStacksInWindowingModes(
+                () -> mService.removeStacksInWindowingModes(
                         new int[]{WINDOWING_MODE_UNDEFINED}));
         assertSecurityException(expectCallable,
-                () -> mTestService.removeStacksWithActivityTypes(
+                () -> mService.removeStacksWithActivityTypes(
                         new int[]{ACTIVITY_TYPE_UNDEFINED}));
-        assertSecurityException(expectCallable, () -> mTestService.removeTask(0));
+        assertSecurityException(expectCallable, () -> mService.removeTask(0));
         assertSecurityException(expectCallable,
-                () -> mTestService.setTaskWindowingMode(0, WINDOWING_MODE_UNDEFINED, true));
+                () -> mService.setTaskWindowingMode(0, WINDOWING_MODE_UNDEFINED, true));
         assertSecurityException(expectCallable,
-                () -> mTestService.moveTaskToStack(0, INVALID_STACK_ID, true));
+                () -> mService.moveTaskToStack(0, INVALID_STACK_ID, true));
         assertSecurityException(expectCallable,
-                () -> mTestService.setTaskWindowingModeSplitScreenPrimary(0,
+                () -> mService.setTaskWindowingModeSplitScreenPrimary(0,
                         SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT, true, true, new Rect(), true));
-        assertSecurityException(expectCallable, () -> mTestService.dismissSplitScreenMode(true));
-        assertSecurityException(expectCallable, () -> mTestService.dismissPip(true, 0));
+        assertSecurityException(expectCallable, () -> mService.dismissSplitScreenMode(true));
+        assertSecurityException(expectCallable, () -> mService.dismissPip(true, 0));
         assertSecurityException(expectCallable,
-                () -> mTestService.moveTopActivityToPinnedStack(INVALID_STACK_ID, new Rect()));
+                () -> mService.moveTopActivityToPinnedStack(INVALID_STACK_ID, new Rect()));
         assertSecurityException(expectCallable,
-                () -> mTestService.resizeStack(INVALID_STACK_ID, new Rect(), true, true, true, 0));
+                () -> mService.resizeStack(INVALID_STACK_ID, new Rect(), true, true, true, 0));
         assertSecurityException(expectCallable,
-                () -> mTestService.resizeDockedStack(new Rect(), new Rect(), new Rect(), new Rect(),
+                () -> mService.resizeDockedStack(new Rect(), new Rect(), new Rect(), new Rect(),
                         new Rect()));
         assertSecurityException(expectCallable,
-                () -> mTestService.resizePinnedStack(new Rect(), new Rect()));
-        assertSecurityException(expectCallable, () -> mTestService.getAllStackInfos());
+                () -> mService.resizePinnedStack(new Rect(), new Rect()));
+        assertSecurityException(expectCallable, () -> mService.getAllStackInfos());
         assertSecurityException(expectCallable,
-                () -> mTestService.getStackInfo(WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_UNDEFINED));
+                () -> mService.getStackInfo(WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_UNDEFINED));
         assertSecurityException(expectCallable, () -> {
             try {
-                mTestService.getFocusedStackInfo();
+                mService.getFocusedStackInfo();
             } catch (RemoteException e) {
                 // Ignore
             }
         });
         assertSecurityException(expectCallable,
-                () -> mTestService.moveTasksToFullscreenStack(INVALID_STACK_ID, true));
+                () -> mService.moveTasksToFullscreenStack(INVALID_STACK_ID, true));
         assertSecurityException(expectCallable,
-                () -> mTestService.startActivityFromRecents(0, new Bundle()));
-        assertSecurityException(expectCallable, () -> mTestService.getTaskSnapshot(0, true));
-        assertSecurityException(expectCallable, () -> mTestService.registerTaskStackListener(null));
+                () -> mService.startActivityFromRecents(0, new Bundle()));
+        assertSecurityException(expectCallable, () -> mService.getTaskSnapshot(0, true));
+        assertSecurityException(expectCallable, () -> mService.registerTaskStackListener(null));
         assertSecurityException(expectCallable,
-                () -> mTestService.unregisterTaskStackListener(null));
-        assertSecurityException(expectCallable, () -> mTestService.getTaskDescription(0));
-        assertSecurityException(expectCallable, () -> mTestService.cancelTaskWindowTransition(0));
-        assertSecurityException(expectCallable, () -> mTestService.startRecentsActivity(null, null,
+                () -> mService.unregisterTaskStackListener(null));
+        assertSecurityException(expectCallable, () -> mService.getTaskDescription(0));
+        assertSecurityException(expectCallable, () -> mService.cancelTaskWindowTransition(0));
+        assertSecurityException(expectCallable, () -> mService.startRecentsActivity(null, null,
                 null));
-        assertSecurityException(expectCallable, () -> mTestService.cancelRecentsAnimation(true));
-        assertSecurityException(expectCallable, () -> mTestService.stopAppSwitches());
-        assertSecurityException(expectCallable, () -> mTestService.resumeAppSwitches());
+        assertSecurityException(expectCallable, () -> mService.cancelRecentsAnimation(true));
+        assertSecurityException(expectCallable, () -> mService.stopAppSwitches());
+        assertSecurityException(expectCallable, () -> mService.resumeAppSwitches());
     }
 
     private void testGetTasksApis(boolean expectCallable) {
-        mTestService.getRecentTasks(MAX_VALUE, 0, TEST_USER_0_ID);
-        mTestService.getTasks(MAX_VALUE);
+        mService.getRecentTasks(MAX_VALUE, 0, TEST_USER_0_ID);
+        mService.getTasks(MAX_VALUE);
         if (expectCallable) {
             assertTrue(mRecentTasks.mLastAllowed);
             assertTrue(mRunningTasks.mLastAllowed);
@@ -1072,10 +1081,9 @@
     }
 
     private TaskBuilder createTaskBuilder(String packageName, String className) {
-        return new TaskBuilder(mTestService.mStackSupervisor)
+        return new TaskBuilder(mService.mStackSupervisor)
                 .setComponent(new ComponentName(packageName, className))
                 .setStack(mStack)
-                .setTaskId(sLastTaskId++)
                 .setUserId(TEST_USER_0_ID);
     }
 
@@ -1140,68 +1148,6 @@
         }
     }
 
-    private class MyTestActivityTaskManagerService extends TestActivityTaskManagerService {
-        MyTestActivityTaskManagerService(Context context) {
-            super(context);
-        }
-
-        @Override
-        protected RecentTasks createRecentTasks() {
-            return spy(new TestRecentTasks(this, mTaskPersister));
-        }
-
-        @Override
-        protected ActivityStackSupervisor createStackSupervisor() {
-            if (mTestStackSupervisor == null) {
-                mTestStackSupervisor = new MyTestActivityStackSupervisor(this, mH.getLooper());
-            }
-            return mTestStackSupervisor;
-        }
-
-        @Override
-        void createDefaultDisplay() {
-            super.createDefaultDisplay();
-            mDisplay = mRootActivityContainer.getActivityDisplay(DEFAULT_DISPLAY);
-            mOtherDisplay = TestActivityDisplay.create(mTestStackSupervisor, DEFAULT_DISPLAY + 1);
-            mSingleTaskDisplay = TestActivityDisplay.create(mTestStackSupervisor,
-                    DEFAULT_DISPLAY + 2);
-            mSingleTaskDisplay.setDisplayToSingleTaskInstance();
-            mRootActivityContainer.addChild(mOtherDisplay, ActivityDisplay.POSITION_TOP);
-            mRootActivityContainer.addChild(mDisplay, ActivityDisplay.POSITION_TOP);
-            mRootActivityContainer.addChild(mSingleTaskDisplay, ActivityDisplay.POSITION_TOP);
-        }
-    }
-
-    private class MyTestActivityStackSupervisor extends TestActivityStackSupervisor {
-        MyTestActivityStackSupervisor(ActivityTaskManagerService service, Looper looper) {
-            super(service, looper);
-        }
-
-        @Override
-        RunningTasks createRunningTasks() {
-            mRunningTasks = new TestRunningTasks();
-            return mRunningTasks;
-        }
-    }
-
-    private static class MyTestActivityStack extends TestActivityStack {
-        private ActivityDisplay mDisplay = null;
-
-        MyTestActivityStack(ActivityDisplay display, ActivityStackSupervisor supervisor) {
-            super(display, sLastStackId++, supervisor, WINDOWING_MODE_FULLSCREEN,
-                    ACTIVITY_TYPE_STANDARD, true /* onTop */, false /* createActivity */);
-            mDisplay = display;
-        }
-
-        @Override
-        ActivityDisplay getDisplay() {
-            if (mDisplay != null) {
-                return mDisplay;
-            }
-            return super.getDisplay();
-        }
-    }
-
     private static class CallbacksRecorder implements Callbacks {
         public final ArrayList<TaskRecord> mAdded = new ArrayList<>();
         public final ArrayList<TaskRecord> mTrimmed = new ArrayList<>();
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 f5a1d75..ce5a211 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
@@ -30,6 +30,7 @@
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.verifyNoMoreInteractions;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
+import static com.android.server.wm.ActivityStackSupervisor.ON_TOP;
 import static com.android.server.wm.RecentsAnimationController.REORDER_KEEP_IN_PLACE;
 import static com.android.server.wm.RecentsAnimationController.REORDER_MOVE_TO_ORIGINAL_POSITION;
 
@@ -132,8 +133,14 @@
     @Test
     public void testIncludedApps_expectTargetAndVisible() {
         mWm.setRecentsAnimationController(mController);
-        final AppWindowToken homeAppWindow = createAppWindowToken(mDisplayContent,
-                WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME);
+        final ActivityStack homStack = mDisplayContent.mAcitvityDisplay.getOrCreateStack(
+                WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, ON_TOP);
+        final AppWindowToken homeAppWindow =
+                new ActivityTestsBase.ActivityBuilder(mWm.mAtmService)
+                        .setStack(homStack)
+                        .setCreateTask(true)
+                        .build()
+                        .mAppWindowToken;
         final AppWindowToken appWindow = createAppWindowToken(mDisplayContent,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
         final AppWindowToken hiddenAppWindow = createAppWindowToken(mDisplayContent,
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 0e119e3..e2074f5 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java
@@ -74,8 +74,9 @@
     @Before
     public void setUp() throws Exception {
         mRecentsAnimationController = mock(RecentsAnimationController.class);
-        doReturn(mRecentsAnimationController).when(
-                mService.mWindowManager).getRecentsAnimationController();
+        mService.mWindowManager.setRecentsAnimationController(mRecentsAnimationController);
+        doNothing().when(mService.mWindowManager).initializeRecentsAnimation(
+                anyInt(), any(), any(), anyInt(), any());
         doReturn(true).when(mService.mWindowManager).canStartRecentsAnimation();
 
         final RecentTasks recentTasks = mService.getRecentTasks();
@@ -115,8 +116,18 @@
 
     @Test
     public void testPreloadRecentsActivity() {
-        // Ensure that the fake recent component can be resolved by the recents intent.
-        mockTaskRecordFactory(builder -> builder.setComponent(mRecentsComponent));
+        final ActivityDisplay defaultDisplay = mRootActivityContainer.getDefaultDisplay();
+        final ActivityStack homeStack =
+                defaultDisplay.getStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME);
+        defaultDisplay.positionChildAtTop(homeStack, false /* includingParents */);
+        ActivityRecord topRunningHomeActivity = homeStack.topRunningActivityLocked();
+        if (topRunningHomeActivity == null) {
+            topRunningHomeActivity = new ActivityBuilder(mService)
+                    .setStack(homeStack)
+                    .setCreateTask(true)
+                    .build();
+        }
+
         ActivityInfo aInfo = new ActivityInfo();
         aInfo.applicationInfo = new ApplicationInfo();
         aInfo.applicationInfo.uid = 10001;
@@ -204,6 +215,13 @@
         ActivityStack homeStack = display.getHomeStack();
         // Assume the home activity support recents.
         ActivityRecord targetActivity = homeStack.getTopActivity();
+        if (targetActivity == null) {
+            targetActivity = new ActivityBuilder(mService)
+                    .setCreateTask(true)
+                    .setStack(homeStack)
+                    .build();
+        }
+
         // Put another home activity in home stack.
         ActivityRecord anotherHomeActivity = new ActivityBuilder(mService)
                 .setComponent(new ComponentName(mContext.getPackageName(), "Home2"))
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 d4f24f9..539a79c 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
@@ -97,7 +97,7 @@
      */
     @Test
     public void testRestoringInvalidTask() {
-        ((TestActivityDisplay) mRootActivityContainer.getDefaultDisplay()).removeAllTasks();
+        mRootActivityContainer.getDefaultDisplay().removeAllTasks();
         TaskRecord task = mRootActivityContainer.anyTaskForId(0 /*taskId*/,
                 MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE, null, false /* onTop */);
         assertNull(task);
@@ -304,21 +304,23 @@
      */
     @Test
     public void testResizeDockedStackForSplitScreenPrimary() {
-        final Rect taskSize = new Rect(0, 0, 600, 600);
+        final Rect taskSize = new Rect(0, 0, 1000, 1000);
         final Rect stackSize = new Rect(0, 0, 300, 300);
 
         // Create primary split-screen stack with a task.
-        final ActivityStack primaryStack = mRootActivityContainer.getDefaultDisplay()
-                .createStack(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD,
-                        true /* onTop */);
-        final TaskRecord task = new TaskBuilder(mSupervisor).setStack(primaryStack).build();
+        final ActivityStack primaryStack = new StackBuilder(mRootActivityContainer)
+                .setActivityType(ACTIVITY_TYPE_STANDARD)
+                .setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY)
+                .setOnTop(true)
+                .build();
+        final TaskRecord task = primaryStack.topTask();
 
         // Resize dock stack.
         mService.resizeDockedStack(stackSize, taskSize, null, null, null);
 
         // Verify dock stack & its task bounds if is equal as resized result.
-        assertEquals(primaryStack.getBounds(), stackSize);
-        assertEquals(task.getBounds(), taskSize);
+        assertEquals(stackSize, primaryStack.getBounds());
+        assertEquals(taskSize, task.getBounds());
     }
 
     /**
@@ -328,8 +330,9 @@
     public void testFindTaskToMoveToFrontWhenRecentsOnTop() {
         // Create stack/task on default display.
         final ActivityDisplay display = mRootActivityContainer.getDefaultDisplay();
-        final TestActivityStack targetStack = (TestActivityStack) new StackBuilder(
-                mRootActivityContainer).setOnTop(false).build();
+        final ActivityStack targetStack = new StackBuilder(mRootActivityContainer)
+                .setOnTop(false)
+                .build();
         final TaskRecord targetTask = targetStack.getChildAt(0);
 
         // Create Recents on top of the display.
@@ -505,12 +508,10 @@
         mockResolveSecondaryHomeActivity();
 
         // Create secondary displays.
-        final TestActivityDisplay secondDisplay = spy(createNewActivityDisplay());
+        final TestActivityDisplay secondDisplay = createNewActivityDisplay();
         mRootActivityContainer.addChild(secondDisplay, POSITION_TOP);
         doReturn(true).when(secondDisplay).supportsSystemDecorations();
 
-        // Create mock tasks and other necessary mocks.
-        mockTaskRecordFactory();
         doReturn(true).when(mRootActivityContainer)
                 .ensureVisibilityAndConfig(any(), anyInt(), anyBoolean(), anyBoolean());
         doReturn(true).when(mRootActivityContainer).canStartHomeOnDisplay(
@@ -621,7 +622,6 @@
         info.applicationInfo.packageName = "android";
         info.name = ResolverActivity.class.getName();
         doReturn(info).when(mRootActivityContainer).resolveHomeActivity(anyInt(), any());
-        mockTaskRecordFactory();
 
         mRootActivityContainer.startHomeOnDisplay(0 /* userId */, "test", DEFAULT_DISPLAY);
         final ActivityRecord resolverActivity = mRootActivityContainer.topRunningActivity();
diff --git a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
index f51ce13..db105dd 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
@@ -96,7 +96,7 @@
                     mWm.getDefaultDisplayContentLocked().getWindowingMode());
 
             mWm.mIsPc = true;
-            mWm.mSupportsFreeformWindowManagement = true;
+            mWm.mAtmService.mSupportsFreeformWindowManagement = true;
 
             mWm.mRoot.onSettingsRetrieved();
 
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 df7c9a4..c42098e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
@@ -16,6 +16,9 @@
 
 package com.android.server.wm;
 
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.os.Process.THREAD_PRIORITY_DEFAULT;
 import static android.testing.DexmakerShareClassLoaderRule.runWithDexmakerShareClassLoader;
 import static android.view.Display.DEFAULT_DISPLAY;
 
@@ -25,61 +28,89 @@
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyBoolean;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyInt;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyString;
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
 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.eq;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.nullable;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
 
 import android.app.ActivityManagerInternal;
 import android.app.AppOpsManager;
+import android.app.usage.UsageStatsManagerInternal;
 import android.content.BroadcastReceiver;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.IntentFilter;
+import android.content.pm.IPackageManager;
+import android.content.pm.PackageManagerInternal;
 import android.database.ContentObserver;
+import android.hardware.display.DisplayManager;
 import android.hardware.display.DisplayManagerInternal;
 import android.net.Uri;
 import android.os.Handler;
+import android.os.Looper;
+import android.os.PowerManager;
 import android.os.PowerManagerInternal;
 import android.os.PowerSaveState;
 import android.os.UserHandle;
-import android.view.Display;
+import android.provider.DeviceConfig;
 import android.view.InputChannel;
+import android.view.Surface;
+import android.view.SurfaceControl;
 
 import com.android.dx.mockito.inline.extended.StaticMockitoSession;
 import com.android.server.LocalServices;
 import com.android.server.LockGuard;
+import com.android.server.ServiceThread;
 import com.android.server.Watchdog;
+import com.android.server.am.ActivityManagerService;
+import com.android.server.appop.AppOpsService;
+import com.android.server.display.color.ColorDisplayService;
 import com.android.server.input.InputManagerService;
+import com.android.server.policy.PermissionPolicyInternal;
 import com.android.server.policy.WindowManagerPolicy;
+import com.android.server.statusbar.StatusBarManagerInternal;
+import com.android.server.uri.UriGrantsManagerInternal;
 import com.android.server.wm.utils.MockTracker;
 
 import org.junit.rules.TestRule;
 import org.junit.runner.Description;
 import org.junit.runners.model.Statement;
-import org.mockito.invocation.InvocationOnMock;
 import org.mockito.quality.Strictness;
 
+import java.io.File;
 import java.util.concurrent.atomic.AtomicBoolean;
 
 /**
- * JUnit test rule to create a mock {@link WindowManagerService} instance for tests.
+ * JUnit test rule to correctly setting up system services like {@link WindowManagerService}
+ * and {@link ActivityTaskManagerService} for tests.
  */
 public class SystemServicesTestRule implements TestRule {
 
     private static final String TAG = SystemServicesTestRule.class.getSimpleName();
 
+    static int sNextDisplayId = DEFAULT_DISPLAY + 100;
+    static int sNextTaskId = 100;
+
     private final AtomicBoolean mCurrentMessagesProcessed = new AtomicBoolean(false);
 
+    private Context mContext;
     private MockTracker mMockTracker;
     private StaticMockitoSession mMockitoSession;
-    private WindowManagerService mWindowManagerService;
-    private TestWindowManagerPolicy mWindowManagerPolicy;
+    ServiceThread mHandlerThread;
+    private ActivityManagerService mAmService;
+    private ActivityTaskManagerService mAtmService;
+    private WindowManagerService mWmService;
+    private TestWindowManagerPolicy mWMPolicy;
+    private InputManagerService mImService;
+    /**
+     * Spied {@link SurfaceControl.Transaction} class than can be used to verify calls.
+     */
+    SurfaceControl.Transaction mTransaction;
 
     /** {@link MockTracker} to track mocks created by {@link SystemServicesTestRule}. */
     private static class Tracker extends MockTracker {
@@ -103,92 +134,183 @@
     }
 
     private void setUp() {
-        mMockTracker = new Tracker();
+        try {
+            mMockTracker = new Tracker();
 
-        mMockitoSession = mockitoSession()
-                .spyStatic(LocalServices.class)
-                .mockStatic(LockGuard.class)
-                .mockStatic(Watchdog.class)
-                .strictness(Strictness.LENIENT)
-                .startMocking();
+            mMockitoSession = mockitoSession()
+                    .spyStatic(LocalServices.class)
+                    .mockStatic(LockGuard.class)
+                    .mockStatic(Watchdog.class)
+                    .strictness(Strictness.LENIENT)
+                    .startMocking();
+
+            setUpSystemCore();
+            setUpLocalServices();
+            setUpActivityTaskManagerService();
+            setUpWindowManagerService();
+        } finally {
+            mMockTracker.stopTracking();
+        }
+    }
+
+    private void setUpSystemCore() {
+        mHandlerThread = new ServiceThread(
+                "WmTestsThread", THREAD_PRIORITY_DEFAULT, true /* allowIo */);
+        mHandlerThread.start();
 
         doReturn(mock(Watchdog.class)).when(Watchdog::getInstance);
 
-        final Context context = getInstrumentation().getTargetContext();
-        spyOn(context);
+        mContext = getInstrumentation().getTargetContext();
+        spyOn(mContext);
 
-        doReturn(null).when(context)
+        doReturn(null).when(mContext)
                 .registerReceiver(nullable(BroadcastReceiver.class), any(IntentFilter.class));
-        doReturn(null).when(context)
+        doReturn(null).when(mContext)
                 .registerReceiverAsUser(any(BroadcastReceiver.class), any(UserHandle.class),
                         any(IntentFilter.class), nullable(String.class), nullable(Handler.class));
 
-        final ContentResolver contentResolver = context.getContentResolver();
+        final ContentResolver contentResolver = mContext.getContentResolver();
         spyOn(contentResolver);
         doNothing().when(contentResolver)
                 .registerContentObserver(any(Uri.class), anyBoolean(), any(ContentObserver.class),
                         anyInt());
+    }
 
-        final AppOpsManager appOpsManager = mock(AppOpsManager.class);
-        doReturn(appOpsManager).when(context)
-                .getSystemService(eq(Context.APP_OPS_SERVICE));
+    private void setUpLocalServices() {
+        // Tear down any local services just in case.
+        tearDownLocalServices();
 
+        // UriGrantsManagerInternal
+        final UriGrantsManagerInternal ugmi = mock(UriGrantsManagerInternal.class);
+        LocalServices.addService(UriGrantsManagerInternal.class, ugmi);
+
+        // AppOpsManager
+        final AppOpsManager aom = mock(AppOpsManager.class);
+        doReturn(aom).when(mContext).getSystemService(eq(Context.APP_OPS_SERVICE));
+
+        // DisplayManagerInternal
         final DisplayManagerInternal dmi = mock(DisplayManagerInternal.class);
         doReturn(dmi).when(() -> LocalServices.getService(eq(DisplayManagerInternal.class)));
 
+        // ColorDisplayServiceInternal
+        final ColorDisplayService.ColorDisplayServiceInternal cds =
+                mock(ColorDisplayService.ColorDisplayServiceInternal.class);
+        doReturn(cds).when(() -> LocalServices.getService(
+                eq(ColorDisplayService.ColorDisplayServiceInternal.class)));
+
+        final UsageStatsManagerInternal usmi = mock(UsageStatsManagerInternal.class);
+        LocalServices.addService(UsageStatsManagerInternal.class, usmi);
+
+        // PackageManagerInternal
+        final PackageManagerInternal packageManagerInternal = mock(PackageManagerInternal.class);
+        LocalServices.addService(PackageManagerInternal.class, packageManagerInternal);
+        doReturn(false).when(packageManagerInternal).isPermissionsReviewRequired(
+                anyString(), anyInt());
+        doReturn(null).when(packageManagerInternal).getDefaultHomeActivity(anyInt());
+
+        // PowerManagerInternal
         final PowerManagerInternal pmi = mock(PowerManagerInternal.class);
         final PowerSaveState state = new PowerSaveState.Builder().build();
         doReturn(state).when(pmi).getLowPowerState(anyInt());
         doReturn(pmi).when(() -> LocalServices.getService(eq(PowerManagerInternal.class)));
 
-        final ActivityManagerInternal ami = mock(ActivityManagerInternal.class);
-        doReturn(ami).when(() -> LocalServices.getService(eq(ActivityManagerInternal.class)));
+        // PermissionPolicyInternal
+        final PermissionPolicyInternal ppi = mock(PermissionPolicyInternal.class);
+        LocalServices.addService(PermissionPolicyInternal.class, ppi);
+        doReturn(true).when(ppi).checkStartActivity(any(), anyInt(), any());
 
-        final ActivityTaskManagerInternal atmi = mock(ActivityTaskManagerInternal.class);
-        doAnswer((InvocationOnMock invocationOnMock) -> {
-            final Runnable runnable = invocationOnMock.getArgument(0);
-            if (runnable != null) {
-                runnable.run();
-            }
-            return null;
-        }).when(atmi).notifyKeyguardFlagsChanged(nullable(Runnable.class), anyInt());
-        doReturn(atmi).when(() -> LocalServices.getService(eq(ActivityTaskManagerInternal.class)));
-
-        final InputManagerService ims = mock(InputManagerService.class);
+        // InputManagerService
+        mImService = mock(InputManagerService.class);
         // InputChannel is final and can't be mocked.
         final InputChannel[] input = InputChannel.openInputChannelPair(TAG_WM);
         if (input != null && input.length > 1) {
-            doReturn(input[1]).when(ims).monitorInput(anyString(), anyInt());
+            doReturn(input[1]).when(mImService).monitorInput(anyString(), anyInt());
         }
 
-        final ActivityTaskManagerService atms = mock(ActivityTaskManagerService.class);
-        final TaskChangeNotificationController taskChangeNotificationController = mock(
-                TaskChangeNotificationController.class);
-        doReturn(taskChangeNotificationController).when(atms).getTaskChangeNotificationController();
-        final WindowManagerGlobalLock wmLock = new WindowManagerGlobalLock();
-        doReturn(wmLock).when(atms).getGlobalLock();
+        // StatusBarManagerInternal
+        final StatusBarManagerInternal sbmi = mock(StatusBarManagerInternal.class);
+        doReturn(sbmi).when(() -> LocalServices.getService(eq(StatusBarManagerInternal.class)));
+    }
 
-        mWindowManagerPolicy = new TestWindowManagerPolicy(this::getWindowManagerService);
-        mWindowManagerService = WindowManagerService.main(
-                context, ims, false, false, mWindowManagerPolicy, atms, StubTransaction::new);
+    private void setUpActivityTaskManagerService() {
+        // ActivityManagerService
+        mAmService = new ActivityManagerService(
+                new AMTestInjector(mContext, mHandlerThread), mHandlerThread);
+        spyOn(mAmService);
+        doReturn(mock(IPackageManager.class)).when(mAmService).getPackageManager();
+        doNothing().when(mAmService).grantEphemeralAccessLocked(
+                anyInt(), any(), anyInt(), anyInt());
 
-        mWindowManagerService.onInitReady();
+        // ActivityManagerInternal
+        final ActivityManagerInternal amInternal = mAmService.mInternal;
+        spyOn(amInternal);
+        doNothing().when(amInternal).trimApplications();
+        doNothing().when(amInternal).updateCpuStats();
+        doNothing().when(amInternal).updateOomAdj();
+        doNothing().when(amInternal).updateBatteryStats(any(), anyInt(), anyInt(), anyBoolean());
+        doNothing().when(amInternal).updateActivityUsageStats(
+                any(), anyInt(), anyInt(), any(), any());
+        doNothing().when(amInternal).startProcess(
+                any(), any(), anyBoolean(), anyBoolean(), any(), any());
+        doNothing().when(amInternal).updateOomLevelsForDisplay(anyInt());
+        LocalServices.addService(ActivityManagerInternal.class, amInternal);
 
-        final Display display = mWindowManagerService.mDisplayManager.getDisplay(DEFAULT_DISPLAY);
-        // Display creation is driven by the ActivityManagerService via
-        // ActivityStackSupervisor. We emulate those steps here.
-        DisplayContent displayContent = mWindowManagerService.mRoot
-                .createDisplayContent(display, mock(ActivityDisplay.class));
-        displayContent.reconfigureDisplayLocked();
+        mAtmService = new TestActivityTaskManagerService(mContext, mAmService);
+        LocalServices.addService(ActivityTaskManagerInternal.class, mAtmService.getAtmInternal());
+    }
 
-        mMockTracker.stopTracking();
+    private void setUpWindowManagerService() {
+        mWMPolicy = new TestWindowManagerPolicy(this::getWindowManagerService);
+        mWmService = WindowManagerService.main(
+                mContext, mImService, false, false, mWMPolicy, mAtmService, StubTransaction::new);
+        spyOn(mWmService);
+
+        // Setup factory classes to prevent calls to native code.
+        mTransaction = spy(StubTransaction.class);
+        // Return a spied Transaction class than can be used to verify calls.
+        mWmService.mTransactionFactory = () -> mTransaction;
+        // Return a SurfaceControl.Builder class that creates mocked SurfaceControl instances.
+        mWmService.mSurfaceBuilderFactory = (unused) -> new MockSurfaceControlBuilder();
+        // Return mocked Surface instances.
+        mWmService.mSurfaceFactory = () -> mock(Surface.class);
+        mWmService.mSurfaceAnimationRunner = new SurfaceAnimationRunner(
+                null, null, mTransaction, mWmService.mPowerManagerInternal);
+
+        mWmService.onInitReady();
+        mAmService.setWindowManager(mWmService);
+        mWmService.mDisplayEnabled = true;
+        mWmService.mDisplayReady = true;
+        // Set configuration for default display
+        mWmService.getDefaultDisplayContentLocked().reconfigureDisplayLocked();
+
+        // Mock root, some default display, and home stack.
+        spyOn(mWmService.mRoot);
+        final ActivityDisplay display = mAtmService.mRootActivityContainer.getDefaultDisplay();
+        spyOn(display);
+        spyOn(display.mDisplayContent);
+        final ActivityStack homeStack = display.getStack(
+                WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME);
+        spyOn(homeStack);
+        spyOn(homeStack.mTaskStack);
     }
 
     private void tearDown() {
         waitUntilWindowManagerHandlersIdle();
-        removeLocalServices();
-        mWindowManagerService = null;
-        mWindowManagerPolicy = null;
+        // Unregister display listener from root to avoid issues with subsequent tests.
+        mContext.getSystemService(DisplayManager.class)
+                .unregisterDisplayListener(mAtmService.mRootActivityContainer);
+        // ProptertiesChangesListener is registered in the constructor of WindowManagerService to
+        // a static object, so we need to clean it up in tearDown(), even though we didn't set up
+        // in tests.
+        DeviceConfig.removeOnPropertiesChangedListener(mWmService.mPropertiesChangedListener);
+        mWmService = null;
+        mWMPolicy = null;
+
+        tearDownLocalServices();
+        tearDownSystemCore();
+    }
+
+    private void tearDownSystemCore() {
         if (mMockitoSession != null) {
             mMockitoSession.finishMocking();
             mMockitoSession = null;
@@ -198,15 +320,36 @@
             mMockTracker.close();
             mMockTracker = null;
         }
+
+        if (mHandlerThread != null) {
+            // Make sure there are no running messages and then quit the thread so the next test
+            // won't be affected.
+            mHandlerThread.getThreadHandler().runWithScissors(mHandlerThread::quit,
+                    0 /* timeout */);
+        }
     }
 
-    private static void removeLocalServices() {
+    private static void tearDownLocalServices() {
+        LocalServices.removeServiceForTest(DisplayManagerInternal.class);
+        LocalServices.removeServiceForTest(PowerManagerInternal.class);
+        LocalServices.removeServiceForTest(ActivityManagerInternal.class);
+        LocalServices.removeServiceForTest(ActivityTaskManagerInternal.class);
         LocalServices.removeServiceForTest(WindowManagerInternal.class);
         LocalServices.removeServiceForTest(WindowManagerPolicy.class);
+        LocalServices.removeServiceForTest(PackageManagerInternal.class);
+        LocalServices.removeServiceForTest(UriGrantsManagerInternal.class);
+        LocalServices.removeServiceForTest(PermissionPolicyInternal.class);
+        LocalServices.removeServiceForTest(ColorDisplayService.ColorDisplayServiceInternal.class);
+        LocalServices.removeServiceForTest(UsageStatsManagerInternal.class);
+        LocalServices.removeServiceForTest(StatusBarManagerInternal.class);
     }
 
     WindowManagerService getWindowManagerService() {
-        return mWindowManagerService;
+        return mWmService;
+    }
+
+    ActivityTaskManagerService getActivityTaskManagerService() {
+        return mAtmService;
     }
 
     void cleanupWindowManagerHandlers() {
@@ -229,6 +372,7 @@
         waitHandlerIdle(wm.mH);
         waitHandlerIdle(wm.mAnimationHandler);
         waitHandlerIdle(SurfaceAnimationThread.getHandler());
+        waitHandlerIdle(mHandlerThread.getThreadHandler());
     }
 
     private void waitHandlerIdle(Handler handler) {
@@ -251,4 +395,121 @@
             }
         }
     }
+
+    protected class TestActivityTaskManagerService extends ActivityTaskManagerService {
+        // ActivityStackSupervisor may be created more than once while setting up AMS and ATMS.
+        // We keep the reference in order to prevent creating it twice.
+        ActivityStackSupervisor mTestStackSupervisor;
+
+        TestActivityTaskManagerService(Context context, ActivityManagerService ams) {
+            super(context);
+            spyOn(this);
+
+            mSupportsMultiWindow = true;
+            mSupportsMultiDisplay = true;
+            mSupportsSplitScreenMultiWindow = true;
+            mSupportsFreeformWindowManagement = true;
+            mSupportsPictureInPicture = true;
+
+            doReturn(mock(IPackageManager.class)).when(this).getPackageManager();
+            // allow background activity starts by default
+            doReturn(true).when(this).isBackgroundActivityStartsEnabled();
+            doNothing().when(this).updateCpuStats();
+
+            // AppOpsService
+            final AppOpsService aos = mock(AppOpsService.class);
+            doReturn(aos).when(this).getAppOpsService();
+            // Make sure permission checks aren't overridden.
+            doReturn(AppOpsManager.MODE_DEFAULT)
+                    .when(aos).noteOperation(anyInt(), anyInt(), anyString());
+
+            setUsageStatsManager(LocalServices.getService(UsageStatsManagerInternal.class));
+            ams.mActivityTaskManager = this;
+            ams.mAtmInternal = mInternal;
+            onActivityManagerInternalAdded();
+            initialize(
+                    ams.mIntentFirewall, ams.mPendingIntentController, mHandlerThread.getLooper());
+            spyOn(getLifecycleManager());
+            spyOn(getLockTaskController());
+            spyOn(getTaskChangeNotificationController());
+            initRootActivityContainerMocks();
+        }
+
+        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;
+        }
+
+        @Override
+        protected ActivityStackSupervisor createStackSupervisor() {
+            if (mTestStackSupervisor == null) {
+                mTestStackSupervisor = new TestActivityStackSupervisor(this, mH.getLooper());
+            }
+            return mTestStackSupervisor;
+        }
+    }
+
+    /**
+     * An {@link ActivityStackSupervisor} which stubs out certain methods that depend on
+     * setup not available in the test environment. Also specifies an injector for
+     */
+    protected class TestActivityStackSupervisor extends ActivityStackSupervisor {
+
+        TestActivityStackSupervisor(ActivityTaskManagerService service, Looper looper) {
+            super(service, looper);
+            spyOn(this);
+
+            // Do not schedule idle that may touch methods outside the scope of the test.
+            doNothing().when(this).scheduleIdleLocked();
+            doNothing().when(this).scheduleIdleTimeoutLocked(any());
+            // unit test version does not handle launch wake lock
+            doNothing().when(this).acquireLaunchWakelock();
+            doReturn(mock(KeyguardController.class)).when(this).getKeyguardController();
+
+            mLaunchingActivityWakeLock = mock(PowerManager.WakeLock.class);
+
+            initialize();
+        }
+    }
+
+    // TODO: Can we just mock this?
+    private static class AMTestInjector extends ActivityManagerService.Injector {
+        private ServiceThread mHandlerThread;
+
+        AMTestInjector(Context context, ServiceThread handlerThread) {
+            super(context);
+            mHandlerThread = handlerThread;
+        }
+
+        @Override
+        public Context getContext() {
+            return getInstrumentation().getTargetContext();
+        }
+
+        @Override
+        public AppOpsService getAppOpsService(File file, Handler handler) {
+            return null;
+        }
+
+        @Override
+        public Handler getUiHandler(ActivityManagerService service) {
+            return mHandlerThread.getThreadHandler();
+        }
+
+        @Override
+        public boolean isNetworkRestrictedForUid(int uid) {
+            return false;
+        }
+    }
 }
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 2cebebf..bcff704 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java
@@ -1277,17 +1277,18 @@
     }
 
     private ActivityRecord createSourceActivity(TestActivityDisplay display) {
-        final TestActivityStack stack = display.createStack(display.getWindowingMode(),
+        final ActivityStack stack = display.createStack(display.getWindowingMode(),
                 ACTIVITY_TYPE_STANDARD, true);
         return new ActivityBuilder(mService).setStack(stack).setCreateTask(true).build();
     }
 
     private void addFreeformTaskTo(TestActivityDisplay display, Rect bounds) {
-        final TestActivityStack stack = display.createStack(display.getWindowingMode(),
+        final ActivityStack stack = display.createStack(display.getWindowingMode(),
                 ACTIVITY_TYPE_STANDARD, true);
         stack.setWindowingMode(WINDOWING_MODE_FREEFORM);
         final TaskRecord task = new TaskBuilder(mSupervisor).setStack(stack).build();
-        task.setBounds(bounds);
+        // Just work around the unnecessary adjustments for bounds.
+        task.getWindowConfiguration().setBounds(bounds);
     }
 
     private void assertEquivalentWindowingMode(int expected, int actual, int parentWindowingMode) {
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
index a0302f6..c83401b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
@@ -28,14 +28,19 @@
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
 import static android.util.DisplayMetrics.DENSITY_DEFAULT;
 import static android.view.Surface.ROTATION_0;
+import static android.view.Surface.ROTATION_90;
 
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.eq;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
+import static com.android.server.policy.WindowManagerPolicy.USER_ROTATION_FREE;
+import static com.android.server.wm.DisplayRotation.FIXED_TO_USER_ROTATION_ENABLED;
 import static com.android.server.wm.WindowContainer.POSITION_TOP;
 
+import static com.google.common.truth.Truth.assertThat;
+
 import static org.hamcrest.Matchers.not;
 import static org.hamcrest.Matchers.sameInstance;
 import static org.junit.Assert.assertEquals;
@@ -64,6 +69,7 @@
 import android.util.Xml;
 import android.view.DisplayInfo;
 
+import androidx.test.filters.FlakyTest;
 import androidx.test.filters.MediumTest;
 
 import com.android.internal.app.IVoiceInteractor;
@@ -102,6 +108,7 @@
     public void setUp() throws Exception {
         TaskRecord.setTaskRecordFactory(null);
         mParentBounds = new Rect(10 /*left*/, 30 /*top*/, 80 /*right*/, 60 /*bottom*/);
+        removeGlobalMinSizeRestriction();
     }
 
     @Test
@@ -165,6 +172,7 @@
 
     /** Ensures that bounds on freeform stacks are not clipped. */
     @Test
+    @FlakyTest(bugId = 137879065)
     public void testAppBounds_FreeFormBounds() {
         final Rect freeFormBounds = new Rect(mParentBounds);
         freeFormBounds.offset(10, 10);
@@ -174,6 +182,7 @@
 
     /** Ensures that fully contained bounds are not clipped. */
     @Test
+    @FlakyTest(bugId = 137879065)
     public void testAppBounds_ContainedBounds() {
         final Rect insetBounds = new Rect(mParentBounds);
         insetBounds.inset(5, 5, 5, 5);
@@ -182,6 +191,7 @@
     }
 
     @Test
+    @FlakyTest(bugId = 137879065)
     public void testFitWithinBounds() {
         final Rect parentBounds = new Rect(10, 10, 200, 200);
         ActivityDisplay display = mService.mRootActivityContainer.getDefaultDisplay();
@@ -221,6 +231,7 @@
 
     /** Tests that the task bounds adjust properly to changes between FULLSCREEN and FREEFORM */
     @Test
+    @FlakyTest(bugId = 137879065)
     public void testBoundsOnModeChangeFreeformToFullscreen() {
         ActivityDisplay display = mService.mRootActivityContainer.getDefaultDisplay();
         ActivityStack stack = new StackBuilder(mRootActivityContainer).setDisplay(display)
@@ -248,18 +259,6 @@
     }
 
     /**
-     * This is a temporary hack to trigger an onConfigurationChange at the task level after an
-     * orientation is requested. Normally this is done by the onDescendentOrientationChanged call
-     * up the WM hierarchy, but since the WM hierarchy is mocked out, it doesn't happen here.
-     * TODO: remove this when we either get a WM hierarchy or when hierarchies are merged.
-     */
-    private void setActivityRequestedOrientation(ActivityRecord activity, int orientation) {
-        activity.setRequestedOrientation(orientation);
-        ConfigurationContainer taskRecord = activity.getParent();
-        taskRecord.onConfigurationChanged(taskRecord.getParent().getConfiguration());
-    }
-
-    /**
      * Tests that a task with forced orientation has orientation-consistent bounds within the
      * parent.
      */
@@ -268,49 +267,48 @@
         final Rect fullScreenBounds = new Rect(0, 0, 1920, 1080);
         final Rect fullScreenBoundsPort = new Rect(0, 0, 1080, 1920);
         DisplayInfo info = new DisplayInfo();
+        mService.mContext.getDisplay().getDisplayInfo(info);
         info.logicalWidth = fullScreenBounds.width();
         info.logicalHeight = fullScreenBounds.height();
         ActivityDisplay display = addNewActivityDisplayAt(info, POSITION_TOP);
         assertTrue(mRootActivityContainer.getActivityDisplay(display.mDisplayId) != null);
-        // Override display orientation. Normally this is available via DisplayContent, but DC
-        // is mocked-out.
-        display.getRequestedOverrideConfiguration().orientation =
-                Configuration.ORIENTATION_LANDSCAPE;
-        display.onRequestedOverrideConfigurationChanged(
-                display.getRequestedOverrideConfiguration());
+        // Fix the display orientation to landscape which is the natural rotation (0) for the test
+        // display.
+        final DisplayRotation dr = display.mDisplayContent.getDisplayRotation();
+        dr.setFixedToUserRotation(FIXED_TO_USER_ROTATION_ENABLED);
+        dr.setUserRotation(USER_ROTATION_FREE, ROTATION_0);
+
         ActivityStack stack = new StackBuilder(mRootActivityContainer)
                 .setWindowingMode(WINDOWING_MODE_FULLSCREEN).setDisplay(display).build();
         TaskRecord task = stack.getChildAt(0);
         ActivityRecord root = task.getTopActivity();
-        assertEquals(root, task.getTopActivity());
 
         assertEquals(fullScreenBounds, task.getBounds());
 
         // Setting app to fixed portrait fits within parent
-        setActivityRequestedOrientation(root, SCREEN_ORIENTATION_PORTRAIT);
+        root.setRequestedOrientation(SCREEN_ORIENTATION_PORTRAIT);
         assertEquals(root, task.getRootActivity());
         assertEquals(SCREEN_ORIENTATION_PORTRAIT, task.getRootActivity().getOrientation());
-        assertTrue(task.getBounds().width() < task.getBounds().height());
+        assertThat(task.getBounds().width()).isLessThan(task.getBounds().height());
         assertEquals(fullScreenBounds.height(), task.getBounds().height());
 
         // Top activity gets used
         ActivityRecord top = new ActivityBuilder(mService).setTask(task).setStack(stack).build();
         assertEquals(top, task.getTopActivity());
-        setActivityRequestedOrientation(top, SCREEN_ORIENTATION_LANDSCAPE);
-        assertTrue(task.getBounds().width() > task.getBounds().height());
+        top.setRequestedOrientation(SCREEN_ORIENTATION_LANDSCAPE);
+        assertThat(task.getBounds().width()).isGreaterThan(task.getBounds().height());
         assertEquals(task.getBounds().width(), fullScreenBounds.width());
 
         // Setting app to unspecified restores
-        setActivityRequestedOrientation(top, SCREEN_ORIENTATION_UNSPECIFIED);
+        top.setRequestedOrientation(SCREEN_ORIENTATION_UNSPECIFIED);
         assertEquals(fullScreenBounds, task.getBounds());
 
         // Setting app to fixed landscape and changing display
-        setActivityRequestedOrientation(top, SCREEN_ORIENTATION_LANDSCAPE);
-        // simulate display orientation changing (normally done via DisplayContent)
-        display.getRequestedOverrideConfiguration().orientation =
-                Configuration.ORIENTATION_PORTRAIT;
-        display.setBounds(fullScreenBoundsPort);
-        assertTrue(task.getBounds().width() > task.getBounds().height());
+        top.setRequestedOrientation(SCREEN_ORIENTATION_LANDSCAPE);
+        // Fix the display orientation to portrait which is 90 degrees for the test display.
+        dr.setUserRotation(USER_ROTATION_FREE, ROTATION_90);
+
+        assertThat(task.getBounds().width()).isGreaterThan(task.getBounds().height());
         assertEquals(fullScreenBoundsPort.width(), task.getBounds().width());
 
         // in FREEFORM, no constraint
@@ -323,7 +321,7 @@
 
         // FULLSCREEN letterboxes bounds
         stack.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
-        assertTrue(task.getBounds().width() > task.getBounds().height());
+        assertThat(task.getBounds().width()).isGreaterThan(task.getBounds().height());
         assertEquals(fullScreenBoundsPort.width(), task.getBounds().width());
 
         // FREEFORM restores bounds as before
@@ -335,6 +333,7 @@
     public void testIgnoresForcedOrientationWhenParentHandles() {
         final Rect fullScreenBounds = new Rect(0, 0, 1920, 1080);
         DisplayInfo info = new DisplayInfo();
+        mService.mContext.getDisplay().getDisplayInfo(info);
         info.logicalWidth = fullScreenBounds.width();
         info.logicalHeight = fullScreenBounds.height();
         ActivityDisplay display = addNewActivityDisplayAt(info, POSITION_TOP);
@@ -355,7 +354,7 @@
 
         // Setting app to fixed portrait fits within parent, but TaskRecord shouldn't adjust the
         // bounds because its parent says it will handle it at a later time.
-        setActivityRequestedOrientation(root, SCREEN_ORIENTATION_PORTRAIT);
+        root.setRequestedOrientation(SCREEN_ORIENTATION_PORTRAIT);
         assertEquals(root, task.getRootActivity());
         assertEquals(SCREEN_ORIENTATION_PORTRAIT, task.getRootActivity().getOrientation());
         assertEquals(fullScreenBounds, task.getBounds());
@@ -646,7 +645,7 @@
         final ActivityRecord activity0 = task0.getChildAt(0);
 
         final TaskRecord task1 = getTestTask();
-        final ActivityRecord activity1 = task0.getChildAt(0);
+        final ActivityRecord activity1 = task1.getChildAt(0);
 
         assertEquals(task0.taskId,
                 ActivityRecord.getTaskForActivityLocked(activity0.appToken, false /* onlyRoot */));
diff --git a/services/tests/wmtests/src/com/android/server/wm/TestActivityDisplay.java b/services/tests/wmtests/src/com/android/server/wm/TestActivityDisplay.java
new file mode 100644
index 0000000..c143969
--- /dev/null
+++ b/services/tests/wmtests/src/com/android/server/wm/TestActivityDisplay.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm;
+
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS;
+
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyBoolean;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
+
+import android.hardware.display.DisplayManagerGlobal;
+import android.view.Display;
+import android.view.DisplayInfo;
+
+class TestActivityDisplay extends ActivityDisplay {
+    private final ActivityStackSupervisor mSupervisor;
+
+    static TestActivityDisplay create(ActivityStackSupervisor supervisor) {
+        return create(supervisor, SystemServicesTestRule.sNextDisplayId++);
+    }
+
+    static TestActivityDisplay create(ActivityStackSupervisor supervisor, DisplayInfo info) {
+        return create(supervisor, SystemServicesTestRule.sNextDisplayId++, info);
+    }
+
+    static TestActivityDisplay create(ActivityStackSupervisor supervisor, int displayId) {
+        final DisplayInfo info = new DisplayInfo();
+        supervisor.mService.mContext.getDisplay().getDisplayInfo(info);
+        return create(supervisor, displayId, info);
+    }
+
+    static TestActivityDisplay create(ActivityStackSupervisor supervisor, int displayId,
+            DisplayInfo info) {
+        if (displayId == DEFAULT_DISPLAY) {
+            synchronized (supervisor.mService.mGlobalLock) {
+                return new TestActivityDisplay(supervisor,
+                        supervisor.mRootActivityContainer.mDisplayManager.getDisplay(displayId));
+            }
+        }
+        final Display display = new Display(DisplayManagerGlobal.getInstance(), displayId,
+                info, DEFAULT_DISPLAY_ADJUSTMENTS);
+
+        synchronized (supervisor.mService.mGlobalLock) {
+            return new TestActivityDisplay(supervisor, display);
+        }
+    }
+
+    private TestActivityDisplay(ActivityStackSupervisor supervisor, Display display) {
+        super(supervisor.mService.mRootActivityContainer, display);
+        // Normally this comes from display-properties as exposed by WM. Without that, just
+        // hard-code to FULLSCREEN for tests.
+        setWindowingMode(WINDOWING_MODE_FULLSCREEN);
+        mSupervisor = supervisor;
+        spyOn(this);
+        spyOn(mDisplayContent);
+        doAnswer(invocation -> {
+            // Bypass all the rotation animation and display freezing stuff for testing and just
+            // set the rotation we want for the display
+            final DisplayContent dc = mDisplayContent;
+            final int oldRotation = dc.getRotation();
+            final int rotation = dc.getDisplayRotation().rotationForOrientation(
+                    dc.getLastOrientation(), oldRotation);
+            if (oldRotation == rotation) {
+                return false;
+            }
+            dc.setLayoutNeeded();
+            dc.setRotation(rotation);
+            return true;
+        }).when(mDisplayContent).updateRotationUnchecked(anyBoolean());
+    }
+
+    @SuppressWarnings("TypeParameterUnusedInFormals")
+    @Override
+    ActivityStack createStackUnchecked(int windowingMode, int activityType,
+            int stackId, boolean onTop) {
+        return new ActivityTestsBase.StackBuilder(mSupervisor.mRootActivityContainer)
+                .setDisplay(this)
+                .setWindowingMode(windowingMode)
+                .setActivityType(activityType)
+                .setStackId(stackId)
+                .setOnTop(onTop)
+                .setCreateActivity(false)
+                .build();
+    }
+}
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 acfc2ea..921f105 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java
@@ -27,6 +27,7 @@
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.eq;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.reset;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.times;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
@@ -113,6 +114,7 @@
 
     @Test
     public void testAddChildSetsSurfacePosition() {
+        reset(mTransaction);
         try (MockSurfaceBuildingContainer top = new MockSurfaceBuildingContainer(mWm)) {
             WindowContainer child = new WindowContainer(mWm);
             child.setBounds(1, 1, 10, 10);
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java
index 06bcdf8..60cefe8 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java
@@ -57,6 +57,7 @@
 
     private final IWindow mIWindow = new TestIWindow();
     private final Rect mEmptyRect = new Rect();
+    private DisplayContent mTestDisplayContent;
 
     static class FrameTestWindowState extends WindowState {
         boolean mDockedResizingForTest = false;
@@ -77,6 +78,9 @@
     @Before
     public void setUp() throws Exception {
         mStubStack = mock(TaskStack.class);
+        DisplayInfo testDisplayInfo = new DisplayInfo(mDisplayInfo);
+        testDisplayInfo.displayCutout = null;
+        mTestDisplayContent = createNewDisplay(testDisplayInfo);
     }
 
     // Do not use this function directly in the tests below. Instead, use more explicit function
@@ -100,6 +104,10 @@
         assertRect(w.getStableInsets(), left, top, right, bottom);
     }
 
+    private void assertFrame(WindowState w, Rect frame) {
+        assertEquals(w.getFrameLw(), frame);
+    }
+
     private void assertFrame(WindowState w, int left, int top, int right, int bottom) {
         assertRect(w.getFrameLw(), left, top, right, bottom);
     }
@@ -380,9 +388,10 @@
     }
 
     @Test
+    @FlakyTest(bugId = 137879065)
     public void testLayoutLetterboxedWindow() {
         // First verify task behavior in multi-window mode.
-        final DisplayInfo displayInfo = mWm.getDefaultDisplayContentLocked().getDisplayInfo();
+        final DisplayInfo displayInfo = mTestDisplayContent.getDisplayInfo();
         final int logicalWidth = displayInfo.logicalWidth;
         final int logicalHeight = displayInfo.logicalHeight;
 
@@ -413,13 +422,14 @@
         final Rect cf = new Rect(xInset, 0, logicalWidth - xInset, logicalHeight);
         Configuration config = new Configuration(w.mAppToken.getRequestedOverrideConfiguration());
         config.windowConfiguration.setBounds(cf);
+        config.windowConfiguration.setAppBounds(cf);
         w.mAppToken.onRequestedOverrideConfigurationChanged(config);
         pf.set(0, 0, logicalWidth, logicalHeight);
         task.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
         task.setBounds(null);
         windowFrames.setFrames(pf, pf, pf, cf, cf, pf, cf, mEmptyRect);
         w.computeFrameLw();
-        assertFrame(w, cf.left, cf.top, cf.right, cf.bottom);
+        assertFrame(w, cf);
         assertContentFrame(w, cf);
         assertContentInset(w, 0, 0, 0, 0);
     }
@@ -483,7 +493,7 @@
         w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP;
         task.setWindowingMode(WINDOWING_MODE_FREEFORM);
 
-        DisplayContent dc = mWm.getDefaultDisplayContentLocked();
+        DisplayContent dc = mTestDisplayContent;
         dc.mInputMethodTarget = w;
         WindowState mockIme = mock(WindowState.class);
         Mockito.doReturn(true).when(mockIme).isVisibleNow();
@@ -537,7 +547,7 @@
         attrs.width = width;
         attrs.height = height;
 
-        AppWindowToken token = createAppWindowToken(mWm.getDefaultDisplayContentLocked(),
+        AppWindowToken token = createAppWindowToken(mTestDisplayContent,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
 
         FrameTestWindowState ws = new FrameTestWindowState(mWm, mIWindow, token, attrs);
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
index 36698ea..763d086 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
@@ -517,13 +517,19 @@
 
     @Test
     public void testGetTransformationMatrix() {
+        final int PARENT_WINDOW_OFFSET = 1;
+        final int DISPLAY_IN_PARENT_WINDOW_OFFSET = 2;
+        final int WINDOW_OFFSET = 3;
+        final float OFFSET_SUM =
+                PARENT_WINDOW_OFFSET + DISPLAY_IN_PARENT_WINDOW_OFFSET + WINDOW_OFFSET;
+
         synchronized (mWm.mGlobalLock) {
             final WindowState win0 = createWindow(null, TYPE_APPLICATION, "win0");
-            win0.getFrameLw().offsetTo(1, 0);
 
             final DisplayContent dc = createNewDisplay();
+            win0.getFrameLw().offsetTo(PARENT_WINDOW_OFFSET, 0);
             dc.reparentDisplayContent(win0, win0.getSurfaceControl());
-            dc.updateLocation(win0, 2, 0);
+            dc.updateLocation(win0, DISPLAY_IN_PARENT_WINDOW_OFFSET, 0);
 
             final float[] values = new float[9];
             final Matrix matrix = new Matrix();
@@ -531,12 +537,12 @@
             final WindowState win1 = createWindow(null, TYPE_APPLICATION, dc, "win1");
             win1.mHasSurface = true;
             win1.mSurfaceControl = mock(SurfaceControl.class);
-            win1.getFrameLw().offsetTo(3, 0);
+            win1.getFrameLw().offsetTo(WINDOW_OFFSET, 0);
             win1.updateSurfacePosition(t);
             win1.getTransformationMatrix(values, matrix);
 
             matrix.getValues(values);
-            assertEquals(6f, values[Matrix.MTRANS_X], 0f);
+            assertEquals(OFFSET_SUM, values[Matrix.MTRANS_X], 0f);
             assertEquals(0f, values[Matrix.MTRANS_Y], 0f);
         }
     }
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 dc461d1..0732066 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
@@ -20,8 +20,6 @@
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
 import static android.os.Process.SYSTEM_UID;
-import static android.view.Display.DEFAULT_DISPLAY;
-import static android.view.DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS;
 import static android.view.View.VISIBLE;
 import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
 import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
@@ -38,20 +36,18 @@
 
 import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
 
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
+import static com.android.server.wm.ActivityDisplay.POSITION_TOP;
 
 import static org.mockito.Mockito.mock;
 
 
 import android.content.Context;
 import android.content.res.Configuration;
-import android.hardware.display.DisplayManagerGlobal;
 import android.testing.DexmakerShareClassLoaderRule;
 import android.util.Log;
 import android.view.Display;
 import android.view.DisplayInfo;
 import android.view.IWindow;
-import android.view.Surface;
 import android.view.SurfaceControl.Transaction;
 import android.view.WindowManager;
 
@@ -79,10 +75,6 @@
     WindowManagerService mWm;
     private final IWindow mIWindow = new TestIWindow();
     private Session mMockSession;
-    // The default display is removed in {@link #setUp} and then we iterate over all displays to
-    // make sure we don't collide with any existing display. If we run into no other display, the
-    // added display should be treated as default. This cannot be the default display
-    private static int sNextDisplayId = DEFAULT_DISPLAY + 1;
     static int sNextStackId = 1000;
 
     /** Non-default display. */
@@ -134,27 +126,16 @@
         // in the set up are clear. This can be removed when b/37850063 is fixed.
         try {
             mMockSession = mock(Session.class);
-            mTransaction = spy(StubTransaction.class);
 
             final Context context = getInstrumentation().getTargetContext();
 
             mWm = mSystemServicesTestRule.getWindowManagerService();
-
-            // Setup factory classes to prevent calls to native code.
-
-            // Return a spied Transaction class than can be used to verify calls.
-            mWm.mTransactionFactory = () -> mTransaction;
-            // Return a SurfaceControl.Builder class that creates mocked SurfaceControl instances.
-            mWm.mSurfaceBuilderFactory = (unused) -> new MockSurfaceControlBuilder();
-            // Return mocked Surface instances.
-            mWm.mSurfaceFactory = () -> mock(Surface.class);
+            mTransaction = mSystemServicesTestRule.mTransaction;
 
             beforeCreateDisplay();
 
             context.getDisplay().getDisplayInfo(mDisplayInfo);
             mDisplayContent = createNewDisplay();
-            mWm.mDisplayEnabled = true;
-            mWm.mDisplayReady = true;
 
             // Set-up some common windows.
             mCommonWindows = new HashSet<>();
@@ -211,12 +192,6 @@
                     nonCommonWindows.pollLast().removeImmediately();
                 }
 
-                for (int i = mWm.mRoot.mChildren.size() - 1; i >= 0; --i) {
-                    final DisplayContent displayContent = mWm.mRoot.mChildren.get(i);
-                    if (!displayContent.isDefaultDisplay) {
-                        displayContent.removeImmediately();
-                    }
-                }
                 // Remove app transition & window freeze timeout callbacks to prevent unnecessary
                 // actions after test.
                 mWm.getDefaultDisplayContentLocked().mAppTransition
@@ -408,13 +383,11 @@
     }
 
     /** Creates a {@link DisplayContent} and adds it to the system. */
-    DisplayContent createNewDisplay(DisplayInfo displayInfo) {
-        final int displayId = sNextDisplayId++;
-        final Display display = new Display(DisplayManagerGlobal.getInstance(), displayId,
-                displayInfo, DEFAULT_DISPLAY_ADJUSTMENTS);
-        synchronized (mWm.mGlobalLock) {
-            return new DisplayContent(display, mWm, mock(ActivityDisplay.class));
-        }
+    DisplayContent createNewDisplay(DisplayInfo info) {
+        final ActivityDisplay display =
+                TestActivityDisplay.create(mWm.mAtmService.mStackSupervisor, info);
+        mWm.mAtmService.mRootActivityContainer.addChild(display, POSITION_TOP);
+        return display.mDisplayContent;
     }
 
     /**
@@ -428,17 +401,7 @@
         DisplayInfo displayInfo = new DisplayInfo();
         displayInfo.copyFrom(mDisplayInfo);
         displayInfo.state = displayState;
-        final int displayId = sNextDisplayId++;
-        final Display display = new Display(DisplayManagerGlobal.getInstance(), displayId,
-                displayInfo, DEFAULT_DISPLAY_ADJUSTMENTS);
-        synchronized (mWm.mGlobalLock) {
-            // Display creation is driven by DisplayWindowController via ActivityStackSupervisor.
-            // We skip those steps here.
-            final ActivityDisplay mockAd = mock(ActivityDisplay.class);
-            final DisplayContent displayContent = mWm.mRoot.createDisplayContent(display, mockAd);
-            displayContent.reconfigureDisplayLocked();
-            return displayContent;
-        }
+        return createNewDisplay(displayInfo);
     }
 
     /** Creates a {@link com.android.server.wm.WindowTestUtils.TestWindowState} */