1 /*
2 * Copyright 2020 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 #undef LOG_TAG
18 #define LOG_TAG "LibSurfaceFlingerUnittests"
19
20 #include <gmock/gmock.h>
21 #include <gtest/gtest.h>
22
23 #include <scheduler/interface/ICompositor.h>
24
25 #include "FrameTimeline.h"
26 #include "Scheduler/MessageQueue.h"
27 #include "mock/MockVSyncDispatch.h"
28 #include "utils/Timers.h"
29
30 namespace android {
31
32 using namespace std::chrono_literals;
33 using namespace testing;
34
35 using CallbackToken = scheduler::VSyncDispatch::CallbackToken;
36
37 struct NoOpCompositor final : ICompositor {
configureandroid::NoOpCompositor38 void configure() override {}
commitandroid::NoOpCompositor39 bool commit(PhysicalDisplayId, const scheduler::FrameTargets&) override { return false; }
compositeandroid::NoOpCompositor40 CompositeResultsPerDisplay composite(PhysicalDisplayId,
41 const scheduler::FrameTargeters&) override {
42 return {};
43 }
sampleandroid::NoOpCompositor44 void sample() override {}
sendNotifyExpectedPresentHintandroid::NoOpCompositor45 void sendNotifyExpectedPresentHint(PhysicalDisplayId) {}
46 } gNoOpCompositor;
47
48 class TestableMessageQueue : public impl::MessageQueue {
49 struct MockHandler : MessageQueue::Handler {
50 using MessageQueue::Handler::Handler;
51
52 MOCK_METHOD(void, dispatchFrame, (VsyncId, TimePoint), (override));
53 MOCK_METHOD(bool, isFramePending, (), (const, override));
54 MOCK_METHOD(TimePoint, getExpectedVsyncTime, (), (const override));
55 };
56
TestableMessageQueue(sp<MockHandler> handler)57 explicit TestableMessageQueue(sp<MockHandler> handler)
58 : impl::MessageQueue(gNoOpCompositor, handler), mHandler(std::move(handler)) {}
59
60 // impl::MessageQueue overrides:
onFrameSignal(ICompositor &,VsyncId,TimePoint)61 void onFrameSignal(ICompositor&, VsyncId, TimePoint) override {}
62
63 public:
TestableMessageQueue()64 TestableMessageQueue() : TestableMessageQueue(sp<MockHandler>::make(*this)) {}
65
66 using impl::MessageQueue::vsyncCallback;
67
68 const sp<MockHandler> mHandler;
69 };
70
71 struct MockTokenManager : frametimeline::TokenManager {
72 MOCK_METHOD1(generateTokenForPredictions, int64_t(frametimeline::TimelineItem&& prediction));
73 MOCK_CONST_METHOD1(getPredictionsForToken, std::optional<frametimeline::TimelineItem>(int64_t));
74 };
75
76 struct MessageQueueTest : testing::Test {
SetUpandroid::MessageQueueTest77 void SetUp() override {
78 EXPECT_CALL(*mVSyncDispatch, registerCallback(_, "sf")).WillOnce(Return(mCallbackToken));
79 EXPECT_NO_FATAL_FAILURE(
80 mEventQueue.initVsyncInternal(mVSyncDispatch, mTokenManager, kDuration));
81 EXPECT_CALL(*mVSyncDispatch, unregisterCallback(mCallbackToken)).Times(1);
82 }
83
84 std::shared_ptr<mock::VSyncDispatch> mVSyncDispatch = std::make_shared<mock::VSyncDispatch>();
85 MockTokenManager mTokenManager;
86 TestableMessageQueue mEventQueue;
87
88 const CallbackToken mCallbackToken{5};
89
90 static constexpr Duration kDuration = 100ms;
91 static constexpr Duration kDifferentDuration = 250ms;
92 };
93
94 namespace {
95
TEST_F(MessageQueueTest,commit)96 TEST_F(MessageQueueTest, commit) {
97 const auto timing = scheduler::VSyncDispatch::ScheduleTiming{.workDuration = kDuration.ns(),
98 .readyDuration = 0,
99 .lastVsync = 0};
100 EXPECT_FALSE(mEventQueue.getScheduledFrameResult());
101
102 const auto timePoint = TimePoint::fromNs(1234);
103 const auto scheduleResult = scheduler::ScheduleResult{timePoint, timePoint};
104 EXPECT_CALL(*mVSyncDispatch, schedule(mCallbackToken, timing)).WillOnce(Return(scheduleResult));
105 EXPECT_NO_FATAL_FAILURE(mEventQueue.scheduleFrame());
106
107 const auto scheduledFrameResult = mEventQueue.getScheduledFrameResult();
108 ASSERT_TRUE(scheduledFrameResult);
109 EXPECT_EQ(1234, scheduledFrameResult->callbackTime.ns());
110 EXPECT_EQ(1234, scheduledFrameResult->vsyncTime.ns());
111 }
112
TEST_F(MessageQueueTest,commitTwice)113 TEST_F(MessageQueueTest, commitTwice) {
114 InSequence s;
115 const auto timing = scheduler::VSyncDispatch::ScheduleTiming{.workDuration = kDuration.ns(),
116 .readyDuration = 0,
117 .lastVsync = 0};
118
119 auto timePoint = TimePoint::fromNs(1234);
120 auto scheduleResult = scheduler::ScheduleResult{timePoint, timePoint};
121 EXPECT_CALL(*mVSyncDispatch, schedule(mCallbackToken, timing)).WillOnce(Return(scheduleResult));
122 EXPECT_NO_FATAL_FAILURE(mEventQueue.scheduleFrame());
123
124 auto scheduledFrameResult = mEventQueue.getScheduledFrameResult();
125 ASSERT_TRUE(scheduledFrameResult);
126 EXPECT_EQ(1234, scheduledFrameResult->callbackTime.ns());
127 EXPECT_EQ(1234, scheduledFrameResult->vsyncTime.ns());
128
129 timePoint = TimePoint::fromNs(4567);
130 scheduleResult = scheduler::ScheduleResult{timePoint, timePoint};
131 EXPECT_CALL(*mVSyncDispatch, schedule(mCallbackToken, timing)).WillOnce(Return(scheduleResult));
132 EXPECT_NO_FATAL_FAILURE(mEventQueue.scheduleFrame());
133
134 scheduledFrameResult = mEventQueue.getScheduledFrameResult();
135 ASSERT_TRUE(scheduledFrameResult);
136 EXPECT_EQ(4567, scheduledFrameResult->callbackTime.ns());
137 EXPECT_EQ(4567, scheduledFrameResult->vsyncTime.ns());
138 }
139
TEST_F(MessageQueueTest,commitTwiceWithCallback)140 TEST_F(MessageQueueTest, commitTwiceWithCallback) {
141 InSequence s;
142 const auto timing = scheduler::VSyncDispatch::ScheduleTiming{.workDuration = kDuration.ns(),
143 .readyDuration = 0,
144 .lastVsync = 0};
145
146 const auto timePoint = TimePoint::fromNs(1234);
147 auto scheduleResult = scheduler::ScheduleResult{timePoint, timePoint};
148 EXPECT_CALL(*mVSyncDispatch, schedule(mCallbackToken, timing)).WillOnce(Return(scheduleResult));
149 EXPECT_NO_FATAL_FAILURE(mEventQueue.scheduleFrame());
150
151 auto scheduledFrameResult = mEventQueue.getScheduledFrameResult();
152 ASSERT_TRUE(scheduledFrameResult);
153 EXPECT_EQ(1234, scheduledFrameResult->callbackTime.ns());
154 EXPECT_EQ(1234, scheduledFrameResult->vsyncTime.ns());
155
156 constexpr TimePoint kStartTime = TimePoint::fromNs(100);
157 constexpr TimePoint kEndTime = kStartTime + kDuration;
158 constexpr TimePoint kPresentTime = TimePoint::fromNs(500);
159 constexpr VsyncId vsyncId{42};
160
161 EXPECT_CALL(mTokenManager,
162 generateTokenForPredictions(
163 frametimeline::TimelineItem(kStartTime.ns(), kEndTime.ns(),
164 kPresentTime.ns(), kPresentTime.ns())))
165 .WillOnce(Return(ftl::to_underlying(vsyncId)));
166 EXPECT_CALL(*mEventQueue.mHandler, dispatchFrame(vsyncId, kPresentTime)).Times(1);
167 EXPECT_NO_FATAL_FAILURE(
168 mEventQueue.vsyncCallback(kPresentTime.ns(), kStartTime.ns(), kEndTime.ns()));
169
170 EXPECT_FALSE(mEventQueue.getScheduledFrameResult());
171
172 const auto timingAfterCallback =
173 scheduler::VSyncDispatch::ScheduleTiming{.workDuration = kDuration.ns(),
174 .readyDuration = 0,
175 .lastVsync = kPresentTime.ns()};
176 scheduleResult = scheduler::ScheduleResult{TimePoint::fromNs(0), TimePoint::fromNs(0)};
177 EXPECT_CALL(*mVSyncDispatch, schedule(mCallbackToken, timingAfterCallback))
178 .WillOnce(Return(scheduleResult));
179 EXPECT_NO_FATAL_FAILURE(mEventQueue.scheduleFrame());
180 }
181
TEST_F(MessageQueueTest,commitWithDurationChange)182 TEST_F(MessageQueueTest, commitWithDurationChange) {
183 EXPECT_NO_FATAL_FAILURE(mEventQueue.setDuration(kDifferentDuration));
184
185 const auto timing =
186 scheduler::VSyncDispatch::ScheduleTiming{.workDuration = kDifferentDuration.ns(),
187 .readyDuration = 0,
188 .lastVsync = 0};
189
190 const auto scheduleResult =
191 scheduler::ScheduleResult{TimePoint::fromNs(0), TimePoint::fromNs(0)};
192 EXPECT_CALL(*mVSyncDispatch, schedule(mCallbackToken, timing)).WillOnce(Return(scheduleResult));
193 EXPECT_NO_FATAL_FAILURE(mEventQueue.scheduleFrame());
194 }
195
TEST_F(MessageQueueTest,scheduleResultWhenFrameIsPending)196 TEST_F(MessageQueueTest, scheduleResultWhenFrameIsPending) {
197 const auto timePoint = TimePoint::now();
198 EXPECT_CALL(*mEventQueue.mHandler, isFramePending()).WillOnce(Return(true));
199 EXPECT_CALL(*mEventQueue.mHandler, getExpectedVsyncTime()).WillRepeatedly(Return(timePoint));
200
201 const auto scheduledFrameResult = mEventQueue.getScheduledFrameResult();
202
203 ASSERT_TRUE(scheduledFrameResult);
204 EXPECT_NEAR(static_cast<double>(TimePoint::now().ns()),
205 static_cast<double>(scheduledFrameResult->callbackTime.ns()), ms2ns(1));
206 EXPECT_EQ(timePoint, scheduledFrameResult->vsyncTime);
207 }
208
209 } // namespace
210 } // namespace android
211