Skip to content

Commit 00a764e

Browse files
author
Dennis Kiilerich
committed
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
1 parent d0503fa commit 00a764e

2 files changed

Lines changed: 98 additions & 13 deletions

File tree

services/surfaceflinger/SurfaceFlinger.cpp

Lines changed: 82 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4075,6 +4075,10 @@ void SurfaceFlinger::processDisplayAdded(const wp<IBinder>& displayToken,
40754075
incRefreshableDisplays();
40764076
}
40774077

4078+
if (FlagManager::getInstance().correct_virtual_display_power_state()) {
4079+
applyOptimizationPolicy(__func__);
4080+
}
4081+
40784082
mDisplays.try_emplace(displayToken, std::move(display));
40794083

40804084
// For an external display, loadDisplayModes already attempted to select the same mode
@@ -4131,6 +4135,10 @@ void SurfaceFlinger::processDisplayRemoved(const wp<IBinder>& displayToken) {
41314135
// not be accessible.
41324136
}));
41334137
}
4138+
4139+
if (FlagManager::getInstance().correct_virtual_display_power_state()) {
4140+
applyOptimizationPolicy(__func__);
4141+
}
41344142
}
41354143

41364144
void SurfaceFlinger::processDisplayChanged(const wp<IBinder>& displayToken,
@@ -5679,7 +5687,7 @@ void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& display, hal:
56795687
}
56805688

56815689
const auto displayId = display->getPhysicalId();
5682-
ALOGD("Setting power mode %d on display %s", mode, to_string(displayId).c_str());
5690+
ALOGD("Setting power mode %d on physical display %s", mode, to_string(displayId).c_str());
56835691

56845692
const auto currentMode = display->getPowerMode();
56855693
if (currentMode == mode) {
@@ -5722,11 +5730,11 @@ void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& display, hal:
57225730
}
57235731

57245732
if (displayId == mActiveDisplayId) {
5725-
// TODO: b/281692563 - Merge the syscalls. For now, keep uclamp in a separate syscall
5726-
// and set it before SCHED_FIFO due to b/190237315.
5727-
constexpr const char* kWhence = "setPowerMode(ON)";
5728-
setSchedAttr(true, kWhence);
5729-
setSchedFifo(true, kWhence);
5733+
if (FlagManager::getInstance().correct_virtual_display_power_state()) {
5734+
applyOptimizationPolicy("setPhysicalDisplayPowerMode(ON)");
5735+
} else {
5736+
disablePowerOptimizations("setPhysicalDisplayPowerMode(ON)");
5737+
}
57305738
}
57315739

57325740
getHwComposer().setPowerMode(displayId, mode);
@@ -5753,9 +5761,11 @@ void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& display, hal:
57535761
if (const auto display = getActivatableDisplay()) {
57545762
onActiveDisplayChangedLocked(activeDisplay.get(), *display);
57555763
} else {
5756-
constexpr const char* kWhence = "setPowerMode(OFF)";
5757-
setSchedFifo(false, kWhence);
5758-
setSchedAttr(false, kWhence);
5764+
if (FlagManager::getInstance().correct_virtual_display_power_state()) {
5765+
applyOptimizationPolicy("setPhysicalDisplayPowerMode(OFF)");
5766+
} else {
5767+
enablePowerOptimizations("setPhysicalDisplayPowerMode(OFF)");
5768+
}
57595769

57605770
if (currentModeNotDozeSuspend) {
57615771
if (!FlagManager::getInstance().multithreaded_present()) {
@@ -5816,7 +5826,67 @@ void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& display, hal:
58165826

58175827
mScheduler->setDisplayPowerMode(displayId, mode);
58185828

5819-
ALOGD("Finished setting power mode %d on display %s", mode, to_string(displayId).c_str());
5829+
ALOGD("Finished setting power mode %d on physical display %s", mode,
5830+
to_string(displayId).c_str());
5831+
}
5832+
5833+
void SurfaceFlinger::setVirtualDisplayPowerMode(const sp<DisplayDevice>& display,
5834+
hal::PowerMode mode) {
5835+
if (!display->isVirtual()) {
5836+
ALOGE("%s: Invalid operation on physical display", __func__);
5837+
return;
5838+
}
5839+
5840+
const auto displayId = display->getVirtualId();
5841+
ALOGD("Setting power mode %d on virtual display %s %s", mode, to_string(displayId).c_str(),
5842+
display->getDisplayName().c_str());
5843+
5844+
display->setPowerMode(static_cast<hal::PowerMode>(mode));
5845+
5846+
applyOptimizationPolicy(__func__);
5847+
5848+
ALOGD("Finished setting power mode %d on virtual display %s", mode,
5849+
to_string(displayId).c_str());
5850+
}
5851+
5852+
bool SurfaceFlinger::shouldOptimizeForPerformance() {
5853+
for (const auto& [_, display] : mDisplays) {
5854+
// Displays that are optimized for power are always powered on and should not influence
5855+
// whether there is an active display for the purpose of power optimization, etc. If these
5856+
// displays are being shown somewhere, a different (physical or virtual) display that is
5857+
// optimized for performance will be powered on in addition. Displays optimized for
5858+
// performance will change power mode, so if they are off then they are not active.
5859+
if (display->isPoweredOn() &&
5860+
display->getOptimizationPolicy() ==
5861+
gui::ISurfaceComposer::OptimizationPolicy::optimizeForPerformance) {
5862+
return true;
5863+
}
5864+
}
5865+
return false;
5866+
}
5867+
5868+
void SurfaceFlinger::enablePowerOptimizations(const char* whence) {
5869+
ALOGD("%s: Enabling power optimizations", whence);
5870+
5871+
setSchedAttr(false, whence);
5872+
setSchedFifo(false, whence);
5873+
}
5874+
5875+
void SurfaceFlinger::disablePowerOptimizations(const char* whence) {
5876+
ALOGD("%s: Disabling power optimizations", whence);
5877+
5878+
// TODO: b/281692563 - Merge the syscalls. For now, keep uclamp in a separate syscall
5879+
// and set it before SCHED_FIFO due to b/190237315.
5880+
setSchedAttr(true, whence);
5881+
setSchedFifo(true, whence);
5882+
}
5883+
5884+
void SurfaceFlinger::applyOptimizationPolicy(const char* whence) {
5885+
if (shouldOptimizeForPerformance()) {
5886+
disablePowerOptimizations(whence);
5887+
} else {
5888+
enablePowerOptimizations(whence);
5889+
}
58205890
}
58215891

58225892
void SurfaceFlinger::setPowerMode(const sp<IBinder>& displayToken, int mode) {
@@ -5838,9 +5908,8 @@ void SurfaceFlinger::setPowerMode(const sp<IBinder>& displayToken, int mode) {
58385908
ALOGE("Failed to set power mode %d for display token %p", mode, displayToken.get());
58395909
} else if (display->isVirtual()) {
58405910
if (FlagManager::getInstance().correct_virtual_display_power_state()) {
5841-
ALOGD("Setting power mode %d on virtual display %s", mode,
5842-
display->getDisplayName().c_str());
5843-
display->setPowerMode(static_cast<hal::PowerMode>(mode));
5911+
ftl::FakeGuard guard(mStateLock);
5912+
setVirtualDisplayPowerMode(display, static_cast<hal::PowerMode>(mode));
58445913
} else {
58455914
ALOGW("Attempt to set power mode %d for virtual display", mode);
58465915
}

services/surfaceflinger/SurfaceFlinger.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -735,6 +735,22 @@ class SurfaceFlinger : public BnSurfaceComposer,
735735
// Called on the main thread in response to setPowerMode()
736736
void setPowerModeInternal(const sp<DisplayDevice>& display, hal::PowerMode mode)
737737
REQUIRES(mStateLock, kMainThreadContext);
738+
void setVirtualDisplayPowerMode(const sp<DisplayDevice>& display, hal::PowerMode mode)
739+
REQUIRES(mStateLock, kMainThreadContext);
740+
741+
// Returns whether to optimize globally for performance instead of power.
742+
bool shouldOptimizeForPerformance() REQUIRES(mStateLock);
743+
744+
// Turns on power optimizations, for example when there are no displays to be optimized for
745+
// performance.
746+
static void enablePowerOptimizations(const char* whence);
747+
748+
// Turns off power optimizations.
749+
static void disablePowerOptimizations(const char* whence);
750+
751+
// Enables or disables power optimizations depending on whether there are displays that should
752+
// be optimized for performance.
753+
void applyOptimizationPolicy(const char* whence) REQUIRES(mStateLock);
738754

739755
// Returns the preferred mode for PhysicalDisplayId if the Scheduler has selected one for that
740756
// display. Falls back to the display's defaultModeId otherwise.

0 commit comments

Comments
 (0)