SF: Break dependency between VsyncConfiguration and RefreshRateConfigs
The VsyncConfiguration class doesn't need to know the list of
supported refresh rates, because the offsets can be calculated
and cached on the fly. This is better because the list of refresh
rates can change during runtime (for example for Android TV).
After fixing this the dependency on RefreshRateConfigs is only needed
for getting the current refresh rate at construction time. For
this it's sufficient to pass only the Fps instead of the whole
RefreshRateConfigs object.
Bug: 159590486
Test: presubmit
Change-Id: I1c0ceaf2524b517e85c8067577fc9f5146f1f632
diff --git a/services/surfaceflinger/Scheduler/VsyncConfiguration.cpp b/services/surfaceflinger/Scheduler/VsyncConfiguration.cpp
index 8431323..cb57aea 100644
--- a/services/surfaceflinger/Scheduler/VsyncConfiguration.cpp
+++ b/services/surfaceflinger/Scheduler/VsyncConfiguration.cpp
@@ -16,14 +16,19 @@
#include "VsyncConfiguration.h"
-#include <cutils/properties.h>
-
+#include <chrono>
+#include <cinttypes>
#include <optional>
+#include <cutils/properties.h>
+#include <log/log.h>
+
#include "SurfaceFlingerProperties.h"
namespace {
+using namespace std::chrono_literals;
+
std::optional<nsecs_t> getProperty(const char* name) {
char value[PROPERTY_VALUE_MAX];
property_get(name, value, "-1");
@@ -31,19 +36,6 @@
return std::nullopt;
}
-std::vector<android::Fps> getRefreshRatesFromConfigs(
- const android::scheduler::RefreshRateConfigs& refreshRateConfigs) {
- const auto& allRefreshRates = refreshRateConfigs.getAllRefreshRates();
- std::vector<android::Fps> refreshRates;
- refreshRates.reserve(allRefreshRates.size());
-
- for (const auto& [ignored, refreshRate] : allRefreshRates) {
- refreshRates.emplace_back(refreshRate->getFps());
- }
-
- return refreshRates;
-}
-
} // namespace
namespace android::scheduler::impl {
@@ -51,25 +43,19 @@
VsyncConfiguration::VsyncConfiguration(Fps currentFps) : mRefreshRateFps(currentFps) {}
PhaseOffsets::VsyncConfigSet VsyncConfiguration::getConfigsForRefreshRate(Fps fps) const {
- const auto iter = std::find_if(mOffsets.begin(), mOffsets.end(),
- [&fps](const std::pair<Fps, VsyncConfigSet>& candidateFps) {
- return fps.equalsWithMargin(candidateFps.first);
- });
+ std::lock_guard lock(mLock);
+ return getConfigsForRefreshRateLocked(fps);
+}
- if (iter != mOffsets.end()) {
+PhaseOffsets::VsyncConfigSet VsyncConfiguration::getConfigsForRefreshRateLocked(Fps fps) const {
+ const auto iter = mOffsetsCache.find(fps);
+ if (iter != mOffsetsCache.end()) {
return iter->second;
}
- // 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 %s", to_string(fps).c_str());
- return constructOffsets(fps.getPeriodNsecs());
-}
-
-void VsyncConfiguration::initializeOffsets(const std::vector<Fps>& refreshRates) {
- for (const auto fps : refreshRates) {
- mOffsets.emplace(fps, constructOffsets(fps.getPeriodNsecs()));
- }
+ const auto offset = constructOffsets(fps.getPeriodNsecs());
+ mOffsetsCache[fps] = offset;
+ return offset;
}
void VsyncConfiguration::dump(std::string& result) const {
@@ -98,10 +84,8 @@
earlyGpu.appWorkDuration.count(), earlyGpu.sfWorkDuration.count());
}
-PhaseOffsets::PhaseOffsets(const scheduler::RefreshRateConfigs& refreshRateConfigs)
- : PhaseOffsets(getRefreshRatesFromConfigs(refreshRateConfigs),
- refreshRateConfigs.getCurrentRefreshRate().getFps(),
- sysprop::vsync_event_phase_offset_ns(1000000),
+PhaseOffsets::PhaseOffsets(Fps currentRefreshRate)
+ : PhaseOffsets(currentRefreshRate, sysprop::vsync_event_phase_offset_ns(1000000),
sysprop::vsync_sf_event_phase_offset_ns(1000000),
getProperty("debug.sf.early_phase_offset_ns"),
getProperty("debug.sf.early_gl_phase_offset_ns"),
@@ -121,15 +105,17 @@
getProperty("debug.sf.phase_offset_threshold_for_next_vsync_ns")
.value_or(std::numeric_limits<nsecs_t>::max())) {}
-PhaseOffsets::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,
- std::optional<nsecs_t> highFpsEarlyAppOffsetNs,
- std::optional<nsecs_t> highFpsEarlyGpuAppOffsetNs, nsecs_t thresholdForNextVsync)
+PhaseOffsets::PhaseOffsets(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,
+ std::optional<nsecs_t> highFpsEarlyAppOffsetNs,
+ std::optional<nsecs_t> highFpsEarlyGpuAppOffsetNs,
+ nsecs_t thresholdForNextVsync)
: VsyncConfiguration(currentFps),
mVSyncPhaseOffsetNs(vsyncPhaseOffsetNs),
mSfVSyncPhaseOffsetNs(sfVSyncPhaseOffsetNs),
@@ -143,9 +129,7 @@
mHighFpsEarlyGpuSfOffsetNs(highFpsEarlyGpuSfOffsetNs),
mHighFpsEarlyAppOffsetNs(highFpsEarlyAppOffsetNs),
mHighFpsEarlyGpuAppOffsetNs(highFpsEarlyGpuAppOffsetNs),
- mThresholdForNextVsync(thresholdForNextVsync) {
- initializeOffsets(refreshRates);
-}
+ mThresholdForNextVsync(thresholdForNextVsync) {}
PhaseOffsets::VsyncConfigSet PhaseOffsets::constructOffsets(nsecs_t vsyncDuration) const {
if (vsyncDuration < std::chrono::nanoseconds(15ms).count()) {
@@ -361,10 +345,8 @@
};
}
-WorkDuration::WorkDuration(const scheduler::RefreshRateConfigs& refreshRateConfigs)
- : WorkDuration(getRefreshRatesFromConfigs(refreshRateConfigs),
- refreshRateConfigs.getCurrentRefreshRate().getFps(),
- getProperty("debug.sf.late.sf.duration").value_or(-1),
+WorkDuration::WorkDuration(Fps currentRefreshRate)
+ : WorkDuration(currentRefreshRate, getProperty("debug.sf.late.sf.duration").value_or(-1),
getProperty("debug.sf.late.app.duration").value_or(-1),
getProperty("debug.sf.early.sf.duration").value_or(mSfDuration),
getProperty("debug.sf.early.app.duration").value_or(mAppDuration),
@@ -373,17 +355,15 @@
validateSysprops();
}
-WorkDuration::WorkDuration(const std::vector<Fps>& refreshRates, Fps currentFps, nsecs_t sfDuration,
- nsecs_t appDuration, nsecs_t sfEarlyDuration, nsecs_t appEarlyDuration,
+WorkDuration::WorkDuration(Fps currentRefreshRate, nsecs_t sfDuration, nsecs_t appDuration,
+ nsecs_t sfEarlyDuration, nsecs_t appEarlyDuration,
nsecs_t sfEarlyGpuDuration, nsecs_t appEarlyGpuDuration)
- : VsyncConfiguration(currentFps),
+ : VsyncConfiguration(currentRefreshRate),
mSfDuration(sfDuration),
mAppDuration(appDuration),
mSfEarlyDuration(sfEarlyDuration),
mAppEarlyDuration(appEarlyDuration),
mSfEarlyGpuDuration(sfEarlyGpuDuration),
- mAppEarlyGpuDuration(appEarlyGpuDuration) {
- initializeOffsets(refreshRates);
-}
+ mAppEarlyGpuDuration(appEarlyGpuDuration) {}
} // namespace android::scheduler::impl