From fc690e2a2d1d3cf08d71a02c4ecd14665c0f2039 Mon Sep 17 00:00:00 2001 From: Cheng Shi Date: Fri, 22 Oct 2021 08:53:11 +0000 Subject: Dispatch vsync when receiving vsync timeout to handle vsync loss. Currently we do not have a mechanism to guarantee the arrival of the vsync signal. The vsync signal loss may occur when the renderNodeAnimator is running. The render thread took a long time to perform drawing without time to read the pipe, and the pipe was filled with other signals like configChanged, causing surfaceflinger to miss a vsync signal. If a vsync lost, causing DisplayEventDispatcher::mWaitingForVsync to be true, resulting in DisplayEventDispatcher::scheduleVsync can no longer schedule another vsync. So we need to dispatch vsync when receiving vsync timeout. Bug: 204097701 Test: Manual Change-Id: Ibfa7a301ea17ebd58cae6b790a61d66c3d2e43fd Signed-off-by: shicheng --- libs/gui/DisplayEventDispatcher.cpp | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) (limited to 'libs/gui/DisplayEventDispatcher.cpp') diff --git a/libs/gui/DisplayEventDispatcher.cpp b/libs/gui/DisplayEventDispatcher.cpp index e1b1efc0ed..46800f2f14 100644 --- a/libs/gui/DisplayEventDispatcher.cpp +++ b/libs/gui/DisplayEventDispatcher.cpp @@ -33,10 +33,13 @@ namespace android { // using just a few large reads. static const size_t EVENT_BUFFER_SIZE = 100; +static constexpr nsecs_t WAITING_FOR_VSYNC_TIMEOUT = ms2ns(300); + DisplayEventDispatcher::DisplayEventDispatcher( const sp& looper, ISurfaceComposer::VsyncSource vsyncSource, ISurfaceComposer::EventRegistrationFlags eventRegistration) - : mLooper(looper), mReceiver(vsyncSource, eventRegistration), mWaitingForVsync(false) { + : mLooper(looper), mReceiver(vsyncSource, eventRegistration), mWaitingForVsync(false), + mLastVsyncCount(0), mLastScheduleVsyncTime(0) { ALOGV("dispatcher %p ~ Initializing display event dispatcher.", this); } @@ -86,6 +89,7 @@ status_t DisplayEventDispatcher::scheduleVsync() { } mWaitingForVsync = true; + mLastScheduleVsyncTime = systemTime(SYSTEM_TIME_MONOTONIC); } return OK; } @@ -124,9 +128,21 @@ int DisplayEventDispatcher::handleEvent(int, int events, void*) { this, ns2ms(vsyncTimestamp), to_string(vsyncDisplayId).c_str(), vsyncCount, vsyncEventData.id); mWaitingForVsync = false; + mLastVsyncCount = vsyncCount; dispatchVsync(vsyncTimestamp, vsyncDisplayId, vsyncCount, vsyncEventData); } + if (mWaitingForVsync) { + const nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC); + const nsecs_t vsyncScheduleDelay = currentTime - mLastScheduleVsyncTime; + if (vsyncScheduleDelay > WAITING_FOR_VSYNC_TIMEOUT) { + ALOGW("Vsync time out! vsyncScheduleDelay=%" PRId64 "ms", ns2ms(vsyncScheduleDelay)); + mWaitingForVsync = false; + dispatchVsync(currentTime, vsyncDisplayId /* displayId is not used */, + ++mLastVsyncCount, vsyncEventData /* empty data */); + } + } + return 1; // keep the callback } -- cgit v1.2.3-59-g8ed1b