• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2023 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 <mutex>
21 #include <sys/stat.h>
22 #include <unistd.h>
23 
24 #include "bundle_mgr_client.h"
25 #include "file_util.h"
26 #include "hiview_log_config_manager.h"
27 #include "hiview_napi_err_code.h"
28 #include "ipc_skeleton.h"
29 #include "iservice_registry.h"
30 #include "string_util.h"
31 #include "system_ability_definition.h"
32 
33 namespace OHOS {
34 namespace HiviewDFX {
35 namespace {
36 DEFINE_LOG_TAG("HiViewSA-HiViewServiceAbility");
37 constexpr int MAXRETRYTIMEOUT = 10;
38 constexpr int USER_ID_MOD = 200000;
39 
GetApplicationNameById(int32_t uid)40 static std::string GetApplicationNameById(int32_t uid)
41 {
42     std::string bundleName;
43     AppExecFwk::BundleMgrClient client;
44     if (client.GetNameForUid(uid, bundleName) != ERR_OK) {
45         HIVIEW_LOGW("Failed to query bundle name, uid:%{public}d.", uid);
46     }
47     return bundleName;
48 }
49 
GetSandBoxPathByUid(int32_t uid)50 static std::string GetSandBoxPathByUid(int32_t uid)
51 {
52     std::string bundleName = GetApplicationNameById(uid);
53     if (bundleName.empty()) {
54         return "";
55     }
56     std::string path;
57     path.append("/data/app/el2/")
58         .append(std::to_string(uid / USER_ID_MOD))
59         .append("/base/")
60         .append(bundleName)
61         .append("/cache/hiview");
62     return path;
63 }
64 
ComposeFilePath(const std::string & rootDir,const std::string & destDir,const std::string & fileName)65 static std::string ComposeFilePath(const std::string& rootDir, const std::string& destDir, const std::string& fileName)
66 {
67     std::string filePath(rootDir);
68     if (destDir.empty()) {
69         filePath.append("/").append(fileName);
70     } else {
71         filePath.append("/").append(destDir).append("/").append(fileName);
72     }
73     return filePath;
74 }
75 }
76 
Dump(int32_t fd,const std::vector<std::u16string> & args)77 int HiviewServiceAbility::Dump(int32_t fd, const std::vector<std::u16string> &args)
78 {
79     auto service = GetOrSetHiviewService(nullptr);
80     if (service != nullptr) {
81         std::vector<std::string> cmds;
82         for (const auto &arg : args) {
83             cmds.push_back(StringUtil::ConvertToUTF8(arg));
84         }
85         service->DumpRequestDispatcher(fd, cmds);
86     }
87     return 0;
88 }
89 
HiviewServiceAbility()90 HiviewServiceAbility::HiviewServiceAbility() : SystemAbility(DFX_SYS_HIVIEW_ABILITY_ID, true)
91 {
92     HIVIEW_LOGI("begin, cmd : %d", DFX_SYS_HIVIEW_ABILITY_ID);
93 }
94 
~HiviewServiceAbility()95 HiviewServiceAbility::~HiviewServiceAbility()
96 {
97     HIVIEW_LOGI("begin, cmd : %d", DFX_SYS_HIVIEW_ABILITY_ID);
98 }
99 
StartServiceAbility(int sleepS)100 void HiviewServiceAbility::StartServiceAbility(int sleepS)
101 {
102     HIVIEW_LOGI("called");
103 
104     sptr<ISystemAbilityManager> serviceManager;
105 
106     int retryTimeout = MAXRETRYTIMEOUT;
107     while (retryTimeout > 0) {
108         --retryTimeout;
109         if (sleepS > 0) {
110             sleep(sleepS);
111         }
112 
113         SystemAbilityManagerClient::GetInstance().DestroySystemAbilityManagerObject();
114         serviceManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
115         if (serviceManager == nullptr) {
116             continue;
117         }
118 
119         int result = serviceManager->AddSystemAbility(DFX_SYS_HIVIEW_ABILITY_ID, new HiviewServiceAbility());
120         if (result != 0) {
121             HIVIEW_LOGE("AddSystemAbility error %d", result);
122             continue;
123         }
124         break;
125     }
126 
127     if (serviceManager == nullptr) {
128         HIVIEW_LOGE("serviceManager == nullptr");
129         return;
130     }
131 
132     auto abilityObjext = serviceManager->AsObject();
133     if (abilityObjext == nullptr) {
134         HIVIEW_LOGE("AsObject() == nullptr");
135         return;
136     }
137 
138     bool ret = abilityObjext->AddDeathRecipient(new HiviewServiceAbilityDeathRecipient());
139     if (ret == false) {
140         HIVIEW_LOGE("AddDeathRecipient == false");
141     }
142 }
143 
StartService(HiviewService * service)144 void HiviewServiceAbility::StartService(HiviewService *service)
145 {
146     GetOrSetHiviewService(service);
147     StartServiceAbility(0);
148     IPCSkeleton::JoinWorkThread();
149 }
150 
GetOrSetHiviewService(HiviewService * service)151 HiviewService *HiviewServiceAbility::GetOrSetHiviewService(HiviewService *service)
152 {
153     static HiviewService *ref = nullptr;
154     if (service != nullptr) {
155         ref = service;
156     }
157     return ref;
158 }
159 
List(const std::string & logType,std::vector<HiviewFileInfo> & fileInfos)160 int32_t HiviewServiceAbility::List(const std::string& logType, std::vector<HiviewFileInfo>& fileInfos)
161 {
162     auto configInfoPtr = HiviewLogConfigManager::GetInstance().GetConfigInfoByType(logType);
163     if (configInfoPtr == nullptr) {
164         HIVIEW_LOGI("invalid logtype: %{public}s", logType.c_str());
165         return HiviewNapiErrCode::ERR_INNER_INVALID_LOGTYPE;
166     }
167     GetFileInfoUnderDir(configInfoPtr->path, fileInfos);
168     return 0;
169 }
170 
GetFileInfoUnderDir(const std::string & dirPath,std::vector<HiviewFileInfo> & fileInfos)171 void HiviewServiceAbility::GetFileInfoUnderDir(const std::string& dirPath, std::vector<HiviewFileInfo>& fileInfos)
172 {
173     DIR* dir = opendir(dirPath.c_str());
174     if (dir == nullptr) {
175         HIVIEW_LOGW("open dir failed.");
176         return;
177     }
178     struct stat statBuf {};
179     for (auto* ent = readdir(dir); ent != nullptr; ent = readdir(dir)) {
180         if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0 || ent->d_type == DT_DIR) {
181             continue;
182         }
183         std::string filePath(dirPath + ent->d_name);
184         if (stat(filePath.c_str(), &statBuf) != 0) {
185             HIVIEW_LOGW("stat file failed.");
186             continue;
187         }
188         fileInfos.emplace_back(ent->d_name, statBuf.st_mtime, statBuf.st_size);
189     }
190     closedir(dir);
191 }
192 
Copy(const std::string & logType,const std::string & logName,const std::string & dest)193 int32_t HiviewServiceAbility::Copy(const std::string& logType, const std::string& logName, const std::string& dest)
194 {
195     return CopyOrMoveFile(logType, logName, dest, false);
196 }
197 
Move(const std::string & logType,const std::string & logName,const std::string & dest)198 int32_t HiviewServiceAbility::Move(const std::string& logType, const std::string& logName, const std::string& dest)
199 {
200     return CopyOrMoveFile(logType, logName, dest, true);
201 }
202 
CopyOrMoveFile(const std::string & logType,const std::string & logName,const std::string & dest,bool isMove)203 int32_t HiviewServiceAbility::CopyOrMoveFile(
204     const std::string& logType, const std::string& logName, const std::string& dest, bool isMove)
205 {
206     auto service = GetOrSetHiviewService();
207     if (service == nullptr) {
208         return HiviewNapiErrCode::ERR_DEFAULT;
209     }
210     auto configInfoPtr = HiviewLogConfigManager::GetInstance().GetConfigInfoByType(logType);
211     if (configInfoPtr == nullptr) {
212         HIVIEW_LOGI("invalid logtype: %{public}s", logType.c_str());
213         return HiviewNapiErrCode::ERR_INNER_INVALID_LOGTYPE;
214     }
215     if (isMove && configInfoPtr->isReadOnly) {
216         HIVIEW_LOGW("log: %{public}s is read only.", logType.c_str());
217         return HiviewNapiErrCode::ERR_INNER_READ_ONLY;
218     }
219     int32_t uid = IPCSkeleton::GetCallingUid();
220     HIVIEW_LOGI("uid %{public}d, isMove: %{public}d", uid, isMove);
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.", 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     auto configInfoPtr = HiviewLogConfigManager::GetInstance().GetConfigInfoByType(logType);
241     if (configInfoPtr == nullptr) {
242         HIVIEW_LOGI("invalid logtype: %{public}s", logType.c_str());
243         return HiviewNapiErrCode::ERR_INNER_INVALID_LOGTYPE;
244     }
245     if (configInfoPtr->isReadOnly) {
246         HIVIEW_LOGW("log: %{public}s is read only.", logType.c_str());
247         return HiviewNapiErrCode::ERR_INNER_READ_ONLY;
248     }
249     std::string sourceFile = configInfoPtr->path + logName;
250     if (!FileUtil::FileExists(sourceFile)) {
251         HIVIEW_LOGW("file: %{public}s not exist.", logName.c_str());
252         return HiviewNapiErrCode::ERR_SOURCE_FILE_NOT_EXIST;
253     }
254     return service->Remove(sourceFile);
255 }
256 
OnDump()257 void HiviewServiceAbility::OnDump()
258 {
259     HIVIEW_LOGI("called");
260 }
261 
OnStart()262 void HiviewServiceAbility::OnStart()
263 {
264     HIVIEW_LOGI("called");
265 }
266 
OnStop()267 void HiviewServiceAbility::OnStop()
268 {
269     HIVIEW_LOGI("called");
270 }
271 
HiviewServiceAbilityDeathRecipient()272 HiviewServiceAbilityDeathRecipient::HiviewServiceAbilityDeathRecipient()
273 {
274     HIVIEW_LOGI("called");
275 }
276 
~HiviewServiceAbilityDeathRecipient()277 HiviewServiceAbilityDeathRecipient::~HiviewServiceAbilityDeathRecipient()
278 {
279     HIVIEW_LOGI("called");
280 }
281 
OnRemoteDied(const wptr<IRemoteObject> & object)282 void HiviewServiceAbilityDeathRecipient::OnRemoteDied(const wptr<IRemoteObject> &object)
283 {
284     HIVIEW_LOGI("called");
285     if (object == nullptr) {
286         return;
287     }
288     HiviewServiceAbility::StartServiceAbility(1);
289 }
290 } // namespace HiviewDFX
291 } // namespace OHOS
292