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