diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java index 7f115fad5735c..d3061e21efeb6 100644 --- a/core/java/android/view/SurfaceControl.java +++ b/core/java/android/view/SurfaceControl.java @@ -2779,9 +2779,13 @@ public final class SurfaceControl implements Parcelable { * is allowed as a convenience. */ public Transaction() { - mNativeObject = nativeCreateTransaction(); - mFreeNativeResources - = sRegistry.registerNativeAllocation(this, mNativeObject); + this(nativeCreateTransaction()); + } + + private Transaction(long nativeObject) { + mNativeObject = nativeObject; + mFreeNativeResources = + sRegistry.registerNativeAllocation(this, mNativeObject); } private Transaction(Parcel in) { diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 777e89d145b2d..39fc2c0443076 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -4169,19 +4169,22 @@ public final class ViewRootImpl implements ViewParent, + " didProduceBuffer=" + didProduceBuffer); } + Transaction tmpTransaction = new Transaction(); + tmpTransaction.merge(mRtBLASTSyncTransaction); + // If frame wasn't drawn, clear out the next transaction so it doesn't affect the next // draw attempt. The next transaction and transaction complete callback were only set // for the current draw attempt. if (!didProduceBuffer) { mBlastBufferQueue.setSyncTransaction(null); - // Apply the transactions that were sent to mergeWithNextTransaction since the + // Get the transactions that were sent to mergeWithNextTransaction since the // frame didn't draw on this vsync. It's possible the frame will draw later, but // it's better to not be sync than to block on a frame that may never come. - mBlastBufferQueue.applyPendingTransactions(mRtLastAttemptedDrawFrameNum); + Transaction pendingTransactions = mBlastBufferQueue.gatherPendingTransactions( + mRtLastAttemptedDrawFrameNum); + tmpTransaction.merge(pendingTransactions); } - Transaction tmpTransaction = new Transaction(); - tmpTransaction.merge(mRtBLASTSyncTransaction); // Post at front of queue so the buffer can be processed immediately and allow RT // to continue processing new buffers. If RT tries to process buffers before the sync // buffer is applied, the new buffers will not get acquired and could result in a diff --git a/core/jni/android_graphics_BLASTBufferQueue.cpp b/core/jni/android_graphics_BLASTBufferQueue.cpp index 55f136997aad5..4f13a9cf257eb 100644 --- a/core/jni/android_graphics_BLASTBufferQueue.cpp +++ b/core/jni/android_graphics_BLASTBufferQueue.cpp @@ -30,6 +30,11 @@ namespace android { +static struct { + jclass clazz; + jmethodID ctor; +} gTransactionClassInfo; + static jlong nativeCreate(JNIEnv* env, jclass clazz, jstring jName) { ScopedUtfChars name(env, jName); sp queue = new BLASTBufferQueue(name.c_str()); @@ -86,6 +91,14 @@ static bool nativeIsSameSurfaceControl(JNIEnv* env, jclass clazz, jlong ptr, jlo return queue->isSameSurfaceControl(reinterpret_cast(surfaceControl)); } +static jobject nativeGatherPendingTransactions(JNIEnv* env, jclass clazz, jlong ptr, + jlong frameNum) { + sp queue = reinterpret_cast(ptr); + SurfaceComposerClient::Transaction* transaction = queue->gatherPendingTransactions(frameNum); + return env->NewObject(gTransactionClassInfo.clazz, gTransactionClassInfo.ctor, + reinterpret_cast(transaction)); +} + static const JNINativeMethod gMethods[] = { /* name, signature, funcPtr */ // clang-format off @@ -98,6 +111,7 @@ static const JNINativeMethod gMethods[] = { {"nativeGetLastAcquiredFrameNum", "(J)J", (void*)nativeGetLastAcquiredFrameNum}, {"nativeApplyPendingTransactions", "(JJ)V", (void*)nativeApplyPendingTransactions}, {"nativeIsSameSurfaceControl", "(JJ)Z", (void*)nativeIsSameSurfaceControl}, + {"nativeGatherPendingTransactions", "(JJ)Landroid/view/SurfaceControl$Transaction;", (void*)nativeGatherPendingTransactions} // clang-format on }; @@ -105,6 +119,11 @@ int register_android_graphics_BLASTBufferQueue(JNIEnv* env) { int res = jniRegisterNativeMethods(env, "android/graphics/BLASTBufferQueue", gMethods, NELEM(gMethods)); LOG_ALWAYS_FATAL_IF(res < 0, "Unable to register native methods."); + + jclass transactionClazz = FindClassOrDie(env, "android/view/SurfaceControl$Transaction"); + gTransactionClassInfo.clazz = MakeGlobalRefOrDie(env, transactionClazz); + gTransactionClassInfo.ctor = + GetMethodIDOrDie(env, gTransactionClassInfo.clazz, "", "(J)V"); return 0; } diff --git a/graphics/java/android/graphics/BLASTBufferQueue.java b/graphics/java/android/graphics/BLASTBufferQueue.java index a9e730d58e65e..2678c79d14542 100644 --- a/graphics/java/android/graphics/BLASTBufferQueue.java +++ b/graphics/java/android/graphics/BLASTBufferQueue.java @@ -39,6 +39,8 @@ public final class BLASTBufferQueue { private static native long nativeGetLastAcquiredFrameNum(long ptr); private static native void nativeApplyPendingTransactions(long ptr, long frameNumber); private static native boolean nativeIsSameSurfaceControl(long ptr, long surfaceControlPtr); + private static native SurfaceControl.Transaction nativeGatherPendingTransactions(long ptr, + long frameNumber); /** Create a new connection with the surface flinger. */ public BLASTBufferQueue(String name, SurfaceControl sc, int width, int height, @@ -159,4 +161,17 @@ public final class BLASTBufferQueue { public boolean isSameSurfaceControl(SurfaceControl sc) { return nativeIsSameSurfaceControl(mNativeObject, sc.mNativeObject); } + + /** + * Get any transactions that were passed to {@link #mergeWithNextTransaction} with the + * specified frameNumber. This is intended to ensure transactions don't get stuck as pending + * if the specified frameNumber is never drawn. + * + * @param frameNumber The frameNumber used to determine which transactions to apply. + * @return a Transaction that contains the merge of all the transactions that were sent to + * mergeWithNextTransaction + */ + public SurfaceControl.Transaction gatherPendingTransactions(long frameNumber) { + return nativeGatherPendingTransactions(mNativeObject, frameNumber); + } }