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 specific 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 }
153 )";
154
155 constexpr char kJSON_ADPF[] = R"(
156 {
157 "Nodes": [
158 {
159 "Name": "OTHER",
160 "Path": "<AdpfConfig>:OTHER",
161 "Values": [
162 "ADPF_DEFAULT"
163 ],
164 "Type": "Event"
165 },
166 {
167 "Name": "SURFACEFLINGER",
168 "Path": "<AdpfConfig>:SURFACEFLINGER",
169 "Values": [
170 "ADPF_DEFAULT",
171 "ADPF_SF"
172 ],
173 "Type": "Event"
174 }
175 ],
176 "Actions": [
177 {
178 "PowerHint": "SF_PLAYING",
179 "Node": "SURFACEFLINGER",
180 "Duration": 0,
181 "Value": "ADPF_SF"
182 },
183 {
184 "PowerHint": "SF_RESET",
185 "Node": "SURFACEFLINGER",
186 "Duration": 0,
187 "Value": "ADPF_DEFAULT"
188 }
189 ],
190 "AdpfConfig": [
191 {
192 "Name": "ADPF_DEFAULT",
193 "PID_On": true,
194 "PID_Po": 5.0,
195 "PID_Pu": 3.0,
196 "PID_I": 0.001,
197 "PID_I_Init": 200,
198 "PID_I_High": 512,
199 "PID_I_Low": -120,
200 "PID_Do": 500.0,
201 "PID_Du": 0.0,
202 "SamplingWindow_P": 1,
203 "SamplingWindow_I": 0,
204 "SamplingWindow_D": 1,
205 "UclampMin_On": true,
206 "UclampMin_Init": 100,
207 "UclampMin_LoadUp": 200,
208 "UclampMin_LoadReset": 300,
209 "UclampMin_High": 384,
210 "UclampMin_Low": 0,
211 "ReportingRateLimitNs": 166666660,
212 "TargetTimeFactor": 1.0,
213 "StaleTimeFactor": 10.0,
214 "GpuBoost": true,
215 "GpuCapacityBoostMax": 325000,
216 "GpuCapacityLoadUpHeadroom": 1000,
217 "HeuristicBoost_On": true,
218 "HBoostModerateJankThreshold": 4,
219 "HBoostOffMaxAvgDurRatio": 4.0,
220 "HBoostSevereJankPidPu": 0.5,
221 "HBoostSevereJankThreshold": 2,
222 "HBoostUclampMinCeilingRange": [480, 800],
223 "HBoostUclampMinFloorRange": [200, 400],
224 "JankCheckTimeFactor": 1.2,
225 "LowFrameRateThreshold": 25,
226 "MaxRecordsNum": 50
227 },
228 {
229 "Name": "ADPF_SF",
230 "PID_On": false,
231 "PID_Po": 0,
232 "PID_Pu": 0,
233 "PID_I": 0,
234 "PID_I_Init": 0,
235 "PID_I_High": 0,
236 "PID_I_Low": 0,
237 "PID_Do": 0,
238 "PID_Du": 0,
239 "SamplingWindow_P": 0,
240 "SamplingWindow_I": 0,
241 "SamplingWindow_D": 0,
242 "UclampMin_On": true,
243 "UclampMin_Init": 200,
244 "UclampMin_LoadUp": 157,
245 "UclampMin_LoadReset": 157,
246 "UclampMin_High": 157,
247 "UclampMin_Low": 157,
248 "ReportingRateLimitNs": 83333330,
249 "TargetTimeFactor": 1.4,
250 "StaleTimeFactor": 5.0
251 },
252 {
253 "Name": "SF_VIDEO_30FPS",
254 "PID_On": true,
255 "PID_Po": 5.0,
256 "PID_Pu": 3.0,
257 "PID_I": 0.001,
258 "PID_I_Init": 200,
259 "PID_I_High": 512,
260 "PID_I_Low": -120,
261 "PID_Do": 500.0,
262 "PID_Du": 300.0,
263 "SamplingWindow_P": 0,
264 "SamplingWindow_I": 0,
265 "SamplingWindow_D": 0,
266 "UclampMin_On": true,
267 "UclampMin_Init": 200,
268 "UclampMin_LoadUp": 157,
269 "UclampMin_LoadReset": 157,
270 "UclampMin_High": 480,
271 "UclampMin_Low": 240,
272 "ReportingRateLimitNs": 83333330,
273 "TargetTimeFactor": 1.4,
274 "StaleTimeFactor": 5.0,
275 "GpuBoost": false,
276 "GpuCapacityBoostMax": 32500
277 }
278 ],
279 "GpuSysfsPath" : "/sys/devices/platform/123.abc"
280 }
281 )";
282
283 class HintManagerTest : public ::testing::Test, public HintManager {
284 protected:
HintManagerTest()285 HintManagerTest()
286 : HintManager(nullptr, std::unordered_map<std::string, Hint>{},
287 std::vector<std::shared_ptr<AdpfConfig>>(), tag_adpfs_, {}) {
288 android::base::SetMinimumLogSeverity(android::base::VERBOSE);
289 prop_ = "vendor.pwhal.mode";
290 }
291
SetUp()292 virtual void SetUp() {
293 // Set up 3 dummy nodes
294 std::unique_ptr<TemporaryFile> tf = std::make_unique<TemporaryFile>();
295 nodes_.emplace_back(new FileNode(
296 "n0", tf->path, {{"n0_value0"}, {"n0_value1"}, {"n0_value2"}}, 2,
297 false, false));
298 files_.emplace_back(std::move(tf));
299 tf = std::make_unique<TemporaryFile>();
300 nodes_.emplace_back(new FileNode(
301 "n1", tf->path, {{"n1_value0"}, {"n1_value1"}, {"n1_value2"}}, 2,
302 true, true));
303 files_.emplace_back(std::move(tf));
304 nodes_.emplace_back(new PropertyNode(
305 "n2", prop_, {{"n2_value0"}, {"n2_value1"}, {"n2_value2"}}, 2,
306 true));
307 nm_ = new NodeLooperThread(std::move(nodes_));
308 // Set up dummy actions
309 // "INTERACTION"
310 // Node0, value1, 800ms
311 // Node1, value1, forever
312 // Node2, value1, 800ms
313 // "LAUNCH"
314 // Node0, value0, forever
315 // Node1, value0, 400ms
316 // Node2, value0, 400ms
317 actions_["INTERACTION"].node_actions =
318 std::vector<NodeAction>{{0, 1, 800ms}, {1, 1, 0ms}, {2, 1, 800ms}};
319 actions_["LAUNCH"].node_actions =
320 std::vector<NodeAction>{{0, 0, 0ms}, {1, 0, 400ms}, {2, 0, 400ms}};
321
322 // Prepare dummy files to replace the nodes' path in example json_doc
323 files_.emplace_back(std::make_unique<TemporaryFile>());
324 files_.emplace_back(std::make_unique<TemporaryFile>());
325 // replace file path
326 json_doc_ = kJSON_RAW;
327 std::string from =
328 "/sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq";
329 size_t start_pos = json_doc_.find(from);
330 json_doc_.replace(start_pos, from.length(), files_[0 + 2]->path);
331 from = "/sys/devices/system/cpu/cpu4/cpufreq/scaling_min_freq";
332 start_pos = json_doc_.find(from);
333 json_doc_.replace(start_pos, from.length(), files_[1 + 2]->path);
334 EXPECT_TRUE(android::base::SetProperty(prop_, "")) << "failed to clear property";
335 }
336
TearDown()337 virtual void TearDown() {
338 actions_.clear();
339 nodes_.clear();
340 files_.clear();
341 nm_ = nullptr;
342 tag_adpfs_.clear();
343 }
344 sp<NodeLooperThread> nm_;
345 std::unordered_map<std::string, Hint> actions_;
346 std::vector<std::unique_ptr<Node>> nodes_;
347 std::vector<std::unique_ptr<TemporaryFile>> files_;
348 std::string json_doc_;
349 std::string prop_;
350 std::unordered_map<std::string, std::shared_ptr<AdpfConfig>> tag_adpfs_;
351 };
352
_VerifyPropertyValue(const std::string & path,const std::string & value)353 static inline void _VerifyPropertyValue(const std::string& path,
354 const std::string& value) {
355 std::string s = android::base::GetProperty(path, "");
356 EXPECT_EQ(value, s);
357 }
358
_VerifyPathValue(const std::string & path,const std::string & value)359 static inline void _VerifyPathValue(const std::string& path,
360 const std::string& value) {
361 std::string s;
362 EXPECT_TRUE(android::base::ReadFileToString(path, &s)) << strerror(errno);
363 EXPECT_EQ(value, s);
364 }
365
_VerifyStats(const HintStats & stats,uint32_t count,uint64_t duration_min,uint64_t duration_max)366 static inline void _VerifyStats(const HintStats &stats, uint32_t count, uint64_t duration_min,
367 uint64_t duration_max) {
368 EXPECT_EQ(stats.count, count);
369 EXPECT_GE(stats.duration_ms, duration_min);
370 EXPECT_LT(stats.duration_ms, duration_max);
371 }
372
373 // Test GetHints
TEST_F(HintManagerTest,GetHintsTest)374 TEST_F(HintManagerTest, GetHintsTest) {
375 HintManager hm(nm_, actions_, std::vector<std::shared_ptr<AdpfConfig>>(), tag_adpfs_, {});
376 EXPECT_TRUE(hm.Start());
377 std::vector<std::string> hints = hm.GetHints();
378 EXPECT_TRUE(hm.IsRunning());
379 EXPECT_EQ(2u, hints.size());
380 EXPECT_NE(std::find(hints.begin(), hints.end(), "INTERACTION"), hints.end());
381 EXPECT_NE(std::find(hints.begin(), hints.end(), "LAUNCH"), hints.end());
382 }
383
384 // Test GetHintStats
TEST_F(HintManagerTest,GetHintStatsTest)385 TEST_F(HintManagerTest, GetHintStatsTest) {
386 auto hm =
387 std::make_unique<HintManager>(nm_, actions_, std::vector<std::shared_ptr<AdpfConfig>>(),
388 tag_adpfs_, std::optional<std::string>{});
389 EXPECT_TRUE(InitHintStatus(hm));
390 EXPECT_TRUE(hm->Start());
391 HintStats launch_stats(hm->GetHintStats("LAUNCH"));
392 EXPECT_EQ(0, launch_stats.count);
393 EXPECT_EQ(0, launch_stats.duration_ms);
394 HintStats interaction_stats(hm->GetHintStats("INTERACTION"));
395 EXPECT_EQ(0, interaction_stats.count);
396 EXPECT_EQ(0, interaction_stats.duration_ms);
397 }
398
399 // Test initialization of default values
TEST_F(HintManagerTest,HintInitDefaultTest)400 TEST_F(HintManagerTest, HintInitDefaultTest) {
401 HintManager hm(nm_, actions_, std::vector<std::shared_ptr<AdpfConfig>>(), tag_adpfs_, {});
402 EXPECT_TRUE(hm.Start());
403 std::this_thread::sleep_for(kSLEEP_TOLERANCE_MS);
404 EXPECT_TRUE(hm.IsRunning());
405 _VerifyPathValue(files_[0]->path, "");
406 _VerifyPathValue(files_[1]->path, "n1_value2");
407 _VerifyPropertyValue(prop_, "n2_value2");
408 }
409
410 // Test IsHintSupported
TEST_F(HintManagerTest,HintSupportedTest)411 TEST_F(HintManagerTest, HintSupportedTest) {
412 HintManager hm(nm_, actions_, std::vector<std::shared_ptr<AdpfConfig>>(), tag_adpfs_, {});
413 EXPECT_TRUE(hm.IsHintSupported("INTERACTION"));
414 EXPECT_TRUE(hm.IsHintSupported("LAUNCH"));
415 EXPECT_FALSE(hm.IsHintSupported("NO_SUCH_HINT"));
416 }
417
418 // Test hint/cancel/expire with dummy actions
TEST_F(HintManagerTest,HintTest)419 TEST_F(HintManagerTest, HintTest) {
420 auto hm =
421 std::make_unique<HintManager>(nm_, actions_, std::vector<std::shared_ptr<AdpfConfig>>(),
422 tag_adpfs_, std::optional<std::string>{});
423 EXPECT_TRUE(InitHintStatus(hm));
424 EXPECT_TRUE(hm->Start());
425 EXPECT_TRUE(hm->IsRunning());
426 EXPECT_TRUE(hm->DoHint("INTERACTION"));
427 std::this_thread::sleep_for(kSLEEP_TOLERANCE_MS);
428 _VerifyPathValue(files_[0]->path, "n0_value1");
429 _VerifyPathValue(files_[1]->path, "n1_value1");
430 _VerifyPropertyValue(prop_, "n2_value1");
431 // this won't change the expire time of INTERACTION hint
432 EXPECT_TRUE(hm->DoHint("INTERACTION", 200ms));
433 // now place new hint
434 EXPECT_TRUE(hm->DoHint("LAUNCH"));
435 std::this_thread::sleep_for(kSLEEP_TOLERANCE_MS);
436 _VerifyPathValue(files_[0]->path, "n0_value0");
437 _VerifyPathValue(files_[1]->path, "n1_value0");
438 _VerifyPropertyValue(prop_, "n2_value0");
439 EXPECT_TRUE(hm->DoHint("LAUNCH", 500ms));
440 // "LAUNCH" node1 not expired
441 std::this_thread::sleep_for(400ms);
442 _VerifyPathValue(files_[0]->path, "n0_value0");
443 _VerifyPathValue(files_[1]->path, "n1_value0");
444 _VerifyPropertyValue(prop_, "n2_value0");
445 // "LAUNCH" node1 expired
446 std::this_thread::sleep_for(100ms + kSLEEP_TOLERANCE_MS);
447 _VerifyPathValue(files_[0]->path, "n0_value0");
448 _VerifyPathValue(files_[1]->path, "n1_value1");
449 _VerifyPropertyValue(prop_, "n2_value1");
450 EXPECT_TRUE(hm->EndHint("LAUNCH"));
451 std::this_thread::sleep_for(kSLEEP_TOLERANCE_MS);
452 // "LAUNCH" canceled
453 _VerifyPathValue(files_[0]->path, "n0_value1");
454 _VerifyPathValue(files_[1]->path, "n1_value1");
455 _VerifyPropertyValue(prop_, "n2_value1");
456 std::this_thread::sleep_for(200ms);
457 // "INTERACTION" node0 expired
458 _VerifyPathValue(files_[0]->path, "n0_value2");
459 _VerifyPathValue(files_[1]->path, "n1_value1");
460 _VerifyPropertyValue(prop_, "n2_value2");
461 EXPECT_TRUE(hm->EndHint("INTERACTION"));
462 std::this_thread::sleep_for(kSLEEP_TOLERANCE_MS);
463 // "INTERACTION" canceled
464 _VerifyPathValue(files_[0]->path, "n0_value2");
465 _VerifyPathValue(files_[1]->path, "n1_value2");
466 _VerifyPropertyValue(prop_, "n2_value2");
467 }
468
469 // Test collecting stats with simple actions
TEST_F(HintManagerTest,HintStatsTest)470 TEST_F(HintManagerTest, HintStatsTest) {
471 auto hm =
472 std::make_unique<HintManager>(nm_, actions_, std::vector<std::shared_ptr<AdpfConfig>>(),
473 tag_adpfs_, std::optional<std::string>{});
474 EXPECT_TRUE(InitHintStatus(hm));
475 EXPECT_TRUE(hm->Start());
476 EXPECT_TRUE(hm->IsRunning());
477 EXPECT_TRUE(hm->DoHint("INTERACTION"));
478 std::this_thread::sleep_for(kSLEEP_TOLERANCE_MS);
479 _VerifyPathValue(files_[0]->path, "n0_value1");
480 _VerifyPathValue(files_[1]->path, "n1_value1");
481 _VerifyPropertyValue(prop_, "n2_value1");
482 // now place "LAUNCH" hint with timeout of 500ms
483 EXPECT_TRUE(hm->DoHint("LAUNCH", 500ms));
484 std::this_thread::sleep_for(kSLEEP_TOLERANCE_MS);
485 _VerifyPathValue(files_[0]->path, "n0_value0");
486 _VerifyPathValue(files_[1]->path, "n1_value0");
487 _VerifyPropertyValue(prop_, "n2_value0");
488 // "LAUNCH" expired
489 std::this_thread::sleep_for(500ms + kSLEEP_TOLERANCE_MS);
490 _VerifyPathValue(files_[0]->path, "n0_value1");
491 _VerifyPathValue(files_[1]->path, "n1_value1");
492 _VerifyPropertyValue(prop_, "n2_value1");
493 HintStats launch_stats(hm->GetHintStats("LAUNCH"));
494 // Since duration is recorded at the next DoHint,
495 // duration should be 0.
496 _VerifyStats(launch_stats, 1, 0, 100);
497 std::this_thread::sleep_for(100ms + kSLEEP_TOLERANCE_MS);
498 EXPECT_TRUE(hm->EndHint("INTERACTION"));
499 std::this_thread::sleep_for(kSLEEP_TOLERANCE_MS);
500 // "INTERACTION" canceled
501 _VerifyPathValue(files_[0]->path, "n0_value2");
502 _VerifyPathValue(files_[1]->path, "n1_value2");
503 _VerifyPropertyValue(prop_, "n2_value2");
504 HintStats interaction_stats(hm->GetHintStats("INTERACTION"));
505 _VerifyStats(interaction_stats, 1, 800, 900);
506 std::this_thread::sleep_for(kSLEEP_TOLERANCE_MS);
507 // Second LAUNCH hint sent to get the first duration recorded.
508 EXPECT_TRUE(hm->DoHint("LAUNCH"));
509 launch_stats = hm->GetHintStats("LAUNCH");
510 _VerifyStats(launch_stats, 2, 500, 600);
511 }
512
513 // Test parsing nodes
TEST_F(HintManagerTest,ParseNodesTest)514 TEST_F(HintManagerTest, ParseNodesTest) {
515 std::vector<std::unique_ptr<Node>> nodes = HintManager::ParseNodes(json_doc_);
516 EXPECT_EQ(4u, nodes.size());
517 EXPECT_EQ("CPUCluster0MinFreq", nodes[0]->GetName());
518 EXPECT_EQ("CPUCluster1MinFreq", nodes[1]->GetName());
519 EXPECT_EQ(files_[0 + 2]->path, nodes[0]->GetPath());
520 EXPECT_EQ(files_[1 + 2]->path, nodes[1]->GetPath());
521 EXPECT_EQ("1512000", nodes[0]->GetValues()[0]);
522 EXPECT_EQ("1134000", nodes[0]->GetValues()[1]);
523 EXPECT_EQ("384000", nodes[0]->GetValues()[2]);
524 EXPECT_EQ("1512000", nodes[1]->GetValues()[0]);
525 EXPECT_EQ("1134000", nodes[1]->GetValues()[1]);
526 EXPECT_EQ("384000", nodes[1]->GetValues()[2]);
527 EXPECT_EQ(2u, nodes[0]->GetDefaultIndex());
528 EXPECT_EQ(2u, nodes[1]->GetDefaultIndex());
529 EXPECT_TRUE(nodes[0]->GetResetOnInit());
530 EXPECT_FALSE(nodes[1]->GetResetOnInit());
531 // no dynamic_cast intentionally in Android
532 EXPECT_FALSE(reinterpret_cast<FileNode*>(nodes[0].get())->GetHoldFd());
533 EXPECT_TRUE(reinterpret_cast<FileNode*>(nodes[1].get())->GetHoldFd());
534 EXPECT_EQ("ModeProperty", nodes[2]->GetName());
535 EXPECT_EQ(prop_, nodes[2]->GetPath());
536 EXPECT_EQ("HIGH", nodes[2]->GetValues()[0]);
537 EXPECT_EQ("LOW", nodes[2]->GetValues()[1]);
538 EXPECT_EQ("NONE", nodes[2]->GetValues()[2]);
539 EXPECT_EQ(2u, nodes[2]->GetDefaultIndex());
540 EXPECT_FALSE(nodes[2]->GetResetOnInit());
541 }
542
543 // Test parsing nodes with duplicate name
TEST_F(HintManagerTest,ParseNodesDuplicateNameTest)544 TEST_F(HintManagerTest, ParseNodesDuplicateNameTest) {
545 std::string from = "CPUCluster0MinFreq";
546 size_t start_pos = json_doc_.find(from);
547 json_doc_.replace(start_pos, from.length(), "CPUCluster1MinFreq");
548 std::vector<std::unique_ptr<Node>> nodes = HintManager::ParseNodes(json_doc_);
549 EXPECT_EQ(0u, nodes.size());
550 }
551
TEST_F(HintManagerTest,ParsePropertyNodesDuplicatNameTest)552 TEST_F(HintManagerTest, ParsePropertyNodesDuplicatNameTest) {
553 std::string from = "ModeProperty";
554 size_t start_pos = json_doc_.find(from);
555 json_doc_.replace(start_pos, from.length(), "CPUCluster1MinFreq");
556 std::vector<std::unique_ptr<Node>> nodes = HintManager::ParseNodes(json_doc_);
557 EXPECT_EQ(0u, nodes.size());
558 }
559
560 // Test parsing nodes with duplicate path
TEST_F(HintManagerTest,ParseNodesDuplicatePathTest)561 TEST_F(HintManagerTest, ParseNodesDuplicatePathTest) {
562 std::string from = files_[0 + 2]->path;
563 size_t start_pos = json_doc_.find(from);
564 json_doc_.replace(start_pos, from.length(), files_[1 + 2]->path);
565 std::vector<std::unique_ptr<Node>> nodes = HintManager::ParseNodes(json_doc_);
566 EXPECT_EQ(0u, nodes.size());
567 }
568
569 // Test parsing file node with duplicate value
TEST_F(HintManagerTest,ParseFileNodesDuplicateValueTest)570 TEST_F(HintManagerTest, ParseFileNodesDuplicateValueTest) {
571 std::string from = "1512000";
572 size_t start_pos = json_doc_.find(from);
573 json_doc_.replace(start_pos, from.length(), "1134000");
574 std::vector<std::unique_ptr<Node>> nodes = HintManager::ParseNodes(json_doc_);
575 EXPECT_EQ(0u, nodes.size());
576 }
577
578 // Test parsing property node with duplicate value
TEST_F(HintManagerTest,ParsePropertyNodesDuplicateValueTest)579 TEST_F(HintManagerTest, ParsePropertyNodesDuplicateValueTest) {
580 std::string from = "HIGH";
581 size_t start_pos = json_doc_.find(from);
582 json_doc_.replace(start_pos, from.length(), "LOW");
583 std::vector<std::unique_ptr<Node>> nodes = HintManager::ParseNodes(json_doc_);
584 EXPECT_EQ(0u, nodes.size());
585 }
586
587 // Test parsing file node with empty value
TEST_F(HintManagerTest,ParseFileNodesEmptyValueTest)588 TEST_F(HintManagerTest, ParseFileNodesEmptyValueTest) {
589 std::string from = "384000";
590 size_t start_pos = json_doc_.find(from);
591 json_doc_.replace(start_pos, from.length(), "");
592 std::vector<std::unique_ptr<Node>> nodes = HintManager::ParseNodes(json_doc_);
593 EXPECT_EQ(0u, nodes.size());
594 }
595
596 // Test parsing property node with empty value
TEST_F(HintManagerTest,ParsePropertyNodesEmptyValueTest)597 TEST_F(HintManagerTest, ParsePropertyNodesEmptyValueTest) {
598 std::string from = "LOW";
599 size_t start_pos = json_doc_.find(from);
600 json_doc_.replace(start_pos, from.length(), "");
601 std::vector<std::unique_ptr<Node>> nodes = HintManager::ParseNodes(json_doc_);
602 EXPECT_EQ(4u, nodes.size());
603 EXPECT_EQ("CPUCluster0MinFreq", nodes[0]->GetName());
604 EXPECT_EQ("CPUCluster1MinFreq", nodes[1]->GetName());
605 EXPECT_EQ(files_[0 + 2]->path, nodes[0]->GetPath());
606 EXPECT_EQ(files_[1 + 2]->path, nodes[1]->GetPath());
607 EXPECT_EQ("1512000", nodes[0]->GetValues()[0]);
608 EXPECT_EQ("1134000", nodes[0]->GetValues()[1]);
609 EXPECT_EQ("384000", nodes[0]->GetValues()[2]);
610 EXPECT_EQ("1512000", nodes[1]->GetValues()[0]);
611 EXPECT_EQ("1134000", nodes[1]->GetValues()[1]);
612 EXPECT_EQ("384000", nodes[1]->GetValues()[2]);
613 EXPECT_EQ(2u, nodes[0]->GetDefaultIndex());
614 EXPECT_EQ(2u, nodes[1]->GetDefaultIndex());
615 EXPECT_TRUE(nodes[0]->GetResetOnInit());
616 EXPECT_FALSE(nodes[1]->GetResetOnInit());
617 // no dynamic_cast intentionally in Android
618 EXPECT_FALSE(reinterpret_cast<FileNode*>(nodes[0].get())->GetHoldFd());
619 EXPECT_TRUE(reinterpret_cast<FileNode*>(nodes[1].get())->GetHoldFd());
620 EXPECT_EQ("ModeProperty", nodes[2]->GetName());
621 EXPECT_EQ(prop_, nodes[2]->GetPath());
622 EXPECT_EQ("HIGH", nodes[2]->GetValues()[0]);
623 EXPECT_EQ("", nodes[2]->GetValues()[1]);
624 EXPECT_EQ("NONE", nodes[2]->GetValues()[2]);
625 EXPECT_EQ(2u, nodes[2]->GetDefaultIndex());
626 EXPECT_FALSE(nodes[2]->GetResetOnInit());
627 }
628
629 // Test parsing invalid json for nodes
TEST_F(HintManagerTest,ParseBadFileNodesTest)630 TEST_F(HintManagerTest, ParseBadFileNodesTest) {
631 std::vector<std::unique_ptr<Node>> nodes = HintManager::ParseNodes("invalid json");
632 EXPECT_EQ(0u, nodes.size());
633 nodes = HintManager::ParseNodes(
634 "{\"devices\":{\"15\":[\"armeabi-v7a\"],\"16\":[\"armeabi-v7a\"],"
635 "\"26\":[\"armeabi-v7a\",\"arm64-v8a\",\"x86\",\"x86_64\"]}}");
636 EXPECT_EQ(0u, nodes.size());
637 }
638
639 // Test parsing actions
TEST_F(HintManagerTest,ParseActionsTest)640 TEST_F(HintManagerTest, ParseActionsTest) {
641 std::vector<std::unique_ptr<Node>> nodes = HintManager::ParseNodes(json_doc_);
642 std::unordered_map<std::string, Hint> actions = HintManager::ParseActions(json_doc_, nodes);
643 EXPECT_EQ(7u, actions.size());
644
645 EXPECT_EQ(2u, actions["INTERACTION"].node_actions.size());
646 EXPECT_EQ(1u, actions["INTERACTION"].node_actions[0].node_index);
647 EXPECT_EQ(1u, actions["INTERACTION"].node_actions[0].value_index);
648 EXPECT_EQ(std::chrono::milliseconds(800).count(),
649 actions["INTERACTION"].node_actions[0].timeout_ms.count());
650
651 EXPECT_EQ(2u, actions["INTERACTION"].node_actions[1].node_index);
652 EXPECT_EQ(1u, actions["INTERACTION"].node_actions[1].value_index);
653 EXPECT_EQ(std::chrono::milliseconds(800).count(),
654 actions["INTERACTION"].node_actions[1].timeout_ms.count());
655
656 EXPECT_EQ(3u, actions["LAUNCH"].node_actions.size());
657
658 EXPECT_EQ(0u, actions["LAUNCH"].node_actions[0].node_index);
659 EXPECT_EQ(1u, actions["LAUNCH"].node_actions[0].value_index);
660 EXPECT_EQ(std::chrono::milliseconds(500).count(),
661 actions["LAUNCH"].node_actions[0].timeout_ms.count());
662
663 EXPECT_EQ(2u, actions["LAUNCH"].node_actions[1].node_index);
664 EXPECT_EQ(0u, actions["LAUNCH"].node_actions[1].value_index);
665 EXPECT_EQ(std::chrono::milliseconds(500).count(),
666 actions["LAUNCH"].node_actions[1].timeout_ms.count());
667
668 EXPECT_EQ(1u, actions["LAUNCH"].node_actions[2].node_index);
669 EXPECT_EQ(0u, actions["LAUNCH"].node_actions[2].value_index);
670 EXPECT_EQ(std::chrono::milliseconds(2000).count(),
671 actions["LAUNCH"].node_actions[2].timeout_ms.count());
672 EXPECT_EQ("vendor.pwhal.enable.test", actions["LAUNCH"].node_actions[2].enable_property);
673
674 EXPECT_EQ(1u, actions["MASK_LAUNCH_MODE"].hint_actions.size());
675 EXPECT_EQ(HintActionType::MaskHint, actions["MASK_LAUNCH_MODE"].hint_actions[0].type);
676 EXPECT_EQ("LAUNCH", actions["MASK_LAUNCH_MODE"].hint_actions[0].value);
677
678 EXPECT_EQ(2u, actions["MASK_LAUNCH_INTERACTION_MODE"].hint_actions.size());
679 EXPECT_EQ(HintActionType::MaskHint,
680 actions["MASK_LAUNCH_INTERACTION_MODE"].hint_actions[0].type);
681 EXPECT_EQ("LAUNCH", actions["MASK_LAUNCH_INTERACTION_MODE"].hint_actions[0].value);
682 EXPECT_EQ(HintActionType::MaskHint,
683 actions["MASK_LAUNCH_INTERACTION_MODE"].hint_actions[1].type);
684 EXPECT_EQ("INTERACTION", actions["MASK_LAUNCH_INTERACTION_MODE"].hint_actions[1].value);
685
686 EXPECT_EQ(1u, actions["DO_LAUNCH_MODE"].hint_actions.size());
687 EXPECT_EQ(HintActionType::DoHint, actions["DO_LAUNCH_MODE"].hint_actions[0].type);
688 EXPECT_EQ("LAUNCH", actions["DO_LAUNCH_MODE"].hint_actions[0].value);
689
690 EXPECT_EQ(1u, actions["END_LAUNCH_MODE"].hint_actions.size());
691 EXPECT_EQ(HintActionType::EndHint, actions["END_LAUNCH_MODE"].hint_actions[0].type);
692 EXPECT_EQ("LAUNCH", actions["END_LAUNCH_MODE"].hint_actions[0].value);
693 }
694
695 // Test parsing actions with duplicate File node
TEST_F(HintManagerTest,ParseActionDuplicateFileNodeTest)696 TEST_F(HintManagerTest, ParseActionDuplicateFileNodeTest) {
697 std::string from = R"("Node": "CPUCluster0MinFreq")";
698 size_t start_pos = json_doc_.find(from);
699 json_doc_.replace(start_pos, from.length(), R"("Node": "CPUCluster1MinFreq")");
700 std::vector<std::unique_ptr<Node>> nodes = HintManager::ParseNodes(json_doc_);
701 EXPECT_EQ(4u, nodes.size());
702 auto actions = HintManager::ParseActions(json_doc_, nodes);
703 EXPECT_EQ(0u, actions.size());
704 }
705
706 // Test parsing actions with duplicate Property node
TEST_F(HintManagerTest,ParseActionDuplicatePropertyNodeTest)707 TEST_F(HintManagerTest, ParseActionDuplicatePropertyNodeTest) {
708 std::string from = R"("Node": "CPUCluster0MinFreq")";
709 size_t start_pos = json_doc_.find(from);
710 json_doc_.replace(start_pos, from.length(), R"("Node": "ModeProperty")");
711 auto nodes = HintManager::ParseNodes(json_doc_);
712 EXPECT_EQ(4u, nodes.size());
713 auto actions = HintManager::ParseActions(json_doc_, nodes);
714 EXPECT_EQ(0u, actions.size());
715 }
716
717 // Test parsing invalid json for actions
TEST_F(HintManagerTest,ParseBadActionsTest)718 TEST_F(HintManagerTest, ParseBadActionsTest) {
719 std::vector<std::unique_ptr<Node>> nodes = HintManager::ParseNodes(json_doc_);
720 auto actions = HintManager::ParseActions("invalid json", nodes);
721 EXPECT_EQ(0u, actions.size());
722 actions = HintManager::ParseActions(
723 "{\"devices\":{\"15\":[\"armeabi-v7a\"],\"16\":[\"armeabi-v7a\"],"
724 "\"26\":[\"armeabi-v7a\",\"arm64-v8a\",\"x86\",\"x86_64\"]}}",
725 nodes);
726 EXPECT_EQ(0u, actions.size());
727 }
728
729 // Test hint/cancel/expire with json config
TEST_F(HintManagerTest,GetFromJSONTest)730 TEST_F(HintManagerTest, GetFromJSONTest) {
731 TemporaryFile json_file;
732 ASSERT_TRUE(android::base::WriteStringToFile(json_doc_, json_file.path))
733 << strerror(errno);
734 HintManager *hm = HintManager::GetFromJSON(json_file.path, false);
735 EXPECT_NE(nullptr, hm);
736 EXPECT_FALSE(hm->IsRunning());
737 EXPECT_TRUE(hm->Start());
738 EXPECT_TRUE(hm->IsRunning());
739 hm = HintManager::GetFromJSON(json_file.path);
740 EXPECT_NE(nullptr, hm);
741 EXPECT_TRUE(hm->IsRunning());
742 std::this_thread::sleep_for(kSLEEP_TOLERANCE_MS);
743 EXPECT_TRUE(hm->IsRunning());
744 // Initial default value on Node0
745 _VerifyPathValue(files_[0 + 2]->path, "384000");
746 _VerifyPathValue(files_[1 + 2]->path, "");
747 _VerifyPropertyValue(prop_, "");
748 // Do INTERACTION
749 EXPECT_TRUE(hm->DoHint("INTERACTION"));
750 std::this_thread::sleep_for(kSLEEP_TOLERANCE_MS);
751 _VerifyPathValue(files_[0 + 2]->path, "384000");
752 _VerifyPathValue(files_[1 + 2]->path, "1134000");
753 _VerifyPropertyValue(prop_, "LOW");
754 // Do LAUNCH
755 _VerifyPropertyValue("vendor.pwhal.enable.test", "1");
756 EXPECT_TRUE(hm->DoHint("LAUNCH"));
757 std::this_thread::sleep_for(kSLEEP_TOLERANCE_MS);
758 _VerifyPathValue(files_[0 + 2]->path, "1134000");
759 _VerifyPathValue(files_[1 + 2]->path, "1512000");
760 _VerifyPropertyValue(prop_, "HIGH");
761 std::this_thread::sleep_for(500ms);
762 // "LAUNCH" node0 expired
763 _VerifyPathValue(files_[0 + 2]->path, "384000");
764 _VerifyPathValue(files_[1 + 2]->path, "1512000");
765 _VerifyPropertyValue(prop_, "LOW");
766 EXPECT_TRUE(hm->EndHint("LAUNCH"));
767 std::this_thread::sleep_for(kSLEEP_TOLERANCE_MS);
768 // "LAUNCH" canceled
769 _VerifyPathValue(files_[0 + 2]->path, "384000");
770 _VerifyPathValue(files_[1 + 2]->path, "1134000");
771 _VerifyPropertyValue(prop_, "LOW");
772 std::this_thread::sleep_for(300ms);
773 // "INTERACTION" node1 expired
774 _VerifyPathValue(files_[0 + 2]->path, "384000");
775 _VerifyPathValue(files_[1 + 2]->path, "384000");
776 _VerifyPropertyValue(prop_, "NONE");
777
778 // Disable action[2] of LAUNCH
779 EXPECT_TRUE(hm->EndHint("LAUNCH"));
780 _VerifyPropertyValue("vendor.pwhal.enable.test", "1");
781 EXPECT_TRUE(hm->DoHint("DISABLE_LAUNCH_ACT2"));
782 std::this_thread::sleep_for(kSLEEP_TOLERANCE_MS);
783 _VerifyPropertyValue("vendor.pwhal.enable.test", "0");
784 EXPECT_TRUE(hm->DoHint("LAUNCH"));
785 std::this_thread::sleep_for(kSLEEP_TOLERANCE_MS);
786 _VerifyPathValue(files_[0 + 2]->path, "1134000");
787 // action[2] have no effect.
788 _VerifyPathValue(files_[1 + 2]->path, "384000");
789 _VerifyPropertyValue(prop_, "HIGH");
790 EXPECT_TRUE(hm->EndHint("LAUNCH"));
791 EXPECT_TRUE(hm->EndHint("DISABLE_LAUNCH_ACT2"));
792
793 // Mask LAUNCH and do LAUNCH
794 EXPECT_TRUE(hm->DoHint("MASK_LAUNCH_MODE"));
795 EXPECT_FALSE(hm->DoHint("LAUNCH")); // should fail
796 std::this_thread::sleep_for(kSLEEP_TOLERANCE_MS);
797 _VerifyPathValue(files_[0 + 2]->path, "384000");
798 _VerifyPathValue(files_[1 + 2]->path, "384000");
799 _VerifyPropertyValue(prop_, "NONE");
800
801 // UnMask LAUNCH and do LAUNCH
802 EXPECT_TRUE(hm->EndHint("MASK_LAUNCH_MODE"));
803 EXPECT_TRUE(hm->DoHint("LAUNCH"));
804 std::this_thread::sleep_for(kSLEEP_TOLERANCE_MS);
805 _VerifyPathValue(files_[0 + 2]->path, "1134000");
806 _VerifyPathValue(files_[1 + 2]->path, "1512000");
807 _VerifyPropertyValue(prop_, "HIGH");
808 // END_LAUNCH_MODE should deactivate LAUNCH
809 EXPECT_TRUE(hm->DoHint("END_LAUNCH_MODE"));
810 std::this_thread::sleep_for(kSLEEP_TOLERANCE_MS);
811 _VerifyPathValue(files_[0 + 2]->path, "384000");
812 _VerifyPathValue(files_[1 + 2]->path, "384000");
813 _VerifyPropertyValue(prop_, "NONE");
814 EXPECT_TRUE(hm->EndHint("END_LAUNCH_MODE"));
815
816 // DO_LAUNCH_MODE should activate LAUNCH
817 EXPECT_TRUE(hm->DoHint("DO_LAUNCH_MODE"));
818 std::this_thread::sleep_for(kSLEEP_TOLERANCE_MS);
819 _VerifyPathValue(files_[0 + 2]->path, "1134000");
820 _VerifyPathValue(files_[1 + 2]->path, "1512000");
821 _VerifyPropertyValue(prop_, "HIGH");
822
823 // Mask LAUNCH
824 EXPECT_TRUE(hm->DoHint("MASK_LAUNCH_MODE"));
825 EXPECT_FALSE(hm->IsHintEnabled("LAUNCH"));
826 // Mask LAUNCH and INTERACTION
827 EXPECT_TRUE(hm->DoHint("MASK_LAUNCH_INTERACTION_MODE"));
828 EXPECT_FALSE(hm->IsHintEnabled("LAUNCH"));
829 EXPECT_FALSE(hm->IsHintEnabled("INTERACTION"));
830 // End Mask LAUNCH and INTERACTION
831 EXPECT_TRUE(hm->EndHint("MASK_LAUNCH_INTERACTION_MODE"));
832 EXPECT_FALSE(hm->IsHintEnabled("LAUNCH"));
833 EXPECT_TRUE(hm->IsHintEnabled("INTERACTION"));
834 // End Mask LAUNCH
835 EXPECT_TRUE(hm->EndHint("MASK_LAUNCH_MODE"));
836 EXPECT_TRUE(hm->IsHintEnabled("LAUNCH"));
837 }
838
839 // Test parsing AdpfConfig
TEST_F(HintManagerTest,ParseAdpfConfigsTest)840 TEST_F(HintManagerTest, ParseAdpfConfigsTest) {
841 std::string json_doc = std::string(kJSON_ADPF);
842 std::vector<std::shared_ptr<AdpfConfig>> adpfs = HintManager::ParseAdpfConfigs(json_doc);
843 EXPECT_EQ(3u, adpfs.size());
844 EXPECT_EQ("ADPF_DEFAULT", adpfs[0]->mName);
845 EXPECT_EQ("ADPF_SF", adpfs[1]->mName);
846 EXPECT_TRUE(adpfs[0]->mPidOn);
847 EXPECT_FALSE(adpfs[1]->mPidOn);
848 EXPECT_EQ(5.0, adpfs[0]->mPidPo);
849 EXPECT_EQ(0.0, adpfs[1]->mPidPo);
850 EXPECT_EQ(3.0, adpfs[0]->mPidPu);
851 EXPECT_EQ(0.0, adpfs[1]->mPidPu);
852 EXPECT_EQ(0.001, adpfs[0]->mPidI);
853 EXPECT_EQ(0.0, adpfs[1]->mPidI);
854 EXPECT_EQ(200LL, adpfs[0]->mPidIInit);
855 EXPECT_EQ(0LL, adpfs[1]->mPidIInit);
856 EXPECT_EQ(512LL, adpfs[0]->mPidIHigh);
857 EXPECT_EQ(0LL, adpfs[1]->mPidIHigh);
858 EXPECT_EQ(-120LL, adpfs[0]->mPidILow);
859 EXPECT_EQ(0LL, adpfs[1]->mPidILow);
860 EXPECT_EQ(500.0, adpfs[0]->mPidDo);
861 EXPECT_EQ(0.0, adpfs[1]->mPidDo);
862 EXPECT_EQ(500.0, adpfs[0]->mPidDo);
863 EXPECT_EQ(0.0, adpfs[1]->mPidDo);
864 EXPECT_EQ(1LLU, adpfs[0]->mSamplingWindowP);
865 EXPECT_EQ(0LLU, adpfs[1]->mSamplingWindowP);
866 EXPECT_EQ(0LLU, adpfs[0]->mSamplingWindowI);
867 EXPECT_EQ(0LLU, adpfs[1]->mSamplingWindowI);
868 EXPECT_EQ(1LLU, adpfs[0]->mSamplingWindowD);
869 EXPECT_EQ(0LLU, adpfs[1]->mSamplingWindowD);
870 EXPECT_TRUE(adpfs[0]->mUclampMinOn);
871 EXPECT_TRUE(adpfs[1]->mUclampMinOn);
872 EXPECT_EQ(100U, adpfs[0]->mUclampMinInit);
873 EXPECT_EQ(200U, adpfs[0]->mUclampMinLoadUp);
874 EXPECT_EQ(300U, adpfs[0]->mUclampMinLoadReset);
875 EXPECT_EQ(200U, adpfs[1]->mUclampMinInit);
876 EXPECT_EQ(384U, adpfs[0]->mUclampMinHigh);
877 EXPECT_EQ(157U, adpfs[1]->mUclampMinHigh);
878 EXPECT_EQ(157U, adpfs[1]->mUclampMinLoadUp);
879 EXPECT_EQ(157U, adpfs[1]->mUclampMinLoadReset);
880 EXPECT_EQ(0U, adpfs[0]->mUclampMinLow);
881 EXPECT_EQ(157U, adpfs[1]->mUclampMinLow);
882 EXPECT_EQ(166666660LL, adpfs[0]->mReportingRateLimitNs);
883 EXPECT_EQ(83333330LL, adpfs[1]->mReportingRateLimitNs);
884 EXPECT_EQ(1.0, adpfs[0]->mTargetTimeFactor);
885 EXPECT_EQ(1.4, adpfs[1]->mTargetTimeFactor);
886 EXPECT_EQ(10.0, adpfs[0]->mStaleTimeFactor);
887 EXPECT_EQ(5.0, adpfs[1]->mStaleTimeFactor);
888 EXPECT_TRUE(adpfs[0]->mHeuristicBoostOn.value());
889 EXPECT_FALSE(adpfs[1]->mHeuristicBoostOn.has_value());
890 EXPECT_EQ(4U, adpfs[0]->mHBoostModerateJankThreshold.value());
891 EXPECT_FALSE(adpfs[1]->mHBoostModerateJankThreshold.has_value());
892 EXPECT_EQ(4.0, adpfs[0]->mHBoostOffMaxAvgDurRatio.value());
893 EXPECT_FALSE(adpfs[1]->mHBoostOffMaxAvgDurRatio.has_value());
894 EXPECT_EQ(0.5, adpfs[0]->mHBoostSevereJankPidPu.value());
895 EXPECT_FALSE(adpfs[1]->mHBoostSevereJankPidPu.has_value());
896 EXPECT_EQ(2U, adpfs[0]->mHBoostSevereJankThreshold.value());
897 EXPECT_FALSE(adpfs[1]->mHBoostSevereJankThreshold.has_value());
898 EXPECT_EQ(480U, adpfs[0]->mHBoostUclampMinCeilingRange.value().first);
899 EXPECT_EQ(800U, adpfs[0]->mHBoostUclampMinCeilingRange.value().second);
900 EXPECT_FALSE(adpfs[1]->mHBoostUclampMinCeilingRange.has_value());
901 EXPECT_EQ(200U, adpfs[0]->mHBoostUclampMinFloorRange.value().first);
902 EXPECT_EQ(400U, adpfs[0]->mHBoostUclampMinFloorRange.value().second);
903 EXPECT_FALSE(adpfs[1]->mHBoostUclampMinFloorRange.has_value());
904 EXPECT_EQ(1.2, adpfs[0]->mJankCheckTimeFactor.value());
905 EXPECT_FALSE(adpfs[1]->mJankCheckTimeFactor.has_value());
906 EXPECT_EQ(25U, adpfs[0]->mLowFrameRateThreshold.value());
907 EXPECT_FALSE(adpfs[1]->mLowFrameRateThreshold.has_value());
908 EXPECT_EQ(50U, adpfs[0]->mMaxRecordsNum.value());
909 EXPECT_FALSE(adpfs[1]->mMaxRecordsNum.has_value());
910 }
911
912 // Test parsing adpf configs with duplicate name
TEST_F(HintManagerTest,ParseAdpfConfigsDuplicateNameTest)913 TEST_F(HintManagerTest, ParseAdpfConfigsDuplicateNameTest) {
914 std::string json_doc = std::string(kJSON_ADPF);
915 std::string from = "\"Name\": \"ADPF_DEFAULT\"";
916 size_t start_pos = json_doc.find(from);
917 json_doc.replace(start_pos, from.length(), "\"Name\": \"ADPF_SF\"");
918 std::vector<std::shared_ptr<AdpfConfig>> adpfs = HintManager::ParseAdpfConfigs(json_doc);
919 EXPECT_EQ(0u, adpfs.size());
920 }
921
922 // Test parsing adpf configs without PID_Po
TEST_F(HintManagerTest,ParseAdpfConfigsWithoutPIDPoTest)923 TEST_F(HintManagerTest, ParseAdpfConfigsWithoutPIDPoTest) {
924 std::string json_doc = std::string(kJSON_ADPF);
925 std::string from = "\"PID_Po\": 0,";
926 size_t start_pos = json_doc.find(from);
927 json_doc.replace(start_pos, from.length(), "");
928 std::vector<std::shared_ptr<AdpfConfig>> adpfs = HintManager::ParseAdpfConfigs(json_doc);
929 EXPECT_EQ(0u, adpfs.size());
930 }
931
932 // Test parsing adpf configs with partially missing heuristic boost config
TEST_F(HintManagerTest,ParseAdpfConfigsWithBrokenHBoostConfig)933 TEST_F(HintManagerTest, ParseAdpfConfigsWithBrokenHBoostConfig) {
934 std::string json_doc = std::string(kJSON_ADPF);
935 std::string from = "\"JankCheckTimeFactor\": 1.2";
936 size_t start_pos = json_doc.find(from);
937 json_doc.replace(start_pos, from.length(), "");
938 std::vector<std::shared_ptr<AdpfConfig>> adpfs = HintManager::ParseAdpfConfigs(json_doc);
939 EXPECT_EQ(0u, adpfs.size());
940 }
941
942 // Test hint/cancel/expire with json config
TEST_F(HintManagerTest,GetFromJSONAdpfConfigTest)943 TEST_F(HintManagerTest, GetFromJSONAdpfConfigTest) {
944 TemporaryFile json_file;
945 ASSERT_TRUE(android::base::WriteStringToFile(kJSON_ADPF, json_file.path)) << strerror(errno);
946 HintManager *hm = HintManager::GetFromJSON(json_file.path, false);
947 EXPECT_NE(nullptr, hm);
948 EXPECT_TRUE(hm->Start());
949 EXPECT_TRUE(hm->IsRunning());
950
951 // Get default Adpf Profile
952 EXPECT_EQ("ADPF_DEFAULT", hm->GetAdpfProfile()->mName);
953 EXPECT_EQ("ADPF_SF", hm->GetAdpfProfile("SURFACEFLINGER")->mName);
954
955 // Set specific Adpf Profile
956 EXPECT_FALSE(hm->SetAdpfProfile("OTHER", "NoSuchProfile"));
957 // Test SF_PLAYING
958 EXPECT_TRUE(hm->SetAdpfProfile("SURFACEFLINGER", "SF_VIDEO_30FPS"));
959 EXPECT_EQ("SF_VIDEO_30FPS", hm->GetAdpfProfile("SURFACEFLINGER")->mName);
960 // Test SF_RESET
961 EXPECT_TRUE(hm->SetAdpfProfile("SURFACEFLINGER", "ADPF_SF"));
962 EXPECT_EQ("ADPF_SF", hm->GetAdpfProfile("SURFACEFLINGER")->mName);
963 }
964
TEST_F(HintManagerTest,IsAdpfProfileSupported)965 TEST_F(HintManagerTest, IsAdpfProfileSupported) {
966 TemporaryFile json_file;
967 ASSERT_TRUE(android::base::WriteStringToFile(kJSON_ADPF, json_file.path)) << strerror(errno);
968 HintManager *hm = HintManager::GetFromJSON(json_file.path, false);
969 EXPECT_NE(nullptr, hm);
970
971 // Check if given AdpfProfile supported
972 EXPECT_FALSE(hm->IsAdpfProfileSupported("NoSuchProfile"));
973 EXPECT_TRUE(hm->IsAdpfProfileSupported("ADPF_DEFAULT"));
974 EXPECT_TRUE(hm->IsAdpfProfileSupported("ADPF_SF"));
975 }
976
TEST_F(HintManagerTest,IsAdpfSupported)977 TEST_F(HintManagerTest, IsAdpfSupported) {
978 TemporaryFile json_file;
979 // Use json with AdpfConfig
980 ASSERT_TRUE(android::base::WriteStringToFile(kJSON_ADPF, json_file.path)) << strerror(errno);
981 HintManager *hm = HintManager::GetFromJSON(json_file.path, false);
982 EXPECT_NE(nullptr, hm);
983 EXPECT_TRUE(hm->IsAdpfSupported());
984
985 // Use a json doc without AdpfConfig
986 ASSERT_TRUE(android::base::WriteStringToFile(kJSON_RAW, json_file.path)) << strerror(errno);
987 hm = HintManager::GetFromJSON(json_file.path, false);
988 EXPECT_NE(nullptr, hm);
989 EXPECT_FALSE(hm->IsAdpfSupported());
990 }
991
TEST_F(HintManagerTest,GetAdpfProfile)992 TEST_F(HintManagerTest, GetAdpfProfile) {
993 TemporaryFile json_file;
994 ASSERT_TRUE(android::base::WriteStringToFile(kJSON_ADPF, json_file.path)) << strerror(errno);
995 HintManager *hm = HintManager::GetFromJSON(json_file.path, false);
996 EXPECT_NE(nullptr, hm);
997 EXPECT_EQ("ADPF_DEFAULT", hm->GetAdpfProfile()->mName);
998 EXPECT_EQ("ADPF_DEFAULT", hm->GetAdpfProfile("OTHER")->mName);
999 EXPECT_EQ("ADPF_DEFAULT", hm->GetAdpfProfile("HWUI")->mName);
1000 EXPECT_EQ("ADPF_DEFAULT", hm->GetAdpfProfile("APP")->mName);
1001 EXPECT_EQ("ADPF_DEFAULT", hm->GetAdpfProfile("GAME")->mName);
1002 EXPECT_EQ("ADPF_SF", hm->GetAdpfProfile("SURFACEFLINGER")->mName);
1003 EXPECT_EQ("ADPF_DEFAULT", hm->GetAdpfProfile("NoSuchTag")->mName);
1004 }
1005
TEST_F(HintManagerTest,SetAdpfProfile)1006 TEST_F(HintManagerTest, SetAdpfProfile) {
1007 TemporaryFile json_file;
1008 ASSERT_TRUE(android::base::WriteStringToFile(kJSON_ADPF, json_file.path)) << strerror(errno);
1009 HintManager *hm = HintManager::GetFromJSON(json_file.path, false);
1010 EXPECT_NE(nullptr, hm);
1011 EXPECT_TRUE(hm->SetAdpfProfile("OTHER", "ADPF_DEFAULT"));
1012 EXPECT_FALSE(hm->SetAdpfProfile("OTHER", "NoSuchProfile"));
1013 EXPECT_FALSE(hm->SetAdpfProfile("NoSuchTag", "ADPF_DEFAULT"));
1014 EXPECT_TRUE(hm->SetAdpfProfile("OTHER", "ADPF_SF"));
1015 EXPECT_EQ("ADPF_DEFAULT", hm->GetAdpfProfile("ADPF_SF")->mName);
1016 EXPECT_TRUE(hm->SetAdpfProfile("OTHER", "SF_VIDEO_30FPS"));
1017 EXPECT_EQ("SF_VIDEO_30FPS", hm->GetAdpfProfile("OTHER")->mName);
1018 }
1019
TEST_F(HintManagerTest,DoHintForEventNode)1020 TEST_F(HintManagerTest, DoHintForEventNode) {
1021 TemporaryFile json_file;
1022 ASSERT_TRUE(android::base::WriteStringToFile(kJSON_ADPF, json_file.path)) << strerror(errno);
1023 HintManager *hm = HintManager::GetFromJSON(json_file.path, false);
1024 EXPECT_NE(nullptr, hm);
1025 EXPECT_TRUE(hm->Start());
1026 EXPECT_TRUE(hm->IsRunning());
1027 EXPECT_EQ("ADPF_SF", hm->GetAdpfProfile("SURFACEFLINGER")->mName);
1028 hm->DoHint("SF_RESET");
1029 std::this_thread::sleep_for(kSLEEP_TOLERANCE_MS);
1030 EXPECT_EQ("ADPF_DEFAULT", hm->GetAdpfProfile("SURFACEFLINGER")->mName);
1031 }
1032
TEST_F(HintManagerTest,RegisterAdpfUpdateEventAndUnregister)1033 TEST_F(HintManagerTest, RegisterAdpfUpdateEventAndUnregister) {
1034 TemporaryFile json_file;
1035 ASSERT_TRUE(android::base::WriteStringToFile(kJSON_ADPF, json_file.path)) << strerror(errno);
1036 HintManager *hm = HintManager::GetFromJSON(json_file.path, false);
1037 EXPECT_NE(nullptr, hm);
1038 EXPECT_TRUE(hm->Start());
1039 EXPECT_TRUE(hm->IsRunning());
1040 int count = 0;
1041 std::string name;
1042 AdpfCallback callback = [&](std::shared_ptr<AdpfConfig> profile) {
1043 count++;
1044 name = profile->mName;
1045 };
1046 // the callback should be invoked by DoHint().
1047 hm->RegisterAdpfUpdateEvent("SURFACEFLINGER", &callback);
1048 hm->DoHint("SF_RESET");
1049 std::this_thread::sleep_for(kSLEEP_TOLERANCE_MS);
1050 EXPECT_EQ(1, count);
1051 EXPECT_EQ("ADPF_DEFAULT", name);
1052
1053 // Unregister and DoHint('SF_PLAYING'). the callback shouldn't be called.
1054 hm->UnregisterAdpfUpdateEvent("SURFACEFLINGER", &callback);
1055 hm->EndHint("SF_RESET");
1056 hm->DoHint("SF_PLAYING");
1057 std::this_thread::sleep_for(kSLEEP_TOLERANCE_MS);
1058 EXPECT_EQ("ADPF_SF", hm->GetAdpfProfile("SURFACEFLINGER")->mName);
1059 EXPECT_EQ(1, count);
1060 EXPECT_EQ("ADPF_DEFAULT", name);
1061 }
1062
TEST_F(HintManagerTest,GetAdpfProfileFromDoHint)1063 TEST_F(HintManagerTest, GetAdpfProfileFromDoHint) {
1064 TemporaryFile json_file;
1065 ASSERT_TRUE(android::base::WriteStringToFile(kJSON_ADPF, json_file.path)) << strerror(errno);
1066 HintManager *hm = HintManager::GetFromJSON(json_file.path, false);
1067 EXPECT_NE(nullptr, hm);
1068 // Check the default profile is at index:0.
1069 EXPECT_EQ("ADPF_DEFAULT", hm->GetAdpfProfileFromDoHint()->mName);
1070 // Make sure that SetAdpfProfile wouldn't impact GetAdpfProfileFromDoHint().
1071 EXPECT_TRUE(hm->SetAdpfProfile("OTHER", "ADPF_SF"));
1072 EXPECT_EQ("ADPF_SF", hm->GetAdpfProfile("OTHER")->mName);
1073 EXPECT_EQ("ADPF_DEFAULT", hm->GetAdpfProfileFromDoHint()->mName);
1074 }
1075
TEST_F(HintManagerTest,SetAdpfProfileFromDoHint)1076 TEST_F(HintManagerTest, SetAdpfProfileFromDoHint) {
1077 TemporaryFile json_file;
1078 ASSERT_TRUE(android::base::WriteStringToFile(kJSON_ADPF, json_file.path)) << strerror(errno);
1079 HintManager *hm = HintManager::GetFromJSON(json_file.path, false);
1080 EXPECT_NE(nullptr, hm);
1081 // Check the default profile is at index:0.
1082 EXPECT_EQ("ADPF_DEFAULT", hm->GetAdpfProfile("OTHER")->mName);
1083 // Make sure that SetAdpfProfileFromDoHint wouldn't impact GetAdpfProfile().
1084 EXPECT_TRUE(hm->SetAdpfProfileFromDoHint("ADPF_SF"));
1085 EXPECT_EQ("ADPF_SF", hm->GetAdpfProfileFromDoHint()->mName);
1086 EXPECT_EQ("ADPF_DEFAULT", hm->GetAdpfProfile("OTHER")->mName);
1087 }
1088
TEST_F(HintManagerTest,GpuConfigSupport)1089 TEST_F(HintManagerTest, GpuConfigSupport) {
1090 TemporaryFile json_file;
1091 ASSERT_TRUE(android::base::WriteStringToFile(kJSON_ADPF, json_file.path)) << strerror(errno);
1092 HintManager *hm = HintManager::GetFromJSON(json_file.path, false);
1093 ASSERT_TRUE(hm);
1094
1095 EXPECT_THAT(hm->gpu_sysfs_config_path(), Optional(Eq("/sys/devices/platform/123.abc")));
1096 ASSERT_TRUE(hm->SetAdpfProfile("OTHER", "ADPF_DEFAULT"));
1097 auto profile = hm->GetAdpfProfile();
1098 EXPECT_THAT(profile->mGpuBoostOn, Optional(true));
1099 EXPECT_THAT(profile->mGpuBoostCapacityMax, Optional(325000));
1100 EXPECT_EQ(profile->mGpuCapacityLoadUpHeadroom, 1000);
1101
1102 ASSERT_TRUE(hm->SetAdpfProfile("OTHER", "ADPF_SF"));
1103 profile = hm->GetAdpfProfile();
1104 EXPECT_FALSE(profile->mGpuBoostOn);
1105 EXPECT_FALSE(profile->mGpuBoostCapacityMax);
1106 EXPECT_EQ(profile->mGpuCapacityLoadUpHeadroom, 0);
1107 }
1108
1109 } // namespace perfmgr
1110 } // namespace android
1111