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