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);
-        }
     }
 }