xref: /aosp_15_r20/frameworks/native/services/surfaceflinger/tests/unittests/LayerInfoTest.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 "LayerInfoTest"
19 
20 #include <gtest/gtest.h>
21 
22 #include <scheduler/Fps.h>
23 
24 #include <common/test/FlagUtils.h>
25 #include "FpsOps.h"
26 #include "Scheduler/LayerHistory.h"
27 #include "Scheduler/LayerInfo.h"
28 #include "TestableScheduler.h"
29 #include "TestableSurfaceFlinger.h"
30 #include "mock/MockSchedulerCallback.h"
31 
32 #include <com_android_graphics_surfaceflinger_flags.h>
33 
34 namespace android::scheduler {
35 
36 using android::mock::createDisplayMode;
37 
38 class LayerInfoTest : public testing::Test {
39 protected:
40     using FrameTimeData = LayerInfo::FrameTimeData;
41 
42     static constexpr Fps LO_FPS = 30_Hz;
43     static constexpr Fps HI_FPS = 90_Hz;
44 
LayerInfoTest()45     LayerInfoTest() { mFlinger.resetScheduler(mScheduler); }
46 
setFrameTimes(const std::deque<FrameTimeData> & frameTimes)47     void setFrameTimes(const std::deque<FrameTimeData>& frameTimes) {
48         layerInfo.mFrameTimes = frameTimes;
49     }
50 
setLastRefreshRate(Fps fps)51     void setLastRefreshRate(Fps fps) {
52         layerInfo.mLastRefreshRate.reported = fps;
53         layerInfo.mLastRefreshRate.calculated = fps;
54     }
55 
calculateAverageFrameTime()56     auto calculateAverageFrameTime() { return layerInfo.calculateAverageFrameTime(); }
57 
58     LayerInfo layerInfo{"TestLayerInfo", 0, LayerHistory::LayerVoteType::Heuristic};
59 
60     std::shared_ptr<RefreshRateSelector> mSelector =
61             std::make_shared<RefreshRateSelector>(makeModes(createDisplayMode(DisplayModeId(0),
62                                                                               LO_FPS),
63                                                             createDisplayMode(DisplayModeId(1),
64                                                                               HI_FPS)),
65                                                   DisplayModeId(0));
66     mock::SchedulerCallback mSchedulerCallback;
67     TestableSurfaceFlinger mFlinger;
68     TestableScheduler* mScheduler = new TestableScheduler(mSelector, mFlinger, mSchedulerCallback);
69 };
70 
71 namespace {
72 
73 using namespace com::android::graphics::surfaceflinger;
74 
TEST_F(LayerInfoTest,prefersPresentTime)75 TEST_F(LayerInfoTest, prefersPresentTime) {
76     std::deque<FrameTimeData> frameTimes;
77     constexpr auto kExpectedFps = 50_Hz;
78     constexpr auto kPeriod = kExpectedFps.getPeriodNsecs();
79     constexpr int kNumFrames = 10;
80     for (int i = 1; i <= kNumFrames; i++) {
81         frameTimes.push_back(FrameTimeData{.presentTime = kPeriod * i,
82                                            .queueTime = 0,
83                                            .pendingModeChange = false});
84     }
85     setFrameTimes(frameTimes);
86     const auto averageFrameTime = calculateAverageFrameTime();
87     ASSERT_TRUE(averageFrameTime.has_value());
88     ASSERT_EQ(kExpectedFps, Fps::fromPeriodNsecs(*averageFrameTime));
89 }
90 
TEST_F(LayerInfoTest,fallbacksToQueueTimeIfNoPresentTime)91 TEST_F(LayerInfoTest, fallbacksToQueueTimeIfNoPresentTime) {
92     std::deque<FrameTimeData> frameTimes;
93     constexpr auto kExpectedFps = 50_Hz;
94     constexpr auto kPeriod = kExpectedFps.getPeriodNsecs();
95     constexpr int kNumFrames = 10;
96     for (int i = 1; i <= kNumFrames; i++) {
97         frameTimes.push_back(FrameTimeData{.presentTime = 0,
98                                            .queueTime = kPeriod * i,
99                                            .pendingModeChange = false});
100     }
101     setFrameTimes(frameTimes);
102     setLastRefreshRate(20_Hz); // Set to some valid value.
103     const auto averageFrameTime = calculateAverageFrameTime();
104     ASSERT_TRUE(averageFrameTime.has_value());
105     ASSERT_EQ(kExpectedFps, Fps::fromPeriodNsecs(*averageFrameTime));
106 }
107 
TEST_F(LayerInfoTest,returnsNulloptIfThereWasConfigChange)108 TEST_F(LayerInfoTest, returnsNulloptIfThereWasConfigChange) {
109     std::deque<FrameTimeData> frameTimesWithoutConfigChange;
110     const auto period = (50_Hz).getPeriodNsecs();
111     constexpr int kNumFrames = 10;
112     for (int i = 1; i <= kNumFrames; i++) {
113         frameTimesWithoutConfigChange.push_back(FrameTimeData{.presentTime = period * i,
114                                                               .queueTime = period * i,
115                                                               .pendingModeChange = false});
116     }
117 
118     setFrameTimes(frameTimesWithoutConfigChange);
119     ASSERT_TRUE(calculateAverageFrameTime().has_value());
120 
121     {
122         // Config change in the first record
123         auto frameTimes = frameTimesWithoutConfigChange;
124         frameTimes[0].pendingModeChange = true;
125         setFrameTimes(frameTimes);
126         ASSERT_FALSE(calculateAverageFrameTime().has_value());
127     }
128 
129     {
130         // Config change in the last record
131         auto frameTimes = frameTimesWithoutConfigChange;
132         frameTimes[frameTimes.size() - 1].pendingModeChange = true;
133         setFrameTimes(frameTimes);
134         ASSERT_FALSE(calculateAverageFrameTime().has_value());
135     }
136 
137     {
138         // Config change in the middle
139         auto frameTimes = frameTimesWithoutConfigChange;
140         frameTimes[frameTimes.size() / 2].pendingModeChange = true;
141         setFrameTimes(frameTimes);
142         ASSERT_FALSE(calculateAverageFrameTime().has_value());
143     }
144 }
145 
146 // A frame can be recorded twice with very close presentation or queue times.
147 // Make sure that this doesn't influence the calculated average FPS.
TEST_F(LayerInfoTest,ignoresSmallPeriods)148 TEST_F(LayerInfoTest, ignoresSmallPeriods) {
149     std::deque<FrameTimeData> frameTimes;
150     constexpr auto kExpectedFps = 50_Hz;
151     constexpr auto kExpectedPeriod = kExpectedFps.getPeriodNsecs();
152     constexpr auto kSmallPeriod = (250_Hz).getPeriodNsecs();
153     constexpr int kNumIterations = 10;
154     for (int i = 1; i <= kNumIterations; i++) {
155         frameTimes.push_back(FrameTimeData{.presentTime = kExpectedPeriod * i,
156                                            .queueTime = 0,
157                                            .pendingModeChange = false});
158 
159         // A duplicate frame
160         frameTimes.push_back(FrameTimeData{.presentTime = kExpectedPeriod * i + kSmallPeriod,
161                                            .queueTime = 0,
162                                            .pendingModeChange = false});
163     }
164     setFrameTimes(frameTimes);
165     const auto averageFrameTime = calculateAverageFrameTime();
166     ASSERT_TRUE(averageFrameTime.has_value());
167     ASSERT_EQ(kExpectedFps, Fps::fromPeriodNsecs(*averageFrameTime));
168 }
169 
170 // There may be a big period of time between two frames. Make sure that
171 // this doesn't influence the calculated average FPS.
TEST_F(LayerInfoTest,ignoresLargePeriods)172 TEST_F(LayerInfoTest, ignoresLargePeriods) {
173     std::deque<FrameTimeData> frameTimes;
174     constexpr auto kExpectedFps = 50_Hz;
175     constexpr auto kExpectedPeriod = kExpectedFps.getPeriodNsecs();
176     constexpr auto kLargePeriod = (9_Hz).getPeriodNsecs();
177 
178     auto record = [&](nsecs_t time) {
179         frameTimes.push_back(
180                 FrameTimeData{.presentTime = time, .queueTime = 0, .pendingModeChange = false});
181     };
182 
183     auto time = kExpectedPeriod; // Start with non-zero time.
184     record(time);
185     time += kLargePeriod;
186     record(time);
187     constexpr int kNumIterations = 10;
188     for (int i = 1; i <= kNumIterations; i++) {
189         time += kExpectedPeriod;
190         record(time);
191     }
192 
193     setFrameTimes(frameTimes);
194     const auto averageFrameTime = calculateAverageFrameTime();
195     ASSERT_TRUE(averageFrameTime.has_value());
196     ASSERT_EQ(kExpectedFps, Fps::fromPeriodNsecs(*averageFrameTime));
197 }
198 
TEST_F(LayerInfoTest,getRefreshRateVote_explicitVote)199 TEST_F(LayerInfoTest, getRefreshRateVote_explicitVote) {
200     LayerInfo::LayerVote vote = {.type = LayerHistory::LayerVoteType::ExplicitDefault,
201                                  .fps = 20_Hz};
202     layerInfo.setLayerVote(vote);
203 
204     auto actualVotes =
205             layerInfo.getRefreshRateVote(*mScheduler->refreshRateSelector(), systemTime());
206     ASSERT_EQ(actualVotes.size(), 1u);
207     ASSERT_EQ(actualVotes[0].type, vote.type);
208     ASSERT_EQ(actualVotes[0].fps, vote.fps);
209     ASSERT_EQ(actualVotes[0].seamlessness, vote.seamlessness);
210     ASSERT_EQ(actualVotes[0].category, vote.category);
211 }
212 
TEST_F(LayerInfoTest,getRefreshRateVote_explicitVoteWithCategory)213 TEST_F(LayerInfoTest, getRefreshRateVote_explicitVoteWithCategory) {
214     LayerInfo::LayerVote vote = {.type = LayerHistory::LayerVoteType::ExplicitDefault,
215                                  .fps = 20_Hz,
216                                  .category = FrameRateCategory::High,
217                                  .categorySmoothSwitchOnly = true};
218     layerInfo.setLayerVote(vote);
219 
220     auto actualVotes =
221             layerInfo.getRefreshRateVote(*mScheduler->refreshRateSelector(), systemTime());
222     ASSERT_EQ(actualVotes.size(), 2u);
223     ASSERT_EQ(actualVotes[0].type, LayerHistory::LayerVoteType::ExplicitCategory);
224     ASSERT_EQ(actualVotes[0].category, vote.category);
225     ASSERT_TRUE(actualVotes[0].categorySmoothSwitchOnly);
226     ASSERT_EQ(actualVotes[1].type, vote.type);
227     ASSERT_EQ(actualVotes[1].fps, vote.fps);
228     ASSERT_EQ(actualVotes[1].seamlessness, vote.seamlessness);
229     ASSERT_EQ(actualVotes[1].category, FrameRateCategory::Default);
230     ASSERT_TRUE(actualVotes[1].categorySmoothSwitchOnly);
231 }
232 
TEST_F(LayerInfoTest,getRefreshRateVote_explicitCategory)233 TEST_F(LayerInfoTest, getRefreshRateVote_explicitCategory) {
234     LayerInfo::LayerVote vote = {.type = LayerHistory::LayerVoteType::ExplicitDefault,
235                                  .category = FrameRateCategory::High};
236     layerInfo.setLayerVote(vote);
237 
238     auto actualVotes =
239             layerInfo.getRefreshRateVote(*mScheduler->refreshRateSelector(), systemTime());
240     ASSERT_EQ(actualVotes.size(), 1u);
241     ASSERT_EQ(actualVotes[0].type, LayerHistory::LayerVoteType::ExplicitCategory);
242     ASSERT_EQ(actualVotes[0].category, vote.category);
243     ASSERT_EQ(actualVotes[0].fps, 0_Hz);
244 }
245 
TEST_F(LayerInfoTest,getRefreshRateVote_categoryNoPreference)246 TEST_F(LayerInfoTest, getRefreshRateVote_categoryNoPreference) {
247     LayerInfo::LayerVote vote = {.type = LayerHistory::LayerVoteType::ExplicitDefault,
248                                  .category = FrameRateCategory::NoPreference};
249     layerInfo.setLayerVote(vote);
250 
251     auto actualVotes =
252             layerInfo.getRefreshRateVote(*mScheduler->refreshRateSelector(), systemTime());
253     ASSERT_EQ(actualVotes.size(), 1u);
254     ASSERT_EQ(actualVotes[0].type, LayerHistory::LayerVoteType::ExplicitCategory);
255     ASSERT_EQ(actualVotes[0].category, vote.category);
256     ASSERT_EQ(actualVotes[0].fps, 0_Hz);
257 }
258 
TEST_F(LayerInfoTest,getRefreshRateVote_noData)259 TEST_F(LayerInfoTest, getRefreshRateVote_noData) {
260     LayerInfo::LayerVote vote = {
261             .type = LayerHistory::LayerVoteType::Heuristic,
262     };
263     layerInfo.setLayerVote(vote);
264 
265     auto actualVotes =
266             layerInfo.getRefreshRateVote(*mScheduler->refreshRateSelector(), systemTime());
267     ASSERT_EQ(actualVotes.size(), 1u);
268     ASSERT_EQ(actualVotes[0].type, LayerHistory::LayerVoteType::Max);
269     ASSERT_EQ(actualVotes[0].fps, vote.fps);
270 }
271 
TEST_F(LayerInfoTest,isFrontBuffered)272 TEST_F(LayerInfoTest, isFrontBuffered) {
273     SET_FLAG_FOR_TEST(flags::vrr_config, true);
274     ASSERT_FALSE(layerInfo.isFrontBuffered());
275 
276     LayerProps prop = {.isFrontBuffered = true};
277     layerInfo.setLastPresentTime(0, 0, LayerHistory::LayerUpdateType::Buffer, true, prop);
278     ASSERT_TRUE(layerInfo.isFrontBuffered());
279 
280     prop.isFrontBuffered = false;
281     layerInfo.setLastPresentTime(0, 0, LayerHistory::LayerUpdateType::Buffer, true, prop);
282     ASSERT_FALSE(layerInfo.isFrontBuffered());
283 }
284 
285 } // namespace
286 } // namespace android::scheduler
287