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