Merge "SurfaceFlinger: refresh rate calculation when no timestamps" into rvc-dev
diff --git a/services/surfaceflinger/Scheduler/LayerInfoV2.cpp b/services/surfaceflinger/Scheduler/LayerInfoV2.cpp
index bf1fb88..44b4264 100644
--- a/services/surfaceflinger/Scheduler/LayerInfoV2.cpp
+++ b/services/surfaceflinger/Scheduler/LayerInfoV2.cpp
@@ -111,21 +111,28 @@
// Calculate the refresh rate by finding the average delta between frames
nsecs_t totalPresentTimeDeltas = 0;
+ int numFrames = 0;
for (auto it = mFrameTimes.begin(); it != mFrameTimes.end() - 1; ++it) {
// If there are no presentation timestamp provided we can't calculate the refresh rate
if (it->presetTime == 0 || (it + 1)->presetTime == 0) {
- return std::nullopt;
+ continue;
}
totalPresentTimeDeltas +=
std::max(((it + 1)->presetTime - it->presetTime), mHighRefreshRatePeriod);
+ numFrames++;
}
- const float averageFrameTime =
- static_cast<float>(totalPresentTimeDeltas) / (mFrameTimes.size() - 1);
+ if (numFrames == 0) {
+ return std::nullopt;
+ }
+ const float averageFrameTime = static_cast<float>(totalPresentTimeDeltas) / numFrames;
// Now once we calculated the refresh rate we need to make sure that all the frames we captured
// are evenly distributed and we don't calculate the average across some burst of frames.
for (auto it = mFrameTimes.begin(); it != mFrameTimes.end() - 1; ++it) {
+ if (it->presetTime == 0 || (it + 1)->presetTime == 0) {
+ continue;
+ }
const nsecs_t presentTimeDeltas =
std::max(((it + 1)->presetTime - it->presetTime), mHighRefreshRatePeriod);
if (std::abs(presentTimeDeltas - averageFrameTime) > 2 * averageFrameTime) {
diff --git a/services/surfaceflinger/tests/unittests/LayerHistoryTestV2.cpp b/services/surfaceflinger/tests/unittests/LayerHistoryTestV2.cpp
index 6fca673..15207c9 100644
--- a/services/surfaceflinger/tests/unittests/LayerHistoryTestV2.cpp
+++ b/services/surfaceflinger/tests/unittests/LayerHistoryTestV2.cpp
@@ -512,5 +512,46 @@
EXPECT_EQ(1, frequentLayerCount(time));
}
+TEST_F(LayerHistoryTestV2, calculateRefreshRate30Hz) {
+ const auto layer = createLayer();
+ EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true));
+ EXPECT_CALL(*layer, getFrameRateForLayerTree()).WillRepeatedly(Return(Layer::FrameRate()));
+
+ EXPECT_EQ(1, layerCount());
+ EXPECT_EQ(0, activeLayerCount());
+
+ nsecs_t time = systemTime();
+ const nsecs_t frameTime = 33'333'333;
+
+ for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) {
+ time += frameTime;
+ history().record(layer.get(), time, time);
+ }
+ ASSERT_EQ(1, history().summarize(time).size());
+ EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, history().summarize(time)[0].vote);
+ EXPECT_FLOAT_EQ(30.f, history().summarize(time)[0].desiredRefreshRate);
+}
+
+TEST_F(LayerHistoryTestV2, calculateRefreshRate30HzSkipTimestamp) {
+ const auto layer = createLayer();
+ EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true));
+ EXPECT_CALL(*layer, getFrameRateForLayerTree()).WillRepeatedly(Return(Layer::FrameRate()));
+
+ EXPECT_EQ(1, layerCount());
+ EXPECT_EQ(0, activeLayerCount());
+
+ nsecs_t time = systemTime();
+ const nsecs_t frameTime = 33'333'333;
+
+ for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) {
+ time += frameTime;
+ const auto timestamp = (i == PRESENT_TIME_HISTORY_SIZE / 2) ? 0 : time;
+ history().record(layer.get(), timestamp, time);
+ }
+ ASSERT_EQ(1, history().summarize(time).size());
+ EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, history().summarize(time)[0].vote);
+ EXPECT_FLOAT_EQ(30.f, history().summarize(time)[0].desiredRefreshRate);
+}
+
} // namespace
} // namespace android::scheduler