1*38e8c45fSAndroid Build Coastguard Worker /*
2*38e8c45fSAndroid Build Coastguard Worker * Copyright (C) 2011 The Android Open Source Project
3*38e8c45fSAndroid Build Coastguard Worker *
4*38e8c45fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*38e8c45fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*38e8c45fSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*38e8c45fSAndroid Build Coastguard Worker *
8*38e8c45fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*38e8c45fSAndroid Build Coastguard Worker *
10*38e8c45fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*38e8c45fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*38e8c45fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*38e8c45fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*38e8c45fSAndroid Build Coastguard Worker * limitations under the License.
15*38e8c45fSAndroid Build Coastguard Worker */
16*38e8c45fSAndroid Build Coastguard Worker
17*38e8c45fSAndroid Build Coastguard Worker // TODO(b/129481165): remove the #pragma below and fix conversion issues
18*38e8c45fSAndroid Build Coastguard Worker #pragma clang diagnostic push
19*38e8c45fSAndroid Build Coastguard Worker #pragma clang diagnostic ignored "-Wconversion"
20*38e8c45fSAndroid Build Coastguard Worker
21*38e8c45fSAndroid Build Coastguard Worker #define ATRACE_TAG ATRACE_TAG_GRAPHICS
22*38e8c45fSAndroid Build Coastguard Worker
23*38e8c45fSAndroid Build Coastguard Worker #include <pthread.h>
24*38e8c45fSAndroid Build Coastguard Worker #include <sched.h>
25*38e8c45fSAndroid Build Coastguard Worker #include <sys/types.h>
26*38e8c45fSAndroid Build Coastguard Worker
27*38e8c45fSAndroid Build Coastguard Worker #include <chrono>
28*38e8c45fSAndroid Build Coastguard Worker #include <cstdint>
29*38e8c45fSAndroid Build Coastguard Worker #include <optional>
30*38e8c45fSAndroid Build Coastguard Worker #include <type_traits>
31*38e8c45fSAndroid Build Coastguard Worker #include <utility>
32*38e8c45fSAndroid Build Coastguard Worker
33*38e8c45fSAndroid Build Coastguard Worker #include <android-base/stringprintf.h>
34*38e8c45fSAndroid Build Coastguard Worker
35*38e8c45fSAndroid Build Coastguard Worker #include <binder/IPCThreadState.h>
36*38e8c45fSAndroid Build Coastguard Worker #include <common/trace.h>
37*38e8c45fSAndroid Build Coastguard Worker #include <cutils/compiler.h>
38*38e8c45fSAndroid Build Coastguard Worker #include <cutils/sched_policy.h>
39*38e8c45fSAndroid Build Coastguard Worker
40*38e8c45fSAndroid Build Coastguard Worker #include <gui/DisplayEventReceiver.h>
41*38e8c45fSAndroid Build Coastguard Worker #include <gui/SchedulingPolicy.h>
42*38e8c45fSAndroid Build Coastguard Worker
43*38e8c45fSAndroid Build Coastguard Worker #include <utils/Errors.h>
44*38e8c45fSAndroid Build Coastguard Worker
45*38e8c45fSAndroid Build Coastguard Worker #include <common/FlagManager.h>
46*38e8c45fSAndroid Build Coastguard Worker #include <scheduler/FrameRateMode.h>
47*38e8c45fSAndroid Build Coastguard Worker #include <scheduler/VsyncConfig.h>
48*38e8c45fSAndroid Build Coastguard Worker #include "FrameTimeline.h"
49*38e8c45fSAndroid Build Coastguard Worker #include "VSyncDispatch.h"
50*38e8c45fSAndroid Build Coastguard Worker
51*38e8c45fSAndroid Build Coastguard Worker #include "EventThread.h"
52*38e8c45fSAndroid Build Coastguard Worker
53*38e8c45fSAndroid Build Coastguard Worker #undef LOG_TAG
54*38e8c45fSAndroid Build Coastguard Worker #define LOG_TAG "EventThread"
55*38e8c45fSAndroid Build Coastguard Worker
56*38e8c45fSAndroid Build Coastguard Worker using namespace std::chrono_literals;
57*38e8c45fSAndroid Build Coastguard Worker
58*38e8c45fSAndroid Build Coastguard Worker namespace android {
59*38e8c45fSAndroid Build Coastguard Worker
60*38e8c45fSAndroid Build Coastguard Worker using base::StringAppendF;
61*38e8c45fSAndroid Build Coastguard Worker using base::StringPrintf;
62*38e8c45fSAndroid Build Coastguard Worker
63*38e8c45fSAndroid Build Coastguard Worker namespace {
64*38e8c45fSAndroid Build Coastguard Worker
vsyncPeriod(VSyncRequest request)65*38e8c45fSAndroid Build Coastguard Worker auto vsyncPeriod(VSyncRequest request) {
66*38e8c45fSAndroid Build Coastguard Worker return static_cast<std::underlying_type_t<VSyncRequest>>(request);
67*38e8c45fSAndroid Build Coastguard Worker }
68*38e8c45fSAndroid Build Coastguard Worker
toString(VSyncRequest request)69*38e8c45fSAndroid Build Coastguard Worker std::string toString(VSyncRequest request) {
70*38e8c45fSAndroid Build Coastguard Worker switch (request) {
71*38e8c45fSAndroid Build Coastguard Worker case VSyncRequest::None:
72*38e8c45fSAndroid Build Coastguard Worker return "VSyncRequest::None";
73*38e8c45fSAndroid Build Coastguard Worker case VSyncRequest::Single:
74*38e8c45fSAndroid Build Coastguard Worker return "VSyncRequest::Single";
75*38e8c45fSAndroid Build Coastguard Worker case VSyncRequest::SingleSuppressCallback:
76*38e8c45fSAndroid Build Coastguard Worker return "VSyncRequest::SingleSuppressCallback";
77*38e8c45fSAndroid Build Coastguard Worker default:
78*38e8c45fSAndroid Build Coastguard Worker return StringPrintf("VSyncRequest::Periodic{period=%d}", vsyncPeriod(request));
79*38e8c45fSAndroid Build Coastguard Worker }
80*38e8c45fSAndroid Build Coastguard Worker }
81*38e8c45fSAndroid Build Coastguard Worker
toString(const EventThreadConnection & connection)82*38e8c45fSAndroid Build Coastguard Worker std::string toString(const EventThreadConnection& connection) {
83*38e8c45fSAndroid Build Coastguard Worker return StringPrintf("Connection{%p, %s}", &connection,
84*38e8c45fSAndroid Build Coastguard Worker toString(connection.vsyncRequest).c_str());
85*38e8c45fSAndroid Build Coastguard Worker }
86*38e8c45fSAndroid Build Coastguard Worker
toString(const DisplayEventReceiver::Event & event)87*38e8c45fSAndroid Build Coastguard Worker std::string toString(const DisplayEventReceiver::Event& event) {
88*38e8c45fSAndroid Build Coastguard Worker switch (event.header.type) {
89*38e8c45fSAndroid Build Coastguard Worker case DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG:
90*38e8c45fSAndroid Build Coastguard Worker return StringPrintf("Hotplug{displayId=%s, %s}",
91*38e8c45fSAndroid Build Coastguard Worker to_string(event.header.displayId).c_str(),
92*38e8c45fSAndroid Build Coastguard Worker event.hotplug.connected ? "connected" : "disconnected");
93*38e8c45fSAndroid Build Coastguard Worker case DisplayEventReceiver::DISPLAY_EVENT_VSYNC:
94*38e8c45fSAndroid Build Coastguard Worker return StringPrintf("VSync{displayId=%s, count=%u, expectedPresentationTime=%" PRId64
95*38e8c45fSAndroid Build Coastguard Worker "}",
96*38e8c45fSAndroid Build Coastguard Worker to_string(event.header.displayId).c_str(), event.vsync.count,
97*38e8c45fSAndroid Build Coastguard Worker event.vsync.vsyncData.preferredExpectedPresentationTime());
98*38e8c45fSAndroid Build Coastguard Worker case DisplayEventReceiver::DISPLAY_EVENT_MODE_CHANGE:
99*38e8c45fSAndroid Build Coastguard Worker return StringPrintf("ModeChanged{displayId=%s, modeId=%u}",
100*38e8c45fSAndroid Build Coastguard Worker to_string(event.header.displayId).c_str(), event.modeChange.modeId);
101*38e8c45fSAndroid Build Coastguard Worker case DisplayEventReceiver::DISPLAY_EVENT_HDCP_LEVELS_CHANGE:
102*38e8c45fSAndroid Build Coastguard Worker return StringPrintf("HdcpLevelsChange{displayId=%s, connectedLevel=%d, maxLevel=%d}",
103*38e8c45fSAndroid Build Coastguard Worker to_string(event.header.displayId).c_str(),
104*38e8c45fSAndroid Build Coastguard Worker event.hdcpLevelsChange.connectedLevel,
105*38e8c45fSAndroid Build Coastguard Worker event.hdcpLevelsChange.maxLevel);
106*38e8c45fSAndroid Build Coastguard Worker case DisplayEventReceiver::DISPLAY_EVENT_MODE_REJECTION:
107*38e8c45fSAndroid Build Coastguard Worker return StringPrintf("ModeRejected{displayId=%s, modeId=%u}",
108*38e8c45fSAndroid Build Coastguard Worker to_string(event.header.displayId).c_str(),
109*38e8c45fSAndroid Build Coastguard Worker event.modeRejection.modeId);
110*38e8c45fSAndroid Build Coastguard Worker default:
111*38e8c45fSAndroid Build Coastguard Worker return "Event{}";
112*38e8c45fSAndroid Build Coastguard Worker }
113*38e8c45fSAndroid Build Coastguard Worker }
114*38e8c45fSAndroid Build Coastguard Worker
makeHotplug(PhysicalDisplayId displayId,nsecs_t timestamp,bool connected)115*38e8c45fSAndroid Build Coastguard Worker DisplayEventReceiver::Event makeHotplug(PhysicalDisplayId displayId, nsecs_t timestamp,
116*38e8c45fSAndroid Build Coastguard Worker bool connected) {
117*38e8c45fSAndroid Build Coastguard Worker DisplayEventReceiver::Event event;
118*38e8c45fSAndroid Build Coastguard Worker event.header = {DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG, displayId, timestamp};
119*38e8c45fSAndroid Build Coastguard Worker event.hotplug.connected = connected;
120*38e8c45fSAndroid Build Coastguard Worker return event;
121*38e8c45fSAndroid Build Coastguard Worker }
122*38e8c45fSAndroid Build Coastguard Worker
makeHotplugError(nsecs_t timestamp,int32_t connectionError)123*38e8c45fSAndroid Build Coastguard Worker DisplayEventReceiver::Event makeHotplugError(nsecs_t timestamp, int32_t connectionError) {
124*38e8c45fSAndroid Build Coastguard Worker DisplayEventReceiver::Event event;
125*38e8c45fSAndroid Build Coastguard Worker PhysicalDisplayId unusedDisplayId;
126*38e8c45fSAndroid Build Coastguard Worker event.header = {DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG, unusedDisplayId, timestamp};
127*38e8c45fSAndroid Build Coastguard Worker event.hotplug.connected = false;
128*38e8c45fSAndroid Build Coastguard Worker event.hotplug.connectionError = connectionError;
129*38e8c45fSAndroid Build Coastguard Worker return event;
130*38e8c45fSAndroid Build Coastguard Worker }
131*38e8c45fSAndroid Build Coastguard Worker
makeVSync(PhysicalDisplayId displayId,nsecs_t timestamp,uint32_t count,nsecs_t expectedPresentationTime,nsecs_t deadlineTimestamp)132*38e8c45fSAndroid Build Coastguard Worker DisplayEventReceiver::Event makeVSync(PhysicalDisplayId displayId, nsecs_t timestamp,
133*38e8c45fSAndroid Build Coastguard Worker uint32_t count, nsecs_t expectedPresentationTime,
134*38e8c45fSAndroid Build Coastguard Worker nsecs_t deadlineTimestamp) {
135*38e8c45fSAndroid Build Coastguard Worker DisplayEventReceiver::Event event;
136*38e8c45fSAndroid Build Coastguard Worker event.header = {DisplayEventReceiver::DISPLAY_EVENT_VSYNC, displayId, timestamp};
137*38e8c45fSAndroid Build Coastguard Worker event.vsync.count = count;
138*38e8c45fSAndroid Build Coastguard Worker event.vsync.vsyncData.preferredFrameTimelineIndex = 0;
139*38e8c45fSAndroid Build Coastguard Worker // Temporarily store the current vsync information in frameTimelines[0], marked as
140*38e8c45fSAndroid Build Coastguard Worker // platform-preferred. When the event is dispatched later, the frame interval at that time is
141*38e8c45fSAndroid Build Coastguard Worker // used with this information to generate multiple frame timeline choices.
142*38e8c45fSAndroid Build Coastguard Worker event.vsync.vsyncData.frameTimelines[0] = {.vsyncId = FrameTimelineInfo::INVALID_VSYNC_ID,
143*38e8c45fSAndroid Build Coastguard Worker .deadlineTimestamp = deadlineTimestamp,
144*38e8c45fSAndroid Build Coastguard Worker .expectedPresentationTime =
145*38e8c45fSAndroid Build Coastguard Worker expectedPresentationTime};
146*38e8c45fSAndroid Build Coastguard Worker return event;
147*38e8c45fSAndroid Build Coastguard Worker }
148*38e8c45fSAndroid Build Coastguard Worker
makeModeChanged(const scheduler::FrameRateMode & mode)149*38e8c45fSAndroid Build Coastguard Worker DisplayEventReceiver::Event makeModeChanged(const scheduler::FrameRateMode& mode) {
150*38e8c45fSAndroid Build Coastguard Worker DisplayEventReceiver::Event event;
151*38e8c45fSAndroid Build Coastguard Worker event.header = {DisplayEventReceiver::DISPLAY_EVENT_MODE_CHANGE,
152*38e8c45fSAndroid Build Coastguard Worker mode.modePtr->getPhysicalDisplayId(), systemTime()};
153*38e8c45fSAndroid Build Coastguard Worker event.modeChange.modeId = ftl::to_underlying(mode.modePtr->getId());
154*38e8c45fSAndroid Build Coastguard Worker event.modeChange.vsyncPeriod = mode.fps.getPeriodNsecs();
155*38e8c45fSAndroid Build Coastguard Worker return event;
156*38e8c45fSAndroid Build Coastguard Worker }
157*38e8c45fSAndroid Build Coastguard Worker
makeFrameRateOverrideEvent(PhysicalDisplayId displayId,FrameRateOverride frameRateOverride)158*38e8c45fSAndroid Build Coastguard Worker DisplayEventReceiver::Event makeFrameRateOverrideEvent(PhysicalDisplayId displayId,
159*38e8c45fSAndroid Build Coastguard Worker FrameRateOverride frameRateOverride) {
160*38e8c45fSAndroid Build Coastguard Worker return DisplayEventReceiver::Event{
161*38e8c45fSAndroid Build Coastguard Worker .header =
162*38e8c45fSAndroid Build Coastguard Worker DisplayEventReceiver::Event::Header{
163*38e8c45fSAndroid Build Coastguard Worker .type = DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE,
164*38e8c45fSAndroid Build Coastguard Worker .displayId = displayId,
165*38e8c45fSAndroid Build Coastguard Worker .timestamp = systemTime(),
166*38e8c45fSAndroid Build Coastguard Worker },
167*38e8c45fSAndroid Build Coastguard Worker .frameRateOverride = frameRateOverride,
168*38e8c45fSAndroid Build Coastguard Worker };
169*38e8c45fSAndroid Build Coastguard Worker }
170*38e8c45fSAndroid Build Coastguard Worker
makeFrameRateOverrideFlushEvent(PhysicalDisplayId displayId)171*38e8c45fSAndroid Build Coastguard Worker DisplayEventReceiver::Event makeFrameRateOverrideFlushEvent(PhysicalDisplayId displayId) {
172*38e8c45fSAndroid Build Coastguard Worker return DisplayEventReceiver::Event{
173*38e8c45fSAndroid Build Coastguard Worker .header = DisplayEventReceiver::Event::Header{
174*38e8c45fSAndroid Build Coastguard Worker .type = DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE_FLUSH,
175*38e8c45fSAndroid Build Coastguard Worker .displayId = displayId,
176*38e8c45fSAndroid Build Coastguard Worker .timestamp = systemTime(),
177*38e8c45fSAndroid Build Coastguard Worker }};
178*38e8c45fSAndroid Build Coastguard Worker }
179*38e8c45fSAndroid Build Coastguard Worker
makeHdcpLevelsChange(PhysicalDisplayId displayId,int32_t connectedLevel,int32_t maxLevel)180*38e8c45fSAndroid Build Coastguard Worker DisplayEventReceiver::Event makeHdcpLevelsChange(PhysicalDisplayId displayId,
181*38e8c45fSAndroid Build Coastguard Worker int32_t connectedLevel, int32_t maxLevel) {
182*38e8c45fSAndroid Build Coastguard Worker return DisplayEventReceiver::Event{
183*38e8c45fSAndroid Build Coastguard Worker .header =
184*38e8c45fSAndroid Build Coastguard Worker DisplayEventReceiver::Event::Header{
185*38e8c45fSAndroid Build Coastguard Worker .type = DisplayEventReceiver::DISPLAY_EVENT_HDCP_LEVELS_CHANGE,
186*38e8c45fSAndroid Build Coastguard Worker .displayId = displayId,
187*38e8c45fSAndroid Build Coastguard Worker .timestamp = systemTime(),
188*38e8c45fSAndroid Build Coastguard Worker },
189*38e8c45fSAndroid Build Coastguard Worker .hdcpLevelsChange.connectedLevel = connectedLevel,
190*38e8c45fSAndroid Build Coastguard Worker .hdcpLevelsChange.maxLevel = maxLevel,
191*38e8c45fSAndroid Build Coastguard Worker };
192*38e8c45fSAndroid Build Coastguard Worker }
193*38e8c45fSAndroid Build Coastguard Worker
makeModeRejection(PhysicalDisplayId displayId,DisplayModeId modeId)194*38e8c45fSAndroid Build Coastguard Worker DisplayEventReceiver::Event makeModeRejection(PhysicalDisplayId displayId, DisplayModeId modeId) {
195*38e8c45fSAndroid Build Coastguard Worker return DisplayEventReceiver::Event{
196*38e8c45fSAndroid Build Coastguard Worker .header =
197*38e8c45fSAndroid Build Coastguard Worker DisplayEventReceiver::Event::Header{
198*38e8c45fSAndroid Build Coastguard Worker .type = DisplayEventReceiver::DISPLAY_EVENT_MODE_REJECTION,
199*38e8c45fSAndroid Build Coastguard Worker .displayId = displayId,
200*38e8c45fSAndroid Build Coastguard Worker .timestamp = systemTime(),
201*38e8c45fSAndroid Build Coastguard Worker },
202*38e8c45fSAndroid Build Coastguard Worker .modeRejection.modeId = ftl::to_underlying(modeId),
203*38e8c45fSAndroid Build Coastguard Worker };
204*38e8c45fSAndroid Build Coastguard Worker }
205*38e8c45fSAndroid Build Coastguard Worker
206*38e8c45fSAndroid Build Coastguard Worker } // namespace
207*38e8c45fSAndroid Build Coastguard Worker
EventThreadConnection(EventThread * eventThread,uid_t callingUid,EventRegistrationFlags eventRegistration)208*38e8c45fSAndroid Build Coastguard Worker EventThreadConnection::EventThreadConnection(EventThread* eventThread, uid_t callingUid,
209*38e8c45fSAndroid Build Coastguard Worker EventRegistrationFlags eventRegistration)
210*38e8c45fSAndroid Build Coastguard Worker : mOwnerUid(callingUid),
211*38e8c45fSAndroid Build Coastguard Worker mEventRegistration(eventRegistration),
212*38e8c45fSAndroid Build Coastguard Worker mEventThread(eventThread),
213*38e8c45fSAndroid Build Coastguard Worker mChannel(gui::BitTube::DefaultSize) {}
214*38e8c45fSAndroid Build Coastguard Worker
~EventThreadConnection()215*38e8c45fSAndroid Build Coastguard Worker EventThreadConnection::~EventThreadConnection() {
216*38e8c45fSAndroid Build Coastguard Worker // do nothing here -- clean-up will happen automatically
217*38e8c45fSAndroid Build Coastguard Worker // when the main thread wakes up
218*38e8c45fSAndroid Build Coastguard Worker }
219*38e8c45fSAndroid Build Coastguard Worker
onFirstRef()220*38e8c45fSAndroid Build Coastguard Worker void EventThreadConnection::onFirstRef() {
221*38e8c45fSAndroid Build Coastguard Worker // NOTE: mEventThread doesn't hold a strong reference on us
222*38e8c45fSAndroid Build Coastguard Worker mEventThread->registerDisplayEventConnection(sp<EventThreadConnection>::fromExisting(this));
223*38e8c45fSAndroid Build Coastguard Worker }
224*38e8c45fSAndroid Build Coastguard Worker
stealReceiveChannel(gui::BitTube * outChannel)225*38e8c45fSAndroid Build Coastguard Worker binder::Status EventThreadConnection::stealReceiveChannel(gui::BitTube* outChannel) {
226*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock lock(mLock);
227*38e8c45fSAndroid Build Coastguard Worker if (mChannel.initCheck() != NO_ERROR) {
228*38e8c45fSAndroid Build Coastguard Worker return binder::Status::fromStatusT(NAME_NOT_FOUND);
229*38e8c45fSAndroid Build Coastguard Worker }
230*38e8c45fSAndroid Build Coastguard Worker
231*38e8c45fSAndroid Build Coastguard Worker outChannel->setReceiveFd(mChannel.moveReceiveFd());
232*38e8c45fSAndroid Build Coastguard Worker outChannel->setSendFd(base::unique_fd(dup(mChannel.getSendFd())));
233*38e8c45fSAndroid Build Coastguard Worker return binder::Status::ok();
234*38e8c45fSAndroid Build Coastguard Worker }
235*38e8c45fSAndroid Build Coastguard Worker
setVsyncRate(int rate)236*38e8c45fSAndroid Build Coastguard Worker binder::Status EventThreadConnection::setVsyncRate(int rate) {
237*38e8c45fSAndroid Build Coastguard Worker mEventThread->setVsyncRate(static_cast<uint32_t>(rate),
238*38e8c45fSAndroid Build Coastguard Worker sp<EventThreadConnection>::fromExisting(this));
239*38e8c45fSAndroid Build Coastguard Worker return binder::Status::ok();
240*38e8c45fSAndroid Build Coastguard Worker }
241*38e8c45fSAndroid Build Coastguard Worker
requestNextVsync()242*38e8c45fSAndroid Build Coastguard Worker binder::Status EventThreadConnection::requestNextVsync() {
243*38e8c45fSAndroid Build Coastguard Worker SFTRACE_CALL();
244*38e8c45fSAndroid Build Coastguard Worker mEventThread->requestNextVsync(sp<EventThreadConnection>::fromExisting(this));
245*38e8c45fSAndroid Build Coastguard Worker return binder::Status::ok();
246*38e8c45fSAndroid Build Coastguard Worker }
247*38e8c45fSAndroid Build Coastguard Worker
getLatestVsyncEventData(ParcelableVsyncEventData * outVsyncEventData)248*38e8c45fSAndroid Build Coastguard Worker binder::Status EventThreadConnection::getLatestVsyncEventData(
249*38e8c45fSAndroid Build Coastguard Worker ParcelableVsyncEventData* outVsyncEventData) {
250*38e8c45fSAndroid Build Coastguard Worker SFTRACE_CALL();
251*38e8c45fSAndroid Build Coastguard Worker outVsyncEventData->vsync =
252*38e8c45fSAndroid Build Coastguard Worker mEventThread->getLatestVsyncEventData(sp<EventThreadConnection>::fromExisting(this),
253*38e8c45fSAndroid Build Coastguard Worker systemTime());
254*38e8c45fSAndroid Build Coastguard Worker return binder::Status::ok();
255*38e8c45fSAndroid Build Coastguard Worker }
256*38e8c45fSAndroid Build Coastguard Worker
getSchedulingPolicy(gui::SchedulingPolicy * outPolicy)257*38e8c45fSAndroid Build Coastguard Worker binder::Status EventThreadConnection::getSchedulingPolicy(gui::SchedulingPolicy* outPolicy) {
258*38e8c45fSAndroid Build Coastguard Worker return gui::getSchedulingPolicy(outPolicy);
259*38e8c45fSAndroid Build Coastguard Worker }
260*38e8c45fSAndroid Build Coastguard Worker
postEvent(const DisplayEventReceiver::Event & event)261*38e8c45fSAndroid Build Coastguard Worker status_t EventThreadConnection::postEvent(const DisplayEventReceiver::Event& event) {
262*38e8c45fSAndroid Build Coastguard Worker constexpr auto toStatus = [](ssize_t size) {
263*38e8c45fSAndroid Build Coastguard Worker return size < 0 ? status_t(size) : status_t(NO_ERROR);
264*38e8c45fSAndroid Build Coastguard Worker };
265*38e8c45fSAndroid Build Coastguard Worker
266*38e8c45fSAndroid Build Coastguard Worker if (event.header.type == DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE ||
267*38e8c45fSAndroid Build Coastguard Worker event.header.type == DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE_FLUSH) {
268*38e8c45fSAndroid Build Coastguard Worker mPendingEvents.emplace_back(event);
269*38e8c45fSAndroid Build Coastguard Worker if (event.header.type == DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE) {
270*38e8c45fSAndroid Build Coastguard Worker return status_t(NO_ERROR);
271*38e8c45fSAndroid Build Coastguard Worker }
272*38e8c45fSAndroid Build Coastguard Worker
273*38e8c45fSAndroid Build Coastguard Worker auto size = DisplayEventReceiver::sendEvents(&mChannel, mPendingEvents.data(),
274*38e8c45fSAndroid Build Coastguard Worker mPendingEvents.size());
275*38e8c45fSAndroid Build Coastguard Worker mPendingEvents.clear();
276*38e8c45fSAndroid Build Coastguard Worker return toStatus(size);
277*38e8c45fSAndroid Build Coastguard Worker }
278*38e8c45fSAndroid Build Coastguard Worker
279*38e8c45fSAndroid Build Coastguard Worker auto size = DisplayEventReceiver::sendEvents(&mChannel, &event, 1);
280*38e8c45fSAndroid Build Coastguard Worker return toStatus(size);
281*38e8c45fSAndroid Build Coastguard Worker }
282*38e8c45fSAndroid Build Coastguard Worker
283*38e8c45fSAndroid Build Coastguard Worker // ---------------------------------------------------------------------------
284*38e8c45fSAndroid Build Coastguard Worker
285*38e8c45fSAndroid Build Coastguard Worker EventThread::~EventThread() = default;
286*38e8c45fSAndroid Build Coastguard Worker
287*38e8c45fSAndroid Build Coastguard Worker namespace impl {
288*38e8c45fSAndroid Build Coastguard Worker
EventThread(const char * name,std::shared_ptr<scheduler::VsyncSchedule> vsyncSchedule,android::frametimeline::TokenManager * tokenManager,IEventThreadCallback & callback,std::chrono::nanoseconds workDuration,std::chrono::nanoseconds readyDuration)289*38e8c45fSAndroid Build Coastguard Worker EventThread::EventThread(const char* name, std::shared_ptr<scheduler::VsyncSchedule> vsyncSchedule,
290*38e8c45fSAndroid Build Coastguard Worker android::frametimeline::TokenManager* tokenManager,
291*38e8c45fSAndroid Build Coastguard Worker IEventThreadCallback& callback, std::chrono::nanoseconds workDuration,
292*38e8c45fSAndroid Build Coastguard Worker std::chrono::nanoseconds readyDuration)
293*38e8c45fSAndroid Build Coastguard Worker : mThreadName(name),
294*38e8c45fSAndroid Build Coastguard Worker mVsyncTracer(base::StringPrintf("VSYNC-%s", name), 0),
295*38e8c45fSAndroid Build Coastguard Worker mWorkDuration(base::StringPrintf("VsyncWorkDuration-%s", name), workDuration),
296*38e8c45fSAndroid Build Coastguard Worker mReadyDuration(readyDuration),
297*38e8c45fSAndroid Build Coastguard Worker mVsyncSchedule(std::move(vsyncSchedule)),
298*38e8c45fSAndroid Build Coastguard Worker mVsyncRegistration(mVsyncSchedule->getDispatch(), createDispatchCallback(), name),
299*38e8c45fSAndroid Build Coastguard Worker mTokenManager(tokenManager),
300*38e8c45fSAndroid Build Coastguard Worker mCallback(callback) {
301*38e8c45fSAndroid Build Coastguard Worker mThread = std::thread([this]() NO_THREAD_SAFETY_ANALYSIS {
302*38e8c45fSAndroid Build Coastguard Worker std::unique_lock<std::mutex> lock(mMutex);
303*38e8c45fSAndroid Build Coastguard Worker threadMain(lock);
304*38e8c45fSAndroid Build Coastguard Worker });
305*38e8c45fSAndroid Build Coastguard Worker
306*38e8c45fSAndroid Build Coastguard Worker pthread_setname_np(mThread.native_handle(), mThreadName);
307*38e8c45fSAndroid Build Coastguard Worker
308*38e8c45fSAndroid Build Coastguard Worker pid_t tid = pthread_gettid_np(mThread.native_handle());
309*38e8c45fSAndroid Build Coastguard Worker
310*38e8c45fSAndroid Build Coastguard Worker // Use SCHED_FIFO to minimize jitter
311*38e8c45fSAndroid Build Coastguard Worker constexpr int EVENT_THREAD_PRIORITY = 2;
312*38e8c45fSAndroid Build Coastguard Worker struct sched_param param = {0};
313*38e8c45fSAndroid Build Coastguard Worker param.sched_priority = EVENT_THREAD_PRIORITY;
314*38e8c45fSAndroid Build Coastguard Worker if (pthread_setschedparam(mThread.native_handle(), SCHED_FIFO, ¶m) != 0) {
315*38e8c45fSAndroid Build Coastguard Worker ALOGE("Couldn't set SCHED_FIFO for EventThread");
316*38e8c45fSAndroid Build Coastguard Worker }
317*38e8c45fSAndroid Build Coastguard Worker
318*38e8c45fSAndroid Build Coastguard Worker set_sched_policy(tid, SP_FOREGROUND);
319*38e8c45fSAndroid Build Coastguard Worker }
320*38e8c45fSAndroid Build Coastguard Worker
~EventThread()321*38e8c45fSAndroid Build Coastguard Worker EventThread::~EventThread() {
322*38e8c45fSAndroid Build Coastguard Worker {
323*38e8c45fSAndroid Build Coastguard Worker std::lock_guard<std::mutex> lock(mMutex);
324*38e8c45fSAndroid Build Coastguard Worker mState = State::Quit;
325*38e8c45fSAndroid Build Coastguard Worker mCondition.notify_all();
326*38e8c45fSAndroid Build Coastguard Worker }
327*38e8c45fSAndroid Build Coastguard Worker mThread.join();
328*38e8c45fSAndroid Build Coastguard Worker }
329*38e8c45fSAndroid Build Coastguard Worker
setDuration(std::chrono::nanoseconds workDuration,std::chrono::nanoseconds readyDuration)330*38e8c45fSAndroid Build Coastguard Worker void EventThread::setDuration(std::chrono::nanoseconds workDuration,
331*38e8c45fSAndroid Build Coastguard Worker std::chrono::nanoseconds readyDuration) {
332*38e8c45fSAndroid Build Coastguard Worker std::lock_guard<std::mutex> lock(mMutex);
333*38e8c45fSAndroid Build Coastguard Worker mWorkDuration = workDuration;
334*38e8c45fSAndroid Build Coastguard Worker mReadyDuration = readyDuration;
335*38e8c45fSAndroid Build Coastguard Worker
336*38e8c45fSAndroid Build Coastguard Worker mVsyncRegistration.update({.workDuration = mWorkDuration.get().count(),
337*38e8c45fSAndroid Build Coastguard Worker .readyDuration = mReadyDuration.count(),
338*38e8c45fSAndroid Build Coastguard Worker .lastVsync = mLastVsyncCallbackTime.ns(),
339*38e8c45fSAndroid Build Coastguard Worker .committedVsyncOpt = mLastCommittedVsyncTime.ns()});
340*38e8c45fSAndroid Build Coastguard Worker }
341*38e8c45fSAndroid Build Coastguard Worker
createEventConnection(EventRegistrationFlags eventRegistration) const342*38e8c45fSAndroid Build Coastguard Worker sp<EventThreadConnection> EventThread::createEventConnection(
343*38e8c45fSAndroid Build Coastguard Worker EventRegistrationFlags eventRegistration) const {
344*38e8c45fSAndroid Build Coastguard Worker auto connection = sp<EventThreadConnection>::make(const_cast<EventThread*>(this),
345*38e8c45fSAndroid Build Coastguard Worker IPCThreadState::self()->getCallingUid(),
346*38e8c45fSAndroid Build Coastguard Worker eventRegistration);
347*38e8c45fSAndroid Build Coastguard Worker if (FlagManager::getInstance().misc1()) {
348*38e8c45fSAndroid Build Coastguard Worker const int policy = SCHED_FIFO;
349*38e8c45fSAndroid Build Coastguard Worker connection->setMinSchedulerPolicy(policy, sched_get_priority_min(policy));
350*38e8c45fSAndroid Build Coastguard Worker }
351*38e8c45fSAndroid Build Coastguard Worker return connection;
352*38e8c45fSAndroid Build Coastguard Worker }
353*38e8c45fSAndroid Build Coastguard Worker
registerDisplayEventConnection(const sp<EventThreadConnection> & connection)354*38e8c45fSAndroid Build Coastguard Worker status_t EventThread::registerDisplayEventConnection(const sp<EventThreadConnection>& connection) {
355*38e8c45fSAndroid Build Coastguard Worker std::lock_guard<std::mutex> lock(mMutex);
356*38e8c45fSAndroid Build Coastguard Worker
357*38e8c45fSAndroid Build Coastguard Worker // this should never happen
358*38e8c45fSAndroid Build Coastguard Worker auto it = std::find(mDisplayEventConnections.cbegin(),
359*38e8c45fSAndroid Build Coastguard Worker mDisplayEventConnections.cend(), connection);
360*38e8c45fSAndroid Build Coastguard Worker if (it != mDisplayEventConnections.cend()) {
361*38e8c45fSAndroid Build Coastguard Worker ALOGW("DisplayEventConnection %p already exists", connection.get());
362*38e8c45fSAndroid Build Coastguard Worker mCondition.notify_all();
363*38e8c45fSAndroid Build Coastguard Worker return ALREADY_EXISTS;
364*38e8c45fSAndroid Build Coastguard Worker }
365*38e8c45fSAndroid Build Coastguard Worker
366*38e8c45fSAndroid Build Coastguard Worker mDisplayEventConnections.push_back(connection);
367*38e8c45fSAndroid Build Coastguard Worker mCondition.notify_all();
368*38e8c45fSAndroid Build Coastguard Worker return NO_ERROR;
369*38e8c45fSAndroid Build Coastguard Worker }
370*38e8c45fSAndroid Build Coastguard Worker
removeDisplayEventConnectionLocked(const wp<EventThreadConnection> & connection)371*38e8c45fSAndroid Build Coastguard Worker void EventThread::removeDisplayEventConnectionLocked(const wp<EventThreadConnection>& connection) {
372*38e8c45fSAndroid Build Coastguard Worker auto it = std::find(mDisplayEventConnections.cbegin(),
373*38e8c45fSAndroid Build Coastguard Worker mDisplayEventConnections.cend(), connection);
374*38e8c45fSAndroid Build Coastguard Worker if (it != mDisplayEventConnections.cend()) {
375*38e8c45fSAndroid Build Coastguard Worker mDisplayEventConnections.erase(it);
376*38e8c45fSAndroid Build Coastguard Worker }
377*38e8c45fSAndroid Build Coastguard Worker }
378*38e8c45fSAndroid Build Coastguard Worker
setVsyncRate(uint32_t rate,const sp<EventThreadConnection> & connection)379*38e8c45fSAndroid Build Coastguard Worker void EventThread::setVsyncRate(uint32_t rate, const sp<EventThreadConnection>& connection) {
380*38e8c45fSAndroid Build Coastguard Worker if (static_cast<std::underlying_type_t<VSyncRequest>>(rate) < 0) {
381*38e8c45fSAndroid Build Coastguard Worker return;
382*38e8c45fSAndroid Build Coastguard Worker }
383*38e8c45fSAndroid Build Coastguard Worker
384*38e8c45fSAndroid Build Coastguard Worker std::lock_guard<std::mutex> lock(mMutex);
385*38e8c45fSAndroid Build Coastguard Worker
386*38e8c45fSAndroid Build Coastguard Worker const auto request = rate == 0 ? VSyncRequest::None : static_cast<VSyncRequest>(rate);
387*38e8c45fSAndroid Build Coastguard Worker if (connection->vsyncRequest != request) {
388*38e8c45fSAndroid Build Coastguard Worker connection->vsyncRequest = request;
389*38e8c45fSAndroid Build Coastguard Worker mCondition.notify_all();
390*38e8c45fSAndroid Build Coastguard Worker }
391*38e8c45fSAndroid Build Coastguard Worker }
392*38e8c45fSAndroid Build Coastguard Worker
requestNextVsync(const sp<EventThreadConnection> & connection)393*38e8c45fSAndroid Build Coastguard Worker void EventThread::requestNextVsync(const sp<EventThreadConnection>& connection) {
394*38e8c45fSAndroid Build Coastguard Worker mCallback.resync();
395*38e8c45fSAndroid Build Coastguard Worker
396*38e8c45fSAndroid Build Coastguard Worker std::lock_guard<std::mutex> lock(mMutex);
397*38e8c45fSAndroid Build Coastguard Worker
398*38e8c45fSAndroid Build Coastguard Worker if (connection->vsyncRequest == VSyncRequest::None) {
399*38e8c45fSAndroid Build Coastguard Worker connection->vsyncRequest = VSyncRequest::Single;
400*38e8c45fSAndroid Build Coastguard Worker mCondition.notify_all();
401*38e8c45fSAndroid Build Coastguard Worker } else if (connection->vsyncRequest == VSyncRequest::SingleSuppressCallback) {
402*38e8c45fSAndroid Build Coastguard Worker connection->vsyncRequest = VSyncRequest::Single;
403*38e8c45fSAndroid Build Coastguard Worker }
404*38e8c45fSAndroid Build Coastguard Worker }
405*38e8c45fSAndroid Build Coastguard Worker
getLatestVsyncEventData(const sp<EventThreadConnection> & connection,nsecs_t now) const406*38e8c45fSAndroid Build Coastguard Worker VsyncEventData EventThread::getLatestVsyncEventData(const sp<EventThreadConnection>& connection,
407*38e8c45fSAndroid Build Coastguard Worker nsecs_t now) const {
408*38e8c45fSAndroid Build Coastguard Worker // Resync so that the vsync is accurate with hardware. getLatestVsyncEventData is an alternate
409*38e8c45fSAndroid Build Coastguard Worker // way to get vsync data (instead of posting callbacks to Choreographer).
410*38e8c45fSAndroid Build Coastguard Worker mCallback.resync();
411*38e8c45fSAndroid Build Coastguard Worker
412*38e8c45fSAndroid Build Coastguard Worker VsyncEventData vsyncEventData;
413*38e8c45fSAndroid Build Coastguard Worker const Period frameInterval = mCallback.getVsyncPeriod(connection->mOwnerUid);
414*38e8c45fSAndroid Build Coastguard Worker vsyncEventData.frameInterval = frameInterval.ns();
415*38e8c45fSAndroid Build Coastguard Worker const auto [presentTime, deadline] = [&]() -> std::pair<nsecs_t, nsecs_t> {
416*38e8c45fSAndroid Build Coastguard Worker std::lock_guard<std::mutex> lock(mMutex);
417*38e8c45fSAndroid Build Coastguard Worker const auto vsyncTime = mVsyncSchedule->getTracker().nextAnticipatedVSyncTimeFrom(
418*38e8c45fSAndroid Build Coastguard Worker now + mWorkDuration.get().count() + mReadyDuration.count());
419*38e8c45fSAndroid Build Coastguard Worker return {vsyncTime, vsyncTime - mReadyDuration.count()};
420*38e8c45fSAndroid Build Coastguard Worker }();
421*38e8c45fSAndroid Build Coastguard Worker generateFrameTimeline(vsyncEventData, frameInterval.ns(), now, presentTime, deadline);
422*38e8c45fSAndroid Build Coastguard Worker if (FlagManager::getInstance().vrr_config()) {
423*38e8c45fSAndroid Build Coastguard Worker mCallback.onExpectedPresentTimePosted(TimePoint::fromNs(presentTime));
424*38e8c45fSAndroid Build Coastguard Worker }
425*38e8c45fSAndroid Build Coastguard Worker return vsyncEventData;
426*38e8c45fSAndroid Build Coastguard Worker }
427*38e8c45fSAndroid Build Coastguard Worker
enableSyntheticVsync(bool enable)428*38e8c45fSAndroid Build Coastguard Worker void EventThread::enableSyntheticVsync(bool enable) {
429*38e8c45fSAndroid Build Coastguard Worker std::lock_guard<std::mutex> lock(mMutex);
430*38e8c45fSAndroid Build Coastguard Worker if (!mVSyncState || mVSyncState->synthetic == enable) {
431*38e8c45fSAndroid Build Coastguard Worker return;
432*38e8c45fSAndroid Build Coastguard Worker }
433*38e8c45fSAndroid Build Coastguard Worker
434*38e8c45fSAndroid Build Coastguard Worker mVSyncState->synthetic = enable;
435*38e8c45fSAndroid Build Coastguard Worker mCondition.notify_all();
436*38e8c45fSAndroid Build Coastguard Worker }
437*38e8c45fSAndroid Build Coastguard Worker
omitVsyncDispatching(bool omitted)438*38e8c45fSAndroid Build Coastguard Worker void EventThread::omitVsyncDispatching(bool omitted) {
439*38e8c45fSAndroid Build Coastguard Worker std::lock_guard<std::mutex> lock(mMutex);
440*38e8c45fSAndroid Build Coastguard Worker if (!mVSyncState || mVSyncState->omitted == omitted) {
441*38e8c45fSAndroid Build Coastguard Worker return;
442*38e8c45fSAndroid Build Coastguard Worker }
443*38e8c45fSAndroid Build Coastguard Worker
444*38e8c45fSAndroid Build Coastguard Worker mVSyncState->omitted = omitted;
445*38e8c45fSAndroid Build Coastguard Worker mCondition.notify_all();
446*38e8c45fSAndroid Build Coastguard Worker }
447*38e8c45fSAndroid Build Coastguard Worker
onVsync(nsecs_t vsyncTime,nsecs_t wakeupTime,nsecs_t readyTime)448*38e8c45fSAndroid Build Coastguard Worker void EventThread::onVsync(nsecs_t vsyncTime, nsecs_t wakeupTime, nsecs_t readyTime) {
449*38e8c45fSAndroid Build Coastguard Worker std::lock_guard<std::mutex> lock(mMutex);
450*38e8c45fSAndroid Build Coastguard Worker mLastVsyncCallbackTime = TimePoint::fromNs(vsyncTime);
451*38e8c45fSAndroid Build Coastguard Worker
452*38e8c45fSAndroid Build Coastguard Worker LOG_FATAL_IF(!mVSyncState);
453*38e8c45fSAndroid Build Coastguard Worker mVsyncTracer = (mVsyncTracer + 1) % 2;
454*38e8c45fSAndroid Build Coastguard Worker mPendingEvents.push_back(makeVSync(mVsyncSchedule->getPhysicalDisplayId(), wakeupTime,
455*38e8c45fSAndroid Build Coastguard Worker ++mVSyncState->count, vsyncTime, readyTime));
456*38e8c45fSAndroid Build Coastguard Worker mCondition.notify_all();
457*38e8c45fSAndroid Build Coastguard Worker }
458*38e8c45fSAndroid Build Coastguard Worker
onHotplugReceived(PhysicalDisplayId displayId,bool connected)459*38e8c45fSAndroid Build Coastguard Worker void EventThread::onHotplugReceived(PhysicalDisplayId displayId, bool connected) {
460*38e8c45fSAndroid Build Coastguard Worker std::lock_guard<std::mutex> lock(mMutex);
461*38e8c45fSAndroid Build Coastguard Worker
462*38e8c45fSAndroid Build Coastguard Worker mPendingEvents.push_back(makeHotplug(displayId, systemTime(), connected));
463*38e8c45fSAndroid Build Coastguard Worker mCondition.notify_all();
464*38e8c45fSAndroid Build Coastguard Worker }
465*38e8c45fSAndroid Build Coastguard Worker
onHotplugConnectionError(int32_t errorCode)466*38e8c45fSAndroid Build Coastguard Worker void EventThread::onHotplugConnectionError(int32_t errorCode) {
467*38e8c45fSAndroid Build Coastguard Worker std::lock_guard<std::mutex> lock(mMutex);
468*38e8c45fSAndroid Build Coastguard Worker
469*38e8c45fSAndroid Build Coastguard Worker mPendingEvents.push_back(makeHotplugError(systemTime(), errorCode));
470*38e8c45fSAndroid Build Coastguard Worker mCondition.notify_all();
471*38e8c45fSAndroid Build Coastguard Worker }
472*38e8c45fSAndroid Build Coastguard Worker
onModeChanged(const scheduler::FrameRateMode & mode)473*38e8c45fSAndroid Build Coastguard Worker void EventThread::onModeChanged(const scheduler::FrameRateMode& mode) {
474*38e8c45fSAndroid Build Coastguard Worker std::lock_guard<std::mutex> lock(mMutex);
475*38e8c45fSAndroid Build Coastguard Worker
476*38e8c45fSAndroid Build Coastguard Worker mPendingEvents.push_back(makeModeChanged(mode));
477*38e8c45fSAndroid Build Coastguard Worker mCondition.notify_all();
478*38e8c45fSAndroid Build Coastguard Worker }
479*38e8c45fSAndroid Build Coastguard Worker
onFrameRateOverridesChanged(PhysicalDisplayId displayId,std::vector<FrameRateOverride> overrides)480*38e8c45fSAndroid Build Coastguard Worker void EventThread::onFrameRateOverridesChanged(PhysicalDisplayId displayId,
481*38e8c45fSAndroid Build Coastguard Worker std::vector<FrameRateOverride> overrides) {
482*38e8c45fSAndroid Build Coastguard Worker std::lock_guard<std::mutex> lock(mMutex);
483*38e8c45fSAndroid Build Coastguard Worker
484*38e8c45fSAndroid Build Coastguard Worker for (auto frameRateOverride : overrides) {
485*38e8c45fSAndroid Build Coastguard Worker mPendingEvents.push_back(makeFrameRateOverrideEvent(displayId, frameRateOverride));
486*38e8c45fSAndroid Build Coastguard Worker }
487*38e8c45fSAndroid Build Coastguard Worker mPendingEvents.push_back(makeFrameRateOverrideFlushEvent(displayId));
488*38e8c45fSAndroid Build Coastguard Worker
489*38e8c45fSAndroid Build Coastguard Worker mCondition.notify_all();
490*38e8c45fSAndroid Build Coastguard Worker }
491*38e8c45fSAndroid Build Coastguard Worker
onHdcpLevelsChanged(PhysicalDisplayId displayId,int32_t connectedLevel,int32_t maxLevel)492*38e8c45fSAndroid Build Coastguard Worker void EventThread::onHdcpLevelsChanged(PhysicalDisplayId displayId, int32_t connectedLevel,
493*38e8c45fSAndroid Build Coastguard Worker int32_t maxLevel) {
494*38e8c45fSAndroid Build Coastguard Worker std::lock_guard<std::mutex> lock(mMutex);
495*38e8c45fSAndroid Build Coastguard Worker
496*38e8c45fSAndroid Build Coastguard Worker mPendingEvents.push_back(makeHdcpLevelsChange(displayId, connectedLevel, maxLevel));
497*38e8c45fSAndroid Build Coastguard Worker mCondition.notify_all();
498*38e8c45fSAndroid Build Coastguard Worker }
499*38e8c45fSAndroid Build Coastguard Worker
onModeRejected(PhysicalDisplayId displayId,DisplayModeId modeId)500*38e8c45fSAndroid Build Coastguard Worker void EventThread::onModeRejected(PhysicalDisplayId displayId, DisplayModeId modeId) {
501*38e8c45fSAndroid Build Coastguard Worker std::lock_guard<std::mutex> lock(mMutex);
502*38e8c45fSAndroid Build Coastguard Worker
503*38e8c45fSAndroid Build Coastguard Worker mPendingEvents.push_back(makeModeRejection(displayId, modeId));
504*38e8c45fSAndroid Build Coastguard Worker mCondition.notify_all();
505*38e8c45fSAndroid Build Coastguard Worker }
506*38e8c45fSAndroid Build Coastguard Worker
507*38e8c45fSAndroid Build Coastguard Worker // Merge lists of buffer stuffed Uids
addBufferStuffedUids(BufferStuffingMap bufferStuffedUids)508*38e8c45fSAndroid Build Coastguard Worker void EventThread::addBufferStuffedUids(BufferStuffingMap bufferStuffedUids) {
509*38e8c45fSAndroid Build Coastguard Worker std::lock_guard<std::mutex> lock(mMutex);
510*38e8c45fSAndroid Build Coastguard Worker for (auto& [uid, count] : bufferStuffedUids) {
511*38e8c45fSAndroid Build Coastguard Worker mBufferStuffedUids.emplace_or_replace(uid, count);
512*38e8c45fSAndroid Build Coastguard Worker }
513*38e8c45fSAndroid Build Coastguard Worker }
514*38e8c45fSAndroid Build Coastguard Worker
threadMain(std::unique_lock<std::mutex> & lock)515*38e8c45fSAndroid Build Coastguard Worker void EventThread::threadMain(std::unique_lock<std::mutex>& lock) {
516*38e8c45fSAndroid Build Coastguard Worker DisplayEventConsumers consumers;
517*38e8c45fSAndroid Build Coastguard Worker
518*38e8c45fSAndroid Build Coastguard Worker while (mState != State::Quit) {
519*38e8c45fSAndroid Build Coastguard Worker std::optional<DisplayEventReceiver::Event> event;
520*38e8c45fSAndroid Build Coastguard Worker
521*38e8c45fSAndroid Build Coastguard Worker // Determine next event to dispatch.
522*38e8c45fSAndroid Build Coastguard Worker if (!mPendingEvents.empty()) {
523*38e8c45fSAndroid Build Coastguard Worker event = mPendingEvents.front();
524*38e8c45fSAndroid Build Coastguard Worker mPendingEvents.pop_front();
525*38e8c45fSAndroid Build Coastguard Worker
526*38e8c45fSAndroid Build Coastguard Worker if (event->header.type == DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG) {
527*38e8c45fSAndroid Build Coastguard Worker if (event->hotplug.connectionError == 0) {
528*38e8c45fSAndroid Build Coastguard Worker if (event->hotplug.connected && !mVSyncState) {
529*38e8c45fSAndroid Build Coastguard Worker mVSyncState.emplace();
530*38e8c45fSAndroid Build Coastguard Worker } else if (!event->hotplug.connected &&
531*38e8c45fSAndroid Build Coastguard Worker mVsyncSchedule->getPhysicalDisplayId() == event->header.displayId) {
532*38e8c45fSAndroid Build Coastguard Worker mVSyncState.reset();
533*38e8c45fSAndroid Build Coastguard Worker }
534*38e8c45fSAndroid Build Coastguard Worker } else {
535*38e8c45fSAndroid Build Coastguard Worker // Ignore vsync stuff on an error.
536*38e8c45fSAndroid Build Coastguard Worker }
537*38e8c45fSAndroid Build Coastguard Worker }
538*38e8c45fSAndroid Build Coastguard Worker }
539*38e8c45fSAndroid Build Coastguard Worker
540*38e8c45fSAndroid Build Coastguard Worker bool vsyncRequested = false;
541*38e8c45fSAndroid Build Coastguard Worker
542*38e8c45fSAndroid Build Coastguard Worker // Find connections that should consume this event.
543*38e8c45fSAndroid Build Coastguard Worker auto it = mDisplayEventConnections.begin();
544*38e8c45fSAndroid Build Coastguard Worker while (it != mDisplayEventConnections.end()) {
545*38e8c45fSAndroid Build Coastguard Worker if (const auto connection = it->promote()) {
546*38e8c45fSAndroid Build Coastguard Worker if (event && shouldConsumeEvent(*event, connection)) {
547*38e8c45fSAndroid Build Coastguard Worker consumers.push_back(connection);
548*38e8c45fSAndroid Build Coastguard Worker }
549*38e8c45fSAndroid Build Coastguard Worker
550*38e8c45fSAndroid Build Coastguard Worker vsyncRequested |= connection->vsyncRequest != VSyncRequest::None;
551*38e8c45fSAndroid Build Coastguard Worker
552*38e8c45fSAndroid Build Coastguard Worker ++it;
553*38e8c45fSAndroid Build Coastguard Worker } else {
554*38e8c45fSAndroid Build Coastguard Worker it = mDisplayEventConnections.erase(it);
555*38e8c45fSAndroid Build Coastguard Worker }
556*38e8c45fSAndroid Build Coastguard Worker }
557*38e8c45fSAndroid Build Coastguard Worker
558*38e8c45fSAndroid Build Coastguard Worker if (!consumers.empty()) {
559*38e8c45fSAndroid Build Coastguard Worker dispatchEvent(*event, consumers);
560*38e8c45fSAndroid Build Coastguard Worker consumers.clear();
561*38e8c45fSAndroid Build Coastguard Worker }
562*38e8c45fSAndroid Build Coastguard Worker
563*38e8c45fSAndroid Build Coastguard Worker if (mVSyncState && vsyncRequested) {
564*38e8c45fSAndroid Build Coastguard Worker const bool vsyncOmitted =
565*38e8c45fSAndroid Build Coastguard Worker FlagManager::getInstance().no_vsyncs_on_screen_off() && mVSyncState->omitted;
566*38e8c45fSAndroid Build Coastguard Worker if (vsyncOmitted) {
567*38e8c45fSAndroid Build Coastguard Worker mState = State::Idle;
568*38e8c45fSAndroid Build Coastguard Worker SFTRACE_INT("VsyncPendingScreenOn", 1);
569*38e8c45fSAndroid Build Coastguard Worker } else {
570*38e8c45fSAndroid Build Coastguard Worker mState = mVSyncState->synthetic ? State::SyntheticVSync : State::VSync;
571*38e8c45fSAndroid Build Coastguard Worker if (FlagManager::getInstance().no_vsyncs_on_screen_off()) {
572*38e8c45fSAndroid Build Coastguard Worker SFTRACE_INT("VsyncPendingScreenOn", 0);
573*38e8c45fSAndroid Build Coastguard Worker }
574*38e8c45fSAndroid Build Coastguard Worker }
575*38e8c45fSAndroid Build Coastguard Worker } else {
576*38e8c45fSAndroid Build Coastguard Worker ALOGW_IF(!mVSyncState, "Ignoring VSYNC request while display is disconnected");
577*38e8c45fSAndroid Build Coastguard Worker mState = State::Idle;
578*38e8c45fSAndroid Build Coastguard Worker }
579*38e8c45fSAndroid Build Coastguard Worker
580*38e8c45fSAndroid Build Coastguard Worker if (mState == State::VSync) {
581*38e8c45fSAndroid Build Coastguard Worker const auto scheduleResult = mVsyncRegistration.schedule(
582*38e8c45fSAndroid Build Coastguard Worker {.workDuration = mWorkDuration.get().count(),
583*38e8c45fSAndroid Build Coastguard Worker .readyDuration = mReadyDuration.count(),
584*38e8c45fSAndroid Build Coastguard Worker .lastVsync = mLastVsyncCallbackTime.ns(),
585*38e8c45fSAndroid Build Coastguard Worker .committedVsyncOpt = mLastCommittedVsyncTime.ns()});
586*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(!scheduleResult, "Error scheduling callback");
587*38e8c45fSAndroid Build Coastguard Worker } else {
588*38e8c45fSAndroid Build Coastguard Worker mVsyncRegistration.cancel();
589*38e8c45fSAndroid Build Coastguard Worker }
590*38e8c45fSAndroid Build Coastguard Worker
591*38e8c45fSAndroid Build Coastguard Worker if (!mPendingEvents.empty()) {
592*38e8c45fSAndroid Build Coastguard Worker continue;
593*38e8c45fSAndroid Build Coastguard Worker }
594*38e8c45fSAndroid Build Coastguard Worker
595*38e8c45fSAndroid Build Coastguard Worker // Wait for event or client registration/request.
596*38e8c45fSAndroid Build Coastguard Worker if (mState == State::Idle) {
597*38e8c45fSAndroid Build Coastguard Worker mCondition.wait(lock);
598*38e8c45fSAndroid Build Coastguard Worker } else {
599*38e8c45fSAndroid Build Coastguard Worker // Generate a fake VSYNC after a long timeout in case the driver stalls. When the
600*38e8c45fSAndroid Build Coastguard Worker // display is off, keep feeding clients at 60 Hz.
601*38e8c45fSAndroid Build Coastguard Worker const std::chrono::nanoseconds timeout =
602*38e8c45fSAndroid Build Coastguard Worker mState == State::SyntheticVSync ? 16ms : 1000ms;
603*38e8c45fSAndroid Build Coastguard Worker if (mCondition.wait_for(lock, timeout) == std::cv_status::timeout) {
604*38e8c45fSAndroid Build Coastguard Worker if (mState == State::VSync) {
605*38e8c45fSAndroid Build Coastguard Worker ALOGW("Faking VSYNC due to driver stall for thread %s", mThreadName);
606*38e8c45fSAndroid Build Coastguard Worker }
607*38e8c45fSAndroid Build Coastguard Worker
608*38e8c45fSAndroid Build Coastguard Worker LOG_FATAL_IF(!mVSyncState);
609*38e8c45fSAndroid Build Coastguard Worker const auto now = systemTime(SYSTEM_TIME_MONOTONIC);
610*38e8c45fSAndroid Build Coastguard Worker const auto deadlineTimestamp = now + timeout.count();
611*38e8c45fSAndroid Build Coastguard Worker const auto expectedVSyncTime = deadlineTimestamp + timeout.count();
612*38e8c45fSAndroid Build Coastguard Worker mPendingEvents.push_back(makeVSync(mVsyncSchedule->getPhysicalDisplayId(), now,
613*38e8c45fSAndroid Build Coastguard Worker ++mVSyncState->count, expectedVSyncTime,
614*38e8c45fSAndroid Build Coastguard Worker deadlineTimestamp));
615*38e8c45fSAndroid Build Coastguard Worker }
616*38e8c45fSAndroid Build Coastguard Worker }
617*38e8c45fSAndroid Build Coastguard Worker }
618*38e8c45fSAndroid Build Coastguard Worker // cancel any pending vsync event before exiting
619*38e8c45fSAndroid Build Coastguard Worker mVsyncRegistration.cancel();
620*38e8c45fSAndroid Build Coastguard Worker }
621*38e8c45fSAndroid Build Coastguard Worker
shouldConsumeEvent(const DisplayEventReceiver::Event & event,const sp<EventThreadConnection> & connection) const622*38e8c45fSAndroid Build Coastguard Worker bool EventThread::shouldConsumeEvent(const DisplayEventReceiver::Event& event,
623*38e8c45fSAndroid Build Coastguard Worker const sp<EventThreadConnection>& connection) const {
624*38e8c45fSAndroid Build Coastguard Worker const auto throttleVsync = [&]() REQUIRES(mMutex) {
625*38e8c45fSAndroid Build Coastguard Worker const auto& vsyncData = event.vsync.vsyncData;
626*38e8c45fSAndroid Build Coastguard Worker if (connection->frameRate.isValid()) {
627*38e8c45fSAndroid Build Coastguard Worker return !mVsyncSchedule->getTracker()
628*38e8c45fSAndroid Build Coastguard Worker .isVSyncInPhase(vsyncData.preferredExpectedPresentationTime(),
629*38e8c45fSAndroid Build Coastguard Worker connection->frameRate);
630*38e8c45fSAndroid Build Coastguard Worker }
631*38e8c45fSAndroid Build Coastguard Worker
632*38e8c45fSAndroid Build Coastguard Worker const auto expectedPresentTime =
633*38e8c45fSAndroid Build Coastguard Worker TimePoint::fromNs(event.vsync.vsyncData.preferredExpectedPresentationTime());
634*38e8c45fSAndroid Build Coastguard Worker return mCallback.throttleVsync(expectedPresentTime, connection->mOwnerUid);
635*38e8c45fSAndroid Build Coastguard Worker };
636*38e8c45fSAndroid Build Coastguard Worker
637*38e8c45fSAndroid Build Coastguard Worker switch (event.header.type) {
638*38e8c45fSAndroid Build Coastguard Worker case DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG:
639*38e8c45fSAndroid Build Coastguard Worker return true;
640*38e8c45fSAndroid Build Coastguard Worker
641*38e8c45fSAndroid Build Coastguard Worker case DisplayEventReceiver::DISPLAY_EVENT_HDCP_LEVELS_CHANGE:
642*38e8c45fSAndroid Build Coastguard Worker return true;
643*38e8c45fSAndroid Build Coastguard Worker
644*38e8c45fSAndroid Build Coastguard Worker case DisplayEventReceiver::DISPLAY_EVENT_MODE_CHANGE: {
645*38e8c45fSAndroid Build Coastguard Worker return connection->mEventRegistration.test(
646*38e8c45fSAndroid Build Coastguard Worker gui::ISurfaceComposer::EventRegistration::modeChanged);
647*38e8c45fSAndroid Build Coastguard Worker }
648*38e8c45fSAndroid Build Coastguard Worker
649*38e8c45fSAndroid Build Coastguard Worker case DisplayEventReceiver::DISPLAY_EVENT_VSYNC:
650*38e8c45fSAndroid Build Coastguard Worker switch (connection->vsyncRequest) {
651*38e8c45fSAndroid Build Coastguard Worker case VSyncRequest::None:
652*38e8c45fSAndroid Build Coastguard Worker return false;
653*38e8c45fSAndroid Build Coastguard Worker case VSyncRequest::SingleSuppressCallback:
654*38e8c45fSAndroid Build Coastguard Worker connection->vsyncRequest = VSyncRequest::None;
655*38e8c45fSAndroid Build Coastguard Worker return false;
656*38e8c45fSAndroid Build Coastguard Worker case VSyncRequest::Single: {
657*38e8c45fSAndroid Build Coastguard Worker if (throttleVsync()) {
658*38e8c45fSAndroid Build Coastguard Worker return false;
659*38e8c45fSAndroid Build Coastguard Worker }
660*38e8c45fSAndroid Build Coastguard Worker connection->vsyncRequest = VSyncRequest::SingleSuppressCallback;
661*38e8c45fSAndroid Build Coastguard Worker return true;
662*38e8c45fSAndroid Build Coastguard Worker }
663*38e8c45fSAndroid Build Coastguard Worker case VSyncRequest::Periodic:
664*38e8c45fSAndroid Build Coastguard Worker if (throttleVsync()) {
665*38e8c45fSAndroid Build Coastguard Worker return false;
666*38e8c45fSAndroid Build Coastguard Worker }
667*38e8c45fSAndroid Build Coastguard Worker return true;
668*38e8c45fSAndroid Build Coastguard Worker default:
669*38e8c45fSAndroid Build Coastguard Worker // We don't throttle vsync if the app set a vsync request rate
670*38e8c45fSAndroid Build Coastguard Worker // since there is no easy way to do that and this is a very
671*38e8c45fSAndroid Build Coastguard Worker // rare case
672*38e8c45fSAndroid Build Coastguard Worker return event.vsync.count % vsyncPeriod(connection->vsyncRequest) == 0;
673*38e8c45fSAndroid Build Coastguard Worker }
674*38e8c45fSAndroid Build Coastguard Worker
675*38e8c45fSAndroid Build Coastguard Worker case DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE:
676*38e8c45fSAndroid Build Coastguard Worker [[fallthrough]];
677*38e8c45fSAndroid Build Coastguard Worker case DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE_FLUSH:
678*38e8c45fSAndroid Build Coastguard Worker return connection->mEventRegistration.test(
679*38e8c45fSAndroid Build Coastguard Worker gui::ISurfaceComposer::EventRegistration::frameRateOverride);
680*38e8c45fSAndroid Build Coastguard Worker
681*38e8c45fSAndroid Build Coastguard Worker default:
682*38e8c45fSAndroid Build Coastguard Worker return false;
683*38e8c45fSAndroid Build Coastguard Worker }
684*38e8c45fSAndroid Build Coastguard Worker }
685*38e8c45fSAndroid Build Coastguard Worker
generateToken(nsecs_t timestamp,nsecs_t deadlineTimestamp,nsecs_t expectedPresentationTime) const686*38e8c45fSAndroid Build Coastguard Worker int64_t EventThread::generateToken(nsecs_t timestamp, nsecs_t deadlineTimestamp,
687*38e8c45fSAndroid Build Coastguard Worker nsecs_t expectedPresentationTime) const {
688*38e8c45fSAndroid Build Coastguard Worker if (mTokenManager != nullptr) {
689*38e8c45fSAndroid Build Coastguard Worker return mTokenManager->generateTokenForPredictions(
690*38e8c45fSAndroid Build Coastguard Worker {timestamp, deadlineTimestamp, expectedPresentationTime});
691*38e8c45fSAndroid Build Coastguard Worker }
692*38e8c45fSAndroid Build Coastguard Worker return FrameTimelineInfo::INVALID_VSYNC_ID;
693*38e8c45fSAndroid Build Coastguard Worker }
694*38e8c45fSAndroid Build Coastguard Worker
generateFrameTimeline(VsyncEventData & outVsyncEventData,nsecs_t frameInterval,nsecs_t timestamp,nsecs_t preferredExpectedPresentationTime,nsecs_t preferredDeadlineTimestamp) const695*38e8c45fSAndroid Build Coastguard Worker void EventThread::generateFrameTimeline(VsyncEventData& outVsyncEventData, nsecs_t frameInterval,
696*38e8c45fSAndroid Build Coastguard Worker nsecs_t timestamp,
697*38e8c45fSAndroid Build Coastguard Worker nsecs_t preferredExpectedPresentationTime,
698*38e8c45fSAndroid Build Coastguard Worker nsecs_t preferredDeadlineTimestamp) const {
699*38e8c45fSAndroid Build Coastguard Worker uint32_t currentIndex = 0;
700*38e8c45fSAndroid Build Coastguard Worker // Add 1 to ensure the preferredFrameTimelineIndex entry (when multiplier == 0) is included.
701*38e8c45fSAndroid Build Coastguard Worker for (int64_t multiplier = -VsyncEventData::kFrameTimelinesCapacity + 1;
702*38e8c45fSAndroid Build Coastguard Worker currentIndex < VsyncEventData::kFrameTimelinesCapacity; multiplier++) {
703*38e8c45fSAndroid Build Coastguard Worker nsecs_t deadlineTimestamp = preferredDeadlineTimestamp + multiplier * frameInterval;
704*38e8c45fSAndroid Build Coastguard Worker // Valid possible frame timelines must have future values, so find a later frame timeline.
705*38e8c45fSAndroid Build Coastguard Worker if (deadlineTimestamp <= timestamp) {
706*38e8c45fSAndroid Build Coastguard Worker continue;
707*38e8c45fSAndroid Build Coastguard Worker }
708*38e8c45fSAndroid Build Coastguard Worker
709*38e8c45fSAndroid Build Coastguard Worker nsecs_t expectedPresentationTime =
710*38e8c45fSAndroid Build Coastguard Worker preferredExpectedPresentationTime + multiplier * frameInterval;
711*38e8c45fSAndroid Build Coastguard Worker if (expectedPresentationTime >= preferredExpectedPresentationTime +
712*38e8c45fSAndroid Build Coastguard Worker scheduler::VsyncConfig::kEarlyLatchMaxThreshold.count()) {
713*38e8c45fSAndroid Build Coastguard Worker if (currentIndex == 0) {
714*38e8c45fSAndroid Build Coastguard Worker ALOGW("%s: Expected present time is too far in the future but no timelines are "
715*38e8c45fSAndroid Build Coastguard Worker "valid. preferred EPT=%" PRId64 ", Calculated EPT=%" PRId64
716*38e8c45fSAndroid Build Coastguard Worker ", multiplier=%" PRId64 ", frameInterval=%" PRId64 ", threshold=%" PRId64,
717*38e8c45fSAndroid Build Coastguard Worker __func__, preferredExpectedPresentationTime, expectedPresentationTime,
718*38e8c45fSAndroid Build Coastguard Worker multiplier, frameInterval,
719*38e8c45fSAndroid Build Coastguard Worker static_cast<int64_t>(
720*38e8c45fSAndroid Build Coastguard Worker scheduler::VsyncConfig::kEarlyLatchMaxThreshold.count()));
721*38e8c45fSAndroid Build Coastguard Worker }
722*38e8c45fSAndroid Build Coastguard Worker break;
723*38e8c45fSAndroid Build Coastguard Worker }
724*38e8c45fSAndroid Build Coastguard Worker
725*38e8c45fSAndroid Build Coastguard Worker if (multiplier == 0) {
726*38e8c45fSAndroid Build Coastguard Worker outVsyncEventData.preferredFrameTimelineIndex = currentIndex;
727*38e8c45fSAndroid Build Coastguard Worker }
728*38e8c45fSAndroid Build Coastguard Worker
729*38e8c45fSAndroid Build Coastguard Worker outVsyncEventData.frameTimelines[currentIndex] =
730*38e8c45fSAndroid Build Coastguard Worker {.vsyncId = generateToken(timestamp, deadlineTimestamp, expectedPresentationTime),
731*38e8c45fSAndroid Build Coastguard Worker .deadlineTimestamp = deadlineTimestamp,
732*38e8c45fSAndroid Build Coastguard Worker .expectedPresentationTime = expectedPresentationTime};
733*38e8c45fSAndroid Build Coastguard Worker currentIndex++;
734*38e8c45fSAndroid Build Coastguard Worker }
735*38e8c45fSAndroid Build Coastguard Worker
736*38e8c45fSAndroid Build Coastguard Worker if (currentIndex == 0) {
737*38e8c45fSAndroid Build Coastguard Worker ALOGW("%s: No timelines are valid. preferred EPT=%" PRId64 ", frameInterval=%" PRId64
738*38e8c45fSAndroid Build Coastguard Worker ", threshold=%" PRId64,
739*38e8c45fSAndroid Build Coastguard Worker __func__, preferredExpectedPresentationTime, frameInterval,
740*38e8c45fSAndroid Build Coastguard Worker static_cast<int64_t>(scheduler::VsyncConfig::kEarlyLatchMaxThreshold.count()));
741*38e8c45fSAndroid Build Coastguard Worker outVsyncEventData.frameTimelines[currentIndex] =
742*38e8c45fSAndroid Build Coastguard Worker {.vsyncId = generateToken(timestamp, preferredDeadlineTimestamp,
743*38e8c45fSAndroid Build Coastguard Worker preferredExpectedPresentationTime),
744*38e8c45fSAndroid Build Coastguard Worker .deadlineTimestamp = preferredDeadlineTimestamp,
745*38e8c45fSAndroid Build Coastguard Worker .expectedPresentationTime = preferredExpectedPresentationTime};
746*38e8c45fSAndroid Build Coastguard Worker currentIndex++;
747*38e8c45fSAndroid Build Coastguard Worker }
748*38e8c45fSAndroid Build Coastguard Worker
749*38e8c45fSAndroid Build Coastguard Worker outVsyncEventData.frameTimelinesLength = currentIndex;
750*38e8c45fSAndroid Build Coastguard Worker }
751*38e8c45fSAndroid Build Coastguard Worker
dispatchEvent(const DisplayEventReceiver::Event & event,const DisplayEventConsumers & consumers)752*38e8c45fSAndroid Build Coastguard Worker void EventThread::dispatchEvent(const DisplayEventReceiver::Event& event,
753*38e8c45fSAndroid Build Coastguard Worker const DisplayEventConsumers& consumers) {
754*38e8c45fSAndroid Build Coastguard Worker // List of Uids that have been sent vsync data with queued buffer count.
755*38e8c45fSAndroid Build Coastguard Worker // Used to keep track of which Uids can be removed from the map of
756*38e8c45fSAndroid Build Coastguard Worker // buffer stuffed clients.
757*38e8c45fSAndroid Build Coastguard Worker ftl::SmallVector<uid_t, 10> uidsPostedQueuedBuffers;
758*38e8c45fSAndroid Build Coastguard Worker for (const auto& consumer : consumers) {
759*38e8c45fSAndroid Build Coastguard Worker DisplayEventReceiver::Event copy = event;
760*38e8c45fSAndroid Build Coastguard Worker if (event.header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
761*38e8c45fSAndroid Build Coastguard Worker const Period frameInterval = mCallback.getVsyncPeriod(consumer->mOwnerUid);
762*38e8c45fSAndroid Build Coastguard Worker copy.vsync.vsyncData.frameInterval = frameInterval.ns();
763*38e8c45fSAndroid Build Coastguard Worker generateFrameTimeline(copy.vsync.vsyncData, frameInterval.ns(), copy.header.timestamp,
764*38e8c45fSAndroid Build Coastguard Worker event.vsync.vsyncData.preferredExpectedPresentationTime(),
765*38e8c45fSAndroid Build Coastguard Worker event.vsync.vsyncData.preferredDeadlineTimestamp());
766*38e8c45fSAndroid Build Coastguard Worker }
767*38e8c45fSAndroid Build Coastguard Worker auto it = mBufferStuffedUids.find(consumer->mOwnerUid);
768*38e8c45fSAndroid Build Coastguard Worker if (it != mBufferStuffedUids.end()) {
769*38e8c45fSAndroid Build Coastguard Worker copy.vsync.vsyncData.numberQueuedBuffers = it->second;
770*38e8c45fSAndroid Build Coastguard Worker uidsPostedQueuedBuffers.emplace_back(consumer->mOwnerUid);
771*38e8c45fSAndroid Build Coastguard Worker } else {
772*38e8c45fSAndroid Build Coastguard Worker copy.vsync.vsyncData.numberQueuedBuffers = 0;
773*38e8c45fSAndroid Build Coastguard Worker }
774*38e8c45fSAndroid Build Coastguard Worker switch (consumer->postEvent(copy)) {
775*38e8c45fSAndroid Build Coastguard Worker case NO_ERROR:
776*38e8c45fSAndroid Build Coastguard Worker break;
777*38e8c45fSAndroid Build Coastguard Worker
778*38e8c45fSAndroid Build Coastguard Worker case -EAGAIN:
779*38e8c45fSAndroid Build Coastguard Worker // TODO: Try again if pipe is full.
780*38e8c45fSAndroid Build Coastguard Worker ALOGW("Failed dispatching %s for %s", toString(event).c_str(),
781*38e8c45fSAndroid Build Coastguard Worker toString(*consumer).c_str());
782*38e8c45fSAndroid Build Coastguard Worker break;
783*38e8c45fSAndroid Build Coastguard Worker
784*38e8c45fSAndroid Build Coastguard Worker default:
785*38e8c45fSAndroid Build Coastguard Worker // Treat EPIPE and other errors as fatal.
786*38e8c45fSAndroid Build Coastguard Worker removeDisplayEventConnectionLocked(consumer);
787*38e8c45fSAndroid Build Coastguard Worker }
788*38e8c45fSAndroid Build Coastguard Worker }
789*38e8c45fSAndroid Build Coastguard Worker // The clients that have already received the queued buffer count
790*38e8c45fSAndroid Build Coastguard Worker // can be removed from the buffer stuffed Uid list to avoid
791*38e8c45fSAndroid Build Coastguard Worker // being sent duplicate messages.
792*38e8c45fSAndroid Build Coastguard Worker for (auto uid : uidsPostedQueuedBuffers) {
793*38e8c45fSAndroid Build Coastguard Worker mBufferStuffedUids.erase(uid);
794*38e8c45fSAndroid Build Coastguard Worker }
795*38e8c45fSAndroid Build Coastguard Worker if (event.header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC &&
796*38e8c45fSAndroid Build Coastguard Worker FlagManager::getInstance().vrr_config()) {
797*38e8c45fSAndroid Build Coastguard Worker mLastCommittedVsyncTime =
798*38e8c45fSAndroid Build Coastguard Worker TimePoint::fromNs(event.vsync.vsyncData.preferredExpectedPresentationTime());
799*38e8c45fSAndroid Build Coastguard Worker mCallback.onExpectedPresentTimePosted(mLastCommittedVsyncTime);
800*38e8c45fSAndroid Build Coastguard Worker }
801*38e8c45fSAndroid Build Coastguard Worker }
802*38e8c45fSAndroid Build Coastguard Worker
dump(std::string & result) const803*38e8c45fSAndroid Build Coastguard Worker void EventThread::dump(std::string& result) const {
804*38e8c45fSAndroid Build Coastguard Worker std::lock_guard<std::mutex> lock(mMutex);
805*38e8c45fSAndroid Build Coastguard Worker
806*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&result, "%s: state=%s VSyncState=", mThreadName, toCString(mState));
807*38e8c45fSAndroid Build Coastguard Worker if (mVSyncState) {
808*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&result, "{displayId=%s, count=%u%s}\n",
809*38e8c45fSAndroid Build Coastguard Worker to_string(mVsyncSchedule->getPhysicalDisplayId()).c_str(), mVSyncState->count,
810*38e8c45fSAndroid Build Coastguard Worker mVSyncState->synthetic ? ", synthetic" : "");
811*38e8c45fSAndroid Build Coastguard Worker } else {
812*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&result, "none\n");
813*38e8c45fSAndroid Build Coastguard Worker }
814*38e8c45fSAndroid Build Coastguard Worker
815*38e8c45fSAndroid Build Coastguard Worker const auto relativeLastCallTime =
816*38e8c45fSAndroid Build Coastguard Worker ticks<std::milli, float>(mLastVsyncCallbackTime - TimePoint::now());
817*38e8c45fSAndroid Build Coastguard Worker const auto relativeLastCommittedTime =
818*38e8c45fSAndroid Build Coastguard Worker ticks<std::milli, float>(mLastCommittedVsyncTime - TimePoint::now());
819*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&result, "mWorkDuration=%.2f mReadyDuration=%.2f last vsync time ",
820*38e8c45fSAndroid Build Coastguard Worker mWorkDuration.get().count() / 1e6f, mReadyDuration.count() / 1e6f);
821*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&result, "%.2fms relative to now\n", relativeLastCallTime);
822*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&result, " with vsync committed at %.2fms", relativeLastCommittedTime);
823*38e8c45fSAndroid Build Coastguard Worker
824*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&result, " pending events (count=%zu):\n", mPendingEvents.size());
825*38e8c45fSAndroid Build Coastguard Worker for (const auto& event : mPendingEvents) {
826*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&result, " %s\n", toString(event).c_str());
827*38e8c45fSAndroid Build Coastguard Worker }
828*38e8c45fSAndroid Build Coastguard Worker
829*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&result, " connections (count=%zu):\n", mDisplayEventConnections.size());
830*38e8c45fSAndroid Build Coastguard Worker for (const auto& ptr : mDisplayEventConnections) {
831*38e8c45fSAndroid Build Coastguard Worker if (const auto connection = ptr.promote()) {
832*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&result, " %s\n", toString(*connection).c_str());
833*38e8c45fSAndroid Build Coastguard Worker }
834*38e8c45fSAndroid Build Coastguard Worker }
835*38e8c45fSAndroid Build Coastguard Worker result += '\n';
836*38e8c45fSAndroid Build Coastguard Worker }
837*38e8c45fSAndroid Build Coastguard Worker
toCString(State state)838*38e8c45fSAndroid Build Coastguard Worker const char* EventThread::toCString(State state) {
839*38e8c45fSAndroid Build Coastguard Worker switch (state) {
840*38e8c45fSAndroid Build Coastguard Worker case State::Idle:
841*38e8c45fSAndroid Build Coastguard Worker return "Idle";
842*38e8c45fSAndroid Build Coastguard Worker case State::Quit:
843*38e8c45fSAndroid Build Coastguard Worker return "Quit";
844*38e8c45fSAndroid Build Coastguard Worker case State::SyntheticVSync:
845*38e8c45fSAndroid Build Coastguard Worker return "SyntheticVSync";
846*38e8c45fSAndroid Build Coastguard Worker case State::VSync:
847*38e8c45fSAndroid Build Coastguard Worker return "VSync";
848*38e8c45fSAndroid Build Coastguard Worker }
849*38e8c45fSAndroid Build Coastguard Worker }
850*38e8c45fSAndroid Build Coastguard Worker
onNewVsyncSchedule(std::shared_ptr<scheduler::VsyncSchedule> schedule)851*38e8c45fSAndroid Build Coastguard Worker void EventThread::onNewVsyncSchedule(std::shared_ptr<scheduler::VsyncSchedule> schedule) {
852*38e8c45fSAndroid Build Coastguard Worker // Hold onto the old registration until after releasing the mutex to avoid deadlock.
853*38e8c45fSAndroid Build Coastguard Worker scheduler::VSyncCallbackRegistration oldRegistration =
854*38e8c45fSAndroid Build Coastguard Worker onNewVsyncScheduleInternal(std::move(schedule));
855*38e8c45fSAndroid Build Coastguard Worker }
856*38e8c45fSAndroid Build Coastguard Worker
onNewVsyncScheduleInternal(std::shared_ptr<scheduler::VsyncSchedule> schedule)857*38e8c45fSAndroid Build Coastguard Worker scheduler::VSyncCallbackRegistration EventThread::onNewVsyncScheduleInternal(
858*38e8c45fSAndroid Build Coastguard Worker std::shared_ptr<scheduler::VsyncSchedule> schedule) {
859*38e8c45fSAndroid Build Coastguard Worker std::lock_guard<std::mutex> lock(mMutex);
860*38e8c45fSAndroid Build Coastguard Worker const bool reschedule = mVsyncRegistration.cancel() == scheduler::CancelResult::Cancelled;
861*38e8c45fSAndroid Build Coastguard Worker mVsyncSchedule = std::move(schedule);
862*38e8c45fSAndroid Build Coastguard Worker auto oldRegistration =
863*38e8c45fSAndroid Build Coastguard Worker std::exchange(mVsyncRegistration,
864*38e8c45fSAndroid Build Coastguard Worker scheduler::VSyncCallbackRegistration(mVsyncSchedule->getDispatch(),
865*38e8c45fSAndroid Build Coastguard Worker createDispatchCallback(),
866*38e8c45fSAndroid Build Coastguard Worker mThreadName));
867*38e8c45fSAndroid Build Coastguard Worker if (reschedule) {
868*38e8c45fSAndroid Build Coastguard Worker mVsyncRegistration.schedule({.workDuration = mWorkDuration.get().count(),
869*38e8c45fSAndroid Build Coastguard Worker .readyDuration = mReadyDuration.count(),
870*38e8c45fSAndroid Build Coastguard Worker .lastVsync = mLastVsyncCallbackTime.ns(),
871*38e8c45fSAndroid Build Coastguard Worker .committedVsyncOpt = mLastCommittedVsyncTime.ns()});
872*38e8c45fSAndroid Build Coastguard Worker }
873*38e8c45fSAndroid Build Coastguard Worker return oldRegistration;
874*38e8c45fSAndroid Build Coastguard Worker }
875*38e8c45fSAndroid Build Coastguard Worker
createDispatchCallback()876*38e8c45fSAndroid Build Coastguard Worker scheduler::VSyncDispatch::Callback EventThread::createDispatchCallback() {
877*38e8c45fSAndroid Build Coastguard Worker return [this](nsecs_t vsyncTime, nsecs_t wakeupTime, nsecs_t readyTime) {
878*38e8c45fSAndroid Build Coastguard Worker onVsync(vsyncTime, wakeupTime, readyTime);
879*38e8c45fSAndroid Build Coastguard Worker };
880*38e8c45fSAndroid Build Coastguard Worker }
881*38e8c45fSAndroid Build Coastguard Worker
882*38e8c45fSAndroid Build Coastguard Worker } // namespace impl
883*38e8c45fSAndroid Build Coastguard Worker } // namespace android
884*38e8c45fSAndroid Build Coastguard Worker
885*38e8c45fSAndroid Build Coastguard Worker // TODO(b/129481165): remove the #pragma below and fix conversion issues
886*38e8c45fSAndroid Build Coastguard Worker #pragma clang diagnostic pop // ignored "-Wconversion"
887