Teach JankTracker about new swap behaviors
Bug: 30440166
If we are using HWC2, there's a change in timing
when in triple buffering with the pipelined offsets.
This changes JankTracker to recognize that and silently
erase that from the total duration
Change-Id: Ib1fd4209070f17dbd2baed707c8cf73fb11c3cf2
diff --git a/libs/hwui/JankTracker.cpp b/libs/hwui/JankTracker.cpp
index ebe9c42..ed6b211 100644
--- a/libs/hwui/JankTracker.cpp
+++ b/libs/hwui/JankTracker.cpp
@@ -16,6 +16,7 @@
#include "JankTracker.h"
#include "Properties.h"
+#include "utils/TimeUtils.h"
#include <algorithm>
#include <cutils/ashmem.h>
@@ -119,11 +120,27 @@
return index;
}
-JankTracker::JankTracker(nsecs_t frameIntervalNanos) {
+JankTracker::JankTracker(const DisplayInfo& displayInfo) {
// By default this will use malloc memory. It may be moved later to ashmem
// if there is shared space for it and a request comes in to do that.
mData = new ProfileData;
reset();
+ nsecs_t frameIntervalNanos = static_cast<nsecs_t>(1_s / displayInfo.fps);
+#if USE_HWC2
+ nsecs_t sfOffset = frameIntervalNanos - (displayInfo.presentationDeadline - 1_ms);
+ nsecs_t offsetDelta = sfOffset - displayInfo.appVsyncOffset;
+ // There are two different offset cases. If the offsetDelta is positive
+ // and small, then the intention is to give apps extra time by leveraging
+ // pipelining between the UI & RT threads. If the offsetDelta is large or
+ // negative, the intention is to subtract time from the total duration
+ // in which case we can't afford to wait for dequeueBuffer blockage.
+ if (offsetDelta <= 4_ms && offsetDelta >= 0) {
+ // SF will begin composition at VSYNC-app + offsetDelta. If we are triple
+ // buffered, this is the expected time at which dequeueBuffer will
+ // return due to the staggering of VSYNC-app & VSYNC-sf.
+ mDequeueTimeForgiveness = offsetDelta + 4_ms;
+ }
+#endif
setFrameInterval(frameIntervalNanos);
}
@@ -213,6 +230,19 @@
mData->totalFrameCount++;
// Fast-path for jank-free frames
int64_t totalDuration = frame.duration(sFrameStart, FrameInfoIndex::FrameCompleted);
+ if (mDequeueTimeForgiveness
+ && frame[FrameInfoIndex::DequeueBufferDuration] > 500_us) {
+ nsecs_t expectedDequeueDuration =
+ mDequeueTimeForgiveness + frame[FrameInfoIndex::Vsync]
+ - frame[FrameInfoIndex::IssueDrawCommandsStart];
+ if (expectedDequeueDuration > 0) {
+ // Forgive only up to the expected amount, but not more than
+ // the actual time spent blocked.
+ nsecs_t forgiveAmount = std::min(expectedDequeueDuration,
+ frame[FrameInfoIndex::DequeueBufferDuration]);
+ totalDuration -= forgiveAmount;
+ }
+ }
uint32_t framebucket = frameCountIndexForFrameTime(totalDuration);
// Keep the fast path as fast as possible.
if (CC_LIKELY(totalDuration < mFrameInterval)) {