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 <chrono>
16 #include <dlfcn.h>
17 #include "socperf_config.h"
18 #include "config_policy_utils.h"
19 #include "hisysevent.h"
20 #include "hitrace_meter.h"
21 #include "parameters.h"
22 #ifdef RES_SCHED_SA_INIT
23 #include "res_sa_init.h"
24 #endif
25 
26 namespace OHOS {
27 namespace SOCPERF {
28 namespace {
29     std::mutex g_resStrToIdMutex;
30     std::unordered_map<std::string, int32_t> g_resStrToIdInfo;
31     void* g_handle;
32     const std::string SPLIT_OR = "|";
33     const std::string SPLIT_EQUAL = "=";
34     const std::string SPLIT_SPACE = " ";
35 }
36 
GetInstance()37 SocPerfConfig& SocPerfConfig::GetInstance()
38 {
39     static SocPerfConfig socPerfConfig_;
40     return socPerfConfig_;
41 }
42 
SocPerfConfig()43 SocPerfConfig::SocPerfConfig() {}
44 
~SocPerfConfig()45 SocPerfConfig::~SocPerfConfig()
46 {
47     if (g_handle != nullptr) {
48         dlclose(g_handle);
49         g_handle = nullptr;
50     }
51 }
52 
Init()53 bool SocPerfConfig::Init()
54 {
55 #ifdef RES_SCHED_SA_INIT
56     std::lock_guard<std::mutex> xmlLock(ResourceSchedule::ResSchedSaInit::GetInstance().saInitXmlMutex_);
57 #endif
58     std::string resourceConfigXml = system::GetParameter("ohos.boot.kernel", "").size() > 0 ?
59         SOCPERF_BOOST_CONFIG_XML_EXT : SOCPERF_BOOST_CONFIG_XML;
60     if (!LoadConfigXmlFile(SOCPERF_RESOURCE_CONFIG_XML)) {
61         SOC_PERF_LOGE("Failed to load %{private}s", SOCPERF_RESOURCE_CONFIG_XML.c_str());
62         return false;
63     }
64 
65     if (!LoadConfigXmlFile(resourceConfigXml)) {
66         SOC_PERF_LOGE("Failed to load %{private}s", resourceConfigXml.c_str());
67         return false;
68     }
69 
70     std::unique_lock<std::mutex> lock(g_resStrToIdMutex);
71     g_resStrToIdInfo.clear();
72     g_resStrToIdInfo = std::unordered_map<std::string, int32_t>();
73     lock.unlock();
74     SOC_PERF_LOGD("SocPerf Init SUCCESS!");
75     return true;
76 }
77 
IsGovResId(int32_t resId) const78 bool SocPerfConfig::IsGovResId(int32_t resId) const
79 {
80     auto item = resourceNodeInfo_.find(resId);
81     if (item != resourceNodeInfo_.end() && item->second->isGov) {
82         return true;
83     }
84     return false;
85 }
86 
IsValidResId(int32_t resId) const87 bool SocPerfConfig::IsValidResId(int32_t resId) const
88 {
89     if (resourceNodeInfo_.find(resId) == resourceNodeInfo_.end()) {
90         return false;
91     }
92     return true;
93 }
94 
GetRealConfigPath(const std::string & configFile)95 std::string SocPerfConfig::GetRealConfigPath(const std::string& configFile)
96 {
97     char buf[PATH_MAX + 1];
98     char* configFilePath = GetOneCfgFile(configFile.c_str(), buf, PATH_MAX + 1);
99     char tmpPath[PATH_MAX + 1] = {0};
100     if (!configFilePath || strlen(configFilePath) == 0 || strlen(configFilePath) > PATH_MAX ||
101         !realpath(configFilePath, tmpPath)) {
102         SOC_PERF_LOGE("load %{private}s file fail", configFile.c_str());
103         return "";
104     }
105     return std::string(tmpPath);
106 }
107 
LoadConfigXmlFile(const std::string & configFile)108 bool SocPerfConfig::LoadConfigXmlFile(const std::string& configFile)
109 {
110     std::string realConfigFile = GetRealConfigPath(configFile);
111     if (realConfigFile.size() == 0) {
112         return false;
113     }
114     xmlKeepBlanksDefault(0);
115     xmlDoc* file = xmlReadFile(realConfigFile.c_str(), nullptr, XML_PARSE_NOERROR | XML_PARSE_NOWARNING);
116     if (!file) {
117         SOC_PERF_LOGE("Failed to open xml file");
118         return false;
119     }
120     xmlNode* rootNode = xmlDocGetRootElement(file);
121     if (!rootNode) {
122         SOC_PERF_LOGE("Failed to get xml file's RootNode");
123         xmlFreeDoc(file);
124         return false;
125     }
126     if (!xmlStrcmp(rootNode->name, reinterpret_cast<const xmlChar*>("Configs"))) {
127         if (realConfigFile.find(SOCPERF_RESOURCE_CONFIG_XML) != std::string::npos) {
128             bool ret = ParseResourceXmlFile(rootNode, realConfigFile, file);
129             if (!ret) {
130                 xmlFreeDoc(file);
131                 return false;
132             }
133         } else {
134             bool ret = ParseBoostXmlFile(rootNode, realConfigFile, file);
135             if (!ret) {
136                 xmlFreeDoc(file);
137                 return false;
138             }
139         }
140     } else {
141         SOC_PERF_LOGE("Wrong format for xml file");
142         xmlFreeDoc(file);
143         return false;
144     }
145     xmlFreeDoc(file);
146     SOC_PERF_LOGD("Success to Load %{private}s", configFile.c_str());
147     return true;
148 }
149 
InitPerfFunc(const char * perfSoPath,const char * perfSoFunc)150 void SocPerfConfig::InitPerfFunc(const char* perfSoPath, const char* perfSoFunc)
151 {
152     if (perfSoPath == nullptr || perfSoFunc == nullptr) {
153         return;
154     }
155 
156     g_handle = dlopen(perfSoPath, RTLD_NOW);
157     if (g_handle == nullptr) {
158         SOC_PERF_LOGE("perf so doesn't exist");
159         return;
160     }
161 
162     reportFunc_ = reinterpret_cast<ReportDataFunc>(dlsym(g_handle, perfSoFunc));
163     if (reportFunc_ == nullptr) {
164         SOC_PERF_LOGE("perf func doesn't exist");
165         dlclose(g_handle);
166     }
167 }
168 
ParseBoostXmlFile(const xmlNode * rootNode,const std::string & realConfigFile,xmlDoc * file)169 bool SocPerfConfig::ParseBoostXmlFile(const xmlNode* rootNode, const std::string& realConfigFile, xmlDoc* file)
170 {
171     if (!LoadCmd(rootNode, realConfigFile)) {
172         return false;
173     }
174     return true;
175 }
176 
ParseResourceXmlFile(const xmlNode * rootNode,const std::string & realConfigFile,xmlDoc * file)177 bool SocPerfConfig::ParseResourceXmlFile(const xmlNode* rootNode, const std::string& realConfigFile, xmlDoc* file)
178 {
179     xmlNode* child = rootNode->children;
180     for (; child; child = child->next) {
181         if (!xmlStrcmp(child->name, reinterpret_cast<const xmlChar*>("Resource"))) {
182             if (!LoadResource(child, realConfigFile)) {
183                 return false;
184             }
185         } else if (!xmlStrcmp(child->name, reinterpret_cast<const xmlChar*>("GovResource"))) {
186             if (!LoadGovResource(child, realConfigFile)) {
187                 return false;
188             }
189         } else if (!xmlStrcmp(child->name, reinterpret_cast<const xmlChar*>("Info"))) {
190             LoadInfo(child, realConfigFile);
191         }
192     }
193     return true;
194 }
195 
LoadResource(xmlNode * child,const std::string & configFile)196 bool SocPerfConfig::LoadResource(xmlNode* child, const std::string& configFile)
197 {
198     xmlNode* grandson = child->children;
199     for (; grandson; grandson = grandson->next) {
200         if (!xmlStrcmp(grandson->name, reinterpret_cast<const xmlChar*>("res"))) {
201             if (!TraversalFreqResource(grandson, configFile)) {
202                 return false;
203             }
204         }
205     }
206 
207     if (!CheckPairResIdValid() || !CheckDefValid()) {
208         return false;
209     }
210 
211     return true;
212 }
213 
TraversalFreqResource(xmlNode * grandson,const std::string & configFile)214 bool SocPerfConfig::TraversalFreqResource(xmlNode* grandson, const std::string& configFile)
215 {
216     char* id = reinterpret_cast<char*>(xmlGetProp(grandson, reinterpret_cast<const xmlChar*>("id")));
217     char* name = reinterpret_cast<char*>(xmlGetProp(grandson, reinterpret_cast<const xmlChar*>("name")));
218     char* pair = reinterpret_cast<char*>(xmlGetProp(grandson, reinterpret_cast<const xmlChar*>("pair")));
219     char* mode = reinterpret_cast<char*>(xmlGetProp(grandson, reinterpret_cast<const xmlChar*>("mode")));
220     char* persistMode = reinterpret_cast<char*>(xmlGetProp(grandson, reinterpret_cast<const xmlChar*>("switch")));
221     if (!CheckResourceTag(id, name, pair, mode, persistMode, configFile)) {
222         xmlFree(id);
223         xmlFree(name);
224         xmlFree(pair);
225         xmlFree(mode);
226         xmlFree(persistMode);
227         return false;
228     }
229     xmlNode* greatGrandson = grandson->children;
230     std::shared_ptr<ResNode> resNode = std::make_shared<ResNode>(atoi(id), name, mode ? atoi(mode) : 0,
231         pair ? atoi(pair) : INVALID_VALUE, persistMode ? atoi(persistMode) : 0);
232     xmlFree(id);
233     xmlFree(name);
234     xmlFree(pair);
235     xmlFree(mode);
236     if (!LoadFreqResourceContent(persistMode ? atoi(persistMode) : 0, greatGrandson, configFile, resNode)) {
237         xmlFree(persistMode);
238         return false;
239     }
240     xmlFree(persistMode);
241     return true;
242 }
243 
LoadFreqResourceContent(int32_t persistMode,xmlNode * greatGrandson,const std::string & configFile,std::shared_ptr<ResNode> resNode)244 bool SocPerfConfig::LoadFreqResourceContent(int32_t persistMode, xmlNode* greatGrandson, const std::string& configFile,
245     std::shared_ptr<ResNode> resNode)
246 {
247     char *def = nullptr;
248     char *path  = nullptr;
249     char *node  = nullptr;
250     for (; greatGrandson; greatGrandson = greatGrandson->next) {
251         if (!xmlStrcmp(greatGrandson->name, reinterpret_cast<const xmlChar*>("default"))) {
252             xmlFree(def);
253             def = reinterpret_cast<char*>(xmlNodeGetContent(greatGrandson));
254         } else if (persistMode != REPORT_TO_PERFSO &&
255             !xmlStrcmp(greatGrandson->name, reinterpret_cast<const xmlChar*>("path"))) {
256             xmlFree(path);
257             path = reinterpret_cast<char*>(xmlNodeGetContent(greatGrandson));
258         } else if (!xmlStrcmp(greatGrandson->name, reinterpret_cast<const xmlChar*>("node"))) {
259             xmlFree(node);
260             node = reinterpret_cast<char*>(xmlNodeGetContent(greatGrandson));
261         }
262     }
263     if (!CheckResourceTag(persistMode, def, path, configFile)) {
264         xmlFree(def);
265         xmlFree(path);
266         xmlFree(node);
267         return false;
268     }
269     resNode->def = atoll(def);
270     if (persistMode != REPORT_TO_PERFSO) {
271         resNode->path = path;
272     }
273     xmlFree(def);
274     xmlFree(path);
275     if (node && !LoadResourceAvailable(resNode, node)) {
276         SOC_PERF_LOGE("Invalid resource node for %{private}s", configFile.c_str());
277         xmlFree(node);
278         return false;
279     }
280     xmlFree(node);
281 
282     std::unique_lock<std::mutex> lock(g_resStrToIdMutex);
283     g_resStrToIdInfo.insert(std::pair<std::string, int32_t>(resNode->name, resNode->id));
284     lock.unlock();
285 
286     std::unique_lock<std::mutex> lockResourceNode(resourceNodeMutex_);
287     resourceNodeInfo_.insert(std::pair<int32_t, std::shared_ptr<ResNode>>(resNode->id, resNode));
288     lockResourceNode.unlock();
289 
290     return true;
291 }
292 
LoadGovResource(xmlNode * child,const std::string & configFile)293 bool SocPerfConfig::LoadGovResource(xmlNode* child, const std::string& configFile)
294 {
295     xmlNode* grandson = child->children;
296     for (; grandson; grandson = grandson->next) {
297         if (xmlStrcmp(grandson->name, reinterpret_cast<const xmlChar*>("res"))) {
298             continue;
299         }
300         char* id = reinterpret_cast<char*>(xmlGetProp(grandson, reinterpret_cast<const xmlChar*>("id")));
301         char* name = reinterpret_cast<char*>(xmlGetProp(grandson, reinterpret_cast<const xmlChar*>("name")));
302         char* persistMode = reinterpret_cast<char*>(xmlGetProp(grandson,
303             reinterpret_cast<const xmlChar*>("switch")));
304         if (!CheckGovResourceTag(id, name, persistMode, configFile)) {
305             xmlFree(id);
306             xmlFree(name);
307             xmlFree(persistMode);
308             return false;
309         }
310         xmlNode* greatGrandson = grandson->children;
311         std::shared_ptr<GovResNode> govResNode = std::make_shared<GovResNode>(atoi(id),
312             name, persistMode ? atoi(persistMode) : 0);
313         xmlFree(id);
314         xmlFree(name);
315 
316         std::unique_lock<std::mutex> lock(g_resStrToIdMutex);
317         g_resStrToIdInfo.insert(std::pair<std::string, int32_t>(govResNode->name, govResNode->id));
318         lock.unlock();
319 
320         std::unique_lock<std::mutex> lockResourceNode(resourceNodeMutex_);
321         resourceNodeInfo_.insert(std::pair<int32_t, std::shared_ptr<GovResNode>>(govResNode->id, govResNode));
322         lockResourceNode.unlock();
323 
324         if (!TraversalGovResource(persistMode ? atoi(persistMode) : 0, greatGrandson, configFile, govResNode)) {
325             xmlFree(persistMode);
326             return false;
327         }
328         xmlFree(persistMode);
329     }
330 
331     if (!CheckDefValid()) {
332         return false;
333     }
334 
335     return true;
336 }
337 
LoadInfo(xmlNode * child,const std::string & configFile)338 void SocPerfConfig::LoadInfo(xmlNode* child, const std::string& configFile)
339 {
340     xmlNode* grandson = child->children;
341     if (!grandson || xmlStrcmp(grandson->name, reinterpret_cast<const xmlChar*>("inf"))) {
342         return;
343     }
344     char* perfSoPath = reinterpret_cast<char*>(xmlGetProp(grandson, reinterpret_cast<const xmlChar*>("path")));
345     char* perfSoFunc = reinterpret_cast<char*>(xmlGetProp(grandson, reinterpret_cast<const xmlChar*>("func")));
346     InitPerfFunc(perfSoPath, perfSoFunc);
347     xmlFree(perfSoPath);
348     xmlFree(perfSoFunc);
349 }
350 
TraversalGovResource(int32_t persistMode,xmlNode * greatGrandson,const std::string & configFile,std::shared_ptr<GovResNode> govResNode)351 bool SocPerfConfig::TraversalGovResource(int32_t persistMode, xmlNode* greatGrandson, const std::string& configFile,
352     std::shared_ptr<GovResNode> govResNode)
353 {
354     for (; greatGrandson; greatGrandson = greatGrandson->next) {
355         if (!xmlStrcmp(greatGrandson->name, reinterpret_cast<const xmlChar*>("default"))) {
356             char* def = reinterpret_cast<char*>(xmlNodeGetContent(greatGrandson));
357             if (!def || !IsNumber(def)) {
358                 SOC_PERF_LOGE("Invalid governor resource default for %{private}s", configFile.c_str());
359                 xmlFree(def);
360                 return false;
361             }
362             govResNode->def = atoll(def);
363             xmlFree(def);
364         } else if (persistMode != REPORT_TO_PERFSO &&
365             !xmlStrcmp(greatGrandson->name, reinterpret_cast<const xmlChar*>("path"))) {
366             char* path = reinterpret_cast<char*>(xmlNodeGetContent(greatGrandson));
367             if (!path) {
368                 SOC_PERF_LOGE("Invalid governor resource path for %{private}s", configFile.c_str());
369                 return false;
370             }
371             govResNode->paths.push_back(path);
372             xmlFree(path);
373         } else if (persistMode != REPORT_TO_PERFSO &&
374             !xmlStrcmp(greatGrandson->name, reinterpret_cast<const xmlChar*>("node"))) {
375             char* level = reinterpret_cast<char*>(
376                 xmlGetProp(greatGrandson, reinterpret_cast<const xmlChar*>("level")));
377             char* node = reinterpret_cast<char*>(xmlNodeGetContent(greatGrandson));
378             if (!level || !IsNumber(level) || !node
379                 || !LoadGovResourceAvailable(govResNode, level, node)) {
380                 SOC_PERF_LOGE("Invalid governor resource node for %{private}s", configFile.c_str());
381                 xmlFree(level);
382                 xmlFree(node);
383                 return false;
384             }
385             xmlFree(level);
386             xmlFree(node);
387         }
388     }
389     return true;
390 }
391 
LoadCmd(const xmlNode * rootNode,const std::string & configFile)392 bool SocPerfConfig::LoadCmd(const xmlNode* rootNode, const std::string& configFile)
393 {
394     xmlNode* child = rootNode->children;
395     for (; child; child = child->next) { // Iterate all cmdID
396         if (xmlStrcmp(child->name, reinterpret_cast<const xmlChar*>("cmd"))) {
397             continue;
398         }
399         char* id = reinterpret_cast<char*>(xmlGetProp(child, reinterpret_cast<const xmlChar*>("id")));
400         char* name = reinterpret_cast<char*>(xmlGetProp(child, reinterpret_cast<const xmlChar*>("name")));
401         if (!CheckCmdTag(id, name, configFile)) {
402             xmlFree(id);
403             xmlFree(name);
404             return false;
405         }
406         xmlNode* grandson = child->children;
407         std::shared_ptr<Actions> actions = std::make_shared<Actions>(atoi(id), name);
408         xmlFree(id);
409         xmlFree(name);
410 
411         char* mode = reinterpret_cast<char*>(xmlGetProp(child, reinterpret_cast<const xmlChar*>("mode")));
412         if (mode) {
413             ParseModeCmd(mode, configFile, actions);
414             xmlFree(mode);
415         }
416 
417         if (!TraversalBoostResource(grandson, configFile, actions)) {
418             return false;
419         }
420         std::unique_lock<std::mutex> lockPerfActions(perfActionsMutex_);
421         perfActionsInfo_.insert(std::pair<int32_t, std::shared_ptr<Actions>>(actions->id, actions));
422         lockPerfActions.unlock();
423     }
424 
425     if (!CheckActionResIdAndValueValid(configFile)) {
426         return false;
427     }
428 
429     return true;
430 }
431 
ParseModeCmd(const char * mode,const std::string & configFile,std::shared_ptr<Actions> actions)432 void SocPerfConfig::ParseModeCmd(const char* mode, const std::string& configFile, std::shared_ptr<Actions> actions)
433 {
434     if (!mode) {
435         return;
436     }
437 
438     std::string modeStr = mode;
439     std::vector<std::string> modeListResult = Split(modeStr, SPLIT_OR);
440     for (auto pairStr : modeListResult) {
441         std::vector<std::string> itemPair = Split(pairStr, SPLIT_EQUAL);
442         if (itemPair.size() != RES_MODE_AND_ID_PAIR) {
443             SOC_PERF_LOGW("Invaild device mode pair for %{private}s", configFile.c_str());
444             continue;
445         }
446 
447         std::string modeDeviceStr = itemPair[0];
448         std::string modeCmdIdStr = itemPair[RES_MODE_AND_ID_PAIR -1];
449         if (modeDeviceStr.empty() || !IsNumber(modeCmdIdStr)) {
450             SOC_PERF_LOGW("Invaild device mode name for %{private}s", configFile.c_str());
451             continue;
452         }
453 
454         int32_t cmdId = atoi(modeCmdIdStr.c_str());
455         auto iter = actions->modeMap.find(modeDeviceStr);
456         if (iter != actions->modeMap.end()) {
457             iter->second = cmdId;
458         } else {
459             std::unique_lock<std::mutex> lockModeMap(actions->modeMapMutex_);
460             actions->modeMap.insert(std::pair<std::string, int32_t>(modeDeviceStr, cmdId));
461             lockModeMap.unlock();
462         }
463     }
464 }
465 
ParseDuration(xmlNode * greatGrandson,const std::string & configFile,std::shared_ptr<Action> action) const466 bool SocPerfConfig::ParseDuration(xmlNode *greatGrandson,
467     const std::string& configFile, std::shared_ptr<Action> action) const
468 {
469     if (xmlStrcmp(greatGrandson->name, reinterpret_cast<const xmlChar*>("duration"))) {
470         return true;
471     }
472     char* duration = reinterpret_cast<char*>(xmlNodeGetContent(greatGrandson));
473     if (!duration || !IsNumber(duration)) {
474         SOC_PERF_LOGE("Invalid cmd duration for %{private}s", configFile.c_str());
475         xmlFree(duration);
476         return false;
477     }
478     action->duration = atoi(duration);
479     xmlFree(duration);
480     return true;
481 }
482 
ParseResValue(xmlNode * greatGrandson,const std::string & configFile,std::shared_ptr<Action> action)483 bool SocPerfConfig::ParseResValue(xmlNode* greatGrandson, const std::string& configFile, std::shared_ptr<Action> action)
484 {
485     if (!xmlStrcmp(greatGrandson->name, reinterpret_cast<const xmlChar*>("duration"))) {
486         return true;
487     }
488     char* resStr = reinterpret_cast<char*>(const_cast<xmlChar*>(greatGrandson->name));
489     char* resValue = reinterpret_cast<char*>(xmlNodeGetContent(greatGrandson));
490     if (!resStr || g_resStrToIdInfo.find(resStr) == g_resStrToIdInfo.end()
491         || !resValue || !IsNumber(resValue)) {
492         SOC_PERF_LOGE("Invalid cmd resource(%{public}s) for %{private}s", resStr, configFile.c_str());
493         xmlFree(resValue);
494         return false;
495     }
496     action->variable.push_back(g_resStrToIdInfo[resStr]);
497     action->variable.push_back(atoll(resValue));
498     xmlFree(resValue);
499     return true;
500 }
501 
GetXmlIntProp(const xmlNode * xmlNode,const char * propName) const502 int32_t SocPerfConfig::GetXmlIntProp(const xmlNode* xmlNode, const char* propName) const
503 {
504     int ret = -1;
505     char* propValue = reinterpret_cast<char*>(xmlGetProp(xmlNode, reinterpret_cast<const xmlChar*>(propName)));
506     if (propValue != nullptr && IsNumber(propValue)) {
507         ret = atoi(propValue);
508     }
509     if (propValue != nullptr) {
510         xmlFree(propValue);
511     }
512     return ret;
513 }
514 
TraversalBoostResource(xmlNode * grandson,const std::string & configFile,std::shared_ptr<Actions> actions)515 bool SocPerfConfig::TraversalBoostResource(xmlNode* grandson,
516     const std::string& configFile, std::shared_ptr<Actions> actions)
517 {
518     for (; grandson; grandson = grandson->next) { // Iterate all Action
519         std::shared_ptr<Action> action = std::make_shared<Action>();
520         action->thermalLvl_ = GetXmlIntProp(grandson, "thermalLvl");
521         action->thermalCmdId_ = GetXmlIntProp(grandson, "thermalCmdId");
522         xmlNode* greatGrandson = grandson->children;
523         for (; greatGrandson; greatGrandson = greatGrandson->next) { // Iterate duration and all res
524             bool ret = ParseDuration(greatGrandson, configFile, action);
525             if (!ret) {
526                 return false;
527             }
528             if (action->duration == 0) {
529                 actions->isLongTimePerf = true;
530             }
531             ret = ParseResValue(greatGrandson, configFile, action);
532             if (!ret) {
533                 return false;
534             }
535         }
536         actions->actionList.push_back(action);
537     }
538     return true;
539 }
540 
CheckResourceTag(const char * id,const char * name,const char * pair,const char * mode,const char * persistMode,const std::string & configFile) const541 bool SocPerfConfig::CheckResourceTag(const char* id, const char* name, const char* pair, const char* mode,
542     const char* persistMode, const std::string& configFile) const
543 {
544     if (!id || !IsNumber(id) || !IsValidRangeResId(atoi(id))) {
545         SOC_PERF_LOGE("Invalid resource id for %{private}s", configFile.c_str());
546         return false;
547     }
548     if (!name) {
549         SOC_PERF_LOGE("Invalid resource name for %{private}s", configFile.c_str());
550         return false;
551     }
552     if (pair && (!IsNumber(pair) || !IsValidRangeResId(atoi(pair)))) {
553         SOC_PERF_LOGE("Invalid resource pair for %{private}s", configFile.c_str());
554         return false;
555     }
556     if (mode && !IsNumber(mode)) {
557         SOC_PERF_LOGE("Invalid resource mode for %{private}s", configFile.c_str());
558         return false;
559     }
560     return CheckResourcePersistMode(persistMode, configFile);
561 }
562 
CheckResourcePersistMode(const char * persistMode,const std::string & configFile) const563 bool SocPerfConfig::CheckResourcePersistMode(const char* persistMode, const std::string& configFile) const
564 {
565     if (persistMode && (!IsNumber(persistMode) || !IsValidPersistMode(atoi(persistMode)))) {
566         SOC_PERF_LOGE("Invalid resource persistMode for %{private}s", configFile.c_str());
567         return false;
568     }
569     return true;
570 }
571 
CheckResourceTag(int32_t persistMode,const char * def,const char * path,const std::string & configFile) const572 bool SocPerfConfig::CheckResourceTag(int32_t persistMode, const char* def,
573     const char* path, const std::string& configFile) const
574 {
575     if (!def || !IsNumber(def)) {
576         SOC_PERF_LOGE("Invalid resource default for %{private}s", configFile.c_str());
577         return false;
578     }
579     if (persistMode != REPORT_TO_PERFSO && !path) {
580         SOC_PERF_LOGE("Invalid resource path for %{private}s", configFile.c_str());
581         return false;
582     }
583     return true;
584 }
585 
LoadResourceAvailable(std::shared_ptr<ResNode> resNode,const char * node)586 bool SocPerfConfig::LoadResourceAvailable(std::shared_ptr<ResNode> resNode, const char* node)
587 {
588     std::string nodeStr = node;
589     std::vector<std::string> result = Split(nodeStr, SPLIT_SPACE);
590     for (auto str : result) {
591         if (IsNumber(str)) {
592             resNode->available.insert(stoll(str));
593         } else {
594             return false;
595         }
596     }
597     return true;
598 }
599 
CheckPairResIdValid() const600 bool SocPerfConfig::CheckPairResIdValid() const
601 {
602     for (auto iter = resourceNodeInfo_.begin(); iter != resourceNodeInfo_.end(); ++iter) {
603         if (iter->second->isGov) {
604             continue;
605         }
606         int32_t resId = iter->first;
607         std::shared_ptr<ResNode> resNode = std::static_pointer_cast<ResNode>(iter->second);
608         int32_t pairResId = resNode->pair;
609         if (pairResId != INVALID_VALUE && resourceNodeInfo_.find(pairResId) == resourceNodeInfo_.end()) {
610             SOC_PERF_LOGE("resId[%{public}d]'s pairResId[%{public}d] is not valid", resId, pairResId);
611             return false;
612         }
613     }
614     return true;
615 }
616 
CheckDefValid() const617 bool SocPerfConfig::CheckDefValid() const
618 {
619     for (auto iter = resourceNodeInfo_.begin(); iter != resourceNodeInfo_.end(); ++iter) {
620         int32_t resId = iter->first;
621         std::shared_ptr<ResourceNode> resourceNode = iter->second;
622         int64_t def = resourceNode->def;
623         if (!resourceNode->available.empty() && resourceNode->available.find(def) == resourceNode->available.end()) {
624             SOC_PERF_LOGE("resId[%{public}d]'s def[%{public}lld] is not valid", resId, (long long)def);
625             return false;
626         }
627     }
628     return true;
629 }
630 
CheckGovResourceTag(const char * id,const char * name,const char * persistMode,const std::string & configFile) const631 bool SocPerfConfig::CheckGovResourceTag(const char* id, const char* name,
632     const char* persistMode, const std::string& configFile) const
633 {
634     if (!id || !IsNumber(id) || !IsValidRangeResId(atoi(id))) {
635         SOC_PERF_LOGE("Invalid governor resource id for %{private}s", configFile.c_str());
636         return false;
637     }
638     if (!name) {
639         SOC_PERF_LOGE("Invalid governor resource name for %{private}s", configFile.c_str());
640         return false;
641     }
642     if (persistMode && (!IsNumber(persistMode) || !IsValidPersistMode(atoi(persistMode)))) {
643         SOC_PERF_LOGE("Invalid governor resource persistMode for %{private}s", configFile.c_str());
644         return false;
645     }
646     return true;
647 }
648 
LoadGovResourceAvailable(std::shared_ptr<GovResNode> govResNode,const char * level,const char * node)649 bool SocPerfConfig::LoadGovResourceAvailable(std::shared_ptr<GovResNode> govResNode,
650     const char* level, const char* node)
651 {
652     govResNode->available.insert(atoll(level));
653     std::string nodeStr = node;
654     std::vector<std::string> result = Split(nodeStr, SPLIT_OR);
655     if (result.size() != govResNode->paths.size()) {
656         SOC_PERF_LOGE("Invalid governor resource node matches paths");
657         return false;
658     }
659     std::unique_lock<std::mutex> levelMutex(govResNode->levelToStrMutex_);
660     govResNode->levelToStr.insert(std::pair<int32_t, std::vector<std::string>>(atoll(level), result));
661     levelMutex.unlock();
662     return true;
663 }
664 
CheckCmdTag(const char * id,const char * name,const std::string & configFile) const665 bool SocPerfConfig::CheckCmdTag(const char* id, const char* name, const std::string& configFile) const
666 {
667     if (!id || !IsNumber(id)) {
668         SOC_PERF_LOGE("Invalid cmd id for %{private}s", configFile.c_str());
669         return false;
670     }
671     if (!name) {
672         SOC_PERF_LOGE("Invalid cmd name for %{private}s", configFile.c_str());
673         return false;
674     }
675     return true;
676 }
677 
TraversalActions(std::shared_ptr<Action> action,int32_t actionId)678 bool SocPerfConfig::TraversalActions(std::shared_ptr<Action> action, int32_t actionId)
679 {
680     for (int32_t i = 0; i < (int32_t)action->variable.size() - 1; i += RES_ID_AND_VALUE_PAIR) {
681         int32_t resId = action->variable[i];
682         int64_t resValue = action->variable[i + 1];
683         if (resourceNodeInfo_.find(resId) != resourceNodeInfo_.end()) {
684             if (resourceNodeInfo_[resId]->persistMode != REPORT_TO_PERFSO &&
685                 !resourceNodeInfo_[resId]->available.empty() &&
686                 resourceNodeInfo_[resId]->available.find(resValue) == resourceNodeInfo_[resId]->available.end()) {
687                 SOC_PERF_LOGE("action[%{public}d]'s resValue[%{public}lld] is not valid",
688                     actionId, (long long)resValue);
689                 return false;
690             }
691         } else {
692             SOC_PERF_LOGE("action[%{public}d]'s resId[%{public}d] is not valid", actionId, resId);
693             return false;
694         }
695     }
696     return true;
697 }
698 
CheckActionResIdAndValueValid(const std::string & configFile)699 bool SocPerfConfig::CheckActionResIdAndValueValid(const std::string& configFile)
700 {
701     std::unordered_map<int32_t, std::shared_ptr<Actions>> actionsInfo = perfActionsInfo_;
702     for (auto actionsIter = actionsInfo.begin(); actionsIter != actionsInfo.end(); ++actionsIter) {
703         int32_t actionId = actionsIter->first;
704         std::shared_ptr<Actions> actions = actionsIter->second;
705         for (auto actionIter = actions->actionList.begin(); actionIter != actions->actionList.end(); ++actionIter) {
706             bool ret = TraversalActions(*actionIter, actionId);
707             if (!ret) {
708                 return false;
709             }
710         }
711     }
712     return true;
713 }
714 } // namespace SOCPERF
715 } // namespace OHOS
716