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