1 /*
2  * Copyright (C) 2011 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 // TODO(b/129481165): remove the #pragma below and fix conversion issues
18 #pragma clang diagnostic push
19 #pragma clang diagnostic ignored "-Wconversion"
20 
21 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
22 
23 #include <pthread.h>
24 #include <sched.h>
25 #include <sys/types.h>
26 
27 #include <chrono>
28 #include <cstdint>
29 #include <optional>
30 #include <type_traits>
31 
32 #include <android-base/stringprintf.h>
33 
34 #include <binder/IPCThreadState.h>
35 
36 #include <cutils/compiler.h>
37 #include <cutils/sched_policy.h>
38 
39 #include <gui/DisplayEventReceiver.h>
40 
41 #include <utils/Errors.h>
42 #include <utils/Trace.h>
43 
44 #include "DisplayHardware/DisplayMode.h"
45 #include "FrameTimeline.h"
46 
47 #include "EventThread.h"
48 
49 #undef LOG_TAG
50 #define LOG_TAG "EventThread"
51 
52 using namespace std::chrono_literals;
53 
54 namespace android {
55 
56 using base::StringAppendF;
57 using base::StringPrintf;
58 
59 namespace {
60 
vsyncPeriod(VSyncRequest request)61 auto vsyncPeriod(VSyncRequest request) {
62     return static_cast<std::underlying_type_t<VSyncRequest>>(request);
63 }
64 
toString(VSyncRequest request)65 std::string toString(VSyncRequest request) {
66     switch (request) {
67         case VSyncRequest::None:
68             return "VSyncRequest::None";
69         case VSyncRequest::Single:
70             return "VSyncRequest::Single";
71         case VSyncRequest::SingleSuppressCallback:
72             return "VSyncRequest::SingleSuppressCallback";
73         default:
74             return StringPrintf("VSyncRequest::Periodic{period=%d}", vsyncPeriod(request));
75     }
76 }
77 
toString(const EventThreadConnection & connection)78 std::string toString(const EventThreadConnection& connection) {
79     return StringPrintf("Connection{%p, %s}", &connection,
80                         toString(connection.vsyncRequest).c_str());
81 }
82 
toString(const DisplayEventReceiver::Event & event)83 std::string toString(const DisplayEventReceiver::Event& event) {
84     switch (event.header.type) {
85         case DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG:
86             return StringPrintf("Hotplug{displayId=%s, %s}",
87                                 to_string(event.header.displayId).c_str(),
88                                 event.hotplug.connected ? "connected" : "disconnected");
89         case DisplayEventReceiver::DISPLAY_EVENT_VSYNC:
90             return StringPrintf("VSync{displayId=%s, count=%u, expectedVSyncTimestamp=%" PRId64 "}",
91                                 to_string(event.header.displayId).c_str(), event.vsync.count,
92                                 event.vsync.expectedVSyncTimestamp);
93         case DisplayEventReceiver::DISPLAY_EVENT_MODE_CHANGE:
94             return StringPrintf("ModeChanged{displayId=%s, modeId=%u}",
95                                 to_string(event.header.displayId).c_str(), event.modeChange.modeId);
96         default:
97             return "Event{}";
98     }
99 }
100 
makeHotplug(PhysicalDisplayId displayId,nsecs_t timestamp,bool connected)101 DisplayEventReceiver::Event makeHotplug(PhysicalDisplayId displayId, nsecs_t timestamp,
102                                         bool connected) {
103     DisplayEventReceiver::Event event;
104     event.header = {DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG, displayId, timestamp};
105     event.hotplug.connected = connected;
106     return event;
107 }
108 
makeVSync(PhysicalDisplayId displayId,nsecs_t timestamp,uint32_t count,nsecs_t expectedVSyncTimestamp,nsecs_t deadlineTimestamp,int64_t vsyncId)109 DisplayEventReceiver::Event makeVSync(PhysicalDisplayId displayId, nsecs_t timestamp,
110                                       uint32_t count, nsecs_t expectedVSyncTimestamp,
111                                       nsecs_t deadlineTimestamp, int64_t vsyncId) {
112     DisplayEventReceiver::Event event;
113     event.header = {DisplayEventReceiver::DISPLAY_EVENT_VSYNC, displayId, timestamp};
114     event.vsync.count = count;
115     event.vsync.expectedVSyncTimestamp = expectedVSyncTimestamp;
116     event.vsync.deadlineTimestamp = deadlineTimestamp;
117     event.vsync.vsyncId = vsyncId;
118     return event;
119 }
120 
makeModeChanged(DisplayModePtr mode)121 DisplayEventReceiver::Event makeModeChanged(DisplayModePtr mode) {
122     DisplayEventReceiver::Event event;
123     event.header = {DisplayEventReceiver::DISPLAY_EVENT_MODE_CHANGE, mode->getPhysicalDisplayId(),
124                     systemTime()};
125     event.modeChange.modeId = mode->getId().value();
126     event.modeChange.vsyncPeriod = mode->getVsyncPeriod();
127     return event;
128 }
129 
makeFrameRateOverrideEvent(PhysicalDisplayId displayId,FrameRateOverride frameRateOverride)130 DisplayEventReceiver::Event makeFrameRateOverrideEvent(PhysicalDisplayId displayId,
131                                                        FrameRateOverride frameRateOverride) {
132     return DisplayEventReceiver::Event{
133             .header =
134                     DisplayEventReceiver::Event::Header{
135                             .type = DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE,
136                             .displayId = displayId,
137                             .timestamp = systemTime(),
138                     },
139             .frameRateOverride = frameRateOverride,
140     };
141 }
142 
makeFrameRateOverrideFlushEvent(PhysicalDisplayId displayId)143 DisplayEventReceiver::Event makeFrameRateOverrideFlushEvent(PhysicalDisplayId displayId) {
144     return DisplayEventReceiver::Event{
145             .header = DisplayEventReceiver::Event::Header{
146                     .type = DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE_FLUSH,
147                     .displayId = displayId,
148                     .timestamp = systemTime(),
149             }};
150 }
151 
152 } // namespace
153 
EventThreadConnection(EventThread * eventThread,uid_t callingUid,ResyncCallback resyncCallback,ISurfaceComposer::EventRegistrationFlags eventRegistration)154 EventThreadConnection::EventThreadConnection(
155         EventThread* eventThread, uid_t callingUid, ResyncCallback resyncCallback,
156         ISurfaceComposer::EventRegistrationFlags eventRegistration)
157       : resyncCallback(std::move(resyncCallback)),
158         mOwnerUid(callingUid),
159         mEventRegistration(eventRegistration),
160         mEventThread(eventThread),
161         mChannel(gui::BitTube::DefaultSize) {}
162 
~EventThreadConnection()163 EventThreadConnection::~EventThreadConnection() {
164     // do nothing here -- clean-up will happen automatically
165     // when the main thread wakes up
166 }
167 
onFirstRef()168 void EventThreadConnection::onFirstRef() {
169     // NOTE: mEventThread doesn't hold a strong reference on us
170     mEventThread->registerDisplayEventConnection(this);
171 }
172 
stealReceiveChannel(gui::BitTube * outChannel)173 status_t EventThreadConnection::stealReceiveChannel(gui::BitTube* outChannel) {
174     outChannel->setReceiveFd(mChannel.moveReceiveFd());
175     outChannel->setSendFd(base::unique_fd(dup(mChannel.getSendFd())));
176     return NO_ERROR;
177 }
178 
setVsyncRate(uint32_t rate)179 status_t EventThreadConnection::setVsyncRate(uint32_t rate) {
180     mEventThread->setVsyncRate(rate, this);
181     return NO_ERROR;
182 }
183 
requestNextVsync()184 void EventThreadConnection::requestNextVsync() {
185     ATRACE_NAME("requestNextVsync");
186     mEventThread->requestNextVsync(this);
187 }
188 
postEvent(const DisplayEventReceiver::Event & event)189 status_t EventThreadConnection::postEvent(const DisplayEventReceiver::Event& event) {
190     constexpr auto toStatus = [](ssize_t size) {
191         return size < 0 ? status_t(size) : status_t(NO_ERROR);
192     };
193 
194     if (event.header.type == DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE ||
195         event.header.type == DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE_FLUSH) {
196         mPendingEvents.emplace_back(event);
197         if (event.header.type == DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE) {
198             return status_t(NO_ERROR);
199         }
200 
201         auto size = DisplayEventReceiver::sendEvents(&mChannel, mPendingEvents.data(),
202                                                      mPendingEvents.size());
203         mPendingEvents.clear();
204         return toStatus(size);
205     }
206 
207     auto size = DisplayEventReceiver::sendEvents(&mChannel, &event, 1);
208     return toStatus(size);
209 }
210 
211 // ---------------------------------------------------------------------------
212 
213 EventThread::~EventThread() = default;
214 
215 namespace impl {
216 
EventThread(std::unique_ptr<VSyncSource> vsyncSource,android::frametimeline::TokenManager * tokenManager,InterceptVSyncsCallback interceptVSyncsCallback,ThrottleVsyncCallback throttleVsyncCallback,GetVsyncPeriodFunction getVsyncPeriodFunction)217 EventThread::EventThread(std::unique_ptr<VSyncSource> vsyncSource,
218                          android::frametimeline::TokenManager* tokenManager,
219                          InterceptVSyncsCallback interceptVSyncsCallback,
220                          ThrottleVsyncCallback throttleVsyncCallback,
221                          GetVsyncPeriodFunction getVsyncPeriodFunction)
222       : mVSyncSource(std::move(vsyncSource)),
223         mTokenManager(tokenManager),
224         mInterceptVSyncsCallback(std::move(interceptVSyncsCallback)),
225         mThrottleVsyncCallback(std::move(throttleVsyncCallback)),
226         mGetVsyncPeriodFunction(std::move(getVsyncPeriodFunction)),
227         mThreadName(mVSyncSource->getName()) {
228 
229     LOG_ALWAYS_FATAL_IF(getVsyncPeriodFunction == nullptr,
230             "getVsyncPeriodFunction must not be null");
231 
232     mVSyncSource->setCallback(this);
233 
234     mThread = std::thread([this]() NO_THREAD_SAFETY_ANALYSIS {
235         std::unique_lock<std::mutex> lock(mMutex);
236         threadMain(lock);
237     });
238 
239     pthread_setname_np(mThread.native_handle(), mThreadName);
240 
241     pid_t tid = pthread_gettid_np(mThread.native_handle());
242 
243     // Use SCHED_FIFO to minimize jitter
244     constexpr int EVENT_THREAD_PRIORITY = 2;
245     struct sched_param param = {0};
246     param.sched_priority = EVENT_THREAD_PRIORITY;
247     if (pthread_setschedparam(mThread.native_handle(), SCHED_FIFO, &param) != 0) {
248         ALOGE("Couldn't set SCHED_FIFO for EventThread");
249     }
250 
251     set_sched_policy(tid, SP_FOREGROUND);
252 }
253 
~EventThread()254 EventThread::~EventThread() {
255     mVSyncSource->setCallback(nullptr);
256 
257     {
258         std::lock_guard<std::mutex> lock(mMutex);
259         mState = State::Quit;
260         mCondition.notify_all();
261     }
262     mThread.join();
263 }
264 
setDuration(std::chrono::nanoseconds workDuration,std::chrono::nanoseconds readyDuration)265 void EventThread::setDuration(std::chrono::nanoseconds workDuration,
266                               std::chrono::nanoseconds readyDuration) {
267     std::lock_guard<std::mutex> lock(mMutex);
268     mVSyncSource->setDuration(workDuration, readyDuration);
269 }
270 
createEventConnection(ResyncCallback resyncCallback,ISurfaceComposer::EventRegistrationFlags eventRegistration) const271 sp<EventThreadConnection> EventThread::createEventConnection(
272         ResyncCallback resyncCallback,
273         ISurfaceComposer::EventRegistrationFlags eventRegistration) const {
274     return new EventThreadConnection(const_cast<EventThread*>(this),
275                                      IPCThreadState::self()->getCallingUid(),
276                                      std::move(resyncCallback), eventRegistration);
277 }
278 
registerDisplayEventConnection(const sp<EventThreadConnection> & connection)279 status_t EventThread::registerDisplayEventConnection(const sp<EventThreadConnection>& connection) {
280     std::lock_guard<std::mutex> lock(mMutex);
281 
282     // this should never happen
283     auto it = std::find(mDisplayEventConnections.cbegin(),
284             mDisplayEventConnections.cend(), connection);
285     if (it != mDisplayEventConnections.cend()) {
286         ALOGW("DisplayEventConnection %p already exists", connection.get());
287         mCondition.notify_all();
288         return ALREADY_EXISTS;
289     }
290 
291     mDisplayEventConnections.push_back(connection);
292     mCondition.notify_all();
293     return NO_ERROR;
294 }
295 
removeDisplayEventConnectionLocked(const wp<EventThreadConnection> & connection)296 void EventThread::removeDisplayEventConnectionLocked(const wp<EventThreadConnection>& connection) {
297     auto it = std::find(mDisplayEventConnections.cbegin(),
298             mDisplayEventConnections.cend(), connection);
299     if (it != mDisplayEventConnections.cend()) {
300         mDisplayEventConnections.erase(it);
301     }
302 }
303 
setVsyncRate(uint32_t rate,const sp<EventThreadConnection> & connection)304 void EventThread::setVsyncRate(uint32_t rate, const sp<EventThreadConnection>& connection) {
305     if (static_cast<std::underlying_type_t<VSyncRequest>>(rate) < 0) {
306         return;
307     }
308 
309     std::lock_guard<std::mutex> lock(mMutex);
310 
311     const auto request = rate == 0 ? VSyncRequest::None : static_cast<VSyncRequest>(rate);
312     if (connection->vsyncRequest != request) {
313         connection->vsyncRequest = request;
314         mCondition.notify_all();
315     }
316 }
317 
requestNextVsync(const sp<EventThreadConnection> & connection)318 void EventThread::requestNextVsync(const sp<EventThreadConnection>& connection) {
319     if (connection->resyncCallback) {
320         connection->resyncCallback();
321     }
322 
323     std::lock_guard<std::mutex> lock(mMutex);
324 
325     if (connection->vsyncRequest == VSyncRequest::None) {
326         connection->vsyncRequest = VSyncRequest::Single;
327         mCondition.notify_all();
328     } else if (connection->vsyncRequest == VSyncRequest::SingleSuppressCallback) {
329         connection->vsyncRequest = VSyncRequest::Single;
330     }
331 }
332 
onScreenReleased()333 void EventThread::onScreenReleased() {
334     std::lock_guard<std::mutex> lock(mMutex);
335     if (!mVSyncState || mVSyncState->synthetic) {
336         return;
337     }
338 
339     mVSyncState->synthetic = true;
340     mCondition.notify_all();
341 }
342 
onScreenAcquired()343 void EventThread::onScreenAcquired() {
344     std::lock_guard<std::mutex> lock(mMutex);
345     if (!mVSyncState || !mVSyncState->synthetic) {
346         return;
347     }
348 
349     mVSyncState->synthetic = false;
350     mCondition.notify_all();
351 }
352 
onVSyncEvent(nsecs_t timestamp,nsecs_t expectedVSyncTimestamp,nsecs_t deadlineTimestamp)353 void EventThread::onVSyncEvent(nsecs_t timestamp, nsecs_t expectedVSyncTimestamp,
354                                nsecs_t deadlineTimestamp) {
355     std::lock_guard<std::mutex> lock(mMutex);
356 
357     LOG_FATAL_IF(!mVSyncState);
358     const int64_t vsyncId = [&] {
359         if (mTokenManager != nullptr) {
360             return mTokenManager->generateTokenForPredictions(
361                     {timestamp, deadlineTimestamp, expectedVSyncTimestamp});
362         }
363         return FrameTimelineInfo::INVALID_VSYNC_ID;
364     }();
365 
366     mPendingEvents.push_back(makeVSync(mVSyncState->displayId, timestamp, ++mVSyncState->count,
367                                        expectedVSyncTimestamp, deadlineTimestamp, vsyncId));
368     mCondition.notify_all();
369 }
370 
onHotplugReceived(PhysicalDisplayId displayId,bool connected)371 void EventThread::onHotplugReceived(PhysicalDisplayId displayId, bool connected) {
372     std::lock_guard<std::mutex> lock(mMutex);
373 
374     mPendingEvents.push_back(makeHotplug(displayId, systemTime(), connected));
375     mCondition.notify_all();
376 }
377 
onModeChanged(DisplayModePtr mode)378 void EventThread::onModeChanged(DisplayModePtr mode) {
379     std::lock_guard<std::mutex> lock(mMutex);
380 
381     mPendingEvents.push_back(makeModeChanged(mode));
382     mCondition.notify_all();
383 }
384 
onFrameRateOverridesChanged(PhysicalDisplayId displayId,std::vector<FrameRateOverride> overrides)385 void EventThread::onFrameRateOverridesChanged(PhysicalDisplayId displayId,
386                                               std::vector<FrameRateOverride> overrides) {
387     std::lock_guard<std::mutex> lock(mMutex);
388 
389     for (auto frameRateOverride : overrides) {
390         mPendingEvents.push_back(makeFrameRateOverrideEvent(displayId, frameRateOverride));
391     }
392     mPendingEvents.push_back(makeFrameRateOverrideFlushEvent(displayId));
393 
394     mCondition.notify_all();
395 }
396 
getEventThreadConnectionCount()397 size_t EventThread::getEventThreadConnectionCount() {
398     std::lock_guard<std::mutex> lock(mMutex);
399     return mDisplayEventConnections.size();
400 }
401 
threadMain(std::unique_lock<std::mutex> & lock)402 void EventThread::threadMain(std::unique_lock<std::mutex>& lock) {
403     DisplayEventConsumers consumers;
404 
405     while (mState != State::Quit) {
406         std::optional<DisplayEventReceiver::Event> event;
407 
408         // Determine next event to dispatch.
409         if (!mPendingEvents.empty()) {
410             event = mPendingEvents.front();
411             mPendingEvents.pop_front();
412 
413             switch (event->header.type) {
414                 case DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG:
415                     if (event->hotplug.connected && !mVSyncState) {
416                         mVSyncState.emplace(event->header.displayId);
417                     } else if (!event->hotplug.connected && mVSyncState &&
418                                mVSyncState->displayId == event->header.displayId) {
419                         mVSyncState.reset();
420                     }
421                     break;
422 
423                 case DisplayEventReceiver::DISPLAY_EVENT_VSYNC:
424                     if (mInterceptVSyncsCallback) {
425                         mInterceptVSyncsCallback(event->header.timestamp);
426                     }
427                     break;
428             }
429         }
430 
431         bool vsyncRequested = false;
432 
433         // Find connections that should consume this event.
434         auto it = mDisplayEventConnections.begin();
435         while (it != mDisplayEventConnections.end()) {
436             if (const auto connection = it->promote()) {
437                 vsyncRequested |= connection->vsyncRequest != VSyncRequest::None;
438 
439                 if (event && shouldConsumeEvent(*event, connection)) {
440                     consumers.push_back(connection);
441                 }
442 
443                 ++it;
444             } else {
445                 it = mDisplayEventConnections.erase(it);
446             }
447         }
448 
449         if (!consumers.empty()) {
450             dispatchEvent(*event, consumers);
451             consumers.clear();
452         }
453 
454         State nextState;
455         if (mVSyncState && vsyncRequested) {
456             nextState = mVSyncState->synthetic ? State::SyntheticVSync : State::VSync;
457         } else {
458             ALOGW_IF(!mVSyncState, "Ignoring VSYNC request while display is disconnected");
459             nextState = State::Idle;
460         }
461 
462         if (mState != nextState) {
463             if (mState == State::VSync) {
464                 mVSyncSource->setVSyncEnabled(false);
465             } else if (nextState == State::VSync) {
466                 mVSyncSource->setVSyncEnabled(true);
467             }
468 
469             mState = nextState;
470         }
471 
472         if (event) {
473             continue;
474         }
475 
476         // Wait for event or client registration/request.
477         if (mState == State::Idle) {
478             mCondition.wait(lock);
479         } else {
480             // Generate a fake VSYNC after a long timeout in case the driver stalls. When the
481             // display is off, keep feeding clients at 60 Hz.
482             const std::chrono::nanoseconds timeout =
483                     mState == State::SyntheticVSync ? 16ms : 1000ms;
484             if (mCondition.wait_for(lock, timeout) == std::cv_status::timeout) {
485                 if (mState == State::VSync) {
486                     ALOGW("Faking VSYNC due to driver stall for thread %s", mThreadName);
487                     std::string debugInfo = "VsyncSource debug info:\n";
488                     mVSyncSource->dump(debugInfo);
489                     // Log the debug info line-by-line to avoid logcat overflow
490                     auto pos = debugInfo.find('\n');
491                     while (pos != std::string::npos) {
492                         ALOGW("%s", debugInfo.substr(0, pos).c_str());
493                         debugInfo = debugInfo.substr(pos + 1);
494                         pos = debugInfo.find('\n');
495                     }
496                 }
497 
498                 LOG_FATAL_IF(!mVSyncState);
499                 const auto now = systemTime(SYSTEM_TIME_MONOTONIC);
500                 const auto deadlineTimestamp = now + timeout.count();
501                 const auto expectedVSyncTime = deadlineTimestamp + timeout.count();
502                 const int64_t vsyncId = [&] {
503                     if (mTokenManager != nullptr) {
504                         return mTokenManager->generateTokenForPredictions(
505                                 {now, deadlineTimestamp, expectedVSyncTime});
506                     }
507                     return FrameTimelineInfo::INVALID_VSYNC_ID;
508                 }();
509                 mPendingEvents.push_back(makeVSync(mVSyncState->displayId, now,
510                                                    ++mVSyncState->count, expectedVSyncTime,
511                                                    deadlineTimestamp, vsyncId));
512             }
513         }
514     }
515 }
516 
shouldConsumeEvent(const DisplayEventReceiver::Event & event,const sp<EventThreadConnection> & connection) const517 bool EventThread::shouldConsumeEvent(const DisplayEventReceiver::Event& event,
518                                      const sp<EventThreadConnection>& connection) const {
519     const auto throttleVsync = [&] {
520         return mThrottleVsyncCallback &&
521                 mThrottleVsyncCallback(event.vsync.expectedVSyncTimestamp, connection->mOwnerUid);
522     };
523 
524     switch (event.header.type) {
525         case DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG:
526             return true;
527 
528         case DisplayEventReceiver::DISPLAY_EVENT_MODE_CHANGE: {
529             return connection->mEventRegistration.test(
530                     ISurfaceComposer::EventRegistration::modeChanged);
531         }
532 
533         case DisplayEventReceiver::DISPLAY_EVENT_VSYNC:
534             switch (connection->vsyncRequest) {
535                 case VSyncRequest::None:
536                     return false;
537                 case VSyncRequest::SingleSuppressCallback:
538                     connection->vsyncRequest = VSyncRequest::None;
539                     return false;
540                 case VSyncRequest::Single: {
541                     if (throttleVsync()) {
542                         return false;
543                     }
544                     connection->vsyncRequest = VSyncRequest::SingleSuppressCallback;
545                     return true;
546                 }
547                 case VSyncRequest::Periodic:
548                     if (throttleVsync()) {
549                         return false;
550                     }
551                     return true;
552                 default:
553                     // We don't throttle vsync if the app set a vsync request rate
554                     // since there is no easy way to do that and this is a very
555                     // rare case
556                     return event.vsync.count % vsyncPeriod(connection->vsyncRequest) == 0;
557             }
558 
559         case DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE:
560             [[fallthrough]];
561         case DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE_FLUSH:
562             return connection->mEventRegistration.test(
563                     ISurfaceComposer::EventRegistration::frameRateOverride);
564 
565         default:
566             return false;
567     }
568 }
569 
dispatchEvent(const DisplayEventReceiver::Event & event,const DisplayEventConsumers & consumers)570 void EventThread::dispatchEvent(const DisplayEventReceiver::Event& event,
571                                 const DisplayEventConsumers& consumers) {
572     for (const auto& consumer : consumers) {
573         DisplayEventReceiver::Event copy = event;
574         if (event.header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
575             copy.vsync.frameInterval = mGetVsyncPeriodFunction(consumer->mOwnerUid);
576         }
577         switch (consumer->postEvent(copy)) {
578             case NO_ERROR:
579                 break;
580 
581             case -EAGAIN:
582                 // TODO: Try again if pipe is full.
583                 ALOGW("Failed dispatching %s for %s", toString(event).c_str(),
584                       toString(*consumer).c_str());
585                 break;
586 
587             default:
588                 // Treat EPIPE and other errors as fatal.
589                 removeDisplayEventConnectionLocked(consumer);
590         }
591     }
592 }
593 
dump(std::string & result) const594 void EventThread::dump(std::string& result) const {
595     std::lock_guard<std::mutex> lock(mMutex);
596 
597     StringAppendF(&result, "%s: state=%s VSyncState=", mThreadName, toCString(mState));
598     if (mVSyncState) {
599         StringAppendF(&result, "{displayId=%s, count=%u%s}\n",
600                       to_string(mVSyncState->displayId).c_str(), mVSyncState->count,
601                       mVSyncState->synthetic ? ", synthetic" : "");
602     } else {
603         StringAppendF(&result, "none\n");
604     }
605 
606     StringAppendF(&result, "  pending events (count=%zu):\n", mPendingEvents.size());
607     for (const auto& event : mPendingEvents) {
608         StringAppendF(&result, "    %s\n", toString(event).c_str());
609     }
610 
611     StringAppendF(&result, "  connections (count=%zu):\n", mDisplayEventConnections.size());
612     for (const auto& ptr : mDisplayEventConnections) {
613         if (const auto connection = ptr.promote()) {
614             StringAppendF(&result, "    %s\n", toString(*connection).c_str());
615         }
616     }
617 }
618 
toCString(State state)619 const char* EventThread::toCString(State state) {
620     switch (state) {
621         case State::Idle:
622             return "Idle";
623         case State::Quit:
624             return "Quit";
625         case State::SyntheticVSync:
626             return "SyntheticVSync";
627         case State::VSync:
628             return "VSync";
629     }
630 }
631 
632 } // namespace impl
633 } // namespace android
634 
635 // TODO(b/129481165): remove the #pragma below and fix conversion issues
636 #pragma clang diagnostic pop // ignored "-Wconversion"
637