1 /*
2 * Copyright (c) 2021-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 #include "hiview_service_ability.h"
16
17 #include <cstdio>
18 #include <dirent.h>
19 #include <fcntl.h>
20 #include <functional>
21 #include <mutex>
22 #include <sys/stat.h>
23 #include <unistd.h>
24
25 #include "bundle_mgr_client.h"
26 #include "file_util.h"
27 #include "hiview_log_config_manager.h"
28 #include "ipc_skeleton.h"
29 #include "iservice_registry.h"
30 #include "string_util.h"
31 #include "system_ability_definition.h"
32 #include "utility/trace_collector.h"
33
34 namespace OHOS {
35 namespace HiviewDFX {
36 namespace {
37 DEFINE_LOG_TAG("HiViewSA-HiViewServiceAbility");
38 constexpr int MAXRETRYTIMEOUT = 10;
39 constexpr int USER_ID_MOD = 200000;
40
GetApplicationNameById(int32_t uid)41 static std::string GetApplicationNameById(int32_t uid)
42 {
43 std::string bundleName;
44 AppExecFwk::BundleMgrClient client;
45 if (client.GetNameForUid(uid, bundleName) != ERR_OK) {
46 HIVIEW_LOGW("Failed to query bundle name, uid:%{public}d.", uid);
47 }
48 return bundleName;
49 }
50
GetSandBoxPathByUid(int32_t uid)51 static std::string GetSandBoxPathByUid(int32_t uid)
52 {
53 std::string bundleName = GetApplicationNameById(uid);
54 if (bundleName.empty()) {
55 return "";
56 }
57 std::string path;
58 path.append("/data/app/el2/")
59 .append(std::to_string(uid / USER_ID_MOD))
60 .append("/base/")
61 .append(bundleName)
62 .append("/cache/hiview");
63 return path;
64 }
65
ComposeFilePath(const std::string & rootDir,const std::string & destDir,const std::string & fileName)66 static std::string ComposeFilePath(const std::string& rootDir, const std::string& destDir, const std::string& fileName)
67 {
68 std::string filePath(rootDir);
69 if (destDir.empty()) {
70 filePath.append("/").append(fileName);
71 } else {
72 filePath.append("/").append(destDir).append("/").append(fileName);
73 }
74 return filePath;
75 }
76 }
77
Dump(int32_t fd,const std::vector<std::u16string> & args)78 int HiviewServiceAbility::Dump(int32_t fd, const std::vector<std::u16string> &args)
79 {
80 auto service = GetOrSetHiviewService(nullptr);
81 if (service != nullptr) {
82 std::vector<std::string> cmds;
83 for (const auto &arg : args) {
84 cmds.push_back(StringUtil::ConvertToUTF8(arg));
85 }
86 service->DumpRequestDispatcher(fd, cmds);
87 }
88 return 0;
89 }
90
HiviewServiceAbility()91 HiviewServiceAbility::HiviewServiceAbility() : SystemAbility(DFX_SYS_HIVIEW_ABILITY_ID, true)
92 {
93 HIVIEW_LOGI("begin, cmd : %d", DFX_SYS_HIVIEW_ABILITY_ID);
94 }
95
~HiviewServiceAbility()96 HiviewServiceAbility::~HiviewServiceAbility()
97 {
98 HIVIEW_LOGI("begin, cmd : %d", DFX_SYS_HIVIEW_ABILITY_ID);
99 }
100
StartServiceAbility(int sleepS)101 void HiviewServiceAbility::StartServiceAbility(int sleepS)
102 {
103 sptr<ISystemAbilityManager> serviceManager;
104
105 int retryTimeout = MAXRETRYTIMEOUT;
106 while (retryTimeout > 0) {
107 --retryTimeout;
108 if (sleepS > 0) {
109 sleep(sleepS);
110 }
111
112 SystemAbilityManagerClient::GetInstance().DestroySystemAbilityManagerObject();
113 serviceManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
114 if (serviceManager == nullptr) {
115 continue;
116 }
117
118 int result = serviceManager->AddSystemAbility(DFX_SYS_HIVIEW_ABILITY_ID, new HiviewServiceAbility());
119 if (result != 0) {
120 HIVIEW_LOGE("AddSystemAbility error %d", result);
121 continue;
122 }
123 break;
124 }
125
126 if (serviceManager == nullptr) {
127 HIVIEW_LOGE("serviceManager == nullptr");
128 return;
129 }
130
131 auto abilityObjext = serviceManager->AsObject();
132 if (abilityObjext == nullptr) {
133 HIVIEW_LOGE("AsObject() == nullptr");
134 return;
135 }
136
137 bool ret = abilityObjext->AddDeathRecipient(new HiviewServiceAbilityDeathRecipient());
138 if (ret == false) {
139 HIVIEW_LOGE("AddDeathRecipient == false");
140 }
141 }
142
StartService(HiviewService * service)143 void HiviewServiceAbility::StartService(HiviewService *service)
144 {
145 GetOrSetHiviewService(service);
146 StartServiceAbility(0);
147 IPCSkeleton::JoinWorkThread();
148 }
149
GetOrSetHiviewService(HiviewService * service)150 HiviewService *HiviewServiceAbility::GetOrSetHiviewService(HiviewService *service)
151 {
152 static HiviewService *ref = nullptr;
153 if (service != nullptr) {
154 ref = service;
155 }
156 return ref;
157 }
158
List(const std::string & logType,std::vector<HiviewFileInfo> & fileInfos)159 int32_t HiviewServiceAbility::List(const std::string& logType, std::vector<HiviewFileInfo>& fileInfos)
160 {
161 auto configInfoPtr = HiviewLogConfigManager::GetInstance().GetConfigInfoByType(logType);
162 if (configInfoPtr == nullptr) {
163 HIVIEW_LOGI("invalid logtype: %{public}s", logType.c_str());
164 return HiviewNapiErrCode::ERR_INNER_INVALID_LOGTYPE;
165 }
166 GetFileInfoUnderDir(configInfoPtr->path, fileInfos);
167 return 0;
168 }
169
GetFileInfoUnderDir(const std::string & dirPath,std::vector<HiviewFileInfo> & fileInfos)170 void HiviewServiceAbility::GetFileInfoUnderDir(const std::string& dirPath, std::vector<HiviewFileInfo>& fileInfos)
171 {
172 DIR* dir = opendir(dirPath.c_str());
173 if (dir == nullptr) {
174 HIVIEW_LOGW("open dir failed.");
175 return;
176 }
177 struct stat statBuf {};
178 for (auto* ent = readdir(dir); ent != nullptr; ent = readdir(dir)) {
179 if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0 || ent->d_type == DT_DIR) {
180 continue;
181 }
182 std::string filePath(dirPath + ent->d_name);
183 if (stat(filePath.c_str(), &statBuf) != 0) {
184 HIVIEW_LOGW("stat file failed.");
185 continue;
186 }
187 fileInfos.emplace_back(ent->d_name, statBuf.st_mtime, statBuf.st_size);
188 }
189 closedir(dir);
190 }
191
Copy(const std::string & logType,const std::string & logName,const std::string & dest)192 int32_t HiviewServiceAbility::Copy(const std::string& logType, const std::string& logName, const std::string& dest)
193 {
194 return CopyOrMoveFile(logType, logName, dest, false);
195 }
196
Move(const std::string & logType,const std::string & logName,const std::string & dest)197 int32_t HiviewServiceAbility::Move(const std::string& logType, const std::string& logName, const std::string& dest)
198 {
199 return CopyOrMoveFile(logType, logName, dest, true);
200 }
201
CopyOrMoveFile(const std::string & logType,const std::string & logName,const std::string & dest,bool isMove)202 int32_t HiviewServiceAbility::CopyOrMoveFile(
203 const std::string& logType, const std::string& logName, const std::string& dest, bool isMove)
204 {
205 auto service = GetOrSetHiviewService();
206 if (service == nullptr) {
207 return HiviewNapiErrCode::ERR_DEFAULT;
208 }
209 auto configInfoPtr = HiviewLogConfigManager::GetInstance().GetConfigInfoByType(logType);
210 if (configInfoPtr == nullptr) {
211 HIVIEW_LOGI("invalid logtype: %{public}s", logType.c_str());
212 return HiviewNapiErrCode::ERR_INNER_INVALID_LOGTYPE;
213 }
214 if (isMove && configInfoPtr->isReadOnly) {
215 HIVIEW_LOGW("log: %{public}s is read only.", logType.c_str());
216 return HiviewNapiErrCode::ERR_INNER_READ_ONLY;
217 }
218 int32_t uid = IPCSkeleton::GetCallingUid();
219 HIVIEW_LOGI("uid %{public}d, isMove: %{public}d, type:%{public}s, name:%{public}s",
220 uid, isMove, logType.c_str(), StringUtil::HideSnInfo(logName).c_str());
221 std::string sandboxPath = GetSandBoxPathByUid(uid);
222 if (sandboxPath.empty()) {
223 return HiviewNapiErrCode::ERR_DEFAULT;
224 }
225 std::string sourceFile = configInfoPtr->path + logName;
226 if (!FileUtil::FileExists(sourceFile)) {
227 HIVIEW_LOGW("file: %{public}s not exist.", StringUtil::HideSnInfo(logName).c_str());
228 return HiviewNapiErrCode::ERR_SOURCE_FILE_NOT_EXIST;
229 }
230 std::string fullPath = ComposeFilePath(sandboxPath, dest, logName);
231 return isMove ? service->Move(sourceFile, fullPath) : service->Copy(sourceFile, fullPath);
232 }
233
Remove(const std::string & logType,const std::string & logName)234 int32_t HiviewServiceAbility::Remove(const std::string& logType, const std::string& logName)
235 {
236 auto service = GetOrSetHiviewService();
237 if (service == nullptr) {
238 return HiviewNapiErrCode::ERR_DEFAULT;
239 }
240 HIVIEW_LOGI("type:%{public}s, name:%{public}s", logType.c_str(), StringUtil::HideSnInfo(logName).c_str());
241 auto configInfoPtr = HiviewLogConfigManager::GetInstance().GetConfigInfoByType(logType);
242 if (configInfoPtr == nullptr) {
243 HIVIEW_LOGI("invalid logtype: %{public}s", logType.c_str());
244 return HiviewNapiErrCode::ERR_INNER_INVALID_LOGTYPE;
245 }
246 if (configInfoPtr->isReadOnly) {
247 HIVIEW_LOGW("log: %{public}s is read only.", logType.c_str());
248 return HiviewNapiErrCode::ERR_INNER_READ_ONLY;
249 }
250 std::string sourceFile = configInfoPtr->path + logName;
251 if (!FileUtil::FileExists(sourceFile)) {
252 HIVIEW_LOGW("file: %{public}s not exist.", StringUtil::HideSnInfo(logName).c_str());
253 return HiviewNapiErrCode::ERR_SOURCE_FILE_NOT_EXIST;
254 }
255 return service->Remove(sourceFile);
256 }
257
OnDump()258 void HiviewServiceAbility::OnDump()
259 {
260 HIVIEW_LOGI("called");
261 }
262
OnStart()263 void HiviewServiceAbility::OnStart()
264 {
265 HIVIEW_LOGI("called");
266 }
267
OnStop()268 void HiviewServiceAbility::OnStop()
269 {
270 HIVIEW_LOGI("called");
271 }
272
OpenSnapshotTrace(const std::vector<std::string> & tagGroups)273 CollectResultParcelable<int32_t> HiviewServiceAbility::OpenSnapshotTrace(const std::vector<std::string>& tagGroups)
274 {
275 auto traceRetHandler = [&tagGroups] (HiviewService* service) {
276 return service->OpenSnapshotTrace(tagGroups);
277 };
278 return TraceCalling<int32_t>(traceRetHandler);
279 }
280
DumpSnapshotTrace(int32_t caller)281 CollectResultParcelable<std::vector<std::string>> HiviewServiceAbility::DumpSnapshotTrace(int32_t caller)
282 {
283 auto traceRetHandler = [caller] (HiviewService* service) {
284 return service->DumpSnapshotTrace(static_cast<UCollect::TraceCaller>(caller));
285 };
286 return TraceCalling<std::vector<std::string>>(traceRetHandler);
287 }
288
OpenRecordingTrace(const std::string & tags)289 CollectResultParcelable<int32_t> HiviewServiceAbility::OpenRecordingTrace(const std::string& tags)
290 {
291 auto traceRetHandler = [&tags] (HiviewService* service) {
292 return service->OpenRecordingTrace(tags);
293 };
294 return TraceCalling<int32_t>(traceRetHandler);
295 }
296
RecordingTraceOn()297 CollectResultParcelable<int32_t> HiviewServiceAbility::RecordingTraceOn()
298 {
299 auto traceRetHandler = [] (HiviewService* service) {
300 return service->RecordingTraceOn();
301 };
302 return TraceCalling<int32_t>(traceRetHandler);
303 }
304
RecordingTraceOff()305 CollectResultParcelable<std::vector<std::string>> HiviewServiceAbility::RecordingTraceOff()
306 {
307 auto traceRetHandler = [] (HiviewService* service) {
308 return service->RecordingTraceOff();
309 };
310 return TraceCalling<std::vector<std::string>>(traceRetHandler);
311 }
312
CloseTrace()313 CollectResultParcelable<int32_t> HiviewServiceAbility::CloseTrace()
314 {
315 auto traceRetHandler = [] (HiviewService* service) {
316 return service->CloseTrace();
317 };
318 return TraceCalling<int32_t>(traceRetHandler);
319 }
320
RecoverTrace()321 CollectResultParcelable<int32_t> HiviewServiceAbility::RecoverTrace()
322 {
323 auto traceRetHandler = [] (HiviewService* service) {
324 return service->RecoverTrace();
325 };
326 return TraceCalling<int32_t>(traceRetHandler);
327 }
328
CaptureDurationTrace(UCollectClient::AppCaller & appCaller)329 CollectResultParcelable<int32_t> HiviewServiceAbility::CaptureDurationTrace(UCollectClient::AppCaller &appCaller)
330 {
331 appCaller.uid = IPCSkeleton::GetCallingUid();
332 appCaller.pid = IPCSkeleton::GetCallingPid();
333
334 auto traceRetHandler = [=, &appCaller] (HiviewService* service) {
335 return service->CaptureDurationTrace(appCaller);
336 };
337 return TraceCalling<int32_t>(traceRetHandler);
338 }
339
GetSysCpuUsage()340 CollectResultParcelable<double> HiviewServiceAbility::GetSysCpuUsage()
341 {
342 return TraceCalling<double>([] (HiviewService* service) {
343 return service->GetSysCpuUsage();
344 });
345 }
346
SetAppResourceLimit(UCollectClient::MemoryCaller & memoryCaller)347 CollectResultParcelable<int32_t> HiviewServiceAbility::SetAppResourceLimit(UCollectClient::MemoryCaller& memoryCaller)
348 {
349 auto handler = [&memoryCaller] (HiviewService* service) {
350 return service->SetAppResourceLimit(memoryCaller);
351 };
352 return TraceCalling<int32_t>(handler);
353 }
354
GetGraphicUsage(int32_t pid)355 CollectResultParcelable<int32_t> HiviewServiceAbility::GetGraphicUsage(int32_t pid)
356 {
357 auto handler = [pid] (HiviewService* service) {
358 return service->GetGraphicUsage(pid);
359 };
360 return TraceCalling<int32_t>(handler);
361 }
362
HiviewServiceAbilityDeathRecipient()363 HiviewServiceAbilityDeathRecipient::HiviewServiceAbilityDeathRecipient()
364 {
365 HIVIEW_LOGI("called");
366 }
367
~HiviewServiceAbilityDeathRecipient()368 HiviewServiceAbilityDeathRecipient::~HiviewServiceAbilityDeathRecipient()
369 {
370 HIVIEW_LOGI("called");
371 }
372
OnRemoteDied(const wptr<IRemoteObject> & object)373 void HiviewServiceAbilityDeathRecipient::OnRemoteDied(const wptr<IRemoteObject> &object)
374 {
375 HIVIEW_LOGI("called");
376 if (object == nullptr) {
377 return;
378 }
379 HiviewServiceAbility::StartServiceAbility(1);
380 }
381 } // namespace HiviewDFX
382 } // namespace OHOS
383