SF: Unify data types for display modes
Remove the RefreshRateConfigs::RefreshRate wrapper around DisplayMode.
Store DisplayModes as a SmallMap, so that RefreshRateConfigs uses the
same data structure for lookup by ID. Use iterators into that map for
all bookkeeping in RefreshRateConfigs.
Bug: 182939859
Bug: 185535769
Test: libsurfaceflinger_unittest
Change-Id: I7708fa997089802c45d906b17b7a073f5c82105e
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index 0b23a5a..635b088 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -404,7 +404,7 @@
}
if (display) {
- const Fps refreshRate = display->refreshRateConfigs().getCurrentRefreshRate().getFps();
+ const Fps refreshRate = display->refreshRateConfigs().getActiveMode()->getFps();
const std::optional<Fps> renderRate =
mFlinger->mScheduler->getFrameRateOverride(getOwnerUid());
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 99335e5..f5a4b3d 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -196,7 +196,7 @@
ATRACE_INT(mActiveModeFPSTrace.c_str(), mode->getFps().getIntValue());
mActiveMode = mode;
if (mRefreshRateConfigs) {
- mRefreshRateConfigs->setCurrentModeId(mActiveMode->getId());
+ mRefreshRateConfigs->setActiveModeId(mActiveMode->getId());
}
if (mRefreshRateOverlay) {
mRefreshRateOverlay->changeRefreshRate(mActiveMode->getFps());
@@ -227,21 +227,16 @@
}
DisplayModePtr DisplayDevice::getMode(DisplayModeId modeId) const {
- const auto it =
- std::find_if(mSupportedModes.begin(), mSupportedModes.end(),
- [&](const DisplayModePtr& mode) { return mode->getId() == modeId; });
- if (it != mSupportedModes.end()) {
- return *it;
- }
- return nullptr;
+ const DisplayModePtr nullMode;
+ return mSupportedModes.get(modeId).value_or(std::cref(nullMode));
}
std::optional<DisplayModeId> DisplayDevice::translateModeId(hal::HWConfigId hwcId) const {
const auto it =
std::find_if(mSupportedModes.begin(), mSupportedModes.end(),
- [&](const DisplayModePtr& mode) { return mode->getHwcId() == hwcId; });
+ [hwcId](const auto& pair) { return pair.second->getHwcId() == hwcId; });
if (it != mSupportedModes.end()) {
- return (*it)->getId();
+ return it->second->getId();
}
return {};
}
@@ -366,12 +361,12 @@
activeMode ? to_string(*activeMode).c_str() : "none");
result.append(" supportedModes=\n");
-
- for (const auto& mode : mSupportedModes) {
- result.append(" ");
+ for (const auto& [id, mode] : mSupportedModes) {
+ result.append(" ");
result.append(to_string(*mode));
- result.append("\n");
+ result.push_back('\n');
}
+
StringAppendF(&result, " deviceProductInfo=");
if (mDeviceProductInfo) {
mDeviceProductInfo->dump(result);
diff --git a/services/surfaceflinger/DisplayHardware/DisplayMode.h b/services/surfaceflinger/DisplayHardware/DisplayMode.h
index 0ab9605..61a9a08 100644
--- a/services/surfaceflinger/DisplayHardware/DisplayMode.h
+++ b/services/surfaceflinger/DisplayHardware/DisplayMode.h
@@ -18,10 +18,10 @@
#include <cstddef>
#include <memory>
-#include <vector>
#include <android-base/stringprintf.h>
#include <android/configuration.h>
+#include <ftl/small_map.h>
#include <ui/DisplayId.h>
#include <ui/DisplayMode.h>
#include <ui/Size.h>
@@ -38,8 +38,17 @@
class DisplayMode;
using DisplayModePtr = std::shared_ptr<const DisplayMode>;
-using DisplayModes = std::vector<DisplayModePtr>;
-using DisplayModeId = StrongTyping<ui::DisplayModeId, struct DisplayModeIdTag, Compare, Hash>;
+
+// Prevent confusion with fps_approx_ops on the underlying Fps.
+bool operator<(const DisplayModePtr&, const DisplayModePtr&) = delete;
+bool operator>(const DisplayModePtr&, const DisplayModePtr&) = delete;
+bool operator<=(const DisplayModePtr&, const DisplayModePtr&) = delete;
+bool operator>=(const DisplayModePtr&, const DisplayModePtr&) = delete;
+
+using DisplayModeId = StrongTyping<ui::DisplayModeId, struct DisplayModeIdTag, Compare>;
+
+using DisplayModes = ftl::SmallMap<DisplayModeId, DisplayModePtr, 3>;
+using DisplayModeIterator = DisplayModes::const_iterator;
class DisplayMode {
public:
@@ -61,35 +70,30 @@
return *this;
}
- Builder& setWidth(int32_t width) {
- mDisplayMode->mWidth = width;
+ Builder& setResolution(ui::Size resolution) {
+ mDisplayMode->mResolution = resolution;
return *this;
}
- Builder& setHeight(int32_t height) {
- mDisplayMode->mHeight = height;
- return *this;
- }
-
- Builder& setVsyncPeriod(int32_t vsyncPeriod) {
+ Builder& setVsyncPeriod(nsecs_t vsyncPeriod) {
mDisplayMode->mFps = Fps::fromPeriodNsecs(vsyncPeriod);
return *this;
}
Builder& setDpiX(int32_t dpiX) {
if (dpiX == -1) {
- mDisplayMode->mDpiX = getDefaultDensity();
+ mDisplayMode->mDpi.x = getDefaultDensity();
} else {
- mDisplayMode->mDpiX = dpiX / 1000.0f;
+ mDisplayMode->mDpi.x = dpiX / 1000.f;
}
return *this;
}
Builder& setDpiY(int32_t dpiY) {
if (dpiY == -1) {
- mDisplayMode->mDpiY = getDefaultDensity();
+ mDisplayMode->mDpi.y = getDefaultDensity();
} else {
- mDisplayMode->mDpiY = dpiY / 1000.0f;
+ mDisplayMode->mDpi.y = dpiY / 1000.f;
}
return *this;
}
@@ -107,59 +111,76 @@
// information to begin with. This is also used for virtual displays and
// older HWC implementations, so be careful about orientation.
- auto longDimension = std::max(mDisplayMode->mWidth, mDisplayMode->mHeight);
- if (longDimension >= 1080) {
+ if (std::max(mDisplayMode->getWidth(), mDisplayMode->getHeight()) >= 1080) {
return ACONFIGURATION_DENSITY_XHIGH;
} else {
return ACONFIGURATION_DENSITY_TV;
}
}
+
std::shared_ptr<DisplayMode> mDisplayMode;
};
DisplayModeId getId() const { return mId; }
+
hal::HWConfigId getHwcId() const { return mHwcId; }
PhysicalDisplayId getPhysicalDisplayId() const { return mPhysicalDisplayId; }
- int32_t getWidth() const { return mWidth; }
- int32_t getHeight() const { return mHeight; }
- ui::Size getSize() const { return {mWidth, mHeight}; }
+ ui::Size getResolution() const { return mResolution; }
+ int32_t getWidth() const { return mResolution.getWidth(); }
+ int32_t getHeight() const { return mResolution.getHeight(); }
+
Fps getFps() const { return mFps; }
nsecs_t getVsyncPeriod() const { return mFps.getPeriodNsecs(); }
- float getDpiX() const { return mDpiX; }
- float getDpiY() const { return mDpiY; }
+
+ struct Dpi {
+ float x = -1;
+ float y = -1;
+
+ bool operator==(Dpi other) const { return x == other.x && y == other.y; }
+ };
+
+ Dpi getDpi() const { return mDpi; }
// Switches between modes in the same group are seamless, i.e.
// without visual interruptions such as a black screen.
int32_t getGroup() const { return mGroup; }
- bool equalsExceptDisplayModeId(const DisplayModePtr& other) const {
- return mHwcId == other->mHwcId && mWidth == other->mWidth && mHeight == other->mHeight &&
- getVsyncPeriod() == other->getVsyncPeriod() && mDpiX == other->mDpiX &&
- mDpiY == other->mDpiY && mGroup == other->mGroup;
- }
-
private:
explicit DisplayMode(hal::HWConfigId id) : mHwcId(id) {}
- hal::HWConfigId mHwcId;
+ const hal::HWConfigId mHwcId;
DisplayModeId mId;
+
PhysicalDisplayId mPhysicalDisplayId;
- int32_t mWidth = -1;
- int32_t mHeight = -1;
+ ui::Size mResolution;
Fps mFps;
- float mDpiX = -1;
- float mDpiY = -1;
+ Dpi mDpi;
int32_t mGroup = -1;
};
+inline bool equalsExceptDisplayModeId(const DisplayMode& lhs, const DisplayMode& rhs) {
+ return lhs.getHwcId() == rhs.getHwcId() && lhs.getResolution() == rhs.getResolution() &&
+ lhs.getVsyncPeriod() == rhs.getVsyncPeriod() && lhs.getDpi() == rhs.getDpi() &&
+ lhs.getGroup() == rhs.getGroup();
+}
+
inline std::string to_string(const DisplayMode& mode) {
- return base::StringPrintf("{id=%d, hwcId=%d, width=%d, height=%d, refreshRate=%s, "
- "dpiX=%.2f, dpiY=%.2f, group=%d}",
+ return base::StringPrintf("{id=%d, hwcId=%d, resolution=%dx%d, refreshRate=%s, "
+ "dpi=%.2fx%.2f, group=%d}",
mode.getId().value(), mode.getHwcId(), mode.getWidth(),
- mode.getHeight(), to_string(mode.getFps()).c_str(), mode.getDpiX(),
- mode.getDpiY(), mode.getGroup());
+ mode.getHeight(), to_string(mode.getFps()).c_str(), mode.getDpi().x,
+ mode.getDpi().y, mode.getGroup());
+}
+
+template <typename... DisplayModePtrs>
+inline DisplayModes makeModes(const DisplayModePtrs&... modePtrs) {
+ DisplayModes modes;
+ // Note: The omission of std::move(modePtrs) is intentional, because order of evaluation for
+ // arguments is unspecified.
+ (modes.try_emplace(modePtrs->getId(), modePtrs), ...);
+ return modes;
}
} // namespace android
diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
index 65c8613..3226f22 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
+++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
@@ -38,10 +38,33 @@
namespace android::scheduler {
namespace {
+struct RefreshRateScore {
+ DisplayModeIterator modeIt;
+ float score;
+};
+
+template <typename Iterator>
+const DisplayModePtr& getMaxScoreRefreshRate(Iterator begin, Iterator end) {
+ const auto it =
+ std::max_element(begin, end, [](RefreshRateScore max, RefreshRateScore current) {
+ const auto& [modeIt, score] = current;
+
+ std::string name = to_string(modeIt->second->getFps());
+ ALOGV("%s scores %.2f", name.c_str(), score);
+
+ ATRACE_INT(name.c_str(), static_cast<int>(std::round(score * 100)));
+
+ constexpr float kEpsilon = 0.0001f;
+ return score > max.score * (1 + kEpsilon);
+ });
+
+ return it->modeIt->second;
+}
+
constexpr RefreshRateConfigs::GlobalSignals kNoSignals;
std::string formatLayerInfo(const RefreshRateConfigs::LayerRequirement& layer, float weight) {
- return base::StringPrintf("%s (type=%s, weight=%.2f seamlessness=%s) %s", layer.name.c_str(),
+ return base::StringPrintf("%s (type=%s, weight=%.2f, seamlessness=%s) %s", layer.name.c_str(),
ftl::enum_string(layer.vote).c_str(), weight,
ftl::enum_string(layer.seamlessness).c_str(),
to_string(layer.desiredRefreshRate).c_str());
@@ -52,8 +75,8 @@
knownFrameRates.reserve(knownFrameRates.size() + modes.size());
// Add all supported refresh rates.
- for (const auto& mode : modes) {
- knownFrameRates.push_back(Fps::fromPeriodNsecs(mode->getVsyncPeriod()));
+ for (const auto& [id, mode] : modes) {
+ knownFrameRates.push_back(mode->getFps());
}
// Sort and remove duplicates.
@@ -64,17 +87,51 @@
return knownFrameRates;
}
-} // namespace
+// The Filter is a `bool(const DisplayMode&)` predicate.
+template <typename Filter>
+std::vector<DisplayModeIterator> sortByRefreshRate(const DisplayModes& modes, Filter&& filter) {
+ std::vector<DisplayModeIterator> sortedModes;
+ sortedModes.reserve(modes.size());
-using AllRefreshRatesMapType = RefreshRateConfigs::AllRefreshRatesMapType;
-using RefreshRate = RefreshRateConfigs::RefreshRate;
+ for (auto it = modes.begin(); it != modes.end(); ++it) {
+ const auto& [id, mode] = *it;
-std::string RefreshRate::toString() const {
- return base::StringPrintf("{id=%d, hwcId=%d, fps=%.2f, width=%d, height=%d group=%d}",
- getModeId().value(), mode->getHwcId(), getFps().getValue(),
- mode->getWidth(), mode->getHeight(), getModeGroup());
+ if (filter(*mode)) {
+ ALOGV("%s: including mode %d", __func__, id.value());
+ sortedModes.push_back(it);
+ }
+ }
+
+ std::sort(sortedModes.begin(), sortedModes.end(), [](auto it1, auto it2) {
+ const auto& mode1 = it1->second;
+ const auto& mode2 = it2->second;
+
+ if (mode1->getVsyncPeriod() == mode2->getVsyncPeriod()) {
+ return mode1->getGroup() > mode2->getGroup();
+ }
+
+ return mode1->getVsyncPeriod() > mode2->getVsyncPeriod();
+ });
+
+ return sortedModes;
}
+bool canModesSupportFrameRateOverride(const std::vector<DisplayModeIterator>& sortedModes) {
+ for (const auto it1 : sortedModes) {
+ const auto& mode1 = it1->second;
+ for (const auto it2 : sortedModes) {
+ const auto& mode2 = it2->second;
+
+ if (RefreshRateConfigs::getFrameRateDivisor(mode1->getFps(), mode2->getFps()) >= 2) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+} // namespace
+
std::string RefreshRateConfigs::Policy::toString() const {
return base::StringPrintf("default mode ID: %d, allowGroupSwitching = %d"
", primary range: %s, app request range: %s",
@@ -94,15 +151,14 @@
return {quotient, remainder};
}
-bool RefreshRateConfigs::isVoteAllowed(const LayerRequirement& layer,
- const RefreshRate& refreshRate) const {
+bool RefreshRateConfigs::isVoteAllowed(const LayerRequirement& layer, Fps refreshRate) const {
using namespace fps_approx_ops;
switch (layer.vote) {
case LayerVoteType::ExplicitExactOrMultiple:
case LayerVoteType::Heuristic:
if (mConfig.frameRateMultipleThreshold != 0 &&
- refreshRate.getFps() >= Fps::fromValue(mConfig.frameRateMultipleThreshold) &&
+ refreshRate >= Fps::fromValue(mConfig.frameRateMultipleThreshold) &&
layer.desiredRefreshRate < Fps::fromValue(mConfig.frameRateMultipleThreshold / 2)) {
// Don't vote high refresh rates past the threshold for layers with a low desired
// refresh rate. For example, desired 24 fps with 120 Hz threshold means no vote for
@@ -120,11 +176,11 @@
return true;
}
-float RefreshRateConfigs::calculateNonExactMatchingLayerScoreLocked(
- const LayerRequirement& layer, const RefreshRate& refreshRate) const {
+float RefreshRateConfigs::calculateNonExactMatchingLayerScoreLocked(const LayerRequirement& layer,
+ Fps refreshRate) const {
constexpr float kScoreForFractionalPairs = .8f;
- const auto displayPeriod = refreshRate.getVsyncPeriod();
+ const auto displayPeriod = refreshRate.getPeriodNsecs();
const auto layerPeriod = layer.desiredRefreshRate.getPeriodNsecs();
if (layer.vote == LayerVoteType::ExplicitDefault) {
// Find the actual rate the layer will render, assuming
@@ -147,7 +203,7 @@
if (layer.vote == LayerVoteType::ExplicitExactOrMultiple ||
layer.vote == LayerVoteType::Heuristic) {
- if (isFractionalPairOrMultiple(refreshRate.getFps(), layer.desiredRefreshRate)) {
+ if (isFractionalPairOrMultiple(refreshRate, layer.desiredRefreshRate)) {
return kScoreForFractionalPairs;
}
@@ -182,8 +238,7 @@
return 0;
}
-float RefreshRateConfigs::calculateLayerScoreLocked(const LayerRequirement& layer,
- const RefreshRate& refreshRate,
+float RefreshRateConfigs::calculateLayerScoreLocked(const LayerRequirement& layer, Fps refreshRate,
bool isSeamlessSwitch) const {
if (!isVoteAllowed(layer, refreshRate)) {
return 0;
@@ -195,14 +250,14 @@
// If the layer wants Max, give higher score to the higher refresh rate
if (layer.vote == LayerVoteType::Max) {
- const auto ratio = refreshRate.getFps().getValue() /
- mAppRequestRefreshRates.back()->getFps().getValue();
+ const auto& maxRefreshRate = mAppRequestRefreshRates.back()->second;
+ const auto ratio = refreshRate.getValue() / maxRefreshRate->getFps().getValue();
// use ratio^2 to get a lower score the more we get further from peak
return ratio * ratio;
}
if (layer.vote == LayerVoteType::ExplicitExact) {
- const int divisor = getFrameRateDivisor(refreshRate.getFps(), layer.desiredRefreshRate);
+ const int divisor = getFrameRateDivisor(refreshRate, layer.desiredRefreshRate);
if (mSupportsFrameRateOverrideByContent) {
// Since we support frame rate override, allow refresh rates which are
// multiples of the layer's request, as those apps would be throttled
@@ -215,7 +270,7 @@
// If the layer frame rate is a divisor of the refresh rate it should score
// the highest score.
- if (getFrameRateDivisor(refreshRate.getFps(), layer.desiredRefreshRate) > 0) {
+ if (getFrameRateDivisor(refreshRate, layer.desiredRefreshRate) > 0) {
return 1.0f * seamlessness;
}
@@ -227,14 +282,9 @@
kNonExactMatchingPenalty;
}
-struct RefreshRateScore {
- const RefreshRate* refreshRate;
- float score;
-};
-
auto RefreshRateConfigs::getBestRefreshRate(const std::vector<LayerRequirement>& layers,
GlobalSignals signals) const
- -> std::pair<RefreshRate, GlobalSignals> {
+ -> std::pair<DisplayModePtr, GlobalSignals> {
std::lock_guard lock(mLock);
if (mGetBestRefreshRateCache &&
@@ -249,7 +299,7 @@
auto RefreshRateConfigs::getBestRefreshRateLocked(const std::vector<LayerRequirement>& layers,
GlobalSignals signals) const
- -> std::pair<RefreshRate, GlobalSignals> {
+ -> std::pair<DisplayModePtr, GlobalSignals> {
ATRACE_CALL();
ALOGV("%s: %zu layers", __func__, layers.size());
@@ -298,21 +348,22 @@
explicitExactOrMultipleVoteLayers > 0 || explicitExact > 0;
const Policy* policy = getCurrentPolicyLocked();
- const auto& defaultMode = mRefreshRates.at(policy->defaultMode);
+ const auto& defaultMode = mDisplayModes.get(policy->defaultMode)->get();
// If the default mode group is different from the group of current mode,
// this means a layer requesting a seamed mode switch just disappeared and
// we should switch back to the default group.
// However if a seamed layer is still present we anchor around the group
// of the current mode, in order to prevent unnecessary seamed mode switches
// (e.g. when pausing a video playback).
- const auto anchorGroup = seamedFocusedLayers > 0 ? mCurrentRefreshRate->getModeGroup()
- : defaultMode->getModeGroup();
+ const auto anchorGroup =
+ seamedFocusedLayers > 0 ? mActiveModeIt->second->getGroup() : defaultMode->getGroup();
// 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.
if (signals.touch && !hasExplicitVoteLayers) {
- ALOGV("TouchBoost - choose %s", getMaxRefreshRateByPolicyLocked().getName().c_str());
- return {getMaxRefreshRateByPolicyLocked(anchorGroup), GlobalSignals{.touch = true}};
+ const DisplayModePtr& max = getMaxRefreshRateByPolicyLocked(anchorGroup);
+ ALOGV("TouchBoost - choose %s", to_string(max->getFps()).c_str());
+ return {max, GlobalSignals{.touch = true}};
}
// If the primary range consists of a single refresh rate then we can only
@@ -322,28 +373,30 @@
isApproxEqual(policy->primaryRange.min, policy->primaryRange.max);
if (!signals.touch && signals.idle && !(primaryRangeIsSingleRate && hasExplicitVoteLayers)) {
- ALOGV("Idle - choose %s", getMinRefreshRateByPolicyLocked().getName().c_str());
- return {getMinRefreshRateByPolicyLocked(), GlobalSignals{.idle = true}};
+ const DisplayModePtr& min = getMinRefreshRateByPolicyLocked();
+ ALOGV("Idle - choose %s", to_string(min->getFps()).c_str());
+ return {min, GlobalSignals{.idle = true}};
}
if (layers.empty() || noVoteLayers == layers.size()) {
- const auto& refreshRate = getMaxRefreshRateByPolicyLocked(anchorGroup);
- ALOGV("no layers with votes - choose %s", refreshRate.getName().c_str());
- return {refreshRate, kNoSignals};
+ const DisplayModePtr& max = getMaxRefreshRateByPolicyLocked(anchorGroup);
+ ALOGV("no layers with votes - choose %s", to_string(max->getFps()).c_str());
+ return {max, kNoSignals};
}
// Only if all layers want Min we should return Min
if (noVoteLayers + minVoteLayers == layers.size()) {
- ALOGV("all layers Min - choose %s", getMinRefreshRateByPolicyLocked().getName().c_str());
- return {getMinRefreshRateByPolicyLocked(), kNoSignals};
+ const DisplayModePtr& min = getMinRefreshRateByPolicyLocked();
+ ALOGV("all layers Min - choose %s", to_string(min->getFps()).c_str());
+ return {min, kNoSignals};
}
// Find the best refresh rate based on score
std::vector<RefreshRateScore> scores;
scores.reserve(mAppRequestRefreshRates.size());
- for (const auto refreshRate : mAppRequestRefreshRates) {
- scores.emplace_back(RefreshRateScore{refreshRate, 0.0f});
+ for (const DisplayModeIterator modeIt : mAppRequestRefreshRates) {
+ scores.emplace_back(RefreshRateScore{modeIt, 0.0f});
}
for (const auto& layer : layers) {
@@ -354,17 +407,16 @@
continue;
}
- auto weight = layer.weight;
+ const auto weight = layer.weight;
- for (auto i = 0u; i < scores.size(); i++) {
- const bool isSeamlessSwitch =
- scores[i].refreshRate->getModeGroup() == mCurrentRefreshRate->getModeGroup();
+ for (auto& [modeIt, score] : scores) {
+ const auto& [id, mode] = *modeIt;
+ const bool isSeamlessSwitch = mode->getGroup() == mActiveModeIt->second->getGroup();
if (layer.seamlessness == Seamlessness::OnlySeamless && !isSeamlessSwitch) {
ALOGV("%s ignores %s to avoid non-seamless switch. Current mode = %s",
- formatLayerInfo(layer, weight).c_str(),
- scores[i].refreshRate->toString().c_str(),
- mCurrentRefreshRate->toString().c_str());
+ formatLayerInfo(layer, weight).c_str(), to_string(*mode).c_str(),
+ to_string(*mActiveModeIt->second).c_str());
continue;
}
@@ -372,9 +424,8 @@
!layer.focused) {
ALOGV("%s ignores %s because it's not focused and the switch is going to be seamed."
" Current mode = %s",
- formatLayerInfo(layer, weight).c_str(),
- scores[i].refreshRate->toString().c_str(),
- mCurrentRefreshRate->toString().c_str());
+ formatLayerInfo(layer, weight).c_str(), to_string(*mode).c_str(),
+ to_string(*mActiveModeIt->second).c_str());
continue;
}
@@ -383,17 +434,14 @@
// mode group otherwise. In second case, if the current mode group is different
// from the default, this means a layer with seamlessness=SeamedAndSeamless has just
// disappeared.
- const bool isInPolicyForDefault = scores[i].refreshRate->getModeGroup() == anchorGroup;
+ const bool isInPolicyForDefault = mode->getGroup() == anchorGroup;
if (layer.seamlessness == Seamlessness::Default && !isInPolicyForDefault) {
ALOGV("%s ignores %s. Current mode = %s", formatLayerInfo(layer, weight).c_str(),
- scores[i].refreshRate->toString().c_str(),
- mCurrentRefreshRate->toString().c_str());
+ to_string(*mode).c_str(), to_string(*mActiveModeIt->second).c_str());
continue;
}
- const bool inPrimaryRange =
- policy->primaryRange.includes(scores[i].refreshRate->getFps());
-
+ const bool inPrimaryRange = policy->primaryRange.includes(mode->getFps());
if ((primaryRangeIsSingleRate || !inPrimaryRange) &&
!(layer.focused &&
(layer.vote == LayerVoteType::ExplicitDefault ||
@@ -404,30 +452,31 @@
}
const auto layerScore =
- calculateLayerScoreLocked(layer, *scores[i].refreshRate, isSeamlessSwitch);
+ calculateLayerScoreLocked(layer, mode->getFps(), isSeamlessSwitch);
ALOGV("%s gives %s score of %.4f", formatLayerInfo(layer, weight).c_str(),
- scores[i].refreshRate->getName().c_str(), layerScore);
- scores[i].score += weight * layerScore;
+ to_string(mode->getFps()).c_str(), layerScore);
+
+ score += weight * layerScore;
}
}
// Now that we scored all the refresh rates we need to pick the one that got the highest score.
// In case of a tie we will pick the higher refresh rate if any of the layers wanted Max,
// or the lower otherwise.
- const RefreshRate* bestRefreshRate = maxVoteLayers > 0
- ? getBestRefreshRate(scores.rbegin(), scores.rend())
- : getBestRefreshRate(scores.begin(), scores.end());
+ const DisplayModePtr& bestRefreshRate = maxVoteLayers > 0
+ ? getMaxScoreRefreshRate(scores.rbegin(), scores.rend())
+ : getMaxScoreRefreshRate(scores.begin(), scores.end());
if (primaryRangeIsSingleRate) {
// If we never scored any layers, then choose the rate from the primary
// range instead of picking a random score from the app range.
if (std::all_of(scores.begin(), scores.end(),
[](RefreshRateScore score) { return score.score == 0; })) {
- const auto& refreshRate = getMaxRefreshRateByPolicyLocked(anchorGroup);
- ALOGV("layers not scored - choose %s", refreshRate.getName().c_str());
- return {refreshRate, kNoSignals};
+ const DisplayModePtr& max = getMaxRefreshRateByPolicyLocked(anchorGroup);
+ ALOGV("layers not scored - choose %s", to_string(max->getFps()).c_str());
+ return {max, kNoSignals};
} else {
- return {*bestRefreshRate, kNoSignals};
+ return {bestRefreshRate, kNoSignals};
}
}
@@ -435,7 +484,7 @@
// interactive (as opposed to ExplicitExactOrMultiple) and therefore if those posted an explicit
// vote we should not change it if we get a touch event. Only apply touch boost if it will
// actually increase the refresh rate over the normal selection.
- const RefreshRate& touchRefreshRate = getMaxRefreshRateByPolicyLocked(anchorGroup);
+ const DisplayModePtr& touchRefreshRate = getMaxRefreshRateByPolicyLocked(anchorGroup);
const bool touchBoostForExplicitExact = [&] {
if (mSupportsFrameRateOverrideByContent) {
@@ -450,12 +499,12 @@
using fps_approx_ops::operator<;
if (signals.touch && explicitDefaultVoteLayers == 0 && touchBoostForExplicitExact &&
- bestRefreshRate->getFps() < touchRefreshRate.getFps()) {
- ALOGV("TouchBoost - choose %s", touchRefreshRate.getName().c_str());
+ bestRefreshRate->getFps() < touchRefreshRate->getFps()) {
+ ALOGV("TouchBoost - choose %s", to_string(touchRefreshRate->getFps()).c_str());
return {touchRefreshRate, GlobalSignals{.touch = true}};
}
- return {*bestRefreshRate, kNoSignals};
+ return {bestRefreshRate, kNoSignals};
}
std::unordered_map<uid_t, std::vector<const RefreshRateConfigs::LayerRequirement*>>
@@ -489,26 +538,28 @@
return layersByUid;
}
-std::vector<RefreshRateScore> initializeScoresForAllRefreshRates(
- const AllRefreshRatesMapType& refreshRates) {
- std::vector<RefreshRateScore> scores;
- scores.reserve(refreshRates.size());
- for (const auto& [ignored, refreshRate] : refreshRates) {
- scores.emplace_back(RefreshRateScore{refreshRate.get(), 0.0f});
- }
- std::sort(scores.begin(), scores.end(),
- [](const auto& a, const auto& b) { return *a.refreshRate < *b.refreshRate; });
- return scores;
-}
-
RefreshRateConfigs::UidToFrameRateOverride RefreshRateConfigs::getFrameRateOverrides(
- const std::vector<LayerRequirement>& layers, Fps displayFrameRate,
+ const std::vector<LayerRequirement>& layers, Fps displayRefreshRate,
GlobalSignals globalSignals) const {
ATRACE_CALL();
- ALOGV("getFrameRateOverrides %zu layers", layers.size());
+ ALOGV("%s: %zu layers", __func__, layers.size());
+
std::lock_guard lock(mLock);
- std::vector<RefreshRateScore> scores = initializeScoresForAllRefreshRates(mRefreshRates);
+
+ std::vector<RefreshRateScore> scores;
+ scores.reserve(mDisplayModes.size());
+
+ for (auto it = mDisplayModes.begin(); it != mDisplayModes.end(); ++it) {
+ scores.emplace_back(RefreshRateScore{it, 0.0f});
+ }
+
+ std::sort(scores.begin(), scores.end(), [](const auto& lhs, const auto& rhs) {
+ const auto& mode1 = lhs.modeIt->second;
+ const auto& mode2 = rhs.modeIt->second;
+ return isStrictlyLess(mode1->getFps(), mode2->getFps());
+ });
+
std::unordered_map<uid_t, std::vector<const LayerRequirement*>> layersByUid =
groupLayersByUid(layers);
UidToFrameRateOverride frameRateOverrides;
@@ -524,8 +575,8 @@
continue;
}
- for (auto& score : scores) {
- score.score = 0;
+ for (auto& [_, score] : scores) {
+ score = 0;
}
for (const auto& layer : layersWithSameUid) {
@@ -536,137 +587,114 @@
LOG_ALWAYS_FATAL_IF(layer->vote != LayerVoteType::ExplicitDefault &&
layer->vote != LayerVoteType::ExplicitExactOrMultiple &&
layer->vote != LayerVoteType::ExplicitExact);
- for (RefreshRateScore& score : scores) {
- const auto layerScore = calculateLayerScoreLocked(*layer, *score.refreshRate,
- /*isSeamlessSwitch*/ true);
- score.score += layer->weight * layerScore;
+ for (auto& [modeIt, score] : scores) {
+ constexpr bool isSeamlessSwitch = true;
+ const auto layerScore = calculateLayerScoreLocked(*layer, modeIt->second->getFps(),
+ isSeamlessSwitch);
+ score += layer->weight * layerScore;
}
}
// We just care about the refresh rates which are a divisor of the
// display refresh rate
- auto iter =
- std::remove_if(scores.begin(), scores.end(), [&](const RefreshRateScore& score) {
- return getFrameRateDivisor(displayFrameRate, score.refreshRate->getFps()) == 0;
- });
- scores.erase(iter, scores.end());
+ const auto it = std::remove_if(scores.begin(), scores.end(), [&](RefreshRateScore score) {
+ const auto& [id, mode] = *score.modeIt;
+ return getFrameRateDivisor(displayRefreshRate, mode->getFps()) == 0;
+ });
+ scores.erase(it, scores.end());
// If we never scored any layers, we don't have a preferred frame rate
if (std::all_of(scores.begin(), scores.end(),
- [](const RefreshRateScore& score) { return score.score == 0; })) {
+ [](RefreshRateScore score) { return score.score == 0; })) {
continue;
}
// Now that we scored all the refresh rates we need to pick the one that got the highest
// score.
- const RefreshRate* bestRefreshRate = getBestRefreshRate(scores.begin(), scores.end());
+ const DisplayModePtr& bestRefreshRate =
+ getMaxScoreRefreshRate(scores.begin(), scores.end());
+
frameRateOverrides.emplace(uid, bestRefreshRate->getFps());
}
return frameRateOverrides;
}
-template <typename Iter>
-const RefreshRate* RefreshRateConfigs::getBestRefreshRate(Iter begin, Iter end) const {
- constexpr auto kEpsilon = 0.0001f;
- const RefreshRate* bestRefreshRate = begin->refreshRate;
- float max = begin->score;
- for (auto i = begin; i != end; ++i) {
- const auto [refreshRate, score] = *i;
- ALOGV("%s scores %.2f", refreshRate->getName().c_str(), score);
-
- ATRACE_INT(refreshRate->getName().c_str(), static_cast<int>(std::round(score * 100)));
-
- if (score > max * (1 + kEpsilon)) {
- max = score;
- bestRefreshRate = refreshRate;
- }
- }
-
- return bestRefreshRate;
-}
-
std::optional<Fps> RefreshRateConfigs::onKernelTimerChanged(
- std::optional<DisplayModeId> desiredActiveConfigId, bool timerExpired) const {
+ std::optional<DisplayModeId> desiredActiveModeId, bool timerExpired) const {
std::lock_guard lock(mLock);
- const auto& current = desiredActiveConfigId ? *mRefreshRates.at(*desiredActiveConfigId)
- : *mCurrentRefreshRate;
- const auto& min = *mMinSupportedRefreshRate;
+ const DisplayModePtr& current = desiredActiveModeId
+ ? mDisplayModes.get(*desiredActiveModeId)->get()
+ : mActiveModeIt->second;
- if (current != min) {
- const auto& refreshRate = timerExpired ? min : current;
- return refreshRate.getFps();
+ const DisplayModePtr& min = mMinRefreshRateModeIt->second;
+ if (current == min) {
+ return {};
}
- return {};
+ const auto& mode = timerExpired ? min : current;
+ return mode->getFps();
}
-const RefreshRate& RefreshRateConfigs::getMinRefreshRateByPolicyLocked() const {
- for (auto refreshRate : mPrimaryRefreshRates) {
- if (mCurrentRefreshRate->getModeGroup() == refreshRate->getModeGroup()) {
- return *refreshRate;
+const DisplayModePtr& RefreshRateConfigs::getMinRefreshRateByPolicyLocked() const {
+ for (const DisplayModeIterator modeIt : mPrimaryRefreshRates) {
+ const auto& mode = modeIt->second;
+ if (mActiveModeIt->second->getGroup() == mode->getGroup()) {
+ return mode;
}
}
+
ALOGE("Can't find min refresh rate by policy with the same mode group"
" as the current mode %s",
- mCurrentRefreshRate->toString().c_str());
- // Defaulting to the lowest refresh rate
- return *mPrimaryRefreshRates.front();
+ to_string(*mActiveModeIt->second).c_str());
+
+ // Default to the lowest refresh rate.
+ return mPrimaryRefreshRates.front()->second;
}
-RefreshRate RefreshRateConfigs::getMaxRefreshRateByPolicy() const {
+DisplayModePtr RefreshRateConfigs::getMaxRefreshRateByPolicy() const {
std::lock_guard lock(mLock);
return getMaxRefreshRateByPolicyLocked();
}
-const RefreshRate& RefreshRateConfigs::getMaxRefreshRateByPolicyLocked(int anchorGroup) const {
- for (auto it = mPrimaryRefreshRates.rbegin(); it != mPrimaryRefreshRates.rend(); it++) {
- const auto& refreshRate = (**it);
- if (anchorGroup == refreshRate.getModeGroup()) {
- return refreshRate;
+const DisplayModePtr& RefreshRateConfigs::getMaxRefreshRateByPolicyLocked(int anchorGroup) const {
+ for (auto it = mPrimaryRefreshRates.rbegin(); it != mPrimaryRefreshRates.rend(); ++it) {
+ const auto& mode = (*it)->second;
+ if (anchorGroup == mode->getGroup()) {
+ return mode;
}
}
+
ALOGE("Can't find max refresh rate by policy with the same mode group"
" as the current mode %s",
- mCurrentRefreshRate->toString().c_str());
- // Defaulting to the highest refresh rate
- return *mPrimaryRefreshRates.back();
+ to_string(*mActiveModeIt->second).c_str());
+
+ // Default to the highest refresh rate.
+ return mPrimaryRefreshRates.back()->second;
}
-RefreshRate RefreshRateConfigs::getCurrentRefreshRate() const {
+DisplayModePtr RefreshRateConfigs::getActiveMode() const {
std::lock_guard lock(mLock);
- return *mCurrentRefreshRate;
+ return mActiveModeIt->second;
}
-RefreshRate RefreshRateConfigs::getCurrentRefreshRateByPolicy() const {
- std::lock_guard lock(mLock);
- return getCurrentRefreshRateByPolicyLocked();
-}
-
-const RefreshRate& RefreshRateConfigs::getCurrentRefreshRateByPolicyLocked() const {
- if (std::find(mAppRequestRefreshRates.begin(), mAppRequestRefreshRates.end(),
- mCurrentRefreshRate) != mAppRequestRefreshRates.end()) {
- return *mCurrentRefreshRate;
- }
- return *mRefreshRates.at(getCurrentPolicyLocked()->defaultMode);
-}
-
-void RefreshRateConfigs::setCurrentModeId(DisplayModeId modeId) {
+void RefreshRateConfigs::setActiveModeId(DisplayModeId modeId) {
std::lock_guard lock(mLock);
// Invalidate the cached invocation to getBestRefreshRate. This forces
// the refresh rate to be recomputed on the next call to getBestRefreshRate.
mGetBestRefreshRateCache.reset();
- mCurrentRefreshRate = mRefreshRates.at(modeId).get();
+ mActiveModeIt = mDisplayModes.find(modeId);
+ LOG_ALWAYS_FATAL_IF(mActiveModeIt == mDisplayModes.end());
}
-RefreshRateConfigs::RefreshRateConfigs(const DisplayModes& modes, DisplayModeId currentModeId,
+RefreshRateConfigs::RefreshRateConfigs(DisplayModes modes, DisplayModeId activeModeId,
Config config)
: mKnownFrameRates(constructKnownFrameRates(modes)), mConfig(config) {
initializeIdleTimer();
- updateDisplayModes(modes, currentModeId);
+ updateDisplayModes(std::move(modes), activeModeId);
}
void RefreshRateConfigs::initializeIdleTimer() {
@@ -688,64 +716,43 @@
}
}
-void RefreshRateConfigs::updateDisplayModes(const DisplayModes& modes,
- DisplayModeId currentModeId) {
+void RefreshRateConfigs::updateDisplayModes(DisplayModes modes, DisplayModeId activeModeId) {
std::lock_guard lock(mLock);
- // The current mode should be supported
- LOG_ALWAYS_FATAL_IF(std::none_of(modes.begin(), modes.end(), [&](DisplayModePtr mode) {
- return mode->getId() == currentModeId;
- }));
-
// Invalidate the cached invocation to getBestRefreshRate. This forces
// the refresh rate to be recomputed on the next call to getBestRefreshRate.
mGetBestRefreshRateCache.reset();
- mRefreshRates.clear();
- for (const auto& mode : modes) {
- const auto modeId = mode->getId();
- mRefreshRates.emplace(modeId,
- std::make_unique<RefreshRate>(mode, RefreshRate::ConstructorTag(0)));
- if (modeId == currentModeId) {
- mCurrentRefreshRate = mRefreshRates.at(modeId).get();
- }
- }
+ mDisplayModes = std::move(modes);
+ mActiveModeIt = mDisplayModes.find(activeModeId);
+ LOG_ALWAYS_FATAL_IF(mActiveModeIt == mDisplayModes.end());
- std::vector<const RefreshRate*> sortedModes;
- getSortedRefreshRateListLocked([](const RefreshRate&) { return true; }, &sortedModes);
+ const auto sortedModes =
+ sortByRefreshRate(mDisplayModes, [](const DisplayMode&) { return true; });
+ mMinRefreshRateModeIt = sortedModes.front();
+ mMaxRefreshRateModeIt = sortedModes.back();
+
// Reset the policy because the old one may no longer be valid.
mDisplayManagerPolicy = {};
- mDisplayManagerPolicy.defaultMode = currentModeId;
- mMinSupportedRefreshRate = sortedModes.front();
- mMaxSupportedRefreshRate = sortedModes.back();
+ mDisplayManagerPolicy.defaultMode = activeModeId;
- mSupportsFrameRateOverrideByContent = false;
- if (mConfig.enableFrameRateOverride) {
- for (const auto& mode1 : sortedModes) {
- for (const auto& mode2 : sortedModes) {
- if (getFrameRateDivisor(mode1->getFps(), mode2->getFps()) >= 2) {
- mSupportsFrameRateOverrideByContent = true;
- break;
- }
- }
- }
- }
+ mSupportsFrameRateOverrideByContent =
+ mConfig.enableFrameRateOverride && canModesSupportFrameRateOverride(sortedModes);
constructAvailableRefreshRates();
}
bool RefreshRateConfigs::isPolicyValidLocked(const Policy& policy) const {
// defaultMode must be a valid mode, and within the given refresh rate range.
- auto iter = mRefreshRates.find(policy.defaultMode);
- if (iter == mRefreshRates.end()) {
+ if (const auto mode = mDisplayModes.get(policy.defaultMode)) {
+ if (!policy.primaryRange.includes(mode->get()->getFps())) {
+ ALOGE("Default mode is not in the primary range.");
+ return false;
+ }
+ } else {
ALOGE("Default mode is not found.");
return false;
}
- const RefreshRate& refreshRate = *iter->second;
- if (!policy.primaryRange.includes(refreshRate.getFps())) {
- ALOGE("Default mode is not in the primary range.");
- return false;
- }
using namespace fps_approx_ops;
return policy.appRequestRange.min <= policy.primaryRange.min &&
@@ -799,77 +806,46 @@
bool RefreshRateConfigs::isModeAllowed(DisplayModeId modeId) const {
std::lock_guard lock(mLock);
- for (const RefreshRate* refreshRate : mAppRequestRefreshRates) {
- if (refreshRate->getModeId() == modeId) {
- return true;
- }
- }
- return false;
-}
-
-void RefreshRateConfigs::getSortedRefreshRateListLocked(
- const std::function<bool(const RefreshRate&)>& shouldAddRefreshRate,
- std::vector<const RefreshRate*>* outRefreshRates) {
- outRefreshRates->clear();
- outRefreshRates->reserve(mRefreshRates.size());
- for (const auto& [type, refreshRate] : mRefreshRates) {
- if (shouldAddRefreshRate(*refreshRate)) {
- ALOGV("getSortedRefreshRateListLocked: mode %d added to list policy",
- refreshRate->getModeId().value());
- outRefreshRates->push_back(refreshRate.get());
- }
- }
-
- std::sort(outRefreshRates->begin(), outRefreshRates->end(),
- [](const auto refreshRate1, const auto refreshRate2) {
- if (refreshRate1->mode->getVsyncPeriod() !=
- refreshRate2->mode->getVsyncPeriod()) {
- return refreshRate1->mode->getVsyncPeriod() >
- refreshRate2->mode->getVsyncPeriod();
- } else {
- return refreshRate1->mode->getGroup() > refreshRate2->mode->getGroup();
- }
- });
+ return std::any_of(mAppRequestRefreshRates.begin(), mAppRequestRefreshRates.end(),
+ [modeId](DisplayModeIterator modeIt) {
+ return modeIt->second->getId() == modeId;
+ });
}
void RefreshRateConfigs::constructAvailableRefreshRates() {
- // Filter modes based on current policy and sort based on vsync period
+ // Filter modes based on current policy and sort on refresh rate.
const Policy* policy = getCurrentPolicyLocked();
- const auto& defaultMode = mRefreshRates.at(policy->defaultMode)->mode;
- ALOGV("constructAvailableRefreshRates: %s ", policy->toString().c_str());
+ ALOGV("%s: %s ", __func__, policy->toString().c_str());
- auto filterRefreshRates =
- [&](FpsRange range, const char* rangeName,
- std::vector<const RefreshRate*>* outRefreshRates) REQUIRES(mLock) {
- getSortedRefreshRateListLocked(
- [&](const RefreshRate& refreshRate) REQUIRES(mLock) {
- const auto& mode = refreshRate.mode;
+ const auto& defaultMode = mDisplayModes.get(policy->defaultMode)->get();
- return mode->getHeight() == defaultMode->getHeight() &&
- mode->getWidth() == defaultMode->getWidth() &&
- mode->getDpiX() == defaultMode->getDpiX() &&
- mode->getDpiY() == defaultMode->getDpiY() &&
- (policy->allowGroupSwitching ||
- mode->getGroup() == defaultMode->getGroup()) &&
- range.includes(mode->getFps());
- },
- outRefreshRates);
+ const auto filterRefreshRates = [&](FpsRange range, const char* rangeName) REQUIRES(mLock) {
+ const auto filter = [&](const DisplayMode& mode) {
+ return mode.getResolution() == defaultMode->getResolution() &&
+ mode.getDpi() == defaultMode->getDpi() &&
+ (policy->allowGroupSwitching || mode.getGroup() == defaultMode->getGroup()) &&
+ range.includes(mode.getFps());
+ };
- LOG_ALWAYS_FATAL_IF(outRefreshRates->empty(), "No matching modes for %s range %s",
- rangeName, to_string(range).c_str());
+ const auto modes = sortByRefreshRate(mDisplayModes, filter);
+ LOG_ALWAYS_FATAL_IF(modes.empty(), "No matching modes for %s range %s", rangeName,
+ to_string(range).c_str());
- auto stringifyRefreshRates = [&]() -> std::string {
- std::string str;
- for (auto refreshRate : *outRefreshRates) {
- base::StringAppendF(&str, "%s ", refreshRate->getName().c_str());
- }
- return str;
- };
- ALOGV("%s refresh rates: %s", rangeName, stringifyRefreshRates().c_str());
- };
+ const auto stringifyModes = [&] {
+ std::string str;
+ for (const auto modeIt : modes) {
+ str += to_string(modeIt->second->getFps());
+ str.push_back(' ');
+ }
+ return str;
+ };
+ ALOGV("%s refresh rates: %s", rangeName, stringifyModes().c_str());
- filterRefreshRates(policy->primaryRange, "primary", &mPrimaryRefreshRates);
- filterRefreshRates(policy->appRequestRange, "app request", &mAppRequestRefreshRates);
+ return modes;
+ };
+
+ mPrimaryRefreshRates = filterRefreshRates(policy->primaryRange, "primary");
+ mAppRequestRefreshRates = filterRefreshRates(policy->appRequestRange, "app request");
}
Fps RefreshRateConfigs::findClosestKnownFrameRate(Fps frameRate) const {
@@ -893,36 +869,39 @@
RefreshRateConfigs::KernelIdleTimerAction RefreshRateConfigs::getIdleTimerAction() const {
std::lock_guard lock(mLock);
- const auto& deviceMin = *mMinSupportedRefreshRate;
- const auto& minByPolicy = getMinRefreshRateByPolicyLocked();
- const auto& maxByPolicy = getMaxRefreshRateByPolicyLocked();
- const auto& currentPolicy = getCurrentPolicyLocked();
+
+ const Fps deviceMinFps = mMinRefreshRateModeIt->second->getFps();
+ const DisplayModePtr& minByPolicy = getMinRefreshRateByPolicyLocked();
// Kernel idle timer will set the refresh rate to the device min. If DisplayManager says that
// the min allowed refresh rate is higher than the device min, we do not want to enable the
// timer.
- if (deviceMin < minByPolicy) {
- return RefreshRateConfigs::KernelIdleTimerAction::TurnOff;
+ if (isStrictlyLess(deviceMinFps, minByPolicy->getFps())) {
+ return KernelIdleTimerAction::TurnOff;
}
+
+ const DisplayModePtr& maxByPolicy = getMaxRefreshRateByPolicyLocked();
if (minByPolicy == maxByPolicy) {
- // when min primary range in display manager policy is below device min turn on the timer.
- if (isApproxLess(currentPolicy->primaryRange.min, deviceMin.getFps())) {
- return RefreshRateConfigs::KernelIdleTimerAction::TurnOn;
+ // Turn on the timer when the min of the primary range is below the device min.
+ if (const Policy* currentPolicy = getCurrentPolicyLocked();
+ isApproxLess(currentPolicy->primaryRange.min, deviceMinFps)) {
+ return KernelIdleTimerAction::TurnOn;
}
- return RefreshRateConfigs::KernelIdleTimerAction::TurnOff;
+ return KernelIdleTimerAction::TurnOff;
}
+
// Turn on the timer in all other cases.
- return RefreshRateConfigs::KernelIdleTimerAction::TurnOn;
+ return KernelIdleTimerAction::TurnOn;
}
-int RefreshRateConfigs::getFrameRateDivisor(Fps displayFrameRate, Fps layerFrameRate) {
+int RefreshRateConfigs::getFrameRateDivisor(Fps displayRefreshRate, Fps layerFrameRate) {
// This calculation needs to be in sync with the java code
// in DisplayManagerService.getDisplayInfoForFrameRateOverride
// The threshold must be smaller than 0.001 in order to differentiate
// between the fractional pairs (e.g. 59.94 and 60).
constexpr float kThreshold = 0.0009f;
- const auto numPeriods = displayFrameRate.getValue() / layerFrameRate.getValue();
+ const auto numPeriods = displayRefreshRate.getValue() / layerFrameRate.getValue();
const auto numPeriodsRounded = std::round(numPeriods);
if (std::abs(numPeriods - numPeriodsRounded) > kThreshold) {
return 0;
@@ -952,29 +931,32 @@
currentPolicy.toString().c_str());
}
- auto mode = mCurrentRefreshRate->mode;
- base::StringAppendF(&result, "Current mode: %s\n", mCurrentRefreshRate->toString().c_str());
+ base::StringAppendF(&result, "Active mode: %s\n", to_string(*mActiveModeIt->second).c_str());
- result.append("Refresh rates:\n");
- for (const auto& [id, refreshRate] : mRefreshRates) {
- mode = refreshRate->mode;
- base::StringAppendF(&result, "\t%s\n", refreshRate->toString().c_str());
+ result.append("Display modes:\n");
+ for (const auto& [id, mode] : mDisplayModes) {
+ result.push_back('\t');
+ result.append(to_string(*mode));
+ result.push_back('\n');
}
base::StringAppendF(&result, "Supports Frame Rate Override By Content: %s\n",
mSupportsFrameRateOverrideByContent ? "yes" : "no");
- base::StringAppendF(&result, "Idle timer: ");
- if (mConfig.kernelIdleTimerController.has_value()) {
- if (mConfig.kernelIdleTimerController == KernelIdleTimerController::Sysprop) {
- base::StringAppendF(&result, "(kernel(sysprop))");
- } else {
- base::StringAppendF(&result, "(kernel(hwc))");
- }
+
+ result.append("Idle timer: ");
+ if (const auto controller = mConfig.kernelIdleTimerController) {
+ base::StringAppendF(&result, "(kernel via %s) ", ftl::enum_string(*controller).c_str());
} else {
- base::StringAppendF(&result, "(platform)");
+ result.append("(platform) ");
}
- base::StringAppendF(&result, " %s\n", mIdleTimer ? mIdleTimer->dump().c_str() : "off");
- result.append("\n");
+
+ if (mIdleTimer) {
+ result.append(mIdleTimer->dump());
+ } else {
+ result.append("off");
+ }
+
+ result.append("\n\n");
}
std::chrono::milliseconds RefreshRateConfigs::getIdleTimerTimeout() {
diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
index 30d3edd..05a8692 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
+++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
@@ -56,50 +56,6 @@
static constexpr nsecs_t MARGIN_FOR_PERIOD_CALCULATION =
std::chrono::nanoseconds(800us).count();
- class RefreshRate {
- private:
- // Effectively making the constructor private while allowing
- // std::make_unique to create the object
- struct ConstructorTag {
- explicit ConstructorTag(int) {}
- };
-
- public:
- RefreshRate(DisplayModePtr mode, ConstructorTag) : mode(mode) {}
-
- DisplayModeId getModeId() const { return mode->getId(); }
- nsecs_t getVsyncPeriod() const { return mode->getVsyncPeriod(); }
- int32_t getModeGroup() const { return mode->getGroup(); }
- std::string getName() const { return to_string(getFps()); }
- Fps getFps() const { return mode->getFps(); }
- DisplayModePtr getMode() const { return mode; }
-
- // Checks whether the fps of this RefreshRate struct is within a given min and max refresh
- // rate passed in. Margin of error is applied to the boundaries for approximation.
- bool inPolicy(Fps minRefreshRate, Fps maxRefreshRate) const;
-
- bool operator==(const RefreshRate& other) const { return mode == other.mode; }
- bool operator!=(const RefreshRate& other) const { return !operator==(other); }
-
- bool operator<(const RefreshRate& other) const {
- return isStrictlyLess(getFps(), other.getFps());
- }
-
- std::string toString() const;
- friend std::ostream& operator<<(std::ostream& os, const RefreshRate& refreshRate) {
- return os << refreshRate.toString();
- }
-
- private:
- friend RefreshRateConfigs;
- friend class RefreshRateConfigsTest;
-
- DisplayModePtr mode;
- };
-
- using AllRefreshRatesMapType =
- std::unordered_map<DisplayModeId, std::unique_ptr<const RefreshRate>>;
-
struct Policy {
private:
static constexpr int kAllowGroupSwitchingDefault = false;
@@ -236,12 +192,12 @@
// Returns the refresh rate that best fits the given layers, and whether the refresh rate was
// chosen based on touch boost and/or idle timer.
- std::pair<RefreshRate, GlobalSignals> getBestRefreshRate(const std::vector<LayerRequirement>&,
- GlobalSignals) const EXCLUDES(mLock);
+ std::pair<DisplayModePtr, GlobalSignals> getBestRefreshRate(
+ const std::vector<LayerRequirement>&, GlobalSignals) const EXCLUDES(mLock);
FpsRange getSupportedRefreshRateRange() const EXCLUDES(mLock) {
std::lock_guard lock(mLock);
- return {mMinSupportedRefreshRate->getFps(), mMaxSupportedRefreshRate->getFps()};
+ return {mMinRefreshRateModeIt->second->getFps(), mMaxRefreshRateModeIt->second->getFps()};
}
std::optional<Fps> onKernelTimerChanged(std::optional<DisplayModeId> desiredActiveModeId,
@@ -249,30 +205,15 @@
// Returns the highest refresh rate according to the current policy. May change at runtime. Only
// uses the primary range, not the app request range.
- RefreshRate getMaxRefreshRateByPolicy() const EXCLUDES(mLock);
+ DisplayModePtr getMaxRefreshRateByPolicy() const EXCLUDES(mLock);
- // Returns the current refresh rate
- RefreshRate getCurrentRefreshRate() const EXCLUDES(mLock);
-
- // Returns the current refresh rate, if allowed. Otherwise the default that is allowed by
- // the policy.
- RefreshRate getCurrentRefreshRateByPolicy() const;
-
- // Returns the refresh rate that corresponds to a DisplayModeId. This may change at
- // runtime.
- // TODO(b/159590486) An invalid mode id may be given here if the dipslay modes have changed.
- RefreshRate getRefreshRateFromModeId(DisplayModeId modeId) const EXCLUDES(mLock) {
- std::lock_guard lock(mLock);
- return *mRefreshRates.at(modeId);
- };
-
- // Stores the current modeId the device operates at
- void setCurrentModeId(DisplayModeId) EXCLUDES(mLock);
+ void setActiveModeId(DisplayModeId) EXCLUDES(mLock);
+ DisplayModePtr getActiveMode() const EXCLUDES(mLock);
// Returns a known frame rate that is the closest to frameRate
Fps findClosestKnownFrameRate(Fps frameRate) const;
- enum class KernelIdleTimerController { Sysprop, HwcApi };
+ enum class KernelIdleTimerController { Sysprop, HwcApi, ftl_last = HwcApi };
// Configuration flags.
struct Config {
@@ -291,7 +232,7 @@
std::optional<KernelIdleTimerController> kernelIdleTimerController;
};
- RefreshRateConfigs(const DisplayModes&, DisplayModeId,
+ RefreshRateConfigs(DisplayModes, DisplayModeId activeModeId,
Config config = {.enableFrameRateOverride = false,
.frameRateMultipleThreshold = 0,
.idleTimerTimeout = 0ms,
@@ -305,7 +246,7 @@
// differ in resolution.
bool canSwitch() const EXCLUDES(mLock) {
std::lock_guard lock(mLock);
- return mRefreshRates.size() > 1;
+ return mDisplayModes.size() > 1;
}
// Class to enumerate options around toggling the kernel timer on and off.
@@ -323,7 +264,7 @@
// Return the display refresh rate divisor to match the layer
// frame rate, or 0 if the display refresh rate is not a multiple of the
// layer refresh rate.
- static int getFrameRateDivisor(Fps displayFrameRate, Fps layerFrameRate);
+ static int getFrameRateDivisor(Fps displayRefreshRate, Fps layerFrameRate);
// Returns if the provided frame rates have a ratio t*1000/1001 or t*1001/1000
// for an integer t.
@@ -391,54 +332,39 @@
void constructAvailableRefreshRates() REQUIRES(mLock);
- void getSortedRefreshRateListLocked(
- const std::function<bool(const RefreshRate&)>& shouldAddRefreshRate,
- std::vector<const RefreshRate*>* outRefreshRates) REQUIRES(mLock);
-
- std::pair<RefreshRate, GlobalSignals> getBestRefreshRateLocked(
+ std::pair<DisplayModePtr, GlobalSignals> getBestRefreshRateLocked(
const std::vector<LayerRequirement>&, GlobalSignals) const REQUIRES(mLock);
- // Returns the refresh rate with the highest score in the collection specified from begin
- // to end. If there are more than one with the same highest refresh rate, the first one is
- // returned.
- template <typename Iter>
- const RefreshRate* getBestRefreshRate(Iter begin, Iter end) const;
-
// Returns number of display frames and remainder when dividing the layer refresh period by
// display refresh period.
std::pair<nsecs_t, nsecs_t> getDisplayFrames(nsecs_t layerPeriod, nsecs_t displayPeriod) const;
// Returns the lowest refresh rate according to the current policy. May change at runtime. Only
// uses the primary range, not the app request range.
- const RefreshRate& getMinRefreshRateByPolicyLocked() const REQUIRES(mLock);
+ const DisplayModePtr& getMinRefreshRateByPolicyLocked() const REQUIRES(mLock);
// Returns the highest refresh rate according to the current policy. May change at runtime. Only
// uses the primary range, not the app request range.
- const RefreshRate& getMaxRefreshRateByPolicyLocked() const REQUIRES(mLock) {
- return getMaxRefreshRateByPolicyLocked(mCurrentRefreshRate->getModeGroup());
+ const DisplayModePtr& getMaxRefreshRateByPolicyLocked(int anchorGroup) const REQUIRES(mLock);
+ const DisplayModePtr& getMaxRefreshRateByPolicyLocked() const REQUIRES(mLock) {
+ return getMaxRefreshRateByPolicyLocked(mActiveModeIt->second->getGroup());
}
- const RefreshRate& getMaxRefreshRateByPolicyLocked(int anchorGroup) const REQUIRES(mLock);
-
- // Returns the current refresh rate, if allowed. Otherwise the default that is allowed by
- // the policy.
- const RefreshRate& getCurrentRefreshRateByPolicyLocked() const REQUIRES(mLock);
-
const Policy* getCurrentPolicyLocked() const REQUIRES(mLock);
bool isPolicyValidLocked(const Policy& policy) const REQUIRES(mLock);
// Returns whether the layer is allowed to vote for the given refresh rate.
- bool isVoteAllowed(const LayerRequirement&, const RefreshRate&) const;
+ bool isVoteAllowed(const LayerRequirement&, Fps) const;
// calculates a score for a layer. Used to determine the display refresh rate
// and the frame rate override for certains applications.
- float calculateLayerScoreLocked(const LayerRequirement&, const RefreshRate&,
+ float calculateLayerScoreLocked(const LayerRequirement&, Fps refreshRate,
bool isSeamlessSwitch) const REQUIRES(mLock);
- float calculateNonExactMatchingLayerScoreLocked(const LayerRequirement&,
- const RefreshRate&) const REQUIRES(mLock);
+ float calculateNonExactMatchingLayerScoreLocked(const LayerRequirement&, Fps refreshRate) const
+ REQUIRES(mLock);
- void updateDisplayModes(const DisplayModes& mode, DisplayModeId currentModeId) EXCLUDES(mLock);
+ void updateDisplayModes(DisplayModes, DisplayModeId activeModeId) EXCLUDES(mLock);
void initializeIdleTimer();
@@ -449,32 +375,22 @@
: mIdleTimerCallbacks->platform;
}
- // The list of refresh rates, indexed by display modes ID. This may change after this
- // object is initialized.
- AllRefreshRatesMapType mRefreshRates GUARDED_BY(mLock);
+ // The display modes of the active display. The DisplayModeIterators below are pointers into
+ // this container, so must be invalidated whenever the DisplayModes change. The Policy below
+ // is also dependent, so must be reset as well.
+ DisplayModes mDisplayModes GUARDED_BY(mLock);
- // The list of refresh rates in the primary range of the current policy, ordered by vsyncPeriod
- // (the first element is the lowest refresh rate).
- std::vector<const RefreshRate*> mPrimaryRefreshRates GUARDED_BY(mLock);
+ DisplayModeIterator mActiveModeIt GUARDED_BY(mLock);
+ DisplayModeIterator mMinRefreshRateModeIt GUARDED_BY(mLock);
+ DisplayModeIterator mMaxRefreshRateModeIt GUARDED_BY(mLock);
- // The list of refresh rates in the app request range of the current policy, ordered by
- // vsyncPeriod (the first element is the lowest refresh rate).
- std::vector<const RefreshRate*> mAppRequestRefreshRates GUARDED_BY(mLock);
+ // Display modes that satisfy the Policy's ranges, filtered and sorted by refresh rate.
+ std::vector<DisplayModeIterator> mPrimaryRefreshRates GUARDED_BY(mLock);
+ std::vector<DisplayModeIterator> mAppRequestRefreshRates GUARDED_BY(mLock);
- // The current display mode. This will change at runtime. This is set by SurfaceFlinger on
- // the main thread, and read by the Scheduler (and other objects) on other threads.
- const RefreshRate* mCurrentRefreshRate GUARDED_BY(mLock);
-
- // The policy values will change at runtime. They're set by SurfaceFlinger on the main thread,
- // and read by the Scheduler (and other objects) on other threads.
Policy mDisplayManagerPolicy GUARDED_BY(mLock);
std::optional<Policy> mOverridePolicy GUARDED_BY(mLock);
- // The min and max refresh rates supported by the device.
- // This may change at runtime.
- const RefreshRate* mMinSupportedRefreshRate GUARDED_BY(mLock);
- const RefreshRate* mMaxSupportedRefreshRate GUARDED_BY(mLock);
-
mutable std::mutex mLock;
// A sorted list of known frame rates that a Heuristic layer will choose
@@ -486,7 +402,7 @@
struct GetBestRefreshRateCache {
std::pair<std::vector<LayerRequirement>, GlobalSignals> arguments;
- std::pair<RefreshRate, GlobalSignals> result;
+ std::pair<DisplayModePtr, GlobalSignals> result;
};
mutable std::optional<GetBestRefreshRateCache> mGetBestRefreshRateCache GUARDED_BY(mLock);
diff --git a/services/surfaceflinger/Scheduler/RefreshRateStats.h b/services/surfaceflinger/Scheduler/RefreshRateStats.h
index f1ad755..ed65bc6 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateStats.h
+++ b/services/surfaceflinger/Scheduler/RefreshRateStats.h
@@ -17,7 +17,9 @@
#pragma once
#include <chrono>
-#include <numeric>
+#include <cinttypes>
+#include <cstdlib>
+#include <string>
#include <android-base/stringprintf.h>
#include <ftl/small_map.h>
@@ -25,6 +27,7 @@
#include <scheduler/Fps.h>
+#include "DisplayHardware/Hal.h"
#include "TimeStats/TimeStats.h"
namespace android::scheduler {
@@ -41,16 +44,16 @@
static constexpr int64_t MS_PER_HOUR = 60 * MS_PER_MIN;
static constexpr int64_t MS_PER_DAY = 24 * MS_PER_HOUR;
+ using PowerMode = android::hardware::graphics::composer::hal::PowerMode;
+
public:
// TODO(b/185535769): Inject clock to avoid sleeping in tests.
- RefreshRateStats(TimeStats& timeStats, Fps currentRefreshRate,
- android::hardware::graphics::composer::hal::PowerMode currentPowerMode)
+ RefreshRateStats(TimeStats& timeStats, Fps currentRefreshRate, PowerMode currentPowerMode)
: mTimeStats(timeStats),
mCurrentRefreshRate(currentRefreshRate),
mCurrentPowerMode(currentPowerMode) {}
- // Sets power mode.
- void setPowerMode(android::hardware::graphics::composer::hal::PowerMode mode) {
+ void setPowerMode(PowerMode mode) {
if (mCurrentPowerMode == mode) {
return;
}
@@ -115,7 +118,7 @@
uint32_t fps = 0;
- if (mCurrentPowerMode == android::hardware::graphics::composer::hal::PowerMode::ON) {
+ if (mCurrentPowerMode == PowerMode::ON) {
// Normal power mode is counted under different config modes.
const auto total = std::as_const(mFpsTotalTimes)
.get(mCurrentRefreshRate)
@@ -144,7 +147,7 @@
TimeStats& mTimeStats;
Fps mCurrentRefreshRate;
- android::hardware::graphics::composer::hal::PowerMode mCurrentPowerMode;
+ PowerMode mCurrentPowerMode;
ftl::SmallMap<Fps, std::chrono::milliseconds, 2, FpsApproxEqual> mFpsTotalTimes;
std::chrono::milliseconds mScreenOffTime = std::chrono::milliseconds::zero();
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index 1fa455a..74d7739 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -166,18 +166,15 @@
impl::EventThread::GetVsyncPeriodFunction Scheduler::makeGetVsyncPeriodFunction() const {
return [this](uid_t uid) {
- const auto refreshRateConfigs = holdRefreshRateConfigs();
- nsecs_t basePeriod = refreshRateConfigs->getCurrentRefreshRate().getVsyncPeriod();
+ const Fps refreshRate = holdRefreshRateConfigs()->getActiveMode()->getFps();
+ const nsecs_t basePeriod = refreshRate.getPeriodNsecs();
+
const auto frameRate = getFrameRateOverride(uid);
if (!frameRate.has_value()) {
return basePeriod;
}
- const auto divisor =
- scheduler::RefreshRateConfigs::getFrameRateDivisor(refreshRateConfigs
- ->getCurrentRefreshRate()
- .getFps(),
- *frameRate);
+ const auto divisor = RefreshRateConfigs::getFrameRateDivisor(refreshRate, *frameRate);
if (divisor <= 1) {
return basePeriod;
}
@@ -307,7 +304,7 @@
// mode change is in progress. In that case we shouldn't dispatch an event
// as it will be dispatched when the current mode changes.
if (std::scoped_lock lock(mRefreshRateConfigsLock);
- mRefreshRateConfigs->getCurrentRefreshRate().getMode() != mPolicy.mode) {
+ mRefreshRateConfigs->getActiveMode() != mPolicy.mode) {
return;
}
@@ -422,7 +419,7 @@
}
}
-void Scheduler::resyncToHardwareVsync(bool makeAvailable, nsecs_t period) {
+void Scheduler::resyncToHardwareVsync(bool makeAvailable, Fps refreshRate) {
{
std::lock_guard<std::mutex> lock(mHWVsyncLock);
if (makeAvailable) {
@@ -434,11 +431,7 @@
}
}
- if (period <= 0) {
- return;
- }
-
- setVsyncPeriod(period);
+ setVsyncPeriod(refreshRate.getPeriodNsecs());
}
void Scheduler::resync() {
@@ -448,15 +441,17 @@
const nsecs_t last = mLastResyncTime.exchange(now);
if (now - last > kIgnoreDelay) {
- const auto vsyncPeriod = [&] {
+ const auto refreshRate = [&] {
std::scoped_lock lock(mRefreshRateConfigsLock);
- return mRefreshRateConfigs->getCurrentRefreshRate().getVsyncPeriod();
+ return mRefreshRateConfigs->getActiveMode()->getFps();
}();
- resyncToHardwareVsync(false, vsyncPeriod);
+ resyncToHardwareVsync(false, refreshRate);
}
}
void Scheduler::setVsyncPeriod(nsecs_t period) {
+ if (period <= 0) return;
+
std::lock_guard<std::mutex> lock(mHWVsyncLock);
mVsyncSchedule->getController().startPeriodTransition(period);
@@ -578,21 +573,20 @@
// TODO(145561154): cleanup the kernel idle timer implementation and the refresh rate
// magic number
- const auto refreshRate = [&] {
+ const Fps refreshRate = [&] {
std::scoped_lock lock(mRefreshRateConfigsLock);
- return mRefreshRateConfigs->getCurrentRefreshRate();
+ return mRefreshRateConfigs->getActiveMode()->getFps();
}();
constexpr Fps FPS_THRESHOLD_FOR_KERNEL_TIMER = 65_Hz;
using namespace fps_approx_ops;
- if (state == TimerState::Reset && refreshRate.getFps() > FPS_THRESHOLD_FOR_KERNEL_TIMER) {
+ if (state == TimerState::Reset && refreshRate > FPS_THRESHOLD_FOR_KERNEL_TIMER) {
// If we're not in performance mode then the kernel timer shouldn't do
// anything, as the refresh rate during DPU power collapse will be the
// same.
- resyncToHardwareVsync(true /* makeAvailable */, refreshRate.getVsyncPeriod());
- } else if (state == TimerState::Expired &&
- refreshRate.getFps() <= FPS_THRESHOLD_FOR_KERNEL_TIMER) {
+ resyncToHardwareVsync(true /* makeAvailable */, refreshRate);
+ } else if (state == TimerState::Expired && refreshRate <= FPS_THRESHOLD_FOR_KERNEL_TIMER) {
// Disable HW VSYNC if the timer expired, as we don't need it enabled if
// we're not pushing frames, and if we're in PERFORMANCE mode then we'll
// need to update the VsyncController model anyway.
@@ -693,11 +687,9 @@
}
}
if (refreshRateChanged) {
- const auto newRefreshRate = refreshRateConfigs->getRefreshRateFromModeId(newMode->getId());
-
- mSchedulerCallback.changeRefreshRate(newRefreshRate,
- consideredSignals.idle ? DisplayModeEvent::None
- : DisplayModeEvent::Changed);
+ mSchedulerCallback.requestDisplayMode(std::move(newMode),
+ consideredSignals.idle ? DisplayModeEvent::None
+ : DisplayModeEvent::Changed);
}
if (frameRateOverridesChanged) {
mSchedulerCallback.triggerOnFrameRateOverridesChanged();
@@ -715,16 +707,13 @@
if (mDisplayPowerTimer &&
(!mPolicy.isDisplayPowerStateNormal || mPolicy.displayPowerTimer == TimerState::Reset)) {
constexpr GlobalSignals kNoSignals;
- return {configs->getMaxRefreshRateByPolicy().getMode(), kNoSignals};
+ return {configs->getMaxRefreshRateByPolicy(), kNoSignals};
}
const GlobalSignals signals{.touch = mTouchTimer && mPolicy.touch == TouchState::Active,
.idle = mPolicy.idleTimer == TimerState::Expired};
- const auto [refreshRate, consideredSignals] =
- configs->getBestRefreshRate(mPolicy.contentRequirements, signals);
-
- return {refreshRate.getMode(), consideredSignals};
+ return configs->getBestRefreshRate(mPolicy.contentRequirements, signals);
}
DisplayModePtr Scheduler::getPreferredDisplayMode() {
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index f6c81c0..a8113d4 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -86,12 +86,11 @@
// Indicates frame activity, i.e. whether commit and/or composite is taking place.
enum class FrameHint { kNone, kActive };
- using RefreshRate = RefreshRateConfigs::RefreshRate;
using DisplayModeEvent = scheduler::DisplayModeEvent;
virtual void scheduleComposite(FrameHint) = 0;
virtual void setVsyncEnabled(bool) = 0;
- virtual void changeRefreshRate(const RefreshRate&, DisplayModeEvent) = 0;
+ virtual void requestDisplayMode(DisplayModePtr, DisplayModeEvent) = 0;
virtual void kernelTimerChanged(bool expired) = 0;
virtual void triggerOnFrameRateOverridesChanged() = 0;
@@ -166,8 +165,7 @@
// If makeAvailable is true, then hardware vsync will be turned on.
// Otherwise, if hardware vsync is not already enabled then this method will
// no-op.
- // The period is the vsync period from the current display configuration.
- void resyncToHardwareVsync(bool makeAvailable, nsecs_t period);
+ void resyncToHardwareVsync(bool makeAvailable, Fps refreshRate);
void resync() EXCLUDES(mRefreshRateConfigsLock);
void forceNextResync() { mLastResyncTime = 0; }
@@ -236,7 +234,7 @@
nsecs_t getVsyncPeriodFromRefreshRateConfigs() const EXCLUDES(mRefreshRateConfigsLock) {
std::scoped_lock lock(mRefreshRateConfigsLock);
- return mRefreshRateConfigs->getCurrentRefreshRate().getVsyncPeriod();
+ return mRefreshRateConfigs->getActiveMode()->getFps().getPeriodNsecs();
}
// Returns the framerate of the layer with the given sequence ID
diff --git a/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.h b/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.h
index 3186d6d..4923031 100644
--- a/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.h
+++ b/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.h
@@ -29,6 +29,7 @@
namespace android::scheduler {
+class TimeKeeper;
class VSyncTracker;
// VSyncDispatchTimerQueueEntry is a helper class representing internal state for each entry in
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 94b16b4..0ee3121 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1044,15 +1044,13 @@
const auto& supportedModes = display->getSupportedModes();
info->supportedDisplayModes.clear();
info->supportedDisplayModes.reserve(supportedModes.size());
- for (const auto& mode : supportedModes) {
+
+ for (const auto& [id, mode] : supportedModes) {
ui::DisplayMode outMode;
- outMode.id = static_cast<int32_t>(mode->getId().value());
+ outMode.id = static_cast<int32_t>(id.value());
- auto width = mode->getWidth();
- auto height = mode->getHeight();
-
- auto xDpi = mode->getDpiX();
- auto yDpi = mode->getDpiY();
+ auto [width, height] = mode->getResolution();
+ auto [xDpi, yDpi] = mode->getDpi();
if (display->isPrimary() &&
(internalDisplayOrientation == ui::ROTATION_90 ||
@@ -1146,7 +1144,7 @@
// Start receiving vsync samples now, so that we can detect a period
// switch.
- mScheduler->resyncToHardwareVsync(true, info.mode->getVsyncPeriod());
+ mScheduler->resyncToHardwareVsync(true, info.mode->getFps());
// As we called to set period, we will call to onRefreshRateChangeCompleted once
// VsyncController model is locked.
modulateVsync(&VsyncModulator::onRefreshRateChangeInitiated);
@@ -1212,7 +1210,7 @@
return;
}
- if (display->getActiveMode()->getSize() != upcomingModeInfo.mode->getSize()) {
+ if (display->getActiveMode()->getResolution() != upcomingModeInfo.mode->getResolution()) {
auto& state = mCurrentState.displays.editValueFor(display->getDisplayToken());
// We need to generate new sequenceId in order to recreate the display (and this
// way the framebuffer).
@@ -1248,7 +1246,7 @@
void SurfaceFlinger::desiredActiveModeChangeDone(const sp<DisplayDevice>& display) {
const auto refreshRate = display->getDesiredActiveMode()->mode->getFps();
clearDesiredActiveModeState(display);
- mScheduler->resyncToHardwareVsync(true, refreshRate.getPeriodNsecs());
+ mScheduler->resyncToHardwareVsync(true, refreshRate);
updatePhaseConfiguration(refreshRate);
}
@@ -2680,11 +2678,11 @@
mDebugInTransaction = 0;
}
-void SurfaceFlinger::loadDisplayModes(PhysicalDisplayId displayId, DisplayModes& outModes,
- DisplayModePtr& outActiveMode) const {
+std::pair<DisplayModes, DisplayModePtr> SurfaceFlinger::loadDisplayModes(
+ PhysicalDisplayId displayId) const {
std::vector<HWComposer::HWCDisplayMode> hwcModes;
std::optional<hal::HWDisplayId> activeModeHwcId;
- bool activeModeIsSupported;
+
int attempt = 0;
constexpr int kMaxAttempts = 3;
do {
@@ -2692,63 +2690,60 @@
activeModeHwcId = getHwComposer().getActiveMode(displayId);
LOG_ALWAYS_FATAL_IF(!activeModeHwcId, "HWC returned no active mode");
- activeModeIsSupported =
- std::any_of(hwcModes.begin(), hwcModes.end(),
- [activeModeHwcId](const HWComposer::HWCDisplayMode& mode) {
- return mode.hwcId == *activeModeHwcId;
- });
- } while (!activeModeIsSupported && ++attempt < kMaxAttempts);
- LOG_ALWAYS_FATAL_IF(!activeModeIsSupported,
+ const auto isActiveMode = [activeModeHwcId](const HWComposer::HWCDisplayMode& mode) {
+ return mode.hwcId == *activeModeHwcId;
+ };
+
+ if (std::any_of(hwcModes.begin(), hwcModes.end(), isActiveMode)) {
+ break;
+ }
+ } while (++attempt < kMaxAttempts);
+
+ LOG_ALWAYS_FATAL_IF(attempt == kMaxAttempts,
"After %d attempts HWC still returns an active mode which is not"
- " supported. Active mode ID = %" PRIu64 " . Supported modes = %s",
+ " supported. Active mode ID = %" PRIu64 ". Supported modes = %s",
kMaxAttempts, *activeModeHwcId, base::Join(hwcModes, ", ").c_str());
DisplayModes oldModes;
-
if (const auto token = getPhysicalDisplayTokenLocked(displayId)) {
oldModes = getDisplayDeviceLocked(token)->getSupportedModes();
}
- int largestUsedModeId = -1; // Use int instead of DisplayModeId for signedness
- for (const auto& mode : oldModes) {
- const auto id = static_cast<int>(mode->getId().value());
- if (id > largestUsedModeId) {
- largestUsedModeId = id;
- }
- }
+ ui::DisplayModeId nextModeId = 1 +
+ std::accumulate(oldModes.begin(), oldModes.end(), static_cast<ui::DisplayModeId>(-1),
+ [](ui::DisplayModeId max, const auto& pair) {
+ return std::max(max, pair.first.value());
+ });
DisplayModes newModes;
- int32_t nextModeId = largestUsedModeId + 1;
for (const auto& hwcMode : hwcModes) {
- newModes.push_back(DisplayMode::Builder(hwcMode.hwcId)
- .setId(DisplayModeId{nextModeId++})
- .setPhysicalDisplayId(displayId)
- .setWidth(hwcMode.width)
- .setHeight(hwcMode.height)
- .setVsyncPeriod(hwcMode.vsyncPeriod)
- .setDpiX(hwcMode.dpiX)
- .setDpiY(hwcMode.dpiY)
- .setGroup(hwcMode.configGroup)
- .build());
+ const DisplayModeId id{nextModeId++};
+ newModes.try_emplace(id,
+ DisplayMode::Builder(hwcMode.hwcId)
+ .setId(id)
+ .setPhysicalDisplayId(displayId)
+ .setResolution({hwcMode.width, hwcMode.height})
+ .setVsyncPeriod(hwcMode.vsyncPeriod)
+ .setDpiX(hwcMode.dpiX)
+ .setDpiY(hwcMode.dpiY)
+ .setGroup(hwcMode.configGroup)
+ .build());
}
- const bool modesAreSame =
+ const bool sameModes =
std::equal(newModes.begin(), newModes.end(), oldModes.begin(), oldModes.end(),
- [](DisplayModePtr left, DisplayModePtr right) {
- return left->equalsExceptDisplayModeId(right);
+ [](const auto& lhs, const auto& rhs) {
+ return equalsExceptDisplayModeId(*lhs.second, *rhs.second);
});
- if (modesAreSame) {
- // The supported modes have not changed, keep the old IDs.
- outModes = oldModes;
- } else {
- outModes = newModes;
- }
+ // Keep IDs if modes have not changed.
+ const auto& modes = sameModes ? oldModes : newModes;
+ const DisplayModePtr activeMode =
+ std::find_if(modes.begin(), modes.end(), [activeModeHwcId](const auto& pair) {
+ return pair.second->getHwcId() == activeModeHwcId;
+ })->second;
- outActiveMode = *std::find_if(outModes.begin(), outModes.end(),
- [activeModeHwcId](const DisplayModePtr& mode) {
- return mode->getHwcId() == *activeModeHwcId;
- });
+ return {modes, activeMode};
}
void SurfaceFlinger::processDisplayHotplugEventsLocked() {
@@ -2764,9 +2759,7 @@
const auto it = mPhysicalDisplayTokens.find(displayId);
if (event.connection == hal::Connection::CONNECTED) {
- DisplayModes supportedModes;
- DisplayModePtr activeMode;
- loadDisplayModes(displayId, supportedModes, activeMode);
+ auto [supportedModes, activeMode] = loadDisplayModes(displayId);
if (it == mPhysicalDisplayTokens.end()) {
ALOGV("Creating display %s", to_string(displayId).c_str());
@@ -2777,7 +2770,7 @@
.hwcDisplayId = event.hwcDisplayId,
.deviceProductInfo = std::move(info->deviceProductInfo),
.supportedModes = std::move(supportedModes),
- .activeMode = activeMode};
+ .activeMode = std::move(activeMode)};
state.isSecure = true; // All physical displays are currently considered secure.
state.displayName = std::move(info->name);
@@ -2792,7 +2785,7 @@
auto& state = mCurrentState.displays.editValueFor(token);
state.sequenceId = DisplayDeviceState{}.sequenceId; // Generate new sequenceId
state.physical->supportedModes = std::move(supportedModes);
- state.physical->activeMode = activeMode;
+ state.physical->activeMode = std::move(activeMode);
if (getHwComposer().updatesDeviceProductInfoOnHotplugReconnect()) {
state.physical->deviceProductInfo = std::move(info->deviceProductInfo);
}
@@ -2925,7 +2918,7 @@
ui::Size resolution(0, 0);
ui::PixelFormat pixelFormat = static_cast<ui::PixelFormat>(PIXEL_FORMAT_UNKNOWN);
if (state.physical) {
- resolution = state.physical->activeMode->getSize();
+ resolution = state.physical->activeMode->getResolution();
pixelFormat = static_cast<ui::PixelFormat>(PIXEL_FORMAT_RGBA_8888);
} else if (state.surface != nullptr) {
int status = state.surface->query(NATIVE_WINDOW_WIDTH, &resolution.width);
@@ -2979,7 +2972,7 @@
LOG_FATAL_IF(!displayId);
displaySurface =
sp<FramebufferSurface>::make(getHwComposer(), *displayId, bqConsumer,
- state.physical->activeMode->getSize(),
+ state.physical->activeMode->getResolution(),
ui::Size(maxGraphicsWidth, maxGraphicsHeight));
producer = bqProducer;
}
@@ -3092,7 +3085,7 @@
}
void SurfaceFlinger::updateInternalDisplayVsyncLocked(const sp<DisplayDevice>& activeDisplay) {
mVsyncConfiguration->reset();
- const Fps refreshRate = activeDisplay->refreshRateConfigs().getCurrentRefreshRate().getFps();
+ const Fps refreshRate = activeDisplay->refreshRateConfigs().getActiveMode()->getFps();
updatePhaseConfiguration(refreshRate);
mRefreshRateStats->setRefreshRate(refreshRate);
}
@@ -3354,7 +3347,7 @@
mCompositionEngine->updateCursorAsync(refreshArgs);
}
-void SurfaceFlinger::changeRefreshRate(const RefreshRate& refreshRate, DisplayModeEvent event) {
+void SurfaceFlinger::requestDisplayMode(DisplayModePtr mode, DisplayModeEvent event) {
// If this is called from the main thread mStateLock must be locked before
// Currently the only way to call this function from the main thread is from
// Scheduler::chooseRefreshRateForContent
@@ -3367,14 +3360,12 @@
}
ATRACE_CALL();
- // Don't do any updating if the current fps is the same as the new one.
- if (!display->refreshRateConfigs().isModeAllowed(refreshRate.getModeId())) {
- ALOGV("Skipping mode %d as it is not part of allowed modes",
- refreshRate.getModeId().value());
+ if (!display->refreshRateConfigs().isModeAllowed(mode->getId())) {
+ ALOGV("Skipping disallowed mode %d", mode->getId().value());
return;
}
- setDesiredActiveMode({refreshRate.getMode(), event});
+ setDesiredActiveMode({std::move(mode), event});
}
void SurfaceFlinger::triggerOnFrameRateOverridesChanged() {
@@ -4802,8 +4793,7 @@
{}, mPid, getuid(), transactionId);
setPowerModeInternal(display, hal::PowerMode::ON);
- const nsecs_t vsyncPeriod =
- display->refreshRateConfigs().getCurrentRefreshRate().getVsyncPeriod();
+ const nsecs_t vsyncPeriod = display->refreshRateConfigs().getActiveMode()->getVsyncPeriod();
mAnimFrameTracker.setDisplayRefreshPeriod(vsyncPeriod);
mActiveDisplayTransformHint = display->getTransformHint();
// Use phase of 0 since phase is not known.
@@ -4842,7 +4832,7 @@
if (mInterceptor->isEnabled()) {
mInterceptor->savePowerModeUpdate(display->getSequenceId(), static_cast<int32_t>(mode));
}
- const auto vsyncPeriod = display->refreshRateConfigs().getCurrentRefreshRate().getVsyncPeriod();
+ const auto refreshRate = display->refreshRateConfigs().getActiveMode()->getFps();
if (currentMode == hal::PowerMode::OFF) {
// Turn on the display
if (display->isInternal() && (!activeDisplay || !activeDisplay->isPoweredOn())) {
@@ -4860,7 +4850,7 @@
if (isDisplayActiveLocked(display) && mode != hal::PowerMode::DOZE_SUSPEND) {
setHWCVsyncEnabled(displayId, mHWCVsyncPendingState);
mScheduler->onScreenAcquired(mAppConnectionHandle);
- mScheduler->resyncToHardwareVsync(true, vsyncPeriod);
+ mScheduler->resyncToHardwareVsync(true, refreshRate);
}
mVisibleRegionsDirty = true;
@@ -4890,7 +4880,7 @@
getHwComposer().setPowerMode(displayId, mode);
if (isDisplayActiveLocked(display) && currentMode == hal::PowerMode::DOZE_SUSPEND) {
mScheduler->onScreenAcquired(mAppConnectionHandle);
- mScheduler->resyncToHardwareVsync(true, vsyncPeriod);
+ mScheduler->resyncToHardwareVsync(true, refreshRate);
}
} else if (mode == hal::PowerMode::DOZE_SUSPEND) {
// Leave display going to doze
@@ -5376,8 +5366,10 @@
std::string fps, xDpi, yDpi;
if (const auto activeMode = display->getActiveMode()) {
fps = to_string(activeMode->getFps());
- xDpi = base::StringPrintf("%.2f", activeMode->getDpiX());
- yDpi = base::StringPrintf("%.2f", activeMode->getDpiY());
+
+ const auto dpi = activeMode->getDpi();
+ xDpi = base::StringPrintf("%.2f", dpi.x);
+ yDpi = base::StringPrintf("%.2f", dpi.y);
} else {
fps = "unknown";
xDpi = "unknown";
@@ -6137,7 +6129,7 @@
if (!updateOverlay) return;
// Update the overlay on the main thread to avoid race conditions with
- // mRefreshRateConfigs->getCurrentRefreshRate()
+ // mRefreshRateConfigs->getActiveMode()
static_cast<void>(mScheduler->schedule([=] {
const auto display = ON_MAIN_THREAD(getDefaultDisplayDeviceLocked());
if (!display) {
@@ -7181,7 +7173,7 @@
refreshRate = *frameRateOverride;
} else if (!getHwComposer().isHeadless()) {
if (const auto display = ON_MAIN_THREAD(getDefaultDisplayDeviceLocked())) {
- refreshRate = display->refreshRateConfigs().getCurrentRefreshRate().getFps();
+ refreshRate = display->refreshRateConfigs().getActiveMode()->getFps();
}
}
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index fa65803..01732be 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -679,8 +679,8 @@
// Toggles hardware VSYNC by calling into HWC.
void setVsyncEnabled(bool) override;
- // Initiates a refresh rate change to be applied on commit.
- void changeRefreshRate(const RefreshRate&, DisplayModeEvent) override;
+ // Sets the desired display mode if allowed by policy.
+ void requestDisplayMode(DisplayModePtr, DisplayModeEvent) override;
// Called when kernel idle timer has expired. Used to update the refresh rate overlay.
void kernelTimerChanged(bool expired) override;
// Called when the frame rate override list changed to trigger an event.
@@ -975,8 +975,9 @@
/*
* Display management
*/
- void loadDisplayModes(PhysicalDisplayId displayId, DisplayModes& outModes,
- DisplayModePtr& outActiveMode) const REQUIRES(mStateLock);
+ std::pair<DisplayModes, DisplayModePtr> loadDisplayModes(PhysicalDisplayId) const
+ REQUIRES(mStateLock);
+
sp<DisplayDevice> setupNewDisplayDeviceInternal(
const wp<IBinder>& displayToken,
std::shared_ptr<compositionengine::Display> compositionDisplay,
diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h
index b796dfe..93abc9f 100644
--- a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h
+++ b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h
@@ -55,6 +55,7 @@
#include "renderengine/mock/RenderEngine.h"
#include "scheduler/TimeKeeper.h"
#include "tests/unittests/mock/DisplayHardware/MockComposer.h"
+#include "tests/unittests/mock/DisplayHardware/MockDisplayMode.h"
#include "tests/unittests/mock/DisplayHardware/MockHWC2.h"
#include "tests/unittests/mock/DisplayHardware/MockPowerAdvisor.h"
#include "tests/unittests/mock/MockEventThread.h"
@@ -207,7 +208,9 @@
void setRefreshRateFps(Fps) override {}
void dump(std::string &) const override {}
};
+
namespace scheduler {
+
class TestableScheduler : public Scheduler, private ICompositor {
public:
TestableScheduler(const std::shared_ptr<scheduler::RefreshRateConfigs> &refreshRateConfigs,
@@ -216,9 +219,6 @@
std::make_unique<android::mock::VSyncTracker>(), refreshRateConfigs,
callback) {}
- void scheduleFrame(){};
- void postMessage(sp<MessageHandler> &&){};
-
TestableScheduler(std::unique_ptr<VsyncController> controller,
std::unique_ptr<VSyncTracker> tracker,
std::shared_ptr<RefreshRateConfigs> configs, ISchedulerCallback &callback)
@@ -273,8 +273,13 @@
bool commit(nsecs_t, int64_t, nsecs_t) override { return false; }
void composite(nsecs_t, int64_t) override {}
void sample() override {}
+
+ // MessageQueue overrides:
+ void scheduleFrame() override {}
+ void postMessage(sp<MessageHandler>&&) override {}
};
-}; // namespace scheduler
+
+} // namespace scheduler
namespace surfaceflinger::test {
@@ -405,8 +410,6 @@
return mFlinger->onInitializeDisplays();
}
- void scheduleComposite(FrameHint){};
-
void setGlobalShadowSettings(FuzzedDataProvider *fdp) {
const half4 ambientColor{fdp->ConsumeFloatingPoint<float>(),
fdp->ConsumeFloatingPoint<float>(),
@@ -678,31 +681,22 @@
std::unique_ptr<EventThread> sfEventThread,
scheduler::ISchedulerCallback *callback = nullptr,
bool hasMultipleModes = false) {
- DisplayModes modes{DisplayMode::Builder(0)
- .setId(DisplayModeId(0))
- .setPhysicalDisplayId(PhysicalDisplayId::fromPort(0))
- .setVsyncPeriod(16'666'667)
- .setGroup(0)
- .build()};
+ constexpr DisplayModeId kModeId60{0};
+ DisplayModes modes = makeModes(mock::createDisplayMode(kModeId60, 60_Hz));
if (hasMultipleModes) {
- modes.emplace_back(DisplayMode::Builder(1)
- .setId(DisplayModeId(1))
- .setPhysicalDisplayId(PhysicalDisplayId::fromPort(0))
- .setVsyncPeriod(11'111'111)
- .setGroup(0)
- .build());
+ constexpr DisplayModeId kModeId90{1};
+ modes.try_emplace(kModeId90, mock::createDisplayMode(kModeId90, 90_Hz));
}
- const auto currMode = DisplayModeId(0);
- mRefreshRateConfigs = std::make_shared<scheduler::RefreshRateConfigs>(modes, currMode);
- const auto currFps = mRefreshRateConfigs->getCurrentRefreshRate().getFps();
- mFlinger->mVsyncConfiguration = mFactory.createVsyncConfiguration(currFps);
+ mRefreshRateConfigs = std::make_shared<scheduler::RefreshRateConfigs>(modes, kModeId60);
+ const auto fps = mRefreshRateConfigs->getActiveMode()->getFps();
+ mFlinger->mVsyncConfiguration = mFactory.createVsyncConfiguration(fps);
mFlinger->mVsyncModulator = sp<scheduler::VsyncModulator>::make(
mFlinger->mVsyncConfiguration->getCurrentConfigs());
mFlinger->mRefreshRateStats =
- std::make_unique<scheduler::RefreshRateStats>(*mFlinger->mTimeStats, currFps,
- /*powerMode=*/hal::PowerMode::OFF);
+ std::make_unique<scheduler::RefreshRateStats>(*mFlinger->mTimeStats, fps,
+ hal::PowerMode::OFF);
mScheduler = new scheduler::TestableScheduler(std::move(vsyncController),
std::move(vsyncTracker), mRefreshRateConfigs,
@@ -765,8 +759,6 @@
return mFlinger->setPowerModeInternal(display, mode);
}
- auto onMessageReceived(int32_t /*what*/) { return 0; }
-
auto &getTransactionQueue() { return mFlinger->mTransactionQueue; }
auto &getPendingTransactionQueue() { return mFlinger->mPendingTransactionQueues; }
@@ -818,15 +810,16 @@
}
private:
- void scheduleRefresh(FrameHint) {}
+ void scheduleComposite(FrameHint) override {}
void setVsyncEnabled(bool) override {}
- void changeRefreshRate(const RefreshRate &, DisplayModeEvent) override {}
+ void requestDisplayMode(DisplayModePtr, DisplayModeEvent) override {}
void kernelTimerChanged(bool) override {}
- void triggerOnFrameRateOverridesChanged() {}
+ void triggerOnFrameRateOverridesChanged() override {}
surfaceflinger::test::Factory mFactory;
sp<SurfaceFlinger> mFlinger = new SurfaceFlinger(mFactory, SurfaceFlinger::SkipInitialization);
scheduler::TestableScheduler *mScheduler = nullptr;
std::shared_ptr<scheduler::RefreshRateConfigs> mRefreshRateConfigs;
};
+
} // namespace android
diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.cpp b/services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.cpp
index d504155..da60a69 100644
--- a/services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.cpp
+++ b/services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.cpp
@@ -15,22 +15,31 @@
*
*/
-#include "surfaceflinger_scheduler_fuzzer.h"
+#include <ftl/enum.h>
#include <fuzzer/FuzzedDataProvider.h>
#include <processgroup/sched_policy.h>
+
#include "Scheduler/DispSyncSource.h"
#include "Scheduler/OneShotTimer.h"
#include "Scheduler/VSyncDispatchTimerQueue.h"
#include "Scheduler/VSyncPredictor.h"
#include "Scheduler/VSyncReactor.h"
+
#include "surfaceflinger_fuzzers_utils.h"
+#include "surfaceflinger_scheduler_fuzzer.h"
namespace android::fuzz {
using hardware::graphics::composer::hal::PowerMode;
-static constexpr PowerMode kPowerModes[] = {PowerMode::ON, PowerMode::DOZE, PowerMode::OFF,
- PowerMode::DOZE_SUSPEND, PowerMode::ON_SUSPEND};
+constexpr nsecs_t kVsyncPeriods[] = {(30_Hz).getPeriodNsecs(), (60_Hz).getPeriodNsecs(),
+ (72_Hz).getPeriodNsecs(), (90_Hz).getPeriodNsecs(),
+ (120_Hz).getPeriodNsecs()};
+
+constexpr auto kLayerVoteTypes = ftl::enum_range<scheduler::RefreshRateConfigs::LayerVoteType>();
+
+constexpr PowerMode kPowerModes[] = {PowerMode::ON, PowerMode::DOZE, PowerMode::OFF,
+ PowerMode::DOZE_SUSPEND, PowerMode::ON_SUSPEND};
constexpr uint16_t kRandomStringLength = 256;
constexpr std::chrono::duration kSyncPeriod(16ms);
@@ -319,39 +328,42 @@
using RefreshRateConfigs = scheduler::RefreshRateConfigs;
using LayerRequirement = RefreshRateConfigs::LayerRequirement;
using RefreshRateStats = scheduler::RefreshRateStats;
- uint16_t minRefreshRate = mFdp.ConsumeIntegralInRange<uint16_t>(1, UINT16_MAX >> 1);
- uint16_t maxRefreshRate = mFdp.ConsumeIntegralInRange<uint16_t>(minRefreshRate + 1, UINT16_MAX);
- DisplayModeId hwcConfigIndexType = DisplayModeId(mFdp.ConsumeIntegralInRange<uint8_t>(0, 10));
+ const uint16_t minRefreshRate = mFdp.ConsumeIntegralInRange<uint16_t>(1, UINT16_MAX >> 1);
+ const uint16_t maxRefreshRate =
+ mFdp.ConsumeIntegralInRange<uint16_t>(minRefreshRate + 1, UINT16_MAX);
+
+ const DisplayModeId modeId{mFdp.ConsumeIntegralInRange<uint8_t>(0, 10)};
DisplayModes displayModes;
for (uint16_t fps = minRefreshRate; fps < maxRefreshRate; ++fps) {
- constexpr int32_t kGroup = 0;
- const auto refreshRate = Fps::fromValue(static_cast<float>(fps));
- displayModes.push_back(scheduler::createDisplayMode(hwcConfigIndexType, kGroup,
- refreshRate.getPeriodNsecs()));
+ displayModes.try_emplace(modeId,
+ mock::createDisplayMode(modeId,
+ Fps::fromValue(static_cast<float>(fps))));
}
- auto refreshRateConfigs =
- std::make_unique<RefreshRateConfigs>(displayModes, hwcConfigIndexType);
+
+ RefreshRateConfigs refreshRateConfigs(displayModes, modeId);
+
const RefreshRateConfigs::GlobalSignals globalSignals = {.touch = false, .idle = false};
- auto layers = std::vector<LayerRequirement>{
- LayerRequirement{.weight = mFdp.ConsumeFloatingPoint<float>()}};
- refreshRateConfigs->getBestRefreshRate(layers, globalSignals);
+ std::vector<LayerRequirement> layers = {{.weight = mFdp.ConsumeFloatingPoint<float>()}};
+
+ refreshRateConfigs.getBestRefreshRate(layers, globalSignals);
+
layers[0].name = mFdp.ConsumeRandomLengthString(kRandomStringLength);
layers[0].ownerUid = mFdp.ConsumeIntegral<uint16_t>();
layers[0].desiredRefreshRate = Fps::fromValue(mFdp.ConsumeFloatingPoint<float>());
- layers[0].vote = mFdp.PickValueInArray(kLayerVoteTypes);
+ layers[0].vote = mFdp.PickValueInArray(kLayerVoteTypes.values);
auto frameRateOverrides =
- refreshRateConfigs->getFrameRateOverrides(layers,
- Fps::fromValue(
- mFdp.ConsumeFloatingPoint<float>()),
- globalSignals);
+ refreshRateConfigs.getFrameRateOverrides(layers,
+ Fps::fromValue(
+ mFdp.ConsumeFloatingPoint<float>()),
+ globalSignals);
- refreshRateConfigs->setDisplayManagerPolicy(
- {hwcConfigIndexType,
+ refreshRateConfigs.setDisplayManagerPolicy(
+ {modeId,
{Fps::fromValue(mFdp.ConsumeFloatingPoint<float>()),
Fps::fromValue(mFdp.ConsumeFloatingPoint<float>())}});
- refreshRateConfigs->setCurrentModeId(hwcConfigIndexType);
+ refreshRateConfigs.setActiveModeId(modeId);
RefreshRateConfigs::isFractionalPairOrMultiple(Fps::fromValue(
mFdp.ConsumeFloatingPoint<float>()),
@@ -361,13 +373,13 @@
Fps::fromValue(mFdp.ConsumeFloatingPoint<float>()));
android::mock::TimeStats timeStats;
- std::unique_ptr<RefreshRateStats> refreshRateStats =
- std::make_unique<RefreshRateStats>(timeStats,
- Fps::fromValue(mFdp.ConsumeFloatingPoint<float>()),
- PowerMode::OFF);
- refreshRateStats->setRefreshRate(
- refreshRateConfigs->getRefreshRateFromModeId(hwcConfigIndexType).getFps());
- refreshRateStats->setPowerMode(mFdp.PickValueInArray(kPowerModes));
+ RefreshRateStats refreshRateStats(timeStats, Fps::fromValue(mFdp.ConsumeFloatingPoint<float>()),
+ PowerMode::OFF);
+
+ const auto fpsOpt = displayModes.get(modeId, [](const auto& mode) { return mode->getFps(); });
+ refreshRateStats.setRefreshRate(*fpsOpt);
+
+ refreshRateStats.setPowerMode(mFdp.PickValueInArray(kPowerModes));
}
void SchedulerFuzzer::process() {
diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.h b/services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.h
index 84b3912..1a49ead 100644
--- a/services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.h
+++ b/services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.h
@@ -22,6 +22,8 @@
#pragma once
+#include <scheduler/TimeKeeper.h>
+
#include "Clock.h"
#include "Layer.h"
#include "Scheduler/EventThread.h"
@@ -29,24 +31,9 @@
#include "Scheduler/Scheduler.h"
#include "Scheduler/VSyncTracker.h"
#include "Scheduler/VsyncModulator.h"
-#include "scheduler/TimeKeeper.h"
namespace android::fuzz {
-constexpr int64_t kVsyncPeriods[] = {static_cast<int64_t>(1e9f / 30),
- static_cast<int64_t>(1e9f / 60),
- static_cast<int64_t>(1e9f / 72),
- static_cast<int64_t>(1e9f / 90),
- static_cast<int64_t>(1e9f / 120)};
-
-android::scheduler::RefreshRateConfigs::LayerVoteType kLayerVoteTypes[] =
- {android::scheduler::RefreshRateConfigs::LayerVoteType::NoVote,
- android::scheduler::RefreshRateConfigs::LayerVoteType::Min,
- android::scheduler::RefreshRateConfigs::LayerVoteType::Max,
- android::scheduler::RefreshRateConfigs::LayerVoteType::Heuristic,
- android::scheduler::RefreshRateConfigs::LayerVoteType::ExplicitDefault,
- android::scheduler::RefreshRateConfigs::LayerVoteType::ExplicitExactOrMultiple};
-
class FuzzImplClock : public android::scheduler::Clock {
public:
nsecs_t now() const { return 1; }
@@ -168,18 +155,6 @@
namespace android::scheduler {
-DisplayModePtr createDisplayMode(DisplayModeId modeId, int32_t group, int64_t vsyncPeriod,
- ui::Size resolution = ui::Size()) {
- return DisplayMode::Builder(hal::HWConfigId(modeId.value()))
- .setId(modeId)
- .setPhysicalDisplayId(PhysicalDisplayId::fromPort(0))
- .setVsyncPeriod(int32_t(vsyncPeriod))
- .setGroup(group)
- .setHeight(resolution.height)
- .setWidth(resolution.width)
- .build();
-}
-
class ControllableClock : public TimeKeeper {
public:
nsecs_t now() const { return 1; };
diff --git a/services/surfaceflinger/tests/unittests/DisplayDevice_InitiateModeChange.cpp b/services/surfaceflinger/tests/unittests/DisplayDevice_InitiateModeChange.cpp
index 40a9b1a..93af225 100644
--- a/services/surfaceflinger/tests/unittests/DisplayDevice_InitiateModeChange.cpp
+++ b/services/surfaceflinger/tests/unittests/DisplayDevice_InitiateModeChange.cpp
@@ -44,68 +44,42 @@
mFlinger.onComposerHalHotplug(PrimaryDisplayVariant::HWC_DISPLAY_ID, Connection::CONNECTED);
mDisplay = PrimaryDisplayVariant::makeFakeExistingDisplayInjector(this)
- .setDisplayModes({kDisplayMode60, kDisplayMode90, kDisplayMode120},
- kDisplayModeId60)
+ .setDisplayModes(makeModes(kMode60, kMode90, kMode120), kModeId60)
.inject();
}
protected:
sp<DisplayDevice> mDisplay;
- const DisplayModeId kDisplayModeId60 = DisplayModeId(0);
- const DisplayModePtr kDisplayMode60 =
- DisplayMode::Builder(hal::HWConfigId(kDisplayModeId60.value()))
- .setId(kDisplayModeId60)
- .setPhysicalDisplayId(PrimaryDisplayVariant::DISPLAY_ID::get())
- .setVsyncPeriod(int32_t(16'666'667))
- .setGroup(0)
- .setHeight(1000)
- .setWidth(1000)
- .build();
+ static constexpr DisplayModeId kModeId60{0};
+ static constexpr DisplayModeId kModeId90{1};
+ static constexpr DisplayModeId kModeId120{2};
- const DisplayModeId kDisplayModeId90 = DisplayModeId(1);
- const DisplayModePtr kDisplayMode90 =
- DisplayMode::Builder(hal::HWConfigId(kDisplayModeId90.value()))
- .setId(kDisplayModeId90)
- .setPhysicalDisplayId(PrimaryDisplayVariant::DISPLAY_ID::get())
- .setVsyncPeriod(int32_t(11'111'111))
- .setGroup(0)
- .setHeight(1000)
- .setWidth(1000)
- .build();
-
- const DisplayModeId kDisplayModeId120 = DisplayModeId(2);
- const DisplayModePtr kDisplayMode120 =
- DisplayMode::Builder(hal::HWConfigId(kDisplayModeId120.value()))
- .setId(kDisplayModeId120)
- .setPhysicalDisplayId(PrimaryDisplayVariant::DISPLAY_ID::get())
- .setVsyncPeriod(int32_t(8'333'333))
- .setGroup(0)
- .setHeight(1000)
- .setWidth(1000)
- .build();
+ static inline const DisplayModePtr kMode60 = createDisplayMode(kModeId60, 60_Hz);
+ static inline const DisplayModePtr kMode90 = createDisplayMode(kModeId90, 90_Hz);
+ static inline const DisplayModePtr kMode120 = createDisplayMode(kModeId120, 120_Hz);
};
TEST_F(InitiateModeChangeTest, setDesiredActiveMode_setCurrentMode) {
- EXPECT_FALSE(mDisplay->setDesiredActiveMode({kDisplayMode60, Event::None}));
+ EXPECT_FALSE(mDisplay->setDesiredActiveMode({kMode60, Event::None}));
EXPECT_EQ(std::nullopt, mDisplay->getDesiredActiveMode());
}
TEST_F(InitiateModeChangeTest, setDesiredActiveMode_setNewMode) {
- EXPECT_TRUE(mDisplay->setDesiredActiveMode({kDisplayMode90, Event::None}));
+ EXPECT_TRUE(mDisplay->setDesiredActiveMode({kMode90, Event::None}));
ASSERT_NE(std::nullopt, mDisplay->getDesiredActiveMode());
- EXPECT_EQ(kDisplayMode90, mDisplay->getDesiredActiveMode()->mode);
+ EXPECT_EQ(kMode90, mDisplay->getDesiredActiveMode()->mode);
EXPECT_EQ(Event::None, mDisplay->getDesiredActiveMode()->event);
// Setting another mode should be cached but return false
- EXPECT_FALSE(mDisplay->setDesiredActiveMode({kDisplayMode120, Event::None}));
+ EXPECT_FALSE(mDisplay->setDesiredActiveMode({kMode120, Event::None}));
ASSERT_NE(std::nullopt, mDisplay->getDesiredActiveMode());
- EXPECT_EQ(kDisplayMode120, mDisplay->getDesiredActiveMode()->mode);
+ EXPECT_EQ(kMode120, mDisplay->getDesiredActiveMode()->mode);
EXPECT_EQ(Event::None, mDisplay->getDesiredActiveMode()->event);
}
TEST_F(InitiateModeChangeTest, clearDesiredActiveModeState) {
- EXPECT_TRUE(mDisplay->setDesiredActiveMode({kDisplayMode90, Event::None}));
+ EXPECT_TRUE(mDisplay->setDesiredActiveMode({kMode90, Event::None}));
ASSERT_NE(std::nullopt, mDisplay->getDesiredActiveMode());
mDisplay->clearDesiredActiveModeState();
@@ -113,9 +87,9 @@
}
TEST_F(InitiateModeChangeTest, initiateModeChange) NO_THREAD_SAFETY_ANALYSIS {
- EXPECT_TRUE(mDisplay->setDesiredActiveMode({kDisplayMode90, Event::None}));
+ EXPECT_TRUE(mDisplay->setDesiredActiveMode({kMode90, Event::None}));
ASSERT_NE(std::nullopt, mDisplay->getDesiredActiveMode());
- EXPECT_EQ(kDisplayMode90, mDisplay->getDesiredActiveMode()->mode);
+ EXPECT_EQ(kMode90, mDisplay->getDesiredActiveMode()->mode);
EXPECT_EQ(Event::None, mDisplay->getDesiredActiveMode()->event);
hal::VsyncPeriodChangeConstraints constraints{
@@ -126,7 +100,7 @@
EXPECT_EQ(OK,
mDisplay->initiateModeChange(*mDisplay->getDesiredActiveMode(), constraints,
&timeline));
- EXPECT_EQ(kDisplayMode90, mDisplay->getUpcomingActiveMode().mode);
+ EXPECT_EQ(kMode90, mDisplay->getUpcomingActiveMode().mode);
EXPECT_EQ(Event::None, mDisplay->getUpcomingActiveMode().event);
mDisplay->clearDesiredActiveModeState();
@@ -135,9 +109,9 @@
TEST_F(InitiateModeChangeTest, getUpcomingActiveMode_desiredActiveModeChanged)
NO_THREAD_SAFETY_ANALYSIS {
- EXPECT_TRUE(mDisplay->setDesiredActiveMode({kDisplayMode90, Event::None}));
+ EXPECT_TRUE(mDisplay->setDesiredActiveMode({kMode90, Event::None}));
ASSERT_NE(std::nullopt, mDisplay->getDesiredActiveMode());
- EXPECT_EQ(kDisplayMode90, mDisplay->getDesiredActiveMode()->mode);
+ EXPECT_EQ(kMode90, mDisplay->getDesiredActiveMode()->mode);
EXPECT_EQ(Event::None, mDisplay->getDesiredActiveMode()->event);
hal::VsyncPeriodChangeConstraints constraints{
@@ -148,21 +122,21 @@
EXPECT_EQ(OK,
mDisplay->initiateModeChange(*mDisplay->getDesiredActiveMode(), constraints,
&timeline));
- EXPECT_EQ(kDisplayMode90, mDisplay->getUpcomingActiveMode().mode);
+ EXPECT_EQ(kMode90, mDisplay->getUpcomingActiveMode().mode);
EXPECT_EQ(Event::None, mDisplay->getUpcomingActiveMode().event);
- EXPECT_FALSE(mDisplay->setDesiredActiveMode({kDisplayMode120, Event::None}));
+ EXPECT_FALSE(mDisplay->setDesiredActiveMode({kMode120, Event::None}));
ASSERT_NE(std::nullopt, mDisplay->getDesiredActiveMode());
- EXPECT_EQ(kDisplayMode120, mDisplay->getDesiredActiveMode()->mode);
+ EXPECT_EQ(kMode120, mDisplay->getDesiredActiveMode()->mode);
EXPECT_EQ(Event::None, mDisplay->getDesiredActiveMode()->event);
- EXPECT_EQ(kDisplayMode90, mDisplay->getUpcomingActiveMode().mode);
+ EXPECT_EQ(kMode90, mDisplay->getUpcomingActiveMode().mode);
EXPECT_EQ(Event::None, mDisplay->getUpcomingActiveMode().event);
EXPECT_EQ(OK,
mDisplay->initiateModeChange(*mDisplay->getDesiredActiveMode(), constraints,
&timeline));
- EXPECT_EQ(kDisplayMode120, mDisplay->getUpcomingActiveMode().mode);
+ EXPECT_EQ(kMode120, mDisplay->getUpcomingActiveMode().mode);
EXPECT_EQ(Event::None, mDisplay->getUpcomingActiveMode().event);
mDisplay->clearDesiredActiveModeState();
diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h b/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h
index 54b8bcb..565c244 100644
--- a/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h
+++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h
@@ -45,6 +45,7 @@
#include "TestableScheduler.h"
#include "TestableSurfaceFlinger.h"
#include "mock/DisplayHardware/MockComposer.h"
+#include "mock/DisplayHardware/MockDisplayMode.h"
#include "mock/DisplayHardware/MockPowerAdvisor.h"
#include "mock/MockEventThread.h"
#include "mock/MockNativeWindowSurface.h"
@@ -235,9 +236,9 @@
using CONNECTION_TYPE = DisplayConnectionTypeGetter<DisplayIdType>;
using HWC_DISPLAY_ID_OPT = HwcDisplayIdGetter<DisplayIdType>;
- // The display width and height
static constexpr int WIDTH = width;
static constexpr int HEIGHT = height;
+ static constexpr ui::Size RESOLUTION{WIDTH, HEIGHT};
static constexpr int GRALLOC_USAGE = grallocUsage;
@@ -262,7 +263,7 @@
static auto makeFakeExistingDisplayInjector(DisplayTransactionTest* test) {
auto ceDisplayArgs = compositionengine::DisplayCreationArgsBuilder();
ceDisplayArgs.setId(DISPLAY_ID::get())
- .setPixels({WIDTH, HEIGHT})
+ .setPixels(RESOLUTION)
.setPowerAdvisor(&test->mPowerAdvisor);
auto compositionDisplay =
@@ -357,8 +358,7 @@
TestableSurfaceFlinger::FakeHwcDisplayInjector(displayId, HWC_DISPLAY_TYPE,
static_cast<bool>(DisplayVariant::PRIMARY))
.setHwcDisplayId(HWC_DISPLAY_ID)
- .setWidth(DisplayVariant::WIDTH)
- .setHeight(DisplayVariant::HEIGHT)
+ .setResolution(DisplayVariant::RESOLUTION)
.setActiveConfig(HWC_ACTIVE_CONFIG_ID)
.setPowerMode(INIT_POWER_MODE)
.inject(&test->mFlinger, test->mComposer);
@@ -381,7 +381,7 @@
auto ceDisplayArgs = compositionengine::DisplayCreationArgsBuilder()
.setId(DisplayVariant::DISPLAY_ID::get())
- .setPixels({DisplayVariant::WIDTH, DisplayVariant::HEIGHT})
+ .setPixels(DisplayVariant::RESOLUTION)
.setIsSecure(static_cast<bool>(DisplayVariant::SECURE))
.setPowerAdvisor(&test->mPowerAdvisor)
.setName(std::string("Injected display for ") +
@@ -541,7 +541,7 @@
auto ceDisplayArgs = compositionengine::DisplayCreationArgsBuilder()
.setId(Base::DISPLAY_ID::get())
- .setPixels({Base::WIDTH, Base::HEIGHT})
+ .setPixels(Base::RESOLUTION)
.setIsSecure(static_cast<bool>(Base::SECURE))
.setPowerAdvisor(&test->mPowerAdvisor)
.setName(std::string("Injected display for ") +
@@ -593,7 +593,7 @@
const auto displayId = Base::DISPLAY_ID::get();
auto ceDisplayArgs = compositionengine::DisplayCreationArgsBuilder()
.setId(displayId)
- .setPixels({Base::WIDTH, Base::HEIGHT})
+ .setPixels(Base::RESOLUTION)
.setIsSecure(static_cast<bool>(Base::SECURE))
.setPowerAdvisor(&test->mPowerAdvisor)
.setName(std::string("Injected display for ") +
@@ -736,6 +736,12 @@
HdrNotSupportedVariant<SimpleHwcVirtualDisplayVariant>,
NoPerFrameMetadataSupportVariant<SimpleHwcVirtualDisplayVariant>>;
+inline DisplayModePtr createDisplayMode(DisplayModeId modeId, Fps refreshRate, int32_t group = 0,
+ ui::Size resolution = ui::Size(1920, 1080)) {
+ return mock::createDisplayMode(modeId, refreshRate, group, resolution,
+ PrimaryDisplayVariant::DISPLAY_ID::get());
+}
+
} // namespace android
// TODO(b/129481165): remove the #pragma below and fix conversion issues
diff --git a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp
index e108bea..17511cd 100644
--- a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp
+++ b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp
@@ -31,6 +31,7 @@
#include "Scheduler/LayerInfo.h"
#include "TestableScheduler.h"
#include "TestableSurfaceFlinger.h"
+#include "mock/DisplayHardware/MockDisplayMode.h"
#include "mock/MockLayer.h"
#include "mock/MockSchedulerCallback.h"
@@ -42,6 +43,8 @@
using MockLayer = android::mock::MockLayer;
+using android::mock::createDisplayMode;
+
class LayerHistoryTest : public testing::Test {
protected:
static constexpr auto PRESENT_TIME_HISTORY_SIZE = LayerInfo::HISTORY_SIZE;
@@ -122,22 +125,12 @@
ASSERT_EQ(desiredRefreshRate, summary[0].desiredRefreshRate);
}
- std::shared_ptr<RefreshRateConfigs> mConfigs = std::make_shared<
- RefreshRateConfigs>(DisplayModes{DisplayMode::Builder(0)
- .setId(DisplayModeId(0))
- .setPhysicalDisplayId(
- PhysicalDisplayId::fromPort(0))
- .setVsyncPeriod(int32_t(LO_FPS_PERIOD))
- .setGroup(0)
- .build(),
- DisplayMode::Builder(1)
- .setId(DisplayModeId(1))
- .setPhysicalDisplayId(
- PhysicalDisplayId::fromPort(0))
- .setVsyncPeriod(int32_t(HI_FPS_PERIOD))
- .setGroup(0)
- .build()},
- DisplayModeId(0));
+ std::shared_ptr<RefreshRateConfigs> mConfigs =
+ std::make_shared<RefreshRateConfigs>(makeModes(createDisplayMode(DisplayModeId(0),
+ LO_FPS),
+ createDisplayMode(DisplayModeId(1),
+ HI_FPS)),
+ DisplayModeId(0));
mock::SchedulerCallback mSchedulerCallback;
diff --git a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
index 97f3747..fcde532 100644
--- a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
+++ b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
@@ -25,46 +25,33 @@
#include "DisplayHardware/HWC2.h"
#include "FpsOps.h"
#include "Scheduler/RefreshRateConfigs.h"
+#include "mock/DisplayHardware/MockDisplayMode.h"
using namespace std::chrono_literals;
namespace android::scheduler {
-namespace {
-
-DisplayModePtr createDisplayMode(DisplayModeId modeId, Fps refreshRate, int32_t group = 0,
- ui::Size resolution = ui::Size()) {
- return DisplayMode::Builder(hal::HWConfigId(modeId.value()))
- .setId(modeId)
- .setPhysicalDisplayId(PhysicalDisplayId::fromPort(0))
- .setVsyncPeriod(static_cast<int32_t>(refreshRate.getPeriodNsecs()))
- .setGroup(group)
- .setHeight(resolution.height)
- .setWidth(resolution.width)
- .build();
-}
-
-} // namespace
namespace hal = android::hardware::graphics::composer::hal;
-using RefreshRate = RefreshRateConfigs::RefreshRate;
using LayerVoteType = RefreshRateConfigs::LayerVoteType;
using LayerRequirement = RefreshRateConfigs::LayerRequirement;
+using mock::createDisplayMode;
+
struct TestableRefreshRateConfigs : RefreshRateConfigs {
using RefreshRateConfigs::RefreshRateConfigs;
- RefreshRate getMinSupportedRefreshRate() const {
+ DisplayModePtr getMinSupportedRefreshRate() const {
std::lock_guard lock(mLock);
- return *mMinSupportedRefreshRate;
+ return mMinRefreshRateModeIt->second;
}
- RefreshRate getMaxSupportedRefreshRate() const {
+ DisplayModePtr getMaxSupportedRefreshRate() const {
std::lock_guard lock(mLock);
- return *mMaxSupportedRefreshRate;
+ return mMaxRefreshRateModeIt->second;
}
- RefreshRate getMinRefreshRateByPolicy() const {
+ DisplayModePtr getMinRefreshRateByPolicy() const {
std::lock_guard lock(mLock);
return getMinRefreshRateByPolicyLocked();
}
@@ -79,8 +66,8 @@
return RefreshRateConfigs::getBestRefreshRate(layers, signals);
}
- RefreshRate getBestRefreshRate(const std::vector<LayerRequirement>& layers = {},
- GlobalSignals signals = {}) const {
+ DisplayModePtr getBestRefreshRate(const std::vector<LayerRequirement>& layers = {},
+ GlobalSignals signals = {}) const {
return getBestRefreshRateAndSignals(layers, signals).first;
}
};
@@ -90,10 +77,6 @@
RefreshRateConfigsTest();
~RefreshRateConfigsTest();
- static RefreshRate asRefreshRate(DisplayModePtr displayMode) {
- return {displayMode, RefreshRate::ConstructorTag(0)};
- }
-
static constexpr DisplayModeId kModeId60{0};
static constexpr DisplayModeId kModeId90{1};
static constexpr DisplayModeId kModeId72{2};
@@ -126,30 +109,30 @@
static inline const DisplayModePtr kMode24Frac = createDisplayMode(kModeId24Frac, 23.976_Hz);
// Test configurations.
- static inline const DisplayModes kModes_60 = {kMode60};
- static inline const DisplayModes kModes_60_90 = {kMode60, kMode90};
- static inline const DisplayModes kModes_60_90_G1 = {kMode60, kMode90_G1};
- static inline const DisplayModes kModes_60_90_4K = {kMode60, kMode90_4K};
- static inline const DisplayModes kModes_60_72_90 = {kMode60, kMode90, kMode72};
- static inline const DisplayModes kModes_60_90_72_120 = {kMode60, kMode90, kMode72, kMode120};
- static inline const DisplayModes kModes_30_60_72_90_120 = {kMode60, kMode90, kMode72, kMode120,
- kMode30};
+ static inline const DisplayModes kModes_60 = makeModes(kMode60);
+ static inline const DisplayModes kModes_60_90 = makeModes(kMode60, kMode90);
+ static inline const DisplayModes kModes_60_90_G1 = makeModes(kMode60, kMode90_G1);
+ static inline const DisplayModes kModes_60_90_4K = makeModes(kMode60, kMode90_4K);
+ static inline const DisplayModes kModes_60_72_90 = makeModes(kMode60, kMode90, kMode72);
+ static inline const DisplayModes kModes_60_90_72_120 =
+ makeModes(kMode60, kMode90, kMode72, kMode120);
+ static inline const DisplayModes kModes_30_60_72_90_120 =
+ makeModes(kMode60, kMode90, kMode72, kMode120, kMode30);
- static inline const DisplayModes kModes_30_60 = {kMode60, kMode90_G1, kMode72_G1, kMode120_G1,
- kMode30};
- static inline const DisplayModes kModes_30_60_72_90 = {kMode60, kMode90, kMode72, kMode120_G1,
- kMode30};
- static inline const DisplayModes kModes_30_60_90 = {kMode60, kMode90, kMode72_G1, kMode120_G1,
- kMode30};
- static inline const DisplayModes kModes_25_30_50_60 = {kMode60, kMode90, kMode72_G1,
- kMode120_G1, kMode30_G1, kMode25_G1,
- kMode50};
- static inline const DisplayModes kModes_60_120 = {kMode60, kMode120};
+ static inline const DisplayModes kModes_30_60 =
+ makeModes(kMode60, kMode90_G1, kMode72_G1, kMode120_G1, kMode30);
+ static inline const DisplayModes kModes_30_60_72_90 =
+ makeModes(kMode60, kMode90, kMode72, kMode120_G1, kMode30);
+ static inline const DisplayModes kModes_30_60_90 =
+ makeModes(kMode60, kMode90, kMode72_G1, kMode120_G1, kMode30);
+ static inline const DisplayModes kModes_25_30_50_60 =
+ makeModes(kMode60, kMode90, kMode72_G1, kMode120_G1, kMode30_G1, kMode25_G1, kMode50);
+ static inline const DisplayModes kModes_60_120 = makeModes(kMode60, kMode120);
// This is a typical TV configuration.
- static inline const DisplayModes kModes_24_25_30_50_60_Frac = {kMode24, kMode24Frac, kMode25,
- kMode30, kMode30Frac, kMode50,
- kMode60, kMode60Frac};
+ static inline const DisplayModes kModes_24_25_30_50_60_Frac =
+ makeModes(kMode24, kMode24Frac, kMode25, kMode30, kMode30Frac, kMode50, kMode60,
+ kMode60Frac);
};
RefreshRateConfigsTest::RefreshRateConfigsTest() {
@@ -183,8 +166,8 @@
const auto minRate = configs.getMinSupportedRefreshRate();
const auto performanceRate = configs.getMaxSupportedRefreshRate();
- EXPECT_EQ(asRefreshRate(kMode60), minRate);
- EXPECT_EQ(asRefreshRate(kMode90), performanceRate);
+ EXPECT_EQ(kMode60, minRate);
+ EXPECT_EQ(kMode90, performanceRate);
const auto minRateByPolicy = configs.getMinRefreshRateByPolicy();
const auto performanceRateByPolicy = configs.getMaxRefreshRateByPolicy();
@@ -201,19 +184,19 @@
const auto minRate60 = configs.getMinRefreshRateByPolicy();
const auto performanceRate60 = configs.getMaxRefreshRateByPolicy();
- EXPECT_EQ(asRefreshRate(kMode60), minRate);
- EXPECT_EQ(asRefreshRate(kMode60), minRate60);
- EXPECT_EQ(asRefreshRate(kMode60), performanceRate60);
+ EXPECT_EQ(kMode60, minRate);
+ EXPECT_EQ(kMode60, minRate60);
+ EXPECT_EQ(kMode60, performanceRate60);
EXPECT_GE(configs.setDisplayManagerPolicy({kModeId90, {60_Hz, 90_Hz}}), 0);
- configs.setCurrentModeId(kModeId90);
+ configs.setActiveModeId(kModeId90);
const auto minRate90 = configs.getMinRefreshRateByPolicy();
const auto performanceRate90 = configs.getMaxRefreshRateByPolicy();
- EXPECT_EQ(asRefreshRate(kMode90_G1), performanceRate);
- EXPECT_EQ(asRefreshRate(kMode90_G1), minRate90);
- EXPECT_EQ(asRefreshRate(kMode90_G1), performanceRate90);
+ EXPECT_EQ(kMode90_G1, performanceRate);
+ EXPECT_EQ(kMode90_G1, minRate90);
+ EXPECT_EQ(kMode90_G1, performanceRate90);
}
TEST_F(RefreshRateConfigsTest, twoModes_storesFullRefreshRateMap_differentResolutions) {
@@ -224,19 +207,19 @@
const auto minRate60 = configs.getMinRefreshRateByPolicy();
const auto performanceRate60 = configs.getMaxRefreshRateByPolicy();
- EXPECT_EQ(asRefreshRate(kMode60), minRate);
- EXPECT_EQ(asRefreshRate(kMode60), minRate60);
- EXPECT_EQ(asRefreshRate(kMode60), performanceRate60);
+ EXPECT_EQ(kMode60, minRate);
+ EXPECT_EQ(kMode60, minRate60);
+ EXPECT_EQ(kMode60, performanceRate60);
EXPECT_GE(configs.setDisplayManagerPolicy({kModeId90, {60_Hz, 90_Hz}}), 0);
- configs.setCurrentModeId(kModeId90);
+ configs.setActiveModeId(kModeId90);
const auto minRate90 = configs.getMinRefreshRateByPolicy();
const auto performanceRate90 = configs.getMaxRefreshRateByPolicy();
- EXPECT_EQ(asRefreshRate(kMode90_4K), performanceRate);
- EXPECT_EQ(asRefreshRate(kMode90_4K), minRate90);
- EXPECT_EQ(asRefreshRate(kMode90_4K), performanceRate90);
+ EXPECT_EQ(kMode90_4K, performanceRate);
+ EXPECT_EQ(kMode90_4K, minRate90);
+ EXPECT_EQ(kMode90_4K, performanceRate90);
}
TEST_F(RefreshRateConfigsTest, twoModes_policyChange) {
@@ -245,35 +228,35 @@
const auto minRate = configs.getMinRefreshRateByPolicy();
const auto performanceRate = configs.getMaxRefreshRateByPolicy();
- EXPECT_EQ(asRefreshRate(kMode60), minRate);
- EXPECT_EQ(asRefreshRate(kMode90), performanceRate);
+ EXPECT_EQ(kMode60, minRate);
+ EXPECT_EQ(kMode90, performanceRate);
EXPECT_GE(configs.setDisplayManagerPolicy({kModeId60, {60_Hz, 60_Hz}}), 0);
const auto minRate60 = configs.getMinRefreshRateByPolicy();
const auto performanceRate60 = configs.getMaxRefreshRateByPolicy();
- EXPECT_EQ(asRefreshRate(kMode60), minRate60);
- EXPECT_EQ(asRefreshRate(kMode60), performanceRate60);
+ EXPECT_EQ(kMode60, minRate60);
+ EXPECT_EQ(kMode60, performanceRate60);
}
-TEST_F(RefreshRateConfigsTest, twoModes_getCurrentRefreshRate) {
+TEST_F(RefreshRateConfigsTest, twoModes_getActiveMode) {
TestableRefreshRateConfigs configs(kModes_60_90, kModeId60);
{
- const auto current = configs.getCurrentRefreshRate();
- EXPECT_EQ(current.getModeId(), kModeId60);
+ const auto mode = configs.getActiveMode();
+ EXPECT_EQ(mode->getId(), kModeId60);
}
- configs.setCurrentModeId(kModeId90);
+ configs.setActiveModeId(kModeId90);
{
- const auto current = configs.getCurrentRefreshRate();
- EXPECT_EQ(current.getModeId(), kModeId90);
+ const auto mode = configs.getActiveMode();
+ EXPECT_EQ(mode->getId(), kModeId90);
}
EXPECT_GE(configs.setDisplayManagerPolicy({kModeId90, {90_Hz, 90_Hz}}), 0);
{
- const auto current = configs.getCurrentRefreshRate();
- EXPECT_EQ(current.getModeId(), kModeId90);
+ const auto mode = configs.getActiveMode();
+ EXPECT_EQ(mode->getId(), kModeId90);
}
}
@@ -283,10 +266,10 @@
// If there are no layers we select the default frame rate, which is the max of the primary
// range.
- EXPECT_EQ(asRefreshRate(kMode90), configs.getBestRefreshRate());
+ EXPECT_EQ(kMode90, configs.getBestRefreshRate());
EXPECT_EQ(configs.setDisplayManagerPolicy({kModeId60, {60_Hz, 60_Hz}}), NO_ERROR);
- EXPECT_EQ(asRefreshRate(kMode60), configs.getBestRefreshRate());
+ EXPECT_EQ(kMode60, configs.getBestRefreshRate());
}
{
// We select max even when this will cause a non-seamless switch.
@@ -294,7 +277,7 @@
constexpr bool kAllowGroupSwitching = true;
EXPECT_EQ(configs.setDisplayManagerPolicy({kModeId90, kAllowGroupSwitching, {0_Hz, 90_Hz}}),
NO_ERROR);
- EXPECT_EQ(asRefreshRate(kMode90_G1), configs.getBestRefreshRate());
+ EXPECT_EQ(kMode90_G1, configs.getBestRefreshRate());
}
}
@@ -306,104 +289,104 @@
lr.vote = LayerVoteType::Min;
lr.name = "Min";
- EXPECT_EQ(asRefreshRate(kMode60), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode60, configs.getBestRefreshRate(layers));
lr.vote = LayerVoteType::Max;
lr.name = "Max";
- EXPECT_EQ(asRefreshRate(kMode90), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode90, configs.getBestRefreshRate(layers));
lr.desiredRefreshRate = 90_Hz;
lr.vote = LayerVoteType::Heuristic;
lr.name = "90Hz Heuristic";
- EXPECT_EQ(asRefreshRate(kMode90), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode90, configs.getBestRefreshRate(layers));
lr.desiredRefreshRate = 60_Hz;
lr.name = "60Hz Heuristic";
- EXPECT_EQ(asRefreshRate(kMode60), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode60, configs.getBestRefreshRate(layers));
lr.desiredRefreshRate = 45_Hz;
lr.name = "45Hz Heuristic";
- EXPECT_EQ(asRefreshRate(kMode90), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode90, configs.getBestRefreshRate(layers));
lr.desiredRefreshRate = 30_Hz;
lr.name = "30Hz Heuristic";
- EXPECT_EQ(asRefreshRate(kMode60), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode60, configs.getBestRefreshRate(layers));
lr.desiredRefreshRate = 24_Hz;
lr.name = "24Hz Heuristic";
- EXPECT_EQ(asRefreshRate(kMode60), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode60, configs.getBestRefreshRate(layers));
lr.name = "";
EXPECT_GE(configs.setDisplayManagerPolicy({kModeId60, {60_Hz, 60_Hz}}), 0);
lr.vote = LayerVoteType::Min;
- EXPECT_EQ(asRefreshRate(kMode60), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode60, configs.getBestRefreshRate(layers));
lr.vote = LayerVoteType::Max;
- EXPECT_EQ(asRefreshRate(kMode60), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode60, configs.getBestRefreshRate(layers));
lr.desiredRefreshRate = 90_Hz;
lr.vote = LayerVoteType::Heuristic;
- EXPECT_EQ(asRefreshRate(kMode60), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode60, configs.getBestRefreshRate(layers));
lr.desiredRefreshRate = 60_Hz;
- EXPECT_EQ(asRefreshRate(kMode60), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode60, configs.getBestRefreshRate(layers));
lr.desiredRefreshRate = 45_Hz;
- EXPECT_EQ(asRefreshRate(kMode60), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode60, configs.getBestRefreshRate(layers));
lr.desiredRefreshRate = 30_Hz;
- EXPECT_EQ(asRefreshRate(kMode60), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode60, configs.getBestRefreshRate(layers));
lr.desiredRefreshRate = 24_Hz;
- EXPECT_EQ(asRefreshRate(kMode60), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode60, configs.getBestRefreshRate(layers));
EXPECT_GE(configs.setDisplayManagerPolicy({kModeId90, {90_Hz, 90_Hz}}), 0);
lr.vote = LayerVoteType::Min;
- EXPECT_EQ(asRefreshRate(kMode90), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode90, configs.getBestRefreshRate(layers));
lr.vote = LayerVoteType::Max;
- EXPECT_EQ(asRefreshRate(kMode90), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode90, configs.getBestRefreshRate(layers));
lr.desiredRefreshRate = 90_Hz;
lr.vote = LayerVoteType::Heuristic;
- EXPECT_EQ(asRefreshRate(kMode90), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode90, configs.getBestRefreshRate(layers));
lr.desiredRefreshRate = 60_Hz;
- EXPECT_EQ(asRefreshRate(kMode90), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode90, configs.getBestRefreshRate(layers));
lr.desiredRefreshRate = 45_Hz;
- EXPECT_EQ(asRefreshRate(kMode90), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode90, configs.getBestRefreshRate(layers));
lr.desiredRefreshRate = 30_Hz;
- EXPECT_EQ(asRefreshRate(kMode90), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode90, configs.getBestRefreshRate(layers));
lr.desiredRefreshRate = 24_Hz;
- EXPECT_EQ(asRefreshRate(kMode90), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode90, configs.getBestRefreshRate(layers));
EXPECT_GE(configs.setDisplayManagerPolicy({kModeId60, {0_Hz, 120_Hz}}), 0);
lr.vote = LayerVoteType::Min;
- EXPECT_EQ(asRefreshRate(kMode60), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode60, configs.getBestRefreshRate(layers));
lr.vote = LayerVoteType::Max;
- EXPECT_EQ(asRefreshRate(kMode90), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode90, configs.getBestRefreshRate(layers));
lr.desiredRefreshRate = 90_Hz;
lr.vote = LayerVoteType::Heuristic;
- EXPECT_EQ(asRefreshRate(kMode90), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode90, configs.getBestRefreshRate(layers));
lr.desiredRefreshRate = 60_Hz;
- EXPECT_EQ(asRefreshRate(kMode60), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode60, configs.getBestRefreshRate(layers));
lr.desiredRefreshRate = 45_Hz;
- EXPECT_EQ(asRefreshRate(kMode90), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode90, configs.getBestRefreshRate(layers));
lr.desiredRefreshRate = 30_Hz;
- EXPECT_EQ(asRefreshRate(kMode60), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode60, configs.getBestRefreshRate(layers));
lr.desiredRefreshRate = 24_Hz;
- EXPECT_EQ(asRefreshRate(kMode60), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode60, configs.getBestRefreshRate(layers));
}
TEST_F(RefreshRateConfigsTest, getBestRefreshRate_multipleThreshold_60_90) {
@@ -414,32 +397,32 @@
lr.vote = LayerVoteType::Min;
lr.name = "Min";
- EXPECT_EQ(asRefreshRate(kMode60), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode60, configs.getBestRefreshRate(layers));
lr.vote = LayerVoteType::Max;
lr.name = "Max";
- EXPECT_EQ(asRefreshRate(kMode90), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode90, configs.getBestRefreshRate(layers));
lr.desiredRefreshRate = 90_Hz;
lr.vote = LayerVoteType::Heuristic;
lr.name = "90Hz Heuristic";
- EXPECT_EQ(asRefreshRate(kMode90), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode90, configs.getBestRefreshRate(layers));
lr.desiredRefreshRate = 60_Hz;
lr.name = "60Hz Heuristic";
- EXPECT_EQ(asRefreshRate(kMode60), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode60, configs.getBestRefreshRate(layers));
lr.desiredRefreshRate = 45_Hz;
lr.name = "45Hz Heuristic";
- EXPECT_EQ(asRefreshRate(kMode90), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode90, configs.getBestRefreshRate(layers));
lr.desiredRefreshRate = 30_Hz;
lr.name = "30Hz Heuristic";
- EXPECT_EQ(asRefreshRate(kMode60), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode60, configs.getBestRefreshRate(layers));
lr.desiredRefreshRate = 24_Hz;
lr.name = "24Hz Heuristic";
- EXPECT_EQ(asRefreshRate(kMode60), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode60, configs.getBestRefreshRate(layers));
}
TEST_F(RefreshRateConfigsTest, getBestRefreshRate_60_72_90) {
@@ -449,26 +432,26 @@
auto& lr = layers[0];
lr.vote = LayerVoteType::Min;
- EXPECT_EQ(asRefreshRate(kMode60), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode60, configs.getBestRefreshRate(layers));
lr.vote = LayerVoteType::Max;
- EXPECT_EQ(asRefreshRate(kMode90), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode90, configs.getBestRefreshRate(layers));
lr.desiredRefreshRate = 90_Hz;
lr.vote = LayerVoteType::Heuristic;
- EXPECT_EQ(asRefreshRate(kMode90), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode90, configs.getBestRefreshRate(layers));
lr.desiredRefreshRate = 60_Hz;
- EXPECT_EQ(asRefreshRate(kMode60), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode60, configs.getBestRefreshRate(layers));
lr.desiredRefreshRate = 45_Hz;
- EXPECT_EQ(asRefreshRate(kMode90), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode90, configs.getBestRefreshRate(layers));
lr.desiredRefreshRate = 30_Hz;
- EXPECT_EQ(asRefreshRate(kMode60), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode60, configs.getBestRefreshRate(layers));
lr.desiredRefreshRate = 24_Hz;
- EXPECT_EQ(asRefreshRate(kMode72), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode72, configs.getBestRefreshRate(layers));
}
TEST_F(RefreshRateConfigsTest, getBestRefreshRate_30_60_72_90_120) {
@@ -482,19 +465,19 @@
lr1.vote = LayerVoteType::Heuristic;
lr2.desiredRefreshRate = 60_Hz;
lr2.vote = LayerVoteType::Heuristic;
- EXPECT_EQ(asRefreshRate(kMode120), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode120, configs.getBestRefreshRate(layers));
lr1.desiredRefreshRate = 24_Hz;
lr1.vote = LayerVoteType::Heuristic;
lr2.desiredRefreshRate = 48_Hz;
lr2.vote = LayerVoteType::Heuristic;
- EXPECT_EQ(asRefreshRate(kMode72), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode72, configs.getBestRefreshRate(layers));
lr1.desiredRefreshRate = 24_Hz;
lr1.vote = LayerVoteType::Heuristic;
lr2.desiredRefreshRate = 48_Hz;
lr2.vote = LayerVoteType::Heuristic;
- EXPECT_EQ(asRefreshRate(kMode72), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode72, configs.getBestRefreshRate(layers));
}
TEST_F(RefreshRateConfigsTest, getBestRefreshRate_30_60_90_120_DifferentTypes) {
@@ -510,7 +493,7 @@
lr2.desiredRefreshRate = 60_Hz;
lr2.vote = LayerVoteType::Heuristic;
lr2.name = "60Hz Heuristic";
- EXPECT_EQ(asRefreshRate(kMode120), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode120, configs.getBestRefreshRate(layers));
lr1.desiredRefreshRate = 24_Hz;
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
@@ -518,7 +501,7 @@
lr2.desiredRefreshRate = 60_Hz;
lr2.vote = LayerVoteType::Heuristic;
lr2.name = "60Hz Heuristic";
- EXPECT_EQ(asRefreshRate(kMode120), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode120, configs.getBestRefreshRate(layers));
lr1.desiredRefreshRate = 24_Hz;
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
@@ -526,7 +509,7 @@
lr2.desiredRefreshRate = 60_Hz;
lr2.vote = LayerVoteType::ExplicitDefault;
lr2.name = "60Hz ExplicitDefault";
- EXPECT_EQ(asRefreshRate(kMode120), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode120, configs.getBestRefreshRate(layers));
lr1.desiredRefreshRate = 24_Hz;
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
@@ -534,7 +517,7 @@
lr2.desiredRefreshRate = 90_Hz;
lr2.vote = LayerVoteType::Heuristic;
lr2.name = "90Hz Heuristic";
- EXPECT_EQ(asRefreshRate(kMode90), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode90, configs.getBestRefreshRate(layers));
lr1.desiredRefreshRate = 24_Hz;
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
@@ -542,7 +525,7 @@
lr2.desiredRefreshRate = 90_Hz;
lr2.vote = LayerVoteType::ExplicitDefault;
lr2.name = "90Hz Heuristic";
- EXPECT_EQ(asRefreshRate(kMode72), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode72, configs.getBestRefreshRate(layers));
lr1.desiredRefreshRate = 24_Hz;
lr1.vote = LayerVoteType::ExplicitDefault;
@@ -550,7 +533,7 @@
lr2.desiredRefreshRate = 90_Hz;
lr2.vote = LayerVoteType::Heuristic;
lr2.name = "90Hz Heuristic";
- EXPECT_EQ(asRefreshRate(kMode90), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode90, configs.getBestRefreshRate(layers));
lr1.desiredRefreshRate = 24_Hz;
lr1.vote = LayerVoteType::Heuristic;
@@ -558,7 +541,7 @@
lr2.desiredRefreshRate = 90_Hz;
lr2.vote = LayerVoteType::ExplicitDefault;
lr2.name = "90Hz ExplicitDefault";
- EXPECT_EQ(asRefreshRate(kMode72), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode72, configs.getBestRefreshRate(layers));
lr1.desiredRefreshRate = 24_Hz;
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
@@ -566,7 +549,7 @@
lr2.desiredRefreshRate = 90_Hz;
lr2.vote = LayerVoteType::ExplicitDefault;
lr2.name = "90Hz ExplicitDefault";
- EXPECT_EQ(asRefreshRate(kMode72), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode72, configs.getBestRefreshRate(layers));
lr1.desiredRefreshRate = 24_Hz;
lr1.vote = LayerVoteType::ExplicitDefault;
@@ -574,7 +557,7 @@
lr2.desiredRefreshRate = 90_Hz;
lr2.vote = LayerVoteType::ExplicitExactOrMultiple;
lr2.name = "90Hz ExplicitExactOrMultiple";
- EXPECT_EQ(asRefreshRate(kMode90), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode90, configs.getBestRefreshRate(layers));
}
TEST_F(RefreshRateConfigsTest, getBestRefreshRate_30_60_90_120_DifferentTypes_multipleThreshold) {
@@ -591,7 +574,7 @@
lr2.desiredRefreshRate = 60_Hz;
lr2.vote = LayerVoteType::Heuristic;
lr2.name = "60Hz Heuristic";
- EXPECT_EQ(asRefreshRate(kMode120), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode120, configs.getBestRefreshRate(layers));
lr1.desiredRefreshRate = 24_Hz;
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
@@ -599,7 +582,7 @@
lr2.desiredRefreshRate = 60_Hz;
lr2.vote = LayerVoteType::Heuristic;
lr2.name = "60Hz Heuristic";
- EXPECT_EQ(asRefreshRate(kMode60), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode60, configs.getBestRefreshRate(layers));
lr1.desiredRefreshRate = 24_Hz;
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
@@ -607,7 +590,7 @@
lr2.desiredRefreshRate = 60_Hz;
lr2.vote = LayerVoteType::ExplicitDefault;
lr2.name = "60Hz ExplicitDefault";
- EXPECT_EQ(asRefreshRate(kMode72), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode72, configs.getBestRefreshRate(layers));
lr1.desiredRefreshRate = 24_Hz;
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
@@ -615,7 +598,7 @@
lr2.desiredRefreshRate = 90_Hz;
lr2.vote = LayerVoteType::Heuristic;
lr2.name = "90Hz Heuristic";
- EXPECT_EQ(asRefreshRate(kMode90), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode90, configs.getBestRefreshRate(layers));
lr1.desiredRefreshRate = 24_Hz;
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
@@ -623,7 +606,7 @@
lr2.desiredRefreshRate = 90_Hz;
lr2.vote = LayerVoteType::ExplicitDefault;
lr2.name = "90Hz Heuristic";
- EXPECT_EQ(asRefreshRate(kMode72), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode72, configs.getBestRefreshRate(layers));
lr1.desiredRefreshRate = 24_Hz;
lr1.vote = LayerVoteType::ExplicitDefault;
@@ -631,7 +614,7 @@
lr2.desiredRefreshRate = 90_Hz;
lr2.vote = LayerVoteType::Heuristic;
lr2.name = "90Hz Heuristic";
- EXPECT_EQ(asRefreshRate(kMode90), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode90, configs.getBestRefreshRate(layers));
lr1.desiredRefreshRate = 24_Hz;
lr1.vote = LayerVoteType::Heuristic;
@@ -639,7 +622,7 @@
lr2.desiredRefreshRate = 90_Hz;
lr2.vote = LayerVoteType::ExplicitDefault;
lr2.name = "90Hz ExplicitDefault";
- EXPECT_EQ(asRefreshRate(kMode72), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode72, configs.getBestRefreshRate(layers));
lr1.desiredRefreshRate = 24_Hz;
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
@@ -647,7 +630,7 @@
lr2.desiredRefreshRate = 90_Hz;
lr2.vote = LayerVoteType::ExplicitDefault;
lr2.name = "90Hz ExplicitDefault";
- EXPECT_EQ(asRefreshRate(kMode72), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode72, configs.getBestRefreshRate(layers));
lr1.desiredRefreshRate = 24_Hz;
lr1.vote = LayerVoteType::ExplicitDefault;
@@ -655,7 +638,7 @@
lr2.desiredRefreshRate = 90_Hz;
lr2.vote = LayerVoteType::ExplicitExactOrMultiple;
lr2.name = "90Hz ExplicitExactOrMultiple";
- EXPECT_EQ(asRefreshRate(kMode90), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode90, configs.getBestRefreshRate(layers));
}
TEST_F(RefreshRateConfigsTest, getBestRefreshRate_30_60) {
@@ -665,26 +648,26 @@
auto& lr = layers[0];
lr.vote = LayerVoteType::Min;
- EXPECT_EQ(asRefreshRate(kMode30), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode30, configs.getBestRefreshRate(layers));
lr.vote = LayerVoteType::Max;
- EXPECT_EQ(asRefreshRate(kMode60), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode60, configs.getBestRefreshRate(layers));
lr.desiredRefreshRate = 90_Hz;
lr.vote = LayerVoteType::Heuristic;
- EXPECT_EQ(asRefreshRate(kMode60), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode60, configs.getBestRefreshRate(layers));
lr.desiredRefreshRate = 60_Hz;
- EXPECT_EQ(asRefreshRate(kMode60), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode60, configs.getBestRefreshRate(layers));
lr.desiredRefreshRate = 45_Hz;
- EXPECT_EQ(asRefreshRate(kMode60), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode60, configs.getBestRefreshRate(layers));
lr.desiredRefreshRate = 30_Hz;
- EXPECT_EQ(asRefreshRate(kMode30), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode30, configs.getBestRefreshRate(layers));
lr.desiredRefreshRate = 24_Hz;
- EXPECT_EQ(asRefreshRate(kMode60), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode60, configs.getBestRefreshRate(layers));
}
TEST_F(RefreshRateConfigsTest, getBestRefreshRate_30_60_72_90) {
@@ -695,42 +678,42 @@
lr.vote = LayerVoteType::Min;
lr.name = "Min";
- EXPECT_EQ(asRefreshRate(kMode30), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode30, configs.getBestRefreshRate(layers));
lr.vote = LayerVoteType::Max;
lr.name = "Max";
- EXPECT_EQ(asRefreshRate(kMode90), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode90, configs.getBestRefreshRate(layers));
lr.desiredRefreshRate = 90_Hz;
lr.vote = LayerVoteType::Heuristic;
lr.name = "90Hz Heuristic";
- EXPECT_EQ(asRefreshRate(kMode90), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode90, configs.getBestRefreshRate(layers));
lr.desiredRefreshRate = 60_Hz;
lr.name = "60Hz Heuristic";
- EXPECT_EQ(asRefreshRate(kMode60), configs.getBestRefreshRate(layers));
- EXPECT_EQ(asRefreshRate(kMode90), configs.getBestRefreshRate(layers, {.touch = true}));
+ EXPECT_EQ(kMode60, configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode90, configs.getBestRefreshRate(layers, {.touch = true}));
lr.desiredRefreshRate = 45_Hz;
lr.name = "45Hz Heuristic";
- EXPECT_EQ(asRefreshRate(kMode90), configs.getBestRefreshRate(layers));
- EXPECT_EQ(asRefreshRate(kMode90), configs.getBestRefreshRate(layers, {.touch = true}));
+ EXPECT_EQ(kMode90, configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode90, configs.getBestRefreshRate(layers, {.touch = true}));
lr.desiredRefreshRate = 30_Hz;
lr.name = "30Hz Heuristic";
- EXPECT_EQ(asRefreshRate(kMode30), configs.getBestRefreshRate(layers));
- EXPECT_EQ(asRefreshRate(kMode90), configs.getBestRefreshRate(layers, {.touch = true}));
+ EXPECT_EQ(kMode30, configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode90, configs.getBestRefreshRate(layers, {.touch = true}));
lr.desiredRefreshRate = 24_Hz;
lr.name = "24Hz Heuristic";
- EXPECT_EQ(asRefreshRate(kMode72), configs.getBestRefreshRate(layers));
- EXPECT_EQ(asRefreshRate(kMode90), configs.getBestRefreshRate(layers, {.touch = true}));
+ EXPECT_EQ(kMode72, configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode90, configs.getBestRefreshRate(layers, {.touch = true}));
lr.desiredRefreshRate = 24_Hz;
lr.vote = LayerVoteType::ExplicitExactOrMultiple;
lr.name = "24Hz ExplicitExactOrMultiple";
- EXPECT_EQ(asRefreshRate(kMode72), configs.getBestRefreshRate(layers));
- EXPECT_EQ(asRefreshRate(kMode90), configs.getBestRefreshRate(layers, {.touch = true}));
+ EXPECT_EQ(kMode72, configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode90, configs.getBestRefreshRate(layers, {.touch = true}));
}
TEST_F(RefreshRateConfigsTest, getBestRefreshRate_PriorityTest) {
@@ -742,39 +725,39 @@
lr1.vote = LayerVoteType::Min;
lr2.vote = LayerVoteType::Max;
- EXPECT_EQ(asRefreshRate(kMode90), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode90, configs.getBestRefreshRate(layers));
lr1.vote = LayerVoteType::Min;
lr2.vote = LayerVoteType::Heuristic;
lr2.desiredRefreshRate = 24_Hz;
- EXPECT_EQ(asRefreshRate(kMode60), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode60, configs.getBestRefreshRate(layers));
lr1.vote = LayerVoteType::Min;
lr2.vote = LayerVoteType::ExplicitExactOrMultiple;
lr2.desiredRefreshRate = 24_Hz;
- EXPECT_EQ(asRefreshRate(kMode60), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode60, configs.getBestRefreshRate(layers));
lr1.vote = LayerVoteType::Max;
lr2.vote = LayerVoteType::Heuristic;
lr2.desiredRefreshRate = 60_Hz;
- EXPECT_EQ(asRefreshRate(kMode90), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode90, configs.getBestRefreshRate(layers));
lr1.vote = LayerVoteType::Max;
lr2.vote = LayerVoteType::ExplicitExactOrMultiple;
lr2.desiredRefreshRate = 60_Hz;
- EXPECT_EQ(asRefreshRate(kMode90), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode90, configs.getBestRefreshRate(layers));
lr1.vote = LayerVoteType::Heuristic;
lr1.desiredRefreshRate = 15_Hz;
lr2.vote = LayerVoteType::Heuristic;
lr2.desiredRefreshRate = 45_Hz;
- EXPECT_EQ(asRefreshRate(kMode90), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode90, configs.getBestRefreshRate(layers));
lr1.vote = LayerVoteType::Heuristic;
lr1.desiredRefreshRate = 30_Hz;
lr2.vote = LayerVoteType::ExplicitExactOrMultiple;
lr2.desiredRefreshRate = 45_Hz;
- EXPECT_EQ(asRefreshRate(kMode90), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode90, configs.getBestRefreshRate(layers));
}
TEST_F(RefreshRateConfigsTest, getBestRefreshRate_24FpsVideo) {
@@ -786,9 +769,9 @@
lr.vote = LayerVoteType::ExplicitExactOrMultiple;
for (float fps = 23.0f; fps < 25.0f; fps += 0.1f) {
lr.desiredRefreshRate = Fps::fromValue(fps);
- const auto refreshRate = configs.getBestRefreshRate(layers);
- EXPECT_EQ(asRefreshRate(kMode60), refreshRate)
- << lr.desiredRefreshRate << " chooses " << refreshRate.getName();
+ const auto mode = configs.getBestRefreshRate(layers);
+ EXPECT_EQ(kMode60, mode) << lr.desiredRefreshRate << " chooses "
+ << to_string(mode->getFps());
}
}
@@ -802,9 +785,9 @@
lr.vote = LayerVoteType::ExplicitExactOrMultiple;
for (float fps = 23.0f; fps < 25.0f; fps += 0.1f) {
lr.desiredRefreshRate = Fps::fromValue(fps);
- const auto refreshRate = configs.getBestRefreshRate(layers);
- EXPECT_EQ(asRefreshRate(kMode60), refreshRate)
- << lr.desiredRefreshRate << " chooses " << refreshRate.getName();
+ const auto mode = configs.getBestRefreshRate(layers);
+ EXPECT_EQ(kMode60, mode) << lr.desiredRefreshRate << " chooses "
+ << to_string(mode->getFps());
}
}
@@ -819,19 +802,19 @@
lr1.desiredRefreshRate = 60_Hz;
lr2.vote = LayerVoteType::ExplicitExactOrMultiple;
lr2.desiredRefreshRate = 90_Hz;
- EXPECT_EQ(asRefreshRate(kMode90), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode90, configs.getBestRefreshRate(layers));
lr1.vote = LayerVoteType::ExplicitDefault;
lr1.desiredRefreshRate = 90_Hz;
lr2.vote = LayerVoteType::ExplicitExactOrMultiple;
lr2.desiredRefreshRate = 60_Hz;
- EXPECT_EQ(asRefreshRate(kMode60), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode60, configs.getBestRefreshRate(layers));
lr1.vote = LayerVoteType::Heuristic;
lr1.desiredRefreshRate = 90_Hz;
lr2.vote = LayerVoteType::ExplicitExactOrMultiple;
lr2.desiredRefreshRate = 60_Hz;
- EXPECT_EQ(asRefreshRate(kMode90), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode90, configs.getBestRefreshRate(layers));
}
TEST_F(RefreshRateConfigsTest, getBestRefreshRate_75HzContent) {
@@ -843,9 +826,9 @@
lr.vote = LayerVoteType::ExplicitExactOrMultiple;
for (float fps = 75.0f; fps < 100.0f; fps += 0.1f) {
lr.desiredRefreshRate = Fps::fromValue(fps);
- const auto refreshRate = configs.getBestRefreshRate(layers, {});
- EXPECT_EQ(asRefreshRate(kMode90), refreshRate)
- << lr.desiredRefreshRate << " chooses " << refreshRate.getName();
+ const auto mode = configs.getBestRefreshRate(layers, {});
+ EXPECT_EQ(kMode90, mode) << lr.desiredRefreshRate << " chooses "
+ << to_string(mode->getFps());
}
}
@@ -862,7 +845,7 @@
lr2.vote = LayerVoteType::Heuristic;
lr2.desiredRefreshRate = 90_Hz;
lr2.name = "90Hz Heuristic";
- EXPECT_EQ(asRefreshRate(kMode90), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode90, configs.getBestRefreshRate(layers));
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
lr1.desiredRefreshRate = 60_Hz;
@@ -870,14 +853,14 @@
lr2.vote = LayerVoteType::ExplicitDefault;
lr2.desiredRefreshRate = 90_Hz;
lr2.name = "90Hz ExplicitDefault";
- EXPECT_EQ(asRefreshRate(kMode60), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode60, configs.getBestRefreshRate(layers));
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
lr1.desiredRefreshRate = 60_Hz;
lr1.name = "60Hz ExplicitExactOrMultiple";
lr2.vote = LayerVoteType::Max;
lr2.name = "Max";
- EXPECT_EQ(asRefreshRate(kMode90), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode90, configs.getBestRefreshRate(layers));
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
lr1.desiredRefreshRate = 30_Hz;
@@ -885,14 +868,14 @@
lr2.vote = LayerVoteType::Heuristic;
lr2.desiredRefreshRate = 90_Hz;
lr2.name = "90Hz Heuristic";
- EXPECT_EQ(asRefreshRate(kMode90), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode90, configs.getBestRefreshRate(layers));
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
lr1.desiredRefreshRate = 30_Hz;
lr1.name = "30Hz ExplicitExactOrMultiple";
lr2.vote = LayerVoteType::Max;
lr2.name = "Max";
- EXPECT_EQ(asRefreshRate(kMode90), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode90, configs.getBestRefreshRate(layers));
}
TEST_F(RefreshRateConfigsTest, scrollWhileWatching60fps_60_90) {
@@ -907,28 +890,28 @@
lr1.name = "60Hz ExplicitExactOrMultiple";
lr2.vote = LayerVoteType::NoVote;
lr2.name = "NoVote";
- EXPECT_EQ(asRefreshRate(kMode60), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode60, configs.getBestRefreshRate(layers));
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
lr1.desiredRefreshRate = 60_Hz;
lr1.name = "60Hz ExplicitExactOrMultiple";
lr2.vote = LayerVoteType::NoVote;
lr2.name = "NoVote";
- EXPECT_EQ(asRefreshRate(kMode90), configs.getBestRefreshRate(layers, {.touch = true}));
+ EXPECT_EQ(kMode90, configs.getBestRefreshRate(layers, {.touch = true}));
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
lr1.desiredRefreshRate = 60_Hz;
lr1.name = "60Hz ExplicitExactOrMultiple";
lr2.vote = LayerVoteType::Max;
lr2.name = "Max";
- EXPECT_EQ(asRefreshRate(kMode90), configs.getBestRefreshRate(layers, {.touch = true}));
+ EXPECT_EQ(kMode90, configs.getBestRefreshRate(layers, {.touch = true}));
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
lr1.desiredRefreshRate = 60_Hz;
lr1.name = "60Hz ExplicitExactOrMultiple";
lr2.vote = LayerVoteType::Max;
lr2.name = "Max";
- EXPECT_EQ(asRefreshRate(kMode90), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode90, configs.getBestRefreshRate(layers));
// The other layer starts to provide buffers
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
@@ -937,7 +920,7 @@
lr2.vote = LayerVoteType::Heuristic;
lr2.desiredRefreshRate = 90_Hz;
lr2.name = "90Hz Heuristic";
- EXPECT_EQ(asRefreshRate(kMode90), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode90, configs.getBestRefreshRate(layers));
}
TEST_F(RefreshRateConfigsTest, touchConsidered) {
@@ -1023,8 +1006,7 @@
ss << "ExplicitDefault " << desired;
lr.name = ss.str();
- const auto refreshRate = configs.getBestRefreshRate(layers);
- EXPECT_EQ(refreshRate.getFps(), expected);
+ EXPECT_EQ(expected, configs.getBestRefreshRate(layers)->getFps());
}
}
@@ -1035,36 +1017,36 @@
// Test that 23.976 will choose 24 if 23.976 is not supported
{
- TestableRefreshRateConfigs configs({kMode24, kMode25, kMode30, kMode30Frac, kMode60,
- kMode60Frac},
+ TestableRefreshRateConfigs configs(makeModes(kMode24, kMode25, kMode30, kMode30Frac,
+ kMode60, kMode60Frac),
kModeId60);
lr.vote = LayerVoteType::ExplicitExactOrMultiple;
lr.desiredRefreshRate = 23.976_Hz;
lr.name = "ExplicitExactOrMultiple 23.976 Hz";
- EXPECT_EQ(kModeId24, configs.getBestRefreshRate(layers).getModeId());
+ EXPECT_EQ(kModeId24, configs.getBestRefreshRate(layers)->getId());
}
// Test that 24 will choose 23.976 if 24 is not supported
{
- TestableRefreshRateConfigs configs({kMode24Frac, kMode25, kMode30, kMode30Frac, kMode60,
- kMode60Frac},
+ TestableRefreshRateConfigs configs(makeModes(kMode24Frac, kMode25, kMode30, kMode30Frac,
+ kMode60, kMode60Frac),
kModeId60);
lr.desiredRefreshRate = 24_Hz;
lr.name = "ExplicitExactOrMultiple 24 Hz";
- EXPECT_EQ(kModeId24Frac, configs.getBestRefreshRate(layers).getModeId());
+ EXPECT_EQ(kModeId24Frac, configs.getBestRefreshRate(layers)->getId());
}
// Test that 29.97 will prefer 59.94 over 60 and 30
{
- TestableRefreshRateConfigs configs({kMode24, kMode24Frac, kMode25, kMode30, kMode60,
- kMode60Frac},
+ TestableRefreshRateConfigs configs(makeModes(kMode24, kMode24Frac, kMode25, kMode30,
+ kMode60, kMode60Frac),
kModeId60);
lr.desiredRefreshRate = 29.97_Hz;
lr.name = "ExplicitExactOrMultiple 29.97 Hz";
- EXPECT_EQ(kModeId60Frac, configs.getBestRefreshRate(layers).getModeId());
+ EXPECT_EQ(kModeId60Frac, configs.getBestRefreshRate(layers)->getId());
}
}
@@ -1083,32 +1065,31 @@
ss << "ExplicitExact " << desired;
lr.name = ss.str();
- auto selectedRefreshRate = configs.getBestRefreshRate(layers);
- EXPECT_EQ(selectedRefreshRate.getFps(), lr.desiredRefreshRate);
+ EXPECT_EQ(lr.desiredRefreshRate, configs.getBestRefreshRate(layers)->getFps());
}
}
// Test that 23.976 will choose 24 if 23.976 is not supported
{
- TestableRefreshRateConfigs configs({kMode24, kMode25, kMode30, kMode30Frac, kMode60,
- kMode60Frac},
+ TestableRefreshRateConfigs configs(makeModes(kMode24, kMode25, kMode30, kMode30Frac,
+ kMode60, kMode60Frac),
kModeId60);
lr.vote = LayerVoteType::ExplicitExact;
lr.desiredRefreshRate = 23.976_Hz;
lr.name = "ExplicitExact 23.976 Hz";
- EXPECT_EQ(kModeId24, configs.getBestRefreshRate(layers).getModeId());
+ EXPECT_EQ(kModeId24, configs.getBestRefreshRate(layers)->getId());
}
// Test that 24 will choose 23.976 if 24 is not supported
{
- TestableRefreshRateConfigs configs({kMode24Frac, kMode25, kMode30, kMode30Frac, kMode60,
- kMode60Frac},
+ TestableRefreshRateConfigs configs(makeModes(kMode24Frac, kMode25, kMode30, kMode30Frac,
+ kMode60, kMode60Frac),
kModeId60);
lr.desiredRefreshRate = 24_Hz;
lr.name = "ExplicitExact 24 Hz";
- EXPECT_EQ(kModeId24Frac, configs.getBestRefreshRate(layers).getModeId());
+ EXPECT_EQ(kModeId24Frac, configs.getBestRefreshRate(layers)->getId());
}
}
@@ -1126,10 +1107,9 @@
lr.name = "60Hz ExplicitDefault";
lr.focused = true;
- const auto [refreshRate, signals] =
- configs.getBestRefreshRate(layers, {.touch = true, .idle = true});
+ const auto [mode, signals] = configs.getBestRefreshRate(layers, {.touch = true, .idle = true});
- EXPECT_EQ(refreshRate, asRefreshRate(kMode60));
+ EXPECT_EQ(mode, kMode60);
EXPECT_FALSE(signals.touch);
}
@@ -1146,7 +1126,7 @@
lr.desiredRefreshRate = 90_Hz;
lr.name = "90Hz ExplicitDefault";
lr.focused = true;
- EXPECT_EQ(asRefreshRate(kMode90), configs.getBestRefreshRate(layers, {.idle = true}));
+ EXPECT_EQ(kMode90, configs.getBestRefreshRate(layers, {.idle = true}));
}
TEST_F(RefreshRateConfigsTest,
@@ -1155,8 +1135,8 @@
EXPECT_GE(configs.setDisplayManagerPolicy({kModeId90, {90_Hz, 90_Hz}, {60_Hz, 90_Hz}}), 0);
- const auto [refreshRate, signals] = configs.getBestRefreshRateAndSignals({}, {});
- EXPECT_EQ(refreshRate, asRefreshRate(kMode90));
+ const auto [mode, signals] = configs.getBestRefreshRateAndSignals({}, {});
+ EXPECT_EQ(mode, kMode90);
EXPECT_FALSE(signals.touch);
std::vector<LayerRequirement> layers = {{.weight = 1.f}};
@@ -1166,46 +1146,46 @@
lr.desiredRefreshRate = 60_Hz;
lr.name = "60Hz ExplicitExactOrMultiple";
lr.focused = false;
- EXPECT_EQ(asRefreshRate(kMode90), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode90, configs.getBestRefreshRate(layers));
lr.focused = true;
- EXPECT_EQ(asRefreshRate(kMode90), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode90, configs.getBestRefreshRate(layers));
lr.vote = LayerVoteType::ExplicitDefault;
lr.desiredRefreshRate = 60_Hz;
lr.name = "60Hz ExplicitDefault";
lr.focused = false;
- EXPECT_EQ(asRefreshRate(kMode90), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode90, configs.getBestRefreshRate(layers));
lr.focused = true;
- EXPECT_EQ(asRefreshRate(kMode60), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode60, configs.getBestRefreshRate(layers));
lr.vote = LayerVoteType::Heuristic;
lr.desiredRefreshRate = 60_Hz;
lr.name = "60Hz Heuristic";
lr.focused = false;
- EXPECT_EQ(asRefreshRate(kMode90), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode90, configs.getBestRefreshRate(layers));
lr.focused = true;
- EXPECT_EQ(asRefreshRate(kMode90), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode90, configs.getBestRefreshRate(layers));
lr.vote = LayerVoteType::Max;
lr.desiredRefreshRate = 60_Hz;
lr.name = "60Hz Max";
lr.focused = false;
- EXPECT_EQ(asRefreshRate(kMode90), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode90, configs.getBestRefreshRate(layers));
lr.focused = true;
- EXPECT_EQ(asRefreshRate(kMode90), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode90, configs.getBestRefreshRate(layers));
lr.vote = LayerVoteType::Min;
lr.desiredRefreshRate = 60_Hz;
lr.name = "60Hz Min";
lr.focused = false;
- EXPECT_EQ(asRefreshRate(kMode90), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode90, configs.getBestRefreshRate(layers));
lr.focused = true;
- EXPECT_EQ(asRefreshRate(kMode90), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode90, configs.getBestRefreshRate(layers));
}
TEST_F(RefreshRateConfigsTest, groupSwitchingNotAllowed) {
@@ -1221,7 +1201,7 @@
layer.name = "90Hz ExplicitDefault";
layer.focused = true;
- EXPECT_EQ(kModeId60, configs.getBestRefreshRate(layers).getModeId());
+ EXPECT_EQ(kModeId60, configs.getBestRefreshRate(layers)->getId());
}
TEST_F(RefreshRateConfigsTest, groupSwitchingWithOneLayer) {
@@ -1239,7 +1219,7 @@
layer.seamlessness = Seamlessness::SeamedAndSeamless;
layer.name = "90Hz ExplicitDefault";
layer.focused = true;
- EXPECT_EQ(kModeId90, configs.getBestRefreshRate(layers).getModeId());
+ EXPECT_EQ(kModeId90, configs.getBestRefreshRate(layers)->getId());
}
TEST_F(RefreshRateConfigsTest, groupSwitchingWithOneLayerOnlySeamless) {
@@ -1258,7 +1238,7 @@
layer.seamlessness = Seamlessness::OnlySeamless;
layer.name = "90Hz ExplicitDefault";
layer.focused = true;
- EXPECT_EQ(kModeId60, configs.getBestRefreshRate(layers).getModeId());
+ EXPECT_EQ(kModeId60, configs.getBestRefreshRate(layers)->getId());
}
TEST_F(RefreshRateConfigsTest, groupSwitchingWithOneLayerOnlySeamlessDefaultFps) {
@@ -1269,7 +1249,7 @@
policy.allowGroupSwitching = true;
EXPECT_GE(configs.setDisplayManagerPolicy(policy), 0);
- configs.setCurrentModeId(kModeId90);
+ configs.setActiveModeId(kModeId90);
// Verify that we won't do a seamless switch if we request the same mode as the default
std::vector<LayerRequirement> layers = {{.weight = 1.f}};
@@ -1279,7 +1259,7 @@
layer.seamlessness = Seamlessness::OnlySeamless;
layer.name = "60Hz ExplicitDefault";
layer.focused = true;
- EXPECT_EQ(kModeId90, configs.getBestRefreshRate(layers).getModeId());
+ EXPECT_EQ(kModeId90, configs.getBestRefreshRate(layers)->getId());
}
TEST_F(RefreshRateConfigsTest, groupSwitchingWithOneLayerDefaultSeamlessness) {
@@ -1290,7 +1270,7 @@
policy.allowGroupSwitching = true;
EXPECT_GE(configs.setDisplayManagerPolicy(policy), 0);
- configs.setCurrentModeId(kModeId90);
+ configs.setActiveModeId(kModeId90);
// Verify that if the current config is in another group and there are no layers with
// seamlessness=SeamedAndSeamless we'll go back to the default group.
@@ -1303,7 +1283,7 @@
layer.name = "60Hz ExplicitDefault";
layer.focused = true;
- EXPECT_EQ(kModeId60, configs.getBestRefreshRate(layers).getModeId());
+ EXPECT_EQ(kModeId60, configs.getBestRefreshRate(layers)->getId());
}
TEST_F(RefreshRateConfigsTest, groupSwitchingWithTwoLayersOnlySeamlessAndSeamed) {
@@ -1314,7 +1294,7 @@
policy.allowGroupSwitching = true;
EXPECT_GE(configs.setDisplayManagerPolicy(policy), 0);
- configs.setCurrentModeId(kModeId90);
+ configs.setActiveModeId(kModeId90);
// If there's a layer with seamlessness=SeamedAndSeamless, another layer with
// seamlessness=OnlySeamless can't change the mode group.
@@ -1332,7 +1312,7 @@
layers[1].name = "90Hz ExplicitDefault";
layers[1].focused = false;
- EXPECT_EQ(kModeId90, configs.getBestRefreshRate(layers).getModeId());
+ EXPECT_EQ(kModeId90, configs.getBestRefreshRate(layers)->getId());
}
TEST_F(RefreshRateConfigsTest, groupSwitchingWithTwoLayersDefaultFocusedAndSeamed) {
@@ -1343,7 +1323,7 @@
policy.allowGroupSwitching = true;
EXPECT_GE(configs.setDisplayManagerPolicy(policy), 0);
- configs.setCurrentModeId(kModeId90);
+ configs.setActiveModeId(kModeId90);
// If there's a focused layer with seamlessness=SeamedAndSeamless, another layer with
// seamlessness=Default can't change the mode group back to the group of the default
@@ -1365,7 +1345,7 @@
layers[1].vote = LayerVoteType::ExplicitDefault;
layers[1].name = "90Hz ExplicitDefault";
- EXPECT_EQ(kModeId90, configs.getBestRefreshRate(layers).getModeId());
+ EXPECT_EQ(kModeId90, configs.getBestRefreshRate(layers)->getId());
}
TEST_F(RefreshRateConfigsTest, groupSwitchingWithTwoLayersDefaultNotFocusedAndSeamed) {
@@ -1376,7 +1356,7 @@
policy.allowGroupSwitching = true;
EXPECT_GE(configs.setDisplayManagerPolicy(policy), 0);
- configs.setCurrentModeId(kModeId90);
+ configs.setActiveModeId(kModeId90);
// Layer with seamlessness=Default can change the mode group if there's a not
// focused layer with seamlessness=SeamedAndSeamless. This happens for example,
@@ -1395,7 +1375,7 @@
layers[1].vote = LayerVoteType::ExplicitDefault;
layers[1].name = "90Hz ExplicitDefault";
- EXPECT_EQ(kModeId60, configs.getBestRefreshRate(layers).getModeId());
+ EXPECT_EQ(kModeId60, configs.getBestRefreshRate(layers)->getId());
}
TEST_F(RefreshRateConfigsTest, nonSeamlessVotePrefersSeamlessSwitches) {
@@ -1415,10 +1395,10 @@
layer.name = "60Hz ExplicitExactOrMultiple";
layer.focused = true;
- EXPECT_EQ(kModeId60, configs.getBestRefreshRate(layers).getModeId());
+ EXPECT_EQ(kModeId60, configs.getBestRefreshRate(layers)->getId());
- configs.setCurrentModeId(kModeId120);
- EXPECT_EQ(kModeId120, configs.getBestRefreshRate(layers).getModeId());
+ configs.setActiveModeId(kModeId120);
+ EXPECT_EQ(kModeId120, configs.getBestRefreshRate(layers)->getId());
}
TEST_F(RefreshRateConfigsTest, nonSeamlessExactAndSeamlessMultipleLayers) {
@@ -1443,14 +1423,14 @@
.weight = 1.f,
.focused = true}};
- EXPECT_EQ(kModeId50, configs.getBestRefreshRate(layers).getModeId());
+ EXPECT_EQ(kModeId50, configs.getBestRefreshRate(layers)->getId());
auto& seamedLayer = layers[0];
seamedLayer.desiredRefreshRate = 30_Hz;
seamedLayer.name = "30Hz ExplicitDefault";
- configs.setCurrentModeId(kModeId30);
+ configs.setActiveModeId(kModeId30);
- EXPECT_EQ(kModeId25, configs.getBestRefreshRate(layers).getModeId());
+ EXPECT_EQ(kModeId25, configs.getBestRefreshRate(layers)->getId());
}
TEST_F(RefreshRateConfigsTest, minLayersDontTrigerSeamedSwitch) {
@@ -1465,7 +1445,7 @@
std::vector<LayerRequirement> layers = {
{.name = "Min", .vote = LayerVoteType::Min, .weight = 1.f, .focused = true}};
- EXPECT_EQ(kModeId90, configs.getBestRefreshRate(layers).getModeId());
+ EXPECT_EQ(kModeId90, configs.getBestRefreshRate(layers)->getId());
}
TEST_F(RefreshRateConfigsTest, primaryVsAppRequestPolicy) {
@@ -1485,12 +1465,12 @@
layers[0].vote = voteType;
layers[0].desiredRefreshRate = fps;
layers[0].focused = args.focused;
- return configs.getBestRefreshRate(layers, {.touch = args.touch}).getModeId();
+ return configs.getBestRefreshRate(layers, {.touch = args.touch})->getId();
};
EXPECT_GE(configs.setDisplayManagerPolicy({kModeId60, {30_Hz, 60_Hz}, {30_Hz, 90_Hz}}), 0);
- EXPECT_EQ(kModeId60, configs.getBestRefreshRate().getModeId());
+ EXPECT_EQ(kModeId60, configs.getBestRefreshRate()->getId());
EXPECT_EQ(kModeId60, getFrameRate(LayerVoteType::NoVote, 90_Hz));
EXPECT_EQ(kModeId30, getFrameRate(LayerVoteType::Min, 90_Hz));
EXPECT_EQ(kModeId60, getFrameRate(LayerVoteType::Max, 90_Hz));
@@ -1537,7 +1517,7 @@
// Refresh rate will be chosen by either touch state or idle state.
EXPECT_EQ(!touchActive, signals.idle);
- return refreshRate.getModeId();
+ return refreshRate->getId();
};
EXPECT_GE(configs.setDisplayManagerPolicy({kModeId60, {60_Hz, 90_Hz}, {60_Hz, 90_Hz}}), 0);
@@ -1555,10 +1535,10 @@
}
// With no layers, idle should still be lower priority than touch boost.
- EXPECT_EQ(kModeId90, configs.getBestRefreshRate({}, {.touch = true, .idle = true}).getModeId());
+ EXPECT_EQ(kModeId90, configs.getBestRefreshRate({}, {.touch = true, .idle = true})->getId());
// Idle should be higher precedence than other layer frame rate considerations.
- configs.setCurrentModeId(kModeId90);
+ configs.setActiveModeId(kModeId90);
{
constexpr bool kTouchActive = false;
@@ -1572,7 +1552,7 @@
}
// Idle should be applied rather than the current config when there are no layers.
- EXPECT_EQ(kModeId60, configs.getBestRefreshRate({}, {.idle = true}).getModeId());
+ EXPECT_EQ(kModeId60, configs.getBestRefreshRate({}, {.idle = true})->getId());
}
TEST_F(RefreshRateConfigsTest, findClosestKnownFrameRate) {
@@ -1598,13 +1578,12 @@
struct Expectation {
Fps fps;
- const RefreshRate& refreshRate;
+ DisplayModePtr mode;
};
const std::initializer_list<Expectation> knownFrameRatesExpectations = {
- {24_Hz, asRefreshRate(kMode60)}, {30_Hz, asRefreshRate(kMode60)},
- {45_Hz, asRefreshRate(kMode90)}, {60_Hz, asRefreshRate(kMode60)},
- {72_Hz, asRefreshRate(kMode90)}, {90_Hz, asRefreshRate(kMode90)},
+ {24_Hz, kMode60}, {30_Hz, kMode60}, {45_Hz, kMode90},
+ {60_Hz, kMode60}, {72_Hz, kMode90}, {90_Hz, kMode90},
};
// Make sure the test tests all the known frame rate
@@ -1620,9 +1599,9 @@
auto& layer = layers[0];
layer.vote = LayerVoteType::Heuristic;
- for (const auto& [fps, refreshRate] : knownFrameRatesExpectations) {
+ for (const auto& [fps, mode] : knownFrameRatesExpectations) {
layer.desiredRefreshRate = fps;
- EXPECT_EQ(refreshRate, configs.getBestRefreshRate(layers));
+ EXPECT_EQ(mode, configs.getBestRefreshRate(layers));
}
}
@@ -1641,21 +1620,21 @@
explicitExactLayer.name = "ExplicitExact";
explicitExactLayer.desiredRefreshRate = 30_Hz;
- EXPECT_EQ(asRefreshRate(kMode30), configs.getBestRefreshRate(layers));
- EXPECT_EQ(asRefreshRate(kMode30), configs.getBestRefreshRate(layers, {.touch = true}));
+ EXPECT_EQ(kMode30, configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode30, configs.getBestRefreshRate(layers, {.touch = true}));
explicitExactOrMultipleLayer.desiredRefreshRate = 120_Hz;
explicitExactLayer.desiredRefreshRate = 60_Hz;
- EXPECT_EQ(asRefreshRate(kMode60), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode60, configs.getBestRefreshRate(layers));
explicitExactLayer.desiredRefreshRate = 72_Hz;
- EXPECT_EQ(asRefreshRate(kMode72), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode72, configs.getBestRefreshRate(layers));
explicitExactLayer.desiredRefreshRate = 90_Hz;
- EXPECT_EQ(asRefreshRate(kMode90), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode90, configs.getBestRefreshRate(layers));
explicitExactLayer.desiredRefreshRate = 120_Hz;
- EXPECT_EQ(asRefreshRate(kMode120), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode120, configs.getBestRefreshRate(layers));
}
TEST_F(RefreshRateConfigsTest, getBestRefreshRate_ExplicitExactEnableFrameRateOverride) {
@@ -1674,21 +1653,21 @@
explicitExactLayer.name = "ExplicitExact";
explicitExactLayer.desiredRefreshRate = 30_Hz;
- EXPECT_EQ(asRefreshRate(kMode60), configs.getBestRefreshRate(layers));
- EXPECT_EQ(asRefreshRate(kMode120), configs.getBestRefreshRate(layers, {.touch = true}));
+ EXPECT_EQ(kMode60, configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode120, configs.getBestRefreshRate(layers, {.touch = true}));
explicitExactOrMultipleLayer.desiredRefreshRate = 120_Hz;
explicitExactLayer.desiredRefreshRate = 60_Hz;
- EXPECT_EQ(asRefreshRate(kMode120), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode120, configs.getBestRefreshRate(layers));
explicitExactLayer.desiredRefreshRate = 72_Hz;
- EXPECT_EQ(asRefreshRate(kMode72), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode72, configs.getBestRefreshRate(layers));
explicitExactLayer.desiredRefreshRate = 90_Hz;
- EXPECT_EQ(asRefreshRate(kMode90), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode90, configs.getBestRefreshRate(layers));
explicitExactLayer.desiredRefreshRate = 120_Hz;
- EXPECT_EQ(asRefreshRate(kMode120), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode120, configs.getBestRefreshRate(layers));
}
TEST_F(RefreshRateConfigsTest, getBestRefreshRate_ReadsCache) {
@@ -1697,7 +1676,7 @@
using GlobalSignals = RefreshRateConfigs::GlobalSignals;
const auto args = std::make_pair(std::vector<LayerRequirement>{},
GlobalSignals{.touch = true, .idle = true});
- const auto result = std::make_pair(asRefreshRate(kMode90), GlobalSignals{.touch = true});
+ const auto result = std::make_pair(kMode90, GlobalSignals{.touch = true});
configs.mutableGetBestRefreshRateCache() = {args, result};
@@ -1736,13 +1715,13 @@
explicitExactLayer.name = "ExplicitExact";
explicitExactLayer.desiredRefreshRate = 30_Hz;
- EXPECT_EQ(asRefreshRate(kMode60), configs.getBestRefreshRate(layers));
- EXPECT_EQ(asRefreshRate(kMode120), configs.getBestRefreshRate(layers, {.touch = true}));
+ EXPECT_EQ(kMode60, configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode120, configs.getBestRefreshRate(layers, {.touch = true}));
explicitExactOrMultipleLayer.vote = LayerVoteType::NoVote;
- EXPECT_EQ(asRefreshRate(kMode60), configs.getBestRefreshRate(layers));
- EXPECT_EQ(asRefreshRate(kMode60), configs.getBestRefreshRate(layers, {.touch = true}));
+ EXPECT_EQ(kMode60, configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode60, configs.getBestRefreshRate(layers, {.touch = true}));
}
TEST_F(RefreshRateConfigsTest, getBestRefreshRate_FractionalRefreshRates_ExactAndDefault) {
@@ -1761,7 +1740,7 @@
explicitDefaultLayer.name = "ExplicitDefault";
explicitDefaultLayer.desiredRefreshRate = 59.94_Hz;
- EXPECT_EQ(asRefreshRate(kMode60), configs.getBestRefreshRate(layers));
+ EXPECT_EQ(kMode60, configs.getBestRefreshRate(layers));
}
// b/190578904
@@ -1771,17 +1750,20 @@
DisplayModes displayModes;
for (int fps = kMinRefreshRate; fps < kMaxRefreshRate; fps++) {
- displayModes.push_back(
- createDisplayMode(DisplayModeId(fps), Fps::fromValue(static_cast<float>(fps))));
+ const DisplayModeId modeId(fps);
+ displayModes.try_emplace(modeId,
+ createDisplayMode(modeId,
+ Fps::fromValue(static_cast<float>(fps))));
}
- const TestableRefreshRateConfigs configs(displayModes, displayModes[0]->getId());
+ const TestableRefreshRateConfigs configs(std::move(displayModes),
+ DisplayModeId(kMinRefreshRate));
std::vector<LayerRequirement> layers = {{.weight = 1.f}};
const auto testRefreshRate = [&](Fps fps, LayerVoteType vote) {
layers[0].desiredRefreshRate = fps;
layers[0].vote = vote;
- EXPECT_EQ(fps.getIntValue(), configs.getBestRefreshRate(layers).getFps().getIntValue())
+ EXPECT_EQ(fps.getIntValue(), configs.getBestRefreshRate(layers)->getFps().getIntValue())
<< "Failed for " << ftl::enum_string(vote);
};
@@ -1796,15 +1778,14 @@
// b/190578904
TEST_F(RefreshRateConfigsTest, getBestRefreshRate_conflictingVotes) {
- const DisplayModes displayModes = {
- createDisplayMode(DisplayModeId(0), 43_Hz),
- createDisplayMode(DisplayModeId(1), 53_Hz),
- createDisplayMode(DisplayModeId(2), 55_Hz),
- createDisplayMode(DisplayModeId(3), 60_Hz),
- };
+ constexpr DisplayModeId kActiveModeId{0};
+ DisplayModes displayModes = makeModes(createDisplayMode(kActiveModeId, 43_Hz),
+ createDisplayMode(DisplayModeId(1), 53_Hz),
+ createDisplayMode(DisplayModeId(2), 55_Hz),
+ createDisplayMode(DisplayModeId(3), 60_Hz));
const RefreshRateConfigs::GlobalSignals globalSignals = {.touch = false, .idle = false};
- const TestableRefreshRateConfigs configs(displayModes, displayModes[0]->getId());
+ const TestableRefreshRateConfigs configs(std::move(displayModes), kActiveModeId);
const std::vector<LayerRequirement> layers = {
{
@@ -1821,13 +1802,13 @@
},
};
- EXPECT_EQ(53_Hz, configs.getBestRefreshRate(layers, globalSignals).getFps());
+ EXPECT_EQ(53_Hz, configs.getBestRefreshRate(layers, globalSignals)->getFps());
}
-TEST_F(RefreshRateConfigsTest, testComparisonOperator) {
- EXPECT_TRUE(asRefreshRate(kMode60) < asRefreshRate(kMode90));
- EXPECT_FALSE(asRefreshRate(kMode60) < asRefreshRate(kMode60));
- EXPECT_FALSE(asRefreshRate(kMode90) < asRefreshRate(kMode90));
+TEST_F(RefreshRateConfigsTest, modeComparison) {
+ EXPECT_LT(kMode60->getFps(), kMode90->getFps());
+ EXPECT_GE(kMode60->getFps(), kMode60->getFps());
+ EXPECT_GE(kMode90->getFps(), kMode90->getFps());
}
TEST_F(RefreshRateConfigsTest, testKernelIdleTimerAction) {
@@ -1877,27 +1858,27 @@
RefreshRateConfigs configs(kModes_30_60_72_90_120, kModeId30);
const auto frameRate = 30_Hz;
- Fps displayRefreshRate = configs.getCurrentRefreshRate().getFps();
+ Fps displayRefreshRate = configs.getActiveMode()->getFps();
EXPECT_EQ(1, RefreshRateConfigs::getFrameRateDivisor(displayRefreshRate, frameRate));
- configs.setCurrentModeId(kModeId60);
- displayRefreshRate = configs.getCurrentRefreshRate().getFps();
+ configs.setActiveModeId(kModeId60);
+ displayRefreshRate = configs.getActiveMode()->getFps();
EXPECT_EQ(2, RefreshRateConfigs::getFrameRateDivisor(displayRefreshRate, frameRate));
- configs.setCurrentModeId(kModeId72);
- displayRefreshRate = configs.getCurrentRefreshRate().getFps();
+ configs.setActiveModeId(kModeId72);
+ displayRefreshRate = configs.getActiveMode()->getFps();
EXPECT_EQ(0, RefreshRateConfigs::getFrameRateDivisor(displayRefreshRate, frameRate));
- configs.setCurrentModeId(kModeId90);
- displayRefreshRate = configs.getCurrentRefreshRate().getFps();
+ configs.setActiveModeId(kModeId90);
+ displayRefreshRate = configs.getActiveMode()->getFps();
EXPECT_EQ(3, RefreshRateConfigs::getFrameRateDivisor(displayRefreshRate, frameRate));
- configs.setCurrentModeId(kModeId120);
- displayRefreshRate = configs.getCurrentRefreshRate().getFps();
+ configs.setActiveModeId(kModeId120);
+ displayRefreshRate = configs.getActiveMode()->getFps();
EXPECT_EQ(4, RefreshRateConfigs::getFrameRateDivisor(displayRefreshRate, frameRate));
- configs.setCurrentModeId(kModeId90);
- displayRefreshRate = configs.getCurrentRefreshRate().getFps();
+ configs.setActiveModeId(kModeId90);
+ displayRefreshRate = configs.getActiveMode()->getFps();
EXPECT_EQ(4, RefreshRateConfigs::getFrameRateDivisor(displayRefreshRate, 22.5_Hz));
EXPECT_EQ(0, RefreshRateConfigs::getFrameRateDivisor(24_Hz, 25_Hz));
diff --git a/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp
index df4a9c4..e2e3d7b 100644
--- a/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp
+++ b/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp
@@ -21,8 +21,6 @@
#include <log/log.h>
#include <thread>
-#include "DisplayHardware/DisplayMode.h"
-#include "Scheduler/RefreshRateConfigs.h"
#include "Scheduler/RefreshRateStats.h"
#include "mock/MockTimeStats.h"
@@ -35,29 +33,15 @@
class RefreshRateStatsTest : public testing::Test {
protected:
- static inline const auto CONFIG_ID_0 = DisplayModeId(0);
- static inline const auto CONFIG_ID_1 = DisplayModeId(1);
- static inline const auto CONFIG_GROUP_0 = 0;
- static constexpr int64_t VSYNC_90 = 11111111;
- static constexpr int64_t VSYNC_60 = 16666667;
-
RefreshRateStatsTest();
~RefreshRateStatsTest();
- void init(const DisplayModes& configs) {
- mRefreshRateConfigs =
- std::make_unique<RefreshRateConfigs>(configs, /*currentConfig=*/CONFIG_ID_0);
-
- const auto currFps = mRefreshRateConfigs->getRefreshRateFromModeId(CONFIG_ID_0).getFps();
- mRefreshRateStats = std::make_unique<RefreshRateStats>(mTimeStats, currFps,
- /*currentPowerMode=*/PowerMode::OFF);
+ void resetStats(Fps fps) {
+ mRefreshRateStats = std::make_unique<RefreshRateStats>(mTimeStats, fps, PowerMode::OFF);
}
mock::TimeStats mTimeStats;
- std::unique_ptr<RefreshRateConfigs> mRefreshRateConfigs;
std::unique_ptr<RefreshRateStats> mRefreshRateStats;
-
- DisplayModePtr createDisplayMode(DisplayModeId modeId, int32_t group, int64_t vsyncPeriod);
};
RefreshRateStatsTest::RefreshRateStatsTest() {
@@ -72,20 +56,10 @@
ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name());
}
-DisplayModePtr RefreshRateStatsTest::createDisplayMode(DisplayModeId modeId, int32_t group,
- int64_t vsyncPeriod) {
- return DisplayMode::Builder(static_cast<hal::HWConfigId>(modeId.value()))
- .setId(modeId)
- .setPhysicalDisplayId(PhysicalDisplayId::fromPort(0))
- .setVsyncPeriod(static_cast<int32_t>(vsyncPeriod))
- .setGroup(group)
- .build();
-}
-
namespace {
-TEST_F(RefreshRateStatsTest, oneConfigTest) {
- init({createDisplayMode(CONFIG_ID_0, CONFIG_GROUP_0, VSYNC_90)});
+TEST_F(RefreshRateStatsTest, oneMode) {
+ resetStats(90_Hz);
EXPECT_CALL(mTimeStats, recordRefreshRate(0, _)).Times(AtLeast(1));
EXPECT_CALL(mTimeStats, recordRefreshRate(90, _)).Times(AtLeast(1));
@@ -102,8 +76,7 @@
EXPECT_LT(screenOff, times.get("ScreenOff")->get());
EXPECT_FALSE(times.contains("90.00 Hz"));
- const auto config0Fps = mRefreshRateConfigs->getRefreshRateFromModeId(CONFIG_ID_0).getFps();
- mRefreshRateStats->setRefreshRate(config0Fps);
+ mRefreshRateStats->setRefreshRate(90_Hz);
mRefreshRateStats->setPowerMode(PowerMode::ON);
screenOff = mRefreshRateStats->getTotalTimes().get("ScreenOff")->get();
std::this_thread::sleep_for(std::chrono::milliseconds(2));
@@ -121,20 +94,18 @@
EXPECT_LT(screenOff, times.get("ScreenOff")->get());
EXPECT_EQ(ninety, times.get("90.00 Hz")->get());
- mRefreshRateStats->setRefreshRate(config0Fps);
+ mRefreshRateStats->setRefreshRate(90_Hz);
screenOff = mRefreshRateStats->getTotalTimes().get("ScreenOff")->get();
std::this_thread::sleep_for(std::chrono::milliseconds(2));
times = mRefreshRateStats->getTotalTimes();
- // Because the power mode is not PowerMode::ON, switching the config
- // does not update refresh rates that come from the config.
+ // Stats are not updated while the screen is off.
EXPECT_LT(screenOff, times.get("ScreenOff")->get());
EXPECT_EQ(ninety, times.get("90.00 Hz")->get());
}
-TEST_F(RefreshRateStatsTest, twoConfigsTest) {
- init({createDisplayMode(CONFIG_ID_0, CONFIG_GROUP_0, VSYNC_90),
- createDisplayMode(CONFIG_ID_1, CONFIG_GROUP_0, VSYNC_60)});
+TEST_F(RefreshRateStatsTest, twoModes) {
+ resetStats(90_Hz);
EXPECT_CALL(mTimeStats, recordRefreshRate(0, _)).Times(AtLeast(1));
EXPECT_CALL(mTimeStats, recordRefreshRate(60, _)).Times(AtLeast(1));
@@ -153,9 +124,7 @@
EXPECT_FALSE(times.contains("60.00 Hz"));
EXPECT_FALSE(times.contains("90.00 Hz"));
- const auto config0Fps = mRefreshRateConfigs->getRefreshRateFromModeId(CONFIG_ID_0).getFps();
- const auto config1Fps = mRefreshRateConfigs->getRefreshRateFromModeId(CONFIG_ID_1).getFps();
- mRefreshRateStats->setRefreshRate(config0Fps);
+ mRefreshRateStats->setRefreshRate(90_Hz);
mRefreshRateStats->setPowerMode(PowerMode::ON);
screenOff = mRefreshRateStats->getTotalTimes().get("ScreenOff")->get();
std::this_thread::sleep_for(std::chrono::milliseconds(2));
@@ -165,8 +134,7 @@
ASSERT_TRUE(times.contains("90.00 Hz"));
EXPECT_LT(0ms, times.get("90.00 Hz")->get());
- // When power mode is normal, time for configs updates.
- mRefreshRateStats->setRefreshRate(config1Fps);
+ mRefreshRateStats->setRefreshRate(60_Hz);
auto ninety = mRefreshRateStats->getTotalTimes().get("90.00 Hz")->get();
std::this_thread::sleep_for(std::chrono::milliseconds(2));
times = mRefreshRateStats->getTotalTimes();
@@ -176,7 +144,7 @@
ASSERT_TRUE(times.contains("60.00 Hz"));
EXPECT_LT(0ms, times.get("60.00 Hz")->get());
- mRefreshRateStats->setRefreshRate(config0Fps);
+ mRefreshRateStats->setRefreshRate(90_Hz);
auto sixty = mRefreshRateStats->getTotalTimes().get("60.00 Hz")->get();
std::this_thread::sleep_for(std::chrono::milliseconds(2));
times = mRefreshRateStats->getTotalTimes();
@@ -185,7 +153,7 @@
EXPECT_LT(ninety, times.get("90.00 Hz")->get());
EXPECT_EQ(sixty, times.get("60.00 Hz")->get());
- mRefreshRateStats->setRefreshRate(config1Fps);
+ mRefreshRateStats->setRefreshRate(60_Hz);
ninety = mRefreshRateStats->getTotalTimes().get("90.00 Hz")->get();
std::this_thread::sleep_for(std::chrono::milliseconds(2));
times = mRefreshRateStats->getTotalTimes();
@@ -194,10 +162,9 @@
EXPECT_EQ(ninety, times.get("90.00 Hz")->get());
EXPECT_LT(sixty, times.get("60.00 Hz")->get());
- // Because the power mode is not PowerMode::ON, switching the config
- // does not update refresh rates that come from the config.
+ // Stats are not updated while the screen is off.
mRefreshRateStats->setPowerMode(PowerMode::DOZE);
- mRefreshRateStats->setRefreshRate(config0Fps);
+ mRefreshRateStats->setRefreshRate(90_Hz);
sixty = mRefreshRateStats->getTotalTimes().get("60.00 Hz")->get();
std::this_thread::sleep_for(std::chrono::milliseconds(2));
times = mRefreshRateStats->getTotalTimes();
@@ -206,7 +173,7 @@
EXPECT_EQ(ninety, times.get("90.00 Hz")->get());
EXPECT_EQ(sixty, times.get("60.00 Hz")->get());
- mRefreshRateStats->setRefreshRate(config1Fps);
+ mRefreshRateStats->setRefreshRate(60_Hz);
screenOff = mRefreshRateStats->getTotalTimes().get("ScreenOff")->get();
std::this_thread::sleep_for(std::chrono::milliseconds(2));
times = mRefreshRateStats->getTotalTimes();
diff --git a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
index a992a91..aab2795 100644
--- a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
@@ -24,12 +24,15 @@
#include "Scheduler/RefreshRateConfigs.h"
#include "TestableScheduler.h"
#include "TestableSurfaceFlinger.h"
+#include "mock/DisplayHardware/MockDisplayMode.h"
#include "mock/MockEventThread.h"
#include "mock/MockLayer.h"
#include "mock/MockSchedulerCallback.h"
namespace android::scheduler {
+using android::mock::createDisplayMode;
+
using testing::_;
using testing::Return;
@@ -55,21 +58,11 @@
SchedulerTest();
- const DisplayModePtr mode60 = DisplayMode::Builder(0)
- .setId(DisplayModeId(0))
- .setPhysicalDisplayId(PhysicalDisplayId::fromPort(0))
- .setVsyncPeriod((60_Hz).getPeriodNsecs())
- .setGroup(0)
- .build();
- const DisplayModePtr mode120 = DisplayMode::Builder(1)
- .setId(DisplayModeId(1))
- .setPhysicalDisplayId(PhysicalDisplayId::fromPort(0))
- .setVsyncPeriod((120_Hz).getPeriodNsecs())
- .setGroup(0)
- .build();
+ static inline const DisplayModePtr kMode60 = createDisplayMode(DisplayModeId(0), 60_Hz);
+ static inline const DisplayModePtr kMode120 = createDisplayMode(DisplayModeId(1), 120_Hz);
std::shared_ptr<RefreshRateConfigs> mConfigs =
- std::make_shared<RefreshRateConfigs>(DisplayModes{mode60}, mode60->getId());
+ std::make_shared<RefreshRateConfigs>(makeModes(kMode60), kMode60->getId());
mock::SchedulerCallback mSchedulerCallback;
TestableScheduler* mScheduler = new TestableScheduler{mConfigs, mSchedulerCallback};
@@ -172,7 +165,7 @@
constexpr uint32_t kDisplayArea = 999'999;
mScheduler->onActiveDisplayAreaChanged(kDisplayArea);
- EXPECT_CALL(mSchedulerCallback, changeRefreshRate(_, _)).Times(0);
+ EXPECT_CALL(mSchedulerCallback, requestDisplayMode(_, _)).Times(0);
mScheduler->chooseRefreshRateForContent();
}
@@ -182,7 +175,7 @@
ASSERT_EQ(1u, mScheduler->layerHistorySize());
mScheduler->setRefreshRateConfigs(
- std::make_shared<RefreshRateConfigs>(DisplayModes{mode60, mode120}, mode60->getId()));
+ std::make_shared<RefreshRateConfigs>(makeModes(kMode60, kMode120), kMode60->getId()));
ASSERT_EQ(0u, mScheduler->getNumActiveLayers());
mScheduler->recordLayerHistory(layer.get(), 0, LayerHistory::LayerUpdateType::Buffer);
@@ -221,12 +214,12 @@
}
MATCHER(Is120Hz, "") {
- return isApproxEqual(arg.getFps(), 120_Hz);
+ return isApproxEqual(arg->getFps(), 120_Hz);
}
TEST_F(SchedulerTest, chooseRefreshRateForContentSelectsMaxRefreshRate) {
mScheduler->setRefreshRateConfigs(
- std::make_shared<RefreshRateConfigs>(DisplayModes{mode60, mode120}, mode60->getId()));
+ std::make_shared<RefreshRateConfigs>(makeModes(kMode60, kMode120), kMode60->getId()));
const sp<MockLayer> layer = sp<MockLayer>::make(mFlinger.flinger());
EXPECT_CALL(*layer, isVisible()).WillOnce(Return(true));
@@ -239,11 +232,11 @@
constexpr uint32_t kDisplayArea = 999'999;
mScheduler->onActiveDisplayAreaChanged(kDisplayArea);
- EXPECT_CALL(mSchedulerCallback, changeRefreshRate(Is120Hz(), _)).Times(1);
+ EXPECT_CALL(mSchedulerCallback, requestDisplayMode(Is120Hz(), _)).Times(1);
mScheduler->chooseRefreshRateForContent();
// No-op if layer requirements have not changed.
- EXPECT_CALL(mSchedulerCallback, changeRefreshRate(_, _)).Times(0);
+ EXPECT_CALL(mSchedulerCallback, requestDisplayMode(_, _)).Times(0);
mScheduler->chooseRefreshRateForContent();
}
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayModeSwitching.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayModeSwitching.cpp
index 3205952..32d57b5 100644
--- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayModeSwitching.cpp
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayModeSwitching.cpp
@@ -43,13 +43,11 @@
mFlinger.onComposerHalHotplug(PrimaryDisplayVariant::HWC_DISPLAY_ID, Connection::CONNECTED);
{
- DisplayModes modes = {kDisplayMode60, kDisplayMode90, kDisplayMode120,
- kDisplayMode90DifferentResolution};
- const DisplayModeId activeModeId = kDisplayModeId60;
- auto configs = std::make_shared<scheduler::RefreshRateConfigs>(modes, activeModeId);
+ DisplayModes modes = makeModes(kMode60, kMode90, kMode120, kMode90_4K);
+ auto configs = std::make_shared<scheduler::RefreshRateConfigs>(modes, kModeId60);
mDisplay = PrimaryDisplayVariant::makeFakeExistingDisplayInjector(this)
- .setDisplayModes(modes, activeModeId, std::move(configs))
+ .setDisplayModes(std::move(modes), kModeId60, std::move(configs))
.inject();
}
@@ -68,49 +66,18 @@
sp<DisplayDevice> mDisplay;
mock::EventThread* mAppEventThread;
- const DisplayModeId kDisplayModeId60 = DisplayModeId(0);
- const DisplayModePtr kDisplayMode60 =
- DisplayMode::Builder(hal::HWConfigId(kDisplayModeId60.value()))
- .setId(kDisplayModeId60)
- .setPhysicalDisplayId(PrimaryDisplayVariant::DISPLAY_ID::get())
- .setVsyncPeriod((60_Hz).getPeriodNsecs())
- .setGroup(0)
- .setHeight(1000)
- .setWidth(1000)
- .build();
+ static constexpr DisplayModeId kModeId60{0};
+ static constexpr DisplayModeId kModeId90{1};
+ static constexpr DisplayModeId kModeId120{2};
+ static constexpr DisplayModeId kModeId90_4K{3};
- const DisplayModeId kDisplayModeId90 = DisplayModeId(1);
- const DisplayModePtr kDisplayMode90 =
- DisplayMode::Builder(hal::HWConfigId(kDisplayModeId90.value()))
- .setId(kDisplayModeId90)
- .setPhysicalDisplayId(PrimaryDisplayVariant::DISPLAY_ID::get())
- .setVsyncPeriod((90_Hz).getPeriodNsecs())
- .setGroup(1)
- .setHeight(1000)
- .setWidth(1000)
- .build();
+ static inline const DisplayModePtr kMode60 = createDisplayMode(kModeId60, 60_Hz, 0);
+ static inline const DisplayModePtr kMode90 = createDisplayMode(kModeId90, 90_Hz, 1);
+ static inline const DisplayModePtr kMode120 = createDisplayMode(kModeId120, 120_Hz, 2);
- const DisplayModeId kDisplayModeId120 = DisplayModeId(2);
- const DisplayModePtr kDisplayMode120 =
- DisplayMode::Builder(hal::HWConfigId(kDisplayModeId120.value()))
- .setId(kDisplayModeId120)
- .setPhysicalDisplayId(PrimaryDisplayVariant::DISPLAY_ID::get())
- .setVsyncPeriod((120_Hz).getPeriodNsecs())
- .setGroup(2)
- .setHeight(1000)
- .setWidth(1000)
- .build();
-
- const DisplayModeId kDisplayModeId90DifferentResolution = DisplayModeId(3);
- const DisplayModePtr kDisplayMode90DifferentResolution =
- DisplayMode::Builder(hal::HWConfigId(kDisplayModeId90DifferentResolution.value()))
- .setId(kDisplayModeId90DifferentResolution)
- .setPhysicalDisplayId(PrimaryDisplayVariant::DISPLAY_ID::get())
- .setVsyncPeriod((90_Hz).getPeriodNsecs())
- .setGroup(3)
- .setHeight(2000)
- .setWidth(2000)
- .build();
+ static constexpr ui::Size kResolution4K{3840, 2160};
+ static inline const DisplayModePtr kMode90_4K =
+ createDisplayMode(kModeId90_4K, 90_Hz, 3, kResolution4K);
};
void DisplayModeSwitchingTest::setupScheduler(
@@ -145,39 +112,39 @@
TEST_F(DisplayModeSwitchingTest, changeRefreshRate_OnActiveDisplay_WithRefreshRequired) {
ASSERT_FALSE(mDisplay->getDesiredActiveMode().has_value());
- ASSERT_EQ(mDisplay->getActiveMode()->getId(), kDisplayModeId60);
+ ASSERT_EQ(mDisplay->getActiveMode()->getId(), kModeId60);
mFlinger.onActiveDisplayChanged(mDisplay);
- mFlinger.setDesiredDisplayModeSpecs(mDisplay->getDisplayToken().promote(),
- kDisplayModeId90.value(), false, 0.f, 120.f, 0.f, 120.f);
+ mFlinger.setDesiredDisplayModeSpecs(mDisplay->getDisplayToken().promote(), kModeId90.value(),
+ false, 0.f, 120.f, 0.f, 120.f);
ASSERT_TRUE(mDisplay->getDesiredActiveMode().has_value());
- ASSERT_EQ(mDisplay->getDesiredActiveMode()->mode->getId(), kDisplayModeId90);
- ASSERT_EQ(mDisplay->getActiveMode()->getId(), kDisplayModeId60);
+ ASSERT_EQ(mDisplay->getDesiredActiveMode()->mode->getId(), kModeId90);
+ ASSERT_EQ(mDisplay->getActiveMode()->getId(), kModeId60);
// Verify that next commit will call setActiveConfigWithConstraints in HWC
const VsyncPeriodChangeTimeline timeline{.refreshRequired = true};
EXPECT_CALL(*mComposer,
setActiveConfigWithConstraints(PrimaryDisplayVariant::HWC_DISPLAY_ID,
- hal::HWConfigId(kDisplayModeId90.value()), _, _))
+ hal::HWConfigId(kModeId90.value()), _, _))
.WillOnce(DoAll(SetArgPointee<3>(timeline), Return(Error::NONE)));
mFlinger.commit();
Mock::VerifyAndClearExpectations(mComposer);
ASSERT_TRUE(mDisplay->getDesiredActiveMode().has_value());
- ASSERT_EQ(mDisplay->getActiveMode()->getId(), kDisplayModeId60);
+ ASSERT_EQ(mDisplay->getActiveMode()->getId(), kModeId60);
// Verify that the next commit will complete the mode change and send
// a onModeChanged event to the framework.
- EXPECT_CALL(*mAppEventThread, onModeChanged(kDisplayMode90));
+ EXPECT_CALL(*mAppEventThread, onModeChanged(kMode90));
mFlinger.commit();
Mock::VerifyAndClearExpectations(mAppEventThread);
ASSERT_FALSE(mDisplay->getDesiredActiveMode().has_value());
- ASSERT_EQ(mDisplay->getActiveMode()->getId(), kDisplayModeId90);
+ ASSERT_EQ(mDisplay->getActiveMode()->getId(), kModeId90);
}
TEST_F(DisplayModeSwitchingTest, changeRefreshRate_OnActiveDisplay_WithoutRefreshRequired) {
@@ -185,27 +152,27 @@
mFlinger.onActiveDisplayChanged(mDisplay);
- mFlinger.setDesiredDisplayModeSpecs(mDisplay->getDisplayToken().promote(),
- kDisplayModeId90.value(), true, 0.f, 120.f, 0.f, 120.f);
+ mFlinger.setDesiredDisplayModeSpecs(mDisplay->getDisplayToken().promote(), kModeId90.value(),
+ true, 0.f, 120.f, 0.f, 120.f);
ASSERT_TRUE(mDisplay->getDesiredActiveMode().has_value());
- ASSERT_EQ(mDisplay->getDesiredActiveMode()->mode->getId(), kDisplayModeId90);
- ASSERT_EQ(mDisplay->getActiveMode()->getId(), kDisplayModeId60);
+ ASSERT_EQ(mDisplay->getDesiredActiveMode()->mode->getId(), kModeId90);
+ ASSERT_EQ(mDisplay->getActiveMode()->getId(), kModeId60);
// Verify that next commit will call setActiveConfigWithConstraints in HWC
// and complete the mode change.
const VsyncPeriodChangeTimeline timeline{.refreshRequired = false};
EXPECT_CALL(*mComposer,
setActiveConfigWithConstraints(PrimaryDisplayVariant::HWC_DISPLAY_ID,
- hal::HWConfigId(kDisplayModeId90.value()), _, _))
+ hal::HWConfigId(kModeId90.value()), _, _))
.WillOnce(DoAll(SetArgPointee<3>(timeline), Return(Error::NONE)));
- EXPECT_CALL(*mAppEventThread, onModeChanged(kDisplayMode90));
+ EXPECT_CALL(*mAppEventThread, onModeChanged(kMode90));
mFlinger.commit();
ASSERT_FALSE(mDisplay->getDesiredActiveMode().has_value());
- ASSERT_EQ(mDisplay->getActiveMode()->getId(), kDisplayModeId90);
+ ASSERT_EQ(mDisplay->getActiveMode()->getId(), kModeId90);
}
TEST_F(DisplayModeSwitchingTest, twoConsecutiveSetDesiredDisplayModeSpecs) {
@@ -213,72 +180,72 @@
// is still being processed the later call will be respected.
ASSERT_FALSE(mDisplay->getDesiredActiveMode().has_value());
- ASSERT_EQ(mDisplay->getActiveMode()->getId(), kDisplayModeId60);
+ ASSERT_EQ(mDisplay->getActiveMode()->getId(), kModeId60);
mFlinger.onActiveDisplayChanged(mDisplay);
- mFlinger.setDesiredDisplayModeSpecs(mDisplay->getDisplayToken().promote(),
- kDisplayModeId90.value(), false, 0.f, 120.f, 0.f, 120.f);
+ mFlinger.setDesiredDisplayModeSpecs(mDisplay->getDisplayToken().promote(), kModeId90.value(),
+ false, 0.f, 120.f, 0.f, 120.f);
const VsyncPeriodChangeTimeline timeline{.refreshRequired = true};
EXPECT_CALL(*mComposer,
setActiveConfigWithConstraints(PrimaryDisplayVariant::HWC_DISPLAY_ID,
- hal::HWConfigId(kDisplayModeId90.value()), _, _))
+ hal::HWConfigId(kModeId90.value()), _, _))
.WillOnce(DoAll(SetArgPointee<3>(timeline), Return(Error::NONE)));
mFlinger.commit();
- mFlinger.setDesiredDisplayModeSpecs(mDisplay->getDisplayToken().promote(),
- kDisplayModeId120.value(), false, 0.f, 180.f, 0.f, 180.f);
+ mFlinger.setDesiredDisplayModeSpecs(mDisplay->getDisplayToken().promote(), kModeId120.value(),
+ false, 0.f, 180.f, 0.f, 180.f);
ASSERT_TRUE(mDisplay->getDesiredActiveMode().has_value());
- ASSERT_EQ(mDisplay->getDesiredActiveMode()->mode->getId(), kDisplayModeId120);
+ ASSERT_EQ(mDisplay->getDesiredActiveMode()->mode->getId(), kModeId120);
EXPECT_CALL(*mComposer,
setActiveConfigWithConstraints(PrimaryDisplayVariant::HWC_DISPLAY_ID,
- hal::HWConfigId(kDisplayModeId120.value()), _, _))
+ hal::HWConfigId(kModeId120.value()), _, _))
.WillOnce(DoAll(SetArgPointee<3>(timeline), Return(Error::NONE)));
mFlinger.commit();
ASSERT_TRUE(mDisplay->getDesiredActiveMode().has_value());
- ASSERT_EQ(mDisplay->getDesiredActiveMode()->mode->getId(), kDisplayModeId120);
+ ASSERT_EQ(mDisplay->getDesiredActiveMode()->mode->getId(), kModeId120);
mFlinger.commit();
ASSERT_FALSE(mDisplay->getDesiredActiveMode().has_value());
- ASSERT_EQ(mDisplay->getActiveMode()->getId(), kDisplayModeId120);
+ ASSERT_EQ(mDisplay->getActiveMode()->getId(), kModeId120);
}
TEST_F(DisplayModeSwitchingTest, changeResolution_OnActiveDisplay_WithoutRefreshRequired) {
ASSERT_FALSE(mDisplay->getDesiredActiveMode().has_value());
- ASSERT_EQ(mDisplay->getActiveMode()->getId(), kDisplayModeId60);
+ ASSERT_EQ(mDisplay->getActiveMode()->getId(), kModeId60);
mFlinger.onActiveDisplayChanged(mDisplay);
- mFlinger.setDesiredDisplayModeSpecs(mDisplay->getDisplayToken().promote(),
- kDisplayModeId90DifferentResolution.value(), false, 0.f,
- 120.f, 0.f, 120.f);
+ mFlinger.setDesiredDisplayModeSpecs(mDisplay->getDisplayToken().promote(), kModeId90_4K.value(),
+ false, 0.f, 120.f, 0.f, 120.f);
ASSERT_TRUE(mDisplay->getDesiredActiveMode().has_value());
- ASSERT_EQ(mDisplay->getDesiredActiveMode()->mode->getId(), kDisplayModeId90DifferentResolution);
- ASSERT_EQ(mDisplay->getActiveMode()->getId(), kDisplayModeId60);
+ ASSERT_EQ(mDisplay->getDesiredActiveMode()->mode->getId(), kModeId90_4K);
+ ASSERT_EQ(mDisplay->getActiveMode()->getId(), kModeId60);
// Verify that next commit will call setActiveConfigWithConstraints in HWC
// and complete the mode change.
const VsyncPeriodChangeTimeline timeline{.refreshRequired = false};
EXPECT_CALL(*mComposer,
setActiveConfigWithConstraints(PrimaryDisplayVariant::HWC_DISPLAY_ID,
- hal::HWConfigId(
- kDisplayModeId90DifferentResolution.value()),
- _, _))
+ hal::HWConfigId(kModeId90_4K.value()), _, _))
.WillOnce(DoAll(SetArgPointee<3>(timeline), Return(Error::NONE)));
EXPECT_CALL(*mAppEventThread, onHotplugReceived(mDisplay->getPhysicalId(), true));
// Misc expecations. We don't need to enforce these method calls, but since the helper methods
// already set expectations we should add new ones here, otherwise the test will fail.
- EXPECT_CALL(*mConsumer, setDefaultBufferSize(2000, 2000)).WillOnce(Return(NO_ERROR));
+ EXPECT_CALL(*mConsumer,
+ setDefaultBufferSize(static_cast<uint32_t>(kResolution4K.getWidth()),
+ static_cast<uint32_t>(kResolution4K.getHeight())))
+ .WillOnce(Return(NO_ERROR));
EXPECT_CALL(*mConsumer, consumerConnect(_, false)).WillOnce(Return(NO_ERROR));
EXPECT_CALL(*mComposer, setClientTargetSlotCount(_)).WillOnce(Return(hal::Error::NONE));
@@ -296,7 +263,7 @@
mDisplay = mFlinger.getDisplay(displayToken);
ASSERT_FALSE(mDisplay->getDesiredActiveMode().has_value());
- ASSERT_EQ(mDisplay->getActiveMode()->getId(), kDisplayModeId90DifferentResolution);
+ ASSERT_EQ(mDisplay->getActiveMode()->getId(), kModeId90_4K);
}
} // namespace
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetupNewDisplayDeviceInternalTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetupNewDisplayDeviceInternalTest.cpp
index 38dceb9..a0e078b 100644
--- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetupNewDisplayDeviceInternalTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetupNewDisplayDeviceInternalTest.cpp
@@ -240,19 +240,17 @@
ASSERT_TRUE(hwcDisplayId);
mFlinger.getHwComposer().allocatePhysicalDisplay(*hwcDisplayId, *displayId);
DisplayModePtr activeMode = DisplayMode::Builder(Case::Display::HWC_ACTIVE_CONFIG_ID)
- .setWidth(Case::Display::WIDTH)
- .setHeight(Case::Display::HEIGHT)
+ .setResolution(Case::Display::RESOLUTION)
.setVsyncPeriod(DEFAULT_VSYNC_PERIOD)
.setDpiX(DEFAULT_DPI)
.setDpiY(DEFAULT_DPI)
.setGroup(0)
.build();
- DisplayModes modes{activeMode};
state.physical = {.id = *displayId,
.type = *connectionType,
.hwcDisplayId = *hwcDisplayId,
- .supportedModes = modes,
- .activeMode = activeMode};
+ .supportedModes = makeModes(activeMode),
+ .activeMode = std::move(activeMode)};
}
state.isSecure = static_cast<bool>(Case::Display::SECURE);
@@ -270,8 +268,7 @@
EXPECT_EQ(static_cast<bool>(Case::Display::VIRTUAL), device->isVirtual());
EXPECT_EQ(static_cast<bool>(Case::Display::SECURE), device->isSecure());
EXPECT_EQ(static_cast<bool>(Case::Display::PRIMARY), device->isPrimary());
- EXPECT_EQ(Case::Display::WIDTH, device->getWidth());
- EXPECT_EQ(Case::Display::HEIGHT, device->getHeight());
+ EXPECT_EQ(Case::Display::RESOLUTION, device->getSize());
EXPECT_EQ(Case::WideColorSupport::WIDE_COLOR_SUPPORTED, device->hasWideColorGamut());
EXPECT_EQ(Case::HdrSupport::HDR10_PLUS_SUPPORTED, device->hasHDR10PlusSupport());
EXPECT_EQ(Case::HdrSupport::HDR10_SUPPORTED, device->hasHDR10Support());
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index fe0564e..aff4d83 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -45,6 +45,7 @@
#include "SurfaceInterceptor.h"
#include "TestableScheduler.h"
#include "mock/DisplayHardware/MockComposer.h"
+#include "mock/DisplayHardware/MockDisplayMode.h"
#include "mock/MockFrameTimeline.h"
#include "mock/MockFrameTracer.h"
#include "mock/MockSchedulerCallback.h"
@@ -227,31 +228,24 @@
if (std::holds_alternative<RefreshRateConfigsPtr>(modesVariant)) {
configs = std::move(std::get<RefreshRateConfigsPtr>(modesVariant));
} else {
- DisplayModes modes = {DisplayMode::Builder(0)
- .setId(DisplayModeId(0))
- .setPhysicalDisplayId(PhysicalDisplayId::fromPort(0))
- .setVsyncPeriod(16'666'667)
- .setGroup(0)
- .build()};
+ constexpr DisplayModeId kModeId60{0};
+ DisplayModes modes = makeModes(mock::createDisplayMode(kModeId60, 60_Hz));
if (std::holds_alternative<TwoDisplayModes>(modesVariant)) {
- modes.emplace_back(DisplayMode::Builder(1)
- .setId(DisplayModeId(1))
- .setPhysicalDisplayId(PhysicalDisplayId::fromPort(0))
- .setVsyncPeriod(11'111'111)
- .setGroup(0)
- .build());
+ constexpr DisplayModeId kModeId90{1};
+ modes.try_emplace(kModeId90, mock::createDisplayMode(kModeId90, 90_Hz));
}
- configs = std::make_shared<scheduler::RefreshRateConfigs>(modes, DisplayModeId(0));
+ configs = std::make_shared<scheduler::RefreshRateConfigs>(modes, kModeId60);
}
- const auto currFps = configs->getCurrentRefreshRate().getFps();
- mFlinger->mVsyncConfiguration = mFactory.createVsyncConfiguration(currFps);
+ const auto fps = configs->getActiveMode()->getFps();
+ mFlinger->mVsyncConfiguration = mFactory.createVsyncConfiguration(fps);
mFlinger->mVsyncModulator = sp<scheduler::VsyncModulator>::make(
mFlinger->mVsyncConfiguration->getCurrentConfigs());
+
mFlinger->mRefreshRateStats =
- std::make_unique<scheduler::RefreshRateStats>(*mFlinger->mTimeStats, currFps,
+ std::make_unique<scheduler::RefreshRateStats>(*mFlinger->mTimeStats, fps,
hal::PowerMode::OFF);
using Callback = scheduler::ISchedulerCallback;
@@ -572,8 +566,7 @@
class FakeHwcDisplayInjector {
public:
static constexpr hal::HWDisplayId DEFAULT_HWC_DISPLAY_ID = 1000;
- static constexpr int32_t DEFAULT_WIDTH = 1920;
- static constexpr int32_t DEFAULT_HEIGHT = 1280;
+ static constexpr ui::Size DEFAULT_RESOLUTION{1920, 1280};
static constexpr int32_t DEFAULT_VSYNC_PERIOD = 16'666'667;
static constexpr int32_t DEFAULT_CONFIG_GROUP = 7;
static constexpr int32_t DEFAULT_DPI = 320;
@@ -589,17 +582,12 @@
return *this;
}
- auto& setWidth(int32_t width) {
- mWidth = width;
+ auto& setResolution(ui::Size resolution) {
+ mResolution = resolution;
return *this;
}
- auto& setHeight(int32_t height) {
- mHeight = height;
- return *this;
- }
-
- auto& setVsyncPeriod(int32_t vsyncPeriod) {
+ auto& setVsyncPeriod(nsecs_t vsyncPeriod) {
mVsyncPeriod = vsyncPeriod;
return *this;
}
@@ -660,18 +648,20 @@
EXPECT_CALL(*composer,
getDisplayAttribute(mHwcDisplayId, mActiveConfig, hal::Attribute::WIDTH, _))
- .WillRepeatedly(DoAll(SetArgPointee<3>(mWidth), Return(hal::Error::NONE)));
+ .WillRepeatedly(DoAll(SetArgPointee<3>(mResolution.getWidth()),
+ Return(hal::Error::NONE)));
EXPECT_CALL(*composer,
getDisplayAttribute(mHwcDisplayId, mActiveConfig, hal::Attribute::HEIGHT,
_))
- .WillRepeatedly(DoAll(SetArgPointee<3>(mHeight), Return(hal::Error::NONE)));
+ .WillRepeatedly(DoAll(SetArgPointee<3>(mResolution.getHeight()),
+ Return(hal::Error::NONE)));
EXPECT_CALL(*composer,
getDisplayAttribute(mHwcDisplayId, mActiveConfig,
hal::Attribute::VSYNC_PERIOD, _))
- .WillRepeatedly(
- DoAll(SetArgPointee<3>(mVsyncPeriod), Return(hal::Error::NONE)));
+ .WillRepeatedly(DoAll(SetArgPointee<3>(static_cast<int32_t>(mVsyncPeriod)),
+ Return(hal::Error::NONE)));
EXPECT_CALL(*composer,
getDisplayAttribute(mHwcDisplayId, mActiveConfig, hal::Attribute::DPI_X, _))
@@ -708,9 +698,8 @@
const bool mIsPrimary;
hal::HWDisplayId mHwcDisplayId = DEFAULT_HWC_DISPLAY_ID;
- int32_t mWidth = DEFAULT_WIDTH;
- int32_t mHeight = DEFAULT_HEIGHT;
- int32_t mVsyncPeriod = DEFAULT_VSYNC_PERIOD;
+ ui::Size mResolution = DEFAULT_RESOLUTION;
+ nsecs_t mVsyncPeriod = DEFAULT_VSYNC_PERIOD;
int32_t mDpiX = DEFAULT_DPI;
int32_t mDpiY = DEFAULT_DPI;
int32_t mConfigGroup = DEFAULT_CONFIG_GROUP;
@@ -723,12 +712,12 @@
class FakeDisplayDeviceInjector {
public:
FakeDisplayDeviceInjector(TestableSurfaceFlinger& flinger,
- std::shared_ptr<compositionengine::Display> compositionDisplay,
+ std::shared_ptr<compositionengine::Display> display,
std::optional<ui::DisplayConnectionType> connectionType,
std::optional<hal::HWDisplayId> hwcDisplayId, bool isPrimary)
: mFlinger(flinger),
mCreationArgs(flinger.mFlinger.get(), flinger.mFlinger->getHwComposer(),
- mDisplayToken, compositionDisplay),
+ mDisplayToken, display),
mHwcDisplayId(hwcDisplayId) {
mCreationArgs.connectionType = connectionType;
mCreationArgs.isPrimary = isPrimary;
@@ -805,49 +794,52 @@
}
sp<DisplayDevice> inject() NO_THREAD_SAFETY_ANALYSIS {
+ const auto displayId = mCreationArgs.compositionDisplay->getDisplayId();
+
auto& modes = mCreationArgs.supportedModes;
auto& activeModeId = mCreationArgs.activeModeId;
- if (!mCreationArgs.refreshRateConfigs) {
- if (modes.empty()) {
- activeModeId = DisplayModeId(0);
- modes.emplace_back(
- DisplayMode::Builder(FakeHwcDisplayInjector::DEFAULT_ACTIVE_CONFIG)
- .setId(activeModeId)
- .setPhysicalDisplayId(PhysicalDisplayId::fromPort(0))
- .setWidth(FakeHwcDisplayInjector::DEFAULT_WIDTH)
- .setHeight(FakeHwcDisplayInjector::DEFAULT_HEIGHT)
- .setVsyncPeriod(FakeHwcDisplayInjector::DEFAULT_VSYNC_PERIOD)
- .setDpiX(FakeHwcDisplayInjector::DEFAULT_DPI)
- .setDpiY(FakeHwcDisplayInjector::DEFAULT_DPI)
- .setGroup(0)
- .build());
- }
+ if (displayId && !mCreationArgs.refreshRateConfigs) {
+ if (const auto physicalId = PhysicalDisplayId::tryCast(*displayId)) {
+ if (modes.empty()) {
+ constexpr DisplayModeId kModeId{0};
+ DisplayModePtr mode =
+ DisplayMode::Builder(FakeHwcDisplayInjector::DEFAULT_ACTIVE_CONFIG)
+ .setId(kModeId)
+ .setPhysicalDisplayId(*physicalId)
+ .setResolution(FakeHwcDisplayInjector::DEFAULT_RESOLUTION)
+ .setVsyncPeriod(
+ FakeHwcDisplayInjector::DEFAULT_VSYNC_PERIOD)
+ .setDpiX(FakeHwcDisplayInjector::DEFAULT_DPI)
+ .setDpiY(FakeHwcDisplayInjector::DEFAULT_DPI)
+ .setGroup(FakeHwcDisplayInjector::DEFAULT_CONFIG_GROUP)
+ .build();
- mCreationArgs.refreshRateConfigs =
- std::make_shared<scheduler::RefreshRateConfigs>(modes, activeModeId);
+ modes = ftl::init::map(kModeId, std::move(mode));
+ activeModeId = kModeId;
+ }
+
+ mCreationArgs.refreshRateConfigs =
+ std::make_shared<scheduler::RefreshRateConfigs>(modes, activeModeId);
+ }
}
DisplayDeviceState state;
if (const auto type = mCreationArgs.connectionType) {
- const auto displayId = mCreationArgs.compositionDisplay->getDisplayId();
LOG_ALWAYS_FATAL_IF(!displayId);
const auto physicalId = PhysicalDisplayId::tryCast(*displayId);
LOG_ALWAYS_FATAL_IF(!physicalId);
LOG_ALWAYS_FATAL_IF(!mHwcDisplayId);
- const auto it = std::find_if(modes.begin(), modes.end(),
- [&activeModeId](const DisplayModePtr& mode) {
- return mode->getId() == activeModeId;
- });
- LOG_ALWAYS_FATAL_IF(it == modes.end());
+ const auto activeMode = modes.get(activeModeId);
+ LOG_ALWAYS_FATAL_IF(!activeMode);
state.physical = {.id = *physicalId,
.type = *type,
.hwcDisplayId = *mHwcDisplayId,
.deviceProductInfo = {},
.supportedModes = modes,
- .activeMode = *it};
+ .activeMode = activeMode->get()};
}
state.isSecure = mCreationArgs.isSecure;
diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockDisplayMode.h b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockDisplayMode.h
new file mode 100644
index 0000000..a83ecbc
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockDisplayMode.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "DisplayHardware/DisplayMode.h"
+
+namespace android::mock {
+
+inline DisplayModePtr createDisplayMode(
+ DisplayModeId modeId, Fps refreshRate, int32_t group = 0,
+ ui::Size resolution = ui::Size(1920, 1080),
+ PhysicalDisplayId displayId = PhysicalDisplayId::fromPort(0)) {
+ return DisplayMode::Builder(hal::HWConfigId(modeId.value()))
+ .setId(modeId)
+ .setPhysicalDisplayId(displayId)
+ .setVsyncPeriod(refreshRate.getPeriodNsecs())
+ .setGroup(group)
+ .setResolution(resolution)
+ .build();
+}
+
+} // namespace android::mock
diff --git a/services/surfaceflinger/tests/unittests/mock/MockSchedulerCallback.h b/services/surfaceflinger/tests/unittests/mock/MockSchedulerCallback.h
index c90b8ed..5083d56 100644
--- a/services/surfaceflinger/tests/unittests/mock/MockSchedulerCallback.h
+++ b/services/surfaceflinger/tests/unittests/mock/MockSchedulerCallback.h
@@ -25,7 +25,7 @@
struct SchedulerCallback final : ISchedulerCallback {
MOCK_METHOD(void, scheduleComposite, (FrameHint), (override));
MOCK_METHOD(void, setVsyncEnabled, (bool), (override));
- MOCK_METHOD(void, changeRefreshRate, (const RefreshRate&, DisplayModeEvent), (override));
+ MOCK_METHOD(void, requestDisplayMode, (DisplayModePtr, DisplayModeEvent), (override));
MOCK_METHOD(void, kernelTimerChanged, (bool), (override));
MOCK_METHOD(void, triggerOnFrameRateOverridesChanged, (), (override));
};
@@ -33,7 +33,7 @@
struct NoOpSchedulerCallback final : ISchedulerCallback {
void scheduleComposite(FrameHint) override {}
void setVsyncEnabled(bool) override {}
- void changeRefreshRate(const RefreshRate&, DisplayModeEvent) override {}
+ void requestDisplayMode(DisplayModePtr, DisplayModeEvent) override {}
void kernelTimerChanged(bool) override {}
void triggerOnFrameRateOverridesChanged() override {}
};