Eliminate usage of global transaction for display configuration.

For seamless rotation to work in the brave new world we need the setting
of the display projection to occur in the same transaction as the
reconfiguration of the stack SurfaceControl. To understand this simply see
that the inverse rotation for seamless rotation happens at the
WindowStateAnimator level so if the stack bounds weren't updated to the new
rotation we would clip. This means: We need to use the pending transaction.
We also need to port the rotation animation to use the pending transaction
as it needs to perform transactions at the same time as setting the display
projection. A pleasant consequence is we can eliminate some "inTransaction"
code-paths that always seemed to be a bit of a wart.

Bug: 72038766
Test: Manual. go/wm-smoke.
Change-Id: I949fbe8150d452c1ef5c13e704ddf87269f824f3
diff --git a/services/core/java/com/android/server/display/DisplayDevice.java b/services/core/java/com/android/server/display/DisplayDevice.java
index 3a8e291..2405925 100644
--- a/services/core/java/com/android/server/display/DisplayDevice.java
+++ b/services/core/java/com/android/server/display/DisplayDevice.java
@@ -45,7 +45,7 @@
     private Rect mCurrentDisplayRect;
 
     // The display device owns its surface, but it should only set it
-    // within a transaction from performTraversalInTransactionLocked.
+    // within a transaction from performTraversalLocked.
     private Surface mCurrentSurface;
 
     // DEBUG STATE: Last device info which was written to the log, or null if none.
@@ -122,7 +122,7 @@
     /**
      * Gives the display device a chance to update its properties while in a transaction.
      */
-    public void performTraversalInTransactionLocked() {
+    public void performTraversalLocked(SurfaceControl.Transaction t) {
     }
 
     /**
@@ -140,7 +140,7 @@
     /**
      * Sets the mode, if supported.
      */
-    public void requestDisplayModesInTransactionLocked(int colorMode, int modeId) {
+    public void requestDisplayModesLocked(int colorMode, int modeId) {
     }
 
     public void onOverlayChangedLocked() {
@@ -149,10 +149,10 @@
     /**
      * Sets the display layer stack while in a transaction.
      */
-    public final void setLayerStackInTransactionLocked(int layerStack) {
+    public final void setLayerStackLocked(SurfaceControl.Transaction t, int layerStack) {
         if (mCurrentLayerStack != layerStack) {
             mCurrentLayerStack = layerStack;
-            SurfaceControl.setDisplayLayerStack(mDisplayToken, layerStack);
+            t.setDisplayLayerStack(mDisplayToken, layerStack);
         }
     }
 
@@ -166,7 +166,7 @@
      *            mapped to. displayRect is specified post-orientation, that is
      *            it uses the orientation seen by the end-user
      */
-    public final void setProjectionInTransactionLocked(int orientation,
+    public final void setProjectionLocked(SurfaceControl.Transaction t, int orientation,
             Rect layerStackRect, Rect displayRect) {
         if (mCurrentOrientation != orientation
                 || mCurrentLayerStackRect == null
@@ -185,7 +185,7 @@
             }
             mCurrentDisplayRect.set(displayRect);
 
-            SurfaceControl.setDisplayProjection(mDisplayToken,
+            t.setDisplayProjection(mDisplayToken,
                     orientation, layerStackRect, displayRect);
         }
     }
@@ -193,10 +193,10 @@
     /**
      * Sets the display surface while in a transaction.
      */
-    public final void setSurfaceInTransactionLocked(Surface surface) {
+    public final void setSurfaceLocked(SurfaceControl.Transaction t, Surface surface) {
         if (mCurrentSurface != surface) {
             mCurrentSurface = surface;
-            SurfaceControl.setDisplaySurface(mDisplayToken, surface);
+            t.setDisplaySurface(mDisplayToken, surface);
         }
     }
 
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index a5c1fe2..9861ea7 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -74,6 +74,7 @@
 import android.view.Display;
 import android.view.DisplayInfo;
 import android.view.Surface;
+import android.view.SurfaceControl;
 
 import com.android.internal.util.Preconditions;
 import com.android.server.AnimationThread;
@@ -457,14 +458,14 @@
     }
 
     @VisibleForTesting
-    void performTraversalInTransactionFromWindowManagerInternal() {
+    void performTraversalInternal(SurfaceControl.Transaction t) {
         synchronized (mSyncRoot) {
             if (!mPendingTraversal) {
                 return;
             }
             mPendingTraversal = false;
 
-            performTraversalInTransactionLocked();
+            performTraversalLocked(t);
         }
 
         // List is self-synchronized copy-on-write.
@@ -1056,7 +1057,7 @@
         return changed;
     }
 
-    private void performTraversalInTransactionLocked() {
+    private void performTraversalLocked(SurfaceControl.Transaction t) {
         // Clear all viewports before configuring displays so that we can keep
         // track of which ones we have configured.
         clearViewportsLocked();
@@ -1065,8 +1066,8 @@
         final int count = mDisplayDevices.size();
         for (int i = 0; i < count; i++) {
             DisplayDevice device = mDisplayDevices.get(i);
-            configureDisplayInTransactionLocked(device);
-            device.performTraversalInTransactionLocked();
+            configureDisplayLocked(t, device);
+            device.performTraversalLocked(t);
         }
 
         // Tell the input system about these new viewports.
@@ -1150,7 +1151,7 @@
         mVirtualTouchViewports.clear();
     }
 
-    private void configureDisplayInTransactionLocked(DisplayDevice device) {
+    private void configureDisplayLocked(SurfaceControl.Transaction t, DisplayDevice device) {
         final DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
         final boolean ownContent = (info.flags & DisplayDeviceInfo.FLAG_OWN_CONTENT_ONLY) != 0;
 
@@ -1175,7 +1176,7 @@
                     + device.getDisplayDeviceInfoLocked());
             return;
         }
-        display.configureDisplayInTransactionLocked(device, info.state == Display.STATE_OFF);
+        display.configureDisplayLocked(t, device, info.state == Display.STATE_OFF);
 
         // Update the viewports if needed.
         if (!mDefaultViewport.valid
@@ -1233,7 +1234,7 @@
         mHandler.sendMessage(msg);
     }
 
-    // Requests that performTraversalsInTransactionFromWindowManager be called at a
+    // Requests that performTraversals be called at a
     // later time to apply changes to surfaces and displays.
     private void scheduleTraversalLocked(boolean inTraversal) {
         if (!mPendingTraversal && mWindowManagerInternal != null) {
@@ -2031,8 +2032,8 @@
         }
 
         @Override
-        public void performTraversalInTransactionFromWindowManager() {
-            performTraversalInTransactionFromWindowManagerInternal();
+        public void performTraversal(SurfaceControl.Transaction t) {
+            performTraversalInternal(t);
         }
 
         @Override
diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
index 0d8ec6d..5ca9abc 100644
--- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
@@ -584,10 +584,9 @@
         }
 
         @Override
-        public void requestDisplayModesInTransactionLocked(
-                int colorMode, int modeId) {
-            if (requestModeInTransactionLocked(modeId) ||
-                    requestColorModeInTransactionLocked(colorMode)) {
+        public void requestDisplayModesLocked(int colorMode, int modeId) {
+            if (requestModeLocked(modeId) ||
+                    requestColorModeLocked(colorMode)) {
                 updateDeviceInfoLocked();
             }
         }
@@ -597,7 +596,7 @@
             updateDeviceInfoLocked();
         }
 
-        public boolean requestModeInTransactionLocked(int modeId) {
+        public boolean requestModeLocked(int modeId) {
             if (modeId == 0) {
                 modeId = mDefaultModeId;
             } else if (mSupportedModes.indexOfKey(modeId) < 0) {
@@ -623,7 +622,7 @@
             return true;
         }
 
-        public boolean requestColorModeInTransactionLocked(int colorMode) {
+        public boolean requestColorModeLocked(int colorMode) {
             if (mActiveColorMode == colorMode) {
                 return false;
             }
diff --git a/services/core/java/com/android/server/display/LogicalDisplay.java b/services/core/java/com/android/server/display/LogicalDisplay.java
index e582fdf..23ee56b 100644
--- a/services/core/java/com/android/server/display/LogicalDisplay.java
+++ b/services/core/java/com/android/server/display/LogicalDisplay.java
@@ -21,6 +21,7 @@
 import android.view.Display;
 import android.view.DisplayInfo;
 import android.view.Surface;
+import android.view.SurfaceControl;
 
 import java.io.PrintWriter;
 import java.util.Arrays;
@@ -304,17 +305,18 @@
      * @param device The display device to modify.
      * @param isBlanked True if the device is being blanked.
      */
-    public void configureDisplayInTransactionLocked(DisplayDevice device,
+    public void configureDisplayLocked(SurfaceControl.Transaction t,
+            DisplayDevice device,
             boolean isBlanked) {
         // Set the layer stack.
-        device.setLayerStackInTransactionLocked(isBlanked ? BLANK_LAYER_STACK : mLayerStack);
+        device.setLayerStackLocked(t, isBlanked ? BLANK_LAYER_STACK : mLayerStack);
 
         // Set the color mode and mode.
         if (device == mPrimaryDisplayDevice) {
-            device.requestDisplayModesInTransactionLocked(
+            device.requestDisplayModesLocked(
                     mRequestedColorMode, mRequestedModeId);
         } else {
-            device.requestDisplayModesInTransactionLocked(0, 0);  // Revert to default.
+            device.requestDisplayModesLocked(0, 0);  // Revert to default.
         }
 
         // Only grab the display info now as it may have been changed based on the requests above.
@@ -377,7 +379,7 @@
         mTempDisplayRect.right += mDisplayOffsetX;
         mTempDisplayRect.top += mDisplayOffsetY;
         mTempDisplayRect.bottom += mDisplayOffsetY;
-        device.setProjectionInTransactionLocked(orientation, mTempLayerStackRect, mTempDisplayRect);
+        device.setProjectionLocked(t, orientation, mTempLayerStackRect, mTempDisplayRect);
     }
 
     /**
diff --git a/services/core/java/com/android/server/display/OverlayDisplayAdapter.java b/services/core/java/com/android/server/display/OverlayDisplayAdapter.java
index 27327d4..e65637f 100644
--- a/services/core/java/com/android/server/display/OverlayDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/OverlayDisplayAdapter.java
@@ -271,12 +271,12 @@
         }
 
         @Override
-        public void performTraversalInTransactionLocked() {
+        public void performTraversalLocked(SurfaceControl.Transaction t) {
             if (mSurfaceTexture != null) {
                 if (mSurface == null) {
                     mSurface = new Surface(mSurfaceTexture);
                 }
-                setSurfaceInTransactionLocked(mSurface);
+                setSurfaceLocked(t, mSurface);
             }
         }
 
@@ -315,7 +315,7 @@
         }
 
         @Override
-        public void requestDisplayModesInTransactionLocked(int color, int id) {
+        public void requestDisplayModesLocked(int color, int id) {
             int index = -1;
             if (id == 0) {
                 // Use the default.
diff --git a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
index f86d576..6111c23 100644
--- a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
@@ -269,12 +269,12 @@
         }
 
         @Override
-        public void performTraversalInTransactionLocked() {
+        public void performTraversalLocked(SurfaceControl.Transaction t) {
             if ((mPendingChanges & PENDING_RESIZE) != 0) {
-                SurfaceControl.setDisplaySize(getDisplayTokenLocked(), mWidth, mHeight);
+                t.setDisplaySize(getDisplayTokenLocked(), mWidth, mHeight);
             }
             if ((mPendingChanges & PENDING_SURFACE_CHANGE) != 0) {
-                setSurfaceInTransactionLocked(mSurface);
+                setSurfaceLocked(t, mSurface);
             }
             mPendingChanges = 0;
         }
diff --git a/services/core/java/com/android/server/display/WifiDisplayAdapter.java b/services/core/java/com/android/server/display/WifiDisplayAdapter.java
index 3293379..e8d6ad4 100644
--- a/services/core/java/com/android/server/display/WifiDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/WifiDisplayAdapter.java
@@ -620,9 +620,9 @@
         }
 
         @Override
-        public void performTraversalInTransactionLocked() {
+        public void performTraversalLocked(SurfaceControl.Transaction t) {
             if (mSurface != null) {
-                setSurfaceInTransactionLocked(mSurface);
+                setSurfaceLocked(t, mSurface);
             }
         }
 
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index b2f153a..fef615d 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -1092,7 +1092,7 @@
                 mService.registerAppFreezeListener(this);
                 mService.mAppsFreezingScreen++;
                 if (mService.mAppsFreezingScreen == 1) {
-                    mService.startFreezingDisplayLocked(false, 0, 0, getDisplayContent());
+                    mService.startFreezingDisplayLocked(0, 0, getDisplayContent());
                     mService.mH.removeMessages(H.APP_FREEZE_TIMEOUT);
                     mService.mH.sendEmptyMessageDelayed(H.APP_FREEZE_TIMEOUT, 2000);
                 }
diff --git a/services/core/java/com/android/server/wm/BlackFrame.java b/services/core/java/com/android/server/wm/BlackFrame.java
index f19cd0f..1977e12 100644
--- a/services/core/java/com/android/server/wm/BlackFrame.java
+++ b/services/core/java/com/android/server/wm/BlackFrame.java
@@ -41,7 +41,7 @@
         final int layer;
         final SurfaceControl surface;
 
-        BlackSurface(int layer,
+        BlackSurface(SurfaceControl.Transaction transaction, int layer,
                 int l, int t, int r, int b, DisplayContent dc) throws OutOfResourcesException {
             left = l;
             top = t;
@@ -56,24 +56,24 @@
                     .setParent(null) // TODO: Work-around for b/69259549
                     .build();
 
-            surface.setAlpha(1);
-            surface.setLayer(layer);
-            surface.show();
+            transaction.setAlpha(surface, 1);
+            transaction.setLayer(surface, layer);
+            transaction.show(surface);
             if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) Slog.i(TAG_WM,
                             "  BLACK " + surface + ": CREATE layer=" + layer);
         }
 
-        void setAlpha(float alpha) {
-            surface.setAlpha(alpha);
+        void setAlpha(SurfaceControl.Transaction t, float alpha) {
+            t.setAlpha(surface, alpha);
         }
 
-        void setMatrix(Matrix matrix) {
+        void setMatrix(SurfaceControl.Transaction t, Matrix matrix) {
             mTmpMatrix.setTranslate(left, top);
             mTmpMatrix.postConcat(matrix);
             mTmpMatrix.getValues(mTmpFloats);
-            surface.setPosition(mTmpFloats[Matrix.MTRANS_X],
+            t.setPosition(surface, mTmpFloats[Matrix.MTRANS_X],
                     mTmpFloats[Matrix.MTRANS_Y]);
-            surface.setMatrix(
+            t.setMatrix(surface,
                     mTmpFloats[Matrix.MSCALE_X], mTmpFloats[Matrix.MSKEW_Y],
                     mTmpFloats[Matrix.MSKEW_X], mTmpFloats[Matrix.MSCALE_Y]);
             if (false) {
@@ -87,8 +87,8 @@
             }
         }
 
-        void clearMatrix() {
-            surface.setMatrix(1, 0, 0, 1);
+        void clearMatrix(SurfaceControl.Transaction t) {
+            t.setMatrix(surface, 1, 0, 0, 1);
         }
     }
 
@@ -113,7 +113,8 @@
         }
     }
 
-    public BlackFrame(Rect outer, Rect inner, int layer, DisplayContent dc,
+    public BlackFrame(SurfaceControl.Transaction t,
+            Rect outer, Rect inner, int layer, DisplayContent dc,
             boolean forceDefaultOrientation) throws OutOfResourcesException {
         boolean success = false;
 
@@ -125,19 +126,19 @@
         mInnerRect = new Rect(inner);
         try {
             if (outer.top < inner.top) {
-                mBlackSurfaces[0] = new BlackSurface(layer,
+                mBlackSurfaces[0] = new BlackSurface(t, layer,
                         outer.left, outer.top, inner.right, inner.top, dc);
             }
             if (outer.left < inner.left) {
-                mBlackSurfaces[1] = new BlackSurface(layer,
+                mBlackSurfaces[1] = new BlackSurface(t, layer,
                         outer.left, inner.top, inner.left, outer.bottom, dc);
             }
             if (outer.bottom > inner.bottom) {
-                mBlackSurfaces[2] = new BlackSurface(layer,
+                mBlackSurfaces[2] = new BlackSurface(t, layer,
                         inner.left, inner.bottom, outer.right, outer.bottom, dc);
             }
             if (outer.right > inner.right) {
-                mBlackSurfaces[3] = new BlackSurface(layer,
+                mBlackSurfaces[3] = new BlackSurface(t, layer,
                         inner.right, outer.top, outer.right, inner.bottom, dc);
             }
             success = true;
@@ -161,36 +162,36 @@
         }
     }
 
-    public void hide() {
+    public void hide(SurfaceControl.Transaction t) {
         if (mBlackSurfaces != null) {
             for (int i=0; i<mBlackSurfaces.length; i++) {
                 if (mBlackSurfaces[i] != null) {
-                    mBlackSurfaces[i].surface.hide();
+                    t.hide(mBlackSurfaces[i].surface);
                 }
             }
         }
     }
 
-    public void setAlpha(float alpha) {
+    public void setAlpha(SurfaceControl.Transaction t, float alpha) {
         for (int i=0; i<mBlackSurfaces.length; i++) {
             if (mBlackSurfaces[i] != null) {
-                mBlackSurfaces[i].setAlpha(alpha);
+                mBlackSurfaces[i].setAlpha(t, alpha);
             }
         }
     }
 
-    public void setMatrix(Matrix matrix) {
+    public void setMatrix(SurfaceControl.Transaction t, Matrix matrix) {
         for (int i=0; i<mBlackSurfaces.length; i++) {
             if (mBlackSurfaces[i] != null) {
-                mBlackSurfaces[i].setMatrix(matrix);
+                mBlackSurfaces[i].setMatrix(t, matrix);
             }
         }
     }
 
-    public void clearMatrix() {
+    public void clearMatrix(SurfaceControl.Transaction t) {
         for (int i=0; i<mBlackSurfaces.length; i++) {
             if (mBlackSurfaces[i] != null) {
-                mBlackSurfaces[i].clearMatrix();
+                mBlackSurfaces[i].clearMatrix(t);
             }
         }
     }
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 2dce913..6680680 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -258,7 +258,7 @@
      * Current rotation of the display.
      * Constants as per {@link android.view.Surface.Rotation}.
      *
-     * @see #updateRotationUnchecked(boolean)
+     * @see #updateRotationUnchecked()
      */
     private int mRotation = 0;
 
@@ -274,7 +274,7 @@
      * Flag indicating that the application is receiving an orientation that has different metrics
      * than it expected. E.g. Portrait instead of Landscape.
      *
-     * @see #updateRotationUnchecked(boolean)
+     * @see #updateRotationUnchecked()
      */
     private boolean mAltOrientation = false;
 
@@ -926,7 +926,7 @@
      * Returns true if the rotation has been changed.  In this case YOU MUST CALL
      * {@link WindowManagerService#sendNewConfiguration(int)} TO UNFREEZE THE SCREEN.
      */
-    boolean updateRotationUnchecked(boolean inTransaction) {
+    boolean updateRotationUnchecked() {
         if (mService.mDeferredRotationPauseCount > 0) {
             // Rotation updates have been paused temporarily.  Defer the update until
             // updates have been resumed.
@@ -1030,7 +1030,7 @@
         mService.mPolicy.selectRotationAnimationLw(anim);
 
         if (!rotateSeamlessly) {
-            mService.startFreezingDisplayLocked(inTransaction, anim[0], anim[1], this);
+            mService.startFreezingDisplayLocked(anim[0], anim[1], this);
             // startFreezingDisplayLocked can reset the ScreenRotationAnimation.
             screenRotationAnimation = mService.mAnimator.getScreenRotationAnimationLocked(
                     mDisplayId);
@@ -1053,40 +1053,27 @@
         // #computeScreenConfiguration() later.
         updateDisplayAndOrientation(getConfiguration().uiMode);
 
-        if (!inTransaction) {
-            if (SHOW_TRANSACTIONS) {
-                Slog.i(TAG_WM, ">>> OPEN TRANSACTION setRotationUnchecked");
-            }
-            mService.openSurfaceTransaction();
-        }
-        try {
-            // NOTE: We disable the rotation in the emulator because
-            //       it doesn't support hardware OpenGL emulation yet.
-            if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null
-                    && screenRotationAnimation.hasScreenshot()) {
-                if (screenRotationAnimation.setRotationInTransaction(rotation,
-                        MAX_ANIMATION_DURATION, mService.getTransitionAnimationScaleLocked(),
-                        mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight)) {
-                    mService.scheduleAnimationLocked();
-                }
-            }
-
-            if (rotateSeamlessly) {
-                forAllWindows(w -> {
-                    w.mWinAnimator.seamlesslyRotateWindow(oldRotation, rotation);
-                }, true /* traverseTopToBottom */);
-            }
-
-            mService.mDisplayManagerInternal.performTraversalInTransactionFromWindowManager();
-        } finally {
-            if (!inTransaction) {
-                mService.closeSurfaceTransaction("setRotationUnchecked");
-                if (SHOW_LIGHT_TRANSACTIONS) {
-                    Slog.i(TAG_WM, "<<< CLOSE TRANSACTION setRotationUnchecked");
-                }
+        // NOTE: We disable the rotation in the emulator because
+        //       it doesn't support hardware OpenGL emulation yet.
+        if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null
+                && screenRotationAnimation.hasScreenshot()) {
+            if (screenRotationAnimation.setRotation(getPendingTransaction(), rotation,
+                    MAX_ANIMATION_DURATION, mService.getTransitionAnimationScaleLocked(),
+                    mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight)) {
+                mService.scheduleAnimationLocked();
             }
         }
 
+        if (rotateSeamlessly) {
+            forAllWindows(w -> {
+                    w.mWinAnimator.seamlesslyRotateWindow(getPendingTransaction(),
+                            oldRotation, rotation);
+            }, true /* traverseTopToBottom */);
+        }
+
+        mService.mDisplayManagerInternal.performTraversal(getPendingTransaction());
+        scheduleAnimation();
+
         forAllWindows(w -> {
             if (w.mHasSurface && !rotateSeamlessly) {
                 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Set mOrientationChanging of " + w);
@@ -2808,7 +2795,7 @@
 
             if (isDefaultDisplay && (pendingLayoutChanges & FINISH_LAYOUT_REDO_CONFIG) != 0) {
                 if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout");
-                if (mService.updateOrientationFromAppTokensLocked(true, mDisplayId)) {
+                if (mService.updateOrientationFromAppTokensLocked(mDisplayId)) {
                     setLayoutNeeded();
                     mService.mH.obtainMessage(SEND_NEW_CONFIGURATION, mDisplayId).sendToTarget();
                 }
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index f32c275..32ae523 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -37,6 +37,7 @@
 import android.util.proto.ProtoOutputStream;
 import android.view.Display;
 import android.view.DisplayInfo;
+import android.view.SurfaceControl;
 import android.view.WindowManager;
 
 import com.android.internal.util.ArrayUtils;
@@ -128,6 +129,11 @@
     private final Handler mHandler;
 
     private String mCloseSystemDialogsReason;
+
+    // Only a seperate transaction until we seperate the apply surface changes
+    // transaction from the global transaction.
+    private final SurfaceControl.Transaction mDisplayTransaction = new SurfaceControl.Transaction();
+
     private final Consumer<WindowState> mCloseSystemDialogsConsumer = w -> {
         if (w.mHasSurface) {
             try {
@@ -725,7 +731,7 @@
             if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation");
             // TODO(multi-display): Update rotation for different displays separately.
             final int displayId = defaultDisplay.getDisplayId();
-            if (defaultDisplay.updateRotationUnchecked(false /* inTransaction */)) {
+            if (defaultDisplay.updateRotationUnchecked()) {
                 mService.mH.obtainMessage(SEND_NEW_CONFIGURATION, displayId).sendToTarget();
             } else {
                 mUpdateRotation = false;
@@ -735,7 +741,7 @@
             // PhoneWindowManager.
             final DisplayContent vrDisplay = mService.mVr2dDisplayId != INVALID_DISPLAY
                     ? getDisplayContent(mService.mVr2dDisplayId) : null;
-            if (vrDisplay != null && vrDisplay.updateRotationUnchecked(false /* inTransaction */)) {
+            if (vrDisplay != null && vrDisplay.updateRotationUnchecked()) {
                 mService.mH.obtainMessage(SEND_NEW_CONFIGURATION, mService.mVr2dDisplayId)
                         .sendToTarget();
             }
@@ -835,7 +841,8 @@
 
         // Give the display manager a chance to adjust properties like display rotation if it needs
         // to.
-        mService.mDisplayManagerInternal.performTraversalInTransactionFromWindowManager();
+        mService.mDisplayManagerInternal.performTraversal(mDisplayTransaction);
+        SurfaceControl.mergeToGlobalTransaction(mDisplayTransaction);
     }
 
     /**
diff --git a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
index 5a39de5..ad2fabb 100644
--- a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
+++ b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
@@ -224,8 +224,7 @@
     }
 
     public ScreenRotationAnimation(Context context, DisplayContent displayContent,
-            boolean inTransaction, boolean forceDefaultOrientation,
-            boolean isSecure, WindowManagerService service) {
+            boolean forceDefaultOrientation, boolean isSecure, WindowManagerService service) {
         mService = service;
         mContext = context;
         mDisplayContent = displayContent;
@@ -260,52 +259,39 @@
         mOriginalWidth = originalWidth;
         mOriginalHeight = originalHeight;
 
-        if (!inTransaction) {
-            if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG_WM,
-                    ">>> OPEN TRANSACTION ScreenRotationAnimation");
-            mService.openSurfaceTransaction();
-        }
-
+        final SurfaceControl.Transaction t = new SurfaceControl.Transaction();
         try {
-            try {
-                mSurfaceControl = displayContent.makeOverlay()
-                        .setName("ScreenshotSurface")
-                        .setSize(mWidth, mHeight)
-                        .setSecure(isSecure)
-                        .build();
+            mSurfaceControl = displayContent.makeOverlay()
+                    .setName("ScreenshotSurface")
+                    .setSize(mWidth, mHeight)
+                    .setSecure(isSecure)
+                    .build();
 
-                // capture a screenshot into the surface we just created
-                Surface sur = new Surface();
-                sur.copyFrom(mSurfaceControl);
-                // TODO(multidisplay): we should use the proper display
-                SurfaceControl.screenshot(SurfaceControl.getBuiltInDisplay(
-                        SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN), sur);
-                mSurfaceControl.setLayer(SCREEN_FREEZE_LAYER_SCREENSHOT);
-                mSurfaceControl.setAlpha(0);
-                mSurfaceControl.show();
-                sur.destroy();
-            } catch (OutOfResourcesException e) {
-                Slog.w(TAG, "Unable to allocate freeze surface", e);
-            }
-
-            if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) Slog.i(TAG_WM,
-                    "  FREEZE " + mSurfaceControl + ": CREATE");
-
-            setRotationInTransaction(originalRotation);
-        } finally {
-            if (!inTransaction) {
-                mService.closeSurfaceTransaction("ScreenRotationAnimation");
-                if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG_WM,
-                        "<<< CLOSE TRANSACTION ScreenRotationAnimation");
-            }
+            // capture a screenshot into the surface we just created
+            Surface sur = new Surface();
+            sur.copyFrom(mSurfaceControl);
+            // TODO(multidisplay): we should use the proper display
+            SurfaceControl.screenshot(SurfaceControl.getBuiltInDisplay(
+                            SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN), sur);
+            t.setLayer(mSurfaceControl, SCREEN_FREEZE_LAYER_SCREENSHOT);
+            t.setAlpha(mSurfaceControl, 0);
+            t.show(mSurfaceControl);
+            sur.destroy();
+        } catch (OutOfResourcesException e) {
+            Slog.w(TAG, "Unable to allocate freeze surface", e);
         }
+
+        if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) Slog.i(TAG_WM,
+                "  FREEZE " + mSurfaceControl + ": CREATE");
+        setRotation(t, originalRotation);
+        t.apply();
     }
 
     boolean hasScreenshot() {
         return mSurfaceControl != null;
     }
 
-    private void setSnapshotTransformInTransaction(Matrix matrix, float alpha) {
+    private void setSnapshotTransform(SurfaceControl.Transaction t, Matrix matrix, float alpha) {
         if (mSurfaceControl != null) {
             matrix.getValues(mTmpFloats);
             float x = mTmpFloats[Matrix.MTRANS_X];
@@ -315,11 +301,11 @@
                 x -= mCurrentDisplayRect.left;
                 y -= mCurrentDisplayRect.top;
             }
-            mSurfaceControl.setPosition(x, y);
-            mSurfaceControl.setMatrix(
+            t.setPosition(mSurfaceControl, x, y);
+            t.setMatrix(mSurfaceControl,
                     mTmpFloats[Matrix.MSCALE_X], mTmpFloats[Matrix.MSKEW_Y],
                     mTmpFloats[Matrix.MSKEW_X], mTmpFloats[Matrix.MSCALE_Y]);
-            mSurfaceControl.setAlpha(alpha);
+            t.setAlpha(mSurfaceControl, alpha);
             if (DEBUG_TRANSFORMS) {
                 float[] srcPnts = new float[] { 0, 0, mWidth, mHeight };
                 float[] dstPnts = new float[4];
@@ -353,8 +339,7 @@
         }
     }
 
-    // Must be called while in a transaction.
-    private void setRotationInTransaction(int rotation) {
+    private void setRotation(SurfaceControl.Transaction t, int rotation) {
         mCurRotation = rotation;
 
         // Compute the transformation matrix that must be applied
@@ -364,15 +349,14 @@
         createRotationMatrix(delta, mWidth, mHeight, mSnapshotInitialMatrix);
 
         if (DEBUG_STATE) Slog.v(TAG, "**** ROTATION: " + delta);
-        setSnapshotTransformInTransaction(mSnapshotInitialMatrix, 1.0f);
+        setSnapshotTransform(t, mSnapshotInitialMatrix, 1.0f);
     }
 
-    // Must be called while in a transaction.
-    public boolean setRotationInTransaction(int rotation,
+    public boolean setRotation(SurfaceControl.Transaction t, int rotation,
             long maxAnimationDuration, float animationScale, int finalWidth, int finalHeight) {
-        setRotationInTransaction(rotation);
+        setRotation(t, rotation);
         if (TWO_PHASE_ANIMATION) {
-            return startAnimation(maxAnimationDuration, animationScale,
+            return startAnimation(t, maxAnimationDuration, animationScale,
                     finalWidth, finalHeight, false, 0, 0);
         }
 
@@ -383,7 +367,7 @@
     /**
      * Returns true if animating.
      */
-    private boolean startAnimation(long maxAnimationDuration,
+    private boolean startAnimation(SurfaceControl.Transaction t, long maxAnimationDuration,
             float animationScale, int finalWidth, int finalHeight, boolean dismissing,
             int exitAnim, int enterAnim) {
         if (mSurfaceControl == null) {
@@ -542,11 +526,6 @@
 
         final int layerStack = mDisplayContent.getDisplay().getLayerStack();
         if (USE_CUSTOM_BLACK_FRAME && mCustomBlackFrame == null) {
-            if (SHOW_LIGHT_TRANSACTIONS || DEBUG_STATE) Slog.i(
-                    TAG_WM,
-                    ">>> OPEN TRANSACTION ScreenRotationAnimation.startAnimation");
-            mService.openSurfaceTransaction();
-
             // Compute the transformation matrix that must be applied
             // the the black frame to make it stay in the initial position
             // before the new screen rotation.  This is different than the
@@ -559,24 +538,15 @@
                 Rect outer = new Rect(-mOriginalWidth*1, -mOriginalHeight*1,
                         mOriginalWidth*2, mOriginalHeight*2);
                 Rect inner = new Rect(0, 0, mOriginalWidth, mOriginalHeight);
-                mCustomBlackFrame = new BlackFrame(outer, inner,
+                mCustomBlackFrame = new BlackFrame(t, outer, inner,
                         SCREEN_FREEZE_LAYER_CUSTOM, mDisplayContent, false);
-                mCustomBlackFrame.setMatrix(mFrameInitialMatrix);
+                mCustomBlackFrame.setMatrix(t, mFrameInitialMatrix);
             } catch (OutOfResourcesException e) {
                 Slog.w(TAG, "Unable to allocate black surface", e);
-            } finally {
-                mService.closeSurfaceTransaction("ScreenRotationAnimation.startAnimation");
-                if (SHOW_LIGHT_TRANSACTIONS || DEBUG_STATE) Slog.i(
-                        TAG_WM,
-                        "<<< CLOSE TRANSACTION ScreenRotationAnimation.startAnimation");
             }
         }
 
         if (!customAnim && mExitingBlackFrame == null) {
-            if (SHOW_LIGHT_TRANSACTIONS || DEBUG_STATE) Slog.i(
-                    TAG_WM,
-                    ">>> OPEN TRANSACTION ScreenRotationAnimation.startAnimation");
-            mService.openSurfaceTransaction();
             try {
                 // Compute the transformation matrix that must be applied
                 // the the black frame to make it stay in the initial position
@@ -599,38 +569,23 @@
                             mOriginalWidth*2, mOriginalHeight*2);
                     inner = new Rect(0, 0, mOriginalWidth, mOriginalHeight);
                 }
-                mExitingBlackFrame = new BlackFrame(outer, inner,
+                mExitingBlackFrame = new BlackFrame(t, outer, inner,
                         SCREEN_FREEZE_LAYER_EXIT, mDisplayContent, mForceDefaultOrientation);
-                mExitingBlackFrame.setMatrix(mFrameInitialMatrix);
+                mExitingBlackFrame.setMatrix(t, mFrameInitialMatrix);
             } catch (OutOfResourcesException e) {
                 Slog.w(TAG, "Unable to allocate black surface", e);
-            } finally {
-                mService.closeSurfaceTransaction("ScreenRotationAnimation.startAnimation");
-                if (SHOW_LIGHT_TRANSACTIONS || DEBUG_STATE) Slog.i(
-                        TAG_WM,
-                        "<<< CLOSE TRANSACTION ScreenRotationAnimation.startAnimation");
             }
         }
 
         if (customAnim && mEnteringBlackFrame == null) {
-            if (SHOW_LIGHT_TRANSACTIONS || DEBUG_STATE) Slog.i(
-                    TAG_WM,
-                    ">>> OPEN TRANSACTION ScreenRotationAnimation.startAnimation");
-            mService.openSurfaceTransaction();
-
             try {
                 Rect outer = new Rect(-finalWidth*1, -finalHeight*1,
                         finalWidth*2, finalHeight*2);
                 Rect inner = new Rect(0, 0, finalWidth, finalHeight);
-                mEnteringBlackFrame = new BlackFrame(outer, inner,
+                mEnteringBlackFrame = new BlackFrame(t, outer, inner,
                         SCREEN_FREEZE_LAYER_ENTER, mDisplayContent, false);
             } catch (OutOfResourcesException e) {
                 Slog.w(TAG, "Unable to allocate black surface", e);
-            } finally {
-                mService.closeSurfaceTransaction("ScreenRotationAnimation.startAnimation");
-                if (SHOW_LIGHT_TRANSACTIONS || DEBUG_STATE) Slog.i(
-                        TAG_WM,
-                        "<<< CLOSE TRANSACTION ScreenRotationAnimation.startAnimation");
             }
         }
 
@@ -640,7 +595,7 @@
     /**
      * Returns true if animating.
      */
-    public boolean dismiss(long maxAnimationDuration,
+    public boolean dismiss(SurfaceControl.Transaction t, long maxAnimationDuration,
             float animationScale, int finalWidth, int finalHeight, int exitAnim, int enterAnim) {
         if (DEBUG_STATE) Slog.v(TAG, "Dismiss!");
         if (mSurfaceControl == null) {
@@ -648,7 +603,7 @@
             return false;
         }
         if (!mStarted) {
-            startAnimation(maxAnimationDuration, animationScale, finalWidth, finalHeight,
+            startAnimation(t, maxAnimationDuration, animationScale, finalWidth, finalHeight,
                     true, exitAnim, enterAnim);
         }
         if (!mStarted) {
@@ -919,7 +874,7 @@
         return more;
     }
 
-    void updateSurfacesInTransaction() {
+    void updateSurfaces(SurfaceControl.Transaction t) {
         if (!mStarted) {
             return;
         }
@@ -927,28 +882,28 @@
         if (mSurfaceControl != null) {
             if (!mMoreStartExit && !mMoreFinishExit && !mMoreRotateExit) {
                 if (DEBUG_STATE) Slog.v(TAG, "Exit animations done, hiding screenshot surface");
-                mSurfaceControl.hide();
+                t.hide(mSurfaceControl);
             }
         }
 
         if (mCustomBlackFrame != null) {
             if (!mMoreStartFrame && !mMoreFinishFrame && !mMoreRotateFrame) {
                 if (DEBUG_STATE) Slog.v(TAG, "Frame animations done, hiding black frame");
-                mCustomBlackFrame.hide();
+                mCustomBlackFrame.hide(t);
             } else {
-                mCustomBlackFrame.setMatrix(mFrameTransformation.getMatrix());
+                mCustomBlackFrame.setMatrix(t, mFrameTransformation.getMatrix());
             }
         }
 
         if (mExitingBlackFrame != null) {
             if (!mMoreStartExit && !mMoreFinishExit && !mMoreRotateExit) {
                 if (DEBUG_STATE) Slog.v(TAG, "Frame animations done, hiding exiting frame");
-                mExitingBlackFrame.hide();
+                mExitingBlackFrame.hide(t);
             } else {
                 mExitFrameFinalMatrix.setConcat(mExitTransformation.getMatrix(), mFrameInitialMatrix);
-                mExitingBlackFrame.setMatrix(mExitFrameFinalMatrix);
+                mExitingBlackFrame.setMatrix(t, mExitFrameFinalMatrix);
                 if (mForceDefaultOrientation) {
-                    mExitingBlackFrame.setAlpha(mExitTransformation.getAlpha());
+                    mExitingBlackFrame.setAlpha(t, mExitTransformation.getAlpha());
                 }
             }
         }
@@ -956,13 +911,13 @@
         if (mEnteringBlackFrame != null) {
             if (!mMoreStartEnter && !mMoreFinishEnter && !mMoreRotateEnter) {
                 if (DEBUG_STATE) Slog.v(TAG, "Frame animations done, hiding entering frame");
-                mEnteringBlackFrame.hide();
+                mEnteringBlackFrame.hide(t);
             } else {
-                mEnteringBlackFrame.setMatrix(mEnterTransformation.getMatrix());
+                mEnteringBlackFrame.setMatrix(t, mEnterTransformation.getMatrix());
             }
         }
 
-        setSnapshotTransformInTransaction(mSnapshotFinalMatrix, mExitTransformation.getAlpha());
+        setSnapshotTransform(t, mSnapshotFinalMatrix, mExitTransformation.getAlpha());
     }
 
     public boolean stepAnimationLocked(long now) {
diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java
index ab10197..793ffce 100644
--- a/services/core/java/com/android/server/wm/WindowAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowAnimator.java
@@ -30,6 +30,7 @@
 import android.util.SparseArray;
 import android.util.TimeUtils;
 import android.view.Choreographer;
+import android.view.SurfaceControl;
 
 import com.android.server.AnimationThread;
 import com.android.server.policy.WindowManagerPolicy;
@@ -94,6 +95,8 @@
     private final ArrayList<Runnable> mAfterPrepareSurfacesRunnables = new ArrayList<>();
     private boolean mInExecuteAfterPrepareSurfacesRunnables;
 
+    private final SurfaceControl.Transaction mTransaction = new SurfaceControl.Transaction();
+
     WindowAnimator(final WindowManagerService service) {
         mService = service;
         mContext = service.mContext;
@@ -203,7 +206,7 @@
                     final ScreenRotationAnimation screenRotationAnimation =
                             mDisplayContentsAnimators.valueAt(i).mScreenRotationAnimation;
                     if (screenRotationAnimation != null) {
-                        screenRotationAnimation.updateSurfacesInTransaction();
+                        screenRotationAnimation.updateSurfaces(mTransaction);
                     }
                     orAnimating(dc.getDockedDividerController().animate(mCurrentTime));
                     //TODO (multidisplay): Magnification is supported only for the default display.
@@ -219,6 +222,8 @@
                 if (mService.mWatermark != null) {
                     mService.mWatermark.drawIfNeeded();
                 }
+
+                SurfaceControl.mergeToGlobalTransaction(mTransaction);
             } catch (RuntimeException e) {
                 Slog.wtf(TAG, "Unhandled exception in Window Manager", e);
             } finally {
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 82fbb51..394532b 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -809,6 +809,8 @@
     SurfaceBuilderFactory mSurfaceBuilderFactory = SurfaceControl.Builder::new;
     TransactionFactory mTransactionFactory = SurfaceControl.Transaction::new;
 
+    private final SurfaceControl.Transaction mTransaction = mTransactionFactory.make();
+
     static void boostPriorityForLockedSection() {
         sThreadPriorityBooster.boost();
     }
@@ -1487,7 +1489,7 @@
             if (localLOGV || DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "addWindow: New client "
                     + client.asBinder() + ": window=" + win + " Callers=" + Debug.getCallers(5));
 
-            if (win.isVisibleOrAdding() && updateOrientationFromAppTokensLocked(false, displayId)) {
+            if (win.isVisibleOrAdding() && updateOrientationFromAppTokensLocked(displayId)) {
                 reportNewConfig = true;
             }
         }
@@ -2049,7 +2051,7 @@
 
             Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER,
                     "relayoutWindow: updateOrientationFromAppTokens");
-            configChanged = updateOrientationFromAppTokensLocked(false, displayId);
+            configChanged = updateOrientationFromAppTokensLocked(displayId);
             Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
 
             if (toBeDisplayed && win.mIsWallpaper) {
@@ -2340,7 +2342,7 @@
         }
         Configuration config = null;
 
-        if (updateOrientationFromAppTokensLocked(false, displayId)) {
+        if (updateOrientationFromAppTokensLocked(displayId)) {
             // If we changed the orientation but mOrientationChangeComplete is already true,
             // we used seamless rotation, and we don't need to freeze the screen.
             if (freezeThisOneIfNeeded != null && !mRoot.mOrientationChangeComplete) {
@@ -2367,7 +2369,7 @@
                 int anim[] = new int[2];
                 mPolicy.selectRotationAnimationLw(anim);
 
-                startFreezingDisplayLocked(false, anim[0], anim[1], displayContent);
+                startFreezingDisplayLocked(anim[0], anim[1], displayContent);
                 config = new Configuration(mTempConfiguration);
             }
         }
@@ -2387,7 +2389,7 @@
      * tokens.
      * @see android.view.IWindowManager#updateOrientationFromAppTokens(Configuration, IBinder, int)
      */
-    boolean updateOrientationFromAppTokensLocked(boolean inTransaction, int displayId) {
+    boolean updateOrientationFromAppTokensLocked(int displayId) {
         long ident = Binder.clearCallingIdentity();
         try {
             final DisplayContent dc = mRoot.getDisplayContent(displayId);
@@ -2400,7 +2402,7 @@
                 if (dc.isDefaultDisplay) {
                     mPolicy.setCurrentOrientationLw(req);
                 }
-                if (dc.updateRotationUnchecked(inTransaction)) {
+                if (dc.updateRotationUnchecked()) {
                     // changed
                     return true;
                 }
@@ -2873,7 +2875,7 @@
                 mClientFreezingScreen = true;
                 final long origId = Binder.clearCallingIdentity();
                 try {
-                    startFreezingDisplayLocked(false, exitAnim, enterAnim);
+                    startFreezingDisplayLocked(exitAnim, enterAnim);
                     mH.removeMessages(H.CLIENT_FREEZE_TIMEOUT);
                     mH.sendEmptyMessageDelayed(H.CLIENT_FREEZE_TIMEOUT, 5000);
                 } finally {
@@ -3774,8 +3776,7 @@
             if (mDeferredRotationPauseCount == 0) {
                 // TODO(multi-display): Update rotation for different displays separately.
                 final DisplayContent displayContent = getDefaultDisplayContentLocked();
-                final boolean changed = displayContent.updateRotationUnchecked(
-                        false /* inTransaction */);
+                final boolean changed = displayContent.updateRotationUnchecked();
                 if (changed) {
                     mH.obtainMessage(H.SEND_NEW_CONFIGURATION, displayContent.getDisplayId())
                             .sendToTarget();
@@ -3800,8 +3801,7 @@
             synchronized (mWindowMap) {
                 final DisplayContent displayContent = getDefaultDisplayContentLocked();
                 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "updateRotation: display");
-                rotationChanged = displayContent.updateRotationUnchecked(
-                        false /* inTransaction */);
+                rotationChanged = displayContent.updateRotationUnchecked();
                 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
                 if (!rotationChanged || forceRelayout) {
                     displayContent.setLayoutNeeded();
@@ -5326,8 +5326,7 @@
         displayContent.setLayoutNeeded();
 
         final int displayId = displayContent.getDisplayId();
-        boolean configChanged = updateOrientationFromAppTokensLocked(false /* inTransaction */,
-                displayId);
+        boolean configChanged = updateOrientationFromAppTokensLocked(displayId);
         final Configuration currentDisplayConfig = displayContent.getConfiguration();
         mTempConfiguration.setTo(currentDisplayConfig);
         displayContent.computeScreenConfiguration(mTempConfiguration);
@@ -5335,7 +5334,7 @@
 
         if (configChanged) {
             mWaitingForConfig = true;
-            startFreezingDisplayLocked(false /* inTransaction */, 0 /* exitAnim */,
+            startFreezingDisplayLocked(0 /* exitAnim */,
                     0 /* enterAnim */, displayContent);
             mH.obtainMessage(H.SEND_NEW_CONFIGURATION, displayId).sendToTarget();
         }
@@ -5651,12 +5650,12 @@
         return false;
     }
 
-    void startFreezingDisplayLocked(boolean inTransaction, int exitAnim, int enterAnim) {
-        startFreezingDisplayLocked(inTransaction, exitAnim, enterAnim,
+    void startFreezingDisplayLocked(int exitAnim, int enterAnim) {
+        startFreezingDisplayLocked(exitAnim, enterAnim,
                 getDefaultDisplayContentLocked());
     }
 
-    void startFreezingDisplayLocked(boolean inTransaction, int exitAnim, int enterAnim,
+    void startFreezingDisplayLocked(int exitAnim, int enterAnim,
             DisplayContent displayContent) {
         if (mDisplayFrozen) {
             return;
@@ -5669,8 +5668,8 @@
         }
 
         if (DEBUG_ORIENTATION) Slog.d(TAG_WM,
-                "startFreezingDisplayLocked: inTransaction=" + inTransaction
-                + " exitAnim=" + exitAnim + " enterAnim=" + enterAnim
+                "startFreezingDisplayLocked: exitAnim="
+                + exitAnim + " enterAnim=" + enterAnim
                 + " called by " + Debug.getCallers(8));
         mScreenFrozenLock.acquire();
 
@@ -5714,7 +5713,7 @@
 
             displayContent.updateDisplayInfo();
             screenRotationAnimation = new ScreenRotationAnimation(mContext, displayContent,
-                    inTransaction, mPolicy.isDefaultOrientationForced(), isSecure,
+                    mPolicy.isDefaultOrientationForced(), isSecure,
                     this);
             mAnimator.setScreenRotationAnimationLocked(mFrozenDisplayId,
                     screenRotationAnimation);
@@ -5777,9 +5776,10 @@
             if (!mPolicy.validateRotationAnimationLw(mExitAnimId, mEnterAnimId, false)) {
                 mExitAnimId = mEnterAnimId = 0;
             }
-            if (screenRotationAnimation.dismiss(MAX_ANIMATION_DURATION,
+            if (screenRotationAnimation.dismiss(mTransaction, MAX_ANIMATION_DURATION,
                     getTransitionAnimationScaleLocked(), displayInfo.logicalWidth,
                         displayInfo.logicalHeight, mExitAnimId, mEnterAnimId)) {
+                mTransaction.apply();
                 scheduleAnimationLocked();
             } else {
                 screenRotationAnimation.kill();
@@ -5802,7 +5802,7 @@
         // to avoid inconsistent states.  However, something interesting
         // could have actually changed during that time so re-evaluate it
         // now to catch that.
-        configChanged = updateOrientationFromAppTokensLocked(false, displayId);
+        configChanged = updateOrientationFromAppTokensLocked(displayId);
 
         // A little kludge: a lot could have happened while the
         // display was frozen, so now that we are coming back we
@@ -5816,8 +5816,7 @@
 
         if (updateRotation) {
             if (DEBUG_ORIENTATION) Slog.d(TAG_WM, "Performing post-rotate rotation");
-            configChanged |= displayContent.updateRotationUnchecked(
-                    false /* inTransaction */);
+            configChanged |= displayContent.updateRotationUnchecked();
         }
 
         if (configChanged) {
@@ -7027,8 +7026,9 @@
             if (DEBUG_ORIENTATION) {
                 Slog.i(TAG, "Performing post-rotate rotation after seamless rotation");
             }
+
             final DisplayContent displayContent = w.getDisplayContent();
-            if (displayContent.updateRotationUnchecked(false /* inTransaction */)) {
+            if (displayContent.updateRotationUnchecked()) {
                 mH.obtainMessage(H.SEND_NEW_CONFIGURATION, displayContent.getDisplayId())
                         .sendToTarget();
             }
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 68bb530..8866fe5 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -2015,7 +2015,7 @@
             removeImmediately();
             // Removing a visible window will effect the computed orientation
             // So just update orientation if needed.
-            if (wasVisible && mService.updateOrientationFromAppTokensLocked(false, displayId)) {
+            if (wasVisible && mService.updateOrientationFromAppTokensLocked(displayId)) {
                 mService.mH.obtainMessage(SEND_NEW_CONFIGURATION, displayId).sendToTarget();
             }
             mService.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 13f05e0..b6ff68f 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -1415,7 +1415,8 @@
         }
     }
 
-    void seamlesslyRotateWindow(int oldRotation, int newRotation) {
+    void seamlesslyRotateWindow(SurfaceControl.Transaction t,
+            int oldRotation, int newRotation) {
         final WindowState w = mWin;
         if (!w.isVisibleNow() || w.mIsWallpaper) {
             return;
@@ -1456,11 +1457,11 @@
         float DsDy = mService.mTmpFloats[Matrix.MSCALE_Y];
         float nx = mService.mTmpFloats[Matrix.MTRANS_X];
         float ny = mService.mTmpFloats[Matrix.MTRANS_Y];
-        mSurfaceController.setPositionInTransaction(nx, ny, false);
-        mSurfaceController.setMatrixInTransaction(DsDx * w.mHScale,
+        t.setPosition(mSurfaceController.mSurfaceControl, nx, ny);
+        t.setMatrix(mSurfaceController.mSurfaceControl, DsDx * w.mHScale,
                 DtDx * w.mVScale,
                 DtDy * w.mHScale,
-                DsDy * w.mVScale, false);
+                DsDy * w.mVScale);
     }
 
     /** The force-scaled state for a given window can persist past