Skip to content

Commit a28d830

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. setPhysicalDisplayPowerMode now applies optimiation policy for any internal display power mode change (external displays are out of scope in this CL). This is necessary for foldables since the active display has not always been updated at that point. (This includes undoing commit 92bf32a, fixing the issue it caused, and adding an additional flag) Bug: 406147398 Bug: 342681202 Bug: 404073995 Flag: android.companion.virtualdevice.flags.correct_virtual_display_power_state Flag: com.android.graphics.surfaceflinger.flags.disable_synthetic_vsync_for_performance Test: ran failing tests (https://android-build.corp.google.com/builds/abtd/run/L41000030010571741) and SurfaceFlinger unit tests. Also verified logs include the call to applyOptimizationPolicy and SurfaceFlinger dumpsys not showing display in synthetic VSYNC when powered on. Change-Id: I4ffcb42379fa97546ad307f8077455495382e878
1 parent 35f9fab commit a28d830

File tree

8 files changed

+107
-71
lines changed

8 files changed

+107
-71
lines changed

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: 52 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -5678,7 +5678,15 @@ void SurfaceFlinger::setPhysicalDisplayPowerMode(const sp<DisplayDevice>& displa
56785678
incRefreshableDisplays();
56795679
}
56805680

5681+
const bool shouldApplyOptimizationPolicy =
5682+
FlagManager::getInstance().disable_synthetic_vsync_for_performance() &&
5683+
FlagManager::getInstance().correct_virtual_display_power_state();
5684+
if (isInternalDisplay && shouldApplyOptimizationPolicy) {
5685+
applyOptimizationPolicy(__func__);
5686+
}
5687+
56815688
const auto activeMode = display->refreshRateSelector().getActiveMode().modePtr;
5689+
using OptimizationPolicy = gui::ISurfaceComposer::OptimizationPolicy;
56825690
if (currentMode == hal::PowerMode::OFF) {
56835691
// Turn on the display
56845692

@@ -5693,12 +5701,9 @@ void SurfaceFlinger::setPhysicalDisplayPowerMode(const sp<DisplayDevice>& displa
56935701
onActiveDisplayChangedLocked(activeDisplay.get(), *display);
56945702
}
56955703

5696-
if (displayId == mActiveDisplayId) {
5697-
if (FlagManager::getInstance().correct_virtual_display_power_state()) {
5698-
applyOptimizationPolicy("setPhysicalDisplayPowerMode(ON)");
5699-
} else {
5700-
disablePowerOptimizations("setPhysicalDisplayPowerMode(ON)");
5701-
}
5704+
if (displayId == mActiveDisplayId && !shouldApplyOptimizationPolicy) {
5705+
optimizeThreadScheduling("setPhysicalDisplayPowerMode(ON/DOZE)",
5706+
OptimizationPolicy::optimizeForPerformance);
57025707
}
57035708

57045709
getHwComposer().setPowerMode(displayId, mode);
@@ -5707,7 +5712,7 @@ void SurfaceFlinger::setPhysicalDisplayPowerMode(const sp<DisplayDevice>& displa
57075712
mScheduler->getVsyncSchedule(displayId)->getPendingHardwareVsyncState();
57085713
requestHardwareVsync(displayId, enable);
57095714

5710-
if (displayId == mActiveDisplayId) {
5715+
if (displayId == mActiveDisplayId && !shouldApplyOptimizationPolicy) {
57115716
mScheduler->enableSyntheticVsync(false);
57125717
}
57135718

@@ -5724,13 +5729,12 @@ void SurfaceFlinger::setPhysicalDisplayPowerMode(const sp<DisplayDevice>& displa
57245729
if (const auto display = getActivatableDisplay()) {
57255730
onActiveDisplayChangedLocked(activeDisplay.get(), *display);
57265731
} else {
5727-
if (FlagManager::getInstance().correct_virtual_display_power_state()) {
5728-
applyOptimizationPolicy("setPhysicalDisplayPowerMode(OFF)");
5729-
} else {
5730-
enablePowerOptimizations("setPhysicalDisplayPowerMode(OFF)");
5732+
if (!shouldApplyOptimizationPolicy) {
5733+
optimizeThreadScheduling("setPhysicalDisplayPowerMode(OFF)",
5734+
OptimizationPolicy::optimizeForPower);
57315735
}
57325736

5733-
if (currentModeNotDozeSuspend) {
5737+
if (currentModeNotDozeSuspend && !shouldApplyOptimizationPolicy) {
57345738
mScheduler->enableSyntheticVsync();
57355739
}
57365740
}
@@ -5758,7 +5762,9 @@ void SurfaceFlinger::setPhysicalDisplayPowerMode(const sp<DisplayDevice>& displa
57585762
ALOGI("Force repainting for DOZE_SUSPEND -> DOZE or ON.");
57595763
mVisibleRegionsDirty = true;
57605764
scheduleRepaint();
5761-
mScheduler->enableSyntheticVsync(false);
5765+
if (!shouldApplyOptimizationPolicy) {
5766+
mScheduler->enableSyntheticVsync(false);
5767+
}
57625768
}
57635769
constexpr bool kAllowToEnable = true;
57645770
mScheduler->resyncToHardwareVsync(displayId, kAllowToEnable, activeMode.get());
@@ -5768,7 +5774,7 @@ void SurfaceFlinger::setPhysicalDisplayPowerMode(const sp<DisplayDevice>& displa
57685774
constexpr bool kDisallow = true;
57695775
mScheduler->disableHardwareVsync(displayId, kDisallow);
57705776

5771-
if (displayId == mActiveDisplayId) {
5777+
if (displayId == mActiveDisplayId && !shouldApplyOptimizationPolicy) {
57725778
mScheduler->enableSyntheticVsync();
57735779
}
57745780
getHwComposer().setPowerMode(displayId, mode);
@@ -5807,43 +5813,44 @@ void SurfaceFlinger::setVirtualDisplayPowerMode(const sp<DisplayDevice>& display
58075813
to_string(displayId).c_str());
58085814
}
58095815

5810-
bool SurfaceFlinger::shouldOptimizeForPerformance() {
5811-
for (const auto& [_, display] : mDisplays) {
5812-
// Displays that are optimized for power are always powered on and should not influence
5813-
// whether there is an active display for the purpose of power optimization, etc. If these
5814-
// displays are being shown somewhere, a different (physical or virtual) display that is
5815-
// optimized for performance will be powered on in addition. Displays optimized for
5816-
// performance will change power mode, so if they are off then they are not active.
5817-
if (display->isPoweredOn() &&
5818-
display->getOptimizationPolicy() ==
5819-
gui::ISurfaceComposer::OptimizationPolicy::optimizeForPerformance) {
5820-
return true;
5821-
}
5822-
}
5823-
return false;
5824-
}
5825-
5826-
void SurfaceFlinger::enablePowerOptimizations(const char* whence) {
5827-
ALOGD("%s: Enabling power optimizations", whence);
5828-
5829-
setSchedAttr(false, whence);
5830-
setSchedFifo(false, whence);
5831-
}
5832-
5833-
void SurfaceFlinger::disablePowerOptimizations(const char* whence) {
5834-
ALOGD("%s: Disabling power optimizations", whence);
5816+
void SurfaceFlinger::optimizeThreadScheduling(
5817+
const char* whence, gui::ISurfaceComposer::OptimizationPolicy optimizationPolicy) {
5818+
ALOGD("%s: Optimizing thread scheduling: %s", whence, to_string(optimizationPolicy));
58355819

5820+
const bool optimizeForPerformance =
5821+
optimizationPolicy == gui::ISurfaceComposer::OptimizationPolicy::optimizeForPerformance;
58365822
// TODO: b/281692563 - Merge the syscalls. For now, keep uclamp in a separate syscall
58375823
// and set it before SCHED_FIFO due to b/190237315.
5838-
setSchedAttr(true, whence);
5839-
setSchedFifo(true, whence);
5824+
setSchedAttr(optimizeForPerformance, whence);
5825+
setSchedFifo(optimizeForPerformance, whence);
58405826
}
58415827

58425828
void SurfaceFlinger::applyOptimizationPolicy(const char* whence) {
5843-
if (shouldOptimizeForPerformance()) {
5844-
disablePowerOptimizations(whence);
5845-
} else {
5846-
enablePowerOptimizations(whence);
5829+
using OptimizationPolicy = gui::ISurfaceComposer::OptimizationPolicy;
5830+
5831+
const bool optimizeForPerformance =
5832+
std::any_of(mDisplays.begin(), mDisplays.end(), [](const auto& pair) {
5833+
const auto& display = pair.second;
5834+
return display->isPoweredOn() &&
5835+
display->getOptimizationPolicy() ==
5836+
OptimizationPolicy::optimizeForPerformance;
5837+
});
5838+
5839+
optimizeThreadScheduling(whence,
5840+
optimizeForPerformance ? OptimizationPolicy::optimizeForPerformance
5841+
: OptimizationPolicy::optimizeForPower);
5842+
5843+
if (mScheduler) {
5844+
const bool disableSyntheticVsync =
5845+
std::any_of(mDisplays.begin(), mDisplays.end(), [](const auto& pair) {
5846+
const auto& display = pair.second;
5847+
const hal::PowerMode powerMode = display->getPowerMode();
5848+
return powerMode != hal::PowerMode::OFF &&
5849+
powerMode != hal::PowerMode::DOZE_SUSPEND &&
5850+
display->getOptimizationPolicy() ==
5851+
OptimizationPolicy::optimizeForPerformance;
5852+
});
5853+
mScheduler->enableSyntheticVsync(!disableSyntheticVsync);
58475854
}
58485855
}
58495856

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/common/FlagManager.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ void FlagManager::dump(std::string& result) const {
147147
DUMP_ACONFIG_FLAG(deprecate_frame_tracker);
148148
DUMP_ACONFIG_FLAG(deprecate_vsync_sf);
149149
DUMP_ACONFIG_FLAG(detached_mirror);
150+
DUMP_ACONFIG_FLAG(disable_synthetic_vsync_for_performance);
150151
DUMP_ACONFIG_FLAG(display_config_error_hal);
151152
DUMP_ACONFIG_FLAG(display_protected);
152153
DUMP_ACONFIG_FLAG(dont_skip_on_early_ro);
@@ -284,6 +285,7 @@ FLAG_MANAGER_ACONFIG_FLAG(latch_unsignaled_with_auto_refresh_changed, "");
284285
FLAG_MANAGER_ACONFIG_FLAG(deprecate_vsync_sf, "");
285286
FLAG_MANAGER_ACONFIG_FLAG(allow_n_vsyncs_in_targeter, "");
286287
FLAG_MANAGER_ACONFIG_FLAG(detached_mirror, "");
288+
FLAG_MANAGER_ACONFIG_FLAG(disable_synthetic_vsync_for_performance, "");
287289
FLAG_MANAGER_ACONFIG_FLAG(commit_not_composited, "");
288290
FLAG_MANAGER_ACONFIG_FLAG(correct_dpi_with_display_size, "");
289291
FLAG_MANAGER_ACONFIG_FLAG(local_tonemap_screenshots, "debug.sf.local_tonemap_screenshots");

services/surfaceflinger/common/include/common/FlagManager.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ class FlagManager {
8181
bool deprecate_frame_tracker() const;
8282
bool deprecate_vsync_sf() const;
8383
bool detached_mirror() const;
84+
bool disable_synthetic_vsync_for_performance() const;
8485
bool display_config_error_hal() const;
8586
bool display_protected() const;
8687
bool dont_skip_on_early_ro() const;

services/surfaceflinger/surfaceflinger_flags_new.aconfig

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,16 @@ flag {
133133
}
134134
} # detached_mirror
135135

136+
flag {
137+
name: "disable_synthetic_vsync_for_performance"
138+
namespace: "core_graphics"
139+
description: "Turn off synthetic VSYNC when adjusting thread scheduling for performance"
140+
bug: "406147398"
141+
metadata {
142+
purpose: PURPOSE_BUGFIX
143+
}
144+
} # disable_synthetic_vsync_for_performance
145+
136146
flag {
137147
name: "display_config_error_hal"
138148
namespace: "core_graphics"

services/surfaceflinger/tests/unittests/SurfaceFlinger_SetPhysicalDisplayPowerModeTest.cpp

Lines changed: 26 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,10 @@ void SetPhysicalDisplayPowerModeTest::transitionDisplayCommon() {
335352
// --------------------------------------------------------------------
336353
// Preconditions
337354

355+
SET_FLAG_FOR_TEST(android::companion::virtualdevice::flags::correct_virtual_display_power_state,
356+
true);
357+
SET_FLAG_FOR_TEST(flags::disable_synthetic_vsync_for_performance, true);
358+
338359
Case::Doze::setupComposerCallExpectations(this);
339360
auto display =
340361
Case::injectDisplayWithInitialPowerMode(this, Case::Transition::INITIAL_POWER_MODE);

0 commit comments

Comments
 (0)