1 /*
2 * Copyright (c) 2021 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 #include "raw_param.h"
16 #include <cinttypes>
17 #include <thread>
18 #include <securec.h>
19 #include <string_ex.h>
20 #include <unistd.h>
21 #include "hilog_wrapper.h"
22 #include "dump_manager_service.h"
23
24 namespace OHOS {
25 namespace HiviewDFX {
26 namespace {
27 static const bool SHOW_PROGRESS_BAR = false;
28 static const int PROGRESS_LENGTH = 128;
29 static const char PROGRESS_STYLE = '=';
30 static const char PROGRESS_TICK[] = {'-', '\\', '|', '/'};
31 } // namespace
32
RawParam(int calllingUid,int calllingPid,uint32_t reqId,std::vector<std::u16string> & args,int outfd)33 RawParam::RawParam(int calllingUid, int calllingPid, uint32_t reqId, std::vector<std::u16string> &args, int outfd)
34 : uid_(calllingUid), pid_(calllingPid), canceled_(false), finished_(false), reqId_(reqId), outfd_(outfd)
35 {
36 DUMPER_HILOGD(MODULE_SERVICE, "create|pid=%{public}d, reqId=%{public}u", pid_, reqId_);
37 Init(args);
38 }
39
~RawParam()40 RawParam::~RawParam()
41 {
42 DUMPER_HILOGD(MODULE_SERVICE, "release|pid=%{public}d, reqId=%{public}u", pid_, reqId_);
43 Uninit();
44 }
45
Init(std::vector<std::u16string> & args)46 bool RawParam::Init(std::vector<std::u16string> &args)
47 {
48 DUMPER_HILOGD(MODULE_SERVICE, "enter|");
49 if (deathRecipient_ == nullptr) {
50 deathRecipient_ = sptr<IRemoteObject::DeathRecipient>(new ClientDeathRecipient(reqId_, canceled_));
51 }
52 DUMPER_HILOGD(MODULE_SERVICE, "debug|argc=%{public}zu", args.size());
53 if (args.size() >= ARG_MIN_COUNT) {
54 SetCallerPpid(Str16ToStr8(args[args.size() - 1]));
55 args.pop_back();
56 }
57 for (size_t i = 0; i < args.size() && i <= ARG_MAX_COUNT; i++) {
58 argValues_[i] = std::make_unique<ArgValue>();
59 if (sprintf_s(argValues_[i]->value, SINGLE_ARG_MAXLEN, "%s", Str16ToStr8(args[i]).c_str()) < 0) {
60 return false;
61 }
62 argHead_[i] = argValues_[i]->value;
63 }
64 DUMPER_HILOGD(MODULE_SERVICE, "leave|true");
65 return true;
66 }
67
Uninit()68 void RawParam::Uninit()
69 {
70 DUMPER_HILOGD(MODULE_SERVICE, "enter|");
71 CloseOutputFd();
72 DUMPER_HILOGD(MODULE_SERVICE, "leave|");
73 }
74
GetOutputFd()75 int &RawParam::GetOutputFd()
76 {
77 return outfd_;
78 }
79
CloseOutputFd()80 void RawParam::CloseOutputFd()
81 {
82 DUMPER_HILOGD(MODULE_SERVICE, "enter|outfd=%{public}d", outfd_);
83 if (outfd_ > -1) {
84 DUMPER_HILOGD(MODULE_SERVICE, "debug|outfd=%{public}d", outfd_);
85 close(outfd_);
86 }
87 outfd_ = -1;
88 DUMPER_HILOGD(MODULE_SERVICE, "leave|outfd=%{public}d", outfd_);
89 }
90
GetArgc()91 int RawParam::GetArgc()
92 {
93 int count = 0;
94 for (int i = 0; i < ARG_MAX_COUNT; i++) {
95 if (argHead_[i] == nullptr) {
96 break;
97 }
98 count = i + 1;
99 }
100 return count;
101 }
102
GetArgv()103 char **RawParam::GetArgv()
104 {
105 return argHead_;
106 }
107
GetUid()108 int RawParam::GetUid()
109 {
110 return uid_;
111 }
112
GetPid()113 int RawParam::GetPid()
114 {
115 return pid_;
116 }
117
GetRequestId()118 uint32_t RawParam::GetRequestId()
119 {
120 return reqId_;
121 }
122
IsCanceled()123 bool RawParam::IsCanceled()
124 {
125 return canceled_;
126 }
127
IsFinished()128 bool RawParam::IsFinished()
129 {
130 return (canceled_ || finished_ || hasError_);
131 }
132
HasError()133 bool RawParam::HasError()
134 {
135 return hasError_;
136 }
137
Cancel()138 void RawParam::Cancel()
139 {
140 canceled_ = true;
141 DUMPER_HILOGD(MODULE_SERVICE, "debug|reqId=%{public}u", reqId_);
142 }
143
SetProgressEnabled(bool enable)144 void RawParam::SetProgressEnabled(bool enable)
145 {
146 progressEnabled_ = enable;
147 }
148
IsProgressEnabled() const149 bool RawParam::IsProgressEnabled() const
150 {
151 return progressEnabled_;
152 }
153
SetTitle(const std::string & path)154 void RawParam::SetTitle(const std::string &path)
155 {
156 path_ = path;
157 }
158
SetFolder(const std::string & folder)159 void RawParam::SetFolder(const std::string &folder)
160 {
161 folder_ = folder;
162 }
163
GetFolder()164 std::string RawParam::GetFolder()
165 {
166 return folder_;
167 }
168
SetCallerPpid(const std::string & ppid)169 void RawParam::SetCallerPpid(const std::string &ppid)
170 {
171 StrToInt(ppid, callerPpid_);
172 }
173
GetCallerPpid()174 int RawParam::GetCallerPpid()
175 {
176 return callerPpid_;
177 }
178
UpdateProgress(uint32_t total,uint32_t current)179 void RawParam::UpdateProgress(uint32_t total, uint32_t current)
180 {
181 if ((!progressEnabled_) || (outfd_ < 0) || (total < 1) || (total < current)) {
182 return;
183 }
184 UpdateProgress((uint64_t(FINISH) * current) / total);
185 }
186
UpdateProgress(uint64_t progress)187 void RawParam::UpdateProgress(uint64_t progress)
188 {
189 if ((!progressEnabled_) || (outfd_ < 0) || (progress > FINISH)) {
190 return;
191 }
192 progress_ = std::max(progress, progress_);
193 progressTick_ = (progressTick_ + 1) % sizeof(PROGRESS_TICK);
194 if (SHOW_PROGRESS_BAR) {
195 char barbuf[PROGRESS_LENGTH + 1] = {0};
196 for (size_t i = 0; ((i < progress_) && (i < PROGRESS_LENGTH)); i++) {
197 barbuf[i] = PROGRESS_STYLE;
198 }
199 dprintf(outfd_, "\033[?25l\r[%-100s],%2" PRIu64 "%%,[%c]\033[?25h",
200 barbuf, progress_, PROGRESS_TICK[progressTick_]);
201 } else {
202 dprintf(outfd_, "\033[?25l\r%2" PRIu64 "%%,[%c]\033[?25h", progress_, PROGRESS_TICK[progressTick_]);
203 }
204 if (progress_ == FINISH) {
205 dprintf(outfd_, "%s\n", path_.c_str());
206 }
207 }
208
ClientDeathRecipient(uint32_t reqId,bool & deathed)209 RawParam::ClientDeathRecipient::ClientDeathRecipient(uint32_t reqId, bool &deathed) : reqId_(reqId), deathed_(deathed)
210 {}
211
OnRemoteDied(const wptr<IRemoteObject> & remote)212 void RawParam::ClientDeathRecipient::OnRemoteDied(const wptr<IRemoteObject> &remote)
213 {
214 if (remote == nullptr || remote.promote() == nullptr) {
215 return;
216 }
217 auto dumpManagerService = DumpDelayedSpSingleton<DumpManagerService>::GetInstance();
218 if (dumpManagerService == nullptr) {
219 return;
220 }
221 DUMPER_HILOGD(MODULE_SERVICE, "enter|reqId=%{public}d", reqId_);
222 deathed_ = true;
223 DUMPER_HILOGD(MODULE_SERVICE, "leave|reqId=%{public}d", reqId_);
224 }
225
Dump() const226 void RawParam::Dump() const
227 {
228 DUMPER_HILOGD(MODULE_SERVICE, "enter|");
229 DUMPER_HILOGD(MODULE_SERVICE, "debug|uid=%{public}d, pid=%{public}d", uid_, pid_);
230 DUMPER_HILOGD(MODULE_SERVICE, "debug|reqId=%{public}u", reqId_);
231 DUMPER_HILOGD(MODULE_SERVICE, "leave|");
232 }
233 } // namespace HiviewDFX
234 } // namespace OHOS
235