SF: Merge per-display maps in Scheduler
Fixes: 266715559
Test: libsurfaceflinger_unittest
Change-Id: Ia8934f73f237c37e8f477be5183f84a9c1a40a5a
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index 3e12db6..63a0173 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -50,8 +50,9 @@
#include "FrontEnd/LayerHandle.h"
#include "OneShotTimer.h"
#include "SurfaceFlingerProperties.h"
-#include "VSyncPredictor.h"
-#include "VSyncReactor.h"
+#include "VSyncTracker.h"
+#include "VsyncController.h"
+#include "VsyncSchedule.h"
#define RETURN_IF_INVALID_HANDLE(handle, ...) \
do { \
@@ -119,14 +120,13 @@
void Scheduler::registerDisplayInternal(PhysicalDisplayId displayId,
RefreshRateSelectorPtr selectorPtr,
- std::shared_ptr<VsyncSchedule> vsyncSchedule) {
+ VsyncSchedulePtr schedulePtr) {
demotePacesetterDisplay();
std::shared_ptr<VsyncSchedule> pacesetterVsyncSchedule;
{
std::scoped_lock lock(mDisplayLock);
- mRefreshRateSelectors.emplace_or_replace(displayId, std::move(selectorPtr));
- mVsyncSchedules.emplace_or_replace(displayId, std::move(vsyncSchedule));
+ mDisplays.emplace_or_replace(displayId, std::move(selectorPtr), std::move(schedulePtr));
pacesetterVsyncSchedule = promotePacesetterDisplayLocked();
}
@@ -139,13 +139,12 @@
std::shared_ptr<VsyncSchedule> pacesetterVsyncSchedule;
{
std::scoped_lock lock(mDisplayLock);
- mRefreshRateSelectors.erase(displayId);
- mVsyncSchedules.erase(displayId);
+ mDisplays.erase(displayId);
// Do not allow removing the final display. Code in the scheduler expects
// there to be at least one display. (This may be relaxed in the future with
// headless virtual display.)
- LOG_ALWAYS_FATAL_IF(mRefreshRateSelectors.empty(), "Cannot unregister all displays!");
+ LOG_ALWAYS_FATAL_IF(mDisplays.empty(), "Cannot unregister all displays!");
pacesetterVsyncSchedule = promotePacesetterDisplayLocked();
}
@@ -199,20 +198,27 @@
impl::EventThread::GetVsyncPeriodFunction Scheduler::makeGetVsyncPeriodFunction() const {
return [this](uid_t uid) {
- const Fps refreshRate = pacesetterSelectorPtr()->getActiveMode().fps;
- const nsecs_t currentPeriod =
- getVsyncSchedule()->period().ns() ?: refreshRate.getPeriodNsecs();
+ const auto [refreshRate, period] = [this] {
+ std::scoped_lock lock(mDisplayLock);
+ const auto pacesetterOpt = pacesetterDisplayLocked();
+ LOG_ALWAYS_FATAL_IF(!pacesetterOpt);
+ const Display& pacesetter = *pacesetterOpt;
+ return std::make_pair(pacesetter.selectorPtr->getActiveMode().fps,
+ pacesetter.schedulePtr->period());
+ }();
+
+ const Period currentPeriod = period != Period::zero() ? period : refreshRate.getPeriod();
const auto frameRate = getFrameRateOverride(uid);
if (!frameRate.has_value()) {
- return currentPeriod;
+ return currentPeriod.ns();
}
const auto divisor = RefreshRateSelector::getFrameRateDivisor(refreshRate, *frameRate);
if (divisor <= 1) {
- return currentPeriod;
+ return currentPeriod.ns();
}
- return currentPeriod * divisor;
+ return currentPeriod.ns() * divisor;
};
}
@@ -413,23 +419,24 @@
std::scoped_lock lock(mDisplayLock);
ftl::FakeGuard guard(kMainThreadContext);
- for (const auto& [id, _] : mRefreshRateSelectors) {
+ for (const auto& [id, _] : mDisplays) {
resyncToHardwareVsyncLocked(id, allowToEnable);
}
}
void Scheduler::resyncToHardwareVsyncLocked(PhysicalDisplayId id, bool allowToEnable,
std::optional<Fps> refreshRate) {
- auto schedule = getVsyncScheduleLocked(id);
- if (schedule->isHardwareVsyncAllowed(allowToEnable)) {
+ const auto displayOpt = mDisplays.get(id);
+ LOG_ALWAYS_FATAL_IF(!displayOpt);
+ const Display& display = *displayOpt;
+
+ if (display.schedulePtr->isHardwareVsyncAllowed(allowToEnable)) {
if (!refreshRate) {
- auto selectorPtr = mRefreshRateSelectors.get(id);
- LOG_ALWAYS_FATAL_IF(!selectorPtr);
- refreshRate = selectorPtr->get()->getActiveMode().modePtr->getFps();
+ refreshRate = display.selectorPtr->getActiveMode().modePtr->getFps();
}
if (refreshRate->isValid()) {
- schedule->startPeriodTransition(mSchedulerCallback, refreshRate->getPeriod(),
- false /* force */);
+ display.schedulePtr->startPeriodTransition(mSchedulerCallback, refreshRate->getPeriod(),
+ false /* force */);
}
}
}
@@ -438,9 +445,10 @@
std::scoped_lock lock(mDisplayLock);
ftl::FakeGuard guard(kMainThreadContext);
- auto selectorPtr = mRefreshRateSelectors.get(id);
- LOG_ALWAYS_FATAL_IF(!selectorPtr);
- const auto mode = selectorPtr->get()->getActiveMode();
+ const auto displayOpt = mDisplays.get(id);
+ LOG_ALWAYS_FATAL_IF(!displayOpt);
+ const Display& display = *displayOpt;
+ const auto mode = display.selectorPtr->getActiveMode();
using fps_approx_ops::operator!=;
LOG_ALWAYS_FATAL_IF(renderFrameRate != mode.fps,
@@ -451,7 +459,7 @@
ALOGV("%s %s (%s)", __func__, to_string(mode.fps).c_str(),
to_string(mode.modePtr->getFps()).c_str());
- getVsyncScheduleLocked(id)->getTracker().setRenderRate(renderFrameRate);
+ display.schedulePtr->getTracker().setRenderRate(renderFrameRate);
}
void Scheduler::resync() {
@@ -558,22 +566,24 @@
mLayerHistory.clear();
}
-std::shared_ptr<const VsyncSchedule> Scheduler::getVsyncSchedule(
- std::optional<PhysicalDisplayId> idOpt) const {
+auto Scheduler::getVsyncSchedule(std::optional<PhysicalDisplayId> idOpt) const
+ -> ConstVsyncSchedulePtr {
std::scoped_lock lock(mDisplayLock);
return getVsyncScheduleLocked(idOpt);
}
-std::shared_ptr<const VsyncSchedule> Scheduler::getVsyncScheduleLocked(
- std::optional<PhysicalDisplayId> idOpt) const {
+auto Scheduler::getVsyncScheduleLocked(std::optional<PhysicalDisplayId> idOpt) const
+ -> ConstVsyncSchedulePtr {
ftl::FakeGuard guard(kMainThreadContext);
+
if (!idOpt) {
LOG_ALWAYS_FATAL_IF(!mPacesetterDisplayId, "Missing a pacesetter!");
idOpt = mPacesetterDisplayId;
}
- auto scheduleOpt = mVsyncSchedules.get(*idOpt);
- LOG_ALWAYS_FATAL_IF(!scheduleOpt);
- return std::const_pointer_cast<const VsyncSchedule>(scheduleOpt->get());
+
+ const auto displayOpt = mDisplays.get(*idOpt);
+ LOG_ALWAYS_FATAL_IF(!displayOpt);
+ return displayOpt->get().schedulePtr;
}
void Scheduler::kernelIdleTimerCallback(TimerState state) {
@@ -597,9 +607,9 @@
// need to update the VsyncController model anyway.
std::scoped_lock lock(mDisplayLock);
ftl::FakeGuard guard(kMainThreadContext);
- constexpr bool disallow = false;
- for (auto& [_, schedule] : mVsyncSchedules) {
- schedule->disableHardwareVsync(mSchedulerCallback, disallow);
+ for (const auto& [_, display] : mDisplays) {
+ constexpr bool kDisallow = false;
+ display.schedulePtr->disableHardwareVsync(mSchedulerCallback, kDisallow);
}
}
@@ -664,12 +674,12 @@
to_string(*mPacesetterDisplayId).c_str());
getVsyncScheduleLocked()->dump(out);
}
- for (auto& [id, vsyncSchedule] : mVsyncSchedules) {
+ for (auto& [id, display] : mDisplays) {
if (id == mPacesetterDisplayId) {
continue;
}
base::StringAppendF(&out, "VsyncSchedule for follower %s:\n", to_string(id).c_str());
- vsyncSchedule->dump(out);
+ display.schedulePtr->dump(out);
}
}
@@ -699,25 +709,29 @@
std::shared_ptr<VsyncSchedule> Scheduler::promotePacesetterDisplayLocked(
std::optional<PhysicalDisplayId> pacesetterIdOpt) {
// TODO(b/241286431): Choose the pacesetter display.
- mPacesetterDisplayId = pacesetterIdOpt.value_or(mRefreshRateSelectors.begin()->first);
+ mPacesetterDisplayId = pacesetterIdOpt.value_or(mDisplays.begin()->first);
ALOGI("Display %s is the pacesetter", to_string(*mPacesetterDisplayId).c_str());
- auto vsyncSchedule = getVsyncScheduleLocked(*mPacesetterDisplayId);
- if (const auto pacesetterPtr = pacesetterSelectorPtrLocked()) {
- pacesetterPtr->setIdleTimerCallbacks(
+ std::shared_ptr<VsyncSchedule> newVsyncSchedulePtr;
+ if (const auto pacesetterOpt = pacesetterDisplayLocked()) {
+ const Display& pacesetter = *pacesetterOpt;
+
+ pacesetter.selectorPtr->setIdleTimerCallbacks(
{.platform = {.onReset = [this] { idleTimerCallback(TimerState::Reset); },
.onExpired = [this] { idleTimerCallback(TimerState::Expired); }},
.kernel = {.onReset = [this] { kernelIdleTimerCallback(TimerState::Reset); },
.onExpired =
[this] { kernelIdleTimerCallback(TimerState::Expired); }}});
- pacesetterPtr->startIdleTimer();
+ pacesetter.selectorPtr->startIdleTimer();
- const Fps refreshRate = pacesetterPtr->getActiveMode().modePtr->getFps();
- vsyncSchedule->startPeriodTransition(mSchedulerCallback, refreshRate.getPeriod(),
- true /* force */);
+ newVsyncSchedulePtr = pacesetter.schedulePtr;
+
+ const Fps refreshRate = pacesetter.selectorPtr->getActiveMode().modePtr->getFps();
+ newVsyncSchedulePtr->startPeriodTransition(mSchedulerCallback, refreshRate.getPeriod(),
+ true /* force */);
}
- return vsyncSchedule;
+ return newVsyncSchedulePtr;
}
void Scheduler::applyNewVsyncSchedule(std::shared_ptr<VsyncSchedule> vsyncSchedule) {
@@ -831,9 +845,10 @@
const auto globalSignals = makeGlobalSignals();
- for (const auto& [id, selectorPtr] : mRefreshRateSelectors) {
+ for (const auto& [id, display] : mDisplays) {
auto rankedFrameRates =
- selectorPtr->getRankedFrameRates(mPolicy.contentRequirements, globalSignals);
+ display.selectorPtr->getRankedFrameRates(mPolicy.contentRequirements,
+ globalSignals);
for (const auto& [frameRateMode, score] : rankedFrameRates.ranking) {
const auto [it, inserted] = refreshRateTallies.try_emplace(frameRateMode.fps, score);
@@ -852,7 +867,7 @@
// Find the first refresh rate common to all displays.
while (maxScoreIt != refreshRateTallies.cend() &&
- maxScoreIt->second.displayCount != mRefreshRateSelectors.size()) {
+ maxScoreIt->second.displayCount != mDisplays.size()) {
++maxScoreIt;
}
@@ -861,8 +876,7 @@
for (auto it = maxScoreIt + 1; it != refreshRateTallies.cend(); ++it) {
const auto [fps, tally] = *it;
- if (tally.displayCount == mRefreshRateSelectors.size() &&
- tally.score > maxScoreIt->second.score) {
+ if (tally.displayCount == mDisplays.size() && tally.score > maxScoreIt->second.score) {
maxScoreIt = it;
}
}
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index 1f6d378..43aab2d 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -32,7 +32,6 @@
#include <ui/GraphicTypes.h>
#pragma clang diagnostic pop // ignored "-Wconversion -Wextra"
-#include <ftl/algorithm.h>
#include <ftl/fake_guard.h>
#include <ftl/optional.h>
#include <scheduler/Features.h>
@@ -51,7 +50,6 @@
#include "RefreshRateSelector.h"
#include "Utils/Dumper.h"
#include "VsyncModulator.h"
-#include "VsyncSchedule.h"
namespace android::scheduler {
@@ -94,6 +92,8 @@
using GlobalSignals = RefreshRateSelector::GlobalSignals;
+class VsyncSchedule;
+
class Scheduler : android::impl::MessageQueue {
using Impl = android::impl::MessageQueue;
@@ -109,6 +109,9 @@
using RefreshRateSelectorPtr = std::shared_ptr<RefreshRateSelector>;
+ using ConstVsyncSchedulePtr = std::shared_ptr<const VsyncSchedule>;
+ using VsyncSchedulePtr = std::shared_ptr<VsyncSchedule>;
+
void registerDisplay(PhysicalDisplayId, RefreshRateSelectorPtr) REQUIRES(kMainThreadContext)
EXCLUDES(mDisplayLock);
void unregisterDisplay(PhysicalDisplayId) REQUIRES(kMainThreadContext) EXCLUDES(mDisplayLock);
@@ -237,12 +240,12 @@
void setDisplayPowerMode(PhysicalDisplayId, hal::PowerMode powerMode)
REQUIRES(kMainThreadContext);
- std::shared_ptr<const VsyncSchedule> getVsyncSchedule(
- std::optional<PhysicalDisplayId> idOpt = std::nullopt) const EXCLUDES(mDisplayLock);
- std::shared_ptr<VsyncSchedule> getVsyncSchedule(
- std::optional<PhysicalDisplayId> idOpt = std::nullopt) EXCLUDES(mDisplayLock) {
- return std::const_pointer_cast<VsyncSchedule>(
- static_cast<const Scheduler*>(this)->getVsyncSchedule(idOpt));
+ ConstVsyncSchedulePtr getVsyncSchedule(std::optional<PhysicalDisplayId> = std::nullopt) const
+ EXCLUDES(mDisplayLock);
+
+ VsyncSchedulePtr getVsyncSchedule(std::optional<PhysicalDisplayId> idOpt = std::nullopt)
+ EXCLUDES(mDisplayLock) {
+ return std::const_pointer_cast<VsyncSchedule>(std::as_const(*this).getVsyncSchedule(idOpt));
}
// Returns true if a given vsync timestamp is considered valid vsync
@@ -339,9 +342,8 @@
// the caller on the main thread to avoid deadlock, since the timer thread locks it before exit.
void demotePacesetterDisplay() REQUIRES(kMainThreadContext) EXCLUDES(mDisplayLock, mPolicyLock);
- void registerDisplayInternal(PhysicalDisplayId, RefreshRateSelectorPtr,
- std::shared_ptr<VsyncSchedule>) REQUIRES(kMainThreadContext)
- EXCLUDES(mDisplayLock);
+ void registerDisplayInternal(PhysicalDisplayId, RefreshRateSelectorPtr, VsyncSchedulePtr)
+ REQUIRES(kMainThreadContext) EXCLUDES(mDisplayLock);
struct Policy;
@@ -420,16 +422,37 @@
// must lock for writes but not reads. See also mPolicyLock for locking order.
mutable std::mutex mDisplayLock;
- display::PhysicalDisplayMap<PhysicalDisplayId, RefreshRateSelectorPtr> mRefreshRateSelectors
- GUARDED_BY(mDisplayLock) GUARDED_BY(kMainThreadContext);
+ struct Display {
+ Display(RefreshRateSelectorPtr selectorPtr, VsyncSchedulePtr schedulePtr)
+ : selectorPtr(std::move(selectorPtr)), schedulePtr(std::move(schedulePtr)) {}
- // TODO (b/266715559): Store in the same map as mRefreshRateSelectors.
- display::PhysicalDisplayMap<PhysicalDisplayId, std::shared_ptr<VsyncSchedule>> mVsyncSchedules
- GUARDED_BY(mDisplayLock) GUARDED_BY(kMainThreadContext);
+ // Effectively const except in move constructor.
+ RefreshRateSelectorPtr selectorPtr;
+ VsyncSchedulePtr schedulePtr;
+ };
+
+ using DisplayRef = std::reference_wrapper<Display>;
+ using ConstDisplayRef = std::reference_wrapper<const Display>;
+
+ display::PhysicalDisplayMap<PhysicalDisplayId, Display> mDisplays GUARDED_BY(mDisplayLock)
+ GUARDED_BY(kMainThreadContext);
ftl::Optional<PhysicalDisplayId> mPacesetterDisplayId GUARDED_BY(mDisplayLock)
GUARDED_BY(kMainThreadContext);
+ ftl::Optional<DisplayRef> pacesetterDisplayLocked() REQUIRES(mDisplayLock) {
+ return static_cast<const Scheduler*>(this)->pacesetterDisplayLocked().transform(
+ [](const Display& display) { return std::ref(const_cast<Display&>(display)); });
+ }
+
+ ftl::Optional<ConstDisplayRef> pacesetterDisplayLocked() const REQUIRES(mDisplayLock) {
+ ftl::FakeGuard guard(kMainThreadContext);
+ return mPacesetterDisplayId.and_then([this](PhysicalDisplayId pacesetterId)
+ REQUIRES(mDisplayLock, kMainThreadContext) {
+ return mDisplays.get(pacesetterId);
+ });
+ }
+
RefreshRateSelectorPtr pacesetterSelectorPtr() const EXCLUDES(mDisplayLock) {
std::scoped_lock lock(mDisplayLock);
return pacesetterSelectorPtrLocked();
@@ -437,19 +460,17 @@
RefreshRateSelectorPtr pacesetterSelectorPtrLocked() const REQUIRES(mDisplayLock) {
ftl::FakeGuard guard(kMainThreadContext);
- return mPacesetterDisplayId
- .and_then([this](PhysicalDisplayId pacesetterId)
- REQUIRES(mDisplayLock, kMainThreadContext) {
- return mRefreshRateSelectors.get(pacesetterId);
- })
- .or_else(ftl::static_ref<RefreshRateSelectorPtr>([] { return nullptr; }))
+ return pacesetterDisplayLocked()
+ .transform([](const Display& display) { return display.selectorPtr; })
+ .or_else([] { return std::optional<RefreshRateSelectorPtr>(nullptr); })
.value();
}
- std::shared_ptr<const VsyncSchedule> getVsyncScheduleLocked(
- std::optional<PhysicalDisplayId> idOpt = std::nullopt) const REQUIRES(mDisplayLock);
- std::shared_ptr<VsyncSchedule> getVsyncScheduleLocked(
- std::optional<PhysicalDisplayId> idOpt = std::nullopt) REQUIRES(mDisplayLock) {
+ ConstVsyncSchedulePtr getVsyncScheduleLocked(
+ std::optional<PhysicalDisplayId> = std::nullopt) const REQUIRES(mDisplayLock);
+
+ VsyncSchedulePtr getVsyncScheduleLocked(std::optional<PhysicalDisplayId> idOpt = std::nullopt)
+ REQUIRES(mDisplayLock) {
return std::const_pointer_cast<VsyncSchedule>(
static_cast<const Scheduler*>(this)->getVsyncScheduleLocked(idOpt));
}