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