Revert "Create a VsyncSchedule per display"
This reverts commit 31d41415101ff3483ce1cc5a9c2ef322490a05bd.
Conflicts:
services/surfaceflinger/Scheduler/EventThread.cpp
services/surfaceflinger/SurfaceFlinger.cpp
Bug: 267562341
Test: ARC Regression Dashboard
Change-Id: I0757a7df540fad316b2db42e4c77f1c73bc49420
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index eed57ef..c314b5c 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -114,18 +114,10 @@
}
void Scheduler::registerDisplay(PhysicalDisplayId displayId, RefreshRateSelectorPtr selectorPtr) {
- registerDisplayInternal(displayId, std::move(selectorPtr),
- std::make_shared<VsyncSchedule>(displayId, mFeatures));
-}
-
-void Scheduler::registerDisplayInternal(PhysicalDisplayId displayId,
- RefreshRateSelectorPtr selectorPtr,
- std::shared_ptr<VsyncSchedule> vsyncSchedule) {
demoteLeaderDisplay();
std::scoped_lock lock(mDisplayLock);
mRefreshRateSelectors.emplace_or_replace(displayId, std::move(selectorPtr));
- mVsyncSchedules.emplace_or_replace(displayId, std::move(vsyncSchedule));
promoteLeaderDisplay();
}
@@ -135,7 +127,6 @@
std::scoped_lock lock(mDisplayLock);
mRefreshRateSelectors.erase(displayId);
- mVsyncSchedules.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
@@ -163,49 +154,52 @@
compositor.sample();
}
-std::optional<Fps> Scheduler::getFrameRateOverride(uid_t uid) const {
- std::scoped_lock lock(mDisplayLock);
- return getFrameRateOverrideLocked(uid);
+void Scheduler::createVsyncSchedule(FeatureFlags features) {
+ mVsyncSchedule.emplace(features);
}
-std::optional<Fps> Scheduler::getFrameRateOverrideLocked(uid_t uid) const {
+std::optional<Fps> Scheduler::getFrameRateOverride(uid_t uid) const {
const bool supportsFrameRateOverrideByContent =
- leaderSelectorPtrLocked()->supportsAppFrameRateOverrideByContent();
+ leaderSelectorPtr()->supportsAppFrameRateOverrideByContent();
return mFrameRateOverrideMappings
.getFrameRateOverrideForUid(uid, supportsFrameRateOverrideByContent);
}
-bool Scheduler::isVsyncTargetForUid(TimePoint expectedVsyncTime, uid_t uid) const {
+bool Scheduler::isVsyncValid(TimePoint expectedVsyncTimestamp, uid_t uid) const {
const auto frameRate = getFrameRateOverride(uid);
if (!frameRate.has_value()) {
return true;
}
- return isVsyncInPhase(expectedVsyncTime, *frameRate);
+ return mVsyncSchedule->getTracker().isVSyncInPhase(expectedVsyncTimestamp.ns(), *frameRate);
}
-bool Scheduler::isVsyncInPhase(TimePoint expectedVsyncTime, Fps frameRate) const {
- return getVsyncSchedule()->getTracker().isVSyncInPhase(expectedVsyncTime.ns(), frameRate);
+bool Scheduler::isVsyncInPhase(TimePoint timePoint, const Fps frameRate) const {
+ return mVsyncSchedule->getTracker().isVSyncInPhase(timePoint.ns(), frameRate);
}
-Fps Scheduler::getLeaderRenderFrameRate(uid_t uid) const {
- std::scoped_lock lock(mDisplayLock);
- ftl::FakeGuard guard(kMainThreadContext);
- auto vsyncSchedule = getVsyncScheduleLocked();
+impl::EventThread::ThrottleVsyncCallback Scheduler::makeThrottleVsyncCallback() const {
+ return [this](nsecs_t expectedVsyncTimestamp, uid_t uid) {
+ return !isVsyncValid(TimePoint::fromNs(expectedVsyncTimestamp), uid);
+ };
+}
- const Fps refreshRate = leaderSelectorPtrLocked()->getActiveMode().fps;
- const nsecs_t currentPeriod = vsyncSchedule->period().ns() ?: refreshRate.getPeriodNsecs();
+impl::EventThread::GetVsyncPeriodFunction Scheduler::makeGetVsyncPeriodFunction() const {
+ return [this](uid_t uid) {
+ const Fps refreshRate = leaderSelectorPtr()->getActiveMode().fps;
+ const nsecs_t currentPeriod = mVsyncSchedule->period().ns() ?: refreshRate.getPeriodNsecs();
- const auto frameRate = getFrameRateOverrideLocked(uid);
- if (!frameRate.has_value()) {
- return Fps::fromPeriodNsecs(currentPeriod);
- }
+ const auto frameRate = getFrameRateOverride(uid);
+ if (!frameRate.has_value()) {
+ return currentPeriod;
+ }
- const auto divisor = RefreshRateSelector::getFrameRateDivisor(refreshRate, *frameRate);
- if (divisor <= 1) {
- return Fps::fromPeriodNsecs(currentPeriod);
- }
- return Fps::fromPeriodNsecs(currentPeriod * divisor);
+ const auto divisor = RefreshRateSelector::getFrameRateDivisor(refreshRate, *frameRate);
+ if (divisor <= 1) {
+ return currentPeriod;
+ }
+ return currentPeriod * divisor;
+ };
}
ConnectionHandle Scheduler::createEventThread(Cycle cycle,
@@ -213,7 +207,9 @@
std::chrono::nanoseconds workDuration,
std::chrono::nanoseconds readyDuration) {
auto eventThread = std::make_unique<impl::EventThread>(cycle == Cycle::Render ? "app" : "appSf",
- getVsyncSchedule(), *this, tokenManager,
+ *mVsyncSchedule, tokenManager,
+ makeThrottleVsyncCallback(),
+ makeGetVsyncPeriodFunction(),
workDuration, readyDuration);
auto& handle = cycle == Cycle::Render ? mAppConnectionHandle : mSfConnectionHandle;
@@ -276,6 +272,7 @@
thread = mConnections[handle].thread.get();
}
thread->onScreenAcquired();
+ mScreenAcquired = true;
}
void Scheduler::onScreenReleased(ConnectionHandle handle) {
@@ -286,6 +283,7 @@
thread = mConnections[handle].thread.get();
}
thread->onScreenReleased();
+ mScreenAcquired = false;
}
void Scheduler::onFrameRateOverridesChanged(ConnectionHandle handle, PhysicalDisplayId displayId) {
@@ -396,57 +394,48 @@
setDuration(config.sfWorkDuration);
}
-void Scheduler::enableHardwareVsync(PhysicalDisplayId id) {
- auto schedule = getVsyncSchedule(id);
- schedule->enableHardwareVsync(mSchedulerCallback);
-}
-
-void Scheduler::disableHardwareVsync(PhysicalDisplayId id, bool disallow) {
- auto schedule = getVsyncSchedule(id);
- schedule->disableHardwareVsync(mSchedulerCallback, disallow);
-}
-
-void Scheduler::resyncAllToHardwareVsync(bool allowToEnable) {
- std::scoped_lock lock(mDisplayLock);
- ftl::FakeGuard guard(kMainThreadContext);
-
- for (const auto& [id, _] : mRefreshRateSelectors) {
- resyncToHardwareVsyncLocked(id, allowToEnable);
+void Scheduler::enableHardwareVsync() {
+ std::lock_guard<std::mutex> lock(mHWVsyncLock);
+ if (!mPrimaryHWVsyncEnabled && mHWVsyncAvailable) {
+ mVsyncSchedule->getTracker().resetModel();
+ mSchedulerCallback.setVsyncEnabled(true);
+ mPrimaryHWVsyncEnabled = true;
}
}
-void Scheduler::resyncToHardwareVsyncLocked(PhysicalDisplayId id, bool allowToEnable,
- std::optional<Fps> refreshRate) {
- if (!refreshRate) {
- auto selectorPtr = mRefreshRateSelectors.get(id);
- LOG_ALWAYS_FATAL_IF(!selectorPtr);
- refreshRate = selectorPtr->get()->getActiveMode().modePtr->getFps();
+void Scheduler::disableHardwareVsync(bool makeUnavailable) {
+ std::lock_guard<std::mutex> lock(mHWVsyncLock);
+ if (mPrimaryHWVsyncEnabled) {
+ mSchedulerCallback.setVsyncEnabled(false);
+ mPrimaryHWVsyncEnabled = false;
}
- auto schedule = getVsyncScheduleLocked(id);
- if (allowToEnable) {
- schedule->allowHardwareVsync();
- } else if (!schedule->isHardwareVsyncAllowed()) {
- // Hardware vsync is not currently allowed, so abort the resync
- // attempt for now.
- return;
+ if (makeUnavailable) {
+ mHWVsyncAvailable = false;
}
-
- setVsyncPeriod(schedule, refreshRate->getPeriodNsecs(), false /* force */);
}
-void Scheduler::setRenderRate(PhysicalDisplayId id, Fps renderFrameRate) {
- std::scoped_lock lock(mDisplayLock);
- ftl::FakeGuard guard(kMainThreadContext);
+void Scheduler::resyncToHardwareVsync(bool makeAvailable, Fps refreshRate) {
+ {
+ std::lock_guard<std::mutex> lock(mHWVsyncLock);
+ if (makeAvailable) {
+ mHWVsyncAvailable = makeAvailable;
+ } else if (!mHWVsyncAvailable) {
+ // Hardware vsync is not currently available, so abort the resync
+ // attempt for now
+ return;
+ }
+ }
- auto selectorPtr = mRefreshRateSelectors.get(id);
- LOG_ALWAYS_FATAL_IF(!selectorPtr);
- const auto mode = selectorPtr->get()->getActiveMode();
+ setVsyncPeriod(refreshRate.getPeriodNsecs());
+}
+
+void Scheduler::setRenderRate(Fps renderFrameRate) {
+ const auto mode = leaderSelectorPtr()->getActiveMode();
using fps_approx_ops::operator!=;
LOG_ALWAYS_FATAL_IF(renderFrameRate != mode.fps,
- "Mismatch in render frame rates. Selector: %s, Scheduler: %s, Display: "
- "%" PRIu64,
- to_string(mode.fps).c_str(), to_string(renderFrameRate).c_str(), id.value);
+ "Mismatch in render frame rates. Selector: %s, Scheduler: %s",
+ to_string(mode.fps).c_str(), to_string(renderFrameRate).c_str());
ALOGV("%s %s (%s)", __func__, to_string(mode.fps).c_str(),
to_string(mode.modePtr->getFps()).c_str());
@@ -455,7 +444,7 @@
LOG_ALWAYS_FATAL_IF(divisor == 0, "%s <> %s -- not divisors", to_string(mode.fps).c_str(),
to_string(mode.fps).c_str());
- getVsyncScheduleLocked(id)->getTracker().setDivisor(static_cast<unsigned>(divisor));
+ mVsyncSchedule->getTracker().setDivisor(static_cast<unsigned>(divisor));
}
void Scheduler::resync() {
@@ -465,43 +454,49 @@
const nsecs_t last = mLastResyncTime.exchange(now);
if (now - last > kIgnoreDelay) {
- resyncAllToHardwareVsync(false /* allowToEnable */);
+ const auto refreshRate = leaderSelectorPtr()->getActiveMode().modePtr->getFps();
+ resyncToHardwareVsync(false, refreshRate);
}
}
-void Scheduler::setVsyncPeriod(const std::shared_ptr<VsyncSchedule>& schedule, nsecs_t period,
- bool force) {
- ALOGD("Scheduler::setVsyncPeriod");
+void Scheduler::setVsyncPeriod(nsecs_t period) {
if (period <= 0) return;
- // TODO (b/266712910):The old code held mHWVsyncLock before calling
- // startPeriodTransition. Move these into a new method on VsyncSchedule that
- // encapsulates this behavior there and allows holding the lock the whole
- // time.
- schedule->getController().startPeriodTransition(period, force);
- schedule->enableHardwareVsync(mSchedulerCallback);
+ std::lock_guard<std::mutex> lock(mHWVsyncLock);
+ mVsyncSchedule->getController().startPeriodTransition(period);
+
+ if (!mPrimaryHWVsyncEnabled) {
+ mVsyncSchedule->getTracker().resetModel();
+ mSchedulerCallback.setVsyncEnabled(true);
+ mPrimaryHWVsyncEnabled = true;
+ }
}
-bool Scheduler::addResyncSample(PhysicalDisplayId id, nsecs_t timestamp,
- std::optional<nsecs_t> hwcVsyncPeriod) {
- bool periodFlushed = false;
- auto schedule = getVsyncSchedule(id);
- if (schedule->getController().addHwVsyncTimestamp(timestamp, hwcVsyncPeriod, &periodFlushed)) {
- schedule->enableHardwareVsync(mSchedulerCallback);
- } else {
- schedule->disableHardwareVsync(mSchedulerCallback, false /* disallow */);
+void Scheduler::addResyncSample(nsecs_t timestamp, std::optional<nsecs_t> hwcVsyncPeriod,
+ bool* periodFlushed) {
+ bool needsHwVsync = false;
+ *periodFlushed = false;
+ { // Scope for the lock
+ std::lock_guard<std::mutex> lock(mHWVsyncLock);
+ if (mPrimaryHWVsyncEnabled) {
+ needsHwVsync =
+ mVsyncSchedule->getController().addHwVsyncTimestamp(timestamp, hwcVsyncPeriod,
+ periodFlushed);
+ }
}
- return periodFlushed;
+ if (needsHwVsync) {
+ enableHardwareVsync();
+ } else {
+ disableHardwareVsync(false);
+ }
}
-void Scheduler::addPresentFence(PhysicalDisplayId id, std::shared_ptr<FenceTime> fence) {
- auto schedule = getVsyncSchedule(id);
- const bool needMoreSignals = schedule->getController().addPresentFence(std::move(fence));
- if (needMoreSignals) {
- schedule->enableHardwareVsync(mSchedulerCallback);
+void Scheduler::addPresentFence(std::shared_ptr<FenceTime> fence) {
+ if (mVsyncSchedule->getController().addPresentFence(std::move(fence))) {
+ enableHardwareVsync();
} else {
- schedule->disableHardwareVsync(mSchedulerCallback, false /* disallow */);
+ disableHardwareVsync(false);
}
}
@@ -553,22 +548,12 @@
}
}
-void Scheduler::setDisplayPowerMode(PhysicalDisplayId id, hal::PowerMode powerMode) {
- const bool isLeader = [this, id]() REQUIRES(kMainThreadContext) {
- ftl::FakeGuard guard(mDisplayLock);
- return id == mLeaderDisplayId;
- }();
- if (isLeader) {
- // TODO (b/255657128): This needs to be handled per display.
+void Scheduler::setDisplayPowerMode(hal::PowerMode powerMode) {
+ {
std::lock_guard<std::mutex> lock(mPolicyLock);
mPolicy.displayPowerMode = powerMode;
}
- {
- std::scoped_lock lock(mDisplayLock);
- auto vsyncSchedule = getVsyncScheduleLocked(id);
- vsyncSchedule->getController().setDisplayPowerMode(powerMode);
- }
- if (!isLeader) return;
+ mVsyncSchedule->getController().setDisplayPowerMode(powerMode);
if (mDisplayPowerTimer) {
mDisplayPowerTimer->reset();
@@ -579,24 +564,6 @@
mLayerHistory.clear();
}
-std::shared_ptr<const VsyncSchedule> Scheduler::getVsyncSchedule(
- std::optional<PhysicalDisplayId> idOpt) const {
- std::scoped_lock lock(mDisplayLock);
- return getVsyncScheduleLocked(idOpt);
-}
-
-std::shared_ptr<const VsyncSchedule> Scheduler::getVsyncScheduleLocked(
- std::optional<PhysicalDisplayId> idOpt) const {
- ftl::FakeGuard guard(kMainThreadContext);
- if (!idOpt) {
- LOG_ALWAYS_FATAL_IF(!mLeaderDisplayId, "Missing a leader!");
- idOpt = mLeaderDisplayId;
- }
- auto scheduleOpt = mVsyncSchedules.get(*idOpt);
- LOG_ALWAYS_FATAL_IF(!scheduleOpt);
- return std::const_pointer_cast<const VsyncSchedule>(scheduleOpt->get());
-}
-
void Scheduler::kernelIdleTimerCallback(TimerState state) {
ATRACE_INT("ExpiredKernelIdleTimer", static_cast<int>(state));
@@ -611,17 +578,12 @@
// If we're not in performance mode then the kernel timer shouldn't do
// anything, as the refresh rate during DPU power collapse will be the
// same.
- resyncAllToHardwareVsync(true /* allowToEnable */);
+ resyncToHardwareVsync(true /* makeAvailable */, refreshRate);
} else if (state == TimerState::Expired && refreshRate <= FPS_THRESHOLD_FOR_KERNEL_TIMER) {
// Disable HW VSYNC if the timer expired, as we don't need it enabled if
// we're not pushing frames, and if we're in PERFORMANCE mode then we'll
// need to update the VsyncController model anyway.
- std::scoped_lock lock(mDisplayLock);
- ftl::FakeGuard guard(kMainThreadContext);
- constexpr bool disallow = false;
- for (auto& [_, schedule] : mVsyncSchedules) {
- schedule->disableHardwareVsync(mSchedulerCallback, disallow);
- }
+ disableHardwareVsync(false /* makeUnavailable */);
}
mSchedulerCallback.kernelTimerChanged(state == TimerState::Expired);
@@ -675,23 +637,19 @@
mFrameRateOverrideMappings.dump(dumper);
dumper.eol();
+
+ {
+ utils::Dumper::Section section(dumper, "Hardware VSYNC"sv);
+
+ std::lock_guard lock(mHWVsyncLock);
+ dumper.dump("screenAcquired"sv, mScreenAcquired.load());
+ dumper.dump("hwVsyncAvailable"sv, mHWVsyncAvailable);
+ dumper.dump("hwVsyncEnabled"sv, mPrimaryHWVsyncEnabled);
+ }
}
void Scheduler::dumpVsync(std::string& out) const {
- std::scoped_lock lock(mDisplayLock);
- ftl::FakeGuard guard(kMainThreadContext);
- if (mLeaderDisplayId) {
- base::StringAppendF(&out, "VsyncSchedule for leader %s:\n",
- to_string(*mLeaderDisplayId).c_str());
- getVsyncScheduleLocked()->dump(out);
- }
- for (auto& [id, vsyncSchedule] : mVsyncSchedules) {
- if (id == mLeaderDisplayId) {
- continue;
- }
- base::StringAppendF(&out, "VsyncSchedule for follower %s:\n", to_string(id).c_str());
- vsyncSchedule->dump(out);
- }
+ mVsyncSchedule->dump(out);
}
bool Scheduler::updateFrameRateOverrides(GlobalSignals consideredSignals, Fps displayRefreshRate) {
@@ -711,7 +669,6 @@
mLeaderDisplayId = leaderIdOpt.value_or(mRefreshRateSelectors.begin()->first);
ALOGI("Display %s is the leader", to_string(*mLeaderDisplayId).c_str());
- auto vsyncSchedule = getVsyncScheduleLocked(*mLeaderDisplayId);
if (const auto leaderPtr = leaderSelectorPtrLocked()) {
leaderPtr->setIdleTimerCallbacks(
{.platform = {.onReset = [this] { idleTimerCallback(TimerState::Reset); },
@@ -721,17 +678,6 @@
[this] { kernelIdleTimerCallback(TimerState::Expired); }}});
leaderPtr->startIdleTimer();
-
- const Fps refreshRate = leaderPtr->getActiveMode().modePtr->getFps();
- setVsyncPeriod(vsyncSchedule, refreshRate.getPeriodNsecs(), true /* force */);
- }
-
- updateVsyncRegistration(vsyncSchedule->getDispatch());
- {
- std::lock_guard<std::mutex> lock(mConnectionsLock);
- for (auto& [_, connection] : mConnections) {
- connection.thread->onNewVsyncSchedule(vsyncSchedule);
- }
}
}