1 /*
2 * Copyright (C) 2018 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 "-Wextra"
20
21 #undef LOG_TAG
22 #define LOG_TAG "LibSurfaceFlingerUnittests"
23
24 #include <gmock/gmock.h>
25 #include <gtest/gtest.h>
26 #include <log/log.h>
27 #include <scheduler/VsyncConfig.h>
28 #include <utils/Errors.h>
29
30 #include "AsyncCallRecorder.h"
31 #include "DisplayHardware/DisplayMode.h"
32 #include "FrameTimeline.h"
33 #include "Scheduler/EventThread.h"
34 #include "mock/MockVSyncDispatch.h"
35 #include "mock/MockVSyncTracker.h"
36 #include "mock/MockVsyncController.h"
37
38 using namespace std::chrono_literals;
39 using namespace std::placeholders;
40
41 using testing::_;
42 using testing::Invoke;
43 using testing::Return;
44
45 namespace android {
46
47 using namespace ftl::flag_operators;
48
49 namespace {
50
51 constexpr PhysicalDisplayId INTERNAL_DISPLAY_ID = PhysicalDisplayId::fromPort(111u);
52 constexpr PhysicalDisplayId EXTERNAL_DISPLAY_ID = PhysicalDisplayId::fromPort(222u);
53 constexpr PhysicalDisplayId DISPLAY_ID_64BIT =
54 PhysicalDisplayId::fromEdid(0xffu, 0xffffu, 0xffff'ffffu);
55
56 constexpr std::chrono::duration VSYNC_PERIOD(16ms);
57
58 } // namespace
59
60 class EventThreadTest : public testing::Test {
61 protected:
62 static constexpr std::chrono::nanoseconds kWorkDuration = 0ms;
63 static constexpr std::chrono::nanoseconds kReadyDuration = 3ms;
64
65 class MockEventThreadConnection : public EventThreadConnection {
66 public:
MockEventThreadConnection(impl::EventThread * eventThread,uid_t callingUid,ResyncCallback && resyncCallback,EventRegistrationFlags eventRegistration)67 MockEventThreadConnection(impl::EventThread* eventThread, uid_t callingUid,
68 ResyncCallback&& resyncCallback,
69 EventRegistrationFlags eventRegistration)
70 : EventThreadConnection(eventThread, callingUid, std::move(resyncCallback),
71 eventRegistration) {}
72 MOCK_METHOD1(postEvent, status_t(const DisplayEventReceiver::Event& event));
73 };
74
75 using ConnectionEventRecorder =
76 AsyncCallRecorderWithCannedReturn<status_t (*)(const DisplayEventReceiver::Event&)>;
77
78 EventThreadTest();
79 ~EventThreadTest() override;
80
81 void setupEventThread(std::chrono::nanoseconds vsyncPeriod);
82 sp<MockEventThreadConnection> createConnection(ConnectionEventRecorder& recorder,
83 EventRegistrationFlags eventRegistration = {},
84 uid_t ownerUid = mConnectionUid);
85
86 void expectVSyncCallbackScheduleReceived(bool expectState);
87 void expectVSyncSetDurationCallReceived(std::chrono::nanoseconds expectedDuration,
88 std::chrono::nanoseconds expectedReadyDuration);
89 void expectVsyncEventReceivedByConnection(const char* name,
90 ConnectionEventRecorder& connectionEventRecorder,
91 nsecs_t expectedTimestamp, unsigned expectedCount);
92 void expectVsyncEventReceivedByConnection(nsecs_t expectedTimestamp, unsigned expectedCount);
93 void expectVsyncEventFrameTimelinesCorrect(
94 nsecs_t expectedTimestamp, gui::VsyncEventData::FrameTimeline preferredVsyncData);
95 void expectVsyncEventDataFrameTimelinesValidLength(VsyncEventData vsyncEventData,
96 std::chrono::nanoseconds vsyncPeriod);
97 void expectHotplugEventReceivedByConnection(PhysicalDisplayId expectedDisplayId,
98 bool expectedConnected);
99 void expectConfigChangedEventReceivedByConnection(PhysicalDisplayId expectedDisplayId,
100 int32_t expectedConfigId,
101 nsecs_t expectedVsyncPeriod);
102 void expectThrottleVsyncReceived(nsecs_t expectedTimestamp, uid_t);
103 void expectUidFrameRateMappingEventReceivedByConnection(PhysicalDisplayId expectedDisplayId,
104 std::vector<FrameRateOverride>);
105
onVSyncEvent(nsecs_t timestamp,nsecs_t expectedPresentationTime,nsecs_t deadlineTimestamp)106 void onVSyncEvent(nsecs_t timestamp, nsecs_t expectedPresentationTime,
107 nsecs_t deadlineTimestamp) {
108 mThread->onVsync(expectedPresentationTime, timestamp, deadlineTimestamp);
109 }
110
111 AsyncCallRecorderWithCannedReturn<
112 scheduler::ScheduleResult (*)(scheduler::VSyncDispatch::CallbackToken,
113 scheduler::VSyncDispatch::ScheduleTiming)>
114 mVSyncCallbackScheduleRecorder{0};
115 AsyncCallRecorderWithCannedReturn<
116 scheduler::ScheduleResult (*)(scheduler::VSyncDispatch::CallbackToken,
117 scheduler::VSyncDispatch::ScheduleTiming)>
118 mVSyncCallbackUpdateRecorder{0};
119 AsyncCallRecorderWithCannedReturn<
120 scheduler::VSyncDispatch::CallbackToken (*)(scheduler::VSyncDispatch::Callback,
121 std::string)>
122 mVSyncCallbackRegisterRecorder{scheduler::VSyncDispatch::CallbackToken(0)};
123 AsyncCallRecorder<void (*)(scheduler::VSyncDispatch::CallbackToken)>
124 mVSyncCallbackUnregisterRecorder;
125 AsyncCallRecorder<void (*)()> mResyncCallRecorder;
126 AsyncCallRecorder<void (*)(nsecs_t, uid_t)> mThrottleVsyncCallRecorder;
127 ConnectionEventRecorder mConnectionEventCallRecorder{0};
128 ConnectionEventRecorder mThrottledConnectionEventCallRecorder{0};
129
130 std::shared_ptr<scheduler::VsyncSchedule> mVsyncSchedule;
131 std::unique_ptr<impl::EventThread> mThread;
132 sp<MockEventThreadConnection> mConnection;
133 sp<MockEventThreadConnection> mThrottledConnection;
134 std::unique_ptr<frametimeline::impl::TokenManager> mTokenManager;
135
136 static constexpr uid_t mConnectionUid = 443;
137 static constexpr uid_t mThrottledConnectionUid = 177;
138 };
139
EventThreadTest()140 EventThreadTest::EventThreadTest() {
141 const ::testing::TestInfo* const test_info =
142 ::testing::UnitTest::GetInstance()->current_test_info();
143 ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name());
144
145 auto mockDispatchPtr = std::make_shared<mock::VSyncDispatch>();
146 mVsyncSchedule = std::shared_ptr<scheduler::VsyncSchedule>(
147 new scheduler::VsyncSchedule(INTERNAL_DISPLAY_ID,
148 std::make_shared<mock::VSyncTracker>(), mockDispatchPtr,
149 nullptr));
150 mock::VSyncDispatch& mockDispatch = *mockDispatchPtr;
151 EXPECT_CALL(mockDispatch, registerCallback(_, _))
152 .WillRepeatedly(Invoke(mVSyncCallbackRegisterRecorder.getInvocable()));
153 EXPECT_CALL(mockDispatch, schedule(_, _))
154 .WillRepeatedly(Invoke(mVSyncCallbackScheduleRecorder.getInvocable()));
155 EXPECT_CALL(mockDispatch, update(_, _))
156 .WillRepeatedly(Invoke(mVSyncCallbackUpdateRecorder.getInvocable()));
157 EXPECT_CALL(mockDispatch, unregisterCallback(_))
158 .WillRepeatedly(Invoke(mVSyncCallbackUnregisterRecorder.getInvocable()));
159 }
160
~EventThreadTest()161 EventThreadTest::~EventThreadTest() {
162 const ::testing::TestInfo* const test_info =
163 ::testing::UnitTest::GetInstance()->current_test_info();
164 ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name());
165
166 mThread.reset();
167 // EventThread should unregister itself as VSyncSource callback.
168 EXPECT_TRUE(mVSyncCallbackUnregisterRecorder.waitForCall().has_value());
169 }
170
setupEventThread(std::chrono::nanoseconds vsyncPeriod)171 void EventThreadTest::setupEventThread(std::chrono::nanoseconds vsyncPeriod) {
172 const auto throttleVsync = [&](nsecs_t expectedVsyncTimestamp, uid_t uid) {
173 mThrottleVsyncCallRecorder.getInvocable()(expectedVsyncTimestamp, uid);
174 return (uid == mThrottledConnectionUid);
175 };
176 const auto getVsyncPeriod = [vsyncPeriod](uid_t uid) { return vsyncPeriod.count(); };
177
178 mTokenManager = std::make_unique<frametimeline::impl::TokenManager>();
179 mThread = std::make_unique<impl::EventThread>("EventThreadTest", mVsyncSchedule,
180 mTokenManager.get(), throttleVsync,
181 getVsyncPeriod, kWorkDuration, kReadyDuration);
182
183 // EventThread should register itself as VSyncSource callback.
184 EXPECT_TRUE(mVSyncCallbackRegisterRecorder.waitForCall().has_value());
185
186 mConnection =
187 createConnection(mConnectionEventCallRecorder,
188 gui::ISurfaceComposer::EventRegistration::modeChanged |
189 gui::ISurfaceComposer::EventRegistration::frameRateOverride);
190 mThrottledConnection = createConnection(mThrottledConnectionEventCallRecorder,
191 gui::ISurfaceComposer::EventRegistration::modeChanged,
192 mThrottledConnectionUid);
193
194 // A display must be connected for VSYNC events to be delivered.
195 mThread->onHotplugReceived(INTERNAL_DISPLAY_ID, true);
196 expectHotplugEventReceivedByConnection(INTERNAL_DISPLAY_ID, true);
197 }
198
createConnection(ConnectionEventRecorder & recorder,EventRegistrationFlags eventRegistration,uid_t ownerUid)199 sp<EventThreadTest::MockEventThreadConnection> EventThreadTest::createConnection(
200 ConnectionEventRecorder& recorder, EventRegistrationFlags eventRegistration,
201 uid_t ownerUid) {
202 sp<MockEventThreadConnection> connection =
203 sp<MockEventThreadConnection>::make(mThread.get(), ownerUid,
204 mResyncCallRecorder.getInvocable(),
205 eventRegistration);
206 EXPECT_CALL(*connection, postEvent(_)).WillRepeatedly(Invoke(recorder.getInvocable()));
207 return connection;
208 }
209
expectVSyncCallbackScheduleReceived(bool expectState)210 void EventThreadTest::expectVSyncCallbackScheduleReceived(bool expectState) {
211 if (expectState) {
212 ASSERT_TRUE(mVSyncCallbackScheduleRecorder.waitForCall().has_value());
213 } else {
214 ASSERT_FALSE(mVSyncCallbackScheduleRecorder.waitForUnexpectedCall().has_value());
215 }
216 }
217
expectVSyncSetDurationCallReceived(std::chrono::nanoseconds expectedDuration,std::chrono::nanoseconds expectedReadyDuration)218 void EventThreadTest::expectVSyncSetDurationCallReceived(
219 std::chrono::nanoseconds expectedDuration, std::chrono::nanoseconds expectedReadyDuration) {
220 auto args = mVSyncCallbackUpdateRecorder.waitForCall();
221 ASSERT_TRUE(args.has_value());
222 EXPECT_EQ(expectedDuration.count(), std::get<1>(args.value()).workDuration);
223 EXPECT_EQ(expectedReadyDuration.count(), std::get<1>(args.value()).readyDuration);
224 }
225
expectThrottleVsyncReceived(nsecs_t expectedTimestamp,uid_t uid)226 void EventThreadTest::expectThrottleVsyncReceived(nsecs_t expectedTimestamp, uid_t uid) {
227 auto args = mThrottleVsyncCallRecorder.waitForCall();
228 ASSERT_TRUE(args.has_value());
229 EXPECT_EQ(expectedTimestamp, std::get<0>(args.value()));
230 EXPECT_EQ(uid, std::get<1>(args.value()));
231 }
232
expectVsyncEventReceivedByConnection(const char * name,ConnectionEventRecorder & connectionEventRecorder,nsecs_t expectedTimestamp,unsigned expectedCount)233 void EventThreadTest::expectVsyncEventReceivedByConnection(
234 const char* name, ConnectionEventRecorder& connectionEventRecorder,
235 nsecs_t expectedTimestamp, unsigned expectedCount) {
236 auto args = connectionEventRecorder.waitForCall();
237 ASSERT_TRUE(args.has_value()) << name << " did not receive an event for timestamp "
238 << expectedTimestamp;
239 const auto& event = std::get<0>(args.value());
240 EXPECT_EQ(DisplayEventReceiver::DISPLAY_EVENT_VSYNC, event.header.type)
241 << name << " did not get the correct event for timestamp " << expectedTimestamp;
242 EXPECT_EQ(expectedTimestamp, event.header.timestamp)
243 << name << " did not get the expected timestamp for timestamp " << expectedTimestamp;
244 EXPECT_EQ(expectedCount, event.vsync.count)
245 << name << " did not get the expected count for timestamp " << expectedTimestamp;
246 }
247
expectVsyncEventReceivedByConnection(nsecs_t expectedTimestamp,unsigned expectedCount)248 void EventThreadTest::expectVsyncEventReceivedByConnection(nsecs_t expectedTimestamp,
249 unsigned expectedCount) {
250 expectVsyncEventReceivedByConnection("mConnectionEventCallRecorder",
251 mConnectionEventCallRecorder, expectedTimestamp,
252 expectedCount);
253 }
254
expectVsyncEventFrameTimelinesCorrect(nsecs_t expectedTimestamp,VsyncEventData::FrameTimeline preferredVsyncData)255 void EventThreadTest::expectVsyncEventFrameTimelinesCorrect(
256 nsecs_t expectedTimestamp, VsyncEventData::FrameTimeline preferredVsyncData) {
257 auto args = mConnectionEventCallRecorder.waitForCall();
258 ASSERT_TRUE(args.has_value()) << " did not receive an event for timestamp "
259 << expectedTimestamp;
260 const auto& event = std::get<0>(args.value());
261 for (int i = 0; i < event.vsync.vsyncData.frameTimelinesLength; i++) {
262 auto prediction = mTokenManager->getPredictionsForToken(
263 event.vsync.vsyncData.frameTimelines[i].vsyncId);
264 EXPECT_TRUE(prediction.has_value());
265 EXPECT_EQ(prediction.value().endTime,
266 event.vsync.vsyncData.frameTimelines[i].deadlineTimestamp)
267 << "Deadline timestamp does not match cached value";
268 EXPECT_EQ(prediction.value().presentTime,
269 event.vsync.vsyncData.frameTimelines[i].expectedPresentationTime)
270 << "Expected vsync.vsyncData timestamp does not match cached value";
271
272 if (i > 0) {
273 EXPECT_GT(event.vsync.vsyncData.frameTimelines[i].deadlineTimestamp,
274 event.vsync.vsyncData.frameTimelines[i - 1].deadlineTimestamp)
275 << "Deadline timestamp out of order for frame timeline " << i;
276 EXPECT_GT(event.vsync.vsyncData.frameTimelines[i].expectedPresentationTime,
277 event.vsync.vsyncData.frameTimelines[i - 1].expectedPresentationTime)
278 << "Expected vsync.vsyncData timestamp out of order for frame timeline " << i;
279 }
280
281 // Vsync ID order lines up with registration into test token manager.
282 EXPECT_EQ(i, event.vsync.vsyncData.frameTimelines[i].vsyncId)
283 << "Vsync ID incorrect for frame timeline " << i;
284 if (i == event.vsync.vsyncData.preferredFrameTimelineIndex) {
285 EXPECT_EQ(event.vsync.vsyncData.frameTimelines[i].deadlineTimestamp,
286 preferredVsyncData.deadlineTimestamp)
287 << "Preferred deadline timestamp incorrect" << i;
288 EXPECT_EQ(event.vsync.vsyncData.frameTimelines[i].expectedPresentationTime,
289 preferredVsyncData.expectedPresentationTime)
290 << "Preferred expected vsync.vsyncData timestamp incorrect" << i;
291 }
292 }
293 }
294
expectVsyncEventDataFrameTimelinesValidLength(VsyncEventData vsyncEventData,std::chrono::nanoseconds vsyncPeriod)295 void EventThreadTest::expectVsyncEventDataFrameTimelinesValidLength(
296 VsyncEventData vsyncEventData, std::chrono::nanoseconds vsyncPeriod) {
297 float nonPreferredTimelinesAmount =
298 scheduler::VsyncConfig::kEarlyLatchMaxThreshold / vsyncPeriod;
299 EXPECT_LE(vsyncEventData.frameTimelinesLength, nonPreferredTimelinesAmount + 1)
300 << "Amount of non-preferred frame timelines too many;"
301 << " expected presentation time will be over threshold";
302 EXPECT_LT(nonPreferredTimelinesAmount, VsyncEventData::kFrameTimelinesCapacity)
303 << "Amount of non-preferred frame timelines should be less than max capacity";
304 EXPECT_GT(static_cast<int64_t>(vsyncEventData.frameTimelinesLength), 0)
305 << "Frame timelines length should be greater than 0";
306 EXPECT_LT(vsyncEventData.preferredFrameTimelineIndex, vsyncEventData.frameTimelinesLength)
307 << "Preferred frame timeline index should be less than frame timelines length";
308 }
309
expectHotplugEventReceivedByConnection(PhysicalDisplayId expectedDisplayId,bool expectedConnected)310 void EventThreadTest::expectHotplugEventReceivedByConnection(PhysicalDisplayId expectedDisplayId,
311 bool expectedConnected) {
312 auto args = mConnectionEventCallRecorder.waitForCall();
313 ASSERT_TRUE(args.has_value());
314 const auto& event = std::get<0>(args.value());
315 EXPECT_EQ(DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG, event.header.type);
316 EXPECT_EQ(expectedDisplayId, event.header.displayId);
317 EXPECT_EQ(expectedConnected, event.hotplug.connected);
318 }
319
expectConfigChangedEventReceivedByConnection(PhysicalDisplayId expectedDisplayId,int32_t expectedConfigId,nsecs_t expectedVsyncPeriod)320 void EventThreadTest::expectConfigChangedEventReceivedByConnection(
321 PhysicalDisplayId expectedDisplayId, int32_t expectedConfigId,
322 nsecs_t expectedVsyncPeriod) {
323 auto args = mConnectionEventCallRecorder.waitForCall();
324 ASSERT_TRUE(args.has_value());
325 const auto& event = std::get<0>(args.value());
326 EXPECT_EQ(DisplayEventReceiver::DISPLAY_EVENT_MODE_CHANGE, event.header.type);
327 EXPECT_EQ(expectedDisplayId, event.header.displayId);
328 EXPECT_EQ(expectedConfigId, event.modeChange.modeId);
329 EXPECT_EQ(expectedVsyncPeriod, event.modeChange.vsyncPeriod);
330 }
331
expectUidFrameRateMappingEventReceivedByConnection(PhysicalDisplayId expectedDisplayId,std::vector<FrameRateOverride> expectedOverrides)332 void EventThreadTest::expectUidFrameRateMappingEventReceivedByConnection(
333 PhysicalDisplayId expectedDisplayId, std::vector<FrameRateOverride> expectedOverrides) {
334 for (const auto [uid, frameRateHz] : expectedOverrides) {
335 auto args = mConnectionEventCallRecorder.waitForCall();
336 ASSERT_TRUE(args.has_value());
337 const auto& event = std::get<0>(args.value());
338 EXPECT_EQ(DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE, event.header.type);
339 EXPECT_EQ(expectedDisplayId, event.header.displayId);
340 EXPECT_EQ(uid, event.frameRateOverride.uid);
341 EXPECT_EQ(frameRateHz, event.frameRateOverride.frameRateHz);
342 }
343
344 auto args = mConnectionEventCallRecorder.waitForCall();
345 ASSERT_TRUE(args.has_value());
346 const auto& event = std::get<0>(args.value());
347 EXPECT_EQ(DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE_FLUSH, event.header.type);
348 EXPECT_EQ(expectedDisplayId, event.header.displayId);
349 }
350
351 namespace {
352
353 using namespace testing;
354
355 /* ------------------------------------------------------------------------
356 * Test cases
357 */
358
TEST_F(EventThreadTest,canCreateAndDestroyThreadWithNoEventsSent)359 TEST_F(EventThreadTest, canCreateAndDestroyThreadWithNoEventsSent) {
360 setupEventThread(VSYNC_PERIOD);
361
362 EXPECT_FALSE(mVSyncCallbackRegisterRecorder.waitForCall(0us).has_value());
363 EXPECT_FALSE(mVSyncCallbackScheduleRecorder.waitForCall(0us).has_value());
364 EXPECT_FALSE(mVSyncCallbackUpdateRecorder.waitForCall(0us).has_value());
365 EXPECT_FALSE(mVSyncCallbackUnregisterRecorder.waitForCall(0us).has_value());
366 EXPECT_FALSE(mResyncCallRecorder.waitForCall(0us).has_value());
367 EXPECT_FALSE(mConnectionEventCallRecorder.waitForCall(0us).has_value());
368 }
369
TEST_F(EventThreadTest,vsyncRequestIsIgnoredIfDisplayIsDisconnected)370 TEST_F(EventThreadTest, vsyncRequestIsIgnoredIfDisplayIsDisconnected) {
371 setupEventThread(VSYNC_PERIOD);
372
373 mThread->onHotplugReceived(INTERNAL_DISPLAY_ID, false);
374 expectHotplugEventReceivedByConnection(INTERNAL_DISPLAY_ID, false);
375
376 // Signal that we want the next vsync event to be posted to the connection.
377 mThread->requestNextVsync(mConnection);
378
379 // EventThread should not enable vsync callbacks.
380 expectVSyncCallbackScheduleReceived(false);
381 }
382
TEST_F(EventThreadTest,requestNextVsyncPostsASingleVSyncEventToTheConnection)383 TEST_F(EventThreadTest, requestNextVsyncPostsASingleVSyncEventToTheConnection) {
384 setupEventThread(VSYNC_PERIOD);
385
386 // Signal that we want the next vsync event to be posted to the connection
387 mThread->requestNextVsync(mConnection);
388
389 // EventThread should immediately request a resync.
390 EXPECT_TRUE(mResyncCallRecorder.waitForCall().has_value());
391
392 // EventThread should enable schedule a vsync callback
393 expectVSyncCallbackScheduleReceived(true);
394
395 // Use the received callback to signal a first vsync event.
396 // The throttler should receive the event, as well as the connection.
397 onVSyncEvent(123, 456, 789);
398 expectThrottleVsyncReceived(456, mConnectionUid);
399 expectVsyncEventReceivedByConnection(123, 1u);
400
401 // EventThread is requesting one more callback due to VsyncRequest::SingleSuppressCallback
402 expectVSyncCallbackScheduleReceived(true);
403
404 // Use the received callback to signal a second vsync event.
405 // The throttler should receive the event, but the connection should
406 // not as it was only interested in the first.
407 onVSyncEvent(456, 123, 0);
408 EXPECT_FALSE(mThrottleVsyncCallRecorder.waitForUnexpectedCall().has_value());
409 EXPECT_FALSE(mConnectionEventCallRecorder.waitForUnexpectedCall().has_value());
410
411 // EventThread should also detect that at this point that it does not need
412 // any more vsync events, and should disable their generation.
413 expectVSyncCallbackScheduleReceived(false);
414 }
415
TEST_F(EventThreadTest,requestNextVsyncEventFrameTimelinesCorrect)416 TEST_F(EventThreadTest, requestNextVsyncEventFrameTimelinesCorrect) {
417 setupEventThread(VSYNC_PERIOD);
418
419 // Signal that we want the next vsync event to be posted to the connection
420 mThread->requestNextVsync(mConnection);
421
422 expectVSyncCallbackScheduleReceived(true);
423
424 // Use the received callback to signal a vsync event.
425 // The throttler should receive the event, as well as the connection.
426 onVSyncEvent(123, 456, 789);
427 expectVsyncEventFrameTimelinesCorrect(123, {-1, 789, 456});
428 }
429
TEST_F(EventThreadTest,requestNextVsyncEventFrameTimelinesValidLength)430 TEST_F(EventThreadTest, requestNextVsyncEventFrameTimelinesValidLength) {
431 // The VsyncEventData should not have kFrameTimelinesCapacity amount of valid frame timelines,
432 // due to longer vsync period and kEarlyLatchMaxThreshold. Use length-2 to avoid decimal
433 // truncation (e.g. 60Hz has 16.6... ms vsync period).
434 std::chrono::nanoseconds vsyncPeriod(scheduler::VsyncConfig::kEarlyLatchMaxThreshold /
435 (VsyncEventData::kFrameTimelinesCapacity - 2));
436 setupEventThread(vsyncPeriod);
437
438 // Signal that we want the next vsync event to be posted to the connection
439 mThread->requestNextVsync(mConnection);
440
441 expectVSyncCallbackScheduleReceived(true);
442
443 // Use the received callback to signal a vsync event.
444 // The throttler should receive the event, as well as the connection.
445 nsecs_t expectedTimestamp = 123;
446 onVSyncEvent(expectedTimestamp, 456, 789);
447
448 auto args = mConnectionEventCallRecorder.waitForCall();
449 ASSERT_TRUE(args.has_value()) << " did not receive an event for timestamp "
450 << expectedTimestamp;
451 const VsyncEventData vsyncEventData = std::get<0>(args.value()).vsync.vsyncData;
452 expectVsyncEventDataFrameTimelinesValidLength(vsyncEventData, vsyncPeriod);
453 }
454
TEST_F(EventThreadTest,getLatestVsyncEventData)455 TEST_F(EventThreadTest, getLatestVsyncEventData) {
456 setupEventThread(VSYNC_PERIOD);
457
458 const nsecs_t now = systemTime();
459 const nsecs_t preferredExpectedPresentationTime = now + 20000000;
460 const nsecs_t preferredDeadline = preferredExpectedPresentationTime - kReadyDuration.count();
461
462 mock::VSyncTracker& mockTracker =
463 *static_cast<mock::VSyncTracker*>(&mVsyncSchedule->getTracker());
464 EXPECT_CALL(mockTracker, nextAnticipatedVSyncTimeFrom(_))
465 .WillOnce(Return(preferredExpectedPresentationTime));
466
467 VsyncEventData vsyncEventData = mThread->getLatestVsyncEventData(mConnection);
468
469 // Check EventThread immediately requested a resync.
470 EXPECT_TRUE(mResyncCallRecorder.waitForCall().has_value());
471
472 expectVsyncEventDataFrameTimelinesValidLength(vsyncEventData, VSYNC_PERIOD);
473 EXPECT_GT(vsyncEventData.frameTimelines[0].deadlineTimestamp, now)
474 << "Deadline timestamp should be greater than frame time";
475 for (size_t i = 0; i < vsyncEventData.frameTimelinesLength; i++) {
476 auto prediction =
477 mTokenManager->getPredictionsForToken(vsyncEventData.frameTimelines[i].vsyncId);
478 EXPECT_TRUE(prediction.has_value());
479 EXPECT_EQ(prediction.value().endTime, vsyncEventData.frameTimelines[i].deadlineTimestamp)
480 << "Deadline timestamp does not match cached value";
481 EXPECT_EQ(prediction.value().presentTime,
482 vsyncEventData.frameTimelines[i].expectedPresentationTime)
483 << "Expected vsync timestamp does not match cached value";
484 EXPECT_GT(vsyncEventData.frameTimelines[i].expectedPresentationTime,
485 vsyncEventData.frameTimelines[i].deadlineTimestamp)
486 << "Expected vsync timestamp should be greater than deadline";
487
488 if (i > 0) {
489 EXPECT_GT(vsyncEventData.frameTimelines[i].deadlineTimestamp,
490 vsyncEventData.frameTimelines[i - 1].deadlineTimestamp)
491 << "Deadline timestamp out of order for frame timeline " << i;
492 EXPECT_GT(vsyncEventData.frameTimelines[i].expectedPresentationTime,
493 vsyncEventData.frameTimelines[i - 1].expectedPresentationTime)
494 << "Expected vsync timestamp out of order for frame timeline " << i;
495 }
496
497 // Vsync ID order lines up with registration into test token manager.
498 EXPECT_EQ(i, vsyncEventData.frameTimelines[i].vsyncId)
499 << "Vsync ID incorrect for frame timeline " << i;
500 if (i == vsyncEventData.preferredFrameTimelineIndex) {
501 EXPECT_EQ(vsyncEventData.frameTimelines[i].deadlineTimestamp, preferredDeadline)
502 << "Preferred deadline timestamp incorrect" << i;
503 EXPECT_EQ(vsyncEventData.frameTimelines[i].expectedPresentationTime,
504 preferredExpectedPresentationTime)
505 << "Preferred expected vsync timestamp incorrect" << i;
506 }
507 }
508 }
509
TEST_F(EventThreadTest,setVsyncRateZeroPostsNoVSyncEventsToThatConnection)510 TEST_F(EventThreadTest, setVsyncRateZeroPostsNoVSyncEventsToThatConnection) {
511 setupEventThread(VSYNC_PERIOD);
512
513 // Create a first connection, register it, and request a vsync rate of zero.
514 ConnectionEventRecorder firstConnectionEventRecorder{0};
515 sp<MockEventThreadConnection> firstConnection = createConnection(firstConnectionEventRecorder);
516 mThread->setVsyncRate(0, firstConnection);
517
518 // By itself, this should not enable vsync events
519 expectVSyncCallbackScheduleReceived(false);
520
521 // However if there is another connection which wants events at a nonzero rate.....
522 ConnectionEventRecorder secondConnectionEventRecorder{0};
523 sp<MockEventThreadConnection> secondConnection =
524 createConnection(secondConnectionEventRecorder);
525 mThread->setVsyncRate(1, secondConnection);
526
527 // EventThread should enable vsync callbacks.
528 expectVSyncCallbackScheduleReceived(true);
529
530 // Send a vsync event. EventThread should then make a call to the
531 // the second connection. The first connection should not
532 // get the event.
533 onVSyncEvent(123, 0456, 0);
534 EXPECT_FALSE(firstConnectionEventRecorder.waitForUnexpectedCall().has_value());
535 expectVsyncEventReceivedByConnection("secondConnection", secondConnectionEventRecorder, 123,
536 1u);
537 }
538
TEST_F(EventThreadTest,setVsyncRateOnePostsAllEventsToThatConnection)539 TEST_F(EventThreadTest, setVsyncRateOnePostsAllEventsToThatConnection) {
540 setupEventThread(VSYNC_PERIOD);
541
542 mThread->setVsyncRate(1, mConnection);
543
544 // EventThread should enable vsync callbacks.
545 expectVSyncCallbackScheduleReceived(true);
546
547 // Send a vsync event. EventThread should then make a call to the
548 // throttler, and the connection.
549 onVSyncEvent(123, 456, 789);
550 expectThrottleVsyncReceived(456, mConnectionUid);
551 expectVsyncEventReceivedByConnection(123, 1u);
552
553 // A second event should go to the same places.
554 onVSyncEvent(456, 123, 0);
555 expectThrottleVsyncReceived(123, mConnectionUid);
556 expectVsyncEventReceivedByConnection(456, 2u);
557
558 // A third event should go to the same places.
559 onVSyncEvent(789, 777, 111);
560 expectThrottleVsyncReceived(777, mConnectionUid);
561 expectVsyncEventReceivedByConnection(789, 3u);
562 }
563
TEST_F(EventThreadTest,setVsyncRateTwoPostsEveryOtherEventToThatConnection)564 TEST_F(EventThreadTest, setVsyncRateTwoPostsEveryOtherEventToThatConnection) {
565 setupEventThread(VSYNC_PERIOD);
566
567 mThread->setVsyncRate(2, mConnection);
568
569 // EventThread should enable vsync callbacks.
570 expectVSyncCallbackScheduleReceived(true);
571
572 // The first event will not be seen by the connection.
573 onVSyncEvent(123, 456, 789);
574 EXPECT_FALSE(mConnectionEventCallRecorder.waitForUnexpectedCall().has_value());
575 EXPECT_FALSE(mThrottleVsyncCallRecorder.waitForUnexpectedCall().has_value());
576
577 // The second event will be seen by the connection.
578 onVSyncEvent(456, 123, 0);
579 expectVsyncEventReceivedByConnection(456, 2u);
580 EXPECT_FALSE(mThrottleVsyncCallRecorder.waitForUnexpectedCall().has_value());
581
582 // The third event will not be seen by the connection.
583 onVSyncEvent(789, 777, 744);
584 EXPECT_FALSE(mConnectionEventCallRecorder.waitForUnexpectedCall().has_value());
585 EXPECT_FALSE(mThrottleVsyncCallRecorder.waitForUnexpectedCall().has_value());
586
587 // The fourth event will be seen by the connection.
588 onVSyncEvent(101112, 7847, 86);
589 expectVsyncEventReceivedByConnection(101112, 4u);
590 }
591
TEST_F(EventThreadTest,connectionsRemovedIfInstanceDestroyed)592 TEST_F(EventThreadTest, connectionsRemovedIfInstanceDestroyed) {
593 setupEventThread(VSYNC_PERIOD);
594
595 mThread->setVsyncRate(1, mConnection);
596
597 // EventThread should enable vsync callbacks.
598 expectVSyncCallbackScheduleReceived(true);
599
600 // Destroy the only (strong) reference to the connection.
601 mConnection = nullptr;
602
603 // The first event will not be seen by the connection.
604 onVSyncEvent(123, 56, 789);
605 EXPECT_FALSE(mConnectionEventCallRecorder.waitForUnexpectedCall().has_value());
606
607 // EventThread should disable vsync callbacks
608 expectVSyncCallbackScheduleReceived(false);
609 }
610
TEST_F(EventThreadTest,connectionsRemovedIfEventDeliveryError)611 TEST_F(EventThreadTest, connectionsRemovedIfEventDeliveryError) {
612 setupEventThread(VSYNC_PERIOD);
613
614 ConnectionEventRecorder errorConnectionEventRecorder{NO_MEMORY};
615 sp<MockEventThreadConnection> errorConnection = createConnection(errorConnectionEventRecorder);
616 mThread->setVsyncRate(1, errorConnection);
617
618 // EventThread should enable vsync callbacks.
619 expectVSyncCallbackScheduleReceived(true);
620
621 // The first event will be seen by the connection, which then returns an error.
622 onVSyncEvent(123, 456, 789);
623 expectVsyncEventReceivedByConnection("errorConnection", errorConnectionEventRecorder, 123, 1u);
624
625 // Another schedule is expected, since the connection is removed only after
626 // the next vsync is requested.
627 expectVSyncCallbackScheduleReceived(true);
628
629 // A subsequent event will not be seen by the connection.
630 onVSyncEvent(456, 123, 0);
631 EXPECT_FALSE(errorConnectionEventRecorder.waitForUnexpectedCall().has_value());
632
633 // EventThread should disable vsync callbacks with the second event
634 expectVSyncCallbackScheduleReceived(false);
635 }
636
TEST_F(EventThreadTest,tracksEventConnections)637 TEST_F(EventThreadTest, tracksEventConnections) {
638 setupEventThread(VSYNC_PERIOD);
639
640 EXPECT_EQ(2, mThread->getEventThreadConnectionCount());
641 ConnectionEventRecorder errorConnectionEventRecorder{NO_MEMORY};
642 sp<MockEventThreadConnection> errorConnection = createConnection(errorConnectionEventRecorder);
643 mThread->setVsyncRate(1, errorConnection);
644 EXPECT_EQ(3, mThread->getEventThreadConnectionCount());
645 ConnectionEventRecorder secondConnectionEventRecorder{0};
646 sp<MockEventThreadConnection> secondConnection =
647 createConnection(secondConnectionEventRecorder);
648 mThread->setVsyncRate(1, secondConnection);
649 EXPECT_EQ(4, mThread->getEventThreadConnectionCount());
650
651 // EventThread should enable vsync callbacks.
652 expectVSyncCallbackScheduleReceived(true);
653
654 // The first event will be seen by the connection, which then returns an error.
655 onVSyncEvent(123, 456, 789);
656 expectVsyncEventReceivedByConnection("errorConnection", errorConnectionEventRecorder, 123, 1u);
657 expectVsyncEventReceivedByConnection("successConnection", secondConnectionEventRecorder, 123,
658 1u);
659 EXPECT_EQ(3, mThread->getEventThreadConnectionCount());
660 }
661
TEST_F(EventThreadTest,eventsDroppedIfNonfatalEventDeliveryError)662 TEST_F(EventThreadTest, eventsDroppedIfNonfatalEventDeliveryError) {
663 setupEventThread(VSYNC_PERIOD);
664
665 ConnectionEventRecorder errorConnectionEventRecorder{WOULD_BLOCK};
666 sp<MockEventThreadConnection> errorConnection = createConnection(errorConnectionEventRecorder);
667 mThread->setVsyncRate(1, errorConnection);
668
669 // EventThread should enable vsync callbacks.
670 expectVSyncCallbackScheduleReceived(true);
671
672 // The first event will be seen by the connection, which then returns a non-fatal error.
673 onVSyncEvent(123, 456, 789);
674 expectVsyncEventReceivedByConnection("errorConnection", errorConnectionEventRecorder, 123, 1u);
675 expectVSyncCallbackScheduleReceived(true);
676
677 // A subsequent event will be seen by the connection, which still then returns a non-fatal
678 // error.
679 onVSyncEvent(456, 123, 0);
680 expectVsyncEventReceivedByConnection("errorConnection", errorConnectionEventRecorder, 456, 2u);
681 expectVSyncCallbackScheduleReceived(true);
682
683 // EventThread will not disable vsync callbacks as the errors are non-fatal.
684 onVSyncEvent(456, 123, 0);
685 expectVSyncCallbackScheduleReceived(true);
686 }
687
TEST_F(EventThreadTest,setPhaseOffsetForwardsToVSyncSource)688 TEST_F(EventThreadTest, setPhaseOffsetForwardsToVSyncSource) {
689 setupEventThread(VSYNC_PERIOD);
690
691 mThread->setDuration(321ns, 456ns);
692 expectVSyncSetDurationCallReceived(321ns, 456ns);
693 }
694
TEST_F(EventThreadTest,postHotplugInternalDisconnect)695 TEST_F(EventThreadTest, postHotplugInternalDisconnect) {
696 setupEventThread(VSYNC_PERIOD);
697
698 mThread->onHotplugReceived(INTERNAL_DISPLAY_ID, false);
699 expectHotplugEventReceivedByConnection(INTERNAL_DISPLAY_ID, false);
700 }
701
TEST_F(EventThreadTest,postHotplugInternalConnect)702 TEST_F(EventThreadTest, postHotplugInternalConnect) {
703 setupEventThread(VSYNC_PERIOD);
704
705 mThread->onHotplugReceived(INTERNAL_DISPLAY_ID, true);
706 expectHotplugEventReceivedByConnection(INTERNAL_DISPLAY_ID, true);
707 }
708
TEST_F(EventThreadTest,postHotplugExternalDisconnect)709 TEST_F(EventThreadTest, postHotplugExternalDisconnect) {
710 setupEventThread(VSYNC_PERIOD);
711
712 mThread->onHotplugReceived(EXTERNAL_DISPLAY_ID, false);
713 expectHotplugEventReceivedByConnection(EXTERNAL_DISPLAY_ID, false);
714 }
715
TEST_F(EventThreadTest,postHotplugExternalConnect)716 TEST_F(EventThreadTest, postHotplugExternalConnect) {
717 setupEventThread(VSYNC_PERIOD);
718
719 mThread->onHotplugReceived(EXTERNAL_DISPLAY_ID, true);
720 expectHotplugEventReceivedByConnection(EXTERNAL_DISPLAY_ID, true);
721 }
722
TEST_F(EventThreadTest,postConfigChangedPrimary)723 TEST_F(EventThreadTest, postConfigChangedPrimary) {
724 setupEventThread(VSYNC_PERIOD);
725
726 const auto mode = DisplayMode::Builder(hal::HWConfigId(0))
727 .setPhysicalDisplayId(INTERNAL_DISPLAY_ID)
728 .setId(DisplayModeId(7))
729 .setVsyncPeriod(16666666)
730 .build();
731 const Fps fps = mode->getFps() / 2;
732
733 mThread->onModeChanged({fps, ftl::as_non_null(mode)});
734 expectConfigChangedEventReceivedByConnection(INTERNAL_DISPLAY_ID, 7, fps.getPeriodNsecs());
735 }
736
TEST_F(EventThreadTest,postConfigChangedExternal)737 TEST_F(EventThreadTest, postConfigChangedExternal) {
738 setupEventThread(VSYNC_PERIOD);
739
740 const auto mode = DisplayMode::Builder(hal::HWConfigId(0))
741 .setPhysicalDisplayId(EXTERNAL_DISPLAY_ID)
742 .setId(DisplayModeId(5))
743 .setVsyncPeriod(16666666)
744 .build();
745 const Fps fps = mode->getFps() / 2;
746
747 mThread->onModeChanged({fps, ftl::as_non_null(mode)});
748 expectConfigChangedEventReceivedByConnection(EXTERNAL_DISPLAY_ID, 5, fps.getPeriodNsecs());
749 }
750
TEST_F(EventThreadTest,postConfigChangedPrimary64bit)751 TEST_F(EventThreadTest, postConfigChangedPrimary64bit) {
752 setupEventThread(VSYNC_PERIOD);
753
754 const auto mode = DisplayMode::Builder(hal::HWConfigId(0))
755 .setPhysicalDisplayId(DISPLAY_ID_64BIT)
756 .setId(DisplayModeId(7))
757 .setVsyncPeriod(16666666)
758 .build();
759 const Fps fps = mode->getFps() / 2;
760 mThread->onModeChanged({fps, ftl::as_non_null(mode)});
761 expectConfigChangedEventReceivedByConnection(DISPLAY_ID_64BIT, 7, fps.getPeriodNsecs());
762 }
763
TEST_F(EventThreadTest,suppressConfigChanged)764 TEST_F(EventThreadTest, suppressConfigChanged) {
765 setupEventThread(VSYNC_PERIOD);
766
767 ConnectionEventRecorder suppressConnectionEventRecorder{0};
768 sp<MockEventThreadConnection> suppressConnection =
769 createConnection(suppressConnectionEventRecorder);
770
771 const auto mode = DisplayMode::Builder(hal::HWConfigId(0))
772 .setPhysicalDisplayId(INTERNAL_DISPLAY_ID)
773 .setId(DisplayModeId(9))
774 .setVsyncPeriod(16666666)
775 .build();
776 const Fps fps = mode->getFps() / 2;
777
778 mThread->onModeChanged({fps, ftl::as_non_null(mode)});
779 expectConfigChangedEventReceivedByConnection(INTERNAL_DISPLAY_ID, 9, fps.getPeriodNsecs());
780
781 auto args = suppressConnectionEventRecorder.waitForCall();
782 ASSERT_FALSE(args.has_value());
783 }
784
TEST_F(EventThreadTest,postUidFrameRateMapping)785 TEST_F(EventThreadTest, postUidFrameRateMapping) {
786 setupEventThread(VSYNC_PERIOD);
787
788 const std::vector<FrameRateOverride> overrides = {
789 {.uid = 1, .frameRateHz = 20},
790 {.uid = 3, .frameRateHz = 40},
791 {.uid = 5, .frameRateHz = 60},
792 };
793
794 mThread->onFrameRateOverridesChanged(INTERNAL_DISPLAY_ID, overrides);
795 expectUidFrameRateMappingEventReceivedByConnection(INTERNAL_DISPLAY_ID, overrides);
796 }
797
TEST_F(EventThreadTest,suppressUidFrameRateMapping)798 TEST_F(EventThreadTest, suppressUidFrameRateMapping) {
799 setupEventThread(VSYNC_PERIOD);
800
801 const std::vector<FrameRateOverride> overrides = {
802 {.uid = 1, .frameRateHz = 20},
803 {.uid = 3, .frameRateHz = 40},
804 {.uid = 5, .frameRateHz = 60},
805 };
806
807 ConnectionEventRecorder suppressConnectionEventRecorder{0};
808 sp<MockEventThreadConnection> suppressConnection =
809 createConnection(suppressConnectionEventRecorder);
810
811 mThread->onFrameRateOverridesChanged(INTERNAL_DISPLAY_ID, overrides);
812 expectUidFrameRateMappingEventReceivedByConnection(INTERNAL_DISPLAY_ID, overrides);
813
814 auto args = suppressConnectionEventRecorder.waitForCall();
815 ASSERT_FALSE(args.has_value());
816 }
817
TEST_F(EventThreadTest,requestNextVsyncWithThrottleVsyncDoesntPostVSync)818 TEST_F(EventThreadTest, requestNextVsyncWithThrottleVsyncDoesntPostVSync) {
819 setupEventThread(VSYNC_PERIOD);
820
821 // Signal that we want the next vsync event to be posted to the throttled connection
822 mThread->requestNextVsync(mThrottledConnection);
823
824 // EventThread should immediately request a resync.
825 EXPECT_TRUE(mResyncCallRecorder.waitForCall().has_value());
826
827 // EventThread should enable vsync callbacks.
828 expectVSyncCallbackScheduleReceived(true);
829
830 // Use the received callback to signal a first vsync event.
831 // The throttler should receive the event, but not the connection.
832 onVSyncEvent(123, 456, 789);
833 expectThrottleVsyncReceived(456, mThrottledConnectionUid);
834 mThrottledConnectionEventCallRecorder.waitForUnexpectedCall();
835 expectVSyncCallbackScheduleReceived(true);
836
837 // Use the received callback to signal a second vsync event.
838 // The throttler should receive the event, but the connection should
839 // not as it was only interested in the first.
840 onVSyncEvent(456, 123, 0);
841 expectThrottleVsyncReceived(123, mThrottledConnectionUid);
842 EXPECT_FALSE(mConnectionEventCallRecorder.waitForUnexpectedCall().has_value());
843 expectVSyncCallbackScheduleReceived(true);
844
845 // EventThread should not change the vsync state as it didn't send the event
846 // yet
847 onVSyncEvent(456, 123, 0);
848 expectVSyncCallbackScheduleReceived(true);
849 }
850
851 } // namespace
852 } // namespace android
853
854 // TODO(b/129481165): remove the #pragma below and fix conversion issues
855 #pragma clang diagnostic pop // ignored "-Wextra"
856