• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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