From 5dde597cabb5deff47a1e77c69a217c840893532 Mon Sep 17 00:00:00 2001 From: Ady Abraham Date: Wed, 13 May 2020 10:50:54 -0700 Subject: [PATCH] SurfaceFlinger: ignore invisible layers We keeps around layers that explicitly voted with setFrameRate API even if those are not visible. This is to be able to react when those become visible. However there is a bug in that logic that causes SurfaceFlinger to treat explicit invisible layers as Max. Bug: 153111478 Bug: 156506455 Test: adb shell /data/nativetest64/libsurfaceflinger_unittest/libsurfaceflinger_unittest Change-Id: I15dde0b79bf670874edee90336caa812f791cf26 --- .../Scheduler/LayerHistoryV2.cpp | 6 ++-- .../tests/unittests/LayerHistoryTestV2.cpp | 29 +++++++++++++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/services/surfaceflinger/Scheduler/LayerHistoryV2.cpp b/services/surfaceflinger/Scheduler/LayerHistoryV2.cpp index b067466f9a..e6c5cc9700 100644 --- a/services/surfaceflinger/Scheduler/LayerHistoryV2.cpp +++ b/services/surfaceflinger/Scheduler/LayerHistoryV2.cpp @@ -174,8 +174,10 @@ void LayerHistoryV2::partitionLayers(nsecs_t now) { return LayerVoteType::NoVote; } }(); - if (layer->isVisible() && (frameRate.rate > 0 || voteType == LayerVoteType::NoVote)) { - info->setLayerVote(voteType, frameRate.rate); + + if (frameRate.rate > 0 || voteType == LayerVoteType::NoVote) { + const auto type = layer->isVisible() ? voteType : LayerVoteType::NoVote; + info->setLayerVote(type, frameRate.rate); } else { info->resetLayerVote(); } diff --git a/services/surfaceflinger/tests/unittests/LayerHistoryTestV2.cpp b/services/surfaceflinger/tests/unittests/LayerHistoryTestV2.cpp index 6fca673f6b..431cf0f4b3 100644 --- a/services/surfaceflinger/tests/unittests/LayerHistoryTestV2.cpp +++ b/services/surfaceflinger/tests/unittests/LayerHistoryTestV2.cpp @@ -512,5 +512,34 @@ TEST_F(LayerHistoryTestV2, inactiveLayers) { EXPECT_EQ(1, frequentLayerCount(time)); } +TEST_F(LayerHistoryTestV2, invisibleExplicitLayer) { + auto explicitVisiblelayer = createLayer(); + auto explicitInvisiblelayer = createLayer(); + + EXPECT_CALL(*explicitVisiblelayer, isVisible()).WillRepeatedly(Return(true)); + EXPECT_CALL(*explicitVisiblelayer, getFrameRateForLayerTree()) + .WillRepeatedly(Return( + Layer::FrameRate(60.0f, Layer::FrameRateCompatibility::ExactOrMultiple))); + + EXPECT_CALL(*explicitInvisiblelayer, isVisible()).WillRepeatedly(Return(false)); + EXPECT_CALL(*explicitInvisiblelayer, getFrameRateForLayerTree()) + .WillRepeatedly(Return( + Layer::FrameRate(90.0f, Layer::FrameRateCompatibility::ExactOrMultiple))); + + nsecs_t time = systemTime(); + + // Post a buffer to the layers to make them active + history().record(explicitVisiblelayer.get(), time, time); + history().record(explicitInvisiblelayer.get(), time, time); + + EXPECT_EQ(2, layerCount()); + ASSERT_EQ(1, history().summarize(time).size()); + EXPECT_EQ(LayerHistory::LayerVoteType::ExplicitExactOrMultiple, + history().summarize(time)[0].vote); + EXPECT_FLOAT_EQ(60.0f, history().summarize(time)[0].desiredRefreshRate); + EXPECT_EQ(2, activeLayerCount()); + EXPECT_EQ(2, frequentLayerCount(time)); +} + } // namespace } // namespace android::scheduler