diff options
author | 2024-03-14 18:40:15 -0700 | |
---|---|---|
committer | 2024-03-19 14:08:40 -0700 | |
commit | 45681988238f32330f64161a8897c02f6d42b5ed (patch) | |
tree | a7a90cebae6aa610ba7f9f364424e2971e5945b4 | |
parent | 52f0abecf3d5d7e9dbd0e4b3824531e346c8f546 (diff) |
Add MRR guard logic to SF scheduler
Uses a flag to guard the new dVRR scheduler features
from MRR devices. This is to easily allow development on
dVRR devices and MRR devices separately.
Bug: 330224639
Test: atest libsurfaceflinger_unittest
Test: atest CtsSurfaceControlTestsStaging
Test: dumpsys and observe no category or GTE
Change-Id: I8be520b5630c1a8fbde5f0fb2265e803e46983a8
9 files changed, 108 insertions, 11 deletions
diff --git a/services/surfaceflinger/Scheduler/LayerHistory.cpp b/services/surfaceflinger/Scheduler/LayerHistory.cpp index b8d5e76358..974c837139 100644 --- a/services/surfaceflinger/Scheduler/LayerHistory.cpp +++ b/services/surfaceflinger/Scheduler/LayerHistory.cpp @@ -40,14 +40,15 @@ namespace android::scheduler { namespace { -bool isLayerActive(const LayerInfo& info, nsecs_t threshold) { +bool isLayerActive(const LayerInfo& info, nsecs_t threshold, bool isVrrDevice) { if (FlagManager::getInstance().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()) { + const auto frameRate = info.getSetFrameRateVote(); + if (frameRate.isValid() && !frameRate.isNoVote() && frameRate.isVoteValidForMrr(isVrrDevice)) { return true; } @@ -194,7 +195,7 @@ auto LayerHistory::summarize(const RefreshRateSelector& selector, nsecs_t now) - std::lock_guard lock(mLock); - partitionLayers(now); + partitionLayers(now, selector.isVrrDevice()); for (const auto& [key, value] : mActiveLayerInfos) { auto& info = value.second; @@ -236,7 +237,7 @@ auto LayerHistory::summarize(const RefreshRateSelector& selector, nsecs_t now) - return summary; } -void LayerHistory::partitionLayers(nsecs_t now) { +void LayerHistory::partitionLayers(nsecs_t now, bool isVrrDevice) { ATRACE_CALL(); const nsecs_t threshold = getActiveLayerThreshold(now); @@ -244,7 +245,7 @@ void LayerHistory::partitionLayers(nsecs_t now) { LayerInfos::iterator it = mInactiveLayerInfos.begin(); while (it != mInactiveLayerInfos.end()) { auto& [layerUnsafe, info] = it->second; - if (isLayerActive(*info, threshold)) { + if (isLayerActive(*info, threshold, isVrrDevice)) { // move this to the active map mActiveLayerInfos.insert({it->first, std::move(it->second)}); @@ -262,7 +263,7 @@ void LayerHistory::partitionLayers(nsecs_t now) { it = mActiveLayerInfos.begin(); while (it != mActiveLayerInfos.end()) { auto& [layerUnsafe, info] = it->second; - if (isLayerActive(*info, threshold)) { + if (isLayerActive(*info, threshold, isVrrDevice)) { // Set layer vote if set const auto frameRate = info->getSetFrameRateVote(); @@ -305,7 +306,7 @@ void LayerHistory::partitionLayers(nsecs_t now) { trace(*info, gameFrameRateOverrideVoteType, gameModeFrameRateOverride.getIntValue()); } - } else if (frameRate.isValid()) { + } else if (frameRate.isValid() && frameRate.isVoteValidForMrr(isVrrDevice)) { info->setLayerVote({setFrameRateVoteType, frameRate.vote.rate, frameRate.vote.seamlessness, frameRate.category}); if (CC_UNLIKELY(mTraceEnabled)) { @@ -321,14 +322,30 @@ void LayerHistory::partitionLayers(nsecs_t now) { gameDefaultFrameRateOverride.getIntValue()); } } else { + if (frameRate.isValid() && !frameRate.isVoteValidForMrr(isVrrDevice)) { + ATRACE_FORMAT_INSTANT("Reset layer to ignore explicit vote on MRR %s: %s " + "%s %s", + info->getName().c_str(), + ftl::enum_string(frameRate.vote.type).c_str(), + to_string(frameRate.vote.rate).c_str(), + ftl::enum_string(frameRate.category).c_str()); + } info->resetLayerVote(); } } else { - if (frameRate.isValid()) { + if (frameRate.isValid() && frameRate.isVoteValidForMrr(isVrrDevice)) { const auto type = info->isVisible() ? voteType : LayerVoteType::NoVote; info->setLayerVote({type, frameRate.vote.rate, frameRate.vote.seamlessness, frameRate.category}); } else { + if (!frameRate.isVoteValidForMrr(isVrrDevice)) { + ATRACE_FORMAT_INSTANT("Reset layer to ignore explicit vote on MRR %s: %s " + "%s %s", + info->getName().c_str(), + ftl::enum_string(frameRate.vote.type).c_str(), + to_string(frameRate.vote.rate).c_str(), + ftl::enum_string(frameRate.category).c_str()); + } info->resetLayerVote(); } } diff --git a/services/surfaceflinger/Scheduler/LayerHistory.h b/services/surfaceflinger/Scheduler/LayerHistory.h index a6f1b56bf2..c09f148a9b 100644 --- a/services/surfaceflinger/Scheduler/LayerHistory.h +++ b/services/surfaceflinger/Scheduler/LayerHistory.h @@ -111,9 +111,12 @@ private: std::string dumpGameFrameRateOverridesLocked() const REQUIRES(mLock); // Iterates over layers maps moving all active layers to mActiveLayerInfos and all inactive - // layers to mInactiveLayerInfos. + // layers to mInactiveLayerInfos. Layer's active state is determined by multiple factors + // such as update activity, visibility, and frame rate vote. // worst case time complexity is O(2 * inactive + active) - void partitionLayers(nsecs_t now) REQUIRES(mLock); + // now: the current time (system time) when calling the method + // isVrrDevice: true if the device has DisplayMode with VrrConfig specified. + void partitionLayers(nsecs_t now, bool isVrrDevice) REQUIRES(mLock); enum class LayerStatus { NotFound, diff --git a/services/surfaceflinger/Scheduler/LayerInfo.cpp b/services/surfaceflinger/Scheduler/LayerInfo.cpp index 9745452e89..1bc4ac2f11 100644 --- a/services/surfaceflinger/Scheduler/LayerInfo.cpp +++ b/services/surfaceflinger/Scheduler/LayerInfo.cpp @@ -566,6 +566,18 @@ bool LayerInfo::FrameRate::isValid() const { return isNoVote() || vote.rate.isValid() || category != FrameRateCategory::Default; } +bool LayerInfo::FrameRate::isVoteValidForMrr(bool isVrrDevice) const { + if (isVrrDevice || FlagManager::getInstance().frame_rate_category_mrr()) { + return true; + } + + if (category == FrameRateCategory::Default && vote.type != FrameRateCompatibility::Gte) { + return true; + } + + return false; +} + std::ostream& operator<<(std::ostream& stream, const LayerInfo::FrameRate& rate) { return stream << "{rate=" << rate.vote.rate << " type=" << ftl::enum_string(rate.vote.type) << " seamlessness=" << ftl::enum_string(rate.vote.seamlessness) << '}'; diff --git a/services/surfaceflinger/Scheduler/LayerInfo.h b/services/surfaceflinger/Scheduler/LayerInfo.h index 326e444815..40903ed7c8 100644 --- a/services/surfaceflinger/Scheduler/LayerInfo.h +++ b/services/surfaceflinger/Scheduler/LayerInfo.h @@ -146,6 +146,10 @@ public: // selection. bool isNoVote() const; + // Checks whether the given FrameRate's vote specifications is valid for MRR devices + // given the current flagging. + bool isVoteValidForMrr(bool isVrrDevice) const; + private: static Seamlessness getSeamlessness(Fps rate, Seamlessness seamlessness) { if (!rate.isValid()) { diff --git a/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp b/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp index ad59f1a574..ae646a0885 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp +++ b/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp @@ -1216,6 +1216,8 @@ void RefreshRateSelector::setActiveMode(DisplayModeId modeId, Fps renderFrameRat LOG_ALWAYS_FATAL_IF(!activeModeOpt); mActiveModeOpt.emplace(FrameRateMode{renderFrameRate, ftl::as_non_null(activeModeOpt->get())}); + mIsVrrDevice = FlagManager::getInstance().vrr_config() && + activeModeOpt->get()->getVrrConfig().has_value(); } RefreshRateSelector::RefreshRateSelector(DisplayModes modes, DisplayModeId activeModeId, @@ -1429,7 +1431,8 @@ void RefreshRateSelector::constructAvailableRefreshRates() { } return str; }; - ALOGV("%s render rates: %s", rangeName, stringifyModes().c_str()); + ALOGV("%s render rates: %s, isVrrDevice? %d", rangeName, stringifyModes().c_str(), + mIsVrrDevice); return frameRateModes; }; @@ -1438,6 +1441,11 @@ void RefreshRateSelector::constructAvailableRefreshRates() { mAppRequestFrameRates = filterRefreshRates(policy->appRequestRanges, "app request"); } +bool RefreshRateSelector::isVrrDevice() const { + std::lock_guard lock(mLock); + return mIsVrrDevice; +} + Fps RefreshRateSelector::findClosestKnownFrameRate(Fps frameRate) const { using namespace fps_approx_ops; diff --git a/services/surfaceflinger/Scheduler/RefreshRateSelector.h b/services/surfaceflinger/Scheduler/RefreshRateSelector.h index 6051e8935d..a6b02369ad 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateSelector.h +++ b/services/surfaceflinger/Scheduler/RefreshRateSelector.h @@ -406,6 +406,8 @@ public: std::chrono::milliseconds getIdleTimerTimeout(); + bool isVrrDevice() const; + private: friend struct TestableRefreshRateSelector; @@ -513,6 +515,9 @@ private: std::vector<FrameRateMode> mPrimaryFrameRates GUARDED_BY(mLock); std::vector<FrameRateMode> mAppRequestFrameRates GUARDED_BY(mLock); + // Caches whether the device is VRR-compatible based on the active display mode. + bool mIsVrrDevice GUARDED_BY(mLock) = false; + Policy mDisplayManagerPolicy GUARDED_BY(mLock); std::optional<Policy> mOverridePolicy GUARDED_BY(mLock); diff --git a/services/surfaceflinger/tests/unittests/LayerHistoryIntegrationTest.cpp b/services/surfaceflinger/tests/unittests/LayerHistoryIntegrationTest.cpp index 110f324c8b..2fb80b146e 100644 --- a/services/surfaceflinger/tests/unittests/LayerHistoryIntegrationTest.cpp +++ b/services/surfaceflinger/tests/unittests/LayerHistoryIntegrationTest.cpp @@ -274,6 +274,8 @@ TEST_F(LayerHistoryIntegrationTest, oneLayerExplicitExactVote) { } TEST_F(LayerHistoryIntegrationTest, oneLayerExplicitCategory) { + SET_FLAG_FOR_TEST(flags::frame_rate_category_mrr, true); + createLegacyAndFrontedEndLayer(1); setFrameRateCategory(1, ANATIVEWINDOW_FRAME_RATE_CATEGORY_HIGH); diff --git a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp index 9b8ff42782..c63aaeb487 100644 --- a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp +++ b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp @@ -548,7 +548,41 @@ TEST_F(LayerHistoryTest, oneLayerExplicitExactVote) { EXPECT_EQ(0, frequentLayerCount(time)); } +TEST_F(LayerHistoryTest, oneLayerExplicitVoteWithCategory_vrrFeatureOff) { + SET_FLAG_FOR_TEST(flags::frame_rate_category_mrr, false); + + auto layer = createLayer(); + EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); + EXPECT_CALL(*layer, getFrameRateForLayerTree()) + .WillRepeatedly( + Return(Layer::FrameRate(73.4_Hz, Layer::FrameRateCompatibility::Default, + Seamlessness::OnlySeamless, FrameRateCategory::High))); + + // Set default to Min so it is obvious that the vote reset triggered. + setDefaultLayerVote(layer.get(), LayerHistory::LayerVoteType::Min); + + 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; + } + + // There is only 1 LayerRequirement due to the disabled flag frame_rate_category_mrr. + ASSERT_EQ(1, summarizeLayerHistory(time).size()); + EXPECT_EQ(1, activeLayerCount()); + EXPECT_EQ(1, frequentLayerCount(time)); + EXPECT_EQ(LayerHistory::LayerVoteType::Min, summarizeLayerHistory(time)[0].vote); + EXPECT_EQ(0_Hz, summarizeLayerHistory(time)[0].desiredRefreshRate); + EXPECT_EQ(FrameRateCategory::Default, summarizeLayerHistory(time)[0].frameRateCategory); +} + TEST_F(LayerHistoryTest, oneLayerExplicitCategory) { + SET_FLAG_FOR_TEST(flags::frame_rate_category_mrr, true); + auto layer = createLayer(); EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); EXPECT_CALL(*layer, getFrameRateForLayerTree()) @@ -588,6 +622,8 @@ TEST_F(LayerHistoryTest, oneLayerExplicitCategory) { // This test case should be the same as oneLayerNoVote except instead of layer vote is NoVote, // the category is NoPreference. TEST_F(LayerHistoryTest, oneLayerCategoryNoPreference) { + SET_FLAG_FOR_TEST(flags::frame_rate_category_mrr, true); + auto layer = createLayer(); EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); EXPECT_CALL(*layer, getFrameRateForLayerTree()) @@ -617,6 +653,8 @@ TEST_F(LayerHistoryTest, oneLayerCategoryNoPreference) { } TEST_F(LayerHistoryTest, oneLayerExplicitVoteWithCategory) { + SET_FLAG_FOR_TEST(flags::frame_rate_category_mrr, true); + auto layer = createLayer(); EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); EXPECT_CALL(*layer, getFrameRateForLayerTree()) diff --git a/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp b/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp index 3baa48d002..94989aac84 100644 --- a/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp +++ b/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp @@ -17,6 +17,7 @@ #include <gmock/gmock.h> #include <gtest/gtest.h> +#include <common/test/FlagUtils.h> #include <renderengine/mock/FakeExternalTexture.h> #include "FrontEnd/LayerHierarchy.h" @@ -26,6 +27,8 @@ #include "LayerHierarchyTest.h" #include "ui/GraphicTypes.h" +#include <com_android_graphics_surfaceflinger_flags.h> + #define UPDATE_AND_VERIFY(BUILDER, ...) \ ({ \ SCOPED_TRACE(""); \ @@ -42,6 +45,7 @@ namespace android::surfaceflinger::frontend { using ftl::Flags; using namespace ftl::flag_operators; +using namespace com::android::graphics::surfaceflinger; // To run test: /** @@ -668,6 +672,8 @@ TEST_F(LayerSnapshotTest, translateDataspace) { // This test is similar to "frameRate" test case but checks that the setFrameRateCategory API // interaction also works correctly with the setFrameRate API within SF frontend. TEST_F(LayerSnapshotTest, frameRateWithCategory) { + SET_FLAG_FOR_TEST(flags::frame_rate_category_mrr, true); + // ROOT // ├── 1 // │ ├── 11 (frame rate set to 244.f) @@ -864,6 +870,8 @@ TEST_F(LayerSnapshotTest, frameRateSelectionStrategy) { } TEST_F(LayerSnapshotTest, frameRateSelectionStrategyWithCategory) { + SET_FLAG_FOR_TEST(flags::frame_rate_category_mrr, true); + // ROOT // ├── 1 // │ ├── 11 |