xref: /aosp_15_r20/frameworks/native/services/surfaceflinger/tests/unittests/MessageQueueTest.cpp (revision 38e8c45f13ce32b0dcecb25141ffecaf386fa17f)
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