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