Loading services/surfaceflinger/DisplayDevice.cpp +24 −31 Original line number Diff line number Diff line Loading @@ -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() Loading Loading @@ -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) { Loading Loading @@ -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; } Loading @@ -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) { Loading services/surfaceflinger/DisplayDevice.h +11 −27 Original line number Diff line number Diff line Loading @@ -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) { Loading @@ -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); Loading Loading @@ -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; }; Loading services/surfaceflinger/Scheduler/RefreshRateSelector.h +0 −7 Original line number Diff line number Diff line Loading @@ -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 Loading services/surfaceflinger/SurfaceFlinger.cpp +24 −23 Original line number Diff line number Diff line Loading @@ -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, Loading Loading @@ -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); Loading @@ -1315,7 +1315,7 @@ void SurfaceFlinger::finalizeDisplayModeChange(DisplayDevice& display) { updatePhaseConfiguration(activeMode.fps); } if (pendingMode.event != scheduler::DisplayModeEvent::None) { if (pendingModeOpt->emitEvent) { dispatchDisplayModeChangeEvent(displayId, activeMode); } } Loading @@ -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) { Loading @@ -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; } Loading @@ -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) { Loading @@ -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; } Loading @@ -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; } Loading @@ -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; } Loading @@ -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); } } Loading Loading @@ -7298,8 +7299,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; Loading services/surfaceflinger/tests/unittests/DisplayDevice_InitiateModeChange.cpp +28 −36 Original line number Diff line number Diff line Loading @@ -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(); Loading Loading @@ -65,32 +69,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(); Loading @@ -99,10 +101,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(), Loading @@ -110,8 +110,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()); Loading @@ -119,16 +118,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(), Loading @@ -136,21 +133,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 Loading
services/surfaceflinger/DisplayDevice.cpp +24 −31 Original line number Diff line number Diff line Loading @@ -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() Loading Loading @@ -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) { Loading Loading @@ -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; } Loading @@ -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) { Loading
services/surfaceflinger/DisplayDevice.h +11 −27 Original line number Diff line number Diff line Loading @@ -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) { Loading @@ -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); Loading Loading @@ -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; }; Loading
services/surfaceflinger/Scheduler/RefreshRateSelector.h +0 −7 Original line number Diff line number Diff line Loading @@ -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 Loading
services/surfaceflinger/SurfaceFlinger.cpp +24 −23 Original line number Diff line number Diff line Loading @@ -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, Loading Loading @@ -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); Loading @@ -1315,7 +1315,7 @@ void SurfaceFlinger::finalizeDisplayModeChange(DisplayDevice& display) { updatePhaseConfiguration(activeMode.fps); } if (pendingMode.event != scheduler::DisplayModeEvent::None) { if (pendingModeOpt->emitEvent) { dispatchDisplayModeChangeEvent(displayId, activeMode); } } Loading @@ -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) { Loading @@ -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; } Loading @@ -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) { Loading @@ -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; } Loading @@ -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; } Loading @@ -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; } Loading @@ -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); } } Loading Loading @@ -7298,8 +7299,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; Loading
services/surfaceflinger/tests/unittests/DisplayDevice_InitiateModeChange.cpp +28 −36 Original line number Diff line number Diff line Loading @@ -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(); Loading Loading @@ -65,32 +69,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(); Loading @@ -99,10 +101,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(), Loading @@ -110,8 +110,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()); Loading @@ -119,16 +118,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(), Loading @@ -136,21 +133,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