summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Rachel Lee <rnlee@google.com> 2023-12-26 17:33:41 -0800
committer Rachel Lee <rnlee@google.com> 2024-01-02 17:09:53 -0800
commit9580ff12b560e37b17be4fd9a3f1084415f8debc (patch)
tree162985cc91df9717488e163312ef9fd64d1c65f9
parenta5643cb05f6d4b5012d443dbdd3077b3fae2bf0c (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
-rw-r--r--libs/nativewindow/include/system/window.h11
-rw-r--r--services/surfaceflinger/Scheduler/LayerInfo.cpp2
-rw-r--r--services/surfaceflinger/Scheduler/RefreshRateSelector.cpp20
-rw-r--r--services/surfaceflinger/Scheduler/include/scheduler/Fps.h1
-rw-r--r--services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp6
-rw-r--r--services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp76
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) {