Loading services/surfaceflinger/TimeStats/TimeStats.cpp +9 −8 Original line number Diff line number Diff line Loading @@ -427,8 +427,8 @@ bool TimeStats::recordReadyLocked(int32_t layerId, TimeRecord* timeRecord) { return true; } static int32_t clampToSmallestBucket(Fps fps, size_t bucketWidth) { return (fps.getIntValue() / bucketWidth) * bucketWidth; static int32_t clampToNearestBucket(Fps fps, size_t bucketWidth) { return std::round(fps.getValue() / bucketWidth) * bucketWidth; } void TimeStats::flushAvailableRecordsToStatsLocked(int32_t layerId, Fps displayRefreshRate, Loading @@ -441,9 +441,9 @@ void TimeStats::flushAvailableRecordsToStatsLocked(int32_t layerId, Fps displayR TimeRecord& prevTimeRecord = layerRecord.prevTimeRecord; std::deque<TimeRecord>& timeRecords = layerRecord.timeRecords; const int32_t refreshRateBucket = clampToSmallestBucket(displayRefreshRate, REFRESH_RATE_BUCKET_WIDTH); clampToNearestBucket(displayRefreshRate, REFRESH_RATE_BUCKET_WIDTH); const int32_t renderRateBucket = clampToSmallestBucket(renderRate ? *renderRate : displayRefreshRate, clampToNearestBucket(renderRate ? *renderRate : displayRefreshRate, RENDER_RATE_BUCKET_WIDTH); while (!timeRecords.empty()) { if (!recordReadyLocked(layerId, &timeRecords[0])) break; Loading Loading @@ -799,9 +799,9 @@ void TimeStats::incrementJankyFrames(const JankyFramesInfo& info) { static const std::string kDefaultLayerName = "none"; const int32_t refreshRateBucket = clampToSmallestBucket(info.refreshRate, REFRESH_RATE_BUCKET_WIDTH); clampToNearestBucket(info.refreshRate, REFRESH_RATE_BUCKET_WIDTH); const int32_t renderRateBucket = clampToSmallestBucket(info.renderRate ? *info.renderRate : info.refreshRate, clampToNearestBucket(info.renderRate ? *info.renderRate : info.refreshRate, RENDER_RATE_BUCKET_WIDTH); const TimeStatsHelper::TimelineStatsKey timelineKey = {refreshRateBucket, renderRateBucket}; Loading Loading @@ -1021,6 +1021,7 @@ void TimeStats::disable() { void TimeStats::clearAll() { std::lock_guard<std::mutex> lock(mMutex); mTimeStats.stats.clear(); clearGlobalLocked(); clearLayersLocked(); } Loading services/surfaceflinger/tests/unittests/TimeStatsTest.cpp +42 −18 Original line number Diff line number Diff line Loading @@ -897,24 +897,24 @@ TEST_F(TimeStatsTest, canClearDumpOnlyTimeStats) { EXPECT_THAT(result, HasSubstr("compositionStrategyChanges = 0")); EXPECT_THAT(result, HasSubstr("averageFrameDuration = 0.000 ms")); EXPECT_THAT(result, HasSubstr("averageRenderEngineTiming = 0.000 ms")); std::string expectedResult = "totalTimelineFrames = " + std::to_string(0); EXPECT_THAT(result, HasSubstr(expectedResult)); expectedResult = "jankyFrames = " + std::to_string(0); EXPECT_THAT(result, HasSubstr(expectedResult)); expectedResult = "sfLongCpuJankyFrames = " + std::to_string(0); EXPECT_THAT(result, HasSubstr(expectedResult)); expectedResult = "sfLongGpuJankyFrames = " + std::to_string(0); EXPECT_THAT(result, HasSubstr(expectedResult)); expectedResult = "sfUnattributedJankyFrames = " + std::to_string(0); EXPECT_THAT(result, HasSubstr(expectedResult)); expectedResult = "appUnattributedJankyFrames = " + std::to_string(0); EXPECT_THAT(result, HasSubstr(expectedResult)); expectedResult = "sfSchedulingJankyFrames = " + std::to_string(0); EXPECT_THAT(result, HasSubstr(expectedResult)); expectedResult = "sfPredictionErrorJankyFrames = " + std::to_string(0); EXPECT_THAT(result, HasSubstr(expectedResult)); expectedResult = "appBufferStuffingJankyFrames = " + std::to_string(0); EXPECT_THAT(result, HasSubstr(expectedResult)); std::string expectedResult = "totalTimelineFrames = "; EXPECT_THAT(result, Not(HasSubstr(expectedResult))); expectedResult = "jankyFrames = "; EXPECT_THAT(result, Not(HasSubstr(expectedResult))); expectedResult = "sfLongCpuJankyFrames = "; EXPECT_THAT(result, Not(HasSubstr(expectedResult))); expectedResult = "sfLongGpuJankyFrames = "; EXPECT_THAT(result, Not(HasSubstr(expectedResult))); expectedResult = "sfUnattributedJankyFrames = "; EXPECT_THAT(result, Not(HasSubstr(expectedResult))); expectedResult = "appUnattributedJankyFrames = "; EXPECT_THAT(result, Not(HasSubstr(expectedResult))); expectedResult = "sfSchedulingJankyFrames = "; EXPECT_THAT(result, Not(HasSubstr(expectedResult))); expectedResult = "sfPredictionErrorJankyFrames = "; EXPECT_THAT(result, Not(HasSubstr(expectedResult))); expectedResult = "appBufferStuffingJankyFrames = "; EXPECT_THAT(result, Not(HasSubstr(expectedResult))); } TEST_F(TimeStatsTest, canDumpWithMaxLayers) { Loading Loading @@ -1348,6 +1348,30 @@ TEST_F(TimeStatsTest, canSurviveMonkey) { } } TEST_F(TimeStatsTest, refreshRateIsClampedToNearestBucket) { // this stat is not in the proto so verify by checking the string dump const auto verifyRefreshRateBucket = [&](Fps fps, int32_t bucket) { EXPECT_TRUE(inputCommand(InputCommand::CLEAR, FMT_STRING).empty()); EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty()); insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000); mTimeStats->incrementJankyFrames( {fps, std::nullopt, UID_0, genLayerName(LAYER_ID_0), JankType::None, 0, 0, 0}); const std::string result(inputCommand(InputCommand::DUMP_ALL, FMT_STRING)); std::string expectedResult = "displayRefreshRate = " + std::to_string(bucket) + " fps"; EXPECT_THAT(result, HasSubstr(expectedResult)) << "failed for " << fps; }; verifyRefreshRateBucket(Fps(91.f), 90); verifyRefreshRateBucket(Fps(89.f), 90); verifyRefreshRateBucket(Fps(61.f), 60); verifyRefreshRateBucket(Fps(59.f), 60); verifyRefreshRateBucket(Fps(31.f), 30); verifyRefreshRateBucket(Fps(29.f), 30); } } // namespace } // namespace android Loading Loading
services/surfaceflinger/TimeStats/TimeStats.cpp +9 −8 Original line number Diff line number Diff line Loading @@ -427,8 +427,8 @@ bool TimeStats::recordReadyLocked(int32_t layerId, TimeRecord* timeRecord) { return true; } static int32_t clampToSmallestBucket(Fps fps, size_t bucketWidth) { return (fps.getIntValue() / bucketWidth) * bucketWidth; static int32_t clampToNearestBucket(Fps fps, size_t bucketWidth) { return std::round(fps.getValue() / bucketWidth) * bucketWidth; } void TimeStats::flushAvailableRecordsToStatsLocked(int32_t layerId, Fps displayRefreshRate, Loading @@ -441,9 +441,9 @@ void TimeStats::flushAvailableRecordsToStatsLocked(int32_t layerId, Fps displayR TimeRecord& prevTimeRecord = layerRecord.prevTimeRecord; std::deque<TimeRecord>& timeRecords = layerRecord.timeRecords; const int32_t refreshRateBucket = clampToSmallestBucket(displayRefreshRate, REFRESH_RATE_BUCKET_WIDTH); clampToNearestBucket(displayRefreshRate, REFRESH_RATE_BUCKET_WIDTH); const int32_t renderRateBucket = clampToSmallestBucket(renderRate ? *renderRate : displayRefreshRate, clampToNearestBucket(renderRate ? *renderRate : displayRefreshRate, RENDER_RATE_BUCKET_WIDTH); while (!timeRecords.empty()) { if (!recordReadyLocked(layerId, &timeRecords[0])) break; Loading Loading @@ -799,9 +799,9 @@ void TimeStats::incrementJankyFrames(const JankyFramesInfo& info) { static const std::string kDefaultLayerName = "none"; const int32_t refreshRateBucket = clampToSmallestBucket(info.refreshRate, REFRESH_RATE_BUCKET_WIDTH); clampToNearestBucket(info.refreshRate, REFRESH_RATE_BUCKET_WIDTH); const int32_t renderRateBucket = clampToSmallestBucket(info.renderRate ? *info.renderRate : info.refreshRate, clampToNearestBucket(info.renderRate ? *info.renderRate : info.refreshRate, RENDER_RATE_BUCKET_WIDTH); const TimeStatsHelper::TimelineStatsKey timelineKey = {refreshRateBucket, renderRateBucket}; Loading Loading @@ -1021,6 +1021,7 @@ void TimeStats::disable() { void TimeStats::clearAll() { std::lock_guard<std::mutex> lock(mMutex); mTimeStats.stats.clear(); clearGlobalLocked(); clearLayersLocked(); } Loading
services/surfaceflinger/tests/unittests/TimeStatsTest.cpp +42 −18 Original line number Diff line number Diff line Loading @@ -897,24 +897,24 @@ TEST_F(TimeStatsTest, canClearDumpOnlyTimeStats) { EXPECT_THAT(result, HasSubstr("compositionStrategyChanges = 0")); EXPECT_THAT(result, HasSubstr("averageFrameDuration = 0.000 ms")); EXPECT_THAT(result, HasSubstr("averageRenderEngineTiming = 0.000 ms")); std::string expectedResult = "totalTimelineFrames = " + std::to_string(0); EXPECT_THAT(result, HasSubstr(expectedResult)); expectedResult = "jankyFrames = " + std::to_string(0); EXPECT_THAT(result, HasSubstr(expectedResult)); expectedResult = "sfLongCpuJankyFrames = " + std::to_string(0); EXPECT_THAT(result, HasSubstr(expectedResult)); expectedResult = "sfLongGpuJankyFrames = " + std::to_string(0); EXPECT_THAT(result, HasSubstr(expectedResult)); expectedResult = "sfUnattributedJankyFrames = " + std::to_string(0); EXPECT_THAT(result, HasSubstr(expectedResult)); expectedResult = "appUnattributedJankyFrames = " + std::to_string(0); EXPECT_THAT(result, HasSubstr(expectedResult)); expectedResult = "sfSchedulingJankyFrames = " + std::to_string(0); EXPECT_THAT(result, HasSubstr(expectedResult)); expectedResult = "sfPredictionErrorJankyFrames = " + std::to_string(0); EXPECT_THAT(result, HasSubstr(expectedResult)); expectedResult = "appBufferStuffingJankyFrames = " + std::to_string(0); EXPECT_THAT(result, HasSubstr(expectedResult)); std::string expectedResult = "totalTimelineFrames = "; EXPECT_THAT(result, Not(HasSubstr(expectedResult))); expectedResult = "jankyFrames = "; EXPECT_THAT(result, Not(HasSubstr(expectedResult))); expectedResult = "sfLongCpuJankyFrames = "; EXPECT_THAT(result, Not(HasSubstr(expectedResult))); expectedResult = "sfLongGpuJankyFrames = "; EXPECT_THAT(result, Not(HasSubstr(expectedResult))); expectedResult = "sfUnattributedJankyFrames = "; EXPECT_THAT(result, Not(HasSubstr(expectedResult))); expectedResult = "appUnattributedJankyFrames = "; EXPECT_THAT(result, Not(HasSubstr(expectedResult))); expectedResult = "sfSchedulingJankyFrames = "; EXPECT_THAT(result, Not(HasSubstr(expectedResult))); expectedResult = "sfPredictionErrorJankyFrames = "; EXPECT_THAT(result, Not(HasSubstr(expectedResult))); expectedResult = "appBufferStuffingJankyFrames = "; EXPECT_THAT(result, Not(HasSubstr(expectedResult))); } TEST_F(TimeStatsTest, canDumpWithMaxLayers) { Loading Loading @@ -1348,6 +1348,30 @@ TEST_F(TimeStatsTest, canSurviveMonkey) { } } TEST_F(TimeStatsTest, refreshRateIsClampedToNearestBucket) { // this stat is not in the proto so verify by checking the string dump const auto verifyRefreshRateBucket = [&](Fps fps, int32_t bucket) { EXPECT_TRUE(inputCommand(InputCommand::CLEAR, FMT_STRING).empty()); EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty()); insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000); mTimeStats->incrementJankyFrames( {fps, std::nullopt, UID_0, genLayerName(LAYER_ID_0), JankType::None, 0, 0, 0}); const std::string result(inputCommand(InputCommand::DUMP_ALL, FMT_STRING)); std::string expectedResult = "displayRefreshRate = " + std::to_string(bucket) + " fps"; EXPECT_THAT(result, HasSubstr(expectedResult)) << "failed for " << fps; }; verifyRefreshRateBucket(Fps(91.f), 90); verifyRefreshRateBucket(Fps(89.f), 90); verifyRefreshRateBucket(Fps(61.f), 60); verifyRefreshRateBucket(Fps(59.f), 60); verifyRefreshRateBucket(Fps(31.f), 30); verifyRefreshRateBucket(Fps(29.f), 30); } } // namespace } // namespace android Loading