1 /*
2 * Copyright (C) 2017 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 specic language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <android-base/file.h>
18 #include <android-base/logging.h>
19 #include <android-base/properties.h>
20 #include <android-base/stringprintf.h>
21 #include <gmock/gmock.h>
22 #include <gtest/gtest.h>
23
24 #include <algorithm>
25 #include <thread>
26
27 #include "perfmgr/AdpfConfig.h"
28 #include "perfmgr/FileNode.h"
29 #include "perfmgr/HintManager.h"
30 #include "perfmgr/PropertyNode.h"
31
32 namespace android {
33 namespace perfmgr {
34
35 using std::literals::chrono_literals::operator""ms;
36
37 using testing::Eq;
38 using testing::Optional;
39
40 constexpr auto kSLEEP_TOLERANCE_MS = 50ms;
41
42 constexpr char kJSON_RAW[] = R"(
43 {
44 "Nodes": [
45 {
46 "Name": "CPUCluster0MinFreq",
47 "Path": "/sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq",
48 "Values": [
49 "1512000",
50 "1134000",
51 "384000"
52 ],
53 "DefaultIndex": 2,
54 "ResetOnInit": true
55 },
56 {
57 "Name": "CPUCluster1MinFreq",
58 "Path": "/sys/devices/system/cpu/cpu4/cpufreq/scaling_min_freq",
59 "Values": [
60 "1512000",
61 "1134000",
62 "384000"
63 ],
64 "HoldFd": true
65 },
66 {
67 "Name": "ModeProperty",
68 "Path": "vendor.pwhal.mode",
69 "Values": [
70 "HIGH",
71 "LOW",
72 "NONE"
73 ],
74 "Type": "Property"
75 },
76 {
77 "Name": "TestEnableProperty",
78 "Path": "vendor.pwhal.enable.test",
79 "Values": [
80 "0",
81 "1"
82 ],
83 "Type": "Property",
84 "ResetOnInit": true
85 }
86 ],
87 "Actions": [
88 {
89 "PowerHint": "INTERACTION",
90 "Node": "CPUCluster1MinFreq",
91 "Value": "1134000",
92 "Duration": 800
93 },
94 {
95 "PowerHint": "INTERACTION",
96 "Node": "ModeProperty",
97 "Value": "LOW",
98 "Duration": 800
99 },
100 {
101 "PowerHint": "LAUNCH",
102 "Node": "CPUCluster0MinFreq",
103 "Value": "1134000",
104 "EnableProperty": "vendor.pwhal.enable.no_exist",
105 "Duration": 500
106 },
107 {
108 "PowerHint": "LAUNCH",
109 "Node": "ModeProperty",
110 "Value": "HIGH",
111 "Duration": 500
112 },
113 {
114 "PowerHint": "LAUNCH",
115 "Node": "CPUCluster1MinFreq",
116 "Value": "1512000",
117 "EnableProperty": "vendor.pwhal.enable.test",
118 "Duration": 2000
119 },
120 {
121 "PowerHint": "DISABLE_LAUNCH_ACT2",
122 "Node": "TestEnableProperty",
123 "Value": "0",
124 "Duration": 0
125 },
126 {
127 "PowerHint": "MASK_LAUNCH_MODE",
128 "Type": "MaskHint",
129 "Value": "LAUNCH"
130 },
131 {
132 "PowerHint": "MASK_LAUNCH_INTERACTION_MODE",
133 "Type": "MaskHint",
134 "Value": "LAUNCH"
135 },
136 {
137 "PowerHint": "MASK_LAUNCH_INTERACTION_MODE",
138 "Type": "MaskHint",
139 "Value": "INTERACTION"
140 },
141 {
142 "PowerHint": "END_LAUNCH_MODE",
143 "Type": "EndHint",
144 "Value": "LAUNCH"
145 },
146 {
147 "PowerHint": "DO_LAUNCH_MODE",
148 "Type": "DoHint",
149 "Value": "LAUNCH"
150 }
151 ],
152 "GpuSysfsPath" : "/sys/devices/platform/123.abc",
153 "AdpfConfig": [
154 {
155 "Name": "REFRESH_120FPS",
156 "PID_On": true,
157 "PID_Po": 5.0,
158 "PID_Pu": 3.0,
159 "PID_I": 0.001,
160 "PID_I_Init": 200,
161 "PID_I_High": 512,
162 "PID_I_Low": -120,
163 "PID_Do": 500.0,
164 "PID_Du": 0.0,
165 "SamplingWindow_P": 1,
166 "SamplingWindow_I": 0,
167 "SamplingWindow_D": 1,
168 "UclampMin_On": true,
169 "UclampMin_Init": 100,
170 "UclampMin_LoadUp": 200,
171 "UclampMin_LoadReset": 300,
172 "UclampMin_High": 384,
173 "UclampMin_Low": 0,
174 "ReportingRateLimitNs": 166666660,
175 "EarlyBoost_On": false,
176 "EarlyBoost_TimeFactor": 0.8,
177 "TargetTimeFactor": 1.0,
178 "StaleTimeFactor": 10.0,
179 "GpuBoost": true,
180 "GpuCapacityBoostMax": 300000,
181 "GpuCapacityLoadUpHeadroom": 1000,
182 "HeuristicBoost_On": true,
183 "HBoostOnMissedCycles": 4,
184 "HBoostOffMaxAvgRatio": 4.0,
185 "HBoostOffMissedCycles": 2,
186 "HBoostPidPuFactor": 0.5,
187 "HBoostUclampMin": 800,
188 "JankCheckTimeFactor": 1.2,
189 "LowFrameRateThreshold": 25,
190 "MaxRecordsNum": 50
191 },
192 {
193 "Name": "REFRESH_60FPS",
194 "PID_On": false,
195 "PID_Po": 0,
196 "PID_Pu": 0,
197 "PID_I": 0,
198 "PID_I_Init": 0,
199 "PID_I_High": 0,
200 "PID_I_Low": 0,
201 "PID_Do": 0,
202 "PID_Du": 0,
203 "SamplingWindow_P": 0,
204 "SamplingWindow_I": 0,
205 "SamplingWindow_D": 0,
206 "UclampMin_On": true,
207 "UclampMin_Init": 200,
208 "UclampMin_High": 157,
209 "UclampMin_Low": 157,
210 "ReportingRateLimitNs": 83333330,
211 "EarlyBoost_On": true,
212 "EarlyBoost_TimeFactor": 1.2,
213 "TargetTimeFactor": 1.4,
214 "StaleTimeFactor": 5.0
215 }
216 ]
217 }
218 )";
219
220 class HintManagerTest : public ::testing::Test, public HintManager {
221 protected:
HintManagerTest()222 HintManagerTest()
223 : HintManager(nullptr, std::unordered_map<std::string, Hint>{},
224 std::vector<std::shared_ptr<AdpfConfig>>(), {}) {
225 android::base::SetMinimumLogSeverity(android::base::VERBOSE);
226 prop_ = "vendor.pwhal.mode";
227 }
228
SetUp()229 virtual void SetUp() {
230 // Set up 3 dummy nodes
231 std::unique_ptr<TemporaryFile> tf = std::make_unique<TemporaryFile>();
232 nodes_.emplace_back(new FileNode(
233 "n0", tf->path, {{"n0_value0"}, {"n0_value1"}, {"n0_value2"}}, 2,
234 false, false));
235 files_.emplace_back(std::move(tf));
236 tf = std::make_unique<TemporaryFile>();
237 nodes_.emplace_back(new FileNode(
238 "n1", tf->path, {{"n1_value0"}, {"n1_value1"}, {"n1_value2"}}, 2,
239 true, true));
240 files_.emplace_back(std::move(tf));
241 nodes_.emplace_back(new PropertyNode(
242 "n2", prop_, {{"n2_value0"}, {"n2_value1"}, {"n2_value2"}}, 2,
243 true));
244 nm_ = new NodeLooperThread(std::move(nodes_));
245 // Set up dummy actions
246 // "INTERACTION"
247 // Node0, value1, 800ms
248 // Node1, value1, forever
249 // Node2, value1, 800ms
250 // "LAUNCH"
251 // Node0, value0, forever
252 // Node1, value0, 400ms
253 // Node2, value0, 400ms
254 actions_["INTERACTION"].node_actions =
255 std::vector<NodeAction>{{0, 1, 800ms}, {1, 1, 0ms}, {2, 1, 800ms}};
256 actions_["LAUNCH"].node_actions =
257 std::vector<NodeAction>{{0, 0, 0ms}, {1, 0, 400ms}, {2, 0, 400ms}};
258
259 // Prepare dummy files to replace the nodes' path in example json_doc
260 files_.emplace_back(std::make_unique<TemporaryFile>());
261 files_.emplace_back(std::make_unique<TemporaryFile>());
262 // replace file path
263 json_doc_ = kJSON_RAW;
264 std::string from =
265 "/sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq";
266 size_t start_pos = json_doc_.find(from);
267 json_doc_.replace(start_pos, from.length(), files_[0 + 2]->path);
268 from = "/sys/devices/system/cpu/cpu4/cpufreq/scaling_min_freq";
269 start_pos = json_doc_.find(from);
270 json_doc_.replace(start_pos, from.length(), files_[1 + 2]->path);
271 EXPECT_TRUE(android::base::SetProperty(prop_, ""))
272 << "failed to clear property";
273 }
274
TearDown()275 virtual void TearDown() {
276 actions_.clear();
277 nodes_.clear();
278 files_.clear();
279 nm_ = nullptr;
280 }
281 sp<NodeLooperThread> nm_;
282 std::unordered_map<std::string, Hint> actions_;
283 std::vector<std::unique_ptr<Node>> nodes_;
284 std::vector<std::unique_ptr<TemporaryFile>> files_;
285 std::string json_doc_;
286 std::string prop_;
287 };
288
_VerifyPropertyValue(const std::string & path,const std::string & value)289 static inline void _VerifyPropertyValue(const std::string& path,
290 const std::string& value) {
291 std::string s = android::base::GetProperty(path, "");
292 EXPECT_EQ(value, s);
293 }
294
_VerifyPathValue(const std::string & path,const std::string & value)295 static inline void _VerifyPathValue(const std::string& path,
296 const std::string& value) {
297 std::string s;
298 EXPECT_TRUE(android::base::ReadFileToString(path, &s)) << strerror(errno);
299 EXPECT_EQ(value, s);
300 }
301
_VerifyStats(const HintStats & stats,uint32_t count,uint64_t duration_min,uint64_t duration_max)302 static inline void _VerifyStats(const HintStats &stats, uint32_t count, uint64_t duration_min,
303 uint64_t duration_max) {
304 EXPECT_EQ(stats.count, count);
305 EXPECT_GE(stats.duration_ms, duration_min);
306 EXPECT_LT(stats.duration_ms, duration_max);
307 }
308
309 // Test GetHints
TEST_F(HintManagerTest,GetHintsTest)310 TEST_F(HintManagerTest, GetHintsTest) {
311 HintManager hm(nm_, actions_, std::vector<std::shared_ptr<AdpfConfig>>(), {});
312 EXPECT_TRUE(hm.Start());
313 std::vector<std::string> hints = hm.GetHints();
314 EXPECT_TRUE(hm.IsRunning());
315 EXPECT_EQ(2u, hints.size());
316 EXPECT_NE(std::find(hints.begin(), hints.end(), "INTERACTION"), hints.end());
317 EXPECT_NE(std::find(hints.begin(), hints.end(), "LAUNCH"), hints.end());
318 }
319
320 // Test GetHintStats
TEST_F(HintManagerTest,GetHintStatsTest)321 TEST_F(HintManagerTest, GetHintStatsTest) {
322 auto hm =
323 std::make_unique<HintManager>(nm_, actions_, std::vector<std::shared_ptr<AdpfConfig>>(),
324 std::optional<std::string>{});
325 EXPECT_TRUE(InitHintStatus(hm));
326 EXPECT_TRUE(hm->Start());
327 HintStats launch_stats(hm->GetHintStats("LAUNCH"));
328 EXPECT_EQ(0, launch_stats.count);
329 EXPECT_EQ(0, launch_stats.duration_ms);
330 HintStats interaction_stats(hm->GetHintStats("INTERACTION"));
331 EXPECT_EQ(0, interaction_stats.count);
332 EXPECT_EQ(0, interaction_stats.duration_ms);
333 }
334
335 // Test initialization of default values
TEST_F(HintManagerTest,HintInitDefaultTest)336 TEST_F(HintManagerTest, HintInitDefaultTest) {
337 HintManager hm(nm_, actions_, std::vector<std::shared_ptr<AdpfConfig>>(), {});
338 EXPECT_TRUE(hm.Start());
339 std::this_thread::sleep_for(kSLEEP_TOLERANCE_MS);
340 EXPECT_TRUE(hm.IsRunning());
341 _VerifyPathValue(files_[0]->path, "");
342 _VerifyPathValue(files_[1]->path, "n1_value2");
343 _VerifyPropertyValue(prop_, "n2_value2");
344 }
345
346 // Test IsHintSupported
TEST_F(HintManagerTest,HintSupportedTest)347 TEST_F(HintManagerTest, HintSupportedTest) {
348 HintManager hm(nm_, actions_, std::vector<std::shared_ptr<AdpfConfig>>(), {});
349 EXPECT_TRUE(hm.IsHintSupported("INTERACTION"));
350 EXPECT_TRUE(hm.IsHintSupported("LAUNCH"));
351 EXPECT_FALSE(hm.IsHintSupported("NO_SUCH_HINT"));
352 }
353
354 // Test hint/cancel/expire with dummy actions
TEST_F(HintManagerTest,HintTest)355 TEST_F(HintManagerTest, HintTest) {
356 auto hm =
357 std::make_unique<HintManager>(nm_, actions_, std::vector<std::shared_ptr<AdpfConfig>>(),
358 std::optional<std::string>{});
359 EXPECT_TRUE(InitHintStatus(hm));
360 EXPECT_TRUE(hm->Start());
361 EXPECT_TRUE(hm->IsRunning());
362 EXPECT_TRUE(hm->DoHint("INTERACTION"));
363 std::this_thread::sleep_for(kSLEEP_TOLERANCE_MS);
364 _VerifyPathValue(files_[0]->path, "n0_value1");
365 _VerifyPathValue(files_[1]->path, "n1_value1");
366 _VerifyPropertyValue(prop_, "n2_value1");
367 // this won't change the expire time of INTERACTION hint
368 EXPECT_TRUE(hm->DoHint("INTERACTION", 200ms));
369 // now place new hint
370 EXPECT_TRUE(hm->DoHint("LAUNCH"));
371 std::this_thread::sleep_for(kSLEEP_TOLERANCE_MS);
372 _VerifyPathValue(files_[0]->path, "n0_value0");
373 _VerifyPathValue(files_[1]->path, "n1_value0");
374 _VerifyPropertyValue(prop_, "n2_value0");
375 EXPECT_TRUE(hm->DoHint("LAUNCH", 500ms));
376 // "LAUNCH" node1 not expired
377 std::this_thread::sleep_for(400ms);
378 _VerifyPathValue(files_[0]->path, "n0_value0");
379 _VerifyPathValue(files_[1]->path, "n1_value0");
380 _VerifyPropertyValue(prop_, "n2_value0");
381 // "LAUNCH" node1 expired
382 std::this_thread::sleep_for(100ms + kSLEEP_TOLERANCE_MS);
383 _VerifyPathValue(files_[0]->path, "n0_value0");
384 _VerifyPathValue(files_[1]->path, "n1_value1");
385 _VerifyPropertyValue(prop_, "n2_value1");
386 EXPECT_TRUE(hm->EndHint("LAUNCH"));
387 std::this_thread::sleep_for(kSLEEP_TOLERANCE_MS);
388 // "LAUNCH" canceled
389 _VerifyPathValue(files_[0]->path, "n0_value1");
390 _VerifyPathValue(files_[1]->path, "n1_value1");
391 _VerifyPropertyValue(prop_, "n2_value1");
392 std::this_thread::sleep_for(200ms);
393 // "INTERACTION" node0 expired
394 _VerifyPathValue(files_[0]->path, "n0_value2");
395 _VerifyPathValue(files_[1]->path, "n1_value1");
396 _VerifyPropertyValue(prop_, "n2_value2");
397 EXPECT_TRUE(hm->EndHint("INTERACTION"));
398 std::this_thread::sleep_for(kSLEEP_TOLERANCE_MS);
399 // "INTERACTION" canceled
400 _VerifyPathValue(files_[0]->path, "n0_value2");
401 _VerifyPathValue(files_[1]->path, "n1_value2");
402 _VerifyPropertyValue(prop_, "n2_value2");
403 }
404
405 // Test collecting stats with simple actions
TEST_F(HintManagerTest,HintStatsTest)406 TEST_F(HintManagerTest, HintStatsTest) {
407 auto hm =
408 std::make_unique<HintManager>(nm_, actions_, std::vector<std::shared_ptr<AdpfConfig>>(),
409 std::optional<std::string>{});
410 EXPECT_TRUE(InitHintStatus(hm));
411 EXPECT_TRUE(hm->Start());
412 EXPECT_TRUE(hm->IsRunning());
413 EXPECT_TRUE(hm->DoHint("INTERACTION"));
414 std::this_thread::sleep_for(kSLEEP_TOLERANCE_MS);
415 _VerifyPathValue(files_[0]->path, "n0_value1");
416 _VerifyPathValue(files_[1]->path, "n1_value1");
417 _VerifyPropertyValue(prop_, "n2_value1");
418 // now place "LAUNCH" hint with timeout of 500ms
419 EXPECT_TRUE(hm->DoHint("LAUNCH", 500ms));
420 std::this_thread::sleep_for(kSLEEP_TOLERANCE_MS);
421 _VerifyPathValue(files_[0]->path, "n0_value0");
422 _VerifyPathValue(files_[1]->path, "n1_value0");
423 _VerifyPropertyValue(prop_, "n2_value0");
424 // "LAUNCH" expired
425 std::this_thread::sleep_for(500ms + kSLEEP_TOLERANCE_MS);
426 _VerifyPathValue(files_[0]->path, "n0_value1");
427 _VerifyPathValue(files_[1]->path, "n1_value1");
428 _VerifyPropertyValue(prop_, "n2_value1");
429 HintStats launch_stats(hm->GetHintStats("LAUNCH"));
430 // Since duration is recorded at the next DoHint,
431 // duration should be 0.
432 _VerifyStats(launch_stats, 1, 0, 100);
433 std::this_thread::sleep_for(100ms + kSLEEP_TOLERANCE_MS);
434 EXPECT_TRUE(hm->EndHint("INTERACTION"));
435 std::this_thread::sleep_for(kSLEEP_TOLERANCE_MS);
436 // "INTERACTION" canceled
437 _VerifyPathValue(files_[0]->path, "n0_value2");
438 _VerifyPathValue(files_[1]->path, "n1_value2");
439 _VerifyPropertyValue(prop_, "n2_value2");
440 HintStats interaction_stats(hm->GetHintStats("INTERACTION"));
441 _VerifyStats(interaction_stats, 1, 800, 900);
442 std::this_thread::sleep_for(kSLEEP_TOLERANCE_MS);
443 // Second LAUNCH hint sent to get the first duration recorded.
444 EXPECT_TRUE(hm->DoHint("LAUNCH"));
445 launch_stats = hm->GetHintStats("LAUNCH");
446 _VerifyStats(launch_stats, 2, 500, 600);
447 }
448
449 // Test parsing nodes
TEST_F(HintManagerTest,ParseNodesTest)450 TEST_F(HintManagerTest, ParseNodesTest) {
451 std::vector<std::unique_ptr<Node>> nodes =
452 HintManager::ParseNodes(json_doc_);
453 EXPECT_EQ(4u, nodes.size());
454 EXPECT_EQ("CPUCluster0MinFreq", nodes[0]->GetName());
455 EXPECT_EQ("CPUCluster1MinFreq", nodes[1]->GetName());
456 EXPECT_EQ(files_[0 + 2]->path, nodes[0]->GetPath());
457 EXPECT_EQ(files_[1 + 2]->path, nodes[1]->GetPath());
458 EXPECT_EQ("1512000", nodes[0]->GetValues()[0]);
459 EXPECT_EQ("1134000", nodes[0]->GetValues()[1]);
460 EXPECT_EQ("384000", nodes[0]->GetValues()[2]);
461 EXPECT_EQ("1512000", nodes[1]->GetValues()[0]);
462 EXPECT_EQ("1134000", nodes[1]->GetValues()[1]);
463 EXPECT_EQ("384000", nodes[1]->GetValues()[2]);
464 EXPECT_EQ(2u, nodes[0]->GetDefaultIndex());
465 EXPECT_EQ(2u, nodes[1]->GetDefaultIndex());
466 EXPECT_TRUE(nodes[0]->GetResetOnInit());
467 EXPECT_FALSE(nodes[1]->GetResetOnInit());
468 // no dynamic_cast intentionally in Android
469 EXPECT_FALSE(reinterpret_cast<FileNode*>(nodes[0].get())->GetHoldFd());
470 EXPECT_TRUE(reinterpret_cast<FileNode*>(nodes[1].get())->GetHoldFd());
471 EXPECT_EQ("ModeProperty", nodes[2]->GetName());
472 EXPECT_EQ(prop_, nodes[2]->GetPath());
473 EXPECT_EQ("HIGH", nodes[2]->GetValues()[0]);
474 EXPECT_EQ("LOW", nodes[2]->GetValues()[1]);
475 EXPECT_EQ("NONE", nodes[2]->GetValues()[2]);
476 EXPECT_EQ(2u, nodes[2]->GetDefaultIndex());
477 EXPECT_FALSE(nodes[2]->GetResetOnInit());
478 }
479
480 // Test parsing nodes with duplicate name
TEST_F(HintManagerTest,ParseNodesDuplicateNameTest)481 TEST_F(HintManagerTest, ParseNodesDuplicateNameTest) {
482 std::string from = "CPUCluster0MinFreq";
483 size_t start_pos = json_doc_.find(from);
484 json_doc_.replace(start_pos, from.length(), "CPUCluster1MinFreq");
485 std::vector<std::unique_ptr<Node>> nodes =
486 HintManager::ParseNodes(json_doc_);
487 EXPECT_EQ(0u, nodes.size());
488 }
489
TEST_F(HintManagerTest,ParsePropertyNodesDuplicatNameTest)490 TEST_F(HintManagerTest, ParsePropertyNodesDuplicatNameTest) {
491 std::string from = "ModeProperty";
492 size_t start_pos = json_doc_.find(from);
493 json_doc_.replace(start_pos, from.length(), "CPUCluster1MinFreq");
494 std::vector<std::unique_ptr<Node>> nodes =
495 HintManager::ParseNodes(json_doc_);
496 EXPECT_EQ(0u, nodes.size());
497 }
498
499 // Test parsing nodes with duplicate path
TEST_F(HintManagerTest,ParseNodesDuplicatePathTest)500 TEST_F(HintManagerTest, ParseNodesDuplicatePathTest) {
501 std::string from = files_[0 + 2]->path;
502 size_t start_pos = json_doc_.find(from);
503 json_doc_.replace(start_pos, from.length(), files_[1 + 2]->path);
504 std::vector<std::unique_ptr<Node>> nodes =
505 HintManager::ParseNodes(json_doc_);
506 EXPECT_EQ(0u, nodes.size());
507 }
508
509 // Test parsing file node with duplicate value
TEST_F(HintManagerTest,ParseFileNodesDuplicateValueTest)510 TEST_F(HintManagerTest, ParseFileNodesDuplicateValueTest) {
511 std::string from = "1512000";
512 size_t start_pos = json_doc_.find(from);
513 json_doc_.replace(start_pos, from.length(), "1134000");
514 std::vector<std::unique_ptr<Node>> nodes =
515 HintManager::ParseNodes(json_doc_);
516 EXPECT_EQ(0u, nodes.size());
517 }
518
519 // Test parsing property node with duplicate value
TEST_F(HintManagerTest,ParsePropertyNodesDuplicateValueTest)520 TEST_F(HintManagerTest, ParsePropertyNodesDuplicateValueTest) {
521 std::string from = "HIGH";
522 size_t start_pos = json_doc_.find(from);
523 json_doc_.replace(start_pos, from.length(), "LOW");
524 std::vector<std::unique_ptr<Node>> nodes =
525 HintManager::ParseNodes(json_doc_);
526 EXPECT_EQ(0u, nodes.size());
527 }
528
529 // Test parsing file node with empty value
TEST_F(HintManagerTest,ParseFileNodesEmptyValueTest)530 TEST_F(HintManagerTest, ParseFileNodesEmptyValueTest) {
531 std::string from = "384000";
532 size_t start_pos = json_doc_.find(from);
533 json_doc_.replace(start_pos, from.length(), "");
534 std::vector<std::unique_ptr<Node>> nodes =
535 HintManager::ParseNodes(json_doc_);
536 EXPECT_EQ(0u, nodes.size());
537 }
538
539 // Test parsing property node with empty value
TEST_F(HintManagerTest,ParsePropertyNodesEmptyValueTest)540 TEST_F(HintManagerTest, ParsePropertyNodesEmptyValueTest) {
541 std::string from = "LOW";
542 size_t start_pos = json_doc_.find(from);
543 json_doc_.replace(start_pos, from.length(), "");
544 std::vector<std::unique_ptr<Node>> nodes =
545 HintManager::ParseNodes(json_doc_);
546 EXPECT_EQ(4u, nodes.size());
547 EXPECT_EQ("CPUCluster0MinFreq", nodes[0]->GetName());
548 EXPECT_EQ("CPUCluster1MinFreq", nodes[1]->GetName());
549 EXPECT_EQ(files_[0 + 2]->path, nodes[0]->GetPath());
550 EXPECT_EQ(files_[1 + 2]->path, nodes[1]->GetPath());
551 EXPECT_EQ("1512000", nodes[0]->GetValues()[0]);
552 EXPECT_EQ("1134000", nodes[0]->GetValues()[1]);
553 EXPECT_EQ("384000", nodes[0]->GetValues()[2]);
554 EXPECT_EQ("1512000", nodes[1]->GetValues()[0]);
555 EXPECT_EQ("1134000", nodes[1]->GetValues()[1]);
556 EXPECT_EQ("384000", nodes[1]->GetValues()[2]);
557 EXPECT_EQ(2u, nodes[0]->GetDefaultIndex());
558 EXPECT_EQ(2u, nodes[1]->GetDefaultIndex());
559 EXPECT_TRUE(nodes[0]->GetResetOnInit());
560 EXPECT_FALSE(nodes[1]->GetResetOnInit());
561 // no dynamic_cast intentionally in Android
562 EXPECT_FALSE(reinterpret_cast<FileNode*>(nodes[0].get())->GetHoldFd());
563 EXPECT_TRUE(reinterpret_cast<FileNode*>(nodes[1].get())->GetHoldFd());
564 EXPECT_EQ("ModeProperty", nodes[2]->GetName());
565 EXPECT_EQ(prop_, nodes[2]->GetPath());
566 EXPECT_EQ("HIGH", nodes[2]->GetValues()[0]);
567 EXPECT_EQ("", nodes[2]->GetValues()[1]);
568 EXPECT_EQ("NONE", nodes[2]->GetValues()[2]);
569 EXPECT_EQ(2u, nodes[2]->GetDefaultIndex());
570 EXPECT_FALSE(nodes[2]->GetResetOnInit());
571 }
572
573 // Test parsing invalid json for nodes
TEST_F(HintManagerTest,ParseBadFileNodesTest)574 TEST_F(HintManagerTest, ParseBadFileNodesTest) {
575 std::vector<std::unique_ptr<Node>> nodes =
576 HintManager::ParseNodes("invalid json");
577 EXPECT_EQ(0u, nodes.size());
578 nodes = HintManager::ParseNodes(
579 "{\"devices\":{\"15\":[\"armeabi-v7a\"],\"16\":[\"armeabi-v7a\"],"
580 "\"26\":[\"armeabi-v7a\",\"arm64-v8a\",\"x86\",\"x86_64\"]}}");
581 EXPECT_EQ(0u, nodes.size());
582 }
583
584 // Test parsing actions
TEST_F(HintManagerTest,ParseActionsTest)585 TEST_F(HintManagerTest, ParseActionsTest) {
586 std::vector<std::unique_ptr<Node>> nodes =
587 HintManager::ParseNodes(json_doc_);
588 std::unordered_map<std::string, Hint> actions = HintManager::ParseActions(json_doc_, nodes);
589 EXPECT_EQ(7u, actions.size());
590
591 EXPECT_EQ(2u, actions["INTERACTION"].node_actions.size());
592 EXPECT_EQ(1u, actions["INTERACTION"].node_actions[0].node_index);
593 EXPECT_EQ(1u, actions["INTERACTION"].node_actions[0].value_index);
594 EXPECT_EQ(std::chrono::milliseconds(800).count(),
595 actions["INTERACTION"].node_actions[0].timeout_ms.count());
596
597 EXPECT_EQ(2u, actions["INTERACTION"].node_actions[1].node_index);
598 EXPECT_EQ(1u, actions["INTERACTION"].node_actions[1].value_index);
599 EXPECT_EQ(std::chrono::milliseconds(800).count(),
600 actions["INTERACTION"].node_actions[1].timeout_ms.count());
601
602 EXPECT_EQ(3u, actions["LAUNCH"].node_actions.size());
603
604 EXPECT_EQ(0u, actions["LAUNCH"].node_actions[0].node_index);
605 EXPECT_EQ(1u, actions["LAUNCH"].node_actions[0].value_index);
606 EXPECT_EQ(std::chrono::milliseconds(500).count(),
607 actions["LAUNCH"].node_actions[0].timeout_ms.count());
608
609 EXPECT_EQ(2u, actions["LAUNCH"].node_actions[1].node_index);
610 EXPECT_EQ(0u, actions["LAUNCH"].node_actions[1].value_index);
611 EXPECT_EQ(std::chrono::milliseconds(500).count(),
612 actions["LAUNCH"].node_actions[1].timeout_ms.count());
613
614 EXPECT_EQ(1u, actions["LAUNCH"].node_actions[2].node_index);
615 EXPECT_EQ(0u, actions["LAUNCH"].node_actions[2].value_index);
616 EXPECT_EQ(std::chrono::milliseconds(2000).count(),
617 actions["LAUNCH"].node_actions[2].timeout_ms.count());
618 EXPECT_EQ("vendor.pwhal.enable.test", actions["LAUNCH"].node_actions[2].enable_property);
619
620 EXPECT_EQ(1u, actions["MASK_LAUNCH_MODE"].hint_actions.size());
621 EXPECT_EQ(HintActionType::MaskHint, actions["MASK_LAUNCH_MODE"].hint_actions[0].type);
622 EXPECT_EQ("LAUNCH", actions["MASK_LAUNCH_MODE"].hint_actions[0].value);
623
624 EXPECT_EQ(2u, actions["MASK_LAUNCH_INTERACTION_MODE"].hint_actions.size());
625 EXPECT_EQ(HintActionType::MaskHint,
626 actions["MASK_LAUNCH_INTERACTION_MODE"].hint_actions[0].type);
627 EXPECT_EQ("LAUNCH", actions["MASK_LAUNCH_INTERACTION_MODE"].hint_actions[0].value);
628 EXPECT_EQ(HintActionType::MaskHint,
629 actions["MASK_LAUNCH_INTERACTION_MODE"].hint_actions[1].type);
630 EXPECT_EQ("INTERACTION", actions["MASK_LAUNCH_INTERACTION_MODE"].hint_actions[1].value);
631
632 EXPECT_EQ(1u, actions["DO_LAUNCH_MODE"].hint_actions.size());
633 EXPECT_EQ(HintActionType::DoHint, actions["DO_LAUNCH_MODE"].hint_actions[0].type);
634 EXPECT_EQ("LAUNCH", actions["DO_LAUNCH_MODE"].hint_actions[0].value);
635
636 EXPECT_EQ(1u, actions["END_LAUNCH_MODE"].hint_actions.size());
637 EXPECT_EQ(HintActionType::EndHint, actions["END_LAUNCH_MODE"].hint_actions[0].type);
638 EXPECT_EQ("LAUNCH", actions["END_LAUNCH_MODE"].hint_actions[0].value);
639 }
640
641 // Test parsing actions with duplicate File node
TEST_F(HintManagerTest,ParseActionDuplicateFileNodeTest)642 TEST_F(HintManagerTest, ParseActionDuplicateFileNodeTest) {
643 std::string from = R"("Node": "CPUCluster0MinFreq")";
644 size_t start_pos = json_doc_.find(from);
645 json_doc_.replace(start_pos, from.length(), R"("Node": "CPUCluster1MinFreq")");
646 std::vector<std::unique_ptr<Node>> nodes =
647 HintManager::ParseNodes(json_doc_);
648 EXPECT_EQ(4u, nodes.size());
649 auto actions = HintManager::ParseActions(json_doc_, nodes);
650 EXPECT_EQ(0u, actions.size());
651 }
652
653 // Test parsing actions with duplicate Property node
TEST_F(HintManagerTest,ParseActionDuplicatePropertyNodeTest)654 TEST_F(HintManagerTest, ParseActionDuplicatePropertyNodeTest) {
655 std::string from = R"("Node": "CPUCluster0MinFreq")";
656 size_t start_pos = json_doc_.find(from);
657 json_doc_.replace(start_pos, from.length(), R"("Node": "ModeProperty")");
658 auto nodes = HintManager::ParseNodes(json_doc_);
659 EXPECT_EQ(4u, nodes.size());
660 auto actions = HintManager::ParseActions(json_doc_, nodes);
661 EXPECT_EQ(0u, actions.size());
662 }
663
664 // Test parsing invalid json for actions
TEST_F(HintManagerTest,ParseBadActionsTest)665 TEST_F(HintManagerTest, ParseBadActionsTest) {
666 std::vector<std::unique_ptr<Node>> nodes =
667 HintManager::ParseNodes(json_doc_);
668 auto actions = HintManager::ParseActions("invalid json", nodes);
669 EXPECT_EQ(0u, actions.size());
670 actions = HintManager::ParseActions(
671 "{\"devices\":{\"15\":[\"armeabi-v7a\"],\"16\":[\"armeabi-v7a\"],"
672 "\"26\":[\"armeabi-v7a\",\"arm64-v8a\",\"x86\",\"x86_64\"]}}",
673 nodes);
674 EXPECT_EQ(0u, actions.size());
675 }
676
677 // Test hint/cancel/expire with json config
TEST_F(HintManagerTest,GetFromJSONTest)678 TEST_F(HintManagerTest, GetFromJSONTest) {
679 TemporaryFile json_file;
680 ASSERT_TRUE(android::base::WriteStringToFile(json_doc_, json_file.path))
681 << strerror(errno);
682 HintManager *hm = HintManager::GetFromJSON(json_file.path, false);
683 EXPECT_NE(nullptr, hm);
684 EXPECT_FALSE(hm->IsRunning());
685 EXPECT_TRUE(hm->Start());
686 EXPECT_TRUE(hm->IsRunning());
687 hm = HintManager::GetFromJSON(json_file.path);
688 EXPECT_NE(nullptr, hm);
689 EXPECT_TRUE(hm->IsRunning());
690 std::this_thread::sleep_for(kSLEEP_TOLERANCE_MS);
691 EXPECT_TRUE(hm->IsRunning());
692 // Initial default value on Node0
693 _VerifyPathValue(files_[0 + 2]->path, "384000");
694 _VerifyPathValue(files_[1 + 2]->path, "");
695 _VerifyPropertyValue(prop_, "");
696 // Do INTERACTION
697 EXPECT_TRUE(hm->DoHint("INTERACTION"));
698 std::this_thread::sleep_for(kSLEEP_TOLERANCE_MS);
699 _VerifyPathValue(files_[0 + 2]->path, "384000");
700 _VerifyPathValue(files_[1 + 2]->path, "1134000");
701 _VerifyPropertyValue(prop_, "LOW");
702 // Do LAUNCH
703 _VerifyPropertyValue("vendor.pwhal.enable.test", "1");
704 EXPECT_TRUE(hm->DoHint("LAUNCH"));
705 std::this_thread::sleep_for(kSLEEP_TOLERANCE_MS);
706 _VerifyPathValue(files_[0 + 2]->path, "1134000");
707 _VerifyPathValue(files_[1 + 2]->path, "1512000");
708 _VerifyPropertyValue(prop_, "HIGH");
709 std::this_thread::sleep_for(500ms);
710 // "LAUNCH" node0 expired
711 _VerifyPathValue(files_[0 + 2]->path, "384000");
712 _VerifyPathValue(files_[1 + 2]->path, "1512000");
713 _VerifyPropertyValue(prop_, "LOW");
714 EXPECT_TRUE(hm->EndHint("LAUNCH"));
715 std::this_thread::sleep_for(kSLEEP_TOLERANCE_MS);
716 // "LAUNCH" canceled
717 _VerifyPathValue(files_[0 + 2]->path, "384000");
718 _VerifyPathValue(files_[1 + 2]->path, "1134000");
719 _VerifyPropertyValue(prop_, "LOW");
720 std::this_thread::sleep_for(300ms);
721 // "INTERACTION" node1 expired
722 _VerifyPathValue(files_[0 + 2]->path, "384000");
723 _VerifyPathValue(files_[1 + 2]->path, "384000");
724 _VerifyPropertyValue(prop_, "NONE");
725
726 // Disable action[2] of LAUNCH
727 EXPECT_TRUE(hm->EndHint("LAUNCH"));
728 _VerifyPropertyValue("vendor.pwhal.enable.test", "1");
729 EXPECT_TRUE(hm->DoHint("DISABLE_LAUNCH_ACT2"));
730 std::this_thread::sleep_for(kSLEEP_TOLERANCE_MS);
731 _VerifyPropertyValue("vendor.pwhal.enable.test", "0");
732 EXPECT_TRUE(hm->DoHint("LAUNCH"));
733 std::this_thread::sleep_for(kSLEEP_TOLERANCE_MS);
734 _VerifyPathValue(files_[0 + 2]->path, "1134000");
735 // action[2] have no effect.
736 _VerifyPathValue(files_[1 + 2]->path, "384000");
737 _VerifyPropertyValue(prop_, "HIGH");
738 EXPECT_TRUE(hm->EndHint("LAUNCH"));
739 EXPECT_TRUE(hm->EndHint("DISABLE_LAUNCH_ACT2"));
740
741 // Mask LAUNCH and do LAUNCH
742 EXPECT_TRUE(hm->DoHint("MASK_LAUNCH_MODE"));
743 EXPECT_FALSE(hm->DoHint("LAUNCH")); // should fail
744 std::this_thread::sleep_for(kSLEEP_TOLERANCE_MS);
745 _VerifyPathValue(files_[0 + 2]->path, "384000");
746 _VerifyPathValue(files_[1 + 2]->path, "384000");
747 _VerifyPropertyValue(prop_, "NONE");
748
749 // UnMask LAUNCH and do LAUNCH
750 EXPECT_TRUE(hm->EndHint("MASK_LAUNCH_MODE"));
751 EXPECT_TRUE(hm->DoHint("LAUNCH"));
752 std::this_thread::sleep_for(kSLEEP_TOLERANCE_MS);
753 _VerifyPathValue(files_[0 + 2]->path, "1134000");
754 _VerifyPathValue(files_[1 + 2]->path, "1512000");
755 _VerifyPropertyValue(prop_, "HIGH");
756 // END_LAUNCH_MODE should deactivate LAUNCH
757 EXPECT_TRUE(hm->DoHint("END_LAUNCH_MODE"));
758 std::this_thread::sleep_for(kSLEEP_TOLERANCE_MS);
759 _VerifyPathValue(files_[0 + 2]->path, "384000");
760 _VerifyPathValue(files_[1 + 2]->path, "384000");
761 _VerifyPropertyValue(prop_, "NONE");
762 EXPECT_TRUE(hm->EndHint("END_LAUNCH_MODE"));
763
764 // DO_LAUNCH_MODE should activate LAUNCH
765 EXPECT_TRUE(hm->DoHint("DO_LAUNCH_MODE"));
766 std::this_thread::sleep_for(kSLEEP_TOLERANCE_MS);
767 _VerifyPathValue(files_[0 + 2]->path, "1134000");
768 _VerifyPathValue(files_[1 + 2]->path, "1512000");
769 _VerifyPropertyValue(prop_, "HIGH");
770
771 // Mask LAUNCH
772 EXPECT_TRUE(hm->DoHint("MASK_LAUNCH_MODE"));
773 EXPECT_FALSE(hm->IsHintEnabled("LAUNCH"));
774 // Mask LAUNCH and INTERACTION
775 EXPECT_TRUE(hm->DoHint("MASK_LAUNCH_INTERACTION_MODE"));
776 EXPECT_FALSE(hm->IsHintEnabled("LAUNCH"));
777 EXPECT_FALSE(hm->IsHintEnabled("INTERACTION"));
778 // End Mask LAUNCH and INTERACTION
779 EXPECT_TRUE(hm->EndHint("MASK_LAUNCH_INTERACTION_MODE"));
780 EXPECT_FALSE(hm->IsHintEnabled("LAUNCH"));
781 EXPECT_TRUE(hm->IsHintEnabled("INTERACTION"));
782 // End Mask LAUNCH
783 EXPECT_TRUE(hm->EndHint("MASK_LAUNCH_MODE"));
784 EXPECT_TRUE(hm->IsHintEnabled("LAUNCH"));
785 }
786
787 // Test parsing AdpfConfig
TEST_F(HintManagerTest,ParseAdpfConfigsTest)788 TEST_F(HintManagerTest, ParseAdpfConfigsTest) {
789 std::vector<std::shared_ptr<AdpfConfig>> adpfs = HintManager::ParseAdpfConfigs(json_doc_);
790 EXPECT_EQ(2u, adpfs.size());
791 EXPECT_EQ("REFRESH_120FPS", adpfs[0]->mName);
792 EXPECT_EQ("REFRESH_60FPS", adpfs[1]->mName);
793 EXPECT_TRUE(adpfs[0]->mPidOn);
794 EXPECT_FALSE(adpfs[1]->mPidOn);
795 EXPECT_EQ(5.0, adpfs[0]->mPidPo);
796 EXPECT_EQ(0.0, adpfs[1]->mPidPo);
797 EXPECT_EQ(3.0, adpfs[0]->mPidPu);
798 EXPECT_EQ(0.0, adpfs[1]->mPidPu);
799 EXPECT_EQ(0.001, adpfs[0]->mPidI);
800 EXPECT_EQ(0.0, adpfs[1]->mPidI);
801 EXPECT_EQ(200LL, adpfs[0]->mPidIInit);
802 EXPECT_EQ(0LL, adpfs[1]->mPidIInit);
803 EXPECT_EQ(512LL, adpfs[0]->mPidIHigh);
804 EXPECT_EQ(0LL, adpfs[1]->mPidIHigh);
805 EXPECT_EQ(-120LL, adpfs[0]->mPidILow);
806 EXPECT_EQ(0LL, adpfs[1]->mPidILow);
807 EXPECT_EQ(500.0, adpfs[0]->mPidDo);
808 EXPECT_EQ(0.0, adpfs[1]->mPidDo);
809 EXPECT_EQ(500.0, adpfs[0]->mPidDo);
810 EXPECT_EQ(0.0, adpfs[1]->mPidDo);
811 EXPECT_EQ(1LLU, adpfs[0]->mSamplingWindowP);
812 EXPECT_EQ(0LLU, adpfs[1]->mSamplingWindowP);
813 EXPECT_EQ(0LLU, adpfs[0]->mSamplingWindowI);
814 EXPECT_EQ(0LLU, adpfs[1]->mSamplingWindowI);
815 EXPECT_EQ(1LLU, adpfs[0]->mSamplingWindowD);
816 EXPECT_EQ(0LLU, adpfs[1]->mSamplingWindowD);
817 EXPECT_TRUE(adpfs[0]->mUclampMinOn);
818 EXPECT_TRUE(adpfs[1]->mUclampMinOn);
819 EXPECT_EQ(100U, adpfs[0]->mUclampMinInit);
820 EXPECT_EQ(200U, adpfs[0]->mUclampMinLoadUp);
821 EXPECT_EQ(300U, adpfs[0]->mUclampMinLoadReset);
822 EXPECT_EQ(200U, adpfs[1]->mUclampMinInit);
823 EXPECT_EQ(384U, adpfs[0]->mUclampMinHigh);
824 EXPECT_EQ(157U, adpfs[1]->mUclampMinHigh);
825 EXPECT_EQ(157U, adpfs[1]->mUclampMinLoadUp);
826 EXPECT_EQ(157U, adpfs[1]->mUclampMinLoadReset);
827 EXPECT_EQ(0U, adpfs[0]->mUclampMinLow);
828 EXPECT_EQ(157U, adpfs[1]->mUclampMinLow);
829 EXPECT_EQ(166666660LL, adpfs[0]->mReportingRateLimitNs);
830 EXPECT_EQ(83333330LL, adpfs[1]->mReportingRateLimitNs);
831 EXPECT_EQ(1.0, adpfs[0]->mTargetTimeFactor);
832 EXPECT_EQ(1.4, adpfs[1]->mTargetTimeFactor);
833 EXPECT_EQ(10.0, adpfs[0]->mStaleTimeFactor);
834 EXPECT_EQ(5.0, adpfs[1]->mStaleTimeFactor);
835 EXPECT_TRUE(adpfs[0]->mHeuristicBoostOn.value());
836 EXPECT_FALSE(adpfs[1]->mHeuristicBoostOn.has_value());
837 EXPECT_EQ(4U, adpfs[0]->mHBoostOnMissedCycles.value());
838 EXPECT_FALSE(adpfs[1]->mHBoostOnMissedCycles.has_value());
839 EXPECT_EQ(4.0, adpfs[0]->mHBoostOffMaxAvgRatio.value());
840 EXPECT_FALSE(adpfs[1]->mHBoostOffMaxAvgRatio.has_value());
841 EXPECT_EQ(2U, adpfs[0]->mHBoostOffMissedCycles.value());
842 EXPECT_FALSE(adpfs[1]->mHBoostOffMissedCycles.has_value());
843 EXPECT_EQ(0.5, adpfs[0]->mHBoostPidPuFactor.value());
844 EXPECT_FALSE(adpfs[1]->mHBoostPidPuFactor.has_value());
845 EXPECT_EQ(800U, adpfs[0]->mHBoostUclampMin.value());
846 EXPECT_FALSE(adpfs[1]->mHBoostUclampMin.has_value());
847 EXPECT_EQ(1.2, adpfs[0]->mJankCheckTimeFactor.value());
848 EXPECT_FALSE(adpfs[1]->mJankCheckTimeFactor.has_value());
849 EXPECT_EQ(25U, adpfs[0]->mLowFrameRateThreshold.value());
850 EXPECT_FALSE(adpfs[1]->mLowFrameRateThreshold.has_value());
851 EXPECT_EQ(50U, adpfs[0]->mMaxRecordsNum.value());
852 EXPECT_FALSE(adpfs[1]->mMaxRecordsNum.has_value());
853 }
854
855 // Test parsing adpf configs with duplicate name
TEST_F(HintManagerTest,ParseAdpfConfigsDuplicateNameTest)856 TEST_F(HintManagerTest, ParseAdpfConfigsDuplicateNameTest) {
857 std::string from = "REFRESH_120FPS";
858 size_t start_pos = json_doc_.find(from);
859 json_doc_.replace(start_pos, from.length(), "REFRESH_60FPS");
860 std::vector<std::shared_ptr<AdpfConfig>> adpfs = HintManager::ParseAdpfConfigs(json_doc_);
861 EXPECT_EQ(0u, adpfs.size());
862 }
863
864 // Test parsing adpf configs without PID_Po
TEST_F(HintManagerTest,ParseAdpfConfigsWithoutPIDPoTest)865 TEST_F(HintManagerTest, ParseAdpfConfigsWithoutPIDPoTest) {
866 std::string from = "\"PID_Po\": 0,";
867 size_t start_pos = json_doc_.find(from);
868 json_doc_.replace(start_pos, from.length(), "");
869 std::vector<std::shared_ptr<AdpfConfig>> adpfs = HintManager::ParseAdpfConfigs(json_doc_);
870 EXPECT_EQ(0u, adpfs.size());
871 }
872
873 // Test parsing adpf configs with partially missing heuristic boost config
TEST_F(HintManagerTest,ParseAdpfConfigsWithBrokenHBoostConfig)874 TEST_F(HintManagerTest, ParseAdpfConfigsWithBrokenHBoostConfig) {
875 std::string from = "\"HBoostUclampMin\": 800,";
876 size_t start_pos = json_doc_.find(from);
877 json_doc_.replace(start_pos, from.length(), "");
878 std::vector<std::shared_ptr<AdpfConfig>> adpfs = HintManager::ParseAdpfConfigs(json_doc_);
879 EXPECT_EQ(0u, adpfs.size());
880 }
881
882 // Test hint/cancel/expire with json config
TEST_F(HintManagerTest,GetFromJSONAdpfConfigTest)883 TEST_F(HintManagerTest, GetFromJSONAdpfConfigTest) {
884 TemporaryFile json_file;
885 ASSERT_TRUE(android::base::WriteStringToFile(json_doc_, json_file.path)) << strerror(errno);
886 HintManager *hm = HintManager::GetFromJSON(json_file.path, false);
887 EXPECT_NE(nullptr, hm);
888 EXPECT_TRUE(hm->Start());
889 EXPECT_TRUE(hm->IsRunning());
890
891 // Get default Adpf Profile
892 EXPECT_EQ("REFRESH_120FPS", hm->GetAdpfProfile()->mName);
893
894 // Set specific Adpf Profile
895 EXPECT_FALSE(hm->SetAdpfProfile("NoSuchProfile"));
896 EXPECT_TRUE(hm->SetAdpfProfile("REFRESH_60FPS"));
897 EXPECT_EQ("REFRESH_60FPS", hm->GetAdpfProfile()->mName);
898 EXPECT_TRUE(hm->SetAdpfProfile("REFRESH_120FPS"));
899 EXPECT_EQ("REFRESH_120FPS", hm->GetAdpfProfile()->mName);
900 }
901
TEST_F(HintManagerTest,IsAdpfProfileSupported)902 TEST_F(HintManagerTest, IsAdpfProfileSupported) {
903 TemporaryFile json_file;
904 ASSERT_TRUE(android::base::WriteStringToFile(json_doc_, json_file.path)) << strerror(errno);
905 HintManager *hm = HintManager::GetFromJSON(json_file.path, false);
906 EXPECT_NE(nullptr, hm);
907
908 // Check if given AdpfProfile supported
909 EXPECT_FALSE(hm->IsAdpfProfileSupported("NoSuchProfile"));
910 EXPECT_TRUE(hm->IsAdpfProfileSupported("REFRESH_60FPS"));
911 EXPECT_TRUE(hm->IsAdpfProfileSupported("REFRESH_120FPS"));
912 }
913
TEST_F(HintManagerTest,GpuConfigSupport)914 TEST_F(HintManagerTest, GpuConfigSupport) {
915 TemporaryFile json_file;
916 ASSERT_TRUE(android::base::WriteStringToFile(json_doc_, json_file.path)) << strerror(errno);
917 HintManager *hm = HintManager::GetFromJSON(json_file.path, false);
918 ASSERT_TRUE(hm);
919
920 EXPECT_THAT(hm->gpu_sysfs_config_path(), Optional(Eq("/sys/devices/platform/123.abc")));
921 ASSERT_TRUE(hm->SetAdpfProfile("REFRESH_120FPS"));
922 auto profile = hm->GetAdpfProfile();
923 EXPECT_THAT(profile->mGpuBoostOn, Optional(true));
924 EXPECT_THAT(profile->mGpuBoostCapacityMax, Optional(300000));
925 EXPECT_EQ(profile->mGpuCapacityLoadUpHeadroom, 1000);
926
927 ASSERT_TRUE(hm->SetAdpfProfile("REFRESH_60FPS"));
928 profile = hm->GetAdpfProfile();
929 EXPECT_FALSE(profile->mGpuBoostOn);
930 EXPECT_FALSE(profile->mGpuBoostCapacityMax);
931 EXPECT_EQ(profile->mGpuCapacityLoadUpHeadroom, 0);
932 }
933
934 } // namespace perfmgr
935 } // namespace android
936