SF: fix getFrameRateForLayerTree
In commit bdda8f08e38620b071d1c77e8345b141f7fcedfe we removed the
wp<Layer> from LayerHistory and instead updated LayerHistory when
something changed in the Layer itself. That change didn't take into
account that the FrameRateForLayerTree for a layer might change
as a result of a setFrameRate called on a different Layer. In this change
we update the FrameRateForLayerTree for each layer that is impacted
by a setFrameRate call and update LayerHistory accordingly.
Test: atest SetFrameRateTest
Bug: 169873384
Bug: 183225713
Change-Id: Idf044e82225697e6132200dee9cec45b08fe4f5f
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index def2711..4fee723 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -129,7 +129,6 @@
mCurrentState.frameRateSelectionPriority = PRIORITY_UNSET;
mCurrentState.metadata = args.metadata;
mCurrentState.shadowRadius = 0.f;
- mCurrentState.treeHasFrameRateVote = false;
mCurrentState.fixedTransformHint = ui::Transform::ROT_INVALID;
mCurrentState.frameTimelineInfo = {};
mCurrentState.postTime = -1;
@@ -861,8 +860,15 @@
// list.
addSurfaceFrameDroppedForBuffer(bufferSurfaceFrame);
}
+ const bool frameRateVoteChanged =
+ mDrawingState.frameRateForLayerTree != stateToCommit.frameRateForLayerTree;
mDrawingState = stateToCommit;
+ if (frameRateVoteChanged) {
+ mFlinger->mScheduler->recordLayerHistory(this, systemTime(),
+ LayerHistory::LayerUpdateType::SetFrameRate);
+ }
+
// Set the present state for all bufferlessSurfaceFramesTX to Presented. The
// bufferSurfaceFrameTX will be presented in latchBuffer.
for (auto& [token, surfaceFrame] : mDrawingState.bufferlessSurfaceFramesTX) {
@@ -1265,8 +1271,7 @@
};
// update parents and children about the vote
- // 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
+ // First traverse the tree and count how many layers has votes.
int layersWithVote = 0;
traverseTree([&layersWithVote](Layer* layer) {
const auto layerVotedWithDefaultCompatibility =
@@ -1286,20 +1291,11 @@
}
});
- // Now update the other layers
+ // Now we can update the tree frame rate vote for each layer in the tree
+ const bool treeHasFrameRateVote = layersWithVote > 0;
bool transactionNeeded = false;
- traverseTree([layersWithVote, &transactionNeeded, this](Layer* layer) {
- const bool treeHasFrameRateVote = layersWithVote > 0;
- if (layer->mCurrentState.treeHasFrameRateVote != treeHasFrameRateVote) {
- layer->mCurrentState.sequence++;
- layer->mCurrentState.treeHasFrameRateVote = treeHasFrameRateVote;
- layer->mCurrentState.modified = true;
- layer->setTransactionFlags(eTransactionNeeded);
- transactionNeeded = true;
-
- mFlinger->mScheduler->recordLayerHistory(layer, systemTime(),
- LayerHistory::LayerUpdateType::SetFrameRate);
- }
+ traverseTree([treeHasFrameRateVote, &transactionNeeded](Layer* layer) {
+ transactionNeeded = layer->updateFrameRateForLayerTree(treeHasFrameRateVote);
});
if (transactionNeeded) {
@@ -1428,32 +1424,42 @@
return surfaceFrame;
}
-Layer::FrameRate Layer::getFrameRateForLayerTree() const {
- const auto frameRate = getDrawingState().frameRate;
+bool Layer::updateFrameRateForLayerTree(bool treeHasFrameRateVote) {
+ const auto updateCurrentState = [&](FrameRate frameRate) {
+ if (mCurrentState.frameRateForLayerTree == frameRate) {
+ return false;
+ }
+ mCurrentState.frameRateForLayerTree = frameRate;
+ mCurrentState.sequence++;
+ mCurrentState.modified = true;
+ setTransactionFlags(eTransactionNeeded);
+ return true;
+ };
+
+ const auto frameRate = mCurrentState.frameRate;
if (frameRate.rate.isValid() || frameRate.type == FrameRateCompatibility::NoVote) {
- return frameRate;
+ return updateCurrentState(frameRate);
}
// 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;
+ for (sp<Layer> parent = getParent(); parent; parent = parent->getParent()) {
+ if (parent->mCurrentState.frameRate.rate.isValid()) {
+ return updateCurrentState(parent->mCurrentState.frameRate);
}
}
// 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};
+ if (treeHasFrameRateVote) {
+ return updateCurrentState(FrameRate(Fps(0.0f), FrameRateCompatibility::NoVote));
}
- return frameRate;
+ return updateCurrentState(frameRate);
}
-// ----------------------------------------------------------------------------
-// pageflip handling...
-// ----------------------------------------------------------------------------
+Layer::FrameRate Layer::getFrameRateForLayerTree() const {
+ return getDrawingState().frameRateForLayerTree;
+}
bool Layer::isHiddenByPolicy() const {
const State& s(mDrawingState);