diff options
author | 2022-03-03 09:03:06 -0800 | |
---|---|---|
committer | 2022-03-15 14:40:44 -0700 | |
commit | b0054a2646e2031b9e55230f6e511e00171601f7 (patch) | |
tree | 9a12d9a61cadf61990158af8841f2689e3848496 | |
parent | 6c7b36e812413a8fb0ada8e287a648dcedfbb107 (diff) |
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
25 files changed, 1061 insertions, 1277 deletions
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index 0b23a5a5bb..635b0884d9 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -404,7 +404,7 @@ void BufferLayer::onPostComposition(const DisplayDevice* display, } 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 99335e59c0..f5a4b3d6ca 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -196,7 +196,7 @@ void DisplayDevice::setActiveMode(DisplayModeId id) { 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 @@ const DisplayModes& DisplayDevice::getSupportedModes() const { } 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 @@ void DisplayDevice::dump(std::string& result) const { 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 0ab9605fca..61a9a08a5c 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 @@ namespace hal = android::hardware::graphics::composer::hal; 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 @@ public: return *this; } - Builder& setWidth(int32_t width) { - mDisplayMode->mWidth = width; - return *this; - } - - Builder& setHeight(int32_t height) { - mDisplayMode->mHeight = height; + Builder& setResolution(ui::Size resolution) { + mDisplayMode->mResolution = resolution; 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 @@ public: // 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 65c8613c1b..3226f22027 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 @@ std::vector<Fps> constructKnownFrameRates(const DisplayModes& modes) { 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 @@ std::vector<Fps> constructKnownFrameRates(const DisplayModes& modes) { 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()); + + for (auto it = modes.begin(); it != modes.end(); ++it) { + const auto& [id, mode] = *it; -using AllRefreshRatesMapType = RefreshRateConfigs::AllRefreshRatesMapType; -using RefreshRate = RefreshRateConfigs::RefreshRate; + 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(); + }); -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()); + 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 @@ std::pair<nsecs_t, nsecs_t> RefreshRateConfigs::getDisplayFrames(nsecs_t layerPe 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 @@ bool RefreshRateConfigs::isVoteAllowed(const LayerRequirement& layer, 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 @@ float RefreshRateConfigs::calculateNonExactMatchingLayerScoreLocked( 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 @@ float RefreshRateConfigs::calculateNonExactMatchingLayerScoreLocked( 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 @@ float RefreshRateConfigs::calculateLayerScoreLocked(const LayerRequirement& laye // 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 @@ float RefreshRateConfigs::calculateLayerScoreLocked(const LayerRequirement& laye // 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 @@ float RefreshRateConfigs::calculateLayerScoreLocked(const LayerRequirement& laye 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::getBestRefreshRate(const std::vector<LayerRequirement>& 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 @@ auto RefreshRateConfigs::getBestRefreshRateLocked(const std::vector<LayerRequire 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 @@ auto RefreshRateConfigs::getBestRefreshRateLocked(const std::vector<LayerRequire 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 @@ auto RefreshRateConfigs::getBestRefreshRateLocked(const std::vector<LayerRequire 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 @@ auto RefreshRateConfigs::getBestRefreshRateLocked(const std::vector<LayerRequire !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 @@ auto RefreshRateConfigs::getBestRefreshRateLocked(const std::vector<LayerRequire // 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 @@ auto RefreshRateConfigs::getBestRefreshRateLocked(const std::vector<LayerRequire } 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 @@ auto RefreshRateConfigs::getBestRefreshRateLocked(const std::vector<LayerRequire // 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 @@ auto RefreshRateConfigs::getBestRefreshRateLocked(const std::vector<LayerRequire 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 @@ groupLayersByUid(const std::vector<RefreshRateConfigs::LayerRequirement>& layers 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 @@ RefreshRateConfigs::UidToFrameRateOverride RefreshRateConfigs::getFrameRateOverr continue; } - for (auto& score : scores) { - score.score = 0; + for (auto& [_, score] : scores) { + score = 0; } for (const auto& layer : layersWithSameUid) { @@ -536,137 +587,114 @@ RefreshRateConfigs::UidToFrameRateOverride RefreshRateConfigs::getFrameRateOverr 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()); -RefreshRate RefreshRateConfigs::getCurrentRefreshRate() const { - std::lock_guard lock(mLock); - return *mCurrentRefreshRate; + // Default to the highest refresh rate. + return mPrimaryRefreshRates.back()->second; } -RefreshRate RefreshRateConfigs::getCurrentRefreshRateByPolicy() const { +DisplayModePtr RefreshRateConfigs::getActiveMode() const { std::lock_guard lock(mLock); - return getCurrentRefreshRateByPolicyLocked(); + return mActiveModeIt->second; } -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::initializeIdleTimer() { } } -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()); + + const auto sortedModes = + sortByRefreshRate(mDisplayModes, [](const DisplayMode&) { return true; }); + mMinRefreshRateModeIt = sortedModes.front(); + mMaxRefreshRateModeIt = sortedModes.back(); - std::vector<const RefreshRate*> sortedModes; - getSortedRefreshRateListLocked([](const RefreshRate&) { return true; }, &sortedModes); // Reset the policy because the old one may no longer be valid. mDisplayManagerPolicy = {}; - mDisplayManagerPolicy.defaultMode = currentModeId; - mMinSupportedRefreshRate = sortedModes.front(); - mMaxSupportedRefreshRate = sortedModes.back(); - - 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; - } - } - } - } + mDisplayManagerPolicy.defaultMode = activeModeId; + + 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 @@ RefreshRateConfigs::Policy RefreshRateConfigs::getDisplayManagerPolicy() const { 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()); - - 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; - - 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); - - LOG_ALWAYS_FATAL_IF(outRefreshRates->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()); - }; + ALOGV("%s: %s ", __func__, policy->toString().c_str()); + + const auto& defaultMode = mDisplayModes.get(policy->defaultMode)->get(); + + 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()); + }; + + 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()); + + 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()); + + return modes; + }; - filterRefreshRates(policy->primaryRange, "primary", &mPrimaryRefreshRates); - filterRefreshRates(policy->appRequestRange, "app request", &mAppRequestRefreshRates); + mPrimaryRefreshRates = filterRefreshRates(policy->primaryRange, "primary"); + mAppRequestRefreshRates = filterRefreshRates(policy->appRequestRange, "app request"); } Fps RefreshRateConfigs::findClosestKnownFrameRate(Fps frameRate) const { @@ -893,36 +869,39 @@ Fps RefreshRateConfigs::findClosestKnownFrameRate(Fps frameRate) const { 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 @@ void RefreshRateConfigs::dump(std::string& result) const { 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 { + result.append("(platform) "); + } + + if (mIdleTimer) { + result.append(mIdleTimer->dump()); } else { - base::StringAppendF(&result, "(platform)"); + result.append("off"); } - base::StringAppendF(&result, " %s\n", mIdleTimer ? mIdleTimer->dump().c_str() : "off"); - result.append("\n"); + + result.append("\n\n"); } std::chrono::milliseconds RefreshRateConfigs::getIdleTimerTimeout() { diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h index 30d3edd05e..05a8692f51 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h +++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h @@ -56,50 +56,6 @@ public: 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 @@ public: // 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 @@ public: // 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); - - // 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); - }; + DisplayModePtr getMaxRefreshRateByPolicy() const EXCLUDES(mLock); - // 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 @@ public: std::optional<KernelIdleTimerController> kernelIdleTimerController; }; - RefreshRateConfigs(const DisplayModes&, DisplayModeId, + RefreshRateConfigs(DisplayModes, DisplayModeId activeModeId, Config config = {.enableFrameRateOverride = false, .frameRateMultipleThreshold = 0, .idleTimerTimeout = 0ms, @@ -305,7 +246,7 @@ public: // 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 @@ public: // 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 @@ private: 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 @@ private: : 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 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); + // 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 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); + DisplayModeIterator mActiveModeIt GUARDED_BY(mLock); + DisplayModeIterator mMinRefreshRateModeIt GUARDED_BY(mLock); + DisplayModeIterator mMaxRefreshRateModeIt 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); + // 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 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 @@ private: 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 f1ad75597a..ed65bc607d 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 @@ class RefreshRateStats { 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 @@ private: 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 @@ private: 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 1fa455aad0..74d77394af 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.cpp +++ b/services/surfaceflinger/Scheduler/Scheduler.cpp @@ -166,18 +166,15 @@ impl::EventThread::ThrottleVsyncCallback Scheduler::makeThrottleVsyncCallback() 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 @@ void Scheduler::dispatchCachedReportedMode() { // 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::disableHardwareVsync(bool makeUnavailable) { } } -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 @@ void Scheduler::resyncToHardwareVsync(bool makeAvailable, nsecs_t period) { } } - if (period <= 0) { - return; - } - - setVsyncPeriod(period); + setVsyncPeriod(refreshRate.getPeriodNsecs()); } void Scheduler::resync() { @@ -448,15 +441,17 @@ void Scheduler::resync() { 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 @@ void Scheduler::kernelIdleTimerCallback(TimerState state) { // 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 @@ auto Scheduler::applyPolicy(S Policy::*statePtr, T&& newState) -> GlobalSignals } } 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 @@ auto Scheduler::chooseDisplayMode() -> std::pair<DisplayModePtr, GlobalSignals> 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 f6c81c0ba2..a8113d423a 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.h +++ b/services/surfaceflinger/Scheduler/Scheduler.h @@ -86,12 +86,11 @@ struct ISchedulerCallback { // 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 @@ public: // 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 @@ public: 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 3186d6d399..4923031098 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 94b16b4821..0ee3121489 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1044,15 +1044,13 @@ status_t SurfaceFlinger::getDynamicDisplayInfo(const sp<IBinder>& displayToken, const auto& supportedModes = display->getSupportedModes(); info->supportedDisplayModes.clear(); info->supportedDisplayModes.reserve(supportedModes.size()); - for (const auto& mode : supportedModes) { - ui::DisplayMode outMode; - outMode.id = static_cast<int32_t>(mode->getId().value()); - auto width = mode->getWidth(); - auto height = mode->getHeight(); + for (const auto& [id, mode] : supportedModes) { + ui::DisplayMode outMode; + outMode.id = static_cast<int32_t>(id.value()); - 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 @@ void SurfaceFlinger::setDesiredActiveMode(const ActiveModeInfo& info) { // 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 @@ void SurfaceFlinger::updateInternalStateWithChangedMode() { 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::clearDesiredActiveModeState(const sp<DisplayDevice>& displa 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 @@ void SurfaceFlinger::commitTransactions() { 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 @@ void SurfaceFlinger::loadDisplayModes(PhysicalDisplayId displayId, DisplayModes& 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 bool modesAreSame = + 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 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 @@ void SurfaceFlinger::processDisplayHotplugEventsLocked() { 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 @@ void SurfaceFlinger::processDisplayHotplugEventsLocked() { .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 @@ void SurfaceFlinger::processDisplayHotplugEventsLocked() { 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 @@ void SurfaceFlinger::processDisplayAdded(const wp<IBinder>& displayToken, 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 @@ void SurfaceFlinger::processDisplayAdded(const wp<IBinder>& displayToken, 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::processDisplayChanged(const wp<IBinder>& displayToken, } 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 @@ void SurfaceFlinger::updateCursorAsync() { 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 @@ void SurfaceFlinger::changeRefreshRate(const RefreshRate& refreshRate, DisplayMo } 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 @@ void SurfaceFlinger::onInitializeDisplays() { {}, 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 @@ void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& display, hal: 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 @@ void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& display, hal: 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 @@ void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& display, hal: 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 @@ void SurfaceFlinger::dumpAllLocked(const DumpArgs& args, std::string& result) co 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 @@ void SurfaceFlinger::kernelTimerChanged(bool expired) { 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 @@ uint32_t SurfaceFlinger::getMaxAcquiredBufferCountForCurrentRefreshRate(uid_t ui 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 fa6580342b..01732be337 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -679,8 +679,8 @@ private: // 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 @@ private: /* * 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 b796dfeb1f..93abc9f3eb 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 @@ struct FakePhaseOffsets : scheduler::VsyncConfiguration { 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 @@ public: 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 @@ private: 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 @@ public: return mFlinger->onInitializeDisplays(); } - void scheduleComposite(FrameHint){}; - void setGlobalShadowSettings(FuzzedDataProvider *fdp) { const half4 ambientColor{fdp->ConsumeFloatingPoint<float>(), fdp->ConsumeFloatingPoint<float>(), @@ -678,31 +681,22 @@ public: 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 @@ public: 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 @@ public: } 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 d5041553dc..da60a6981b 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 @@ void SchedulerFuzzer::fuzzRefreshRateConfigs() { 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 @@ void SchedulerFuzzer::fuzzRefreshRateConfigs() { 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 84b391246e..1a49ead275 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 @@ public: 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 40a9b1aad0..93af225b3e 100644 --- a/services/surfaceflinger/tests/unittests/DisplayDevice_InitiateModeChange.cpp +++ b/services/surfaceflinger/tests/unittests/DisplayDevice_InitiateModeChange.cpp @@ -44,68 +44,42 @@ public: 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(); - - 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 constexpr DisplayModeId kModeId60{0}; + static constexpr DisplayModeId kModeId90{1}; + static constexpr DisplayModeId kModeId120{2}; + + 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, clearDesiredActiveModeState) { } 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 @@ TEST_F(InitiateModeChangeTest, initiateModeChange) NO_THREAD_SAFETY_ANALYSIS { 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, initiateModeChange) NO_THREAD_SAFETY_ANALYSIS { 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 @@ NO_THREAD_SAFETY_ANALYSIS { 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 54b8bcb2a4..565c2445e0 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 @@ struct DisplayVariant { 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 @@ struct DisplayVariant { 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 @@ struct HwcDisplayVariant { 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 @@ struct HwcDisplayVariant { 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 @@ struct NonHwcVirtualDisplayVariant 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 @@ struct HwcVirtualDisplayVariant 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 @@ using HwcVirtualDisplayCase = 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 e108beaca9..17511cd615 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 @@ namespace android::scheduler { 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 @@ protected: 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 97f3747d07..fcde532b85 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 @@ struct TestableRefreshRateConfigs : RefreshRateConfigs { 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 @@ protected: 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 @@ protected: 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_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_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 = + 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 @@ TEST_F(RefreshRateConfigsTest, twoModes_storesFullRefreshRateMap) { 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 @@ TEST_F(RefreshRateConfigsTest, twoModes_storesFullRefreshRateMap_differentGroups 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 @@ TEST_F(RefreshRateConfigsTest, twoModes_storesFullRefreshRateMap_differentResolu 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 @@ TEST_F(RefreshRateConfigsTest, twoModes_policyChange) { 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 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_noLayers) { // 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 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_noLayers) { 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 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_60_90) { 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 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_multipleThreshold_60_90) { 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 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_60_72_90) { 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 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_30_60_72_90_120) { 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 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_30_60_90_120_DifferentTypes) { 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 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_30_60_90_120_DifferentTypes) { 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 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_30_60_90_120_DifferentTypes) { 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 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_30_60_90_120_DifferentTypes) { 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 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_30_60_90_120_DifferentTypes) { 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 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_30_60_90_120_DifferentTypes) { 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 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_30_60_90_120_DifferentTypes) { 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 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_30_60_90_120_DifferentTypes) { 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 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_30_60_90_120_DifferentTypes) { 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 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_30_60_90_120_DifferentTypes_mu 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 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_30_60_90_120_DifferentTypes_mu 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 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_30_60_90_120_DifferentTypes_mu 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 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_30_60_90_120_DifferentTypes_mu 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 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_30_60_90_120_DifferentTypes_mu 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 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_30_60_90_120_DifferentTypes_mu 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 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_30_60_90_120_DifferentTypes_mu 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 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_30_60_90_120_DifferentTypes_mu 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 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_30_60_90_120_DifferentTypes_mu 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 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_30_60) { 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 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_30_60_72_90) { 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 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_PriorityTest) { 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 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_24FpsVideo) { 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 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_24FpsVideo_multipleThreshold_6 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 @@ TEST_F(RefreshRateConfigsTest, twoModes_getBestRefreshRate_Explicit) { 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 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_75HzContent) { 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 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_Multiples) { 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 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_Multiples) { 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 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_Multiples) { 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 @@ TEST_F(RefreshRateConfigsTest, scrollWhileWatching60fps_60_90) { 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 @@ TEST_F(RefreshRateConfigsTest, scrollWhileWatching60fps_60_90) { 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 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_ExplicitDefault) { 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_F(RefreshRateConfigsTest, // 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 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_ExplicitExact_WithFractionalRe 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 @@ TEST_F(RefreshRateConfigsTest, 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 @@ TEST_F(RefreshRateConfigsTest, 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 @@ TEST_F(RefreshRateConfigsTest, 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 @@ TEST_F(RefreshRateConfigsTest, 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 @@ TEST_F(RefreshRateConfigsTest, groupSwitchingNotAllowed) { 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 @@ TEST_F(RefreshRateConfigsTest, groupSwitchingWithOneLayer) { 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 @@ TEST_F(RefreshRateConfigsTest, groupSwitchingWithOneLayerOnlySeamless) { 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 @@ TEST_F(RefreshRateConfigsTest, groupSwitchingWithOneLayerOnlySeamlessDefaultFps) 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 @@ TEST_F(RefreshRateConfigsTest, groupSwitchingWithOneLayerOnlySeamlessDefaultFps) 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 @@ TEST_F(RefreshRateConfigsTest, groupSwitchingWithOneLayerDefaultSeamlessness) { 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 @@ TEST_F(RefreshRateConfigsTest, groupSwitchingWithOneLayerDefaultSeamlessness) { 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 @@ TEST_F(RefreshRateConfigsTest, groupSwitchingWithTwoLayersOnlySeamlessAndSeamed) 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 @@ TEST_F(RefreshRateConfigsTest, groupSwitchingWithTwoLayersOnlySeamlessAndSeamed) 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 @@ TEST_F(RefreshRateConfigsTest, groupSwitchingWithTwoLayersDefaultFocusedAndSeame 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 @@ TEST_F(RefreshRateConfigsTest, groupSwitchingWithTwoLayersDefaultFocusedAndSeame 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 @@ TEST_F(RefreshRateConfigsTest, groupSwitchingWithTwoLayersDefaultNotFocusedAndSe 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 @@ TEST_F(RefreshRateConfigsTest, groupSwitchingWithTwoLayersDefaultNotFocusedAndSe 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 @@ TEST_F(RefreshRateConfigsTest, nonSeamlessVotePrefersSeamlessSwitches) { 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 @@ TEST_F(RefreshRateConfigsTest, nonSeamlessExactAndSeamlessMultipleLayers) { .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 @@ TEST_F(RefreshRateConfigsTest, minLayersDontTrigerSeamedSwitch) { 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 @@ TEST_F(RefreshRateConfigsTest, primaryVsAppRequestPolicy) { 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 @@ TEST_F(RefreshRateConfigsTest, idle) { // 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 @@ TEST_F(RefreshRateConfigsTest, idle) { } // 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 @@ TEST_F(RefreshRateConfigsTest, idle) { } // 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 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_KnownFrameRate) { 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 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_KnownFrameRate) { 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 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_ExplicitExact) { 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 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_ExplicitExactEnableFrameRateOv 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 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_ReadsCache) { 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 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_ExplicitExactTouchBoost) { 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 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_FractionalRefreshRates_ExactAn 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 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_withCloseRefreshRates) { 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 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_withCloseRefreshRates) { // 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 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_conflictingVotes) { }, }; - 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 @@ TEST_F(RefreshRateConfigsTest, getFrameRateDivisor) { 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 df4a9c46d1..e2e3d7b12b 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 @@ namespace android::scheduler { 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 @@ RefreshRateStatsTest::~RefreshRateStatsTest() { 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 @@ TEST_F(RefreshRateStatsTest, oneConfigTest) { 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 @@ TEST_F(RefreshRateStatsTest, oneConfigTest) { 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 @@ TEST_F(RefreshRateStatsTest, twoConfigsTest) { 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 @@ TEST_F(RefreshRateStatsTest, twoConfigsTest) { 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 @@ TEST_F(RefreshRateStatsTest, twoConfigsTest) { 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 @@ TEST_F(RefreshRateStatsTest, twoConfigsTest) { 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 @@ TEST_F(RefreshRateStatsTest, twoConfigsTest) { 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 @@ TEST_F(RefreshRateStatsTest, twoConfigsTest) { 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 a992a91226..aab27957c3 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 @@ protected: 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 @@ TEST_F(SchedulerTest, chooseRefreshRateForContentIsNoopWhenModeSwitchingIsNotSup 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 @@ TEST_F(SchedulerTest, updateDisplayModes) { 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 @@ TEST_F(SchedulerTest, calculateMaxAcquiredBufferCount) { } 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 @@ TEST_F(SchedulerTest, chooseRefreshRateForContentSelectsMaxRefreshRate) { 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 3205952f5a..32d57b5b34 100644 --- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayModeSwitching.cpp +++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayModeSwitching.cpp @@ -43,13 +43,11 @@ public: 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 @@ protected: 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(); - - 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(); - - 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 DisplayModeId kModeId60{0}; + static constexpr DisplayModeId kModeId90{1}; + static constexpr DisplayModeId kModeId120{2}; + static constexpr DisplayModeId kModeId90_4K{3}; + + 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); + + 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 @@ void DisplayModeSwitchingTest::setupScheduler( 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 @@ TEST_F(DisplayModeSwitchingTest, changeRefreshRate_OnActiveDisplay_WithoutRefres 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 @@ TEST_F(DisplayModeSwitchingTest, twoConsecutiveSetDesiredDisplayModeSpecs) { // 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 @@ TEST_F(DisplayModeSwitchingTest, changeResolution_OnActiveDisplay_WithoutRefresh 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 38dceb9570..a0e078bf5e 100644 --- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetupNewDisplayDeviceInternalTest.cpp +++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetupNewDisplayDeviceInternalTest.cpp @@ -240,19 +240,17 @@ void SetupNewDisplayDeviceInternalTest::setupNewDisplayDeviceInternalTest() { 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 @@ void SetupNewDisplayDeviceInternalTest::setupNewDisplayDeviceInternalTest() { 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 fe0564e0d3..aff4d83398 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 @@ public: 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 @@ public: 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 @@ public: return *this; } - auto& setWidth(int32_t width) { - mWidth = width; - return *this; - } - - auto& setHeight(int32_t height) { - mHeight = height; + auto& setResolution(ui::Size resolution) { + mResolution = resolution; return *this; } - auto& setVsyncPeriod(int32_t vsyncPeriod) { + auto& setVsyncPeriod(nsecs_t vsyncPeriod) { mVsyncPeriod = vsyncPeriod; return *this; } @@ -660,18 +648,20 @@ public: 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 @@ public: 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 @@ public: 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 @@ public: } 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(); + + modes = ftl::init::map(kModeId, std::move(mode)); + activeModeId = kModeId; + } + + mCreationArgs.refreshRateConfigs = + std::make_shared<scheduler::RefreshRateConfigs>(modes, activeModeId); } - - 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 0000000000..a83ecbca26 --- /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 c90b8ed6c7..5083d561ac 100644 --- a/services/surfaceflinger/tests/unittests/mock/MockSchedulerCallback.h +++ b/services/surfaceflinger/tests/unittests/mock/MockSchedulerCallback.h @@ -25,7 +25,7 @@ namespace android::scheduler::mock { 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 SchedulerCallback final : ISchedulerCallback { 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 {} }; |