Update jank reasons in timestats
This change populates the following jank reasons into timestats
* SF Scheduling
* Prediction Error
* Buffer Stuffing
Bug: 177944020
Test: TimeStatsTest, FrameTimelineTest
Change-Id: Ibd72e7b0055ccd505871b419f77ff67b7bc874c8
diff --git a/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp b/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp
index b3ab8f1..f222129 100644
--- a/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp
+++ b/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp
@@ -155,12 +155,9 @@
uint32_t* maxDisplayFrames;
nsecs_t maxTokenRetentionTime;
static constexpr pid_t kSurfaceFlingerPid = 666;
- static constexpr nsecs_t kPresentThreshold =
- std::chrono::duration_cast<std::chrono::nanoseconds>(2ns).count();
- static constexpr nsecs_t kDeadlineThreshold =
- std::chrono::duration_cast<std::chrono::nanoseconds>(2ns).count();
- static constexpr nsecs_t kStartThreshold =
- std::chrono::duration_cast<std::chrono::nanoseconds>(2ns).count();
+ static constexpr nsecs_t kPresentThreshold = std::chrono::nanoseconds(2ns).count();
+ static constexpr nsecs_t kDeadlineThreshold = std::chrono::nanoseconds(2ns).count();
+ static constexpr nsecs_t kStartThreshold = std::chrono::nanoseconds(2ns).count();
static constexpr JankClassificationThresholds kTestThresholds{kPresentThreshold,
kDeadlineThreshold,
kStartThreshold};
@@ -443,28 +440,21 @@
0}));
auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
int64_t surfaceFrameToken1 = mTokenManager->generateTokenForPredictions(
- {std::chrono::duration_cast<std::chrono::nanoseconds>(10ms).count(),
- std::chrono::duration_cast<std::chrono::nanoseconds>(20ms).count(),
- std::chrono::duration_cast<std::chrono::nanoseconds>(60ms).count()});
+ {std::chrono::nanoseconds(10ms).count(), std::chrono::nanoseconds(20ms).count(),
+ std::chrono::nanoseconds(60ms).count()});
int64_t sfToken1 = mTokenManager->generateTokenForPredictions(
- {std::chrono::duration_cast<std::chrono::nanoseconds>(52ms).count(),
- std::chrono::duration_cast<std::chrono::nanoseconds>(56ms).count(),
- std::chrono::duration_cast<std::chrono::nanoseconds>(60ms).count()});
+ {std::chrono::nanoseconds(52ms).count(), std::chrono::nanoseconds(56ms).count(),
+ std::chrono::nanoseconds(60ms).count()});
auto surfaceFrame1 =
mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne,
sUidOne, sLayerNameOne, sLayerNameOne);
- mFrameTimeline->setSfWakeUp(sfToken1,
- std::chrono::duration_cast<std::chrono::nanoseconds>(52ms).count(),
- refreshRate);
- surfaceFrame1->setAcquireFenceTime(
- std::chrono::duration_cast<std::chrono::nanoseconds>(20ms).count());
+ mFrameTimeline->setSfWakeUp(sfToken1, std::chrono::nanoseconds(52ms).count(), refreshRate);
+ surfaceFrame1->setAcquireFenceTime(std::chrono::nanoseconds(20ms).count());
surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented);
mFrameTimeline->addSurfaceFrame(surfaceFrame1);
- presentFence1->signalForTest(
- std::chrono::duration_cast<std::chrono::nanoseconds>(70ms).count());
+ presentFence1->signalForTest(std::chrono::nanoseconds(70ms).count());
- mFrameTimeline->setSfPresent(std::chrono::duration_cast<std::chrono::nanoseconds>(59ms).count(),
- presentFence1);
+ mFrameTimeline->setSfPresent(std::chrono::nanoseconds(59ms).count(), presentFence1);
}
TEST_F(FrameTimelineTest, presentFenceSignaled_reportsDisplayMiss) {
@@ -476,27 +466,20 @@
auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
int64_t surfaceFrameToken1 = mTokenManager->generateTokenForPredictions(
- {std::chrono::duration_cast<std::chrono::nanoseconds>(10ms).count(),
- std::chrono::duration_cast<std::chrono::nanoseconds>(20ms).count(),
- std::chrono::duration_cast<std::chrono::nanoseconds>(60ms).count()});
+ {std::chrono::nanoseconds(10ms).count(), std::chrono::nanoseconds(20ms).count(),
+ std::chrono::nanoseconds(60ms).count()});
int64_t sfToken1 = mTokenManager->generateTokenForPredictions(
- {std::chrono::duration_cast<std::chrono::nanoseconds>(52ms).count(),
- std::chrono::duration_cast<std::chrono::nanoseconds>(56ms).count(),
- std::chrono::duration_cast<std::chrono::nanoseconds>(60ms).count()});
+ {std::chrono::nanoseconds(52ms).count(), std::chrono::nanoseconds(56ms).count(),
+ std::chrono::nanoseconds(60ms).count()});
auto surfaceFrame1 =
mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne,
sUidOne, sLayerNameOne, sLayerNameOne);
- mFrameTimeline->setSfWakeUp(sfToken1,
- std::chrono::duration_cast<std::chrono::nanoseconds>(52ms).count(),
- refreshRate);
+ mFrameTimeline->setSfWakeUp(sfToken1, std::chrono::nanoseconds(52ms).count(), refreshRate);
surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented);
- surfaceFrame1->setAcquireFenceTime(
- std::chrono::duration_cast<std::chrono::nanoseconds>(20ms).count());
+ surfaceFrame1->setAcquireFenceTime(std::chrono::nanoseconds(20ms).count());
mFrameTimeline->addSurfaceFrame(surfaceFrame1);
- presentFence1->signalForTest(
- std::chrono::duration_cast<std::chrono::nanoseconds>(90ms).count());
- mFrameTimeline->setSfPresent(std::chrono::duration_cast<std::chrono::nanoseconds>(56ms).count(),
- presentFence1);
+ presentFence1->signalForTest(std::chrono::nanoseconds(90ms).count());
+ mFrameTimeline->setSfPresent(std::chrono::nanoseconds(56ms).count(), presentFence1);
EXPECT_EQ(surfaceFrame1->getJankType(), JankType::DisplayHAL);
}
@@ -511,32 +494,120 @@
.count()}));
auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
int64_t surfaceFrameToken1 = mTokenManager->generateTokenForPredictions(
- {std::chrono::duration_cast<std::chrono::nanoseconds>(10ms).count(),
- std::chrono::duration_cast<std::chrono::nanoseconds>(20ms).count(),
- std::chrono::duration_cast<std::chrono::nanoseconds>(60ms).count()});
+ {std::chrono::nanoseconds(10ms).count(), std::chrono::nanoseconds(20ms).count(),
+ std::chrono::nanoseconds(60ms).count()});
int64_t sfToken1 = mTokenManager->generateTokenForPredictions(
- {std::chrono::duration_cast<std::chrono::nanoseconds>(82ms).count(),
- std::chrono::duration_cast<std::chrono::nanoseconds>(86ms).count(),
- std::chrono::duration_cast<std::chrono::nanoseconds>(90ms).count()});
+ {std::chrono::nanoseconds(82ms).count(), std::chrono::nanoseconds(86ms).count(),
+ std::chrono::nanoseconds(90ms).count()});
auto surfaceFrame1 =
mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne,
sUidOne, sLayerNameOne, sLayerNameOne);
- surfaceFrame1->setAcquireFenceTime(
- std::chrono::duration_cast<std::chrono::nanoseconds>(45ms).count());
- mFrameTimeline->setSfWakeUp(sfToken1,
- std::chrono::duration_cast<std::chrono::nanoseconds>(52ms).count(),
- refreshRate);
+ surfaceFrame1->setAcquireFenceTime(std::chrono::nanoseconds(45ms).count());
+ mFrameTimeline->setSfWakeUp(sfToken1, std::chrono::nanoseconds(52ms).count(), refreshRate);
surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented);
mFrameTimeline->addSurfaceFrame(surfaceFrame1);
- presentFence1->signalForTest(
- std::chrono::duration_cast<std::chrono::nanoseconds>(90ms).count());
- mFrameTimeline->setSfPresent(std::chrono::duration_cast<std::chrono::nanoseconds>(86ms).count(),
- presentFence1);
+ presentFence1->signalForTest(std::chrono::nanoseconds(90ms).count());
+ mFrameTimeline->setSfPresent(std::chrono::nanoseconds(86ms).count(), presentFence1);
EXPECT_EQ(surfaceFrame1->getJankType(), JankType::AppDeadlineMissed);
}
+TEST_F(FrameTimelineTest, presentFenceSignaled_reportsSfScheduling) {
+ Fps refreshRate = Fps::fromPeriodNsecs(std::chrono::nanoseconds(32ms).count());
+ EXPECT_CALL(*mTimeStats,
+ incrementJankyFrames(
+ TimeStats::JankyFramesInfo{refreshRate, std::nullopt, sUidOne,
+ sLayerNameOne,
+ JankType::SurfaceFlingerScheduling, 0, 0,
+ std::chrono::duration_cast<
+ std::chrono::nanoseconds>(-10ms)
+ .count()}));
+ auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
+ int64_t surfaceFrameToken1 = mTokenManager->generateTokenForPredictions(
+ {std::chrono::nanoseconds(40ms).count(), std::chrono::nanoseconds(60ms).count(),
+ std::chrono::nanoseconds(92ms).count()});
+ int64_t sfToken1 = mTokenManager->generateTokenForPredictions(
+ {std::chrono::nanoseconds(52ms).count(), std::chrono::nanoseconds(56ms).count(),
+ std::chrono::nanoseconds(60ms).count()});
+ auto surfaceFrame1 =
+ mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne,
+ sUidOne, sLayerNameOne, sLayerNameOne);
+ surfaceFrame1->setAcquireFenceTime(std::chrono::nanoseconds(50ms).count());
+ mFrameTimeline->setSfWakeUp(sfToken1, std::chrono::nanoseconds(52ms).count(), refreshRate);
+
+ surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented);
+ mFrameTimeline->addSurfaceFrame(surfaceFrame1);
+ presentFence1->signalForTest(std::chrono::nanoseconds(60ms).count());
+ mFrameTimeline->setSfPresent(std::chrono::nanoseconds(56ms).count(), presentFence1);
+
+ EXPECT_EQ(surfaceFrame1->getJankType(), JankType::SurfaceFlingerScheduling);
+}
+
+TEST_F(FrameTimelineTest, presentFenceSignaled_reportsSfPredictionError) {
+ Fps refreshRate = Fps(16.66f);
+ EXPECT_CALL(*mTimeStats,
+ incrementJankyFrames(
+ TimeStats::JankyFramesInfo{refreshRate, std::nullopt, sUidOne,
+ sLayerNameOne, JankType::PredictionError, 0,
+ std::chrono::duration_cast<
+ std::chrono::nanoseconds>(5ms)
+ .count(),
+ 0}));
+ auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
+ int64_t surfaceFrameToken1 = mTokenManager->generateTokenForPredictions(
+ {std::chrono::nanoseconds(30ms).count(), std::chrono::nanoseconds(40ms).count(),
+ std::chrono::nanoseconds(60ms).count()});
+ int64_t sfToken1 = mTokenManager->generateTokenForPredictions(
+ {std::chrono::nanoseconds(52ms).count(), std::chrono::nanoseconds(56ms).count(),
+ std::chrono::nanoseconds(60ms).count()});
+ auto surfaceFrame1 =
+ mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne,
+ sUidOne, sLayerNameOne, sLayerNameOne);
+ surfaceFrame1->setAcquireFenceTime(std::chrono::nanoseconds(40ms).count());
+ mFrameTimeline->setSfWakeUp(sfToken1, std::chrono::nanoseconds(52ms).count(), refreshRate);
+
+ surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented);
+ mFrameTimeline->addSurfaceFrame(surfaceFrame1);
+ presentFence1->signalForTest(std::chrono::nanoseconds(65ms).count());
+ mFrameTimeline->setSfPresent(std::chrono::nanoseconds(56ms).count(), presentFence1);
+
+ EXPECT_EQ(surfaceFrame1->getJankType(), JankType::PredictionError);
+}
+
+TEST_F(FrameTimelineTest, presentFenceSignaled_reportsAppBufferStuffing) {
+ Fps refreshRate = Fps::fromPeriodNsecs(std::chrono::nanoseconds(32ms).count());
+ EXPECT_CALL(*mTimeStats,
+ incrementJankyFrames(
+ TimeStats::JankyFramesInfo{refreshRate, std::nullopt, sUidOne,
+ sLayerNameOne,
+ JankType::BufferStuffing |
+ JankType::SurfaceFlingerScheduling,
+ 0, 0, 0}));
+ auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
+ int64_t surfaceFrameToken1 = mTokenManager->generateTokenForPredictions(
+ {std::chrono::nanoseconds(30ms).count(), std::chrono::nanoseconds(40ms).count(),
+ std::chrono::nanoseconds(58ms).count()});
+ int64_t sfToken1 = mTokenManager->generateTokenForPredictions(
+ {std::chrono::nanoseconds(82ms).count(), std::chrono::nanoseconds(86ms).count(),
+ std::chrono::nanoseconds(90ms).count()});
+ auto surfaceFrame1 =
+ mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne,
+ sUidOne, sLayerNameOne, sLayerNameOne);
+ surfaceFrame1->setAcquireFenceTime(std::chrono::nanoseconds(40ms).count());
+ mFrameTimeline->setSfWakeUp(sfToken1, std::chrono::nanoseconds(82ms).count(), refreshRate);
+
+ surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented,
+ /*previousLatchTime*/
+ std::chrono::nanoseconds(56ms).count());
+ mFrameTimeline->addSurfaceFrame(surfaceFrame1);
+ presentFence1->signalForTest(std::chrono::nanoseconds(90ms).count());
+ mFrameTimeline->setSfPresent(std::chrono::nanoseconds(86ms).count(), presentFence1);
+
+ EXPECT_EQ(surfaceFrame1->getJankType(),
+ JankType::BufferStuffing | JankType::SurfaceFlingerScheduling);
+}
+
TEST_F(FrameTimelineTest, presentFenceSignaled_reportsAppMissWithRenderRate) {
Fps refreshRate = Fps(11.0);
Fps renderRate = Fps(30.0);
@@ -549,29 +620,22 @@
.count()}));
auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
int64_t surfaceFrameToken1 = mTokenManager->generateTokenForPredictions(
- {std::chrono::duration_cast<std::chrono::nanoseconds>(10ms).count(),
- std::chrono::duration_cast<std::chrono::nanoseconds>(20ms).count(),
- std::chrono::duration_cast<std::chrono::nanoseconds>(60ms).count()});
+ {std::chrono::nanoseconds(10ms).count(), std::chrono::nanoseconds(20ms).count(),
+ std::chrono::nanoseconds(60ms).count()});
int64_t sfToken1 = mTokenManager->generateTokenForPredictions(
- {std::chrono::duration_cast<std::chrono::nanoseconds>(82ms).count(),
- std::chrono::duration_cast<std::chrono::nanoseconds>(86ms).count(),
- std::chrono::duration_cast<std::chrono::nanoseconds>(90ms).count()});
+ {std::chrono::nanoseconds(82ms).count(), std::chrono::nanoseconds(86ms).count(),
+ std::chrono::nanoseconds(90ms).count()});
auto surfaceFrame1 =
mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne,
sUidOne, sLayerNameOne, sLayerNameOne);
- surfaceFrame1->setAcquireFenceTime(
- std::chrono::duration_cast<std::chrono::nanoseconds>(45ms).count());
- mFrameTimeline->setSfWakeUp(sfToken1,
- std::chrono::duration_cast<std::chrono::nanoseconds>(52ms).count(),
- refreshRate);
+ surfaceFrame1->setAcquireFenceTime(std::chrono::nanoseconds(45ms).count());
+ mFrameTimeline->setSfWakeUp(sfToken1, std::chrono::nanoseconds(52ms).count(), refreshRate);
surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented);
surfaceFrame1->setRenderRate(renderRate);
mFrameTimeline->addSurfaceFrame(surfaceFrame1);
- presentFence1->signalForTest(
- std::chrono::duration_cast<std::chrono::nanoseconds>(90ms).count());
- mFrameTimeline->setSfPresent(std::chrono::duration_cast<std::chrono::nanoseconds>(86ms).count(),
- presentFence1);
+ presentFence1->signalForTest(std::chrono::nanoseconds(90ms).count());
+ mFrameTimeline->setSfPresent(std::chrono::nanoseconds(86ms).count(), presentFence1);
EXPECT_EQ(surfaceFrame1->getJankType(), JankType::AppDeadlineMissed);
}