SF: use parent layer frame rate
If an ancestor of a layer set a frame rate, and that layer doesn't
have a frame rate configured, use the one of the ancestor. The reason
for this is to support the high refresh rate deny list where WM will
set the frame rate on a container layer which is not visible. With this
change we will treat all child layers of that container as if they voted
themselves.
Test: test app that sets preferredDisplayModeId
Bug: 163079696
Change-Id: I3c55d393af72e19cd7b4f107d8cc0b2e85289d96
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index a545d18..24d1b52 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -1432,9 +1432,10 @@
};
// update parents and children about the vote
- // First traverse the tree and count how many layers has votes
+ // First traverse the tree and count how many layers has votes. In addition
+ // activate the layers in Scheduler's LayerHistory for it to check for changes
int layersWithVote = 0;
- traverseTree([&layersWithVote](Layer* layer) {
+ traverseTree([&layersWithVote, this](Layer* layer) {
const auto layerVotedWithDefaultCompatibility =
layer->mCurrentState.frameRate.rate.isValid() &&
layer->mCurrentState.frameRate.type == FrameRateCompatibility::Default;
@@ -1447,6 +1448,9 @@
if (layerVotedWithDefaultCompatibility || layerVotedWithNoVote) {
layersWithVote++;
}
+
+ mFlinger->mScheduler->recordLayerHistory(layer, systemTime(),
+ LayerHistory::LayerUpdateType::SetFrameRate);
});
// Now update the other layers
@@ -1474,10 +1478,6 @@
return false;
}
- // Activate the layer in Scheduler's LayerHistory
- mFlinger->mScheduler->recordLayerHistory(this, systemTime(),
- LayerHistory::LayerUpdateType::SetFrameRate);
-
mCurrentState.sequence++;
mCurrentState.frameRate = frameRate;
mCurrentState.modified = true;
@@ -1501,8 +1501,16 @@
return frameRate;
}
- // This layer doesn't have a frame rate. If one of its ancestors or successors
- // have a vote, return a NoVote for ancestors/successors to set the vote
+ // This layer doesn't have a frame rate. Check if its ancestors have a vote
+ if (sp<Layer> parent = getParent(); parent) {
+ if (const auto parentFrameRate = parent->getFrameRateForLayerTree();
+ parentFrameRate.rate.isValid()) {
+ return parentFrameRate;
+ }
+ }
+
+ // This layer and its ancestors don't have a frame rate. If one of successors
+ // has a vote, return a NoVote for successors to set the vote
if (getDrawingState().treeHasFrameRateVote) {
return {Fps(0.0f), FrameRateCompatibility::NoVote};
}
@@ -1692,11 +1700,11 @@
const FloatRect& crop = outputLayerState.sourceCrop;
StringAppendF(&result, "%6.1f %6.1f %6.1f %6.1f | ", crop.left, crop.top, crop.right,
crop.bottom);
- if (layerState.frameRate.rate.isValid() ||
- layerState.frameRate.type != FrameRateCompatibility::Default) {
- StringAppendF(&result, "%s %15s %17s", to_string(layerState.frameRate.rate).c_str(),
- frameRateCompatibilityString(layerState.frameRate.type).c_str(),
- toString(layerState.frameRate.seamlessness).c_str());
+ const auto frameRate = getFrameRateForLayerTree();
+ if (frameRate.rate.isValid() || frameRate.type != FrameRateCompatibility::Default) {
+ StringAppendF(&result, "%s %15s %17s", to_string(frameRate.rate).c_str(),
+ frameRateCompatibilityString(frameRate.type).c_str(),
+ toString(frameRate.seamlessness).c_str());
} else {
result.append(41, ' ');
}
diff --git a/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp b/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp
index 1bbe8e2..c8f4cb4 100644
--- a/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp
@@ -263,13 +263,13 @@
commitTransaction();
EXPECT_EQ(FRAME_RATE_VOTE3, parent->getFrameRateForLayerTree());
EXPECT_EQ(FRAME_RATE_VOTE2, child1->getFrameRateForLayerTree());
- EXPECT_EQ(FRAME_RATE_TREE, child2->getFrameRateForLayerTree());
+ EXPECT_EQ(FRAME_RATE_VOTE2, child2->getFrameRateForLayerTree());
child1->setFrameRate(FRAME_RATE_NO_VOTE);
commitTransaction();
EXPECT_EQ(FRAME_RATE_VOTE3, parent->getFrameRateForLayerTree());
- EXPECT_EQ(FRAME_RATE_TREE, child1->getFrameRateForLayerTree());
- EXPECT_EQ(FRAME_RATE_TREE, child2->getFrameRateForLayerTree());
+ EXPECT_EQ(FRAME_RATE_VOTE3, child1->getFrameRateForLayerTree());
+ EXPECT_EQ(FRAME_RATE_VOTE3, child2->getFrameRateForLayerTree());
parent->setFrameRate(FRAME_RATE_NO_VOTE);
commitTransaction();
@@ -293,8 +293,8 @@
parent->setFrameRate(FRAME_RATE_VOTE1);
commitTransaction();
EXPECT_EQ(FRAME_RATE_VOTE1, parent->getFrameRateForLayerTree());
- EXPECT_EQ(FRAME_RATE_TREE, child1->getFrameRateForLayerTree());
- EXPECT_EQ(FRAME_RATE_TREE, child2->getFrameRateForLayerTree());
+ EXPECT_EQ(FRAME_RATE_VOTE1, child1->getFrameRateForLayerTree());
+ EXPECT_EQ(FRAME_RATE_VOTE1, child2->getFrameRateForLayerTree());
parent->setFrameRate(FRAME_RATE_NO_VOTE);
commitTransaction();
@@ -356,14 +356,14 @@
parent->setFrameRate(FRAME_RATE_VOTE1);
commitTransaction();
EXPECT_EQ(FRAME_RATE_VOTE1, parent->getFrameRateForLayerTree());
- EXPECT_EQ(FRAME_RATE_TREE, child1->getFrameRateForLayerTree());
+ EXPECT_EQ(FRAME_RATE_VOTE1, child1->getFrameRateForLayerTree());
EXPECT_EQ(FRAME_RATE_NO_VOTE, child2->getFrameRateForLayerTree());
addChild(child1, child2);
commitTransaction();
EXPECT_EQ(FRAME_RATE_VOTE1, parent->getFrameRateForLayerTree());
- EXPECT_EQ(FRAME_RATE_TREE, child1->getFrameRateForLayerTree());
- EXPECT_EQ(FRAME_RATE_TREE, child2->getFrameRateForLayerTree());
+ EXPECT_EQ(FRAME_RATE_VOTE1, child1->getFrameRateForLayerTree());
+ EXPECT_EQ(FRAME_RATE_VOTE1, child2->getFrameRateForLayerTree());
parent->setFrameRate(FRAME_RATE_NO_VOTE);
commitTransaction();
@@ -387,13 +387,13 @@
parent->setFrameRate(FRAME_RATE_VOTE1);
commitTransaction();
EXPECT_EQ(FRAME_RATE_VOTE1, parent->getFrameRateForLayerTree());
- EXPECT_EQ(FRAME_RATE_TREE, child1->getFrameRateForLayerTree());
- EXPECT_EQ(FRAME_RATE_TREE, child2->getFrameRateForLayerTree());
+ EXPECT_EQ(FRAME_RATE_VOTE1, child1->getFrameRateForLayerTree());
+ EXPECT_EQ(FRAME_RATE_VOTE1, child2->getFrameRateForLayerTree());
removeChild(child1, child2);
commitTransaction();
EXPECT_EQ(FRAME_RATE_VOTE1, parent->getFrameRateForLayerTree());
- EXPECT_EQ(FRAME_RATE_TREE, child1->getFrameRateForLayerTree());
+ EXPECT_EQ(FRAME_RATE_VOTE1, child1->getFrameRateForLayerTree());
EXPECT_EQ(FRAME_RATE_NO_VOTE, child2->getFrameRateForLayerTree());
parent->setFrameRate(FRAME_RATE_NO_VOTE);