Loading services/surfaceflinger/Scheduler/Scheduler.cpp +11 −6 Original line number Diff line number Diff line Loading @@ -123,19 +123,22 @@ void Scheduler::setPacesetterDisplay(std::optional<PhysicalDisplayId> pacesetter promotePacesetterDisplay(pacesetterIdOpt); } void Scheduler::registerDisplay(PhysicalDisplayId displayId, RefreshRateSelectorPtr selectorPtr) { void Scheduler::registerDisplay(PhysicalDisplayId displayId, RefreshRateSelectorPtr selectorPtr, PhysicalDisplayId activeDisplayId) { auto schedulePtr = std::make_shared<VsyncSchedule>(selectorPtr->getActiveMode().modePtr, mFeatures, [this](PhysicalDisplayId id, bool enable) { onHardwareVsyncRequest(id, enable); }); registerDisplayInternal(displayId, std::move(selectorPtr), std::move(schedulePtr)); registerDisplayInternal(displayId, std::move(selectorPtr), std::move(schedulePtr), activeDisplayId); } void Scheduler::registerDisplayInternal(PhysicalDisplayId displayId, RefreshRateSelectorPtr selectorPtr, VsyncSchedulePtr schedulePtr) { VsyncSchedulePtr schedulePtr, PhysicalDisplayId activeDisplayId) { demotePacesetterDisplay(); auto [pacesetterVsyncSchedule, isNew] = [&]() FTL_FAKE_GUARD(kMainThreadContext) { Loading @@ -145,7 +148,7 @@ void Scheduler::registerDisplayInternal(PhysicalDisplayId displayId, std::move(schedulePtr), mFeatures) .second; return std::make_pair(promotePacesetterDisplayLocked(), isNew); return std::make_pair(promotePacesetterDisplayLocked(activeDisplayId), isNew); }(); applyNewVsyncSchedule(std::move(pacesetterVsyncSchedule)); Loading @@ -158,7 +161,9 @@ void Scheduler::registerDisplayInternal(PhysicalDisplayId displayId, dispatchHotplug(displayId, Hotplug::Connected); } void Scheduler::unregisterDisplay(PhysicalDisplayId displayId) { void Scheduler::unregisterDisplay(PhysicalDisplayId displayId, PhysicalDisplayId activeDisplayId) { LOG_ALWAYS_FATAL_IF(displayId == activeDisplayId, "Cannot unregister the active display!"); dispatchHotplug(displayId, Hotplug::Disconnected); demotePacesetterDisplay(); Loading @@ -173,7 +178,7 @@ void Scheduler::unregisterDisplay(PhysicalDisplayId displayId) { // headless virtual display.) LOG_ALWAYS_FATAL_IF(mDisplays.empty(), "Cannot unregister all displays!"); pacesetterVsyncSchedule = promotePacesetterDisplayLocked(); pacesetterVsyncSchedule = promotePacesetterDisplayLocked(activeDisplayId); } applyNewVsyncSchedule(std::move(pacesetterVsyncSchedule)); } Loading services/surfaceflinger/Scheduler/Scheduler.h +12 −4 Original line number Diff line number Diff line Loading @@ -101,9 +101,16 @@ public: using ConstVsyncSchedulePtr = std::shared_ptr<const VsyncSchedule>; using VsyncSchedulePtr = std::shared_ptr<VsyncSchedule>; void registerDisplay(PhysicalDisplayId, RefreshRateSelectorPtr) REQUIRES(kMainThreadContext) // After registration/unregistration, `activeDisplayId` is promoted to pacesetter. Note that the // active display is never unregistered, since hotplug disconnect never happens for activatable // displays, i.e. a foldable's internal displays or otherwise the (internal or external) primary // display. // TODO: b/255635821 - Remove active display parameters. void registerDisplay(PhysicalDisplayId, RefreshRateSelectorPtr, PhysicalDisplayId activeDisplayId) REQUIRES(kMainThreadContext) EXCLUDES(mDisplayLock); void unregisterDisplay(PhysicalDisplayId) REQUIRES(kMainThreadContext) EXCLUDES(mDisplayLock); void unregisterDisplay(PhysicalDisplayId, PhysicalDisplayId activeDisplayId) REQUIRES(kMainThreadContext) EXCLUDES(mDisplayLock); void run(); Loading Loading @@ -388,8 +395,9 @@ private: // 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, VsyncSchedulePtr) REQUIRES(kMainThreadContext) EXCLUDES(mDisplayLock); void registerDisplayInternal(PhysicalDisplayId, RefreshRateSelectorPtr, VsyncSchedulePtr, PhysicalDisplayId activeDisplayId) REQUIRES(kMainThreadContext) EXCLUDES(mDisplayLock); struct Policy; Loading services/surfaceflinger/SurfaceFlinger.cpp +5 −3 Original line number Diff line number Diff line Loading @@ -3736,7 +3736,8 @@ void SurfaceFlinger::processDisplayAdded(const wp<IBinder>& displayToken, ftl::FakeGuard guard(kMainThreadContext); // For hotplug reconnect, renew the registration since display modes have been reloaded. mScheduler->registerDisplay(display->getPhysicalId(), display->holdRefreshRateSelector()); mScheduler->registerDisplay(display->getPhysicalId(), display->holdRefreshRateSelector(), mActiveDisplayId); } if (display->isVirtual()) { Loading Loading @@ -3775,7 +3776,7 @@ void SurfaceFlinger::processDisplayRemoved(const wp<IBinder>& displayToken) { if (display->isVirtual()) { releaseVirtualDisplay(display->getVirtualId()); } else { mScheduler->unregisterDisplay(display->getPhysicalId()); mScheduler->unregisterDisplay(display->getPhysicalId(), mActiveDisplayId); } } Loading Loading @@ -4395,7 +4396,8 @@ void SurfaceFlinger::initScheduler(const sp<const DisplayDevice>& display) { getFactory(), activeRefreshRate, *mTimeStats); // The pacesetter must be registered before EventThread creation below. mScheduler->registerDisplay(display->getPhysicalId(), display->holdRefreshRateSelector()); mScheduler->registerDisplay(display->getPhysicalId(), display->holdRefreshRateSelector(), mActiveDisplayId); if (FlagManager::getInstance().vrr_config()) { mScheduler->setRenderRate(display->getPhysicalId(), activeMode.fps); } Loading services/surfaceflinger/tests/unittests/SchedulerTest.cpp +16 −9 Original line number Diff line number Diff line Loading @@ -337,12 +337,15 @@ TEST_F(SchedulerTest, chooseDisplayModesSingleDisplayHighHintTouchSignal) { } TEST_F(SchedulerTest, chooseDisplayModesMultipleDisplays) { constexpr PhysicalDisplayId kActiveDisplayId = kDisplayId1; mScheduler->registerDisplay(kDisplayId1, std::make_shared<RefreshRateSelector>(kDisplay1Modes, kDisplay1Mode60->getId())); kDisplay1Mode60->getId()), kActiveDisplayId); mScheduler->registerDisplay(kDisplayId2, std::make_shared<RefreshRateSelector>(kDisplay2Modes, kDisplay2Mode60->getId())); kDisplay2Mode60->getId()), kActiveDisplayId); using DisplayModeChoice = TestableScheduler::DisplayModeChoice; TestableScheduler::DisplayModeChoiceMap expectedChoices; Loading Loading @@ -402,10 +405,10 @@ TEST_F(SchedulerTest, chooseDisplayModesMultipleDisplays) { { // The kDisplayId3 does not support 120Hz, The pacesetter display rate is chosen to be 120 // Hz. In this case only the display kDisplayId3 choose 60Hz as it does not support 120Hz. mScheduler ->registerDisplay(kDisplayId3, mScheduler->registerDisplay(kDisplayId3, std::make_shared<RefreshRateSelector>(kDisplay3Modes, kDisplay3Mode60->getId())); kDisplay3Mode60->getId()), kActiveDisplayId); const GlobalSignals globalSignals = {.touch = true}; mScheduler->replaceTouchTimer(10); Loading Loading @@ -447,12 +450,15 @@ TEST_F(SchedulerTest, chooseDisplayModesMultipleDisplays) { } TEST_F(SchedulerTest, onFrameSignalMultipleDisplays) { constexpr PhysicalDisplayId kActiveDisplayId = kDisplayId1; mScheduler->registerDisplay(kDisplayId1, std::make_shared<RefreshRateSelector>(kDisplay1Modes, kDisplay1Mode60->getId())); kDisplay1Mode60->getId()), kActiveDisplayId); mScheduler->registerDisplay(kDisplayId2, std::make_shared<RefreshRateSelector>(kDisplay2Modes, kDisplay2Mode60->getId())); kDisplay2Mode60->getId()), kActiveDisplayId); using VsyncIds = std::vector<std::pair<PhysicalDisplayId, VsyncId>>; Loading Loading @@ -574,7 +580,8 @@ TEST_F(SchedulerTest, nextFrameIntervalTest) { mFlinger.getTimeStats(), mSchedulerCallback}; scheduler.registerDisplay(kMode->getPhysicalDisplayId(), vrrSelectorPtr, vrrTracker); scheduler.registerDisplay(kMode->getPhysicalDisplayId(), vrrSelectorPtr, std::nullopt, vrrTracker); vrrSelectorPtr->setActiveMode(kMode->getId(), frameRate); scheduler.setRenderRate(kMode->getPhysicalDisplayId(), frameRate); vrrTracker->addVsyncTimestamp(0); Loading services/surfaceflinger/tests/unittests/TestableScheduler.h +7 −9 Original line number Diff line number Diff line Loading @@ -53,7 +53,7 @@ public: factory, selectorPtr->getActiveMode().fps, timeStats) { const auto displayId = selectorPtr->getActiveMode().modePtr->getPhysicalDisplayId(); registerDisplay(displayId, std::move(selectorPtr), std::move(controller), std::move(tracker)); std::move(tracker), displayId); ON_CALL(*this, postMessage).WillByDefault([](sp<MessageHandler>&& handler) { // Execute task to prevent broken promise exception on destruction. Loading Loading @@ -85,14 +85,16 @@ public: void registerDisplay( PhysicalDisplayId displayId, RefreshRateSelectorPtr selectorPtr, std::optional<PhysicalDisplayId> activeDisplayIdOpt = {}, std::shared_ptr<VSyncTracker> vsyncTracker = std::make_shared<mock::VSyncTracker>()) { registerDisplay(displayId, std::move(selectorPtr), std::make_unique<mock::VsyncController>(), vsyncTracker); std::make_unique<mock::VsyncController>(), vsyncTracker, activeDisplayIdOpt.value_or(displayId)); } void registerDisplay(PhysicalDisplayId displayId, RefreshRateSelectorPtr selectorPtr, std::unique_ptr<VsyncController> controller, std::shared_ptr<VSyncTracker> tracker) { std::shared_ptr<VSyncTracker> tracker, PhysicalDisplayId activeDisplayId) { ftl::FakeGuard guard(kMainThreadContext); Scheduler::registerDisplayInternal(displayId, std::move(selectorPtr), std::shared_ptr<VsyncSchedule>( Loading @@ -101,16 +103,12 @@ public: mock::VSyncDispatch>(), std::move(controller), mockRequestHardwareVsync .AsStdFunction()))); .AsStdFunction())), activeDisplayId); } testing::MockFunction<void(PhysicalDisplayId, bool)> mockRequestHardwareVsync; void unregisterDisplay(PhysicalDisplayId displayId) { ftl::FakeGuard guard(kMainThreadContext); Scheduler::unregisterDisplay(displayId); } std::optional<PhysicalDisplayId> pacesetterDisplayId() const NO_THREAD_SAFETY_ANALYSIS { return mPacesetterDisplayId; } Loading Loading
services/surfaceflinger/Scheduler/Scheduler.cpp +11 −6 Original line number Diff line number Diff line Loading @@ -123,19 +123,22 @@ void Scheduler::setPacesetterDisplay(std::optional<PhysicalDisplayId> pacesetter promotePacesetterDisplay(pacesetterIdOpt); } void Scheduler::registerDisplay(PhysicalDisplayId displayId, RefreshRateSelectorPtr selectorPtr) { void Scheduler::registerDisplay(PhysicalDisplayId displayId, RefreshRateSelectorPtr selectorPtr, PhysicalDisplayId activeDisplayId) { auto schedulePtr = std::make_shared<VsyncSchedule>(selectorPtr->getActiveMode().modePtr, mFeatures, [this](PhysicalDisplayId id, bool enable) { onHardwareVsyncRequest(id, enable); }); registerDisplayInternal(displayId, std::move(selectorPtr), std::move(schedulePtr)); registerDisplayInternal(displayId, std::move(selectorPtr), std::move(schedulePtr), activeDisplayId); } void Scheduler::registerDisplayInternal(PhysicalDisplayId displayId, RefreshRateSelectorPtr selectorPtr, VsyncSchedulePtr schedulePtr) { VsyncSchedulePtr schedulePtr, PhysicalDisplayId activeDisplayId) { demotePacesetterDisplay(); auto [pacesetterVsyncSchedule, isNew] = [&]() FTL_FAKE_GUARD(kMainThreadContext) { Loading @@ -145,7 +148,7 @@ void Scheduler::registerDisplayInternal(PhysicalDisplayId displayId, std::move(schedulePtr), mFeatures) .second; return std::make_pair(promotePacesetterDisplayLocked(), isNew); return std::make_pair(promotePacesetterDisplayLocked(activeDisplayId), isNew); }(); applyNewVsyncSchedule(std::move(pacesetterVsyncSchedule)); Loading @@ -158,7 +161,9 @@ void Scheduler::registerDisplayInternal(PhysicalDisplayId displayId, dispatchHotplug(displayId, Hotplug::Connected); } void Scheduler::unregisterDisplay(PhysicalDisplayId displayId) { void Scheduler::unregisterDisplay(PhysicalDisplayId displayId, PhysicalDisplayId activeDisplayId) { LOG_ALWAYS_FATAL_IF(displayId == activeDisplayId, "Cannot unregister the active display!"); dispatchHotplug(displayId, Hotplug::Disconnected); demotePacesetterDisplay(); Loading @@ -173,7 +178,7 @@ void Scheduler::unregisterDisplay(PhysicalDisplayId displayId) { // headless virtual display.) LOG_ALWAYS_FATAL_IF(mDisplays.empty(), "Cannot unregister all displays!"); pacesetterVsyncSchedule = promotePacesetterDisplayLocked(); pacesetterVsyncSchedule = promotePacesetterDisplayLocked(activeDisplayId); } applyNewVsyncSchedule(std::move(pacesetterVsyncSchedule)); } Loading
services/surfaceflinger/Scheduler/Scheduler.h +12 −4 Original line number Diff line number Diff line Loading @@ -101,9 +101,16 @@ public: using ConstVsyncSchedulePtr = std::shared_ptr<const VsyncSchedule>; using VsyncSchedulePtr = std::shared_ptr<VsyncSchedule>; void registerDisplay(PhysicalDisplayId, RefreshRateSelectorPtr) REQUIRES(kMainThreadContext) // After registration/unregistration, `activeDisplayId` is promoted to pacesetter. Note that the // active display is never unregistered, since hotplug disconnect never happens for activatable // displays, i.e. a foldable's internal displays or otherwise the (internal or external) primary // display. // TODO: b/255635821 - Remove active display parameters. void registerDisplay(PhysicalDisplayId, RefreshRateSelectorPtr, PhysicalDisplayId activeDisplayId) REQUIRES(kMainThreadContext) EXCLUDES(mDisplayLock); void unregisterDisplay(PhysicalDisplayId) REQUIRES(kMainThreadContext) EXCLUDES(mDisplayLock); void unregisterDisplay(PhysicalDisplayId, PhysicalDisplayId activeDisplayId) REQUIRES(kMainThreadContext) EXCLUDES(mDisplayLock); void run(); Loading Loading @@ -388,8 +395,9 @@ private: // 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, VsyncSchedulePtr) REQUIRES(kMainThreadContext) EXCLUDES(mDisplayLock); void registerDisplayInternal(PhysicalDisplayId, RefreshRateSelectorPtr, VsyncSchedulePtr, PhysicalDisplayId activeDisplayId) REQUIRES(kMainThreadContext) EXCLUDES(mDisplayLock); struct Policy; Loading
services/surfaceflinger/SurfaceFlinger.cpp +5 −3 Original line number Diff line number Diff line Loading @@ -3736,7 +3736,8 @@ void SurfaceFlinger::processDisplayAdded(const wp<IBinder>& displayToken, ftl::FakeGuard guard(kMainThreadContext); // For hotplug reconnect, renew the registration since display modes have been reloaded. mScheduler->registerDisplay(display->getPhysicalId(), display->holdRefreshRateSelector()); mScheduler->registerDisplay(display->getPhysicalId(), display->holdRefreshRateSelector(), mActiveDisplayId); } if (display->isVirtual()) { Loading Loading @@ -3775,7 +3776,7 @@ void SurfaceFlinger::processDisplayRemoved(const wp<IBinder>& displayToken) { if (display->isVirtual()) { releaseVirtualDisplay(display->getVirtualId()); } else { mScheduler->unregisterDisplay(display->getPhysicalId()); mScheduler->unregisterDisplay(display->getPhysicalId(), mActiveDisplayId); } } Loading Loading @@ -4395,7 +4396,8 @@ void SurfaceFlinger::initScheduler(const sp<const DisplayDevice>& display) { getFactory(), activeRefreshRate, *mTimeStats); // The pacesetter must be registered before EventThread creation below. mScheduler->registerDisplay(display->getPhysicalId(), display->holdRefreshRateSelector()); mScheduler->registerDisplay(display->getPhysicalId(), display->holdRefreshRateSelector(), mActiveDisplayId); if (FlagManager::getInstance().vrr_config()) { mScheduler->setRenderRate(display->getPhysicalId(), activeMode.fps); } Loading
services/surfaceflinger/tests/unittests/SchedulerTest.cpp +16 −9 Original line number Diff line number Diff line Loading @@ -337,12 +337,15 @@ TEST_F(SchedulerTest, chooseDisplayModesSingleDisplayHighHintTouchSignal) { } TEST_F(SchedulerTest, chooseDisplayModesMultipleDisplays) { constexpr PhysicalDisplayId kActiveDisplayId = kDisplayId1; mScheduler->registerDisplay(kDisplayId1, std::make_shared<RefreshRateSelector>(kDisplay1Modes, kDisplay1Mode60->getId())); kDisplay1Mode60->getId()), kActiveDisplayId); mScheduler->registerDisplay(kDisplayId2, std::make_shared<RefreshRateSelector>(kDisplay2Modes, kDisplay2Mode60->getId())); kDisplay2Mode60->getId()), kActiveDisplayId); using DisplayModeChoice = TestableScheduler::DisplayModeChoice; TestableScheduler::DisplayModeChoiceMap expectedChoices; Loading Loading @@ -402,10 +405,10 @@ TEST_F(SchedulerTest, chooseDisplayModesMultipleDisplays) { { // The kDisplayId3 does not support 120Hz, The pacesetter display rate is chosen to be 120 // Hz. In this case only the display kDisplayId3 choose 60Hz as it does not support 120Hz. mScheduler ->registerDisplay(kDisplayId3, mScheduler->registerDisplay(kDisplayId3, std::make_shared<RefreshRateSelector>(kDisplay3Modes, kDisplay3Mode60->getId())); kDisplay3Mode60->getId()), kActiveDisplayId); const GlobalSignals globalSignals = {.touch = true}; mScheduler->replaceTouchTimer(10); Loading Loading @@ -447,12 +450,15 @@ TEST_F(SchedulerTest, chooseDisplayModesMultipleDisplays) { } TEST_F(SchedulerTest, onFrameSignalMultipleDisplays) { constexpr PhysicalDisplayId kActiveDisplayId = kDisplayId1; mScheduler->registerDisplay(kDisplayId1, std::make_shared<RefreshRateSelector>(kDisplay1Modes, kDisplay1Mode60->getId())); kDisplay1Mode60->getId()), kActiveDisplayId); mScheduler->registerDisplay(kDisplayId2, std::make_shared<RefreshRateSelector>(kDisplay2Modes, kDisplay2Mode60->getId())); kDisplay2Mode60->getId()), kActiveDisplayId); using VsyncIds = std::vector<std::pair<PhysicalDisplayId, VsyncId>>; Loading Loading @@ -574,7 +580,8 @@ TEST_F(SchedulerTest, nextFrameIntervalTest) { mFlinger.getTimeStats(), mSchedulerCallback}; scheduler.registerDisplay(kMode->getPhysicalDisplayId(), vrrSelectorPtr, vrrTracker); scheduler.registerDisplay(kMode->getPhysicalDisplayId(), vrrSelectorPtr, std::nullopt, vrrTracker); vrrSelectorPtr->setActiveMode(kMode->getId(), frameRate); scheduler.setRenderRate(kMode->getPhysicalDisplayId(), frameRate); vrrTracker->addVsyncTimestamp(0); Loading
services/surfaceflinger/tests/unittests/TestableScheduler.h +7 −9 Original line number Diff line number Diff line Loading @@ -53,7 +53,7 @@ public: factory, selectorPtr->getActiveMode().fps, timeStats) { const auto displayId = selectorPtr->getActiveMode().modePtr->getPhysicalDisplayId(); registerDisplay(displayId, std::move(selectorPtr), std::move(controller), std::move(tracker)); std::move(tracker), displayId); ON_CALL(*this, postMessage).WillByDefault([](sp<MessageHandler>&& handler) { // Execute task to prevent broken promise exception on destruction. Loading Loading @@ -85,14 +85,16 @@ public: void registerDisplay( PhysicalDisplayId displayId, RefreshRateSelectorPtr selectorPtr, std::optional<PhysicalDisplayId> activeDisplayIdOpt = {}, std::shared_ptr<VSyncTracker> vsyncTracker = std::make_shared<mock::VSyncTracker>()) { registerDisplay(displayId, std::move(selectorPtr), std::make_unique<mock::VsyncController>(), vsyncTracker); std::make_unique<mock::VsyncController>(), vsyncTracker, activeDisplayIdOpt.value_or(displayId)); } void registerDisplay(PhysicalDisplayId displayId, RefreshRateSelectorPtr selectorPtr, std::unique_ptr<VsyncController> controller, std::shared_ptr<VSyncTracker> tracker) { std::shared_ptr<VSyncTracker> tracker, PhysicalDisplayId activeDisplayId) { ftl::FakeGuard guard(kMainThreadContext); Scheduler::registerDisplayInternal(displayId, std::move(selectorPtr), std::shared_ptr<VsyncSchedule>( Loading @@ -101,16 +103,12 @@ public: mock::VSyncDispatch>(), std::move(controller), mockRequestHardwareVsync .AsStdFunction()))); .AsStdFunction())), activeDisplayId); } testing::MockFunction<void(PhysicalDisplayId, bool)> mockRequestHardwareVsync; void unregisterDisplay(PhysicalDisplayId displayId) { ftl::FakeGuard guard(kMainThreadContext); Scheduler::unregisterDisplay(displayId); } std::optional<PhysicalDisplayId> pacesetterDisplayId() const NO_THREAD_SAFETY_ANALYSIS { return mPacesetterDisplayId; } Loading