SurfaceFlinger: no app vsyncs during config switch
Do not dipatch vsync callbacks to applications during a config
switch as applications will get choreographer callbacks at uneven
times and will stuff the queue to surface flinger.
Test: test google/perf/jank/UIBench/UIBench-Trace:com.android.uibench.janktests.UiBenchJankTests#testClippedListView -v
Change-Id: I0537933c27af83a9186bcff54c3596d612c748ea
diff --git a/services/surfaceflinger/Scheduler/DispSyncSource.cpp b/services/surfaceflinger/Scheduler/DispSyncSource.cpp
index 697d634..d848c97 100644
--- a/services/surfaceflinger/Scheduler/DispSyncSource.cpp
+++ b/services/surfaceflinger/Scheduler/DispSyncSource.cpp
@@ -85,7 +85,19 @@
}
}
+void DispSyncSource::pauseVsyncCallback(bool pause) {
+ std::lock_guard lock(mVsyncMutex);
+ mCallbackPaused = pause;
+}
+
void DispSyncSource::onDispSyncEvent(nsecs_t when) {
+ {
+ std::lock_guard lock(mVsyncMutex);
+ if (mCallbackPaused) {
+ return;
+ }
+ }
+
VSyncSource::Callback* callback;
{
std::lock_guard lock(mCallbackMutex);
diff --git a/services/surfaceflinger/Scheduler/DispSyncSource.h b/services/surfaceflinger/Scheduler/DispSyncSource.h
index 0fd84a2..5e3d181 100644
--- a/services/surfaceflinger/Scheduler/DispSyncSource.h
+++ b/services/surfaceflinger/Scheduler/DispSyncSource.h
@@ -33,6 +33,7 @@
void setVSyncEnabled(bool enable) override;
void setCallback(VSyncSource::Callback* callback) override;
void setPhaseOffset(nsecs_t phaseOffset) override;
+ void pauseVsyncCallback(bool pause) override;
private:
// The following method is the implementation of the DispSync::Callback.
@@ -53,6 +54,7 @@
std::mutex mVsyncMutex;
nsecs_t mPhaseOffset GUARDED_BY(mVsyncMutex);
bool mEnabled GUARDED_BY(mVsyncMutex) = false;
+ bool mCallbackPaused GUARDED_BY(mVsyncMutex) = false;
};
} // namespace android
\ No newline at end of file
diff --git a/services/surfaceflinger/Scheduler/EventThread.cpp b/services/surfaceflinger/Scheduler/EventThread.cpp
index 5d9cfde..4b500f1 100644
--- a/services/surfaceflinger/Scheduler/EventThread.cpp
+++ b/services/surfaceflinger/Scheduler/EventThread.cpp
@@ -203,6 +203,12 @@
mVSyncSource->setPhaseOffset(phaseOffset);
}
+void EventThread::pauseVsyncCallback(bool pause) {
+ std::lock_guard<std::mutex> lock(mMutex);
+ ATRACE_INT("vsyncPaused", pause);
+ mVSyncSource->pauseVsyncCallback(pause);
+}
+
sp<EventThreadConnection> EventThread::createEventConnection(
ResyncCallback resyncCallback, ResetIdleTimerCallback resetIdleTimerCallback) const {
return new EventThreadConnection(const_cast<EventThread*>(this), std::move(resyncCallback),
diff --git a/services/surfaceflinger/Scheduler/EventThread.h b/services/surfaceflinger/Scheduler/EventThread.h
index b275183..3411438 100644
--- a/services/surfaceflinger/Scheduler/EventThread.h
+++ b/services/surfaceflinger/Scheduler/EventThread.h
@@ -66,6 +66,9 @@
virtual void setVSyncEnabled(bool enable) = 0;
virtual void setCallback(Callback* callback) = 0;
virtual void setPhaseOffset(nsecs_t phaseOffset) = 0;
+
+ // pause/resume vsync callback generation
+ virtual void pauseVsyncCallback(bool pause) = 0;
};
class EventThreadConnection : public BnDisplayEventConnection {
@@ -119,6 +122,8 @@
// Requests the next vsync. If resetIdleTimer is set to true, it resets the idle timer.
virtual void requestNextVsync(const sp<EventThreadConnection>& connection,
bool resetIdleTimer) = 0;
+
+ virtual void pauseVsyncCallback(bool pause) = 0;
};
namespace impl {
@@ -152,6 +157,8 @@
void setPhaseOffset(nsecs_t phaseOffset) override;
+ void pauseVsyncCallback(bool pause) override;
+
private:
friend EventThreadTest;
diff --git a/services/surfaceflinger/Scheduler/InjectVSyncSource.h b/services/surfaceflinger/Scheduler/InjectVSyncSource.h
index a0e1447..90609af 100644
--- a/services/surfaceflinger/Scheduler/InjectVSyncSource.h
+++ b/services/surfaceflinger/Scheduler/InjectVSyncSource.h
@@ -44,6 +44,7 @@
void setVSyncEnabled(bool) override {}
void setPhaseOffset(nsecs_t) override {}
+ void pauseVsyncCallback(bool) {}
private:
std::mutex mCallbackMutex;
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index 30fba3c..8ed3958 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -163,6 +163,12 @@
mConnections[handle->id]->thread->setPhaseOffset(phaseOffset);
}
+void Scheduler::pauseVsyncCallback(const android::sp<android::Scheduler::ConnectionHandle>& handle,
+ bool pause) {
+ RETURN_IF_INVALID();
+ mConnections[handle->id]->thread->pauseVsyncCallback(pause);
+}
+
void Scheduler::getDisplayStatInfo(DisplayStatInfo* stats) {
stats->vsyncTime = mPrimaryDispSync->computeNextRefresh(0);
stats->vsyncPeriod = mPrimaryDispSync->getPeriod();
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index 7b5278c..ce5c87e 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -111,6 +111,9 @@
// Offers ability to modify phase offset in the event thread.
void setPhaseOffset(const sp<ConnectionHandle>& handle, nsecs_t phaseOffset);
+ // pause/resume vsync callback generation to avoid sending vsync callbacks during config switch
+ void pauseVsyncCallback(const sp<ConnectionHandle>& handle, bool pause);
+
void getDisplayStatInfo(DisplayStatInfo* stats);
void enableHardwareVsync();