SurfaceFlinger: add support for FrameRateCompatibilityType
Bug: 147516364
Test: adb shell /data/nativetest64/SurfaceFlinger_test/SurfaceFlinger_test --gtest_filter='SetFrameRateTest.*'
Test: adb shell /data/nativetest64/libsurfaceflinger_unittest/libsurfaceflinger_unittest --gtest_filter=*RefreshRateConfigs*
Test: adb shell /data/nativetest64/libsurfaceflinger_unittest/libsurfaceflinger_unittest --gtest_filter=*LayerHistory*
Change-Id: I49272804e25f04e1d7a148a0008551cbc5428011
diff --git a/services/surfaceflinger/Scheduler/LayerHistory.cpp b/services/surfaceflinger/Scheduler/LayerHistory.cpp
index b976523..9aada11 100644
--- a/services/surfaceflinger/Scheduler/LayerHistory.cpp
+++ b/services/surfaceflinger/Scheduler/LayerHistory.cpp
@@ -39,7 +39,7 @@
namespace {
bool isLayerActive(const Layer& layer, const LayerInfo& info, nsecs_t threshold) {
- if (layer.getFrameRate().has_value()) {
+ if (layer.getFrameRate().rate > 0) {
return layer.isVisible();
}
return layer.isVisible() && info.getLastUpdatedTime() >= threshold;
@@ -126,18 +126,27 @@
// Only use the layer if the reference still exists.
if (layer || CC_UNLIKELY(mTraceEnabled)) {
// Check if frame rate was set on layer.
- auto frameRate = layer->getFrameRate();
- if (frameRate.has_value() && frameRate.value() > 0.f) {
- summary.push_back(
- {layer->getName(), LayerVoteType::Explicit, *frameRate, /* weight */ 1.0f});
+ const auto frameRate = layer->getFrameRate();
+ if (frameRate.rate > 0.f) {
+ const auto voteType = [&]() {
+ switch (frameRate.type) {
+ case Layer::FrameRateCompatibility::Default:
+ return LayerVoteType::ExplicitDefault;
+ case Layer::FrameRateCompatibility::ExactOrMultiple:
+ return LayerVoteType::ExplicitExactOrMultiple;
+ case Layer::FrameRateCompatibility::NoVote:
+ return LayerVoteType::NoVote;
+ }
+ }();
+ summary.push_back({layer->getName(), voteType, frameRate.rate, /* weight */ 1.0f});
} else if (recent) {
- frameRate = info->getRefreshRate(now);
- summary.push_back({layer->getName(), LayerVoteType::Heuristic, *frameRate,
+ summary.push_back({layer->getName(), LayerVoteType::Heuristic,
+ info->getRefreshRate(now),
/* weight */ 1.0f});
}
if (CC_UNLIKELY(mTraceEnabled)) {
- trace(weakLayer, round<int>(*frameRate));
+ trace(weakLayer, round<int>(frameRate.rate));
}
}
}
diff --git a/services/surfaceflinger/Scheduler/LayerHistoryV2.cpp b/services/surfaceflinger/Scheduler/LayerHistoryV2.cpp
index a6d2c74..ce085f4 100644
--- a/services/surfaceflinger/Scheduler/LayerHistoryV2.cpp
+++ b/services/surfaceflinger/Scheduler/LayerHistoryV2.cpp
@@ -40,7 +40,7 @@
namespace {
bool isLayerActive(const Layer& layer, const LayerInfoV2& info, nsecs_t threshold) {
- if (layer.getFrameRate().has_value()) {
+ if (layer.getFrameRate().rate > 0) {
return layer.isVisible();
}
return layer.isVisible() && info.getLastUpdatedTime() >= threshold;
@@ -63,13 +63,17 @@
const auto& name = layer->getName();
const auto noVoteTag = "LFPS NoVote " + name;
const auto heuristicVoteTag = "LFPS Heuristic " + name;
- const auto explicitVoteTag = "LFPS Explicit " + name;
+ const auto explicitDefaultVoteTag = "LFPS ExplicitDefault" + name;
+ const auto explicitExactOrMultipleVoteTag = "LFPS ExplicitExactOrMultiple" + name;
const auto minVoteTag = "LFPS Min " + name;
const auto maxVoteTag = "LFPS Max " + name;
ATRACE_INT(noVoteTag.c_str(), type == LayerHistory::LayerVoteType::NoVote ? 1 : 0);
ATRACE_INT(heuristicVoteTag.c_str(), type == LayerHistory::LayerVoteType::Heuristic ? fps : 0);
- ATRACE_INT(explicitVoteTag.c_str(), type == LayerHistory::LayerVoteType::Explicit ? fps : 0);
+ ATRACE_INT(explicitDefaultVoteTag.c_str(),
+ type == LayerHistory::LayerVoteType::ExplicitDefault ? fps : 0);
+ ATRACE_INT(explicitExactOrMultipleVoteTag.c_str(),
+ type == LayerHistory::LayerVoteType::ExplicitExactOrMultiple ? fps : 0);
ATRACE_INT(minVoteTag.c_str(), type == LayerHistory::LayerVoteType::Min ? 1 : 0);
ATRACE_INT(maxVoteTag.c_str(), type == LayerHistory::LayerVoteType::Max ? 1 : 0);
@@ -160,12 +164,18 @@
i++;
// Set layer vote if set
const auto frameRate = layer->getFrameRate();
- if (frameRate.has_value()) {
- if (*frameRate == Layer::FRAME_RATE_NO_VOTE) {
- info->setLayerVote(LayerVoteType::NoVote, 0.f);
- } else {
- info->setLayerVote(LayerVoteType::Explicit, *frameRate);
+ const auto voteType = [&]() {
+ switch (frameRate.type) {
+ case Layer::FrameRateCompatibility::Default:
+ return LayerVoteType::ExplicitDefault;
+ case Layer::FrameRateCompatibility::ExactOrMultiple:
+ return LayerVoteType::ExplicitExactOrMultiple;
+ case Layer::FrameRateCompatibility::NoVote:
+ return LayerVoteType::NoVote;
}
+ }();
+ if (frameRate.rate > 0 || voteType == LayerVoteType::NoVote) {
+ info->setLayerVote(voteType, frameRate.rate);
} else {
info->resetLayerVote();
}
diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
index d2af912..c73e825 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
+++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
@@ -37,7 +37,8 @@
int explicitContentFramerate = 0;
for (const auto& layer : layers) {
const auto desiredRefreshRateRound = round<int>(layer.desiredRefreshRate);
- if (layer.vote == LayerVoteType::Explicit) {
+ if (layer.vote == LayerVoteType::ExplicitDefault ||
+ layer.vote == LayerVoteType::ExplicitExactOrMultiple) {
if (desiredRefreshRateRound > explicitContentFramerate) {
explicitContentFramerate = desiredRefreshRateRound;
}
@@ -94,7 +95,8 @@
int noVoteLayers = 0;
int minVoteLayers = 0;
int maxVoteLayers = 0;
- int explicitVoteLayers = 0;
+ int explicitDefaultVoteLayers = 0;
+ int explicitExactOrMultipleVoteLayers = 0;
for (const auto& layer : layers) {
if (layer.vote == LayerVoteType::NoVote)
noVoteLayers++;
@@ -102,8 +104,10 @@
minVoteLayers++;
else if (layer.vote == LayerVoteType::Max)
maxVoteLayers++;
- else if (layer.vote == LayerVoteType::Explicit)
- explicitVoteLayers++;
+ else if (layer.vote == LayerVoteType::ExplicitDefault)
+ explicitDefaultVoteLayers++;
+ else if (layer.vote == LayerVoteType::ExplicitExactOrMultiple)
+ explicitExactOrMultipleVoteLayers++;
}
// Only if all layers want Min we should return Min
@@ -112,7 +116,7 @@
}
// If we have some Max layers and no Explicit we should return Max
- if (maxVoteLayers > 0 && explicitVoteLayers == 0) {
+ if (maxVoteLayers > 0 && explicitDefaultVoteLayers + explicitExactOrMultipleVoteLayers == 0) {
return *mAvailableRefreshRates.back();
}
@@ -131,9 +135,22 @@
continue;
}
- // If we have Explicit layers, ignore the Hueristic ones
- if (explicitVoteLayers > 0 && layer.vote == LayerVoteType::Heuristic) {
- continue;
+ // Adjust the weight in case we have explicit layers. The priority is:
+ // - ExplicitExactOrMultiple
+ // - ExplicitDefault
+ // - Heuristic
+ auto weight = layer.weight;
+ if (explicitExactOrMultipleVoteLayers + explicitDefaultVoteLayers > 0) {
+ if (layer.vote == LayerVoteType::Heuristic) {
+ weight /= 2.f;
+ }
+ }
+
+ if (explicitExactOrMultipleVoteLayers > 0) {
+ if (layer.vote == LayerVoteType::Heuristic ||
+ layer.vote == LayerVoteType::ExplicitDefault) {
+ weight /= 2.f;
+ }
}
for (auto& [refreshRate, overallScore] : scores) {
@@ -152,10 +169,10 @@
static constexpr size_t MAX_FRAMES_TO_FIT = 10; // Stop calculating when score < 0.1
if (displayFramesRem == 0) {
// Layer desired refresh rate matches the display rate.
- layerScore = layer.weight * 1.0f;
+ layerScore = weight * 1.0f;
} else if (displayFramesQuot == 0) {
// Layer desired refresh rate is higher the display rate.
- layerScore = layer.weight *
+ layerScore = weight *
(static_cast<float>(layerPeriod) / static_cast<float>(displayPeriod)) *
(1.0f / (MAX_FRAMES_TO_FIT + 1));
} else {
@@ -168,11 +185,11 @@
iter++;
}
- layerScore = layer.weight * (1.0f / iter);
+ layerScore = weight * (1.0f / iter);
}
- ALOGV("%s (weight %.2f) %.2fHz gives %s score of %.2f", layer.name.c_str(),
- layer.weight, 1e9f / layerPeriod, refreshRate->name.c_str(), layerScore);
+ ALOGV("%s (weight %.2f) %.2fHz gives %s score of %.2f", layer.name.c_str(), weight,
+ 1e9f / layerPeriod, refreshRate->name.c_str(), layerScore);
overallScore += layerScore;
}
}
diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
index c762efd..fc95959 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
+++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
@@ -96,11 +96,14 @@
// Describes the different options the layer voted for refresh rate
enum class LayerVoteType {
- NoVote, // Doesn't care about the refresh rate
- Min, // Minimal refresh rate available
- Max, // Maximal refresh rate available
- Heuristic, // Specific refresh rate that was calculated by platform using a heuristic
- Explicit, // Specific refresh rate that was provided by the app
+ NoVote, // Doesn't care about the refresh rate
+ Min, // Minimal refresh rate available
+ Max, // Maximal refresh rate available
+ Heuristic, // Specific refresh rate that was calculated by platform using a heuristic
+ ExplicitDefault, // Specific refresh rate that was provided by the app with Default
+ // compatibility
+ ExplicitExactOrMultiple // Specific refresh rate that was provided by the app with
+ // ExactOrMultiple compatibility
};
// Captures the layer requirements for a refresh rate. This will be used to determine the
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index 258ce0a..52fb6f3 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -408,7 +408,8 @@
"SurfaceView - "
"com.google.android.youtube/"
"com.google.android.apps.youtube.app.WatchWhileActivity#0") {
- layer->setFrameRate(vote);
+ layer->setFrameRate(
+ Layer::FrameRate(vote, Layer::FrameRateCompatibility::ExactOrMultiple));
}
}
}
@@ -562,7 +563,8 @@
bool Scheduler::layerHistoryHasClientSpecifiedFrameRate() {
for (const auto& layer : mFeatures.contentRequirements) {
- if (layer.vote == scheduler::RefreshRateConfigs::LayerVoteType::Explicit) {
+ if (layer.vote == scheduler::RefreshRateConfigs::LayerVoteType::ExplicitDefault ||
+ layer.vote == scheduler::RefreshRateConfigs::LayerVoteType::ExplicitExactOrMultiple) {
return true;
}
}