RefreshRateConfigs: Fix for default seamlessness and seamed layers
When there's a focused layer with has requested a seamless change
a layer with default seamlessness is not supposed to be able to
change the refresh rate group. This behaviour is covered by the test
groupSwitchingWithTwoLayersDefaultFocusedAndSeamed.
However if the seamed layer is not focused a default layer is
allowed to switch back to the group of the default mode.
Test: atest RefreshRateConfigsTest
Bug: 183128900
Change-Id: I1a7da19fbfda3b221bda6f2d2dbb9fa65de23cf5
diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
index 91e8043..0e4256b 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
+++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
@@ -215,7 +215,7 @@
int explicitExactOrMultipleVoteLayers = 0;
int explicitExact = 0;
float maxExplicitWeight = 0;
- int seamedLayers = 0;
+ int seamedFocusedLayers = 0;
for (const auto& layer : layers) {
switch (layer.vote) {
case LayerVoteType::NoVote:
@@ -243,8 +243,8 @@
break;
}
- if (layer.seamlessness == Seamlessness::SeamedAndSeamless) {
- seamedLayers++;
+ if (layer.seamlessness == Seamlessness::SeamedAndSeamless && layer.focused) {
+ seamedFocusedLayers++;
}
}
@@ -329,12 +329,11 @@
// mode group otherwise. In second case, if the current mode group is different
// from the default, this means a layer with seamlessness=SeamedAndSeamless has just
// disappeared.
- const bool isInPolicyForDefault = seamedLayers > 0
+ const bool isInPolicyForDefault = seamedFocusedLayers > 0
? scores[i].refreshRate->getModeGroup() == mCurrentRefreshRate->getModeGroup()
: scores[i].refreshRate->getModeGroup() == defaultMode->getModeGroup();
- if (layer.seamlessness == Seamlessness::Default && !isInPolicyForDefault &&
- !layer.focused) {
+ if (layer.seamlessness == Seamlessness::Default && !isInPolicyForDefault) {
ALOGV("%s ignores %s. Current mode = %s", formatLayerInfo(layer, weight).c_str(),
scores[i].refreshRate->toString().c_str(),
mCurrentRefreshRate->toString().c_str());
diff --git a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
index b0c0b6d..eb54eb8 100644
--- a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
+++ b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
@@ -1328,7 +1328,7 @@
.getModeId());
}
-TEST_F(RefreshRateConfigsTest, groupSwitchingWithTwoLayersDefaultAndSeamed) {
+TEST_F(RefreshRateConfigsTest, groupSwitchingWithTwoLayersDefaultFocusedAndSeamed) {
auto refreshRateConfigs =
std::make_unique<RefreshRateConfigs>(m60_90DeviceWithDifferentGroups,
/*currentConfigId=*/HWC_CONFIG_ID_60);
@@ -1339,8 +1339,12 @@
refreshRateConfigs->setCurrentModeId(HWC_CONFIG_ID_90);
- // If there's a layer with seamlessness=SeamedAndSeamless, another layer with
- // seamlessness=Default can't change the mode group.
+ // If there's a focused layer with seamlessness=SeamedAndSeamless, another layer with
+ // seamlessness=Default can't change the mode group back to the group of the default
+ // mode.
+ // For example, this may happen when a video playback requests and gets a seamed switch,
+ // but another layer (with default seamlessness) starts animating. The animating layer
+ // should not cause a seamed switch.
auto layers = std::vector<LayerRequirement>{LayerRequirement{.weight = 1.0f}};
layers[0].seamlessness = Seamlessness::Default;
layers[0].desiredRefreshRate = Fps(60.0f);
@@ -1348,14 +1352,47 @@
layers[0].vote = LayerVoteType::ExplicitDefault;
layers[0].name = "60Hz ExplicitDefault";
- layers.push_back(LayerRequirement{.weight = 0.5f});
+ layers.push_back(LayerRequirement{.weight = 0.1f});
+ layers[1].seamlessness = Seamlessness::SeamedAndSeamless;
+ layers[1].desiredRefreshRate = Fps(90.0f);
+ layers[1].focused = true;
+ layers[1].vote = LayerVoteType::ExplicitDefault;
+ layers[1].name = "90Hz ExplicitDefault";
+
+ ASSERT_EQ(HWC_CONFIG_ID_90,
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})
+ .getModeId());
+}
+
+TEST_F(RefreshRateConfigsTest, groupSwitchingWithTwoLayersDefaultNotFocusedAndSeamed) {
+ auto refreshRateConfigs =
+ std::make_unique<RefreshRateConfigs>(m60_90DeviceWithDifferentGroups,
+ /*currentConfigId=*/HWC_CONFIG_ID_60);
+ RefreshRateConfigs::Policy policy;
+ policy.defaultMode = refreshRateConfigs->getCurrentPolicy().defaultMode;
+ policy.allowGroupSwitching = true;
+ ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy(policy), 0);
+
+ refreshRateConfigs->setCurrentModeId(HWC_CONFIG_ID_90);
+
+ // Layer with seamlessness=Default can change the mode group if there's a not
+ // focused layer with seamlessness=SeamedAndSeamless. This happens for example,
+ // when in split screen mode the user switches between the two visible applications.
+ auto layers = std::vector<LayerRequirement>{LayerRequirement{.weight = 1.0f}};
+ layers[0].seamlessness = Seamlessness::Default;
+ layers[0].desiredRefreshRate = Fps(60.0f);
+ layers[0].focused = true;
+ layers[0].vote = LayerVoteType::ExplicitDefault;
+ layers[0].name = "60Hz ExplicitDefault";
+
+ layers.push_back(LayerRequirement{.weight = 0.7f});
layers[1].seamlessness = Seamlessness::SeamedAndSeamless;
layers[1].desiredRefreshRate = Fps(90.0f);
layers[1].focused = false;
layers[1].vote = LayerVoteType::ExplicitDefault;
layers[1].name = "90Hz ExplicitDefault";
- ASSERT_EQ(HWC_CONFIG_ID_90,
+ ASSERT_EQ(HWC_CONFIG_ID_60,
refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})
.getModeId());
}