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