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 "dump_manager_service.h"
16 #include <file_ex.h>
17 #include <if_system_ability_manager.h>
18 #include <ipc_skeleton.h>
19 #include <iservice_registry.h>
20 #include <string_ex.h>
21 #include <system_ability_definition.h>
22 #include <thread>
23 #include <unistd.h>
24
25 #include "common.h"
26 #include "dump_log_manager.h"
27 #include "hilog_wrapper.h"
28 #include "manager/dump_implement.h"
29 #include "raw_param.h"
30 #include "inner/dump_service_id.h"
31 #include "common/dumper_constant.h"
32 using namespace std;
33 namespace OHOS {
34 namespace HiviewDFX {
35 namespace {
36 const std::string DUMPMGR_SERVICE_NAME = "HiDumperManagerService";
37 auto dumpManagerService = DelayedSpSingleton<DumpManagerService>::GetInstance();
38 const bool G_REGISTER_RESULT = SystemAbility::MakeAndRegisterAbility(dumpManagerService.GetRefPtr());
39 static const int32_t STOP_WAIT = 3;
40 static const int32_t REQUEST_MAX = 2;
41 static const uint32_t REQUESTID_MAX = 100000;
42 } // namespace
DumpManagerService()43 DumpManagerService::DumpManagerService() : SystemAbility(DFX_SYS_HIDUMPER_ABILITY_ID, true)
44 {
45 }
46
~DumpManagerService()47 DumpManagerService::~DumpManagerService()
48 {
49 }
50
OnStart()51 void DumpManagerService::OnStart()
52 {
53 if (started_) {
54 DUMPER_HILOGE(MODULE_SERVICE, "error|it's ready, nothing to do.");
55 return;
56 }
57 if (!Publish(DelayedSpSingleton<DumpManagerService>::GetInstance())) {
58 DUMPER_HILOGE(MODULE_SERVICE, "error|register to system ability manager failed.");
59 return;
60 }
61 started_ = true;
62 }
63
OnStop()64 void DumpManagerService::OnStop()
65 {
66 if (!started_) {
67 return;
68 }
69 DUMPER_HILOGD(MODULE_SERVICE, "enter|");
70 blockRequest_ = true;
71 CancelAllRequest();
72 for (int i = 0; i < STOP_WAIT; i++) {
73 if (requestRawParamMap_.empty()) {
74 break;
75 }
76 sleep(1);
77 }
78 started_ = false;
79 blockRequest_ = false;
80 DUMPER_HILOGD(MODULE_SERVICE, "leave|");
81 }
82
Request(std::vector<std::u16string> & args,int outfd)83 int32_t DumpManagerService::Request(std::vector<std::u16string> &args, int outfd)
84 {
85 const sptr<IDumpCallbackBroker> callback;
86 return Request(args, outfd, callback);
87 }
88
Dump(int32_t fd,const std::vector<std::u16string> & args)89 int32_t DumpManagerService::Dump(int32_t fd, const std::vector<std::u16string> &args)
90 {
91 std::string result = DUMPMGR_SERVICE_NAME;
92 if (!SaveStringToFd(fd, result)) {
93 DUMPER_HILOGE(MODULE_SERVICE, "DumpManagerService::Dump failed, save to fd failed.");
94 DUMPER_HILOGE(MODULE_SERVICE, "Dump Info:\n");
95 DUMPER_HILOGE(MODULE_SERVICE, "%{public}s", result.c_str());
96 return ERR_OK;
97 }
98 return ERR_OK;
99 }
100
Request(std::vector<std::u16string> & args,int outfd,const sptr<IDumpCallbackBroker> & callback)101 int32_t DumpManagerService::Request(std::vector<std::u16string> &args, int outfd,
102 const sptr<IDumpCallbackBroker> &callback)
103 {
104 if (blockRequest_) {
105 return DumpStatus::DUMP_FAIL;
106 }
107 if (!started_) {
108 return DumpStatus::DUMP_FAIL;
109 }
110 int sum = GetRequestSum();
111 DUMPER_HILOGD(MODULE_SERVICE, "debug|sum=%{public}d", sum);
112 if (sum >= REQUEST_MAX) {
113 return DumpStatus::DUMP_REQUEST_MAX;
114 } else if (sum == 0) {
115 DumpLogManager::Init();
116 }
117 DUMPER_HILOGD(MODULE_SERVICE, "enter|");
118 const std::shared_ptr<RawParam> rawParam = AddRequestRawParam(args, outfd, callback);
119 int32_t ret = StartRequest(rawParam);
120 DUMPER_HILOGD(MODULE_SERVICE, "leave|ret=%{public}d", ret);
121 return ret;
122 }
123
EraseCallback(const sptr<IDumpCallbackBroker> & callback)124 void DumpManagerService::EraseCallback(const sptr<IDumpCallbackBroker> &callback)
125 {
126 DUMPER_HILOGD(MODULE_SERVICE, "enter|");
127 unique_lock<mutex> lock(mutex_);
128 for (auto &requestIt : requestRawParamMap_) {
129 if (requestIt.second == nullptr) {
130 continue;
131 }
132 requestIt.second->EraseCallback(callback);
133 }
134 DUMPER_HILOGD(MODULE_SERVICE, "leave|");
135 }
136
137 #ifdef DUMP_TEST_MODE // for mock test
SetTestMainFunc(DumpManagerServiceTestMainFunc testMainFunc)138 void DumpManagerService::SetTestMainFunc(DumpManagerServiceTestMainFunc testMainFunc)
139 {
140 testMainFunc_ = testMainFunc;
141 }
142 #endif // for mock test
143
GetRequestSum()144 int DumpManagerService::GetRequestSum()
145 {
146 unique_lock<mutex> lock(mutex_);
147 return requestRawParamMap_.size();
148 }
149
AddRequestRawParam(std::vector<std::u16string> & args,int outfd,const sptr<IDumpCallbackBroker> callback)150 std::shared_ptr<RawParam> DumpManagerService::AddRequestRawParam(std::vector<std::u16string> &args, int outfd,
151 const sptr<IDumpCallbackBroker> callback)
152 {
153 unique_lock<mutex> lock(mutex_);
154 uint32_t requestId = 0;
155 do { // find a requestId
156 requestId = GetRequestId();
157 } while (requestRawParamMap_.count(requestId) > 0);
158 int32_t calllingUid = IPCSkeleton::GetCallingUid();
159 int32_t calllingPid = IPCSkeleton::GetCallingPid();
160 DUMPER_HILOGD(MODULE_SERVICE, "debug|requestId=%{public}u, calllingUid=%{public}d, calllingPid=%{public}d",
161 requestId, calllingUid, calllingPid);
162 std::shared_ptr<RawParam> requestHandle =
163 std::make_shared<RawParam>(calllingUid, calllingPid, requestId, args, outfd, callback);
164 requestRawParamMap_.insert(std::make_pair(requestId, requestHandle));
165 return requestHandle;
166 }
167
EraseRequestRawParam(const std::shared_ptr<RawParam> rawParam)168 void DumpManagerService::EraseRequestRawParam(const std::shared_ptr<RawParam> rawParam)
169 {
170 if (rawParam == nullptr) {
171 return;
172 }
173 DUMPER_HILOGD(MODULE_SERVICE, "enter|");
174 unique_lock<mutex> lock(mutex_);
175 uint32_t requestId = rawParam->GetRequestId();
176 DUMPER_HILOGD(MODULE_SERVICE, "debug|requestId=%{public}u", requestId);
177 if (requestRawParamMap_.count(requestId) > 0) {
178 requestRawParamMap_.erase(requestId);
179 DUMPER_HILOGD(MODULE_SERVICE, "debug|erase");
180 }
181 DUMPER_HILOGD(MODULE_SERVICE, "leave|");
182 }
183
CancelAllRequest()184 void DumpManagerService::CancelAllRequest()
185 {
186 DUMPER_HILOGD(MODULE_SERVICE, "enter|");
187 unique_lock<mutex> lock(mutex_);
188 for (auto &requestIt : requestRawParamMap_) {
189 if (requestIt.second == nullptr) {
190 continue;
191 }
192 requestIt.second->Cancel();
193 }
194 DUMPER_HILOGD(MODULE_SERVICE, "leave|");
195 }
196
GetRequestId()197 uint32_t DumpManagerService::GetRequestId()
198 {
199 requestIndex_ = (requestIndex_ + 1) % REQUESTID_MAX;
200 return requestIndex_;
201 }
202
StartRequest(const std::shared_ptr<RawParam> rawParam)203 int32_t DumpManagerService::StartRequest(const std::shared_ptr<RawParam> rawParam)
204 {
205 RequestMain(rawParam);
206 return DumpStatus::DUMP_OK;
207 }
208
RequestMain(const std::shared_ptr<RawParam> rawParam)209 void DumpManagerService::RequestMain(const std::shared_ptr<RawParam> rawParam)
210 {
211 DUMPER_HILOGD(MODULE_SERVICE, "enter|");
212 rawParam->UpdateStatus(IDumpCallbackBroker::STATUS_DUMP_STARTED, true);
213 int argC = rawParam->GetArgc();
214 char **argV = rawParam->GetArgv();
215 std::string folder = DumpLogManager::CreateTmpFolder(rawParam->GetRequestId());
216 rawParam->SetFolder(folder);
217 uint32_t status;
218 if ((argC > 0) && (argV != nullptr)) {
219 DUMPER_HILOGD(MODULE_SERVICE, "debug|enter task, argC=%{public}d", argC);
220 for (int i = 0; i < argC; i++) {
221 DUMPER_HILOGD(MODULE_SERVICE, "debug|argV[%{public}d]=%{public}s", i, argV[i]);
222 }
223 #ifdef DUMP_TEST_MODE // for mock test
224 if (testMainFunc_ != nullptr) {
225 testMainFunc_(argC, argV, rawParam);
226 }
227 #else // for mock test
228 DumpImplement::GetInstance().Main(argC, argV, rawParam);
229 #endif // for mock test
230 DUMPER_HILOGD(MODULE_SERVICE, "debug|leave task");
231 status = IDumpCallbackBroker::STATUS_DUMP_FINISHED;
232 } else {
233 status = IDumpCallbackBroker::STATUS_DUMP_ERROR;
234 }
235 DumpLogManager::EraseTmpFolder(rawParam->GetRequestId());
236 DumpLogManager::EraseLogs();
237 rawParam->CloseOutputFd();
238 rawParam->UpdateStatus(status, true);
239 EraseRequestRawParam(rawParam);
240 DUMPER_HILOGD(MODULE_SERVICE, "leave|");
241 }
242 } // namespace HiviewDFX
243 } // namespace OHOS
244