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