Loading services/surfaceflinger/SurfaceFlinger.cpp +33 −14 Original line number Diff line number Diff line Loading @@ -5821,12 +5821,15 @@ void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& display, hal: } getHwComposer().setPowerMode(displayId, mode); if (displayId == mActiveDisplayId && mode != hal::PowerMode::DOZE_SUSPEND) { if (mode != hal::PowerMode::DOZE_SUSPEND && (displayId == mActiveDisplayId || FlagManager::getInstance().multithreaded_present())) { const bool enable = mScheduler->getVsyncSchedule(displayId)->getPendingHardwareVsyncState(); requestHardwareVsync(displayId, enable); if (displayId == mActiveDisplayId) { mScheduler->enableSyntheticVsync(false); } constexpr bool kAllowToEnable = true; mScheduler->resyncToHardwareVsync(displayId, kAllowToEnable, activeMode.get()); Loading @@ -5835,8 +5838,8 @@ void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& display, hal: mVisibleRegionsDirty = true; scheduleComposite(FrameHint::kActive); } else if (mode == hal::PowerMode::OFF) { const bool currentModeNotDozeSuspend = (*currentModeOpt != hal::PowerMode::DOZE_SUSPEND); // Turn off the display if (displayId == mActiveDisplayId) { if (const auto display = getActivatableDisplay()) { onActiveDisplayChangedLocked(activeDisplay.get(), *display); Loading @@ -5850,14 +5853,24 @@ void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& display, hal: strerror(errno)); } if (*currentModeOpt != hal::PowerMode::DOZE_SUSPEND) { if (currentModeNotDozeSuspend) { if (!FlagManager::getInstance().multithreaded_present()) { mScheduler->disableHardwareVsync(displayId, true); } mScheduler->enableSyntheticVsync(); } } } if (currentModeNotDozeSuspend && FlagManager::getInstance().multithreaded_present()) { constexpr bool kDisallow = true; mScheduler->disableHardwareVsync(displayId, kDisallow); } // Disable VSYNC before turning off the display. // We must disable VSYNC *before* turning off the display. The call to // disableHardwareVsync, above, schedules a task to turn it off after // this method returns. But by that point, the display is OFF, so the // call just updates the pending state, without actually disabling // VSYNC. requestHardwareVsync(displayId, false); getHwComposer().setPowerMode(displayId, mode); Loading @@ -5866,18 +5879,24 @@ void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& display, hal: } else if (mode == hal::PowerMode::DOZE || mode == hal::PowerMode::ON) { // Update display while dozing getHwComposer().setPowerMode(displayId, mode); if (displayId == mActiveDisplayId && *currentModeOpt == hal::PowerMode::DOZE_SUSPEND) { if (*currentModeOpt == hal::PowerMode::DOZE_SUSPEND && (displayId == mActiveDisplayId || FlagManager::getInstance().multithreaded_present())) { if (displayId == mActiveDisplayId) { ALOGI("Force repainting for DOZE_SUSPEND -> DOZE or ON."); mVisibleRegionsDirty = true; scheduleRepaint(); mScheduler->enableSyntheticVsync(false); mScheduler->resyncToHardwareVsync(displayId, true /* allowToEnable */, activeMode.get()); } constexpr bool kAllowToEnable = true; mScheduler->resyncToHardwareVsync(displayId, kAllowToEnable, activeMode.get()); } } else if (mode == hal::PowerMode::DOZE_SUSPEND) { // Leave display going to doze if (displayId == mActiveDisplayId || FlagManager::getInstance().multithreaded_present()) { constexpr bool kDisallow = true; mScheduler->disableHardwareVsync(displayId, kDisallow); } if (displayId == mActiveDisplayId) { mScheduler->disableHardwareVsync(displayId, true); mScheduler->enableSyntheticVsync(); } getHwComposer().setPowerMode(displayId, mode); Loading services/surfaceflinger/tests/unittests/SurfaceFlinger_FoldableTest.cpp +33 −0 Original line number Diff line number Diff line Loading @@ -188,5 +188,38 @@ TEST_F(FoldableTest, requestsHardwareVsyncForBothDisplays) { scheduler.onHardwareVsyncRequest(mOuterDisplay->getPhysicalId(), true); } TEST_F(FoldableTest, requestVsyncOnPowerOn) { EXPECT_CALL(mFlinger.scheduler()->mockRequestHardwareVsync, Call(kInnerDisplayId, true)) .Times(1); EXPECT_CALL(mFlinger.scheduler()->mockRequestHardwareVsync, Call(kOuterDisplayId, true)) .Times(1); mFlinger.setPowerModeInternal(mInnerDisplay, PowerMode::ON); mFlinger.setPowerModeInternal(mOuterDisplay, PowerMode::ON); } TEST_F(FoldableTest, disableVsyncOnPowerOffPacesetter) { // When the device boots, the inner display should be the pacesetter. ASSERT_EQ(mFlinger.scheduler()->pacesetterDisplayId(), kInnerDisplayId); testing::InSequence seq; EXPECT_CALL(mFlinger.scheduler()->mockRequestHardwareVsync, Call(kInnerDisplayId, true)) .Times(1); EXPECT_CALL(mFlinger.scheduler()->mockRequestHardwareVsync, Call(kOuterDisplayId, true)) .Times(1); // Turning off the pacesetter will result in disabling VSYNC. EXPECT_CALL(mFlinger.scheduler()->mockRequestHardwareVsync, Call(kInnerDisplayId, false)) .Times(1); mFlinger.setPowerModeInternal(mInnerDisplay, PowerMode::ON); mFlinger.setPowerModeInternal(mOuterDisplay, PowerMode::ON); mFlinger.setPowerModeInternal(mInnerDisplay, PowerMode::OFF); // Other display is now the pacesetter. ASSERT_EQ(mFlinger.scheduler()->pacesetterDisplayId(), kOuterDisplayId); } } // namespace } // namespace android services/surfaceflinger/tests/unittests/SurfaceFlinger_SetPowerModeInternalTest.cpp +9 −2 Original line number Diff line number Diff line Loading @@ -73,11 +73,13 @@ struct EventThreadBaseSupportedVariant { struct EventThreadNotSupportedVariant : public EventThreadBaseSupportedVariant { static void setupEnableVsyncCallExpectations(DisplayTransactionTest* test) { setupVsyncNoCallExpectations(test); EXPECT_CALL(test->mFlinger.scheduler()->mockRequestHardwareVsync, Call(_, true)).Times(1); EXPECT_CALL(*test->mEventThread, enableSyntheticVsync(_)).Times(0); } static void setupDisableVsyncCallExpectations(DisplayTransactionTest* test) { setupVsyncNoCallExpectations(test); EXPECT_CALL(test->mFlinger.scheduler()->mockRequestHardwareVsync, Call(_, false)).Times(1); EXPECT_CALL(*test->mEventThread, enableSyntheticVsync(_)).Times(0); } }; Loading Loading @@ -298,6 +300,11 @@ using PrimaryDisplayPowerCase = // A sample configuration for the external display. // In addition to not having event thread support, we emulate not having doze // support. // TODO (b/267483230): ExternalDisplay supports the features tracked in // DispSyncIsSupportedVariant, but is the follower, so the // expectations set by DispSyncIsSupportedVariant don't match (wrong schedule). // We need a way to retrieve the proper DisplayId from // setupResetModelCallExpectations (or pass it in). template <typename TransitionVariant> using ExternalDisplayPowerCase = DisplayPowerCase<ExternalDisplayVariant, DozeNotSupportedVariant<ExternalDisplayVariant>, Loading Loading
services/surfaceflinger/SurfaceFlinger.cpp +33 −14 Original line number Diff line number Diff line Loading @@ -5821,12 +5821,15 @@ void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& display, hal: } getHwComposer().setPowerMode(displayId, mode); if (displayId == mActiveDisplayId && mode != hal::PowerMode::DOZE_SUSPEND) { if (mode != hal::PowerMode::DOZE_SUSPEND && (displayId == mActiveDisplayId || FlagManager::getInstance().multithreaded_present())) { const bool enable = mScheduler->getVsyncSchedule(displayId)->getPendingHardwareVsyncState(); requestHardwareVsync(displayId, enable); if (displayId == mActiveDisplayId) { mScheduler->enableSyntheticVsync(false); } constexpr bool kAllowToEnable = true; mScheduler->resyncToHardwareVsync(displayId, kAllowToEnable, activeMode.get()); Loading @@ -5835,8 +5838,8 @@ void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& display, hal: mVisibleRegionsDirty = true; scheduleComposite(FrameHint::kActive); } else if (mode == hal::PowerMode::OFF) { const bool currentModeNotDozeSuspend = (*currentModeOpt != hal::PowerMode::DOZE_SUSPEND); // Turn off the display if (displayId == mActiveDisplayId) { if (const auto display = getActivatableDisplay()) { onActiveDisplayChangedLocked(activeDisplay.get(), *display); Loading @@ -5850,14 +5853,24 @@ void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& display, hal: strerror(errno)); } if (*currentModeOpt != hal::PowerMode::DOZE_SUSPEND) { if (currentModeNotDozeSuspend) { if (!FlagManager::getInstance().multithreaded_present()) { mScheduler->disableHardwareVsync(displayId, true); } mScheduler->enableSyntheticVsync(); } } } if (currentModeNotDozeSuspend && FlagManager::getInstance().multithreaded_present()) { constexpr bool kDisallow = true; mScheduler->disableHardwareVsync(displayId, kDisallow); } // Disable VSYNC before turning off the display. // We must disable VSYNC *before* turning off the display. The call to // disableHardwareVsync, above, schedules a task to turn it off after // this method returns. But by that point, the display is OFF, so the // call just updates the pending state, without actually disabling // VSYNC. requestHardwareVsync(displayId, false); getHwComposer().setPowerMode(displayId, mode); Loading @@ -5866,18 +5879,24 @@ void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& display, hal: } else if (mode == hal::PowerMode::DOZE || mode == hal::PowerMode::ON) { // Update display while dozing getHwComposer().setPowerMode(displayId, mode); if (displayId == mActiveDisplayId && *currentModeOpt == hal::PowerMode::DOZE_SUSPEND) { if (*currentModeOpt == hal::PowerMode::DOZE_SUSPEND && (displayId == mActiveDisplayId || FlagManager::getInstance().multithreaded_present())) { if (displayId == mActiveDisplayId) { ALOGI("Force repainting for DOZE_SUSPEND -> DOZE or ON."); mVisibleRegionsDirty = true; scheduleRepaint(); mScheduler->enableSyntheticVsync(false); mScheduler->resyncToHardwareVsync(displayId, true /* allowToEnable */, activeMode.get()); } constexpr bool kAllowToEnable = true; mScheduler->resyncToHardwareVsync(displayId, kAllowToEnable, activeMode.get()); } } else if (mode == hal::PowerMode::DOZE_SUSPEND) { // Leave display going to doze if (displayId == mActiveDisplayId || FlagManager::getInstance().multithreaded_present()) { constexpr bool kDisallow = true; mScheduler->disableHardwareVsync(displayId, kDisallow); } if (displayId == mActiveDisplayId) { mScheduler->disableHardwareVsync(displayId, true); mScheduler->enableSyntheticVsync(); } getHwComposer().setPowerMode(displayId, mode); Loading
services/surfaceflinger/tests/unittests/SurfaceFlinger_FoldableTest.cpp +33 −0 Original line number Diff line number Diff line Loading @@ -188,5 +188,38 @@ TEST_F(FoldableTest, requestsHardwareVsyncForBothDisplays) { scheduler.onHardwareVsyncRequest(mOuterDisplay->getPhysicalId(), true); } TEST_F(FoldableTest, requestVsyncOnPowerOn) { EXPECT_CALL(mFlinger.scheduler()->mockRequestHardwareVsync, Call(kInnerDisplayId, true)) .Times(1); EXPECT_CALL(mFlinger.scheduler()->mockRequestHardwareVsync, Call(kOuterDisplayId, true)) .Times(1); mFlinger.setPowerModeInternal(mInnerDisplay, PowerMode::ON); mFlinger.setPowerModeInternal(mOuterDisplay, PowerMode::ON); } TEST_F(FoldableTest, disableVsyncOnPowerOffPacesetter) { // When the device boots, the inner display should be the pacesetter. ASSERT_EQ(mFlinger.scheduler()->pacesetterDisplayId(), kInnerDisplayId); testing::InSequence seq; EXPECT_CALL(mFlinger.scheduler()->mockRequestHardwareVsync, Call(kInnerDisplayId, true)) .Times(1); EXPECT_CALL(mFlinger.scheduler()->mockRequestHardwareVsync, Call(kOuterDisplayId, true)) .Times(1); // Turning off the pacesetter will result in disabling VSYNC. EXPECT_CALL(mFlinger.scheduler()->mockRequestHardwareVsync, Call(kInnerDisplayId, false)) .Times(1); mFlinger.setPowerModeInternal(mInnerDisplay, PowerMode::ON); mFlinger.setPowerModeInternal(mOuterDisplay, PowerMode::ON); mFlinger.setPowerModeInternal(mInnerDisplay, PowerMode::OFF); // Other display is now the pacesetter. ASSERT_EQ(mFlinger.scheduler()->pacesetterDisplayId(), kOuterDisplayId); } } // namespace } // namespace android
services/surfaceflinger/tests/unittests/SurfaceFlinger_SetPowerModeInternalTest.cpp +9 −2 Original line number Diff line number Diff line Loading @@ -73,11 +73,13 @@ struct EventThreadBaseSupportedVariant { struct EventThreadNotSupportedVariant : public EventThreadBaseSupportedVariant { static void setupEnableVsyncCallExpectations(DisplayTransactionTest* test) { setupVsyncNoCallExpectations(test); EXPECT_CALL(test->mFlinger.scheduler()->mockRequestHardwareVsync, Call(_, true)).Times(1); EXPECT_CALL(*test->mEventThread, enableSyntheticVsync(_)).Times(0); } static void setupDisableVsyncCallExpectations(DisplayTransactionTest* test) { setupVsyncNoCallExpectations(test); EXPECT_CALL(test->mFlinger.scheduler()->mockRequestHardwareVsync, Call(_, false)).Times(1); EXPECT_CALL(*test->mEventThread, enableSyntheticVsync(_)).Times(0); } }; Loading Loading @@ -298,6 +300,11 @@ using PrimaryDisplayPowerCase = // A sample configuration for the external display. // In addition to not having event thread support, we emulate not having doze // support. // TODO (b/267483230): ExternalDisplay supports the features tracked in // DispSyncIsSupportedVariant, but is the follower, so the // expectations set by DispSyncIsSupportedVariant don't match (wrong schedule). // We need a way to retrieve the proper DisplayId from // setupResetModelCallExpectations (or pass it in). template <typename TransitionVariant> using ExternalDisplayPowerCase = DisplayPowerCase<ExternalDisplayVariant, DozeNotSupportedVariant<ExternalDisplayVariant>, Loading