SF: move RefreshRateConfigs to DisplayDevice
Move RefreshRateConfigs to DisplayDevice to be able to maintain
a per-display refresh rate switching policy.
Test: SF unit tests
Test: refresh rate switching is working on device with
more than one display
Bug: 187539899
Change-Id: Ica6a955e8ad0e563a0740f6579b61fc592eb982c
diff --git a/services/surfaceflinger/Scheduler/LayerHistory.cpp b/services/surfaceflinger/Scheduler/LayerHistory.cpp
index 0563795..84e3548 100644
--- a/services/surfaceflinger/Scheduler/LayerHistory.cpp
+++ b/services/surfaceflinger/Scheduler/LayerHistory.cpp
@@ -75,10 +75,9 @@
}
} // namespace
-LayerHistory::LayerHistory(const RefreshRateConfigs& refreshRateConfigs)
+LayerHistory::LayerHistory()
: mTraceEnabled(traceEnabled()), mUseFrameRatePriority(useFrameRatePriority()) {
LayerInfo::setTraceEnabled(mTraceEnabled);
- LayerInfo::setRefreshRateConfigs(refreshRateConfigs);
}
LayerHistory::~LayerHistory() = default;
@@ -138,7 +137,8 @@
}
}
-LayerHistory::Summary LayerHistory::summarize(nsecs_t now) {
+LayerHistory::Summary LayerHistory::summarize(const RefreshRateConfigs& refreshRateConfigs,
+ nsecs_t now) {
LayerHistory::Summary summary;
std::lock_guard lock(mLock);
@@ -151,7 +151,7 @@
ALOGV("%s has priority: %d %s focused", info->getName().c_str(), frameRateSelectionPriority,
layerFocused ? "" : "not");
- const auto vote = info->getRefreshRateVote(now);
+ const auto vote = info->getRefreshRateVote(refreshRateConfigs, now);
// Skip NoVote layer as those don't have any requirements
if (vote.type == LayerHistory::LayerVoteType::NoVote) {
continue;
diff --git a/services/surfaceflinger/Scheduler/LayerHistory.h b/services/surfaceflinger/Scheduler/LayerHistory.h
index 82f6c39..92236f5 100644
--- a/services/surfaceflinger/Scheduler/LayerHistory.h
+++ b/services/surfaceflinger/Scheduler/LayerHistory.h
@@ -42,7 +42,7 @@
public:
using LayerVoteType = RefreshRateConfigs::LayerVoteType;
- LayerHistory(const RefreshRateConfigs&);
+ LayerHistory();
~LayerHistory();
// Layers are unregistered when the weak reference expires.
@@ -67,7 +67,7 @@
using Summary = std::vector<RefreshRateConfigs::LayerRequirement>;
// Rebuilds sets of active/inactive layers, and accumulates stats for active layers.
- Summary summarize(nsecs_t now);
+ Summary summarize(const RefreshRateConfigs&, nsecs_t now);
void clear();
diff --git a/services/surfaceflinger/Scheduler/LayerInfo.cpp b/services/surfaceflinger/Scheduler/LayerInfo.cpp
index 989bf4e..8a45b66 100644
--- a/services/surfaceflinger/Scheduler/LayerInfo.cpp
+++ b/services/surfaceflinger/Scheduler/LayerInfo.cpp
@@ -34,7 +34,6 @@
namespace android::scheduler {
-const RefreshRateConfigs* LayerInfo::sRefreshRateConfigs = nullptr;
bool LayerInfo::sTraceEnabled = false;
LayerInfo::LayerInfo(const std::string& name, uid_t ownerUid,
@@ -184,7 +183,8 @@
return static_cast<nsecs_t>(averageFrameTime);
}
-std::optional<Fps> LayerInfo::calculateRefreshRateIfPossible(nsecs_t now) {
+std::optional<Fps> LayerInfo::calculateRefreshRateIfPossible(
+ const RefreshRateConfigs& refreshRateConfigs, nsecs_t now) {
static constexpr float MARGIN = 1.0f; // 1Hz
if (!hasEnoughDataForHeuristic()) {
ALOGV("Not enough data");
@@ -196,9 +196,7 @@
const auto refreshRate = Fps::fromPeriodNsecs(*averageFrameTime);
const bool refreshRateConsistent = mRefreshRateHistory.add(refreshRate, now);
if (refreshRateConsistent) {
- const auto knownRefreshRate =
- sRefreshRateConfigs->findClosestKnownFrameRate(refreshRate);
-
+ const auto knownRefreshRate = refreshRateConfigs.findClosestKnownFrameRate(refreshRate);
// To avoid oscillation, use the last calculated refresh rate if it is
// close enough
if (std::abs(mLastRefreshRate.calculated.getValue() - refreshRate.getValue()) >
@@ -220,7 +218,8 @@
: std::nullopt;
}
-LayerInfo::LayerVote LayerInfo::getRefreshRateVote(nsecs_t now) {
+LayerInfo::LayerVote LayerInfo::getRefreshRateVote(const RefreshRateConfigs& refreshRateConfigs,
+ nsecs_t now) {
if (mLayerVote.type != LayerHistory::LayerVoteType::Heuristic) {
ALOGV("%s voted %d ", mName.c_str(), static_cast<int>(mLayerVote.type));
return mLayerVote;
@@ -247,7 +246,7 @@
clearHistory(now);
}
- auto refreshRate = calculateRefreshRateIfPossible(now);
+ auto refreshRate = calculateRefreshRateIfPossible(refreshRateConfigs, now);
if (refreshRate.has_value()) {
ALOGV("%s calculated refresh rate: %s", mName.c_str(), to_string(*refreshRate).c_str());
return {LayerHistory::LayerVoteType::Heuristic, refreshRate.value()};
diff --git a/services/surfaceflinger/Scheduler/LayerInfo.h b/services/surfaceflinger/Scheduler/LayerInfo.h
index 34cc389..ce9783c 100644
--- a/services/surfaceflinger/Scheduler/LayerInfo.h
+++ b/services/surfaceflinger/Scheduler/LayerInfo.h
@@ -122,10 +122,6 @@
static void setTraceEnabled(bool enabled) { sTraceEnabled = enabled; }
- static void setRefreshRateConfigs(const RefreshRateConfigs& refreshRateConfigs) {
- sRefreshRateConfigs = &refreshRateConfigs;
- }
-
LayerInfo(const std::string& name, uid_t ownerUid, LayerHistory::LayerVoteType defaultVote);
LayerInfo(const LayerInfo&) = delete;
@@ -161,7 +157,7 @@
uid_t getOwnerUid() const { return mOwnerUid; }
- LayerVote getRefreshRateVote(nsecs_t now);
+ LayerVote getRefreshRateVote(const RefreshRateConfigs&, nsecs_t now);
// Return the last updated time. If the present time is farther in the future than the
// updated time, the updated time is the present time.
@@ -263,7 +259,7 @@
bool isFrequent(nsecs_t now) const;
bool isAnimating(nsecs_t now) const;
bool hasEnoughDataForHeuristic() const;
- std::optional<Fps> calculateRefreshRateIfPossible(nsecs_t now);
+ std::optional<Fps> calculateRefreshRateIfPossible(const RefreshRateConfigs&, nsecs_t now);
std::optional<nsecs_t> calculateAverageFrameTime() const;
bool isFrameTimeValid(const FrameTimeData&) const;
@@ -300,7 +296,6 @@
mutable std::unordered_map<LayerHistory::LayerVoteType, std::string> mTraceTags;
// Shared for all LayerInfo instances
- static const RefreshRateConfigs* sRefreshRateConfigs;
static bool sTraceEnabled;
};
diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
index dfd1395..884862d 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
+++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
@@ -316,8 +316,6 @@
Config config = {.enableFrameRateOverride = false,
.frameRateMultipleThreshold = 0});
- void updateDisplayModes(const DisplayModes& mode, DisplayModeId currentModeId) EXCLUDES(mLock);
-
// Returns whether switching modes (refresh rate or resolution) is possible.
// TODO(b/158780872): Consider HAL support, and skip frame rate detection if the modes only
// differ in resolution.
@@ -354,6 +352,9 @@
void dump(std::string& result) const EXCLUDES(mLock);
+ RefreshRateConfigs(const RefreshRateConfigs&) = delete;
+ void operator=(const RefreshRateConfigs&) = delete;
+
private:
friend class RefreshRateConfigsTest;
@@ -405,6 +406,8 @@
float calculateLayerScoreLocked(const LayerRequirement&, const RefreshRate&,
bool isSeamlessSwitch) const REQUIRES(mLock);
+ void updateDisplayModes(const DisplayModes& mode, DisplayModeId currentModeId) EXCLUDES(mLock);
+
// The list of refresh rates, indexed by display modes ID. This may change after this
// object is initialized.
AllRefreshRatesMapType mRefreshRates GUARDED_BY(mLock);
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index 384e4e9..861f3ac 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -117,16 +117,17 @@
}
};
-Scheduler::Scheduler(const scheduler::RefreshRateConfigs& configs, ISchedulerCallback& callback)
+Scheduler::Scheduler(const std::shared_ptr<scheduler::RefreshRateConfigs>& configs,
+ ISchedulerCallback& callback)
: Scheduler(configs, callback,
{.supportKernelTimer = sysprop::support_kernel_idle_timer(false),
.useContentDetection = sysprop::use_content_detection_for_refresh_rate(false)}) {
}
-Scheduler::Scheduler(const scheduler::RefreshRateConfigs& configs, ISchedulerCallback& callback,
- Options options)
+Scheduler::Scheduler(const std::shared_ptr<scheduler::RefreshRateConfigs>& configs,
+ ISchedulerCallback& callback, Options options)
: Scheduler(createVsyncSchedule(options.supportKernelTimer), configs, callback,
- createLayerHistory(configs), options) {
+ createLayerHistory(), options) {
using namespace sysprop;
const int setIdleTimerMs = base::GetIntProperty("debug.sf.set_idle_timer_ms"s, 0);
@@ -159,7 +160,8 @@
}
}
-Scheduler::Scheduler(VsyncSchedule schedule, const scheduler::RefreshRateConfigs& configs,
+Scheduler::Scheduler(VsyncSchedule schedule,
+ const std::shared_ptr<scheduler::RefreshRateConfigs>& configs,
ISchedulerCallback& schedulerCallback,
std::unique_ptr<LayerHistory> layerHistory, Options options)
: mOptions(options),
@@ -194,9 +196,8 @@
return {std::move(controller), std::move(tracker), std::move(dispatch)};
}
-std::unique_ptr<LayerHistory> Scheduler::createLayerHistory(
- const scheduler::RefreshRateConfigs& configs) {
- return std::make_unique<scheduler::LayerHistory>(configs);
+std::unique_ptr<LayerHistory> Scheduler::createLayerHistory() {
+ return std::make_unique<scheduler::LayerHistory>();
}
std::unique_ptr<VSyncSource> Scheduler::makePrimaryDispSyncSource(
@@ -207,11 +208,14 @@
}
std::optional<Fps> Scheduler::getFrameRateOverride(uid_t uid) const {
- if (!mRefreshRateConfigs.supportsFrameRateOverride()) {
- return std::nullopt;
+ {
+ std::scoped_lock lock(mRefreshRateConfigsLock);
+ if (!mRefreshRateConfigs->supportsFrameRateOverride()) {
+ return std::nullopt;
+ }
}
- std::lock_guard lock(mFrameRateOverridesMutex);
+ std::lock_guard lock(mFrameRateOverridesLock);
{
const auto iter = mFrameRateOverridesFromBackdoor.find(uid);
if (iter != mFrameRateOverridesFromBackdoor.end()) {
@@ -239,7 +243,8 @@
}
impl::EventThread::ThrottleVsyncCallback Scheduler::makeThrottleVsyncCallback() const {
- if (!mRefreshRateConfigs.supportsFrameRateOverride()) {
+ std::scoped_lock lock(mRefreshRateConfigsLock);
+ if (!mRefreshRateConfigs->supportsFrameRateOverride()) {
return {};
}
@@ -250,14 +255,18 @@
impl::EventThread::GetVsyncPeriodFunction Scheduler::makeGetVsyncPeriodFunction() const {
return [this](uid_t uid) {
- nsecs_t basePeriod = mRefreshRateConfigs.getCurrentRefreshRate().getVsyncPeriod();
+ const auto refreshRateConfigs = holdRefreshRateConfigs();
+ nsecs_t basePeriod = refreshRateConfigs->getCurrentRefreshRate().getVsyncPeriod();
const auto frameRate = getFrameRateOverride(uid);
if (!frameRate.has_value()) {
return basePeriod;
}
- const auto divider = scheduler::RefreshRateConfigs::getFrameRateDivider(
- mRefreshRateConfigs.getCurrentRefreshRate().getFps(), *frameRate);
+ const auto divider =
+ scheduler::RefreshRateConfigs::getFrameRateDivider(refreshRateConfigs
+ ->getCurrentRefreshRate()
+ .getFps(),
+ *frameRate);
if (divider <= 1) {
return basePeriod;
}
@@ -343,7 +352,7 @@
void Scheduler::onFrameRateOverridesChanged(ConnectionHandle handle, PhysicalDisplayId displayId) {
std::vector<FrameRateOverride> overrides;
{
- std::lock_guard lock(mFrameRateOverridesMutex);
+ std::lock_guard lock(mFrameRateOverridesLock);
for (const auto& [uid, frameRate] : mFrameRateOverridesFromBackdoor) {
overrides.emplace_back(FrameRateOverride{uid, frameRate.getValue()});
}
@@ -388,7 +397,10 @@
}
const auto modeId = *mFeatures.modeId;
- const auto vsyncPeriod = mRefreshRateConfigs.getRefreshRateFromModeId(modeId).getVsyncPeriod();
+ const auto vsyncPeriod = [&] {
+ std::scoped_lock lock(mRefreshRateConfigsLock);
+ return mRefreshRateConfigs->getRefreshRateFromModeId(modeId).getVsyncPeriod();
+ }();
// If there is no change from cached mode, there is no need to dispatch an event
if (modeId == mFeatures.cachedModeChangedParams->modeId &&
@@ -532,7 +544,11 @@
const nsecs_t last = mLastResyncTime.exchange(now);
if (now - last > kIgnoreDelay) {
- resyncToHardwareVsync(false, mRefreshRateConfigs.getCurrentRefreshRate().getVsyncPeriod());
+ const auto vsyncPeriod = [&] {
+ std::scoped_lock lock(mRefreshRateConfigsLock);
+ return mRefreshRateConfigs->getCurrentRefreshRate().getVsyncPeriod();
+ }();
+ resyncToHardwareVsync(false, vsyncPeriod);
}
}
@@ -602,9 +618,12 @@
void Scheduler::recordLayerHistory(Layer* layer, nsecs_t presentTime,
LayerHistory::LayerUpdateType updateType) {
- if (mRefreshRateConfigs.canSwitch()) {
- mLayerHistory->record(layer, presentTime, systemTime(), updateType);
+ {
+ std::scoped_lock lock(mRefreshRateConfigsLock);
+ if (!mRefreshRateConfigs->canSwitch()) return;
}
+
+ mLayerHistory->record(layer, presentTime, systemTime(), updateType);
}
void Scheduler::setModeChangePending(bool pending) {
@@ -612,11 +631,16 @@
}
void Scheduler::chooseRefreshRateForContent() {
- if (!mRefreshRateConfigs.canSwitch()) return;
+ {
+ std::scoped_lock lock(mRefreshRateConfigsLock);
+ if (!mRefreshRateConfigs->canSwitch()) return;
+ }
ATRACE_CALL();
- scheduler::LayerHistory::Summary summary = mLayerHistory->summarize(systemTime());
+ const auto refreshRateConfigs = holdRefreshRateConfigs();
+ scheduler::LayerHistory::Summary summary =
+ mLayerHistory->summarize(*refreshRateConfigs, systemTime());
scheduler::RefreshRateConfigs::GlobalSignals consideredSignals;
DisplayModeId newModeId;
bool frameRateChanged;
@@ -626,7 +650,7 @@
mFeatures.contentRequirements = summary;
newModeId = calculateRefreshRateModeId(&consideredSignals);
- auto newRefreshRate = mRefreshRateConfigs.getRefreshRateFromModeId(newModeId);
+ auto newRefreshRate = refreshRateConfigs->getRefreshRateFromModeId(newModeId);
frameRateOverridesChanged =
updateFrameRateOverrides(consideredSignals, newRefreshRate.getFps());
@@ -643,7 +667,7 @@
}
}
if (frameRateChanged) {
- auto newRefreshRate = mRefreshRateConfigs.getRefreshRateFromModeId(newModeId);
+ auto newRefreshRate = refreshRateConfigs->getRefreshRateFromModeId(newModeId);
mSchedulerCallback.changeRefreshRate(newRefreshRate,
consideredSignals.idle ? ModeEvent::None
: ModeEvent::Changed);
@@ -689,7 +713,11 @@
// TODO(145561154): cleanup the kernel idle timer implementation and the refresh rate
// magic number
- const auto& refreshRate = mRefreshRateConfigs.getCurrentRefreshRate();
+ const auto refreshRate = [&] {
+ std::scoped_lock lock(mRefreshRateConfigsLock);
+ return mRefreshRateConfigs->getCurrentRefreshRate();
+ }();
+
constexpr Fps FPS_THRESHOLD_FOR_KERNEL_TIMER{65.0f};
if (state == TimerState::Reset &&
refreshRate.getFps().greaterThanWithMargin(FPS_THRESHOLD_FOR_KERNEL_TIMER)) {
@@ -741,7 +769,7 @@
mLayerHistory ? mLayerHistory->dump().c_str() : "(no layer history)");
{
- std::lock_guard lock(mFrameRateOverridesMutex);
+ std::lock_guard lock(mFrameRateOverridesLock);
StringAppendF(&result, "Frame Rate Overrides (backdoor): {");
for (const auto& [uid, frameRate] : mFrameRateOverridesFromBackdoor) {
StringAppendF(&result, "[uid: %d frameRate: %s], ", uid, to_string(frameRate).c_str());
@@ -767,16 +795,17 @@
bool Scheduler::updateFrameRateOverrides(
scheduler::RefreshRateConfigs::GlobalSignals consideredSignals, Fps displayRefreshRate) {
- if (!mRefreshRateConfigs.supportsFrameRateOverride()) {
+ const auto refreshRateConfigs = holdRefreshRateConfigs();
+ if (!refreshRateConfigs->supportsFrameRateOverride()) {
return false;
}
if (!consideredSignals.idle) {
const auto frameRateOverrides =
- mRefreshRateConfigs.getFrameRateOverrides(mFeatures.contentRequirements,
+ refreshRateConfigs->getFrameRateOverrides(mFeatures.contentRequirements,
displayRefreshRate,
consideredSignals.touch);
- std::lock_guard lock(mFrameRateOverridesMutex);
+ std::lock_guard lock(mFrameRateOverridesLock);
if (!std::equal(mFrameRateOverridesByContent.begin(), mFrameRateOverridesByContent.end(),
frameRateOverrides.begin(), frameRateOverrides.end(),
[](const std::pair<uid_t, Fps>& a, const std::pair<uid_t, Fps>& b) {
@@ -795,6 +824,7 @@
bool refreshRateChanged = false;
bool frameRateOverridesChanged;
scheduler::RefreshRateConfigs::GlobalSignals consideredSignals;
+ const auto refreshRateConfigs = holdRefreshRateConfigs();
{
std::lock_guard<std::mutex> lock(mFeatureStateLock);
if (*currentState == newState) {
@@ -802,7 +832,7 @@
}
*currentState = newState;
newModeId = calculateRefreshRateModeId(&consideredSignals);
- const RefreshRate& newRefreshRate = mRefreshRateConfigs.getRefreshRateFromModeId(newModeId);
+ const RefreshRate& newRefreshRate = refreshRateConfigs->getRefreshRateFromModeId(newModeId);
frameRateOverridesChanged =
updateFrameRateOverrides(consideredSignals, newRefreshRate.getFps());
if (mFeatures.modeId == newModeId) {
@@ -817,7 +847,7 @@
}
}
if (refreshRateChanged) {
- const RefreshRate& newRefreshRate = mRefreshRateConfigs.getRefreshRateFromModeId(newModeId);
+ const RefreshRate& newRefreshRate = refreshRateConfigs->getRefreshRateFromModeId(newModeId);
mSchedulerCallback.changeRefreshRate(newRefreshRate,
consideredSignals.idle ? ModeEvent::None
@@ -834,20 +864,21 @@
ATRACE_CALL();
if (consideredSignals) *consideredSignals = {};
+ const auto refreshRateConfigs = holdRefreshRateConfigs();
// If Display Power is not in normal operation we want to be in performance mode. When coming
// back to normal mode, a grace period is given with DisplayPowerTimer.
if (mDisplayPowerTimer &&
(!mFeatures.isDisplayPowerStateNormal ||
mFeatures.displayPowerTimer == TimerState::Reset)) {
- return mRefreshRateConfigs.getMaxRefreshRateByPolicy().getModeId();
+ return refreshRateConfigs->getMaxRefreshRateByPolicy().getModeId();
}
const bool touchActive = mTouchTimer && mFeatures.touch == TouchState::Active;
const bool idle = mIdleTimer && mFeatures.idleTimer == TimerState::Expired;
- return mRefreshRateConfigs
- .getBestRefreshRate(mFeatures.contentRequirements, {.touch = touchActive, .idle = idle},
- consideredSignals)
+ return refreshRateConfigs
+ ->getBestRefreshRate(mFeatures.contentRequirements,
+ {.touch = touchActive, .idle = idle}, consideredSignals)
.getModeId();
}
@@ -902,7 +933,7 @@
return;
}
- std::lock_guard lock(mFrameRateOverridesMutex);
+ std::lock_guard lock(mFrameRateOverridesLock);
if (frameRateOverride.frameRateHz != 0.f) {
mFrameRateOverridesFromBackdoor[frameRateOverride.uid] = Fps(frameRateOverride.frameRateHz);
} else {
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index 7a2fdb5..dc17f90 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -72,7 +72,7 @@
using RefreshRate = scheduler::RefreshRateConfigs::RefreshRate;
using ModeEvent = scheduler::RefreshRateConfigEvent;
- Scheduler(const scheduler::RefreshRateConfigs&, ISchedulerCallback&);
+ Scheduler(const std::shared_ptr<scheduler::RefreshRateConfigs>&, ISchedulerCallback&);
~Scheduler();
using ConnectionHandle = scheduler::ConnectionHandle;
@@ -95,7 +95,7 @@
void onScreenReleased(ConnectionHandle);
void onFrameRateOverridesChanged(ConnectionHandle, PhysicalDisplayId)
- EXCLUDES(mFrameRateOverridesMutex) EXCLUDES(mConnectionsLock);
+ EXCLUDES(mFrameRateOverridesLock) EXCLUDES(mConnectionsLock);
// Modifies work duration in the event thread.
void setDuration(ConnectionHandle, std::chrono::nanoseconds workDuration,
@@ -116,7 +116,7 @@
// no-op.
// The period is the vsync period from the current display configuration.
void resyncToHardwareVsync(bool makeAvailable, nsecs_t period);
- void resync();
+ void resync() EXCLUDES(mRefreshRateConfigsLock);
// Passes a vsync sample to VsyncController. periodFlushed will be true if
// VsyncController detected that the vsync period changed, and false otherwise.
@@ -127,12 +127,13 @@
// Layers are registered on creation, and unregistered when the weak reference expires.
void registerLayer(Layer*);
- void recordLayerHistory(Layer*, nsecs_t presentTime, LayerHistory::LayerUpdateType updateType);
+ void recordLayerHistory(Layer*, nsecs_t presentTime, LayerHistory::LayerUpdateType updateType)
+ EXCLUDES(mRefreshRateConfigsLock);
void setModeChangePending(bool pending);
void deregisterLayer(Layer*);
// Detects content using layer history, and selects a matching refresh rate.
- void chooseRefreshRateForContent();
+ void chooseRefreshRateForContent() EXCLUDES(mRefreshRateConfigsLock);
bool isIdleTimerEnabled() const { return mIdleTimer.has_value(); }
void resetIdleTimer();
@@ -147,7 +148,7 @@
// Returns true if a given vsync timestamp is considered valid vsync
// for a given uid
bool isVsyncValid(nsecs_t expectedVsyncTimestamp, uid_t uid) const
- EXCLUDES(mFrameRateOverridesMutex);
+ EXCLUDES(mFrameRateOverridesLock);
std::chrono::steady_clock::time_point getPreviousVsyncFrom(nsecs_t expectedPresentTime) const;
@@ -176,9 +177,21 @@
// Stores the preferred refresh rate that an app should run at.
// FrameRateOverride.refreshRateHz == 0 means no preference.
- void setPreferredRefreshRateForUid(FrameRateOverride) EXCLUDES(mFrameRateOverridesMutex);
+ void setPreferredRefreshRateForUid(FrameRateOverride) EXCLUDES(mFrameRateOverridesLock);
// Retrieves the overridden refresh rate for a given uid.
- std::optional<Fps> getFrameRateOverride(uid_t uid) const EXCLUDES(mFrameRateOverridesMutex);
+ std::optional<Fps> getFrameRateOverride(uid_t uid) const
+ EXCLUDES(mRefreshRateConfigsLock, mFrameRateOverridesLock);
+
+ void setRefreshRateConfigs(std::shared_ptr<scheduler::RefreshRateConfigs> refreshRateConfigs)
+ EXCLUDES(mRefreshRateConfigsLock) {
+ std::scoped_lock lock(mRefreshRateConfigsLock);
+ mRefreshRateConfigs = std::move(refreshRateConfigs);
+ }
+
+ nsecs_t getVsyncPeriodFromRefreshRateConfigs() const EXCLUDES(mRefreshRateConfigsLock) {
+ std::scoped_lock lock(mRefreshRateConfigsLock);
+ return mRefreshRateConfigs->getCurrentRefreshRate().getVsyncPeriod();
+ }
private:
friend class TestableScheduler;
@@ -203,14 +216,14 @@
};
// Unlike the testing constructor, this creates the VsyncSchedule, LayerHistory, and timers.
- Scheduler(const scheduler::RefreshRateConfigs&, ISchedulerCallback&, Options);
+ Scheduler(const std::shared_ptr<scheduler::RefreshRateConfigs>&, ISchedulerCallback&, Options);
// Used by tests to inject mocks.
- Scheduler(VsyncSchedule, const scheduler::RefreshRateConfigs&, ISchedulerCallback&,
- std::unique_ptr<LayerHistory>, Options);
+ Scheduler(VsyncSchedule, const std::shared_ptr<scheduler::RefreshRateConfigs>&,
+ ISchedulerCallback&, std::unique_ptr<LayerHistory>, Options);
static VsyncSchedule createVsyncSchedule(bool supportKernelIdleTimer);
- static std::unique_ptr<LayerHistory> createLayerHistory(const scheduler::RefreshRateConfigs&);
+ static std::unique_ptr<LayerHistory> createLayerHistory();
// Create a connection on the given EventThread.
ConnectionHandle createConnection(std::unique_ptr<EventThread>);
@@ -218,7 +231,7 @@
EventThread*, ISurfaceComposer::EventRegistrationFlags eventRegistration = {});
// Update feature state machine to given state when corresponding timer resets or expires.
- void kernelIdleTimerCallback(TimerState);
+ void kernelIdleTimerCallback(TimerState) EXCLUDES(mRefreshRateConfigsLock);
void idleTimerCallback(TimerState);
void touchTimerCallback(TimerState);
void displayPowerTimerCallback(TimerState);
@@ -236,14 +249,21 @@
scheduler::RefreshRateConfigs::GlobalSignals* consideredSignals = nullptr)
REQUIRES(mFeatureStateLock);
- void dispatchCachedReportedMode() REQUIRES(mFeatureStateLock);
+ void dispatchCachedReportedMode() REQUIRES(mFeatureStateLock) EXCLUDES(mRefreshRateConfigsLock);
bool updateFrameRateOverrides(scheduler::RefreshRateConfigs::GlobalSignals consideredSignals,
Fps displayRefreshRate) REQUIRES(mFeatureStateLock)
- EXCLUDES(mFrameRateOverridesMutex);
+ EXCLUDES(mFrameRateOverridesLock);
- impl::EventThread::ThrottleVsyncCallback makeThrottleVsyncCallback() const;
+ impl::EventThread::ThrottleVsyncCallback makeThrottleVsyncCallback() const
+ EXCLUDES(mRefreshRateConfigsLock);
impl::EventThread::GetVsyncPeriodFunction makeGetVsyncPeriodFunction() const;
+ std::shared_ptr<scheduler::RefreshRateConfigs> holdRefreshRateConfigs() const
+ EXCLUDES(mRefreshRateConfigsLock) {
+ std::scoped_lock lock(mRefreshRateConfigsLock);
+ return mRefreshRateConfigs;
+ }
+
// Stores EventThread associated with a given VSyncSource, and an initial EventThreadConnection.
struct Connection {
sp<EventThreadConnection> connection;
@@ -304,7 +324,9 @@
std::optional<ModeChangedParams> cachedModeChangedParams;
} mFeatures GUARDED_BY(mFeatureStateLock);
- const scheduler::RefreshRateConfigs& mRefreshRateConfigs;
+ mutable std::mutex mRefreshRateConfigsLock;
+ std::shared_ptr<scheduler::RefreshRateConfigs> mRefreshRateConfigs
+ GUARDED_BY(mRefreshRateConfigsLock);
std::mutex mVsyncTimelineLock;
std::optional<hal::VsyncPeriodChangeTimeline> mLastVsyncPeriodChangeTimeline
@@ -315,14 +337,14 @@
// The frame rate override lists need their own mutex as they are being read
// by SurfaceFlinger, Scheduler and EventThread (as a callback) to prevent deadlocks
- mutable std::mutex mFrameRateOverridesMutex;
+ mutable std::mutex mFrameRateOverridesLock;
// mappings between a UID and a preferred refresh rate that this app would
// run at.
scheduler::RefreshRateConfigs::UidToFrameRateOverride mFrameRateOverridesByContent
- GUARDED_BY(mFrameRateOverridesMutex);
+ GUARDED_BY(mFrameRateOverridesLock);
scheduler::RefreshRateConfigs::UidToFrameRateOverride mFrameRateOverridesFromBackdoor
- GUARDED_BY(mFrameRateOverridesMutex);
+ GUARDED_BY(mFrameRateOverridesLock);
};
} // namespace android