• 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 (!LoadCmd(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 
LoadCmd(const xmlNode * rootNode,const std::string & configFile)581 bool SocPerfConfig::LoadCmd(const xmlNode* rootNode, const std::string& configFile)
582 {
583     xmlNode* child = rootNode->children;
584     for (; child; child = child->next) { // Iterate all cmdID
585         if (!xmlStrcmp(child->name, reinterpret_cast<const xmlChar*>("cmd"))) {
586             if (!LoadCmdInfo(child, configFile)) {
587                 return false;
588             }
589         } else if (!xmlStrcmp(child->name, reinterpret_cast<const xmlChar*>("interaction"))) {
590             LoadInterAction(child, configFile);
591         }
592     }
593 
594     if (!CheckActionResIdAndValueValid(configFile)) {
595         return false;
596     }
597 
598     return true;
599 }
600 
LoadCmdInfo(const xmlNode * child,const std::string & configFile)601 bool SocPerfConfig::LoadCmdInfo(const xmlNode* child, const std::string& configFile)
602 {
603     char* id = reinterpret_cast<char*>(xmlGetProp(child, reinterpret_cast<const xmlChar*>("id")));
604     char* name = reinterpret_cast<char*>(xmlGetProp(child, reinterpret_cast<const xmlChar*>("name")));
605     if (!CheckCmdTag(id, name, configFile)) {
606         xmlFree(id);
607         xmlFree(name);
608         return false;
609     }
610 
611     auto it = perfActionsInfo_.find(atoi(id));
612     if (it != perfActionsInfo_.end()) {
613         xmlFree(id);
614         xmlFree(name);
615         return true;
616     }
617 
618     xmlNode* grandson = child->children;
619     std::shared_ptr<Actions> actions = std::make_shared<Actions>(atoi(id), name);
620     xmlFree(id);
621     xmlFree(name);
622 
623     char* interaction = reinterpret_cast<char*>(xmlGetProp(child, reinterpret_cast<const xmlChar*>("interaction")));
624     if (interaction) {
625         if (atoi(interaction) == 0) {
626             actions->interaction = false;
627         }
628         xmlFree(interaction);
629     }
630 
631     char* mode = reinterpret_cast<char*>(xmlGetProp(child, reinterpret_cast<const xmlChar*>("mode")));
632     if (mode) {
633         ParseModeCmd(mode, configFile, actions);
634         xmlFree(mode);
635     }
636 
637     if (!TraversalBoostResource(grandson, configFile, actions)) {
638         return false;
639     }
640 
641     std::unique_lock<std::mutex> lockPerfActions(perfActionsMutex_);
642     perfActionsInfo_.insert(std::pair<int32_t, std::shared_ptr<Actions>>(actions->id, actions));
643     lockPerfActions.unlock();
644     return true;
645 }
646 
ParseModeCmd(const char * mode,const std::string & configFile,std::shared_ptr<Actions> actions)647 void SocPerfConfig::ParseModeCmd(const char* mode, const std::string& configFile, std::shared_ptr<Actions> actions)
648 {
649     if (!mode) {
650         return;
651     }
652 
653     std::string modeStr = mode;
654     std::vector<std::string> modeListResult = Split(modeStr, SPLIT_OR);
655     for (auto pairStr : modeListResult) {
656         std::vector<std::string> itemPair = Split(pairStr, SPLIT_EQUAL);
657         if (itemPair.size() != RES_MODE_AND_ID_PAIR) {
658             SOC_PERF_LOGW("Invaild device mode pair for %{private}s", configFile.c_str());
659             continue;
660         }
661 
662         std::string modeDeviceStr = itemPair[0];
663         std::string modeCmdIdStr = itemPair[RES_MODE_AND_ID_PAIR -1];
664         if (modeDeviceStr.empty() || !IsNumber(modeCmdIdStr)) {
665             SOC_PERF_LOGW("Invaild device mode name for %{private}s", configFile.c_str());
666             continue;
667         }
668 
669         int32_t cmdId = atoi(modeCmdIdStr.c_str());
670         auto existMode = std::find_if(actions->modeMap.begin(), actions->modeMap.end(),
671             [&modeDeviceStr](const std::shared_ptr<ModeMap>& modeItem) {
672             return modeItem->mode == modeDeviceStr;
673         });
674         if (existMode != actions->modeMap.end()) {
675             (*existMode)->cmdId = cmdId;
676         } else {
677             std::shared_ptr<ModeMap> newMode = std::make_shared<ModeMap>(modeDeviceStr, cmdId);
678             actions->modeMap.push_back(newMode);
679         }
680     }
681 }
682 
ParseDuration(xmlNode * greatGrandson,const std::string & configFile,std::shared_ptr<Action> action) const683 bool SocPerfConfig::ParseDuration(xmlNode *greatGrandson,
684     const std::string& configFile, std::shared_ptr<Action> action) const
685 {
686     if (xmlStrcmp(greatGrandson->name, reinterpret_cast<const xmlChar*>("duration"))) {
687         return true;
688     }
689     char* duration = reinterpret_cast<char*>(xmlNodeGetContent(greatGrandson));
690     if (!duration || !IsNumber(duration)) {
691         SOC_PERF_LOGE("Invalid cmd duration for %{private}s", configFile.c_str());
692         xmlFree(duration);
693         return false;
694     }
695     action->duration = atoi(duration);
696     xmlFree(duration);
697     return true;
698 }
699 
ParseResValue(xmlNode * greatGrandson,const std::string & configFile,std::shared_ptr<Action> action)700 bool SocPerfConfig::ParseResValue(xmlNode* greatGrandson, const std::string& configFile, std::shared_ptr<Action> action)
701 {
702     if (!xmlStrcmp(greatGrandson->name, reinterpret_cast<const xmlChar*>("duration"))) {
703         return true;
704     }
705     char* resStr = reinterpret_cast<char*>(const_cast<xmlChar*>(greatGrandson->name));
706     char* resValue = reinterpret_cast<char*>(xmlNodeGetContent(greatGrandson));
707     if (!resStr || g_resStrToIdInfo.find(resStr) == g_resStrToIdInfo.end()
708         || !resValue || !IsNumber(resValue)) {
709         SOC_PERF_LOGE("Invalid cmd resource(%{public}s) for %{private}s", resStr, configFile.c_str());
710         xmlFree(resValue);
711         return false;
712     }
713     action->variable.push_back(g_resStrToIdInfo[resStr]);
714     action->variable.push_back(atoll(resValue));
715     xmlFree(resValue);
716     return true;
717 }
718 
GetXmlIntProp(const xmlNode * xmlNode,const char * propName) const719 int32_t SocPerfConfig::GetXmlIntProp(const xmlNode* xmlNode, const char* propName) const
720 {
721     int ret = -1;
722     char* propValue = reinterpret_cast<char*>(xmlGetProp(xmlNode, reinterpret_cast<const xmlChar*>(propName)));
723     if (propValue != nullptr && IsNumber(propValue)) {
724         ret = atoi(propValue);
725     }
726     if (propValue != nullptr) {
727         xmlFree(propValue);
728     }
729     return ret;
730 }
731 
TraversalBoostResource(xmlNode * grandson,const std::string & configFile,std::shared_ptr<Actions> actions)732 bool SocPerfConfig::TraversalBoostResource(xmlNode* grandson,
733     const std::string& configFile, std::shared_ptr<Actions> actions)
734 {
735     for (; grandson; grandson = grandson->next) { // Iterate all Action
736         std::shared_ptr<Action> action = std::make_shared<Action>();
737         action->thermalLvl_ = GetXmlIntProp(grandson, "thermalLvl");
738         action->thermalCmdId_ = GetXmlIntProp(grandson, "thermalCmdId");
739         xmlNode* greatGrandson = grandson->children;
740         for (; greatGrandson; greatGrandson = greatGrandson->next) { // Iterate duration and all res
741             bool ret = ParseDuration(greatGrandson, configFile, action);
742             if (!ret) {
743                 return false;
744             }
745             if (action->duration == 0) {
746                 actions->isLongTimePerf = true;
747             }
748             ret = ParseResValue(greatGrandson, configFile, action);
749             if (!ret) {
750                 return false;
751             }
752         }
753         actions->actionList.push_back(action);
754     }
755     return true;
756 }
757 
CheckResourceTag(const char * id,const char * name,const char * pair,const char * mode,const char * persistMode,const std::string & configFile) const758 bool SocPerfConfig::CheckResourceTag(const char* id, const char* name, const char* pair, const char* mode,
759     const char* persistMode, const std::string& configFile) const
760 {
761     if (!id || !IsNumber(id) || !IsValidRangeResId(atoi(id))) {
762         SOC_PERF_LOGE("Invalid resource id for %{private}s", configFile.c_str());
763         return false;
764     }
765     if (!name) {
766         SOC_PERF_LOGE("Invalid resource name for %{private}s", configFile.c_str());
767         return false;
768     }
769     if (pair && (!IsNumber(pair) || !IsValidRangeResId(atoi(pair)))) {
770         SOC_PERF_LOGE("Invalid resource pair for %{private}s", configFile.c_str());
771         return false;
772     }
773     if (mode && !IsNumber(mode)) {
774         SOC_PERF_LOGE("Invalid resource mode for %{private}s", configFile.c_str());
775         return false;
776     }
777     return CheckResourcePersistMode(persistMode, configFile);
778 }
779 
CheckResourcePersistMode(const char * persistMode,const std::string & configFile) const780 bool SocPerfConfig::CheckResourcePersistMode(const char* persistMode, const std::string& configFile) const
781 {
782     if (persistMode && (!IsNumber(persistMode) || !IsValidPersistMode(atoi(persistMode)))) {
783         SOC_PERF_LOGE("Invalid resource persistMode for %{private}s", configFile.c_str());
784         return false;
785     }
786     return true;
787 }
788 
CheckResourceTag(int32_t persistMode,const char * def,const char * path,const std::string & configFile) const789 bool SocPerfConfig::CheckResourceTag(int32_t persistMode, const char* def,
790     const char* path, const std::string& configFile) const
791 {
792     if (!def || !IsNumber(def)) {
793         SOC_PERF_LOGE("Invalid resource default for %{private}s", configFile.c_str());
794         return false;
795     }
796     if (persistMode != REPORT_TO_PERFSO && !path) {
797         SOC_PERF_LOGE("Invalid resource path for %{private}s", configFile.c_str());
798         return false;
799     }
800     return true;
801 }
802 
LoadResourceAvailable(std::shared_ptr<ResNode> resNode,const char * node)803 bool SocPerfConfig::LoadResourceAvailable(std::shared_ptr<ResNode> resNode, const char* node)
804 {
805     std::string nodeStr = node;
806     std::vector<std::string> result = Split(nodeStr, SPLIT_SPACE);
807     for (auto str : result) {
808         if (IsNumber(str)) {
809             resNode->available.insert(atoll(str.c_str()));
810         } else {
811             return false;
812         }
813     }
814     return true;
815 }
816 
CheckPairResIdValid() const817 bool SocPerfConfig::CheckPairResIdValid() const
818 {
819     for (auto iter = resourceNodeInfo_.begin(); iter != resourceNodeInfo_.end(); ++iter) {
820         if (iter->second->isGov) {
821             continue;
822         }
823         int32_t resId = iter->first;
824         std::shared_ptr<ResNode> resNode = std::static_pointer_cast<ResNode>(iter->second);
825         int32_t pairResId = resNode->pair;
826         if (pairResId != INVALID_VALUE && resourceNodeInfo_.find(pairResId) == resourceNodeInfo_.end()) {
827             SOC_PERF_LOGE("resId[%{public}d]'s pairResId[%{public}d] is not valid", resId, pairResId);
828             return false;
829         }
830     }
831     return true;
832 }
833 
CheckDefValid() const834 bool SocPerfConfig::CheckDefValid() const
835 {
836     for (auto iter = resourceNodeInfo_.begin(); iter != resourceNodeInfo_.end(); ++iter) {
837         int32_t resId = iter->first;
838         std::shared_ptr<ResourceNode> resourceNode = iter->second;
839         int64_t def = resourceNode->def;
840         if (!resourceNode->available.empty() && resourceNode->available.find(def) == resourceNode->available.end()) {
841             SOC_PERF_LOGE("resId[%{public}d]'s def[%{public}lld] is not valid", resId, (long long)def);
842             return false;
843         }
844     }
845     return true;
846 }
847 
CheckGovResourceTag(const char * id,const char * name,const char * persistMode,const std::string & configFile) const848 bool SocPerfConfig::CheckGovResourceTag(const char* id, const char* name,
849     const char* persistMode, const std::string& configFile) const
850 {
851     if (!id || !IsNumber(id) || !IsValidRangeResId(atoi(id))) {
852         SOC_PERF_LOGE("Invalid governor resource id for %{private}s", configFile.c_str());
853         return false;
854     }
855     if (!name) {
856         SOC_PERF_LOGE("Invalid governor resource name for %{private}s", configFile.c_str());
857         return false;
858     }
859     if (persistMode && (!IsNumber(persistMode) || !IsValidPersistMode(atoi(persistMode)))) {
860         SOC_PERF_LOGE("Invalid governor resource persistMode for %{private}s", configFile.c_str());
861         return false;
862     }
863     return true;
864 }
865 
LoadGovResourceAvailable(std::shared_ptr<GovResNode> govResNode,const char * level,const char * node)866 bool SocPerfConfig::LoadGovResourceAvailable(std::shared_ptr<GovResNode> govResNode,
867     const char* level, const char* node)
868 {
869     govResNode->available.insert(atoll(level));
870     std::string nodeStr = node;
871     std::vector<std::string> result = Split(nodeStr, SPLIT_OR);
872     if (result.size() != govResNode->paths.size()) {
873         SOC_PERF_LOGE("Invalid governor resource node matches paths");
874         return false;
875     }
876     std::unique_lock<std::mutex> levelMutex(govResNode->levelToStrMutex_);
877     govResNode->levelToStr.insert(std::pair<int32_t, std::vector<std::string>>(atoll(level), result));
878     levelMutex.unlock();
879     return true;
880 }
881 
CheckCmdTag(const char * id,const char * name,const std::string & configFile) const882 bool SocPerfConfig::CheckCmdTag(const char* id, const char* name, const std::string& configFile) const
883 {
884     if (!id || !IsNumber(id)) {
885         SOC_PERF_LOGE("Invalid cmd id for %{private}s", configFile.c_str());
886         return false;
887     }
888     if (!name) {
889         SOC_PERF_LOGE("Invalid cmd name for %{private}s", configFile.c_str());
890         return false;
891     }
892     return true;
893 }
894 
TraversalActions(std::shared_ptr<Action> action,int32_t actionId)895 bool SocPerfConfig::TraversalActions(std::shared_ptr<Action> action, int32_t actionId)
896 {
897     for (int32_t i = 0; i < (int32_t)action->variable.size() - 1; i += RES_ID_AND_VALUE_PAIR) {
898         int32_t resId = action->variable[i];
899         int64_t resValue = action->variable[i + 1];
900         if (resourceNodeInfo_.find(resId) != resourceNodeInfo_.end()) {
901             if (resourceNodeInfo_[resId]->persistMode != REPORT_TO_PERFSO &&
902                 !resourceNodeInfo_[resId]->available.empty() &&
903                 resourceNodeInfo_[resId]->available.find(resValue) == resourceNodeInfo_[resId]->available.end()) {
904                 SOC_PERF_LOGE("action[%{public}d]'s resValue[%{public}lld] is not valid",
905                     actionId, (long long)resValue);
906                 return false;
907             }
908         } else {
909             SOC_PERF_LOGE("action[%{public}d]'s resId[%{public}d] is not valid", actionId, resId);
910             return false;
911         }
912     }
913     return true;
914 }
915 
CheckActionResIdAndValueValid(const std::string & configFile)916 bool SocPerfConfig::CheckActionResIdAndValueValid(const std::string& configFile)
917 {
918     std::unordered_map<int32_t, std::shared_ptr<Actions>> actionsInfo = perfActionsInfo_;
919     for (auto actionsIter = actionsInfo.begin(); actionsIter != actionsInfo.end(); ++actionsIter) {
920         int32_t actionId = actionsIter->first;
921         std::shared_ptr<Actions> actions = actionsIter->second;
922         for (auto actionIter = actions->actionList.begin(); actionIter != actions->actionList.end(); ++actionIter) {
923             bool ret = TraversalActions(*actionIter, actionId);
924             if (!ret) {
925                 return false;
926             }
927         }
928     }
929     return true;
930 }
931 } // namespace SOCPERF
932 } // namespace OHOS
933