diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 042219f4cb0bb..0dd6e22c6c3af 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 3b7328e72913a..d4fb3e327754a 100644 --- a/core/jni/android_graphics_BLASTBufferQueue.cpp +++ b/core/jni/android_graphics_BLASTBufferQueue.cpp @@ -139,6 +139,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 @@ -152,6 +157,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 2393eaf32e9a1..e369acc9c1a4c 100644 --- a/graphics/java/android/graphics/BLASTBufferQueue.java +++ b/graphics/java/android/graphics/BLASTBufferQueue.java @@ -39,6 +39,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)} @@ -141,6 +142,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); }