diff options
6 files changed, 53 insertions, 33 deletions
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp index 819b952074..4cd4c6d638 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.cpp +++ b/services/surfaceflinger/Scheduler/Scheduler.cpp @@ -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) { @@ -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)); @@ -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(); @@ -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)); } diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h index fc935cd3c4..7a3007945b 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.h +++ b/services/surfaceflinger/Scheduler/Scheduler.h @@ -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(); @@ -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; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index cf5f55d7bd..b75be37119 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3717,7 +3717,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()) { @@ -3756,7 +3757,7 @@ void SurfaceFlinger::processDisplayRemoved(const wp<IBinder>& displayToken) { if (display->isVirtual()) { releaseVirtualDisplay(display->getVirtualId()); } else { - mScheduler->unregisterDisplay(display->getPhysicalId()); + mScheduler->unregisterDisplay(display->getPhysicalId(), mActiveDisplayId); } } @@ -4376,7 +4377,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); } diff --git a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp index 03c12d6f73..be3fce669f 100644 --- a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp +++ b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp @@ -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; @@ -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, - std::make_shared<RefreshRateSelector>(kDisplay3Modes, - kDisplay3Mode60->getId())); + mScheduler->registerDisplay(kDisplayId3, + std::make_shared<RefreshRateSelector>(kDisplay3Modes, + kDisplay3Mode60->getId()), + kActiveDisplayId); const GlobalSignals globalSignals = {.touch = true}; mScheduler->replaceTouchTimer(10); @@ -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>>; @@ -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); diff --git a/services/surfaceflinger/tests/unittests/TestableScheduler.h b/services/surfaceflinger/tests/unittests/TestableScheduler.h index 1472ebf009..e436273c9e 100644 --- a/services/surfaceflinger/tests/unittests/TestableScheduler.h +++ b/services/surfaceflinger/tests/unittests/TestableScheduler.h @@ -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. @@ -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>( @@ -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; } diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h index bce7729d80..99223f0aa3 100644 --- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h @@ -1079,8 +1079,8 @@ public: if (mFlinger.scheduler() && mRegisterDisplay) { mFlinger.scheduler()->registerDisplay(physicalId, display->holdRefreshRateSelector(), - std::move(controller), - std::move(tracker)); + std::move(controller), std::move(tracker), + mFlinger.mutableActiveDisplayId()); } display->setActiveMode(activeModeId, fps, fps); |