• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
29 namespace android {
30 
31 using namespace std::chrono_literals;
32 using namespace testing;
33 
34 using CallbackToken = scheduler::VSyncDispatch::CallbackToken;
35 
36 struct NoOpCompositor final : ICompositor {
configureandroid::NoOpCompositor37     void configure() override {}
commitandroid::NoOpCompositor38     bool commit(PhysicalDisplayId, const scheduler::FrameTargets&) override { return false; }
compositeandroid::NoOpCompositor39     CompositeResultsPerDisplay composite(PhysicalDisplayId,
40                                          const scheduler::FrameTargeters&) override {
41         return {};
42     }
sampleandroid::NoOpCompositor43     void sample() override {}
44 } gNoOpCompositor;
45 
46 class TestableMessageQueue : public impl::MessageQueue {
47     struct MockHandler : MessageQueue::Handler {
48         using MessageQueue::Handler::Handler;
49 
50         MOCK_METHOD(void, dispatchFrame, (VsyncId, TimePoint), (override));
51     };
52 
TestableMessageQueue(sp<MockHandler> handler)53     explicit TestableMessageQueue(sp<MockHandler> handler)
54           : impl::MessageQueue(gNoOpCompositor, handler), mHandler(std::move(handler)) {}
55 
56     // impl::MessageQueue overrides:
onFrameSignal(ICompositor &,VsyncId,TimePoint)57     void onFrameSignal(ICompositor&, VsyncId, TimePoint) override {}
58 
59 public:
TestableMessageQueue()60     TestableMessageQueue() : TestableMessageQueue(sp<MockHandler>::make(*this)) {}
61 
62     using impl::MessageQueue::vsyncCallback;
63 
64     const sp<MockHandler> mHandler;
65 };
66 
67 struct MockTokenManager : frametimeline::TokenManager {
68     MOCK_METHOD1(generateTokenForPredictions, int64_t(frametimeline::TimelineItem&& prediction));
69     MOCK_CONST_METHOD1(getPredictionsForToken, std::optional<frametimeline::TimelineItem>(int64_t));
70 };
71 
72 struct MessageQueueTest : testing::Test {
SetUpandroid::MessageQueueTest73     void SetUp() override {
74         EXPECT_CALL(*mVSyncDispatch, registerCallback(_, "sf")).WillOnce(Return(mCallbackToken));
75         EXPECT_NO_FATAL_FAILURE(mEventQueue.initVsync(mVSyncDispatch, mTokenManager, kDuration));
76         EXPECT_CALL(*mVSyncDispatch, unregisterCallback(mCallbackToken)).Times(1);
77     }
78 
79     std::shared_ptr<mock::VSyncDispatch> mVSyncDispatch = std::make_shared<mock::VSyncDispatch>();
80     MockTokenManager mTokenManager;
81     TestableMessageQueue mEventQueue;
82 
83     const CallbackToken mCallbackToken{5};
84 
85     static constexpr Duration kDuration = 100ms;
86     static constexpr Duration kDifferentDuration = 250ms;
87 };
88 
89 namespace {
90 
TEST_F(MessageQueueTest,commit)91 TEST_F(MessageQueueTest, commit) {
92     const auto timing = scheduler::VSyncDispatch::ScheduleTiming{.workDuration = kDuration.ns(),
93                                                                  .readyDuration = 0,
94                                                                  .earliestVsync = 0};
95     EXPECT_FALSE(mEventQueue.getScheduledFrameTime());
96 
97     EXPECT_CALL(*mVSyncDispatch, schedule(mCallbackToken, timing)).WillOnce(Return(1234));
98     EXPECT_NO_FATAL_FAILURE(mEventQueue.scheduleFrame());
99 
100     ASSERT_TRUE(mEventQueue.getScheduledFrameTime());
101     EXPECT_EQ(1234, mEventQueue.getScheduledFrameTime()->time_since_epoch().count());
102 }
103 
TEST_F(MessageQueueTest,commitTwice)104 TEST_F(MessageQueueTest, commitTwice) {
105     InSequence s;
106     const auto timing = scheduler::VSyncDispatch::ScheduleTiming{.workDuration = kDuration.ns(),
107                                                                  .readyDuration = 0,
108                                                                  .earliestVsync = 0};
109 
110     EXPECT_CALL(*mVSyncDispatch, schedule(mCallbackToken, timing)).WillOnce(Return(1234));
111     EXPECT_NO_FATAL_FAILURE(mEventQueue.scheduleFrame());
112 
113     ASSERT_TRUE(mEventQueue.getScheduledFrameTime());
114     EXPECT_EQ(1234, mEventQueue.getScheduledFrameTime()->time_since_epoch().count());
115 
116     EXPECT_CALL(*mVSyncDispatch, schedule(mCallbackToken, timing)).WillOnce(Return(4567));
117     EXPECT_NO_FATAL_FAILURE(mEventQueue.scheduleFrame());
118 
119     ASSERT_TRUE(mEventQueue.getScheduledFrameTime());
120     EXPECT_EQ(4567, mEventQueue.getScheduledFrameTime()->time_since_epoch().count());
121 }
122 
TEST_F(MessageQueueTest,commitTwiceWithCallback)123 TEST_F(MessageQueueTest, commitTwiceWithCallback) {
124     InSequence s;
125     const auto timing = scheduler::VSyncDispatch::ScheduleTiming{.workDuration = kDuration.ns(),
126                                                                  .readyDuration = 0,
127                                                                  .earliestVsync = 0};
128 
129     EXPECT_CALL(*mVSyncDispatch, schedule(mCallbackToken, timing)).WillOnce(Return(1234));
130     EXPECT_NO_FATAL_FAILURE(mEventQueue.scheduleFrame());
131 
132     ASSERT_TRUE(mEventQueue.getScheduledFrameTime());
133     EXPECT_EQ(1234, mEventQueue.getScheduledFrameTime()->time_since_epoch().count());
134 
135     constexpr TimePoint kStartTime = TimePoint::fromNs(100);
136     constexpr TimePoint kEndTime = kStartTime + kDuration;
137     constexpr TimePoint kPresentTime = TimePoint::fromNs(500);
138     constexpr VsyncId vsyncId{42};
139 
140     EXPECT_CALL(mTokenManager,
141                 generateTokenForPredictions(frametimeline::TimelineItem(kStartTime.ns(),
142                                                                         kEndTime.ns(),
143                                                                         kPresentTime.ns())))
144             .WillOnce(Return(ftl::to_underlying(vsyncId)));
145     EXPECT_CALL(*mEventQueue.mHandler, dispatchFrame(vsyncId, kPresentTime)).Times(1);
146     EXPECT_NO_FATAL_FAILURE(
147             mEventQueue.vsyncCallback(kPresentTime.ns(), kStartTime.ns(), kEndTime.ns()));
148 
149     EXPECT_FALSE(mEventQueue.getScheduledFrameTime());
150 
151     const auto timingAfterCallback =
152             scheduler::VSyncDispatch::ScheduleTiming{.workDuration = kDuration.ns(),
153                                                      .readyDuration = 0,
154                                                      .earliestVsync = kPresentTime.ns()};
155 
156     EXPECT_CALL(*mVSyncDispatch, schedule(mCallbackToken, timingAfterCallback)).WillOnce(Return(0));
157     EXPECT_NO_FATAL_FAILURE(mEventQueue.scheduleFrame());
158 }
159 
TEST_F(MessageQueueTest,commitWithDurationChange)160 TEST_F(MessageQueueTest, commitWithDurationChange) {
161     EXPECT_NO_FATAL_FAILURE(mEventQueue.setDuration(kDifferentDuration));
162 
163     const auto timing =
164             scheduler::VSyncDispatch::ScheduleTiming{.workDuration = kDifferentDuration.ns(),
165                                                      .readyDuration = 0,
166                                                      .earliestVsync = 0};
167 
168     EXPECT_CALL(*mVSyncDispatch, schedule(mCallbackToken, timing)).WillOnce(Return(0));
169     EXPECT_NO_FATAL_FAILURE(mEventQueue.scheduleFrame());
170 }
171 
172 } // namespace
173 } // namespace android
174