• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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