1 /*
2 * Copyright (C) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #include <iostream>
16 #include <fstream>
17 #include <sstream>
18 #include <algorithm>
19 #include <unistd.h>
20 #include <dirent.h>
21 #include <cstdio>
22 #include <cstdlib>
23 #include <climits>
24 #include "sys/time.h"
25 #include "include/sp_utils.h"
26 namespace OHOS {
27 namespace SmartPerf {
FileAccess(const std::string & fileName)28 bool SPUtils::FileAccess(const std::string &fileName)
29 {
30 return (access(fileName.c_str(), F_OK) == 0);
31 }
32
LoadFile(const std::string & filePath,std::string & content)33 bool SPUtils::LoadFile(const std::string &filePath, std::string &content)
34 {
35 char realPath[PATH_MAX] = {0x00};
36 if (realpath(filePath.c_str(), realPath) == nullptr) {
37 std::cout << "" << std::endl;
38 }
39 std::ifstream file(realPath);
40 if (!file.is_open()) {
41 return false;
42 }
43
44 file.seekg(0, std::ios::end);
45 file.tellg();
46
47 content.clear();
48 file.seekg(0, std::ios::beg);
49 copy(std::istreambuf_iterator<char>(file), std::istreambuf_iterator<char>(), std::back_inserter(content));
50 // remove '' \n\r
51 ReplaceString(content);
52 return true;
53 }
54
LoadCmd(const std::string & cmd,std::string & result)55 bool SPUtils::LoadCmd(const std::string &cmd, std::string &result)
56 {
57 std::string cmdExc = cmd;
58 FILE *fd = popen(cmdExc.c_str(), "r");
59 if (fd == nullptr) {
60 return false;
61 }
62 char buf[1024] = {'\0'};
63 int ret = fread(buf, sizeof(buf), 1, fd);
64 if (ret >= 0) {
65 result = buf;
66 }
67 if (pclose(fd) == -1) {
68 std::cout << "" << std::endl;
69 }
70 // remove '' \n\r
71 ReplaceString(result);
72 return ret >= 0 ? true : false;
73 }
74
IncludePathDelimiter(const std::string & path)75 std::string SPUtils::IncludePathDelimiter(const std::string &path)
76 {
77 if (path.rfind("/") != path.size() - 1) {
78 return path + "/";
79 }
80
81 return path;
82 }
83
ForDirFiles(const std::string & path,std::vector<std::string> & files)84 void SPUtils::ForDirFiles(const std::string &path, std::vector<std::string> &files)
85 {
86 std::string pathStringWithDelimiter;
87 DIR *dir = opendir(path.c_str());
88 if (dir == nullptr) {
89 return;
90 }
91
92 while (true) {
93 struct dirent *ptr = readdir(dir);
94 if (ptr == nullptr) {
95 break;
96 }
97
98 // current dir OR parent dir
99 if ((strcmp(ptr->d_name, ".") == 0) || (strcmp(ptr->d_name, "..") == 0)) {
100 continue;
101 } else if (ptr->d_type == DT_DIR) {
102 pathStringWithDelimiter = IncludePathDelimiter(path) + std::string(ptr->d_name);
103 ForDirFiles(pathStringWithDelimiter, files);
104 } else {
105 files.push_back(IncludePathDelimiter(path) + std::string(ptr->d_name));
106 }
107 }
108 closedir(dir);
109 }
110
IsSubString(const std::string & str,const std::string & sub)111 bool SPUtils::IsSubString(const std::string &str, const std::string &sub)
112 {
113 if (sub.empty() || str.empty()) {
114 return false;
115 }
116
117 return str.find(sub) != std::string::npos;
118 }
119
StrSplit(const std::string & content,const std::string & sp,std::vector<std::string> & out)120 void SPUtils::StrSplit(const std::string &content, const std::string &sp, std::vector<std::string> &out)
121 {
122 size_t index = 0;
123 while (index != std::string::npos) {
124 size_t tEnd = content.find_first_of(sp, index);
125 std::string tmp = content.substr(index, tEnd - index);
126 if (tmp != "" && tmp != " ") {
127 out.push_back(tmp);
128 }
129 if (tEnd == std::string::npos) {
130 break;
131 }
132 index = tEnd + 1;
133 }
134 }
135
ExtractNumber(const std::string & str)136 std::string SPUtils::ExtractNumber(const std::string &str)
137 {
138 int cntInt = 0;
139 const int shift = 10;
140 for (int i = 0; str[i] != '\0'; ++i) {
141 if (str[i] >= '0' && str[i] <= '9') {
142 cntInt *= shift;
143 cntInt += str[i] - '0';
144 }
145 }
146 return std::to_string(cntInt);
147 }
148
ReplaceString(std::string & res)149 void SPUtils::ReplaceString(std::string &res)
150 {
151 std::string flagOne = "\r";
152 std::string flagTwo = "\n";
153 std::string::size_type ret = res.find(flagOne);
154 while (ret != res.npos) {
155 res.replace(ret, 1, "");
156 ret = res.find(flagOne);
157 }
158 ret = res.find(flagTwo);
159 while (ret != res.npos) {
160 res.replace(ret, 1, "");
161 ret = res.find(flagTwo);
162 }
163 }
164
GetCurTime()165 long long SPUtils::GetCurTime()
166 {
167 struct timeval tv;
168 gettimeofday(&tv, nullptr);
169 long long timestamp = tv.tv_sec * 1000 + tv.tv_usec / 1000;
170 return timestamp;
171 }
172
GetTopPkgName()173 std::string SPUtils::GetTopPkgName()
174 {
175 std::string cmd = "hidumper -s AbilityManagerService -a '-a' | grep 'bundle name' | head -n 1";
176 std::string curTopPkgStr = "";
177 LoadCmd(cmd, curTopPkgStr);
178 uint64_t left = curTopPkgStr.find_first_of("[");
179 uint64_t right = curTopPkgStr.find_first_of("]");
180 std::string topPkg = curTopPkgStr.substr(left + 1, right - left - 1);
181 return topPkg;
182 }
183
GetSplitOne(std::string cmd)184 static std::string GetSplitOne(std::string cmd)
185 {
186 std::string result;
187 SPUtils::LoadCmd(cmd, result);
188 std::vector<std::string> splitStrings;
189 SPUtils::StrSplit(result, "=", splitStrings);
190 return splitStrings[1];
191 }
192
GetDeviceInfo()193 std::map<std::string, std::string> SPUtils::GetDeviceInfo()
194 {
195 std::map<std::string, std::string> resultMap;
196 std::string sn = GetSplitOne("param get |grep ohos.boot.sn");
197 std::string deviceTypeName = GetSplitOne("param get |grep ohos.boot.hardware");
198 std::string brand = GetSplitOne("param get |grep const.product.brand");
199 std::string version = GetSplitOne("param get |grep const.product.software.version");
200 resultMap["sn"] = sn;
201 resultMap["deviceTypeName"] = deviceTypeName;
202 resultMap["brand"] = brand;
203 resultMap["board"] = "hw";
204 resultMap["version"] = version;
205 return resultMap;
206 }
GetCpuInfo()207 std::map<std::string, std::string> SPUtils::GetCpuInfo()
208 {
209 std::vector<std::string> policyFiles;
210 std::map<std::string, std::string> resultMap;
211 std::string basePath = "/sys/devices/system/cpu/cpufreq/";
212 std::cout << "policyFiles size:" << policyFiles.size() << std::endl;
213 DIR *dir = opendir(basePath.c_str());
214 if (dir == nullptr) {
215 return resultMap;
216 }
217 while (true) {
218 struct dirent *ptr = readdir(dir);
219 if (ptr == nullptr) {
220 break;
221 }
222 if ((strcmp(ptr->d_name, ".") == 0) || (strcmp(ptr->d_name, "..") == 0)) {
223 continue;
224 }
225 policyFiles.push_back(IncludePathDelimiter(basePath) + std::string(ptr->d_name));
226 }
227 for (size_t i = 0; i < policyFiles.size(); i++) {
228 std::string cpus;
229 LoadFile(policyFiles[i] + "/affected_cpus", cpus);
230 std::string max;
231 LoadFile(policyFiles[i] + "/cpuinfo_max_freq", max);
232 std::string min;
233 LoadFile(policyFiles[i] + "/cpuinfo_min_freq", min);
234 std::string nameBase = "cpu-c" + std::to_string(i + 1) + "-";
235 resultMap[nameBase + "cluster"] = cpus;
236 resultMap[nameBase + "max"] = max;
237 resultMap[nameBase + "min"] = min;
238 }
239 return resultMap;
240 }
GetGpuInfo()241 std::map<std::string, std::string> SPUtils::GetGpuInfo()
242 {
243 const std::vector<std::string> gpuCurFreqPaths = {
244 "/sys/class/devfreq/fde60000.gpu/",
245 "/sys/class/devfreq/gpufreq/",
246 };
247 std::map<std::string, std::string> resultMap;
248 for (auto path : gpuCurFreqPaths) {
249 if (FileAccess(path)) {
250 std::string max;
251 SPUtils::LoadFile(path + "/max_freq", max);
252 std::string min;
253 SPUtils::LoadFile(path + "/min_freq", min);
254 resultMap["gpu_max_freq"] = max;
255 resultMap["gpu_min_freq"] = min;
256 }
257 }
258 return resultMap;
259 }
260
261 }
262 }
263