Skip to content

Commit bac7071

Browse files
author
Dennis Kiilerich
committed
Turn off synthetic VSYNC when adjusting thread scheduling for performance
* This CL explicitly sets synthetic VSYNC state based on the new power state. Before, the synthetic VSYNC state was assumed based on the previous power state and in some cases was not set explicitly. * The previous behaviour of enabling synthetic VSYNC if the only display is DOZE_SUSPEND is preserved. * This also fixes a hypothetical gap where it would not optimise for performance if there were a display that needed it, while the primary display was DOZE_SUSPEND. 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: I181aefad586ad7b1732c837b67a01d61939d1d3e
1 parent 913c8f3 commit bac7071

5 files changed

Lines changed: 95 additions & 71 deletions

File tree

services/surfaceflinger/DisplayDevice.cpp

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -50,17 +50,6 @@ namespace android {
5050

5151
namespace hal = hardware::graphics::composer::hal;
5252

53-
namespace gui {
54-
inline std::string_view to_string(ISurfaceComposer::OptimizationPolicy optimizationPolicy) {
55-
switch (optimizationPolicy) {
56-
case ISurfaceComposer::OptimizationPolicy::optimizeForPower:
57-
return "optimizeForPower";
58-
case ISurfaceComposer::OptimizationPolicy::optimizeForPerformance:
59-
return "optimizeForPerformance";
60-
}
61-
}
62-
} // namespace gui
63-
6453
DisplayDeviceCreationArgs::DisplayDeviceCreationArgs(
6554
const sp<SurfaceFlinger>& flinger, HWComposer& hwComposer, const wp<IBinder>& displayToken,
6655
std::shared_ptr<compositionengine::Display> compositionDisplay)

services/surfaceflinger/DisplayDevice.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,17 @@ namespace display {
6767
class DisplaySnapshot;
6868
} // namespace display
6969

70+
namespace gui {
71+
inline const char* to_string(ISurfaceComposer::OptimizationPolicy optimizationPolicy) {
72+
switch (optimizationPolicy) {
73+
case ISurfaceComposer::OptimizationPolicy::optimizeForPower:
74+
return "optimizeForPower";
75+
case ISurfaceComposer::OptimizationPolicy::optimizeForPerformance:
76+
return "optimizeForPerformance";
77+
}
78+
}
79+
} // namespace gui
80+
7081
class DisplayDevice : public RefBase {
7182
public:
7283
constexpr static float sDefaultMinLumiance = 0.0;

services/surfaceflinger/SurfaceFlinger.cpp

Lines changed: 54 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -5719,7 +5719,13 @@ void SurfaceFlinger::setPhysicalDisplayPowerMode(const sp<DisplayDevice>& displa
57195719
incRefreshableDisplays();
57205720
}
57215721

5722+
if (displayId == mActiveDisplayId &&
5723+
FlagManager::getInstance().correct_virtual_display_power_state()) {
5724+
applyOptimizationPolicy(__func__);
5725+
}
5726+
57225727
const auto activeMode = display->refreshRateSelector().getActiveMode().modePtr;
5728+
using OptimizationPolicy = gui::ISurfaceComposer::OptimizationPolicy;
57235729
if (currentMode == hal::PowerMode::OFF) {
57245730
// Turn on the display
57255731

@@ -5734,12 +5740,10 @@ void SurfaceFlinger::setPhysicalDisplayPowerMode(const sp<DisplayDevice>& displa
57345740
onActiveDisplayChangedLocked(activeDisplay.get(), *display);
57355741
}
57365742

5737-
if (displayId == mActiveDisplayId) {
5738-
if (FlagManager::getInstance().correct_virtual_display_power_state()) {
5739-
applyOptimizationPolicy("setPhysicalDisplayPowerMode(ON)");
5740-
} else {
5741-
disablePowerOptimizations("setPhysicalDisplayPowerMode(ON)");
5742-
}
5743+
if (displayId == mActiveDisplayId &&
5744+
!FlagManager::getInstance().correct_virtual_display_power_state()) {
5745+
optimizeThreadScheduling("setPhysicalDisplayPowerMode(ON/DOZE)",
5746+
OptimizationPolicy::optimizeForPerformance);
57435747
}
57445748

57455749
getHwComposer().setPowerMode(displayId, mode);
@@ -5748,7 +5752,8 @@ void SurfaceFlinger::setPhysicalDisplayPowerMode(const sp<DisplayDevice>& displa
57485752
mScheduler->getVsyncSchedule(displayId)->getPendingHardwareVsyncState();
57495753
requestHardwareVsync(displayId, enable);
57505754

5751-
if (displayId == mActiveDisplayId) {
5755+
if (displayId == mActiveDisplayId &&
5756+
!FlagManager::getInstance().correct_virtual_display_power_state()) {
57525757
mScheduler->enableSyntheticVsync(false);
57535758
}
57545759

@@ -5765,13 +5770,13 @@ void SurfaceFlinger::setPhysicalDisplayPowerMode(const sp<DisplayDevice>& displa
57655770
if (const auto display = getActivatableDisplay()) {
57665771
onActiveDisplayChangedLocked(activeDisplay.get(), *display);
57675772
} else {
5768-
if (FlagManager::getInstance().correct_virtual_display_power_state()) {
5769-
applyOptimizationPolicy("setPhysicalDisplayPowerMode(OFF)");
5770-
} else {
5771-
enablePowerOptimizations("setPhysicalDisplayPowerMode(OFF)");
5773+
if (!FlagManager::getInstance().correct_virtual_display_power_state()) {
5774+
optimizeThreadScheduling("setPhysicalDisplayPowerMode(OFF)",
5775+
OptimizationPolicy::optimizeForPower);
57725776
}
57735777

5774-
if (currentModeNotDozeSuspend) {
5778+
if (currentModeNotDozeSuspend &&
5779+
!FlagManager::getInstance().correct_virtual_display_power_state()) {
57755780
mScheduler->enableSyntheticVsync();
57765781
}
57775782
}
@@ -5799,7 +5804,9 @@ void SurfaceFlinger::setPhysicalDisplayPowerMode(const sp<DisplayDevice>& displa
57995804
ALOGI("Force repainting for DOZE_SUSPEND -> DOZE or ON.");
58005805
mVisibleRegionsDirty = true;
58015806
scheduleRepaint();
5802-
mScheduler->enableSyntheticVsync(false);
5807+
if (!FlagManager::getInstance().correct_virtual_display_power_state()) {
5808+
mScheduler->enableSyntheticVsync(false);
5809+
}
58035810
}
58045811
constexpr bool kAllowToEnable = true;
58055812
mScheduler->resyncToHardwareVsync(displayId, kAllowToEnable, activeMode.get());
@@ -5809,7 +5816,8 @@ void SurfaceFlinger::setPhysicalDisplayPowerMode(const sp<DisplayDevice>& displa
58095816
constexpr bool kDisallow = true;
58105817
mScheduler->disableHardwareVsync(displayId, kDisallow);
58115818

5812-
if (displayId == mActiveDisplayId) {
5819+
if (displayId == mActiveDisplayId &&
5820+
!FlagManager::getInstance().correct_virtual_display_power_state()) {
58135821
mScheduler->enableSyntheticVsync();
58145822
}
58155823
getHwComposer().setPowerMode(displayId, mode);
@@ -5848,43 +5856,44 @@ void SurfaceFlinger::setVirtualDisplayPowerMode(const sp<DisplayDevice>& display
58485856
to_string(displayId).c_str());
58495857
}
58505858

5851-
bool SurfaceFlinger::shouldOptimizeForPerformance() {
5852-
for (const auto& [_, display] : mDisplays) {
5853-
// Displays that are optimized for power are always powered on and should not influence
5854-
// whether there is an active display for the purpose of power optimization, etc. If these
5855-
// displays are being shown somewhere, a different (physical or virtual) display that is
5856-
// optimized for performance will be powered on in addition. Displays optimized for
5857-
// performance will change power mode, so if they are off then they are not active.
5858-
if (display->isPoweredOn() &&
5859-
display->getOptimizationPolicy() ==
5860-
gui::ISurfaceComposer::OptimizationPolicy::optimizeForPerformance) {
5861-
return true;
5862-
}
5863-
}
5864-
return false;
5865-
}
5866-
5867-
void SurfaceFlinger::enablePowerOptimizations(const char* whence) {
5868-
ALOGD("%s: Enabling power optimizations", whence);
5869-
5870-
setSchedAttr(false, whence);
5871-
setSchedFifo(false, whence);
5872-
}
5873-
5874-
void SurfaceFlinger::disablePowerOptimizations(const char* whence) {
5875-
ALOGD("%s: Disabling power optimizations", whence);
5859+
void SurfaceFlinger::optimizeThreadScheduling(
5860+
const char* whence, gui::ISurfaceComposer::OptimizationPolicy optimizationPolicy) {
5861+
ALOGD("%s: Optimizing thread scheduling: %s", whence, to_string(optimizationPolicy));
58765862

5863+
const bool optimizeForPerformance =
5864+
optimizationPolicy == gui::ISurfaceComposer::OptimizationPolicy::optimizeForPerformance;
58775865
// TODO: b/281692563 - Merge the syscalls. For now, keep uclamp in a separate syscall
58785866
// and set it before SCHED_FIFO due to b/190237315.
5879-
setSchedAttr(true, whence);
5880-
setSchedFifo(true, whence);
5867+
setSchedAttr(optimizeForPerformance, whence);
5868+
setSchedFifo(optimizeForPerformance, whence);
58815869
}
58825870

58835871
void SurfaceFlinger::applyOptimizationPolicy(const char* whence) {
5884-
if (shouldOptimizeForPerformance()) {
5885-
disablePowerOptimizations(whence);
5886-
} else {
5887-
enablePowerOptimizations(whence);
5872+
using OptimizationPolicy = gui::ISurfaceComposer::OptimizationPolicy;
5873+
5874+
const bool optimizeForPerformance =
5875+
std::any_of(mDisplays.begin(), mDisplays.end(), [](const auto& pair) {
5876+
const auto& display = pair.second;
5877+
return display->isPoweredOn() &&
5878+
display->getOptimizationPolicy() ==
5879+
OptimizationPolicy::optimizeForPerformance;
5880+
});
5881+
5882+
optimizeThreadScheduling(whence,
5883+
optimizeForPerformance ? OptimizationPolicy::optimizeForPerformance
5884+
: OptimizationPolicy::optimizeForPower);
5885+
5886+
if (mScheduler) {
5887+
const bool disableSyntheticVsync =
5888+
std::any_of(mDisplays.begin(), mDisplays.end(), [](const auto& pair) {
5889+
const auto& display = pair.second;
5890+
const hal::PowerMode powerMode = display->getPowerMode();
5891+
return powerMode != hal::PowerMode::OFF &&
5892+
powerMode != hal::PowerMode::DOZE_SUSPEND &&
5893+
display->getOptimizationPolicy() ==
5894+
OptimizationPolicy::optimizeForPerformance;
5895+
});
5896+
mScheduler->enableSyntheticVsync(!disableSyntheticVsync);
58885897
}
58895898
}
58905899

services/surfaceflinger/SurfaceFlinger.h

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -733,19 +733,14 @@ class SurfaceFlinger : public BnSurfaceComposer,
733733
void setVirtualDisplayPowerMode(const sp<DisplayDevice>& display, hal::PowerMode mode)
734734
REQUIRES(mStateLock, kMainThreadContext);
735735

736-
// Returns whether to optimize globally for performance instead of power.
737-
bool shouldOptimizeForPerformance() REQUIRES(mStateLock);
738-
739-
// Turns on power optimizations, for example when there are no displays to be optimized for
740-
// performance.
741-
static void enablePowerOptimizations(const char* whence);
742-
743-
// Turns off power optimizations.
744-
static void disablePowerOptimizations(const char* whence);
736+
// Adjusts thread scheduling according to the optimization policy
737+
static void optimizeThreadScheduling(
738+
const char* whence, gui::ISurfaceComposer::OptimizationPolicy optimizationPolicy);
745739

746740
// Enables or disables power optimizations depending on whether there are displays that should
747741
// be optimized for performance.
748-
void applyOptimizationPolicy(const char* whence) REQUIRES(mStateLock);
742+
void applyOptimizationPolicy(const char* whence) REQUIRES(kMainThreadContext)
743+
REQUIRES(mStateLock);
749744

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

services/surfaceflinger/tests/unittests/SurfaceFlinger_SetPhysicalDisplayPowerModeTest.cpp

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#undef LOG_TAG
1818
#define LOG_TAG "LibSurfaceFlingerUnittests"
1919

20+
#include <android_companion_virtualdevice_flags.h>
2021
#include <com_android_graphics_surfaceflinger_flags.h>
2122
#include <common/test/FlagUtils.h>
2223
#include "DisplayTransactionTestHelpers.h"
@@ -78,11 +79,19 @@ struct EventThreadBaseSupportedVariant {
7879
struct EventThreadNotSupportedVariant : public EventThreadBaseSupportedVariant {
7980
static void setupEnableVsyncCallExpectations(DisplayTransactionTest* test) {
8081
EXPECT_CALL(test->mFlinger.scheduler()->mockRequestHardwareVsync, Call(_, true)).Times(1);
82+
setupDisableSyntheticVsyncCallExpectations(test);
83+
}
84+
85+
static void setupDisableSyntheticVsyncCallExpectations(DisplayTransactionTest* test) {
8186
EXPECT_CALL(*test->mEventThread, enableSyntheticVsync(_)).Times(0);
8287
}
8388

8489
static void setupDisableVsyncCallExpectations(DisplayTransactionTest* test) {
8590
EXPECT_CALL(test->mFlinger.scheduler()->mockRequestHardwareVsync, Call(_, false)).Times(1);
91+
setupEnableSyntheticVsyncCallExpectations(test);
92+
}
93+
94+
static void setupEnableSyntheticVsyncCallExpectations(DisplayTransactionTest* test) {
8695
EXPECT_CALL(*test->mEventThread, enableSyntheticVsync(_)).Times(0);
8796
}
8897
};
@@ -91,12 +100,20 @@ struct EventThreadIsSupportedVariant : public EventThreadBaseSupportedVariant {
91100
static void setupEnableVsyncCallExpectations(DisplayTransactionTest* test) {
92101
// Expect to enable hardware VSYNC and disable synthetic VSYNC.
93102
EXPECT_CALL(test->mFlinger.scheduler()->mockRequestHardwareVsync, Call(_, true)).Times(1);
103+
setupDisableSyntheticVsyncCallExpectations(test);
104+
}
105+
106+
static void setupDisableSyntheticVsyncCallExpectations(DisplayTransactionTest* test) {
94107
EXPECT_CALL(*test->mEventThread, enableSyntheticVsync(false)).Times(1);
95108
}
96109

97110
static void setupDisableVsyncCallExpectations(DisplayTransactionTest* test) {
98111
// Expect to disable hardware VSYNC and enable synthetic VSYNC.
99112
EXPECT_CALL(test->mFlinger.scheduler()->mockRequestHardwareVsync, Call(_, false)).Times(1);
113+
setupEnableSyntheticVsyncCallExpectations(test);
114+
}
115+
116+
static void setupEnableSyntheticVsyncCallExpectations(DisplayTransactionTest* test) {
100117
EXPECT_CALL(*test->mEventThread, enableSyntheticVsync(true)).Times(1);
101118
}
102119
};
@@ -151,7 +168,7 @@ struct TransitionOffToDozeSuspendVariant
151168
template <typename Case>
152169
static void setupCallExpectations(DisplayTransactionTest* test) {
153170
Case::setupComposerCallExpectations(test, Case::Doze::ACTUAL_POWER_MODE_FOR_DOZE_SUSPEND);
154-
Case::EventThread::setupVsyncNoCallExpectations(test);
171+
Case::EventThread::setupEnableSyntheticVsyncCallExpectations(test);
155172
Case::setupRepaintEverythingCallExpectations(test);
156173
}
157174

@@ -176,7 +193,7 @@ struct TransitionDozeSuspendToOffVariant
176193
: public TransitionVariantCommon<PowerMode::DOZE_SUSPEND, PowerMode::OFF> {
177194
template <typename Case>
178195
static void setupCallExpectations(DisplayTransactionTest* test) {
179-
Case::EventThread::setupVsyncNoCallExpectations(test);
196+
Case::EventThread::setupEnableSyntheticVsyncCallExpectations(test);
180197
Case::setupComposerCallExpectations(test, IComposerClient::PowerMode::OFF);
181198
}
182199

@@ -188,7 +205,7 @@ struct TransitionDozeSuspendToOffVariant
188205
struct TransitionOnToDozeVariant : public TransitionVariantCommon<PowerMode::ON, PowerMode::DOZE> {
189206
template <typename Case>
190207
static void setupCallExpectations(DisplayTransactionTest* test) {
191-
Case::EventThread::setupVsyncNoCallExpectations(test);
208+
Case::EventThread::setupDisableSyntheticVsyncCallExpectations(test);
192209
Case::setupComposerCallExpectations(test, Case::Doze::ACTUAL_POWER_MODE_FOR_DOZE);
193210
}
194211
};
@@ -206,7 +223,7 @@ struct TransitionDozeSuspendToDozeVariant
206223
struct TransitionDozeToOnVariant : public TransitionVariantCommon<PowerMode::DOZE, PowerMode::ON> {
207224
template <typename Case>
208225
static void setupCallExpectations(DisplayTransactionTest* test) {
209-
Case::EventThread::setupVsyncNoCallExpectations(test);
226+
Case::EventThread::setupDisableSyntheticVsyncCallExpectations(test);
210227
Case::setupComposerCallExpectations(test, IComposerClient::PowerMode::ON);
211228
}
212229
};
@@ -234,7 +251,7 @@ struct TransitionOnToUnknownVariant
234251
: public TransitionVariantCommon<PowerMode::ON, static_cast<PowerMode>(POWER_MODE_LEET)> {
235252
template <typename Case>
236253
static void setupCallExpectations(DisplayTransactionTest* test) {
237-
Case::EventThread::setupVsyncNoCallExpectations(test);
254+
Case::EventThread::setupDisableSyntheticVsyncCallExpectations(test);
238255
Case::setupNoComposerPowerModeCallExpectations(test);
239256
}
240257
};
@@ -335,6 +352,9 @@ void SetPhysicalDisplayPowerModeTest::transitionDisplayCommon() {
335352
// --------------------------------------------------------------------
336353
// Preconditions
337354

355+
SET_FLAG_FOR_TEST(android::companion::virtualdevice::flags::correct_virtual_display_power_state,
356+
true);
357+
338358
Case::Doze::setupComposerCallExpectations(this);
339359
auto display =
340360
Case::injectDisplayWithInitialPowerMode(this, Case::Transition::INITIAL_POWER_MODE);

0 commit comments

Comments
 (0)