Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7e74d2ca authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Only call onNewVsyncSchedule if the pacesetter changes" into udc-dev

parents ed6c3def d649463a
Loading
Loading
Loading
Loading
+24 −10
Original line number Diff line number Diff line
@@ -130,7 +130,7 @@ void Scheduler::registerDisplayInternal(PhysicalDisplayId displayId,

        pacesetterVsyncSchedule = promotePacesetterDisplayLocked();
    }
    applyNewVsyncSchedule(std::move(pacesetterVsyncSchedule));
    applyNewVsyncScheduleIfNonNull(std::move(pacesetterVsyncSchedule));
}

void Scheduler::unregisterDisplay(PhysicalDisplayId displayId) {
@@ -149,7 +149,7 @@ void Scheduler::unregisterDisplay(PhysicalDisplayId displayId) {

        pacesetterVsyncSchedule = promotePacesetterDisplayLocked();
    }
    applyNewVsyncSchedule(std::move(pacesetterVsyncSchedule));
    applyNewVsyncScheduleIfNonNull(std::move(pacesetterVsyncSchedule));
}

void Scheduler::run() {
@@ -693,16 +693,17 @@ void Scheduler::promotePacesetterDisplay(std::optional<PhysicalDisplayId> pacese
        pacesetterVsyncSchedule = promotePacesetterDisplayLocked(pacesetterIdOpt);
    }

    applyNewVsyncSchedule(std::move(pacesetterVsyncSchedule));
    applyNewVsyncScheduleIfNonNull(std::move(pacesetterVsyncSchedule));
}

std::shared_ptr<VsyncSchedule> Scheduler::promotePacesetterDisplayLocked(
        std::optional<PhysicalDisplayId> pacesetterIdOpt) {
    // TODO(b/241286431): Choose the pacesetter display.
    const auto oldPacesetterDisplayIdOpt = mPacesetterDisplayId;
    mPacesetterDisplayId = pacesetterIdOpt.value_or(mRefreshRateSelectors.begin()->first);
    ALOGI("Display %s is the pacesetter", to_string(*mPacesetterDisplayId).c_str());

    auto vsyncSchedule = getVsyncScheduleLocked(*mPacesetterDisplayId);
    auto newVsyncSchedule = getVsyncScheduleLocked(*mPacesetterDisplayId);
    if (const auto pacesetterPtr = pacesetterSelectorPtrLocked()) {
        pacesetterPtr->setIdleTimerCallbacks(
                {.platform = {.onReset = [this] { idleTimerCallback(TimerState::Reset); },
@@ -713,15 +714,28 @@ std::shared_ptr<VsyncSchedule> Scheduler::promotePacesetterDisplayLocked(

        pacesetterPtr->startIdleTimer();

        // Track the new period, which may have changed due to switching to a
        // new pacesetter or due to a hotplug event. In the former case, this
        // is important so that VSYNC modulation does not get stuck in the
        // initiated state if a transition started on the old pacesetter.
        const Fps refreshRate = pacesetterPtr->getActiveMode().modePtr->getFps();
        vsyncSchedule->startPeriodTransition(mSchedulerCallback, refreshRate.getPeriod(),
        newVsyncSchedule->startPeriodTransition(mSchedulerCallback, refreshRate.getPeriod(),
                                                true /* force */);
    }
    return vsyncSchedule;
    if (oldPacesetterDisplayIdOpt == mPacesetterDisplayId) {
        return nullptr;
    }
    return newVsyncSchedule;
}

void Scheduler::applyNewVsyncSchedule(std::shared_ptr<VsyncSchedule> vsyncSchedule) {
    onNewVsyncSchedule(vsyncSchedule->getDispatch());
void Scheduler::applyNewVsyncScheduleIfNonNull(
        std::shared_ptr<VsyncSchedule> pacesetterSchedulePtr) {
    if (!pacesetterSchedulePtr) {
        // The pacesetter has not changed, so there is no new VsyncSchedule to
        // apply.
        return;
    }
    onNewVsyncSchedule(pacesetterSchedulePtr->getDispatch());
    std::vector<android::EventThread*> threads;
    {
        std::lock_guard<std::mutex> lock(mConnectionsLock);
@@ -731,7 +745,7 @@ void Scheduler::applyNewVsyncSchedule(std::shared_ptr<VsyncSchedule> vsyncSchedu
        }
    }
    for (auto* thread : threads) {
        thread->onNewVsyncSchedule(vsyncSchedule);
        thread->onNewVsyncSchedule(pacesetterSchedulePtr);
    }
}

+3 −1
Original line number Diff line number Diff line
@@ -329,10 +329,12 @@ private:
    // MessageQueue and EventThread need to use the new pacesetter's
    // VsyncSchedule, and this must happen while mDisplayLock is *not* locked,
    // or else we may deadlock with EventThread.
    // Returns the new pacesetter's VsyncSchedule, or null if the pacesetter is
    // unchanged.
    std::shared_ptr<VsyncSchedule> promotePacesetterDisplayLocked(
            std::optional<PhysicalDisplayId> pacesetterIdOpt = std::nullopt)
            REQUIRES(kMainThreadContext, mDisplayLock);
    void applyNewVsyncSchedule(std::shared_ptr<VsyncSchedule>) EXCLUDES(mDisplayLock);
    void applyNewVsyncScheduleIfNonNull(std::shared_ptr<VsyncSchedule>) EXCLUDES(mDisplayLock);

    // Blocks until the pacesetter's idle timer thread exits. `mDisplayLock` must not be locked by
    // the caller on the main thread to avoid deadlock, since the timer thread locks it before exit.
+19 −0
Original line number Diff line number Diff line
@@ -384,4 +384,23 @@ TEST_F(SchedulerTest, chooseDisplayModesMultipleDisplays) {
    }
}

TEST_F(SchedulerTest, changingPacesetterChangesVsyncSchedule) {
    // Add a second display so we can change the pacesetter.
    mScheduler->registerDisplay(kDisplayId2,
                                std::make_shared<RefreshRateSelector>(kDisplay2Modes,
                                                                      kDisplay2Mode60->getId()));
    // Ensure that the pacesetter is the one we expect.
    mScheduler->setPacesetterDisplay(kDisplayId1);

    // Switching to the other will call onNewVsyncSchedule.
    EXPECT_CALL(*mEventThread, onNewVsyncSchedule(mScheduler->getVsyncSchedule(kDisplayId2)))
            .Times(1);
    mScheduler->setPacesetterDisplay(kDisplayId2);
}

TEST_F(SchedulerTest, promotingSamePacesetterDoesNotChangeVsyncSchedule) {
    EXPECT_CALL(*mEventThread, onNewVsyncSchedule(_)).Times(0);
    mScheduler->setPacesetterDisplay(kDisplayId1);
}

} // namespace android::scheduler