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> ¶meter, 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