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 (!LoadConfig(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
LoadConfig(const xmlNode * rootNode,const std::string & configFile)581 bool SocPerfConfig::LoadConfig(const xmlNode* rootNode, const std::string& configFile)
582 {
583 bool configTag = IsConfigTag(rootNode);
584 xmlNode* configNode = rootNode->children;
585 if (configTag) {
586 if (!HandleConfigNode(configNode, configFile)) {
587 return false;
588 }
589 } else {
590 if (!LoadConfigInfo(rootNode, configFile, DEFAULT_CONFIG_MODE)) {
591 return false;
592 }
593 }
594
595 if (!CheckActionResIdAndValueValid(configFile)) {
596 return false;
597 }
598
599 return true;
600 }
601
HandleConfigNode(const xmlNode * configNode,const std::string & configFile)602 bool SocPerfConfig::HandleConfigNode(const xmlNode* configNode, const std::string& configFile)
603 {
604 for (; configNode; configNode = configNode->next) { // Iterate all Config
605 if (!xmlStrcmp(configNode->name, reinterpret_cast<const xmlChar*>("Config"))) {
606 std::string configMode = GetConfigMode(configNode);
607 if (configMode.empty()) {
608 configMode = DEFAULT_CONFIG_MODE;
609 }
610 if (!LoadConfigInfo(configNode, configFile, configMode)) {
611 return false;
612 }
613 }
614 }
615 return true;
616 }
617
GetConfigMode(const xmlNode * node)618 std::string SocPerfConfig::GetConfigMode(const xmlNode* node)
619 {
620 const xmlChar* configModeXml = xmlGetProp(node, reinterpret_cast<const xmlChar*>("mode"));
621 if (configModeXml == nullptr) {
622 return "";
623 }
624 char* configMode = reinterpret_cast<char*>(const_cast<xmlChar*>(configModeXml));
625 std::string configModeStr(configMode);
626 xmlFree(configMode);
627 return configModeStr;
628 }
629
IsConfigTag(const xmlNode * rootNode)630 bool SocPerfConfig::IsConfigTag(const xmlNode* rootNode)
631 {
632 xmlNode* child = rootNode->children;
633 for (; child; child = child->next) {
634 if (!xmlStrcmp(child->name, reinterpret_cast<const xmlChar*>("Config"))) {
635 return true;
636 }
637 }
638 return false;
639 }
640
LoadConfigInfo(const xmlNode * configNode,const std::string & configFile,const std::string & configMode)641 bool SocPerfConfig::LoadConfigInfo(const xmlNode* configNode, const std::string& configFile,
642 const std::string& configMode)
643 {
644 xmlNode* child = configNode->children;
645 for (; child; child = child->next) { // Iterate all cmdID
646 if (!xmlStrcmp(child->name, reinterpret_cast<const xmlChar*>("cmd"))) {
647 if (!LoadCmdInfo(child, configFile, configMode)) {
648 return false;
649 }
650 } else if (!xmlStrcmp(child->name, reinterpret_cast<const xmlChar*>("interaction"))) {
651 LoadInterAction(child, configFile);
652 }
653 }
654 return true;
655 }
656
LoadCmdInfo(const xmlNode * child,const std::string & configFile,const std::string & configMode)657 bool SocPerfConfig::LoadCmdInfo(const xmlNode* child, const std::string& configFile, const std::string& configMode)
658 {
659 char* id = reinterpret_cast<char*>(xmlGetProp(child, reinterpret_cast<const xmlChar*>("id")));
660 char* name = reinterpret_cast<char*>(xmlGetProp(child, reinterpret_cast<const xmlChar*>("name")));
661 if (!CheckCmdTag(id, name, configFile)) {
662 xmlFree(id);
663 xmlFree(name);
664 return false;
665 }
666
667 auto config = configPerfActionsInfo_.find(configMode);
668 std::unordered_map<int32_t, std::shared_ptr<Actions>> perfActionsInfo = {};
669 if (config != configPerfActionsInfo_.end()) {
670 perfActionsInfo = config->second;
671 }
672
673 auto it = perfActionsInfo.find(atoi(id));
674 if (it != perfActionsInfo.end()) {
675 xmlFree(id);
676 xmlFree(name);
677 return true;
678 }
679
680 xmlNode* grandson = child->children;
681 std::shared_ptr<Actions> actions = std::make_shared<Actions>(atoi(id), name);
682 xmlFree(id);
683 xmlFree(name);
684
685 char* interaction = reinterpret_cast<char*>(xmlGetProp(child, reinterpret_cast<const xmlChar*>("interaction")));
686 if (interaction) {
687 if (atoi(interaction) == 0) {
688 actions->interaction = false;
689 }
690 xmlFree(interaction);
691 }
692
693 char* mode = reinterpret_cast<char*>(xmlGetProp(child, reinterpret_cast<const xmlChar*>("mode")));
694 if (mode) {
695 if (configMode == DEFAULT_CONFIG_MODE) {
696 ParseModeCmd(mode, configFile, actions);
697 }
698 xmlFree(mode);
699 }
700
701 if (!TraversalBoostResource(grandson, configFile, actions)) {
702 return false;
703 }
704
705 std::unique_lock<std::mutex> lockPerfActions(perfActionsMutex_);
706 perfActionsInfo.insert(std::pair<int32_t, std::shared_ptr<Actions>>(actions->id, actions));
707 configPerfActionsInfo_[configMode] = perfActionsInfo;
708 lockPerfActions.unlock();
709 return true;
710 }
711
ParseModeCmd(const char * mode,const std::string & configFile,std::shared_ptr<Actions> actions)712 void SocPerfConfig::ParseModeCmd(const char* mode, const std::string& configFile, std::shared_ptr<Actions> actions)
713 {
714 if (!mode) {
715 return;
716 }
717
718 std::string modeStr = mode;
719 std::vector<std::string> modeListResult = Split(modeStr, SPLIT_OR);
720 for (auto pairStr : modeListResult) {
721 std::vector<std::string> itemPair = Split(pairStr, SPLIT_EQUAL);
722 if (itemPair.size() != RES_MODE_AND_ID_PAIR) {
723 SOC_PERF_LOGW("Invaild device mode pair for %{private}s", configFile.c_str());
724 continue;
725 }
726
727 std::string modeDeviceStr = itemPair[0];
728 std::string modeCmdIdStr = itemPair[RES_MODE_AND_ID_PAIR -1];
729 if (modeDeviceStr.empty() || !IsNumber(modeCmdIdStr)) {
730 SOC_PERF_LOGW("Invaild device mode name for %{private}s", configFile.c_str());
731 continue;
732 }
733
734 int32_t cmdId = atoi(modeCmdIdStr.c_str());
735 auto existMode = std::find_if(actions->modeMap.begin(), actions->modeMap.end(),
736 [&modeDeviceStr](const std::shared_ptr<ModeMap>& modeItem) {
737 return modeItem->mode == modeDeviceStr;
738 });
739 if (existMode != actions->modeMap.end()) {
740 (*existMode)->cmdId = cmdId;
741 } else {
742 std::shared_ptr<ModeMap> newMode = std::make_shared<ModeMap>(modeDeviceStr, cmdId);
743 actions->modeMap.push_back(newMode);
744 }
745 }
746 }
747
ParseDuration(xmlNode * greatGrandson,const std::string & configFile,std::shared_ptr<Action> action) const748 bool SocPerfConfig::ParseDuration(xmlNode *greatGrandson,
749 const std::string& configFile, std::shared_ptr<Action> action) const
750 {
751 if (xmlStrcmp(greatGrandson->name, reinterpret_cast<const xmlChar*>("duration"))) {
752 return true;
753 }
754 char* duration = reinterpret_cast<char*>(xmlNodeGetContent(greatGrandson));
755 if (!duration || !IsNumber(duration)) {
756 SOC_PERF_LOGE("Invalid cmd duration for %{private}s", configFile.c_str());
757 xmlFree(duration);
758 return false;
759 }
760 action->duration = atoi(duration);
761 xmlFree(duration);
762 return true;
763 }
764
ParseResValue(xmlNode * greatGrandson,const std::string & configFile,std::shared_ptr<Action> action)765 bool SocPerfConfig::ParseResValue(xmlNode* greatGrandson, const std::string& configFile, std::shared_ptr<Action> action)
766 {
767 if (!xmlStrcmp(greatGrandson->name, reinterpret_cast<const xmlChar*>("duration"))) {
768 return true;
769 }
770 char* resStr = reinterpret_cast<char*>(const_cast<xmlChar*>(greatGrandson->name));
771 char* resValue = reinterpret_cast<char*>(xmlNodeGetContent(greatGrandson));
772 if (!resStr || g_resStrToIdInfo.find(resStr) == g_resStrToIdInfo.end()
773 || !resValue || !IsNumber(resValue)) {
774 SOC_PERF_LOGE("Invalid cmd resource(%{public}s) for %{private}s", resStr, configFile.c_str());
775 xmlFree(resValue);
776 return false;
777 }
778 action->variable.push_back(g_resStrToIdInfo[resStr]);
779 action->variable.push_back(atoll(resValue));
780 xmlFree(resValue);
781 return true;
782 }
783
GetXmlIntProp(const xmlNode * xmlNode,const char * propName,int32_t def) const784 int32_t SocPerfConfig::GetXmlIntProp(const xmlNode* xmlNode, const char* propName, int32_t def) const
785 {
786 int ret = def;
787 char* propValue = reinterpret_cast<char*>(xmlGetProp(xmlNode, reinterpret_cast<const xmlChar*>(propName)));
788 if (propValue != nullptr && IsNumber(propValue)) {
789 ret = atoi(propValue);
790 }
791 if (propValue != nullptr) {
792 xmlFree(propValue);
793 }
794 return ret;
795 }
796
TraversalBoostResource(xmlNode * grandson,const std::string & configFile,std::shared_ptr<Actions> actions)797 bool SocPerfConfig::TraversalBoostResource(xmlNode* grandson,
798 const std::string& configFile, std::shared_ptr<Actions> actions)
799 {
800 for (; grandson; grandson = grandson->next) { // Iterate all Action
801 std::shared_ptr<Action> action = std::make_shared<Action>();
802 action->thermalLvl_ = GetXmlIntProp(grandson, "thermalLvl", INVALID_THERMAL_LVL);
803 if (action->thermalLvl_ != INVALID_THERMAL_LVL) {
804 if (minThermalLvl_ == INVALID_THERMAL_LVL || minThermalLvl_ > action->thermalLvl_) {
805 minThermalLvl_ = action->thermalLvl_;
806 }
807 }
808 action->thermalCmdId_ = GetXmlIntProp(grandson, "thermalCmdId", INVALID_THERMAL_CMD_ID);
809 xmlNode* greatGrandson = grandson->children;
810 for (; greatGrandson; greatGrandson = greatGrandson->next) { // Iterate duration and all res
811 bool ret = ParseDuration(greatGrandson, configFile, action);
812 if (!ret) {
813 return false;
814 }
815 if (action->duration == 0) {
816 actions->isLongTimePerf = true;
817 }
818 ret = ParseResValue(greatGrandson, configFile, action);
819 if (!ret) {
820 return false;
821 }
822 }
823 actions->actionList.push_back(action);
824 }
825 return true;
826 }
827
CheckResourceTag(const char * id,const char * name,const char * pair,const char * mode,const char * persistMode,const std::string & configFile) const828 bool SocPerfConfig::CheckResourceTag(const char* id, const char* name, const char* pair, const char* mode,
829 const char* persistMode, const std::string& configFile) const
830 {
831 if (!id || !IsNumber(id) || !IsValidRangeResId(atoi(id))) {
832 SOC_PERF_LOGE("Invalid resource id for %{private}s", configFile.c_str());
833 return false;
834 }
835 if (!name) {
836 SOC_PERF_LOGE("Invalid resource name for %{private}s", configFile.c_str());
837 return false;
838 }
839 if (pair && (!IsNumber(pair) || !IsValidRangeResId(atoi(pair)))) {
840 SOC_PERF_LOGE("Invalid resource pair for %{private}s", configFile.c_str());
841 return false;
842 }
843 if (mode && !IsNumber(mode)) {
844 SOC_PERF_LOGE("Invalid resource mode for %{private}s", configFile.c_str());
845 return false;
846 }
847 return CheckResourcePersistMode(persistMode, configFile);
848 }
849
CheckResourcePersistMode(const char * persistMode,const std::string & configFile) const850 bool SocPerfConfig::CheckResourcePersistMode(const char* persistMode, const std::string& configFile) const
851 {
852 if (persistMode && (!IsNumber(persistMode) || !IsValidPersistMode(atoi(persistMode)))) {
853 SOC_PERF_LOGE("Invalid resource persistMode for %{private}s", configFile.c_str());
854 return false;
855 }
856 return true;
857 }
858
CheckResourceTag(int32_t persistMode,const char * def,const char * path,const std::string & configFile) const859 bool SocPerfConfig::CheckResourceTag(int32_t persistMode, const char* def,
860 const char* path, const std::string& configFile) const
861 {
862 if (!def || !IsNumber(def)) {
863 SOC_PERF_LOGE("Invalid resource default for %{private}s", configFile.c_str());
864 return false;
865 }
866 if (persistMode != REPORT_TO_PERFSO && !path) {
867 SOC_PERF_LOGE("Invalid resource path for %{private}s", configFile.c_str());
868 return false;
869 }
870 return true;
871 }
872
LoadResourceAvailable(std::shared_ptr<ResNode> resNode,const char * node)873 bool SocPerfConfig::LoadResourceAvailable(std::shared_ptr<ResNode> resNode, const char* node)
874 {
875 std::string nodeStr = node;
876 std::vector<std::string> result = Split(nodeStr, SPLIT_SPACE);
877 for (auto str : result) {
878 if (IsNumber(str)) {
879 resNode->available.insert(atoll(str.c_str()));
880 } else {
881 return false;
882 }
883 }
884 return true;
885 }
886
CheckPairResIdValid() const887 bool SocPerfConfig::CheckPairResIdValid() const
888 {
889 for (auto iter = resourceNodeInfo_.begin(); iter != resourceNodeInfo_.end(); ++iter) {
890 if (iter->second->isGov) {
891 continue;
892 }
893 int32_t resId = iter->first;
894 std::shared_ptr<ResNode> resNode = std::static_pointer_cast<ResNode>(iter->second);
895 int32_t pairResId = resNode->pair;
896 if (pairResId != INVALID_VALUE && resourceNodeInfo_.find(pairResId) == resourceNodeInfo_.end()) {
897 SOC_PERF_LOGE("resId[%{public}d]'s pairResId[%{public}d] is not valid", resId, pairResId);
898 return false;
899 }
900 }
901 return true;
902 }
903
CheckDefValid() const904 bool SocPerfConfig::CheckDefValid() const
905 {
906 for (auto iter = resourceNodeInfo_.begin(); iter != resourceNodeInfo_.end(); ++iter) {
907 int32_t resId = iter->first;
908 std::shared_ptr<ResourceNode> resourceNode = iter->second;
909 int64_t def = resourceNode->def;
910 if (!resourceNode->available.empty() && resourceNode->available.find(def) == resourceNode->available.end()) {
911 SOC_PERF_LOGE("resId[%{public}d]'s def[%{public}lld] is not valid", resId, (long long)def);
912 return false;
913 }
914 }
915 return true;
916 }
917
CheckGovResourceTag(const char * id,const char * name,const char * persistMode,const std::string & configFile) const918 bool SocPerfConfig::CheckGovResourceTag(const char* id, const char* name,
919 const char* persistMode, const std::string& configFile) const
920 {
921 if (!id || !IsNumber(id) || !IsValidRangeResId(atoi(id))) {
922 SOC_PERF_LOGE("Invalid governor resource id for %{private}s", configFile.c_str());
923 return false;
924 }
925 if (!name) {
926 SOC_PERF_LOGE("Invalid governor resource name for %{private}s", configFile.c_str());
927 return false;
928 }
929 if (persistMode && (!IsNumber(persistMode) || !IsValidPersistMode(atoi(persistMode)))) {
930 SOC_PERF_LOGE("Invalid governor resource persistMode for %{private}s", configFile.c_str());
931 return false;
932 }
933 return true;
934 }
935
LoadGovResourceAvailable(std::shared_ptr<GovResNode> govResNode,const char * level,const char * node)936 bool SocPerfConfig::LoadGovResourceAvailable(std::shared_ptr<GovResNode> govResNode,
937 const char* level, const char* node)
938 {
939 govResNode->available.insert(atoll(level));
940 std::string nodeStr = node;
941 std::vector<std::string> result = Split(nodeStr, SPLIT_OR);
942 if (result.size() != govResNode->paths.size()) {
943 SOC_PERF_LOGE("Invalid governor resource node matches paths");
944 return false;
945 }
946 std::unique_lock<std::mutex> levelMutex(govResNode->levelToStrMutex_);
947 govResNode->levelToStr.insert(std::pair<int32_t, std::vector<std::string>>(atoll(level), result));
948 levelMutex.unlock();
949 return true;
950 }
951
CheckCmdTag(const char * id,const char * name,const std::string & configFile) const952 bool SocPerfConfig::CheckCmdTag(const char* id, const char* name, const std::string& configFile) const
953 {
954 if (!id || !IsNumber(id)) {
955 SOC_PERF_LOGE("Invalid cmd id for %{private}s", configFile.c_str());
956 return false;
957 }
958 if (!name) {
959 SOC_PERF_LOGE("Invalid cmd name for %{private}s", configFile.c_str());
960 return false;
961 }
962 return true;
963 }
964
TraversalActions(std::shared_ptr<Action> action,int32_t actionId)965 bool SocPerfConfig::TraversalActions(std::shared_ptr<Action> action, int32_t actionId)
966 {
967 for (int32_t i = 0; i < (int32_t)action->variable.size() - 1; i += RES_ID_AND_VALUE_PAIR) {
968 int32_t resId = action->variable[i];
969 int64_t resValue = action->variable[i + 1];
970 if (resourceNodeInfo_.find(resId) != resourceNodeInfo_.end()) {
971 if (resourceNodeInfo_[resId]->persistMode != REPORT_TO_PERFSO &&
972 !resourceNodeInfo_[resId]->available.empty() &&
973 resourceNodeInfo_[resId]->available.find(resValue) == resourceNodeInfo_[resId]->available.end()) {
974 SOC_PERF_LOGE("action[%{public}d]'s resValue[%{public}lld] is not valid",
975 actionId, (long long)resValue);
976 return false;
977 }
978 } else {
979 SOC_PERF_LOGE("action[%{public}d]'s resId[%{public}d] is not valid", actionId, resId);
980 return false;
981 }
982 }
983 return true;
984 }
985
CheckActionResIdAndValueValid(const std::string & configFile)986 bool SocPerfConfig::CheckActionResIdAndValueValid(const std::string& configFile)
987 {
988 std::unordered_map<std::string,
989 std::unordered_map<int32_t, std::shared_ptr<Actions>>> configs = configPerfActionsInfo_;
990 for (auto configsIter = configs.begin(); configsIter != configs.end(); ++configsIter) {
991 std::unordered_map<int32_t, std::shared_ptr<Actions>> actionsInfo = configsIter->second;
992 if (!CheckActionsValid(actionsInfo)) {
993 return false;
994 }
995 }
996 return true;
997 }
998
CheckActionsValid(std::unordered_map<int32_t,std::shared_ptr<Actions>> & actionsInfo)999 bool SocPerfConfig::CheckActionsValid(std::unordered_map<int32_t, std::shared_ptr<Actions>>& actionsInfo)
1000 {
1001 for (auto actionsIter = actionsInfo.begin(); actionsIter != actionsInfo.end(); ++actionsIter) {
1002 int32_t actionId = actionsIter->first;
1003 std::shared_ptr<Actions> actions = actionsIter->second;
1004 for (auto actionIter = actions->actionList.begin(); actionIter != actions->actionList.end(); ++actionIter) {
1005 bool ret = TraversalActions(*actionIter, actionId);
1006 if (!ret) {
1007 return false;
1008 }
1009 }
1010 }
1011 return true;
1012 }
1013 } // namespace SOCPERF
1014 } // namespace OHOS
1015