From fbe31452b28f69da89299037093cd2a12d1827f2 Mon Sep 17 00:00:00 2001 From: yang-jingbo1985 Date: Sat, 21 Oct 2023 20:50:06 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E5=A4=87=E4=BB=BD=E6=81=A2=E5=A4=8D?= =?UTF-8?q?=E4=B8=BA=E4=BA=91=E5=A4=87=E4=BB=BD=E6=94=AF=E6=8C=81=E6=81=A2?= =?UTF-8?q?=E5=A4=8D=E4=BC=98=E5=85=88=E7=BA=A7=E8=83=BD=E5=8A=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: yang-jingbo1985 --- services/backup_sa/BUILD.gn | 1 + .../module_ipc/svc_restore_deps_manager.h | 61 ++++++++ .../src/module_external/bms_adapter.cpp | 14 +- services/backup_sa/src/module_ipc/service.cpp | 39 ++++- .../module_ipc/svc_restore_deps_manager.cpp | 144 ++++++++++++++++++ .../src/module_ipc/svc_session_manager.cpp | 23 ++- tests/unittests/backup_sa/module_ipc/BUILD.gn | 2 + utils/include/b_json/b_json_entity_caps.h | 16 +- .../b_json/b_json_entity_extension_config.h | 2 + .../b_json/b_json_entity_extension_config.cpp | 11 ++ 10 files changed, 294 insertions(+), 19 deletions(-) create mode 100644 services/backup_sa/include/module_ipc/svc_restore_deps_manager.h create mode 100644 services/backup_sa/src/module_ipc/svc_restore_deps_manager.cpp diff --git a/services/backup_sa/BUILD.gn b/services/backup_sa/BUILD.gn index 16e1f6529..d589c50d6 100644 --- a/services/backup_sa/BUILD.gn +++ b/services/backup_sa/BUILD.gn @@ -24,6 +24,7 @@ ohos_shared_library("backup_sa") { "src/module_ipc/service_stub.cpp", "src/module_ipc/svc_backup_connection.cpp", "src/module_ipc/svc_extension_proxy.cpp", + "src/module_ipc/svc_restore_deps_manager.cpp", "src/module_ipc/svc_session_manager.cpp", "src/module_sched/sched_scheduler.cpp", ] diff --git a/services/backup_sa/include/module_ipc/svc_restore_deps_manager.h b/services/backup_sa/include/module_ipc/svc_restore_deps_manager.h new file mode 100644 index 000000000..263f8d5a7 --- /dev/null +++ b/services/backup_sa/include/module_ipc/svc_restore_deps_manager.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_FILEMGMT_BACKUP_SVC_RESTORE_DEPS_MANAGER_H +#define OHOS_FILEMGMT_BACKUP_SVC_RESTORE_DEPS_MANAGER_H + +#include +#include + +#include "b_json/b_json_entity_caps.h" + +namespace OHOS::FileManagement::Backup { +using namespace std; + +class SvcRestoreDepsManager { +public: + static SvcRestoreDepsManager &GetInstance() + { + static SvcRestoreDepsManager manager; + return manager; + } + + vector GetRestoreBundleNames(const vector &infos); + void AddRestoredBundles(const string &bundleName); + vector GetRestoreBundleNames(); + vector GetAllBundles() const; + bool IsAllBundlesRestored() const; + +private: + SvcRestoreDepsManager() {} + ~SvcRestoreDepsManager() = default; + SvcRestoreDepsManager(const SvcRestoreDepsManager &manager) = delete; + SvcRestoreDepsManager &operator=(const SvcRestoreDepsManager &manager) = delete; + + void BuildDepsMap(const vector &infos); + vector SplitString(const string &str, char delim); + void AddBundles(vector &bundles, const string &bundleName); + bool IsAllDepsRestored(const string &bundleName); + + map> depsMap_ {}; + vector allBundles_ {}; // 所有的应用 + + vector toRestoreBundles_ {}; // 有依赖的应用 + vector restoredBundles_ {}; // 已经恢复完成的应用 +}; + +} // namespace OHOS::FileManagement::Backup + +#endif // OHOS_FILEMGMT_BACKUP_SVC_RESTORE_DEPS_MANAGER_H diff --git a/services/backup_sa/src/module_external/bms_adapter.cpp b/services/backup_sa/src/module_external/bms_adapter.cpp index 571bce2a0..1e4da6bd4 100644 --- a/services/backup_sa/src/module_external/bms_adapter.cpp +++ b/services/backup_sa/src/module_external/bms_adapter.cpp @@ -61,7 +61,7 @@ static sptr GetBundleManager() return iface_cast(bundleObj); } -static tuple GetAllowAndExtName(const vector &extensionInfos) +static tuple GetAllowAndExtName(const vector &extensionInfos) { for (auto &&ext : extensionInfos) { if (ext.type != AppExecFwk::ExtensionAbilityType::BACKUP) { @@ -74,10 +74,10 @@ static tuple GetAllowAndExtName(const vector cachedEntity(out[0], ext.bundleName); auto cache = cachedEntity.Structuralize(); - return {cache.GetAllowToBackupRestore(), ext.name}; + return {cache.GetAllowToBackupRestore(), ext.name, cache.GetRestoreDeps()}; } HILOGI("No backup extension ability found"); - return {false, ""}; + return {false, "", ""}; } static int64_t GetBundleStats(const string &bundleName, int32_t userId) @@ -117,11 +117,11 @@ vector BundleMgrAdapter::GetBundleInfos(int32_t use HILOGI("Unsupported applications, name : %{public}s", installedBundle.name.data()); continue; } - auto [allToBackup, extName] = GetAllowAndExtName(installedBundle.extensionInfos); + auto [allToBackup, extName, restoreDeps] = GetAllowAndExtName(installedBundle.extensionInfos); auto dataSize = GetBundleStats(installedBundle.name, userId); bundleInfos.emplace_back(BJsonEntityCaps::BundleInfo {installedBundle.name, installedBundle.versionCode, installedBundle.versionName, dataSize, allToBackup, - extName}); + extName, false, restoreDeps}); } return bundleInfos; } @@ -141,11 +141,11 @@ vector BundleMgrAdapter::GetBundleInfos(const vecto HILOGI("Unsupported applications, name : %{public}s", installedBundle.name.data()); continue; } - auto [allToBackup, extName] = GetAllowAndExtName(installedBundle.extensionInfos); + auto [allToBackup, extName, restoreDeps] = GetAllowAndExtName(installedBundle.extensionInfos); auto dataSize = GetBundleStats(installedBundle.name, userId); bundleInfos.emplace_back(BJsonEntityCaps::BundleInfo {installedBundle.name, installedBundle.versionCode, installedBundle.versionName, dataSize, allToBackup, - extName}); + extName, false, restoreDeps}); } return bundleInfos; } diff --git a/services/backup_sa/src/module_ipc/service.cpp b/services/backup_sa/src/module_ipc/service.cpp index 30ec68790..35f06428c 100644 --- a/services/backup_sa/src/module_ipc/service.cpp +++ b/services/backup_sa/src/module_ipc/service.cpp @@ -50,6 +50,7 @@ #include "ipc_skeleton.h" #include "module_external/bms_adapter.h" #include "module_ipc/svc_backup_connection.h" +#include "module_ipc/svc_restore_deps_manager.h" #include "parameter.h" #include "system_ability_definition.h" @@ -246,8 +247,20 @@ ErrCode Service::AppendBundlesRestoreSession(UniqueFd fd, if (!bundleInfos.size()) { throw BError(BError::Codes::SA_INVAL_ARG, "Json entity caps is empty"); } - session_->AppendBundles(bundleNames); - for (auto bundleName : bundleNames) { + + vector restoreBundleInfos {}; + for (auto &bundleInfo : bundleInfos) { + if (find(bundleNames.begin(), bundleNames.end(), bundleInfo.name) != bundleNames.end()) { + restoreBundleInfos.push_back(bundleInfo); + } + } + vector restoreBundleNames = SvcRestoreDepsManager::GetInstance().GetRestoreBundleNames(restoreBundleInfos); + if (restoreBundleNames.empty()) { + return BError(BError::Codes::OK); + } + + session_->AppendBundles(restoreBundleNames); + for (auto bundleName : restoreBundleNames) { HILOGD("bundleName: %{public}s", bundleName.c_str()); for (auto &&bundleInfo : bundleInfos) { if (bundleInfo.name != bundleName) { @@ -657,6 +670,28 @@ void Service::ClearSessionAndSchedInfo(const string &bundleName) try { session_->RemoveExtInfo(bundleName); sched_->RemoveExtConn(bundleName); + + if (session_->GetScenario() == IServiceReverse::Scenario::RESTORE) { + SvcRestoreDepsManager::GetInstance().AddRestoredBundles(bundleName); + + // 该应用恢复完成,判断依赖hap的前置hap是否全部恢复完成,如果成了,追加该依赖hap + vector restoreBundleNames = SvcRestoreDepsManager::GetInstance().GetRestoreBundleNames(); + if (!restoreBundleNames.empty()) { // 启动恢复会话 + session_->AppendBundles(restoreBundleNames); + for (auto &bundleName : restoreBundleNames) { + for (auto &bundleInfo : SvcRestoreDepsManager::GetInstance().GetAllBundles()) { + if (bundleName == bundleInfo.name) { + session_->SetNeedToInstall(bundleInfo.name, bundleInfo.needToInstall); + session_->SetBundleRestoreType(bundleInfo.name, RESTORE_DATA_WAIT_SEND); + session_->SetBundleVersionCode(bundleInfo.name, bundleInfo.versionCode); + session_->SetBundleVersionName(bundleInfo.name, bundleInfo.versionName); + session_->SetBundleDataSize(bundleInfo.name, bundleInfo.spaceOccupied); + } + } + } + } + } + sched_->Sched(); } catch (const BError &e) { return; diff --git a/services/backup_sa/src/module_ipc/svc_restore_deps_manager.cpp b/services/backup_sa/src/module_ipc/svc_restore_deps_manager.cpp new file mode 100644 index 000000000..d5ed966cb --- /dev/null +++ b/services/backup_sa/src/module_ipc/svc_restore_deps_manager.cpp @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "module_ipc/svc_restore_deps_manager.h" + +#include "filemgmt_libhilog.h" + +namespace OHOS::FileManagement::Backup { + +vector SvcRestoreDepsManager::GetRestoreBundleNames(const vector &bundleInfos) +{ + HILOGI("SvcRestoreDepsManager::GetRestoreBundleNames, bundleInfos.size():%{public}d", bundleInfos.size()); + vector restoreBundleNames {}; // 需要恢复的应用列表 + + BuildDepsMap(bundleInfos); // 构建依赖Map + + for (auto &bundleInfo : bundleInfos) { + string restoreDeps = bundleInfo.restoreDeps; + if (restoreDeps.empty()) { + // 将没有依赖的应用加入到需要恢复的应用列表 + restoreBundleNames.emplace_back(bundleInfo.name); + } else { + AddBundles(toRestoreBundles_, bundleInfo.name); + + // 如果该应用的依赖项已经完成备份,也需要加到需要恢复的应用列表 + if (IsAllDepsRestored(bundleInfo.name)) { + AddBundles(restoreBundleNames, bundleInfo.name); + toRestoreBundles_.erase(remove(toRestoreBundles_.begin(), toRestoreBundles_.end(), bundleInfo.name), + toRestoreBundles_.end()); + } + } + } + + return restoreBundleNames; +} + +vector SvcRestoreDepsManager::GetRestoreBundleNames() +{ + HILOGI("SvcRestoreDepsManager::GetRestoreBundleNames"); + vector restoreBundleNames {}; // 需要恢复的应用列表 + for (auto &bundle : toRestoreBundles_) { // 所有有依赖的应用 + // 如果该应用的依赖项已经完成备份,也需要加到 restoreBundleNames + if (IsAllDepsRestored(bundle)) { + AddBundles(restoreBundleNames, bundle); + toRestoreBundles_.erase(remove(toRestoreBundles_.begin(), toRestoreBundles_.end(), bundle), + toRestoreBundles_.end()); + } + } + return restoreBundleNames; +} + +bool SvcRestoreDepsManager::IsAllDepsRestored(const string &bundle) +{ + HILOGI("SvcRestoreDepsManager::IsAllDepsRestored, bundle:%{public}s", bundle.c_str()); + if (depsMap_.find(bundle) == depsMap_.end()) { + return false; + } + bool isAllDepsRestored = true; + vector depList = depsMap_[bundle]; + for (auto &dep : depList) { + if (find(restoredBundles_.begin(), restoredBundles_.end(), dep) == restoredBundles_.end()) { + isAllDepsRestored = false; + break; + } + } + HILOGI("SvcRestoreDepsManager::IsAllDepsRestored, isAllDepsRestored:%{public}d", isAllDepsRestored); + return isAllDepsRestored; +} + +void SvcRestoreDepsManager::BuildDepsMap(const vector &bundleInfos) +{ + HILOGI("SvcRestoreDepsManager::BuildDepsMap, bundleInfos.size():%{public}d", bundleInfos.size()); + for (auto &bundleInfo : bundleInfos) { + if (depsMap_.find(bundleInfo.name) != depsMap_.end()) { + continue; + } + allBundles_.emplace_back(bundleInfo); + + vector depsList {}; + string restoreDeps = bundleInfo.restoreDeps; + if (restoreDeps.find(",") != string::npos) { + depsList = SplitString(restoreDeps, ','); + } else { + if (!restoreDeps.empty()) { + depsList.emplace_back(restoreDeps); + } + } + + depsMap_.insert(make_pair(bundleInfo.name, depsList)); + } +} + +vector SvcRestoreDepsManager::SplitString(const string &str, char delim) +{ + HILOGI("SvcRestoreDepsManager::SplitString, str:%{public}s", str.c_str()); + stringstream ss(str); + string item {}; + vector results {}; + while (getline(ss, item, delim)) { + if (!item.empty()) { + results.push_back(item); + } + } + HILOGI("SvcRestoreDepsManager::SplitString, results.size():%{public}d", results.size()); + return results; +} + +void SvcRestoreDepsManager::AddBundles(vector &bundles, const string &bundleName) +{ + if (find(bundles.begin(), bundles.end(), bundleName) == bundles.end()) { + HILOGI("SvcRestoreDepsManager::AddBundles, bundleName:%{public}s", bundleName.c_str()); + bundles.emplace_back(bundleName); + } +} + +void SvcRestoreDepsManager::AddRestoredBundles(const string &bundleName) +{ + HILOGI("SvcRestoreDepsManager::AddRestoredBundles, bundleName:%{public}s", bundleName.c_str()); + AddBundles(restoredBundles_, bundleName); +} + +vector SvcRestoreDepsManager::GetAllBundles() const +{ + return allBundles_; +} + +bool SvcRestoreDepsManager::IsAllBundlesRestored() const +{ + return toRestoreBundles_.empty(); +} + +} // namespace OHOS::FileManagement::Backup \ No newline at end of file diff --git a/services/backup_sa/src/module_ipc/svc_session_manager.cpp b/services/backup_sa/src/module_ipc/svc_session_manager.cpp index a117a6fe7..615fc1171 100644 --- a/services/backup_sa/src/module_ipc/svc_session_manager.cpp +++ b/services/backup_sa/src/module_ipc/svc_session_manager.cpp @@ -31,6 +31,7 @@ #include "module_external/bms_adapter.h" #include "module_external/sms_adapter.h" #include "module_ipc/service.h" +#include "module_ipc/svc_restore_deps_manager.h" namespace OHOS::FileManagement::Backup { using namespace std; @@ -426,10 +427,13 @@ bool SvcSessionManager::IsOnAllBundlesFinished() } auto iter = find_if(impl_.backupExtNameMap.begin(), impl_.backupExtNameMap.end(), [](const auto &it) { return it.second.isBundleFinished == false; }); - if (iter == impl_.backupExtNameMap.end() && impl_.isAppendFinish) { - return true; + bool isAllBundlesFinished = (iter == impl_.backupExtNameMap.end() && impl_.isAppendFinish); + if (impl_.scenario == IServiceReverse::Scenario::RESTORE) { + bool isAllBundlesRestored = SvcRestoreDepsManager::GetInstance().IsAllBundlesRestored(); + isAllBundlesFinished = (isAllBundlesFinished && isAllBundlesRestored); } - return false; + + return isAllBundlesFinished; } bool SvcSessionManager::IsOnOnStartSched() @@ -496,10 +500,13 @@ bool SvcSessionManager::GetNeedToInstall(const std::string &bundleName) bool SvcSessionManager::NeedToUnloadService() { unique_lock lock(lock_); - if (!impl_.clientToken || !impl_.clientProxy || !impl_.backupExtNameMap.size()) { - return true; - } - return false; + bool isNeedToUnloadService = (!impl_.clientToken || !impl_.clientProxy || !impl_.backupExtNameMap.size()); + if (impl_.scenario == IServiceReverse::Scenario::RESTORE) { + bool isAllBundlesRestored = SvcRestoreDepsManager::GetInstance().IsAllBundlesRestored(); + isNeedToUnloadService = (isNeedToUnloadService && isAllBundlesRestored); + } + + return isNeedToUnloadService; } void SvcSessionManager::SetBundleRestoreType(const std::string &bundleName, RestoreTypeEnum restoreType) @@ -635,4 +642,4 @@ void SvcSessionManager::BundleExtTimerStop(const std::string &bundleName) } } -} // namespace OHOS::FileManagement::Backup- +} // namespace OHOS::FileManagement::Backup diff --git a/tests/unittests/backup_sa/module_ipc/BUILD.gn b/tests/unittests/backup_sa/module_ipc/BUILD.gn index 4d7d4a39c..8ab1aeab9 100644 --- a/tests/unittests/backup_sa/module_ipc/BUILD.gn +++ b/tests/unittests/backup_sa/module_ipc/BUILD.gn @@ -59,6 +59,7 @@ ohos_unittest("backup_service_test") { sources = [ "${path_backup_mock}/accesstoken/accesstoken_kit_mock.cpp", "${path_backup}/services/backup_sa/src/module_ipc/service.cpp", + "${path_backup}/services/backup_sa/src/module_ipc/svc_restore_deps_manager.cpp", "service_test.cpp", ] sources += backup_mock_src @@ -103,6 +104,7 @@ ohos_unittest("backup_service_session_test") { sources = [ "${path_backup_mock}/affwk/service_registry_mock.cpp", "${path_backup_mock}/bundle_manager/src/mock_bundle_manager.cpp", + "${path_backup}/services/backup_sa/src/module_ipc/svc_restore_deps_manager.cpp", "${path_backup}/services/backup_sa/src/module_ipc/svc_session_manager.cpp", "svc_session_manager_test.cpp", ] diff --git a/utils/include/b_json/b_json_entity_caps.h b/utils/include/b_json/b_json_entity_caps.h index 9ab7bc212..ecb9a4461 100644 --- a/utils/include/b_json/b_json_entity_caps.h +++ b/utils/include/b_json/b_json_entity_caps.h @@ -30,6 +30,7 @@ public: bool allToBackup; std::string extensionName; bool needToInstall {false}; + std::string restoreDeps; }; public: @@ -57,6 +58,7 @@ public: arrObj["allToBackup"] = item.allToBackup; arrObj["extensionName"] = item.extensionName; arrObj["needToInstall"] = item.needToInstall; + arrObj["restoreDeps"] = item.restoreDeps; obj_["bundleInfos"].append(arrObj); } } @@ -81,6 +83,16 @@ public: return obj_["deviceType"].asString(); } + std::string GetRestoreDeps() + { + if (!obj_ || !obj_.isMember("restoreDeps") || !obj_["restoreDeps"].isString()) { + HILOGI("Failed to get field restoreDeps"); + return ""; + } + + return obj_["restoreDeps"].asString(); + } + std::vector GetBundleInfos() { if (!obj_ || !obj_.isMember("bundleInfos") || !obj_["bundleInfos"].isArray()) { @@ -91,14 +103,14 @@ public: for (const auto &item : obj_["bundleInfos"]) { if (!item || !item["name"].isString() || !item["versionCode"].isUInt() || !item["versionName"].isString() || !item["spaceOccupied"].isInt64() || !item["allToBackup"].isBool() || - !item["extensionName"].isString() || !item["needToInstall"].isBool()) { + !item["extensionName"].isString() || !item["needToInstall"].isBool() || !item["restoreDeps"].isString()) { HILOGI("Failed to get field bundleInfos, type error"); return {}; } bundleInfos.emplace_back(BundleInfo {item["name"].asString(), item["versionCode"].asUInt(), item["versionName"].asString(), item["spaceOccupied"].asInt64(), item["allToBackup"].asBool(), item["extensionName"].asString(), - item["needToInstall"].asBool()}); + item["needToInstall"].asBool(), item["restoreDeps"].asString()}); } return bundleInfos; } diff --git a/utils/include/b_json/b_json_entity_extension_config.h b/utils/include/b_json/b_json_entity_extension_config.h index 54f002324..b73062988 100644 --- a/utils/include/b_json/b_json_entity_extension_config.h +++ b/utils/include/b_json/b_json_entity_extension_config.h @@ -55,6 +55,8 @@ public: */ bool GetFullBackupOnly() const; + std::string GetRestoreDeps() const; + public: std::string GetJSonSource(std::string_view jsonFromRealWorld, std::any option); diff --git a/utils/src/b_json/b_json_entity_extension_config.cpp b/utils/src/b_json/b_json_entity_extension_config.cpp index 726c1ed30..f6e7e751e 100644 --- a/utils/src/b_json/b_json_entity_extension_config.cpp +++ b/utils/src/b_json/b_json_entity_extension_config.cpp @@ -140,4 +140,15 @@ string BJsonEntityExtensionConfig::GetJSonSource(string_view jsonFromRealWorld, } return BFile::ReadFile(UniqueFd(open(jsonFilePath.c_str(), O_RDONLY))).get(); } + +string BJsonEntityExtensionConfig::GetRestoreDeps() const +{ + if (!obj_ || !obj_.isMember("restoreDeps") || !obj_["restoreDeps"].isString()) { + HILOGE("Failed to init field restoreDeps"); + return ""; + } + + return obj_["restoreDeps"].asString(); +} + } // namespace OHOS::FileManagement::Backup -- Gitee From 79a8702e08f8ebdb1d47d9c2e4d5d149298e7d54 Mon Sep 17 00:00:00 2001 From: yang-jingbo1985 Date: Tue, 24 Oct 2023 19:49:49 +0800 Subject: [PATCH 2/2] =?UTF-8?q?backup=5Ftool=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: yang-jingbo1985 --- .../backup_sa/include/module_ipc/service.h | 9 ++ .../module_ipc/svc_restore_deps_manager.h | 24 +++-- services/backup_sa/src/module_ipc/service.cpp | 88 +++++++++------ .../module_ipc/svc_restore_deps_manager.cpp | 101 +++++++++++------- .../src/module_ipc/svc_session_manager.cpp | 18 ++-- tools/backup_tool/src/tools_op_restore.cpp | 80 +++++++++++--- utils/include/b_json/b_json_entity_caps.h | 3 +- .../b_json/b_json_entity_extension_config.h | 5 + 8 files changed, 222 insertions(+), 106 deletions(-) diff --git a/services/backup_sa/include/module_ipc/service.h b/services/backup_sa/include/module_ipc/service.h index d1f163d35..b45d1ae6e 100644 --- a/services/backup_sa/include/module_ipc/service.h +++ b/services/backup_sa/include/module_ipc/service.h @@ -137,6 +137,7 @@ private: * */ void OnStartSched(); + /** * @brief 通知客户端程序扩展能力处理结果 * @@ -145,6 +146,14 @@ private: */ void NoticeClientFinish(const std::string &bundleName, ErrCode errCode); + /** + * @brief 处理有依赖的应用恢复 + * + * @param bundleName 应用名称 + * + */ + void HandleRestoreDepsBundle(const std::string &bundleName); + private: static sptr instance_; static std::mutex instanceLock_; diff --git a/services/backup_sa/include/module_ipc/svc_restore_deps_manager.h b/services/backup_sa/include/module_ipc/svc_restore_deps_manager.h index 263f8d5a7..d830cb2b6 100644 --- a/services/backup_sa/include/module_ipc/svc_restore_deps_manager.h +++ b/services/backup_sa/include/module_ipc/svc_restore_deps_manager.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022-2023 Huawei Device Co., Ltd. + * Copyright (c) 2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -16,13 +16,15 @@ #ifndef OHOS_FILEMGMT_BACKUP_SVC_RESTORE_DEPS_MANAGER_H #define OHOS_FILEMGMT_BACKUP_SVC_RESTORE_DEPS_MANAGER_H +#include +#include #include #include #include "b_json/b_json_entity_caps.h" +#include "i_service.h" namespace OHOS::FileManagement::Backup { -using namespace std; class SvcRestoreDepsManager { public: @@ -31,12 +33,17 @@ public: static SvcRestoreDepsManager manager; return manager; } + struct RestoreInfo { + RestoreTypeEnum restoreType_ {RESTORE_DATA_WAIT_SEND}; + set fileNames_ {}; + }; - vector GetRestoreBundleNames(const vector &infos); + vector GetRestoreBundleNames(const vector &infos, RestoreTypeEnum restoreType); + map GetRestoreBundleMap(); void AddRestoredBundles(const string &bundleName); - vector GetRestoreBundleNames(); vector GetAllBundles() const; bool IsAllBundlesRestored() const; + void UpdateToRestoreBundleMap(const string &bundleName, const string &fileName); private: SvcRestoreDepsManager() {} @@ -45,15 +52,14 @@ private: SvcRestoreDepsManager &operator=(const SvcRestoreDepsManager &manager) = delete; void BuildDepsMap(const vector &infos); - vector SplitString(const string &str, char delim); - void AddBundles(vector &bundles, const string &bundleName); + vector SplitString(const string &srcStr, const string &separator); bool IsAllDepsRestored(const string &bundleName); + mutable std::shared_mutex lock_; map> depsMap_ {}; vector allBundles_ {}; // 所有的应用 - - vector toRestoreBundles_ {}; // 有依赖的应用 - vector restoredBundles_ {}; // 已经恢复完成的应用 + map toRestoreBundleMap_ {}; // 有依赖的应用 + set restoredBundles_ {}; // 已经恢复完成的应用 }; } // namespace OHOS::FileManagement::Backup diff --git a/services/backup_sa/src/module_ipc/service.cpp b/services/backup_sa/src/module_ipc/service.cpp index 35f06428c..0af268afd 100644 --- a/services/backup_sa/src/module_ipc/service.cpp +++ b/services/backup_sa/src/module_ipc/service.cpp @@ -117,6 +117,7 @@ UniqueFd Service::GetLocalCapabilities() return move(cachedEntity.GetFd()); } catch (const BError &e) { + HILOGE("GetLocalCapabilities failed, errCode = %{public}d", e.GetCode()); return UniqueFd(-e.GetCode()); } catch (const exception &e) { HILOGI("Catched an unexpected low-level exception %{public}s", e.what()); @@ -230,6 +231,19 @@ ErrCode Service::Start() return BError(BError::Codes::OK); } +static void GetRestoreBundleNames(const vector &bundleInfos, + vector &restoreBundleNames, + RestoreTypeEnum restoreType, + const vector &bundleNames) +{ + vector restoreBundleInfos {}; + for (auto &bundleInfo : bundleInfos) { + if (find(bundleNames.begin(), bundleNames.end(), bundleInfo.name) != bundleNames.end()) { + restoreBundleInfos.emplace_back(bundleInfo); + } + } + restoreBundleNames = SvcRestoreDepsManager::GetInstance().GetRestoreBundleNames(restoreBundleInfos, restoreType); +} ErrCode Service::AppendBundlesRestoreSession(UniqueFd fd, const vector &bundleNames, RestoreTypeEnum restoreType, @@ -247,18 +261,11 @@ ErrCode Service::AppendBundlesRestoreSession(UniqueFd fd, if (!bundleInfos.size()) { throw BError(BError::Codes::SA_INVAL_ARG, "Json entity caps is empty"); } - - vector restoreBundleInfos {}; - for (auto &bundleInfo : bundleInfos) { - if (find(bundleNames.begin(), bundleNames.end(), bundleInfo.name) != bundleNames.end()) { - restoreBundleInfos.push_back(bundleInfo); - } - } - vector restoreBundleNames = SvcRestoreDepsManager::GetInstance().GetRestoreBundleNames(restoreBundleInfos); + vector restoreBundleNames {}; + GetRestoreBundleNames(bundleInfos, restoreBundleNames, restoreType, bundleNames); if (restoreBundleNames.empty()) { return BError(BError::Codes::OK); } - session_->AppendBundles(restoreBundleNames); for (auto bundleName : restoreBundleNames) { HILOGD("bundleName: %{public}s", bundleName.c_str()); @@ -487,6 +494,7 @@ ErrCode Service::GetFileHandle(const string &bundleName, const string &fileName) if (!regex_match(fileName, regex("^[0-9a-zA-Z_.]+$"))) { throw BError(BError::Codes::SA_INVAL_ARG, "Filename is not alphanumeric"); } + SvcRestoreDepsManager::GetInstance().UpdateToRestoreBundleMap(bundleName, fileName); session_->SetExtFileNameRequest(bundleName, fileName); auto action = session_->GetServiceSchedAction(bundleName); if (action == BConstants::ServiceSchedAction::RUNNING) { @@ -670,28 +678,7 @@ void Service::ClearSessionAndSchedInfo(const string &bundleName) try { session_->RemoveExtInfo(bundleName); sched_->RemoveExtConn(bundleName); - - if (session_->GetScenario() == IServiceReverse::Scenario::RESTORE) { - SvcRestoreDepsManager::GetInstance().AddRestoredBundles(bundleName); - - // 该应用恢复完成,判断依赖hap的前置hap是否全部恢复完成,如果成了,追加该依赖hap - vector restoreBundleNames = SvcRestoreDepsManager::GetInstance().GetRestoreBundleNames(); - if (!restoreBundleNames.empty()) { // 启动恢复会话 - session_->AppendBundles(restoreBundleNames); - for (auto &bundleName : restoreBundleNames) { - for (auto &bundleInfo : SvcRestoreDepsManager::GetInstance().GetAllBundles()) { - if (bundleName == bundleInfo.name) { - session_->SetNeedToInstall(bundleInfo.name, bundleInfo.needToInstall); - session_->SetBundleRestoreType(bundleInfo.name, RESTORE_DATA_WAIT_SEND); - session_->SetBundleVersionCode(bundleInfo.name, bundleInfo.versionCode); - session_->SetBundleVersionName(bundleInfo.name, bundleInfo.versionName); - session_->SetBundleDataSize(bundleInfo.name, bundleInfo.spaceOccupied); - } - } - } - } - } - + HandleRestoreDepsBundle(bundleName); sched_->Sched(); } catch (const BError &e) { return; @@ -704,6 +691,45 @@ void Service::ClearSessionAndSchedInfo(const string &bundleName) } } +void Service::HandleRestoreDepsBundle(const string &bundleName) +{ + if (session_->GetScenario() != IServiceReverse::Scenario::RESTORE) { + return; + } + HILOGI("Begin, bundleName: %{public}s", bundleName.c_str()); + SvcRestoreDepsManager::GetInstance().AddRestoredBundles(bundleName); + // 该应用恢复完成,判断依赖hap的前置hap是否全部恢复完成,如果成了,追加该依赖hap + auto restoreBundleMap = SvcRestoreDepsManager::GetInstance().GetRestoreBundleMap(); + if (restoreBundleMap.empty()) { + HILOGI("restoreBundleMap is empty."); + return; + } + // 启动恢复会话 + vector restoreBundleNames {}; + for (auto &bundle : restoreBundleMap) { + HILOGI("Start restore session, bundle: %{public}s", bundle.first.c_str()); + restoreBundleNames.emplace_back(bundle.first); + } + session_->AppendBundles(restoreBundleNames); + for (auto &bundle : restoreBundleMap) { + for (auto &bundleInfo : SvcRestoreDepsManager::GetInstance().GetAllBundles()) { + if (bundle.first != bundleInfo.name) { + continue; + } + SvcRestoreDepsManager::RestoreInfo info = bundle.second; + session_->SetNeedToInstall(bundleInfo.name, bundleInfo.needToInstall); + session_->SetBundleRestoreType(bundleInfo.name, info.restoreType_); + session_->SetBundleVersionCode(bundleInfo.name, bundleInfo.versionCode); + session_->SetBundleVersionName(bundleInfo.name, bundleInfo.versionName); + session_->SetBundleDataSize(bundleInfo.name, bundleInfo.spaceOccupied); + for (auto &fileName : info.fileNames_) { + session_->SetExtFileNameRequest(bundleInfo.name, fileName); + } + } + } + HILOGI("End"); +} + void Service::OnAllBundlesFinished(ErrCode errCode) { if (session_->IsOnAllBundlesFinished()) { diff --git a/services/backup_sa/src/module_ipc/svc_restore_deps_manager.cpp b/services/backup_sa/src/module_ipc/svc_restore_deps_manager.cpp index d5ed966cb..4f760ba8d 100644 --- a/services/backup_sa/src/module_ipc/svc_restore_deps_manager.cpp +++ b/services/backup_sa/src/module_ipc/svc_restore_deps_manager.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022-2023 Huawei Device Co., Ltd. + * Copyright (c) 2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -18,13 +18,14 @@ #include "filemgmt_libhilog.h" namespace OHOS::FileManagement::Backup { +using namespace std; -vector SvcRestoreDepsManager::GetRestoreBundleNames(const vector &bundleInfos) +vector SvcRestoreDepsManager::GetRestoreBundleNames(const vector &bundleInfos, + RestoreTypeEnum restoreType) { - HILOGI("SvcRestoreDepsManager::GetRestoreBundleNames, bundleInfos.size():%{public}d", bundleInfos.size()); + unique_lock lock(lock_); vector restoreBundleNames {}; // 需要恢复的应用列表 - - BuildDepsMap(bundleInfos); // 构建依赖Map + BuildDepsMap(bundleInfos); // 构建依赖Map for (auto &bundleInfo : bundleInfos) { string restoreDeps = bundleInfo.restoreDeps; @@ -32,13 +33,14 @@ vector SvcRestoreDepsManager::GetRestoreBundleNames(const vector SvcRestoreDepsManager::GetRestoreBundleNames(const vector SvcRestoreDepsManager::GetRestoreBundleNames() +map SvcRestoreDepsManager::GetRestoreBundleMap() { - HILOGI("SvcRestoreDepsManager::GetRestoreBundleNames"); - vector restoreBundleNames {}; // 需要恢复的应用列表 - for (auto &bundle : toRestoreBundles_) { // 所有有依赖的应用 + unique_lock lock(lock_); + map restoreBundleMap {}; // 需要恢复的应用列表 + for (auto it = toRestoreBundleMap_.begin(); it != toRestoreBundleMap_.end();) { // 所有有依赖的应用 // 如果该应用的依赖项已经完成备份,也需要加到 restoreBundleNames - if (IsAllDepsRestored(bundle)) { - AddBundles(restoreBundleNames, bundle); - toRestoreBundles_.erase(remove(toRestoreBundles_.begin(), toRestoreBundles_.end(), bundle), - toRestoreBundles_.end()); + string bundleName = it->first; + if (IsAllDepsRestored(bundleName)) { + RestoreInfo restoreInfo = it->second; + restoreBundleMap.insert(make_pair(bundleName, restoreInfo)); + toRestoreBundleMap_.erase(it++); + } else { + it++; } } - return restoreBundleNames; + return restoreBundleMap; } bool SvcRestoreDepsManager::IsAllDepsRestored(const string &bundle) { - HILOGI("SvcRestoreDepsManager::IsAllDepsRestored, bundle:%{public}s", bundle.c_str()); if (depsMap_.find(bundle) == depsMap_.end()) { return false; } @@ -75,13 +79,11 @@ bool SvcRestoreDepsManager::IsAllDepsRestored(const string &bundle) break; } } - HILOGI("SvcRestoreDepsManager::IsAllDepsRestored, isAllDepsRestored:%{public}d", isAllDepsRestored); return isAllDepsRestored; } void SvcRestoreDepsManager::BuildDepsMap(const vector &bundleInfos) { - HILOGI("SvcRestoreDepsManager::BuildDepsMap, bundleInfos.size():%{public}d", bundleInfos.size()); for (auto &bundleInfo : bundleInfos) { if (depsMap_.find(bundleInfo.name) != depsMap_.end()) { continue; @@ -91,7 +93,7 @@ void SvcRestoreDepsManager::BuildDepsMap(const vector depsList {}; string restoreDeps = bundleInfo.restoreDeps; if (restoreDeps.find(",") != string::npos) { - depsList = SplitString(restoreDeps, ','); + depsList = SplitString(restoreDeps, ","); } else { if (!restoreDeps.empty()) { depsList.emplace_back(restoreDeps); @@ -102,33 +104,41 @@ void SvcRestoreDepsManager::BuildDepsMap(const vector SvcRestoreDepsManager::SplitString(const string &str, char delim) +vector SvcRestoreDepsManager::SplitString(const string &srcStr, const string &separator) { - HILOGI("SvcRestoreDepsManager::SplitString, str:%{public}s", str.c_str()); - stringstream ss(str); - string item {}; - vector results {}; - while (getline(ss, item, delim)) { - if (!item.empty()) { - results.push_back(item); + HILOGI("srcStr:%{public}s, separator:%{public}s", srcStr.c_str(), separator.c_str()); + vector dst; + if (srcStr.empty() || separator.empty()) { + return dst; + } + size_t start = 0; + size_t index = srcStr.find_first_of(separator, 0); + while (index != srcStr.npos) { + if (start != index) { + string tempStr = srcStr.substr(start, index - start); + tempStr.erase(0, tempStr.find_first_not_of(" ")); + tempStr.erase(tempStr.find_last_not_of(" ") + 1); + tempStr.erase(tempStr.find_last_not_of("\r") + 1); + dst.push_back(tempStr); } + start = index + 1; + index = srcStr.find_first_of(separator, start); } - HILOGI("SvcRestoreDepsManager::SplitString, results.size():%{public}d", results.size()); - return results; -} -void SvcRestoreDepsManager::AddBundles(vector &bundles, const string &bundleName) -{ - if (find(bundles.begin(), bundles.end(), bundleName) == bundles.end()) { - HILOGI("SvcRestoreDepsManager::AddBundles, bundleName:%{public}s", bundleName.c_str()); - bundles.emplace_back(bundleName); + if (!srcStr.substr(start).empty()) { + string tempStr = srcStr.substr(start); + tempStr.erase(0, tempStr.find_first_not_of(" ")); + tempStr.erase(tempStr.find_last_not_of(" ") + 1); + tempStr.erase(tempStr.find_last_not_of("\r") + 1); + dst.push_back(tempStr); } + return dst; } void SvcRestoreDepsManager::AddRestoredBundles(const string &bundleName) { - HILOGI("SvcRestoreDepsManager::AddRestoredBundles, bundleName:%{public}s", bundleName.c_str()); - AddBundles(restoredBundles_, bundleName); + unique_lock lock(lock_); + restoredBundles_.insert(bundleName); } vector SvcRestoreDepsManager::GetAllBundles() const @@ -138,7 +148,16 @@ vector SvcRestoreDepsManager::GetAllBundles() const bool SvcRestoreDepsManager::IsAllBundlesRestored() const { - return toRestoreBundles_.empty(); + return toRestoreBundleMap_.empty(); +} + +void SvcRestoreDepsManager::UpdateToRestoreBundleMap(const string &bundleName, const string &fileName) +{ + unique_lock lock(lock_); + auto it = toRestoreBundleMap_.find(bundleName); + if (it != toRestoreBundleMap_.end()) { + it->second.fileNames_.insert(fileName); + } } } // namespace OHOS::FileManagement::Backup \ No newline at end of file diff --git a/services/backup_sa/src/module_ipc/svc_session_manager.cpp b/services/backup_sa/src/module_ipc/svc_session_manager.cpp index 615fc1171..c936119db 100644 --- a/services/backup_sa/src/module_ipc/svc_session_manager.cpp +++ b/services/backup_sa/src/module_ipc/svc_session_manager.cpp @@ -432,7 +432,7 @@ bool SvcSessionManager::IsOnAllBundlesFinished() bool isAllBundlesRestored = SvcRestoreDepsManager::GetInstance().IsAllBundlesRestored(); isAllBundlesFinished = (isAllBundlesFinished && isAllBundlesRestored); } - + HILOGI("isAllBundlesFinished:%{public}d", isAllBundlesFinished); return isAllBundlesFinished; } @@ -504,8 +504,8 @@ bool SvcSessionManager::NeedToUnloadService() if (impl_.scenario == IServiceReverse::Scenario::RESTORE) { bool isAllBundlesRestored = SvcRestoreDepsManager::GetInstance().IsAllBundlesRestored(); isNeedToUnloadService = (isNeedToUnloadService && isAllBundlesRestored); - } - + } + HILOGI("isNeedToUnloadService:%{public}d", isNeedToUnloadService); return isNeedToUnloadService; } @@ -600,20 +600,18 @@ uint32_t SvcSessionManager::CalAppProcessTime(const std::string &bundleName) int64_t appSize = it->second.dataSize; /* timeout = (AppSize / 3Ms) * 3 + 30 */ timeout = defaultTimeout + (appSize / processRate) * multiple; - HILOGI("Calculate App extension process run timeout=%{public}lld(s), bundleName=%{public}s ", - timeout, bundleName.c_str()); + HILOGI("Calculate App extension process run timeout=%{public}lld(s), bundleName=%{public}s ", timeout, + bundleName.c_str()); } catch (const BError &e) { - HILOGE("Failed to get app<%{public}s> dataInfo, default time=%{public}lld, err=%{public}d", - bundleName.c_str(), defaultTimeout, e.GetCode()); + HILOGE("Failed to get app<%{public}s> dataInfo, default time=%{public}lld, err=%{public}d", bundleName.c_str(), + defaultTimeout, e.GetCode()); timeout = defaultTimeout; } resTimeoutMs = (uint32_t)(timeout * invertMillisecond % UINT_MAX); /* conver second to millisecond */ return resTimeoutMs; } -void SvcSessionManager::BundleExtTimerStart ( - const std::string &bundleName, - const Utils::Timer::TimerCallback& callback) +void SvcSessionManager::BundleExtTimerStart(const std::string &bundleName, const Utils::Timer::TimerCallback &callback) { unique_lock lock(lock_); if (!impl_.clientToken) { diff --git a/tools/backup_tool/src/tools_op_restore.cpp b/tools/backup_tool/src/tools_op_restore.cpp index c5259997f..9c1649181 100644 --- a/tools/backup_tool/src/tools_op_restore.cpp +++ b/tools/backup_tool/src/tools_op_restore.cpp @@ -248,16 +248,8 @@ static bool GetRealPath(string &path) return true; } -static int32_t InitPathCapFile(const string &pathCapFile, vector bundleNames) +static int32_t InitFd(UniqueFd &fd, const vector &bundleNames) { - StartTrace(HITRACE_TAG_FILEMANAGEMENT, "Init"); - string realPath = pathCapFile; - if (!GetRealPath(realPath)) { - fprintf(stderr, "path to realpath error"); - return -errno; - } - - UniqueFd fd(open(realPath.data(), O_RDWR, S_IRWXU)); if (fd < 0) { fprintf(stderr, "Failed to open file error: %d %s\n", errno, strerror(errno)); FinishTrace(HITRACE_TAG_FILEMANAGEMENT); @@ -278,7 +270,15 @@ static int32_t InitPathCapFile(const string &pathCapFile, vector bundleN cachedEntity.Persist(); fd = move(cachedEntity.GetFd()); } - auto ctx = make_shared(); + return 0; +} + +static int32_t InitRestoreSession(shared_ptr ctx) +{ + if (!ctx) { + throw BError(BError::Codes::TOOL_INVAL_ARG, generic_category().message(errno)); + return -1; + } ctx->session_ = BSessionRestore::Init( BSessionRestore::Callbacks {.onFileReady = bind(OnFileReady, ctx, placeholders::_1, placeholders::_2), .onBundleStarted = bind(OnBundleStarted, ctx, placeholders::_1, placeholders::_2), @@ -290,10 +290,51 @@ static int32_t InitPathCapFile(const string &pathCapFile, vector bundleN FinishTrace(HITRACE_TAG_FILEMANAGEMENT); return -EPERM; } - int ret = ctx->session_->AppendBundles(move(fd), bundleNames); + return 0; +} + +static int32_t InitPathCapFile(const string &pathCapFile, vector bundleNames, bool depMode) +{ + StartTrace(HITRACE_TAG_FILEMANAGEMENT, "Init"); + string realPath = pathCapFile; + if (!GetRealPath(realPath)) { + fprintf(stderr, "path to realpath error"); + return -errno; + } + + UniqueFd fd(open(realPath.data(), O_RDWR, S_IRWXU)); + int32_t ret = InitFd(fd, bundleNames); if (ret != 0) { - printf("restore append bundles error: %d\n", ret); - return -ret; + printf("Failed to get fd error:%d\n", ret); + return ret; + } + auto ctx = make_shared(); + ret = InitRestoreSession(ctx); + if (ret != 0) { + printf("Failed to init restore session error:%d\n", ret); + return ret; + } + + if (depMode) { + for (auto &bundleName : bundleNames) { + UniqueFd fd(open(realPath.data(), O_RDWR, S_IRWXU)); + if (fd < 0) { + fprintf(stderr, "Failed to open file error: %d %s\n", errno, strerror(errno)); + FinishTrace(HITRACE_TAG_FILEMANAGEMENT); + return -errno; + } + int ret = ctx->session_->AppendBundles(move(fd), {bundleName}); + if (ret != 0) { + printf("restore append bundles error: %d\n", ret); + return -ret; + } + } + } else { + ret = ctx->session_->AppendBundles(move(fd), bundleNames); + if (ret != 0) { + printf("restore append bundles error: %d\n", ret); + return -ret; + } } ctx->SetBundleFinishedCount(bundleNames.size()); RestoreApp(ctx, bundleNames); @@ -303,10 +344,17 @@ static int32_t InitPathCapFile(const string &pathCapFile, vector bundleN static int Exec(map> &mapArgToVal) { + bool depMode = false; + if (mapArgToVal.find("depMode") != mapArgToVal.end()) { + string strFlag = *(mapArgToVal["depMode"].begin()); + printf("Exec, strFlag:%s", strFlag.c_str()); + depMode = (strFlag == "true"); + } + if (mapArgToVal.find("pathCapFile") == mapArgToVal.end() || mapArgToVal.find("bundles") == mapArgToVal.end()) { return -EPERM; } - return InitPathCapFile(*(mapArgToVal["pathCapFile"].begin()), mapArgToVal["bundles"]); + return InitPathCapFile(*(mapArgToVal["pathCapFile"].begin()), mapArgToVal["bundles"], depMode); } /** @@ -323,6 +371,10 @@ static bool g_autoRegHack = ToolsOp::Register(ToolsOp {ToolsOp::Descriptor { { .paramName = "bundles", .repeatable = true, + }, + { + .paramName = "depMode", + .repeatable = false, }}, .funcGenHelpMsg = GenHelpMsg, .funcExec = Exec, diff --git a/utils/include/b_json/b_json_entity_caps.h b/utils/include/b_json/b_json_entity_caps.h index ecb9a4461..14afc43f1 100644 --- a/utils/include/b_json/b_json_entity_caps.h +++ b/utils/include/b_json/b_json_entity_caps.h @@ -103,7 +103,8 @@ public: for (const auto &item : obj_["bundleInfos"]) { if (!item || !item["name"].isString() || !item["versionCode"].isUInt() || !item["versionName"].isString() || !item["spaceOccupied"].isInt64() || !item["allToBackup"].isBool() || - !item["extensionName"].isString() || !item["needToInstall"].isBool() || !item["restoreDeps"].isString()) { + !item["extensionName"].isString() || !item["needToInstall"].isBool() || + !item["restoreDeps"].isString()) { HILOGI("Failed to get field bundleInfos, type error"); return {}; } diff --git a/utils/include/b_json/b_json_entity_extension_config.h b/utils/include/b_json/b_json_entity_extension_config.h index b73062988..e6fbdb774 100644 --- a/utils/include/b_json/b_json_entity_extension_config.h +++ b/utils/include/b_json/b_json_entity_extension_config.h @@ -55,6 +55,11 @@ public: */ bool GetFullBackupOnly() const; + /** + * @brief 从JSon对象中获取应用依赖项 + * + * @return 应用依赖项: 该应用恢复依赖的应用 + */ std::string GetRestoreDeps() const; public: -- Gitee