diff options
author | 2025-03-11 20:17:53 -0700 | |
---|---|---|
committer | 2025-03-11 20:17:53 -0700 | |
commit | 2c710c3d39907e5909ed1b007911e5fecc3badf7 (patch) | |
tree | b1051b41ad48e45d25e917d933f07719226be740 | |
parent | 89366b4eb895f5752d53e58e2a87bc5be32b4a1d (diff) | |
parent | 00a764ee8a3d2b59991f0e08557ac7a876862b81 (diff) |
Merge "Use power mode of all independent displays to control power optimisations." into main
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 95 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.h | 16 |
2 files changed, 98 insertions, 13 deletions
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 9cd2314cf5..0029bfc63e 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -4075,6 +4075,10 @@ void SurfaceFlinger::processDisplayAdded(const wp<IBinder>& displayToken, incRefreshableDisplays(); } + if (FlagManager::getInstance().correct_virtual_display_power_state()) { + applyOptimizationPolicy(__func__); + } + mDisplays.try_emplace(displayToken, std::move(display)); // For an external display, loadDisplayModes already attempted to select the same mode @@ -4131,6 +4135,10 @@ void SurfaceFlinger::processDisplayRemoved(const wp<IBinder>& displayToken) { // not be accessible. })); } + + if (FlagManager::getInstance().correct_virtual_display_power_state()) { + applyOptimizationPolicy(__func__); + } } void SurfaceFlinger::processDisplayChanged(const wp<IBinder>& displayToken, @@ -5680,7 +5688,7 @@ void SurfaceFlinger::setPhysicalDisplayPowerMode(const sp<DisplayDevice>& displa } const auto displayId = display->getPhysicalId(); - ALOGD("Setting power mode %d on display %s", mode, to_string(displayId).c_str()); + ALOGD("Setting power mode %d on physical display %s", mode, to_string(displayId).c_str()); const auto currentMode = display->getPowerMode(); if (currentMode == mode) { @@ -5723,11 +5731,11 @@ void SurfaceFlinger::setPhysicalDisplayPowerMode(const sp<DisplayDevice>& displa } if (displayId == mActiveDisplayId) { - // TODO: b/281692563 - Merge the syscalls. For now, keep uclamp in a separate syscall - // and set it before SCHED_FIFO due to b/190237315. - constexpr const char* kWhence = "setPowerMode(ON)"; - setSchedAttr(true, kWhence); - setSchedFifo(true, kWhence); + if (FlagManager::getInstance().correct_virtual_display_power_state()) { + applyOptimizationPolicy("setPhysicalDisplayPowerMode(ON)"); + } else { + disablePowerOptimizations("setPhysicalDisplayPowerMode(ON)"); + } } getHwComposer().setPowerMode(displayId, mode); @@ -5754,9 +5762,11 @@ void SurfaceFlinger::setPhysicalDisplayPowerMode(const sp<DisplayDevice>& displa if (const auto display = getActivatableDisplay()) { onActiveDisplayChangedLocked(activeDisplay.get(), *display); } else { - constexpr const char* kWhence = "setPowerMode(OFF)"; - setSchedFifo(false, kWhence); - setSchedAttr(false, kWhence); + if (FlagManager::getInstance().correct_virtual_display_power_state()) { + applyOptimizationPolicy("setPhysicalDisplayPowerMode(OFF)"); + } else { + enablePowerOptimizations("setPhysicalDisplayPowerMode(OFF)"); + } if (currentModeNotDozeSuspend) { if (!FlagManager::getInstance().multithreaded_present()) { @@ -5817,7 +5827,67 @@ void SurfaceFlinger::setPhysicalDisplayPowerMode(const sp<DisplayDevice>& displa mScheduler->setDisplayPowerMode(displayId, mode); - ALOGD("Finished setting power mode %d on display %s", mode, to_string(displayId).c_str()); + ALOGD("Finished setting power mode %d on physical display %s", mode, + to_string(displayId).c_str()); +} + +void SurfaceFlinger::setVirtualDisplayPowerMode(const sp<DisplayDevice>& display, + hal::PowerMode mode) { + if (!display->isVirtual()) { + ALOGE("%s: Invalid operation on physical display", __func__); + return; + } + + const auto displayId = display->getVirtualId(); + ALOGD("Setting power mode %d on virtual display %s %s", mode, to_string(displayId).c_str(), + display->getDisplayName().c_str()); + + display->setPowerMode(static_cast<hal::PowerMode>(mode)); + + applyOptimizationPolicy(__func__); + + ALOGD("Finished setting power mode %d on virtual display %s", mode, + 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); + + // 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); +} + +void SurfaceFlinger::applyOptimizationPolicy(const char* whence) { + if (shouldOptimizeForPerformance()) { + disablePowerOptimizations(whence); + } else { + enablePowerOptimizations(whence); + } } void SurfaceFlinger::setPowerMode(const sp<IBinder>& displayToken, int mode) { @@ -5839,9 +5909,8 @@ void SurfaceFlinger::setPowerMode(const sp<IBinder>& displayToken, int mode) { ALOGE("Failed to set power mode %d for display token %p", mode, displayToken.get()); } else if (display->isVirtual()) { if (FlagManager::getInstance().correct_virtual_display_power_state()) { - ALOGD("Setting power mode %d on virtual display %s", mode, - display->getDisplayName().c_str()); - display->setPowerMode(static_cast<hal::PowerMode>(mode)); + ftl::FakeGuard guard(mStateLock); + setVirtualDisplayPowerMode(display, static_cast<hal::PowerMode>(mode)); } else { ALOGW("Attempt to set power mode %d for virtual display", mode); } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index fc596d7cf1..37f362fd21 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -735,6 +735,22 @@ private: // Called on the main thread in response to setPowerMode() void setPhysicalDisplayPowerMode(const sp<DisplayDevice>& display, hal::PowerMode mode) REQUIRES(mStateLock, kMainThreadContext); + 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); + + // Enables or disables power optimizations depending on whether there are displays that should + // be optimized for performance. + void applyOptimizationPolicy(const char* whence) 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. |