summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/surfaceflinger/Scheduler/LayerHistory.cpp4
-rw-r--r--services/surfaceflinger/Scheduler/LayerHistory.h3
-rw-r--r--services/surfaceflinger/Scheduler/LayerInfo.cpp5
-rw-r--r--services/surfaceflinger/Scheduler/LayerInfo.h31
-rw-r--r--services/surfaceflinger/Scheduler/Scheduler.cpp7
-rw-r--r--services/surfaceflinger/Scheduler/SchedulerUtils.h15
-rw-r--r--services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp17
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);