• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2023 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_resources/b_constants.h"
30 #include "filemgmt_libhilog.h"
31 #include "module_external/bms_adapter.h"
32 #include "module_ipc/service.h"
33 
34 namespace OHOS::FileManagement::Backup {
35 using namespace std;
36 
VerifyCallerAndScenario(uint32_t clientToken,IServiceReverse::Scenario scenario) const37 void SvcSessionManager::VerifyCallerAndScenario(uint32_t clientToken, IServiceReverse::Scenario scenario) const
38 {
39     shared_lock<shared_mutex> lock(lock_);
40     if (impl_.scenario != scenario) {
41         throw BError(BError::Codes::SDK_MIXED_SCENARIO);
42     }
43     if (impl_.clientToken != clientToken) {
44         throw BError(BError::Codes::SA_REFUSED_ACT, "Caller mismatched");
45     }
46     HILOGE("Succeed to verify the caller");
47 }
48 
Active(Impl newImpl)49 void SvcSessionManager::Active(Impl newImpl)
50 {
51     unique_lock<shared_mutex> lock(lock_);
52     const Impl &oldImpl = impl_;
53     if (oldImpl.clientToken) {
54         throw BError(BError::Codes::SA_REFUSED_ACT, "Already have an active session");
55     }
56 
57     if (!newImpl.clientToken) {
58         throw BError(BError::Codes::SA_INVAL_ARG, "No caller token was specified");
59     }
60     if (newImpl.scenario == IServiceReverse::Scenario::UNDEFINED) {
61         throw BError(BError::Codes::SA_INVAL_ARG, "No scenario was specified");
62     }
63 
64     InitClient(newImpl);
65     impl_ = newImpl;
66 }
67 
Deactive(const wptr<IRemoteObject> & remoteInAction,bool force)68 void SvcSessionManager::Deactive(const wptr<IRemoteObject> &remoteInAction, bool force)
69 {
70     unique_lock<shared_mutex> lock(lock_);
71     if (!impl_.clientToken || !impl_.clientProxy) {
72         HILOGI("Empty session");
73         return;
74     }
75     if (!force && (!impl_.clientToken || !impl_.clientProxy)) {
76         throw BError(BError::Codes::SA_REFUSED_ACT, "Try to deactive an empty session");
77     }
78     auto remoteHeldByProxy = impl_.clientProxy->AsObject();
79     if (!force && (remoteInAction != remoteHeldByProxy)) {
80         throw BError(BError::Codes::SA_INVAL_ARG, "Only the client actived the session can deactive it");
81     }
82 
83     deathRecipient_ = nullptr;
84     HILOGI("Succeed to deactive a session");
85     impl_ = {};
86     extConnectNum_ = 0;
87 }
88 
VerifyBundleName(string & bundleName)89 void SvcSessionManager::VerifyBundleName(string &bundleName)
90 {
91     shared_lock<shared_mutex> lock(lock_);
92     if (!impl_.clientToken) {
93         throw BError(BError::Codes::SA_INVAL_ARG, "No caller token was specified");
94     }
95     auto asVerify = [&bundleName](const auto &it) { return it.first == bundleName; };
96     if (none_of(impl_.backupExtNameMap.begin(), impl_.backupExtNameMap.end(), asVerify)) {
97         stringstream ss;
98         ss << "Could not find the " << bundleName << " from current session";
99         throw BError(BError::Codes::SA_REFUSED_ACT, ss.str());
100     }
101     HILOGE("Succeed to verify the bundleName");
102 }
103 
GetServiceReverseProxy()104 sptr<IServiceReverse> SvcSessionManager::GetServiceReverseProxy()
105 {
106     unique_lock<shared_mutex> lock(lock_);
107     if (!impl_.clientProxy) {
108         throw BError(BError::Codes::SA_REFUSED_ACT, "Try to deactive an empty session");
109     }
110     return impl_.clientProxy;
111 }
112 
GetScenario()113 IServiceReverse::Scenario SvcSessionManager::GetScenario()
114 {
115     shared_lock<shared_mutex> lock(lock_);
116     if (!impl_.clientToken) {
117         throw BError(BError::Codes::SA_INVAL_ARG, "No caller token was specified");
118     }
119     return impl_.scenario;
120 }
121 
GetSessionUserId()122 int32_t SvcSessionManager::GetSessionUserId()
123 {
124     return impl_.userId;
125 }
126 
SetSessionUserId(int32_t userId)127 void SvcSessionManager::SetSessionUserId(int32_t userId)
128 {
129     impl_.userId = userId;
130 }
131 
OnBunleFileReady(const string & bundleName,const string & fileName)132 bool SvcSessionManager::OnBunleFileReady(const string &bundleName, const string &fileName)
133 {
134     unique_lock<shared_mutex> lock(lock_);
135     if (!impl_.clientToken) {
136         throw BError(BError::Codes::SA_INVAL_ARG, "No caller token was specified");
137     }
138 
139     auto it = impl_.backupExtNameMap.find(bundleName);
140     if (it == impl_.backupExtNameMap.end()) {
141         stringstream ss;
142         ss << "Could not find the " << bundleName << " from current session";
143         throw BError(BError::Codes::SA_REFUSED_ACT, ss.str());
144     }
145 
146     // 判断是否结束 通知EXTENTION清理资源  TOOL应用完成备份
147     if (impl_.scenario == IServiceReverse::Scenario::RESTORE) {
148         it->second.isBundleFinished = true;
149         return true;
150     } else if (impl_.scenario == IServiceReverse::Scenario::BACKUP) {
151         if (!fileName.empty() && fileName != BConstants::EXT_BACKUP_MANAGE) {
152             auto ret = it->second.fileNameInfo.insert(fileName);
153             if (!ret.second) {
154                 it->second.fileNameInfo.erase(fileName);
155             }
156         } else if (fileName.empty()) {
157             it->second.receExtAppDone = true;
158         }
159         if (it->second.receExtManageJson && it->second.fileNameInfo.empty() && it->second.receExtAppDone) {
160             it->second.isBundleFinished = true;
161             return true;
162         }
163     }
164     return false;
165 }
166 
OnBunleExtManageInfo(const string & bundleName,UniqueFd fd)167 UniqueFd SvcSessionManager::OnBunleExtManageInfo(const string &bundleName, UniqueFd fd)
168 {
169     if (!impl_.clientToken) {
170         throw BError(BError::Codes::SA_INVAL_ARG, "No caller token was specified");
171     }
172     if (impl_.scenario != IServiceReverse::Scenario::BACKUP) {
173         throw BError(BError::Codes::SA_INVAL_ARG, "Invalid Scenario");
174     }
175 
176     BJsonCachedEntity<BJsonEntityExtManage> cachedEntity(move(fd));
177     auto cache = cachedEntity.Structuralize();
178     auto info = cache.GetExtManage();
179 
180     for (auto &fileName : info) {
181         HILOGE("fileName %{public}s", fileName.data());
182         OnBunleFileReady(bundleName, fileName);
183     }
184 
185     unique_lock<shared_mutex> lock(lock_);
186     auto it = GetBackupExtNameMap(bundleName);
187     it->second.receExtManageJson = true;
188     return move(cachedEntity.GetFd());
189 }
190 
RemoveExtInfo(const string & bundleName)191 void SvcSessionManager::RemoveExtInfo(const string &bundleName)
192 {
193     HILOGI("Begin");
194     unique_lock<shared_mutex> lock(lock_);
195     auto it = impl_.backupExtNameMap.find(bundleName);
196     if (it == impl_.backupExtNameMap.end()) {
197         return;
198     }
199     impl_.backupExtNameMap.erase(it);
200     extConnectNum_--;
201 }
202 
GetExtConnection(const BundleName & bundleName)203 wptr<SvcBackupConnection> SvcSessionManager::GetExtConnection(const BundleName &bundleName)
204 {
205     HILOGI("Begin");
206     shared_lock<shared_mutex> lock(lock_);
207     if (!impl_.clientToken) {
208         throw BError(BError::Codes::SA_INVAL_ARG, "No caller token was specified");
209     }
210 
211     auto it = GetBackupExtNameMap(bundleName);
212     if (!it->second.backUpConnection) {
213         throw BError(BError::Codes::SA_INVAL_ARG, "Svc backup connection is empty");
214     }
215 
216     return wptr(it->second.backUpConnection);
217 }
218 
GetBackupExtAbility(const string & bundleName)219 sptr<SvcBackupConnection> SvcSessionManager::GetBackupExtAbility(const string &bundleName)
220 {
221     HILOGI("Begin");
222     auto callDied = [revPtr {reversePtr_}](const string &&bundleName) {
223         auto revPtrStrong = revPtr.promote();
224         if (!revPtrStrong) {
225             // 服务先于客户端死亡是一种异常场景,但该场景对本流程来说也没什么影响,所以只是简单记录一下
226             HILOGW("It's curious that the backup sa dies before the backup client");
227             return;
228         }
229         revPtrStrong->OnBackupExtensionDied(move(bundleName), ESRCH);
230     };
231 
232     auto callConnDone = [revPtr {reversePtr_}](const string &&bundleName) {
233         auto revPtrStrong = revPtr.promote();
234         if (!revPtrStrong) {
235             // 服务先于客户端死亡是一种异常场景,但该场景对本流程来说也没什么影响,所以只是简单记录一下
236             HILOGW("It's curious that the backup sa dies before the backup client");
237             return;
238         }
239         revPtrStrong->ExtConnectDone(move(bundleName));
240     };
241 
242     return sptr<SvcBackupConnection>(new SvcBackupConnection(callDied, callConnDone));
243 }
244 
DumpInfo(const int fd,const std::vector<std::u16string> & args)245 void SvcSessionManager::DumpInfo(const int fd, const std::vector<std::u16string> &args)
246 {
247     dprintf(fd, "---------------------backup info--------------------\n");
248     dprintf(fd, "Scenario: %d\n", impl_.scenario);
249 }
250 
InitClient(Impl & newImpl)251 void SvcSessionManager::InitClient(Impl &newImpl)
252 {
253     if (!newImpl.clientProxy) {
254         throw BError(BError::Codes::SA_INVAL_ARG, "Invalid client");
255     }
256     auto remoteObj = newImpl.clientProxy->AsObject();
257     if (!remoteObj) {
258         throw BError(BError::Codes::SA_BROKEN_IPC, "Proxy's remote object can't be nullptr");
259     }
260 
261     auto callback = [revPtr {reversePtr_}](const wptr<IRemoteObject> &obj) {
262         HILOGI("Client died.");
263 
264         auto revPtrStrong = revPtr.promote();
265         if (!revPtrStrong) {
266             // 服务先于客户端死亡是一种异常场景,但该场景对本流程来说也没什么影响,所以只是简单记录一下
267             HILOGW("It's curious that the backup sa dies before the backup client");
268             return;
269         }
270         (void)revPtrStrong->StopAll(obj);
271     };
272     deathRecipient_ = sptr(new SvcDeathRecipient(callback));
273     remoteObj->AddDeathRecipient(deathRecipient_);
274     HILOGI("Succeed to active a session");
275 }
276 
SetExtFileNameRequest(const string & bundleName,const string & fileName)277 void SvcSessionManager::SetExtFileNameRequest(const string &bundleName, const string &fileName)
278 {
279     HILOGI("Begin");
280     unique_lock<shared_mutex> lock(lock_);
281     if (!impl_.clientToken) {
282         throw BError(BError::Codes::SA_INVAL_ARG, "No caller token was specified");
283     }
284 
285     auto it = GetBackupExtNameMap(bundleName);
286     it->second.fileNameInfo.insert(fileName);
287 }
288 
GetExtFileNameRequest(const std::string & bundleName)289 std::set<std::string> SvcSessionManager::GetExtFileNameRequest(const std::string &bundleName)
290 {
291     HILOGI("Begin");
292     unique_lock<shared_mutex> lock(lock_);
293     if (!impl_.clientToken) {
294         throw BError(BError::Codes::SA_INVAL_ARG, "No caller token was specified");
295     }
296 
297     if (impl_.scenario != IServiceReverse::Scenario::RESTORE) {
298         throw BError(BError::Codes::SA_INVAL_ARG, "Invalid Scenario");
299     }
300     auto it = GetBackupExtNameMap(bundleName);
301     set<string> fileNameInfo = it->second.fileNameInfo;
302     it->second.fileNameInfo.clear();
303     return fileNameInfo;
304 }
305 
GetBackupExtNameMap(const string & bundleName)306 map<BundleName, BackupExtInfo>::iterator SvcSessionManager::GetBackupExtNameMap(const string &bundleName)
307 {
308     auto it = impl_.backupExtNameMap.find(bundleName);
309     if (it == impl_.backupExtNameMap.end()) {
310         stringstream ss;
311         ss << "Could not find the " << bundleName << " from current session";
312         throw BError(BError::Codes::SA_REFUSED_ACT, ss.str());
313     }
314     return it;
315 }
316 
GetSchedBundleName(string & bundleName)317 bool SvcSessionManager::GetSchedBundleName(string &bundleName)
318 {
319     HILOGI("Begin");
320     shared_lock<shared_mutex> lock(lock_);
321     if (extConnectNum_ >= BConstants::EXT_CONNECT_MAX_COUNT) {
322         return false;
323     }
324 
325     for (auto &&it : impl_.backupExtNameMap) {
326         if (it.second.schedAction == BConstants::ServiceSchedAction::WAIT) {
327             bundleName = it.first;
328             return true;
329         }
330     }
331     return false;
332 }
333 
GetServiceSchedAction(const std::string & bundleName)334 BConstants::ServiceSchedAction SvcSessionManager::GetServiceSchedAction(const std::string &bundleName)
335 {
336     HILOGI("Begin");
337     shared_lock<shared_mutex> lock(lock_);
338     if (!impl_.clientToken) {
339         throw BError(BError::Codes::SA_INVAL_ARG, "No caller token was specified");
340     }
341     auto it = GetBackupExtNameMap(bundleName);
342     return it->second.schedAction;
343 }
344 
SetServiceSchedAction(const string & bundleName,BConstants::ServiceSchedAction action)345 void SvcSessionManager::SetServiceSchedAction(const string &bundleName, BConstants::ServiceSchedAction action)
346 {
347     HILOGI("Begin");
348     unique_lock<shared_mutex> lock(lock_);
349     if (!impl_.clientToken) {
350         throw BError(BError::Codes::SA_INVAL_ARG, "No caller token was specified");
351     }
352 
353     auto it = GetBackupExtNameMap(bundleName);
354     it->second.schedAction = action;
355     if (it->second.schedAction == BConstants::ServiceSchedAction::INSTALLING) {
356         extConnectNum_++;
357     }
358 }
359 
GetBackupExtName(const string & bundleName)360 string SvcSessionManager::GetBackupExtName(const string &bundleName)
361 {
362     HILOGI("Begin");
363     shared_lock<shared_mutex> lock(lock_);
364     if (!impl_.clientToken) {
365         throw BError(BError::Codes::SA_INVAL_ARG, "No caller token was specified");
366     }
367     string name = bundleName;
368     VerifyBundleName(name);
369     auto bundleInfos = BundleMgrAdapter::GetBundleInfos({bundleName}, impl_.userId);
370     for (auto &&bundleInfo : bundleInfos) {
371         if (!bundleInfo.allToBackup || bundleInfo.extensionName.empty()) {
372             throw BError(BError::Codes::SA_INVAL_ARG,
373                          string(bundleInfo.name).append(" is not allow to backup or extension name is empty"));
374         }
375         if (bundleInfo.name == bundleName) {
376             return bundleInfo.extensionName;
377         }
378     }
379     throw BError(BError::Codes::SA_INVAL_ARG, "Could not find the extension name");
380 }
381 
AppendBundles(const vector<BundleName> & bundleNames)382 void SvcSessionManager::AppendBundles(const vector<BundleName> &bundleNames)
383 {
384     HILOGI("Begin");
385     unique_lock<shared_mutex> lock(lock_);
386     if (!impl_.clientToken) {
387         throw BError(BError::Codes::SA_INVAL_ARG, "No caller token was specified");
388     }
389 
390     for (auto &&bundleName : bundleNames) {
391         BackupExtInfo info {};
392         info.backUpConnection = GetBackupExtAbility(bundleName);
393         impl_.backupExtNameMap.insert(make_pair(bundleName, info));
394     }
395 }
396 
Start()397 void SvcSessionManager::Start()
398 {
399     HILOGI("Begin");
400     unique_lock<shared_mutex> lock(lock_);
401     if (!impl_.clientToken) {
402         throw BError(BError::Codes::SA_INVAL_ARG, "No caller token was specified");
403     }
404     impl_.isBackupStart = true;
405 }
406 
Finish()407 void SvcSessionManager::Finish()
408 {
409     HILOGI("Begin");
410     unique_lock<shared_mutex> lock(lock_);
411     if (!impl_.clientToken) {
412         throw BError(BError::Codes::SA_INVAL_ARG, "No caller token was specified");
413     }
414     impl_.isAppendFinish = true;
415 }
416 
IsOnAllBundlesFinished()417 bool SvcSessionManager::IsOnAllBundlesFinished()
418 {
419     shared_lock<shared_mutex> lock(lock_);
420     if (!impl_.clientToken) {
421         throw BError(BError::Codes::SA_INVAL_ARG, "No caller token was specified");
422     }
423     auto iter = find_if(impl_.backupExtNameMap.begin(), impl_.backupExtNameMap.end(),
424                         [](const auto &it) { return it.second.isBundleFinished == false; });
425     if (iter == impl_.backupExtNameMap.end() && impl_.isAppendFinish) {
426         return true;
427     }
428     return false;
429 }
430 
IsOnOnStartSched()431 bool SvcSessionManager::IsOnOnStartSched()
432 {
433     shared_lock<shared_mutex> lock(lock_);
434     if (!impl_.clientToken) {
435         throw BError(BError::Codes::SA_INVAL_ARG, "No caller token was specified");
436     }
437     if (impl_.isBackupStart && impl_.backupExtNameMap.size()) {
438         return true;
439     }
440 
441     return false;
442 }
443 
SetInstallState(const string & bundleName,const string & state)444 void SvcSessionManager::SetInstallState(const string &bundleName, const string &state)
445 {
446     HILOGI("Begin");
447     unique_lock<shared_mutex> lock(lock_);
448     if (!impl_.clientToken) {
449         throw BError(BError::Codes::SA_INVAL_ARG, "No caller token was specified");
450     }
451 
452     auto it = GetBackupExtNameMap(bundleName);
453     it->second.installState = state;
454 }
455 
GetInstallState(const string & bundleName)456 string SvcSessionManager::GetInstallState(const string &bundleName)
457 {
458     HILOGI("Begin");
459     unique_lock<shared_mutex> lock(lock_);
460     if (!impl_.clientToken) {
461         throw BError(BError::Codes::SA_INVAL_ARG, "No caller token was specified");
462     }
463 
464     auto it = GetBackupExtNameMap(bundleName);
465     return it->second.installState;
466 }
467 
SetNeedToInstall(const std::string & bundleName,bool needToInstall)468 void SvcSessionManager::SetNeedToInstall(const std::string &bundleName, bool needToInstall)
469 {
470     HILOGI("Begin");
471     unique_lock<shared_mutex> lock(lock_);
472     if (!impl_.clientToken) {
473         throw BError(BError::Codes::SA_INVAL_ARG, "No caller token was specified");
474     }
475 
476     auto it = GetBackupExtNameMap(bundleName);
477     it->second.bNeedToInstall = needToInstall;
478 }
479 
GetNeedToInstall(const std::string & bundleName)480 bool SvcSessionManager::GetNeedToInstall(const std::string &bundleName)
481 {
482     HILOGI("Begin");
483     unique_lock<shared_mutex> lock(lock_);
484     if (!impl_.clientToken) {
485         throw BError(BError::Codes::SA_INVAL_ARG, "No caller token was specified");
486     }
487 
488     auto it = GetBackupExtNameMap(bundleName);
489     return it->second.bNeedToInstall;
490 }
491 
NeedToUnloadService()492 bool SvcSessionManager::NeedToUnloadService()
493 {
494     unique_lock<shared_mutex> lock(lock_);
495     if (!impl_.clientToken || !impl_.clientProxy || !impl_.backupExtNameMap.size()) {
496         return true;
497     }
498     return false;
499 }
500 
SetBundleRestoreType(const std::string & bundleName,RestoreTypeEnum restoreType)501 void SvcSessionManager::SetBundleRestoreType(const std::string &bundleName, RestoreTypeEnum restoreType)
502 {
503     unique_lock<shared_mutex> lock(lock_);
504     if (!impl_.clientToken) {
505         throw BError(BError::Codes::SA_INVAL_ARG, "No caller token was specified");
506     }
507 
508     auto it = GetBackupExtNameMap(bundleName);
509     it->second.restoreType = restoreType;
510 }
511 
GetBundleRestoreType(const std::string & bundleName)512 RestoreTypeEnum SvcSessionManager::GetBundleRestoreType(const std::string &bundleName)
513 {
514     unique_lock<shared_mutex> lock(lock_);
515     if (!impl_.clientToken) {
516         throw BError(BError::Codes::SA_INVAL_ARG, "No caller token was specified");
517     }
518 
519     auto it = GetBackupExtNameMap(bundleName);
520     return it->second.restoreType;
521 }
522 
SetBundleVersionCode(const std::string & bundleName,uint32_t versionCode)523 void SvcSessionManager::SetBundleVersionCode(const std::string &bundleName, uint32_t versionCode)
524 {
525     unique_lock<shared_mutex> lock(lock_);
526     if (!impl_.clientToken) {
527         throw BError(BError::Codes::SA_INVAL_ARG, "No caller token was specified");
528     }
529 
530     auto it = GetBackupExtNameMap(bundleName);
531     it->second.versionCode = versionCode;
532 }
533 
GetBundleVersionCode(const std::string & bundleName)534 uint32_t SvcSessionManager::GetBundleVersionCode(const std::string &bundleName)
535 {
536     unique_lock<shared_mutex> lock(lock_);
537     if (!impl_.clientToken) {
538         throw BError(BError::Codes::SA_INVAL_ARG, "No caller token was specified");
539     }
540 
541     auto it = GetBackupExtNameMap(bundleName);
542     return it->second.versionCode;
543 }
544 
SetBundleVersionName(const std::string & bundleName,std::string versionName)545 void SvcSessionManager::SetBundleVersionName(const std::string &bundleName, std::string versionName)
546 {
547     unique_lock<shared_mutex> lock(lock_);
548     if (!impl_.clientToken) {
549         throw BError(BError::Codes::SA_INVAL_ARG, "No caller token was specified");
550     }
551 
552     auto it = GetBackupExtNameMap(bundleName);
553     it->second.versionName = versionName;
554 }
555 
GetBundleVersionName(const std::string & bundleName)556 std::string SvcSessionManager::GetBundleVersionName(const std::string &bundleName)
557 {
558     unique_lock<shared_mutex> lock(lock_);
559     if (!impl_.clientToken) {
560         throw BError(BError::Codes::SA_INVAL_ARG, "No caller token was specified");
561     }
562 
563     auto it = GetBackupExtNameMap(bundleName);
564     return it->second.versionName;
565 }
566 } // namespace OHOS::FileManagement::Backup