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

Commit 1ab20c51 authored by Dominik Laskowski's avatar Dominik Laskowski
Browse files

SF: Remove DisplayDevice::ActiveModeInfo

This type is redundant with DisplayModeRequest, so store the desired and
pending modes as DisplayModeRequestOpt. This is a step toward flowing
the request through one of desired/pending/active states.

Use the std::nullopt state of the desired mode instead of relying on the
implicitly associated TracedOrdinal<bool>.

Bug: 241285876
Test: presubmit
Change-Id: Ie12a5ad420745761c73b1ce2c536862f79a50665
parent 86382017
Loading
Loading
Loading
Loading
+24 −31
Original line number Diff line number Diff line
@@ -70,7 +70,7 @@ DisplayDevice::DisplayDevice(DisplayDeviceCreationArgs& args)
        mIsPrimary(args.isPrimary),
        mRequestedRefreshRate(args.requestedRefreshRate),
        mRefreshRateSelector(std::move(args.refreshRateSelector)),
        mDesiredModeChanged(concatId("DesiredModeChanged"), false) {
        mHasDesiredModeTrace(concatId("HasDesiredMode"), false) {
    mCompositionDisplay->editState().isSecure = args.isSecure;
    mCompositionDisplay->createRenderSurface(
            compositionengine::RenderSurfaceCreationArgsBuilder()
@@ -217,20 +217,13 @@ void DisplayDevice::setActiveMode(DisplayModeId modeId, Fps vsyncRate, Fps rende
    updateRefreshRateOverlayRate(vsyncRate, renderFps);
}

bool DisplayDevice::initiateModeChange(const ActiveModeInfo& info,
bool DisplayDevice::initiateModeChange(display::DisplayModeRequest&& desiredMode,
                                       const hal::VsyncPeriodChangeConstraints& constraints,
                                       hal::VsyncPeriodChangeTimeline& outTimeline) {
    if (!info.modeOpt || info.modeOpt->modePtr->getPhysicalDisplayId() != getPhysicalId()) {
        ALOGE("Trying to initiate a mode change to invalid mode %s on display %s",
              info.modeOpt ? std::to_string(info.modeOpt->modePtr->getId().value()).c_str()
                           : "null",
              to_string(getId()).c_str());
        return BAD_VALUE;
    }
    mPendingMode = info;
    mPendingModeOpt = std::move(desiredMode);
    mIsModeSetPending = true;

    const auto& mode = *info.modeOpt->modePtr;
    const auto& mode = *mPendingModeOpt->mode.modePtr;

    if (mHwComposer.setActiveModeWithConstraints(getPhysicalId(), mode.getHwcId(), constraints,
                                                 &outTimeline) != OK) {
@@ -528,35 +521,36 @@ void DisplayDevice::animateOverlay() {
    }
}

auto DisplayDevice::setDesiredMode(const ActiveModeInfo& info, bool force) -> DesiredModeAction {
auto DisplayDevice::setDesiredMode(display::DisplayModeRequest&& desiredMode, bool force)
        -> DesiredModeAction {
    ATRACE_CALL();

    LOG_ALWAYS_FATAL_IF(!info.modeOpt, "desired mode not provided");
    LOG_ALWAYS_FATAL_IF(getPhysicalId() != info.modeOpt->modePtr->getPhysicalDisplayId(),
    const auto& desiredModePtr = desiredMode.mode.modePtr;

    LOG_ALWAYS_FATAL_IF(getPhysicalId() != desiredModePtr->getPhysicalDisplayId(),
                        "DisplayId mismatch");

    ALOGV("%s(%s)", __func__, to_string(*info.modeOpt->modePtr).c_str());
    ALOGV("%s(%s)", __func__, to_string(*desiredModePtr).c_str());

    std::scoped_lock lock(mDesiredModeLock);
    if (mDesiredModeChanged) {
    if (mDesiredModeOpt) {
        // A mode transition was already scheduled, so just override the desired mode.
        const auto event = mDesiredMode.event;
        mDesiredMode = info;
        mDesiredMode.event = mDesiredMode.event | event;
        const bool emitEvent = mDesiredModeOpt->emitEvent;
        mDesiredModeOpt = std::move(desiredMode);
        mDesiredModeOpt->emitEvent |= emitEvent;
        return DesiredModeAction::None;
    }

    const auto& desiredMode = *info.modeOpt->modePtr;

    // If the desired mode is already active...
    const auto activeMode = refreshRateSelector().getActiveMode();
    if (!force && activeMode.modePtr->getId() == desiredMode.getId()) {
        if (activeMode == info.modeOpt) {
    if (!force && activeMode.modePtr->getId() == desiredModePtr->getId()) {
        if (activeMode == desiredMode.mode) {
            return DesiredModeAction::None;
        }

        // ...but the render rate changed:
        setActiveMode(desiredMode.getId(), desiredMode.getVsyncRate(), info.modeOpt->fps);
        setActiveMode(desiredModePtr->getId(), desiredModePtr->getVsyncRate(),
                      desiredMode.mode.fps);
        return DesiredModeAction::InitiateRenderRateSwitch;
    }

@@ -566,21 +560,20 @@ auto DisplayDevice::setDesiredMode(const ActiveModeInfo& info, bool force) -> De
                  activeMode.modePtr->getVsyncRate());

    // Initiate a mode change.
    mDesiredModeChanged = true;
    mDesiredMode = info;
    mDesiredModeOpt = std::move(desiredMode);
    mHasDesiredModeTrace = true;
    return DesiredModeAction::InitiateDisplayModeSwitch;
}

auto DisplayDevice::getDesiredMode() const -> ftl::Optional<ActiveModeInfo> {
auto DisplayDevice::getDesiredMode() const -> DisplayModeRequestOpt {
    std::scoped_lock lock(mDesiredModeLock);
    if (mDesiredModeChanged) return mDesiredMode;
    return std::nullopt;
    return mDesiredModeOpt;
}

void DisplayDevice::clearDesiredMode() {
    std::scoped_lock lock(mDesiredModeLock);
    mDesiredMode.event = scheduler::DisplayModeEvent::None;
    mDesiredModeChanged = false;
    mDesiredModeOpt.reset();
    mHasDesiredModeTrace = false;
}

void DisplayDevice::adjustRefreshRate(Fps pacesetterDisplayRefreshRate) {
+11 −27
Original line number Diff line number Diff line
@@ -186,35 +186,19 @@ public:
     * Display mode management.
     */

    // TODO(b/241285876): Replace ActiveModeInfo and DisplayModeEvent with DisplayModeRequest.
    struct ActiveModeInfo {
        using Event = scheduler::DisplayModeEvent;

        ActiveModeInfo() = default;
        ActiveModeInfo(scheduler::FrameRateMode mode, Event event)
              : modeOpt(std::move(mode)), event(event) {}

        explicit ActiveModeInfo(display::DisplayModeRequest&& request)
              : ActiveModeInfo(std::move(request.mode),
                               request.emitEvent ? Event::Changed : Event::None) {}

        ftl::Optional<scheduler::FrameRateMode> modeOpt;
        Event event = Event::None;

        bool operator!=(const ActiveModeInfo& other) const {
            return modeOpt != other.modeOpt || event != other.event;
        }
    };

    enum class DesiredModeAction { None, InitiateDisplayModeSwitch, InitiateRenderRateSwitch };

    DesiredModeAction setDesiredMode(const ActiveModeInfo&, bool force = false)
    DesiredModeAction setDesiredMode(display::DisplayModeRequest&&, bool force = false)
            EXCLUDES(mDesiredModeLock);

    ftl::Optional<ActiveModeInfo> getDesiredMode() const EXCLUDES(mDesiredModeLock);
    using DisplayModeRequestOpt = ftl::Optional<display::DisplayModeRequest>;

    DisplayModeRequestOpt getDesiredMode() const EXCLUDES(mDesiredModeLock);
    void clearDesiredMode() EXCLUDES(mDesiredModeLock);

    ActiveModeInfo getPendingMode() const REQUIRES(kMainThreadContext) { return mPendingMode; }
    DisplayModeRequestOpt getPendingMode() const REQUIRES(kMainThreadContext) {
        return mPendingModeOpt;
    }
    bool isModeSetPending() const REQUIRES(kMainThreadContext) { return mIsModeSetPending; }

    scheduler::FrameRateMode getActiveMode() const REQUIRES(kMainThreadContext) {
@@ -223,7 +207,7 @@ public:

    void setActiveMode(DisplayModeId, Fps vsyncRate, Fps renderFps);

    bool initiateModeChange(const ActiveModeInfo&, const hal::VsyncPeriodChangeConstraints&,
    bool initiateModeChange(display::DisplayModeRequest&&, const hal::VsyncPeriodChangeConstraints&,
                            hal::VsyncPeriodChangeTimeline& outTimeline)
            REQUIRES(kMainThreadContext);

@@ -316,10 +300,10 @@ private:
    float mHdrSdrRatio = 1.0f;

    mutable std::mutex mDesiredModeLock;
    ActiveModeInfo mDesiredMode GUARDED_BY(mDesiredModeLock);
    TracedOrdinal<bool> mDesiredModeChanged GUARDED_BY(mDesiredModeLock);
    DisplayModeRequestOpt mDesiredModeOpt GUARDED_BY(mDesiredModeLock);
    TracedOrdinal<bool> mHasDesiredModeTrace GUARDED_BY(mDesiredModeLock);

    ActiveModeInfo mPendingMode GUARDED_BY(kMainThreadContext);
    DisplayModeRequestOpt mPendingModeOpt GUARDED_BY(kMainThreadContext);
    bool mIsModeSetPending GUARDED_BY(kMainThreadContext) = false;
};

+0 −7
Original line number Diff line number Diff line
@@ -39,13 +39,6 @@ namespace android::scheduler {

using namespace std::chrono_literals;

enum class DisplayModeEvent : unsigned { None = 0b0, Changed = 0b1 };

inline DisplayModeEvent operator|(DisplayModeEvent lhs, DisplayModeEvent rhs) {
    using T = std::underlying_type_t<DisplayModeEvent>;
    return static_cast<DisplayModeEvent>(static_cast<T>(lhs) | static_cast<T>(rhs));
}

using FrameRateOverride = DisplayEventReceiver::Event::FrameRateOverride;

// Selects the refresh rate of a display by ranking its `DisplayModes` in accordance with
+24 −23
Original line number Diff line number Diff line
@@ -1190,7 +1190,7 @@ void SurfaceFlinger::setDesiredMode(display::DisplayModeRequest&& request, bool
    const auto mode = request.mode;
    const bool emitEvent = request.emitEvent;

    switch (display->setDesiredMode(DisplayDevice::ActiveModeInfo(std::move(request)), force)) {
    switch (display->setDesiredMode(std::move(request), force)) {
        case DisplayDevice::DesiredModeAction::InitiateDisplayModeSwitch:
            // DisplayDevice::setDesiredMode updated the render rate, so inform Scheduler.
            mScheduler->setRenderRate(displayId,
@@ -1286,27 +1286,27 @@ void SurfaceFlinger::finalizeDisplayModeChange(DisplayDevice& display) {
    const auto displayId = display.getPhysicalId();
    ATRACE_NAME(ftl::Concat(__func__, ' ', displayId.value).c_str());

    const auto pendingMode = display.getPendingMode();
    if (!pendingMode.modeOpt) {
    const auto pendingModeOpt = display.getPendingMode();
    if (!pendingModeOpt) {
        // There is no pending mode change. This can happen if the active
        // display changed and the mode change happened on a different display.
        return;
    }

    if (display.getActiveMode().modePtr->getResolution() !=
        pendingMode.modeOpt->modePtr->getResolution()) {
    const auto& activeMode = pendingModeOpt->mode;

    if (display.getActiveMode().modePtr->getResolution() != activeMode.modePtr->getResolution()) {
        auto& state = mCurrentState.displays.editValueFor(display.getDisplayToken());
        // We need to generate new sequenceId in order to recreate the display (and this
        // way the framebuffer).
        state.sequenceId = DisplayDeviceState{}.sequenceId;
        state.physical->activeMode = pendingMode.modeOpt->modePtr.get();
        state.physical->activeMode = activeMode.modePtr.get();
        processDisplayChangesLocked();

        // processDisplayChangesLocked will update all necessary components so we're done here.
        return;
    }

    const auto& activeMode = *pendingMode.modeOpt;
    display.finalizeModeChange(activeMode.modePtr->getId(), activeMode.modePtr->getVsyncRate(),
                               activeMode.fps);

@@ -1315,7 +1315,7 @@ void SurfaceFlinger::finalizeDisplayModeChange(DisplayDevice& display) {
        updatePhaseConfiguration(activeMode.fps);
    }

    if (pendingMode.event != scheduler::DisplayModeEvent::None) {
    if (pendingModeOpt->emitEvent) {
        dispatchDisplayModeChangeEvent(displayId, activeMode);
    }
}
@@ -1329,12 +1329,15 @@ void SurfaceFlinger::dropModeRequest(const sp<DisplayDevice>& display) {
}

void SurfaceFlinger::applyActiveMode(const sp<DisplayDevice>& display) {
    const auto desiredModeOpt = display->getDesiredMode();
    const auto& modeOpt = desiredModeOpt->modeOpt;
    const auto displayId = modeOpt->modePtr->getPhysicalDisplayId();
    const auto renderFps = modeOpt->fps;
    const auto activeModeOpt = display->getDesiredMode();
    auto activeModePtr = activeModeOpt->mode.modePtr;
    const auto displayId = activeModePtr->getPhysicalDisplayId();
    const auto renderFps = activeModeOpt->mode.fps;

    dropModeRequest(display);
    mScheduler->resyncToHardwareVsync(displayId, true /* allowToEnable */, modeOpt->modePtr.get());

    constexpr bool kAllowToEnable = true;
    mScheduler->resyncToHardwareVsync(displayId, kAllowToEnable, std::move(activeModePtr).take());
    mScheduler->setRenderRate(displayId, renderFps);

    if (displayId == mActiveDisplayId) {
@@ -1351,7 +1354,7 @@ void SurfaceFlinger::initiateDisplayModeChanges() {
        const auto display = getDisplayDeviceLocked(id);
        if (!display) continue;

        const auto desiredModeOpt = display->getDesiredMode();
        auto desiredModeOpt = display->getDesiredMode();
        if (!desiredModeOpt) {
            continue;
        }
@@ -1361,7 +1364,7 @@ void SurfaceFlinger::initiateDisplayModeChanges() {
            continue;
        }

        const auto desiredModeId = desiredModeOpt->modeOpt->modePtr->getId();
        const auto desiredModeId = desiredModeOpt->mode.modePtr->getId();
        const auto displayModePtrOpt = physical.snapshot().displayModes().get(desiredModeId);

        if (!displayModePtrOpt) {
@@ -1375,7 +1378,7 @@ void SurfaceFlinger::initiateDisplayModeChanges() {
              to_string(displayModePtrOpt->get()->getVsyncRate()).c_str(),
              to_string(display->getId()).c_str());

        if (display->getActiveMode() == desiredModeOpt->modeOpt) {
        if (display->getActiveMode() == desiredModeOpt->mode) {
            applyActiveMode(display);
            continue;
        }
@@ -1383,9 +1386,7 @@ void SurfaceFlinger::initiateDisplayModeChanges() {
        // Desired active mode was set, it is different than the mode currently in use, however
        // allowed modes might have changed by the time we process the refresh.
        // Make sure the desired mode is still allowed
        const auto displayModeAllowed =
                display->refreshRateSelector().isModeAllowed(*desiredModeOpt->modeOpt);
        if (!displayModeAllowed) {
        if (!display->refreshRateSelector().isModeAllowed(desiredModeOpt->mode)) {
            dropModeRequest(display);
            continue;
        }
@@ -1396,7 +1397,7 @@ void SurfaceFlinger::initiateDisplayModeChanges() {
        constraints.seamlessRequired = false;
        hal::VsyncPeriodChangeTimeline outTimeline;

        if (!display->initiateModeChange(*desiredModeOpt, constraints, outTimeline)) {
        if (!display->initiateModeChange(std::move(*desiredModeOpt), constraints, outTimeline)) {
            continue;
        }

@@ -1418,7 +1419,7 @@ void SurfaceFlinger::initiateDisplayModeChanges() {
        finalizeDisplayModeChange(*display);

        const auto desiredModeOpt = display->getDesiredMode();
        if (desiredModeOpt && display->getActiveMode() == desiredModeOpt->modeOpt) {
        if (desiredModeOpt && display->getActiveMode() == desiredModeOpt->mode) {
            applyActiveMode(display);
        }
    }
@@ -7286,8 +7287,8 @@ void SurfaceFlinger::kernelTimerChanged(bool expired) {
        if (!display->isRefreshRateOverlayEnabled()) return;

        const auto desiredModeIdOpt =
                display->getDesiredMode().transform([](const DisplayDevice::ActiveModeInfo& info) {
                    return info.modeOpt->modePtr->getId();
                display->getDesiredMode().transform([](const display::DisplayModeRequest& request) {
                    return request.mode.modePtr->getId();
                });

        const bool timerExpired = mKernelIdleTimerEnabled && expired;
+28 −36
Original line number Diff line number Diff line
@@ -23,16 +23,20 @@
#include <gmock/gmock.h>
#include <gtest/gtest.h>

#define EXPECT_DISPLAY_MODE_REQUEST(expected, requestOpt)                               \
    ASSERT_TRUE(requestOpt);                                                            \
    EXPECT_FRAME_RATE_MODE(expected.mode.modePtr, expected.mode.fps, requestOpt->mode); \
    EXPECT_EQ(expected.emitEvent, requestOpt->emitEvent)

namespace android {
namespace {

using FakeDisplayDeviceInjector = TestableSurfaceFlinger::FakeDisplayDeviceInjector;
using DisplayModeRequest = display::DisplayModeRequest;

class InitiateModeChangeTest : public DisplayTransactionTest {
public:
    using Action = DisplayDevice::DesiredModeAction;
    using Event = scheduler::DisplayModeEvent;

    void SetUp() override {
        injectFakeBufferQueueFactory();
        injectFakeNativeWindowSurfaceFactory();
@@ -64,32 +68,30 @@ protected:
            ftl::as_non_null(createDisplayMode(kModeId90, 90_Hz));
    static inline const ftl::NonNull<DisplayModePtr> kMode120 =
            ftl::as_non_null(createDisplayMode(kModeId120, 120_Hz));

    static inline const DisplayModeRequest kDesiredMode30{{30_Hz, kMode60}, .emitEvent = false};
    static inline const DisplayModeRequest kDesiredMode60{{60_Hz, kMode60}, .emitEvent = true};
    static inline const DisplayModeRequest kDesiredMode90{{90_Hz, kMode90}, .emitEvent = false};
    static inline const DisplayModeRequest kDesiredMode120{{120_Hz, kMode120}, .emitEvent = true};
};

TEST_F(InitiateModeChangeTest, setDesiredModeToActiveMode) {
    EXPECT_EQ(Action::None,
              mDisplay->setDesiredMode({scheduler::FrameRateMode{60_Hz, kMode60}, Event::None}));
    EXPECT_EQ(Action::None, mDisplay->setDesiredMode(DisplayModeRequest(kDesiredMode60)));
    EXPECT_FALSE(mDisplay->getDesiredMode());
}

TEST_F(InitiateModeChangeTest, setDesiredMode) {
    EXPECT_EQ(Action::InitiateDisplayModeSwitch,
              mDisplay->setDesiredMode({scheduler::FrameRateMode{90_Hz, kMode90}, Event::None}));
    ASSERT_TRUE(mDisplay->getDesiredMode());
    EXPECT_FRAME_RATE_MODE(kMode90, 90_Hz, *mDisplay->getDesiredMode()->modeOpt);
    EXPECT_EQ(Event::None, mDisplay->getDesiredMode()->event);
              mDisplay->setDesiredMode(DisplayModeRequest(kDesiredMode90)));
    EXPECT_DISPLAY_MODE_REQUEST(kDesiredMode90, mDisplay->getDesiredMode());

    // Setting another mode should be cached but return None.
    EXPECT_EQ(Action::None,
              mDisplay->setDesiredMode({scheduler::FrameRateMode{120_Hz, kMode120}, Event::None}));
    ASSERT_TRUE(mDisplay->getDesiredMode());
    EXPECT_FRAME_RATE_MODE(kMode120, 120_Hz, *mDisplay->getDesiredMode()->modeOpt);
    EXPECT_EQ(Event::None, mDisplay->getDesiredMode()->event);
    EXPECT_EQ(Action::None, mDisplay->setDesiredMode(DisplayModeRequest(kDesiredMode120)));
    EXPECT_DISPLAY_MODE_REQUEST(kDesiredMode120, mDisplay->getDesiredMode());
}

TEST_F(InitiateModeChangeTest, clearDesiredMode) {
    EXPECT_EQ(Action::InitiateDisplayModeSwitch,
              mDisplay->setDesiredMode({scheduler::FrameRateMode{90_Hz, kMode90}, Event::None}));
              mDisplay->setDesiredMode(DisplayModeRequest(kDesiredMode90)));
    EXPECT_TRUE(mDisplay->getDesiredMode());

    mDisplay->clearDesiredMode();
@@ -98,10 +100,8 @@ TEST_F(InitiateModeChangeTest, clearDesiredMode) {

TEST_F(InitiateModeChangeTest, initiateModeChange) REQUIRES(kMainThreadContext) {
    EXPECT_EQ(Action::InitiateDisplayModeSwitch,
              mDisplay->setDesiredMode({scheduler::FrameRateMode{90_Hz, kMode90}, Event::None}));
    ASSERT_TRUE(mDisplay->getDesiredMode());
    EXPECT_FRAME_RATE_MODE(kMode90, 90_Hz, *mDisplay->getDesiredMode()->modeOpt);
    EXPECT_EQ(Event::None, mDisplay->getDesiredMode()->event);
              mDisplay->setDesiredMode(DisplayModeRequest(kDesiredMode90)));
    EXPECT_DISPLAY_MODE_REQUEST(kDesiredMode90, mDisplay->getDesiredMode());

    const hal::VsyncPeriodChangeConstraints constraints{
            .desiredTimeNanos = systemTime(),
@@ -109,8 +109,7 @@ TEST_F(InitiateModeChangeTest, initiateModeChange) REQUIRES(kMainThreadContext)
    };
    hal::VsyncPeriodChangeTimeline timeline;
    EXPECT_TRUE(mDisplay->initiateModeChange(*mDisplay->getDesiredMode(), constraints, timeline));
    EXPECT_FRAME_RATE_MODE(kMode90, 90_Hz, *mDisplay->getPendingMode().modeOpt);
    EXPECT_EQ(Event::None, mDisplay->getPendingMode().event);
    EXPECT_DISPLAY_MODE_REQUEST(kDesiredMode90, mDisplay->getPendingMode());

    mDisplay->clearDesiredMode();
    EXPECT_FALSE(mDisplay->getDesiredMode());
@@ -118,16 +117,14 @@ TEST_F(InitiateModeChangeTest, initiateModeChange) REQUIRES(kMainThreadContext)

TEST_F(InitiateModeChangeTest, initiateRenderRateSwitch) {
    EXPECT_EQ(Action::InitiateRenderRateSwitch,
              mDisplay->setDesiredMode({scheduler::FrameRateMode{30_Hz, kMode60}, Event::None}));
              mDisplay->setDesiredMode(DisplayModeRequest(kDesiredMode30)));
    EXPECT_FALSE(mDisplay->getDesiredMode());
}

TEST_F(InitiateModeChangeTest, initiateDisplayModeSwitch) FTL_FAKE_GUARD(kMainThreadContext) {
    EXPECT_EQ(Action::InitiateDisplayModeSwitch,
              mDisplay->setDesiredMode({scheduler::FrameRateMode{90_Hz, kMode90}, Event::None}));
    ASSERT_TRUE(mDisplay->getDesiredMode());
    EXPECT_FRAME_RATE_MODE(kMode90, 90_Hz, *mDisplay->getDesiredMode()->modeOpt);
    EXPECT_EQ(Event::None, mDisplay->getDesiredMode()->event);
              mDisplay->setDesiredMode(DisplayModeRequest(kDesiredMode90)));
    EXPECT_DISPLAY_MODE_REQUEST(kDesiredMode90, mDisplay->getDesiredMode());

    const hal::VsyncPeriodChangeConstraints constraints{
            .desiredTimeNanos = systemTime(),
@@ -135,21 +132,16 @@ TEST_F(InitiateModeChangeTest, initiateDisplayModeSwitch) FTL_FAKE_GUARD(kMainTh
    };
    hal::VsyncPeriodChangeTimeline timeline;
    EXPECT_TRUE(mDisplay->initiateModeChange(*mDisplay->getDesiredMode(), constraints, timeline));
    EXPECT_FRAME_RATE_MODE(kMode90, 90_Hz, *mDisplay->getPendingMode().modeOpt);
    EXPECT_EQ(Event::None, mDisplay->getPendingMode().event);
    EXPECT_DISPLAY_MODE_REQUEST(kDesiredMode90, mDisplay->getPendingMode());

    EXPECT_EQ(Action::None,
              mDisplay->setDesiredMode({scheduler::FrameRateMode{120_Hz, kMode120}, Event::None}));
    EXPECT_EQ(Action::None, mDisplay->setDesiredMode(DisplayModeRequest(kDesiredMode120)));
    ASSERT_TRUE(mDisplay->getDesiredMode());
    EXPECT_FRAME_RATE_MODE(kMode120, 120_Hz, *mDisplay->getDesiredMode()->modeOpt);
    EXPECT_EQ(Event::None, mDisplay->getDesiredMode()->event);
    EXPECT_DISPLAY_MODE_REQUEST(kDesiredMode120, mDisplay->getDesiredMode());

    EXPECT_FRAME_RATE_MODE(kMode90, 90_Hz, *mDisplay->getPendingMode().modeOpt);
    EXPECT_EQ(Event::None, mDisplay->getPendingMode().event);
    EXPECT_DISPLAY_MODE_REQUEST(kDesiredMode90, mDisplay->getPendingMode());

    EXPECT_TRUE(mDisplay->initiateModeChange(*mDisplay->getDesiredMode(), constraints, timeline));
    EXPECT_FRAME_RATE_MODE(kMode120, 120_Hz, *mDisplay->getPendingMode().modeOpt);
    EXPECT_EQ(Event::None, mDisplay->getPendingMode().event);
    EXPECT_DISPLAY_MODE_REQUEST(kDesiredMode120, mDisplay->getPendingMode());

    mDisplay->clearDesiredMode();
    EXPECT_FALSE(mDisplay->getDesiredMode());
Loading