Buffer stuffing recovery when blocked on dequeueBuffer
Detect when the client is blocked waiting on buffer release
and only recover from buffer stuffing then. This is a more
conservative measure for recovery that will prevent the
client from being maximally buffer stuffed. This still provides
some "padding" to prevent from additional app janks that
can be exposed if we recover from buffer stuffing too
aggressively. Recover by delaying 1 frame and adding animation
offsets.
Bug: b/294922229
Test: presubmit, manually check perfetto traces
Flag: android.view.flags.buffer_stuffing_recovery
Change-Id: I24e34591e809aebd7626657c6340faed323227ad
diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp
index 7aee903..f476ce1 100644
--- a/libs/gui/BLASTBufferQueue.cpp
+++ b/libs/gui/BLASTBufferQueue.cpp
@@ -1232,6 +1232,11 @@
return OK;
}
+ // Provide a callback for Choreographer to start buffer stuffing recovery when blocked
+ // on buffer release.
+ std::function<void()> callbackCopy = bbq->getWaitForBufferReleaseCallback();
+ if (callbackCopy) callbackCopy();
+
// BufferQueue has already checked if we have a free buffer. If there's an unread interrupt,
// we want to ignore it. This must be done before unlocking the BufferQueue lock to ensure
// we don't miss an interrupt.
@@ -1344,6 +1349,16 @@
mApplyToken = std::move(applyToken);
}
+void BLASTBufferQueue::setWaitForBufferReleaseCallback(std::function<void()> callback) {
+ std::lock_guard _lock{mWaitForBufferReleaseMutex};
+ mWaitForBufferReleaseCallback = std::move(callback);
+}
+
+std::function<void()> BLASTBufferQueue::getWaitForBufferReleaseCallback() const {
+ std::lock_guard _lock{mWaitForBufferReleaseMutex};
+ return mWaitForBufferReleaseCallback;
+}
+
#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
void BLASTBufferQueue::updateBufferReleaseProducer() {