• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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