1 /*
2 * Copyright (C) 2024 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 #include <gtest/gtest.h>
18
19 #include <vector>
20
21 #include "aidl/SessionRecords.h"
22
23 #define MS_TO_NS(x) (x * 1000 * 1000)
24 #define MS_TO_US(x) (x * 1000)
25
26 namespace aidl {
27 namespace google {
28 namespace hardware {
29 namespace power {
30 namespace impl {
31 namespace pixel {
32
33 class SessionRecordsTest : public ::testing::Test {
34 public:
SetUp()35 void SetUp() {
36 mRecords = std::make_shared<SessionRecords>(kMaxNumOfRecords, kJankCheckTimeFactor);
37 }
38
39 protected:
fakeWorkDurations(const std::vector<int32_t> fakedTotalDurationsMs)40 std::vector<WorkDuration> fakeWorkDurations(const std::vector<int32_t> fakedTotalDurationsMs) {
41 std::vector<WorkDuration> fakedWorkDurationsNs;
42 for (auto &d : fakedTotalDurationsMs) {
43 fakedWorkDurationsNs.emplace_back(0, MS_TO_NS(d));
44 }
45 return fakedWorkDurationsNs;
46 }
47
fakeWorkDurations(const std::vector<std::pair<int32_t,int32_t>> fakedReportedDurationsMs)48 std::vector<WorkDuration> fakeWorkDurations(
49 const std::vector<std::pair<int32_t, int32_t>> fakedReportedDurationsMs) {
50 std::vector<WorkDuration> fakedWorkDurationsNs;
51 for (auto &r : fakedReportedDurationsMs) {
52 fakedWorkDurationsNs.emplace_back(MS_TO_NS(r.first), MS_TO_NS(r.second));
53 }
54 return fakedWorkDurationsNs;
55 }
56
57 static constexpr int32_t kMaxNumOfRecords = 5;
58 static constexpr double kJankCheckTimeFactor = 1.5;
59 std::shared_ptr<SessionRecords> mRecords;
60 };
61
TEST_F(SessionRecordsTest,NoRecords)62 TEST_F(SessionRecordsTest, NoRecords) {
63 ASSERT_EQ(0, mRecords->getNumOfRecords());
64 ASSERT_FALSE(mRecords->getMaxDuration().has_value());
65 ASSERT_FALSE(mRecords->getAvgDuration().has_value());
66 ASSERT_EQ(0, mRecords->getNumOfMissedCycles());
67 }
68
TEST_F(SessionRecordsTest,addReportedDurations)69 TEST_F(SessionRecordsTest, addReportedDurations) {
70 FrameBuckets buckets;
71 mRecords->addReportedDurations(fakeWorkDurations({3, 4, 3, 2}), MS_TO_NS(3), buckets);
72 ASSERT_EQ(4, mRecords->getNumOfRecords());
73 ASSERT_EQ(MS_TO_US(4), mRecords->getMaxDuration().value());
74 ASSERT_EQ(MS_TO_US(3), mRecords->getAvgDuration().value());
75 ASSERT_EQ(0, mRecords->getNumOfMissedCycles());
76
77 // Push more records to override part of the old ones in the ring buffer
78 mRecords->addReportedDurations(fakeWorkDurations({2, 1, 2}), MS_TO_NS(3), buckets);
79 ASSERT_EQ(5, mRecords->getNumOfRecords());
80 ASSERT_EQ(MS_TO_US(3), mRecords->getMaxDuration().value());
81 ASSERT_EQ(MS_TO_US(2), mRecords->getAvgDuration().value());
82 ASSERT_EQ(0, mRecords->getNumOfMissedCycles());
83
84 // More records to override the ring buffer more rounds
85 mRecords->addReportedDurations(fakeWorkDurations({10, 2, 9, 8, 4, 5, 7, 6}), MS_TO_NS(3),
86 buckets);
87 ASSERT_EQ(5, mRecords->getNumOfRecords());
88 ASSERT_EQ(MS_TO_US(8), mRecords->getMaxDuration().value());
89 ASSERT_EQ(MS_TO_US(6), mRecords->getAvgDuration().value());
90 ASSERT_EQ(4, mRecords->getNumOfMissedCycles());
91 }
92
TEST_F(SessionRecordsTest,checkLowFrameRate)93 TEST_F(SessionRecordsTest, checkLowFrameRate) {
94 FrameBuckets buckets;
95 ASSERT_FALSE(mRecords->isLowFrameRate(25));
96 mRecords->addReportedDurations(fakeWorkDurations({{0, 8}, {10, 9}, {20, 8}, {30, 8}}),
97 MS_TO_NS(10), buckets);
98 ASSERT_EQ(4, mRecords->getNumOfRecords());
99 ASSERT_FALSE(mRecords->isLowFrameRate(25));
100
101 mRecords->addReportedDurations(fakeWorkDurations({{130, 8}, {230, 9}}), MS_TO_NS(10), buckets);
102 ASSERT_EQ(5, mRecords->getNumOfRecords());
103 ASSERT_FALSE(mRecords->isLowFrameRate(25));
104
105 mRecords->addReportedDurations(fakeWorkDurations({{330, 8}, {430, 9}}), MS_TO_NS(10), buckets);
106 ASSERT_EQ(5, mRecords->getNumOfRecords());
107 ASSERT_TRUE(mRecords->isLowFrameRate(25));
108
109 mRecords->addReportedDurations(fakeWorkDurations({{440, 8}, {450, 9}}), MS_TO_NS(10), buckets);
110 ASSERT_EQ(5, mRecords->getNumOfRecords());
111 ASSERT_FALSE(mRecords->isLowFrameRate(25));
112 }
113
TEST_F(SessionRecordsTest,switchTargetDuration)114 TEST_F(SessionRecordsTest, switchTargetDuration) {
115 FrameBuckets buckets;
116 ASSERT_FALSE(mRecords->isLowFrameRate(25));
117 mRecords->addReportedDurations(fakeWorkDurations({{0, 8}, {10, 9}, {20, 19}, {40, 8}}),
118 MS_TO_NS(10), buckets);
119 ASSERT_EQ(4, mRecords->getNumOfRecords());
120 ASSERT_EQ(MS_TO_US(19), mRecords->getMaxDuration().value());
121 ASSERT_EQ(MS_TO_US(11), mRecords->getAvgDuration().value());
122 ASSERT_EQ(1, mRecords->getNumOfMissedCycles());
123
124 // Change the target duration. It will reset all the old record states.
125 mRecords->resetRecords();
126 ASSERT_EQ(0, mRecords->getNumOfRecords());
127 ASSERT_FALSE(mRecords->getMaxDuration().has_value());
128 ASSERT_FALSE(mRecords->getAvgDuration().has_value());
129 ASSERT_EQ(0, mRecords->getNumOfMissedCycles());
130 ASSERT_FALSE(mRecords->isLowFrameRate(25));
131
132 mRecords->addReportedDurations(fakeWorkDurations({{50, 14}, {70, 16}}), MS_TO_NS(20), buckets);
133 ASSERT_EQ(2, mRecords->getNumOfRecords());
134 ASSERT_EQ(MS_TO_US(16), mRecords->getMaxDuration().value());
135 ASSERT_EQ(MS_TO_US(15), mRecords->getAvgDuration().value());
136 ASSERT_EQ(0, mRecords->getNumOfMissedCycles());
137 ASSERT_FALSE(mRecords->isLowFrameRate(25));
138 }
139
TEST_F(SessionRecordsTest,checkFPSJitters)140 TEST_F(SessionRecordsTest, checkFPSJitters) {
141 FrameBuckets buckets;
142 ASSERT_EQ(0, mRecords->getNumOfFPSJitters());
143 mRecords->addReportedDurations(fakeWorkDurations({{0, 8}, {10, 9}, {20, 8}, {30, 8}}),
144 MS_TO_NS(10), buckets, true);
145 ASSERT_EQ(0, mRecords->getNumOfFPSJitters());
146 ASSERT_EQ(100, mRecords->getLatestFPS());
147
148 mRecords->addReportedDurations(fakeWorkDurations({{40, 22}, {80, 8}}), MS_TO_NS(10), buckets,
149 true);
150 ASSERT_EQ(1, mRecords->getNumOfFPSJitters());
151 ASSERT_EQ(50, mRecords->getLatestFPS());
152 mRecords->addReportedDurations(fakeWorkDurations({{90, 8}, {100, 8}, {110, 7}}), MS_TO_NS(10),
153 buckets, true);
154 ASSERT_EQ(1, mRecords->getNumOfFPSJitters());
155
156 // Push more records to override part of the old ones in the ring buffer
157 mRecords->addReportedDurations(fakeWorkDurations({{120, 22}, {150, 8}}), MS_TO_NS(10), buckets,
158 true);
159 ASSERT_EQ(1, mRecords->getNumOfFPSJitters());
160
161 // Cancel the new FPS Jitter evaluation for the new records report.
162 mRecords->addReportedDurations(fakeWorkDurations({{160, 8}, {170, 8}}), MS_TO_NS(10), buckets);
163 ASSERT_EQ(1, mRecords->getNumOfFPSJitters());
164 ASSERT_EQ(0, mRecords->getLatestFPS());
165
166 // All the old FPS Jitters stored in the records buffer got overrode by new records.
167 mRecords->addReportedDurations(fakeWorkDurations({{190, 8}, {230, 8}, {300, 8}}), MS_TO_NS(10),
168 buckets);
169 ASSERT_EQ(0, mRecords->getNumOfFPSJitters());
170 ASSERT_EQ(0, mRecords->getLatestFPS());
171 }
172
TEST_F(SessionRecordsTest,updateFrameBuckets)173 TEST_F(SessionRecordsTest, updateFrameBuckets) {
174 FrameBuckets buckets;
175
176 mRecords->addReportedDurations(fakeWorkDurations({10, 11, 16, 17, 26, 40}), MS_TO_NS(10),
177 buckets);
178 ASSERT_EQ(6, buckets.totalNumOfFrames);
179 ASSERT_EQ(1, buckets.numOfFrames17to25ms);
180 ASSERT_EQ(1, buckets.numOfFrames25to34ms);
181 ASSERT_EQ(1, buckets.numOfFrames34to67ms);
182 ASSERT_EQ(0, buckets.numOfFrames67to100ms);
183 ASSERT_EQ(0, buckets.numOfFramesOver100ms);
184
185 mRecords->addReportedDurations(fakeWorkDurations({80, 100}), MS_TO_NS(10), buckets);
186 ASSERT_EQ(8, buckets.totalNumOfFrames);
187 ASSERT_EQ(1, buckets.numOfFrames17to25ms);
188 ASSERT_EQ(1, buckets.numOfFrames25to34ms);
189 ASSERT_EQ(1, buckets.numOfFrames34to67ms);
190 ASSERT_EQ(1, buckets.numOfFrames67to100ms);
191 ASSERT_EQ(1, buckets.numOfFramesOver100ms);
192
193 FrameBuckets newBuckets{2, 1, 1, 1, 1, 0};
194 buckets.addUpNewFrames(newBuckets);
195 ASSERT_EQ(10, buckets.totalNumOfFrames);
196 ASSERT_EQ(2, buckets.numOfFrames17to25ms);
197 ASSERT_EQ(2, buckets.numOfFrames25to34ms);
198 ASSERT_EQ(2, buckets.numOfFrames34to67ms);
199 ASSERT_EQ(2, buckets.numOfFrames67to100ms);
200 ASSERT_EQ(1, buckets.numOfFramesOver100ms);
201 }
202
203 } // namespace pixel
204 } // namespace impl
205 } // namespace power
206 } // namespace hardware
207 } // namespace google
208 } // namespace aidl
209