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 /*
17 * 注意:
18 * - 注意点1:本文件原则上只处理与IPC无关的业务逻辑
19 * - 注意点2:This document, in principle, captures all exceptions.
20 * Prevent exceptions from spreading to insecure modules.
21 */
22 #include "module_ipc/service.h"
23
24 #include <algorithm>
25 #include <cerrno>
26 #include <cstddef>
27 #include <cstdint>
28 #include <cstring>
29 #include <regex>
30
31 #include <fcntl.h>
32 #include <sys/stat.h>
33 #include <sys/types.h>
34 #include <sys/vfs.h>
35
36 #include <directory_ex.h>
37
38 #include "ability_manager_client.h"
39 #include "accesstoken_kit.h"
40 #include "b_error/b_error.h"
41 #include "b_error/b_excep_utils.h"
42 #include "b_file_info.h"
43 #include "b_json/b_json_cached_entity.h"
44 #include "b_json/b_json_entity_caps.h"
45 #include "b_ohos/startup/backup_para.h"
46 #include "b_process/b_multiuser.h"
47 #include "b_resources/b_constants.h"
48 #include "bundle_mgr_client.h"
49 #include "filemgmt_libhilog.h"
50 #include "ipc_skeleton.h"
51 #include "module_app_gallery/app_gallery_dispose_proxy.h"
52 #include "module_external/bms_adapter.h"
53 #include "module_external/sms_adapter.h"
54 #include "module_ipc/svc_backup_connection.h"
55 #include "module_ipc/svc_restore_deps_manager.h"
56 #include "parameter.h"
57 #include "system_ability_definition.h"
58
59 namespace OHOS::FileManagement::Backup {
60 using namespace std;
61
62 REGISTER_SYSTEM_ABILITY_BY_ID(Service, FILEMANAGEMENT_BACKUP_SERVICE_SA_ID, false);
63
64 namespace {
65 constexpr int32_t DEBUG_ID = 100;
66 } // namespace
67
68 /* Shell/Xts user id equal to 0/1, we need set default 100 */
GetUserIdDefault()69 static inline int32_t GetUserIdDefault()
70 {
71 auto [isDebug, debugId] = BackupPara().GetBackupDebugOverrideAccount();
72 if (isDebug && debugId > DEBUG_ID) {
73 return debugId;
74 }
75 auto multiuser = BMultiuser::ParseUid(IPCSkeleton::GetCallingUid());
76 if ((multiuser.userId == BConstants::SYSTEM_UID) || (multiuser.userId == BConstants::XTS_UID)) {
77 return BConstants::DEFAULT_USER_ID;
78 }
79 return multiuser.userId;
80 }
81
OnStart()82 void Service::OnStart()
83 {
84 bool res = SystemAbility::Publish(sptr(this));
85 sched_ = sptr(new SchedScheduler(wptr(this), wptr(session_)));
86 sched_->StartTimer();
87 HILOGI("End, res = %{public}d", res);
88 }
89
OnStop()90 void Service::OnStop()
91 {
92 HILOGI("Called");
93 int32_t oldMemoryParaSize = BConstants::DEFAULT_VFS_CACHE_PRESSURE;
94 if (session_ != nullptr) {
95 oldMemoryParaSize = session_->GetMemParaCurSize();
96 }
97 StorageMgrAdapter::UpdateMemPara(oldMemoryParaSize);
98 }
99
GetLocalCapabilities()100 UniqueFd Service::GetLocalCapabilities()
101 {
102 try {
103 HILOGI("Begin");
104 /*
105 Only called by restore app before InitBackupSession,
106 so there must be set init userId.
107 */
108 session_->IncreaseSessionCnt();
109 session_->SetSessionUserId(GetUserIdDefault());
110 VerifyCaller();
111 string path = BConstants::GetSaBundleBackupRootDir(session_->GetSessionUserId());
112 BExcepUltils::VerifyPath(path, false);
113 BJsonCachedEntity<BJsonEntityCaps> cachedEntity(
114 UniqueFd(open(path.data(), O_TMPFILE | O_RDWR, S_IRUSR | S_IWUSR)));
115
116 auto cache = cachedEntity.Structuralize();
117
118 cache.SetSystemFullName(GetOSFullName());
119 cache.SetDeviceType(GetDeviceType());
120 auto bundleInfos = BundleMgrAdapter::GetBundleInfos(session_->GetSessionUserId());
121 cache.SetBundleInfos(bundleInfos);
122 cachedEntity.Persist();
123 session_->DecreaseSessionCnt();
124 return move(cachedEntity.GetFd());
125 } catch (const BError &e) {
126 session_->DecreaseSessionCnt();
127 HILOGE("GetLocalCapabilities failed, errCode = %{public}d", e.GetCode());
128 return UniqueFd(-e.GetCode());
129 } catch (const exception &e) {
130 session_->DecreaseSessionCnt();
131 HILOGI("Catched an unexpected low-level exception %{public}s", e.what());
132 return UniqueFd(-EPERM);
133 } catch (...) {
134 session_->DecreaseSessionCnt();
135 HILOGI("Unexpected exception");
136 return UniqueFd(-EPERM);
137 }
138 }
139
StopAll(const wptr<IRemoteObject> & obj,bool force)140 void Service::StopAll(const wptr<IRemoteObject> &obj, bool force)
141 {
142 session_->Deactive(obj, force);
143 }
144
VerifyCallerAndGetCallerName()145 string Service::VerifyCallerAndGetCallerName()
146 {
147 uint32_t tokenCaller = IPCSkeleton::GetCallingTokenID();
148 int tokenType = Security::AccessToken::AccessTokenKit::GetTokenType(tokenCaller);
149 if (tokenType == Security::AccessToken::ATokenTypeEnum::TOKEN_HAP) {
150 Security::AccessToken::HapTokenInfo hapTokenInfo;
151 if (Security::AccessToken::AccessTokenKit::GetHapTokenInfo(tokenCaller, hapTokenInfo) != 0) {
152 throw BError(BError::Codes::SA_INVAL_ARG, "Get hap token info failed");
153 }
154 session_->VerifyBundleName(hapTokenInfo.bundleName);
155 return hapTokenInfo.bundleName;
156 } else {
157 HILOGE("tokenID = %{private}d", tokenCaller);
158 throw BError(BError::Codes::SA_INVAL_ARG, string("Invalid token type ").append(to_string(tokenType)));
159 }
160 }
161
VerifyCaller()162 void Service::VerifyCaller()
163 {
164 uint32_t tokenCaller = IPCSkeleton::GetCallingTokenID();
165 int tokenType = Security::AccessToken::AccessTokenKit::GetTokenType(tokenCaller);
166 switch (tokenType) {
167 case Security::AccessToken::ATokenTypeEnum::TOKEN_NATIVE: /* Update Service */
168 case Security::AccessToken::ATokenTypeEnum::TOKEN_HAP: {
169 const string permission = "ohos.permission.BACKUP";
170 if (Security::AccessToken::AccessTokenKit::VerifyAccessToken(tokenCaller, permission) ==
171 Security::AccessToken::TypePermissionState::PERMISSION_DENIED) {
172 throw BError(BError::Codes::SA_INVAL_ARG,
173 string("Permission denied, token type is ").append(to_string(tokenType)));
174 }
175 break;
176 }
177 case Security::AccessToken::ATokenTypeEnum::TOKEN_SHELL:
178 if (IPCSkeleton::GetCallingUid() != BConstants::SYSTEM_UID) {
179 throw BError(BError::Codes::SA_INVAL_ARG, "Calling uid is invalid");
180 }
181 break;
182 default:
183 throw BError(BError::Codes::SA_INVAL_ARG, string("Invalid token type ").append(to_string(tokenType)));
184 break;
185 }
186 }
187
VerifyCaller(IServiceReverse::Scenario scenario)188 void Service::VerifyCaller(IServiceReverse::Scenario scenario)
189 {
190 session_->VerifyCallerAndScenario(IPCSkeleton::GetCallingTokenID(), scenario);
191 VerifyCaller();
192 }
193
InitRestoreSession(sptr<IServiceReverse> remote)194 ErrCode Service::InitRestoreSession(sptr<IServiceReverse> remote)
195 {
196 try {
197 VerifyCaller();
198 session_->Active({
199 .clientToken = IPCSkeleton::GetCallingTokenID(),
200 .scenario = IServiceReverse::Scenario::RESTORE,
201 .clientProxy = remote,
202 .userId = GetUserIdDefault(),
203 });
204 return BError(BError::Codes::OK);
205 } catch (const BError &e) {
206 StopAll(nullptr, true);
207 return e.GetCode();
208 } catch (const exception &e) {
209 HILOGI("Catched an unexpected low-level exception %{public}s", e.what());
210 return EPERM;
211 } catch (...) {
212 HILOGI("Unexpected exception");
213 return EPERM;
214 }
215 }
216
InitBackupSession(sptr<IServiceReverse> remote)217 ErrCode Service::InitBackupSession(sptr<IServiceReverse> remote)
218 {
219 try {
220 VerifyCaller();
221 int32_t oldSize = StorageMgrAdapter::UpdateMemPara(BConstants::BACKUP_VFS_CACHE_PRESSURE);
222 HILOGE("InitBackupSession oldSize %{public}d", oldSize);
223 session_->SetMemParaCurSize(oldSize);
224 session_->Active({
225 .clientToken = IPCSkeleton::GetCallingTokenID(),
226 .scenario = IServiceReverse::Scenario::BACKUP,
227 .clientProxy = remote,
228 .userId = GetUserIdDefault(),
229 });
230 return BError(BError::Codes::OK);
231 } catch (const BError &e) {
232 StopAll(nullptr, true);
233 return e.GetCode();
234 }
235 }
236
Start()237 ErrCode Service::Start()
238 {
239 HILOGI("Begin");
240 VerifyCaller(session_->GetScenario());
241 session_->Start();
242 OnStartSched();
243 return BError(BError::Codes::OK);
244 }
245
SpeicalVersion(const string & versionName,uint32_t versionCode)246 static bool SpeicalVersion(const string &versionName, uint32_t versionCode)
247 {
248 auto iter = find_if(BConstants::DEFAULT_VERSION_NAMES_VEC.begin(), BConstants::DEFAULT_VERSION_NAMES_VEC.end(),
249 [&versionName](const auto &version) { return version == versionName; });
250 if (versionCode == BConstants::DEFAULT_VERSION_CODE && iter != BConstants::DEFAULT_VERSION_NAMES_VEC.end()) {
251 return true;
252 }
253 return false;
254 }
255
GetRestoreBundleNames(UniqueFd fd,sptr<SvcSessionManager> session,const vector<BundleName> & bundleNames)256 static vector<BJsonEntityCaps::BundleInfo> GetRestoreBundleNames(UniqueFd fd,
257 sptr<SvcSessionManager> session,
258 const vector<BundleName> &bundleNames)
259 {
260 // BundleMgrAdapter::GetBundleInfos可能耗时
261 auto restoreInfos = BundleMgrAdapter::GetBundleInfos(bundleNames, session->GetSessionUserId());
262 BJsonCachedEntity<BJsonEntityCaps> cachedEntity(move(fd));
263 auto cache = cachedEntity.Structuralize();
264 auto bundleInfos = cache.GetBundleInfos();
265 if (!bundleInfos.size()) {
266 throw BError(BError::Codes::SA_INVAL_ARG, "Json entity caps is empty");
267 }
268 vector<BJsonEntityCaps::BundleInfo> restoreBundleInfos {};
269 for (auto &restoreInfo : restoreInfos) {
270 auto it = find_if(bundleInfos.begin(), bundleInfos.end(),
271 [&restoreInfo](const auto &obj) { return obj.name == restoreInfo.name; });
272 if (it == bundleInfos.end()) {
273 session->GetServiceReverseProxy()->RestoreOnBundleStarted(BError(BError::Codes::SA_BUNDLE_INFO_EMPTY),
274 restoreInfo.name);
275 continue;
276 }
277 BJsonEntityCaps::BundleInfo info = {.name = (*it).name,
278 .versionCode = (*it).versionCode,
279 .versionName = (*it).versionName,
280 .spaceOccupied = (*it).spaceOccupied,
281 .allToBackup = (*it).allToBackup,
282 .extensionName = restoreInfo.extensionName,
283 .restoreDeps = restoreInfo.restoreDeps};
284 restoreBundleInfos.emplace_back(info);
285 }
286 return restoreBundleInfos;
287 }
288
AppendBundlesRestoreSession(UniqueFd fd,const vector<BundleName> & bundleNames,RestoreTypeEnum restoreType,int32_t userId)289 ErrCode Service::AppendBundlesRestoreSession(UniqueFd fd,
290 const vector<BundleName> &bundleNames,
291 RestoreTypeEnum restoreType,
292 int32_t userId)
293 {
294 try {
295 HILOGI("Begin");
296 session_->IncreaseSessionCnt();
297 if (userId != DEFAULT_INVAL_VALUE) { /* multi user scenario */
298 session_->SetSessionUserId(userId);
299 }
300 VerifyCaller(IServiceReverse::Scenario::RESTORE);
301 auto restoreInfos = GetRestoreBundleNames(move(fd), session_, bundleNames);
302 auto restoreBundleNames = SvcRestoreDepsManager::GetInstance().GetRestoreBundleNames(restoreInfos, restoreType);
303 if (restoreBundleNames.empty()) {
304 session_->DecreaseSessionCnt();
305 return BError(BError::Codes::OK);
306 }
307 session_->AppendBundles(restoreBundleNames);
308 for (auto restoreInfo : restoreInfos) {
309 auto it = find_if(restoreBundleNames.begin(), restoreBundleNames.end(),
310 [&restoreInfo](const auto &bundleName) { return bundleName == restoreInfo.name; });
311 if (it == restoreBundleNames.end()) {
312 throw BError(BError::Codes::SA_BUNDLE_INFO_EMPTY, "Can't find bundle name");
313 }
314 HILOGD("bundleName: %{public}s, extensionName: %{public}s", restoreInfo.name.c_str(),
315 restoreInfo.extensionName.c_str());
316 if ((restoreInfo.allToBackup == false &&
317 !SpeicalVersion(restoreInfo.versionName, restoreInfo.versionCode)) ||
318 restoreInfo.extensionName.empty()) {
319 session_->GetServiceReverseProxy()->RestoreOnBundleStarted(
320 BError(BError::Codes::SA_FORBID_BACKUP_RESTORE), restoreInfo.name);
321 session_->RemoveExtInfo(restoreInfo.name);
322 continue;
323 }
324 session_->SetBundleRestoreType(restoreInfo.name, restoreType);
325 session_->SetBundleVersionCode(restoreInfo.name, restoreInfo.versionCode);
326 session_->SetBundleVersionName(restoreInfo.name, restoreInfo.versionName);
327 session_->SetBundleDataSize(restoreInfo.name, restoreInfo.spaceOccupied);
328 session_->SetBackupExtName(restoreInfo.name, restoreInfo.extensionName);
329 }
330 OnStartSched();
331 session_->DecreaseSessionCnt();
332 return BError(BError::Codes::OK);
333 } catch (const BError &e) {
334 session_->DecreaseSessionCnt();
335 return e.GetCode();
336 } catch (...) {
337 session_->DecreaseSessionCnt();
338 HILOGI("Unexpected exception");
339 return EPERM;
340 }
341 }
342
AppendBundlesBackupSession(const vector<BundleName> & bundleNames)343 ErrCode Service::AppendBundlesBackupSession(const vector<BundleName> &bundleNames)
344 {
345 try {
346 HILOGI("Begin");
347 session_->IncreaseSessionCnt(); // BundleMgrAdapter::GetBundleInfos可能耗时
348 VerifyCaller(IServiceReverse::Scenario::BACKUP);
349 auto backupInfos = BundleMgrAdapter::GetBundleInfos(bundleNames, session_->GetSessionUserId());
350 session_->AppendBundles(bundleNames);
351 for (auto info : backupInfos) {
352 session_->SetBundleDataSize(info.name, info.spaceOccupied);
353 session_->SetBackupExtName(info.name, info.extensionName);
354 if (info.allToBackup == false) {
355 session_->GetServiceReverseProxy()->BackupOnBundleStarted(
356 BError(BError::Codes::SA_FORBID_BACKUP_RESTORE), info.name);
357 session_->RemoveExtInfo(info.name);
358 }
359 }
360 OnStartSched();
361 session_->DecreaseSessionCnt();
362 return BError(BError::Codes::OK);
363 } catch (const BError &e) {
364 session_->DecreaseSessionCnt();
365 HILOGE("Failed, errCode = %{public}d", e.GetCode());
366 return e.GetCode();
367 } catch (const exception &e) {
368 session_->DecreaseSessionCnt();
369 HILOGI("Catched an unexpected low-level exception %{public}s", e.what());
370 return EPERM;
371 } catch (...) {
372 session_->DecreaseSessionCnt();
373 HILOGI("Unexpected exception");
374 return EPERM;
375 }
376 }
377
Finish()378 ErrCode Service::Finish()
379 {
380 HILOGI("Begin");
381 VerifyCaller(session_->GetScenario());
382 session_->Finish();
383 OnAllBundlesFinished(BError(BError::Codes::OK));
384 return BError(BError::Codes::OK);
385 }
386
PublishFile(const BFileInfo & fileInfo)387 ErrCode Service::PublishFile(const BFileInfo &fileInfo)
388 {
389 try {
390 HILOGI("Begin");
391 VerifyCaller(IServiceReverse::Scenario::RESTORE);
392
393 auto backUpConnection = session_->GetExtConnection(fileInfo.owner);
394
395 auto proxy = backUpConnection->GetBackupExtProxy();
396 if (!proxy) {
397 throw BError(BError::Codes::SA_INVAL_ARG, "Extension backup Proxy is empty");
398 }
399 ErrCode res = proxy->PublishFile(fileInfo.fileName);
400 if (res) {
401 HILOGE("Failed to publish file for backup extension");
402 }
403
404 return res;
405 } catch (const BError &e) {
406 return e.GetCode();
407 } catch (const exception &e) {
408 HILOGI("Catched an unexpected low-level exception %{public}s", e.what());
409 return EPERM;
410 } catch (...) {
411 HILOGI("Unexpected exception");
412 return EPERM;
413 }
414 }
415
AppFileReady(const string & fileName,UniqueFd fd)416 ErrCode Service::AppFileReady(const string &fileName, UniqueFd fd)
417 {
418 try {
419 HILOGI("Begin");
420 string callerName = VerifyCallerAndGetCallerName();
421 if (fileName.find('/') != string::npos) {
422 throw BError(BError::Codes::SA_INVAL_ARG, "Filename is not valid");
423 }
424 if (fileName == BConstants::EXT_BACKUP_MANAGE) {
425 fd = session_->OnBunleExtManageInfo(callerName, move(fd));
426 }
427
428 session_->GetServiceReverseProxy()->BackupOnFileReady(callerName, fileName, move(fd));
429
430 if (session_->OnBunleFileReady(callerName, fileName)) {
431 auto backUpConnection = session_->GetExtConnection(callerName);
432 auto proxy = backUpConnection->GetBackupExtProxy();
433 if (!proxy) {
434 throw BError(BError::Codes::SA_INVAL_ARG, "Extension backup Proxy is empty");
435 }
436 // 通知extension清空缓存
437 proxy->HandleClear();
438 // 清除Timer
439 session_->BundleExtTimerStop(callerName);
440 // 通知TOOL 备份完成
441 session_->GetServiceReverseProxy()->BackupOnBundleFinished(BError(BError::Codes::OK), callerName);
442 // 断开extension
443 backUpConnection->DisconnectBackupExtAbility();
444 ClearSessionAndSchedInfo(callerName);
445 }
446 OnAllBundlesFinished(BError(BError::Codes::OK));
447 return BError(BError::Codes::OK);
448 } catch (const BError &e) {
449 return e.GetCode(); // 任意异常产生,终止监听该任务
450 } catch (const exception &e) {
451 HILOGI("Catched an unexpected low-level exception %{public}s", e.what());
452 return EPERM;
453 } catch (...) {
454 HILOGI("Unexpected exception");
455 return EPERM;
456 }
457 }
458
AppDone(ErrCode errCode)459 ErrCode Service::AppDone(ErrCode errCode)
460 {
461 try {
462 HILOGI("Begin");
463 string callerName = VerifyCallerAndGetCallerName();
464 if (session_->OnBunleFileReady(callerName)) {
465 auto backUpConnection = session_->GetExtConnection(callerName);
466 auto proxy = backUpConnection->GetBackupExtProxy();
467 if (!proxy) {
468 throw BError(BError::Codes::SA_INVAL_ARG, "Extension backup Proxy is empty");
469 }
470 proxy->HandleClear();
471 session_->BundleExtTimerStop(callerName);
472 IServiceReverse::Scenario scenario = session_->GetScenario();
473 if (scenario == IServiceReverse::Scenario::BACKUP) {
474 session_->GetServiceReverseProxy()->BackupOnBundleFinished(errCode, callerName);
475 } else if (scenario == IServiceReverse::Scenario::RESTORE) {
476 session_->GetServiceReverseProxy()->RestoreOnBundleFinished(errCode, callerName);
477 }
478 backUpConnection->DisconnectBackupExtAbility();
479 ClearSessionAndSchedInfo(callerName);
480 }
481 OnAllBundlesFinished(BError(BError::Codes::OK));
482 return BError(BError::Codes::OK);
483 } catch (const BError &e) {
484 return e.GetCode(); // 任意异常产生,终止监听该任务
485 } catch (const exception &e) {
486 HILOGI("Catched an unexpected low-level exception %{public}s", e.what());
487 return EPERM;
488 } catch (...) {
489 HILOGI("Unexpected exception");
490 return EPERM;
491 }
492 }
493
LaunchBackupExtension(const BundleName & bundleName)494 ErrCode Service::LaunchBackupExtension(const BundleName &bundleName)
495 {
496 try {
497 HILOGE("begin %{public}s", bundleName.data());
498 IServiceReverse::Scenario scenario = session_->GetScenario();
499 BConstants::ExtensionAction action;
500 if (scenario == IServiceReverse::Scenario::BACKUP) {
501 action = BConstants::ExtensionAction::BACKUP;
502 } else if (scenario == IServiceReverse::Scenario::RESTORE) {
503 action = BConstants::ExtensionAction::RESTORE;
504 } else {
505 throw BError(BError::Codes::SA_INVAL_ARG, "Failed to scenario");
506 }
507
508 AAFwk::Want want;
509 string backupExtName = session_->GetBackupExtName(bundleName); /* new device app ext name */
510 HILOGD("backupExtName: %{public}s, bundleName: %{public}s", backupExtName.data(), bundleName.data());
511 string versionName = session_->GetBundleVersionName(bundleName); /* old device app version name */
512 uint32_t versionCode = session_->GetBundleVersionCode(bundleName); /* old device app version code */
513 RestoreTypeEnum restoreType = session_->GetBundleRestoreType(bundleName); /* app restore type */
514
515 want.SetElementName(bundleName, backupExtName);
516 want.SetParam(BConstants::EXTENSION_ACTION_PARA, static_cast<int>(action));
517 want.SetParam(BConstants::EXTENSION_VERSION_CODE_PARA, static_cast<int>(versionCode));
518 want.SetParam(BConstants::EXTENSION_RESTORE_TYPE_PARA, static_cast<int>(restoreType));
519 want.SetParam(BConstants::EXTENSION_VERSION_NAME_PARA, versionName);
520
521 auto backUpConnection = session_->GetExtConnection(bundleName);
522
523 ErrCode ret = backUpConnection->ConnectBackupExtAbility(want, session_->GetSessionUserId());
524 return ret;
525 } catch (const BError &e) {
526 return e.GetCode();
527 } catch (const exception &e) {
528 HILOGI("Catched an unexpected low-level exception %{public}s", e.what());
529 return EPERM;
530 } catch (...) {
531 HILOGI("Unexpected exception");
532 return EPERM;
533 }
534 }
535
GetFileHandle(const string & bundleName,const string & fileName)536 ErrCode Service::GetFileHandle(const string &bundleName, const string &fileName)
537 {
538 try {
539 HILOGI("Begin");
540 VerifyCaller(IServiceReverse::Scenario::RESTORE);
541
542 bool updateRes = SvcRestoreDepsManager::GetInstance().UpdateToRestoreBundleMap(bundleName, fileName);
543 if (updateRes) {
544 return BError(BError::Codes::OK);
545 }
546 auto action = session_->GetServiceSchedAction(bundleName);
547 if (action == BConstants::ServiceSchedAction::RUNNING) {
548 auto backUpConnection = session_->GetExtConnection(bundleName);
549 auto proxy = backUpConnection->GetBackupExtProxy();
550 if (!proxy) {
551 throw BError(BError::Codes::SA_INVAL_ARG, "Extension backup Proxy is empty");
552 }
553 UniqueFd fd = proxy->GetFileHandle(fileName);
554 if (fd < 0) {
555 HILOGE("Failed to extension file handle");
556 }
557 session_->GetServiceReverseProxy()->RestoreOnFileReady(bundleName, fileName, move(fd));
558 } else {
559 session_->SetExtFileNameRequest(bundleName, fileName);
560 }
561 return BError(BError::Codes::OK);
562 } catch (const BError &e) {
563 return e.GetCode();
564 } catch (const exception &e) {
565 HILOGI("Catched an unexpected low-level exception %{public}s", e.what());
566 return EPERM;
567 } catch (...) {
568 HILOGI("Unexpected exception");
569 return EPERM;
570 }
571 }
572
OnBackupExtensionDied(const string && bundleName)573 void Service::OnBackupExtensionDied(const string &&bundleName)
574 {
575 try {
576 string callName = move(bundleName);
577 session_->VerifyBundleName(callName);
578
579 /* Standard Log Output, for testers */
580 HILOGE("Backup <%{public}s> Extension Process Died", callName.data());
581 string versionName = session_->GetBundleVersionName(bundleName); /* old device app version name */
582 uint32_t versionCode = session_->GetBundleVersionCode(bundleName); /* old device app version code */
583 if (versionCode == BConstants::DEFAULT_VERSION_CODE && versionName == BConstants::DEFAULT_VERSION_NAME) {
584 ExtConnectDied(bundleName);
585 return;
586 }
587 // 重新连接清理缓存
588 HILOGE("Clear backup extension data, bundleName: %{public}s", bundleName.data());
589 auto backUpConnection = session_->GetExtConnection(bundleName);
590 auto callConnDone = [ptr {wptr(this)}](const string &&bundleName) {
591 auto thisPtr = ptr.promote();
592 if (!thisPtr) {
593 HILOGW("this pointer is null.");
594 return;
595 }
596 auto sessionConnection = thisPtr->session_->GetExtConnection(bundleName);
597 if (sessionConnection->IsExtAbilityConnected()) {
598 sessionConnection->DisconnectBackupExtAbility();
599 }
600 thisPtr->ExtConnectDied(bundleName);
601 };
602 backUpConnection->SetCallback(callConnDone);
603 auto ret = LaunchBackupExtension(bundleName);
604 if (ret) {
605 ExtConnectDied(bundleName);
606 return;
607 }
608 } catch (...) {
609 HILOGE("Unexpected exception");
610 return;
611 }
612 }
613
ExtConnectDied(const string & callName)614 void Service::ExtConnectDied(const string &callName)
615 {
616 try {
617 HILOGI("Begin");
618 /* Clear Timer */
619 session_->BundleExtTimerStop(callName);
620 auto backUpConnection = session_->GetExtConnection(callName);
621 if (backUpConnection->IsExtAbilityConnected()) {
622 backUpConnection->DisconnectBackupExtAbility();
623 }
624 /* Clear Session before notice client finish event */
625 ClearSessionAndSchedInfo(callName);
626 /* Notice Client Ext Ability Process Died */
627 NoticeClientFinish(callName, BError(BError::Codes::EXT_ABILITY_DIED));
628 } catch (...) {
629 HILOGE("Unexpected exception");
630 return;
631 }
632 }
633
ExtStart(const string & bundleName)634 void Service::ExtStart(const string &bundleName)
635 {
636 try {
637 HILOGE("begin %{public}s", bundleName.data());
638 if (IncrementalBackup(bundleName)) {
639 return;
640 }
641 IServiceReverse::Scenario scenario = session_->GetScenario();
642 auto backUpConnection = session_->GetExtConnection(bundleName);
643 auto proxy = backUpConnection->GetBackupExtProxy();
644 if (!proxy) {
645 throw BError(BError::Codes::SA_INVAL_ARG, "Extension backup Proxy is empty");
646 }
647 if (scenario == IServiceReverse::Scenario::BACKUP) {
648 auto ret = proxy->HandleBackup();
649 session_->GetServiceReverseProxy()->BackupOnBundleStarted(ret, bundleName);
650 if (ret) {
651 ClearSessionAndSchedInfo(bundleName);
652 }
653 return;
654 }
655 if (scenario != IServiceReverse::Scenario::RESTORE) {
656 throw BError(BError::Codes::SA_INVAL_ARG, "Failed to scenario");
657 }
658 auto ret = proxy->HandleRestore();
659 session_->GetServiceReverseProxy()->RestoreOnBundleStarted(ret, bundleName);
660 auto fileNameVec = session_->GetExtFileNameRequest(bundleName);
661 for (auto &fileName : fileNameVec) {
662 UniqueFd fd = proxy->GetFileHandle(fileName);
663 if (fd < 0) {
664 HILOGE("Failed to extension file handle");
665 }
666 session_->GetServiceReverseProxy()->RestoreOnFileReady(bundleName, fileName, move(fd));
667 }
668 return;
669 } catch (const BError &e) {
670 return;
671 } catch (const exception &e) {
672 HILOGI("Catched an unexpected low-level exception %{public}s", e.what());
673 return;
674 } catch (...) {
675 HILOGI("Unexpected exception");
676 return;
677 }
678 }
679
Dump(int fd,const vector<u16string> & args)680 int Service::Dump(int fd, const vector<u16string> &args)
681 {
682 if (fd < 0) {
683 HILOGI("HiDumper handle invalid");
684 return -1;
685 }
686
687 session_->DumpInfo(fd, args);
688 return 0;
689 }
690
ExtConnectFailed(const string & bundleName,ErrCode ret)691 void Service::ExtConnectFailed(const string &bundleName, ErrCode ret)
692 {
693 try {
694 HILOGE("begin %{public}s", bundleName.data());
695 IServiceReverse::Scenario scenario = session_->GetScenario();
696 if (scenario == IServiceReverse::Scenario::BACKUP && session_->GetIsIncrementalBackup()) {
697 session_->GetServiceReverseProxy()->IncrementalBackupOnBundleStarted(ret, bundleName);
698 } else if (scenario == IServiceReverse::Scenario::RESTORE &&
699 BackupPara().GetBackupOverrideIncrementalRestore()) {
700 session_->GetServiceReverseProxy()->IncrementalRestoreOnBundleStarted(ret, bundleName);
701
702 DisposeErr disposeErr = AppGalleryDisposeProxy::GetInstance()->EndRestore(bundleName);
703 HILOGI("ExtConnectFailed EndRestore, code=%{public}d, bundleName=%{public}s", disposeErr,
704 bundleName.c_str());
705 } else if (scenario == IServiceReverse::Scenario::BACKUP) {
706 session_->GetServiceReverseProxy()->BackupOnBundleStarted(ret, bundleName);
707 } else if (scenario == IServiceReverse::Scenario::RESTORE) {
708 session_->GetServiceReverseProxy()->RestoreOnBundleStarted(ret, bundleName);
709
710 DisposeErr disposeErr = AppGalleryDisposeProxy::GetInstance()->EndRestore(bundleName);
711 HILOGI("ExtConnectFailed EndRestore, code=%{public}d, bundleName=%{public}s", disposeErr,
712 bundleName.c_str());
713 }
714 ClearSessionAndSchedInfo(bundleName);
715 return;
716 } catch (const BError &e) {
717 return;
718 } catch (const exception &e) {
719 HILOGI("Catched an unexpected low-level exception %{public}s", e.what());
720 return;
721 } catch (...) {
722 HILOGI("Unexpected exception");
723 return;
724 }
725 }
726
NoticeClientFinish(const string & bundleName,ErrCode errCode)727 void Service::NoticeClientFinish(const string &bundleName, ErrCode errCode)
728 {
729 auto scenario = session_->GetScenario();
730 if (scenario == IServiceReverse::Scenario::BACKUP && session_->GetIsIncrementalBackup()) {
731 session_->GetServiceReverseProxy()->IncrementalBackupOnBundleFinished(errCode, bundleName);
732 } else if (scenario == IServiceReverse::Scenario::RESTORE && BackupPara().GetBackupOverrideIncrementalRestore()) {
733 session_->GetServiceReverseProxy()->IncrementalRestoreOnBundleFinished(errCode, bundleName);
734 } else if (scenario == IServiceReverse::Scenario::BACKUP) {
735 session_->GetServiceReverseProxy()->BackupOnBundleFinished(errCode, bundleName);
736 } else if (scenario == IServiceReverse::Scenario::RESTORE) {
737 session_->GetServiceReverseProxy()->RestoreOnBundleFinished(errCode, bundleName);
738 };
739 /* If all bundle ext process finish, notice client. */
740 OnAllBundlesFinished(BError(BError::Codes::OK));
741 }
742
ExtConnectDone(string bundleName)743 void Service::ExtConnectDone(string bundleName)
744 {
745 /* Callback for App Ext Timeout Process. */
746 auto timeoutCallback = [ptr {wptr(this)}, bundleName]() {
747 auto thisPtr = ptr.promote();
748 if (!thisPtr) {
749 HILOGW("this pointer is null.");
750 return;
751 }
752 auto sessionPtr = ptr->session_;
753 auto sessionConnection = sessionPtr->GetExtConnection(bundleName);
754 /* Standard Log Output, for testers */
755 HILOGE("Backup <%{public}s> Extension Process Timeout", bundleName.data());
756 sessionPtr->BundleExtTimerStop(bundleName);
757 sessionConnection->DisconnectBackupExtAbility();
758 /* Must clear bundle session before call NoticeClientFinish. */
759 thisPtr->ClearSessionAndSchedInfo(bundleName);
760 thisPtr->NoticeClientFinish(bundleName, BError(BError::Codes::EXT_ABILITY_TIMEOUT));
761 };
762
763 try {
764 HILOGE("begin %{public}s", bundleName.data());
765 session_->BundleExtTimerStart(bundleName, timeoutCallback);
766 session_->SetServiceSchedAction(bundleName, BConstants::ServiceSchedAction::RUNNING);
767 sched_->Sched(bundleName);
768 } catch (const BError &e) {
769 return;
770 } catch (const exception &e) {
771 HILOGI("Catched an unexpected low-level exception %{public}s", e.what());
772 return;
773 } catch (...) {
774 HILOGI("Unexpected exception");
775 return;
776 }
777 }
778
ClearSessionAndSchedInfo(const string & bundleName)779 void Service::ClearSessionAndSchedInfo(const string &bundleName)
780 {
781 try {
782 session_->RemoveExtInfo(bundleName);
783 sched_->RemoveExtConn(bundleName);
784 HandleRestoreDepsBundle(bundleName);
785 sched_->Sched();
786 } catch (const BError &e) {
787 return;
788 } catch (const exception &e) {
789 HILOGI("Catched an unexpected low-level exception %{public}s", e.what());
790 return;
791 } catch (...) {
792 HILOGI("Unexpected exception");
793 return;
794 }
795 }
796
HandleRestoreDepsBundle(const string & bundleName)797 void Service::HandleRestoreDepsBundle(const string &bundleName)
798 {
799 if (session_->GetScenario() != IServiceReverse::Scenario::RESTORE) {
800 return;
801 }
802 HILOGI("Begin, bundleName: %{public}s", bundleName.c_str());
803 SvcRestoreDepsManager::GetInstance().AddRestoredBundles(bundleName);
804 // 该应用恢复完成,判断依赖hap的前置hap是否全部恢复完成,如果成了,追加该依赖hap
805 auto restoreBundleMap = SvcRestoreDepsManager::GetInstance().GetRestoreBundleMap();
806 if (restoreBundleMap.empty()) {
807 HILOGI("restoreBundleMap is empty.");
808 return;
809 }
810 // 启动恢复会话
811 vector<string> restoreBundleNames {};
812 for (const auto &bundle : restoreBundleMap) {
813 HILOGI("Start restore session, bundle: %{public}s", bundle.first.c_str());
814 restoreBundleNames.emplace_back(bundle.first);
815 }
816 session_->AppendBundles(restoreBundleNames);
817 for (const auto &bundle : restoreBundleMap) {
818 for (auto &bundleInfo : SvcRestoreDepsManager::GetInstance().GetAllBundles()) {
819 if (bundle.first != bundleInfo.name) {
820 continue;
821 }
822 SvcRestoreDepsManager::RestoreInfo info = bundle.second;
823 session_->SetBundleRestoreType(bundleInfo.name, info.restoreType_);
824 session_->SetBundleVersionCode(bundleInfo.name, bundleInfo.versionCode);
825 session_->SetBundleVersionName(bundleInfo.name, bundleInfo.versionName);
826 session_->SetBundleDataSize(bundleInfo.name, bundleInfo.spaceOccupied);
827 session_->SetBackupExtName(bundleInfo.name, bundleInfo.extensionName);
828 for (auto &fileName : info.fileNames_) {
829 session_->SetExtFileNameRequest(bundleInfo.name, fileName);
830 }
831 }
832 }
833 HILOGI("End");
834 }
835
OnAllBundlesFinished(ErrCode errCode)836 void Service::OnAllBundlesFinished(ErrCode errCode)
837 {
838 if (session_->IsOnAllBundlesFinished()) {
839 IServiceReverse::Scenario scenario = session_->GetScenario();
840 if (scenario == IServiceReverse::Scenario::BACKUP && session_->GetIsIncrementalBackup()) {
841 session_->GetServiceReverseProxy()->IncrementalBackupOnAllBundlesFinished(errCode);
842 } else if (scenario == IServiceReverse::Scenario::RESTORE &&
843 BackupPara().GetBackupOverrideIncrementalRestore()) {
844 session_->GetServiceReverseProxy()->IncrementalRestoreOnAllBundlesFinished(errCode);
845 } else if (scenario == IServiceReverse::Scenario::BACKUP) {
846 session_->GetServiceReverseProxy()->BackupOnAllBundlesFinished(errCode);
847 } else if (scenario == IServiceReverse::Scenario::RESTORE) {
848 session_->GetServiceReverseProxy()->RestoreOnAllBundlesFinished(errCode);
849 }
850 if (!BackupPara().GetBackupOverrideBackupSARelease()) {
851 sched_->TryUnloadServiceTimer(true);
852 }
853 }
854 }
855
OnStartSched()856 void Service::OnStartSched()
857 {
858 if (session_->IsOnOnStartSched()) {
859 for (int num = 0; num < BConstants::EXT_CONNECT_MAX_COUNT; num++) {
860 sched_->Sched();
861 }
862 }
863 }
864
SendAppGalleryNotify(const BundleName & bundleName)865 void Service::SendAppGalleryNotify(const BundleName &bundleName)
866 {
867 IServiceReverse::Scenario scenario = session_->GetScenario();
868 if (scenario == IServiceReverse::Scenario::RESTORE) {
869 DisposeErr disposeErr = AppGalleryDisposeProxy::GetInstance()->StartRestore(bundleName);
870 HILOGI("SendAppGalleryNotify StartRestore, code=%{public}d, bundleName=%{public}s", disposeErr,
871 bundleName.c_str());
872 }
873 }
874
SessionDeactive()875 void Service::SessionDeactive()
876 {
877 try {
878 HILOGI("Begin");
879 // 结束定时器
880 sched_->ClearSchedulerData();
881 // 清除缓存数据
882 session_->ClearSessionData();
883 // 卸载服务
884 sched_->TryUnloadService();
885 } catch (...) {
886 HILOGI("Unexpected exception");
887 return;
888 }
889 }
890 } // namespace OHOS::FileManagement::Backup
891