Merge "Synchronize window config updates (8/n)" into main
diff --git a/core/java/android/app/servertransaction/ActivityConfigurationChangeItem.java b/core/java/android/app/servertransaction/ActivityConfigurationChangeItem.java
index dd332c8..bc8fac5 100644
--- a/core/java/android/app/servertransaction/ActivityConfigurationChangeItem.java
+++ b/core/java/android/app/servertransaction/ActivityConfigurationChangeItem.java
@@ -71,17 +71,13 @@
     @NonNull
     public static ActivityConfigurationChangeItem obtain(@NonNull IBinder activityToken,
             @NonNull Configuration config) {
-        if (config == null) {
-            throw new IllegalArgumentException("Config must not be null.");
-        }
-
         ActivityConfigurationChangeItem instance =
                 ObjectPool.obtain(ActivityConfigurationChangeItem.class);
         if (instance == null) {
             instance = new ActivityConfigurationChangeItem();
         }
         instance.setActivityToken(activityToken);
-        instance.mConfiguration = config;
+        instance.mConfiguration = new Configuration(config);
 
         return instance;
     }
@@ -89,7 +85,7 @@
     @Override
     public void recycle() {
         super.recycle();
-        mConfiguration = Configuration.EMPTY;
+        mConfiguration = null;
         ObjectPool.recycle(this);
     }
 
diff --git a/core/java/android/app/servertransaction/ActivityRelaunchItem.java b/core/java/android/app/servertransaction/ActivityRelaunchItem.java
index a5dd115..3ce094e 100644
--- a/core/java/android/app/servertransaction/ActivityRelaunchItem.java
+++ b/core/java/android/app/servertransaction/ActivityRelaunchItem.java
@@ -32,6 +32,7 @@
 
 import com.android.internal.content.ReferrerIntent;
 
+import java.util.ArrayList;
 import java.util.List;
 import java.util.Objects;
 
@@ -51,7 +52,7 @@
 
     /**
      * A record that was properly configured for relaunch. Execution will be cancelled if not
-     * initialized after {@link #preExecute(ClientTransactionHandler, IBinder)}.
+     * initialized after {@link #preExecute(ClientTransactionHandler)}.
      */
     private ActivityClientRecord mActivityClientRecord;
 
@@ -99,10 +100,11 @@
             instance = new ActivityRelaunchItem();
         }
         instance.setActivityToken(activityToken);
-        instance.mPendingResults = pendingResults;
-        instance.mPendingNewIntents = pendingNewIntents;
+        instance.mPendingResults = pendingResults != null ? new ArrayList<>(pendingResults) : null;
+        instance.mPendingNewIntents =
+                pendingNewIntents != null ? new ArrayList<>(pendingNewIntents) : null;
         instance.mConfigChanges = configChanges;
-        instance.mConfig = config;
+        instance.mConfig = new MergedConfiguration(config);
         instance.mPreserveWindow = preserveWindow;
 
         return instance;
diff --git a/core/java/android/app/servertransaction/ActivityResultItem.java b/core/java/android/app/servertransaction/ActivityResultItem.java
index 24fced4..51a09fb 100644
--- a/core/java/android/app/servertransaction/ActivityResultItem.java
+++ b/core/java/android/app/servertransaction/ActivityResultItem.java
@@ -35,6 +35,7 @@
 import android.os.Parcelable;
 import android.os.Trace;
 
+import java.util.ArrayList;
 import java.util.List;
 import java.util.Objects;
 
@@ -82,7 +83,7 @@
             instance = new ActivityResultItem();
         }
         instance.setActivityToken(activityToken);
-        instance.mResultInfoList = resultInfoList;
+        instance.mResultInfoList = new ArrayList<>(resultInfoList);
 
         return instance;
     }
diff --git a/core/java/android/app/servertransaction/ActivityTransactionItem.java b/core/java/android/app/servertransaction/ActivityTransactionItem.java
index 2a65b35..b4ff476 100644
--- a/core/java/android/app/servertransaction/ActivityTransactionItem.java
+++ b/core/java/android/app/servertransaction/ActivityTransactionItem.java
@@ -20,6 +20,8 @@
 
 import static com.android.internal.annotations.VisibleForTesting.Visibility.PACKAGE;
 
+import static java.util.Objects.requireNonNull;
+
 import android.annotation.CallSuper;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -93,7 +95,7 @@
     }
 
     void setActivityToken(@NonNull IBinder activityToken) {
-        mActivityToken = activityToken;
+        mActivityToken = requireNonNull(activityToken);
     }
 
     // To be overridden
diff --git a/core/java/android/app/servertransaction/ClientTransaction.java b/core/java/android/app/servertransaction/ClientTransaction.java
index 9c0cd39..7c34cde 100644
--- a/core/java/android/app/servertransaction/ClientTransaction.java
+++ b/core/java/android/app/servertransaction/ClientTransaction.java
@@ -54,12 +54,14 @@
 
     /** A list of individual callbacks to a client. */
     @UnsupportedAppUsage
+    @Nullable
     private List<ClientTransactionItem> mActivityCallbacks;
 
     /**
      * Final lifecycle state in which the client activity should be after the transaction is
      * executed.
      */
+    @Nullable
     private ActivityLifecycleItem mLifecycleStateRequest;
 
     /** Target client. */
@@ -123,6 +125,7 @@
     @VisibleForTesting(visibility = PACKAGE)
     @UnsupportedAppUsage
     @Deprecated
+    @Nullable
     public ActivityLifecycleItem getLifecycleStateRequest() {
         return mLifecycleStateRequest;
     }
@@ -207,7 +210,7 @@
             for (int i = 0; i < size; i++) {
                 mActivityCallbacks.get(i).recycle();
             }
-            mActivityCallbacks.clear();
+            mActivityCallbacks = null;
         }
         if (mLifecycleStateRequest != null) {
             mLifecycleStateRequest.recycle();
diff --git a/core/java/android/app/servertransaction/ConfigurationChangeItem.java b/core/java/android/app/servertransaction/ConfigurationChangeItem.java
index 96961ace..0e327a7 100644
--- a/core/java/android/app/servertransaction/ConfigurationChangeItem.java
+++ b/core/java/android/app/servertransaction/ConfigurationChangeItem.java
@@ -64,7 +64,7 @@
         if (instance == null) {
             instance = new ConfigurationChangeItem();
         }
-        instance.mConfiguration = config;
+        instance.mConfiguration = new Configuration(config);
         instance.mDeviceId = deviceId;
 
         return instance;
diff --git a/core/java/android/app/servertransaction/LaunchActivityItem.java b/core/java/android/app/servertransaction/LaunchActivityItem.java
index a64c744..d2ef65a 100644
--- a/core/java/android/app/servertransaction/LaunchActivityItem.java
+++ b/core/java/android/app/servertransaction/LaunchActivityItem.java
@@ -45,6 +45,7 @@
 import com.android.internal.app.IVoiceInteractor;
 import com.android.internal.content.ReferrerIntent;
 
+import java.util.ArrayList;
 import java.util.List;
 import java.util.Objects;
 
@@ -135,10 +136,16 @@
         if (instance == null) {
             instance = new LaunchActivityItem();
         }
-        setValues(instance, activityToken, intent, ident, info, curConfig, overrideConfig, deviceId,
-                referrer, voiceInteractor, procState, state, persistentState, pendingResults,
-                pendingNewIntents, activityOptions, isForward, profilerInfo, assistToken,
-                activityClientController, shareableActivityToken,
+        setValues(instance, activityToken, new Intent(intent), ident,  new ActivityInfo(info),
+                new Configuration(curConfig), new Configuration(overrideConfig), deviceId,
+                referrer, voiceInteractor, procState,
+                state != null ? new Bundle(state) : null,
+                persistentState != null ? new PersistableBundle(persistentState) : null,
+                pendingResults != null ? new ArrayList<>(pendingResults) : null,
+                pendingNewIntents != null ? new ArrayList<>(pendingNewIntents) : null,
+                activityOptions, isForward,
+                profilerInfo != null ? new ProfilerInfo(profilerInfo) : null,
+                assistToken, activityClientController, shareableActivityToken,
                 launchedFromBubble, taskFragmentToken);
 
         return instance;
diff --git a/core/java/android/app/servertransaction/MoveToDisplayItem.java b/core/java/android/app/servertransaction/MoveToDisplayItem.java
index e56d3f8..961da19 100644
--- a/core/java/android/app/servertransaction/MoveToDisplayItem.java
+++ b/core/java/android/app/servertransaction/MoveToDisplayItem.java
@@ -69,7 +69,7 @@
         }
         instance.setActivityToken(activityToken);
         instance.mTargetDisplayId = targetDisplayId;
-        instance.mConfiguration = configuration;
+        instance.mConfiguration = new Configuration(configuration);
 
         return instance;
     }
@@ -78,7 +78,7 @@
     public void recycle() {
         super.recycle();
         mTargetDisplayId = 0;
-        mConfiguration = Configuration.EMPTY;
+        mConfiguration = null;
         ObjectPool.recycle(this);
     }
 
diff --git a/core/java/android/app/servertransaction/NewIntentItem.java b/core/java/android/app/servertransaction/NewIntentItem.java
index 8e995aa..acf2ea4 100644
--- a/core/java/android/app/servertransaction/NewIntentItem.java
+++ b/core/java/android/app/servertransaction/NewIntentItem.java
@@ -32,6 +32,7 @@
 
 import com.android.internal.content.ReferrerIntent;
 
+import java.util.ArrayList;
 import java.util.List;
 import java.util.Objects;
 
@@ -71,7 +72,7 @@
             instance = new NewIntentItem();
         }
         instance.setActivityToken(activityToken);
-        instance.mIntents = intents;
+        instance.mIntents = new ArrayList<>(intents);
         instance.mResume = resume;
 
         return instance;
diff --git a/core/java/android/app/servertransaction/WindowContextInfoChangeItem.java b/core/java/android/app/servertransaction/WindowContextInfoChangeItem.java
index 375d1bf..cbad92f 100644
--- a/core/java/android/app/servertransaction/WindowContextInfoChangeItem.java
+++ b/core/java/android/app/servertransaction/WindowContextInfoChangeItem.java
@@ -65,7 +65,7 @@
             instance = new WindowContextInfoChangeItem();
         }
         instance.mClientToken = requireNonNull(clientToken);
-        instance.mInfo = new WindowContextInfo(config, displayId);
+        instance.mInfo = new WindowContextInfo(new Configuration(config), displayId);
 
         return instance;
     }
diff --git a/core/java/android/app/servertransaction/WindowStateResizeItem.java b/core/java/android/app/servertransaction/WindowStateResizeItem.java
index 9828133..7d3eb87 100644
--- a/core/java/android/app/servertransaction/WindowStateResizeItem.java
+++ b/core/java/android/app/servertransaction/WindowStateResizeItem.java
@@ -77,10 +77,10 @@
             instance = new WindowStateResizeItem();
         }
         instance.mWindow = requireNonNull(window);
-        instance.mFrames = requireNonNull(frames);
+        instance.mFrames = new ClientWindowFrames(frames);
         instance.mReportDraw = reportDraw;
-        instance.mConfiguration = requireNonNull(configuration);
-        instance.mInsetsState = requireNonNull(insetsState);
+        instance.mConfiguration = new MergedConfiguration(configuration);
+        instance.mInsetsState = new InsetsState(insetsState);
         instance.mForceLayout = forceLayout;
         instance.mAlwaysConsumeSystemBars = alwaysConsumeSystemBars;
         instance.mDisplayId = displayId;
diff --git a/core/java/android/window/ClientWindowFrames.java b/core/java/android/window/ClientWindowFrames.java
index 0ce076b6..1bd921b 100644
--- a/core/java/android/window/ClientWindowFrames.java
+++ b/core/java/android/window/ClientWindowFrames.java
@@ -22,6 +22,8 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 
+import java.util.Objects;
+
 /**
  * The window frame container class used by client side for layout.
  * @hide
@@ -101,6 +103,29 @@
     }
 
     @Override
+    public boolean equals(@Nullable Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+        final ClientWindowFrames other = (ClientWindowFrames) o;
+        return frame.equals(other.frame)
+                && displayFrame.equals(other.displayFrame)
+                && parentFrame.equals(other.parentFrame)
+                && Objects.equals(attachedFrame, other.attachedFrame)
+                && isParentFrameClippedByDisplayCutout == other.isParentFrameClippedByDisplayCutout
+                && compatScale == other.compatScale;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(frame, displayFrame, parentFrame, attachedFrame,
+                isParentFrameClippedByDisplayCutout, compatScale);
+    }
+
+    @Override
     public int describeContents() {
         return 0;
     }
diff --git a/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java b/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
index 36e1223..4b02257 100644
--- a/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
+++ b/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
@@ -227,8 +227,7 @@
         try {
             // Send process level config change.
             ClientTransaction transaction = newTransaction(activityThread);
-            transaction.addCallback(ConfigurationChangeItem.obtain(
-                    new Configuration(newConfig), DEVICE_ID_INVALID));
+            transaction.addCallback(ConfigurationChangeItem.obtain(newConfig, DEVICE_ID_INVALID));
             appThread.scheduleTransaction(transaction);
             InstrumentationRegistry.getInstrumentation().waitForIdleSync();
 
@@ -245,7 +244,7 @@
             newConfig.smallestScreenWidthDp++;
             transaction = newTransaction(activityThread);
             transaction.addCallback(ActivityConfigurationChangeItem.obtain(
-                    activity.getActivityToken(), new Configuration(newConfig)));
+                    activity.getActivityToken(), newConfig));
             appThread.scheduleTransaction(transaction);
             InstrumentationRegistry.getInstrumentation().waitForIdleSync();
 
diff --git a/core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java b/core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java
index 4bbde0c..723c081 100644
--- a/core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java
+++ b/core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java
@@ -26,6 +26,7 @@
 import static org.junit.Assert.assertNotSame;
 import static org.junit.Assert.assertSame;
 
+import android.annotation.NonNull;
 import android.app.ActivityOptions;
 import android.app.IApplicationThread;
 import android.app.servertransaction.TestUtils.LaunchActivityItemBuilder;
@@ -80,74 +81,29 @@
 
     @Test
     public void testRecycleActivityConfigurationChangeItem() {
-        ActivityConfigurationChangeItem emptyItem = ActivityConfigurationChangeItem.obtain(
-                null /* activityToken */, Configuration.EMPTY);
-        ActivityConfigurationChangeItem item = ActivityConfigurationChangeItem.obtain(
-                mActivityToken, config());
-        assertNotSame(item, emptyItem);
-        assertNotEquals(item, emptyItem);
-
-        item.recycle();
-        assertEquals(item, emptyItem);
-
-        ActivityConfigurationChangeItem item2 = ActivityConfigurationChangeItem.obtain(
-                mActivityToken, config());
-        assertSame(item, item2);
-        assertNotEquals(item2, emptyItem);
+        testRecycle(() -> ActivityConfigurationChangeItem.obtain(mActivityToken, config()));
     }
 
     @Test
     public void testRecycleActivityResultItem() {
-        ActivityResultItem emptyItem = ActivityResultItem.obtain(
-                null /* activityToken */, null /* resultInfoList */);
-        ActivityResultItem item = ActivityResultItem.obtain(mActivityToken, resultInfoList());
-        assertNotSame(item, emptyItem);
-        assertNotEquals(item, emptyItem);
-
-        item.recycle();
-        assertEquals(item, emptyItem);
-
-        ActivityResultItem item2 = ActivityResultItem.obtain(mActivityToken, resultInfoList());
-        assertSame(item, item2);
-        assertNotEquals(item2, emptyItem);
+        testRecycle(() -> ActivityResultItem.obtain(mActivityToken, resultInfoList()));
     }
 
     @Test
     public void testRecycleConfigurationChangeItem() {
-        ConfigurationChangeItem emptyItem = ConfigurationChangeItem.obtain(null, 0);
-        ConfigurationChangeItem item = ConfigurationChangeItem.obtain(config(), 1);
-        assertNotSame(item, emptyItem);
-        assertNotEquals(item, emptyItem);
-
-        item.recycle();
-        assertEquals(item, emptyItem);
-
-        ConfigurationChangeItem item2 = ConfigurationChangeItem.obtain(config(), 1);
-        assertSame(item, item2);
-        assertNotEquals(item2, emptyItem);
+        testRecycle(() -> ConfigurationChangeItem.obtain(config(), 1));
     }
 
     @Test
     public void testRecycleDestroyActivityItem() {
-        DestroyActivityItem emptyItem = DestroyActivityItem.obtain(
-                null /* activityToken */, false, 0);
-        DestroyActivityItem item = DestroyActivityItem.obtain(mActivityToken, true, 117);
-        assertNotSame(item, emptyItem);
-        assertNotEquals(item, emptyItem);
-
-        item.recycle();
-        assertEquals(item, emptyItem);
-
-        DestroyActivityItem item2 = DestroyActivityItem.obtain(mActivityToken, true, 14);
-        assertSame(item, item2);
-        assertNotEquals(item2, emptyItem);
+        testRecycle(() -> DestroyActivityItem.obtain(mActivityToken, true, 117));
     }
 
     @Test
     public void testRecycleLaunchActivityItem() {
         final IBinder activityToken = new Binder();
         final Intent intent = new Intent("action");
-        int ident = 57;
+        final int ident = 57;
         final ActivityInfo activityInfo = new ActivityInfo();
         activityInfo.flags = 42;
         activityInfo.setMaxAspectRatio(2.4f);
@@ -158,20 +114,19 @@
         final Configuration overrideConfig = new Configuration();
         overrideConfig.assetsSeq = 5;
         final String referrer = "referrer";
-        int procState = 4;
+        final int procState = 4;
         final Bundle bundle = new Bundle();
         bundle.putString("key", "value");
         final PersistableBundle persistableBundle = new PersistableBundle();
         persistableBundle.putInt("k", 4);
         final IBinder assistToken = new Binder();
         final IBinder shareableActivityToken = new Binder();
-        int deviceId = 3;
+        final int deviceId = 3;
+        final IBinder taskFragmentToken = new Binder();
 
-        final Supplier<LaunchActivityItem> itemSupplier = () -> new LaunchActivityItemBuilder()
-                .setActivityToken(activityToken)
-                .setIntent(intent)
+        testRecycle(() -> new LaunchActivityItemBuilder(
+                activityToken, intent, activityInfo)
                 .setIdent(ident)
-                .setInfo(activityInfo)
                 .setCurConfig(config())
                 .setOverrideConfig(overrideConfig)
                 .setReferrer(referrer)
@@ -183,154 +138,74 @@
                 .setIsForward(true)
                 .setAssistToken(assistToken)
                 .setShareableActivityToken(shareableActivityToken)
-                .setTaskFragmentToken(new Binder())
+                .setTaskFragmentToken(taskFragmentToken)
                 .setDeviceId(deviceId)
-                .build();
-
-        LaunchActivityItem emptyItem = new LaunchActivityItemBuilder().build();
-        LaunchActivityItem item = itemSupplier.get();
-        assertNotSame(item, emptyItem);
-        assertNotEquals(item, emptyItem);
-
-        item.recycle();
-        assertEquals(item, emptyItem);
-
-        LaunchActivityItem item2 = itemSupplier.get();
-        assertSame(item, item2);
-        assertNotEquals(item2, emptyItem);
+                .build());
     }
 
     @Test
     public void testRecycleActivityRelaunchItem() {
-        ActivityRelaunchItem emptyItem = ActivityRelaunchItem.obtain(
-                null /* activityToken */, null, null, 0, null, false);
-        Configuration overrideConfig = new Configuration();
-        overrideConfig.assetsSeq = 5;
-        ActivityRelaunchItem item = ActivityRelaunchItem.obtain(mActivityToken, resultInfoList(),
-                referrerIntentList(), 42, mergedConfig(), true);
-        assertNotSame(item, emptyItem);
-        assertNotEquals(item, emptyItem);
-
-        item.recycle();
-        assertEquals(item, emptyItem);
-
-        ActivityRelaunchItem item2 = ActivityRelaunchItem.obtain(mActivityToken, resultInfoList(),
-                referrerIntentList(), 42, mergedConfig(), true);
-        assertSame(item, item2);
-        assertNotEquals(item2, emptyItem);
+        testRecycle(() -> ActivityRelaunchItem.obtain(mActivityToken,
+                resultInfoList(), referrerIntentList(), 42, mergedConfig(), true));
     }
 
     @Test
     public void testRecycleMoveToDisplayItem() {
-        MoveToDisplayItem emptyItem = MoveToDisplayItem.obtain(
-                null /* activityToken */, 0, Configuration.EMPTY);
-        MoveToDisplayItem item = MoveToDisplayItem.obtain(mActivityToken, 4, config());
-        assertNotSame(item, emptyItem);
-        assertNotEquals(item, emptyItem);
-
-        item.recycle();
-        assertEquals(item, emptyItem);
-
-        MoveToDisplayItem item2 = MoveToDisplayItem.obtain(mActivityToken, 3, config());
-        assertSame(item, item2);
-        assertNotEquals(item2, emptyItem);
+        testRecycle(() -> MoveToDisplayItem.obtain(mActivityToken, 4, config()));
     }
 
     @Test
     public void testRecycleNewIntentItem() {
-        NewIntentItem emptyItem = NewIntentItem.obtain(
-                null /* activityToken */, null /* intents */, false /* resume */);
-        NewIntentItem item = NewIntentItem.obtain(mActivityToken, referrerIntentList(), false);
-        assertNotSame(item, emptyItem);
-        assertNotEquals(item, emptyItem);
-
-        item.recycle();
-        assertEquals(item, emptyItem);
-
-        NewIntentItem item2 = NewIntentItem.obtain(mActivityToken, referrerIntentList(), false);
-        assertSame(item, item2);
-        assertNotEquals(item2, emptyItem);
+        testRecycle(() -> NewIntentItem.obtain(mActivityToken, referrerIntentList(), false));
     }
 
     @Test
     public void testRecyclePauseActivityItemItem() {
-        PauseActivityItem emptyItem = PauseActivityItem.obtain(
-                null /* activityToken */, false, false, 0, false, false);
-        PauseActivityItem item = PauseActivityItem.obtain(
-                mActivityToken, true, true, 5, true, true);
-        assertNotSame(item, emptyItem);
-        assertNotEquals(item, emptyItem);
-
-        item.recycle();
-        assertEquals(item, emptyItem);
-
-        PauseActivityItem item2 = PauseActivityItem.obtain(
-                mActivityToken, true, false, 5, true, true);
-        assertSame(item, item2);
-        assertNotEquals(item2, emptyItem);
+        testRecycle(() -> PauseActivityItem.obtain(mActivityToken, true, true, 5, true, true));
     }
 
     @Test
     public void testRecycleResumeActivityItem() {
-        ResumeActivityItem emptyItem = ResumeActivityItem.obtain(
-                null /* activityToken */, false, false);
-        ResumeActivityItem item = ResumeActivityItem.obtain(mActivityToken, 3, true, false);
-        assertNotSame(item, emptyItem);
-        assertNotEquals(item, emptyItem);
-
-        item.recycle();
-        assertEquals(item, emptyItem);
-
-        ResumeActivityItem item2 = ResumeActivityItem.obtain(mActivityToken, 2, true, false);
-        assertSame(item, item2);
-        assertNotEquals(item2, emptyItem);
+        testRecycle(() -> ResumeActivityItem.obtain(mActivityToken, 3, true, false));
     }
 
     @Test
     public void testRecycleStartActivityItem() {
-        StartActivityItem emptyItem = StartActivityItem.obtain(
-                null /* activityToken */, null /* activityOptions */);
-        StartActivityItem item = StartActivityItem.obtain(mActivityToken,
-                ActivityOptions.makeBasic());
-        assertNotSame(item, emptyItem);
-        assertNotEquals(item, emptyItem);
-
-        item.recycle();
-        assertEquals(item, emptyItem);
-
-        StartActivityItem item2 = StartActivityItem.obtain(mActivityToken,
-                ActivityOptions.makeBasic().setLaunchDisplayId(10));
-        assertSame(item, item2);
-        assertNotEquals(item2, emptyItem);
+        testRecycle(() -> StartActivityItem.obtain(mActivityToken, ActivityOptions.makeBasic()));
     }
 
     @Test
     public void testRecycleStopItem() {
-        StopActivityItem emptyItem = StopActivityItem.obtain(null /* activityToken */, 0);
-        StopActivityItem item = StopActivityItem.obtain(mActivityToken, 4);
-        assertNotSame(item, emptyItem);
-        assertNotEquals(item, emptyItem);
-
-        item.recycle();
-        assertEquals(item, emptyItem);
-
-        StopActivityItem item2 = StopActivityItem.obtain(mActivityToken, 3);
-        assertSame(item, item2);
-        assertNotEquals(item2, emptyItem);
+        testRecycle(() -> StopActivityItem.obtain(mActivityToken, 4));
     }
 
     @Test
     public void testRecycleClientTransaction() {
-        ClientTransaction emptyItem = ClientTransaction.obtain(null);
-        ClientTransaction item = ClientTransaction.obtain(mApplicationThread);
-        assertNotSame(item, emptyItem);
-        assertNotEquals(item, emptyItem);
+        testRecycle(() -> ClientTransaction.obtain(mApplicationThread));
+    }
 
+    private void testRecycle(@NonNull Supplier<? extends ObjectPoolItem> obtain) {
+        // Reuse the same object after recycle.
+        final ObjectPoolItem item = obtain.get();
         item.recycle();
-        assertEquals(item, emptyItem);
+        final ObjectPoolItem item2 = obtain.get();
 
-        ClientTransaction item2 = ClientTransaction.obtain(mApplicationThread);
         assertSame(item, item2);
-        assertNotEquals(item2, emptyItem);
+
+        // Create new object when the pool is empty.
+        final ObjectPoolItem item3 = obtain.get();
+
+        assertNotSame(item, item3);
+        assertEquals(item, item3);
+
+        // Reset fields after recycle.
+        item.recycle();
+
+        assertNotEquals(item, item3);
+
+        // Recycled objects are equal.
+        item3.recycle();
+
+        assertEquals(item, item3);
     }
 }
diff --git a/core/tests/coretests/src/android/app/servertransaction/TestUtils.java b/core/tests/coretests/src/android/app/servertransaction/TestUtils.java
index 5a88bad..c0e2a49 100644
--- a/core/tests/coretests/src/android/app/servertransaction/TestUtils.java
+++ b/core/tests/coretests/src/android/app/servertransaction/TestUtils.java
@@ -18,6 +18,8 @@
 
 import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
 
+import static java.util.Objects.requireNonNull;
+
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.ActivityOptions;
@@ -92,17 +94,18 @@
     }
 
     static class LaunchActivityItemBuilder {
-        @Nullable
-        private IBinder mActivityToken;
-        @Nullable
-        private Intent mIntent;
+        @NonNull
+        private final IBinder mActivityToken;
+        @NonNull
+        private final Intent mIntent;
+        @NonNull
+        private final ActivityInfo mInfo;
+        @NonNull
+        private final Configuration mCurConfig = new Configuration();
+        @NonNull
+        private final Configuration mOverrideConfig = new Configuration();
+
         private int mIdent;
-        @Nullable
-        private ActivityInfo mInfo;
-        @Nullable
-        private Configuration mCurConfig;
-        @Nullable
-        private Configuration mOverrideConfig;
         private int mDeviceId;
         @Nullable
         private String mReferrer;
@@ -130,16 +133,11 @@
         @Nullable
         private IBinder mTaskFragmentToken;
 
-        @NonNull
-        LaunchActivityItemBuilder setActivityToken(@Nullable IBinder activityToken) {
-            mActivityToken = activityToken;
-            return this;
-        }
-
-        @NonNull
-        LaunchActivityItemBuilder setIntent(@Nullable Intent intent) {
-            mIntent = intent;
-            return this;
+        LaunchActivityItemBuilder(@NonNull IBinder activityToken, @NonNull Intent intent,
+                @NonNull ActivityInfo info) {
+            mActivityToken = requireNonNull(activityToken);
+            mIntent = requireNonNull(intent);
+            mInfo = requireNonNull(info);
         }
 
         @NonNull
@@ -149,20 +147,14 @@
         }
 
         @NonNull
-        LaunchActivityItemBuilder setInfo(@Nullable ActivityInfo info) {
-            mInfo = info;
+        LaunchActivityItemBuilder setCurConfig(@NonNull Configuration curConfig) {
+            mCurConfig.setTo(curConfig);
             return this;
         }
 
         @NonNull
-        LaunchActivityItemBuilder setCurConfig(@Nullable Configuration curConfig) {
-            mCurConfig = curConfig;
-            return this;
-        }
-
-        @NonNull
-        LaunchActivityItemBuilder setOverrideConfig(@Nullable Configuration overrideConfig) {
-            mOverrideConfig = overrideConfig;
+        LaunchActivityItemBuilder setOverrideConfig(@NonNull Configuration overrideConfig) {
+            mOverrideConfig.setTo(overrideConfig);
             return this;
         }
 
diff --git a/core/tests/coretests/src/android/app/servertransaction/TransactionExecutorTests.java b/core/tests/coretests/src/android/app/servertransaction/TransactionExecutorTests.java
index f2b0f2e..443dcb4 100644
--- a/core/tests/coretests/src/android/app/servertransaction/TransactionExecutorTests.java
+++ b/core/tests/coretests/src/android/app/servertransaction/TransactionExecutorTests.java
@@ -44,6 +44,8 @@
 import android.app.ClientTransactionHandler;
 import android.app.servertransaction.ActivityLifecycleItem.LifecycleState;
 import android.app.servertransaction.TestUtils.LaunchActivityItemBuilder;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
 import android.os.IBinder;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -290,7 +292,7 @@
         // A previous queued launch transaction runs on main thread (execute).
         final ClientTransaction launchTransaction = ClientTransaction.obtain(null /* client */);
         final LaunchActivityItem launchItem =
-                spy(new LaunchActivityItemBuilder().setActivityToken(token).build());
+                spy(new LaunchActivityItemBuilder(token, new Intent(), new ActivityInfo()).build());
         launchTransaction.addCallback(launchItem);
         mExecutor.execute(launchTransaction);
 
@@ -322,7 +324,7 @@
         // A previous queued launch transaction runs on main thread (execute).
         final ClientTransaction launchTransaction = ClientTransaction.obtain(null /* client */);
         final LaunchActivityItem launchItem =
-                spy(new LaunchActivityItemBuilder().setActivityToken(token).build());
+                spy(new LaunchActivityItemBuilder(token, new Intent(), new ActivityInfo()).build());
         launchTransaction.addTransactionItem(launchItem);
         mExecutor.execute(launchTransaction);
 
diff --git a/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java b/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java
index 4aa62c5..07921bf 100644
--- a/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java
+++ b/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java
@@ -173,11 +173,9 @@
         final PersistableBundle persistableBundle = new PersistableBundle();
         persistableBundle.putInt("k", 4);
 
-        final LaunchActivityItem item = new LaunchActivityItemBuilder()
-                .setActivityToken(activityToken)
-                .setIntent(intent)
+        final LaunchActivityItem item = new LaunchActivityItemBuilder(
+                activityToken, intent, activityInfo)
                 .setIdent(ident)
-                .setInfo(activityInfo)
                 .setCurConfig(config())
                 .setOverrideConfig(overrideConfig)
                 .setReferrer(referrer)
diff --git a/core/tests/coretests/src/android/app/servertransaction/WindowStateResizeItemTest.java b/core/tests/coretests/src/android/app/servertransaction/WindowStateResizeItemTest.java
index c00eb91..4d45daf 100644
--- a/core/tests/coretests/src/android/app/servertransaction/WindowStateResizeItemTest.java
+++ b/core/tests/coretests/src/android/app/servertransaction/WindowStateResizeItemTest.java
@@ -52,16 +52,18 @@
     private PendingTransactionActions mPendingActions;
     @Mock
     private IWindow mWindow;
-    @Mock
-    private ClientWindowFrames mFrames;
-    @Mock
-    private MergedConfiguration mConfiguration;
-    @Mock
+
     private InsetsState mInsetsState;
+    private ClientWindowFrames mFrames;
+    private MergedConfiguration mConfiguration;
 
     @Before
     public void setup() {
         MockitoAnnotations.initMocks(this);
+
+        mInsetsState = new InsetsState();
+        mFrames = new ClientWindowFrames();
+        mConfiguration = new MergedConfiguration();
     }
 
     @Test
diff --git a/services/core/java/com/android/server/wm/ActivityClientController.java b/services/core/java/com/android/server/wm/ActivityClientController.java
index 26f0d34..7b399c8 100644
--- a/services/core/java/com/android/server/wm/ActivityClientController.java
+++ b/services/core/java/com/android/server/wm/ActivityClientController.java
@@ -1018,9 +1018,8 @@
         }
 
         try {
-            final ClientTransaction transaction = ClientTransaction.obtain(r.app.getThread());
-            transaction.addCallback(EnterPipRequestedItem.obtain(r.token));
-            mService.getLifecycleManager().scheduleTransaction(transaction);
+            mService.getLifecycleManager().scheduleTransaction(r.app.getThread(),
+                    EnterPipRequestedItem.obtain(r.token));
             return true;
         } catch (Exception e) {
             Slog.w(TAG, "Failed to send enter pip requested item: "
diff --git a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
index 777b5cd..e196d46 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
@@ -936,7 +936,7 @@
 
                 final int deviceId = getDeviceIdForDisplayId(r.getDisplayId());
                 clientTransaction.addCallback(LaunchActivityItem.obtain(r.token,
-                        new Intent(r.intent), System.identityHashCode(r), r.info,
+                        r.intent, System.identityHashCode(r), r.info,
                         // TODO: Have this take the merged configuration instead of separate global
                         // and override configs.
                         mergedConfiguration.getGlobalConfiguration(),
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 0c996e0..1776ba5 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -195,6 +195,8 @@
         setBooted(mAtm);
         // Because the booted state is set, avoid starting real home if there is no task.
         doReturn(false).when(mRootWindowContainer).resumeHomeActivity(any(), anyString(), any());
+        // Do not execute the transaction, because we can't verify the parameter after it recycles.
+        doNothing().when(mClientLifecycleManager).scheduleTransaction(any());
     }
 
     private TestStartingWindowOrganizer registerTestStartingWindowOrganizer() {
@@ -262,7 +264,7 @@
                 pauseFound.value = true;
             }
             return null;
-        }).when(activity.app.getThread()).scheduleTransaction(any());
+        }).when(mClientLifecycleManager).scheduleTransaction(any());
 
         activity.setState(STOPPED, "testPausingWhenVisibleFromStopped");
 
@@ -477,7 +479,7 @@
                 .build();
         final Task task = activity.getTask();
         activity.setState(DESTROYED, "Testing");
-        clearInvocations(mAtm.getLifecycleManager());
+        clearInvocations(mClientLifecycleManager);
 
         final Configuration newConfig = new Configuration(task.getConfiguration());
         newConfig.orientation = newConfig.orientation == ORIENTATION_PORTRAIT
@@ -487,7 +489,7 @@
 
         ensureActivityConfiguration(activity);
 
-        verify(mAtm.getLifecycleManager(), never())
+        verify(mClientLifecycleManager, never())
                 .scheduleTransaction(any(), isA(ActivityConfigurationChangeItem.class));
     }
 
@@ -500,7 +502,7 @@
         // test properly.
         activity.finishRelaunching();
         // Clear out any calls to scheduleTransaction from launching the activity.
-        reset(mAtm.getLifecycleManager());
+        reset(mClientLifecycleManager);
 
         final Task task = activity.getTask();
         activity.setState(RESUMED, "Testing");
@@ -517,7 +519,7 @@
         // The configuration change is still sent to the activity, even if it doesn't relaunch.
         final ActivityConfigurationChangeItem expected =
                 ActivityConfigurationChangeItem.obtain(activity.token, newConfig);
-        verify(mAtm.getLifecycleManager()).scheduleTransaction(
+        verify(mClientLifecycleManager).scheduleTransaction(
                 eq(activity.app.getThread()), eq(expected));
     }
 
@@ -558,19 +560,7 @@
         activity.setLastReportedConfiguration(new MergedConfiguration(new Configuration(),
                 activity.getConfiguration()));
 
-        clearInvocations(mAtm.getLifecycleManager());
-        final Configuration newConfig = new Configuration(activity.getConfiguration());
-        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;
-        }
+        clearInvocations(mClientLifecycleManager);
 
         // Mimic the behavior that display doesn't handle app's requested orientation.
         final DisplayContent dc = activity.getTask().getDisplayContent();
@@ -578,12 +568,15 @@
         doReturn(false).when(dc).handlesOrientationChangeFromDescendant(anyInt());
 
         final int requestedOrientation;
-        switch (newConfig.orientation) {
-            case ORIENTATION_LANDSCAPE:
-                requestedOrientation = SCREEN_ORIENTATION_LANDSCAPE;
-                break;
+        final int expectedOrientation;
+        switch (activity.getConfiguration().orientation) {
             case ORIENTATION_PORTRAIT:
+                requestedOrientation = SCREEN_ORIENTATION_LANDSCAPE;
+                expectedOrientation = ORIENTATION_LANDSCAPE;
+                break;
+            case ORIENTATION_LANDSCAPE:
                 requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
+                expectedOrientation = ORIENTATION_PORTRAIT;
                 break;
             default:
                 throw new IllegalStateException("Orientation in new config should be either"
@@ -595,11 +588,11 @@
 
         activity.setRequestedOrientation(requestedOrientation);
 
+        final Configuration currentConfig = activity.getConfiguration();
+        assertEquals(expectedOrientation, currentConfig.orientation);
         final ActivityConfigurationChangeItem expected =
-                ActivityConfigurationChangeItem.obtain(activity.token, newConfig);
-        verify(mAtm.getLifecycleManager()).scheduleTransaction(eq(activity.app.getThread()),
-                eq(expected));
-
+                ActivityConfigurationChangeItem.obtain(activity.token, currentConfig);
+        verify(mClientLifecycleManager).scheduleTransaction(activity.app.getThread(), expected);
         verify(displayRotation).onSetRequestedOrientation();
     }
 
@@ -788,7 +781,7 @@
 
         final Task stack = new TaskBuilder(mSupervisor).setCreateActivity(true).build();
         try {
-            clearInvocations(mAtm.getLifecycleManager());
+            clearInvocations(mClientLifecycleManager);
             doReturn(false).when(stack).isTranslucent(any());
             assertTrue(task.shouldBeVisible(null /* starting */));
 
@@ -796,7 +789,10 @@
                     activity.getConfiguration()));
 
             final Configuration newConfig = new Configuration(activity.getConfiguration());
-            final int shortSide = Math.min(newConfig.screenWidthDp, newConfig.screenHeightDp);
+            final int shortSide = newConfig.screenWidthDp == newConfig.screenHeightDp
+                    // To avoid the case where it is always portrait because of width == height.
+                    ? newConfig.screenWidthDp - 1
+                    : Math.min(newConfig.screenWidthDp, newConfig.screenHeightDp);
             final int longSide = Math.max(newConfig.screenWidthDp, newConfig.screenHeightDp);
             if (newConfig.orientation == ORIENTATION_PORTRAIT) {
                 newConfig.orientation = ORIENTATION_LANDSCAPE;
@@ -811,12 +807,12 @@
             task.onConfigurationChanged(newConfig);
 
             activity.ensureActivityConfiguration(0 /* globalChanges */,
-                    false /* preserveWindow */, true /* ignoreStopState */);
+                    false /* preserveWindow */, true /* ignoreVisibility */);
 
             final ActivityConfigurationChangeItem expected =
-                    ActivityConfigurationChangeItem.obtain(activity.token, newConfig);
-            verify(mAtm.getLifecycleManager()).scheduleTransaction(
-                    eq(activity.app.getThread()), eq(expected));
+                    ActivityConfigurationChangeItem.obtain(activity.token,
+                            activity.getConfiguration());
+            verify(mClientLifecycleManager).scheduleTransaction(activity.app.getThread(), expected);
         } finally {
             stack.getDisplayArea().removeChild(stack);
         }
@@ -1259,12 +1255,12 @@
         targetActivity.resultTo = sourceActivity;
         targetActivity.setForceSendResultForMediaProjection();
 
-        clearInvocations(mAtm.getLifecycleManager());
+        clearInvocations(mClientLifecycleManager);
 
         targetActivity.finishIfPossible(0, new Intent(), null, "test", false /* oomAdj */);
 
         try {
-            verify(mAtm.getLifecycleManager(), atLeastOnce()).scheduleTransaction(
+            verify(mClientLifecycleManager, atLeastOnce()).scheduleTransaction(
                     any(ClientTransaction.class));
         } catch (RemoteException ignored) {
         }
@@ -1283,7 +1279,7 @@
         targetActivity.setState(RESUMED, "test");
         targetActivity.resultTo = resultToActivity;
 
-        clearInvocations(mAtm.getLifecycleManager());
+        clearInvocations(mClientLifecycleManager);
         targetActivity.finishIfPossible(0, new Intent(), null, "test", false /* oomAdj */);
         waitUntilHandlersIdle();
 
@@ -1786,10 +1782,10 @@
             final ActivityRecord activity = createActivityWithTask();
             final WindowProcessController wpc = activity.app;
             setup.accept(activity);
-            clearInvocations(mAtm.getLifecycleManager());
+            clearInvocations(mClientLifecycleManager);
             activity.getTask().removeImmediately("test");
             try {
-                verify(mAtm.getLifecycleManager()).scheduleTransaction(any(),
+                verify(mClientLifecycleManager).scheduleTransaction(any(),
                         isA(DestroyActivityItem.class));
             } catch (RemoteException ignored) {
             }
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 e7ebd7db..3c027ff 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
@@ -39,9 +39,10 @@
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.Mockito.atLeast;
+import static org.mockito.Mockito.clearInvocations;
 import static org.mockito.Mockito.doCallRealMethod;
 import static org.mockito.Mockito.never;
 
@@ -51,7 +52,7 @@
 import android.app.ActivityManager;
 import android.app.IApplicationThread;
 import android.app.PictureInPictureParams;
-import android.app.servertransaction.ClientTransaction;
+import android.app.servertransaction.ClientTransactionItem;
 import android.app.servertransaction.EnterPipRequestedItem;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
@@ -90,9 +91,6 @@
 @RunWith(WindowTestRunner.class)
 public class ActivityTaskManagerServiceTests extends WindowTestsBase {
 
-    private final ArgumentCaptor<ClientTransaction> mClientTransactionCaptor =
-            ArgumentCaptor.forClass(ClientTransaction.class);
-
     private static final String DEFAULT_PACKAGE_NAME = "my.application.package";
     private static final int DEFAULT_USER_ID = 100;
 
@@ -123,53 +121,42 @@
         final ClientLifecycleManager mockLifecycleManager = mock(ClientLifecycleManager.class);
         doReturn(mockLifecycleManager).when(mAtm).getLifecycleManager();
         doReturn(true).when(activity).checkEnterPictureInPictureState(anyString(), anyBoolean());
+        clearInvocations(mClientLifecycleManager);
 
         mAtm.mActivityClientController.requestPictureInPictureMode(activity);
 
-        verify(mockLifecycleManager).scheduleTransaction(mClientTransactionCaptor.capture());
-        final ClientTransaction transaction = mClientTransactionCaptor.getValue();
+        final ArgumentCaptor<ClientTransactionItem> clientTransactionItemCaptor =
+                ArgumentCaptor.forClass(ClientTransactionItem.class);
+        verify(mockLifecycleManager).scheduleTransaction(any(),
+                clientTransactionItemCaptor.capture());
+        final ClientTransactionItem transactionItem = clientTransactionItemCaptor.getValue();
         // Check that only an enter pip request item callback was scheduled.
-        assertEquals(1, transaction.getCallbacks().size());
-        assertTrue(transaction.getCallbacks().get(0) instanceof EnterPipRequestedItem);
-        // Check the activity lifecycle state remains unchanged.
-        assertNull(transaction.getLifecycleStateRequest());
+        assertTrue(transactionItem instanceof EnterPipRequestedItem);
     }
 
     @Test
     public void testOnPictureInPictureRequested_cannotEnterPip() throws RemoteException {
         final Task stack = new TaskBuilder(mSupervisor).setCreateActivity(true).build();
         final ActivityRecord activity = stack.getBottomMostTask().getTopNonFinishingActivity();
-        ClientLifecycleManager lifecycleManager = mAtm.getLifecycleManager();
         doReturn(false).when(activity).inPinnedWindowingMode();
         doReturn(false).when(activity).checkEnterPictureInPictureState(anyString(), anyBoolean());
+        clearInvocations(mClientLifecycleManager);
 
         mAtm.mActivityClientController.requestPictureInPictureMode(activity);
 
-        verify(lifecycleManager, atLeast(0))
-                .scheduleTransaction(mClientTransactionCaptor.capture());
-        final ClientTransaction transaction = mClientTransactionCaptor.getValue();
-        // Check that none are enter pip request items.
-        transaction.getCallbacks().forEach(clientTransactionItem -> {
-            assertFalse(clientTransactionItem instanceof EnterPipRequestedItem);
-        });
+        verify(mClientLifecycleManager, never()).scheduleTransaction(any(), any());
     }
 
     @Test
     public void testOnPictureInPictureRequested_alreadyInPIPMode() throws RemoteException {
         final Task stack = new TaskBuilder(mSupervisor).setCreateActivity(true).build();
         final ActivityRecord activity = stack.getBottomMostTask().getTopNonFinishingActivity();
-        ClientLifecycleManager lifecycleManager = mAtm.getLifecycleManager();
         doReturn(true).when(activity).inPinnedWindowingMode();
+        clearInvocations(mClientLifecycleManager);
 
         mAtm.mActivityClientController.requestPictureInPictureMode(activity);
 
-        verify(lifecycleManager, atLeast(0))
-                .scheduleTransaction(mClientTransactionCaptor.capture());
-        final ClientTransaction transaction = mClientTransactionCaptor.getValue();
-        // Check that none are enter pip request items.
-        transaction.getCallbacks().forEach(clientTransactionItem -> {
-            assertFalse(clientTransactionItem instanceof EnterPipRequestedItem);
-        });
+        verify(mClientLifecycleManager, never()).scheduleTransaction(any(), any());
     }
 
     @Test
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 491d5b5..8de45b0 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java
@@ -202,8 +202,7 @@
                 any() /* starting */, anyInt() /* configChanges */,
                 anyBoolean() /* preserveWindows */, anyBoolean() /* notifyClients */);
         doReturn(app).when(mAtm).getProcessController(eq(recentActivity.processName), anyInt());
-        ClientLifecycleManager lifecycleManager = mAtm.getLifecycleManager();
-        doNothing().when(lifecycleManager).scheduleTransaction(any());
+        doNothing().when(mClientLifecycleManager).scheduleTransaction(any());
 
         startRecentsActivity();
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java
index b89182d..46cff8b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java
@@ -306,29 +306,28 @@
 
     @Test
     public void testCachedStateConfigurationChange() throws RemoteException {
-        final ClientLifecycleManager clientManager = mAtm.getLifecycleManager();
-        doNothing().when(clientManager).scheduleTransaction(any(), any());
+        doNothing().when(mClientLifecycleManager).scheduleTransaction(any(), any());
         final IApplicationThread thread = mWpc.getThread();
         final Configuration newConfig = new Configuration(mWpc.getConfiguration());
         newConfig.densityDpi += 100;
         // Non-cached state will send the change directly.
         mWpc.setReportedProcState(ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND);
-        clearInvocations(clientManager);
+        clearInvocations(mClientLifecycleManager);
         mWpc.onConfigurationChanged(newConfig);
-        verify(clientManager).scheduleTransaction(eq(thread), any());
+        verify(mClientLifecycleManager).scheduleTransaction(eq(thread), any());
 
         // Cached state won't send the change.
-        clearInvocations(clientManager);
+        clearInvocations(mClientLifecycleManager);
         mWpc.setReportedProcState(ActivityManager.PROCESS_STATE_CACHED_ACTIVITY);
         newConfig.densityDpi += 100;
         mWpc.onConfigurationChanged(newConfig);
-        verify(clientManager, never()).scheduleTransaction(eq(thread), any());
+        verify(mClientLifecycleManager, never()).scheduleTransaction(eq(thread), any());
 
         // Cached -> non-cached will send the previous deferred config immediately.
         mWpc.setReportedProcState(ActivityManager.PROCESS_STATE_RECEIVER);
         final ArgumentCaptor<ConfigurationChangeItem> captor =
                 ArgumentCaptor.forClass(ConfigurationChangeItem.class);
-        verify(clientManager).scheduleTransaction(eq(thread), captor.capture());
+        verify(mClientLifecycleManager).scheduleTransaction(eq(thread), captor.capture());
         final ClientTransactionHandler client = mock(ClientTransactionHandler.class);
         captor.getValue().preExecute(client);
         final ArgumentCaptor<Configuration> configCaptor =
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 e0ed642..df4af11 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
@@ -152,6 +152,7 @@
     ActivityTaskManagerService mAtm;
     RootWindowContainer mRootWindowContainer;
     ActivityTaskSupervisor mSupervisor;
+    ClientLifecycleManager mClientLifecycleManager;
     WindowManagerService mWm;
     private final IWindow mIWindow = new TestIWindow();
     private Session mTestSession;
@@ -215,6 +216,7 @@
         mAtm = mSystemServicesTestRule.getActivityTaskManagerService();
         mSupervisor = mAtm.mTaskSupervisor;
         mRootWindowContainer = mAtm.mRootWindowContainer;
+        mClientLifecycleManager = mAtm.getLifecycleManager();
         mWm = mSystemServicesTestRule.getWindowManagerService();
         mOriginalPerDisplayFocusEnabled = mWm.mPerDisplayFocusEnabled;
         SystemServicesTestRule.checkHoldsLock(mWm.mGlobalLock);