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