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