Merge changes Id05d2eac,I3d8bcbf8 into sc-dev
* changes:
SF: Add DisplayDevice::initiateModeChange
SF: Store display modes in DisplayDevice
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index 63be3ed..e5e10a0 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -16,6 +16,7 @@
#define LOG_TAG "LayerState"
+#include <apex/window.h>
#include <inttypes.h>
#include <binder/Parcel.h>
@@ -620,7 +621,8 @@
return NO_ERROR;
}
-bool ValidateFrameRate(float frameRate, int8_t compatibility, const char* inFunctionName) {
+bool ValidateFrameRate(float frameRate, int8_t compatibility, const char* inFunctionName,
+ bool privileged) {
const char* functionName = inFunctionName != nullptr ? inFunctionName : "call";
int floatClassification = std::fpclassify(frameRate);
if (frameRate < 0 || floatClassification == FP_INFINITE || floatClassification == FP_NAN) {
@@ -629,8 +631,10 @@
}
if (compatibility != ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT &&
- compatibility != ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_FIXED_SOURCE) {
- ALOGE("%s failed - invalid compatibility value %d", functionName, compatibility);
+ compatibility != ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_FIXED_SOURCE &&
+ (!privileged || compatibility != ANATIVEWINDOW_FRAME_RATE_EXACT)) {
+ ALOGE("%s failed - invalid compatibility value %d privileged: %s", functionName,
+ compatibility, privileged ? "yes" : "no");
return false;
}
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 4a372bb..78f655a 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -1518,7 +1518,10 @@
mStatus = BAD_INDEX;
return *this;
}
- if (!ValidateFrameRate(frameRate, compatibility, "Transaction::setFrameRate")) {
+ // Allow privileged values as well here, those will be ignored by SF if
+ // the caller is not privileged
+ if (!ValidateFrameRate(frameRate, compatibility, "Transaction::setFrameRate",
+ /*privileged=*/true)) {
mStatus = BAD_VALUE;
return *this;
}
diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h
index 4a291ae..83a9d33 100644
--- a/libs/gui/include/gui/LayerState.h
+++ b/libs/gui/include/gui/LayerState.h
@@ -309,11 +309,14 @@
return compare_type(lhs.token, rhs.token);
}
-// Returns true if the frameRate and compatibility are valid values, false
-// othwerise. If either of the params are invalid, an error log is printed, and
-// functionName is added to the log to indicate which function call failed.
-// functionName can be null.
-bool ValidateFrameRate(float frameRate, int8_t compatibility, const char* functionName);
+// Returns true if the frameRate is valid.
+//
+// @param frameRate the frame rate in Hz
+// @param compatibility a ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_*
+// @param functionName calling function or nullptr. Used for logging
+// @param privileged whether caller has unscoped surfaceflinger access
+bool ValidateFrameRate(float frameRate, int8_t compatibility, const char* functionName,
+ bool privileged = false);
struct CaptureArgs {
const static int32_t UNSET_UID = -1;
diff --git a/libs/nativewindow/include/apex/window.h b/libs/nativewindow/include/apex/window.h
index 2d1354c..0923438 100644
--- a/libs/nativewindow/include/apex/window.h
+++ b/libs/nativewindow/include/apex/window.h
@@ -39,6 +39,19 @@
// clang-format on
};
+/*
+ * Internal extension of compatibility value for ANativeWindow_setFrameRate. */
+enum ANativeWindow_FrameRateCompatibilityInternal {
+ /**
+ * This surface belongs to an app on the High Refresh Rate Deny list, and needs the display
+ * to operate at the exact frame rate.
+ *
+ * This is used internally by the platform and should not be used by apps.
+ * @hide
+ */
+ ANATIVEWINDOW_FRAME_RATE_EXACT = 100,
+};
+
/**
* Prototype of the function that an ANativeWindow implementation would call
* when ANativeWindow_cancelBuffer is called.
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index a545d18..66ce3f1 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -1432,21 +1432,28 @@
};
// update parents and children about the vote
- // First traverse the tree and count how many layers has votes
+ // First traverse the tree and count how many layers has votes. In addition
+ // activate the layers in Scheduler's LayerHistory for it to check for changes
int layersWithVote = 0;
- traverseTree([&layersWithVote](Layer* layer) {
+ traverseTree([&layersWithVote, this](Layer* layer) {
const auto layerVotedWithDefaultCompatibility =
layer->mCurrentState.frameRate.rate.isValid() &&
layer->mCurrentState.frameRate.type == FrameRateCompatibility::Default;
const auto layerVotedWithNoVote =
layer->mCurrentState.frameRate.type == FrameRateCompatibility::NoVote;
+ const auto layerVotedWithExactCompatibility =
+ layer->mCurrentState.frameRate.type == FrameRateCompatibility::Exact;
// We do not count layers that are ExactOrMultiple for the same reason
// we are allowing touch boost for those layers. See
// RefreshRateConfigs::getBestRefreshRate for more details.
- if (layerVotedWithDefaultCompatibility || layerVotedWithNoVote) {
+ if (layerVotedWithDefaultCompatibility || layerVotedWithNoVote ||
+ layerVotedWithExactCompatibility) {
layersWithVote++;
}
+
+ mFlinger->mScheduler->recordLayerHistory(layer, systemTime(),
+ LayerHistory::LayerUpdateType::SetFrameRate);
});
// Now update the other layers
@@ -1474,10 +1481,6 @@
return false;
}
- // Activate the layer in Scheduler's LayerHistory
- mFlinger->mScheduler->recordLayerHistory(this, systemTime(),
- LayerHistory::LayerUpdateType::SetFrameRate);
-
mCurrentState.sequence++;
mCurrentState.frameRate = frameRate;
mCurrentState.modified = true;
@@ -1501,8 +1504,16 @@
return frameRate;
}
- // This layer doesn't have a frame rate. If one of its ancestors or successors
- // have a vote, return a NoVote for ancestors/successors to set the vote
+ // This layer doesn't have a frame rate. Check if its ancestors have a vote
+ if (sp<Layer> parent = getParent(); parent) {
+ if (const auto parentFrameRate = parent->getFrameRateForLayerTree();
+ parentFrameRate.rate.isValid()) {
+ return parentFrameRate;
+ }
+ }
+
+ // This layer and its ancestors don't have a frame rate. If one of successors
+ // has a vote, return a NoVote for successors to set the vote
if (getDrawingState().treeHasFrameRateVote) {
return {Fps(0.0f), FrameRateCompatibility::NoVote};
}
@@ -1654,6 +1665,8 @@
return "ExactOrMultiple";
case FrameRateCompatibility::NoVote:
return "NoVote";
+ case FrameRateCompatibility::Exact:
+ return "Exact";
}
}
@@ -1692,11 +1705,11 @@
const FloatRect& crop = outputLayerState.sourceCrop;
StringAppendF(&result, "%6.1f %6.1f %6.1f %6.1f | ", crop.left, crop.top, crop.right,
crop.bottom);
- if (layerState.frameRate.rate.isValid() ||
- layerState.frameRate.type != FrameRateCompatibility::Default) {
- StringAppendF(&result, "%s %15s %17s", to_string(layerState.frameRate.rate).c_str(),
- frameRateCompatibilityString(layerState.frameRate.type).c_str(),
- toString(layerState.frameRate.seamlessness).c_str());
+ const auto frameRate = getFrameRateForLayerTree();
+ if (frameRate.rate.isValid() || frameRate.type != FrameRateCompatibility::Default) {
+ StringAppendF(&result, "%s %15s %17s", to_string(frameRate.rate).c_str(),
+ frameRateCompatibilityString(frameRate.type).c_str(),
+ toString(frameRate.seamlessness).c_str());
} else {
result.append(41, ' ');
}
@@ -2755,6 +2768,8 @@
return FrameRateCompatibility::Default;
case ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_FIXED_SOURCE:
return FrameRateCompatibility::ExactOrMultiple;
+ case ANATIVEWINDOW_FRAME_RATE_EXACT:
+ return FrameRateCompatibility::Exact;
default:
LOG_ALWAYS_FATAL("Invalid frame rate compatibility value %d", compatibility);
return FrameRateCompatibility::Default;
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index f78b5f3..359340e 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -145,6 +145,8 @@
enum class FrameRateCompatibility {
Default, // Layer didn't specify any specific handling strategy
+ Exact, // Layer needs the exact frame rate.
+
ExactOrMultiple, // Layer needs the exact frame rate (or a multiple of it) to present the
// content properly. Any other value will result in a pull down.
diff --git a/services/surfaceflinger/Scheduler/LayerHistory.cpp b/services/surfaceflinger/Scheduler/LayerHistory.cpp
index 170933d..7ef531d 100644
--- a/services/surfaceflinger/Scheduler/LayerHistory.cpp
+++ b/services/surfaceflinger/Scheduler/LayerHistory.cpp
@@ -71,6 +71,7 @@
traceType(LayerHistory::LayerVoteType::Heuristic, fps);
traceType(LayerHistory::LayerVoteType::ExplicitDefault, fps);
traceType(LayerHistory::LayerVoteType::ExplicitExactOrMultiple, fps);
+ traceType(LayerHistory::LayerVoteType::ExplicitExact, fps);
traceType(LayerHistory::LayerVoteType::Min, 1);
traceType(LayerHistory::LayerVoteType::Max, 1);
@@ -172,6 +173,8 @@
return LayerVoteType::ExplicitExactOrMultiple;
case Layer::FrameRateCompatibility::NoVote:
return LayerVoteType::NoVote;
+ case Layer::FrameRateCompatibility::Exact:
+ return LayerVoteType::ExplicitExact;
}
}();
diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
index 0f1e267..81ffe0f 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
+++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
@@ -83,6 +83,8 @@
return "ExplicitDefault";
case LayerVoteType::ExplicitExactOrMultiple:
return "ExplicitExactOrMultiple";
+ case LayerVoteType::ExplicitExact:
+ return "ExplicitExact";
}
}
@@ -165,6 +167,18 @@
return (1.0f / iter) * seamlessness;
}
+ if (layer.vote == LayerVoteType::ExplicitExact) {
+ const int divider = getFrameRateDivider(refreshRate.getFps(), layer.desiredRefreshRate);
+ if (mSupportsFrameRateOverride) {
+ // Since we support frame rate override, allow refresh rates which are
+ // multiples of the layer's request, as those apps would be throttled
+ // down to run at the desired refresh rate.
+ return divider > 0;
+ }
+
+ return divider == 1;
+ }
+
return 0;
}
@@ -199,21 +213,34 @@
int maxVoteLayers = 0;
int explicitDefaultVoteLayers = 0;
int explicitExactOrMultipleVoteLayers = 0;
+ int explicitExact = 0;
float maxExplicitWeight = 0;
int seamedLayers = 0;
for (const auto& layer : layers) {
- if (layer.vote == LayerVoteType::NoVote) {
- noVoteLayers++;
- } else if (layer.vote == LayerVoteType::Min) {
- minVoteLayers++;
- } else if (layer.vote == LayerVoteType::Max) {
- maxVoteLayers++;
- } else if (layer.vote == LayerVoteType::ExplicitDefault) {
- explicitDefaultVoteLayers++;
- maxExplicitWeight = std::max(maxExplicitWeight, layer.weight);
- } else if (layer.vote == LayerVoteType::ExplicitExactOrMultiple) {
- explicitExactOrMultipleVoteLayers++;
- maxExplicitWeight = std::max(maxExplicitWeight, layer.weight);
+ switch (layer.vote) {
+ case LayerVoteType::NoVote:
+ noVoteLayers++;
+ break;
+ case LayerVoteType::Min:
+ minVoteLayers++;
+ break;
+ case LayerVoteType::Max:
+ maxVoteLayers++;
+ break;
+ case LayerVoteType::ExplicitDefault:
+ explicitDefaultVoteLayers++;
+ maxExplicitWeight = std::max(maxExplicitWeight, layer.weight);
+ break;
+ case LayerVoteType::ExplicitExactOrMultiple:
+ explicitExactOrMultipleVoteLayers++;
+ maxExplicitWeight = std::max(maxExplicitWeight, layer.weight);
+ break;
+ case LayerVoteType::ExplicitExact:
+ explicitExact++;
+ maxExplicitWeight = std::max(maxExplicitWeight, layer.weight);
+ break;
+ case LayerVoteType::Heuristic:
+ break;
}
if (layer.seamlessness == Seamlessness::SeamedAndSeamless) {
@@ -221,8 +248,8 @@
}
}
- const bool hasExplicitVoteLayers =
- explicitDefaultVoteLayers > 0 || explicitExactOrMultipleVoteLayers > 0;
+ const bool hasExplicitVoteLayers = explicitDefaultVoteLayers > 0 ||
+ explicitExactOrMultipleVoteLayers > 0 || explicitExact > 0;
// Consider the touch event if there are no Explicit* layers. Otherwise wait until after we've
// selected a refresh rate to see if we should apply touch boost.
@@ -318,7 +345,9 @@
bool inPrimaryRange = scores[i].refreshRate->inPolicy(policy->primaryRange.min,
policy->primaryRange.max);
if ((primaryRangeIsSingleRate || !inPrimaryRange) &&
- !(layer.focused && layer.vote == LayerVoteType::ExplicitDefault)) {
+ !(layer.focused &&
+ (layer.vote == LayerVoteType::ExplicitDefault ||
+ layer.vote == LayerVoteType::ExplicitExact))) {
// Only focused layers with ExplicitDefault frame rate settings are allowed to score
// refresh rates outside the primary range.
continue;
@@ -358,7 +387,8 @@
// actually increase the refresh rate over the normal selection.
const RefreshRate& touchRefreshRate = getMaxRefreshRateByPolicyLocked();
- if (globalSignals.touch && explicitDefaultVoteLayers == 0 &&
+ bool touchBoostForExplicitExact = explicitExact == 0 || mSupportsFrameRateOverride;
+ if (globalSignals.touch && explicitDefaultVoteLayers == 0 && touchBoostForExplicitExact &&
bestRefreshRate->fps.lessThanWithMargin(touchRefreshRate.fps)) {
setTouchConsidered();
ALOGV("TouchBoost - choose %s", touchRefreshRate.getName().c_str());
@@ -412,7 +442,7 @@
}
RefreshRateConfigs::UidToFrameRateOverride RefreshRateConfigs::getFrameRateOverrides(
- const std::vector<LayerRequirement>& layers, Fps displayFrameRate) const {
+ const std::vector<LayerRequirement>& layers, Fps displayFrameRate, bool touch) const {
ATRACE_CALL();
if (!mSupportsFrameRateOverride) return {};
@@ -423,6 +453,17 @@
groupLayersByUid(layers);
UidToFrameRateOverride frameRateOverrides;
for (const auto& [uid, layersWithSameUid] : layersByUid) {
+ // Layers with ExplicitExactOrMultiple expect touch boost
+ const bool hasExplicitExactOrMultiple =
+ std::any_of(layersWithSameUid.cbegin(), layersWithSameUid.cend(),
+ [](const auto& layer) {
+ return layer->vote == LayerVoteType::ExplicitExactOrMultiple;
+ });
+
+ if (touch && hasExplicitExactOrMultiple) {
+ continue;
+ }
+
for (auto& score : scores) {
score.score = 0;
}
@@ -433,7 +474,8 @@
}
LOG_ALWAYS_FATAL_IF(layer->vote != LayerVoteType::ExplicitDefault &&
- layer->vote != LayerVoteType::ExplicitExactOrMultiple);
+ layer->vote != LayerVoteType::ExplicitExactOrMultiple &&
+ layer->vote != LayerVoteType::ExplicitExact);
for (RefreshRateScore& score : scores) {
const auto layerScore = calculateLayerScoreLocked(*layer, *score.refreshRate,
/*isSeamlessSwitch*/ true);
@@ -559,8 +601,10 @@
mCurrentRefreshRate = mRefreshRates.at(configId).get();
}
-RefreshRateConfigs::RefreshRateConfigs(const DisplayModes& configs, DisplayModeId currentConfigId)
- : mKnownFrameRates(constructKnownFrameRates(configs)) {
+RefreshRateConfigs::RefreshRateConfigs(const DisplayModes& configs, DisplayModeId currentConfigId,
+ bool enableFrameRateOverride)
+ : mKnownFrameRates(constructKnownFrameRates(configs)),
+ mEnableFrameRateOverride(enableFrameRateOverride) {
updateDisplayConfigs(configs, currentConfigId);
}
@@ -589,7 +633,7 @@
mMaxSupportedRefreshRate = sortedConfigs.back();
mSupportsFrameRateOverride = false;
- if (android::sysprop::enable_frame_rate_override(true)) {
+ if (mEnableFrameRateOverride) {
for (const auto& config1 : sortedConfigs) {
for (const auto& config2 : sortedConfigs) {
if (getFrameRateDivider(config1->getFps(), config2->getFps()) >= 2) {
@@ -826,4 +870,4 @@
} // namespace android::scheduler
// TODO(b/129481165): remove the #pragma below and fix conversion issues
-#pragma clang diagnostic pop // ignored "-Wextra"
\ No newline at end of file
+#pragma clang diagnostic pop // ignored "-Wextra"
diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
index 29402f5..0c7dc05 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
+++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
@@ -211,8 +211,11 @@
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
+ ExplicitExactOrMultiple, // Specific refresh rate that was provided by the app with
+ // ExactOrMultiple compatibility
+ ExplicitExact, // Specific refresh rate that was provided by the app with
+ // Exact compatibility
+
};
// Captures the layer requirements for a refresh rate. This will be used to determine the
@@ -298,7 +301,8 @@
// Returns a known frame rate that is the closest to frameRate
Fps findClosestKnownFrameRate(Fps frameRate) const;
- RefreshRateConfigs(const DisplayModes& configs, DisplayModeId currentConfigId);
+ RefreshRateConfigs(const DisplayModes& configs, DisplayModeId currentConfigId,
+ bool enableFrameRateOverride = false);
void updateDisplayConfigs(const DisplayModes& configs, DisplayModeId currentConfig)
EXCLUDES(mLock);
@@ -327,10 +331,15 @@
// Returns a divider for the current refresh rate
int getRefreshRateDivider(Fps frameRate) const EXCLUDES(mLock);
- // Returns the frame rate override for each uid
using UidToFrameRateOverride = std::map<uid_t, Fps>;
+ // Returns the frame rate override for each uid.
+ //
+ // @param layers list of visible layers
+ // @param displayFrameRate the display frame rate
+ // @param touch whether touch timer is active (i.e. user touched the screen recently)
UidToFrameRateOverride getFrameRateOverrides(const std::vector<LayerRequirement>& layers,
- Fps displayFrameRate) const EXCLUDES(mLock);
+ Fps displayFrameRate, bool touch) const
+ EXCLUDES(mLock);
void dump(std::string& result) const EXCLUDES(mLock);
@@ -410,6 +419,7 @@
// from based on the closest value.
const std::vector<Fps> mKnownFrameRates;
+ const bool mEnableFrameRateOverride;
bool mSupportsFrameRateOverride;
};
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index 588b83d..d861209 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -763,17 +763,11 @@
return false;
}
- if (consideredSignals.touch) {
- std::lock_guard lock(mFrameRateOverridesMutex);
- const bool changed = !mFrameRateOverridesByContent.empty();
- mFrameRateOverridesByContent.clear();
- return changed;
- }
-
if (!consideredSignals.idle) {
const auto frameRateOverrides =
mRefreshRateConfigs.getFrameRateOverrides(mFeatures.contentRequirements,
- displayRefreshRate);
+ displayRefreshRate,
+ consideredSignals.touch);
std::lock_guard lock(mFrameRateOverridesMutex);
if (!std::equal(mFrameRateOverridesByContent.begin(), mFrameRateOverridesByContent.end(),
frameRateOverrides.begin(), frameRateOverrides.end(),
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 3a9f7de..a764cbb 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -2942,7 +2942,9 @@
auto currentConfig = getHwComposer().getActiveMode(primaryDisplayId)->getId();
const auto modes = getHwComposer().getModes(primaryDisplayId);
- mRefreshRateConfigs = std::make_unique<scheduler::RefreshRateConfigs>(modes, currentConfig);
+ mRefreshRateConfigs = std::make_unique<
+ scheduler::RefreshRateConfigs>(modes, currentConfig,
+ android::sysprop::enable_frame_rate_override(true));
const auto& currRefreshRate = mRefreshRateConfigs->getRefreshRateFromConfigId(currentConfig);
mRefreshRateStats =
std::make_unique<scheduler::RefreshRateStats>(*mTimeStats, currRefreshRate.getFps(),
@@ -3895,7 +3897,7 @@
}
if (what & layer_state_t::eFrameRateChanged) {
if (ValidateFrameRate(s.frameRate, s.frameRateCompatibility,
- "SurfaceFlinger::setClientStateLocked") &&
+ "SurfaceFlinger::setClientStateLocked", privileged) &&
layer->setFrameRate(Layer::FrameRate(Fps(s.frameRate),
Layer::FrameRate::convertCompatibility(
s.frameRateCompatibility),
diff --git a/services/surfaceflinger/TimeStats/TimeStats.h b/services/surfaceflinger/TimeStats/TimeStats.h
index 8fac8e9..df40ef6 100644
--- a/services/surfaceflinger/TimeStats/TimeStats.h
+++ b/services/surfaceflinger/TimeStats/TimeStats.h
@@ -315,8 +315,9 @@
static const size_t MAX_NUM_LAYER_RECORDS = 200;
static const size_t MAX_NUM_LAYER_STATS = 200;
+ static const size_t MAX_NUM_PULLED_LAYERS = MAX_NUM_LAYER_STATS;
std::unique_ptr<StatsEventDelegate> mStatsDelegate = std::make_unique<StatsEventDelegate>();
- size_t mMaxPulledLayers = 8;
+ size_t mMaxPulledLayers = MAX_NUM_PULLED_LAYERS;
size_t mMaxPulledHistogramBuckets = 6;
};
diff --git a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
index 0a747ab..738ded1 100644
--- a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
+++ b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
@@ -1506,6 +1506,89 @@
}
}
+TEST_F(RefreshRateConfigsTest, getBestRefreshRate_ExplicitExact) {
+ auto refreshRateConfigs =
+ std::make_unique<RefreshRateConfigs>(m30_60_72_90_120Device,
+ /*currentConfigId=*/HWC_CONFIG_ID_60);
+
+ auto layers = std::vector<LayerRequirement>{LayerRequirement{.weight = 1.0f},
+ LayerRequirement{.weight = 0.5f}};
+ auto& explicitExactLayer = layers[0];
+ auto& explicitExactOrMultipleLayer = layers[1];
+
+ explicitExactOrMultipleLayer.vote = LayerVoteType::ExplicitExactOrMultiple;
+ explicitExactOrMultipleLayer.name = "ExplicitExactOrMultiple";
+ explicitExactOrMultipleLayer.desiredRefreshRate = Fps(60);
+
+ explicitExactLayer.vote = LayerVoteType::ExplicitExact;
+ explicitExactLayer.name = "ExplicitExact";
+ explicitExactLayer.desiredRefreshRate = Fps(30);
+
+ EXPECT_EQ(mExpected30Config,
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
+ EXPECT_EQ(mExpected30Config,
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = true, .idle = false}));
+
+ explicitExactOrMultipleLayer.desiredRefreshRate = Fps(120);
+ explicitExactLayer.desiredRefreshRate = Fps(60);
+ EXPECT_EQ(mExpected60Config,
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
+
+ explicitExactLayer.desiredRefreshRate = Fps(72);
+ EXPECT_EQ(mExpected72Config,
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
+
+ explicitExactLayer.desiredRefreshRate = Fps(90);
+ EXPECT_EQ(mExpected90Config,
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
+
+ explicitExactLayer.desiredRefreshRate = Fps(120);
+ EXPECT_EQ(mExpected120Config,
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
+}
+
+TEST_F(RefreshRateConfigsTest, getBestRefreshRate_ExplicitExactEnableFrameRateOverride) {
+ auto refreshRateConfigs =
+ std::make_unique<RefreshRateConfigs>(m30_60_72_90_120Device,
+ /*currentConfigId=*/HWC_CONFIG_ID_60,
+ /*enableFrameRateOverride=*/true);
+
+ auto layers = std::vector<LayerRequirement>{LayerRequirement{.weight = 1.0f},
+ LayerRequirement{.weight = 0.5f}};
+ auto& explicitExactLayer = layers[0];
+ auto& explicitExactOrMultipleLayer = layers[1];
+
+ explicitExactOrMultipleLayer.vote = LayerVoteType::ExplicitExactOrMultiple;
+ explicitExactOrMultipleLayer.name = "ExplicitExactOrMultiple";
+ explicitExactOrMultipleLayer.desiredRefreshRate = Fps(60);
+
+ explicitExactLayer.vote = LayerVoteType::ExplicitExact;
+ explicitExactLayer.name = "ExplicitExact";
+ explicitExactLayer.desiredRefreshRate = Fps(30);
+
+ EXPECT_EQ(mExpected60Config,
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
+ EXPECT_EQ(mExpected120Config,
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = true, .idle = false}));
+
+ explicitExactOrMultipleLayer.desiredRefreshRate = Fps(120);
+ explicitExactLayer.desiredRefreshRate = Fps(60);
+ EXPECT_EQ(mExpected120Config,
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
+
+ explicitExactLayer.desiredRefreshRate = Fps(72);
+ EXPECT_EQ(mExpected72Config,
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
+
+ explicitExactLayer.desiredRefreshRate = Fps(90);
+ EXPECT_EQ(mExpected90Config,
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
+
+ explicitExactLayer.desiredRefreshRate = Fps(120);
+ EXPECT_EQ(mExpected120Config,
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
+}
+
TEST_F(RefreshRateConfigsTest, testComparisonOperator) {
EXPECT_TRUE(mExpected60Config < mExpected90Config);
EXPECT_FALSE(mExpected60Config < mExpected60Config);
@@ -1537,7 +1620,7 @@
EXPECT_EQ(KernelIdleTimerAction::TurnOff, refreshRateConfigs->getIdleTimerAction());
}
-TEST_F(RefreshRateConfigsTest, RefreshRateDividerForUid) {
+TEST_F(RefreshRateConfigsTest, getRefreshRateDivider) {
auto refreshRateConfigs =
std::make_unique<RefreshRateConfigs>(m30_60_72_90_120Device,
/*currentConfigId=*/HWC_CONFIG_ID_30);
@@ -1562,57 +1645,66 @@
EXPECT_EQ(4, refreshRateConfigs->getRefreshRateDivider(Fps(22.6f)));
}
-TEST_F(RefreshRateConfigsTest, populatePreferredFrameRate_noLayers) {
+TEST_F(RefreshRateConfigsTest, getFrameRateOverrides_noLayers) {
auto refreshRateConfigs =
std::make_unique<RefreshRateConfigs>(m30_60_72_90_120Device, /*currentConfigId=*/
HWC_CONFIG_ID_120);
auto layers = std::vector<LayerRequirement>{};
- ASSERT_TRUE(refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f)).empty());
+ ASSERT_TRUE(refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f), /*touch=*/false)
+ .empty());
}
TEST_F(RefreshRateConfigsTest, getFrameRateOverrides_60on120) {
auto refreshRateConfigs =
std::make_unique<RefreshRateConfigs>(m30_60_72_90_120Device, /*currentConfigId=*/
- HWC_CONFIG_ID_120);
+ HWC_CONFIG_ID_120,
+ /*enableFrameRateOverride=*/true);
auto layers = std::vector<LayerRequirement>{LayerRequirement{.weight = 1.0f}};
layers[0].name = "Test layer";
layers[0].ownerUid = 1234;
layers[0].desiredRefreshRate = Fps(60.0f);
layers[0].vote = LayerVoteType::ExplicitDefault;
- auto frameRateOverrides = refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f));
+ auto frameRateOverrides =
+ refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f), /*touch=*/false);
ASSERT_EQ(1, frameRateOverrides.size());
ASSERT_EQ(1, frameRateOverrides.count(1234));
ASSERT_EQ(60.0f, frameRateOverrides.at(1234).getValue());
layers[0].vote = LayerVoteType::ExplicitExactOrMultiple;
- frameRateOverrides = refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f));
+ frameRateOverrides =
+ refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f), /*touch=*/false);
ASSERT_EQ(1, frameRateOverrides.size());
ASSERT_EQ(1, frameRateOverrides.count(1234));
ASSERT_EQ(60.0f, frameRateOverrides.at(1234).getValue());
layers[0].vote = LayerVoteType::NoVote;
- frameRateOverrides = refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f));
+ frameRateOverrides =
+ refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f), /*touch=*/false);
ASSERT_TRUE(frameRateOverrides.empty());
layers[0].vote = LayerVoteType::Min;
- frameRateOverrides = refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f));
+ frameRateOverrides =
+ refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f), /*touch=*/false);
ASSERT_TRUE(frameRateOverrides.empty());
layers[0].vote = LayerVoteType::Max;
- frameRateOverrides = refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f));
+ frameRateOverrides =
+ refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f), /*touch=*/false);
ASSERT_TRUE(frameRateOverrides.empty());
layers[0].vote = LayerVoteType::Heuristic;
- frameRateOverrides = refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f));
+ frameRateOverrides =
+ refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f), /*touch=*/false);
ASSERT_TRUE(frameRateOverrides.empty());
}
-TEST_F(RefreshRateConfigsTest, populatePreferredFrameRate_twoUids) {
+TEST_F(RefreshRateConfigsTest, getFrameRateOverrides_twoUids) {
auto refreshRateConfigs =
std::make_unique<RefreshRateConfigs>(m30_60_72_90_120Device, /*currentConfigId=*/
- HWC_CONFIG_ID_120);
+ HWC_CONFIG_ID_120,
+ /*enableFrameRateOverride=*/true);
auto layers = std::vector<LayerRequirement>{
LayerRequirement{.ownerUid = 1234, .weight = 1.0f},
@@ -1626,7 +1718,8 @@
layers[1].name = "Test layer 5678";
layers[1].desiredRefreshRate = Fps(30.0f);
layers[1].vote = LayerVoteType::ExplicitDefault;
- auto frameRateOverrides = refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f));
+ auto frameRateOverrides =
+ refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f), /*touch=*/false);
ASSERT_EQ(2, frameRateOverrides.size());
ASSERT_EQ(1, frameRateOverrides.count(1234));
@@ -1635,13 +1728,66 @@
ASSERT_EQ(30.0f, frameRateOverrides.at(5678).getValue());
layers[1].vote = LayerVoteType::Heuristic;
- frameRateOverrides = refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f));
+ frameRateOverrides =
+ refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f), /*touch=*/false);
ASSERT_EQ(1, frameRateOverrides.size());
ASSERT_EQ(1, frameRateOverrides.count(1234));
ASSERT_EQ(60.0f, frameRateOverrides.at(1234).getValue());
layers[1].ownerUid = 1234;
- frameRateOverrides = refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f));
+ frameRateOverrides =
+ refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f), /*touch=*/false);
+ ASSERT_TRUE(frameRateOverrides.empty());
+}
+
+TEST_F(RefreshRateConfigsTest, getFrameRateOverrides_touch) {
+ auto refreshRateConfigs =
+ std::make_unique<RefreshRateConfigs>(m30_60_72_90_120Device, /*currentConfigId=*/
+ HWC_CONFIG_ID_120,
+ /*enableFrameRateOverride=*/true);
+
+ auto layers = std::vector<LayerRequirement>{
+ LayerRequirement{.ownerUid = 1234, .weight = 1.0f},
+ };
+
+ layers[0].name = "Test layer";
+ layers[0].desiredRefreshRate = Fps(60.0f);
+ layers[0].vote = LayerVoteType::ExplicitDefault;
+
+ auto frameRateOverrides =
+ refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f), /*touch=*/false);
+ ASSERT_EQ(1, frameRateOverrides.size());
+ ASSERT_EQ(1, frameRateOverrides.count(1234));
+ ASSERT_EQ(60.0f, frameRateOverrides.at(1234).getValue());
+
+ frameRateOverrides =
+ refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f), /*touch=*/true);
+ ASSERT_EQ(1, frameRateOverrides.size());
+ ASSERT_EQ(1, frameRateOverrides.count(1234));
+ ASSERT_EQ(60.0f, frameRateOverrides.at(1234).getValue());
+
+ layers[0].vote = LayerVoteType::ExplicitExact;
+ frameRateOverrides =
+ refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f), /*touch=*/false);
+ ASSERT_EQ(1, frameRateOverrides.size());
+ ASSERT_EQ(1, frameRateOverrides.count(1234));
+ ASSERT_EQ(60.0f, frameRateOverrides.at(1234).getValue());
+
+ frameRateOverrides =
+ refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f), /*touch=*/true);
+ ASSERT_EQ(1, frameRateOverrides.size());
+ ASSERT_EQ(1, frameRateOverrides.count(1234));
+ ASSERT_EQ(60.0f, frameRateOverrides.at(1234).getValue());
+
+ layers[0].vote = LayerVoteType::ExplicitExactOrMultiple;
+ frameRateOverrides =
+ refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f), /*touch=*/false);
+ ASSERT_EQ(1, frameRateOverrides.size());
+ ASSERT_EQ(1, frameRateOverrides.count(1234));
+ ASSERT_EQ(60.0f, frameRateOverrides.at(1234).getValue());
+
+ frameRateOverrides =
+ refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f), /*touch=*/true);
ASSERT_TRUE(frameRateOverrides.empty());
}
diff --git a/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp b/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp
index 1bbe8e2..e060df2 100644
--- a/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp
@@ -263,13 +263,13 @@
commitTransaction();
EXPECT_EQ(FRAME_RATE_VOTE3, parent->getFrameRateForLayerTree());
EXPECT_EQ(FRAME_RATE_VOTE2, child1->getFrameRateForLayerTree());
- EXPECT_EQ(FRAME_RATE_TREE, child2->getFrameRateForLayerTree());
+ EXPECT_EQ(FRAME_RATE_VOTE2, child2->getFrameRateForLayerTree());
child1->setFrameRate(FRAME_RATE_NO_VOTE);
commitTransaction();
EXPECT_EQ(FRAME_RATE_VOTE3, parent->getFrameRateForLayerTree());
- EXPECT_EQ(FRAME_RATE_TREE, child1->getFrameRateForLayerTree());
- EXPECT_EQ(FRAME_RATE_TREE, child2->getFrameRateForLayerTree());
+ EXPECT_EQ(FRAME_RATE_VOTE3, child1->getFrameRateForLayerTree());
+ EXPECT_EQ(FRAME_RATE_VOTE3, child2->getFrameRateForLayerTree());
parent->setFrameRate(FRAME_RATE_NO_VOTE);
commitTransaction();
@@ -293,8 +293,8 @@
parent->setFrameRate(FRAME_RATE_VOTE1);
commitTransaction();
EXPECT_EQ(FRAME_RATE_VOTE1, parent->getFrameRateForLayerTree());
- EXPECT_EQ(FRAME_RATE_TREE, child1->getFrameRateForLayerTree());
- EXPECT_EQ(FRAME_RATE_TREE, child2->getFrameRateForLayerTree());
+ EXPECT_EQ(FRAME_RATE_VOTE1, child1->getFrameRateForLayerTree());
+ EXPECT_EQ(FRAME_RATE_VOTE1, child2->getFrameRateForLayerTree());
parent->setFrameRate(FRAME_RATE_NO_VOTE);
commitTransaction();
@@ -356,14 +356,14 @@
parent->setFrameRate(FRAME_RATE_VOTE1);
commitTransaction();
EXPECT_EQ(FRAME_RATE_VOTE1, parent->getFrameRateForLayerTree());
- EXPECT_EQ(FRAME_RATE_TREE, child1->getFrameRateForLayerTree());
+ EXPECT_EQ(FRAME_RATE_VOTE1, child1->getFrameRateForLayerTree());
EXPECT_EQ(FRAME_RATE_NO_VOTE, child2->getFrameRateForLayerTree());
addChild(child1, child2);
commitTransaction();
EXPECT_EQ(FRAME_RATE_VOTE1, parent->getFrameRateForLayerTree());
- EXPECT_EQ(FRAME_RATE_TREE, child1->getFrameRateForLayerTree());
- EXPECT_EQ(FRAME_RATE_TREE, child2->getFrameRateForLayerTree());
+ EXPECT_EQ(FRAME_RATE_VOTE1, child1->getFrameRateForLayerTree());
+ EXPECT_EQ(FRAME_RATE_VOTE1, child2->getFrameRateForLayerTree());
parent->setFrameRate(FRAME_RATE_NO_VOTE);
commitTransaction();
@@ -387,13 +387,13 @@
parent->setFrameRate(FRAME_RATE_VOTE1);
commitTransaction();
EXPECT_EQ(FRAME_RATE_VOTE1, parent->getFrameRateForLayerTree());
- EXPECT_EQ(FRAME_RATE_TREE, child1->getFrameRateForLayerTree());
- EXPECT_EQ(FRAME_RATE_TREE, child2->getFrameRateForLayerTree());
+ EXPECT_EQ(FRAME_RATE_VOTE1, child1->getFrameRateForLayerTree());
+ EXPECT_EQ(FRAME_RATE_VOTE1, child2->getFrameRateForLayerTree());
removeChild(child1, child2);
commitTransaction();
EXPECT_EQ(FRAME_RATE_VOTE1, parent->getFrameRateForLayerTree());
- EXPECT_EQ(FRAME_RATE_TREE, child1->getFrameRateForLayerTree());
+ EXPECT_EQ(FRAME_RATE_VOTE1, child1->getFrameRateForLayerTree());
EXPECT_EQ(FRAME_RATE_NO_VOTE, child2->getFrameRateForLayerTree());
parent->setFrameRate(FRAME_RATE_NO_VOTE);
@@ -473,5 +473,20 @@
std::make_shared<EffectLayerFactory>()),
PrintToStringParamName);
+TEST_F(SetFrameRateTest, ValidateFrameRate) {
+ EXPECT_TRUE(ValidateFrameRate(60.0f, ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT, ""));
+ EXPECT_TRUE(ValidateFrameRate(60.0f, ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT, ""));
+ EXPECT_TRUE(ValidateFrameRate(60.0f, ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_FIXED_SOURCE, ""));
+ EXPECT_TRUE(ValidateFrameRate(60.0f, ANATIVEWINDOW_FRAME_RATE_EXACT, "", /*privileged=*/true));
+
+ EXPECT_FALSE(ValidateFrameRate(-1, ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT, ""));
+ EXPECT_FALSE(
+ ValidateFrameRate(1.0f / 0.0f, ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT, ""));
+ EXPECT_FALSE(
+ ValidateFrameRate(0.0f / 0.0f, ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT, ""));
+
+ EXPECT_FALSE(ValidateFrameRate(60.0f, ANATIVEWINDOW_FRAME_RATE_EXACT, ""));
+}
+
} // namespace
} // namespace android