blob: 830dcced6c946150e40c1a396b69ffa4470c6cb4 [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
Dominik Laskowski6eab42d2021-09-13 14:34:13 -070024#include "FpsOps.h"
Marin Shalamanov2045d5b2020-12-28 18:11:41 +010025#include "Scheduler/LayerHistory.h"
26#include "Scheduler/LayerInfo.h"
Rachel Leece6e0042023-06-27 11:22:54 -070027#include "TestableScheduler.h"
28#include "TestableSurfaceFlinger.h"
29#include "mock/MockSchedulerCallback.h"
Marin Shalamanov2045d5b2020-12-28 18:11:41 +010030
31namespace android::scheduler {
32
Rachel Leece6e0042023-06-27 11:22:54 -070033using android::mock::createDisplayMode;
34
Marin Shalamanov2045d5b2020-12-28 18:11:41 +010035class LayerInfoTest : public testing::Test {
36protected:
37 using FrameTimeData = LayerInfo::FrameTimeData;
38
Rachel Leece6e0042023-06-27 11:22:54 -070039 static constexpr Fps LO_FPS = 30_Hz;
40 static constexpr Fps HI_FPS = 90_Hz;
41
42 LayerInfoTest() { mFlinger.resetScheduler(mScheduler); }
43
Marin Shalamanov2045d5b2020-12-28 18:11:41 +010044 void setFrameTimes(const std::deque<FrameTimeData>& frameTimes) {
45 layerInfo.mFrameTimes = frameTimes;
46 }
47
48 void setLastRefreshRate(Fps fps) {
49 layerInfo.mLastRefreshRate.reported = fps;
50 layerInfo.mLastRefreshRate.calculated = fps;
51 }
52
53 auto calculateAverageFrameTime() { return layerInfo.calculateAverageFrameTime(); }
54
Ady Abrahambdda8f02021-04-01 16:06:11 -070055 LayerInfo layerInfo{"TestLayerInfo", 0, LayerHistory::LayerVoteType::Heuristic};
Rachel Leece6e0042023-06-27 11:22:54 -070056
57 std::shared_ptr<RefreshRateSelector> mSelector =
58 std::make_shared<RefreshRateSelector>(makeModes(createDisplayMode(DisplayModeId(0),
59 LO_FPS),
60 createDisplayMode(DisplayModeId(1),
61 HI_FPS)),
62 DisplayModeId(0));
63 mock::SchedulerCallback mSchedulerCallback;
ramindanid4354a92023-10-02 15:11:09 -070064 mock::VsyncTrackerCallback mVsyncTrackerCallback;
65 TestableScheduler* mScheduler =
66 new TestableScheduler(mSelector, mSchedulerCallback, mVsyncTrackerCallback);
Rachel Leece6e0042023-06-27 11:22:54 -070067 TestableSurfaceFlinger mFlinger;
Marin Shalamanov2045d5b2020-12-28 18:11:41 +010068};
69
70namespace {
71
72TEST_F(LayerInfoTest, prefersPresentTime) {
73 std::deque<FrameTimeData> frameTimes;
Dominik Laskowski6eab42d2021-09-13 14:34:13 -070074 constexpr auto kExpectedFps = 50_Hz;
Marin Shalamanov2045d5b2020-12-28 18:11:41 +010075 constexpr auto kPeriod = kExpectedFps.getPeriodNsecs();
76 constexpr int kNumFrames = 10;
77 for (int i = 1; i <= kNumFrames; i++) {
78 frameTimes.push_back(FrameTimeData{.presentTime = kPeriod * i,
79 .queueTime = 0,
Marin Shalamanova7fe3042021-01-29 21:02:08 +010080 .pendingModeChange = false});
Marin Shalamanov2045d5b2020-12-28 18:11:41 +010081 }
82 setFrameTimes(frameTimes);
83 const auto averageFrameTime = calculateAverageFrameTime();
84 ASSERT_TRUE(averageFrameTime.has_value());
Dominik Laskowski6eab42d2021-09-13 14:34:13 -070085 ASSERT_EQ(kExpectedFps, Fps::fromPeriodNsecs(*averageFrameTime));
Marin Shalamanov2045d5b2020-12-28 18:11:41 +010086}
87
88TEST_F(LayerInfoTest, fallbacksToQueueTimeIfNoPresentTime) {
89 std::deque<FrameTimeData> frameTimes;
Dominik Laskowski6eab42d2021-09-13 14:34:13 -070090 constexpr auto kExpectedFps = 50_Hz;
Marin Shalamanov2045d5b2020-12-28 18:11:41 +010091 constexpr auto kPeriod = kExpectedFps.getPeriodNsecs();
92 constexpr int kNumFrames = 10;
93 for (int i = 1; i <= kNumFrames; i++) {
94 frameTimes.push_back(FrameTimeData{.presentTime = 0,
95 .queueTime = kPeriod * i,
Marin Shalamanova7fe3042021-01-29 21:02:08 +010096 .pendingModeChange = false});
Marin Shalamanov2045d5b2020-12-28 18:11:41 +010097 }
98 setFrameTimes(frameTimes);
Dominik Laskowski6eab42d2021-09-13 14:34:13 -070099 setLastRefreshRate(20_Hz); // Set to some valid value.
Marin Shalamanov2045d5b2020-12-28 18:11:41 +0100100 const auto averageFrameTime = calculateAverageFrameTime();
101 ASSERT_TRUE(averageFrameTime.has_value());
Dominik Laskowski6eab42d2021-09-13 14:34:13 -0700102 ASSERT_EQ(kExpectedFps, Fps::fromPeriodNsecs(*averageFrameTime));
Marin Shalamanov2045d5b2020-12-28 18:11:41 +0100103}
104
105TEST_F(LayerInfoTest, returnsNulloptIfThereWasConfigChange) {
106 std::deque<FrameTimeData> frameTimesWithoutConfigChange;
Dominik Laskowski6eab42d2021-09-13 14:34:13 -0700107 const auto period = (50_Hz).getPeriodNsecs();
Marin Shalamanov2045d5b2020-12-28 18:11:41 +0100108 constexpr int kNumFrames = 10;
109 for (int i = 1; i <= kNumFrames; i++) {
110 frameTimesWithoutConfigChange.push_back(FrameTimeData{.presentTime = period * i,
111 .queueTime = period * i,
Marin Shalamanova7fe3042021-01-29 21:02:08 +0100112 .pendingModeChange = false});
Marin Shalamanov2045d5b2020-12-28 18:11:41 +0100113 }
114
115 setFrameTimes(frameTimesWithoutConfigChange);
116 ASSERT_TRUE(calculateAverageFrameTime().has_value());
117
118 {
119 // Config change in the first record
120 auto frameTimes = frameTimesWithoutConfigChange;
Marin Shalamanova7fe3042021-01-29 21:02:08 +0100121 frameTimes[0].pendingModeChange = true;
Marin Shalamanov2045d5b2020-12-28 18:11:41 +0100122 setFrameTimes(frameTimes);
123 ASSERT_FALSE(calculateAverageFrameTime().has_value());
124 }
125
126 {
127 // Config change in the last record
128 auto frameTimes = frameTimesWithoutConfigChange;
Marin Shalamanova7fe3042021-01-29 21:02:08 +0100129 frameTimes[frameTimes.size() - 1].pendingModeChange = true;
Marin Shalamanov2045d5b2020-12-28 18:11:41 +0100130 setFrameTimes(frameTimes);
131 ASSERT_FALSE(calculateAverageFrameTime().has_value());
132 }
133
134 {
135 // Config change in the middle
136 auto frameTimes = frameTimesWithoutConfigChange;
Marin Shalamanova7fe3042021-01-29 21:02:08 +0100137 frameTimes[frameTimes.size() / 2].pendingModeChange = true;
Marin Shalamanov2045d5b2020-12-28 18:11:41 +0100138 setFrameTimes(frameTimes);
139 ASSERT_FALSE(calculateAverageFrameTime().has_value());
140 }
141}
142
143// A frame can be recorded twice with very close presentation or queue times.
144// Make sure that this doesn't influence the calculated average FPS.
145TEST_F(LayerInfoTest, ignoresSmallPeriods) {
146 std::deque<FrameTimeData> frameTimes;
Dominik Laskowski6eab42d2021-09-13 14:34:13 -0700147 constexpr auto kExpectedFps = 50_Hz;
Marin Shalamanov2045d5b2020-12-28 18:11:41 +0100148 constexpr auto kExpectedPeriod = kExpectedFps.getPeriodNsecs();
Dominik Laskowski6eab42d2021-09-13 14:34:13 -0700149 constexpr auto kSmallPeriod = (250_Hz).getPeriodNsecs();
Marin Shalamanov2045d5b2020-12-28 18:11:41 +0100150 constexpr int kNumIterations = 10;
151 for (int i = 1; i <= kNumIterations; i++) {
152 frameTimes.push_back(FrameTimeData{.presentTime = kExpectedPeriod * i,
153 .queueTime = 0,
Marin Shalamanova7fe3042021-01-29 21:02:08 +0100154 .pendingModeChange = false});
Marin Shalamanov2045d5b2020-12-28 18:11:41 +0100155
156 // A duplicate frame
157 frameTimes.push_back(FrameTimeData{.presentTime = kExpectedPeriod * i + kSmallPeriod,
158 .queueTime = 0,
Marin Shalamanova7fe3042021-01-29 21:02:08 +0100159 .pendingModeChange = false});
Marin Shalamanov2045d5b2020-12-28 18:11:41 +0100160 }
161 setFrameTimes(frameTimes);
162 const auto averageFrameTime = calculateAverageFrameTime();
163 ASSERT_TRUE(averageFrameTime.has_value());
Dominik Laskowski6eab42d2021-09-13 14:34:13 -0700164 ASSERT_EQ(kExpectedFps, Fps::fromPeriodNsecs(*averageFrameTime));
Marin Shalamanov2045d5b2020-12-28 18:11:41 +0100165}
166
167// There may be a big period of time between two frames. Make sure that
168// this doesn't influence the calculated average FPS.
169TEST_F(LayerInfoTest, ignoresLargePeriods) {
170 std::deque<FrameTimeData> frameTimes;
Dominik Laskowski6eab42d2021-09-13 14:34:13 -0700171 constexpr auto kExpectedFps = 50_Hz;
Marin Shalamanov2045d5b2020-12-28 18:11:41 +0100172 constexpr auto kExpectedPeriod = kExpectedFps.getPeriodNsecs();
Dominik Laskowski6eab42d2021-09-13 14:34:13 -0700173 constexpr auto kLargePeriod = (9_Hz).getPeriodNsecs();
Marin Shalamanov2045d5b2020-12-28 18:11:41 +0100174
175 auto record = [&](nsecs_t time) {
176 frameTimes.push_back(
Marin Shalamanova7fe3042021-01-29 21:02:08 +0100177 FrameTimeData{.presentTime = time, .queueTime = 0, .pendingModeChange = false});
Marin Shalamanov2045d5b2020-12-28 18:11:41 +0100178 };
179
180 auto time = kExpectedPeriod; // Start with non-zero time.
181 record(time);
182 time += kLargePeriod;
183 record(time);
184 constexpr int kNumIterations = 10;
185 for (int i = 1; i <= kNumIterations; i++) {
186 time += kExpectedPeriod;
187 record(time);
188 }
189
190 setFrameTimes(frameTimes);
191 const auto averageFrameTime = calculateAverageFrameTime();
192 ASSERT_TRUE(averageFrameTime.has_value());
Dominik Laskowski6eab42d2021-09-13 14:34:13 -0700193 ASSERT_EQ(kExpectedFps, Fps::fromPeriodNsecs(*averageFrameTime));
Marin Shalamanov2045d5b2020-12-28 18:11:41 +0100194}
195
Rachel Leece6e0042023-06-27 11:22:54 -0700196TEST_F(LayerInfoTest, getRefreshRateVote_explicitVote) {
197 LayerInfo::LayerVote vote = {.type = LayerHistory::LayerVoteType::ExplicitDefault,
198 .fps = 20_Hz};
199 layerInfo.setLayerVote(vote);
200
201 auto actualVotes =
202 layerInfo.getRefreshRateVote(*mScheduler->refreshRateSelector(), systemTime());
203 ASSERT_EQ(actualVotes.size(), 1u);
204 ASSERT_EQ(actualVotes[0].type, vote.type);
205 ASSERT_EQ(actualVotes[0].fps, vote.fps);
206 ASSERT_EQ(actualVotes[0].seamlessness, vote.seamlessness);
207 ASSERT_EQ(actualVotes[0].category, vote.category);
208}
209
210TEST_F(LayerInfoTest, getRefreshRateVote_explicitVoteWithCategory) {
211 LayerInfo::LayerVote vote = {.type = LayerHistory::LayerVoteType::ExplicitDefault,
212 .fps = 20_Hz,
213 .category = FrameRateCategory::High};
214 layerInfo.setLayerVote(vote);
215
216 auto actualVotes =
217 layerInfo.getRefreshRateVote(*mScheduler->refreshRateSelector(), systemTime());
218 ASSERT_EQ(actualVotes.size(), 2u);
219 ASSERT_EQ(actualVotes[0].type, LayerHistory::LayerVoteType::ExplicitCategory);
220 ASSERT_EQ(actualVotes[0].category, vote.category);
221 ASSERT_EQ(actualVotes[1].type, vote.type);
222 ASSERT_EQ(actualVotes[1].fps, vote.fps);
223 ASSERT_EQ(actualVotes[1].seamlessness, vote.seamlessness);
224 ASSERT_EQ(actualVotes[1].category, vote.category);
225}
226
227TEST_F(LayerInfoTest, getRefreshRateVote_explicitCategory) {
Rachel Leece6e0042023-06-27 11:22:54 -0700228 LayerInfo::LayerVote vote = {.type = LayerHistory::LayerVoteType::ExplicitDefault,
229 .category = FrameRateCategory::High};
230 layerInfo.setLayerVote(vote);
231
232 auto actualVotes =
233 layerInfo.getRefreshRateVote(*mScheduler->refreshRateSelector(), systemTime());
234 ASSERT_EQ(actualVotes.size(), 1u);
235 ASSERT_EQ(actualVotes[0].type, LayerHistory::LayerVoteType::ExplicitCategory);
236 ASSERT_EQ(actualVotes[0].category, vote.category);
Rachel Leef377b362023-09-06 15:01:06 -0700237 ASSERT_EQ(actualVotes[0].fps, 0_Hz);
238}
239
240TEST_F(LayerInfoTest, getRefreshRateVote_categoryNoPreference) {
241 LayerInfo::LayerVote vote = {.type = LayerHistory::LayerVoteType::ExplicitDefault,
242 .category = FrameRateCategory::NoPreference};
243 layerInfo.setLayerVote(vote);
244
245 auto actualVotes =
246 layerInfo.getRefreshRateVote(*mScheduler->refreshRateSelector(), systemTime());
247 ASSERT_EQ(actualVotes.size(), 1u);
248 ASSERT_EQ(actualVotes[0].type, LayerHistory::LayerVoteType::ExplicitCategory);
249 ASSERT_EQ(actualVotes[0].category, vote.category);
250 ASSERT_EQ(actualVotes[0].fps, 0_Hz);
Rachel Leece6e0042023-06-27 11:22:54 -0700251}
252
253TEST_F(LayerInfoTest, getRefreshRateVote_noData) {
254 LayerInfo::LayerVote vote = {
255 .type = LayerHistory::LayerVoteType::Heuristic,
256 };
257 layerInfo.setLayerVote(vote);
258
259 auto actualVotes =
260 layerInfo.getRefreshRateVote(*mScheduler->refreshRateSelector(), systemTime());
261 ASSERT_EQ(actualVotes.size(), 1u);
262 ASSERT_EQ(actualVotes[0].type, LayerHistory::LayerVoteType::Max);
263 ASSERT_EQ(actualVotes[0].fps, vote.fps);
264}
265
Marin Shalamanov2045d5b2020-12-28 18:11:41 +0100266} // namespace
267} // namespace android::scheduler