1 /*
2 * Copyright (C) 2009 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 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
18
19 #include <binder/IPCThreadState.h>
20
21 #include <utils/Log.h>
22 #include <utils/Timers.h>
23 #include <utils/threads.h>
24
25 #include <gui/DisplayEventReceiver.h>
26
27 #include "EventThread.h"
28 #include "FrameTimeline.h"
29 #include "MessageQueue.h"
30
31 namespace android::impl {
32
dispatchFrame(int64_t vsyncId,nsecs_t expectedVsyncTime)33 void MessageQueue::Handler::dispatchFrame(int64_t vsyncId, nsecs_t expectedVsyncTime) {
34 if (!mFramePending.exchange(true)) {
35 mVsyncId = vsyncId;
36 mExpectedVsyncTime = expectedVsyncTime;
37 mQueue.mLooper->sendMessage(this, Message());
38 }
39 }
40
isFramePending() const41 bool MessageQueue::Handler::isFramePending() const {
42 return mFramePending.load();
43 }
44
handleMessage(const Message &)45 void MessageQueue::Handler::handleMessage(const Message&) {
46 mFramePending.store(false);
47
48 const nsecs_t frameTime = systemTime();
49 auto& compositor = mQueue.mCompositor;
50
51 if (!compositor.commit(frameTime, mVsyncId, mExpectedVsyncTime)) {
52 return;
53 }
54
55 compositor.composite(frameTime, mVsyncId);
56 compositor.sample();
57 }
58
MessageQueue(ICompositor & compositor)59 MessageQueue::MessageQueue(ICompositor& compositor)
60 : MessageQueue(compositor, sp<Handler>::make(*this)) {}
61
62 constexpr bool kAllowNonCallbacks = true;
63
MessageQueue(ICompositor & compositor,sp<Handler> handler)64 MessageQueue::MessageQueue(ICompositor& compositor, sp<Handler> handler)
65 : mCompositor(compositor),
66 mLooper(sp<Looper>::make(kAllowNonCallbacks)),
67 mHandler(std::move(handler)) {}
68
69 // TODO(b/169865816): refactor VSyncInjections to use MessageQueue directly
70 // and remove the EventThread from MessageQueue
setInjector(sp<EventThreadConnection> connection)71 void MessageQueue::setInjector(sp<EventThreadConnection> connection) {
72 auto& tube = mInjector.tube;
73
74 if (const int fd = tube.getFd(); fd >= 0) {
75 mLooper->removeFd(fd);
76 }
77
78 if (connection) {
79 // The EventThreadConnection is retained when disabling injection, so avoid subsequently
80 // stealing invalid FDs. Note that the stolen FDs are kept open.
81 if (tube.getFd() < 0) {
82 connection->stealReceiveChannel(&tube);
83 } else {
84 ALOGW("Recycling channel for VSYNC injection.");
85 }
86
87 mLooper->addFd(
88 tube.getFd(), 0, Looper::EVENT_INPUT,
89 [](int, int, void* data) {
90 reinterpret_cast<MessageQueue*>(data)->injectorCallback();
91 return 1; // Keep registration.
92 },
93 this);
94 }
95
96 std::lock_guard lock(mInjector.mutex);
97 mInjector.connection = std::move(connection);
98 }
99
vsyncCallback(nsecs_t vsyncTime,nsecs_t targetWakeupTime,nsecs_t readyTime)100 void MessageQueue::vsyncCallback(nsecs_t vsyncTime, nsecs_t targetWakeupTime, nsecs_t readyTime) {
101 ATRACE_CALL();
102 // Trace VSYNC-sf
103 mVsync.value = (mVsync.value + 1) % 2;
104
105 {
106 std::lock_guard lock(mVsync.mutex);
107 mVsync.lastCallbackTime = std::chrono::nanoseconds(vsyncTime);
108 mVsync.scheduledFrameTime.reset();
109 }
110
111 const auto vsyncId = mVsync.tokenManager->generateTokenForPredictions(
112 {targetWakeupTime, readyTime, vsyncTime});
113
114 mHandler->dispatchFrame(vsyncId, vsyncTime);
115 }
116
initVsync(scheduler::VSyncDispatch & dispatch,frametimeline::TokenManager & tokenManager,std::chrono::nanoseconds workDuration)117 void MessageQueue::initVsync(scheduler::VSyncDispatch& dispatch,
118 frametimeline::TokenManager& tokenManager,
119 std::chrono::nanoseconds workDuration) {
120 setDuration(workDuration);
121 mVsync.tokenManager = &tokenManager;
122 mVsync.registration = std::make_unique<
123 scheduler::VSyncCallbackRegistration>(dispatch,
124 std::bind(&MessageQueue::vsyncCallback, this,
125 std::placeholders::_1,
126 std::placeholders::_2,
127 std::placeholders::_3),
128 "sf");
129 }
130
setDuration(std::chrono::nanoseconds workDuration)131 void MessageQueue::setDuration(std::chrono::nanoseconds workDuration) {
132 ATRACE_CALL();
133 std::lock_guard lock(mVsync.mutex);
134 mVsync.workDuration = workDuration;
135 if (mVsync.scheduledFrameTime) {
136 mVsync.scheduledFrameTime = mVsync.registration->schedule(
137 {mVsync.workDuration.get().count(),
138 /*readyDuration=*/0, mVsync.lastCallbackTime.count()});
139 }
140 }
141
waitMessage()142 void MessageQueue::waitMessage() {
143 do {
144 IPCThreadState::self()->flushCommands();
145 int32_t ret = mLooper->pollOnce(-1);
146 switch (ret) {
147 case Looper::POLL_WAKE:
148 case Looper::POLL_CALLBACK:
149 continue;
150 case Looper::POLL_ERROR:
151 ALOGE("Looper::POLL_ERROR");
152 continue;
153 case Looper::POLL_TIMEOUT:
154 // timeout (should not happen)
155 continue;
156 default:
157 // should not happen
158 ALOGE("Looper::pollOnce() returned unknown status %d", ret);
159 continue;
160 }
161 } while (true);
162 }
163
postMessage(sp<MessageHandler> && handler)164 void MessageQueue::postMessage(sp<MessageHandler>&& handler) {
165 mLooper->sendMessage(handler, Message());
166 }
167
scheduleFrame()168 void MessageQueue::scheduleFrame() {
169 ATRACE_CALL();
170
171 {
172 std::lock_guard lock(mInjector.mutex);
173 if (CC_UNLIKELY(mInjector.connection)) {
174 ALOGD("%s while injecting VSYNC", __FUNCTION__);
175 mInjector.connection->requestNextVsync();
176 return;
177 }
178 }
179
180 std::lock_guard lock(mVsync.mutex);
181 mVsync.scheduledFrameTime =
182 mVsync.registration->schedule({.workDuration = mVsync.workDuration.get().count(),
183 .readyDuration = 0,
184 .earliestVsync = mVsync.lastCallbackTime.count()});
185 }
186
injectorCallback()187 void MessageQueue::injectorCallback() {
188 ssize_t n;
189 DisplayEventReceiver::Event buffer[8];
190 while ((n = DisplayEventReceiver::getEvents(&mInjector.tube, buffer, 8)) > 0) {
191 for (int i = 0; i < n; i++) {
192 if (buffer[i].header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
193 auto& vsync = buffer[i].vsync;
194 mHandler->dispatchFrame(vsync.vsyncData.preferredVsyncId(),
195 vsync.vsyncData.preferredExpectedPresentationTime());
196 break;
197 }
198 }
199 }
200 }
201
getScheduledFrameTime() const202 auto MessageQueue::getScheduledFrameTime() const -> std::optional<Clock::time_point> {
203 if (mHandler->isFramePending()) {
204 return Clock::now();
205 }
206
207 std::lock_guard lock(mVsync.mutex);
208 if (const auto time = mVsync.scheduledFrameTime) {
209 return Clock::time_point(std::chrono::nanoseconds(*time));
210 }
211
212 return std::nullopt;
213 }
214
215 } // namespace android::impl
216