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