diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 9e2b6e0a26868..e7c1e04a5d57b 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -4031,6 +4031,10 @@ public final class ViewRootImpl implements ViewParent, mBlastBufferQueue.setNextTransaction(null); mBlastBufferQueue.setTransactionCompleteCallback(mRtLastAttemptedDrawFrameNum, null); + // Apply 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); } mHandler.postAtFrontOfQueue(() -> { diff --git a/core/jni/android_graphics_BLASTBufferQueue.cpp b/core/jni/android_graphics_BLASTBufferQueue.cpp index 3e31b46b5bda5..a5fbcf51d224c 100644 --- a/core/jni/android_graphics_BLASTBufferQueue.cpp +++ b/core/jni/android_graphics_BLASTBufferQueue.cpp @@ -144,6 +144,11 @@ static jlong nativeGetLastAcquiredFrameNum(JNIEnv* env, jclass clazz, jlong ptr) return queue->getLastAcquiredFrameNum(); } +static void nativeApplyPendingTransactions(JNIEnv* env, jclass clazz, jlong ptr, jlong frameNum) { + sp queue = reinterpret_cast(ptr); + queue->applyPendingTransactions(frameNum); +} + static const JNINativeMethod gMethods[] = { /* name, signature, funcPtr */ // clang-format off @@ -158,6 +163,7 @@ static const JNINativeMethod gMethods[] = { "(JJLandroid/graphics/BLASTBufferQueue$TransactionCompleteCallback;)V", (void*)nativeSetTransactionCompleteCallback}, {"nativeGetLastAcquiredFrameNum", "(J)J", (void*)nativeGetLastAcquiredFrameNum}, + {"nativeApplyPendingTransactions", "(JJ)V", (void*)nativeApplyPendingTransactions}, // clang-format on }; diff --git a/graphics/java/android/graphics/BLASTBufferQueue.java b/graphics/java/android/graphics/BLASTBufferQueue.java index 0e1360fcdbbca..9164ad98d7e9e 100644 --- a/graphics/java/android/graphics/BLASTBufferQueue.java +++ b/graphics/java/android/graphics/BLASTBufferQueue.java @@ -40,6 +40,7 @@ public final class BLASTBufferQueue { private static native void nativeSetTransactionCompleteCallback(long ptr, long frameNumber, TransactionCompleteCallback callback); private static native long nativeGetLastAcquiredFrameNum(long ptr); + private static native void nativeApplyPendingTransactions(long ptr, long frameNumber); /** * Callback sent to {@link #setTransactionCompleteCallback(long, TransactionCompleteCallback)} @@ -146,6 +147,17 @@ public final class BLASTBufferQueue { nativeMergeWithNextTransaction(mNativeObject, nativeTransaction, frameNumber); } + /** + * Apply 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. + */ + public void applyPendingTransactions(long frameNumber) { + nativeApplyPendingTransactions(mNativeObject, frameNumber); + } + public long getLastAcquiredFrameNum() { return nativeGetLastAcquiredFrameNum(mNativeObject); }