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 (param.find("--") != std::string::npos && param.find(commandShell)) {
572 errorInfo = "invalid parameter -- '" + param + "'";
573 return false;
574 }
575 return true;
576 }
577
RemSpaceAndTraPara(std::vector<std::string> & outParam,std::map<std::string,std::string> & mapInfo,std::string & errorInfo)578 bool SPUtils::RemSpaceAndTraPara(std::vector<std::string>& outParam, std::map<std::string, std::string>& mapInfo,
579 std::string &errorInfo)
580 {
581 std::string keyParam;
582 std::string valueParm;
583 std::vector<std::string> subOut;
584
585 for (auto it = outParam.begin(); it != outParam.end(); ++it) { // Parsing keys and values
586 subOut.clear();
587 SPUtils::StrSplit(*it, " ", subOut);
588 if (mapInfo.end() != mapInfo.find(subOut[0])) {
589 errorInfo = "duplicate parameters -- '" + subOut[0] + "'";
590 return false;
591 }
592
593 if (subOut.size() >= UI_INDEX_2) {
594 keyParam = subOut[0];
595 valueParm = subOut[1];
596 SPUtils::RemoveSpace(keyParam);
597 SPUtils::RemoveSpace(valueParm);
598 mapInfo[keyParam] = valueParm;
599 } else if (subOut.size() >= 1) {
600 keyParam = subOut[0];
601 SPUtils::RemoveSpace(keyParam);
602 mapInfo[keyParam] = "";
603 }
604 }
605 return true;
606 }
607
VeriyKey(std::set<std::string> & keys,std::map<std::string,std::string> & mapInfo,std::string & errorInfo)608 bool SPUtils::VeriyKey(std::set<std::string> &keys, std::map<std::string, std::string> &mapInfo,
609 std::string &errorInfo)
610 {
611 for (auto it = mapInfo.begin(); it != mapInfo.end(); ++it) {
612 if (keys.end() == keys.find(it->first)) {
613 errorInfo = "invalid parameter -- '" + it->first + "'";
614 return false;
615 }
616 }
617
618 return true;
619 }
620
VerifyValueStr(std::map<std::string,std::string> & mapInfo,std::string & errorInfo)621 bool SPUtils::VerifyValueStr(std::map<std::string, std::string> &mapInfo, std::string &errorInfo)
622 {
623 auto a = mapInfo.find("VIEW");
624 if (mapInfo.end() != a && a->second.empty()) { // Cannot be null
625 errorInfo += "option requires an argument -- '" + a->first + "'";
626 return false;
627 }
628 a = mapInfo.find("PKG");
629 if (mapInfo.end() != a && a->second.empty()) { // Cannot be null
630 errorInfo += "option requires an argument -- '" + a->first + "'";
631 return false;
632 }
633 a = mapInfo.find("PID");
634 if (mapInfo.end() != a && a->second.empty()) { // Cannot be null
635 errorInfo += "option requires an argument -- '" + a->first + "'";
636 return false;
637 }
638 a = mapInfo.find("OUT");
639 if (mapInfo.end() != a) {
640 if (a->second.empty()) {
641 errorInfo += "option requires an argument -- '" + a->first + "'";
642 return false;
643 }
644 // The total length of file path and name cannot exceed PATH_MAX
645 if (a->second.length() >= PATH_MAX) {
646 errorInfo +=
647 "invalid parameter, file path cannot exceed " + std::to_string(PATH_MAX) + " -- '" + a->first + "'";
648 return false;
649 }
650 size_t pos = a->second.rfind('/');
651 if (pos == a->second.length()) { // not file name
652 errorInfo += "invalid parameter,not file name -- '" + a->first + "'";
653 return false;
654 }
655 if (std::string::npos != pos &&
656 (!SPUtils::FileAccess(a->second.substr(0, pos)))) { // determine if the directory exists
657 errorInfo += "invalid parameter,file path not found -- '" + a->first + "'";
658 return false;
659 }
660 std::string outStr = a->second;
661 std::vector<std::string> outList;
662 SPUtils::StrSplit(outStr, "/", outList);
663 for (auto it = outList.begin(); outList.end() != it; ++it) {
664 if ((*it).length() >= NAME_MAX) {
665 errorInfo += "invalid parameter, file directory or name cannot exceed 255 -- '" + a->first + "'";
666 return false;
667 }
668 }
669 }
670 return true;
671 }
672
IntegerValueVerification(std::set<std::string> & keys,std::map<std::string,std::string> & mapInfo,std::string & errorInfo)673 bool SPUtils::IntegerValueVerification(std::set<std::string> &keys, std::map<std::string, std::string> &mapInfo,
674 std::string &errorInfo)
675 {
676 std::vector<std::string> integerCheck; // Number of integers to be detected
677
678 if (keys.end() != keys.find("N")) {
679 integerCheck.push_back("N");
680 }
681 if (keys.end() != keys.find("fl")) {
682 integerCheck.push_back("fl");
683 }
684 if (keys.end() != keys.find("ftl")) {
685 integerCheck.push_back("ftl");
686 }
687 if (keys.end() != keys.find("PID")) {
688 integerCheck.push_back("PID");
689 }
690
691 for (auto it = integerCheck.begin(); it != integerCheck.end(); ++it) {
692 auto a = mapInfo.find(*it);
693 if (mapInfo.end() != a) {
694 if (a->second.empty()) {
695 errorInfo += "option requires an argument -- '" + a->first + "'";
696 return false;
697 }
698 if (!SPUtils::IntegerVerification(a->second, errorInfo)) {
699 errorInfo += "option parameter out of range -- '" + a->first + "'";
700 return false;
701 }
702 }
703 }
704
705 return true;
706 }
707
IsHmKernel()708 bool SPUtils::IsHmKernel()
709 {
710 bool isHM = false;
711 utsname unameBuf;
712 if ((uname(&unameBuf)) == 0) {
713 std::string osRelease = unameBuf.release;
714 isHM = osRelease.find("HongMeng") != std::string::npos;
715 }
716 return isHM;
717 }
718
GetCpuNum()719 std::string SPUtils::GetCpuNum()
720 {
721 std::string cpuCores = "cpuCores||";
722 std::shared_ptr<CpuCollector> collector = CpuCollector::Create();
723 CollectResult<std::vector<CpuFreq>> result = collector->CollectCpuFrequency();
724 std::vector<CpuFreq> &cpufreq = result.data;
725 size_t cpuNum = cpufreq.size();
726 cpuCores += std::to_string(cpuNum);
727 if (cpuNum == 0) {
728 std::cout << "CPU frequency collection failed." << std::endl;
729 LOGE("CPU frequency collection failed.");
730 }
731 return cpuCores;
732 }
GetCurrentTime(int prevTime)733 void SPUtils::GetCurrentTime(int prevTime)
734 {
735 LOGD("SPUtils::prevTime (%d)", prevTime);
736 unsigned long sleepNowTime = 10000;
737 bool shouldContinue = true;
738 while (shouldContinue) {
739 struct timespec time1 = { 0 };
740 clock_gettime(CLOCK_MONOTONIC, &time1);
741 int curTimeNow = static_cast<int>(time1.tv_sec - 1);
742 if (curTimeNow == prevTime) {
743 usleep(sleepNowTime);
744 } else {
745 shouldContinue = false;
746 }
747 }
748 }
749
IsForeGround(const std::string & pkg)750 bool SPUtils::IsForeGround(const std::string &pkg)
751 {
752 bool isFoundAppName = false;
753 bool isForeground = false;
754 std::string result;
755 const std::string cmd = "hidumper -s AbilityManagerService -a -l";
756 if (cmd.empty()) {
757 LOGI("cmd is null");
758 return false;
759 }
760
761 FILE *fd = popen(cmd.c_str(), "r");
762 if (fd == nullptr) {
763 return false;
764 }
765 size_t bytesRead;
766 std::array<char, BUFFER_SIZE> buf;
767 while ((bytesRead = fread(buf.data(), 1, buf.size(), fd)) > 0) {
768 result.append(buf.data(), bytesRead);
769 }
770 if (pclose(fd) == -1) {
771 LOGE("Error: failed to close file");
772 return false;
773 }
774
775 std::istringstream iss(result);
776 std::string line;
777 while (std::getline(iss, line)) {
778 if (!isFoundAppName && line.find("mission name #[#" + pkg) != std::string::npos) {
779 isFoundAppName = true;
780 }
781 if (isFoundAppName) {
782 if (line.find("app state") != std::string::npos) {
783 isForeground = IsFindForeGround(line);
784 break;
785 }
786 }
787 }
788 return isForeground;
789 }
790
IsFindForeGround(const std::string & line)791 bool SPUtils::IsFindForeGround(const std::string &line)
792 {
793 return line.find("FOREGROUND") != std::string::npos;
794 }
795
IsFindAbilist()796 bool SPUtils::IsFindAbilist()
797 {
798 std::string abilist = OHOS::system::GetParameter(DEVICE_CMD_MAP.at(DeviceCmd::ABILIST), "Unknown");
799 std::string brand = OHOS::system::GetParameter(DEVICE_CMD_MAP.at(DeviceCmd::BRAND), "Unknown");
800 if (abilist.find("arm") != std::string::npos && brand.find("HUA") != std::string::npos) {
801 return true;
802 } else if (abilist.find("arm") != std::string::npos && brand.find("HUA") == std::string::npos) {
803 return OHOS::SmartPerf::FPS::GetInstance().SetOtherDeviceFlag();
804 } else {
805 return false;
806 }
807 }
SetRkFlag()808 void SPUtils::SetRkFlag()
809 {
810 bool findAbilistResult = IsFindAbilist();
811 if (!findAbilistResult) {
812 OHOS::SmartPerf::FPS::GetInstance().SetRkFlag();
813 OHOS::SmartPerf::Power::GetInstance().SetRkFlag();
814 OHOS::SmartPerf::GPU::GetInstance().SetRkFlag();
815 OHOS::SmartPerf::DDR::GetInstance().SetRkFlag();
816 }
817 }
GetPathPermissions(const std::string & path)818 bool SPUtils::GetPathPermissions(const std::string &path)
819 {
820 const std::string dataCsv = "/data/local/tmp/data.csv";
821 const std::string indexInfoCsv = "/data/local/tmp/smartperf/1/t_index_info.csv";
822 int isDataCsv = strcmp(path.c_str(), dataCsv.c_str());
823 int isIndexInfoCsv = strcmp(path.c_str(), indexInfoCsv.c_str());
824 if (!path.empty()) {
825 std::string cmdResult;
826 std::string cmd;
827 if (isDataCsv == 0 || isIndexInfoCsv == 0) {
828 cmd = "ls -l " + path;
829 LoadCmd(cmd, cmdResult);
830 std::string result = cmdResult.substr(0, 10);
831 return result == "-rw-r--r--";
832 } else {
833 LOGE("the path is false");
834 return false;
835 }
836 } else {
837 LOGE("THE path is empty");
838 return false;
839 }
840 }
841
GetIsGameApp(const std::string & pkg)842 bool SPUtils::GetIsGameApp(const std::string& pkg)
843 {
844 bool isGame = false;
845 const std::string cmd = "hidumper -s 66006 -a '-t " + pkg + "'";
846 LOGD("SPUtils::GetIsGameApp cmd (%s)", cmd.c_str());
847 FILE *fd = popen(cmd.c_str(), "r");
848 if (fd == nullptr) {
849 LOGD("FPS::fd is empty");
850 return false;
851 }
852 char buf[1024] = {'\0'};
853 while ((fgets(buf, sizeof(buf), fd)) != nullptr) {
854 std::string line(buf);
855 if (line.find("---") != std::string::npos || line.length() <= 1) {
856 continue;
857 }
858 if (line.find("bundleName unknown") != std::string::npos) {
859 isGame = IsFindDHGame(pkg);
860 break;
861 } else {
862 std::vector<std::string> params;
863 SPUtils::StrSplit(line, " ", params);
864 if (params[0] == "1" && params[1] == pkg) {
865 isGame = true;
866 LOGD("SPUtils::GetIsGameApp isGame", isGame);
867 break;
868 }
869 }
870 }
871 if (pclose(fd) == -1) {
872 LOGE("SPUtils::IsGameApp Error Failed to close file");
873 }
874 return isGame;
875 }
GetVersion()876 std::string SPUtils::GetVersion()
877 {
878 return SMART_PERF_VERSION;
879 }
880
GetTtyDeviceFd()881 int& SPUtils::GetTtyDeviceFd()
882 {
883 static int fd = dup(STDERR_FILENO);
884 return fd;
885 }
886
GetTestsaPlugin(int command)887 void SPUtils::GetTestsaPlugin(int command)
888 {
889 #ifdef ARKTEST_ENABLE
890 //Call the function
891 std::string stopJsonString = "{\"command\": \"stopCollect\"}";
892 OHOS::testserver::TestServerClient::GetInstance().SpDaemonProcess(command, stopJsonString);
893 #endif
894 }
895
KillStartDaemon()896 void SPUtils::KillStartDaemon()
897 {
898 std::string pidCmd = "ps -ef | grep SP_daemon";
899 std::string cmdResult = "";
900 OHOS::SmartPerf::SPUtils::LoadCmd(pidCmd, cmdResult);
901 if (cmdResult.find("testserver") != std::string::npos) {
902 int command = 2;
903 GetTestsaPlugin(command);
904 }
905 }
906
CreateDir(const std::string & dirPath)907 void SPUtils::CreateDir(const std::string &dirPath)
908 {
909 if (!SPUtils::FileAccess(dirPath)) {
910 std::string cmd = CMD_COMMAND_MAP.at(CmdCommand::CREAT_DIR) + dirPath;
911 std::string cmdResult;
912 if (!SPUtils::LoadCmd(cmd, cmdResult)) {
913 WLOGE("%s capture not be created!", dirPath.c_str());
914 } else {
915 WLOGI("%s created successfully!", dirPath.c_str());
916 return;
917 }
918
919 std::string chmodCmd = "chmod 777 " + dirPath;
920 std::string chmodResult;
921 if (!SPUtils::LoadCmd(chmodCmd, chmodResult)) {
922 WLOGE("Failed to chmod %s", dirPath.c_str());
923 }
924 }
925 }
926
RemoveDirOrFile(const std::string & dirPath)927 void SPUtils::RemoveDirOrFile(const std::string &dirPath)
928 {
929 char pathChar[PATH_MAX] = {0x00};
930 if ((realpath(dirPath.c_str(), pathChar) == nullptr)) {
931 WLOGI("%s is not exist.", dirPath.c_str());
932 return;
933 }
934 LOGD("%s is exist, remove...", dirPath.c_str());
935
936 std::string cmd = CMD_COMMAND_MAP.at(CmdCommand::REMOVE) + dirPath;
937 std::string cmdResult;
938 if (!SPUtils::LoadCmd(cmd, cmdResult)) {
939 WLOGE("%s capture not be removed!", dirPath.c_str());
940 } else {
941 WLOGI("%s removed successfully!", dirPath.c_str());
942 }
943 }
944
CopyFiles(const std::string & cpStr)945 void SPUtils::CopyFiles(const std::string& cpStr)
946 {
947 std::string cmd = CMD_COMMAND_MAP.at(CmdCommand::CP) + cpStr;
948 std::string cmdResult;
949 if (!SPUtils::LoadCmd(cmd, cmdResult)) {
950 WLOGE("Failed to copy files: %s", cpStr.c_str());
951 }
952 }
953
TarFiles(const std::string & tarStr)954 void SPUtils::TarFiles(const std::string& tarStr)
955 {
956 std::string tarCommand = CMD_COMMAND_MAP.at(CmdCommand::TAR) + tarStr;
957 std::string cmdResult;
958 if (!SPUtils::LoadCmd(tarCommand, cmdResult)) {
959 WLOGE("Failed to tar log files");
960 }
961 }
962
GetFileSize(std::string filePath)963 size_t SPUtils::GetFileSize(std::string filePath)
964 {
965 struct stat statbuf;
966 if (stat(filePath.c_str(), &statbuf) == -1) {
967 LOGE("Failed to get file size for %s", filePath.c_str());
968 return 0;
969 }
970 return static_cast<size_t>(statbuf.st_size);
971 }
972
IsFindDHGame(const std::string & pkg)973 bool SPUtils::IsFindDHGame(const std::string &pkg)
974 {
975 bool isdhGame = false;
976 const std::string dumperSurface = HIDUMPER_CMD_MAP.at(HidumperCmd::DUMPER_SURFACE);
977 char buf[1024] = {'\0'};
978 FILE *fd = popen(dumperSurface.c_str(), "r");
979 if (fd == nullptr) {
980 return isdhGame;
981 }
982 while (fgets(buf, sizeof(buf), fd) != nullptr) {
983 std::string line = buf;
984 if (line.find(pkg) != std::string::npos || line.find("ShellAssistantAnco") != std::string::npos) {
985 isdhGame = true;
986 break;
987 }
988 }
989 pclose(fd);
990 return isdhGame;
991 }
992
GetSurface()993 std::string SPUtils::GetSurface()
994 {
995 std::string cmdResult;
996 std::string dumperSurface = HIDUMPER_CMD_MAP.at(HidumperCmd::DUMPER_SURFACE);
997 LoadCmd(dumperSurface, cmdResult);
998 size_t positionLeft = cmdResult.find("[");
999 size_t positionRight = cmdResult.find("]");
1000 size_t positionNum = 1;
1001 return cmdResult.substr(positionLeft + positionNum, positionRight - positionLeft - positionNum);
1002 }
1003
GetProductName()1004 std::string SPUtils::GetProductName()
1005 {
1006 return PRODUCT_NAME;
1007 }
1008 }
1009 }
1010