Skip to content

Commit 8e3e2ea

Browse files
committed
SF: omit vsync callbacks when screen is OFF
This CL is submitted behind a flag and in still in development. The flag should not be enabled just yet. Test: manual Bug: 331636736 Flag: com.android.graphics.surfaceflinger.flags.no_vsyncs_on_screen_off Change-Id: Iec9cde3bafb9c112c9ce9beebe6dded4727fc99c
1 parent a8217b5 commit 8e3e2ea

9 files changed

Lines changed: 88 additions & 1 deletion

File tree

services/surfaceflinger/DisplayDevice.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,10 @@ bool DisplayDevice::isPoweredOn() const {
201201
return mPowerMode != hal::PowerMode::OFF;
202202
}
203203

204+
bool DisplayDevice::isRefreshable() const {
205+
return mPowerMode == hal::PowerMode::DOZE || mPowerMode == hal::PowerMode::ON;
206+
}
207+
204208
ui::Dataspace DisplayDevice::getCompositionDataSpace() const {
205209
return mCompositionDisplay->getState().dataspace;
206210
}

services/surfaceflinger/DisplayDevice.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,7 @@ class DisplayDevice : public RefBase {
173173
hardware::graphics::composer::hal::PowerMode getPowerMode() const;
174174
void setPowerMode(hardware::graphics::composer::hal::PowerMode);
175175
bool isPoweredOn() const;
176+
bool isRefreshable() const;
176177
void tracePowerMode();
177178

178179
// Enables layer caching on this DisplayDevice

services/surfaceflinger/Scheduler/EventThread.cpp

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -420,6 +420,16 @@ void EventThread::enableSyntheticVsync(bool enable) {
420420
mCondition.notify_all();
421421
}
422422

423+
void EventThread::omitVsyncDispatching(bool omitted) {
424+
std::lock_guard<std::mutex> lock(mMutex);
425+
if (!mVSyncState || mVSyncState->omitted == omitted) {
426+
return;
427+
}
428+
429+
mVSyncState->omitted = omitted;
430+
mCondition.notify_all();
431+
}
432+
423433
void EventThread::onVsync(nsecs_t vsyncTime, nsecs_t wakeupTime, nsecs_t readyTime) {
424434
std::lock_guard<std::mutex> lock(mMutex);
425435
mLastVsyncCallbackTime = TimePoint::fromNs(vsyncTime);
@@ -521,7 +531,17 @@ void EventThread::threadMain(std::unique_lock<std::mutex>& lock) {
521531
}
522532

523533
if (mVSyncState && vsyncRequested) {
524-
mState = mVSyncState->synthetic ? State::SyntheticVSync : State::VSync;
534+
const bool vsyncOmitted =
535+
FlagManager::getInstance().no_vsyncs_on_screen_off() && mVSyncState->omitted;
536+
if (vsyncOmitted) {
537+
mState = State::Idle;
538+
SFTRACE_INT("VsyncPendingScreenOn", 1);
539+
} else {
540+
mState = mVSyncState->synthetic ? State::SyntheticVSync : State::VSync;
541+
if (FlagManager::getInstance().no_vsyncs_on_screen_off()) {
542+
SFTRACE_INT("VsyncPendingScreenOn", 0);
543+
}
544+
}
525545
} else {
526546
ALOGW_IF(!mVSyncState, "Ignoring VSYNC request while display is disconnected");
527547
mState = State::Idle;

services/surfaceflinger/Scheduler/EventThread.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,8 @@ class EventThread {
106106
// Feed clients with fake VSYNC, e.g. while the display is off.
107107
virtual void enableSyntheticVsync(bool) = 0;
108108

109+
virtual void omitVsyncDispatching(bool) = 0;
110+
109111
virtual void onHotplugReceived(PhysicalDisplayId displayId, bool connected) = 0;
110112

111113
virtual void onHotplugConnectionError(int32_t connectionError) = 0;
@@ -165,6 +167,8 @@ class EventThread : public android::EventThread {
165167

166168
void enableSyntheticVsync(bool) override;
167169

170+
void omitVsyncDispatching(bool) override;
171+
168172
void onHotplugReceived(PhysicalDisplayId displayId, bool connected) override;
169173

170174
void onHotplugConnectionError(int32_t connectionError) override;
@@ -240,6 +244,9 @@ class EventThread : public android::EventThread {
240244

241245
// True if VSYNC should be faked, e.g. when display is off.
242246
bool synthetic = false;
247+
248+
// True if VSYNC should not be delivered to apps. Used when the display is off.
249+
bool omitted = false;
243250
};
244251

245252
// TODO(b/74619554): Create per-display threads waiting on respective VSYNC signals,

services/surfaceflinger/Scheduler/Scheduler.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,14 @@ void Scheduler::enableSyntheticVsync(bool enable) {
405405
eventThreadFor(Cycle::Render).enableSyntheticVsync(enable);
406406
}
407407

408+
void Scheduler::omitVsyncDispatching(bool omitted) {
409+
eventThreadFor(Cycle::Render).omitVsyncDispatching(omitted);
410+
// Note: If we don't couple Cycle::LastComposite event thread, there is a black screen
411+
// after boot. This is most likely sysui or system_server dependency on sf instance
412+
// Choreographer
413+
eventThreadFor(Cycle::LastComposite).omitVsyncDispatching(omitted);
414+
}
415+
408416
void Scheduler::onFrameRateOverridesChanged() {
409417
const auto [pacesetterId, supportsFrameRateOverrideByContent] = [this] {
410418
std::scoped_lock lock(mDisplayLock);

services/surfaceflinger/Scheduler/Scheduler.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ class Scheduler : public IEventThreadCallback, android::impl::MessageQueue {
154154
bool onDisplayModeChanged(PhysicalDisplayId, const FrameRateMode&) EXCLUDES(mPolicyLock);
155155

156156
void enableSyntheticVsync(bool = true) REQUIRES(kMainThreadContext);
157+
void omitVsyncDispatching(bool) REQUIRES(kMainThreadContext);
157158

158159
void onHdcpLevelsChanged(Cycle, PhysicalDisplayId, int32_t, int32_t);
159160

services/surfaceflinger/SurfaceFlinger.cpp

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3660,6 +3660,26 @@ sp<DisplayDevice> SurfaceFlinger::setupNewDisplayDeviceInternal(
36603660
return display;
36613661
}
36623662

3663+
void SurfaceFlinger::incRefreshableDisplays() {
3664+
if (FlagManager::getInstance().no_vsyncs_on_screen_off()) {
3665+
mRefreshableDisplays++;
3666+
if (mRefreshableDisplays == 1) {
3667+
ftl::FakeGuard guard(kMainThreadContext);
3668+
mScheduler->omitVsyncDispatching(false);
3669+
}
3670+
}
3671+
}
3672+
3673+
void SurfaceFlinger::decRefreshableDisplays() {
3674+
if (FlagManager::getInstance().no_vsyncs_on_screen_off()) {
3675+
mRefreshableDisplays--;
3676+
if (mRefreshableDisplays == 0) {
3677+
ftl::FakeGuard guard(kMainThreadContext);
3678+
mScheduler->omitVsyncDispatching(true);
3679+
}
3680+
}
3681+
}
3682+
36633683
void SurfaceFlinger::processDisplayAdded(const wp<IBinder>& displayToken,
36643684
const DisplayDeviceState& state) {
36653685
ui::Size resolution(0, 0);
@@ -3751,6 +3771,10 @@ void SurfaceFlinger::processDisplayAdded(const wp<IBinder>& displayToken,
37513771
display->adjustRefreshRate(mScheduler->getPacesetterRefreshRate());
37523772
}
37533773

3774+
if (display->isRefreshable()) {
3775+
incRefreshableDisplays();
3776+
}
3777+
37543778
mDisplays.try_emplace(displayToken, std::move(display));
37553779

37563780
// For an external display, loadDisplayModes already attempted to select the same mode
@@ -3785,6 +3809,10 @@ void SurfaceFlinger::processDisplayRemoved(const wp<IBinder>& displayToken) {
37853809
} else {
37863810
mScheduler->unregisterDisplay(display->getPhysicalId(), mActiveDisplayId);
37873811
}
3812+
3813+
if (display->isRefreshable()) {
3814+
decRefreshableDisplays();
3815+
}
37883816
}
37893817

37903818
mDisplays.erase(displayToken);
@@ -3819,6 +3847,10 @@ void SurfaceFlinger::processDisplayChanged(const wp<IBinder>& displayToken,
38193847
if (display->isVirtual()) {
38203848
releaseVirtualDisplay(display->getVirtualId());
38213849
}
3850+
3851+
if (display->isRefreshable()) {
3852+
decRefreshableDisplays();
3853+
}
38223854
}
38233855

38243856
mDisplays.erase(displayToken);
@@ -5317,7 +5349,15 @@ void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& display, hal:
53175349
activeDisplay->isPoweredOn(),
53185350
"Trying to change power mode on inactive display without powering off active display");
53195351

5352+
const bool couldRefresh = display->isRefreshable();
53205353
display->setPowerMode(mode);
5354+
const bool canRefresh = display->isRefreshable();
5355+
5356+
if (couldRefresh && !canRefresh) {
5357+
decRefreshableDisplays();
5358+
} else if (!couldRefresh && canRefresh) {
5359+
incRefreshableDisplays();
5360+
}
53215361

53225362
const auto activeMode = display->refreshRateSelector().getActiveMode().modePtr;
53235363
if (currentMode == hal::PowerMode::OFF) {

services/surfaceflinger/SurfaceFlinger.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1423,6 +1423,11 @@ class SurfaceFlinger : public BnSurfaceComposer,
14231423
// Whether a display should be turned on when initialized
14241424
bool mSkipPowerOnForQuiescent;
14251425

1426+
// used for omitting vsync callbacks to apps when the display is not updatable
1427+
int mRefreshableDisplays GUARDED_BY(mStateLock) = 0;
1428+
void incRefreshableDisplays() REQUIRES(mStateLock);
1429+
void decRefreshableDisplays() REQUIRES(mStateLock);
1430+
14261431
frontend::LayerLifecycleManager mLayerLifecycleManager GUARDED_BY(kMainThreadContext);
14271432
frontend::LayerHierarchyBuilder mLayerHierarchyBuilder GUARDED_BY(kMainThreadContext);
14281433
frontend::LayerSnapshotBuilder mLayerSnapshotBuilder GUARDED_BY(kMainThreadContext);

services/surfaceflinger/tests/unittests/mock/MockEventThread.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ class EventThread : public android::EventThread {
3030
MOCK_METHOD(sp<EventThreadConnection>, createEventConnection, (EventRegistrationFlags),
3131
(const, override));
3232
MOCK_METHOD(void, enableSyntheticVsync, (bool), (override));
33+
MOCK_METHOD(void, omitVsyncDispatching, (bool), (override));
3334
MOCK_METHOD(void, onHotplugReceived, (PhysicalDisplayId, bool), (override));
3435
MOCK_METHOD(void, onHotplugConnectionError, (int32_t), (override));
3536
MOCK_METHOD(void, onModeChanged, (const scheduler::FrameRateMode&), (override));

0 commit comments

Comments
 (0)