• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include "socperf_config.h"
16 
17 #include <algorithm>
18 #include <chrono>
19 #include <dlfcn.h>
20 
21 #include "config_policy_utils.h"
22 #include "parameters.h"
23 #ifdef RES_SCHED_SA_INIT
24 #include "res_sa_init.h"
25 #endif
26 
27 namespace OHOS {
28 namespace SOCPERF {
29 namespace {
30     std::mutex g_resStrToIdMutex;
31     std::unordered_map<std::string, int32_t> g_resStrToIdInfo;
32     void* g_handle;
33     const std::string SPLIT_OR = "|";
34     const std::string SPLIT_EQUAL = "=";
35     const std::string SPLIT_SPACE = " ";
36 }
37 
GetInstance()38 SocPerfConfig& SocPerfConfig::GetInstance()
39 {
40     static SocPerfConfig socPerfConfig_;
41     return socPerfConfig_;
42 }
43 
SocPerfConfig()44 SocPerfConfig::SocPerfConfig() {}
45 
~SocPerfConfig()46 SocPerfConfig::~SocPerfConfig()
47 {
48     if (g_handle != nullptr) {
49         dlclose(g_handle);
50         g_handle = nullptr;
51     }
52 }
53 
Init()54 bool SocPerfConfig::Init()
55 {
56 #ifdef RES_SCHED_SA_INIT
57     std::lock_guard<std::mutex> xmlLock(ResourceSchedule::ResSchedSaInit::GetInstance().saInitXmlMutex_);
58 #endif
59     std::string resourceConfigXml = system::GetParameter("ohos.boot.kernel", "").size() > 0 ?
60         SOCPERF_BOOST_CONFIG_XML_EXT : SOCPERF_BOOST_CONFIG_XML;
61     if (!LoadAllConfigXmlFile(SOCPERF_RESOURCE_CONFIG_XML)) {
62         SOC_PERF_LOGE("Failed to load %{private}s", SOCPERF_RESOURCE_CONFIG_XML.c_str());
63         return false;
64     }
65 
66     if (!LoadAllConfigXmlFile(resourceConfigXml)) {
67         SOC_PERF_LOGE("Failed to load %{private}s", resourceConfigXml.c_str());
68         return false;
69     }
70 
71     if (!LoadAllConfigXmlFile(CAMERA_AWARE_CONFIG_XML)) {
72         SOC_PERF_LOGE("Failed to load %{private}s", CAMERA_AWARE_CONFIG_XML.c_str());
73     }
74 
75     std::unique_lock<std::mutex> lock(g_resStrToIdMutex);
76     g_resStrToIdInfo.clear();
77     g_resStrToIdInfo = std::unordered_map<std::string, int32_t>();
78     lock.unlock();
79 
80     SOC_PERF_LOGD("SocPerf Init SUCCESS!");
81     return true;
82 }
83 
IsGovResId(int32_t resId) const84 bool SocPerfConfig::IsGovResId(int32_t resId) const
85 {
86     auto item = resourceNodeInfo_.find(resId);
87     if (item != resourceNodeInfo_.end() && item->second->isGov) {
88         return true;
89     }
90     return false;
91 }
92 
IsValidResId(int32_t resId) const93 bool SocPerfConfig::IsValidResId(int32_t resId) const
94 {
95     if (resourceNodeInfo_.find(resId) == resourceNodeInfo_.end()) {
96         return false;
97     }
98     return true;
99 }
100 
GetRealConfigPath(const std::string & configFile)101 std::string SocPerfConfig::GetRealConfigPath(const std::string& configFile)
102 {
103     char buf[PATH_MAX + 1];
104     char* configFilePath = GetOneCfgFile(configFile.c_str(), buf, PATH_MAX + 1);
105     char tmpPath[PATH_MAX + 1] = {0};
106     if (!configFilePath || strlen(configFilePath) == 0 || strlen(configFilePath) > PATH_MAX ||
107         !realpath(configFilePath, tmpPath)) {
108         SOC_PERF_LOGE("load %{private}s file fail", configFile.c_str());
109         return "";
110     }
111     return std::string(tmpPath);
112 }
113 
GetAllRealConfigPath(const std::string & configFile)114 std::vector<std::string> SocPerfConfig::GetAllRealConfigPath(const std::string& configFile)
115 {
116     std::vector<std::string> configFilePaths;
117     auto cfgFiles = GetCfgFiles(configFile.c_str());
118     if (cfgFiles == nullptr) {
119         return configFilePaths;
120     }
121     for (const auto& file : cfgFiles->paths) {
122         if (file == nullptr) {
123             continue;
124         }
125         configFilePaths.emplace_back(std::string(file));
126     }
127     FreeCfgFiles(cfgFiles);
128     reverse(configFilePaths.begin(), configFilePaths.end());
129     return configFilePaths;
130 }
131 
LoadAllConfigXmlFile(const std::string & configFile)132 bool SocPerfConfig::LoadAllConfigXmlFile(const std::string& configFile)
133 {
134     std::vector<std::string> filePaths = GetAllRealConfigPath(configFile);
135     for (auto realConfigFile : filePaths) {
136         if (!(LoadConfigXmlFile(realConfigFile.c_str()))) {
137             return false;
138         }
139     }
140     SOC_PERF_LOGD("Success to Load %{private}s", configFile.c_str());
141     return true;
142 }
143 
LoadConfigXmlFile(const std::string & realConfigFile)144 bool SocPerfConfig::LoadConfigXmlFile(const std::string& realConfigFile)
145 {
146     if (realConfigFile.size() == 0) {
147         return false;
148     }
149     xmlKeepBlanksDefault(0);
150     xmlDoc* file = xmlReadFile(realConfigFile.c_str(), nullptr, XML_PARSE_NOERROR | XML_PARSE_NOWARNING);
151     if (!file) {
152         SOC_PERF_LOGE("Failed to open xml file");
153         return false;
154     }
155     xmlNode* rootNode = xmlDocGetRootElement(file);
156     if (!rootNode) {
157         SOC_PERF_LOGE("Failed to get xml file's RootNode");
158         xmlFreeDoc(file);
159         return false;
160     }
161     if (!xmlStrcmp(rootNode->name, reinterpret_cast<const xmlChar*>("Configs"))) {
162         if (realConfigFile.find(SOCPERF_RESOURCE_CONFIG_XML) != std::string::npos) {
163             bool ret = ParseResourceXmlFile(rootNode, realConfigFile, file);
164             if (!ret) {
165                 xmlFreeDoc(file);
166                 return false;
167             }
168         } else {
169             bool ret = ParseBoostXmlFile(rootNode, realConfigFile, file);
170             if (!ret) {
171                 xmlFreeDoc(file);
172                 return false;
173             }
174         }
175     } else {
176         SOC_PERF_LOGE("Wrong format for xml file");
177         xmlFreeDoc(file);
178         return false;
179     }
180     xmlFreeDoc(file);
181     SOC_PERF_LOGD("Success to access %{private}s", realConfigFile.c_str());
182 
183     return true;
184 }
185 
InitPerfFunc(const char * perfSoPath,const char * perfReportFunc,const char * perfScenarioFunc)186 void SocPerfConfig::InitPerfFunc(const char* perfSoPath, const char* perfReportFunc, const char* perfScenarioFunc)
187 {
188     if (perfSoPath == nullptr || (perfReportFunc == nullptr && perfScenarioFunc == nullptr)) {
189         return;
190     }
191 
192     if (reportFunc_ != nullptr && scenarioFunc_ != nullptr) {
193         return;
194     }
195 
196     g_handle = dlopen(perfSoPath, RTLD_NOW);
197     if (g_handle == nullptr) {
198         SOC_PERF_LOGE("perf so doesn't exist");
199         return;
200     }
201 
202     if (reportFunc_ == nullptr && perfReportFunc != nullptr) {
203         reportFunc_ = reinterpret_cast<ReportDataFunc>(dlsym(g_handle, perfReportFunc));
204     }
205 
206     if (scenarioFunc_ == nullptr && perfScenarioFunc != nullptr) {
207         scenarioFunc_ = reinterpret_cast<PerfScenarioFunc>(dlsym(g_handle, perfScenarioFunc));
208     }
209 
210     if (reportFunc_ == nullptr && scenarioFunc_ == nullptr) {
211         SOC_PERF_LOGE("perf func doesn't exist");
212         dlclose(g_handle);
213         g_handle = nullptr;
214     }
215 }
216 
ParseBoostXmlFile(const xmlNode * rootNode,const std::string & realConfigFile,xmlDoc * file)217 bool SocPerfConfig::ParseBoostXmlFile(const xmlNode* rootNode, const std::string& realConfigFile, xmlDoc* file)
218 {
219     if (!LoadConfig(rootNode, realConfigFile)) {
220         return false;
221     }
222     return true;
223 }
224 
ParseResourceXmlFile(const xmlNode * rootNode,const std::string & realConfigFile,xmlDoc * file)225 bool SocPerfConfig::ParseResourceXmlFile(const xmlNode* rootNode, const std::string& realConfigFile, xmlDoc* file)
226 {
227     xmlNode* child = rootNode->children;
228     for (; child; child = child->next) {
229         if (!xmlStrcmp(child->name, reinterpret_cast<const xmlChar*>("Resource"))) {
230             if (!LoadResource(child, realConfigFile)) {
231                 return false;
232             }
233         } else if (!xmlStrcmp(child->name, reinterpret_cast<const xmlChar*>("GovResource"))) {
234             if (!LoadGovResource(child, realConfigFile)) {
235                 return false;
236             }
237         } else if (!xmlStrcmp(child->name, reinterpret_cast<const xmlChar*>("SceneResource"))) {
238             LoadSceneResource(child, realConfigFile);
239         } else if (!xmlStrcmp(child->name, reinterpret_cast<const xmlChar*>("Info"))) {
240             LoadInfo(child, realConfigFile);
241         }
242     }
243     return true;
244 }
245 
LoadResource(xmlNode * child,const std::string & configFile)246 bool SocPerfConfig::LoadResource(xmlNode* child, const std::string& configFile)
247 {
248     xmlNode* grandson = child->children;
249     for (; grandson; grandson = grandson->next) {
250         if (!xmlStrcmp(grandson->name, reinterpret_cast<const xmlChar*>("res"))) {
251             if (!TraversalFreqResource(grandson, configFile)) {
252                 return false;
253             }
254         }
255     }
256 
257     if (!CheckPairResIdValid() || !CheckDefValid()) {
258         return false;
259     }
260 
261     return true;
262 }
263 
CheckTrace(const char * trace)264 bool SocPerfConfig::CheckTrace(const char* trace)
265 {
266     if (trace && IsNumber(trace) && atoi(trace) == PERF_OPEN_TRACE) {
267         return true;
268     }
269     return false;
270 }
271 
TraversalFreqResource(xmlNode * grandson,const std::string & configFile)272 bool SocPerfConfig::TraversalFreqResource(xmlNode* grandson, const std::string& configFile)
273 {
274     char* id = reinterpret_cast<char*>(xmlGetProp(grandson, reinterpret_cast<const xmlChar*>("id")));
275     char* name = reinterpret_cast<char*>(xmlGetProp(grandson, reinterpret_cast<const xmlChar*>("name")));
276     char* pair = reinterpret_cast<char*>(xmlGetProp(grandson, reinterpret_cast<const xmlChar*>("pair")));
277     char* mode = reinterpret_cast<char*>(xmlGetProp(grandson, reinterpret_cast<const xmlChar*>("mode")));
278     char* persistMode = reinterpret_cast<char*>(xmlGetProp(grandson, reinterpret_cast<const xmlChar*>("switch")));
279     char* trace = reinterpret_cast<char*>(xmlGetProp(grandson, reinterpret_cast<const xmlChar*>("trace")));
280     if (!CheckResourceTag(id, name, pair, mode, persistMode, configFile)) {
281         xmlFree(id);
282         xmlFree(name);
283         xmlFree(pair);
284         xmlFree(mode);
285         xmlFree(persistMode);
286         xmlFree(trace);
287         return false;
288     }
289     auto it = resourceNodeInfo_.find(atoi(id));
290     if (it != resourceNodeInfo_.end()) {
291         xmlFree(id);
292         xmlFree(name);
293         xmlFree(pair);
294         xmlFree(mode);
295         xmlFree(persistMode);
296         xmlFree(trace);
297         return true;
298     }
299     xmlNode* greatGrandson = grandson->children;
300     std::shared_ptr<ResNode> resNode = std::make_shared<ResNode>(atoi(id), name, mode ? atoi(mode) : 0,
301         pair ? atoi(pair) : INVALID_VALUE, persistMode ? atoi(persistMode) : 0);
302     resNode->trace = CheckTrace(trace);
303     xmlFree(id);
304     xmlFree(name);
305     xmlFree(pair);
306     xmlFree(mode);
307     xmlFree(trace);
308     if (!LoadFreqResourceContent(persistMode ? atoi(persistMode) : 0, greatGrandson, configFile, resNode)) {
309         xmlFree(persistMode);
310         return false;
311     }
312     xmlFree(persistMode);
313     return true;
314 }
315 
LoadFreqResourceContent(int32_t persistMode,xmlNode * greatGrandson,const std::string & configFile,std::shared_ptr<ResNode> resNode)316 bool SocPerfConfig::LoadFreqResourceContent(int32_t persistMode, xmlNode* greatGrandson, const std::string& configFile,
317     std::shared_ptr<ResNode> resNode)
318 {
319     char *def = nullptr;
320     char *path  = nullptr;
321     char *node  = nullptr;
322     for (; greatGrandson; greatGrandson = greatGrandson->next) {
323         if (!xmlStrcmp(greatGrandson->name, reinterpret_cast<const xmlChar*>("default"))) {
324             xmlFree(def);
325             def = reinterpret_cast<char*>(xmlNodeGetContent(greatGrandson));
326         } else if (persistMode != REPORT_TO_PERFSO &&
327             !xmlStrcmp(greatGrandson->name, reinterpret_cast<const xmlChar*>("path"))) {
328             xmlFree(path);
329             path = reinterpret_cast<char*>(xmlNodeGetContent(greatGrandson));
330         } else if (!xmlStrcmp(greatGrandson->name, reinterpret_cast<const xmlChar*>("node"))) {
331             xmlFree(node);
332             node = reinterpret_cast<char*>(xmlNodeGetContent(greatGrandson));
333         }
334     }
335     if (!CheckResourceTag(persistMode, def, path, configFile)) {
336         xmlFree(def);
337         xmlFree(path);
338         xmlFree(node);
339         return false;
340     }
341     resNode->def = atoll(def);
342     if (persistMode != REPORT_TO_PERFSO) {
343         resNode->path = path;
344     }
345     xmlFree(def);
346     xmlFree(path);
347     if (node && !LoadResourceAvailable(resNode, node)) {
348         SOC_PERF_LOGE("Invalid resource node for %{private}s", configFile.c_str());
349         xmlFree(node);
350         return false;
351     }
352     xmlFree(node);
353 
354     std::unique_lock<std::mutex> lock(g_resStrToIdMutex);
355     g_resStrToIdInfo.insert(std::pair<std::string, int32_t>(resNode->name, resNode->id));
356     lock.unlock();
357 
358     std::unique_lock<std::mutex> lockResourceNode(resourceNodeMutex_);
359     resourceNodeInfo_.insert(std::pair<int32_t, std::shared_ptr<ResNode>>(resNode->id, resNode));
360     lockResourceNode.unlock();
361 
362     return true;
363 }
364 
LoadGovResource(xmlNode * child,const std::string & configFile)365 bool SocPerfConfig::LoadGovResource(xmlNode* child, const std::string& configFile)
366 {
367     xmlNode* grandson = child->children;
368     for (; grandson; grandson = grandson->next) {
369         if (xmlStrcmp(grandson->name, reinterpret_cast<const xmlChar*>("res"))) {
370             continue;
371         }
372         char* id = reinterpret_cast<char*>(xmlGetProp(grandson, reinterpret_cast<const xmlChar*>("id")));
373         char* name = reinterpret_cast<char*>(xmlGetProp(grandson, reinterpret_cast<const xmlChar*>("name")));
374         char* persistMode = reinterpret_cast<char*>(xmlGetProp(grandson,
375             reinterpret_cast<const xmlChar*>("switch")));
376         char* trace = reinterpret_cast<char*>(xmlGetProp(grandson, reinterpret_cast<const xmlChar*>("trace")));
377         if (!CheckGovResourceTag(id, name, persistMode, configFile)) {
378             xmlFree(id);
379             xmlFree(name);
380             xmlFree(persistMode);
381             xmlFree(trace);
382             return false;
383         }
384         auto it = resourceNodeInfo_.find(atoi(id));
385         if (it != resourceNodeInfo_.end()) {
386             xmlFree(id);
387             xmlFree(name);
388             xmlFree(persistMode);
389             xmlFree(trace);
390             continue;
391         }
392         xmlNode* greatGrandson = grandson->children;
393         std::shared_ptr<GovResNode> govResNode = std::make_shared<GovResNode>(atoi(id),
394             name, persistMode ? atoi(persistMode) : 0);
395         govResNode->trace = CheckTrace(trace);
396         xmlFree(id);
397         xmlFree(name);
398         xmlFree(trace);
399         std::unique_lock<std::mutex> lock(g_resStrToIdMutex);
400         g_resStrToIdInfo.insert(std::pair<std::string, int32_t>(govResNode->name, govResNode->id));
401         lock.unlock();
402 
403         std::unique_lock<std::mutex> lockResourceNode(resourceNodeMutex_);
404         resourceNodeInfo_.insert(std::pair<int32_t, std::shared_ptr<GovResNode>>(govResNode->id, govResNode));
405         lockResourceNode.unlock();
406 
407         if (!TraversalGovResource(persistMode ? atoi(persistMode) : 0, greatGrandson, configFile, govResNode)) {
408             xmlFree(persistMode);
409             return false;
410         }
411         xmlFree(persistMode);
412     }
413 
414     if (!CheckDefValid()) {
415         return false;
416     }
417 
418     return true;
419 }
420 
LoadInfo(xmlNode * child,const std::string & configFile)421 void SocPerfConfig::LoadInfo(xmlNode* child, const std::string& configFile)
422 {
423     xmlNode* grandson = child->children;
424     if (!grandson || xmlStrcmp(grandson->name, reinterpret_cast<const xmlChar*>("inf"))) {
425         return;
426     }
427     char* perfSoPath = reinterpret_cast<char*>(xmlGetProp(grandson, reinterpret_cast<const xmlChar*>("path")));
428     char* perfReportFunc =
429         reinterpret_cast<char*>(xmlGetProp(grandson, reinterpret_cast<const xmlChar*>("func")));
430     char* perfScenarioFunc =
431         reinterpret_cast<char*>(xmlGetProp(grandson, reinterpret_cast<const xmlChar*>("scenarioFunc")));
432     InitPerfFunc(perfSoPath, perfReportFunc, perfScenarioFunc);
433     xmlFree(perfSoPath);
434     xmlFree(perfReportFunc);
435     xmlFree(perfScenarioFunc);
436 }
437 
LoadInterAction(xmlNode * child,const std::string & configFile)438 void SocPerfConfig::LoadInterAction(xmlNode* child, const std::string& configFile)
439 {
440     xmlNode* grandson = child->children;
441     for (; grandson; grandson = grandson->next) {
442         if (xmlStrcmp(grandson->name, reinterpret_cast<const xmlChar*>("weak"))) {
443             continue;
444         }
445         char* cmdId = reinterpret_cast<char*>(xmlGetProp(grandson, reinterpret_cast<const xmlChar*>("id")));
446         char* delayTime = reinterpret_cast<char*>(xmlGetProp(grandson, reinterpret_cast<const xmlChar*>("delay")));
447         char* actionType = reinterpret_cast<char*>(xmlGetProp(grandson, reinterpret_cast<const xmlChar*>("type")));
448 
449         std::shared_ptr<InterAction> interAction = std::make_shared<InterAction>(
450             atoi(cmdId), atoi(actionType), atoll(delayTime));
451         interAction_.push_back(interAction);
452 
453         xmlFree(actionType);
454         xmlFree(delayTime);
455         xmlFree(cmdId);
456     }
457 }
458 
LoadSceneResource(xmlNode * child,const std::string & configFile)459 bool SocPerfConfig::LoadSceneResource(xmlNode* child, const std::string& configFile)
460 {
461     xmlNode* grandson = child->children;
462     for (; grandson; grandson = grandson->next) {
463         if (xmlStrcmp(grandson->name, reinterpret_cast<const xmlChar*>("scene"))) {
464             continue;
465         }
466         char* name = reinterpret_cast<char*>(xmlGetProp(grandson, reinterpret_cast<const xmlChar*>("name")));
467         char* persistMode = reinterpret_cast<char*>(xmlGetProp(grandson,
468             reinterpret_cast<const xmlChar*>("switch")));
469         if (!CheckSceneResourceTag(name, persistMode, configFile)) {
470             xmlFree(name);
471             xmlFree(persistMode);
472             return false;
473         }
474 
475         auto it = sceneResourceInfo_.find(name);
476         if (it != sceneResourceInfo_.end()) {
477             xmlFree(name);
478             xmlFree(persistMode);
479             continue;
480         }
481 
482         xmlNode* greatGrandson = grandson->children;
483         std::shared_ptr<SceneResNode> sceneResNode =
484             std::make_shared<SceneResNode>(name, persistMode ? atoi(persistMode) : 0);
485         xmlFree(name);
486         xmlFree(persistMode);
487 
488         std::unique_lock<std::mutex> lockSceneResource(sceneResourceMutex_);
489         sceneResourceInfo_.insert(std::pair<std::string, std::shared_ptr<SceneResNode>>(sceneResNode->name,
490             sceneResNode));
491         lockSceneResource.unlock();
492 
493         if (!TraversalSceneResource(greatGrandson, configFile, sceneResNode)) {
494             return false;
495         }
496     }
497 
498     return true;
499 }
500 
TraversalSceneResource(xmlNode * greatGrandson,const std::string & configFile,std::shared_ptr<SceneResNode> sceneResNode)501 bool SocPerfConfig::TraversalSceneResource(xmlNode* greatGrandson, const std::string& configFile,
502     std::shared_ptr<SceneResNode> sceneResNode)
503 {
504     for (; greatGrandson; greatGrandson = greatGrandson->next) {
505         if (!xmlStrcmp(greatGrandson->name, reinterpret_cast<const xmlChar*>("item"))) {
506             char* req = reinterpret_cast<char*>(
507                 xmlGetProp(greatGrandson, reinterpret_cast<const xmlChar*>("req")));
508             char* item = reinterpret_cast<char*>(xmlNodeGetContent(greatGrandson));
509             if (!item || (req && !IsNumber(req))) {
510                 SOC_PERF_LOGE("Invalid sceneernor resource item for %{private}s", configFile.c_str());
511                 xmlFree(item);
512                 xmlFree(req);
513                 return false;
514             }
515 
516             std::shared_ptr<SceneItem> sceneItem =
517                 std::make_shared<SceneItem>(item, req ? atoi(req) : 1);
518             sceneResNode->items.push_back(sceneItem);
519             xmlFree(item);
520             xmlFree(req);
521         }
522     }
523     return true;
524 }
525 
CheckSceneResourceTag(const char * name,const char * persistMode,const std::string & configFile) const526 bool SocPerfConfig::CheckSceneResourceTag(const char* name, const char* persistMode,
527     const std::string& configFile) const
528 {
529     if (!name) {
530         SOC_PERF_LOGE("Invalid sceneernor resource name for %{private}s", configFile.c_str());
531         return false;
532     }
533     if (persistMode && (!IsNumber(persistMode) || !IsValidPersistMode(atoi(persistMode)))) {
534         SOC_PERF_LOGE("Invalid sceneernor resource persistMode for %{private}s", configFile.c_str());
535         return false;
536     }
537     return true;
538 }
539 
TraversalGovResource(int32_t persistMode,xmlNode * greatGrandson,const std::string & configFile,std::shared_ptr<GovResNode> govResNode)540 bool SocPerfConfig::TraversalGovResource(int32_t persistMode, xmlNode* greatGrandson, const std::string& configFile,
541     std::shared_ptr<GovResNode> govResNode)
542 {
543     for (; greatGrandson; greatGrandson = greatGrandson->next) {
544         if (!xmlStrcmp(greatGrandson->name, reinterpret_cast<const xmlChar*>("default"))) {
545             char* def = reinterpret_cast<char*>(xmlNodeGetContent(greatGrandson));
546             if (!def || !IsNumber(def)) {
547                 SOC_PERF_LOGE("Invalid governor resource default for %{private}s", configFile.c_str());
548                 xmlFree(def);
549                 return false;
550             }
551             govResNode->def = atoll(def);
552             xmlFree(def);
553         } else if (persistMode != REPORT_TO_PERFSO &&
554             !xmlStrcmp(greatGrandson->name, reinterpret_cast<const xmlChar*>("path"))) {
555             char* path = reinterpret_cast<char*>(xmlNodeGetContent(greatGrandson));
556             if (!path) {
557                 SOC_PERF_LOGE("Invalid governor resource path for %{private}s", configFile.c_str());
558                 return false;
559             }
560             govResNode->paths.push_back(path);
561             xmlFree(path);
562         } else if (persistMode != REPORT_TO_PERFSO &&
563             !xmlStrcmp(greatGrandson->name, reinterpret_cast<const xmlChar*>("node"))) {
564             char* level = reinterpret_cast<char*>(
565                 xmlGetProp(greatGrandson, reinterpret_cast<const xmlChar*>("level")));
566             char* node = reinterpret_cast<char*>(xmlNodeGetContent(greatGrandson));
567             if (!level || !IsNumber(level) || !node
568                 || !LoadGovResourceAvailable(govResNode, level, node)) {
569                 SOC_PERF_LOGE("Invalid governor resource node for %{private}s", configFile.c_str());
570                 xmlFree(level);
571                 xmlFree(node);
572                 return false;
573             }
574             xmlFree(level);
575             xmlFree(node);
576         }
577     }
578     return true;
579 }
580 
LoadConfig(const xmlNode * rootNode,const std::string & configFile)581 bool SocPerfConfig::LoadConfig(const xmlNode* rootNode, const std::string& configFile)
582 {
583     bool configTag = IsConfigTag(rootNode);
584     xmlNode* configNode = rootNode->children;
585     if (configTag) {
586         if (!HandleConfigNode(configNode, configFile)) {
587             return false;
588         }
589     } else {
590         if (!LoadConfigInfo(rootNode, configFile, DEFAULT_CONFIG_MODE)) {
591             return false;
592         }
593     }
594 
595     if (!CheckActionResIdAndValueValid(configFile)) {
596         return false;
597     }
598 
599     return true;
600 }
601 
HandleConfigNode(const xmlNode * configNode,const std::string & configFile)602 bool SocPerfConfig::HandleConfigNode(const xmlNode* configNode, const std::string& configFile)
603 {
604     for (; configNode; configNode = configNode->next) { // Iterate all Config
605         if (!xmlStrcmp(configNode->name, reinterpret_cast<const xmlChar*>("Config"))) {
606             std::string configMode = GetConfigMode(configNode);
607             if (configMode.empty()) {
608                 configMode = DEFAULT_CONFIG_MODE;
609             }
610             if (!LoadConfigInfo(configNode, configFile, configMode)) {
611                 return false;
612             }
613         }
614     }
615     return true;
616 }
617 
GetConfigMode(const xmlNode * node)618 std::string SocPerfConfig::GetConfigMode(const xmlNode* node)
619 {
620     const xmlChar* configModeXml = xmlGetProp(node, reinterpret_cast<const xmlChar*>("mode"));
621     if (configModeXml == nullptr) {
622         return "";
623     }
624     char* configMode =  reinterpret_cast<char*>(const_cast<xmlChar*>(configModeXml));
625     std::string configModeStr(configMode);
626     xmlFree(configMode);
627     return configModeStr;
628 }
629 
IsConfigTag(const xmlNode * rootNode)630 bool SocPerfConfig::IsConfigTag(const xmlNode* rootNode)
631 {
632     xmlNode* child = rootNode->children;
633     for (; child; child = child->next) {
634         if (!xmlStrcmp(child->name, reinterpret_cast<const xmlChar*>("Config"))) {
635             return true;
636         }
637     }
638     return false;
639 }
640 
LoadConfigInfo(const xmlNode * configNode,const std::string & configFile,const std::string & configMode)641 bool SocPerfConfig::LoadConfigInfo(const xmlNode* configNode, const std::string& configFile,
642     const std::string& configMode)
643 {
644     xmlNode* child = configNode->children;
645     for (; child; child = child->next) { // Iterate all cmdID
646         if (!xmlStrcmp(child->name, reinterpret_cast<const xmlChar*>("cmd"))) {
647             if (!LoadCmdInfo(child, configFile, configMode)) {
648                 return false;
649             }
650         } else if (!xmlStrcmp(child->name, reinterpret_cast<const xmlChar*>("interaction"))) {
651             LoadInterAction(child, configFile);
652         }
653     }
654     return true;
655 }
656 
LoadCmdInfo(const xmlNode * child,const std::string & configFile,const std::string & configMode)657 bool SocPerfConfig::LoadCmdInfo(const xmlNode* child, const std::string& configFile, const std::string& configMode)
658 {
659     char* id = reinterpret_cast<char*>(xmlGetProp(child, reinterpret_cast<const xmlChar*>("id")));
660     char* name = reinterpret_cast<char*>(xmlGetProp(child, reinterpret_cast<const xmlChar*>("name")));
661     if (!CheckCmdTag(id, name, configFile)) {
662         xmlFree(id);
663         xmlFree(name);
664         return false;
665     }
666 
667     auto config = configPerfActionsInfo_.find(configMode);
668     std::unordered_map<int32_t, std::shared_ptr<Actions>> perfActionsInfo = {};
669     if (config != configPerfActionsInfo_.end()) {
670         perfActionsInfo = config->second;
671     }
672 
673     auto it = perfActionsInfo.find(atoi(id));
674     if (it != perfActionsInfo.end()) {
675         xmlFree(id);
676         xmlFree(name);
677         return true;
678     }
679 
680     xmlNode* grandson = child->children;
681     std::shared_ptr<Actions> actions = std::make_shared<Actions>(atoi(id), name);
682     xmlFree(id);
683     xmlFree(name);
684 
685     char* interaction = reinterpret_cast<char*>(xmlGetProp(child, reinterpret_cast<const xmlChar*>("interaction")));
686     if (interaction) {
687         if (atoi(interaction) == 0) {
688             actions->interaction = false;
689         }
690         xmlFree(interaction);
691     }
692 
693     char* mode = reinterpret_cast<char*>(xmlGetProp(child, reinterpret_cast<const xmlChar*>("mode")));
694     if (mode) {
695         if (configMode == DEFAULT_CONFIG_MODE) {
696             ParseModeCmd(mode, configFile, actions);
697         }
698         xmlFree(mode);
699     }
700 
701     if (!TraversalBoostResource(grandson, configFile, actions)) {
702         return false;
703     }
704 
705     std::unique_lock<std::mutex> lockPerfActions(perfActionsMutex_);
706     perfActionsInfo.insert(std::pair<int32_t, std::shared_ptr<Actions>>(actions->id, actions));
707     configPerfActionsInfo_[configMode] = perfActionsInfo;
708     lockPerfActions.unlock();
709     return true;
710 }
711 
ParseModeCmd(const char * mode,const std::string & configFile,std::shared_ptr<Actions> actions)712 void SocPerfConfig::ParseModeCmd(const char* mode, const std::string& configFile, std::shared_ptr<Actions> actions)
713 {
714     if (!mode) {
715         return;
716     }
717 
718     std::string modeStr = mode;
719     std::vector<std::string> modeListResult = Split(modeStr, SPLIT_OR);
720     for (auto pairStr : modeListResult) {
721         std::vector<std::string> itemPair = Split(pairStr, SPLIT_EQUAL);
722         if (itemPair.size() != RES_MODE_AND_ID_PAIR) {
723             SOC_PERF_LOGW("Invaild device mode pair for %{private}s", configFile.c_str());
724             continue;
725         }
726 
727         std::string modeDeviceStr = itemPair[0];
728         std::string modeCmdIdStr = itemPair[RES_MODE_AND_ID_PAIR -1];
729         if (modeDeviceStr.empty() || !IsNumber(modeCmdIdStr)) {
730             SOC_PERF_LOGW("Invaild device mode name for %{private}s", configFile.c_str());
731             continue;
732         }
733 
734         int32_t cmdId = atoi(modeCmdIdStr.c_str());
735         auto existMode = std::find_if(actions->modeMap.begin(), actions->modeMap.end(),
736             [&modeDeviceStr](const std::shared_ptr<ModeMap>& modeItem) {
737             return modeItem->mode == modeDeviceStr;
738         });
739         if (existMode != actions->modeMap.end()) {
740             (*existMode)->cmdId = cmdId;
741         } else {
742             std::shared_ptr<ModeMap> newMode = std::make_shared<ModeMap>(modeDeviceStr, cmdId);
743             actions->modeMap.push_back(newMode);
744         }
745     }
746 }
747 
ParseDuration(xmlNode * greatGrandson,const std::string & configFile,std::shared_ptr<Action> action) const748 bool SocPerfConfig::ParseDuration(xmlNode *greatGrandson,
749     const std::string& configFile, std::shared_ptr<Action> action) const
750 {
751     if (xmlStrcmp(greatGrandson->name, reinterpret_cast<const xmlChar*>("duration"))) {
752         return true;
753     }
754     char* duration = reinterpret_cast<char*>(xmlNodeGetContent(greatGrandson));
755     if (!duration || !IsNumber(duration)) {
756         SOC_PERF_LOGE("Invalid cmd duration for %{private}s", configFile.c_str());
757         xmlFree(duration);
758         return false;
759     }
760     action->duration = atoi(duration);
761     xmlFree(duration);
762     return true;
763 }
764 
ParseResValue(xmlNode * greatGrandson,const std::string & configFile,std::shared_ptr<Action> action)765 bool SocPerfConfig::ParseResValue(xmlNode* greatGrandson, const std::string& configFile, std::shared_ptr<Action> action)
766 {
767     if (!xmlStrcmp(greatGrandson->name, reinterpret_cast<const xmlChar*>("duration"))) {
768         return true;
769     }
770     char* resStr = reinterpret_cast<char*>(const_cast<xmlChar*>(greatGrandson->name));
771     char* resValue = reinterpret_cast<char*>(xmlNodeGetContent(greatGrandson));
772     if (!resStr || g_resStrToIdInfo.find(resStr) == g_resStrToIdInfo.end()
773         || !resValue || !IsNumber(resValue)) {
774         SOC_PERF_LOGE("Invalid cmd resource(%{public}s) for %{private}s", resStr, configFile.c_str());
775         xmlFree(resValue);
776         return false;
777     }
778     action->variable.push_back(g_resStrToIdInfo[resStr]);
779     action->variable.push_back(atoll(resValue));
780     xmlFree(resValue);
781     return true;
782 }
783 
GetXmlIntProp(const xmlNode * xmlNode,const char * propName,int32_t def) const784 int32_t SocPerfConfig::GetXmlIntProp(const xmlNode* xmlNode, const char* propName, int32_t def) const
785 {
786     int ret = def;
787     char* propValue = reinterpret_cast<char*>(xmlGetProp(xmlNode, reinterpret_cast<const xmlChar*>(propName)));
788     if (propValue != nullptr && IsNumber(propValue)) {
789         ret = atoi(propValue);
790     }
791     if (propValue != nullptr) {
792         xmlFree(propValue);
793     }
794     return ret;
795 }
796 
TraversalBoostResource(xmlNode * grandson,const std::string & configFile,std::shared_ptr<Actions> actions)797 bool SocPerfConfig::TraversalBoostResource(xmlNode* grandson,
798     const std::string& configFile, std::shared_ptr<Actions> actions)
799 {
800     for (; grandson; grandson = grandson->next) { // Iterate all Action
801         std::shared_ptr<Action> action = std::make_shared<Action>();
802         action->thermalLvl_ = GetXmlIntProp(grandson, "thermalLvl", INVALID_THERMAL_LVL);
803         if (action->thermalLvl_ != INVALID_THERMAL_LVL) {
804             if (minThermalLvl_ == INVALID_THERMAL_LVL || minThermalLvl_ > action->thermalLvl_) {
805                 minThermalLvl_ = action->thermalLvl_;
806             }
807         }
808         action->thermalCmdId_ = GetXmlIntProp(grandson, "thermalCmdId", INVALID_THERMAL_CMD_ID);
809         xmlNode* greatGrandson = grandson->children;
810         for (; greatGrandson; greatGrandson = greatGrandson->next) { // Iterate duration and all res
811             bool ret = ParseDuration(greatGrandson, configFile, action);
812             if (!ret) {
813                 return false;
814             }
815             if (action->duration == 0) {
816                 actions->isLongTimePerf = true;
817             }
818             ret = ParseResValue(greatGrandson, configFile, action);
819             if (!ret) {
820                 return false;
821             }
822         }
823         actions->actionList.push_back(action);
824     }
825     return true;
826 }
827 
CheckResourceTag(const char * id,const char * name,const char * pair,const char * mode,const char * persistMode,const std::string & configFile) const828 bool SocPerfConfig::CheckResourceTag(const char* id, const char* name, const char* pair, const char* mode,
829     const char* persistMode, const std::string& configFile) const
830 {
831     if (!id || !IsNumber(id) || !IsValidRangeResId(atoi(id))) {
832         SOC_PERF_LOGE("Invalid resource id for %{private}s", configFile.c_str());
833         return false;
834     }
835     if (!name) {
836         SOC_PERF_LOGE("Invalid resource name for %{private}s", configFile.c_str());
837         return false;
838     }
839     if (pair && (!IsNumber(pair) || !IsValidRangeResId(atoi(pair)))) {
840         SOC_PERF_LOGE("Invalid resource pair for %{private}s", configFile.c_str());
841         return false;
842     }
843     if (mode && !IsNumber(mode)) {
844         SOC_PERF_LOGE("Invalid resource mode for %{private}s", configFile.c_str());
845         return false;
846     }
847     return CheckResourcePersistMode(persistMode, configFile);
848 }
849 
CheckResourcePersistMode(const char * persistMode,const std::string & configFile) const850 bool SocPerfConfig::CheckResourcePersistMode(const char* persistMode, const std::string& configFile) const
851 {
852     if (persistMode && (!IsNumber(persistMode) || !IsValidPersistMode(atoi(persistMode)))) {
853         SOC_PERF_LOGE("Invalid resource persistMode for %{private}s", configFile.c_str());
854         return false;
855     }
856     return true;
857 }
858 
CheckResourceTag(int32_t persistMode,const char * def,const char * path,const std::string & configFile) const859 bool SocPerfConfig::CheckResourceTag(int32_t persistMode, const char* def,
860     const char* path, const std::string& configFile) const
861 {
862     if (!def || !IsNumber(def)) {
863         SOC_PERF_LOGE("Invalid resource default for %{private}s", configFile.c_str());
864         return false;
865     }
866     if (persistMode != REPORT_TO_PERFSO && !path) {
867         SOC_PERF_LOGE("Invalid resource path for %{private}s", configFile.c_str());
868         return false;
869     }
870     return true;
871 }
872 
LoadResourceAvailable(std::shared_ptr<ResNode> resNode,const char * node)873 bool SocPerfConfig::LoadResourceAvailable(std::shared_ptr<ResNode> resNode, const char* node)
874 {
875     std::string nodeStr = node;
876     std::vector<std::string> result = Split(nodeStr, SPLIT_SPACE);
877     for (auto str : result) {
878         if (IsNumber(str)) {
879             resNode->available.insert(atoll(str.c_str()));
880         } else {
881             return false;
882         }
883     }
884     return true;
885 }
886 
CheckPairResIdValid() const887 bool SocPerfConfig::CheckPairResIdValid() const
888 {
889     for (auto iter = resourceNodeInfo_.begin(); iter != resourceNodeInfo_.end(); ++iter) {
890         if (iter->second->isGov) {
891             continue;
892         }
893         int32_t resId = iter->first;
894         std::shared_ptr<ResNode> resNode = std::static_pointer_cast<ResNode>(iter->second);
895         int32_t pairResId = resNode->pair;
896         if (pairResId != INVALID_VALUE && resourceNodeInfo_.find(pairResId) == resourceNodeInfo_.end()) {
897             SOC_PERF_LOGE("resId[%{public}d]'s pairResId[%{public}d] is not valid", resId, pairResId);
898             return false;
899         }
900     }
901     return true;
902 }
903 
CheckDefValid() const904 bool SocPerfConfig::CheckDefValid() const
905 {
906     for (auto iter = resourceNodeInfo_.begin(); iter != resourceNodeInfo_.end(); ++iter) {
907         int32_t resId = iter->first;
908         std::shared_ptr<ResourceNode> resourceNode = iter->second;
909         int64_t def = resourceNode->def;
910         if (!resourceNode->available.empty() && resourceNode->available.find(def) == resourceNode->available.end()) {
911             SOC_PERF_LOGE("resId[%{public}d]'s def[%{public}lld] is not valid", resId, (long long)def);
912             return false;
913         }
914     }
915     return true;
916 }
917 
CheckGovResourceTag(const char * id,const char * name,const char * persistMode,const std::string & configFile) const918 bool SocPerfConfig::CheckGovResourceTag(const char* id, const char* name,
919     const char* persistMode, const std::string& configFile) const
920 {
921     if (!id || !IsNumber(id) || !IsValidRangeResId(atoi(id))) {
922         SOC_PERF_LOGE("Invalid governor resource id for %{private}s", configFile.c_str());
923         return false;
924     }
925     if (!name) {
926         SOC_PERF_LOGE("Invalid governor resource name for %{private}s", configFile.c_str());
927         return false;
928     }
929     if (persistMode && (!IsNumber(persistMode) || !IsValidPersistMode(atoi(persistMode)))) {
930         SOC_PERF_LOGE("Invalid governor resource persistMode for %{private}s", configFile.c_str());
931         return false;
932     }
933     return true;
934 }
935 
LoadGovResourceAvailable(std::shared_ptr<GovResNode> govResNode,const char * level,const char * node)936 bool SocPerfConfig::LoadGovResourceAvailable(std::shared_ptr<GovResNode> govResNode,
937     const char* level, const char* node)
938 {
939     govResNode->available.insert(atoll(level));
940     std::string nodeStr = node;
941     std::vector<std::string> result = Split(nodeStr, SPLIT_OR);
942     if (result.size() != govResNode->paths.size()) {
943         SOC_PERF_LOGE("Invalid governor resource node matches paths");
944         return false;
945     }
946     std::unique_lock<std::mutex> levelMutex(govResNode->levelToStrMutex_);
947     govResNode->levelToStr.insert(std::pair<int32_t, std::vector<std::string>>(atoll(level), result));
948     levelMutex.unlock();
949     return true;
950 }
951 
CheckCmdTag(const char * id,const char * name,const std::string & configFile) const952 bool SocPerfConfig::CheckCmdTag(const char* id, const char* name, const std::string& configFile) const
953 {
954     if (!id || !IsNumber(id)) {
955         SOC_PERF_LOGE("Invalid cmd id for %{private}s", configFile.c_str());
956         return false;
957     }
958     if (!name) {
959         SOC_PERF_LOGE("Invalid cmd name for %{private}s", configFile.c_str());
960         return false;
961     }
962     return true;
963 }
964 
TraversalActions(std::shared_ptr<Action> action,int32_t actionId)965 bool SocPerfConfig::TraversalActions(std::shared_ptr<Action> action, int32_t actionId)
966 {
967     for (int32_t i = 0; i < (int32_t)action->variable.size() - 1; i += RES_ID_AND_VALUE_PAIR) {
968         int32_t resId = action->variable[i];
969         int64_t resValue = action->variable[i + 1];
970         if (resourceNodeInfo_.find(resId) != resourceNodeInfo_.end()) {
971             if (resourceNodeInfo_[resId]->persistMode != REPORT_TO_PERFSO &&
972                 !resourceNodeInfo_[resId]->available.empty() &&
973                 resourceNodeInfo_[resId]->available.find(resValue) == resourceNodeInfo_[resId]->available.end()) {
974                 SOC_PERF_LOGE("action[%{public}d]'s resValue[%{public}lld] is not valid",
975                     actionId, (long long)resValue);
976                 return false;
977             }
978         } else {
979             SOC_PERF_LOGE("action[%{public}d]'s resId[%{public}d] is not valid", actionId, resId);
980             return false;
981         }
982     }
983     return true;
984 }
985 
CheckActionResIdAndValueValid(const std::string & configFile)986 bool SocPerfConfig::CheckActionResIdAndValueValid(const std::string& configFile)
987 {
988     std::unordered_map<std::string,
989         std::unordered_map<int32_t, std::shared_ptr<Actions>>> configs = configPerfActionsInfo_;
990     for (auto configsIter = configs.begin(); configsIter != configs.end(); ++configsIter) {
991         std::unordered_map<int32_t, std::shared_ptr<Actions>> actionsInfo = configsIter->second;
992         if (!CheckActionsValid(actionsInfo)) {
993             return false;
994         }
995     }
996     return true;
997 }
998 
CheckActionsValid(std::unordered_map<int32_t,std::shared_ptr<Actions>> & actionsInfo)999 bool SocPerfConfig::CheckActionsValid(std::unordered_map<int32_t, std::shared_ptr<Actions>>& actionsInfo)
1000 {
1001     for (auto actionsIter = actionsInfo.begin(); actionsIter != actionsInfo.end(); ++actionsIter) {
1002         int32_t actionId = actionsIter->first;
1003         std::shared_ptr<Actions> actions = actionsIter->second;
1004         for (auto actionIter = actions->actionList.begin(); actionIter != actions->actionList.end(); ++actionIter) {
1005             bool ret = TraversalActions(*actionIter, actionId);
1006             if (!ret) {
1007                 return false;
1008             }
1009         }
1010     }
1011     return true;
1012 }
1013 } // namespace SOCPERF
1014 } // namespace OHOS
1015