diff options
Diffstat (limited to 'services/surfaceflinger/SurfaceFlinger.cpp')
| -rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 95 |
1 files changed, 82 insertions, 13 deletions
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 099aa7a865..217581c1a9 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, @@ -5679,7 +5687,7 @@ void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& display, hal: } 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) { @@ -5722,11 +5730,11 @@ void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& display, hal: } 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); @@ -5753,9 +5761,11 @@ void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& display, hal: 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()) { @@ -5816,7 +5826,67 @@ void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& display, hal: 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) { @@ -5838,9 +5908,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); } |