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

Commit a5643cb0 authored by Leon Scroggins's avatar Leon Scroggins Committed by Android (Google) Code Review
Browse files

Merge "Revert "SF: Flow DisplayModeRequest through mode set FSM"" into main

parents 68f75b87 63abc2ba
Loading
Loading
Loading
Loading
+8 −24
Original line number Original line Diff line number Diff line
@@ -222,6 +222,7 @@ bool DisplayDevice::initiateModeChange(display::DisplayModeRequest&& desiredMode
                                       const hal::VsyncPeriodChangeConstraints& constraints,
                                       const hal::VsyncPeriodChangeConstraints& constraints,
                                       hal::VsyncPeriodChangeTimeline& outTimeline) {
                                       hal::VsyncPeriodChangeTimeline& outTimeline) {
    mPendingModeOpt = std::move(desiredMode);
    mPendingModeOpt = std::move(desiredMode);
    mIsModeSetPending = true;


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


@@ -234,22 +235,9 @@ bool DisplayDevice::initiateModeChange(display::DisplayModeRequest&& desiredMode
    return true;
    return true;
}
}


auto DisplayDevice::finalizeModeChange() -> ModeChange {
void DisplayDevice::finalizeModeChange(DisplayModeId modeId, Fps vsyncRate, Fps renderFps) {
    if (!mPendingModeOpt) return NoModeChange{"No pending mode"};
    setActiveMode(modeId, vsyncRate, renderFps);

    mIsModeSetPending = false;
    auto pendingMode = *std::exchange(mPendingModeOpt, std::nullopt);
    auto& pendingModePtr = pendingMode.mode.modePtr;

    if (!mRefreshRateSelector->displayModes().contains(pendingModePtr->getId())) {
        return NoModeChange{"Unknown pending mode"};
    }

    if (getActiveMode().modePtr->getResolution() != pendingModePtr->getResolution()) {
        return ResolutionChange{std::move(pendingMode)};
    }

    setActiveMode(pendingModePtr->getId(), pendingModePtr->getVsyncRate(), pendingMode.mode.fps);
    return RefreshRateChange{std::move(pendingMode)};
}
}


nsecs_t DisplayDevice::getVsyncPeriodFromHWC() const {
nsecs_t DisplayDevice::getVsyncPeriodFromHWC() const {
@@ -587,15 +575,11 @@ auto DisplayDevice::getDesiredMode() const -> DisplayModeRequestOpt {
    return mDesiredModeOpt;
    return mDesiredModeOpt;
}
}


auto DisplayDevice::takeDesiredMode() -> DisplayModeRequestOpt {
void DisplayDevice::clearDesiredMode() {
    DisplayModeRequestOpt desiredModeOpt;
    {
    std::scoped_lock lock(mDesiredModeLock);
    std::scoped_lock lock(mDesiredModeLock);
        std::swap(mDesiredModeOpt, desiredModeOpt);
    mDesiredModeOpt.reset();
    mHasDesiredModeTrace = false;
    mHasDesiredModeTrace = false;
}
}
    return desiredModeOpt;
}


void DisplayDevice::adjustRefreshRate(Fps pacesetterDisplayRefreshRate) {
void DisplayDevice::adjustRefreshRate(Fps pacesetterDisplayRefreshRate) {
    using fps_approx_ops::operator<=;
    using fps_approx_ops::operator<=;
+7 −29
Original line number Original line Diff line number Diff line
@@ -19,7 +19,6 @@
#include <memory>
#include <memory>
#include <string>
#include <string>
#include <unordered_map>
#include <unordered_map>
#include <variant>


#include <android-base/thread_annotations.h>
#include <android-base/thread_annotations.h>
#include <android/native_window.h>
#include <android/native_window.h>
@@ -196,11 +195,12 @@ public:
    using DisplayModeRequestOpt = ftl::Optional<display::DisplayModeRequest>;
    using DisplayModeRequestOpt = ftl::Optional<display::DisplayModeRequest>;


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


    bool isModeSetPending() const REQUIRES(kMainThreadContext) {
    DisplayModeRequestOpt getPendingMode() const REQUIRES(kMainThreadContext) {
        return mPendingModeOpt.has_value();
        return mPendingModeOpt;
    }
    }
    bool isModeSetPending() const REQUIRES(kMainThreadContext) { return mIsModeSetPending; }


    scheduler::FrameRateMode getActiveMode() const REQUIRES(kMainThreadContext) {
    scheduler::FrameRateMode getActiveMode() const REQUIRES(kMainThreadContext) {
        return mRefreshRateSelector->getActiveMode();
        return mRefreshRateSelector->getActiveMode();
@@ -212,25 +212,8 @@ public:
                            hal::VsyncPeriodChangeTimeline& outTimeline)
                            hal::VsyncPeriodChangeTimeline& outTimeline)
            REQUIRES(kMainThreadContext);
            REQUIRES(kMainThreadContext);


    struct NoModeChange {
    void finalizeModeChange(DisplayModeId, Fps vsyncRate, Fps renderFps)
        const char* reason;
            REQUIRES(kMainThreadContext);
    };

    struct ResolutionChange {
        display::DisplayModeRequest activeMode;
    };

    struct RefreshRateChange {
        display::DisplayModeRequest activeMode;
    };

    using ModeChange = std::variant<NoModeChange, ResolutionChange, RefreshRateChange>;

    // Clears the pending DisplayModeRequest, and returns the ModeChange that occurred. If it was a
    // RefreshRateChange, the pending mode becomes the active mode. If it was a ResolutionChange,
    // the caller is responsible for resizing the framebuffer to match the active resolution by
    // recreating the DisplayDevice.
    ModeChange finalizeModeChange() REQUIRES(kMainThreadContext);


    scheduler::RefreshRateSelector& refreshRateSelector() const { return *mRefreshRateSelector; }
    scheduler::RefreshRateSelector& refreshRateSelector() const { return *mRefreshRateSelector; }


@@ -267,8 +250,6 @@ public:
    void dump(utils::Dumper&) const;
    void dump(utils::Dumper&) const;


private:
private:
    friend class TestableSurfaceFlinger;

    template <size_t N>
    template <size_t N>
    inline std::string concatId(const char (&str)[N]) const {
    inline std::string concatId(const char (&str)[N]) const {
        return std::string(ftl::Concat(str, ' ', getId().value).str());
        return std::string(ftl::Concat(str, ' ', getId().value).str());
@@ -319,15 +300,12 @@ private:
    // This parameter is only used for hdr/sdr ratio overlay
    // This parameter is only used for hdr/sdr ratio overlay
    float mHdrSdrRatio = 1.0f;
    float mHdrSdrRatio = 1.0f;


    // A DisplayModeRequest flows through three states: desired, pending, and active. Requests
    // within a frame are merged into a single desired request. Unless cleared, the request is
    // relayed to HWC on the next frame, and becomes pending. The mode becomes active once HWC
    // signals the present fence to confirm the mode set.
    mutable std::mutex mDesiredModeLock;
    mutable std::mutex mDesiredModeLock;
    DisplayModeRequestOpt mDesiredModeOpt GUARDED_BY(mDesiredModeLock);
    DisplayModeRequestOpt mDesiredModeOpt GUARDED_BY(mDesiredModeLock);
    TracedOrdinal<bool> mHasDesiredModeTrace GUARDED_BY(mDesiredModeLock);
    TracedOrdinal<bool> mHasDesiredModeTrace GUARDED_BY(mDesiredModeLock);


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


struct DisplayDeviceState {
struct DisplayDeviceState {
+69 −60
Original line number Original line Diff line number Diff line
@@ -59,7 +59,6 @@
#include <ftl/concat.h>
#include <ftl/concat.h>
#include <ftl/fake_guard.h>
#include <ftl/fake_guard.h>
#include <ftl/future.h>
#include <ftl/future.h>
#include <ftl/match.h>
#include <ftl/unit.h>
#include <ftl/unit.h>
#include <gui/AidlStatusUtil.h>
#include <gui/AidlStatusUtil.h>
#include <gui/BufferQueue.h>
#include <gui/BufferQueue.h>
@@ -1236,21 +1235,20 @@ status_t SurfaceFlinger::getDisplayStats(const sp<IBinder>& displayToken,
    return NO_ERROR;
    return NO_ERROR;
}
}


void SurfaceFlinger::setDesiredMode(display::DisplayModeRequest&& desiredMode, bool force) {
void SurfaceFlinger::setDesiredMode(display::DisplayModeRequest&& request, bool force) {
    const auto mode = desiredMode.mode;
    const auto displayId = request.mode.modePtr->getPhysicalDisplayId();
    const auto displayId = mode.modePtr->getPhysicalDisplayId();

    ATRACE_NAME(ftl::Concat(__func__, ' ', displayId.value).c_str());
    ATRACE_NAME(ftl::Concat(__func__, ' ', displayId.value).c_str());


    const auto display = getDisplayDeviceLocked(displayId);
    const auto display = getDisplayDeviceLocked(displayId);
    if (!display) {
    if (!display) {
        ALOGW("%s: Unknown display %s", __func__, to_string(displayId).c_str());
        ALOGW("%s: display is no longer valid", __func__);
        return;
        return;
    }
    }


    const bool emitEvent = desiredMode.emitEvent;
    const auto mode = request.mode;
    const bool emitEvent = request.emitEvent;


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


    ftl::match(
    const auto pendingModeOpt = display.getPendingMode();
            display.finalizeModeChange(),
    if (!pendingModeOpt) {
            [this, displayId](DisplayDevice::RefreshRateChange change) {
        // There is no pending mode change. This can happen if the active
                ftl::FakeGuard guard(mStateLock);
        // display changed and the mode change happened on a different display.

        return;
                if (change.activeMode.emitEvent) {
                    dispatchDisplayModeChangeEvent(displayId, change.activeMode.mode);
    }
    }


                applyActiveMode(std::move(change.activeMode));
    const auto& activeMode = pendingModeOpt->mode;
            },

            [&](DisplayDevice::ResolutionChange change) {
    if (display.getActiveMode().modePtr->getResolution() != activeMode.modePtr->getResolution()) {
        auto& state = mCurrentState.displays.editValueFor(display.getDisplayToken());
        auto& state = mCurrentState.displays.editValueFor(display.getDisplayToken());
                // Assign a new sequence ID to recreate the display and so its framebuffer.
        // We need to generate new sequenceId in order to recreate the display (and this
        // way the framebuffer).
        state.sequenceId = DisplayDeviceState{}.sequenceId;
        state.sequenceId = DisplayDeviceState{}.sequenceId;
                state.physical->activeMode = change.activeMode.mode.modePtr.get();
        state.physical->activeMode = activeMode.modePtr.get();

                ftl::FakeGuard guard1(kMainThreadContext);
                ftl::FakeGuard guard2(mStateLock);
        processDisplayChangesLocked();
        processDisplayChangesLocked();


                applyActiveMode(std::move(change.activeMode));
        // processDisplayChangesLocked will update all necessary components so we're done here.
            },
        return;
            [](DisplayDevice::NoModeChange noChange) {
    }
                // TODO(b/255635821): Remove this case, as it should no longer happen.

                ALOGE("A mode change was initiated but not finalized: %s", noChange.reason);
    display.finalizeModeChange(activeMode.modePtr->getId(), activeMode.modePtr->getVsyncRate(),
            });
                               activeMode.fps);

    if (displayId == mActiveDisplayId) {
        mRefreshRateStats->setRefreshRate(activeMode.fps);
        updatePhaseConfiguration(activeMode.fps);
    }

    if (pendingModeOpt->emitEvent) {
        dispatchDisplayModeChangeEvent(displayId, activeMode);
    }
}
}


void SurfaceFlinger::dropModeRequest(display::DisplayModeRequest&& request) {
void SurfaceFlinger::dropModeRequest(const sp<DisplayDevice>& display) {
    if (request.mode.modePtr->getPhysicalDisplayId() == mActiveDisplayId) {
    display->clearDesiredMode();
    if (display->getPhysicalId() == mActiveDisplayId) {
        // TODO(b/255635711): Check for pending mode changes on other displays.
        // TODO(b/255635711): Check for pending mode changes on other displays.
        mScheduler->setModeChangePending(false);
        mScheduler->setModeChangePending(false);
    }
    }
}
}


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


    dropModeRequest(std::move(activeMode));
    dropModeRequest(display);


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


    if (displayId == mActiveDisplayId) {
    if (displayId == mActiveDisplayId) {
        mRefreshRateStats->setRefreshRate(renderFps);
        updatePhaseConfiguration(renderFps);
        updatePhaseConfiguration(renderFps);
    }
    }
}
}
@@ -1408,50 +1412,50 @@ void SurfaceFlinger::initiateDisplayModeChanges() {
        const auto display = getDisplayDeviceLocked(id);
        const auto display = getDisplayDeviceLocked(id);
        if (!display) continue;
        if (!display) continue;


        auto desiredModeOpt = display->takeDesiredMode();
        auto desiredModeOpt = display->getDesiredMode();
        if (!desiredModeOpt) {
        if (!desiredModeOpt) {
            continue;
            continue;
        }
        }


        auto desiredMode = std::move(*desiredModeOpt);

        if (!shouldApplyRefreshRateSelectorPolicy(*display)) {
        if (!shouldApplyRefreshRateSelectorPolicy(*display)) {
            dropModeRequest(std::move(desiredMode));
            dropModeRequest(display);
            continue;
            continue;
        }
        }


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


        if (!displayModePtrOpt) {
        if (!displayModePtrOpt) {
            ALOGW("%s: Unknown mode %d for display %s", __func__, desiredModeId.value(),
            ALOGW("Desired display mode is no longer supported. Mode ID = %d",
                  to_string(id).c_str());
                  desiredModeId.value());
            dropModeRequest(std::move(desiredMode));
            dropModeRequest(display);
            continue;
            continue;
        }
        }


        if (display->getActiveMode() == desiredMode.mode) {
        ALOGV("%s changing active mode to %d(%s) for display %s", __func__, desiredModeId.value(),
            dropModeRequest(std::move(desiredMode));
              to_string(displayModePtrOpt->get()->getVsyncRate()).c_str(),
              to_string(display->getId()).c_str());

        if (display->getActiveMode() == desiredModeOpt->mode) {
            applyActiveMode(display);
            continue;
            continue;
        }
        }


        // The desired mode is different from the active mode. However, the allowed modes might have
        // Desired active mode was set, it is different than the mode currently in use, however
        // changed since setDesiredMode scheduled a mode transition.
        // allowed modes might have changed by the time we process the refresh.
        if (!display->refreshRateSelector().isModeAllowed(desiredMode.mode)) {
        // Make sure the desired mode is still allowed
            dropModeRequest(std::move(desiredMode));
        if (!display->refreshRateSelector().isModeAllowed(desiredModeOpt->mode)) {
            dropModeRequest(display);
            continue;
            continue;
        }
        }


        ALOGV("Mode setting display %s to %d (%s)", to_string(id).c_str(), desiredModeId.value(),
        // TODO(b/142753666) use constrains
              to_string(displayModePtrOpt.value().get()->getVsyncRate()).c_str());

        // TODO(b/142753666): Use constraints.
        hal::VsyncPeriodChangeConstraints constraints;
        hal::VsyncPeriodChangeConstraints constraints;
        constraints.desiredTimeNanos = systemTime();
        constraints.desiredTimeNanos = systemTime();
        constraints.seamlessRequired = false;
        constraints.seamlessRequired = false;
        hal::VsyncPeriodChangeTimeline outTimeline;
        hal::VsyncPeriodChangeTimeline outTimeline;


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


@@ -1471,6 +1475,11 @@ void SurfaceFlinger::initiateDisplayModeChanges() {
    if (displayToUpdateImmediately) {
    if (displayToUpdateImmediately) {
        const auto display = getDisplayDeviceLocked(*displayToUpdateImmediately);
        const auto display = getDisplayDeviceLocked(*displayToUpdateImmediately);
        finalizeDisplayModeChange(*display);
        finalizeDisplayModeChange(*display);

        const auto desiredModeOpt = display->getDesiredMode();
        if (desiredModeOpt && display->getActiveMode() == desiredModeOpt->mode) {
            applyActiveMode(display);
        }
    }
    }
}
}


@@ -7395,7 +7404,7 @@ void SurfaceFlinger::kernelTimerChanged(bool expired) {
    if (!updateOverlay) return;
    if (!updateOverlay) return;


    // Update the overlay on the main thread to avoid race conditions with
    // Update the overlay on the main thread to avoid race conditions with
    // RefreshRateSelector::getActiveMode.
    // RefreshRateSelector::getActiveMode
    static_cast<void>(mScheduler->schedule([=, this] {
    static_cast<void>(mScheduler->schedule([=, this] {
        const auto display = FTL_FAKE_GUARD(mStateLock, getDefaultDisplayDeviceLocked());
        const auto display = FTL_FAKE_GUARD(mStateLock, getDefaultDisplayDeviceLocked());
        if (!display) {
        if (!display) {
+3 −3
Original line number Original line Diff line number Diff line
@@ -727,9 +727,9 @@ private:
    void initiateDisplayModeChanges() REQUIRES(mStateLock, kMainThreadContext);
    void initiateDisplayModeChanges() REQUIRES(mStateLock, kMainThreadContext);
    void finalizeDisplayModeChange(DisplayDevice&) REQUIRES(mStateLock, kMainThreadContext);
    void finalizeDisplayModeChange(DisplayDevice&) REQUIRES(mStateLock, kMainThreadContext);


    // TODO(b/241285191): Move to Scheduler.
    // TODO(b/241285191): Replace DisplayDevice with DisplayModeRequest, and move to Scheduler.
    void dropModeRequest(display::DisplayModeRequest&&) REQUIRES(mStateLock);
    void dropModeRequest(const sp<DisplayDevice>&) REQUIRES(mStateLock);
    void applyActiveMode(display::DisplayModeRequest&&) REQUIRES(mStateLock);
    void applyActiveMode(const sp<DisplayDevice>&) REQUIRES(mStateLock);


    // Called on the main thread in response to setPowerMode()
    // Called on the main thread in response to setPowerMode()
    void setPowerModeInternal(const sp<DisplayDevice>& display, hal::PowerMode mode)
    void setPowerModeInternal(const sp<DisplayDevice>& display, hal::PowerMode mode)
+23 −54
Original line number Original line Diff line number Diff line
@@ -23,13 +23,10 @@
#include <gmock/gmock.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <gtest/gtest.h>


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

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


namespace android {
namespace android {
namespace {
namespace {
@@ -40,7 +37,6 @@ using DisplayModeRequest = display::DisplayModeRequest;
class InitiateModeChangeTest : public DisplayTransactionTest {
class InitiateModeChangeTest : public DisplayTransactionTest {
public:
public:
    using Action = DisplayDevice::DesiredModeAction;
    using Action = DisplayDevice::DesiredModeAction;

    void SetUp() override {
    void SetUp() override {
        injectFakeBufferQueueFactory();
        injectFakeBufferQueueFactory();
        injectFakeNativeWindowSurfaceFactory();
        injectFakeNativeWindowSurfaceFactory();
@@ -88,43 +84,36 @@ TEST_F(InitiateModeChangeTest, setDesiredModeToActiveMode) {
TEST_F(InitiateModeChangeTest, setDesiredMode) {
TEST_F(InitiateModeChangeTest, setDesiredMode) {
    EXPECT_EQ(Action::InitiateDisplayModeSwitch,
    EXPECT_EQ(Action::InitiateDisplayModeSwitch,
              mDisplay->setDesiredMode(DisplayModeRequest(kDesiredMode90)));
              mDisplay->setDesiredMode(DisplayModeRequest(kDesiredMode90)));
    EXPECT_DISPLAY_MODE_REQUEST_OPT(kDesiredMode90, mDisplay->getDesiredMode());
    EXPECT_DISPLAY_MODE_REQUEST(kDesiredMode90, mDisplay->getDesiredMode());


    EXPECT_EQ(Action::None, mDisplay->setDesiredMode(DisplayModeRequest(kDesiredMode120)));
    EXPECT_EQ(Action::None, mDisplay->setDesiredMode(DisplayModeRequest(kDesiredMode120)));
    EXPECT_DISPLAY_MODE_REQUEST_OPT(kDesiredMode120, mDisplay->getDesiredMode());
    EXPECT_DISPLAY_MODE_REQUEST(kDesiredMode120, mDisplay->getDesiredMode());
}
}


TEST_F(InitiateModeChangeTest, takeDesiredMode) {
TEST_F(InitiateModeChangeTest, clearDesiredMode) {
    EXPECT_EQ(Action::InitiateDisplayModeSwitch,
    EXPECT_EQ(Action::InitiateDisplayModeSwitch,
              mDisplay->setDesiredMode(DisplayModeRequest(kDesiredMode90)));
              mDisplay->setDesiredMode(DisplayModeRequest(kDesiredMode90)));
    EXPECT_EQ(kDesiredMode90, mDisplay->getDesiredMode());
    EXPECT_TRUE(mDisplay->getDesiredMode());


    EXPECT_EQ(kDesiredMode90, mDisplay->takeDesiredMode());
    mDisplay->clearDesiredMode();
    EXPECT_FALSE(mDisplay->getDesiredMode());
    EXPECT_FALSE(mDisplay->getDesiredMode());
}
}


TEST_F(InitiateModeChangeTest, initiateModeChange) FTL_FAKE_GUARD(kMainThreadContext) {
TEST_F(InitiateModeChangeTest, initiateModeChange) REQUIRES(kMainThreadContext) {
    EXPECT_EQ(Action::InitiateDisplayModeSwitch,
    EXPECT_EQ(Action::InitiateDisplayModeSwitch,
              mDisplay->setDesiredMode(DisplayModeRequest(kDesiredMode90)));
              mDisplay->setDesiredMode(DisplayModeRequest(kDesiredMode90)));
    EXPECT_DISPLAY_MODE_REQUEST_OPT(kDesiredMode90, mDisplay->getDesiredMode());
    EXPECT_DISPLAY_MODE_REQUEST(kDesiredMode90, mDisplay->getDesiredMode());


    const hal::VsyncPeriodChangeConstraints constraints{
    const hal::VsyncPeriodChangeConstraints constraints{
            .desiredTimeNanos = systemTime(),
            .desiredTimeNanos = systemTime(),
            .seamlessRequired = false,
            .seamlessRequired = false,
    };
    };
    hal::VsyncPeriodChangeTimeline timeline;
    hal::VsyncPeriodChangeTimeline timeline;
    EXPECT_TRUE(mDisplay->initiateModeChange(*mDisplay->getDesiredMode(), constraints, timeline));
    EXPECT_DISPLAY_MODE_REQUEST(kDesiredMode90, mDisplay->getPendingMode());


    auto desiredModeOpt = mDisplay->takeDesiredMode();
    mDisplay->clearDesiredMode();
    ASSERT_TRUE(desiredModeOpt);
    EXPECT_FALSE(mDisplay->getDesiredMode());
    EXPECT_FALSE(mDisplay->getDesiredMode());

    EXPECT_TRUE(mDisplay->initiateModeChange(std::move(*desiredModeOpt), constraints, timeline));

    auto modeChange = mDisplay->finalizeModeChange();

    auto* changePtr = std::get_if<DisplayDevice::RefreshRateChange>(&modeChange);
    ASSERT_TRUE(changePtr);
    EXPECT_DISPLAY_MODE_REQUEST(kDesiredMode90, changePtr->activeMode);
}
}


TEST_F(InitiateModeChangeTest, initiateRenderRateSwitch) {
TEST_F(InitiateModeChangeTest, initiateRenderRateSwitch) {
@@ -136,47 +125,27 @@ TEST_F(InitiateModeChangeTest, initiateRenderRateSwitch) {
TEST_F(InitiateModeChangeTest, initiateDisplayModeSwitch) FTL_FAKE_GUARD(kMainThreadContext) {
TEST_F(InitiateModeChangeTest, initiateDisplayModeSwitch) FTL_FAKE_GUARD(kMainThreadContext) {
    EXPECT_EQ(Action::InitiateDisplayModeSwitch,
    EXPECT_EQ(Action::InitiateDisplayModeSwitch,
              mDisplay->setDesiredMode(DisplayModeRequest(kDesiredMode90)));
              mDisplay->setDesiredMode(DisplayModeRequest(kDesiredMode90)));
    EXPECT_DISPLAY_MODE_REQUEST_OPT(kDesiredMode90, mDisplay->getDesiredMode());
    EXPECT_DISPLAY_MODE_REQUEST(kDesiredMode90, mDisplay->getDesiredMode());


    const hal::VsyncPeriodChangeConstraints constraints{
    const hal::VsyncPeriodChangeConstraints constraints{
            .desiredTimeNanos = systemTime(),
            .desiredTimeNanos = systemTime(),
            .seamlessRequired = false,
            .seamlessRequired = false,
    };
    };
    hal::VsyncPeriodChangeTimeline timeline;
    hal::VsyncPeriodChangeTimeline timeline;
    EXPECT_TRUE(mDisplay->initiateModeChange(*mDisplay->getDesiredMode(), constraints, timeline));
    EXPECT_DISPLAY_MODE_REQUEST(kDesiredMode90, mDisplay->getPendingMode());


    auto desiredModeOpt = mDisplay->takeDesiredMode();
    ASSERT_TRUE(desiredModeOpt);
    EXPECT_FALSE(mDisplay->getDesiredMode());

    EXPECT_TRUE(mDisplay->initiateModeChange(std::move(*desiredModeOpt), constraints, timeline));

    auto modeChange = mDisplay->finalizeModeChange();
    auto* changePtr = std::get_if<DisplayDevice::RefreshRateChange>(&modeChange);
    ASSERT_TRUE(changePtr);
    EXPECT_DISPLAY_MODE_REQUEST(kDesiredMode90, changePtr->activeMode);

    // The latest request should override the desired mode.
    EXPECT_EQ(Action::InitiateDisplayModeSwitch,
              mDisplay->setDesiredMode(DisplayModeRequest(kDesiredMode60)));
    EXPECT_EQ(Action::None, mDisplay->setDesiredMode(DisplayModeRequest(kDesiredMode120)));
    EXPECT_EQ(Action::None, mDisplay->setDesiredMode(DisplayModeRequest(kDesiredMode120)));
    ASSERT_TRUE(mDisplay->getDesiredMode());
    EXPECT_DISPLAY_MODE_REQUEST(kDesiredMode120, mDisplay->getDesiredMode());


    EXPECT_DISPLAY_MODE_REQUEST_OPT(kDesiredMode120, mDisplay->getDesiredMode());
    EXPECT_DISPLAY_MODE_REQUEST(kDesiredMode90, mDisplay->getPendingMode());


    // No pending mode change.
    EXPECT_TRUE(mDisplay->initiateModeChange(*mDisplay->getDesiredMode(), constraints, timeline));
    EXPECT_TRUE(
    EXPECT_DISPLAY_MODE_REQUEST(kDesiredMode120, mDisplay->getPendingMode());
            std::holds_alternative<DisplayDevice::NoModeChange>(mDisplay->finalizeModeChange()));


    desiredModeOpt = mDisplay->takeDesiredMode();
    mDisplay->clearDesiredMode();
    ASSERT_TRUE(desiredModeOpt);
    EXPECT_FALSE(mDisplay->getDesiredMode());
    EXPECT_FALSE(mDisplay->getDesiredMode());

    EXPECT_TRUE(mDisplay->initiateModeChange(std::move(*desiredModeOpt), constraints, timeline));

    modeChange = mDisplay->finalizeModeChange();

    changePtr = std::get_if<DisplayDevice::RefreshRateChange>(&modeChange);
    ASSERT_TRUE(changePtr);
    EXPECT_DISPLAY_MODE_REQUEST(kDesiredMode120, changePtr->activeMode);
}
}


} // namespace
} // namespace
Loading