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 "Fps.h"
23 #include "Scheduler/LayerHistory.h"
24 #include "Scheduler/LayerInfo.h"
25
26 namespace android::scheduler {
27
28 class LayerInfoTest : public testing::Test {
29 protected:
30 using FrameTimeData = LayerInfo::FrameTimeData;
31
setFrameTimes(const std::deque<FrameTimeData> & frameTimes)32 void setFrameTimes(const std::deque<FrameTimeData>& frameTimes) {
33 layerInfo.mFrameTimes = frameTimes;
34 }
35
setLastRefreshRate(Fps fps)36 void setLastRefreshRate(Fps fps) {
37 layerInfo.mLastRefreshRate.reported = fps;
38 layerInfo.mLastRefreshRate.calculated = fps;
39 }
40
calculateAverageFrameTime()41 auto calculateAverageFrameTime() { return layerInfo.calculateAverageFrameTime(); }
42
43 LayerInfo layerInfo{"TestLayerInfo", 0, LayerHistory::LayerVoteType::Heuristic};
44 };
45
46 namespace {
47
TEST_F(LayerInfoTest,prefersPresentTime)48 TEST_F(LayerInfoTest, prefersPresentTime) {
49 std::deque<FrameTimeData> frameTimes;
50 constexpr auto kExpectedFps = Fps(50.0f);
51 constexpr auto kPeriod = kExpectedFps.getPeriodNsecs();
52 constexpr int kNumFrames = 10;
53 for (int i = 1; i <= kNumFrames; i++) {
54 frameTimes.push_back(FrameTimeData{.presentTime = kPeriod * i,
55 .queueTime = 0,
56 .pendingModeChange = false});
57 }
58 setFrameTimes(frameTimes);
59 const auto averageFrameTime = calculateAverageFrameTime();
60 ASSERT_TRUE(averageFrameTime.has_value());
61 const auto averageFps = Fps::fromPeriodNsecs(*averageFrameTime);
62 ASSERT_TRUE(kExpectedFps.equalsWithMargin(averageFps))
63 << "Expected " << averageFps << " to be equal to " << kExpectedFps;
64 }
65
TEST_F(LayerInfoTest,fallbacksToQueueTimeIfNoPresentTime)66 TEST_F(LayerInfoTest, fallbacksToQueueTimeIfNoPresentTime) {
67 std::deque<FrameTimeData> frameTimes;
68 constexpr auto kExpectedFps = Fps(50.0f);
69 constexpr auto kPeriod = kExpectedFps.getPeriodNsecs();
70 constexpr int kNumFrames = 10;
71 for (int i = 1; i <= kNumFrames; i++) {
72 frameTimes.push_back(FrameTimeData{.presentTime = 0,
73 .queueTime = kPeriod * i,
74 .pendingModeChange = false});
75 }
76 setFrameTimes(frameTimes);
77 setLastRefreshRate(Fps(20.0f)); // Set to some valid value
78 const auto averageFrameTime = calculateAverageFrameTime();
79 ASSERT_TRUE(averageFrameTime.has_value());
80 const auto averageFps = Fps::fromPeriodNsecs(*averageFrameTime);
81 ASSERT_TRUE(kExpectedFps.equalsWithMargin(averageFps))
82 << "Expected " << averageFps << " to be equal to " << kExpectedFps;
83 }
84
TEST_F(LayerInfoTest,returnsNulloptIfThereWasConfigChange)85 TEST_F(LayerInfoTest, returnsNulloptIfThereWasConfigChange) {
86 std::deque<FrameTimeData> frameTimesWithoutConfigChange;
87 const auto period = Fps(50.0f).getPeriodNsecs();
88 constexpr int kNumFrames = 10;
89 for (int i = 1; i <= kNumFrames; i++) {
90 frameTimesWithoutConfigChange.push_back(FrameTimeData{.presentTime = period * i,
91 .queueTime = period * i,
92 .pendingModeChange = false});
93 }
94
95 setFrameTimes(frameTimesWithoutConfigChange);
96 ASSERT_TRUE(calculateAverageFrameTime().has_value());
97
98 {
99 // Config change in the first record
100 auto frameTimes = frameTimesWithoutConfigChange;
101 frameTimes[0].pendingModeChange = true;
102 setFrameTimes(frameTimes);
103 ASSERT_FALSE(calculateAverageFrameTime().has_value());
104 }
105
106 {
107 // Config change in the last record
108 auto frameTimes = frameTimesWithoutConfigChange;
109 frameTimes[frameTimes.size() - 1].pendingModeChange = true;
110 setFrameTimes(frameTimes);
111 ASSERT_FALSE(calculateAverageFrameTime().has_value());
112 }
113
114 {
115 // Config change in the middle
116 auto frameTimes = frameTimesWithoutConfigChange;
117 frameTimes[frameTimes.size() / 2].pendingModeChange = true;
118 setFrameTimes(frameTimes);
119 ASSERT_FALSE(calculateAverageFrameTime().has_value());
120 }
121 }
122
123 // A frame can be recorded twice with very close presentation or queue times.
124 // Make sure that this doesn't influence the calculated average FPS.
TEST_F(LayerInfoTest,ignoresSmallPeriods)125 TEST_F(LayerInfoTest, ignoresSmallPeriods) {
126 std::deque<FrameTimeData> frameTimes;
127 constexpr auto kExpectedFps = Fps(50.0f);
128 constexpr auto kExpectedPeriod = kExpectedFps.getPeriodNsecs();
129 constexpr auto kSmallPeriod = Fps(250.0f).getPeriodNsecs();
130 constexpr int kNumIterations = 10;
131 for (int i = 1; i <= kNumIterations; i++) {
132 frameTimes.push_back(FrameTimeData{.presentTime = kExpectedPeriod * i,
133 .queueTime = 0,
134 .pendingModeChange = false});
135
136 // A duplicate frame
137 frameTimes.push_back(FrameTimeData{.presentTime = kExpectedPeriod * i + kSmallPeriod,
138 .queueTime = 0,
139 .pendingModeChange = false});
140 }
141 setFrameTimes(frameTimes);
142 const auto averageFrameTime = calculateAverageFrameTime();
143 ASSERT_TRUE(averageFrameTime.has_value());
144 const auto averageFps = Fps::fromPeriodNsecs(*averageFrameTime);
145 ASSERT_TRUE(kExpectedFps.equalsWithMargin(averageFps))
146 << "Expected " << averageFps << " to be equal to " << kExpectedFps;
147 }
148
149 // There may be a big period of time between two frames. Make sure that
150 // this doesn't influence the calculated average FPS.
TEST_F(LayerInfoTest,ignoresLargePeriods)151 TEST_F(LayerInfoTest, ignoresLargePeriods) {
152 std::deque<FrameTimeData> frameTimes;
153 constexpr auto kExpectedFps = Fps(50.0f);
154 constexpr auto kExpectedPeriod = kExpectedFps.getPeriodNsecs();
155 constexpr auto kLargePeriod = Fps(9.0f).getPeriodNsecs();
156
157 auto record = [&](nsecs_t time) {
158 frameTimes.push_back(
159 FrameTimeData{.presentTime = time, .queueTime = 0, .pendingModeChange = false});
160 };
161
162 auto time = kExpectedPeriod; // Start with non-zero time.
163 record(time);
164 time += kLargePeriod;
165 record(time);
166 constexpr int kNumIterations = 10;
167 for (int i = 1; i <= kNumIterations; i++) {
168 time += kExpectedPeriod;
169 record(time);
170 }
171
172 setFrameTimes(frameTimes);
173 const auto averageFrameTime = calculateAverageFrameTime();
174 ASSERT_TRUE(averageFrameTime.has_value());
175 const auto averageFps = Fps::fromPeriodNsecs(*averageFrameTime);
176 ASSERT_TRUE(kExpectedFps.equalsWithMargin(averageFps))
177 << "Expected " << averageFps << " to be equal to " << kExpectedFps;
178 }
179
180 } // namespace
181 } // namespace android::scheduler
182