1 /*
2 * Copyright (c) 2023 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
16 #include "system_ability_manager_dumper.h"
17
18 #include "accesstoken_kit.h"
19 #include "ffrt_inner.h"
20 #include "file_ex.h"
21 #include "ipc_skeleton.h"
22 #include "system_ability_manager.h"
23 #include "if_local_ability_manager.h"
24 #include "ipc_payload_statistics.h"
25 #include "samgr_err_code.h"
26
27 namespace OHOS {
28 namespace {
29 constexpr const char* HIDUMPER_PROCESS_NAME = "hidumper_service";
30 constexpr const char* ARGS_QUERY_SA_STATE = "-sa";
31 constexpr const char* ARGS_QUERY_PROCESS_STATE = "-p";
32 constexpr const char* ARGS_QUERY_SA_IN_CURRENT_STATE = "-sm";
33 constexpr const char* ARGS_HELP = "-h";
34 constexpr const char* ARGS_QUERY_ALL_SA_STATE = "-l";
35 constexpr const char* ARGS_FFRT_SEPARATOR = "|";
36 constexpr size_t MIN_ARGS_SIZE = 1;
37 constexpr size_t MAX_ARGS_SIZE = 2;
38 constexpr int32_t FFRT_DUMP_PROC_LEN = 2;
39 constexpr int32_t FFRT_DUMP_PIDS_INDEX = 1;
40 constexpr int FFRT_BUFFER_SIZE = 512 * 1024;
41
42 constexpr const char* IPC_STAT_STR_START = "--start-stat";
43 constexpr const char* IPC_STAT_STR_STOP = "--stop-stat";
44 constexpr const char* IPC_STAT_STR_GET = "--stat";
45 constexpr const char* IPC_STAT_STR_ALL = "all";
46 constexpr const char* IPC_STAT_STR_SAMGR = "samgr";
47 constexpr const char* IPC_DUMP_SUCCESS = " success\n";
48 constexpr const char* IPC_DUMP_FAIL = " fail\n";
49 }
50
FfrtDumpProc(std::shared_ptr<SystemAbilityStateScheduler> abilityStateScheduler,int32_t fd,const std::vector<std::string> & args)51 int32_t SystemAbilityManagerDumper::FfrtDumpProc(std::shared_ptr<SystemAbilityStateScheduler> abilityStateScheduler,
52 int32_t fd, const std::vector<std::string>& args)
53 {
54 if (!CanDump()) {
55 HILOGE("Dump failed, not allowed");
56 return ERR_PERMISSION_DENIED;
57 }
58 std::string result;
59 GetFfrtDumpInfoProc(abilityStateScheduler, args, result);
60 return SaveDumpResultToFd(fd, result);
61 }
62
GetFfrtDumpInfoProc(std::shared_ptr<SystemAbilityStateScheduler> abilityStateScheduler,const std::vector<std::string> & args,std::string & result)63 bool SystemAbilityManagerDumper::GetFfrtDumpInfoProc(std::shared_ptr<SystemAbilityStateScheduler> abilityStateScheduler,
64 const std::vector<std::string>& args, std::string& result)
65 {
66 if (args.size() < FFRT_DUMP_PROC_LEN || args[FFRT_DUMP_PIDS_INDEX].empty()) {
67 HILOGE("FfrtDump param pid not exist");
68 IllegalInput(result);
69 return false;
70 }
71 std::string pidStr = args[FFRT_DUMP_PIDS_INDEX];
72 std::vector<int32_t> processIds;
73 SystemAbilityManagerDumper::FfrtDumpParser(processIds, pidStr);
74 if (processIds.empty()) {
75 HILOGE("FfrtDumpParser parse failed, illegal input processIdsStr %{public}s ", pidStr.c_str());
76 IllegalInput(result);
77 return false;
78 }
79 HILOGD("FfrtDumpProc: processIdsSize=%{public}zu", processIds.size());
80 for (const int32_t pid : processIds) {
81 if (pid == getpid()) {
82 GetSAMgrFfrtInfo(result);
83 continue;
84 }
85 std::u16string processName;
86 int32_t queryResult = abilityStateScheduler->GetProcessNameByProcessId(pid, processName);
87 if (queryResult != ERR_OK) {
88 HILOGE("GetProcessNameByProcessId failed, pid %{public}d not exist", pid);
89 result.append("process " + std::to_string(pid) + " not found!\n");
90 continue;
91 }
92 DumpFfrtInfoByProcName(pid, processName, result);
93 }
94 return true;
95 }
96
FfrtDumpParser(std::vector<int32_t> & processIds,const std::string & processIdsStr)97 bool SystemAbilityManagerDumper::FfrtDumpParser(std::vector<int32_t>& processIds, const std::string& processIdsStr)
98 {
99 std::string processIdsVecStr = processIdsStr + ARGS_FFRT_SEPARATOR;
100 std::size_t pos = processIdsVecStr.find(ARGS_FFRT_SEPARATOR);
101 while (pos != std::string::npos) {
102 std::string processIdStr = processIdsVecStr.substr(0, pos);
103 processIdsVecStr = processIdsVecStr.substr(pos + 1, processIdsVecStr.size() - pos - 1);
104 pos = processIdsVecStr.find(ARGS_FFRT_SEPARATOR);
105 int32_t processId = -1;
106 if (!StrToInt(processIdStr, processId)) {
107 HILOGE("StrToInt processIdStr %{public}s error", processIdStr.c_str());
108 continue;
109 }
110 if (processId > 0) {
111 processIds.emplace_back(processId);
112 }
113 }
114 return true;
115 }
116
GetSAMgrFfrtInfo(std::string & result)117 void SystemAbilityManagerDumper::GetSAMgrFfrtInfo(std::string& result)
118 {
119 char* buffer = new char[FFRT_BUFFER_SIZE + 1]();
120 buffer[FFRT_BUFFER_SIZE] = 0;
121 ffrt_dump(ffrt_dump_cmd_t::DUMP_INFO_ALL, buffer, FFRT_BUFFER_SIZE);
122 if (strlen(buffer) == 0) {
123 HILOGE("get samgr FfrtDumperInfo failed");
124 delete[] buffer;
125 return;
126 }
127 std::string ffrtDumpInfoStr(buffer);
128 result.append(ffrtDumpInfoStr + "\n");
129 delete[] buffer;
130 }
131
DumpFfrtInfoByProcName(int32_t pid,const std::u16string processName,std::string & result)132 void SystemAbilityManagerDumper::DumpFfrtInfoByProcName(int32_t pid, const std::u16string processName,
133 std::string& result)
134 {
135 sptr<ILocalAbilityManager> obj =
136 iface_cast<ILocalAbilityManager>(SystemAbilityManager::GetInstance()->GetSystemProcess(processName));
137 if (obj == nullptr) {
138 HILOGE("GetSystemProcess failed, pid:%{public}d processName:%{public}s not exist",
139 pid, Str16ToStr8(processName).c_str());
140 result.append("process " + std::to_string(pid) + " not found!\n");
141 return;
142 }
143 std::string resultForProcess;
144 if (!obj->FfrtDumperProc(resultForProcess)) {
145 HILOGE("safwk FfrtDumperProc execute failed");
146 return;
147 }
148 result.append(resultForProcess + "\n");
149 }
150
SaveDumpResultToFd(int32_t fd,const std::string & result)151 int32_t SystemAbilityManagerDumper::SaveDumpResultToFd(int32_t fd, const std::string& result)
152 {
153 if (!SaveStringToFd(fd, result)) {
154 HILOGE("save to fd failed");
155 return SAVE_FD_FAIL;
156 }
157 HILOGD("save to fd success");
158 return ERR_OK;
159 }
160
StartSamgrIpcStatistics(std::string & result)161 bool SystemAbilityManagerDumper::StartSamgrIpcStatistics(std::string& result)
162 {
163 result = std::string("StartIpcStatistics pid:") + std::to_string(getpid());
164 bool ret = IPCPayloadStatistics::StartStatistics();
165 result += ret ? IPC_DUMP_SUCCESS : IPC_DUMP_FAIL;
166 return ret;
167 }
168
StopSamgrIpcStatistics(std::string & result)169 bool SystemAbilityManagerDumper::StopSamgrIpcStatistics(std::string& result)
170 {
171 result = std::string("StopSamgrIpcStatistics pid:") + std::to_string(getpid());
172 bool ret = IPCPayloadStatistics::StopStatistics();
173 result += ret ? IPC_DUMP_SUCCESS : IPC_DUMP_FAIL;
174 return ret;
175 }
176
GetSamgrIpcStatistics(std::string & result)177 bool SystemAbilityManagerDumper::GetSamgrIpcStatistics(std::string& result)
178 {
179 result += "********************************GlobalStatisticsInfo********************************";
180 result += "\nCurrentPid:";
181 result += std::to_string(getpid());
182 result += "\nTotalCount:";
183 result += std::to_string(IPCPayloadStatistics::GetTotalCount());
184 result += "\nTotalTimeCost:";
185 result += std::to_string(IPCPayloadStatistics::GetTotalCost());
186 std::vector<int32_t> pids;
187 pids = IPCPayloadStatistics::GetPids();
188 for (unsigned int i = 0; i < pids.size(); i++) {
189 result += "\n--------------------------------ProcessStatisticsInfo-------------------------------";
190 result += "\nCallingPid:";
191 result += std::to_string(pids[i]);
192 result += "\nCallingPidTotalCount:";
193 result += std::to_string(IPCPayloadStatistics::GetCount(pids[i]));
194 result += "\nCallingPidTotalTimeCost:";
195 result += std::to_string(IPCPayloadStatistics::GetCost(pids[i]));
196 std::vector<IPCInterfaceInfo> intfs;
197 intfs = IPCPayloadStatistics::GetDescriptorCodes(pids[i]);
198 for (unsigned int j = 0; j < intfs.size(); j++) {
199 result += "\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~InterfaceStatisticsInfo~~~~~~~~~~~~~~~~~~~~~~~~~~~~~";
200 result += "\nDescriptorCode:";
201 result += Str16ToStr8(intfs[j].desc) + std::string("_") + std::to_string(intfs[j].code);
202 result += "\nDescriptorCodeCount:";
203 result += std::to_string(
204 IPCPayloadStatistics::GetDescriptorCodeCount(pids[i], intfs[j].desc, intfs[j].code));
205 result += "\nDescriptorCodeTimeCost:";
206 result += "\nTotal:";
207 result += std::to_string(
208 IPCPayloadStatistics::GetDescriptorCodeCost(pids[i], intfs[j].desc, intfs[j].code).totalCost);
209 result += " | Max:";
210 result += std::to_string(
211 IPCPayloadStatistics::GetDescriptorCodeCost(pids[i], intfs[j].desc, intfs[j].code).maxCost);
212 result += " | Min:";
213 result += std::to_string(
214 IPCPayloadStatistics::GetDescriptorCodeCost(pids[i], intfs[j].desc, intfs[j].code).minCost);
215 result += " | Avg:";
216 result += std::to_string(
217 IPCPayloadStatistics::GetDescriptorCodeCost(pids[i], intfs[j].desc, intfs[j].code).averCost);
218 result += "\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~";
219 }
220 result += "\n------------------------------------------------------------------------------------";
221 }
222 result += "\n************************************************************************************\n";
223 return true;
224 }
225
IpcDumpIsAllProcess(const std::string & processName)226 bool SystemAbilityManagerDumper::IpcDumpIsAllProcess(const std::string& processName)
227 {
228 return processName == IPC_STAT_STR_ALL;
229 }
230
IpcDumpIsSamgr(const std::string & processName)231 bool SystemAbilityManagerDumper::IpcDumpIsSamgr(const std::string& processName)
232 {
233 return processName == IPC_STAT_STR_SAMGR;
234 }
235
IpcDumpCmdParser(int32_t & cmd,const std::vector<std::string> & args)236 bool SystemAbilityManagerDumper::IpcDumpCmdParser(int32_t& cmd, const std::vector<std::string>& args)
237 {
238 if (!CanDump()) {
239 HILOGE("IPC Dump failed, not allowed");
240 return false;
241 }
242
243 if (args.size() < IPC_STAT_CMD_LEN) {
244 HILOGE("IPC Dump failed, length error");
245 return false;
246 }
247
248 if (args[IPC_STAT_CMD_INDEX] == IPC_STAT_STR_START) {
249 cmd = IPC_STAT_CMD_START;
250 } else if (args[IPC_STAT_CMD_INDEX] == IPC_STAT_STR_STOP) {
251 cmd = IPC_STAT_CMD_STOP;
252 } else if (args[IPC_STAT_CMD_INDEX] == IPC_STAT_STR_GET) {
253 cmd = IPC_STAT_CMD_GET;
254 } else {
255 return false;
256 }
257 return true;
258 }
259
Dump(std::shared_ptr<SystemAbilityStateScheduler> abilityStateScheduler,const std::vector<std::string> & args,std::string & result)260 bool SystemAbilityManagerDumper::Dump(std::shared_ptr<SystemAbilityStateScheduler> abilityStateScheduler,
261 const std::vector<std::string>& args, std::string& result)
262 {
263 if (!CanDump()) {
264 HILOGE("Dump failed, not allowed");
265 return false;
266 }
267 if (args.size() == MIN_ARGS_SIZE) {
268 // -l
269 if (args[0] == ARGS_QUERY_ALL_SA_STATE) {
270 ShowAllSystemAbilityInfo(abilityStateScheduler, result);
271 return true;
272 }
273 // -h
274 if (args[0] == ARGS_HELP) {
275 ShowHelp(result);
276 return true;
277 }
278 }
279 if (args.size() == MAX_ARGS_SIZE) {
280 // -sa said
281 if (args[0] == ARGS_QUERY_SA_STATE) {
282 int said = atoi(args[1].c_str());
283 ShowSystemAbilityInfo(said, abilityStateScheduler, result);
284 return true;
285 }
286 // -p processname
287 if (args[0] == ARGS_QUERY_PROCESS_STATE) {
288 ShowProcessInfo(args[1], abilityStateScheduler, result);
289 return true;
290 }
291 // -sm state
292 if (args[0] == ARGS_QUERY_SA_IN_CURRENT_STATE) {
293 ShowAllSystemAbilityInfoInState(args[1], abilityStateScheduler, result);
294 return true;
295 }
296 }
297 IllegalInput(result);
298 return false;
299 }
300
CanDump()301 bool SystemAbilityManagerDumper::CanDump()
302 {
303 uint32_t accessToken = IPCSkeleton::GetCallingTokenID();
304 Security::AccessToken::NativeTokenInfo nativeTokenInfo;
305 int32_t result = Security::AccessToken::AccessTokenKit::GetNativeTokenInfo(accessToken, nativeTokenInfo);
306 if (result == ERR_OK && nativeTokenInfo.processName == HIDUMPER_PROCESS_NAME) {
307 return true;
308 }
309 return false;
310 }
311
ShowHelp(std::string & result)312 void SystemAbilityManagerDumper::ShowHelp(std::string& result)
313 {
314 result.append("SystemAbilityManager Dump options:\n")
315 .append(" [-h] [cmd]...\n")
316 .append("cmd maybe one of:\n")
317 .append(" -sa said: query sa state infos.\n")
318 .append(" -p processname: query process state infos.\n")
319 .append(" -sm state: query all sa based on state infos.\n")
320 .append(" -l: query all sa state infos.\n");
321 }
322
ShowAllSystemAbilityInfo(std::shared_ptr<SystemAbilityStateScheduler> abilityStateScheduler,std::string & result)323 void SystemAbilityManagerDumper::ShowAllSystemAbilityInfo(
324 std::shared_ptr<SystemAbilityStateScheduler> abilityStateScheduler, std::string& result)
325 {
326 if (abilityStateScheduler == nullptr) {
327 HILOGE("abilityStateScheduler is nullptr");
328 return;
329 }
330 abilityStateScheduler->GetAllSystemAbilityInfo(result);
331 }
332
ShowSystemAbilityInfo(int32_t said,std::shared_ptr<SystemAbilityStateScheduler> abilityStateScheduler,std::string & result)333 void SystemAbilityManagerDumper::ShowSystemAbilityInfo(int32_t said,
334 std::shared_ptr<SystemAbilityStateScheduler> abilityStateScheduler, std::string& result)
335 {
336 if (abilityStateScheduler == nullptr) {
337 HILOGE("abilityStateScheduler is nullptr");
338 return;
339 }
340 abilityStateScheduler->GetSystemAbilityInfo(said, result);
341 }
342
ShowProcessInfo(const std::string & processName,std::shared_ptr<SystemAbilityStateScheduler> abilityStateScheduler,std::string & result)343 void SystemAbilityManagerDumper::ShowProcessInfo(const std::string& processName,
344 std::shared_ptr<SystemAbilityStateScheduler> abilityStateScheduler, std::string& result)
345 {
346 if (abilityStateScheduler == nullptr) {
347 HILOGE("abilityStateScheduler is nullptr");
348 return;
349 }
350 abilityStateScheduler->GetProcessInfo(processName, result);
351 }
352
ShowAllSystemAbilityInfoInState(const std::string & state,std::shared_ptr<SystemAbilityStateScheduler> abilityStateScheduler,std::string & result)353 void SystemAbilityManagerDumper::ShowAllSystemAbilityInfoInState(const std::string& state,
354 std::shared_ptr<SystemAbilityStateScheduler> abilityStateScheduler, std::string& result)
355 {
356 if (abilityStateScheduler == nullptr) {
357 HILOGE("abilityStateScheduler is nullptr");
358 return;
359 }
360 abilityStateScheduler->GetAllSystemAbilityInfoByState(state, result);
361 }
362
IllegalInput(std::string & result)363 void SystemAbilityManagerDumper::IllegalInput(std::string& result)
364 {
365 result.append("The arguments are illegal and you can enter '-h' for help.\n");
366 }
367 } // namespace OHOS