1 /*
2  * Copyright (c) 2022-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 
16 #include "module_ipc/sa_backup_connection.h"
17 #include "b_error/b_error.h"
18 #include "b_error/b_excep_utils.h"
19 #include "filemgmt_libhilog.h"
20 #include "system_ability_definition.h"
21 
22 namespace OHOS::FileManagement::Backup {
23 using namespace std;
24 
ConnectBackupSAExt(std::string bundleName,std::string extension,std::string extInfo)25 ErrCode SABackupConnection::ConnectBackupSAExt(std::string bundleName, std::string extension, std::string extInfo)
26 {
27     bundleName_ = bundleName;
28     extension_ = extension;
29     extInfo_ = extInfo;
30     saId_ = std::atoi(bundleName.c_str());
31     return LoadBackupSAExt();
32 }
33 
DisconnectBackupSAExt()34 ErrCode SABackupConnection::DisconnectBackupSAExt()
35 {
36     HILOGI("called begin");
37     if (!isLoaded_.load() || !isConnected_.load() || !proxy_) {
38         HILOGD("No need to unload, connect first");
39         return BError(BError::Codes::OK);
40     }
41     isConnected_.store(false);
42     isLoaded_.store(false);
43     proxy_ = nullptr;
44     string().swap(bundleName_);
45     saId_ = BConstants::BACKUP_DEFAULT_SA_ID;
46     reloadNum_.store(0);
47     sptr<ISystemAbilityManager> samgrProxy = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
48         if (!samgrProxy) {
49         HILOGE("SamgrProxy is nullptr");
50         return BError(BError::Codes::SA_EXT_ERR_SAMGR);
51     }
52     int32_t result = samgrProxy->UnloadSystemAbility(saId_);
53     if (result != ERR_OK) {
54         HILOGE("UnloadSA, UnloadSystemAbility %{public}s result: %{public}d", bundleName_.c_str(), result);
55     }
56     return BError(BError::Codes::OK);
57 }
58 
IsSAExtConnected()59 bool SABackupConnection::IsSAExtConnected()
60 {
61     HILOGI("called begin");
62     return isConnected_.load();
63 }
64 
GetBackupSAExtProxy()65 sptr<ILocalAbilityManager> SABackupConnection::GetBackupSAExtProxy()
66 {
67     return proxy_;
68 }
69 
LoadBackupSAExt()70 ErrCode SABackupConnection::LoadBackupSAExt()
71 {
72     if (proxy_ && isConnected_.load()) {
73         HILOGI("SA %{public}d is running.", saId_);
74         callConnected_(move(bundleName_));
75         return BError(BError::Codes::OK);
76     }
77     if (reloadNum_.load() >= BConstants::BACKUP_SA_RELOAD_MAX) {
78         HILOGI("SA %{public}d reload done and return", saId_);
79         callDied_(move(bundleName_));
80         return BError(BError::Codes::SA_EXT_RELOAD_FAIL);
81     }
82     vector<ISystemAbilityManager::SaExtensionInfo> saExtentionInfos;
83     sptr<ISystemAbilityManager> samgrProxy = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
84     if (!samgrProxy) {
85         HILOGE("SamgrProxy is nullptr");
86         return BError(BError::Codes::SA_EXT_ERR_SAMGR);
87     }
88     int32_t ret = samgrProxy->GetRunningSaExtensionInfoList(extension_, saExtentionInfos);
89     if (ret != ERR_OK) {
90         HILOGE("GetExtensionSaIds err, ret %{public}d.", ret);
91         return BError(BError::Codes::SA_EXT_ERR_SAMGR);
92     }
93     for (ISystemAbilityManager::SaExtensionInfo saExtentionInfo : saExtentionInfos) {
94         if (saExtentionInfo.saId == saId_) {
95             isConnected_.store(true);
96             isLoaded_.store(false);
97             HILOGI("Get running sa proxy success.");
98             proxy_ = iface_cast<ILocalAbilityManager>(saExtentionInfo.processObj);
99             callConnected_(move(bundleName_));
100             return BError(BError::Codes::OK);
101         }
102     }
103     return LoadBackupSAExtInner();
104 }
105 
LoadBackupSAExtInner()106 ErrCode SABackupConnection::LoadBackupSAExtInner()
107 {
108     sptr<ISystemAbilityManager> samgrProxy = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
109     if (!samgrProxy) {
110         HILOGE("SamgrProxy is nullptr");
111         return BError(BError::Codes::SA_EXT_ERR_SAMGR);
112     }
113     sptr<SALoadCallback> loadCallback(new SALoadCallback());
114     if (loadCallback == nullptr) {
115         HILOGE("loadCallback is nullptr");
116         return BError(BError::Codes::SA_INVAL_ARG);
117     }
118     int32_t ret = samgrProxy->LoadSystemAbility(saId_, loadCallback);
119     if (ret != ERR_OK) {
120         HILOGE("Failed to Load systemAbility, systemAbility:%{private}d. ret code:%{public}d", saId_, ret);
121         return BError(BError::Codes::SA_EXT_ERR_SAMGR);
122     }
123     isLoaded_.store(true);
124     reloadNum_.store(reloadNum_.load() + 1);
125     unique_lock<mutex> lock(mutex_);
126     auto waitStatus =
127         loadCallback->proxyConVar_.wait_for(lock, std::chrono::milliseconds(BConstants::BACKUP_LOADSA_TIMEOUT_MS),
128                                             [loadCallback]() { return loadCallback->isLoadSuccess_.load(); });
129     if (!waitStatus) {
130         HILOGE("Load sa %{public}d timeout", saId_);
131         lock.unlock();
132         isConnected_.store(false);
133         return LoadBackupSAExt();
134     }
135     lock.unlock();
136     isConnected_.store(true);
137     return LoadBackupSAExt();
138 }
139 
InputParaSet(MessageParcel & data)140 bool SABackupConnection::InputParaSet(MessageParcel &data)
141 {
142     if (extension_ == BConstants::EXTENSION_BACKUP) {
143         if (!data.WriteString(extInfo_)) {
144             HILOGE("InputParaSet WriteString failed sa: %{public}d, extInfo: %{public}s, extension: %{public}s",
145                 saId_, extInfo_.c_str(), extension_.c_str());
146             return false;
147         }
148         return true;
149     } else if (extension_ == BConstants::EXTENSION_RESTORE) {
150         if (!data.WriteFileDescriptor(fd_) || !data.WriteString(extInfo_)) {
151             HILOGE("InputParaSet WriteString failed sa: %{public}d, extension: %{public}s",
152                 saId_, extension_.c_str());
153             return false;
154         }
155         return true;
156     }
157 
158     HILOGD("SABackupExtentionPara InFunc sa: %{public}d, extension: %{public}s", saId_, extension_.c_str());
159     return false;
160 }
161 
OutputParaGet(MessageParcel & reply)162 bool SABackupConnection::OutputParaGet(MessageParcel &reply)
163 {
164     parcel_.ClearFileDescriptor();
165     if (!parcel_.Append(reply)) {
166         HILOGE("OutputParaGet append failed sa is %{public}d, extension: %{public}s", saId_, extension_.c_str());
167         return false;
168     }
169     HILOGD("SABackupExtentionPara OutFunc sa is %{public}d, extension: %{public}s", saId_, extension_.c_str());
170     return true;
171 }
172 
CallBackupSA()173 ErrCode SABackupConnection::CallBackupSA()
174 {
175     auto task = [this]() {
176         HILOGI("called begin");
177         if (proxy_) {
178             HILOGI("SA backup called begin");
179             int32_t ret = proxy_->SystemAbilityExtProc(BConstants::EXTENSION_BACKUP, saId_, this);
180             HILOGI("SA backup done %{public}d", ret);
181             int fd = parcel_.ReadFileDescriptor();
182             std::string result = parcel_.ReadString();
183             callBackup_(move(bundleName_), move(fd), move(result), move(ret));
184         }
185     };
186 
187     threadPool_.AddTask([task]() {
188         try {
189             task();
190         } catch (...) {
191             HILOGE("Failed to add task to thread pool");
192         }
193     });
194     return BError(BError::Codes::OK);
195 }
196 
CallRestoreSA(UniqueFd fd)197 ErrCode SABackupConnection::CallRestoreSA(UniqueFd fd)
198 {
199     fd_ = move(fd);
200     auto task = [this]() {
201         HILOGI("called begin");
202         if (proxy_) {
203             HILOGI("SA restore called begin");
204             int32_t ret = proxy_->SystemAbilityExtProc(BConstants::EXTENSION_RESTORE, saId_, this);
205             HILOGI("SA restore done %{public}d", ret);
206             std::string result = parcel_.ReadString();
207             callRestore_(move(bundleName_), move(result), move(ret));
208         }
209     };
210 
211     threadPool_.AddTask([task]() {
212         try {
213             task();
214         } catch (...) {
215             HILOGE("Failed to add task to thread pool");
216         }
217     });
218     return BError(BError::Codes::OK);
219 }
220 
OnLoadSystemAbilitySuccess(int32_t systemAbilityId,const OHOS::sptr<IRemoteObject> & remoteObject)221 void SABackupConnection::SALoadCallback::OnLoadSystemAbilitySuccess(int32_t systemAbilityId,
222                                                                     const OHOS::sptr<IRemoteObject> &remoteObject)
223 {
224     HILOGI("Load backup sa success, systemAbilityId: %{private}d, remoteObject result:%{private}s", systemAbilityId,
225            (remoteObject != nullptr) ? "true" : "false");
226     if (remoteObject == nullptr) {
227         isLoadSuccess_.store(false);
228         proxyConVar_.notify_one();
229         return;
230     }
231     isLoadSuccess_.store(true);
232     proxyConVar_.notify_one();
233 }
234 
OnLoadSystemAbilityFail(int32_t systemAbilityId)235 void SABackupConnection::SALoadCallback::OnLoadSystemAbilityFail(int32_t systemAbilityId)
236 {
237     HILOGE("Load backup sa failed, systemAbilityId:%{private}d", systemAbilityId);
238     isLoadSuccess_.store(false);
239     proxyConVar_.notify_one();
240 }
241 } // namespace OHOS::FileManagement::Backup
242