Loading services/surfaceflinger/Scheduler/Scheduler.cpp +11 −12 Original line number Original line Diff line number Diff line Loading @@ -94,7 +94,7 @@ void Scheduler::startTimers() { } } } } void Scheduler::setRefreshRateSelector(std::shared_ptr<RefreshRateSelector> selectorPtr) { void Scheduler::setRefreshRateSelector(RefreshRateSelectorPtr selectorPtr) { // The current RefreshRateSelector instance may outlive this call, so unbind its idle timer. // The current RefreshRateSelector instance may outlive this call, so unbind its idle timer. { { // mRefreshRateSelectorLock is not locked here to avoid the deadlock // mRefreshRateSelectorLock is not locked here to avoid the deadlock Loading Loading @@ -126,13 +126,12 @@ void Scheduler::setRefreshRateSelector(std::shared_ptr<RefreshRateSelector> sele mRefreshRateSelector->startIdleTimer(); mRefreshRateSelector->startIdleTimer(); } } void Scheduler::registerDisplay(sp<const DisplayDevice> display) { void Scheduler::registerDisplay(PhysicalDisplayId displayId, RefreshRateSelectorPtr selectorPtr) { if (display->isPrimary()) { if (!mLeaderDisplayId) { mLeaderDisplayId = display->getPhysicalId(); mLeaderDisplayId = displayId; } } const bool ok = mDisplays.try_emplace(display->getPhysicalId(), std::move(display)).second; mRefreshRateSelectors.emplace_or_replace(displayId, std::move(selectorPtr)); ALOGE_IF(!ok, "%s: Duplicate display", __func__); } } void Scheduler::unregisterDisplay(PhysicalDisplayId displayId) { void Scheduler::unregisterDisplay(PhysicalDisplayId displayId) { Loading @@ -140,7 +139,7 @@ void Scheduler::unregisterDisplay(PhysicalDisplayId displayId) { mLeaderDisplayId.reset(); mLeaderDisplayId.reset(); } } mDisplays.erase(displayId); mRefreshRateSelectors.erase(displayId); } } void Scheduler::run() { void Scheduler::run() { Loading Loading @@ -711,10 +710,9 @@ auto Scheduler::chooseDisplayModes() const -> DisplayModeChoiceMap { const auto globalSignals = makeGlobalSignals(); const auto globalSignals = makeGlobalSignals(); for (const auto& [id, display] : mDisplays) { for (const auto& [id, selectorPtr] : mRefreshRateSelectors) { auto rankedRefreshRates = auto rankedRefreshRates = display->holdRefreshRateSelector() selectorPtr->getRankedRefreshRates(mPolicy.contentRequirements, globalSignals); ->getRankedRefreshRates(mPolicy.contentRequirements, globalSignals); for (const auto& [modePtr, score] : rankedRefreshRates.ranking) { for (const auto& [modePtr, score] : rankedRefreshRates.ranking) { const auto [it, inserted] = refreshRateTallies.try_emplace(modePtr->getFps(), score); const auto [it, inserted] = refreshRateTallies.try_emplace(modePtr->getFps(), score); Loading @@ -733,7 +731,7 @@ auto Scheduler::chooseDisplayModes() const -> DisplayModeChoiceMap { // Find the first refresh rate common to all displays. // Find the first refresh rate common to all displays. while (maxScoreIt != refreshRateTallies.cend() && while (maxScoreIt != refreshRateTallies.cend() && maxScoreIt->second.displayCount != mDisplays.size()) { maxScoreIt->second.displayCount != mRefreshRateSelectors.size()) { ++maxScoreIt; ++maxScoreIt; } } Loading @@ -742,7 +740,8 @@ auto Scheduler::chooseDisplayModes() const -> DisplayModeChoiceMap { for (auto it = maxScoreIt + 1; it != refreshRateTallies.cend(); ++it) { for (auto it = maxScoreIt + 1; it != refreshRateTallies.cend(); ++it) { const auto [fps, tally] = *it; const auto [fps, tally] = *it; if (tally.displayCount == mDisplays.size() && tally.score > maxScoreIt->second.score) { if (tally.displayCount == mRefreshRateSelectors.size() && tally.score > maxScoreIt->second.score) { maxScoreIt = it; maxScoreIt = it; } } } } Loading services/surfaceflinger/Scheduler/Scheduler.h +8 −8 Original line number Original line Diff line number Diff line Loading @@ -39,7 +39,6 @@ #include "Display/DisplayMap.h" #include "Display/DisplayMap.h" #include "Display/DisplayModeRequest.h" #include "Display/DisplayModeRequest.h" #include "DisplayDevice.h" #include "EventThread.h" #include "EventThread.h" #include "FrameRateOverrideMappings.h" #include "FrameRateOverrideMappings.h" #include "LayerHistory.h" #include "LayerHistory.h" Loading Loading @@ -107,10 +106,11 @@ public: virtual ~Scheduler(); virtual ~Scheduler(); void startTimers(); void startTimers(); void setRefreshRateSelector(std::shared_ptr<RefreshRateSelector>) EXCLUDES(mRefreshRateSelectorLock); void registerDisplay(sp<const DisplayDevice>); using RefreshRateSelectorPtr = std::shared_ptr<RefreshRateSelector>; void setRefreshRateSelector(RefreshRateSelectorPtr) EXCLUDES(mRefreshRateSelectorLock); void registerDisplay(PhysicalDisplayId, RefreshRateSelectorPtr); void unregisterDisplay(PhysicalDisplayId); void unregisterDisplay(PhysicalDisplayId); void run(); void run(); Loading Loading @@ -299,8 +299,7 @@ private: EXCLUDES(mRefreshRateSelectorLock); EXCLUDES(mRefreshRateSelectorLock); android::impl::EventThread::GetVsyncPeriodFunction makeGetVsyncPeriodFunction() const; android::impl::EventThread::GetVsyncPeriodFunction makeGetVsyncPeriodFunction() const; std::shared_ptr<RefreshRateSelector> holdRefreshRateSelector() const RefreshRateSelectorPtr holdRefreshRateSelector() const EXCLUDES(mRefreshRateSelectorLock) { EXCLUDES(mRefreshRateSelectorLock) { std::scoped_lock lock(mRefreshRateSelectorLock); std::scoped_lock lock(mRefreshRateSelectorLock); return mRefreshRateSelector; return mRefreshRateSelector; } } Loading Loading @@ -336,7 +335,7 @@ private: mutable std::mutex mPolicyLock; mutable std::mutex mPolicyLock; display::PhysicalDisplayMap<PhysicalDisplayId, sp<const DisplayDevice>> mDisplays; display::PhysicalDisplayMap<PhysicalDisplayId, RefreshRateSelectorPtr> mRefreshRateSelectors; std::optional<PhysicalDisplayId> mLeaderDisplayId; std::optional<PhysicalDisplayId> mLeaderDisplayId; struct Policy { struct Policy { Loading @@ -359,8 +358,9 @@ private: std::optional<ModeChangedParams> cachedModeChangedParams; std::optional<ModeChangedParams> cachedModeChangedParams; } mPolicy GUARDED_BY(mPolicyLock); } mPolicy GUARDED_BY(mPolicyLock); // TODO(b/255635821): Remove this by instead looking up the `mLeaderDisplayId` selector. mutable std::mutex mRefreshRateSelectorLock; mutable std::mutex mRefreshRateSelectorLock; std::shared_ptr<RefreshRateSelector> mRefreshRateSelector GUARDED_BY(mRefreshRateSelectorLock); RefreshRateSelectorPtr mRefreshRateSelector GUARDED_BY(mRefreshRateSelectorLock); std::mutex mVsyncTimelineLock; std::mutex mVsyncTimelineLock; std::optional<hal::VsyncPeriodChangeTimeline> mLastVsyncPeriodChangeTimeline std::optional<hal::VsyncPeriodChangeTimeline> mLastVsyncPeriodChangeTimeline Loading services/surfaceflinger/SurfaceFlinger.cpp +8 −6 Original line number Original line Diff line number Diff line Loading @@ -2937,11 +2937,15 @@ void SurfaceFlinger::processDisplayAdded(const wp<IBinder>& displayToken, displaySurface, producer); displaySurface, producer); if (mScheduler && !display->isVirtual()) { if (mScheduler && !display->isVirtual()) { auto selectorPtr = display->holdRefreshRateSelector(); // Display modes are reloaded on hotplug reconnect. // Display modes are reloaded on hotplug reconnect. if (display->isPrimary()) { if (display->isPrimary()) { mScheduler->setRefreshRateSelector(display->holdRefreshRateSelector()); mScheduler->setRefreshRateSelector(selectorPtr); } } mScheduler->registerDisplay(display); const auto displayId = display->getPhysicalId(); mScheduler->registerDisplay(displayId, std::move(selectorPtr)); dispatchDisplayHotplugEvent(display->getPhysicalId(), true); dispatchDisplayHotplugEvent(display->getPhysicalId(), true); } } Loading Loading @@ -2994,8 +2998,6 @@ void SurfaceFlinger::processDisplayChanged(const wp<IBinder>& displayToken, display->disconnect(); display->disconnect(); if (display->isVirtual()) { if (display->isVirtual()) { releaseVirtualDisplay(display->getVirtualId()); releaseVirtualDisplay(display->getVirtualId()); } else { mScheduler->unregisterDisplay(display->getPhysicalId()); } } } } Loading Loading @@ -3409,8 +3411,8 @@ void SurfaceFlinger::initScheduler(const sp<const DisplayDevice>& display) { } } mScheduler->createVsyncSchedule(features); mScheduler->createVsyncSchedule(features); mScheduler->setRefreshRateSelector(std::move(selectorPtr)); mScheduler->setRefreshRateSelector(selectorPtr); mScheduler->registerDisplay(display); mScheduler->registerDisplay(display->getPhysicalId(), std::move(selectorPtr)); } } setVsyncEnabled(false); setVsyncEnabled(false); mScheduler->startTimers(); mScheduler->startTimers(); Loading services/surfaceflinger/tests/unittests/SchedulerTest.cpp +18 −41 Original line number Original line Diff line number Diff line Loading @@ -20,7 +20,6 @@ #include <mutex> #include <mutex> #include "FakeDisplayInjector.h" #include "Scheduler/EventThread.h" #include "Scheduler/EventThread.h" #include "Scheduler/RefreshRateSelector.h" #include "Scheduler/RefreshRateSelector.h" #include "TestableScheduler.h" #include "TestableScheduler.h" Loading @@ -41,7 +40,6 @@ namespace { using MockEventThread = android::mock::EventThread; using MockEventThread = android::mock::EventThread; using MockLayer = android::mock::MockLayer; using MockLayer = android::mock::MockLayer; using FakeDisplayDeviceInjector = TestableSurfaceFlinger::FakeDisplayDeviceInjector; class SchedulerTest : public testing::Test { class SchedulerTest : public testing::Test { protected: protected: Loading Loading @@ -90,10 +88,6 @@ protected: sp<MockEventThreadConnection> mEventThreadConnection; sp<MockEventThreadConnection> mEventThreadConnection; TestableSurfaceFlinger mFlinger; TestableSurfaceFlinger mFlinger; Hwc2::mock::PowerAdvisor mPowerAdvisor; sp<android::mock::NativeWindow> mNativeWindow = sp<android::mock::NativeWindow>::make(); FakeDisplayInjector mFakeDisplayInjector{mFlinger, mPowerAdvisor, mNativeWindow}; }; }; SchedulerTest::SchedulerTest() { SchedulerTest::SchedulerTest() { Loading Loading @@ -240,14 +234,11 @@ MATCHER(Is120Hz, "") { } } TEST_F(SchedulerTest, chooseRefreshRateForContentSelectsMaxRefreshRate) { TEST_F(SchedulerTest, chooseRefreshRateForContentSelectsMaxRefreshRate) { const auto display = mFakeDisplayInjector.injectInternalDisplay( const auto selectorPtr = [&](FakeDisplayDeviceInjector& injector) { std::make_shared<RefreshRateSelector>(kDisplay1Modes, kDisplay1Mode60->getId()); injector.setDisplayModes(kDisplay1Modes, kDisplay1Mode60->getId()); }, {.displayId = kDisplayId1}); mScheduler->registerDisplay(display); mScheduler->registerDisplay(kDisplayId1, selectorPtr); mScheduler->setRefreshRateSelector(display->holdRefreshRateSelector()); mScheduler->setRefreshRateSelector(selectorPtr); const sp<MockLayer> layer = sp<MockLayer>::make(mFlinger.flinger()); const sp<MockLayer> layer = sp<MockLayer>::make(mFlinger.flinger()); EXPECT_CALL(*layer, isVisible()).WillOnce(Return(true)); EXPECT_CALL(*layer, isVisible()).WillOnce(Return(true)); Loading @@ -269,13 +260,9 @@ TEST_F(SchedulerTest, chooseRefreshRateForContentSelectsMaxRefreshRate) { } } TEST_F(SchedulerTest, chooseDisplayModesSingleDisplay) { TEST_F(SchedulerTest, chooseDisplayModesSingleDisplay) { const auto display = mFakeDisplayInjector.injectInternalDisplay( mScheduler->registerDisplay(kDisplayId1, [&](FakeDisplayDeviceInjector& injector) { std::make_shared<RefreshRateSelector>(kDisplay1Modes, injector.setDisplayModes(kDisplay1Modes, kDisplay1Mode60->getId()); kDisplay1Mode60->getId())); }, {.displayId = kDisplayId1}); mScheduler->registerDisplay(display); std::vector<RefreshRateSelector::LayerRequirement> layers = std::vector<RefreshRateSelector::LayerRequirement> layers = std::vector<RefreshRateSelector::LayerRequirement>({{.weight = 1.f}, {.weight = 1.f}}); std::vector<RefreshRateSelector::LayerRequirement>({{.weight = 1.f}, {.weight = 1.f}}); Loading Loading @@ -314,23 +301,16 @@ TEST_F(SchedulerTest, chooseDisplayModesSingleDisplay) { EXPECT_EQ(choice->get(), DisplayModeChoice(kDisplay1Mode120, globalSignals)); EXPECT_EQ(choice->get(), DisplayModeChoice(kDisplay1Mode120, globalSignals)); mScheduler->unregisterDisplay(kDisplayId1); mScheduler->unregisterDisplay(kDisplayId1); EXPECT_TRUE(mScheduler->mutableDisplays().empty()); EXPECT_FALSE(mScheduler->hasRefreshRateSelectors()); } } TEST_F(SchedulerTest, chooseDisplayModesMultipleDisplays) { TEST_F(SchedulerTest, chooseDisplayModesMultipleDisplays) { const auto display1 = mFakeDisplayInjector.injectInternalDisplay( mScheduler->registerDisplay(kDisplayId1, [&](FakeDisplayDeviceInjector& injector) { std::make_shared<RefreshRateSelector>(kDisplay1Modes, injector.setDisplayModes(kDisplay1Modes, kDisplay1Mode60->getId()); kDisplay1Mode60->getId())); }, mScheduler->registerDisplay(kDisplayId2, {.displayId = kDisplayId1, .hwcDisplayId = 42, .isPrimary = true}); std::make_shared<RefreshRateSelector>(kDisplay2Modes, const auto display2 = mFakeDisplayInjector.injectInternalDisplay( kDisplay2Mode60->getId())); [&](FakeDisplayDeviceInjector& injector) { injector.setDisplayModes(kDisplay2Modes, kDisplay2Mode60->getId()); }, {.displayId = kDisplayId2, .hwcDisplayId = 41, .isPrimary = false}); mScheduler->registerDisplay(display1); mScheduler->registerDisplay(display2); using DisplayModeChoice = TestableScheduler::DisplayModeChoice; using DisplayModeChoice = TestableScheduler::DisplayModeChoice; TestableScheduler::DisplayModeChoiceMap expectedChoices; TestableScheduler::DisplayModeChoiceMap expectedChoices; Loading Loading @@ -380,13 +360,10 @@ TEST_F(SchedulerTest, chooseDisplayModesMultipleDisplays) { } } { { // This display does not support 120 Hz, so we should choose 60 Hz despite the touch signal. // This display does not support 120 Hz, so we should choose 60 Hz despite the touch signal. const auto display3 = mFakeDisplayInjector.injectInternalDisplay( mScheduler [&](FakeDisplayDeviceInjector& injector) { ->registerDisplay(kDisplayId3, injector.setDisplayModes(kDisplay3Modes, kDisplay3Mode60->getId()); std::make_shared<RefreshRateSelector>(kDisplay3Modes, }, kDisplay3Mode60->getId())); {.displayId = kDisplayId3, .hwcDisplayId = 40, .isPrimary = false}); mScheduler->registerDisplay(display3); const GlobalSignals globalSignals = {.touch = true}; const GlobalSignals globalSignals = {.touch = true}; mScheduler->replaceTouchTimer(10); mScheduler->replaceTouchTimer(10); Loading services/surfaceflinger/tests/unittests/TestableScheduler.h +5 −8 Original line number Original line Diff line number Diff line Loading @@ -32,15 +32,13 @@ namespace android::scheduler { class TestableScheduler : public Scheduler, private ICompositor { class TestableScheduler : public Scheduler, private ICompositor { public: public: TestableScheduler(std::shared_ptr<RefreshRateSelector> selectorPtr, TestableScheduler(RefreshRateSelectorPtr selectorPtr, ISchedulerCallback& callback) ISchedulerCallback& callback) : TestableScheduler(std::make_unique<mock::VsyncController>(), : TestableScheduler(std::make_unique<mock::VsyncController>(), std::make_unique<mock::VSyncTracker>(), std::move(selectorPtr), std::make_unique<mock::VSyncTracker>(), std::move(selectorPtr), callback) {} callback) {} TestableScheduler(std::unique_ptr<VsyncController> controller, TestableScheduler(std::unique_ptr<VsyncController> controller, std::unique_ptr<VSyncTracker> tracker, std::unique_ptr<VSyncTracker> tracker, RefreshRateSelectorPtr selectorPtr, std::shared_ptr<RefreshRateSelector> selectorPtr, ISchedulerCallback& callback) ISchedulerCallback& callback) : Scheduler(*this, callback, Feature::kContentDetection) { : Scheduler(*this, callback, Feature::kContentDetection) { mVsyncSchedule.emplace(VsyncSchedule(std::move(tracker), nullptr, std::move(controller))); mVsyncSchedule.emplace(VsyncSchedule(std::move(tracker), nullptr, std::move(controller))); Loading Loading @@ -68,16 +66,15 @@ public: auto& mutablePrimaryHWVsyncEnabled() { return mPrimaryHWVsyncEnabled; } auto& mutablePrimaryHWVsyncEnabled() { return mPrimaryHWVsyncEnabled; } auto& mutableHWVsyncAvailable() { return mHWVsyncAvailable; } auto& mutableHWVsyncAvailable() { return mHWVsyncAvailable; } auto& mutableLayerHistory() { return mLayerHistory; } auto refreshRateSelector() { return holdRefreshRateSelector(); } bool hasRefreshRateSelectors() const { return !mRefreshRateSelectors.empty(); } auto& mutableDisplays() { return mDisplays; } auto& mutableLayerHistory() { return mLayerHistory; } size_t layerHistorySize() NO_THREAD_SAFETY_ANALYSIS { size_t layerHistorySize() NO_THREAD_SAFETY_ANALYSIS { return mLayerHistory.mActiveLayerInfos.size() + mLayerHistory.mInactiveLayerInfos.size(); return mLayerHistory.mActiveLayerInfos.size() + mLayerHistory.mInactiveLayerInfos.size(); } } auto refreshRateSelector() { return holdRefreshRateSelector(); } size_t getNumActiveLayers() NO_THREAD_SAFETY_ANALYSIS { size_t getNumActiveLayers() NO_THREAD_SAFETY_ANALYSIS { return mLayerHistory.mActiveLayerInfos.size(); return mLayerHistory.mActiveLayerInfos.size(); } } Loading Loading
services/surfaceflinger/Scheduler/Scheduler.cpp +11 −12 Original line number Original line Diff line number Diff line Loading @@ -94,7 +94,7 @@ void Scheduler::startTimers() { } } } } void Scheduler::setRefreshRateSelector(std::shared_ptr<RefreshRateSelector> selectorPtr) { void Scheduler::setRefreshRateSelector(RefreshRateSelectorPtr selectorPtr) { // The current RefreshRateSelector instance may outlive this call, so unbind its idle timer. // The current RefreshRateSelector instance may outlive this call, so unbind its idle timer. { { // mRefreshRateSelectorLock is not locked here to avoid the deadlock // mRefreshRateSelectorLock is not locked here to avoid the deadlock Loading Loading @@ -126,13 +126,12 @@ void Scheduler::setRefreshRateSelector(std::shared_ptr<RefreshRateSelector> sele mRefreshRateSelector->startIdleTimer(); mRefreshRateSelector->startIdleTimer(); } } void Scheduler::registerDisplay(sp<const DisplayDevice> display) { void Scheduler::registerDisplay(PhysicalDisplayId displayId, RefreshRateSelectorPtr selectorPtr) { if (display->isPrimary()) { if (!mLeaderDisplayId) { mLeaderDisplayId = display->getPhysicalId(); mLeaderDisplayId = displayId; } } const bool ok = mDisplays.try_emplace(display->getPhysicalId(), std::move(display)).second; mRefreshRateSelectors.emplace_or_replace(displayId, std::move(selectorPtr)); ALOGE_IF(!ok, "%s: Duplicate display", __func__); } } void Scheduler::unregisterDisplay(PhysicalDisplayId displayId) { void Scheduler::unregisterDisplay(PhysicalDisplayId displayId) { Loading @@ -140,7 +139,7 @@ void Scheduler::unregisterDisplay(PhysicalDisplayId displayId) { mLeaderDisplayId.reset(); mLeaderDisplayId.reset(); } } mDisplays.erase(displayId); mRefreshRateSelectors.erase(displayId); } } void Scheduler::run() { void Scheduler::run() { Loading Loading @@ -711,10 +710,9 @@ auto Scheduler::chooseDisplayModes() const -> DisplayModeChoiceMap { const auto globalSignals = makeGlobalSignals(); const auto globalSignals = makeGlobalSignals(); for (const auto& [id, display] : mDisplays) { for (const auto& [id, selectorPtr] : mRefreshRateSelectors) { auto rankedRefreshRates = auto rankedRefreshRates = display->holdRefreshRateSelector() selectorPtr->getRankedRefreshRates(mPolicy.contentRequirements, globalSignals); ->getRankedRefreshRates(mPolicy.contentRequirements, globalSignals); for (const auto& [modePtr, score] : rankedRefreshRates.ranking) { for (const auto& [modePtr, score] : rankedRefreshRates.ranking) { const auto [it, inserted] = refreshRateTallies.try_emplace(modePtr->getFps(), score); const auto [it, inserted] = refreshRateTallies.try_emplace(modePtr->getFps(), score); Loading @@ -733,7 +731,7 @@ auto Scheduler::chooseDisplayModes() const -> DisplayModeChoiceMap { // Find the first refresh rate common to all displays. // Find the first refresh rate common to all displays. while (maxScoreIt != refreshRateTallies.cend() && while (maxScoreIt != refreshRateTallies.cend() && maxScoreIt->second.displayCount != mDisplays.size()) { maxScoreIt->second.displayCount != mRefreshRateSelectors.size()) { ++maxScoreIt; ++maxScoreIt; } } Loading @@ -742,7 +740,8 @@ auto Scheduler::chooseDisplayModes() const -> DisplayModeChoiceMap { for (auto it = maxScoreIt + 1; it != refreshRateTallies.cend(); ++it) { for (auto it = maxScoreIt + 1; it != refreshRateTallies.cend(); ++it) { const auto [fps, tally] = *it; const auto [fps, tally] = *it; if (tally.displayCount == mDisplays.size() && tally.score > maxScoreIt->second.score) { if (tally.displayCount == mRefreshRateSelectors.size() && tally.score > maxScoreIt->second.score) { maxScoreIt = it; maxScoreIt = it; } } } } Loading
services/surfaceflinger/Scheduler/Scheduler.h +8 −8 Original line number Original line Diff line number Diff line Loading @@ -39,7 +39,6 @@ #include "Display/DisplayMap.h" #include "Display/DisplayMap.h" #include "Display/DisplayModeRequest.h" #include "Display/DisplayModeRequest.h" #include "DisplayDevice.h" #include "EventThread.h" #include "EventThread.h" #include "FrameRateOverrideMappings.h" #include "FrameRateOverrideMappings.h" #include "LayerHistory.h" #include "LayerHistory.h" Loading Loading @@ -107,10 +106,11 @@ public: virtual ~Scheduler(); virtual ~Scheduler(); void startTimers(); void startTimers(); void setRefreshRateSelector(std::shared_ptr<RefreshRateSelector>) EXCLUDES(mRefreshRateSelectorLock); void registerDisplay(sp<const DisplayDevice>); using RefreshRateSelectorPtr = std::shared_ptr<RefreshRateSelector>; void setRefreshRateSelector(RefreshRateSelectorPtr) EXCLUDES(mRefreshRateSelectorLock); void registerDisplay(PhysicalDisplayId, RefreshRateSelectorPtr); void unregisterDisplay(PhysicalDisplayId); void unregisterDisplay(PhysicalDisplayId); void run(); void run(); Loading Loading @@ -299,8 +299,7 @@ private: EXCLUDES(mRefreshRateSelectorLock); EXCLUDES(mRefreshRateSelectorLock); android::impl::EventThread::GetVsyncPeriodFunction makeGetVsyncPeriodFunction() const; android::impl::EventThread::GetVsyncPeriodFunction makeGetVsyncPeriodFunction() const; std::shared_ptr<RefreshRateSelector> holdRefreshRateSelector() const RefreshRateSelectorPtr holdRefreshRateSelector() const EXCLUDES(mRefreshRateSelectorLock) { EXCLUDES(mRefreshRateSelectorLock) { std::scoped_lock lock(mRefreshRateSelectorLock); std::scoped_lock lock(mRefreshRateSelectorLock); return mRefreshRateSelector; return mRefreshRateSelector; } } Loading Loading @@ -336,7 +335,7 @@ private: mutable std::mutex mPolicyLock; mutable std::mutex mPolicyLock; display::PhysicalDisplayMap<PhysicalDisplayId, sp<const DisplayDevice>> mDisplays; display::PhysicalDisplayMap<PhysicalDisplayId, RefreshRateSelectorPtr> mRefreshRateSelectors; std::optional<PhysicalDisplayId> mLeaderDisplayId; std::optional<PhysicalDisplayId> mLeaderDisplayId; struct Policy { struct Policy { Loading @@ -359,8 +358,9 @@ private: std::optional<ModeChangedParams> cachedModeChangedParams; std::optional<ModeChangedParams> cachedModeChangedParams; } mPolicy GUARDED_BY(mPolicyLock); } mPolicy GUARDED_BY(mPolicyLock); // TODO(b/255635821): Remove this by instead looking up the `mLeaderDisplayId` selector. mutable std::mutex mRefreshRateSelectorLock; mutable std::mutex mRefreshRateSelectorLock; std::shared_ptr<RefreshRateSelector> mRefreshRateSelector GUARDED_BY(mRefreshRateSelectorLock); RefreshRateSelectorPtr mRefreshRateSelector GUARDED_BY(mRefreshRateSelectorLock); std::mutex mVsyncTimelineLock; std::mutex mVsyncTimelineLock; std::optional<hal::VsyncPeriodChangeTimeline> mLastVsyncPeriodChangeTimeline std::optional<hal::VsyncPeriodChangeTimeline> mLastVsyncPeriodChangeTimeline Loading
services/surfaceflinger/SurfaceFlinger.cpp +8 −6 Original line number Original line Diff line number Diff line Loading @@ -2937,11 +2937,15 @@ void SurfaceFlinger::processDisplayAdded(const wp<IBinder>& displayToken, displaySurface, producer); displaySurface, producer); if (mScheduler && !display->isVirtual()) { if (mScheduler && !display->isVirtual()) { auto selectorPtr = display->holdRefreshRateSelector(); // Display modes are reloaded on hotplug reconnect. // Display modes are reloaded on hotplug reconnect. if (display->isPrimary()) { if (display->isPrimary()) { mScheduler->setRefreshRateSelector(display->holdRefreshRateSelector()); mScheduler->setRefreshRateSelector(selectorPtr); } } mScheduler->registerDisplay(display); const auto displayId = display->getPhysicalId(); mScheduler->registerDisplay(displayId, std::move(selectorPtr)); dispatchDisplayHotplugEvent(display->getPhysicalId(), true); dispatchDisplayHotplugEvent(display->getPhysicalId(), true); } } Loading Loading @@ -2994,8 +2998,6 @@ void SurfaceFlinger::processDisplayChanged(const wp<IBinder>& displayToken, display->disconnect(); display->disconnect(); if (display->isVirtual()) { if (display->isVirtual()) { releaseVirtualDisplay(display->getVirtualId()); releaseVirtualDisplay(display->getVirtualId()); } else { mScheduler->unregisterDisplay(display->getPhysicalId()); } } } } Loading Loading @@ -3409,8 +3411,8 @@ void SurfaceFlinger::initScheduler(const sp<const DisplayDevice>& display) { } } mScheduler->createVsyncSchedule(features); mScheduler->createVsyncSchedule(features); mScheduler->setRefreshRateSelector(std::move(selectorPtr)); mScheduler->setRefreshRateSelector(selectorPtr); mScheduler->registerDisplay(display); mScheduler->registerDisplay(display->getPhysicalId(), std::move(selectorPtr)); } } setVsyncEnabled(false); setVsyncEnabled(false); mScheduler->startTimers(); mScheduler->startTimers(); Loading
services/surfaceflinger/tests/unittests/SchedulerTest.cpp +18 −41 Original line number Original line Diff line number Diff line Loading @@ -20,7 +20,6 @@ #include <mutex> #include <mutex> #include "FakeDisplayInjector.h" #include "Scheduler/EventThread.h" #include "Scheduler/EventThread.h" #include "Scheduler/RefreshRateSelector.h" #include "Scheduler/RefreshRateSelector.h" #include "TestableScheduler.h" #include "TestableScheduler.h" Loading @@ -41,7 +40,6 @@ namespace { using MockEventThread = android::mock::EventThread; using MockEventThread = android::mock::EventThread; using MockLayer = android::mock::MockLayer; using MockLayer = android::mock::MockLayer; using FakeDisplayDeviceInjector = TestableSurfaceFlinger::FakeDisplayDeviceInjector; class SchedulerTest : public testing::Test { class SchedulerTest : public testing::Test { protected: protected: Loading Loading @@ -90,10 +88,6 @@ protected: sp<MockEventThreadConnection> mEventThreadConnection; sp<MockEventThreadConnection> mEventThreadConnection; TestableSurfaceFlinger mFlinger; TestableSurfaceFlinger mFlinger; Hwc2::mock::PowerAdvisor mPowerAdvisor; sp<android::mock::NativeWindow> mNativeWindow = sp<android::mock::NativeWindow>::make(); FakeDisplayInjector mFakeDisplayInjector{mFlinger, mPowerAdvisor, mNativeWindow}; }; }; SchedulerTest::SchedulerTest() { SchedulerTest::SchedulerTest() { Loading Loading @@ -240,14 +234,11 @@ MATCHER(Is120Hz, "") { } } TEST_F(SchedulerTest, chooseRefreshRateForContentSelectsMaxRefreshRate) { TEST_F(SchedulerTest, chooseRefreshRateForContentSelectsMaxRefreshRate) { const auto display = mFakeDisplayInjector.injectInternalDisplay( const auto selectorPtr = [&](FakeDisplayDeviceInjector& injector) { std::make_shared<RefreshRateSelector>(kDisplay1Modes, kDisplay1Mode60->getId()); injector.setDisplayModes(kDisplay1Modes, kDisplay1Mode60->getId()); }, {.displayId = kDisplayId1}); mScheduler->registerDisplay(display); mScheduler->registerDisplay(kDisplayId1, selectorPtr); mScheduler->setRefreshRateSelector(display->holdRefreshRateSelector()); mScheduler->setRefreshRateSelector(selectorPtr); const sp<MockLayer> layer = sp<MockLayer>::make(mFlinger.flinger()); const sp<MockLayer> layer = sp<MockLayer>::make(mFlinger.flinger()); EXPECT_CALL(*layer, isVisible()).WillOnce(Return(true)); EXPECT_CALL(*layer, isVisible()).WillOnce(Return(true)); Loading @@ -269,13 +260,9 @@ TEST_F(SchedulerTest, chooseRefreshRateForContentSelectsMaxRefreshRate) { } } TEST_F(SchedulerTest, chooseDisplayModesSingleDisplay) { TEST_F(SchedulerTest, chooseDisplayModesSingleDisplay) { const auto display = mFakeDisplayInjector.injectInternalDisplay( mScheduler->registerDisplay(kDisplayId1, [&](FakeDisplayDeviceInjector& injector) { std::make_shared<RefreshRateSelector>(kDisplay1Modes, injector.setDisplayModes(kDisplay1Modes, kDisplay1Mode60->getId()); kDisplay1Mode60->getId())); }, {.displayId = kDisplayId1}); mScheduler->registerDisplay(display); std::vector<RefreshRateSelector::LayerRequirement> layers = std::vector<RefreshRateSelector::LayerRequirement> layers = std::vector<RefreshRateSelector::LayerRequirement>({{.weight = 1.f}, {.weight = 1.f}}); std::vector<RefreshRateSelector::LayerRequirement>({{.weight = 1.f}, {.weight = 1.f}}); Loading Loading @@ -314,23 +301,16 @@ TEST_F(SchedulerTest, chooseDisplayModesSingleDisplay) { EXPECT_EQ(choice->get(), DisplayModeChoice(kDisplay1Mode120, globalSignals)); EXPECT_EQ(choice->get(), DisplayModeChoice(kDisplay1Mode120, globalSignals)); mScheduler->unregisterDisplay(kDisplayId1); mScheduler->unregisterDisplay(kDisplayId1); EXPECT_TRUE(mScheduler->mutableDisplays().empty()); EXPECT_FALSE(mScheduler->hasRefreshRateSelectors()); } } TEST_F(SchedulerTest, chooseDisplayModesMultipleDisplays) { TEST_F(SchedulerTest, chooseDisplayModesMultipleDisplays) { const auto display1 = mFakeDisplayInjector.injectInternalDisplay( mScheduler->registerDisplay(kDisplayId1, [&](FakeDisplayDeviceInjector& injector) { std::make_shared<RefreshRateSelector>(kDisplay1Modes, injector.setDisplayModes(kDisplay1Modes, kDisplay1Mode60->getId()); kDisplay1Mode60->getId())); }, mScheduler->registerDisplay(kDisplayId2, {.displayId = kDisplayId1, .hwcDisplayId = 42, .isPrimary = true}); std::make_shared<RefreshRateSelector>(kDisplay2Modes, const auto display2 = mFakeDisplayInjector.injectInternalDisplay( kDisplay2Mode60->getId())); [&](FakeDisplayDeviceInjector& injector) { injector.setDisplayModes(kDisplay2Modes, kDisplay2Mode60->getId()); }, {.displayId = kDisplayId2, .hwcDisplayId = 41, .isPrimary = false}); mScheduler->registerDisplay(display1); mScheduler->registerDisplay(display2); using DisplayModeChoice = TestableScheduler::DisplayModeChoice; using DisplayModeChoice = TestableScheduler::DisplayModeChoice; TestableScheduler::DisplayModeChoiceMap expectedChoices; TestableScheduler::DisplayModeChoiceMap expectedChoices; Loading Loading @@ -380,13 +360,10 @@ TEST_F(SchedulerTest, chooseDisplayModesMultipleDisplays) { } } { { // This display does not support 120 Hz, so we should choose 60 Hz despite the touch signal. // This display does not support 120 Hz, so we should choose 60 Hz despite the touch signal. const auto display3 = mFakeDisplayInjector.injectInternalDisplay( mScheduler [&](FakeDisplayDeviceInjector& injector) { ->registerDisplay(kDisplayId3, injector.setDisplayModes(kDisplay3Modes, kDisplay3Mode60->getId()); std::make_shared<RefreshRateSelector>(kDisplay3Modes, }, kDisplay3Mode60->getId())); {.displayId = kDisplayId3, .hwcDisplayId = 40, .isPrimary = false}); mScheduler->registerDisplay(display3); const GlobalSignals globalSignals = {.touch = true}; const GlobalSignals globalSignals = {.touch = true}; mScheduler->replaceTouchTimer(10); mScheduler->replaceTouchTimer(10); Loading
services/surfaceflinger/tests/unittests/TestableScheduler.h +5 −8 Original line number Original line Diff line number Diff line Loading @@ -32,15 +32,13 @@ namespace android::scheduler { class TestableScheduler : public Scheduler, private ICompositor { class TestableScheduler : public Scheduler, private ICompositor { public: public: TestableScheduler(std::shared_ptr<RefreshRateSelector> selectorPtr, TestableScheduler(RefreshRateSelectorPtr selectorPtr, ISchedulerCallback& callback) ISchedulerCallback& callback) : TestableScheduler(std::make_unique<mock::VsyncController>(), : TestableScheduler(std::make_unique<mock::VsyncController>(), std::make_unique<mock::VSyncTracker>(), std::move(selectorPtr), std::make_unique<mock::VSyncTracker>(), std::move(selectorPtr), callback) {} callback) {} TestableScheduler(std::unique_ptr<VsyncController> controller, TestableScheduler(std::unique_ptr<VsyncController> controller, std::unique_ptr<VSyncTracker> tracker, std::unique_ptr<VSyncTracker> tracker, RefreshRateSelectorPtr selectorPtr, std::shared_ptr<RefreshRateSelector> selectorPtr, ISchedulerCallback& callback) ISchedulerCallback& callback) : Scheduler(*this, callback, Feature::kContentDetection) { : Scheduler(*this, callback, Feature::kContentDetection) { mVsyncSchedule.emplace(VsyncSchedule(std::move(tracker), nullptr, std::move(controller))); mVsyncSchedule.emplace(VsyncSchedule(std::move(tracker), nullptr, std::move(controller))); Loading Loading @@ -68,16 +66,15 @@ public: auto& mutablePrimaryHWVsyncEnabled() { return mPrimaryHWVsyncEnabled; } auto& mutablePrimaryHWVsyncEnabled() { return mPrimaryHWVsyncEnabled; } auto& mutableHWVsyncAvailable() { return mHWVsyncAvailable; } auto& mutableHWVsyncAvailable() { return mHWVsyncAvailable; } auto& mutableLayerHistory() { return mLayerHistory; } auto refreshRateSelector() { return holdRefreshRateSelector(); } bool hasRefreshRateSelectors() const { return !mRefreshRateSelectors.empty(); } auto& mutableDisplays() { return mDisplays; } auto& mutableLayerHistory() { return mLayerHistory; } size_t layerHistorySize() NO_THREAD_SAFETY_ANALYSIS { size_t layerHistorySize() NO_THREAD_SAFETY_ANALYSIS { return mLayerHistory.mActiveLayerInfos.size() + mLayerHistory.mInactiveLayerInfos.size(); return mLayerHistory.mActiveLayerInfos.size() + mLayerHistory.mInactiveLayerInfos.size(); } } auto refreshRateSelector() { return holdRefreshRateSelector(); } size_t getNumActiveLayers() NO_THREAD_SAFETY_ANALYSIS { size_t getNumActiveLayers() NO_THREAD_SAFETY_ANALYSIS { return mLayerHistory.mActiveLayerInfos.size(); return mLayerHistory.mActiveLayerInfos.size(); } } Loading