Loading services/surfaceflinger/DisplayDevice.cpp +5 −5 Original line number Diff line number Diff line Loading @@ -510,21 +510,21 @@ void DisplayDevice::clearDesiredActiveModeState() { mDesiredActiveModeChanged = false; } void DisplayDevice::adjustRefreshRate(Fps leaderDisplayRefreshRate) { void DisplayDevice::adjustRefreshRate(Fps pacesetterDisplayRefreshRate) { using fps_approx_ops::operator==; if (mRequestedRefreshRate == 0_Hz) { return; } using fps_approx_ops::operator>; if (mRequestedRefreshRate > leaderDisplayRefreshRate) { mAdjustedRefreshRate = leaderDisplayRefreshRate; if (mRequestedRefreshRate > pacesetterDisplayRefreshRate) { mAdjustedRefreshRate = pacesetterDisplayRefreshRate; return; } unsigned divisor = static_cast<unsigned>( std::round(leaderDisplayRefreshRate.getValue() / mRequestedRefreshRate.getValue())); mAdjustedRefreshRate = leaderDisplayRefreshRate / divisor; std::round(pacesetterDisplayRefreshRate.getValue() / mRequestedRefreshRate.getValue())); mAdjustedRefreshRate = pacesetterDisplayRefreshRate / divisor; } std::atomic<int32_t> DisplayDeviceState::sNextSequenceId(1); Loading services/surfaceflinger/DisplayDevice.h +3 −3 Original line number Diff line number Diff line Loading @@ -247,9 +247,9 @@ public: Fps getAdjustedRefreshRate() const { return mAdjustedRefreshRate; } // Round the requested refresh rate to match a divisor of the leader // Round the requested refresh rate to match a divisor of the pacesetter // display's refresh rate. Only supported for virtual displays. void adjustRefreshRate(Fps leaderDisplayRefreshRate); void adjustRefreshRate(Fps pacesetterDisplayRefreshRate); // release HWC resources (if any) for removable displays void disconnect(); Loading Loading @@ -290,7 +290,7 @@ private: // for virtual displays to match this requested refresh rate. const Fps mRequestedRefreshRate; // Adjusted refresh rate, rounded to match a divisor of the leader // Adjusted refresh rate, rounded to match a divisor of the pacesetter // display's refresh rate. Only supported for virtual displays. Fps mAdjustedRefreshRate = 0_Hz; Loading services/surfaceflinger/Layer.cpp +2 −1 Original line number Diff line number Diff line Loading @@ -196,7 +196,8 @@ Layer::Layer(const LayerCreationArgs& args) mDrawingState.color.b = -1.0_hf; } mFrameTracker.setDisplayRefreshPeriod(args.flinger->mScheduler->getLeaderVsyncPeriod().ns()); mFrameTracker.setDisplayRefreshPeriod( args.flinger->mScheduler->getPacesetterVsyncPeriod().ns()); mOwnerUid = args.ownerUid; mOwnerPid = args.ownerPid; Loading services/surfaceflinger/Scheduler/Scheduler.cpp +49 −48 Original line number Diff line number Diff line Loading @@ -81,7 +81,7 @@ Scheduler::~Scheduler() { mTouchTimer.reset(); // Stop idle timer and clear callbacks, as the RefreshRateSelector may outlive the Scheduler. demoteLeaderDisplay(); demotePacesetterDisplay(); } void Scheduler::startTimers() { Loading @@ -106,11 +106,11 @@ void Scheduler::startTimers() { } } void Scheduler::setLeaderDisplay(std::optional<PhysicalDisplayId> leaderIdOpt) { demoteLeaderDisplay(); void Scheduler::setPacesetterDisplay(std::optional<PhysicalDisplayId> pacesetterIdOpt) { demotePacesetterDisplay(); std::scoped_lock lock(mDisplayLock); promoteLeaderDisplay(leaderIdOpt); promotePacesetterDisplay(pacesetterIdOpt); } void Scheduler::registerDisplay(PhysicalDisplayId displayId, RefreshRateSelectorPtr selectorPtr) { Loading @@ -121,17 +121,17 @@ void Scheduler::registerDisplay(PhysicalDisplayId displayId, RefreshRateSelector void Scheduler::registerDisplayInternal(PhysicalDisplayId displayId, RefreshRateSelectorPtr selectorPtr, std::shared_ptr<VsyncSchedule> vsyncSchedule) { demoteLeaderDisplay(); demotePacesetterDisplay(); std::scoped_lock lock(mDisplayLock); mRefreshRateSelectors.emplace_or_replace(displayId, std::move(selectorPtr)); mVsyncSchedules.emplace_or_replace(displayId, std::move(vsyncSchedule)); promoteLeaderDisplay(); promotePacesetterDisplay(); } void Scheduler::unregisterDisplay(PhysicalDisplayId displayId) { demoteLeaderDisplay(); demotePacesetterDisplay(); std::scoped_lock lock(mDisplayLock); mRefreshRateSelectors.erase(displayId); Loading @@ -142,7 +142,7 @@ void Scheduler::unregisterDisplay(PhysicalDisplayId displayId) { // headless virtual display.) LOG_ALWAYS_FATAL_IF(mRefreshRateSelectors.empty(), "Cannot unregister all displays!"); promoteLeaderDisplay(); promotePacesetterDisplay(); } void Scheduler::run() { Loading @@ -165,7 +165,7 @@ void Scheduler::onFrameSignal(ICompositor& compositor, VsyncId vsyncId, std::optional<Fps> Scheduler::getFrameRateOverride(uid_t uid) const { const bool supportsFrameRateOverrideByContent = leaderSelectorPtr()->supportsAppFrameRateOverrideByContent(); pacesetterSelectorPtr()->supportsAppFrameRateOverrideByContent(); return mFrameRateOverrideMappings .getFrameRateOverrideForUid(uid, supportsFrameRateOverrideByContent); } Loading @@ -192,7 +192,7 @@ impl::EventThread::ThrottleVsyncCallback Scheduler::makeThrottleVsyncCallback() impl::EventThread::GetVsyncPeriodFunction Scheduler::makeGetVsyncPeriodFunction() const { return [this](uid_t uid) { const Fps refreshRate = leaderSelectorPtr()->getActiveMode().fps; const Fps refreshRate = pacesetterSelectorPtr()->getActiveMode().fps; const nsecs_t currentPeriod = getVsyncSchedule()->period().ns() ?: refreshRate.getPeriodNsecs(); Loading Loading @@ -285,7 +285,7 @@ void Scheduler::enableSyntheticVsync(bool enable) { void Scheduler::onFrameRateOverridesChanged(ConnectionHandle handle, PhysicalDisplayId displayId) { const bool supportsFrameRateOverrideByContent = leaderSelectorPtr()->supportsAppFrameRateOverrideByContent(); pacesetterSelectorPtr()->supportsAppFrameRateOverrideByContent(); std::vector<FrameRateOverride> overrides = mFrameRateOverrideMappings.getAllFrameRateOverrides(supportsFrameRateOverrideByContent); Loading Loading @@ -326,7 +326,7 @@ void Scheduler::dispatchCachedReportedMode() { // If the mode is not the current mode, this means that a // mode change is in progress. In that case we shouldn't dispatch an event // as it will be dispatched when the current mode changes. if (leaderSelectorPtr()->getActiveMode() != mPolicy.modeOpt) { if (pacesetterSelectorPtr()->getActiveMode() != mPolicy.modeOpt) { return; } Loading Loading @@ -489,7 +489,7 @@ void Scheduler::deregisterLayer(Layer* layer) { void Scheduler::recordLayerHistory(Layer* layer, nsecs_t presentTime, LayerHistory::LayerUpdateType updateType) { if (leaderSelectorPtr()->canSwitch()) { if (pacesetterSelectorPtr()->canSwitch()) { mLayerHistory.record(layer, presentTime, systemTime(), updateType); } } Loading @@ -504,7 +504,7 @@ void Scheduler::setDefaultFrameRateCompatibility(Layer* layer) { } void Scheduler::chooseRefreshRateForContent() { const auto selectorPtr = leaderSelectorPtr(); const auto selectorPtr = pacesetterSelectorPtr(); if (!selectorPtr->canSwitch()) return; ATRACE_CALL(); Loading @@ -514,22 +514,22 @@ void Scheduler::chooseRefreshRateForContent() { } void Scheduler::resetIdleTimer() { leaderSelectorPtr()->resetIdleTimer(); pacesetterSelectorPtr()->resetIdleTimer(); } void Scheduler::onTouchHint() { if (mTouchTimer) { mTouchTimer->reset(); leaderSelectorPtr()->resetKernelIdleTimer(); pacesetterSelectorPtr()->resetKernelIdleTimer(); } } void Scheduler::setDisplayPowerMode(PhysicalDisplayId id, hal::PowerMode powerMode) { const bool isLeader = [this, id]() REQUIRES(kMainThreadContext) { const bool isPacesetter = [this, id]() REQUIRES(kMainThreadContext) { ftl::FakeGuard guard(mDisplayLock); return id == mLeaderDisplayId; return id == mPacesetterDisplayId; }(); if (isLeader) { if (isPacesetter) { // TODO (b/255657128): This needs to be handled per display. std::lock_guard<std::mutex> lock(mPolicyLock); mPolicy.displayPowerMode = powerMode; Loading @@ -539,7 +539,7 @@ void Scheduler::setDisplayPowerMode(PhysicalDisplayId id, hal::PowerMode powerMo auto vsyncSchedule = getVsyncScheduleLocked(id); vsyncSchedule->getController().setDisplayPowerMode(powerMode); } if (!isLeader) return; if (!isPacesetter) return; if (mDisplayPowerTimer) { mDisplayPowerTimer->reset(); Loading @@ -560,8 +560,8 @@ 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; LOG_ALWAYS_FATAL_IF(!mPacesetterDisplayId, "Missing a pacesetter!"); idOpt = mPacesetterDisplayId; } auto scheduleOpt = mVsyncSchedules.get(*idOpt); LOG_ALWAYS_FATAL_IF(!scheduleOpt); Loading @@ -573,7 +573,7 @@ void Scheduler::kernelIdleTimerCallback(TimerState state) { // TODO(145561154): cleanup the kernel idle timer implementation and the refresh rate // magic number const Fps refreshRate = leaderSelectorPtr()->getActiveMode().modePtr->getFps(); const Fps refreshRate = pacesetterSelectorPtr()->getActiveMode().modePtr->getFps(); constexpr Fps FPS_THRESHOLD_FOR_KERNEL_TIMER = 65_Hz; using namespace fps_approx_ops; Loading Loading @@ -637,7 +637,7 @@ void Scheduler::dump(utils::Dumper& dumper) const { { std::scoped_lock lock(mDisplayLock); ftl::FakeGuard guard(kMainThreadContext); dumper.dump("leaderDisplayId"sv, mLeaderDisplayId); dumper.dump("pacesetterDisplayId"sv, mPacesetterDisplayId); } dumper.dump("layerHistory"sv, mLayerHistory.dump()); dumper.dump("touchTimer"sv, mTouchTimer.transform(&OneShotTimer::interval)); Loading @@ -651,13 +651,13 @@ void Scheduler::dump(utils::Dumper& dumper) const { 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()); if (mPacesetterDisplayId) { base::StringAppendF(&out, "VsyncSchedule for pacesetter %s:\n", to_string(*mPacesetterDisplayId).c_str()); getVsyncScheduleLocked()->dump(out); } for (auto& [id, vsyncSchedule] : mVsyncSchedules) { if (id == mLeaderDisplayId) { if (id == mPacesetterDisplayId) { continue; } base::StringAppendF(&out, "VsyncSchedule for follower %s:\n", to_string(id).c_str()); Loading @@ -669,7 +669,7 @@ bool Scheduler::updateFrameRateOverrides(GlobalSignals consideredSignals, Fps di if (consideredSignals.idle) return false; const auto frameRateOverrides = leaderSelectorPtr()->getFrameRateOverrides(mPolicy.contentRequirements, pacesetterSelectorPtr()->getFrameRateOverrides(mPolicy.contentRequirements, displayRefreshRate, consideredSignals); // Note that RefreshRateSelector::supportsFrameRateOverrideByContent is checked when querying Loading @@ -677,23 +677,23 @@ bool Scheduler::updateFrameRateOverrides(GlobalSignals consideredSignals, Fps di return mFrameRateOverrideMappings.updateFrameRateOverridesByContent(frameRateOverrides); } void Scheduler::promoteLeaderDisplay(std::optional<PhysicalDisplayId> leaderIdOpt) { // TODO(b/241286431): Choose the leader display. mLeaderDisplayId = leaderIdOpt.value_or(mRefreshRateSelectors.begin()->first); ALOGI("Display %s is the leader", to_string(*mLeaderDisplayId).c_str()); void Scheduler::promotePacesetterDisplay(std::optional<PhysicalDisplayId> pacesetterIdOpt) { // TODO(b/241286431): Choose the pacesetter display. mPacesetterDisplayId = pacesetterIdOpt.value_or(mRefreshRateSelectors.begin()->first); ALOGI("Display %s is the pacesetter", to_string(*mPacesetterDisplayId).c_str()); auto vsyncSchedule = getVsyncScheduleLocked(*mLeaderDisplayId); if (const auto leaderPtr = leaderSelectorPtrLocked()) { leaderPtr->setIdleTimerCallbacks( auto vsyncSchedule = getVsyncScheduleLocked(*mPacesetterDisplayId); if (const auto pacesetterPtr = pacesetterSelectorPtrLocked()) { pacesetterPtr->setIdleTimerCallbacks( {.platform = {.onReset = [this] { idleTimerCallback(TimerState::Reset); }, .onExpired = [this] { idleTimerCallback(TimerState::Expired); }}, .kernel = {.onReset = [this] { kernelIdleTimerCallback(TimerState::Reset); }, .onExpired = [this] { kernelIdleTimerCallback(TimerState::Expired); }}}); leaderPtr->startIdleTimer(); pacesetterPtr->startIdleTimer(); const Fps refreshRate = leaderPtr->getActiveMode().modePtr->getFps(); const Fps refreshRate = pacesetterPtr->getActiveMode().modePtr->getFps(); vsyncSchedule->startPeriodTransition(mSchedulerCallback, refreshRate.getPeriod(), true /* force */); } Loading @@ -707,14 +707,14 @@ void Scheduler::promoteLeaderDisplay(std::optional<PhysicalDisplayId> leaderIdOp } } void Scheduler::demoteLeaderDisplay() { void Scheduler::demotePacesetterDisplay() { // No need to lock for reads on kMainThreadContext. if (const auto leaderPtr = FTL_FAKE_GUARD(mDisplayLock, leaderSelectorPtrLocked())) { leaderPtr->stopIdleTimer(); leaderPtr->clearIdleTimerCallbacks(); if (const auto pacesetterPtr = FTL_FAKE_GUARD(mDisplayLock, pacesetterSelectorPtrLocked())) { pacesetterPtr->stopIdleTimer(); pacesetterPtr->clearIdleTimerCallbacks(); } // Clear state that depends on the leader's RefreshRateSelector. // Clear state that depends on the pacesetter's RefreshRateSelector. std::scoped_lock lock(mPolicyLock); mPolicy = {}; } Loading Loading @@ -743,10 +743,11 @@ auto Scheduler::applyPolicy(S Policy::*statePtr, T&& newState) -> GlobalSignals modeChoices = chooseDisplayModes(); // TODO(b/240743786): The leader display's mode must change for any DisplayModeRequest // to go through. Fix this by tracking per-display Scheduler::Policy and timers. // TODO(b/240743786): The pacesetter display's mode must change for any // DisplayModeRequest to go through. Fix this by tracking per-display Scheduler::Policy // and timers. std::tie(modeOpt, consideredSignals) = modeChoices.get(*mLeaderDisplayId) modeChoices.get(*mPacesetterDisplayId) .transform([](const DisplayModeChoice& choice) { return std::make_pair(choice.mode, choice.consideredSignals); }) Loading Loading @@ -879,7 +880,7 @@ GlobalSignals Scheduler::makeGlobalSignals() const { FrameRateMode Scheduler::getPreferredDisplayMode() { std::lock_guard<std::mutex> lock(mPolicyLock); const auto frameRateMode = leaderSelectorPtr() pacesetterSelectorPtr() ->getRankedFrameRates(mPolicy.contentRequirements, makeGlobalSignals()) .ranking.front() .frameRateMode; Loading services/surfaceflinger/Scheduler/Scheduler.h +26 −26 Original line number Diff line number Diff line Loading @@ -102,8 +102,8 @@ public: void startTimers(); // TODO(b/241285191): Remove this API by promoting leader in onScreen{Acquired,Released}. void setLeaderDisplay(std::optional<PhysicalDisplayId>) REQUIRES(kMainThreadContext) // TODO(b/241285191): Remove this API by promoting pacesetter in onScreen{Acquired,Released}. void setPacesetterDisplay(std::optional<PhysicalDisplayId>) REQUIRES(kMainThreadContext) EXCLUDES(mDisplayLock); using RefreshRateSelectorPtr = std::shared_ptr<RefreshRateSelector>; Loading Loading @@ -167,9 +167,9 @@ public: const VsyncModulator& vsyncModulator() const { return *mVsyncModulator; } // In some cases, we should only modulate for the leader display. In those // In some cases, we should only modulate for the pacesetter display. In those // cases, the caller should pass in the relevant display, and the method // will no-op if it's not the leader. Other cases are not specific to a // will no-op if it's not the pacesetter. Other cases are not specific to a // display. template <typename... Args, typename Handler = std::optional<VsyncConfig> (VsyncModulator::*)(Args...)> Loading @@ -177,13 +177,13 @@ public: if (id) { std::scoped_lock lock(mDisplayLock); ftl::FakeGuard guard(kMainThreadContext); if (id != mLeaderDisplayId) { if (id != mPacesetterDisplayId) { return; } } if (const auto config = (*mVsyncModulator.*handler)(args...)) { setVsyncConfig(*config, getLeaderVsyncPeriod()); setVsyncConfig(*config, getPacesetterVsyncPeriod()); } } Loading Loading @@ -254,7 +254,7 @@ public: void dump(ConnectionHandle, std::string&) const; void dumpVsync(std::string&) const EXCLUDES(mDisplayLock); // Returns the preferred refresh rate and frame rate for the leader display. // Returns the preferred refresh rate and frame rate for the pacesetter display. FrameRateMode getPreferredDisplayMode(); // Notifies the scheduler about a refresh rate timeline change. Loading @@ -277,12 +277,12 @@ public: // Retrieves the overridden refresh rate for a given uid. std::optional<Fps> getFrameRateOverride(uid_t) const EXCLUDES(mDisplayLock); Period getLeaderVsyncPeriod() const EXCLUDES(mDisplayLock) { return leaderSelectorPtr()->getActiveMode().fps.getPeriod(); Period getPacesetterVsyncPeriod() const EXCLUDES(mDisplayLock) { return pacesetterSelectorPtr()->getActiveMode().fps.getPeriod(); } Fps getLeaderRefreshRate() const EXCLUDES(mDisplayLock) { return leaderSelectorPtr()->getActiveMode().fps; Fps getPacesetterRefreshRate() const EXCLUDES(mDisplayLock) { return pacesetterSelectorPtr()->getActiveMode().fps; } // Returns the framerate of the layer with the given sequence ID Loading Loading @@ -318,14 +318,14 @@ private: void resyncAllToHardwareVsync(bool allowToEnable) EXCLUDES(mDisplayLock); void setVsyncConfig(const VsyncConfig&, Period vsyncPeriod); // Chooses a leader among the registered displays, unless `leaderIdOpt` is specified. The new // `mLeaderDisplayId` is never `std::nullopt`. void promoteLeaderDisplay(std::optional<PhysicalDisplayId> leaderIdOpt = std::nullopt) // Chooses a pacesetter among the registered displays, unless `pacesetterIdOpt` is specified. // The new `mPacesetterDisplayId` is never `std::nullopt`. void promotePacesetterDisplay(std::optional<PhysicalDisplayId> pacesetterIdOpt = std::nullopt) REQUIRES(kMainThreadContext, mDisplayLock); // Blocks until the leader's idle timer thread exits. `mDisplayLock` must not be locked by the // caller on the main thread to avoid deadlock, since the timer thread locks it before exit. void demoteLeaderDisplay() REQUIRES(kMainThreadContext) EXCLUDES(mDisplayLock, mPolicyLock); // Blocks until the pacesetter's idle timer thread exits. `mDisplayLock` must not be locked by // 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) Loading Loading @@ -415,23 +415,23 @@ private: display::PhysicalDisplayMap<PhysicalDisplayId, std::shared_ptr<VsyncSchedule>> mVsyncSchedules GUARDED_BY(mDisplayLock) GUARDED_BY(kMainThreadContext); ftl::Optional<PhysicalDisplayId> mLeaderDisplayId GUARDED_BY(mDisplayLock) ftl::Optional<PhysicalDisplayId> mPacesetterDisplayId GUARDED_BY(mDisplayLock) GUARDED_BY(kMainThreadContext); RefreshRateSelectorPtr leaderSelectorPtr() const EXCLUDES(mDisplayLock) { RefreshRateSelectorPtr pacesetterSelectorPtr() const EXCLUDES(mDisplayLock) { std::scoped_lock lock(mDisplayLock); return leaderSelectorPtrLocked(); return pacesetterSelectorPtrLocked(); } RefreshRateSelectorPtr leaderSelectorPtrLocked() const REQUIRES(mDisplayLock) { RefreshRateSelectorPtr pacesetterSelectorPtrLocked() const REQUIRES(mDisplayLock) { ftl::FakeGuard guard(kMainThreadContext); const RefreshRateSelectorPtr noLeader; return mLeaderDisplayId .and_then([this](PhysicalDisplayId leaderId) const RefreshRateSelectorPtr noPacesetter; return mPacesetterDisplayId .and_then([this](PhysicalDisplayId pacesetterId) REQUIRES(mDisplayLock, kMainThreadContext) { return mRefreshRateSelectors.get(leaderId); return mRefreshRateSelectors.get(pacesetterId); }) .value_or(std::cref(noLeader)); .value_or(std::cref(noPacesetter)); } std::shared_ptr<const VsyncSchedule> getVsyncScheduleLocked( Loading Loading
services/surfaceflinger/DisplayDevice.cpp +5 −5 Original line number Diff line number Diff line Loading @@ -510,21 +510,21 @@ void DisplayDevice::clearDesiredActiveModeState() { mDesiredActiveModeChanged = false; } void DisplayDevice::adjustRefreshRate(Fps leaderDisplayRefreshRate) { void DisplayDevice::adjustRefreshRate(Fps pacesetterDisplayRefreshRate) { using fps_approx_ops::operator==; if (mRequestedRefreshRate == 0_Hz) { return; } using fps_approx_ops::operator>; if (mRequestedRefreshRate > leaderDisplayRefreshRate) { mAdjustedRefreshRate = leaderDisplayRefreshRate; if (mRequestedRefreshRate > pacesetterDisplayRefreshRate) { mAdjustedRefreshRate = pacesetterDisplayRefreshRate; return; } unsigned divisor = static_cast<unsigned>( std::round(leaderDisplayRefreshRate.getValue() / mRequestedRefreshRate.getValue())); mAdjustedRefreshRate = leaderDisplayRefreshRate / divisor; std::round(pacesetterDisplayRefreshRate.getValue() / mRequestedRefreshRate.getValue())); mAdjustedRefreshRate = pacesetterDisplayRefreshRate / divisor; } std::atomic<int32_t> DisplayDeviceState::sNextSequenceId(1); Loading
services/surfaceflinger/DisplayDevice.h +3 −3 Original line number Diff line number Diff line Loading @@ -247,9 +247,9 @@ public: Fps getAdjustedRefreshRate() const { return mAdjustedRefreshRate; } // Round the requested refresh rate to match a divisor of the leader // Round the requested refresh rate to match a divisor of the pacesetter // display's refresh rate. Only supported for virtual displays. void adjustRefreshRate(Fps leaderDisplayRefreshRate); void adjustRefreshRate(Fps pacesetterDisplayRefreshRate); // release HWC resources (if any) for removable displays void disconnect(); Loading Loading @@ -290,7 +290,7 @@ private: // for virtual displays to match this requested refresh rate. const Fps mRequestedRefreshRate; // Adjusted refresh rate, rounded to match a divisor of the leader // Adjusted refresh rate, rounded to match a divisor of the pacesetter // display's refresh rate. Only supported for virtual displays. Fps mAdjustedRefreshRate = 0_Hz; Loading
services/surfaceflinger/Layer.cpp +2 −1 Original line number Diff line number Diff line Loading @@ -196,7 +196,8 @@ Layer::Layer(const LayerCreationArgs& args) mDrawingState.color.b = -1.0_hf; } mFrameTracker.setDisplayRefreshPeriod(args.flinger->mScheduler->getLeaderVsyncPeriod().ns()); mFrameTracker.setDisplayRefreshPeriod( args.flinger->mScheduler->getPacesetterVsyncPeriod().ns()); mOwnerUid = args.ownerUid; mOwnerPid = args.ownerPid; Loading
services/surfaceflinger/Scheduler/Scheduler.cpp +49 −48 Original line number Diff line number Diff line Loading @@ -81,7 +81,7 @@ Scheduler::~Scheduler() { mTouchTimer.reset(); // Stop idle timer and clear callbacks, as the RefreshRateSelector may outlive the Scheduler. demoteLeaderDisplay(); demotePacesetterDisplay(); } void Scheduler::startTimers() { Loading @@ -106,11 +106,11 @@ void Scheduler::startTimers() { } } void Scheduler::setLeaderDisplay(std::optional<PhysicalDisplayId> leaderIdOpt) { demoteLeaderDisplay(); void Scheduler::setPacesetterDisplay(std::optional<PhysicalDisplayId> pacesetterIdOpt) { demotePacesetterDisplay(); std::scoped_lock lock(mDisplayLock); promoteLeaderDisplay(leaderIdOpt); promotePacesetterDisplay(pacesetterIdOpt); } void Scheduler::registerDisplay(PhysicalDisplayId displayId, RefreshRateSelectorPtr selectorPtr) { Loading @@ -121,17 +121,17 @@ void Scheduler::registerDisplay(PhysicalDisplayId displayId, RefreshRateSelector void Scheduler::registerDisplayInternal(PhysicalDisplayId displayId, RefreshRateSelectorPtr selectorPtr, std::shared_ptr<VsyncSchedule> vsyncSchedule) { demoteLeaderDisplay(); demotePacesetterDisplay(); std::scoped_lock lock(mDisplayLock); mRefreshRateSelectors.emplace_or_replace(displayId, std::move(selectorPtr)); mVsyncSchedules.emplace_or_replace(displayId, std::move(vsyncSchedule)); promoteLeaderDisplay(); promotePacesetterDisplay(); } void Scheduler::unregisterDisplay(PhysicalDisplayId displayId) { demoteLeaderDisplay(); demotePacesetterDisplay(); std::scoped_lock lock(mDisplayLock); mRefreshRateSelectors.erase(displayId); Loading @@ -142,7 +142,7 @@ void Scheduler::unregisterDisplay(PhysicalDisplayId displayId) { // headless virtual display.) LOG_ALWAYS_FATAL_IF(mRefreshRateSelectors.empty(), "Cannot unregister all displays!"); promoteLeaderDisplay(); promotePacesetterDisplay(); } void Scheduler::run() { Loading @@ -165,7 +165,7 @@ void Scheduler::onFrameSignal(ICompositor& compositor, VsyncId vsyncId, std::optional<Fps> Scheduler::getFrameRateOverride(uid_t uid) const { const bool supportsFrameRateOverrideByContent = leaderSelectorPtr()->supportsAppFrameRateOverrideByContent(); pacesetterSelectorPtr()->supportsAppFrameRateOverrideByContent(); return mFrameRateOverrideMappings .getFrameRateOverrideForUid(uid, supportsFrameRateOverrideByContent); } Loading @@ -192,7 +192,7 @@ impl::EventThread::ThrottleVsyncCallback Scheduler::makeThrottleVsyncCallback() impl::EventThread::GetVsyncPeriodFunction Scheduler::makeGetVsyncPeriodFunction() const { return [this](uid_t uid) { const Fps refreshRate = leaderSelectorPtr()->getActiveMode().fps; const Fps refreshRate = pacesetterSelectorPtr()->getActiveMode().fps; const nsecs_t currentPeriod = getVsyncSchedule()->period().ns() ?: refreshRate.getPeriodNsecs(); Loading Loading @@ -285,7 +285,7 @@ void Scheduler::enableSyntheticVsync(bool enable) { void Scheduler::onFrameRateOverridesChanged(ConnectionHandle handle, PhysicalDisplayId displayId) { const bool supportsFrameRateOverrideByContent = leaderSelectorPtr()->supportsAppFrameRateOverrideByContent(); pacesetterSelectorPtr()->supportsAppFrameRateOverrideByContent(); std::vector<FrameRateOverride> overrides = mFrameRateOverrideMappings.getAllFrameRateOverrides(supportsFrameRateOverrideByContent); Loading Loading @@ -326,7 +326,7 @@ void Scheduler::dispatchCachedReportedMode() { // If the mode is not the current mode, this means that a // mode change is in progress. In that case we shouldn't dispatch an event // as it will be dispatched when the current mode changes. if (leaderSelectorPtr()->getActiveMode() != mPolicy.modeOpt) { if (pacesetterSelectorPtr()->getActiveMode() != mPolicy.modeOpt) { return; } Loading Loading @@ -489,7 +489,7 @@ void Scheduler::deregisterLayer(Layer* layer) { void Scheduler::recordLayerHistory(Layer* layer, nsecs_t presentTime, LayerHistory::LayerUpdateType updateType) { if (leaderSelectorPtr()->canSwitch()) { if (pacesetterSelectorPtr()->canSwitch()) { mLayerHistory.record(layer, presentTime, systemTime(), updateType); } } Loading @@ -504,7 +504,7 @@ void Scheduler::setDefaultFrameRateCompatibility(Layer* layer) { } void Scheduler::chooseRefreshRateForContent() { const auto selectorPtr = leaderSelectorPtr(); const auto selectorPtr = pacesetterSelectorPtr(); if (!selectorPtr->canSwitch()) return; ATRACE_CALL(); Loading @@ -514,22 +514,22 @@ void Scheduler::chooseRefreshRateForContent() { } void Scheduler::resetIdleTimer() { leaderSelectorPtr()->resetIdleTimer(); pacesetterSelectorPtr()->resetIdleTimer(); } void Scheduler::onTouchHint() { if (mTouchTimer) { mTouchTimer->reset(); leaderSelectorPtr()->resetKernelIdleTimer(); pacesetterSelectorPtr()->resetKernelIdleTimer(); } } void Scheduler::setDisplayPowerMode(PhysicalDisplayId id, hal::PowerMode powerMode) { const bool isLeader = [this, id]() REQUIRES(kMainThreadContext) { const bool isPacesetter = [this, id]() REQUIRES(kMainThreadContext) { ftl::FakeGuard guard(mDisplayLock); return id == mLeaderDisplayId; return id == mPacesetterDisplayId; }(); if (isLeader) { if (isPacesetter) { // TODO (b/255657128): This needs to be handled per display. std::lock_guard<std::mutex> lock(mPolicyLock); mPolicy.displayPowerMode = powerMode; Loading @@ -539,7 +539,7 @@ void Scheduler::setDisplayPowerMode(PhysicalDisplayId id, hal::PowerMode powerMo auto vsyncSchedule = getVsyncScheduleLocked(id); vsyncSchedule->getController().setDisplayPowerMode(powerMode); } if (!isLeader) return; if (!isPacesetter) return; if (mDisplayPowerTimer) { mDisplayPowerTimer->reset(); Loading @@ -560,8 +560,8 @@ 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; LOG_ALWAYS_FATAL_IF(!mPacesetterDisplayId, "Missing a pacesetter!"); idOpt = mPacesetterDisplayId; } auto scheduleOpt = mVsyncSchedules.get(*idOpt); LOG_ALWAYS_FATAL_IF(!scheduleOpt); Loading @@ -573,7 +573,7 @@ void Scheduler::kernelIdleTimerCallback(TimerState state) { // TODO(145561154): cleanup the kernel idle timer implementation and the refresh rate // magic number const Fps refreshRate = leaderSelectorPtr()->getActiveMode().modePtr->getFps(); const Fps refreshRate = pacesetterSelectorPtr()->getActiveMode().modePtr->getFps(); constexpr Fps FPS_THRESHOLD_FOR_KERNEL_TIMER = 65_Hz; using namespace fps_approx_ops; Loading Loading @@ -637,7 +637,7 @@ void Scheduler::dump(utils::Dumper& dumper) const { { std::scoped_lock lock(mDisplayLock); ftl::FakeGuard guard(kMainThreadContext); dumper.dump("leaderDisplayId"sv, mLeaderDisplayId); dumper.dump("pacesetterDisplayId"sv, mPacesetterDisplayId); } dumper.dump("layerHistory"sv, mLayerHistory.dump()); dumper.dump("touchTimer"sv, mTouchTimer.transform(&OneShotTimer::interval)); Loading @@ -651,13 +651,13 @@ void Scheduler::dump(utils::Dumper& dumper) const { 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()); if (mPacesetterDisplayId) { base::StringAppendF(&out, "VsyncSchedule for pacesetter %s:\n", to_string(*mPacesetterDisplayId).c_str()); getVsyncScheduleLocked()->dump(out); } for (auto& [id, vsyncSchedule] : mVsyncSchedules) { if (id == mLeaderDisplayId) { if (id == mPacesetterDisplayId) { continue; } base::StringAppendF(&out, "VsyncSchedule for follower %s:\n", to_string(id).c_str()); Loading @@ -669,7 +669,7 @@ bool Scheduler::updateFrameRateOverrides(GlobalSignals consideredSignals, Fps di if (consideredSignals.idle) return false; const auto frameRateOverrides = leaderSelectorPtr()->getFrameRateOverrides(mPolicy.contentRequirements, pacesetterSelectorPtr()->getFrameRateOverrides(mPolicy.contentRequirements, displayRefreshRate, consideredSignals); // Note that RefreshRateSelector::supportsFrameRateOverrideByContent is checked when querying Loading @@ -677,23 +677,23 @@ bool Scheduler::updateFrameRateOverrides(GlobalSignals consideredSignals, Fps di return mFrameRateOverrideMappings.updateFrameRateOverridesByContent(frameRateOverrides); } void Scheduler::promoteLeaderDisplay(std::optional<PhysicalDisplayId> leaderIdOpt) { // TODO(b/241286431): Choose the leader display. mLeaderDisplayId = leaderIdOpt.value_or(mRefreshRateSelectors.begin()->first); ALOGI("Display %s is the leader", to_string(*mLeaderDisplayId).c_str()); void Scheduler::promotePacesetterDisplay(std::optional<PhysicalDisplayId> pacesetterIdOpt) { // TODO(b/241286431): Choose the pacesetter display. mPacesetterDisplayId = pacesetterIdOpt.value_or(mRefreshRateSelectors.begin()->first); ALOGI("Display %s is the pacesetter", to_string(*mPacesetterDisplayId).c_str()); auto vsyncSchedule = getVsyncScheduleLocked(*mLeaderDisplayId); if (const auto leaderPtr = leaderSelectorPtrLocked()) { leaderPtr->setIdleTimerCallbacks( auto vsyncSchedule = getVsyncScheduleLocked(*mPacesetterDisplayId); if (const auto pacesetterPtr = pacesetterSelectorPtrLocked()) { pacesetterPtr->setIdleTimerCallbacks( {.platform = {.onReset = [this] { idleTimerCallback(TimerState::Reset); }, .onExpired = [this] { idleTimerCallback(TimerState::Expired); }}, .kernel = {.onReset = [this] { kernelIdleTimerCallback(TimerState::Reset); }, .onExpired = [this] { kernelIdleTimerCallback(TimerState::Expired); }}}); leaderPtr->startIdleTimer(); pacesetterPtr->startIdleTimer(); const Fps refreshRate = leaderPtr->getActiveMode().modePtr->getFps(); const Fps refreshRate = pacesetterPtr->getActiveMode().modePtr->getFps(); vsyncSchedule->startPeriodTransition(mSchedulerCallback, refreshRate.getPeriod(), true /* force */); } Loading @@ -707,14 +707,14 @@ void Scheduler::promoteLeaderDisplay(std::optional<PhysicalDisplayId> leaderIdOp } } void Scheduler::demoteLeaderDisplay() { void Scheduler::demotePacesetterDisplay() { // No need to lock for reads on kMainThreadContext. if (const auto leaderPtr = FTL_FAKE_GUARD(mDisplayLock, leaderSelectorPtrLocked())) { leaderPtr->stopIdleTimer(); leaderPtr->clearIdleTimerCallbacks(); if (const auto pacesetterPtr = FTL_FAKE_GUARD(mDisplayLock, pacesetterSelectorPtrLocked())) { pacesetterPtr->stopIdleTimer(); pacesetterPtr->clearIdleTimerCallbacks(); } // Clear state that depends on the leader's RefreshRateSelector. // Clear state that depends on the pacesetter's RefreshRateSelector. std::scoped_lock lock(mPolicyLock); mPolicy = {}; } Loading Loading @@ -743,10 +743,11 @@ auto Scheduler::applyPolicy(S Policy::*statePtr, T&& newState) -> GlobalSignals modeChoices = chooseDisplayModes(); // TODO(b/240743786): The leader display's mode must change for any DisplayModeRequest // to go through. Fix this by tracking per-display Scheduler::Policy and timers. // TODO(b/240743786): The pacesetter display's mode must change for any // DisplayModeRequest to go through. Fix this by tracking per-display Scheduler::Policy // and timers. std::tie(modeOpt, consideredSignals) = modeChoices.get(*mLeaderDisplayId) modeChoices.get(*mPacesetterDisplayId) .transform([](const DisplayModeChoice& choice) { return std::make_pair(choice.mode, choice.consideredSignals); }) Loading Loading @@ -879,7 +880,7 @@ GlobalSignals Scheduler::makeGlobalSignals() const { FrameRateMode Scheduler::getPreferredDisplayMode() { std::lock_guard<std::mutex> lock(mPolicyLock); const auto frameRateMode = leaderSelectorPtr() pacesetterSelectorPtr() ->getRankedFrameRates(mPolicy.contentRequirements, makeGlobalSignals()) .ranking.front() .frameRateMode; Loading
services/surfaceflinger/Scheduler/Scheduler.h +26 −26 Original line number Diff line number Diff line Loading @@ -102,8 +102,8 @@ public: void startTimers(); // TODO(b/241285191): Remove this API by promoting leader in onScreen{Acquired,Released}. void setLeaderDisplay(std::optional<PhysicalDisplayId>) REQUIRES(kMainThreadContext) // TODO(b/241285191): Remove this API by promoting pacesetter in onScreen{Acquired,Released}. void setPacesetterDisplay(std::optional<PhysicalDisplayId>) REQUIRES(kMainThreadContext) EXCLUDES(mDisplayLock); using RefreshRateSelectorPtr = std::shared_ptr<RefreshRateSelector>; Loading Loading @@ -167,9 +167,9 @@ public: const VsyncModulator& vsyncModulator() const { return *mVsyncModulator; } // In some cases, we should only modulate for the leader display. In those // In some cases, we should only modulate for the pacesetter display. In those // cases, the caller should pass in the relevant display, and the method // will no-op if it's not the leader. Other cases are not specific to a // will no-op if it's not the pacesetter. Other cases are not specific to a // display. template <typename... Args, typename Handler = std::optional<VsyncConfig> (VsyncModulator::*)(Args...)> Loading @@ -177,13 +177,13 @@ public: if (id) { std::scoped_lock lock(mDisplayLock); ftl::FakeGuard guard(kMainThreadContext); if (id != mLeaderDisplayId) { if (id != mPacesetterDisplayId) { return; } } if (const auto config = (*mVsyncModulator.*handler)(args...)) { setVsyncConfig(*config, getLeaderVsyncPeriod()); setVsyncConfig(*config, getPacesetterVsyncPeriod()); } } Loading Loading @@ -254,7 +254,7 @@ public: void dump(ConnectionHandle, std::string&) const; void dumpVsync(std::string&) const EXCLUDES(mDisplayLock); // Returns the preferred refresh rate and frame rate for the leader display. // Returns the preferred refresh rate and frame rate for the pacesetter display. FrameRateMode getPreferredDisplayMode(); // Notifies the scheduler about a refresh rate timeline change. Loading @@ -277,12 +277,12 @@ public: // Retrieves the overridden refresh rate for a given uid. std::optional<Fps> getFrameRateOverride(uid_t) const EXCLUDES(mDisplayLock); Period getLeaderVsyncPeriod() const EXCLUDES(mDisplayLock) { return leaderSelectorPtr()->getActiveMode().fps.getPeriod(); Period getPacesetterVsyncPeriod() const EXCLUDES(mDisplayLock) { return pacesetterSelectorPtr()->getActiveMode().fps.getPeriod(); } Fps getLeaderRefreshRate() const EXCLUDES(mDisplayLock) { return leaderSelectorPtr()->getActiveMode().fps; Fps getPacesetterRefreshRate() const EXCLUDES(mDisplayLock) { return pacesetterSelectorPtr()->getActiveMode().fps; } // Returns the framerate of the layer with the given sequence ID Loading Loading @@ -318,14 +318,14 @@ private: void resyncAllToHardwareVsync(bool allowToEnable) EXCLUDES(mDisplayLock); void setVsyncConfig(const VsyncConfig&, Period vsyncPeriod); // Chooses a leader among the registered displays, unless `leaderIdOpt` is specified. The new // `mLeaderDisplayId` is never `std::nullopt`. void promoteLeaderDisplay(std::optional<PhysicalDisplayId> leaderIdOpt = std::nullopt) // Chooses a pacesetter among the registered displays, unless `pacesetterIdOpt` is specified. // The new `mPacesetterDisplayId` is never `std::nullopt`. void promotePacesetterDisplay(std::optional<PhysicalDisplayId> pacesetterIdOpt = std::nullopt) REQUIRES(kMainThreadContext, mDisplayLock); // Blocks until the leader's idle timer thread exits. `mDisplayLock` must not be locked by the // caller on the main thread to avoid deadlock, since the timer thread locks it before exit. void demoteLeaderDisplay() REQUIRES(kMainThreadContext) EXCLUDES(mDisplayLock, mPolicyLock); // Blocks until the pacesetter's idle timer thread exits. `mDisplayLock` must not be locked by // 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) Loading Loading @@ -415,23 +415,23 @@ private: display::PhysicalDisplayMap<PhysicalDisplayId, std::shared_ptr<VsyncSchedule>> mVsyncSchedules GUARDED_BY(mDisplayLock) GUARDED_BY(kMainThreadContext); ftl::Optional<PhysicalDisplayId> mLeaderDisplayId GUARDED_BY(mDisplayLock) ftl::Optional<PhysicalDisplayId> mPacesetterDisplayId GUARDED_BY(mDisplayLock) GUARDED_BY(kMainThreadContext); RefreshRateSelectorPtr leaderSelectorPtr() const EXCLUDES(mDisplayLock) { RefreshRateSelectorPtr pacesetterSelectorPtr() const EXCLUDES(mDisplayLock) { std::scoped_lock lock(mDisplayLock); return leaderSelectorPtrLocked(); return pacesetterSelectorPtrLocked(); } RefreshRateSelectorPtr leaderSelectorPtrLocked() const REQUIRES(mDisplayLock) { RefreshRateSelectorPtr pacesetterSelectorPtrLocked() const REQUIRES(mDisplayLock) { ftl::FakeGuard guard(kMainThreadContext); const RefreshRateSelectorPtr noLeader; return mLeaderDisplayId .and_then([this](PhysicalDisplayId leaderId) const RefreshRateSelectorPtr noPacesetter; return mPacesetterDisplayId .and_then([this](PhysicalDisplayId pacesetterId) REQUIRES(mDisplayLock, kMainThreadContext) { return mRefreshRateSelectors.get(leaderId); return mRefreshRateSelectors.get(pacesetterId); }) .value_or(std::cref(noLeader)); .value_or(std::cref(noPacesetter)); } std::shared_ptr<const VsyncSchedule> getVsyncScheduleLocked( Loading