[SF] Update DisplayMode::Fps with PeakFps
Update to incorporate display refresh rate on
DisplayMode
With the addition of VRR, vsync period
does not necessarily represent the
refresh rate of the display, having a
peakRefreshRate that represents the
display peak refresh rate helps with
separating the concern of vsync period
being different from the peak refresh rate
supported by the device.
Test: atest libsurfaceflinger_unittest
BUG: 286048920
BUG: 284845445
Change-Id: I9d90e4def4cf3efcd5a696a4ec43fbf7698abfe4
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 70ccaf8..252ba8e 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -208,12 +208,12 @@
return mPowerMode && *mPowerMode != hal::PowerMode::OFF;
}
-void DisplayDevice::setActiveMode(DisplayModeId modeId, Fps displayFps, Fps renderFps) {
- ATRACE_INT(mActiveModeFPSTrace.c_str(), displayFps.getIntValue());
+void DisplayDevice::setActiveMode(DisplayModeId modeId, Fps vsyncRate, Fps renderFps) {
+ ATRACE_INT(mActiveModeFPSTrace.c_str(), vsyncRate.getIntValue());
ATRACE_INT(mRenderFrameRateFPSTrace.c_str(), renderFps.getIntValue());
mRefreshRateSelector->setActiveMode(modeId, renderFps);
- updateRefreshRateOverlayRate(displayFps, renderFps);
+ updateRefreshRateOverlayRate(vsyncRate, renderFps);
}
status_t DisplayDevice::initiateModeChange(const ActiveModeInfo& info,
@@ -230,14 +230,14 @@
mIsModeSetPending = true;
const auto& pendingMode = *info.modeOpt->modePtr;
- ATRACE_INT(mActiveModeFPSHwcTrace.c_str(), pendingMode.getFps().getIntValue());
+ ATRACE_INT(mActiveModeFPSHwcTrace.c_str(), pendingMode.getVsyncRate().getIntValue());
return mHwComposer.setActiveModeWithConstraints(getPhysicalId(), pendingMode.getHwcId(),
constraints, outTimeline);
}
-void DisplayDevice::finalizeModeChange(DisplayModeId modeId, Fps displayFps, Fps renderFps) {
- setActiveMode(modeId, displayFps, renderFps);
+void DisplayDevice::finalizeModeChange(DisplayModeId modeId, Fps vsyncRate, Fps renderFps) {
+ setActiveMode(modeId, vsyncRate, renderFps);
mIsModeSetPending = false;
}
@@ -253,7 +253,7 @@
return vsyncPeriod;
}
- return refreshRateSelector().getActiveMode().modePtr->getVsyncPeriod();
+ return refreshRateSelector().getActiveMode().modePtr->getVsyncRate().getPeriodNsecs();
}
ui::Dataspace DisplayDevice::getCompositionDataSpace() const {
@@ -466,17 +466,19 @@
features |= RefreshRateOverlay::Features::SetByHwc;
}
+ // TODO(b/296636258) Update to use the render rate range in VRR mode.
const auto fpsRange = mRefreshRateSelector->getSupportedRefreshRateRange();
mRefreshRateOverlay = std::make_unique<RefreshRateOverlay>(fpsRange, features);
mRefreshRateOverlay->setLayerStack(getLayerStack());
mRefreshRateOverlay->setViewport(getSize());
- updateRefreshRateOverlayRate(getActiveMode().modePtr->getFps(), getActiveMode().fps, setByHwc);
+ updateRefreshRateOverlayRate(getActiveMode().modePtr->getVsyncRate(), getActiveMode().fps,
+ setByHwc);
}
-void DisplayDevice::updateRefreshRateOverlayRate(Fps displayFps, Fps renderFps, bool setByHwc) {
+void DisplayDevice::updateRefreshRateOverlayRate(Fps vsyncRate, Fps renderFps, bool setByHwc) {
ATRACE_CALL();
if (mRefreshRateOverlay && (!mRefreshRateOverlay->isSetByHwc() || setByHwc)) {
- mRefreshRateOverlay->changeRefreshRate(displayFps, renderFps);
+ mRefreshRateOverlay->changeRefreshRate(vsyncRate, renderFps);
}
}
@@ -486,7 +488,7 @@
const auto newMode =
mRefreshRateSelector->onKernelTimerChanged(desiredModeId, timerExpired);
if (newMode) {
- updateRefreshRateOverlayRate(newMode->modePtr->getFps(), newMode->fps);
+ updateRefreshRateOverlayRate(newMode->modePtr->getVsyncRate(), newMode->fps);
return true;
}
}
@@ -541,14 +543,14 @@
return DesiredActiveModeAction::None;
}
- setActiveMode(desiredMode.getId(), desiredMode.getFps(), info.modeOpt->fps);
+ setActiveMode(desiredMode.getId(), desiredMode.getVsyncRate(), info.modeOpt->fps);
return DesiredActiveModeAction::InitiateRenderRateSwitch;
}
// Set the render frame rate to the current physical refresh rate to schedule the next
// frame as soon as possible.
- setActiveMode(currentMode.modePtr->getId(), currentMode.modePtr->getFps(),
- currentMode.modePtr->getFps());
+ setActiveMode(currentMode.modePtr->getId(), currentMode.modePtr->getVsyncRate(),
+ currentMode.modePtr->getVsyncRate());
// Initiate a mode change.
mDesiredActiveModeChanged = true;
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index a3fa701..a044534 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -224,14 +224,14 @@
return mRefreshRateSelector->getActiveMode();
}
- void setActiveMode(DisplayModeId, Fps displayFps, Fps renderFps);
+ void setActiveMode(DisplayModeId, Fps vsyncRate, Fps renderFps);
status_t initiateModeChange(const ActiveModeInfo&,
const hal::VsyncPeriodChangeConstraints& constraints,
hal::VsyncPeriodChangeTimeline* outTimeline)
REQUIRES(kMainThreadContext);
- void finalizeModeChange(DisplayModeId, Fps displayFps, Fps renderFps)
+ void finalizeModeChange(DisplayModeId, Fps vsyncRate, Fps renderFps)
REQUIRES(kMainThreadContext);
scheduler::RefreshRateSelector& refreshRateSelector() const { return *mRefreshRateSelector; }
@@ -246,7 +246,7 @@
// Enables an overlay to be displayed with the current refresh rate
void enableRefreshRateOverlay(bool enable, bool setByHwc, bool showSpinner, bool showRenderRate,
bool showInMiddle) REQUIRES(kMainThreadContext);
- void updateRefreshRateOverlayRate(Fps displayFps, Fps renderFps, bool setByHwc = false);
+ void updateRefreshRateOverlayRate(Fps vsyncRate, Fps renderFps, bool setByHwc = false);
bool isRefreshRateOverlayEnabled() const { return mRefreshRateOverlay != nullptr; }
bool onKernelTimerChanged(std::optional<DisplayModeId>, bool timerExpired);
diff --git a/services/surfaceflinger/DisplayHardware/DisplayMode.h b/services/surfaceflinger/DisplayHardware/DisplayMode.h
index 1810925..422513b 100644
--- a/services/surfaceflinger/DisplayHardware/DisplayMode.h
+++ b/services/surfaceflinger/DisplayHardware/DisplayMode.h
@@ -32,6 +32,8 @@
#include "DisplayHardware/Hal.h"
#include "Scheduler/StrongTyping.h"
+#include <com_android_graphics_surfaceflinger_flags.h>
+
namespace android {
namespace hal = android::hardware::graphics::composer::hal;
@@ -49,6 +51,7 @@
using DisplayModes = ftl::SmallMap<DisplayModeId, DisplayModePtr, 3>;
using DisplayModeIterator = DisplayModes::const_iterator;
+using namespace com::android::graphics::surfaceflinger;
class DisplayMode {
public:
@@ -76,7 +79,12 @@
}
Builder& setVsyncPeriod(nsecs_t vsyncPeriod) {
- mDisplayMode->mFps = Fps::fromPeriodNsecs(vsyncPeriod);
+ mDisplayMode->mVsyncRate = Fps::fromPeriodNsecs(vsyncPeriod);
+ return *this;
+ }
+
+ Builder& setVrrConfig(std::optional<hal::VrrConfig> vrrConfig) {
+ mDisplayMode->mVrrConfig = std::move(vrrConfig);
return *this;
}
@@ -130,8 +138,17 @@
int32_t getWidth() const { return mResolution.getWidth(); }
int32_t getHeight() const { return mResolution.getHeight(); }
- Fps getFps() const { return mFps; }
- nsecs_t getVsyncPeriod() const { return mFps.getPeriodNsecs(); }
+ // Peak refresh rate represents the highest refresh rate that can be used
+ // for the presentation.
+ Fps getPeakFps() const {
+ return flags::vrr_config() && mVrrConfig
+ ? Fps::fromPeriodNsecs(mVrrConfig->minFrameIntervalNs)
+ : mVsyncRate;
+ }
+
+ Fps getVsyncRate() const { return mVsyncRate; }
+
+ std::optional<hal::VrrConfig> getVrrConfig() const { return mVrrConfig; }
struct Dpi {
float x = -1;
@@ -155,23 +172,25 @@
PhysicalDisplayId mPhysicalDisplayId;
ui::Size mResolution;
- Fps mFps;
+ Fps mVsyncRate;
Dpi mDpi;
int32_t mGroup = -1;
+ std::optional<hal::VrrConfig> mVrrConfig;
};
inline bool equalsExceptDisplayModeId(const DisplayMode& lhs, const DisplayMode& rhs) {
return lhs.getHwcId() == rhs.getHwcId() && lhs.getResolution() == rhs.getResolution() &&
- lhs.getVsyncPeriod() == rhs.getVsyncPeriod() && lhs.getDpi() == rhs.getDpi() &&
- lhs.getGroup() == rhs.getGroup();
+ lhs.getVsyncRate().getPeriodNsecs() == rhs.getVsyncRate().getPeriodNsecs() &&
+ lhs.getDpi() == rhs.getDpi() && lhs.getGroup() == rhs.getGroup();
}
inline std::string to_string(const DisplayMode& mode) {
- return base::StringPrintf("{id=%d, hwcId=%d, resolution=%dx%d, refreshRate=%s, "
- "dpi=%.2fx%.2f, group=%d}",
+ return base::StringPrintf("{id=%d, hwcId=%d, resolution=%dx%d, vsyncRate=%s, "
+ "dpi=%.2fx%.2f, group=%d, vrrConfig=%s}",
mode.getId().value(), mode.getHwcId(), mode.getWidth(),
- mode.getHeight(), to_string(mode.getFps()).c_str(), mode.getDpi().x,
- mode.getDpi().y, mode.getGroup());
+ mode.getHeight(), to_string(mode.getVsyncRate()).c_str(),
+ mode.getDpi().x, mode.getDpi().y, mode.getGroup(),
+ to_string(mode.getVrrConfig()).c_str());
}
template <typename... DisplayModePtrs>
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index a9bb928..812621f 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -285,13 +285,12 @@
std::vector<HWCDisplayMode> modes;
modes.reserve(configs.size());
for (auto config : configs) {
- auto hwcMode = HWCDisplayMode{
- .hwcId = static_cast<hal::HWConfigId>(config.configId),
- .width = config.width,
- .height = config.height,
- .vsyncPeriod = config.vsyncPeriod,
- .configGroup = config.configGroup,
- };
+ auto hwcMode = HWCDisplayMode{.hwcId = static_cast<hal::HWConfigId>(config.configId),
+ .width = config.width,
+ .height = config.height,
+ .vsyncPeriod = config.vsyncPeriod,
+ .configGroup = config.configGroup,
+ .vrrConfig = config.vrrConfig};
if (config.dpi) {
hwcMode.dpiX = config.dpi->x;
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index 86f3825..b4d3d28 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -102,11 +102,13 @@
float dpiX = -1.f;
float dpiY = -1.f;
int32_t configGroup = -1;
+ std::optional<hal::VrrConfig> vrrConfig;
friend std::ostream& operator<<(std::ostream& os, const HWCDisplayMode& mode) {
return os << "id=" << mode.hwcId << " res=" << mode.width << "x" << mode.height
<< " vsyncPeriod=" << mode.vsyncPeriod << " dpi=" << mode.dpiX << "x"
- << mode.dpiY << " group=" << mode.configGroup;
+ << mode.dpiY << " group=" << mode.configGroup
+ << " vrrConfig=" << to_string(mode.vrrConfig).c_str();
}
};
diff --git a/services/surfaceflinger/DisplayHardware/Hal.h b/services/surfaceflinger/DisplayHardware/Hal.h
index e95ae89..20f7548 100644
--- a/services/surfaceflinger/DisplayHardware/Hal.h
+++ b/services/surfaceflinger/DisplayHardware/Hal.h
@@ -24,6 +24,7 @@
#include <aidl/android/hardware/graphics/composer3/Composition.h>
#include <aidl/android/hardware/graphics/composer3/DisplayCapability.h>
#include <aidl/android/hardware/graphics/composer3/DisplayConfiguration.h>
+#include <aidl/android/hardware/graphics/composer3/VrrConfig.h>
#define ERROR_HAS_CHANGES 5
@@ -73,6 +74,7 @@
using VsyncPeriodChangeConstraints = IComposerClient::VsyncPeriodChangeConstraints;
using Hdr = aidl::android::hardware::graphics::common::Hdr;
using DisplayConfiguration = V3_0::DisplayConfiguration;
+using VrrConfig = V3_0::VrrConfig;
} // namespace hardware::graphics::composer::hal
@@ -148,6 +150,34 @@
}
}
+inline std::string to_string(
+ const std::optional<aidl::android::hardware::graphics::composer3::VrrConfig>& vrrConfig) {
+ if (vrrConfig) {
+ std::ostringstream out;
+ out << "{minFrameIntervalNs=" << vrrConfig->minFrameIntervalNs << ", ";
+ out << "frameIntervalPowerHints={";
+ if (vrrConfig->frameIntervalPowerHints) {
+ const auto& powerHint = *vrrConfig->frameIntervalPowerHints;
+ for (size_t i = 0; i < powerHint.size(); i++) {
+ if (i > 0) out << ", ";
+ out << "[frameIntervalNs=" << powerHint[i]->frameIntervalNs
+ << ", averageRefreshPeriodNs=" << powerHint[i]->averageRefreshPeriodNs << "]";
+ }
+ }
+ out << "}, ";
+ out << "notifyExpectedPresentConfig={";
+ if (vrrConfig->notifyExpectedPresentConfig) {
+ out << "notifyExpectedPresentHeadsUpNs="
+ << vrrConfig->notifyExpectedPresentConfig->notifyExpectedPresentHeadsUpNs
+ << ", notifyExpectedPresentTimeoutNs="
+ << vrrConfig->notifyExpectedPresentConfig->notifyExpectedPresentTimeoutNs;
+ }
+ out << "}}";
+ return out.str();
+ }
+ return "N/A";
+}
+
inline std::string to_string(hardware::graphics::composer::hal::V2_4::Error error) {
// 5 is reserved for historical reason, during validation 5 means has changes.
if (ERROR_HAS_CHANGES == static_cast<int32_t>(error)) {
diff --git a/services/surfaceflinger/RefreshRateOverlay.cpp b/services/surfaceflinger/RefreshRateOverlay.cpp
index 577211f..e918dc9 100644
--- a/services/surfaceflinger/RefreshRateOverlay.cpp
+++ b/services/surfaceflinger/RefreshRateOverlay.cpp
@@ -27,7 +27,7 @@
namespace android {
-auto RefreshRateOverlay::draw(int displayFps, int renderFps, SkColor color,
+auto RefreshRateOverlay::draw(int vsyncRate, int renderFps, SkColor color,
ui::Transform::RotationFlags rotation, ftl::Flags<Features> features)
-> Buffers {
const size_t loopCount = features.test(Features::Spinner) ? 6 : 1;
@@ -70,7 +70,7 @@
canvas->setMatrix(canvasTransform);
int left = 0;
- drawNumber(displayFps, left, color, *canvas);
+ drawNumber(vsyncRate, left, color, *canvas);
left += 3 * (kDigitWidth + kDigitSpace);
if (features.test(Features::Spinner)) {
switch (i) {
@@ -153,7 +153,7 @@
.apply();
}
-auto RefreshRateOverlay::getOrCreateBuffers(Fps displayFps, Fps renderFps) -> const Buffers& {
+auto RefreshRateOverlay::getOrCreateBuffers(Fps vsyncRate, Fps renderFps) -> const Buffers& {
static const Buffers kNoBuffers;
if (!mSurfaceControl) return kNoBuffers;
@@ -180,16 +180,16 @@
createTransaction().setTransform(mSurfaceControl->get(), transform).apply();
BufferCache::const_iterator it =
- mBufferCache.find({displayFps.getIntValue(), renderFps.getIntValue(), transformHint});
+ mBufferCache.find({vsyncRate.getIntValue(), renderFps.getIntValue(), transformHint});
if (it == mBufferCache.end()) {
// HWC minFps is not known by the framework in order
// to consider lower rates we set minFps to 0.
const int minFps = isSetByHwc() ? 0 : mFpsRange.min.getIntValue();
const int maxFps = mFpsRange.max.getIntValue();
- // Clamp to the range. The current displayFps may be outside of this range if the display
+ // Clamp to the range. The current vsyncRate may be outside of this range if the display
// has changed its set of supported refresh rates.
- const int displayIntFps = std::clamp(displayFps.getIntValue(), minFps, maxFps);
+ const int displayIntFps = std::clamp(vsyncRate.getIntValue(), minFps, maxFps);
const int renderIntFps = renderFps.getIntValue();
// Ensure non-zero range to avoid division by zero.
@@ -242,17 +242,17 @@
createTransaction().setLayerStack(mSurfaceControl->get(), stack).apply();
}
-void RefreshRateOverlay::changeRefreshRate(Fps displayFps, Fps renderFps) {
- mDisplayFps = displayFps;
+void RefreshRateOverlay::changeRefreshRate(Fps vsyncRate, Fps renderFps) {
+ mVsyncRate = vsyncRate;
mRenderFps = renderFps;
- const auto buffer = getOrCreateBuffers(displayFps, renderFps)[mFrame];
+ const auto buffer = getOrCreateBuffers(vsyncRate, renderFps)[mFrame];
createTransaction().setBuffer(mSurfaceControl->get(), buffer).apply();
}
void RefreshRateOverlay::animate() {
- if (!mFeatures.test(Features::Spinner) || !mDisplayFps) return;
+ if (!mFeatures.test(Features::Spinner) || !mVsyncRate) return;
- const auto& buffers = getOrCreateBuffers(*mDisplayFps, *mRenderFps);
+ const auto& buffers = getOrCreateBuffers(*mVsyncRate, *mRenderFps);
mFrame = (mFrame + 1) % buffers.size();
const auto buffer = buffers[mFrame];
createTransaction().setBuffer(mSurfaceControl->get(), buffer).apply();
diff --git a/services/surfaceflinger/RefreshRateOverlay.h b/services/surfaceflinger/RefreshRateOverlay.h
index 65c61cb..c0fc79b 100644
--- a/services/surfaceflinger/RefreshRateOverlay.h
+++ b/services/surfaceflinger/RefreshRateOverlay.h
@@ -56,7 +56,7 @@
private:
using Buffers = std::vector<sp<GraphicBuffer>>;
- static Buffers draw(int displayFps, int renderFps, SkColor, ui::Transform::RotationFlags,
+ static Buffers draw(int vsyncRate, int renderFps, SkColor, ui::Transform::RotationFlags,
ftl::Flags<Features>);
static void drawNumber(int number, int left, SkColor, SkCanvas&);
@@ -65,12 +65,12 @@
SurfaceComposerClient::Transaction createTransaction() const;
struct Key {
- int displayFps;
+ int vsyncRate;
int renderFps;
ui::Transform::RotationFlags flags;
bool operator==(Key other) const {
- return displayFps == other.displayFps && renderFps == other.renderFps &&
+ return vsyncRate == other.vsyncRate && renderFps == other.renderFps &&
flags == other.flags;
}
};
@@ -78,7 +78,7 @@
using BufferCache = ftl::SmallMap<Key, Buffers, 9>;
BufferCache mBufferCache;
- std::optional<Fps> mDisplayFps;
+ std::optional<Fps> mVsyncRate;
std::optional<Fps> mRenderFps;
size_t mFrame = 0;
diff --git a/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp b/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp
index be28e98..3ee6a4d 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp
+++ b/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp
@@ -39,12 +39,16 @@
#include "../SurfaceFlingerProperties.h"
#include "RefreshRateSelector.h"
+#include <com_android_graphics_surfaceflinger_flags.h>
+
#undef LOG_TAG
#define LOG_TAG "RefreshRateSelector"
namespace android::scheduler {
namespace {
+using namespace com::android::graphics::surfaceflinger;
+
struct RefreshRateScore {
FrameRateMode frameRateMode;
float overallScore;
@@ -69,7 +73,7 @@
// Add all supported refresh rates.
for (const auto& [id, mode] : modes) {
- knownFrameRates.push_back(mode->getFps());
+ knownFrameRates.push_back(mode->getPeakFps());
}
// Sort and remove duplicates.
@@ -91,17 +95,17 @@
const auto& mode1 = it1->second;
const auto& mode2 = it2->second;
- if (mode1->getVsyncPeriod() == mode2->getVsyncPeriod()) {
+ if (mode1->getVsyncRate().getPeriodNsecs() == mode2->getVsyncRate().getPeriodNsecs()) {
return mode1->getGroup() > mode2->getGroup();
}
- return mode1->getVsyncPeriod() > mode2->getVsyncPeriod();
+ return mode1->getVsyncRate().getPeriodNsecs() > mode2->getVsyncRate().getPeriodNsecs();
});
return sortedModes;
}
-std::pair<unsigned, unsigned> divisorRange(Fps fps, FpsRange range,
+std::pair<unsigned, unsigned> divisorRange(Fps vsyncRate, Fps peakFps, FpsRange range,
RefreshRateSelector::Config::FrameRateOverride config) {
if (config != RefreshRateSelector::Config::FrameRateOverride::Enabled) {
return {1, 1};
@@ -109,8 +113,14 @@
using fps_approx_ops::operator/;
// use signed type as `fps / range.max` might be 0
- const auto start = std::max(1, static_cast<int>(fps / range.max) - 1);
- const auto end = fps /
+ auto start = std::max(1, static_cast<int>(peakFps / range.max) - 1);
+ if (flags::vrr_config()) {
+ start = std::max(1,
+ static_cast<int>(vsyncRate /
+ std::min(range.max, peakFps, fps_approx_ops::operator<)) -
+ 1);
+ }
+ const auto end = vsyncRate /
std::max(range.min, RefreshRateSelector::kMinSupportedFrameRate,
fps_approx_ops::operator<);
@@ -123,7 +133,8 @@
for (const auto it2 : sortedModes) {
const auto& mode2 = it2->second;
- if (RefreshRateSelector::getFrameRateDivisor(mode1->getFps(), mode2->getFps()) >= 2) {
+ if (RefreshRateSelector::getFrameRateDivisor(mode1->getPeakFps(),
+ mode2->getPeakFps()) >= 2) {
return true;
}
}
@@ -176,10 +187,12 @@
if (!filterModes(*mode)) {
continue;
}
+ const auto vsyncRate = mode->getVsyncRate();
+ const auto peakFps = mode->getPeakFps();
const auto [start, end] =
- divisorRange(mode->getFps(), renderRange, mConfig.enableFrameRateOverride);
+ divisorRange(vsyncRate, peakFps, renderRange, mConfig.enableFrameRateOverride);
for (auto divisor = start; divisor <= end; divisor++) {
- const auto fps = mode->getFps() / divisor;
+ const auto fps = vsyncRate / divisor;
using fps_approx_ops::operator<;
if (divisor > 1 && fps < kMinSupportedFrameRate) {
break;
@@ -199,28 +212,30 @@
const auto [existingIter, emplaceHappened] =
ratesMap.try_emplace(Key{fps, mode->getGroup()}, it);
if (emplaceHappened) {
- ALOGV("%s: including %s (%s)", __func__, to_string(fps).c_str(),
- to_string(mode->getFps()).c_str());
+ ALOGV("%s: including %s (%s(%s))", __func__, to_string(fps).c_str(),
+ to_string(peakFps).c_str(), to_string(vsyncRate).c_str());
} else {
// If the primary physical range is a single rate, prefer to stay in that rate
// even if there is a lower physical refresh rate available. This would cause more
// cases to stay within the primary physical range
- const Fps existingModeFps = existingIter->second->second->getFps();
+ const Fps existingModeFps = existingIter->second->second->getPeakFps();
const bool existingModeIsPrimaryRange = policy.primaryRangeIsSingleRate() &&
policy.primaryRanges.physical.includes(existingModeFps);
const bool newModeIsPrimaryRange = policy.primaryRangeIsSingleRate() &&
- policy.primaryRanges.physical.includes(mode->getFps());
+ policy.primaryRanges.physical.includes(mode->getPeakFps());
if (newModeIsPrimaryRange == existingModeIsPrimaryRange) {
// We might need to update the map as we found a lower refresh rate
- if (isStrictlyLess(mode->getFps(), existingModeFps)) {
+ if (isStrictlyLess(mode->getPeakFps(), existingModeFps)) {
existingIter->second = it;
- ALOGV("%s: changing %s (%s) as we found a lower physical rate", __func__,
- to_string(fps).c_str(), to_string(mode->getFps()).c_str());
+ ALOGV("%s: changing %s (%s(%s)) as we found a lower physical rate",
+ __func__, to_string(fps).c_str(), to_string(peakFps).c_str(),
+ to_string(vsyncRate).c_str());
}
} else if (newModeIsPrimaryRange) {
existingIter->second = it;
- ALOGV("%s: changing %s (%s) to stay in the primary range", __func__,
- to_string(fps).c_str(), to_string(mode->getFps()).c_str());
+ ALOGV("%s: changing %s (%s(%s)) to stay in the primary range", __func__,
+ to_string(fps).c_str(), to_string(peakFps).c_str(),
+ to_string(vsyncRate).c_str());
}
}
}
@@ -237,8 +252,8 @@
const auto lowestRefreshRateIt =
std::min_element(frameRateModes.begin(), frameRateModes.end(),
[](const FrameRateMode& lhs, const FrameRateMode& rhs) {
- return isStrictlyLess(lhs.modePtr->getFps(),
- rhs.modePtr->getFps());
+ return isStrictlyLess(lhs.modePtr->getVsyncRate(),
+ rhs.modePtr->getVsyncRate());
});
frameRateModes.erase(frameRateModes.begin(), lowestRefreshRateIt);
@@ -623,7 +638,7 @@
}
const bool inPrimaryPhysicalRange =
- policy->primaryRanges.physical.includes(modePtr->getFps());
+ policy->primaryRanges.physical.includes(modePtr->getPeakFps());
const bool inPrimaryRenderRange = policy->primaryRanges.render.includes(fps);
if (((policy->primaryRangeIsSingleRate() && !inPrimaryPhysicalRange) ||
!inPrimaryRenderRange) &&
@@ -664,21 +679,24 @@
Fps::fromValue(mConfig.frameRateMultipleThreshold / 2);
if (fixedSourceLayer && layerBelowThreshold) {
const bool modeAboveThreshold =
- modePtr->getFps() >= Fps::fromValue(mConfig.frameRateMultipleThreshold);
+ modePtr->getPeakFps() >= Fps::fromValue(mConfig.frameRateMultipleThreshold);
if (modeAboveThreshold) {
- ALOGV("%s gives %s (%s) fixed source (above threshold) score of %.4f",
+ ALOGV("%s gives %s (%s(%s)) fixed source (above threshold) score of %.4f",
formatLayerInfo(layer, weight).c_str(), to_string(fps).c_str(),
- to_string(modePtr->getFps()).c_str(), layerScore);
+ to_string(modePtr->getPeakFps()).c_str(),
+ to_string(modePtr->getVsyncRate()).c_str(), layerScore);
fixedRateBelowThresholdLayersScore.modeAboveThreshold += weightedLayerScore;
} else {
- ALOGV("%s gives %s (%s) fixed source (below threshold) score of %.4f",
+ ALOGV("%s gives %s (%s(%s)) fixed source (below threshold) score of %.4f",
formatLayerInfo(layer, weight).c_str(), to_string(fps).c_str(),
- to_string(modePtr->getFps()).c_str(), layerScore);
+ to_string(modePtr->getPeakFps()).c_str(),
+ to_string(modePtr->getVsyncRate()).c_str(), layerScore);
fixedRateBelowThresholdLayersScore.modeBelowThreshold += weightedLayerScore;
}
} else {
- ALOGV("%s gives %s (%s) score of %.4f", formatLayerInfo(layer, weight).c_str(),
- to_string(fps).c_str(), to_string(modePtr->getFps()).c_str(), layerScore);
+ ALOGV("%s gives %s (%s(%s)) score of %.4f", formatLayerInfo(layer, weight).c_str(),
+ to_string(fps).c_str(), to_string(modePtr->getPeakFps()).c_str(),
+ to_string(modePtr->getVsyncRate()).c_str(), layerScore);
overallScore += weightedLayerScore;
}
}
@@ -699,13 +717,14 @@
[](RefreshRateScore max, RefreshRateScore current) {
return current.overallScore > max.overallScore;
});
- ALOGV("%s (%s) is the best refresh rate without fixed source layers. It is %s the "
+ ALOGV("%s (%s(%s)) is the best refresh rate without fixed source layers. It is %s the "
"threshold for "
"refresh rate multiples",
to_string(maxScoreIt->frameRateMode.fps).c_str(),
- to_string(maxScoreIt->frameRateMode.modePtr->getFps()).c_str(),
+ to_string(maxScoreIt->frameRateMode.modePtr->getPeakFps()).c_str(),
+ to_string(maxScoreIt->frameRateMode.modePtr->getVsyncRate()).c_str(),
maxScoreAboveThreshold ? "above" : "below");
- return maxScoreIt->frameRateMode.modePtr->getFps() >=
+ return maxScoreIt->frameRateMode.modePtr->getPeakFps() >=
Fps::fromValue(mConfig.frameRateMultipleThreshold);
}();
@@ -715,8 +734,9 @@
if (maxScoreAboveThreshold) {
overallScore += fixedRateBelowThresholdLayersScore.modeAboveThreshold;
}
- ALOGV("%s (%s) adjusted overallScore is %.4f", to_string(frameRateMode.fps).c_str(),
- to_string(frameRateMode.modePtr->getFps()).c_str(), overallScore);
+ ALOGV("%s (%s(%s)) adjusted overallScore is %.4f", to_string(frameRateMode.fps).c_str(),
+ to_string(frameRateMode.modePtr->getPeakFps()).c_str(),
+ to_string(frameRateMode.modePtr->getVsyncRate()).c_str(), overallScore);
}
// Now that we scored all the refresh rates we need to pick the one that got the highest
@@ -842,6 +862,7 @@
const auto* policyPtr = getCurrentPolicyLocked();
// We don't want to run lower than 30fps
+ // TODO(b/297600226): revise this for dVRR
const Fps minFrameRate = std::max(policyPtr->appRequestRanges.render.min, 30_Hz, isApproxLess);
using fps_approx_ops::operator/;
@@ -933,7 +954,7 @@
const auto current = [&]() REQUIRES(mLock) -> FrameRateMode {
if (desiredActiveModeId) {
const auto& modePtr = mDisplayModes.get(*desiredActiveModeId)->get();
- return FrameRateMode{modePtr->getFps(), ftl::as_non_null(modePtr)};
+ return FrameRateMode{modePtr->getPeakFps(), ftl::as_non_null(modePtr)};
}
return getActiveModeLocked();
@@ -944,7 +965,7 @@
return {};
}
- return timerExpired ? FrameRateMode{min->getFps(), ftl::as_non_null(min)} : current;
+ return timerExpired ? FrameRateMode{min->getPeakFps(), ftl::as_non_null(min)} : current;
}
const DisplayModePtr& RefreshRateSelector::getMinRefreshRateByPolicyLocked() const {
@@ -970,12 +991,12 @@
bool maxByAnchorFound = false;
for (auto it = mPrimaryFrameRates.rbegin(); it != mPrimaryFrameRates.rend(); ++it) {
using namespace fps_approx_ops;
- if (it->modePtr->getFps() > (*max)->getFps()) {
+ if (it->modePtr->getPeakFps() > (*max)->getPeakFps()) {
max = &it->modePtr;
}
if (anchorGroup == it->modePtr->getGroup() &&
- it->modePtr->getFps() >= (*maxByAnchor)->getFps()) {
+ it->modePtr->getPeakFps() >= (*maxByAnchor)->getPeakFps()) {
maxByAnchorFound = true;
maxByAnchor = &it->modePtr;
}
@@ -1053,8 +1074,9 @@
return;
}
- ALOGV("%s(%s) %s (%s) scored %.2f", whence, ftl::enum_string(refreshRateOrder).c_str(),
- to_string(frameRateMode.fps).c_str(), to_string(modePtr->getFps()).c_str(), score);
+ ALOGV("%s(%s) %s (%s(%s)) scored %.2f", whence, ftl::enum_string(refreshRateOrder).c_str(),
+ to_string(frameRateMode.fps).c_str(), to_string(modePtr->getPeakFps()).c_str(),
+ to_string(modePtr->getVsyncRate()).c_str(), score);
ranking.emplace_back(ScoredFrameRate{frameRateMode, score});
};
@@ -1134,8 +1156,8 @@
mDisplayModes = std::move(modes);
const auto activeModeOpt = mDisplayModes.get(activeModeId);
LOG_ALWAYS_FATAL_IF(!activeModeOpt);
- mActiveModeOpt =
- FrameRateMode{activeModeOpt->get()->getFps(), ftl::as_non_null(activeModeOpt->get())};
+ mActiveModeOpt = FrameRateMode{activeModeOpt->get()->getPeakFps(),
+ ftl::as_non_null(activeModeOpt->get())};
const auto sortedModes = sortByRefreshRate(mDisplayModes);
mMinRefreshRateModeIt = sortedModes.front();
@@ -1161,7 +1183,7 @@
if (mConfig.enableFrameRateOverride ==
Config::FrameRateOverride::AppOverrideNativeRefreshRates) {
for (const auto& [_, mode] : mDisplayModes) {
- mAppOverrideNativeRefreshRates.try_emplace(mode->getFps(), ftl::unit);
+ mAppOverrideNativeRefreshRates.try_emplace(mode->getPeakFps(), ftl::unit);
}
}
@@ -1171,7 +1193,7 @@
bool RefreshRateSelector::isPolicyValidLocked(const Policy& policy) const {
// defaultMode must be a valid mode, and within the given refresh rate range.
if (const auto mode = mDisplayModes.get(policy.defaultMode)) {
- if (!policy.primaryRanges.physical.includes(mode->get()->getFps())) {
+ if (!policy.primaryRanges.physical.includes(mode->get()->getPeakFps())) {
ALOGE("Default mode is not in the primary range.");
return false;
}
@@ -1284,8 +1306,8 @@
return mode.getResolution() == defaultMode->getResolution() &&
mode.getDpi() == defaultMode->getDpi() &&
(policy->allowGroupSwitching || mode.getGroup() == defaultMode->getGroup()) &&
- ranges.physical.includes(mode.getFps()) &&
- (supportsFrameRateOverride() || ranges.render.includes(mode.getFps()));
+ ranges.physical.includes(mode.getPeakFps()) &&
+ (supportsFrameRateOverride() || ranges.render.includes(mode.getPeakFps()));
};
auto frameRateModes = createFrameRateModes(*policy, filterModes, ranges.render);
@@ -1340,13 +1362,13 @@
auto RefreshRateSelector::getIdleTimerAction() const -> KernelIdleTimerAction {
std::lock_guard lock(mLock);
- const Fps deviceMinFps = mMinRefreshRateModeIt->second->getFps();
+ const Fps deviceMinFps = mMinRefreshRateModeIt->second->getPeakFps();
const DisplayModePtr& minByPolicy = getMinRefreshRateByPolicyLocked();
// Kernel idle timer will set the refresh rate to the device min. If DisplayManager says that
// the min allowed refresh rate is higher than the device min, we do not want to enable the
// timer.
- if (isStrictlyLess(deviceMinFps, minByPolicy->getFps())) {
+ if (isStrictlyLess(deviceMinFps, minByPolicy->getPeakFps())) {
return KernelIdleTimerAction::TurnOff;
}
diff --git a/services/surfaceflinger/Scheduler/RefreshRateSelector.h b/services/surfaceflinger/Scheduler/RefreshRateSelector.h
index 73e1d38..9bcbc0e 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateSelector.h
+++ b/services/surfaceflinger/Scheduler/RefreshRateSelector.h
@@ -253,7 +253,8 @@
FpsRange getSupportedRefreshRateRange() const EXCLUDES(mLock) {
std::lock_guard lock(mLock);
- return {mMinRefreshRateModeIt->second->getFps(), mMaxRefreshRateModeIt->second->getFps()};
+ return {mMinRefreshRateModeIt->second->getPeakFps(),
+ mMaxRefreshRateModeIt->second->getPeakFps()};
}
ftl::Optional<FrameRateMode> onKernelTimerChanged(
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index 27c96f7..595550b 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -494,7 +494,7 @@
if (display.schedulePtr->isHardwareVsyncAllowed(allowToEnable)) {
if (!refreshRate) {
- refreshRate = display.selectorPtr->getActiveMode().modePtr->getFps();
+ refreshRate = display.selectorPtr->getActiveMode().modePtr->getVsyncRate();
}
if (refreshRate->isValid()) {
constexpr bool kForce = false;
@@ -542,7 +542,7 @@
to_string(mode.fps).c_str(), to_string(renderFrameRate).c_str(), id.value);
ALOGV("%s %s (%s)", __func__, to_string(mode.fps).c_str(),
- to_string(mode.modePtr->getFps()).c_str());
+ to_string(mode.modePtr->getVsyncRate()).c_str());
display.schedulePtr->getTracker().setRenderRate(renderFrameRate);
}
@@ -717,7 +717,7 @@
// TODO(145561154): cleanup the kernel idle timer implementation and the refresh rate
// magic number
- const Fps refreshRate = pacesetterSelectorPtr()->getActiveMode().modePtr->getFps();
+ const Fps refreshRate = pacesetterSelectorPtr()->getActiveMode().modePtr->getPeakFps();
constexpr Fps FPS_THRESHOLD_FOR_KERNEL_TIMER = 65_Hz;
using namespace fps_approx_ops;
@@ -877,7 +877,7 @@
newVsyncSchedulePtr = pacesetter.schedulePtr;
- const Fps refreshRate = pacesetter.selectorPtr->getActiveMode().modePtr->getFps();
+ const Fps refreshRate = pacesetter.selectorPtr->getActiveMode().modePtr->getVsyncRate();
constexpr bool kForce = true;
newVsyncSchedulePtr->startPeriodTransition(refreshRate.getPeriod(), kForce);
}
diff --git a/services/surfaceflinger/Scheduler/VsyncConfiguration.h b/services/surfaceflinger/Scheduler/VsyncConfiguration.h
index a24e43f..b6cb373 100644
--- a/services/surfaceflinger/Scheduler/VsyncConfiguration.h
+++ b/services/surfaceflinger/Scheduler/VsyncConfiguration.h
@@ -143,7 +143,7 @@
*/
class WorkDuration : public VsyncConfiguration {
public:
- explicit WorkDuration(Fps currentRefrshRate);
+ explicit WorkDuration(Fps currentRefreshRate);
protected:
// Used for unit tests
diff --git a/services/surfaceflinger/Scheduler/include/scheduler/FrameRateMode.h b/services/surfaceflinger/Scheduler/include/scheduler/FrameRateMode.h
index db38ebe..59a6df2 100644
--- a/services/surfaceflinger/Scheduler/include/scheduler/FrameRateMode.h
+++ b/services/surfaceflinger/Scheduler/include/scheduler/FrameRateMode.h
@@ -36,7 +36,8 @@
};
inline std::string to_string(const FrameRateMode& mode) {
- return to_string(mode.fps) + " (" + to_string(mode.modePtr->getFps()) + ")";
+ return to_string(mode.fps) + " (" + to_string(mode.modePtr->getPeakFps()) + "(" +
+ to_string(mode.modePtr->getVsyncRate()) + "))";
}
} // namespace android::scheduler
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 3e25fb7..54d6740 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1044,8 +1044,8 @@
outMode.xDpi = xDpi;
outMode.yDpi = yDpi;
- const nsecs_t period = mode->getVsyncPeriod();
- outMode.refreshRate = Fps::fromPeriodNsecs(period).getValue();
+ const auto peakFps = mode->getPeakFps();
+ outMode.refreshRate = peakFps.getValue();
const auto vsyncConfigSet =
mVsyncConfiguration->getConfigsForRefreshRate(Fps::fromValue(outMode.refreshRate));
@@ -1065,7 +1065,7 @@
//
// We add an additional 1ms to allow for processing time and
// differences between the ideal and actual refresh rate.
- outMode.presentationDeadline = period - outMode.sfVsyncOffset + 1000000;
+ outMode.presentationDeadline = peakFps.getPeriodNsecs() - outMode.sfVsyncOffset + 1000000;
excludeDolbyVisionIf4k30Present(display->getHdrCapabilities().getSupportedHdrTypes(),
outMode);
info->supportedDisplayModes.push_back(outMode);
@@ -1200,7 +1200,7 @@
// Start receiving vsync samples now, so that we can detect a period
// switch.
mScheduler->resyncToHardwareVsync(displayId, true /* allowToEnable */,
- mode.modePtr->getFps());
+ mode.modePtr->getVsyncRate());
// As we called to set period, we will call to onRefreshRateChangeCompleted once
// VsyncController model is locked.
@@ -1254,7 +1254,7 @@
const auto& snapshot = snapshotRef.get();
const auto fpsOpt = snapshot.displayModes().get(modeId).transform(
- [](const DisplayModePtr& mode) { return mode->getFps(); });
+ [](const DisplayModePtr& mode) { return mode->getPeakFps(); });
if (!fpsOpt) {
ALOGE("%s: Invalid mode %d for display %s", whence, modeId.value(),
@@ -1303,7 +1303,7 @@
}
const auto& activeMode = *upcomingModeInfo.modeOpt;
- display.finalizeModeChange(activeMode.modePtr->getId(), activeMode.modePtr->getFps(),
+ display.finalizeModeChange(activeMode.modePtr->getId(), activeMode.modePtr->getVsyncRate(),
activeMode.fps);
if (displayId == mActiveDisplayId) {
@@ -1328,10 +1328,10 @@
const auto desiredActiveMode = display->getDesiredActiveMode();
const auto& modeOpt = desiredActiveMode->modeOpt;
const auto displayId = modeOpt->modePtr->getPhysicalDisplayId();
- const auto displayFps = modeOpt->modePtr->getFps();
+ const auto vsyncRate = modeOpt->modePtr->getVsyncRate();
const auto renderFps = modeOpt->fps;
clearDesiredActiveModeState(display);
- mScheduler->resyncToHardwareVsync(displayId, true /* allowToEnable */, displayFps);
+ mScheduler->resyncToHardwareVsync(displayId, true /* allowToEnable */, vsyncRate);
mScheduler->setRenderRate(displayId, renderFps);
if (displayId == mActiveDisplayId) {
@@ -1372,7 +1372,7 @@
}
ALOGV("%s changing active mode to %d(%s) for display %s", __func__, desiredModeId.value(),
- to_string(displayModePtrOpt->get()->getFps()).c_str(),
+ to_string(displayModePtrOpt->get()->getVsyncRate()).c_str(),
to_string(display->getId()).c_str());
if (display->getActiveMode() == desiredActiveMode->modeOpt) {
@@ -3212,6 +3212,7 @@
.setPhysicalDisplayId(displayId)
.setResolution({hwcMode.width, hwcMode.height})
.setVsyncPeriod(hwcMode.vsyncPeriod)
+ .setVrrConfig(hwcMode.vrrConfig)
.setDpiX(hwcMode.dpiX)
.setDpiY(hwcMode.dpiY)
.setGroup(hwcMode.configGroup)
@@ -3435,7 +3436,7 @@
if (const auto& physical = state.physical) {
const auto& mode = *physical->activeMode;
- display->setActiveMode(mode.getId(), mode.getFps(), mode.getFps());
+ display->setActiveMode(mode.getId(), mode.getVsyncRate(), mode.getVsyncRate());
}
display->setLayerFilter(makeLayerFilterForDisplay(display->getId(), state.layerStack));
@@ -5678,7 +5679,7 @@
display->setPowerMode(mode);
- const auto refreshRate = display->refreshRateSelector().getActiveMode().modePtr->getFps();
+ const auto refreshRate = display->refreshRateSelector().getActiveMode().modePtr->getVsyncRate();
if (!currentModeOpt || *currentModeOpt == hal::PowerMode::OFF) {
// Turn on the display
@@ -6406,7 +6407,7 @@
std::string fps, xDpi, yDpi;
if (const auto activeModePtr =
display->refreshRateSelector().getActiveMode().modePtr.get()) {
- fps = to_string(activeModePtr->getFps());
+ fps = to_string(activeModePtr->getVsyncRate());
const auto dpi = activeModePtr->getDpi();
xDpi = base::StringPrintf("%.2f", dpi.x);
@@ -7969,7 +7970,7 @@
return snapshot.displayModes().get(defaultModeId);
})
.transform([](const DisplayModePtr& modePtr) {
- return scheduler::FrameRateMode{modePtr->getFps(), ftl::as_non_null(modePtr)};
+ return scheduler::FrameRateMode{modePtr->getPeakFps(), ftl::as_non_null(modePtr)};
});
}
diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h
index 437fd35..c4077df 100644
--- a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h
+++ b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h
@@ -666,7 +666,7 @@
}
mRefreshRateSelector = std::make_shared<scheduler::RefreshRateSelector>(modes, kModeId60);
- const auto fps = mRefreshRateSelector->getActiveMode().modePtr->getFps();
+ const auto fps = mRefreshRateSelector->getActiveMode().modePtr->getVsyncRate();
mFlinger->mVsyncConfiguration = mFactory.createVsyncConfiguration(fps);
mFlinger->mRefreshRateStats =
diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.cpp b/services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.cpp
index 4d1a5ff..cbbfa16 100644
--- a/services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.cpp
+++ b/services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.cpp
@@ -390,7 +390,7 @@
PowerMode::OFF);
const auto fpsOpt = displayModes.get(modeId).transform(
- [](const DisplayModePtr& mode) { return mode->getFps(); });
+ [](const DisplayModePtr& mode) { return mode->getVsyncRate(); });
refreshRateStats.setRefreshRate(*fpsOpt);
refreshRateStats.setPowerMode(mFdp.PickValueInArray(kPowerModes));
diff --git a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
index 91c6239..9b46009 100644
--- a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
+++ b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
@@ -703,7 +703,7 @@
.setId(DisplayModeId(7))
.setVsyncPeriod(16666666)
.build();
- const Fps fps = mode->getFps() / 2;
+ const Fps fps = mode->getPeakFps() / 2;
mThread->onModeChanged({fps, ftl::as_non_null(mode)});
expectConfigChangedEventReceivedByConnection(INTERNAL_DISPLAY_ID, 7, fps.getPeriodNsecs());
@@ -717,7 +717,7 @@
.setId(DisplayModeId(5))
.setVsyncPeriod(16666666)
.build();
- const Fps fps = mode->getFps() / 2;
+ const Fps fps = mode->getPeakFps() / 2;
mThread->onModeChanged({fps, ftl::as_non_null(mode)});
expectConfigChangedEventReceivedByConnection(EXTERNAL_DISPLAY_ID, 5, fps.getPeriodNsecs());
@@ -731,7 +731,7 @@
.setId(DisplayModeId(7))
.setVsyncPeriod(16666666)
.build();
- const Fps fps = mode->getFps() / 2;
+ const Fps fps = mode->getPeakFps() / 2;
mThread->onModeChanged({fps, ftl::as_non_null(mode)});
expectConfigChangedEventReceivedByConnection(DISPLAY_ID_64BIT, 7, fps.getPeriodNsecs());
}
@@ -748,7 +748,7 @@
.setId(DisplayModeId(9))
.setVsyncPeriod(16666666)
.build();
- const Fps fps = mode->getFps() / 2;
+ const Fps fps = mode->getPeakFps() / 2;
mThread->onModeChanged({fps, ftl::as_non_null(mode)});
expectConfigChangedEventReceivedByConnection(INTERNAL_DISPLAY_ID, 9, fps.getPeriodNsecs());
diff --git a/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp
index 50c1626..264b172 100644
--- a/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp
+++ b/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp
@@ -36,6 +36,9 @@
#include "libsurfaceflinger_unittest_main.h"
+#include <com_android_graphics_surfaceflinger_flags.h>
+
+using namespace com::android::graphics::surfaceflinger;
using namespace std::chrono_literals;
namespace android::scheduler {
@@ -48,6 +51,7 @@
using SetPolicyResult = RefreshRateSelector::SetPolicyResult;
using mock::createDisplayMode;
+using mock::createVrrDisplayMode;
struct TestableRefreshRateSelector : RefreshRateSelector {
using RefreshRateSelector::FrameRateRanking;
@@ -201,6 +205,19 @@
static inline const ftl::NonNull<DisplayModePtr> kMode10 =
ftl::as_non_null(createDisplayMode(kModeId10, 10_Hz));
+ // VRR modes
+ static inline const ftl::NonNull<DisplayModePtr> kVrrMode120TE240 = ftl::as_non_null(
+ createVrrDisplayMode(kModeId120, 240_Hz,
+ hal::VrrConfig{
+ .minFrameIntervalNs =
+ static_cast<Fps>(120_Hz).getPeriodNsecs()}));
+
+ static inline const ftl::NonNull<DisplayModePtr> kVrrMode60TE120 = ftl::as_non_null(
+ createVrrDisplayMode(kModeId60, 120_Hz,
+ hal::VrrConfig{.minFrameIntervalNs =
+ static_cast<Fps>(60_Hz).getPeriodNsecs()},
+ /*group=*/1));
+
// Test configurations.
static inline const DisplayModes kModes_60 = makeModes(kMode60);
static inline const DisplayModes kModes_35_60_90 = makeModes(kMode35, kMode60, kMode90);
@@ -225,6 +242,11 @@
static inline const DisplayModes kModes_1_5_10 = makeModes(kMode1, kMode5, kMode10);
static inline const DisplayModes kModes_60_90_120 = makeModes(kMode60, kMode90, kMode120);
+ // VRR display modes
+ static inline const DisplayModes kVrrMode_120 = makeModes(kVrrMode120TE240);
+ static inline const DisplayModes kVrrModes_60_120 =
+ makeModes(kVrrMode60TE120, kVrrMode120TE240);
+
// This is a typical TV configuration.
static inline const DisplayModes kModes_24_25_30_50_60_Frac =
makeModes(kMode24, kMode24Frac, kMode25, kMode30, kMode30Frac, kMode50, kMode60,
@@ -973,7 +995,8 @@
lr.desiredRefreshRate = Fps::fromValue(fps);
const auto mode = selector.getBestFrameRateMode(layers);
EXPECT_EQ(kMode60, mode) << lr.desiredRefreshRate << " chooses "
- << to_string(mode->getFps());
+ << to_string(mode->getPeakFps()) << "("
+ << to_string(mode->getVsyncRate()) << ")";
}
}
@@ -988,7 +1011,8 @@
lr.desiredRefreshRate = Fps::fromValue(fps);
const auto mode = selector.getBestFrameRateMode(layers);
EXPECT_EQ(kMode60, mode) << lr.desiredRefreshRate << " chooses "
- << to_string(mode->getFps());
+ << to_string(mode->getPeakFps()) << "("
+ << to_string(mode->getVsyncRate()) << ")";
}
}
@@ -1029,7 +1053,8 @@
lr.desiredRefreshRate = Fps::fromValue(fps);
const auto mode = selector.getBestFrameRateMode(layers, {});
EXPECT_EQ(kMode90, mode) << lr.desiredRefreshRate << " chooses "
- << to_string(mode->getFps());
+ << to_string(mode->getPeakFps()) << "("
+ << to_string(mode->getVsyncRate()) << ")";
}
}
@@ -1146,9 +1171,9 @@
for (size_t i = 0; i < expectedRefreshRates.size(); ++i) {
EXPECT_EQ(expectedRefreshRates[i], refreshRates[i].frameRateMode)
<< "Expected " << expectedRefreshRates[i].fps.getIntValue() << " ("
- << expectedRefreshRates[i].modePtr->getFps().getIntValue() << ")"
+ << expectedRefreshRates[i].modePtr->getVsyncRate().getIntValue() << ")"
<< " Actual " << refreshRates[i].frameRateMode.fps.getIntValue() << " ("
- << refreshRates[i].frameRateMode.modePtr->getFps().getIntValue() << ")";
+ << refreshRates[i].frameRateMode.modePtr->getVsyncRate().getIntValue() << ")";
}
}
@@ -1175,9 +1200,9 @@
for (size_t i = 0; i < expectedRefreshRates.size(); ++i) {
EXPECT_EQ(expectedRefreshRates[i], refreshRates[i].frameRateMode)
<< "Expected " << expectedRefreshRates[i].fps.getIntValue() << " ("
- << expectedRefreshRates[i].modePtr->getFps().getIntValue() << ")"
+ << expectedRefreshRates[i].modePtr->getVsyncRate().getIntValue() << ")"
<< " Actual " << refreshRates[i].frameRateMode.fps.getIntValue() << " ("
- << refreshRates[i].frameRateMode.modePtr->getFps().getIntValue() << ")";
+ << refreshRates[i].frameRateMode.modePtr->getVsyncRate().getIntValue() << ")";
}
}
@@ -1207,9 +1232,9 @@
for (size_t i = 0; i < expectedRefreshRates.size(); ++i) {
EXPECT_EQ(expectedRefreshRates[i], refreshRates[i].frameRateMode)
<< "Expected " << expectedRefreshRates[i].fps.getIntValue() << " ("
- << expectedRefreshRates[i].modePtr->getFps().getIntValue() << ")"
+ << expectedRefreshRates[i].modePtr->getVsyncRate().getIntValue() << ")"
<< " Actual " << refreshRates[i].frameRateMode.fps.getIntValue() << " ("
- << refreshRates[i].frameRateMode.modePtr->getFps().getIntValue() << ")";
+ << refreshRates[i].frameRateMode.modePtr->getVsyncRate().getIntValue() << ")";
}
}
@@ -1239,9 +1264,9 @@
for (size_t i = 0; i < expectedRefreshRates.size(); ++i) {
EXPECT_EQ(expectedRefreshRates[i], refreshRates[i].frameRateMode)
<< "Expected " << expectedRefreshRates[i].fps.getIntValue() << " ("
- << expectedRefreshRates[i].modePtr->getFps().getIntValue() << ")"
+ << expectedRefreshRates[i].modePtr->getVsyncRate().getIntValue() << ")"
<< " Actual " << refreshRates[i].frameRateMode.fps.getIntValue() << " ("
- << refreshRates[i].frameRateMode.modePtr->getFps().getIntValue() << ")";
+ << refreshRates[i].frameRateMode.modePtr->getVsyncRate().getIntValue() << ")";
}
}
@@ -1267,9 +1292,9 @@
for (size_t i = 0; i < expectedRefreshRates.size(); ++i) {
EXPECT_EQ(expectedRefreshRates[i], refreshRates[i].frameRateMode)
<< "Expected " << expectedRefreshRates[i].fps.getIntValue() << " ("
- << expectedRefreshRates[i].modePtr->getFps().getIntValue() << ")"
+ << expectedRefreshRates[i].modePtr->getVsyncRate().getIntValue() << ")"
<< " Actual " << refreshRates[i].frameRateMode.fps.getIntValue() << " ("
- << refreshRates[i].frameRateMode.modePtr->getFps().getIntValue() << ")";
+ << refreshRates[i].frameRateMode.modePtr->getVsyncRate().getIntValue() << ")";
}
std::tie(refreshRates, signals) =
@@ -1281,9 +1306,9 @@
for (size_t i = 0; i < expectedRefreshRates.size(); ++i) {
EXPECT_EQ(expectedRefreshRates[i], refreshRates[i].frameRateMode)
<< "Expected " << expectedRefreshRates[i].fps.getIntValue() << " ("
- << expectedRefreshRates[i].modePtr->getFps().getIntValue() << ")"
+ << expectedRefreshRates[i].modePtr->getVsyncRate().getIntValue() << ")"
<< " Actual " << refreshRates[i].frameRateMode.fps.getIntValue() << " ("
- << refreshRates[i].frameRateMode.modePtr->getFps().getIntValue() << ")";
+ << refreshRates[i].frameRateMode.modePtr->getVsyncRate().getIntValue() << ")";
}
std::vector<LayerRequirement> layers = {{.weight = 1.f}};
@@ -1301,9 +1326,9 @@
for (size_t i = 0; i < expectedRefreshRates.size(); ++i) {
EXPECT_EQ(expectedRefreshRates[i], refreshRates[i].frameRateMode)
<< "Expected " << expectedRefreshRates[i].fps.getIntValue() << " ("
- << expectedRefreshRates[i].modePtr->getFps().getIntValue() << ")"
+ << expectedRefreshRates[i].modePtr->getVsyncRate().getIntValue() << ")"
<< " Actual " << refreshRates[i].frameRateMode.fps.getIntValue() << " ("
- << refreshRates[i].frameRateMode.modePtr->getFps().getIntValue() << ")";
+ << refreshRates[i].frameRateMode.modePtr->getVsyncRate().getIntValue() << ")";
}
std::tie(refreshRates, signals) =
@@ -1326,9 +1351,9 @@
for (size_t i = 0; i < expectedRefreshRates.size(); ++i) {
EXPECT_EQ(expectedRefreshRates[i], refreshRates[i].frameRateMode)
<< "Expected " << expectedRefreshRates[i].fps.getIntValue() << " ("
- << expectedRefreshRates[i].modePtr->getFps().getIntValue() << ")"
+ << expectedRefreshRates[i].modePtr->getVsyncRate().getIntValue() << ")"
<< " Actual " << refreshRates[i].frameRateMode.fps.getIntValue() << " ("
- << refreshRates[i].frameRateMode.modePtr->getFps().getIntValue() << ")";
+ << refreshRates[i].frameRateMode.modePtr->getVsyncRate().getIntValue() << ")";
}
}
@@ -1434,7 +1459,7 @@
layers[1].frameRateCategory = testCase.frameRateCategory;
}
- EXPECT_EQ(testCase.expectedFrameRate, selector.getBestFrameRateMode(layers)->getFps())
+ EXPECT_EQ(testCase.expectedFrameRate, selector.getBestFrameRateMode(layers)->getPeakFps())
<< "did not get expected frame rate for " << lr.name;
}
}
@@ -1491,7 +1516,7 @@
layers[1].frameRateCategory = testCase.frameRateCategory;
}
- EXPECT_EQ(testCase.expectedFrameRate, selector.getBestFrameRateMode(layers)->getFps())
+ EXPECT_EQ(testCase.expectedFrameRate, selector.getBestFrameRateMode(layers)->getPeakFps())
<< "did not get expected frame rate for " << lr.name;
}
}
@@ -1529,9 +1554,10 @@
ss << "ExplicitDefault " << desired;
lr.name = ss.str();
- const auto bestFps = selector.getBestFrameRateMode(layers)->getFps();
- EXPECT_EQ(expected, bestFps)
- << "expected " << expected << " for " << desired << " but got " << bestFps;
+ const auto bestMode = selector.getBestFrameRateMode(layers);
+ EXPECT_EQ(expected, bestMode->getPeakFps())
+ << "expected " << expected << " for " << desired << " but got "
+ << bestMode->getPeakFps() << "(" << bestMode->getVsyncRate() << ")";
}
}
@@ -1608,7 +1634,7 @@
ss << "ExplicitExact " << desired;
lr.name = ss.str();
- EXPECT_EQ(lr.desiredRefreshRate, selector.getBestFrameRateMode(layers)->getFps());
+ EXPECT_EQ(lr.desiredRefreshRate, selector.getBestFrameRateMode(layers)->getPeakFps());
}
}
}
@@ -1713,9 +1739,9 @@
for (size_t i = 0; i < expectedRanking.size(); ++i) {
EXPECT_EQ(expectedRanking[i], actualRanking[i].frameRateMode)
<< "Expected " << expectedRanking[i].fps.getIntValue() << " ("
- << expectedRanking[i].modePtr->getFps().getIntValue() << ")"
+ << expectedRanking[i].modePtr->getVsyncRate().getIntValue() << ")"
<< " Actual " << actualRanking[i].frameRateMode.fps.getIntValue() << " ("
- << actualRanking[i].frameRateMode.modePtr->getFps().getIntValue() << ")";
+ << actualRanking[i].frameRateMode.modePtr->getVsyncRate().getIntValue() << ")";
}
lr1.vote = LayerVoteType::Max;
@@ -1755,9 +1781,9 @@
for (size_t i = 0; i < expectedRanking.size(); ++i) {
EXPECT_EQ(expectedRanking[i], actualRanking[i].frameRateMode)
<< "Expected " << expectedRanking[i].fps.getIntValue() << " ("
- << expectedRanking[i].modePtr->getFps().getIntValue() << ")"
+ << expectedRanking[i].modePtr->getVsyncRate().getIntValue() << ")"
<< " Actual " << actualRanking[i].frameRateMode.fps.getIntValue() << " ("
- << actualRanking[i].frameRateMode.modePtr->getFps().getIntValue() << ")";
+ << actualRanking[i].frameRateMode.modePtr->getVsyncRate().getIntValue() << ")";
}
lr1.vote = LayerVoteType::Heuristic;
@@ -1795,9 +1821,9 @@
for (size_t i = 0; i < expectedRanking.size(); ++i) {
EXPECT_EQ(expectedRanking[i], actualRanking[i].frameRateMode)
<< "Expected " << expectedRanking[i].fps.getIntValue() << " ("
- << expectedRanking[i].modePtr->getFps().getIntValue() << ")"
+ << expectedRanking[i].modePtr->getVsyncRate().getIntValue() << ")"
<< " Actual " << actualRanking[i].frameRateMode.fps.getIntValue() << " ("
- << actualRanking[i].frameRateMode.modePtr->getFps().getIntValue() << ")";
+ << actualRanking[i].frameRateMode.modePtr->getVsyncRate().getIntValue() << ")";
}
lr1.desiredRefreshRate = 120_Hz;
@@ -1838,9 +1864,9 @@
for (size_t i = 0; i < expectedRanking.size(); ++i) {
EXPECT_EQ(expectedRanking[i], actualRanking[i].frameRateMode)
<< "Expected " << expectedRanking[i].fps.getIntValue() << " ("
- << expectedRanking[i].modePtr->getFps().getIntValue() << ")"
+ << expectedRanking[i].modePtr->getVsyncRate().getIntValue() << ")"
<< " Actual " << actualRanking[i].frameRateMode.fps.getIntValue() << " ("
- << actualRanking[i].frameRateMode.modePtr->getFps().getIntValue() << ")";
+ << actualRanking[i].frameRateMode.modePtr->getVsyncRate().getIntValue() << ")";
}
}
@@ -2485,7 +2511,8 @@
const auto testRefreshRate = [&](Fps fps, LayerVoteType vote) {
layers[0].desiredRefreshRate = fps;
layers[0].vote = vote;
- EXPECT_EQ(fps.getIntValue(), selector.getBestFrameRateMode(layers)->getFps().getIntValue())
+ EXPECT_EQ(fps.getIntValue(),
+ selector.getBestFrameRateMode(layers)->getPeakFps().getIntValue())
<< "Failed for " << ftl::enum_string(vote);
};
@@ -2524,13 +2551,13 @@
},
};
- EXPECT_EQ(53_Hz, selector.getBestFrameRateMode(layers, globalSignals)->getFps());
+ EXPECT_EQ(53_Hz, selector.getBestFrameRateMode(layers, globalSignals)->getPeakFps());
}
TEST_P(RefreshRateSelectorTest, modeComparison) {
- EXPECT_LT(kMode60->getFps(), kMode90->getFps());
- EXPECT_GE(kMode60->getFps(), kMode60->getFps());
- EXPECT_GE(kMode90->getFps(), kMode90->getFps());
+ EXPECT_LT(kMode60->getPeakFps(), kMode90->getPeakFps());
+ EXPECT_GE(kMode60->getPeakFps(), kMode60->getPeakFps());
+ EXPECT_GE(kMode90->getPeakFps(), kMode90->getPeakFps());
}
TEST_P(RefreshRateSelectorTest, testKernelIdleTimerAction) {
@@ -2579,27 +2606,27 @@
auto selector = createSelector(kModes_30_60_72_90_120, kModeId30);
const auto frameRate = 30_Hz;
- Fps displayRefreshRate = selector.getActiveMode().getFps();
+ Fps displayRefreshRate = selector.getActiveMode().getPeakFps();
EXPECT_EQ(1, RefreshRateSelector::getFrameRateDivisor(displayRefreshRate, frameRate));
selector.setActiveMode(kModeId60, 60_Hz);
- displayRefreshRate = selector.getActiveMode().getFps();
+ displayRefreshRate = selector.getActiveMode().getPeakFps();
EXPECT_EQ(2, RefreshRateSelector::getFrameRateDivisor(displayRefreshRate, frameRate));
selector.setActiveMode(kModeId72, 72_Hz);
- displayRefreshRate = selector.getActiveMode().getFps();
+ displayRefreshRate = selector.getActiveMode().getPeakFps();
EXPECT_EQ(0, RefreshRateSelector::getFrameRateDivisor(displayRefreshRate, frameRate));
selector.setActiveMode(kModeId90, 90_Hz);
- displayRefreshRate = selector.getActiveMode().getFps();
+ displayRefreshRate = selector.getActiveMode().getPeakFps();
EXPECT_EQ(3, RefreshRateSelector::getFrameRateDivisor(displayRefreshRate, frameRate));
selector.setActiveMode(kModeId120, 120_Hz);
- displayRefreshRate = selector.getActiveMode().getFps();
+ displayRefreshRate = selector.getActiveMode().getPeakFps();
EXPECT_EQ(4, RefreshRateSelector::getFrameRateDivisor(displayRefreshRate, frameRate));
selector.setActiveMode(kModeId90, 90_Hz);
- displayRefreshRate = selector.getActiveMode().getFps();
+ displayRefreshRate = selector.getActiveMode().getPeakFps();
EXPECT_EQ(4, RefreshRateSelector::getFrameRateDivisor(displayRefreshRate, 22.5_Hz));
EXPECT_EQ(0, RefreshRateSelector::getFrameRateDivisor(24_Hz, 25_Hz));
@@ -3029,7 +3056,7 @@
for (size_t i = 0; i < expected.size(); i++) {
const auto [expectedRenderRate, expectedRefreshRate] = expected[i];
EXPECT_EQ(expectedRenderRate, primaryRefreshRates[i].fps);
- EXPECT_EQ(expectedRefreshRate, primaryRefreshRates[i].modePtr->getFps());
+ EXPECT_EQ(expectedRefreshRate, primaryRefreshRates[i].modePtr->getPeakFps());
}
}
@@ -3175,6 +3202,7 @@
}
// TODO(b/266481656): Once this bug is fixed, we can remove this test
+// And test for VRR when we remove this work around for VRR.
TEST_P(RefreshRateSelectorTest, noLowerFrameRateOnMinVote) {
auto selector = createSelector(kModes_60_90, kModeId60);
@@ -3304,5 +3332,187 @@
EXPECT_FRAME_RATE_MODE(kMode90, 90_Hz, selector.getBestScoredFrameRate(layers).frameRateMode);
}
+// VRR tests
+TEST_P(RefreshRateSelectorTest, singleMinMaxRateForVrr) {
+ if (GetParam() != Config::FrameRateOverride::Enabled || !flags::vrr_config()) {
+ return;
+ }
+
+ auto selector = createSelector(kVrrMode_120, kModeId120);
+ EXPECT_TRUE(selector.supportsFrameRateOverride());
+
+ const auto minRate = selector.getMinSupportedRefreshRate();
+ const auto performanceRate = selector.getMaxSupportedRefreshRate();
+ const auto minRateByPolicy = selector.getMinRefreshRateByPolicy();
+ const auto performanceRateByPolicy = selector.getMaxRefreshRateByPolicy();
+
+ EXPECT_EQ(kVrrMode120TE240, minRate);
+ EXPECT_EQ(kVrrMode120TE240, performanceRate);
+ EXPECT_EQ(kVrrMode120TE240, minRateByPolicy);
+ EXPECT_EQ(kVrrMode120TE240, performanceRateByPolicy);
+}
+
+TEST_P(RefreshRateSelectorTest, renderRateChangesWithPolicyChangeForVrr) {
+ if (GetParam() != Config::FrameRateOverride::Enabled || !flags::vrr_config()) {
+ return;
+ }
+
+ auto selector = createSelector(kVrrModes_60_120, kModeId120);
+
+ const FpsRange only120 = {120_Hz, 120_Hz};
+ EXPECT_EQ(SetPolicyResult::Changed,
+ selector.setDisplayManagerPolicy(
+ {kModeId120, {only120, only120}, {only120, only120}}));
+ EXPECT_FRAME_RATE_MODE(kVrrMode120TE240, 120_Hz,
+ selector.getBestScoredFrameRate({}).frameRateMode);
+
+ const FpsRange range120 = {0_Hz, 120_Hz};
+ EXPECT_EQ(SetPolicyResult::Changed,
+ selector.setDisplayManagerPolicy(
+ {kModeId120, {only120, range120}, {only120, range120}}));
+ EXPECT_FRAME_RATE_MODE(kVrrMode120TE240, 120_Hz,
+ selector.getBestScoredFrameRate({}).frameRateMode);
+
+ const FpsRange range90 = {0_Hz, 90_Hz};
+ EXPECT_EQ(SetPolicyResult::Changed,
+ selector.setDisplayManagerPolicy(
+ {kModeId120, {only120, range90}, {only120, range90}}));
+ EXPECT_FRAME_RATE_MODE(kVrrMode120TE240, 80_Hz,
+ selector.getBestScoredFrameRate({}).frameRateMode);
+
+ const FpsRange range80 = {0_Hz, 80_Hz};
+ EXPECT_EQ(SetPolicyResult::Changed,
+ selector.setDisplayManagerPolicy(
+ {kModeId120, {only120, range80}, {only120, range80}}));
+ EXPECT_FRAME_RATE_MODE(kVrrMode120TE240, 80_Hz,
+ selector.getBestScoredFrameRate({}).frameRateMode);
+
+ const FpsRange range60 = {0_Hz, 60_Hz};
+ EXPECT_EQ(SetPolicyResult::Changed,
+ selector.setDisplayManagerPolicy(
+ {kModeId120, {only120, range60}, {only120, range60}}));
+ EXPECT_FRAME_RATE_MODE(kVrrMode120TE240, 60_Hz,
+ selector.getBestScoredFrameRate({}).frameRateMode);
+
+ const FpsRange range48 = {0_Hz, 48_Hz};
+ EXPECT_EQ(SetPolicyResult::Changed,
+ selector.setDisplayManagerPolicy(
+ {kModeId120, {only120, range48}, {only120, range48}}));
+ EXPECT_FRAME_RATE_MODE(kVrrMode120TE240, 48_Hz,
+ selector.getBestScoredFrameRate({}).frameRateMode);
+
+ const FpsRange range30 = {0_Hz, 30_Hz};
+ EXPECT_EQ(SetPolicyResult::Changed,
+ selector.setDisplayManagerPolicy(
+ {kModeId120, {only120, range30}, {only120, range30}}));
+ EXPECT_FRAME_RATE_MODE(kVrrMode120TE240, 30_Hz,
+ selector.getBestScoredFrameRate({}).frameRateMode);
+}
+
+TEST_P(RefreshRateSelectorTest, modeChangesWithPolicyChangeForVrr) {
+ if (GetParam() != Config::FrameRateOverride::Enabled || !flags::vrr_config()) {
+ return;
+ }
+
+ auto selector = createSelector(kVrrModes_60_120, kModeId120);
+
+ const FpsRange range120 = {0_Hz, 120_Hz};
+ const FpsRange range60 = {0_Hz, 60_Hz};
+
+ EXPECT_EQ(SetPolicyResult::Changed,
+ selector.setDisplayManagerPolicy(
+ {kModeId120, {range120, range60}, {range120, range60}}));
+ EXPECT_FRAME_RATE_MODE(kVrrMode120TE240, 60_Hz,
+ selector.getBestScoredFrameRate({}).frameRateMode);
+
+ EXPECT_EQ(SetPolicyResult::Changed,
+ selector.setDisplayManagerPolicy(
+ {kModeId60, {range60, range60}, {range60, range60}}));
+ EXPECT_FRAME_RATE_MODE(kVrrMode60TE120, 60_Hz,
+ selector.getBestScoredFrameRate({}).frameRateMode);
+}
+
+TEST_P(RefreshRateSelectorTest, getFrameRateOverridesForVrr) {
+ if (GetParam() != Config::FrameRateOverride::Enabled || !flags::vrr_config()) {
+ return;
+ }
+
+ auto selector = createSelector(kVrrMode_120, kModeId120);
+ // TODO(b/297600226) Run at lower than 30 Fps for dVRR
+ const std::vector<Fps> desiredRefreshRates = {30_Hz, 34.285_Hz, 40_Hz, 48_Hz,
+ 60_Hz, 80_Hz, 120_Hz};
+ const std::vector<LayerVoteType> layerVotes = {LayerVoteType::ExplicitDefault,
+ LayerVoteType::ExplicitExactOrMultiple,
+ LayerVoteType::ExplicitExact};
+
+ std::vector<LayerRequirement> layers = {{.weight = 1.f}};
+ layers[0].name = "Test layer";
+ layers[0].ownerUid = 1234;
+
+ for (auto desiredRefreshRate : desiredRefreshRates) {
+ layers[0].desiredRefreshRate = desiredRefreshRate;
+ for (auto vote : layerVotes) {
+ layers[0].vote = vote;
+ auto frameRateOverrides = selector.getFrameRateOverrides(layers, 240_Hz, {});
+ EXPECT_EQ(1u, frameRateOverrides.size());
+ ASSERT_EQ(1u, frameRateOverrides.count(1234));
+ EXPECT_EQ(desiredRefreshRate, frameRateOverrides.at(1234));
+ }
+ }
+}
+
+TEST_P(RefreshRateSelectorTest, renderFrameRatesForVrr) {
+ if (GetParam() != Config::FrameRateOverride::Enabled || !flags::vrr_config()) {
+ return;
+ }
+
+ auto selector = createSelector(kVrrMode_120, kModeId120);
+ const FpsRange only120 = {120_Hz, 120_Hz};
+ const FpsRange range120 = {0_Hz, 120_Hz};
+
+ EXPECT_EQ(SetPolicyResult::Changed,
+ selector.setDisplayManagerPolicy(
+ {kModeId120, {only120, range120}, {only120, range120}}));
+
+ std::vector<Fps> expected = {20_Hz, 21.818_Hz, 24_Hz, 26.666_Hz, 30_Hz, 34.285_Hz,
+ 40_Hz, 48_Hz, 60_Hz, 80_Hz, 120_Hz};
+
+ auto primaryRefreshRates = selector.getPrimaryFrameRates();
+ ASSERT_EQ(expected.size(), primaryRefreshRates.size());
+
+ for (size_t i = 0; i < expected.size(); i++) {
+ EXPECT_EQ(expected[i], primaryRefreshRates[i].fps);
+ EXPECT_EQ(120_Hz, primaryRefreshRates[i].modePtr->getPeakFps());
+ }
+
+ // Render range (0,90)
+ const FpsRange range90 = {0_Hz, 90_Hz};
+ EXPECT_EQ(SetPolicyResult::Changed,
+ selector.setDisplayManagerPolicy(
+ {kModeId120, {range120, range90}, {range120, range90}}));
+
+ expected = {20_Hz, 21.818_Hz, 24_Hz, 26.666_Hz, 30_Hz, 34.285_Hz, 40_Hz, 48_Hz, 60_Hz, 80_Hz};
+
+ primaryRefreshRates = selector.getPrimaryFrameRates();
+ ASSERT_EQ(expected.size(), primaryRefreshRates.size());
+ for (size_t i = 0; i < expected.size(); i++) {
+ EXPECT_EQ(expected[i], primaryRefreshRates[i].fps);
+ EXPECT_EQ(120_Hz, primaryRefreshRates[i].modePtr->getPeakFps());
+ }
+
+ // Render range (0,60)
+ const FpsRange range60 = {0_Hz, 60_Hz};
+ EXPECT_EQ(SetPolicyResult::Changed,
+ selector.setDisplayManagerPolicy(
+ {kModeId120, {range120, range60}, {range120, range60}}));
+ expected = {20_Hz, 21.818_Hz, 24_Hz, 26.666_Hz, 30_Hz, 34.285_Hz, 40_Hz, 48_Hz, 60_Hz};
+
+ primaryRefreshRates = selector.getPrimaryFrameRates();
+ ASSERT_EQ(expected.size(), primaryRefreshRates.size());
+ for (size_t i = 0; i < expected.size(); i++) {
+ EXPECT_EQ(expected[i], primaryRefreshRates[i].fps);
+ EXPECT_EQ(120_Hz, primaryRefreshRates[i].modePtr->getPeakFps());
+ }
+}
} // namespace
} // namespace android::scheduler
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index 8458aa3..908c9ab 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -997,7 +997,7 @@
const auto activeMode = modes.get(activeModeId);
LOG_ALWAYS_FATAL_IF(!activeMode);
- const auto fps = activeMode->get()->getFps();
+ const auto fps = activeMode->get()->getPeakFps();
state.physical = {.id = physicalId,
.hwcDisplayId = *mHwcDisplayId,
diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockDisplayMode.h b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockDisplayMode.h
index 3b36361..cb05c00 100644
--- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockDisplayMode.h
+++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockDisplayMode.h
@@ -20,17 +20,23 @@
namespace android::mock {
-inline DisplayModePtr createDisplayMode(
- DisplayModeId modeId, Fps refreshRate, int32_t group = 0,
+inline DisplayMode::Builder createDisplayModeBuilder(
+ DisplayModeId modeId, Fps displayRefreshRate, int32_t group = 0,
ui::Size resolution = ui::Size(1920, 1080),
PhysicalDisplayId displayId = PhysicalDisplayId::fromPort(0)) {
return DisplayMode::Builder(hal::HWConfigId(modeId.value()))
.setId(modeId)
.setPhysicalDisplayId(displayId)
- .setVsyncPeriod(refreshRate.getPeriodNsecs())
+ .setVsyncPeriod(displayRefreshRate.getPeriodNsecs())
.setGroup(group)
- .setResolution(resolution)
- .build();
+ .setResolution(resolution);
+}
+
+inline DisplayModePtr createDisplayMode(
+ DisplayModeId modeId, Fps refreshRate, int32_t group = 0,
+ ui::Size resolution = ui::Size(1920, 1080),
+ PhysicalDisplayId displayId = PhysicalDisplayId::fromPort(0)) {
+ return createDisplayModeBuilder(modeId, refreshRate, group, resolution, displayId).build();
}
inline DisplayModePtr createDisplayMode(PhysicalDisplayId displayId, DisplayModeId modeId,
@@ -38,11 +44,19 @@
return createDisplayMode(modeId, refreshRate, {}, {}, displayId);
}
+inline DisplayModePtr createVrrDisplayMode(
+ DisplayModeId modeId, Fps displayRefreshRate, hal::VrrConfig vrrConfig, int32_t group = 0,
+ ui::Size resolution = ui::Size(1920, 1080),
+ PhysicalDisplayId displayId = PhysicalDisplayId::fromPort(0)) {
+ return createDisplayModeBuilder(modeId, displayRefreshRate, group, resolution, displayId)
+ .setVrrConfig(std::move(vrrConfig))
+ .build();
+}
inline DisplayModePtr cloneForDisplay(PhysicalDisplayId displayId, const DisplayModePtr& modePtr) {
return DisplayMode::Builder(modePtr->getHwcId())
.setId(modePtr->getId())
.setPhysicalDisplayId(displayId)
- .setVsyncPeriod(modePtr->getVsyncPeriod())
+ .setVsyncPeriod(modePtr->getVsyncRate().getPeriodNsecs())
.setGroup(modePtr->getGroup())
.setResolution(modePtr->getResolution())
.build();
diff --git a/services/surfaceflinger/tests/unittests/mock/MockFrameRateMode.h b/services/surfaceflinger/tests/unittests/mock/MockFrameRateMode.h
index 4cfdd58..bfcdd9b 100644
--- a/services/surfaceflinger/tests/unittests/mock/MockFrameRateMode.h
+++ b/services/surfaceflinger/tests/unittests/mock/MockFrameRateMode.h
@@ -19,7 +19,7 @@
#include <scheduler/FrameRateMode.h>
// Use a C style macro to keep the line numbers printed in gtest
-#define EXPECT_FRAME_RATE_MODE(_modePtr, _fps, _mode) \
- EXPECT_EQ((scheduler::FrameRateMode{(_fps), (_modePtr)}), (_mode)) \
- << "Expected " << (_fps) << " (" << (_modePtr)->getFps() << ") but was " \
- << (_mode).fps << " (" << (_mode).modePtr->getFps() << ")"
+#define EXPECT_FRAME_RATE_MODE(_modePtr, _fps, _mode) \
+ EXPECT_EQ((scheduler::FrameRateMode{(_fps), (_modePtr)}), (_mode)) \
+ << "Expected " << (_fps) << " (" << (_modePtr)->getVsyncRate() << ") but was " \
+ << (_mode).fps << " (" << (_mode).modePtr->getVsyncRate() << ")"