Change hwui jank detection to use deadline & gpu completion (2/2)
- Use GPU finish time as well as actual deadline to determine jank
rate.
- Use dynamic interval to adjust for 60/90hz switching
- Move frame metrics reporting into JankTracker to adjust the
deadline communicated to the app when in stuffing scenario.
- Adjust double-stuffing detection to be a bit more readable.
Test: GraphicsStatsValidationTest.java
Test: adb shell dumpsys gfxinfo
Test: FrameMetricsListenerTest
Test: Log output of FrameMetricsObserver
Bug: 169858044
Change-Id: Ia1cae9f0c5358d1cd3bf043289ea8b4d26154737
diff --git a/services/surfaceflinger/Scheduler/EventThread.cpp b/services/surfaceflinger/Scheduler/EventThread.cpp
index 6553efe..2321e2d 100644
--- a/services/surfaceflinger/Scheduler/EventThread.cpp
+++ b/services/surfaceflinger/Scheduler/EventThread.cpp
@@ -217,12 +217,18 @@
EventThread::EventThread(std::unique_ptr<VSyncSource> vsyncSource,
android::frametimeline::TokenManager* tokenManager,
InterceptVSyncsCallback interceptVSyncsCallback,
- ThrottleVsyncCallback throttleVsyncCallback)
+ ThrottleVsyncCallback throttleVsyncCallback,
+ GetVsyncPeriodFunction getVsyncPeriodFunction)
: mVSyncSource(std::move(vsyncSource)),
mTokenManager(tokenManager),
mInterceptVSyncsCallback(std::move(interceptVSyncsCallback)),
mThrottleVsyncCallback(std::move(throttleVsyncCallback)),
+ mGetVsyncPeriodFunction(std::move(getVsyncPeriodFunction)),
mThreadName(mVSyncSource->getName()) {
+
+ LOG_ALWAYS_FATAL_IF(getVsyncPeriodFunction == nullptr,
+ "getVsyncPeriodFunction must not be null");
+
mVSyncSource->setCallback(this);
mThread = std::thread([this]() NO_THREAD_SAFETY_ANALYSIS {
@@ -565,7 +571,11 @@
void EventThread::dispatchEvent(const DisplayEventReceiver::Event& event,
const DisplayEventConsumers& consumers) {
for (const auto& consumer : consumers) {
- switch (consumer->postEvent(event)) {
+ DisplayEventReceiver::Event copy = event;
+ if (event.header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
+ copy.vsync.frameInterval = mGetVsyncPeriodFunction(consumer->mOwnerUid);
+ }
+ switch (consumer->postEvent(copy)) {
case NO_ERROR:
break;
diff --git a/services/surfaceflinger/Scheduler/EventThread.h b/services/surfaceflinger/Scheduler/EventThread.h
index 3540604..1e6793f 100644
--- a/services/surfaceflinger/Scheduler/EventThread.h
+++ b/services/surfaceflinger/Scheduler/EventThread.h
@@ -152,9 +152,10 @@
public:
using InterceptVSyncsCallback = std::function<void(nsecs_t)>;
using ThrottleVsyncCallback = std::function<bool(nsecs_t, uid_t)>;
+ using GetVsyncPeriodFunction = std::function<nsecs_t(uid_t)>;
EventThread(std::unique_ptr<VSyncSource>, frametimeline::TokenManager*, InterceptVSyncsCallback,
- ThrottleVsyncCallback);
+ ThrottleVsyncCallback, GetVsyncPeriodFunction);
~EventThread();
sp<EventThreadConnection> createEventConnection(
@@ -210,6 +211,7 @@
const InterceptVSyncsCallback mInterceptVSyncsCallback;
const ThrottleVsyncCallback mThrottleVsyncCallback;
+ const GetVsyncPeriodFunction mGetVsyncPeriodFunction;
const char* const mThreadName;
std::thread mThread;
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index 8426737..1d25c72 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -248,15 +248,34 @@
};
}
+impl::EventThread::GetVsyncPeriodFunction Scheduler::makeGetVsyncPeriodFunction() const {
+ return [this](uid_t uid) {
+ nsecs_t basePeriod = mRefreshRateConfigs.getCurrentRefreshRate().getVsyncPeriod();
+ const auto frameRate = getFrameRateOverride(uid);
+ if (!frameRate.has_value()) {
+ return basePeriod;
+ }
+
+ const auto divider = scheduler::RefreshRateConfigs::getFrameRateDivider(
+ mRefreshRateConfigs.getCurrentRefreshRate().getFps(), *frameRate);
+ if (divider <= 1) {
+ return basePeriod;
+ }
+ return basePeriod * divider;
+ };
+}
+
Scheduler::ConnectionHandle Scheduler::createConnection(
const char* connectionName, frametimeline::TokenManager* tokenManager,
std::chrono::nanoseconds workDuration, std::chrono::nanoseconds readyDuration,
impl::EventThread::InterceptVSyncsCallback interceptCallback) {
auto vsyncSource = makePrimaryDispSyncSource(connectionName, workDuration, readyDuration);
auto throttleVsync = makeThrottleVsyncCallback();
+ auto getVsyncPeriod = makeGetVsyncPeriodFunction();
auto eventThread = std::make_unique<impl::EventThread>(std::move(vsyncSource), tokenManager,
std::move(interceptCallback),
- std::move(throttleVsync));
+ std::move(throttleVsync),
+ std::move(getVsyncPeriod));
return createConnection(std::move(eventThread));
}
@@ -444,7 +463,8 @@
std::make_unique<impl::EventThread>(std::move(vsyncSource),
/*tokenManager=*/nullptr,
impl::EventThread::InterceptVSyncsCallback(),
- impl::EventThread::ThrottleVsyncCallback());
+ impl::EventThread::ThrottleVsyncCallback(),
+ impl::EventThread::GetVsyncPeriodFunction());
// EventThread does not dispatch VSYNC unless the display is connected and powered on.
eventThread->onHotplugReceived(PhysicalDisplayId::fromPort(0), true);
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index d4932e7..4d1f3c6 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -240,6 +240,7 @@
EXCLUDES(mFrameRateOverridesMutex);
impl::EventThread::ThrottleVsyncCallback makeThrottleVsyncCallback() const;
+ impl::EventThread::GetVsyncPeriodFunction makeGetVsyncPeriodFunction() const;
// Stores EventThread associated with a given VSyncSource, and an initial EventThreadConnection.
struct Connection {