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/svc_session_manager.h"
17 
18 #include <algorithm>
19 #include <cstdint>
20 #include <memory>
21 #include <regex>
22 #include <sstream>
23 #include <string>
24 
25 #include "b_error/b_error.h"
26 #include "b_file_info.h"
27 #include "b_json/b_json_entity_caps.h"
28 #include "b_json/b_json_entity_ext_manage.h"
29 #include "b_radar/b_radar.h"
30 #include "b_resources/b_constants.h"
31 #include "b_sa/b_sa_utils.h"
32 #include "b_utils/b_time.h"
33 #include "filemgmt_libhilog.h"
34 #include "module_ipc/service.h"
35 #include "module_ipc/svc_restore_deps_manager.h"
36 #include "unique_fd.h"
37 
38 namespace OHOS::FileManagement::Backup {
39 using namespace std;
40 
VerifyCallerAndScenario(uint32_t clientToken,IServiceReverse::Scenario scenario) const41 void SvcSessionManager::VerifyCallerAndScenario(uint32_t clientToken, IServiceReverse::Scenario scenario) const
42 {
43     shared_lock<shared_mutex> lock(lock_);
44     if (impl_.scenario != scenario) {
45         HILOGE("Inconsistent scenario, impl scenario:%{public}d", impl_.scenario);
46         AppRadar::Info info("", "", "Inconsistent scenario");
47         AppRadar::GetInstance().RecordDefaultFuncRes(info, "SvcSessionManager::VerifyCallerAndScenario", impl_.userId,
48                                                      BizStageBackup::BIZ_STAGE_PERMISSION_CHECK_FAIL,
49                                                      BError(BError::Codes::SDK_MIXED_SCENARIO).GetCode());
50         throw BError(BError::Codes::SDK_MIXED_SCENARIO);
51     }
52     if (impl_.clientToken != clientToken) {
53         AppRadar::Info info2("", "", "Caller mismatched");
54         AppRadar::GetInstance().RecordDefaultFuncRes(info2, "SvcSessionManager::VerifyCallerAndScenario", impl_.userId,
55                                                      BizStageBackup::BIZ_STAGE_PERMISSION_CHECK_FAIL,
56                                                      BError(BError::Codes::SDK_MIXED_SCENARIO).GetCode());
57         throw BError(BError::Codes::SA_REFUSED_ACT, "Caller mismatched");
58     }
59     HILOGD("Succeed to verify the caller");
60 }
61 
GetImpl()62 SvcSessionManager::Impl SvcSessionManager::GetImpl()
63 {
64     return impl_;
65 }
66 
GetSessionCnt()67 int SvcSessionManager::GetSessionCnt()
68 {
69     return sessionCnt_.load();
70 }
71 
Active(Impl newImpl,bool force)72 ErrCode SvcSessionManager::Active(Impl newImpl, bool force)
73 {
74     unique_lock<shared_mutex> lock(lock_);
75     const Impl &oldImpl = impl_;
76     if (oldImpl.clientToken) {
77         HILOGE("Already have an active session");
78         return BError(BError::Codes::SA_REFUSED_ACT);
79     }
80 
81     if (!force && !newImpl.clientToken) {
82         throw BError(BError::Codes::SA_INVAL_ARG, "No caller token was specified");
83     }
84     if (!force && newImpl.scenario == IServiceReverse::Scenario::UNDEFINED) {
85         throw BError(BError::Codes::SA_INVAL_ARG, "No scenario was specified");
86     }
87 
88     if (!force) {
89         InitClient(newImpl);
90     }
91     impl_ = newImpl;
92     IncreaseSessionCnt(__PRETTY_FUNCTION__);
93     return BError(BError::Codes::OK);
94 }
95 
Deactive(const wptr<IRemoteObject> & remoteInAction,bool force)96 void SvcSessionManager::Deactive(const wptr<IRemoteObject> &remoteInAction, bool force)
97 {
98     unique_lock<shared_mutex> lock(lock_);
99     if (!impl_.clientToken) {
100         HILOGI("Empty session");
101         return;
102     }
103     if (!force && (!impl_.clientToken || !impl_.clientProxy)) {
104         return;
105     }
106     if (!force && (remoteInAction != impl_.clientProxy->AsObject())) {
107         throw BError(BError::Codes::SA_INVAL_ARG, "Only the client actived the session can deactive it");
108     }
109 
110     deathRecipient_ = nullptr;
111     AppRadar::Info info("", "", "deactive session success");
112     if (impl_.scenario == IServiceReverse::Scenario::RESTORE) {
113         AppRadar::GetInstance().RecordRestoreFuncRes(info, "SvcSessionManager::Deactive", impl_.userId,
114             BizStageRestore::BIZ_STAGE_DEACTIVE_SESSION, ERR_OK);
115     } else if (impl_.scenario == IServiceReverse::Scenario::BACKUP) {
116         AppRadar::GetInstance().RecordBackupFuncRes(info, "SvcSessionManager::Deactive", impl_.userId,
117             BizStageBackup::BIZ_STAGE_DEACTIVE_SESSION, ERR_OK);
118     }
119     HILOGI("Succeed to deactive a session");
120     impl_ = {};
121     extConnectNum_ = 0;
122     DecreaseSessionCnt(__PRETTY_FUNCTION__);
123 }
124 
VerifyBundleName(string & bundleName)125 void SvcSessionManager::VerifyBundleName(string &bundleName)
126 {
127     shared_lock<shared_mutex> lock(lock_);
128     if (!impl_.clientToken) {
129         throw BError(BError::Codes::SA_INVAL_ARG, "No caller token was specified");
130     }
131     auto asVerify = [&bundleName](const auto &it) { return it.first == bundleName; };
132     if (none_of(impl_.backupExtNameMap.begin(), impl_.backupExtNameMap.end(), asVerify)) {
133         stringstream ss;
134         ss << "Could not find the " << bundleName << " from current session";
135         throw BError(BError::Codes::SA_REFUSED_ACT, ss.str());
136     }
137     HILOGD("Succeed to verify the bundleName");
138 }
139 
GetServiceReverseProxy()140 sptr<IServiceReverse> SvcSessionManager::GetServiceReverseProxy()
141 {
142     unique_lock<shared_mutex> lock(lock_);
143     if (!impl_.clientProxy) {
144         throw BError(BError::Codes::SA_REFUSED_ACT, "Try to deactive an empty session");
145     }
146     return impl_.clientProxy;
147 }
148 
GetScenario()149 IServiceReverse::Scenario SvcSessionManager::GetScenario()
150 {
151     shared_lock<shared_mutex> lock(lock_);
152     if (!impl_.clientToken) {
153         throw BError(BError::Codes::SA_INVAL_ARG, "No caller token was specified");
154     }
155     return impl_.scenario;
156 }
157 
GetSessionUserId()158 int32_t SvcSessionManager::GetSessionUserId()
159 {
160     return impl_.userId;
161 }
162 
SetSessionUserId(int32_t userId)163 void SvcSessionManager::SetSessionUserId(int32_t userId)
164 {
165     impl_.userId = userId;
166 }
167 
OnBundleFileReady(const string & bundleName,const string & fileName)168 bool SvcSessionManager::OnBundleFileReady(const string &bundleName, const string &fileName)
169 {
170     unique_lock<shared_mutex> lock(lock_);
171     if (!impl_.clientToken) {
172         throw BError(BError::Codes::SA_INVAL_ARG, "No caller token was specified");
173     }
174     HILOGD("Begin, bundleName name is:%{private}s", bundleName.c_str());
175     auto it = impl_.backupExtNameMap.find(bundleName);
176     if (it == impl_.backupExtNameMap.end()) {
177         stringstream ss;
178         ss << "Could not find the " << bundleName << " from current session";
179         throw BError(BError::Codes::SA_REFUSED_ACT, ss.str());
180     }
181 
182     // 判断是否结束 通知EXTENTION清理资源  TOOL应用完成备份
183     if (impl_.scenario == IServiceReverse::Scenario::RESTORE || SAUtils::IsSABundleName(bundleName)) {
184         it->second.isBundleFinished = true;
185         return true;
186     } else if (impl_.scenario == IServiceReverse::Scenario::BACKUP) {
187         if (!fileName.empty() && fileName != BConstants::EXT_BACKUP_MANAGE) {
188             auto ret = it->second.fileNameInfo.insert(fileName);
189             if (!ret.second) {
190                 it->second.fileNameInfo.erase(fileName);
191             }
192         } else if (fileName.empty()) {
193             it->second.receExtAppDone = true;
194         }
195         if (it->second.receExtManageJson && it->second.fileNameInfo.empty() && it->second.receExtAppDone) {
196             HILOGI("The bundle manage json info and file info support current app done");
197             it->second.isBundleFinished = true;
198             return true;
199         }
200     }
201     HILOGD("End, bundleName name is:%{private}s", bundleName.c_str());
202     return false;
203 }
204 
OnBundleExtManageInfo(const string & bundleName,UniqueFd fd)205 UniqueFd SvcSessionManager::OnBundleExtManageInfo(const string &bundleName, UniqueFd fd)
206 {
207     if (!impl_.clientToken) {
208         throw BError(BError::Codes::SA_INVAL_ARG, "No caller token was specified");
209     }
210     if (impl_.scenario != IServiceReverse::Scenario::BACKUP) {
211         throw BError(BError::Codes::SA_INVAL_ARG, "Invalid Scenario");
212     }
213 
214     BJsonCachedEntity<BJsonEntityExtManage> cachedEntity(move(fd));
215     auto cache = cachedEntity.Structuralize();
216     auto info = cache.GetExtManage();
217 
218     for (auto &fileName : info) {
219         HILOGE("fileName %{public}s", fileName.data());
220         OnBundleFileReady(bundleName, fileName);
221     }
222 
223     unique_lock<shared_mutex> lock(lock_);
224     auto it = GetBackupExtNameMap(bundleName);
225     it->second.receExtManageJson = true;
226     return move(cachedEntity.GetFd());
227 }
228 
RemoveExtInfo(const string & bundleName)229 void SvcSessionManager::RemoveExtInfo(const string &bundleName)
230 {
231     HILOGD("svcMrg:RemoveExt, bundleName:%{public}s", bundleName.c_str());
232     unique_lock<shared_mutex> lock(lock_);
233     auto it = impl_.backupExtNameMap.find(bundleName);
234     if (it == impl_.backupExtNameMap.end()) {
235         HILOGI("BackupExtNameMap not contain %{public}s", bundleName.c_str());
236         return;
237     }
238     if (extConnectNum_) {
239         extConnectNum_--;
240     }
241     int32_t &appendNum = impl_.backupExtNameMap[bundleName].appendNum;
242     if (--appendNum > 0) {
243         HILOGI("No need remove bundleName:%{public}s, appendNum=%{public}d", bundleName.c_str(), appendNum);
244         return;
245     }
246     impl_.backupExtNameMap.erase(it);
247 }
248 
GetExtConnection(const BundleName & bundleName)249 wptr<SvcBackupConnection> SvcSessionManager::GetExtConnection(const BundleName &bundleName)
250 {
251     HILOGD("svcMrg:GetExt, bundleName:%{public}s", bundleName.c_str());
252     shared_lock<shared_mutex> lock(lock_);
253     if (!impl_.clientToken) {
254         throw BError(BError::Codes::SA_INVAL_ARG, "No caller token was specified");
255     }
256 
257     auto it = GetBackupExtNameMap(bundleName);
258     if (!it->second.backUpConnection) {
259         throw BError(BError::Codes::SA_INVAL_ARG, "Svc backup connection is empty");
260     }
261 
262     return wptr(it->second.backUpConnection);
263 }
264 
GetSAExtConnection(const BundleName & bundleName)265 std::weak_ptr<SABackupConnection> SvcSessionManager::GetSAExtConnection(const BundleName &bundleName)
266 {
267     HILOGD("svcMrg:GetExt, bundleName:%{public}s", bundleName.c_str());
268     shared_lock<shared_mutex> lock(lock_);
269     if (!impl_.clientToken) {
270         throw BError(BError::Codes::SA_INVAL_ARG, "No caller token was specified");
271     }
272 
273     auto it = GetBackupExtNameMap(bundleName);
274     if (!it->second.saBackupConnection) {
275         throw BError(BError::Codes::SA_INVAL_ARG, "SA backup connection is empty");
276     }
277 
278     return std::weak_ptr<SABackupConnection>(it->second.saBackupConnection);
279 }
280 
GetBackupAbilityExt(const string & bundleName)281 sptr<SvcBackupConnection> SvcSessionManager::GetBackupAbilityExt(const string &bundleName)
282 {
283     auto callDied = [revPtr {reversePtr_}](const string &&bundleName, bool isSecondCalled = false) {
284         auto revPtrStrong = revPtr.promote();
285         if (!revPtrStrong) {
286             // 服务先于客户端死亡是一种异常场景,但该场景对本流程来说也没什么影响,所以只是简单记录一下
287             HILOGW("It's curious that the backup sa dies before the backup client");
288             return;
289         }
290         revPtrStrong->OnBackupExtensionDied(move(bundleName), isSecondCalled);
291     };
292 
293     auto callConnected = [revPtr {reversePtr_}](const string &&bundleName) {
294         auto revPtrStrong = revPtr.promote();
295         if (!revPtrStrong) {
296             // 服务先于客户端死亡是一种异常场景,但该场景对本流程来说也没什么影响,所以只是简单记录一下
297             HILOGW("It's curious that the backup sa dies before the backup client");
298             return;
299         }
300         revPtrStrong->ExtConnectDone(move(bundleName));
301     };
302 
303     return sptr<SvcBackupConnection>(new SvcBackupConnection(callDied, callConnected, bundleName));
304 }
305 
GetBackupSAExt(const std::string & bundleName)306 std::shared_ptr<SABackupConnection> SvcSessionManager::GetBackupSAExt(const std::string &bundleName)
307 {
308     auto callDied = [revPtr {reversePtr_}](const string &&bundleName) {
309         auto revPtrStrong = revPtr.promote();
310         if (!revPtrStrong) {
311             // 服务先于客户端死亡是一种异常场景,但该场景对本流程来说也没什么影响,所以只是简单记录一下
312             HILOGW("It's curious that the backup sa dies before the backup client");
313             return;
314         }
315         revPtrStrong->OnBackupExtensionDied(move(bundleName));
316     };
317 
318     auto callConnected = [revPtr {reversePtr_}](const string &&bundleName) {
319         auto revPtrStrong = revPtr.promote();
320         if (!revPtrStrong) {
321             // 服务先于客户端死亡是一种异常场景,但该场景对本流程来说也没什么影响,所以只是简单记录一下
322             HILOGW("It's curious that the backup sa dies before the backup client");
323             return;
324         }
325         revPtrStrong->ExtConnectDone(move(bundleName));
326     };
327 
328     auto callBackup = [revPtr {reversePtr_}](const string &&bundleName, const int &&fd, const std::string result,
329                                              const ErrCode &&errCode) {
330         auto revPtrStrong = revPtr.promote();
331         if (!revPtrStrong) {
332             // 服务先于客户端死亡是一种异常场景,但该场景对本流程来说也没什么影响,所以只是简单记录一下
333             HILOGW("It's curious that the backup sa dies before the backup client");
334             return;
335         }
336         revPtrStrong->OnSABackup(move(bundleName), move(fd), move(result), move(errCode));
337     };
338 
339     auto callRestore = [revPtr {reversePtr_}](const string &&bundleName, const std::string result,
340                                               const ErrCode &&errCode) {
341         auto revPtrStrong = revPtr.promote();
342         if (!revPtrStrong) {
343             // 服务先于客户端死亡是一种异常场景,但该场景对本流程来说也没什么影响,所以只是简单记录一下
344             HILOGW("It's curious that the backup sa dies before the backup client");
345             return;
346         }
347         revPtrStrong->OnSARestore(move(bundleName), move(result), move(errCode));
348     };
349 
350     return std::make_shared<SABackupConnection>(callDied, callConnected, callBackup, callRestore);
351 }
352 
DumpInfo(const int fd,const std::vector<std::u16string> & args)353 void SvcSessionManager::DumpInfo(const int fd, const std::vector<std::u16string> &args)
354 {
355     dprintf(fd, "---------------------backup info--------------------\n");
356     dprintf(fd, "Scenario: %d\n", impl_.scenario);
357 }
358 
InitClient(Impl & newImpl)359 void SvcSessionManager::InitClient(Impl &newImpl)
360 {
361     if (!newImpl.clientProxy) {
362         throw BError(BError::Codes::SA_INVAL_ARG, "Invalid client");
363     }
364     auto remoteObj = newImpl.clientProxy->AsObject();
365     if (!remoteObj) {
366         throw BError(BError::Codes::SA_BROKEN_IPC, "Proxy's remote object can't be nullptr");
367     }
368 
369     auto callback = [revPtr {reversePtr_}](const wptr<IRemoteObject> &obj) {
370         HILOGI("Client died.");
371 
372         auto revPtrStrong = revPtr.promote();
373         if (!revPtrStrong) {
374             // 服务先于客户端死亡是一种异常场景,但该场景对本流程来说也没什么影响,所以只是简单记录一下
375             HILOGW("It's curious that the backup sa dies before the backup client");
376             return;
377         }
378         (void)revPtrStrong->SessionDeactive();
379     };
380     deathRecipient_ = sptr(new SvcDeathRecipient(callback));
381     remoteObj->AddDeathRecipient(deathRecipient_);
382     AppRadar::Info info("", "", "active session success");
383     if (newImpl.scenario == IServiceReverse::Scenario::RESTORE) {
384         AppRadar::GetInstance().RecordRestoreFuncRes(info, "SvcSessionManager::InitClient", newImpl.userId,
385             BizStageRestore::BIZ_STAGE_ACTIVE_SESSION, ERR_OK);
386     } else if (newImpl.scenario == IServiceReverse::Scenario::BACKUP) {
387         AppRadar::GetInstance().RecordBackupFuncRes(info, "SvcSessionManager::InitClient", newImpl.userId,
388             BizStageBackup::BIZ_STAGE_ACTIVE_SESSION, ERR_OK);
389     }
390     HILOGI("Succeed to active a session");
391 }
392 
SetExtFileNameRequest(const string & bundleName,const string & fileName)393 void SvcSessionManager::SetExtFileNameRequest(const string &bundleName, const string &fileName)
394 {
395     unique_lock<shared_mutex> lock(lock_);
396     if (!impl_.clientToken) {
397         throw BError(BError::Codes::SA_INVAL_ARG, "No caller token was specified");
398     }
399 
400     auto it = GetBackupExtNameMap(bundleName);
401     it->second.fileNameInfo.insert(fileName);
402 }
403 
GetExtFileNameRequest(const std::string & bundleName)404 std::set<std::string> SvcSessionManager::GetExtFileNameRequest(const std::string &bundleName)
405 {
406     unique_lock<shared_mutex> lock(lock_);
407     if (!impl_.clientToken) {
408         throw BError(BError::Codes::SA_INVAL_ARG, "No caller token was specified");
409     }
410 
411     if (impl_.scenario != IServiceReverse::Scenario::RESTORE) {
412         throw BError(BError::Codes::SA_INVAL_ARG, "Invalid Scenario");
413     }
414     auto it = GetBackupExtNameMap(bundleName);
415     set<string> fileNameInfo = it->second.fileNameInfo;
416     it->second.fileNameInfo.clear();
417     return fileNameInfo;
418 }
419 
GetBackupExtNameMap(const string & bundleName)420 map<BundleName, BackupExtInfo>::iterator SvcSessionManager::GetBackupExtNameMap(const string &bundleName)
421 {
422     auto it = impl_.backupExtNameMap.find(bundleName);
423     if (it == impl_.backupExtNameMap.end()) {
424         stringstream ss;
425         ss << "Could not find the " << bundleName << " from current session";
426         throw BError(BError::Codes::SA_REFUSED_ACT, ss.str());
427     }
428     return it;
429 }
430 
GetSchedBundleName(string & bundleName)431 bool SvcSessionManager::GetSchedBundleName(string &bundleName)
432 {
433     unique_lock<shared_mutex> lock(lock_);
434     if (extConnectNum_ >= BConstants::EXT_CONNECT_MAX_COUNT) {
435         return false;
436     }
437 
438     for (auto &&it : impl_.backupExtNameMap) {
439         if (it.second.schedAction == BConstants::ServiceSchedAction::WAIT) {
440             bundleName = it.first;
441             if (!it.second.isReadyLaunch) {
442                 HILOGE("Current bundle:%{public}s can not sched, baseInfo is not set done", bundleName.c_str());
443                 return false;
444             }
445             it.second.schedAction = BConstants::ServiceSchedAction::START;
446             extConnectNum_++;
447             return true;
448         }
449     }
450     return false;
451 }
452 
GetServiceSchedAction(const std::string & bundleName)453 BConstants::ServiceSchedAction SvcSessionManager::GetServiceSchedAction(const std::string &bundleName)
454 {
455     shared_lock<shared_mutex> lock(lock_);
456     if (!impl_.clientToken) {
457         throw BError(BError::Codes::SA_INVAL_ARG, "No caller token was specified");
458     }
459     auto it = GetBackupExtNameMap(bundleName);
460     return it->second.schedAction;
461 }
462 
SetServiceSchedAction(const string & bundleName,BConstants::ServiceSchedAction action)463 void SvcSessionManager::SetServiceSchedAction(const string &bundleName, BConstants::ServiceSchedAction action)
464 {
465     unique_lock<shared_mutex> lock(lock_);
466     if (!impl_.clientToken) {
467         throw BError(BError::Codes::SA_INVAL_ARG, "No caller token was specified");
468     }
469 
470     auto it = GetBackupExtNameMap(bundleName);
471     it->second.schedAction = action;
472     if (it->second.schedAction == BConstants::ServiceSchedAction::START) {
473         extConnectNum_++;
474     }
475 }
476 
SetBackupExtName(const string & bundleName,const string & backupExtName)477 void SvcSessionManager::SetBackupExtName(const string &bundleName, const string &backupExtName)
478 {
479     unique_lock<shared_mutex> lock(lock_);
480     if (!impl_.clientToken) {
481         throw BError(BError::Codes::SA_INVAL_ARG, "No caller token was specified");
482     }
483 
484     auto it = GetBackupExtNameMap(bundleName);
485     it->second.backupExtName = backupExtName;
486 }
487 
GetBackupExtName(const string & bundleName)488 string SvcSessionManager::GetBackupExtName(const string &bundleName)
489 {
490     shared_lock<shared_mutex> lock(lock_);
491     if (!impl_.clientToken) {
492         throw BError(BError::Codes::SA_INVAL_ARG, "No caller token was specified");
493     }
494 
495     auto it = GetBackupExtNameMap(bundleName);
496     return it->second.backupExtName;
497 }
498 
SetBackupExtInfo(const string & bundleName,const string & extInfo)499 void SvcSessionManager::SetBackupExtInfo(const string &bundleName, const string &extInfo)
500 {
501     unique_lock<shared_mutex> lock(lock_);
502     if (!impl_.clientToken) {
503         throw BError(BError::Codes::SA_INVAL_ARG, "No caller token was specified");
504     }
505 
506     auto it = GetBackupExtNameMap(bundleName);
507     it->second.extInfo = extInfo;
508 }
509 
GetBackupExtInfo(const string & bundleName)510 std::string SvcSessionManager::GetBackupExtInfo(const string &bundleName)
511 {
512     shared_lock<shared_mutex> lock(lock_);
513     if (!impl_.clientToken) {
514         throw BError(BError::Codes::SA_INVAL_ARG, "No caller token was specified");
515     }
516 
517     auto it = GetBackupExtNameMap(bundleName);
518     return it->second.extInfo;
519 }
520 
AppendBundles(const vector<BundleName> & bundleNames)521 void SvcSessionManager::AppendBundles(const vector<BundleName> &bundleNames)
522 {
523     unique_lock<shared_mutex> lock(lock_);
524     if (!impl_.clientToken) {
525         throw BError(BError::Codes::SA_INVAL_ARG, "No caller token was specified");
526     }
527 
528     for (auto &&bundleName : bundleNames) {
529         HILOGD("bundleName: %{public}s", bundleName.c_str());
530         BackupExtInfo info {};
531         auto it = impl_.backupExtNameMap.find(bundleName);
532         if (it != impl_.backupExtNameMap.end()) {
533             HILOGI("BackupExtNameMap already contain %{public}s", bundleName.c_str());
534             info.backUpConnection = impl_.backupExtNameMap[bundleName].backUpConnection;
535             info.saBackupConnection = impl_.backupExtNameMap[bundleName].saBackupConnection;
536             info.appendNum = impl_.backupExtNameMap[bundleName].appendNum + 1;
537             impl_.backupExtNameMap[bundleName] = info;
538             continue;
539         }
540         if (SAUtils::IsSABundleName(bundleName)) {
541             info.saBackupConnection = GetBackupSAExt(bundleName);
542         } else {
543             info.backUpConnection = GetBackupAbilityExt(bundleName);
544         }
545         impl_.backupExtNameMap.insert(make_pair(bundleName, info));
546     }
547     impl_.isBackupStart = true;
548     impl_.isAppendFinish = true;
549 }
550 
CreateBackupConnection(BundleName & bundleName)551 sptr<SvcBackupConnection> SvcSessionManager::CreateBackupConnection(BundleName &bundleName)
552 {
553     HILOGD("SvcSessionManager::CreateBackupConnection begin.");
554     return GetBackupAbilityExt(bundleName);
555 }
556 
Start()557 void SvcSessionManager::Start()
558 {
559     unique_lock<shared_mutex> lock(lock_);
560     if (!impl_.clientToken) {
561         throw BError(BError::Codes::SA_INVAL_ARG, "No caller token was specified");
562     }
563     impl_.isBackupStart = true;
564 }
565 
Finish()566 void SvcSessionManager::Finish()
567 {
568     unique_lock<shared_mutex> lock(lock_);
569     if (!impl_.clientToken) {
570         throw BError(BError::Codes::SA_INVAL_ARG, "No caller token was specified");
571     }
572     impl_.isAppendFinish = true;
573 }
574 
IsOnAllBundlesFinished()575 bool SvcSessionManager::IsOnAllBundlesFinished()
576 {
577     shared_lock<shared_mutex> lock(lock_);
578     if (!impl_.clientToken) {
579         throw BError(BError::Codes::SA_INVAL_ARG, "No caller token was specified");
580     }
581     bool isAllBundlesFinished = !impl_.backupExtNameMap.size();
582     if (impl_.scenario == IServiceReverse::Scenario::RESTORE) {
583         bool isAllBundlesRestored = SvcRestoreDepsManager::GetInstance().IsAllBundlesRestored();
584         isAllBundlesFinished = (isAllBundlesFinished && isAllBundlesRestored);
585     }
586     HILOGD("isAllBundlesFinished:%{public}d", isAllBundlesFinished);
587     return isAllBundlesFinished;
588 }
589 
IsOnOnStartSched()590 bool SvcSessionManager::IsOnOnStartSched()
591 {
592     shared_lock<shared_mutex> lock(lock_);
593     if (!impl_.clientToken) {
594         throw BError(BError::Codes::SA_INVAL_ARG, "No caller token was specified");
595     }
596     if (impl_.isBackupStart && impl_.backupExtNameMap.size()) {
597         return true;
598     }
599 
600     return false;
601 }
602 
NeedToUnloadService()603 bool SvcSessionManager::NeedToUnloadService()
604 {
605     unique_lock<shared_mutex> lock(lock_);
606     if (impl_.restoreDataType == RestoreTypeEnum::RESTORE_DATA_READDY) {
607         return false;
608     }
609     bool isNeedToUnloadService = (!impl_.backupExtNameMap.size() && (sessionCnt_.load() <= 0));
610     if (impl_.scenario == IServiceReverse::Scenario::RESTORE) {
611         bool isAllBundlesRestored = SvcRestoreDepsManager::GetInstance().IsAllBundlesRestored();
612         isNeedToUnloadService = (isNeedToUnloadService && isAllBundlesRestored);
613     }
614     HILOGD("isNeedToUnloadService:%{public}d", isNeedToUnloadService);
615     return isNeedToUnloadService;
616 }
617 
SetBundleRestoreType(const std::string & bundleName,RestoreTypeEnum restoreType)618 void SvcSessionManager::SetBundleRestoreType(const std::string &bundleName, RestoreTypeEnum restoreType)
619 {
620     unique_lock<shared_mutex> lock(lock_);
621     if (!impl_.clientToken) {
622         throw BError(BError::Codes::SA_INVAL_ARG, "No caller token was specified");
623     }
624 
625     auto it = GetBackupExtNameMap(bundleName);
626     it->second.restoreType = restoreType;
627 }
628 
GetBundleRestoreType(const std::string & bundleName)629 RestoreTypeEnum SvcSessionManager::GetBundleRestoreType(const std::string &bundleName)
630 {
631     shared_lock<shared_mutex> lock(lock_);
632     if (!impl_.clientToken) {
633         throw BError(BError::Codes::SA_INVAL_ARG, "No caller token was specified");
634     }
635 
636     auto it = GetBackupExtNameMap(bundleName);
637     return it->second.restoreType;
638 }
639 
SetBundleVersionCode(const std::string & bundleName,int64_t versionCode)640 void SvcSessionManager::SetBundleVersionCode(const std::string &bundleName, int64_t versionCode)
641 {
642     unique_lock<shared_mutex> lock(lock_);
643     if (!impl_.clientToken) {
644         throw BError(BError::Codes::SA_INVAL_ARG, "No caller token was specified");
645     }
646 
647     auto it = GetBackupExtNameMap(bundleName);
648     it->second.versionCode = versionCode;
649 }
650 
GetBundleVersionCode(const std::string & bundleName)651 int64_t SvcSessionManager::GetBundleVersionCode(const std::string &bundleName)
652 {
653     shared_lock<shared_mutex> lock(lock_);
654     if (!impl_.clientToken) {
655         throw BError(BError::Codes::SA_INVAL_ARG, "No caller token was specified");
656     }
657 
658     auto it = GetBackupExtNameMap(bundleName);
659     return it->second.versionCode;
660 }
661 
SetBundleVersionName(const std::string & bundleName,std::string versionName)662 void SvcSessionManager::SetBundleVersionName(const std::string &bundleName, std::string versionName)
663 {
664     unique_lock<shared_mutex> lock(lock_);
665     if (!impl_.clientToken) {
666         throw BError(BError::Codes::SA_INVAL_ARG, "No caller token was specified");
667     }
668 
669     auto it = GetBackupExtNameMap(bundleName);
670     it->second.versionName = versionName;
671 }
672 
GetBundleVersionName(const std::string & bundleName)673 std::string SvcSessionManager::GetBundleVersionName(const std::string &bundleName)
674 {
675     shared_lock<shared_mutex> lock(lock_);
676     if (!impl_.clientToken) {
677         throw BError(BError::Codes::SA_INVAL_ARG, "No caller token was specified");
678     }
679 
680     auto it = GetBackupExtNameMap(bundleName);
681     return it->second.versionName;
682 }
683 
SetBundleDataSize(const std::string & bundleName,int64_t dataSize)684 void SvcSessionManager::SetBundleDataSize(const std::string &bundleName, int64_t dataSize)
685 {
686     unique_lock<shared_mutex> lock(lock_);
687     if (!impl_.clientToken) {
688         throw BError(BError::Codes::SA_INVAL_ARG, "No caller token was specified");
689     }
690 
691     auto it = GetBackupExtNameMap(bundleName);
692     it->second.dataSize = dataSize;
693 }
694 
CalAppProcessTime(const std::string & bundleName)695 uint32_t SvcSessionManager::CalAppProcessTime(const std::string &bundleName)
696 {
697     const int64_t minTimeout = 900;      /* 900 second */
698     const int64_t defaultTimeout = 30;           /* 30 second */
699     const int64_t processRate = 3 * 1024 * 1024; /* 3M/s */
700     const int64_t multiple = 3;
701     const int64_t invertMillisecond = 1000;
702     int64_t timeout;
703     uint32_t resTimeoutMs;
704 
705     try {
706         auto it = GetBackupExtNameMap(bundleName);
707         int64_t appSize = it->second.dataSize;
708         /* timeout = (AppSize / 3Ms) * 3 + 30 */
709         timeout = defaultTimeout + (appSize / processRate) * multiple;
710     } catch (const BError &e) {
711         HILOGE("Failed to get app<%{public}s> dataInfo, err=%{public}d", bundleName.c_str(), e.GetCode());
712         timeout = defaultTimeout;
713     }
714     timeout = timeout < minTimeout ? minTimeout : timeout;
715     resTimeoutMs = (uint32_t)(timeout * invertMillisecond % UINT_MAX); /* conver second to millisecond */
716     HILOGI("Calculate App extension process run timeout=%{public}u(ms), bundleName=%{public}s ", resTimeoutMs,
717            bundleName.c_str());
718     return resTimeoutMs;
719 }
720 
StartFwkTimer(const std::string & bundleName,const Utils::Timer::TimerCallback & callback)721 bool SvcSessionManager::StartFwkTimer(const std::string &bundleName, const Utils::Timer::TimerCallback &callback)
722 {
723     unique_lock<shared_mutex> lock(lock_);
724     HILOGI("StartFwkTimer begin bundleName %{public}s", bundleName.c_str());
725     if (!impl_.clientToken) {
726         HILOGE("No caller token was specified");
727         return false;
728     }
729     auto it = GetBackupExtNameMap(bundleName);
730     if (it->second.fwkTimerStatus == true) {
731         HILOGE("FwkTimer is registered, unregister first.");
732         return false;
733     }
734     uint32_t timeout = CalAppProcessTime(bundleName);
735 
736     it->second.fwkTimerStatus = true;
737     it->second.timerId = timer_.Register(callback, timeout, true);
738     HILOGI("StartFwkTimer end bundleName %{public}s", bundleName.c_str());
739     return true;
740 }
741 
StopFwkTimer(const std::string & bundleName)742 bool SvcSessionManager::StopFwkTimer(const std::string &bundleName)
743 {
744     unique_lock<shared_mutex> lock(lock_);
745     HILOGI("StopFwkTimer begin bundleName %{public}s", bundleName.c_str());
746     if (!impl_.clientToken) {
747         HILOGE("No caller token was specified");
748         return false;
749     }
750     auto it = GetBackupExtNameMap(bundleName);
751     if (it->second.fwkTimerStatus == false) {
752         HILOGE("FwkTimer is unregistered, register first.");
753         return true;
754     }
755 
756     it->second.fwkTimerStatus = false;
757     timer_.Unregister(it->second.timerId);
758     HILOGI("StopFwkTimer end bundleName %{public}s", bundleName.c_str());
759     return true;
760 }
761 
StartExtTimer(const std::string & bundleName,const Utils::Timer::TimerCallback & callback)762 bool SvcSessionManager::StartExtTimer(const std::string &bundleName, const Utils::Timer::TimerCallback &callback)
763 {
764     unique_lock<shared_mutex> lock(lock_);
765     HILOGI("StartExtTimer begin bundleName %{public}s", bundleName.c_str());
766     if (!impl_.clientToken) {
767         HILOGE("No caller token was specified");
768         return false;
769     }
770     auto it = GetBackupExtNameMap(bundleName);
771     if (it->second.extTimerStatus == true) {
772         HILOGE("ExtTimer is registered, unregister first.");
773         return false;
774     }
775     uint32_t timeout = it->second.timeout;
776     timeout = (timeout != BConstants::TIMEOUT_INVALID) ? timeout : BConstants::DEFAULT_TIMEOUT;
777     it->second.extTimerStatus = true;
778     it->second.timerId = timer_.Register(callback, timeout, true);
779     HILOGI("StartExtTimer end, timeout %{public}u(ms), bundleName %{public}s", timeout, bundleName.c_str());
780     return true;
781 }
782 
StopExtTimer(const std::string & bundleName)783 bool SvcSessionManager::StopExtTimer(const std::string &bundleName)
784 {
785     unique_lock<shared_mutex> lock(lock_);
786     HILOGI("StopExtTimer begin bundleName %{public}s", bundleName.c_str());
787     if (!impl_.clientToken) {
788         HILOGE("No caller token was specified");
789         return false;
790     }
791     auto it = GetBackupExtNameMap(bundleName);
792     if (it->second.extTimerStatus == false) {
793         HILOGE("ExtTimer is unregistered, register first.");
794         return true;
795     }
796 
797     it->second.extTimerStatus = false;
798     it->second.timeout = BConstants::TIMEOUT_INVALID;
799     timer_.Unregister(it->second.timerId);
800     HILOGI("StopExtTimer end bundleName %{public}s", bundleName.c_str());
801     return true;
802 }
803 
UpdateTimer(const std::string & bundleName,uint32_t timeout,const Utils::Timer::TimerCallback & callback)804 bool SvcSessionManager::UpdateTimer(const std::string &bundleName, uint32_t timeout,
805     const Utils::Timer::TimerCallback &callback)
806 {
807     unique_lock<shared_mutex> lock(lock_);
808     HILOGI("UpdateTimer begin bundleName %{public}s", bundleName.c_str());
809     if (!impl_.clientToken) {
810         HILOGE("No caller token was specified");
811         return false;
812     }
813     auto it = GetBackupExtNameMap(bundleName);
814     it->second.timeout = timeout;
815     if (it->second.extTimerStatus == false) {
816         HILOGI("ExtTimer is unregistered, just store timeout %{public}u(ms)", timeout);
817         return true;
818     }
819 
820     timer_.Unregister(it->second.timerId);
821     HILOGI("UpdateTimer timeout %{public}u(ms), bundleName %{public}s ", timeout, bundleName.c_str());
822     it->second.timerId = timer_.Register(callback, timeout, true);
823     it->second.extTimerStatus = true;
824     HILOGI("UpdateTimer end bundleName %{public}s", bundleName.c_str());
825     return true;
826 }
827 
IncreaseSessionCnt(const std::string funcName)828 void SvcSessionManager::IncreaseSessionCnt(const std::string funcName)
829 {
830     sessionCnt_++;
831     HILOGI("func name:%{public}s, %{public}d.", funcName.c_str(), sessionCnt_.load());
832 }
833 
DecreaseSessionCnt(const std::string funcName)834 void SvcSessionManager::DecreaseSessionCnt(const std::string funcName)
835 {
836     if (sessionCnt_.load() > 0) {
837         sessionCnt_--;
838     } else {
839         HILOGE("Invalid sessionCount.");
840     }
841     HILOGI("func name:%{public}s, %{public}d.", funcName.c_str(), sessionCnt_.load());
842 }
843 
ClearSessionData()844 ErrCode SvcSessionManager::ClearSessionData()
845 {
846     unique_lock<shared_mutex> lock(lock_);
847     ErrCode ret = BError(BError::Codes::OK);
848     for (auto &&it : impl_.backupExtNameMap) {
849         // clear timer
850         if (it.second.fwkTimerStatus == true || it.second.extTimerStatus == true) {
851             it.second.fwkTimerStatus = false;
852             it.second.extTimerStatus = false;
853             timer_.Unregister(it.second.timerId);
854         }
855         // disconnect extension
856         if (it.second.schedAction == BConstants::ServiceSchedAction::RUNNING) {
857             auto backUpConnection = it.second.backUpConnection;
858             if (backUpConnection == nullptr) {
859                 HILOGE("Clear session error, backUpConnection is empty");
860                 return BError(BError::Codes::SA_INVAL_ARG);
861             }
862             auto proxy = backUpConnection->GetBackupExtProxy();
863             if (proxy == nullptr) {
864                 HILOGE("Clear session error, proxy is empty");
865                 return BError(BError::Codes::EXT_INVAL_ARG);
866             }
867             if (impl_.restoreDataType != RestoreTypeEnum::RESTORE_DATA_READDY) {
868                 ret = proxy->HandleClear();
869             }
870             backUpConnection->DisconnectBackupExtAbility();
871         }
872         if (ret != BError(BError::Codes::OK)) {
873             return ret;
874         }
875         // clear data
876         it.second.schedAction = BConstants::ServiceSchedAction::FINISH;
877     }
878     impl_.backupExtNameMap.clear();
879     return BError(BError::Codes::OK);
880 }
881 
GetIsIncrementalBackup()882 bool SvcSessionManager::GetIsIncrementalBackup()
883 {
884     unique_lock<shared_mutex> lock(lock_);
885     if (!impl_.clientToken) {
886         throw BError(BError::Codes::SA_INVAL_ARG, "No caller token was specified");
887     }
888     return impl_.isIncrementalBackup;
889 }
890 
SetIncrementalData(const BIncrementalData & incrementalData)891 void SvcSessionManager::SetIncrementalData(const BIncrementalData &incrementalData)
892 {
893     unique_lock<shared_mutex> lock(lock_);
894     if (!impl_.clientToken) {
895         throw BError(BError::Codes::SA_INVAL_ARG, "No caller token was specified");
896     }
897     auto it = GetBackupExtNameMap(incrementalData.bundleName);
898     it->second.lastIncrementalTime = incrementalData.lastIncrementalTime;
899     it->second.manifestFd = incrementalData.manifestFd;
900     it->second.backupParameters = incrementalData.backupParameters;
901     it->second.backupPriority = incrementalData.backupPriority;
902 }
903 
GetIncrementalManifestFd(const string & bundleName)904 int32_t SvcSessionManager::GetIncrementalManifestFd(const string &bundleName)
905 {
906     unique_lock<shared_mutex> lock(lock_);
907     if (!impl_.clientToken) {
908         throw BError(BError::Codes::SA_INVAL_ARG, "No caller token was specified");
909     }
910     auto it = GetBackupExtNameMap(bundleName);
911     return it->second.manifestFd;
912 }
913 
GetLastIncrementalTime(const string & bundleName)914 int64_t SvcSessionManager::GetLastIncrementalTime(const string &bundleName)
915 {
916     unique_lock<shared_mutex> lock(lock_);
917     if (!impl_.clientToken) {
918         throw BError(BError::Codes::SA_INVAL_ARG, "No caller token was specified");
919     }
920     auto it = GetBackupExtNameMap(bundleName);
921     return it->second.lastIncrementalTime;
922 }
923 
GetMemParaCurSize()924 int32_t SvcSessionManager::GetMemParaCurSize()
925 {
926     return memoryParaCurSize_;
927 }
928 
SetMemParaCurSize(int32_t size)929 void SvcSessionManager::SetMemParaCurSize(int32_t size)
930 {
931     memoryParaCurSize_ = size;
932 }
933 
SetClearDataFlag(const std::string & bundleName,bool isClearData)934 void SvcSessionManager::SetClearDataFlag(const std::string &bundleName, bool isClearData)
935 {
936     unique_lock<shared_mutex> lock(lock_);
937     if (!impl_.clientToken) {
938         throw BError(BError::Codes::SA_INVAL_ARG, "No caller token was specified");
939     }
940     auto it = GetBackupExtNameMap(bundleName);
941     it->second.isClearData = isClearData;
942     HILOGI("bundleName:%{public}s, set clear data flag:%{public}d.", bundleName.c_str(), isClearData);
943 }
GetClearDataFlag(const std::string & bundleName)944 bool SvcSessionManager::GetClearDataFlag(const std::string &bundleName)
945 {
946     unique_lock<shared_mutex> lock(lock_);
947     if (!impl_.clientToken) {
948         throw BError(BError::Codes::SA_INVAL_ARG, "No caller token was specified");
949     }
950     auto it = GetBackupExtNameMap(bundleName);
951     return it->second.isClearData;
952 }
953 
ValidRestoreDataType(RestoreTypeEnum restoreDataType)954 bool SvcSessionManager::ValidRestoreDataType(RestoreTypeEnum restoreDataType)
955 {
956     return impl_.restoreDataType == restoreDataType;
957 }
958 
CleanAndCheckIfNeedWait(ErrCode & ret,std::vector<std::string> & bundleNameList)959 bool SvcSessionManager::CleanAndCheckIfNeedWait(ErrCode &ret, std::vector<std::string> &bundleNameList)
960 {
961     unique_lock<shared_mutex> lock(lock_);
962     for (auto it = impl_.backupExtNameMap.begin(); it != impl_.backupExtNameMap.end();) {
963         if (it->second.schedAction == BConstants::ServiceSchedAction::WAIT) {
964             it = impl_.backupExtNameMap.erase(it);
965         } else if (it->second.schedAction == BConstants::ServiceSchedAction::START ||
966             (it->second.schedAction == BConstants::ServiceSchedAction::RUNNING && !it->second.isInPublishFile)) {
967             if (it->second.fwkTimerStatus == true || it->second.extTimerStatus == true) {
968                 it->second.fwkTimerStatus = false;
969                 it->second.extTimerStatus = false;
970                 timer_.Unregister(it->second.timerId);
971             }
972             auto backUpConnection = it->second.backUpConnection;
973             if (backUpConnection == nullptr) {
974                 HILOGE("Clear session error, backUpConnection is empty");
975                 it = impl_.backupExtNameMap.erase(it);
976                 continue;
977             }
978             auto proxy = backUpConnection->GetBackupExtProxy();
979             // start action
980             if (proxy == nullptr) {
981                 HILOGE("Clear session error, backUpConnection is empty");
982                 backUpConnection->DisconnectBackupExtAbility();
983                 it = impl_.backupExtNameMap.erase(it);
984                 continue;
985             }
986             // running action
987             ErrCode retTmp = ERR_OK;
988             if (impl_.restoreDataType != RestoreTypeEnum::RESTORE_DATA_READDY) {
989                 retTmp = proxy->HandleClear();
990             }
991             if (retTmp == ERR_OK) {
992                 bundleNameList.push_back(it->first);
993             } else {
994                 ret = retTmp;
995             }
996             backUpConnection->DisconnectBackupExtAbility();
997             it = impl_.backupExtNameMap.erase(it);
998         } else {
999             ++it;
1000         }
1001     }
1002     if (impl_.backupExtNameMap.empty()) {
1003         HILOGI("Release normally, no need wait");
1004         return false;
1005     }
1006     HILOGI("Release abnormally, need wait for restore");
1007     return true;
1008 }
1009 
SetPublishFlag(const std::string & bundleName)1010 void SvcSessionManager::SetPublishFlag(const std::string &bundleName)
1011 {
1012     unique_lock<shared_mutex> lock(lock_);
1013     if (!impl_.clientToken) {
1014         throw BError(BError::Codes::SA_INVAL_ARG, "No caller token was specified");
1015     }
1016     auto it = GetBackupExtNameMap(bundleName);
1017     it->second.isInPublishFile = true;
1018     HILOGE("Set PublishFile success, bundleName = %{public}s", bundleName.c_str());
1019 }
1020 
SetImplRestoreType(const RestoreTypeEnum restoreType)1021 void SvcSessionManager::SetImplRestoreType(const RestoreTypeEnum restoreType)
1022 {
1023     impl_.restoreDataType = restoreType;
1024 }
1025 
SetIsReadyLaunch(const std::string & bundleName)1026 void SvcSessionManager::SetIsReadyLaunch(const std::string &bundleName)
1027 {
1028     unique_lock<shared_mutex> lock(lock_);
1029     if (!impl_.clientToken) {
1030         throw BError(BError::Codes::SA_INVAL_ARG, "No caller token was specified");
1031     }
1032     auto it = GetBackupExtNameMap(bundleName);
1033     it->second.isReadyLaunch = true;
1034     HILOGE("SetIsReadyLaunch success, bundleName = %{public}s", bundleName.c_str());
1035 }
1036 } // namespace OHOS::FileManagement::Backup
1037