1 /*
2  * Copyright (C) 2024 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 "executor/ipc_stat_dumper.h"
17 
18 #include <cstdio>
19 #include <thread>
20 #include <unistd.h>
21 
22 #include "app_mgr_client.h"
23 #include "dump_common_utils.h"
24 #include "dump_utils.h"
25 #include "file_ex.h"
26 #include "running_process_info.h"
27 #include "securec.h"
28 #include "system_ability_definition.h"
29 
30 namespace OHOS {
31 namespace HiviewDFX {
32 const int SAMGR_SA_ID = 0;
33 
34 using AppExecFwk::RunningProcessInfo;
35 using AppExecFwk::AppMgrClient;
36 using StringMatrix = std::shared_ptr<std::vector<std::vector<std::string>>>;
37 
IPCStatDumper()38 IPCStatDumper::IPCStatDumper()
39 {}
40 
~IPCStatDumper()41 IPCStatDumper::~IPCStatDumper()
42 {}
43 
SendErrorMessage(const std::string & errorStr)44 void IPCStatDumper::SendErrorMessage(const std::string &errorStr)
45 {
46     if (ptrReqCtl_ == nullptr) {
47         DUMPER_HILOGE(MODULE_SERVICE, "ptrReqCtl_ is nullptr, return");
48         return;
49     }
50     int rawParamFd = ptrReqCtl_->GetOutputFd();
51     if (rawParamFd < 0) {
52         DUMPER_HILOGE(MODULE_SERVICE, "rawParamFd(%{public}d) is invalid, return", rawParamFd);
53         return;
54     }
55     SaveStringToFd(rawParamFd, errorStr + "\n");
56 }
57 
PreExecute(const std::shared_ptr<DumperParameter> & parameter,StringMatrix dumpDatas)58 DumpStatus IPCStatDumper::PreExecute(const std::shared_ptr<DumperParameter> &parameter, StringMatrix dumpDatas)
59 {
60     ptrReqCtl_ = parameter->getClientCallback();
61     pid_ = parameter->GetOpts().ipcStatPid_;
62     isDumpAllIpc_ = parameter->GetOpts().isDumpAllIpc_;
63     isDumpIpc_ = parameter->GetOpts().isDumpIpc_;
64     isDumpIpcStartStat_ = parameter->GetOpts().isDumpIpcStartStat_;
65     isDumpIpcStopStat_ = parameter->GetOpts().isDumpIpcStopStat_;
66     isDumpIpcStat_ = parameter->GetOpts().isDumpIpcStat_;
67     result_ = dumpDatas;
68     return DumpStatus::DUMP_OK;
69 }
70 
CheckPidIsSa(const sptr<ISystemAbilityManager> & sam,std::vector<std::string> & args,sptr<IRemoteObject> & sa)71 bool IPCStatDumper::CheckPidIsSa(const sptr<ISystemAbilityManager> &sam, std::vector<std::string> &args,
72                                  sptr<IRemoteObject> &sa)
73 {
74     if (sam == nullptr) {
75         DUMPER_HILOGE(MODULE_SERVICE, "get samgr fail!");
76         return false;
77     }
78 
79     std::list<SystemProcessInfo> systemProcessInfos;
80     int32_t ret = sam->GetRunningSystemProcess(systemProcessInfos);
81     if (ret != ERR_OK) {
82         DUMPER_HILOGE(MODULE_SERVICE, "get running system process fail! ret:%{public}d", ret);
83         return false;
84     }
85     bool isFind = false;
86     for (const auto& sysProcessInfo : systemProcessInfos) {
87         if (pid_ == sysProcessInfo.pid) {
88             args.push_back(sysProcessInfo.processName);
89             isFind = true;
90             break;
91         }
92     }
93     if (!isFind) {
94         DUMPER_HILOGE(MODULE_SERVICE, "pid:%{public}d is not in systemProcessInfos!", pid_);
95         return false;
96     }
97 
98     sa = sam->CheckSystemAbility(SAMGR_SA_ID);
99     return true;
100 }
101 
CheckPidIsApp(const sptr<ISystemAbilityManager> & sam,std::vector<std::string> & args,sptr<IRemoteObject> & sa)102 bool IPCStatDumper::CheckPidIsApp(const sptr<ISystemAbilityManager> &sam, std::vector<std::string> &args,
103                                   sptr<IRemoteObject> &sa)
104 {
105     if (sam == nullptr) {
106         DUMPER_HILOGE(MODULE_SERVICE, "get samgr fail!");
107         return false;
108     }
109 
110     auto appMgrClient = std::make_unique<AppMgrClient>();
111     std::vector<RunningProcessInfo> runningProcessInfos;
112     int32_t ret = appMgrClient->GetAllRunningProcesses(runningProcessInfos);
113     if (ret != ERR_OK) {
114         DUMPER_HILOGE(MODULE_SERVICE, "get running app process fail! ret:%{public}d", ret);
115         return false;
116     }
117     bool isFind = false;
118     for (const auto& runningProcessInfo : runningProcessInfos) {
119         if (pid_ == runningProcessInfo.pid_) {
120             args.push_back(std::to_string(pid_));
121             isFind = true;
122             break;
123         }
124     }
125     if (!isFind) {
126         DUMPER_HILOGE(MODULE_SERVICE, "pid:%{public}d is not in app runningProcessInfos!", pid_);
127         return false;
128     }
129 
130     sa = sam->CheckSystemAbility(APP_MGR_SERVICE_ID);
131     return true;
132 }
133 
SetIpcStatCmd(const sptr<ISystemAbilityManager> & sam,sptr<IRemoteObject> & sa)134 DumpStatus IPCStatDumper::SetIpcStatCmd(const sptr<ISystemAbilityManager> &sam, sptr<IRemoteObject> &sa)
135 {
136     if (sam == nullptr) {
137         DUMPER_HILOGE(MODULE_SERVICE, "get samgr fail!");
138         return DumpStatus::DUMP_FAIL;
139     }
140 
141     std::vector<std::string> args;
142     args.push_back("--ipc");
143     if (isDumpAllIpc_) {
144         args.push_back("all");
145     } else {
146         if (!CheckPidIsSa(sam, args, sa) && !CheckPidIsApp(sam, args, sa)) {
147             DUMPER_HILOGE(MODULE_SERVICE, "args get process id fail");
148             SendErrorMessage("pid is not support ipc statistic.");
149             return DumpStatus::DUMP_FAIL;
150         }
151     }
152     if (isDumpIpcStartStat_) {
153         args.push_back("--start-stat");
154     } else if (isDumpIpcStopStat_) {
155         args.push_back("--stop-stat");
156     } else if (isDumpIpcStat_) {
157         args.push_back("--stat");
158     } else {
159         DUMPER_HILOGE(MODULE_SERVICE, "cmd is not valid.");
160         SendErrorMessage("input ARG is not valid");
161         return DumpStatus::DUMP_FAIL;
162     }
163     if (!args.empty()) {
164         std::transform(args.begin(), args.end(), std::back_inserter(ipcDumpCmd_), Str8ToStr16);
165     }
166 
167     return DumpStatus::DUMP_OK;
168 }
169 
DoDumpIpcStat(sptr<IRemoteObject> & sa)170 DumpStatus IPCStatDumper::DoDumpIpcStat(sptr<IRemoteObject> &sa)
171 {
172     if (sa == nullptr) {
173         DUMPER_HILOGE(MODULE_SERVICE, "no such system ability\n");
174         return DumpStatus::DUMP_FAIL;
175     }
176 
177     int rawParamFd = ptrReqCtl_->GetOutputFd();
178     int ret = sa->Dump(rawParamFd, ipcDumpCmd_);
179     if (ret != ERR_OK) {
180         DUMPER_HILOGE(MODULE_SERVICE, "system ability dump fail! ret:%{public}d\n", ret);
181     }
182     if (rawParamFd < 0) {
183         DUMPER_HILOGE(MODULE_SERVICE, "sa dump failed\n");
184         return DumpStatus::DUMP_FAIL;
185     }
186 
187     return DumpStatus::DUMP_OK;
188 }
189 
DumpIpcStat(const sptr<ISystemAbilityManager> & sam,sptr<IRemoteObject> & sa)190 DumpStatus IPCStatDumper::DumpIpcStat(const sptr<ISystemAbilityManager> &sam, sptr<IRemoteObject> &sa)
191 {
192     if (sam == nullptr) {
193         DUMPER_HILOGE(MODULE_SERVICE, "get samgr fail!");
194         return DumpStatus::DUMP_FAIL;
195     }
196 
197     std::vector<int32_t> saIds = { SAMGR_SA_ID, APP_MGR_SERVICE_ID };
198     sptr<IRemoteObject> tmpSa;
199 
200     if (isDumpAllIpc_) {
201         for (auto &id : saIds) {
202             tmpSa = sam->CheckSystemAbility(id);
203             if (DoDumpIpcStat(tmpSa) != DumpStatus::DUMP_OK) {
204                 DUMPER_HILOGE(MODULE_SERVICE, "sa dump failed %{public}d\n", id);
205                 return DumpStatus::DUMP_FAIL;
206             }
207         }
208     } else {
209         if (DoDumpIpcStat(sa) != DumpStatus::DUMP_OK) {
210             DUMPER_HILOGE(MODULE_SERVICE, "sa dump failed \n");
211             return DumpStatus::DUMP_FAIL;
212         }
213     }
214 
215     return DumpStatus::DUMP_OK;
216 }
217 
Execute()218 DumpStatus IPCStatDumper::Execute()
219 {
220     if (ptrReqCtl_ == nullptr) {
221         DUMPER_HILOGE(MODULE_SERVICE, "ptrReqCtl_ is nullptr, return");
222         return DumpStatus::DUMP_FAIL;
223     }
224 
225     DUMPER_HILOGI(MODULE_COMMON, "info|IPCStatDumper Execute, %{public}d", pid_);
226     sptr<ISystemAbilityManager> sam = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
227     if (sam == nullptr) {
228         DUMPER_HILOGE(MODULE_SERVICE, "get samgr fail!");
229         return DumpStatus::DUMP_FAIL;
230     }
231     sptr<IRemoteObject> sa;
232     if (SetIpcStatCmd(sam, sa) != DumpStatus::DUMP_OK) {
233         DUMPER_HILOGE(MODULE_SERVICE, "no such process\n");
234         return DumpStatus::DUMP_FAIL;
235     }
236 
237     if (DumpIpcStat(sam, sa) != DumpStatus::DUMP_OK) {
238         DUMPER_HILOGE(MODULE_SERVICE, "dump ipc statistic fail\n");
239         return DumpStatus::DUMP_FAIL;
240     }
241     DUMPER_HILOGI(MODULE_COMMON, "info|IPCStatDumper Execute end");
242     return DumpStatus::DUMP_OK;
243 }
244 
AfterExecute()245 DumpStatus IPCStatDumper::AfterExecute()
246 {
247     return DumpStatus::DUMP_OK;
248 }
249 
250 }  // namespace HiviewDFX
251 }  // namespace OHOS
252