diff options
| author | 2020-12-09 09:11:58 +0000 | |
|---|---|---|
| committer | 2020-12-09 09:11:58 +0000 | |
| commit | 45cd13145938cbbe7f3fa778fa517b5e23cf148c (patch) | |
| tree | f51c36ba7989b1493beeb1dbc440e0c96e3f3f11 | |
| parent | 826b244b464f33241e24edd1cca277a5384038eb (diff) | |
| parent | 68a9409306f2d3b1eae220eb20c7fac4fa3e5452 (diff) | |
Merge changes Id0af0598,Iebb77a33
* changes:
SF: Don't store config ids in RefreshRateStats
Add Fps class
24 files changed, 741 insertions, 506 deletions
diff --git a/services/surfaceflinger/Fps.h b/services/surfaceflinger/Fps.h new file mode 100644 index 0000000000..38a9af0149 --- /dev/null +++ b/services/surfaceflinger/Fps.h @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2020 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 <cmath> +#include <ostream> +#include <string> + +#include <android-base/stringprintf.h> +#include <utils/Timers.h> + +namespace android { + +// Value which represents "frames per second". This class is a wrapper around +// float, providing some useful utilities, such as comparisons with tolerance +// and converting between period duruation and frequency. +class Fps { +public: + static constexpr Fps fromPeriodNsecs(nsecs_t period) { return Fps(1e9f / period, period); } + + Fps() = default; + explicit constexpr Fps(float fps) + : fps(fps), period(fps == 0.0f ? 0 : static_cast<nsecs_t>(1e9f / fps)) {} + + constexpr float getValue() const { return fps; } + + constexpr nsecs_t getPeriodNsecs() const { return period; } + + bool equalsWithMargin(const Fps& other) const { return std::abs(fps - other.fps) < kMargin; } + + // DO NOT use for std::sort. Instead use comparesLess(). + bool lessThanWithMargin(const Fps& other) const { return fps + kMargin < other.fps; } + + bool greaterThanWithMargin(const Fps& other) const { return fps > other.fps + kMargin; } + + bool lessThanOrEqualWithMargin(const Fps& other) const { return !greaterThanWithMargin(other); } + + bool greaterThanOrEqualWithMargin(const Fps& other) const { return !lessThanWithMargin(other); } + + bool isValid() const { return fps > 0.0f; } + + int getIntValue() const { return static_cast<int>(std::round(fps)); } + + // Use this comparator for sorting. Using a comparator with margins can + // cause std::sort to crash. + inline static bool comparesLess(const Fps& left, const Fps& right) { + return left.fps < right.fps; + } + + // Compares two FPS with margin. + // Transitivity is not guaranteed, i.e. a==b and b==c doesn't imply a==c. + // DO NOT use with hash maps. Instead use EqualsInBuckets. + struct EqualsWithMargin { + bool operator()(const Fps& left, const Fps& right) const { + return left.equalsWithMargin(right); + } + }; + + // Equals comparator which can be used with hash maps. + // It's guaranteed that if two elements are equal, then their hashes are equal. + struct EqualsInBuckets { + bool operator()(const Fps& left, const Fps& right) const { + return left.getBucket() == right.getBucket(); + } + }; + + inline friend std::string to_string(const Fps& fps) { + return base::StringPrintf("%.2ffps", fps.fps); + } + + inline friend std::ostream& operator<<(std::ostream& os, const Fps& fps) { + return os << to_string(fps); + } + +private: + friend std::hash<android::Fps>; + + constexpr Fps(float fps, nsecs_t period) : fps(fps), period(period) {} + + float getBucket() const { return std::round(fps / kMargin); } + + static constexpr float kMargin = 0.001f; + float fps = 0; + nsecs_t period = 0; +}; + +static_assert(std::is_trivially_copyable_v<Fps>); + +} // namespace android + +namespace std { +template <> +struct hash<android::Fps> { + std::size_t operator()(const android::Fps& fps) const { + return std::hash<float>()(fps.getBucket()); + } +}; +} // namespace std
\ No newline at end of file diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 90396dd322..949227b119 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -1425,7 +1425,8 @@ void Layer::updateTreeHasFrameRateVote() { // First traverse the tree and count how many layers has votes int layersWithVote = 0; traverseTree([&layersWithVote](Layer* layer) { - const auto layerVotedWithDefaultCompatibility = layer->mCurrentState.frameRate.rate > 0 && + const auto layerVotedWithDefaultCompatibility = + layer->mCurrentState.frameRate.rate.isValid() && layer->mCurrentState.frameRate.type == FrameRateCompatibility::Default; const auto layerVotedWithNoVote = layer->mCurrentState.frameRate.type == FrameRateCompatibility::NoVote; @@ -1486,14 +1487,14 @@ void Layer::setFrameTimelineVsyncForTransaction(int64_t frameTimelineVsyncId, ns Layer::FrameRate Layer::getFrameRateForLayerTree() const { const auto frameRate = getDrawingState().frameRate; - if (frameRate.rate > 0 || frameRate.type == FrameRateCompatibility::NoVote) { + if (frameRate.rate.isValid() || frameRate.type == FrameRateCompatibility::NoVote) { return frameRate; } // This layer doesn't have a frame rate. If one of its ancestors or successors // have a vote, return a NoVote for ancestors/successors to set the vote if (getDrawingState().treeHasFrameRateVote) { - return {0, FrameRateCompatibility::NoVote}; + return {Fps(0.0f), FrameRateCompatibility::NoVote}; } return frameRate; @@ -1687,9 +1688,9 @@ void Layer::miniDump(std::string& result, const DisplayDevice& display) const { const FloatRect& crop = outputLayerState.sourceCrop; StringAppendF(&result, "%6.1f %6.1f %6.1f %6.1f | ", crop.left, crop.top, crop.right, crop.bottom); - if (layerState.frameRate.rate != 0 || + if (layerState.frameRate.rate.isValid() || layerState.frameRate.type != FrameRateCompatibility::Default) { - StringAppendF(&result, "% 6.2ffps %15s seamless=%s", layerState.frameRate.rate, + StringAppendF(&result, "%s %15s seamless=%s", to_string(layerState.frameRate.rate).c_str(), frameRateCompatibilityString(layerState.frameRate.type).c_str(), toString(layerState.frameRate.seamlessness).c_str()); } else { diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 75d68a16f2..e9fd550660 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -45,6 +45,7 @@ #include "ClientCache.h" #include "DisplayHardware/ComposerHal.h" #include "DisplayHardware/HWComposer.h" +#include "Fps.h" #include "FrameTracker.h" #include "LayerVector.h" #include "MonitoredProducer.h" @@ -155,7 +156,7 @@ public: struct FrameRate { using Seamlessness = scheduler::Seamlessness; - float rate; + Fps rate; FrameRateCompatibility type; Seamlessness seamlessness; @@ -163,11 +164,12 @@ public: : rate(0), type(FrameRateCompatibility::Default), seamlessness(Seamlessness::Default) {} - FrameRate(float rate, FrameRateCompatibility type, bool shouldBeSeamless = true) + FrameRate(Fps rate, FrameRateCompatibility type, bool shouldBeSeamless = true) : rate(rate), type(type), seamlessness(getSeamlessness(rate, shouldBeSeamless)) {} bool operator==(const FrameRate& other) const { - return rate == other.rate && type == other.type && seamlessness == other.seamlessness; + return rate.equalsWithMargin(other.rate) && type == other.type && + seamlessness == other.seamlessness; } bool operator!=(const FrameRate& other) const { return !(*this == other); } @@ -177,8 +179,8 @@ public: static FrameRateCompatibility convertCompatibility(int8_t compatibility); private: - static Seamlessness getSeamlessness(float rate, bool shouldBeSeamless) { - if (rate == 0.0f) { + static Seamlessness getSeamlessness(Fps rate, bool shouldBeSeamless) { + if (!rate.isValid()) { // Refresh rate of 0 is a special value which should reset the vote to // its default value. return Seamlessness::Default; diff --git a/services/surfaceflinger/RefreshRateOverlay.cpp b/services/surfaceflinger/RefreshRateOverlay.cpp index f676d5b44b..f99d54ac53 100644 --- a/services/surfaceflinger/RefreshRateOverlay.cpp +++ b/services/surfaceflinger/RefreshRateOverlay.cpp @@ -190,7 +190,7 @@ bool RefreshRateOverlay::createLayer() { Mutex::Autolock _l(mFlinger.mStateLock); mLayer = mClient->getLayerUser(mIBinder); - mLayer->setFrameRate(Layer::FrameRate(0, Layer::FrameRateCompatibility::NoVote)); + mLayer->setFrameRate(Layer::FrameRate(Fps(0.0f), Layer::FrameRateCompatibility::NoVote)); // setting Layer's Z requires resorting layersSortedByZ ssize_t idx = mFlinger.mCurrentState.layersSortedByZ.indexOf(mLayer); @@ -205,7 +205,7 @@ bool RefreshRateOverlay::createLayer() { void RefreshRateOverlay::primeCache() { auto& allRefreshRates = mFlinger.mRefreshRateConfigs->getAllRefreshRates(); if (allRefreshRates.size() == 1) { - auto fps = allRefreshRates.begin()->second->getFps(); + int fps = allRefreshRates.begin()->second->getFps().getIntValue(); half4 color = {LOW_FPS_COLOR, ALPHA}; mBufferCache.emplace(fps, SevenSegmentDrawer::drawNumber(fps, color, mShowSpinner)); return; @@ -214,7 +214,7 @@ void RefreshRateOverlay::primeCache() { std::vector<uint32_t> supportedFps; supportedFps.reserve(allRefreshRates.size()); for (auto& [ignored, refreshRate] : allRefreshRates) { - supportedFps.push_back(refreshRate->getFps()); + supportedFps.push_back(refreshRate->getFps().getIntValue()); } std::sort(supportedFps.begin(), supportedFps.end()); @@ -240,7 +240,7 @@ void RefreshRateOverlay::setViewport(ui::Size viewport) { } void RefreshRateOverlay::changeRefreshRate(const RefreshRate& refreshRate) { - mCurrentFps = refreshRate.getFps(); + mCurrentFps = refreshRate.getFps().getIntValue(); auto buffer = mBufferCache[*mCurrentFps][mFrame]; mLayer->setBuffer(buffer, Fence::NO_FENCE, 0, 0, {}, mLayer->getHeadFrameNumber(-1 /* expectedPresentTime */)); diff --git a/services/surfaceflinger/Scheduler/LayerHistory.cpp b/services/surfaceflinger/Scheduler/LayerHistory.cpp index c0d00f3369..499daad031 100644 --- a/services/surfaceflinger/Scheduler/LayerHistory.cpp +++ b/services/surfaceflinger/Scheduler/LayerHistory.cpp @@ -41,7 +41,7 @@ namespace { bool isLayerActive(const Layer& layer, const LayerInfo& info, nsecs_t threshold) { // Layers with an explicit vote are always kept active - if (layer.getFrameRateForLayerTree().rate > 0) { + if (layer.getFrameRateForLayerTree().rate.isValid()) { return true; } @@ -86,9 +86,8 @@ LayerHistory::LayerHistory(const RefreshRateConfigs& refreshRateConfigs) LayerHistory::~LayerHistory() = default; -void LayerHistory::registerLayer(Layer* layer, float /*lowRefreshRate*/, float highRefreshRate, - LayerVoteType type) { - const nsecs_t highRefreshRatePeriod = static_cast<nsecs_t>(1e9f / highRefreshRate); +void LayerHistory::registerLayer(Layer* layer, Fps highRefreshRate, LayerVoteType type) { + const nsecs_t highRefreshRatePeriod = highRefreshRate.getPeriodNsecs(); auto info = std::make_unique<LayerInfo>(layer->getName(), highRefreshRatePeriod, type); std::lock_guard lock(mLock); mLayerInfos.emplace_back(layer, std::move(info)); @@ -148,7 +147,7 @@ LayerHistory::Summary LayerHistory::summarize(nsecs_t now) { {strong->getName(), vote.type, vote.fps, vote.seamlessness, weight, layerFocused}); if (CC_UNLIKELY(mTraceEnabled)) { - trace(layer, *info, vote.type, static_cast<int>(std::round(vote.fps))); + trace(layer, *info, vote.type, vote.fps.getIntValue()); } } @@ -177,7 +176,7 @@ void LayerHistory::partitionLayers(nsecs_t now) { } }(); - if (frameRate.rate > 0 || voteType == LayerVoteType::NoVote) { + if (frameRate.rate.isValid() || voteType == LayerVoteType::NoVote) { const auto type = layer->isVisible() ? voteType : LayerVoteType::NoVote; info->setLayerVote({type, frameRate.rate, frameRate.seamlessness}); } else { diff --git a/services/surfaceflinger/Scheduler/LayerHistory.h b/services/surfaceflinger/Scheduler/LayerHistory.h index 507ccc6b11..4214bab8ff 100644 --- a/services/surfaceflinger/Scheduler/LayerHistory.h +++ b/services/surfaceflinger/Scheduler/LayerHistory.h @@ -46,7 +46,7 @@ public: ~LayerHistory(); // Layers are unregistered when the weak reference expires. - void registerLayer(Layer*, float lowRefreshRate, float highRefreshRate, LayerVoteType type); + void registerLayer(Layer*, Fps highRefreshRate, LayerVoteType type); // Sets the display size. Client is responsible for synchronization. void setDisplayArea(uint32_t displayArea) { mDisplayArea = displayArea; } diff --git a/services/surfaceflinger/Scheduler/LayerInfo.cpp b/services/surfaceflinger/Scheduler/LayerInfo.cpp index 66ac98adbf..1c0065c9ad 100644 --- a/services/surfaceflinger/Scheduler/LayerInfo.cpp +++ b/services/surfaceflinger/Scheduler/LayerInfo.cpp @@ -38,7 +38,7 @@ LayerInfo::LayerInfo(const std::string& name, nsecs_t highRefreshRatePeriod, : mName(name), mHighRefreshRatePeriod(highRefreshRatePeriod), mDefaultVote(defaultVote), - mLayerVote({defaultVote, 0.0f}), + mLayerVote({defaultVote, Fps(0.0f)}), mRefreshRateHistory(name) {} void LayerInfo::setLastPresentTime(nsecs_t lastPresentTime, nsecs_t now, LayerUpdateType updateType, @@ -91,7 +91,8 @@ bool LayerInfo::isFrequent(nsecs_t now) const { // Layer is considered frequent if the average frame rate is higher than the threshold const auto totalTime = mFrameTimes.back().queueTime - it->queueTime; - return (1e9f * (numFrames - 1)) / totalTime >= MIN_FPS_FOR_FREQUENT_LAYER; + return Fps::fromPeriodNsecs(totalTime / (numFrames - 1)) + .greaterThanOrEqualWithMargin(MIN_FPS_FOR_FREQUENT_LAYER); } bool LayerInfo::isAnimating(nsecs_t now) const { @@ -139,7 +140,7 @@ std::optional<nsecs_t> LayerInfo::calculateAverageFrameTime() const { missingPresentTime = true; // If there are no presentation timestamps and we haven't calculated // one in the past then we can't calculate the refresh rate - if (mLastRefreshRate.reported == 0) { + if (!mLastRefreshRate.reported.isValid()) { return std::nullopt; } continue; @@ -163,7 +164,7 @@ std::optional<nsecs_t> LayerInfo::calculateAverageFrameTime() const { return static_cast<nsecs_t>(averageFrameTime); } -std::optional<float> LayerInfo::calculateRefreshRateIfPossible(nsecs_t now) { +std::optional<Fps> LayerInfo::calculateRefreshRateIfPossible(nsecs_t now) { static constexpr float MARGIN = 1.0f; // 1Hz if (!hasEnoughDataForHeuristic()) { ALOGV("Not enough data"); @@ -172,7 +173,7 @@ std::optional<float> LayerInfo::calculateRefreshRateIfPossible(nsecs_t now) { const auto averageFrameTime = calculateAverageFrameTime(); if (averageFrameTime.has_value()) { - const auto refreshRate = 1e9f / *averageFrameTime; + const auto refreshRate = Fps::fromPeriodNsecs(*averageFrameTime); const bool refreshRateConsistent = mRefreshRateHistory.add(refreshRate, now); if (refreshRateConsistent) { const auto knownRefreshRate = @@ -180,22 +181,23 @@ std::optional<float> LayerInfo::calculateRefreshRateIfPossible(nsecs_t now) { // To avoid oscillation, use the last calculated refresh rate if it is // close enough - if (std::abs(mLastRefreshRate.calculated - refreshRate) > MARGIN && - mLastRefreshRate.reported != knownRefreshRate) { + if (std::abs(mLastRefreshRate.calculated.getValue() - refreshRate.getValue()) > + MARGIN && + !mLastRefreshRate.reported.equalsWithMargin(knownRefreshRate)) { mLastRefreshRate.calculated = refreshRate; mLastRefreshRate.reported = knownRefreshRate; } - ALOGV("%s %.2fHz rounded to nearest known frame rate %.2fHz", mName.c_str(), - refreshRate, mLastRefreshRate.reported); + ALOGV("%s %s rounded to nearest known frame rate %s", mName.c_str(), + to_string(refreshRate).c_str(), to_string(mLastRefreshRate.reported).c_str()); } else { - ALOGV("%s Not stable (%.2fHz) returning last known frame rate %.2fHz", mName.c_str(), - refreshRate, mLastRefreshRate.reported); + ALOGV("%s Not stable (%s) returning last known frame rate %s", mName.c_str(), + to_string(refreshRate).c_str(), to_string(mLastRefreshRate.reported).c_str()); } } - return mLastRefreshRate.reported == 0 ? std::nullopt - : std::make_optional(mLastRefreshRate.reported); + return mLastRefreshRate.reported.isValid() ? std::make_optional(mLastRefreshRate.reported) + : std::nullopt; } LayerInfo::LayerVote LayerInfo::getRefreshRateVote(nsecs_t now) { @@ -207,13 +209,13 @@ LayerInfo::LayerVote LayerInfo::getRefreshRateVote(nsecs_t now) { if (isAnimating(now)) { ALOGV("%s is animating", mName.c_str()); mLastRefreshRate.animatingOrInfrequent = true; - return {LayerHistory::LayerVoteType::Max, 0}; + return {LayerHistory::LayerVoteType::Max, Fps(0.0f)}; } if (!isFrequent(now)) { ALOGV("%s is infrequent", mName.c_str()); mLastRefreshRate.animatingOrInfrequent = true; - return {LayerHistory::LayerVoteType::Min, 0}; + return {LayerHistory::LayerVoteType::Min, Fps(0.0f)}; } // If the layer was previously tagged as animating or infrequent, we clear @@ -225,12 +227,12 @@ LayerInfo::LayerVote LayerInfo::getRefreshRateVote(nsecs_t now) { auto refreshRate = calculateRefreshRateIfPossible(now); if (refreshRate.has_value()) { - ALOGV("%s calculated refresh rate: %.2f", mName.c_str(), refreshRate.value()); + ALOGV("%s calculated refresh rate: %s", mName.c_str(), to_string(*refreshRate).c_str()); return {LayerHistory::LayerVoteType::Heuristic, refreshRate.value()}; } ALOGV("%s Max (can't resolve refresh rate)", mName.c_str()); - return {LayerHistory::LayerVoteType::Max, 0}; + return {LayerHistory::LayerVoteType::Max, Fps(0.0f)}; } const char* LayerInfo::getTraceTag(android::scheduler::LayerHistory::LayerVoteType type) const { @@ -256,7 +258,7 @@ void LayerInfo::RefreshRateHistory::clear() { mRefreshRates.clear(); } -bool LayerInfo::RefreshRateHistory::add(float refreshRate, nsecs_t now) { +bool LayerInfo::RefreshRateHistory::add(Fps refreshRate, nsecs_t now) { mRefreshRates.push_back({refreshRate, now}); while (mRefreshRates.size() >= HISTORY_SIZE || now - mRefreshRates.front().timestamp > HISTORY_DURATION.count()) { @@ -268,7 +270,7 @@ bool LayerInfo::RefreshRateHistory::add(float refreshRate, nsecs_t now) { mHeuristicTraceTagData = makeHeuristicTraceTagData(); } - ATRACE_INT(mHeuristicTraceTagData->average.c_str(), static_cast<int>(refreshRate)); + ATRACE_INT(mHeuristicTraceTagData->average.c_str(), refreshRate.getIntValue()); } return isConsistent(); @@ -279,15 +281,16 @@ bool LayerInfo::RefreshRateHistory::isConsistent() const { const auto max = std::max_element(mRefreshRates.begin(), mRefreshRates.end()); const auto min = std::min_element(mRefreshRates.begin(), mRefreshRates.end()); - const auto consistent = max->refreshRate - min->refreshRate <= MARGIN_FPS; + const auto consistent = + max->refreshRate.getValue() - min->refreshRate.getValue() < MARGIN_CONSISTENT_FPS; if (CC_UNLIKELY(sTraceEnabled)) { if (!mHeuristicTraceTagData.has_value()) { mHeuristicTraceTagData = makeHeuristicTraceTagData(); } - ATRACE_INT(mHeuristicTraceTagData->max.c_str(), static_cast<int>(max->refreshRate)); - ATRACE_INT(mHeuristicTraceTagData->min.c_str(), static_cast<int>(min->refreshRate)); + ATRACE_INT(mHeuristicTraceTagData->max.c_str(), max->refreshRate.getIntValue()); + ATRACE_INT(mHeuristicTraceTagData->min.c_str(), min->refreshRate.getIntValue()); ATRACE_INT(mHeuristicTraceTagData->consistent.c_str(), consistent); } diff --git a/services/surfaceflinger/Scheduler/LayerInfo.h b/services/surfaceflinger/Scheduler/LayerInfo.h index e43467062f..9304e62765 100644 --- a/services/surfaceflinger/Scheduler/LayerInfo.h +++ b/services/surfaceflinger/Scheduler/LayerInfo.h @@ -50,9 +50,9 @@ class LayerInfo { // is within a threshold. If a layer is infrequent, its average refresh rate is disregarded in // favor of a low refresh rate. static constexpr size_t FREQUENT_LAYER_WINDOW_SIZE = 3; - static constexpr float MIN_FPS_FOR_FREQUENT_LAYER = 10.0f; + static constexpr Fps MIN_FPS_FOR_FREQUENT_LAYER{10.0f}; static constexpr auto MAX_FREQUENT_LAYER_PERIOD_NS = - std::chrono::nanoseconds(static_cast<nsecs_t>(1e9f / MIN_FPS_FOR_FREQUENT_LAYER)) + 1ms; + std::chrono::nanoseconds(MIN_FPS_FOR_FREQUENT_LAYER.getPeriodNsecs()) + 1ms; friend class LayerHistoryTest; @@ -60,7 +60,7 @@ public: // Holds information about the layer vote struct LayerVote { LayerHistory::LayerVoteType type = LayerHistory::LayerVoteType::Heuristic; - float fps = 0.0f; + Fps fps{0.0f}; Seamlessness seamlessness = Seamlessness::Default; }; @@ -92,7 +92,7 @@ public: void setDefaultLayerVote(LayerHistory::LayerVoteType type) { mDefaultVote = type; } // Resets the layer vote to its default. - void resetLayerVote() { mLayerVote = {mDefaultVote, 0.0f, Seamlessness::Default}; } + void resetLayerVote() { mLayerVote = {mDefaultVote, Fps(0.0f), Seamlessness::Default}; } LayerVote getRefreshRateVote(nsecs_t now); @@ -130,9 +130,9 @@ private: // Holds information about the calculated and reported refresh rate struct RefreshRateHeuristicData { // Rate calculated on the layer - float calculated = 0.0f; + Fps calculated{0.0f}; // Last reported rate for LayerInfo::getRefreshRate() - float reported = 0.0f; + Fps reported{0.0f}; // Whether the last reported rate for LayerInfo::getRefreshRate() // was due to animation or infrequent updates bool animatingOrInfrequent = false; @@ -151,18 +151,20 @@ private: void clear(); // Adds a new refresh rate and returns true if it is consistent - bool add(float refreshRate, nsecs_t now); + bool add(Fps refreshRate, nsecs_t now); private: friend class LayerHistoryTest; // Holds the refresh rate when it was calculated struct RefreshRateData { - float refreshRate = 0.0f; + Fps refreshRate{0.0f}; nsecs_t timestamp = 0; bool operator<(const RefreshRateData& other) const { - return refreshRate < other.refreshRate; + // We don't need comparison with margins since we are using + // this to find the min and max refresh rates. + return refreshRate.getValue() < other.refreshRate.getValue(); } }; @@ -180,13 +182,13 @@ private: const std::string mName; mutable std::optional<HeuristicTraceTagData> mHeuristicTraceTagData; std::deque<RefreshRateData> mRefreshRates; - static constexpr float MARGIN_FPS = 1.0; + static constexpr float MARGIN_CONSISTENT_FPS = 1.0; }; bool isFrequent(nsecs_t now) const; bool isAnimating(nsecs_t now) const; bool hasEnoughDataForHeuristic() const; - std::optional<float> calculateRefreshRateIfPossible(nsecs_t now); + std::optional<Fps> calculateRefreshRateIfPossible(nsecs_t now); std::optional<nsecs_t> calculateAverageFrameTime() const; bool isFrameTimeValid(const FrameTimeData&) const; diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp index 83fa20ef34..4b7251b989 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp +++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp @@ -29,10 +29,10 @@ namespace android::scheduler { namespace { std::string formatLayerInfo(const RefreshRateConfigs::LayerRequirement& layer, float weight) { - return base::StringPrintf("%s (type=%s, weight=%.2f seamlessness=%s) %.2fHz", - layer.name.c_str(), + return base::StringPrintf("%s (type=%s, weight=%.2f seamlessness=%s) %s", layer.name.c_str(), RefreshRateConfigs::layerVoteTypeString(layer.vote).c_str(), weight, - toString(layer.seamlessness).c_str(), layer.desiredRefreshRate); + toString(layer.seamlessness).c_str(), + to_string(layer.desiredRefreshRate).c_str()); } } // namespace @@ -41,7 +41,7 @@ using RefreshRate = RefreshRateConfigs::RefreshRate; std::string RefreshRate::toString() const { return base::StringPrintf("{id=%d, hwcId=%d, fps=%.2f, width=%d, height=%d group=%d}", - getConfigId().value(), hwcConfig->getId(), getFps(), + getConfigId().value(), hwcConfig->getId(), getFps().getValue(), hwcConfig->getWidth(), hwcConfig->getHeight(), getConfigGroup()); } @@ -64,9 +64,9 @@ std::string RefreshRateConfigs::layerVoteTypeString(LayerVoteType vote) { std::string RefreshRateConfigs::Policy::toString() const { return base::StringPrintf("default config ID: %d, allowGroupSwitching = %d" - ", primary range: [%.2f %.2f], app request range: [%.2f %.2f]", - defaultConfig.value(), allowGroupSwitching, primaryRange.min, - primaryRange.max, appRequestRange.min, appRequestRange.max); + ", primary range: %s, app request range: %s", + defaultConfig.value(), allowGroupSwitching, + primaryRange.toString().c_str(), appRequestRange.toString().c_str()); } std::pair<nsecs_t, nsecs_t> RefreshRateConfigs::getDisplayFrames(nsecs_t layerPeriod, @@ -144,7 +144,8 @@ const RefreshRate& RefreshRateConfigs::getBestRefreshRate( // move out the of range if layers explicitly request a different refresh // rate. const Policy* policy = getCurrentPolicyLocked(); - const bool primaryRangeIsSingleRate = policy->primaryRange.min == policy->primaryRange.max; + const bool primaryRangeIsSingleRate = + policy->primaryRange.min.equalsWithMargin(policy->primaryRange.max); if (!globalSignals.touch && globalSignals.idle && !(primaryRangeIsSingleRate && hasExplicitVoteLayers)) { @@ -229,17 +230,18 @@ const RefreshRate& RefreshRateConfigs::getBestRefreshRate( // If the layer wants Max, give higher score to the higher refresh rate if (layer.vote == LayerVoteType::Max) { - const auto ratio = scores[i].first->fps / scores.back().first->fps; + const auto ratio = + scores[i].first->fps.getValue() / scores.back().first->fps.getValue(); // use ratio^2 to get a lower score the more we get further from peak const auto layerScore = ratio * ratio; ALOGV("%s gives %s score of %.2f", formatLayerInfo(layer, weight).c_str(), - scores[i].first->name.c_str(), layerScore); + scores[i].first->getName().c_str(), layerScore); scores[i].second += weight * layerScore; continue; } const auto displayPeriod = scores[i].first->hwcConfig->getVsyncPeriod(); - const auto layerPeriod = round<nsecs_t>(1e9f / layer.desiredRefreshRate); + const auto layerPeriod = layer.desiredRefreshRate.getPeriodNsecs(); if (layer.vote == LayerVoteType::ExplicitDefault) { const auto layerScore = [&]() { // Find the actual rate the layer will render, assuming @@ -256,7 +258,7 @@ const RefreshRate& RefreshRateConfigs::getBestRefreshRate( }(); ALOGV("%s gives %s score of %.2f", formatLayerInfo(layer, weight).c_str(), - scores[i].first->name.c_str(), layerScore); + scores[i].first->getName().c_str(), layerScore); scores[i].second += weight * layerScore; continue; } @@ -297,7 +299,7 @@ const RefreshRate& RefreshRateConfigs::getBestRefreshRate( constexpr float kSeamedSwitchPenalty = 0.95f; const float seamlessness = isSeamlessSwitch ? 1.0f : kSeamedSwitchPenalty; ALOGV("%s gives %s score of %.2f", formatLayerInfo(layer, weight).c_str(), - scores[i].first->name.c_str(), layerScore); + scores[i].first->getName().c_str(), layerScore); scores[i].second += weight * layerScore * seamlessness; continue; } @@ -331,7 +333,7 @@ const RefreshRate& RefreshRateConfigs::getBestRefreshRate( const RefreshRate& touchRefreshRate = getMaxRefreshRateByPolicyLocked(); if (globalSignals.touch && explicitDefaultVoteLayers == 0 && - bestRefreshRate->fps < touchRefreshRate.fps) { + bestRefreshRate->fps.lessThanWithMargin(touchRefreshRate.fps)) { setTouchConsidered(); ALOGV("TouchBoost - choose %s", touchRefreshRate.getName().c_str()); return touchRefreshRate; @@ -347,9 +349,9 @@ const RefreshRate* RefreshRateConfigs::getBestRefreshRate(Iter begin, Iter end) float max = begin->second; for (auto i = begin; i != end; ++i) { const auto [refreshRate, score] = *i; - ALOGV("%s scores %.2f", refreshRate->name.c_str(), score); + ALOGV("%s scores %.2f", refreshRate->getName().c_str(), score); - ATRACE_INT(refreshRate->name.c_str(), round<int>(score * 100)); + ATRACE_INT(refreshRate->getName().c_str(), round<int>(score * 100)); if (score > max * (1 + EPSILON)) { max = score; @@ -433,10 +435,10 @@ RefreshRateConfigs::RefreshRateConfigs( for (auto configId = HwcConfigIndexType(0); configId.value() < configs.size(); configId++) { const auto& config = configs.at(static_cast<size_t>(configId.value())); - const float fps = 1e9f / config->getVsyncPeriod(); mRefreshRates.emplace(configId, std::make_unique<RefreshRate>(configId, config, - base::StringPrintf("%.2ffps", fps), fps, + Fps::fromPeriodNsecs( + config->getVsyncPeriod()), RefreshRate::ConstructorTag(0))); if (configId == currentConfigId) { mCurrentRefreshRate = mRefreshRates.at(configId).get(); @@ -463,8 +465,8 @@ bool RefreshRateConfigs::isPolicyValid(const Policy& policy) { ALOGE("Default config is not in the primary range."); return false; } - return policy.appRequestRange.min <= policy.primaryRange.min && - policy.appRequestRange.max >= policy.primaryRange.max; + return policy.appRequestRange.min.lessThanOrEqualWithMargin(policy.primaryRange.min) && + policy.appRequestRange.max.greaterThanOrEqualWithMargin(policy.primaryRange.max); } status_t RefreshRateConfigs::setDisplayManagerPolicy(const Policy& policy) { @@ -550,12 +552,9 @@ void RefreshRateConfigs::constructAvailableRefreshRates() { // Filter configs based on current policy and sort based on vsync period const Policy* policy = getCurrentPolicyLocked(); const auto& defaultConfig = mRefreshRates.at(policy->defaultConfig)->hwcConfig; - ALOGV("constructAvailableRefreshRates: default %d group %d primaryRange=[%.2f %.2f]" - " appRequestRange=[%.2f %.2f]", - policy->defaultConfig.value(), defaultConfig->getConfigGroup(), policy->primaryRange.min, - policy->primaryRange.max, policy->appRequestRange.min, policy->appRequestRange.max); + ALOGV("constructAvailableRefreshRates: %s ", policy->toString().c_str()); - auto filterRefreshRates = [&](float min, float max, const char* listName, + auto filterRefreshRates = [&](Fps min, Fps max, const char* listName, std::vector<const RefreshRate*>* outRefreshRates) { getSortedRefreshRateList( [&](const RefreshRate& refreshRate) REQUIRES(mLock) { @@ -572,12 +571,12 @@ void RefreshRateConfigs::constructAvailableRefreshRates() { outRefreshRates); LOG_ALWAYS_FATAL_IF(outRefreshRates->empty(), - "No matching configs for %s range: min=%.0f max=%.0f", listName, min, - max); + "No matching configs for %s range: min=%s max=%s", listName, + to_string(min).c_str(), to_string(max).c_str()); auto stringifyRefreshRates = [&]() -> std::string { std::string str; for (auto refreshRate : *outRefreshRates) { - base::StringAppendF(&str, "%s ", refreshRate->name.c_str()); + base::StringAppendF(&str, "%s ", refreshRate->getName().c_str()); } return str; }; @@ -590,39 +589,39 @@ void RefreshRateConfigs::constructAvailableRefreshRates() { &mAppRequestRefreshRates); } -std::vector<float> RefreshRateConfigs::constructKnownFrameRates( +std::vector<Fps> RefreshRateConfigs::constructKnownFrameRates( const std::vector<std::shared_ptr<const HWC2::Display::Config>>& configs) { - std::vector<float> knownFrameRates = {24.0f, 30.0f, 45.0f, 60.0f, 72.0f}; + std::vector<Fps> knownFrameRates = {Fps(24.0f), Fps(30.0f), Fps(45.0f), Fps(60.0f), Fps(72.0f)}; knownFrameRates.reserve(knownFrameRates.size() + configs.size()); // Add all supported refresh rates to the set for (const auto& config : configs) { - const auto refreshRate = 1e9f / config->getVsyncPeriod(); + const auto refreshRate = Fps::fromPeriodNsecs(config->getVsyncPeriod()); knownFrameRates.emplace_back(refreshRate); } // Sort and remove duplicates - const auto frameRatesEqual = [](float a, float b) { return std::abs(a - b) <= 0.01f; }; - std::sort(knownFrameRates.begin(), knownFrameRates.end()); + std::sort(knownFrameRates.begin(), knownFrameRates.end(), Fps::comparesLess); knownFrameRates.erase(std::unique(knownFrameRates.begin(), knownFrameRates.end(), - frameRatesEqual), + Fps::EqualsWithMargin()), knownFrameRates.end()); return knownFrameRates; } -float RefreshRateConfigs::findClosestKnownFrameRate(float frameRate) const { - if (frameRate <= *mKnownFrameRates.begin()) { +Fps RefreshRateConfigs::findClosestKnownFrameRate(Fps frameRate) const { + if (frameRate.lessThanOrEqualWithMargin(*mKnownFrameRates.begin())) { return *mKnownFrameRates.begin(); } - if (frameRate >= *std::prev(mKnownFrameRates.end())) { + if (frameRate.greaterThanOrEqualWithMargin(*std::prev(mKnownFrameRates.end()))) { return *std::prev(mKnownFrameRates.end()); } - auto lowerBound = std::lower_bound(mKnownFrameRates.begin(), mKnownFrameRates.end(), frameRate); + auto lowerBound = std::lower_bound(mKnownFrameRates.begin(), mKnownFrameRates.end(), frameRate, + Fps::comparesLess); - const auto distance1 = std::abs(frameRate - *lowerBound); - const auto distance2 = std::abs(frameRate - *std::prev(lowerBound)); + const auto distance1 = std::abs((frameRate.getValue() - lowerBound->getValue())); + const auto distance2 = std::abs((frameRate.getValue() - std::prev(lowerBound)->getValue())); return distance1 < distance2 ? *lowerBound : *std::prev(lowerBound); } @@ -657,7 +656,7 @@ void RefreshRateConfigs::setPreferredRefreshRateForUid(FrameRateOverride frameRa std::lock_guard lock(mLock); if (frameRateOverride.frameRateHz != 0) { - mPreferredRefreshRateForUid[frameRateOverride.uid] = frameRateOverride.frameRateHz; + mPreferredRefreshRateForUid[frameRateOverride.uid] = Fps(frameRateOverride.frameRateHz); } else { mPreferredRefreshRateForUid.erase(frameRateOverride.uid); } @@ -675,7 +674,7 @@ int RefreshRateConfigs::getRefreshRateDividerForUid(uid_t uid) const { // in DisplayManagerService.getDisplayInfoForFrameRateOverride constexpr float kThreshold = 0.1f; const auto refreshRateHz = iter->second; - const auto numPeriods = mCurrentRefreshRate->getFps() / refreshRateHz; + const auto numPeriods = mCurrentRefreshRate->getFps().getValue() / refreshRateHz.getValue(); const auto numPeriodsRounded = std::round(numPeriods); if (std::abs(numPeriods - numPeriodsRounded) > kThreshold) { return 1; @@ -690,7 +689,7 @@ std::vector<FrameRateOverride> RefreshRateConfigs::getFrameRateOverrides() { overrides.reserve(mPreferredRefreshRateForUid.size()); for (const auto [uid, frameRate] : mPreferredRefreshRateForUid) { - overrides.emplace_back(FrameRateOverride{uid, frameRate}); + overrides.emplace_back(FrameRateOverride{uid, frameRate.getValue()}); } return overrides; diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h index 6e0c0d3897..ec7ffe5b30 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h +++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h @@ -25,6 +25,7 @@ #include <type_traits> #include "DisplayHardware/HWComposer.h" +#include "Fps.h" #include "HwcStrongTypes.h" #include "Scheduler/SchedulerUtils.h" #include "Scheduler/Seamlessness.h" @@ -64,29 +65,31 @@ public: public: RefreshRate(HwcConfigIndexType configId, - std::shared_ptr<const HWC2::Display::Config> config, std::string name, - float fps, ConstructorTag) - : configId(configId), hwcConfig(config), name(std::move(name)), fps(fps) {} + std::shared_ptr<const HWC2::Display::Config> config, Fps fps, ConstructorTag) + : configId(configId), hwcConfig(config), fps(std::move(fps)) {} RefreshRate(const RefreshRate&) = delete; HwcConfigIndexType getConfigId() const { return configId; } nsecs_t getVsyncPeriod() const { return hwcConfig->getVsyncPeriod(); } int32_t getConfigGroup() const { return hwcConfig->getConfigGroup(); } - const std::string& getName() const { return name; } - float getFps() const { return fps; } + std::string getName() const { return to_string(fps); } + Fps getFps() const { return fps; } // Checks whether the fps of this RefreshRate struct is within a given min and max refresh - // rate passed in. FPS_EPSILON is applied to the boundaries for approximation. - bool inPolicy(float minRefreshRate, float maxRefreshRate) const { - return (fps >= (minRefreshRate - FPS_EPSILON) && fps <= (maxRefreshRate + FPS_EPSILON)); + // rate passed in. Margin of error is applied to the boundaries for approximation. + bool inPolicy(Fps minRefreshRate, Fps maxRefreshRate) const { + return minRefreshRate.lessThanOrEqualWithMargin(fps) && + fps.lessThanOrEqualWithMargin(maxRefreshRate); } bool operator!=(const RefreshRate& other) const { return configId != other.configId || hwcConfig != other.hwcConfig; } - bool operator<(const RefreshRate& other) const { return getFps() < other.getFps(); } + bool operator<(const RefreshRate& other) const { + return getFps().getValue() < other.getFps().getValue(); + } bool operator==(const RefreshRate& other) const { return !(*this != other); } @@ -96,18 +99,13 @@ public: friend RefreshRateConfigs; friend class RefreshRateConfigsTest; - // The tolerance within which we consider FPS approximately equals. - static constexpr float FPS_EPSILON = 0.001f; - // This config ID corresponds to the position of the config in the vector that is stored // on the device. const HwcConfigIndexType configId; // The config itself std::shared_ptr<const HWC2::Display::Config> hwcConfig; - // Human readable name of the refresh rate. - const std::string name; // Refresh rate in frames per second - const float fps = 0; + const Fps fps{0.0f}; }; using AllRefreshRatesMapType = @@ -119,14 +117,19 @@ public: public: struct Range { - float min = 0; - float max = std::numeric_limits<float>::max(); + Fps min{0.0f}; + Fps max{std::numeric_limits<float>::max()}; bool operator==(const Range& other) const { - return min == other.min && max == other.max; + return min.equalsWithMargin(other.min) && max.equalsWithMargin(other.max); } bool operator!=(const Range& other) const { return !(*this == other); } + + std::string toString() const { + return base::StringPrintf("[%s %s]", to_string(min).c_str(), + to_string(max).c_str()); + } }; // The default config, used to ensure we only initiate display config switches within the @@ -221,7 +224,7 @@ public: // Layer vote type. LayerVoteType vote = LayerVoteType::NoVote; // Layer's desired refresh rate, if applicable. - float desiredRefreshRate = 0.0f; + Fps desiredRefreshRate{0.0f}; // If a seamless mode switch is required. Seamlessness seamlessness = Seamlessness::Default; // Layer's weight in the range of [0, 1]. The higher the weight the more impact this layer @@ -232,7 +235,7 @@ public: bool operator==(const LayerRequirement& other) const { return name == other.name && vote == other.vote && - desiredRefreshRate == other.desiredRefreshRate && + desiredRefreshRate.equalsWithMargin(other.desiredRefreshRate) && seamlessness == other.seamlessness && weight == other.weight && focused == other.focused; } @@ -295,7 +298,7 @@ public: static std::string layerVoteTypeString(LayerVoteType vote); // Returns a known frame rate that is the closest to frameRate - float findClosestKnownFrameRate(float frameRate) const; + Fps findClosestKnownFrameRate(Fps frameRate) const; RefreshRateConfigs(const std::vector<std::shared_ptr<const HWC2::Display::Config>>& configs, HwcConfigIndexType currentConfigId); @@ -332,7 +335,7 @@ private: friend class RefreshRateConfigsTest; void constructAvailableRefreshRates() REQUIRES(mLock); - static std::vector<float> constructKnownFrameRates( + static std::vector<Fps> constructKnownFrameRates( const std::vector<std::shared_ptr<const HWC2::Display::Config>>& configs); void getSortedRefreshRateList( @@ -387,7 +390,7 @@ private: // A mapping between a UID and a preferred refresh rate that this app would // run at. - std::unordered_map<uid_t, float> mPreferredRefreshRateForUid GUARDED_BY(mLock); + std::unordered_map<uid_t, Fps> mPreferredRefreshRateForUid GUARDED_BY(mLock); // The min and max refresh rates supported by the device. // This will not change at runtime. @@ -398,7 +401,7 @@ private: // A sorted list of known frame rates that a Heuristic layer will choose // from based on the closest value. - const std::vector<float> mKnownFrameRates; + const std::vector<Fps> mKnownFrameRates; }; } // namespace android::scheduler diff --git a/services/surfaceflinger/Scheduler/RefreshRateStats.h b/services/surfaceflinger/Scheduler/RefreshRateStats.h index d9e7b371ff..80f4665150 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateStats.h +++ b/services/surfaceflinger/Scheduler/RefreshRateStats.h @@ -18,7 +18,7 @@ #include <numeric> -#include "Scheduler/RefreshRateConfigs.h" +#include "Fps.h" #include "Scheduler/SchedulerUtils.h" #include "TimeStats/TimeStats.h" @@ -40,12 +40,10 @@ class RefreshRateStats { static constexpr int64_t MS_PER_DAY = 24 * MS_PER_HOUR; public: - RefreshRateStats(const RefreshRateConfigs& refreshRateConfigs, TimeStats& timeStats, - HwcConfigIndexType currentConfigId, + RefreshRateStats(TimeStats& timeStats, Fps currentRefreshRate, android::hardware::graphics::composer::hal::PowerMode currentPowerMode) - : mRefreshRateConfigs(refreshRateConfigs), - mTimeStats(timeStats), - mCurrentConfigMode(currentConfigId), + : mTimeStats(timeStats), + mCurrentRefreshRate(currentRefreshRate), mCurrentPowerMode(currentPowerMode) {} // Sets power mode. @@ -59,12 +57,12 @@ public: // Sets config mode. If the mode has changed, it records how much time was spent in the previous // mode. - void setConfigMode(HwcConfigIndexType configId) { - if (mCurrentConfigMode == configId) { + void setRefreshRate(Fps currRefreshRate) { + if (mCurrentRefreshRate.equalsWithMargin(currRefreshRate)) { return; } flushTime(); - mCurrentConfigMode = configId; + mCurrentRefreshRate = currRefreshRate; } // Returns a map between human readable refresh rate and number of seconds the device spent in @@ -79,10 +77,10 @@ public: // Multiple configs may map to the same name, e.g. "60fps". Add the // times for such configs together. for (const auto& [configId, time] : mConfigModesTotalTime) { - totalTime[mRefreshRateConfigs.getRefreshRateFromConfigId(configId).getName()] = 0; + totalTime[to_string(configId)] = 0; } for (const auto& [configId, time] : mConfigModesTotalTime) { - totalTime[mRefreshRateConfigs.getRefreshRateFromConfigId(configId).getName()] += time; + totalTime[to_string(configId)] += time; } totalTime["ScreenOff"] = mScreenOffTime; return totalTime; @@ -111,12 +109,11 @@ private: uint32_t fps = 0; if (mCurrentPowerMode == android::hardware::graphics::composer::hal::PowerMode::ON) { // Normal power mode is counted under different config modes. - if (mConfigModesTotalTime.find(mCurrentConfigMode) == mConfigModesTotalTime.end()) { - mConfigModesTotalTime[mCurrentConfigMode] = 0; + if (mConfigModesTotalTime.find(mCurrentRefreshRate) == mConfigModesTotalTime.end()) { + mConfigModesTotalTime[mCurrentRefreshRate] = 0; } - mConfigModesTotalTime[mCurrentConfigMode] += timeElapsedMs; - fps = static_cast<uint32_t>(std::round( - mRefreshRateConfigs.getRefreshRateFromConfigId(mCurrentConfigMode).getFps())); + mConfigModesTotalTime[mCurrentRefreshRate] += timeElapsedMs; + fps = static_cast<uint32_t>(mCurrentRefreshRate.getIntValue()); } else { mScreenOffTime += timeElapsedMs; } @@ -134,16 +131,13 @@ private: days, hours, mins, sec, secRemainderMs); } - // Keeps information about refresh rate configs that device has. - const RefreshRateConfigs& mRefreshRateConfigs; - // Aggregate refresh rate statistics for telemetry. TimeStats& mTimeStats; - HwcConfigIndexType mCurrentConfigMode; + Fps mCurrentRefreshRate; android::hardware::graphics::composer::hal::PowerMode mCurrentPowerMode; - std::unordered_map<HwcConfigIndexType /* configId */, int64_t /* duration in ms */> + std::unordered_map<Fps, int64_t /* duration in ms */, std::hash<Fps>, Fps::EqualsInBuckets> mConfigModesTotalTime; int64_t mScreenOffTime = 0; diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp index 52bf483fdd..07411b08d0 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.cpp +++ b/services/surfaceflinger/Scheduler/Scheduler.cpp @@ -510,25 +510,22 @@ void Scheduler::setIgnorePresentFences(bool ignore) { void Scheduler::registerLayer(Layer* layer) { if (!mLayerHistory) return; - const auto minFps = mRefreshRateConfigs.getMinRefreshRate().getFps(); const auto maxFps = mRefreshRateConfigs.getMaxRefreshRate().getFps(); if (layer->getWindowType() == InputWindowInfo::Type::STATUS_BAR) { - mLayerHistory->registerLayer(layer, minFps, maxFps, - scheduler::LayerHistory::LayerVoteType::NoVote); + mLayerHistory->registerLayer(layer, maxFps, scheduler::LayerHistory::LayerVoteType::NoVote); } else if (!mOptions.useContentDetection) { // If the content detection feature is off, all layers are registered at Max. We still keep // the layer history, since we use it for other features (like Frame Rate API), so layers // still need to be registered. - mLayerHistory->registerLayer(layer, minFps, maxFps, - scheduler::LayerHistory::LayerVoteType::Max); + mLayerHistory->registerLayer(layer, maxFps, scheduler::LayerHistory::LayerVoteType::Max); } else { if (layer->getWindowType() == InputWindowInfo::Type::WALLPAPER) { // Running Wallpaper at Min is considered as part of content detection. - mLayerHistory->registerLayer(layer, minFps, maxFps, + mLayerHistory->registerLayer(layer, maxFps, scheduler::LayerHistory::LayerVoteType::Min); } else { - mLayerHistory->registerLayer(layer, minFps, maxFps, + mLayerHistory->registerLayer(layer, maxFps, scheduler::LayerHistory::LayerVoteType::Heuristic); } } @@ -618,14 +615,15 @@ void Scheduler::kernelIdleTimerCallback(TimerState state) { // TODO(145561154): cleanup the kernel idle timer implementation and the refresh rate // magic number const auto& refreshRate = mRefreshRateConfigs.getCurrentRefreshRate(); - constexpr float FPS_THRESHOLD_FOR_KERNEL_TIMER = 65.0f; - if (state == TimerState::Reset && refreshRate.getFps() > FPS_THRESHOLD_FOR_KERNEL_TIMER) { + constexpr Fps FPS_THRESHOLD_FOR_KERNEL_TIMER{65.0f}; + if (state == TimerState::Reset && + refreshRate.getFps().greaterThanWithMargin(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) { + refreshRate.getFps().lessThanOrEqualWithMargin(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. diff --git a/services/surfaceflinger/Scheduler/VsyncConfiguration.cpp b/services/surfaceflinger/Scheduler/VsyncConfiguration.cpp index aac2569044..8431323888 100644 --- a/services/surfaceflinger/Scheduler/VsyncConfiguration.cpp +++ b/services/surfaceflinger/Scheduler/VsyncConfiguration.cpp @@ -31,15 +31,10 @@ std::optional<nsecs_t> getProperty(const char* name) { return std::nullopt; } -bool fpsEqualsWithMargin(float fpsA, float fpsB) { - static constexpr float MARGIN = 0.01f; - return std::abs(fpsA - fpsB) <= MARGIN; -} - -std::vector<float> getRefreshRatesFromConfigs( +std::vector<android::Fps> getRefreshRatesFromConfigs( const android::scheduler::RefreshRateConfigs& refreshRateConfigs) { const auto& allRefreshRates = refreshRateConfigs.getAllRefreshRates(); - std::vector<float> refreshRates; + std::vector<android::Fps> refreshRates; refreshRates.reserve(allRefreshRates.size()); for (const auto& [ignored, refreshRate] : allRefreshRates) { @@ -53,12 +48,12 @@ std::vector<float> getRefreshRatesFromConfigs( namespace android::scheduler::impl { -VsyncConfiguration::VsyncConfiguration(float currentFps) : mRefreshRateFps(currentFps) {} +VsyncConfiguration::VsyncConfiguration(Fps currentFps) : mRefreshRateFps(currentFps) {} -PhaseOffsets::VsyncConfigSet VsyncConfiguration::getConfigsForRefreshRate(float fps) const { +PhaseOffsets::VsyncConfigSet VsyncConfiguration::getConfigsForRefreshRate(Fps fps) const { const auto iter = std::find_if(mOffsets.begin(), mOffsets.end(), - [&fps](const std::pair<float, VsyncConfigSet>& candidateFps) { - return fpsEqualsWithMargin(fps, candidateFps.first); + [&fps](const std::pair<Fps, VsyncConfigSet>& candidateFps) { + return fps.equalsWithMargin(candidateFps.first); }); if (iter != mOffsets.end()) { @@ -67,13 +62,13 @@ PhaseOffsets::VsyncConfigSet VsyncConfiguration::getConfigsForRefreshRate(float // Unknown refresh rate. This might happen if we get a hotplug event for an external display. // In this case just construct the offset. - ALOGW("Can't find offset for %.2f fps", fps); - return constructOffsets(static_cast<nsecs_t>(1e9f / fps)); + ALOGW("Can't find offset for %s", to_string(fps).c_str()); + return constructOffsets(fps.getPeriodNsecs()); } -void VsyncConfiguration::initializeOffsets(const std::vector<float>& refreshRates) { +void VsyncConfiguration::initializeOffsets(const std::vector<Fps>& refreshRates) { for (const auto fps : refreshRates) { - mOffsets.emplace(fps, constructOffsets(static_cast<nsecs_t>(1e9f / fps))); + mOffsets.emplace(fps, constructOffsets(fps.getPeriodNsecs())); } } @@ -127,7 +122,7 @@ PhaseOffsets::PhaseOffsets(const scheduler::RefreshRateConfigs& refreshRateConfi .value_or(std::numeric_limits<nsecs_t>::max())) {} PhaseOffsets::PhaseOffsets( - const std::vector<float>& refreshRates, float currentFps, nsecs_t vsyncPhaseOffsetNs, + const std::vector<Fps>& refreshRates, Fps currentFps, nsecs_t vsyncPhaseOffsetNs, nsecs_t sfVSyncPhaseOffsetNs, std::optional<nsecs_t> earlySfOffsetNs, std::optional<nsecs_t> earlyGpuSfOffsetNs, std::optional<nsecs_t> earlyAppOffsetNs, std::optional<nsecs_t> earlyGpuAppOffsetNs, nsecs_t highFpsVsyncPhaseOffsetNs, @@ -378,10 +373,9 @@ WorkDuration::WorkDuration(const scheduler::RefreshRateConfigs& refreshRateConfi validateSysprops(); } -WorkDuration::WorkDuration(const std::vector<float>& refreshRates, float currentFps, - nsecs_t sfDuration, nsecs_t appDuration, nsecs_t sfEarlyDuration, - nsecs_t appEarlyDuration, nsecs_t sfEarlyGpuDuration, - nsecs_t appEarlyGpuDuration) +WorkDuration::WorkDuration(const std::vector<Fps>& refreshRates, Fps currentFps, nsecs_t sfDuration, + nsecs_t appDuration, nsecs_t sfEarlyDuration, nsecs_t appEarlyDuration, + nsecs_t sfEarlyGpuDuration, nsecs_t appEarlyGpuDuration) : VsyncConfiguration(currentFps), mSfDuration(sfDuration), mAppDuration(appDuration), diff --git a/services/surfaceflinger/Scheduler/VsyncConfiguration.h b/services/surfaceflinger/Scheduler/VsyncConfiguration.h index c27a25d738..a120e976f0 100644 --- a/services/surfaceflinger/Scheduler/VsyncConfiguration.h +++ b/services/surfaceflinger/Scheduler/VsyncConfiguration.h @@ -18,6 +18,9 @@ #include <unordered_map> +#include <utils/Timers.h> + +#include "Fps.h" #include "RefreshRateConfigs.h" #include "VsyncModulator.h" @@ -35,9 +38,9 @@ public: virtual ~VsyncConfiguration() = default; virtual VsyncConfigSet getCurrentConfigs() const = 0; - virtual VsyncConfigSet getConfigsForRefreshRate(float fps) const = 0; + virtual VsyncConfigSet getConfigsForRefreshRate(Fps fps) const = 0; - virtual void setRefreshRateFps(float fps) = 0; + virtual void setRefreshRateFps(Fps fps) = 0; virtual void dump(std::string& result) const = 0; }; @@ -51,10 +54,10 @@ namespace impl { */ class VsyncConfiguration : public scheduler::VsyncConfiguration { public: - explicit VsyncConfiguration(float currentFps); + explicit VsyncConfiguration(Fps currentFps); // Returns early, early GL, and late offsets for Apps and SF for a given refresh rate. - VsyncConfigSet getConfigsForRefreshRate(float fps) const override; + VsyncConfigSet getConfigsForRefreshRate(Fps fps) const override; // Returns early, early GL, and late offsets for Apps and SF. VsyncConfigSet getCurrentConfigs() const override { @@ -63,17 +66,17 @@ public: // This function should be called when the device is switching between different // refresh rates, to properly update the offsets. - void setRefreshRateFps(float fps) override { mRefreshRateFps = fps; } + void setRefreshRateFps(Fps fps) override { mRefreshRateFps = fps; } // Returns current offsets in human friendly format. void dump(std::string& result) const override; protected: - void initializeOffsets(const std::vector<float>& refreshRates); + void initializeOffsets(const std::vector<Fps>& refreshRates); virtual VsyncConfiguration::VsyncConfigSet constructOffsets(nsecs_t vsyncDuration) const = 0; - std::unordered_map<float, VsyncConfigSet> mOffsets; - std::atomic<float> mRefreshRateFps; + std::unordered_map<Fps, VsyncConfigSet, std::hash<Fps>, Fps::EqualsInBuckets> mOffsets; + std::atomic<Fps> mRefreshRateFps; }; /* @@ -86,10 +89,9 @@ public: protected: // Used for unit tests - PhaseOffsets(const std::vector<float>& refreshRates, float currentFps, - nsecs_t vsyncPhaseOffsetNs, nsecs_t sfVSyncPhaseOffsetNs, - std::optional<nsecs_t> earlySfOffsetNs, std::optional<nsecs_t> earlyGpuSfOffsetNs, - std::optional<nsecs_t> earlyAppOffsetNs, + PhaseOffsets(const std::vector<Fps>& refreshRates, Fps currentFps, nsecs_t vsyncPhaseOffsetNs, + nsecs_t sfVSyncPhaseOffsetNs, std::optional<nsecs_t> earlySfOffsetNs, + std::optional<nsecs_t> earlyGpuSfOffsetNs, std::optional<nsecs_t> earlyAppOffsetNs, std::optional<nsecs_t> earlyGpuAppOffsetNs, nsecs_t highFpsVsyncPhaseOffsetNs, nsecs_t highFpsSfVSyncPhaseOffsetNs, std::optional<nsecs_t> highFpsEarlySfOffsetNs, std::optional<nsecs_t> highFpsEarlyGpuSfOffsetNs, @@ -130,7 +132,7 @@ public: protected: // Used for unit tests - WorkDuration(const std::vector<float>& refreshRates, float currentFps, nsecs_t sfDuration, + WorkDuration(const std::vector<Fps>& refreshRates, Fps currentFps, nsecs_t sfDuration, nsecs_t appDuration, nsecs_t sfEarlyDuration, nsecs_t appEarlyDuration, nsecs_t sfEarlyGpuDuration, nsecs_t appEarlyGpuDuration); diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index e7bee49911..20003d0c4f 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -921,10 +921,10 @@ status_t SurfaceFlinger::getDisplayConfigs(const sp<IBinder>& displayToken, } const nsecs_t period = hwConfig->getVsyncPeriod(); - config.refreshRate = 1e9f / period; + config.refreshRate = Fps::fromPeriodNsecs(period).getValue(); const auto vsyncConfigSet = - mVsyncConfiguration->getConfigsForRefreshRate(config.refreshRate); + mVsyncConfiguration->getConfigsForRefreshRate(Fps(config.refreshRate)); config.appVsyncOffset = vsyncConfigSet.late.appOffset; config.sfVsyncOffset = vsyncConfigSet.late.sfOffset; config.configGroup = hwConfig->getConfigGroup(); @@ -1042,7 +1042,7 @@ status_t SurfaceFlinger::setActiveConfig(const sp<IBinder>& displayToken, int mo return INVALID_OPERATION; } else { const HwcConfigIndexType config(mode); - const float fps = mRefreshRateConfigs->getRefreshRateFromConfigId(config).getFps(); + const auto fps = mRefreshRateConfigs->getRefreshRateFromConfigId(config).getFps(); // Keep the old switching type. const auto allowGroupSwitching = mRefreshRateConfigs->getCurrentPolicy().allowGroupSwitching; @@ -1071,16 +1071,17 @@ void SurfaceFlinger::setActiveConfigInternal() { std::lock_guard<std::mutex> lock(mActiveConfigLock); mRefreshRateConfigs->setCurrentConfigId(mUpcomingActiveConfig.configId); - mRefreshRateStats->setConfigMode(mUpcomingActiveConfig.configId); display->setActiveConfig(mUpcomingActiveConfig.configId); auto& refreshRate = mRefreshRateConfigs->getRefreshRateFromConfigId(mUpcomingActiveConfig.configId); + mRefreshRateStats->setRefreshRate(refreshRate.getFps()); + if (refreshRate.getVsyncPeriod() != oldRefreshRate.getVsyncPeriod()) { mTimeStats->incrementRefreshRateSwitches(); } updatePhaseConfiguration(refreshRate); - ATRACE_INT("ActiveConfigFPS", refreshRate.getFps()); + ATRACE_INT("ActiveConfigFPS", refreshRate.getFps().getValue()); if (mUpcomingActiveConfig.event != Scheduler::ConfigEvent::None) { const nsecs_t vsyncPeriod = @@ -1138,7 +1139,7 @@ void SurfaceFlinger::performSetActiveConfig() { mUpcomingActiveConfig = *desiredActiveConfig; const auto displayId = display->getPhysicalId(); - ATRACE_INT("ActiveConfigFPS_HWC", refreshRate.getFps()); + ATRACE_INT("ActiveConfigFPS_HWC", refreshRate.getFps().getValue()); // TODO(b/142753666) use constrains hal::VsyncPeriodChangeConstraints constraints; @@ -2885,10 +2886,10 @@ void SurfaceFlinger::initScheduler(PhysicalDisplayId primaryDisplayId) { std::make_unique<scheduler::RefreshRateConfigs>(getHwComposer().getConfigs( primaryDisplayId), currentConfig); + const auto& currRefreshRate = mRefreshRateConfigs->getRefreshRateFromConfigId(currentConfig); mRefreshRateStats = - std::make_unique<scheduler::RefreshRateStats>(*mRefreshRateConfigs, *mTimeStats, - currentConfig, hal::PowerMode::OFF); - mRefreshRateStats->setConfigMode(currentConfig); + std::make_unique<scheduler::RefreshRateStats>(*mTimeStats, currRefreshRate.getFps(), + hal::PowerMode::OFF); mVsyncConfiguration = getFactory().createVsyncConfiguration(*mRefreshRateConfigs); mVsyncModulator.emplace(mVsyncConfiguration->getCurrentConfigs()); @@ -2896,8 +2897,7 @@ void SurfaceFlinger::initScheduler(PhysicalDisplayId primaryDisplayId) { // start the EventThread mScheduler = getFactory().createScheduler(*mRefreshRateConfigs, *this); const auto configs = mVsyncConfiguration->getCurrentConfigs(); - const nsecs_t vsyncPeriod = - mRefreshRateConfigs->getRefreshRateFromConfigId(currentConfig).getVsyncPeriod(); + const nsecs_t vsyncPeriod = currRefreshRate.getVsyncPeriod(); mAppConnectionHandle = mScheduler->createConnection("app", mFrameTimeline->getTokenManager(), /*workDuration=*/configs.late.appWorkDuration, @@ -3792,7 +3792,7 @@ uint32_t SurfaceFlinger::setClientStateLocked( if (what & layer_state_t::eFrameRateChanged) { if (ValidateFrameRate(s.frameRate, s.frameRateCompatibility, "SurfaceFlinger::setClientStateLocked") && - layer->setFrameRate(Layer::FrameRate(s.frameRate, + layer->setFrameRate(Layer::FrameRate(Fps(s.frameRate), Layer::FrameRate::convertCompatibility( s.frameRateCompatibility), s.shouldBeSeamless))) { @@ -4725,8 +4725,8 @@ void SurfaceFlinger::dumpAllLocked(const DumpArgs& args, std::string& result) co const auto activeConfig = getHwComposer().getActiveConfig(*displayId); std::string fps, xDpi, yDpi; if (activeConfig) { - fps = base::StringPrintf("%.2f Hz", - 1e9f / getHwComposer().getDisplayVsyncPeriod(*displayId)); + const auto vsyncPeriod = getHwComposer().getDisplayVsyncPeriod(*displayId); + fps = base::StringPrintf("%s", to_string(Fps::fromPeriodNsecs(vsyncPeriod)).c_str()); xDpi = base::StringPrintf("%.2f", activeConfig->getDpiX()); yDpi = base::StringPrintf("%.2f", activeConfig->getDpiY()); } else { @@ -5982,11 +5982,7 @@ status_t SurfaceFlinger::setDesiredDisplayConfigSpecsInternal( } scheduler::RefreshRateConfigs::Policy currentPolicy = mRefreshRateConfigs->getCurrentPolicy(); - ALOGV("Setting desired display config specs: defaultConfig: %d primaryRange: [%.0f %.0f]" - " expandedRange: [%.0f %.0f]", - currentPolicy.defaultConfig.value(), currentPolicy.primaryRange.min, - currentPolicy.primaryRange.max, currentPolicy.appRequestRange.min, - currentPolicy.appRequestRange.max); + ALOGV("Setting desired display config specs: %s", currentPolicy.toString().c_str()); // TODO(b/140204874): Leave the event in until we do proper testing with all apps that might // be depending in this callback. @@ -6042,8 +6038,8 @@ status_t SurfaceFlinger::setDesiredDisplayConfigSpecs( using Policy = scheduler::RefreshRateConfigs::Policy; const Policy policy{HwcConfigIndexType(defaultConfig), allowGroupSwitching, - {primaryRefreshRateMin, primaryRefreshRateMax}, - {appRequestRefreshRateMin, appRequestRefreshRateMax}}; + {Fps(primaryRefreshRateMin), Fps(primaryRefreshRateMax)}, + {Fps(appRequestRefreshRateMin), Fps(appRequestRefreshRateMax)}}; constexpr bool kOverridePolicy = false; return setDesiredDisplayConfigSpecsInternal(display, policy, kOverridePolicy); @@ -6075,10 +6071,10 @@ status_t SurfaceFlinger::getDesiredDisplayConfigSpecs( mRefreshRateConfigs->getDisplayManagerPolicy(); *outDefaultConfig = policy.defaultConfig.value(); *outAllowGroupSwitching = policy.allowGroupSwitching; - *outPrimaryRefreshRateMin = policy.primaryRange.min; - *outPrimaryRefreshRateMax = policy.primaryRange.max; - *outAppRequestRefreshRateMin = policy.appRequestRange.min; - *outAppRequestRefreshRateMax = policy.appRequestRange.max; + *outPrimaryRefreshRateMin = policy.primaryRange.min.getValue(); + *outPrimaryRefreshRateMax = policy.primaryRange.max.getValue(); + *outAppRequestRefreshRateMin = policy.appRequestRange.min.getValue(); + *outAppRequestRefreshRateMax = policy.appRequestRange.max.getValue(); return NO_ERROR; } else if (display->isVirtual()) { return INVALID_OPERATION; @@ -6087,10 +6083,10 @@ status_t SurfaceFlinger::getDesiredDisplayConfigSpecs( *outDefaultConfig = getHwComposer().getActiveConfigIndex(displayId); *outAllowGroupSwitching = false; auto vsyncPeriod = getHwComposer().getActiveConfig(displayId)->getVsyncPeriod(); - *outPrimaryRefreshRateMin = 1e9f / vsyncPeriod; - *outPrimaryRefreshRateMax = 1e9f / vsyncPeriod; - *outAppRequestRefreshRateMin = 1e9f / vsyncPeriod; - *outAppRequestRefreshRateMax = 1e9f / vsyncPeriod; + *outPrimaryRefreshRateMin = Fps::fromPeriodNsecs(vsyncPeriod).getValue(); + *outPrimaryRefreshRateMax = Fps::fromPeriodNsecs(vsyncPeriod).getValue(); + *outAppRequestRefreshRateMin = Fps::fromPeriodNsecs(vsyncPeriod).getValue(); + *outAppRequestRefreshRateMax = Fps::fromPeriodNsecs(vsyncPeriod).getValue(); return NO_ERROR; } } @@ -6186,7 +6182,7 @@ status_t SurfaceFlinger::setFrameRate(const sp<IGraphicBufferProducer>& surface, return BAD_VALUE; } if (layer->setFrameRate( - Layer::FrameRate(frameRate, + Layer::FrameRate(Fps{frameRate}, Layer::FrameRate::convertCompatibility(compatibility), shouldBeSeamless))) { setTransactionFlags(eTraversalNeeded); diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp index 871222c8b0..a00e959762 100644 --- a/services/surfaceflinger/tests/unittests/Android.bp +++ b/services/surfaceflinger/tests/unittests/Android.bp @@ -44,6 +44,7 @@ cc_test { "DisplayDevice_GetBestColorModeTest.cpp", "DisplayDevice_SetProjectionTest.cpp", "EventThreadTest.cpp", + "FpsTest.cpp", "FrameTimelineTest.cpp", "HWComposerTest.cpp", "OneShotTimerTest.cpp", diff --git a/services/surfaceflinger/tests/unittests/FakeVsyncConfiguration.h b/services/surfaceflinger/tests/unittests/FakeVsyncConfiguration.h index 4cd1e0adf1..36e24d25f7 100644 --- a/services/surfaceflinger/tests/unittests/FakeVsyncConfiguration.h +++ b/services/surfaceflinger/tests/unittests/FakeVsyncConfiguration.h @@ -26,7 +26,7 @@ struct FakePhaseOffsets : VsyncConfiguration { static constexpr nsecs_t FAKE_PHASE_OFFSET_NS = 0; static constexpr auto FAKE_DURATION_OFFSET_NS = std::chrono::nanoseconds(0); - VsyncConfigSet getConfigsForRefreshRate(float) const override { return getCurrentConfigs(); } + VsyncConfigSet getConfigsForRefreshRate(Fps) const override { return getCurrentConfigs(); } VsyncConfigSet getCurrentConfigs() const override { return {{FAKE_PHASE_OFFSET_NS, FAKE_PHASE_OFFSET_NS, FAKE_DURATION_OFFSET_NS, @@ -37,7 +37,7 @@ struct FakePhaseOffsets : VsyncConfiguration { FAKE_DURATION_OFFSET_NS}}; } - void setRefreshRateFps(float) override {} + void setRefreshRateFps(Fps) override {} void dump(std::string&) const override {} }; diff --git a/services/surfaceflinger/tests/unittests/FpsTest.cpp b/services/surfaceflinger/tests/unittests/FpsTest.cpp new file mode 100644 index 0000000000..db732cfeaf --- /dev/null +++ b/services/surfaceflinger/tests/unittests/FpsTest.cpp @@ -0,0 +1,98 @@ +/* + * Copyright 2020 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. + */ + +#include "Fps.h" + +#include <gmock/gmock.h> +#include <gtest/gtest.h> + +namespace android { + +TEST(FpsTest, construct) { + Fps fpsDefault; + EXPECT_FALSE(fpsDefault.isValid()); + + Fps fps1(60.0f); + EXPECT_TRUE(fps1.isValid()); + Fps fps2 = Fps::fromPeriodNsecs(static_cast<nsecs_t>(1e9f / 60.0f)); + EXPECT_TRUE(fps2.isValid()); + EXPECT_TRUE(fps1.equalsWithMargin(fps2)); +} + +TEST(FpsTest, compare) { + constexpr float kEpsilon = 1e-4f; + const Fps::EqualsInBuckets equalsInBuckets; + const Fps::EqualsWithMargin equalsWithMargin; + + EXPECT_TRUE(Fps(60.0f).equalsWithMargin(Fps(60.f))); + EXPECT_TRUE(Fps(60.0f).equalsWithMargin(Fps(60.f - kEpsilon))); + EXPECT_TRUE(Fps(60.0f).equalsWithMargin(Fps(60.f + kEpsilon))); + + EXPECT_TRUE(equalsInBuckets(Fps(60.0f), Fps(60.0f))); + EXPECT_TRUE(equalsInBuckets(Fps(60.0f), Fps(60.0f - kEpsilon))); + EXPECT_TRUE(equalsInBuckets(Fps(60.0f), Fps(60.0f + kEpsilon))); + + EXPECT_TRUE(equalsWithMargin(Fps(60.0f), Fps(60.0f))); + EXPECT_TRUE(equalsWithMargin(Fps(60.0f), Fps(60.0f - kEpsilon))); + EXPECT_TRUE(equalsWithMargin(Fps(60.0f), Fps(60.0f + kEpsilon))); + + EXPECT_TRUE(Fps(60.0f).lessThanOrEqualWithMargin(Fps(60.f + kEpsilon))); + EXPECT_TRUE(Fps(60.0f).lessThanOrEqualWithMargin(Fps(60.f))); + EXPECT_TRUE(Fps(60.0f).lessThanOrEqualWithMargin(Fps(60.f - kEpsilon))); + + EXPECT_TRUE(Fps(60.0f).greaterThanOrEqualWithMargin(Fps(60.f + kEpsilon))); + EXPECT_TRUE(Fps(60.0f).greaterThanOrEqualWithMargin(Fps(60.f))); + EXPECT_TRUE(Fps(60.0f).greaterThanOrEqualWithMargin(Fps(60.f - kEpsilon))); + + // Fps with difference of 1 should be different + EXPECT_FALSE(Fps(60.0f).equalsWithMargin(Fps(61.f))); + EXPECT_TRUE(Fps(60.0f).lessThanWithMargin(Fps(61.f))); + EXPECT_TRUE(Fps(60.0f).greaterThanWithMargin(Fps(59.f))); + + // These are common refresh rates which should be different. + EXPECT_FALSE(Fps(60.0f).equalsWithMargin(Fps(59.94f))); + EXPECT_TRUE(Fps(60.0f).greaterThanWithMargin(Fps(59.94f))); + EXPECT_FALSE(equalsInBuckets(Fps(60.0f), Fps(59.94f))); + EXPECT_FALSE(equalsWithMargin(Fps(60.0f), Fps(59.94f))); + EXPECT_NE(std::hash<Fps>()(Fps(60.0f)), std::hash<Fps>()(Fps(59.94f))); + + EXPECT_FALSE(Fps(30.0f).equalsWithMargin(Fps(29.97f))); + EXPECT_TRUE(Fps(30.0f).greaterThanWithMargin(Fps(29.97f))); + EXPECT_FALSE(equalsInBuckets(Fps(30.0f), Fps(29.97f))); + EXPECT_FALSE(equalsWithMargin(Fps(30.0f), Fps(29.97f))); + EXPECT_NE(std::hash<Fps>()(Fps(30.0f)), std::hash<Fps>()(Fps(29.97f))); +} + +TEST(FpsTest, getIntValue) { + EXPECT_EQ(30, Fps(30.1f).getIntValue()); + EXPECT_EQ(31, Fps(30.9f).getIntValue()); + EXPECT_EQ(31, Fps(30.5f).getIntValue()); +} + +TEST(FpsTest, equalsInBucketsImpliesEqualHashes) { + constexpr float kStep = 1e-4f; + const Fps::EqualsInBuckets equals; + for (float fps = 30.0f; fps < 31.0f; fps += kStep) { + const Fps left(fps); + const Fps right(fps + kStep); + if (equals(left, right)) { + ASSERT_EQ(std::hash<Fps>()(left), std::hash<Fps>()(right)) + << "left= " << left << " right=" << right; + } + } +} + +} // namespace android diff --git a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp index fbb46370b9..cbc1e0203a 100644 --- a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp +++ b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp @@ -32,7 +32,9 @@ using testing::_; using testing::Return; -namespace android::scheduler { +namespace android { + +namespace scheduler { class LayerHistoryTest : public testing::Test { protected: @@ -43,11 +45,11 @@ protected: static constexpr auto REFRESH_RATE_AVERAGE_HISTORY_DURATION = LayerInfo::RefreshRateHistory::HISTORY_DURATION; - static constexpr float LO_FPS = 30.f; - static constexpr auto LO_FPS_PERIOD = static_cast<nsecs_t>(1e9f / LO_FPS); + static constexpr Fps LO_FPS{30.f}; + static constexpr auto LO_FPS_PERIOD = LO_FPS.getPeriodNsecs(); - static constexpr float HI_FPS = 90.f; - static constexpr auto HI_FPS_PERIOD = static_cast<nsecs_t>(1e9f / HI_FPS); + static constexpr Fps HI_FPS{90.f}; + static constexpr auto HI_FPS_PERIOD = HI_FPS.getPeriodNsecs(); LayerHistoryTest() { mFlinger.resetScheduler(mScheduler); } @@ -88,20 +90,19 @@ protected: return sp<mock::MockLayer>(new mock::MockLayer(mFlinger.flinger(), std::move(name))); } - void recordFramesAndExpect(const sp<mock::MockLayer>& layer, nsecs_t& time, float frameRate, - float desiredRefreshRate, int numFrames) { - const nsecs_t framePeriod = static_cast<nsecs_t>(1e9f / frameRate); + void recordFramesAndExpect(const sp<mock::MockLayer>& layer, nsecs_t& time, Fps frameRate, + Fps desiredRefreshRate, int numFrames) { LayerHistory::Summary summary; for (int i = 0; i < numFrames; i++) { history().record(layer.get(), time, time, LayerHistory::LayerUpdateType::Buffer); - time += framePeriod; + time += frameRate.getPeriodNsecs(); summary = history().summarize(time); } ASSERT_EQ(1, summary.size()); ASSERT_EQ(LayerHistory::LayerVoteType::Heuristic, summary[0].vote); - ASSERT_FLOAT_EQ(desiredRefreshRate, summary[0].desiredRefreshRate) + ASSERT_TRUE(desiredRefreshRate.equalsWithMargin(summary[0].desiredRefreshRate)) << "Frame rate is " << frameRate; } @@ -196,7 +197,7 @@ TEST_F(LayerHistoryTest, explicitTimestamp) { ASSERT_EQ(1, history().summarize(time).size()); EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, history().summarize(time)[0].vote); - EXPECT_FLOAT_EQ(LO_FPS, history().summarize(time)[0].desiredRefreshRate); + EXPECT_TRUE(LO_FPS.equalsWithMargin(history().summarize(time)[0].desiredRefreshRate)); EXPECT_EQ(1, activeLayerCount()); EXPECT_EQ(1, frequentLayerCount(time)); } @@ -289,7 +290,7 @@ TEST_F(LayerHistoryTest, oneLayerExplicitVote) { EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); EXPECT_CALL(*layer, getFrameRateForLayerTree()) .WillRepeatedly( - Return(Layer::FrameRate(73.4f, Layer::FrameRateCompatibility::Default))); + Return(Layer::FrameRate(Fps(73.4f), Layer::FrameRateCompatibility::Default))); EXPECT_EQ(1, layerCount()); EXPECT_EQ(0, activeLayerCount()); @@ -302,7 +303,7 @@ TEST_F(LayerHistoryTest, oneLayerExplicitVote) { ASSERT_EQ(1, history().summarize(time).size()); EXPECT_EQ(LayerHistory::LayerVoteType::ExplicitDefault, history().summarize(time)[0].vote); - EXPECT_FLOAT_EQ(73.4f, history().summarize(time)[0].desiredRefreshRate); + EXPECT_TRUE(Fps(73.4f).equalsWithMargin(history().summarize(time)[0].desiredRefreshRate)); EXPECT_EQ(1, activeLayerCount()); EXPECT_EQ(1, frequentLayerCount(time)); @@ -311,7 +312,7 @@ TEST_F(LayerHistoryTest, oneLayerExplicitVote) { time += MAX_ACTIVE_LAYER_PERIOD_NS.count(); ASSERT_EQ(1, history().summarize(time).size()); EXPECT_EQ(LayerHistory::LayerVoteType::ExplicitDefault, history().summarize(time)[0].vote); - EXPECT_FLOAT_EQ(73.4f, history().summarize(time)[0].desiredRefreshRate); + EXPECT_TRUE(Fps(73.4f).equalsWithMargin(history().summarize(time)[0].desiredRefreshRate)); EXPECT_EQ(1, activeLayerCount()); EXPECT_EQ(0, frequentLayerCount(time)); } @@ -321,7 +322,7 @@ TEST_F(LayerHistoryTest, oneLayerExplicitExactVote) { EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); EXPECT_CALL(*layer, getFrameRateForLayerTree()) .WillRepeatedly(Return( - Layer::FrameRate(73.4f, Layer::FrameRateCompatibility::ExactOrMultiple))); + Layer::FrameRate(Fps(73.4f), Layer::FrameRateCompatibility::ExactOrMultiple))); EXPECT_EQ(1, layerCount()); EXPECT_EQ(0, activeLayerCount()); @@ -335,7 +336,7 @@ TEST_F(LayerHistoryTest, oneLayerExplicitExactVote) { ASSERT_EQ(1, history().summarize(time).size()); EXPECT_EQ(LayerHistory::LayerVoteType::ExplicitExactOrMultiple, history().summarize(time)[0].vote); - EXPECT_FLOAT_EQ(73.4f, history().summarize(time)[0].desiredRefreshRate); + EXPECT_TRUE(Fps(73.4f).equalsWithMargin(history().summarize(time)[0].desiredRefreshRate)); EXPECT_EQ(1, activeLayerCount()); EXPECT_EQ(1, frequentLayerCount(time)); @@ -345,7 +346,7 @@ TEST_F(LayerHistoryTest, oneLayerExplicitExactVote) { ASSERT_EQ(1, history().summarize(time).size()); EXPECT_EQ(LayerHistory::LayerVoteType::ExplicitExactOrMultiple, history().summarize(time)[0].vote); - EXPECT_FLOAT_EQ(73.4f, history().summarize(time)[0].desiredRefreshRate); + EXPECT_TRUE(Fps(73.4f).equalsWithMargin(history().summarize(time)[0].desiredRefreshRate)); EXPECT_EQ(1, activeLayerCount()); EXPECT_EQ(0, frequentLayerCount(time)); } @@ -397,7 +398,8 @@ TEST_F(LayerHistoryTest, multipleLayers) { ASSERT_EQ(2, summary.size()); EXPECT_EQ(LayerHistory::LayerVoteType::Min, summary[0].vote); ASSERT_EQ(LayerHistory::LayerVoteType::Heuristic, summary[1].vote); - EXPECT_FLOAT_EQ(HI_FPS, history().summarize(time)[1].desiredRefreshRate); + EXPECT_TRUE(HI_FPS.equalsWithMargin(history().summarize(time)[1].desiredRefreshRate)); + EXPECT_EQ(2, activeLayerCount()); EXPECT_EQ(1, frequentLayerCount(time)); @@ -411,7 +413,7 @@ TEST_F(LayerHistoryTest, multipleLayers) { ASSERT_EQ(1, summary.size()); EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, summary[0].vote); - EXPECT_FLOAT_EQ(LO_FPS, summary[0].desiredRefreshRate); + EXPECT_TRUE(LO_FPS.equalsWithMargin(summary[0].desiredRefreshRate)); EXPECT_EQ(1, activeLayerCount()); EXPECT_EQ(1, frequentLayerCount(time)); @@ -430,7 +432,7 @@ TEST_F(LayerHistoryTest, multipleLayers) { ASSERT_EQ(2, summary.size()); EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, summary[0].vote); - EXPECT_FLOAT_EQ(LO_FPS, summary[0].desiredRefreshRate); + EXPECT_TRUE(LO_FPS.equalsWithMargin(summary[0].desiredRefreshRate)); EXPECT_EQ(LayerHistory::LayerVoteType::Max, summary[1].vote); EXPECT_EQ(2, activeLayerCount()); EXPECT_EQ(2, frequentLayerCount(time)); @@ -440,9 +442,9 @@ TEST_F(LayerHistoryTest, multipleLayers) { summary = history().summarize(time); ASSERT_EQ(2, summary.size()); EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, summary[0].vote); - EXPECT_FLOAT_EQ(LO_FPS, summary[0].desiredRefreshRate); + EXPECT_TRUE(LO_FPS.equalsWithMargin(summary[0].desiredRefreshRate)); EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, summary[1].vote); - EXPECT_FLOAT_EQ(HI_FPS, summary[1].desiredRefreshRate); + EXPECT_TRUE(HI_FPS.equalsWithMargin(summary[1].desiredRefreshRate)); EXPECT_EQ(2, activeLayerCount()); EXPECT_EQ(2, frequentLayerCount(time)); @@ -452,9 +454,9 @@ TEST_F(LayerHistoryTest, multipleLayers) { ASSERT_EQ(2, summary.size()); EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, summary[0].vote); EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, summary[0].vote); - EXPECT_FLOAT_EQ(LO_FPS, summary[0].desiredRefreshRate); + EXPECT_TRUE(LO_FPS.equalsWithMargin(summary[0].desiredRefreshRate)); EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, summary[1].vote); - EXPECT_FLOAT_EQ(HI_FPS, summary[1].desiredRefreshRate); + EXPECT_TRUE(HI_FPS.equalsWithMargin(summary[1].desiredRefreshRate)); EXPECT_EQ(2, layerCount()); EXPECT_EQ(2, activeLayerCount()); EXPECT_EQ(2, frequentLayerCount(time)); @@ -469,7 +471,7 @@ TEST_F(LayerHistoryTest, multipleLayers) { ASSERT_EQ(1, summary.size()); EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, summary[0].vote); - EXPECT_FLOAT_EQ(LO_FPS, summary[0].desiredRefreshRate); + EXPECT_TRUE(LO_FPS.equalsWithMargin(summary[0].desiredRefreshRate)); EXPECT_EQ(1, activeLayerCount()); EXPECT_EQ(1, frequentLayerCount(time)); @@ -490,7 +492,7 @@ TEST_F(LayerHistoryTest, multipleLayers) { ASSERT_EQ(1, summary.size()); EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, summary[0].vote); - EXPECT_FLOAT_EQ(HI_FPS, summary[0].desiredRefreshRate); + EXPECT_TRUE(HI_FPS.equalsWithMargin(summary[0].desiredRefreshRate)); EXPECT_EQ(1, layerCount()); EXPECT_EQ(1, activeLayerCount()); EXPECT_EQ(1, frequentLayerCount(time)); @@ -567,12 +569,12 @@ TEST_F(LayerHistoryTest, invisibleExplicitLayer) { EXPECT_CALL(*explicitVisiblelayer, isVisible()).WillRepeatedly(Return(true)); EXPECT_CALL(*explicitVisiblelayer, getFrameRateForLayerTree()) .WillRepeatedly(Return( - Layer::FrameRate(60.0f, Layer::FrameRateCompatibility::ExactOrMultiple))); + Layer::FrameRate(Fps(60.0f), Layer::FrameRateCompatibility::ExactOrMultiple))); EXPECT_CALL(*explicitInvisiblelayer, isVisible()).WillRepeatedly(Return(false)); EXPECT_CALL(*explicitInvisiblelayer, getFrameRateForLayerTree()) .WillRepeatedly(Return( - Layer::FrameRate(90.0f, Layer::FrameRateCompatibility::ExactOrMultiple))); + Layer::FrameRate(Fps(90.0f), Layer::FrameRateCompatibility::ExactOrMultiple))); nsecs_t time = systemTime(); @@ -585,7 +587,7 @@ TEST_F(LayerHistoryTest, invisibleExplicitLayer) { ASSERT_EQ(1, history().summarize(time).size()); EXPECT_EQ(LayerHistory::LayerVoteType::ExplicitExactOrMultiple, history().summarize(time)[0].vote); - EXPECT_FLOAT_EQ(60.0f, history().summarize(time)[0].desiredRefreshRate); + EXPECT_TRUE(Fps(60.0f).equalsWithMargin(history().summarize(time)[0].desiredRefreshRate)); EXPECT_EQ(2, activeLayerCount()); EXPECT_EQ(2, frequentLayerCount(time)); } @@ -643,7 +645,7 @@ TEST_F(LayerHistoryTest, heuristicLayer60Hz) { nsecs_t time = systemTime(); for (float fps = 54.0f; fps < 65.0f; fps += 0.1f) { - recordFramesAndExpect(layer, time, fps, 60.0f, PRESENT_TIME_HISTORY_SIZE); + recordFramesAndExpect(layer, time, Fps(fps), Fps(60.0f), PRESENT_TIME_HISTORY_SIZE); } } @@ -653,13 +655,13 @@ TEST_F(LayerHistoryTest, heuristicLayer60_30Hz) { EXPECT_CALL(*layer, getFrameRateForLayerTree()).WillRepeatedly(Return(Layer::FrameRate())); nsecs_t time = systemTime(); - recordFramesAndExpect(layer, time, 60.0f, 60.0f, PRESENT_TIME_HISTORY_SIZE); + recordFramesAndExpect(layer, time, Fps(60.0f), Fps(60.0f), PRESENT_TIME_HISTORY_SIZE); - recordFramesAndExpect(layer, time, 60.0f, 60.0f, PRESENT_TIME_HISTORY_SIZE); - recordFramesAndExpect(layer, time, 30.0f, 60.0f, PRESENT_TIME_HISTORY_SIZE); - recordFramesAndExpect(layer, time, 30.0f, 30.0f, PRESENT_TIME_HISTORY_SIZE); - recordFramesAndExpect(layer, time, 60.0f, 30.0f, PRESENT_TIME_HISTORY_SIZE); - recordFramesAndExpect(layer, time, 60.0f, 60.0f, PRESENT_TIME_HISTORY_SIZE); + recordFramesAndExpect(layer, time, Fps(60.0f), Fps(60.0f), PRESENT_TIME_HISTORY_SIZE); + recordFramesAndExpect(layer, time, Fps(30.0f), Fps(60.0f), PRESENT_TIME_HISTORY_SIZE); + recordFramesAndExpect(layer, time, Fps(30.0f), Fps(30.0f), PRESENT_TIME_HISTORY_SIZE); + recordFramesAndExpect(layer, time, Fps(60.0f), Fps(30.0f), PRESENT_TIME_HISTORY_SIZE); + recordFramesAndExpect(layer, time, Fps(60.0f), Fps(60.0f), PRESENT_TIME_HISTORY_SIZE); } TEST_F(LayerHistoryTest, heuristicLayerNotOscillating) { @@ -669,11 +671,11 @@ TEST_F(LayerHistoryTest, heuristicLayerNotOscillating) { nsecs_t time = systemTime(); - recordFramesAndExpect(layer, time, 27.10f, 30.0f, PRESENT_TIME_HISTORY_SIZE); - recordFramesAndExpect(layer, time, 26.90f, 30.0f, PRESENT_TIME_HISTORY_SIZE); - recordFramesAndExpect(layer, time, 26.00f, 24.0f, PRESENT_TIME_HISTORY_SIZE); - recordFramesAndExpect(layer, time, 26.90f, 24.0f, PRESENT_TIME_HISTORY_SIZE); - recordFramesAndExpect(layer, time, 27.10f, 30.0f, PRESENT_TIME_HISTORY_SIZE); + recordFramesAndExpect(layer, time, Fps(27.10f), Fps(30.0f), PRESENT_TIME_HISTORY_SIZE); + recordFramesAndExpect(layer, time, Fps(26.90f), Fps(30.0f), PRESENT_TIME_HISTORY_SIZE); + recordFramesAndExpect(layer, time, Fps(26.00f), Fps(24.0f), PRESENT_TIME_HISTORY_SIZE); + recordFramesAndExpect(layer, time, Fps(26.90f), Fps(24.0f), PRESENT_TIME_HISTORY_SIZE); + recordFramesAndExpect(layer, time, Fps(27.10f), Fps(30.0f), PRESENT_TIME_HISTORY_SIZE); } class LayerHistoryTestParameterized : public LayerHistoryTest, @@ -724,7 +726,7 @@ TEST_P(LayerHistoryTestParameterized, HeuristicLayerWithInfrequentLayer) { bool max = false; bool min = false; - float heuristic = 0; + Fps heuristic{0.0}; for (const auto& layer : history().summarize(time)) { if (layer.vote == LayerHistory::LayerVoteType::Heuristic) { heuristic = layer.desiredRefreshRate; @@ -736,7 +738,7 @@ TEST_P(LayerHistoryTestParameterized, HeuristicLayerWithInfrequentLayer) { } if (infrequentLayerUpdates > FREQUENT_LAYER_WINDOW_SIZE) { - EXPECT_FLOAT_EQ(24.0f, heuristic); + EXPECT_TRUE(Fps(24.0f).equalsWithMargin(heuristic)); EXPECT_FALSE(max); if (history().summarize(time).size() == 2) { EXPECT_TRUE(min); @@ -750,4 +752,5 @@ INSTANTIATE_TEST_CASE_P(LeapYearTests, LayerHistoryTestParameterized, ::testing::Values(1s, 2s, 3s, 4s, 5s)); } // namespace -} // namespace android::scheduler +} // namespace scheduler +} // namespace android diff --git a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp index f2b7191500..83ad737526 100644 --- a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp +++ b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp @@ -30,6 +30,7 @@ using namespace std::chrono_literals; using testing::_; namespace android { + namespace scheduler { namespace hal = android::hardware::graphics::composer::hal; @@ -43,11 +44,11 @@ protected: RefreshRateConfigsTest(); ~RefreshRateConfigsTest(); - float findClosestKnownFrameRate(const RefreshRateConfigs& refreshRateConfigs, float frameRate) { + Fps findClosestKnownFrameRate(const RefreshRateConfigs& refreshRateConfigs, Fps frameRate) { return refreshRateConfigs.findClosestKnownFrameRate(frameRate); } - std::vector<float> getKnownFrameRate(const RefreshRateConfigs& refreshRateConfigs) { + std::vector<Fps> getKnownFrameRate(const RefreshRateConfigs& refreshRateConfigs) { return refreshRateConfigs.mKnownFrameRates; } @@ -62,29 +63,29 @@ protected: // Test configs std::shared_ptr<const HWC2::Display::Config> mConfig60 = - createConfig(HWC_CONFIG_ID_60, 0, static_cast<int64_t>(1e9f / 60)); + createConfig(HWC_CONFIG_ID_60, 0, Fps(60.0f).getPeriodNsecs()); std::shared_ptr<const HWC2::Display::Config> mConfig90 = - createConfig(HWC_CONFIG_ID_90, 0, static_cast<int64_t>(1e9f / 90)); + createConfig(HWC_CONFIG_ID_90, 0, Fps(90.0f).getPeriodNsecs()); std::shared_ptr<const HWC2::Display::Config> mConfig90DifferentGroup = - createConfig(HWC_CONFIG_ID_90, 1, static_cast<int64_t>(1e9f / 90)); + createConfig(HWC_CONFIG_ID_90, 1, Fps(90.0f).getPeriodNsecs()); std::shared_ptr<const HWC2::Display::Config> mConfig90DifferentResolution = - createConfig(HWC_CONFIG_ID_90, 0, static_cast<int64_t>(1e9f / 90), 111, 222); + createConfig(HWC_CONFIG_ID_90, 0, Fps(90.0f).getPeriodNsecs(), 111, 222); std::shared_ptr<const HWC2::Display::Config> mConfig72 = - createConfig(HWC_CONFIG_ID_72, 0, static_cast<int64_t>(1e9f / 72)); + createConfig(HWC_CONFIG_ID_72, 0, Fps(72.0f).getPeriodNsecs()); std::shared_ptr<const HWC2::Display::Config> mConfig72DifferentGroup = - createConfig(HWC_CONFIG_ID_72, 1, static_cast<int64_t>(1e9f / 72)); + createConfig(HWC_CONFIG_ID_72, 1, Fps(72.0f).getPeriodNsecs()); std::shared_ptr<const HWC2::Display::Config> mConfig120 = - createConfig(HWC_CONFIG_ID_120, 0, static_cast<int64_t>(1e9f / 120)); + createConfig(HWC_CONFIG_ID_120, 0, Fps(120.0f).getPeriodNsecs()); std::shared_ptr<const HWC2::Display::Config> mConfig120DifferentGroup = - createConfig(HWC_CONFIG_ID_120, 1, static_cast<int64_t>(1e9f / 120)); + createConfig(HWC_CONFIG_ID_120, 1, Fps(120.0f).getPeriodNsecs()); std::shared_ptr<const HWC2::Display::Config> mConfig30 = - createConfig(HWC_CONFIG_ID_30, 0, static_cast<int64_t>(1e9f / 30)); + createConfig(HWC_CONFIG_ID_30, 0, Fps(30.0f).getPeriodNsecs()); std::shared_ptr<const HWC2::Display::Config> mConfig30DifferentGroup = - createConfig(HWC_CONFIG_ID_30, 1, static_cast<int64_t>(1e9f / 30)); + createConfig(HWC_CONFIG_ID_30, 1, Fps(30.0f).getPeriodNsecs()); std::shared_ptr<const HWC2::Display::Config> mConfig25DifferentGroup = - createConfig(HWC_CONFIG_ID_25, 1, static_cast<int64_t>(1e9f / 25)); + createConfig(HWC_CONFIG_ID_25, 1, Fps(25.0f).getPeriodNsecs()); std::shared_ptr<const HWC2::Display::Config> mConfig50 = - createConfig(HWC_CONFIG_ID_50, 0, static_cast<int64_t>(1e9f / 50)); + createConfig(HWC_CONFIG_ID_50, 0, Fps(50.0f).getPeriodNsecs()); // Test device configurations // The positions of the configs in the arrays below MUST match their IDs. For example, @@ -124,23 +125,23 @@ protected: mConfig50}; // Expected RefreshRate objects - RefreshRate mExpected60Config = {HWC_CONFIG_ID_60, mConfig60, "60fps", 60, + RefreshRate mExpected60Config = {HWC_CONFIG_ID_60, mConfig60, Fps(60), RefreshRate::ConstructorTag(0)}; RefreshRate mExpectedAlmost60Config = {HWC_CONFIG_ID_60, - createConfig(HWC_CONFIG_ID_60, 0, 16666665), "60fps", 60, + createConfig(HWC_CONFIG_ID_60, 0, 16666665), Fps(60), RefreshRate::ConstructorTag(0)}; - RefreshRate mExpected90Config = {HWC_CONFIG_ID_90, mConfig90, "90fps", 90, + RefreshRate mExpected90Config = {HWC_CONFIG_ID_90, mConfig90, Fps(90), RefreshRate::ConstructorTag(0)}; RefreshRate mExpected90DifferentGroupConfig = {HWC_CONFIG_ID_90, mConfig90DifferentGroup, - "90fps", 90, RefreshRate::ConstructorTag(0)}; + Fps(90), RefreshRate::ConstructorTag(0)}; RefreshRate mExpected90DifferentResolutionConfig = {HWC_CONFIG_ID_90, - mConfig90DifferentResolution, "90fps", 90, + mConfig90DifferentResolution, Fps(90), RefreshRate::ConstructorTag(0)}; - RefreshRate mExpected72Config = {HWC_CONFIG_ID_72, mConfig72, "72fps", 72, + RefreshRate mExpected72Config = {HWC_CONFIG_ID_72, mConfig72, Fps(72.0f), RefreshRate::ConstructorTag(0)}; - RefreshRate mExpected30Config = {HWC_CONFIG_ID_30, mConfig30, "30fps", 30, + RefreshRate mExpected30Config = {HWC_CONFIG_ID_30, mConfig30, Fps(30), RefreshRate::ConstructorTag(0)}; - RefreshRate mExpected120Config = {HWC_CONFIG_ID_120, mConfig120, "120fps", 120, + RefreshRate mExpected120Config = {HWC_CONFIG_ID_120, mConfig120, Fps(120), RefreshRate::ConstructorTag(0)}; Hwc2::mock::Display mDisplay; @@ -192,8 +193,11 @@ TEST_F(RefreshRateConfigsTest, invalidPolicy) { auto refreshRateConfigs = std::make_unique<RefreshRateConfigs>(m60OnlyConfigDevice, /*currentConfigId=*/HWC_CONFIG_ID_60); - ASSERT_LT(refreshRateConfigs->setDisplayManagerPolicy({HwcConfigIndexType(10), {60, 60}}), 0); - ASSERT_LT(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_60, {20, 40}}), 0); + ASSERT_LT(refreshRateConfigs->setDisplayManagerPolicy( + {HwcConfigIndexType(10), {Fps(60), Fps(60)}}), + 0); + ASSERT_LT(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_60, {Fps(20), Fps(40)}}), + 0); } TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_storesFullRefreshRateMap) { @@ -227,7 +231,8 @@ TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_storesFullRefreshRateMap_differe ASSERT_EQ(mExpected60Config, minRate60); ASSERT_EQ(mExpected60Config, performanceRate60); - ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_90, {60, 90}}), 0); + ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_90, {Fps(60), Fps(90)}}), + 0); refreshRateConfigs->setCurrentConfigId(HWC_CONFIG_ID_90); const auto& minRate90 = refreshRateConfigs->getMinRefreshRateByPolicy(); @@ -252,7 +257,8 @@ TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_storesFullRefreshRateMap_differe ASSERT_EQ(mExpected60Config, minRate60); ASSERT_EQ(mExpected60Config, performanceRate60); - ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_90, {60, 90}}), 0); + ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_90, {Fps(60), Fps(90)}}), + 0); refreshRateConfigs->setCurrentConfigId(HWC_CONFIG_ID_90); const auto& minRate90 = refreshRateConfigs->getMinRefreshRateByPolicy(); @@ -274,7 +280,8 @@ TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_policyChange) { ASSERT_EQ(mExpected60Config, minRate); ASSERT_EQ(mExpected90Config, performanceRate); - ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_60, {60, 60}}), 0); + ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_60, {Fps(60), Fps(60)}}), + 0); auto& minRate60 = refreshRateConfigs->getMinRefreshRateByPolicy(); auto& performanceRate60 = refreshRateConfigs->getMaxRefreshRateByPolicy(); @@ -297,7 +304,8 @@ TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_getCurrentRefreshRate) { EXPECT_EQ(current.getConfigId(), HWC_CONFIG_ID_90); } - ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_90, {90, 90}}), 0); + ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_90, {Fps(90), Fps(90)}}), + 0); { auto& current = refreshRateConfigs->getCurrentRefreshRate(); EXPECT_EQ(current.getConfigId(), HWC_CONFIG_ID_90); @@ -315,7 +323,8 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_noLayers) { EXPECT_EQ(mExpected90Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_60, {60, 60}}), 0); + ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_60, {Fps(60), Fps(60)}}), + 0); EXPECT_EQ(mExpected60Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); } @@ -338,34 +347,35 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_60_90) { EXPECT_EQ(mExpected90Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - lr.desiredRefreshRate = 90.0f; + lr.desiredRefreshRate = Fps(90.0f); lr.vote = LayerVoteType::Heuristic; lr.name = "90Hz Heuristic"; EXPECT_EQ(mExpected90Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - lr.desiredRefreshRate = 60.0f; + lr.desiredRefreshRate = Fps(60.0f); lr.name = "60Hz Heuristic"; EXPECT_EQ(mExpected60Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - lr.desiredRefreshRate = 45.0f; + lr.desiredRefreshRate = Fps(45.0f); lr.name = "45Hz Heuristic"; EXPECT_EQ(mExpected90Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - lr.desiredRefreshRate = 30.0f; + lr.desiredRefreshRate = Fps(30.0f); lr.name = "30Hz Heuristic"; EXPECT_EQ(mExpected60Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - lr.desiredRefreshRate = 24.0f; + lr.desiredRefreshRate = Fps(24.0f); lr.name = "24Hz Heuristic"; EXPECT_EQ(mExpected60Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); lr.name = ""; - ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_60, {60, 60}}), 0); + ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_60, {Fps(60), Fps(60)}}), + 0); lr.vote = LayerVoteType::Min; EXPECT_EQ(mExpected60Config, @@ -375,28 +385,30 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_60_90) { EXPECT_EQ(mExpected60Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - lr.desiredRefreshRate = 90.0f; + lr.desiredRefreshRate = Fps(90.0f); lr.vote = LayerVoteType::Heuristic; EXPECT_EQ(mExpected60Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - lr.desiredRefreshRate = 60.0f; + lr.desiredRefreshRate = Fps(60.0f); EXPECT_EQ(mExpected60Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - lr.desiredRefreshRate = 45.0f; + lr.desiredRefreshRate = Fps(45.0f); EXPECT_EQ(mExpected60Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - lr.desiredRefreshRate = 30.0f; + lr.desiredRefreshRate = Fps(30.0f); EXPECT_EQ(mExpected60Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - lr.desiredRefreshRate = 24.0f; + lr.desiredRefreshRate = Fps(24.0f); EXPECT_EQ(mExpected60Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_90, {90, 90}}), 0); + ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy( + {HWC_CONFIG_ID_90, {Fps(90.0f), Fps(90.0f)}}), + 0); lr.vote = LayerVoteType::Min; EXPECT_EQ(mExpected90Config, @@ -406,28 +418,30 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_60_90) { EXPECT_EQ(mExpected90Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - lr.desiredRefreshRate = 90.0f; + lr.desiredRefreshRate = Fps(90.0f); lr.vote = LayerVoteType::Heuristic; EXPECT_EQ(mExpected90Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - lr.desiredRefreshRate = 60.0f; + lr.desiredRefreshRate = Fps(60.0f); EXPECT_EQ(mExpected90Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - lr.desiredRefreshRate = 45.0f; + lr.desiredRefreshRate = Fps(45.0f); EXPECT_EQ(mExpected90Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - lr.desiredRefreshRate = 30.0f; + lr.desiredRefreshRate = Fps(30.0f); EXPECT_EQ(mExpected90Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - lr.desiredRefreshRate = 24.0f; + lr.desiredRefreshRate = Fps(24.0f); EXPECT_EQ(mExpected90Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_60, {0, 120}}), 0); + ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy( + {HWC_CONFIG_ID_60, {Fps(0.0f), Fps(120.0f)}}), + 0); lr.vote = LayerVoteType::Min; EXPECT_EQ(mExpected60Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); @@ -436,24 +450,24 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_60_90) { EXPECT_EQ(mExpected90Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - lr.desiredRefreshRate = 90.0f; + lr.desiredRefreshRate = Fps(90.0f); lr.vote = LayerVoteType::Heuristic; EXPECT_EQ(mExpected90Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - lr.desiredRefreshRate = 60.0f; + lr.desiredRefreshRate = Fps(60.0f); EXPECT_EQ(mExpected60Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - lr.desiredRefreshRate = 45.0f; + lr.desiredRefreshRate = Fps(45.0f); EXPECT_EQ(mExpected90Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - lr.desiredRefreshRate = 30.0f; + lr.desiredRefreshRate = Fps(30.0f); EXPECT_EQ(mExpected60Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - lr.desiredRefreshRate = 24.0f; + lr.desiredRefreshRate = Fps(24.0f); EXPECT_EQ(mExpected60Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); } @@ -474,24 +488,24 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_60_72_90) { EXPECT_EQ(mExpected90Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - lr.desiredRefreshRate = 90.0f; + lr.desiredRefreshRate = Fps(90.0f); lr.vote = LayerVoteType::Heuristic; EXPECT_EQ(mExpected90Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - lr.desiredRefreshRate = 60.0f; + lr.desiredRefreshRate = Fps(60.0f); EXPECT_EQ(mExpected60Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - lr.desiredRefreshRate = 45.0f; + lr.desiredRefreshRate = Fps(45.0f); EXPECT_EQ(mExpected90Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - lr.desiredRefreshRate = 30.0f; + lr.desiredRefreshRate = Fps(30.0f); EXPECT_EQ(mExpected60Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - lr.desiredRefreshRate = 24.0f; + lr.desiredRefreshRate = Fps(24.0f); EXPECT_EQ(mExpected72Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); } @@ -506,23 +520,23 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_30_60_72_90_120) { auto& lr1 = layers[0]; auto& lr2 = layers[1]; - lr1.desiredRefreshRate = 24.0f; + lr1.desiredRefreshRate = Fps(24.0f); lr1.vote = LayerVoteType::Heuristic; - lr2.desiredRefreshRate = 60.0f; + lr2.desiredRefreshRate = Fps(60.0f); lr2.vote = LayerVoteType::Heuristic; EXPECT_EQ(mExpected120Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - lr1.desiredRefreshRate = 24.0f; + lr1.desiredRefreshRate = Fps(24.0f); lr1.vote = LayerVoteType::Heuristic; - lr2.desiredRefreshRate = 48.0f; + lr2.desiredRefreshRate = Fps(48.0f); lr2.vote = LayerVoteType::Heuristic; EXPECT_EQ(mExpected72Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - lr1.desiredRefreshRate = 24.0f; + lr1.desiredRefreshRate = Fps(24.0f); lr1.vote = LayerVoteType::Heuristic; - lr2.desiredRefreshRate = 48.0f; + lr2.desiredRefreshRate = Fps(48.0f); lr2.vote = LayerVoteType::Heuristic; EXPECT_EQ(mExpected72Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); @@ -538,82 +552,82 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_30_60_90_120_DifferentTypes) { auto& lr1 = layers[0]; auto& lr2 = layers[1]; - lr1.desiredRefreshRate = 24.0f; + lr1.desiredRefreshRate = Fps(24.0f); lr1.vote = LayerVoteType::ExplicitDefault; lr1.name = "24Hz ExplicitDefault"; - lr2.desiredRefreshRate = 60.0f; + lr2.desiredRefreshRate = Fps(60.0f); lr2.vote = LayerVoteType::Heuristic; lr2.name = "60Hz Heuristic"; EXPECT_EQ(mExpected120Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - lr1.desiredRefreshRate = 24.0f; + lr1.desiredRefreshRate = Fps(24.0f); lr1.vote = LayerVoteType::ExplicitExactOrMultiple; lr1.name = "24Hz ExplicitExactOrMultiple"; - lr2.desiredRefreshRate = 60.0f; + lr2.desiredRefreshRate = Fps(60.0f); lr2.vote = LayerVoteType::Heuristic; lr2.name = "60Hz Heuristic"; EXPECT_EQ(mExpected120Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - lr1.desiredRefreshRate = 24.0f; + lr1.desiredRefreshRate = Fps(24.0f); lr1.vote = LayerVoteType::ExplicitExactOrMultiple; lr1.name = "24Hz ExplicitExactOrMultiple"; - lr2.desiredRefreshRate = 60.0f; + lr2.desiredRefreshRate = Fps(60.0f); lr2.vote = LayerVoteType::ExplicitDefault; lr2.name = "60Hz ExplicitDefault"; EXPECT_EQ(mExpected120Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - lr1.desiredRefreshRate = 24.0f; + lr1.desiredRefreshRate = Fps(24.0f); lr1.vote = LayerVoteType::ExplicitExactOrMultiple; lr1.name = "24Hz ExplicitExactOrMultiple"; - lr2.desiredRefreshRate = 90.0f; + lr2.desiredRefreshRate = Fps(90.0f); lr2.vote = LayerVoteType::Heuristic; lr2.name = "90Hz Heuristic"; EXPECT_EQ(mExpected90Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - lr1.desiredRefreshRate = 24.0f; + lr1.desiredRefreshRate = Fps(24.0f); lr1.vote = LayerVoteType::ExplicitExactOrMultiple; lr1.name = "24Hz ExplicitExactOrMultiple"; - lr2.desiredRefreshRate = 90.0f; + lr2.desiredRefreshRate = Fps(90.0f); lr2.vote = LayerVoteType::ExplicitDefault; lr2.name = "90Hz Heuristic"; EXPECT_EQ(mExpected72Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - lr1.desiredRefreshRate = 24.0f; + lr1.desiredRefreshRate = Fps(24.0f); lr1.vote = LayerVoteType::ExplicitDefault; lr1.name = "24Hz ExplicitDefault"; - lr2.desiredRefreshRate = 90.0f; + lr2.desiredRefreshRate = Fps(90.0f); lr2.vote = LayerVoteType::Heuristic; lr2.name = "90Hz Heuristic"; EXPECT_EQ(mExpected90Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - lr1.desiredRefreshRate = 24.0f; + lr1.desiredRefreshRate = Fps(24.0f); lr1.vote = LayerVoteType::Heuristic; lr1.name = "24Hz Heuristic"; - lr2.desiredRefreshRate = 90.0f; + lr2.desiredRefreshRate = Fps(90.0f); lr2.vote = LayerVoteType::ExplicitDefault; lr2.name = "90Hz ExplicitDefault"; EXPECT_EQ(mExpected72Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - lr1.desiredRefreshRate = 24.0f; + lr1.desiredRefreshRate = Fps(24.0f); lr1.vote = LayerVoteType::ExplicitExactOrMultiple; lr1.name = "24Hz ExplicitExactOrMultiple"; - lr2.desiredRefreshRate = 90.0f; + lr2.desiredRefreshRate = Fps(90.0f); lr2.vote = LayerVoteType::ExplicitDefault; lr2.name = "90Hz ExplicitDefault"; EXPECT_EQ(mExpected72Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - lr1.desiredRefreshRate = 24.0f; + lr1.desiredRefreshRate = Fps(24.0f); lr1.vote = LayerVoteType::ExplicitDefault; lr1.name = "24Hz ExplicitDefault"; - lr2.desiredRefreshRate = 90.0f; + lr2.desiredRefreshRate = Fps(90.0f); lr2.vote = LayerVoteType::ExplicitExactOrMultiple; lr2.name = "90Hz ExplicitExactOrMultiple"; EXPECT_EQ(mExpected90Config, @@ -636,24 +650,24 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_30_60) { EXPECT_EQ(mExpected60Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - lr.desiredRefreshRate = 90.0f; + lr.desiredRefreshRate = Fps(90.0f); lr.vote = LayerVoteType::Heuristic; EXPECT_EQ(mExpected60Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - lr.desiredRefreshRate = 60.0f; + lr.desiredRefreshRate = Fps(60.0f); EXPECT_EQ(mExpected60Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - lr.desiredRefreshRate = 45.0f; + lr.desiredRefreshRate = Fps(45.0f); EXPECT_EQ(mExpected60Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - lr.desiredRefreshRate = 30.0f; + lr.desiredRefreshRate = Fps(30.0f); EXPECT_EQ(mExpected30Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - lr.desiredRefreshRate = 24.0f; + lr.desiredRefreshRate = Fps(24.0f); EXPECT_EQ(mExpected60Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); } @@ -676,41 +690,41 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_30_60_72_90) { EXPECT_EQ(mExpected90Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - lr.desiredRefreshRate = 90.0f; + lr.desiredRefreshRate = Fps(90.0f); lr.vote = LayerVoteType::Heuristic; lr.name = "90Hz Heuristic"; EXPECT_EQ(mExpected90Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - lr.desiredRefreshRate = 60.0f; + lr.desiredRefreshRate = Fps(60.0f); lr.name = "60Hz Heuristic"; EXPECT_EQ(mExpected60Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); EXPECT_EQ(mExpected90Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = true, .idle = false})); - lr.desiredRefreshRate = 45.0f; + lr.desiredRefreshRate = Fps(45.0f); lr.name = "45Hz Heuristic"; EXPECT_EQ(mExpected90Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); EXPECT_EQ(mExpected90Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = true, .idle = false})); - lr.desiredRefreshRate = 30.0f; + lr.desiredRefreshRate = Fps(30.0f); lr.name = "30Hz Heuristic"; EXPECT_EQ(mExpected30Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); EXPECT_EQ(mExpected90Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = true, .idle = false})); - lr.desiredRefreshRate = 24.0f; + lr.desiredRefreshRate = Fps(24.0f); lr.name = "24Hz Heuristic"; EXPECT_EQ(mExpected72Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); EXPECT_EQ(mExpected90Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = true, .idle = false})); - lr.desiredRefreshRate = 24.0f; + lr.desiredRefreshRate = Fps(24.0f); lr.vote = LayerVoteType::ExplicitExactOrMultiple; lr.name = "24Hz ExplicitExactOrMultiple"; EXPECT_EQ(mExpected72Config, @@ -736,39 +750,39 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_PriorityTest) { lr1.vote = LayerVoteType::Min; lr2.vote = LayerVoteType::Heuristic; - lr2.desiredRefreshRate = 24.0f; + lr2.desiredRefreshRate = Fps(24.0f); EXPECT_EQ(mExpected60Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); lr1.vote = LayerVoteType::Min; lr2.vote = LayerVoteType::ExplicitExactOrMultiple; - lr2.desiredRefreshRate = 24.0f; + lr2.desiredRefreshRate = Fps(24.0f); EXPECT_EQ(mExpected60Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); lr1.vote = LayerVoteType::Max; lr2.vote = LayerVoteType::Heuristic; - lr2.desiredRefreshRate = 60.0f; + lr2.desiredRefreshRate = Fps(60.0f); EXPECT_EQ(mExpected90Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); lr1.vote = LayerVoteType::Max; lr2.vote = LayerVoteType::ExplicitExactOrMultiple; - lr2.desiredRefreshRate = 60.0f; + lr2.desiredRefreshRate = Fps(60.0f); EXPECT_EQ(mExpected90Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); lr1.vote = LayerVoteType::Heuristic; - lr1.desiredRefreshRate = 15.0f; + lr1.desiredRefreshRate = Fps(15.0f); lr2.vote = LayerVoteType::Heuristic; - lr2.desiredRefreshRate = 45.0f; + lr2.desiredRefreshRate = Fps(45.0f); EXPECT_EQ(mExpected90Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); lr1.vote = LayerVoteType::Heuristic; - lr1.desiredRefreshRate = 30.0f; + lr1.desiredRefreshRate = Fps(30.0f); lr2.vote = LayerVoteType::ExplicitExactOrMultiple; - lr2.desiredRefreshRate = 45.0f; + lr2.desiredRefreshRate = Fps(45.0f); EXPECT_EQ(mExpected90Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); } @@ -783,7 +797,7 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_24FpsVideo) { lr.vote = LayerVoteType::ExplicitExactOrMultiple; for (float fps = 23.0f; fps < 25.0f; fps += 0.1f) { - lr.desiredRefreshRate = fps; + lr.desiredRefreshRate = Fps(fps); const auto& refreshRate = refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}); EXPECT_EQ(mExpected60Config, refreshRate) << fps << "Hz chooses " << refreshRate.getName(); @@ -801,33 +815,33 @@ TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_getBestRefreshRate_Explicit) { auto& lr2 = layers[1]; lr1.vote = LayerVoteType::Heuristic; - lr1.desiredRefreshRate = 60.0f; + lr1.desiredRefreshRate = Fps(60.0f); lr2.vote = LayerVoteType::ExplicitExactOrMultiple; - lr2.desiredRefreshRate = 90.0f; + lr2.desiredRefreshRate = Fps(90.0f); EXPECT_EQ(mExpected90Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); lr1.vote = LayerVoteType::ExplicitDefault; - lr1.desiredRefreshRate = 90.0f; + lr1.desiredRefreshRate = Fps(90.0f); lr2.vote = LayerVoteType::ExplicitExactOrMultiple; - lr2.desiredRefreshRate = 60.0f; + lr2.desiredRefreshRate = Fps(60.0f); EXPECT_EQ(mExpected60Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); lr1.vote = LayerVoteType::Heuristic; - lr1.desiredRefreshRate = 90.0f; + lr1.desiredRefreshRate = Fps(90.0f); lr2.vote = LayerVoteType::ExplicitExactOrMultiple; - lr2.desiredRefreshRate = 60.0f; + lr2.desiredRefreshRate = Fps(60.0f); EXPECT_EQ(mExpected90Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); } TEST_F(RefreshRateConfigsTest, testInPolicy) { - ASSERT_TRUE(mExpectedAlmost60Config.inPolicy(60.000004f, 60.000004f)); - ASSERT_TRUE(mExpectedAlmost60Config.inPolicy(59.0f, 60.1f)); - ASSERT_FALSE(mExpectedAlmost60Config.inPolicy(75.0f, 90.0f)); - ASSERT_FALSE(mExpectedAlmost60Config.inPolicy(60.0011f, 90.0f)); - ASSERT_FALSE(mExpectedAlmost60Config.inPolicy(50.0f, 59.998f)); + ASSERT_TRUE(mExpectedAlmost60Config.inPolicy(Fps(60.000004f), Fps(60.000004f))); + ASSERT_TRUE(mExpectedAlmost60Config.inPolicy(Fps(59.0f), Fps(60.1f))); + ASSERT_FALSE(mExpectedAlmost60Config.inPolicy(Fps(75.0f), Fps(90.0f))); + ASSERT_FALSE(mExpectedAlmost60Config.inPolicy(Fps(60.0011f), Fps(90.0f))); + ASSERT_FALSE(mExpectedAlmost60Config.inPolicy(Fps(50.0f), Fps(59.998f))); } TEST_F(RefreshRateConfigsTest, getBestRefreshRate_75HzContent) { @@ -840,7 +854,7 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_75HzContent) { lr.vote = LayerVoteType::ExplicitExactOrMultiple; for (float fps = 75.0f; fps < 100.0f; fps += 0.1f) { - lr.desiredRefreshRate = fps; + lr.desiredRefreshRate = Fps(fps); const auto& refreshRate = refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}); EXPECT_EQ(mExpected90Config, refreshRate) << fps << "Hz chooses " << refreshRate.getName(); @@ -858,25 +872,25 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_Multiples) { auto& lr2 = layers[1]; lr1.vote = LayerVoteType::ExplicitExactOrMultiple; - lr1.desiredRefreshRate = 60.0f; + lr1.desiredRefreshRate = Fps(60.0f); lr1.name = "60Hz ExplicitExactOrMultiple"; lr2.vote = LayerVoteType::Heuristic; - lr2.desiredRefreshRate = 90.0f; + lr2.desiredRefreshRate = Fps(90.0f); lr2.name = "90Hz Heuristic"; EXPECT_EQ(mExpected90Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); lr1.vote = LayerVoteType::ExplicitExactOrMultiple; - lr1.desiredRefreshRate = 60.0f; + lr1.desiredRefreshRate = Fps(60.0f); lr1.name = "60Hz ExplicitExactOrMultiple"; lr2.vote = LayerVoteType::ExplicitDefault; - lr2.desiredRefreshRate = 90.0f; + lr2.desiredRefreshRate = Fps(90.0f); lr2.name = "90Hz ExplicitDefault"; EXPECT_EQ(mExpected60Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); lr1.vote = LayerVoteType::ExplicitExactOrMultiple; - lr1.desiredRefreshRate = 60.0f; + lr1.desiredRefreshRate = Fps(60.0f); lr1.name = "60Hz ExplicitExactOrMultiple"; lr2.vote = LayerVoteType::Max; lr2.name = "Max"; @@ -884,16 +898,16 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_Multiples) { refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); lr1.vote = LayerVoteType::ExplicitExactOrMultiple; - lr1.desiredRefreshRate = 30.0f; + lr1.desiredRefreshRate = Fps(30.0f); lr1.name = "30Hz ExplicitExactOrMultiple"; lr2.vote = LayerVoteType::Heuristic; - lr2.desiredRefreshRate = 90.0f; + lr2.desiredRefreshRate = Fps(90.0f); lr2.name = "90Hz Heuristic"; EXPECT_EQ(mExpected90Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); lr1.vote = LayerVoteType::ExplicitExactOrMultiple; - lr1.desiredRefreshRate = 30.0f; + lr1.desiredRefreshRate = Fps(30.0f); lr1.name = "30Hz ExplicitExactOrMultiple"; lr2.vote = LayerVoteType::Max; lr2.name = "Max"; @@ -912,7 +926,7 @@ TEST_F(RefreshRateConfigsTest, scrollWhileWatching60fps_60_90) { auto& lr2 = layers[1]; lr1.vote = LayerVoteType::ExplicitExactOrMultiple; - lr1.desiredRefreshRate = 60.0f; + lr1.desiredRefreshRate = Fps(60.0f); lr1.name = "60Hz ExplicitExactOrMultiple"; lr2.vote = LayerVoteType::NoVote; lr2.name = "NoVote"; @@ -920,7 +934,7 @@ TEST_F(RefreshRateConfigsTest, scrollWhileWatching60fps_60_90) { refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); lr1.vote = LayerVoteType::ExplicitExactOrMultiple; - lr1.desiredRefreshRate = 60.0f; + lr1.desiredRefreshRate = Fps(60.0f); lr1.name = "60Hz ExplicitExactOrMultiple"; lr2.vote = LayerVoteType::NoVote; lr2.name = "NoVote"; @@ -928,7 +942,7 @@ TEST_F(RefreshRateConfigsTest, scrollWhileWatching60fps_60_90) { refreshRateConfigs->getBestRefreshRate(layers, {.touch = true, .idle = false})); lr1.vote = LayerVoteType::ExplicitExactOrMultiple; - lr1.desiredRefreshRate = 60.0f; + lr1.desiredRefreshRate = Fps(60.0f); lr1.name = "60Hz ExplicitExactOrMultiple"; lr2.vote = LayerVoteType::Max; lr2.name = "Max"; @@ -936,7 +950,7 @@ TEST_F(RefreshRateConfigsTest, scrollWhileWatching60fps_60_90) { refreshRateConfigs->getBestRefreshRate(layers, {.touch = true, .idle = false})); lr1.vote = LayerVoteType::ExplicitExactOrMultiple; - lr1.desiredRefreshRate = 60.0f; + lr1.desiredRefreshRate = Fps(60.0f); lr1.name = "60Hz ExplicitExactOrMultiple"; lr2.vote = LayerVoteType::Max; lr2.name = "Max"; @@ -945,10 +959,10 @@ TEST_F(RefreshRateConfigsTest, scrollWhileWatching60fps_60_90) { // The other layer starts to provide buffers lr1.vote = LayerVoteType::ExplicitExactOrMultiple; - lr1.desiredRefreshRate = 60.0f; + lr1.desiredRefreshRate = Fps(60.0f); lr1.name = "60Hz ExplicitExactOrMultiple"; lr2.vote = LayerVoteType::Heuristic; - lr2.desiredRefreshRate = 90.0f; + lr2.desiredRefreshRate = Fps(90.0f); lr2.name = "90Hz Heuristic"; EXPECT_EQ(mExpected90Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); @@ -972,40 +986,40 @@ TEST_F(RefreshRateConfigsTest, touchConsidered) { auto& lr2 = layers[1]; lr1.vote = LayerVoteType::ExplicitExactOrMultiple; - lr1.desiredRefreshRate = 60.0f; + lr1.desiredRefreshRate = Fps(60.0f); lr1.name = "60Hz ExplicitExactOrMultiple"; lr2.vote = LayerVoteType::Heuristic; - lr2.desiredRefreshRate = 60.0f; + lr2.desiredRefreshRate = Fps(60.0f); lr2.name = "60Hz Heuristic"; refreshRateConfigs->getBestRefreshRate(layers, {.touch = true, .idle = false}, &consideredSignals); EXPECT_EQ(true, consideredSignals.touch); lr1.vote = LayerVoteType::ExplicitDefault; - lr1.desiredRefreshRate = 60.0f; + lr1.desiredRefreshRate = Fps(60.0f); lr1.name = "60Hz ExplicitExactOrMultiple"; lr2.vote = LayerVoteType::Heuristic; - lr2.desiredRefreshRate = 60.0f; + lr2.desiredRefreshRate = Fps(60.0f); lr2.name = "60Hz Heuristic"; refreshRateConfigs->getBestRefreshRate(layers, {.touch = true, .idle = false}, &consideredSignals); EXPECT_EQ(false, consideredSignals.touch); lr1.vote = LayerVoteType::ExplicitExactOrMultiple; - lr1.desiredRefreshRate = 60.0f; + lr1.desiredRefreshRate = Fps(60.0f); lr1.name = "60Hz ExplicitExactOrMultiple"; lr2.vote = LayerVoteType::Heuristic; - lr2.desiredRefreshRate = 60.0f; + lr2.desiredRefreshRate = Fps(60.0f); lr2.name = "60Hz Heuristic"; refreshRateConfigs->getBestRefreshRate(layers, {.touch = true, .idle = false}, &consideredSignals); EXPECT_EQ(true, consideredSignals.touch); lr1.vote = LayerVoteType::ExplicitDefault; - lr1.desiredRefreshRate = 60.0f; + lr1.desiredRefreshRate = Fps(60.0f); lr1.name = "60Hz ExplicitExactOrMultiple"; lr2.vote = LayerVoteType::Heuristic; - lr2.desiredRefreshRate = 60.0f; + lr2.desiredRefreshRate = Fps(60.0f); lr2.name = "60Hz Heuristic"; refreshRateConfigs->getBestRefreshRate(layers, {.touch = true, .idle = false}, &consideredSignals); @@ -1041,7 +1055,7 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_ExplicitDefault) { for (const auto& test : testCases) { lr.vote = LayerVoteType::ExplicitDefault; - lr.desiredRefreshRate = test.first; + lr.desiredRefreshRate = Fps(test.first); std::stringstream ss; ss << "ExplicitDefault " << test.first << " fps"; @@ -1049,7 +1063,7 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_ExplicitDefault) { const auto& refreshRate = refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}); - EXPECT_FLOAT_EQ(refreshRate.getFps(), test.second) + EXPECT_TRUE(refreshRate.getFps().equalsWithMargin(Fps(test.second))) << "Expecting " << test.first << "fps => " << test.second << "Hz"; } } @@ -1061,7 +1075,7 @@ TEST_F(RefreshRateConfigsTest, /*currentConfigId=*/HWC_CONFIG_ID_90); ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy( - {HWC_CONFIG_ID_90, {90.f, 90.f}, {60.f, 90.f}}), + {HWC_CONFIG_ID_90, {Fps(90.f), Fps(90.f)}, {Fps(60.f), Fps(90.f)}}), 0); auto layers = std::vector<LayerRequirement>{LayerRequirement{.weight = 1.0f}}; @@ -1069,7 +1083,7 @@ TEST_F(RefreshRateConfigsTest, RefreshRateConfigs::GlobalSignals consideredSignals; lr.vote = LayerVoteType::ExplicitDefault; - lr.desiredRefreshRate = 60.0f; + lr.desiredRefreshRate = Fps(60.0f); lr.name = "60Hz ExplicitDefault"; lr.focused = true; EXPECT_EQ(mExpected60Config, @@ -1085,14 +1099,14 @@ TEST_F(RefreshRateConfigsTest, /*currentConfigId=*/HWC_CONFIG_ID_60); ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy( - {HWC_CONFIG_ID_60, {60.f, 60.f}, {60.f, 90.f}}), + {HWC_CONFIG_ID_60, {Fps(60.f), Fps(60.f)}, {Fps(60.f), Fps(90.f)}}), 0); auto layers = std::vector<LayerRequirement>{LayerRequirement{.weight = 1.0f}}; auto& lr = layers[0]; lr.vote = LayerVoteType::ExplicitDefault; - lr.desiredRefreshRate = 90.0f; + lr.desiredRefreshRate = Fps(90.0f); lr.name = "90Hz ExplicitDefault"; lr.focused = true; EXPECT_EQ(mExpected90Config, @@ -1106,7 +1120,7 @@ TEST_F(RefreshRateConfigsTest, /*currentConfigId=*/HWC_CONFIG_ID_90); ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy( - {HWC_CONFIG_ID_90, {90.f, 90.f}, {60.f, 90.f}}), + {HWC_CONFIG_ID_90, {Fps(90.f), Fps(90.f)}, {Fps(60.f), Fps(90.f)}}), 0); RefreshRateConfigs::GlobalSignals consideredSignals; @@ -1119,7 +1133,7 @@ TEST_F(RefreshRateConfigsTest, auto& lr = layers[0]; lr.vote = LayerVoteType::ExplicitExactOrMultiple; - lr.desiredRefreshRate = 60.0f; + lr.desiredRefreshRate = Fps(60.0f); lr.name = "60Hz ExplicitExactOrMultiple"; lr.focused = false; EXPECT_EQ(mExpected90Config, @@ -1130,7 +1144,7 @@ TEST_F(RefreshRateConfigsTest, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); lr.vote = LayerVoteType::ExplicitDefault; - lr.desiredRefreshRate = 60.0f; + lr.desiredRefreshRate = Fps(60.0f); lr.name = "60Hz ExplicitDefault"; lr.focused = false; EXPECT_EQ(mExpected90Config, @@ -1141,7 +1155,7 @@ TEST_F(RefreshRateConfigsTest, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); lr.vote = LayerVoteType::Heuristic; - lr.desiredRefreshRate = 60.0f; + lr.desiredRefreshRate = Fps(60.0f); lr.name = "60Hz Heuristic"; lr.focused = false; EXPECT_EQ(mExpected90Config, @@ -1152,7 +1166,7 @@ TEST_F(RefreshRateConfigsTest, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); lr.vote = LayerVoteType::Max; - lr.desiredRefreshRate = 60.0f; + lr.desiredRefreshRate = Fps(60.0f); lr.name = "60Hz Max"; lr.focused = false; EXPECT_EQ(mExpected90Config, @@ -1163,7 +1177,7 @@ TEST_F(RefreshRateConfigsTest, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); lr.vote = LayerVoteType::Min; - lr.desiredRefreshRate = 60.0f; + lr.desiredRefreshRate = Fps(60.0f); lr.name = "60Hz Min"; lr.focused = false; EXPECT_EQ(mExpected90Config, @@ -1182,7 +1196,7 @@ TEST_F(RefreshRateConfigsTest, groupSwitching) { auto layers = std::vector<LayerRequirement>{LayerRequirement{.weight = 1.0f}}; auto& layer = layers[0]; layer.vote = LayerVoteType::ExplicitDefault; - layer.desiredRefreshRate = 90.0f; + layer.desiredRefreshRate = Fps(90.0f); layer.seamlessness = Seamlessness::SeamedAndSeamless; layer.name = "90Hz ExplicitDefault"; layer.focused = true; @@ -1207,7 +1221,7 @@ TEST_F(RefreshRateConfigsTest, groupSwitching) { // Verify that we won't do a seamless switch if we request the same mode as the default refreshRateConfigs->setCurrentConfigId(HWC_CONFIG_ID_90); - layer.desiredRefreshRate = 60.0f; + layer.desiredRefreshRate = Fps(60.0f); layer.name = "60Hz ExplicitDefault"; layer.seamlessness = Seamlessness::OnlySeamless; ASSERT_EQ(HWC_CONFIG_ID_90, @@ -1216,7 +1230,7 @@ TEST_F(RefreshRateConfigsTest, groupSwitching) { // 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. - layer.desiredRefreshRate = 60.0f; + layer.desiredRefreshRate = Fps(60.0f); layer.name = "60Hz ExplicitDefault"; layer.seamlessness = Seamlessness::Default; ASSERT_EQ(HWC_CONFIG_ID_60, @@ -1231,7 +1245,7 @@ TEST_F(RefreshRateConfigsTest, groupSwitching) { layers.push_back(LayerRequirement{.weight = 0.5f}); auto& layer2 = layers[layers.size() - 1]; layer2.vote = LayerVoteType::ExplicitDefault; - layer2.desiredRefreshRate = 90.0f; + layer2.desiredRefreshRate = Fps(90.0f); layer2.name = "90Hz ExplicitDefault"; layer2.seamlessness = Seamlessness::SeamedAndSeamless; layer2.focused = false; @@ -1262,7 +1276,7 @@ TEST_F(RefreshRateConfigsTest, nonSeamlessVotePrefersSeamlessSwitches) { auto layers = std::vector<LayerRequirement>{LayerRequirement{.weight = 1.0f}}; auto& layer = layers[0]; layer.vote = LayerVoteType::ExplicitExactOrMultiple; - layer.desiredRefreshRate = 60.0f; + layer.desiredRefreshRate = Fps(60.0f); layer.seamlessness = Seamlessness::SeamedAndSeamless; layer.name = "60Hz ExplicitExactOrMultiple"; layer.focused = true; @@ -1291,13 +1305,13 @@ TEST_F(RefreshRateConfigsTest, nonSeamlessExactAndSeamlessMultipleLayers) { auto layers = std::vector< LayerRequirement>{LayerRequirement{.name = "60Hz ExplicitDefault", .vote = LayerVoteType::ExplicitDefault, - .desiredRefreshRate = 60.0f, + .desiredRefreshRate = Fps(60.0f), .seamlessness = Seamlessness::SeamedAndSeamless, .weight = 0.5f, .focused = false}, LayerRequirement{.name = "25Hz ExplicitExactOrMultiple", .vote = LayerVoteType::ExplicitExactOrMultiple, - .desiredRefreshRate = 25.0f, + .desiredRefreshRate = Fps(25.0f), .seamlessness = Seamlessness::OnlySeamless, .weight = 1.0f, .focused = true}}; @@ -1307,7 +1321,7 @@ TEST_F(RefreshRateConfigsTest, nonSeamlessExactAndSeamlessMultipleLayers) { refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}) .getConfigId()); - seamedLayer.name = "30Hz ExplicitDefault", seamedLayer.desiredRefreshRate = 30.0f; + seamedLayer.name = "30Hz ExplicitDefault", seamedLayer.desiredRefreshRate = Fps(30.0f); refreshRateConfigs->setCurrentConfigId(HWC_CONFIG_ID_30); ASSERT_EQ(HWC_CONFIG_ID_25, @@ -1325,7 +1339,7 @@ TEST_F(RefreshRateConfigsTest, primaryVsAppRequestPolicy) { // Return the config ID from calling getBestRefreshRate() for a single layer with the // given voteType and fps. - auto getFrameRate = [&](LayerVoteType voteType, float fps, bool touchActive = false, + auto getFrameRate = [&](LayerVoteType voteType, Fps fps, bool touchActive = false, bool focused = true) -> HwcConfigIndexType { layers[0].vote = voteType; layers[0].desiredRefreshRate = fps; @@ -1335,43 +1349,44 @@ TEST_F(RefreshRateConfigsTest, primaryVsAppRequestPolicy) { }; ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy( - {HWC_CONFIG_ID_60, {30.f, 60.f}, {30.f, 90.f}}), + {HWC_CONFIG_ID_60, {Fps(30.f), Fps(60.f)}, {Fps(30.f), Fps(90.f)}}), 0); EXPECT_EQ(HWC_CONFIG_ID_60, refreshRateConfigs->getBestRefreshRate({}, {.touch = false, .idle = false}) .getConfigId()); - EXPECT_EQ(HWC_CONFIG_ID_60, getFrameRate(LayerVoteType::NoVote, 90.f)); - EXPECT_EQ(HWC_CONFIG_ID_30, getFrameRate(LayerVoteType::Min, 90.f)); - EXPECT_EQ(HWC_CONFIG_ID_60, getFrameRate(LayerVoteType::Max, 90.f)); - EXPECT_EQ(HWC_CONFIG_ID_60, getFrameRate(LayerVoteType::Heuristic, 90.f)); - EXPECT_EQ(HWC_CONFIG_ID_90, getFrameRate(LayerVoteType::ExplicitDefault, 90.f)); - EXPECT_EQ(HWC_CONFIG_ID_60, getFrameRate(LayerVoteType::ExplicitExactOrMultiple, 90.f)); + EXPECT_EQ(HWC_CONFIG_ID_60, getFrameRate(LayerVoteType::NoVote, Fps(90.f))); + EXPECT_EQ(HWC_CONFIG_ID_30, getFrameRate(LayerVoteType::Min, Fps(90.f))); + EXPECT_EQ(HWC_CONFIG_ID_60, getFrameRate(LayerVoteType::Max, Fps(90.f))); + EXPECT_EQ(HWC_CONFIG_ID_60, getFrameRate(LayerVoteType::Heuristic, Fps(90.f))); + EXPECT_EQ(HWC_CONFIG_ID_90, getFrameRate(LayerVoteType::ExplicitDefault, Fps(90.f))); + EXPECT_EQ(HWC_CONFIG_ID_60, getFrameRate(LayerVoteType::ExplicitExactOrMultiple, Fps(90.f))); // Layers not focused are not allowed to override primary config EXPECT_EQ(HWC_CONFIG_ID_60, - getFrameRate(LayerVoteType::ExplicitDefault, 90.f, /*touch=*/false, + getFrameRate(LayerVoteType::ExplicitDefault, Fps(90.f), /*touch=*/false, /*focused=*/false)); EXPECT_EQ(HWC_CONFIG_ID_60, - getFrameRate(LayerVoteType::ExplicitExactOrMultiple, 90.f, /*touch=*/false, + getFrameRate(LayerVoteType::ExplicitExactOrMultiple, Fps(90.f), /*touch=*/false, /*focused=*/false)); // Touch boost should be restricted to the primary range. - EXPECT_EQ(HWC_CONFIG_ID_60, getFrameRate(LayerVoteType::Max, 90.f, /*touch=*/true)); + EXPECT_EQ(HWC_CONFIG_ID_60, getFrameRate(LayerVoteType::Max, Fps(90.f), /*touch=*/true)); // When we're higher than the primary range max due to a layer frame rate setting, touch boost // shouldn't drag us back down to the primary range max. - EXPECT_EQ(HWC_CONFIG_ID_90, getFrameRate(LayerVoteType::ExplicitDefault, 90.f, /*touch=*/true)); + EXPECT_EQ(HWC_CONFIG_ID_90, + getFrameRate(LayerVoteType::ExplicitDefault, Fps(90.f), /*touch=*/true)); EXPECT_EQ(HWC_CONFIG_ID_60, - getFrameRate(LayerVoteType::ExplicitExactOrMultiple, 90.f, /*touch=*/true)); + getFrameRate(LayerVoteType::ExplicitExactOrMultiple, Fps(90.f), /*touch=*/true)); ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy( - {HWC_CONFIG_ID_60, {60.f, 60.f}, {60.f, 60.f}}), + {HWC_CONFIG_ID_60, {Fps(60.f), Fps(60.f)}, {Fps(60.f), Fps(60.f)}}), 0); - EXPECT_EQ(HWC_CONFIG_ID_60, getFrameRate(LayerVoteType::NoVote, 90.f)); - EXPECT_EQ(HWC_CONFIG_ID_60, getFrameRate(LayerVoteType::Min, 90.f)); - EXPECT_EQ(HWC_CONFIG_ID_60, getFrameRate(LayerVoteType::Max, 90.f)); - EXPECT_EQ(HWC_CONFIG_ID_60, getFrameRate(LayerVoteType::Heuristic, 90.f)); - EXPECT_EQ(HWC_CONFIG_ID_60, getFrameRate(LayerVoteType::ExplicitDefault, 90.f)); - EXPECT_EQ(HWC_CONFIG_ID_60, getFrameRate(LayerVoteType::ExplicitExactOrMultiple, 90.f)); + EXPECT_EQ(HWC_CONFIG_ID_60, getFrameRate(LayerVoteType::NoVote, Fps(90.f))); + EXPECT_EQ(HWC_CONFIG_ID_60, getFrameRate(LayerVoteType::Min, Fps(90.f))); + EXPECT_EQ(HWC_CONFIG_ID_60, getFrameRate(LayerVoteType::Max, Fps(90.f))); + EXPECT_EQ(HWC_CONFIG_ID_60, getFrameRate(LayerVoteType::Heuristic, Fps(90.f))); + EXPECT_EQ(HWC_CONFIG_ID_60, getFrameRate(LayerVoteType::ExplicitDefault, Fps(90.f))); + EXPECT_EQ(HWC_CONFIG_ID_60, getFrameRate(LayerVoteType::ExplicitExactOrMultiple, Fps(90.f))); } TEST_F(RefreshRateConfigsTest, idle) { @@ -1385,7 +1400,7 @@ TEST_F(RefreshRateConfigsTest, idle) { const auto getIdleFrameRate = [&](LayerVoteType voteType, bool touchActive) -> HwcConfigIndexType { layers[0].vote = voteType; - layers[0].desiredRefreshRate = 90.f; + layers[0].desiredRefreshRate = Fps(90.f); RefreshRateConfigs::GlobalSignals consideredSignals; const auto configId = refreshRateConfigs @@ -1398,7 +1413,7 @@ TEST_F(RefreshRateConfigsTest, idle) { }; ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy( - {HWC_CONFIG_ID_60, {60.f, 90.f}, {60.f, 90.f}}), + {HWC_CONFIG_ID_60, {Fps(60.f), Fps(90.f)}, {Fps(60.f), Fps(90.f)}}), 0); // Idle should be lower priority than touch boost. @@ -1439,22 +1454,22 @@ TEST_F(RefreshRateConfigsTest, findClosestKnownFrameRate) { /*currentConfigId=*/HWC_CONFIG_ID_60); for (float fps = 1.0f; fps <= 120.0f; fps += 0.1f) { - const auto knownFrameRate = findClosestKnownFrameRate(*refreshRateConfigs, fps); - float expectedFrameRate; + const auto knownFrameRate = findClosestKnownFrameRate(*refreshRateConfigs, Fps(fps)); + Fps expectedFrameRate; if (fps < 26.91f) { - expectedFrameRate = 24.0f; + expectedFrameRate = Fps(24.0f); } else if (fps < 37.51f) { - expectedFrameRate = 30.0f; + expectedFrameRate = Fps(30.0f); } else if (fps < 52.51f) { - expectedFrameRate = 45.0f; + expectedFrameRate = Fps(45.0f); } else if (fps < 66.01f) { - expectedFrameRate = 60.0f; + expectedFrameRate = Fps(60.0f); } else if (fps < 81.01f) { - expectedFrameRate = 72.0f; + expectedFrameRate = Fps(72.0f); } else { - expectedFrameRate = 90.0f; + expectedFrameRate = Fps(90.0f); } - EXPECT_FLOAT_EQ(expectedFrameRate, knownFrameRate) + EXPECT_TRUE(expectedFrameRate.equalsWithMargin(knownFrameRate)) << "findClosestKnownFrameRate(" << fps << ") = " << knownFrameRate; } } @@ -1465,26 +1480,27 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_KnownFrameRate) { /*currentConfigId=*/HWC_CONFIG_ID_60); struct ExpectedRate { - float rate; + Fps rate; const RefreshRate& expected; }; /* clang-format off */ std::vector<ExpectedRate> knownFrameRatesExpectations = { - {24.0f, mExpected60Config}, - {30.0f, mExpected60Config}, - {45.0f, mExpected90Config}, - {60.0f, mExpected60Config}, - {72.0f, mExpected90Config}, - {90.0f, mExpected90Config}, + {Fps(24.0f), mExpected60Config}, + {Fps(30.0f), mExpected60Config}, + {Fps(45.0f), mExpected90Config}, + {Fps(60.0f), mExpected60Config}, + {Fps(72.0f), mExpected90Config}, + {Fps(90.0f), mExpected90Config}, }; /* clang-format on */ // Make sure the test tests all the known frame rate const auto knownFrameRateList = getKnownFrameRate(*refreshRateConfigs); - const auto equal = std::equal(knownFrameRateList.begin(), knownFrameRateList.end(), - knownFrameRatesExpectations.begin(), - [](float a, const ExpectedRate& b) { return a == b.rate; }); + const auto equal = + std::equal(knownFrameRateList.begin(), knownFrameRateList.end(), + knownFrameRatesExpectations.begin(), + [](Fps a, const ExpectedRate& b) { return a.equalsWithMargin(b.rate); }); EXPECT_TRUE(equal); auto layers = std::vector<LayerRequirement>{LayerRequirement{.weight = 1.0f}}; @@ -1514,15 +1530,18 @@ TEST_F(RefreshRateConfigsTest, testKernelIdleTimerAction) { EXPECT_EQ(KernelIdleTimerAction::TurnOn, refreshRateConfigs->getIdleTimerAction()); // SetPolicy(60, 90), current 60Hz => TurnOn. - ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_60, {60, 90}}), 0); + ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_60, {Fps(60), Fps(90)}}), + 0); EXPECT_EQ(KernelIdleTimerAction::TurnOn, refreshRateConfigs->getIdleTimerAction()); // SetPolicy(60, 60), current 60Hz => NoChange, avoid extra calls. - ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_60, {60, 60}}), 0); + ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_60, {Fps(60), Fps(60)}}), + 0); EXPECT_EQ(KernelIdleTimerAction::NoChange, refreshRateConfigs->getIdleTimerAction()); // SetPolicy(90, 90), current 90Hz => TurnOff. - ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_90, {90, 90}}), 0); + ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_90, {Fps(90), Fps(90)}}), + 0); EXPECT_EQ(KernelIdleTimerAction::TurnOff, refreshRateConfigs->getIdleTimerAction()); } @@ -1554,7 +1573,7 @@ TEST_F(RefreshRateConfigsTest, RefreshRateDividerForUid) { EXPECT_EQ(4, refreshRateConfigs->getRefreshRateDividerForUid(uid)); refreshRateConfigs->setCurrentConfigId(HWC_CONFIG_ID_90); - refreshRateConfigs->setPreferredRefreshRateForUid({uid, 22.5}); + refreshRateConfigs->setPreferredRefreshRateForUid({uid, 22.5f}); EXPECT_EQ(4, refreshRateConfigs->getRefreshRateDividerForUid(uid)); refreshRateConfigs->setPreferredRefreshRateForUid({uid, 22.6f}); EXPECT_EQ(4, refreshRateConfigs->getRefreshRateDividerForUid(uid)); diff --git a/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp index d0bb9e291a..f938ba1133 100644 --- a/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp +++ b/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp @@ -25,6 +25,8 @@ #include <log/log.h> #include <thread> +#include "Scheduler/HwcStrongTypes.h" +#include "Scheduler/RefreshRateConfigs.h" #include "Scheduler/RefreshRateStats.h" #include "mock/DisplayHardware/MockDisplay.h" #include "mock/MockTimeStats.h" @@ -51,8 +53,9 @@ protected: void init(const std::vector<std::shared_ptr<const HWC2::Display::Config>>& configs) { mRefreshRateConfigs = std::make_unique<RefreshRateConfigs>(configs, /*currentConfig=*/CONFIG_ID_0); - mRefreshRateStats = std::make_unique<RefreshRateStats>(*mRefreshRateConfigs, mTimeStats, - /*currentConfigId=*/CONFIG_ID_0, + + const auto currFps = mRefreshRateConfigs->getRefreshRateFromConfigId(CONFIG_ID_0).getFps(); + mRefreshRateStats = std::make_unique<RefreshRateStats>(mTimeStats, currFps, /*currentPowerMode=*/PowerMode::OFF); } @@ -81,7 +84,7 @@ RefreshRateStatsTest::~RefreshRateStatsTest() { std::shared_ptr<const HWC2::Display::Config> RefreshRateStatsTest::createConfig( HwcConfigIndexType configId, int32_t configGroup, int64_t vsyncPeriod) { return HWC2::Display::Config::Builder(mDisplay, configId.value()) - .setVsyncPeriod(int32_t(vsyncPeriod)) + .setVsyncPeriod(static_cast<int32_t>(vsyncPeriod)) .setConfigGroup(configGroup) .build(); } @@ -110,7 +113,8 @@ TEST_F(RefreshRateStatsTest, oneConfigTest) { EXPECT_LT(screenOff, times["ScreenOff"]); EXPECT_EQ(0u, times.count("90.00fps")); - mRefreshRateStats->setConfigMode(CONFIG_ID_0); + const auto config0Fps = mRefreshRateConfigs->getRefreshRateFromConfigId(CONFIG_ID_0).getFps(); + mRefreshRateStats->setRefreshRate(config0Fps); mRefreshRateStats->setPowerMode(PowerMode::ON); screenOff = mRefreshRateStats->getTotalTimes()["ScreenOff"]; std::this_thread::sleep_for(std::chrono::milliseconds(2)); @@ -126,7 +130,7 @@ TEST_F(RefreshRateStatsTest, oneConfigTest) { EXPECT_LT(screenOff, times["ScreenOff"]); EXPECT_EQ(ninety, times["90.00fps"]); - mRefreshRateStats->setConfigMode(CONFIG_ID_0); + mRefreshRateStats->setRefreshRate(config0Fps); screenOff = mRefreshRateStats->getTotalTimes()["ScreenOff"]; std::this_thread::sleep_for(std::chrono::milliseconds(2)); times = mRefreshRateStats->getTotalTimes(); @@ -157,7 +161,9 @@ TEST_F(RefreshRateStatsTest, twoConfigsTest) { times = mRefreshRateStats->getTotalTimes(); EXPECT_LT(screenOff, times["ScreenOff"]); - mRefreshRateStats->setConfigMode(CONFIG_ID_0); + const auto config0Fps = mRefreshRateConfigs->getRefreshRateFromConfigId(CONFIG_ID_0).getFps(); + const auto config1Fps = mRefreshRateConfigs->getRefreshRateFromConfigId(CONFIG_ID_1).getFps(); + mRefreshRateStats->setRefreshRate(config0Fps); mRefreshRateStats->setPowerMode(PowerMode::ON); screenOff = mRefreshRateStats->getTotalTimes()["ScreenOff"]; std::this_thread::sleep_for(std::chrono::milliseconds(2)); @@ -167,7 +173,7 @@ TEST_F(RefreshRateStatsTest, twoConfigsTest) { EXPECT_LT(0, times["90.00fps"]); // When power mode is normal, time for configs updates. - mRefreshRateStats->setConfigMode(CONFIG_ID_1); + mRefreshRateStats->setRefreshRate(config1Fps); int ninety = mRefreshRateStats->getTotalTimes()["90.00fps"]; std::this_thread::sleep_for(std::chrono::milliseconds(2)); times = mRefreshRateStats->getTotalTimes(); @@ -176,7 +182,7 @@ TEST_F(RefreshRateStatsTest, twoConfigsTest) { ASSERT_EQ(1u, times.count("60.00fps")); EXPECT_LT(0, times["60.00fps"]); - mRefreshRateStats->setConfigMode(CONFIG_ID_0); + mRefreshRateStats->setRefreshRate(config0Fps); int sixty = mRefreshRateStats->getTotalTimes()["60.00fps"]; std::this_thread::sleep_for(std::chrono::milliseconds(2)); times = mRefreshRateStats->getTotalTimes(); @@ -184,7 +190,7 @@ TEST_F(RefreshRateStatsTest, twoConfigsTest) { EXPECT_LT(ninety, times["90.00fps"]); EXPECT_EQ(sixty, times["60.00fps"]); - mRefreshRateStats->setConfigMode(CONFIG_ID_1); + mRefreshRateStats->setRefreshRate(config1Fps); ninety = mRefreshRateStats->getTotalTimes()["90.00fps"]; std::this_thread::sleep_for(std::chrono::milliseconds(2)); times = mRefreshRateStats->getTotalTimes(); @@ -195,7 +201,7 @@ TEST_F(RefreshRateStatsTest, twoConfigsTest) { // Because the power mode is not PowerMode::ON, switching the config // does not update refresh rates that come from the config. mRefreshRateStats->setPowerMode(PowerMode::DOZE); - mRefreshRateStats->setConfigMode(CONFIG_ID_0); + mRefreshRateStats->setRefreshRate(config0Fps); sixty = mRefreshRateStats->getTotalTimes()["60.00fps"]; std::this_thread::sleep_for(std::chrono::milliseconds(2)); times = mRefreshRateStats->getTotalTimes(); @@ -203,7 +209,7 @@ TEST_F(RefreshRateStatsTest, twoConfigsTest) { EXPECT_EQ(ninety, times["90.00fps"]); EXPECT_EQ(sixty, times["60.00fps"]); - mRefreshRateStats->setConfigMode(CONFIG_ID_1); + mRefreshRateStats->setRefreshRate(config1Fps); screenOff = mRefreshRateStats->getTotalTimes()["ScreenOff"]; std::this_thread::sleep_for(std::chrono::milliseconds(2)); times = mRefreshRateStats->getTotalTimes(); diff --git a/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp b/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp index 5278641e5b..c47b141823 100644 --- a/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp +++ b/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp @@ -108,11 +108,12 @@ std::string PrintToStringParamName( */ class SetFrameRateTest : public ::testing::TestWithParam<std::shared_ptr<LayerFactory>> { protected: - const FrameRate FRAME_RATE_VOTE1 = FrameRate(67.f, FrameRateCompatibility::Default); - const FrameRate FRAME_RATE_VOTE2 = FrameRate(14.f, FrameRateCompatibility::ExactOrMultiple); - const FrameRate FRAME_RATE_VOTE3 = FrameRate(99.f, FrameRateCompatibility::NoVote); - const FrameRate FRAME_RATE_TREE = FrameRate(0, FrameRateCompatibility::NoVote); - const FrameRate FRAME_RATE_NO_VOTE = FrameRate(0, FrameRateCompatibility::Default); + const FrameRate FRAME_RATE_VOTE1 = FrameRate(Fps(67.f), FrameRateCompatibility::Default); + const FrameRate FRAME_RATE_VOTE2 = + FrameRate(Fps(14.f), FrameRateCompatibility::ExactOrMultiple); + const FrameRate FRAME_RATE_VOTE3 = FrameRate(Fps(99.f), FrameRateCompatibility::NoVote); + const FrameRate FRAME_RATE_TREE = FrameRate(Fps(0.f), FrameRateCompatibility::NoVote); + const FrameRate FRAME_RATE_NO_VOTE = FrameRate(Fps(0.f), FrameRateCompatibility::Default); SetFrameRateTest(); diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h index c0de465668..030073ca8a 100644 --- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h @@ -223,12 +223,14 @@ public: .build()); } - mFlinger->mRefreshRateConfigs = std::make_unique< - scheduler::RefreshRateConfigs>(configs, /*currentConfig=*/HwcConfigIndexType(0)); - mFlinger->mRefreshRateStats = std::make_unique< - scheduler::RefreshRateStats>(*mFlinger->mRefreshRateConfigs, *mFlinger->mTimeStats, - /*currentConfig=*/HwcConfigIndexType(0), - /*powerMode=*/hal::PowerMode::OFF); + const auto currConfig = HwcConfigIndexType(0); + mFlinger->mRefreshRateConfigs = + std::make_unique<scheduler::RefreshRateConfigs>(configs, currConfig); + const auto currFps = + mFlinger->mRefreshRateConfigs->getRefreshRateFromConfigId(currConfig).getFps(); + mFlinger->mRefreshRateStats = + std::make_unique<scheduler::RefreshRateStats>(*mFlinger->mTimeStats, currFps, + /*powerMode=*/hal::PowerMode::OFF); mFlinger->mVsyncConfiguration = mFactory.createVsyncConfiguration(*mFlinger->mRefreshRateConfigs); mFlinger->mVsyncModulator.emplace(mFlinger->mVsyncConfiguration->getCurrentConfigs()); diff --git a/services/surfaceflinger/tests/unittests/VsyncConfigurationTest.cpp b/services/surfaceflinger/tests/unittests/VsyncConfigurationTest.cpp index 72ee6db737..2a35f69560 100644 --- a/services/surfaceflinger/tests/unittests/VsyncConfigurationTest.cpp +++ b/services/surfaceflinger/tests/unittests/VsyncConfigurationTest.cpp @@ -29,17 +29,18 @@ namespace android::scheduler { class TestableWorkDuration : public impl::WorkDuration { public: - TestableWorkDuration(float currentFps, nsecs_t sfDuration, nsecs_t appDuration, + TestableWorkDuration(Fps currentFps, nsecs_t sfDuration, nsecs_t appDuration, nsecs_t sfEarlyDuration, nsecs_t appEarlyDuration, nsecs_t sfEarlyGlDuration, nsecs_t appEarlyGlDuration) - : impl::WorkDuration({60.0f, 90.0f}, currentFps, sfDuration, appDuration, sfEarlyDuration, - appEarlyDuration, sfEarlyGlDuration, appEarlyGlDuration) {} + : impl::WorkDuration({Fps(60.0f), Fps(90.0f)}, currentFps, sfDuration, appDuration, + sfEarlyDuration, appEarlyDuration, sfEarlyGlDuration, + appEarlyGlDuration) {} }; class WorkDurationTest : public testing::Test { protected: WorkDurationTest() - : mWorkDuration(60.0f, 10'500'000, 20'500'000, 16'000'000, 16'500'000, 13'500'000, + : mWorkDuration(Fps(60.0f), 10'500'000, 20'500'000, 16'000'000, 16'500'000, 13'500'000, 21'000'000) {} ~WorkDurationTest() = default; @@ -51,9 +52,9 @@ protected: * Test cases */ TEST_F(WorkDurationTest, getConfigsForRefreshRate_60Hz) { - mWorkDuration.setRefreshRateFps(60.0f); + mWorkDuration.setRefreshRateFps(Fps(60.0f)); auto currentOffsets = mWorkDuration.getCurrentConfigs(); - auto offsets = mWorkDuration.getConfigsForRefreshRate(60.0f); + auto offsets = mWorkDuration.getConfigsForRefreshRate(Fps(60.0f)); EXPECT_EQ(currentOffsets, offsets); EXPECT_EQ(offsets.late.sfOffset, 6'166'667); @@ -76,9 +77,9 @@ TEST_F(WorkDurationTest, getConfigsForRefreshRate_60Hz) { } TEST_F(WorkDurationTest, getConfigsForRefreshRate_90Hz) { - mWorkDuration.setRefreshRateFps(90.0f); + mWorkDuration.setRefreshRateFps(Fps(90.0f)); auto currentOffsets = mWorkDuration.getCurrentConfigs(); - auto offsets = mWorkDuration.getConfigsForRefreshRate(90.0f); + auto offsets = mWorkDuration.getConfigsForRefreshRate(Fps(90.0f)); EXPECT_EQ(currentOffsets, offsets); EXPECT_EQ(offsets.late.sfOffset, 611'111); @@ -101,7 +102,7 @@ TEST_F(WorkDurationTest, getConfigsForRefreshRate_90Hz) { } TEST_F(WorkDurationTest, getConfigsForRefreshRate_DefaultOffsets) { - TestableWorkDuration phaseOffsetsWithDefaultValues(60.0f, -1, -1, -1, -1, -1, -1); + TestableWorkDuration phaseOffsetsWithDefaultValues(Fps(60.0f), -1, -1, -1, -1, -1, -1); auto validateOffsets = [](const auto& offsets, std::chrono::nanoseconds vsyncPeriod) { EXPECT_EQ(offsets.late.sfOffset, 1'000'000); @@ -123,21 +124,20 @@ TEST_F(WorkDurationTest, getConfigsForRefreshRate_DefaultOffsets) { EXPECT_EQ(offsets.earlyGpu.appWorkDuration, vsyncPeriod); }; - const auto testForRefreshRate = [&](float refreshRate) { + const auto testForRefreshRate = [&](Fps refreshRate) { phaseOffsetsWithDefaultValues.setRefreshRateFps(refreshRate); auto currentOffsets = phaseOffsetsWithDefaultValues.getCurrentConfigs(); auto offsets = phaseOffsetsWithDefaultValues.getConfigsForRefreshRate(refreshRate); EXPECT_EQ(currentOffsets, offsets); - validateOffsets(offsets, - std::chrono::nanoseconds(static_cast<nsecs_t>(1e9f / refreshRate))); + validateOffsets(offsets, std::chrono::nanoseconds(refreshRate.getPeriodNsecs())); }; - testForRefreshRate(90.0f); - testForRefreshRate(60.0f); + testForRefreshRate(Fps(90.0f)); + testForRefreshRate(Fps(60.0f)); } TEST_F(WorkDurationTest, getConfigsForRefreshRate_unknownRefreshRate) { - auto offsets = mWorkDuration.getConfigsForRefreshRate(14.7f); + auto offsets = mWorkDuration.getConfigsForRefreshRate(Fps(14.7f)); EXPECT_EQ(offsets.late.sfOffset, 57'527'208); EXPECT_EQ(offsets.late.appOffset, 37'027'208); @@ -171,9 +171,9 @@ public: std::optional<nsecs_t> highFpsEarlyAppOffsetNs, std::optional<nsecs_t> highFpsEarlyGpuAppOffsetNs, nsecs_t thresholdForNextVsync) - : impl::PhaseOffsets({60.0f, 90.0f}, 60.0f, vsyncPhaseOffsetNs, sfVSyncPhaseOffsetNs, - earlySfOffsetNs, earlyGpuSfOffsetNs, earlyAppOffsetNs, - earlyGpuAppOffsetNs, highFpsVsyncPhaseOffsetNs, + : impl::PhaseOffsets({Fps(60.0f), Fps(90.0f)}, Fps(60.0f), vsyncPhaseOffsetNs, + sfVSyncPhaseOffsetNs, earlySfOffsetNs, earlyGpuSfOffsetNs, + earlyAppOffsetNs, earlyGpuAppOffsetNs, highFpsVsyncPhaseOffsetNs, highFpsSfVSyncPhaseOffsetNs, highFpsEarlySfOffsetNs, highFpsEarlyGpuSfOffsetNs, highFpsEarlyAppOffsetNs, highFpsEarlyGpuAppOffsetNs, thresholdForNextVsync) {} @@ -190,7 +190,7 @@ protected: }; TEST_F(PhaseOffsetsTest, getConfigsForRefreshRate_unknownRefreshRate) { - auto offsets = mPhaseOffsets.getConfigsForRefreshRate(14.7f); + auto offsets = mPhaseOffsets.getConfigsForRefreshRate(Fps(14.7f)); EXPECT_EQ(offsets.late.sfOffset, 6'000'000); EXPECT_EQ(offsets.late.appOffset, 2'000'000); @@ -212,7 +212,7 @@ TEST_F(PhaseOffsetsTest, getConfigsForRefreshRate_unknownRefreshRate) { } TEST_F(PhaseOffsetsTest, getConfigsForRefreshRate_60Hz) { - auto offsets = mPhaseOffsets.getConfigsForRefreshRate(60.0f); + auto offsets = mPhaseOffsets.getConfigsForRefreshRate(Fps(60.0f)); EXPECT_EQ(offsets.late.sfOffset, 6'000'000); EXPECT_EQ(offsets.late.appOffset, 2'000'000); @@ -234,7 +234,7 @@ TEST_F(PhaseOffsetsTest, getConfigsForRefreshRate_60Hz) { } TEST_F(PhaseOffsetsTest, getConfigsForRefreshRate_90Hz) { - auto offsets = mPhaseOffsets.getConfigsForRefreshRate(90.0f); + auto offsets = mPhaseOffsets.getConfigsForRefreshRate(Fps(90.0f)); EXPECT_EQ(offsets.late.sfOffset, 1'000'000); EXPECT_EQ(offsets.late.appOffset, 2'000'000); @@ -258,7 +258,7 @@ TEST_F(PhaseOffsetsTest, getConfigsForRefreshRate_90Hz) { TEST_F(PhaseOffsetsTest, getConfigsForRefreshRate_DefaultValues_60Hz) { TestablePhaseOffsets phaseOffsets{1'000'000, 1'000'000, {}, {}, {}, {}, 2'000'000, 1'000'000, {}, {}, {}, {}, 10'000'000}; - auto offsets = phaseOffsets.getConfigsForRefreshRate(60.0f); + auto offsets = phaseOffsets.getConfigsForRefreshRate(Fps(60.0f)); EXPECT_EQ(offsets.late.sfOffset, 1'000'000); EXPECT_EQ(offsets.late.appOffset, 1'000'000); @@ -282,7 +282,7 @@ TEST_F(PhaseOffsetsTest, getConfigsForRefreshRate_DefaultValues_60Hz) { TEST_F(PhaseOffsetsTest, getConfigsForRefreshRate_DefaultValues_90Hz) { TestablePhaseOffsets phaseOffsets{1'000'000, 1'000'000, {}, {}, {}, {}, 2'000'000, 1'000'000, {}, {}, {}, {}, 10'000'000}; - auto offsets = phaseOffsets.getConfigsForRefreshRate(90.0f); + auto offsets = phaseOffsets.getConfigsForRefreshRate(Fps(90.0f)); EXPECT_EQ(offsets.late.sfOffset, 1'000'000); EXPECT_EQ(offsets.late.appOffset, 2'000'000); |