1 /*
2 * Copyright (C) 2021 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 <iostream>
16 #include <fstream>
17 #include <sstream>
18 #include <algorithm>
19 #include <unistd.h>
20 #include <dirent.h>
21 #include <cstdio>
22 #include <cstdlib>
23 #include <climits>
24 #include <cctype>
25 #include <climits>
26 #include <sys/utsname.h>
27 #include "sys/time.h"
28 #include "securec.h"
29 #include "include/sp_utils.h"
30 #include "include/sp_log.h"
31 #include "include/common.h"
32 #include "cpu_collector.h"
33 #include "collect_result.h"
34 #include "include/FPS.h"
35 #include "include/GPU.h"
36 #include "include/Power.h"
37 #include "include/DDR.h"
38 #include "include/profiler_fps.h"
39 #include "include/FileDescriptor.h"
40 #include "include/Threads.h"
41
42 using namespace OHOS::HiviewDFX;
43 using namespace OHOS::HiviewDFX::UCollectUtil;
44 using namespace OHOS::HiviewDFX::UCollect;
45
46 namespace OHOS {
47 namespace SmartPerf {
48 const unsigned int INT_MAX_LEN = 10;
49 const unsigned int CHAR_NUM_DIFF = 48;
50 const unsigned int UI_DECIMALISM = 10;
51 const unsigned int UI_INDEX_2 = 2;
52 const int BUFFER_SIZE = 1024;
53 const std::string SMART_PERF_VERSION = "1.0.6";
FileAccess(const std::string & fileName)54 bool SPUtils::FileAccess(const std::string &fileName)
55 {
56 return (access(fileName.c_str(), F_OK) == 0);
57 }
HasNumber(const std::string & str)58 bool SPUtils::HasNumber(const std::string &str)
59 {
60 return std::any_of(str.begin(), str.end(), [](char c) { return std::isdigit(c); });
61 }
Cmp(const std::string & a,const std::string & b)62 bool SPUtils::Cmp(const std::string &a, const std::string &b)
63 {
64 if (HasNumber(a) && HasNumber(b)) {
65 std::string stra = a.substr(0, a.find_first_of("0123456789"));
66 std::string strb = b.substr(0, b.find_first_of("0123456789"));
67 if (stra != strb) {
68 return stra < strb;
69 }
70 int numa = SPUtilesTye::StringToSometype<int>(a.substr(stra.length()));
71 int numb = SPUtilesTye::StringToSometype<int>(b.substr(strb.length()));
72 return numa < numb;
73 }
74 return false;
75 }
76
LoadFile(const std::string & filePath,std::string & content)77 bool SPUtils::LoadFile(const std::string &filePath, std::string &content)
78 {
79 char realPath[PATH_MAX] = {0x00};
80 if ((realpath(filePath.c_str(), realPath) == nullptr)) {
81 std::cout << "" << std::endl;
82 }
83 std::ifstream file(realPath);
84 if (!file.is_open()) {
85 return false;
86 }
87
88 file.seekg(0, std::ios::end);
89 file.tellg();
90
91 content.clear();
92 file.seekg(0, std::ios::beg);
93 copy(std::istreambuf_iterator<char>(file), std::istreambuf_iterator<char>(), std::back_inserter(content));
94 // remove '' \n\r
95 ReplaceString(content);
96 return true;
97 }
98
LoadCmdWithLinkBreak(const std::string & cmd,bool isClearLinkBreak,std::string & result)99 bool SPUtils::LoadCmdWithLinkBreak(const std::string &cmd, bool isClearLinkBreak, std::string &result)
100 {
101 const std::string cmdExc = cmd;
102 FILE *fd = popen(cmdExc.c_str(), "r");
103 if (fd == nullptr) {
104 return false;
105 }
106 char buf[4096] = {'\0'};
107 size_t ret = fread(buf, 1, sizeof(buf) - 1, fd);
108 if (ret >= 0) {
109 buf[ret] = '\0';
110 result = buf;
111 }
112 if (pclose(fd) == -1) {
113 LOGE("Error: Failed to close file");
114 return false;
115 }
116
117 if (isClearLinkBreak) {
118 // remove '' \n\r
119 ReplaceString(result);
120 }
121
122 return ret >= 0 ? true : false;
123 }
124
LoadCmd(const std::string & cmd,std::string & result)125 bool SPUtils::LoadCmd(const std::string &cmd, std::string &result)
126 {
127 return LoadCmdWithLinkBreak(cmd, true, result);
128 }
129
IncludePathDelimiter(const std::string & path)130 std::string SPUtils::IncludePathDelimiter(const std::string &path)
131 {
132 if (!path.empty() && path.back() != '/') {
133 return path + "/";
134 } else {
135 return path;
136 }
137 }
138
ForDirFiles(const std::string & path,std::vector<std::string> & files)139 void SPUtils::ForDirFiles(const std::string &path, std::vector<std::string> &files)
140 {
141 std::string pathStringWithDelimiter;
142 DIR *dir = opendir(path.c_str());
143 if (dir == nullptr) {
144 return;
145 }
146
147 while (true) {
148 struct dirent *ptr = readdir(dir);
149 if (ptr == nullptr) {
150 break;
151 }
152
153 // current dir OR parent dir
154 if ((strcmp(ptr->d_name, ".") == 0) || (strcmp(ptr->d_name, "..") == 0)) {
155 continue;
156 } else if (ptr->d_type == DT_DIR) {
157 pathStringWithDelimiter = IncludePathDelimiter(path) + std::string(ptr->d_name);
158 ForDirFiles(pathStringWithDelimiter, files);
159 } else {
160 files.push_back(IncludePathDelimiter(path) + std::string(ptr->d_name));
161 }
162 }
163 closedir(dir);
164 }
165
IsSubString(const std::string & str,const std::string & sub)166 bool SPUtils::IsSubString(const std::string &str, const std::string &sub)
167 {
168 if (sub.empty() || str.empty()) {
169 return false;
170 }
171 return str.find(sub) != std::string::npos;
172 }
173
StrSplit(const std::string & content,const std::string & sp,std::vector<std::string> & out)174 void SPUtils::StrSplit(const std::string &content, const std::string &sp, std::vector<std::string> &out)
175 {
176 size_t index = 0;
177 while (index != std::string::npos) {
178 size_t tEnd = content.find_first_of(sp, index);
179 std::string tmp = content.substr(index, tEnd - index);
180 if (tmp != "" && tmp != " ") {
181 out.push_back(tmp);
182 }
183 if (tEnd == std::string::npos) {
184 break;
185 }
186 index = tEnd + 1;
187 }
188 }
189
ExtractNumber(const std::string & str)190 std::string SPUtils::ExtractNumber(const std::string &str)
191 {
192 int cntInt = 0;
193 const int shift = 10;
194 for (int i = 0; str[i] != '\0'; ++i) {
195 if (str[i] >= '0' && str[i] <= '9') {
196 cntInt *= shift;
197 cntInt += str[i] - '0';
198 }
199 }
200 return std::to_string(cntInt);
201 }
202
ReplaceString(std::string & res)203 void SPUtils::ReplaceString(std::string &res)
204 {
205 std::string flagOne = "\r";
206 std::string flagTwo = "\n";
207 std::string::size_type ret = res.find(flagOne);
208 while (ret != res.npos) {
209 res.replace(ret, 1, "");
210 ret = res.find(flagOne);
211 }
212 ret = res.find(flagTwo);
213 while (ret != res.npos) {
214 res.replace(ret, 1, "");
215 ret = res.find(flagTwo);
216 }
217 }
218
GetCurTime()219 long long SPUtils::GetCurTime()
220 {
221 struct timeval tv;
222 gettimeofday(&tv, nullptr);
223 long long timestamp = tv.tv_sec * 1000 + tv.tv_usec / 1000;
224 return timestamp;
225 }
226
GetTopPkgName()227 std::string SPUtils::GetTopPkgName()
228 {
229 std::string cmd = HIDUMPER_CMD_MAP.at(HidumperCmd::DUMPER_HEAD);
230 std::string curTopPkgStr = "";
231 LoadCmd(cmd, curTopPkgStr);
232 uint64_t left = curTopPkgStr.find_first_of("[");
233 uint64_t right = curTopPkgStr.find_first_of("]");
234 std::string topPkg = curTopPkgStr.substr(left + 1, static_cast<int64_t>(right) - static_cast<int64_t>(left) - 1);
235 return topPkg;
236 }
237
GetRadar()238 std::string SPUtils::GetRadar()
239 {
240 std::string cmd = HISYSEVENT_CMD_MAP.at(HisyseventCmd::HISYS_APP_START);
241 std::string curRadar = "";
242 LoadCmd(cmd, curRadar);
243 return curRadar;
244 }
GetScreen()245 std::string SPUtils::GetScreen()
246 {
247 std::string cmd = HIDUMPER_CMD_MAP.at(HidumperCmd::DUMPER_SCREEN);
248 std::string screenStr = "";
249 FILE *fd = popen(cmd.c_str(), "r");
250 if (fd == nullptr) {
251 return screenStr;
252 }
253 char buf[4096] = {'\0'};
254 while ((fgets(buf, sizeof(buf), fd)) != nullptr) {
255 std::string line(buf);
256 if (line.find("activeMode") != std::string::npos) {
257 screenStr = line;
258 }
259 }
260 pclose(fd);
261 return screenStr;
262 }
GetRadarFrame()263 std::string SPUtils::GetRadarFrame()
264 {
265 std::string cmd = HISYSEVENT_CMD_MAP.at(HisyseventCmd::HISYS_JANK);
266 std::string curRadar = "";
267 LoadCmd(cmd, curRadar);
268 return curRadar;
269 }
GetRadarResponse()270 std::string SPUtils::GetRadarResponse()
271 {
272 std::string cmd = HISYSEVENT_CMD_MAP.at(HisyseventCmd::HISYS_RESPONSE);
273 std::string curRadar = "";
274 LoadCmd(cmd, curRadar);
275 return curRadar;
276 }
GetRadarComplete()277 std::string SPUtils::GetRadarComplete()
278 {
279 std::string cmd = HISYSEVENT_CMD_MAP.at(HisyseventCmd::HISYS_COMPLETED);
280 std::string curRadar = "";
281 LoadCmd(cmd, curRadar);
282 return curRadar;
283 }
GetSplitOne(std::string cmd)284 static std::string GetSplitOne(std::string cmd)
285 {
286 std::string result;
287 SPUtils::LoadCmd(cmd, result);
288 return result;
289 }
290
GetDeviceInfoMap()291 std::string SPUtils::GetDeviceInfoMap()
292 {
293 size_t len = 2;
294 bool isTcpMessage = false;
295 std::map<std::string, std::string> deviceInfoMap;
296 std::map<std::string, std::string> cpuInfo = GetCpuInfo(isTcpMessage);
297 std::map<std::string, std::string> gpuInfo = GetGpuInfo(isTcpMessage);
298 std::map<std::string, std::string> deviceInfo = GetDeviceInfo();
299 std::string screenInfos = GetScreen();
300 size_t pos = screenInfos.find(": ");
301 size_t pos1 = screenInfos.find(",");
302 std::string screenSize = screenInfos.substr(pos + len, pos1 - pos - len);
303 deviceInfoMap.insert(cpuInfo.begin(), cpuInfo.end());
304 deviceInfoMap.insert(gpuInfo.begin(), gpuInfo.end());
305 deviceInfoMap.insert(deviceInfo.begin(), deviceInfo.end());
306 deviceInfoMap["activeMode"] = screenSize;
307 if (deviceInfoMap.empty()) {
308 LOGE("Failed to obtain device information");
309 }
310 for (auto iter = deviceInfoMap.cbegin(); iter != deviceInfoMap.cend(); ++iter) {
311 printf("%s: %s\n", iter->first.c_str(), iter->second.c_str());
312 }
313 std::cout << "" << std::endl;
314 return std::string("command exec finished!");
315 }
316
GetDeviceInfo()317 std::map<std::string, std::string> SPUtils::GetDeviceInfo()
318 {
319 std::map<std::string, std::string> resultMap;
320 std::string sn = GetSplitOne(DEVICE_CMD_MAP.at(DeviceCmd::SN));
321 std::string deviceTypeName = GetSplitOne(DEVICE_CMD_MAP.at(DeviceCmd::DEVICET_NAME));
322 std::string brand = GetSplitOne(DEVICE_CMD_MAP.at(DeviceCmd::BRAND));
323 std::string version = GetSplitOne(DEVICE_CMD_MAP.at(DeviceCmd::VERSION));
324 std::string abilist = GetSplitOne(DEVICE_CMD_MAP.at(DeviceCmd::ABILIST));
325 std::string name = GetSplitOne(DEVICE_CMD_MAP.at(DeviceCmd::NAME));
326 std::string model = GetSplitOne(DEVICE_CMD_MAP.at(DeviceCmd::MODEL));
327 std::string fullname = GetSplitOne(DEVICE_CMD_MAP.at(DeviceCmd::FULL_NAME));
328 resultMap["sn"] = sn;
329 resultMap["deviceTypeName"] = deviceTypeName;
330 resultMap["brand"] = brand;
331 resultMap["board"] = "hw";
332 resultMap["version"] = version;
333 resultMap["abilist"] = abilist;
334 resultMap["name"] = name;
335 resultMap["model"] = model;
336 resultMap["fullname"] = fullname;
337 resultMap["daemonPerfVersion"] = SMART_PERF_VERSION;
338 return resultMap;
339 }
GetCpuInfo(bool isTcpMessage)340 std::map<std::string, std::string> SPUtils::GetCpuInfo(bool isTcpMessage)
341 {
342 std::string clusterNames;
343 std::vector<std::string> policyFiles;
344 std::map<std::string, std::string> resultMap;
345 std::string basePath = "/sys/devices/system/cpu/cpufreq/";
346 DIR *dir = opendir(basePath.c_str());
347 if (dir == nullptr) {
348 return resultMap;
349 }
350 while (true) {
351 struct dirent *ptr = readdir(dir);
352 if (ptr == nullptr) {
353 break;
354 }
355 if ((strcmp(ptr->d_name, ".") == 0) || (strcmp(ptr->d_name, "..") == 0)) {
356 continue;
357 }
358 std::string clusterName = std::string(ptr->d_name);
359 if (!isTcpMessage) {
360 clusterNames += clusterName + " ";
361 resultMap["cpu_cluster_name"] = clusterNames;
362 }
363 policyFiles.push_back(IncludePathDelimiter(basePath) + clusterName);
364 }
365 closedir(dir);
366 for (size_t i = 0; i < policyFiles.size(); i++) {
367 std::string cpus;
368 LoadFile(policyFiles[i] + "/affected_cpus", cpus);
369 std::string max;
370 LoadFile(policyFiles[i] + "/cpuinfo_max_freq", max);
371 std::string min;
372 LoadFile(policyFiles[i] + "/cpuinfo_min_freq", min);
373 std::string nameBase;
374 if (!isTcpMessage) {
375 nameBase = "cpu_c" + std::to_string(i + 1) + "_";
376 } else {
377 nameBase = "cpu-c" + std::to_string(i + 1) + "-";
378 }
379 resultMap[nameBase + "cluster"] = cpus;
380 resultMap[nameBase + "max"] = max;
381 resultMap[nameBase + "min"] = min;
382 }
383 return resultMap;
384 }
GetGpuInfo(bool isTcpMessage)385 std::map<std::string, std::string> SPUtils::GetGpuInfo(bool isTcpMessage)
386 {
387 const std::vector<std::string> gpuCurFreqPaths = {
388 "/sys/class/devfreq/fde60000.gpu/",
389 "/sys/class/devfreq/gpufreq/",
390 };
391 std::map<std::string, std::string> resultMap;
392 for (auto path : gpuCurFreqPaths) {
393 if (FileAccess(path)) {
394 std::string max;
395 SPUtils::LoadFile(path + "/max_freq", max);
396 std::string min;
397 SPUtils::LoadFile(path + "/min_freq", min);
398 resultMap["gpu_max_freq"] = max;
399 resultMap["gpu_min_freq"] = min;
400 }
401 }
402 return resultMap;
403 }
404
RemoveSpace(std::string & str)405 void SPUtils::RemoveSpace(std::string &str)
406 {
407 int len = 0;
408
409 for (size_t i = 0; i < str.length(); i++) {
410 if (str[i] != ' ') {
411 break;
412 }
413
414 ++len;
415 }
416
417 if (len > 0) {
418 str = str.substr(len);
419 }
420
421 len = 0;
422 for (size_t i = str.length(); i > 0; --i) {
423 if (str[i - 1] != ' ') {
424 break;
425 }
426
427 ++len;
428 }
429
430 if (len > 0) {
431 for (int i = 0; i < len; i++) {
432 str.pop_back();
433 }
434 }
435 }
436
437
IntegerVerification(std::string str,std::string errorInfo)438 bool SPUtils::IntegerVerification(std::string str, std::string errorInfo)
439 {
440 uint64_t dest = 0;
441 bool isValid = false;
442
443 if (str.empty()) {
444 errorInfo = "option requires an argument";
445 LOGE("sour(%s) error(%s)", str.c_str(), errorInfo.c_str());
446 return false;
447 }
448 if (str.length() > INT_MAX_LEN) {
449 errorInfo = "invalid option parameters";
450 LOGE("sour(%s) error(%s)", str.c_str(), errorInfo.c_str());
451 return false;
452 }
453
454 for (size_t i = 0; i < str.length(); i++) {
455 if (str[i] < '0' || str[i] > '9') {
456 errorInfo = "invalid option parameters";
457 LOGE("sour(%s) error(%s)", str.c_str(), errorInfo.c_str());
458 return false;
459 }
460
461 if (!isValid && (str[i] == '0')) {
462 continue;
463 }
464
465 isValid = true;
466 dest *= UI_DECIMALISM;
467 dest += (str[i] - CHAR_NUM_DIFF);
468 }
469
470 if (dest == 0 || dest > INT_MAX) {
471 errorInfo = "option parameter out of range";
472 LOGE("sour(%s) dest(%u) error(%s)", str.c_str(), dest, errorInfo.c_str());
473 return false;
474 }
475
476 return true;
477 }
478
VeriyParameter(std::set<std::string> & keys,std::string param,std::string & errorInfo)479 bool SPUtils::VeriyParameter(std::set<std::string> &keys, std::string param, std::string &errorInfo)
480 {
481 std::string keyParam;
482 std::string valueParm;
483 std::vector<std::string> out;
484 std::vector<std::string> subOut;
485 std::map<std::string, std::string> mapInfo;
486
487 if (param.empty()) {
488 errorInfo = "The parameter cannot be empty";
489 return false;
490 }
491 if (param.find("-PKG") != std::string::npos &&
492 param.find("-PID") != std::string::npos) {
493 LOGE("-PKG and -PID cannot be used together with");
494 return false;
495 }
496 SPUtils::StrSplit(param, "-", out);
497
498 for (auto it = out.begin(); it != out.end(); ++it) { // Parsing keys and values
499 subOut.clear();
500 SPUtils::StrSplit(*it, " ", subOut);
501 if (mapInfo.end() != mapInfo.find(subOut[0])) {
502 errorInfo = "duplicate parameters -- '" + subOut[0] + "'";
503 return false;
504 }
505
506 if (subOut.size() >= UI_INDEX_2) {
507 keyParam = subOut[0];
508 valueParm = subOut[1];
509 SPUtils::RemoveSpace(keyParam);
510 SPUtils::RemoveSpace(valueParm);
511 mapInfo[keyParam] = valueParm;
512 } else if (subOut.size() >= 1) {
513 keyParam = subOut[0];
514 SPUtils::RemoveSpace(keyParam);
515 mapInfo[keyParam] = "";
516 }
517 }
518
519 if (!VeriyKey(keys, mapInfo, errorInfo)) {
520 LOGE("%s", errorInfo.c_str());
521 return false;
522 }
523
524 if (!VerifyValueStr(mapInfo, errorInfo)) {
525 LOGE("%s", errorInfo.c_str());
526 return false;
527 }
528
529 if (!IntegerValueVerification(keys, mapInfo, errorInfo)) {
530 LOGE("%s", errorInfo.c_str());
531 return false;
532 }
533 return true;
534 }
535
VeriyKey(std::set<std::string> & keys,std::map<std::string,std::string> & mapInfo,std::string & errorInfo)536 bool SPUtils::VeriyKey(std::set<std::string> &keys, std::map<std::string, std::string> &mapInfo,
537 std::string &errorInfo)
538 {
539 for (auto it = mapInfo.begin(); it != mapInfo.end(); ++it) {
540 if (keys.end() == keys.find(it->first)) {
541 errorInfo = "invalid parameter -- '" + it->first + "'";
542 return false;
543 }
544 }
545
546 return true;
547 }
548
VerifyValueStr(std::map<std::string,std::string> & mapInfo,std::string & errorInfo)549 bool SPUtils::VerifyValueStr(std::map<std::string, std::string> &mapInfo, std::string &errorInfo)
550 {
551 auto a = mapInfo.find("VIEW");
552 if (mapInfo.end() != a && a->second.empty()) { // Cannot be null
553 errorInfo += "option requires an argument -- '" + a->first + "'";
554 return false;
555 }
556 a = mapInfo.find("PKG");
557 if (mapInfo.end() != a && a->second.empty()) { // Cannot be null
558 errorInfo += "option requires an argument -- '" + a->first + "'";
559 return false;
560 }
561 a = mapInfo.find("PID");
562 if (mapInfo.end() != a && a->second.empty()) { // Cannot be null
563 errorInfo += "option requires an argument -- '" + a->first + "'";
564 return false;
565 }
566 a = mapInfo.find("OUT");
567 if (mapInfo.end() != a) {
568 if (a->second.empty()) {
569 errorInfo += "option requires an argument -- '" + a->first + "'";
570 return false;
571 }
572 // The total length of file path and name cannot exceed PATH_MAX
573 if (a->second.length() >= PATH_MAX) {
574 errorInfo +=
575 "invalid parameter, file path cannot exceed " + std::to_string(PATH_MAX) + " -- '" + a->first + "'";
576 return false;
577 }
578 size_t pos = a->second.rfind('/');
579 if (pos == a->second.length()) { // not file name
580 errorInfo += "invalid parameter,not file name -- '" + a->first + "'";
581 return false;
582 }
583 if (std::string::npos != pos &&
584 (!SPUtils::FileAccess(a->second.substr(0, pos)))) { // determine if the directory exists
585 errorInfo += "invalid parameter,file path not found -- '" + a->first + "'";
586 return false;
587 }
588 std::string outStr = a->second;
589 std::vector<std::string> outList;
590 SPUtils::StrSplit(outStr, "/", outList);
591 for (auto it = outList.begin(); outList.end() != it; ++it) {
592 if ((*it).length() >= NAME_MAX) {
593 errorInfo += "invalid parameter, file directory or name cannot exceed 255 -- '" + a->first + "'";
594 return false;
595 }
596 }
597 }
598 return true;
599 }
600
IntegerValueVerification(std::set<std::string> & keys,std::map<std::string,std::string> & mapInfo,std::string & errorInfo)601 bool SPUtils::IntegerValueVerification(std::set<std::string> &keys, std::map<std::string, std::string> &mapInfo,
602 std::string &errorInfo)
603 {
604 std::vector<std::string> integerCheck; // Number of integers to be detected
605
606 if (keys.end() != keys.find("N")) {
607 integerCheck.push_back("N");
608 }
609 if (keys.end() != keys.find("fl")) {
610 integerCheck.push_back("fl");
611 }
612 if (keys.end() != keys.find("ftl")) {
613 integerCheck.push_back("ftl");
614 }
615 if (keys.end() != keys.find("PID")) {
616 integerCheck.push_back("PID");
617 }
618
619 for (auto it = integerCheck.begin(); it != integerCheck.end(); ++it) {
620 auto a = mapInfo.find(*it);
621 if (mapInfo.end() != a) {
622 if (a->second.empty()) {
623 errorInfo += "option requires an argument -- '" + a->first + "'";
624 return false;
625 }
626 if (!SPUtils::IntegerVerification(a->second, errorInfo)) {
627 errorInfo += "option parameter out of range -- '" + a->first + "'";
628 return false;
629 }
630 }
631 }
632
633 return true;
634 }
635
IsHmKernel()636 bool SPUtils::IsHmKernel()
637 {
638 bool isHM = false;
639 utsname unameBuf;
640 if ((uname(&unameBuf)) == 0) {
641 std::string osRelease = unameBuf.release;
642 isHM = osRelease.find("HongMeng") != std::string::npos;
643 }
644 return isHM;
645 }
646
GetCpuNum()647 std::string SPUtils::GetCpuNum()
648 {
649 std::string cpuCores = "cpuCores||";
650 std::shared_ptr<CpuCollector> collector = CpuCollector::Create();
651 CollectResult<std::vector<CpuFreq>> result = collector->CollectCpuFrequency();
652 std::vector<CpuFreq> &cpufreq = result.data;
653 size_t cpuNum = cpufreq.size();
654 cpuCores += std::to_string(cpuNum);
655 if (cpuNum == 0) {
656 std::cout << "CPU frequency collection failed." << std::endl;
657 LOGE("CPU frequency collection failed.");
658 }
659 return cpuCores;
660 }
GetCurrentTime(int prevTime)661 void SPUtils::GetCurrentTime(int prevTime)
662 {
663 LOGD("SPUtils::prevTime (%d)", prevTime);
664 unsigned long sleepNowTime = 10000;
665 bool shouldContinue = true;
666 while (shouldContinue) {
667 struct timespec time1 = { 0 };
668 clock_gettime(CLOCK_MONOTONIC, &time1);
669 int curTimeNow = static_cast<int>(time1.tv_sec - 1);
670 if (curTimeNow == prevTime) {
671 usleep(sleepNowTime);
672 } else {
673 shouldContinue = false;
674 }
675 }
676 }
677
IsForeGround(const std::string & pkg)678 bool SPUtils::IsForeGround(const std::string &pkg)
679 {
680 bool isFoundAppName = false;
681 bool isForeground = false;
682 std::string result;
683 const std::string cmd = "hidumper -s AbilityManagerService -a -l";
684 if (cmd.empty()) {
685 LOGI("cmd is null");
686 return false;
687 }
688
689 FILE *fd = popen(cmd.c_str(), "r");
690 if (fd == nullptr) {
691 return false;
692 }
693 size_t bytesRead;
694 std::array<char, BUFFER_SIZE> buf;
695 while ((bytesRead = fread(buf.data(), 1, buf.size(), fd)) > 0) {
696 result.append(buf.data(), bytesRead);
697 }
698 if (pclose(fd) == -1) {
699 LOGE("Error: failed to close file");
700 return false;
701 }
702
703 std::istringstream iss(result);
704 std::string line;
705 while (std::getline(iss, line)) {
706 if (!isFoundAppName && line.find("mission name #[#" + pkg) != std::string::npos) {
707 isFoundAppName = true;
708 }
709 if (isFoundAppName) {
710 if (line.find("app state") != std::string::npos) {
711 isForeground = IsFindForeGround(line);
712 break;
713 }
714 }
715 }
716 return isForeground;
717 }
718
IsFindForeGround(const std::string & line)719 bool SPUtils::IsFindForeGround(const std::string &line)
720 {
721 return line.find("FOREGROUND") != std::string::npos;
722 }
723
IsFindAbilist()724 bool SPUtils::IsFindAbilist()
725 {
726 std::string abilist = GetSplitOne(DEVICE_CMD_MAP.at(DeviceCmd::ABILIST));
727 std::string brand = GetSplitOne(DEVICE_CMD_MAP.at(DeviceCmd::BRAND));
728 if (abilist.find("arm") != std::string::npos && brand.find("HUA") != std::string::npos) {
729 return true;
730 } else if (abilist.find("arm") != std::string::npos && brand.find("HUA") == std::string::npos) {
731 return OHOS::SmartPerf::FPS::GetInstance().SetOtherDeviceFlag();
732 } else {
733 return false;
734 }
735 }
SetRkFlag()736 void SPUtils::SetRkFlag()
737 {
738 bool findAbilistResult = IsFindAbilist();
739 if (!findAbilistResult) {
740 OHOS::SmartPerf::FPS::GetInstance().SetRkFlag();
741 OHOS::SmartPerf::Power::GetInstance().SetRkFlag();
742 OHOS::SmartPerf::GPU::GetInstance().SetRkFlag();
743 OHOS::SmartPerf::ProfilerFPS::GetInstance().SetRkFlag();
744 OHOS::SmartPerf::DDR::GetInstance().SetRkFlag();
745 }
746 }
GetPathPermissions(const std::string & path)747 bool SPUtils::GetPathPermissions(const std::string &path)
748 {
749 const std::string dataCsv = "/data/local/tmp/data.csv";
750 const std::string indexInfoCsv = "/data/local/tmp/smartperf/1/t_index_info.csv";
751 int isDataCsv = strcmp(path.c_str(), dataCsv.c_str());
752 int isIndexInfoCsv = strcmp(path.c_str(), indexInfoCsv.c_str());
753 if (!path.empty()) {
754 std::string cmdResult;
755 std::string cmd;
756 if (isDataCsv == 0 || isIndexInfoCsv == 0) {
757 cmd = "ls -l " + path;
758 LoadCmd(cmd, cmdResult);
759 std::string result = cmdResult.substr(0, 10);
760 return result == "-rw-r--r--";
761 } else {
762 LOGE("the path is false");
763 return false;
764 }
765 } else {
766 LOGE("THE path is empty");
767 return false;
768 }
769 }
770
GetIsGameApp(std::string pkg)771 bool SPUtils::GetIsGameApp(std::string pkg)
772 {
773 bool isGame = false;
774 const std::string cmd = "hidumper -s 66006 -a '-t " + pkg + "'";
775 LOGD("SPUtils::GetIsGameApp cmd (%s)", cmd.c_str());
776 FILE *fd = popen(cmd.c_str(), "r");
777 if (fd == nullptr) {
778 LOGD("ProfilerFPS::fd is empty");
779 return false;
780 }
781 char buf[1024] = {'\0'};
782 while ((fgets(buf, sizeof(buf), fd)) != nullptr) {
783 std::string line(buf);
784 if (line.find("---") != std::string::npos || line.length() <= 1) {
785 continue;
786 }
787 if (line.find("bundleName unknown") != std::string::npos) {
788 isGame = false;
789 break;
790 } else {
791 std::vector<std::string> params;
792 SPUtils::StrSplit(line, " ", params);
793 if (params[0] == "1" && params[1] == pkg) {
794 isGame = true;
795 LOGD("SPUtils::GetIsGameApp isGame", isGame);
796 break;
797 }
798 }
799 }
800 if (pclose(fd) == -1) {
801 LOGE("SPUtils::IsGameApp Error Failed to close file");
802 }
803 return isGame;
804 }
GetVersion()805 std::string SPUtils::GetVersion()
806 {
807 return SMART_PERF_VERSION;
808 }
809
GetTtyDeviceFd()810 int& SPUtils::GetTtyDeviceFd()
811 {
812 static int fd = dup(STDERR_FILENO);
813 return fd;
814 }
815
GetBundleName(const std::string & pid,std::string & bundleName)816 void SPUtils::GetBundleName(const std::string &pid, std::string &bundleName)
817 {
818 std::string filePath = "/proc/";
819 filePath.append(pid).append("/cmdline");
820 LOGD("GetBundleName filePath:%s", filePath.c_str());
821 if (!LoadFile(filePath, bundleName)) {
822 LOGD("Get process name by pid failed! %s", filePath.c_str());
823 return;
824 }
825 bundleName.resize(strlen(bundleName.c_str()));
826 if (bundleName.size() >= 2 && bundleName.substr(0, 2) == "./") { // 2: size
827 bundleName = bundleName.substr(2); // 2: point
828 }
829 size_t found = bundleName.rfind("/");
830 std::string procName;
831 if (found != std::string::npos) {
832 procName = bundleName.substr(found + 1);
833 } else {
834 procName = bundleName;
835 }
836 bundleName = std::move(procName);
837 LOGD("GetBundleName bundleName:%s", bundleName.c_str());
838 }
839 }
840 }
841