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/service.h"
17
18 #include <algorithm>
19 #include <chrono>
20 #include <cerrno>
21 #include <cstddef>
22 #include <cstdint>
23 #include <cstring>
24 #include <regex>
25
26 #include <fcntl.h>
27 #include <iomanip>
28 #include <sys/stat.h>
29 #include <sys/types.h>
30 #include <sys/vfs.h>
31
32 #include <directory_ex.h>
33
34 #include "ability_manager_client.h"
35 #include "accesstoken_kit.h"
36 #include "b_anony/b_anony.h"
37 #include "b_error/b_error.h"
38 #include "b_error/b_excep_utils.h"
39 #include "b_file_info.h"
40 #include "b_json/b_json_cached_entity.h"
41 #include "b_jsonutil/b_jsonutil.h"
42 #include "b_ohos/startup/backup_para.h"
43 #include "b_process/b_multiuser.h"
44 #include "b_radar/b_radar.h"
45 #include "b_resources/b_constants.h"
46 #include "b_sa/b_sa_utils.h"
47 #include "bundle_mgr_client.h"
48 #include "filemgmt_libhilog.h"
49 #include "hisysevent.h"
50 #include "hitrace_meter.h"
51 #include "ipc_skeleton.h"
52 #include "access_token.h"
53 #include "tokenid_kit.h"
54 #include "module_app_gallery/app_gallery_dispose_proxy.h"
55 #include "module_external/bms_adapter.h"
56 #include "module_external/sms_adapter.h"
57 #include "module_ipc/svc_backup_connection.h"
58 #include "module_ipc/svc_restore_deps_manager.h"
59 #include "module_notify/notify_work_service.h"
60 #include "parameter.h"
61 #include "parameters.h"
62 #include "system_ability_definition.h"
63
64 namespace OHOS::FileManagement::Backup {
65 using namespace std;
66
MakeDetailList(const vector<BundleName> & bundleNames)67 vector<BIncrementalData> Service::MakeDetailList(const vector<BundleName> &bundleNames)
68 {
69 vector<BIncrementalData> bundleDetails {};
70 for (auto bundleName : bundleNames) {
71 bundleDetails.emplace_back(BIncrementalData {bundleName, 0});
72 }
73 return bundleDetails;
74 }
75
Finish()76 ErrCode Service::Finish()
77 {
78 HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__);
79 try {
80 VerifyCaller(session_->GetScenario());
81 session_->Finish();
82 OnAllBundlesFinished(BError(BError::Codes::OK));
83 return BError(BError::Codes::OK);
84 } catch (const BError &e) {
85 ReleaseOnException();
86 HILOGE("Failde to Finish");
87 return e.GetCode();
88 }
89 }
90
PublishFile(const BFileInfo & fileInfo)91 ErrCode Service::PublishFile(const BFileInfo &fileInfo)
92 {
93 HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__);
94 try {
95 VerifyCaller(IServiceReverse::Scenario::RESTORE);
96 if (!fileInfo.fileName.empty()) {
97 HILOGE("Forbit to use publishFile with fileName for App");
98 return EPERM;
99 }
100 auto backUpConnection = session_->GetExtConnection(fileInfo.owner);
101 if (backUpConnection == nullptr) {
102 HILOGE("PublishFile error, backUpConnection is empty");
103 return BError(BError::Codes::SA_INVAL_ARG);
104 }
105 auto proxy = backUpConnection->GetBackupExtProxy();
106 if (!proxy) {
107 HILOGE("PublishFile error, Extension backup Proxy is empty");
108 return BError(BError::Codes::SA_INVAL_ARG);
109 }
110 ErrCode res = proxy->PublishFile(fileInfo.fileName);
111 if (res) {
112 HILOGE("Failed to publish file for backup extension");
113 }
114 return res;
115 } catch (const BError &e) {
116 return e.GetCode();
117 } catch (const exception &e) {
118 HILOGI("Catched an unexpected low-level exception %{public}s", e.what());
119 return EPERM;
120 } catch (...) {
121 HILOGI("Unexpected exception");
122 return EPERM;
123 }
124 }
125
AppFileReady(const string & fileName,UniqueFd fd,int32_t errCode)126 ErrCode Service::AppFileReady(const string &fileName, UniqueFd fd, int32_t errCode)
127 {
128 HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__);
129 try {
130 string callerName = VerifyCallerAndGetCallerName();
131 if (fileName.find('/') != string::npos) {
132 throw BError(BError::Codes::SA_INVAL_ARG, "Filename is not valid");
133 }
134 if (fileName == BConstants::EXT_BACKUP_MANAGE) {
135 fd = session_->OnBundleExtManageInfo(callerName, move(fd));
136 }
137 session_->GetServiceReverseProxy()->BackupOnFileReady(callerName, fileName, move(fd), errCode);
138 FileReadyRadarReport(callerName, fileName, errCode, session_->GetScenario());
139 if (session_->OnBundleFileReady(callerName, fileName)) {
140 auto backUpConnection = session_->GetExtConnection(callerName);
141 if (backUpConnection == nullptr) {
142 HILOGE("AppFileReady error, backUpConnection is empty");
143 return BError(BError::Codes::SA_INVAL_ARG);
144 }
145 auto proxy = backUpConnection->GetBackupExtProxy();
146 if (!proxy) {
147 HILOGE("AppFileReady error, Extension backup Proxy is empty");
148 return BError(BError::Codes::SA_INVAL_ARG);
149 }
150 // 通知extension清空缓存
151 proxy->HandleClear();
152 // 清除Timer
153 session_->StopFwkTimer(callerName);
154 session_->StopExtTimer(callerName);
155 // 通知TOOL 备份完成
156 session_->GetServiceReverseProxy()->BackupOnBundleFinished(BError(BError::Codes::OK), callerName);
157 BundleEndRadarReport(callerName, BError(BError::Codes::OK), session_->GetScenario());
158 // 断开extension
159 backUpConnection->DisconnectBackupExtAbility();
160 ClearSessionAndSchedInfo(callerName);
161 }
162 OnAllBundlesFinished(BError(BError::Codes::OK));
163 return BError(BError::Codes::OK);
164 } catch (const BError &e) {
165 return e.GetCode(); // 任意异常产生,终止监听该任务
166 } catch (const exception &e) {
167 HILOGI("Catched an unexpected low-level exception %{public}s", e.what());
168 return EPERM;
169 } catch (...) {
170 HILOGI("Unexpected exception");
171 return EPERM;
172 }
173 }
174
AppDone(ErrCode errCode)175 ErrCode Service::AppDone(ErrCode errCode)
176 {
177 HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__);
178 try {
179 if (session_ == nullptr) {
180 HILOGE("App finish error, session info is empty");
181 return BError(BError::Codes::SA_INVAL_ARG);
182 }
183 string callerName = VerifyCallerAndGetCallerName();
184 HILOGI("Begin, callerName is: %{public}s, errCode: %{public}d", callerName.c_str(), errCode);
185 if (session_->OnBundleFileReady(callerName) || errCode != BError(BError::Codes::OK)) {
186 std::shared_ptr<ExtensionMutexInfo> mutexPtr = GetExtensionMutex(callerName);
187 if (mutexPtr == nullptr) {
188 HILOGE("extension mutex ptr is nullptr");
189 return BError(BError::Codes::SA_INVAL_ARG);
190 }
191 std::lock_guard<std::mutex> lock(mutexPtr->callbackMutex);
192 auto backUpConnection = session_->GetExtConnection(callerName);
193 if (backUpConnection == nullptr) {
194 HILOGE("App finish error, backUpConnection is empty");
195 return BError(BError::Codes::SA_INVAL_ARG);
196 }
197 auto proxy = backUpConnection->GetBackupExtProxy();
198 if (!proxy) {
199 throw BError(BError::Codes::SA_INVAL_ARG, "Extension backup Proxy is empty");
200 }
201 proxy->HandleClear();
202 session_->StopFwkTimer(callerName);
203 session_->StopExtTimer(callerName);
204 backUpConnection->DisconnectBackupExtAbility();
205 ClearSessionAndSchedInfo(callerName);
206 NotifyCallerCurAppDone(errCode, callerName);
207 }
208 RemoveExtensionMutex(callerName);
209 OnAllBundlesFinished(BError(BError::Codes::OK));
210 return BError(BError::Codes::OK);
211 } catch (const BError &e) {
212 ReleaseOnException();
213 HILOGE("AppDone error, err code is: %{public}d", e.GetCode());
214 return e.GetCode(); // 任意异常产生,终止监听该任务
215 } catch (const exception &e) {
216 ReleaseOnException();
217 HILOGI("Catched an unexpected low-level exception %{public}s", e.what());
218 return EPERM;
219 } catch (...) {
220 HILOGI("Unexpected exception");
221 return EPERM;
222 }
223 }
224
LaunchBackupExtension(const BundleName & bundleName)225 ErrCode Service::LaunchBackupExtension(const BundleName &bundleName)
226 {
227 HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__);
228 try {
229 HILOGI("begin %{public}s", bundleName.data());
230 IServiceReverse::Scenario scenario = session_->GetScenario();
231 BConstants::ExtensionAction action;
232 if (scenario == IServiceReverse::Scenario::BACKUP || scenario == IServiceReverse::Scenario::CLEAN) {
233 action = BConstants::ExtensionAction::BACKUP;
234 } else if (scenario == IServiceReverse::Scenario::RESTORE) {
235 action = BConstants::ExtensionAction::RESTORE;
236 } else {
237 throw BError(BError::Codes::SA_INVAL_ARG, "Failed to scenario");
238 }
239 if (SAUtils::IsSABundleName(bundleName)) {
240 return LaunchBackupSAExtension(bundleName);
241 }
242 AAFwk::Want want;
243 SetWant(want, bundleName, action);
244 auto backUpConnection = session_->GetExtConnection(bundleName);
245 if (backUpConnection == nullptr) {
246 HILOGE("LaunchBackupExtension error, backUpConnection is empty");
247 return BError(BError::Codes::SA_INVAL_ARG);
248 }
249 if (backUpConnection->IsExtAbilityConnected() && !backUpConnection->WaitDisconnectDone()) {
250 HILOGE("LaunchBackupExtension error, WaitDisconnectDone failed");
251 return BError(BError::Codes::SA_INVAL_ARG);
252 }
253 ErrCode ret = backUpConnection->ConnectBackupExtAbility(want, session_->GetSessionUserId());
254 if (ret) {
255 HILOGE("ConnectBackupExtAbility faild, bundleName:%{public}s, ret:%{public}d", bundleName.c_str(), ret);
256 ExtensionConnectFailRadarReport(bundleName, ret, scenario);
257 return BError(BError::Codes::SA_BOOT_EXT_FAIL);
258 }
259 return BError(BError::Codes::OK);
260 } catch (const BError &e) {
261 return e.GetCode();
262 } catch (const exception &e) {
263 HILOGI("Catched an unexpected low-level exception %{public}s", e.what());
264 return EPERM;
265 } catch (...) {
266 HILOGI("Unexpected exception");
267 return EPERM;
268 }
269 }
270
SetWant(AAFwk::Want & want,const BundleName & bundleName,const BConstants::ExtensionAction & action)271 void Service::SetWant(AAFwk::Want &want, const BundleName &bundleName, const BConstants::ExtensionAction &action)
272 {
273 BJsonUtil::BundleDetailInfo bundleDetail = BJsonUtil::ParseBundleNameIndexStr(bundleName);
274 string backupExtName = session_->GetBackupExtName(bundleName); /* new device app ext name */
275 HILOGI("BackupExtName: %{public}s, bundleName: %{public}s", backupExtName.data(), bundleName.data());
276 string versionName = session_->GetBundleVersionName(bundleName); /* old device app version name */
277 int64_t versionCode = session_->GetBundleVersionCode(bundleName); /* old device app version code */
278 RestoreTypeEnum restoreType = session_->GetBundleRestoreType(bundleName); /* app restore type */
279 string bundleExtInfo = session_->GetBackupExtInfo(bundleName);
280 HILOGI("BundleExtInfo is:%{public}s", GetAnonyString(bundleExtInfo).c_str());
281 want.SetElementName(bundleDetail.bundleName, backupExtName);
282 want.SetParam(BConstants::EXTENSION_ACTION_PARA, static_cast<int>(action));
283 want.SetParam(BConstants::EXTENSION_VERSION_CODE_PARA, static_cast<long>(versionCode));
284 want.SetParam(BConstants::EXTENSION_RESTORE_TYPE_PARA, static_cast<int>(restoreType));
285 want.SetParam(BConstants::EXTENSION_VERSION_NAME_PARA, versionName);
286 want.SetParam(BConstants::EXTENSION_RESTORE_EXT_INFO_PARA, bundleExtInfo);
287 want.SetParam(BConstants::EXTENSION_BACKUP_EXT_INFO_PARA, bundleExtInfo);
288 want.SetParam(BConstants::EXTENSION_APP_CLONE_INDEX_PARA, bundleDetail.bundleIndex);
289 }
290
GetSupportBackupBundleNames(vector<BJsonEntityCaps::BundleInfo> & backupInfos,bool isIncBackup,const std::vector<std::string> & srcBundleNames)291 std::vector<std::string> Service::GetSupportBackupBundleNames(vector<BJsonEntityCaps::BundleInfo> &backupInfos,
292 bool isIncBackup, const std::vector<std::string> &srcBundleNames)
293 {
294 HILOGI("Begin");
295 std::vector<std::string> supportBackupNames;
296 for (auto info : backupInfos) {
297 HILOGI("Current backupInfo bundleName:%{public}s, index:%{public}d, extName:%{public}s", info.name.c_str(),
298 info.appIndex, info.extensionName.c_str());
299 std::string bundleNameIndexInfo = BJsonUtil::BuildBundleNameIndexInfo(info.name, info.appIndex);
300 if (!info.allToBackup) {
301 if (isIncBackup) {
302 session_->GetServiceReverseProxy()->IncrementalBackupOnBundleStarted(
303 BError(BError::Codes::SA_FORBID_BACKUP_RESTORE), bundleNameIndexInfo);
304 } else {
305 session_->GetServiceReverseProxy()->BackupOnBundleStarted(
306 BError(BError::Codes::SA_FORBID_BACKUP_RESTORE), bundleNameIndexInfo);
307 }
308 BundleBeginRadarReport(bundleNameIndexInfo, BError(BError::Codes::SA_FORBID_BACKUP_RESTORE).GetCode(),
309 IServiceReverse::Scenario::BACKUP);
310 continue;
311 }
312 supportBackupNames.emplace_back(bundleNameIndexInfo);
313 }
314 HandleNotSupportBundleNames(srcBundleNames, supportBackupNames, isIncBackup);
315 HILOGI("End");
316 return supportBackupNames;
317 }
318
SetCurrentSessProperties(BJsonEntityCaps::BundleInfo & info,std::map<std::string,bool> & isClearDataFlags,const std::string & bundleNameIndexInfo)319 void Service::SetCurrentSessProperties(BJsonEntityCaps::BundleInfo &info,
320 std::map<std::string, bool> &isClearDataFlags, const std::string &bundleNameIndexInfo)
321 {
322 HILOGI("Begin");
323 if (session_ == nullptr) {
324 HILOGE("Set currrent session properties error, session is empty");
325 return;
326 }
327 session_->SetBundleDataSize(bundleNameIndexInfo, info.spaceOccupied);
328 auto iter = isClearDataFlags.find(bundleNameIndexInfo);
329 if (iter != isClearDataFlags.end()) {
330 session_->SetClearDataFlag(bundleNameIndexInfo, iter->second);
331 }
332 HILOGI("End");
333 }
334
HandleNotSupportBundleNames(const std::vector<std::string> & srcBundleNames,std::vector<std::string> & supportBundleNames,bool isIncBackup)335 void Service::HandleNotSupportBundleNames(const std::vector<std::string> &srcBundleNames,
336 std::vector<std::string> &supportBundleNames, bool isIncBackup)
337 {
338 for (auto bundleName : srcBundleNames) {
339 auto it = std::find(supportBundleNames.begin(), supportBundleNames.end(), bundleName);
340 if (it != supportBundleNames.end()) {
341 continue;
342 }
343 HILOGE("bundleName:%{public}s, can not find from supportBundleNames", bundleName.c_str());
344 if (isIncBackup) {
345 session_->GetServiceReverseProxy()->IncrementalBackupOnBundleStarted(
346 BError(BError::Codes::SA_BUNDLE_INFO_EMPTY), bundleName);
347 } else {
348 session_->GetServiceReverseProxy()->BackupOnBundleStarted(
349 BError(BError::Codes::SA_BUNDLE_INFO_EMPTY), bundleName);
350 }
351 }
352 }
353 }
354