Merge "Merge SV transactions to VRI BlastBufferQueue"
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index b5185ae..26e3bb2 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -457,18 +457,8 @@
                                 Log.d(TAG, System.identityHashCode(this)
                                         + " updateSurfaceAlpha RT: set alpha=" + alpha);
                             }
-                            if (useBLAST) {
-                                synchronized (viewRoot.getBlastTransactionLock()) {
-                                    viewRoot.getBLASTSyncTransaction()
-                                            .setAlpha(mSurfaceControl, alpha);
-                                }
-                            } else {
-                                Transaction t = new SurfaceControl.Transaction();
-                                t.setAlpha(mSurfaceControl, alpha);
-                                t.deferTransactionUntil(mSurfaceControl,
-                                        viewRoot.getSurfaceControl(), frame);
-                                t.apply();
-                            }
+                            mRtTransaction.setAlpha(mSurfaceControl, alpha);
+                            applyRtTransaction(frame);
                         }
                         // It's possible that mSurfaceControl is released in the UI thread before
                         // the transaction completes. If that happens, an exception is thrown, which
@@ -818,17 +808,8 @@
                         return;
                     }
 
-                    if (useBLAST) {
-                        synchronized (viewRoot.getBlastTransactionLock()) {
-                            updateRelativeZ(viewRoot.getBLASTSyncTransaction());
-                        }
-                    } else {
-                        final SurfaceControl.Transaction t = new SurfaceControl.Transaction();
-                        updateRelativeZ(t);
-                        t.deferTransactionUntil(mSurfaceControl,
-                                viewRoot.getSurfaceControl(), frame);
-                        t.apply();
-                    }
+                    updateRelativeZ(mRtTransaction);
+                    applyRtTransaction(frame);
                 }
                 // It's possible that mSurfaceControl is released in the UI thread before
                 // the transaction completes. If that happens, an exception is thrown, which
@@ -927,7 +908,7 @@
     }
 
     private boolean performSurfaceTransaction(ViewRootImpl viewRoot, Translator translator,
-        boolean creating, boolean sizeChanged, boolean needBLASTSync) {
+            boolean creating, boolean sizeChanged) {
         boolean realSizeChanged = false;
 
         mSurfaceLock.lock();
@@ -990,8 +971,6 @@
                     mTmpTransaction.setWindowCrop(mSurfaceControl, mSurfaceWidth,
                             mSurfaceHeight);
                 }
-            } else if (needBLASTSync) {
-                viewRoot.setUseBLASTSyncTransaction();
             }
             mTmpTransaction.setCornerRadius(mSurfaceControl, mCornerRadius);
             if (sizeChanged && !creating) {
@@ -1109,11 +1088,8 @@
                     return;
                 }
 
-                final boolean needBLASTSync =
-                    (layoutSizeChanged || positionChanged || visibleChanged) &&
-                        useBLASTSync(viewRoot);
                 final boolean realSizeChanged = performSurfaceTransaction(viewRoot,
-                    translator, creating, sizeChanged, needBLASTSync);
+                        translator, creating, sizeChanged);
                 final boolean redrawNeeded = sizeChanged || creating ||
                     (mVisible && !mDrawFinished);
 
@@ -1351,13 +1327,7 @@
     }
 
     private void applySurfaceTransforms(SurfaceControl surface, SurfaceControl.Transaction t,
-            Rect position, long frameNumber) {
-        final ViewRootImpl viewRoot = getViewRootImpl();
-        if (frameNumber > 0 && viewRoot != null && !useBLASTSync(viewRoot)) {
-            t.deferTransactionUntil(surface, viewRoot.getSurfaceControl(),
-                    frameNumber);
-        }
-
+            Rect position) {
         onSetSurfacePositionAndScaleRT(t, surface,
                 position.left /*positionLeft*/,
                 position.top /*positionTop*/,
@@ -1378,24 +1348,29 @@
         return mRTLastReportedPosition;
     }
 
-    private void setParentSpaceRectangle(Transaction t, Rect position, long frameNumber) {
-        final ViewRootImpl viewRoot = getViewRootImpl();
-        applySurfaceTransforms(mSurfaceControl, t, position, frameNumber);
-        applyChildSurfaceTransaction_renderWorker(t, viewRoot.mSurface, frameNumber);
-    }
-
     private void setParentSpaceRectangle(Rect position, long frameNumber) {
         final ViewRootImpl viewRoot = getViewRootImpl();
-        final boolean useBLAST = useBLASTSync(viewRoot);
+        applySurfaceTransforms(mSurfaceControl, mRtTransaction, position);
+        applyChildSurfaceTransaction_renderWorker(mRtTransaction, viewRoot.mSurface, frameNumber);
+        applyRtTransaction(frameNumber);
+    }
 
+    private void applyRtTransaction(long frameNumber) {
+        final ViewRootImpl viewRoot = getViewRootImpl();
+        boolean useBLAST = viewRoot != null && useBLASTSync(viewRoot);
         if (useBLAST) {
-            synchronized (viewRoot.getBlastTransactionLock()) {
-                setParentSpaceRectangle(viewRoot.getBLASTSyncTransaction(), position, frameNumber);
-            }
-        } else {
-            setParentSpaceRectangle(mRtTransaction, position, frameNumber);
-            mRtTransaction.apply();
+            // If we are using BLAST, merge the transaction with the viewroot buffer transaction.
+            viewRoot.mergeWithNextTransaction(mRtTransaction, frameNumber);
+            return;
         }
+
+        // Otherwise if the if the ViewRoot is not null, use deferred transaction instead.
+        if (frameNumber > 0 && viewRoot != null && viewRoot.mSurface.isValid()
+                && mSurfaceControl != null) {
+            mRtTransaction.deferTransactionUntil(mSurfaceControl,
+                    viewRoot.getSurfaceControl(), frameNumber);
+        }
+        mRtTransaction.apply();
     }
 
     private Rect mRTLastReportedPosition = new Rect();
@@ -1444,8 +1419,6 @@
 
         @Override
         public void positionLost(long frameNumber) {
-            final ViewRootImpl viewRoot = getViewRootImpl();
-            boolean useBLAST = viewRoot != null && useBLASTSync(viewRoot);
             if (DEBUG) {
                 Log.d(TAG, String.format("%d windowPositionLost, frameNr = %d",
                         System.identityHashCode(this), frameNumber));
@@ -1461,30 +1434,20 @@
              * need to hold the lock here.
              */
             synchronized (mSurfaceControlLock) {
-                if (useBLAST) {
-                    synchronized (viewRoot.getBlastTransactionLock()) {
-                        viewRoot.getBLASTSyncTransaction().hide(mSurfaceControl);
-                        if (mRtReleaseSurfaces) {
-                            mRtReleaseSurfaces = false;
-                            releaseSurfaces(viewRoot.getBLASTSyncTransaction());
-                        }
-                    }
-                } else {
-                    if (frameNumber > 0 && viewRoot != null && viewRoot.mSurface.isValid()) {
-                        mRtTransaction.deferTransactionUntil(mSurfaceControl,
-                                viewRoot.getSurfaceControl(), frameNumber);
-                    }
-                    mRtTransaction.hide(mSurfaceControl);
-                    if (mRtReleaseSurfaces) {
-                        mRtReleaseSurfaces = false;
-                        releaseSurfaces(mRtTransaction);
-                    }
-                    // If we aren't using BLAST, we apply the transaction locally, otherwise we let
-                    // the ViewRoot apply it for us.
-                    // If the ViewRoot is null, we behave as if we aren't using BLAST so we need to
-                    // apply the transaction.
-                    mRtTransaction.apply();
+                final ViewRootImpl viewRoot = getViewRootImpl();
+                boolean deferTransaction = frameNumber > 0 && viewRoot != null
+                        && viewRoot.mSurface.isValid() && !useBLASTSync(viewRoot);
+                if (deferTransaction) {
+                    mRtTransaction.deferTransactionUntil(mSurfaceControl,
+                            viewRoot.getSurfaceControl(), frameNumber);
                 }
+
+                mRtTransaction.hide(mSurfaceControl);
+                if (mRtReleaseSurfaces) {
+                    mRtReleaseSurfaces = false;
+                    releaseSurfaces(mRtTransaction);
+                }
+                applyRtTransaction(frameNumber);
                 mRtHandlingPositionUpdates = false;
             }
         }
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index ecba615..0fc2d7a 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -10117,4 +10117,14 @@
     int getSurfaceSequenceId() {
         return mSurfaceSequenceId;
     }
+
+    /**
+     * Merges the transaction passed in with the next transaction in BLASTBufferQueue. This ensures
+     * you can add transactions to the upcoming frame.
+     */
+    void mergeWithNextTransaction(Transaction t, long frameNumber) {
+        if (mBlastBufferQueue != null) {
+            mBlastBufferQueue.mergeWithNextTransaction(t, frameNumber);
+        }
+    }
 }
diff --git a/core/jni/android_graphics_BLASTBufferQueue.cpp b/core/jni/android_graphics_BLASTBufferQueue.cpp
index 66a17c3..8d3faf4 100644
--- a/core/jni/android_graphics_BLASTBufferQueue.cpp
+++ b/core/jni/android_graphics_BLASTBufferQueue.cpp
@@ -114,6 +114,13 @@
     queue->flushShadowQueue();
 }
 
+static void nativeMergeWithNextTransaction(JNIEnv*, jclass clazz, jlong ptr, jlong transactionPtr,
+                                           jlong framenumber) {
+    sp<BLASTBufferQueue> queue = reinterpret_cast<BLASTBufferQueue*>(ptr);
+    auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionPtr);
+    queue->mergeWithNextTransaction(transaction, framenumber);
+}
+
 static void nativeSetTransactionCompleteCallback(JNIEnv* env, jclass clazz, jlong ptr,
                                                  jlong frameNumber,
                                                  jobject transactionCompleteCallback) {
@@ -138,6 +145,7 @@
         {"nativeSetNextTransaction", "(JJ)V", (void*)nativeSetNextTransaction},
         {"nativeUpdate", "(JJJJ)V", (void*)nativeUpdate},
         {"nativeFlushShadowQueue", "(J)V", (void*)nativeFlushShadowQueue},
+        {"nativeMergeWithNextTransaction", "(JJJ)V", (void*)nativeMergeWithNextTransaction},
         {"nativeSetTransactionCompleteCallback",
                 "(JJLandroid/graphics/BLASTBufferQueue$TransactionCompleteCallback;)V",
                 (void*)nativeSetTransactionCompleteCallback}
diff --git a/graphics/java/android/graphics/BLASTBufferQueue.java b/graphics/java/android/graphics/BLASTBufferQueue.java
index be40dc6..4914336 100644
--- a/graphics/java/android/graphics/BLASTBufferQueue.java
+++ b/graphics/java/android/graphics/BLASTBufferQueue.java
@@ -34,6 +34,8 @@
     private static native void nativeSetNextTransaction(long ptr, long transactionPtr);
     private static native void nativeUpdate(long ptr, long surfaceControl, long width, long height);
     private static native void nativeFlushShadowQueue(long ptr);
+    private static native void nativeMergeWithNextTransaction(long ptr, long transactionPtr,
+                                                              long frameNumber);
     private static native void nativeSetTransactionCompleteCallback(long ptr, long frameNumber,
             TransactionCompleteCallback callback);
 
@@ -111,4 +113,14 @@
     public void flushShadowQueue() {
         nativeFlushShadowQueue(mNativeObject);
     }
+
+    /**
+     * Merge the transaction passed in to the next transaction in BlastBufferQueue. The next
+     * transaction will be applied or merged when the next frame with specified frame number
+     * is available.
+     */
+    public void mergeWithNextTransaction(SurfaceControl.Transaction t, long frameNumber) {
+        nativeMergeWithNextTransaction(mNativeObject, t.mNativeObject, frameNumber);
+    }
+
 }