From 9f19b5d19864d32f74c0cbb32f556b0b0028f1c8 Mon Sep 17 00:00:00 2001 From: chaviw Date: Fri, 3 Sep 2021 16:19:08 -0500 Subject: [PATCH] Call applyPendingTransactions when frame didn't draw It's possible for a caller to requested mergeWithNextTransaction, but the main frame had nothing new to draw. If that's the case, the mergeWithNextTransactions will be stuck and never applied (or applied much later). Since this could end up blocking Transactions, it's better to force apply these when we know a frame wasn't going to draw this vsync. Test: Existing tests pass Bug: 195262673 Change-Id: Ic0919ba6446d6a12d824185f6b3e540c2d5319d7 --- core/java/android/view/ViewRootImpl.java | 4 ++++ core/jni/android_graphics_BLASTBufferQueue.cpp | 6 ++++++ graphics/java/android/graphics/BLASTBufferQueue.java | 12 ++++++++++++ 3 files changed, 22 insertions(+) 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); }