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