diff options
| -rw-r--r-- | libs/gui/include/gui/JankInfo.h | 14 | ||||
| -rw-r--r-- | services/surfaceflinger/FrameTimeline/FrameTimeline.cpp | 43 | ||||
| -rw-r--r-- | services/surfaceflinger/FrameTimeline/FrameTimeline.h | 8 | ||||
| -rw-r--r-- | services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp | 69 |
4 files changed, 128 insertions, 6 deletions
diff --git a/libs/gui/include/gui/JankInfo.h b/libs/gui/include/gui/JankInfo.h index bf354e7bb4..1fc80c30d7 100644 --- a/libs/gui/include/gui/JankInfo.h +++ b/libs/gui/include/gui/JankInfo.h @@ -18,7 +18,7 @@ namespace android { -// Jank information tracked by SurfaceFlinger(SF) for perfetto tracing and telemetry. +// Jank type tracked by SurfaceFlinger(SF) for Perfetto tracing and telemetry. enum JankType { // No Jank None = 0x0, @@ -50,4 +50,16 @@ enum JankType { Dropped = 0x200, }; +// Jank severity type tracked by SurfaceFlinger(SF) for Perfetto tracing and telemetry. +enum class JankSeverityType { + // Unknown: not enough information to classify the severity of a jank + Unknown = 0, + // None: no jank + None = 1, + // Partial: jank caused by missing the deadline by less than the app's frame interval + Partial = 2, + // Full: jank caused by missing the deadline by more than the app's frame interval + Full = 3, +}; + } // namespace android diff --git a/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp b/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp index 9dc3938322..803299cf6f 100644 --- a/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp +++ b/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp @@ -280,6 +280,19 @@ int32_t jankTypeBitmaskToProto(int32_t jankType) { return protoJank; } +FrameTimelineEvent::JankSeverityType toProto(JankSeverityType jankSeverityType) { + switch (jankSeverityType) { + case JankSeverityType::Unknown: + return FrameTimelineEvent::SEVERITY_UNKNOWN; + case JankSeverityType::None: + return FrameTimelineEvent::SEVERITY_NONE; + case JankSeverityType::Partial: + return FrameTimelineEvent::SEVERITY_PARTIAL; + case JankSeverityType::Full: + return FrameTimelineEvent::SEVERITY_FULL; + } +} + // Returns the smallest timestamp from the set of predictions and actuals. nsecs_t getMinTime(PredictionState predictionState, TimelineItem predictions, TimelineItem actuals) { @@ -389,6 +402,15 @@ std::optional<int32_t> SurfaceFrame::getJankType() const { return mJankType; } +std::optional<JankSeverityType> SurfaceFrame::getJankSeverityType() const { + std::scoped_lock lock(mMutex); + if (mActuals.presentTime == 0) { + // Frame hasn't been presented yet. + return std::nullopt; + } + return mJankSeverityType; +} + nsecs_t SurfaceFrame::getBaseTime() const { std::scoped_lock lock(mMutex); return getMinTime(mPredictionState, mPredictions, mActuals); @@ -505,10 +527,11 @@ std::string SurfaceFrame::miniDump() const { } void SurfaceFrame::classifyJankLocked(int32_t displayFrameJankType, const Fps& refreshRate, - nsecs_t& deadlineDelta) { + Fps displayFrameRenderRate, nsecs_t& deadlineDelta) { if (mActuals.presentTime == Fence::SIGNAL_TIME_INVALID) { // Cannot do any classification for invalid present time. mJankType = JankType::Unknown; + mJankSeverityType = JankSeverityType::Unknown; deadlineDelta = -1; return; } @@ -519,6 +542,7 @@ void SurfaceFrame::classifyJankLocked(int32_t displayFrameJankType, const Fps& r // reasonable app, so prediction expire would mean a huge scheduling delay. mJankType = mPresentState != PresentState::Presented ? JankType::Dropped : JankType::AppDeadlineMissed; + mJankSeverityType = JankSeverityType::Unknown; deadlineDelta = -1; return; } @@ -543,6 +567,11 @@ void SurfaceFrame::classifyJankLocked(int32_t displayFrameJankType, const Fps& r if (std::abs(presentDelta) > mJankClassificationThresholds.presentThreshold) { mFramePresentMetadata = presentDelta > 0 ? FramePresentMetadata::LatePresent : FramePresentMetadata::EarlyPresent; + // Jank that is missing by less than the render rate period is classified as partial jank, + // otherwise it is a full jank. + mJankSeverityType = std::abs(presentDelta) < displayFrameRenderRate.getPeriodNsecs() + ? JankSeverityType::Partial + : JankSeverityType::Full; } else { mFramePresentMetadata = FramePresentMetadata::OnTimePresent; } @@ -613,6 +642,7 @@ void SurfaceFrame::classifyJankLocked(int32_t displayFrameJankType, const Fps& r mJankType = JankType::Dropped; // Since frame was not presented, lets drop any present value mActuals.presentTime = 0; + mJankSeverityType = JankSeverityType::Unknown; } } @@ -625,7 +655,7 @@ void SurfaceFrame::onPresent(nsecs_t presentTime, int32_t displayFrameJankType, mActuals.presentTime = presentTime; nsecs_t deadlineDelta = 0; - classifyJankLocked(displayFrameJankType, refreshRate, deadlineDelta); + classifyJankLocked(displayFrameJankType, refreshRate, displayFrameRenderRate, deadlineDelta); if (mPredictionState != PredictionState::None) { // Only update janky frames if the app used vsync predictions @@ -718,6 +748,7 @@ void SurfaceFrame::traceActuals(int64_t displayFrameToken, nsecs_t monoBootOffse actualSurfaceFrameStartEvent->set_jank_type(jankTypeBitmaskToProto(mJankType)); actualSurfaceFrameStartEvent->set_prediction_type(toProto(mPredictionState)); actualSurfaceFrameStartEvent->set_is_buffer(mIsBuffer); + actualSurfaceFrameStartEvent->set_jank_severity_type(toProto(mJankSeverityType)); }); // Actual timeline end @@ -910,6 +941,7 @@ void FrameTimeline::DisplayFrame::classifyJank(nsecs_t& deadlineDelta, nsecs_t& // Cannot do jank classification with expired predictions or invalid signal times. Set the // deltas to 0 as both negative and positive deltas are used as real values. mJankType = JankType::Unknown; + mJankSeverityType = JankSeverityType::Unknown; deadlineDelta = 0; deltaToVsync = 0; if (!presentTimeValid) { @@ -941,6 +973,11 @@ void FrameTimeline::DisplayFrame::classifyJank(nsecs_t& deadlineDelta, nsecs_t& if (std::abs(presentDelta) > mJankClassificationThresholds.presentThreshold) { mFramePresentMetadata = presentDelta > 0 ? FramePresentMetadata::LatePresent : FramePresentMetadata::EarlyPresent; + // Jank that is missing by less than the render rate period is classified as partial jank, + // otherwise it is a full jank. + mJankSeverityType = std::abs(presentDelta) < mRenderRate.getPeriodNsecs() + ? JankSeverityType::Partial + : JankSeverityType::Full; } else { mFramePresentMetadata = FramePresentMetadata::OnTimePresent; } @@ -1119,6 +1156,7 @@ void FrameTimeline::DisplayFrame::addSkippedFrame(pid_t surfaceFlingerPid, nsecs actualDisplayFrameStartEvent->set_prediction_type(toProto(PredictionState::Valid)); actualDisplayFrameStartEvent->set_present_type(FrameTimelineEvent::PRESENT_DROPPED); actualDisplayFrameStartEvent->set_jank_type(jankTypeBitmaskToProto(JankType::Dropped)); + actualDisplayFrameStartEvent->set_jank_severity_type(toProto(JankSeverityType::None)); }); // Actual timeline end @@ -1160,6 +1198,7 @@ void FrameTimeline::DisplayFrame::traceActuals(pid_t surfaceFlingerPid, actualDisplayFrameStartEvent->set_gpu_composition(mGpuFence != FenceTime::NO_FENCE); actualDisplayFrameStartEvent->set_jank_type(jankTypeBitmaskToProto(mJankType)); actualDisplayFrameStartEvent->set_prediction_type(toProto(mPredictionState)); + actualDisplayFrameStartEvent->set_jank_severity_type(toProto(mJankSeverityType)); }); // Actual timeline end diff --git a/services/surfaceflinger/FrameTimeline/FrameTimeline.h b/services/surfaceflinger/FrameTimeline/FrameTimeline.h index 6598e218fd..b5047a3467 100644 --- a/services/surfaceflinger/FrameTimeline/FrameTimeline.h +++ b/services/surfaceflinger/FrameTimeline/FrameTimeline.h @@ -168,6 +168,7 @@ public: // Returns std::nullopt if the frame hasn't been classified yet. // Used by both SF and FrameTimeline. std::optional<int32_t> getJankType() const; + std::optional<JankSeverityType> getJankSeverityType() const; // Functions called by SF int64_t getToken() const { return mToken; }; @@ -232,7 +233,7 @@ private: void tracePredictions(int64_t displayFrameToken, nsecs_t monoBootOffset) const; void traceActuals(int64_t displayFrameToken, nsecs_t monoBootOffset) const; void classifyJankLocked(int32_t displayFrameJankType, const Fps& refreshRate, - nsecs_t& deadlineDelta) REQUIRES(mMutex); + Fps displayFrameRenderRate, nsecs_t& deadlineDelta) REQUIRES(mMutex); const int64_t mToken; const int32_t mInputEventId; @@ -252,6 +253,8 @@ private: mutable std::mutex mMutex; // Bitmask for the type of jank int32_t mJankType GUARDED_BY(mMutex) = JankType::None; + // Enum for the severity of jank + JankSeverityType mJankSeverityType GUARDED_BY(mMutex) = JankSeverityType::None; // Indicates if this frame was composited by the GPU or not bool mGpuComposition GUARDED_BY(mMutex) = false; // Refresh rate for this frame. @@ -404,6 +407,7 @@ public: FramePresentMetadata getFramePresentMetadata() const { return mFramePresentMetadata; }; FrameReadyMetadata getFrameReadyMetadata() const { return mFrameReadyMetadata; }; int32_t getJankType() const { return mJankType; } + JankSeverityType getJankSeverityType() const { return mJankSeverityType; } const std::vector<std::shared_ptr<SurfaceFrame>>& getSurfaceFrames() const { return mSurfaceFrames; } @@ -435,6 +439,8 @@ public: PredictionState mPredictionState = PredictionState::None; // Bitmask for the type of jank int32_t mJankType = JankType::None; + // Enum for the severity of jank + JankSeverityType mJankSeverityType = JankSeverityType::None; // A valid gpu fence indicates that the DisplayFrame was composited by the GPU std::shared_ptr<FenceTime> mGpuFence = FenceTime::NO_FENCE; // Enum for the type of present diff --git a/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp b/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp index 9dd14317ef..ddc3967c40 100644 --- a/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp +++ b/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp @@ -41,6 +41,7 @@ using ProtoActualSurfaceFrameStart = perfetto::protos::FrameTimelineEvent_Actual using ProtoFrameEnd = perfetto::protos::FrameTimelineEvent_FrameEnd; using ProtoPresentType = perfetto::protos::FrameTimelineEvent_PresentType; using ProtoJankType = perfetto::protos::FrameTimelineEvent_JankType; +using ProtoJankSeverityType = perfetto::protos::FrameTimelineEvent_JankSeverityType; using ProtoPredictionType = perfetto::protos::FrameTimelineEvent_PredictionType; namespace android::frametimeline { @@ -335,7 +336,9 @@ TEST_F(FrameTimelineTest, presentFenceSignaled_presentedFramesUpdated) { EXPECT_EQ(presentedSurfaceFrame1.getActuals().presentTime, 42); EXPECT_EQ(presentedSurfaceFrame2.getActuals().presentTime, 42); EXPECT_NE(surfaceFrame1->getJankType(), std::nullopt); + EXPECT_NE(surfaceFrame1->getJankSeverityType(), std::nullopt); EXPECT_NE(surfaceFrame2->getJankType(), std::nullopt); + EXPECT_NE(surfaceFrame2->getJankSeverityType(), std::nullopt); } TEST_F(FrameTimelineTest, displayFramesSlidingWindowMovesAfterLimit) { @@ -493,8 +496,10 @@ TEST_F(FrameTimelineTest, presentFenceSignaled_invalidSignalTime) { auto displayFrame0 = getDisplayFrame(0); EXPECT_EQ(displayFrame0->getActuals().presentTime, 59); EXPECT_EQ(displayFrame0->getJankType(), JankType::Unknown | JankType::DisplayHAL); + EXPECT_EQ(displayFrame0->getJankSeverityType(), JankSeverityType::Unknown); EXPECT_EQ(surfaceFrame1->getActuals().presentTime, -1); EXPECT_EQ(surfaceFrame1->getJankType(), JankType::Unknown); + EXPECT_EQ(surfaceFrame1->getJankSeverityType(), JankSeverityType::Unknown); } // Tests related to TimeStats @@ -604,6 +609,7 @@ TEST_F(FrameTimelineTest, presentFenceSignaled_reportsDisplayMiss) { presentFence1->signalForTest(90); mFrameTimeline->setSfPresent(56, presentFence1); EXPECT_EQ(surfaceFrame1->getJankType(), JankType::DisplayHAL); + EXPECT_EQ(surfaceFrame1->getJankSeverityType(), JankSeverityType::Full); } TEST_F(FrameTimelineTest, presentFenceSignaled_reportsAppMiss) { @@ -633,6 +639,7 @@ TEST_F(FrameTimelineTest, presentFenceSignaled_reportsAppMiss) { mFrameTimeline->setSfPresent(86, presentFence1); EXPECT_EQ(surfaceFrame1->getJankType(), JankType::AppDeadlineMissed); + EXPECT_EQ(surfaceFrame1->getJankSeverityType(), JankSeverityType::Partial); } TEST_F(FrameTimelineTest, presentFenceSignaled_reportsSfScheduling) { @@ -662,6 +669,7 @@ TEST_F(FrameTimelineTest, presentFenceSignaled_reportsSfScheduling) { mFrameTimeline->setSfPresent(56, presentFence1); EXPECT_EQ(surfaceFrame1->getJankType(), JankType::SurfaceFlingerScheduling); + EXPECT_EQ(surfaceFrame1->getJankSeverityType(), JankSeverityType::Full); } TEST_F(FrameTimelineTest, presentFenceSignaled_reportsSfPredictionError) { @@ -691,6 +699,7 @@ TEST_F(FrameTimelineTest, presentFenceSignaled_reportsSfPredictionError) { mFrameTimeline->setSfPresent(56, presentFence1); EXPECT_EQ(surfaceFrame1->getJankType(), JankType::PredictionError); + EXPECT_EQ(surfaceFrame1->getJankSeverityType(), JankSeverityType::Partial); } TEST_F(FrameTimelineTest, presentFenceSignaled_reportsAppBufferStuffing) { @@ -721,6 +730,7 @@ TEST_F(FrameTimelineTest, presentFenceSignaled_reportsAppBufferStuffing) { mFrameTimeline->setSfPresent(86, presentFence1); EXPECT_EQ(surfaceFrame1->getJankType(), JankType::BufferStuffing); + EXPECT_EQ(surfaceFrame1->getJankSeverityType(), JankSeverityType::Full); } TEST_F(FrameTimelineTest, presentFenceSignaled_reportsAppMissWithRenderRate) { @@ -752,6 +762,7 @@ TEST_F(FrameTimelineTest, presentFenceSignaled_reportsAppMissWithRenderRate) { mFrameTimeline->setSfPresent(86, presentFence1); EXPECT_EQ(surfaceFrame1->getJankType(), JankType::AppDeadlineMissed); + EXPECT_EQ(surfaceFrame1->getJankSeverityType(), JankSeverityType::Full); } TEST_F(FrameTimelineTest, presentFenceSignaled_displayFramePredictionExpiredPresentsSurfaceFrame) { @@ -788,12 +799,14 @@ TEST_F(FrameTimelineTest, presentFenceSignaled_displayFramePredictionExpiredPres auto displayFrame = getDisplayFrame(0); EXPECT_EQ(displayFrame->getJankType(), JankType::Unknown); + EXPECT_EQ(displayFrame->getJankSeverityType(), JankSeverityType::Unknown); EXPECT_EQ(displayFrame->getFrameStartMetadata(), FrameStartMetadata::UnknownStart); EXPECT_EQ(displayFrame->getFrameReadyMetadata(), FrameReadyMetadata::UnknownFinish); EXPECT_EQ(displayFrame->getFramePresentMetadata(), FramePresentMetadata::UnknownPresent); EXPECT_EQ(surfaceFrame1->getActuals().presentTime, 90); EXPECT_EQ(surfaceFrame1->getJankType(), JankType::Unknown | JankType::AppDeadlineMissed); + EXPECT_EQ(surfaceFrame1->getJankSeverityType(), JankSeverityType::Full); } /* @@ -920,7 +933,8 @@ ProtoExpectedDisplayFrameStart createProtoExpectedDisplayFrameStart(int64_t cook ProtoActualDisplayFrameStart createProtoActualDisplayFrameStart( int64_t cookie, int64_t token, pid_t pid, ProtoPresentType presentType, bool onTimeFinish, - bool gpuComposition, ProtoJankType jankType, ProtoPredictionType predictionType) { + bool gpuComposition, ProtoJankType jankType, ProtoJankSeverityType jankSeverityType, + ProtoPredictionType predictionType) { ProtoActualDisplayFrameStart proto; proto.set_cookie(cookie); proto.set_token(token); @@ -929,6 +943,7 @@ ProtoActualDisplayFrameStart createProtoActualDisplayFrameStart( proto.set_on_time_finish(onTimeFinish); proto.set_gpu_composition(gpuComposition); proto.set_jank_type(jankType); + proto.set_jank_severity_type(jankSeverityType); proto.set_prediction_type(predictionType); return proto; } @@ -949,7 +964,8 @@ ProtoExpectedSurfaceFrameStart createProtoExpectedSurfaceFrameStart(int64_t cook ProtoActualSurfaceFrameStart createProtoActualSurfaceFrameStart( int64_t cookie, int64_t token, int64_t displayFrameToken, pid_t pid, std::string layerName, ProtoPresentType presentType, bool onTimeFinish, bool gpuComposition, - ProtoJankType jankType, ProtoPredictionType predictionType, bool isBuffer) { + ProtoJankType jankType, ProtoJankSeverityType jankSeverityType, + ProtoPredictionType predictionType, bool isBuffer) { ProtoActualSurfaceFrameStart proto; proto.set_cookie(cookie); proto.set_token(token); @@ -960,6 +976,7 @@ ProtoActualSurfaceFrameStart createProtoActualSurfaceFrameStart( proto.set_on_time_finish(onTimeFinish); proto.set_gpu_composition(gpuComposition); proto.set_jank_type(jankType); + proto.set_jank_severity_type(jankSeverityType); proto.set_prediction_type(predictionType); proto.set_is_buffer(isBuffer); return proto; @@ -1002,6 +1019,8 @@ void validateTraceEvent(const ProtoActualDisplayFrameStart& received, EXPECT_EQ(received.gpu_composition(), source.gpu_composition()); ASSERT_TRUE(received.has_jank_type()); EXPECT_EQ(received.jank_type(), source.jank_type()); + ASSERT_TRUE(received.has_jank_severity_type()); + EXPECT_EQ(received.jank_severity_type(), source.jank_severity_type()); ASSERT_TRUE(received.has_prediction_type()); EXPECT_EQ(received.prediction_type(), source.prediction_type()); } @@ -1049,6 +1068,8 @@ void validateTraceEvent(const ProtoActualSurfaceFrameStart& received, EXPECT_EQ(received.gpu_composition(), source.gpu_composition()); ASSERT_TRUE(received.has_jank_type()); EXPECT_EQ(received.jank_type(), source.jank_type()); + ASSERT_TRUE(received.has_jank_severity_type()); + EXPECT_EQ(received.jank_severity_type(), source.jank_severity_type()); ASSERT_TRUE(received.has_prediction_type()); EXPECT_EQ(received.prediction_type(), source.prediction_type()); ASSERT_TRUE(received.has_is_buffer()); @@ -1116,6 +1137,7 @@ TEST_F(FrameTimelineTest, traceDisplayFrameSkipped) { createProtoActualDisplayFrameStart(traceCookie + 9, 0, kSurfaceFlingerPid, FrameTimelineEvent::PRESENT_DROPPED, true, false, FrameTimelineEvent::JANK_DROPPED, + FrameTimelineEvent::SEVERITY_NONE, FrameTimelineEvent::PREDICTION_VALID); auto protoSkippedActualDisplayFrameEnd = createProtoFrameEnd(traceCookie + 9); @@ -1176,6 +1198,7 @@ TEST_F(FrameTimelineTest, traceDisplayFrame_emitsValidTracePacket) { kSurfaceFlingerPid, FrameTimelineEvent::PRESENT_ON_TIME, true, false, FrameTimelineEvent::JANK_NONE, + FrameTimelineEvent::SEVERITY_NONE, FrameTimelineEvent::PREDICTION_VALID); auto protoActualDisplayFrameEnd = createProtoFrameEnd(traceCookie + 2); @@ -1255,6 +1278,7 @@ TEST_F(FrameTimelineTest, traceDisplayFrame_predictionExpiredDoesNotTraceExpecte kSurfaceFlingerPid, FrameTimelineEvent::PRESENT_UNSPECIFIED, false, false, FrameTimelineEvent::JANK_UNKNOWN, + FrameTimelineEvent::SEVERITY_UNKNOWN, FrameTimelineEvent::PREDICTION_EXPIRED); auto protoActualDisplayFrameEnd = createProtoFrameEnd(traceCookie + 1); @@ -1330,6 +1354,7 @@ TEST_F(FrameTimelineTest, traceSurfaceFrame_emitsValidTracePacket) { displayFrameToken1, sPidOne, sLayerNameOne, FrameTimelineEvent::PRESENT_DROPPED, true, false, FrameTimelineEvent::JANK_DROPPED, + FrameTimelineEvent::SEVERITY_UNKNOWN, FrameTimelineEvent::PREDICTION_VALID, true); auto protoDroppedSurfaceFrameActualEnd = createProtoFrameEnd(traceCookie + 2); @@ -1342,6 +1367,7 @@ TEST_F(FrameTimelineTest, traceSurfaceFrame_emitsValidTracePacket) { displayFrameToken1, sPidOne, sLayerNameOne, FrameTimelineEvent::PRESENT_ON_TIME, true, false, FrameTimelineEvent::JANK_NONE, + FrameTimelineEvent::SEVERITY_NONE, FrameTimelineEvent::PREDICTION_VALID, true); auto protoPresentedSurfaceFrameActualEnd = createProtoFrameEnd(traceCookie + 4); @@ -1488,6 +1514,7 @@ TEST_F(FrameTimelineTest, traceSurfaceFrame_predictionExpiredIsAppMissedDeadline displayFrameToken, sPidOne, sLayerNameOne, FrameTimelineEvent::PRESENT_UNSPECIFIED, false, false, FrameTimelineEvent::JANK_APP_DEADLINE_MISSED, + FrameTimelineEvent::SEVERITY_UNKNOWN, FrameTimelineEvent::PREDICTION_EXPIRED, true); auto protoActualSurfaceFrameEnd = createProtoFrameEnd(traceCookie + 1); @@ -1565,6 +1592,7 @@ TEST_F(FrameTimelineTest, traceSurfaceFrame_predictionExpiredDroppedFramesTraced displayFrameToken, sPidOne, sLayerNameOne, FrameTimelineEvent::PRESENT_DROPPED, false, false, FrameTimelineEvent::JANK_DROPPED, + FrameTimelineEvent::SEVERITY_UNKNOWN, FrameTimelineEvent::PREDICTION_EXPIRED, true); auto protoActualSurfaceFrameEnd = createProtoFrameEnd(traceCookie + 1); @@ -1643,6 +1671,7 @@ TEST_F(FrameTimelineTest, jankClassification_presentOnTimeDoesNotClassify) { EXPECT_EQ(displayFrame->getFramePresentMetadata(), FramePresentMetadata::OnTimePresent); EXPECT_EQ(displayFrame->getFrameReadyMetadata(), FrameReadyMetadata::OnTimeFinish); EXPECT_EQ(displayFrame->getJankType(), JankType::None); + EXPECT_EQ(displayFrame->getJankSeverityType(), JankSeverityType::None); } TEST_F(FrameTimelineTest, jankClassification_displayFrameOnTimeFinishEarlyPresent) { @@ -1669,6 +1698,7 @@ TEST_F(FrameTimelineTest, jankClassification_displayFrameOnTimeFinishEarlyPresen EXPECT_EQ(displayFrame->getFramePresentMetadata(), FramePresentMetadata::EarlyPresent); EXPECT_EQ(displayFrame->getFrameReadyMetadata(), FrameReadyMetadata::OnTimeFinish); EXPECT_EQ(displayFrame->getJankType(), JankType::SurfaceFlingerScheduling); + EXPECT_EQ(displayFrame->getJankSeverityType(), JankSeverityType::Partial); // Fences for the second frame haven't been flushed yet, so it should be 0 auto displayFrame2 = getDisplayFrame(1); @@ -1682,6 +1712,7 @@ TEST_F(FrameTimelineTest, jankClassification_displayFrameOnTimeFinishEarlyPresen EXPECT_EQ(displayFrame2->getFramePresentMetadata(), FramePresentMetadata::EarlyPresent); EXPECT_EQ(displayFrame2->getFrameReadyMetadata(), FrameReadyMetadata::OnTimeFinish); EXPECT_EQ(displayFrame2->getJankType(), JankType::PredictionError); + EXPECT_EQ(displayFrame->getJankSeverityType(), JankSeverityType::Partial); } TEST_F(FrameTimelineTest, jankClassification_displayFrameOnTimeFinishLatePresent) { @@ -1708,6 +1739,7 @@ TEST_F(FrameTimelineTest, jankClassification_displayFrameOnTimeFinishLatePresent EXPECT_EQ(displayFrame->getFramePresentMetadata(), FramePresentMetadata::LatePresent); EXPECT_EQ(displayFrame->getFrameReadyMetadata(), FrameReadyMetadata::OnTimeFinish); EXPECT_EQ(displayFrame->getJankType(), JankType::DisplayHAL); + EXPECT_EQ(displayFrame->getJankSeverityType(), JankSeverityType::Partial); // Fences for the second frame haven't been flushed yet, so it should be 0 auto displayFrame2 = getDisplayFrame(1); @@ -1722,6 +1754,7 @@ TEST_F(FrameTimelineTest, jankClassification_displayFrameOnTimeFinishLatePresent EXPECT_EQ(displayFrame2->getFramePresentMetadata(), FramePresentMetadata::LatePresent); EXPECT_EQ(displayFrame2->getFrameReadyMetadata(), FrameReadyMetadata::OnTimeFinish); EXPECT_EQ(displayFrame2->getJankType(), JankType::PredictionError); + EXPECT_EQ(displayFrame->getJankSeverityType(), JankSeverityType::Partial); } TEST_F(FrameTimelineTest, jankClassification_displayFrameLateFinishEarlyPresent) { @@ -1744,6 +1777,7 @@ TEST_F(FrameTimelineTest, jankClassification_displayFrameLateFinishEarlyPresent) EXPECT_EQ(displayFrame->getFramePresentMetadata(), FramePresentMetadata::EarlyPresent); EXPECT_EQ(displayFrame->getFrameReadyMetadata(), FrameReadyMetadata::LateFinish); EXPECT_EQ(displayFrame->getJankType(), JankType::SurfaceFlingerScheduling); + EXPECT_EQ(displayFrame->getJankSeverityType(), JankSeverityType::Full); } TEST_F(FrameTimelineTest, jankClassification_displayFrameLateFinishLatePresent) { @@ -1789,6 +1823,7 @@ TEST_F(FrameTimelineTest, jankClassification_displayFrameLateFinishLatePresent) EXPECT_EQ(displayFrame0->getFramePresentMetadata(), FramePresentMetadata::LatePresent); EXPECT_EQ(displayFrame0->getFrameReadyMetadata(), FrameReadyMetadata::LateFinish); EXPECT_EQ(displayFrame0->getJankType(), JankType::SurfaceFlingerGpuDeadlineMissed); + EXPECT_EQ(displayFrame0->getJankSeverityType(), JankSeverityType::Full); // case 3 - cpu time = 86 - 82 = 4, vsync period = 30 mFrameTimeline->setSfWakeUp(sfToken3, 106, RR_30, RR_30); @@ -1803,6 +1838,7 @@ TEST_F(FrameTimelineTest, jankClassification_displayFrameLateFinishLatePresent) EXPECT_EQ(displayFrame1->getFramePresentMetadata(), FramePresentMetadata::LatePresent); EXPECT_EQ(displayFrame1->getFrameReadyMetadata(), FrameReadyMetadata::LateFinish); EXPECT_EQ(displayFrame1->getJankType(), JankType::SurfaceFlingerGpuDeadlineMissed); + EXPECT_EQ(displayFrame1->getJankSeverityType(), JankSeverityType::Full); // case 4 - cpu time = 86 - 82 = 4, vsync period = 30 mFrameTimeline->setSfWakeUp(sfToken4, 120, RR_30, RR_30); @@ -1817,6 +1853,7 @@ TEST_F(FrameTimelineTest, jankClassification_displayFrameLateFinishLatePresent) EXPECT_EQ(displayFrame2->getFramePresentMetadata(), FramePresentMetadata::LatePresent); EXPECT_EQ(displayFrame2->getFrameReadyMetadata(), FrameReadyMetadata::LateFinish); EXPECT_EQ(displayFrame2->getJankType(), JankType::SurfaceFlingerStuffing); + EXPECT_EQ(displayFrame2->getJankSeverityType(), JankSeverityType::Full); addEmptyDisplayFrame(); @@ -1825,6 +1862,7 @@ TEST_F(FrameTimelineTest, jankClassification_displayFrameLateFinishLatePresent) EXPECT_EQ(displayFrame3->getFramePresentMetadata(), FramePresentMetadata::LatePresent); EXPECT_EQ(displayFrame3->getFrameReadyMetadata(), FrameReadyMetadata::LateFinish); EXPECT_EQ(displayFrame3->getJankType(), JankType::SurfaceFlingerGpuDeadlineMissed); + EXPECT_EQ(displayFrame3->getJankSeverityType(), JankSeverityType::Full); } TEST_F(FrameTimelineTest, jankClassification_surfaceFrameOnTimeFinishEarlyPresent) { @@ -1877,12 +1915,14 @@ TEST_F(FrameTimelineTest, jankClassification_surfaceFrameOnTimeFinishEarlyPresen EXPECT_EQ(displayFrame1->getFramePresentMetadata(), FramePresentMetadata::EarlyPresent); EXPECT_EQ(displayFrame1->getFrameReadyMetadata(), FrameReadyMetadata::OnTimeFinish); EXPECT_EQ(displayFrame1->getJankType(), JankType::SurfaceFlingerScheduling); + EXPECT_EQ(displayFrame1->getJankSeverityType(), JankSeverityType::Partial); actuals1 = presentedSurfaceFrame1.getActuals(); EXPECT_EQ(actuals1.presentTime, 30); EXPECT_EQ(presentedSurfaceFrame1.getFramePresentMetadata(), FramePresentMetadata::EarlyPresent); EXPECT_EQ(presentedSurfaceFrame1.getFrameReadyMetadata(), FrameReadyMetadata::OnTimeFinish); EXPECT_EQ(presentedSurfaceFrame1.getJankType(), JankType::SurfaceFlingerScheduling); + EXPECT_EQ(presentedSurfaceFrame1.getJankSeverityType(), JankSeverityType::Partial); // Fences for the second frame haven't been flushed yet, so it should be 0 presentFence2->signalForTest(65); @@ -1905,12 +1945,14 @@ TEST_F(FrameTimelineTest, jankClassification_surfaceFrameOnTimeFinishEarlyPresen EXPECT_EQ(displayFrame2->getFramePresentMetadata(), FramePresentMetadata::EarlyPresent); EXPECT_EQ(displayFrame2->getFrameReadyMetadata(), FrameReadyMetadata::OnTimeFinish); EXPECT_EQ(displayFrame2->getJankType(), JankType::PredictionError); + EXPECT_EQ(displayFrame2->getJankSeverityType(), JankSeverityType::Partial); actuals2 = presentedSurfaceFrame2.getActuals(); EXPECT_EQ(actuals2.presentTime, 65); EXPECT_EQ(presentedSurfaceFrame2.getFramePresentMetadata(), FramePresentMetadata::EarlyPresent); EXPECT_EQ(presentedSurfaceFrame2.getFrameReadyMetadata(), FrameReadyMetadata::OnTimeFinish); EXPECT_EQ(presentedSurfaceFrame2.getJankType(), JankType::PredictionError); + EXPECT_EQ(presentedSurfaceFrame2.getJankSeverityType(), JankSeverityType::Partial); } TEST_F(FrameTimelineTest, jankClassification_surfaceFrameOnTimeFinishLatePresent) { @@ -1963,12 +2005,14 @@ TEST_F(FrameTimelineTest, jankClassification_surfaceFrameOnTimeFinishLatePresent EXPECT_EQ(displayFrame1->getFramePresentMetadata(), FramePresentMetadata::LatePresent); EXPECT_EQ(displayFrame1->getFrameReadyMetadata(), FrameReadyMetadata::OnTimeFinish); EXPECT_EQ(displayFrame1->getJankType(), JankType::DisplayHAL); + EXPECT_EQ(displayFrame1->getJankSeverityType(), JankSeverityType::Partial); actuals1 = presentedSurfaceFrame1.getActuals(); EXPECT_EQ(actuals1.presentTime, 50); EXPECT_EQ(presentedSurfaceFrame1.getFramePresentMetadata(), FramePresentMetadata::LatePresent); EXPECT_EQ(presentedSurfaceFrame1.getFrameReadyMetadata(), FrameReadyMetadata::OnTimeFinish); EXPECT_EQ(presentedSurfaceFrame1.getJankType(), JankType::DisplayHAL); + EXPECT_EQ(presentedSurfaceFrame1.getJankSeverityType(), JankSeverityType::Partial); // Fences for the second frame haven't been flushed yet, so it should be 0 presentFence2->signalForTest(86); @@ -1991,12 +2035,14 @@ TEST_F(FrameTimelineTest, jankClassification_surfaceFrameOnTimeFinishLatePresent EXPECT_EQ(displayFrame2->getFramePresentMetadata(), FramePresentMetadata::LatePresent); EXPECT_EQ(displayFrame2->getFrameReadyMetadata(), FrameReadyMetadata::OnTimeFinish); EXPECT_EQ(displayFrame2->getJankType(), JankType::PredictionError); + EXPECT_EQ(displayFrame2->getJankSeverityType(), JankSeverityType::Full); actuals2 = presentedSurfaceFrame2.getActuals(); EXPECT_EQ(actuals2.presentTime, 86); EXPECT_EQ(presentedSurfaceFrame2.getFramePresentMetadata(), FramePresentMetadata::LatePresent); EXPECT_EQ(presentedSurfaceFrame2.getFrameReadyMetadata(), FrameReadyMetadata::OnTimeFinish); EXPECT_EQ(presentedSurfaceFrame2.getJankType(), JankType::PredictionError); + EXPECT_EQ(presentedSurfaceFrame2.getJankSeverityType(), JankSeverityType::Full); } TEST_F(FrameTimelineTest, jankClassification_surfaceFrameLateFinishEarlyPresent) { @@ -2033,12 +2079,14 @@ TEST_F(FrameTimelineTest, jankClassification_surfaceFrameLateFinishEarlyPresent) EXPECT_EQ(displayFrame1->getFramePresentMetadata(), FramePresentMetadata::OnTimePresent); EXPECT_EQ(displayFrame1->getFrameReadyMetadata(), FrameReadyMetadata::OnTimeFinish); EXPECT_EQ(displayFrame1->getJankType(), JankType::None); + EXPECT_EQ(displayFrame1->getJankSeverityType(), JankSeverityType::None); actuals1 = presentedSurfaceFrame1.getActuals(); EXPECT_EQ(actuals1.presentTime, 50); EXPECT_EQ(presentedSurfaceFrame1.getFramePresentMetadata(), FramePresentMetadata::EarlyPresent); EXPECT_EQ(presentedSurfaceFrame1.getFrameReadyMetadata(), FrameReadyMetadata::LateFinish); EXPECT_EQ(presentedSurfaceFrame1.getJankType(), JankType::Unknown); + EXPECT_EQ(presentedSurfaceFrame1.getJankSeverityType(), JankSeverityType::Partial); } TEST_F(FrameTimelineTest, jankClassification_surfaceFrameLateFinishLatePresent) { @@ -2095,12 +2143,14 @@ TEST_F(FrameTimelineTest, jankClassification_surfaceFrameLateFinishLatePresent) EXPECT_EQ(displayFrame1->getFramePresentMetadata(), FramePresentMetadata::OnTimePresent); EXPECT_EQ(displayFrame1->getFrameReadyMetadata(), FrameReadyMetadata::OnTimeFinish); EXPECT_EQ(displayFrame1->getJankType(), JankType::None); + EXPECT_EQ(displayFrame1->getJankSeverityType(), JankSeverityType::None); actuals1 = presentedSurfaceFrame1.getActuals(); EXPECT_EQ(actuals1.presentTime, 40); EXPECT_EQ(presentedSurfaceFrame1.getFramePresentMetadata(), FramePresentMetadata::LatePresent); EXPECT_EQ(presentedSurfaceFrame1.getFrameReadyMetadata(), FrameReadyMetadata::LateFinish); EXPECT_EQ(presentedSurfaceFrame1.getJankType(), JankType::AppDeadlineMissed); + EXPECT_EQ(presentedSurfaceFrame1.getJankSeverityType(), JankSeverityType::Partial); // Fences for the second frame haven't been flushed yet, so it should be 0 presentFence2->signalForTest(60); @@ -2115,6 +2165,7 @@ TEST_F(FrameTimelineTest, jankClassification_surfaceFrameLateFinishLatePresent) EXPECT_EQ(displayFrame2->getFramePresentMetadata(), FramePresentMetadata::LatePresent); EXPECT_EQ(displayFrame2->getFrameReadyMetadata(), FrameReadyMetadata::LateFinish); EXPECT_EQ(displayFrame2->getJankType(), JankType::SurfaceFlingerCpuDeadlineMissed); + EXPECT_EQ(displayFrame2->getJankSeverityType(), JankSeverityType::Partial); actuals2 = presentedSurfaceFrame2.getActuals(); EXPECT_EQ(actuals2.presentTime, 60); @@ -2122,6 +2173,7 @@ TEST_F(FrameTimelineTest, jankClassification_surfaceFrameLateFinishLatePresent) EXPECT_EQ(presentedSurfaceFrame2.getFrameReadyMetadata(), FrameReadyMetadata::LateFinish); EXPECT_EQ(presentedSurfaceFrame2.getJankType(), JankType::SurfaceFlingerCpuDeadlineMissed | JankType::AppDeadlineMissed); + EXPECT_EQ(presentedSurfaceFrame2.getJankSeverityType(), JankSeverityType::Partial); } TEST_F(FrameTimelineTest, jankClassification_multiJankBufferStuffingAndAppDeadlineMissed) { @@ -2181,10 +2233,12 @@ TEST_F(FrameTimelineTest, jankClassification_multiJankBufferStuffingAndAppDeadli EXPECT_EQ(displayFrame1->getFramePresentMetadata(), FramePresentMetadata::OnTimePresent); EXPECT_EQ(displayFrame1->getFrameReadyMetadata(), FrameReadyMetadata::OnTimeFinish); EXPECT_EQ(displayFrame1->getJankType(), JankType::None); + EXPECT_EQ(displayFrame1->getJankSeverityType(), JankSeverityType::None); EXPECT_EQ(presentedSurfaceFrame1.getFramePresentMetadata(), FramePresentMetadata::LatePresent); EXPECT_EQ(presentedSurfaceFrame1.getFrameReadyMetadata(), FrameReadyMetadata::LateFinish); EXPECT_EQ(presentedSurfaceFrame1.getJankType(), JankType::AppDeadlineMissed); + EXPECT_EQ(presentedSurfaceFrame1.getJankSeverityType(), JankSeverityType::Full); // Fences for the second frame haven't been flushed yet, so it should be 0 EXPECT_EQ(displayFrame2->getActuals().presentTime, 0); @@ -2201,11 +2255,13 @@ TEST_F(FrameTimelineTest, jankClassification_multiJankBufferStuffingAndAppDeadli EXPECT_EQ(displayFrame2->getFramePresentMetadata(), FramePresentMetadata::OnTimePresent); EXPECT_EQ(displayFrame2->getFrameReadyMetadata(), FrameReadyMetadata::OnTimeFinish); EXPECT_EQ(displayFrame2->getJankType(), JankType::None); + EXPECT_EQ(displayFrame2->getJankSeverityType(), JankSeverityType::None); EXPECT_EQ(presentedSurfaceFrame2.getFramePresentMetadata(), FramePresentMetadata::LatePresent); EXPECT_EQ(presentedSurfaceFrame2.getFrameReadyMetadata(), FrameReadyMetadata::LateFinish); EXPECT_EQ(presentedSurfaceFrame2.getJankType(), JankType::AppDeadlineMissed | JankType::BufferStuffing); + EXPECT_EQ(presentedSurfaceFrame2.getJankSeverityType(), JankSeverityType::Full); } TEST_F(FrameTimelineTest, jankClassification_appDeadlineAdjustedForBufferStuffing) { @@ -2266,10 +2322,12 @@ TEST_F(FrameTimelineTest, jankClassification_appDeadlineAdjustedForBufferStuffin EXPECT_EQ(displayFrame1->getFramePresentMetadata(), FramePresentMetadata::OnTimePresent); EXPECT_EQ(displayFrame1->getFrameReadyMetadata(), FrameReadyMetadata::OnTimeFinish); EXPECT_EQ(displayFrame1->getJankType(), JankType::None); + EXPECT_EQ(displayFrame1->getJankSeverityType(), JankSeverityType::None); EXPECT_EQ(presentedSurfaceFrame1.getFramePresentMetadata(), FramePresentMetadata::LatePresent); EXPECT_EQ(presentedSurfaceFrame1.getFrameReadyMetadata(), FrameReadyMetadata::LateFinish); EXPECT_EQ(presentedSurfaceFrame1.getJankType(), JankType::AppDeadlineMissed); + EXPECT_EQ(presentedSurfaceFrame1.getJankSeverityType(), JankSeverityType::Full); // Fences for the second frame haven't been flushed yet, so it should be 0 EXPECT_EQ(displayFrame2->getActuals().presentTime, 0); @@ -2286,10 +2344,12 @@ TEST_F(FrameTimelineTest, jankClassification_appDeadlineAdjustedForBufferStuffin EXPECT_EQ(displayFrame2->getFramePresentMetadata(), FramePresentMetadata::OnTimePresent); EXPECT_EQ(displayFrame2->getFrameReadyMetadata(), FrameReadyMetadata::OnTimeFinish); EXPECT_EQ(displayFrame2->getJankType(), JankType::None); + EXPECT_EQ(displayFrame2->getJankSeverityType(), JankSeverityType::None); EXPECT_EQ(presentedSurfaceFrame2.getFramePresentMetadata(), FramePresentMetadata::LatePresent); EXPECT_EQ(presentedSurfaceFrame2.getFrameReadyMetadata(), FrameReadyMetadata::OnTimeFinish); EXPECT_EQ(presentedSurfaceFrame2.getJankType(), JankType::BufferStuffing); + EXPECT_EQ(presentedSurfaceFrame2.getJankSeverityType(), JankSeverityType::Full); } TEST_F(FrameTimelineTest, jankClassification_displayFrameLateFinishLatePresent_GpuAndCpuMiss) { @@ -2317,6 +2377,7 @@ TEST_F(FrameTimelineTest, jankClassification_displayFrameLateFinishLatePresent_G EXPECT_EQ(displayFrame->getFramePresentMetadata(), FramePresentMetadata::LatePresent); EXPECT_EQ(displayFrame->getFrameReadyMetadata(), FrameReadyMetadata::LateFinish); EXPECT_EQ(displayFrame->getJankType(), JankType::SurfaceFlingerGpuDeadlineMissed); + EXPECT_EQ(displayFrame->getJankSeverityType(), JankSeverityType::Full); // Case 2: No GPU fence so it will not use GPU composition. mFrameTimeline->setSfWakeUp(sfToken2, 52, RR_30, RR_30); @@ -2334,6 +2395,7 @@ TEST_F(FrameTimelineTest, jankClassification_displayFrameLateFinishLatePresent_G EXPECT_EQ(displayFrame2->getFramePresentMetadata(), FramePresentMetadata::LatePresent); EXPECT_EQ(displayFrame2->getFrameReadyMetadata(), FrameReadyMetadata::LateFinish); EXPECT_EQ(displayFrame2->getJankType(), JankType::SurfaceFlingerCpuDeadlineMissed); + EXPECT_EQ(displayFrame2->getJankSeverityType(), JankSeverityType::Full); } TEST_F(FrameTimelineTest, jankClassification_presentFenceError) { @@ -2364,6 +2426,7 @@ TEST_F(FrameTimelineTest, jankClassification_presentFenceError) { EXPECT_EQ(displayFrame->getFramePresentMetadata(), FramePresentMetadata::UnknownPresent); EXPECT_EQ(displayFrame->getFrameReadyMetadata(), FrameReadyMetadata::UnknownFinish); EXPECT_EQ(displayFrame->getJankType(), JankType::Unknown | JankType::DisplayHAL); + EXPECT_EQ(displayFrame->getJankSeverityType(), JankSeverityType::Unknown); } { auto displayFrame = getDisplayFrame(1); @@ -2371,6 +2434,7 @@ TEST_F(FrameTimelineTest, jankClassification_presentFenceError) { EXPECT_EQ(displayFrame->getFramePresentMetadata(), FramePresentMetadata::UnknownPresent); EXPECT_EQ(displayFrame->getFrameReadyMetadata(), FrameReadyMetadata::UnknownFinish); EXPECT_EQ(displayFrame->getJankType(), JankType::Unknown | JankType::DisplayHAL); + EXPECT_EQ(displayFrame->getJankSeverityType(), JankSeverityType::Unknown); } { auto displayFrame = getDisplayFrame(2); @@ -2378,6 +2442,7 @@ TEST_F(FrameTimelineTest, jankClassification_presentFenceError) { EXPECT_EQ(displayFrame->getFramePresentMetadata(), FramePresentMetadata::OnTimePresent); EXPECT_EQ(displayFrame->getFrameReadyMetadata(), FrameReadyMetadata::OnTimeFinish); EXPECT_EQ(displayFrame->getJankType(), JankType::None); + EXPECT_EQ(displayFrame->getJankSeverityType(), JankSeverityType::None); } } |