diff options
author | 2023-12-26 17:33:41 -0800 | |
---|---|---|
committer | 2024-01-02 17:09:53 -0800 | |
commit | 9580ff12b560e37b17be4fd9a3f1084415f8debc (patch) | |
tree | 162985cc91df9717488e163312ef9fd64d1c65f9 | |
parent | a5643cb05f6d4b5012d443dbdd3077b3fae2bf0c (diff) |
Support HIGH_INTERACTIVE category in native
This is mainly to be used by toolkit to send the touch interaction to
SF (in effort to handle touch signal in toolkit instead of SF).
The HighInteractive category is similar to Heuristic layer type
but will be considered in touch boost logic.
Bug: 315071842
Test: atest libsurfaceflinger_unittest
Test: atest CtsSurfaceControlTestsStaging
Change-Id: I97a94fa970e165424757e4537468fbeda4226a72
6 files changed, 109 insertions, 7 deletions
diff --git a/libs/nativewindow/include/system/window.h b/libs/nativewindow/include/system/window.h index a98ea86073..969a5cff05 100644 --- a/libs/nativewindow/include/system/window.h +++ b/libs/nativewindow/include/system/window.h @@ -1095,10 +1095,19 @@ enum { ANATIVEWINDOW_FRAME_RATE_CATEGORY_NORMAL = 3, /** + * Indicates that, as a result of a user interaction, an animation is likely to start. + * This category is a signal that a user interaction heuristic determined the need of a + * high refresh rate, and is not an explicit request from the app. + * As opposed to FRAME_RATE_CATEGORY_HIGH, this vote may be ignored in favor of + * more explicit votes. + */ + ANATIVEWINDOW_FRAME_RATE_CATEGORY_HIGH_HINT = 4, + + /** * Indicates a frame rate suitable for animations that require a high frame rate, which may * increase smoothness but may also increase power usage. */ - ANATIVEWINDOW_FRAME_RATE_CATEGORY_HIGH = 4 + ANATIVEWINDOW_FRAME_RATE_CATEGORY_HIGH = 5 }; /* diff --git a/services/surfaceflinger/Scheduler/LayerInfo.cpp b/services/surfaceflinger/Scheduler/LayerInfo.cpp index 97fca395b4..5094232a4e 100644 --- a/services/surfaceflinger/Scheduler/LayerInfo.cpp +++ b/services/surfaceflinger/Scheduler/LayerInfo.cpp @@ -528,6 +528,8 @@ FrameRateCategory LayerInfo::FrameRate::convertCategory(int8_t category) { return FrameRateCategory::Low; case ANATIVEWINDOW_FRAME_RATE_CATEGORY_NORMAL: return FrameRateCategory::Normal; + case ANATIVEWINDOW_FRAME_RATE_CATEGORY_HIGH_HINT: + return FrameRateCategory::HighHint; case ANATIVEWINDOW_FRAME_RATE_CATEGORY_HIGH: return FrameRateCategory::High; default: diff --git a/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp b/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp index e06221a43d..c3709e5cc2 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp +++ b/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp @@ -420,6 +420,11 @@ float RefreshRateSelector::calculateLayerScoreLocked(const LayerRequirement& lay const float seamlessness = isSeamlessSwitch ? 1.0f : kSeamedSwitchPenalty; if (layer.vote == LayerVoteType::ExplicitCategory) { + // HighHint is considered later for touch boost. + if (layer.frameRateCategory == FrameRateCategory::HighHint) { + return 0.f; + } + if (getFrameRateCategoryRange(layer.frameRateCategory).includes(refreshRate)) { return 1.f; } @@ -507,6 +512,7 @@ auto RefreshRateSelector::getRankedFrameRatesLocked(const std::vector<LayerRequi int explicitExact = 0; int explicitGteLayers = 0; int explicitCategoryVoteLayers = 0; + int interactiveLayers = 0; int seamedFocusedLayers = 0; int categorySmoothSwitchOnlyLayers = 0; @@ -534,7 +540,13 @@ auto RefreshRateSelector::getRankedFrameRatesLocked(const std::vector<LayerRequi explicitGteLayers++; break; case LayerVoteType::ExplicitCategory: - explicitCategoryVoteLayers++; + if (layer.frameRateCategory == FrameRateCategory::HighHint) { + // HighHint does not count as an explicit signal from an app. It may be + // be a touch signal. + interactiveLayers++; + } else { + explicitCategoryVoteLayers++; + } if (layer.frameRateCategory == FrameRateCategory::NoPreference) { // Count this layer for Min vote as well. The explicit vote avoids // touch boost and idle for choosing a category, while Min vote is for correct @@ -831,13 +843,14 @@ auto RefreshRateSelector::getRankedFrameRatesLocked(const std::vector<LayerRequi const auto touchRefreshRates = rankFrameRates(anchorGroup, RefreshRateOrder::Descending); using fps_approx_ops::operator<; - if (signals.touch && explicitDefaultVoteLayers == 0 && explicitCategoryVoteLayers == 0 && + const bool hasInteraction = signals.touch || interactiveLayers > 0; + if (hasInteraction && explicitDefaultVoteLayers == 0 && explicitCategoryVoteLayers == 0 && touchBoostForExplicitExact && scores.front().frameRateMode.fps < touchRefreshRates.front().frameRateMode.fps) { ALOGV("Touch Boost"); ATRACE_FORMAT_INSTANT("%s (Touch Boost [late])", to_string(touchRefreshRates.front().frameRateMode.fps).c_str()); - return {touchRefreshRates, GlobalSignals{.touch = true}}; + return {touchRefreshRates, GlobalSignals{.touch = signals.touch}}; } // If we never scored any layers, and we don't favor high refresh rates, prefer to stay with the @@ -1512,6 +1525,7 @@ FpsRange RefreshRateSelector::getFrameRateCategoryRange(FrameRateCategory catego return FpsRange{60_Hz, 90_Hz}; case FrameRateCategory::Low: return FpsRange{30_Hz, 30_Hz}; + case FrameRateCategory::HighHint: case FrameRateCategory::NoPreference: case FrameRateCategory::Default: LOG_ALWAYS_FATAL("Should not get fps range for frame rate category: %s", diff --git a/services/surfaceflinger/Scheduler/include/scheduler/Fps.h b/services/surfaceflinger/Scheduler/include/scheduler/Fps.h index 2806450c5f..84ef89fb4a 100644 --- a/services/surfaceflinger/Scheduler/include/scheduler/Fps.h +++ b/services/surfaceflinger/Scheduler/include/scheduler/Fps.h @@ -88,6 +88,7 @@ enum class FrameRateCategory : int32_t { NoPreference, Low, Normal, + HighHint, High, ftl_last = High diff --git a/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp b/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp index ba32c68b61..55b20b3b47 100644 --- a/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp +++ b/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp @@ -650,7 +650,7 @@ TEST_F(LayerSnapshotTest, frameRateWithCategory) { // │ └── 13 // └── 2 setFrameRate(11, 244.f, 0, 0); - setFrameRateCategory(122, 3 /* Normal */); + setFrameRateCategory(122, ANATIVEWINDOW_FRAME_RATE_CATEGORY_NORMAL); UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER); // verify parent 1 gets no vote @@ -845,7 +845,7 @@ TEST_F(LayerSnapshotTest, frameRateSelectionStrategyWithCategory) { // │ │ └── 1221 // │ └── 13 // └── 2 - setFrameRateCategory(12, 4 /* high */); + setFrameRateCategory(12, ANATIVEWINDOW_FRAME_RATE_CATEGORY_HIGH); setFrameRate(122, 123.f, 0, 0); setFrameRateSelectionStrategy(12, 1 /* OverrideChildren */); @@ -887,7 +887,7 @@ TEST_F(LayerSnapshotTest, frameRateSelectionStrategyWithCategory) { // │ │ └── 1221 // │ └── 13 // └── 2 - setFrameRateCategory(12, 0 /* default */); + setFrameRateCategory(12, ANATIVEWINDOW_FRAME_RATE_CATEGORY_DEFAULT); setFrameRateSelectionStrategy(12, 0 /* Default */); UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER); // verify parent 1 gets no vote diff --git a/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp index 0cacf810c0..1e526ba348 100644 --- a/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp +++ b/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp @@ -1607,6 +1607,82 @@ TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_withFrameRateCategory_60_12 } } +TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_withFrameRateCategory_HighHint) { + auto selector = createSelector(makeModes(kMode24, kMode30, kMode60, kMode120), kModeId60); + + std::vector<LayerRequirement> layers = {{.weight = 1.f}, {.weight = 1.f}}; + auto& lr1 = layers[0]; + auto& lr2 = layers[1]; + + lr1.vote = LayerVoteType::ExplicitCategory; + lr1.frameRateCategory = FrameRateCategory::HighHint; + lr1.name = "ExplicitCategory HighHint"; + lr2.vote = LayerVoteType::NoVote; + lr2.name = "NoVote"; + auto actualFrameRateMode = selector.getBestFrameRateMode(layers); + // Gets touch boost + EXPECT_EQ(120_Hz, actualFrameRateMode.fps); + EXPECT_EQ(kModeId120, actualFrameRateMode.modePtr->getId()); + + lr1.vote = LayerVoteType::ExplicitCategory; + lr1.frameRateCategory = FrameRateCategory::HighHint; + lr1.name = "ExplicitCategory HighHint"; + lr2.vote = LayerVoteType::ExplicitDefault; + lr2.desiredRefreshRate = 30_Hz; + lr2.name = "30Hz ExplicitDefault"; + actualFrameRateMode = selector.getBestFrameRateMode(layers); + EXPECT_EQ(30_Hz, actualFrameRateMode.fps); + EXPECT_EQ(kModeId30, actualFrameRateMode.modePtr->getId()); + + lr1.vote = LayerVoteType::ExplicitCategory; + lr1.frameRateCategory = FrameRateCategory::HighHint; + lr1.name = "ExplicitCategory HighHint"; + lr2.vote = LayerVoteType::ExplicitCategory; + lr2.frameRateCategory = FrameRateCategory::HighHint; + lr2.name = "ExplicitCategory HighHint#2"; + actualFrameRateMode = selector.getBestFrameRateMode(layers); + // Gets touch boost + EXPECT_EQ(120_Hz, actualFrameRateMode.fps); + EXPECT_EQ(kModeId120, actualFrameRateMode.modePtr->getId()); + + lr1.vote = LayerVoteType::ExplicitCategory; + lr1.frameRateCategory = FrameRateCategory::HighHint; + lr1.name = "ExplicitCategory HighHint"; + lr2.vote = LayerVoteType::ExplicitCategory; + lr2.frameRateCategory = FrameRateCategory::Low; + lr2.name = "ExplicitCategory Low"; + actualFrameRateMode = selector.getBestFrameRateMode(layers); + EXPECT_EQ(30_Hz, actualFrameRateMode.fps); + EXPECT_EQ(kModeId30, actualFrameRateMode.modePtr->getId()); + + lr1.vote = LayerVoteType::ExplicitCategory; + lr1.frameRateCategory = FrameRateCategory::HighHint; + lr1.name = "ExplicitCategory HighHint"; + lr2.vote = LayerVoteType::ExplicitExactOrMultiple; + lr2.desiredRefreshRate = 30_Hz; + lr2.name = "30Hz ExplicitExactOrMultiple"; + actualFrameRateMode = selector.getBestFrameRateMode(layers); + // Gets touch boost + EXPECT_EQ(120_Hz, actualFrameRateMode.fps); + EXPECT_EQ(kModeId120, actualFrameRateMode.modePtr->getId()); + + lr1.vote = LayerVoteType::ExplicitCategory; + lr1.frameRateCategory = FrameRateCategory::HighHint; + lr1.name = "ExplicitCategory HighHint"; + lr2.vote = LayerVoteType::ExplicitExact; + lr2.desiredRefreshRate = 30_Hz; + lr2.name = "30Hz ExplicitExact"; + actualFrameRateMode = selector.getBestFrameRateMode(layers); + if (selector.supportsAppFrameRateOverrideByContent()) { + // Gets touch boost + EXPECT_EQ(120_Hz, actualFrameRateMode.fps); + EXPECT_EQ(kModeId120, actualFrameRateMode.modePtr->getId()); + } else { + EXPECT_EQ(30_Hz, actualFrameRateMode.fps); + EXPECT_EQ(kModeId30, actualFrameRateMode.modePtr->getId()); + } +} + TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_withFrameRateCategory_smoothSwitchOnly_60_120_nonVrr) { if (GetParam() != Config::FrameRateOverride::Enabled) { |