diff --git a/frameworks/native/backup_ext/BUILD.gn b/frameworks/native/backup_ext/BUILD.gn index ab24d367b6976f64b6e645514493d0c98b7cc6ed..1c68e310b637aa586e16b4769b19f37e6292ed71 100644 --- a/frameworks/native/backup_ext/BUILD.gn +++ b/frameworks/native/backup_ext/BUILD.gn @@ -73,6 +73,7 @@ ohos_shared_library("backup_extension_ability_native") { "c_utils:utils", "hilog:libhilog", "hitrace:hitrace_meter", + "init:libbegetutil", "ipc:ipc_core", "napi:ace_napi", ] diff --git a/frameworks/native/backup_ext/include/ext_backup.h b/frameworks/native/backup_ext/include/ext_backup.h index b4d902bc92c401e7007e2d991c8c41efa0106f04..4e6bf1711e44c75f57fd9b396f9f202a4eba8e8b 100644 --- a/frameworks/native/backup_ext/include/ext_backup.h +++ b/frameworks/native/backup_ext/include/ext_backup.h @@ -26,6 +26,7 @@ namespace OHOS::FileManagement::Backup { class ExtBackup; using CreatorFunc = std::function &runtime)>; +class BackupExtension; class ExtBackup : public AbilityRuntime::ExtensionBase { public: @@ -170,8 +171,6 @@ public: */ bool RestoreDataReady(); - void SetClearDataFlag(bool isClearData); - /** * @brief Invoke the extended function of the APP */ @@ -183,6 +182,8 @@ public: static void SetCreator(const CreatorFunc &creator); + void SetBackupExtExtension(const wptr &extExtension); + protected: std::string appVersionStr_; std::string restoreRetInfo_; @@ -197,7 +198,7 @@ private: BConstants::ExtensionAction extAction_ {BConstants::ExtensionAction::INVALID}; ErrCode GetParament(const AAFwk::Want &want); static CreatorFunc creator_; - bool isClearData_ {true}; + wptr bakExtExtension_; }; } // namespace OHOS::FileManagement::Backup diff --git a/frameworks/native/backup_ext/include/ext_extension.h b/frameworks/native/backup_ext/include/ext_extension.h index f74b25bb09c5ce0643d40f17b5010b16b48114d5..0c9b26ec881dfc642cf770532728d2af4e919e00 100644 --- a/frameworks/native/backup_ext/include/ext_extension.h +++ b/frameworks/native/backup_ext/include/ext_extension.h @@ -24,6 +24,7 @@ #include +#include "b_json/b_json/clear_data_config.h" #include "b_json/b_json_entity_extension_config.h" #include "b_json/b_json_entity_ext_manage.h" #include "b_json/b_report_entity.h" @@ -60,6 +61,9 @@ public: public: explicit BackupExtExtension(const std::shared_ptr &extension) : extension_(extension) { + if (extension_ != nullptr) { + extension_->SetBackupExtExtension(this); + } threadPool_.Start(BConstants::EXTENSION_THREAD_POOL_COUNT); } ~BackupExtExtension() diff --git a/frameworks/native/backup_ext/src/ext_backup.cpp b/frameworks/native/backup_ext/src/ext_backup.cpp index 1a4bc1f78913a20c534f4c31e9885eb123eb20c9..d2a1a48c2ba75cad4f5a4066417c2c2da266bc11 100644 --- a/frameworks/native/backup_ext/src/ext_backup.cpp +++ b/frameworks/native/backup_ext/src/ext_backup.cpp @@ -45,6 +45,11 @@ void ExtBackup::SetCreator(const CreatorFunc &creator) creator_ = creator; } +void ExtBackup::SetBackupExtExtension(const wptr &extExtension) +{ + bakExtExtension_ = extExtension; +} + void ExtBackup::Init(const shared_ptr &record, const shared_ptr &application, shared_ptr &handler, @@ -205,10 +210,9 @@ void ExtBackup::OnDisconnect(const AAFwk::Want &want) { try { HILOGI("begin disconnect"); - if (isClearData_) { - auto remoteObject = sptr( - new BackupExtExtension(std::static_pointer_cast(shared_from_this()))); - remoteObject->ExtClear(); + sptr extExtension = bakExtExtension_.promote(); + if (extExtension != nullptr) { + extExtension->ExtClear(); } Extension::OnDisconnect(want); extAction_ = BConstants::ExtensionAction::INVALID; @@ -252,11 +256,6 @@ bool ExtBackup::RestoreDataReady() return restoreType_ == RestoreTypeEnum::RESTORE_DATA_READDY; } -void ExtBackup::SetClearDataFlag(bool isClearData) -{ - isClearData_ = isClearData; -} - ErrCode ExtBackup::OnBackup(function callback) { HILOGI("BackupExtensionAbility(base) OnBackup."); diff --git a/frameworks/native/backup_ext/src/ext_extension.cpp b/frameworks/native/backup_ext/src/ext_extension.cpp index 3ab7acc64ea89f394438a2d9d86f1cb8cc426bd3..e723ca0ce50b8d39ce8a28ce5abfa6b469e555a2 100644 --- a/frameworks/native/backup_ext/src/ext_extension.cpp +++ b/frameworks/native/backup_ext/src/ext_extension.cpp @@ -66,6 +66,8 @@ const string INDEX_FILE_RESTORE = string(BConstants::PATH_BUNDLE_BACKUP_HOME). append(BConstants::EXT_BACKUP_MANAGE); const string INDEX_FILE_INCREMENTAL_BACKUP = string(BConstants::PATH_BUNDLE_BACKUP_HOME). append(BConstants::SA_BUNDLE_BACKUP_BACKUP); +const string MEDIA_LIBRARY_BUNDLE_NAME = "com.ohos.medialibrary.medialibrarydata"; +const string FILE_MANAGER_BUNDLE_NAME = "com.huawei.hmos.filemanager"; using namespace std; namespace { @@ -1393,6 +1395,15 @@ void BackupExtExtension::DoClear() string(BConstants::PATH_BUNDLE_BACKUP_HOME_EL1).append(BConstants::SA_BUNDLE_BACKUP_BACKUP)); ForceRemoveDirectory( string(BConstants::PATH_BUNDLE_BACKUP_HOME_EL1).append(BConstants::SA_BUNDLE_BACKUP_RESTORE)); + // delete special directory + if (bundleName_.compare(MEDIA_LIBRARY_BUNDLE_NAME)) { + ForceRemoveDirectory(string(BConstants::MEDIA_LIBRARY_PATH).append(BConstants::SA_BUNDLE_BACKUP_BACKUP)); + ForceRemoveDirectory(string(BConstants::MEDIA_LIBRARY_PATH).append(BConstants::SA_BUNDLE_BACKUP_RESTORE)); + } + if (bundleName_.compare(FILE_MANAGER_BUNDLE_NAME)) { + ForceRemoveDirectory(string(BConstants::FILE_MANAGER_PATH).append(BConstants::SA_BUNDLE_BACKUP_BACKUP)); + ForceRemoveDirectory(string(BConstants::FILE_MANAGER_PATH).append(BConstants::SA_BUNDLE_BACKUP_RESTORE)); + } unique_lock lock(lock_); } catch (...) { HILOGE("Failed to clear"); diff --git a/frameworks/native/backup_ext/src/sub_ext_extension.cpp b/frameworks/native/backup_ext/src/sub_ext_extension.cpp index 888d44c6eb7d7d71d0dbe2b3dd1f936a5b0b59a6..001149ddd461a776993f8babd682345963d3c742 100644 --- a/frameworks/native/backup_ext/src/sub_ext_extension.cpp +++ b/frameworks/native/backup_ext/src/sub_ext_extension.cpp @@ -101,7 +101,6 @@ void BackupExtExtension::SetClearDataFlag(bool isClearData) HILOGE("Extension handle have been released"); return; } - extension_->SetClearDataFlag(isClearData); if (!extension_->WasFromSpecialVersion() && !extension_->RestoreDataReady()) { DoClear(); } diff --git a/frameworks/native/backup_kit_inner/src/b_incremental_backup_session.cpp b/frameworks/native/backup_kit_inner/src/b_incremental_backup_session.cpp index f747d28c7662c0b22edf870320e7253fee023ee2..bc4a6e687ed79e2eeb63ae8a5b2d59bd4ecb3ea7 100644 --- a/frameworks/native/backup_kit_inner/src/b_incremental_backup_session.cpp +++ b/frameworks/native/backup_kit_inner/src/b_incremental_backup_session.cpp @@ -29,7 +29,7 @@ BIncrementalBackupSession::~BIncrementalBackupSession() HILOGI("Death Recipient is nullptr"); return; } - auto proxy = ServiceProxy::GetInstance(); + auto proxy = ServiceProxy::GetServiceProxyPointer(); if (proxy == nullptr) { return; } diff --git a/frameworks/native/backup_kit_inner/src/b_incremental_restore_session.cpp b/frameworks/native/backup_kit_inner/src/b_incremental_restore_session.cpp index 000241ad00fa33ddcf07acdfb1e09ba657c34a52..1b5b24c6a317fcc5adb90b87eab9be84b7e04a95 100644 --- a/frameworks/native/backup_kit_inner/src/b_incremental_restore_session.cpp +++ b/frameworks/native/backup_kit_inner/src/b_incremental_restore_session.cpp @@ -29,7 +29,7 @@ BIncrementalRestoreSession::~BIncrementalRestoreSession() HILOGI("Death Recipient is nullptr"); return; } - auto proxy = ServiceProxy::GetInstance(); + auto proxy = ServiceProxy::GetServiceProxyPointer(); if (proxy == nullptr) { return; } diff --git a/frameworks/native/backup_kit_inner/src/b_incremental_session_restore_async.cpp b/frameworks/native/backup_kit_inner/src/b_incremental_session_restore_async.cpp index 84f75d66efc567dbca2fd01b5de3c13ab20f57d3..67ed9f49b7e6277c6fa63cb306565c0d73b5f769 100644 --- a/frameworks/native/backup_kit_inner/src/b_incremental_session_restore_async.cpp +++ b/frameworks/native/backup_kit_inner/src/b_incremental_session_restore_async.cpp @@ -30,7 +30,7 @@ BIncrementalSessionRestoreAsync::~BIncrementalSessionRestoreAsync() HILOGE("Death Recipient is nullptr"); return; } - auto proxy = ServiceProxy::GetInstance(); + auto proxy = ServiceProxy::GetServiceProxyPointer(); if (proxy == nullptr) { return; } diff --git a/frameworks/native/backup_kit_inner/src/b_session_backup.cpp b/frameworks/native/backup_kit_inner/src/b_session_backup.cpp index 04176686bd8da61518fe2d153cc41f938d62503d..495e9d545c79ad57f64205e9d4bf90c8ce062350 100644 --- a/frameworks/native/backup_kit_inner/src/b_session_backup.cpp +++ b/frameworks/native/backup_kit_inner/src/b_session_backup.cpp @@ -29,7 +29,7 @@ BSessionBackup::~BSessionBackup() HILOGI("Death Recipient is nullptr"); return; } - auto proxy = ServiceProxy::GetInstance(); + auto proxy = ServiceProxy::GetServiceProxyPointer(); if (proxy == nullptr) { return; } diff --git a/frameworks/native/backup_kit_inner/src/b_session_restore.cpp b/frameworks/native/backup_kit_inner/src/b_session_restore.cpp index 250d68bc7f24b8124536264115c5d79964f7599a..c284aa26fc911346bd980ac88e2786c08aa7bb27 100644 --- a/frameworks/native/backup_kit_inner/src/b_session_restore.cpp +++ b/frameworks/native/backup_kit_inner/src/b_session_restore.cpp @@ -29,7 +29,7 @@ BSessionRestore::~BSessionRestore() HILOGI("Death Recipient is nullptr"); return; } - auto proxy = ServiceProxy::GetInstance(); + auto proxy = ServiceProxy::GetServiceProxyPointer(); if (proxy == nullptr) { return; } diff --git a/frameworks/native/backup_kit_inner/src/b_session_restore_async.cpp b/frameworks/native/backup_kit_inner/src/b_session_restore_async.cpp index 10c388fb58b468f1ea7bf402fa39527ec0d55a50..142b5fd3614ec5f24ca00d05ed4f4f6cb56fb78f 100644 --- a/frameworks/native/backup_kit_inner/src/b_session_restore_async.cpp +++ b/frameworks/native/backup_kit_inner/src/b_session_restore_async.cpp @@ -31,7 +31,7 @@ BSessionRestoreAsync::~BSessionRestoreAsync() HILOGI("Death Recipient is nullptr"); return; } - auto proxy = ServiceProxy::GetInstance(); + auto proxy = ServiceProxy::GetServiceProxyPointer(); if (proxy == nullptr) { return; } diff --git a/frameworks/native/backup_kit_inner/src/service_proxy.cpp b/frameworks/native/backup_kit_inner/src/service_proxy.cpp index 1d004e4f16e346181588c601b4cbfce81328748d..66849eaf916963420e50d9520d6e7e10c10738eb 100644 --- a/frameworks/native/backup_kit_inner/src/service_proxy.cpp +++ b/frameworks/native/backup_kit_inner/src/service_proxy.cpp @@ -415,6 +415,12 @@ ErrCode ServiceProxy::Finish() return reply.ReadInt32(); } +sptr ServiceProxy::GetServiceProxyPointer() +{ + HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__); + return serviceProxy_; +} + sptr ServiceProxy::GetInstance() { HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__); diff --git a/interfaces/inner_api/native/backup_kit_inner/impl/service_proxy.h b/interfaces/inner_api/native/backup_kit_inner/impl/service_proxy.h index d0845087ee63d5148626174e238c488aafeb1f2b..620caaa8febcfc733c26698dd9e16078c368e028 100644 --- a/interfaces/inner_api/native/backup_kit_inner/impl/service_proxy.h +++ b/interfaces/inner_api/native/backup_kit_inner/impl/service_proxy.h @@ -76,6 +76,7 @@ public: public: template bool WriteParcelableVector(const std::vector &parcelableVector, Parcel &data); + sptr GetServiceProxyPointer(); static sptr GetInstance(); static void InvaildInstance(); diff --git a/services/5203.json b/services/5203.json index a38a55395fbb8eaa757307132fa566256b2f6476..758a56c823fca675133a65b1bee0bfb51a1d2454 100644 --- a/services/5203.json +++ b/services/5203.json @@ -5,6 +5,7 @@ "name": 5203, "libpath": "libbackup_sa.z.so", "run-on-create": false, + "auto-restart": true, "distributed": false, "dump_level": 1, "start-on-demand": { diff --git a/services/backup_sa/include/module_ipc/service.h b/services/backup_sa/include/module_ipc/service.h index 45a9393e5a3bd987ec3eda79f67aa9377b924302..f633cc8f1721f264ed410171b3c9d48005eb1549 100644 --- a/services/backup_sa/include/module_ipc/service.h +++ b/services/backup_sa/include/module_ipc/service.h @@ -227,12 +227,38 @@ public: */ std::function GetBackupInfoConnectDied(wptr obj, std::string &bundleName); + /** + * @brief 清理残留数据 + * + * @param bundleName 应用名称 + * + */ + void ClearResidualBundleData(const std::string &bundleName); + + /** + * @brief 添加清理记录 + * + * @param bundleName 应用名称 + * + */ + void AddClearBundleRecord(const std::string &bundleName); + + /** + * @brief 删除清理记录 + * + * @param bundleName 应用名称 + * + */ + void DelClearBundleRecord(const std::string &bundleName); + + public: explicit Service(int32_t saID, bool runOnCreate = false) : SystemAbility(saID, runOnCreate) { threadPool_.Start(BConstants::EXTENSION_THREAD_POOL_COUNT); session_ = sptr(new SvcSessionManager(wptr(this))); disposal_ = make_shared(); + clearRecorder_ = make_shared(); }; ~Service() override { @@ -391,6 +417,13 @@ private: */ ErrCode GetBackupInfoCmdHandle(BundleName &bundleName, std::string &result); + /** + * @brief 添加需要清理的Session + * + * @param bundleNames 需要清理的应用包信息 + * + */ + ErrCode AppendBundlesClearSession(const std::vector &bundleNames); private: static sptr instance_; static std::mutex instanceLock_; @@ -403,6 +436,7 @@ private: sptr session_; sptr sched_; std::shared_ptr disposal_; + std::shared_ptr clearRecorder_; friend class ServiceTest; diff --git a/services/backup_sa/include/module_ipc/svc_session_manager.h b/services/backup_sa/include/module_ipc/svc_session_manager.h index 7baf1cabb497f8fae39e39ea406e3adae9220071..7eb402f1abdd10f5dbe13a7109326b49af43ef78 100644 --- a/services/backup_sa/include/module_ipc/svc_session_manager.h +++ b/services/backup_sa/include/module_ipc/svc_session_manager.h @@ -104,7 +104,7 @@ public: * * @param impl 客户端信息 */ - ErrCode Active(Impl newImpl); + ErrCode Active(Impl newImpl, bool force = false); /** * @brief 关闭会话 diff --git a/services/backup_sa/src/module_ipc/service.cpp b/services/backup_sa/src/module_ipc/service.cpp index 8f65b2178ea21c37dd667fcfed57bb84392eeb38..9bfbbc83e4315bcd39733995132abde1c93bdb17 100644 --- a/services/backup_sa/src/module_ipc/service.cpp +++ b/services/backup_sa/src/module_ipc/service.cpp @@ -75,6 +75,7 @@ namespace { constexpr int32_t DEBUG_ID = 100; constexpr int32_t INDEX = 3; constexpr int32_t MS_1000 = 1000; +constexpr int MS_100 = 1000; const static string BROADCAST_TYPE = "broadcast"; const std::string FILE_BACKUP_EVENTS = "FILE_BACKUP_EVENTS"; const static string UNICAST_TYPE = "unicast"; @@ -111,10 +112,23 @@ void Service::OnStart() string work_status = system::GetParameter(BACKUPSERVICE_WORK_STATUS_KEY, ""); HILOGI("Param %{public}s value is %{public}s", BACKUPSERVICE_WORK_STATUS_KEY.c_str(), work_status.c_str()); if (work_status.compare(BACKUPSERVICE_WORK_STATUS_ON) == 0) { - bool isSetSucc = system::SetParameter(BACKUPSERVICE_WORK_STATUS_KEY, BACKUPSERVICE_WORK_STATUS_OFF); - HILOGI("SetParameter %{public}s false end, result %{public}d.", BACKUPSERVICE_WORK_STATUS_KEY.c_str(), - isSetSucc); - sched_->TryUnloadService(); + std::vector residualBundleNameList = clearRecorder_->GetAllClearBundleRecord(); + if (residualBundleNameList.empty()) { + bool isSetSucc = system::SetParameter(BACKUPSERVICE_WORK_STATUS_KEY, BACKUPSERVICE_WORK_STATUS_OFF); + HILOGI("SetParameter %{public}s false end, result %{public}d.", BACKUPSERVICE_WORK_STATUS_KEY.c_str(), + isSetSucc); + sched_->TryUnloadService(); + } else { + session_->Active( + { + .clientToken = IPCSKeleton::GetCallingTokenID(), + .scenario = IServiceReverse::Scenario::BACKUP, + .clientProxy = nullptr, + .userId = GetUserIdDefault(), + }, + true); + AppendBundlesClearSession(residualBundleNameList); + } } HILOGI("SA OnStart End, res = %{public}d", res); } @@ -1004,37 +1018,9 @@ void Service::OnBackupExtensionDied(const string &&bundleName) string callName = move(bundleName); HILOGE("Backup <%{public}s> Extension Process Died", callName.c_str()); session_->VerifyBundleName(callName); - string versionName = session_->GetBundleVersionName(bundleName); /* old device app version name */ - string versionNameFlag = - versionName.substr(0, versionName.find_first_of(BConstants::VERSION_NAME_SEPARATOR_CHAR)); - if (versionNameFlag == BConstants::DEFAULT_VERSION_NAME && - session_->ValidRestoreDataType(RestoreTypeEnum::RESTORE_DATA_READDY)) { - ExtConnectDied(bundleName); - return; - } // 重新连接清理缓存 - HILOGE("Clear backup extension data, bundleName: %{public}s", bundleName.data()); - auto backUpConnection = session_->GetExtConnection(bundleName); - auto callConnected = [ptr {wptr(this)}](const string &&bundleName) { - HILOGE("OnBackupExtensionDied callConnected <%{public}s>", bundleName.c_str()); - auto thisPtr = ptr.promote(); - if (!thisPtr) { - HILOGW("this pointer is null."); - return; - } - thisPtr->ExtConnectDied(bundleName); - }; - if (backUpConnection == nullptr) { - HILOGE("OnBackupExtensionDied error. backUpConnection is empty"); - ExtConnectDied(bundleName); - return; - } - backUpConnection->SetCallback(callConnected); - auto ret = LaunchBackupExtension(bundleName); - if (ret) { - ExtConnectDied(bundleName); - return; - } + HILOGI("Clear backup extension data, bundleName: %{public}s", bundleName.data()); + ExtConnectDied(bundleName); } catch (...) { HILOGE("Unexpected exception, bundleName: %{public}s", bundleName.c_str()); ExtConnectDied(bundleName); @@ -1053,8 +1039,12 @@ void Service::ExtConnectDied(const string &callName) if (backUpConnection != nullptr && backUpConnection->IsExtAbilityConnected()) { backUpConnection->DisconnectBackupExtAbility(); } - /* Clear Session before notice client finish event */ - ClearSessionAndSchedInfo(callName); + session_->SetServiceSchedAction(callName, BConstants::ServiceSchedAction::CLEAN); + auto ret = LaunchBackupExtension(callName); + if (ret) { + /* Clear Session before notice client finish event */ + ClearSessionAndSchedInfo(callName); + } /* Notice Client Ext Ability Process Died */ NoticeClientFinish(callName, BError(BError::Codes::EXT_ABILITY_DIED)); } catch (...) { @@ -1086,6 +1076,8 @@ void Service::ExtStart(const string &bundleName) if (!proxy) { throw BError(BError::Codes::SA_INVAL_ARG, "ExtStart bundle task error, Extension backup Proxy is empty"); } + std::string name = bundleName; + proxy->UpdateFdSendRate(name, DEFAULT_FD_SEND_RATE); if (scenario == IServiceReverse::Scenario::BACKUP) { auto ret = proxy->HandleBackup(session_->GetClearDataFlag(bundleName)); session_->GetServiceReverseProxy()->BackupOnBundleStarted(ret, bundleName); @@ -1231,7 +1223,17 @@ void Service::ExtConnectDone(string bundleName) try { HILOGE("begin %{public}s", bundleName.data()); session_->BundleExtTimerStart(bundleName, timeoutCallback); - session_->SetServiceSchedAction(bundleName, BConstants::ServiceSchedAction::RUNNING); + BConstants::ServiceSchedAction curSchedAction = session_->GetServiceSchedAction(bundleName); + if (curSchedAction == BConstants::ServiceSchedAction::CLEAN) { + sched_->Sched(bundleName_); + return; + } + if (curSchedAction == BConstants::ServiceSchedAction::START && + clearRecorder_->FindClearBundleRecord(bundleName)) { + session_->SetServiceSchedAction(bundleName, BConstants::ServiceSchedAction::CLEAN); + } else { + session_->SetServiceSchedAction(bundleName, BConstants::ServiceSchedAction::RUNNING); + } sched_->Sched(bundleName); } catch (...) { HILOGE("Unexpected exception, bundleName: %{public}s", bundleName.c_str()); @@ -1249,6 +1251,7 @@ void Service::ClearSessionAndSchedInfo(const string &bundleName) session_->RemoveExtInfo(bundleName); sched_->RemoveExtConn(bundleName); HandleRestoreDepsBundle(bundleName); + DelClearBundleRecord(bundleName); sched_->Sched(); } catch (const BError &e) { return; @@ -1507,6 +1510,29 @@ std::function Service::GetBackupInfoConnectDied(wptr }; } +void Service::ClearResidualBundleData(const std::string &bundleName) +{ + auto backUpConnection = session_->GetExtConnection(bundleName); + if (backUpConnection == nullptr) { + throw BError(BError::Codes::SA_INVAL_ARG, "backUpConnection is empty"); + } + auto proxy = backUpConnection->GetBackupExtProxy(); + if (!proxy) { + throw BError(BError::Codes::SA_INVAL_ARG, "Extension backup Proxy is empty"); + } + // 通知ext清理 + proxy->HandleClear(); + ClearSessionAndSchedInfo(bundleName); + // 所有应用清理完成后卸载SA + if (session_->GetImpl().clientProxy == nullptr && session_->IsOnAllBundlesFinished()) { + sched_->TryloadService(); + return; + } + if (session_->GetImpl().clientProxy != nullptr) { + OnAllBundlesFinished(BError(BError::Codes::OK)); + } +} + ErrCode Service::GetBackupInfoCmdHandle(BundleName &bundleName, std::string &result) { if (session_ == nullptr) { @@ -1574,6 +1600,38 @@ ErrCode Service::GetBackupInfo(BundleName &bundleName, std::string &result) } } +ErrCode Service::AppendBundlesClearSession(const std::vector &bundleNames) +{ + HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__); + try { + session_->IncreaseSessionCnt(); // BundleMgrAdapter::GetBundleInfos可能耗时 + auto backupInfos = BundleMgrAdapter::GetBundleInfos(bundleNames, session_->GetSessionUserId()); + session_->AppendBundles(bundleNames); + for (auto info : backupInfos) { + session_->SetBundleDataSize(info.name, info.spaceOccupied); + session_->SetBackupExtName(info.name, info.extensionName); + } + OnStartSched(); + session_->DecreaseSessionCnt(); + return BError(BError::Codes::OK); + } catch (const BError &e) { + HandleExceptionOnAppendBundles(session_, bundleNames, {}); + session_->DecreaseSessionCnt(); + HILOGE("Failed, errCode = %{public}d", e.GetCode()); + return e.GetCode(); + } catch (const exception &e) { + HandleExceptionOnAppendBundles(session_, bundleNames, {}); + session_->DecreaseSessionCnt(); + HILOGE("Catched an unexpected low-level exception %{public}s", e.what()); + return EPERM; + } catch (...) { + HandleExceptionOnAppendBundles(session_, bundleNames, {}); + session_->DecreaseSessionCnt(); + HILOGE("Unexpected exception"); + return EPERM; + } +} + ErrCode Service::UpdateTimer(BundleName &bundleName, uint32_t timeOut, bool &result) { auto timeoutCallback = [ptr {wptr(this)}, bundleName]() { @@ -1765,4 +1823,44 @@ void Service::NotifyCallerCurAppDone(ErrCode errCode, const std::string &callerN session_->GetServiceReverseProxy()->RestoreOnBundleFinished(errCode, callerName); } } + +void Service::AddClearBundleRecord(const std::string &bundleName) +{ + // 添加清理记录 + if (!clearRecorder_->InsertClearBundleRecord(bundleName)) { + HILOGE("Failed to add clear bundle record, bundleName=%{public}s", bundleName.c_str()); + return; + } + + // 设置开机自启 + string work_status = system::GetParameter(BACKUPSERVICE_WORK_STATUS_KEY, ""); + HILOGI("Param %{public}s value is %{public}s", BACKUPSERVICE_WORK_STATUS_KEY.c_str(), work_status.c_str()); + if (work_status.compare(BACKUPSERVICE_WORK_STATUS_OFF) == 0) { + bool isSetSucc = system::SetParameter(BACKUPSERVICE_WORK_STATUS_KEY, BACKUPSERVICE_WORK_STATUS_ON); + HILOGI("SetParameter %{public}s true end, result %{public}d.", BACKUPSERVICE_WORK_STATUS_KEY.c_str(), + isSetSucc); + } + HILOGI("Add clear bundle record OK, bundleName=%{public}s", bundleName.c_str()); +} + +void Service::DelClearBundleRecord(const std::string &bundleName) +{ + // 删除清理记录 + if (!clearRecorder_->DeleteClearBundleRecord(bundleName)) { + HILOGE("Failed to delete clear bundle record, bundleName=%{public}s", bundleName.c_str()); + return; + } + + if (!clearRecorder_->HasClearBundleRecord()) { + // 清理记录为空,设置开机不自启 + string work_status = system::GetParameter(BACKUPSERVICE_WORK_STATUS_KEY, ""); + HILOGI("Param %{public}s value is %{public}s", BACKUPSERVICE_WORK_STATUS_KEY.c_str(), work_status.c_str()); + if (work_status.compare(BACKUPSERVICE_WORK_STATUS_ON) == 0) { + bool isSetSucc = system::SetParameter(BACKUPSERVICE_WORK_STATUS_KEY, BACKUPSERVICE_WORK_STATUS_OFF); + HILOGI("SetParameter %{public}s true end, result %{public}d.", BACKUPSERVICE_WORK_STATUS_KEY.c_str(), + isSetSucc); + } + } + HILOGI("Delete clear bundle record OK, bundleName=%{public}s", bundleName.c_str()); +} } // namespace OHOS::FileManagement::Backup 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 aab1b01c9c84305a367e29976e472f84eae6b6dc..a182dff29822d4eddd65cff0bed003c23339c150 100644 --- a/services/backup_sa/src/module_ipc/svc_session_manager.cpp +++ b/services/backup_sa/src/module_ipc/svc_session_manager.cpp @@ -59,7 +59,7 @@ int SvcSessionManager::GetSessionCnt() return sessionCnt_.load(); } -ErrCode SvcSessionManager::Active(Impl newImpl) +ErrCode SvcSessionManager::Active(Impl newImpl, bool force) { unique_lock lock(lock_); const Impl &oldImpl = impl_; @@ -68,14 +68,16 @@ ErrCode SvcSessionManager::Active(Impl newImpl) return BError(BError::Codes::SA_REFUSED_ACT); } - if (!newImpl.clientToken) { + if (!force && !newImpl.clientToken) { throw BError(BError::Codes::SA_INVAL_ARG, "No caller token was specified"); } - if (newImpl.scenario == IServiceReverse::Scenario::UNDEFINED) { + if (!force && newImpl.scenario == IServiceReverse::Scenario::UNDEFINED) { throw BError(BError::Codes::SA_INVAL_ARG, "No scenario was specified"); } - InitClient(newImpl); + if (!force) { + InitClient(newImpl); + } impl_ = newImpl; unloadSAFlag_ = false; return BError(BError::Codes::OK); diff --git a/services/backup_sa/src/module_sched/sched_scheduler.cpp b/services/backup_sa/src/module_sched/sched_scheduler.cpp index 20f7e530c92930aab08ef5a689a7787286526cfb..fc9445369ca07415f010a6e49c696a933242e092 100644 --- a/services/backup_sa/src/module_sched/sched_scheduler.cpp +++ b/services/backup_sa/src/module_sched/sched_scheduler.cpp @@ -116,6 +116,9 @@ void SchedScheduler::ExecutingQueueTasks(const string &bundleName) reversePtr_->SendStartAppGalleryNotify(bundleName); reversePtr_->ExtStart(bundleName); } + } else if (action == BConstants::ServiceSchedAction::CLEAN) { + HILOGI("Current bundle %{public}s process is cleaning", bundleName.data()); + reversePtr_->ClearResidualBundleData(bundleName); } } diff --git a/tests/mock/backup_kit_inner/service_proxy_mock.cpp b/tests/mock/backup_kit_inner/service_proxy_mock.cpp index 95af50b71d06825b69bb51869b7c205e10128787..6e2ece040ce3e67f1a95f95b63b9f181db1e7d35 100644 --- a/tests/mock/backup_kit_inner/service_proxy_mock.cpp +++ b/tests/mock/backup_kit_inner/service_proxy_mock.cpp @@ -187,6 +187,11 @@ ErrCode ServiceProxy::UpdateSendRate(std::string &bundleName, int32_t sendRate, return BError(BError::Codes::OK); } +sptr ServiceProxy::GetServiceProxyPointer() +{ + return serviceProxy_; +} + sptr ServiceProxy::GetInstance() { if (!GetMockGetInstance()) { diff --git a/tests/mock/module_ipc/service_mock.cpp b/tests/mock/module_ipc/service_mock.cpp index c058c5e8365192df93ca1661178718dc278033a4..309c0e3b4af9c142911c7a382adbd3a580ba1fe1 100644 --- a/tests/mock/module_ipc/service_mock.cpp +++ b/tests/mock/module_ipc/service_mock.cpp @@ -234,4 +234,8 @@ void Service::OnSABackup(const std::string &bundleName, } void Service::OnSARestore(const std::string &bundleName, const std::string &result, const ErrCode &errCode) {} + +void Service::ClearResidualBundleData(const std::string &bundleName) +{ +} } // namespace OHOS::FileManagement::Backup diff --git a/tests/mock/module_ipc/svc_session_manager_mock.cpp b/tests/mock/module_ipc/svc_session_manager_mock.cpp index 53b97b777bb8e73a97fb4ebefb3839d0b1e679d6..c328e2fe6584a55472ed0d2ba9e661da0e6703a4 100644 --- a/tests/mock/module_ipc/svc_session_manager_mock.cpp +++ b/tests/mock/module_ipc/svc_session_manager_mock.cpp @@ -41,7 +41,7 @@ void SvcSessionManager::VerifyCallerAndScenario(uint32_t clientToken, IServiceRe GTEST_LOG_(INFO) << "VerifyCallerAndScenario"; } -ErrCode SvcSessionManager::Active(Impl newImpl) +ErrCode SvcSessionManager::Active(Impl newImpl, bool force) { GTEST_LOG_(INFO) << "Active"; extConnectNum_ = 0; diff --git a/tests/mock/module_ipc/svc_session_manager_throw_mock.cpp b/tests/mock/module_ipc/svc_session_manager_throw_mock.cpp index 80acd08fcab61190243b8bcf8b9ca84c17845f1a..f60b5f5e4057ca3c1927bc3e6ff1e790efc59d9a 100644 --- a/tests/mock/module_ipc/svc_session_manager_throw_mock.cpp +++ b/tests/mock/module_ipc/svc_session_manager_throw_mock.cpp @@ -24,7 +24,7 @@ void SvcSessionManager::VerifyCallerAndScenario(uint32_t clientToken, IServiceRe BackupSvcSessionManager::session->VerifyCallerAndScenario(clientToken, scenario); } -ErrCode SvcSessionManager::Active(Impl newImpl) +ErrCode SvcSessionManager::Active(Impl newImpl, bool force) { return BackupSvcSessionManager::session->Active(newImpl); } diff --git a/tests/unittests/backup_sa/session/service_proxy_mock.cpp b/tests/unittests/backup_sa/session/service_proxy_mock.cpp index 7220842562c3aafab49350bf5e33da678c37ed05..0d90ede8deea135ae5c1afc9afd5dd82c209ffc7 100644 --- a/tests/unittests/backup_sa/session/service_proxy_mock.cpp +++ b/tests/unittests/backup_sa/session/service_proxy_mock.cpp @@ -167,6 +167,11 @@ ErrCode ServiceProxy::UpdateSendRate(std::string &bundleName, int32_t sendRate, return BError(BError::Codes::OK); } +sptr ServiceProxy::GetServiceProxyPointer() +{ + return serviceProxy_; +} + sptr ServiceProxy::GetInstance() { return serviceProxy_; diff --git a/utils/BUILD.gn b/utils/BUILD.gn index 151ab2480952d44f0d996e643939aa1ccf607bb8..4d520708c7f3039be2dfd5fa67ffaa6d3f1c7b1b 100644 --- a/utils/BUILD.gn +++ b/utils/BUILD.gn @@ -65,6 +65,7 @@ ohos_shared_library("backup_utils") { "src/b_filesystem/b_dir.cpp", "src/b_filesystem/b_file.cpp", "src/b_filesystem/b_file_hash.cpp", + "src/b_json/b_json_clear_data_config.cpp", "src/b_json/b_json_entity_ext_manage.cpp", "src/b_json/b_json_entity_extension_config.cpp", "src/b_json/b_json_service_disposal_config.cpp", diff --git a/utils/include/b_json/b_json_clear_data_config.h b/utils/include/b_json/b_json_clear_data_config.h new file mode 100644 index 0000000000000000000000000000000000000000..bef85a967bea509c07ca0b25e449325f469a5234 --- /dev/null +++ b/utils/include/b_json/b_json_clear_data_config.h @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2024 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_B_JSON_CLEAR_DATA_CONFIG_H +#define OHOS_FILEMGMT_BACKUP_B_JSON_CLEAR_DATA_CONFIG_H + +#include +#include +#include + +namespace OHOS::FileManagement::Backup { +class BJsonClearDataConfig { +public: + /** + * @brief 判断配置文件中是否有记录 + * + */ + bool HasClearBundleRecord(); + + /** + * @brief 判断配置文件中是否存在bundleName记录 + * + * @param bundlename + */ + bool FindClearBundleRecord(const std::string& bundleName); + + /** + * @brief 配置文件中插入bundleName记录 + * + * @param bundlename + */ + bool InsertClearBundleRecord(const std::string& bundleName); + + /** + * @brief 配置文件中删除bundleName记录 + * + * @param bundlename + */ + bool DeleteClearBundleRecord(const std::string& bundleName); + + /** + * @brief 配置文件中获取bundlename + * + */ + std::vector GetAllClearBundleRecord(); + + /** + * @brief 删除配置文件 + * + * + */ + bool DeleteConfigFile(); + +public: + /** + * @brief 构造方法 + * + * + */ + BJsonClearDataConfig(); +private: + /** + * @brief 配置文件中删除bundleName记录 + * + * @param bundlename + */ + bool WriteClearBundleRecord(const std::string& bundleName); + +private: + std::mutex fileMutex_; +}; + +} // namespace OHOS::FileManagement::Backup +#endif // OHOS_FILEMGMT_BACKUP_B_JSON_SERVICE_DISPOSAL_CONFIG_H \ No newline at end of file diff --git a/utils/include/b_resources/b_constants.h b/utils/include/b_resources/b_constants.h index 7d85e5f907475e13c556b03a6878db74ed8ff9fe..b439c83d02e2a2d6806ce6c2dc86a474f96ba63f 100644 --- a/utils/include/b_resources/b_constants.h +++ b/utils/include/b_resources/b_constants.h @@ -43,6 +43,7 @@ enum ServiceSchedAction { START = 1, RUNNING = 2, FINISH = 3, + CLEAN = 4, }; constexpr int SPAN_USERID_UID = 200000; @@ -113,6 +114,8 @@ static inline std::string_view BACKUP_TOOL_INCREMENTAL = "/incremental"; static inline std::string BACKUP_DIR_PRE = "/data/storage/"; static inline std::string CONTEXT_ELS[] = {"el1", "el2"}; static inline std::string BACKUP_DIR_END = "/base/.backup/"; +static inline std::string_view MEDIA_LIBRARY_PATH = "/storage/media/local/files/.backup"; +static inline std::string_view FILE_MANAGER_PATH = "/storage/User/currentUser/.backup"; // SA Ext constexpr int BACKUP_DEFAULT_SA_ID = -1; constexpr int BACKUP_SA_RELOAD_MAX = 2; diff --git a/utils/src/b_json/b_json_clear_data_config.cpp b/utils/src/b_json/b_json_clear_data_config.cpp new file mode 100644 index 0000000000000000000000000000000000000000..50be323f0d4835213cdf9e9703b93a6024c4583f --- /dev/null +++ b/utils/src/b_json/b_json_clear_data_config.cpp @@ -0,0 +1,356 @@ +/* + * Copyright (c) 2024 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 "b_json_clear_data_config.h" + +#include +#include +#include +#include +#include "unique_fd.h" +#include "filemgmt_libhilog.h" + +#include "cJSON.h" + +namespace OHOS::FileManagement::Backup { +using namespace std; + +namespace { + const string PATH_BUNDLE_BACKUP_HOME = "/data/service/el2/100/backup/"; + const string CONFIG_NAME = "ClearDataConfig.json"; +} + +BJsonClearDataConfig::BJsonClearDataConfig() +{ + string filePath = PATH_BUNDLE_BACKUP_HOME + CONFIG_NAME; + if (access(filePath.c_str(), F_OK) == 0) { + HILOGI("file exist filePath:%{public}s", filePath.c_str()); + return ; + } + HILOGI("Failed to access filePath :%{public}s", filePath.c_str()); + UniqueFd fd(open(filePath.c_str(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR)); + if (fd < 0) { + HILOGE("Failed to creat filePath :%{public}s", filePath.c_str()); + return ; + } + cJSON *jsonObjectDis = cJSON_CreateObject(); + if (jsonObjectDis == nullptr) { + HILOGE("Creat json failed"); + return ; + } + cJSON *jsonArray = cJSON_CreateArray(); + if (jsonArray == nullptr) { + HILOGE("Creat json failed"); + cJSON_Delete(jsonObjectDis); + return ; + } + cJSON_AddItemToObject(jsonObjectDis, "ClearDataConfigFile", jsonArray); + + char *newStr = cJSON_Print(jsonObjectDis); + if (newStr == nullptr) { + HILOGE("cJSON_Print json failed"); + cJSON_Delete(jsonObjectDis); + return ; + } + ofstream outFile(filePath); + if (!outFile.is_open()) { + HILOGE("open json failed"); + free(newStr); + cJSON_Delete(jsonObjectDis); + return ; + } + outFile << newStr; + outFile.close(); + free(newStr); + cJSON_Delete(jsonObjectDis); + HILOGI("Creat filePath ok :%{public}s", filePath.c_str()); +} + +bool BJsonClearDataConfig::HasClearBundleRecord() +{ + lock_guard autoLock(fileMutex_); + string filePath = PATH_BUNDLE_BACKUP_HOME + CONFIG_NAME; + ifstream inFile(filePath); + if (!inFile.is_open()) { + HILOGE("open json failed"); + return false; + } + + string jsonString((istreambuf_iterator(inFile)), istreambuf_iterator()); + inFile.close(); + + cJSON *jsonObjectDis = cJSON_Parse(jsonString.c_str()); + if (jsonObjectDis == nullptr) { + HILOGE("parse json failed"); + return false; + } + + cJSON *configArray = cJSON_GetObjectItem(jsonObjectDis, "DispoasalConfigFile"); + if (configArray == nullptr) { + HILOGE("parse json failed"); + cJSON_Delete(jsonObjectDis); + return false; + } + + int recordSize = cJSON_GetArraySize(configArray); + cJSON_Delete(jsonObjectDis); + return recordSize > 0; +} + +bool BJsonClearDataConfig::FindClearBundleRecord(const string& bundleName) +{ + lock_guard autoLock(fileMutex_); + string filePath = PATH_BUNDLE_BACKUP_HOME + CONFIG_NAME; + ifstream inFile(filePath); + if (!inFile.is_open()) { + HILOGE("open json failed"); + return false; + } + + string jsonString((istreambuf_iterator(inFile)), istreambuf_iterator()); + inFile.close(); + + cJSON *jsonObjectDis = cJSON_Parse(jsonString.c_str()); + if (jsonObjectDis == nullptr) { + HILOGE("parse json failed"); + return false; + } + + cJSON *configArray = cJSON_GetObjectItem(jsonObjectDis, "DispoasalConfigFile"); + if (configArray == nullptr) { + HILOGE("parse json failed"); + cJSON_Delete(jsonObjectDis); + return false; + } + bool ifBundlename = false; + for (int i = 0; i < cJSON_GetArraySize(configArray); ++i) { + cJSON *item = cJSON_GetArrayItem(configArray, i); + if (item != nullptr && cJSON_GetObjectItem(item, "bundleName") != nullptr && + cJSON_GetObjectItem(item, "bundleName")->type == cJSON_String && + cJSON_GetObjectItem(item, "bundleName")->valuestring == bundleName) { + ifBundlename = true; + } + } + + cJSON_Delete(jsonObjectDis); + return ifBundlename; +} + +bool BJsonClearDataConfig::InsertClearBundleRecord(const string& bundleName) +{ + lock_guard autoLock(fileMutex_); + string filePath = PATH_BUNDLE_BACKUP_HOME + CONFIG_NAME; + ifstream inFile(filePath); + if (!inFile.is_open()) { + HILOGE("open json failed"); + return false; + } + + string jsonString((istreambuf_iterator(inFile)), istreambuf_iterator()); + inFile.close(); + + cJSON *jsonObjectDis = cJSON_Parse(jsonString.c_str()); + if (jsonObjectDis == nullptr) { + HILOGE("parse json failed"); + return false; + } + + cJSON *configArray = cJSON_GetObjectItem(jsonObjectDis, "DispoasalConfigFile"); + if (configArray == nullptr) { + HILOGE("parse json failed"); + cJSON_Delete(jsonObjectDis); + return false; + } + + for (int i = 0; i < cJSON_GetArraySize(configArray); ++i) { + cJSON *item = cJSON_GetArrayItem(configArray, i); + if (item != nullptr && cJSON_GetObjectItem(item, "bundleName") != nullptr && + cJSON_GetObjectItem(item, "bundleName")->type == cJSON_String && + cJSON_GetObjectItem(item, "bundleName")->valuestring == bundleName) { + HILOGI("record already exist, bundleName=%{public}s", bundleName.c_str()); + cJSON_Delete(jsonObjectDis); + return true; + } + } + + if (!WriteClearBundleRecord(bundleName)) { + HILOGE("InsertClearBundleRecord Failed"); + cJSON_Delete(jsonObjectDis); + return false; + } + + HILOGI("InsertClearBundleRecord Ok"); + cJSON_Delete(jsonObjectDis); + return true; +} + +bool BJsonClearDataConfig::DeleteClearBundleRecord(const string& bundleName) +{ + lock_guard autoLock(fileMutex_); + string filePath = PATH_BUNDLE_BACKUP_HOME + CONFIG_NAME; + ifstream input(filePath); + if (!input.is_open()) { + HILOGE("open json failed"); + return false; + } + + string jsonString((istreambuf_iterator(input)), istreambuf_iterator()); + input.close(); + + cJSON *jsonObjectDis = cJSON_Parse(jsonString.c_str()); + if (jsonObjectDis == nullptr) { + HILOGE("parse json failed"); + return false; + } + + cJSON *configArray = cJSON_GetObjectItem(jsonObjectDis, "DispoasalConfigFile"); + if (configArray == nullptr) { + cJSON_Delete(jsonObjectDis); + return false; + } + for (int i = 0; i < cJSON_GetArraySize(configArray); ++i) { + cJSON *item = cJSON_GetArrayItem(configArray, i); + if (item != nullptr && cJSON_GetObjectItem(item, "bundleName") != nullptr && + cJSON_GetObjectItem(item, "bundleName")->type == cJSON_String && + cJSON_GetObjectItem(item, "bundleName")->valuestring == bundleName) { + cJSON_DeleteItemFromArray(configArray, i); + break; + } + } + char *newStr = cJSON_Print(jsonObjectDis); + if (newStr == nullptr) { + HILOGE("cJSON_Print json failed"); + cJSON_Delete(jsonObjectDis); + return false; + } + ofstream output(filePath); + if (!output.is_open()) { + HILOGE("open json failed"); + free(newStr); + cJSON_Delete(jsonObjectDis); + return false; + } + output << newStr; + output.close(); + + free(newStr); + cJSON_Delete(jsonObjectDis); + return true; +} + +vector BJsonClearDataConfig::GetAllClearBundleRecord() +{ + lock_guard autoLock(fileMutex_); + string filePath = PATH_BUNDLE_BACKUP_HOME + CONFIG_NAME; + vector bundleNameList; + ifstream inFile(filePath); + if (!inFile.is_open()) { + HILOGE("open json failed"); + return {}; + } + string jsonString((istreambuf_iterator(inFile)), istreambuf_iterator()); + inFile.close(); + + cJSON *jsonObjectDis = cJSON_Parse(jsonString.c_str()); + if (jsonObjectDis == nullptr) { + HILOGE("parse json failed"); + return {}; + } + + cJSON *configArray = cJSON_GetObjectItem(jsonObjectDis, "DispoasalConfigFile"); + if (configArray == nullptr) { + HILOGE("parse json failed"); + cJSON_Delete(jsonObjectDis); + return {}; + } + for (int i = 0; i < cJSON_GetArraySize(configArray); ++i) { + cJSON *item = cJSON_GetArrayItem(configArray, i); + if (item != nullptr && cJSON_GetObjectItem(item, "bundleName") != nullptr && + cJSON_GetObjectItem(item, "bundleName")->type == cJSON_String) { + bundleNameList.push_back(cJSON_GetObjectItem(item, "bundleName")->valuestring); + } + } + cJSON_Delete(jsonObjectDis); + return bundleNameList; +} + +bool BJsonClearDataConfig::DeleteConfigFile() +{ + string filePath = PATH_BUNDLE_BACKUP_HOME + CONFIG_NAME; + if (access(filePath.c_str(), F_OK) != 0) { + HILOGE("File is not exist"); + return false; + } + if (remove(filePath.c_str()) != 0) { + HILOGE("Delete DisposalConfigFile failed"); + return false; + } + HILOGI("All Restore Finished, Delete DisposalConfigFile OK"); + return true; +} + +bool BJsonClearDataConfig::WriteClearBundleRecord(const string& bundleName) +{ + string filePath = PATH_BUNDLE_BACKUP_HOME + CONFIG_NAME; + ifstream inFile(filePath); + if (!inFile.is_open()) { + HILOGE("open json failed"); + return false; + } + string jsonString((istreambuf_iterator(inFile)), istreambuf_iterator()); + inFile.close(); + + cJSON *jsonObjectDis = cJSON_Parse(jsonString.c_str()); + if (jsonObjectDis == nullptr) { + HILOGE("parse json failed"); + return false; + } + + cJSON *configArray = cJSON_GetObjectItem(jsonObjectDis, "DispoasalConfigFile"); + if (configArray == nullptr) { + HILOGE("parse json failed"); + cJSON_Delete(jsonObjectDis); + return false; + } + cJSON *newItem = cJSON_CreateObject(); + if (configArray == nullptr || newItem == nullptr) { + HILOGE("parse json failed"); + cJSON_Delete(jsonObjectDis); + return false; + } + + cJSON_AddStringToObject(newItem, "bundleName", bundleName.c_str()); + cJSON_AddItemToArray(configArray, newItem); + char *newStr = cJSON_Print(jsonObjectDis); + if (newStr == nullptr) { + HILOGE("cJSON_Print json failed"); + cJSON_Delete(jsonObjectDis); + return false; + } + ofstream outFile(filePath); + if (!outFile.is_open()) { + HILOGE("open json failed"); + free(newStr); + cJSON_Delete(jsonObjectDis); + return false; + } + outFile << newStr; + outFile.close(); + + free(newStr); + cJSON_Delete(jsonObjectDis); + return true; +} +} // namespace OHOS::FileManagement::Backup \ No newline at end of file