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