1 /*
2 * Copyright (c) 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
16 #include "hiview_service_agent.h"
17
18 #include "application_context.h"
19 #include "file_util.h"
20 #include "hiview_err_code.h"
21 #include "hiview_service_ability_proxy.h"
22 #include "iservice_registry.h"
23 #include "hiview_logger.h"
24 #include "storage_acl.h"
25 #include "string_util.h"
26 #include "system_ability_definition.h"
27
28 namespace OHOS {
29 namespace HiviewDFX {
30 namespace {
31 DEFINE_LOG_TAG("HiviewServiceAgent");
32 }
33
GetInstance()34 HiviewServiceAgent& HiviewServiceAgent::GetInstance()
35 {
36 static HiviewServiceAgent hiviewServiceAgent;
37 return hiviewServiceAgent;
38 }
39
List(const std::string & logType,std::vector<HiviewFileInfo> & fileInfos)40 int32_t HiviewServiceAgent::List(const std::string& logType, std::vector<HiviewFileInfo>& fileInfos)
41 {
42 auto service = GetRemoteService();
43 if (service == nullptr) {
44 HIVIEW_LOGE("cannot get service.");
45 return HiviewNapiErrCode::ERR_DEFAULT;
46 }
47 HiviewServiceAbilityProxy proxy(service);
48 return proxy.List(logType, fileInfos);
49 }
50
Copy(const std::string & logType,const std::string & logName,const std::string & dest)51 int32_t HiviewServiceAgent::Copy(const std::string& logType, const std::string& logName, const std::string& dest)
52 {
53 return CopyOrMoveFile(logType, logName, dest, false);
54 }
55
Move(const std::string & logType,const std::string & logName,const std::string & dest)56 int32_t HiviewServiceAgent::Move(const std::string& logType, const std::string& logName, const std::string& dest)
57 {
58 return CopyOrMoveFile(logType, logName, dest, true);
59 }
60
CopyOrMoveFile(const std::string & logType,const std::string & logName,const std::string & dest,bool isMove)61 int32_t HiviewServiceAgent::CopyOrMoveFile(
62 const std::string& logType, const std::string& logName, const std::string& dest, bool isMove)
63 {
64 if (!CheckAndCreateHiviewDir(dest)) {
65 HIVIEW_LOGE("create dirs failed.");
66 return HiviewNapiErrCode::ERR_DEFAULT;
67 }
68 auto service = GetRemoteService();
69 if (service == nullptr) {
70 HIVIEW_LOGE("cannot get service.");
71 return HiviewNapiErrCode::ERR_DEFAULT;
72 }
73 HiviewServiceAbilityProxy proxy(service);
74 return isMove ? proxy.Move(logType, logName, dest) : proxy.Copy(logType, logName, dest);
75 }
76
Remove(const std::string & logType,const std::string & logName)77 int32_t HiviewServiceAgent::Remove(const std::string& logType, const std::string& logName)
78 {
79 auto service = GetRemoteService();
80 if (service == nullptr) {
81 HIVIEW_LOGE("cannot get service.");
82 return HiviewNapiErrCode::ERR_DEFAULT;
83 }
84 HiviewServiceAbilityProxy proxy(service);
85 return proxy.Remove(logType, logName);
86 }
87
GetRemoteService()88 sptr<IRemoteObject> HiviewServiceAgent::GetRemoteService()
89 {
90 std::lock_guard<std::mutex> proxyGuard(proxyMutex_);
91 if (hiviewServiceAbilityProxy_ != nullptr) {
92 return hiviewServiceAbilityProxy_;
93 }
94 HIVIEW_LOGI("refresh remote service instance.");
95 auto abilityManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
96 if (abilityManager == nullptr) {
97 return nullptr;
98 }
99 hiviewServiceAbilityProxy_ = abilityManager->CheckSystemAbility(DFX_SYS_HIVIEW_ABILITY_ID);
100 if (hiviewServiceAbilityProxy_ == nullptr) {
101 HIVIEW_LOGE("get hiview ability failed.");
102 return nullptr;
103 }
104 deathRecipient_ = sptr<IRemoteObject::DeathRecipient>(new HiviewServiceDeathRecipient(*this));
105 if (deathRecipient_ == nullptr) {
106 HIVIEW_LOGE("create service deathrecipient failed.");
107 hiviewServiceAbilityProxy_ = nullptr;
108 return nullptr;
109 }
110 hiviewServiceAbilityProxy_->AddDeathRecipient(deathRecipient_);
111 return hiviewServiceAbilityProxy_;
112 }
113
ProcessDeathObserver(const wptr<IRemoteObject> & remote)114 void HiviewServiceAgent::ProcessDeathObserver(const wptr<IRemoteObject>& remote)
115 {
116 std::lock_guard<std::mutex> proxyGuard(proxyMutex_);
117 if (hiviewServiceAbilityProxy_ == nullptr) {
118 HIVIEW_LOGW("hiview remote service died and local instance is null.");
119 return;
120 }
121 if (hiviewServiceAbilityProxy_ == remote.promote()) {
122 hiviewServiceAbilityProxy_->RemoveDeathRecipient(deathRecipient_);
123 hiviewServiceAbilityProxy_ = nullptr;
124 deathRecipient_ = nullptr;
125 HIVIEW_LOGW("hiview remote service died.");
126 } else {
127 HIVIEW_LOGW("unknown service died.");
128 }
129 }
130
CheckAndCreateHiviewDir(const std::string & destDir)131 bool HiviewServiceAgent::CheckAndCreateHiviewDir(const std::string& destDir)
132 {
133 if (destDir.find("..") != std::string::npos) {
134 HIVIEW_LOGE("invalid destDir: %{public}s", destDir.c_str());
135 return false;
136 }
137 std::shared_ptr<OHOS::AbilityRuntime::ApplicationContext> context =
138 OHOS::AbilityRuntime::Context::GetApplicationContext();
139 if (context == nullptr) {
140 HIVIEW_LOGE("Context is null.");
141 return false;
142 }
143 std::string baseDir = context->GetBaseDir();
144 std::string cacheDir = context->GetCacheDir();
145 if (baseDir.empty() || cacheDir.empty()) {
146 HIVIEW_LOGE("file dir is empty.");
147 return false;
148 }
149 int aclBaseRet = OHOS::StorageDaemon::AclSetAccess(baseDir, "g:1201:x");
150 int aclCacheRet = OHOS::StorageDaemon::AclSetAccess(cacheDir, "g:1201:x");
151 if (aclBaseRet != 0 || aclCacheRet != 0) {
152 HIVIEW_LOGE("set acl access for app failed.");
153 return false;
154 }
155 std::string hiviewDir = cacheDir + "/hiview";
156 if (!CreateAndGrantAclPermission(hiviewDir)) {
157 HIVIEW_LOGE("create hiview dir failed.");
158 return false;
159 }
160 if (!destDir.empty() && !CreateDestDirs(hiviewDir, destDir)) {
161 HIVIEW_LOGE("create dest dir failed.");
162 return false;
163 }
164 return true;
165 }
166
CreateDestDirs(const std::string & rootDir,const std::string & destDir)167 bool HiviewServiceAgent::CreateDestDirs(const std::string& rootDir, const std::string& destDir)
168 {
169 std::vector<std::string> dirNames;
170 StringUtil::SplitStr(destDir, "/", dirNames, false, true);
171 std::string fullPath(rootDir);
172 for (auto& dirName : dirNames) {
173 fullPath.append("/").append(dirName);
174 if (!CreateAndGrantAclPermission(fullPath)) {
175 return false;
176 }
177 }
178 return true;
179 }
180
CreateAndGrantAclPermission(const std::string & dirPath)181 bool HiviewServiceAgent::CreateAndGrantAclPermission(const std::string& dirPath)
182 {
183 if (!FileUtil::FileExists(dirPath) && !FileUtil::ForceCreateDirectory(dirPath)) {
184 HIVIEW_LOGE("create dir failed.");
185 return false;
186 }
187 if (OHOS::StorageDaemon::AclSetAccess(dirPath, "g:1201:rwx") != 0) {
188 HIVIEW_LOGE("set acl access failed.");
189 return false;
190 }
191 return true;
192 }
193 } // namespace HiviewDFX
194 } // namespace OHOS