summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Dennis Kiilerich <dki@google.com> 2025-02-06 02:34:05 -0800
committer Dennis Kiilerich <dki@google.com> 2025-03-11 11:26:47 -0700
commit00a764ee8a3d2b59991f0e08557ac7a876862b81 (patch)
tree44e96e569d948cfceb37aa30ffe507da70ec3502
parentd0503fa4db892711445b44302d36968a88a469a8 (diff)
Use power mode of all independent displays to control power optimisations.
In the following cases, if there is any performance-optimised/independent active display (powered on) then power optimisations are disabled. If there is no performance-optimised/independent active display then power optimisations are enabled, even if there are power-optimised displays that are powered on. * Physical or virtual display power mode change * Physical or virtual display added or removed Power optimisations include: * Lowering thread priority Bug: 342681202 Bug: 241285876 Flag: android.companion.virtualdevice.flags.correct_virtual_display_power_state Test: manually tested with flag on/off using Android Auto Projected Change-Id: I96068c8779dbfe2b51b4d9acd522b6cb3995681f
-rw-r--r--services/surfaceflinger/SurfaceFlinger.cpp95
-rw-r--r--services/surfaceflinger/SurfaceFlinger.h16
2 files changed, 98 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);
}
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 39e237b1f9..8a0489fcb4 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 setPowerModeInternal(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.