diff options
7 files changed, 59 insertions, 23 deletions
diff --git a/services/surfaceflinger/Scheduler/LayerHistory.cpp b/services/surfaceflinger/Scheduler/LayerHistory.cpp index e762af3ec5..f80c2336f7 100644 --- a/services/surfaceflinger/Scheduler/LayerHistory.cpp +++ b/services/surfaceflinger/Scheduler/LayerHistory.cpp @@ -46,11 +46,13 @@ LayerHistory::LayerHistory() { LayerHistory::~LayerHistory() = default; std::unique_ptr<LayerHistory::LayerHandle> LayerHistory::createLayer(const std::string name, + float minRefreshRate, float maxRefreshRate) { const int64_t id = sNextId++; std::lock_guard lock(mLock); - mInactiveLayerInfos.emplace(id, std::make_shared<LayerInfo>(name, maxRefreshRate)); + mInactiveLayerInfos.emplace(id, + std::make_shared<LayerInfo>(name, minRefreshRate, maxRefreshRate)); return std::make_unique<LayerHistory::LayerHandle>(*this, id); } diff --git a/services/surfaceflinger/Scheduler/LayerHistory.h b/services/surfaceflinger/Scheduler/LayerHistory.h index 2569b4638a..5598cc1cf5 100644 --- a/services/surfaceflinger/Scheduler/LayerHistory.h +++ b/services/surfaceflinger/Scheduler/LayerHistory.h @@ -53,7 +53,8 @@ public: ~LayerHistory(); // When the layer is first created, register it. - std::unique_ptr<LayerHandle> createLayer(const std::string name, float maxRefreshRate); + std::unique_ptr<LayerHandle> createLayer(const std::string name, float minRefreshRate, + float maxRefreshRate); // Method for inserting layers and their requested present time into the unordered map. void insert(const std::unique_ptr<LayerHandle>& layerHandle, nsecs_t presentTime, bool isHdr); diff --git a/services/surfaceflinger/Scheduler/LayerInfo.cpp b/services/surfaceflinger/Scheduler/LayerInfo.cpp index 3104724041..beddb9be61 100644 --- a/services/surfaceflinger/Scheduler/LayerInfo.cpp +++ b/services/surfaceflinger/Scheduler/LayerInfo.cpp @@ -24,9 +24,10 @@ namespace android { namespace scheduler { -LayerInfo::LayerInfo(const std::string name, float maxRefreshRate) +LayerInfo::LayerInfo(const std::string name, float minRefreshRate, float maxRefreshRate) : mName(name), mMinRefreshDuration(1e9f / maxRefreshRate), + mLowActivityRefreshDuration(1e9f / minRefreshRate), mRefreshRateHistory(mMinRefreshDuration) {} LayerInfo::~LayerInfo() = default; @@ -47,7 +48,7 @@ void LayerInfo::setLastPresentTime(nsecs_t lastPresentTime) { const nsecs_t timeDiff = lastPresentTime - mLastPresentTime; mLastPresentTime = lastPresentTime; // Ignore time diff that are too high - those are stale values - if (timeDiff > TIME_EPSILON_NS.count()) return; + if (timeDiff > OBSOLETE_TIME_EPSILON_NS.count()) return; const nsecs_t refreshDuration = (timeDiff > 0) ? timeDiff : mMinRefreshDuration; mRefreshRateHistory.insertRefreshRate(refreshDuration); } diff --git a/services/surfaceflinger/Scheduler/LayerInfo.h b/services/surfaceflinger/Scheduler/LayerInfo.h index 90d426969c..2c50053ebd 100644 --- a/services/surfaceflinger/Scheduler/LayerInfo.h +++ b/services/surfaceflinger/Scheduler/LayerInfo.h @@ -96,8 +96,9 @@ class LayerInfo { return false; } - // The last update should not be older than TIME_EPSILON_NS nanoseconds. - const int64_t obsoleteEpsilon = systemTime() - scheduler::TIME_EPSILON_NS.count(); + // The last update should not be older than OBSOLETE_TIME_EPSILON_NS nanoseconds. + const int64_t obsoleteEpsilon = + systemTime() - scheduler::OBSOLETE_TIME_EPSILON_NS.count(); if (mElements.at(mElements.size() - 1) < obsoleteEpsilon) { return false; } @@ -105,6 +106,25 @@ class LayerInfo { return true; } + bool isLowActivityLayer() const { + // We want to make sure that we received more than two frames from the layer + // in order to check low activity. + if (mElements.size() < 2) { + return false; + } + + const int64_t obsoleteEpsilon = + systemTime() - scheduler::LOW_ACTIVITY_EPSILON_NS.count(); + // Check the frame before last to determine whether there is low activity. + // If that frame is older than LOW_ACTIVITY_EPSILON_NS, the layer is sending + // infrequent updates. + if (mElements.at(mElements.size() - 2) < obsoleteEpsilon) { + return true; + } + + return false; + } + void clearHistory() { mElements.clear(); } private: @@ -114,7 +134,7 @@ class LayerInfo { }; public: - LayerInfo(const std::string name, float maxRefreshRate); + LayerInfo(const std::string name, float minRefreshRate, float maxRefreshRate); ~LayerInfo(); LayerInfo(const LayerInfo&) = delete; @@ -144,6 +164,10 @@ public: // Calculate the average refresh rate. float getDesiredRefreshRate() const { std::lock_guard lock(mLock); + + if (mPresentTimeHistory.isLowActivityLayer()) { + return 1e9f / mLowActivityRefreshDuration; + } return mRefreshRateHistory.getRefreshRateAvg(); } @@ -175,6 +199,7 @@ public: private: const std::string mName; const nsecs_t mMinRefreshDuration; + const nsecs_t mLowActivityRefreshDuration; mutable std::mutex mLock; nsecs_t mLastUpdatedTime GUARDED_BY(mLock) = 0; nsecs_t mLastPresentTime GUARDED_BY(mLock) = 0; diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp index bb24f73834..99d6faee1c 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.cpp +++ b/services/surfaceflinger/Scheduler/Scheduler.cpp @@ -330,8 +330,11 @@ std::unique_ptr<scheduler::LayerHistory::LayerHandle> Scheduler::registerLayer( : RefreshRateType::PERFORMANCE; const auto refreshRate = mRefreshRateConfigs.getRefreshRate(refreshRateType); - const uint32_t fps = (refreshRate) ? refreshRate->fps : 0; - return mLayerHistory.createLayer(name, fps); + const uint32_t performanceFps = (refreshRate) ? refreshRate->fps : 0; + + const auto defaultRefreshRate = mRefreshRateConfigs.getRefreshRate(RefreshRateType::DEFAULT); + const uint32_t defaultFps = (defaultRefreshRate) ? defaultRefreshRate->fps : 0; + return mLayerHistory.createLayer(name, defaultFps, performanceFps); } void Scheduler::addLayerPresentTimeAndHDR( diff --git a/services/surfaceflinger/Scheduler/SchedulerUtils.h b/services/surfaceflinger/Scheduler/SchedulerUtils.h index d3b1bd07c4..ced1899109 100644 --- a/services/surfaceflinger/Scheduler/SchedulerUtils.h +++ b/services/surfaceflinger/Scheduler/SchedulerUtils.h @@ -36,13 +36,16 @@ static constexpr size_t ARRAY_SIZE = 30; static constexpr int SCREEN_OFF_CONFIG_ID = -1; static constexpr uint32_t HWC2_SCREEN_OFF_CONFIG_ID = 0xffffffff; -// This number is used when we try to determine how long does a given layer stay relevant. -// The value is set based on testing different scenarios. -static constexpr std::chrono::nanoseconds TIME_EPSILON_NS = 200ms; - // This number is used when we try to determine how long do we keep layer information around -// before we remove it. -static constexpr std::chrono::nanoseconds OBSOLETE_TIME_EPSILON_NS = 200ms; +// before we remove it. It is also used to determine how long the layer stays relevant. +// This time period captures infrequent updates when playing YouTube video with static image, +// or waiting idle in messaging app, when cursor is blinking. +static constexpr std::chrono::nanoseconds OBSOLETE_TIME_EPSILON_NS = 1200ms; + +// Layer is considered low activity if the buffers come more than LOW_ACTIVITY_EPSILON_NS +// apart. This is helping SF to vote for lower refresh rates when there is not activity +// in screen. +static constexpr std::chrono::nanoseconds LOW_ACTIVITY_EPSILON_NS = 250ms; // Calculates the statistical mean (average) in the data structure (array, vector). The // function does not modify the contents of the array. diff --git a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp index 2b1dfa8f38..7ec90660ce 100644 --- a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp +++ b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp @@ -25,6 +25,7 @@ public: protected: std::unique_ptr<LayerHistory> mLayerHistory; + static constexpr float MIN_REFRESH_RATE = 30.f; static constexpr float MAX_REFRESH_RATE = 90.f; }; @@ -36,7 +37,7 @@ LayerHistoryTest::~LayerHistoryTest() {} namespace { TEST_F(LayerHistoryTest, oneLayer) { std::unique_ptr<LayerHistory::LayerHandle> testLayer = - mLayerHistory->createLayer("TestLayer", MAX_REFRESH_RATE); + mLayerHistory->createLayer("TestLayer", MIN_REFRESH_RATE, MAX_REFRESH_RATE); mLayerHistory->setVisibility(testLayer, true); mLayerHistory->insert(testLayer, 0, false /*isHDR*/); @@ -60,7 +61,7 @@ TEST_F(LayerHistoryTest, oneLayer) { TEST_F(LayerHistoryTest, oneHDRLayer) { std::unique_ptr<LayerHistory::LayerHandle> testLayer = - mLayerHistory->createLayer("TestHDRLayer", MAX_REFRESH_RATE); + mLayerHistory->createLayer("TestHDRLayer", MIN_REFRESH_RATE, MAX_REFRESH_RATE); mLayerHistory->setVisibility(testLayer, true); mLayerHistory->insert(testLayer, 0, true /*isHDR*/); @@ -74,7 +75,7 @@ TEST_F(LayerHistoryTest, oneHDRLayer) { TEST_F(LayerHistoryTest, explicitTimestamp) { std::unique_ptr<LayerHistory::LayerHandle> test30FpsLayer = - mLayerHistory->createLayer("30FpsLayer", MAX_REFRESH_RATE); + mLayerHistory->createLayer("30FpsLayer", MIN_REFRESH_RATE, MAX_REFRESH_RATE); mLayerHistory->setVisibility(test30FpsLayer, true); nsecs_t startTime = systemTime(); @@ -87,13 +88,13 @@ TEST_F(LayerHistoryTest, explicitTimestamp) { TEST_F(LayerHistoryTest, multipleLayers) { std::unique_ptr<LayerHistory::LayerHandle> testLayer = - mLayerHistory->createLayer("TestLayer", MAX_REFRESH_RATE); + mLayerHistory->createLayer("TestLayer", MIN_REFRESH_RATE, MAX_REFRESH_RATE); mLayerHistory->setVisibility(testLayer, true); std::unique_ptr<LayerHistory::LayerHandle> test30FpsLayer = - mLayerHistory->createLayer("30FpsLayer", MAX_REFRESH_RATE); + mLayerHistory->createLayer("30FpsLayer", MIN_REFRESH_RATE, MAX_REFRESH_RATE); mLayerHistory->setVisibility(test30FpsLayer, true); std::unique_ptr<LayerHistory::LayerHandle> testLayer2 = - mLayerHistory->createLayer("TestLayer2", MAX_REFRESH_RATE); + mLayerHistory->createLayer("TestLayer2", MIN_REFRESH_RATE, MAX_REFRESH_RATE); mLayerHistory->setVisibility(testLayer2, true); nsecs_t startTime = systemTime(); @@ -119,8 +120,8 @@ TEST_F(LayerHistoryTest, multipleLayers) { mLayerHistory->insert(testLayer2, 0, false /*isHDR*/); } EXPECT_FLOAT_EQ(MAX_REFRESH_RATE, mLayerHistory->getDesiredRefreshRateAndHDR().first); - // After 100 ms frames become obsolete. - std::this_thread::sleep_for(std::chrono::milliseconds(500)); + // After 1200 ms frames become obsolete. + std::this_thread::sleep_for(std::chrono::milliseconds(1500)); // Insert the 31st frame. mLayerHistory->insert(test30FpsLayer, startTime + (30 * 33333333), false /*isHDR*/); EXPECT_FLOAT_EQ(30.f, mLayerHistory->getDesiredRefreshRateAndHDR().first); |