blob: 22cfbd8d8acd8fe4798c59efc99457f2e2aedcb3 [file] [log] [blame]
Marin Shalamanov2045d5b2020-12-28 18:11:41 +01001/*
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
Dominik Laskowskif6b4ba62021-11-09 12:46:10 -080022#include <scheduler/Fps.h>
23
Ady Abraham3db8a3c2023-11-20 17:53:47 -080024#include <common/test/FlagUtils.h>
Dominik Laskowski6eab42d2021-09-13 14:34:13 -070025#include "FpsOps.h"
Marin Shalamanov2045d5b2020-12-28 18:11:41 +010026#include "Scheduler/LayerHistory.h"
27#include "Scheduler/LayerInfo.h"
Rachel Leece6e0042023-06-27 11:22:54 -070028#include "TestableScheduler.h"
29#include "TestableSurfaceFlinger.h"
30#include "mock/MockSchedulerCallback.h"
Marin Shalamanov2045d5b2020-12-28 18:11:41 +010031
Alec Mouri89f5d4e2023-10-20 17:12:49 +000032#include <com_android_graphics_surfaceflinger_flags.h>
33
Marin Shalamanov2045d5b2020-12-28 18:11:41 +010034namespace android::scheduler {
35
Rachel Leece6e0042023-06-27 11:22:54 -070036using android::mock::createDisplayMode;
37
Marin Shalamanov2045d5b2020-12-28 18:11:41 +010038class LayerInfoTest : public testing::Test {
39protected:
40 using FrameTimeData = LayerInfo::FrameTimeData;
41
Rachel Leece6e0042023-06-27 11:22:54 -070042 static constexpr Fps LO_FPS = 30_Hz;
43 static constexpr Fps HI_FPS = 90_Hz;
44
45 LayerInfoTest() { mFlinger.resetScheduler(mScheduler); }
46
Marin Shalamanov2045d5b2020-12-28 18:11:41 +010047 void setFrameTimes(const std::deque<FrameTimeData>& frameTimes) {
48 layerInfo.mFrameTimes = frameTimes;
49 }
50
51 void setLastRefreshRate(Fps fps) {
52 layerInfo.mLastRefreshRate.reported = fps;
53 layerInfo.mLastRefreshRate.calculated = fps;
54 }
55
56 auto calculateAverageFrameTime() { return layerInfo.calculateAverageFrameTime(); }
57
Ady Abrahambdda8f02021-04-01 16:06:11 -070058 LayerInfo layerInfo{"TestLayerInfo", 0, LayerHistory::LayerVoteType::Heuristic};
Rachel Leece6e0042023-06-27 11:22:54 -070059
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;
ramindanid4354a92023-10-02 15:11:09 -070067 mock::VsyncTrackerCallback mVsyncTrackerCallback;
Rachel Leece6e0042023-06-27 11:22:54 -070068 TestableSurfaceFlinger mFlinger;
Leon Scroggins III823d4ca2023-12-12 16:57:34 -050069 TestableScheduler* mScheduler =
70 new TestableScheduler(mSelector, mFlinger, mSchedulerCallback, mVsyncTrackerCallback);
Marin Shalamanov2045d5b2020-12-28 18:11:41 +010071};
72
73namespace {
74
Alec Mouri89f5d4e2023-10-20 17:12:49 +000075using namespace com::android::graphics::surfaceflinger;
76
Marin Shalamanov2045d5b2020-12-28 18:11:41 +010077TEST_F(LayerInfoTest, prefersPresentTime) {
78 std::deque<FrameTimeData> frameTimes;
Dominik Laskowski6eab42d2021-09-13 14:34:13 -070079 constexpr auto kExpectedFps = 50_Hz;
Marin Shalamanov2045d5b2020-12-28 18:11:41 +010080 constexpr auto kPeriod = kExpectedFps.getPeriodNsecs();
81 constexpr int kNumFrames = 10;
82 for (int i = 1; i <= kNumFrames; i++) {
83 frameTimes.push_back(FrameTimeData{.presentTime = kPeriod * i,
84 .queueTime = 0,
Marin Shalamanova7fe3042021-01-29 21:02:08 +010085 .pendingModeChange = false});
Marin Shalamanov2045d5b2020-12-28 18:11:41 +010086 }
87 setFrameTimes(frameTimes);
88 const auto averageFrameTime = calculateAverageFrameTime();
89 ASSERT_TRUE(averageFrameTime.has_value());
Dominik Laskowski6eab42d2021-09-13 14:34:13 -070090 ASSERT_EQ(kExpectedFps, Fps::fromPeriodNsecs(*averageFrameTime));
Marin Shalamanov2045d5b2020-12-28 18:11:41 +010091}
92
93TEST_F(LayerInfoTest, fallbacksToQueueTimeIfNoPresentTime) {
94 std::deque<FrameTimeData> frameTimes;
Dominik Laskowski6eab42d2021-09-13 14:34:13 -070095 constexpr auto kExpectedFps = 50_Hz;
Marin Shalamanov2045d5b2020-12-28 18:11:41 +010096 constexpr auto kPeriod = kExpectedFps.getPeriodNsecs();
97 constexpr int kNumFrames = 10;
98 for (int i = 1; i <= kNumFrames; i++) {
99 frameTimes.push_back(FrameTimeData{.presentTime = 0,
100 .queueTime = kPeriod * i,
Marin Shalamanova7fe3042021-01-29 21:02:08 +0100101 .pendingModeChange = false});
Marin Shalamanov2045d5b2020-12-28 18:11:41 +0100102 }
103 setFrameTimes(frameTimes);
Dominik Laskowski6eab42d2021-09-13 14:34:13 -0700104 setLastRefreshRate(20_Hz); // Set to some valid value.
Marin Shalamanov2045d5b2020-12-28 18:11:41 +0100105 const auto averageFrameTime = calculateAverageFrameTime();
106 ASSERT_TRUE(averageFrameTime.has_value());
Dominik Laskowski6eab42d2021-09-13 14:34:13 -0700107 ASSERT_EQ(kExpectedFps, Fps::fromPeriodNsecs(*averageFrameTime));
Marin Shalamanov2045d5b2020-12-28 18:11:41 +0100108}
109
110TEST_F(LayerInfoTest, returnsNulloptIfThereWasConfigChange) {
111 std::deque<FrameTimeData> frameTimesWithoutConfigChange;
Dominik Laskowski6eab42d2021-09-13 14:34:13 -0700112 const auto period = (50_Hz).getPeriodNsecs();
Marin Shalamanov2045d5b2020-12-28 18:11:41 +0100113 constexpr int kNumFrames = 10;
114 for (int i = 1; i <= kNumFrames; i++) {
115 frameTimesWithoutConfigChange.push_back(FrameTimeData{.presentTime = period * i,
116 .queueTime = period * i,
Marin Shalamanova7fe3042021-01-29 21:02:08 +0100117 .pendingModeChange = false});
Marin Shalamanov2045d5b2020-12-28 18:11:41 +0100118 }
119
120 setFrameTimes(frameTimesWithoutConfigChange);
121 ASSERT_TRUE(calculateAverageFrameTime().has_value());
122
123 {
124 // Config change in the first record
125 auto frameTimes = frameTimesWithoutConfigChange;
Marin Shalamanova7fe3042021-01-29 21:02:08 +0100126 frameTimes[0].pendingModeChange = true;
Marin Shalamanov2045d5b2020-12-28 18:11:41 +0100127 setFrameTimes(frameTimes);
128 ASSERT_FALSE(calculateAverageFrameTime().has_value());
129 }
130
131 {
132 // Config change in the last record
133 auto frameTimes = frameTimesWithoutConfigChange;
Marin Shalamanova7fe3042021-01-29 21:02:08 +0100134 frameTimes[frameTimes.size() - 1].pendingModeChange = true;
Marin Shalamanov2045d5b2020-12-28 18:11:41 +0100135 setFrameTimes(frameTimes);
136 ASSERT_FALSE(calculateAverageFrameTime().has_value());
137 }
138
139 {
140 // Config change in the middle
141 auto frameTimes = frameTimesWithoutConfigChange;
Marin Shalamanova7fe3042021-01-29 21:02:08 +0100142 frameTimes[frameTimes.size() / 2].pendingModeChange = true;
Marin Shalamanov2045d5b2020-12-28 18:11:41 +0100143 setFrameTimes(frameTimes);
144 ASSERT_FALSE(calculateAverageFrameTime().has_value());
145 }
146}
147
148// A frame can be recorded twice with very close presentation or queue times.
149// Make sure that this doesn't influence the calculated average FPS.
150TEST_F(LayerInfoTest, ignoresSmallPeriods) {
151 std::deque<FrameTimeData> frameTimes;
Dominik Laskowski6eab42d2021-09-13 14:34:13 -0700152 constexpr auto kExpectedFps = 50_Hz;
Marin Shalamanov2045d5b2020-12-28 18:11:41 +0100153 constexpr auto kExpectedPeriod = kExpectedFps.getPeriodNsecs();
Dominik Laskowski6eab42d2021-09-13 14:34:13 -0700154 constexpr auto kSmallPeriod = (250_Hz).getPeriodNsecs();
Marin Shalamanov2045d5b2020-12-28 18:11:41 +0100155 constexpr int kNumIterations = 10;
156 for (int i = 1; i <= kNumIterations; i++) {
157 frameTimes.push_back(FrameTimeData{.presentTime = kExpectedPeriod * i,
158 .queueTime = 0,
Marin Shalamanova7fe3042021-01-29 21:02:08 +0100159 .pendingModeChange = false});
Marin Shalamanov2045d5b2020-12-28 18:11:41 +0100160
161 // A duplicate frame
162 frameTimes.push_back(FrameTimeData{.presentTime = kExpectedPeriod * i + kSmallPeriod,
163 .queueTime = 0,
Marin Shalamanova7fe3042021-01-29 21:02:08 +0100164 .pendingModeChange = false});
Marin Shalamanov2045d5b2020-12-28 18:11:41 +0100165 }
166 setFrameTimes(frameTimes);
167 const auto averageFrameTime = calculateAverageFrameTime();
168 ASSERT_TRUE(averageFrameTime.has_value());
Dominik Laskowski6eab42d2021-09-13 14:34:13 -0700169 ASSERT_EQ(kExpectedFps, Fps::fromPeriodNsecs(*averageFrameTime));
Marin Shalamanov2045d5b2020-12-28 18:11:41 +0100170}
171
172// There may be a big period of time between two frames. Make sure that
173// this doesn't influence the calculated average FPS.
174TEST_F(LayerInfoTest, ignoresLargePeriods) {
175 std::deque<FrameTimeData> frameTimes;
Dominik Laskowski6eab42d2021-09-13 14:34:13 -0700176 constexpr auto kExpectedFps = 50_Hz;
Marin Shalamanov2045d5b2020-12-28 18:11:41 +0100177 constexpr auto kExpectedPeriod = kExpectedFps.getPeriodNsecs();
Dominik Laskowski6eab42d2021-09-13 14:34:13 -0700178 constexpr auto kLargePeriod = (9_Hz).getPeriodNsecs();
Marin Shalamanov2045d5b2020-12-28 18:11:41 +0100179
180 auto record = [&](nsecs_t time) {
181 frameTimes.push_back(
Marin Shalamanova7fe3042021-01-29 21:02:08 +0100182 FrameTimeData{.presentTime = time, .queueTime = 0, .pendingModeChange = false});
Marin Shalamanov2045d5b2020-12-28 18:11:41 +0100183 };
184
185 auto time = kExpectedPeriod; // Start with non-zero time.
186 record(time);
187 time += kLargePeriod;
188 record(time);
189 constexpr int kNumIterations = 10;
190 for (int i = 1; i <= kNumIterations; i++) {
191 time += kExpectedPeriod;
192 record(time);
193 }
194
195 setFrameTimes(frameTimes);
196 const auto averageFrameTime = calculateAverageFrameTime();
197 ASSERT_TRUE(averageFrameTime.has_value());
Dominik Laskowski6eab42d2021-09-13 14:34:13 -0700198 ASSERT_EQ(kExpectedFps, Fps::fromPeriodNsecs(*averageFrameTime));
Marin Shalamanov2045d5b2020-12-28 18:11:41 +0100199}
200
Rachel Leece6e0042023-06-27 11:22:54 -0700201TEST_F(LayerInfoTest, getRefreshRateVote_explicitVote) {
202 LayerInfo::LayerVote vote = {.type = LayerHistory::LayerVoteType::ExplicitDefault,
203 .fps = 20_Hz};
204 layerInfo.setLayerVote(vote);
205
206 auto actualVotes =
207 layerInfo.getRefreshRateVote(*mScheduler->refreshRateSelector(), systemTime());
208 ASSERT_EQ(actualVotes.size(), 1u);
209 ASSERT_EQ(actualVotes[0].type, vote.type);
210 ASSERT_EQ(actualVotes[0].fps, vote.fps);
211 ASSERT_EQ(actualVotes[0].seamlessness, vote.seamlessness);
212 ASSERT_EQ(actualVotes[0].category, vote.category);
213}
214
215TEST_F(LayerInfoTest, getRefreshRateVote_explicitVoteWithCategory) {
216 LayerInfo::LayerVote vote = {.type = LayerHistory::LayerVoteType::ExplicitDefault,
217 .fps = 20_Hz,
218 .category = FrameRateCategory::High};
219 layerInfo.setLayerVote(vote);
220
221 auto actualVotes =
222 layerInfo.getRefreshRateVote(*mScheduler->refreshRateSelector(), systemTime());
223 ASSERT_EQ(actualVotes.size(), 2u);
224 ASSERT_EQ(actualVotes[0].type, LayerHistory::LayerVoteType::ExplicitCategory);
225 ASSERT_EQ(actualVotes[0].category, vote.category);
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, vote.category);
230}
231
232TEST_F(LayerInfoTest, getRefreshRateVote_explicitCategory) {
Rachel Leece6e0042023-06-27 11:22:54 -0700233 LayerInfo::LayerVote vote = {.type = LayerHistory::LayerVoteType::ExplicitDefault,
234 .category = FrameRateCategory::High};
235 layerInfo.setLayerVote(vote);
236
237 auto actualVotes =
238 layerInfo.getRefreshRateVote(*mScheduler->refreshRateSelector(), systemTime());
239 ASSERT_EQ(actualVotes.size(), 1u);
240 ASSERT_EQ(actualVotes[0].type, LayerHistory::LayerVoteType::ExplicitCategory);
241 ASSERT_EQ(actualVotes[0].category, vote.category);
Rachel Leef377b362023-09-06 15:01:06 -0700242 ASSERT_EQ(actualVotes[0].fps, 0_Hz);
243}
244
245TEST_F(LayerInfoTest, getRefreshRateVote_categoryNoPreference) {
246 LayerInfo::LayerVote vote = {.type = LayerHistory::LayerVoteType::ExplicitDefault,
247 .category = FrameRateCategory::NoPreference};
248 layerInfo.setLayerVote(vote);
249
250 auto actualVotes =
251 layerInfo.getRefreshRateVote(*mScheduler->refreshRateSelector(), systemTime());
252 ASSERT_EQ(actualVotes.size(), 1u);
253 ASSERT_EQ(actualVotes[0].type, LayerHistory::LayerVoteType::ExplicitCategory);
254 ASSERT_EQ(actualVotes[0].category, vote.category);
255 ASSERT_EQ(actualVotes[0].fps, 0_Hz);
Rachel Leece6e0042023-06-27 11:22:54 -0700256}
257
258TEST_F(LayerInfoTest, getRefreshRateVote_noData) {
259 LayerInfo::LayerVote vote = {
260 .type = LayerHistory::LayerVoteType::Heuristic,
261 };
262 layerInfo.setLayerVote(vote);
263
264 auto actualVotes =
265 layerInfo.getRefreshRateVote(*mScheduler->refreshRateSelector(), systemTime());
266 ASSERT_EQ(actualVotes.size(), 1u);
267 ASSERT_EQ(actualVotes[0].type, LayerHistory::LayerVoteType::Max);
268 ASSERT_EQ(actualVotes[0].fps, vote.fps);
269}
270
Alec Mouri89f5d4e2023-10-20 17:12:49 +0000271TEST_F(LayerInfoTest, isFrontBuffered) {
272 SET_FLAG_FOR_TEST(flags::vrr_config, true);
273 ASSERT_FALSE(layerInfo.isFrontBuffered());
274
275 LayerProps prop = {.isFrontBuffered = true};
276 layerInfo.setLastPresentTime(0, 0, LayerHistory::LayerUpdateType::Buffer, true, prop);
277 ASSERT_TRUE(layerInfo.isFrontBuffered());
278
279 prop.isFrontBuffered = false;
280 layerInfo.setLastPresentTime(0, 0, LayerHistory::LayerUpdateType::Buffer, true, prop);
281 ASSERT_FALSE(layerInfo.isFrontBuffered());
282}
283
Marin Shalamanov2045d5b2020-12-28 18:11:41 +0100284} // namespace
285} // namespace android::scheduler