diff options
Diffstat (limited to 'libs/hwui/JankTracker.cpp')
-rw-r--r-- | libs/hwui/JankTracker.cpp | 87 |
1 files changed, 52 insertions, 35 deletions
diff --git a/libs/hwui/JankTracker.cpp b/libs/hwui/JankTracker.cpp index cf29e434a351..81a79801073c 100644 --- a/libs/hwui/JankTracker.cpp +++ b/libs/hwui/JankTracker.cpp @@ -38,16 +38,27 @@ namespace android { namespace uirenderer { struct Comparison { + JankType type; + std::function<int64_t(nsecs_t)> computeThreadshold; FrameInfoIndex start; FrameInfoIndex end; }; -static const Comparison COMPARISONS[] = { - {FrameInfoIndex::IntendedVsync, FrameInfoIndex::Vsync}, - {FrameInfoIndex::OldestInputEvent, FrameInfoIndex::Vsync}, - {FrameInfoIndex::Vsync, FrameInfoIndex::SyncStart}, - {FrameInfoIndex::SyncStart, FrameInfoIndex::IssueDrawCommandsStart}, - {FrameInfoIndex::IssueDrawCommandsStart, FrameInfoIndex::FrameCompleted}, +static const std::array<Comparison, 4> COMPARISONS{ + Comparison{JankType::kMissedVsync, [](nsecs_t) { return 1; }, FrameInfoIndex::IntendedVsync, + FrameInfoIndex::Vsync}, + + Comparison{JankType::kSlowUI, + [](nsecs_t frameInterval) { return static_cast<int64_t>(.5 * frameInterval); }, + FrameInfoIndex::Vsync, FrameInfoIndex::SyncStart}, + + Comparison{JankType::kSlowSync, + [](nsecs_t frameInterval) { return static_cast<int64_t>(.2 * frameInterval); }, + FrameInfoIndex::SyncStart, FrameInfoIndex::IssueDrawCommandsStart}, + + Comparison{JankType::kSlowRT, + [](nsecs_t frameInterval) { return static_cast<int64_t>(.75 * frameInterval); }, + FrameInfoIndex::IssueDrawCommandsStart, FrameInfoIndex::FrameCompleted}, }; // If the event exceeds 10 seconds throw it away, this isn't a jank event @@ -91,24 +102,10 @@ JankTracker::JankTracker(ProfileDataContainer* globalData, const DisplayInfo& di void JankTracker::setFrameInterval(nsecs_t frameInterval) { mFrameInterval = frameInterval; - mThresholds[kMissedVsync] = 1; - /* - * Due to interpolation and sample rate differences between the touch - * panel and the display (example, 85hz touch panel driving a 60hz display) - * we call high latency 1.5 * frameinterval - * - * NOTE: Be careful when tuning this! A theoretical 1,000hz touch panel - * on a 60hz display will show kOldestInputEvent - kIntendedVsync of being 15ms - * Thus this must always be larger than frameInterval, or it will fail - */ - mThresholds[kHighInputLatency] = static_cast<int64_t>(1.5 * frameInterval); - - // Note that these do not add up to 1. This is intentional. It's to deal - // with variance in values, and should be sort of an upper-bound on what - // is reasonable to expect. - mThresholds[kSlowUI] = static_cast<int64_t>(.5 * frameInterval); - mThresholds[kSlowSync] = static_cast<int64_t>(.2 * frameInterval); - mThresholds[kSlowRT] = static_cast<int64_t>(.75 * frameInterval); + + for (auto& comparison : COMPARISONS) { + mThresholds[comparison.type] = comparison.computeThreadshold(frameInterval); + } } void JankTracker::finishFrame(const FrameInfo& frame) { @@ -129,28 +126,48 @@ void JankTracker::finishFrame(const FrameInfo& frame) { totalDuration -= forgiveAmount; } } + LOG_ALWAYS_FATAL_IF(totalDuration <= 0, "Impossible totalDuration %" PRId64, totalDuration); mData->reportFrame(totalDuration); (*mGlobalData)->reportFrame(totalDuration); - // Keep the fast path as fast as possible. - if (CC_LIKELY(totalDuration < mFrameInterval)) { + // Only things like Surface.lockHardwareCanvas() are exempt from tracking + if (CC_UNLIKELY(frame[FrameInfoIndex::Flags] & EXEMPT_FRAMES_FLAGS)) { return; } - // Only things like Surface.lockHardwareCanvas() are exempt from tracking - if (frame[FrameInfoIndex::Flags] & EXEMPT_FRAMES_FLAGS) { + if (totalDuration > mFrameInterval) { + mData->reportJank(); + (*mGlobalData)->reportJank(); + } + + bool isTripleBuffered = mSwapDeadline > frame[FrameInfoIndex::IntendedVsync]; + + mSwapDeadline = std::max(mSwapDeadline + mFrameInterval, + frame[FrameInfoIndex::IntendedVsync] + mFrameInterval); + + // If we hit the deadline, cool! + if (frame[FrameInfoIndex::FrameCompleted] < mSwapDeadline) { + if (isTripleBuffered) { + mData->reportJankType(JankType::kHighInputLatency); + (*mGlobalData)->reportJankType(JankType::kHighInputLatency); + } return; } - mData->reportJank(); - (*mGlobalData)->reportJank(); + mData->reportJankType(JankType::kMissedDeadline); + (*mGlobalData)->reportJankType(JankType::kMissedDeadline); + + // Janked, reset the swap deadline + nsecs_t jitterNanos = frame[FrameInfoIndex::FrameCompleted] - frame[FrameInfoIndex::Vsync]; + nsecs_t lastFrameOffset = jitterNanos % mFrameInterval; + mSwapDeadline = frame[FrameInfoIndex::FrameCompleted] - lastFrameOffset + mFrameInterval; - for (int i = 0; i < NUM_BUCKETS; i++) { - int64_t delta = frame.duration(COMPARISONS[i].start, COMPARISONS[i].end); - if (delta >= mThresholds[i] && delta < IGNORE_EXCEEDING) { - mData->reportJankType((JankType)i); - (*mGlobalData)->reportJankType((JankType)i); + for (auto& comparison : COMPARISONS) { + int64_t delta = frame.duration(comparison.start, comparison.end); + if (delta >= mThresholds[comparison.type] && delta < IGNORE_EXCEEDING) { + mData->reportJankType(comparison.type); + (*mGlobalData)->reportJankType(comparison.type); } } |