• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2023 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 
16 
17 #include "socperf.h"
18 
19 #ifdef CUSTOMIZATION_CONFIG_POLICY_ENABLE
20 #include "config_policy_utils.h"
21 #endif // CUSTOMIZATION_CONFIG_POLICY_ENABLE
22 
23 #include "hitrace_meter.h"
24 
25 namespace OHOS {
26 namespace SOCPERF {
SocPerf()27 SocPerf::SocPerf()
28 {
29 }
30 
~SocPerf()31 SocPerf::~SocPerf()
32 {
33 }
34 
Init()35 bool SocPerf::Init()
36 {
37 #ifdef CUSTOMIZATION_CONFIG_POLICY_ENABLE
38     if (!LoadConfigXmlFile(SOCPERF_RESOURCE_CONFIG_XML)) {
39         SOC_PERF_LOGE("Failed to load %{public}s", SOCPERF_RESOURCE_CONFIG_XML.c_str());
40         return false;
41     }
42 
43     if (!LoadConfigXmlFile(SOCPERF_BOOST_CONFIG_XML)) {
44         SOC_PERF_LOGE("Failed to load %{public}s", SOCPERF_BOOST_CONFIG_XML.c_str());
45         return false;
46     }
47 #endif // CUSTOMIZATION_CONFIG_POLICY_ENABLE
48 
49     PrintCachedInfo();
50 
51     if (!CreateHandlers()) {
52         SOC_PERF_LOGE("Failed to create handler threads");
53         return false;
54     }
55 
56     InitHandlerThreads();
57 
58     resNodeInfo.clear();
59     govResNodeInfo.clear();
60     resStrToIdInfo.clear();
61     limitRequest = std::vector<std::unordered_map<int32_t, int32_t>>(ACTION_TYPE_MAX);
62 
63     enabled = true;
64 
65     SOC_PERF_LOGD("SocPerf Init SUCCESS!");
66 
67     return true;
68 }
69 
PerfRequest(int32_t cmdId,const std::string & msg)70 void SocPerf::PerfRequest(int32_t cmdId, const std::string& msg)
71 {
72     if (!enabled) {
73         SOC_PERF_LOGE("SocPerf disabled!");
74         return;
75     }
76     if (perfActionsInfo.find(cmdId) == perfActionsInfo.end()) {
77         SOC_PERF_LOGE("Invalid PerfRequest cmdId[%{public}d]", cmdId);
78         return;
79     }
80     SOC_PERF_LOGD("cmdId[%{public}d]msg[%{public}s]", cmdId, msg.c_str());
81 
82     std::string trace_str(__func__);
83     trace_str.append(",cmdId[").append(std::to_string(cmdId)).append("]");
84     trace_str.append(",msg[").append(msg).append("]");
85     StartTrace(HITRACE_TAG_OHOS, trace_str, -1);
86     DoFreqActions(perfActionsInfo[cmdId], EVENT_INVALID, ACTION_TYPE_PERF);
87     FinishTrace(HITRACE_TAG_OHOS);
88 }
89 
PerfRequestEx(int32_t cmdId,bool onOffTag,const std::string & msg)90 void SocPerf::PerfRequestEx(int32_t cmdId, bool onOffTag, const std::string& msg)
91 {
92     if (!enabled) {
93         SOC_PERF_LOGE("SocPerf disabled!");
94         return;
95     }
96     if (perfActionsInfo.find(cmdId) == perfActionsInfo.end()) {
97         SOC_PERF_LOGE("Invalid PerfRequestEx cmdId[%{public}d]", cmdId);
98         return;
99     }
100     SOC_PERF_LOGD("cmdId[%{public}d]onOffTag[%{public}d]msg[%{public}s]",
101         cmdId, onOffTag, msg.c_str());
102 
103     std::string trace_str(__func__);
104     trace_str.append(",cmdId[").append(std::to_string(cmdId)).append("]");
105     trace_str.append(",onOff[").append(std::to_string(onOffTag)).append("]");
106     trace_str.append(",msg[").append(msg).append("]");
107     StartTrace(HITRACE_TAG_OHOS, trace_str, -1);
108     DoFreqActions(perfActionsInfo[cmdId], onOffTag ? EVENT_ON : EVENT_OFF, ACTION_TYPE_PERF);
109     FinishTrace(HITRACE_TAG_OHOS);
110 }
111 
PowerLimitBoost(bool onOffTag,const std::string & msg)112 void SocPerf::PowerLimitBoost(bool onOffTag, const std::string& msg)
113 {
114     if (!enabled) {
115         SOC_PERF_LOGE("SocPerf disabled!");
116         return;
117     }
118     SOC_PERF_LOGD("onOffTag[%{public}d]msg[%{public}s]", onOffTag, msg.c_str());
119 
120     std::string trace_str(__func__);
121     trace_str.append(",onOff[").append(std::to_string(onOffTag)).append("]");
122     trace_str.append(",msg[").append(msg).append("]");
123     StartTrace(HITRACE_TAG_OHOS, trace_str, -1);
124     for (auto handler : handlers) {
125         if (handler) {
126             auto event = AppExecFwk::InnerEvent::Get(INNER_EVENT_ID_POWER_LIMIT_BOOST_FREQ, onOffTag ? 1 : 0);
127             handler->SendEvent(event);
128         }
129     }
130     FinishTrace(HITRACE_TAG_OHOS);
131 }
132 
ThermalLimitBoost(bool onOffTag,const std::string & msg)133 void SocPerf::ThermalLimitBoost(bool onOffTag, const std::string& msg)
134 {
135     if (!enabled) {
136         SOC_PERF_LOGE("SocPerf disabled!");
137         return;
138     }
139     SOC_PERF_LOGD("onOffTag[%{public}d]msg[%{public}s]", onOffTag, msg.c_str());
140     std::string trace_str(__func__);
141     trace_str.append(",onOff[").append(std::to_string(onOffTag)).append("]");
142     trace_str.append(",msg[").append(msg).append("]");
143     StartTrace(HITRACE_TAG_OHOS, trace_str, -1);
144     for (auto handler : handlers) {
145         if (handler) {
146             auto event = AppExecFwk::InnerEvent::Get(INNER_EVENT_ID_THERMAL_LIMIT_BOOST_FREQ, onOffTag ? 1 : 0);
147             handler->SendEvent(event);
148         }
149     }
150     FinishTrace(HITRACE_TAG_OHOS);
151 }
152 
SendLimitRequestEventOff(std::shared_ptr<SocPerfHandler> handler,int32_t clientId,int32_t resId,int32_t eventId)153 void SocPerf::SendLimitRequestEventOff(std::shared_ptr<SocPerfHandler> handler,
154     int32_t clientId, int32_t resId, int32_t eventId)
155 {
156     auto iter = limitRequest[clientId].find(resId);
157     if (iter != limitRequest[clientId].end()
158         && limitRequest[clientId][resId] != INVALID_VALUE) {
159         auto resAction = std::make_shared<ResAction>(
160             limitRequest[clientId][resId], 0, clientId, EVENT_OFF, -1);
161         auto event = AppExecFwk::InnerEvent::Get(eventId, resAction, resId);
162         handler->SendEvent(event);
163         limitRequest[clientId].erase(iter);
164     }
165 }
166 
SendLimitRequestEventOn(std::shared_ptr<SocPerfHandler> handler,int32_t clientId,int32_t resId,int64_t resValue,int32_t eventId)167 void SocPerf::SendLimitRequestEventOn(std::shared_ptr<SocPerfHandler> handler,
168     int32_t clientId, int32_t resId, int64_t resValue, int32_t eventId)
169 {
170     if (resValue != INVALID_VALUE && resValue != RESET_VALUE) {
171         auto resAction = std::make_shared<ResAction>(resValue, 0, clientId, EVENT_ON, -1);
172         auto event = AppExecFwk::InnerEvent::Get(eventId, resAction, resId);
173         handler->SendEvent(event);
174         limitRequest[clientId].insert(std::pair<int32_t, int32_t>(resId, resValue));
175     }
176 }
177 
SendLimitRequestEvent(int32_t clientId,int32_t resId,int64_t resValue)178 void SocPerf::SendLimitRequestEvent(int32_t clientId, int32_t resId, int64_t resValue)
179 {
180     int32_t eventId, realResId, levelResId;
181     if (resId > RES_ID_ADDITION) {
182         realResId = resId - RES_ID_ADDITION;
183         levelResId = resId;
184         eventId = INNER_EVENT_ID_DO_FREQ_ACTION_LEVEL;
185     } else {
186         realResId = resId;
187         levelResId = resId + RES_ID_ADDITION;
188         eventId = INNER_EVENT_ID_DO_FREQ_ACTION;
189     }
190 
191     auto handler = GetHandlerByResId(realResId);
192     if (!handler) {
193         return;
194     }
195     std::lock_guard<std::mutex> lock(mutex_);
196     SendLimitRequestEventOff(handler, clientId, realResId, INNER_EVENT_ID_DO_FREQ_ACTION);
197     SendLimitRequestEventOff(handler, clientId, levelResId, INNER_EVENT_ID_DO_FREQ_ACTION_LEVEL);
198     SendLimitRequestEventOn(handler, clientId, resId, resValue, eventId);
199 }
200 
LimitRequest(int32_t clientId,const std::vector<int32_t> & tags,const std::vector<int64_t> & configs,const std::string & msg)201 void SocPerf::LimitRequest(int32_t clientId,
202     const std::vector<int32_t>& tags, const std::vector<int64_t>& configs, const std::string& msg)
203 {
204     if (!enabled) {
205         SOC_PERF_LOGE("SocPerf disabled!");
206         return;
207     }
208     if (tags.size() != configs.size()) {
209         SOC_PERF_LOGE("tags'size and configs' size must be the same!");
210         return;
211     }
212     if (clientId <= (int32_t)ACTION_TYPE_PERF || clientId >= (int32_t)ACTION_TYPE_MAX) {
213         SOC_PERF_LOGE("clientId must be between ACTION_TYPE_PERF and ACTION_TYPE_MAX!");
214         return;
215     }
216     for (int32_t i = 0; i < (int32_t)tags.size(); i++) {
217         SOC_PERF_LOGD("clientId[%{public}d],tags[%{public}d],configs[%{public}lld],msg[%{public}s]",
218             clientId, tags[i], (long long)configs[i], msg.c_str());
219         SendLimitRequestEvent(clientId, tags[i], configs[i]);
220     }
221 }
222 
DoFreqActions(std::shared_ptr<Actions> actions,int32_t onOff,int32_t actionType)223 void SocPerf::DoFreqActions(std::shared_ptr<Actions> actions, int32_t onOff, int32_t actionType)
224 {
225     std::shared_ptr<ResActionItem> header[MAX_HANDLER_THREADS] = { nullptr };
226     std::shared_ptr<ResActionItem> curItem[MAX_HANDLER_THREADS] = { nullptr };
227     for (auto iter = actions->actionList.begin(); iter != actions->actionList.end(); iter++) {
228         std::shared_ptr<Action> action = *iter;
229         for (int32_t i = 0; i < (int32_t)action->variable.size() - 1; i += RES_ID_AND_VALUE_PAIR) {
230             if (!IsValidResId(action->variable[i])) {
231                 continue;
232             }
233             auto resActionItem = std::make_shared<ResActionItem>(action->variable[i]);
234             resActionItem->resAction =
235                 std::make_shared<ResAction>(action->variable[i + 1], action->duration, actionType, onOff, actions->id);
236             int32_t id = action->variable[i] / RES_ID_NUMS_PER_TYPE - 1;
237             if (curItem[id]) {
238                 curItem[id]->next = resActionItem;
239             } else {
240                 header[id] = resActionItem;
241             }
242             curItem[id] = resActionItem;
243         }
244     }
245     for (int32_t i = 0; i < MAX_HANDLER_THREADS; ++i) {
246         if (!handlers[i] || !header[i]) {
247             continue;
248         }
249         auto event = AppExecFwk::InnerEvent::Get(INNER_EVENT_ID_DO_FREQ_ACTION_PACK, header[i]);
250         handlers[i]->SendEvent(event);
251     }
252 }
253 
254 #ifdef CUSTOMIZATION_CONFIG_POLICY_ENABLE
GetRealConfigPath(const std::string configFile)255 std::string SocPerf::GetRealConfigPath(const std::string configFile)
256 {
257     char buf[PATH_MAX + 1];
258     char* configFilePath = GetOneCfgFile(configFile.c_str(), buf, PATH_MAX + 1);
259     char tmpPath[PATH_MAX + 1] = {0};
260     if (!configFilePath || strlen(configFilePath) == 0 || strlen(configFilePath) > PATH_MAX ||
261         !realpath(configFilePath, tmpPath)) {
262         SOC_PERF_LOGE("load %{public}s file fail", configFile.c_str());
263         return "";
264     }
265     return std::string(tmpPath);
266 }
267 #endif // CUSTOMIZATION_CONFIG_POLICY_ENABLE
268 
GetHandlerByResId(int32_t resId)269 std::shared_ptr<SocPerfHandler> SocPerf::GetHandlerByResId(int32_t resId)
270 {
271     if (!IsValidResId(resId)) {
272         return nullptr;
273     }
274     return handlers[resId / RES_ID_NUMS_PER_TYPE - 1];
275 }
276 
277 #ifdef CUSTOMIZATION_CONFIG_POLICY_ENABLE
LoadConfigXmlFile(std::string configFile)278 bool SocPerf::LoadConfigXmlFile(std::string configFile)
279 {
280     std::string realConfigFile = GetRealConfigPath(configFile);
281     if (realConfigFile.size() <= 0) {
282         return false;
283     }
284     xmlKeepBlanksDefault(0);
285     xmlDoc* file = xmlReadFile(realConfigFile.c_str(), nullptr, XML_PARSE_NOERROR | XML_PARSE_NOWARNING);
286     if (!file) {
287         SOC_PERF_LOGE("Failed to open xml file");
288         return false;
289     }
290     xmlNode* rootNode = xmlDocGetRootElement(file);
291     if (!rootNode) {
292         SOC_PERF_LOGE("Failed to get xml file's RootNode");
293         xmlFreeDoc(file);
294         return false;
295     }
296     if (!xmlStrcmp(rootNode->name, reinterpret_cast<const xmlChar*>("Configs"))) {
297         if (realConfigFile.find(SOCPERF_RESOURCE_CONFIG_XML) != std::string::npos) {
298             xmlNode* child = rootNode->children;
299             for (; child; child = child->next) {
300                 if (!xmlStrcmp(child->name, reinterpret_cast<const xmlChar*>("Resource"))) {
301                     if (!LoadResource(child, realConfigFile)) {
302                         xmlFreeDoc(file);
303                         return false;
304                     }
305                 } else if (!xmlStrcmp(child->name, reinterpret_cast<const xmlChar*>("GovResource"))) {
306                     if (!LoadGovResource(child, realConfigFile)) {
307                         xmlFreeDoc(file);
308                         return false;
309                     }
310                 }
311             }
312         } else {
313             if (!LoadCmd(rootNode, realConfigFile)) {
314                 xmlFreeDoc(file);
315                 return false;
316             }
317         }
318     } else {
319         SOC_PERF_LOGE("Wrong format for xml file");
320         xmlFreeDoc(file);
321         return false;
322     }
323     xmlFreeDoc(file);
324     SOC_PERF_LOGD("Success to Load %{public}s", configFile.c_str());
325     return true;
326 }
327 #endif // CUSTOMIZATION_CONFIG_POLICY_ENABLE
328 
CreateHandlers()329 bool SocPerf::CreateHandlers()
330 {
331     handlers = std::vector<std::shared_ptr<SocPerfHandler>>(MAX_HANDLER_THREADS);
332     std::string threadName = "socperf#";
333     for (int32_t i = 0; i < (int32_t)handlers.size(); i++) {
334         if (!handlerSwitch[i]) {
335             handlers[i] = nullptr;
336             continue;
337         }
338         auto runner = AppExecFwk::EventRunner::Create(threadName + std::to_string(i));
339         if (!runner) {
340             SOC_PERF_LOGE("Failed to Create EventRunner");
341             return false;
342         }
343         handlers[i] = std::make_shared<SocPerfHandler>(runner);
344     }
345     SOC_PERF_LOGD("Success to Create All Handler threads");
346     return true;
347 }
348 
InitHandlerThreads()349 void SocPerf::InitHandlerThreads()
350 {
351     for (auto iter = resNodeInfo.begin(); iter != resNodeInfo.end(); ++iter) {
352         std::shared_ptr<ResNode> resNode = iter->second;
353         auto handler = GetHandlerByResId(resNode->id);
354         if (!handler) {
355             continue;
356         }
357         auto event = AppExecFwk::InnerEvent::Get(INNER_EVENT_ID_INIT_RES_NODE_INFO, resNode);
358         handler->SendEvent(event);
359     }
360     for (auto iter = govResNodeInfo.begin(); iter != govResNodeInfo.end(); ++iter) {
361         std::shared_ptr<GovResNode> govResNode = iter->second;
362         auto handler = GetHandlerByResId(govResNode->id);
363         if (!handler) {
364             continue;
365         }
366         auto event = AppExecFwk::InnerEvent::Get(INNER_EVENT_ID_INIT_GOV_RES_NODE_INFO, govResNode);
367         handler->SendEvent(event);
368     }
369 }
370 
LoadResource(xmlNode * child,std::string configFile)371 bool SocPerf::LoadResource(xmlNode* child, std::string configFile)
372 {
373     xmlNode* grandson = child->children;
374     for (; grandson; grandson = grandson->next) {
375         if (!xmlStrcmp(grandson->name, reinterpret_cast<const xmlChar*>("res"))) {
376             char* id = reinterpret_cast<char*>(xmlGetProp(grandson, reinterpret_cast<const xmlChar*>("id")));
377             char* name = reinterpret_cast<char*>(xmlGetProp(grandson, reinterpret_cast<const xmlChar*>("name")));
378             char* pair = reinterpret_cast<char*>(xmlGetProp(grandson, reinterpret_cast<const xmlChar*>("pair")));
379             char* mode = reinterpret_cast<char*>(xmlGetProp(grandson, reinterpret_cast<const xmlChar*>("mode")));
380             if (!CheckResourceTag(id, name, pair, mode, configFile)) {
381                 xmlFree(id);
382                 xmlFree(name);
383                 xmlFree(pair);
384                 xmlFree(mode);
385                 return false;
386             }
387             xmlNode* greatGrandson = grandson->children;
388             std::shared_ptr<ResNode> resNode = std::make_shared<ResNode>(
389                 atoi(id), name, mode ? atoi(mode) : 0, pair ? atoi(pair) : INVALID_VALUE);
390             xmlFree(id);
391             xmlFree(name);
392             xmlFree(pair);
393             xmlFree(mode);
394             char *def = nullptr;
395             char *path  = nullptr;
396             char *node  = nullptr;
397             for (; greatGrandson; greatGrandson = greatGrandson->next) {
398                 if (!xmlStrcmp(greatGrandson->name, reinterpret_cast<const xmlChar*>("default"))) {
399                     xmlFree(def);
400                     def = reinterpret_cast<char*>(xmlNodeGetContent(greatGrandson));
401                 } else if (!xmlStrcmp(greatGrandson->name, reinterpret_cast<const xmlChar*>("path"))) {
402                     xmlFree(path);
403                     path = reinterpret_cast<char*>(xmlNodeGetContent(greatGrandson));
404                 } else if (!xmlStrcmp(greatGrandson->name, reinterpret_cast<const xmlChar*>("node"))) {
405                     xmlFree(node);
406                     node = reinterpret_cast<char*>(xmlNodeGetContent(greatGrandson));
407                 }
408             }
409             if (!CheckResourceTag(def, path, configFile)) {
410                 xmlFree(def);
411                 xmlFree(path);
412                 xmlFree(node);
413                 return false;
414             }
415             resNode->def = atoll(def);
416             resNode->path = path;
417             xmlFree(def);
418             xmlFree(path);
419             if (node && !LoadResourceAvailable(resNode, node)) {
420                 SOC_PERF_LOGE("Invalid resource node for %{public}s", configFile.c_str());
421                 xmlFree(node);
422                 return false;
423             }
424             xmlFree(node);
425 
426             resStrToIdInfo.insert(std::pair<std::string, int32_t>(resNode->name, resNode->id));
427             resNodeInfo.insert(std::pair<int32_t, std::shared_ptr<ResNode>>(resNode->id, resNode));
428             handlerSwitch[resNode->id / RES_ID_NUMS_PER_TYPE - 1] = true;
429         }
430     }
431 
432     if (!CheckPairResIdValid() || !CheckResDefValid()) {
433         return false;
434     }
435 
436     return true;
437 }
438 
LoadGovResource(xmlNode * child,std::string configFile)439 bool SocPerf::LoadGovResource(xmlNode* child, std::string configFile)
440 {
441     xmlNode* grandson = child->children;
442     for (; grandson; grandson = grandson->next) {
443         if (xmlStrcmp(grandson->name, reinterpret_cast<const xmlChar*>("res"))) {
444             continue;
445         }
446         char* id = reinterpret_cast<char*>(xmlGetProp(grandson, reinterpret_cast<const xmlChar*>("id")));
447         char* name = reinterpret_cast<char*>(xmlGetProp(grandson, reinterpret_cast<const xmlChar*>("name")));
448         if (!CheckGovResourceTag(id, name, configFile)) {
449             xmlFree(id);
450             xmlFree(name);
451             return false;
452         }
453         xmlNode* greatGrandson = grandson->children;
454         std::shared_ptr<GovResNode> govResNode = std::make_shared<GovResNode>(atoi(id), name);
455         xmlFree(id);
456         xmlFree(name);
457         handlerSwitch[govResNode->id / RES_ID_NUMS_PER_TYPE - 1] = true;
458         for (; greatGrandson; greatGrandson = greatGrandson->next) {
459             if (!xmlStrcmp(greatGrandson->name, reinterpret_cast<const xmlChar*>("default"))) {
460                 char* def = reinterpret_cast<char*>(xmlNodeGetContent(greatGrandson));
461                 if (!def || !IsNumber(def)) {
462                     SOC_PERF_LOGE("Invalid governor resource default for %{public}s", configFile.c_str());
463                     xmlFree(def);
464                     return false;
465                 }
466                 govResNode->def = atoll(def);
467                 xmlFree(def);
468             } else if (!xmlStrcmp(greatGrandson->name, reinterpret_cast<const xmlChar*>("path"))) {
469                 char* path = reinterpret_cast<char*>(xmlNodeGetContent(greatGrandson));
470                 if (!path) {
471                     SOC_PERF_LOGE("Invalid governor resource path for %{public}s", configFile.c_str());
472                     return false;
473                 }
474                 govResNode->paths.push_back(path);
475                 xmlFree(path);
476             } else if (!xmlStrcmp(greatGrandson->name, reinterpret_cast<const xmlChar*>("node"))) {
477                 char* level = reinterpret_cast<char*>(
478                     xmlGetProp(greatGrandson, reinterpret_cast<const xmlChar*>("level")));
479                 char* node = reinterpret_cast<char*>(xmlNodeGetContent(greatGrandson));
480                 if (!level || !IsNumber(level) || !node
481                     || !LoadGovResourceAvailable(govResNode, level, node)) {
482                     SOC_PERF_LOGE("Invalid governor resource node for %{public}s", configFile.c_str());
483                     xmlFree(level);
484                     xmlFree(node);
485                     return false;
486                 }
487                 xmlFree(level);
488                 xmlFree(node);
489             }
490         }
491 
492         resStrToIdInfo.insert(std::pair<std::string, int32_t>(govResNode->name, govResNode->id));
493         govResNodeInfo.insert(std::pair<int32_t, std::shared_ptr<GovResNode>>(govResNode->id, govResNode));
494     }
495 
496     if (!CheckGovResDefValid()) {
497         return false;
498     }
499 
500     return true;
501 }
502 
LoadCmd(xmlNode * rootNode,std::string configFile)503 bool SocPerf::LoadCmd(xmlNode* rootNode, std::string configFile)
504 {
505     xmlNode* child = rootNode->children;
506     for (; child; child = child->next) { // Iterate all cmdID
507         if (xmlStrcmp(child->name, reinterpret_cast<const xmlChar*>("cmd"))) {
508             continue;
509         }
510         char* id = reinterpret_cast<char*>(xmlGetProp(child, reinterpret_cast<const xmlChar*>("id")));
511         char* name = reinterpret_cast<char*>(xmlGetProp(child, reinterpret_cast<const xmlChar*>("name")));
512         if (!CheckCmdTag(id, name, configFile)) {
513             xmlFree(id);
514             xmlFree(name);
515             return false;
516         }
517         xmlNode* grandson = child->children;
518         std::shared_ptr<Actions> actions = std::make_shared<Actions>(atoi(id), name);
519         xmlFree(id);
520         xmlFree(name);
521         for (; grandson; grandson = grandson->next) { // Iterate all Action
522             std::shared_ptr<Action> action = std::make_shared<Action>();
523             xmlNode* greatGrandson = grandson->children;
524             for (; greatGrandson; greatGrandson = greatGrandson->next) { // Iterate duration and all res
525                 if (!xmlStrcmp(greatGrandson->name, reinterpret_cast<const xmlChar*>("duration"))) {
526                     char* duration = reinterpret_cast<char*>(xmlNodeGetContent(greatGrandson));
527                     if (!duration || !IsNumber(duration)) {
528                         SOC_PERF_LOGE("Invalid cmd duration for %{public}s", configFile.c_str());
529                         xmlFree(duration);
530                         return false;
531                     }
532                     action->duration = atoi(duration);
533                     xmlFree(duration);
534                 } else {
535                     char* resStr = reinterpret_cast<char*>(const_cast<xmlChar*>(greatGrandson->name));
536                     char* resValue = reinterpret_cast<char*>(xmlNodeGetContent(greatGrandson));
537                     if (!resStr || resStrToIdInfo.find(resStr) == resStrToIdInfo.end()
538                         || !resValue || !IsNumber(resValue)) {
539                         SOC_PERF_LOGE("Invalid cmd resource(%{public}s) for %{public}s", resStr, configFile.c_str());
540                         xmlFree(resValue);
541                         return false;
542                     }
543                     action->variable.push_back(resStrToIdInfo[resStr]);
544                     action->variable.push_back(atoll(resValue));
545                     xmlFree(resValue);
546                 }
547             }
548             actions->actionList.push_back(action);
549         }
550 
551         if (configFile.find(SOCPERF_BOOST_CONFIG_XML) != std::string::npos) {
552             perfActionsInfo.insert(std::pair<int32_t, std::shared_ptr<Actions>>(actions->id, actions));
553         }
554     }
555 
556     if (!CheckActionResIdAndValueValid(configFile)) {
557         return false;
558     }
559 
560     return true;
561 }
562 
CheckResourceTag(char * id,char * name,char * pair,char * mode,std::string configFile)563 bool SocPerf::CheckResourceTag(char* id, char* name, char* pair, char* mode, std::string configFile)
564 {
565     if (!id || !IsNumber(id) || !IsValidResId(atoi(id))) {
566         SOC_PERF_LOGE("Invalid resource id for %{public}s", configFile.c_str());
567         return false;
568     }
569     if (!name) {
570         SOC_PERF_LOGE("Invalid resource name for %{public}s", configFile.c_str());
571         return false;
572     }
573     if (pair && (!IsNumber(pair) || !IsValidResId(atoi(pair)))) {
574         SOC_PERF_LOGE("Invalid resource pair for %{public}s", configFile.c_str());
575         return false;
576     }
577     if (mode && !IsNumber(mode)) {
578         SOC_PERF_LOGE("Invalid resource mode for %{public}s", configFile.c_str());
579         return false;
580     }
581     return true;
582 }
583 
CheckResourceTag(char * def,char * path,std::string configFile)584 bool SocPerf::CheckResourceTag(char* def, char* path, std::string configFile)
585 {
586     if (!def || !IsNumber(def)) {
587         SOC_PERF_LOGE("Invalid resource default for %{public}s", configFile.c_str());
588         return false;
589     }
590     if (!path) {
591         SOC_PERF_LOGE("Invalid resource path for %{public}s", configFile.c_str());
592         return false;
593     }
594     return true;
595 }
596 
LoadResourceAvailable(std::shared_ptr<ResNode> resNode,char * node)597 bool SocPerf::LoadResourceAvailable(std::shared_ptr<ResNode> resNode, char* node)
598 {
599     std::string nodeStr = node;
600     std::vector<std::string> result = Split(nodeStr, " ");
601     for (auto str : result) {
602         if (IsNumber(str)) {
603             resNode->available.insert(stoll(str));
604         } else {
605             return false;
606         }
607     }
608     return true;
609 }
610 
CheckPairResIdValid()611 bool SocPerf::CheckPairResIdValid()
612 {
613     for (auto iter = resNodeInfo.begin(); iter != resNodeInfo.end(); ++iter) {
614         int32_t resId = iter->first;
615         std::shared_ptr<ResNode> resNode = iter->second;
616         int32_t pairResId = resNode->pair;
617         if (pairResId != INVALID_VALUE && resNodeInfo.find(pairResId) == resNodeInfo.end()) {
618             SOC_PERF_LOGE("resId[%{public}d]'s pairResId[%{public}d] is not valid", resId, pairResId);
619             return false;
620         }
621     }
622     return true;
623 }
624 
CheckResDefValid()625 bool SocPerf::CheckResDefValid()
626 {
627     for (auto iter = resNodeInfo.begin(); iter != resNodeInfo.end(); ++iter) {
628         int32_t resId = iter->first;
629         std::shared_ptr<ResNode> resNode = iter->second;
630         int64_t def = resNode->def;
631         if (!resNode->available.empty() && resNode->available.find(def) == resNode->available.end()) {
632             SOC_PERF_LOGE("resId[%{public}d]'s def[%{public}lld] is not valid", resId, (long long)def);
633             return false;
634         }
635     }
636     return true;
637 }
638 
CheckGovResourceTag(char * id,char * name,std::string configFile)639 bool SocPerf::CheckGovResourceTag(char* id, char* name, std::string configFile)
640 {
641     if (!id || !IsNumber(id) || !IsValidResId(atoi(id))) {
642         SOC_PERF_LOGE("Invalid governor resource id for %{public}s", configFile.c_str());
643         return false;
644     }
645     if (!name) {
646         SOC_PERF_LOGE("Invalid governor resource name for %{public}s", configFile.c_str());
647         return false;
648     }
649     return true;
650 }
651 
LoadGovResourceAvailable(std::shared_ptr<GovResNode> govResNode,char * level,char * node)652 bool SocPerf::LoadGovResourceAvailable(std::shared_ptr<GovResNode> govResNode, char* level, char* node)
653 {
654     govResNode->available.insert(atoll(level));
655     std::string nodeStr = node;
656     std::vector<std::string> result = Split(nodeStr, "|");
657     if (result.size() != govResNode->paths.size()) {
658         SOC_PERF_LOGE("Invalid governor resource node matches paths");
659         return false;
660     }
661     govResNode->levelToStr.insert(std::pair<int32_t, std::vector<std::string>>(atoll(level), result));
662     return true;
663 }
664 
CheckGovResDefValid()665 bool SocPerf::CheckGovResDefValid()
666 {
667     for (auto iter = govResNodeInfo.begin(); iter != govResNodeInfo.end(); ++iter) {
668         int32_t govResId = iter->first;
669         std::shared_ptr<GovResNode> govResNode = iter->second;
670         int32_t def = govResNode->def;
671         if (govResNode->available.find(def) == govResNode->available.end()) {
672             SOC_PERF_LOGE("govResId[%{public}d]'s def[%{public}d] is not valid", govResId, def);
673             return false;
674         }
675     }
676     return true;
677 }
678 
CheckCmdTag(char * id,char * name,std::string configFile)679 bool SocPerf::CheckCmdTag(char* id, char* name, std::string configFile)
680 {
681     if (!id || !IsNumber(id)) {
682         SOC_PERF_LOGE("Invalid cmd id for %{public}s", configFile.c_str());
683         return false;
684     }
685     if (!name) {
686         SOC_PERF_LOGE("Invalid cmd name for %{public}s", configFile.c_str());
687         return false;
688     }
689     return true;
690 }
691 
CheckActionResIdAndValueValid(std::string configFile)692 bool SocPerf::CheckActionResIdAndValueValid(std::string configFile)
693 {
694     std::unordered_map<int32_t, std::shared_ptr<Actions>> actionsInfo;
695     if (configFile.find(SOCPERF_BOOST_CONFIG_XML) != std::string::npos) {
696         actionsInfo = perfActionsInfo;
697     }
698     for (auto actionsIter = actionsInfo.begin(); actionsIter != actionsInfo.end(); ++actionsIter) {
699         int32_t actionId = actionsIter->first;
700         std::shared_ptr<Actions> actions = actionsIter->second;
701         for (auto actionIter = actions->actionList.begin(); actionIter != actions->actionList.end(); ++actionIter) {
702             std::shared_ptr<Action> action = *actionIter;
703             for (int32_t i = 0; i < (int32_t)action->variable.size() - 1; i += RES_ID_AND_VALUE_PAIR) {
704                 int32_t resId = action->variable[i];
705                 int64_t resValue = action->variable[i + 1];
706                 if (resNodeInfo.find(resId) != resNodeInfo.end()) {
707                     if (!resNodeInfo[resId]->available.empty()
708                         && resNodeInfo[resId]->available.find(resValue) == resNodeInfo[resId]->available.end()) {
709                         SOC_PERF_LOGE("action[%{public}d]'s resValue[%{public}lld] is not valid",
710                             actionId, (long long)resValue);
711                         return false;
712                     }
713                 } else if (govResNodeInfo.find(resId) != govResNodeInfo.end()) {
714                     if (govResNodeInfo[resId]->available.find(resValue) == govResNodeInfo[resId]->available.end()) {
715                         SOC_PERF_LOGE("action[%{public}d]'s resValue[%{public}lld] is not valid",
716                             actionId, (long long)resValue);
717                         return false;
718                     }
719                 } else {
720                     SOC_PERF_LOGE("action[%{public}d]'s resId[%{public}d] is not valid", actionId, resId);
721                     return false;
722                 }
723             }
724         }
725     }
726     return true;
727 }
728 
PrintCachedInfo()729 void SocPerf::PrintCachedInfo()
730 {
731     SOC_PERF_LOGD("------------------------------------");
732     SOC_PERF_LOGD("resNodeInfo(%{public}d)", (int32_t)resNodeInfo.size());
733     for (auto iter = resNodeInfo.begin(); iter != resNodeInfo.end(); ++iter) {
734         std::shared_ptr<ResNode> resNode = iter->second;
735         resNode->PrintString();
736     }
737     SOC_PERF_LOGD("------------------------------------");
738     SOC_PERF_LOGD("govResNodeInfo(%{public}d)", (int32_t)govResNodeInfo.size());
739     for (auto iter = govResNodeInfo.begin(); iter != govResNodeInfo.end(); ++iter) {
740         std::shared_ptr<GovResNode> govResNode = iter->second;
741         govResNode->PrintString();
742     }
743     SOC_PERF_LOGD("------------------------------------");
744     SOC_PERF_LOGD("perfActionsInfo(%{public}d)", (int32_t)perfActionsInfo.size());
745     for (auto iter = perfActionsInfo.begin(); iter != perfActionsInfo.end(); ++iter) {
746         std::shared_ptr<Actions> actions = iter->second;
747         actions->PrintString();
748     }
749     SOC_PERF_LOGD("------------------------------------");
750 }
751 } // namespace SOCPERF
752 } // namespace OHOS
753