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> ¶meter, StringMatrix dumpDatas)59 DumpStatus IPCStatDumper::PreExecute(const std::shared_ptr<DumperParameter> ¶meter, 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