Loading services/surfaceflinger/Scheduler/Scheduler.cpp +128 −11 Original line number Diff line number Diff line Loading @@ -57,6 +57,39 @@ } \ } while (false) namespace { using android::Fps; using android::FpsApproxEqual; using android::FpsHash; using android::scheduler::AggregatedFpsScore; using android::scheduler::RefreshRateRankingsAndSignals; // Returns the aggregated score per Fps for the RefreshRateRankingsAndSignals sourced. auto getAggregatedScoresPerFps( const std::vector<RefreshRateRankingsAndSignals>& refreshRateRankingsAndSignalsPerDisplay) -> std::unordered_map<Fps, AggregatedFpsScore, FpsHash, FpsApproxEqual> { std::unordered_map<Fps, AggregatedFpsScore, FpsHash, FpsApproxEqual> aggregatedScoresPerFps; for (const auto& refreshRateRankingsAndSignal : refreshRateRankingsAndSignalsPerDisplay) { const auto& refreshRateRankings = refreshRateRankingsAndSignal.refreshRateRankings; std::for_each(refreshRateRankings.begin(), refreshRateRankings.end(), [&](const auto& it) { const auto [score, result] = aggregatedScoresPerFps.try_emplace(it.displayModePtr->getFps(), AggregatedFpsScore{it.score, /* numDisplays */ 1}); if (!result) { // update score->second.totalScore += it.score; score->second.numDisplays++; } }); } return aggregatedScoresPerFps; } } // namespace namespace android::scheduler { Scheduler::Scheduler(ICompositor& compositor, ISchedulerCallback& callback, FeatureFlags features) Loading Loading @@ -662,6 +695,7 @@ template <typename S, typename T> auto Scheduler::applyPolicy(S Policy::*statePtr, T&& newState) -> GlobalSignals { DisplayModePtr newMode; GlobalSignals consideredSignals; std::vector<DisplayModeConfig> displayModeConfigs; bool refreshRateChanged = false; bool frameRateOverridesChanged; Loading @@ -674,9 +708,27 @@ auto Scheduler::applyPolicy(S Policy::*statePtr, T&& newState) -> GlobalSignals if (currentState == newState) return {}; currentState = std::forward<T>(newState); const auto [rankings, signals] = getRankedDisplayModes(); newMode = rankings.front().displayModePtr; consideredSignals = signals; displayModeConfigs = getBestDisplayModeConfigs(); // mPolicy holds the current mode, using the current mode we find out // what display is currently being tracked through the policy and // then find the DisplayModeConfig for that display. So that // later we check if the policy mode has changed for the same display in policy. // If mPolicy mode isn't available then we take the first display from the best display // modes as the candidate for policy changes and frame rate overrides. // TODO(b/240743786) Update the single display based assumptions and make mode changes // and mPolicy per display. const DisplayModeConfig& displayModeConfigForCurrentPolicy = mPolicy.mode ? *std::find_if(displayModeConfigs.begin(), displayModeConfigs.end(), [&](const auto& displayModeConfig) REQUIRES(mPolicyLock) { return displayModeConfig.displayModePtr ->getPhysicalDisplayId() == mPolicy.mode->getPhysicalDisplayId(); }) : displayModeConfigs.front(); newMode = displayModeConfigForCurrentPolicy.displayModePtr; consideredSignals = displayModeConfigForCurrentPolicy.signals; frameRateOverridesChanged = updateFrameRateOverrides(consideredSignals, newMode->getFps()); if (mPolicy.mode == newMode) { Loading @@ -691,9 +743,7 @@ auto Scheduler::applyPolicy(S Policy::*statePtr, T&& newState) -> GlobalSignals } } if (refreshRateChanged) { mSchedulerCallback.requestDisplayMode(std::move(newMode), consideredSignals.idle ? DisplayModeEvent::None : DisplayModeEvent::Changed); mSchedulerCallback.requestDisplayModes(std::move(displayModeConfigs)); } if (frameRateOverridesChanged) { mSchedulerCallback.triggerOnFrameRateOverridesChanged(); Loading @@ -701,12 +751,68 @@ auto Scheduler::applyPolicy(S Policy::*statePtr, T&& newState) -> GlobalSignals return consideredSignals; } auto Scheduler::getRankedDisplayModes() -> std::pair<std::vector<RefreshRateRanking>, GlobalSignals> { void Scheduler::registerDisplay(const sp<const DisplayDevice>& display) { const bool ok = mDisplays.try_emplace(display->getPhysicalId(), display).second; ALOGE_IF(!ok, "Duplicate display registered"); } void Scheduler::unregisterDisplay(PhysicalDisplayId displayId) { mDisplays.erase(displayId); } std::vector<DisplayModeConfig> Scheduler::getBestDisplayModeConfigs() const { ATRACE_CALL(); const auto configs = holdRefreshRateConfigs(); std::vector<RefreshRateRankingsAndSignals> refreshRateRankingsAndSignalsPerDisplay; refreshRateRankingsAndSignalsPerDisplay.reserve(mDisplays.size()); const auto displayModeSelectionParams = getDisplayModeSelectionParams(); std::for_each(mDisplays.begin(), mDisplays.end(), [&](const auto& display) { const auto& [refreshRateRankings, globalSignals] = display.second->holdRefreshRateConfigs() ->getRankedRefreshRates(displayModeSelectionParams.layerRequirements, displayModeSelectionParams.globalSignals); refreshRateRankingsAndSignalsPerDisplay.emplace_back( RefreshRateRankingsAndSignals{refreshRateRankings, globalSignals}); }); // FPS and their Aggregated score. std::unordered_map<Fps, AggregatedFpsScore, FpsHash, FpsApproxEqual> aggregatedScoresPerFps = getAggregatedScoresPerFps(refreshRateRankingsAndSignalsPerDisplay); Fps chosenFps = std::max_element(aggregatedScoresPerFps.begin(), aggregatedScoresPerFps.end(), [](const auto& max, const auto& current) { return max.second.totalScore <= current.second.totalScore; }) ->first; return getDisplayModeConfigsForTheChosenFps(chosenFps, refreshRateRankingsAndSignalsPerDisplay); } std::vector<DisplayModeConfig> Scheduler::getDisplayModeConfigsForTheChosenFps( Fps chosenFps, const std::vector<RefreshRateRankingsAndSignals>& refreshRateRankingsAndSignalsPerDisplay) const { std::vector<DisplayModeConfig> displayModeConfigs; displayModeConfigs.reserve(mDisplays.size()); using fps_approx_ops::operator==; std::for_each(refreshRateRankingsAndSignalsPerDisplay.begin(), refreshRateRankingsAndSignalsPerDisplay.end(), [&](const auto& refreshRateRankingsAndSignal) { for (const auto& ranking : refreshRateRankingsAndSignal.refreshRateRankings) { if (ranking.displayModePtr->getFps() == chosenFps) { displayModeConfigs.emplace_back( DisplayModeConfig{refreshRateRankingsAndSignal.globalSignals, ranking.displayModePtr}); break; } } }); return displayModeConfigs; } DisplayModeSelectionParams Scheduler::getDisplayModeSelectionParams() const { const bool powerOnImminent = mDisplayPowerTimer && (mPolicy.displayPowerMode != hal::PowerMode::ON || mPolicy.displayPowerTimer == TimerState::Reset); Loading @@ -715,7 +821,18 @@ auto Scheduler::getRankedDisplayModes() .idle = mPolicy.idleTimer == TimerState::Expired, .powerOnImminent = powerOnImminent}; return configs->getRankedRefreshRates(mPolicy.contentRequirements, signals); return {mPolicy.contentRequirements, signals}; } auto Scheduler::getRankedDisplayModes() -> std::pair<std::vector<RefreshRateRanking>, GlobalSignals> { ATRACE_CALL(); const auto configs = holdRefreshRateConfigs(); const auto displayModeSelectionParams = getDisplayModeSelectionParams(); return configs->getRankedRefreshRates(displayModeSelectionParams.layerRequirements, displayModeSelectionParams.globalSignals); } DisplayModePtr Scheduler::getPreferredDisplayMode() { Loading services/surfaceflinger/Scheduler/Scheduler.h +52 −3 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ #include <mutex> #include <optional> #include <unordered_map> #include <utility> // TODO(b/129481165): remove the #pragma below and fix conversion issues #pragma clang diagnostic push Loading @@ -32,9 +33,11 @@ #include <ui/GraphicTypes.h> #pragma clang diagnostic pop // ignored "-Wconversion -Wextra" #include <DisplayDevice.h> #include <scheduler/Features.h> #include <scheduler/Time.h> #include "Display/DisplayMap.h" #include "EventThread.h" #include "FrameRateOverrideMappings.h" #include "LayerHistory.h" Loading Loading @@ -83,11 +86,22 @@ class TokenManager; namespace scheduler { using GlobalSignals = RefreshRateConfigs::GlobalSignals; // Config representing the DisplayMode and considered signals for the Display. struct DisplayModeConfig { const GlobalSignals signals; const DisplayModePtr displayModePtr; DisplayModeConfig(GlobalSignals signals, DisplayModePtr displayModePtr) : signals(signals), displayModePtr(std::move(displayModePtr)) {} }; struct ISchedulerCallback { using DisplayModeEvent = scheduler::DisplayModeEvent; virtual void setVsyncEnabled(bool) = 0; virtual void requestDisplayMode(DisplayModePtr, DisplayModeEvent) = 0; virtual void requestDisplayModes(std::vector<DisplayModeConfig>) = 0; virtual void kernelTimerChanged(bool expired) = 0; virtual void triggerOnFrameRateOverridesChanged() = 0; Loading @@ -95,6 +109,25 @@ protected: ~ISchedulerCallback() = default; }; // Holds the total score of the FPS and // number of displays the FPS is found in. struct AggregatedFpsScore { float totalScore; size_t numDisplays; }; // Represents LayerRequirements and GlobalSignals to be considered for the display mode selection. struct DisplayModeSelectionParams { std::vector<RefreshRateConfigs::LayerRequirement> layerRequirements; GlobalSignals globalSignals; }; // Represents the RefreshRateRankings and GlobalSignals for the selected RefreshRateRankings. struct RefreshRateRankingsAndSignals { std::vector<RefreshRateRanking> refreshRateRankings; GlobalSignals globalSignals; }; class Scheduler : android::impl::MessageQueue { using Impl = android::impl::MessageQueue; Loading Loading @@ -237,6 +270,9 @@ public: return mLayerHistory.getLayerFramerate(now, id); } void registerDisplay(const sp<const DisplayDevice>&); void unregisterDisplay(PhysicalDisplayId); private: friend class TestableScheduler; Loading @@ -260,8 +296,6 @@ private: void setVsyncPeriod(nsecs_t period); using GlobalSignals = RefreshRateConfigs::GlobalSignals; struct Policy; // Sets the S state of the policy to the T value under mPolicyLock, and chooses a display mode Loading @@ -274,6 +308,17 @@ private: std::pair<std::vector<RefreshRateRanking>, GlobalSignals> getRankedDisplayModes() REQUIRES(mPolicyLock); // Returns the best display mode per display. std::vector<DisplayModeConfig> getBestDisplayModeConfigs() const REQUIRES(mPolicyLock); // Returns the list of DisplayModeConfigs per display for the chosenFps. std::vector<DisplayModeConfig> getDisplayModeConfigsForTheChosenFps( Fps chosenFps, const std::vector<RefreshRateRankingsAndSignals>&) const; // Returns the DisplayModeSelectionParams to be considered for the // DisplayMode selection based on the current Policy and GlobalSignals. DisplayModeSelectionParams getDisplayModeSelectionParams() const REQUIRES(mPolicyLock); bool updateFrameRateOverrides(GlobalSignals, Fps displayRefreshRate) REQUIRES(mPolicyLock); void dispatchCachedReportedMode() REQUIRES(mPolicyLock) EXCLUDES(mRefreshRateConfigsLock); Loading Loading @@ -323,6 +368,10 @@ private: mutable std::mutex mPolicyLock; // Holds the Physical displays registered through the SurfaceFlinger, used for making // the refresh rate selections. display::PhysicalDisplayMap<PhysicalDisplayId, const sp<const DisplayDevice>> mDisplays; struct Policy { // Policy for choosing the display mode. LayerHistory::Summary contentRequirements; Loading services/surfaceflinger/Scheduler/include/scheduler/Fps.h +4 −0 Original line number Diff line number Diff line Loading @@ -138,6 +138,10 @@ struct FpsApproxEqual { bool operator()(Fps lhs, Fps rhs) const { return isApproxEqual(lhs, rhs); } }; struct FpsHash { size_t operator()(Fps fps) const { return std::hash<nsecs_t>()(fps.getPeriodNsecs()); } }; inline std::string to_string(Fps fps) { return base::StringPrintf("%.2f Hz", fps.getValue()); } Loading services/surfaceflinger/SurfaceFlinger.cpp +27 −14 Original line number Diff line number Diff line Loading @@ -2938,7 +2938,7 @@ void SurfaceFlinger::processDisplayAdded(const wp<IBinder>& displayToken, if (display->isPrimary()) { mScheduler->setRefreshRateConfigs(display->holdRefreshRateConfigs()); } mScheduler->registerDisplay(display); dispatchDisplayHotplugEvent(display->getPhysicalId(), true); } Loading @@ -2954,6 +2954,7 @@ void SurfaceFlinger::processDisplayRemoved(const wp<IBinder>& displayToken) { releaseVirtualDisplay(display->getVirtualId()); } else { dispatchDisplayHotplugEvent(display->getPhysicalId(), false); mScheduler->unregisterDisplay(display->getPhysicalId()); } } Loading Loading @@ -2990,6 +2991,8 @@ void SurfaceFlinger::processDisplayChanged(const wp<IBinder>& displayToken, display->disconnect(); if (display->isVirtual()) { releaseVirtualDisplay(display->getVirtualId()); } else { mScheduler->unregisterDisplay(display->getPhysicalId()); } } Loading Loading @@ -3319,25 +3322,34 @@ void SurfaceFlinger::updateCursorAsync() { mCompositionEngine->updateCursorAsync(refreshArgs); } void SurfaceFlinger::requestDisplayMode(DisplayModePtr mode, DisplayModeEvent event) { void SurfaceFlinger::requestDisplayModes( std::vector<scheduler::DisplayModeConfig> displayModeConfigs) { if (mBootStage != BootStage::FINISHED) { ALOGV("Currently in the boot stage, skipping display mode changes"); return; } ATRACE_CALL(); // If this is called from the main thread mStateLock must be locked before // Currently the only way to call this function from the main thread is from // Scheduler::chooseRefreshRateForContent ConditionalLock lock(mStateLock, std::this_thread::get_id() != mMainThreadId); const auto display = getDefaultDisplayDeviceLocked(); if (!display || mBootStage != BootStage::FINISHED) { return; } ATRACE_CALL(); if (!display->refreshRateConfigs().isModeAllowed(mode->getId())) { ALOGV("Skipping disallowed mode %d", mode->getId().value()); return; std::for_each(displayModeConfigs.begin(), displayModeConfigs.end(), [&](const auto& config) REQUIRES(mStateLock) { const auto& displayModePtr = config.displayModePtr; if (const auto display = getDisplayDeviceLocked(displayModePtr->getPhysicalDisplayId()); display->refreshRateConfigs().isModeAllowed(displayModePtr->getId())) { const auto event = config.signals.idle ? DisplayModeEvent::None : DisplayModeEvent::Changed; setDesiredActiveMode({displayModePtr, event}); } else { ALOGV("Skipping disallowed mode %d for display %" PRId64, displayModePtr->getId().value(), display->getPhysicalId().value); } setDesiredActiveMode({std::move(mode), event}); }); } void SurfaceFlinger::triggerOnFrameRateOverridesChanged() { Loading Loading @@ -3386,6 +3398,7 @@ void SurfaceFlinger::initScheduler(const sp<const DisplayDevice>& display) { mScheduler->createVsyncSchedule(features); mScheduler->setRefreshRateConfigs(std::move(configs)); mScheduler->registerDisplay(display); } setVsyncEnabled(false); mScheduler->startTimers(); Loading services/surfaceflinger/SurfaceFlinger.h +2 −2 Original line number Diff line number Diff line Loading @@ -631,8 +631,8 @@ private: // Toggles hardware VSYNC by calling into HWC. void setVsyncEnabled(bool) override; // Sets the desired display mode if allowed by policy. void requestDisplayMode(DisplayModePtr, DisplayModeEvent) override; // Sets the desired display mode per display if allowed by policy . void requestDisplayModes(std::vector<scheduler::DisplayModeConfig>) override; // Called when kernel idle timer has expired. Used to update the refresh rate overlay. void kernelTimerChanged(bool expired) override; // Called when the frame rate override list changed to trigger an event. Loading Loading
services/surfaceflinger/Scheduler/Scheduler.cpp +128 −11 Original line number Diff line number Diff line Loading @@ -57,6 +57,39 @@ } \ } while (false) namespace { using android::Fps; using android::FpsApproxEqual; using android::FpsHash; using android::scheduler::AggregatedFpsScore; using android::scheduler::RefreshRateRankingsAndSignals; // Returns the aggregated score per Fps for the RefreshRateRankingsAndSignals sourced. auto getAggregatedScoresPerFps( const std::vector<RefreshRateRankingsAndSignals>& refreshRateRankingsAndSignalsPerDisplay) -> std::unordered_map<Fps, AggregatedFpsScore, FpsHash, FpsApproxEqual> { std::unordered_map<Fps, AggregatedFpsScore, FpsHash, FpsApproxEqual> aggregatedScoresPerFps; for (const auto& refreshRateRankingsAndSignal : refreshRateRankingsAndSignalsPerDisplay) { const auto& refreshRateRankings = refreshRateRankingsAndSignal.refreshRateRankings; std::for_each(refreshRateRankings.begin(), refreshRateRankings.end(), [&](const auto& it) { const auto [score, result] = aggregatedScoresPerFps.try_emplace(it.displayModePtr->getFps(), AggregatedFpsScore{it.score, /* numDisplays */ 1}); if (!result) { // update score->second.totalScore += it.score; score->second.numDisplays++; } }); } return aggregatedScoresPerFps; } } // namespace namespace android::scheduler { Scheduler::Scheduler(ICompositor& compositor, ISchedulerCallback& callback, FeatureFlags features) Loading Loading @@ -662,6 +695,7 @@ template <typename S, typename T> auto Scheduler::applyPolicy(S Policy::*statePtr, T&& newState) -> GlobalSignals { DisplayModePtr newMode; GlobalSignals consideredSignals; std::vector<DisplayModeConfig> displayModeConfigs; bool refreshRateChanged = false; bool frameRateOverridesChanged; Loading @@ -674,9 +708,27 @@ auto Scheduler::applyPolicy(S Policy::*statePtr, T&& newState) -> GlobalSignals if (currentState == newState) return {}; currentState = std::forward<T>(newState); const auto [rankings, signals] = getRankedDisplayModes(); newMode = rankings.front().displayModePtr; consideredSignals = signals; displayModeConfigs = getBestDisplayModeConfigs(); // mPolicy holds the current mode, using the current mode we find out // what display is currently being tracked through the policy and // then find the DisplayModeConfig for that display. So that // later we check if the policy mode has changed for the same display in policy. // If mPolicy mode isn't available then we take the first display from the best display // modes as the candidate for policy changes and frame rate overrides. // TODO(b/240743786) Update the single display based assumptions and make mode changes // and mPolicy per display. const DisplayModeConfig& displayModeConfigForCurrentPolicy = mPolicy.mode ? *std::find_if(displayModeConfigs.begin(), displayModeConfigs.end(), [&](const auto& displayModeConfig) REQUIRES(mPolicyLock) { return displayModeConfig.displayModePtr ->getPhysicalDisplayId() == mPolicy.mode->getPhysicalDisplayId(); }) : displayModeConfigs.front(); newMode = displayModeConfigForCurrentPolicy.displayModePtr; consideredSignals = displayModeConfigForCurrentPolicy.signals; frameRateOverridesChanged = updateFrameRateOverrides(consideredSignals, newMode->getFps()); if (mPolicy.mode == newMode) { Loading @@ -691,9 +743,7 @@ auto Scheduler::applyPolicy(S Policy::*statePtr, T&& newState) -> GlobalSignals } } if (refreshRateChanged) { mSchedulerCallback.requestDisplayMode(std::move(newMode), consideredSignals.idle ? DisplayModeEvent::None : DisplayModeEvent::Changed); mSchedulerCallback.requestDisplayModes(std::move(displayModeConfigs)); } if (frameRateOverridesChanged) { mSchedulerCallback.triggerOnFrameRateOverridesChanged(); Loading @@ -701,12 +751,68 @@ auto Scheduler::applyPolicy(S Policy::*statePtr, T&& newState) -> GlobalSignals return consideredSignals; } auto Scheduler::getRankedDisplayModes() -> std::pair<std::vector<RefreshRateRanking>, GlobalSignals> { void Scheduler::registerDisplay(const sp<const DisplayDevice>& display) { const bool ok = mDisplays.try_emplace(display->getPhysicalId(), display).second; ALOGE_IF(!ok, "Duplicate display registered"); } void Scheduler::unregisterDisplay(PhysicalDisplayId displayId) { mDisplays.erase(displayId); } std::vector<DisplayModeConfig> Scheduler::getBestDisplayModeConfigs() const { ATRACE_CALL(); const auto configs = holdRefreshRateConfigs(); std::vector<RefreshRateRankingsAndSignals> refreshRateRankingsAndSignalsPerDisplay; refreshRateRankingsAndSignalsPerDisplay.reserve(mDisplays.size()); const auto displayModeSelectionParams = getDisplayModeSelectionParams(); std::for_each(mDisplays.begin(), mDisplays.end(), [&](const auto& display) { const auto& [refreshRateRankings, globalSignals] = display.second->holdRefreshRateConfigs() ->getRankedRefreshRates(displayModeSelectionParams.layerRequirements, displayModeSelectionParams.globalSignals); refreshRateRankingsAndSignalsPerDisplay.emplace_back( RefreshRateRankingsAndSignals{refreshRateRankings, globalSignals}); }); // FPS and their Aggregated score. std::unordered_map<Fps, AggregatedFpsScore, FpsHash, FpsApproxEqual> aggregatedScoresPerFps = getAggregatedScoresPerFps(refreshRateRankingsAndSignalsPerDisplay); Fps chosenFps = std::max_element(aggregatedScoresPerFps.begin(), aggregatedScoresPerFps.end(), [](const auto& max, const auto& current) { return max.second.totalScore <= current.second.totalScore; }) ->first; return getDisplayModeConfigsForTheChosenFps(chosenFps, refreshRateRankingsAndSignalsPerDisplay); } std::vector<DisplayModeConfig> Scheduler::getDisplayModeConfigsForTheChosenFps( Fps chosenFps, const std::vector<RefreshRateRankingsAndSignals>& refreshRateRankingsAndSignalsPerDisplay) const { std::vector<DisplayModeConfig> displayModeConfigs; displayModeConfigs.reserve(mDisplays.size()); using fps_approx_ops::operator==; std::for_each(refreshRateRankingsAndSignalsPerDisplay.begin(), refreshRateRankingsAndSignalsPerDisplay.end(), [&](const auto& refreshRateRankingsAndSignal) { for (const auto& ranking : refreshRateRankingsAndSignal.refreshRateRankings) { if (ranking.displayModePtr->getFps() == chosenFps) { displayModeConfigs.emplace_back( DisplayModeConfig{refreshRateRankingsAndSignal.globalSignals, ranking.displayModePtr}); break; } } }); return displayModeConfigs; } DisplayModeSelectionParams Scheduler::getDisplayModeSelectionParams() const { const bool powerOnImminent = mDisplayPowerTimer && (mPolicy.displayPowerMode != hal::PowerMode::ON || mPolicy.displayPowerTimer == TimerState::Reset); Loading @@ -715,7 +821,18 @@ auto Scheduler::getRankedDisplayModes() .idle = mPolicy.idleTimer == TimerState::Expired, .powerOnImminent = powerOnImminent}; return configs->getRankedRefreshRates(mPolicy.contentRequirements, signals); return {mPolicy.contentRequirements, signals}; } auto Scheduler::getRankedDisplayModes() -> std::pair<std::vector<RefreshRateRanking>, GlobalSignals> { ATRACE_CALL(); const auto configs = holdRefreshRateConfigs(); const auto displayModeSelectionParams = getDisplayModeSelectionParams(); return configs->getRankedRefreshRates(displayModeSelectionParams.layerRequirements, displayModeSelectionParams.globalSignals); } DisplayModePtr Scheduler::getPreferredDisplayMode() { Loading
services/surfaceflinger/Scheduler/Scheduler.h +52 −3 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ #include <mutex> #include <optional> #include <unordered_map> #include <utility> // TODO(b/129481165): remove the #pragma below and fix conversion issues #pragma clang diagnostic push Loading @@ -32,9 +33,11 @@ #include <ui/GraphicTypes.h> #pragma clang diagnostic pop // ignored "-Wconversion -Wextra" #include <DisplayDevice.h> #include <scheduler/Features.h> #include <scheduler/Time.h> #include "Display/DisplayMap.h" #include "EventThread.h" #include "FrameRateOverrideMappings.h" #include "LayerHistory.h" Loading Loading @@ -83,11 +86,22 @@ class TokenManager; namespace scheduler { using GlobalSignals = RefreshRateConfigs::GlobalSignals; // Config representing the DisplayMode and considered signals for the Display. struct DisplayModeConfig { const GlobalSignals signals; const DisplayModePtr displayModePtr; DisplayModeConfig(GlobalSignals signals, DisplayModePtr displayModePtr) : signals(signals), displayModePtr(std::move(displayModePtr)) {} }; struct ISchedulerCallback { using DisplayModeEvent = scheduler::DisplayModeEvent; virtual void setVsyncEnabled(bool) = 0; virtual void requestDisplayMode(DisplayModePtr, DisplayModeEvent) = 0; virtual void requestDisplayModes(std::vector<DisplayModeConfig>) = 0; virtual void kernelTimerChanged(bool expired) = 0; virtual void triggerOnFrameRateOverridesChanged() = 0; Loading @@ -95,6 +109,25 @@ protected: ~ISchedulerCallback() = default; }; // Holds the total score of the FPS and // number of displays the FPS is found in. struct AggregatedFpsScore { float totalScore; size_t numDisplays; }; // Represents LayerRequirements and GlobalSignals to be considered for the display mode selection. struct DisplayModeSelectionParams { std::vector<RefreshRateConfigs::LayerRequirement> layerRequirements; GlobalSignals globalSignals; }; // Represents the RefreshRateRankings and GlobalSignals for the selected RefreshRateRankings. struct RefreshRateRankingsAndSignals { std::vector<RefreshRateRanking> refreshRateRankings; GlobalSignals globalSignals; }; class Scheduler : android::impl::MessageQueue { using Impl = android::impl::MessageQueue; Loading Loading @@ -237,6 +270,9 @@ public: return mLayerHistory.getLayerFramerate(now, id); } void registerDisplay(const sp<const DisplayDevice>&); void unregisterDisplay(PhysicalDisplayId); private: friend class TestableScheduler; Loading @@ -260,8 +296,6 @@ private: void setVsyncPeriod(nsecs_t period); using GlobalSignals = RefreshRateConfigs::GlobalSignals; struct Policy; // Sets the S state of the policy to the T value under mPolicyLock, and chooses a display mode Loading @@ -274,6 +308,17 @@ private: std::pair<std::vector<RefreshRateRanking>, GlobalSignals> getRankedDisplayModes() REQUIRES(mPolicyLock); // Returns the best display mode per display. std::vector<DisplayModeConfig> getBestDisplayModeConfigs() const REQUIRES(mPolicyLock); // Returns the list of DisplayModeConfigs per display for the chosenFps. std::vector<DisplayModeConfig> getDisplayModeConfigsForTheChosenFps( Fps chosenFps, const std::vector<RefreshRateRankingsAndSignals>&) const; // Returns the DisplayModeSelectionParams to be considered for the // DisplayMode selection based on the current Policy and GlobalSignals. DisplayModeSelectionParams getDisplayModeSelectionParams() const REQUIRES(mPolicyLock); bool updateFrameRateOverrides(GlobalSignals, Fps displayRefreshRate) REQUIRES(mPolicyLock); void dispatchCachedReportedMode() REQUIRES(mPolicyLock) EXCLUDES(mRefreshRateConfigsLock); Loading Loading @@ -323,6 +368,10 @@ private: mutable std::mutex mPolicyLock; // Holds the Physical displays registered through the SurfaceFlinger, used for making // the refresh rate selections. display::PhysicalDisplayMap<PhysicalDisplayId, const sp<const DisplayDevice>> mDisplays; struct Policy { // Policy for choosing the display mode. LayerHistory::Summary contentRequirements; Loading
services/surfaceflinger/Scheduler/include/scheduler/Fps.h +4 −0 Original line number Diff line number Diff line Loading @@ -138,6 +138,10 @@ struct FpsApproxEqual { bool operator()(Fps lhs, Fps rhs) const { return isApproxEqual(lhs, rhs); } }; struct FpsHash { size_t operator()(Fps fps) const { return std::hash<nsecs_t>()(fps.getPeriodNsecs()); } }; inline std::string to_string(Fps fps) { return base::StringPrintf("%.2f Hz", fps.getValue()); } Loading
services/surfaceflinger/SurfaceFlinger.cpp +27 −14 Original line number Diff line number Diff line Loading @@ -2938,7 +2938,7 @@ void SurfaceFlinger::processDisplayAdded(const wp<IBinder>& displayToken, if (display->isPrimary()) { mScheduler->setRefreshRateConfigs(display->holdRefreshRateConfigs()); } mScheduler->registerDisplay(display); dispatchDisplayHotplugEvent(display->getPhysicalId(), true); } Loading @@ -2954,6 +2954,7 @@ void SurfaceFlinger::processDisplayRemoved(const wp<IBinder>& displayToken) { releaseVirtualDisplay(display->getVirtualId()); } else { dispatchDisplayHotplugEvent(display->getPhysicalId(), false); mScheduler->unregisterDisplay(display->getPhysicalId()); } } Loading Loading @@ -2990,6 +2991,8 @@ void SurfaceFlinger::processDisplayChanged(const wp<IBinder>& displayToken, display->disconnect(); if (display->isVirtual()) { releaseVirtualDisplay(display->getVirtualId()); } else { mScheduler->unregisterDisplay(display->getPhysicalId()); } } Loading Loading @@ -3319,25 +3322,34 @@ void SurfaceFlinger::updateCursorAsync() { mCompositionEngine->updateCursorAsync(refreshArgs); } void SurfaceFlinger::requestDisplayMode(DisplayModePtr mode, DisplayModeEvent event) { void SurfaceFlinger::requestDisplayModes( std::vector<scheduler::DisplayModeConfig> displayModeConfigs) { if (mBootStage != BootStage::FINISHED) { ALOGV("Currently in the boot stage, skipping display mode changes"); return; } ATRACE_CALL(); // If this is called from the main thread mStateLock must be locked before // Currently the only way to call this function from the main thread is from // Scheduler::chooseRefreshRateForContent ConditionalLock lock(mStateLock, std::this_thread::get_id() != mMainThreadId); const auto display = getDefaultDisplayDeviceLocked(); if (!display || mBootStage != BootStage::FINISHED) { return; } ATRACE_CALL(); if (!display->refreshRateConfigs().isModeAllowed(mode->getId())) { ALOGV("Skipping disallowed mode %d", mode->getId().value()); return; std::for_each(displayModeConfigs.begin(), displayModeConfigs.end(), [&](const auto& config) REQUIRES(mStateLock) { const auto& displayModePtr = config.displayModePtr; if (const auto display = getDisplayDeviceLocked(displayModePtr->getPhysicalDisplayId()); display->refreshRateConfigs().isModeAllowed(displayModePtr->getId())) { const auto event = config.signals.idle ? DisplayModeEvent::None : DisplayModeEvent::Changed; setDesiredActiveMode({displayModePtr, event}); } else { ALOGV("Skipping disallowed mode %d for display %" PRId64, displayModePtr->getId().value(), display->getPhysicalId().value); } setDesiredActiveMode({std::move(mode), event}); }); } void SurfaceFlinger::triggerOnFrameRateOverridesChanged() { Loading Loading @@ -3386,6 +3398,7 @@ void SurfaceFlinger::initScheduler(const sp<const DisplayDevice>& display) { mScheduler->createVsyncSchedule(features); mScheduler->setRefreshRateConfigs(std::move(configs)); mScheduler->registerDisplay(display); } setVsyncEnabled(false); mScheduler->startTimers(); Loading
services/surfaceflinger/SurfaceFlinger.h +2 −2 Original line number Diff line number Diff line Loading @@ -631,8 +631,8 @@ private: // Toggles hardware VSYNC by calling into HWC. void setVsyncEnabled(bool) override; // Sets the desired display mode if allowed by policy. void requestDisplayMode(DisplayModePtr, DisplayModeEvent) override; // Sets the desired display mode per display if allowed by policy . void requestDisplayModes(std::vector<scheduler::DisplayModeConfig>) override; // Called when kernel idle timer has expired. Used to update the refresh rate overlay. void kernelTimerChanged(bool expired) override; // Called when the frame rate override list changed to trigger an event. Loading