Loading services/surfaceflinger/Scheduler/LayerHistory.cpp +8 −1 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ #include "LayerHistory.h" #include <android-base/stringprintf.h> #include <com_android_graphics_surfaceflinger_flags.h> #include <cutils/properties.h> #include <gui/TraceUtils.h> #include <utils/Log.h> Loading @@ -39,8 +40,14 @@ namespace android::scheduler { namespace { using namespace com::android::graphics::surfaceflinger; bool isLayerActive(const LayerInfo& info, nsecs_t threshold) { // Layers with an explicit frame rate or frame rate category are always kept active, if (flags::misc1() && !info.isVisible()) { return false; } // Layers with an explicit frame rate or frame rate category are kept active, // but ignore NoVote. if (info.getSetFrameRateVote().isValid() && !info.getSetFrameRateVote().isNoVote()) { return true; Loading services/surfaceflinger/Scheduler/LayerInfo.cpp +9 −6 Original line number Diff line number Diff line Loading @@ -304,12 +304,15 @@ LayerInfo::RefreshRateVotes LayerInfo::getRefreshRateVote(const RefreshRateSelec if (mLayerVote.type != LayerHistory::LayerVoteType::Heuristic) { if (mLayerVote.category != FrameRateCategory::Default) { ATRACE_FORMAT_INSTANT("ExplicitCategory (%s)", const auto voteType = mLayerVote.type == LayerHistory::LayerVoteType::NoVote ? LayerHistory::LayerVoteType::NoVote : LayerHistory::LayerVoteType::ExplicitCategory; ATRACE_FORMAT_INSTANT("Vote %s (category=%s)", ftl::enum_string(voteType).c_str(), ftl::enum_string(mLayerVote.category).c_str()); ALOGV("%s uses frame rate category: %d", mName.c_str(), static_cast<int>(mLayerVote.category)); votes.push_back({LayerHistory::LayerVoteType::ExplicitCategory, Fps(), Seamlessness::Default, mLayerVote.category, ALOGV("%s voted %s with category: %s", mName.c_str(), ftl::enum_string(voteType).c_str(), ftl::enum_string(mLayerVote.category).c_str()); votes.push_back({voteType, Fps(), Seamlessness::Default, mLayerVote.category, mLayerVote.categorySmoothSwitchOnly}); } Loading services/surfaceflinger/Scheduler/RefreshRateSelector.cpp +0 −1 Original line number Diff line number Diff line Loading @@ -401,7 +401,6 @@ float RefreshRateSelector::calculateDistanceScoreFromMax(Fps refreshRate) const float RefreshRateSelector::calculateLayerScoreLocked(const LayerRequirement& layer, Fps refreshRate, bool isSeamlessSwitch) const { ATRACE_CALL(); // Slightly prefer seamless switches. constexpr float kSeamedSwitchPenalty = 0.95f; const float seamlessness = isSeamlessSwitch ? 1.0f : kSeamedSwitchPenalty; Loading services/surfaceflinger/tests/unittests/LayerHistoryIntegrationTest.cpp +31 −1 Original line number Diff line number Diff line Loading @@ -18,12 +18,14 @@ #define LOG_TAG "LayerHistoryIntegrationTest" #include <Layer.h> #include <com_android_graphics_surfaceflinger_flags.h> #include <gmock/gmock.h> #include <gtest/gtest.h> #include <log/log.h> #include <renderengine/mock/FakeExternalTexture.h> #include "FlagUtils.h" #include "FpsOps.h" #include "LayerHierarchyTest.h" #include "Scheduler/LayerHistory.h" Loading @@ -36,6 +38,7 @@ namespace android::scheduler { using android::mock::createDisplayMode; using namespace com::android::graphics::surfaceflinger; class LayerHistoryIntegrationTest : public surfaceflinger::frontend::LayerSnapshotTestBase { protected: Loading Loading @@ -492,7 +495,9 @@ TEST_F(LayerHistoryIntegrationTest, inactiveLayers) { EXPECT_EQ(1, frequentLayerCount(time)); } TEST_F(LayerHistoryIntegrationTest, invisibleExplicitLayer) { TEST_F(LayerHistoryIntegrationTest, invisibleExplicitLayerIsActive) { SET_FLAG_FOR_TEST(flags::misc1, false); auto explicitVisiblelayer = createLegacyAndFrontedEndLayer(1); auto explicitInvisiblelayer = createLegacyAndFrontedEndLayer(2); hideLayer(2); Loading @@ -515,6 +520,31 @@ TEST_F(LayerHistoryIntegrationTest, invisibleExplicitLayer) { EXPECT_EQ(2, frequentLayerCount(time)); } TEST_F(LayerHistoryIntegrationTest, invisibleExplicitLayerIsNotActive) { SET_FLAG_FOR_TEST(flags::misc1, true); auto explicitVisiblelayer = createLegacyAndFrontedEndLayer(1); auto explicitInvisiblelayer = createLegacyAndFrontedEndLayer(2); hideLayer(2); setFrameRate(1, 60.0f, ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_FIXED_SOURCE, ANATIVEWINDOW_CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS); setFrameRate(2, 90.0f, ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_FIXED_SOURCE, ANATIVEWINDOW_CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS); nsecs_t time = systemTime(); // Post a buffer to the layers to make them active setBufferWithPresentTime(explicitVisiblelayer, time); setBufferWithPresentTime(explicitInvisiblelayer, time); EXPECT_EQ(2u, layerCount()); ASSERT_EQ(1u, summarizeLayerHistory(time).size()); EXPECT_EQ(LayerHistory::LayerVoteType::ExplicitExactOrMultiple, summarizeLayerHistory(time)[0].vote); EXPECT_EQ(60_Hz, summarizeLayerHistory(time)[0].desiredRefreshRate); EXPECT_EQ(1u, activeLayerCount()); EXPECT_EQ(1, frequentLayerCount(time)); } TEST_F(LayerHistoryIntegrationTest, infrequentAnimatingLayer) { auto layer = createLegacyAndFrontedEndLayer(1); Loading services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp +66 −0 Original line number Diff line number Diff line Loading @@ -22,10 +22,12 @@ #define LOG_TAG "LayerHistoryTest" #include <Layer.h> #include <com_android_graphics_surfaceflinger_flags.h> #include <gmock/gmock.h> #include <gtest/gtest.h> #include <log/log.h> #include "FlagUtils.h" #include "FpsOps.h" #include "Scheduler/LayerHistory.h" #include "Scheduler/LayerInfo.h" Loading Loading @@ -149,6 +151,8 @@ protected: namespace { using namespace com::android::graphics::surfaceflinger; TEST_F(LayerHistoryTest, singleLayerNoVoteDefaultCompatibility) { const auto layer = createLayer(); EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); Loading Loading @@ -555,6 +559,33 @@ TEST_F(LayerHistoryTest, oneLayerExplicitVoteWithCategory) { EXPECT_EQ(FrameRateCategory::High, summarizeLayerHistory(time)[0].frameRateCategory); } TEST_F(LayerHistoryTest, oneLayerExplicitVoteWithCategoryNotVisibleDoesNotVote) { SET_FLAG_FOR_TEST(flags::misc1, true); auto layer = createLayer(); EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(false)); EXPECT_CALL(*layer, getFrameRateForLayerTree()) .WillRepeatedly( Return(Layer::FrameRate(12.34_Hz, Layer::FrameRateCompatibility::Default, Seamlessness::OnlySeamless, FrameRateCategory::High))); EXPECT_EQ(1, layerCount()); EXPECT_EQ(0, activeLayerCount()); nsecs_t time = systemTime(); for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { history().record(layer->getSequence(), layer->getLayerProps(), time, time, LayerHistory::LayerUpdateType::Buffer); time += HI_FPS_PERIOD; } // Layer is not visible, so the layer is moved to inactive, infrequent, and it will not have // votes to consider for refresh rate selection. ASSERT_EQ(0, summarizeLayerHistory(time).size()); EXPECT_EQ(0, activeLayerCount()); EXPECT_EQ(0, frequentLayerCount(time)); } TEST_F(LayerHistoryTest, multipleLayers) { auto layer1 = createLayer("A"); auto layer2 = createLayer("B"); Loading Loading @@ -780,6 +811,8 @@ TEST_F(LayerHistoryTest, inactiveLayers) { } TEST_F(LayerHistoryTest, invisibleExplicitLayer) { SET_FLAG_FOR_TEST(flags::misc1, false); auto explicitVisiblelayer = createLayer(); auto explicitInvisiblelayer = createLayer(); Loading Loading @@ -810,6 +843,39 @@ TEST_F(LayerHistoryTest, invisibleExplicitLayer) { EXPECT_EQ(2, frequentLayerCount(time)); } TEST_F(LayerHistoryTest, invisibleExplicitLayerDoesNotVote) { SET_FLAG_FOR_TEST(flags::misc1, true); auto explicitVisiblelayer = createLayer(); auto explicitInvisiblelayer = createLayer(); EXPECT_CALL(*explicitVisiblelayer, isVisible()).WillRepeatedly(Return(true)); EXPECT_CALL(*explicitVisiblelayer, getFrameRateForLayerTree()) .WillRepeatedly(Return( Layer::FrameRate(60_Hz, Layer::FrameRateCompatibility::ExactOrMultiple))); EXPECT_CALL(*explicitInvisiblelayer, isVisible()).WillRepeatedly(Return(false)); EXPECT_CALL(*explicitInvisiblelayer, getFrameRateForLayerTree()) .WillRepeatedly(Return( Layer::FrameRate(90_Hz, Layer::FrameRateCompatibility::ExactOrMultiple))); nsecs_t time = systemTime(); // Post a buffer to the layers to make them active history().record(explicitVisiblelayer->getSequence(), explicitVisiblelayer->getLayerProps(), time, time, LayerHistory::LayerUpdateType::Buffer); history().record(explicitInvisiblelayer->getSequence(), explicitInvisiblelayer->getLayerProps(), time, time, LayerHistory::LayerUpdateType::Buffer); EXPECT_EQ(2, layerCount()); ASSERT_EQ(1, summarizeLayerHistory(time).size()); EXPECT_EQ(LayerHistory::LayerVoteType::ExplicitExactOrMultiple, summarizeLayerHistory(time)[0].vote); EXPECT_EQ(60_Hz, summarizeLayerHistory(time)[0].desiredRefreshRate); EXPECT_EQ(1, activeLayerCount()); EXPECT_EQ(1, frequentLayerCount(time)); } TEST_F(LayerHistoryTest, infrequentAnimatingLayer) { auto layer = createLayer(); Loading Loading
services/surfaceflinger/Scheduler/LayerHistory.cpp +8 −1 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ #include "LayerHistory.h" #include <android-base/stringprintf.h> #include <com_android_graphics_surfaceflinger_flags.h> #include <cutils/properties.h> #include <gui/TraceUtils.h> #include <utils/Log.h> Loading @@ -39,8 +40,14 @@ namespace android::scheduler { namespace { using namespace com::android::graphics::surfaceflinger; bool isLayerActive(const LayerInfo& info, nsecs_t threshold) { // Layers with an explicit frame rate or frame rate category are always kept active, if (flags::misc1() && !info.isVisible()) { return false; } // Layers with an explicit frame rate or frame rate category are kept active, // but ignore NoVote. if (info.getSetFrameRateVote().isValid() && !info.getSetFrameRateVote().isNoVote()) { return true; Loading
services/surfaceflinger/Scheduler/LayerInfo.cpp +9 −6 Original line number Diff line number Diff line Loading @@ -304,12 +304,15 @@ LayerInfo::RefreshRateVotes LayerInfo::getRefreshRateVote(const RefreshRateSelec if (mLayerVote.type != LayerHistory::LayerVoteType::Heuristic) { if (mLayerVote.category != FrameRateCategory::Default) { ATRACE_FORMAT_INSTANT("ExplicitCategory (%s)", const auto voteType = mLayerVote.type == LayerHistory::LayerVoteType::NoVote ? LayerHistory::LayerVoteType::NoVote : LayerHistory::LayerVoteType::ExplicitCategory; ATRACE_FORMAT_INSTANT("Vote %s (category=%s)", ftl::enum_string(voteType).c_str(), ftl::enum_string(mLayerVote.category).c_str()); ALOGV("%s uses frame rate category: %d", mName.c_str(), static_cast<int>(mLayerVote.category)); votes.push_back({LayerHistory::LayerVoteType::ExplicitCategory, Fps(), Seamlessness::Default, mLayerVote.category, ALOGV("%s voted %s with category: %s", mName.c_str(), ftl::enum_string(voteType).c_str(), ftl::enum_string(mLayerVote.category).c_str()); votes.push_back({voteType, Fps(), Seamlessness::Default, mLayerVote.category, mLayerVote.categorySmoothSwitchOnly}); } Loading
services/surfaceflinger/Scheduler/RefreshRateSelector.cpp +0 −1 Original line number Diff line number Diff line Loading @@ -401,7 +401,6 @@ float RefreshRateSelector::calculateDistanceScoreFromMax(Fps refreshRate) const float RefreshRateSelector::calculateLayerScoreLocked(const LayerRequirement& layer, Fps refreshRate, bool isSeamlessSwitch) const { ATRACE_CALL(); // Slightly prefer seamless switches. constexpr float kSeamedSwitchPenalty = 0.95f; const float seamlessness = isSeamlessSwitch ? 1.0f : kSeamedSwitchPenalty; Loading
services/surfaceflinger/tests/unittests/LayerHistoryIntegrationTest.cpp +31 −1 Original line number Diff line number Diff line Loading @@ -18,12 +18,14 @@ #define LOG_TAG "LayerHistoryIntegrationTest" #include <Layer.h> #include <com_android_graphics_surfaceflinger_flags.h> #include <gmock/gmock.h> #include <gtest/gtest.h> #include <log/log.h> #include <renderengine/mock/FakeExternalTexture.h> #include "FlagUtils.h" #include "FpsOps.h" #include "LayerHierarchyTest.h" #include "Scheduler/LayerHistory.h" Loading @@ -36,6 +38,7 @@ namespace android::scheduler { using android::mock::createDisplayMode; using namespace com::android::graphics::surfaceflinger; class LayerHistoryIntegrationTest : public surfaceflinger::frontend::LayerSnapshotTestBase { protected: Loading Loading @@ -492,7 +495,9 @@ TEST_F(LayerHistoryIntegrationTest, inactiveLayers) { EXPECT_EQ(1, frequentLayerCount(time)); } TEST_F(LayerHistoryIntegrationTest, invisibleExplicitLayer) { TEST_F(LayerHistoryIntegrationTest, invisibleExplicitLayerIsActive) { SET_FLAG_FOR_TEST(flags::misc1, false); auto explicitVisiblelayer = createLegacyAndFrontedEndLayer(1); auto explicitInvisiblelayer = createLegacyAndFrontedEndLayer(2); hideLayer(2); Loading @@ -515,6 +520,31 @@ TEST_F(LayerHistoryIntegrationTest, invisibleExplicitLayer) { EXPECT_EQ(2, frequentLayerCount(time)); } TEST_F(LayerHistoryIntegrationTest, invisibleExplicitLayerIsNotActive) { SET_FLAG_FOR_TEST(flags::misc1, true); auto explicitVisiblelayer = createLegacyAndFrontedEndLayer(1); auto explicitInvisiblelayer = createLegacyAndFrontedEndLayer(2); hideLayer(2); setFrameRate(1, 60.0f, ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_FIXED_SOURCE, ANATIVEWINDOW_CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS); setFrameRate(2, 90.0f, ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_FIXED_SOURCE, ANATIVEWINDOW_CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS); nsecs_t time = systemTime(); // Post a buffer to the layers to make them active setBufferWithPresentTime(explicitVisiblelayer, time); setBufferWithPresentTime(explicitInvisiblelayer, time); EXPECT_EQ(2u, layerCount()); ASSERT_EQ(1u, summarizeLayerHistory(time).size()); EXPECT_EQ(LayerHistory::LayerVoteType::ExplicitExactOrMultiple, summarizeLayerHistory(time)[0].vote); EXPECT_EQ(60_Hz, summarizeLayerHistory(time)[0].desiredRefreshRate); EXPECT_EQ(1u, activeLayerCount()); EXPECT_EQ(1, frequentLayerCount(time)); } TEST_F(LayerHistoryIntegrationTest, infrequentAnimatingLayer) { auto layer = createLegacyAndFrontedEndLayer(1); Loading
services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp +66 −0 Original line number Diff line number Diff line Loading @@ -22,10 +22,12 @@ #define LOG_TAG "LayerHistoryTest" #include <Layer.h> #include <com_android_graphics_surfaceflinger_flags.h> #include <gmock/gmock.h> #include <gtest/gtest.h> #include <log/log.h> #include "FlagUtils.h" #include "FpsOps.h" #include "Scheduler/LayerHistory.h" #include "Scheduler/LayerInfo.h" Loading Loading @@ -149,6 +151,8 @@ protected: namespace { using namespace com::android::graphics::surfaceflinger; TEST_F(LayerHistoryTest, singleLayerNoVoteDefaultCompatibility) { const auto layer = createLayer(); EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); Loading Loading @@ -555,6 +559,33 @@ TEST_F(LayerHistoryTest, oneLayerExplicitVoteWithCategory) { EXPECT_EQ(FrameRateCategory::High, summarizeLayerHistory(time)[0].frameRateCategory); } TEST_F(LayerHistoryTest, oneLayerExplicitVoteWithCategoryNotVisibleDoesNotVote) { SET_FLAG_FOR_TEST(flags::misc1, true); auto layer = createLayer(); EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(false)); EXPECT_CALL(*layer, getFrameRateForLayerTree()) .WillRepeatedly( Return(Layer::FrameRate(12.34_Hz, Layer::FrameRateCompatibility::Default, Seamlessness::OnlySeamless, FrameRateCategory::High))); EXPECT_EQ(1, layerCount()); EXPECT_EQ(0, activeLayerCount()); nsecs_t time = systemTime(); for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { history().record(layer->getSequence(), layer->getLayerProps(), time, time, LayerHistory::LayerUpdateType::Buffer); time += HI_FPS_PERIOD; } // Layer is not visible, so the layer is moved to inactive, infrequent, and it will not have // votes to consider for refresh rate selection. ASSERT_EQ(0, summarizeLayerHistory(time).size()); EXPECT_EQ(0, activeLayerCount()); EXPECT_EQ(0, frequentLayerCount(time)); } TEST_F(LayerHistoryTest, multipleLayers) { auto layer1 = createLayer("A"); auto layer2 = createLayer("B"); Loading Loading @@ -780,6 +811,8 @@ TEST_F(LayerHistoryTest, inactiveLayers) { } TEST_F(LayerHistoryTest, invisibleExplicitLayer) { SET_FLAG_FOR_TEST(flags::misc1, false); auto explicitVisiblelayer = createLayer(); auto explicitInvisiblelayer = createLayer(); Loading Loading @@ -810,6 +843,39 @@ TEST_F(LayerHistoryTest, invisibleExplicitLayer) { EXPECT_EQ(2, frequentLayerCount(time)); } TEST_F(LayerHistoryTest, invisibleExplicitLayerDoesNotVote) { SET_FLAG_FOR_TEST(flags::misc1, true); auto explicitVisiblelayer = createLayer(); auto explicitInvisiblelayer = createLayer(); EXPECT_CALL(*explicitVisiblelayer, isVisible()).WillRepeatedly(Return(true)); EXPECT_CALL(*explicitVisiblelayer, getFrameRateForLayerTree()) .WillRepeatedly(Return( Layer::FrameRate(60_Hz, Layer::FrameRateCompatibility::ExactOrMultiple))); EXPECT_CALL(*explicitInvisiblelayer, isVisible()).WillRepeatedly(Return(false)); EXPECT_CALL(*explicitInvisiblelayer, getFrameRateForLayerTree()) .WillRepeatedly(Return( Layer::FrameRate(90_Hz, Layer::FrameRateCompatibility::ExactOrMultiple))); nsecs_t time = systemTime(); // Post a buffer to the layers to make them active history().record(explicitVisiblelayer->getSequence(), explicitVisiblelayer->getLayerProps(), time, time, LayerHistory::LayerUpdateType::Buffer); history().record(explicitInvisiblelayer->getSequence(), explicitInvisiblelayer->getLayerProps(), time, time, LayerHistory::LayerUpdateType::Buffer); EXPECT_EQ(2, layerCount()); ASSERT_EQ(1, summarizeLayerHistory(time).size()); EXPECT_EQ(LayerHistory::LayerVoteType::ExplicitExactOrMultiple, summarizeLayerHistory(time)[0].vote); EXPECT_EQ(60_Hz, summarizeLayerHistory(time)[0].desiredRefreshRate); EXPECT_EQ(1, activeLayerCount()); EXPECT_EQ(1, frequentLayerCount(time)); } TEST_F(LayerHistoryTest, infrequentAnimatingLayer) { auto layer = createLayer(); Loading