• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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(PhysicalDisplayId displayId,DisplayModeId modeId,nsecs_t vsyncPeriod)121 DisplayEventReceiver::Event makeModeChanged(PhysicalDisplayId displayId, DisplayModeId modeId,
122                                             nsecs_t vsyncPeriod) {
123     DisplayEventReceiver::Event event;
124     event.header = {DisplayEventReceiver::DISPLAY_EVENT_MODE_CHANGE, displayId, systemTime()};
125     event.modeChange.modeId = modeId.value();
126     event.modeChange.vsyncPeriod = vsyncPeriod;
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(PhysicalDisplayId displayId,DisplayModeId modeId,nsecs_t vsyncPeriod)378 void EventThread::onModeChanged(PhysicalDisplayId displayId, DisplayModeId modeId,
379                                 nsecs_t vsyncPeriod) {
380     std::lock_guard<std::mutex> lock(mMutex);
381 
382     mPendingEvents.push_back(makeModeChanged(displayId, modeId, vsyncPeriod));
383     mCondition.notify_all();
384 }
385 
onFrameRateOverridesChanged(PhysicalDisplayId displayId,std::vector<FrameRateOverride> overrides)386 void EventThread::onFrameRateOverridesChanged(PhysicalDisplayId displayId,
387                                               std::vector<FrameRateOverride> overrides) {
388     std::lock_guard<std::mutex> lock(mMutex);
389 
390     for (auto frameRateOverride : overrides) {
391         mPendingEvents.push_back(makeFrameRateOverrideEvent(displayId, frameRateOverride));
392     }
393     mPendingEvents.push_back(makeFrameRateOverrideFlushEvent(displayId));
394 
395     mCondition.notify_all();
396 }
397 
getEventThreadConnectionCount()398 size_t EventThread::getEventThreadConnectionCount() {
399     std::lock_guard<std::mutex> lock(mMutex);
400     return mDisplayEventConnections.size();
401 }
402 
threadMain(std::unique_lock<std::mutex> & lock)403 void EventThread::threadMain(std::unique_lock<std::mutex>& lock) {
404     DisplayEventConsumers consumers;
405 
406     while (mState != State::Quit) {
407         std::optional<DisplayEventReceiver::Event> event;
408 
409         // Determine next event to dispatch.
410         if (!mPendingEvents.empty()) {
411             event = mPendingEvents.front();
412             mPendingEvents.pop_front();
413 
414             switch (event->header.type) {
415                 case DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG:
416                     if (event->hotplug.connected && !mVSyncState) {
417                         mVSyncState.emplace(event->header.displayId);
418                     } else if (!event->hotplug.connected && mVSyncState &&
419                                mVSyncState->displayId == event->header.displayId) {
420                         mVSyncState.reset();
421                     }
422                     break;
423 
424                 case DisplayEventReceiver::DISPLAY_EVENT_VSYNC:
425                     if (mInterceptVSyncsCallback) {
426                         mInterceptVSyncsCallback(event->header.timestamp);
427                     }
428                     break;
429             }
430         }
431 
432         bool vsyncRequested = false;
433 
434         // Find connections that should consume this event.
435         auto it = mDisplayEventConnections.begin();
436         while (it != mDisplayEventConnections.end()) {
437             if (const auto connection = it->promote()) {
438                 vsyncRequested |= connection->vsyncRequest != VSyncRequest::None;
439 
440                 if (event && shouldConsumeEvent(*event, connection)) {
441                     consumers.push_back(connection);
442                 }
443 
444                 ++it;
445             } else {
446                 it = mDisplayEventConnections.erase(it);
447             }
448         }
449 
450         if (!consumers.empty()) {
451             dispatchEvent(*event, consumers);
452             consumers.clear();
453         }
454 
455         State nextState;
456         if (mVSyncState && vsyncRequested) {
457             nextState = mVSyncState->synthetic ? State::SyntheticVSync : State::VSync;
458         } else {
459             ALOGW_IF(!mVSyncState, "Ignoring VSYNC request while display is disconnected");
460             nextState = State::Idle;
461         }
462 
463         if (mState != nextState) {
464             if (mState == State::VSync) {
465                 mVSyncSource->setVSyncEnabled(false);
466             } else if (nextState == State::VSync) {
467                 mVSyncSource->setVSyncEnabled(true);
468             }
469 
470             mState = nextState;
471         }
472 
473         if (event) {
474             continue;
475         }
476 
477         // Wait for event or client registration/request.
478         if (mState == State::Idle) {
479             mCondition.wait(lock);
480         } else {
481             // Generate a fake VSYNC after a long timeout in case the driver stalls. When the
482             // display is off, keep feeding clients at 60 Hz.
483             const std::chrono::nanoseconds timeout =
484                     mState == State::SyntheticVSync ? 16ms : 1000ms;
485             if (mCondition.wait_for(lock, timeout) == std::cv_status::timeout) {
486                 if (mState == State::VSync) {
487                     ALOGW("Faking VSYNC due to driver stall for thread %s", mThreadName);
488                     std::string debugInfo = "VsyncSource debug info:\n";
489                     mVSyncSource->dump(debugInfo);
490                     // Log the debug info line-by-line to avoid logcat overflow
491                     auto pos = debugInfo.find('\n');
492                     while (pos != std::string::npos) {
493                         ALOGW("%s", debugInfo.substr(0, pos).c_str());
494                         debugInfo = debugInfo.substr(pos + 1);
495                         pos = debugInfo.find('\n');
496                     }
497                 }
498 
499                 LOG_FATAL_IF(!mVSyncState);
500                 const auto now = systemTime(SYSTEM_TIME_MONOTONIC);
501                 const auto deadlineTimestamp = now + timeout.count();
502                 const auto expectedVSyncTime = deadlineTimestamp + timeout.count();
503                 const int64_t vsyncId = [&] {
504                     if (mTokenManager != nullptr) {
505                         return mTokenManager->generateTokenForPredictions(
506                                 {now, deadlineTimestamp, expectedVSyncTime});
507                     }
508                     return FrameTimelineInfo::INVALID_VSYNC_ID;
509                 }();
510                 mPendingEvents.push_back(makeVSync(mVSyncState->displayId, now,
511                                                    ++mVSyncState->count, expectedVSyncTime,
512                                                    deadlineTimestamp, vsyncId));
513             }
514         }
515     }
516 }
517 
shouldConsumeEvent(const DisplayEventReceiver::Event & event,const sp<EventThreadConnection> & connection) const518 bool EventThread::shouldConsumeEvent(const DisplayEventReceiver::Event& event,
519                                      const sp<EventThreadConnection>& connection) const {
520     const auto throttleVsync = [&] {
521         return mThrottleVsyncCallback &&
522                 mThrottleVsyncCallback(event.vsync.expectedVSyncTimestamp, connection->mOwnerUid);
523     };
524 
525     switch (event.header.type) {
526         case DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG:
527             return true;
528 
529         case DisplayEventReceiver::DISPLAY_EVENT_MODE_CHANGE: {
530             return connection->mEventRegistration.test(
531                     ISurfaceComposer::EventRegistration::modeChanged);
532         }
533 
534         case DisplayEventReceiver::DISPLAY_EVENT_VSYNC:
535             switch (connection->vsyncRequest) {
536                 case VSyncRequest::None:
537                     return false;
538                 case VSyncRequest::SingleSuppressCallback:
539                     connection->vsyncRequest = VSyncRequest::None;
540                     return false;
541                 case VSyncRequest::Single: {
542                     if (throttleVsync()) {
543                         return false;
544                     }
545                     connection->vsyncRequest = VSyncRequest::SingleSuppressCallback;
546                     return true;
547                 }
548                 case VSyncRequest::Periodic:
549                     if (throttleVsync()) {
550                         return false;
551                     }
552                     return true;
553                 default:
554                     // We don't throttle vsync if the app set a vsync request rate
555                     // since there is no easy way to do that and this is a very
556                     // rare case
557                     return event.vsync.count % vsyncPeriod(connection->vsyncRequest) == 0;
558             }
559 
560         case DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE:
561             [[fallthrough]];
562         case DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE_FLUSH:
563             return connection->mEventRegistration.test(
564                     ISurfaceComposer::EventRegistration::frameRateOverride);
565 
566         default:
567             return false;
568     }
569 }
570 
dispatchEvent(const DisplayEventReceiver::Event & event,const DisplayEventConsumers & consumers)571 void EventThread::dispatchEvent(const DisplayEventReceiver::Event& event,
572                                 const DisplayEventConsumers& consumers) {
573     for (const auto& consumer : consumers) {
574         DisplayEventReceiver::Event copy = event;
575         if (event.header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
576             copy.vsync.frameInterval = mGetVsyncPeriodFunction(consumer->mOwnerUid);
577         }
578         switch (consumer->postEvent(copy)) {
579             case NO_ERROR:
580                 break;
581 
582             case -EAGAIN:
583                 // TODO: Try again if pipe is full.
584                 ALOGW("Failed dispatching %s for %s", toString(event).c_str(),
585                       toString(*consumer).c_str());
586                 break;
587 
588             default:
589                 // Treat EPIPE and other errors as fatal.
590                 removeDisplayEventConnectionLocked(consumer);
591         }
592     }
593 }
594 
dump(std::string & result) const595 void EventThread::dump(std::string& result) const {
596     std::lock_guard<std::mutex> lock(mMutex);
597 
598     StringAppendF(&result, "%s: state=%s VSyncState=", mThreadName, toCString(mState));
599     if (mVSyncState) {
600         StringAppendF(&result, "{displayId=%s, count=%u%s}\n",
601                       to_string(mVSyncState->displayId).c_str(), mVSyncState->count,
602                       mVSyncState->synthetic ? ", synthetic" : "");
603     } else {
604         StringAppendF(&result, "none\n");
605     }
606 
607     StringAppendF(&result, "  pending events (count=%zu):\n", mPendingEvents.size());
608     for (const auto& event : mPendingEvents) {
609         StringAppendF(&result, "    %s\n", toString(event).c_str());
610     }
611 
612     StringAppendF(&result, "  connections (count=%zu):\n", mDisplayEventConnections.size());
613     for (const auto& ptr : mDisplayEventConnections) {
614         if (const auto connection = ptr.promote()) {
615             StringAppendF(&result, "    %s\n", toString(*connection).c_str());
616         }
617     }
618 }
619 
toCString(State state)620 const char* EventThread::toCString(State state) {
621     switch (state) {
622         case State::Idle:
623             return "Idle";
624         case State::Quit:
625             return "Quit";
626         case State::SyntheticVSync:
627             return "SyntheticVSync";
628         case State::VSync:
629             return "VSync";
630     }
631 }
632 
633 } // namespace impl
634 } // namespace android
635 
636 // TODO(b/129481165): remove the #pragma below and fix conversion issues
637 #pragma clang diagnostic pop // ignored "-Wconversion"
638