1 /*
2 * Copyright (C) 2023 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 <gmock/gmock.h>
18 #include <gtest/gtest.h>
19
20 #include "aidl/UClampVoter.h"
21
22 namespace aidl {
23 namespace google {
24 namespace hardware {
25 namespace power {
26 namespace impl {
27 namespace pixel {
28
29 using std::literals::chrono_literals::operator""s;
30 using std::literals::chrono_literals::operator""ms;
31 using std::literals::chrono_literals::operator""ns;
32
33 using testing::Optional;
34
TEST(VoteRange,active)35 TEST(VoteRange, active) {
36 auto tNow = std::chrono::steady_clock::now();
37 VoteRange vr(true, tNow, 200ms);
38 EXPECT_TRUE(vr.active());
39 }
40
TEST(VoteRange,inActive)41 TEST(VoteRange, inActive) {
42 auto tNow = std::chrono::steady_clock::now();
43 VoteRange vr(false, tNow, 200ms);
44 EXPECT_FALSE(vr.active());
45 }
46
TEST(VoteRange,defaultConstructorValues)47 TEST(VoteRange, defaultConstructorValues) {
48 UclampRange uclamp_range;
49 EXPECT_EQ(0, uclamp_range.uclampMin);
50 EXPECT_EQ(1024, uclamp_range.uclampMax);
51 }
52
TEST(VoteRange,isTimeInRange)53 TEST(VoteRange, isTimeInRange) {
54 const auto tNow = std::chrono::steady_clock::now();
55 VoteRange vote_range(true, tNow, 250ms);
56 EXPECT_FALSE(vote_range.isTimeInRange(tNow - 1ns));
57 EXPECT_TRUE(vote_range.isTimeInRange(tNow));
58 EXPECT_TRUE(vote_range.isTimeInRange(tNow + 1ns));
59 EXPECT_TRUE(vote_range.isTimeInRange(tNow + 250ms));
60 EXPECT_FALSE(vote_range.isTimeInRange(tNow + 250ms + 1ns));
61 }
62
TEST(VoteRange,isTimeInRangeInActive)63 TEST(VoteRange, isTimeInRangeInActive) {
64 const auto tNow = std::chrono::steady_clock::now();
65 VoteRange vote_range(true, tNow, 250ms);
66 EXPECT_TRUE(vote_range.active());
67 vote_range.setActive(false);
68 EXPECT_FALSE(vote_range.active());
69 EXPECT_FALSE(vote_range.isTimeInRange(tNow));
70 EXPECT_FALSE(vote_range.isTimeInRange(tNow + 1ns));
71 EXPECT_FALSE(vote_range.isTimeInRange(tNow + 250ms));
72 EXPECT_FALSE(vote_range.isTimeInRange(tNow + 250ms + 1ns));
73 }
74
TEST(VoteRange,getUclampRange)75 TEST(VoteRange, getUclampRange) {
76 const auto tNow = std::chrono::steady_clock::now();
77 const auto tNext = tNow + 1s;
78 const auto tEnd1 = tNow + 4000000001ns;
79 const auto tPrev = tNow - 1s;
80
81 VoteRange voteFirst(true, tNow, 4000000000ns);
82 EXPECT_FALSE(voteFirst.isTimeInRange(tPrev));
83 EXPECT_TRUE(voteFirst.isTimeInRange(tNext));
84 EXPECT_FALSE(voteFirst.isTimeInRange(tEnd1));
85
86 Votes votes;
87 votes.add(1,
88 CpuVote(voteFirst.active(), voteFirst.startTime(), voteFirst.durationNs(), 11, 1024));
89 UclampRange ur;
90
91 votes.getUclampRange(ur, tNext);
92 EXPECT_EQ(11, ur.uclampMin);
93 EXPECT_EQ(kUclampMax, ur.uclampMax);
94 }
95
TEST(UclampVoter,simple)96 TEST(UclampVoter, simple) {
97 const auto tNow = std::chrono::steady_clock::now();
98
99 auto votes = std::make_shared<Votes>();
100 EXPECT_EQ(0, votes->size());
101
102 votes->add(1, CpuVote(true, tNow, 4s, 11, 1024));
103 EXPECT_EQ(1, votes->size());
104
105 votes->add(2, CpuVote(true, tNow, 1s, 22, 1024));
106 EXPECT_EQ(2, votes->size());
107
108 UclampRange ur1;
109 votes->getUclampRange(ur1, tNow);
110 EXPECT_EQ(22, ur1.uclampMin);
111 EXPECT_EQ(kUclampMax, ur1.uclampMax);
112
113 UclampRange ur2;
114 votes->getUclampRange(ur2, tNow + 2s);
115 EXPECT_EQ(11, ur2.uclampMin);
116 EXPECT_EQ(kUclampMax, ur2.uclampMax);
117
118 UclampRange ur3;
119 votes->getUclampRange(ur3, tNow + 5s);
120 EXPECT_EQ(0, ur3.uclampMin);
121 EXPECT_EQ(1024, ur3.uclampMax);
122
123 EXPECT_FALSE(votes->allTimedOut(tNow + 200ns));
124 EXPECT_TRUE(votes->allTimedOut(tNow + 5s));
125
126 EXPECT_TRUE(votes->setUseVote(2, false));
127 EXPECT_TRUE(votes->anyTimedOut(tNow + 5s));
128 EXPECT_TRUE(votes->setUseVote(2, true));
129
130 EXPECT_FALSE(votes->anyTimedOut(tNow + 200ns));
131 }
132
TEST(UclampVoter,overwrite)133 TEST(UclampVoter, overwrite) {
134 const auto tNow = std::chrono::steady_clock::now();
135
136 auto votes = std::make_shared<Votes>();
137 EXPECT_EQ(0, votes->size());
138
139 votes->add(1, CpuVote(true, tNow, 4s, 11, 1024));
140 EXPECT_EQ(1, votes->size());
141
142 votes->add(2, CpuVote(true, tNow, 2s, 22, 1024));
143 EXPECT_EQ(2, votes->size());
144
145 UclampRange ucr1;
146 votes->getUclampRange(ucr1, tNow + 1s);
147 EXPECT_EQ(22, ucr1.uclampMin);
148
149 votes->add(1, CpuVote(true, tNow, 5s, 32, 1024));
150 UclampRange ucr2;
151 votes->getUclampRange(ucr2, tNow + 1s);
152 EXPECT_EQ(32, ucr2.uclampMin);
153 }
154
TEST(UclampVoter,updateDuration)155 TEST(UclampVoter, updateDuration) {
156 const auto tNow = std::chrono::steady_clock::now();
157
158 auto votes = std::make_shared<Votes>();
159 EXPECT_EQ(0, votes->size());
160
161 votes->add(1, CpuVote(true, tNow, 4s, 11, 1024));
162 votes->add(2, CpuVote(true, tNow, 2s, 22, 1024));
163 EXPECT_EQ(2, votes->size());
164
165 EXPECT_TRUE(votes->allTimedOut(tNow + 7s));
166 votes->updateDuration(1, 8s);
167 EXPECT_FALSE(votes->allTimedOut(tNow + 7s));
168 votes->updateDuration(5, 10s);
169 EXPECT_TRUE(votes->allTimedOut(tNow + 9s));
170 }
171
TEST(UclampVoter,loadVoteTest)172 TEST(UclampVoter, loadVoteTest) {
173 const int defaultVoteId = 1;
174 const int loadVoteId = 2;
175 const int uclampMinDefault = 50;
176 const int uclampMinInit = 162;
177 const int uclampMinHigh = 450;
178 const auto tNow = std::chrono::steady_clock::now();
179 UclampRange ucr;
180 auto votes = std::make_shared<Votes>();
181
182 // Default: min = 50 (original)
183 votes->add(defaultVoteId, CpuVote(true, tNow, 400ms, uclampMinDefault, 1024));
184 votes->getUclampRange(ucr, tNow + 100ms);
185 EXPECT_EQ(uclampMinDefault, ucr.uclampMin);
186
187 // Default: min = UclampMinInit
188 votes->add(defaultVoteId, CpuVote(true, tNow, 400ns, uclampMinInit, 1024));
189 // Load: min = uclampMinHigh
190 votes->add(loadVoteId, CpuVote(true, tNow, 250ns, uclampMinHigh, 1024));
191
192 // Check that load is enabled
193 ucr.uclampMin = 0;
194 votes->getUclampRange(ucr, tNow + 100ns);
195 EXPECT_EQ(uclampMinHigh, ucr.uclampMin);
196
197 // Timeout or restore after 1st frame
198 // Expect to get 162.
199 ucr.uclampMin = 0;
200 votes->getUclampRange(ucr, tNow + 350ns);
201 EXPECT_EQ(uclampMinInit, ucr.uclampMin);
202 }
203
TEST(GpuCapacityVoter,testIncorrectTyping)204 TEST(GpuCapacityVoter, testIncorrectTyping) {
205 const auto now = std::chrono::steady_clock::now();
206 Votes votes;
207 static constexpr int gpu_vote_id = static_cast<int>(AdpfVoteType::GPU_CAPACITY);
208 static constexpr int cpu_vote_id = static_cast<int>(AdpfVoteType::CPU_LOAD_UP);
209
210 votes.add(cpu_vote_id, GpuVote(true, now, 250ns, Cycles(1024)));
211 EXPECT_FALSE(votes.voteIsActive(cpu_vote_id));
212 EXPECT_FALSE(votes.setUseVote(cpu_vote_id, true));
213 EXPECT_FALSE(votes.remove(cpu_vote_id));
214
215 votes.add(gpu_vote_id, CpuVote(true, now, 250ns, 66, 77));
216 EXPECT_FALSE(votes.voteIsActive(gpu_vote_id));
217 EXPECT_FALSE(votes.setUseVote(cpu_vote_id, true));
218 EXPECT_FALSE(votes.remove(cpu_vote_id));
219
220 UclampRange range;
221 votes.getUclampRange(range, now);
222 EXPECT_EQ(range.uclampMin, 0);
223 EXPECT_EQ(range.uclampMax, 1024);
224
225 EXPECT_FALSE(votes.getGpuCapacityRequest(now));
226 }
227
TEST(GpuCapacityVoter,testGpuUseVote)228 TEST(GpuCapacityVoter, testGpuUseVote) {
229 const auto now = std::chrono::steady_clock::now();
230 Votes votes;
231 static constexpr int gpu_vote_id1 = static_cast<int>(AdpfVoteType::GPU_CAPACITY);
232 static constexpr int gpu_vote_id2 = static_cast<int>(AdpfVoteType::GPU_LOAD_UP);
233
234 votes.add(gpu_vote_id1, GpuVote(true, now, 250ns, Cycles(1024)));
235 EXPECT_TRUE(votes.setUseVote(gpu_vote_id1, true));
236 EXPECT_FALSE(votes.setUseVote(gpu_vote_id2, true));
237 }
238
TEST(GpuCapacityVoter,testBasicVoteActivation)239 TEST(GpuCapacityVoter, testBasicVoteActivation) {
240 auto const now = std::chrono::steady_clock::now();
241 auto const timeout = 1s;
242 auto const gpu_vote_id = static_cast<int>(AdpfVoteType::GPU_CAPACITY);
243 Votes votes;
244
245 votes.add(gpu_vote_id, GpuVote(true, now, 250ns, Cycles(100)));
246
247 EXPECT_EQ(votes.size(), 1);
248 EXPECT_TRUE(votes.voteIsActive(gpu_vote_id));
249
250 votes.setUseVote(gpu_vote_id, false);
251 EXPECT_FALSE(votes.voteIsActive(gpu_vote_id));
252
253 votes.setUseVote(gpu_vote_id, true);
254 EXPECT_TRUE(votes.voteIsActive(gpu_vote_id));
255
256 EXPECT_TRUE(votes.remove(gpu_vote_id));
257 }
258
TEST(GpuCapacityVoter,testBasicVoteTimeouts)259 TEST(GpuCapacityVoter, testBasicVoteTimeouts) {
260 auto const now = std::chrono::steady_clock::now();
261 auto const timeout = 1s;
262 auto const gpu_vote_id = static_cast<int>(AdpfVoteType::GPU_CAPACITY);
263 Cycles const cycles(100);
264
265 Votes votes;
266 votes.add(gpu_vote_id, GpuVote(true, now, timeout, cycles));
267
268 EXPECT_THAT(votes.getGpuCapacityRequest(now + 1ns), Optional(Cycles(100)));
269
270 auto capacity2 = votes.getGpuCapacityRequest(now + 2 * timeout);
271 EXPECT_FALSE(capacity2);
272 }
273
TEST(GpuCapacityVoter,testVoteTimeouts)274 TEST(GpuCapacityVoter, testVoteTimeouts) {
275 auto const now = std::chrono::steady_clock::now();
276 auto const timeout = 1s;
277 auto const timeout2 = 10s;
278 auto const gpu_vote_id = static_cast<int>(AdpfVoteType::GPU_CAPACITY);
279 auto const cpu_vote_id = static_cast<int>(AdpfVoteType::CPU_LOAD_UP);
280 Cycles const cycles(100);
281
282 Votes votes;
283 votes.add(gpu_vote_id, GpuVote(true, now, timeout, cycles));
284 votes.add(cpu_vote_id, CpuVote(true, now, timeout2, 66, 88));
285
286 EXPECT_EQ(votes.size(), 2);
287 EXPECT_EQ(votes.voteTimeout(gpu_vote_id), now + timeout);
288
289 EXPECT_FALSE(votes.allTimedOut(now + std::chrono::microseconds(56)));
290 EXPECT_FALSE(votes.anyTimedOut(now + std::chrono::microseconds(56)));
291 EXPECT_FALSE(votes.allTimedOut(now + 2 * timeout));
292 EXPECT_TRUE(votes.anyTimedOut(now + 2 * timeout));
293 EXPECT_TRUE(votes.allTimedOut(now + 20 * timeout));
294 EXPECT_TRUE(votes.anyTimedOut(now + 20 * timeout));
295 }
296
TEST(GpuCapacityVoter,testGpuVoteActive)297 TEST(GpuCapacityVoter, testGpuVoteActive) {
298 auto const now = std::chrono::steady_clock::now();
299 auto const timeout = 1s;
300 auto const gpu_vote_id = static_cast<int>(AdpfVoteType::GPU_CAPACITY);
301 Cycles const cycles(100);
302
303 Votes votes;
304 votes.add(gpu_vote_id, GpuVote(true, now, timeout, cycles));
305
306 EXPECT_TRUE(votes.voteIsActive(gpu_vote_id));
307 EXPECT_THAT(votes.getGpuCapacityRequest(now), Optional(cycles));
308 EXPECT_TRUE(votes.setUseVote(gpu_vote_id, false));
309 ASSERT_FALSE(votes.getGpuCapacityRequest(now));
310
311 EXPECT_FALSE(votes.voteIsActive(gpu_vote_id));
312
313 EXPECT_EQ(votes.size(), 1);
314 }
315
TEST(GpuCapacityVoter,testGpuVoteSum)316 TEST(GpuCapacityVoter, testGpuVoteSum) {
317 auto const now = std::chrono::steady_clock::now();
318
319 auto const capacity_vote_id = static_cast<int>(AdpfVoteType::GPU_CAPACITY);
320 auto const load_vote_id = static_cast<int>(AdpfVoteType::GPU_LOAD_UP);
321
322 Votes votes;
323 votes.add(capacity_vote_id, GpuVote(true, now, 100ms, Cycles(321)));
324 votes.add(load_vote_id, GpuVote(true, now, 50ms, Cycles(123)));
325
326 EXPECT_TRUE(votes.voteIsActive(capacity_vote_id));
327 EXPECT_TRUE(votes.voteIsActive(load_vote_id));
328
329 EXPECT_THAT(votes.getGpuCapacityRequest(now + 1ms), Optional(Cycles(444)));
330 EXPECT_THAT(votes.getGpuCapacityRequest(now + 51ms), Optional(Cycles(321)));
331 EXPECT_FALSE(votes.getGpuCapacityRequest(now + 101ms));
332
333 EXPECT_TRUE(votes.setUseVote(load_vote_id, false));
334 EXPECT_TRUE(votes.voteIsActive(capacity_vote_id));
335 EXPECT_FALSE(votes.voteIsActive(load_vote_id));
336 EXPECT_THAT(votes.getGpuCapacityRequest(now + 1ms), Optional(Cycles(321)));
337
338 EXPECT_EQ(votes.size(), 2);
339 }
340 } // namespace pixel
341 } // namespace impl
342 } // namespace power
343 } // namespace hardware
344 } // namespace google
345 } // namespace aidl
346