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