diff options
-rw-r--r-- | services/surfaceflinger/DisplayDevice.cpp | 11 | ||||
-rw-r--r-- | services/surfaceflinger/DisplayDevice.h | 11 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 99 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.h | 15 | ||||
-rw-r--r-- | services/surfaceflinger/tests/unittests/SurfaceFlinger_SetPhysicalDisplayPowerModeTest.cpp | 30 |
5 files changed, 95 insertions, 71 deletions
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index bad5e2e3b5..de7d455fa4 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -50,17 +50,6 @@ namespace android { namespace hal = hardware::graphics::composer::hal; -namespace gui { -inline std::string_view to_string(ISurfaceComposer::OptimizationPolicy optimizationPolicy) { - switch (optimizationPolicy) { - case ISurfaceComposer::OptimizationPolicy::optimizeForPower: - return "optimizeForPower"; - case ISurfaceComposer::OptimizationPolicy::optimizeForPerformance: - return "optimizeForPerformance"; - } -} -} // namespace gui - DisplayDeviceCreationArgs::DisplayDeviceCreationArgs( const sp<SurfaceFlinger>& flinger, HWComposer& hwComposer, const wp<IBinder>& displayToken, std::shared_ptr<compositionengine::Display> compositionDisplay) diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index 7d7c8adb7b..1b14145147 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -67,6 +67,17 @@ namespace display { class DisplaySnapshot; } // namespace display +namespace gui { +inline const char* to_string(ISurfaceComposer::OptimizationPolicy optimizationPolicy) { + switch (optimizationPolicy) { + case ISurfaceComposer::OptimizationPolicy::optimizeForPower: + return "optimizeForPower"; + case ISurfaceComposer::OptimizationPolicy::optimizeForPerformance: + return "optimizeForPerformance"; + } +} +} // namespace gui + class DisplayDevice : public RefBase { public: constexpr static float sDefaultMinLumiance = 0.0; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 940374b256..aa933ee8a7 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -5719,7 +5719,13 @@ void SurfaceFlinger::setPhysicalDisplayPowerMode(const sp<DisplayDevice>& displa incRefreshableDisplays(); } + if (displayId == mActiveDisplayId && + FlagManager::getInstance().correct_virtual_display_power_state()) { + applyOptimizationPolicy(__func__); + } + const auto activeMode = display->refreshRateSelector().getActiveMode().modePtr; + using OptimizationPolicy = gui::ISurfaceComposer::OptimizationPolicy; if (currentMode == hal::PowerMode::OFF) { // Turn on the display @@ -5734,12 +5740,10 @@ void SurfaceFlinger::setPhysicalDisplayPowerMode(const sp<DisplayDevice>& displa onActiveDisplayChangedLocked(activeDisplay.get(), *display); } - if (displayId == mActiveDisplayId) { - if (FlagManager::getInstance().correct_virtual_display_power_state()) { - applyOptimizationPolicy("setPhysicalDisplayPowerMode(ON)"); - } else { - disablePowerOptimizations("setPhysicalDisplayPowerMode(ON)"); - } + if (displayId == mActiveDisplayId && + !FlagManager::getInstance().correct_virtual_display_power_state()) { + optimizeThreadScheduling("setPhysicalDisplayPowerMode(ON/DOZE)", + OptimizationPolicy::optimizeForPerformance); } getHwComposer().setPowerMode(displayId, mode); @@ -5748,7 +5752,8 @@ void SurfaceFlinger::setPhysicalDisplayPowerMode(const sp<DisplayDevice>& displa mScheduler->getVsyncSchedule(displayId)->getPendingHardwareVsyncState(); requestHardwareVsync(displayId, enable); - if (displayId == mActiveDisplayId) { + if (displayId == mActiveDisplayId && + !FlagManager::getInstance().correct_virtual_display_power_state()) { mScheduler->enableSyntheticVsync(false); } @@ -5765,13 +5770,13 @@ void SurfaceFlinger::setPhysicalDisplayPowerMode(const sp<DisplayDevice>& displa if (const auto display = getActivatableDisplay()) { onActiveDisplayChangedLocked(activeDisplay.get(), *display); } else { - if (FlagManager::getInstance().correct_virtual_display_power_state()) { - applyOptimizationPolicy("setPhysicalDisplayPowerMode(OFF)"); - } else { - enablePowerOptimizations("setPhysicalDisplayPowerMode(OFF)"); + if (!FlagManager::getInstance().correct_virtual_display_power_state()) { + optimizeThreadScheduling("setPhysicalDisplayPowerMode(OFF)", + OptimizationPolicy::optimizeForPower); } - if (currentModeNotDozeSuspend) { + if (currentModeNotDozeSuspend && + !FlagManager::getInstance().correct_virtual_display_power_state()) { mScheduler->enableSyntheticVsync(); } } @@ -5799,7 +5804,9 @@ void SurfaceFlinger::setPhysicalDisplayPowerMode(const sp<DisplayDevice>& displa ALOGI("Force repainting for DOZE_SUSPEND -> DOZE or ON."); mVisibleRegionsDirty = true; scheduleRepaint(); - mScheduler->enableSyntheticVsync(false); + if (!FlagManager::getInstance().correct_virtual_display_power_state()) { + mScheduler->enableSyntheticVsync(false); + } } constexpr bool kAllowToEnable = true; mScheduler->resyncToHardwareVsync(displayId, kAllowToEnable, activeMode.get()); @@ -5809,7 +5816,8 @@ void SurfaceFlinger::setPhysicalDisplayPowerMode(const sp<DisplayDevice>& displa constexpr bool kDisallow = true; mScheduler->disableHardwareVsync(displayId, kDisallow); - if (displayId == mActiveDisplayId) { + if (displayId == mActiveDisplayId && + !FlagManager::getInstance().correct_virtual_display_power_state()) { mScheduler->enableSyntheticVsync(); } getHwComposer().setPowerMode(displayId, mode); @@ -5848,43 +5856,44 @@ void SurfaceFlinger::setVirtualDisplayPowerMode(const sp<DisplayDevice>& display to_string(displayId).c_str()); } -bool SurfaceFlinger::shouldOptimizeForPerformance() { - for (const auto& [_, display] : mDisplays) { - // Displays that are optimized for power are always powered on and should not influence - // whether there is an active display for the purpose of power optimization, etc. If these - // displays are being shown somewhere, a different (physical or virtual) display that is - // optimized for performance will be powered on in addition. Displays optimized for - // performance will change power mode, so if they are off then they are not active. - if (display->isPoweredOn() && - display->getOptimizationPolicy() == - gui::ISurfaceComposer::OptimizationPolicy::optimizeForPerformance) { - return true; - } - } - return false; -} - -void SurfaceFlinger::enablePowerOptimizations(const char* whence) { - ALOGD("%s: Enabling power optimizations", whence); - - setSchedAttr(false, whence); - setSchedFifo(false, whence); -} - -void SurfaceFlinger::disablePowerOptimizations(const char* whence) { - ALOGD("%s: Disabling power optimizations", whence); +void SurfaceFlinger::optimizeThreadScheduling( + const char* whence, gui::ISurfaceComposer::OptimizationPolicy optimizationPolicy) { + ALOGD("%s: Optimizing thread scheduling: %s", whence, to_string(optimizationPolicy)); + const bool optimizeForPerformance = + optimizationPolicy == gui::ISurfaceComposer::OptimizationPolicy::optimizeForPerformance; // TODO: b/281692563 - Merge the syscalls. For now, keep uclamp in a separate syscall // and set it before SCHED_FIFO due to b/190237315. - setSchedAttr(true, whence); - setSchedFifo(true, whence); + setSchedAttr(optimizeForPerformance, whence); + setSchedFifo(optimizeForPerformance, whence); } void SurfaceFlinger::applyOptimizationPolicy(const char* whence) { - if (shouldOptimizeForPerformance()) { - disablePowerOptimizations(whence); - } else { - enablePowerOptimizations(whence); + using OptimizationPolicy = gui::ISurfaceComposer::OptimizationPolicy; + + const bool optimizeForPerformance = + std::any_of(mDisplays.begin(), mDisplays.end(), [](const auto& pair) { + const auto& display = pair.second; + return display->isPoweredOn() && + display->getOptimizationPolicy() == + OptimizationPolicy::optimizeForPerformance; + }); + + optimizeThreadScheduling(whence, + optimizeForPerformance ? OptimizationPolicy::optimizeForPerformance + : OptimizationPolicy::optimizeForPower); + + if (mScheduler) { + const bool disableSyntheticVsync = + std::any_of(mDisplays.begin(), mDisplays.end(), [](const auto& pair) { + const auto& display = pair.second; + const hal::PowerMode powerMode = display->getPowerMode(); + return powerMode != hal::PowerMode::OFF && + powerMode != hal::PowerMode::DOZE_SUSPEND && + display->getOptimizationPolicy() == + OptimizationPolicy::optimizeForPerformance; + }); + mScheduler->enableSyntheticVsync(!disableSyntheticVsync); } } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 9cf0c6aaa0..f61214cc65 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -733,19 +733,14 @@ private: void setVirtualDisplayPowerMode(const sp<DisplayDevice>& display, hal::PowerMode mode) REQUIRES(mStateLock, kMainThreadContext); - // Returns whether to optimize globally for performance instead of power. - bool shouldOptimizeForPerformance() REQUIRES(mStateLock); - - // Turns on power optimizations, for example when there are no displays to be optimized for - // performance. - static void enablePowerOptimizations(const char* whence); - - // Turns off power optimizations. - static void disablePowerOptimizations(const char* whence); + // Adjusts thread scheduling according to the optimization policy + static void optimizeThreadScheduling( + const char* whence, gui::ISurfaceComposer::OptimizationPolicy optimizationPolicy); // Enables or disables power optimizations depending on whether there are displays that should // be optimized for performance. - void applyOptimizationPolicy(const char* whence) REQUIRES(mStateLock); + void applyOptimizationPolicy(const char* whence) REQUIRES(kMainThreadContext) + REQUIRES(mStateLock); // Returns the preferred mode for PhysicalDisplayId if the Scheduler has selected one for that // display. Falls back to the display's defaultModeId otherwise. diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetPhysicalDisplayPowerModeTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetPhysicalDisplayPowerModeTest.cpp index d5c22a9601..2332bf62da 100644 --- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetPhysicalDisplayPowerModeTest.cpp +++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetPhysicalDisplayPowerModeTest.cpp @@ -17,6 +17,7 @@ #undef LOG_TAG #define LOG_TAG "LibSurfaceFlingerUnittests" +#include <android_companion_virtualdevice_flags.h> #include <com_android_graphics_surfaceflinger_flags.h> #include <common/test/FlagUtils.h> #include "DisplayTransactionTestHelpers.h" @@ -78,11 +79,19 @@ struct EventThreadBaseSupportedVariant { struct EventThreadNotSupportedVariant : public EventThreadBaseSupportedVariant { static void setupEnableVsyncCallExpectations(DisplayTransactionTest* test) { EXPECT_CALL(test->mFlinger.scheduler()->mockRequestHardwareVsync, Call(_, true)).Times(1); + setupDisableSyntheticVsyncCallExpectations(test); + } + + static void setupDisableSyntheticVsyncCallExpectations(DisplayTransactionTest* test) { EXPECT_CALL(*test->mEventThread, enableSyntheticVsync(_)).Times(0); } static void setupDisableVsyncCallExpectations(DisplayTransactionTest* test) { EXPECT_CALL(test->mFlinger.scheduler()->mockRequestHardwareVsync, Call(_, false)).Times(1); + setupEnableSyntheticVsyncCallExpectations(test); + } + + static void setupEnableSyntheticVsyncCallExpectations(DisplayTransactionTest* test) { EXPECT_CALL(*test->mEventThread, enableSyntheticVsync(_)).Times(0); } }; @@ -91,12 +100,20 @@ struct EventThreadIsSupportedVariant : public EventThreadBaseSupportedVariant { static void setupEnableVsyncCallExpectations(DisplayTransactionTest* test) { // Expect to enable hardware VSYNC and disable synthetic VSYNC. EXPECT_CALL(test->mFlinger.scheduler()->mockRequestHardwareVsync, Call(_, true)).Times(1); + setupDisableSyntheticVsyncCallExpectations(test); + } + + static void setupDisableSyntheticVsyncCallExpectations(DisplayTransactionTest* test) { EXPECT_CALL(*test->mEventThread, enableSyntheticVsync(false)).Times(1); } static void setupDisableVsyncCallExpectations(DisplayTransactionTest* test) { // Expect to disable hardware VSYNC and enable synthetic VSYNC. EXPECT_CALL(test->mFlinger.scheduler()->mockRequestHardwareVsync, Call(_, false)).Times(1); + setupEnableSyntheticVsyncCallExpectations(test); + } + + static void setupEnableSyntheticVsyncCallExpectations(DisplayTransactionTest* test) { EXPECT_CALL(*test->mEventThread, enableSyntheticVsync(true)).Times(1); } }; @@ -151,7 +168,7 @@ struct TransitionOffToDozeSuspendVariant template <typename Case> static void setupCallExpectations(DisplayTransactionTest* test) { Case::setupComposerCallExpectations(test, Case::Doze::ACTUAL_POWER_MODE_FOR_DOZE_SUSPEND); - Case::EventThread::setupVsyncNoCallExpectations(test); + Case::EventThread::setupEnableSyntheticVsyncCallExpectations(test); Case::setupRepaintEverythingCallExpectations(test); } @@ -176,7 +193,7 @@ struct TransitionDozeSuspendToOffVariant : public TransitionVariantCommon<PowerMode::DOZE_SUSPEND, PowerMode::OFF> { template <typename Case> static void setupCallExpectations(DisplayTransactionTest* test) { - Case::EventThread::setupVsyncNoCallExpectations(test); + Case::EventThread::setupEnableSyntheticVsyncCallExpectations(test); Case::setupComposerCallExpectations(test, IComposerClient::PowerMode::OFF); } @@ -188,7 +205,7 @@ struct TransitionDozeSuspendToOffVariant struct TransitionOnToDozeVariant : public TransitionVariantCommon<PowerMode::ON, PowerMode::DOZE> { template <typename Case> static void setupCallExpectations(DisplayTransactionTest* test) { - Case::EventThread::setupVsyncNoCallExpectations(test); + Case::EventThread::setupDisableSyntheticVsyncCallExpectations(test); Case::setupComposerCallExpectations(test, Case::Doze::ACTUAL_POWER_MODE_FOR_DOZE); } }; @@ -206,7 +223,7 @@ struct TransitionDozeSuspendToDozeVariant struct TransitionDozeToOnVariant : public TransitionVariantCommon<PowerMode::DOZE, PowerMode::ON> { template <typename Case> static void setupCallExpectations(DisplayTransactionTest* test) { - Case::EventThread::setupVsyncNoCallExpectations(test); + Case::EventThread::setupDisableSyntheticVsyncCallExpectations(test); Case::setupComposerCallExpectations(test, IComposerClient::PowerMode::ON); } }; @@ -234,7 +251,7 @@ struct TransitionOnToUnknownVariant : public TransitionVariantCommon<PowerMode::ON, static_cast<PowerMode>(POWER_MODE_LEET)> { template <typename Case> static void setupCallExpectations(DisplayTransactionTest* test) { - Case::EventThread::setupVsyncNoCallExpectations(test); + Case::EventThread::setupDisableSyntheticVsyncCallExpectations(test); Case::setupNoComposerPowerModeCallExpectations(test); } }; @@ -335,6 +352,9 @@ void SetPhysicalDisplayPowerModeTest::transitionDisplayCommon() { // -------------------------------------------------------------------- // Preconditions + SET_FLAG_FOR_TEST(android::companion::virtualdevice::flags::correct_virtual_display_power_state, + true); + Case::Doze::setupComposerCallExpectations(this); auto display = Case::injectDisplayWithInitialPowerMode(this, Case::Transition::INITIAL_POWER_MODE); |