diff --git a/services/backup_sa/include/module_ipc/service.h b/services/backup_sa/include/module_ipc/service.h index 9f0db0a2142b36812e2611f63a79aae2e85104a9..d1f163d3593ae575e44cfe837c5aa3ece83c9281 100644 --- a/services/backup_sa/include/module_ipc/service.h +++ b/services/backup_sa/include/module_ipc/service.h @@ -137,6 +137,13 @@ private: * */ void OnStartSched(); + /** + * @brief 通知客户端程序扩展能力处理结果 + * + * @param bundleName 应用名称 + * + */ + void NoticeClientFinish(const std::string &bundleName, ErrCode errCode); private: static sptr instance_; 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 6113ac1aad08eb38a6ac61dd3e9b5cd905ddaba7..59509266e07c559ce96d76adf9f474714aa527e2 100644 --- a/services/backup_sa/include/module_ipc/svc_session_manager.h +++ b/services/backup_sa/include/module_ipc/svc_session_manager.h @@ -35,6 +35,7 @@ #include "i_service.h" #include "module_ipc/svc_backup_connection.h" #include "svc_death_recipient.h" +#include "timer.h" namespace OHOS::FileManagement::Backup { struct BackupExtInfo { @@ -53,6 +54,10 @@ struct BackupExtInfo { uint32_t versionCode; /* Clone App: old device app versionCode */ std::string versionName; + /* Ext Ability APP process time */ + uint32_t extTimerId; + /* Timer Status: true is start & false is stop */ + bool timerStatus {false}; }; class Service; @@ -354,6 +359,22 @@ public: */ std::string GetBundleVersionName(const std::string &bundleName); + /** + * @brief 启动应用扩展能力定时器 + * + * @param bundleName 应用名称 + * @return + */ + void BundleExtTimerStart(const std::string &bundleName, const Utils::Timer::TimerCallback& callback); + + /** + * @brief 取消/暂停应用扩展能力定时器 + * + * @param bundleName 应用名称 + * @return + */ + void BundleExtTimerStop(const std::string &bundleName); + private: /** * @brief 获取backup extension ability @@ -377,14 +398,28 @@ private: */ std::map::iterator GetBackupExtNameMap(const std::string &bundleName); + /** + * @brief 计算出应用程序处理数据可能使用的时间 + * + * @param bundleName 应用名称 + * @return + */ + uint32_t CalAppProcessTime(const std::string &bundleName); + public: /** * @brief Construct a new Svc Session object * * @param reversePtr 指向Service的反向指针,使用wptr避免循环引用 */ - explicit SvcSessionManager(wptr reversePtr) : reversePtr_(reversePtr) {} - ~SvcSessionManager() override = default; + explicit SvcSessionManager(wptr reversePtr) : reversePtr_(reversePtr) + { + extBundleTimer.Setup(); + } + ~SvcSessionManager() override + { + extBundleTimer.Shutdown(); + } private: mutable std::shared_mutex lock_; @@ -392,6 +427,7 @@ private: sptr deathRecipient_; Impl impl_; uint32_t extConnectNum_ {0}; + Utils::Timer extBundleTimer {"backupBundleExtTimer"}; }; } // 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 9b77fdf772a1f0a8a85156d5bb7b8f526ef58a23..da8a147286f603a2f3f560c19d29970edbbee3fc 100644 --- a/services/backup_sa/src/module_ipc/service.cpp +++ b/services/backup_sa/src/module_ipc/service.cpp @@ -342,6 +342,8 @@ ErrCode Service::AppFileReady(const string &fileName, UniqueFd fd) } // 通知extension清空缓存 proxy->HandleClear(); + // 清除Timer + session_->BundleExtTimerStop(callerName); // 通知TOOL 备份完成 session_->GetServiceReverseProxy()->BackupOnBundleFinished(BError(BError::Codes::OK), callerName); // 断开extension @@ -373,6 +375,7 @@ ErrCode Service::AppDone(ErrCode errCode) throw BError(BError::Codes::SA_INVAL_ARG, "Extension backup Proxy is empty"); } proxy->HandleClear(); + session_->BundleExtTimerStop(callerName); IServiceReverse::Scenario scenario = session_->GetScenario(); if (scenario == IServiceReverse::Scenario::BACKUP) { session_->GetServiceReverseProxy()->BackupOnBundleFinished(errCode, callerName); @@ -472,20 +475,21 @@ ErrCode Service::GetFileHandle(const string &bundleName, const string &fileName) void Service::OnBackupExtensionDied(const string &&bundleName, ErrCode ret) { try { - HILOGI("extension died. Died bundleName = %{public}s", bundleName.data()); string callName = move(bundleName); session_->VerifyBundleName(callName); - auto scenario = session_->GetScenario(); - if (scenario == IServiceReverse::Scenario::BACKUP) { - session_->GetServiceReverseProxy()->BackupOnBundleFinished(ret, callName); - } else if (scenario == IServiceReverse::Scenario::RESTORE) { - session_->GetServiceReverseProxy()->RestoreOnBundleFinished(ret, callName); - } + + /* Standard Log Output, for testers */ + HILOGE("Backup <%{public}s> Extension Process Died", callName.data()); + /* Clear Timer */ + session_->BundleExtTimerStop(callName); auto backUpConnection = session_->GetExtConnection(callName); if (backUpConnection->IsExtAbilityConnected()) { backUpConnection->DisconnectBackupExtAbility(); } - ClearSessionAndSchedInfo(bundleName); + /* Clear Session before notice client finish event */ + ClearSessionAndSchedInfo(callName); + /* Notice Client Ext Ability Process Died */ + NoticeClientFinish(callName, BError(BError::Codes::EXT_ABILITY_DIED)); } catch (const BError &e) { return; } catch (const exception &e) { @@ -580,10 +584,41 @@ void Service::ExtConnectFailed(const string &bundleName, ErrCode ret) } } +void Service::NoticeClientFinish(const string &bundleName, ErrCode errCode) +{ + auto scenario = session_->GetScenario(); + if (scenario == IServiceReverse::Scenario::BACKUP) { + session_->GetServiceReverseProxy()->BackupOnBundleFinished(errCode, bundleName); + } else if (scenario == IServiceReverse::Scenario::RESTORE) { + session_->GetServiceReverseProxy()->RestoreOnBundleFinished(errCode, bundleName); + }; + /* If all bundle ext process finish, notice client. */ + OnAllBundlesFinished(BError(BError::Codes::OK)); +} + void Service::ExtConnectDone(string bundleName) { + /* Callback for App Ext Timeout Process. */ + auto timeoutCallback = [ptr {wptr(this)}, bundleName]() { + auto thisPtr = ptr.promote(); + if (!thisPtr) { + HILOGW("this pointer is null."); + return; + } + auto sessionPtr = ptr->session_; + auto sessionConnection = sessionPtr->GetExtConnection(bundleName); + /* Standard Log Output, for testers */ + HILOGE("Backup <%{public}s> Extension Process Timeout", bundleName.data()); + sessionPtr->BundleExtTimerStop(bundleName); + sessionConnection->DisconnectBackupExtAbility(); + /* Must clear bundle session before call NoticeClientFinish. */ + thisPtr->ClearSessionAndSchedInfo(bundleName); + thisPtr->NoticeClientFinish(bundleName, BError(BError::Codes::EXT_ABILITY_TIMEOUT)); + }; + try { HILOGE("begin %{public}s", bundleName.data()); + session_->BundleExtTimerStart(bundleName, timeoutCallback); session_->SetServiceSchedAction(bundleName, BConstants::ServiceSchedAction::RUNNING); sched_->Sched(bundleName); } catch (const BError &e) { 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 9b5f1abf6485400fca9376fb0b226af214d16b4b..a5b9c1dacb1d2a8543004c585afc53cf8c7defa4 100644 --- a/services/backup_sa/src/module_ipc/svc_session_manager.cpp +++ b/services/backup_sa/src/module_ipc/svc_session_manager.cpp @@ -29,6 +29,7 @@ #include "b_resources/b_constants.h" #include "filemgmt_libhilog.h" #include "module_external/bms_adapter.h" +#include "module_external/sms_adapter.h" #include "module_ipc/service.h" namespace OHOS::FileManagement::Backup { @@ -563,4 +564,63 @@ std::string SvcSessionManager::GetBundleVersionName(const std::string &bundleNam auto it = GetBackupExtNameMap(bundleName); return it->second.versionName; } -} // namespace OHOS::FileManagement::Backup \ No newline at end of file + +uint32_t SvcSessionManager::CalAppProcessTime(const std::string &bundleName) +{ + const uint32_t defaultTimeout = 30; /* 30 second */ + const uint32_t processRate = 3 * 1024 * 1024; /* 3M/s */ + const uint32_t multiple = 3; + const uint32_t invertMillisecond = 1000; + StorageManager::BundleStats stat; + uint32_t timeout; + uint64_t appSize; + + try { + stat = StorageMgrAdapter::GetBundleStats(bundleName); + appSize = (stat.appSize_ + stat.cacheSize_ + stat.dataSize_); + /* % UINT_MAX force conver uint64 to uint32 */ + /* timeout = (AppSize / 3Ms) * 3 + 30 */ + timeout = (uint32_t)(defaultTimeout + (appSize / processRate) * multiple % UINT_MAX); + HILOGI("appSize=%{public}lld, cacheSize=%{public}lld, dataSize=%{public}lld, timeout=%{public}u(s)", + stat.appSize_, stat.cacheSize_, stat.dataSize_, timeout); + } catch (const BError &e) { + HILOGE("Failed to get app<%{public}s> dataInfo, default time=%{public}u, err=%{public}d", + bundleName.c_str(), defaultTimeout, e.GetCode()); + timeout = defaultTimeout; + } + timeout = timeout * invertMillisecond % UINT_MAX; /* conver second to millisecond */ + return timeout; +} + +void SvcSessionManager::BundleExtTimerStart ( + const std::string &bundleName, + const Utils::Timer::TimerCallback& callback) +{ + unique_lock lock(lock_); + if (!impl_.clientToken) { + throw BError(BError::Codes::SA_INVAL_ARG, "No caller token was specified"); + } + uint32_t timeout = CalAppProcessTime(bundleName); + + auto it = GetBackupExtNameMap(bundleName); + if (it->second.timerStatus == false) { + it->second.timerStatus = true; + it->second.extTimerId = extBundleTimer.Register(callback, timeout, true); + } +} + +void SvcSessionManager::BundleExtTimerStop(const std::string &bundleName) +{ + unique_lock lock(lock_); + if (!impl_.clientToken) { + throw BError(BError::Codes::SA_INVAL_ARG, "No caller token was specified"); + } + + auto it = GetBackupExtNameMap(bundleName); + if (it->second.timerStatus == true) { + it->second.timerStatus = false; + extBundleTimer.Unregister(it->second.extTimerId); + } +} + +} // 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 c5e4d89520e14026ee058469fe88140562934203..36e649576b8c09b60e53dfa15e22c6c2798a1063 100644 --- a/tests/mock/module_ipc/svc_session_manager_mock.cpp +++ b/tests/mock/module_ipc/svc_session_manager_mock.cpp @@ -305,5 +305,9 @@ std::string SvcSessionManager::GetBundleVersionName(const std::string &bundleNam } return it->second.versionName; } +void SvcSessionManager::BundleExtTimerStart ( + const std::string &bundleName, const Utils::Timer::TimerCallback& callback) {} + +void SvcSessionManager::BundleExtTimerStop(const std::string &bundleName) {} } // namespace OHOS::FileManagement::Backup diff --git a/utils/include/b_error/b_error.h b/utils/include/b_error/b_error.h index 6c549639bdcc0498be0eba15d6ff9b14b10d5f92..37bf19df95ac75ab465886e1d87f35909c34bb91 100644 --- a/utils/include/b_error/b_error.h +++ b/utils/include/b_error/b_error.h @@ -79,6 +79,8 @@ public: EXT_BROKEN_FRAMEWORK = 0x5001, EXT_BROKEN_BACKUP_SA = 0x5002, EXT_BROKEN_IPC = 0x5003, + EXT_ABILITY_DIED = 0x5004, + EXT_ABILITY_TIMEOUT = 0x5005, }; enum BackupErrorCode { @@ -203,6 +205,8 @@ private: {Codes::EXT_BROKEN_FRAMEWORK, "Extension found the appex framework is broken"}, {Codes::EXT_BROKEN_BACKUP_SA, "Extension found the backup SA died"}, {Codes::EXT_BROKEN_IPC, "Extension failed to do IPC"}, + {Codes::EXT_ABILITY_TIMEOUT, "Extension process timeout"}, + {Codes::EXT_ABILITY_DIED, "Extension process died"}, }; static inline const std::map errCodeTable_ { @@ -224,6 +228,8 @@ private: {static_cast(Codes::EXT_BROKEN_FRAMEWORK), BackupErrorCode::E_UKERR}, {static_cast(Codes::EXT_BROKEN_BACKUP_SA), BackupErrorCode::E_IPCSS}, {static_cast(Codes::EXT_BROKEN_IPC), BackupErrorCode::E_IPCSS}, + {static_cast(Codes::EXT_ABILITY_DIED), BackupErrorCode::E_INVAL}, + {static_cast(Codes::EXT_ABILITY_TIMEOUT), BackupErrorCode::E_INVAL}, {BackupErrorCode::E_IPCSS, BackupErrorCode::E_IPCSS}, {BackupErrorCode::E_INVAL, BackupErrorCode::E_INVAL}, {BackupErrorCode::E_UKERR, BackupErrorCode::E_UKERR},