Loading services/surfaceflinger/Scheduler/LayerInfoV2.cpp +19 −14 Original line number Original line Diff line number Diff line Loading @@ -50,23 +50,28 @@ void LayerInfoV2::setLastPresentTime(nsecs_t lastPresentTime, nsecs_t now, } } } } bool LayerInfoV2::isFrequent(nsecs_t now) const { bool LayerInfoV2::isFrequent(nsecs_t now) { mLastReportedIsFrequent = [&] { for (auto it = mFrameTimes.crbegin(); it != mFrameTimes.crend(); ++it) { for (auto it = mFrameTimes.crbegin(); it != mFrameTimes.crend(); ++it) { if (now - it->queueTime >= MAX_FREQUENT_LAYER_PERIOD_NS.count()) { if (now - it->queueTime >= MAX_FREQUENT_LAYER_PERIOD_NS.count()) { ALOGV("%s infrequent (last frame is %.2fms ago", mName.c_str(), ALOGV("%s infrequent (last frame is %.2fms ago)", mName.c_str(), (now - mFrameTimes.back().queueTime) / 1e6f); (now - mFrameTimes.back().queueTime) / 1e6f); return false; return false; } } const auto numFrames = std::distance(mFrameTimes.crbegin(), it + 1); const auto numFrames = std::distance(mFrameTimes.crbegin(), it + 1); if (numFrames >= FREQUENT_LAYER_WINDOW_SIZE) { if (numFrames >= FREQUENT_LAYER_WINDOW_SIZE) { ALOGV("%s frequent (burst of %zu frames", mName.c_str(), numFrames); ALOGV("%s frequent (burst of %zu frames)", mName.c_str(), numFrames); return true; return true; } } } } ALOGV("%s infrequent (not enough frames %zu)", mName.c_str(), mFrameTimes.size()); ALOGV("%s %sfrequent (not enough frames %zu)", mName.c_str(), return false; mLastReportedIsFrequent ? "" : "in", mFrameTimes.size()); return mLastReportedIsFrequent; }(); return mLastReportedIsFrequent; } } bool LayerInfoV2::hasEnoughDataForHeuristic() const { bool LayerInfoV2::hasEnoughDataForHeuristic() const { Loading services/surfaceflinger/Scheduler/LayerInfoV2.h +8 −1 Original line number Original line Diff line number Diff line Loading @@ -94,7 +94,7 @@ private: bool pendingConfigChange; bool pendingConfigChange; }; }; bool isFrequent(nsecs_t now) const; bool isFrequent(nsecs_t now); bool hasEnoughDataForHeuristic() const; bool hasEnoughDataForHeuristic() const; std::optional<float> calculateRefreshRateIfPossible(); std::optional<float> calculateRefreshRateIfPossible(); std::pair<nsecs_t, bool> calculateAverageFrameTime() const; std::pair<nsecs_t, bool> calculateAverageFrameTime() const; Loading @@ -110,6 +110,13 @@ private: float mLastReportedRefreshRate = 0.0f; float mLastReportedRefreshRate = 0.0f; // Used to determine whether a layer should be considered frequent or // not when we don't have enough frames. This member will not be cleared // as part of clearHistory() to remember whether this layer was frequent // or not before we processed touch boost (or anything else that would // clear layer history). bool mLastReportedIsFrequent = true; // Holds information about the layer vote // Holds information about the layer vote struct { struct { LayerHistory::LayerVoteType type; LayerHistory::LayerVoteType type; Loading services/surfaceflinger/tests/unittests/LayerHistoryTestV2.cpp +38 −17 Original line number Original line Diff line number Diff line Loading @@ -103,17 +103,8 @@ TEST_F(LayerHistoryTestV2, oneLayer) { EXPECT_TRUE(history().summarize(time).empty()); EXPECT_TRUE(history().summarize(time).empty()); EXPECT_EQ(0, activeLayerCount()); EXPECT_EQ(0, activeLayerCount()); // The first few updates are considered infrequent // The first few updates are considered frequent for (int i = 0; i < FREQUENT_LAYER_WINDOW_SIZE - 1; i++) { for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE - 1; i++) { history().record(layer.get(), 0, time); ASSERT_EQ(1, history().summarize(time).size()); EXPECT_EQ(LayerHistory::LayerVoteType::Min, history().summarize(time)[0].vote); EXPECT_EQ(1, activeLayerCount()); EXPECT_EQ(0, frequentLayerCount(time)); } // Max returned if active layers have insufficient history. for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE - FREQUENT_LAYER_WINDOW_SIZE - 1; i++) { history().record(layer.get(), 0, time); history().record(layer.get(), 0, time); ASSERT_EQ(1, history().summarize(time).size()); ASSERT_EQ(1, history().summarize(time).size()); EXPECT_EQ(LayerHistory::LayerVoteType::Max, history().summarize(time)[0].vote); EXPECT_EQ(LayerHistory::LayerVoteType::Max, history().summarize(time)[0].vote); Loading Loading @@ -144,8 +135,8 @@ TEST_F(LayerHistoryTestV2, oneInvisibleLayer) { history().record(layer.get(), 0, time); history().record(layer.get(), 0, time); auto summary = history().summarize(time); auto summary = history().summarize(time); ASSERT_EQ(1, history().summarize(time).size()); ASSERT_EQ(1, history().summarize(time).size()); // Layer is still considered inactive so we expect to get Min // Layer is still considered active so we expect to get Max EXPECT_EQ(LayerHistory::LayerVoteType::Min, history().summarize(time)[0].vote); EXPECT_EQ(LayerHistory::LayerVoteType::Max, history().summarize(time)[0].vote); EXPECT_EQ(1, activeLayerCount()); EXPECT_EQ(1, activeLayerCount()); EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(false)); EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(false)); Loading Loading @@ -475,13 +466,13 @@ TEST_F(LayerHistoryTestV2, inactiveLayers) { nsecs_t time = systemTime(); nsecs_t time = systemTime(); // The first few updates are considered infrequent // The first few updates are considered frequent for (int i = 0; i < FREQUENT_LAYER_WINDOW_SIZE - 1; i++) { for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE - 1; i++) { history().record(layer.get(), 0, time); history().record(layer.get(), 0, time); ASSERT_EQ(1, history().summarize(time).size()); ASSERT_EQ(1, history().summarize(time).size()); EXPECT_EQ(LayerHistory::LayerVoteType::Min, history().summarize(time)[0].vote); EXPECT_EQ(LayerHistory::LayerVoteType::Max, history().summarize(time)[0].vote); EXPECT_EQ(1, activeLayerCount()); EXPECT_EQ(1, activeLayerCount()); EXPECT_EQ(0, frequentLayerCount(time)); EXPECT_EQ(1, frequentLayerCount(time)); } } // advance the time for the previous frame to be inactive // advance the time for the previous frame to be inactive Loading @@ -508,6 +499,36 @@ TEST_F(LayerHistoryTestV2, inactiveLayers) { EXPECT_EQ(LayerHistory::LayerVoteType::Max, history().summarize(time)[0].vote); EXPECT_EQ(LayerHistory::LayerVoteType::Max, history().summarize(time)[0].vote); EXPECT_EQ(1, activeLayerCount()); EXPECT_EQ(1, activeLayerCount()); EXPECT_EQ(1, frequentLayerCount(time)); EXPECT_EQ(1, frequentLayerCount(time)); // advance the time for the previous frame to be inactive time += MAX_ACTIVE_LAYER_PERIOD_NS.count(); // Now event if we post a quick few frame we should stay infrequent for (int i = 0; i < FREQUENT_LAYER_WINDOW_SIZE - 1; i++) { history().record(layer.get(), time, time); time += HI_FPS_PERIOD; EXPECT_EQ(1, layerCount()); ASSERT_EQ(1, history().summarize(time).size()); EXPECT_EQ(LayerHistory::LayerVoteType::Min, history().summarize(time)[0].vote); EXPECT_EQ(1, activeLayerCount()); EXPECT_EQ(0, frequentLayerCount(time)); } // clear the history history().clear(); // Now event if we post a quick few frame we should stay infrequent for (int i = 0; i < FREQUENT_LAYER_WINDOW_SIZE - 1; i++) { history().record(layer.get(), time, time); time += HI_FPS_PERIOD; EXPECT_EQ(1, layerCount()); ASSERT_EQ(1, history().summarize(time).size()); EXPECT_EQ(LayerHistory::LayerVoteType::Min, history().summarize(time)[0].vote); EXPECT_EQ(1, activeLayerCount()); EXPECT_EQ(0, frequentLayerCount(time)); } } } TEST_F(LayerHistoryTestV2, invisibleExplicitLayer) { TEST_F(LayerHistoryTestV2, invisibleExplicitLayer) { Loading Loading
services/surfaceflinger/Scheduler/LayerInfoV2.cpp +19 −14 Original line number Original line Diff line number Diff line Loading @@ -50,23 +50,28 @@ void LayerInfoV2::setLastPresentTime(nsecs_t lastPresentTime, nsecs_t now, } } } } bool LayerInfoV2::isFrequent(nsecs_t now) const { bool LayerInfoV2::isFrequent(nsecs_t now) { mLastReportedIsFrequent = [&] { for (auto it = mFrameTimes.crbegin(); it != mFrameTimes.crend(); ++it) { for (auto it = mFrameTimes.crbegin(); it != mFrameTimes.crend(); ++it) { if (now - it->queueTime >= MAX_FREQUENT_LAYER_PERIOD_NS.count()) { if (now - it->queueTime >= MAX_FREQUENT_LAYER_PERIOD_NS.count()) { ALOGV("%s infrequent (last frame is %.2fms ago", mName.c_str(), ALOGV("%s infrequent (last frame is %.2fms ago)", mName.c_str(), (now - mFrameTimes.back().queueTime) / 1e6f); (now - mFrameTimes.back().queueTime) / 1e6f); return false; return false; } } const auto numFrames = std::distance(mFrameTimes.crbegin(), it + 1); const auto numFrames = std::distance(mFrameTimes.crbegin(), it + 1); if (numFrames >= FREQUENT_LAYER_WINDOW_SIZE) { if (numFrames >= FREQUENT_LAYER_WINDOW_SIZE) { ALOGV("%s frequent (burst of %zu frames", mName.c_str(), numFrames); ALOGV("%s frequent (burst of %zu frames)", mName.c_str(), numFrames); return true; return true; } } } } ALOGV("%s infrequent (not enough frames %zu)", mName.c_str(), mFrameTimes.size()); ALOGV("%s %sfrequent (not enough frames %zu)", mName.c_str(), return false; mLastReportedIsFrequent ? "" : "in", mFrameTimes.size()); return mLastReportedIsFrequent; }(); return mLastReportedIsFrequent; } } bool LayerInfoV2::hasEnoughDataForHeuristic() const { bool LayerInfoV2::hasEnoughDataForHeuristic() const { Loading
services/surfaceflinger/Scheduler/LayerInfoV2.h +8 −1 Original line number Original line Diff line number Diff line Loading @@ -94,7 +94,7 @@ private: bool pendingConfigChange; bool pendingConfigChange; }; }; bool isFrequent(nsecs_t now) const; bool isFrequent(nsecs_t now); bool hasEnoughDataForHeuristic() const; bool hasEnoughDataForHeuristic() const; std::optional<float> calculateRefreshRateIfPossible(); std::optional<float> calculateRefreshRateIfPossible(); std::pair<nsecs_t, bool> calculateAverageFrameTime() const; std::pair<nsecs_t, bool> calculateAverageFrameTime() const; Loading @@ -110,6 +110,13 @@ private: float mLastReportedRefreshRate = 0.0f; float mLastReportedRefreshRate = 0.0f; // Used to determine whether a layer should be considered frequent or // not when we don't have enough frames. This member will not be cleared // as part of clearHistory() to remember whether this layer was frequent // or not before we processed touch boost (or anything else that would // clear layer history). bool mLastReportedIsFrequent = true; // Holds information about the layer vote // Holds information about the layer vote struct { struct { LayerHistory::LayerVoteType type; LayerHistory::LayerVoteType type; Loading
services/surfaceflinger/tests/unittests/LayerHistoryTestV2.cpp +38 −17 Original line number Original line Diff line number Diff line Loading @@ -103,17 +103,8 @@ TEST_F(LayerHistoryTestV2, oneLayer) { EXPECT_TRUE(history().summarize(time).empty()); EXPECT_TRUE(history().summarize(time).empty()); EXPECT_EQ(0, activeLayerCount()); EXPECT_EQ(0, activeLayerCount()); // The first few updates are considered infrequent // The first few updates are considered frequent for (int i = 0; i < FREQUENT_LAYER_WINDOW_SIZE - 1; i++) { for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE - 1; i++) { history().record(layer.get(), 0, time); ASSERT_EQ(1, history().summarize(time).size()); EXPECT_EQ(LayerHistory::LayerVoteType::Min, history().summarize(time)[0].vote); EXPECT_EQ(1, activeLayerCount()); EXPECT_EQ(0, frequentLayerCount(time)); } // Max returned if active layers have insufficient history. for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE - FREQUENT_LAYER_WINDOW_SIZE - 1; i++) { history().record(layer.get(), 0, time); history().record(layer.get(), 0, time); ASSERT_EQ(1, history().summarize(time).size()); ASSERT_EQ(1, history().summarize(time).size()); EXPECT_EQ(LayerHistory::LayerVoteType::Max, history().summarize(time)[0].vote); EXPECT_EQ(LayerHistory::LayerVoteType::Max, history().summarize(time)[0].vote); Loading Loading @@ -144,8 +135,8 @@ TEST_F(LayerHistoryTestV2, oneInvisibleLayer) { history().record(layer.get(), 0, time); history().record(layer.get(), 0, time); auto summary = history().summarize(time); auto summary = history().summarize(time); ASSERT_EQ(1, history().summarize(time).size()); ASSERT_EQ(1, history().summarize(time).size()); // Layer is still considered inactive so we expect to get Min // Layer is still considered active so we expect to get Max EXPECT_EQ(LayerHistory::LayerVoteType::Min, history().summarize(time)[0].vote); EXPECT_EQ(LayerHistory::LayerVoteType::Max, history().summarize(time)[0].vote); EXPECT_EQ(1, activeLayerCount()); EXPECT_EQ(1, activeLayerCount()); EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(false)); EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(false)); Loading Loading @@ -475,13 +466,13 @@ TEST_F(LayerHistoryTestV2, inactiveLayers) { nsecs_t time = systemTime(); nsecs_t time = systemTime(); // The first few updates are considered infrequent // The first few updates are considered frequent for (int i = 0; i < FREQUENT_LAYER_WINDOW_SIZE - 1; i++) { for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE - 1; i++) { history().record(layer.get(), 0, time); history().record(layer.get(), 0, time); ASSERT_EQ(1, history().summarize(time).size()); ASSERT_EQ(1, history().summarize(time).size()); EXPECT_EQ(LayerHistory::LayerVoteType::Min, history().summarize(time)[0].vote); EXPECT_EQ(LayerHistory::LayerVoteType::Max, history().summarize(time)[0].vote); EXPECT_EQ(1, activeLayerCount()); EXPECT_EQ(1, activeLayerCount()); EXPECT_EQ(0, frequentLayerCount(time)); EXPECT_EQ(1, frequentLayerCount(time)); } } // advance the time for the previous frame to be inactive // advance the time for the previous frame to be inactive Loading @@ -508,6 +499,36 @@ TEST_F(LayerHistoryTestV2, inactiveLayers) { EXPECT_EQ(LayerHistory::LayerVoteType::Max, history().summarize(time)[0].vote); EXPECT_EQ(LayerHistory::LayerVoteType::Max, history().summarize(time)[0].vote); EXPECT_EQ(1, activeLayerCount()); EXPECT_EQ(1, activeLayerCount()); EXPECT_EQ(1, frequentLayerCount(time)); EXPECT_EQ(1, frequentLayerCount(time)); // advance the time for the previous frame to be inactive time += MAX_ACTIVE_LAYER_PERIOD_NS.count(); // Now event if we post a quick few frame we should stay infrequent for (int i = 0; i < FREQUENT_LAYER_WINDOW_SIZE - 1; i++) { history().record(layer.get(), time, time); time += HI_FPS_PERIOD; EXPECT_EQ(1, layerCount()); ASSERT_EQ(1, history().summarize(time).size()); EXPECT_EQ(LayerHistory::LayerVoteType::Min, history().summarize(time)[0].vote); EXPECT_EQ(1, activeLayerCount()); EXPECT_EQ(0, frequentLayerCount(time)); } // clear the history history().clear(); // Now event if we post a quick few frame we should stay infrequent for (int i = 0; i < FREQUENT_LAYER_WINDOW_SIZE - 1; i++) { history().record(layer.get(), time, time); time += HI_FPS_PERIOD; EXPECT_EQ(1, layerCount()); ASSERT_EQ(1, history().summarize(time).size()); EXPECT_EQ(LayerHistory::LayerVoteType::Min, history().summarize(time)[0].vote); EXPECT_EQ(1, activeLayerCount()); EXPECT_EQ(0, frequentLayerCount(time)); } } } TEST_F(LayerHistoryTestV2, invisibleExplicitLayer) { TEST_F(LayerHistoryTestV2, invisibleExplicitLayer) { Loading